Bug 1350522: Part 7 - Merge pageAction/browserAction/sidebarAction/commands helper classes into API instances. r=aswan
MozReview-Commit-ID: 6aRQ1uybAmg
This commit is contained in:
@@ -48,10 +48,15 @@ XPCOMUtils.defineLazyGetter(this, "browserAreas", () => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// Responsible for the browser_action section of the manifest as well
|
this.browserAction = class extends ExtensionAPI {
|
||||||
// as the associated popup.
|
static for(extension) {
|
||||||
function BrowserAction(options, extension) {
|
return browserActionMap.get(extension);
|
||||||
this.extension = extension;
|
}
|
||||||
|
|
||||||
|
onManifestEntry(entryName) {
|
||||||
|
let {extension} = this;
|
||||||
|
|
||||||
|
let options = extension.manifest.browser_action;
|
||||||
|
|
||||||
let widgetId = makeWidgetId(extension.id);
|
let widgetId = makeWidgetId(extension.id);
|
||||||
this.id = `${widgetId}-browser-action`;
|
this.id = `${widgetId}-browser-action`;
|
||||||
@@ -83,9 +88,20 @@ function BrowserAction(options, extension) {
|
|||||||
extension);
|
extension);
|
||||||
|
|
||||||
EventEmitter.decorate(this);
|
EventEmitter.decorate(this);
|
||||||
}
|
|
||||||
|
|
||||||
BrowserAction.prototype = {
|
this.build();
|
||||||
|
browserActionMap.set(extension, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
onShutdown(reason) {
|
||||||
|
browserActionMap.delete(this.extension);
|
||||||
|
|
||||||
|
this.tabContext.shutdown();
|
||||||
|
CustomizableUI.destroyWidget(this.id);
|
||||||
|
|
||||||
|
this.clearPopup();
|
||||||
|
}
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
let widget = CustomizableUI.createWidget({
|
let widget = CustomizableUI.createWidget({
|
||||||
id: this.id,
|
id: this.id,
|
||||||
@@ -160,7 +176,7 @@ BrowserAction.prototype = {
|
|||||||
(evt, tab) => { this.updateWindow(tab.ownerGlobal); });
|
(evt, tab) => { this.updateWindow(tab.ownerGlobal); });
|
||||||
|
|
||||||
this.widget = widget;
|
this.widget = widget;
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggers this browser action for the given window, with the same effects as
|
* Triggers this browser action for the given window, with the same effects as
|
||||||
@@ -168,8 +184,10 @@ BrowserAction.prototype = {
|
|||||||
*
|
*
|
||||||
* This has no effect if the browser action is disabled for, or not
|
* This has no effect if the browser action is disabled for, or not
|
||||||
* present in, the given window.
|
* present in, the given window.
|
||||||
|
*
|
||||||
|
* @param {Window} window
|
||||||
*/
|
*/
|
||||||
triggerAction: Task.async(function* (window) {
|
async triggerAction(window) {
|
||||||
let popup = ViewPopup.for(this.extension, window);
|
let popup = ViewPopup.for(this.extension, window);
|
||||||
if (popup) {
|
if (popup) {
|
||||||
popup.closePopup();
|
popup.closePopup();
|
||||||
@@ -188,7 +206,7 @@ BrowserAction.prototype = {
|
|||||||
// Google Chrome onClicked extension API.
|
// Google Chrome onClicked extension API.
|
||||||
if (this.getProperty(tab, "popup")) {
|
if (this.getProperty(tab, "popup")) {
|
||||||
if (this.widget.areaType == CustomizableUI.TYPE_MENU_PANEL) {
|
if (this.widget.areaType == CustomizableUI.TYPE_MENU_PANEL) {
|
||||||
yield window.PanelUI.show();
|
await window.PanelUI.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
let event = new window.CustomEvent("command", {bubbles: true, cancelable: true});
|
let event = new window.CustomEvent("command", {bubbles: true, cancelable: true});
|
||||||
@@ -196,7 +214,7 @@ BrowserAction.prototype = {
|
|||||||
} else {
|
} else {
|
||||||
this.emit("click");
|
this.emit("click");
|
||||||
}
|
}
|
||||||
}),
|
}
|
||||||
|
|
||||||
handleEvent(event) {
|
handleEvent(event) {
|
||||||
let button = event.target;
|
let button = event.target;
|
||||||
@@ -279,7 +297,7 @@ BrowserAction.prototype = {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a potentially pre-loaded popup for the given URL in the given
|
* Returns a potentially pre-loaded popup for the given URL in the given
|
||||||
@@ -315,7 +333,7 @@ BrowserAction.prototype = {
|
|||||||
|
|
||||||
let fixedWidth = this.widget.areaType == CustomizableUI.TYPE_MENU_PANEL;
|
let fixedWidth = this.widget.areaType == CustomizableUI.TYPE_MENU_PANEL;
|
||||||
return new ViewPopup(this.extension, window, popupURL, this.browserStyle, fixedWidth, blockParser);
|
return new ViewPopup(this.extension, window, popupURL, this.browserStyle, fixedWidth, blockParser);
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears any pending pre-loaded popup and related timeouts.
|
* Clears any pending pre-loaded popup and related timeouts.
|
||||||
@@ -330,7 +348,7 @@ BrowserAction.prototype = {
|
|||||||
this.pendingPopup = null;
|
this.pendingPopup = null;
|
||||||
}
|
}
|
||||||
this.tabToRevokeDuringClearPopup = null;
|
this.tabToRevokeDuringClearPopup = null;
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears any pending timeouts to clear stale, pre-loaded popups.
|
* Clears any pending timeouts to clear stale, pre-loaded popups.
|
||||||
@@ -344,7 +362,7 @@ BrowserAction.prototype = {
|
|||||||
clearTimeout(this.pendingPopupTimeout);
|
clearTimeout(this.pendingPopupTimeout);
|
||||||
this.pendingPopupTimeout = null;
|
this.pendingPopupTimeout = null;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
// Update the toolbar button |node| with the tab context data
|
// Update the toolbar button |node| with the tab context data
|
||||||
// in |tabData|.
|
// in |tabData|.
|
||||||
@@ -402,7 +420,7 @@ BrowserAction.prototype = {
|
|||||||
--webextension-toolbar-image: url("${IconDetails.escapeUrl(icon)}");
|
--webextension-toolbar-image: url("${IconDetails.escapeUrl(icon)}");
|
||||||
--webextension-toolbar-image-2x: url("${getIcon(baseSize * 2)}");
|
--webextension-toolbar-image-2x: url("${getIcon(baseSize * 2)}");
|
||||||
`);
|
`);
|
||||||
},
|
}
|
||||||
|
|
||||||
// Update the toolbar button for a given window.
|
// Update the toolbar button for a given window.
|
||||||
updateWindow(window) {
|
updateWindow(window) {
|
||||||
@@ -411,7 +429,7 @@ BrowserAction.prototype = {
|
|||||||
let tab = window.gBrowser.selectedTab;
|
let tab = window.gBrowser.selectedTab;
|
||||||
this.updateButton(widget.node, this.tabContext.get(tab));
|
this.updateButton(widget.node, this.tabContext.get(tab));
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
// Update the toolbar button when the extension changes the icon,
|
// Update the toolbar button when the extension changes the icon,
|
||||||
// title, badge, etc. If it only changes a parameter for a single
|
// title, badge, etc. If it only changes a parameter for a single
|
||||||
@@ -426,7 +444,7 @@ BrowserAction.prototype = {
|
|||||||
this.updateWindow(window);
|
this.updateWindow(window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
// tab is allowed to be null.
|
// tab is allowed to be null.
|
||||||
// prop should be one of "icon", "title", "badgeText", "popup", or "badgeBackgroundColor".
|
// prop should be one of "icon", "title", "badgeText", "popup", or "badgeBackgroundColor".
|
||||||
@@ -440,7 +458,7 @@ BrowserAction.prototype = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.updateOnChange(tab);
|
this.updateOnChange(tab);
|
||||||
},
|
}
|
||||||
|
|
||||||
// tab is allowed to be null.
|
// tab is allowed to be null.
|
||||||
// prop should be one of "title", "badgeText", "popup", or "badgeBackgroundColor".
|
// prop should be one of "title", "badgeText", "popup", or "badgeBackgroundColor".
|
||||||
@@ -449,44 +467,13 @@ BrowserAction.prototype = {
|
|||||||
return this.defaults[prop];
|
return this.defaults[prop];
|
||||||
}
|
}
|
||||||
return this.tabContext.get(tab)[prop];
|
return this.tabContext.get(tab)[prop];
|
||||||
},
|
|
||||||
|
|
||||||
shutdown() {
|
|
||||||
this.tabContext.shutdown();
|
|
||||||
CustomizableUI.destroyWidget(this.id);
|
|
||||||
|
|
||||||
this.clearPopup();
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
BrowserAction.for = (extension) => {
|
|
||||||
return browserActionMap.get(extension);
|
|
||||||
};
|
|
||||||
|
|
||||||
global.browserActionFor = BrowserAction.for;
|
|
||||||
|
|
||||||
this.browserAction = class extends ExtensionAPI {
|
|
||||||
onManifestEntry(entryName) {
|
|
||||||
let {extension} = this;
|
|
||||||
let {manifest} = extension;
|
|
||||||
|
|
||||||
this.browserAction = new BrowserAction(manifest.browser_action, extension);
|
|
||||||
this.browserAction.build();
|
|
||||||
browserActionMap.set(extension, this.browserAction);
|
|
||||||
}
|
|
||||||
|
|
||||||
onShutdown(reason) {
|
|
||||||
let {extension} = this;
|
|
||||||
|
|
||||||
browserActionMap.delete(extension);
|
|
||||||
this.browserAction.shutdown();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getAPI(context) {
|
getAPI(context) {
|
||||||
let {extension} = context;
|
let {extension} = context;
|
||||||
let {tabManager} = extension;
|
let {tabManager} = extension;
|
||||||
|
|
||||||
let {browserAction} = this;
|
let browserAction = this;
|
||||||
|
|
||||||
function getTab(tabId) {
|
function getTab(tabId) {
|
||||||
if (tabId !== null) {
|
if (tabId !== null) {
|
||||||
@@ -594,3 +581,6 @@ this.browserAction = class extends ExtensionAPI {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
global.browserActionFor = this.browserAction.for;
|
||||||
|
|
||||||
|
|||||||
@@ -9,22 +9,27 @@ var {
|
|||||||
|
|
||||||
var XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
var XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||||
|
|
||||||
function CommandList(manifest, extension) {
|
this.commands = class extends ExtensionAPI {
|
||||||
this.extension = extension;
|
onManifestEntry(entryName) {
|
||||||
|
let {extension} = this;
|
||||||
|
|
||||||
this.id = makeWidgetId(extension.id);
|
this.id = makeWidgetId(extension.id);
|
||||||
this.windowOpenListener = null;
|
this.windowOpenListener = null;
|
||||||
|
|
||||||
// Map[{String} commandName -> {Object} commandProperties]
|
// Map[{String} commandName -> {Object} commandProperties]
|
||||||
this.commands = this.loadCommandsFromManifest(manifest);
|
this.commands = this.loadCommandsFromManifest(this.extension.manifest);
|
||||||
|
|
||||||
// WeakMap[Window -> <xul:keyset>]
|
// WeakMap[Window -> <xul:keyset>]
|
||||||
this.keysetsMap = new WeakMap();
|
this.keysetsMap = new WeakMap();
|
||||||
|
|
||||||
this.register();
|
this.register();
|
||||||
EventEmitter.decorate(this);
|
EventEmitter.decorate(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onShutdown(reason) {
|
||||||
|
this.unregister();
|
||||||
|
}
|
||||||
|
|
||||||
CommandList.prototype = {
|
|
||||||
/**
|
/**
|
||||||
* Registers the commands to all open windows and to any which
|
* Registers the commands to all open windows and to any which
|
||||||
* are later created.
|
* are later created.
|
||||||
@@ -41,7 +46,7 @@ CommandList.prototype = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
windowTracker.addOpenListener(this.windowOpenListener);
|
windowTracker.addOpenListener(this.windowOpenListener);
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregisters the commands from all open windows and stops commands
|
* Unregisters the commands from all open windows and stops commands
|
||||||
@@ -55,7 +60,7 @@ CommandList.prototype = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
windowTracker.removeOpenListener(this.windowOpenListener);
|
windowTracker.removeOpenListener(this.windowOpenListener);
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a Map from commands for each command in the manifest.commands object.
|
* Creates a Map from commands for each command in the manifest.commands object.
|
||||||
@@ -78,7 +83,7 @@ CommandList.prototype = {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
return commands;
|
return commands;
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers the commands to a document.
|
* Registers the commands to a document.
|
||||||
@@ -96,7 +101,7 @@ CommandList.prototype = {
|
|||||||
});
|
});
|
||||||
doc.documentElement.appendChild(keyset);
|
doc.documentElement.appendChild(keyset);
|
||||||
this.keysetsMap.set(window, keyset);
|
this.keysetsMap.set(window, keyset);
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds a XUL Key element and attaches an onCommand listener which
|
* Builds a XUL Key element and attaches an onCommand listener which
|
||||||
@@ -141,7 +146,7 @@ CommandList.prototype = {
|
|||||||
/* eslint-enable mozilla/balanced-listeners */
|
/* eslint-enable mozilla/balanced-listeners */
|
||||||
|
|
||||||
return keyElement;
|
return keyElement;
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds a XUL Key element from the provided shortcut.
|
* Builds a XUL Key element from the provided shortcut.
|
||||||
@@ -171,7 +176,7 @@ CommandList.prototype = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return keyElement;
|
return keyElement;
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines the corresponding XUL keycode from the given chrome key.
|
* Determines the corresponding XUL keycode from the given chrome key.
|
||||||
@@ -188,7 +193,7 @@ CommandList.prototype = {
|
|||||||
*/
|
*/
|
||||||
getKeycodeAttribute(chromeKey) {
|
getKeycodeAttribute(chromeKey) {
|
||||||
return `VK${chromeKey.replace(/([A-Z])/g, "_$&").toUpperCase()}`;
|
return `VK${chromeKey.replace(/([A-Z])/g, "_$&").toUpperCase()}`;
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines the corresponding XUL modifiers from the chrome modifiers.
|
* Determines the corresponding XUL modifiers from the chrome modifiers.
|
||||||
@@ -214,26 +219,13 @@ CommandList.prototype = {
|
|||||||
return Array.from(chromeModifiers, modifier => {
|
return Array.from(chromeModifiers, modifier => {
|
||||||
return modifiersMap[modifier];
|
return modifiersMap[modifier];
|
||||||
}).join(" ");
|
}).join(" ");
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
this.commands = class extends ExtensionAPI {
|
|
||||||
onManifestEntry(entryName) {
|
|
||||||
let {extension} = this;
|
|
||||||
let {manifest} = extension;
|
|
||||||
|
|
||||||
this.commandList = new CommandList(manifest, extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
onShutdown(reason) {
|
|
||||||
this.commandList.unregister();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getAPI(context) {
|
getAPI(context) {
|
||||||
return {
|
return {
|
||||||
commands: {
|
commands: {
|
||||||
getAll: () => {
|
getAll: () => {
|
||||||
let commands = this.commandList.commands;
|
let commands = this.commands;
|
||||||
return Promise.resolve(Array.from(commands, ([name, command]) => {
|
return Promise.resolve(Array.from(commands, ([name, command]) => {
|
||||||
return ({
|
return ({
|
||||||
name,
|
name,
|
||||||
@@ -246,9 +238,9 @@ this.commands = class extends ExtensionAPI {
|
|||||||
let listener = (eventName, commandName) => {
|
let listener = (eventName, commandName) => {
|
||||||
fire.async(commandName);
|
fire.async(commandName);
|
||||||
};
|
};
|
||||||
this.commandList.on("command", listener);
|
this.on("command", listener);
|
||||||
return () => {
|
return () => {
|
||||||
this.commandList.off("command", listener);
|
this.off("command", listener);
|
||||||
};
|
};
|
||||||
}).api(),
|
}).api(),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -15,10 +15,15 @@ var {
|
|||||||
// WeakMap[Extension -> PageAction]
|
// WeakMap[Extension -> PageAction]
|
||||||
let pageActionMap = new WeakMap();
|
let pageActionMap = new WeakMap();
|
||||||
|
|
||||||
// Handles URL bar icons, including the |page_action| manifest entry
|
this.pageAction = class extends ExtensionAPI {
|
||||||
// and associated API.
|
static for(extension) {
|
||||||
function PageAction(options, extension) {
|
return pageActionMap.get(extension);
|
||||||
this.extension = extension;
|
}
|
||||||
|
|
||||||
|
onManifestEntry(entryName) {
|
||||||
|
let {extension} = this;
|
||||||
|
let options = extension.manifest.page_action;
|
||||||
|
|
||||||
this.id = makeWidgetId(extension.id) + "-page-action";
|
this.id = makeWidgetId(extension.id) + "-page-action";
|
||||||
|
|
||||||
this.tabManager = extension.tabManager;
|
this.tabManager = extension.tabManager;
|
||||||
@@ -45,14 +50,28 @@ function PageAction(options, extension) {
|
|||||||
this.buttons = new WeakMap();
|
this.buttons = new WeakMap();
|
||||||
|
|
||||||
EventEmitter.decorate(this);
|
EventEmitter.decorate(this);
|
||||||
}
|
|
||||||
|
|
||||||
PageAction.prototype = {
|
pageActionMap.set(extension, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
onShutdown(reason) {
|
||||||
|
pageActionMap.delete(this.extension);
|
||||||
|
|
||||||
|
this.tabContext.shutdown();
|
||||||
|
|
||||||
|
for (let window of windowTracker.browserWindows()) {
|
||||||
|
if (this.buttons.has(window)) {
|
||||||
|
this.buttons.get(window).remove();
|
||||||
|
window.document.removeEventListener("popupshowing", this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Returns the value of the property |prop| for the given tab, where
|
// Returns the value of the property |prop| for the given tab, where
|
||||||
// |prop| is one of "show", "title", "icon", "popup".
|
// |prop| is one of "show", "title", "icon", "popup".
|
||||||
getProperty(tab, prop) {
|
getProperty(tab, prop) {
|
||||||
return this.tabContext.get(tab)[prop];
|
return this.tabContext.get(tab)[prop];
|
||||||
},
|
}
|
||||||
|
|
||||||
// Sets the value of the property |prop| for the given tab to the
|
// Sets the value of the property |prop| for the given tab to the
|
||||||
// given value, symmetrically to |getProperty|.
|
// given value, symmetrically to |getProperty|.
|
||||||
@@ -69,7 +88,7 @@ PageAction.prototype = {
|
|||||||
if (tab.selected) {
|
if (tab.selected) {
|
||||||
this.updateButton(tab.ownerGlobal);
|
this.updateButton(tab.ownerGlobal);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
// Updates the page action button in the given window to reflect the
|
// Updates the page action button in the given window to reflect the
|
||||||
// properties of the currently selected tab:
|
// properties of the currently selected tab:
|
||||||
@@ -111,7 +130,7 @@ PageAction.prototype = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
button.hidden = !tabData.show;
|
button.hidden = !tabData.show;
|
||||||
},
|
}
|
||||||
|
|
||||||
// Create an |image| node and add it to the |urlbar-icons|
|
// Create an |image| node and add it to the |urlbar-icons|
|
||||||
// container in the given window.
|
// container in the given window.
|
||||||
@@ -128,7 +147,7 @@ PageAction.prototype = {
|
|||||||
document.getElementById("urlbar-icons").appendChild(button);
|
document.getElementById("urlbar-icons").appendChild(button);
|
||||||
|
|
||||||
return button;
|
return button;
|
||||||
},
|
}
|
||||||
|
|
||||||
// Returns the page action button for the given window, creating it if
|
// Returns the page action button for the given window, creating it if
|
||||||
// it doesn't already exist.
|
// it doesn't already exist.
|
||||||
@@ -139,7 +158,7 @@ PageAction.prototype = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this.buttons.get(window);
|
return this.buttons.get(window);
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggers this page action for the given window, with the same effects as
|
* Triggers this page action for the given window, with the same effects as
|
||||||
@@ -154,7 +173,7 @@ PageAction.prototype = {
|
|||||||
if (pageAction.getProperty(window.gBrowser.selectedTab, "show")) {
|
if (pageAction.getProperty(window.gBrowser.selectedTab, "show")) {
|
||||||
pageAction.handleClick(window);
|
pageAction.handleClick(window);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
handleEvent(event) {
|
handleEvent(event) {
|
||||||
const window = event.target.ownerGlobal;
|
const window = event.target.ownerGlobal;
|
||||||
@@ -179,7 +198,7 @@ PageAction.prototype = {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
// Handles a click event on the page action button for the given
|
// Handles a click event on the page action button for the given
|
||||||
// window.
|
// window.
|
||||||
@@ -202,52 +221,20 @@ PageAction.prototype = {
|
|||||||
} else {
|
} else {
|
||||||
this.emit("click", tab);
|
this.emit("click", tab);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
handleLocationChange(eventType, tab, fromBrowse) {
|
handleLocationChange(eventType, tab, fromBrowse) {
|
||||||
if (fromBrowse) {
|
if (fromBrowse) {
|
||||||
this.tabContext.clear(tab);
|
this.tabContext.clear(tab);
|
||||||
}
|
}
|
||||||
this.updateButton(tab.ownerGlobal);
|
this.updateButton(tab.ownerGlobal);
|
||||||
},
|
|
||||||
|
|
||||||
shutdown() {
|
|
||||||
this.tabContext.shutdown();
|
|
||||||
|
|
||||||
for (let window of windowTracker.browserWindows()) {
|
|
||||||
if (this.buttons.has(window)) {
|
|
||||||
this.buttons.get(window).remove();
|
|
||||||
window.document.removeEventListener("popupshowing", this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
PageAction.for = extension => {
|
|
||||||
return pageActionMap.get(extension);
|
|
||||||
};
|
|
||||||
|
|
||||||
global.pageActionFor = PageAction.for;
|
|
||||||
|
|
||||||
this.pageAction = class extends ExtensionAPI {
|
|
||||||
onManifestEntry(entryName) {
|
|
||||||
let {extension} = this;
|
|
||||||
let {manifest} = extension;
|
|
||||||
|
|
||||||
this.pageAction = new PageAction(manifest.page_action, extension);
|
|
||||||
pageActionMap.set(extension, this.pageAction);
|
|
||||||
}
|
|
||||||
|
|
||||||
onShutdown(reason) {
|
|
||||||
pageActionMap.delete(this.extension);
|
|
||||||
this.pageAction.shutdown();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getAPI(context) {
|
getAPI(context) {
|
||||||
let {extension} = context;
|
let {extension} = context;
|
||||||
|
|
||||||
const {tabManager} = extension;
|
const {tabManager} = extension;
|
||||||
const {pageAction} = this;
|
const pageAction = this;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
pageAction: {
|
pageAction: {
|
||||||
@@ -315,3 +302,5 @@ this.pageAction = class extends ExtensionAPI {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
global.pageActionFor = this.pageAction.for;
|
||||||
|
|||||||
@@ -27,9 +27,17 @@ const sidebarURL = "chrome://browser/content/webext-panels.xul";
|
|||||||
* Responsible for the sidebar_action section of the manifest as well
|
* Responsible for the sidebar_action section of the manifest as well
|
||||||
* as the associated sidebar browser.
|
* as the associated sidebar browser.
|
||||||
*/
|
*/
|
||||||
class SidebarAction {
|
this.sidebarAction = class extends ExtensionAPI {
|
||||||
constructor(options, extension) {
|
static for(extension) {
|
||||||
this.extension = extension;
|
return sidebarActionMap.get(extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
onManifestEntry(entryName) {
|
||||||
|
let {extension} = this;
|
||||||
|
|
||||||
|
extension.once("ready", this.onReady.bind(this));
|
||||||
|
|
||||||
|
let options = extension.manifest.sidebar_action;
|
||||||
|
|
||||||
// Add the extension to the sidebar menu. The sidebar widget will copy
|
// Add the extension to the sidebar menu. The sidebar widget will copy
|
||||||
// from that when it is viewed, so we shouldn't need to update that.
|
// from that when it is viewed, so we shouldn't need to update that.
|
||||||
@@ -52,6 +60,40 @@ class SidebarAction {
|
|||||||
this.createMenuItem(window, this.defaults);
|
this.createMenuItem(window, this.defaults);
|
||||||
};
|
};
|
||||||
windowTracker.addOpenListener(this.windowOpenListener);
|
windowTracker.addOpenListener(this.windowOpenListener);
|
||||||
|
|
||||||
|
sidebarActionMap.set(extension, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
onReady() {
|
||||||
|
this.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
onShutdown(reason) {
|
||||||
|
sidebarActionMap.delete(this.this);
|
||||||
|
|
||||||
|
this.tabContext.shutdown();
|
||||||
|
|
||||||
|
// Don't remove everything on app shutdown so session restore can handle
|
||||||
|
// restoring open sidebars.
|
||||||
|
if (reason === "APP_SHUTDOWN") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let window of windowTracker.browserWindows()) {
|
||||||
|
let {document, SidebarUI} = window;
|
||||||
|
if (SidebarUI.currentID === this.id) {
|
||||||
|
SidebarUI.hide();
|
||||||
|
}
|
||||||
|
let menu = document.getElementById(this.menuId);
|
||||||
|
if (menu) {
|
||||||
|
menu.remove();
|
||||||
|
}
|
||||||
|
let broadcaster = document.getElementById(this.id);
|
||||||
|
if (broadcaster) {
|
||||||
|
broadcaster.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
windowTracker.removeOpenListener(this.windowOpenListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
@@ -238,25 +280,6 @@ class SidebarAction {
|
|||||||
return this.tabContext.get(nativeTab)[prop];
|
return this.tabContext.get(nativeTab)[prop];
|
||||||
}
|
}
|
||||||
|
|
||||||
shutdown() {
|
|
||||||
this.tabContext.shutdown();
|
|
||||||
for (let window of windowTracker.browserWindows()) {
|
|
||||||
let {document, SidebarUI} = window;
|
|
||||||
if (SidebarUI.currentID === this.id) {
|
|
||||||
SidebarUI.hide();
|
|
||||||
}
|
|
||||||
let menu = document.getElementById(this.menuId);
|
|
||||||
if (menu) {
|
|
||||||
menu.remove();
|
|
||||||
}
|
|
||||||
let broadcaster = document.getElementById(this.id);
|
|
||||||
if (broadcaster) {
|
|
||||||
broadcaster.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
windowTracker.removeOpenListener(this.windowOpenListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggers this sidebar action for the given window, with the same effects as
|
* Triggers this sidebar action for the given window, with the same effects as
|
||||||
* if it were toggled via menu or toolbarbutton by a user.
|
* if it were toggled via menu or toolbarbutton by a user.
|
||||||
@@ -269,44 +292,10 @@ class SidebarAction {
|
|||||||
SidebarUI.toggle(this.id);
|
SidebarUI.toggle(this.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
SidebarAction.for = (extension) => {
|
|
||||||
return sidebarActionMap.get(extension);
|
|
||||||
};
|
|
||||||
|
|
||||||
global.sidebarActionFor = SidebarAction.for;
|
|
||||||
|
|
||||||
/* eslint-disable mozilla/balanced-listeners */
|
|
||||||
extensions.on("ready", (type, extension) => {
|
|
||||||
// We build sidebars during ready to ensure the background scripts are ready.
|
|
||||||
if (sidebarActionMap.has(extension)) {
|
|
||||||
sidebarActionMap.get(extension).build();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
/* eslint-enable mozilla/balanced-listeners */
|
|
||||||
|
|
||||||
this.sidebarAction = class extends ExtensionAPI {
|
|
||||||
onManifestEntry(entryName) {
|
|
||||||
let {extension} = this;
|
|
||||||
let {manifest} = extension;
|
|
||||||
|
|
||||||
this.sidebarAction = new SidebarAction(manifest.sidebar_action, extension);
|
|
||||||
sidebarActionMap.set(extension, this.sidebarAction);
|
|
||||||
}
|
|
||||||
|
|
||||||
onShutdown(reason) {
|
|
||||||
// Don't remove everything on app shutdown so session restore can handle
|
|
||||||
// restoring open sidebars.
|
|
||||||
if (reason !== "APP_SHUTDOWN") {
|
|
||||||
this.sidebarAction.shutdown();
|
|
||||||
}
|
|
||||||
sidebarActionMap.delete(this.extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
getAPI(context) {
|
getAPI(context) {
|
||||||
let {extension} = context;
|
let {extension} = context;
|
||||||
const {sidebarAction} = this;
|
const sidebarAction = this;
|
||||||
|
|
||||||
function getTab(tabId) {
|
function getTab(tabId) {
|
||||||
if (tabId !== null) {
|
if (tabId !== null) {
|
||||||
@@ -368,3 +357,5 @@ this.sidebarAction = class extends ExtensionAPI {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
global.sidebarActionFor = this.sidebarAction.for;
|
||||||
|
|||||||
@@ -966,6 +966,7 @@ this.Extension = class extends ExtensionData {
|
|||||||
await this.runManifest(this.manifest);
|
await this.runManifest(this.manifest);
|
||||||
|
|
||||||
Management.emit("ready", this);
|
Management.emit("ready", this);
|
||||||
|
this.emit("ready");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
dump(`Extension error: ${e.message} ${e.filename || e.fileName}:${e.lineNumber} :: ${e.stack || new Error().stack}\n`);
|
dump(`Extension error: ${e.message} ${e.filename || e.fileName}:${e.lineNumber} :: ${e.stack || new Error().stack}\n`);
|
||||||
Cu.reportError(e);
|
Cu.reportError(e);
|
||||||
|
|||||||
Reference in New Issue
Block a user