Bug 1448918 - Create about:welcome page in preparation for firstrun migration. r?dmose draft
authorErica Wright <ewright@mozilla.com>
Mon, 23 Apr 2018 15:47:57 -0400
changeset 793870 b5ee5ca3884739fbf1f04bca61090d603386f09b
parent 793867 35a563bca0998b6d478368208b5ea8feca790f2d
push id109518
push userbmo:ewright@mozilla.com
push dateThu, 10 May 2018 21:33:20 +0000
reviewersdmose
bugs1448918
milestone62.0a1
Bug 1448918 - Create about:welcome page in preparation for firstrun migration. r?dmose MozReview-Commit-ID: L34uRsOeziS
browser/base/content/browser.js
browser/base/content/tabbrowser.js
browser/base/content/utilityOverlay.js
browser/components/about/AboutRedirector.cpp
browser/components/build/nsModule.cpp
browser/extensions/onboarding/OnboardingTelemetry.jsm
browser/extensions/onboarding/README.md
browser/extensions/onboarding/content/onboarding.js
browser/extensions/onboarding/data_events.md
browser/extensions/onboarding/jar.mn
browser/modules/AboutNewTab.jsm
modules/libpref/init/all.js
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -310,17 +310,18 @@ Object.defineProperty(this, "AddonManage
 
 
 var gInitialPages = [
   "about:blank",
   "about:newtab",
   "about:home",
   "about:privatebrowsing",
   "about:welcomeback",
-  "about:sessionrestore"
+  "about:sessionrestore",
+  "about:welcome"
 ];
 
 function isInitialPage(url) {
   return gInitialPages.includes(url) || url == BROWSER_NEW_TAB_URL;
 }
 
 function* browserWindows() {
   let windows = Services.wm.getEnumerator("navigator:browser");
@@ -1247,17 +1248,17 @@ var gBrowserInit = {
       remoteType, sameProcessAsFrameLoader
     });
 
     BrowserSearch.initPlaceHolder();
 
     // Hack to ensure that the about:home favicon is loaded
     // instantaneously, to avoid flickering and improve perceived performance.
     this._callWithURIToLoad(uriToLoad => {
-      if (uriToLoad == "about:home") {
+      if (uriToLoad == "about:home" || uriToLoad == "about:newtab" || uriToLoad == "about:welcome") {
         gBrowser.setIcon(gBrowser.selectedTab, "chrome://branding/content/icon32.png");
       } else if (uriToLoad == "about:privatebrowsing") {
         gBrowser.setIcon(gBrowser.selectedTab, "chrome://browser/skin/privatebrowsing/favicon.svg");
       }
     });
 
     this._setInitialFocus();
 
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -2436,19 +2436,19 @@ window._gBrowser = {
         this._tabFilters.delete(t);
         this._tabListeners.delete(t);
         let notificationbox = this.getNotificationBox(t.linkedBrowser);
         notificationbox.remove();
       }
       throw e;
     }
 
-    // Hack to ensure that the about:newtab favicon is loaded
+    // Hack to ensure that the about:newtab, and about:welcome favicon is loaded
     // instantaneously, to avoid flickering and improve perceived performance.
-    if (aURI == "about:newtab") {
+    if (aURI == "about:newtab" || aURI == "about:home" || aURI == "about:welcome") {
       this.setIcon(t, "chrome://branding/content/icon32.png");
     } else if (aURI == "about:privatebrowsing") {
       this.setIcon(t, "chrome://browser/skin/privatebrowsing/favicon.svg");
     }
 
     // Dispatch a new tab notification.  We do this once we're
     // entirely done, so that things are in a consistent state
     // even if the event listener opens or closes tabs.
@@ -4455,23 +4455,24 @@ class TabProgressListener {
             URLBarSetURI();
           }
         } else if (isSuccessful) {
           this.mBrowser.urlbarChangeTracker.finishedLoad();
         }
 
         // Ignore initial about:blank to prevent flickering.
         if (!this.mBrowser.mIconURL && !ignoreBlank) {
-          // Don't switch to the default icon on about:home or about:newtab,
-          // since these pages get their favicon set in browser code to
-          // improve perceived performance.
+          // Don't switch to the default icon on about:home, about:newtab,
+          // about:privatebrowsing, or about:welcome since these pages get
+          // their favicon set in browser code to improve perceived performance.
           let isNewTab = originalLocation &&
-            (originalLocation.spec == "about:newtab" ||
+             (originalLocation.spec == "about:newtab" ||
               originalLocation.spec == "about:privatebrowsing" ||
-              originalLocation.spec == "about:home");
+              originalLocation.spec == "about:home" ||
+              originalLocation.spec == "about:welcome");
           if (!isNewTab) {
             gBrowser.useDefaultIcon(this.mTab);
           }
         }
       }
 
       // For keyword URIs clear the user typed value since they will be changed into real URIs
       if (location.scheme == "keyword")
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -39,16 +39,17 @@ var TAB_DROP_TYPE = "application/x-moz-t
 var gBidiUI = false;
 
 /**
  * Determines whether the given url is considered a special URL for new tabs.
  */
 function isBlankPageURL(aURL) {
   return aURL == "about:blank" ||
          aURL == "about:home" ||
+         aURL == "about:welcome" ||
          aURL == BROWSER_NEW_TAB_URL;
 }
 
 function getBrowserURL() {
   return "chrome://browser/content/browser.xul";
 }
 
 function getTopWin(skipPopups) {
--- a/browser/components/about/AboutRedirector.cpp
+++ b/browser/components/about/AboutRedirector.cpp
@@ -81,16 +81,20 @@ static const RedirEntry kRedirMap[] = {
     nsIAboutModule::ALLOW_SCRIPT |
     nsIAboutModule::HIDE_FROM_ABOUTABOUT },
   { "welcomeback", "chrome://browser/content/aboutWelcomeBack.xhtml",
     nsIAboutModule::ALLOW_SCRIPT |
     nsIAboutModule::HIDE_FROM_ABOUTABOUT },
   // Actual activity stream URL for home and newtab are set in channel creation
   { "home", "about:blank", ACTIVITY_STREAM_FLAGS },
   { "newtab", "about:blank", ACTIVITY_STREAM_FLAGS },
+  { "welcome", "about:blank",
+    nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
+    nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
+    nsIAboutModule::ALLOW_SCRIPT },
   { "library", "chrome://browser/content/aboutLibrary.xhtml",
     nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
     nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT },
   { "preferences", "chrome://browser/content/preferences/in-content/preferences.xul",
     nsIAboutModule::ALLOW_SCRIPT },
   { "downloads", "chrome://browser/content/downloads/contentAreaDownloadsView.xul",
     nsIAboutModule::ALLOW_SCRIPT },
   { "reader", "chrome://global/content/reader/aboutReader.html",
@@ -143,19 +147,20 @@ AboutRedirector::NewChannel(nsIURI* aURI
     sNTPEnabledCacheInited = true;
   }
 
   for (auto & redir : kRedirMap) {
     if (!strcmp(path.get(), redir.id)) {
       nsAutoCString url;
 
       // Let the aboutNewTabService decide where to redirect for about:home and
-      // enabled about:newtab. Disabled about:newtab page uses fallback.
+      // enabled about:newtab. Disabledx about:newtab page uses fallback.
       if (path.EqualsLiteral("home") ||
-          (sNewTabPageEnabled && path.EqualsLiteral("newtab"))) {
+          (sNewTabPageEnabled && path.EqualsLiteral("newtab")) ||
+          path.EqualsLiteral("welcome")) {
         nsCOMPtr<nsIAboutNewTabService> aboutNewTabService =
           do_GetService("@mozilla.org/browser/aboutnewtab-service;1", &rv);
         NS_ENSURE_SUCCESS(rv, rv);
         rv = aboutNewTabService->GetDefaultURL(url);
         NS_ENSURE_SUCCESS(rv, rv);
       }
       // fall back to the specified url in the map
       if (url.IsEmpty()) {
--- a/browser/components/build/nsModule.cpp
+++ b/browser/components/build/nsModule.cpp
@@ -96,16 +96,17 @@ static const mozilla::Module::ContractID
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "welcomeback", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "home", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "newtab", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "library", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "preferences", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "downloads", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "reader", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "restartrequired", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
+    { NS_ABOUT_MODULE_CONTRACTID_PREFIX "welcome", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
 #if defined(XP_WIN)
     { NS_IEHISTORYENUMERATOR_CONTRACTID, &kNS_WINIEHISTORYENUMERATOR_CID },
 #elif defined(XP_MACOSX)
     { NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID },
 #endif
     { nullptr }
 };
 
--- a/browser/extensions/onboarding/OnboardingTelemetry.jsm
+++ b/browser/extensions/onboarding/OnboardingTelemetry.jsm
@@ -42,17 +42,17 @@ function isMinusOne(num) {
 function isValidCategory(category) {
   return ["logo-interactions", "onboarding-interactions",
     "overlay-interactions", "notification-interactions"]
     .includes(category);
 }
 
 // Validate the page value is within the list
 function isValidPage(page) {
-  return ["about:newtab", "about:home"].includes(page);
+    return ["about:newtab", "about:home", "about:welcome"].includes(page);
 }
 
 // Validate the tour_type value is within the list
 function isValidTourType(type) {
   return ["new", "update"].includes(type);
 }
 
 // Validate the bubble state value is within the list
--- a/browser/extensions/onboarding/README.md
+++ b/browser/extensions/onboarding/README.md
@@ -11,29 +11,29 @@ browser.onboarding.disabled = false
 browser.onboarding.tour-set = "new" // for new user tour, or "update" for update user tour
 ```
 And make sure the value of `browser.onboarding.tourset-verion` and `browser.onboarding.seen-tourset-verion` are the same.
 
 ## How to show the onboarding notification
 
 Besides above settings, notification will wait 5 minutes before showing the first notification on a new profile or the updated user profile (to not put too much information to the user at once).
 
-To manually remove the mute duration, set pref `browser.onboarding.notification.mute-duration-on-first-session-ms` to `0` and notification will be shown at the next time you open `about:home` or `about:newtab`.
+To manually remove the mute duration, set pref `browser.onboarding.notification.mute-duration-on-first-session-ms` to `0` and notification will be shown at the next time you open `about:home`, `about:newtab`, or `about:welcome`.
 
 ## How to show the snippets
 
 Snippets (the remote notification that handled by activity stream) will only be shown after onboarding notifications are all done. You can set preference `browser.onboarding.notification.finished` to `true` to disable onboarding notification and accept snippets right away.
 
 ## Architecture
 
 ![](https://i.imgur.com/7RK89Zw.png)
 
 During booting from `bootstrap.js`, `OnboardingTourType.jsm` will check the onboarding tour type (`new` and `update` are supported types) and set required initial states into preferences.
 
-Everytime `about:home` or `about:newtab` page is opened, `onboarding.js` is injected into that page via [frame scripts](https://developer.mozilla.org/en-US/Firefox/Multiprocess_Firefox/Message_Manager/Communicating_with_frame_scripts).
+Everytime `about:home`, `about:newtab`, or `about:welcome` page is opened, `onboarding.js` is injected into that page via [frame scripts](https://developer.mozilla.org/en-US/Firefox/Multiprocess_Firefox/Message_Manager/Communicating_with_frame_scripts).
 
 Then in `onboarding.js`, all tours are defined inside of `onboardingTourset` dictionary. `getTourIDList` function will load tours from proper preferences. (Check `How to change the order of tours` section for more detail).
 
 When user clicks the action button in each tour, We use [UITour](http://bedrock.readthedocs.io/en/latest/uitour.html) to highlight the correspondent browser UI element. The UITour client is bundled in onboarding addon via `jar.mn`.
 
 ## Landing rules
 
 We would apply some rules:
--- a/browser/extensions/onboarding/content/onboarding.js
+++ b/browser/extensions/onboarding/content/onboarding.js
@@ -6,27 +6,28 @@
 
 "use strict";
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.defineModuleGetter(this, "Onboarding", "resource://onboarding/Onboarding.jsm");
 
 const ABOUT_HOME_URL = "about:home";
 const ABOUT_NEWTAB_URL = "about:newtab";
+const ABOUT_WELCOME_URL = "about:welcome";
 
 // Load onboarding module only when we enable it.
 if (Services.prefs.getBoolPref("browser.onboarding.enabled", false)) {
   addEventListener("load", function onLoad(evt) {
     if (!content || evt.target != content.document) {
       return;
     }
 
     let window = evt.target.defaultView;
     let location = window.location.href;
-    if (location == ABOUT_NEWTAB_URL || location == ABOUT_HOME_URL) {
+    if (location == ABOUT_NEWTAB_URL || location == ABOUT_HOME_URL || location == ABOUT_WELCOME_URL) {
       // We just want to run tests as quickly as possible
       // so in the automation test, we don't do `requestIdleCallback`.
       if (Cu.isInAutomation) {
         new Onboarding(this, window);
         return;
       }
       window.requestIdleCallback(() => {
         new Onboarding(this, window);
--- a/browser/extensions/onboarding/data_events.md
+++ b/browser/extensions/onboarding/data_events.md
@@ -15,17 +15,17 @@ For reference, Onyx is a Mozilla owned s
 ```js
 {
   // These fields are sent from the client
   "addon_version": "1.0.0",
   "category": ["onboarding-interactions"|"overlay-interactions"|"notification-interactions"],
   "client_id": "374dc4d8-0cb2-4ac5-a3cf-c5a9bc3c602e",
   "locale": "en-US",
   "type": ["onboarding_session" | "overlay_session" | "notification_session"],
-  "page": ["about:newtab" | "about:home"],
+  "page": ["about:newtab" | "about:home" | "about:welcome"],
   "parent_session_id": "{45cddbeb-2bec-4f3a-bada-fb87d4b79a6c}",
   "root_session_id": "{45cddbeb-2bec-4f3a-bada-fb87d4b79a6c}",
   "session_begin": 1505440017018,
   "session_end": 1505440021992,
   "session_id": "{12dasd-213asda-213dkakj}",
   "tour_type" ["new" | "update"],
 
   // These fields are generated on the server
@@ -38,17 +38,17 @@ For reference, Onyx is a Mozilla owned s
 
 | KEY | DESCRIPTION | &nbsp; |
 |-----|-------------|:-----:|
 | `addon_version` | [Required] The version of the Onboarding addon. | :one:
 | `category` | [Required] Either ["", "overlay-interactions", "notification-interactions"] to identify which kind of the interaction | :one:
 | `client_id` | [Required] An identifier generated by [ClientID](https://github.com/mozilla/gecko-dev/blob/master/toolkit/modules/ClientID.jsm) module to provide an identifier for this device. This data is automatically appended by `ping-centre` module | :one:
 | `ip` | [Auto populated by Onyx] The IP address of the client. Onyx does use (with the permission) the IP address to infer user's geo-information so that it could prepare the corresponding tiles for the country she lives in. However, Ping-centre will NOT store IP address in the database, where only authorized Mozilla employees can access the telemetry data, and all the raw logs are being strictly managed by the Ops team and will expire according to the Mozilla's data retention policy.| :two:
 | `locale` | The browser chrome's language (e.g. en-US). | :two:
-| `page` | [Required] One of ["about:newtab", "about:home"]| :one:
+| `page` | [Required] One of ["about:newtab", "about:home", "about:welcome"]| :one:
 | `parent_session_id` | [Required] The unique identifier generated by `gUUIDGenerator` service to identify this event belongs to which parent session. Events happen upon overlay will have the `overlay session uuid` as its `parent_session_id`. Events happen upon notification will have the `notification session uuid` as its `parent_session_id`. | :one:
 | `root_session_id` | [Required] The unique identifier generated by `gUUIDGenerator` service to identify this event belongs to which root session. Every event will have the same `onboarding session uuid` as its `root_session_id` when interact in the same tab. | :one:
 | `session_begin` | [Required] Timestamp in (integer) milliseconds when onboarding/overlay/notification becoming visible. | :one:
 | `session_end` | [Required] Timestamp in (integer) milliseconds when onboarding/overlay/notification losing focus. | :one:
 | `session_id` | [Required] The unique identifier generated by `gUUIDGenerator` service to identify the specific user session. We will log different uuid when onboarding is inited/when the overlay is opened/when notification is shown. | :one:
 | `tour_type` | [Required] One of ["new", "update"] indicates the user is a `new` user or the `update` user upgrade from the older version | :one:
 | `type` | [Required] The type of event. Allowed event strings are defined in the below section | :one:
 | `ua` | [Auto populated by Onyx] The user agent string. | :two:
@@ -61,17 +61,17 @@ For reference, Onyx is a Mozilla owned s
   "addon_version": "1.0.0",
   "bubble_state": ["bubble" | "dot" | "hide"],
   "category": ["logo-interactions"|"overlay-interactions"|"notification-interactions"],
   "client_id": "374dc4d8-0cb2-4ac5-a3cf-c5a9bc3c602e",
   "locale": "en-US",
   "logo_state": ["logo" | "watermark"],
   "notification_impression": [1-8],
   "notification_state": ["show" | "hide" | "finished"],
-  "page": ["about:newtab" | "about:home"],
+  "page": ["about:newtab" | "about:home" | "about:welcome"],
   "parent_session_id": "{45cddbeb-2bec-4f3a-bada-fb87d4b79a6c}",
   "root_session_id": "{45cddbeb-2bec-4f3a-bada-fb87d4b79a6c}",
   "current_tour_id": ["onboarding-tour-private-browsing" | "onboarding-tour-addons"|...], // tour ids defined in 'onboardingTourset'
   "target_tour_id": ["onboarding-tour-private-browsing" | "onboarding-tour-addons"|...], // tour ids defined in 'onboardingTourset',
   "tour_id": ["onboarding-tour-private-browsing" | "onboarding-tour-addons"|...], // tour ids defined in 'onboardingTourset'
   "timestamp": 1505440017019,
   "tour_type" ["new" | "update"],
   "type": ["notification-cta-click" | "overlay-cta-click" | "overlay-nav-click" | "overlay-skip-tour"...],
--- a/browser/extensions/onboarding/jar.mn
+++ b/browser/extensions/onboarding/jar.mn
@@ -1,14 +1,14 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # 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/.
 
 [features/onboarding@mozilla.org] chrome.jar:
-  # resource://onboarding/ is referenced in about:home and about:newtab,
+  # resource://onboarding/ is referenced in about:home about:newtab and about:welcome,
   # so make it content-accessible.
 % resource onboarding %content/ contentaccessible=yes
   content/ (content/*)
   # Package UITour-lib.js in here rather than under
   # /browser/components/uitour to avoid "unreferenced files" error when
   # Onboarding extension is not built.
   content/lib/UITour-lib.js (/browser/components/uitour/UITour-lib.js)
   content/modules/ (*.jsm)
--- a/browser/modules/AboutNewTab.jsm
+++ b/browser/modules/AboutNewTab.jsm
@@ -21,17 +21,17 @@ var AboutNewTab = {
   pageListener: null,
 
   isOverridden: false,
 
   init(pageListener) {
     if (this.isOverridden) {
       return;
     }
-    this.pageListener = pageListener || new RemotePages(["about:home", "about:newtab"]);
+    this.pageListener = pageListener || new RemotePages(["about:home", "about:newtab", "about:welcome"]);
     this.pageListener.addMessageListener("NewTab:Customize", this.customize);
     this.pageListener.addMessageListener("NewTab:MaybeShowMigrateMessage",
       this.maybeShowMigrateMessage);
   },
 
   maybeShowMigrateMessage({ target }) {
     AutoMigrate.shouldShowMigratePrompt(target.browser).then((prompt) => {
       if (prompt) {
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -2468,17 +2468,18 @@ pref("security.directory",              
 pref("security.dialog_enable_delay", 1000);
 pref("security.notification_enable_delay", 500);
 
 pref("security.csp.enable", true);
 pref("security.csp.experimentalEnabled", false);
 pref("security.csp.enableStrictDynamic", true);
 
 #if defined(DEBUG) && !defined(ANDROID)
-pref("csp.content_privileged_about_uris_without_csp", "blank,home,newtab,printpreview,srcdoc,studies");
+// about:welcome has been added until Bug 1448359 is fixed at which time home, newtab, and welcome will all be removed.
+pref("csp.content_privileged_about_uris_without_csp", "blank,home,newtab,printpreview,srcdoc,studies,welcome");
 #endif
 
 #ifdef NIGHTLY_BUILD
 pref("security.csp.enable_violation_events", true);
 #else
 pref("security.csp.enable_violation_events", false);
 #endif