1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5/** 6 * A global object that gets used by the C++ interface. 7 */ 8var media = (function() { 9 'use strict'; 10 11 var manager = null; 12 13 // A number->string mapping that is populated through the backend that 14 // describes the phase that the network entity is in. 15 var eventPhases = {}; 16 17 // A number->string mapping that is populated through the backend that 18 // describes the type of event sent from the network. 19 var eventTypes = {}; 20 21 // A mapping of number->CacheEntry where the number is a unique id for that 22 // network request. 23 var cacheEntries = {}; 24 25 // A mapping of url->CacheEntity where the url is the url of the resource. 26 var cacheEntriesByKey = {}; 27 28 var requrestURLs = {}; 29 30 var media = { 31 BAR_WIDTH: 200, 32 BAR_HEIGHT: 25 33 }; 34 35 /** 36 * Users of |media| must call initialize prior to calling other methods. 37 */ 38 media.initialize = function(theManager) { 39 manager = theManager; 40 }; 41 42 media.onReceiveEverything = function(everything) { 43 for (var component in everything) { 44 media.updateAudioComponent(everything[component]); 45 } 46 }; 47 48 media.onReceiveConstants = function(constants) { 49 for (var key in constants.eventTypes) { 50 var value = constants.eventTypes[key]; 51 eventTypes[value] = key; 52 } 53 54 for (var key in constants.eventPhases) { 55 var value = constants.eventPhases[key]; 56 eventPhases[value] = key; 57 } 58 }; 59 60 media.cacheForUrl = function(url) { 61 return cacheEntriesByKey[url]; 62 }; 63 64 media.onNetUpdate = function(updates) { 65 updates.forEach(function(update) { 66 var id = update.source.id; 67 if (!cacheEntries[id]) 68 cacheEntries[id] = new media.CacheEntry; 69 70 switch (eventPhases[update.phase] + '.' + eventTypes[update.type]) { 71 case 'PHASE_BEGIN.DISK_CACHE_ENTRY_IMPL': 72 var key = update.params.key; 73 74 // Merge this source with anything we already know about this key. 75 if (cacheEntriesByKey[key]) { 76 cacheEntriesByKey[key].merge(cacheEntries[id]); 77 cacheEntries[id] = cacheEntriesByKey[key]; 78 } else { 79 cacheEntriesByKey[key] = cacheEntries[id]; 80 } 81 cacheEntriesByKey[key].key = key; 82 break; 83 84 case 'PHASE_BEGIN.SPARSE_READ': 85 cacheEntries[id].readBytes(update.params.offset, 86 update.params.buff_len); 87 cacheEntries[id].sparse = true; 88 break; 89 90 case 'PHASE_BEGIN.SPARSE_WRITE': 91 cacheEntries[id].writeBytes(update.params.offset, 92 update.params.buff_len); 93 cacheEntries[id].sparse = true; 94 break; 95 96 case 'PHASE_BEGIN.URL_REQUEST_START_JOB': 97 requrestURLs[update.source.id] = update.params.url; 98 break; 99 100 case 'PHASE_NONE.HTTP_TRANSACTION_READ_RESPONSE_HEADERS': 101 // Record the total size of the file if this was a range request. 102 var range = /content-range:\s*bytes\s*\d+-\d+\/(\d+)/i.exec( 103 update.params.headers); 104 var key = requrestURLs[update.source.id]; 105 delete requrestURLs[update.source.id]; 106 if (range && key) { 107 if (!cacheEntriesByKey[key]) { 108 cacheEntriesByKey[key] = new media.CacheEntry; 109 cacheEntriesByKey[key].key = key; 110 } 111 cacheEntriesByKey[key].size = range[1]; 112 } 113 break; 114 } 115 }); 116 }; 117 118 media.onRendererTerminated = function(renderId) { 119 util.object.forEach(manager.players_, function(playerInfo, id) { 120 if (playerInfo.properties['render_id'] == renderId) { 121 manager.removePlayer(id); 122 } 123 }); 124 }; 125 126 media.updateAudioComponent = function(component) { 127 var uniqueComponentId = component.owner_id + ':' + component.component_id; 128 switch (component.status) { 129 case 'closed': 130 manager.removeAudioComponent( 131 component.component_type, uniqueComponentId); 132 break; 133 default: 134 manager.updateAudioComponent( 135 component.component_type, uniqueComponentId, component); 136 break; 137 } 138 }; 139 140 media.onPlayerOpen = function(id, timestamp) { 141 manager.addPlayer(id, timestamp); 142 }; 143 144 media.onMediaEvent = function(event) { 145 var source = event.renderer + ':' + event.player; 146 147 // Although this gets called on every event, there is nothing we can do 148 // because there is no onOpen event. 149 media.onPlayerOpen(source); 150 manager.updatePlayerInfoNoRecord( 151 source, event.ticksMillis, 'render_id', event.renderer); 152 manager.updatePlayerInfoNoRecord( 153 source, event.ticksMillis, 'player_id', event.player); 154 155 var propertyCount = 0; 156 util.object.forEach(event.params, function(value, key) { 157 key = key.trim(); 158 159 // These keys get spammed *a lot*, so put them on the display 160 // but don't log list. 161 if (key === 'buffer_start' || 162 key === 'buffer_end' || 163 key === 'buffer_current' || 164 key === 'is_downloading_data') { 165 manager.updatePlayerInfoNoRecord( 166 source, event.ticksMillis, key, value); 167 } else { 168 manager.updatePlayerInfo(source, event.ticksMillis, key, value); 169 } 170 propertyCount += 1; 171 }); 172 173 if (propertyCount === 0) { 174 manager.updatePlayerInfo( 175 source, event.ticksMillis, 'EVENT', event.type); 176 } 177 }; 178 179 // |chrome| is not defined during tests. 180 if (window.chrome && window.chrome.send) { 181 chrome.send('getEverything'); 182 } 183 return media; 184}()); 185