mirror of
https://github.com/Feodor2/Mypal68.git
synced 2025-06-18 14:55:44 -04:00
Change and remove things in extensions
This commit is contained in:
parent
25620e4f4d
commit
5ce6c629a9
@ -51,14 +51,6 @@ pref("extensions.webextensions.default-content-security-policy", "script-src 'se
|
||||
pref("extensions.webextensions.remote", true);
|
||||
pref("extensions.webextensions.background-delayed-startup", true);
|
||||
|
||||
// Extensions that should not be flagged as legacy in about:addons
|
||||
pref("extensions.legacy.exceptions", "testpilot@cliqz.com,@testpilot-containers,jid1-NeEaf3sAHdKHPA@jetpack,@activity-streams,pulse@mozilla.com,@testpilot-addon,@min-vid,tabcentertest1@mozilla.com,snoozetabs@mozilla.com,speaktome@mozilla.com,hoverpad@mozilla.com");
|
||||
|
||||
// Require signed add-ons by default
|
||||
pref("extensions.langpacks.signatures.required", false);
|
||||
pref("xpinstall.signatures.required", false);
|
||||
pref("xpinstall.signatures.devInfoURL", "data:text/plain,");
|
||||
|
||||
// Dictionary download preference
|
||||
pref("browser.dictionaries.download.url", "data:text/plain,");
|
||||
|
||||
@ -717,7 +709,7 @@ pref("browser.preferences.search", true);
|
||||
pref("browser.preferences.defaultPerformanceSettings.enabled", true);
|
||||
|
||||
pref("browser.download.show_plugins_in_list", true);
|
||||
pref("browser.download.hide_plugins_without_extensions", true);
|
||||
pref("browser.download.hide_plugins_without_extensions", false);
|
||||
|
||||
// Backspace and Shift+Backspace behavior
|
||||
// 0 goes Back/Forward
|
||||
@ -1582,8 +1574,6 @@ pref("browser.tabs.crashReporting.requestEmail", false);
|
||||
pref("browser.tabs.crashReporting.emailMe", false);
|
||||
pref("browser.tabs.crashReporting.email", "");
|
||||
|
||||
pref("extensions.legacy.enabled", false);
|
||||
|
||||
// How often to check for CPOW timeouts. CPOWs are only timed out by
|
||||
// the hang monitor.
|
||||
pref("dom.ipc.cpow.timeout", 500);
|
||||
|
@ -933,13 +933,6 @@ var BrowserPageActions = {
|
||||
let action = this._contextAction;
|
||||
this._contextAction = null;
|
||||
|
||||
PageActions.logTelemetry("managed", action);
|
||||
AMTelemetry.recordActionEvent({
|
||||
object: "pageAction",
|
||||
action: "manage",
|
||||
extra: { addonId: action.extensionID },
|
||||
});
|
||||
|
||||
let viewID = "addons://detail/" + encodeURIComponent(action.extensionID);
|
||||
window.BrowserOpenAddonsMgr(viewID);
|
||||
},
|
||||
|
@ -15,7 +15,6 @@ ChromeUtils.import("resource://gre/modules/NotificationDB.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
AddonManager: "resource://gre/modules/AddonManager.jsm",
|
||||
AMTelemetry: "resource://gre/modules/AddonManager.jsm",
|
||||
NewTabPagePreloading: "resource:///modules/NewTabPagePreloading.jsm",
|
||||
BrowserUsageTelemetry: "resource:///modules/BrowserUsageTelemetry.jsm",
|
||||
BrowserUtils: "resource://gre/modules/BrowserUtils.jsm",
|
||||
@ -534,13 +533,6 @@ XPCOMUtils.defineLazyPreferenceGetter(
|
||||
false
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this,
|
||||
"gAddonAbuseReportEnabled",
|
||||
"extensions.abuseReport.enabled",
|
||||
false
|
||||
);
|
||||
|
||||
customElements.setElementCreationCallback("translation-notification", () => {
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://browser/content/translation-notification.js",
|
||||
@ -7763,19 +7755,6 @@ function promptRemoveExtension(addon) {
|
||||
let checkboxState = { value: false };
|
||||
let checkboxMessage = null;
|
||||
|
||||
// Enable abuse report checkbox in the remove extension dialog,
|
||||
// if enabled by the about:config prefs and the addon type
|
||||
// is currently supported.
|
||||
if (
|
||||
gHtmlAboutAddonsEnabled &&
|
||||
gAddonAbuseReportEnabled &&
|
||||
["extension", "theme"].includes(addon.type)
|
||||
) {
|
||||
checkboxMessage = getFormattedString(
|
||||
"webext.remove.abuseReportCheckbox.message",
|
||||
[document.getElementById("bundle_brand").getString("vendorShortName")]
|
||||
);
|
||||
}
|
||||
const result = confirmEx(
|
||||
null,
|
||||
title,
|
||||
@ -7834,20 +7813,16 @@ var ToolbarContextMenu = {
|
||||
let manageExtension = popup.querySelector(
|
||||
".customize-context-manageExtension"
|
||||
);
|
||||
let reportExtension = popup.querySelector(
|
||||
".customize-context-reportExtension"
|
||||
);
|
||||
let separator = reportExtension.nextElementSibling;
|
||||
let id = this._getExtensionId(popup);
|
||||
let addon = id && (await AddonManager.getAddonByID(id));
|
||||
|
||||
let separator = popup.querySelector(
|
||||
".customize-context-removeExtension"
|
||||
).nextElementSibling;
|
||||
for (let element of [removeExtension, manageExtension, separator]) {
|
||||
element.hidden = !addon;
|
||||
}
|
||||
|
||||
reportExtension.hidden =
|
||||
!addon || !gAddonAbuseReportEnabled || !gHtmlAboutAddonsEnabled;
|
||||
|
||||
if (addon) {
|
||||
removeExtension.disabled = !(
|
||||
addon.permissions & AddonManager.PERM_CAN_UNINSTALL
|
||||
@ -7862,45 +7837,18 @@ var ToolbarContextMenu = {
|
||||
return;
|
||||
}
|
||||
let { remove, report } = promptRemoveExtension(addon);
|
||||
AMTelemetry.recordActionEvent({
|
||||
object: "browserAction",
|
||||
action: "uninstall",
|
||||
value: remove ? "accepted" : "cancelled",
|
||||
extra: { addonId: addon.id },
|
||||
});
|
||||
if (remove) {
|
||||
// Leave the extension in pending uninstall if we are also
|
||||
// reporting the add-on.
|
||||
await addon.uninstall(report);
|
||||
if (report) {
|
||||
this.reportExtensionForContextAction(popup, "uninstall");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
async reportExtensionForContextAction(popup, reportEntryPoint) {
|
||||
let id = this._getExtensionId(popup);
|
||||
let addon = id && (await AddonManager.getAddonByID(id));
|
||||
if (!addon) {
|
||||
return;
|
||||
}
|
||||
const win = await BrowserOpenAddonsMgr("addons://list/extension");
|
||||
win.openAbuseReport({
|
||||
addonId: addon.id,
|
||||
reportEntryPoint,
|
||||
});
|
||||
},
|
||||
|
||||
openAboutAddonsForContextAction(popup) {
|
||||
let id = this._getExtensionId(popup);
|
||||
if (id) {
|
||||
let viewID = "addons://detail/" + encodeURIComponent(id);
|
||||
BrowserOpenAddonsMgr(viewID);
|
||||
AMTelemetry.recordActionEvent({
|
||||
object: "browserAction",
|
||||
action: "manage",
|
||||
extra: { addonId: id },
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -398,11 +398,6 @@
|
||||
label="&customizeMenu.removeExtension.label;"
|
||||
contexttype="toolbaritem"
|
||||
class="customize-context-removeExtension"/>
|
||||
<menuitem oncommand="ToolbarContextMenu.reportExtensionForContextAction(this.parentElement, 'toolbar_context_menu')"
|
||||
accesskey="&customizeMenu.reportExtension.accesskey;"
|
||||
label="&customizeMenu.reportExtension.label;"
|
||||
contexttype="toolbaritem"
|
||||
class="customize-context-reportExtension"/>
|
||||
<menuseparator/>
|
||||
<menuitem oncommand="gCustomizeMode.addToPanel(document.popupNode)"
|
||||
accesskey="&customizeMenu.pinToOverflowMenu.accesskey;"
|
||||
|
@ -115,10 +115,6 @@ add_task(async function startup() {
|
||||
"network.loadinfo.skip_type_assertion": {
|
||||
// This is accessed in debug only.
|
||||
},
|
||||
"extensions.getAddons.cache.enabled": {
|
||||
min: 4,
|
||||
max: 55,
|
||||
},
|
||||
"chrome.override_package.global": {
|
||||
min: 0,
|
||||
max: 50,
|
||||
|
@ -27,7 +27,6 @@ support-files =
|
||||
skip-if = !e10s
|
||||
[browser_permissions_pointerevent.js]
|
||||
[browser_permissions_unsigned.js]
|
||||
skip-if = require_signing
|
||||
[browser_update_checkForUpdates.js]
|
||||
[browser_update_findUpdates.js]
|
||||
[browser_update_interactive_noprompt.js]
|
||||
|
@ -9,9 +9,6 @@ const { AddonTestUtils } = ChromeUtils.import(
|
||||
|
||||
AddonTestUtils.initMochitest(this);
|
||||
|
||||
hookExtensionsTelemetry();
|
||||
AddonTestUtils.hookAMTelemetryEvents();
|
||||
|
||||
async function createWebExtension(details) {
|
||||
let options = {
|
||||
manifest: {
|
||||
@ -104,7 +101,6 @@ async function test_sideloading({ useHtmlViews }) {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
["extensions.htmlaboutaddons.enabled", useHtmlViews],
|
||||
["xpinstall.signatures.required", false],
|
||||
["extensions.autoDisableScopes", 15],
|
||||
["extensions.ui.ignoreUnsigned", true],
|
||||
["extensions.allowPrivateBrowsingByDefault", false],
|
||||
@ -373,16 +369,7 @@ async function test_sideloading({ useHtmlViews }) {
|
||||
const getEventsForAddonId = (events, addonId) =>
|
||||
events.filter(ev => ev.value === addonId);
|
||||
|
||||
const amEvents = AddonTestUtils.getAMTelemetryEvents();
|
||||
|
||||
// Test telemetry events for addon1 (1 permission and 1 origin).
|
||||
info("Test telemetry events collected for addon1");
|
||||
|
||||
const baseEventAddon1 = createBaseEventAddon(1);
|
||||
const collectedEventsAddon1 = getEventsForAddonId(
|
||||
amEvents,
|
||||
baseEventAddon1.value
|
||||
);
|
||||
const expectedEventsAddon1 = [
|
||||
{
|
||||
...baseEventAddon1,
|
||||
@ -392,26 +379,7 @@ async function test_sideloading({ useHtmlViews }) {
|
||||
{ ...baseEventAddon1, method: "uninstall" },
|
||||
];
|
||||
|
||||
let i = 0;
|
||||
for (let event of collectedEventsAddon1) {
|
||||
Assert.deepEqual(
|
||||
event,
|
||||
expectedEventsAddon1[i++],
|
||||
"Got the expected telemetry event"
|
||||
);
|
||||
}
|
||||
|
||||
is(
|
||||
collectedEventsAddon1.length,
|
||||
expectedEventsAddon1.length,
|
||||
"Got the expected number of telemetry events for addon1"
|
||||
);
|
||||
|
||||
const baseEventAddon2 = createBaseEventAddon(2);
|
||||
const collectedEventsAddon2 = getEventsForAddonId(
|
||||
amEvents,
|
||||
baseEventAddon2.value
|
||||
);
|
||||
const expectedEventsAddon2 = [
|
||||
{
|
||||
...baseEventAddon2,
|
||||
@ -421,21 +389,6 @@ async function test_sideloading({ useHtmlViews }) {
|
||||
{ ...baseEventAddon2, method: "enable" },
|
||||
{ ...baseEventAddon2, method: "uninstall" },
|
||||
];
|
||||
|
||||
i = 0;
|
||||
for (let event of collectedEventsAddon2) {
|
||||
Assert.deepEqual(
|
||||
event,
|
||||
expectedEventsAddon2[i++],
|
||||
"Got the expected telemetry event"
|
||||
);
|
||||
}
|
||||
|
||||
is(
|
||||
collectedEventsAddon2.length,
|
||||
expectedEventsAddon2.length,
|
||||
"Got the expected number of telemetry events for addon2"
|
||||
);
|
||||
}
|
||||
|
||||
add_task(async function test_xul_aboutaddons_sideloading() {
|
||||
|
@ -65,9 +65,6 @@ add_task(async function setup() {
|
||||
});
|
||||
});
|
||||
|
||||
hookExtensionsTelemetry();
|
||||
AddonTestUtils.hookAMTelemetryEvents();
|
||||
|
||||
// Helper function to test background updates.
|
||||
async function backgroundUpdateTest(url, id, checkIconFn) {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
@ -209,35 +206,6 @@ async function backgroundUpdateTest(url, id, checkIconFn) {
|
||||
await addon.uninstall();
|
||||
await SpecialPowers.popPrefEnv();
|
||||
|
||||
// Test that the expected telemetry events have been recorded (and that they include the
|
||||
// permission_prompt event).
|
||||
const amEvents = AddonTestUtils.getAMTelemetryEvents();
|
||||
const updateEvents = amEvents
|
||||
.filter(evt => evt.method === "update")
|
||||
.map(evt => {
|
||||
delete evt.value;
|
||||
return evt;
|
||||
});
|
||||
|
||||
Assert.deepEqual(
|
||||
updateEvents.map(evt => evt.extra && evt.extra.step),
|
||||
[
|
||||
// First update (cancelled).
|
||||
"started",
|
||||
"download_started",
|
||||
"download_completed",
|
||||
"permissions_prompt",
|
||||
"cancelled",
|
||||
// Second update (completed).
|
||||
"started",
|
||||
"download_started",
|
||||
"download_completed",
|
||||
"permissions_prompt",
|
||||
"completed",
|
||||
],
|
||||
"Got the steps from the collected telemetry events"
|
||||
);
|
||||
|
||||
const method = "update";
|
||||
const object = "extension";
|
||||
const baseExtra = {
|
||||
|
@ -9,9 +9,6 @@ const { AddonTestUtils } = ChromeUtils.import(
|
||||
|
||||
AddonTestUtils.initMochitest(this);
|
||||
|
||||
hookExtensionsTelemetry();
|
||||
AddonTestUtils.hookAMTelemetryEvents();
|
||||
|
||||
const ID_PERMS = "update_perms@tests.mozilla.org";
|
||||
const ID_ORIGINS = "update_origins@tests.mozilla.org";
|
||||
|
||||
@ -27,8 +24,6 @@ add_task(async function setup() {
|
||||
// We don't have pre-pinned certificates for the local mochitest server
|
||||
["extensions.install.requireBuiltInCerts", false],
|
||||
["extensions.update.requireBuiltInCerts", false],
|
||||
// Don't require the extensions to be signed
|
||||
["xpinstall.signatures.required", false],
|
||||
],
|
||||
});
|
||||
|
||||
@ -92,23 +87,6 @@ async function testNoPrompt(origUrl, id) {
|
||||
await addon.uninstall();
|
||||
await SpecialPowers.popPrefEnv();
|
||||
|
||||
// Test that the expected telemetry events have been recorded (and that they do not
|
||||
// include the permission_prompt event).
|
||||
const amEvents = AddonTestUtils.getAMTelemetryEvents();
|
||||
const updateEventsSteps = amEvents
|
||||
.filter(evt => {
|
||||
return evt.method === "update" && evt.extra && evt.extra.addon_id == id;
|
||||
})
|
||||
.map(evt => {
|
||||
return evt.extra.step;
|
||||
});
|
||||
|
||||
// Expect telemetry events related to a completed update with no permissions_prompt event.
|
||||
Assert.deepEqual(
|
||||
updateEventsSteps,
|
||||
["started", "download_started", "download_completed", "completed"],
|
||||
"Got the steps from the collected telemetry events"
|
||||
);
|
||||
}
|
||||
|
||||
// Test that an update that adds new non-promptable permissions is just
|
||||
|
@ -6,9 +6,6 @@ add_task(async function setup() {
|
||||
["extensions.install.requireBuiltInCerts", false],
|
||||
["extensions.update.requireBuiltInCerts", false],
|
||||
|
||||
// Don't require the extensions to be signed
|
||||
["xpinstall.signatures.required", false],
|
||||
|
||||
// Point updates to the local mochitest server
|
||||
["extensions.update.url", `${BASE}/browser_webext_update.json`],
|
||||
],
|
||||
|
@ -451,8 +451,6 @@ async function interactiveUpdateTest(autoUpdate, checkFn) {
|
||||
],
|
||||
});
|
||||
|
||||
AddonTestUtils.hookAMTelemetryEvents();
|
||||
|
||||
// Trigger an update check, manually applying the update if we're testing
|
||||
// without auto-update.
|
||||
async function triggerUpdate(win, addon) {
|
||||
@ -549,75 +547,6 @@ async function interactiveUpdateTest(autoUpdate, checkFn) {
|
||||
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
await addon.uninstall();
|
||||
await SpecialPowers.popPrefEnv();
|
||||
|
||||
const collectedUpdateEvents = AddonTestUtils.getAMTelemetryEvents().filter(
|
||||
evt => {
|
||||
return evt.method === "update";
|
||||
}
|
||||
);
|
||||
|
||||
Assert.deepEqual(
|
||||
collectedUpdateEvents.map(evt => evt.extra.step),
|
||||
[
|
||||
// First update is cancelled on the permission prompt.
|
||||
"started",
|
||||
"download_started",
|
||||
"download_completed",
|
||||
"permissions_prompt",
|
||||
"cancelled",
|
||||
// Second update is expected to be completed.
|
||||
"started",
|
||||
"download_started",
|
||||
"download_completed",
|
||||
"permissions_prompt",
|
||||
"completed",
|
||||
],
|
||||
"Got the expected sequence on update telemetry events"
|
||||
);
|
||||
|
||||
ok(
|
||||
collectedUpdateEvents.every(evt => evt.extra.addon_id === ID),
|
||||
"Every update telemetry event should have the expected addon_id extra var"
|
||||
);
|
||||
|
||||
ok(
|
||||
collectedUpdateEvents.every(
|
||||
evt => evt.extra.source === FAKE_INSTALL_SOURCE
|
||||
),
|
||||
"Every update telemetry event should have the expected source extra var"
|
||||
);
|
||||
|
||||
ok(
|
||||
collectedUpdateEvents.every(evt => evt.extra.updated_from === "user"),
|
||||
"Every update telemetry event should have the update_from extra var 'user'"
|
||||
);
|
||||
|
||||
let hasPermissionsExtras = collectedUpdateEvents
|
||||
.filter(evt => {
|
||||
return evt.extra.step === "permissions_prompt";
|
||||
})
|
||||
.every(evt => {
|
||||
return Number.isInteger(parseInt(evt.extra.num_strings, 10));
|
||||
});
|
||||
|
||||
ok(
|
||||
hasPermissionsExtras,
|
||||
"Every 'permissions_prompt' update telemetry event should have the permissions extra vars"
|
||||
);
|
||||
|
||||
let hasDownloadTimeExtras = collectedUpdateEvents
|
||||
.filter(evt => {
|
||||
return evt.extra.step === "download_completed";
|
||||
})
|
||||
.every(evt => {
|
||||
const download_time = parseInt(evt.extra.download_time, 10);
|
||||
return !isNaN(download_time) && download_time > 0;
|
||||
});
|
||||
|
||||
ok(
|
||||
hasDownloadTimeExtras,
|
||||
"Every 'download_completed' update telemetry event should have a download_time extra vars"
|
||||
);
|
||||
}
|
||||
|
||||
// The tests in this directory install a bunch of extensions but they
|
||||
|
@ -1771,29 +1771,6 @@ BrowserGlue.prototype = {
|
||||
|
||||
ExtensionsUI.init();
|
||||
|
||||
let signingRequired;
|
||||
if (AppConstants.MOZ_REQUIRE_SIGNING) {
|
||||
signingRequired = true;
|
||||
} else {
|
||||
signingRequired = Services.prefs.getBoolPref(
|
||||
"xpinstall.signatures.required"
|
||||
);
|
||||
}
|
||||
|
||||
if (signingRequired) {
|
||||
let disabledAddons = AddonManager.getStartupChanges(
|
||||
AddonManager.STARTUP_CHANGE_DISABLED
|
||||
);
|
||||
AddonManager.getAddonsByIDs(disabledAddons).then(addons => {
|
||||
for (let addon of addons) {
|
||||
if (addon.signedState <= AddonManager.SIGNEDSTATE_MISSING) {
|
||||
this._notifyUnsignedAddonsDisabled();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (AppConstants.MOZ_CRASHREPORTER) {
|
||||
UnsubmittedCrashHandler.init();
|
||||
}
|
||||
|
@ -39,11 +39,6 @@ ChromeUtils.defineModuleGetter(
|
||||
"AddonManager",
|
||||
"resource://gre/modules/AddonManager.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"AMTelemetry",
|
||||
"resource://gre/modules/AddonManager.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"DragPositionManager",
|
||||
@ -1338,13 +1333,11 @@ CustomizeMode.prototype = {
|
||||
|
||||
openAddonsManagerThemes(aEvent) {
|
||||
aEvent.target.parentNode.parentNode.hidePopup();
|
||||
AMTelemetry.recordLinkEvent({ object: "customize", value: "manageThemes" });
|
||||
this.window.BrowserOpenAddonsMgr("addons://list/theme");
|
||||
},
|
||||
|
||||
getMoreThemes(aEvent) {
|
||||
aEvent.target.parentNode.parentNode.hidePopup();
|
||||
AMTelemetry.recordLinkEvent({ object: "customize", value: "getThemes" });
|
||||
let getMoreURL = Services.urlFormatter.formatURLPref(
|
||||
"lightweightThemes.getMoreURL"
|
||||
);
|
||||
@ -1534,11 +1527,6 @@ CustomizeMode.prototype = {
|
||||
button.addEventListener("command", async () => {
|
||||
await button.theme.enable();
|
||||
onThemeSelected(panel);
|
||||
AMTelemetry.recordActionEvent({
|
||||
object: "customize",
|
||||
action: "enable",
|
||||
extra: { type: "theme", addonId: theme.id },
|
||||
});
|
||||
});
|
||||
panel.insertBefore(button, footer);
|
||||
}
|
||||
|
@ -40,11 +40,6 @@
|
||||
label="&customizeMenu.removeExtension.label;"
|
||||
contexttype="toolbaritem"
|
||||
class="customize-context-removeExtension"/>
|
||||
<menuitem oncommand="ToolbarContextMenu.reportExtensionForContextAction(this.parentElement, 'toolbar_context_menu')"
|
||||
accesskey="&customizeMenu.reportExtension.accesskey;"
|
||||
label="&customizeMenu.reportExtension.label;"
|
||||
contexttype="toolbaritem"
|
||||
class="customize-context-reportExtension"/>
|
||||
<menuseparator/>
|
||||
<menuitem oncommand="gCustomizeMode.addToPanel(document.popupNode)"
|
||||
id="customizationPanelItemContextMenuPin"
|
||||
|
@ -854,9 +854,6 @@
|
||||
"extensions.blocklist.enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"extensions.getAddons.showPane": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"geo.enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
|
@ -1,11 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this,
|
||||
"ABUSE_REPORT_ENABLED",
|
||||
"extensions.abuseReport.enabled",
|
||||
false
|
||||
);
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this,
|
||||
"HTML_ABOUTADDONS_ENABLED",
|
||||
@ -207,10 +201,9 @@ add_task(async function browseraction_contextmenu_manage_extension() {
|
||||
let manageExtension = menu.querySelector(
|
||||
".customize-context-manageExtension"
|
||||
);
|
||||
let reportExtension = menu.querySelector(
|
||||
".customize-context-reportExtension"
|
||||
);
|
||||
let separator = reportExtension.nextElementSibling;
|
||||
let separator = popup.querySelector(
|
||||
".customize-context-removeExtension"
|
||||
).nextElementSibling;
|
||||
|
||||
info(`Check visibility: ${visible}`);
|
||||
let expected = visible ? "visible" : "hidden";
|
||||
@ -224,11 +217,6 @@ add_task(async function browseraction_contextmenu_manage_extension() {
|
||||
!visible,
|
||||
`Manage Extension should be ${expected}`
|
||||
);
|
||||
is(
|
||||
reportExtension.hidden,
|
||||
!ABUSE_REPORT_ENABLED || !HTML_ABOUTADDONS_ENABLED || !visible,
|
||||
`Report Extension should be ${expected}`
|
||||
);
|
||||
is(
|
||||
separator.hidden,
|
||||
!visible,
|
||||
@ -594,118 +582,3 @@ add_task(async function browseraction_contextmenu_remove_extension() {
|
||||
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
});
|
||||
|
||||
// This test case verify reporting an extension from the browserAction
|
||||
// context menu (when the browserAction is in the toolbox and in the
|
||||
// overwflow menu, and repeat the test with and without the customize
|
||||
// mode enabled).
|
||||
add_task(async function browseraction_contextmenu_report_extension() {
|
||||
SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
["extensions.htmlaboutaddons.enabled", true],
|
||||
["extensions.abuseReport.enabled", true],
|
||||
],
|
||||
});
|
||||
let win = await BrowserTestUtils.openNewBrowserWindow();
|
||||
let id = "addon_id@example.com";
|
||||
let name = "Bad Add-on";
|
||||
let buttonId = `${makeWidgetId(id)}-browser-action`;
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
name,
|
||||
author: "Bad author",
|
||||
applications: {
|
||||
gecko: { id },
|
||||
},
|
||||
browser_action: {},
|
||||
},
|
||||
useAddonManager: "temporary",
|
||||
});
|
||||
|
||||
async function testContextMenu(menuId, customizing) {
|
||||
info(`Open browserAction context menu in ${menuId}`);
|
||||
let menu = await openContextMenu(menuId, buttonId, win);
|
||||
|
||||
info(`Choosing 'Report Extension' in ${menuId} should show confirm dialog`);
|
||||
let reportExtension = menu.querySelector(
|
||||
".customize-context-reportExtension"
|
||||
);
|
||||
ok(!reportExtension.hidden, "Report extension should be visibile");
|
||||
|
||||
// When running in customizing mode "about:addons" will load in a new tab,
|
||||
// otherwise it will replace the existing blank tab.
|
||||
const onceAboutAddonsTab = customizing
|
||||
? BrowserTestUtils.waitForNewTab(win.gBrowser, "about:addons")
|
||||
: BrowserTestUtils.waitForCondition(() => {
|
||||
return win.gBrowser.currentURI.spec === "about:addons";
|
||||
}, "Wait an about:addons tab to be opened");
|
||||
|
||||
await closeChromeContextMenu(menuId, reportExtension, win);
|
||||
await onceAboutAddonsTab;
|
||||
|
||||
const browser = win.gBrowser.selectedBrowser;
|
||||
is(
|
||||
browser.currentURI.spec,
|
||||
"about:addons",
|
||||
"Got about:addons tab selected"
|
||||
);
|
||||
|
||||
await BrowserTestUtils.browserLoaded(browser);
|
||||
|
||||
const abuseReportFrame = await BrowserTestUtils.waitForCondition(() => {
|
||||
return browser.contentDocument.querySelector(
|
||||
"addon-abuse-report-xulframe"
|
||||
);
|
||||
}, "Wait the abuse report frame");
|
||||
|
||||
ok(
|
||||
!abuseReportFrame.hidden,
|
||||
"Abuse report frame has the expected visibility"
|
||||
);
|
||||
is(
|
||||
abuseReportFrame.report.addon.id,
|
||||
id,
|
||||
"Abuse report frame has the expected addon id"
|
||||
);
|
||||
is(
|
||||
abuseReportFrame.report.reportEntryPoint,
|
||||
"toolbar_context_menu",
|
||||
"Abuse report frame has the expected reportEntryPoint"
|
||||
);
|
||||
|
||||
// Close the new about:addons tab when running in customize mode,
|
||||
// or cancel the abuse report if the about:addons page has been
|
||||
// loaded in the existing blank tab.
|
||||
if (customizing) {
|
||||
info("Closing the about:addons tab");
|
||||
BrowserTestUtils.removeTab(win.gBrowser.selectedTab);
|
||||
} else {
|
||||
info("Navigate the about:addons tab to about:blank");
|
||||
await BrowserTestUtils.loadURI(browser, "about:blank");
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
await extension.startup();
|
||||
|
||||
info("Run tests in normal mode");
|
||||
await runTestContextMenu({
|
||||
buttonId,
|
||||
customizing: false,
|
||||
testContextMenu,
|
||||
win,
|
||||
});
|
||||
|
||||
info("Run tests in customize mode");
|
||||
await runTestContextMenu({
|
||||
buttonId,
|
||||
customizing: true,
|
||||
testContextMenu,
|
||||
win,
|
||||
});
|
||||
|
||||
await extension.unload();
|
||||
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
});
|
||||
|
@ -4,10 +4,6 @@ const BASE =
|
||||
"http://mochi.test:8888/browser/browser/components/extensions/test/browser/";
|
||||
|
||||
add_task(async function test_management_install() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["xpinstall.signatures.required", false]],
|
||||
});
|
||||
|
||||
registerCleanupFunction(async () => {
|
||||
await SpecialPowers.popPrefEnv();
|
||||
});
|
||||
|
@ -19,11 +19,6 @@
|
||||
|
||||
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"AMTelemetry",
|
||||
"resource://gre/modules/AddonManager.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"formAutofillParent",
|
||||
@ -121,10 +116,6 @@ function init_all() {
|
||||
document.getElementById("addonsButton").addEventListener("click", () => {
|
||||
let mainWindow = window.docShell.rootTreeItem.domWindow;
|
||||
mainWindow.BrowserOpenAddonsMgr();
|
||||
AMTelemetry.recordLinkEvent({
|
||||
object: "aboutPreferences",
|
||||
value: "about:addons",
|
||||
});
|
||||
});
|
||||
|
||||
document.dispatchEvent(
|
||||
|
@ -242,7 +242,6 @@ add_task(async function testDisabledBrowserLanguages() {
|
||||
["intl.multilingual.enabled", true],
|
||||
["intl.multilingual.downloadEnabled", true],
|
||||
["intl.locale.requested", "en-US,pl,he,de"],
|
||||
["extensions.langpacks.signatures.required", false],
|
||||
["extensions.getAddons.langpacks.url", langpacksUrl],
|
||||
],
|
||||
});
|
||||
|
@ -2,12 +2,6 @@ export MOZ_PGO=1
|
||||
|
||||
. "$topsrcdir/browser/config/mozconfigs/linux32/common-opt"
|
||||
|
||||
# Add-on signing is not required for DevEdition
|
||||
MOZ_REQUIRE_SIGNING=0
|
||||
|
||||
ac_add_options --with-branding=browser/branding/aurora
|
||||
|
||||
# Enable MOZ_ALLOW_LEGACY_EXTENSIONS
|
||||
ac_add_options "MOZ_ALLOW_LEGACY_EXTENSIONS=1"
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -15,7 +15,5 @@ export MOZILLA_OFFICIAL=1
|
||||
# Don't autoclobber l10n, as this can lead to missing binaries and broken builds
|
||||
# Bug 1283438
|
||||
mk_add_options AUTOCLOBBER=
|
||||
# Enable MOZ_ALLOW_LEGACY_EXTENSIONS
|
||||
ac_add_options "MOZ_ALLOW_LEGACY_EXTENSIONS=1"
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -1,10 +1,5 @@
|
||||
. $topsrcdir/browser/config/mozconfigs/linux64/nightly
|
||||
|
||||
#add-on signing is checked but not enforced
|
||||
MOZ_REQUIRE_SIGNING=0
|
||||
# Enable MOZ_ALLOW_LEGACY_EXTENSIONS
|
||||
ac_add_options "MOZ_ALLOW_LEGACY_EXTENSIONS=1"
|
||||
|
||||
ac_add_options --with-branding=browser/branding/unofficial
|
||||
ac_add_options --enable-update-channel=default
|
||||
|
||||
|
@ -3,11 +3,6 @@ MOZ_AUTOMATION_L10N_CHECK=0
|
||||
ac_add_options --disable-debug
|
||||
ac_add_options --enable-optimize="-O2 -gline-tables-only"
|
||||
|
||||
#add-on signing is checked but not enforced
|
||||
MOZ_REQUIRE_SIGNING=0
|
||||
# Enable MOZ_ALLOW_LEGACY_EXTENSIONS
|
||||
ac_add_options "MOZ_ALLOW_LEGACY_EXTENSIONS=1"
|
||||
|
||||
. $topsrcdir/build/mozconfig.stylo
|
||||
|
||||
# ASan specific options on Linux
|
||||
|
@ -2,9 +2,6 @@ export MOZ_PGO=1
|
||||
|
||||
. "$topsrcdir/browser/config/mozconfigs/linux64/common-opt"
|
||||
|
||||
# Add-on signing is not required for DevEdition
|
||||
MOZ_REQUIRE_SIGNING=0
|
||||
|
||||
ac_add_options --with-branding=browser/branding/aurora
|
||||
|
||||
export MOZ_LTO=1
|
||||
@ -12,7 +9,4 @@ ac_add_options --enable-profile-use
|
||||
ac_add_options --with-pgo-jarlog=/builds/worker/fetches/en-US.log
|
||||
ac_add_options --with-pgo-profile-path=/builds/worker/fetches
|
||||
|
||||
# Enable MOZ_ALLOW_LEGACY_EXTENSIONS
|
||||
ac_add_options "MOZ_ALLOW_LEGACY_EXTENSIONS=1"
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -11,7 +11,4 @@ export MOZILLA_OFFICIAL=1
|
||||
# Bug 1283438
|
||||
mk_add_options AUTOCLOBBER=
|
||||
|
||||
# Enable MOZ_ALLOW_LEGACY_EXTENSIONS
|
||||
ac_add_options "MOZ_ALLOW_LEGACY_EXTENSIONS=1"
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -2,11 +2,6 @@
|
||||
ac_add_options --disable-debug
|
||||
ac_add_options --enable-optimize="-O2 -gline-tables-only"
|
||||
|
||||
#add-on signing is checked but not enforced
|
||||
MOZ_REQUIRE_SIGNING=0
|
||||
# Enable MOZ_ALLOW_LEGACY_EXTENSIONS
|
||||
ac_add_options "MOZ_ALLOW_LEGACY_EXTENSIONS=1"
|
||||
|
||||
. $topsrcdir/build/mozconfig.stylo
|
||||
|
||||
# ASan specific options on Linux
|
||||
|
@ -2,11 +2,6 @@
|
||||
|
||||
unset MOZ_LTO
|
||||
|
||||
#add-on signing is checked but not enforced
|
||||
MOZ_REQUIRE_SIGNING=0
|
||||
# Enable MOZ_ALLOW_LEGACY_EXTENSIONS
|
||||
ac_add_options "MOZ_ALLOW_LEGACY_EXTENSIONS=1"
|
||||
|
||||
ac_add_options --with-branding=browser/branding/unofficial
|
||||
ac_add_options --enable-update-channel=default
|
||||
|
||||
|
@ -1,8 +1,5 @@
|
||||
. "$topsrcdir/browser/config/mozconfigs/macosx64/common-opt"
|
||||
|
||||
# Add-on signing is not required for DevEdition
|
||||
MOZ_REQUIRE_SIGNING=0
|
||||
|
||||
ac_add_options --disable-install-strip
|
||||
|
||||
export MOZ_LTO=1
|
||||
@ -20,7 +17,4 @@ fi
|
||||
|
||||
ac_add_options --with-branding=browser/branding/aurora
|
||||
|
||||
# Enable MOZ_ALLOW_LEGACY_EXTENSIONS
|
||||
ac_add_options "MOZ_ALLOW_LEGACY_EXTENSIONS=1"
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -26,7 +26,4 @@ export MOZILLA_OFFICIAL=1
|
||||
# Bug 1283438
|
||||
mk_add_options AUTOCLOBBER=
|
||||
|
||||
# Enable MOZ_ALLOW_LEGACY_EXTENSIONS
|
||||
ac_add_options "MOZ_ALLOW_LEGACY_EXTENSIONS=1"
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -1,10 +1,5 @@
|
||||
. $topsrcdir/browser/config/mozconfigs/win32/nightly
|
||||
|
||||
#add-on signing is checked but not enforced
|
||||
MOZ_REQUIRE_SIGNING=0
|
||||
# Enable MOZ_ALLOW_LEGACY_EXTENSIONS
|
||||
ac_add_options "MOZ_ALLOW_LEGACY_EXTENSIONS=1"
|
||||
|
||||
ac_add_options --with-branding=browser/branding/unofficial
|
||||
ac_add_options --enable-update-channel=default
|
||||
|
||||
|
@ -3,12 +3,6 @@ export MOZ_PGO=1
|
||||
. "$topsrcdir/build/mozconfig.win-common"
|
||||
. "$topsrcdir/browser/config/mozconfigs/win32/common-opt"
|
||||
|
||||
# Add-on signing is not required for DevEdition
|
||||
MOZ_REQUIRE_SIGNING=0
|
||||
|
||||
ac_add_options --with-branding=browser/branding/aurora
|
||||
|
||||
# Enable MOZ_ALLOW_LEGACY_EXTENSIONS
|
||||
ac_add_options "MOZ_ALLOW_LEGACY_EXTENSIONS=1"
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -16,7 +16,4 @@ export MOZILLA_OFFICIAL=1
|
||||
# Bug 1283438
|
||||
mk_add_options AUTOCLOBBER=
|
||||
|
||||
# Enable MOZ_ALLOW_LEGACY_EXTENSIONS
|
||||
ac_add_options "MOZ_ALLOW_LEGACY_EXTENSIONS=1"
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -15,7 +15,6 @@ unset MAKECAB
|
||||
# --enable-release
|
||||
# LLVM_CONFIG
|
||||
# MOZ_ADDON_SIGNING
|
||||
# MOZ_REQUIRE_SIGNING
|
||||
# --enable-js-shell
|
||||
# build/mozconfig.automation
|
||||
# MOZ_AUTOMATION_ flags
|
||||
|
@ -2,16 +2,10 @@
|
||||
. "$topsrcdir/browser/config/mozconfigs/win64-aarch64/common-win64"
|
||||
. "$topsrcdir/browser/config/mozconfigs/win64-aarch64/common-opt"
|
||||
|
||||
# Add-on signing is not required for DevEdition
|
||||
MOZ_REQUIRE_SIGNING=0
|
||||
|
||||
export MOZ_LTO=1
|
||||
|
||||
ac_add_options --with-branding=browser/branding/aurora
|
||||
|
||||
# Enable MOZ_ALLOW_LEGACY_EXTENSIONS
|
||||
ac_add_options "MOZ_ALLOW_LEGACY_EXTENSIONS=1"
|
||||
|
||||
unset ENABLE_CLANG_PLUGIN
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -15,7 +15,4 @@ export MOZILLA_OFFICIAL=1
|
||||
# Bug 1283438
|
||||
mk_add_options AUTOCLOBBER=
|
||||
|
||||
# Enable MOZ_ALLOW_LEGACY_EXTENSIONS
|
||||
ac_add_options "MOZ_ALLOW_LEGACY_EXTENSIONS=1"
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -1,10 +1,5 @@
|
||||
. $topsrcdir/browser/config/mozconfigs/win64/nightly
|
||||
|
||||
#add-on signing is checked but not enforced
|
||||
MOZ_REQUIRE_SIGNING=0
|
||||
# Enable MOZ_ALLOW_LEGACY_EXTENSIONS
|
||||
ac_add_options "MOZ_ALLOW_LEGACY_EXTENSIONS=1"
|
||||
|
||||
ac_add_options --with-branding=browser/branding/unofficial
|
||||
ac_add_options --enable-update-channel=default
|
||||
|
||||
|
@ -4,12 +4,6 @@ export MOZ_PGO=1
|
||||
. "$topsrcdir/browser/config/mozconfigs/win64/common-win64"
|
||||
. "$topsrcdir/browser/config/mozconfigs/win64/common-opt"
|
||||
|
||||
# Add-on signing is not required for DevEdition
|
||||
MOZ_REQUIRE_SIGNING=0
|
||||
|
||||
ac_add_options --with-branding=browser/branding/aurora
|
||||
|
||||
# Enable MOZ_ALLOW_LEGACY_EXTENSIONS
|
||||
ac_add_options "MOZ_ALLOW_LEGACY_EXTENSIONS=1"
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -15,7 +15,4 @@ export MOZILLA_OFFICIAL=1
|
||||
# Bug 1283438
|
||||
mk_add_options AUTOCLOBBER=
|
||||
|
||||
# Enable MOZ_ALLOW_LEGACY_EXTENSIONS
|
||||
ac_add_options "MOZ_ALLOW_LEGACY_EXTENSIONS=1"
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -14,8 +14,6 @@ unset MAKECAB
|
||||
# --enable-crashreporter
|
||||
# --enable-release
|
||||
# LLVM_CONFIG
|
||||
# MOZ_ADDON_SIGNING
|
||||
# MOZ_REQUIRE_SIGNING
|
||||
# --enable-js-shell
|
||||
# build/mozconfig.automation
|
||||
# MOZ_AUTOMATION_ flags
|
||||
|
@ -15,7 +15,6 @@ const { EventEmitter } = ChromeUtils.import(
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
AddonManager: "resource://gre/modules/AddonManager.jsm",
|
||||
AddonManagerPrivate: "resource://gre/modules/AddonManager.jsm",
|
||||
AMTelemetry: "resource://gre/modules/AddonManager.jsm",
|
||||
AppMenuNotifications: "resource://gre/modules/AppMenuNotifications.jsm",
|
||||
BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.jsm",
|
||||
ExtensionData: "resource://gre/modules/Extension.jsm",
|
||||
@ -160,10 +159,6 @@ var ExtensionsUI = {
|
||||
type: "sideload",
|
||||
});
|
||||
|
||||
AMTelemetry.recordManageEvent(addon, "sideload_prompt", {
|
||||
num_strings: strings.msgs.length,
|
||||
});
|
||||
|
||||
this.showAddonsManager(browser, strings, addon.iconURL, "sideload").then(
|
||||
async answer => {
|
||||
if (answer) {
|
||||
@ -187,11 +182,6 @@ var ExtensionsUI = {
|
||||
},
|
||||
|
||||
showUpdate(browser, info) {
|
||||
AMTelemetry.recordInstallEvent(info.install, {
|
||||
step: "permissions_prompt",
|
||||
num_strings: info.strings.msgs.length,
|
||||
});
|
||||
|
||||
this.showAddonsManager(
|
||||
browser,
|
||||
info.strings,
|
||||
@ -262,17 +252,6 @@ var ExtensionsUI = {
|
||||
histkey = "installWeb";
|
||||
}
|
||||
|
||||
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,
|
||||
});
|
||||
}
|
||||
|
||||
this.showPermissionsPrompt(browser, strings, icon, histkey).then(
|
||||
answer => {
|
||||
if (answer) {
|
||||
@ -554,13 +533,6 @@ var ExtensionsUI = {
|
||||
origins: [],
|
||||
};
|
||||
await ExtensionPermissions.add(addon.id, perms);
|
||||
AMTelemetry.recordActionEvent({
|
||||
addon,
|
||||
object: "doorhanger",
|
||||
action: "privateBrowsingAllowed",
|
||||
view: "postInstall",
|
||||
value: "on",
|
||||
});
|
||||
|
||||
// Reload the extension if it is already enabled. This ensures any change
|
||||
// on the private browsing permission is properly handled.
|
||||
@ -604,21 +576,11 @@ var ExtensionsUI = {
|
||||
let action = {
|
||||
callback: () => {
|
||||
resolve();
|
||||
AMTelemetry.recordActionEvent({
|
||||
object: "doorhanger",
|
||||
action: "dismiss",
|
||||
view: "privateBrowsing",
|
||||
});
|
||||
},
|
||||
dismiss: false,
|
||||
};
|
||||
let manage = {
|
||||
callback: () => {
|
||||
AMTelemetry.recordActionEvent({
|
||||
object: "doorhanger",
|
||||
action: "manage",
|
||||
view: "privateBrowsing",
|
||||
});
|
||||
// Callback may happen in a different window, use the top window
|
||||
// for the new tab.
|
||||
let win = BrowserWindowTracker.getTopWindow();
|
||||
|
@ -18,9 +18,6 @@ mk_add_options AUTOCLOBBER=1
|
||||
|
||||
ac_add_options --enable-crashreporter
|
||||
|
||||
# Disable enforcing that add-ons are signed by the trusted root
|
||||
MOZ_REQUIRE_SIGNING=${MOZ_REQUIRE_SIGNING-0}
|
||||
|
||||
ac_add_options --enable-js-shell
|
||||
|
||||
. "$topsrcdir/build/mozconfig.nasm"
|
||||
|
@ -61,7 +61,7 @@ pref("devtools.remote.tls-handshake-timeout", 10000);
|
||||
// The extension ID for devtools-adb-extension
|
||||
pref("devtools.remote.adb.extensionID", "adb@mozilla.org");
|
||||
// The URL for for devtools-adb-extension (overridden in tests to a local path)
|
||||
pref("devtools.remote.adb.extensionURL", "https://ftp.mozilla.org/pub/mozilla.org/labs/devtools/adb-extension/#OS#/adb-extension-latest-#OS#.xpi");
|
||||
pref("devtools.remote.adb.extensionURL", "");
|
||||
|
||||
// URL of the remote JSON catalog used for device simulation
|
||||
pref("devtools.devices.url", "https://code.cdn.mozilla.net/devices/devices.json");
|
||||
|
@ -9537,40 +9537,6 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
|
||||
!StaticPrefs::extensions_webextensions_remote()) {
|
||||
break;
|
||||
}
|
||||
// This next bit is... awful. Basically, about:addons used to load the
|
||||
// discovery pane remotely. Allow for that, if that's actually the state
|
||||
// we're in (which is no longer the default at time of writing, but still
|
||||
// tested). https://bugzilla.mozilla.org/show_bug.cgi?id=1565606 covers
|
||||
// removing this atrocity.
|
||||
nsCOMPtr<nsIWebNavigation> parent(do_QueryInterface(mParent));
|
||||
if (parent) {
|
||||
nsCOMPtr<nsIURI> parentURL;
|
||||
parent->GetCurrentURI(getter_AddRefs(parentURL));
|
||||
if (parentURL &&
|
||||
parentURL->GetSpecOrDefault().EqualsLiteral("about:addons") &&
|
||||
(!Preferences::GetBool("extensions.htmlaboutaddons.enabled",
|
||||
true) ||
|
||||
!Preferences::GetBool(
|
||||
"extensions.htmlaboutaddons.discover.enabled", true))) {
|
||||
nsCString discoveryURLString;
|
||||
Preferences::GetCString("extensions.webservice.discoverURL",
|
||||
discoveryURLString);
|
||||
nsCOMPtr<nsIURI> discoveryURL;
|
||||
NS_NewURI(getter_AddRefs(discoveryURL), discoveryURLString);
|
||||
|
||||
nsAutoCString discoveryPrePath;
|
||||
if (discoveryURL) {
|
||||
discoveryURL->GetPrePath(discoveryPrePath);
|
||||
}
|
||||
|
||||
nsAutoCString requestedPrePath;
|
||||
uri->GetPrePath(requestedPrePath);
|
||||
// So allow the discovery path to load inside about:addons.
|
||||
if (discoveryPrePath.Equals(requestedPrePath)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef MOZ_LAYOUT_DEBUGGER
|
||||
// Also allow loads in the layout debugger window.
|
||||
nsCOMPtr<nsIDocShellTreeItem> rootItem;
|
||||
|
@ -3003,7 +3003,6 @@ bool ContentParent::ShouldSyncPreference(const char16_t* aData) {
|
||||
BLACKLIST_ENTRY(u"browser.shell."),
|
||||
BLACKLIST_ENTRY(u"browser.slowStartup."),
|
||||
BLACKLIST_ENTRY(u"browser.startup."),
|
||||
BLACKLIST_ENTRY(u"extensions.getAddons.cache."),
|
||||
BLACKLIST_ENTRY(u"media.gmp-manager."),
|
||||
BLACKLIST_ENTRY(u"media.gmp-gmpopenh264."),
|
||||
BLACKLIST_ENTRY(u"privacy.sanitize."),
|
||||
|
@ -888,28 +888,6 @@ nsresult nsContentSecurityManager::CheckSystemPrincipalLoads(
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// FIXME The discovery feature in about:addons uses the SystemPrincpal.
|
||||
// We should remove this exception with bug 1544011.
|
||||
static nsAutoCString sDiscoveryPrePath;
|
||||
static bool recvdPrefValue = false;
|
||||
if (!recvdPrefValue) {
|
||||
nsAutoCString discoveryURLString;
|
||||
Preferences::GetCString("extensions.webservice.discoverURL",
|
||||
discoveryURLString);
|
||||
// discoverURL is by default suffixed with parameters in path like
|
||||
// /%LOCALE%/ so, we use the prePath for comparison
|
||||
nsCOMPtr<nsIURI> discoveryURL;
|
||||
NS_NewURI(getter_AddRefs(discoveryURL), discoveryURLString);
|
||||
if (discoveryURL) {
|
||||
discoveryURL->GetPrePath(sDiscoveryPrePath);
|
||||
}
|
||||
recvdPrefValue = true;
|
||||
}
|
||||
nsAutoCString requestedPrePath;
|
||||
finalURI->GetPrePath(requestedPrePath);
|
||||
if (requestedPrePath.Equals(sDiscoveryPrePath)) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsAutoCString requestedURL;
|
||||
finalURI->GetAsciiSpec(requestedURL);
|
||||
MOZ_LOG(
|
||||
|
@ -173,9 +173,6 @@ pref("xpinstall.whitelist.directRequest", false);
|
||||
pref("xpinstall.whitelist.fileRequest", false);
|
||||
pref("xpinstall.whitelist.add", "https://addons.mozilla.org");
|
||||
|
||||
pref("extensions.langpacks.signatures.required", true);
|
||||
pref("xpinstall.signatures.required", true);
|
||||
|
||||
// Disable add-ons that are not installed by the user in all scopes by default (See the SCOPE
|
||||
// constants in AddonManager.jsm for values to use here, and Bug 1405528 for a rationale).
|
||||
pref("extensions.autoDisableScopes", 15);
|
||||
@ -196,14 +193,6 @@ pref("extensions.minCompatibleAppVersion", "11.0");
|
||||
pref("extensions.update.url", "https://versioncheck.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%¤tAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%&compatMode=%COMPATIBILITY_MODE%");
|
||||
pref("extensions.update.background.url", "https://versioncheck-bg.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%¤tAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%&compatMode=%COMPATIBILITY_MODE%");
|
||||
|
||||
/* preferences for the Get Add-ons pane */
|
||||
pref("extensions.getAddons.cache.enabled", true);
|
||||
pref("extensions.getAddons.search.browseURL", "https://addons.mozilla.org/%LOCALE%/android/search?q=%TERMS%&platform=%OS%&appver=%VERSION%");
|
||||
pref("extensions.getAddons.browseAddons", "https://addons.mozilla.org/%LOCALE%/android/collections/4757633/mob/?page=1&collection_sort=-popularity");
|
||||
pref("extensions.getAddons.get.url", "https://services.addons.mozilla.org/api/v3/addons/search/?guid=%IDS%&lang=%LOCALE%");
|
||||
pref("extensions.getAddons.compatOverides.url", "https://services.addons.mozilla.org/api/v3/addons/compat-override/?guid=%IDS%&lang=%LOCALE%");
|
||||
pref("extensions.getAddons.langpacks.url", "https://services.addons.mozilla.org/api/v3/addons/language-tools/?app=android&type=language&appversion=%VERSION%");
|
||||
|
||||
/* preference for the locale picker */
|
||||
pref("extensions.getLocales.get.url", "");
|
||||
pref("extensions.compatability.locales.buildid", "0");
|
||||
@ -220,8 +209,6 @@ pref("extensions.webextensions.default-content-security-policy", "script-src 'se
|
||||
|
||||
pref("extensions.webextensions.background-delayed-startup", true);
|
||||
|
||||
pref("extensions.legacy.enabled", false);
|
||||
|
||||
/* block popups by default, and notify the user about blocked popups */
|
||||
pref("dom.disable_open_during_load", true);
|
||||
pref("privacy.popups.showBrowserMessage", true);
|
||||
|
@ -288,21 +288,6 @@ var Addons = {
|
||||
let outer = document.createElement("div");
|
||||
outer.className = "addon-item list-item";
|
||||
outer.setAttribute("role", "button");
|
||||
outer.addEventListener(
|
||||
"click",
|
||||
function(event) {
|
||||
try {
|
||||
openLink(
|
||||
Services.urlFormatter.formatURLPref(
|
||||
"extensions.getAddons.browseAddons"
|
||||
)
|
||||
);
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
let img = document.createElement("img");
|
||||
img.className = "icon";
|
||||
|
@ -3,8 +3,5 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
# This file is included at the bottom of all native android mozconfigs
|
||||
#
|
||||
# Disable enforcing that add-ons are signed by the trusted root
|
||||
MOZ_REQUIRE_SIGNING=0
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -2611,7 +2611,7 @@
|
||||
# Private browsing opt-in is only supported on Firefox desktop.
|
||||
- name: extensions.allowPrivateBrowsingByDefault
|
||||
type: bool
|
||||
value: @IS_ANDROID@
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
# This pref should be set to true only in case of regression related to the
|
||||
|
@ -2259,9 +2259,6 @@ pref("services.settings.security.onecrl.collection", "onecrl");
|
||||
pref("services.settings.security.onecrl.signer", "onecrl.content-signature.mozilla.org");
|
||||
pref("services.settings.security.onecrl.checked", 0);
|
||||
|
||||
pref("extensions.abuseReport.enabled", false);
|
||||
pref("extensions.abuseReport.url", "data:text/plain,");
|
||||
|
||||
// Blocklist preferences
|
||||
pref("extensions.blocklist.enabled", false);
|
||||
// OneCRL freshness checking depends on this value, so if you change it,
|
||||
@ -3932,11 +3929,7 @@ pref("browser.meta_refresh_when_inactive.disabled", false);
|
||||
|
||||
// XPInstall prefs
|
||||
pref("xpinstall.whitelist.required", true);
|
||||
// Only Firefox requires add-on signatures
|
||||
pref("xpinstall.signatures.required", false);
|
||||
pref("extensions.langpacks.signatures.required", false);
|
||||
pref("extensions.webExtensionsMinPlatformVersion", "42.0a1");
|
||||
pref("extensions.legacy.enabled", true);
|
||||
|
||||
// Other webextensions prefs
|
||||
pref("extensions.webextensions.keepStorageOnUninstall", false);
|
||||
@ -3970,7 +3963,7 @@ pref("extensions.webextensions.enablePerformanceCounters", true);
|
||||
pref("extensions.webextensions.performanceCountersMaxAge", 5000);
|
||||
|
||||
// The HTML about:addons page.
|
||||
pref("extensions.htmlaboutaddons.enabled", true);
|
||||
pref("extensions.htmlaboutaddons.enabled", false);
|
||||
// Whether to allow the inline options browser in HTML about:addons page.
|
||||
pref("extensions.htmlaboutaddons.inline-options.enabled", true);
|
||||
// Show recommendations on the extension and theme list views.
|
||||
|
@ -3008,11 +3008,6 @@ if test -n "$MOZ_BINARY_EXTENSIONS"; then
|
||||
AC_DEFINE(MOZ_BINARY_EXTENSIONS)
|
||||
fi
|
||||
|
||||
AC_SUBST(MOZ_REQUIRE_SIGNING)
|
||||
if test "$MOZ_REQUIRE_SIGNING" = 1; then
|
||||
AC_DEFINE(MOZ_REQUIRE_SIGNING)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Mac bundle name prefix
|
||||
dnl ========================================================
|
||||
|
@ -89,8 +89,6 @@ def build_dict(config, env=os.environ):
|
||||
d['telemetry'] = substs.get('MOZ_TELEMETRY_REPORTING') == '1'
|
||||
d['tests_enabled'] = substs.get('ENABLE_TESTS') == "1"
|
||||
d['bin_suffix'] = substs.get('BIN_SUFFIX', '')
|
||||
d['require_signing'] = substs.get('MOZ_REQUIRE_SIGNING') == '1'
|
||||
d['allow_legacy_extensions'] = substs.get('MOZ_ALLOW_LEGACY_EXTENSIONS') == '1'
|
||||
d['official'] = bool(substs.get('MOZILLA_OFFICIAL'))
|
||||
d['updater'] = substs.get('MOZ_UPDATER') == '1'
|
||||
d['artifact'] = substs.get('MOZ_ARTIFACT_BUILDS') == '1'
|
||||
|
@ -13,13 +13,6 @@ const { AddonUtils } = ChromeUtils.import(
|
||||
const HTTP_PORT = 8888;
|
||||
const SERVER_ADDRESS = "http://127.0.0.1:8888";
|
||||
|
||||
var prefs = new Preferences();
|
||||
|
||||
prefs.set(
|
||||
"extensions.getAddons.get.url",
|
||||
SERVER_ADDRESS + "/search/guid:%IDS%"
|
||||
);
|
||||
|
||||
AddonTestUtils.init(this);
|
||||
AddonTestUtils.createAppInfo(
|
||||
"xpcshell@tests.mozilla.org",
|
||||
|
@ -18,10 +18,6 @@ const { Preferences } = ChromeUtils.import(
|
||||
);
|
||||
|
||||
const prefs = new Preferences();
|
||||
prefs.set(
|
||||
"extensions.getAddons.get.url",
|
||||
"http://localhost:8888/search/guid:%IDS%"
|
||||
);
|
||||
prefs.set("extensions.install.requireSecureOrigin", false);
|
||||
|
||||
let engine;
|
||||
|
@ -26,7 +26,6 @@ class TestNotifications(PuppeteerMixin, MarionetteTestCase):
|
||||
def tearDown(self):
|
||||
try:
|
||||
self.marionette.clear_pref('extensions.install.requireSecureOrigin')
|
||||
self.marionette.clear_pref('xpinstall.signatures.required')
|
||||
|
||||
self.puppeteer.utils.permissions.remove(self.addons_url, 'install')
|
||||
|
||||
@ -67,15 +66,6 @@ class TestNotifications(PuppeteerMixin, MarionetteTestCase):
|
||||
self.assertIn(self.browser.notification.origin, self.marionette.baseurl)
|
||||
self.assertIsNotNone(self.browser.notification.label)
|
||||
|
||||
def test_addon_install_failed_notification(self):
|
||||
"""Trigger add-on blocked notification using an unsigned add-on"""
|
||||
# Ensure that installing unsigned extensions will fail
|
||||
self.marionette.set_pref('xpinstall.signatures.required', True)
|
||||
|
||||
self.trigger_addon_notification(
|
||||
'webextension-unsigned.xpi',
|
||||
notification=AddOnInstallFailedNotification)
|
||||
|
||||
def trigger_addon_notification(self, addon, notification=AddOnInstallConfirmationNotification):
|
||||
with self.marionette.using_context('content'):
|
||||
self.marionette.navigate(self.addons_url)
|
||||
|
@ -60,8 +60,6 @@ class GeckoInstance(object):
|
||||
# AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_APPLICATION
|
||||
"extensions.autoDisableScopes": 0,
|
||||
"extensions.enabledScopes": 5,
|
||||
# Disable metadata caching for installed add-ons by default
|
||||
"extensions.getAddons.cache.enabled": False,
|
||||
# Disable intalling any distribution add-ons
|
||||
"extensions.installDistroAddons": False,
|
||||
# Make sure Shield doesn't hit the network.
|
||||
@ -73,8 +71,6 @@ class GeckoInstance(object):
|
||||
# Turn off extension updates so they don't bother tests
|
||||
"extensions.update.enabled": False,
|
||||
"extensions.update.notifyUser": False,
|
||||
# Make sure opening about:addons won"t hit the network
|
||||
"extensions.webservice.discoverURL": "http://%(server)s/dummy/discoveryURL",
|
||||
|
||||
# Allow the application to have focus even it runs in the background
|
||||
"focusmanager.testmode": True,
|
||||
|
@ -195,9 +195,6 @@ const RECOMMENDED_PREFS = new Map([
|
||||
["extensions.autoDisableScopes", 0],
|
||||
["extensions.enabledScopes", 5],
|
||||
|
||||
// Disable metadata caching for installed add-ons by default
|
||||
["extensions.getAddons.cache.enabled", false],
|
||||
|
||||
// Disable installing any distribution extensions or add-ons.
|
||||
// Should be set in profile.
|
||||
["extensions.installDistroAddons", false],
|
||||
@ -206,9 +203,6 @@ const RECOMMENDED_PREFS = new Map([
|
||||
["extensions.update.enabled", false],
|
||||
["extensions.update.notifyUser", false],
|
||||
|
||||
// Make sure opening about:addons will not hit the network
|
||||
["extensions.webservice.discoverURL", "http://%(server)s/dummy/discoveryURL"],
|
||||
|
||||
// Allow the application to have focus even it runs in the background
|
||||
["focusmanager.testmode", true],
|
||||
|
||||
|
@ -29,9 +29,6 @@ config = {
|
||||
"MAR_CHANNEL_ID=firefox-mozilla-beta"),
|
||||
] + [
|
||||
# File, from, to
|
||||
("build/mozconfig.common",
|
||||
"MOZ_REQUIRE_SIGNING=${MOZ_REQUIRE_SIGNING-0}",
|
||||
"MOZ_REQUIRE_SIGNING=${MOZ_REQUIRE_SIGNING-1}"),
|
||||
("build/mozconfig.common",
|
||||
"# Disable enforcing that add-ons are signed by the trusted root",
|
||||
"# Enable enforcing that add-ons are signed by the trusted root")
|
||||
|
@ -19,9 +19,6 @@ config = {
|
||||
("build/mozconfig.common",
|
||||
"# Enable enforcing that add-ons are signed by the trusted root",
|
||||
"# Disable enforcing that add-ons are signed by the trusted root"),
|
||||
("build/mozconfig.common",
|
||||
"MOZ_REQUIRE_SIGNING=${MOZ_REQUIRE_SIGNING-1}",
|
||||
"MOZ_REQUIRE_SIGNING=${MOZ_REQUIRE_SIGNING-0}"),
|
||||
],
|
||||
"vcs_share_base": os.path.join(ABS_WORK_DIR, 'hg-shared'),
|
||||
# Pull from ESR repo, since we have already branched it and have landed esr-specific patches on it
|
||||
|
@ -34,11 +34,8 @@ user_pref("dom.send_after_paint_to_content", true);
|
||||
// Only load extensions from the application and user profile
|
||||
// AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_APPLICATION
|
||||
user_pref("extensions.enabledScopes", 5);
|
||||
user_pref("extensions.legacy.enabled", true);
|
||||
// Turn off extension updates so they don't bother tests
|
||||
user_pref("extensions.update.enabled", false);
|
||||
// Prevent network access for recommendations by default. The payload is {"results":[]}.
|
||||
user_pref("extensions.getAddons.discovery.api_url", "data:;base64,eyJyZXN1bHRzIjpbXX0%3D");
|
||||
// Disable useragent updates.
|
||||
user_pref("general.useragent.updates.enabled", false);
|
||||
// Ensure WR doesn't get enabled in tests unless we do it explicitly with the MOZ_WEBRENDER envvar.
|
||||
@ -49,7 +46,6 @@ user_pref("media.gmp-manager.updateEnabled", false);
|
||||
user_pref("security.certerrors.mitm.priming.enabled", false);
|
||||
// Make enablePrivilege continue to work for test code. :-(
|
||||
user_pref("security.turn_off_all_security_so_that_viruses_can_take_over_this_computer", true);
|
||||
user_pref("xpinstall.signatures.required", false);
|
||||
// Prevent Remote Settings to issue non local connections.
|
||||
user_pref("services.settings.server", "http://localhost/remote-settings-dummy/v1");
|
||||
// Ensure autoplay is enabled for all platforms.
|
||||
|
@ -50,15 +50,10 @@ user_pref("extensions.autoDisableScopes", 10);
|
||||
user_pref("extensions.blocklist.enabled", false);
|
||||
user_pref("extensions.blocklist.url", "http://127.0.0.1/extensions-dummy/blocklistURL");
|
||||
user_pref("extensions.checkCompatibility", false);
|
||||
user_pref("extensions.getAddons.get.url", "http://127.0.0.1/extensions-dummy/repositoryGetURL");
|
||||
user_pref("extensions.getAddons.getWithPerformance.url", "http://127.0.0.1/extensions-dummy/repositoryGetWithPerformanceURL");
|
||||
user_pref("extensions.getAddons.search.browseURL", "http://127.0.0.1/extensions-dummy/repositoryBrowseURL");
|
||||
user_pref("extensions.hotfix.url", "http://127.0.0.1/extensions-dummy/hotfixURL");
|
||||
user_pref("extensions.systemAddon.update.url", "http://127.0.0.1/dummy-system-addons.xml");
|
||||
user_pref("extensions.update.background.url", "http://127.0.0.1/extensions-dummy/updateBackgroundURL");
|
||||
user_pref("extensions.update.notifyUser", false);
|
||||
user_pref("extensions.update.url", "http://127.0.0.1/extensions-dummy/updateURL");
|
||||
user_pref("extensions.webservice.discoverURL", "http://127.0.0.1/extensions-dummy/discoveryURL");
|
||||
user_pref("identity.fxaccounts.auth.uri", "https://127.0.0.1/fxa-dummy/");
|
||||
user_pref("identity.fxaccounts.migrateToDevEdition", false);
|
||||
// Avoid idle-daily notifications, to avoid expensive operations that may
|
||||
|
@ -38,7 +38,6 @@ user_pref("dom.use_xbl_scopes_for_remote_xul", false);
|
||||
user_pref("extensions.autoDisableScopes", 0);
|
||||
// Disable blocklist updates so we don't have them reported as leaks
|
||||
user_pref("extensions.blocklist.enabled", false);
|
||||
user_pref("extensions.getAddons.cache.enabled", false);
|
||||
user_pref("extensions.systemAddon.update.url", "http://localhost/dummy-system-addons.xml");
|
||||
user_pref("gfx.color_management.force_srgb", true);
|
||||
user_pref("gfx.color_management.mode", 2);
|
||||
|
@ -105,13 +105,6 @@ user_pref("extensions.blocklist.itemURL", "http://{server}/extensions-dummy/bloc
|
||||
user_pref("extensions.blocklist.url", "http://{server}/extensions-dummy/blocklistURL");
|
||||
// XPI extensions are required for test harnesses to load
|
||||
user_pref("extensions.defaultProviders.enabled", true);
|
||||
// Disable metadata caching for installed add-ons by default
|
||||
user_pref("extensions.getAddons.cache.enabled", false);
|
||||
// Make sure AddonRepository won't hit the network
|
||||
user_pref("extensions.getAddons.get.url", "http://{server}/extensions-dummy/repositoryGetURL");
|
||||
user_pref("extensions.getAddons.getWithPerformance.url", "http://{server}/extensions-dummy/repositoryGetWithPerformanceURL");
|
||||
user_pref("extensions.getAddons.search.browseURL", "http://{server}/extensions-dummy/repositoryBrowseURL");
|
||||
user_pref("extensions.hotfix.url", "http://{server}/extensions-dummy/hotfixURL");
|
||||
// Disable intalling any distribution add-ons
|
||||
user_pref("extensions.installDistroAddons", false);
|
||||
// Disable Screenshots by default for now
|
||||
@ -120,8 +113,6 @@ user_pref("extensions.systemAddon.update.url", "http://{server}/dummy-system-add
|
||||
user_pref("extensions.update.background.url", "http://{server}/extensions-dummy/updateBackgroundURL");
|
||||
// Point update checks to the local testing server for fast failures
|
||||
user_pref("extensions.update.url", "http://{server}/extensions-dummy/updateURL");
|
||||
// Make sure opening about:addons won't hit the network
|
||||
user_pref("extensions.webservice.discoverURL", "http://{server}/extensions-dummy/discoveryURL");
|
||||
user_pref("extensions.privatebrowsing.notification", true);
|
||||
user_pref("findbar.highlightAll", false);
|
||||
user_pref("findbar.modalHighlight", false);
|
||||
|
@ -153,7 +153,6 @@ class ts_paint(TsBase):
|
||||
@register_test()
|
||||
class ts_paint_webext(ts_paint):
|
||||
webextensions = '${talos}/webextensions/dummy/dummy.xpi'
|
||||
preferences = {'xpinstall.signatures.required': False}
|
||||
|
||||
|
||||
@register_test()
|
||||
@ -555,7 +554,6 @@ class tp5o(PageloaderTest):
|
||||
@register_test()
|
||||
class tp5o_webext(tp5o):
|
||||
webextensions = '${talos}/webextensions/dummy/dummy.xpi'
|
||||
preferences = {'xpinstall.signatures.required': False}
|
||||
|
||||
|
||||
@register_test()
|
||||
|
@ -313,7 +313,6 @@ class Test_get_config(object):
|
||||
# assert test_config['unit'] == 'ms'
|
||||
# TODO: this isn't overriden
|
||||
# assert test_config['webextensions'] != '${talos}/webextensions/dummy/dummy-signed.xpi'
|
||||
assert test_config['preferences'] == {'xpinstall.signatures.required': False}
|
||||
|
||||
def test_ts_paint_heavy_has_expected_attributes(self):
|
||||
config = get_config(self.argv_ts_paint_heavy)
|
||||
@ -633,7 +632,6 @@ class Test_get_config(object):
|
||||
assert test_config['timeout'] == 1800
|
||||
assert test_config['unit'] == 'ms'
|
||||
assert test_config['webextensions'] == '${talos}/webextensions/dummy/dummy.xpi'
|
||||
assert test_config['preferences'] == {'xpinstall.signatures.required': False}
|
||||
|
||||
@mock.patch('talos.config.build_manifest', conftest.patched_build_manifest)
|
||||
def test_tp5o_scroll_has_expected_attributes(self):
|
||||
|
@ -1 +1 @@
|
||||
{'deviceroot': '', 'dirs': {}, 'repository': 'https://hg.mozilla.org/releases/mozilla-release', 'buildid': '20131205075310', 'results_log': 'pathtoresults_log', 'symbols_path': None, 'bcontroller_config': 'pathtobcontroller', 'host': '', 'browser_name': 'Firefox', 'sourcestamp': '39faf812aaec', 'remote': False, 'child_process': 'plugin-container', 'browser_version': '26.0', 'extra_args': '', 'develop': True, 'preferences': {'browser.display.overlaynavbuttons': False, 'extensions.getAddons.get.url': 'http://127.0.0.1/extensions-dummy/repositoryGetURL', 'dom.max_chrome_script_run_time': 0, 'network.proxy.type': 1, 'extensions.update.background.url': 'http://127.0.0.1/extensions-dummy/updateBackgroundURL', 'network.proxy.http': 'localhost', 'plugins.update.url': 'http://127.0.0.1/plugins-dummy/updateCheckURL', 'dom.max_script_run_time': 0, 'extensions.update.enabled': False, 'browser.safebrowsing.keyURL': 'http://127.0.0.1/safebrowsing-dummy/newkey', 'media.navigator.permission.disabled': True, 'app.update.checkInstallTime': False, 'app.update.disabledForTesting': True, 'extensions.blocklist.url': 'http://127.0.0.1/extensions-dummy/blocklistURL', 'browser.EULA.override': True, 'extensions.checkCompatibility': False, 'talos.logfile': 'pathtofile', 'browser.safebrowsing.gethashURL': 'http://127.0.0.1/safebrowsing-dummy/gethash', 'extensions.hotfix.url': 'http://127.0.0.1/extensions-dummy/hotfixURL', 'dom.disable_window_move_resize': True, 'network.proxy.http_port': 80, 'browser.dom.window.dump.enabled': True, 'extensions.update.url': 'http://127.0.0.1/extensions-dummy/updateURL', 'browser.chrome.dynamictoolbar': False, 'browser.link.open_newwindow': 2, 'security.turn_off_all_security_so_that_viruses_can_take_over_this_computer': True, 'dom.disable_open_during_load': False, 'extensions.getAddons.search.browseURL': 'http://127.0.0.1/extensions-dummy/repositoryBrowseURL', 'browser.cache.disk.smart_size.enabled': False, 'extensions.getAddons.getWithPerformance.url': 'http://127.0.0.1/extensions-dummy/repositoryGetWithPerformanceURL', 'hangmonitor.timeout': 0, 'dom.send_after_paint_to_content': True, 'security.fileuri.strict_origin_policy': False, 'media.capturestream_hints.enabled': True, 'extensions.update.notifyUser': False, 'extensions.blocklist.enabled': False, 'browser.bookmarks.max_backups': 0, 'browser.shell.checkDefaultBrowser': False, 'media.peerconnection.enabled': True, 'dom.disable_window_flip': True, 'security.enable_java': False, 'browser.warnOnQuit': False, 'media.navigator.enabled': True, 'browser.safebrowsing.updateURL': 'http://127.0.0.1/safebrowsing-dummy/update', 'dom.allow_scripts_to_close_windows': True, 'extensions.webservice.discoverURL': 'http://127.0.0.1/extensions-dummy/discoveryURL'}, 'test_timeout': 1200, 'title': 'qm-pxp01', 'error_filename': 'pathtoerrorfile', 'webserver': 'localhost:15707', 'browser_path':ffox_path, 'port': 20701, 'browser_log': 'browser_output.txt', 'process': 'firefox.exe', 'xperf_path': 'C:/Program Files/Microsoft Windows Performance Toolkit/xperf.exe', 'extensions': ['pathtopageloader'], 'fennecIDs': '', 'init_url': 'http://localhost:15707/getInfo.html', 'browser_wait': 5}
|
||||
{'deviceroot': '', 'dirs': {}, 'repository': 'https://hg.mozilla.org/releases/mozilla-release', 'buildid': '20131205075310', 'results_log': 'pathtoresults_log', 'symbols_path': None, 'bcontroller_config': 'pathtobcontroller', 'host': '', 'browser_name': 'Firefox', 'sourcestamp': '39faf812aaec', 'remote': False, 'child_process': 'plugin-container', 'browser_version': '26.0', 'extra_args': '', 'develop': True, 'preferences': {'browser.display.overlaynavbuttons': False, 'dom.max_chrome_script_run_time': 0, 'network.proxy.type': 1, 'extensions.update.background.url': 'http://127.0.0.1/extensions-dummy/updateBackgroundURL', 'network.proxy.http': 'localhost', 'plugins.update.url': 'http://127.0.0.1/plugins-dummy/updateCheckURL', 'dom.max_script_run_time': 0, 'extensions.update.enabled': False, 'browser.safebrowsing.keyURL': 'http://127.0.0.1/safebrowsing-dummy/newkey', 'media.navigator.permission.disabled': True, 'app.update.checkInstallTime': False, 'app.update.disabledForTesting': True, 'extensions.blocklist.url': 'http://127.0.0.1/extensions-dummy/blocklistURL', 'browser.EULA.override': True, 'extensions.checkCompatibility': False, 'talos.logfile': 'pathtofile', 'browser.safebrowsing.gethashURL': 'http://127.0.0.1/safebrowsing-dummy/gethash', 'dom.disable_window_move_resize': True, 'network.proxy.http_port': 80, 'browser.dom.window.dump.enabled': True, 'extensions.update.url': 'http://127.0.0.1/extensions-dummy/updateURL', 'browser.chrome.dynamictoolbar': False, 'browser.link.open_newwindow': 2, 'security.turn_off_all_security_so_that_viruses_can_take_over_this_computer': True, 'dom.disable_open_during_load': False, 'browser.cache.disk.smart_size.enabled': False, 'hangmonitor.timeout': 0, 'dom.send_after_paint_to_content': True, 'security.fileuri.strict_origin_policy': False, 'media.capturestream_hints.enabled': True, 'extensions.update.notifyUser': False, 'extensions.blocklist.enabled': False, 'browser.bookmarks.max_backups': 0, 'browser.shell.checkDefaultBrowser': False, 'media.peerconnection.enabled': True, 'dom.disable_window_flip': True, 'security.enable_java': False, 'browser.warnOnQuit': False, 'media.navigator.enabled': True, 'browser.safebrowsing.updateURL': 'http://127.0.0.1/safebrowsing-dummy/update', 'dom.allow_scripts_to_close_windows': True, 'test_timeout': 1200, 'title': 'qm-pxp01', 'error_filename': 'pathtoerrorfile', 'webserver': 'localhost:15707', 'browser_path':ffox_path, 'port': 20701, 'browser_log': 'browser_output.txt', 'process': 'firefox.exe', 'xperf_path': 'C:/Program Files/Microsoft Windows Performance Toolkit/xperf.exe', 'extensions': ['pathtopageloader'], 'fennecIDs': '', 'init_url': 'http://localhost:15707/getInfo.html', 'browser_wait': 5}
|
||||
|
@ -65,9 +65,6 @@ class TPSTestRunner(object):
|
||||
'browser.warnOnQuit': False,
|
||||
# Allow installing extensions dropped into the profile folder
|
||||
'extensions.autoDisableScopes': 10,
|
||||
'extensions.getAddons.get.url': 'http://127.0.0.1:4567/addons/api/%IDS%.json',
|
||||
# Our pretend addons server doesn't support metadata...
|
||||
'extensions.getAddons.cache.enabled': False,
|
||||
'extensions.install.requireSecureOrigin': False,
|
||||
'extensions.update.enabled': False,
|
||||
# Don't open a dialog to show available add-on updates
|
||||
@ -77,10 +74,8 @@ class TPSTestRunner(object):
|
||||
'services.sync.autoconnectDelay': 60 * 60 * 10,
|
||||
'toolkit.startup.max_resumed_crashes': -1,
|
||||
# hrm - not sure what the release/beta channels will do?
|
||||
'xpinstall.signatures.required': False,
|
||||
'services.sync.testing.tps': True,
|
||||
'engine.bookmarks.repair.enabled': False,
|
||||
'extensions.legacy.enabled': True,
|
||||
}
|
||||
|
||||
debug_preferences = {
|
||||
|
@ -45,7 +45,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
AddonManager: "resource://gre/modules/AddonManager.jsm",
|
||||
AddonManagerPrivate: "resource://gre/modules/AddonManager.jsm",
|
||||
AddonSettings: "resource://gre/modules/addons/AddonSettings.jsm",
|
||||
AMTelemetry: "resource://gre/modules/AddonManager.jsm",
|
||||
AppConstants: "resource://gre/modules/AppConstants.jsm",
|
||||
AsyncShutdown: "resource://gre/modules/AsyncShutdown.jsm",
|
||||
ExtensionPermissions: "resource://gre/modules/ExtensionPermissions.jsm",
|
||||
@ -1844,14 +1843,12 @@ class Extension extends ExtensionData {
|
||||
return (
|
||||
this.addonData.signedState === AddonManager.SIGNEDSTATE_PRIVILEGED ||
|
||||
this.addonData.signedState === AddonManager.SIGNEDSTATE_SYSTEM ||
|
||||
this.addonData.builtIn ||
|
||||
(AppConstants.MOZ_ALLOW_LEGACY_EXTENSIONS &&
|
||||
this.addonData.temporarilyInstalled)
|
||||
this.addonData.builtIn
|
||||
);
|
||||
}
|
||||
|
||||
get experimentsAllowed() {
|
||||
return AddonSettings.ALLOW_LEGACY_EXTENSIONS || this.isPrivileged;
|
||||
return this.isPrivileged;
|
||||
}
|
||||
|
||||
saveStartupData() {
|
||||
@ -2143,15 +2140,6 @@ class Extension extends ExtensionData {
|
||||
origins: [],
|
||||
});
|
||||
await StartupCache.clearAddonData(addonData.id);
|
||||
|
||||
// Record a telemetry event for the extension automatically allowed on private browsing as
|
||||
// part of the Firefox upgrade.
|
||||
AMTelemetry.recordActionEvent({
|
||||
extra: { addonId: addonData.id },
|
||||
object: "appUpgrade",
|
||||
action: "privateBrowsingAllowed",
|
||||
value: "on",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,14 +2,6 @@
|
||||
|
||||
// This test checks whether the theme experiments work
|
||||
|
||||
add_task(async function setup() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
["extensions.legacy.enabled", AppConstants.MOZ_ALLOW_LEGACY_EXTENSIONS],
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function test_experiment_static_theme() {
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
@ -59,46 +51,28 @@ add_task(async function test_experiment_static_theme() {
|
||||
await extension.startup();
|
||||
|
||||
const testExperimentApplied = rootEl => {
|
||||
if (AppConstants.MOZ_ALLOW_LEGACY_EXTENSIONS) {
|
||||
is(
|
||||
rootEl.style.getPropertyValue("--some-color-property"),
|
||||
hexToCSS("#ff00ff"),
|
||||
"Color property should be parsed and set."
|
||||
);
|
||||
ok(
|
||||
rootEl.style
|
||||
.getPropertyValue("--some-image-property")
|
||||
.startsWith("url("),
|
||||
"Image property should be parsed."
|
||||
);
|
||||
ok(
|
||||
rootEl.style
|
||||
.getPropertyValue("--some-image-property")
|
||||
.endsWith("background.jpg)"),
|
||||
"Image property should be set."
|
||||
);
|
||||
is(
|
||||
rootEl.style.getPropertyValue("--some-random-property"),
|
||||
"no-repeat",
|
||||
"Generic Property should be set."
|
||||
);
|
||||
} else {
|
||||
is(
|
||||
rootEl.style.getPropertyValue("--some-color-property"),
|
||||
"",
|
||||
"Color property should be unset"
|
||||
);
|
||||
is(
|
||||
rootEl.style.getPropertyValue("--some-image-property"),
|
||||
"",
|
||||
"Image property should be unset"
|
||||
);
|
||||
is(
|
||||
rootEl.style.getPropertyValue("--some-random-property"),
|
||||
"",
|
||||
"Generic Property should be unset."
|
||||
);
|
||||
}
|
||||
is(
|
||||
rootEl.style.getPropertyValue("--some-color-property"),
|
||||
hexToCSS("#ff00ff"),
|
||||
"Color property should be parsed and set."
|
||||
);
|
||||
ok(
|
||||
rootEl.style
|
||||
.getPropertyValue("--some-image-property")
|
||||
.startsWith("url("),
|
||||
"Image property should be parsed."
|
||||
);
|
||||
ok(
|
||||
rootEl.style
|
||||
.getPropertyValue("--some-image-property")
|
||||
.endsWith("background.jpg)"),
|
||||
"Image property should be set."
|
||||
);
|
||||
is(
|
||||
rootEl.style.getPropertyValue("--some-random-property"),
|
||||
"no-repeat",
|
||||
"Generic Property should be set."
|
||||
);
|
||||
};
|
||||
|
||||
info("Testing that current window updated with the experiment applied");
|
||||
@ -198,46 +172,28 @@ add_task(async function test_experiment_dynamic_theme() {
|
||||
await extension.awaitMessage("theme-updated");
|
||||
|
||||
const testExperimentApplied = rootEl => {
|
||||
if (AppConstants.MOZ_ALLOW_LEGACY_EXTENSIONS) {
|
||||
is(
|
||||
rootEl.style.getPropertyValue("--some-color-property"),
|
||||
hexToCSS("#ff00ff"),
|
||||
"Color property should be parsed and set."
|
||||
);
|
||||
ok(
|
||||
rootEl.style
|
||||
.getPropertyValue("--some-image-property")
|
||||
.startsWith("url("),
|
||||
"Image property should be parsed."
|
||||
);
|
||||
ok(
|
||||
rootEl.style
|
||||
.getPropertyValue("--some-image-property")
|
||||
.endsWith("background.jpg)"),
|
||||
"Image property should be set."
|
||||
);
|
||||
is(
|
||||
rootEl.style.getPropertyValue("--some-random-property"),
|
||||
"no-repeat",
|
||||
"Generic Property should be set."
|
||||
);
|
||||
} else {
|
||||
is(
|
||||
rootEl.style.getPropertyValue("--some-color-property"),
|
||||
"",
|
||||
"Color property should be unset"
|
||||
);
|
||||
is(
|
||||
rootEl.style.getPropertyValue("--some-image-property"),
|
||||
"",
|
||||
"Image property should be unset"
|
||||
);
|
||||
is(
|
||||
rootEl.style.getPropertyValue("--some-random-property"),
|
||||
"",
|
||||
"Generic Property should be unset."
|
||||
);
|
||||
}
|
||||
is(
|
||||
rootEl.style.getPropertyValue("--some-color-property"),
|
||||
hexToCSS("#ff00ff"),
|
||||
"Color property should be parsed and set."
|
||||
);
|
||||
ok(
|
||||
rootEl.style
|
||||
.getPropertyValue("--some-image-property")
|
||||
.startsWith("url("),
|
||||
"Image property should be parsed."
|
||||
);
|
||||
ok(
|
||||
rootEl.style
|
||||
.getPropertyValue("--some-image-property")
|
||||
.endsWith("background.jpg)"),
|
||||
"Image property should be set."
|
||||
);
|
||||
is(
|
||||
rootEl.style.getPropertyValue("--some-random-property"),
|
||||
"no-repeat",
|
||||
"Generic Property should be set."
|
||||
);
|
||||
};
|
||||
testExperimentApplied(root);
|
||||
|
||||
@ -343,44 +299,26 @@ add_task(async function test_experiment_stylesheet() {
|
||||
|
||||
await extension.startup();
|
||||
|
||||
if (AppConstants.MOZ_ALLOW_LEGACY_EXTENSIONS) {
|
||||
// Wait for stylesheet load.
|
||||
await BrowserTestUtils.waitForCondition(
|
||||
() => computedStyle.fill === expectedFill
|
||||
);
|
||||
// Wait for stylesheet load.
|
||||
await BrowserTestUtils.waitForCondition(
|
||||
() => computedStyle.fill === expectedFill
|
||||
);
|
||||
|
||||
is(
|
||||
root.style.getPropertyValue("--menu-button-background"),
|
||||
expectedColor,
|
||||
"Variable should be parsed and set."
|
||||
);
|
||||
is(
|
||||
computedStyle.backgroundColor,
|
||||
expectedColor,
|
||||
"Menu button should be have correct background"
|
||||
);
|
||||
is(
|
||||
computedStyle.fill,
|
||||
expectedFill,
|
||||
"Menu button should be have correct fill"
|
||||
);
|
||||
} else {
|
||||
is(
|
||||
root.style.getPropertyValue("--menu-button-background"),
|
||||
"",
|
||||
"Variable should be unset"
|
||||
);
|
||||
isnot(
|
||||
computedStyle.backgroundColor,
|
||||
expectedColor,
|
||||
"Menu button should not have custom background"
|
||||
);
|
||||
isnot(
|
||||
computedStyle.fill,
|
||||
expectedFill,
|
||||
"Menu button should not have stylesheet fill"
|
||||
);
|
||||
}
|
||||
is(
|
||||
root.style.getPropertyValue("--menu-button-background"),
|
||||
expectedColor,
|
||||
"Variable should be parsed and set."
|
||||
);
|
||||
is(
|
||||
computedStyle.backgroundColor,
|
||||
expectedColor,
|
||||
"Menu button should be have correct background"
|
||||
);
|
||||
is(
|
||||
computedStyle.fill,
|
||||
expectedFill,
|
||||
"Menu button should be have correct fill"
|
||||
);
|
||||
|
||||
await extension.unload();
|
||||
|
||||
|
@ -73,76 +73,3 @@ add_task(async function test_dynamic_theme() {
|
||||
|
||||
await extension.unload();
|
||||
});
|
||||
|
||||
add_task(async function test_experiments_enabled() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
["extensions.legacy.enabled", AppConstants.MOZ_ALLOW_LEGACY_EXTENSIONS],
|
||||
],
|
||||
});
|
||||
|
||||
info(
|
||||
"Testing that experiments are handled correctly when legacy pref is enabled"
|
||||
);
|
||||
|
||||
const extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
theme: {
|
||||
properties: {
|
||||
such_property: "much_wow",
|
||||
unknown_property: "very_unknown",
|
||||
},
|
||||
},
|
||||
theme_experiment: {
|
||||
properties: {
|
||||
such_property: "--such-property",
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
if (!AppConstants.MOZ_ALLOW_LEGACY_EXTENSIONS) {
|
||||
await waitForConsole(
|
||||
extension.startup,
|
||||
"This extension is not allowed to run theme experiments"
|
||||
);
|
||||
} else {
|
||||
await waitForConsole(
|
||||
extension.startup,
|
||||
"Unrecognized theme property found: properties.unknown_property"
|
||||
);
|
||||
}
|
||||
await extension.unload();
|
||||
|
||||
await SpecialPowers.popPrefEnv();
|
||||
});
|
||||
|
||||
add_task(async function test_experiments_disabled() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["extensions.legacy.enabled", false]],
|
||||
});
|
||||
|
||||
info(
|
||||
"Testing that experiments are handled correctly when legacy pref is disabled"
|
||||
);
|
||||
|
||||
const extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
theme: {
|
||||
properties: {
|
||||
such_property: "much_wow",
|
||||
},
|
||||
},
|
||||
theme_experiment: {
|
||||
properties: {
|
||||
such_property: "--such-property",
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
await waitForConsole(
|
||||
extension.startup,
|
||||
"This extension is not allowed to run theme experiments"
|
||||
);
|
||||
await extension.unload();
|
||||
await SpecialPowers.popPrefEnv();
|
||||
});
|
||||
|
@ -160,7 +160,7 @@ add_task(async function test_bundled_experiments() {
|
||||
{
|
||||
isPrivileged: false,
|
||||
temporarilyInstalled: true,
|
||||
shouldHaveExperiments: AppConstants.MOZ_ALLOW_LEGACY_EXTENSIONS,
|
||||
shouldHaveExperiments: true,
|
||||
},
|
||||
{
|
||||
isPrivileged: false,
|
||||
|
@ -14,38 +14,6 @@ AddonTestUtils.createAppInfo(
|
||||
);
|
||||
AddonTestUtils.usePrivilegedSignatures = false;
|
||||
|
||||
// Assert on the expected "addonsManager.action" telemetry events (and optional filter events to verify
|
||||
// by using a given actionType).
|
||||
function assertActionAMTelemetryEvent(
|
||||
expectedActionEvents,
|
||||
assertMessage,
|
||||
{ actionType } = {}
|
||||
) {
|
||||
const snapshot = Services.telemetry.snapshotEvents(
|
||||
Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS,
|
||||
true
|
||||
);
|
||||
|
||||
ok(
|
||||
snapshot.parent && snapshot.parent.length > 0,
|
||||
"Got parent telemetry events in the snapshot"
|
||||
);
|
||||
|
||||
const events = snapshot.parent
|
||||
.filter(([timestamp, category, method, object, value, extra]) => {
|
||||
return (
|
||||
category === "addonsManager" &&
|
||||
method === "action" &&
|
||||
(!actionType ? true : extra && extra.action === actionType)
|
||||
);
|
||||
})
|
||||
.map(([timestamp, category, method, object, value, extra]) => {
|
||||
return { method, object, value, extra };
|
||||
});
|
||||
|
||||
Assert.deepEqual(events, expectedActionEvents, assertMessage);
|
||||
}
|
||||
|
||||
async function runIncognitoTest(
|
||||
extensionData,
|
||||
privateBrowsingAllowed,
|
||||
@ -221,10 +189,4 @@ add_task(async function test_extension_incognito_spanning_grandfathered() {
|
||||
extra: { addonId, action: "privateBrowsingAllowed" },
|
||||
},
|
||||
];
|
||||
|
||||
assertActionAMTelemetryEvent(
|
||||
expectedEvents,
|
||||
"Got the expected telemetry events for the grandfathered extensions",
|
||||
{ actionType: "privateBrowsingAllowed" }
|
||||
);
|
||||
});
|
||||
|
@ -255,7 +255,6 @@ const DEFAULT_ENVIRONMENT_PREFS = new Map([
|
||||
["extensions.formautofill.addresses.enabled", { what: RECORD_PREF_VALUE }],
|
||||
["extensions.formautofill.creditCards.enabled", { what: RECORD_PREF_VALUE }],
|
||||
["extensions.htmlaboutaddons.enabled", { what: RECORD_PREF_VALUE }],
|
||||
["extensions.legacy.enabled", { what: RECORD_PREF_VALUE }],
|
||||
["extensions.strictCompatibility", { what: RECORD_PREF_VALUE }],
|
||||
["extensions.update.enabled", { what: RECORD_PREF_VALUE }],
|
||||
["extensions.update.url", { what: RECORD_PREF_VALUE }],
|
||||
@ -298,7 +297,6 @@ const DEFAULT_ENVIRONMENT_PREFS = new Map([
|
||||
["security.pki.mitm_detected", { what: RECORD_PREF_VALUE }],
|
||||
["security.mixed_content.block_active_content", { what: RECORD_PREF_VALUE }],
|
||||
["security.mixed_content.block_display_content", { what: RECORD_PREF_VALUE }],
|
||||
["xpinstall.signatures.required", { what: RECORD_PREF_VALUE }],
|
||||
]);
|
||||
|
||||
const LOGGER_NAME = "Toolkit.Telemetry";
|
||||
|
@ -471,21 +471,6 @@ add_task(async function test_can_upload() {
|
||||
PermissionTestUtils.remove(testHttpsUri, HC_PERMISSION);
|
||||
});
|
||||
|
||||
add_task(async function test_hct_for_discopane() {
|
||||
const discoHost = "https://discovery.addons.mozilla.org";
|
||||
|
||||
let discoHttpsUri = Services.io.newURI(discoHost);
|
||||
let permission = PermissionTestUtils.testPermission(
|
||||
discoHttpsUri,
|
||||
HC_PERMISSION
|
||||
);
|
||||
|
||||
ok(
|
||||
permission == Services.perms.ALLOW_ACTION,
|
||||
"Disco Pane needs Hybrid Content Permission for Telemetry data upload"
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function test_init_rejects() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [[TelemetryUtils.Preferences.FhrUploadEnabled, true]],
|
||||
|
@ -5,11 +5,6 @@
|
||||
#LOCALIZATION NOTE (uninstallNotice) %S is the add-on name
|
||||
uninstallNotice=%S has been removed.
|
||||
|
||||
#LOCALIZATION NOTE (numReviews): Semicolon-separated list of plural forms.
|
||||
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
# #1 is the number of reviews
|
||||
numReviews=#1 review;#1 reviews
|
||||
|
||||
#LOCALIZATION NOTE (dateUpdated) %S is the date the addon was last updated
|
||||
dateUpdated=Updated %S
|
||||
|
||||
@ -61,7 +56,6 @@ installCancelled=Install cancelled
|
||||
#LOCALIZATION NOTE (details.notification.incompatible) %1$S is the add-on name, %2$S is brand name, %3$S is application version
|
||||
details.notification.incompatible=%1$S is incompatible with %2$S %3$S.
|
||||
#LOCALIZATION NOTE (details.notification.unsigned, details.notification.unsignedAndDisabled) %1$S is the add-on name, %2$S is brand name
|
||||
details.notification.unsignedAndDisabled=%1$S could not be verified for use in %2$S and has been disabled.
|
||||
details.notification.unsigned=%1$S could not be verified for use in %2$S. Proceed with caution.
|
||||
details.notification.unsigned.link=More Information
|
||||
#LOCALIZATION NOTE (details.notification.blocked) %1$S is the add-on name
|
||||
@ -100,11 +94,6 @@ type.service.name=Services
|
||||
type.legacy.name=Legacy Extensions
|
||||
type.unsupported.name=Unsupported
|
||||
|
||||
#LOCALIZATION NOTE(legacyWarning.description) %S is the brandShortName
|
||||
legacyWarning.description=Missing something? Some extensions are no longer supported by %S.
|
||||
#LOCALIZATION NOTE(legacyThemeWarning.description) %S is the brandShortName
|
||||
legacyThemeWarning.description=Missing something? Some themes are no longer supported by %S.
|
||||
|
||||
#LOCALIZATION NOTE(listHeading.discover) %S is the brandShortName
|
||||
listHeading.discover=Personalize Your %S
|
||||
listHeading.extension=Manage Your Extensions
|
||||
|
@ -192,30 +192,9 @@ detail-rating =
|
||||
addon-restart-now =
|
||||
.label = Restart now
|
||||
|
||||
disabled-unsigned-heading =
|
||||
.value = Some add-ons have been disabled
|
||||
|
||||
disabled-unsigned-description =
|
||||
The following add-ons have not been verified for use in { -brand-short-name }. You can
|
||||
<label data-l10n-name="find-addons">find replacements</label> or ask the developer to get them verified.
|
||||
|
||||
disabled-unsigned-learn-more = Learn more about our efforts to help keep you safe online.
|
||||
|
||||
disabled-unsigned-devinfo =
|
||||
Developers interested in getting their add-ons verified can continue by reading our
|
||||
<label data-l10n-name="learn-more">manual</label>.
|
||||
|
||||
plugin-deprecation-description =
|
||||
Missing something? Some plugins are no longer supported by { -brand-short-name }. <label data-l10n-name="learn-more">Learn More.</label>
|
||||
|
||||
legacy-warning-show-legacy = Show legacy extensions
|
||||
|
||||
legacy-extensions =
|
||||
.value = Legacy Extensions
|
||||
|
||||
legacy-extensions-description =
|
||||
These extensions do not meet current { -brand-short-name } standards so they have been deactivated. <label data-l10n-name="legacy-learn-more">Learn about the changes to add-ons</label>
|
||||
|
||||
private-browsing-description2 =
|
||||
{ -brand-short-name } is changing how extensions work in private browsing. Any new extensions you add to
|
||||
{ -brand-short-name } won’t run by default in Private Windows. Unless you allow it in settings, the
|
||||
@ -223,10 +202,6 @@ private-browsing-description2 =
|
||||
there. We’ve made this change to keep your private browsing private.
|
||||
<label data-l10n-name="private-browsing-learn-more">Learn how to manage extension settings</label>
|
||||
|
||||
extensions-view-discopane =
|
||||
.name = Recommendations
|
||||
.tooltiptext = { extensions-view-discopane.name }
|
||||
|
||||
extensions-view-recent-updates =
|
||||
.name = Recent Updates
|
||||
.tooltiptext = { extensions-view-recent-updates.name }
|
||||
@ -343,24 +318,6 @@ shortcuts-card-collapse-button = Show Less
|
||||
go-back-button =
|
||||
.tooltiptext = Go back
|
||||
|
||||
## Recommended add-ons page
|
||||
|
||||
# Explanatory introduction to the list of recommended add-ons. The action word
|
||||
# ("recommends") in the final sentence is a link to external documentation.
|
||||
discopane-intro =
|
||||
Extensions and themes are like apps for your browser, and they let you
|
||||
protect passwords, download videos, find deals, block annoying ads, change
|
||||
how your browser looks, and much more. These small software programs are
|
||||
often developed by a third party. Here’s a selection { -brand-product-name }
|
||||
<a data-l10n-name="learn-more-trigger">recommends</a> for exceptional
|
||||
security, performance, and functionality.
|
||||
|
||||
# Notice to make user aware that the recommendations are personalized.
|
||||
discopane-notice-recommendations =
|
||||
Some of these recommendations are personalized. They are based on other
|
||||
extensions you’ve installed, profile preferences, and usage statistics.
|
||||
discopane-notice-learn-more = Learn more
|
||||
|
||||
privacy-policy = Privacy Policy
|
||||
|
||||
# Refers to the author of an add-on, shown below the name of the add-on.
|
||||
@ -404,7 +361,6 @@ addon-detail-author-label = Author
|
||||
addon-detail-version-label = Version
|
||||
addon-detail-last-updated-label = Last Updated
|
||||
addon-detail-homepage-label = Homepage
|
||||
addon-detail-rating-label = Rating
|
||||
|
||||
# The average rating that the add-on has received.
|
||||
# Variables:
|
||||
@ -417,15 +373,6 @@ five-star-rating =
|
||||
# $name (string) - The name of the add-on
|
||||
addon-name-disabled = { $name } (disabled)
|
||||
|
||||
# The number of reviews that an add-on has received on AMO.
|
||||
# Variables:
|
||||
# $numberOfReviews (number) - The number of reviews received
|
||||
addon-detail-reviews-link =
|
||||
{ $numberOfReviews ->
|
||||
[one] { $numberOfReviews } review
|
||||
*[other] { $numberOfReviews } reviews
|
||||
}
|
||||
|
||||
## Pending uninstall message bar
|
||||
|
||||
# Variables:
|
||||
@ -448,12 +395,6 @@ addon-detail-private-browsing-help = When allowed, the extension will have acces
|
||||
addon-detail-private-browsing-allow = Allow
|
||||
addon-detail-private-browsing-disallow = Don’t Allow
|
||||
|
||||
# This is the tooltip text for the recommended badge for an extension in about:addons. The
|
||||
# badge is a small icon displayed next to an extension when it is recommended on AMO.
|
||||
addon-badge-recommended =
|
||||
.title = Recommended
|
||||
.alt = Recommended
|
||||
|
||||
available-updates-heading = Available Updates
|
||||
recent-updates-heading = Recent Updates
|
||||
|
||||
@ -461,10 +402,3 @@ release-notes-loading = Loading…
|
||||
release-notes-error = Sorry, but there was an error loading the release notes.
|
||||
|
||||
addon-permissions-empty = This extension doesn’t require any permissions
|
||||
|
||||
recommended-extensions-heading = Recommended Extensions
|
||||
recommended-themes-heading = Recommended Themes
|
||||
|
||||
# A recommendation for the Firefox Color theme shown at the bottom of the theme
|
||||
# list view. The "Firefox Color" name itself should not be translated.
|
||||
recommended-theme-1 = Feeling creative? <a data-l10n-name="link">Build your own theme with Firefox Color.</a>
|
||||
|
@ -1,92 +0,0 @@
|
||||
# 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/.
|
||||
|
||||
abuse-report-title-extension = Report This Extension to { -vendor-short-name }
|
||||
abuse-report-title-theme = Report This Theme to { -vendor-short-name }
|
||||
abuse-report-subtitle = What’s the issue?
|
||||
|
||||
# Variables:
|
||||
# $author-name (string) - Name of the add-on author
|
||||
abuse-report-addon-authored-by = by <a data-l10n-name="author-name">{ $author-name }</a>
|
||||
|
||||
abuse-report-learnmore =
|
||||
Unsure what issue to select?
|
||||
<a data-l10n-name="learnmore-link">Learn more about reporting extensions and themes</a>
|
||||
|
||||
abuse-report-submit-description = Describe the problem (optional)
|
||||
abuse-report-textarea =
|
||||
.placeholder = It’s easier for us to address a problem if we have specifics. Please describe what you’re experiencing. Thank you for helping us keep the web healthy.
|
||||
abuse-report-submit-note =
|
||||
Note: Don’t include personal information (such as name, email address, phone number, physical address).
|
||||
{ -vendor-short-name } keeps a permanent record of these reports.
|
||||
|
||||
## Panel buttons.
|
||||
|
||||
abuse-report-cancel-button = Cancel
|
||||
abuse-report-next-button = Next
|
||||
abuse-report-goback-button = Go back
|
||||
abuse-report-submit-button = Submit
|
||||
|
||||
## Message bars descriptions.
|
||||
|
||||
## Variables:
|
||||
## $addon-name (string) - Name of the add-on
|
||||
abuse-report-messagebar-aborted = Report for <span data-l10n-name="addon-name">{ $addon-name }</span> canceled.
|
||||
abuse-report-messagebar-submitting = Sending report for <span data-l10n-name="addon-name">{ $addon-name }</span>.
|
||||
abuse-report-messagebar-submitted = Thank you for submitting a report. Do you want to remove <span data-l10n-name="addon-name">{ $addon-name }</span>?
|
||||
abuse-report-messagebar-submitted-noremove = Thank you for submitting a report.
|
||||
abuse-report-messagebar-removed-extension = Thank you for submitting a report. You’ve removed the extension <span data-l10n-name="addon-name">{ $addon-name }</span>.
|
||||
abuse-report-messagebar-removed-theme = Thank you for submitting a report. You’ve removed the theme <span data-l10n-name="addon-name">{ $addon-name }</span>.
|
||||
abuse-report-messagebar-error = There was an error sending the report for <span data-l10n-name="addon-name">{ $addon-name }</span>.
|
||||
abuse-report-messagebar-error-recent-submit = The report for <span data-l10n-name="addon-name">{ $addon-name }</span> wasn’t sent because another report was submitted recently.
|
||||
|
||||
## Message bars actions.
|
||||
|
||||
abuse-report-messagebar-action-remove-extension = Yes, Remove It
|
||||
abuse-report-messagebar-action-keep-extension = No, I’ll Keep It
|
||||
abuse-report-messagebar-action-remove-theme = Yes, Remove It
|
||||
abuse-report-messagebar-action-keep-theme = No, I’ll Keep It
|
||||
abuse-report-messagebar-action-retry = Retry
|
||||
abuse-report-messagebar-action-cancel = Cancel
|
||||
|
||||
## Abuse report reasons (optionally paired with related examples and/or suggestions)
|
||||
|
||||
abuse-report-damage-reason = Damages my computer and data
|
||||
abuse-report-damage-example = Example: Injected malware or stole data
|
||||
|
||||
abuse-report-spam-reason = Creates spam or advertising
|
||||
abuse-report-spam-example = Example: Insert ads on webpages
|
||||
|
||||
abuse-report-settings-reason = Changed my search engine, homepage, or new tab without informing or asking me
|
||||
abuse-report-settings-suggestions = Before reporting the extension, you can try changing your settings:
|
||||
abuse-report-settings-suggestions-search = Change your default search settings
|
||||
abuse-report-settings-suggestions-homepage = Change your homepage and new tab
|
||||
|
||||
abuse-report-deceptive-reason = Pretend to be something it’s not
|
||||
abuse-report-deceptive-example = Example: Misleading description or imagery
|
||||
|
||||
abuse-report-broken-reason-extension = Doesn’t work, breaks websites, or slows { -brand-product-name } down
|
||||
abuse-report-broken-reason-theme = Doesn’t work or breaks browser display
|
||||
abuse-report-broken-example =
|
||||
Example: Features are slow, hard to use, or don’t work; parts of websites won’t load or look unusual
|
||||
abuse-report-broken-suggestions-extension =
|
||||
It sounds like you’ve identified a bug. In addition to submitting a report here, the best way
|
||||
to get a functionality issue resolved is to contact the extension developer.
|
||||
<a data-l10n-name="support-link">Visit the extension’s website</a> to get the developer information.
|
||||
abuse-report-broken-suggestions-theme =
|
||||
It sounds like you’ve identified a bug. In addition to submitting a report here, the best way
|
||||
to get a functionality issue resolved is to contact the theme developer.
|
||||
<a data-l10n-name="support-link">Visit the theme’s website</a> to get the developer information.
|
||||
|
||||
abuse-report-policy-reason = Hateful, violent, or illegal content
|
||||
abuse-report-policy-suggestions =
|
||||
Note: Copyright and trademark issues must be reported in a separate process.
|
||||
<a data-l10n-name="report-infringement-link">Use these instructions</a> to
|
||||
report the problem.
|
||||
|
||||
abuse-report-unwanted-reason = Never wanted this extension and can’t get rid of it
|
||||
abuse-report-unwanted-example = Example: An application installed it without my permission
|
||||
|
||||
abuse-report-other-reason = Something else
|
||||
|
@ -243,13 +243,6 @@ this.AppConstants = Object.freeze({
|
||||
false,
|
||||
#endif
|
||||
|
||||
MOZ_REQUIRE_SIGNING:
|
||||
#ifdef MOZ_REQUIRE_SIGNING
|
||||
true,
|
||||
#else
|
||||
false,
|
||||
#endif
|
||||
|
||||
get MOZ_UNSIGNED_SCOPES() {
|
||||
let result = 0;
|
||||
#ifdef MOZ_UNSIGNED_APP_SCOPE
|
||||
@ -261,13 +254,6 @@ this.AppConstants = Object.freeze({
|
||||
return result;
|
||||
},
|
||||
|
||||
MOZ_ALLOW_LEGACY_EXTENSIONS:
|
||||
#ifdef MOZ_ALLOW_LEGACY_EXTENSIONS
|
||||
true,
|
||||
#else
|
||||
false,
|
||||
#endif
|
||||
|
||||
MENUBAR_CAN_AUTOHIDE:
|
||||
#ifdef MENUBAR_CAN_AUTOHIDE
|
||||
true,
|
||||
|
@ -621,18 +621,6 @@ project_flag('MOZ_BLOCK_PROFILE_DOWNGRADE',
|
||||
help='Block users from starting profiles last used by a newer build',
|
||||
set_as_define=True)
|
||||
|
||||
option(env='MOZ_ALLOW_LEGACY_EXTENSIONS',
|
||||
default=milestone.is_nightly,
|
||||
help='Allow legacy browser extensions')
|
||||
|
||||
@depends('MOZ_ALLOW_LEGACY_EXTENSIONS')
|
||||
def legacy_extensions(value):
|
||||
if bool(value):
|
||||
return True
|
||||
|
||||
set_config('MOZ_ALLOW_LEGACY_EXTENSIONS', legacy_extensions)
|
||||
set_define('MOZ_ALLOW_LEGACY_EXTENSIONS', legacy_extensions)
|
||||
|
||||
@depends('MOZ_PLACES', 'MOZ_ANDROID_HISTORY')
|
||||
def check_places_and_android_history(places, android_history):
|
||||
if places and android_history:
|
||||
|
@ -1,395 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
const EXPORTED_SYMBOLS = ["AbuseReporter", "AbuseReportError"];
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
|
||||
Cu.importGlobalProperties(["fetch"]);
|
||||
|
||||
const PREF_ABUSE_REPORT_URL = "extensions.abuseReport.url";
|
||||
|
||||
// Maximum length of the string properties sent to the API endpoint.
|
||||
const MAX_STRING_LENGTH = 255;
|
||||
|
||||
// Minimum time between report submissions (in ms).
|
||||
const MIN_MS_BETWEEN_SUBMITS = 30000;
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
AddonManager: "resource://gre/modules/AddonManager.jsm",
|
||||
AMTelemetry: "resource://gre/modules/AddonManager.jsm",
|
||||
AppConstants: "resource://gre/modules/AppConstants.jsm",
|
||||
ClientID: "resource://gre/modules/ClientID.jsm",
|
||||
Services: "resource://gre/modules/Services.jsm",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this,
|
||||
"ABUSE_REPORT_URL",
|
||||
PREF_ABUSE_REPORT_URL
|
||||
);
|
||||
|
||||
const PRIVATE_REPORT_PROPS = Symbol("privateReportProps");
|
||||
|
||||
const ERROR_TYPES = Object.freeze([
|
||||
"ERROR_ABORTED_SUBMIT",
|
||||
"ERROR_ADDON_NOTFOUND",
|
||||
"ERROR_CLIENT",
|
||||
"ERROR_NETWORK",
|
||||
"ERROR_UNKNOWN",
|
||||
"ERROR_RECENT_SUBMIT",
|
||||
"ERROR_SERVER",
|
||||
]);
|
||||
|
||||
class AbuseReportError extends Error {
|
||||
constructor(errorType, errorInfo = undefined) {
|
||||
if (!ERROR_TYPES.includes(errorType)) {
|
||||
throw new Error(`Unknown AbuseReportError type "${errorType}"`);
|
||||
}
|
||||
|
||||
let message = errorInfo ? `${errorType} - ${errorInfo}` : errorType;
|
||||
|
||||
super(message);
|
||||
this.name = "AbuseReportError";
|
||||
this.errorType = errorType;
|
||||
this.errorInfo = errorInfo;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A singleton object used to create new AbuseReport instances for a given addonId
|
||||
* and enforce a minium amount of time between two report submissions .
|
||||
*/
|
||||
const AbuseReporter = {
|
||||
_lastReportTimestamp: null,
|
||||
|
||||
// Error types.
|
||||
updateLastReportTimestamp() {
|
||||
this._lastReportTimestamp = Date.now();
|
||||
},
|
||||
|
||||
getTimeFromLastReport() {
|
||||
const currentTimestamp = Date.now();
|
||||
if (this._lastReportTimestamp > currentTimestamp) {
|
||||
// Reset the last report timestamp if it is in the future.
|
||||
this._lastReportTimestamp = null;
|
||||
}
|
||||
|
||||
if (!this._lastReportTimestamp) {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
return currentTimestamp - this._lastReportTimestamp;
|
||||
},
|
||||
|
||||
/**
|
||||
* Create an AbuseReport instance, given the addonId and a reportEntryPoint.
|
||||
*
|
||||
* @param {string} addonId
|
||||
* The id of the addon to create the report instance for.
|
||||
* @param {object} options
|
||||
* @param {string} options.reportEntryPoint
|
||||
* An identifier that represent the entry point for the report flow.
|
||||
*
|
||||
* @returns {AbuseReport}
|
||||
* An instance of the AbuseReport class, which represent an ongoing
|
||||
* report.
|
||||
*/
|
||||
async createAbuseReport(addonId, { reportEntryPoint } = {}) {
|
||||
const addon = await AddonManager.getAddonByID(addonId);
|
||||
|
||||
if (!addon) {
|
||||
AMTelemetry.recordReportEvent({
|
||||
addonId,
|
||||
errorType: "ERROR_ADDON_NOTFOUND",
|
||||
reportEntryPoint,
|
||||
});
|
||||
throw new AbuseReportError("ERROR_ADDON_NOTFOUND");
|
||||
}
|
||||
|
||||
const reportData = await this.getReportData(addon);
|
||||
|
||||
return new AbuseReport({
|
||||
addon,
|
||||
reportData,
|
||||
reportEntryPoint,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper function that retrieves from an addon object all the data to send
|
||||
* as part of the submission request, besides the `reason`, `message` which are
|
||||
* going to be received from the submit method of the report object returned
|
||||
* by `createAbuseReport`.
|
||||
* (See https://addons-server.readthedocs.io/en/latest/topics/api/abuse.html)
|
||||
*
|
||||
* @param {AddonWrapper} addon
|
||||
* The addon object to collect the detail from.
|
||||
*
|
||||
* @return {object}
|
||||
* An object that contains the collected details.
|
||||
*/
|
||||
async getReportData(addon) {
|
||||
const truncateString = text =>
|
||||
typeof text == "string" ? text.slice(0, MAX_STRING_LENGTH) : text;
|
||||
|
||||
let installInfo = addon.installTelemetryInfo;
|
||||
|
||||
const data = {
|
||||
addon: addon.id,
|
||||
addon_version: addon.version,
|
||||
addon_name: truncateString(addon.name),
|
||||
addon_summary: truncateString(addon.description),
|
||||
addon_install_origin:
|
||||
addon.sourceURI && truncateString(addon.sourceURI.spec),
|
||||
addon_install_source_url:
|
||||
installInfo &&
|
||||
installInfo.sourceURL &&
|
||||
truncateString(installInfo.sourceURL),
|
||||
install_date: addon.installDate && addon.installDate.toISOString(),
|
||||
};
|
||||
|
||||
// Map addon.installTelemetryInfo values to the supported addon_install_method
|
||||
// values supported by the API endpoint (See API endpoint docs at
|
||||
// https://addons-server.readthedocs.io/en/latest/topics/api/abuse.html).
|
||||
let install_method = "other";
|
||||
if (installInfo) {
|
||||
const { source, method } = installInfo;
|
||||
switch (source) {
|
||||
case "enterprise-policy":
|
||||
case "file-url":
|
||||
case "system-addon":
|
||||
case "temporary-addon":
|
||||
install_method = source.replace(/-/g, "_");
|
||||
break;
|
||||
case "distribution":
|
||||
case "sync":
|
||||
install_method = source;
|
||||
break;
|
||||
default:
|
||||
install_method = "other";
|
||||
}
|
||||
|
||||
switch (method) {
|
||||
case "sideload":
|
||||
case "link":
|
||||
install_method = method;
|
||||
break;
|
||||
case "amWebAPI":
|
||||
case "installTrigger":
|
||||
install_method = method.toLowerCase();
|
||||
break;
|
||||
case "drag-and-drop":
|
||||
case "install-from-file":
|
||||
case "management-webext-api":
|
||||
install_method = method.replace(/-/g, "_");
|
||||
break;
|
||||
}
|
||||
}
|
||||
data.addon_install_method = install_method;
|
||||
|
||||
switch (addon.signedState) {
|
||||
case AddonManager.SIGNEDSTATE_BROKEN:
|
||||
data.addon_signature = "broken";
|
||||
break;
|
||||
case AddonManager.SIGNEDSTATE_UNKNOWN:
|
||||
data.addon_signature = "unknown";
|
||||
break;
|
||||
case AddonManager.SIGNEDSTATE_MISSING:
|
||||
data.addon_signature = "missing";
|
||||
break;
|
||||
case AddonManager.SIGNEDSTATE_PRELIMINARY:
|
||||
data.addon_signature = "preliminary";
|
||||
break;
|
||||
case AddonManager.SIGNEDSTATE_SIGNED:
|
||||
data.addon_signature = "signed";
|
||||
break;
|
||||
case AddonManager.SIGNEDSTATE_SYSTEM:
|
||||
data.addon_signature = "system";
|
||||
break;
|
||||
case AddonManager.SIGNEDSTATE_PRIVILEGED:
|
||||
data.addon_signature = "privileged";
|
||||
break;
|
||||
default:
|
||||
data.addon_signature = `unknown: ${addon.signedState}`;
|
||||
}
|
||||
|
||||
// Set "curated" as addon_signature on recommended addons
|
||||
// (addon.isRecommended internally checks that the addon is also
|
||||
// signed correctly).
|
||||
if (addon.isRecommended) {
|
||||
data.addon_signature = "curated";
|
||||
}
|
||||
|
||||
data.client_id = await ClientID.getClientIdHash();
|
||||
|
||||
data.app = Services.appinfo.name.toLowerCase();
|
||||
data.appversion = Services.appinfo.version;
|
||||
data.lang = Services.locale.appLocaleAsLangTag;
|
||||
data.operating_system = AppConstants.platform;
|
||||
data.operating_system_version = Services.sysinfo.getProperty("version");
|
||||
|
||||
return data;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents an ongoing abuse report. Instances of this class are created
|
||||
* by the `AbuseReporter.createAbuseReport` method.
|
||||
*
|
||||
* This object is used by the reporting UI panel and message bars to:
|
||||
*
|
||||
* - get an errorType in case of a report creation error (e.g. because of a
|
||||
* previously submitted report)
|
||||
* - get the addon details used inside the reporting panel
|
||||
* - submit the abuse report (and re-submit if a previous submission failed
|
||||
* and the user choose to retry to submit it again)
|
||||
* - abort an ongoing submission
|
||||
*
|
||||
* @param {object} options
|
||||
* @param {AddonWrapper|null} options.addon
|
||||
* AddonWrapper instance for the extension/theme being reported.
|
||||
* (May be null if the extension has not been found).
|
||||
* @param {object|null} options.reportData
|
||||
* An object which contains addon and environment details to send as part of a submission
|
||||
* (may be null if the report has a createErrorType).
|
||||
* @param {string} options.reportEntryPoint
|
||||
* A string that identify how the report has been triggered.
|
||||
*/
|
||||
class AbuseReport {
|
||||
constructor({ addon, createErrorType, reportData, reportEntryPoint }) {
|
||||
this[PRIVATE_REPORT_PROPS] = {
|
||||
aborted: false,
|
||||
abortController: new AbortController(),
|
||||
addon,
|
||||
reportData,
|
||||
reportEntryPoint,
|
||||
};
|
||||
}
|
||||
|
||||
recordTelemetry(errorType) {
|
||||
const { addon, reportEntryPoint } = this;
|
||||
AMTelemetry.recordReportEvent({
|
||||
addonId: addon.id,
|
||||
addonType: addon.type,
|
||||
errorType,
|
||||
reportEntryPoint,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit the current report, given a reason and a message.
|
||||
*
|
||||
* @params {object} options
|
||||
* @params {string} options.reason
|
||||
* String identifier for the report reason.
|
||||
* @params {string} [options.message]
|
||||
* An optional string which contains a description for the reported issue.
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
* Resolves once the report has been successfully submitted.
|
||||
* It rejects with an AbuseReportError if the report couldn't be
|
||||
* submitted for a known reason (or another Error type otherwise).
|
||||
*/
|
||||
async submit({ reason, message }) {
|
||||
const { aborted, abortController, reportData, reportEntryPoint } = this[
|
||||
PRIVATE_REPORT_PROPS
|
||||
];
|
||||
|
||||
// Record telemetry event and throw an AbuseReportError.
|
||||
const rejectReportError = async (errorType, { response } = {}) => {
|
||||
this.recordTelemetry(errorType);
|
||||
|
||||
let errorInfo;
|
||||
if (response) {
|
||||
try {
|
||||
errorInfo = JSON.stringify({
|
||||
status: response.status,
|
||||
responseText: await response.text().catch(err => ""),
|
||||
});
|
||||
} catch (err) {
|
||||
// leave the errorInfo empty if we failed to stringify it.
|
||||
}
|
||||
}
|
||||
throw new AbuseReportError(errorType, errorInfo);
|
||||
};
|
||||
|
||||
if (aborted) {
|
||||
// Report aborted before being actually submitted.
|
||||
return rejectReportError("ERROR_ABORTED_SUBMIT");
|
||||
}
|
||||
|
||||
// Prevent submit of a new abuse report in less than MIN_MS_BETWEEN_SUBMITS.
|
||||
let msFromLastReport = AbuseReporter.getTimeFromLastReport();
|
||||
if (msFromLastReport < MIN_MS_BETWEEN_SUBMITS) {
|
||||
return rejectReportError("ERROR_RECENT_SUBMIT");
|
||||
}
|
||||
|
||||
let response;
|
||||
try {
|
||||
response = await fetch(ABUSE_REPORT_URL, {
|
||||
signal: abortController.signal,
|
||||
method: "POST",
|
||||
credentials: "omit",
|
||||
referrerPolicy: "no-referrer",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
...reportData,
|
||||
report_entry_point: reportEntryPoint,
|
||||
message,
|
||||
reason,
|
||||
}),
|
||||
});
|
||||
} catch (err) {
|
||||
if (err.name === "AbortError") {
|
||||
return rejectReportError("ERROR_ABORTED_SUBMIT");
|
||||
}
|
||||
Cu.reportError(err);
|
||||
return rejectReportError("ERROR_NETWORK");
|
||||
}
|
||||
|
||||
if (response.ok && response.status >= 200 && response.status < 400) {
|
||||
// Ensure that the response is also a valid json format.
|
||||
try {
|
||||
await response.json();
|
||||
} catch (err) {
|
||||
this.recordTelemetry("ERROR_UNKNOWN");
|
||||
throw err;
|
||||
}
|
||||
AbuseReporter.updateLastReportTimestamp();
|
||||
this.recordTelemetry();
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (response.status >= 400 && response.status < 500) {
|
||||
return rejectReportError("ERROR_CLIENT", { response });
|
||||
}
|
||||
|
||||
if (response.status >= 500 && response.status < 600) {
|
||||
return rejectReportError("ERROR_SERVER", { response });
|
||||
}
|
||||
|
||||
// We got an unexpected HTTP status code.
|
||||
return rejectReportError("ERROR_UNKNOWN", { response });
|
||||
}
|
||||
|
||||
/**
|
||||
* Abort the report submission.
|
||||
*/
|
||||
abort() {
|
||||
const { abortController } = this[PRIVATE_REPORT_PROPS];
|
||||
abortController.abort();
|
||||
this[PRIVATE_REPORT_PROPS].aborted = true;
|
||||
}
|
||||
|
||||
get addon() {
|
||||
return this[PRIVATE_REPORT_PROPS].addon;
|
||||
}
|
||||
|
||||
get reportEntryPoint() {
|
||||
return this[PRIVATE_REPORT_PROPS].reportEntryPoint;
|
||||
}
|
||||
}
|
@ -92,7 +92,7 @@ Services.ppmm.loadProcessScript(
|
||||
|
||||
const INTEGER = /^[1-9]\d*$/;
|
||||
|
||||
var EXPORTED_SYMBOLS = ["AddonManager", "AddonManagerPrivate", "AMTelemetry"];
|
||||
var EXPORTED_SYMBOLS = ["AddonManager", "AddonManagerPrivate"];
|
||||
|
||||
const CATEGORY_PROVIDER_MODULE = "addon-provider-module";
|
||||
|
||||
@ -588,8 +588,6 @@ var gShutdownInProgress = false;
|
||||
var gPluginPageListener = null;
|
||||
var gBrowserUpdated = null;
|
||||
|
||||
var AMTelemetry;
|
||||
|
||||
/**
|
||||
* This is the real manager, kept here rather than in AddonManager to keep its
|
||||
* contents hidden from API users.
|
||||
@ -606,15 +604,9 @@ var AddonManagerInternal = {
|
||||
providerShutdowns: new Map(),
|
||||
types: {},
|
||||
startupChanges: {},
|
||||
// Store telemetry details per addon provider
|
||||
telemetryDetails: {},
|
||||
upgradeListeners: new Map(),
|
||||
externalExtensionLoaders: new Map(),
|
||||
|
||||
recordTimestamp(name, value) {
|
||||
this.TelemetryTimestamps.add(name, value);
|
||||
},
|
||||
|
||||
/**
|
||||
* Start up a provider, and register its shutdown hook if it has one
|
||||
*
|
||||
@ -695,16 +687,6 @@ var AddonManagerInternal = {
|
||||
return;
|
||||
}
|
||||
|
||||
this.recordTimestamp("AMI_startup_begin");
|
||||
|
||||
// Enable the addonsManager telemetry event category.
|
||||
AMTelemetry.init();
|
||||
|
||||
// clear this for xpcshell test restarts
|
||||
for (let provider in this.telemetryDetails) {
|
||||
delete this.telemetryDetails[provider];
|
||||
}
|
||||
|
||||
let appChanged = undefined;
|
||||
|
||||
let oldAppVersion = null;
|
||||
@ -886,7 +868,6 @@ var AddonManagerInternal = {
|
||||
);
|
||||
|
||||
gStartupComplete = true;
|
||||
this.recordTimestamp("AMI_startup_end");
|
||||
} catch (e) {
|
||||
logger.error("startup failed", e);
|
||||
AddonManagerPrivate.recordException("AMI", "startup failed", e);
|
||||
@ -1345,9 +1326,6 @@ var AddonManagerInternal = {
|
||||
permissions: difference,
|
||||
resolve,
|
||||
reject,
|
||||
// Reference to the related AddonInstall object (used in AMTelemetry to
|
||||
// link the recorded event to the other events from the same install flow).
|
||||
install: info.install,
|
||||
},
|
||||
};
|
||||
Services.obs.notifyObservers(subject, "webextension-update-permissions");
|
||||
@ -1758,9 +1736,6 @@ var AddonManagerInternal = {
|
||||
* An optional <browser> element for download permissions prompts.
|
||||
* @param {nsIPrincipal} [aOptions.triggeringPrincipal]
|
||||
* The principal which is attempting to install the add-on.
|
||||
* @param {Object} [aOptions.telemetryInfo]
|
||||
* An optional object which provides details about the installation source
|
||||
* included in the addon manager telemetry events.
|
||||
* @throws if aUrl is not specified or if an optional argument of
|
||||
* an improper type is passed.
|
||||
*/
|
||||
@ -1842,12 +1817,9 @@ var AddonManagerInternal = {
|
||||
* The nsIFile where the add-on is located
|
||||
* @param aMimetype
|
||||
* An optional mimetype hint for the add-on
|
||||
* @param aTelemetryInfo
|
||||
* An optional object which provides details about the installation source
|
||||
* included in the addon manager telemetry events.
|
||||
* @throws if the aFile or aCallback arguments are not specified
|
||||
*/
|
||||
getInstallForFile(aFile, aMimetype, aTelemetryInfo) {
|
||||
getInstallForFile(aFile, aMimetype) {
|
||||
if (!gStarted) {
|
||||
throw Components.Exception(
|
||||
"AddonManager is not initialized",
|
||||
@ -1874,8 +1846,7 @@ var AddonManagerInternal = {
|
||||
let install = await promiseCallProvider(
|
||||
provider,
|
||||
"getInstallForFile",
|
||||
aFile,
|
||||
aTelemetryInfo
|
||||
aFile
|
||||
);
|
||||
|
||||
if (install) {
|
||||
@ -3287,11 +3258,6 @@ var AddonManagerInternal = {
|
||||
browser: target,
|
||||
triggeringPrincipal: options.triggeringPrincipal,
|
||||
hash: options.hash,
|
||||
telemetryInfo: {
|
||||
source: AddonManager.getInstallSourceFromHost(options.sourceHost),
|
||||
sourceURL: options.sourceURL,
|
||||
method: "amWebAPI",
|
||||
},
|
||||
}).then(install => {
|
||||
let requireConfirm = true;
|
||||
if (
|
||||
@ -3495,10 +3461,6 @@ var AddonManagerPrivate = {
|
||||
.BOOTSTRAP_REASONS;
|
||||
},
|
||||
|
||||
recordTimestamp(name, value) {
|
||||
AddonManagerInternal.recordTimestamp(name, value);
|
||||
},
|
||||
|
||||
_simpleMeasures: {},
|
||||
recordSimpleMeasure(name, value) {
|
||||
this._simpleMeasures[name] = value;
|
||||
@ -3527,14 +3489,6 @@ var AddonManagerPrivate = {
|
||||
return this._simpleMeasures;
|
||||
},
|
||||
|
||||
getTelemetryDetails() {
|
||||
return AddonManagerInternal.telemetryDetails;
|
||||
},
|
||||
|
||||
setTelemetryDetails(aProvider, aDetails) {
|
||||
AddonManagerInternal.telemetryDetails[aProvider] = aDetails;
|
||||
},
|
||||
|
||||
// Start a timer, record a simple measure of the time interval when
|
||||
// timer.done() is called
|
||||
simpleTimer(aName) {
|
||||
@ -3643,7 +3597,6 @@ var AddonManager = {
|
||||
// telemetry events.
|
||||
_installHostSource: new Map([
|
||||
["addons.mozilla.org", "amo"],
|
||||
["discovery.addons.mozilla.org", "disco"],
|
||||
]),
|
||||
|
||||
// Constants for the AddonInstall.state property
|
||||
@ -3927,11 +3880,10 @@ var AddonManager = {
|
||||
return AddonManagerInternal.getInstallForURL(aUrl, aOptions);
|
||||
},
|
||||
|
||||
getInstallForFile(aFile, aMimetype, aTelemetryInfo) {
|
||||
getInstallForFile(aFile, aMimetype) {
|
||||
return AddonManagerInternal.getInstallForFile(
|
||||
aFile,
|
||||
aMimetype,
|
||||
aTelemetryInfo
|
||||
aMimetype
|
||||
);
|
||||
},
|
||||
|
||||
@ -4159,544 +4111,8 @@ var AddonManager = {
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Listens to the AddonManager install and addon events and send telemetry events.
|
||||
*/
|
||||
AMTelemetry = {
|
||||
telemetrySetupDone: false,
|
||||
|
||||
init() {
|
||||
// Enable the addonsManager telemetry event category before the AddonManager
|
||||
// has completed its startup, otherwise telemetry events recorded during the
|
||||
// AddonManager/XPIProvider startup will not be recorded (e.g. the telemetry
|
||||
// events for the extension migrated to the private browsing permission).
|
||||
Services.telemetry.setEventRecordingEnabled("addonsManager", true);
|
||||
},
|
||||
|
||||
// This method is called by the AddonManager, once it has been started, so that we can
|
||||
// init the telemetry event category and start listening for the events related to the
|
||||
// addons installation and management.
|
||||
onStartup() {
|
||||
if (this.telemetrySetupDone) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.telemetrySetupDone = true;
|
||||
|
||||
Services.obs.addObserver(this, "addon-install-origin-blocked");
|
||||
Services.obs.addObserver(this, "addon-install-disabled");
|
||||
Services.obs.addObserver(this, "addon-install-blocked");
|
||||
|
||||
AddonManager.addInstallListener(this);
|
||||
AddonManager.addAddonListener(this);
|
||||
},
|
||||
|
||||
// Observer Service notification callback.
|
||||
|
||||
observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "addon-install-blocked": {
|
||||
const { installs } = subject.wrappedJSObject;
|
||||
this.recordInstallEvent(installs[0], { step: "site_warning" });
|
||||
break;
|
||||
}
|
||||
case "addon-install-origin-blocked": {
|
||||
const { installs } = subject.wrappedJSObject;
|
||||
this.recordInstallEvent(installs[0], { step: "site_blocked" });
|
||||
break;
|
||||
}
|
||||
case "addon-install-disabled": {
|
||||
const { installs } = subject.wrappedJSObject;
|
||||
this.recordInstallEvent(installs[0], {
|
||||
step: "install_disabled_warning",
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// AddonManager install listener callbacks.
|
||||
|
||||
onNewInstall(install) {
|
||||
this.recordInstallEvent(install, { step: "started" });
|
||||
},
|
||||
|
||||
onInstallCancelled(install) {
|
||||
this.recordInstallEvent(install, { step: "cancelled" });
|
||||
},
|
||||
|
||||
onInstallPostponed(install) {
|
||||
this.recordInstallEvent(install, { step: "postponed" });
|
||||
},
|
||||
|
||||
onInstallFailed(install) {
|
||||
this.recordInstallEvent(install, { step: "failed" });
|
||||
},
|
||||
|
||||
onInstallEnded(install) {
|
||||
this.recordInstallEvent(install, { step: "completed" });
|
||||
},
|
||||
|
||||
onDownloadStarted(install) {
|
||||
this.recordInstallEvent(install, { step: "download_started" });
|
||||
},
|
||||
|
||||
onDownloadCancelled(install) {
|
||||
this.recordInstallEvent(install, { step: "cancelled" });
|
||||
},
|
||||
|
||||
onDownloadEnded(install) {
|
||||
let download_time = Math.round(Cu.now() - install.downloadStartedAt);
|
||||
this.recordInstallEvent(install, {
|
||||
step: "download_completed",
|
||||
download_time,
|
||||
});
|
||||
},
|
||||
|
||||
onDownloadFailed(install) {
|
||||
let download_time = Math.round(Cu.now() - install.downloadStartedAt);
|
||||
this.recordInstallEvent(install, {
|
||||
step: "download_failed",
|
||||
download_time,
|
||||
});
|
||||
},
|
||||
|
||||
// Addon listeners callbacks.
|
||||
|
||||
onUninstalled(addon) {
|
||||
this.recordManageEvent(addon, "uninstall");
|
||||
},
|
||||
|
||||
onEnabled(addon) {
|
||||
this.recordManageEvent(addon, "enable");
|
||||
},
|
||||
|
||||
onDisabled(addon) {
|
||||
this.recordManageEvent(addon, "disable");
|
||||
},
|
||||
|
||||
// Internal helpers methods.
|
||||
|
||||
/**
|
||||
* Get a trimmed version of the given string if it is longer than 80 chars.
|
||||
*
|
||||
* @param {string} str
|
||||
* The original string content.
|
||||
*
|
||||
* @returns {string}
|
||||
* The trimmed version of the string when longer than 80 chars, or the given string
|
||||
* unmodified otherwise.
|
||||
*/
|
||||
getTrimmedString(str) {
|
||||
if (str.length <= 80) {
|
||||
return str;
|
||||
}
|
||||
|
||||
const length = str.length;
|
||||
|
||||
// Trim the string to prevent a flood of warnings messages logged internally by recordEvent,
|
||||
// the trimmed version is going to be composed by the first 40 chars and the last 37 and 3 dots
|
||||
// that joins the two parts, to visually indicate that the string has been trimmed.
|
||||
return `${str.slice(0, 40)}...${str.slice(length - 37, length)}`;
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve the addonId for the given AddonInstall instance.
|
||||
*
|
||||
* @param {AddonInstall} install
|
||||
* The AddonInstall instance to retrieve the addonId from.
|
||||
*
|
||||
* @returns {string | null}
|
||||
* The addonId for the given AddonInstall instance (if any).
|
||||
*/
|
||||
getAddonIdFromInstall(install) {
|
||||
// Returns the id of the extension that is being installed, as soon as the
|
||||
// addon is available in the AddonInstall instance (after being downloaded
|
||||
// and validated successfully).
|
||||
if (install.addon) {
|
||||
return install.addon.id;
|
||||
}
|
||||
|
||||
// While updating an addon, the existing addon can be
|
||||
// used to retrieve the addon id since the first update event.
|
||||
if (install.existingAddon) {
|
||||
return install.existingAddon.id;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve the telemetry event's object property value for the given
|
||||
* AddonInstall instance.
|
||||
*
|
||||
* @param {AddonInstall} install
|
||||
* The AddonInstall instance to retrieve the event object from.
|
||||
*
|
||||
* @returns {string}
|
||||
* The object for the given AddonInstall instance.
|
||||
*/
|
||||
getEventObjectFromInstall(install) {
|
||||
let addonType;
|
||||
|
||||
if (install.type) {
|
||||
// The AddonInstall wrapper already provides a type (if it was known when the
|
||||
// install object has been created).
|
||||
addonType = install.type;
|
||||
} else if (install.addon) {
|
||||
// The install flow has reached a step that has an addon instance which we can
|
||||
// check to know the extension type (e.g. after download for the DownloadAddonInstall).
|
||||
addonType = install.addon.type;
|
||||
} else if (install.existingAddon) {
|
||||
// The install flow is an update and we can look the existingAddon to check which was
|
||||
// the add-on type that is being installed.
|
||||
addonType = install.existingAddon.type;
|
||||
}
|
||||
|
||||
return this.getEventObjectFromAddonType(addonType);
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve the telemetry event source for the given AddonInstall instance.
|
||||
*
|
||||
* @param {AddonInstall} install
|
||||
* The AddonInstall instance to retrieve the source from.
|
||||
*
|
||||
* @returns {Object | null}
|
||||
* The telemetry infor ({source, method}) from the given AddonInstall instance.
|
||||
*/
|
||||
getInstallTelemetryInfo(install) {
|
||||
if (install.installTelemetryInfo) {
|
||||
return install.installTelemetryInfo;
|
||||
} else if (
|
||||
install.existingAddon &&
|
||||
install.existingAddon.installTelemetryInfo
|
||||
) {
|
||||
// Get the install source from the existing addon (e.g. for an extension update).
|
||||
return install.existingAddon.installTelemetryInfo;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the telemetry event's object property for the given addon type
|
||||
*
|
||||
* @param {string} addonType
|
||||
* The addon type to convert into the related telemetry event object.
|
||||
*
|
||||
* @returns {string}
|
||||
* The object for the given addon type.
|
||||
*/
|
||||
getEventObjectFromAddonType(addonType) {
|
||||
switch (addonType) {
|
||||
case undefined:
|
||||
return "unknown";
|
||||
case "extension":
|
||||
case "theme":
|
||||
case "locale":
|
||||
case "dictionary":
|
||||
return addonType;
|
||||
default:
|
||||
// Currently this should only include plugins and gmp-plugins
|
||||
return "other";
|
||||
}
|
||||
},
|
||||
|
||||
convertToString(value) {
|
||||
if (value == null) {
|
||||
// Convert null and undefined to empty strings.
|
||||
return "";
|
||||
}
|
||||
switch (typeof value) {
|
||||
case "string":
|
||||
return value;
|
||||
case "boolean":
|
||||
return value ? "1" : "0";
|
||||
}
|
||||
return String(value);
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert all the telemetry event's extra_vars into strings, if needed.
|
||||
*
|
||||
* @param {object} extraVars
|
||||
* @returns {object} The formatted extra vars.
|
||||
*/
|
||||
formatExtraVars({ addon, ...extraVars }) {
|
||||
if (addon) {
|
||||
extraVars.addonId = addon.id;
|
||||
extraVars.type = addon.type;
|
||||
}
|
||||
|
||||
// All the extra_vars in a telemetry event have to be strings.
|
||||
for (var [key, value] of Object.entries(extraVars)) {
|
||||
if (value == undefined) {
|
||||
delete extraVars[key];
|
||||
} else {
|
||||
extraVars[key] = this.convertToString(value);
|
||||
}
|
||||
}
|
||||
|
||||
if (extraVars.addonId) {
|
||||
extraVars.addonId = this.getTrimmedString(extraVars.addonId);
|
||||
}
|
||||
|
||||
return extraVars;
|
||||
},
|
||||
|
||||
/**
|
||||
* Record an install or update event for the given AddonInstall instance.
|
||||
*
|
||||
* @param {AddonInstall} install
|
||||
* The AddonInstall instance to record an install or update event for.
|
||||
* @param {object} extraVars
|
||||
* The additional extra_vars to include in the recorded event.
|
||||
* @param {string} extraVars.step
|
||||
* The current step in the install or update flow.
|
||||
* @param {string} extraVars.download_time
|
||||
* The number of ms needed to download the extension.
|
||||
* @param {string} extraVars.num_strings
|
||||
* The number of permission description string for the extension
|
||||
* permission doorhanger.
|
||||
*/
|
||||
recordInstallEvent(install, extraVars) {
|
||||
// Early exit if AMTelemetry's telemetry setup has not been done yet.
|
||||
if (!this.telemetrySetupDone) {
|
||||
return;
|
||||
}
|
||||
|
||||
let extra = {};
|
||||
|
||||
let telemetryInfo = this.getInstallTelemetryInfo(install);
|
||||
if (telemetryInfo && typeof telemetryInfo.source === "string") {
|
||||
extra.source = telemetryInfo.source;
|
||||
}
|
||||
|
||||
if (extra.source === "internal") {
|
||||
// Do not record the telemetry event for installation sources
|
||||
// that are marked as "internal".
|
||||
return;
|
||||
}
|
||||
|
||||
// Also include the install source's method when applicable (e.g. install events with
|
||||
// source "about:addons" may have "install-from-file" or "url" as their source method).
|
||||
if (telemetryInfo && typeof telemetryInfo.method === "string") {
|
||||
extra.method = telemetryInfo.method;
|
||||
}
|
||||
|
||||
let addonId = this.getAddonIdFromInstall(install);
|
||||
let object = this.getEventObjectFromInstall(install);
|
||||
|
||||
let installId = String(install.installId);
|
||||
let eventMethod = install.existingAddon ? "update" : "install";
|
||||
|
||||
if (addonId) {
|
||||
extra.addon_id = this.getTrimmedString(addonId);
|
||||
}
|
||||
|
||||
if (install.error) {
|
||||
extra.error = AddonManager.errorToString(install.error);
|
||||
}
|
||||
|
||||
if (eventMethod === "update") {
|
||||
// For "update" telemetry events, also include an extra var which determine
|
||||
// if the update has been requested by the user.
|
||||
extra.updated_from = install.isUserRequestedUpdate ? "user" : "app";
|
||||
}
|
||||
|
||||
// All the extra vars in a telemetry event have to be strings.
|
||||
extra = this.formatExtraVars({ ...extraVars, ...extra });
|
||||
|
||||
this.recordEvent({ method: eventMethod, object, value: installId, extra });
|
||||
},
|
||||
|
||||
/**
|
||||
* Record a manage event for the given addon.
|
||||
*
|
||||
* @param {AddonWrapper} addon
|
||||
* The AddonWrapper instance.
|
||||
* @param {object} extraVars
|
||||
* The additional extra_vars to include in the recorded event.
|
||||
* @param {string} extraVars.num_strings
|
||||
* The number of permission description string for the extension
|
||||
* permission doorhanger.
|
||||
*/
|
||||
recordManageEvent(addon, method, extraVars) {
|
||||
// Early exit if AMTelemetry's telemetry setup has not been done yet.
|
||||
if (!this.telemetrySetupDone) {
|
||||
return;
|
||||
}
|
||||
|
||||
let extra = {};
|
||||
|
||||
if (addon.installTelemetryInfo) {
|
||||
if ("source" in addon.installTelemetryInfo) {
|
||||
extra.source = addon.installTelemetryInfo.source;
|
||||
}
|
||||
|
||||
// Also include the install source's method when applicable (e.g. install events with
|
||||
// source "about:addons" may have "install-from-file" or "url" as their source method).
|
||||
if ("method" in addon.installTelemetryInfo) {
|
||||
extra.method = addon.installTelemetryInfo.method;
|
||||
}
|
||||
}
|
||||
|
||||
if (extra.source === "internal") {
|
||||
// Do not record the telemetry event for installation sources
|
||||
// that are marked as "internal".
|
||||
return;
|
||||
}
|
||||
|
||||
let object = this.getEventObjectFromAddonType(addon.type);
|
||||
let value = this.getTrimmedString(addon.id);
|
||||
|
||||
extra = { ...extraVars, ...extra };
|
||||
|
||||
let hasExtraVars = Object.keys(extra).length > 0;
|
||||
extra = this.formatExtraVars(extra);
|
||||
|
||||
this.recordEvent({
|
||||
method,
|
||||
object,
|
||||
value,
|
||||
extra: hasExtraVars ? extra : null,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Record an event for when a link is clicked.
|
||||
*
|
||||
* @param {object} opts
|
||||
* @param {string} opts.object
|
||||
* The object of the event, should be an identifier for where the link
|
||||
* is located. The accepted values are listed in the
|
||||
* addonsManager.link object of the Events.yaml file.
|
||||
* @param {string} opts.value The identifier for the link destination.
|
||||
* @param {object} opts.extra
|
||||
* The extra data to be sent, all keys must be registered in the
|
||||
* extra_keys section of addonsManager.link in Events.yaml.
|
||||
*/
|
||||
recordLinkEvent({ object, value, extra = null }) {
|
||||
this.recordEvent({ method: "link", object, value, extra });
|
||||
},
|
||||
|
||||
/**
|
||||
* Record an event for an action that took place.
|
||||
*
|
||||
* @param {object} opts
|
||||
* @param {string} opts.object
|
||||
* The object of the event, should an identifier for where the action
|
||||
* took place. The accepted values are listed in the
|
||||
* addonsManager.action object of the Events.yaml file.
|
||||
* @param {string} opts.action The identifier for the action.
|
||||
* @param {string} opts.value An optional value for the action.
|
||||
* @param {object} opts.addon
|
||||
* An optional object with the "id" and "type" properties, for example
|
||||
* an AddonWrapper object. Passing this will set some extra properties.
|
||||
* @param {string} opts.addon.id
|
||||
* The add-on ID to assign to extra.addonId.
|
||||
* @param {string} opts.addon.type
|
||||
* The add-on type to assign to extra.type.
|
||||
* @param {string} opts.view The current view, when object is aboutAddons.
|
||||
* @param {object} opts.extra
|
||||
* The extra data to be sent, all keys must be registered in the
|
||||
* extra_keys section of addonsManager.action in Events.yaml. If
|
||||
* opts.addon is passed then it will overwrite the addonId and type
|
||||
* properties in this object, if they are set.
|
||||
*/
|
||||
recordActionEvent({ object, action, value, addon, view, extra }) {
|
||||
extra = { ...extra, action, addon, view };
|
||||
this.recordEvent({
|
||||
method: "action",
|
||||
object,
|
||||
// Treat null and undefined as null.
|
||||
value: value == null ? null : this.convertToString(value),
|
||||
extra: this.formatExtraVars(extra),
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Record an event for a view load in about:addons.
|
||||
*
|
||||
* @param {object} opts
|
||||
* @param {string} opts.view
|
||||
* The identifier for the view. The accepted values are listed in the
|
||||
* object property of addonsManager.view object of the Events.yaml
|
||||
* file.
|
||||
* @param {AddonWrapper} opts.addon
|
||||
* An optional add-on object related to the event.
|
||||
* @param {string} opts.type
|
||||
* An optional type for the view. If opts.addon is set it will
|
||||
* overwrite this value with the type of the add-on.
|
||||
*/
|
||||
recordViewEvent({ view, addon, type }) {
|
||||
this.recordEvent({
|
||||
method: "view",
|
||||
object: "aboutAddons",
|
||||
value: view,
|
||||
extra: this.formatExtraVars({ type, addon }),
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Record an event on abuse report submissions.
|
||||
*
|
||||
* @params {object} opts
|
||||
* @params {string} opts.addonId
|
||||
* The id of the addon being reported.
|
||||
* @params {string} [opts.addonType]
|
||||
* The type of the addon being reported (only present for an existing
|
||||
* addonId).
|
||||
* @params {string} [opts.errorType]
|
||||
* The AbuseReport errorType for a submission failure.
|
||||
* @params {string} opts.reportEntryPoint
|
||||
* The entry point of the abuse report.
|
||||
*/
|
||||
recordReportEvent({ addonId, addonType, errorType, reportEntryPoint }) {
|
||||
this.recordEvent({
|
||||
method: "report",
|
||||
object: reportEntryPoint,
|
||||
value: addonId,
|
||||
extra: this.formatExtraVars({
|
||||
addon_type: addonType,
|
||||
error_type: errorType,
|
||||
}),
|
||||
});
|
||||
},
|
||||
|
||||
recordEvent({ method, object, value, extra }) {
|
||||
if (typeof value != "string") {
|
||||
// The value must be a string or null, make sure it's valid so sending
|
||||
// the event doesn't fail.
|
||||
value = null;
|
||||
}
|
||||
try {
|
||||
Services.telemetry.recordEvent(
|
||||
"addonsManager",
|
||||
method,
|
||||
object,
|
||||
value,
|
||||
extra
|
||||
);
|
||||
} catch (err) {
|
||||
// If the telemetry throws just log the error so it doesn't break any
|
||||
// functionality.
|
||||
Cu.reportError(err);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
this.AddonManager.init();
|
||||
|
||||
// Setup the AMTelemetry once the AddonManager has been started.
|
||||
this.AddonManager.addManagerListener(AMTelemetry);
|
||||
|
||||
// load the timestamps module into AddonManagerInternal
|
||||
ChromeUtils.import(
|
||||
"resource://gre/modules/TelemetryTimestamps.jsm",
|
||||
AddonManagerInternal
|
||||
);
|
||||
Object.freeze(AddonManagerInternal);
|
||||
Object.freeze(AddonManagerPrivate);
|
||||
Object.freeze(AddonManager);
|
||||
|
@ -27,17 +27,14 @@ static bool IsValidHost(const nsACString& host) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (host.EqualsLiteral("addons.mozilla.org") ||
|
||||
host.EqualsLiteral("discovery.addons.mozilla.org")) {
|
||||
if (host.EqualsLiteral("addons.mozilla.org")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// When testing allow access to the developer sites.
|
||||
if (Preferences::GetBool("extensions.webapi.testing", false)) {
|
||||
if (host.LowerCaseEqualsLiteral("addons.allizom.org") ||
|
||||
host.LowerCaseEqualsLiteral("discovery.addons.allizom.org") ||
|
||||
host.LowerCaseEqualsLiteral("addons-dev.allizom.org") ||
|
||||
host.LowerCaseEqualsLiteral("discovery.addons-dev.allizom.org") ||
|
||||
host.LowerCaseEqualsLiteral("example.com")) {
|
||||
return true;
|
||||
}
|
||||
|
@ -87,22 +87,12 @@ amManager.prototype = {
|
||||
retval = false;
|
||||
}
|
||||
|
||||
let telemetryInfo = {
|
||||
source: AddonManager.getInstallSourceFromHost(aPayload.sourceHost),
|
||||
sourceURL: aPayload.sourceURL,
|
||||
};
|
||||
|
||||
if ("method" in aPayload) {
|
||||
telemetryInfo.method = aPayload.method;
|
||||
}
|
||||
|
||||
AddonManager.getInstallForURL(uri, {
|
||||
hash,
|
||||
name,
|
||||
icon,
|
||||
browser: aBrowser,
|
||||
triggeringPrincipal,
|
||||
telemetryInfo,
|
||||
sendCookies: true,
|
||||
}).then(aInstall => {
|
||||
function callCallback(status) {
|
||||
|
@ -17,11 +17,6 @@
|
||||
max-width: var(--section-width);
|
||||
}
|
||||
|
||||
#abuse-reports-messages {
|
||||
margin-inline-start: 28px;
|
||||
max-width: var(--section-width);
|
||||
}
|
||||
|
||||
/* The margin between message bars. */
|
||||
message-bar-stack > * {
|
||||
margin-bottom: 8px;
|
||||
@ -247,14 +242,6 @@ addon-details {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.addon-detail-rating {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.addon-detail-rating > a {
|
||||
margin-inline-start: 8px;
|
||||
}
|
||||
|
||||
.more-options-button {
|
||||
min-width: auto;
|
||||
min-height: auto;
|
||||
|
@ -9,18 +9,13 @@
|
||||
|
||||
<link rel="localization" href="branding/brand.ftl">
|
||||
<link rel="localization" href="toolkit/about/aboutAddons.ftl">
|
||||
<link rel="localization" href="toolkit/about/abuseReports.ftl">
|
||||
|
||||
<script src="chrome://mozapps/content/extensions/named-deck.js"></script>
|
||||
<script src="chrome://mozapps/content/extensions/aboutaddonsCommon.js"></script>
|
||||
<script src="chrome://mozapps/content/extensions/message-bar.js"></script>
|
||||
<script src="chrome://mozapps/content/extensions/abuse-reports.js"></script>
|
||||
<script src="chrome://mozapps/content/extensions/aboutaddons.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<message-bar-stack id="abuse-reports-messages" reverse max-message-bar-count="3">
|
||||
</message-bar-stack>
|
||||
|
||||
<div id="main"></div>
|
||||
|
||||
<!-- Include helpers for the inline options browser select and context menus. -->
|
||||
@ -81,26 +76,6 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="addon-name-container-in-disco-card">
|
||||
<div class="disco-card-head">
|
||||
<span class="disco-addon-name"></span>
|
||||
<span class="disco-addon-author"><a data-l10n-name="author" target="_blank"></a></span>
|
||||
</div>
|
||||
<button class="disco-cta-button primary" action="install-addon"></button>
|
||||
<button class="disco-cta-button" data-l10n-id="manage-addon-button" action="manage-addon"></button>
|
||||
</template>
|
||||
|
||||
<template name="addon-description-in-disco-card">
|
||||
<div>
|
||||
<strong class="disco-description-intro"></strong>
|
||||
<span class="disco-description-main"></span>
|
||||
</div>
|
||||
<div class="disco-description-statistics">
|
||||
<five-star-rating></five-star-rating>
|
||||
<span class="disco-user-count"></span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="addon-details">
|
||||
<div class="deck-tab-group">
|
||||
<named-deck-button-group>
|
||||
@ -122,33 +97,33 @@
|
||||
data-l10n-attrs="accesskey">
|
||||
</button>
|
||||
</div>
|
||||
<div class="addon-detail-row addon-detail-row-updates">
|
||||
<!--div class="addon-detail-row addon-detail-row-updates">
|
||||
<label data-l10n-id="addon-detail-updates-label"></label>
|
||||
<div>
|
||||
<button class="button-link" data-l10n-id="addon-detail-update-check-label" action="update-check" hidden></button>
|
||||
<label>
|
||||
<input type="radio" name="autoupdate" value="1" data-telemetry-value="default">
|
||||
<input type="radio" name="autoupdate" value="1">
|
||||
<span data-l10n-id="addon-detail-updates-radio-default"></span>
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="autoupdate" value="2" data-telemetry-value="enabled">
|
||||
<input type="radio" name="autoupdate" value="2">
|
||||
<span data-l10n-id="addon-detail-updates-radio-on"></span>
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="autoupdate" value="0" data-telemetry-value="">
|
||||
<input type="radio" name="autoupdate" value="0">
|
||||
<span data-l10n-id="addon-detail-updates-radio-off"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div-->
|
||||
<div class="addon-detail-row addon-detail-row-has-help addon-detail-row-private-browsing" hidden>
|
||||
<label data-l10n-id="detail-private-browsing-label"></label>
|
||||
<div>
|
||||
<label>
|
||||
<input type="radio" name="private-browsing" value="1" data-telemetry-value="on">
|
||||
<input type="radio" name="private-browsing" value="1">
|
||||
<span data-l10n-id="addon-detail-private-browsing-allow"></span>
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="private-browsing" value="0" data-telemetry-value="off">
|
||||
<input type="radio" name="private-browsing" value="0">
|
||||
<span data-l10n-id="addon-detail-private-browsing-disallow"></span>
|
||||
</label>
|
||||
</div>
|
||||
@ -170,7 +145,7 @@
|
||||
</div>
|
||||
<div class="addon-detail-row addon-detail-row-author">
|
||||
<label data-l10n-id="addon-detail-author-label"></label>
|
||||
<a target="_blank" data-telemetry-name="author"></a>
|
||||
<a target="_blank"></a>
|
||||
</div>
|
||||
<div class="addon-detail-row addon-detail-row-version">
|
||||
<label data-l10n-id="addon-detail-version-label"></label>
|
||||
@ -180,14 +155,7 @@
|
||||
</div>
|
||||
<div class="addon-detail-row addon-detail-row-homepage">
|
||||
<label data-l10n-id="addon-detail-homepage-label"></label>
|
||||
<a target="_blank" data-telemetry-name="homepage"></a>
|
||||
</div>
|
||||
<div class="addon-detail-row addon-detail-row-rating">
|
||||
<label data-l10n-id="addon-detail-rating-label"></label>
|
||||
<div class="addon-detail-rating">
|
||||
<five-star-rating></five-star-rating>
|
||||
<a target="_blank" data-telemetry-name="rating"></a>
|
||||
</div>
|
||||
<a target="_blank"></a>
|
||||
</div>
|
||||
</section>
|
||||
<inline-options-browser name="preferences"></inline-options-browser>
|
||||
@ -196,15 +164,6 @@
|
||||
</named-deck>
|
||||
</template>
|
||||
|
||||
<template name="five-star-rating">
|
||||
<link rel="stylesheet" href="chrome://mozapps/content/extensions/rating-star.css">
|
||||
<span class="rating-star"></span>
|
||||
<span class="rating-star"></span>
|
||||
<span class="rating-star"></span>
|
||||
<span class="rating-star"></span>
|
||||
<span class="rating-star"></span>
|
||||
</template>
|
||||
|
||||
<template name="panel-list">
|
||||
<link rel="stylesheet" href="chrome://mozapps/content/extensions/panel-list.css">
|
||||
<div class="arrow top" role="presentation"></div>
|
||||
|
@ -4,14 +4,12 @@
|
||||
/* eslint max-len: ["error", 80] */
|
||||
/* exported initialize, hide, show */
|
||||
/* import-globals-from aboutaddonsCommon.js */
|
||||
/* import-globals-from abuse-reports.js */
|
||||
/* global MozXULElement, windowRoot */
|
||||
|
||||
"use strict";
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
AddonManager: "resource://gre/modules/AddonManager.jsm",
|
||||
AMTelemetry: "resource://gre/modules/AddonManager.jsm",
|
||||
ClientID: "resource://gre/modules/ClientID.jsm",
|
||||
DeferredTask: "resource://gre/modules/DeferredTask.jsm",
|
||||
E10SUtils: "resource://gre/modules/E10SUtils.jsm",
|
||||
@ -60,13 +58,6 @@ XPCOMUtils.defineLazyPreferenceGetter(
|
||||
|
||||
const UPDATES_RECENT_TIMESPAN = 2 * 24 * 3600000; // 2 days (in milliseconds)
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this,
|
||||
"ABUSE_REPORT_ENABLED",
|
||||
"extensions.abuseReport.enabled",
|
||||
false
|
||||
);
|
||||
|
||||
const PLUGIN_ICON_URL = "chrome://global/skin/plugins/pluginGeneric.svg";
|
||||
const EXTENSION_ICON_URL =
|
||||
"chrome://mozapps/skin/extensions/extensionGeneric.svg";
|
||||
@ -81,7 +72,6 @@ const PERMISSION_MASKS = {
|
||||
"change-privatebrowsing": AddonManager.PERM_CAN_CHANGE_PRIVATEBROWSING_ACCESS,
|
||||
};
|
||||
|
||||
const PREF_TELEMETRY_ENABLED = "datareporting.healthreport.uploadEnabled";
|
||||
const PRIVATE_BROWSING_PERM_NAME = "internal:privateBrowsingAllowed";
|
||||
const PRIVATE_BROWSING_PERMS = {
|
||||
permissions: [PRIVATE_BROWSING_PERM_NAME],
|
||||
@ -152,14 +142,6 @@ const AddonCardListenerHandler = {
|
||||
},
|
||||
};
|
||||
|
||||
function isAbuseReportSupported(addon) {
|
||||
return (
|
||||
ABUSE_REPORT_ENABLED &&
|
||||
["extension", "theme"].includes(addon.type) &&
|
||||
!(addon.isBuiltin || addon.isSystem)
|
||||
);
|
||||
}
|
||||
|
||||
async function isAllowedInPrivateBrowsing(addon) {
|
||||
// Use the Promise directly so this function stays sync for the other case.
|
||||
let perms = await ExtensionPermissions.get(addon.id);
|
||||
@ -202,13 +184,6 @@ async function getAddonMessageInfo(addon) {
|
||||
message: formatString("blocked", [name]),
|
||||
type: "error",
|
||||
};
|
||||
} else if (isDisabledUnsigned(addon)) {
|
||||
return {
|
||||
linkText: getString("unsigned.link"),
|
||||
linkUrl: SUPPORT_URL + "unsigned-addons",
|
||||
message: formatString("unsignedAndDisabled", [name, appName]),
|
||||
type: "error",
|
||||
};
|
||||
} else if (
|
||||
!addon.isCompatible &&
|
||||
(AddonManager.checkCompatibility ||
|
||||
@ -751,13 +726,9 @@ class AddonOptions extends HTMLElement {
|
||||
case "remove":
|
||||
el.hidden = !hasPermission(addon, "uninstall");
|
||||
break;
|
||||
case "report":
|
||||
el.hidden = !isAbuseReportSupported(addon);
|
||||
break;
|
||||
case "toggle-disabled": {
|
||||
let toggleDisabledAction = addon.userDisabled ? "enable" : "disable";
|
||||
document.l10n.setAttributes(el, `${toggleDisabledAction}-addon-button`);
|
||||
el.hidden = !hasPermission(addon, toggleDisabledAction);
|
||||
break;
|
||||
}
|
||||
case "install-update":
|
||||
@ -822,67 +793,6 @@ class PluginOptions extends AddonOptions {
|
||||
}
|
||||
customElements.define("plugin-options", PluginOptions);
|
||||
|
||||
class FiveStarRating extends HTMLElement {
|
||||
static get observedAttributes() {
|
||||
return ["rating"];
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: "open" });
|
||||
this.shadowRoot.append(importTemplate("five-star-rating"));
|
||||
}
|
||||
|
||||
set rating(v) {
|
||||
this.setAttribute("rating", v);
|
||||
}
|
||||
|
||||
get rating() {
|
||||
let v = parseFloat(this.getAttribute("rating"), 10);
|
||||
if (v >= 0 && v <= 5) {
|
||||
return v;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
get ratingBuckets() {
|
||||
// 0 <= x < 0.25 = empty
|
||||
// 0.25 <= x < 0.75 = half
|
||||
// 0.75 <= x <= 1 = full
|
||||
// ... et cetera, until x <= 5.
|
||||
let { rating } = this;
|
||||
return [0, 1, 2, 3, 4].map(ratingStart => {
|
||||
let distanceToFull = rating - ratingStart;
|
||||
if (distanceToFull < 0.25) {
|
||||
return "empty";
|
||||
}
|
||||
if (distanceToFull < 0.75) {
|
||||
return "half";
|
||||
}
|
||||
return "full";
|
||||
});
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.renderRating();
|
||||
}
|
||||
|
||||
attributeChangedCallback() {
|
||||
this.renderRating();
|
||||
}
|
||||
|
||||
renderRating() {
|
||||
let starElements = this.shadowRoot.querySelectorAll(".rating-star");
|
||||
for (let [i, part] of this.ratingBuckets.entries()) {
|
||||
starElements[i].setAttribute("fill", part);
|
||||
}
|
||||
document.l10n.setAttributes(this, "five-star-rating", {
|
||||
rating: this.rating,
|
||||
});
|
||||
}
|
||||
}
|
||||
customElements.define("five-star-rating", FiveStarRating);
|
||||
|
||||
class ContentSelectDropdown extends HTMLElement {
|
||||
connectedCallback() {
|
||||
if (this.children.length > 0) {
|
||||
@ -1231,12 +1141,6 @@ class AddonDetails extends HTMLElement {
|
||||
if (e.type == "view-changed" && e.target == this.deck) {
|
||||
switch (this.deck.selectedViewName) {
|
||||
case "release-notes":
|
||||
AMTelemetry.recordActionEvent({
|
||||
object: "aboutAddons",
|
||||
view: getTelemetryViewName(this),
|
||||
action: "releaseNotes",
|
||||
addon: this.addon,
|
||||
});
|
||||
let releaseNotes = this.querySelector("update-release-notes");
|
||||
let uri = this.releaseNotesUri;
|
||||
if (uri) {
|
||||
@ -1339,10 +1243,10 @@ class AddonDetails extends HTMLElement {
|
||||
this.querySelector(
|
||||
".addon-detail-contribute"
|
||||
).hidden = !addon.contributionURL;
|
||||
this.querySelector(".addon-detail-row-updates").hidden = !hasPermission(
|
||||
/*this.querySelector(".addon-detail-row-updates").hidden = !hasPermission(
|
||||
addon,
|
||||
"upgrade"
|
||||
);
|
||||
);*/
|
||||
|
||||
// By default, all private browsing rows are hidden. Possibly show one.
|
||||
if (allowPrivateBrowsingByDefault || addon.type != "extension") {
|
||||
@ -1419,19 +1323,6 @@ class AddonDetails extends HTMLElement {
|
||||
homepageRow.hidden = true;
|
||||
}
|
||||
|
||||
// Rating.
|
||||
let ratingRow = this.querySelector(".addon-detail-row-rating");
|
||||
if (addon.averageRating) {
|
||||
ratingRow.querySelector("five-star-rating").rating = addon.averageRating;
|
||||
let reviews = ratingRow.querySelector("a");
|
||||
reviews.href = addon.reviewURL;
|
||||
document.l10n.setAttributes(reviews, "addon-detail-reviews-link", {
|
||||
numberOfReviews: addon.reviewCount,
|
||||
});
|
||||
} else {
|
||||
ratingRow.hidden = true;
|
||||
}
|
||||
|
||||
this.update();
|
||||
}
|
||||
|
||||
@ -1526,7 +1417,6 @@ class AddonCard extends HTMLElement {
|
||||
if (e.type == "click") {
|
||||
switch (action) {
|
||||
case "toggle-disabled":
|
||||
this.recordActionEvent(addon.userDisabled ? "enable" : "disable");
|
||||
if (addon.userDisabled) {
|
||||
if (shouldShowPermissionsPrompt(addon)) {
|
||||
await showPermissionsPrompt(addon);
|
||||
@ -1547,15 +1437,12 @@ class AddonCard extends HTMLElement {
|
||||
}
|
||||
break;
|
||||
case "always-activate":
|
||||
this.recordActionEvent("enable");
|
||||
addon.userDisabled = false;
|
||||
break;
|
||||
case "never-activate":
|
||||
this.recordActionEvent("disable");
|
||||
addon.userDisabled = true;
|
||||
break;
|
||||
case "update-check":
|
||||
this.recordActionEvent("checkForUpdate");
|
||||
let listener = {
|
||||
onUpdateAvailable(addon, install) {
|
||||
attachUpdateHandler(install);
|
||||
@ -1584,7 +1471,6 @@ class AddonCard extends HTMLElement {
|
||||
this.updateInstall = null;
|
||||
break;
|
||||
case "contribute":
|
||||
this.recordActionEvent("contribute");
|
||||
// prettier-ignore
|
||||
windowRoot.ownerGlobal.openUILinkIn(addon.contributionURL, "tab", {
|
||||
triggeringPrincipal:
|
||||
@ -1595,10 +1481,8 @@ class AddonCard extends HTMLElement {
|
||||
break;
|
||||
case "preferences":
|
||||
if (getOptionsType(addon) == "tab") {
|
||||
this.recordActionEvent("preferences", "external");
|
||||
openOptionsInTab(addon.optionsURL);
|
||||
} else if (getOptionsType(addon) == "inline") {
|
||||
this.recordActionEvent("preferences", "inline");
|
||||
loadViewFn(`detail/${this.addon.id}/preferences`, e);
|
||||
}
|
||||
break;
|
||||
@ -1610,16 +1494,9 @@ class AddonCard extends HTMLElement {
|
||||
report,
|
||||
} = windowRoot.ownerGlobal.promptRemoveExtension(addon);
|
||||
let value = remove ? "accepted" : "cancelled";
|
||||
this.recordActionEvent("uninstall", value);
|
||||
if (remove) {
|
||||
await addon.uninstall(true);
|
||||
this.sendEvent("remove");
|
||||
if (report) {
|
||||
openAbuseReport({
|
||||
addonId: addon.id,
|
||||
reportEntryPoint: "uninstall",
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.sendEvent("remove-cancelled");
|
||||
}
|
||||
@ -1634,10 +1511,6 @@ class AddonCard extends HTMLElement {
|
||||
this.panel.toggle(e);
|
||||
}
|
||||
break;
|
||||
case "report":
|
||||
this.panel.hide();
|
||||
openAbuseReport({ addonId: addon.id, reportEntryPoint: "menu" });
|
||||
break;
|
||||
case "link":
|
||||
if (e.target.getAttribute("url")) {
|
||||
windowRoot.ownerGlobal.openWebLinkIn(
|
||||
@ -1656,30 +1529,14 @@ class AddonCard extends HTMLElement {
|
||||
// Handle a click on the card itself.
|
||||
if (!this.expanded) {
|
||||
loadViewFn(`detail/${this.addon.id}`, e);
|
||||
} else if (
|
||||
e.target.localName == "a" &&
|
||||
e.target.getAttribute("data-telemetry-name")
|
||||
) {
|
||||
let value = e.target.getAttribute("data-telemetry-name");
|
||||
AMTelemetry.recordLinkEvent({
|
||||
object: "aboutAddons",
|
||||
addon,
|
||||
value,
|
||||
extra: {
|
||||
view: getTelemetryViewName(this),
|
||||
},
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (e.type == "change") {
|
||||
let { name } = e.target;
|
||||
let telemetryValue = e.target.getAttribute("data-telemetry-value");
|
||||
if (name == "autoupdate") {
|
||||
this.recordActionEvent("setAddonUpdate", telemetryValue);
|
||||
addon.applyBackgroundUpdates = e.target.value;
|
||||
} else if (name == "private-browsing") {
|
||||
this.recordActionEvent("privateBrowsingAllowed", telemetryValue);
|
||||
let policy = WebExtensionPolicy.getByID(addon.id);
|
||||
let extension = policy && policy.extension;
|
||||
|
||||
@ -1961,16 +1818,6 @@ class AddonCard extends HTMLElement {
|
||||
sendEvent(name, detail) {
|
||||
this.dispatchEvent(new CustomEvent(name, { detail }));
|
||||
}
|
||||
|
||||
recordActionEvent(action, value) {
|
||||
AMTelemetry.recordActionEvent({
|
||||
object: "aboutAddons",
|
||||
view: getTelemetryViewName(this),
|
||||
action,
|
||||
addon: this.addon,
|
||||
value,
|
||||
});
|
||||
}
|
||||
}
|
||||
customElements.define("addon-card", AddonCard);
|
||||
|
||||
@ -2118,15 +1965,6 @@ class AddonList extends HTMLElement {
|
||||
message.append(addonName);
|
||||
const undo = document.createElement("button");
|
||||
undo.setAttribute("action", "undo");
|
||||
undo.addEventListener("click", () => {
|
||||
AMTelemetry.recordActionEvent({
|
||||
object: "aboutAddons",
|
||||
view: getTelemetryViewName(this),
|
||||
action: "undo",
|
||||
addon,
|
||||
});
|
||||
addon.cancelUninstall();
|
||||
});
|
||||
|
||||
document.l10n.setAttributes(message, "pending-uninstall-description", {
|
||||
addon: addon.name,
|
||||
@ -2454,17 +2292,6 @@ class UpdatesView {
|
||||
// Generic view management.
|
||||
let mainEl = null;
|
||||
|
||||
/**
|
||||
* The name of the view for an element, used for telemetry.
|
||||
*
|
||||
* @param {Element} el The element to find the view from. A parent of the
|
||||
* element must define a current-view property.
|
||||
* @returns {string} The current view name.
|
||||
*/
|
||||
function getTelemetryViewName(el) {
|
||||
return el.closest("[current-view]").getAttribute("current-view");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from extensions.js once, when about:addons is loading.
|
||||
*/
|
||||
|
@ -6,7 +6,7 @@
|
||||
"use strict";
|
||||
|
||||
/* exported attachUpdateHandler, gBrowser, getBrowserElement, isCorrectlySigned,
|
||||
* isDisabledUnsigned, loadReleaseNotes, openOptionsInTab,
|
||||
* loadReleaseNotes, openOptionsInTab,
|
||||
* promiseEvent, shouldShowPermissionsPrompt, showPermissionsPrompt */
|
||||
|
||||
const { AddonSettings } = ChromeUtils.import(
|
||||
@ -69,10 +69,6 @@ function attachUpdateHandler(install) {
|
||||
type: "update",
|
||||
addon: info.addon,
|
||||
icon: info.addon.icon,
|
||||
// Reference to the related AddonInstall object (used in
|
||||
// AMTelemetry to link the recorded event to the other events from
|
||||
// the same install flow).
|
||||
install,
|
||||
permissions: difference,
|
||||
resolve,
|
||||
reject,
|
||||
@ -191,11 +187,3 @@ function isCorrectlySigned(addon) {
|
||||
// they aren't the correct type for signing.
|
||||
return addon.isCorrectlySigned !== false;
|
||||
}
|
||||
|
||||
function isDisabledUnsigned(addon) {
|
||||
let signingRequired =
|
||||
addon.type == "locale"
|
||||
? AddonSettings.LANGPACKS_REQUIRE_SIGNING
|
||||
: AddonSettings.REQUIRE_SIGNING;
|
||||
return signingRequired && !isCorrectlySigned(addon);
|
||||
}
|
||||
|
@ -1,135 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
|
||||
<link rel="stylesheet" href="chrome://mozapps/content/extensions/aboutaddons.css">
|
||||
<link rel="stylesheet" href="chrome://mozapps/content/extensions/abuse-report-panel.css">
|
||||
|
||||
<link rel="localization" href="branding/brand.ftl">
|
||||
<link rel="localization" href="toolkit/about/aboutAddons.ftl">
|
||||
<link rel="localization" href="toolkit/about/abuseReports.ftl">
|
||||
|
||||
<script src="chrome://mozapps/content/extensions/abuse-report-panel.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- WebComponents Templates -->
|
||||
<template id="tmpl-abuse-report">
|
||||
<div class="modal-overlay-outer"></div>
|
||||
<div class="modal-panel-container">
|
||||
<form class="card addon-abuse-report" onsubmit="return false;">
|
||||
<div class="abuse-report-header">
|
||||
<img class="card-heading-icon addon-icon"/>
|
||||
<div class="card-contents">
|
||||
<span class="addon-name"></span>
|
||||
<span class="addon-author-box"
|
||||
data-l10n-args='{"author-name": "author placeholder"}'
|
||||
data-l10n-id="abuse-report-addon-authored-by">
|
||||
<a data-l10n-name="author-name"
|
||||
class="author" href="#" target="_blank"></a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<button class="abuse-report-close-icon"></button>
|
||||
<div class="abuse-report-contents">
|
||||
<abuse-report-reasons-panel></abuse-report-reasons-panel>
|
||||
<abuse-report-submit-panel hidden></abuse-report-submit-panel>
|
||||
</div>
|
||||
<div class="abuse-report-buttons">
|
||||
<div class="abuse-report-reasons-buttons">
|
||||
<button class="abuse-report-cancel"
|
||||
data-l10n-id="abuse-report-cancel-button">
|
||||
</button>
|
||||
<button class="primary abuse-report-next"
|
||||
data-l10n-id="abuse-report-next-button">
|
||||
</button>
|
||||
</div>
|
||||
<div class="abuse-report-submit-buttons" hidden>
|
||||
<button class="abuse-report-goback"
|
||||
data-l10n-id="abuse-report-goback-button">
|
||||
</button>
|
||||
<button class="primary abuse-report-submit"
|
||||
data-l10n-id="abuse-report-submit-button">
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template id="tmpl-reasons-panel">
|
||||
<h2 class="abuse-report-title"></h2>
|
||||
<hr>
|
||||
<p class="abuse-report-subtitle"
|
||||
data-l10n-id="abuse-report-subtitle">
|
||||
</p>
|
||||
<ul class="abuse-report-reasons">
|
||||
<li is="abuse-report-reason-listitem" report-reason="other"></li>
|
||||
</ul>
|
||||
<p data-l10n-id="abuse-report-learnmore">
|
||||
<a class="abuse-report-learnmore" target="_blank"
|
||||
data-l10n-name="learnmore-link">
|
||||
</a>
|
||||
</p>
|
||||
</template>
|
||||
|
||||
<template id="tmpl-submit-panel">
|
||||
<h2 class="abuse-reason-title"></h2>
|
||||
<abuse-report-reason-suggestions></abuse-report-reason-suggestions>
|
||||
<hr>
|
||||
<p class="abuse-report-subtitle" data-l10n-id="abuse-report-submit-description">
|
||||
</p>
|
||||
<textarea name="message" data-l10n-id="abuse-report-textarea"></textarea>
|
||||
<p class="abuse-report-note" data-l10n-id="abuse-report-submit-note">
|
||||
</p>
|
||||
</template>
|
||||
|
||||
<template id="tmpl-reason-listitem">
|
||||
<label>
|
||||
<input type="radio" name="reason" class="radio">
|
||||
<span class="reason-description"></span>
|
||||
<span hidden class="abuse-report-note reason-example"></span>
|
||||
</label>
|
||||
</template>
|
||||
|
||||
<template id="tmpl-suggestions-settings">
|
||||
<p data-l10n-id="abuse-report-settings-suggestions"><p>
|
||||
<ul>
|
||||
<li>
|
||||
<a class="abuse-settings-search-learnmore" target="_blank"
|
||||
data-l10n-id="abuse-report-settings-suggestions-search">
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="abuse-settings-homepage-learnmore" target="_blank"
|
||||
data-l10n-id="abuse-report-settings-suggestions-homepage">
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<template id="tmpl-suggestions-policy">
|
||||
<p data-l10n-id="abuse-report-policy-suggestions">
|
||||
<a class="abuse-policy-learnmore" target="_blank"
|
||||
data-l10n-name="report-infringement-link">
|
||||
</a>
|
||||
</p>
|
||||
</template>
|
||||
|
||||
<template id="tmpl-suggestions-broken-extension">
|
||||
<p data-l10n-id="abuse-report-broken-suggestions-extension">
|
||||
<a class="extension-support-link" target="_blank"
|
||||
data-l10n-name="support-link">
|
||||
</a>
|
||||
<p>
|
||||
</template>
|
||||
|
||||
<template id="tmpl-suggestions-broken-theme">
|
||||
<p data-l10n-id="abuse-report-broken-suggestions-theme">
|
||||
<a class="extension-support-link" target="_blank"
|
||||
data-l10n-name="support-link">
|
||||
</a>
|
||||
<p>
|
||||
</template>
|
||||
</body>
|
||||
</html>
|
@ -1,283 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
/* globals MozXULElement, Services, useHtmlViews, getHtmlBrowser, htmlBrowserLoaded */
|
||||
|
||||
{
|
||||
const ABUSE_REPORT_ENABLED = Services.prefs.getBoolPref(
|
||||
"extensions.abuseReport.enabled",
|
||||
false
|
||||
);
|
||||
const ABUSE_REPORT_FRAME_URL =
|
||||
"chrome://mozapps/content/extensions/abuse-report-frame.html";
|
||||
const fm = Services.focus;
|
||||
const { AbuseReporter } = ChromeUtils.import(
|
||||
"resource://gre/modules/AbuseReporter.jsm"
|
||||
);
|
||||
|
||||
class AddonAbuseReportsXULFrame extends MozXULElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.report = null;
|
||||
// Keep track if the loadURI has already been called on the
|
||||
// browser element.
|
||||
this.browserLoadURI = false;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.textContent = "";
|
||||
|
||||
const content = MozXULElement.parseXULToFragment(`
|
||||
<browser id="abuse-report-xulframe-overlay-inner"
|
||||
type="content"
|
||||
disablehistory="true"
|
||||
transparent="true"
|
||||
flex="1">
|
||||
</browser>
|
||||
`);
|
||||
|
||||
this.appendChild(content);
|
||||
|
||||
const browser = this.querySelector("browser");
|
||||
this.promiseBrowserLoaded = new Promise(resolve => {
|
||||
browser.addEventListener("load", () => resolve(browser), {
|
||||
once: true,
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener("focus", this);
|
||||
|
||||
this.promiseHtmlAboutAddons.then(win => {
|
||||
win.document.addEventListener("abuse-report:new", this);
|
||||
});
|
||||
|
||||
this.update();
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
this.textContent = "";
|
||||
this.browserLoadURI = false;
|
||||
this.promiseBrowserLoaded = null;
|
||||
this.report = null;
|
||||
document.removeEventListener("focus", this);
|
||||
|
||||
this.promiseHtmlAboutAddons.then(win => {
|
||||
win.document.removeEventListener("abuse-report:new", this);
|
||||
});
|
||||
}
|
||||
|
||||
handleEvent(evt) {
|
||||
// The "abuse-report:new" events are dispatched from the html about:addons sub-frame
|
||||
// (on the html about:addons document).
|
||||
// "abuse-report:cancel", "abuse-report:submit" and "abuse-report:updated" are
|
||||
// all dispatched from the AbuseReport webcomponent (on the AbuseReport element itself).
|
||||
// All the "abuse-report:*" events are also forwarded (dispatched on the frame
|
||||
// DOM element itself) to make it easier for the tests to wait for certain conditions
|
||||
// to be reached.
|
||||
switch (evt.type) {
|
||||
case "focus":
|
||||
this.focus();
|
||||
break;
|
||||
case "abuse-report:new":
|
||||
this.openReport(evt.detail);
|
||||
this.forwardEvent(evt);
|
||||
break;
|
||||
case "abuse-report:cancel":
|
||||
this.cancelReport();
|
||||
this.forwardEvent(evt);
|
||||
break;
|
||||
case "abuse-report:submit":
|
||||
this.onSubmitReport(evt);
|
||||
this.forwardEvent(evt);
|
||||
break;
|
||||
case "abuse-report:updated":
|
||||
this.forwardEvent(evt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
forwardEvent(evt) {
|
||||
this.dispatchEvent(new CustomEvent(evt.type, { detail: evt.detail }));
|
||||
}
|
||||
|
||||
async openReport({ addonId, reportEntryPoint }) {
|
||||
if (this.report) {
|
||||
throw new Error(
|
||||
"Ignoring new abuse report request. AbuseReport panel already open"
|
||||
);
|
||||
} else {
|
||||
try {
|
||||
this.report = await AbuseReporter.createAbuseReport(addonId, {
|
||||
reportEntryPoint,
|
||||
});
|
||||
this.update();
|
||||
} catch (err) {
|
||||
// Log the complete error in the console.
|
||||
console.error("Error creating abuse report for", addonId, err);
|
||||
// The report has an error on creation, and so instead of opening the report
|
||||
// panel an error message-bar is created on the HTML about:addons page.
|
||||
const win = await this.promiseHtmlAboutAddons;
|
||||
win.document.dispatchEvent(
|
||||
new CustomEvent("abuse-report:create-error", {
|
||||
detail: {
|
||||
addonId,
|
||||
addon: err.addon,
|
||||
errorType: err.errorType,
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cancelReport() {
|
||||
if (this.report) {
|
||||
this.report.abort();
|
||||
this.report = null;
|
||||
this.update();
|
||||
}
|
||||
}
|
||||
|
||||
async onSubmitReport(evt) {
|
||||
if (this.report) {
|
||||
this.report = null;
|
||||
this.update();
|
||||
const win = await this.promiseHtmlAboutAddons;
|
||||
win.document.dispatchEvent(evt);
|
||||
}
|
||||
}
|
||||
|
||||
focus() {
|
||||
// Trap the focus in the abuse report modal while it is enabled.
|
||||
if (this.hasAddonId) {
|
||||
this.promiseAbuseReport.then(abuseReport => {
|
||||
abuseReport.focus();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async update() {
|
||||
const { report } = this;
|
||||
if (report && report.addon && !report.errorType) {
|
||||
const { addon, reportEntryPoint } = this.report;
|
||||
this.addonId = addon.id;
|
||||
this.reportEntryPoint = reportEntryPoint;
|
||||
|
||||
// Set the addon id on the addon-abuse-report webcomponent instance
|
||||
// embedded in the XUL browser.
|
||||
this.promiseAbuseReport.then(abuseReport => {
|
||||
this.hidden = false;
|
||||
abuseReport.addEventListener("abuse-report:updated", this, {
|
||||
once: true,
|
||||
});
|
||||
abuseReport.addEventListener("abuse-report:submit", this, {
|
||||
once: true,
|
||||
});
|
||||
abuseReport.addEventListener("abuse-report:cancel", this, {
|
||||
once: true,
|
||||
});
|
||||
abuseReport.setAbuseReport(report);
|
||||
// Hide the content of the underlying about:addons page from
|
||||
// screen readers.
|
||||
this.aboutAddonsContent.setAttribute("aria-hidden", true);
|
||||
// Move the focus to the embedded window.
|
||||
this.focus();
|
||||
this.dispatchEvent(new CustomEvent("abuse-report:frame-shown"));
|
||||
});
|
||||
} else {
|
||||
this.hidden = true;
|
||||
this.removeAttribute("addon-id");
|
||||
this.removeAttribute("report-entry-point");
|
||||
|
||||
// Make the content of the underlying about:addons page visible
|
||||
// to screen readers.
|
||||
this.aboutAddonsContent.setAttribute("aria-hidden", false);
|
||||
|
||||
// Move the focus back to the top level window.
|
||||
fm.moveFocus(window, null, fm.MOVEFOCUS_ROOT, fm.FLAG_BYKEY);
|
||||
this.promiseAbuseReport
|
||||
.then(
|
||||
abuseReport => {
|
||||
abuseReport.removeEventListener("abuse-report:updated", this, {
|
||||
once: true,
|
||||
});
|
||||
abuseReport.removeEventListener("abuse-report:submit", this, {
|
||||
once: true,
|
||||
});
|
||||
abuseReport.removeEventListener("abuse-report:cancel", this, {
|
||||
once: true,
|
||||
});
|
||||
abuseReport.setAbuseReport(null);
|
||||
},
|
||||
err => {
|
||||
console.error("promiseAbuseReport rejected", err);
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
this.dispatchEvent(new CustomEvent("abuse-report:frame-hidden"));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
get aboutAddonsContent() {
|
||||
return document.getElementById("main-page-content");
|
||||
}
|
||||
|
||||
get promiseAbuseReport() {
|
||||
if (!this.browserLoadURI) {
|
||||
const browser = this.querySelector("browser");
|
||||
browser.loadURI(ABUSE_REPORT_FRAME_URL, {
|
||||
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
});
|
||||
this.browserLoadURI = true;
|
||||
}
|
||||
return this.promiseBrowserLoaded.then(browser => {
|
||||
return browser.contentDocument.querySelector("addon-abuse-report");
|
||||
});
|
||||
}
|
||||
|
||||
get promiseHtmlAboutAddons() {
|
||||
const browser = getHtmlBrowser();
|
||||
return htmlBrowserLoaded.then(() => {
|
||||
return browser.contentWindow;
|
||||
});
|
||||
}
|
||||
|
||||
get hasAddonId() {
|
||||
return !!this.addonId;
|
||||
}
|
||||
|
||||
get addonId() {
|
||||
return this.getAttribute("addon-id");
|
||||
}
|
||||
|
||||
set addonId(value) {
|
||||
this.setAttribute("addon-id", value);
|
||||
}
|
||||
|
||||
get reportEntryPoint() {
|
||||
return this.getAttribute("report-entry-point");
|
||||
}
|
||||
|
||||
set reportEntryPoint(value) {
|
||||
this.setAttribute("report-entry-point", value);
|
||||
}
|
||||
}
|
||||
|
||||
// If the html about:addons and the abuse report are both enabled, register
|
||||
// the custom XUL WebComponent and append it to the XUL stack element
|
||||
// (if not registered the element will be just a dummy hidden box)
|
||||
if (useHtmlViews && ABUSE_REPORT_ENABLED) {
|
||||
customElements.define(
|
||||
"addon-abuse-report-xulframe",
|
||||
AddonAbuseReportsXULFrame
|
||||
);
|
||||
}
|
||||
|
||||
// Helper method exported into the about:addons global, used to open the
|
||||
// abuse report panel from outside of the about:addons page
|
||||
// (e.g. triggered from the browserAction context menu).
|
||||
window.openAbuseReport = ({ addonId, reportEntryPoint }) => {
|
||||
const frame = document.querySelector("addon-abuse-report-xulframe");
|
||||
frame.openReport({ addonId, reportEntryPoint });
|
||||
};
|
||||
}
|
@ -1,217 +0,0 @@
|
||||
/* Abuse Reports card */
|
||||
|
||||
:root {
|
||||
--close-icon-url: url("chrome://global/skin/icons/close.svg");
|
||||
--close-icon-size: 20px;
|
||||
|
||||
--radio-image-url: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E %3Ccircle cx='8' cy='8' r='4' fill='%23fff'/%3E %3C/svg%3E");
|
||||
--radio-size: 16px;
|
||||
|
||||
--modal-panel-min-width: 60%;
|
||||
--modal-panel-margin-top: 36px;
|
||||
--modal-panel-margin-bottom: 36px;
|
||||
--modal-panel-margin: 20%;
|
||||
--modal-panel-padding: 40px;
|
||||
|
||||
--line-height: 20px;
|
||||
--textarea-height: 220px;
|
||||
--button-padding: 52px;
|
||||
--listitem-padding-bottom: 14px;
|
||||
--list-radio-column-size: 28px;
|
||||
--note-font-size: 14px;
|
||||
--note-font-weight: 400;
|
||||
--subtitle-font-size: 16px;
|
||||
--subtitle-font-weight: 600;
|
||||
|
||||
--input-radio-border: var(--in-content-box-border-color);
|
||||
--input-radio-background: var(--grey-90-a10);
|
||||
--input-radio-background-hover: var(--grey-90-a20);
|
||||
--input-radio-background-active: var(--grey-90-a30);
|
||||
--input-radio-background-selected: var(--blue-60);
|
||||
--input-radio-background-selected-hover: var(--blue-70);
|
||||
--input-radio-background-selected-active: var(--blue-80);
|
||||
--input-radio-focus-shadow: 0 0 0 1px #0a84ff inset, 0 0 0 1px #0a84ff, 0 0 0 4px rgba(10, 132, 255, 0.3);
|
||||
}
|
||||
|
||||
@supports -moz-bool-pref("browser.in-content.dark-mode") {
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--input-radio-background: #202023;
|
||||
--input-radio-background-hover: #303033;
|
||||
--input-radio-background-active: #404044;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure that the document (embedded in the XUL about:addons using a
|
||||
XUL browser) has a transparent background */
|
||||
html {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.modal-overlay-outer {
|
||||
background: var(--grey-90-a60);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.modal-panel-container {
|
||||
padding-top: var(--modal-panel-margin-top);
|
||||
padding-bottom: var(--modal-panel-margin-bottom);
|
||||
padding-left: var(--modal-panel-margin);
|
||||
padding-right: var(--modal-panel-margin);
|
||||
}
|
||||
|
||||
.addon-abuse-report {
|
||||
min-width: var(--modal-panel-min-width);
|
||||
padding: var(--modal-panel-padding);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.addon-abuse-report:hover {
|
||||
/* Avoid the card box highlighting on hover. */
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.addon-abuse-report button {
|
||||
padding: 0 var(--button-padding);
|
||||
}
|
||||
|
||||
.abuse-report-close-icon {
|
||||
/* position the close button in the panel upper-right corner */
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
inset-inline-end: 16px;
|
||||
}
|
||||
|
||||
button.abuse-report-close-icon {
|
||||
background: var(--close-icon-url) no-repeat center center;
|
||||
-moz-context-properties: fill, fill-opacity;
|
||||
color: inherit !important;
|
||||
fill: currentColor;
|
||||
fill-opacity: 0;
|
||||
min-width: auto;
|
||||
min-height: auto;
|
||||
width: var(--close-icon-size);
|
||||
height: var(--close-icon-size);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
button.abuse-report-close-icon:hover {
|
||||
fill-opacity: 0.1;
|
||||
}
|
||||
|
||||
button.abuse-report-close-icon:hover:active {
|
||||
fill-opacity: 0.2;
|
||||
}
|
||||
|
||||
.abuse-report-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.abuse-report-contents,
|
||||
.abuse-report-contents > hr {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.abuse-report-note {
|
||||
color: var(--in-content-deemphasized-text);
|
||||
font-size: var(--note-font-size);
|
||||
font-weight: var(--note-font-weight);
|
||||
line-height: var(--line-height);
|
||||
}
|
||||
|
||||
.abuse-report-subtitle {
|
||||
font-size: var(--subtitle-font-size);
|
||||
font-weight: var(--subtitle-font-weight);
|
||||
line-height: var(--line-height);
|
||||
}
|
||||
|
||||
ul.abuse-report-reasons {
|
||||
list-style-type: none;
|
||||
padding-inline-start: 0;
|
||||
}
|
||||
|
||||
ul.abuse-report-reasons > li {
|
||||
display: flex;
|
||||
padding-bottom: var(--listitem-padding-bottom);
|
||||
}
|
||||
|
||||
ul.abuse-report-reasons > li > label {
|
||||
width: 100%;
|
||||
line-height: var(--line-height);
|
||||
font-size: var(--subtitle-font-size);
|
||||
font-weight: var(--note-font-weight);
|
||||
}
|
||||
|
||||
ul.abuse-report-reasons > li > label {
|
||||
display: grid;
|
||||
grid-template-columns: var(--list-radio-column-size) auto;
|
||||
grid-template-rows: 50% auto;
|
||||
}
|
||||
|
||||
ul.abuse-report-reasons > li > label > [type=radio] {
|
||||
grid-column: 1;
|
||||
}
|
||||
|
||||
ul.abuse-report-reasons > li > label > span {
|
||||
grid-column: 2;
|
||||
}
|
||||
|
||||
ul.abuse-report-reasons > li > label > span:nth-child(2) {
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
.abuse-report-contents [type=radio] {
|
||||
-moz-appearance: none;
|
||||
height: var(--radio-size);
|
||||
width: var(--radio-size);
|
||||
border-radius: 100%;
|
||||
border: 1px solid var(--input-radio-border);
|
||||
background-color: var(--input-radio-background);
|
||||
margin-inline-start: 4px;
|
||||
margin-inline-end: 4px;
|
||||
}
|
||||
|
||||
.abuse-report-contents [type=radio]:focus {
|
||||
border: none;
|
||||
box-shadow: var(--input-radio-focus-shadow);
|
||||
}
|
||||
|
||||
.abuse-report-contents label:hover [type=radio]:not(:active),
|
||||
.abuse-report-contents [type=radio]:hover {
|
||||
background-color: var(--input-radio-background-hover);
|
||||
}
|
||||
|
||||
.abuse-report-contents [type=radio]:active {
|
||||
background-color: var(--input-radio-background-active);
|
||||
}
|
||||
|
||||
.abuse-report-contents [type=radio]:checked {
|
||||
background-image: var(--radio-image-url);
|
||||
background-color: var(--input-radio-background-selected);
|
||||
background-position: center center;
|
||||
}
|
||||
|
||||
.abuse-report-contents label:hover [type=radio]:checked:not(:active),
|
||||
.abuse-report-contents [type=radio]:checked:hover {
|
||||
background-color: var(--input-radio-background-selected-hover);
|
||||
}
|
||||
|
||||
.abuse-report-contents [type=radio]:checked:active {
|
||||
background-color: var(--input-radio-background-selected-active);
|
||||
}
|
||||
|
||||
abuse-report-submit-panel textarea {
|
||||
width: 100%;
|
||||
height: var(--textarea-height);
|
||||
resize: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
@ -1,730 +0,0 @@
|
||||
/* 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/. */
|
||||
/* eslint max-len: ["error", 80] */
|
||||
|
||||
"use strict";
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"Services",
|
||||
"resource://gre/modules/Services.jsm"
|
||||
);
|
||||
|
||||
const showOnAnyType = () => false;
|
||||
const hideOnAnyType = () => true;
|
||||
const hideOnThemeType = addonType => addonType === "theme";
|
||||
|
||||
// The reasons string used as a key in this Map is expected to stay in sync
|
||||
// with the reasons string used in the "abuseReports.ftl" locale file and
|
||||
// the suggestions templates included in abuse-reports-xulframe.html.
|
||||
const ABUSE_REASONS = (window.ABUSE_REPORT_REASONS = {
|
||||
damage: {
|
||||
isExampleHidden: showOnAnyType,
|
||||
isReasonHidden: hideOnThemeType,
|
||||
},
|
||||
spam: {
|
||||
isExampleHidden: showOnAnyType,
|
||||
isReasonHidden: showOnAnyType,
|
||||
},
|
||||
settings: {
|
||||
hasSuggestions: true,
|
||||
isExampleHidden: hideOnAnyType,
|
||||
isReasonHidden: hideOnThemeType,
|
||||
},
|
||||
deceptive: {
|
||||
isExampleHidden: showOnAnyType,
|
||||
isReasonHidden: showOnAnyType,
|
||||
},
|
||||
broken: {
|
||||
hasAddonTypeL10nId: true,
|
||||
hasAddonTypeSuggestionTemplate: true,
|
||||
hasSuggestions: true,
|
||||
isExampleHidden: hideOnThemeType,
|
||||
isReasonHidden: showOnAnyType,
|
||||
},
|
||||
policy: {
|
||||
hasSuggestions: true,
|
||||
isExampleHidden: hideOnAnyType,
|
||||
isReasonHidden: showOnAnyType,
|
||||
},
|
||||
unwanted: {
|
||||
isExampleHidden: showOnAnyType,
|
||||
isReasonHidden: hideOnThemeType,
|
||||
},
|
||||
other: {
|
||||
isExampleHidden: hideOnAnyType,
|
||||
isReasonHidden: showOnAnyType,
|
||||
},
|
||||
});
|
||||
|
||||
function getReasonL10nId(reason, addonType) {
|
||||
let l10nId = `abuse-report-${reason}-reason`;
|
||||
// Special case reasons that have a addonType-specific
|
||||
// l10n id.
|
||||
if (ABUSE_REASONS[reason].hasAddonTypeL10nId) {
|
||||
l10nId += `-${addonType}`;
|
||||
}
|
||||
return l10nId;
|
||||
}
|
||||
|
||||
function getSuggestionsTemplate(reason, addonType) {
|
||||
const reasonInfo = ABUSE_REASONS[reason];
|
||||
if (!reasonInfo.hasSuggestions) {
|
||||
return null;
|
||||
}
|
||||
let templateId = `tmpl-suggestions-${reason}`;
|
||||
// Special case reasons that have a addonType-specific
|
||||
// suggestion template.
|
||||
if (reasonInfo.hasAddonTypeSuggestionTemplate) {
|
||||
templateId += `-${addonType}`;
|
||||
}
|
||||
return document.getElementById(templateId);
|
||||
}
|
||||
|
||||
// Map of the learnmore links metadata, keyed by link element class.
|
||||
const LEARNMORE_LINKS = {
|
||||
".abuse-report-learnmore": {
|
||||
path: "reporting-extensions-and-themes-abuse",
|
||||
},
|
||||
".abuse-settings-search-learnmore": {
|
||||
path: "prefs-search",
|
||||
},
|
||||
".abuse-settings-homepage-learnmore": {
|
||||
path: "prefs-homepage",
|
||||
},
|
||||
".abuse-policy-learnmore": {
|
||||
baseURL: "https://www.mozilla.org/%LOCALE%/",
|
||||
path: "about/legal/report-infringement/",
|
||||
},
|
||||
};
|
||||
|
||||
// Format links that match the selector in the LEARNMORE_LINKS map
|
||||
// found in a given container element.
|
||||
function formatLearnMoreURLs(containerEl) {
|
||||
for (const [linkClass, linkInfo] of Object.entries(LEARNMORE_LINKS)) {
|
||||
for (const element of containerEl.querySelectorAll(linkClass)) {
|
||||
const baseURL = linkInfo.baseURL
|
||||
? Services.urlFormatter.formatURL(linkInfo.baseURL)
|
||||
: Services.urlFormatter.formatURLPref("app.support.baseURL");
|
||||
|
||||
element.href = baseURL + linkInfo.path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Define a set of getters from a Map<propertyName, selector>.
|
||||
function defineElementSelectorsGetters(object, propsMap) {
|
||||
const props = Object.entries(propsMap).reduce((acc, entry) => {
|
||||
const [name, selector] = entry;
|
||||
acc[name] = { get: () => object.querySelector(selector) };
|
||||
return acc;
|
||||
}, {});
|
||||
Object.defineProperties(object, props);
|
||||
}
|
||||
|
||||
// Define a set of properties getters and setters for a
|
||||
// Map<propertyName, attributeName>.
|
||||
function defineElementAttributesProperties(object, propsMap) {
|
||||
const props = Object.entries(propsMap).reduce((acc, entry) => {
|
||||
const [name, attr] = entry;
|
||||
acc[name] = {
|
||||
get: () => object.getAttribute(attr),
|
||||
set: value => {
|
||||
object.setAttribute(attr, value);
|
||||
},
|
||||
};
|
||||
return acc;
|
||||
}, {});
|
||||
Object.defineProperties(object, props);
|
||||
}
|
||||
|
||||
// Return an object with properties associated to elements
|
||||
// found using the related selector in the propsMap.
|
||||
function getElements(containerEl, propsMap) {
|
||||
return Object.entries(propsMap).reduce((acc, entry) => {
|
||||
const [name, selector] = entry;
|
||||
let elements = containerEl.querySelectorAll(selector);
|
||||
acc[name] = elements.length > 1 ? elements : elements[0];
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
function dispatchCustomEvent(el, eventName, detail) {
|
||||
el.dispatchEvent(new CustomEvent(eventName, { detail }));
|
||||
}
|
||||
|
||||
// This WebComponent extends the li item to represent an abuse report reason
|
||||
// and it is responsible for:
|
||||
// - embedding a photon styled radio buttons
|
||||
// - localizing the reason list item
|
||||
// - optionally embedding a localized example, positioned
|
||||
// below the reason label, and adjusts the item height
|
||||
// accordingly
|
||||
class AbuseReasonListItem extends HTMLLIElement {
|
||||
constructor() {
|
||||
super();
|
||||
defineElementAttributesProperties(this, {
|
||||
addonType: "addon-type",
|
||||
reason: "report-reason",
|
||||
checked: "checked",
|
||||
});
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.update();
|
||||
}
|
||||
|
||||
async update() {
|
||||
if (this.reason !== "other" && !this.addonType) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { reason, checked, addonType } = this;
|
||||
|
||||
this.textContent = "";
|
||||
const content = document.importNode(this.template.content, true);
|
||||
|
||||
if (reason) {
|
||||
const reasonId = `abuse-reason-${reason}`;
|
||||
const reasonInfo = ABUSE_REASONS[reason] || {};
|
||||
|
||||
const { labelEl, descriptionEl, radioEl } = getElements(content, {
|
||||
labelEl: "label",
|
||||
descriptionEl: ".reason-description",
|
||||
radioEl: "input[type=radio]",
|
||||
});
|
||||
|
||||
labelEl.setAttribute("for", reasonId);
|
||||
radioEl.id = reasonId;
|
||||
radioEl.value = reason;
|
||||
radioEl.checked = !!checked;
|
||||
|
||||
// This reason has a different localized description based on the
|
||||
// addon type.
|
||||
document.l10n.setAttributes(
|
||||
descriptionEl,
|
||||
getReasonL10nId(reason, addonType)
|
||||
);
|
||||
|
||||
// Show the reason example if supported for the addon type.
|
||||
if (!reasonInfo.isExampleHidden(addonType)) {
|
||||
const exampleEl = content.querySelector(".reason-example");
|
||||
document.l10n.setAttributes(
|
||||
exampleEl,
|
||||
`abuse-report-${reason}-example`
|
||||
);
|
||||
exampleEl.hidden = false;
|
||||
}
|
||||
}
|
||||
|
||||
formatLearnMoreURLs(content);
|
||||
|
||||
this.appendChild(content);
|
||||
}
|
||||
|
||||
get template() {
|
||||
return document.getElementById("tmpl-reason-listitem");
|
||||
}
|
||||
}
|
||||
|
||||
// This WebComponents implements the first step of the abuse
|
||||
// report submission and embeds a randomized reasons list.
|
||||
class AbuseReasonsPanel extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
defineElementAttributesProperties(this, {
|
||||
addonType: "addon-type",
|
||||
});
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.update();
|
||||
}
|
||||
|
||||
update() {
|
||||
if (!this.isConnected || !this.addonType) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { addonType } = this;
|
||||
|
||||
this.textContent = "";
|
||||
const content = document.importNode(this.template.content, true);
|
||||
|
||||
const { titleEl, listEl } = getElements(content, {
|
||||
titleEl: ".abuse-report-title",
|
||||
listEl: "ul.abuse-report-reasons",
|
||||
});
|
||||
|
||||
// Change the title l10n-id if the addon type is theme.
|
||||
document.l10n.setAttributes(titleEl, `abuse-report-title-${addonType}`);
|
||||
|
||||
// Create the randomized list of reasons.
|
||||
const reasons = Object.keys(ABUSE_REASONS)
|
||||
.filter(reason => reason !== "other")
|
||||
.sort(() => Math.random() - 0.5);
|
||||
|
||||
for (const reason of reasons) {
|
||||
const reasonInfo = ABUSE_REASONS[reason];
|
||||
if (!reasonInfo || reasonInfo.isReasonHidden(addonType)) {
|
||||
// Skip an extension only reason while reporting a theme.
|
||||
continue;
|
||||
}
|
||||
const item = document.createElement("li", {
|
||||
is: "abuse-report-reason-listitem",
|
||||
});
|
||||
item.reason = reason;
|
||||
item.addonType = addonType;
|
||||
|
||||
listEl.prepend(item);
|
||||
}
|
||||
|
||||
listEl.firstElementChild.checked = true;
|
||||
formatLearnMoreURLs(content);
|
||||
|
||||
this.appendChild(content);
|
||||
}
|
||||
|
||||
get template() {
|
||||
return document.getElementById("tmpl-reasons-panel");
|
||||
}
|
||||
}
|
||||
|
||||
// This WebComponent is responsible for the suggestions, which are:
|
||||
// - generated based on a template keyed by abuse report reason
|
||||
// - localized by assigning fluent ids generated from the abuse report reason
|
||||
// - learn more and extension support url are then generated when the
|
||||
// specific reason expects it
|
||||
class AbuseReasonSuggestions extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
defineElementAttributesProperties(this, {
|
||||
extensionSupportURL: "extension-support-url",
|
||||
reason: "report-reason",
|
||||
});
|
||||
}
|
||||
|
||||
update() {
|
||||
const { addonType, extensionSupportURL, reason } = this;
|
||||
|
||||
if (!addonType) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.textContent = "";
|
||||
|
||||
let template = getSuggestionsTemplate(reason, addonType);
|
||||
if (template) {
|
||||
let content = document.importNode(template.content, true);
|
||||
|
||||
formatLearnMoreURLs(content);
|
||||
|
||||
let extSupportLink = content.querySelector("a.extension-support-link");
|
||||
if (extSupportLink) {
|
||||
extSupportLink.href = extensionSupportURL;
|
||||
}
|
||||
|
||||
this.appendChild(content);
|
||||
this.hidden = false;
|
||||
} else {
|
||||
this.hidden = true;
|
||||
}
|
||||
}
|
||||
|
||||
get LEARNMORE_LINKS() {
|
||||
return Object.keys(LEARNMORE_LINKS);
|
||||
}
|
||||
}
|
||||
|
||||
// This WebComponents implements the last step of the abuse report submission.
|
||||
class AbuseSubmitPanel extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
defineElementAttributesProperties(this, {
|
||||
addonType: "addon-type",
|
||||
reason: "report-reason",
|
||||
extensionSupportURL: "extensionSupportURL",
|
||||
});
|
||||
defineElementSelectorsGetters(this, {
|
||||
_textarea: "textarea",
|
||||
_title: ".abuse-reason-title",
|
||||
_suggestions: "abuse-report-reason-suggestions",
|
||||
});
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.render();
|
||||
}
|
||||
|
||||
render() {
|
||||
this.textContent = "";
|
||||
this.appendChild(document.importNode(this.template.content, true));
|
||||
}
|
||||
|
||||
update() {
|
||||
if (!this.isConnected || !this.addonType) {
|
||||
return;
|
||||
}
|
||||
const { addonType, reason, _suggestions, _title } = this;
|
||||
document.l10n.setAttributes(_title, getReasonL10nId(reason, addonType));
|
||||
_suggestions.reason = reason;
|
||||
_suggestions.addonType = addonType;
|
||||
_suggestions.extensionSupportURL = this.extensionSupportURL;
|
||||
_suggestions.update();
|
||||
}
|
||||
|
||||
clear() {
|
||||
this._textarea.value = "";
|
||||
}
|
||||
|
||||
get template() {
|
||||
return document.getElementById("tmpl-submit-panel");
|
||||
}
|
||||
}
|
||||
|
||||
// This WebComponent provides the abuse report
|
||||
class AbuseReport extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this._report = null;
|
||||
defineElementSelectorsGetters(this, {
|
||||
_form: "form",
|
||||
_textarea: "textarea",
|
||||
_radioCheckedReason: "[type=radio]:checked",
|
||||
_reasonsPanel: "abuse-report-reasons-panel",
|
||||
_submitPanel: "abuse-report-submit-panel",
|
||||
_reasonsPanelButtons: ".abuse-report-reasons-buttons",
|
||||
_submitPanelButtons: ".abuse-report-submit-buttons",
|
||||
_iconClose: ".abuse-report-close-icon",
|
||||
_btnNext: "button.abuse-report-next",
|
||||
_btnCancel: "button.abuse-report-cancel",
|
||||
_btnGoBack: "button.abuse-report-goback",
|
||||
_btnSubmit: "button.abuse-report-submit",
|
||||
_addonIconElement: ".abuse-report-header img.addon-icon",
|
||||
_addonNameElement: ".abuse-report-header .addon-name",
|
||||
_linkAddonAuthor: ".abuse-report-header .addon-author-box a.author",
|
||||
});
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.render();
|
||||
|
||||
this.addEventListener("click", this);
|
||||
|
||||
// Start listening to keydown events (to close the modal
|
||||
// when Escape has been pressed and to handling the keyboard
|
||||
// navigation).
|
||||
document.addEventListener("keydown", this);
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
this.textContent = "";
|
||||
this.removeEventListener("click", this);
|
||||
document.removeEventListener("keydown", this);
|
||||
}
|
||||
|
||||
handleEvent(evt) {
|
||||
if (!this.isConnected || !this.addon) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (evt.type) {
|
||||
case "keydown":
|
||||
if (evt.key === "Escape") {
|
||||
// Prevent Esc to close the panel if the textarea is
|
||||
// empty.
|
||||
if (this.message && !this._submitPanel.hidden) {
|
||||
return;
|
||||
}
|
||||
this.cancel();
|
||||
}
|
||||
this.handleKeyboardNavigation(evt);
|
||||
break;
|
||||
case "click":
|
||||
if (evt.target === this._iconClose || evt.target === this._btnCancel) {
|
||||
// NOTE: clear the focus on the clicked element to ensure that
|
||||
// -moz-focusring pseudo class is not still set on the element
|
||||
// when the panel is going to be shown again (See Bug 1560949).
|
||||
evt.target.blur();
|
||||
this.cancel();
|
||||
}
|
||||
if (evt.target === this._btnNext) {
|
||||
this.switchToSubmitMode();
|
||||
}
|
||||
if (evt.target === this._btnGoBack) {
|
||||
this.switchToListMode();
|
||||
}
|
||||
if (evt.target === this._btnSubmit) {
|
||||
this.submit();
|
||||
}
|
||||
if (evt.target.localName === "a") {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
const url = evt.target.getAttribute("href");
|
||||
// Ignore if url is empty.
|
||||
if (url) {
|
||||
window.windowRoot.ownerGlobal.openWebLinkIn(url, "tab", {
|
||||
relatedToCurrent: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
handleKeyboardNavigation(evt) {
|
||||
if (
|
||||
evt.keyCode !== evt.DOM_VK_TAB ||
|
||||
evt.altKey ||
|
||||
evt.controlKey ||
|
||||
evt.metaKey
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fm = Services.focus;
|
||||
const backward = evt.shiftKey;
|
||||
|
||||
const isFirstFocusableElement = el => {
|
||||
// Also consider the document body as a valid first focusable element.
|
||||
if (el === document.body) {
|
||||
return true;
|
||||
}
|
||||
// XXXrpl unfortunately there is no way to get the first focusable element
|
||||
// without asking the focus manager to move focus to it (similar strategy
|
||||
// is also being used in about:prefereces subdialog.js).
|
||||
const rv = el == fm.moveFocus(window, null, fm.MOVEFOCUS_FIRST, 0);
|
||||
fm.setFocus(el, 0);
|
||||
return rv;
|
||||
};
|
||||
|
||||
// If the focus is exiting the panel while navigating
|
||||
// backward, focus the previous element sibling on the
|
||||
// Firefox UI.
|
||||
if (backward && isFirstFocusableElement(evt.target)) {
|
||||
evt.preventDefault();
|
||||
evt.stopImmediatePropagation();
|
||||
const chromeWin = window.windowRoot.ownerGlobal;
|
||||
Services.focus.moveFocus(
|
||||
chromeWin,
|
||||
null,
|
||||
Services.MOVEFOCUS_BACKWARD,
|
||||
Services.focus.FLAG_BYKEY
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
this.textContent = "";
|
||||
this.appendChild(document.importNode(this.template.content, true));
|
||||
}
|
||||
|
||||
async update() {
|
||||
if (!this.addon) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
addonId,
|
||||
_addonIconElement,
|
||||
_addonNameElement,
|
||||
_linkAddonAuthor,
|
||||
_reasonsPanel,
|
||||
_submitPanel,
|
||||
} = this;
|
||||
|
||||
// Ensure that the first step of the abuse submission is the one
|
||||
// currently visible.
|
||||
this.switchToListMode();
|
||||
|
||||
// Cancel the abuse report if the addon is not an extension or theme.
|
||||
if (!["extension", "theme"].includes(this.addonType)) {
|
||||
this.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
_addonNameElement.textContent = this.addonName;
|
||||
|
||||
_linkAddonAuthor.href = this.authorURL || this.homepageURL;
|
||||
_linkAddonAuthor.textContent = this.authorName;
|
||||
document.l10n.setAttributes(
|
||||
_linkAddonAuthor.parentNode,
|
||||
"abuse-report-addon-authored-by",
|
||||
{ "author-name": this.authorName }
|
||||
);
|
||||
|
||||
_addonIconElement.setAttribute("src", this.iconURL);
|
||||
|
||||
_reasonsPanel.addonType = this.addonType;
|
||||
_reasonsPanel.update();
|
||||
|
||||
_submitPanel.addonType = this.addonType;
|
||||
_submitPanel.reason = this.reason;
|
||||
_submitPanel.extensionSupportURL = this.supportURL;
|
||||
_submitPanel.update();
|
||||
|
||||
this.focus();
|
||||
dispatchCustomEvent(this, "abuse-report:updated", {
|
||||
addonId,
|
||||
panel: "reasons",
|
||||
});
|
||||
}
|
||||
|
||||
setAbuseReport(abuseReport) {
|
||||
this._report = abuseReport;
|
||||
// Clear the textarea from any previously entered content.
|
||||
this._submitPanel.clear();
|
||||
|
||||
if (abuseReport) {
|
||||
this.update();
|
||||
this.hidden = false;
|
||||
} else {
|
||||
this.hidden = true;
|
||||
}
|
||||
}
|
||||
|
||||
focus() {
|
||||
if (!this.isConnected || !this.addon) {
|
||||
return;
|
||||
}
|
||||
if (this._reasonsPanel.hidden) {
|
||||
const { _textarea } = this;
|
||||
_textarea.focus();
|
||||
_textarea.select();
|
||||
} else {
|
||||
const { _radioCheckedReason } = this;
|
||||
if (_radioCheckedReason) {
|
||||
_radioCheckedReason.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cancel() {
|
||||
if (!this.isConnected || !this.addon) {
|
||||
return;
|
||||
}
|
||||
this._report = null;
|
||||
dispatchCustomEvent(this, "abuse-report:cancel");
|
||||
}
|
||||
|
||||
submit() {
|
||||
if (!this.isConnected || !this.addon) {
|
||||
return;
|
||||
}
|
||||
dispatchCustomEvent(this, "abuse-report:submit", {
|
||||
addonId: this.addonId,
|
||||
reason: this.reason,
|
||||
message: this.message,
|
||||
report: this._report,
|
||||
});
|
||||
}
|
||||
|
||||
switchToSubmitMode() {
|
||||
if (!this.isConnected || !this.addon) {
|
||||
return;
|
||||
}
|
||||
this._submitPanel.reason = this.reason;
|
||||
this._submitPanel.update();
|
||||
this._reasonsPanel.hidden = true;
|
||||
this._reasonsPanelButtons.hidden = true;
|
||||
this._submitPanel.hidden = false;
|
||||
this._submitPanelButtons.hidden = false;
|
||||
// Adjust the focused element when switching to the submit panel.
|
||||
this.focus();
|
||||
dispatchCustomEvent(this, "abuse-report:updated", {
|
||||
addonId: this.addonId,
|
||||
panel: "submit",
|
||||
});
|
||||
}
|
||||
|
||||
switchToListMode() {
|
||||
if (!this.isConnected || !this.addon) {
|
||||
return;
|
||||
}
|
||||
this._submitPanel.hidden = true;
|
||||
this._submitPanelButtons.hidden = true;
|
||||
this._reasonsPanel.hidden = false;
|
||||
this._reasonsPanelButtons.hidden = false;
|
||||
// Adjust the focused element when switching back to the list of reasons.
|
||||
this.focus();
|
||||
dispatchCustomEvent(this, "abuse-report:updated", {
|
||||
addonId: this.addonId,
|
||||
panel: "reasons",
|
||||
});
|
||||
}
|
||||
|
||||
get addon() {
|
||||
return this._report && this._report.addon;
|
||||
}
|
||||
|
||||
get addonId() {
|
||||
return this.addon && this.addon.id;
|
||||
}
|
||||
|
||||
get addonName() {
|
||||
return this.addon && this.addon.name;
|
||||
}
|
||||
|
||||
get addonType() {
|
||||
return this.addon && this.addon.type;
|
||||
}
|
||||
|
||||
get addonCreator() {
|
||||
return this.addon && this.addon.creator;
|
||||
}
|
||||
|
||||
get homepageURL() {
|
||||
const { addon } = this;
|
||||
return (addon && addon.homepageURL) || this.authorURL || "";
|
||||
}
|
||||
|
||||
get authorName() {
|
||||
// The author name may be missing on some of the test extensions
|
||||
// (or for temporarily installed add-ons).
|
||||
return (this.addonCreator && this.addonCreator.name) || "";
|
||||
}
|
||||
|
||||
get authorURL() {
|
||||
return (this.addonCreator && this.addonCreator.url) || "";
|
||||
}
|
||||
|
||||
get iconURL() {
|
||||
return this.addon && this.addon.iconURL;
|
||||
}
|
||||
|
||||
get supportURL() {
|
||||
return (this.addon && this.addon.supportURL) || this.homepageURL || "";
|
||||
}
|
||||
|
||||
get message() {
|
||||
return this._form.elements.message.value;
|
||||
}
|
||||
|
||||
get reason() {
|
||||
return this._form.elements.reason.value;
|
||||
}
|
||||
|
||||
get template() {
|
||||
return document.getElementById("tmpl-abuse-report");
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("abuse-report-reason-listitem", AbuseReasonListItem, {
|
||||
extends: "li",
|
||||
});
|
||||
customElements.define(
|
||||
"abuse-report-reason-suggestions",
|
||||
AbuseReasonSuggestions
|
||||
);
|
||||
customElements.define("abuse-report-reasons-panel", AbuseReasonsPanel);
|
||||
customElements.define("abuse-report-submit-panel", AbuseSubmitPanel);
|
||||
customElements.define("addon-abuse-report", AbuseReport);
|
||||
|
||||
window.addEventListener(
|
||||
"load",
|
||||
() => {
|
||||
document.body.prepend(document.createElement("addon-abuse-report"));
|
||||
},
|
||||
{ once: true }
|
||||
);
|
@ -1,252 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
/* eslint max-len: ["error", 80] */
|
||||
|
||||
/* exported openAbuseReport */
|
||||
|
||||
/**
|
||||
* This script is part of the HTML about:addons page and it provides some
|
||||
* helpers used for the Abuse Reporting submission (and related message bars).
|
||||
*/
|
||||
|
||||
// Message Bars definitions.
|
||||
const ABUSE_REPORT_MESSAGE_BARS = {
|
||||
// Idle message-bar (used while the submission is still ongoing).
|
||||
submitting: { id: "submitting", actions: ["cancel"] },
|
||||
// Submitted report message-bar.
|
||||
submitted: {
|
||||
id: "submitted",
|
||||
actionAddonTypeSuffix: true,
|
||||
actions: ["remove", "keep"],
|
||||
dismissable: true,
|
||||
},
|
||||
// Submitted report message-bar (with no remove actions).
|
||||
"submitted-no-remove-action": {
|
||||
id: "submitted-noremove",
|
||||
dismissable: true,
|
||||
},
|
||||
// Submitted report and remove addon message-bar.
|
||||
"submitted-and-removed": {
|
||||
id: "removed",
|
||||
addonTypeSuffix: true,
|
||||
dismissable: true,
|
||||
},
|
||||
// The "aborted report" message bar is rendered as a generic informative one,
|
||||
// because aborting a report is triggered by a user choice.
|
||||
ERROR_ABORTED_SUBMIT: {
|
||||
id: "aborted",
|
||||
type: "generic",
|
||||
dismissable: true,
|
||||
},
|
||||
// Errors message bars.
|
||||
ERROR_ADDON_NOTFOUND: {
|
||||
id: "error",
|
||||
type: "error",
|
||||
dismissable: true,
|
||||
},
|
||||
ERROR_CLIENT: {
|
||||
id: "error",
|
||||
type: "error",
|
||||
dismissable: true,
|
||||
},
|
||||
ERROR_NETWORK: {
|
||||
id: "error",
|
||||
actions: ["retry", "cancel"],
|
||||
type: "error",
|
||||
},
|
||||
ERROR_RECENT_SUBMIT: {
|
||||
id: "error-recent-submit",
|
||||
actions: ["retry", "cancel"],
|
||||
type: "error",
|
||||
},
|
||||
ERROR_SERVER: {
|
||||
id: "error",
|
||||
actions: ["retry", "cancel"],
|
||||
type: "error",
|
||||
},
|
||||
ERROR_UNKNOWN: {
|
||||
id: "error",
|
||||
actions: ["retry", "cancel"],
|
||||
type: "error",
|
||||
},
|
||||
};
|
||||
|
||||
function openAbuseReport({ addonId, reportEntryPoint }) {
|
||||
document.dispatchEvent(
|
||||
new CustomEvent("abuse-report:new", {
|
||||
detail: { addonId, reportEntryPoint },
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// Helper function used to create abuse report message bars in the
|
||||
// HTML about:addons page.
|
||||
function createReportMessageBar(
|
||||
definitionId,
|
||||
{ addonId, addonName, addonType },
|
||||
{ onclose, onaction } = {}
|
||||
) {
|
||||
const getMessageL10n = id => `abuse-report-messagebar-${id}`;
|
||||
const getActionL10n = action => getMessageL10n(`action-${action}`);
|
||||
|
||||
const barInfo = ABUSE_REPORT_MESSAGE_BARS[definitionId];
|
||||
if (!barInfo) {
|
||||
throw new Error(`message-bar definition not found: ${definitionId}`);
|
||||
}
|
||||
const { id, dismissable, actions, type } = barInfo;
|
||||
const messageEl = document.createElement("span");
|
||||
|
||||
// The message element includes an addon-name span (also filled by
|
||||
// Fluent), which can be used to apply custom styles to the addon name
|
||||
// included in the message bar (if needed).
|
||||
const addonNameEl = document.createElement("span");
|
||||
addonNameEl.setAttribute("data-l10n-name", "addon-name");
|
||||
messageEl.append(addonNameEl);
|
||||
|
||||
document.l10n.setAttributes(
|
||||
messageEl,
|
||||
getMessageL10n(barInfo.addonTypeSuffix ? `${id}-${addonType}` : id),
|
||||
{ "addon-name": addonName || addonId }
|
||||
);
|
||||
|
||||
const barActions = actions
|
||||
? actions.map(action => {
|
||||
// Some of the message bars require a different per addonType
|
||||
// Fluent id for their actions.
|
||||
const actionId = barInfo.actionAddonTypeSuffix
|
||||
? `${action}-${addonType}`
|
||||
: action;
|
||||
const buttonEl = document.createElement("button");
|
||||
buttonEl.addEventListener("click", () => onaction && onaction(action));
|
||||
document.l10n.setAttributes(buttonEl, getActionL10n(actionId));
|
||||
return buttonEl;
|
||||
})
|
||||
: [];
|
||||
|
||||
const messagebar = document.createElement("message-bar");
|
||||
messagebar.setAttribute("type", type || "generic");
|
||||
if (dismissable) {
|
||||
messagebar.setAttribute("dismissable", "");
|
||||
}
|
||||
messagebar.append(messageEl, ...barActions);
|
||||
messagebar.addEventListener("message-bar:close", onclose, { once: true });
|
||||
|
||||
document.getElementById("abuse-reports-messages").append(messagebar);
|
||||
|
||||
document.dispatchEvent(
|
||||
new CustomEvent("abuse-report:new-message-bar", {
|
||||
detail: { definitionId, messagebar },
|
||||
})
|
||||
);
|
||||
return messagebar;
|
||||
}
|
||||
|
||||
async function submitReport({ report, reason, message }) {
|
||||
const { addon } = report;
|
||||
const addonId = addon.id;
|
||||
const addonName = addon.name;
|
||||
const addonType = addon.type;
|
||||
|
||||
// Create a message bar while we are still submitting the report.
|
||||
const mbSubmitting = createReportMessageBar(
|
||||
"submitting",
|
||||
{ addonId, addonName, addonType },
|
||||
{
|
||||
onaction: action => {
|
||||
if (action === "cancel") {
|
||||
report.abort();
|
||||
mbSubmitting.remove();
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
try {
|
||||
await report.submit({ reason, message });
|
||||
mbSubmitting.remove();
|
||||
|
||||
// Create a submitted message bar when the submission has been
|
||||
// successful.
|
||||
let barId;
|
||||
if (!(addon.permissions & AddonManager.PERM_CAN_UNINSTALL)) {
|
||||
// Do not offer remove action if the addon can't be uninstalled.
|
||||
barId = "submitted-no-remove-action";
|
||||
} else if (report.reportEntryPoint === "uninstall") {
|
||||
// With reportEntryPoint "uninstall" a specific message bar
|
||||
// is going to be used.
|
||||
barId = "submitted-and-removed";
|
||||
} else {
|
||||
// All the other reportEntryPoint ("menu" and "toolbar_context_menu")
|
||||
// use the same kind of message bar.
|
||||
barId = "submitted";
|
||||
}
|
||||
|
||||
const mbInfo = createReportMessageBar(
|
||||
barId,
|
||||
{
|
||||
addonId,
|
||||
addonName,
|
||||
addonType,
|
||||
},
|
||||
{
|
||||
onaction: action => {
|
||||
mbInfo.remove();
|
||||
// action "keep" doesn't require any further action,
|
||||
// just handle "remove".
|
||||
if (action === "remove") {
|
||||
report.addon.uninstall(true);
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
} catch (err) {
|
||||
// Log the complete error in the console.
|
||||
console.error("Error submitting abuse report for", addonId, err);
|
||||
mbSubmitting.remove();
|
||||
// The report has a submission error, create a error message bar which
|
||||
// may optionally allow the user to retry to submit the same report.
|
||||
const barId =
|
||||
err.errorType in ABUSE_REPORT_MESSAGE_BARS
|
||||
? err.errorType
|
||||
: "ERROR_UNKNOWN";
|
||||
|
||||
const mbError = createReportMessageBar(
|
||||
barId,
|
||||
{
|
||||
addonId,
|
||||
addonName,
|
||||
addonType,
|
||||
},
|
||||
{
|
||||
onaction: action => {
|
||||
mbError.remove();
|
||||
switch (action) {
|
||||
case "retry":
|
||||
submitReport({ report, reason, message });
|
||||
break;
|
||||
case "cancel":
|
||||
report.abort();
|
||||
break;
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("abuse-report:submit", ({ detail }) => {
|
||||
submitReport(detail);
|
||||
});
|
||||
|
||||
document.addEventListener("abuse-report:create-error", ({ detail }) => {
|
||||
const { addonId, addon, errorType } = detail;
|
||||
const barId =
|
||||
errorType in ABUSE_REPORT_MESSAGE_BARS ? errorType : "ERROR_UNKNOWN";
|
||||
createReportMessageBar(barId, {
|
||||
addonId,
|
||||
addonName: addon && addon.name,
|
||||
addonType: addon && addon.type,
|
||||
});
|
||||
});
|
@ -36,10 +36,6 @@ xhtml|link {
|
||||
-moz-binding: url("chrome://mozapps/content/extensions/extensions.xml#creator-link");
|
||||
}
|
||||
|
||||
.meta-rating {
|
||||
-moz-binding: url("chrome://mozapps/content/extensions/extensions.xml#rating");
|
||||
}
|
||||
|
||||
.download-progress, .download-progress[mode="undetermined"] {
|
||||
-moz-binding: url("chrome://mozapps/content/extensions/extensions.xml#download-progress");
|
||||
}
|
||||
@ -71,11 +67,6 @@ row[unsupported="true"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#show-disabled-unsigned-extensions .button-text {
|
||||
margin-inline-start: 3px !important;
|
||||
margin-inline-end: 2px !important;
|
||||
}
|
||||
|
||||
#header-searching:not([active]) {
|
||||
visibility: hidden;
|
||||
}
|
||||
@ -186,12 +177,6 @@ row[unsupported="true"] {
|
||||
max-width: 580px;
|
||||
}
|
||||
|
||||
/* Make sure we're not animating hidden images. See bug 623739. */
|
||||
#view-port:not([selectedIndex="0"]) #discover-view .loading,
|
||||
#discover-view:not([selectedIndex="0"]) .loading {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Elements in unselected richlistitems cannot be focused */
|
||||
richlistitem:not([selected]) * {
|
||||
-moz-user-focus: ignore;
|
||||
@ -201,10 +186,6 @@ richlistitem:not([selected]) * {
|
||||
width: 22em;
|
||||
}
|
||||
|
||||
.discover-button[disabled="true"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.view-pane:not(#legacy-view) .addon-control.replacement {
|
||||
display: none;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -18,110 +18,6 @@
|
||||
xmlns:html="http://www.w3.org/1999/xhtml">
|
||||
|
||||
|
||||
<!-- Rating - displays current/average rating, allows setting user rating -->
|
||||
<binding id="rating">
|
||||
<content>
|
||||
<xul:image class="star"
|
||||
onmouseover="document.getBindingParent(this)._hover(1);"
|
||||
onclick="document.getBindingParent(this).userRating = 1;"/>
|
||||
<xul:image class="star"
|
||||
onmouseover="document.getBindingParent(this)._hover(2);"
|
||||
onclick="document.getBindingParent(this).userRating = 2;"/>
|
||||
<xul:image class="star"
|
||||
onmouseover="document.getBindingParent(this)._hover(3);"
|
||||
onclick="document.getBindingParent(this).userRating = 3;"/>
|
||||
<xul:image class="star"
|
||||
onmouseover="document.getBindingParent(this)._hover(4);"
|
||||
onclick="document.getBindingParent(this).userRating = 4;"/>
|
||||
<xul:image class="star"
|
||||
onmouseover="document.getBindingParent(this)._hover(5);"
|
||||
onclick="document.getBindingParent(this).userRating = 5;"/>
|
||||
</content>
|
||||
|
||||
<implementation>
|
||||
<constructor><![CDATA[
|
||||
this._updateStars();
|
||||
]]></constructor>
|
||||
|
||||
<property name="stars" readonly="true">
|
||||
<getter><![CDATA[
|
||||
return document.getAnonymousNodes(this);
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<property name="averageRating">
|
||||
<getter><![CDATA[
|
||||
if (this.hasAttribute("averagerating"))
|
||||
return this.getAttribute("averagerating");
|
||||
return -1;
|
||||
]]></getter>
|
||||
<setter><![CDATA[
|
||||
this.setAttribute("averagerating", val);
|
||||
if (this.showRating == "average")
|
||||
this._updateStars();
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<property name="userRating">
|
||||
<getter><![CDATA[
|
||||
if (this.hasAttribute("userrating"))
|
||||
return this.getAttribute("userrating");
|
||||
return -1;
|
||||
]]></getter>
|
||||
<setter><![CDATA[
|
||||
if (this.showRating != "user")
|
||||
return;
|
||||
this.setAttribute("userrating", val);
|
||||
if (this.showRating == "user")
|
||||
this._updateStars();
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<property name="showRating">
|
||||
<getter><![CDATA[
|
||||
if (this.hasAttribute("showrating"))
|
||||
return this.getAttribute("showrating");
|
||||
return "average";
|
||||
]]></getter>
|
||||
<setter><![CDATA[
|
||||
if (val != "average" || val != "user")
|
||||
throw Components.Exception("Invalid value", Cr.NS_ERROR_ILLEGAL_VALUE);
|
||||
this.setAttribute("showrating", val);
|
||||
this._updateStars();
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<method name="_updateStars">
|
||||
<body><![CDATA[
|
||||
var stars = this.stars;
|
||||
var rating = this[this.showRating + "Rating"];
|
||||
// average ratings can be non-whole numbers, round them so they
|
||||
// match to their closest star
|
||||
rating = Math.round(rating);
|
||||
for (let i = 0; i < stars.length; i++)
|
||||
stars[i].setAttribute("on", rating > i);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="_hover">
|
||||
<parameter name="aScore"/>
|
||||
<body><![CDATA[
|
||||
if (this.showRating != "user")
|
||||
return;
|
||||
var stars = this.stars;
|
||||
for (let i = 0; i < stars.length; i++)
|
||||
stars[i].setAttribute("on", i <= (aScore - 1));
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
<handler event="mouseout">
|
||||
this._updateStars();
|
||||
</handler>
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
<!-- Download progress - shows graphical progress of download and any
|
||||
related status message. -->
|
||||
@ -903,8 +799,7 @@
|
||||
this.setAttribute("previewURL", previewURL ? previewURL : "");
|
||||
this.setAttribute("hasPreview", previewURL ? "true" : "fase");
|
||||
|
||||
let legacyWarning = legacyExtensionsEnabled && !this.mAddon.install &&
|
||||
isLegacyExtension(this.mAddon);
|
||||
let legacyWarning = isLegacyExtension(this.mAddon);
|
||||
this.setAttribute("legacy", legacyWarning);
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "legacy").href = SUPPORT_URL + "webextensions";
|
||||
|
||||
@ -1027,14 +922,6 @@
|
||||
this._errorLink.href = url;
|
||||
this._errorLink.hidden = false;
|
||||
});
|
||||
} else if (!isUpgrade && isDisabledUnsigned(this.mAddon)) {
|
||||
this.setAttribute("notification", "error");
|
||||
this._error.textContent = gStrings.ext.formatStringFromName(
|
||||
"notification.unsignedAndDisabled", [this.mAddon.name, gStrings.brandShortName]
|
||||
);
|
||||
this._errorLink.value = gStrings.ext.GetStringFromName("notification.unsigned.link");
|
||||
this._errorLink.href = SUPPORT_URL + "unsigned-addons";
|
||||
this._errorLink.hidden = false;
|
||||
} else if ((!isUpgrade && !this.mAddon.isCompatible) && (AddonManager.checkCompatibility
|
||||
|| (this.mAddon.blocklistState != Ci.nsIBlocklistService.STATE_SOFTBLOCKED))) {
|
||||
this.setAttribute("notification", "warning");
|
||||
@ -1235,11 +1122,6 @@
|
||||
this.mManualUpdate.releaseNotesURI :
|
||||
this.mAddon.releaseNotesURI;
|
||||
this._fetchReleaseNotes(uri);
|
||||
|
||||
// Dispatch an event so extensions.js can record telemetry.
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent("RelNotesShow", true, true);
|
||||
this.dispatchEvent(event);
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
@ -1267,11 +1149,6 @@
|
||||
this.setAttribute("pending", "uninstall");
|
||||
});
|
||||
}
|
||||
|
||||
// Dispatch an event so extensions.js can track telemetry.
|
||||
var event = document.createEvent("Events");
|
||||
event.initEvent("Uninstall", true, true);
|
||||
this.dispatchEvent(event);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
@ -1526,11 +1403,6 @@
|
||||
else if (this.getAttribute("wasDisabled") != "true")
|
||||
this.mAddon.enable();
|
||||
|
||||
// Dispatch an event so extensions.js can record telemetry.
|
||||
var event = document.createEvent("Events");
|
||||
event.initEvent("Undo", true, true);
|
||||
this.dispatchEvent(event);
|
||||
|
||||
this.removeAttribute("pending");
|
||||
]]></body>
|
||||
</method>
|
||||
|
@ -33,7 +33,6 @@
|
||||
<script src="chrome://global/content/contentAreaUtils.js"/>
|
||||
<script src="chrome://mozapps/content/extensions/aboutaddonsCommon.js"/>
|
||||
<script src="chrome://mozapps/content/extensions/extensions.js"/>
|
||||
<script src="chrome://mozapps/content/extensions/abuse-report-frame.js"/>
|
||||
|
||||
<popupset>
|
||||
<!-- menu for an addon item -->
|
||||
@ -97,7 +96,6 @@
|
||||
<command id="cmd_focusSearch" oncommand=";"/>
|
||||
<command id="cmd_findAllUpdates"/>
|
||||
<command id="cmd_restartApp"/>
|
||||
<command id="cmd_goToDiscoverPane"/>
|
||||
<command id="cmd_goToRecentUpdates"/>
|
||||
<command id="cmd_goToAvailableUpdates"/>
|
||||
<command id="cmd_installFromFile"/>
|
||||
@ -141,11 +139,6 @@
|
||||
<vbox id="category-box">
|
||||
<!-- category list -->
|
||||
<richlistbox id="categories" flex="1">
|
||||
<richlistitem id="category-discover" value="addons://discover/"
|
||||
class="category"
|
||||
data-l10n-id="extensions-view-discopane"
|
||||
data-l10n-attrs="name"
|
||||
priority="1000"/>
|
||||
<richlistitem id="category-legacy" value="addons://legacy/"
|
||||
class="category" priority="20000"
|
||||
hidden="true"/>
|
||||
@ -186,36 +179,6 @@
|
||||
<vbox class="main-content" flex="1">
|
||||
<!-- view port -->
|
||||
<deck id="view-port" flex="1" selectedIndex="0">
|
||||
<!-- discover view -->
|
||||
<deck id="discover-view" flex="1" class="view-pane" selectedIndex="0">
|
||||
<vbox id="discover-loading" align="center" pack="stretch" flex="1" class="alert-container">
|
||||
<spacer class="alert-spacer-before"/>
|
||||
<hbox class="alert loading" align="center">
|
||||
<image/>
|
||||
<label data-l10n-id="loading-label"/>
|
||||
</hbox>
|
||||
<spacer class="alert-spacer-after"/>
|
||||
</vbox>
|
||||
<vbox id="discover-error" align="center" pack="stretch" flex="1" class="alert-container">
|
||||
<spacer class="alert-spacer-before"/>
|
||||
<hbox>
|
||||
<spacer class="discover-spacer-before"/>
|
||||
<vbox class="alert" align="center">
|
||||
<image class="discover-logo"/>
|
||||
<vbox flex="1" align="stretch">
|
||||
<label class="discover-title" data-l10n-id="discover-title"></label>
|
||||
<description class="discover-description" data-l10n-id="discover-description"></description>
|
||||
<description class="discover-footer" data-l10n-id="discover-footer"></description>
|
||||
</vbox>
|
||||
</vbox>
|
||||
<spacer class="discover-spacer-after"/>
|
||||
</hbox>
|
||||
<spacer class="alert-spacer-after"/>
|
||||
</vbox>
|
||||
|
||||
<browser id="discover-browser" type="content" flex="1"
|
||||
disablehistory="true"/>
|
||||
</deck>
|
||||
|
||||
<!-- container for views with the search/tools header -->
|
||||
<vbox id="headered-views" flex="1">
|
||||
@ -226,9 +189,6 @@
|
||||
data-l10n-id="show-all-extensions-button"
|
||||
command="cmd_showAllExtensions"/>
|
||||
<spacer flex="1"/>
|
||||
<button id="show-disabled-unsigned-extensions" hidden="true"
|
||||
class="warning" data-l10n-id="show-unsigned-extensions-button"
|
||||
command="cmd_showUnsignedExtensions"/>
|
||||
<label id="search-label" control="header-search"/>
|
||||
<textbox id="header-search" is="search-textbox" searchbutton="true"
|
||||
data-l10n-id="search-header"
|
||||
@ -265,9 +225,9 @@
|
||||
|
||||
<button id="header-utils-btn" type="menu" data-l10n-id="tools-menu">
|
||||
<menupopup id="utils-menu">
|
||||
<menuitem id="utils-updateNow"
|
||||
<!--menuitem id="utils-updateNow"
|
||||
data-l10n-id="extensions-updates-check-for-updates"
|
||||
command="cmd_findAllUpdates"/>
|
||||
command="cmd_findAllUpdates"/-->
|
||||
<menuitem id="utils-viewUpdates"
|
||||
data-l10n-id="extensions-updates-view-updates"
|
||||
command="cmd_goToRecentUpdates"/>
|
||||
@ -279,16 +239,16 @@
|
||||
data-l10n-id="debug-addons"
|
||||
command="cmd_debugAddons"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="utils-autoUpdateDefault"
|
||||
<!--menuitem id="utils-autoUpdateDefault"
|
||||
data-l10n-id="extensions-updates-update-addons-automatically"
|
||||
type="checkbox" autocheck="false"
|
||||
command="cmd_toggleAutoUpdateDefault"/>
|
||||
<menuitem id="utils-resetAddonUpdatesToAutomatic"
|
||||
command="cmd_toggleAutoUpdateDefault"/-->
|
||||
<!--menuitem id="utils-resetAddonUpdatesToAutomatic"
|
||||
data-l10n-id="extensions-updates-reset-updates-to-automatic"
|
||||
command="cmd_resetAddonAutoUpdate"/>
|
||||
<menuitem id="utils-resetAddonUpdatesToManual"
|
||||
command="cmd_resetAddonAutoUpdate"/-->
|
||||
<!--menuitem id="utils-resetAddonUpdatesToManual"
|
||||
data-l10n-id="extensions-updates-reset-updates-to-manual"
|
||||
command="cmd_resetAddonAutoUpdate"/>
|
||||
command="cmd_resetAddonAutoUpdate"/-->
|
||||
<menuseparator/>
|
||||
<menuitem id="manage-shortcuts"
|
||||
data-l10n-id="manage-extensions-shortcuts"
|
||||
@ -302,23 +262,6 @@
|
||||
<!-- list view -->
|
||||
<vbox id="list-view" flex="1" class="view-pane" align="stretch">
|
||||
<!-- info UI for add-ons that have been disabled for being unsigned -->
|
||||
<vbox id="disabled-unsigned-addons-info" class="alert-container" hidden="true">
|
||||
<label id="disabled-unsigned-addons-heading" data-l10n-id="disabled-unsigned-heading"/>
|
||||
<description data-l10n-id="disabled-unsigned-description">
|
||||
<label class="plain" id="find-alternative-addons" data-l10n-name="find-addons" is="text-link"/>
|
||||
</description>
|
||||
<hbox pack="start"><label id="signing-learn-more" data-l10n-id="disabled-unsigned-learn-more" is="text-link"></label></hbox>
|
||||
<description id="signing-dev-info" data-l10n-id="disabled-unsigned-devinfo">
|
||||
<label class="plain" id="signing-dev-manual-link" data-l10n-name="learn-more" is="text-link"/>
|
||||
</description>
|
||||
</vbox>
|
||||
<vbox id="legacy-extensions-notice" class="alert-container" hidden="true">
|
||||
<vbox class="alert">
|
||||
<description id="legacy-extensions-description">
|
||||
<label class="plain" id="legacy-extensions-learnmore-link" data-l10n-id="legacy-warning-show-legacy" is="text-link"/>
|
||||
</description>
|
||||
</vbox>
|
||||
</vbox>
|
||||
<vbox id="private-browsing-notice" class="alert-container" hidden="true" align="start">
|
||||
<hbox class="message-bar" align="start">
|
||||
<image class="message-bar-icon"/>
|
||||
@ -372,10 +315,6 @@
|
||||
<spacer class="alert-spacer-before"/>
|
||||
<vbox class="alert">
|
||||
<label data-l10n-id="list-empty-installed"/>
|
||||
<button class="discover-button"
|
||||
id="discover-button-install"
|
||||
data-l10n-id="list-empty-button"
|
||||
command="cmd_goToDiscoverPane"/>
|
||||
</vbox>
|
||||
<spacer class="alert-spacer-after"/>
|
||||
</vbox>
|
||||
@ -613,14 +552,6 @@
|
||||
<label class="detail-row-label" data-l10n-id="detail-repository-value"/>
|
||||
<label id="detail-repository" class="detail-row-value" is="text-link"/>
|
||||
</row>
|
||||
<row class="detail-row-complex" id="detail-rating-row">
|
||||
<label class="detail-row-label" data-l10n-id="detail-rating"/>
|
||||
<hbox>
|
||||
<label id="detail-rating" class="meta-value meta-rating"
|
||||
showrating="average"/>
|
||||
<label id="detail-reviews" is="text-link"/>
|
||||
</hbox>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
<hbox id="detail-controls">
|
||||
@ -721,6 +652,5 @@
|
||||
</deck>
|
||||
</vbox>
|
||||
</hbox>
|
||||
<addon-abuse-report-xulframe hidden="true"></addon-abuse-report-xulframe>
|
||||
</stack>
|
||||
</page>
|
||||
|
@ -1,37 +0,0 @@
|
||||
:host {
|
||||
--rating-star-size: 1em;
|
||||
--rating-star-spacing: 0.3ch;
|
||||
|
||||
display: inline-grid;
|
||||
grid-template-columns: repeat(5, var(--rating-star-size));
|
||||
grid-column-gap: var(--rating-star-spacing);
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
:host([hidden]) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.rating-star {
|
||||
display: inline-block;
|
||||
width: var(--rating-star-size);
|
||||
height: var(--rating-star-size);
|
||||
background-image: url("chrome://mozapps/skin/extensions/rating-star.svg#empty");
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100%;
|
||||
|
||||
fill: currentColor;
|
||||
-moz-context-properties: fill;
|
||||
}
|
||||
|
||||
.rating-star[fill="half"] {
|
||||
background-image: url("chrome://mozapps/skin/extensions/rating-star.svg#half");
|
||||
}
|
||||
.rating-star[fill="full"] {
|
||||
background-image: url("chrome://mozapps/skin/extensions/rating-star.svg#full");
|
||||
}
|
||||
|
||||
.rating-star[fill="half"]:dir(rtl) {
|
||||
transform: scaleX(-1);
|
||||
}
|
@ -13,10 +13,6 @@ const { AppConstants } = ChromeUtils.import(
|
||||
"resource://gre/modules/AppConstants.jsm"
|
||||
);
|
||||
|
||||
const PREF_SIGNATURES_REQUIRED = "xpinstall.signatures.required";
|
||||
const PREF_LANGPACK_SIGNATURES = "extensions.langpacks.signatures.required";
|
||||
const PREF_ALLOW_LEGACY = "extensions.legacy.enabled";
|
||||
|
||||
var AddonSettings = {};
|
||||
|
||||
// Make a non-changable property that can't be manipulated from other
|
||||
@ -30,35 +26,6 @@ function makeConstant(name, value) {
|
||||
});
|
||||
}
|
||||
|
||||
if (AppConstants.MOZ_REQUIRE_SIGNING && !Cu.isInAutomation) {
|
||||
makeConstant("REQUIRE_SIGNING", true);
|
||||
makeConstant("LANGPACKS_REQUIRE_SIGNING", true);
|
||||
} else {
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
AddonSettings,
|
||||
"REQUIRE_SIGNING",
|
||||
PREF_SIGNATURES_REQUIRED,
|
||||
false
|
||||
);
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
AddonSettings,
|
||||
"LANGPACKS_REQUIRE_SIGNING",
|
||||
PREF_LANGPACK_SIGNATURES,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
if (AppConstants.MOZ_ALLOW_LEGACY_EXTENSIONS || Cu.isInAutomation) {
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
AddonSettings,
|
||||
"ALLOW_LEGACY_EXTENSIONS",
|
||||
PREF_ALLOW_LEGACY,
|
||||
true
|
||||
);
|
||||
} else {
|
||||
makeConstant("ALLOW_LEGACY_EXTENSIONS", false);
|
||||
}
|
||||
|
||||
if (AppConstants.MOZ_DEV_EDITION) {
|
||||
makeConstant("DEFAULT_THEME_ID", "firefox-compact-dark@mozilla.org");
|
||||
} else {
|
||||
|
@ -31,11 +31,6 @@ const { EventEmitter } = ChromeUtils.import(
|
||||
);
|
||||
const { OS } = ChromeUtils.import("resource://gre/modules/osfile.jsm");
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"AMTelemetry",
|
||||
"resource://gre/modules/AddonManager.jsm"
|
||||
);
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"ExtensionTestCommon",
|
||||
@ -330,7 +325,6 @@ var AddonTestUtils = {
|
||||
addonsList: null,
|
||||
appInfo: null,
|
||||
addonStartup: null,
|
||||
collectedTelemetryEvents: [],
|
||||
testScope: null,
|
||||
testUnpacked: false,
|
||||
useRealCertChecks: false,
|
||||
@ -411,9 +405,6 @@ var AddonTestUtils = {
|
||||
// By default ignore bundled add-ons
|
||||
Services.prefs.setBoolPref("extensions.installDistroAddons", false);
|
||||
|
||||
// Ensure signature checks are enabled by default
|
||||
Services.prefs.setBoolPref("xpinstall.signatures.required", true);
|
||||
|
||||
// Write out an empty blocklist.xml file to the profile to ensure nothing
|
||||
// is blocklisted by default
|
||||
var blockFile = OS.Path.join(this.profileDir.path, "blocklist.xml");
|
||||
@ -1533,21 +1524,16 @@ var AddonTestUtils = {
|
||||
* @param {boolean} [ignoreIncompatible = false]
|
||||
* Optional parameter to ignore add-ons that are incompatible
|
||||
* with the application
|
||||
* @param {Object} [installTelemetryInfo = undefined]
|
||||
* Optional parameter to set the install telemetry info for the
|
||||
* installed addon
|
||||
* @returns {Promise}
|
||||
* Resolves when the install has completed.
|
||||
*/
|
||||
async promiseInstallFile(
|
||||
file,
|
||||
ignoreIncompatible = false,
|
||||
installTelemetryInfo
|
||||
ignoreIncompatible = false
|
||||
) {
|
||||
let install = await AddonManager.getInstallForFile(
|
||||
file,
|
||||
null,
|
||||
installTelemetryInfo
|
||||
null
|
||||
);
|
||||
if (!install) {
|
||||
throw new Error(`No AddonInstall created for ${file.path}`);
|
||||
@ -1782,36 +1768,6 @@ var AddonTestUtils = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Asserts that the expected installTelemetryInfo properties are available
|
||||
* on the AddonWrapper or AddonInstall objects.
|
||||
*
|
||||
* @param {AddonWrapper|AddonInstall} addonOrInstall
|
||||
* The addon or addonInstall object to check.
|
||||
* @param {Object} expectedInstallInfo
|
||||
* The expected installTelemetryInfo properties
|
||||
* (every property can be a primitive value or a regular expression).
|
||||
*/
|
||||
checkInstallInfo(addonOrInstall, expectedInstallInfo) {
|
||||
const installInfo = addonOrInstall.installTelemetryInfo;
|
||||
const { Assert } = this.testScope;
|
||||
|
||||
for (const key of Object.keys(expectedInstallInfo)) {
|
||||
const actual = installInfo[key];
|
||||
let expected = expectedInstallInfo[key];
|
||||
|
||||
// Assert the property value using a regular expression.
|
||||
if (expected && typeof expected.test == "function") {
|
||||
Assert.ok(
|
||||
expected.test(actual),
|
||||
`${key} value "${actual}" has the value expected: "${expected}"`
|
||||
);
|
||||
} else {
|
||||
Assert.deepEqual(actual, expected, `Got the expected value for ${key}`);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper to wait for a webextension to completely start
|
||||
*
|
||||
@ -1917,39 +1873,6 @@ var AddonTestUtils = {
|
||||
]);
|
||||
Services.prefs.setBoolPref(PREF_DISABLE_SECURITY, prevPrefVal);
|
||||
},
|
||||
|
||||
// AMTelemetry events helpers.
|
||||
|
||||
/**
|
||||
* Redefine AMTelemetry.recordEvent to collect the recorded telemetry events and
|
||||
* ensure that there are no unexamined events after the test file is exiting.
|
||||
*/
|
||||
hookAMTelemetryEvents() {
|
||||
let originalRecordEvent = AMTelemetry.recordEvent;
|
||||
AMTelemetry.recordEvent = event => {
|
||||
this.collectedTelemetryEvents.push(event);
|
||||
};
|
||||
this.testScope.registerCleanupFunction(() => {
|
||||
this.testScope.Assert.deepEqual(
|
||||
[],
|
||||
this.collectedTelemetryEvents,
|
||||
"No unexamined telemetry events after test is finished"
|
||||
);
|
||||
AMTelemetry.recordEvent = originalRecordEvent;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrive any AMTelemetry event collected and empty the array of the collected events.
|
||||
*
|
||||
* @returns {Array<Object>}
|
||||
* The array of the collected telemetry data.
|
||||
*/
|
||||
getAMTelemetryEvents() {
|
||||
let events = this.collectedTelemetryEvents;
|
||||
this.collectedTelemetryEvents = [];
|
||||
return events;
|
||||
},
|
||||
};
|
||||
|
||||
for (let [key, val] of Object.entries(AddonTestUtils)) {
|
||||
|
@ -56,10 +56,6 @@ const LOGGER_ID = "addons.update-checker";
|
||||
// (Requires AddonManager.jsm)
|
||||
var logger = Log.repository.getLogger(LOGGER_ID);
|
||||
|
||||
const updateTypeHistogram = Services.telemetry.getHistogramById(
|
||||
"EXTENSION_UPDATE_TYPE"
|
||||
);
|
||||
|
||||
/**
|
||||
* Sanitizes the update URL in an update item, as returned by
|
||||
* parseRDFManifest and parseJSONManifest. Ensures that:
|
||||
@ -275,8 +271,7 @@ function UpdateParser(aId, aUrl, aObserver) {
|
||||
|
||||
let requireBuiltIn = Services.prefs.getBoolPref(
|
||||
PREF_UPDATE_REQUIREBUILTINCERTS,
|
||||
!AppConstants.MOZ_REQUIRE_SIGNING &&
|
||||
!AppConstants.MOZ_APP_VERSION_DISPLAY.endsWith("esr")
|
||||
!AppConstants.MOZ_APP_VERSION_DISPLAY.endsWith("esr")
|
||||
);
|
||||
|
||||
logger.debug("Requesting " + aUrl);
|
||||
@ -316,8 +311,7 @@ UpdateParser.prototype = {
|
||||
|
||||
let requireBuiltIn = Services.prefs.getBoolPref(
|
||||
PREF_UPDATE_REQUIREBUILTINCERTS,
|
||||
!AppConstants.MOZ_REQUIRE_SIGNING &&
|
||||
!AppConstants.MOZ_APP_VERSION_DISPLAY.endsWith("esr")
|
||||
!AppConstants.MOZ_APP_VERSION_DISPLAY.endsWith("esr")
|
||||
);
|
||||
|
||||
try {
|
||||
@ -352,7 +346,6 @@ UpdateParser.prototype = {
|
||||
try {
|
||||
let json = JSON.parse(request.responseText);
|
||||
results = parseJSONManifest(this.id, request, json);
|
||||
updateTypeHistogram.add("JSON");
|
||||
} catch (e) {
|
||||
logger.warn("onUpdateCheckComplete failed to parse update manifest", e);
|
||||
this.notifyError(AddonManager.ERROR_PARSE_ERROR);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user