Bug 1395460 p1 - Remove usages of about:accounts. r?tcsc draft
authorEdouard Oger <eoger@fastmail.com>
Tue, 24 Oct 2017 14:05:52 -0400
changeset 687070 cb1ac4765c717e85fa6e746131af35a5693dfefa
parent 686801 0d1e55d87931fe70ec1d007e886bcd58015ff770
child 687071 0c7cdd914475357334cd1509a036b675e64c2e3d
push id86410
push userbmo:eoger@fastmail.com
push dateThu, 26 Oct 2017 21:40:14 +0000
reviewerstcsc
bugs1395460
milestone58.0a1
Bug 1395460 p1 - Remove usages of about:accounts. r?tcsc MozReview-Commit-ID: APdGc9avJDw
browser/base/content/browser-sync.js
browser/components/customizableui/test/browser_synced_tabs_menu.js
browser/components/preferences/in-content/main.js
browser/components/preferences/in-content/sync.js
browser/components/preferences/in-content/sync.xul
browser/components/uitour/UITour-lib.js
browser/components/uitour/UITour.jsm
browser/components/uitour/test/browser_UITour_sync.js
browser/extensions/activity-stream/lib/SnippetsFeed.jsm
browser/extensions/onboarding/locales/en-US/onboarding.properties
docshell/test/browser/browser_bug1309900_crossProcessHistoryNavigation.js
services/fxaccounts/FxAccounts.jsm
services/fxaccounts/FxAccountsConfig.jsm
--- a/browser/base/content/browser-sync.js
+++ b/browser/base/content/browser-sync.js
@@ -249,37 +249,24 @@ var gSync = {
     default:
       this.openPrefs("menupanel", "fxa");
       break;
     }
 
     PanelUI.hide();
   },
 
-  openAccountsPage(action, urlParams = {}) {
-    let params = new URLSearchParams();
-    if (action) {
-      params.set("action", action);
-    }
-    for (let name in urlParams) {
-      if (urlParams[name] !== undefined) {
-        params.set(name, urlParams[name]);
-      }
-    }
-    let url = "about:accounts?" + params;
+  async openSignInAgainPage(entryPoint) {
+    const url = await fxAccounts.promiseAccountsForceSigninURI(entryPoint);
     switchToTabHavingURI(url, true, {
       replaceQueryString: true,
       triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
     });
   },
 
-  openSignInAgainPage(entryPoint) {
-    this.openAccountsPage("reauth", { entrypoint: entryPoint });
-  },
-
   async openDevicesManagementPage(entryPoint) {
     let url = await fxAccounts.promiseAccountsManageDevicesURI(entryPoint);
     switchToTabHavingURI(url, true, {
       replaceQueryString: true,
       triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
     });
   },
 
--- a/browser/components/customizableui/test/browser_synced_tabs_menu.js
+++ b/browser/components/customizableui/test/browser_synced_tabs_menu.js
@@ -54,17 +54,17 @@ add_task(async function setup() {
     UIState._internal.notifyStateUpdated = origNotifyStateUpdated;
     SyncedTabs._internal = oldInternal;
   });
 });
 
 // The test expects the about:preferences#sync page to open in the current tab
 async function openPrefsFromMenuPanel(expectedPanelId, entryPoint) {
   info("Check Sync button functionality");
-  Services.prefs.setCharPref("identity.fxaccounts.remote.signup.uri", "http://example.com/");
+  Services.prefs.setCharPref("identity.fxaccounts.remote.signup.uri", "https://example.com/");
   CustomizableUI.addWidgetToArea("sync-button", CustomizableUI.AREA_FIXED_OVERFLOW_PANEL);
 
   await waitForOverflowButtonShown();
 
   // check the button's functionality
   await document.getElementById("nav-bar").overflowable.show();
 
   if (entryPoint == "uitour") {
--- a/browser/components/preferences/in-content/main.js
+++ b/browser/components/preferences/in-content/main.js
@@ -554,33 +554,33 @@ var gMainPane = {
           revertCheckbox();
           return;
         case CONFIRM_RESTART_PROMPT_RESTART_LATER:
           createOrRemoveSpecialDevEditionFile();
       }
     }
   },
 
