Skip to content

Commit bffeeb2

Browse files
committed
Bug 1868097 - Whats New Page nimbus tooling r=omc-reviewers,aminomancer
Differential Revision: https://phabricator.services.mozilla.com/D200392
1 parent 6b2d7bc commit bffeeb2

File tree

6 files changed

+216
-7
lines changed

6 files changed

+216
-7
lines changed

browser/app/profile/firefox.js

+3
Original file line numberDiff line numberDiff line change
@@ -3024,3 +3024,6 @@ pref("browser.mailto.dualPrompt.os", false);
30243024
pref("browser.mailto.prompt.os", true);
30253025

30263026
pref("browser.backup.enabled", false);
3027+
3028+
pref("startup.homepage_override_url_nimbus", "");
3029+
pref("startup.homepage_override_nimbus_maxVersion", "");

browser/components/BrowserContentHandler.sys.mjs

+76-7
Original file line numberDiff line numberDiff line change
@@ -240,10 +240,16 @@ function needHomepageOverride(updateMilestones = true) {
240240
* @param update
241241
* The nsIUpdate for the update that has been applied.
242242
* @param defaultOverridePage
243-
* The default override page.
243+
* The default override page
244+
* @param nimbusOverridePage
245+
* Nimbus provided URL
244246
* @return The override page.
245247
*/
246-
function getPostUpdateOverridePage(update, defaultOverridePage) {
248+
function getPostUpdateOverridePage(
249+
update,
250+
defaultOverridePage,
251+
nimbusOverridePage
252+
) {
247253
update = update.QueryInterface(Ci.nsIWritablePropertyBag);
248254
let actions = update.getProperty("actions");
249255
// When the update doesn't specify actions fallback to the original behavior
@@ -258,13 +264,16 @@ function getPostUpdateOverridePage(update, defaultOverridePage) {
258264
return "";
259265
}
260266

261-
// If a policy was set to not allow the update.xml-provided
262-
// URL to be used, use the default fallback (which will also
263-
// be provided by the policy).
267+
// If a policy was set to not allow the update.xml-provided URL to be used,
268+
// use the default fallback (which will also be provided by the policy).
264269
if (!Services.policies.isAllowed("postUpdateCustomPage")) {
265270
return defaultOverridePage;
266271
}
267272

273+
if (nimbusOverridePage) {
274+
return nimbusOverridePage;
275+
}
276+
268277
return update.getProperty("openURL") || defaultOverridePage;
269278
}
270279

@@ -798,7 +807,7 @@ nsBrowserContentHandler.prototype = {
798807
// Turn on 'later run' pages for new profiles.
799808
lazy.LaterRun.enable(lazy.LaterRun.ENABLE_REASON_NEW_PROFILE);
800809
break;
801-
case OVERRIDE_NEW_MSTONE:
810+
case OVERRIDE_NEW_MSTONE: {
802811
// Check whether we will restore a session. If we will, we assume
803812
// that this is an "update" session. This does not take crashes
804813
// into account because that requires waiting for the session file
@@ -811,18 +820,78 @@ nsBrowserContentHandler.prototype = {
811820
"startup.homepage_override_url"
812821
);
813822
let update = lazy.UpdateManager.readyUpdate;
823+
824+
/** If the override URL is provided by an experiment, is a valid
825+
* Firefox What's New Page URL, and the update version is less than
826+
* or equal to the maxVersion set by the experiment, we'll try to use
827+
* the experiment override URL instead of the default or the
828+
* update-provided URL. Additional policy checks are done in
829+
* @see getPostUpdateOverridePage */
830+
const nimbusOverrideUrl = Services.urlFormatter.formatURLPref(
831+
"startup.homepage_override_url_nimbus"
832+
);
833+
const maxVersion = Services.prefs.getCharPref(
834+
"startup.homepage_override_nimbus_maxVersion",
835+
""
836+
);
837+
let nimbusWNP;
838+
839+
// Update version should be less than or equal to maxVersion set by
840+
// the experiment
841+
if (
842+
nimbusOverrideUrl &&
843+
Services.vc.compare(update.appVersion, maxVersion) <= 0
844+
) {
845+
try {
846+
let uri = Services.io.newURI(nimbusOverrideUrl);
847+
// Only allow https://www.mozilla.org and https://www.mozilla.com
848+
if (
849+
uri.scheme === "https" &&
850+
["www.mozilla.org", "www.mozilla.com"].includes(uri.host)
851+
) {
852+
nimbusWNP = uri.spec;
853+
} else {
854+
throw new Error("Bad URL");
855+
}
856+
} catch {
857+
console.error("Invalid WNP URL: ", nimbusOverrideUrl);
858+
}
859+
}
860+
814861
if (
815862
update &&
816863
Services.vc.compare(update.appVersion, old_mstone) > 0
817864
) {
818-
overridePage = getPostUpdateOverridePage(update, overridePage);
865+
overridePage = getPostUpdateOverridePage(
866+
update,
867+
overridePage,
868+
nimbusWNP
869+
);
870+
// Record a Nimbus exposure event for the whatsNewPage feature.
871+
// The override page could be set in 3 ways: 1. set by Nimbus 2.
872+
// set by the update file(openURL) 3. The default evergreen page(Set by the
873+
// startup.homepage_override_url pref, could be different
874+
// depending on the Fx channel). This is done to record that the
875+
// control cohort could have seen the experimental What's New Page
876+
// (and will instead see the default What's New Page).
877+
// recordExposureEvent only records an event if the user is
878+
// enrolled in an experiment or rollout on the whatsNewPage
879+
// feature, so it's safe to call it unconditionally.
880+
if (overridePage) {
881+
let nimbusWNPFeature = lazy.NimbusFeatures.whatsNewPage;
882+
nimbusWNPFeature
883+
.ready()
884+
.then(() => nimbusWNPFeature.recordExposureEvent());
885+
}
886+
819887
// Send the update ping to signal that the update was successful.
820888
lazy.UpdatePing.handleUpdateSuccess(old_mstone, old_buildId);
821889
lazy.LaterRun.enable(lazy.LaterRun.ENABLE_REASON_UPDATE_APPLIED);
822890
}
823891

824892
overridePage = overridePage.replace("%OLD_VERSION%", old_mstone);
825893
break;
894+
}
826895
case OVERRIDE_NEW_BUILD_ID:
827896
if (lazy.UpdateManager.readyUpdate) {
828897
// Send the update ping to signal that the update was successful.

browser/components/tests/browser/whats_new_page/browser.toml

+2
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,5 @@ prefs = [
1919
]
2020

2121
["browser_whats_new_page.js"]
22+
23+
["include:./browser_whats_new_page_nimbus.toml"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/* Any copyright is dedicated to the Public Domain.
2+
* http://creativecommons.org/publicdomain/zero/1.0/ */
3+
4+
"use strict";
5+
6+
add_task(async function nimbus_whats_new_page() {
7+
// The test harness will use the current tab and remove the tab's history.
8+
// Since the page that is tested is opened prior to the test harness taking
9+
// over the current tab the active-update.xml specifies two pages to open by
10+
// having 'https://example.com/|https://example.com/' for the value of openURL
11+
// and then uses the first tab for the test.
12+
gBrowser.selectedTab = gBrowser.tabs[0];
13+
// The test harness also changes the page to about:blank so go back to the
14+
// page that was originally opened.
15+
gBrowser.goBack();
16+
// Wait for the page to go back to the original page.
17+
await TestUtils.waitForCondition(
18+
() =>
19+
gBrowser.selectedBrowser &&
20+
gBrowser.selectedBrowser.currentURI &&
21+
gBrowser.selectedBrowser.currentURI.spec ==
22+
"https://www.mozilla.org/en-US/projects/firefox/whatsnew/",
23+
`Waiting for the expected page to reopen, ${gBrowser.selectedBrowser.currentURI.spec}`
24+
);
25+
is(
26+
gBrowser.selectedBrowser.currentURI.spec,
27+
"https://www.mozilla.org/en-US/projects/firefox/whatsnew/",
28+
"The what's new page's url should equal https://www.mozilla.org/en-US/projects/firefox/whatsnew/"
29+
);
30+
gBrowser.removeTab(gBrowser.selectedTab);
31+
32+
let um = Cc["@mozilla.org/updates/update-manager;1"].getService(
33+
Ci.nsIUpdateManager
34+
);
35+
await TestUtils.waitForCondition(
36+
() => !um.readyUpdate,
37+
"Waiting for the ready update to be removed"
38+
);
39+
ok(!um.readyUpdate, "There should not be a ready update");
40+
await TestUtils.waitForCondition(
41+
() => !!um.getUpdateAt(0),
42+
"Waiting for the ready update to be moved to the update history"
43+
);
44+
ok(!!um.getUpdateAt(0), "There should be an update in the update history");
45+
46+
// Leave no trace. Since this test modifies its support files put them back in
47+
// their original state.
48+
let alternatePath = Services.prefs.getCharPref("app.update.altUpdateDirPath");
49+
let testRoot = Services.prefs.getCharPref("mochitest.testRoot");
50+
let relativePath = alternatePath.substring("<test-root>".length);
51+
if (AppConstants.platform == "win") {
52+
relativePath = relativePath.replace(/\//g, "\\");
53+
}
54+
alternatePath = testRoot + relativePath;
55+
let updateDir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
56+
updateDir.initWithPath(alternatePath);
57+
58+
let activeUpdateFile = updateDir.clone();
59+
activeUpdateFile.append("active-update.xml");
60+
await TestUtils.waitForCondition(
61+
() => !activeUpdateFile.exists(),
62+
"Waiting until the active-update.xml file does not exist"
63+
);
64+
65+
let updatesFile = updateDir.clone();
66+
updatesFile.append("updates.xml");
67+
await TestUtils.waitForCondition(
68+
() => updatesFile.exists(),
69+
"Waiting until the updates.xml file exists"
70+
);
71+
72+
let fos = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(
73+
Ci.nsIFileOutputStream
74+
);
75+
let flags =
76+
FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_TRUNCATE;
77+
78+
let stateSucceeded = "succeeded\n";
79+
let updateStatusFile = updateDir.clone();
80+
updateStatusFile.append("updates");
81+
updateStatusFile.append("0");
82+
updateStatusFile.append("update.status");
83+
updateStatusFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
84+
fos.init(updateStatusFile, flags, FileUtils.PERMS_FILE, 0);
85+
fos.write(stateSucceeded, stateSucceeded.length);
86+
fos.close();
87+
88+
let xmlContents =
89+
'<?xml version="1.0"?><updates xmlns="http://www.mozilla.org/2005/' +
90+
'app-update"><update xmlns="http://www.mozilla.org/2005/app-update" ' +
91+
'appVersion="99999999.0" buildID="20990101111111" channel="test" ' +
92+
'detailsURL="https://127.0.0.1/" displayVersion="1.0" installDate="' +
93+
'1555716429454" isCompleteUpdate="true" name="What\'s New Page Test" ' +
94+
'previousAppVersion="60.0" serviceURL="https://127.0.0.1/update.xml" ' +
95+
'type="minor" platformVersion="99999999.0" actions="showURL" ' +
96+
'openURL="https://example.com/|https://example.com/"><patch size="1" ' +
97+
'type="complete" URL="https://127.0.0.1/complete.mar" ' +
98+
'selected="true" state="pending"/></update></updates>\n';
99+
activeUpdateFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
100+
fos.init(activeUpdateFile, flags, FileUtils.PERMS_FILE, 0);
101+
fos.write(xmlContents, xmlContents.length);
102+
fos.close();
103+
104+
updatesFile.remove(false);
105+
Cc["@mozilla.org/updates/update-manager;1"]
106+
.getService(Ci.nsIUpdateManager)
107+
.QueryInterface(Ci.nsIObserver)
108+
.observe(null, "um-reload-update-data", "");
109+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[DEFAULT]
2+
3+
["browser_whats_new_page_nimbus.js"]
4+
# This is a pref set by nimbus to be used for What's new pages
5+
prefs = ["startup.homepage_override_url_nimbus='https://www.mozilla.org/en-US/projects/firefox/whatsnew/|https://www.mozilla.org/en-US/projects/firefox/whatsnew/'",
6+
"startup.homepage_override_nimbus_maxVersion='99999999.0'"]

toolkit/components/nimbus/FeatureManifest.yaml

+20
Original file line numberDiff line numberDiff line change
@@ -1251,6 +1251,26 @@ fxms-message-11:
12511251
path: "browser/components/asrouter/content-src/schemas/MessagingExperiment.schema.json"
12521252
variables: {}
12531253

1254+
whatsNewPage:
1255+
description: "A Firefox Messaging System message for the What's new page channel"
1256+
owner: omc@mozilla.com
1257+
hasExposure: true
1258+
exposureDescription: >-
1259+
"Exposure is sent if the message is about to be shown after trigger and targeting conditions on the message matched."
1260+
variables:
1261+
overrideUrl:
1262+
description: URL of the What's new page
1263+
type: string
1264+
setPref:
1265+
branch: user
1266+
pref: startup.homepage_override_url_nimbus
1267+
maxVersion:
1268+
description: Maximum Firefox update version
1269+
type: string
1270+
setPref:
1271+
branch: user
1272+
pref: startup.homepage_override_nimbus_maxVersion
1273+
12541274
pbNewtab:
12551275
description: "A Firefox Messaging System message for the pbNewtab message channel"
12561276
owner: omc@mozilla.com

0 commit comments

Comments
 (0)