mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-11-09 21:00:42 +02:00
- Add `envType` to BaseContext. - Pass an explicit envType to all `registerSchemaAPI` invocations. - The factories passed to `registerSchemaAPI` will be split up later, so that content scripts (`content_child`) and addon pages can share common implementations. - The factories that implement the addon API will also be split up, to separate code running in the main process (`addon_parent`) from code running in a child process (`addon_child`). - Remove the use of a hardcoded list of `namespaces` from ProxyContext. Now `envType` is used to specify whether an API should be activated. MozReview-Commit-ID: Jiff8HIwG92 --HG-- extra : rebase_source : 946a3c0009a4e3223c2d10044b3099a94c845394
160 lines
4.3 KiB
JavaScript
160 lines
4.3 KiB
JavaScript
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
|
/* vim: set sts=2 sw=2 et tw=80: */
|
|
"use strict";
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "EventEmitter",
|
|
"resource://devtools/shared/event-emitter.js");
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
|
"resource://gre/modules/Services.jsm");
|
|
|
|
// Import the android PageActions module.
|
|
XPCOMUtils.defineLazyModuleGetter(this, "PageActions",
|
|
"resource://gre/modules/PageActions.jsm");
|
|
|
|
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
|
|
|
|
var {
|
|
IconDetails,
|
|
SingletonEventManager,
|
|
} = ExtensionUtils;
|
|
|
|
// WeakMap[Extension -> PageAction]
|
|
var pageActionMap = new WeakMap();
|
|
|
|
function PageAction(options, extension) {
|
|
this.id = null;
|
|
|
|
this.extension = extension;
|
|
this.icons = IconDetails.normalize({path: options.default_icon}, extension);
|
|
|
|
this.popupUrl = options.default_popup;
|
|
|
|
this.options = {
|
|
title: options.default_title || extension.name,
|
|
id: extension.id,
|
|
clickCallback: () => {
|
|
if (this.popupUrl) {
|
|
let win = Services.wm.getMostRecentWindow("navigator:browser");
|
|
win.BrowserApp.addTab(this.popupUrl, {
|
|
selected: true,
|
|
parentId: win.BrowserApp.selectedTab.id,
|
|
});
|
|
} else {
|
|
this.emit("click");
|
|
}
|
|
},
|
|
};
|
|
|
|
this.shouldShow = false;
|
|
|
|
EventEmitter.decorate(this);
|
|
}
|
|
|
|
PageAction.prototype = {
|
|
show(tabId, context) {
|
|
if (this.id) {
|
|
return Promise.resolve();
|
|
}
|
|
|
|
if (this.options.icon) {
|
|
this.id = PageActions.add(this.options);
|
|
return Promise.resolve();
|
|
}
|
|
|
|
this.shouldShow = true;
|
|
|
|
let {icon} = IconDetails.getPreferredIcon(this.icons, this.extension,
|
|
18 * context.contentWindow.devicePixelRatio);
|
|
|
|
let browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
|
return IconDetails.convertImageURLToDataURL(icon, context, browserWindow).then(dataURI => {
|
|
if (this.shouldShow) {
|
|
this.options.icon = dataURI;
|
|
this.id = PageActions.add(this.options);
|
|
}
|
|
}).catch(() => {
|
|
return Promise.reject({
|
|
message: "Failed to load PageAction icon",
|
|
});
|
|
});
|
|
},
|
|
|
|
hide(tabId) {
|
|
this.shouldShow = false;
|
|
if (this.id) {
|
|
PageActions.remove(this.id);
|
|
this.id = null;
|
|
}
|
|
},
|
|
|
|
setPopup(tab, url) {
|
|
// TODO: Only set the popup for the specified tab once we have Tabs API support.
|
|
this.popupUrl = url;
|
|
},
|
|
|
|
getPopup(tab) {
|
|
// TODO: Only return the popup for the specified tab once we have Tabs API support.
|
|
return this.popupUrl;
|
|
},
|
|
|
|
shutdown() {
|
|
this.hide();
|
|
},
|
|
};
|
|
|
|
/* eslint-disable mozilla/balanced-listeners */
|
|
extensions.on("manifest_page_action", (type, directive, extension, manifest) => {
|
|
let pageAction = new PageAction(manifest.page_action, extension);
|
|
pageActionMap.set(extension, pageAction);
|
|
});
|
|
|
|
extensions.on("shutdown", (type, extension) => {
|
|
if (pageActionMap.has(extension)) {
|
|
pageActionMap.get(extension).shutdown();
|
|
pageActionMap.delete(extension);
|
|
}
|
|
});
|
|
/* eslint-enable mozilla/balanced-listeners */
|
|
|
|
extensions.registerSchemaAPI("pageAction", "addon_parent", context => {
|
|
let {extension} = context;
|
|
return {
|
|
pageAction: {
|
|
onClicked: new SingletonEventManager(context, "pageAction.onClicked", fire => {
|
|
let listener = (event) => {
|
|
fire();
|
|
};
|
|
pageActionMap.get(extension).on("click", listener);
|
|
return () => {
|
|
pageActionMap.get(extension).off("click", listener);
|
|
};
|
|
}).api(),
|
|
|
|
show(tabId) {
|
|
return pageActionMap.get(extension)
|
|
.show(tabId, context)
|
|
.then(() => {});
|
|
},
|
|
|
|
hide(tabId) {
|
|
pageActionMap.get(extension).hide(tabId);
|
|
return Promise.resolve();
|
|
},
|
|
|
|
setPopup(details) {
|
|
// TODO: Use the Tabs API to get the tab from details.tabId.
|
|
let tab = null;
|
|
let url = details.popup && context.uri.resolve(details.popup);
|
|
pageActionMap.get(extension).setPopup(tab, url);
|
|
},
|
|
|
|
getPopup(details) {
|
|
// TODO: Use the Tabs API to get the tab from details.tabId.
|
|
let tab = null;
|
|
let popup = pageActionMap.get(extension).getPopup(tab);
|
|
return Promise.resolve(popup);
|
|
},
|
|
},
|
|
};
|
|
});
|