-  onGetStarted(aEvent) {
-    if (AppConstants.MOZ_DEV_EDITION) {
-      const Cc = Components.classes, Ci = Components.interfaces;
-      let win = Services.wm.getMostRecentWindow("navigator:browser");
-
-      fxAccounts.getSignedInUser().then(data => {
-        if (win) {
-          if (data) {
-            // We have a user, open Sync preferences in the same tab
-            win.openUILinkIn("about:preferences#sync", "current");
-            return;
-          }
-          let accountsTab = win.gBrowser.addTab("about:accounts?action=signin&entrypoint=dev-edition-setup");
-          win.gBrowser.selectedTab = accountsTab;
-        }
-      });
+  async onGetStarted(aEvent) {
+    if (!AppConstants.MOZ_DEV_EDITION) {
+      return;
+    }
+    const win = Services.wm.getMostRecentWindow("navigator:browser");
+    if (!win) {
+      return;
     }
+    const user = await fxAccounts.getSignedInUser();
+    if (user) {
+      // We have a user, open Sync preferences in the same tab
+      win.openUILinkIn("about:preferences#sync", "current");
+      return;
+    }
+    let url = await fxAccounts.promiseAccountsSignInURI("dev-edition-setup");
+    let accountsTab = win.gBrowser.addTab(url);
+    win.gBrowser.selectedTab = accountsTab;
   },
 
   // HOME PAGE
 
   /*
    * Preferences:
    *
    * browser.startup.homepage
--- a/browser/components/preferences/in-content/sync.js
+++ b/browser/components/preferences/in-content/sync.js
@@ -148,16 +148,20 @@ var gSyncPane = {
 
     document.getElementById("tosPP-small-ToS").setAttribute("href", Weave.Svc.Prefs.get("fxa.termsURL"));
     document.getElementById("tosPP-small-PP").setAttribute("href", Weave.Svc.Prefs.get("fxa.privacyURL"));
 
     fxAccounts.promiseAccountsManageURI(this._getEntryPoint()).then(accountsManageURI => {
       document.getElementById("verifiedManage").setAttribute("href", accountsManageURI);
     });
 
+    fxAccounts.promiseAccountsSignUpURI(this._getEntryPoint()).then(signUpURI => {
+      document.getElementById("noFxaSignUp").setAttribute("href", signUpURI);
+    });
+
     this.updateWeavePrefs();
 
     // Notify observers that the UI is now ready
     Services.obs.notifyObservers(window, "sync-pane-loaded");
   },
 
   _toggleComputerNameControls(editMode) {
     let textbox = document.getElementById("fxaSyncComputerName");
@@ -350,27 +354,16 @@ var gSyncPane = {
     });
   },
 
   _getEntryPoint() {
     let params = new URLSearchParams(document.URL.split("#")[0].split("?")[1] || "");
     return params.get("entrypoint") || "preferences";
   },
 
-  _openAboutAccounts(action) {
-    let entryPoint = this._getEntryPoint();
-    let params = new URLSearchParams();
-    if (action) {
-      params.set("action", action);
-    }
-    params.set("entrypoint", entryPoint);
-
-    this.replaceTabWithUrl("about:accounts?" + params);
-  },
-
   openContentInBrowser(url, options) {
     let win = Services.wm.getMostRecentWindow("navigator:browser");
     if (!win) {
       openUILinkIn(url, "tab");
       return;
     }
     win.switchToTabHavingURI(url, true, options);
   },
@@ -381,26 +374,24 @@ var gSyncPane = {
     let browser = window.QueryInterface(Ci.nsIInterfaceRequestor)
       .getInterface(Ci.nsIWebNavigation)
       .QueryInterface(Ci.nsIDocShell)
       .chromeEventHandler;
     // And tell it to load our URL.
     browser.loadURI(url);
   },
 
-  signUp() {
-    this._openAboutAccounts("signup");
+  async signIn() {
+    const url = await fxAccounts.promiseAccountsSignInURI(this._getEntryPoint());
+    this.replaceTabWithUrl(url);
   },
 
-  signIn() {
-    this._openAboutAccounts("signin");
-  },
-
-  reSignIn() {
-    this._openAboutAccounts("reauth");
+  async reSignIn() {
+    const url = await fxAccounts.promiseAccountsForceSigninURI(this._getEntryPoint());
+    this.replaceTabWithUrl(url);
   },
 
 
   clickOrSpaceOrEnterPressed(event) {
     // Note: charCode is deprecated, but 'char' not yet implemented.
     // Replace charCode with char when implemented, see Bug 680830
     return ((event.type == "click" && event.button == 0) ||
       (event.type == "keypress" &&
--- a/browser/components/preferences/in-content/sync.xul
+++ b/browser/components/preferences/in-content/sync.xul
@@ -64,19 +64,17 @@
           <button id="noFxaSignIn"
                   class="accessory-button"
                   label="&signedOut.accountBox.signin2;"
                   accesskey="&signedOut.accountBox.signin2.accesskey;"/>
         </hbox>
         <hbox align="center" flex="1">
           <html:a id="noFxaSignUp"
                   class="openLink"
-                  accesskey="&signedOut.accountBox.create2.accesskey;"
-                  onclick="gSyncPane.signUp();"
-                  onkeypress="gSyncPane.signUp();">&signedOut.accountBox.create2;</html:a>
+                  accesskey="&signedOut.accountBox.create2.accesskey;">&signedOut.accountBox.create2;</html:a>
         </hbox>
       </vbox>
     </hbox>
     <label class="fxaMobilePromo">
         &mobilePromo3.start;<!-- We put these comments to avoid inserting white spaces
         --><image class="androidLink"></image><label id="fxaMobilePromo-android"
                   class="text-link"><!--
         -->&mobilePromo3.androidLink;</label><!--
--- a/browser/components/uitour/UITour-lib.js
+++ b/browser/components/uitour/UITour-lib.js
@@ -568,28 +568,28 @@ if (typeof Mozilla == "undefined") {
    * campaign tracking. Each attribute of the object must have a name that
    * is a string, begins with "utm_" and contains only only alphanumeric
    * characters, dashes or underscores. The values may be any string and will
    * automatically be encoded.
    * @param {String} email - A string containing the default email account
    * for the URL opened by the browser.
    * @since 31, 47 for `extraURLCampaignParams`
    * @example
-   * // Will open about:accounts?action=signup&entrypoint=uitour
+   * // Will open https://accounts.firefox.com/signup?entrypoint=uitour
    * Mozilla.UITour.showFirefoxAccounts();
    * @example
    * // Will open:
-   * // about:accounts?action=signup&entrypoint=uitour&utm_foo=bar&utm_bar=baz
+   * // https://accounts.firefox.com/signup?entrypoint=uitour&utm_foo=bar&utm_bar=baz
    * Mozilla.UITour.showFirefoxAccounts({
    *   'utm_foo': 'bar',
    *   'utm_bar': 'baz'
    * });
    * @example
    * // Will open:
-   * // about:accounts?action=signup&entrypoint=uitour&email=foo%40bar.com
+   * // https://accounts.firefox.com/?action=email&email=foo%40bar.com&entrypoint=uitour
    * Mozilla.UITour.showFirefoxAccounts(null, "foo@bar.com");
    */
   Mozilla.UITour.showFirefoxAccounts = function(extraURLCampaignParams, email) {
     _sendEvent("showFirefoxAccounts", {
       extraURLCampaignParams: JSON.stringify(extraURLCampaignParams),
       email
     });
   };
--- a/browser/components/uitour/UITour.jsm
+++ b/browser/components/uitour/UITour.jsm
@@ -29,16 +29,18 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ProfileAge",
   "resource://gre/modules/ProfileAge.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ReaderParent",
   "resource:///modules/ReaderParent.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PageActions",
   "resource:///modules/PageActions.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts",
+  "resource://gre/modules/FxAccounts.jsm");
 
 // See LOG_LEVELS in Console.jsm. Common examples: "All", "Info", "Warn", & "Error".
 const PREF_LOG_LEVEL      = "browser.uitour.loglevel";
 const PREF_SEENPAGEIDS    = "browser.uitour.seenPageIDs";
 
 const BACKGROUND_PAGE_ACTIONS_ALLOWED = new Set([
   "forceShowReaderIcon",
   "getConfiguration",
@@ -555,35 +557,30 @@ this.UITour = {
           log.warn("openPreferences: Invalid pane specified");
           return false;
         }
         window.openPreferences(data.pane, { origin: "UITour" });
         break;
       }
 
       case "showFirefoxAccounts": {
-        let p;
-        if (data.email) {
-          // With email parameter added, we need to use 'email' action to help FxA determine
-          // whether the email is registered or not and direct the user down the correct flow
-          p =  new URLSearchParams("action=email&entrypoint=uitour");
-          p.append("email", data.email);
-        } else {
-          // 'signup' is the default action that makes sense currently, so we don't
-          // accept arbitrary actions just to be safe...
-          p =  new URLSearchParams("action=signup&entrypoint=uitour");
-        }
-        // Call our helper to validate extraURLCampaignParams and populate URLSearchParams
-        if (!this._populateCampaignParams(p, data.extraURLCampaignParams)) {
-          log.warn("showFirefoxAccounts: invalid campaign args specified");
-          return false;
-        }
+        Promise.resolve().then(() => {
+          return data.email ? fxAccounts.promiseAccountsEmailURI(data.email, "uitour") :
+                              fxAccounts.promiseAccountsSignUpURI("uitour");
+        }).then(uri => {
+          const url = new URL(uri);
+          // Call our helper to validate extraURLCampaignParams and populate URLSearchParams
+          if (!this._populateCampaignParams(url, data.extraURLCampaignParams)) {
+            log.warn("showFirefoxAccounts: invalid campaign args specified");
+            return;
+          }
 
-        // We want to replace the current tab.
-        browser.loadURI("about:accounts?" + p.toString());
+          // We want to replace the current tab.
+          browser.loadURI(url.href);
+        });
         break;
       }
 
       case "resetFirefox": {
         // Open a reset profile dialog window.
         if (ResetProfile.resetSupported()) {
           ResetProfile.openConfirmationDialog(window);
         }
@@ -768,19 +765,19 @@ this.UITour = {
         }
         break;
       }
     }
   },
 
   // Given a string that is a JSONified represenation of an object with
   // additional utm_* URL params that should be appended, validate and append
