[tbb-commits] [tor-browser] 21/311: Bug 1745026 - Part 2: Update messages and UI by Nimbus. r=adw, flod, a=dsmith

gitolite role git at cupani.torproject.org
Tue Apr 26 15:27:01 UTC 2022


This is an automated email from the git hooks/post-receive script.

pierov pushed a commit to branch geckoview-99.0.1-11.0-1
in repository tor-browser.

commit df422c169ae41f44cb2a5df6534073a5830d7df6
Author: Daisuke Akatsuka <daisuke at birchill.co.jp>
AuthorDate: Fri Jan 7 21:33:03 2022 +0000

    Bug 1745026 - Part 2: Update messages and UI by Nimbus. r=adw,flod, a=dsmith
    
    Differential Revision: https://phabricator.services.mozilla.com/D133993
---
 browser/components/urlbar/UrlbarPrefs.jsm          |   3 +
 browser/components/urlbar/UrlbarQuickSuggest.jsm   |  11 +-
 .../components/urlbar/content/firefoxSuggest.ftl   |  94 ++++-
 .../urlbar/content/quicksuggestOnboarding.css      | 152 ++++++--
 .../urlbar/content/quicksuggestOnboarding.html     |  51 ++-
 .../urlbar/content/quicksuggestOnboarding.js       | 181 ++++++++-
 .../browser/browser_quicksuggest_configuration.js  |  84 ----
 .../browser_quicksuggest_onboardingDialog.js       | 421 ++++++++++++++++++++-
 toolkit/components/nimbus/FeatureManifest.yaml     |   4 +
 9 files changed, 817 insertions(+), 184 deletions(-)

