| Index: chrome/renderer/resources/extensions/miscellaneous_bindings.js
|
| diff --git a/chrome/renderer/resources/extensions/miscellaneous_bindings.js b/chrome/renderer/resources/extensions/miscellaneous_bindings.js
|
| index 9a4937d1860c7bb0d79961549097117a031c11fa..b3258b375191b29a7289c19e64a573fad4300243 100644
|
| --- a/chrome/renderer/resources/extensions/miscellaneous_bindings.js
|
| +++ b/chrome/renderer/resources/extensions/miscellaneous_bindings.js
|
| @@ -7,36 +7,25 @@
|
| // background pages. See user_script_slave.cc for script that is loaded by
|
| // content scripts only.
|
|
|
| - require('json_schema');
|
| - var json = require('json');
|
| - var lastError = require('lastError');
|
| - var miscNatives = requireNative('miscellaneous_bindings');
|
| var chrome = requireNative('chrome').GetChrome();
|
| - var CloseChannel = miscNatives.CloseChannel;
|
| - var PortAddRef = miscNatives.PortAddRef;
|
| - var PortRelease = miscNatives.PortRelease;
|
| - var PostMessage = miscNatives.PostMessage;
|
| - var BindToGC = miscNatives.BindToGC;
|
| -
|
| - var chromeHidden = requireNative('chrome_hidden').GetChromeHidden();
|
| -
|
| - var processNatives = requireNative('process');
|
| - var manifestVersion = processNatives.GetManifestVersion();
|
| - var extensionId = processNatives.GetExtensionId();
|
| -
|
| + var Event = require('event_bindings').Event;
|
| + var lastError = require('lastError');
|
| var logActivity = requireNative('activityLogger');
|
| + var miscNatives = requireNative('miscellaneous_bindings_natives');
|
| + var onUnload = require('on_unload');
|
| + var processNatives = requireNative('process');
|
|
|
| - // The reserved channel name for the sendRequest/sendMessage APIs.
|
| + // The reserved channel name for the sendRequest/send(Native)Message APIs.
|
| // Note: sendRequest is deprecated.
|
| - chromeHidden.kRequestChannel = "chrome.extension.sendRequest";
|
| - chromeHidden.kMessageChannel = "chrome.runtime.sendMessage";
|
| - chromeHidden.kNativeMessageChannel = "chrome.runtime.sendNativeMessage";
|
| + var kRequestChannel = "chrome.extension.sendRequest";
|
| + var kMessageChannel = "chrome.runtime.sendMessage";
|
| + var kNativeMessageChannel = "chrome.runtime.sendNativeMessage";
|
|
|
| // Map of port IDs to port object.
|
| var ports = {};
|
|
|
| - // Map of port IDs to chromeHidden.onUnload listeners. Keep track of these
|
| - // to free the onUnload listeners when ports are closed.
|
| + // Map of port IDs to onUnload listeners. Keep track of these to free the
|
| + // onUnload listeners when ports are closed.
|
| var portReleasers = {};
|
|
|
| // Change even to odd and vice versa, to get the other side of a given
|
| @@ -45,62 +34,55 @@
|
|
|
| // Port object. Represents a connection to another script context through
|
| // which messages can be passed.
|
| - function PortImpl(portId, opt_name) {
|
| + function Port(portId, opt_name) {
|
| this.portId_ = portId;
|
| this.name = opt_name;
|
| - this.onDisconnect = new chrome.Event();
|
| - this.onMessage = new chrome.Event();
|
| + this.onDisconnect = new Event();
|
| + this.onMessage = new Event();
|
| }
|
|
|
| // Sends a message asynchronously to the context on the other end of this
|
| // port.
|
| - PortImpl.prototype.postMessage = function(msg) {
|
| - // json.stringify doesn't support a root object which is undefined.
|
| - if (msg === undefined)
|
| - msg = null;
|
| - PostMessage(this.portId_, json.stringify(msg));
|
| + Port.prototype.postMessage = function(msg) {
|
| + miscNatives.PostMessage(this.portId_, msg);
|
| };
|
|
|
| // Disconnects the port from the other end.
|
| - PortImpl.prototype.disconnect = function() {
|
| - CloseChannel(this.portId_, true);
|
| + Port.prototype.disconnect = function() {
|
| + miscNatives.CloseChannel(this.portId_, true);
|
| this.destroy_();
|
| };
|
|
|
| - PortImpl.prototype.destroy_ = function() {
|
| + Port.prototype.destroy_ = function() {
|
| var portId = this.portId_;
|
|
|
| this.onDisconnect.destroy_();
|
| this.onMessage.destroy_();
|
|
|
| - PortRelease(portId);
|
| - chromeHidden.onUnload.removeListener(portReleasers[portId]);
|
| + miscNatives.PortRelease(portId);
|
| + onUnload.removeListener(portReleasers[portId]);
|
|
|
| delete ports[portId];
|
| delete portReleasers[portId];
|
| };
|
|
|
| - chromeHidden.Port = {};
|
| -
|
| // Returns true if the specified port id is in this context. This is used by
|
| // the C++ to avoid creating the javascript message for all the contexts that
|
| // don't care about a particular message.
|
| - chromeHidden.Port.hasPort = function(portId) {
|
| + function hasPort(portId) {
|
| return portId in ports;
|
| };
|
|
|
| // Hidden port creation function. We don't want to expose an API that lets
|
| // people add arbitrary port IDs to the port list.
|
| - chromeHidden.Port.createPort = function(portId, opt_name) {
|
| - if (ports[portId]) {
|
| + function createPort(portId, opt_name) {
|
| + if (ports[portId])
|
| throw new Error("Port '" + portId + "' already exists.");
|
| - }
|
| - var port = new PortImpl(portId, opt_name);
|
| + var port = new Port(portId, opt_name);
|
| ports[portId] = port;
|
| - portReleasers[portId] = PortRelease.bind(this, portId);
|
| - chromeHidden.onUnload.addListener(portReleasers[portId]);
|
| -
|
| - PortAddRef(portId);
|
| + portReleasers[portId] = miscNatives.PortRelease.bind(this, portId);
|
| + onUnload.addListener(portReleasers[portId]);
|
| + miscNatives.PortAddRef(portId);
|
| return port;
|
| };
|
|
|
| @@ -133,78 +115,79 @@
|
| function dispatchOnRequest(portId, channelName, sender,
|
| sourceExtensionId, targetExtensionId, sourceUrl,
|
| isExternal) {
|
| - var isSendMessage = channelName == chromeHidden.kMessageChannel;
|
| + var isSendMessage = channelName == kMessageChannel;
|
| var requestEvent = (isSendMessage ?
|
| (isExternal ?
|
| chrome.runtime.onMessageExternal : chrome.runtime.onMessage) :
|
| (isExternal ?
|
| chrome.extension.onRequestExternal : chrome.extension.onRequest));
|
| - if (requestEvent.hasListeners()) {
|
| - var port = chromeHidden.Port.createPort(portId, channelName);
|
| - port.onMessage.addListener(function(request) {
|
| - var responseCallbackPreserved = false;
|
| - var responseCallback = function(response) {
|
| - if (port) {
|
| - port.postMessage(response);
|
| - port.destroy_();
|
| - port = null;
|
| - } else {
|
| - // We nulled out port when sending the response, and now the page
|
| - // is trying to send another response for the same request.
|
| - handleSendRequestError(isSendMessage, responseCallbackPreserved,
|
| - sourceExtensionId, targetExtensionId);
|
| - }
|
| - };
|
| - // In case the extension never invokes the responseCallback, and also
|
| - // doesn't keep a reference to it, we need to clean up the port. Do
|
| - // so by attaching to the garbage collection of the responseCallback
|
| - // using some native hackery.
|
| - BindToGC(responseCallback, function() {
|
| - if (port) {
|
| - port.destroy_();
|
| - port = null;
|
| - }
|
| - });
|
| - if (!isSendMessage) {
|
| - requestEvent.dispatch(request, sender, responseCallback);
|
| + if (!requestEvent.hasListeners())
|
| + return false;
|
| + var port = createPort(portId, channelName);
|
| + port.onMessage.addListener(function(request) {
|
| + var responseCallbackPreserved = false;
|
| + var responseCallback = function(response) {
|
| + if (port) {
|
| + port.postMessage(response);
|
| + port.destroy_();
|
| + port = null;
|
| } else {
|
| - var rv = requestEvent.dispatch(request, sender, responseCallback);
|
| - responseCallbackPreserved =
|
| - rv && rv.results && rv.results.indexOf(true) > -1;
|
| - if (!responseCallbackPreserved && port) {
|
| - // If they didn't access the response callback, they're not
|
| - // going to send a response, so clean up the port immediately.
|
| - port.destroy_();
|
| - port = null;
|
| - }
|
| + // We nulled out port when sending the response, and now the page
|
| + // is trying to send another response for the same request.
|
| + handleSendRequestError(isSendMessage, responseCallbackPreserved,
|
| + sourceExtensionId, targetExtensionId);
|
| + }
|
| + };
|
| + // In case the extension never invokes the responseCallback, and also
|
| + // doesn't keep a reference to it, we need to clean up the port. Do
|
| + // so by attaching to the garbage collection of the responseCallback
|
| + // using some native hackery.
|
| + miscNatives.BindToGC(responseCallback, function() {
|
| + if (port) {
|
| + port.destroy_();
|
| + port = null;
|
| }
|
| });
|
| - var eventName = (isSendMessage ?
|
| - (isExternal ?
|
| - "runtime.onMessageExternal" : "runtime.onMessage") :
|
| - (isExternal ?
|
| - "extension.onRequestExternal" : "extension.onRequest"));
|
| - logActivity.LogEvent(targetExtensionId,
|
| - eventName,
|
| - [sourceExtensionId, sourceUrl]);
|
| - return true;
|
| - }
|
| - return false;
|
| + if (!isSendMessage) {
|
| + requestEvent.dispatch(request, sender, responseCallback);
|
| + } else {
|
| + var rv = requestEvent.dispatch(request, sender, responseCallback);
|
| + responseCallbackPreserved =
|
| + rv && rv.results && rv.results.indexOf(true) > -1;
|
| + if (!responseCallbackPreserved && port) {
|
| + // If they didn't access the response callback, they're not
|
| + // going to send a response, so clean up the port immediately.
|
| + port.destroy_();
|
| + port = null;
|
| + }
|
| + }
|
| + });
|
| + var eventName = (isSendMessage ?
|
| + (isExternal ?
|
| + "runtime.onMessageExternal" : "runtime.onMessage") :
|
| + (isExternal ?
|
| + "extension.onRequestExternal" : "extension.onRequest"));
|
| + logActivity.LogEvent(targetExtensionId,
|
| + eventName,
|
| + [sourceExtensionId, sourceUrl]);
|
| + return true;
|
| }
|
|
|
| // Called by native code when a channel has been opened to this context.
|
| - chromeHidden.Port.dispatchOnConnect = function(portId,
|
| - channelName,
|
| - sourceTab,
|
| - sourceExtensionId,
|
| - targetExtensionId,
|
| - sourceUrl) {
|
| + function dispatchOnConnect(portId,
|
| + channelName,
|
| + sourceTab,
|
| + sourceExtensionId,
|
| + targetExtensionId,
|
| + sourceUrl) {
|
| // Only create a new Port if someone is actually listening for a connection.
|
| // In addition to being an optimization, this also fixes a bug where if 2
|
| // channels were opened to and from the same process, closing one would
|
| // close both.
|
| + var extensionId = processNatives.GetExtensionId();
|
| if (targetExtensionId != extensionId)
|
| return false; // not for us
|
| +
|
| if (ports[getOppositePortId(portId)])
|
| return false; // this channel was opened by us, so ignore it
|
|
|
| @@ -219,8 +202,7 @@
|
| sender.tab = sourceTab;
|
|
|
| // Special case for sendRequest/onRequest and sendMessage/onMessage.
|
| - if (channelName == chromeHidden.kRequestChannel ||
|
| - channelName == chromeHidden.kMessageChannel) {
|
| + if (channelName == kRequestChannel || channelName == kMessageChannel) {
|
| return dispatchOnRequest(portId, channelName, sender,
|
| sourceExtensionId, targetExtensionId, sourceUrl,
|
| isExternal);
|
| @@ -228,30 +210,31 @@
|
|
|
| var connectEvent = (isExternal ?
|
| chrome.runtime.onConnectExternal : chrome.runtime.onConnect);
|
| - if (connectEvent.hasListeners()) {
|
| - var port = chromeHidden.Port.createPort(portId, channelName);
|
| - port.sender = sender;
|
| - if (manifestVersion < 2)
|
| - port.tab = port.sender.tab;
|
| -
|
| - var eventName = (isExternal ?
|
| - "runtime.onConnectExternal" : "runtime.onConnect");
|
| - connectEvent.dispatch(port);
|
| - logActivity.LogEvent(targetExtensionId,
|
| - eventName,
|
| - [sourceExtensionId]);
|
| - return true;
|
| - }
|
| - return false;
|
| + if (!connectEvent)
|
| + return false;
|
| + if (!connectEvent.hasListeners())
|
| + return false;
|
| +
|
| + var port = createPort(portId, channelName);
|
| + port.sender = sender;
|
| + if (processNatives.manifestVersion < 2)
|
| + port.tab = port.sender.tab;
|
| +
|
| + var eventName = (isExternal ?
|
| + "runtime.onConnectExternal" : "runtime.onConnect");
|
| + connectEvent.dispatch(port);
|
| + logActivity.LogEvent(targetExtensionId,
|
| + eventName,
|
| + [sourceExtensionId]);
|
| + return true;
|
| };
|
|
|
| // Called by native code when a channel has been closed.
|
| - chromeHidden.Port.dispatchOnDisconnect = function(
|
| - portId, errorMessage) {
|
| + function dispatchOnDisconnect(portId, errorMessage) {
|
| var port = ports[portId];
|
| if (port) {
|
| // Update the renderer's port bookkeeping, without notifying the browser.
|
| - CloseChannel(portId, false);
|
| + miscNatives.CloseChannel(portId, false);
|
| if (errorMessage)
|
| lastError.set('Port', errorMessage, null, chrome);
|
| try {
|
| @@ -264,23 +247,18 @@
|
| };
|
|
|
| // Called by native code when a message has been sent to the given port.
|
| - chromeHidden.Port.dispatchOnMessage = function(msg, portId) {
|
| + function dispatchOnMessage(msg, portId) {
|
| var port = ports[portId];
|
| - if (port) {
|
| - if (msg) {
|
| - msg = json.parse(msg);
|
| - }
|
| + if (port)
|
| port.onMessage.dispatch(msg, port);
|
| - }
|
| };
|
|
|
| // Shared implementation used by tabs.sendMessage and runtime.sendMessage.
|
| - chromeHidden.Port.sendMessageImpl = function(port, request,
|
| - responseCallback) {
|
| - if (port.name != chromeHidden.kNativeMessageChannel)
|
| + function sendMessageImpl(port, request, responseCallback) {
|
| + if (port.name != kNativeMessageChannel)
|
| port.postMessage(request);
|
|
|
| - if (port.name == chromeHidden.kMessageChannel && !responseCallback) {
|
| + if (port.name == kMessageChannel && !responseCallback) {
|
| // TODO(mpcomplete): Do this for the old sendRequest API too, after
|
| // verifying it doesn't break anything.
|
| // Go ahead and disconnect immediately if the sender is not expecting
|
| @@ -294,7 +272,7 @@
|
| responseCallback = function() {};
|
|
|
| port.onDisconnect.addListener(function() {
|
| - // For onDisconnects, we only notify the callback if there was an error
|
| + // For onDisconnects, we only notify the callback if there was an error.
|
| try {
|
| if (chrome.runtime.lastError)
|
| responseCallback();
|
| @@ -338,4 +316,16 @@
|
| return [targetId, request, responseCallback];
|
| }
|
|
|
| +exports.kRequestChannel = kRequestChannel;
|
| +exports.kMessageChannel = kMessageChannel;
|
| +exports.kNativeMessageChannel = kNativeMessageChannel;
|
| +exports.Port = Port;
|
| +exports.createPort = createPort;
|
| +exports.sendMessageImpl = sendMessageImpl;
|
| exports.sendMessageUpdateArguments = sendMessageUpdateArguments;
|
| +
|
| +// For C++ code to call.
|
| +exports.hasPort = hasPort;
|
| +exports.dispatchOnConnect = dispatchOnConnect;
|
| +exports.dispatchOnDisconnect = dispatchOnDisconnect;
|
| +exports.dispatchOnMessage = dispatchOnMessage;
|
|
|