diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index fdb2541f7603..426d38b23a16 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -237,8 +237,6 @@ pref("browser.startup.homepage", "about:home"); // Whether we should skip the homepage when opening the first-run page pref("browser.startup.firstrunSkipsHomepage", true); -pref("browser.dedicatedprofile.welcome.accounts.endpoint", "https://accounts.firefox.com/"); - // Show an about:blank window as early as possible for quick startup feedback. // Held to nightly on Linux due to bug 1450626. // Disabled on Mac because the bouncing dock icon already provides feedback. diff --git a/browser/base/content/newInstallPage.js b/browser/base/content/newInstallPage.js index 11b78470e3db..c2d86eafc1e1 100644 --- a/browser/base/content/newInstallPage.js +++ b/browser/base/content/newInstallPage.js @@ -2,12 +2,13 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* global RPMGetUpdateChannel, RPMGetFxAccountsEndpoint */ + const PARAMS = new URL(location).searchParams; const ENTRYPOINT = "new-install-page"; -const SOURCE = `new-install-page-${PARAMS.get("channel")}`; +const SOURCE = `new-install-page-${RPMGetUpdateChannel()}`; const CAMPAIGN = "dedicated-profiles"; const ENDPOINT = PARAMS.get("endpoint"); -const CONTEXT = "fx_desktop_v3"; function appendAccountsParams(url) { url.searchParams.set("entrypoint", ENTRYPOINT); @@ -24,7 +25,8 @@ function appendParams(url, params) { } async function requestFlowMetrics() { - let requestURL = new URL(`${ENDPOINT}metrics-flow`); + let requestURL = new URL(await endpoint); + requestURL.pathname = "metrics-flow"; appendParams(requestURL, { "form_type": "email", }); @@ -47,11 +49,9 @@ async function submitForm(event) { let { flowId, flowBeginTime } = await metrics; - let requestURL = new URL(ENDPOINT); + let requestURL = new URL(await endpoint); appendParams(requestURL, { - "service": "sync", "action": "email", - "context": CONTEXT, "utm_campaign": CAMPAIGN, "email": input.value, "flow_id": flowId, @@ -61,6 +61,8 @@ async function submitForm(event) { window.open(requestURL, "_blank", "noopener"); } +const endpoint = RPMGetFxAccountsEndpoint(ENTRYPOINT); + // This must come before the CSP is set or it will be blocked. const metrics = requestFlowMetrics(); diff --git a/browser/components/nsBrowserContentHandler.js b/browser/components/nsBrowserContentHandler.js index 6bc7f651fdd1..ecb08a61cd2f 100644 --- a/browser/components/nsBrowserContentHandler.js +++ b/browser/components/nsBrowserContentHandler.js @@ -15,6 +15,7 @@ XPCOMUtils.defineLazyModuleGetters(this, { SessionStartup: "resource:///modules/sessionstore/SessionStartup.jsm", ShellService: "resource:///modules/ShellService.jsm", UpdatePing: "resource://gre/modules/UpdatePing.jsm", + RemotePages: "resource://gre/modules/remotepagemanager/RemotePageManagerParent.jsm", }); XPCOMUtils.defineLazyServiceGetter(this, "WindowsUIUtils", "@mozilla.org/windows-ui-utils;1", "nsIWindowsUIUtils"); @@ -23,6 +24,8 @@ XPCOMUtils.defineLazyGetter(this, "gSystemPrincipal", () => Services.scriptSecurityManager.getSystemPrincipal()); XPCOMUtils.defineLazyGlobalGetters(this, [URL]); +const NEWINSTALL_PAGE = "about:newinstall"; + function shouldLoadURI(aURI) { if (aURI && !aURI.schemeIs("chrome")) return true; @@ -60,12 +63,14 @@ function resolveURIInternal(aCmdLine, aArgument) { return uri; } +let gRemoteInstallPage = null; + function getNewInstallPage() { - let url = new URL("about:newinstall"); - let endpoint = Services.prefs.getCharPref("browser.dedicatedprofile.welcome.accounts.endpoint"); - url.searchParams.set("endpoint", endpoint); - url.searchParams.set("channel", AppConstants.MOZ_UPDATE_CHANNEL); - return url.toString(); + if (!gRemoteInstallPage) { + gRemoteInstallPage = new RemotePages(NEWINSTALL_PAGE); + } + + return NEWINSTALL_PAGE; } var gFirstWindow = false; diff --git a/toolkit/components/remotepagemanager/MessagePort.jsm b/toolkit/components/remotepagemanager/MessagePort.jsm index ba2f7ee4d839..da72b1549856 100644 --- a/toolkit/components/remotepagemanager/MessagePort.jsm +++ b/toolkit/components/remotepagemanager/MessagePort.jsm @@ -13,6 +13,8 @@ ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils", "resource://gre/modules/PrivateBrowsingUtils.jsm"); ChromeUtils.defineModuleGetter(this, "PromiseUtils", "resource://gre/modules/PromiseUtils.jsm"); +ChromeUtils.defineModuleGetter(this, "UpdateUtils", + "resource://gre/modules/UpdateUtils.jsm"); /* * Used for all kinds of permissions checks which requires explicit @@ -33,6 +35,10 @@ let RPMAccessManager = { "app.support.baseURL"], "isWindowPrivate": ["yes"], }, + "about:newinstall": { + "getUpdateChannel": ["yes"], + "getFxAccountsEndpoint": ["yes"], + }, }, checkAllowAccess(aPrincipal, aFeature, aValue) { @@ -163,7 +169,7 @@ class MessagePort { // once the other process has responded to the request or some error occurs. sendRequest(name, data = null) { if (this.destroyed) { - return Promise.reject(new Error("Message port has been destroyed")); + return this.window.Promise.reject(new Error("Message port has been destroyed")); } let deferred = PromiseUtils.defer(); @@ -176,7 +182,7 @@ class MessagePort { data, }); - return deferred.promise; + return this.wrapPromise(deferred.promise); } // Handles an IPC message to perform a request of some kind. @@ -291,6 +297,10 @@ class MessagePort { this.requests = []; } + wrapPromise(promise) { + return new this.window.Promise((resolve, reject) => promise.then(resolve, reject)); + } + getBoolPref(aPref) { let principal = this.window.document.nodePrincipal; if (!RPMAccessManager.checkAllowAccess(principal, "getBoolPref", aPref)) { @@ -300,11 +310,7 @@ class MessagePort { } setBoolPref(aPref, aVal) { - return new this.window.Promise(function(resolve) { - AsyncPrefs.set(aPref, aVal).then(function() { - resolve(); - }); - }); + return this.wrapPromise(AsyncPrefs.set(aPref, aVal)); } getFormatURLPref(aFormatURL) { @@ -322,4 +328,21 @@ class MessagePort { } return PrivateBrowsingUtils.isContentWindowPrivate(this.window); } + + getUpdateChannel() { + let principal = this.window.document.nodePrincipal; + if (!RPMAccessManager.checkAllowAccess(principal, "getUpdateChannel", "yes")) { + throw new Error("RPMAccessManager does not allow access to getUpdateChannel"); + } + return UpdateUtils.UpdateChannel; + } + + getFxAccountsEndpoint(aEntrypoint) { + let principal = this.window.document.nodePrincipal; + if (!RPMAccessManager.checkAllowAccess(principal, "getFxAccountsEndpoint", "yes")) { + throw new Error("RPMAccessManager does not allow access to getFxAccountsEndpoint"); + } + + return this.sendRequest("FxAccountsEndpoint", aEntrypoint); + } } diff --git a/toolkit/components/remotepagemanager/RemotePageManagerChild.jsm b/toolkit/components/remotepagemanager/RemotePageManagerChild.jsm index 0b359456ba3a..f6abd1714e5d 100644 --- a/toolkit/components/remotepagemanager/RemotePageManagerChild.jsm +++ b/toolkit/components/remotepagemanager/RemotePageManagerChild.jsm @@ -41,6 +41,12 @@ class ChildMessagePort extends MessagePort { Cu.exportFunction(this.isWindowPrivate.bind(this), window, { defineAs: "RPMIsWindowPrivate", }); + Cu.exportFunction(this.getUpdateChannel.bind(this), window, { + defineAs: "RPMGetUpdateChannel", + }); + Cu.exportFunction(this.getFxAccountsEndpoint.bind(this), window, { + defineAs: "RPMGetFxAccountsEndpoint", + }); // Send a message for load events let loadListener = () => { diff --git a/toolkit/components/remotepagemanager/RemotePageManagerParent.jsm b/toolkit/components/remotepagemanager/RemotePageManagerParent.jsm index f42e5ffbf589..f18a31a2d296 100644 --- a/toolkit/components/remotepagemanager/RemotePageManagerParent.jsm +++ b/toolkit/components/remotepagemanager/RemotePageManagerParent.jsm @@ -21,6 +21,8 @@ var EXPORTED_SYMBOLS = ["RemotePages", "RemotePageManager"]; const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); const {MessageListener, MessagePort} = ChromeUtils.import("resource://gre/modules/remotepagemanager/MessagePort.jsm"); +ChromeUtils.defineModuleGetter(this, "FxAccounts", + "resource://gre/modules/FxAccounts.jsm"); /** * Creates a RemotePages object which listens for new remote pages of some @@ -236,6 +238,10 @@ class ChromeMessagePort extends MessagePort { // Called when the content process is requesting some data. async handleRequest(name, data) { + if (name == "FxAccountsEndpoint") { + return FxAccounts.config.promiseEmailFirstURI(data); + } + throw new Error(`Unknown request ${name}.`); }