diff --git a/browser/components/urlbar/UrlbarPrefs.jsm b/browser/components/urlbar/UrlbarPrefs.jsm
index 1f31ed92de7d4..93fbb4f9cc297 100644
--- a/browser/components/urlbar/UrlbarPrefs.jsm
+++ b/browser/components/urlbar/UrlbarPrefs.jsm
@@ -247,6 +247,9 @@ const PREF_URLBAR_DEFAULTS = new Map([
   // Whether the user has opted in to data collection for quick suggest.
   ["quicksuggest.dataCollection.enabled", false],
 
+  // The version of dialog user saw.
+  ["quicksuggest.onboardingDialogVersion", 0],
+
   // Whether to show the quick suggest onboarding dialog.
   ["quicksuggest.shouldShowOnboardingDialog", true],
 
diff --git a/browser/components/urlbar/UrlbarQuickSuggest.jsm b/browser/components/urlbar/UrlbarQuickSuggest.jsm
index d32a872cf8154..0d448653563f7 100644
--- a/browser/components/urlbar/UrlbarQuickSuggest.jsm
+++ b/browser/components/urlbar/UrlbarQuickSuggest.jsm
@@ -40,6 +40,8 @@ const NONSPONSORED_IAB_CATEGORIES = new Set(["5 - Education"]);
 const FEATURE_AVAILABLE = "quickSuggestEnabled";
 const SEEN_DIALOG_PREF = "quicksuggest.showedOnboardingDialog";
 const RESTARTS_PREF = "quicksuggest.seenRestarts";
+const DIALOG_VERSION_PREF = "quicksuggest.onboardingDialogVersion";
+const DIALOG_VARIATION_PREF = "quickSuggestOnboardingDialogVariation";
 
 // Values returned by the onboarding dialog depending on the user's response.
 // These values are used in telemetry events, so be careful about changing them.
@@ -255,12 +257,19 @@ class Suggestions {
     };
     win.addEventListener("keydown", keyListener, true);
 
-    let params = { choice: undefined };
+    let variationType;
+    try {
+      // An error happens if the pref is not in user prefs.
+      variationType = UrlbarPrefs.get(DIALOG_VARIATION_PREF).toLowerCase();
+    } catch (e) {}
+
+    let params = { choice: undefined, variationType };
     await win.gDialogBox.open(ONBOARDING_URI, params);
 
     win.removeEventListener("keydown", keyListener, true);
 
     UrlbarPrefs.set(SEEN_DIALOG_PREF, true);
+    UrlbarPrefs.set(DIALOG_VERSION_PREF, 1);
 
     // Record the user's opt-in choice on the user branch. This pref is sticky,
     // so it will retain its user-branch value regardless of what the particular
diff --git a/browser/components/urlbar/content/firefoxSuggest.ftl b/browser/components/urlbar/content/firefoxSuggest.ftl
index 712d89ce77065..15b9f4b9d6d3a 100644
--- a/browser/components/urlbar/content/firefoxSuggest.ftl
+++ b/browser/components/urlbar/content/firefoxSuggest.ftl
@@ -85,22 +85,80 @@ addressbar-firefox-suggest-info-sponsored = Based on your selection, you’ll re
 # Data collection: on
 addressbar-firefox-suggest-info-data = Based on your selection, you won’t receive suggestions from the web or sponsored sites. We will process your search query data to develop the { -firefox-suggest-brand-name } feature.
 
-## These strings are used in the introduction pane of the Firefox Suggest online
-## onboarding opt-in dialog.
-
-firefox-suggest-onboarding-introduction-title = Make sure you’ve got our newest search experience
-firefox-suggest-onboarding-introduction-button = Next
-
-## These strings are used in the main pane of the Firefox Suggest online
-## onboarding opt-in dialog. Options are displayed as radio buttons with a label
-## followed by a description.
-
-firefox-suggest-onboarding-main-title = We’re building a richer search experience
-firefox-suggest-onboarding-main-description = Finding the best of the web should be easier. Allowing { -vendor-short-name } to process your search queries will help develop our { -firefox-suggest-brand-name } feature, while keeping your privacy top of mind.
-firefox-suggest-onboarding-main-accept-option-label =
-    Allow improved search experience. <a data-l10n-name="firefox-suggest-onboarding-learn-more-link">Learn more</a>
-firefox-suggest-onboarding-main-accept-option-description = Include suggestions for a more curated web experience.
-firefox-suggest-onboarding-main-reject-option-label = Keep my default experience.
-firefox-suggest-onboarding-main-reject-option-description = Don’t allow search query processing.
+## Used as title on the introduction pane. The text can be formatted to span
+## multiple lines as needed (line breaks are significant).
+
+firefox-suggest-onboarding-introduction-title-1 =
+  Make sure you’ve got our latest
+  search experience
+firefox-suggest-onboarding-introduction-title-2 =
+  We’re building a better search experience —
+  one you can trust
+firefox-suggest-onboarding-introduction-title-3 =
+  We’re building a better way to find what
+  you’re looking for on the web
+firefox-suggest-onboarding-introduction-title-4 =
+  A faster search experience is in the works
+firefox-suggest-onboarding-introduction-title-5 =
+  Together, we can create the kind of search
+  experience the Internet deserves
+firefox-suggest-onboarding-introduction-title-6 =
+  Meet { -firefox-suggest-brand-name }, the next
+  evolution in search
+firefox-suggest-onboarding-introduction-title-7 =
+  Find the best of the web, faster.
+
+##
+
+firefox-suggest-onboarding-introduction-next-button-1 = Find out how
+firefox-suggest-onboarding-introduction-next-button-2 = Find out more
+
+## Used as title on the main pane. The text can be formatted to span
+## multiple lines as needed (line breaks are significant).
+
+firefox-suggest-onboarding-main-title-1 =
+  We’re building a richer search experience
+firefox-suggest-onboarding-main-title-2 =
+  Help us guide the way to the
+  best of the Internet
+firefox-suggest-onboarding-main-title-3 =
+  A richer, smarter search experience
+firefox-suggest-onboarding-main-title-4 =
+  Finding the best of the web, faster
+firefox-suggest-onboarding-main-title-5 =
+  We’re building a better search experience —
+  you can help
+firefox-suggest-onboarding-main-title-6 =
+  It’s time to think outside the search engine
+firefox-suggest-onboarding-main-title-7 =
+  We’re building a smarter search experience —
+  one you can trust
+firefox-suggest-onboarding-main-title-8 =
+  Finding the best of the web should be
+  simpler and more secure.
+
+##
+
+firefox-suggest-onboarding-main-description-1 = Allowing { -vendor-short-name } to process your search queries means you’re helping us create smarter, more relevant search suggestions. And, as always, we’ll keep your privacy top of mind.
+firefox-suggest-onboarding-main-description-2 = When you allow { -vendor-short-name } to process your search queries, you’re helping build a better { -firefox-suggest-brand-name } for everyone. And, as always, we’ll keep your privacy top of mind.
+firefox-suggest-onboarding-main-description-3 = What if your browser helped you zero in on what you’re actually looking for? Allowing { -vendor-short-name } to process your search queries helps us create more relevant search suggestions that still keep your privacy top of mind.
+firefox-suggest-onboarding-main-description-4 = You’re trying to get where you’re going on the web and get on with it. When you allow { -vendor-short-name } to process your search queries, we can help you get there faster—while keeping your privacy top of mind.
+firefox-suggest-onboarding-main-description-5 = Allowing { -vendor-short-name } to process your search queries will help us create more relevant suggestions for everyone. And, as always, we’ll keep your privacy top of mind.
+firefox-suggest-onboarding-main-description-6 = Allowing { -vendor-short-name } to process your search queries will help us create more relevant search suggestions. We’re building { -firefox-suggest-brand-name } to help you get where you’re going on the Internet while keeping your privacy in mind.
+firefox-suggest-onboarding-main-description-7 = Allowing { -vendor-short-name } to process your search queries helps us create more relevant search suggestions.
+firefox-suggest-onboarding-main-description-8 = Allowing { -vendor-short-name } to process your search queries helps us provide more relevant search suggestions. We don’t use this data to profile you on the web.
+
+firefox-suggest-onboarding-main-privacy-first = No user profiling. Privacy-first, always.
+
+firefox-suggest-onboarding-main-accept-option-label = Allow. <a data-l10n-name="learn-more-link">Learn more</a>
+
+firefox-suggest-onboarding-main-accept-option-description-1 = Help improve the { -firefox-suggest-brand-name } feature with more relevant suggestions. Your search queries will be processed.
+firefox-suggest-onboarding-main-accept-option-description-2 = Recommended for people who support improving the { -firefox-suggest-brand-name } feature. 
Your search queries will be processed.
+
+firefox-suggest-onboarding-main-reject-option-label = Don’t allow.
+
+firefox-suggest-onboarding-main-reject-option-description-1 = Keep the default { -firefox-suggest-brand-name } experience with the strictest data-sharing controls.
+firefox-suggest-onboarding-main-reject-option-description-2 = Recommended for people who prefer the strictest data-sharing controls. Keep the default experience.
+
 firefox-suggest-onboarding-main-submit-button = Save preferences
-firefox-suggest-onboarding-main-skip-link = Skip action
+firefox-suggest-onboarding-main-skip-link = Not now
diff --git a/browser/components/urlbar/content/quicksuggestOnboarding.css b/browser/components/urlbar/content/quicksuggestOnboarding.css
index f48712037970a..5eb923f64f5d5 100644
--- a/browser/components/urlbar/content/quicksuggestOnboarding.css
+++ b/browser/components/urlbar/content/quicksuggestOnboarding.css
@@ -8,29 +8,42 @@
  */
 
 :root {
-  /* As this dialog is designed under assuming the base font size is 11px,
-     specify image size using current font-size. */
-  --introduction-logo-width: calc(158 / 11 * 1em);
-  --introduction-logo-height: calc(114 / 11 * 1em);
-  --main-logo-width: calc(100 / 11 * 1em);
-  --main-logo-height: calc(64 / 11 * 1em);
-  /* --fixed-large-margin is constant regardless of compact mode. */
-  --fixed-large-margin: 24px;
+  --introduction-magglass-logo-width: 176px;
+  --introduction-magglass-logo-height: 128px;
+  --introduction-firefox-logo-width: 72px;
+  --introduction-firefox-logo-height: 72px;
+  --main-magglass-logo-width: 88px;
+  --main-magglass-logo-height: 64px;
+  --main-firefox-logo-width: 50px;
+  --main-firefox-logo-height: 50px;
+  --x-large-margin: 40px;
   --large-margin: 24px;
+  --large-margin-const: 24px;
   --small-margin: 16px;
+  --small-margin-const: 16px;
+  --x-small-margin-const: 8px;
   --section-vertical-padding: 32px;
   --section-horizontal-padding: 64px;
 }
 
 body.compact {
-  /* 15px is the usual font-size. */
-  font-size: 13px;
-  --main-logo-width: calc(100 / 13 * 1em);
-  --main-logo-height: calc(64 / 13 * 1em);
+  --main-magglass-logo-width: 66px;
+  --main-magglass-logo-height: 48px;
+  --main-firefox-logo-width: 32px;
+  --main-firefox-logo-height: 32px;
+  --x-large-margin: 20px;
   --large-margin: 12px;
   --small-margin: 8px;
   --section-vertical-padding: 16px;
   --section-horizontal-padding: 32px;
+
+  /* 15px is the non-compact font-size. */
+  font-size: 13px;
+}
+
+body,
+section {
+  width: 536px;
 }
 
 section {
@@ -40,20 +53,30 @@ section {
   flex-direction: column;
   text-align: center;
   padding: var(--section-vertical-padding) var(--section-horizontal-padding);
-  width: 536px;
-  /* This is the natural height of the main section. */
-  min-height: 587px;
+  /* This is the largest approximate natural height of the main section across
+     platforms and dialog variations, erring on the side of being slightly
+     larger than necessary. If you change this, also update COMPACT_MODE_HEIGHT
+     in the JS. */
+  min-height: 650px;
 }
 
 body.compact section {
-  /* This is the natural height of the main section in compact mode. */
-  min-height: 450px;
+  /* This is the largest approximate natural height of the main section across
+     platforms and dialog variations in compact mode, erring on the side of
+     being slightly larger than necessary. */
+  min-height: 510px;
+}
+
+a {
+  cursor: pointer;
+  font-weight: normal;
 }
 
 .title {
   font-size: 1.6em;
   font-weight: 600;
   line-height: 1.5;
+  white-space: pre-line;
 }
 
 .logo {
@@ -77,42 +100,95 @@ body.compact section {
 }
 
 #introduction-section .logo {
-  background-image: url("quicksuggestOnboarding_magglass_animation.svg");
-  width: var(--introduction-logo-width);
-  height: var(--introduction-logo-height);
+  background-image: url("quicksuggestOnboarding_magglass.svg");
+  width: var(--introduction-magglass-logo-width);
+  height: var(--introduction-magglass-logo-height);
   margin-block-end: var(--large-margin);
 }
 
- at media (prefers-reduced-motion: reduce) {
+#introduction-section .logo.firefox {
+  background-image: url("chrome://branding/content/about-logo.svg");
+  width: var(--introduction-firefox-logo-width);
+  height: var(--introduction-firefox-logo-height);
+}
+
+ at media (prefers-reduced-motion: no-preference) {
   #introduction-section .logo {
-    background-image: url("quicksuggestOnboarding_magglass.svg");
+    background-image: url("quicksuggestOnboarding_magglass_animation.svg");
   }
 }
 
 #introduction-section .title {
-  margin-block-end: var(--large-margin);
+  margin-block-end: var(--x-large-margin);
+}
+
+#onboardingClose {
+  position: absolute;
+  top: 0;
+  inset-inline-end: 0;
+  margin: 16px;
+  padding: 0;
+  line-height: 0;
+  min-width: 20px;
+  min-height: 20px;
+}
+
+#onboardingClose:not(.active) {
+  display: none;
+}
+
+#onboardingClose img {
+  -moz-context-properties: fill;
+  fill: currentColor;
 }
 
 #main-section {
