forked from mirrors/gecko-dev
Bug 1831906 - Add release notes link to update modal prompts. r=bytesized,omc-reviewers,application-update-reviewers,jprickett
Differential Revision: https://phabricator.services.mozilla.com/D177410
This commit is contained in:
parent
fcc5b10abb
commit
52d6ffecf9
8 changed files with 125 additions and 24 deletions
|
|
@ -19,6 +19,7 @@ pref("app.update.url.details", "https://www.mozilla.org/%LOCALE%/firefox/aurora/
|
||||||
|
|
||||||
pref("app.releaseNotesURL", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%beta/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=whatsnew");
|
pref("app.releaseNotesURL", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%beta/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=whatsnew");
|
||||||
pref("app.releaseNotesURL.aboutDialog", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%beta/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-desktop&utm_campaign=about-dialog");
|
pref("app.releaseNotesURL.aboutDialog", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%beta/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-desktop&utm_campaign=about-dialog");
|
||||||
|
pref("app.releaseNotesURL.prompt", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=updateprompt");
|
||||||
|
|
||||||
// The number of days a binary is permitted to be old
|
// The number of days a binary is permitted to be old
|
||||||
// without checking for an update. This assumes that
|
// without checking for an update. This assumes that
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ pref("app.update.url.details", "https://www.mozilla.org/%LOCALE%/firefox/nightly
|
||||||
|
|
||||||
pref("app.releaseNotesURL", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=whatsnew");
|
pref("app.releaseNotesURL", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=whatsnew");
|
||||||
pref("app.releaseNotesURL.aboutDialog", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-desktop&utm_campaign=about-dialog");
|
pref("app.releaseNotesURL.aboutDialog", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-desktop&utm_campaign=about-dialog");
|
||||||
|
pref("app.releaseNotesURL.prompt", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=updateprompt");
|
||||||
|
|
||||||
// The number of days a binary is permitted to be old
|
// The number of days a binary is permitted to be old
|
||||||
// without checking for an update. This assumes that
|
// without checking for an update. This assumes that
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ pref("app.update.promptWaitTime", 691200);
|
||||||
pref("app.releaseNotesURL", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=whatsnew");
|
pref("app.releaseNotesURL", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=whatsnew");
|
||||||
pref("app.releaseNotesURL.aboutDialog", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-desktop&utm_campaign=about-dialog");
|
pref("app.releaseNotesURL.aboutDialog", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-desktop&utm_campaign=about-dialog");
|
||||||
#endif
|
#endif
|
||||||
|
pref("app.releaseNotesURL.prompt", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=updateprompt");
|
||||||
|
|
||||||
// The number of days a binary is permitted to be old
|
// The number of days a binary is permitted to be old
|
||||||
// without checking for an update. This assumes that
|
// without checking for an update. This assumes that
|
||||||
|
|
|
||||||
|
|
@ -936,6 +936,12 @@ const PanelUI = {
|
||||||
popupnotification.setAttribute("icon", notification.options.popupIconURL);
|
popupnotification.setAttribute("icon", notification.options.popupIconURL);
|
||||||
popupnotification.setAttribute("hasicon", true);
|
popupnotification.setAttribute("hasicon", true);
|
||||||
}
|
}
|
||||||
|
if (notification.options.learnMoreURL) {
|
||||||
|
popupnotification.setAttribute(
|
||||||
|
"learnmoreurl",
|
||||||
|
notification.options.learnMoreURL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
popupnotification.notification = notification;
|
popupnotification.notification = notification;
|
||||||
popupnotification.show();
|
popupnotification.show();
|
||||||
|
|
|
||||||
|
|
@ -1564,3 +1564,24 @@ opaqueResponseBlocking:
|
||||||
description: Whether filtering of internal responses in the parent ORB is enabled
|
description: Whether filtering of internal responses in the parent ORB is enabled
|
||||||
type: int
|
type: int
|
||||||
setPref: "browser.opaqueResponseBlocking.filterFetchResponse"
|
setPref: "browser.opaqueResponseBlocking.filterFetchResponse"
|
||||||
|
|
||||||
|
updatePrompt:
|
||||||
|
description: Prefs to control content and behavior of update notifications
|
||||||
|
owner: omc@mozilla.com
|
||||||
|
hasExposure: true
|
||||||
|
exposureDescription: >-
|
||||||
|
Exposure is sent at most once per browsing session when an update
|
||||||
|
notification prompt is displayed.
|
||||||
|
isEarlyStartup: true
|
||||||
|
variables:
|
||||||
|
showReleaseNotesLink:
|
||||||
|
type: boolean
|
||||||
|
description: >-
|
||||||
|
If true, the "Learn More" link will be shown in the update prompt. If
|
||||||
|
false or omitted, the link will only be shown for supported locales.
|
||||||
|
releaseNotesURL:
|
||||||
|
type: string
|
||||||
|
fallbackPref: app.releaseNotesURL.prompt
|
||||||
|
description: >-
|
||||||
|
Template for the URL opened when the user clicks the "Learn More" link
|
||||||
|
in the update prompt. If an empty string, the link will not be shown.
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ const lazy = {};
|
||||||
|
|
||||||
ChromeUtils.defineESModuleGetters(lazy, {
|
ChromeUtils.defineESModuleGetters(lazy, {
|
||||||
AppMenuNotifications: "resource://gre/modules/AppMenuNotifications.sys.mjs",
|
AppMenuNotifications: "resource://gre/modules/AppMenuNotifications.sys.mjs",
|
||||||
|
NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs",
|
||||||
});
|
});
|
||||||
|
|
||||||
XPCOMUtils.defineLazyServiceGetter(
|
XPCOMUtils.defineLazyServiceGetter(
|
||||||
|
|
@ -121,8 +122,11 @@ export var UpdateListener = {
|
||||||
// update is found this pref is cleared and the notification won't be shown.
|
// update is found this pref is cleared and the notification won't be shown.
|
||||||
let url = Services.prefs.getCharPref(PREF_APP_UPDATE_UNSUPPORTED_URL, null);
|
let url = Services.prefs.getCharPref(PREF_APP_UPDATE_UNSUPPORTED_URL, null);
|
||||||
if (url) {
|
if (url) {
|
||||||
this.showUpdateNotification("unsupported", true, true, win =>
|
this.showUpdateNotification(
|
||||||
this.openUnsupportedUpdateUrl(win, url)
|
"unsupported",
|
||||||
|
win => this.openUnsupportedUpdateUrl(win, url),
|
||||||
|
true,
|
||||||
|
{ dismissed: true }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -181,13 +185,38 @@ export var UpdateListener = {
|
||||||
win.openURL(detailsURL);
|
win.openURL(detailsURL);
|
||||||
},
|
},
|
||||||
|
|
||||||
showUpdateNotification(
|
getReleaseNotesUrl(update) {
|
||||||
type,
|
try {
|
||||||
mainActionDismiss,
|
// Release notes are enabled by default for EN locales only, but can be
|
||||||
dismissed,
|
// enabled for other locales within an experiment.
|
||||||
mainAction,
|
if (
|
||||||
beforeShowDoorhanger
|
!Services.locale.appLocaleAsBCP47.startsWith("en") &&
|
||||||
) {
|
!lazy.NimbusFeatures.updatePrompt.getVariable("showReleaseNotesLink")
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// The release notes URL is set in the pref app.releaseNotesURL.prompt,
|
||||||
|
// but can also be overridden by an experiment.
|
||||||
|
let url = lazy.NimbusFeatures.updatePrompt.getVariable("releaseNotesURL");
|
||||||
|
if (url) {
|
||||||
|
let versionString = update.appVersion;
|
||||||
|
switch (update.channel) {
|
||||||
|
case "aurora":
|
||||||
|
case "beta":
|
||||||
|
versionString += "beta";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
url = Services.urlFormatter.formatURL(
|
||||||
|
url.replace("%VERSION%", versionString)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return url || null;
|
||||||
|
} catch (error) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
showUpdateNotification(type, mainAction, mainActionDismiss, options = {}) {
|
||||||
const addTelemetry = id => {
|
const addTelemetry = id => {
|
||||||
// No telemetry for the "downloading" state.
|
// No telemetry for the "downloading" state.
|
||||||
if (type !== "downloading") {
|
if (type !== "downloading") {
|
||||||
|
|
@ -218,9 +247,9 @@ export var UpdateListener = {
|
||||||
"update-" + type,
|
"update-" + type,
|
||||||
action,
|
action,
|
||||||
secondaryAction,
|
secondaryAction,
|
||||||
{ dismissed, beforeShowDoorhanger }
|
options
|
||||||
);
|
);
|
||||||
if (dismissed) {
|
if (options.dismissed) {
|
||||||
addTelemetry("UPDATE_NOTIFICATION_BADGE_SHOWN");
|
addTelemetry("UPDATE_NOTIFICATION_BADGE_SHOWN");
|
||||||
} else {
|
} else {
|
||||||
addTelemetry("UPDATE_NOTIFICATION_SHOWN");
|
addTelemetry("UPDATE_NOTIFICATION_SHOWN");
|
||||||
|
|
@ -234,22 +263,35 @@ export var UpdateListener = {
|
||||||
if (!dismissed) {
|
if (!dismissed) {
|
||||||
this.restartDoorhangerShown = true;
|
this.restartDoorhangerShown = true;
|
||||||
}
|
}
|
||||||
this.showUpdateNotification(notification, true, dismissed, () =>
|
this.showUpdateNotification(
|
||||||
this.requestRestart()
|
notification,
|
||||||
|
() => this.requestRestart(),
|
||||||
|
true,
|
||||||
|
{ dismissed }
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
showUpdateAvailableNotification(update, dismissed) {
|
showUpdateAvailableNotification(update, dismissed) {
|
||||||
this.showUpdateNotification("available", false, dismissed, () => {
|
let learnMoreURL = this.getReleaseNotesUrl(update);
|
||||||
|
this.showUpdateNotification(
|
||||||
|
"available",
|
||||||
// This is asynchronous, but we are just going to kick it off.
|
// This is asynchronous, but we are just going to kick it off.
|
||||||
lazy.AppUpdateService.downloadUpdate(update, true);
|
() => lazy.AppUpdateService.downloadUpdate(update, true),
|
||||||
});
|
false,
|
||||||
|
{ dismissed, learnMoreURL }
|
||||||
|
);
|
||||||
|
lazy.NimbusFeatures.updatePrompt.recordExposureEvent({ once: true });
|
||||||
},
|
},
|
||||||
|
|
||||||
showManualUpdateNotification(update, dismissed) {
|
showManualUpdateNotification(update, dismissed) {
|
||||||
this.showUpdateNotification("manual", false, dismissed, win =>
|
let learnMoreURL = this.getReleaseNotesUrl(update);
|
||||||
this.openManualUpdateUrl(win)
|
this.showUpdateNotification(
|
||||||
|
"manual",
|
||||||
|
win => this.openManualUpdateUrl(win),
|
||||||
|
false,
|
||||||
|
{ dismissed, learnMoreURL }
|
||||||
);
|
);
|
||||||
|
lazy.NimbusFeatures.updatePrompt.recordExposureEvent({ once: true });
|
||||||
},
|
},
|
||||||
|
|
||||||
showUnsupportedUpdateNotification(update, dismissed) {
|
showUnsupportedUpdateNotification(update, dismissed) {
|
||||||
|
|
@ -265,19 +307,25 @@ export var UpdateListener = {
|
||||||
url != Services.prefs.getCharPref(PREF_APP_UPDATE_UNSUPPORTED_URL, null)
|
url != Services.prefs.getCharPref(PREF_APP_UPDATE_UNSUPPORTED_URL, null)
|
||||||
) {
|
) {
|
||||||
Services.prefs.setCharPref(PREF_APP_UPDATE_UNSUPPORTED_URL, url);
|
Services.prefs.setCharPref(PREF_APP_UPDATE_UNSUPPORTED_URL, url);
|
||||||
this.showUpdateNotification("unsupported", true, dismissed, win =>
|
this.showUpdateNotification(
|
||||||
this.openUnsupportedUpdateUrl(win, url)
|
"unsupported",
|
||||||
|
win => this.openUnsupportedUpdateUrl(win, url),
|
||||||
|
true,
|
||||||
|
{ dismissed }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
showUpdateDownloadingNotification() {
|
showUpdateDownloadingNotification() {
|
||||||
this.showUpdateNotification("downloading", true, true, () => {
|
this.showUpdateNotification(
|
||||||
|
"downloading",
|
||||||
// The user clicked on the "Downloading update" app menu item.
|
// The user clicked on the "Downloading update" app menu item.
|
||||||
// Code in browser/components/customizableui/content/panelUI.js
|
// Code in browser/components/customizableui/content/panelUI.js
|
||||||
// receives the following notification and opens the about dialog.
|
// receives the following notification and opens the about dialog.
|
||||||
Services.obs.notifyObservers(null, "show-update-progress");
|
() => Services.obs.notifyObservers(null, "show-update-progress"),
|
||||||
});
|
true,
|
||||||
|
{ dismissed: true }
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
scheduleUpdateAvailableNotification(update) {
|
scheduleUpdateAvailableNotification(update) {
|
||||||
|
|
|
||||||
|
|
@ -4,17 +4,37 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
add_task(async function doorhanger_bc_downloadOptIn() {
|
add_task(async function doorhanger_bc_downloadOptIn() {
|
||||||
|
await SpecialPowers.pushPrefEnv({
|
||||||
|
set: [
|
||||||
|
[
|
||||||
|
"app.releaseNotesURL.prompt",
|
||||||
|
`${URL_HOST}/%LOCALE%/firefox/%VERSION%/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=updateprompt`,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
});
|
||||||
await UpdateUtils.setAppUpdateAutoEnabled(false);
|
await UpdateUtils.setAppUpdateAutoEnabled(false);
|
||||||
|
|
||||||
|
let version = "9999999.0";
|
||||||
|
|
||||||
let params = {
|
let params = {
|
||||||
checkAttempts: 1,
|
checkAttempts: 1,
|
||||||
queryString: "&invalidCompleteSize=1&promptWaitTime=0",
|
queryString: "&invalidCompleteSize=1&promptWaitTime=0",
|
||||||
|
version,
|
||||||
};
|
};
|
||||||
await runDoorhangerUpdateTest(params, [
|
await runDoorhangerUpdateTest(params, [
|
||||||
|
{
|
||||||
|
notificationId: "update-available",
|
||||||
|
button: n => n.querySelector(".popup-notification-learnmore-link"),
|
||||||
|
checkActiveUpdate: null,
|
||||||
|
pageURLs: {
|
||||||
|
manual: `${URL_HOST}/${Services.locale.appLocaleAsBCP47}/firefox/${version}/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=updateprompt`,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
notificationId: "update-available",
|
notificationId: "update-available",
|
||||||
button: "button",
|
button: "button",
|
||||||
checkActiveUpdate: null,
|
checkActiveUpdate: null,
|
||||||
|
popupShown: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
notificationId: "update-restart",
|
notificationId: "update-restart",
|
||||||
|
|
|
||||||
|
|
@ -263,7 +263,7 @@ async function setAppUpdateAutoEnabledHelper(enabled) {
|
||||||
* @param notificationId
|
* @param notificationId
|
||||||
* The ID of the notification to get the button for.
|
* The ID of the notification to get the button for.
|
||||||
* @param button
|
* @param button
|
||||||
* The anonid of the button to get.
|
* The anonid of the button to get, or a function to find it.
|
||||||
* @return The button element.
|
* @return The button element.
|
||||||
*/
|
*/
|
||||||
function getNotificationButton(win, notificationId, button) {
|
function getNotificationButton(win, notificationId, button) {
|
||||||
|
|
@ -271,6 +271,9 @@ function getNotificationButton(win, notificationId, button) {
|
||||||
`appMenu-${notificationId}-notification`
|
`appMenu-${notificationId}-notification`
|
||||||
);
|
);
|
||||||
ok(!notification.hidden, `${notificationId} notification is showing`);
|
ok(!notification.hidden, `${notificationId} notification is showing`);
|
||||||
|
if (typeof button === "function") {
|
||||||
|
return button(notification);
|
||||||
|
}
|
||||||
return notification[button];
|
return notification[button];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue