OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This contains unprivileged javascript APIs for extensions and apps. It | 5 // This contains unprivileged javascript APIs for extensions and apps. It |
6 // can be loaded by any extension-related context, such as content scripts or | 6 // can be loaded by any extension-related context, such as content scripts or |
7 // background pages. See user_script_slave.cc for script that is loaded by | 7 // background pages. See user_script_slave.cc for script that is loaded by |
8 // content scripts only. | 8 // content scripts only. |
9 | 9 |
10 // TODO(kalman): factor requiring chrome out of here. | 10 // TODO(kalman): factor requiring chrome out of here. |
(...skipping 12 matching lines...) Expand all Loading... | |
23 var kMessageChannel = "chrome.runtime.sendMessage"; | 23 var kMessageChannel = "chrome.runtime.sendMessage"; |
24 var kNativeMessageChannel = "chrome.runtime.sendNativeMessage"; | 24 var kNativeMessageChannel = "chrome.runtime.sendNativeMessage"; |
25 | 25 |
26 // Map of port IDs to port object. | 26 // Map of port IDs to port object. |
27 var ports = {}; | 27 var ports = {}; |
28 | 28 |
29 // Map of port IDs to unloadEvent listeners. Keep track of these to free the | 29 // Map of port IDs to unloadEvent listeners. Keep track of these to free the |
30 // unloadEvent listeners when ports are closed. | 30 // unloadEvent listeners when ports are closed. |
31 var portReleasers = {}; | 31 var portReleasers = {}; |
32 | 32 |
33 // A stack of tabs ids for the tabs that are dispatching requests. | |
34 var dispatchingTabIds = []; | |
35 | |
33 // Change even to odd and vice versa, to get the other side of a given | 36 // Change even to odd and vice versa, to get the other side of a given |
34 // channel. | 37 // channel. |
35 function getOppositePortId(portId) { return portId ^ 1; } | 38 function getOppositePortId(portId) { return portId ^ 1; } |
36 | 39 |
37 // Port object. Represents a connection to another script context through | 40 // Port object. Represents a connection to another script context through |
38 // which messages can be passed. | 41 // which messages can be passed. |
39 function Port(portId, opt_name) { | 42 function Port(portId, opt_name) { |
40 this.portId_ = portId; | 43 this.portId_ = portId; |
41 this.name = opt_name; | 44 this.name = opt_name; |
42 | 45 |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
135 if (sourceExtensionId != "" && sourceExtensionId != targetExtensionId) | 138 if (sourceExtensionId != "" && sourceExtensionId != targetExtensionId) |
136 $Array.push(errorMsg, "for extension " + targetExtensionId); | 139 $Array.push(errorMsg, "for extension " + targetExtensionId); |
137 if (sourceUrl != "") | 140 if (sourceUrl != "") |
138 $Array.push(errorMsg, "for URL " + sourceUrl); | 141 $Array.push(errorMsg, "for URL " + sourceUrl); |
139 lastError.set(eventName, errorMsg.join(" ") + ").", null, chrome); | 142 lastError.set(eventName, errorMsg.join(" ") + ").", null, chrome); |
140 } | 143 } |
141 | 144 |
142 // Helper function for dispatchOnConnect | 145 // Helper function for dispatchOnConnect |
143 function dispatchOnRequest(portId, channelName, sender, | 146 function dispatchOnRequest(portId, channelName, sender, |
144 sourceExtensionId, targetExtensionId, sourceUrl, | 147 sourceExtensionId, targetExtensionId, sourceUrl, |
145 isExternal) { | 148 isExternal, senderTabId) { |
146 var isSendMessage = channelName == kMessageChannel; | 149 var isSendMessage = channelName == kMessageChannel; |
147 var requestEvent = null; | 150 var requestEvent = null; |
148 if (isSendMessage) { | 151 if (isSendMessage) { |
149 if (chrome.runtime) { | 152 if (chrome.runtime) { |
150 requestEvent = isExternal ? chrome.runtime.onMessageExternal | 153 requestEvent = isExternal ? chrome.runtime.onMessageExternal |
151 : chrome.runtime.onMessage; | 154 : chrome.runtime.onMessage; |
152 } | 155 } |
153 } else { | 156 } else { |
154 if (chrome.extension) { | 157 if (chrome.extension) { |
155 requestEvent = isExternal ? chrome.extension.onRequestExternal | 158 requestEvent = isExternal ? chrome.extension.onRequestExternal |
(...skipping 23 matching lines...) Expand all Loading... | |
179 // In case the extension never invokes the responseCallback, and also | 182 // In case the extension never invokes the responseCallback, and also |
180 // doesn't keep a reference to it, we need to clean up the port. Do | 183 // doesn't keep a reference to it, we need to clean up the port. Do |
181 // so by attaching to the garbage collection of the responseCallback | 184 // so by attaching to the garbage collection of the responseCallback |
182 // using some native hackery. | 185 // using some native hackery. |
183 messagingNatives.BindToGC(responseCallback, function() { | 186 messagingNatives.BindToGC(responseCallback, function() { |
184 if (port) { | 187 if (port) { |
185 port.destroy_(); | 188 port.destroy_(); |
186 port = null; | 189 port = null; |
187 } | 190 } |
188 }); | 191 }); |
192 if (senderTabId) | |
193 dispatchingTabIds.push(senderTabId); | |
189 var rv = requestEvent.dispatch(request, sender, responseCallback); | 194 var rv = requestEvent.dispatch(request, sender, responseCallback); |
195 if (senderTabId) | |
196 dispatchingTabIds.pop(); | |
197 | |
190 if (isSendMessage) { | 198 if (isSendMessage) { |
191 responseCallbackPreserved = | 199 responseCallbackPreserved = |
192 rv && rv.results && $Array.indexOf(rv.results, true) > -1; | 200 rv && rv.results && $Array.indexOf(rv.results, true) > -1; |
193 if (!responseCallbackPreserved && port) { | 201 if (!responseCallbackPreserved && port) { |
194 // If they didn't access the response callback, they're not | 202 // If they didn't access the response callback, they're not |
195 // going to send a response, so clean up the port immediately. | 203 // going to send a response, so clean up the port immediately. |
196 port.destroy_(); | 204 port.destroy_(); |
197 port = null; | 205 port = null; |
198 } | 206 } |
199 } | 207 } |
(...skipping 13 matching lines...) Expand all Loading... | |
213 return true; | 221 return true; |
214 } | 222 } |
215 | 223 |
216 // Called by native code when a channel has been opened to this context. | 224 // Called by native code when a channel has been opened to this context. |
217 function dispatchOnConnect(portId, | 225 function dispatchOnConnect(portId, |
218 channelName, | 226 channelName, |
219 sourceTab, | 227 sourceTab, |
220 sourceExtensionId, | 228 sourceExtensionId, |
221 targetExtensionId, | 229 targetExtensionId, |
222 sourceUrl, | 230 sourceUrl, |
223 tlsChannelId) { | 231 tlsChannelId) { |
not at google - send to devlin
2014/01/23 16:41:59
you could pass the isPlatformApp flag in here and
| |
224 // Only create a new Port if someone is actually listening for a connection. | 232 // Only create a new Port if someone is actually listening for a connection. |
225 // In addition to being an optimization, this also fixes a bug where if 2 | 233 // In addition to being an optimization, this also fixes a bug where if 2 |
226 // channels were opened to and from the same process, closing one would | 234 // channels were opened to and from the same process, closing one would |
227 // close both. | 235 // close both. |
228 var extensionId = processNatives.GetExtensionId(); | 236 var extensionId = processNatives.GetExtensionId(); |
229 if (targetExtensionId != extensionId) | 237 if (targetExtensionId != extensionId) |
230 return false; // not for us | 238 return false; // not for us |
231 | 239 |
232 if (ports[getOppositePortId(portId)]) | 240 if (ports[getOppositePortId(portId)]) |
233 return false; // this channel was opened by us, so ignore it | 241 return false; // this channel was opened by us, so ignore it |
234 | 242 |
235 // Determine whether this is coming from another extension, so we can use | 243 // Determine whether this is coming from another extension, so we can use |
236 // the right event. | 244 // the right event. |
237 var isExternal = sourceExtensionId != extensionId; | 245 var isExternal = sourceExtensionId != extensionId; |
238 | 246 |
239 var sender = {}; | 247 var sender = {}; |
240 if (sourceExtensionId != '') | 248 if (sourceExtensionId != '') |
241 sender.id = sourceExtensionId; | 249 sender.id = sourceExtensionId; |
242 if (sourceUrl) | 250 if (sourceUrl) |
243 sender.url = sourceUrl; | 251 sender.url = sourceUrl; |
244 if (sourceTab) | 252 if (sourceTab && !('isPlatformApp' in sourceTab)) |
245 sender.tab = sourceTab; | 253 sender.tab = sourceTab; |
246 if (tlsChannelId !== undefined) | 254 if (tlsChannelId !== undefined) |
247 sender.tlsChannelId = tlsChannelId; | 255 sender.tlsChannelId = tlsChannelId; |
248 | 256 |
249 // Special case for sendRequest/onRequest and sendMessage/onMessage. | 257 // Special case for sendRequest/onRequest and sendMessage/onMessage. |
250 if (channelName == kRequestChannel || channelName == kMessageChannel) { | 258 if (channelName == kRequestChannel || channelName == kMessageChannel) { |
259 var senderTabId = | |
260 (sourceTab && ('id' in sourceTab) && ('isPlatformApp' in sourceTab)) ? | |
261 sourceTab['id'] : null; | |
251 return dispatchOnRequest(portId, channelName, sender, | 262 return dispatchOnRequest(portId, channelName, sender, |
252 sourceExtensionId, targetExtensionId, sourceUrl, | 263 sourceExtensionId, targetExtensionId, sourceUrl, |
253 isExternal); | 264 isExternal, senderTabId); |
not at google - send to devlin
2014/01/23 16:41:59
The above comment said... maybe it would be easier
| |
254 } | 265 } |
255 | 266 |
256 var connectEvent = null; | 267 var connectEvent = null; |
257 if (chrome.runtime) { | 268 if (chrome.runtime) { |
258 connectEvent = isExternal ? chrome.runtime.onConnectExternal | 269 connectEvent = isExternal ? chrome.runtime.onConnectExternal |
259 : chrome.runtime.onConnect; | 270 : chrome.runtime.onConnect; |
260 } | 271 } |
261 if (!connectEvent) | 272 if (!connectEvent) |
262 return false; | 273 return false; |
263 if (!connectEvent.hasListeners()) | 274 if (!connectEvent.hasListeners()) |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
353 function sendMessageUpdateArguments(functionName, hasOptionsArgument) { | 364 function sendMessageUpdateArguments(functionName, hasOptionsArgument) { |
354 // skip functionName and hasOptionsArgument | 365 // skip functionName and hasOptionsArgument |
355 var args = $Array.slice(arguments, 2); | 366 var args = $Array.slice(arguments, 2); |
356 var alignedArgs = messagingUtils.alignSendMessageArguments(args, | 367 var alignedArgs = messagingUtils.alignSendMessageArguments(args, |
357 hasOptionsArgument); | 368 hasOptionsArgument); |
358 if (!alignedArgs) | 369 if (!alignedArgs) |
359 throw new Error('Invalid arguments to ' + functionName + '.'); | 370 throw new Error('Invalid arguments to ' + functionName + '.'); |
360 return alignedArgs; | 371 return alignedArgs; |
361 } | 372 } |
362 | 373 |
374 function currentTabId() { | |
375 return dispatchingTabIds[dispatchingTabIds.length - 1]; | |
376 } | |
377 | |
363 exports.kRequestChannel = kRequestChannel; | 378 exports.kRequestChannel = kRequestChannel; |
364 exports.kMessageChannel = kMessageChannel; | 379 exports.kMessageChannel = kMessageChannel; |
365 exports.kNativeMessageChannel = kNativeMessageChannel; | 380 exports.kNativeMessageChannel = kNativeMessageChannel; |
366 exports.Port = Port; | 381 exports.Port = Port; |
367 exports.createPort = createPort; | 382 exports.createPort = createPort; |
368 exports.sendMessageImpl = sendMessageImpl; | 383 exports.sendMessageImpl = sendMessageImpl; |
369 exports.sendMessageUpdateArguments = sendMessageUpdateArguments; | 384 exports.sendMessageUpdateArguments = sendMessageUpdateArguments; |
385 exports.currentTabId = currentTabId; | |
370 | 386 |
371 // For C++ code to call. | 387 // For C++ code to call. |
372 exports.hasPort = hasPort; | 388 exports.hasPort = hasPort; |
373 exports.dispatchOnConnect = dispatchOnConnect; | 389 exports.dispatchOnConnect = dispatchOnConnect; |
374 exports.dispatchOnDisconnect = dispatchOnDisconnect; | 390 exports.dispatchOnDisconnect = dispatchOnDisconnect; |
375 exports.dispatchOnMessage = dispatchOnMessage; | 391 exports.dispatchOnMessage = dispatchOnMessage; |
OLD | NEW |