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

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

Issue 141803016: Hide Port privates (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Expose name property Created 6 years, 10 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
« no previous file with comments | « no previous file | chrome/renderer/resources/extensions/utils.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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.
11 var chrome = requireNative('chrome').GetChrome(); 11 var chrome = requireNative('chrome').GetChrome();
12 var Event = require('event_bindings').Event; 12 var Event = require('event_bindings').Event;
13 var lastError = require('lastError'); 13 var lastError = require('lastError');
14 var logActivity = requireNative('activityLogger'); 14 var logActivity = requireNative('activityLogger');
15 var messagingNatives = requireNative('messaging_natives'); 15 var messagingNatives = requireNative('messaging_natives');
16 var processNatives = requireNative('process'); 16 var processNatives = requireNative('process');
17 var unloadEvent = require('unload_event'); 17 var unloadEvent = require('unload_event');
18 var utils = require('utils');
18 var messagingUtils = require('messaging_utils'); 19 var messagingUtils = require('messaging_utils');
19 20
20 // The reserved channel name for the sendRequest/send(Native)Message APIs. 21 // The reserved channel name for the sendRequest/send(Native)Message APIs.
21 // Note: sendRequest is deprecated. 22 // Note: sendRequest is deprecated.
22 var kRequestChannel = "chrome.extension.sendRequest"; 23 var kRequestChannel = "chrome.extension.sendRequest";
23 var kMessageChannel = "chrome.runtime.sendMessage"; 24 var kMessageChannel = "chrome.runtime.sendMessage";
24 var kNativeMessageChannel = "chrome.runtime.sendNativeMessage"; 25 var kNativeMessageChannel = "chrome.runtime.sendNativeMessage";
25 26
26 // Map of port IDs to port object. 27 // Map of port IDs to port object.
27 var ports = {}; 28 var ports = {};
28 29
29 // Map of port IDs to unloadEvent listeners. Keep track of these to free the 30 // Map of port IDs to unloadEvent listeners. Keep track of these to free the
30 // unloadEvent listeners when ports are closed. 31 // unloadEvent listeners when ports are closed.
31 var portReleasers = {}; 32 var portReleasers = {};
32 33
33 // Change even to odd and vice versa, to get the other side of a given 34 // Change even to odd and vice versa, to get the other side of a given
34 // channel. 35 // channel.
35 function getOppositePortId(portId) { return portId ^ 1; } 36 function getOppositePortId(portId) { return portId ^ 1; }
36 37
37 // Port object. Represents a connection to another script context through 38 // Port object. Represents a connection to another script context through
38 // which messages can be passed. 39 // which messages can be passed.
39 function Port(portId, opt_name) { 40 function PortImpl(portId, opt_name) {
40 this.portId_ = portId; 41 this.portId_ = portId;
41 this.name = opt_name; 42 this.name = opt_name;
42 43
43 var portSchema = {name: 'port', $ref: 'runtime.Port'}; 44 var portSchema = {name: 'port', $ref: 'runtime.Port'};
44 var options = {unmanaged: true}; 45 var options = {unmanaged: true};
45 this.onDisconnect = new Event(null, [portSchema], options); 46 this.onDisconnect = new Event(null, [portSchema], options);
46 this.onMessage = new Event( 47 this.onMessage = new Event(
47 null, 48 null,
48 [{name: 'message', type: 'any', optional: true}, portSchema], 49 [{name: 'message', type: 'any', optional: true}, portSchema],
49 options); 50 options);
50 this.onDestroy_ = null; 51 this.onDestroy_ = null;
51 } 52 }
52 53
53 // Sends a message asynchronously to the context on the other end of this 54 // Sends a message asynchronously to the context on the other end of this
54 // port. 55 // port.
55 Port.prototype.postMessage = function(msg) { 56 PortImpl.prototype.postMessage = function(msg) {
56 // JSON.stringify doesn't support a root object which is undefined. 57 // JSON.stringify doesn't support a root object which is undefined.
57 if (msg === undefined) 58 if (msg === undefined)
58 msg = null; 59 msg = null;
59 msg = $JSON.stringify(msg); 60 msg = $JSON.stringify(msg);
60 if (msg === undefined) { 61 if (msg === undefined) {
61 // JSON.stringify can fail with unserializable objects. Log an error and 62 // JSON.stringify can fail with unserializable objects. Log an error and
62 // drop the message. 63 // drop the message.
63 // 64 //
64 // TODO(kalman/mpcomplete): it would be better to do the same validation 65 // TODO(kalman/mpcomplete): it would be better to do the same validation
65 // here that we do for runtime.sendMessage (and variants), i.e. throw an 66 // here that we do for runtime.sendMessage (and variants), i.e. throw an
66 // schema validation Error, but just maintain the old behaviour until 67 // schema validation Error, but just maintain the old behaviour until
67 // there's a good reason not to (http://crbug.com/263077). 68 // there's a good reason not to (http://crbug.com/263077).
68 console.error('Illegal argument to Port.postMessage'); 69 console.error('Illegal argument to Port.postMessage');
69 return; 70 return;
70 } 71 }
71 messagingNatives.PostMessage(this.portId_, msg); 72 messagingNatives.PostMessage(this.portId_, msg);
72 }; 73 };
73 74
74 // Disconnects the port from the other end. 75 // Disconnects the port from the other end.
75 Port.prototype.disconnect = function() { 76 PortImpl.prototype.disconnect = function() {
76 messagingNatives.CloseChannel(this.portId_, true); 77 messagingNatives.CloseChannel(this.portId_, true);
77 this.destroy_(); 78 this.destroy_();
78 }; 79 };
79 80
80 Port.prototype.destroy_ = function() { 81 PortImpl.prototype.destroy_ = function() {
81 var portId = this.portId_; 82 var portId = this.portId_;
82 83
83 if (this.onDestroy_) 84 if (this.onDestroy_)
84 this.onDestroy_(); 85 this.onDestroy_();
85 privates(this.onDisconnect).impl.destroy_(); 86 privates(this.onDisconnect).impl.destroy_();
86 privates(this.onMessage).impl.destroy_(); 87 privates(this.onMessage).impl.destroy_();
87 88
88 messagingNatives.PortRelease(portId); 89 messagingNatives.PortRelease(portId);
89 unloadEvent.removeListener(portReleasers[portId]); 90 unloadEvent.removeListener(portReleasers[portId]);
90 91
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 return false; 161 return false;
161 if (!requestEvent.hasListeners()) 162 if (!requestEvent.hasListeners())
162 return false; 163 return false;
163 var port = createPort(portId, channelName); 164 var port = createPort(portId, channelName);
164 165
165 function messageListener(request) { 166 function messageListener(request) {
166 var responseCallbackPreserved = false; 167 var responseCallbackPreserved = false;
167 var responseCallback = function(response) { 168 var responseCallback = function(response) {
168 if (port) { 169 if (port) {
169 port.postMessage(response); 170 port.postMessage(response);
170 port.destroy_(); 171 privates(port).impl.destroy_();
171 port = null; 172 port = null;
172 } else { 173 } else {
173 // We nulled out port when sending the response, and now the page 174 // We nulled out port when sending the response, and now the page
174 // is trying to send another response for the same request. 175 // is trying to send another response for the same request.
175 handleSendRequestError(isSendMessage, responseCallbackPreserved, 176 handleSendRequestError(isSendMessage, responseCallbackPreserved,
176 sourceExtensionId, targetExtensionId); 177 sourceExtensionId, targetExtensionId);
177 } 178 }
178 }; 179 };
179 // In case the extension never invokes the responseCallback, and also 180 // 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 181 // 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 182 // so by attaching to the garbage collection of the responseCallback
182 // using some native hackery. 183 // using some native hackery.
183 messagingNatives.BindToGC(responseCallback, function() { 184 messagingNatives.BindToGC(responseCallback, function() {
184 if (port) { 185 if (port) {
185 port.destroy_(); 186 privates(port).impl.destroy_();
186 port = null; 187 port = null;
187 } 188 }
188 }); 189 });
189 var rv = requestEvent.dispatch(request, sender, responseCallback); 190 var rv = requestEvent.dispatch(request, sender, responseCallback);
190 if (isSendMessage) { 191 if (isSendMessage) {
191 responseCallbackPreserved = 192 responseCallbackPreserved =
192 rv && rv.results && $Array.indexOf(rv.results, true) > -1; 193 rv && rv.results && $Array.indexOf(rv.results, true) > -1;
193 if (!responseCallbackPreserved && port) { 194 if (!responseCallbackPreserved && port) {
194 // If they didn't access the response callback, they're not 195 // If they didn't access the response callback, they're not
195 // going to send a response, so clean up the port immediately. 196 // going to send a response, so clean up the port immediately.
196 port.destroy_(); 197 privates(port).impl.destroy_();
197 port = null; 198 port = null;
198 } 199 }
199 } 200 }
200 } 201 }
201 202
202 port.onDestroy_ = function() { 203 privates(port).impl.onDestroy_ = function() {
203 port.onMessage.removeListener(messageListener); 204 port.onMessage.removeListener(messageListener);
204 }; 205 };
205 port.onMessage.addListener(messageListener); 206 port.onMessage.addListener(messageListener);
206 207
207 var eventName = isSendMessage ? "runtime.onMessage" : "extension.onRequest"; 208 var eventName = isSendMessage ? "runtime.onMessage" : "extension.onRequest";
208 if (isExternal) 209 if (isExternal)
209 eventName += "External"; 210 eventName += "External";
210 logActivity.LogEvent(targetExtensionId, 211 logActivity.LogEvent(targetExtensionId,
211 eventName, 212 eventName,
212 [sourceExtensionId, sourceUrl]); 213 [sourceExtensionId, sourceUrl]);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 function dispatchOnDisconnect(portId, errorMessage) { 282 function dispatchOnDisconnect(portId, errorMessage) {
282 var port = ports[portId]; 283 var port = ports[portId];
283 if (port) { 284 if (port) {
284 // Update the renderer's port bookkeeping, without notifying the browser. 285 // Update the renderer's port bookkeeping, without notifying the browser.
285 messagingNatives.CloseChannel(portId, false); 286 messagingNatives.CloseChannel(portId, false);
286 if (errorMessage) 287 if (errorMessage)
287 lastError.set('Port', errorMessage, null, chrome); 288 lastError.set('Port', errorMessage, null, chrome);
288 try { 289 try {
289 port.onDisconnect.dispatch(port); 290 port.onDisconnect.dispatch(port);
290 } finally { 291 } finally {
291 port.destroy_(); 292 privates(port).impl.destroy_();
292 lastError.clear(chrome); 293 lastError.clear(chrome);
293 } 294 }
294 } 295 }
295 }; 296 };
296 297
297 // Called by native code when a message has been sent to the given port. 298 // Called by native code when a message has been sent to the given port.
298 function dispatchOnMessage(msg, portId) { 299 function dispatchOnMessage(msg, portId) {
299 var port = ports[portId]; 300 var port = ports[portId];
300 if (port) { 301 if (port) {
301 if (msg) 302 if (msg)
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 } 336 }
336 337
337 function messageListener(response) { 338 function messageListener(response) {
338 try { 339 try {
339 responseCallback(response); 340 responseCallback(response);
340 } finally { 341 } finally {
341 port.disconnect(); 342 port.disconnect();
342 } 343 }
343 } 344 }
344 345
345 port.onDestroy_ = function() { 346 privates(port).impl.onDestroy_ = function() {
346 port.onDisconnect.removeListener(disconnectListener); 347 port.onDisconnect.removeListener(disconnectListener);
347 port.onMessage.removeListener(messageListener); 348 port.onMessage.removeListener(messageListener);
348 }; 349 };
349 port.onDisconnect.addListener(disconnectListener); 350 port.onDisconnect.addListener(disconnectListener);
350 port.onMessage.addListener(messageListener); 351 port.onMessage.addListener(messageListener);
351 }; 352 };
352 353
353 function sendMessageUpdateArguments(functionName, hasOptionsArgument) { 354 function sendMessageUpdateArguments(functionName, hasOptionsArgument) {
354 // skip functionName and hasOptionsArgument 355 // skip functionName and hasOptionsArgument
355 var args = $Array.slice(arguments, 2); 356 var args = $Array.slice(arguments, 2);
356 var alignedArgs = messagingUtils.alignSendMessageArguments(args, 357 var alignedArgs = messagingUtils.alignSendMessageArguments(args,
357 hasOptionsArgument); 358 hasOptionsArgument);
358 if (!alignedArgs) 359 if (!alignedArgs)
359 throw new Error('Invalid arguments to ' + functionName + '.'); 360 throw new Error('Invalid arguments to ' + functionName + '.');
360 return alignedArgs; 361 return alignedArgs;
361 } 362 }
362 363
364 var Port = utils.expose(PortImpl, [
365 'disconnect',
366 'postMessage'
367 ],
368 [
369 'name',
370 'onDisconnect',
371 'onMessage'
372 ]);
373
363 exports.kRequestChannel = kRequestChannel; 374 exports.kRequestChannel = kRequestChannel;
364 exports.kMessageChannel = kMessageChannel; 375 exports.kMessageChannel = kMessageChannel;
365 exports.kNativeMessageChannel = kNativeMessageChannel; 376 exports.kNativeMessageChannel = kNativeMessageChannel;
366 exports.Port = Port; 377 exports.Port = Port;
367 exports.createPort = createPort; 378 exports.createPort = createPort;
368 exports.sendMessageImpl = sendMessageImpl; 379 exports.sendMessageImpl = sendMessageImpl;
369 exports.sendMessageUpdateArguments = sendMessageUpdateArguments; 380 exports.sendMessageUpdateArguments = sendMessageUpdateArguments;
370 381
371 // For C++ code to call. 382 // For C++ code to call.
372 exports.hasPort = hasPort; 383 exports.hasPort = hasPort;
373 exports.dispatchOnConnect = dispatchOnConnect; 384 exports.dispatchOnConnect = dispatchOnConnect;
374 exports.dispatchOnDisconnect = dispatchOnDisconnect; 385 exports.dispatchOnDisconnect = dispatchOnDisconnect;
375 exports.dispatchOnMessage = dispatchOnMessage; 386 exports.dispatchOnMessage = dispatchOnMessage;
OLDNEW
« no previous file with comments | « no previous file | chrome/renderer/resources/extensions/utils.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698