+  display: flex;
+}
+
+#main-section:not(.active) {
   display: none;
 }
 
 #main-section .logo {
   background-image: url("quicksuggestOnboarding_magglass.svg");
-  width: var(--main-logo-width);
-  height: var(--main-logo-height);
+  width: var(--main-magglass-logo-width);
+  height: var(--main-magglass-logo-height);
   margin-block-end: var(--large-margin);
 }
 
+#main-section .logo.firefox {
+  background-image: url("chrome://branding/content/about-logo.svg");
+  width: var(--main-firefox-logo-width);
+  height: var(--main-firefox-logo-height);
+}
+
 #main-section .title {
-  margin-block-end: var(--large-margin);
+  margin-block: 0 var(--small-margin);
+}
+
+#main-section .description-section {
+  /* The effective visual margin between the description and first option should
+      be --large-margin-const. Each child in the description has a bottom margin
+      of --small-margin, so subtract it from --large-margin-const. */
+  margin-block: 0 calc(var(--large-margin-const) - var(--small-margin));
 }
 
 #main-section .description {
-  margin-block: 0 var(--fixed-large-margin);
   font-size: 1.1em;
   font-weight: 400;
   line-height: 1.6;
+  margin-block: 0 var(--small-margin);
+}
+
+#main-section .privacy-first {
+  font-size: 1.1em;
+  font-weight: 700;
+  margin-block: 0 var(--small-margin);
+}
+
+#main-section .privacy-first:not(.active) {
+  display: none;
 }
 
 #main-section .option {
@@ -120,8 +196,13 @@ body.compact section {
   border: 2px solid var(--in-content-box-info-background);
   display: flex;
   text-align: start;
-  padding: var(--small-margin);
-  width: calc(100% - (var(--small-margin) + 2px) * 2);
+  /* Use --small-margin-const for the horizontal padding to make the option's
+     horizontal padding larger than the vertical padding in compact mode. The
+     radio button and text are too close to the left and right edges of the
+     option's border otherwise. */
+  padding: var(--small-margin) var(--small-margin-const);
+  width: 100% - calc(2 * var(--section-horizontal-padding));
+  box-sizing: border-box;
   flex-direction: row;
   position: relative;
 }
@@ -135,7 +216,7 @@ body.compact section {
 }
 
 #main-section .option.reject {
-  margin-block-end: var(--fixed-large-margin);
+  margin-block-end: var(--large-margin-const);
 }
 
 #main-section .option > label {
@@ -176,14 +257,12 @@ body:not(.compact) #main-section .option > input {
   font-size: 1em;
 }
 
-#main-section a {
-  cursor: pointer;
-  font-weight: normal;
+button {
+  margin-block-end: var(--large-margin);
 }
 
-button,
-#onboardingNotNow {
-  margin-block-end: var(--small-margin);
+#onboardingSkipLink {
+  margin-block-end: var(--x-small-margin-const);
 }
 
 /* transition from introduction to main */
@@ -195,7 +274,6 @@ button,
 }
 
 #main-section.active {
-  display: flex;
   animation: fadein 0.3s forwards;
 }
 
diff --git a/browser/components/urlbar/content/quicksuggestOnboarding.html b/browser/components/urlbar/content/quicksuggestOnboarding.html
index 615e1261036ad..5e30e2891fe08 100644
--- a/browser/components/urlbar/content/quicksuggestOnboarding.html
+++ b/browser/components/urlbar/content/quicksuggestOnboarding.html
@@ -21,15 +21,21 @@
   <body role="dialog"
         aria-labelledby="introduction-title">
     <section id="introduction-section">
+      <button id="onboardingClose"
+              tabindex="2"
+              class="ghost-button">
+        <img src="chrome://global/skin/icons/close.svg" />
+      </button>
       <span class="logo" role="presentation"></span>
       <h1 id="introduction-title"
           class="title"
           aria-live="polite"
-          data-l10n-id="firefox-suggest-onboarding-introduction-title"></h1>
+          data-l10n-id="firefox-suggest-onboarding-introduction-title-1"></h1>
       <button id="onboardingNext"
               class="primary"
               tabindex="1"
-              data-l10n-id="firefox-suggest-onboarding-introduction-button"></button>
+              data-l10n-id="firefox-suggest-onboarding-introduction-next-button-1">
+      </button>
       <div class="pager">
         <span class="current"></span>
         <span></span>
@@ -37,27 +43,35 @@
     </section>
     <section id="main-section">
       <span class="logo" role="presentation"></span>
-      <h1 class="title"
+      <h1 id="main-title"
+          class="title"
           aria-live="polite"
-          data-l10n-id="firefox-suggest-onboarding-main-title"></h1>
-      <h2 class="description"
-           tabindex="-1"
-           data-l10n-id="firefox-suggest-onboarding-main-description"></h2>
+          data-l10n-id="firefox-suggest-onboarding-main-title-1"></h1>
+      <div class="description-section">
+        <h2 id="main-description"
+            class="description"
+            tabindex="-1"
+            data-l10n-id="firefox-suggest-onboarding-main-description-1"></h2>
+        <h3 class="privacy-first"
+            tabindex="-1"
+            data-l10n-id="firefox-suggest-onboarding-main-privacy-first"></h2>
+      </div>
       <div class="option accept">
         <label for="onboardingAccept"></label>
         <input id="onboardingAccept"
                type="radio"
-               tabindex="2"
+               tabindex="3"
                name="search-experience"></input>
         <div>
           <div class="option-label"
                data-l10n-id="firefox-suggest-onboarding-main-accept-option-label">
             <a id="onboardingLearnMore"