-  // them to the passed URLSearchParams object. Returns true if the params
+  // them to the passed URL object. Returns true if the params
   // were validated and appended, and false if the request should be ignored.
-  _populateCampaignParams(urlSearchParams, extraURLCampaignParams) {
+  _populateCampaignParams(url, extraURLCampaignParams) {
     // We are extra paranoid about what params we allow to be appended.
     if (typeof extraURLCampaignParams == "undefined") {
       // no params, so it's all good.
       return true;
     }
     if (typeof extraURLCampaignParams != "string") {
       log.warn("_populateCampaignParams: extraURLCampaignParams is not a string");
       return false;
@@ -806,17 +803,17 @@ this.UITour = {
         let value = campaignParams[name];
         if (typeof name != "string" || typeof value != "string" ||
             !name.startsWith("utm_") ||
             value.length == 0 ||
             !reSimpleString.test(name)) {
           log.warn("_populateCampaignParams: invalid campaign param specified");
           return false;
         }
-        urlSearchParams.append(name, value);
+        url.searchParams.append(name, value);
       }
     }
     return true;
   },
 
   setTelemetryBucket(aPageID) {
     let bucket = BUCKET_NAME + BrowserUITelemetry.BUCKET_SEPARATOR + aPageID;
     BrowserUITelemetry.setBucket(bucket);
--- a/browser/components/uitour/test/browser_UITour_sync.js
+++ b/browser/components/uitour/test/browser_UITour_sync.js
@@ -1,20 +1,29 @@
 "use strict";
 
 var gTestTab;
 var gContentAPI;
 var gContentWindow;
 
 registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("identity.fxaccounts.remote.signup.uri");
+  Services.prefs.clearUserPref("identity.fxaccounts.remote.email.uri");
   Services.prefs.clearUserPref("services.sync.username");
 });
 
 add_task(setup_UITourTest);
 
