Bug 1361286 - return message instead of showing notification in Automigration module draft
authorgasolin <gasolin@gmail.com>
Thu, 18 May 2017 15:39:28 +0800
changeset 581074 80ae656c64dd39fcb091788a965e56cc035d2ef7
parent 580912 8e98dab5054dd093a37ba20c62cf0523e484cfbd
child 581075 85fe4c1bc19f3dce0a2a068a75c153bbd011254b
push id59760
push userbmo:gasolin@mozilla.com
push dateFri, 19 May 2017 08:16:14 +0000
bugs1361286
milestone55.0a1
Bug 1361286 - return message instead of showing notification in Automigration module MozReview-Commit-ID: 2H9EFcs04um
browser/app/profile/firefox.js
browser/base/content/newtab/page.js
browser/base/content/tab-content.js
browser/components/migration/AutoMigrate.jsm
browser/components/migration/MigrationUtils.jsm
browser/locales/en-US/chrome/browser/migration/migration.properties
browser/modules/AboutHome.jsm
browser/modules/AboutNewTab.jsm
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1590,16 +1590,17 @@ pref("dom.ipc.processPrelaunch.enabled",
 pref("browser.migrate.automigrate.enabled", true);
 #else
 pref("browser.migrate.automigrate.enabled", false);
 #endif
 // 4 here means the suggestion notification will be automatically
 // hidden the 4th day, so it will actually be shown on 3 different days.
 pref("browser.migrate.automigrate.daysToOfferUndo", 4);
 pref("browser.migrate.automigrate.ui.enabled", true);
+pref("browser.migrate.automigrate.inpage.ui.enabled", true);
 
 // See comments in bug 1340115 on how we got to these numbers.
 pref("browser.migrate.chrome.history.limit", 2000);
 pref("browser.migrate.chrome.history.maxAgeInDays", 180);
 
 // Enable browser frames for use on desktop.  Only exposed to chrome callers.
 pref("dom.mozBrowserFramesEnabled", true);
 
--- a/browser/base/content/newtab/page.js
+++ b/browser/base/content/newtab/page.js
@@ -246,15 +246,11 @@ var gPage = {
       this.onPageVisibleAndLoaded();
     } else {
       addEventListener("load", this);
     }
   },
 
   onPageVisibleAndLoaded() {
     // Maybe tell the user they can undo an initial automigration
-    this.maybeShowAutoMigrationUndoNotification();
-  },
-
-  maybeShowAutoMigrationUndoNotification() {
-    sendAsyncMessage("NewTab:MaybeShowAutoMigrationUndoNotification");
+    sendAsyncMessage("NewTab:MaybeShowUndoMessage");
   },
 };
