Bug 1384608 Show complete themes with legacy extensions
MozReview-Commit-ID: 6jiQZ8SQpzI
--- a/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.dtd
+++ b/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.dtd
@@ -253,13 +253,12 @@
being a link to an external site. -->
<!ENTITY disabledUnsigned.devInfo.start "Developers interested in getting their add-ons verified can continue by reading our ">
<!ENTITY disabledUnsigned.devInfo.linkToManual "manual">
<!ENTITY disabledUnsigned.devInfo.end ".">
<!ENTITY pluginDeprecation.description "Missing something? Some plugins are no longer supported by &brandShortName;.">
<!ENTITY pluginDeprecation.learnMore "Learn More.">
-<!ENTITY legacyWarning.description "Missing something? Some extensions are no longer supported by &brandShortName;.">
<!ENTITY legacyWarning.showLegacy "Show legacy extensions">
<!ENTITY legacyExtensions.title "Legacy Extensions">
<!ENTITY legacyExtensions.description "These extensions do not meet current &brandShortName; standards so they have been deactivated.">
<!ENTITY legacyExtensions.learnMore "Learn about the changes to add-ons">
--- a/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.properties
+++ b/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.properties
@@ -185,8 +185,13 @@ type.extension.name=Extensions
type.themes.name=Themes
type.locale.name=Languages
type.plugin.name=Plugins
type.dictionary.name=Dictionaries
type.service.name=Services
type.experiment.name=Experiments
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.
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -2788,17 +2788,17 @@ var gLegacyView = {
gEventManager.unregisterAddonListener(this, "ANY");
},
onUninstalled() {
this.refreshVisibility();
},
async show(type, request) {
- let addons = await AddonManager.getAddonsByTypes(["extension"]);
+ let addons = await AddonManager.getAddonsByTypes(["extension", "theme"]);
addons = addons.filter(a => !a.hidden &&
(isDisabledLegacy(a) || isDisabledUnsigned(a)));
while (this._listBox.itemCount > 0)
this._listBox.removeItemAt(0);
let elements = addons.map(a => createItem(a));
if (elements.length == 0) {
@@ -2826,17 +2826,17 @@ var gLegacyView = {
},
async refreshVisibility() {
if (legacyExtensionsEnabled) {
this._categoryItem.disabled = true;
return;
}
- let extensions = await AddonManager.getAddonsByTypes(["extension"]);
+ let extensions = await AddonManager.getAddonsByTypes(["extension", "theme"]);
let haveUnsigned = false;
let haveLegacy = false;
for (let extension of extensions) {
if (isDisabledUnsigned(extension)) {
haveUnsigned = true;
}
if (isLegacyExtension(extension)) {
@@ -2965,17 +2965,31 @@ var gListView = {
this.showEmptyNotice(elements.length == 0);
if (elements.length > 0) {
sortElements(elements, ["uiState", "name"], true);
for (let element of elements)
this._listBox.appendChild(element);
}
this.filterDisabledUnsigned(showOnlyDisabledUnsigned);
- document.getElementById("legacy-extensions-notice").hidden = !showLegacyInfo;
+ let legacyNotice = document.getElementById("legacy-extensions-notice");
+ if (showLegacyInfo) {
+ let el = document.getElementById("legacy-extensions-description");
+ if (el.childNodes[0].nodeName == "#text") {
+ el.removeChild(el.childNodes[0]);
+ }
+
+ let descriptionId = (aType == "theme") ?
+ "legacyThemeWarning.description" : "legacyWarning.description";
+ let text = gStrings.ext.formatStringFromName(descriptionId, [gStrings.brandShortName], 1) + " ";
+ el.insertBefore(document.createTextNode(text), el.childNodes[0]);
+ legacyNotice.hidden = false;
+ } else {
+ legacyNotice.hidden = true;
+ }
gEventManager.registerInstallListener(this);
gViewController.updateCommands();
gViewController.notifyViewChanged();
});
},
hide() {
--- a/toolkit/mozapps/extensions/content/extensions.xml
+++ b/toolkit/mozapps/extensions/content/extensions.xml
@@ -1298,16 +1298,17 @@
this.setAttribute("notification", "warning");
this._warning.textContent = gStrings.ext.formatStringFromName(
"notification.incompatible",
[this.mAddon.name, gStrings.brandShortName, gStrings.appVersion], 3
);
this._warningLink.hidden = true;
this._warningBtn.hidden = true;
} else if (!isUpgrade && this.mAddon.appDisabled &&
+ this.mAddon.type == "extension" &&
!this.mAddon.multiprocessCompatible &&
!Services.prefs.getBoolPref("extensions.allow-non-mpc-extensions", true)) {
this.setAttribute("notification", "error");
this._error.textContent = gStrings.ext.formatStringFromName(
"notification.nonMpcDisabled", [this.mAddon.name], 1
);
this._errorLink.value = gStrings.ext.GetStringFromName("notification.nonMpcDisabled.link");
this._errorLink.href = "https://wiki.mozilla.org/Add-ons/ShimsNightly";
@@ -1642,17 +1643,20 @@
<body><![CDATA[
gViewController.loadView("addons://detail/" +
encodeURIComponent(this.mAddon.id));
]]></body>
</method>
<method name="findReplacement">
<body><![CDATA[
- openURL(`https://addons.mozilla.org/find-replacement/?guid=${this.mAddon.id}`);
+ let url = (this.mAddon.type == "theme") ?
+ SUPPORT_URL + "complete-themes" :
+ `https://addons.mozilla.org/find-replacement/?guid=${this.mAddon.id}`;
+ openURL(url);
]]></body>
</method>
<method name="onIncludeUpdateChanged">
<body><![CDATA[
var event = document.createEvent("Events");
event.initEvent("IncludeUpdateChanged", true, true);
this.dispatchEvent(event);
--- a/toolkit/mozapps/extensions/content/extensions.xul
+++ b/toolkit/mozapps/extensions/content/extensions.xul
@@ -363,17 +363,17 @@
</description>
<hbox pack="start"><label class="text-link" id="signing-learn-more">&disabledUnsigned.learnMore;</label></hbox>
<description id="signing-dev-info">
&disabledUnsigned.devInfo.start;<label class="text-link plain" id="signing-dev-manual-link">&disabledUnsigned.devInfo.linkToManual;</label>&disabledUnsigned.devInfo.end;
</description>
</vbox>
<vbox id="legacy-extensions-notice" class="alert-container" hidden="true">
<vbox class="alert">
- <description>&legacyWarning.description;
+ <description id="legacy-extensions-description">
<label class="text-link plain" id="legacy-extensions-learnmore-link">&legacyWarning.showLegacy;</label>
</description>
</vbox>
</vbox>
<vbox id="plugindeprecation-notice" class="alert-container">
<vbox class="alert">
<description>&pluginDeprecation.description;  
<label class="text-link plain" id="plugindeprecation-learnmore-link">&pluginDeprecation.learnMore;</label>
--- a/toolkit/mozapps/extensions/test/browser/browser.ini
+++ b/toolkit/mozapps/extensions/test/browser/browser.ini
@@ -48,16 +48,17 @@ support-files =
skip-if = buildapp == 'mulet'
[browser_file_xpi_no_process_switch.js]
[browser_getmorethemes.js]
[browser_gmpProvider.js]
[browser_install.js]
[browser_installssl.js]
[browser_legacy.js]
[browser_legacy_pre57.js]
+[browser_legacy_themes.js]
[browser_newaddon.js]
[browser_non_mpc.js]
[browser_searching.js]
[browser_system_addons_are_e10s.js]
[browser_task_next_test.js]
[browser_update.js]
[browser_updatessl.js]
[browser_webapi.js]
--- a/toolkit/mozapps/extensions/test/browser/browser_legacy.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_legacy.js
@@ -127,17 +127,17 @@ add_task(async function() {
let catItem = mgrWin.gLegacyView._categoryItem;
is(catItem.disabled, false, "Legacy category is visible");
is(catItem.getAttribute("name"), get_string("type.legacy.name"),
"Category label with no unsigned extensions is correct");
// Follow the link to the legacy extensions page
let legacyLink = mgrWin.document.getElementById("legacy-extensions-learnmore-link");
- is_element_visible(legacyLink, "Link to leagcy extension is visible");
+ is_element_visible(legacyLink, "Link to legacy extension is visible");
let loadPromise = new Promise(resolve => wait_for_view_load(mgrWin, resolve, true));
legacyLink.click();
await loadPromise;
is(mgrWin.gViewController.currentViewId, "addons://legacy/",
"Legacy extensions link leads to the correct view");
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/browser/browser_legacy_themes.js
@@ -0,0 +1,79 @@
+
+add_task(async function() {
+ // The mochitest framework installs a bunch of legacy extensions.
+ // Fortunately, the extensions.legacy.exceptions preference exists to
+ // avoid treating some extensions as legacy for the purposes of the UI.
+ const IGNORE = [
+ "special-powers@mozilla.org",
+ "mochikit@mozilla.org",
+ "workerbootstrap-test@mozilla.org",
+ "worker-test@mozilla.org",
+ ];
+
+ let exceptions = Services.prefs.getCharPref("extensions.legacy.exceptions");
+ exceptions = [ exceptions, ...IGNORE ].join(",");
+
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["extensions.legacy.enabled", false],
+ ["extensions.legacy.exceptions", exceptions],
+ ],
+ });
+
+ const ID = "theme@tests.mozilla.org";
+
+ let provider = new MockProvider();
+ provider.createAddons([{
+ id: ID,
+ name: "Complete Theme",
+ type: "theme",
+ appDisabled: true,
+ }]);
+
+ // Open about:addons and go to the themes list
+ let mgrWin = await open_manager(null);
+ let catUtils = new CategoryUtilities(mgrWin);
+ await catUtils.openType("theme");
+
+ // Our complete theme should not be displayed
+ let list = mgrWin.document.getElementById("addon-list");
+ let item = list.children.find(item => item.mAddon.id == ID);
+ is(item, undefined, `Theme ${ID} should not be in the list of active themes`);
+
+ // The warning banner and the legacy category should both be visible
+ let banner = mgrWin.document.getElementById("legacy-extensions-notice");
+ is_element_visible(banner, "Warning about legacy themes should be visible");
+ is(mgrWin.gLegacyView._categoryItem.disabled, false, "Legacy category should be visible ");
+
+ // Follow the link to the legacy extensions page
+ let legacyLink = mgrWin.document.getElementById("legacy-extensions-learnmore-link");
+ is_element_visible(legacyLink, "Link to legacy extensions is visible");
+
+ let loadPromise = new Promise(resolve => wait_for_view_load(mgrWin, resolve, true));
+ legacyLink.click();
+ await loadPromise;
+
+ is(mgrWin.gViewController.currentViewId, "addons://legacy/",
+ "Legacy extensions link leads to the correct view");
+
+ list = mgrWin.document.getElementById("legacy-list");
+ is(list.children.length, 1, "Should have 1 item in the legacy list");
+ item = list.children[0];
+ is(item.mAddon.id, ID, "Complete theme should be in the list");
+
+ // Click the find a replacement button
+ let button = document.getAnonymousElementByAttribute(item, "anonid", "replacement-btn");
+ is_element_visible(button, "Find a replacement butotn is visible");
+
+ // In automation, app.support.baseURL points to a page on localhost.
+ // The actual page is 404 in the test but that doesn't matter here,
+ // just the fact that we load the right URL.
+ let url = Services.prefs.getStringPref("app.support.baseURL") + "complete-themes";
+ let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, url);
+ button.click();
+ let tab = await tabPromise;
+ ok(true, "Find a replacement button opened SUMO page");
+ await BrowserTestUtils.removeTab(tab);
+
+ await close_manager(mgrWin);
+});