Bug 1155521 - Migrate Pocket add-on and social provider users to the new Pocket button (part 2, migration). r=jaws, a=dolske
authorDrew Willcoxon <adw@mozilla.com>
Tue, 05 May 2015 17:23:59 -0700
changeset 260439 257c096c7673
parent 260438 6be4fccbdfa3
child 260440 2eeb61f35995
push id782
push userjdolske@mozilla.com
push date2015-05-09 00:18 +0000
treeherdermozilla-release@067c9c7a5e75 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws, dolske
bugs1155521
milestone38.0
Bug 1155521 - Migrate Pocket add-on and social provider users to the new Pocket button (part 2, migration). r=jaws, a=dolske
browser/base/content/browser.xul
browser/components/customizableui/CustomizableUI.jsm
browser/components/customizableui/CustomizableWidgets.jsm
browser/components/customizableui/test/browser_1042100_default_placements_update.js
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -725,19 +725,19 @@
            to the default placements of buttons in CustomizableUI.jsm, so the
            customization code doesn't get confused.
       -->
     <toolbar id="nav-bar"
              aria-label="&navbarCmd.label;"
              fullscreentoolbar="true" mode="icons" customizable="true"
              iconsize="small"
 #ifdef MOZ_DEV_EDITION
-             defaultset="urlbar-container,search-container,developer-button,bookmarks-menu-button,downloads-button,home-button,loop-button"
+             defaultset="urlbar-container,search-container,developer-button,bookmarks-menu-button,pocket-button,downloads-button,home-button,loop-button"
 #else
-             defaultset="urlbar-container,search-container,bookmarks-menu-button,downloads-button,home-button,loop-button"
+             defaultset="urlbar-container,search-container,bookmarks-menu-button,pocket-button,downloads-button,home-button,loop-button"
 #endif
              customizationtarget="nav-bar-customization-target"
              overflowable="true"
              overflowbutton="nav-bar-overflow-button"
              overflowtarget="widget-overflow-list"
              overflowpanel="widget-overflow"
              context="toolbar-context-menu">
 
--- a/browser/components/customizableui/CustomizableUI.jsm
+++ b/browser/components/customizableui/CustomizableUI.jsm
@@ -208,16 +208,25 @@ let CustomizableUIInternal = {
       "developer-button",
 #endif
       "bookmarks-menu-button",
       "downloads-button",
       "home-button",
       "loop-button",
     ];
 
