Skip to content

Commit 79223b6

Browse files
Landopstanciu@mozilla.com
authored andcommitted
Merge autoland to mozilla-central
2 parents ad24860 + adb4077 commit 79223b6

111 files changed

Lines changed: 3638 additions & 542 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

browser/app/profile/firefox.js

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1877,13 +1877,6 @@ pref("browser.partnerlink.campaign.topsites", "amzn_2020_a1");
18771877
// Activates preloading of the new tab url.
18781878
pref("browser.newtab.preload", true);
18791879

1880-
// Preonboarding is disabled by default on platforms other than Windows and
1881-
// macOS. For official Mozilla distributions (only for Linux), enabled at
1882-
// runtime in TelemetryReportingPolicy.
1883-
#if !defined(XP_WIN) && !defined(XP_MACOSX)
1884-
pref("browser.preonboarding.enabled", false);
1885-
#endif
1886-
18871880
// For further detail on the TOU prefs below, see the `preonboarding` feature in
18881881
// FeatureManifest.yaml
18891882
// Version of the TOU that the user last accepted
@@ -2155,13 +2148,10 @@ pref("browser.aboutwelcome.enabled", true);
21552148
// Used to set multistage welcome UX
21562149
pref("browser.aboutwelcome.screens", "");
21572150
// Whether to gate loading about:welcome on Nimbus experiments having loaded.
2158-
// Enable the Nimbus experiments gate on Mac and Windows. The gate shows a splash
2159-
// screen while experiments load, then auto-advances. On platforms where experiments
2160-
// are already loaded when the modal opens, skipSplashIfLoaded (true by default)
2161-
// causes the splash to be skipped via screen targeting.
2162-
#if defined(XP_MACOSX) || defined(XP_WIN)
2163-
pref("browser.aboutwelcome.experimentsGate.enabled", true);
2164-
#endif
2151+
// The gate shows a splash screen while experiments load, then auto-advances.
2152+
// On platforms where experiments are already loaded when the modal opens,
2153+
// skipSplashIfLoaded causes the splash to be skipped via screen targeting.
2154+
pref("browser.aboutwelcome.experimentsGate.enabled", true);
21652155
// Whether to skip showing the experiment loading splash screen if Nimbus is
21662156
// already initialized when the preonboarding modal's screen targeting is
21672157
// evaluated.

