зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1450388 Part 1 Refactor EventManager r=kmag
As we add more behaviors to EventManager, the signature of the constructor is going to get really clumsy. Head that off by converting it to take a general parameters object. This introduces a compatibility problem for existing webextension experiments, put in a backward-compatibility shim for now. MozReview-Commit-ID: 72QDfiwRm5j --HG-- extra : rebase_source : 31c3fd561f373a5d75c4336de830aa5a2abfe797
This commit is contained in:
Родитель
efcb51ab74
Коммит
e71d1d5a82
|
@ -33,21 +33,25 @@ this.devtools_network = class extends ExtensionAPI {
|
|||
return {
|
||||
devtools: {
|
||||
network: {
|
||||
onRequestFinished: new EventManager(context, "devtools.network.onRequestFinished", fire => {
|
||||
let onFinished = (data) => {
|
||||
const loader = new ChildNetworkResponseLoader(context, data.requestId);
|
||||
const harEntry = {...data.harEntry, ...loader.api()};
|
||||
const result = Cu.cloneInto(harEntry, context.cloneScope, {
|
||||
cloneFunctions: true,
|
||||
});
|
||||
fire.asyncWithoutClone(result);
|
||||
};
|
||||
onRequestFinished: new EventManager({
|
||||
context,
|
||||
name: "devtools.network.onRequestFinished",
|
||||
register: fire => {
|
||||
let onFinished = (data) => {
|
||||
const loader = new ChildNetworkResponseLoader(context, data.requestId);
|
||||
const harEntry = {...data.harEntry, ...loader.api()};
|
||||
const result = Cu.cloneInto(harEntry, context.cloneScope, {
|
||||
cloneFunctions: true,
|
||||
});
|
||||
fire.asyncWithoutClone(result);
|
||||
};
|
||||
|
||||
let parent = context.childManager.getParentEvent("devtools.network.onRequestFinished");
|
||||
parent.addListener(onFinished);
|
||||
return () => {
|
||||
parent.removeListener(onFinished);
|
||||
};
|
||||
let parent = context.childManager.getParentEvent("devtools.network.onRequestFinished");
|
||||
parent.addListener(onFinished);
|
||||
return () => {
|
||||
parent.removeListener(onFinished);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
},
|
||||
},
|
||||
|
|
|
@ -94,8 +94,10 @@ class ChildDevToolsPanel extends ExtensionUtils.EventEmitter {
|
|||
|
||||
api() {
|
||||
return {
|
||||
onShown: new EventManager(
|
||||
this.context, "devtoolsPanel.onShown", fire => {
|
||||
onShown: new EventManager({
|
||||
context: this.context,
|
||||
name: "devtoolsPanel.onShown",
|
||||
register: fire => {
|
||||
const listener = (eventName, panelContentWindow) => {
|
||||
fire.asyncWithoutClone(panelContentWindow);
|
||||
};
|
||||
|
@ -103,10 +105,13 @@ class ChildDevToolsPanel extends ExtensionUtils.EventEmitter {
|
|||
return () => {
|
||||
this.off("shown", listener);
|
||||
};
|
||||
}).api(),
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onHidden: new EventManager(
|
||||
this.context, "devtoolsPanel.onHidden", fire => {
|
||||
onHidden: new EventManager({
|
||||
context: this.context,
|
||||
name: "devtoolsPanel.onHidden",
|
||||
register: fire => {
|
||||
const listener = () => {
|
||||
fire.async();
|
||||
};
|
||||
|
@ -114,7 +119,8 @@ class ChildDevToolsPanel extends ExtensionUtils.EventEmitter {
|
|||
return () => {
|
||||
this.off("hidden", listener);
|
||||
};
|
||||
}).api(),
|
||||
},
|
||||
}).api(),
|
||||
|
||||
// TODO(rpl): onSearch event and createStatusBarButton method
|
||||
};
|
||||
|
@ -189,8 +195,10 @@ class ChildDevToolsInspectorSidebar extends ExtensionUtils.EventEmitter {
|
|||
const {context, id} = this;
|
||||
|
||||
return {
|
||||
onShown: new EventManager(
|
||||
context, "devtoolsInspectorSidebar.onShown", fire => {
|
||||
onShown: new EventManager({
|
||||
context,
|
||||
name: "devtoolsInspectorSidebar.onShown",
|
||||
register: fire => {
|
||||
const listener = (eventName, panelContentWindow) => {
|
||||
fire.asyncWithoutClone(panelContentWindow);
|
||||
};
|
||||
|
@ -198,10 +206,13 @@ class ChildDevToolsInspectorSidebar extends ExtensionUtils.EventEmitter {
|
|||
return () => {
|
||||
this.off("shown", listener);
|
||||
};
|
||||
}).api(),
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onHidden: new EventManager(
|
||||
context, "devtoolsInspectorSidebar.onHidden", fire => {
|
||||
onHidden: new EventManager({
|
||||
context,
|
||||
name: "devtoolsInspectorSidebar.onHidden",
|
||||
register: fire => {
|
||||
const listener = () => {
|
||||
fire.async();
|
||||
};
|
||||
|
@ -209,7 +220,8 @@ class ChildDevToolsInspectorSidebar extends ExtensionUtils.EventEmitter {
|
|||
return () => {
|
||||
this.off("hidden", listener);
|
||||
};
|
||||
}).api(),
|
||||
},
|
||||
}).api(),
|
||||
|
||||
setObject(jsonObject, rootTitle) {
|
||||
return context.cloneScope.Promise.resolve().then(() => {
|
||||
|
@ -279,8 +291,10 @@ this.devtools_panels = class extends ExtensionAPI {
|
|||
get themeName() {
|
||||
return themeChangeObserver.themeName;
|
||||
},
|
||||
onThemeChanged: new EventManager(
|
||||
context, "devtools.panels.onThemeChanged", fire => {
|
||||
onThemeChanged: new EventManager({
|
||||
context,
|
||||
name: "devtools.panels.onThemeChanged",
|
||||
register: fire => {
|
||||
const listener = (eventName, themeName) => {
|
||||
fire.async(themeName);
|
||||
};
|
||||
|
@ -288,7 +302,8 @@ this.devtools_panels = class extends ExtensionAPI {
|
|||
return () => {
|
||||
themeChangeObserver.off("themeChanged", listener);
|
||||
};
|
||||
}).api(),
|
||||
},
|
||||
}).api(),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -159,17 +159,21 @@ this.menusInternal = class extends ExtensionAPI {
|
|||
return context.childManager.callParentAsyncFunction("menusInternal.removeAll", []);
|
||||
},
|
||||
|
||||
onClicked: new EventManager(context, "menus.onClicked", fire => {
|
||||
let listener = (info, tab) => {
|
||||
withHandlingUserInput(context.contentWindow,
|
||||
() => fire.sync(info, tab));
|
||||
};
|
||||
onClicked: new EventManager({
|
||||
context,
|
||||
name: "menus.onClicked",
|
||||
register: fire => {
|
||||
let listener = (info, tab) => {
|
||||
withHandlingUserInput(context.contentWindow,
|
||||
() => fire.sync(info, tab));
|
||||
};
|
||||
|
||||
let event = context.childManager.getParentEvent("menusInternal.onClicked");
|
||||
event.addListener(listener);
|
||||
return () => {
|
||||
event.removeListener(listener);
|
||||
};
|
||||
let event = context.childManager.getParentEvent("menusInternal.onClicked");
|
||||
event.addListener(listener);
|
||||
return () => {
|
||||
event.removeListener(listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -6,19 +6,23 @@ this.omnibox = class extends ExtensionAPI {
|
|||
getAPI(context) {
|
||||
return {
|
||||
omnibox: {
|
||||
onInputChanged: new EventManager(context, "omnibox.onInputChanged", fire => {
|
||||
let listener = (text, id) => {
|
||||
fire.asyncWithoutClone(text, suggestions => {
|
||||
context.childManager.callParentFunctionNoReturn("omnibox.addSuggestions", [
|
||||
id,
|
||||
suggestions,
|
||||
]);
|
||||
});
|
||||
};
|
||||
context.childManager.getParentEvent("omnibox.onInputChanged").addListener(listener);
|
||||
return () => {
|
||||
context.childManager.getParentEvent("omnibox.onInputChanged").removeListener(listener);
|
||||
};
|
||||
onInputChanged: new EventManager({
|
||||
context,
|
||||
name: "omnibox.onInputChanged",
|
||||
register: fire => {
|
||||
let listener = (text, id) => {
|
||||
fire.asyncWithoutClone(text, suggestions => {
|
||||
context.childManager.callParentFunctionNoReturn("omnibox.addSuggestions", [
|
||||
id,
|
||||
suggestions,
|
||||
]);
|
||||
});
|
||||
};
|
||||
context.childManager.getParentEvent("omnibox.onInputChanged").addListener(listener);
|
||||
return () => {
|
||||
context.childManager.getParentEvent("omnibox.onInputChanged").removeListener(listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -7,7 +7,6 @@ module.exports = {
|
|||
"Tab": true,
|
||||
"TabContext": true,
|
||||
"Window": true,
|
||||
"WindowEventManager": true,
|
||||
"actionContextMenu": true,
|
||||
"browserActionFor": true,
|
||||
"getContainerForCookieStoreId": true,
|
||||
|
|
|
@ -329,56 +329,72 @@ this.bookmarks = class extends ExtensionAPI {
|
|||
}
|
||||
},
|
||||
|
||||
onCreated: new EventManager(context, "bookmarks.onCreated", fire => {
|
||||
let listener = (event, bookmark) => {
|
||||
fire.sync(bookmark.id, bookmark);
|
||||
};
|
||||
onCreated: new EventManager({
|
||||
context,
|
||||
name: "bookmarks.onCreated",
|
||||
register: fire => {
|
||||
let listener = (event, bookmark) => {
|
||||
fire.sync(bookmark.id, bookmark);
|
||||
};
|
||||
|
||||
observer.on("created", listener);
|
||||
incrementListeners();
|
||||
return () => {
|
||||
observer.off("created", listener);
|
||||
decrementListeners();
|
||||
};
|
||||
observer.on("created", listener);
|
||||
incrementListeners();
|
||||
return () => {
|
||||
observer.off("created", listener);
|
||||
decrementListeners();
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onRemoved: new EventManager(context, "bookmarks.onRemoved", fire => {
|
||||
let listener = (event, data) => {
|
||||
fire.sync(data.guid, data.info);
|
||||
};
|
||||
onRemoved: new EventManager({
|
||||
context,
|
||||
name: "bookmarks.onRemoved",
|
||||
register: fire => {
|
||||
let listener = (event, data) => {
|
||||
fire.sync(data.guid, data.info);
|
||||
};
|
||||
|
||||
observer.on("removed", listener);
|
||||
incrementListeners();
|
||||
return () => {
|
||||
observer.off("removed", listener);
|
||||
decrementListeners();
|
||||
};
|
||||
observer.on("removed", listener);
|
||||
incrementListeners();
|
||||
return () => {
|
||||
observer.off("removed", listener);
|
||||
decrementListeners();
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onChanged: new EventManager(context, "bookmarks.onChanged", fire => {
|
||||
let listener = (event, data) => {
|
||||
fire.sync(data.guid, data.info);
|
||||
};
|
||||
onChanged: new EventManager({
|
||||
context,
|
||||
name: "bookmarks.onChanged",
|
||||
register: fire => {
|
||||
let listener = (event, data) => {
|
||||
fire.sync(data.guid, data.info);
|
||||
};
|
||||
|
||||
observer.on("changed", listener);
|
||||
incrementListeners();
|
||||
return () => {
|
||||
observer.off("changed", listener);
|
||||
decrementListeners();
|
||||
};
|
||||
observer.on("changed", listener);
|
||||
incrementListeners();
|
||||
return () => {
|
||||
observer.off("changed", listener);
|
||||
decrementListeners();
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onMoved: new EventManager(context, "bookmarks.onMoved", fire => {
|
||||
let listener = (event, data) => {
|
||||
fire.sync(data.guid, data.info);
|
||||
};
|
||||
onMoved: new EventManager({
|
||||
context,
|
||||
name: "bookmarks.onMoved",
|
||||
register: fire => {
|
||||
let listener = (event, data) => {
|
||||
fire.sync(data.guid, data.info);
|
||||
};
|
||||
|
||||
observer.on("moved", listener);
|
||||
incrementListeners();
|
||||
return () => {
|
||||
observer.off("moved", listener);
|
||||
decrementListeners();
|
||||
};
|
||||
observer.on("moved", listener);
|
||||
incrementListeners();
|
||||
return () => {
|
||||
observer.off("moved", listener);
|
||||
decrementListeners();
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -169,34 +169,6 @@ class WindowTracker extends WindowTrackerBase {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An event manager API provider which listens for a DOM event in any browser
|
||||
* window, and calls the given listener function whenever an event is received.
|
||||
* That listener function receives a `fire` object, which it can use to dispatch
|
||||
* events to the extension, and a DOM event object.
|
||||
*
|
||||
* @param {BaseContext} context
|
||||
* The extension context which the event manager belongs to.
|
||||
* @param {string} name
|
||||
* The API name of the event manager, e.g.,"runtime.onMessage".
|
||||
* @param {string} event
|
||||
* The name of the DOM event to listen for.
|
||||
* @param {function} listener
|
||||
* The listener function to call when a DOM event is received.
|
||||
*/
|
||||
global.WindowEventManager = class extends EventManager {
|
||||
constructor(context, name, event, listener) {
|
||||
super(context, name, fire => {
|
||||
let listener2 = listener.bind(null, fire);
|
||||
|
||||
windowTracker.addListener(event, listener2);
|
||||
return () => {
|
||||
windowTracker.removeListener(event, listener2);
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
class TabTracker extends TabTrackerBase {
|
||||
constructor() {
|
||||
super();
|
||||
|
|
|
@ -584,15 +584,20 @@ this.browserAction = class extends ExtensionAPI {
|
|||
|
||||
return {
|
||||
browserAction: {
|
||||
onClicked: new InputEventManager(context, "browserAction.onClicked", fire => {
|
||||
let listener = (event, browser) => {
|
||||
context.withPendingBrowser(browser, () =>
|
||||
fire.sync(tabManager.convert(tabTracker.activeTab)));
|
||||
};
|
||||
browserAction.on("click", listener);
|
||||
return () => {
|
||||
browserAction.off("click", listener);
|
||||
};
|
||||
onClicked: new EventManager({
|
||||
context,
|
||||
name: "browserAction.onClicked",
|
||||
inputHandling: true,
|
||||
register: fire => {
|
||||
let listener = (event, browser) => {
|
||||
context.withPendingBrowser(browser, () =>
|
||||
fire.sync(tabManager.convert(tabTracker.activeTab)));
|
||||
};
|
||||
browserAction.on("click", listener);
|
||||
return () => {
|
||||
browserAction.off("click", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
enable: function(tabId) {
|
||||
|
|
|
@ -364,14 +364,18 @@ this.commands = class extends ExtensionAPI {
|
|||
this.registerKeys(commands);
|
||||
}
|
||||
},
|
||||
onCommand: new EventManager(context, "commands.onCommand", fire => {
|
||||
let listener = (eventName, commandName) => {
|
||||
fire.async(commandName);
|
||||
};
|
||||
this.on("command", listener);
|
||||
return () => {
|
||||
this.off("command", listener);
|
||||
};
|
||||
onCommand: new EventManager({
|
||||
context,
|
||||
name: "commands.onCommand",
|
||||
register: fire => {
|
||||
let listener = (eventName, commandName) => {
|
||||
fire.async(commandName);
|
||||
};
|
||||
this.on("command", listener);
|
||||
return () => {
|
||||
this.off("command", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -15,37 +15,45 @@ this.devtools_network = class extends ExtensionAPI {
|
|||
return {
|
||||
devtools: {
|
||||
network: {
|
||||
onNavigated: new EventManager(context, "devtools.onNavigated", fire => {
|
||||
let listener = data => {
|
||||
fire.async(data.url);
|
||||
};
|
||||
onNavigated: new EventManager({
|
||||
context,
|
||||
name: "devtools.onNavigated",
|
||||
register: fire => {
|
||||
let listener = data => {
|
||||
fire.async(data.url);
|
||||
};
|
||||
|
||||
let targetPromise = getDevToolsTargetForContext(context);
|
||||
targetPromise.then(target => {
|
||||
target.on("navigate", listener);
|
||||
});
|
||||
return () => {
|
||||
let targetPromise = getDevToolsTargetForContext(context);
|
||||
targetPromise.then(target => {
|
||||
target.off("navigate", listener);
|
||||
target.on("navigate", listener);
|
||||
});
|
||||
};
|
||||
return () => {
|
||||
targetPromise.then(target => {
|
||||
target.off("navigate", listener);
|
||||
});
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
getHAR: function() {
|
||||
return context.devToolsToolbox.getHARFromNetMonitor();
|
||||
},
|
||||
|
||||
onRequestFinished: new EventManager(context, "devtools.network.onRequestFinished", fire => {
|
||||
const listener = (data) => {
|
||||
fire.async(data);
|
||||
};
|
||||
onRequestFinished: new EventManager({
|
||||
context,
|
||||
name: "devtools.network.onRequestFinished",
|
||||
register: fire => {
|
||||
const listener = (data) => {
|
||||
fire.async(data);
|
||||
};
|
||||
|
||||
const toolbox = context.devToolsToolbox;
|
||||
toolbox.addRequestFinishedListener(listener);
|
||||
const toolbox = context.devToolsToolbox;
|
||||
toolbox.addRequestFinishedListener(listener);
|
||||
|
||||
return () => {
|
||||
toolbox.removeRequestFinishedListener(listener);
|
||||
};
|
||||
return () => {
|
||||
toolbox.removeRequestFinishedListener(listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
// The following method is used internally to allow the request API
|
||||
|
|
|
@ -525,8 +525,10 @@ this.devtools_panels = class extends ExtensionAPI {
|
|||
devtools: {
|
||||
panels: {
|
||||
elements: {
|
||||
onSelectionChanged: new EventManager(
|
||||
context, "devtools.panels.elements.onSelectionChanged", fire => {
|
||||
onSelectionChanged: new EventManager({
|
||||
context,
|
||||
name: "devtools.panels.elements.onSelectionChanged",
|
||||
register: fire => {
|
||||
const listener = (eventName) => {
|
||||
fire.async();
|
||||
};
|
||||
|
@ -534,7 +536,8 @@ this.devtools_panels = class extends ExtensionAPI {
|
|||
return () => {
|
||||
toolboxSelectionObserver.off("selectionChanged", listener);
|
||||
};
|
||||
}).api(),
|
||||
},
|
||||
}).api(),
|
||||
createSidebarPane(title) {
|
||||
const id = `devtools-inspector-sidebar-${makeWidgetId(newBasePanelId())}`;
|
||||
|
||||
|
|
|
@ -473,11 +473,15 @@ this.geckoProfiler = class extends ExtensionAPI {
|
|||
throw new Error(`Ran out of options to get symbols from library ${debugName} ${breakpadId}.`);
|
||||
},
|
||||
|
||||
onRunning: new EventManager(context, "geckoProfiler.onRunning", fire => {
|
||||
isRunningObserver.addObserver(fire.async);
|
||||
return () => {
|
||||
isRunningObserver.removeObserver(fire.async);
|
||||
};
|
||||
onRunning: new EventManager({
|
||||
context,
|
||||
name: "geckoProfiler.onRunning",
|
||||
register: fire => {
|
||||
isRunningObserver.addObserver(fire.async);
|
||||
return () => {
|
||||
isRunningObserver.removeObserver(fire.async);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -220,37 +220,49 @@ this.history = class extends ExtensionAPI {
|
|||
return Promise.resolve(results);
|
||||
},
|
||||
|
||||
onVisited: new EventManager(context, "history.onVisited", fire => {
|
||||
let listener = (event, data) => {
|
||||
fire.sync(data);
|
||||
};
|
||||
onVisited: new EventManager({
|
||||
context,
|
||||
name: "history.onVisited",
|
||||
register: fire => {
|
||||
let listener = (event, data) => {
|
||||
fire.sync(data);
|
||||
};
|
||||
|
||||
getHistoryObserver().on("visited", listener);
|
||||
return () => {
|
||||
getHistoryObserver().off("visited", listener);
|
||||
};
|
||||
getHistoryObserver().on("visited", listener);
|
||||
return () => {
|
||||
getHistoryObserver().off("visited", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onVisitRemoved: new EventManager(context, "history.onVisitRemoved", fire => {
|
||||
let listener = (event, data) => {
|
||||
fire.sync(data);
|
||||
};
|
||||
onVisitRemoved: new EventManager({
|
||||
context,
|
||||
name: "history.onVisitRemoved",
|
||||
register: fire => {
|
||||
let listener = (event, data) => {
|
||||
fire.sync(data);
|
||||
};
|
||||
|
||||
getHistoryObserver().on("visitRemoved", listener);
|
||||
return () => {
|
||||
getHistoryObserver().off("visitRemoved", listener);
|
||||
};
|
||||
getHistoryObserver().on("visitRemoved", listener);
|
||||
return () => {
|
||||
getHistoryObserver().off("visitRemoved", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onTitleChanged: new EventManager(context, "history.onTitleChanged", fire => {
|
||||
let listener = (event, data) => {
|
||||
fire.sync(data);
|
||||
};
|
||||
onTitleChanged: new EventManager({
|
||||
context,
|
||||
name: "history.onTitleChanged",
|
||||
register: fire => {
|
||||
let listener = (event, data) => {
|
||||
fire.sync(data);
|
||||
};
|
||||
|
||||
getHistoryObserver().on("titleChanged", listener);
|
||||
return () => {
|
||||
getHistoryObserver().off("titleChanged", listener);
|
||||
};
|
||||
getHistoryObserver().on("titleChanged", listener);
|
||||
return () => {
|
||||
getHistoryObserver().off("titleChanged", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -813,40 +813,48 @@ this.menusInternal = class extends ExtensionAPI {
|
|||
gMenuBuilder.rebuildMenu(extension);
|
||||
},
|
||||
|
||||
onShown: new EventManager(context, "menus.onShown", fire => {
|
||||
let listener = (event, menuIds, contextData) => {
|
||||
let info = {
|
||||
menuIds,
|
||||
contexts: Array.from(getMenuContexts(contextData)),
|
||||
};
|
||||
onShown: new EventManager({
|
||||
context,
|
||||
name: "menus.onShown",
|
||||
register: fire => {
|
||||
let listener = (event, menuIds, contextData) => {
|
||||
let info = {
|
||||
menuIds,
|
||||
contexts: Array.from(getMenuContexts(contextData)),
|
||||
};
|
||||
|
||||
// The menus.onShown event is fired before the user has consciously
|
||||
// interacted with an extension, so we require permissions before
|
||||
// exposing sensitive contextual data.
|
||||
let includeSensitiveData =
|
||||
// The menus.onShown event is fired before the user has consciously
|
||||
// interacted with an extension, so we require permissions before
|
||||
// exposing sensitive contextual data.
|
||||
let includeSensitiveData =
|
||||
extension.tabManager.hasActiveTabPermission(contextData.tab) ||
|
||||
extension.whiteListedHosts.matches(contextData.inFrame ? contextData.frameUrl : contextData.pageUrl);
|
||||
|
||||
addMenuEventInfo(info, contextData, includeSensitiveData);
|
||||
addMenuEventInfo(info, contextData, includeSensitiveData);
|
||||
|
||||
let tab = extension.tabManager.convert(contextData.tab);
|
||||
fire.sync(info, tab);
|
||||
};
|
||||
gOnShownSubscribers.add(extension);
|
||||
extension.on("webext-menu-shown", listener);
|
||||
return () => {
|
||||
gOnShownSubscribers.delete(extension);
|
||||
extension.off("webext-menu-shown", listener);
|
||||
};
|
||||
let tab = extension.tabManager.convert(contextData.tab);
|
||||
fire.sync(info, tab);
|
||||
};
|
||||
gOnShownSubscribers.add(extension);
|
||||
extension.on("webext-menu-shown", listener);
|
||||
return () => {
|
||||
gOnShownSubscribers.delete(extension);
|
||||
extension.off("webext-menu-shown", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
onHidden: new EventManager(context, "menus.onHidden", fire => {
|
||||
let listener = () => {
|
||||
fire.sync();
|
||||
};
|
||||
extension.on("webext-menu-hidden", listener);
|
||||
return () => {
|
||||
extension.off("webext-menu-hidden", listener);
|
||||
};
|
||||
onHidden: new EventManager({
|
||||
context,
|
||||
name: "menus.onHidden",
|
||||
register: fire => {
|
||||
let listener = () => {
|
||||
fire.sync();
|
||||
};
|
||||
extension.on("webext-menu-hidden", listener);
|
||||
return () => {
|
||||
extension.off("webext-menu-hidden", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
};
|
||||
|
||||
|
@ -883,18 +891,22 @@ this.menusInternal = class extends ExtensionAPI {
|
|||
}
|
||||
},
|
||||
|
||||
onClicked: new EventManager(context, "menusInternal.onClicked", fire => {
|
||||
let listener = (event, info, nativeTab) => {
|
||||
let {linkedBrowser} = nativeTab || tabTracker.activeTab;
|
||||
let tab = nativeTab && extension.tabManager.convert(nativeTab);
|
||||
context.withPendingBrowser(linkedBrowser,
|
||||
() => fire.sync(info, tab));
|
||||
};
|
||||
onClicked: new EventManager({
|
||||
context,
|
||||
name: "menusInternal.onClicked",
|
||||
register: fire => {
|
||||
let listener = (event, info, nativeTab) => {
|
||||
let {linkedBrowser} = nativeTab || tabTracker.activeTab;
|
||||
let tab = nativeTab && extension.tabManager.convert(nativeTab);
|
||||
context.withPendingBrowser(linkedBrowser,
|
||||
() => fire.sync(info, tab));
|
||||
};
|
||||
|
||||
extension.on("webext-menu-menuitem-click", listener);
|
||||
return () => {
|
||||
extension.off("webext-menu-menuitem-click", listener);
|
||||
};
|
||||
extension.on("webext-menu-menuitem-click", listener);
|
||||
return () => {
|
||||
extension.off("webext-menu-menuitem-click", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -37,34 +37,46 @@ this.omnibox = class extends ExtensionAPI {
|
|||
}
|
||||
},
|
||||
|
||||
onInputStarted: new EventManager(context, "omnibox.onInputStarted", fire => {
|
||||
let listener = (eventName) => {
|
||||
fire.sync();
|
||||
};
|
||||
extension.on(ExtensionSearchHandler.MSG_INPUT_STARTED, listener);
|
||||
return () => {
|
||||
extension.off(ExtensionSearchHandler.MSG_INPUT_STARTED, listener);
|
||||
};
|
||||
onInputStarted: new EventManager({
|
||||
context,
|
||||
name: "omnibox.onInputStarted",
|
||||
register: fire => {
|
||||
let listener = (eventName) => {
|
||||
fire.sync();
|
||||
};
|
||||
extension.on(ExtensionSearchHandler.MSG_INPUT_STARTED, listener);
|
||||
return () => {
|
||||
extension.off(ExtensionSearchHandler.MSG_INPUT_STARTED, listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onInputCancelled: new EventManager(context, "omnibox.onInputCancelled", fire => {
|
||||
let listener = (eventName) => {
|
||||
fire.sync();
|
||||
};
|
||||
extension.on(ExtensionSearchHandler.MSG_INPUT_CANCELLED, listener);
|
||||
return () => {
|
||||
extension.off(ExtensionSearchHandler.MSG_INPUT_CANCELLED, listener);
|
||||
};
|
||||
onInputCancelled: new EventManager({
|
||||
context,
|
||||
name: "omnibox.onInputCancelled",
|
||||
register: fire => {
|
||||
let listener = (eventName) => {
|
||||
fire.sync();
|
||||
};
|
||||
extension.on(ExtensionSearchHandler.MSG_INPUT_CANCELLED, listener);
|
||||
return () => {
|
||||
extension.off(ExtensionSearchHandler.MSG_INPUT_CANCELLED, listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onInputEntered: new EventManager(context, "omnibox.onInputEntered", fire => {
|
||||
let listener = (eventName, text, disposition) => {
|
||||
fire.sync(text, disposition);
|
||||
};
|
||||
extension.on(ExtensionSearchHandler.MSG_INPUT_ENTERED, listener);
|
||||
return () => {
|
||||
extension.off(ExtensionSearchHandler.MSG_INPUT_ENTERED, listener);
|
||||
};
|
||||
onInputEntered: new EventManager({
|
||||
context,
|
||||
name: "omnibox.onInputEntered",
|
||||
register: fire => {
|
||||
let listener = (eventName, text, disposition) => {
|
||||
fire.sync(text, disposition);
|
||||
};
|
||||
extension.on(ExtensionSearchHandler.MSG_INPUT_ENTERED, listener);
|
||||
return () => {
|
||||
extension.off(ExtensionSearchHandler.MSG_INPUT_ENTERED, listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
// Internal APIs.
|
||||
|
@ -77,14 +89,18 @@ this.omnibox = class extends ExtensionAPI {
|
|||
}
|
||||
},
|
||||
|
||||
onInputChanged: new EventManager(context, "omnibox.onInputChanged", fire => {
|
||||
let listener = (eventName, text, id) => {
|
||||
fire.sync(text, id);
|
||||
};
|
||||
extension.on(ExtensionSearchHandler.MSG_INPUT_CHANGED, listener);
|
||||
return () => {
|
||||
extension.off(ExtensionSearchHandler.MSG_INPUT_CHANGED, listener);
|
||||
};
|
||||
onInputChanged: new EventManager({
|
||||
context,
|
||||
name: "omnibox.onInputChanged",
|
||||
register: fire => {
|
||||
let listener = (eventName, text, id) => {
|
||||
fire.sync(text, id);
|
||||
};
|
||||
extension.on(ExtensionSearchHandler.MSG_INPUT_CHANGED, listener);
|
||||
return () => {
|
||||
extension.off(ExtensionSearchHandler.MSG_INPUT_CHANGED, listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -346,16 +346,21 @@ this.pageAction = class extends ExtensionAPI {
|
|||
|
||||
return {
|
||||
pageAction: {
|
||||
onClicked: new InputEventManager(context, "pageAction.onClicked", fire => {
|
||||
let listener = (evt, tab) => {
|
||||
context.withPendingBrowser(tab.linkedBrowser, () =>
|
||||
fire.sync(tabManager.convert(tab)));
|
||||
};
|
||||
onClicked: new EventManager({
|
||||
context,
|
||||
name: "pageAction.onClicked",
|
||||
inputHandling: true,
|
||||
register: fire => {
|
||||
let listener = (evt, tab) => {
|
||||
context.withPendingBrowser(tab.linkedBrowser, () =>
|
||||
fire.sync(tabManager.convert(tab)));
|
||||
};
|
||||
|
||||
pageAction.on("click", listener);
|
||||
return () => {
|
||||
pageAction.off("click", listener);
|
||||
};
|
||||
pageAction.on("click", listener);
|
||||
return () => {
|
||||
pageAction.off("click", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
show(tabId) {
|
||||
|
|
|
@ -204,15 +204,19 @@ this.sessions = class extends ExtensionAPI {
|
|||
SessionStore.deleteWindowValue(win, encodedKey);
|
||||
},
|
||||
|
||||
onChanged: new EventManager(context, "sessions.onChanged", fire => {
|
||||
let observer = () => {
|
||||
fire.async();
|
||||
};
|
||||
onChanged: new EventManager({
|
||||
context,
|
||||
name: "sessions.onChanged",
|
||||
register: fire => {
|
||||
let observer = () => {
|
||||
fire.async();
|
||||
};
|
||||
|
||||
Services.obs.addObserver(observer, SS_ON_CLOSED_OBJECTS_CHANGED);
|
||||
return () => {
|
||||
Services.obs.removeObserver(observer, SS_ON_CLOSED_OBJECTS_CHANGED);
|
||||
};
|
||||
Services.obs.addObserver(observer, SS_ON_CLOSED_OBJECTS_CHANGED);
|
||||
return () => {
|
||||
Services.obs.removeObserver(observer, SS_ON_CLOSED_OBJECTS_CHANGED);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -110,7 +110,7 @@ const allProperties = new Set([
|
|||
const restricted = new Set(["url", "favIconUrl", "title"]);
|
||||
|
||||
class TabsUpdateFilterEventManager extends EventManager {
|
||||
constructor(context, eventName) {
|
||||
constructor(context) {
|
||||
let {extension} = context;
|
||||
let {tabManager} = extension;
|
||||
|
||||
|
@ -286,7 +286,11 @@ class TabsUpdateFilterEventManager extends EventManager {
|
|||
};
|
||||
};
|
||||
|
||||
super(context, eventName, register);
|
||||
super({
|
||||
context,
|
||||
name: "tabs.onUpdated",
|
||||
register,
|
||||
});
|
||||
}
|
||||
|
||||
addListener(callback, filter) {
|
||||
|
@ -338,26 +342,34 @@ this.tabs = class extends ExtensionAPI {
|
|||
|
||||
let self = {
|
||||
tabs: {
|
||||
onActivated: new EventManager(context, "tabs.onActivated", fire => {
|
||||
let listener = (eventName, event) => {
|
||||
fire.async(event);
|
||||
};
|
||||
onActivated: new EventManager({
|
||||
context,
|
||||
name: "tabs.onActivated",
|
||||
register: fire => {
|
||||
let listener = (eventName, event) => {
|
||||
fire.async(event);
|
||||
};
|
||||
|
||||
tabTracker.on("tab-activated", listener);
|
||||
return () => {
|
||||
tabTracker.off("tab-activated", listener);
|
||||
};
|
||||
tabTracker.on("tab-activated", listener);
|
||||
return () => {
|
||||
tabTracker.off("tab-activated", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onCreated: new EventManager(context, "tabs.onCreated", fire => {
|
||||
let listener = (eventName, event) => {
|
||||
fire.async(tabManager.convert(event.nativeTab, event.currentTab));
|
||||
};
|
||||
onCreated: new EventManager({
|
||||
context,
|
||||
name: "tabs.onCreated",
|
||||
register: fire => {
|
||||
let listener = (eventName, event) => {
|
||||
fire.async(tabManager.convert(event.nativeTab, event.currentTab));
|
||||
};
|
||||
|
||||
tabTracker.on("tab-created", listener);
|
||||
return () => {
|
||||
tabTracker.off("tab-created", listener);
|
||||
};
|
||||
tabTracker.on("tab-created", listener);
|
||||
return () => {
|
||||
tabTracker.off("tab-created", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
/**
|
||||
|
@ -366,98 +378,122 @@ this.tabs = class extends ExtensionAPI {
|
|||
* the tabId in an array to match the API.
|
||||
* @see https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/Tabs/onHighlighted
|
||||
*/
|
||||
onHighlighted: new EventManager(context, "tabs.onHighlighted", fire => {
|
||||
let listener = (eventName, event) => {
|
||||
fire.async({tabIds: [event.tabId], windowId: event.windowId});
|
||||
};
|
||||
onHighlighted: new EventManager({
|
||||
context,
|
||||
name: "tabs.onHighlighted",
|
||||
register: fire => {
|
||||
let listener = (eventName, event) => {
|
||||
fire.async({tabIds: [event.tabId], windowId: event.windowId});
|
||||
};
|
||||
|
||||
tabTracker.on("tab-activated", listener);
|
||||
return () => {
|
||||
tabTracker.off("tab-activated", listener);
|
||||
};
|
||||
tabTracker.on("tab-activated", listener);
|
||||
return () => {
|
||||
tabTracker.off("tab-activated", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onAttached: new EventManager(context, "tabs.onAttached", fire => {
|
||||
let listener = (eventName, event) => {
|
||||
fire.async(event.tabId, {newWindowId: event.newWindowId, newPosition: event.newPosition});
|
||||
};
|
||||
onAttached: new EventManager({
|
||||
context,
|
||||
name: "tabs.onAttached",
|
||||
register: fire => {
|
||||
let listener = (eventName, event) => {
|
||||
fire.async(event.tabId, {newWindowId: event.newWindowId, newPosition: event.newPosition});
|
||||
};
|
||||
|
||||
tabTracker.on("tab-attached", listener);
|
||||
return () => {
|
||||
tabTracker.off("tab-attached", listener);
|
||||
};
|
||||
tabTracker.on("tab-attached", listener);
|
||||
return () => {
|
||||
tabTracker.off("tab-attached", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onDetached: new EventManager(context, "tabs.onDetached", fire => {
|
||||
let listener = (eventName, event) => {
|
||||
fire.async(event.tabId, {oldWindowId: event.oldWindowId, oldPosition: event.oldPosition});
|
||||
};
|
||||
onDetached: new EventManager({
|
||||
context,
|
||||
name: "tabs.onDetached",
|
||||
register: fire => {
|
||||
let listener = (eventName, event) => {
|
||||
fire.async(event.tabId, {oldWindowId: event.oldWindowId, oldPosition: event.oldPosition});
|
||||
};
|
||||
|
||||
tabTracker.on("tab-detached", listener);
|
||||
return () => {
|
||||
tabTracker.off("tab-detached", listener);
|
||||
};
|
||||
tabTracker.on("tab-detached", listener);
|
||||
return () => {
|
||||
tabTracker.off("tab-detached", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onRemoved: new EventManager(context, "tabs.onRemoved", fire => {
|
||||
let listener = (eventName, event) => {
|
||||
fire.async(event.tabId, {windowId: event.windowId, isWindowClosing: event.isWindowClosing});
|
||||
};
|
||||
onRemoved: new EventManager({
|
||||
context,
|
||||
name: "tabs.onRemoved",
|
||||
register: fire => {
|
||||
let listener = (eventName, event) => {
|
||||
fire.async(event.tabId, {windowId: event.windowId, isWindowClosing: event.isWindowClosing});
|
||||
};
|
||||
|
||||
tabTracker.on("tab-removed", listener);
|
||||
return () => {
|
||||
tabTracker.off("tab-removed", listener);
|
||||
};
|
||||
tabTracker.on("tab-removed", listener);
|
||||
return () => {
|
||||
tabTracker.off("tab-removed", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onReplaced: new EventManager(context, "tabs.onReplaced", fire => {
|
||||
return () => {};
|
||||
onReplaced: new EventManager({
|
||||
context,
|
||||
name: "tabs.onReplaced",
|
||||
register: fire => {
|
||||
return () => {};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onMoved: new EventManager(context, "tabs.onMoved", fire => {
|
||||
// There are certain circumstances where we need to ignore a move event.
|
||||
//
|
||||
// Namely, the first time the tab is moved after it's created, we need
|
||||
// to report the final position as the initial position in the tab's
|
||||
// onAttached or onCreated event. This is because most tabs are inserted
|
||||
// in a temporary location and then moved after the TabOpen event fires,
|
||||
// which generates a TabOpen event followed by a TabMove event, which
|
||||
// does not match the contract of our API.
|
||||
let ignoreNextMove = new WeakSet();
|
||||
onMoved: new EventManager({
|
||||
context,
|
||||
name: "tabs.onMoved",
|
||||
register: fire => {
|
||||
// There are certain circumstances where we need to ignore a move event.
|
||||
//
|
||||
// Namely, the first time the tab is moved after it's created, we need
|
||||
// to report the final position as the initial position in the tab's
|
||||
// onAttached or onCreated event. This is because most tabs are inserted
|
||||
// in a temporary location and then moved after the TabOpen event fires,
|
||||
// which generates a TabOpen event followed by a TabMove event, which
|
||||
// does not match the contract of our API.
|
||||
let ignoreNextMove = new WeakSet();
|
||||
|
||||
let openListener = event => {
|
||||
ignoreNextMove.add(event.target);
|
||||
// Remove the tab from the set on the next tick, since it will already
|
||||
// have been moved by then.
|
||||
Promise.resolve().then(() => {
|
||||
ignoreNextMove.delete(event.target);
|
||||
});
|
||||
};
|
||||
let openListener = event => {
|
||||
ignoreNextMove.add(event.target);
|
||||
// Remove the tab from the set on the next tick, since it will already
|
||||
// have been moved by then.
|
||||
Promise.resolve().then(() => {
|
||||
ignoreNextMove.delete(event.target);
|
||||
});
|
||||
};
|
||||
|
||||
let moveListener = event => {
|
||||
let nativeTab = event.originalTarget;
|
||||
let moveListener = event => {
|
||||
let nativeTab = event.originalTarget;
|
||||
|
||||
if (ignoreNextMove.has(nativeTab)) {
|
||||
ignoreNextMove.delete(nativeTab);
|
||||
return;
|
||||
}
|
||||
if (ignoreNextMove.has(nativeTab)) {
|
||||
ignoreNextMove.delete(nativeTab);
|
||||
return;
|
||||
}
|
||||
|
||||
fire.async(tabTracker.getId(nativeTab), {
|
||||
windowId: windowTracker.getId(nativeTab.ownerGlobal),
|
||||
fromIndex: event.detail,
|
||||
toIndex: nativeTab._tPos,
|
||||
});
|
||||
};
|
||||
fire.async(tabTracker.getId(nativeTab), {
|
||||
windowId: windowTracker.getId(nativeTab.ownerGlobal),
|
||||
fromIndex: event.detail,
|
||||
toIndex: nativeTab._tPos,
|
||||
});
|
||||
};
|
||||
|
||||
windowTracker.addListener("TabMove", moveListener);
|
||||
windowTracker.addListener("TabOpen", openListener);
|
||||
return () => {
|
||||
windowTracker.removeListener("TabMove", moveListener);
|
||||
windowTracker.removeListener("TabOpen", openListener);
|
||||
};
|
||||
windowTracker.addListener("TabMove", moveListener);
|
||||
windowTracker.addListener("TabOpen", openListener);
|
||||
return () => {
|
||||
windowTracker.removeListener("TabMove", moveListener);
|
||||
windowTracker.removeListener("TabOpen", openListener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onUpdated: new TabsUpdateFilterEventManager(context, "tabs.onUpdated").api(),
|
||||
onUpdated: new TabsUpdateFilterEventManager(context).api(),
|
||||
|
||||
create(createProperties) {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
@ -896,75 +932,79 @@ this.tabs = class extends ExtensionAPI {
|
|||
return Promise.resolve();
|
||||
},
|
||||
|
||||
onZoomChange: new EventManager(context, "tabs.onZoomChange", fire => {
|
||||
let getZoomLevel = browser => {
|
||||
let {ZoomManager} = browser.ownerGlobal;
|
||||
onZoomChange: new EventManager({
|
||||
context,
|
||||
name: "tabs.onZoomChange",
|
||||
register: fire => {
|
||||
let getZoomLevel = browser => {
|
||||
let {ZoomManager} = browser.ownerGlobal;
|
||||
|
||||
return ZoomManager.getZoomForBrowser(browser);
|
||||
};
|
||||
return ZoomManager.getZoomForBrowser(browser);
|
||||
};
|
||||
|
||||
// Stores the last known zoom level for each tab's browser.
|
||||
// WeakMap[<browser> -> number]
|
||||
let zoomLevels = new WeakMap();
|
||||
// Stores the last known zoom level for each tab's browser.
|
||||
// WeakMap[<browser> -> number]
|
||||
let zoomLevels = new WeakMap();
|
||||
|
||||
// Store the zoom level for all existing tabs.
|
||||
for (let window of windowTracker.browserWindows()) {
|
||||
for (let nativeTab of window.gBrowser.tabs) {
|
||||
let browser = nativeTab.linkedBrowser;
|
||||
// Store the zoom level for all existing tabs.
|
||||
for (let window of windowTracker.browserWindows()) {
|
||||
for (let nativeTab of window.gBrowser.tabs) {
|
||||
let browser = nativeTab.linkedBrowser;
|
||||
zoomLevels.set(browser, getZoomLevel(browser));
|
||||
}
|
||||
}
|
||||
|
||||
let tabCreated = (eventName, event) => {
|
||||
let browser = event.nativeTab.linkedBrowser;
|
||||
zoomLevels.set(browser, getZoomLevel(browser));
|
||||
}
|
||||
}
|
||||
|
||||
let tabCreated = (eventName, event) => {
|
||||
let browser = event.nativeTab.linkedBrowser;
|
||||
zoomLevels.set(browser, getZoomLevel(browser));
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
let zoomListener = event => {
|
||||
let browser = event.originalTarget;
|
||||
let zoomListener = event => {
|
||||
let browser = event.originalTarget;
|
||||
|
||||
// For non-remote browsers, this event is dispatched on the document
|
||||
// rather than on the <browser>.
|
||||
if (browser instanceof Ci.nsIDOMDocument) {
|
||||
browser = browser.docShell.chromeEventHandler;
|
||||
}
|
||||
// For non-remote browsers, this event is dispatched on the document
|
||||
// rather than on the <browser>.
|
||||
if (browser instanceof Ci.nsIDOMDocument) {
|
||||
browser = browser.docShell.chromeEventHandler;
|
||||
}
|
||||
|
||||
let {gBrowser} = browser.ownerGlobal;
|
||||
let nativeTab = gBrowser.getTabForBrowser(browser);
|
||||
if (!nativeTab) {
|
||||
// We only care about zoom events in the top-level browser of a tab.
|
||||
return;
|
||||
}
|
||||
let {gBrowser} = browser.ownerGlobal;
|
||||
let nativeTab = gBrowser.getTabForBrowser(browser);
|
||||
if (!nativeTab) {
|
||||
// We only care about zoom events in the top-level browser of a tab.
|
||||
return;
|
||||
}
|
||||
|
||||
let oldZoomFactor = zoomLevels.get(browser);
|
||||
let newZoomFactor = getZoomLevel(browser);
|
||||
let oldZoomFactor = zoomLevels.get(browser);
|
||||
let newZoomFactor = getZoomLevel(browser);
|
||||
|
||||
if (oldZoomFactor != newZoomFactor) {
|
||||
zoomLevels.set(browser, newZoomFactor);
|
||||
if (oldZoomFactor != newZoomFactor) {
|
||||
zoomLevels.set(browser, newZoomFactor);
|
||||
|
||||
let tabId = tabTracker.getId(nativeTab);
|
||||
fire.async({
|
||||
tabId,
|
||||
oldZoomFactor,
|
||||
newZoomFactor,
|
||||
zoomSettings: self.tabs._getZoomSettings(tabId),
|
||||
});
|
||||
}
|
||||
};
|
||||
let tabId = tabTracker.getId(nativeTab);
|
||||
fire.async({
|
||||
tabId,
|
||||
oldZoomFactor,
|
||||
newZoomFactor,
|
||||
zoomSettings: self.tabs._getZoomSettings(tabId),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
tabTracker.on("tab-attached", tabCreated);
|
||||
tabTracker.on("tab-created", tabCreated);
|
||||
tabTracker.on("tab-attached", tabCreated);
|
||||
tabTracker.on("tab-created", tabCreated);
|
||||
|
||||
windowTracker.addListener("FullZoomChange", zoomListener);
|
||||
windowTracker.addListener("TextZoomChange", zoomListener);
|
||||
return () => {
|
||||
tabTracker.off("tab-attached", tabCreated);
|
||||
tabTracker.off("tab-created", tabCreated);
|
||||
windowTracker.addListener("FullZoomChange", zoomListener);
|
||||
windowTracker.addListener("TextZoomChange", zoomListener);
|
||||
return () => {
|
||||
tabTracker.off("tab-attached", tabCreated);
|
||||
tabTracker.off("tab-created", tabCreated);
|
||||
|
||||
windowTracker.removeListener("FullZoomChange", zoomListener);
|
||||
windowTracker.removeListener("TextZoomChange", zoomListener);
|
||||
};
|
||||
windowTracker.removeListener("FullZoomChange", zoomListener);
|
||||
windowTracker.removeListener("TextZoomChange", zoomListener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
print() {
|
||||
|
|
|
@ -16,6 +16,36 @@ const onXULFrameLoaderCreated = ({target}) => {
|
|||
target.messageManager.sendAsyncMessage("AllowScriptsToClose", {});
|
||||
};
|
||||
|
||||
/**
|
||||
* An event manager API provider which listens for a DOM event in any browser
|
||||
* window, and calls the given listener function whenever an event is received.
|
||||
* That listener function receives a `fire` object, which it can use to dispatch
|
||||
* events to the extension, and a DOM event object.
|
||||
*
|
||||
* @param {BaseContext} context
|
||||
* The extension context which the event manager belongs to.
|
||||
* @param {string} name
|
||||
* The API name of the event manager, e.g.,"runtime.onMessage".
|
||||
* @param {string} event
|
||||
* The name of the DOM event to listen for.
|
||||
* @param {function} listener
|
||||
* The listener function to call when a DOM event is received.
|
||||
*
|
||||
* @returns {object} An injectable api for the new event.
|
||||
*/
|
||||
function WindowEventManager(context, name, event, listener) {
|
||||
let register = fire => {
|
||||
let listener2 = listener.bind(null, fire);
|
||||
|
||||
windowTracker.addListener(event, listener2);
|
||||
return () => {
|
||||
windowTracker.removeListener(event, listener2);
|
||||
};
|
||||
};
|
||||
|
||||
return new EventManager({context, name, register}).api();
|
||||
}
|
||||
|
||||
this.windows = class extends ExtensionAPI {
|
||||
getAPI(context) {
|
||||
let {extension} = context;
|
||||
|
@ -24,38 +54,40 @@ this.windows = class extends ExtensionAPI {
|
|||
|
||||
return {
|
||||
windows: {
|
||||
onCreated:
|
||||
new WindowEventManager(context, "windows.onCreated", "domwindowopened", (fire, window) => {
|
||||
onCreated: WindowEventManager(context, "windows.onCreated", "domwindowopened", (fire, window) => {
|
||||
fire.async(windowManager.convert(window));
|
||||
}).api(),
|
||||
}),
|
||||
|
||||
onRemoved:
|
||||
new WindowEventManager(context, "windows.onRemoved", "domwindowclosed", (fire, window) => {
|
||||
onRemoved: WindowEventManager(context, "windows.onRemoved", "domwindowclosed", (fire, window) => {
|
||||
fire.async(windowTracker.getId(window));
|
||||
}).api(),
|
||||
}),
|
||||
|
||||
onFocusChanged: new EventManager(context, "windows.onFocusChanged", fire => {
|
||||
// Keep track of the last windowId used to fire an onFocusChanged event
|
||||
let lastOnFocusChangedWindowId;
|
||||
onFocusChanged: new EventManager({
|
||||
context,
|
||||
name: "windows.onFocusChanged",
|
||||
register: fire => {
|
||||
// Keep track of the last windowId used to fire an onFocusChanged event
|
||||
let lastOnFocusChangedWindowId;
|
||||
|
||||
let listener = event => {
|
||||
// Wait a tick to avoid firing a superfluous WINDOW_ID_NONE
|
||||
// event when switching focus between two Firefox windows.
|
||||
Promise.resolve().then(() => {
|
||||
let window = Services.focus.activeWindow;
|
||||
let windowId = window ? windowTracker.getId(window) : Window.WINDOW_ID_NONE;
|
||||
if (windowId !== lastOnFocusChangedWindowId) {
|
||||
fire.async(windowId);
|
||||
lastOnFocusChangedWindowId = windowId;
|
||||
}
|
||||
});
|
||||
};
|
||||
windowTracker.addListener("focus", listener);
|
||||
windowTracker.addListener("blur", listener);
|
||||
return () => {
|
||||
windowTracker.removeListener("focus", listener);
|
||||
windowTracker.removeListener("blur", listener);
|
||||
};
|
||||
let listener = event => {
|
||||
// Wait a tick to avoid firing a superfluous WINDOW_ID_NONE
|
||||
// event when switching focus between two Firefox windows.
|
||||
Promise.resolve().then(() => {
|
||||
let window = Services.focus.activeWindow;
|
||||
let windowId = window ? windowTracker.getId(window) : Window.WINDOW_ID_NONE;
|
||||
if (windowId !== lastOnFocusChangedWindowId) {
|
||||
fire.async(windowId);
|
||||
lastOnFocusChangedWindowId = windowId;
|
||||
}
|
||||
});
|
||||
};
|
||||
windowTracker.addListener("focus", listener);
|
||||
windowTracker.addListener("blur", listener);
|
||||
return () => {
|
||||
windowTracker.removeListener("focus", listener);
|
||||
windowTracker.removeListener("blur", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
get: function(windowId, getInfo) {
|
||||
|
|
|
@ -156,14 +156,18 @@ this.browserAction = class extends ExtensionAPI {
|
|||
|
||||
return {
|
||||
browserAction: {
|
||||
onClicked: new EventManager(context, "browserAction.onClicked", fire => {
|
||||
let listener = (event, tab) => {
|
||||
fire.async(tabManager.convert(tab));
|
||||
};
|
||||
browserActionMap.get(extension).on("click", listener);
|
||||
return () => {
|
||||
browserActionMap.get(extension).off("click", listener);
|
||||
};
|
||||
onClicked: new EventManager({
|
||||
context,
|
||||
name: "browserAction.onClicked",
|
||||
register: fire => {
|
||||
let listener = (event, tab) => {
|
||||
fire.async(tabManager.convert(tab));
|
||||
};
|
||||
browserActionMap.get(extension).on("click", listener);
|
||||
return () => {
|
||||
browserActionMap.get(extension).off("click", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
setTitle: function(details) {
|
||||
|
|
|
@ -232,14 +232,18 @@ this.pageAction = class extends ExtensionAPI {
|
|||
|
||||
return {
|
||||
pageAction: {
|
||||
onClicked: new EventManager(context, "pageAction.onClicked", fire => {
|
||||
let listener = (event, tab) => {
|
||||
fire.async(tabManager.convert(tab));
|
||||
};
|
||||
pageActionMap.get(extension).on("click", listener);
|
||||
return () => {
|
||||
pageActionMap.get(extension).off("click", listener);
|
||||
};
|
||||
onClicked: new EventManager({
|
||||
context,
|
||||
name: "pageAction.onClicked",
|
||||
register: fire => {
|
||||
let listener = (event, tab) => {
|
||||
fire.async(tabManager.convert(tab));
|
||||
};
|
||||
pageActionMap.get(extension).on("click", listener);
|
||||
return () => {
|
||||
pageActionMap.get(extension).off("click", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
show(tabId) {
|
||||
|
|
|
@ -103,21 +103,25 @@ this.tabs = class extends ExtensionAPI {
|
|||
|
||||
let self = {
|
||||
tabs: {
|
||||
onActivated: new GlobalEventManager(context, "tabs.onActivated", "Tab:Selected", (fire, data) => {
|
||||
onActivated: makeGlobalEvent(context, "tabs.onActivated", "Tab:Selected", (fire, data) => {
|
||||
let tab = tabManager.get(data.id);
|
||||
|
||||
fire.async({tabId: tab.id, windowId: tab.windowId});
|
||||
}).api(),
|
||||
}),
|
||||
|
||||
onCreated: new EventManager(context, "tabs.onCreated", fire => {
|
||||
let listener = (eventName, event) => {
|
||||
fire.async(tabManager.convert(event.nativeTab));
|
||||
};
|
||||
onCreated: new EventManager({
|
||||
context,
|
||||
name: "tabs.onCreated",
|
||||
register: fire => {
|
||||
let listener = (eventName, event) => {
|
||||
fire.async(tabManager.convert(event.nativeTab));
|
||||
};
|
||||
|
||||
tabTracker.on("tab-created", listener);
|
||||
return () => {
|
||||
tabTracker.off("tab-created", listener);
|
||||
};
|
||||
tabTracker.on("tab-created", listener);
|
||||
return () => {
|
||||
tabTracker.off("tab-created", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
/**
|
||||
|
@ -126,114 +130,130 @@ this.tabs = class extends ExtensionAPI {
|
|||
* the tabId in an array to match the API.
|
||||
* @see https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/Tabs/onHighlighted
|
||||
*/
|
||||
onHighlighted: new GlobalEventManager(context, "tabs.onHighlighted", "Tab:Selected", (fire, data) => {
|
||||
onHighlighted: makeGlobalEvent(context, "tabs.onHighlighted", "Tab:Selected", (fire, data) => {
|
||||
let tab = tabManager.get(data.id);
|
||||
|
||||
fire.async({tabIds: [tab.id], windowId: tab.windowId});
|
||||
}),
|
||||
|
||||
onAttached: new EventManager({
|
||||
context,
|
||||
name: "tabs.onAttached",
|
||||
register: fire => { return () => {}; },
|
||||
}).api(),
|
||||
|
||||
onAttached: new EventManager(context, "tabs.onAttached", fire => {
|
||||
return () => {};
|
||||
onDetached: new EventManager({
|
||||
context,
|
||||
name: "tabs.onDetached",
|
||||
register: fire => { return () => {}; },
|
||||
}).api(),
|
||||
|
||||
onDetached: new EventManager(context, "tabs.onDetached", fire => {
|
||||
return () => {};
|
||||
onRemoved: new EventManager({
|
||||
context,
|
||||
name: "tabs.onRemoved",
|
||||
register: fire => {
|
||||
let listener = (eventName, event) => {
|
||||
fire.async(event.tabId, {windowId: event.windowId, isWindowClosing: event.isWindowClosing});
|
||||
};
|
||||
|
||||
tabTracker.on("tab-removed", listener);
|
||||
return () => {
|
||||
tabTracker.off("tab-removed", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onRemoved: new EventManager(context, "tabs.onRemoved", fire => {
|
||||
let listener = (eventName, event) => {
|
||||
fire.async(event.tabId, {windowId: event.windowId, isWindowClosing: event.isWindowClosing});
|
||||
};
|
||||
|
||||
tabTracker.on("tab-removed", listener);
|
||||
return () => {
|
||||
tabTracker.off("tab-removed", listener);
|
||||
};
|
||||
onReplaced: new EventManager({
|
||||
context,
|
||||
name: "tabs.onReplaced",
|
||||
register: fire => { return () => {}; },
|
||||
}).api(),
|
||||
|
||||
onReplaced: new EventManager(context, "tabs.onReplaced", fire => {
|
||||
return () => {};
|
||||
onMoved: new EventManager({
|
||||
context,
|
||||
name: "tabs.onMoved",
|
||||
register: fire => { return () => {}; },
|
||||
}).api(),
|
||||
|
||||
onMoved: new EventManager(context, "tabs.onMoved", fire => {
|
||||
return () => {};
|
||||
}).api(),
|
||||
onUpdated: new EventManager({
|
||||
context,
|
||||
name: "tabs.onUpdated",
|
||||
register: fire => {
|
||||
const restricted = ["url", "favIconUrl", "title"];
|
||||
|
||||
onUpdated: new EventManager(context, "tabs.onUpdated", fire => {
|
||||
const restricted = ["url", "favIconUrl", "title"];
|
||||
|
||||
function sanitize(extension, changeInfo) {
|
||||
let result = {};
|
||||
let nonempty = false;
|
||||
for (let prop in changeInfo) {
|
||||
if (extension.hasPermission("tabs") || !restricted.includes(prop)) {
|
||||
nonempty = true;
|
||||
result[prop] = changeInfo[prop];
|
||||
function sanitize(extension, changeInfo) {
|
||||
let result = {};
|
||||
let nonempty = false;
|
||||
for (let prop in changeInfo) {
|
||||
if (extension.hasPermission("tabs") || !restricted.includes(prop)) {
|
||||
nonempty = true;
|
||||
result[prop] = changeInfo[prop];
|
||||
}
|
||||
}
|
||||
return [nonempty, result];
|
||||
}
|
||||
return [nonempty, result];
|
||||
}
|
||||
|
||||
let fireForTab = (tab, changed) => {
|
||||
let [needed, changeInfo] = sanitize(extension, changed);
|
||||
if (needed) {
|
||||
fire.async(tab.id, changeInfo, tab.convert());
|
||||
}
|
||||
};
|
||||
let fireForTab = (tab, changed) => {
|
||||
let [needed, changeInfo] = sanitize(extension, changed);
|
||||
if (needed) {
|
||||
fire.async(tab.id, changeInfo, tab.convert());
|
||||
}
|
||||
};
|
||||
|
||||
let listener = event => {
|
||||
let needed = [];
|
||||
let nativeTab;
|
||||
switch (event.type) {
|
||||
case "DOMTitleChanged": {
|
||||
let {BrowserApp} = getBrowserWindow(event.target.ownerGlobal);
|
||||
let listener = event => {
|
||||
let needed = [];
|
||||
let nativeTab;
|
||||
switch (event.type) {
|
||||
case "DOMTitleChanged": {
|
||||
let {BrowserApp} = getBrowserWindow(event.target.ownerGlobal);
|
||||
|
||||
nativeTab = BrowserApp.getTabForWindow(event.target.ownerGlobal);
|
||||
needed.push("title");
|
||||
break;
|
||||
nativeTab = BrowserApp.getTabForWindow(event.target.ownerGlobal);
|
||||
needed.push("title");
|
||||
break;
|
||||
}
|
||||
|
||||
case "DOMAudioPlaybackStarted":
|
||||
case "DOMAudioPlaybackStopped": {
|
||||
let {BrowserApp} = event.target.ownerGlobal;
|
||||
nativeTab = BrowserApp.getTabForBrowser(event.originalTarget);
|
||||
needed.push("audible");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case "DOMAudioPlaybackStarted":
|
||||
case "DOMAudioPlaybackStopped": {
|
||||
let {BrowserApp} = event.target.ownerGlobal;
|
||||
nativeTab = BrowserApp.getTabForBrowser(event.originalTarget);
|
||||
needed.push("audible");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nativeTab) {
|
||||
return;
|
||||
}
|
||||
|
||||
let tab = tabManager.getWrapper(nativeTab);
|
||||
let changeInfo = {};
|
||||
for (let prop of needed) {
|
||||
changeInfo[prop] = tab[prop];
|
||||
}
|
||||
|
||||
fireForTab(tab, changeInfo);
|
||||
};
|
||||
|
||||
let statusListener = ({browser, status, url}) => {
|
||||
let {BrowserApp} = browser.ownerGlobal;
|
||||
let nativeTab = BrowserApp.getTabForBrowser(browser);
|
||||
if (nativeTab) {
|
||||
let changed = {status};
|
||||
if (url) {
|
||||
changed.url = url;
|
||||
if (!nativeTab) {
|
||||
return;
|
||||
}
|
||||
|
||||
fireForTab(tabManager.wrapTab(nativeTab), changed);
|
||||
}
|
||||
};
|
||||
let tab = tabManager.getWrapper(nativeTab);
|
||||
let changeInfo = {};
|
||||
for (let prop of needed) {
|
||||
changeInfo[prop] = tab[prop];
|
||||
}
|
||||
|
||||
windowTracker.addListener("status", statusListener);
|
||||
windowTracker.addListener("DOMTitleChanged", listener);
|
||||
return () => {
|
||||
windowTracker.removeListener("status", statusListener);
|
||||
windowTracker.removeListener("DOMTitleChanged", listener);
|
||||
};
|
||||
fireForTab(tab, changeInfo);
|
||||
};
|
||||
|
||||
let statusListener = ({browser, status, url}) => {
|
||||
let {BrowserApp} = browser.ownerGlobal;
|
||||
let nativeTab = BrowserApp.getTabForBrowser(browser);
|
||||
if (nativeTab) {
|
||||
let changed = {status};
|
||||
if (url) {
|
||||
changed.url = url;
|
||||
}
|
||||
|
||||
fireForTab(tabManager.wrapTab(nativeTab), changed);
|
||||
}
|
||||
};
|
||||
|
||||
windowTracker.addListener("status", statusListener);
|
||||
windowTracker.addListener("DOMTitleChanged", listener);
|
||||
return () => {
|
||||
windowTracker.removeListener("status", statusListener);
|
||||
windowTracker.removeListener("DOMTitleChanged", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
async create(createProperties) {
|
||||
|
|
|
@ -187,11 +187,11 @@ class WindowTracker extends WindowTrackerBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* An event manager API provider which listens for an event in the Android
|
||||
* global EventDispatcher, and calls the given listener function whenever an event
|
||||
* is received. That listener function receives a `fire` object, which it can
|
||||
* use to dispatch events to the extension, and an object detailing the
|
||||
* EventDispatcher event that was received.
|
||||
* Helper to create an event manager which listens for an event in the Android
|
||||
* global EventDispatcher, and calls the given listener function whenever the
|
||||
* event is received. That listener function receives a `fire` object,
|
||||
* which it can use to dispatch events to the extension, and an object
|
||||
* detailing the EventDispatcher event that was received.
|
||||
*
|
||||
* @param {BaseContext} context
|
||||
* The extension context which the event manager belongs to.
|
||||
|
@ -202,10 +202,14 @@ class WindowTracker extends WindowTrackerBase {
|
|||
* @param {function} listener
|
||||
* The listener function to call when an EventDispatcher event is
|
||||
* recieved.
|
||||
*
|
||||
* @returns {object} An injectable api for the new event.
|
||||
*/
|
||||
global.GlobalEventManager = class extends EventManager {
|
||||
constructor(context, name, event, listener) {
|
||||
super(context, name, fire => {
|
||||
global.makeGlobalEvent = function makeGlobalEvent(context, name, event, listener) {
|
||||
return new EventManager({
|
||||
context,
|
||||
name,
|
||||
register: fire => {
|
||||
let listener2 = {
|
||||
onEvent(event, data, callback) {
|
||||
listener(fire, data);
|
||||
|
@ -216,36 +220,8 @@ global.GlobalEventManager = class extends EventManager {
|
|||
return () => {
|
||||
GlobalEventDispatcher.unregisterListener(listener2, [event]);
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* An event manager API provider which listens for a DOM event in any browser
|
||||
* window, and calls the given listener function whenever an event is received.
|
||||
* That listener function receives a `fire` object, which it can use to dispatch
|
||||
* events to the extension, and a DOM event object.
|
||||
*
|
||||
* @param {BaseContext} context
|
||||
* The extension context which the event manager belongs to.
|
||||
* @param {string} name
|
||||
* The API name of the event manager, e.g.,"runtime.onMessage".
|
||||
* @param {string} event
|
||||
* The name of the DOM event to listen for.
|
||||
* @param {function} listener
|
||||
* The listener function to call when a DOM event is received.
|
||||
*/
|
||||
global.WindowEventManager = class extends EventManager {
|
||||
constructor(context, name, event, listener) {
|
||||
super(context, name, fire => {
|
||||
let listener2 = listener.bind(null, fire);
|
||||
|
||||
windowTracker.addListener(event, listener2);
|
||||
return () => {
|
||||
windowTracker.removeListener(event, listener2);
|
||||
};
|
||||
});
|
||||
}
|
||||
},
|
||||
}).api();
|
||||
};
|
||||
|
||||
class TabTracker extends TabTrackerBase {
|
||||
|
|
|
@ -179,19 +179,27 @@ class Port {
|
|||
this.postMessage(json);
|
||||
},
|
||||
|
||||
onDisconnect: new EventManager(this.context, "Port.onDisconnect", fire => {
|
||||
return this.registerOnDisconnect(holder => {
|
||||
let error = holder && holder.deserialize(this.context.cloneScope);
|
||||
portError = error && this.context.normalizeError(error);
|
||||
fire.asyncWithoutClone(portObj);
|
||||
});
|
||||
onDisconnect: new EventManager({
|
||||
context: this.context,
|
||||
name: "Port.onDisconnect",
|
||||
register: fire => {
|
||||
return this.registerOnDisconnect(holder => {
|
||||
let error = holder && holder.deserialize(this.context.cloneScope);
|
||||
portError = error && this.context.normalizeError(error);
|
||||
fire.asyncWithoutClone(portObj);
|
||||
});
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onMessage: new EventManager(this.context, "Port.onMessage", fire => {
|
||||
return this.registerOnMessage(holder => {
|
||||
let msg = holder.deserialize(this.context.cloneScope);
|
||||
fire.asyncWithoutClone(msg, portObj);
|
||||
});
|
||||
onMessage: new EventManager({
|
||||
context: this.context,
|
||||
name: "Port.onMessage",
|
||||
register: fire => {
|
||||
return this.registerOnMessage(holder => {
|
||||
let msg = holder.deserialize(this.context.cloneScope);
|
||||
fire.asyncWithoutClone(msg, portObj);
|
||||
});
|
||||
},
|
||||
}).api(),
|
||||
|
||||
get error() {
|
||||
|
@ -403,63 +411,67 @@ class Messenger {
|
|||
}
|
||||
|
||||
_onMessage(name, filter) {
|
||||
return new EventManager(this.context, name, fire => {
|
||||
const caller = this.context.getCaller();
|
||||
return new EventManager({
|
||||
context: this.context,
|
||||
name,
|
||||
register: fire => {
|
||||
const caller = this.context.getCaller();
|
||||
|
||||
let listener = {
|
||||
messageFilterPermissive: this.optionalFilter,
|
||||
messageFilterStrict: this.filter,
|
||||
let listener = {
|
||||
messageFilterPermissive: this.optionalFilter,
|
||||
messageFilterStrict: this.filter,
|
||||
|
||||
filterMessage: (sender, recipient) => {
|
||||
// Exclude messages coming from content scripts for the devtools extension contexts
|
||||
// (See Bug 1383310).
|
||||
if (this.excludeContentScriptSender && sender.envType === "content_child") {
|
||||
return false;
|
||||
}
|
||||
filterMessage: (sender, recipient) => {
|
||||
// Exclude messages coming from content scripts for the devtools extension contexts
|
||||
// (See Bug 1383310).
|
||||
if (this.excludeContentScriptSender && sender.envType === "content_child") {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ignore the message if it was sent by this Messenger.
|
||||
return (sender.contextId !== this.context.contextId &&
|
||||
filter(sender, recipient));
|
||||
},
|
||||
// Ignore the message if it was sent by this Messenger.
|
||||
return (sender.contextId !== this.context.contextId &&
|
||||
filter(sender, recipient));
|
||||
},
|
||||
|
||||
receiveMessage: ({target, data: holder, sender, recipient, channelId}) => {
|
||||
if (!this.context.active) {
|
||||
return;
|
||||
}
|
||||
receiveMessage: ({target, data: holder, sender, recipient, channelId}) => {
|
||||
if (!this.context.active) {
|
||||
return;
|
||||
}
|
||||
|
||||
let sendResponse;
|
||||
let response = undefined;
|
||||
let promise = new Promise(resolve => {
|
||||
sendResponse = value => {
|
||||
resolve(value);
|
||||
response = promise;
|
||||
};
|
||||
});
|
||||
let sendResponse;
|
||||
let response = undefined;
|
||||
let promise = new Promise(resolve => {
|
||||
sendResponse = value => {
|
||||
resolve(value);
|
||||
response = promise;
|
||||
};
|
||||
});
|
||||
|
||||
let message = holder.deserialize(this.context.cloneScope);
|
||||
holder = null;
|
||||
let message = holder.deserialize(this.context.cloneScope);
|
||||
holder = null;
|
||||
|
||||
sender = Cu.cloneInto(sender, this.context.cloneScope);
|
||||
sendResponse = Cu.exportFunction(sendResponse, this.context.cloneScope);
|
||||
sender = Cu.cloneInto(sender, this.context.cloneScope);
|
||||
sendResponse = Cu.exportFunction(sendResponse, this.context.cloneScope);
|
||||
|
||||
// Note: We intentionally do not use runSafe here so that any
|
||||
// errors are propagated to the message sender.
|
||||
let result = fire.raw(message, sender, sendResponse);
|
||||
message = null;
|
||||
// Note: We intentionally do not use runSafe here so that any
|
||||
// errors are propagated to the message sender.
|
||||
let result = fire.raw(message, sender, sendResponse);
|
||||
message = null;
|
||||
|
||||
if (result instanceof this.context.cloneScope.Promise) {
|
||||
return StrongPromise.wrap(result, channelId, caller);
|
||||
} else if (result === true) {
|
||||
return StrongPromise.wrap(promise, channelId, caller);
|
||||
}
|
||||
return response;
|
||||
},
|
||||
};
|
||||
if (result instanceof this.context.cloneScope.Promise) {
|
||||
return StrongPromise.wrap(result, channelId, caller);
|
||||
} else if (result === true) {
|
||||
return StrongPromise.wrap(promise, channelId, caller);
|
||||
}
|
||||
return response;
|
||||
},
|
||||
};
|
||||
|
||||
MessageChannel.addListener(this.messageManagers, "Extension:Message", listener);
|
||||
return () => {
|
||||
MessageChannel.removeListener(this.messageManagers, "Extension:Message", listener);
|
||||
};
|
||||
MessageChannel.addListener(this.messageManagers, "Extension:Message", listener);
|
||||
return () => {
|
||||
MessageChannel.removeListener(this.messageManagers, "Extension:Message", listener);
|
||||
};
|
||||
},
|
||||
}).api();
|
||||
}
|
||||
|
||||
|
@ -506,41 +518,45 @@ class Messenger {
|
|||
}
|
||||
|
||||
_onConnect(name, filter) {
|
||||
return new EventManager(this.context, name, fire => {
|
||||
let listener = {
|
||||
messageFilterPermissive: this.optionalFilter,
|
||||
messageFilterStrict: this.filter,
|
||||
return new EventManager({
|
||||
context: this.context,
|
||||
name,
|
||||
register: fire => {
|
||||
let listener = {
|
||||
messageFilterPermissive: this.optionalFilter,
|
||||
messageFilterStrict: this.filter,
|
||||
|
||||
filterMessage: (sender, recipient) => {
|
||||
// Exclude messages coming from content scripts for the devtools extension contexts
|
||||
// (See Bug 1383310).
|
||||
if (this.excludeContentScriptSender && sender.envType === "content_child") {
|
||||
return false;
|
||||
}
|
||||
filterMessage: (sender, recipient) => {
|
||||
// Exclude messages coming from content scripts for the devtools extension contexts
|
||||
// (See Bug 1383310).
|
||||
if (this.excludeContentScriptSender && sender.envType === "content_child") {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ignore the port if it was created by this Messenger.
|
||||
return (sender.contextId !== this.context.contextId &&
|
||||
filter(sender, recipient));
|
||||
},
|
||||
// Ignore the port if it was created by this Messenger.
|
||||
return (sender.contextId !== this.context.contextId &&
|
||||
filter(sender, recipient));
|
||||
},
|
||||
|
||||
receiveMessage: ({target, data: message, sender}) => {
|
||||
let {name, portId} = message;
|
||||
let mm = getMessageManager(target);
|
||||
let recipient = Object.assign({}, sender);
|
||||
if (recipient.tab) {
|
||||
recipient.tabId = recipient.tab.id;
|
||||
delete recipient.tab;
|
||||
}
|
||||
let port = new Port(this.context, mm, this.messageManagers, name, portId, sender, recipient);
|
||||
fire.asyncWithoutClone(port.api());
|
||||
return true;
|
||||
},
|
||||
};
|
||||
receiveMessage: ({target, data: message, sender}) => {
|
||||
let {name, portId} = message;
|
||||
let mm = getMessageManager(target);
|
||||
let recipient = Object.assign({}, sender);
|
||||
if (recipient.tab) {
|
||||
recipient.tabId = recipient.tab.id;
|
||||
delete recipient.tab;
|
||||
}
|
||||
let port = new Port(this.context, mm, this.messageManagers, name, portId, sender, recipient);
|
||||
fire.asyncWithoutClone(port.api());
|
||||
return true;
|
||||
},
|
||||
};
|
||||
|
||||
MessageChannel.addListener(this.messageManagers, "Extension:Connect", listener);
|
||||
return () => {
|
||||
MessageChannel.removeListener(this.messageManagers, "Extension:Connect", listener);
|
||||
};
|
||||
MessageChannel.addListener(this.messageManagers, "Extension:Connect", listener);
|
||||
return () => {
|
||||
MessageChannel.removeListener(this.messageManagers, "Extension:Connect", listener);
|
||||
};
|
||||
},
|
||||
}).api();
|
||||
}
|
||||
|
||||
|
|
|
@ -1735,46 +1735,62 @@ defineLazyGetter(LocaleData.prototype, "availableLocales", function() {
|
|||
});
|
||||
|
||||
/**
|
||||
* This is a generic class for managing event listeners.
|
||||
* This is a generic class for managing event listeners.
|
||||
*
|
||||
* @example
|
||||
* new EventManager(context, "api.subAPI", fire => {
|
||||
* let listener = (...) => {
|
||||
* // Fire any listeners registered with addListener.
|
||||
* fire.async(arg1, arg2);
|
||||
* };
|
||||
* // Register the listener.
|
||||
* SomehowRegisterListener(listener);
|
||||
* return () => {
|
||||
* // Return a way to unregister the listener.
|
||||
* SomehowUnregisterListener(listener);
|
||||
* };
|
||||
* new EventManager({
|
||||
* context,
|
||||
* name: "api.subAPI",
|
||||
* register: fire => {
|
||||
* let listener = (...) => {
|
||||
* // Fire any listeners registered with addListener.
|
||||
* fire.async(arg1, arg2);
|
||||
* };
|
||||
* // Register the listener.
|
||||
* SomehowRegisterListener(listener);
|
||||
* return () => {
|
||||
* // Return a way to unregister the listener.
|
||||
* SomehowUnregisterListener(listener);
|
||||
* };
|
||||
* }
|
||||
* }).api()
|
||||
*
|
||||
* The result is an object with addListener, removeListener, and
|
||||
* hasListener methods. `context` is an add-on scope (either an
|
||||
* ExtensionContext in the chrome process or ExtensionContext in a
|
||||
* content process). `name` is for debugging. `register` is a function
|
||||
* to register the listener. `register` should return an
|
||||
* unregister function that will unregister the listener.
|
||||
* @constructor
|
||||
*
|
||||
* @param {BaseContext} context
|
||||
* An object representing the extension instance using this event.
|
||||
* @param {string} name
|
||||
* A name used only for debugging.
|
||||
* @param {function} register
|
||||
* A function called whenever a new listener is added.
|
||||
* content process).
|
||||
*/
|
||||
function EventManager(context, name, register) {
|
||||
this.context = context;
|
||||
this.name = name;
|
||||
this.register = register;
|
||||
this.unregister = new Map();
|
||||
this.inputHandling = false;
|
||||
}
|
||||
class EventManager {
|
||||
/*
|
||||
* @param {object} params
|
||||
* Parameters that control this EventManager.
|
||||
* @param {BaseContext} params.context
|
||||
* An object representing the extension instance using this event.
|
||||
* @param {string} params.name
|
||||
* A name used only for debugging.
|
||||
* @param {functon} params.register
|
||||
* A function called whenever a new listener is added.
|
||||
* @param {boolean} [params.inputHandling=false]
|
||||
* If true, the "handling user input" flag is set while handlers
|
||||
* for this event are executing.
|
||||
*/
|
||||
constructor(params) {
|
||||
// Maintain compatibility with the old EventManager API in which
|
||||
// the constructor took parameters (contest, name, register).
|
||||
// Remove this in bug 1451212.
|
||||
if (arguments.length > 1) {
|
||||
[this.context, this.name, this.register] = arguments;
|
||||
this.inputHandling = false;
|
||||
} else {
|
||||
let {context, name, register, inputHandling = false} = params;
|
||||
this.context = context;
|
||||
this.name = name;
|
||||
this.register = register;
|
||||
this.inputHandling = inputHandling;
|
||||
}
|
||||
this.unregister = new Map();
|
||||
}
|
||||
|
||||
EventManager.prototype = {
|
||||
addListener(callback, ...args) {
|
||||
if (this.unregister.has(callback)) {
|
||||
return;
|
||||
|
@ -1819,11 +1835,10 @@ EventManager.prototype = {
|
|||
},
|
||||
};
|
||||
|
||||
|
||||
let unregister = this.register(fire, ...args);
|
||||
this.unregister.set(callback, unregister);
|
||||
this.context.callOnClose(this);
|
||||
},
|
||||
}
|
||||
|
||||
removeListener(callback) {
|
||||
if (!this.unregister.has(callback)) {
|
||||
|
@ -1840,21 +1855,21 @@ EventManager.prototype = {
|
|||
if (this.unregister.size == 0) {
|
||||
this.context.forgetOnClose(this);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
hasListener(callback) {
|
||||
return this.unregister.has(callback);
|
||||
},
|
||||
}
|
||||
|
||||
revoke() {
|
||||
for (let callback of this.unregister.keys()) {
|
||||
this.removeListener(callback);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
close() {
|
||||
this.revoke();
|
||||
},
|
||||
}
|
||||
|
||||
api() {
|
||||
return {
|
||||
|
@ -1864,8 +1879,8 @@ EventManager.prototype = {
|
|||
setUserInput: this.inputHandling,
|
||||
[Schemas.REVOKE]: () => this.revoke(),
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Simple API for event listeners where events never fire.
|
||||
function ignoreEvent(context, name) {
|
||||
|
|
|
@ -148,20 +148,24 @@ this.storage = class extends ExtensionAPI {
|
|||
},
|
||||
},
|
||||
|
||||
onChanged: new EventManager(context, "storage.onChanged", fire => {
|
||||
let onChanged = (data, area) => {
|
||||
let changes = new context.cloneScope.Object();
|
||||
for (let [key, value] of Object.entries(data)) {
|
||||
changes[key] = deserialize(value);
|
||||
}
|
||||
fire.raw(changes, area);
|
||||
};
|
||||
onChanged: new EventManager({
|
||||
context,
|
||||
name: "storage.onChanged",
|
||||
register: fire => {
|
||||
let onChanged = (data, area) => {
|
||||
let changes = new context.cloneScope.Object();
|
||||
for (let [key, value] of Object.entries(data)) {
|
||||
changes[key] = deserialize(value);
|
||||
}
|
||||
fire.raw(changes, area);
|
||||
};
|
||||
|
||||
let parent = context.childManager.getParentEvent("storage.onChanged");
|
||||
parent.addListener(onChanged);
|
||||
return () => {
|
||||
parent.removeListener(onChanged);
|
||||
};
|
||||
let parent = context.childManager.getParentEvent("storage.onChanged");
|
||||
parent.addListener(onChanged);
|
||||
return () => {
|
||||
parent.removeListener(onChanged);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -177,15 +177,19 @@ this.test = class extends ExtensionAPI {
|
|||
}
|
||||
},
|
||||
|
||||
onMessage: new TestEventManager(context, "test.onMessage", fire => {
|
||||
let handler = (event, ...args) => {
|
||||
fire.async(...args);
|
||||
};
|
||||
onMessage: new TestEventManager({
|
||||
context,
|
||||
name: "test.onMessage",
|
||||
register: fire => {
|
||||
let handler = (event, ...args) => {
|
||||
fire.async(...args);
|
||||
};
|
||||
|
||||
extension.on("test-harness-message", handler);
|
||||
return () => {
|
||||
extension.off("test-harness-message", handler);
|
||||
};
|
||||
extension.on("test-harness-message", handler);
|
||||
return () => {
|
||||
extension.off("test-harness-message", handler);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -125,15 +125,19 @@ this.alarms = class extends ExtensionAPI {
|
|||
return Promise.resolve(cleared);
|
||||
},
|
||||
|
||||
onAlarm: new EventManager(context, "alarms.onAlarm", fire => {
|
||||
let callback = alarm => {
|
||||
fire.sync(alarm.data);
|
||||
};
|
||||
onAlarm: new EventManager({
|
||||
context,
|
||||
name: "alarms.onAlarm",
|
||||
register: fire => {
|
||||
let callback = alarm => {
|
||||
fire.sync(alarm.data);
|
||||
};
|
||||
|
||||
self.callbacks.add(callback);
|
||||
return () => {
|
||||
self.callbacks.delete(callback);
|
||||
};
|
||||
self.callbacks.add(callback);
|
||||
return () => {
|
||||
self.callbacks.delete(callback);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -224,46 +224,58 @@ this.contextualIdentities = class extends ExtensionAPI {
|
|||
return convertedIdentity;
|
||||
},
|
||||
|
||||
onCreated: new EventManager(context, "contextualIdentities.onCreated", fire => {
|
||||
let observer = (subject, topic) => {
|
||||
let convertedIdentity = convertIdentityFromObserver(subject);
|
||||
if (convertedIdentity) {
|
||||
fire.async({contextualIdentity: convertedIdentity});
|
||||
}
|
||||
};
|
||||
onCreated: new EventManager({
|
||||
context,
|
||||
name: "contextualIdentities.onCreated",
|
||||
register: fire => {
|
||||
let observer = (subject, topic) => {
|
||||
let convertedIdentity = convertIdentityFromObserver(subject);
|
||||
if (convertedIdentity) {
|
||||
fire.async({contextualIdentity: convertedIdentity});
|
||||
}
|
||||
};
|
||||
|
||||
Services.obs.addObserver(observer, "contextual-identity-created");
|
||||
return () => {
|
||||
Services.obs.removeObserver(observer, "contextual-identity-created");
|
||||
};
|
||||
Services.obs.addObserver(observer, "contextual-identity-created");
|
||||
return () => {
|
||||
Services.obs.removeObserver(observer, "contextual-identity-created");
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onUpdated: new EventManager(context, "contextualIdentities.onUpdated", fire => {
|
||||
let observer = (subject, topic) => {
|
||||
let convertedIdentity = convertIdentityFromObserver(subject);
|
||||
if (convertedIdentity) {
|
||||
fire.async({contextualIdentity: convertedIdentity});
|
||||
}
|
||||
};
|
||||
onUpdated: new EventManager({
|
||||
context,
|
||||
name: "contextualIdentities.onUpdated",
|
||||
register: fire => {
|
||||
let observer = (subject, topic) => {
|
||||
let convertedIdentity = convertIdentityFromObserver(subject);
|
||||
if (convertedIdentity) {
|
||||
fire.async({contextualIdentity: convertedIdentity});
|
||||
}
|
||||
};
|
||||
|
||||
Services.obs.addObserver(observer, "contextual-identity-updated");
|
||||
return () => {
|
||||
Services.obs.removeObserver(observer, "contextual-identity-updated");
|
||||
};
|
||||
Services.obs.addObserver(observer, "contextual-identity-updated");
|
||||
return () => {
|
||||
Services.obs.removeObserver(observer, "contextual-identity-updated");
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onRemoved: new EventManager(context, "contextualIdentities.onRemoved", fire => {
|
||||
let observer = (subject, topic) => {
|
||||
let convertedIdentity = convertIdentityFromObserver(subject);
|
||||
if (convertedIdentity) {
|
||||
fire.async({contextualIdentity: convertedIdentity});
|
||||
}
|
||||
};
|
||||
onRemoved: new EventManager({
|
||||
context,
|
||||
name: "contextualIdentities.onRemoved",
|
||||
register: fire => {
|
||||
let observer = (subject, topic) => {
|
||||
let convertedIdentity = convertIdentityFromObserver(subject);
|
||||
if (convertedIdentity) {
|
||||
fire.async({contextualIdentity: convertedIdentity});
|
||||
}
|
||||
};
|
||||
|
||||
Services.obs.addObserver(observer, "contextual-identity-deleted");
|
||||
return () => {
|
||||
Services.obs.removeObserver(observer, "contextual-identity-deleted");
|
||||
};
|
||||
Services.obs.addObserver(observer, "contextual-identity-deleted");
|
||||
return () => {
|
||||
Services.obs.removeObserver(observer, "contextual-identity-deleted");
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
},
|
||||
|
|
|
@ -412,48 +412,52 @@ this.cookies = class extends ExtensionAPI {
|
|||
return Promise.resolve(result);
|
||||
},
|
||||
|
||||
onChanged: new EventManager(context, "cookies.onChanged", fire => {
|
||||
let observer = (subject, topic, data) => {
|
||||
let notify = (removed, cookie, cause) => {
|
||||
cookie.QueryInterface(Ci.nsICookie2);
|
||||
onChanged: new EventManager({
|
||||
context,
|
||||
name: "cookies.onChanged",
|
||||
register: fire => {
|
||||
let observer = (subject, topic, data) => {
|
||||
let notify = (removed, cookie, cause) => {
|
||||
cookie.QueryInterface(Ci.nsICookie2);
|
||||
|
||||
if (extension.whiteListedHosts.matchesCookie(cookie)) {
|
||||
fire.async({removed, cookie: convertCookie({cookie, isPrivate: topic == "private-cookie-changed"}), cause});
|
||||
if (extension.whiteListedHosts.matchesCookie(cookie)) {
|
||||
fire.async({removed, cookie: convertCookie({cookie, isPrivate: topic == "private-cookie-changed"}), cause});
|
||||
}
|
||||
};
|
||||
|
||||
// We do our best effort here to map the incompatible states.
|
||||
switch (data) {
|
||||
case "deleted":
|
||||
notify(true, subject, "explicit");
|
||||
break;
|
||||
case "added":
|
||||
notify(false, subject, "explicit");
|
||||
break;
|
||||
case "changed":
|
||||
notify(true, subject, "overwrite");
|
||||
notify(false, subject, "explicit");
|
||||
break;
|
||||
case "batch-deleted":
|
||||
subject.QueryInterface(Ci.nsIArray);
|
||||
for (let i = 0; i < subject.length; i++) {
|
||||
let cookie = subject.queryElementAt(i, Ci.nsICookie2);
|
||||
if (!cookie.isSession && cookie.expiry * 1000 <= Date.now()) {
|
||||
notify(true, cookie, "expired");
|
||||
} else {
|
||||
notify(true, cookie, "evicted");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
// We do our best effort here to map the incompatible states.
|
||||
switch (data) {
|
||||
case "deleted":
|
||||
notify(true, subject, "explicit");
|
||||
break;
|
||||
case "added":
|
||||
notify(false, subject, "explicit");
|
||||
break;
|
||||
case "changed":
|
||||
notify(true, subject, "overwrite");
|
||||
notify(false, subject, "explicit");
|
||||
break;
|
||||
case "batch-deleted":
|
||||
subject.QueryInterface(Ci.nsIArray);
|
||||
for (let i = 0; i < subject.length; i++) {
|
||||
let cookie = subject.queryElementAt(i, Ci.nsICookie2);
|
||||
if (!cookie.isSession && cookie.expiry * 1000 <= Date.now()) {
|
||||
notify(true, cookie, "expired");
|
||||
} else {
|
||||
notify(true, cookie, "evicted");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
Services.obs.addObserver(observer, "cookie-changed");
|
||||
Services.obs.addObserver(observer, "private-cookie-changed");
|
||||
return () => {
|
||||
Services.obs.removeObserver(observer, "cookie-changed");
|
||||
Services.obs.removeObserver(observer, "private-cookie-changed");
|
||||
};
|
||||
Services.obs.addObserver(observer, "cookie-changed");
|
||||
Services.obs.addObserver(observer, "private-cookie-changed");
|
||||
return () => {
|
||||
Services.obs.removeObserver(observer, "cookie-changed");
|
||||
Services.obs.removeObserver(observer, "private-cookie-changed");
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -765,60 +765,72 @@ this.downloads = class extends ExtensionAPI {
|
|||
// ...
|
||||
// }
|
||||
|
||||
onChanged: new EventManager(context, "downloads.onChanged", fire => {
|
||||
const handler = (what, item) => {
|
||||
let changes = {};
|
||||
const noundef = val => (val === undefined) ? null : val;
|
||||
DOWNLOAD_ITEM_CHANGE_FIELDS.forEach(fld => {
|
||||
if (item[fld] != item.prechange[fld]) {
|
||||
changes[fld] = {
|
||||
previous: noundef(item.prechange[fld]),
|
||||
current: noundef(item[fld]),
|
||||
};
|
||||
onChanged: new EventManager({
|
||||
context,
|
||||
name: "downloads.onChanged",
|
||||
register: fire => {
|
||||
const handler = (what, item) => {
|
||||
let changes = {};
|
||||
const noundef = val => (val === undefined) ? null : val;
|
||||
DOWNLOAD_ITEM_CHANGE_FIELDS.forEach(fld => {
|
||||
if (item[fld] != item.prechange[fld]) {
|
||||
changes[fld] = {
|
||||
previous: noundef(item.prechange[fld]),
|
||||
current: noundef(item[fld]),
|
||||
};
|
||||
}
|
||||
});
|
||||
if (Object.keys(changes).length > 0) {
|
||||
changes.id = item.id;
|
||||
fire.async(changes);
|
||||
}
|
||||
});
|
||||
if (Object.keys(changes).length > 0) {
|
||||
changes.id = item.id;
|
||||
fire.async(changes);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
let registerPromise = DownloadMap.getDownloadList().then(() => {
|
||||
DownloadMap.on("change", handler);
|
||||
});
|
||||
return () => {
|
||||
registerPromise.then(() => {
|
||||
DownloadMap.off("change", handler);
|
||||
let registerPromise = DownloadMap.getDownloadList().then(() => {
|
||||
DownloadMap.on("change", handler);
|
||||
});
|
||||
};
|
||||
return () => {
|
||||
registerPromise.then(() => {
|
||||
DownloadMap.off("change", handler);
|
||||
});
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onCreated: new EventManager(context, "downloads.onCreated", fire => {
|
||||
const handler = (what, item) => {
|
||||
fire.async(item.serialize());
|
||||
};
|
||||
let registerPromise = DownloadMap.getDownloadList().then(() => {
|
||||
DownloadMap.on("create", handler);
|
||||
});
|
||||
return () => {
|
||||
registerPromise.then(() => {
|
||||
DownloadMap.off("create", handler);
|
||||
onCreated: new EventManager({
|
||||
context,
|
||||
name: "downloads.onCreated",
|
||||
register: fire => {
|
||||
const handler = (what, item) => {
|
||||
fire.async(item.serialize());
|
||||
};
|
||||
let registerPromise = DownloadMap.getDownloadList().then(() => {
|
||||
DownloadMap.on("create", handler);
|
||||
});
|
||||
};
|
||||
return () => {
|
||||
registerPromise.then(() => {
|
||||
DownloadMap.off("create", handler);
|
||||
});
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onErased: new EventManager(context, "downloads.onErased", fire => {
|
||||
const handler = (what, item) => {
|
||||
fire.async(item.id);
|
||||
};
|
||||
let registerPromise = DownloadMap.getDownloadList().then(() => {
|
||||
DownloadMap.on("erase", handler);
|
||||
});
|
||||
return () => {
|
||||
registerPromise.then(() => {
|
||||
DownloadMap.off("erase", handler);
|
||||
onErased: new EventManager({
|
||||
context,
|
||||
name: "downloads.onErased",
|
||||
register: fire => {
|
||||
const handler = (what, item) => {
|
||||
fire.async(item.id);
|
||||
};
|
||||
let registerPromise = DownloadMap.getDownloadList().then(() => {
|
||||
DownloadMap.on("erase", handler);
|
||||
});
|
||||
};
|
||||
return () => {
|
||||
registerPromise.then(() => {
|
||||
DownloadMap.off("erase", handler);
|
||||
});
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onDeterminingFilename: ignoreEvent(context, "downloads.onDeterminingFilename"),
|
||||
|
|
|
@ -70,15 +70,19 @@ this.idle = class extends ExtensionAPI {
|
|||
setDetectionInterval: function(detectionIntervalInSeconds) {
|
||||
setDetectionInterval(extension, context, detectionIntervalInSeconds);
|
||||
},
|
||||
onStateChanged: new EventManager(context, "idle.onStateChanged", fire => {
|
||||
let listener = (event, data) => {
|
||||
fire.sync(data);
|
||||
};
|
||||
onStateChanged: new EventManager({
|
||||
context,
|
||||
name: "idle.onStateChanged",
|
||||
register: fire => {
|
||||
let listener = (event, data) => {
|
||||
fire.sync(data);
|
||||
};
|
||||
|
||||
getIdleObserver(extension, context).on("stateChanged", listener);
|
||||
return () => {
|
||||
getIdleObserver(extension, context).off("stateChanged", listener);
|
||||
};
|
||||
getIdleObserver(extension, context).on("stateChanged", listener);
|
||||
return () => {
|
||||
getIdleObserver(extension, context).off("stateChanged", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -230,48 +230,64 @@ this.management = class extends ExtensionAPI {
|
|||
addon.userDisabled = !enabled;
|
||||
},
|
||||
|
||||
onDisabled: new EventManager(context, "management.onDisabled", fire => {
|
||||
let listener = (event, data) => {
|
||||
fire.async(data);
|
||||
};
|
||||
onDisabled: new EventManager({
|
||||
context,
|
||||
name: "management.onDisabled",
|
||||
register: fire => {
|
||||
let listener = (event, data) => {
|
||||
fire.async(data);
|
||||
};
|
||||
|
||||
getManagementListener(extension, context).on("onDisabled", listener);
|
||||
return () => {
|
||||
getManagementListener(extension, context).off("onDisabled", listener);
|
||||
};
|
||||
getManagementListener(extension, context).on("onDisabled", listener);
|
||||
return () => {
|
||||
getManagementListener(extension, context).off("onDisabled", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onEnabled: new EventManager(context, "management.onEnabled", fire => {
|
||||
let listener = (event, data) => {
|
||||
fire.async(data);
|
||||
};
|
||||
onEnabled: new EventManager({
|
||||
context,
|
||||
name: "management.onEnabled",
|
||||
register: fire => {
|
||||
let listener = (event, data) => {
|
||||
fire.async(data);
|
||||
};
|
||||
|
||||
getManagementListener(extension, context).on("onEnabled", listener);
|
||||
return () => {
|
||||
getManagementListener(extension, context).off("onEnabled", listener);
|
||||
};
|
||||
getManagementListener(extension, context).on("onEnabled", listener);
|
||||
return () => {
|
||||
getManagementListener(extension, context).off("onEnabled", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onInstalled: new EventManager(context, "management.onInstalled", fire => {
|
||||
let listener = (event, data) => {
|
||||
fire.async(data);
|
||||
};
|
||||
onInstalled: new EventManager({
|
||||
context,
|
||||
name: "management.onInstalled",
|
||||
register: fire => {
|
||||
let listener = (event, data) => {
|
||||
fire.async(data);
|
||||
};
|
||||
|
||||
getManagementListener(extension, context).on("onInstalled", listener);
|
||||
return () => {
|
||||
getManagementListener(extension, context).off("onInstalled", listener);
|
||||
};
|
||||
getManagementListener(extension, context).on("onInstalled", listener);
|
||||
return () => {
|
||||
getManagementListener(extension, context).off("onInstalled", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onUninstalled: new EventManager(context, "management.onUninstalled", fire => {
|
||||
let listener = (event, data) => {
|
||||
fire.async(data);
|
||||
};
|
||||
onUninstalled: new EventManager({
|
||||
context,
|
||||
name: "management.onUninstalled",
|
||||
register: fire => {
|
||||
let listener = (event, data) => {
|
||||
fire.async(data);
|
||||
};
|
||||
|
||||
getManagementListener(extension, context).on("onUninstalled", listener);
|
||||
return () => {
|
||||
getManagementListener(extension, context).off("onUninstalled", listener);
|
||||
};
|
||||
getManagementListener(extension, context).on("onUninstalled", listener);
|
||||
return () => {
|
||||
getManagementListener(extension, context).off("onUninstalled", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
},
|
||||
|
|
|
@ -117,38 +117,50 @@ this.notifications = class extends ExtensionAPI {
|
|||
return Promise.resolve(result);
|
||||
},
|
||||
|
||||
onClosed: new EventManager(context, "notifications.onClosed", fire => {
|
||||
let listener = (event, notificationId) => {
|
||||
// TODO Bug 1413188, Support the byUser argument.
|
||||
fire.async(notificationId, true);
|
||||
};
|
||||
onClosed: new EventManager({
|
||||
context,
|
||||
name: "notifications.onClosed",
|
||||
register: fire => {
|
||||
let listener = (event, notificationId) => {
|
||||
// TODO Bug 1413188, Support the byUser argument.
|
||||
fire.async(notificationId, true);
|
||||
};
|
||||
|
||||
notificationsMap.on("closed", listener);
|
||||
return () => {
|
||||
notificationsMap.off("closed", listener);
|
||||
};
|
||||
notificationsMap.on("closed", listener);
|
||||
return () => {
|
||||
notificationsMap.off("closed", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onClicked: new EventManager(context, "notifications.onClicked", fire => {
|
||||
let listener = (event, notificationId) => {
|
||||
fire.async(notificationId, true);
|
||||
};
|
||||
onClicked: new EventManager({
|
||||
context,
|
||||
name: "notifications.onClicked",
|
||||
register: fire => {
|
||||
let listener = (event, notificationId) => {
|
||||
fire.async(notificationId, true);
|
||||
};
|
||||
|
||||
notificationsMap.on("clicked", listener);
|
||||
return () => {
|
||||
notificationsMap.off("clicked", listener);
|
||||
};
|
||||
notificationsMap.on("clicked", listener);
|
||||
return () => {
|
||||
notificationsMap.off("clicked", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onShown: new EventManager(context, "notifications.onShown", fire => {
|
||||
let listener = (event, notificationId) => {
|
||||
fire.async(notificationId, true);
|
||||
};
|
||||
onShown: new EventManager({
|
||||
context,
|
||||
name: "notifications.onShown",
|
||||
register: fire => {
|
||||
let listener = (event, notificationId) => {
|
||||
fire.async(notificationId, true);
|
||||
};
|
||||
|
||||
notificationsMap.on("shown", listener);
|
||||
return () => {
|
||||
notificationsMap.off("shown", listener);
|
||||
};
|
||||
notificationsMap.on("shown", listener);
|
||||
return () => {
|
||||
notificationsMap.off("shown", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
// TODO Bug 1190681, implement button support.
|
||||
|
|
|
@ -43,7 +43,7 @@ class ProxyFilterEventManager extends EventManager {
|
|||
};
|
||||
};
|
||||
|
||||
super(context, name, register);
|
||||
super({context, name, register});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,14 +61,18 @@ this.proxy = class extends ExtensionAPI {
|
|||
getAPI(context) {
|
||||
let {extension} = context;
|
||||
|
||||
let onError = new EventManager(context, "proxy.onError", fire => {
|
||||
let listener = (name, error) => {
|
||||
fire.async(error);
|
||||
};
|
||||
extension.on("proxy-error", listener);
|
||||
return () => {
|
||||
extension.off("proxy-error", listener);
|
||||
};
|
||||
let onError = new EventManager({
|
||||
context,
|
||||
name: "proxy.onError",
|
||||
register: fire => {
|
||||
let listener = (name, error) => {
|
||||
fire.async(error);
|
||||
};
|
||||
extension.on("proxy-error", listener);
|
||||
return () => {
|
||||
extension.off("proxy-error", listener);
|
||||
};
|
||||
},
|
||||
}).api();
|
||||
|
||||
return {
|
||||
|
|
|
@ -16,64 +16,76 @@ this.runtime = class extends ExtensionAPI {
|
|||
let {extension} = context;
|
||||
return {
|
||||
runtime: {
|
||||
onStartup: new EventManager(context, "runtime.onStartup", fire => {
|
||||
if (context.incognito) {
|
||||
// This event should not fire if we are operating in a private profile.
|
||||
return () => {};
|
||||
}
|
||||
let listener = () => {
|
||||
if (extension.startupReason === "APP_STARTUP") {
|
||||
fire.sync();
|
||||
onStartup: new EventManager({
|
||||
context,
|
||||
name: "runtime.onStartup",
|
||||
register: fire => {
|
||||
if (context.incognito) {
|
||||
// This event should not fire if we are operating in a private profile.
|
||||
return () => {};
|
||||
}
|
||||
};
|
||||
extension.on("startup", listener);
|
||||
return () => {
|
||||
extension.off("startup", listener);
|
||||
};
|
||||
}).api(),
|
||||
|
||||
onInstalled: new EventManager(context, "runtime.onInstalled", fire => {
|
||||
let temporary = !!extension.addonData.temporarilyInstalled;
|
||||
|
||||
let listener = () => {
|
||||
switch (extension.startupReason) {
|
||||
case "APP_STARTUP":
|
||||
if (AddonManagerPrivate.browserUpdated) {
|
||||
fire.sync({reason: "browser_update", temporary});
|
||||
}
|
||||
break;
|
||||
case "ADDON_INSTALL":
|
||||
fire.sync({reason: "install", temporary});
|
||||
break;
|
||||
case "ADDON_UPGRADE":
|
||||
fire.sync({
|
||||
reason: "update",
|
||||
previousVersion: extension.addonData.oldVersion,
|
||||
temporary,
|
||||
});
|
||||
break;
|
||||
}
|
||||
};
|
||||
extension.on("startup", listener);
|
||||
return () => {
|
||||
extension.off("startup", listener);
|
||||
};
|
||||
}).api(),
|
||||
|
||||
onUpdateAvailable: new EventManager(context, "runtime.onUpdateAvailable", fire => {
|
||||
let instanceID = extension.addonData.instanceID;
|
||||
AddonManager.addUpgradeListener(instanceID, upgrade => {
|
||||
extension.upgrade = upgrade;
|
||||
let details = {
|
||||
version: upgrade.version,
|
||||
let listener = () => {
|
||||
if (extension.startupReason === "APP_STARTUP") {
|
||||
fire.sync();
|
||||
}
|
||||
};
|
||||
fire.sync(details);
|
||||
});
|
||||
return () => {
|
||||
AddonManager.removeUpgradeListener(instanceID).catch(e => {
|
||||
// This can happen if we try this after shutdown is complete.
|
||||
extension.on("startup", listener);
|
||||
return () => {
|
||||
extension.off("startup", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onInstalled: new EventManager({
|
||||
context,
|
||||
name: "runtime.onInstalled",
|
||||
register: fire => {
|
||||
let temporary = !!extension.addonData.temporarilyInstalled;
|
||||
|
||||
let listener = () => {
|
||||
switch (extension.startupReason) {
|
||||
case "APP_STARTUP":
|
||||
if (AddonManagerPrivate.browserUpdated) {
|
||||
fire.sync({reason: "browser_update", temporary});
|
||||
}
|
||||
break;
|
||||
case "ADDON_INSTALL":
|
||||
fire.sync({reason: "install", temporary});
|
||||
break;
|
||||
case "ADDON_UPGRADE":
|
||||
fire.sync({
|
||||
reason: "update",
|
||||
previousVersion: extension.addonData.oldVersion,
|
||||
temporary,
|
||||
});
|
||||
break;
|
||||
}
|
||||
};
|
||||
extension.on("startup", listener);
|
||||
return () => {
|
||||
extension.off("startup", listener);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
onUpdateAvailable: new EventManager({
|
||||
context,
|
||||
name: "runtime.onUpdateAvailable",
|
||||
register: fire => {
|
||||
let instanceID = extension.addonData.instanceID;
|
||||
AddonManager.addUpgradeListener(instanceID, upgrade => {
|
||||
extension.upgrade = upgrade;
|
||||
let details = {
|
||||
version: upgrade.version,
|
||||
};
|
||||
fire.sync(details);
|
||||
});
|
||||
};
|
||||
return () => {
|
||||
AddonManager.removeUpgradeListener(instanceID).catch(e => {
|
||||
// This can happen if we try this after shutdown is complete.
|
||||
});
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
|
||||
reload: () => {
|
||||
|
|
|
@ -89,20 +89,24 @@ this.storage = class extends ExtensionAPI {
|
|||
},
|
||||
},
|
||||
|
||||
onChanged: new EventManager(context, "storage.onChanged", fire => {
|
||||
let listenerLocal = changes => {
|
||||
fire.raw(changes, "local");
|
||||
};
|
||||
let listenerSync = changes => {
|
||||
fire.async(changes, "sync");
|
||||
};
|
||||
onChanged: new EventManager({
|
||||
context,
|
||||
name: "storage.onChanged",
|
||||
register: fire => {
|
||||
let listenerLocal = changes => {
|
||||
fire.raw(changes, "local");
|
||||
};
|
||||
let listenerSync = changes => {
|
||||
fire.async(changes, "sync");
|
||||
};
|
||||
|
||||
ExtensionStorage.addOnChangedListener(extension.id, listenerLocal);
|
||||
extensionStorageSync.addOnChangedListener(extension, listenerSync, context);
|
||||
return () => {
|
||||
ExtensionStorage.removeOnChangedListener(extension.id, listenerLocal);
|
||||
extensionStorageSync.removeOnChangedListener(extension, listenerSync);
|
||||
};
|
||||
ExtensionStorage.addOnChangedListener(extension.id, listenerLocal);
|
||||
extensionStorageSync.addOnChangedListener(extension, listenerSync, context);
|
||||
return () => {
|
||||
ExtensionStorage.removeOnChangedListener(extension.id, listenerLocal);
|
||||
extensionStorageSync.removeOnChangedListener(extension, listenerSync);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -411,19 +411,23 @@ this.theme = class extends ExtensionAPI {
|
|||
|
||||
Theme.unload(windowId);
|
||||
},
|
||||
onUpdated: new EventManager(context, "theme.onUpdated", fire => {
|
||||
let callback = (event, theme, windowId) => {
|
||||
if (windowId) {
|
||||
fire.async({theme, windowId});
|
||||
} else {
|
||||
fire.async({theme});
|
||||
}
|
||||
};
|
||||
onUpdated: new EventManager({
|
||||
context,
|
||||
name: "theme.onUpdated",
|
||||
register: fire => {
|
||||
let callback = (event, theme, windowId) => {
|
||||
if (windowId) {
|
||||
fire.async({theme, windowId});
|
||||
} else {
|
||||
fire.async({theme});
|
||||
}
|
||||
};
|
||||
|
||||
onUpdatedEmitter.on("theme-updated", callback);
|
||||
return () => {
|
||||
onUpdatedEmitter.off("theme-updated", callback);
|
||||
};
|
||||
onUpdatedEmitter.on("theme-updated", callback);
|
||||
return () => {
|
||||
onUpdatedEmitter.off("theme-updated", callback);
|
||||
};
|
||||
},
|
||||
}).api(),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -21,12 +21,6 @@ ChromeUtils.import("resource://gre/modules/ExtensionCommon.jsm");
|
|||
|
||||
global.EventEmitter = ExtensionUtils.EventEmitter;
|
||||
global.EventManager = ExtensionCommon.EventManager;
|
||||
global.InputEventManager = class extends EventManager {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.inputHandling = true;
|
||||
}
|
||||
};
|
||||
|
||||
/* globals DEFAULT_STORE, PRIVATE_STORE, CONTAINER_STORE */
|
||||
|
||||
|
|
|
@ -90,61 +90,61 @@ const fillTransitionProperties = (eventName, src, dst) => {
|
|||
};
|
||||
|
||||
// Similar to WebRequestEventManager but for WebNavigation.
|
||||
function WebNavigationEventManager(context, eventName) {
|
||||
let name = `webNavigation.${eventName}`;
|
||||
let register = (fire, urlFilters) => {
|
||||
// Don't create a MatchURLFilters instance if the listener does not include any filter.
|
||||
let filters = urlFilters ? new MatchURLFilters(urlFilters.url) : null;
|
||||
class WebNavigationEventManager extends EventManager {
|
||||
constructor(context, eventName) {
|
||||
let name = `webNavigation.${eventName}`;
|
||||
let register = (fire, urlFilters) => {
|
||||
// Don't create a MatchURLFilters instance if the listener does not include any filter.
|
||||
let filters = urlFilters ? new MatchURLFilters(urlFilters.url) : null;
|
||||
|
||||
let listener = data => {
|
||||
if (!data.browser) {
|
||||
return;
|
||||
}
|
||||
let listener = data => {
|
||||
if (!data.browser) {
|
||||
return;
|
||||
}
|
||||
|
||||
let data2 = {
|
||||
url: data.url,
|
||||
timeStamp: Date.now(),
|
||||
let data2 = {
|
||||
url: data.url,
|
||||
timeStamp: Date.now(),
|
||||
};
|
||||
|
||||
if (eventName == "onErrorOccurred") {
|
||||
data2.error = data.error;
|
||||
}
|
||||
|
||||
if (data.frameId != undefined) {
|
||||
data2.frameId = data.frameId;
|
||||
data2.parentFrameId = data.parentFrameId;
|
||||
}
|
||||
|
||||
if (data.sourceFrameId != undefined) {
|
||||
data2.sourceFrameId = data.sourceFrameId;
|
||||
}
|
||||
|
||||
// Fills in tabId typically.
|
||||
Object.assign(data2, tabTracker.getBrowserData(data.browser));
|
||||
if (data2.tabId < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.sourceTabBrowser) {
|
||||
data2.sourceTabId = tabTracker.getBrowserData(data.sourceTabBrowser).tabId;
|
||||
}
|
||||
|
||||
fillTransitionProperties(eventName, data, data2);
|
||||
|
||||
fire.async(data2);
|
||||
};
|
||||
|
||||
if (eventName == "onErrorOccurred") {
|
||||
data2.error = data.error;
|
||||
}
|
||||
|
||||
if (data.frameId != undefined) {
|
||||
data2.frameId = data.frameId;
|
||||
data2.parentFrameId = data.parentFrameId;
|
||||
}
|
||||
|
||||
if (data.sourceFrameId != undefined) {
|
||||
data2.sourceFrameId = data.sourceFrameId;
|
||||
}
|
||||
|
||||
// Fills in tabId typically.
|
||||
Object.assign(data2, tabTracker.getBrowserData(data.browser));
|
||||
if (data2.tabId < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.sourceTabBrowser) {
|
||||
data2.sourceTabId = tabTracker.getBrowserData(data.sourceTabBrowser).tabId;
|
||||
}
|
||||
|
||||
fillTransitionProperties(eventName, data, data2);
|
||||
|
||||
fire.async(data2);
|
||||
WebNavigation[eventName].addListener(listener, filters);
|
||||
return () => {
|
||||
WebNavigation[eventName].removeListener(listener);
|
||||
};
|
||||
};
|
||||
|
||||
WebNavigation[eventName].addListener(listener, filters);
|
||||
return () => {
|
||||
WebNavigation[eventName].removeListener(listener);
|
||||
};
|
||||
};
|
||||
|
||||
return EventManager.call(this, context, name, register);
|
||||
super({context, name, register});
|
||||
}
|
||||
}
|
||||
|
||||
WebNavigationEventManager.prototype = Object.create(EventManager.prototype);
|
||||
|
||||
const convertGetFrameResult = (tabId, data) => {
|
||||
return {
|
||||
errorOccurred: data.errorOccurred,
|
||||
|
@ -161,8 +161,12 @@ this.webNavigation = class extends ExtensionAPI {
|
|||
|
||||
return {
|
||||
webNavigation: {
|
||||
onTabReplaced: new EventManager(context, "webNavigation.onTabReplaced", fire => {
|
||||
return () => {};
|
||||
onTabReplaced: new EventManager({
|
||||
context,
|
||||
name: "webNavigation.onTabReplaced",
|
||||
register: fire => {
|
||||
return () => {};
|
||||
},
|
||||
}).api(),
|
||||
onBeforeNavigate: new WebNavigationEventManager(context, "onBeforeNavigate").api(),
|
||||
onCommitted: new WebNavigationEventManager(context, "onCommitted").api(),
|
||||
|
|
|
@ -81,24 +81,22 @@ function WebRequestEventManager(context, eventName) {
|
|||
};
|
||||
};
|
||||
|
||||
return EventManager.call(this, context, name, register);
|
||||
return new EventManager({context, name, register}).api();
|
||||
}
|
||||
|
||||
WebRequestEventManager.prototype = Object.create(EventManager.prototype);
|
||||
|
||||
this.webRequest = class extends ExtensionAPI {
|
||||
getAPI(context) {
|
||||
return {
|
||||
webRequest: {
|
||||
onBeforeRequest: new WebRequestEventManager(context, "onBeforeRequest").api(),
|
||||
onBeforeSendHeaders: new WebRequestEventManager(context, "onBeforeSendHeaders").api(),
|
||||
onSendHeaders: new WebRequestEventManager(context, "onSendHeaders").api(),
|
||||
onHeadersReceived: new WebRequestEventManager(context, "onHeadersReceived").api(),
|
||||
onAuthRequired: new WebRequestEventManager(context, "onAuthRequired").api(),
|
||||
onBeforeRedirect: new WebRequestEventManager(context, "onBeforeRedirect").api(),
|
||||
onResponseStarted: new WebRequestEventManager(context, "onResponseStarted").api(),
|
||||
onErrorOccurred: new WebRequestEventManager(context, "onErrorOccurred").api(),
|
||||
onCompleted: new WebRequestEventManager(context, "onCompleted").api(),
|
||||
onBeforeRequest: WebRequestEventManager(context, "onBeforeRequest"),
|
||||
onBeforeSendHeaders: WebRequestEventManager(context, "onBeforeSendHeaders"),
|
||||
onSendHeaders: WebRequestEventManager(context, "onSendHeaders"),
|
||||
onHeadersReceived: WebRequestEventManager(context, "onHeadersReceived"),
|
||||
onAuthRequired: WebRequestEventManager(context, "onAuthRequired"),
|
||||
onBeforeRedirect: WebRequestEventManager(context, "onBeforeRedirect"),
|
||||
onResponseStarted: WebRequestEventManager(context, "onResponseStarted"),
|
||||
onErrorOccurred: WebRequestEventManager(context, "onErrorOccurred"),
|
||||
onCompleted: WebRequestEventManager(context, "onCompleted"),
|
||||
handlerBehaviorChanged: function() {
|
||||
// TODO: Flush all caches.
|
||||
},
|
||||
|
|
|
@ -65,11 +65,15 @@ add_task(async function test_post_unload_listeners() {
|
|||
let context = new StubContext();
|
||||
|
||||
let fire;
|
||||
let manager = new EventManager(context, "EventManager", _fire => {
|
||||
fire = () => {
|
||||
_fire.async();
|
||||
};
|
||||
return () => {};
|
||||
let manager = new EventManager({
|
||||
context,
|
||||
name: "EventManager",
|
||||
register: _fire => {
|
||||
fire = () => {
|
||||
_fire.async();
|
||||
};
|
||||
return () => {};
|
||||
},
|
||||
});
|
||||
|
||||
let fail = event => {
|
||||
|
|
Загрузка…
Ссылка в новой задаче