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