summaryrefslogtreecommitdiff
path: root/chromium/content/browser/resources/media/main.js
blob: cb239da2d5448495ab96c902819b3eb47f9c3916 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
// 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;
}());