Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(509)

Side by Side Diff: extensions/renderer/resources/messaging.js

Issue 1097583004: Move the Extension Port implementation out of messaging.js into its own file port.js. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 6
7 // TODO(kalman): factor requiring chrome out of here. 7 // TODO(kalman): factor requiring chrome out of here.
8 var chrome = requireNative('chrome').GetChrome(); 8 var chrome = requireNative('chrome').GetChrome();
9 var Event = require('event_bindings').Event;
10 var lastError = require('lastError'); 9 var lastError = require('lastError');
11 var logActivity = requireNative('activityLogger'); 10 var logActivity = requireNative('activityLogger');
12 var logging = requireNative('logging'); 11 var logging = requireNative('logging');
13 var messagingNatives = requireNative('messaging_natives'); 12 var messagingNatives = requireNative('messaging_natives');
13 var Port = require('port').Port;
14 var processNatives = requireNative('process'); 14 var processNatives = requireNative('process');
15 var unloadEvent = require('unload_event'); 15 var unloadEvent = require('unload_event');
16 var utils = require('utils');
17 var messagingUtils = require('messaging_utils'); 16 var messagingUtils = require('messaging_utils');
18 17
19 // The reserved channel name for the sendRequest/send(Native)Message APIs. 18 // The reserved channel name for the sendRequest/send(Native)Message APIs.
20 // Note: sendRequest is deprecated. 19 // Note: sendRequest is deprecated.
21 var kRequestChannel = "chrome.extension.sendRequest"; 20 var kRequestChannel = "chrome.extension.sendRequest";
22 var kMessageChannel = "chrome.runtime.sendMessage"; 21 var kMessageChannel = "chrome.runtime.sendMessage";
23 var kNativeMessageChannel = "chrome.runtime.sendNativeMessage"; 22 var kNativeMessageChannel = "chrome.runtime.sendNativeMessage";
24 23
25 // Map of port IDs to port object. 24 // Map of port IDs to port object.
26 var ports = {}; 25 var ports = {};
27 26
28 // Map of port IDs to unloadEvent listeners. Keep track of these to free the 27 // Map of port IDs to unloadEvent listeners. Keep track of these to free the
29 // unloadEvent listeners when ports are closed. 28 // unloadEvent listeners when ports are closed.
30 var portReleasers = {}; 29 var portReleasers = {};
31 30
32 // Change even to odd and vice versa, to get the other side of a given 31 // Change even to odd and vice versa, to get the other side of a given
33 // channel. 32 // channel.
34 function getOppositePortId(portId) { return portId ^ 1; } 33 function getOppositePortId(portId) { return portId ^ 1; }
35 34
36 // Port object. Represents a connection to another script context through
37 // which messages can be passed.
38 function PortImpl(portId, opt_name) {
39 this.portId_ = portId;
40 this.name = opt_name;
41
42 var portSchema = {name: 'port', $ref: 'runtime.Port'};
43 var options = {unmanaged: true};
44 this.onDisconnect = new Event(null, [portSchema], options);
45 this.onMessage = new Event(
46 null,
47 [{name: 'message', type: 'any', optional: true}, portSchema],
48 options);
49 this.onDestroy_ = null;
50 }
51
52 // Sends a message asynchronously to the context on the other end of this
53 // port.
54 PortImpl.prototype.postMessage = function(msg) {
55 // JSON.stringify doesn't support a root object which is undefined.
56 if (msg === undefined)
57 msg = null;
58 msg = $JSON.stringify(msg);
59 if (msg === undefined) {
60 // JSON.stringify can fail with unserializable objects. Log an error and
61 // drop the message.
62 //
63 // TODO(kalman/mpcomplete): it would be better to do the same validation
64 // here that we do for runtime.sendMessage (and variants), i.e. throw an
65 // schema validation Error, but just maintain the old behaviour until
66 // there's a good reason not to (http://crbug.com/263077).
67 console.error('Illegal argument to Port.postMessage');
68 return;
69 }
70 messagingNatives.PostMessage(this.portId_, msg);
71 };
72
73 // Disconnects the port from the other end.
74 PortImpl.prototype.disconnect = function() {
75 messagingNatives.CloseChannel(this.portId_, true);
76 this.destroy_();
77 };
78
79 PortImpl.prototype.destroy_ = function() {
80 var portId = this.portId_;
81
82 if (this.onDestroy_)
83 this.onDestroy_();
84 privates(this.onDisconnect).impl.destroy_();
85 privates(this.onMessage).impl.destroy_();
86
87 messagingNatives.PortRelease(portId);
88 unloadEvent.removeListener(portReleasers[portId]);
89
90 delete ports[portId];
91 delete portReleasers[portId];
92 };
93
94 // Returns true if the specified port id is in this context. This is used by 35 // Returns true if the specified port id is in this context. This is used by
95 // the C++ to avoid creating the javascript message for all the contexts that 36 // the C++ to avoid creating the javascript message for all the contexts that
96 // don't care about a particular message. 37 // don't care about a particular message.
97 function hasPort(portId) { 38 function hasPort(portId) {
98 return portId in ports; 39 return portId in ports;
99 }; 40 };
100 41
101 // Hidden port creation function. We don't want to expose an API that lets 42 // Hidden port creation function. We don't want to expose an API that lets
102 // people add arbitrary port IDs to the port list. 43 // people add arbitrary port IDs to the port list.
103 function createPort(portId, opt_name) { 44 function createPort(portId, opt_name) {
104 if (ports[portId]) 45 if (ports[portId])
105 throw new Error("Port '" + portId + "' already exists."); 46 throw new Error("Port '" + portId + "' already exists.");
106 var port = new Port(portId, opt_name); 47 var port = new Port(portId, opt_name);
107 ports[portId] = port; 48 ports[portId] = port;
108 portReleasers[portId] = $Function.bind(messagingNatives.PortRelease, 49 portReleasers[portId] = $Function.bind(messagingNatives.PortRelease,
109 this, 50 this,
110 portId); 51 portId);
111 unloadEvent.addListener(portReleasers[portId]); 52 unloadEvent.addListener(portReleasers[portId]);
112 messagingNatives.PortAddRef(portId); 53 messagingNatives.PortAddRef(portId);
113 return port; 54 return port;
114 }; 55 };
115 56
57 // Called when a Port is destroyed. Does general accounting cleanup.
58 function onPortDestroyed(port) {
59 var portId = privates(port).impl.portId_;
60 unloadEvent.removeListener(portReleasers[portId]);
61 delete ports[portId];
62 delete portReleasers[portId];
63 }
64
116 // Helper function for dispatchOnRequest. 65 // Helper function for dispatchOnRequest.
117 function handleSendRequestError(isSendMessage, 66 function handleSendRequestError(isSendMessage,
118 responseCallbackPreserved, 67 responseCallbackPreserved,
119 sourceExtensionId, 68 sourceExtensionId,
120 targetExtensionId, 69 targetExtensionId,
121 sourceUrl) { 70 sourceUrl) {
122 var errorMsg = []; 71 var errorMsg = [];
123 var eventName = isSendMessage ? "runtime.onMessage" : "extension.onRequest"; 72 var eventName = isSendMessage ? "runtime.onMessage" : "extension.onRequest";
124 if (isSendMessage && !responseCallbackPreserved) { 73 if (isSendMessage && !responseCallbackPreserved) {
125 $Array.push(errorMsg, 74 $Array.push(errorMsg,
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 // If they didn't access the response callback, they're not 142 // If they didn't access the response callback, they're not
194 // going to send a response, so clean up the port immediately. 143 // going to send a response, so clean up the port immediately.
195 privates(port).impl.destroy_(); 144 privates(port).impl.destroy_();
196 port = null; 145 port = null;
197 } 146 }
198 } 147 }
199 } 148 }
200 149
201 privates(port).impl.onDestroy_ = function() { 150 privates(port).impl.onDestroy_ = function() {
202 port.onMessage.removeListener(messageListener); 151 port.onMessage.removeListener(messageListener);
152 onPortDestroyed(port);
203 }; 153 };
204 port.onMessage.addListener(messageListener); 154 port.onMessage.addListener(messageListener);
205 155
206 var eventName = isSendMessage ? "runtime.onMessage" : "extension.onRequest"; 156 var eventName = isSendMessage ? "runtime.onMessage" : "extension.onRequest";
207 if (isExternal) 157 if (isExternal)
208 eventName += "External"; 158 eventName += "External";
209 logActivity.LogEvent(targetExtensionId, 159 logActivity.LogEvent(targetExtensionId,
210 eventName, 160 eventName,
211 [sourceExtensionId, sourceUrl]); 161 [sourceExtensionId, sourceUrl]);
212 return true; 162 return true;
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 } 298 }
349 299
350 function messageListener(response) { 300 function messageListener(response) {
351 try { 301 try {
352 responseCallback(response); 302 responseCallback(response);
353 } finally { 303 } finally {
354 port.disconnect(); 304 port.disconnect();
355 } 305 }
356 } 306 }
357 307
358 privates(port).impl.onDestroy_ = function() { 308 privates(port).impl.onDestroy_ = function() {
Devlin 2015/04/17 00:14:52 I don't love this part, especially now that it's i
not at google - send to devlin 2015/04/17 00:16:34 You need to be careful, because Ports are exposed
Devlin 2015/04/17 00:25:52 Right, in my mind there's: Private private: Nothin
not at google - send to devlin 2015/04/17 00:27:59 Heh, a distinction unique to these JS bindings. A
359 port.onDisconnect.removeListener(disconnectListener); 309 port.onDisconnect.removeListener(disconnectListener);
360 port.onMessage.removeListener(messageListener); 310 port.onMessage.removeListener(messageListener);
311 onPortDestroyed(port);
361 }; 312 };
362 port.onDisconnect.addListener(disconnectListener); 313 port.onDisconnect.addListener(disconnectListener);
363 port.onMessage.addListener(messageListener); 314 port.onMessage.addListener(messageListener);
364 }; 315 };
365 316
366 function sendMessageUpdateArguments(functionName, hasOptionsArgument) { 317 function sendMessageUpdateArguments(functionName, hasOptionsArgument) {
367 // skip functionName and hasOptionsArgument 318 // skip functionName and hasOptionsArgument
368 var args = $Array.slice(arguments, 2); 319 var args = $Array.slice(arguments, 2);
369 var alignedArgs = messagingUtils.alignSendMessageArguments(args, 320 var alignedArgs = messagingUtils.alignSendMessageArguments(args,
370 hasOptionsArgument); 321 hasOptionsArgument);
371 if (!alignedArgs) 322 if (!alignedArgs)
372 throw new Error('Invalid arguments to ' + functionName + '.'); 323 throw new Error('Invalid arguments to ' + functionName + '.');
373 return alignedArgs; 324 return alignedArgs;
374 } 325 }
375 326
376 var Port = utils.expose('Port', PortImpl, { functions: [
377 'disconnect',
378 'postMessage'
379 ],
380 properties: [
381 'name',
382 'onDisconnect',
383 'onMessage'
384 ] });
385
386 exports.kRequestChannel = kRequestChannel; 327 exports.kRequestChannel = kRequestChannel;
387 exports.kMessageChannel = kMessageChannel; 328 exports.kMessageChannel = kMessageChannel;
388 exports.kNativeMessageChannel = kNativeMessageChannel; 329 exports.kNativeMessageChannel = kNativeMessageChannel;
389 exports.Port = Port;
390 exports.createPort = createPort; 330 exports.createPort = createPort;
391 exports.sendMessageImpl = sendMessageImpl; 331 exports.sendMessageImpl = sendMessageImpl;
392 exports.sendMessageUpdateArguments = sendMessageUpdateArguments; 332 exports.sendMessageUpdateArguments = sendMessageUpdateArguments;
393 333
394 // For C++ code to call. 334 // For C++ code to call.
395 exports.hasPort = hasPort; 335 exports.hasPort = hasPort;
396 exports.dispatchOnConnect = dispatchOnConnect; 336 exports.dispatchOnConnect = dispatchOnConnect;
397 exports.dispatchOnDisconnect = dispatchOnDisconnect; 337 exports.dispatchOnDisconnect = dispatchOnDisconnect;
398 exports.dispatchOnMessage = dispatchOnMessage; 338 exports.dispatchOnMessage = dispatchOnMessage;
OLDNEW
« no previous file with comments | « extensions/renderer/resources/extensions_renderer_resources.grd ('k') | extensions/renderer/resources/port.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698