mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1156826 - Implement browser.runtime.setUninstallURL(). r=kmag
This commit is contained in:
parent
047c72c007
commit
e40f02b580
10
browser/components/extensions/ext-desktop-runtime.js
Normal file
10
browser/components/extensions/ext-desktop-runtime.js
Normal file
@ -0,0 +1,10 @@
|
||||
"use strict";
|
||||
|
||||
/* eslint-disable mozilla/balanced-listeners */
|
||||
extensions.on("uninstall", (msg, extension) => {
|
||||
if (extension.uninstallURL) {
|
||||
let browser = Services.wm.getMostRecentWindow("navigator:browser").gBrowser;
|
||||
browser.addTab(extension.uninstallURL, { relatedToCurrent: true });
|
||||
}
|
||||
});
|
||||
|
@ -8,6 +8,7 @@ browser.jar:
|
||||
content/browser/ext-contextMenus.js
|
||||
content/browser/ext-browserAction.js
|
||||
content/browser/ext-pageAction.js
|
||||
content/browser/ext-desktop-runtime.js
|
||||
content/browser/ext-tabs.js
|
||||
content/browser/ext-windows.js
|
||||
content/browser/ext-bookmarks.js
|
||||
|
@ -21,6 +21,7 @@ support-files =
|
||||
[browser_ext_contextMenus.js]
|
||||
[browser_ext_getViews.js]
|
||||
[browser_ext_lastError.js]
|
||||
[browser_ext_runtime_setUninstallURL.js]
|
||||
[browser_ext_tabs_audio.js]
|
||||
[browser_ext_tabs_captureVisibleTab.js]
|
||||
[browser_ext_tabs_executeScript.js]
|
||||
|
@ -0,0 +1,114 @@
|
||||
"use strict";
|
||||
|
||||
let { AddonManager } = Components.utils.import("resource://gre/modules/AddonManager.jsm", {});
|
||||
let { Extension } = Components.utils.import("resource://gre/modules/Extension.jsm", {});
|
||||
|
||||
function install(url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
AddonManager.getInstallForURL(url, (install) => {
|
||||
install.addListener({
|
||||
onInstallEnded: (i, addon) => resolve(addon),
|
||||
onInstallFailed: () => reject(),
|
||||
});
|
||||
install.install();
|
||||
}, "application/x-xpinstall");
|
||||
});
|
||||
}
|
||||
|
||||
function* makeAndInstallXPI(id, backgroundScript, loadedURL) {
|
||||
let xpi = Extension.generateXPI(id, {
|
||||
background: "(" + backgroundScript.toString() + ")()",
|
||||
});
|
||||
SimpleTest.registerCleanupFunction(function cleanupXPI() {
|
||||
Services.obs.notifyObservers(xpi, "flush-cache-entry", null);
|
||||
xpi.remove(false);
|
||||
});
|
||||
|
||||
let loadPromise = BrowserTestUtils.waitForNewTab(gBrowser, loadedURL);
|
||||
|
||||
let fileURI = Services.io.newFileURI(xpi);
|
||||
info(`installing ${fileURI.spec}`);
|
||||
let addon = yield install(fileURI.spec);
|
||||
info("installed");
|
||||
|
||||
// A WebExtension is started asynchronously, we have our test extension
|
||||
// open a new tab to signal that the background script has executed.
|
||||
let loadTab = yield loadPromise;
|
||||
yield BrowserTestUtils.removeTab(loadTab);
|
||||
|
||||
return addon;
|
||||
}
|
||||
|
||||
|
||||
add_task(function* test_setuninstallurl_badargs() {
|
||||
function backgroundScript() {
|
||||
let promises = [
|
||||
browser.runtime.setUninstallURL("this is not a url")
|
||||
.then(() => {
|
||||
browser.test.notifyFail("setUninstallURL should have failed with bad url");
|
||||
})
|
||||
.catch(error => {
|
||||
browser.test.assertTrue(/Invalid URL/.test(error.message), "error message indicates malformed url");
|
||||
}),
|
||||
|
||||
browser.runtime.setUninstallURL("file:///etc/passwd")
|
||||
.then(() => {
|
||||
browser.test.notifyFail("setUninstallURL should have failed with non-http[s] url");
|
||||
})
|
||||
.catch(error => {
|
||||
browser.test.assertTrue(/must have the scheme http or https/.test(error.message), "error message indicates bad scheme");
|
||||
}),
|
||||
];
|
||||
|
||||
Promise.all(promises)
|
||||
.then(() => browser.test.notifyPass("setUninstallURL bad params"));
|
||||
}
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
background: "(" + backgroundScript.toString() + ")()",
|
||||
});
|
||||
yield extension.startup();
|
||||
yield extension.awaitFinish();
|
||||
yield extension.unload();
|
||||
});
|
||||
|
||||
// Test the documented behavior of setUninstallURL() that passing an
|
||||
// empty string is equivalent to not setting an uninstall URL
|
||||
// (i.e., no new tab is opened upon uninstall)
|
||||
add_task(function* test_setuninstall_empty_url() {
|
||||
function backgroundScript() {
|
||||
browser.runtime.setUninstallURL("")
|
||||
.then(() => browser.tabs.create({ url: "http://example.com/addon_loaded" }));
|
||||
}
|
||||
|
||||
let addon = yield makeAndInstallXPI("test_uinstallurl2@tests.mozilla.org",
|
||||
backgroundScript,
|
||||
"http://example.com/addon_loaded");
|
||||
|
||||
addon.uninstall(true);
|
||||
info("uninstalled");
|
||||
|
||||
// no need to explicitly check for the absence of a new tab,
|
||||
// BrowserTestUtils will eventually complain if one is opened.
|
||||
});
|
||||
|
||||
add_task(function* test_setuninstallurl() {
|
||||
function backgroundScript() {
|
||||
browser.runtime.setUninstallURL("http://example.com/addon_uninstalled")
|
||||
.then(() => browser.tabs.create({ url: "http://example.com/addon_loaded" }));
|
||||
}
|
||||
|
||||
let addon = yield makeAndInstallXPI("test_uinstallurl@tests.mozilla.org",
|
||||
backgroundScript,
|
||||
"http://example.com/addon_loaded");
|
||||
|
||||
// look for a new tab with the uninstall url.
|
||||
let uninstallPromise = BrowserTestUtils.waitForNewTab(gBrowser, "http://example.com/addon_uninstalled");
|
||||
|
||||
addon.uninstall(true);
|
||||
info("uninstalled");
|
||||
|
||||
let uninstalledTab = yield uninstallPromise;
|
||||
isnot(uninstalledTab, null, "opened tab with uninstall url");
|
||||
yield BrowserTestUtils.removeTab(uninstalledTab);
|
||||
});
|
@ -551,6 +551,7 @@ BrowserGlue.prototype = {
|
||||
ExtensionManagement.registerScript("chrome://browser/content/ext-browserAction.js");
|
||||
ExtensionManagement.registerScript("chrome://browser/content/ext-pageAction.js");
|
||||
ExtensionManagement.registerScript("chrome://browser/content/ext-contextMenus.js");
|
||||
ExtensionManagement.registerScript("chrome://browser/content/ext-desktop-runtime.js");
|
||||
ExtensionManagement.registerScript("chrome://browser/content/ext-tabs.js");
|
||||
ExtensionManagement.registerScript("chrome://browser/content/ext-windows.js");
|
||||
ExtensionManagement.registerScript("chrome://browser/content/ext-bookmarks.js");
|
||||
|
@ -52,6 +52,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "AppConstants",
|
||||
"resource://gre/modules/AppConstants.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "MessageChannel",
|
||||
"resource://gre/modules/MessageChannel.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
|
||||
"resource://gre/modules/AddonManager.jsm");
|
||||
|
||||
Cu.import("resource://gre/modules/ExtensionManagement.jsm");
|
||||
|
||||
@ -311,6 +313,21 @@ ExtensionPage = class extends BaseContext {
|
||||
}
|
||||
};
|
||||
|
||||
// For extensions that have called setUninstallURL(), send an event
|
||||
// so the browser can display the URL.
|
||||
let UninstallObserver = {
|
||||
init: function() {
|
||||
AddonManager.addAddonListener(this);
|
||||
},
|
||||
|
||||
onUninstalling: function(addon) {
|
||||
let extension = GlobalManager.extensionMap.get(addon.id);
|
||||
if (extension) {
|
||||
Management.emit("uninstall", extension);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Responsible for loading extension APIs into the right globals.
|
||||
GlobalManager = {
|
||||
// Number of extensions currently enabled.
|
||||
@ -326,6 +343,7 @@ GlobalManager = {
|
||||
init(extension) {
|
||||
if (this.count == 0) {
|
||||
Services.obs.addObserver(this, "content-document-global-created", false);
|
||||
UninstallObserver.init();
|
||||
}
|
||||
this.count++;
|
||||
|
||||
@ -806,6 +824,8 @@ this.Extension = function(addonData) {
|
||||
this.hasShutdown = false;
|
||||
this.onShutdown = new Set();
|
||||
|
||||
this.uninstallURL = null;
|
||||
|
||||
this.permissions = new Set();
|
||||
this.whiteListedHosts = null;
|
||||
this.webAccessibleResources = new Set();
|
||||
|
@ -85,6 +85,26 @@ extensions.registerSchemaAPI("runtime", null, (extension, context) => {
|
||||
let info = {os, arch};
|
||||
return Promise.resolve(info);
|
||||
},
|
||||
|
||||
setUninstallURL: function(url) {
|
||||
if (url.length == 0) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
let uri;
|
||||
try {
|
||||
uri = NetUtil.newURI(url);
|
||||
} catch (e) {
|
||||
return Promise.reject({ message: `Invalid URL: ${JSON.stringify(url)}` });
|
||||
}
|
||||
|
||||
if (uri.scheme != "http" && uri.scheme != "https") {
|
||||
return Promise.reject({ message: "url must have the scheme http or https" });
|
||||
}
|
||||
|
||||
extension.uninstallURL = url;
|
||||
return Promise.resolve();
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
@ -175,7 +175,6 @@
|
||||
},
|
||||
{
|
||||
"name": "setUninstallURL",
|
||||
"unsupported": true,
|
||||
"type": "function",
|
||||
"description": "Sets the URL to be visited upon uninstallation. This may be used to clean up server-side data, do analytics, and implement surveys. Maximum 255 characters.",
|
||||
"async": "callback",
|
||||
|
Loading…
Reference in New Issue
Block a user