// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. /** * A global object that gets used by the C++ interface. */ var media = (function() { 'use strict'; 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(theManager) { manager = theManager; }; media.onReceiveEverything = function(everything) { for (var component in everything) { media.updateAudioComponent(everything[component]); } }; 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) { if (playerInfo.properties['render_id'] == renderId) { manager.removePlayer(id); } }); }; media.updateAudioComponent = function(component) { var uniqueComponentId = component.owner_id + ':' + component.component_id; switch (component.status) { case 'closed': manager.removeAudioComponent( component.component_type, uniqueComponentId); break; default: manager.updateAudioComponent( component.component_type, uniqueComponentId, component); break; } }; media.onPlayerOpen = function(id, timestamp) { manager.addPlayer(id, timestamp); }; media.onMediaEvent = function(event) { var source = event.renderer + ':' + event.player; // Although this gets called on every event, there is nothing we can do // because there is no onOpen event. media.onPlayerOpen(source); manager.updatePlayerInfoNoRecord( source, event.ticksMillis, 'render_id', event.renderer); manager.updatePlayerInfoNoRecord( source, event.ticksMillis, 'player_id', event.player); var propertyCount = 0; util.object.forEach(event.params, function(value, key) { key = key.trim(); // These keys get spammed *a lot*, so put them on the display // but don't log list. if (key === 'buffer_start' || key === 'buffer_end' || key === 'buffer_current' || key === 'is_downloading_data') { manager.updatePlayerInfoNoRecord( source, event.ticksMillis, key, value); } else { manager.updatePlayerInfo(source, event.ticksMillis, key, value); } propertyCount += 1; }); if (propertyCount === 0) { 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; }());