Bug 1411060 - Don't show extension controlled message if add-on isn't installed r?bsilverberg draft
authorMark Striemer <mstriemer@mozilla.com>
Mon, 23 Oct 2017 22:45:38 -0500
changeset 685518 d67d67a8f985c027c434880cc388556a580d255b
parent 685190 86534d5daeef8066928eef910d6d5c60442b24b0
child 737179 e2c58d3cf55400b5c7ce90af6fd9453fb5851943
push id85965
push userbmo:mstriemer@mozilla.com
push dateTue, 24 Oct 2017 19:38:43 +0000
reviewersbsilverberg
bugs1411060
milestone57.0
Bug 1411060 - Don't show extension controlled message if add-on isn't installed r?bsilverberg MozReview-Commit-ID: Fxo4sKgEWPd
browser/components/preferences/in-content/main.js
browser/components/preferences/in-content/tests/browser_homepages_filter_aboutpreferences.js
--- a/browser/components/preferences/in-content/main.js
+++ b/browser/components/preferences/in-content/main.js
@@ -2682,30 +2682,36 @@ function getControllingExtensionId(setti
 }
 
 function getControllingExtensionEl(settingName) {
   return document.getElementById(extensionControlledContentIds[settingName]);
 }
 
 async function handleControllingExtension(prefName) {
   let controllingExtensionId = await getControllingExtensionId(prefName);
-
-  if (controllingExtensionId) {
-    showControllingExtension(prefName, controllingExtensionId);
+  let addon = controllingExtensionId
+    && await AddonManager.getAddonByID(controllingExtensionId);
+
+  // Sometimes the ExtensionSettingsStore gets in a bad state where it thinks
+  // an extension is controlling a setting but the extension has been uninstalled
+  // outside of the regular lifecycle. If the extension isn't currently installed
+  // then we should treat the setting as not being controlled.
+  // See https://bugzilla.mozilla.org/show_bug.cgi?id=1411046 for an example.
+  if (addon) {
+    showControllingExtension(prefName, addon);
   } else {
     hideControllingExtension(prefName);
   }
 
-  return !!controllingExtensionId;
+  return !!addon;
 }
 
-async function showControllingExtension(settingName, extensionId) {
+async function showControllingExtension(settingName, addon) {
+  // Tell the user what extension is controlling the setting.
   let extensionControlledContent = getControllingExtensionEl(settingName);
-  // Tell the user what extension is controlling the setting.
-  let addon = await AddonManager.getAddonByID(extensionId);
   const defaultIcon = "chrome://mozapps/skin/extensions/extensionGeneric.svg";
   let stringParts = document
     .getElementById("bundlePreferences")
     .getString(`extensionControlled.${settingName}`)
     .split("%S");
   let description = extensionControlledContent.querySelector("description");
 
   // Remove the old content from the description.
--- a/browser/components/preferences/in-content/tests/browser_homepages_filter_aboutpreferences.js
+++ b/browser/components/preferences/in-content/tests/browser_homepages_filter_aboutpreferences.js
@@ -1,8 +1,11 @@
+XPCOMUtils.defineLazyModuleGetter(this, "ExtensionSettingsStore",
+                                  "resource://gre/modules/ExtensionSettingsStore.jsm");
+
 add_task(async function testSetHomepageUseCurrent() {
   is(gBrowser.currentURI.spec, "about:blank", "Test starts with about:blank open");
   await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:home");
   await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
   let doc = gBrowser.contentDocument;
   is(gBrowser.currentURI.spec, "about:preferences#general",
      "#general should be in the URI for about:preferences");
   let oldHomepagePref = Services.prefs.getCharPref("browser.startup.homepage");
@@ -70,16 +73,76 @@ function waitForMessageChange(messageId,
 function waitForMessageHidden() {
   return waitForMessageChange(target => target.hidden);
 }
 
 function waitForMessageShown() {
   return waitForMessageChange(target => !target.hidden);
 }
 
+add_task(async function testExtensionControlledHomepageUninstalledAddon() {
+  async function checkHomepageEnabled() {
+    await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
+    let doc = gBrowser.contentDocument;
+    is(gBrowser.currentURI.spec, "about:preferences#general",
+      "#general should be in the URI for about:preferences");
+    let controlledContent = doc.getElementById("browserHomePageExtensionContent");
+
+    // The homepage is enabled.
+    let homepageInut = doc.getElementById("browserHomePage");
+    is(homepageInut.disabled, false, "The homepage input is enabled");
+    is(homepageInut.value, "", "The homepage input is empty");
+    is(controlledContent.hidden, true, "The extension controlled row is hidden");
+
+    await BrowserTestUtils.removeTab(gBrowser.selectedTab);
+  }
+
+  // Verify the setting isn't reported as controlled and the inputs are enabled.
+  is(ExtensionSettingsStore.getSetting("prefs", "homepage_override"), null,
+     "The homepage_override is not set");
+  await checkHomepageEnabled();
+
+  // Write out a bad store file.
+  let storeData = {
+    prefs: {
+      homepage_override: {
+        initialValue: "",
+        precedenceList: [{
+          id: "bad@mochi.test",
+          installDate: 1508802672,
+          value: "https://developer.mozilla.org",
+          enabled: true,
+        }],
+      },
+    },
+  };
+  let jsonFileName = "extension-settings.json";
+  let storePath = OS.Path.join(OS.Constants.Path.profileDir, jsonFileName);
+  await OS.File.writeAtomic(storePath, JSON.stringify(storeData));
+
+  // Reload the ExtensionSettingsStore so it will read the file on disk.
+  await ExtensionSettingsStore._reloadFile();
+
+  // Verify that the setting is reported as set, but the homepage is still enabled
+  // since there is no matching installed extension.
+  is(ExtensionSettingsStore.getSetting("prefs", "homepage_override").value,
+      "https://developer.mozilla.org",
+      "The homepage_override appears to be set");
+  await checkHomepageEnabled();
+
+  // Remove the bad store file that we used.
+  await OS.File.remove(storePath)
+
+  // Reload the ExtensionSettingsStore again so it clears the data we added.
+  await ExtensionSettingsStore._reloadFile();
+
+  is(ExtensionSettingsStore.getSetting("prefs", "homepage_override"), null,
+     "The ExtensionSettingsStore is left empty.");
+});
+
 add_task(async function testExtensionControlledHomepage() {
   await openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
   let doc = gBrowser.contentDocument;
   is(gBrowser.currentURI.spec, "about:preferences#general",
      "#general should be in the URI for about:preferences");
   let homepagePref = () => Services.prefs.getCharPref("browser.startup.homepage");
   let originalHomepagePref = homepagePref();
   let extensionHomepage = "https://developer.mozilla.org/";