Commit 30565a81 authored by tyoverby@chromium.org's avatar tyoverby@chromium.org

Adds cache and buffer graphs to the properties pane.

BUG=260005

Review URL: https://chromiumcodereview.appspot.com/23536020

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@222221 0039d316-1c4b-4281-b951-d872f2087c98
parent 85698b90
......@@ -176,6 +176,12 @@ cr.define('media', function() {
* this file.
*/
generateDetails: function() {
function makeElement(tag, content) {
var toReturn = document.createElement(tag);
toReturn.textContent = content;
return toReturn;
}
this.details_.id = this.key;
this.summaryText_.textContent = this.key || 'Unknown File';
......@@ -188,8 +194,8 @@ cr.define('media', function() {
this.detailTable_.appendChild(body);
var headerRow = document.createElement('tr');
headerRow.appendChild(media.makeElement('th', 'Read From Cache'));
headerRow.appendChild(media.makeElement('th', 'Written To Cache'));
headerRow.appendChild(makeElement('th', 'Read From Cache'));
headerRow.appendChild(makeElement('th', 'Written To Cache'));
header.appendChild(headerRow);
var footerRow = document.createElement('tr');
......@@ -209,8 +215,8 @@ cr.define('media', function() {
var length = Math.max(read.length, written.length);
for (var i = 0; i < length; i++) {
var row = document.createElement('tr');
row.appendChild(media.makeElement('td', read[i] || ''));
row.appendChild(media.makeElement('td', written[i] || ''));
row.appendChild(makeElement('td', read[i] || ''));
row.appendChild(makeElement('td', written[i] || ''));
body.appendChild(row);
}
......
......@@ -8,11 +8,16 @@ var ClientRenderer = (function() {
this.audioStreamListElement = document.getElementById('audio-stream-list');
this.propertiesTable = document.getElementById('property-table');
this.logTable = document.getElementById('log');
this.graphElement = document.getElementById('graphs');
this.selectedPlayer = null;
this.selectedStream = null;
this.selectedPlayerLogIndex = 0;
this.bufferCanvas = document.createElement('canvas');
this.bufferCanvas.width = media.BAR_WIDTH;
this.bufferCanvas.height = media.BAR_HEIGHT;
};
function removeChildren(element) {
......@@ -76,6 +81,7 @@ var ClientRenderer = (function() {
if (player === this.selectedPlayer) {
this.drawProperties_(player.properties);
this.drawLog_();
this.drawGraphs_();
}
if (key === 'name' || key === 'url') {
this.redrawPlayerList_(players);
......@@ -98,6 +104,7 @@ var ClientRenderer = (function() {
this.selectedPlayer = null;
this.drawProperties_(audioStream);
removeChildren(this.logTable.querySelector('tbody'));
removeChildren(this.graphElement);
},
redrawPlayerList_: function(players) {
......@@ -123,7 +130,9 @@ var ClientRenderer = (function() {
this.drawProperties_(player.properties);
removeChildren(this.logTable.querySelector('tbody'));
removeChildren(this.graphElement);
this.drawLog_();
this.drawGraphs_();
},
drawProperties_: function(propertyMap) {
......@@ -131,6 +140,7 @@ var ClientRenderer = (function() {
for (key in propertyMap) {
var value = propertyMap[key];
var row = this.propertiesTable.insertRow(-1);
var keyCell = row.insertCell(-1);
var valueCell = row.insertCell(-1);
......@@ -154,6 +164,76 @@ var ClientRenderer = (function() {
this.selectedPlayerLogIndex);
toDraw.forEach(this.appendEventToLog_.bind(this));
this.selectedPlayerLogIndex = this.selectedPlayer.allEvents.length;
},
drawGraphs_: function() {
function addToGraphs (name, graph, graphElement) {
var li = document.createElement('li');
li.appendChild(graph);
li.appendChild(document.createTextNode(name));
graphElement.appendChild(li);
}
var url = this.selectedPlayer.properties.url;
if (!url) {
return;
}
var cache = media.cacheForUrl(url);
var player = this.selectedPlayer;
var props = player.properties;
var cacheExists = false;
var bufferExists = false;
if (props['buffer_start'] !== undefined &&
props['buffer_current'] !== undefined &&
props['buffer_end'] !== undefined &&
props['total_bytes'] !== undefined) {
this.drawBufferGraph_(props['buffer_start'],
props['buffer_current'],
props['buffer_end'],
props['total_bytes']);
bufferExists = true;
}
if (cache) {
if(player.properties['total_bytes']) {
cache.size = Number(player.properties['total_bytes']);
}
cache.generateDetails();
cacheExists = true;
}
if (!this.graphElement.hasChildNodes()) {
if (bufferExists) {
addToGraphs('buffer', this.bufferCanvas, this.graphElement);
}
if (cacheExists) {
addToGraphs('cache read', cache.readCanvas, this.graphElement);
addToGraphs('cache write', cache.writeCanvas, this.graphElement);
}
}
},
drawBufferGraph_: function(start, current, end, size) {
var ctx = this.bufferCanvas.getContext('2d');
var width = this.bufferCanvas.width;
var height = this.bufferCanvas.height;
ctx.fillStyle = '#aaa';
ctx.fillRect(0, 0, width, height);
var scale_factor = width / size;
var left = start * scale_factor;
var middle = current * scale_factor;
var right = end * scale_factor;
ctx.fillStyle = '#a0a';
ctx.fillRect(left, 0, middle - left, height);
ctx.fillStyle = '#aa0';
ctx.fillRect(middle, 0, right - middle, height);
}
};
......
......@@ -8,13 +8,35 @@
var media = (function() {
'use strict';
var manager_ = null;
var manager = null;
// A number->string mapping that is populated through the backend that
// describes the phase that the network entity is in.
var eventPhases = {};
// A number->string mapping that is populated through the backend that
// describes the type of event sent from the network.
var eventTypes = {};
// A mapping of number->CacheEntry where the number is a unique id for that
// network request.
var cacheEntries = {};
// A mapping of url->CacheEntity where the url is the url of the resource.
var cacheEntriesByKey = {};
var requrestURLs = {};
var media = {
BAR_WIDTH: 200,
BAR_HEIGHT: 25
};
/**
* Users of |media| must call initialize prior to calling other methods.
*/
media.initialize = function(manager) {
manager_ = manager;
media.initialize = function(theManager) {
manager = theManager;
};
media.onReceiveEverything = function(everything) {
......@@ -23,14 +45,80 @@ var media = (function() {
}
};
media.onNetUpdate = function(update) {
// TODO(tyoverby): Implement
media.onReceiveConstants = function(constants) {
for (var key in constants.eventTypes) {
var value = constants.eventTypes[key];
eventTypes[value] = key;
}
for (var key in constants.eventPhases) {
var value = constants.eventPhases[key];
eventPhases[value] = key;
}
};
media.cacheForUrl = function(url) {
return cacheEntriesByKey[url];
};
media.onNetUpdate = function(updates) {
updates.forEach(function(update) {
var id = update.source.id;
if (!cacheEntries[id])
cacheEntries[id] = new media.CacheEntry;
switch (eventPhases[update.phase] + '.' + eventTypes[update.type]) {
case 'PHASE_BEGIN.DISK_CACHE_ENTRY_IMPL':
var key = update.params.key;
// Merge this source with anything we already know about this key.
if (cacheEntriesByKey[key]) {
cacheEntriesByKey[key].merge(cacheEntries[id]);
cacheEntries[id] = cacheEntriesByKey[key];
} else {
cacheEntriesByKey[key] = cacheEntries[id];
}
cacheEntriesByKey[key].key = key;
break;
case 'PHASE_BEGIN.SPARSE_READ':
cacheEntries[id].readBytes(update.params.offset,
update.params.buff_len);
cacheEntries[id].sparse = true;
break;
case 'PHASE_BEGIN.SPARSE_WRITE':
cacheEntries[id].writeBytes(update.params.offset,
update.params.buff_len);
cacheEntries[id].sparse = true;
break;
case 'PHASE_BEGIN.URL_REQUEST_START_JOB':
requrestURLs[update.source.id] = update.params.url;
break;
case 'PHASE_NONE.HTTP_TRANSACTION_READ_RESPONSE_HEADERS':
// Record the total size of the file if this was a range request.
var range = /content-range:\s*bytes\s*\d+-\d+\/(\d+)/i.exec(
update.params.headers);
var key = requrestURLs[update.source.id];
delete requrestURLs[update.source.id];
if (range && key) {
if (!cacheEntriesByKey[key]) {
cacheEntriesByKey[key] = new media.CacheEntry;
cacheEntriesByKey[key].key = key;
}
cacheEntriesByKey[key].size = range[1];
}
break;
}
});
};
media.onRendererTerminated = function(renderId) {
util.object.forEach(manager_.players_, function(playerInfo, id) {
util.object.forEach(manager.players_, function(playerInfo, id) {
if (playerInfo.properties['render_id'] == renderId) {
manager_.removePlayer(id);
manager.removePlayer(id);
}
});
};
......@@ -40,18 +128,18 @@ var media = (function() {
media.addAudioStream = function(event) {
switch (event.status) {
case 'created':
manager_.addAudioStream(event.id);
manager_.updateAudioStream(event.id, { 'playing': event.playing });
manager.addAudioStream(event.id);
manager.updateAudioStream(event.id, { 'playing': event.playing });
break;
case 'closed':
manager_.removeAudioStream(event.id);
manager.removeAudioStream(event.id);
break;
}
};
media.updateAudioStream = function(stream) {
manager_.addAudioStream(stream.id);
manager_.updateAudioStream(stream.id, stream);
manager.addAudioStream(stream.id);
manager.updateAudioStream(stream.id, stream);
};
media.onItemDeleted = function() {
......@@ -61,7 +149,7 @@ var media = (function() {
};
media.onPlayerOpen = function(id, timestamp) {
manager_.addPlayer(id, timestamp);
manager.addPlayer(id, timestamp);
};
media.onMediaEvent = function(event) {
......@@ -70,9 +158,9 @@ var media = (function() {
// Although this gets called on every event, there is nothing we can do
// because there is no onOpen event.
media.onPlayerOpen(source);
manager_.updatePlayerInfoNoRecord(
manager.updatePlayerInfoNoRecord(
source, event.ticksMillis, 'render_id', event.renderer);
manager_.updatePlayerInfoNoRecord(
manager.updatePlayerInfoNoRecord(
source, event.ticksMillis, 'player_id', event.player);
var propertyCount = 0;
......@@ -85,19 +173,23 @@ var media = (function() {
key === 'buffer_end' ||
key === 'buffer_current' ||
key === 'is_downloading_data') {
manager_.updatePlayerInfoNoRecord(
manager.updatePlayerInfoNoRecord(
source, event.ticksMillis, key, value);
} else {
manager_.updatePlayerInfo(source, event.ticksMillis, key, value);
manager.updatePlayerInfo(source, event.ticksMillis, key, value);
}
propertyCount += 1;
});
if (propertyCount === 0) {
manager_.updatePlayerInfo(
manager.updatePlayerInfo(
source, event.ticksMillis, 'EVENT', event.type);
}
};
// |chrome| is not defined during tests.
if (window.chrome && window.chrome.send) {
chrome.send('getEverything');
}
return media;
}());
......@@ -18,6 +18,8 @@ table {
}
td {
border: 1px solid black;
word-wrap: break-word;
max-width: 200px;
}
thead {
color: rgb(50,50,50);
......@@ -43,7 +45,6 @@ h3 {
padding: 0;
padding-left: 25px;
margin: 0;
max-height: 100%;
}
#list-wrapper {
......@@ -52,7 +53,6 @@ h3 {
justify-content: space-between;
align-items: flex-start;
align-content: stretch;
height: 100%;
}
#player-list-wrapper,
......@@ -89,3 +89,7 @@ h3 {
#log-wrapper > thead {
position: fixed;
}
#graphs li {
list-style-type: none;
}
......@@ -9,6 +9,7 @@ found in the LICENSE file.
<meta charset="utf-8">
<title i18n-content="Media Internals"></title>
<link rel="stylesheet" href="media_internals.css">
<script src="chrome://resources/js/cr.js"></script>
</head>
<body>
......@@ -32,6 +33,7 @@ found in the LICENSE file.
</tr>
</thead>
</table>
<ul id="graphs"></ul>
</div>
<div id="log-wrapper">
<h2>
......@@ -45,8 +47,7 @@ found in the LICENSE file.
<td>Value</td>
</tr>
</thead>
<tbody>
</tbody>
<tbody></tbody>
</table>
</div>
</div>
......
......@@ -4,10 +4,12 @@
var media = {};
<include src="main.js"/>
<include src="util.js"/>
<include src="../cache_entry.js"/>
<include src="../disjoint_range_set.js"/>
<include src="player_info.js"/>
<include src="manager.js"/>
<include src="client_renderer.js"/>
<include src="main.js"/>
media.initialize(new Manager(new ClientRenderer()));
......@@ -775,6 +775,7 @@
'../ui/snapshot/snapshot.gyp:snapshot',
'../ui/ui.gyp:shell_dialogs',
'../ui/ui.gyp:ui',
'../ui/ui.gyp:ui_resources',
'../webkit/renderer/webkit_renderer.gyp:webkit_renderer',
'../webkit/support/webkit_support.gyp:glue',
'../webkit/support/webkit_support.gyp:glue_child',
......
......@@ -7,6 +7,8 @@ found in the LICENSE file.
<html>
<body>
<script>
window.chrome = {};
window.setUp = function() {
var doNothing = function() {};
var mockClientRenderer = {
......
......@@ -7,6 +7,8 @@ found in the LICENSE file.
<html>
<body>
<script>
window.chrome = {};
var doNothing = function() {};
var emptyClientRenderer = {
......
......@@ -7,6 +7,8 @@ found in the LICENSE file.
<html>
<body>
<script>
window.chrome = {};
window.setUp = function() {
window.pi = new PlayerInfo('example_id');
};
......
......@@ -12,6 +12,7 @@
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "grit/content_resources.h"
#include "grit/webui_resources.h"
#include "net/base/net_util.h"
namespace content {
......@@ -32,6 +33,7 @@ class WebUIResourceBrowserTest : public ContentBrowserTest {
}
void RunMediaInternalsTest(const base::FilePath::CharType* file) {
AddLibrary(IDR_WEBUI_JS_CR);
AddLibrary(IDR_MEDIA_INTERNALS_NEW_JS);
base::FilePath path;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment