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

Unified Diff: trunk/src/extensions/renderer/resources/messaging.js

Issue 309413002: Revert 274558 "Move some extensions renderer resources to extens..." (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: Created 6 years, 7 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 side-by-side diff with in-line comments
Download patch
Index: trunk/src/extensions/renderer/resources/messaging.js
===================================================================
--- trunk/src/extensions/renderer/resources/messaging.js (revision 274563)
+++ trunk/src/extensions/renderer/resources/messaging.js (working copy)
@@ -1,386 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This contains unprivileged javascript APIs for extensions and apps. It
-// can be loaded by any extension-related context, such as content scripts or
-// background pages. See user_script_slave.cc for script that is loaded by
-// content scripts only.
-
- // TODO(kalman): factor requiring chrome out of here.
- var chrome = requireNative('chrome').GetChrome();
- var Event = require('event_bindings').Event;
- var lastError = require('lastError');
- var logActivity = requireNative('activityLogger');
- var messagingNatives = requireNative('messaging_natives');
- var processNatives = requireNative('process');
- var unloadEvent = require('unload_event');
- var utils = require('utils');
- var messagingUtils = require('messaging_utils');
-
- // The reserved channel name for the sendRequest/send(Native)Message APIs.
- // Note: sendRequest is deprecated.
- 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 unloadEvent listeners. Keep track of these to free the
- // unloadEvent listeners when ports are closed.
- var portReleasers = {};
-
- // Change even to odd and vice versa, to get the other side of a given
- // channel.
- function getOppositePortId(portId) { return portId ^ 1; }
-
- // Port object. Represents a connection to another script context through
- // which messages can be passed.
- function PortImpl(portId, opt_name) {
- this.portId_ = portId;
- this.name = opt_name;
-
- var portSchema = {name: 'port', $ref: 'runtime.Port'};
- var options = {unmanaged: true};
- this.onDisconnect = new Event(null, [portSchema], options);
- this.onMessage = new Event(
- null,
- [{name: 'message', type: 'any', optional: true}, portSchema],
- options);
- this.onDestroy_ = null;
- }
-
- // 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;
- msg = $JSON.stringify(msg);
- if (msg === undefined) {
- // JSON.stringify can fail with unserializable objects. Log an error and
- // drop the message.
- //
- // TODO(kalman/mpcomplete): it would be better to do the same validation
- // here that we do for runtime.sendMessage (and variants), i.e. throw an
- // schema validation Error, but just maintain the old behaviour until
- // there's a good reason not to (http://crbug.com/263077).
- console.error('Illegal argument to Port.postMessage');
- return;
- }
- messagingNatives.PostMessage(this.portId_, msg);
- };
-
- // Disconnects the port from the other end.
- PortImpl.prototype.disconnect = function() {
- messagingNatives.CloseChannel(this.portId_, true);
- this.destroy_();
- };
-
- PortImpl.prototype.destroy_ = function() {
- var portId = this.portId_;
-
- if (this.onDestroy_)
- this.onDestroy_();
- privates(this.onDisconnect).impl.destroy_();
- privates(this.onMessage).impl.destroy_();
-
- messagingNatives.PortRelease(portId);
- unloadEvent.removeListener(portReleasers[portId]);
-
- delete ports[portId];
- delete portReleasers[portId];
- };
-
- // 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.
- 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.
- function createPort(portId, opt_name) {
- if (ports[portId])
- throw new Error("Port '" + portId + "' already exists.");
- var port = new Port(portId, opt_name);
- ports[portId] = port;
- portReleasers[portId] = $Function.bind(messagingNatives.PortRelease,
- this,
- portId);
- unloadEvent.addListener(portReleasers[portId]);
- messagingNatives.PortAddRef(portId);
- return port;
- };
-
- // Helper function for dispatchOnRequest.
- function handleSendRequestError(isSendMessage,
- responseCallbackPreserved,
- sourceExtensionId,
- targetExtensionId,
- sourceUrl) {
- var errorMsg = [];
- var eventName = isSendMessage ? "runtime.onMessage" : "extension.onRequest";
- if (isSendMessage && !responseCallbackPreserved) {
- $Array.push(errorMsg,
- "The chrome." + eventName + " listener must return true if you " +
- "want to send a response after the listener returns");
- } else {
- $Array.push(errorMsg,
- "Cannot send a response more than once per chrome." + eventName +
- " listener per document");
- }
- $Array.push(errorMsg, "(message was sent by extension" + sourceExtensionId);
- if (sourceExtensionId != "" && sourceExtensionId != targetExtensionId)
- $Array.push(errorMsg, "for extension " + targetExtensionId);
- if (sourceUrl != "")
- $Array.push(errorMsg, "for URL " + sourceUrl);
- lastError.set(eventName, errorMsg.join(" ") + ").", null, chrome);
- }
-
- // Helper function for dispatchOnConnect
- function dispatchOnRequest(portId, channelName, sender,
- sourceExtensionId, targetExtensionId, sourceUrl,
- isExternal) {
- var isSendMessage = channelName == kMessageChannel;
- var requestEvent = null;
- if (isSendMessage) {
- if (chrome.runtime) {
- requestEvent = isExternal ? chrome.runtime.onMessageExternal
- : chrome.runtime.onMessage;
- }
- } else {
- if (chrome.extension) {
- requestEvent = isExternal ? chrome.extension.onRequestExternal
- : chrome.extension.onRequest;
- }
- }
- if (!requestEvent)
- return false;
- if (!requestEvent.hasListeners())
- return false;
- var port = createPort(portId, channelName);
-
- function messageListener(request) {
- var responseCallbackPreserved = false;
- var responseCallback = function(response) {
- if (port) {
- port.postMessage(response);
- privates(port).impl.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.
- messagingNatives.BindToGC(responseCallback, function() {
- if (port) {
- privates(port).impl.destroy_();
- port = null;
- }
- });
- var rv = requestEvent.dispatch(request, sender, responseCallback);
- if (isSendMessage) {
- responseCallbackPreserved =
- rv && rv.results && $Array.indexOf(rv.results, 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.
- privates(port).impl.destroy_();
- port = null;
- }
- }
- }
-
- privates(port).impl.onDestroy_ = function() {
- port.onMessage.removeListener(messageListener);
- };
- port.onMessage.addListener(messageListener);
-
- var eventName = isSendMessage ? "runtime.onMessage" : "extension.onRequest";
- if (isExternal)
- eventName += "External";
- logActivity.LogEvent(targetExtensionId,
- eventName,
- [sourceExtensionId, sourceUrl]);
- return true;
- }
-
- // Called by native code when a channel has been opened to this context.
- function dispatchOnConnect(portId,
- channelName,
- sourceTab,
- sourceExtensionId,
- targetExtensionId,
- sourceUrl,
- tlsChannelId) {
- // 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
-
- // Determine whether this is coming from another extension, so we can use
- // the right event.
- var isExternal = sourceExtensionId != extensionId;
-
- var sender = {};
- if (sourceExtensionId != '')
- sender.id = sourceExtensionId;
- if (sourceUrl)
- sender.url = sourceUrl;
- if (sourceTab)
- sender.tab = sourceTab;
- if (tlsChannelId !== undefined)
- sender.tlsChannelId = tlsChannelId;
-
- // Special case for sendRequest/onRequest and sendMessage/onMessage.
- if (channelName == kRequestChannel || channelName == kMessageChannel) {
- return dispatchOnRequest(portId, channelName, sender,
- sourceExtensionId, targetExtensionId, sourceUrl,
- isExternal);
- }
-
- var connectEvent = null;
- if (chrome.runtime) {
- connectEvent = isExternal ? chrome.runtime.onConnectExternal
- : chrome.runtime.onConnect;
- }
- 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.
- function dispatchOnDisconnect(portId, errorMessage) {
- var port = ports[portId];
- if (port) {
- // Update the renderer's port bookkeeping, without notifying the browser.
- messagingNatives.CloseChannel(portId, false);
- if (errorMessage)
- lastError.set('Port', errorMessage, null, chrome);
- try {
- port.onDisconnect.dispatch(port);
- } finally {
- privates(port).impl.destroy_();
- lastError.clear(chrome);
- }
- }
- };
-
- // Called by native code when a message has been sent to the given port.
- function dispatchOnMessage(msg, portId) {
- var port = ports[portId];
- if (port) {
- if (msg)
- msg = $JSON.parse(msg);
- port.onMessage.dispatch(msg, port);
- }
- };
-
- // Shared implementation used by tabs.sendMessage and runtime.sendMessage.
- function sendMessageImpl(port, request, responseCallback) {
- if (port.name != kNativeMessageChannel)
- port.postMessage(request);
-
- 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
- // a response.
- port.disconnect();
- return;
- }
-
- // Ensure the callback exists for the older sendRequest API.
- if (!responseCallback)
- responseCallback = function() {};
-
- // Note: make sure to manually remove the onMessage/onDisconnect listeners
- // that we added before destroying the Port, a workaround to a bug in Port
- // where any onMessage/onDisconnect listeners added but not removed will
- // be leaked when the Port is destroyed.
- // http://crbug.com/320723 tracks a sustainable fix.
-
- function disconnectListener() {
- // For onDisconnects, we only notify the callback if there was an error.
- if (chrome.runtime && chrome.runtime.lastError)
- responseCallback();
- }
-
- function messageListener(response) {
- try {
- responseCallback(response);
- } finally {
- port.disconnect();
- }
- }
-
- privates(port).impl.onDestroy_ = function() {
- port.onDisconnect.removeListener(disconnectListener);
- port.onMessage.removeListener(messageListener);
- };
- port.onDisconnect.addListener(disconnectListener);
- port.onMessage.addListener(messageListener);
- };
-
- function sendMessageUpdateArguments(functionName, hasOptionsArgument) {
- // skip functionName and hasOptionsArgument
- var args = $Array.slice(arguments, 2);
- var alignedArgs = messagingUtils.alignSendMessageArguments(args,
- hasOptionsArgument);
- if (!alignedArgs)
- throw new Error('Invalid arguments to ' + functionName + '.');
- return alignedArgs;
- }
-
-var Port = utils.expose('Port', PortImpl, { functions: [
- 'disconnect',
- 'postMessage'
- ],
- properties: [
- 'name',
- 'onDisconnect',
- 'onMessage'
- ] });
-
-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;
« no previous file with comments | « trunk/src/extensions/renderer/resources/last_error.js ('k') | trunk/src/extensions/renderer/resources/messaging_utils.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698