-               tabindex="3"
-               data-l10n-name="firefox-suggest-onboarding-learn-more-link"></a>
+               tabindex="4"
+               data-l10n-name="learn-more-link"></a>
           </div>
-          <div class="option-description"
-               data-l10n-id="firefox-suggest-onboarding-main-accept-option-description">
+          <div id="main-accept-option-description"
+               class="option-description"
+               data-l10n-id="firefox-suggest-onboarding-main-accept-option-description-1">
           </div>
         </div>
       </div>
@@ -65,24 +79,25 @@
         <label for="onboardingReject"></label>
         <input id="onboardingReject"
                type="radio"
-               tabindex="4"
+               tabindex="5"
                name="search-experience"></input>
         <div>
           <div class="option-label"
                data-l10n-id="firefox-suggest-onboarding-main-reject-option-label">
           </div>
-          <div class="option-description"
-               data-l10n-id="firefox-suggest-onboarding-main-reject-option-description">
+          <div id="main-reject-option-description"
+               class="option-description"
+               data-l10n-id="firefox-suggest-onboarding-main-reject-option-description-1">
           </div>
         </div>
       </div>
       <button id="onboardingSubmit"
               class="primary"
               disabled="true"
-              tabindex="5"
+              tabindex="6"
               data-l10n-id="firefox-suggest-onboarding-main-submit-button"></button>
-      <a id="onboardingNotNow"
-         tabindex="6"
+      <a id="onboardingSkipLink"
+         tabindex="7"
          data-l10n-id="firefox-suggest-onboarding-main-skip-link"></a>
       <div class="pager">
         <span></span>
diff --git a/browser/components/urlbar/content/quicksuggestOnboarding.js b/browser/components/urlbar/content/quicksuggestOnboarding.js
index 7c240e69bd847..2e5d9973910f9 100644
--- a/browser/components/urlbar/content/quicksuggestOnboarding.js
+++ b/browser/components/urlbar/content/quicksuggestOnboarding.js
@@ -8,13 +8,142 @@ const { ONBOARDING_CHOICE } = ChromeUtils.import(
   "resource:///modules/UrlbarQuickSuggest.jsm"
 );
 
