OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 // chrome.runtime.messaging API implementation. | 5 // chrome.runtime.messaging API implementation. |
| 6 // TODO(robwu): Fix this indentation. |
6 | 7 |
7 // TODO(kalman): factor requiring chrome out of here. | 8 // TODO(kalman): factor requiring chrome out of here. |
8 var chrome = requireNative('chrome').GetChrome(); | 9 var chrome = requireNative('chrome').GetChrome(); |
9 var Event = require('event_bindings').Event; | 10 var Event = require('event_bindings').Event; |
10 var lastError = require('lastError'); | 11 var lastError = require('lastError'); |
11 var logActivity = requireNative('activityLogger'); | 12 var logActivity = requireNative('activityLogger'); |
12 var logging = requireNative('logging'); | 13 var logging = requireNative('logging'); |
13 var messagingNatives = requireNative('messaging_natives'); | 14 var messagingNatives = requireNative('messaging_natives'); |
14 var processNatives = requireNative('process'); | 15 var processNatives = requireNative('process'); |
15 var utils = require('utils'); | 16 var utils = require('utils'); |
16 var messagingUtils = require('messaging_utils'); | 17 var messagingUtils = require('messaging_utils'); |
17 | 18 |
18 // The reserved channel name for the sendRequest/send(Native)Message APIs. | 19 // The reserved channel name for the sendRequest/send(Native)Message APIs. |
19 // Note: sendRequest is deprecated. | 20 // Note: sendRequest is deprecated. |
20 var kRequestChannel = "chrome.extension.sendRequest"; | 21 var kRequestChannel = "chrome.extension.sendRequest"; |
21 var kMessageChannel = "chrome.runtime.sendMessage"; | 22 var kMessageChannel = "chrome.runtime.sendMessage"; |
22 var kNativeMessageChannel = "chrome.runtime.sendNativeMessage"; | 23 var kNativeMessageChannel = "chrome.runtime.sendNativeMessage"; |
23 | 24 |
24 // Map of port IDs to port object. | 25 // Map of port IDs to port object. |
25 var ports = {}; | 26 var ports = {__proto__:null}; |
26 | 27 |
27 // Change even to odd and vice versa, to get the other side of a given | 28 // Change even to odd and vice versa, to get the other side of a given |
28 // channel. | 29 // channel. |
29 function getOppositePortId(portId) { return portId ^ 1; } | 30 function getOppositePortId(portId) { return portId ^ 1; } |
30 | 31 |
31 // Port object. Represents a connection to another script context through | 32 // Port object. Represents a connection to another script context through |
32 // which messages can be passed. | 33 // which messages can be passed. |
33 function PortImpl(portId, opt_name) { | 34 function PortImpl(portId, opt_name) { |
34 this.portId_ = portId; | 35 this.portId_ = portId; |
35 this.name = opt_name; | 36 this.name = opt_name; |
36 | 37 |
37 var portSchema = {name: 'port', $ref: 'runtime.Port'}; | 38 // Note: Keep these schemas in sync with the documentation in runtime.json |
38 var options = {unmanaged: true}; | 39 var portSchema = { |
| 40 __proto__: null, |
| 41 name: 'port', |
| 42 $ref: 'runtime.Port', |
| 43 }; |
| 44 var messageSchema = { |
| 45 __proto__: null, |
| 46 name: 'message', |
| 47 type: 'any', |
| 48 optional: true, |
| 49 }; |
| 50 var options = { |
| 51 __proto__: null, |
| 52 unmanaged: true, |
| 53 }; |
39 this.onDisconnect = new Event(null, [portSchema], options); | 54 this.onDisconnect = new Event(null, [portSchema], options); |
40 this.onMessage = new Event( | 55 this.onMessage = new Event(null, [messageSchema, portSchema], options); |
41 null, | |
42 [{name: 'message', type: 'any', optional: true}, portSchema], | |
43 options); | |
44 this.onDestroy_ = null; | 56 this.onDestroy_ = null; |
45 } | 57 } |
| 58 $Object.setPrototypeOf(PortImpl, null); |
| 59 $Object.setPrototypeOf(PortImpl.prototype, null); |
46 | 60 |
47 // Sends a message asynchronously to the context on the other end of this | 61 // Sends a message asynchronously to the context on the other end of this |
48 // port. | 62 // port. |
49 PortImpl.prototype.postMessage = function(msg) { | 63 PortImpl.prototype.postMessage = function(msg) { |
50 // JSON.stringify doesn't support a root object which is undefined. | 64 // JSON.stringify doesn't support a root object which is undefined. |
51 if (msg === undefined) | 65 if (msg === undefined) |
52 msg = null; | 66 msg = null; |
53 msg = $JSON.stringify(msg); | 67 msg = $JSON.stringify(msg); |
54 if (msg === undefined) { | 68 if (msg === undefined) { |
55 // JSON.stringify can fail with unserializable objects. Log an error and | 69 // JSON.stringify can fail with unserializable objects. Log an error and |
56 // drop the message. | 70 // drop the message. |
57 // | 71 // |
58 // TODO(kalman/mpcomplete): it would be better to do the same validation | 72 // TODO(kalman/mpcomplete): it would be better to do the same validation |
59 // here that we do for runtime.sendMessage (and variants), i.e. throw an | 73 // here that we do for runtime.sendMessage (and variants), i.e. throw an |
60 // schema validation Error, but just maintain the old behaviour until | 74 // schema validation Error, but just maintain the old behaviour until |
61 // there's a good reason not to (http://crbug.com/263077). | 75 // there's a good reason not to (http://crbug.com/263077). |
62 console.error('Illegal argument to Port.postMessage'); | 76 console.error('Illegal argument to Port.postMessage'); |
63 return; | 77 return; |
64 } | 78 } |
65 messagingNatives.PostMessage(this.portId_, msg); | 79 messagingNatives.PostMessage(this.portId_, msg); |
66 }; | 80 }; |
67 | 81 |
68 // Disconnects the port from the other end. | 82 // Disconnects the port from the other end. |
69 PortImpl.prototype.disconnect = function() { | 83 PortImpl.prototype.disconnect = function() { |
70 messagingNatives.CloseChannel(this.portId_, true); | 84 messagingNatives.CloseChannel(this.portId_, true); |
71 this.destroy_(); | 85 this.destroy_(); |
72 }; | 86 }; |
73 | 87 |
74 PortImpl.prototype.destroy_ = function() { | 88 PortImpl.prototype.destroy_ = function() { |
75 if (this.onDestroy_) | 89 if (this.onDestroy_) { |
76 this.onDestroy_(); | 90 this.onDestroy_(); |
| 91 this.onDestroy_ = null; |
| 92 } |
77 privates(this.onDisconnect).impl.destroy_(); | 93 privates(this.onDisconnect).impl.destroy_(); |
78 privates(this.onMessage).impl.destroy_(); | 94 privates(this.onMessage).impl.destroy_(); |
79 // TODO(robwu): Remove port lifetime management because it is completely | 95 // TODO(robwu): Remove port lifetime management because it is completely |
80 // handled in the browser. The renderer's only roles are | 96 // handled in the browser. The renderer's only roles are |
81 // 1) rejecting ports so that the browser knows that the renderer is not | 97 // 1) rejecting ports so that the browser knows that the renderer is not |
82 // interested in the port (this is merely an optimization) | 98 // interested in the port (this is merely an optimization) |
83 // 2) acknowledging port creations, so that the browser knows that the port | 99 // 2) acknowledging port creations, so that the browser knows that the port |
84 // was successfully created (from the perspective of the extension), but | 100 // was successfully created (from the perspective of the extension), but |
85 // then closed for some non-fatal reason. | 101 // then closed for some non-fatal reason. |
86 // 3) notifying the browser of explicit port closure via .disconnect(). | 102 // 3) notifying the browser of explicit port closure via .disconnect(). |
(...skipping 20 matching lines...) Expand all Loading... |
107 messagingNatives.PortAddRef(portId); | 123 messagingNatives.PortAddRef(portId); |
108 return port; | 124 return port; |
109 }; | 125 }; |
110 | 126 |
111 // Helper function for dispatchOnRequest. | 127 // Helper function for dispatchOnRequest. |
112 function handleSendRequestError(isSendMessage, | 128 function handleSendRequestError(isSendMessage, |
113 responseCallbackPreserved, | 129 responseCallbackPreserved, |
114 sourceExtensionId, | 130 sourceExtensionId, |
115 targetExtensionId, | 131 targetExtensionId, |
116 sourceUrl) { | 132 sourceUrl) { |
117 var errorMsg = []; | 133 var errorMsg; |
118 var eventName = isSendMessage ? "runtime.onMessage" : "extension.onRequest"; | 134 var eventName = isSendMessage ? 'runtime.onMessage' : 'extension.onRequest'; |
119 if (isSendMessage && !responseCallbackPreserved) { | 135 if (isSendMessage && !responseCallbackPreserved) { |
120 $Array.push(errorMsg, | 136 errorMsg = |
121 "The chrome." + eventName + " listener must return true if you " + | 137 'The chrome.' + eventName + ' listener must return true if you ' + |
122 "want to send a response after the listener returns"); | 138 'want to send a response after the listener returns'; |
123 } else { | 139 } else { |
124 $Array.push(errorMsg, | 140 errorMsg = |
125 "Cannot send a response more than once per chrome." + eventName + | 141 'Cannot send a response more than once per chrome.' + eventName + |
126 " listener per document"); | 142 ' listener per document'; |
127 } | 143 } |
128 $Array.push(errorMsg, "(message was sent by extension" + sourceExtensionId); | 144 errorMsg += ' (message was sent by extension' + sourceExtensionId; |
129 if (sourceExtensionId != "" && sourceExtensionId != targetExtensionId) | 145 if (sourceExtensionId && sourceExtensionId !== targetExtensionId) |
130 $Array.push(errorMsg, "for extension " + targetExtensionId); | 146 errorMsg += ' for extension ' + targetExtensionId; |
131 if (sourceUrl != "") | 147 if (sourceUrl) |
132 $Array.push(errorMsg, "for URL " + sourceUrl); | 148 errorMsg += ' for URL ' + sourceUrl; |
133 lastError.set(eventName, errorMsg.join(" ") + ").", null, chrome); | 149 errorMsg += ').'; |
| 150 lastError.set(eventName, errorMsg, null, chrome); |
134 } | 151 } |
135 | 152 |
136 // Helper function for dispatchOnConnect | 153 // Helper function for dispatchOnConnect |
137 function dispatchOnRequest(portId, channelName, sender, | 154 function dispatchOnRequest(portId, channelName, sender, |
138 sourceExtensionId, targetExtensionId, sourceUrl, | 155 sourceExtensionId, targetExtensionId, sourceUrl, |
139 isExternal) { | 156 isExternal) { |
140 var isSendMessage = channelName == kMessageChannel; | 157 var isSendMessage = channelName == kMessageChannel; |
141 var requestEvent = null; | 158 var requestEvent = null; |
142 if (isSendMessage) { | 159 if (isSendMessage) { |
143 if (chrome.runtime) { | 160 if (chrome.runtime) { |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 exports.$set('Port', Port); | 438 exports.$set('Port', Port); |
422 exports.$set('createPort', createPort); | 439 exports.$set('createPort', createPort); |
423 exports.$set('sendMessageImpl', sendMessageImpl); | 440 exports.$set('sendMessageImpl', sendMessageImpl); |
424 exports.$set('sendMessageUpdateArguments', sendMessageUpdateArguments); | 441 exports.$set('sendMessageUpdateArguments', sendMessageUpdateArguments); |
425 | 442 |
426 // For C++ code to call. | 443 // For C++ code to call. |
427 exports.$set('hasPort', hasPort); | 444 exports.$set('hasPort', hasPort); |
428 exports.$set('dispatchOnConnect', dispatchOnConnect); | 445 exports.$set('dispatchOnConnect', dispatchOnConnect); |
429 exports.$set('dispatchOnDisconnect', dispatchOnDisconnect); | 446 exports.$set('dispatchOnDisconnect', dispatchOnDisconnect); |
430 exports.$set('dispatchOnMessage', dispatchOnMessage); | 447 exports.$set('dispatchOnMessage', dispatchOnMessage); |
OLD | NEW |