+add_task(async function setup() {
+  Services.prefs.setCharPref("identity.fxaccounts.remote.signup.uri",
+                             "https://example.com/signup");
+  Services.prefs.setCharPref("identity.fxaccounts.remote.email.uri",
+                             "https://example.com/?action=email");
+})
+
 add_UITour_task(async function test_checkSyncSetup_disabled() {
   let result = await getConfigurationPromise("sync");
   is(result.setup, false, "Sync shouldn't be setup by default");
 });
 
 add_UITour_task(async function test_checkSyncSetup_enabled() {
   Services.prefs.setCharPref("services.sync.username", "uitour@tests.mozilla.org");
   let result = await getConfigurationPromise("sync");
@@ -46,71 +55,71 @@ add_UITour_task(async function test_chec
   result = await getConfigurationPromise("sync");
   is(result.mobileDevices, 0, "mobileDevices should be 0");
   is(result.desktopDevices, 0, "desktopDevices should be 0");
   is(result.totalDevices, 0, "totalDevices should be 0");
 });
 
 // The showFirefoxAccounts API is sync related, so we test that here too...
 add_UITour_task(async function test_firefoxAccountsNoParams() {
-  info("Load about:accounts containing an iframe to https://accounts.firefox.com");
+  info("Load https://accounts.firefox.com");
   await gContentAPI.showFirefoxAccounts();
   await BrowserTestUtils.browserLoaded(gTestTab.linkedBrowser, false,
-                                       "about:accounts?action=signup&entrypoint=uitour");
+                                       "https://example.com/signup?entrypoint=uitour");
 });
 
 
 add_UITour_task(async function test_firefoxAccountsValidParams() {
-  info("Load about:accounts containing an iframe to https://accounts.firefox.com");
+  info("Load https://accounts.firefox.com");
   await gContentAPI.showFirefoxAccounts({ utm_foo: "foo", utm_bar: "bar" });
   await BrowserTestUtils.browserLoaded(gTestTab.linkedBrowser, false,
-                                       "about:accounts?action=signup&entrypoint=uitour&utm_foo=foo&utm_bar=bar");
+                                       "https://example.com/signup?entrypoint=uitour&utm_foo=foo&utm_bar=bar");
 });
 
 add_UITour_task(async function test_firefoxAccountsWithEmail() {
-  info("Load about:accounts containing an iframe to https://accounts.firefox.com");
+  info("Load https://accounts.firefox.com");
   await gContentAPI.showFirefoxAccounts(null, "foo@bar.com");
   await BrowserTestUtils.browserLoaded(gTestTab.linkedBrowser, false,
-                                       "about:accounts?action=email&entrypoint=uitour&email=foo%40bar.com");
+                                       "https://example.com/?action=email&email=foo%40bar.com&entrypoint=uitour");
 });
 
 add_UITour_task(async function test_firefoxAccountsNonAlphaValue() {
   // All characters in the value are allowed, but they must be automatically escaped.
   // (we throw a unicode character in there too - it's not auto-utf8 encoded,
   // but that's ok, so long as it is escaped correctly.)
   let value = "foo& /=?:\\\xa9";
   // encodeURIComponent encodes spaces to %20 but we want "+"
   let expected = encodeURIComponent(value).replace(/%20/g, "+");
-  info("Load about:accounts containing an iframe to https://accounts.firefox.com");
+  info("Load https://accounts.firefox.com");
   await gContentAPI.showFirefoxAccounts({ utm_foo: value });
   await BrowserTestUtils.browserLoaded(gTestTab.linkedBrowser, false,
-                                       "about:accounts?action=signup&entrypoint=uitour&utm_foo=" + expected);
+                                       "https://example.com/signup?entrypoint=uitour&utm_foo=" + expected);
 });
 
 // A helper to check the request was ignored due to invalid params.
-async function checkAboutAccountsNotLoaded() {
+async function checkFxANotLoaded() {
   try {
     await waitForConditionPromise(() => {
-      return gBrowser.selectedBrowser.currentURI.spec.startsWith("about:accounts");
-    }, "Check if about:accounts opened");
-    ok(false, "No about:accounts tab should have opened");
+      return gBrowser.selectedBrowser.currentURI.spec.startsWith("https://example.com");
+    }, "Check if FxA opened");
+    ok(false, "No FxA tab should have opened");
   } catch (ex) {
-    ok(true, "No about:accounts tab opened");
+    ok(true, "No FxA tab opened");
   }
 }
 
 add_UITour_task(async function test_firefoxAccountsNonObject() {
   // non-string should be rejected.
   await gContentAPI.showFirefoxAccounts(99);
-  await checkAboutAccountsNotLoaded();
+  await checkFxANotLoaded();
 });
 
 add_UITour_task(async function test_firefoxAccountsNonUtmPrefix() {
   // Any non "utm_" name should should be rejected.
   await gContentAPI.showFirefoxAccounts({ utm_foo: "foo", bar: "bar" });
-  await checkAboutAccountsNotLoaded();
+  await checkFxANotLoaded();
 });
 
 add_UITour_task(async function test_firefoxAccountsNonAlphaName() {
   // Any "utm_" name which includes non-alpha chars should be rejected.
   await gContentAPI.showFirefoxAccounts({ utm_foo: "foo", "utm_bar=": "bar" });
-  await checkAboutAccountsNotLoaded();
+  await checkFxANotLoaded();
 });