--- a/browser/base/content/tab-content.js
+++ b/browser/base/content/tab-content.js
@@ -155,17 +155,17 @@ var AboutHomeListener = {
     docElt.setAttribute("snippetsVersion", aData.snippetsVersion);
   },
 
   onPageLoad() {
     addMessageListener("AboutHome:Update", this);
     addEventListener("click", this, true);
     addEventListener("pagehide", this, true);
 
-    sendAsyncMessage("AboutHome:MaybeShowAutoMigrationUndoNotification");
+    sendAsyncMessage("AboutHome:MaybeShowUndoMessage");
     sendAsyncMessage("AboutHome:RequestUpdate");
   },
 
   onClick(aEvent) {
     if (!aEvent.isTrusted || // Don't trust synthetic events
         aEvent.button == 2 || aEvent.target.localName != "button") {
       return;
     }
--- a/browser/components/migration/AutoMigrate.jsm
+++ b/browser/components/migration/AutoMigrate.jsm
@@ -5,32 +5,35 @@
 "use strict";
 
 this.EXPORTED_SYMBOLS = ["AutoMigrate"];
 
 const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
 
 const kAutoMigrateEnabledPref = "browser.migrate.automigrate.enabled";
 const kUndoUIEnabledPref = "browser.migrate.automigrate.ui.enabled";
+const kInPageUIEnabledPref = "browser.migrate.automigrate.inpage.ui.enabled";
 
 const kAutoMigrateBrowserPref = "browser.migrate.automigrate.browser";
 const kAutoMigrateImportedItemIds = "browser.migrate.automigrate.imported-items";
 
 const kAutoMigrateLastUndoPromptDateMsPref = "browser.migrate.automigrate.lastUndoPromptDateMs";
 const kAutoMigrateDaysToOfferUndoPref = "browser.migrate.automigrate.daysToOfferUndo";
 
 const kAutoMigrateUndoSurveyPref = "browser.migrate.automigrate.undo-survey";
 const kAutoMigrateUndoSurveyLocalePref = "browser.migrate.automigrate.undo-survey-locales";
 
 const kNotificationId = "automigration-undo";
 
 Cu.import("resource:///modules/MigrationUtils.jsm");
 Cu.import("resource://gre/modules/Preferences.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Log.jsm");
+
 XPCOMUtils.defineLazyModuleGetter(this, "AsyncShutdown",
                                   "resource://gre/modules/AsyncShutdown.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "LoginHelper",
                                   "resource://gre/modules/LoginHelper.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "NewTabUtils",
                                   "resource://gre/modules/NewTabUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "OS",
                                   "resource://gre/modules/osfile.jsm");
@@ -45,16 +48,19 @@ XPCOMUtils.defineLazyGetter(this, "gBran
 });
 
 Cu.importGlobalProperties(["URL"]);
 
 XPCOMUtils.defineLazyGetter(this, "kUndoStateFullPath", function() {
   return OS.Path.join(OS.Constants.Path.profileDir, "initialMigrationMetadata.jsonlz4");
 });
 
