Chromium Code Reviews| 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 |