Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / resources / hangout_services / thunk.js
blobd03a8318240b5d247af9b2644509f7ede2326352
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.
5 chrome.runtime.onMessageExternal.addListener(
6     function(message, sender, sendResponse) {
7       function doSendResponse(value, errorString) {
8         var error = null;
9         if (errorString) {
10           error = {};
11           error['name'] = 'ComponentExtensonError';
12           error['message'] = errorString;
13         }
15         var errorMessage = error || chrome.extension.lastError;
16         sendResponse({'value': value, 'error': errorMessage});
17       }
19       function getHost(url) {
20         if (!url)
21           return '';
22         // Use the DOM to parse the URL. Since we don't add the anchor to
23         // the page, this is the only reference to it and it will be
24         // deleted once it's gone out of scope.
25         var a = document.createElement('a');
26         a.href = url;
27         var origin = a.protocol + '//' + a.hostname;
28         if (a.port != '')
29           origin = origin + ':' + a.port;
30         origin = origin + '/';
31         return origin;
32       }
34       try {
35         var requestInfo = {};
36         if (sender.tab) {
37           requestInfo['tabId'] = sender.tab.id;
38         }
40         if (sender.guestProcessId) {
41           requestInfo['guestProcessId'] = sender.guestProcessId;
42         }
44         if (sender.guestRenderFrameRoutingId) {
45           requestInfo['guestRenderFrameId'] = sender.guestRenderFrameRoutingId;
46         }
48         var method = message['method'];
49         var origin = getHost(sender.url);
50         if (method == 'cpu.getInfo') {
51           chrome.system.cpu.getInfo(doSendResponse);
52           return true;
53         } else if (method == 'logging.setMetadata') {
54           var metaData = message['metaData'];
55           chrome.webrtcLoggingPrivate.setMetaData(
56               requestInfo, origin, metaData, doSendResponse);
57           return true;
58         } else if (method == 'logging.start') {
59           chrome.webrtcLoggingPrivate.start(
60               requestInfo, origin, doSendResponse);
61           return true;
62         } else if (method == 'logging.uploadOnRenderClose') {
63           chrome.webrtcLoggingPrivate.setUploadOnRenderClose(
64               requestInfo, origin, true);
65           doSendResponse();
66           return false;
67         } else if (method == 'logging.noUploadOnRenderClose') {
68           chrome.webrtcLoggingPrivate.setUploadOnRenderClose(
69               requestInfo, origin, false);
70           doSendResponse();
71           return false;
72         } else if (method == 'logging.stop') {
73           chrome.webrtcLoggingPrivate.stop(
74               requestInfo, origin, doSendResponse);
75           return true;
76         } else if (method == 'logging.upload') {
77           chrome.webrtcLoggingPrivate.upload(
78               requestInfo, origin, doSendResponse);
79           return true;
80         } else if (method == 'logging.uploadStored') {
81           var logId = message['logId'];
82           chrome.webrtcLoggingPrivate.uploadStored(
83               requestInfo, origin, logId, doSendResponse);
84           return true;
85         } else if (method == 'logging.stopAndUpload') {
86           stopAllRtpDump(requestInfo, origin,
87                          function(rtpDumpValue, rtpDumpErrorString) {
88             if (chrome.extension.lastError !== undefined) {
89               // Stopping RTP dump failed, try to stop logging but don't try
90               // to upload since that will fail.
91               chrome.webrtcLoggingPrivate.stop(
92                   requestInfo, origin, function(stopValue, stopErrorString) {
93                 if (chrome.extension.lastError !== undefined) {
94                   // Stopping logging also failed, report the error for logging.
95                   doSendResponse(stopValue, stopErrorString);
96                 } else {
97                   // Stopping logging succeeded, report the error for RTP dump.
98                   doSendResponse(rtpDumpValue, rtpDumpErrorString);
99                 }
100               });
101             } else {
102               // Stopping RTP dump succeeded.
103               chrome.webrtcLoggingPrivate.stop(
104                   requestInfo, origin, function(stopValue, stopErrorString) {
105                 if (chrome.extension.lastError !== undefined) {
106                   // Stopping logging failed, report error and don't try to
107                   // upload since that will fail.
108                   doSendResponse(stopValue, stopErrorString);
109                 } else {
110                   // Stopping logging succeeded.
111                   chrome.webrtcLoggingPrivate.upload(
112                       requestInfo, origin, doSendResponse);
113                 }
114               });
115             }
116           });
117           return true;
118         } else if (method == 'logging.store') {
119           var logId = message['logId'];
120           chrome.webrtcLoggingPrivate.store(
121               requestInfo, origin, logId, doSendResponse);
122           return true;
123         } else if (method == 'logging.discard') {
124           chrome.webrtcLoggingPrivate.discard(
125               requestInfo, origin, doSendResponse);
126           return true;
127         } else if (method == 'getSinks') {
128           chrome.webrtcAudioPrivate.getSinks(doSendResponse);
129           return true;
130         } else if (method == 'getActiveSink') {
131           chrome.webrtcAudioPrivate.getActiveSink(
132               requestInfo, doSendResponse);
133           return true;
134         } else if (method == 'setActiveSink') {
135           var sinkId = message['sinkId'];
136           chrome.webrtcAudioPrivate.setActiveSink(
137               requestInfo, sinkId, doSendResponse);
138           return true;
139         } else if (method == 'getAssociatedSink') {
140           var sourceId = message['sourceId'];
141           chrome.webrtcAudioPrivate.getAssociatedSink(
142               origin, sourceId, doSendResponse);
143           return true;
144         } else if (method == 'isExtensionEnabled') {
145           // This method is necessary because there may be more than one
146           // version of this extension, under different extension IDs. By
147           // first calling this method on the extension ID, the client can
148           // check if it's loaded; if it's not, the extension system will
149           // call the callback with no arguments and set
150           // chrome.runtime.lastError.
151           doSendResponse();
152           return false;
153         } else if (method == 'getNaclArchitecture') {
154           chrome.runtime.getPlatformInfo(function(obj) {
155             doSendResponse(obj.nacl_arch);
156           });
157           return true;
158         } else if (method == 'logging.startRtpDump') {
159           var incoming = message['incoming'] || false;
160           var outgoing = message['outgoing'] || false;
161           chrome.webrtcLoggingPrivate.startRtpDump(
162               requestInfo, origin, incoming, outgoing, doSendResponse);
163           return true;
164         } else if (method == 'logging.stopRtpDump') {
165           var incoming = message['incoming'] || false;
166           var outgoing = message['outgoing'] || false;
167           chrome.webrtcLoggingPrivate.stopRtpDump(
168               requestInfo, origin, incoming, outgoing, doSendResponse);
169           return true;
170         }
171         throw new Error('Unknown method: ' + method);
172       } catch (e) {
173         doSendResponse(null, e.name + ': ' + e.message);
174       }
175     }
178 // If Hangouts connects with a port named 'onSinksChangedListener', we
179 // will register a listener and send it a message {'eventName':
180 // 'onSinksChanged'} whenever the event fires.
181 function onSinksChangedPort(port) {
182   function clientListener() {
183     port.postMessage({'eventName': 'onSinksChanged'});
184   }
185   chrome.webrtcAudioPrivate.onSinksChanged.addListener(clientListener);
187   port.onDisconnect.addListener(function() {
188     chrome.webrtcAudioPrivate.onSinksChanged.removeListener(
189         clientListener);
190   });
193 // This is a one-time-use port for calling chooseDesktopMedia.  The page
194 // sends one message, identifying the requested source types, and the
195 // extension sends a single reply, with the user's selected streamId.  A port
196 // is used so that if the page is closed before that message is sent, the
197 // window picker dialog will be closed.
198 function onChooseDesktopMediaPort(port) {
199   function sendResponse(streamId) {
200     port.postMessage({'value': {'streamId': streamId}});
201     port.disconnect();
202   }
204   port.onMessage.addListener(function(message) {
205     var method = message['method'];
206     if (method == 'chooseDesktopMedia') {
207       var sources = message['sources'];
208       var cancelId = null;
209       if (port.sender.tab) {
210         cancelId = chrome.desktopCapture.chooseDesktopMedia(
211             sources, port.sender.tab, sendResponse);
212       } else {
213         var requestInfo = {};
214         requestInfo['guestProcessId'] = port.sender.guestProcessId || 0;
215         requestInfo['guestRenderFrameId'] =
216             port.sender.guestRenderFrameRoutingId || 0;
217         cancelId = chrome.webrtcDesktopCapturePrivate.chooseDesktopMedia(
218             sources, requestInfo, sendResponse);
219       }
220       port.onDisconnect.addListener(function() {
221         // This method has no effect if called after the user has selected a
222         // desktop media source, so it does not need to be conditional.
223         if (port.sender.tab) {
224           chrome.desktopCapture.cancelChooseDesktopMedia(cancelId);
225         } else {
226           chrome.webrtcDesktopCapturePrivate.cancelChooseDesktopMedia(cancelId);
227         }
228       });
229     }
230   });
233 // A port for continuously reporting relevant CPU usage information to the page.
234 function onProcessCpu(port) {
235   var tabPid = port.sender.guestProcessId || undefined;
236   function processListener(processes) {
237     if (tabPid == undefined) {
238       // getProcessIdForTab sometimes fails, and does not call the callback.
239       // (Tracked at https://crbug.com/368855.)
240       // This call retries it on each process update until it succeeds.
241       chrome.processes.getProcessIdForTab(port.sender.tab.id, function(x) {
242         tabPid = x;
243       });
244       return;
245     }
246     var tabProcess = processes[tabPid];
247     if (!tabProcess) {
248       return;
249     }
250     var pluginProcessCpu = 0, browserProcessCpu = 0, gpuProcessCpu = 0;
251     for (var pid in processes) {
252       var process = processes[pid];
253       if (process.type == 'browser') {
254         browserProcessCpu = process.cpu;
255       } else if (process.type == 'gpu') {
256         gpuProcessCpu = process.cpu;
257       } else if ((process.type == 'plugin' || process.type == 'nacl') &&
258                  process.title.toLowerCase().indexOf('hangouts') > 0) {
259         pluginProcessCpu = process.cpu;
260       }
261     }
263     port.postMessage({
264       'tabCpuUsage': tabProcess.cpu,
265       'browserCpuUsage': browserProcessCpu,
266       'gpuCpuUsage': gpuProcessCpu,
267       'pluginCpuUsage': pluginProcessCpu
268     });
269   }
271   chrome.processes.onUpdated.addListener(processListener);
272   port.onDisconnect.addListener(function() {
273     chrome.processes.onUpdated.removeListener(processListener);
274   });
277 function stopAllRtpDump(requestInfo, origin, callback) {
278   // Stops incoming and outgoing separately, otherwise stopRtpDump will fail if
279   // either type of dump has not been started.
280   chrome.webrtcLoggingPrivate.stopRtpDump(
281       requestInfo, origin, true, false,
282       function() {
283         chrome.webrtcLoggingPrivate.stopRtpDump(
284             requestInfo, origin, false, true, callback);
285       });
288 chrome.runtime.onConnectExternal.addListener(function(port) {
289   if (port.name == 'onSinksChangedListener') {
290     onSinksChangedPort(port);
291   } else if (port.name == 'chooseDesktopMedia') {
292     onChooseDesktopMediaPort(port);
293   } else if (port.name == 'processCpu') {
294     onProcessCpu(port);
295   } else {
296     // Unknown port type.
297     port.disconnect();
298   }