-// Number of height pixels to switch to compact mode to avoid showing scrollbars
-// on the non-compact mode. This is based on the natural height of the full-size
-// section height 587px + padding-block-start 32px + padding-block-end 32px +
-// the approximate height of the tab bar 44px.
-const COMPACT_MODE_HEIGHT = 587 + 32 * 2 + 44;
+const VARIATION_MAP = {
+  a: {
+    l10nUpdates: {
+      onboardingNext: "firefox-suggest-onboarding-introduction-next-button-1",
+      "introduction-title": "firefox-suggest-onboarding-introduction-title-1",
+      "main-title": "firefox-suggest-onboarding-main-title-1",
+      "main-description": "firefox-suggest-onboarding-main-description-1",
+      "main-accept-option-description":
+        "firefox-suggest-onboarding-main-accept-option-description-1",
+      "main-reject-option-description":
+        "firefox-suggest-onboarding-main-reject-option-description-1",
+    },
+  },
+  b: {
+    introductionCloseButton: true,
+    l10nUpdates: {
+      onboardingNext: "firefox-suggest-onboarding-introduction-next-button-1",
+      "introduction-title": "firefox-suggest-onboarding-introduction-title-2",
+      "main-title": "firefox-suggest-onboarding-main-title-2",
+      "main-description": "firefox-suggest-onboarding-main-description-2",
+      "main-accept-option-description":
+        "firefox-suggest-onboarding-main-accept-option-description-1",
+      "main-reject-option-description":
+        "firefox-suggest-onboarding-main-reject-option-description-1",
+    },
+  },
+  c: {
+    logoType: "firefox",
+    l10nUpdates: {
+      onboardingNext: "firefox-suggest-onboarding-introduction-next-button-1",
+      "introduction-title": "firefox-suggest-onboarding-introduction-title-3",
+      "main-title": "firefox-suggest-onboarding-main-title-3",
+      "main-description": "firefox-suggest-onboarding-main-description-3",
+      "main-accept-option-description":
+        "firefox-suggest-onboarding-main-accept-option-description-1",
+      "main-reject-option-description":
+        "firefox-suggest-onboarding-main-reject-option-description-1",
+    },
+  },
+  d: {
+    introductionCloseButton: true,
+    l10nUpdates: {
+      onboardingNext: "firefox-suggest-onboarding-introduction-next-button-1",
+      "introduction-title": "firefox-suggest-onboarding-introduction-title-4",
+      "main-title": "firefox-suggest-onboarding-main-title-4",
+      "main-description": "firefox-suggest-onboarding-main-description-4",
+      "main-accept-option-description":
+        "firefox-suggest-onboarding-main-accept-option-description-2",
+      "main-reject-option-description":
+        "firefox-suggest-onboarding-main-reject-option-description-2",
+    },
+  },
+  e: {
+    logoType: "firefox",
+    introductionCloseButton: true,
+    l10nUpdates: {
+      onboardingNext: "firefox-suggest-onboarding-introduction-next-button-1",
+      "introduction-title": "firefox-suggest-onboarding-introduction-title-5",
+      "main-title": "firefox-suggest-onboarding-main-title-5",
+      "main-description": "firefox-suggest-onboarding-main-description-5",
+      "main-accept-option-description":
+        "firefox-suggest-onboarding-main-accept-option-description-2",
+      "main-reject-option-description":
+        "firefox-suggest-onboarding-main-reject-option-description-2",
+    },
+  },
+  f: {
+    introductionCloseButton: true,
+    l10nUpdates: {
+      onboardingNext: "firefox-suggest-onboarding-introduction-next-button-2",
+      "introduction-title": "firefox-suggest-onboarding-introduction-title-6",
+      "main-title": "firefox-suggest-onboarding-main-title-6",
+      "main-description": "firefox-suggest-onboarding-main-description-6",
+      "main-accept-option-description":
+        "firefox-suggest-onboarding-main-accept-option-description-2",
+      "main-reject-option-description":
+        "firefox-suggest-onboarding-main-reject-option-description-2",
+    },
+  },
+  g: {
+    mainPrivacyFirst: true,
+    l10nUpdates: {
+      onboardingNext: "firefox-suggest-onboarding-introduction-next-button-1",
+      "introduction-title": "firefox-suggest-onboarding-introduction-title-7",
+      "main-title": "firefox-suggest-onboarding-main-title-7",
+      "main-description": "firefox-suggest-onboarding-main-description-7",
+      "main-accept-option-description":
+        "firefox-suggest-onboarding-main-accept-option-description-2",
+      "main-reject-option-description":
+        "firefox-suggest-onboarding-main-reject-option-description-2",
+    },
+  },
+  h: {
+    logoType: "firefox",
+    l10nUpdates: {
+      onboardingNext: "firefox-suggest-onboarding-introduction-next-button-1",
+      "introduction-title": "firefox-suggest-onboarding-introduction-title-2",
+      "main-title": "firefox-suggest-onboarding-main-title-8",
+      "main-description": "firefox-suggest-onboarding-main-description-8",
+      "main-accept-option-description":
+        "firefox-suggest-onboarding-main-accept-option-description-1",
+      "main-reject-option-description":
+        "firefox-suggest-onboarding-main-reject-option-description-1",
+    },
+  },
+};
+
+// If the window height is smaller than this value when the dialog opens, then
+// the dialog will open in compact mode. The dialog will not change modes while
+// it's open even if the window height changes.
+const COMPACT_MODE_HEIGHT =
+  650 + // section min-height (non-compact mode)
+  2 * 32 + // 2 * --section-vertical-padding (non-compact mode)
+  44; // approximate height of the browser window's tab bar
+
+// Used for test only. If links or buttons may be clicked or typed Key_Enter
+// while translating l10n, cannot capture the events since not register listeners
+// yet. To avoid the issue, add this flag to know the listeners are ready.
+let resolveOnboardingReady;
+window._quicksuggestOnboardingReady = new Promise(r => {
+  resolveOnboardingReady = r;
+});
+
+document.addEventListener("DOMContentLoaded", async () => {
+  await document.l10n.ready;
+
+  const variation = VARIATION_MAP[window.arguments[0].variationType];
+  if (variation) {
+    document.l10n.pauseObserving();
+    try {
+      await applyVariation(variation);
+    } finally {
+      document.l10n.resumeObserving();
+    }
+  }
 
-document.addEventListener("DOMContentLoaded", () => {
   addSubmitListener(document.getElementById("onboardingNext"), () => {
     document.getElementById("introduction-section").classList.add("inactive");
     document.getElementById("main-section").classList.add("active");
@@ -23,7 +152,7 @@ document.addEventListener("DOMContentLoaded", () => {
     window.arguments[0].choice = ONBOARDING_CHOICE.LEARN_MORE;
     window.close();
   });
-  addSubmitListener(document.getElementById("onboardingNotNow"), () => {
+  addSubmitListener(document.getElementById("onboardingSkipLink"), () => {
     window.arguments[0].choice = ONBOARDING_CHOICE.NOT_NOW;
     window.close();
   });
@@ -68,9 +197,47 @@ document.addEventListener("DOMContentLoaded", () => {
   if (window.outerHeight < COMPACT_MODE_HEIGHT) {
     document.body.classList.add("compact");
   }
+
+  resolveOnboardingReady();
 });
 
+async function applyVariation(variation) {
+  if (variation.introductionCloseButton) {
+    const onboardingClose = document.getElementById("onboardingClose");
+    onboardingClose.classList.add("active");
+    addSubmitListener(onboardingClose, () => {
+      window.arguments[0].choice = ONBOARDING_CHOICE.NOT_NOW;
+      window.close();
+    });
+  }
+
+  if (variation.logoType) {
+    for (const logo of document.querySelectorAll(".logo")) {
+      logo.classList.add(variation.logoType);
+    }
+  }
+
+  if (variation.mainPrivacyFirst) {
+    const label = document.querySelector("#main-section .privacy-first");
+    label.classList.add("active");
+  }
+
+  if (variation.l10nUpdates) {
+    const translatedElements = [];
+    for (const [id, newL10N] of Object.entries(variation.l10nUpdates)) {
+      const element = document.getElementById(id);
+      document.l10n.setAttributes(element, newL10N);
+      translatedElements.push(element);
+    }
+    await document.l10n.translateElements(translatedElements);
+  }
+}
+
 function addSubmitListener(element, listener) {
+  if (!element) {
+    console.warn("Element is null on addSubmitListener");
+    return;
+  }
   element.addEventListener("click", listener);
   element.addEventListener("keydown", e => {
     if (e.keyCode == e.DOM_VK_RETURN) {
diff --git a/browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_configuration.js b/browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_configuration.js
index 40f42748d8b52..6cdc90c724c4a 100644
--- a/browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_configuration.js
+++ b/browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_configuration.js
@@ -24,90 +24,6 @@ add_task(async function init() {
   await QuickSuggestTestUtils.ensureQuickSuggestInit();
 });
 
-// The default is to wait for no browser restarts to show the onboarding dialog
-// on the first restart. This tests that we can override it by configuring the
-// `showOnboardingDialogOnNthRestart`
-add_task(async function test_override_wait_after_n_restarts() {
-  // Set up non-Nimbus prefs related to showing the onboarding.
-  await SpecialPowers.pushPrefEnv({
-    set: [
-      ["browser.urlbar.quicksuggest.showedOnboardingDialog", false],
-      ["browser.urlbar.quicksuggest.seenRestarts", 0],
-    ],
-  });
-
-  await QuickSuggestTestUtils.withExperiment({
-    valueOverrides: {
-      quickSuggestScenario: "online",
-      // Wait for 1 browser restart
-      quickSuggestShowOnboardingDialogAfterNRestarts: 1,
-    },
-    callback: async () => {
-      let prefPromise = TestUtils.waitForPrefChange(
-        "browser.urlbar.quicksuggest.showedOnboardingDialog",
-        value => value === true
-      ).then(() => info("Saw pref change"));
-
-      // Simulate 2 restarts. this function is only called by BrowserGlue
-      // on startup, the first restart would be where MR1 was shown then
-      // we will show onboarding the 2nd restart after that.
-      info("Simulating first restart");
-      await UrlbarQuickSuggest.maybeShowOnboardingDialog();
-
-      info("Simulating second restart");
-      const dialogPromise = BrowserTestUtils.promiseAlertDialogOpen(
-        null,
-        ONBOARDING_URI,
-        { isSubDialog: true }
-      );
-      const maybeShowPromise = UrlbarQuickSuggest.maybeShowOnboardingDialog();
-      const win = await dialogPromise;
-      if (win.document.readyState != "complete") {
-        await BrowserTestUtils.waitForEvent(win, "load");
-      }
-      // Close dialog.
-      EventUtils.synthesizeKey("KEY_Escape");
-
-      info("Waiting for maybeShowPromise and pref change");
-      await Promise.all([maybeShowPromise, prefPromise]);
-    },
-  });
-
-  await SpecialPowers.popPrefEnv();
-  clearOnboardingPrefs();
-});
-
-add_task(async function test_skip_onboarding_dialog() {
-  // Set up non-Nimbus prefs related to showing the onboarding.
-  await SpecialPowers.pushPrefEnv({
-    set: [
-      ["browser.urlbar.quicksuggest.showedOnboardingDialog", false],
-      ["browser.urlbar.quicksuggest.seenRestarts", 0],
-    ],
-  });
-  await QuickSuggestTestUtils.withExperiment({
-    valueOverrides: {
-      quickSuggestScenario: "online",
-      quickSuggestShouldShowOnboardingDialog: false,
-    },
-    callback: async () => {
-      // Simulate 3 restarts.
-      for (let i = 0; i < 3; i++) {
-        info(`Simulating restart ${i + 1}`);
-        await UrlbarQuickSuggest.maybeShowOnboardingDialog();
-      }
-      Assert.ok(
-        !Services.prefs.getBoolPref(
-          "browser.urlbar.quicksuggest.showedOnboardingDialog"
-        ),
-        "The showed onboarding dialog pref should not be set"
-      );
-    },
-  });
-  await SpecialPowers.popPrefEnv();
-  clearOnboardingPrefs();
-});
-
 add_task(async function test_indexes() {
   await QuickSuggestTestUtils.withExperiment({
     valueOverrides: {
diff --git a/browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_onboardingDialog.js b/browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_onboardingDialog.js
index 41294d83042c4..7f6ef584bebe5 100644
--- a/browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_onboardingDialog.js
+++ b/browser/components/urlbar/tests/quicksuggest/browser/browser_quicksuggest_onboardingDialog.js
@@ -29,6 +29,13 @@ if (AppConstants.platform == "macosx") {
   requestLongerTimeout(3);
 }
 
+// Whether the tab key can move the focus. On macOS with full keyboard access
+// disabled (which is default), this will be false. See `canTabMoveFocus`.
+let gCanTabMoveFocus;
+add_task(async function setup() {
+  gCanTabMoveFocus = await canTabMoveFocus();
+});
+
 // When the user has already enabled the data-collection pref, the dialog should
 // not appear.
 add_task(async function onboardingShouldNotAppear() {
@@ -162,7 +169,7 @@ add_task(async function reject() {
 });
 
 // When the Not Now link is clicked, the user should remain opted out.
-add_task(async function notNow() {
+add_task(async function skip() {
   await doDialogTest({
     callback: async () => {
       let tabCount = gBrowser.tabs.length;
@@ -173,7 +180,7 @@ add_task(async function notNow() {
       });
 
       info("Click on not now link");
-      win.document.getElementById("onboardingNotNow").click();
+      win.document.getElementById("onboardingSkipLink").click();
 
       info("Waiting for maybeShowOnboardingDialog to finish");
       await maybeShowPromise;
@@ -436,8 +443,13 @@ add_task(async function dismissed_other_on_introduction() {
   });
 });
 
-// Tests tabbing through the dialog at initial.
-add_task(async function focus_init_order() {
+// Tests tabbing through the dialog on main section.
+add_task(async function focus_order_on_main() {
+  if (!gCanTabMoveFocus) {
+    Assert.ok(true, "Tab key can't move focus, skipping test");
+    return;
+  }
+
   setDialogPrereqPrefs();
 
   info("Calling showOnboardingDialog");
@@ -449,7 +461,7 @@ add_task(async function focus_init_order() {
     "onboardingAccept",
     "onboardingLearnMore",
     "onboardingReject",
-    "onboardingNotNow",
+    "onboardingSkipLink",
     "onboardingAccept",
   ];
 
@@ -466,6 +478,11 @@ add_task(async function focus_init_order() {
 
 // Tests tabbing through the dialog after selecting accept option.
 add_task(async function focus_order_with_accept_option() {
+  if (!gCanTabMoveFocus) {
+    Assert.ok(true, "Tab key can't move focus, skipping test");
+    return;
+  }
+
   setDialogPrereqPrefs();
 
   info("Calling showOnboardingDialog");
@@ -481,7 +498,7 @@ add_task(async function focus_order_with_accept_option() {
   const order = [
     "onboardingLearnMore",
     "onboardingSubmit",
-    "onboardingNotNow",
+    "onboardingSkipLink",
     "onboardingAccept",
   ];
 
@@ -498,6 +515,11 @@ add_task(async function focus_order_with_accept_option() {
 
 // Tests tabbing through the dialog after selecting reject option.
 add_task(async function focus_order_with_reject_option() {
+  if (!gCanTabMoveFocus) {
+    Assert.ok(true, "Tab key can't move focus, skipping test");
+    return;
+  }
+
   setDialogPrereqPrefs();
 
   info("Calling showOnboardingDialog");
@@ -512,7 +534,7 @@ add_task(async function focus_order_with_reject_option() {
 
   const order = [
     "onboardingSubmit",
-    "onboardingNotNow",
+    "onboardingSkipLink",
     "onboardingLearnMore",
     "onboardingReject",
   ];
@@ -644,11 +666,11 @@ add_task(async function focus_reject() {
 
 // Tests tabbing through the dialog and pressing enter. (no option)
 // Tab key count: 4
-// Expected focused element: not now link
-add_task(async function focus_notNow() {
+// Expected focused element: skip link
+add_task(async function focus_skip() {
   await doFocusTest({
     tabKeyRepeat: 4,
-    expectedFocusID: "onboardingNotNow",
+    expectedFocusID: "onboardingSkipLink",
     callback: async () => {
       let tabCount = gBrowser.tabs.length;
       EventUtils.synthesizeKey("KEY_Enter");
@@ -708,6 +730,281 @@ add_task(async function focus_accept_wraparound() {
   });
 });
 
+// The default is to wait for no browser restarts to show the onboarding dialog
+// on the first restart. This tests that we can override it by configuring the
+// `showOnboardingDialogOnNthRestart`
+add_task(async function nimbus_override_wait_after_n_restarts() {
+  UrlbarPrefs.clear("quicksuggest.shouldShowOnboardingDialog");
+  UrlbarPrefs.clear("quicksuggest.showedOnboardingDialog");
+  UrlbarPrefs.clear("quicksuggest.seenRestarts", 0);
+
+  await QuickSuggestTestUtils.withExperiment({
+    valueOverrides: {
+      quickSuggestScenario: "online",
+      // Wait for 1 browser restart
+      quickSuggestShowOnboardingDialogAfterNRestarts: 1,
+    },
+    callback: async () => {
+      let prefPromise = TestUtils.waitForPrefChange(
+        "browser.urlbar.quicksuggest.showedOnboardingDialog",
+        value => value === true
+      ).then(() => info("Saw pref change"));
+
+      // Simulate 2 restarts. this function is only called by BrowserGlue
+      // on startup, the first restart would be where MR1 was shown then
+      // we will show onboarding the 2nd restart after that.
+      info("Simulating first restart");
+      await UrlbarQuickSuggest.maybeShowOnboardingDialog();
+
+      info("Simulating second restart");
+      const dialogPromise = BrowserTestUtils.promiseAlertDialogOpen(
+        null,
+        ONBOARDING_URI,
+        { isSubDialog: true }
+      );
+      const maybeShowPromise = UrlbarQuickSuggest.maybeShowOnboardingDialog();
+      const win = await dialogPromise;
+      if (win.document.readyState != "complete") {
+        await BrowserTestUtils.waitForEvent(win, "load");
+      }
+      // Close dialog.
+      EventUtils.synthesizeKey("KEY_Escape");
+
+      info("Waiting for maybeShowPromise and pref change");
+      await Promise.all([maybeShowPromise, prefPromise]);
+    },
+  });
+});
+
+add_task(async function nimbus_skip_onboarding_dialog() {
+  UrlbarPrefs.clear("quicksuggest.shouldShowOnboardingDialog");
+  UrlbarPrefs.clear("quicksuggest.showedOnboardingDialog");
+  UrlbarPrefs.clear("quicksuggest.seenRestarts", 0);
+
+  await QuickSuggestTestUtils.withExperiment({
+    valueOverrides: {
+      quickSuggestScenario: "online",
+      quickSuggestShouldShowOnboardingDialog: false,
+    },
+    callback: async () => {
+      // Simulate 3 restarts.
+      for (let i = 0; i < 3; i++) {
+        info(`Simulating restart ${i + 1}`);
+        await UrlbarQuickSuggest.maybeShowOnboardingDialog();
+      }
+      Assert.ok(
+        !Services.prefs.getBoolPref(
+          "browser.urlbar.quicksuggest.showedOnboardingDialog",
+          false
+        ),
+        "The showed onboarding dialog pref should not be set"
+      );
+    },
+  });
+});
+
+// Test the close button on the introduction pane appeared by Nimbus setting.
+// Then when the close button is clicked, the user should remain opted out.
+add_task(async function close_button_on_introduction_pane() {
+  await QuickSuggestTestUtils.withExperiment({
+    valueOverrides: {
+      quickSuggestOnboardingDialogVariation: "B",
+    },
+    callback: async () => {
+      await doDialogTest({
+        callback: async () => {
+          info("Calling showOnboardingDialog");
+          const { win, maybeShowPromise } = await showOnboardingDialog();
+
+          info("Check the visibility of the close button");
+          const closeButton = win.document.getElementById("onboardingClose");
+          Assert.ok(BrowserTestUtils.is_visible(closeButton));
+
+          info("Click on the close button");
+          closeButton.click();
+
+          info("Waiting for maybeShowOnboardingDialog to finish");
+          await maybeShowPromise;
+        },
+        onboardingDialogChoice: "not_now_link",
+        expectedUserBranchPrefs: {
+          "quicksuggest.dataCollection.enabled": false,
+        },
+        telemetryEvents: [
+          {
+            category: QuickSuggestTestUtils.TELEMETRY_EVENT_CATEGORY,
+            method: "data_collect_toggled",
+            object: "disabled",
+          },
+          {
+            category: QuickSuggestTestUtils.TELEMETRY_EVENT_CATEGORY,
+            method: "opt_in_dialog",
+            object: "not_now_link",
+          },
+        ],
+      });
+    },
+  });
+});
+
+// Test the UI variation A.
+add_task(async function variation_A() {
+  await doVariationTest({
+    variation: "A",
+    expectedL10N: {
+      onboardingNext: "firefox-suggest-onboarding-introduction-next-button-1",
+      "introduction-title": "firefox-suggest-onboarding-introduction-title-1",
+      "main-title": "firefox-suggest-onboarding-main-title-1",
+      "main-description": "firefox-suggest-onboarding-main-description-1",
+      "main-accept-option-description":
+        "firefox-suggest-onboarding-main-accept-option-description-1",
+      "main-reject-option-description":
+        "firefox-suggest-onboarding-main-reject-option-description-1",
+    },
+  });
+});
+
+// Test the UI variation B.
+add_task(async function variation_B() {
+  await doVariationTest({
+    variation: "B",
+    expectedUI: {
+      introductionCloseButton: true,
+    },
+    expectedL10N: {
+      onboardingNext: "firefox-suggest-onboarding-introduction-next-button-1",
+      "introduction-title": "firefox-suggest-onboarding-introduction-title-2",
+      "main-title": "firefox-suggest-onboarding-main-title-2",
+      "main-description": "firefox-suggest-onboarding-main-description-2",
+      "main-accept-option-description":
+        "firefox-suggest-onboarding-main-accept-option-description-1",
+      "main-reject-option-description":
+        "firefox-suggest-onboarding-main-reject-option-description-1",
+    },
+  });
+});
+
+// Test the UI variation C.
+add_task(async function variation_C() {
+  await doVariationTest({
+    variation: "C",
+    expectedUI: {
+      firefoxLogo: true,
+    },
+    expectedL10N: {
+      onboardingNext: "firefox-suggest-onboarding-introduction-next-button-1",
+      "introduction-title": "firefox-suggest-onboarding-introduction-title-3",
+      "main-title": "firefox-suggest-onboarding-main-title-3",
+      "main-description": "firefox-suggest-onboarding-main-description-3",
+      "main-accept-option-description":
+        "firefox-suggest-onboarding-main-accept-option-description-1",
+      "main-reject-option-description":
+        "firefox-suggest-onboarding-main-reject-option-description-1",
+    },
+  });
+});
+
+// Test the UI variation D.
+add_task(async function variation_D() {
+  await doVariationTest({
+    variation: "D",
+    expectedUI: {
+      introductionCloseButton: true,
+    },
+    expectedL10N: {
+      onboardingNext: "firefox-suggest-onboarding-introduction-next-button-1",
+      "introduction-title": "firefox-suggest-onboarding-introduction-title-4",
+      "main-title": "firefox-suggest-onboarding-main-title-4",
+      "main-description": "firefox-suggest-onboarding-main-description-4",
+      "main-accept-option-description":
+        "firefox-suggest-onboarding-main-accept-option-description-2",
+      "main-reject-option-description":
+        "firefox-suggest-onboarding-main-reject-option-description-2",
+    },
+  });
+});
+
+// Test the UI variation E.
+add_task(async function variation_E() {
+  await doVariationTest({
+    variation: "E",
+    expectedUI: {
+      firefoxLogo: true,
+      introductionCloseButton: true,
+    },
+    expectedL10N: {
+      onboardingNext: "firefox-suggest-onboarding-introduction-next-button-1",
+      "introduction-title": "firefox-suggest-onboarding-introduction-title-5",
+      "main-title": "firefox-suggest-onboarding-main-title-5",
+      "main-description": "firefox-suggest-onboarding-main-description-5",
+      "main-accept-option-description":
+        "firefox-suggest-onboarding-main-accept-option-description-2",
+      "main-reject-option-description":
+        "firefox-suggest-onboarding-main-reject-option-description-2",
+    },
+  });
+});
+
+// Test the UI variation F.
+add_task(async function variation_F() {
+  await doVariationTest({
+    variation: "F",
+    expectedUI: {
+      introductionCloseButton: true,
+    },
+    expectedL10N: {
+      onboardingNext: "firefox-suggest-onboarding-introduction-next-button-2",
+      "introduction-title": "firefox-suggest-onboarding-introduction-title-6",
+      "main-title": "firefox-suggest-onboarding-main-title-6",
+      "main-description": "firefox-suggest-onboarding-main-description-6",
+      "main-accept-option-description":
+        "firefox-suggest-onboarding-main-accept-option-description-2",
+      "main-reject-option-description":
+        "firefox-suggest-onboarding-main-reject-option-description-2",
+    },
+  });
+});
+
+// Test the UI variation G.
+add_task(async function variation_G() {
+  await doVariationTest({
+    variation: "G",
+    expectedUI: {
+      mainPrivacyFirst: true,
+    },
+    expectedL10N: {
+      onboardingNext: "firefox-suggest-onboarding-introduction-next-button-1",
+      "introduction-title": "firefox-suggest-onboarding-introduction-title-7",
+      "main-title": "firefox-suggest-onboarding-main-title-7",
+      "main-description": "firefox-suggest-onboarding-main-description-7",
+      "main-accept-option-description":
+        "firefox-suggest-onboarding-main-accept-option-description-2",
+      "main-reject-option-description":
+        "firefox-suggest-onboarding-main-reject-option-description-2",
+    },
+  });
+});
+
+// Test the UI variation H.
+add_task(async function variation_H() {
+  await doVariationTest({
+    variation: "H",
+    expectedUI: {
+      firefoxLogo: true,
+    },
+    expectedL10N: {
+      onboardingNext: "firefox-suggest-onboarding-introduction-next-button-1",
+      "introduction-title": "firefox-suggest-onboarding-introduction-title-2",
+      "main-title": "firefox-suggest-onboarding-main-title-8",
+      "main-description": "firefox-suggest-onboarding-main-description-8",
+      "main-accept-option-description":
+        "firefox-suggest-onboarding-main-accept-option-description-1",
+      "main-reject-option-description":
+        "firefox-suggest-onboarding-main-reject-option-description-1",
+    },
+  });
+});
+
 async function doDialogTest({
   onboardingDialogChoice,
   telemetryEvents,
@@ -800,10 +1097,6 @@ async function doDialogTest({
   }
 }
 
-// Whether the tab key can move the focus. On macOS with full keyboard access
-// disabled (which is default), this will be false. See `canTabMoveFocus`.
-let gCanTabMoveFocus;
-
 async function doFocusTest({
   tabKeyRepeat,
   expectedFocusID,
@@ -812,9 +1105,6 @@ async function doFocusTest({
   callback,
   expectedUserBranchPrefs,
 }) {
-  if (gCanTabMoveFocus === undefined) {
-    gCanTabMoveFocus = await canTabMoveFocus();
-  }
   if (!gCanTabMoveFocus && tabKeyRepeat) {
     Assert.ok(true, "Tab key can't move focus, skipping test");
     return;
@@ -887,6 +1177,94 @@ async function doTransitionTest({ trigger }) {
   await maybeShowPromise;
 }
 
+async function doVariationTest({
+  variation,
+  expectedUI = {},
+  expectedL10N = {},
+}) {
+  UrlbarPrefs.clear("quicksuggest.shouldShowOnboardingDialog");
+  UrlbarPrefs.clear("quicksuggest.showedOnboardingDialog");
+  UrlbarPrefs.clear("quicksuggest.seenRestarts", 0);
+
+  await QuickSuggestTestUtils.withExperiment({
+    valueOverrides: {
+      quickSuggestScenario: "online",
+      quickSuggestShowOnboardingDialogAfterNRestarts: 0,
+      quickSuggestOnboardingDialogVariation: variation,
+    },
+    callback: async () => {
+      info("Calling showOnboardingDialog");
+      const { win, maybeShowPromise } = await showOnboardingDialog();
+
+      info("Check the logo");
+      const introductionLogoImage = win.getComputedStyle(
+        win.document.querySelector("#introduction-section .logo")
+      ).backgroundImage;
+      const mainLogoImage = win.getComputedStyle(
+        win.document.querySelector("#main-section .logo")
+      ).backgroundImage;
+
+      if (expectedUI.firefoxLogo) {
+        const logoImage = 'url("chrome://branding/content/about-logo.svg")';
+        Assert.equal(introductionLogoImage, logoImage);
+        Assert.equal(mainLogoImage, logoImage);
+      } else {
+        const logoImage =
+          'url("chrome://browser/content/urlbar/quicksuggestOnboarding_magglass.svg")';
+        const animationImage =
+          'url("chrome://browser/content/urlbar/quicksuggestOnboarding_magglass_animation.svg")';
+        const mediaQuery = window.matchMedia(
+          "(prefers-reduced-motion: no-preference)"
+        );
+        const expectedIntroductionLogoImage = mediaQuery.matches
+          ? animationImage
+          : logoImage;
+        Assert.equal(introductionLogoImage, expectedIntroductionLogoImage);
+        Assert.equal(mainLogoImage, logoImage);
+      }
+
+      info("Check the close button on introduction pane");
+      const onboardingClose = win.document.getElementById("onboardingClose");
+      if (expectedUI.introductionCloseButton) {
+        Assert.ok(BrowserTestUtils.is_visible(onboardingClose));
+      } else {
+        Assert.ok(BrowserTestUtils.is_hidden(onboardingClose));
+      }
+
+      info("Check the l10n attribute");
+      for (const [id, l10n] of Object.entries(expectedL10N)) {
+        const element = win.document.getElementById(id);
+        Assert.equal(element.getAttribute("data-l10n-id"), l10n);
+      }
+
+      // Trigger the transition by pressing Enter on the Next button.
+      EventUtils.synthesizeKey("KEY_Enter");
+      await BrowserTestUtils.waitForCondition(
+        () =>
+          BrowserTestUtils.is_hidden(
+            win.document.getElementById("introduction-section")
+          ) &&
+          BrowserTestUtils.is_visible(
+            win.document.getElementById("main-section")
+          )
+      );
+
+      info("Check the privacy first message on main pane");
+      const mainPrivacyFirst = win.document.querySelector(
+        "#main-section .privacy-first"
+      );
+      if (expectedUI.mainPrivacyFirst) {
+        Assert.ok(BrowserTestUtils.is_visible(mainPrivacyFirst));
+      } else {
+        Assert.ok(BrowserTestUtils.is_hidden(mainPrivacyFirst));
+      }
+
+      EventUtils.synthesizeKey("KEY_Escape");
+      await maybeShowPromise;
+    },
+  });
+}
+
 /**
  * Show onbaording dialog.
  *
@@ -910,6 +1288,9 @@ async function showOnboardingDialog({ skipIntroduction } = {}) {
     await BrowserTestUtils.waitForEvent(win, "load");
   }
 
+  // Wait until all listers on onboarding dialog are ready.
+  await window._quicksuggestOnboardingReady;
+
   if (!skipIntroduction) {
     return { win, maybeShowPromise };
   }
@@ -973,10 +1354,11 @@ async function canTabMoveFocus() {
       });
 
       let doc = win.document;
-      let { activeElement } = doc;
+      doc.getElementById("onboardingAccept").focus();
       EventUtils.synthesizeKey("KEY_Tab");
 
-      canMove = activeElement != doc.activeElement;
+      // Whether or not the focus can move to the link.
+      canMove = doc.activeElement.id === "onboardingLearnMore";
 
       EventUtils.synthesizeKey("KEY_Escape");
       await maybeShowPromise;
@@ -998,5 +1380,6 @@ async function canTabMoveFocus() {
       },
     ],
   });
+
   return canMove;
 }
diff --git a/toolkit/components/nimbus/FeatureManifest.yaml b/toolkit/components/nimbus/FeatureManifest.yaml
index 68a7bceb671c4..d1b3871f036c3 100644
--- a/toolkit/components/nimbus/FeatureManifest.yaml
+++ b/toolkit/components/nimbus/FeatureManifest.yaml
@@ -51,6 +51,10 @@ urlbar:
       description: >-
         The index of non-sponsored QuickSuggest results within the general
         group. A negative index is relative to the end of the group
+    quickSuggestOnboardingDialogVariation:
+      type: string
+      description: >-
+        Specify the messages/UI variation for QuickSuggest onboarding dialog. This should be a single letter from A to H inclusive. This value is case insensitive.
     quickSuggestRemoteSettingsEnabled:
       type: boolean
       fallbackPref: browser.urlbar.quicksuggest.remoteSettings.enabled

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the tbb-commits mailing list