browser/components/BrowserGlue.sys.mjs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ ChromeUtils.defineESModuleGetters(lazy, {
5050
PdfJs: "resource://pdf.js/PdfJs.sys.mjs",
5151
PlacesBrowserStartup:
5252
"moz-src:///browser/components/places/PlacesBrowserStartup.sys.mjs",
53+
PreonboardingSplash:
54+
"resource:///modules/asrouter/PreonboardingSplash.sys.mjs",
5355
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
5456
ProfileDataUpgrader:
5557
"moz-src:///browser/components/ProfileDataUpgrader.sys.mjs",
@@ -938,6 +940,7 @@ BrowserGlue.prototype = {
938940
}
939941
this._windowsWereRestored = true;
940942

943+
lazy.PreonboardingSplash.maybeShowStartupSplash();
941944
lazy.BrowserUsageTelemetry.init();
942945
lazy.SearchSERPTelemetry.init();
943946

browser/components/asrouter/modules/OnboardingMessageProvider.sys.mjs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3718,6 +3718,39 @@ export const OnboardingMessageProvider = {
37183718
return PREONBOARDING_MESSAGES();
37193719
},
37203720

3721+
/**
3722+
* Fill in Nimbus `preonboarding` feature variables from the default
3723+
* preonboarding message when preonboarding is the unconfigured default
3724+
* (`enabled === null`) or enabled without screens. Supplied values win,
3725+
* except nulls and empty arrays, which fall back to the default message's
3726+
* values. Explicitly disabled (`enabled === false`) variables are returned
3727+
* unchanged.
3728+
*
3729+
* @param {object} variables Nimbus `preonboarding` feature variables.
3730+
* @return {object} the variables, merged over the default message if needed.
3731+
*/
3732+
getPreonboardingVariablesWithDefaults(variables) {
3733+
if (
3734+
variables.enabled !== null &&
3735+
!(variables.enabled && !variables.screens?.length)
3736+
) {
3737+
return variables;
3738+
}
3739+
3740+
const preonboardingMessage = this.getPreonboardingMessages().find(
3741+
m => m.id === "NEW_USER_TOU_ONBOARDING"
3742+
);
3743+
return {
3744+
...preonboardingMessage,
3745+
...Object.fromEntries(
3746+
Object.entries(variables).filter(
3747+
([_, value]) =>
3748+
value !== null && !(Array.isArray(value) && !value.length)
3749+
)
3750+
),
3751+
};
3752+
},
3753+
37213754
// If the user has restored from a backup, mutate the restore from backup message to appear once per backup by using the restoration timestamp as the unique message id
37223755
getRestoredFromBackupMessage(messages) {
37233756
const backupRestorationTimestamp = Services.prefs.getIntPref(
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
/**
6+
* This splash screen is the full-viewport loading screen shown to new users at
7+
* startup while first-run experiments enroll behind it. It shows at most once
8+
* per profile (`browser.preonboarding.splashShown`).
9+
*
10+
* When the TOU modal will show, it already includes a splash screen as
11+
* its first screen, so this standalone splash suppresses itself in that case.
12+
*
13+
* It is triggered from BrowserGlue._onWindowsRestored at
14+
* `sessionstore-windows-restored` time so that it appears before about:welcome
15+
* content renders.
16+
*/
17+
18+
const lazy = {};
19+
20+
ChromeUtils.defineESModuleGetters(lazy, {
21+
ASRouterTargeting: "resource:///modules/asrouter/ASRouterTargeting.sys.mjs",
22+
BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.sys.mjs",
23+
ExperimentAPI: "resource://nimbus/ExperimentAPI.sys.mjs",
24+
NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs",
25+
OnboardingMessageProvider:
26+
"resource:///modules/asrouter/OnboardingMessageProvider.sys.mjs",
27+
SpecialMessageActions:
28+
"resource://messaging-system/lib/SpecialMessageActions.sys.mjs",
29+
TelemetryReportingPolicy:
30+
"resource://gre/modules/TelemetryReportingPolicy.sys.mjs",
31+
});
32+
33+
const EXPERIMENTS_GATE_PREF = "browser.aboutwelcome.experimentsGate.enabled";
34+
const SKIP_SPLASH_IF_LOADED_PREF =
35+
"browser.aboutwelcome.experimentsGate.skipSplashIfLoaded";
36+
const DID_SEE_ABOUT_WELCOME_PREF = "trailhead.firstrun.didSeeAboutWelcome";
37+
const SPLASH_SHOWN_PREF = "browser.preonboarding.splashShown";
38+
39+
export const PreonboardingSplash = {
40+
/**
41+
* Stub shims - tests replace these to observe or simulate showing the
42+
* spotlight without a real browser window.
43+
*/
44+
Policy: {
45+
getTopWindow: () =>
46+
lazy.BrowserWindowTracker.getTopWindow({
47+
allowFromInactiveWorkspace: true,
48+
}),
49+
showSpotlight: (config, browser) =>
50+
lazy.SpecialMessageActions.handleAction(config, browser),
51+
},
52+
53+
/**
54+
* Entry point called from BrowserGlue at `sessionstore-windows-restored`
55+
* time.
56+
*/
57+
maybeShowStartupSplash() {
58+
if (!this._shouldShow()) {
59+
return;
60+
}
61+
62+
const screens = this._getSplashScreens();
63+
if (!screens.length) {
64+
return;
65+
}
66+
67+
this._show(screens).catch(e =>
68+
console.error(`PreonboardingSplash: failed to show splash: ${e}`)
69+
);
70+
},
71+
72+
/**
73+
* Determine whether the standalone preonboarding splash should be shown.
74+
*/
75+
_shouldShow() {
76+
if (Services.prefs.getBoolPref(SPLASH_SHOWN_PREF, false)) {
77+
return false;
78+
}
79+
80+
if (!Services.prefs.getBoolPref(EXPERIMENTS_GATE_PREF, false)) {
81+
return false;
82+
}
83+
84+
// The splash exists to allow for first-run experiments to load behind it.
85+
// If Nimbus is disabled (e.g. in automation) there is nothing to wait for,
86+
// and no reason to show it.
87+
if (!lazy.ExperimentAPI.enabled) {
88+
return false;
89+
}
90+
91+
// Likewise if experiments have already loaded there is nothing to wait
92+
// for. This mirrors the loading screen's own render-time targeting; the
93+
// decision must be made here because a spotlight whose only screen is
94+
// filtered out at render time shows an empty modal.
95+
if (
96+
Services.prefs.getBoolPref(SKIP_SPLASH_IF_LOADED_PREF, true) &&
97+
lazy.ASRouterTargeting.Environment.experimentsLoaded
98+
) {
99+
return false;
100+
}
101+
102+
// When the full TOU modal will show, it already includes its own splash as its
103+
// first screen, so this standalone splash doesn't need to fire.
104+
if (lazy.TelemetryReportingPolicy.willShowTOUModal()) {
105+
return false;
106+
}
107+
108+
// Only show the splash to new users who have not already interacted with the TOU.
109+
if (
110+
Services.prefs.getBoolPref(DID_SEE_ABOUT_WELCOME_PREF, false) ||
111+
lazy.TelemetryReportingPolicy.hasUserResolvedTermsOfUse()
112+
) {
113+
return false;
114+
}
115+
116+
return true;
117+
},
118+
119+
/**
120+
* Source the splash screen ("TOU_ONBOARDING_LOADING") from the `preonboarding`
121+
* Nimbus feature, falling back to the built-in default onboarding message
122+
* so the splash is consistent with the TOU modal's screen
123+
*
124+
* @return {object[]} Exactly one splash screen, or [] if unavailable.
125+
*/
126+
_getSplashScreens() {
127+
let variables = lazy.NimbusFeatures.preonboarding.getAllVariables();
128+
129+
// Explicit disablement is a hard opt-out, even when an experiment supplies
130+
// screens, and even on eligible Linux distributions where the TOU flow
131+
// enables itself at runtime. Automation relies on
132+
// `browser.preonboarding.enabled=false` to keep this UI out of tests, and
133+
// CI Linux builds include a `mozilla-official` distribution id, so enabling
134+
// preonboarding at runtime should never override the opt-out here.
135+
if (variables.enabled === false) {
136+
return [];
137+
}
138+
139+
variables =
140+
lazy.OnboardingMessageProvider.getPreonboardingVariablesWithDefaults(
141+
variables
142+
);
143+
144+
const screens = Array.isArray(variables?.screens) ? variables.screens : [];
145+
const splashScreens = screens.filter(
146+
screen => screen.id === "TOU_ONBOARDING_LOADING"
147+
);
148+
149+
// We expect exactly one screen.
150+
if (splashScreens.length !== 1) {
151+
return [];
152+
}
153+
154+
// _shouldShow already decided visibility; the render-time targeting filter
155+
// must not re-decide, or the spotlight could render zero screens.
156+
return splashScreens.map(({ targeting: _targeting, ...screen }) => screen);
157+
},
158+
159+
/**
160+
* Show the standalone preonboarding splash.
161+
*
162+
* @param {object[]} screens the screens from `_getSplashScreens`.
163+
* @return {Promise<boolean>} `true` if the splash was shown.
164+
*/
165+
async _show(screens) {
166+
let win = this.Policy.getTopWindow();
167+
if (!win) {
168+
return false;
169+
}
170+
171+
const config = {
172+
type: "SHOW_SPOTLIGHT",
173+
data: {
174+
content: {
175+
template: "multistage",
176+
id: "PRE_ONBOARDING_SPLASH",
177+
screens,
178+
// The splash auto-advances, but can be dismissed with esc
179+
disableEscClose: false,
180+
},
181+
},
182+
};
183+
184+
this.Policy.showSpotlight(config, win.gBrowser.selectedBrowser);
185+
Services.prefs.setBoolPref(SPLASH_SHOWN_PREF, true);
186+
187+
return true;
188+
},
189+
};

browser/components/asrouter/moz.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ EXTRA_JS_MODULES.asrouter += [
3838
"modules/OnboardingMessageProvider.sys.mjs",
3939
"modules/PageEventManager.sys.mjs",
4040
"modules/PanelTestProvider.sys.mjs",
41+
"modules/PreonboardingSplash.sys.mjs",
4142
"modules/RemoteL10n.sys.mjs",
4243
"modules/SmartWindowNewTabPromo.sys.mjs",
4344
"modules/Spotlight.sys.mjs",

0 commit comments

Comments
 (0)