--- a/browser/extensions/activity-stream/lib/SnippetsFeed.jsm
+++ b/browser/extensions/activity-stream/lib/SnippetsFeed.jsm
@@ -8,16 +8,18 @@ const {utils: Cu} = Components;
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 const {actionTypes: at, actionCreators: ac} = Cu.import("resource://activity-stream/common/Actions.jsm", {});
 
 XPCOMUtils.defineLazyModuleGetter(this, "ShellService",
   "resource:///modules/ShellService.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ProfileAge",
   "resource://gre/modules/ProfileAge.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts",
+  "resource://gre/modules/FxAccounts.jsm");
 
 // Url to fetch snippets, in the urlFormatter service format.
 const SNIPPETS_URL_PREF = "browser.aboutHomeSnippets.updateUrl";
 const TELEMETRY_PREF = "datareporting.healthreport.uploadEnabled";
 const FXA_USERNAME_PREF = "services.sync.username";
 const ONBOARDING_FINISHED_PREF = "browser.onboarding.notification.finished";
 // Prefix for any target matching a search engine.
 const TARGET_SEARCHENGINE_PREFIX = "searchEngine-";
@@ -119,19 +121,20 @@ this.SnippetsFeed = class SnippetsFeed {
     Services.prefs.removeObserver(ONBOARDING_FINISHED_PREF, this._refresh);
     Services.prefs.removeObserver(SNIPPETS_URL_PREF, this._refresh);
     Services.prefs.removeObserver(TELEMETRY_PREF, this._refresh);
     Services.prefs.removeObserver(FXA_USERNAME_PREF, this._refresh);
     Services.obs.removeObserver(this, SEARCH_ENGINE_OBSERVER_TOPIC);
     this.store.dispatch(ac.BroadcastToContent({type: at.SNIPPETS_RESET}));
   }
 