+let log = Log.repository.getLogger("AutoMigrate");
+log.addAppender(new Log.ConsoleAppender(new Log.BasicFormatter()));
+
 const AutoMigrate = {
   get resourceTypesToUse() {
     let {BOOKMARKS, HISTORY, PASSWORDS} = Ci.nsIBrowserProfileMigrator;
     return BOOKMARKS | HISTORY | PASSWORDS;
   },
 
   _checkIfEnabled() {
     let pref = Preferences.get(kAutoMigrateEnabledPref, false);
@@ -293,118 +299,156 @@ const AutoMigrate = {
   _purgeUndoState(reason) {
     // We don't wait for the off-main-thread removal to complete. OS.File will
     // ensure it happens before shutdown.
     OS.File.remove(kUndoStateFullPath, {ignoreAbsent: true}).then(() => {
       this._pendingUndoTasks = false;
     });
 
     let migrationBrowser = Preferences.get(kAutoMigrateBrowserPref, "unknown");
-    Services.prefs.clearUserPref(kAutoMigrateBrowserPref);
+    // keep browserName to help
+    // if we should show the inpage manual import message
+    if (reason !== this.UNDO_REMOVED_REASON_OFFER_REJECTED) {
+      Services.prefs.clearUserPref(kAutoMigrateBrowserPref);
+    }
 
     let histogram =
       Services.telemetry.getKeyedHistogramById("FX_STARTUP_MIGRATION_UNDO_REASON");
     histogram.add(migrationBrowser, reason);
   },
 
   getBrowserUsedForMigration() {
-    let browserId = Services.prefs.getCharPref(kAutoMigrateBrowserPref);
+    let browserId = Services.prefs.getStringPref(kAutoMigrateBrowserPref);
     if (browserId) {
       return MigrationUtils.getBrowserName(browserId);
     }
     return null;
   },
 
   /**
+   * Show the user message indicating we automatically imported
+   * their data via notification bar or the in-page message.
+   * @param target (xul:browser)
+   *        The browser in which we should show the notification.
+   */
+  async maybeShowUndoMessage(target) {
+    let canUndo = await this.canUndo();
+    log.debug(">>> canUndo:", canUndo);
+    if (!(await this.canUndo())) {
+      return "";
+    }
+
+    // The tab might have navigated since we requested the undo state:
+    let canUndoFromThisPage = ["about:home", "about:newtab"].includes(target.currentURI.spec);
+    if (!canUndoFromThisPage ||
+        !Preferences.get(kUndoUIEnabledPref, false)) {
+      return "";
+    }
+
+    let isInPage = Preferences.get(kInPageUIEnabledPref, false);
+
+    // At this stage we're committed to show the prompt - unless we shouldn't,
+    // in which case we remove the undo prefs (which will cause canUndo() to
+    // return false from now on.):
+    if (this.isUndoPromptExpired()) {
+      this._purgeUndoState(this.UNDO_REMOVED_REASON_OFFER_EXPIRED);
+      if (!isInPage) {
+        this._removeNotificationBars();
+      }
+      return "";
+    }
+
+    let remainingDays = Preferences.get(kAutoMigrateDaysToOfferUndoPref, 0);
+    Services.telemetry.getHistogramById("FX_STARTUP_MIGRATION_UNDO_OFFERED").add(4 - remainingDays);
+
+    if (isInPage) {
+      return this.getUndoMigrationMessage();
+    } else {
+      this.showUndoNotificationBar(target);
+      return "";
+    }
+  },
+
+  /**
+   * Return true if we have shown the prompt to user several days.
+   * (defined in kAutoMigrateDaysToOfferUndoPref)
+   */
+  isUndoPromptExpired() {
+    let today = new Date();
+    // Round down to midnight:
+    today = new Date(today.getFullYear(), today.getMonth(), today.getDate());
+    // We store the unix timestamp corresponding to midnight on the last day
+    // on which we prompted. Fetch that and compare it to today's date.
+    // (NB: stored as a string because int prefs are too small for unix
+    // timestamps.)
+    let previousPromptDateMsStr = Preferences.get(kAutoMigrateLastUndoPromptDateMsPref, "0");
+    let previousPromptDate = new Date(parseInt(previousPromptDateMsStr, 10));
+    if (previousPromptDate < today) {
+      let remainingDays = Preferences.get(kAutoMigrateDaysToOfferUndoPref, 4) - 1;
+      Preferences.set(kAutoMigrateDaysToOfferUndoPref, remainingDays);
+      log.debug(">>remain:", remainingDays);
+      Preferences.set(kAutoMigrateLastUndoPromptDateMsPref, today.valueOf().toString());
+      if (remainingDays <= 0) {
+        return true;
+      }
+    }
+    return false;
+  },
+
+  /**
+   * Return the message that denotes the user data is migrated from the other browser.
+   */
+  getUndoMigrationMessage() {
+    let browserName = this.getBrowserUsedForMigration();
+    log.debug(">>> browserName:", this.getBrowserUsedForMigration());
+    if (!browserName) {
+      browserName = MigrationUtils.getLocalizedString("automigration.undo.unknownbrowser");
+    }
+    const kMessageId = "automigration.undo.message2." +
+                      Preferences.get(kAutoMigrateImportedItemIds, "all");
+    const kBrandShortName = gBrandBundle.GetStringFromName("brandShortName");
+    let message = MigrationUtils.getLocalizedString(kMessageId,
+                                                    [kBrandShortName, browserName]);
+    return message;
+  },
+
+  /**
    * Show the user a notification bar indicating we automatically imported
    * their data and offering them the possibility of removing it.
    * @param target (xul:browser)
    *        The browser in which we should show the notification.
    */
-  async maybeShowUndoNotification(target) {
-    if (!(await this.canUndo())) {
-      return;
-    }
-
-    // The tab might have navigated since we requested the undo state:
-    let canUndoFromThisPage = ["about:home", "about:newtab"].includes(target.currentURI.spec);
-    if (!canUndoFromThisPage ||
-        !Preferences.get(kUndoUIEnabledPref, false)) {
-      return;
-    }
-
+  showUndoNotificationBar(target) {
     let win = target.ownerGlobal;
     let notificationBox = win.gBrowser.getNotificationBox(target);
     if (!notificationBox || notificationBox.getNotificationWithValue(kNotificationId)) {
-      return;
+      return "";
     }
 
-    // At this stage we're committed to show the prompt - unless we shouldn't,
-    // in which case we remove the undo prefs (which will cause canUndo() to
-    // return false from now on.):
-    if (!this.shouldStillShowUndoPrompt()) {
-      this._purgeUndoState(this.UNDO_REMOVED_REASON_OFFER_EXPIRED);
-      this._removeNotificationBars();
-      return;
-    }
-
-    let browserName = this.getBrowserUsedForMigration();
-    if (!browserName) {
-      browserName = MigrationUtils.getLocalizedString("automigration.undo.unknownbrowser");
-    }
-    const kMessageId = "automigration.undo.message." +
-                      Preferences.get(kAutoMigrateImportedItemIds, "all");
-    const kBrandShortName = gBrandBundle.GetStringFromName("brandShortName");
-    let message = MigrationUtils.getLocalizedString(kMessageId,
-                                                    [browserName, kBrandShortName]);
-
+    let message = this.getUndoMigrationMessage();
     let buttons = [
       {
         label: MigrationUtils.getLocalizedString("automigration.undo.keep2.label"),
         accessKey: MigrationUtils.getLocalizedString("automigration.undo.keep2.accesskey"),
         callback: () => {
           this._purgeUndoState(this.UNDO_REMOVED_REASON_OFFER_REJECTED);
           this._removeNotificationBars();
         },
       },
       {
         label: MigrationUtils.getLocalizedString("automigration.undo.dontkeep2.label"),
         accessKey: MigrationUtils.getLocalizedString("automigration.undo.dontkeep2.accesskey"),
         callback: () => {
-          this._maybeOpenUndoSurveyTab(win);
-          this.undo();
+          this.undoAutoMigrate(win);
         },
       },
     ];
     notificationBox.appendNotification(
       message, kNotificationId, null, notificationBox.PRIORITY_INFO_HIGH, buttons
     );
-    let remainingDays = Preferences.get(kAutoMigrateDaysToOfferUndoPref, 0);
-    Services.telemetry.getHistogramById("FX_STARTUP_MIGRATION_UNDO_OFFERED").add(4 - remainingDays);
-  },
-
-  shouldStillShowUndoPrompt() {
-    let today = new Date();
-    // Round down to midnight:
-    today = new Date(today.getFullYear(), today.getMonth(), today.getDate());
-    // We store the unix timestamp corresponding to midnight on the last day
-    // on which we prompted. Fetch that and compare it to today's date.
-    // (NB: stored as a string because int prefs are too small for unix
-    // timestamps.)
-    let previousPromptDateMsStr = Preferences.get(kAutoMigrateLastUndoPromptDateMsPref, "0");
-    let previousPromptDate = new Date(parseInt(previousPromptDateMsStr, 10));
-    if (previousPromptDate < today) {
-      let remainingDays = Preferences.get(kAutoMigrateDaysToOfferUndoPref, 4) - 1;
-      Preferences.set(kAutoMigrateDaysToOfferUndoPref, remainingDays);
-      Preferences.set(kAutoMigrateLastUndoPromptDateMsPref, today.valueOf().toString());
-      if (remainingDays <= 0) {
-        return false;
-      }
-    }
-    return true;
   },
 
   UNDO_REMOVED_REASON_UNDO_USED: 0,
   UNDO_REMOVED_REASON_SYNC_SIGNIN: 1,
   UNDO_REMOVED_REASON_PASSWORD_CHANGE: 2,
   UNDO_REMOVED_REASON_BOOKMARK_CHANGE: 3,
   UNDO_REMOVED_REASON_OFFER_EXPIRED: 4,
   UNDO_REMOVED_REASON_OFFER_REJECTED: 5,
@@ -466,16 +510,17 @@ const AutoMigrate = {
       Preferences.set(kAutoMigrateImportedItemIds, itemsWithData);
     }
   },
 
   /**
    * Used for the shutdown blocker's information field.
    */
   _saveUndoStateTrackerForShutdown: "not running",
+
   /**
    * Store the information required for using 'undo' of the automatic
    * migration in the user's profile.
    */
   async saveUndoState() {
     let resolveSavingPromise;
     this._saveUndoStateTrackerForShutdown = "processing undo history";
     this._savingPromise = new Promise(resolve => { resolveSavingPromise = resolve });
@@ -651,11 +696,28 @@ const AutoMigrate = {
     let url = Services.urlFormatter.formatURL(rawURL);
     url = url.replace("%IMPORTEDBROWSER%", encodeURIComponent(migrationBrowser));
     chromeWindow.openUILinkIn(url, "tab");
   },
 
   QueryInterface: XPCOMUtils.generateQI(
     [Ci.nsIObserver, Ci.nsINavBookmarkObserver, Ci.nsISupportsWeakReference]
   ),
+
+  /**
+   * Undo action called by the UndoNotification or by the newtab
+   * @param chromeWindow A reference to the window in which to open a link.
+   */
+  undoAutoMigrate(chromeWindow) {
+    this._maybeOpenUndoSurveyTab(chromeWindow);
+    this.undo();
+  },
+
+  /**
+   * Keep the automigration result and not prompt anymore
+   */
+  keepAutoMigration() {
+    this._purgeUndoState(this.UNDO_REMOVED_REASON_OFFER_REJECTED);
+    Preferences.set(kAutoMigrateDaysToOfferUndoPref, 0);
+  },
 };
 
 AutoMigrate.init();
--- a/browser/components/migration/MigrationUtils.jsm
+++ b/browser/components/migration/MigrationUtils.jsm
@@ -1105,16 +1105,17 @@ this.MigrationUtils = Object.freeze({
 
   gAvailableMigratorKeys,
 
   MIGRATION_ENTRYPOINT_UNKNOWN: 0,
   MIGRATION_ENTRYPOINT_FIRSTRUN: 1,
   MIGRATION_ENTRYPOINT_FXREFRESH: 2,
   MIGRATION_ENTRYPOINT_PLACES: 3,
   MIGRATION_ENTRYPOINT_PASSWORDS: 4,
+  MIGRATION_ENTRYPOINT_NEWTAB: 5,
 
   _sourceNameToIdMapping: {
     "nothing":    1,
     "firefox":    2,
     "edge":       3,
     "ie":         4,
     "chrome":     5,
     "chromium":   6,
--- a/browser/locales/en-US/chrome/browser/migration/migration.properties
+++ b/browser/locales/en-US/chrome/browser/migration/migration.properties
@@ -68,20 +68,20 @@ 64_safari=Other Data
 64_chrome=Other Data
 64_firefox_other=Other Data
 64_360se=Other Data
 
 128_firefox=Windows and Tabs
 
 # Automigration undo notification.
 # %1$S will be replaced with the name of the browser we imported from, %2$S will be replaced with brandShortName
-automigration.undo.message.all              = Pick up where you left off. We’ve imported these sites and your bookmarks, history and passwords from %1$S into %2$S.
-automigration.undo.message.bookmarks        = Pick up where you left off. We’ve imported these sites and your bookmarks from %1$S into %2$S.
-automigration.undo.message.bookmarks.logins = Pick up where you left off. We’ve imported these sites and your bookmarks and passwords from %1$S into %2$S.
-automigration.undo.message.bookmarks.visits = Pick up where you left off. We’ve imported these sites and your bookmarks and history from %1$S into %2$S.
-automigration.undo.message.logins           = Pick up where you left off. We’ve imported your passwords from %1$S into %2$S.
-automigration.undo.message.logins.visits    = Pick up where you left off. We’ve imported these sites and your history and passwords from %1$S into %2$S.
-automigration.undo.message.visits           = Pick up where you left off. We’ve imported these sites and your history from %1$S into %2$S.
+automigration.undo.message2.all              = Dive right in. Try %1$S with your top sites, bookmarks, history and passwords from %2$S.
+automigration.undo.message2.bookmarks        = Dive right in. Try %1$S with your top sites and bookmarks from %2$S.
+automigration.undo.message2.bookmarks.logins = Dive right in. Try %1$S with your top sites, bookmarks and passwords from %2$S.
+automigration.undo.message2.bookmarks.visits = Dive right in. Try %1$S with your top sites, bookmarks and history from %2$S.
+automigration.undo.message2.logins           = Dive right in. Try %1$S with your passwords from %2$S.
+automigration.undo.message2.logins.visits    = Dive right in. Try %1$S with your top sites, history and passwords from %2$S.
+automigration.undo.message2.visits           = Dive right in. Try %1$S with your top sites and history from %2$S.
 automigration.undo.keep2.label            = OK, Got it
 automigration.undo.keep2.accesskey        = O
 automigration.undo.dontkeep2.label        = No Thanks
 automigration.undo.dontkeep2.accesskey    = N
 automigration.undo.unknownbrowser         = Unknown Browser
--- a/browser/modules/AboutHome.jsm
+++ b/browser/modules/AboutHome.jsm
@@ -144,18 +144,18 @@ var AboutHome = {
       case "AboutHome:Settings":
         window.openPreferences(undefined, {origin: "aboutHome"} );
         break;
 
       case "AboutHome:RequestUpdate":
         this.sendAboutHomeData(aMessage.target);
         break;
 
-      case "AboutHome:MaybeShowAutoMigrationUndoNotification":
-        AutoMigrate.maybeShowUndoNotification(aMessage.target);
+      case "AboutHome:MaybeShowUndoMessage":
+        AutoMigrate.maybeShowUndoMessage(aMessage.target);
         break;
     }
   },
 
   // Send all the chrome-privileged data needed by about:home. This
   // gets re-sent when the search engine changes.
   sendAboutHomeData(target) {
     let wrapper = {};
--- a/browser/modules/AboutNewTab.jsm
+++ b/browser/modules/AboutNewTab.jsm
@@ -27,18 +27,52 @@ var AboutNewTab = {
   isOverridden: false,
 
   init() {
     if (this.isOverridden) {
       return;
     }
     this.pageListener = new RemotePages("about:newtab");
     this.pageListener.addMessageListener("NewTab:Customize", this.customize.bind(this));
-    this.pageListener.addMessageListener("NewTab:MaybeShowAutoMigrationUndoNotification",
-      (msg) => AutoMigrate.maybeShowUndoNotification(msg.target.browser));
+    this.pageListener.addMessageListener("NewTab:MaybeShowUndoMessage",
+       this.maybeShowUndoMessage.bind(this));
+    this.pageListener.addMessageListener("NewTab:undoAutoMigration",
+      this.undoAutomigration.bind(this));
+    this.pageListener.addMessageListener("NewTab:manualMigration",
+      this.manualMigration.bind(this));
+    this.pageListener.addMessageListener("NewTab:migrationIsDone",
+      this.doneAutoMigration.bind(this))
+  },
+
+  async maybeShowUndoMessage({ target }) {
+    let browserName = Services.prefs.getStringPref("browser.migrate.automigrate.browser", "");
+    if (!AutoMigrate.isUndoPromptExpired() && browserName == "") { // show manual import message
+      this.pageListener.sendAsyncMessage("NewTab:migrationIsReverted");
+    } else { // show migrated message
+      this.window = target.browser.ownerGlobal;
+      let msg = await AutoMigrate.maybeShowUndoMessage(target.browser);
+      this.pageListener.sendAsyncMessage("NewTab:automigrated", msg);
+    }
+  },
+
+  undoAutomigration({ target }) {
+    // show the message since we don't need to wait undo is actually done
+    this.pageListener.sendAsyncMessage("NewTab:migrationIsReverted");
+    AutoMigrate.undoAutoMigrate(this.window);
+  },
+
+  manualMigration() {
+    // We pass in the type of source we're using for use in telemetry
+    MigrationUtils.showMigrationWizard(this.window, [MigrationUtils.MIGRATION_ENTRYPOINT_NEWTAB]);
+  },
+
+  doneAutoMigration() {
+    AutoMigrate.keepAutoMigration();
+    this.pageListener.sendAsyncMessage("NewTab:hideMigrationMessage");
+>>>>>>> 598ac12... fixup! Bug 1361286 - return message instead of showing notification in Automigration module
   },
 
   customize(message) {
     NewTabUtils.allPages.enabled = message.data.enabled;
     NewTabUtils.allPages.enhanced = message.data.enhanced;
   },
 
   uninit() {