- add sources.
[platform/framework/web/crosswalk.git] / src / content / browser / resources / media / main.js
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  */
8 var 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 key in everything.audio_streams) {
44       media.updateAudioStream(everything.audio_streams[key]);
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   // For whatever reason, addAudioStream is also called on
127   // the removal of audio streams.
128   media.addAudioStream = function(event) {
129     switch (event.status) {
130       case 'created':
131         manager.addAudioStream(event.id);
132         manager.updateAudioStream(event.id, { 'playing': event.playing });
133         break;
134       case 'closed':
135         manager.removeAudioStream(event.id);
136         break;
137     }
138   };
139
140   media.updateAudioStream = function(stream) {
141     manager.addAudioStream(stream.id);
142     manager.updateAudioStream(stream.id, stream);
143   };
144
145   media.onItemDeleted = function() {
146     // This only gets called when an audio stream is removed, which
147     // for whatever reason is also handled by addAudioStream...
148     // Because it is already handled, we can safely ignore it.
149   };
150
151   media.onPlayerOpen = function(id, timestamp) {
152     manager.addPlayer(id, timestamp);
153   };
154
155   media.onMediaEvent = function(event) {
156     var source = event.renderer + ':' + event.player;
157
158     // Although this gets called on every event, there is nothing we can do
159     // because there is no onOpen event.
160     media.onPlayerOpen(source);
161     manager.updatePlayerInfoNoRecord(
162         source, event.ticksMillis, 'render_id', event.renderer);
163     manager.updatePlayerInfoNoRecord(
164         source, event.ticksMillis, 'player_id', event.player);
165
166     var propertyCount = 0;
167     util.object.forEach(event.params, function(value, key) {
168       key = key.trim();
169
170       // These keys get spammed *a lot*, so put them on the display
171       // but don't log list.
172       if (key === 'buffer_start' ||
173           key === 'buffer_end' ||
174           key === 'buffer_current' ||
175           key === 'is_downloading_data') {
176         manager.updatePlayerInfoNoRecord(
177             source, event.ticksMillis, key, value);
178       } else {
179         manager.updatePlayerInfo(source, event.ticksMillis, key, value);
180       }
181       propertyCount += 1;
182     });
183
184     if (propertyCount === 0) {
185       manager.updatePlayerInfo(
186           source, event.ticksMillis, 'EVENT', event.type);
187     }
188   };
189
190   // |chrome| is not defined during tests.
191   if (window.chrome && window.chrome.send) {
192     chrome.send('getEverything');
193   }
194   return media;
195 }());