2017-01-03 21:55:25 +03:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
var EXPORTED_SYMBOLS = ["ExtensionsUI"];
|
|
|
|
|
2019-01-17 21:18:31 +03:00
|
|
|
const { XPCOMUtils } = ChromeUtils.import(
|
|
|
|
"resource://gre/modules/XPCOMUtils.jsm"
|
|
|
|
);
|
|
|
|
const { EventEmitter } = ChromeUtils.import(
|
|
|
|
"resource://gre/modules/EventEmitter.jsm"
|
|
|
|
);
|
2017-01-19 05:16:19 +03:00
|
|
|
|
2018-04-11 13:05:56 +03:00
|
|
|
XPCOMUtils.defineLazyModuleGetters(this, {
|
|
|
|
AddonManager: "resource://gre/modules/AddonManager.jsm",
|
|
|
|
AddonManagerPrivate: "resource://gre/modules/AddonManager.jsm",
|
2018-09-19 19:43:11 +03:00
|
|
|
AMTelemetry: "resource://gre/modules/AddonManager.jsm",
|
2018-04-11 13:05:56 +03:00
|
|
|
AppMenuNotifications: "resource://gre/modules/AppMenuNotifications.jsm",
|
|
|
|
ExtensionData: "resource://gre/modules/Extension.jsm",
|
2019-02-27 23:05:38 +03:00
|
|
|
ExtensionPermissions: "resource://gre/modules/ExtensionPermissions.jsm",
|
2018-04-11 13:05:56 +03:00
|
|
|
Services: "resource://gre/modules/Services.jsm",
|
|
|
|
});
|
2017-01-19 05:16:19 +03:00
|
|
|
|
|
|
|
XPCOMUtils.defineLazyPreferenceGetter(
|
|
|
|
this,
|
|
|
|
"WEBEXT_PERMISSION_PROMPTS",
|
|
|
|
"extensions.webextPermissionPrompts",
|
|
|
|
false
|
|
|
|
);
|
2019-07-05 10:55:19 +03:00
|
|
|
|
2017-01-20 21:28:47 +03:00
|
|
|
const DEFAULT_EXTENSION_ICON =
|
|
|
|
"chrome://mozapps/skin/extensions/extensionGeneric.svg";
|
2017-01-03 21:55:25 +03:00
|
|
|
|
2017-02-08 23:09:49 +03:00
|
|
|
const BROWSER_PROPERTIES = "chrome://browser/locale/browser.properties";
|
2017-02-23 19:41:17 +03:00
|
|
|
const BRAND_PROPERTIES = "chrome://branding/locale/brand.properties";
|
2017-02-08 23:09:49 +03:00
|
|
|
|
2017-01-03 21:55:25 +03:00
|
|
|
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
|
|
|
|
2018-04-08 06:38:21 +03:00
|
|
|
function getTabBrowser(browser) {
|
2018-05-22 02:58:23 +03:00
|
|
|
while (browser.ownerGlobal.docShell.itemType !== Ci.nsIDocShell.typeChrome) {
|
|
|
|
browser = browser.ownerGlobal.docShell.chromeEventHandler;
|
2018-04-08 06:38:21 +03:00
|
|
|
}
|
2020-02-11 19:08:59 +03:00
|
|
|
if (browser.getAttribute("webextension-view-type") == "popup") {
|
|
|
|
browser = browser.ownerGlobal.gBrowser.selectedBrowser;
|
|
|
|
}
|
2018-04-08 06:38:21 +03:00
|
|
|
return { browser, window: browser.ownerGlobal };
|
|
|
|
}
|
|
|
|
|
2017-01-03 21:55:25 +03:00
|
|
|
var ExtensionsUI = {
|
2017-01-19 05:16:19 +03:00
|
|
|
sideloaded: new Set(),
|
2017-01-20 06:28:08 +03:00
|
|
|
updates: new Set(),
|
2017-02-16 02:40:56 +03:00
|
|
|
sideloadListener: null,
|
2017-02-28 20:08:49 +03:00
|
|
|
histogram: null,
|
2017-01-19 05:16:19 +03:00
|
|
|
|
2018-03-18 03:42:51 +03:00
|
|
|
pendingNotifications: new WeakMap(),
|
|
|
|
|
2017-04-16 00:09:41 +03:00
|
|
|
async init() {
|
2017-02-28 20:08:49 +03:00
|
|
|
this.histogram = Services.telemetry.getHistogramById(
|
|
|
|
"EXTENSION_INSTALL_PROMPT_RESULT"
|
|
|
|
);
|
|
|
|
|
2017-04-15 00:39:22 +03:00
|
|
|
Services.obs.addObserver(this, "webextension-permission-prompt");
|
|
|
|
Services.obs.addObserver(this, "webextension-update-permissions");
|
|
|
|
Services.obs.addObserver(this, "webextension-install-notify");
|
|
|
|
Services.obs.addObserver(this, "webextension-optional-permission-prompt");
|
2017-09-08 03:38:55 +03:00
|
|
|
Services.obs.addObserver(this, "webextension-defaultsearch-prompt");
|
2017-01-19 05:16:19 +03:00
|
|
|
|
2017-07-12 00:30:23 +03:00
|
|
|
await Services.wm.getMostRecentWindow("navigator:browser")
|
|
|
|
.delayedStartupPromise;
|
2017-04-16 00:09:41 +03:00
|
|
|
|
2017-01-19 05:16:19 +03:00
|
|
|
this._checkForSideloaded();
|
|
|
|
},
|
|
|
|
|
2017-05-10 22:34:17 +03:00
|
|
|
async _checkForSideloaded() {
|
|
|
|
let sideloaded = await AddonManagerPrivate.getNewSideloads();
|
2017-05-10 22:34:17 +03:00
|
|
|
|
2017-05-10 22:34:17 +03:00
|
|
|
if (!sideloaded.length) {
|
|
|
|
// No new side-loads. We're done.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The ordering shouldn't matter, but tests depend on notifications
|
|
|
|
// happening in a specific order.
|
|
|
|
sideloaded.sort((a, b) => a.id.localeCompare(b.id));
|
|
|
|
|
|
|
|
if (WEBEXT_PERMISSION_PROMPTS) {
|
|
|
|
if (!this.sideloadListener) {
|
|
|
|
this.sideloadListener = {
|
|
|
|
onEnabled: addon => {
|
|
|
|
if (!this.sideloaded.has(addon)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.sideloaded.delete(addon);
|
2019-03-22 22:19:35 +03:00
|
|
|
this._updateNotifications();
|
2017-05-10 22:34:17 +03:00
|
|
|
|
|
|
|
if (this.sideloaded.size == 0) {
|
|
|
|
AddonManager.removeAddonListener(this.sideloadListener);
|
|
|
|
this.sideloadListener = null;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
};
|
|
|
|
AddonManager.addAddonListener(this.sideloadListener);
|
2017-01-19 05:16:19 +03:00
|
|
|
}
|
|
|
|
|
2017-05-10 22:34:17 +03:00
|
|
|
for (let addon of sideloaded) {
|
|
|
|
this.sideloaded.add(addon);
|
2017-05-10 22:34:17 +03:00
|
|
|
}
|
2017-05-15 20:38:33 +03:00
|
|
|
this._updateNotifications();
|
2017-05-10 22:34:17 +03:00
|
|
|
}
|
2017-01-19 05:16:19 +03:00
|
|
|
},
|
|
|
|
|
2017-05-15 20:38:33 +03:00
|
|
|
_updateNotifications() {
|
|
|
|
if (this.sideloaded.size + this.updates.size == 0) {
|
|
|
|
AppMenuNotifications.removeNotification("addon-alert");
|
|
|
|
} else {
|
|
|
|
AppMenuNotifications.showBadgeOnlyNotification("addon-alert");
|
|
|
|
}
|
|
|
|
this.emit("change");
|
|
|
|
},
|
|
|
|
|
2020-02-11 19:08:59 +03:00
|
|
|
showAddonsManager(tabbrowser, strings, icon, histkey) {
|
|
|
|
let global = tabbrowser.selectedBrowser.ownerGlobal;
|
2017-02-08 23:09:49 +03:00
|
|
|
return global
|
|
|
|
.BrowserOpenAddonsMgr("addons://list/extension")
|
|
|
|
.then(aomWin => {
|
2018-05-22 02:58:23 +03:00
|
|
|
let aomBrowser = aomWin.docShell.chromeEventHandler;
|
2017-02-28 20:08:49 +03:00
|
|
|
return this.showPermissionsPrompt(aomBrowser, strings, icon, histkey);
|
2017-01-20 06:28:08 +03:00
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2020-02-11 19:08:59 +03:00
|
|
|
showSideloaded(tabbrowser, addon) {
|
2017-01-20 06:28:08 +03:00
|
|
|
addon.markAsSeen();
|
|
|
|
this.sideloaded.delete(addon);
|
2017-05-15 20:38:33 +03:00
|
|
|
this._updateNotifications();
|
2017-01-20 06:28:08 +03:00
|
|
|
|
2017-02-08 23:09:49 +03:00
|
|
|
let strings = this._buildStrings({
|
2017-01-20 06:28:08 +03:00
|
|
|
addon,
|
|
|
|
permissions: addon.userPermissions,
|
|
|
|
type: "sideload",
|
2017-02-08 23:09:49 +03:00
|
|
|
});
|
2018-09-19 19:43:11 +03:00
|
|
|
|
|
|
|
AMTelemetry.recordManageEvent(addon, "sideload_prompt", {
|
2019-01-29 20:32:51 +03:00
|
|
|
num_strings: strings.msgs.length,
|
2018-09-19 19:43:11 +03:00
|
|
|
});
|
|
|
|
|
2020-02-11 19:08:59 +03:00
|
|
|
this.showAddonsManager(tabbrowser, strings, addon.iconURL, "sideload").then(
|
2018-05-13 04:51:32 +03:00
|
|
|
async answer => {
|
|
|
|
if (answer) {
|
|
|
|
await addon.enable();
|
2019-03-22 22:19:35 +03:00
|
|
|
|
|
|
|
this._updateNotifications();
|
|
|
|
|
2019-03-26 22:04:01 +03:00
|
|
|
// The user has just enabled a sideloaded extension, if the permission
|
|
|
|
// can be changed for the extension, show the post-install panel to
|
|
|
|
// give the user that opportunity.
|
|
|
|
if (
|
|
|
|
addon.permissions &
|
|
|
|
AddonManager.PERM_CAN_CHANGE_PRIVATEBROWSING_ACCESS
|
|
|
|
) {
|
2020-02-11 19:08:59 +03:00
|
|
|
this.showInstallNotification(tabbrowser.selectedBrowser, addon);
|
2018-05-13 04:51:32 +03:00
|
|
|
}
|
2019-07-05 10:55:19 +03:00
|
|
|
}
|
2018-05-13 04:51:32 +03:00
|
|
|
this.emit("sideload-response");
|
2017-02-28 20:08:49 +03:00
|
|
|
}
|
|
|
|
);
|
2017-01-20 06:28:08 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
showUpdate(browser, info) {
|
2019-01-29 20:32:51 +03:00
|
|
|
AMTelemetry.recordInstallEvent(info.install, {
|
|
|
|
step: "permissions_prompt",
|
|
|
|
num_strings: info.strings.msgs.length,
|
|
|
|
});
|
|
|
|
|
2017-02-28 20:08:49 +03:00
|
|
|
this.showAddonsManager(
|
|
|
|
browser,
|
|
|
|
info.strings,
|
|
|
|
info.addon.iconURL,
|
|
|
|
"update"
|
2017-02-08 23:09:49 +03:00
|
|
|
).then(answer => {
|
|
|
|
if (answer) {
|
|
|
|
info.resolve();
|
|
|
|
} else {
|
|
|
|
info.reject();
|
|
|
|
}
|
|
|
|
// At the moment, this prompt will re-appear next time we do an update
|
|
|
|
// check. See bug 1332360 for proposal to avoid this.
|
|
|
|
this.updates.delete(info);
|
2017-05-15 20:38:33 +03:00
|
|
|
this._updateNotifications();
|
2017-02-08 23:09:49 +03:00
|
|
|
});
|
2017-01-03 21:55:25 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
observe(subject, topic, data) {
|
|
|
|
if (topic == "webextension-permission-prompt") {
|
|
|
|
let { target, info } = subject.wrappedJSObject;
|
2017-01-06 03:35:07 +03:00
|
|
|
|
2018-04-08 06:38:21 +03:00
|
|
|
let { browser, window } = getTabBrowser(target);
|
|
|
|
|
2017-01-06 03:35:07 +03:00
|
|
|
// Dismiss the progress notification. Note that this is bad if
|
|
|
|
// there are multiple simultaneous installs happening, see
|
|
|
|
// bug 1329884 for a longer explanation.
|
2018-04-08 06:38:21 +03:00
|
|
|
let progressNotification = window.PopupNotifications.getNotification(
|
|
|
|
"addon-progress",
|
|
|
|
browser
|
|
|
|
);
|
2017-01-06 03:35:07 +03:00
|
|
|
if (progressNotification) {
|
|
|
|
progressNotification.remove();
|
|
|
|
}
|
|
|
|
|
2017-03-02 22:30:41 +03:00
|
|
|
info.unsigned =
|
|
|
|
info.addon.signedState <= AddonManager.SIGNEDSTATE_MISSING;
|
2017-05-10 22:34:17 +03:00
|
|
|
if (
|
|
|
|
info.unsigned &&
|
|
|
|
Cu.isInAutomation &&
|
|
|
|
Services.prefs.getBoolPref("extensions.ui.ignoreUnsigned", false)
|
|
|
|
) {
|
|
|
|
info.unsigned = false;
|
|
|
|
}
|
|
|
|
|
2017-02-17 00:31:50 +03:00
|
|
|
let strings = this._buildStrings(info);
|
2017-03-02 22:30:41 +03:00
|
|
|
|
2017-03-03 22:05:35 +03:00
|
|
|
// If this is an update with no promptable permissions, just apply it
|
2019-09-14 12:39:26 +03:00
|
|
|
if (info.type == "update" && !strings.msgs.length) {
|
2017-03-03 22:05:35 +03:00
|
|
|
info.resolve();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-03-02 22:30:41 +03:00
|
|
|
let icon = info.unsigned
|
|
|
|
? "chrome://browser/skin/warning.svg"
|
|
|
|
: info.icon;
|
|
|
|
|
2017-02-28 20:08:49 +03:00
|
|
|
let histkey;
|
|
|
|
if (info.type == "sideload") {
|
|
|
|
histkey = "sideload";
|
|
|
|
} else if (info.type == "update") {
|
|
|
|
histkey = "update";
|
|
|
|
} else if (info.source == "AMO") {
|
|
|
|
histkey = "installAmo";
|
|
|
|
} else if (info.source == "local") {
|
|
|
|
histkey = "installLocal";
|
|
|
|
} else {
|
|
|
|
histkey = "installWeb";
|
|
|
|
}
|
|
|
|
|
2019-01-29 20:32:51 +03:00
|
|
|
if (info.type == "sideload") {
|
|
|
|
AMTelemetry.recordManageEvent(info.addon, "sideload_prompt", {
|
|
|
|
num_strings: strings.msgs.length,
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
AMTelemetry.recordInstallEvent(info.install, {
|
|
|
|
step: "permissions_prompt",
|
|
|
|
num_strings: strings.msgs.length,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-04-08 06:38:21 +03:00
|
|
|
this.showPermissionsPrompt(browser, strings, icon, histkey).then(
|
2017-02-28 20:08:49 +03:00
|
|
|
answer => {
|
|
|
|
if (answer) {
|
|
|
|
info.resolve();
|
|
|
|
} else {
|
|
|
|
info.reject();
|
2019-07-05 10:55:19 +03:00
|
|
|
}
|
2017-02-28 20:08:49 +03:00
|
|
|
}
|
|
|
|
);
|
2017-01-20 06:28:08 +03:00
|
|
|
} else if (topic == "webextension-update-permissions") {
|
2017-02-08 23:09:49 +03:00
|
|
|
let info = subject.wrappedJSObject;
|
2017-02-17 00:41:27 +03:00
|
|
|
info.type = "update";
|
2017-02-08 23:09:49 +03:00
|
|
|
let strings = this._buildStrings(info);
|
|
|
|
|
|
|
|
// If we don't prompt for any new permissions, just apply it
|
2019-09-14 12:39:26 +03:00
|
|
|
if (!strings.msgs.length) {
|
2017-02-08 23:09:49 +03:00
|
|
|
info.resolve();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let update = {
|
|
|
|
strings,
|
2019-01-29 20:32:51 +03:00
|
|
|
permissions: info.permissions,
|
|
|
|
install: info.install,
|
2017-02-08 23:09:49 +03:00
|
|
|
addon: info.addon,
|
|
|
|
resolve: info.resolve,
|
|
|
|
reject: info.reject,
|
|
|
|
};
|
|
|
|
|
|
|
|
this.updates.add(update);
|
2017-05-15 20:38:33 +03:00
|
|
|
this._updateNotifications();
|
2017-01-20 21:28:47 +03:00
|
|
|
} else if (topic == "webextension-install-notify") {
|
2017-01-20 08:26:23 +03:00
|
|
|
let { target, addon, callback } = subject.wrappedJSObject;
|
|
|
|
this.showInstallNotification(target, addon).then(() => {
|
|
|
|
if (callback) {
|
|
|
|
callback();
|
|
|
|
}
|
|
|
|
});
|
2017-03-24 23:55:09 +03:00
|
|
|
} else if (topic == "webextension-optional-permission-prompt") {
|
|
|
|
let {
|
|
|
|
browser,
|
|
|
|
name,
|
|
|
|
icon,
|
|
|
|
permissions,
|
|
|
|
resolve,
|
|
|
|
} = subject.wrappedJSObject;
|
|
|
|
let strings = this._buildStrings({
|
|
|
|
type: "optional",
|
|
|
|
addon: { name },
|
|
|
|
permissions,
|
|
|
|
});
|
2017-04-11 05:12:23 +03:00
|
|
|
|
|
|
|
// If we don't have any promptable permissions, just proceed
|
2019-09-14 12:39:26 +03:00
|
|
|
if (!strings.msgs.length) {
|
2017-06-02 16:14:22 +03:00
|
|
|
resolve(true);
|
2017-04-11 05:12:23 +03:00
|
|
|
return;
|
|
|
|
}
|
2017-03-24 23:55:09 +03:00
|
|
|
resolve(this.showPermissionsPrompt(browser, strings, icon));
|
2017-09-08 03:38:55 +03:00
|
|
|
} else if (topic == "webextension-defaultsearch-prompt") {
|
2019-03-13 00:32:24 +03:00
|
|
|
let {
|
|
|
|
browser,
|
|
|
|
name,
|
|
|
|
icon,
|
|
|
|
respond,
|
|
|
|
currentEngine,
|
|
|
|
newEngine,
|
|
|
|
} = subject.wrappedJSObject;
|
2017-09-08 03:38:55 +03:00
|
|
|
|
|
|
|
let bundle = Services.strings.createBundle(BROWSER_PROPERTIES);
|
|
|
|
|
|
|
|
let strings = {};
|
|
|
|
strings.acceptText = bundle.GetStringFromName(
|
|
|
|
"webext.defaultSearchYes.label"
|
|
|
|
);
|
|
|
|
strings.acceptKey = bundle.GetStringFromName(
|
|
|
|
"webext.defaultSearchYes.accessKey"
|
|
|
|
);
|
|
|
|
strings.cancelText = bundle.GetStringFromName(
|
|
|
|
"webext.defaultSearchNo.label"
|
|
|
|
);
|
|
|
|
strings.cancelKey = bundle.GetStringFromName(
|
|
|
|
"webext.defaultSearchNo.accessKey"
|
|
|
|
);
|
2018-01-19 21:04:25 +03:00
|
|
|
strings.addonName = name;
|
2017-09-08 03:38:55 +03:00
|
|
|
strings.text = bundle.formatStringFromName(
|
|
|
|
"webext.defaultSearch.description",
|
2019-06-11 18:51:51 +03:00
|
|
|
["<>", currentEngine, newEngine]
|
|
|
|
);
|
2019-03-13 00:32:24 +03:00
|
|
|
|
|
|
|
this.showDefaultSearchPrompt(browser, strings, icon).then(respond);
|
2017-01-03 21:55:25 +03:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2017-02-08 23:09:49 +03:00
|
|
|
// Create a set of formatted strings for a permission prompt
|
|
|
|
_buildStrings(info) {
|
|
|
|
let bundle = Services.strings.createBundle(BROWSER_PROPERTIES);
|
2017-08-02 23:15:30 +03:00
|
|
|
let brandBundle = Services.strings.createBundle(BRAND_PROPERTIES);
|
|
|
|
let appName = brandBundle.GetStringFromName("brandShortName");
|
2018-01-19 21:04:25 +03:00
|
|
|
let info2 = Object.assign({ appName }, info);
|
2017-02-24 05:27:34 +03:00
|
|
|
|
2020-03-13 04:04:41 +03:00
|
|
|
let strings = ExtensionData.formatPermissionStrings(info2, bundle, {
|
|
|
|
collapseOrigins: true,
|
|
|
|
});
|
2018-01-19 21:04:25 +03:00
|
|
|
strings.addonName = info.addon.name;
|
2019-02-21 13:36:33 +03:00
|
|
|
strings.learnMore = bundle.GetStringFromName("webextPerms.learnMore");
|
2018-01-19 21:04:25 +03:00
|
|
|
return strings;
|
2017-02-08 23:09:49 +03:00
|
|
|
},
|
2017-01-03 21:55:25 +03:00
|
|
|
|
2018-04-08 06:38:21 +03:00
|
|
|
async showPermissionsPrompt(target, strings, icon, histkey) {
|
|
|
|
let { browser, window } = getTabBrowser(target);
|
2018-03-18 03:42:51 +03:00
|
|
|
|
2020-04-16 22:38:17 +03:00
|
|
|
// Wait for any pending prompts to complete before showing the next one.
|
2018-03-18 03:42:51 +03:00
|
|
|
let pending;
|
2020-04-16 22:38:17 +03:00
|
|
|
while ((pending = this.pendingNotifications.get(browser))) {
|
2018-03-18 03:42:51 +03:00
|
|
|
await pending;
|
|
|
|
}
|
2017-01-03 21:55:25 +03:00
|
|
|
|
2018-03-18 03:42:51 +03:00
|
|
|
let promise = new Promise(resolve => {
|
|
|
|
function eventCallback(topic) {
|
|
|
|
let doc = this.browser.ownerDocument;
|
|
|
|
if (topic == "showing") {
|
|
|
|
let textEl = doc.getElementById("addon-webext-perm-text");
|
|
|
|
textEl.textContent = strings.text;
|
|
|
|
textEl.hidden = !strings.text;
|
|
|
|
|
|
|
|
let listIntroEl = doc.getElementById("addon-webext-perm-intro");
|
|
|
|
listIntroEl.textContent = strings.listIntro;
|
2019-09-14 12:39:26 +03:00
|
|
|
listIntroEl.hidden = !strings.msgs.length;
|
2018-03-18 03:42:51 +03:00
|
|
|
|
2019-02-21 13:36:33 +03:00
|
|
|
let listInfoEl = doc.getElementById("addon-webext-perm-info");
|
|
|
|
listInfoEl.textContent = strings.learnMore;
|
|
|
|
listInfoEl.href =
|
|
|
|
Services.urlFormatter.formatURLPref("app.support.baseURL") +
|
|
|
|
"extension-permissions";
|
2019-09-14 12:39:26 +03:00
|
|
|
listInfoEl.hidden = !strings.msgs.length;
|
2019-02-21 13:36:33 +03:00
|
|
|
|
2018-03-18 03:42:51 +03:00
|
|
|
let list = doc.getElementById("addon-webext-perm-list");
|
|
|
|
while (list.firstChild) {
|
|
|
|
list.firstChild.remove();
|
|
|
|
}
|
|
|
|
|
|
|
|
for (let msg of strings.msgs) {
|
|
|
|
let item = doc.createElementNS(HTML_NS, "li");
|
|
|
|
item.textContent = msg;
|
|
|
|
list.appendChild(item);
|
|
|
|
}
|
|
|
|
} else if (topic == "swapping") {
|
|
|
|
return true;
|
2017-01-03 21:55:25 +03:00
|
|
|
}
|
2018-05-17 21:46:21 +03:00
|
|
|
if (topic == "removed") {
|
2018-03-18 03:42:51 +03:00
|
|
|
Services.tm.dispatchToMainThread(() => {
|
|
|
|
resolve(false);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return false;
|
2017-02-08 23:09:49 +03:00
|
|
|
}
|
|
|
|
|
2018-03-18 03:42:51 +03:00
|
|
|
let popupOptions = {
|
|
|
|
hideClose: true,
|
|
|
|
popupIconURL: icon || DEFAULT_EXTENSION_ICON,
|
|
|
|
persistent: true,
|
|
|
|
eventCallback,
|
|
|
|
name: strings.addonName,
|
2018-05-17 21:46:21 +03:00
|
|
|
removeOnDismissal: true,
|
2018-03-18 03:42:51 +03:00
|
|
|
};
|
2017-01-03 21:55:25 +03:00
|
|
|
|
2017-02-08 23:09:49 +03:00
|
|
|
let action = {
|
|
|
|
label: strings.acceptText,
|
|
|
|
accessKey: strings.acceptKey,
|
2017-02-28 20:08:49 +03:00
|
|
|
callback: () => {
|
2017-04-24 20:44:41 +03:00
|
|
|
if (histkey) {
|
|
|
|
this.histogram.add(histkey + "Accepted");
|
|
|
|
}
|
2017-02-28 20:08:49 +03:00
|
|
|
resolve(true);
|
|
|
|
},
|
2017-02-08 23:09:49 +03:00
|
|
|
};
|
|
|
|
let secondaryActions = [
|
|
|
|
{
|
|
|
|
label: strings.cancelText,
|
|
|
|
accessKey: strings.cancelKey,
|
2017-02-28 20:08:49 +03:00
|
|
|
callback: () => {
|
2017-04-24 20:44:41 +03:00
|
|
|
if (histkey) {
|
|
|
|
this.histogram.add(histkey + "Rejected");
|
|
|
|
}
|
2017-02-28 20:08:49 +03:00
|
|
|
resolve(false);
|
|
|
|
},
|
2017-02-08 23:09:49 +03:00
|
|
|
},
|
|
|
|
];
|
|
|
|
|
2018-04-08 06:38:21 +03:00
|
|
|
window.PopupNotifications.show(
|
|
|
|
browser,
|
|
|
|
"addon-webext-permissions",
|
|
|
|
strings.header,
|
|
|
|
"addons-notification-icon",
|
|
|
|
action,
|
|
|
|
secondaryActions,
|
|
|
|
popupOptions
|
|
|
|
);
|
2017-09-08 03:38:55 +03:00
|
|
|
});
|
2018-03-18 03:42:51 +03:00
|
|
|
|
2020-04-16 22:38:17 +03:00
|
|
|
this.pendingNotifications.set(browser, promise);
|
|
|
|
promise.finally(() => this.pendingNotifications.delete(browser));
|
2018-03-18 03:42:51 +03:00
|
|
|
return promise;
|
2017-09-08 03:38:55 +03:00
|
|
|
},
|
|
|
|
|
2018-04-08 06:38:21 +03:00
|
|
|
showDefaultSearchPrompt(target, strings, icon) {
|
2017-09-08 03:38:55 +03:00
|
|
|
return new Promise(resolve => {
|
|
|
|
let popupOptions = {
|
|
|
|
hideClose: true,
|
|
|
|
popupIconURL: icon || DEFAULT_EXTENSION_ICON,
|
2018-11-27 21:05:59 +03:00
|
|
|
persistent: true,
|
2017-09-08 03:38:55 +03:00
|
|
|
removeOnDismissal: true,
|
|
|
|
eventCallback(topic) {
|
2018-01-19 21:04:25 +03:00
|
|
|
if (topic == "removed") {
|
2017-09-08 03:38:55 +03:00
|
|
|
resolve(false);
|
|
|
|
}
|
2018-02-27 23:31:55 +03:00
|
|
|
},
|
|
|
|
name: strings.addonName,
|
2017-09-08 03:38:55 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
let action = {
|
|
|
|
label: strings.acceptText,
|
|
|
|
accessKey: strings.acceptKey,
|
|
|
|
disableHighlight: true,
|
|
|
|
callback: () => {
|
|
|
|
resolve(true);
|
|
|
|
},
|
|
|
|
};
|
|
|
|
let secondaryActions = [
|
|
|
|
{
|
|
|
|
label: strings.cancelText,
|
|
|
|
accessKey: strings.cancelKey,
|
|
|
|
callback: () => {
|
|
|
|
resolve(false);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
2018-04-08 06:38:21 +03:00
|
|
|
let { browser, window } = getTabBrowser(target);
|
|
|
|
window.PopupNotifications.show(
|
|
|
|
browser,
|
|
|
|
"addon-webext-defaultsearch",
|
|
|
|
strings.text,
|
|
|
|
"addons-notification-icon",
|
|
|
|
action,
|
|
|
|
secondaryActions,
|
|
|
|
popupOptions
|
|
|
|
);
|
2017-01-03 21:55:25 +03:00
|
|
|
});
|
|
|
|
},
|
2017-01-20 21:28:47 +03:00
|
|
|
|
2019-10-24 00:38:56 +03:00
|
|
|
async showInstallNotification(target, addon) {
|
2018-10-08 17:56:39 +03:00
|
|
|
let { window } = getTabBrowser(target);
|
2017-01-20 21:28:47 +03:00
|
|
|
|
2018-04-08 06:38:21 +03:00
|
|
|
let brandBundle = window.document.getElementById("bundle_brand");
|
2017-01-20 21:28:47 +03:00
|
|
|
let appName = brandBundle.getString("brandShortName");
|
2018-04-08 06:38:21 +03:00
|
|
|
let bundle = window.gNavigatorBundle;
|
2017-01-20 21:28:47 +03:00
|
|
|
|
2018-02-27 23:31:55 +03:00
|
|
|
let message = bundle.getFormattedString("addonPostInstall.message1", [
|
|
|
|
"<>",
|
|
|
|
appName,
|
|
|
|
]);
|
2019-10-24 00:38:56 +03:00
|
|
|
const permissionName = "internal:privateBrowsingAllowed";
|
|
|
|
const { permissions } = await ExtensionPermissions.get(addon.id);
|
|
|
|
const hasIncognito = permissions.includes(permissionName);
|
|
|
|
|
2017-01-20 08:26:23 +03:00
|
|
|
return new Promise(resolve => {
|
2019-02-27 23:05:38 +03:00
|
|
|
// Show or hide private permission ui based on the pref.
|
2019-03-14 21:31:07 +03:00
|
|
|
function setCheckbox(win) {
|
|
|
|
let checkbox = win.document.getElementById("addon-incognito-checkbox");
|
2019-10-24 00:38:56 +03:00
|
|
|
checkbox.checked = hasIncognito;
|
2019-03-26 21:31:57 +03:00
|
|
|
checkbox.hidden = !(
|
|
|
|
addon.permissions &
|
|
|
|
AddonManager.PERM_CAN_CHANGE_PRIVATEBROWSING_ACCESS
|
|
|
|
);
|
2019-03-14 21:31:07 +03:00
|
|
|
}
|
2019-02-27 23:05:38 +03:00
|
|
|
|
2019-03-14 21:31:07 +03:00
|
|
|
async function actionResolve(win) {
|
|
|
|
let checkbox = win.document.getElementById("addon-incognito-checkbox");
|
2019-10-24 00:38:56 +03:00
|
|
|
|
|
|
|
if (checkbox.checked == hasIncognito) {
|
|
|
|
resolve();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let incognitoPermission = {
|
|
|
|
permissions: [permissionName],
|
|
|
|
origins: [],
|
|
|
|
};
|
|
|
|
|
|
|
|
let value;
|
|
|
|
// The checkbox has been changed at this point, otherwise we would
|
|
|
|
// have exited early above.
|
2019-02-27 23:05:38 +03:00
|
|
|
if (checkbox.checked) {
|
2019-10-24 00:38:56 +03:00
|
|
|
await ExtensionPermissions.add(addon.id, incognitoPermission);
|
|
|
|
value = "on";
|
|
|
|
} else if (hasIncognito) {
|
|
|
|
await ExtensionPermissions.remove(addon.id, incognitoPermission);
|
|
|
|
value = "off";
|
|
|
|
}
|
|
|
|
if (value !== undefined) {
|
2019-03-06 16:59:31 +03:00
|
|
|
AMTelemetry.recordActionEvent({
|
|
|
|
addon,
|
|
|
|
object: "doorhanger",
|
|
|
|
action: "privateBrowsingAllowed",
|
|
|
|
view: "postInstall",
|
2019-10-24 00:38:56 +03:00
|
|
|
value,
|
2019-03-06 16:59:31 +03:00
|
|
|
});
|
2019-10-24 00:38:56 +03:00
|
|
|
}
|
|
|
|
// Reload the extension if it is already enabled. This ensures any change
|
|
|
|
// on the private browsing permission is properly handled.
|
|
|
|
if (addon.isActive) {
|
|
|
|
await addon.reload();
|
2019-02-27 23:05:38 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
resolve();
|
|
|
|
}
|
|
|
|
|
2017-01-20 08:26:23 +03:00
|
|
|
let action = {
|
2019-02-27 23:05:38 +03:00
|
|
|
callback: actionResolve,
|
2017-01-20 08:26:23 +03:00
|
|
|
};
|
2017-01-20 21:28:47 +03:00
|
|
|
|
2017-02-10 02:20:02 +03:00
|
|
|
let icon = addon.isWebExtension
|
2018-07-13 14:51:28 +03:00
|
|
|
? AddonManager.getPreferredIconURL(addon, 32, window) ||
|
|
|
|
DEFAULT_EXTENSION_ICON
|
2017-02-10 02:20:02 +03:00
|
|
|
: "chrome://browser/skin/addons/addon-install-installed.svg";
|
2017-01-20 08:26:23 +03:00
|
|
|
let options = {
|
2018-02-27 23:31:55 +03:00
|
|
|
name: addon.name,
|
2018-10-08 17:56:39 +03:00
|
|
|
message,
|
|
|
|
popupIconURL: icon,
|
2019-03-14 21:31:07 +03:00
|
|
|
onRefresh: setCheckbox,
|
|
|
|
onDismissed: win => {
|
2018-10-11 02:40:32 +03:00
|
|
|
AppMenuNotifications.removeNotification("addon-installed");
|
2019-03-14 21:31:07 +03:00
|
|
|
actionResolve(win);
|
2018-10-11 02:40:32 +03:00
|
|
|
},
|
2017-01-20 08:26:23 +03:00
|
|
|
};
|
2018-10-08 17:56:39 +03:00
|
|
|
AppMenuNotifications.showNotification(
|
|
|
|
"addon-installed",
|
|
|
|
action,
|
|
|
|
null,
|
|
|
|
options
|
|
|
|
);
|
2017-01-20 08:26:23 +03:00
|
|
|
});
|
2017-01-20 21:28:47 +03:00
|
|
|
},
|
2017-01-03 21:55:25 +03:00
|
|
|
};
|
2017-01-19 05:16:19 +03:00
|
|
|
|
|
|
|
EventEmitter.decorate(ExtensionsUI);
|