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
) {
11 error
['name'] = 'ComponentExtensonError';
12 error
['message'] = errorString
;
15 var errorMessage
= error
|| chrome
.extension
.lastError
;
16 sendResponse({'value': value
, 'error': errorMessage
});
19 function getHost(url
) {
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');
27 var origin
= a
.protocol
+ '//' + a
.hostname
;
29 origin
= origin
+ ':' + a
.port
;
30 origin
= origin
+ '/';
37 requestInfo
['tabId'] = sender
.tab
.id
;
40 if (sender
.guestProcessId
) {
41 requestInfo
['guestProcessId'] = sender
.guestProcessId
;
44 if (sender
.guestRenderFrameRoutingId
) {
45 requestInfo
['guestRenderFrameId'] = sender
.guestRenderFrameRoutingId
;
48 var method
= message
['method'];
49 var origin
= getHost(sender
.url
);
50 if (method
== 'cpu.getInfo') {
51 chrome
.system
.cpu
.getInfo(doSendResponse
);
53 } else if (method
== 'logging.setMetadata') {
54 var metaData
= message
['metaData'];
55 chrome
.webrtcLoggingPrivate
.setMetaData(
56 requestInfo
, origin
, metaData
, doSendResponse
);
58 } else if (method
== 'logging.start') {
59 chrome
.webrtcLoggingPrivate
.start(
60 requestInfo
, origin
, doSendResponse
);
62 } else if (method
== 'logging.uploadOnRenderClose') {
63 chrome
.webrtcLoggingPrivate
.setUploadOnRenderClose(
64 requestInfo
, origin
, true);
67 } else if (method
== 'logging.noUploadOnRenderClose') {
68 chrome
.webrtcLoggingPrivate
.setUploadOnRenderClose(
69 requestInfo
, origin
, false);
72 } else if (method
== 'logging.stop') {
73 chrome
.webrtcLoggingPrivate
.stop(
74 requestInfo
, origin
, doSendResponse
);
76 } else if (method
== 'logging.upload') {
77 chrome
.webrtcLoggingPrivate
.upload(
78 requestInfo
, origin
, doSendResponse
);
80 } else if (method
== 'logging.uploadStored') {
81 var logId
= message
['logId'];
82 chrome
.webrtcLoggingPrivate
.uploadStored(
83 requestInfo
, origin
, logId
, doSendResponse
);
85 } else if (method
== 'logging.stopAndUpload') {
86 stopAllRtpDump(requestInfo
, origin
, function() {
87 chrome
.webrtcLoggingPrivate
.stop(requestInfo
, origin
, function() {
88 chrome
.webrtcLoggingPrivate
.upload(
89 requestInfo
, origin
, doSendResponse
);
93 } else if (method
== 'logging.store') {
94 var logId
= message
['logId'];
95 chrome
.webrtcLoggingPrivate
.store(
96 requestInfo
, origin
, logId
, doSendResponse
);
98 } else if (method
== 'logging.discard') {
99 chrome
.webrtcLoggingPrivate
.discard(
100 requestInfo
, origin
, doSendResponse
);
102 } else if (method
== 'getSinks') {
103 chrome
.webrtcAudioPrivate
.getSinks(doSendResponse
);
105 } else if (method
== 'getActiveSink') {
106 chrome
.webrtcAudioPrivate
.getActiveSink(
107 requestInfo
, doSendResponse
);
109 } else if (method
== 'setActiveSink') {
110 var sinkId
= message
['sinkId'];
111 chrome
.webrtcAudioPrivate
.setActiveSink(
112 requestInfo
, sinkId
, doSendResponse
);
114 } else if (method
== 'getAssociatedSink') {
115 var sourceId
= message
['sourceId'];
116 chrome
.webrtcAudioPrivate
.getAssociatedSink(
117 origin
, sourceId
, doSendResponse
);
119 } else if (method
== 'isExtensionEnabled') {
120 // This method is necessary because there may be more than one
121 // version of this extension, under different extension IDs. By
122 // first calling this method on the extension ID, the client can
123 // check if it's loaded; if it's not, the extension system will
124 // call the callback with no arguments and set
125 // chrome.runtime.lastError.
128 } else if (method
== 'getNaclArchitecture') {
129 chrome
.runtime
.getPlatformInfo(function(obj
) {
130 doSendResponse(obj
.nacl_arch
);
133 } else if (method
== 'logging.startRtpDump') {
134 var incoming
= message
['incoming'] || false;
135 var outgoing
= message
['outgoing'] || false;
136 chrome
.webrtcLoggingPrivate
.startRtpDump(
137 requestInfo
, origin
, incoming
, outgoing
, doSendResponse
);
139 } else if (method
== 'logging.stopRtpDump') {
140 var incoming
= message
['incoming'] || false;
141 var outgoing
= message
['outgoing'] || false;
142 chrome
.webrtcLoggingPrivate
.stopRtpDump(
143 requestInfo
, origin
, incoming
, outgoing
, doSendResponse
);
146 throw new Error('Unknown method: ' + method
);
148 doSendResponse(null, e
.name
+ ': ' + e
.message
);
153 // If Hangouts connects with a port named 'onSinksChangedListener', we
154 // will register a listener and send it a message {'eventName':
155 // 'onSinksChanged'} whenever the event fires.
156 function onSinksChangedPort(port
) {
157 function clientListener() {
158 port
.postMessage({'eventName': 'onSinksChanged'});
160 chrome
.webrtcAudioPrivate
.onSinksChanged
.addListener(clientListener
);
162 port
.onDisconnect
.addListener(function() {
163 chrome
.webrtcAudioPrivate
.onSinksChanged
.removeListener(
168 // This is a one-time-use port for calling chooseDesktopMedia. The page
169 // sends one message, identifying the requested source types, and the
170 // extension sends a single reply, with the user's selected streamId. A port
171 // is used so that if the page is closed before that message is sent, the
172 // window picker dialog will be closed.
173 function onChooseDesktopMediaPort(port
) {
174 function sendResponse(streamId
) {
175 port
.postMessage({'value': {'streamId': streamId
}});
179 port
.onMessage
.addListener(function(message
) {
180 var method
= message
['method'];
181 if (method
== 'chooseDesktopMedia') {
182 var sources
= message
['sources'];
184 if (port
.sender
.tab
) {
185 cancelId
= chrome
.desktopCapture
.chooseDesktopMedia(
186 sources
, port
.sender
.tab
, sendResponse
);
188 var requestInfo
= {};
189 requestInfo
['guestProcessId'] = port
.sender
.guestProcessId
|| 0;
190 requestInfo
['guestRenderFrameId'] =
191 port
.sender
.guestRenderFrameRoutingId
|| 0;
192 cancelId
= chrome
.webrtcDesktopCapturePrivate
.chooseDesktopMedia(
193 sources
, requestInfo
, sendResponse
);
195 port
.onDisconnect
.addListener(function() {
196 // This method has no effect if called after the user has selected a
197 // desktop media source, so it does not need to be conditional.
198 if (port
.sender
.tab
) {
199 chrome
.desktopCapture
.cancelChooseDesktopMedia(cancelId
);
201 chrome
.webrtcDesktopCapturePrivate
.cancelChooseDesktopMedia(cancelId
);
208 // A port for continuously reporting relevant CPU usage information to the page.
209 function onProcessCpu(port
) {
210 var tabPid
= port
.sender
.guestProcessId
|| undefined;
211 function processListener(processes
) {
212 if (tabPid
== undefined) {
213 // getProcessIdForTab sometimes fails, and does not call the callback.
214 // (Tracked at https://crbug.com/368855.)
215 // This call retries it on each process update until it succeeds.
216 chrome
.processes
.getProcessIdForTab(port
.sender
.tab
.id
, function(x
) {
221 var tabProcess
= processes
[tabPid
];
225 var pluginProcessCpu
= 0, browserProcessCpu
= 0, gpuProcessCpu
= 0;
226 for (var pid
in processes
) {
227 var process
= processes
[pid
];
228 if (process
.type
== 'browser') {
229 browserProcessCpu
= process
.cpu
;
230 } else if (process
.type
== 'gpu') {
231 gpuProcessCpu
= process
.cpu
;
232 } else if ((process
.type
== 'plugin' || process
.type
== 'nacl') &&
233 process
.title
.toLowerCase().indexOf('hangouts') > 0) {
234 pluginProcessCpu
= process
.cpu
;
239 'tabCpuUsage': tabProcess
.cpu
,
240 'browserCpuUsage': browserProcessCpu
,
241 'gpuCpuUsage': gpuProcessCpu
,
242 'pluginCpuUsage': pluginProcessCpu
246 chrome
.processes
.onUpdated
.addListener(processListener
);
247 port
.onDisconnect
.addListener(function() {
248 chrome
.processes
.onUpdated
.removeListener(processListener
);
252 function stopAllRtpDump(requestInfo
, origin
, callback
) {
253 // Stops incoming and outgoing separately, otherwise stopRtpDump will fail if
254 // either type of dump has not been started.
255 chrome
.webrtcLoggingPrivate
.stopRtpDump(
256 requestInfo
, origin
, true, false,
258 chrome
.webrtcLoggingPrivate
.stopRtpDump(
259 requestInfo
, origin
, false, true, callback
);
263 chrome
.runtime
.onConnectExternal
.addListener(function(port
) {
264 if (port
.name
== 'onSinksChangedListener') {
265 onSinksChangedPort(port
);
266 } else if (port
.name
== 'chooseDesktopMedia') {
267 onChooseDesktopMediaPort(port
);
268 } else if (port
.name
== 'processCpu') {
271 // Unknown port type.