Bug 1298979 - Fix LegacyExtensionContext r=aswan

LegacyExtensionContext should inherit from BaseContext instead of
ExtensionContext, because the latter is moving to a separate process.

Remove the optional `url` parameter because the context is not a frame.
`url` is assigned to `sender.url`, which should only be set for frames.
The sender is only used in extension messaging when `runtime.connect` or
`runtime.sendMessage` are used (where `sender.url` is visible at the
receiver). Since legacy extensions don't send messages, there is no
point at all in setting the `url` value.

MozReview-Commit-ID: FJboNC2SZh0

--HG--
extra : rebase_source : bbfd6670355a3b9985b03b5a203f3b0a19cdfde4
This commit is contained in:
Rob Wu 2016-09-06 01:48:58 -07:00
Родитель 3df8d2e80e
Коммит dc0a47c098
4 изменённых файлов: 45 добавлений и 43 удалений

Просмотреть файл

@ -104,7 +104,7 @@ add_task(function* test_legacy_extension_context_contentscript_connection() {
});
});
is(legacyContext.type, "legacy_extension",
is(legacyContext.envType, "legacy_extension",
"LegacyExtensionContext instance has the expected type");
ok(legacyContext.api, "Got the API object");

Просмотреть файл

@ -4,7 +4,7 @@
"use strict";
this.EXPORTED_SYMBOLS = ["Extension", "ExtensionData", "ExtensionContext"];
this.EXPORTED_SYMBOLS = ["Extension", "ExtensionData"];
/* globals Extension ExtensionData */
@ -272,6 +272,8 @@ let ProxyMessenger = {
// Listen on the parent process message manager because `runtime.connect`
// and `runtime.sendMessage` requests must be delivered to all frames in an
// addon process (by the API contract).
// And legacy addons are not associated with a frame, so that is another
// reason for having a parent process manager here.
let messageManagers = [Services.mm, pipmm];
MessageChannel.addListener(messageManagers, "Extension:Connect", this);

Просмотреть файл

@ -17,43 +17,33 @@ const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
// Lazy imports.
XPCOMUtils.defineLazyModuleGetter(this, "Extension",
"resource://gre/modules/Extension.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ExtensionContext",
"resource://gre/modules/Extension.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
var {
BaseContext,
Messenger,
} = ExtensionUtils;
/**
* Instances created from this class provide to a legacy extension
* a simple API to exchange messages with a webextension.
*/
var LegacyExtensionContext = class extends ExtensionContext {
var LegacyExtensionContext = class extends BaseContext {
/**
* Create a new LegacyExtensionContext given a target Extension instance and an optional
* url (which can be used to recognize the messages of container context).
* Create a new LegacyExtensionContext given a target Extension instance.
*
* @param {Extension} targetExtension
* The webextension instance associated with this context. This will be the
* instance of the newly created embedded webextension when this class is
* used through the EmbeddedWebExtensionsUtils.
* @param {Object} [optionalParams]
* An object with the following properties:
* @param {string} [optionalParams.url]
* An URL to mark the messages sent from this context
* (e.g. EmbeddedWebExtension sets it to the base url of the container addon).
*/
constructor(targetExtension, optionalParams = {}) {
let {url} = optionalParams;
super(targetExtension, {
contentWindow: null,
uri: NetUtil.newURI(url || "about:blank"),
type: "legacy_extension",
});
constructor(targetExtension) {
super("legacy_extension", targetExtension);
// Legacy Extensions (xul overlays, bootstrap restartless and Addon SDK)
// runs with a systemPrincipal.
@ -70,6 +60,13 @@ var LegacyExtensionContext = class extends ExtensionContext {
{value: cloneScope, enumerable: true, configurable: true, writable: true}
);
let sender = {id: targetExtension.uuid};
let filter = {extensionId: targetExtension.id};
// Legacy addons live in the main process. Messages from other addons are
// Messages from WebExtensions are sent to the main process and forwarded via
// the parent process manager to the legacy extension.
this.messenger = new Messenger(this, [Services.cpmm], sender, filter);
this.api = {
browser: {
runtime: {
@ -92,13 +89,6 @@ var LegacyExtensionContext = class extends ExtensionContext {
Cu.nukeSandbox(this.cloneScope);
this.cloneScope = null;
}
/**
* The LegacyExtensionContext is not a visible context.
*/
get externallyVisible() {
return false;
}
};
var EmbeddedExtensionManager;
@ -167,9 +157,7 @@ class EmbeddedExtension {
// to subscribe its message listeners (which are supposed to be able to
// receive any message that the embedded part can try to send to it
// during its startup).
this.context = new LegacyExtensionContext(this.extension, {
url: this.resourceURI.resolve("/"),
});
this.context = new LegacyExtensionContext(this.extension);
// Destroy the LegacyExtensionContext cloneScope when
// the embedded webextensions is unloaded.

Просмотреть файл

@ -18,7 +18,7 @@ const {LegacyExtensionContext} = Cu.import("resource://gre/modules/LegacyExtensi
* shutting down
*/
add_task(function* test_legacy_extension_context() {
function backgroundScript() {
function background() {
let bgURL = window.location.href;
let extensionInfo = {
@ -29,6 +29,8 @@ add_task(function* test_legacy_extension_context() {
browser.test.sendMessage("webextension-ready", extensionInfo);
let port;
browser.test.onMessage.addListener(msg => {
if (msg == "do-send-message") {
browser.runtime.sendMessage("webextension -> legacy_extension message").then(reply => {
@ -37,19 +39,21 @@ add_task(function* test_legacy_extension_context() {
browser.test.sendMessage("got-reply-message");
});
} else if (msg == "do-connect") {
let port = browser.runtime.connect();
port = browser.runtime.connect();
port.onMessage.addListener(msg => {
browser.test.assertEq("legacy_extension -> webextension port message", msg,
"Got the expected message from the LegacyExtensionContext");
port.postMessage("webextension -> legacy_extension port message");
});
} else if (msg == "do-disconnect") {
port.disconnect();
}
});
}
let extensionData = {
background: "new " + backgroundScript,
background,
};
let extension = Extension.generate(extensionData);
@ -65,15 +69,23 @@ add_task(function* test_legacy_extension_context() {
});
});
// Connect to the target extension as an external context
// using the given custom sender info.
let legacyContext;
extension.on("startup", function onStartup() {
extension.off("startup", onStartup);
legacyContext = new LegacyExtensionContext(extension);
extension.callOnClose({
close: () => legacyContext.unload(),
});
});
yield extension.startup();
let extensionInfo = yield waitForExtensionInfo;
// Connect to the target extension.id as an external context
// using the given custom sender info.
let legacyContext = new LegacyExtensionContext(extension);
equal(legacyContext.type, "legacy_extension",
equal(legacyContext.envType, "legacy_extension",
"LegacyExtensionContext instance has the expected type");
ok(legacyContext.api, "Got the expected API object");
@ -146,11 +158,11 @@ add_task(function* test_legacy_extension_context() {
port.onDisconnect.addListener(resolve);
});
extension.shutdown();
extension.testMessage("do-disconnect");
yield waitForDisconnect;
do_print("Got the disconnect event on unload");
legacyContext.shutdown();
yield extension.shutdown();
});