+    // Insert the Pocket button after the bookmarks button if it's present.
+    for (let widgetDefinition of CustomizableWidgets) {
+      if (widgetDefinition.id == "pocket-button") {
+        let idx = navbarPlacements.indexOf("bookmarks-menu-button") + 1;
+        navbarPlacements.splice(idx, 0, widgetDefinition.id);
+        break;
+      }
+    }
+
     if (Services.prefs.getBoolPref(kPrefWebIDEInNavbar)) {
       navbarPlacements.push("webide-button");
     }
 
     this.registerArea(CustomizableUI.AREA_NAVBAR, {
       legacy: true,
       type: CustomizableUI.TYPE_TOOLBAR,
       overflowable: true,
@@ -287,17 +296,19 @@ let CustomizableUIInternal = {
 
   _defineBuiltInWidgets: function() {
     for (let widgetDefinition of CustomizableWidgets) {
       this.createBuiltinWidget(widgetDefinition);
     }
   },
 
   _introduceNewBuiltinWidgets: function() {
-    if (!gSavedState || gSavedState.currentVersion >= kVersion) {
+    // We should still enter even if gSavedState.currentVersion >= kVersion
+    // because the per-widget pref facility is independent of versioning.
+    if (!gSavedState) {
       return;
     }
 
     let currentVersion = gSavedState.currentVersion;
     for (let [id, widget] of gPalette) {
       if (widget.defaultArea) {
         let shouldAdd = false;
         let shouldSetPref = false;
@@ -2105,24 +2116,42 @@ let CustomizableUIInternal = {
     return widget.id;
   },
 
   createBuiltinWidget: function(aData) {
     // This should only ever be called on startup, before any windows are
     // opened - so we know there's no build areas to handle. Also, builtin
     // widgets are expected to be (mostly) static, so shouldn't affect the
     // current placement settings.
+
+    // This allows a widget to be both built-in by default but also able to be
+    // destroyed based on criteria that may not be available when the widget is
+    // created -- for example, because some other feature in the browser
+    // supersedes the widget.
+    let conditionalDestroyPromise = aData.conditionalDestroyPromise || null;
+    delete aData.conditionalDestroyPromise;
+
     let widget = this.normalizeWidget(aData, CustomizableUI.SOURCE_BUILTIN);
     if (!widget) {
       ERROR("Error creating builtin widget: " + aData.id);
       return;
     }
 
     LOG("Creating built-in widget with id: " + widget.id);
     gPalette.set(widget.id, widget);
+
+    if (conditionalDestroyPromise) {
+      conditionalDestroyPromise.then(shouldDestroy => {
+        if (shouldDestroy) {
+          this.destroyWidget(widget.id);
+        }
+      }, err => {
+        Cu.reportError(err);
+      });
+    }
   },
 
   // Returns true if the area will eventually lazily restore (but hasn't yet).
   isAreaLazy: function(aArea) {
     if (gPlacements.has(aArea)) {
       return false;
     }
     return gAreas.get(aArea).has("legacy");
--- a/browser/components/customizableui/CustomizableWidgets.jsm
+++ b/browser/components/customizableui/CustomizableWidgets.jsm
@@ -21,16 +21,20 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "Pocket",
   "resource:///modules/Pocket.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ShortcutUtils",
   "resource://gre/modules/ShortcutUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "CharsetMenu",
   "resource://gre/modules/CharsetMenu.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
   "resource://gre/modules/PrivateBrowsingUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
+  "resource://gre/modules/AddonManager.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "SocialService",
+  "resource://gre/modules/SocialService.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "CharsetBundle", function() {
   const kCharsetBundle = "chrome://global/locale/charsetMenu.properties";
   return Services.strings.createBundle(kCharsetBundle);
 });
 XPCOMUtils.defineLazyGetter(this, "BrandBundle", function() {
   const kBrandBundle = "chrome://branding/locale/brand.properties";
   return Services.strings.createBundle(kBrandBundle);
@@ -1074,26 +1078,54 @@ if (Services.prefs.getBoolPref("browser.
       Cu.reportError(ex);
     }
     isEnabledForLocale = enabledLocales.indexOf(browserLocale) != -1;
   }
 
   if (isEnabledForLocale) {
     let pocketButton = {
       id: "pocket-button",
+      defaultArea: CustomizableUI.AREA_NAVBAR,
+      introducedInVersion: "pref",
       type: "view",
       viewId: "PanelUI-pocketView",
       label: PocketBundle.GetStringFromName("pocket-button.label"),
       tooltiptext: PocketBundle.GetStringFromName("pocket-button.tooltiptext"),
       onViewShowing: Pocket.onPanelViewShowing,
       onViewHiding: Pocket.onPanelViewHiding,
+
+      // If the user has the "classic" Pocket add-on installed, use that instead
+      // and destroy the widget.
+      conditionalDestroyPromise: new Promise(resolve => {
+        AddonManager.getAddonByID("isreaditlater@ideashower.com", addon => {
+          resolve(addon && addon.isActive);
+        });
+      }),
     };
 
     CustomizableWidgets.push(pocketButton);
     CustomizableUI.addListener(pocketButton);
+
+    // Uninstall the Pocket social provider if it exists, but only if we haven't
+    // already uninstalled it in this manner.  That way the user can reinstall
+    // it if they prefer it without its being uninstalled every time they start
+    // the browser.
+    let origin = "https://getpocket.com";
+    SocialService.getProvider(origin, provider => {
+      if (provider) {
+        let pref = "social.backup.getpocket-com";
+        if (!Services.prefs.prefHasUserValue(pref)) {
+          let str = Cc["@mozilla.org/supports-string;1"].
+                    createInstance(Ci.nsISupportsString);
+          str.data = JSON.stringify(provider.manifest);
+          Services.prefs.setComplexValue(pref, Ci.nsISupportsString, str);
+          SocialService.uninstallProvider(origin, () => {});
+        }
+      }
+    });
   }
 }
 
 #ifdef E10S_TESTING_ONLY
 /**
   * The e10s button's purpose is to lower the barrier of entry
   * for our Nightly testers to use e10s windows. We'll be removing it
   * once remote tabs are enabled. This button should never ever make it
--- a/browser/components/customizableui/test/browser_1042100_default_placements_update.js
+++ b/browser/components/customizableui/test/browser_1042100_default_placements_update.js
@@ -66,16 +66,37 @@ function test() {
   // Then call the re-init routine so we re-add the builtin widgets
   CustomizableUIInternal._introduceNewBuiltinWidgets();
   is(gFuturePlacements.size, 1,
      "Should have 1 more future placement");
   let haveNavbarPlacements = gFuturePlacements.has(CustomizableUI.AREA_NAVBAR);
   ok(haveNavbarPlacements, "Should have placements for nav-bar");
   if (haveNavbarPlacements) {
     let placements = [...gFuturePlacements.get(CustomizableUI.AREA_NAVBAR)];
+
+    // Ignore widgets that are placed using the pref facility and not the
+    // versioned facility.  They're independent of kVersion and the saved
+    // state's current version, so they may be present in the placements.
+    for (let i = 0; i < placements.length; ) {
+      if (placements[i] == testWidgetNew.id) {
+        i++;
+        continue;
+      }
+      let pref = "browser.toolbarbuttons.introduced." + placements[i];
+      let introduced = false;
+      try {
+        introduced = Services.prefs.getBoolPref(pref);
+      } catch (ex) {}
+      if (!introduced) {
+        i++;
+        continue;
+      }
+      placements.splice(i, 1);
+    }
+
     is(placements.length, 1, "Should have 1 newly placed widget in nav-bar");
     is(placements[0], testWidgetNew.id, "Should have our test widget to be placed in nav-bar");
   }
 
   gFuturePlacements.delete(CustomizableUI.AREA_NAVBAR);
   CustomizableUIBSPass.kVersion--;
   gPalette.delete(testWidgetNew.id);
   gPalette.delete(testWidgetOld.id);