Bug 1350522: Part 6 - Cleanup per-api-instance state logic. r=aswan

MozReview-Commit-ID: 5ixBA34fvFf

--HG--
extra : source : 650808cfe044339ceae30dbd79ef931330f78049
extra : histedit_source : 30316d0b7321bdceaf93fa9dde096579b6251354
This commit is contained in:
Kris Maglione 2017-03-25 11:36:56 -07:00
Родитель 2c9d3185dc
Коммит 56c459b23c
9 изменённых файлов: 82 добавлений и 130 удалений

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

@ -470,25 +470,24 @@ this.browserAction = class extends ExtensionAPI {
let {extension} = this;
let {manifest} = extension;
let browserAction = new BrowserAction(manifest.browser_action, extension);
browserAction.build();
browserActionMap.set(extension, browserAction);
this.browserAction = new BrowserAction(manifest.browser_action, extension);
this.browserAction.build();
browserActionMap.set(extension, this.browserAction);
}
onShutdown(reason) {
let {extension} = this;
if (browserActionMap.has(extension)) {
browserActionMap.get(extension).shutdown();
browserActionMap.delete(extension);
}
browserActionMap.delete(extension);
this.browserAction.shutdown();
}
getAPI(context) {
let {extension} = context;
let {tabManager} = extension;
let {browserAction} = this;
function getTab(tabId) {
if (tabId !== null) {
return tabTracker.getTab(tabId);
@ -502,20 +501,20 @@ this.browserAction = class extends ExtensionAPI {
let listener = () => {
fire.async(tabManager.convert(tabTracker.activeTab));
};
BrowserAction.for(extension).on("click", listener);
browserAction.on("click", listener);
return () => {
BrowserAction.for(extension).off("click", listener);
browserAction.off("click", listener);
};
}).api(),
enable: function(tabId) {
let tab = getTab(tabId);
BrowserAction.for(extension).setProperty(tab, "enabled", true);
browserAction.setProperty(tab, "enabled", true);
},
disable: function(tabId) {
let tab = getTab(tabId);
BrowserAction.for(extension).setProperty(tab, "enabled", false);
browserAction.setProperty(tab, "enabled", false);
},
setTitle: function(details) {
@ -526,13 +525,13 @@ this.browserAction = class extends ExtensionAPI {
if (tab && title == "") {
title = null;
}
BrowserAction.for(extension).setProperty(tab, "title", title);
browserAction.setProperty(tab, "title", title);
},
getTitle: function(details) {
let tab = getTab(details.tabId);
let title = BrowserAction.for(extension).getProperty(tab, "title");
let title = browserAction.getProperty(tab, "title");
return Promise.resolve(title);
},
@ -540,19 +539,19 @@ this.browserAction = class extends ExtensionAPI {
let tab = getTab(details.tabId);
let icon = IconDetails.normalize(details, extension, context);
BrowserAction.for(extension).setProperty(tab, "icon", icon);
browserAction.setProperty(tab, "icon", icon);
},
setBadgeText: function(details) {
let tab = getTab(details.tabId);
BrowserAction.for(extension).setProperty(tab, "badgeText", details.text);
browserAction.setProperty(tab, "badgeText", details.text);
},
getBadgeText: function(details) {
let tab = getTab(details.tabId);
let text = BrowserAction.for(extension).getProperty(tab, "badgeText");
let text = browserAction.getProperty(tab, "badgeText");
return Promise.resolve(text);
},
@ -565,13 +564,13 @@ this.browserAction = class extends ExtensionAPI {
// For internal consistency, we currently resolve both relative to the
// calling context.
let url = details.popup && context.uri.resolve(details.popup);
BrowserAction.for(extension).setProperty(tab, "popup", url);
browserAction.setProperty(tab, "popup", url);
},
getPopup: function(details) {
let tab = getTab(details.tabId);
let popup = BrowserAction.for(extension).getProperty(tab, "popup");
let popup = browserAction.getProperty(tab, "popup");
return Promise.resolve(popup);
},
@ -582,13 +581,13 @@ this.browserAction = class extends ExtensionAPI {
let col = DOMUtils.colorToRGBA(color);
color = col && [col.r, col.g, col.b, Math.round(col.a * 255)];
}
BrowserAction.for(extension).setProperty(tab, "badgeBackgroundColor", color);
browserAction.setProperty(tab, "badgeBackgroundColor", color);
},
getBadgeBackgroundColor: function(details, callback) {
let tab = getTab(details.tabId);
let color = BrowserAction.for(extension).getProperty(tab, "badgeBackgroundColor");
let color = browserAction.getProperty(tab, "badgeBackgroundColor");
return Promise.resolve(color || [0xd9, 0, 0, 255]);
},
},

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

@ -9,9 +9,6 @@ var {
var XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
// WeakMap[Extension -> CommandList]
let commandsMap = new WeakMap();
function CommandList(manifest, extension) {
this.extension = extension;
this.id = makeWidgetId(extension.id);
@ -225,25 +222,18 @@ this.commands = class extends ExtensionAPI {
let {extension} = this;
let {manifest} = extension;
commandsMap.set(extension, new CommandList(manifest, extension));
this.commandList = new CommandList(manifest, extension);
}
onShutdown(reason) {
let {extension} = this;
let commandsList = commandsMap.get(extension);
if (commandsList) {
commandsList.unregister();
commandsMap.delete(extension);
}
this.commandList.unregister();
}
getAPI(context) {
let {extension} = context;
return {
commands: {
getAll() {
let commands = commandsMap.get(extension).commands;
getAll: () => {
let commands = this.commandList.commands;
return Promise.resolve(Array.from(commands, ([name, command]) => {
return ({
name,
@ -256,9 +246,9 @@ this.commands = class extends ExtensionAPI {
let listener = (eventName, commandName) => {
fire.async(commandName);
};
commandsMap.get(extension).on("command", listener);
this.commandList.on("command", listener);
return () => {
commandsMap.get(extension).off("command", listener);
this.commandList.off("command", listener);
};
}).api(),
},

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

@ -8,9 +8,6 @@ var {
SingletonEventManager,
} = ExtensionUtils;
// WeakMap[extension -> keyword]
let gKeywordMap = new WeakMap();
this.omnibox = class extends ExtensionAPI {
onManifestEntry(entryName) {
let {extension} = this;
@ -20,31 +17,24 @@ this.omnibox = class extends ExtensionAPI {
try {
// This will throw if the keyword is already registered.
ExtensionSearchHandler.registerKeyword(keyword, extension);
gKeywordMap.set(extension, keyword);
this.keyword = keyword;
} catch (e) {
extension.manifestError(e.message);
}
}
onShutdown(reason) {
let {extension} = this;
let keyword = gKeywordMap.get(extension);
if (keyword) {
ExtensionSearchHandler.unregisterKeyword(keyword);
gKeywordMap.delete(extension);
}
ExtensionSearchHandler.unregisterKeyword(this.keyword);
}
getAPI(context) {
let {extension} = context;
return {
omnibox: {
setDefaultSuggestion(suggestion) {
let keyword = gKeywordMap.get(extension);
setDefaultSuggestion: (suggestion) => {
try {
// This will throw if the keyword failed to register.
ExtensionSearchHandler.setDefaultSuggestion(keyword, suggestion);
ExtensionSearchHandler.setDefaultSuggestion(this.keyword, suggestion);
} catch (e) {
return Promise.reject(e.message);
}
@ -82,10 +72,9 @@ this.omnibox = class extends ExtensionAPI {
},
omnibox_internal: {
addSuggestions(id, suggestions) {
let keyword = gKeywordMap.get(extension);
addSuggestions: (id, suggestions) => {
try {
ExtensionSearchHandler.addSuggestions(keyword, id, suggestions);
ExtensionSearchHandler.addSuggestions(this.keyword, id, suggestions);
} catch (e) {
// Silently fail because the extension developer can not know for sure if the user
// has already invalidated the callback when asynchronously providing suggestions.

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

@ -234,23 +234,20 @@ this.pageAction = class extends ExtensionAPI {
let {extension} = this;
let {manifest} = extension;
let pageAction = new PageAction(manifest.page_action, extension);
pageActionMap.set(extension, pageAction);
this.pageAction = new PageAction(manifest.page_action, extension);
pageActionMap.set(extension, this.pageAction);
}
onShutdown(reason) {
let {extension} = this;
if (pageActionMap.has(extension)) {
pageActionMap.get(extension).shutdown();
pageActionMap.delete(extension);
}
pageActionMap.delete(this.extension);
this.pageAction.shutdown();
}
getAPI(context) {
let {extension} = context;
const {tabManager} = extension;
const {pageAction} = this;
return {
pageAction: {
@ -258,7 +255,6 @@ this.pageAction = class extends ExtensionAPI {
let listener = (evt, tab) => {
fire.async(tabManager.convert(tab));
};
let pageAction = PageAction.for(extension);
pageAction.on("click", listener);
return () => {
@ -268,25 +264,25 @@ this.pageAction = class extends ExtensionAPI {
show(tabId) {
let tab = tabTracker.getTab(tabId);
PageAction.for(extension).setProperty(tab, "show", true);
pageAction.setProperty(tab, "show", true);
},
hide(tabId) {
let tab = tabTracker.getTab(tabId);
PageAction.for(extension).setProperty(tab, "show", false);
pageAction.setProperty(tab, "show", false);
},
setTitle(details) {
let tab = tabTracker.getTab(details.tabId);
// Clear the tab-specific title when given a null string.
PageAction.for(extension).setProperty(tab, "title", details.title || null);
pageAction.setProperty(tab, "title", details.title || null);
},
getTitle(details) {
let tab = tabTracker.getTab(details.tabId);
let title = PageAction.for(extension).getProperty(tab, "title");
let title = pageAction.getProperty(tab, "title");
return Promise.resolve(title);
},
@ -294,7 +290,7 @@ this.pageAction = class extends ExtensionAPI {
let tab = tabTracker.getTab(details.tabId);
let icon = IconDetails.normalize(details, extension, context);
PageAction.for(extension).setProperty(tab, "icon", icon);
pageAction.setProperty(tab, "icon", icon);
},
setPopup(details) {
@ -306,13 +302,13 @@ this.pageAction = class extends ExtensionAPI {
// For internal consistency, we currently resolve both relative to the
// calling context.
let url = details.popup && context.uri.resolve(details.popup);
PageAction.for(extension).setProperty(tab, "popup", url);
pageAction.setProperty(tab, "popup", url);
},
getPopup(details) {
let tab = tabTracker.getTab(details.tabId);
let popup = PageAction.for(extension).getProperty(tab, "popup");
let popup = pageAction.getProperty(tab, "popup");
return Promise.resolve(popup);
},
},

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

@ -291,25 +291,22 @@ this.sidebarAction = class extends ExtensionAPI {
let {extension} = this;
let {manifest} = extension;
let sidebarAction = new SidebarAction(manifest.sidebar_action, extension);
sidebarActionMap.set(extension, sidebarAction);
this.sidebarAction = new SidebarAction(manifest.sidebar_action, extension);
sidebarActionMap.set(extension, this.sidebarAction);
}
onShutdown(reason) {
let {extension} = this;
if (sidebarActionMap.has(extension)) {
// Don't remove everything on app shutdown so session restore can handle
// restoring open sidebars.
if (extension.shutdownReason !== "APP_SHUTDOWN") {
sidebarActionMap.get(extension).shutdown();
}
sidebarActionMap.delete(extension);
// Don't remove everything on app shutdown so session restore can handle
// restoring open sidebars.
if (reason !== "APP_SHUTDOWN") {
this.sidebarAction.shutdown();
}
sidebarActionMap.delete(this.extension);
}
getAPI(context) {
let {extension} = context;
const {sidebarAction} = this;
function getTab(tabId) {
if (tabId !== null) {
@ -328,13 +325,13 @@ this.sidebarAction = class extends ExtensionAPI {
if (nativeTab && title === "") {
title = null;
}
SidebarAction.for(extension).setProperty(nativeTab, "title", title);
sidebarAction.setProperty(nativeTab, "title", title);
},
getTitle(details) {
let nativeTab = getTab(details.tabId);
let title = SidebarAction.for(extension).getProperty(nativeTab, "title");
let title = sidebarAction.getProperty(nativeTab, "title");
return Promise.resolve(title);
},
@ -342,7 +339,7 @@ this.sidebarAction = class extends ExtensionAPI {
let nativeTab = getTab(details.tabId);
let icon = IconDetails.normalize(details, extension, context);
SidebarAction.for(extension).setProperty(nativeTab, "icon", icon);
sidebarAction.setProperty(nativeTab, "icon", icon);
},
async setPanel(details) {
@ -358,13 +355,13 @@ this.sidebarAction = class extends ExtensionAPI {
throw new ExtensionError("Invalid url for sidebar panel.");
}
SidebarAction.for(extension).setProperty(nativeTab, "panel", url);
sidebarAction.setProperty(nativeTab, "panel", url);
},
getPanel(details) {
let nativeTab = getTab(details.tabId);
let panel = SidebarAction.for(extension).getProperty(nativeTab, "panel");
let panel = sidebarAction.getProperty(nativeTab, "panel");
return Promise.resolve(panel);
},
},

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

@ -12,9 +12,6 @@ var {
promiseExtensionViewLoaded,
} = ExtensionParent;
// WeakMap[Extension -> BackgroundPage]
let backgroundPagesMap = new WeakMap();
// Responsible for the background_page section of the manifest.
class BackgroundPage extends HiddenExtensionPage {
constructor(extension, options) {
@ -79,21 +76,14 @@ class BackgroundPage extends HiddenExtensionPage {
this.backgroundPage = class extends ExtensionAPI {
onManifestEntry(entryName) {
let {extension} = this;
let {manifest} = extension;
let {manifest} = this.extension;
let bgPage = new BackgroundPage(extension, manifest.background);
this.bgPage = new BackgroundPage(this.extension, manifest.background);
backgroundPagesMap.set(extension, bgPage);
return bgPage.build();
return this.bgPage.build();
}
onShutdown() {
let {extension} = this;
if (backgroundPagesMap.has(extension)) {
backgroundPagesMap.get(extension).shutdown();
backgroundPagesMap.delete(extension);
}
this.bgPage.shutdown();
}
};

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

@ -22,6 +22,7 @@ this.geolocation = class extends ExtensionAPI {
onShutdown() {
let {extension} = this;
if (extension.hasPermission("geolocation") &&
Services.perms.testPermission(extension.principal.URI, "geo") == Services.perms.ALLOW_ACTION) {
Services.perms.remove(extension.principal.URI, "geo");

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

@ -10,8 +10,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "protocolService",
"nsIExternalProtocolService");
Cu.importGlobalProperties(["URL"]);
const handlers = new WeakMap();
function hasHandlerApp(handlerConfig) {
let protoInfo = protocolService.getProtocolHandlerInfo(handlerConfig.protocol);
let appHandlers = protoInfo.possibleApplicationHandlers;
@ -44,16 +42,17 @@ this.protocolHandlers = class extends ExtensionAPI {
protoInfo.possibleApplicationHandlers.appendElement(handler, false);
handlerService.store(protoInfo);
}
handlers.set(extension, manifest.protocol_handlers);
}
onShutdown() {
onShutdown(shutdownReason) {
let {extension} = this;
let {manifest} = extension;
if (!handlers.has(extension) || extension.shutdownReason === "APP_SHUTDOWN") {
if (shutdownReason === "APP_SHUTDOWN") {
return;
}
for (let handlerConfig of handlers.get(extension)) {
for (let handlerConfig of manifest.protocol_handlers) {
let protoInfo = protocolService.getProtocolHandlerInfo(handlerConfig.protocol);
let appHandlers = protoInfo.possibleApplicationHandlers;
for (let i = 0; i < appHandlers.length; i++) {
@ -70,6 +69,5 @@ this.protocolHandlers = class extends ExtensionAPI {
}
}
}
handlers.delete(extension);
}
};

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

@ -11,9 +11,6 @@ XPCOMUtils.defineLazyGetter(this, "gThemesEnabled", () => {
return Preferences.get("extensions.webextensions.themes.enabled");
});
// WeakMap[Extension -> Theme]
let themeMap = new WeakMap();
const ICONS = Preferences.get("extensions.webextensions.themes.icons.buttons", "").split(",");
/** Class representing a theme. */
@ -249,45 +246,40 @@ this.theme = class extends ExtensionAPI {
let {extension} = this;
let {manifest} = extension;
let theme = new Theme(extension.baseURI, extension.logger);
theme.load(manifest.theme);
themeMap.set(extension, theme);
}
onShutdown() {
let {extension} = this;
let theme = themeMap.get(extension);
if (!theme) {
// We won't have a theme if themes are disabled.
if (!gThemesEnabled) {
// Return early if themes are disabled.
return;
}
theme.unload();
this.theme = new Theme(extension.baseURI, extension.logger);
this.theme.load(manifest.theme);
}
onShutdown() {
if (this.theme) {
this.theme.unload();
}
}
getAPI(context) {
let {extension} = context;
return {
theme: {
update(details) {
update: (details) => {
if (!gThemesEnabled) {
// Return early if themes are disabled.
return;
}
let theme = themeMap.get(extension);
if (!theme) {
if (!this.theme) {
// WebExtensions using the Theme API will not have a theme defined
// in the manifest. Therefore, we need to initialize the theme the
// first time browser.theme.update is called.
theme = new Theme(extension.baseURI, extension.logger);
themeMap.set(extension, theme);
this.theme = new Theme(extension.baseURI, extension.logger);
}
theme.load(details);
this.theme.load(details);
},
},
};