-  showFirefoxAccounts(browser) {
+  async showFirefoxAccounts(browser) {
+    const url = await fxAccounts.promiseAccountsSignUpURI("snippets");
     // We want to replace the current tab.
-    browser.loadURI("about:accounts?action=signup&entrypoint=snippets");
+    browser.loadURI(url);
   }
 
   onAction(action) {
     switch (action.type) {
       case at.INIT:
         this.init();
         break;
       case at.UNINIT:
--- a/browser/extensions/onboarding/locales/en-US/onboarding.properties
+++ b/browser/extensions/onboarding/locales/en-US/onboarding.properties
@@ -72,25 +72,21 @@ onboarding.notification.onboarding-tour-default-browser.message=It doesn’t take much to get the most from %1$S. Just set %1$S as your default browser and put control, customization, and protection on autopilot.
 onboarding.tour-sync2=Sync
 onboarding.tour-sync.title2=Pick up where you left off.
 onboarding.tour-sync.description2=Sync makes it easy to access bookmarks, passwords, and even open tabs on all your devices. Sync also gives you control of the types of information you want, and don’t want, to share.
 onboarding.tour-sync.logged-in.title=You’re signed in to Sync!
 # LOCALIZATION NOTE(onboarding.tour-sync.logged-in.description): %1$S is brandShortName.
 onboarding.tour-sync.logged-in.description=Sync works when you’re signed in to %1$S on more than one device. Have a mobile device? Install the %1$S app and sign in to get your bookmarks, history, and passwords on the go.
 # LOCALIZATION NOTE(onboarding.tour-sync.form.title): This string is displayed
 # as a title and followed by onboarding.tour-sync.form.description.
-# Your translation should be consistent with the form displayed in
-# about:accounts when signing up to Firefox Account.
 onboarding.tour-sync.form.title=Create a Firefox Account
 # LOCALIZATION NOTE(onboarding.tour-sync.form.description): The description
 # continues after onboarding.tour-sync.form.title to create a complete sentence.
 # If it's not possible for your locale, you can translate this string as
 # "Continue to Firefox Sync" instead.
-# Your translation should be consistent with the form displayed in
-# about:accounts when signing up to Firefox Account.
 onboarding.tour-sync.form.description=to continue to Firefox Sync
 onboarding.tour-sync.button=Next
 onboarding.tour-sync.email-input.placeholder=Email
 onboarding.notification.onboarding-tour-sync.title=Pick up where you left off.
 onboarding.notification.onboarding-tour-sync.message=Still sending yourself links to save or read on your phone? Do it the easy way: get Sync and have the things you save here show up on all of your devices.
 
 onboarding.tour-library=Library
 onboarding.tour-library.title=Keep it together.
--- a/docshell/test/browser/browser_bug1309900_crossProcessHistoryNavigation.js
+++ b/docshell/test/browser/browser_bug1309900_crossProcessHistoryNavigation.js
@@ -8,28 +8,28 @@ add_task(async function runTests() {
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:about");
 
   registerCleanupFunction(function() {
     gBrowser.removeTab(tab);
   });
 
   let browser = tab.linkedBrowser;
 
-  browser.loadURI("about:accounts");
+  browser.loadURI("about:healthreport");
   let href = await BrowserTestUtils.browserLoaded(browser);
-  is(href, "about:accounts", "Check about:accounts loaded");
+  is(href, "about:healthreport", "Check about:healthreport loaded");
 
   // Using a dummy onunload listener to disable the bfcache as that can prevent
   // the test browser load detection mechanism from working.
   browser.loadURI("data:text/html,<body%20onunload=''><iframe></iframe></body>");
   href = await BrowserTestUtils.browserLoaded(browser);
   is(href, "data:text/html,<body%20onunload=''><iframe></iframe></body>",
     "Check data URL loaded");
 
   browser.goBack();
   href = await BrowserTestUtils.browserLoaded(browser);
-  is(href, "about:accounts", "Check we've gone back to about:accounts");
+  is(href, "about:healthreport", "Check we've gone back to about:healthreport");
 
   browser.goForward();
   href = await BrowserTestUtils.browserLoaded(browser);
   is(href, "data:text/html,<body%20onunload=''><iframe></iframe></body>",
      "Check we've gone forward to data URL");
 });
--- a/services/fxaccounts/FxAccounts.jsm
+++ b/services/fxaccounts/FxAccounts.jsm
@@ -1292,26 +1292,39 @@ FxAccountsInternal.prototype = {
   },
 
   requiresHttps() {
     // Also used in FxAccountsOAuthGrantClient.jsm.
     let allowHttp = Services.prefs.getBoolPref("identity.fxaccounts.allowHttp", false);
     return allowHttp !== true;
   },
 
-  promiseAccountsSignUpURI() {
-    return FxAccountsConfig.promiseAccountsSignUpURI();
+  async promiseAccountsSignUpURI(entrypoint) {
+    const url = new URL((await FxAccountsConfig.promiseAccountsSignUpURI()));
+    if (entrypoint) {
+      url.searchParams.append("entrypoint", entrypoint);
+    }
+    return url.href;
   },
 
-  promiseAccountsSignInURI() {
-    return FxAccountsConfig.promiseAccountsSignInURI();
+  async promiseAccountsSignInURI(entrypoint) {
+    const url = new URL((await FxAccountsConfig.promiseAccountsSignInURI()));
+    if (entrypoint) {
+      url.searchParams.append("entrypoint", entrypoint);
+    }
+    return url.href;
   },
 
-  promiseAccountsEmailURI() {
-    return FxAccountsConfig.promiseAccountsEmailURI();
+  async promiseAccountsEmailURI(email, entrypoint) {
+    const url = new URL((await FxAccountsConfig.promiseAccountsEmailURI()));
+    url.searchParams.append("email", email);
+    if (entrypoint) {
+      url.searchParams.append("entrypoint", entrypoint);
+    }
+    return url.href;
   },
 
   /**
    * Pull an URL defined in the user preferences, add the current UID and email
    * to the query string, add entrypoint and extra params to the query string if
    * requested.
    * @param {string} prefName The preference name from where to pull the URL to format.
    * @param {string} [entrypoint] "entrypoint" searchParam value.
@@ -1337,19 +1350,19 @@ FxAccountsInternal.prototype = {
         url.searchParams.append(k, v);
       }
     }
     return this.currentAccountState.resolve(url.href);
   },
 
   // Returns a promise that resolves with the URL to use to force a re-signin
   // of the current account.
-  async promiseAccountsForceSigninURI() {
+  async promiseAccountsForceSigninURI(entrypoint) {
     await FxAccountsConfig.ensureConfigured();
-    return this._formatPrefURL("identity.fxaccounts.remote.force_auth.uri");
+    return this._formatPrefURL("identity.fxaccounts.remote.force_auth.uri", entrypoint);
   },
 
   // Returns a promise that resolves with the URL to use to change
   // the current account's profile image.
   // if settingToEdit is set, the profile page should hightlight that setting
   // for the user to edit.
   async promiseAccountsChangeProfileURI(entrypoint, settingToEdit = null) {
     let extraParams;
--- a/services/fxaccounts/FxAccountsConfig.jsm
+++ b/services/fxaccounts/FxAccountsConfig.jsm
@@ -28,44 +28,37 @@ const CONFIG_PREFS = [
   "identity.fxaccounts.remote.signup.uri",
   "identity.fxaccounts.remote.signin.uri",
   "identity.fxaccounts.remote.email.uri",
   "identity.fxaccounts.remote.force_auth.uri",
 ];
 
 this.FxAccountsConfig = {
 
-  // Returns a promise that resolves with the URI of the remote UI flows.
-  async promiseAccountsSignUpURI() {
+  async _getPrefURL(prefName) {
     await this.ensureConfigured();
-    let url = Services.urlFormatter.formatURLPref("identity.fxaccounts.remote.signup.uri");
+    let url = Services.urlFormatter.formatURLPref(prefName);
     if (fxAccounts.requiresHttps() && !/^https:/.test(url)) { // Comment to un-break emacs js-mode highlighting
       throw new Error("Firefox Accounts server must use HTTPS");
     }
     return url;
   },
 
   // Returns a promise that resolves with the URI of the remote UI flows.
-  async promiseAccountsSignInURI() {
-    await this.ensureConfigured();
-    let url = Services.urlFormatter.formatURLPref("identity.fxaccounts.remote.signin.uri");
-    if (fxAccounts.requiresHttps() && !/^https:/.test(url)) { // Comment to un-break emacs js-mode highlighting
-      throw new Error("Firefox Accounts server must use HTTPS");
-    }
-    return url;
+  promiseAccountsSignUpURI() {
+    return this._getPrefURL("identity.fxaccounts.remote.signup.uri");
   },
 
   // Returns a promise that resolves with the URI of the remote UI flows.
-  async promiseAccountsEmailURI() {
-    await this.ensureConfigured();
-    let url = Services.urlFormatter.formatURLPref("identity.fxaccounts.remote.email.uri");
-    if (fxAccounts.requiresHttps() && !/^https:/.test(url)) { // Comment to un-break emacs js-mode highlighting
-      throw new Error("Firefox Accounts server must use HTTPS");
-    }
-    return url;
+  promiseAccountsSignInURI() {
+    return this._getPrefURL("identity.fxaccounts.remote.signin.uri");
+  },
+
+  promiseAccountsEmailURI() {
+    return this._getPrefURL("identity.fxaccounts.remote.email.uri");
   },
 
   resetConfigURLs() {
     let autoconfigURL = this.getAutoConfigURL();
     if (!autoconfigURL) {
       return;
     }
     // They have the autoconfig uri pref set, so we clear all the prefs that we