зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1220136 - WebExtensions support chrome.management.uninstallSelf, r=kmag
MozReview-Commit-ID: L80ynbuFr7U --HG-- extra : rebase_source : e01716a71bf84fbbb9e8640463f74df66fbb8540
This commit is contained in:
Родитель
59f394c4bb
Коммит
0fbf9fe3b6
|
@ -2,8 +2,24 @@
|
|||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "strBundle", function() {
|
||||
const stringSvc = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService);
|
||||
return stringSvc.createBundle("chrome://global/locale/extensions.properties");
|
||||
});
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
|
||||
"resource://gre/modules/AddonManager.jsm");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "promptService",
|
||||
"@mozilla.org/embedcomp/prompt-service;1",
|
||||
"nsIPromptService");
|
||||
|
||||
function _(key, ...args) {
|
||||
if (args.length) {
|
||||
return strBundle.formatStringFromName(key, args, args.length);
|
||||
}
|
||||
return strBundle.GetStringFromName(key);
|
||||
}
|
||||
|
||||
function installType(addon) {
|
||||
if (addon.temporarilyInstalled) {
|
||||
|
@ -52,11 +68,42 @@ extensions.registerSchemaAPI("management", "addon_parent", context => {
|
|||
}
|
||||
|
||||
resolve(extInfo);
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
uninstallSelf: function(options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (options && options.showConfirmDialog) {
|
||||
let message = _("uninstall.confirmation.message", extension.name);
|
||||
if (options.dialogMessage) {
|
||||
message = `${options.dialogMessage}\n${message}`;
|
||||
}
|
||||
let title = _("uninstall.confirmation.title", extension.name);
|
||||
let buttonFlags = promptService.BUTTON_POS_0 * promptService.BUTTON_TITLE_IS_STRING +
|
||||
promptService.BUTTON_POS_1 * promptService.BUTTON_TITLE_IS_STRING;
|
||||
let button0Title = _("uninstall.confirmation.button-0.label");
|
||||
let button1Title = _("uninstall.confirmation.button-1.label");
|
||||
let response = promptService.confirmEx(null, title, message, buttonFlags, button0Title, button1Title, null, null, {value: 0});
|
||||
if (response == 1) {
|
||||
return reject({message: "User cancelled uninstall of extension"});
|
||||
}
|
||||
}
|
||||
AddonManager.getAddonByID(extension.id, addon => {
|
||||
let canUninstall = Boolean(addon.permissions & AddonManager.PERM_CAN_UNINSTALL);
|
||||
if (!canUninstall) {
|
||||
return reject({message: "The add-on cannot be uninstalled"});
|
||||
}
|
||||
try {
|
||||
addon.uninstall();
|
||||
} catch (err) {
|
||||
return reject(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
|
@ -217,7 +217,6 @@
|
|||
{
|
||||
"name": "uninstallSelf",
|
||||
"type": "function",
|
||||
"unsupported": true,
|
||||
"description": "Uninstalls the calling extension. Note: This function can be used without requesting the 'management' permission in the manifest.",
|
||||
"async": "callback",
|
||||
"parameters": [
|
||||
|
@ -230,6 +229,11 @@
|
|||
"type": "boolean",
|
||||
"optional": true,
|
||||
"description": "Whether or not a confirm-uninstall dialog should prompt the user. Defaults to false."
|
||||
},
|
||||
"dialogMessage": {
|
||||
"type": "string",
|
||||
"optional": true,
|
||||
"description": "The message to display to a user when being asked to confirm removal of the extension."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
Cu.import("resource://gre/modules/AddonManager.jsm");
|
||||
Cu.import("resource://testing-common/AddonTestUtils.jsm");
|
||||
Cu.import("resource://testing-common/MockRegistrar.jsm");
|
||||
|
||||
const {promiseAddonByID} = AddonTestUtils;
|
||||
const id = "uninstall_self_test@tests.mozilla.com";
|
||||
|
||||
const manifest = {
|
||||
applications: {
|
||||
gecko: {
|
||||
id,
|
||||
},
|
||||
},
|
||||
name: "test extension name",
|
||||
version: "1.0",
|
||||
};
|
||||
|
||||
const waitForUninstalled = new Promise(resolve => {
|
||||
const listener = {
|
||||
onUninstalled: (addon) => {
|
||||
equal(addon.id, id, "The expected add-on has been uninstalled");
|
||||
AddonManager.getAddonByID(addon.id, checkedAddon => {
|
||||
equal(checkedAddon, null, "Add-on no longer exists");
|
||||
AddonManager.removeAddonListener(listener);
|
||||
resolve();
|
||||
});
|
||||
},
|
||||
};
|
||||
AddonManager.addAddonListener(listener);
|
||||
});
|
||||
|
||||
let promptService = {
|
||||
_response: null,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPromptService]),
|
||||
confirmEx: function(...args) {
|
||||
this._confirmExArgs = args;
|
||||
return this._response;
|
||||
},
|
||||
};
|
||||
|
||||
add_task(function* setup() {
|
||||
let fakePromptService = MockRegistrar.register("@mozilla.org/embedcomp/prompt-service;1", promptService);
|
||||
do_register_cleanup(() => {
|
||||
MockRegistrar.unregister(fakePromptService);
|
||||
});
|
||||
yield ExtensionTestUtils.startAddonManager();
|
||||
});
|
||||
|
||||
add_task(function* test_management_uninstall_no_prompt() {
|
||||
function background() {
|
||||
browser.test.onMessage.addListener(msg => {
|
||||
browser.management.uninstallSelf();
|
||||
});
|
||||
}
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest,
|
||||
background,
|
||||
useAddonManager: "temporary",
|
||||
});
|
||||
|
||||
yield extension.startup();
|
||||
let addon = yield promiseAddonByID(id);
|
||||
notEqual(addon, null, "Add-on is installed");
|
||||
extension.sendMessage("uninstall");
|
||||
yield waitForUninstalled;
|
||||
yield extension.markUnloaded();
|
||||
});
|
||||
|
||||
add_task(function* test_management_uninstall_prompt_uninstall() {
|
||||
promptService._response = 0;
|
||||
|
||||
function background() {
|
||||
browser.test.onMessage.addListener(msg => {
|
||||
browser.management.uninstallSelf({showConfirmDialog: true});
|
||||
});
|
||||
}
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest,
|
||||
background,
|
||||
useAddonManager: "temporary",
|
||||
});
|
||||
|
||||
yield extension.startup();
|
||||
let addon = yield promiseAddonByID(id);
|
||||
notEqual(addon, null, "Add-on is installed");
|
||||
extension.sendMessage("uninstall");
|
||||
yield waitForUninstalled;
|
||||
yield extension.markUnloaded();
|
||||
|
||||
// Test localization strings
|
||||
equal(promptService._confirmExArgs[1], `Uninstall ${manifest.name}`);
|
||||
equal(promptService._confirmExArgs[2],
|
||||
`The extension “${manifest.name}” is requesting to be uninstalled. What would you like to do?`);
|
||||
equal(promptService._confirmExArgs[4], "Uninstall");
|
||||
equal(promptService._confirmExArgs[5], "Keep Installed");
|
||||
});
|
||||
|
||||
add_task(function* test_management_uninstall_prompt_keep() {
|
||||
promptService._response = 1;
|
||||
|
||||
function background() {
|
||||
browser.test.onMessage.addListener(msg => {
|
||||
browser.management.uninstallSelf({showConfirmDialog: true}).then(() => {
|
||||
browser.test.fail("uninstallSelf rejects when user declines uninstall");
|
||||
}, error => {
|
||||
browser.test.assertEq("User cancelled uninstall of extension",
|
||||
error.message,
|
||||
"Expected rejection when user declines uninstall");
|
||||
browser.test.sendMessage("uninstall-rejected");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest,
|
||||
background,
|
||||
useAddonManager: "temporary",
|
||||
});
|
||||
|
||||
yield extension.startup();
|
||||
let addon = yield promiseAddonByID(id);
|
||||
notEqual(addon, null, "Add-on is installed");
|
||||
extension.sendMessage("uninstall");
|
||||
yield extension.awaitMessage("uninstall-rejected");
|
||||
addon = yield promiseAddonByID(id);
|
||||
notEqual(addon, null, "Add-on remains installed");
|
||||
extension.unload();
|
||||
});
|
|
@ -38,6 +38,7 @@ skip-if = release_build
|
|||
[test_ext_json_parser.js]
|
||||
[test_ext_localStorage.js]
|
||||
[test_ext_management.js]
|
||||
[test_ext_management_uninstall_self.js]
|
||||
[test_ext_manifest_content_security_policy.js]
|
||||
[test_ext_manifest_incognito.js]
|
||||
[test_ext_manifest_minimum_chrome_version.js]
|
||||
|
|
|
@ -18,3 +18,12 @@ csp.error.missing-source = ‘%1$S’ must include the source %2$S
|
|||
|
||||
#LOCALIZATION NOTE (csp.error.illegal-host-wildcard) %2$S a protocol name, such as "http", which appears as "http:", as it would in a URL.
|
||||
csp.error.illegal-host-wildcard = %2$S: wildcard sources in ‘%1$S’ directives must include at least one non-generic sub-domain (e.g., *.example.com rather than *.com)
|
||||
|
||||
#LOCALIZATION NOTE (uninstall.confirmation.title) %S is the name of the extension which is about to be uninstalled.
|
||||
uninstall.confirmation.title = Uninstall %S
|
||||
|
||||
#LOCALIZATION NOTE (uninstall.confirmation.message) %S is the name of the extension which is about to be uninstalled.
|
||||
uninstall.confirmation.message = The extension “%S” is requesting to be uninstalled. What would you like to do?
|
||||
|
||||
uninstall.confirmation.button-0.label = Uninstall
|
||||
uninstall.confirmation.button-1.label = Keep Installed
|
||||
|
|
Загрузка…
Ссылка в новой задаче