Bug 1901533 - Moves Refresh Firefox Infobar into Messaging System r=firefox-desktop-core-reviewers ,fluent-reviewers,omc-reviewers,bolsson,mossop,sachung
Scope of this patch is to pull the refresh (unused and reinstall) firefox infobar into messaging system. The infobars are now idle dispatched through the defaultBrowserCheck trigger (previously `onFirstWindowLoaded`), and will respect [activeNotifications](https://searchfox.org/firefox-main/source/browser/components/asrouter/modules/ASRouterTargeting.sys.mjs#1125) See screenshots below: {F79391908} {F79391907} {F79391906} [try run](https://treeherder.mozilla.org/jobs?repo=try&landoInstance=lando-prod-2025&landoCommitID=88932) Differential Revision: https://phabricator.services.mozilla.com/D323372
This commit is contained in:
@@ -78,7 +78,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||
WebChannel: "resource://gre/modules/WebChannel.sys.mjs",
|
||||
WebProtocolHandlerRegistrar:
|
||||
"resource:///modules/WebProtocolHandlerRegistrar.sys.mjs",
|
||||
WindowsRegistry: "resource://gre/modules/WindowsRegistry.sys.mjs",
|
||||
setTimeout: "resource://gre/modules/Timer.sys.mjs",
|
||||
});
|
||||
|
||||
@@ -509,73 +508,6 @@ BrowserGlue.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Show a notification bar offering a reset.
|
||||
*
|
||||
* @param reason
|
||||
* String of either "unused" or "uninstall", specifying the reason
|
||||
* why a profile reset is offered.
|
||||
*/
|
||||
_resetProfileNotification(reason) {
|
||||
let win = lazy.BrowserWindowTracker.getTopWindow({
|
||||
allowFromInactiveWorkspace: true,
|
||||
});
|
||||
if (!win) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { ResetProfile } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/ResetProfile.sys.mjs"
|
||||
);
|
||||
if (!ResetProfile.resetSupported()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let productName = lazy.gBrandBundle.GetStringFromName("brandShortName");
|
||||
let resetBundle = Services.strings.createBundle(
|
||||
"chrome://global/locale/resetProfile.properties"
|
||||
);
|
||||
|
||||
let message;
|
||||
if (reason == "unused") {
|
||||
message = resetBundle.formatStringFromName("resetUnusedProfile.message", [
|
||||
productName,
|
||||
]);
|
||||
} else if (reason == "uninstall") {
|
||||
message = resetBundle.formatStringFromName("resetUninstalled.message", [
|
||||
productName,
|
||||
]);
|
||||
} else {
|
||||
throw new Error(
|
||||
`Unknown reason (${reason}) given to _resetProfileNotification.`
|
||||
);
|
||||
}
|
||||
let buttons = [
|
||||
{
|
||||
label: resetBundle.formatStringFromName(
|
||||
"refreshProfile.resetButton.label",
|
||||
[productName]
|
||||
),
|
||||
accessKey: resetBundle.GetStringFromName(
|
||||
"refreshProfile.resetButton.accesskey"
|
||||
),
|
||||
callback() {
|
||||
ResetProfile.openConfirmationDialog(win);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
win.gNotificationBox.appendNotification(
|
||||
"reset-profile-notification",
|
||||
{
|
||||
label: message,
|
||||
image: "chrome://global/skin/icons/question-64.png",
|
||||
priority: win.gNotificationBox.PRIORITY_INFO_LOW,
|
||||
},
|
||||
buttons
|
||||
);
|
||||
},
|
||||
|
||||
_notifyUnsignedAddonsDisabled() {
|
||||
let win = lazy.BrowserWindowTracker.getTopWindow({
|
||||
allowFromInactiveWorkspace: true,
|
||||
@@ -802,8 +734,6 @@ BrowserGlue.prototype = {
|
||||
}
|
||||
});
|
||||
|
||||
this._maybeOfferProfileReset();
|
||||
|
||||
this._checkForOldBuildUpdates();
|
||||
|
||||
// Check if Sync is configured
|
||||
@@ -822,56 +752,6 @@ BrowserGlue.prototype = {
|
||||
this._firstWindowTelemetry(aWindow);
|
||||
},
|
||||
|
||||
_maybeOfferProfileReset() {
|
||||
// Offer to reset a user's profile if it hasn't been used for 60 days.
|
||||
const OFFER_PROFILE_RESET_INTERVAL_MS = 60 * 24 * 60 * 60 * 1000;
|
||||
let lastUse = Services.appinfo.replacedLockTime;
|
||||
let disableResetPrompt = Services.prefs.getBoolPref(
|
||||
"browser.disableResetPrompt",
|
||||
false
|
||||
);
|
||||
|
||||
// Also check prefs.js last modified timestamp as a backstop.
|
||||
// This helps for cases where the lock file checks don't work,
|
||||
// e.g. NFS or because the previous time Firefox ran, it ran
|
||||
// for a very long time. See bug 1054947 and related bugs.
|
||||
lastUse = Math.max(
|
||||
lastUse,
|
||||
Services.prefs.userPrefsFileLastModifiedAtStartup
|
||||
);
|
||||
|
||||
if (
|
||||
!disableResetPrompt &&
|
||||
lastUse &&
|
||||
Date.now() - lastUse >= OFFER_PROFILE_RESET_INTERVAL_MS
|
||||
) {
|
||||
this._resetProfileNotification("unused");
|
||||
} else if (AppConstants.platform == "win" && !disableResetPrompt) {
|
||||
// Check if we were just re-installed and offer Firefox Reset
|
||||
let updateChannel;
|
||||
try {
|
||||
updateChannel = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/UpdateUtils.sys.mjs"
|
||||
).UpdateUtils.UpdateChannel;
|
||||
} catch (ex) {}
|
||||
if (updateChannel) {
|
||||
let uninstalledValue = lazy.WindowsRegistry.readRegKey(
|
||||
Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
||||
"Software\\Mozilla\\Firefox",
|
||||
`Uninstalled-${updateChannel}`
|
||||
);
|
||||
let removalSuccessful = lazy.WindowsRegistry.removeRegKey(
|
||||
Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
||||
"Software\\Mozilla\\Firefox",
|
||||
`Uninstalled-${updateChannel}`
|
||||
);
|
||||
if (removalSuccessful && uninstalledValue == "True") {
|
||||
this._resetProfileNotification("uninstall");
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Application shutdown handler.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
|
||||
|
||||
const lazy = {};
|
||||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
WindowsRegistry: "resource://gre/modules/WindowsRegistry.sys.mjs",
|
||||
});
|
||||
|
||||
// Reads and clears the registry value the Windows uninstaller writes
|
||||
function readAndClearUninstalledValue() {
|
||||
if (AppConstants.platform != "win") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Services.prefs.getBoolPref("browser.disableResetPrompt", false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let updateChannel;
|
||||
try {
|
||||
updateChannel = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/UpdateUtils.sys.mjs"
|
||||
).UpdateUtils.UpdateChannel;
|
||||
} catch (ex) {}
|
||||
if (updateChannel) {
|
||||
let uninstalledValue = lazy.WindowsRegistry.readRegKey(
|
||||
Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
||||
"Software\\Mozilla\\Firefox",
|
||||
`Uninstalled-${updateChannel}`
|
||||
);
|
||||
let removalSuccessful = lazy.WindowsRegistry.removeRegKey(
|
||||
Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
|
||||
"Software\\Mozilla\\Firefox",
|
||||
`Uninstalled-${updateChannel}`
|
||||
);
|
||||
return removalSuccessful && uninstalledValue == "True";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export const ReinstallCheck = {
|
||||
_wasReinstalled: null,
|
||||
|
||||
/**
|
||||
* @returns {boolean} whether Firefox was reinstalled since the previous run.
|
||||
*/
|
||||
get wasReinstalled() {
|
||||
if (this._wasReinstalled === null) {
|
||||
this._wasReinstalled = readAndClearUninstalledValue();
|
||||
}
|
||||
return this._wasReinstalled;
|
||||
},
|
||||
};
|
||||
@@ -472,6 +472,25 @@ declare const profileAgeReset: undefined | UnixEpochNumber;
|
||||
type UnixEpochNumber = number;
|
||||
```
|
||||
|
||||
### `profileLastUse`
|
||||
|
||||
The date the profile was last used before the current session, as a UNIX Epoch
|
||||
timestamp. This is the more recent of the previous session's lock file time and
|
||||
the `prefs.js` modification time, and is `0` when neither is available.
|
||||
|
||||
#### Examples
|
||||
* Has the profile been unused for at least 60 days?
|
||||
```java
|
||||
profileLastUse && currentDate|date - profileLastUse >= 5184000000
|
||||
```
|
||||
|
||||
#### Definition
|
||||
```ts
|
||||
declare const profileLastUse: UnixEpochNumber;
|
||||
// UnixEpochNumber is UNIX Epoch timestamp, e.g. 1522843725924
|
||||
type UnixEpochNumber = number;
|
||||
```
|
||||
|
||||
### `providerCohorts`
|
||||
|
||||
Information about cohort settings (from prefs, including shield studies) for each provider.
|
||||
@@ -1334,6 +1353,16 @@ restore the previous session on startup; `false` otherwise.
|
||||
|
||||
A boolean. `true` when both the current install and current profile support creating additional profiles using the `SelectableProfileService`; `false` otherwise.
|
||||
|
||||
### `canResetProfile`
|
||||
|
||||
A boolean. `true` when the current profile can be refreshed.
|
||||
|
||||
Any message using the `RESET_PROFILE` action should include this in its targeting.
|
||||
|
||||
### `isFirefoxReinstalled`
|
||||
|
||||
Windows-only. A boolean. `true` when Firefox was uninstalled and then reinstalled over an existing profile since the previous run; `false` otherwise.
|
||||
|
||||
### `hasSelectableProfiles`
|
||||
|
||||
A boolean. `true` when the `toolkit.profiles.storeID` pref has a value. Indicates that the profile is part of a profile group managed by the `SelectableProfileService`, and the user has used the multiple profiles feature. `false` otherwise.
|
||||
|
||||
@@ -76,6 +76,8 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
|
||||
ProfileAge: "resource://gre/modules/ProfileAge.sys.mjs",
|
||||
Region: "resource://gre/modules/Region.sys.mjs",
|
||||
ReinstallCheck: "moz-src:///browser/components/ReinstallCheck.sys.mjs",
|
||||
ResetProfile: "resource://gre/modules/ResetProfile.sys.mjs",
|
||||
SearchService: "moz-src:///toolkit/components/search/SearchService.sys.mjs",
|
||||
// eslint-disable-next-line mozilla/no-browser-refs-in-toolkit
|
||||
SelectableProfileService:
|
||||
@@ -785,6 +787,22 @@ const TargetingGetters = {
|
||||
get profileAgeReset() {
|
||||
return lazy.ProfileAge().then(times => times.reset);
|
||||
},
|
||||
get profileLastUse() {
|
||||
// The lock file records when the profile was last used, but it can be
|
||||
// unreliable, e.g. on NFS or when the previous session ran for a very long
|
||||
// time. Use the prefs.js modification time as a backstop. See bug 1054947
|
||||
// and related bugs.
|
||||
return Math.max(
|
||||
Services.appinfo.replacedLockTime,
|
||||
Services.prefs.userPrefsFileLastModifiedAtStartup
|
||||
);
|
||||
},
|
||||
get canResetProfile() {
|
||||
return lazy.ResetProfile.resetSupported();
|
||||
},
|
||||
get isFirefoxReinstalled() {
|
||||
return lazy.ReinstallCheck.wasReinstalled;
|
||||
},
|
||||
get usesFirefoxSync() {
|
||||
return Services.prefs.prefHasUserValue(FXA_USERNAME_PREF);
|
||||
},
|
||||
|
||||
@@ -2625,6 +2625,49 @@ const BASE_MESSAGES = () => [
|
||||
id: "selectableProfilesUpdated",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "REFRESH_UNUSED_PROFILE_INFOBAR",
|
||||
template: "infobar",
|
||||
content: {
|
||||
type: "global",
|
||||
priority: 1,
|
||||
text: { string_id: "refresh-unused-profile-infobar-message" },
|
||||
buttons: [
|
||||
{
|
||||
label: { string_id: "refresh-profile-infobar-button" },
|
||||
action: { type: "RESET_PROFILE" },
|
||||
},
|
||||
],
|
||||
},
|
||||
trigger: {
|
||||
id: "defaultBrowserCheck",
|
||||
},
|
||||
skip_in_tests: "fires on startup, may interfere with other tests",
|
||||
priority: 1,
|
||||
targeting:
|
||||
"source == 'startup' && canResetProfile && !'browser.disableResetPrompt'|preferenceValue && profileLastUse && currentDate|date - profileLastUse >= 5184000000 && !activeNotifications",
|
||||
},
|
||||
{
|
||||
id: "REFRESH_REINSTALLED_PROFILE_INFOBAR",
|
||||
template: "infobar",
|
||||
content: {
|
||||
type: "global",
|
||||
priority: 1,
|
||||
text: { string_id: "refresh-reinstalled-profile-infobar-message" },
|
||||
buttons: [
|
||||
{
|
||||
label: { string_id: "refresh-profile-infobar-button" },
|
||||
action: { type: "RESET_PROFILE" },
|
||||
},
|
||||
],
|
||||
},
|
||||
trigger: {
|
||||
id: "defaultBrowserCheck",
|
||||
},
|
||||
skip_in_tests: "fires on startup, may interfere with other tests",
|
||||
targeting:
|
||||
"source == 'startup' && isFirefoxReinstalled && canResetProfile && !'browser.disableResetPrompt'|preferenceValue && !activeNotifications",
|
||||
},
|
||||
{
|
||||
id: "updated-privacy-notice-notification-infobar",
|
||||
groups: ["cfr"],
|
||||
|
||||
@@ -27,6 +27,8 @@ ChromeUtils.defineESModuleGetters(this, {
|
||||
ProfileAge: "resource://gre/modules/ProfileAge.sys.mjs",
|
||||
QueryCache: "resource:///modules/asrouter/ASRouterTargeting.sys.mjs",
|
||||
Region: "resource://gre/modules/Region.sys.mjs",
|
||||
ReinstallCheck: "moz-src:///browser/components/ReinstallCheck.sys.mjs",
|
||||
ResetProfile: "resource://gre/modules/ResetProfile.sys.mjs",
|
||||
SearchService: "moz-src:///toolkit/components/search/SearchService.sys.mjs",
|
||||
SelectableProfileService:
|
||||
"resource:///modules/profiles/SelectableProfileService.sys.mjs",
|
||||
@@ -357,6 +359,83 @@ add_task(async function check_canCreateSelectableProfiles() {
|
||||
await SpecialPowers.popPrefEnv();
|
||||
});
|
||||
|
||||
add_task(async function check_canResetProfile() {
|
||||
const sandbox = sinon.createSandbox();
|
||||
const resetSupported = sandbox.stub(ResetProfile, "resetSupported");
|
||||
|
||||
resetSupported.returns(true);
|
||||
is(
|
||||
await ASRouterTargeting.Environment.canResetProfile,
|
||||
true,
|
||||
"should be true when the profile supports being reset"
|
||||
);
|
||||
|
||||
const message = { id: "foo", targeting: "canResetProfile" };
|
||||
is(
|
||||
await ASRouterTargeting.findMatchingMessage({ messages: [message] }),
|
||||
message,
|
||||
"should select the right item by canResetProfile"
|
||||
);
|
||||
|
||||
resetSupported.returns(false);
|
||||
is(
|
||||
await ASRouterTargeting.Environment.canResetProfile,
|
||||
false,
|
||||
"should be false when the profile doesn't support being reset"
|
||||
);
|
||||
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
add_task(async function check_profileLastUse() {
|
||||
is(
|
||||
await ASRouterTargeting.Environment.profileLastUse,
|
||||
Math.max(
|
||||
Services.appinfo.replacedLockTime,
|
||||
Services.prefs.userPrefsFileLastModifiedAtStartup
|
||||
),
|
||||
"should be the most recent lock file and prefs.js timestamps"
|
||||
);
|
||||
|
||||
const message = {
|
||||
id: "foo",
|
||||
targeting: "profileLastUse <= currentDate|date",
|
||||
};
|
||||
is(
|
||||
await ASRouterTargeting.findMatchingMessage({ messages: [message] }),
|
||||
message,
|
||||
"should select correct item by profileLastUse"
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function check_isFirefoxReinstalled() {
|
||||
const sandbox = sinon.createSandbox();
|
||||
const wasReinstalled = sandbox.stub(ReinstallCheck, "wasReinstalled");
|
||||
|
||||
wasReinstalled.get(() => true);
|
||||
is(
|
||||
await ASRouterTargeting.Environment.isFirefoxReinstalled,
|
||||
true,
|
||||
"should be true when a reinstall was detected"
|
||||
);
|
||||
|
||||
const message = { id: "foo", targeting: "isFirefoxReinstalled" };
|
||||
is(
|
||||
await ASRouterTargeting.findMatchingMessage({ messages: [message] }),
|
||||
message,
|
||||
"should select correct item by isFirefoxReinstalled"
|
||||
);
|
||||
|
||||
wasReinstalled.get(() => false);
|
||||
is(
|
||||
await ASRouterTargeting.Environment.isFirefoxReinstalled,
|
||||
false,
|
||||
"should be false when no reinstall was detected"
|
||||
);
|
||||
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
add_task(async function check_hasSelectableProfiles() {
|
||||
is(
|
||||
await ASRouterTargeting.Environment.hasSelectableProfiles,
|
||||
|
||||
@@ -124,6 +124,7 @@ MOZ_SRC_FILES += [
|
||||
"DefaultBrowserCheck.sys.mjs",
|
||||
"DesktopActorRegistry.sys.mjs",
|
||||
"ProfileDataUpgrader.sys.mjs",
|
||||
"ReinstallCheck.sys.mjs",
|
||||
"StartupTelemetry.sys.mjs",
|
||||
]
|
||||
|
||||
|
||||
@@ -497,3 +497,14 @@ lapsed-user-toast-title = { -brand-product-name } still has your back
|
||||
lapsed-user-toast-subtitle = Check out new ways you can browse with more choice, privacy, and control.
|
||||
lapsed-user-toast-whats-new-button = See what’s new
|
||||
lapsed-user-toast-dismiss-button = Dismiss
|
||||
|
||||
## Refresh Firefox infobar
|
||||
##
|
||||
## Shown at startup when the profile has not been used in over 60 days, or when
|
||||
## Firefox has just been reinstalled over an existing profile.
|
||||
## Both offer to reset the profile to a fresh state.
|
||||
|
||||
refresh-unused-profile-infobar-message = It looks like you haven’t started { -brand-short-name } in a while. Do you want to clean it up for a fresh, like-new experience? And by the way, welcome back!
|
||||
refresh-reinstalled-profile-infobar-message = Looks like you’ve reinstalled { -brand-short-name }. Want us to clean it up for a fresh, like-new experience?
|
||||
refresh-profile-infobar-button = Refresh { -brand-short-name }…
|
||||
.accesskey = e
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
# Any copyright is dedicated to the Public Domain.
|
||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
import fluent.syntax.ast as FTL
|
||||
from fluent.migrate import COPY, REPLACE
|
||||
from fluent.migrate.helpers import TERM_REFERENCE
|
||||
|
||||
|
||||
def migrate(ctx):
|
||||
"""Bug 1901533 - Move the Refresh Firefox infobars into the messaging system, part {index}."""
|
||||
|
||||
source = "toolkit/chrome/global/resetProfile.properties"
|
||||
target = "browser/browser/newtab/asrouter.ftl"
|
||||
|
||||
ctx.add_transforms(
|
||||
target,
|
||||
target,
|
||||
[
|
||||
FTL.Message(
|
||||
id=FTL.Identifier("refresh-unused-profile-infobar-message"),
|
||||
value=REPLACE(
|
||||
source,
|
||||
"resetUnusedProfile.message",
|
||||
{"%1$S": TERM_REFERENCE("brand-short-name")},
|
||||
),
|
||||
),
|
||||
FTL.Message(
|
||||
id=FTL.Identifier("refresh-reinstalled-profile-infobar-message"),
|
||||
value=REPLACE(
|
||||
source,
|
||||
"resetUninstalled.message",
|
||||
{"%1$S": TERM_REFERENCE("brand-short-name")},
|
||||
),
|
||||
),
|
||||
FTL.Message(
|
||||
id=FTL.Identifier("refresh-profile-infobar-button"),
|
||||
value=REPLACE(
|
||||
source,
|
||||
"refreshProfile.resetButton.label",
|
||||
{"%1$S": TERM_REFERENCE("brand-short-name")},
|
||||
),
|
||||
attributes=[
|
||||
FTL.Attribute(
|
||||
id=FTL.Identifier("accesskey"),
|
||||
value=COPY(source, "refreshProfile.resetButton.accesskey"),
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
@@ -66,6 +66,9 @@ export const BLOCKED_ACTION_ONLY_ACTIONS = new Set([
|
||||
"IPPROTECTION_ENROLL",
|
||||
"CREATE_NEW_SELECTABLE_PROFILE",
|
||||
|
||||
// Offers to erase the user's profile data and restart the browser.
|
||||
"RESET_PROFILE",
|
||||
|
||||
// Sends data off the device, or fabricates a record that the user consented
|
||||
// to something.
|
||||
"SUMMARIZE_PAGE",
|
||||
|
||||
@@ -63,6 +63,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
|
||||
// eslint-disable-next-line mozilla/no-browser-refs-in-toolkit
|
||||
Referrals: "resource:///modules/referrals/Referrals.sys.mjs",
|
||||
ResetProfile: "resource://gre/modules/ResetProfile.sys.mjs",
|
||||
// eslint-disable-next-line mozilla/no-browser-refs-in-toolkit
|
||||
SelectableProfileService:
|
||||
"resource:///modules/profiles/SelectableProfileService.sys.mjs",
|
||||
@@ -1220,6 +1221,13 @@ export const SpecialMessageActions = {
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "RESET_PROFILE": {
|
||||
if (!lazy.ResetProfile.resetSupported()) {
|
||||
throw new Error("Profile reset is not supported for this profile.");
|
||||
}
|
||||
await lazy.ResetProfile.openConfirmationDialog(window);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new Error(
|
||||
`Special message action with type ${action.type} is unsupported.`
|
||||
|
||||
+12
@@ -879,6 +879,18 @@
|
||||
"additionalProperties": false,
|
||||
"description": "Creates a new user profile using SelectableProfileService and launches it in a new instance"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["RESET_PROFILE"]
|
||||
}
|
||||
},
|
||||
"required": ["type"],
|
||||
"additionalProperties": false,
|
||||
"description": "Opens the refresh confirmation dialog, which resets the current profile and restarts the browser"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -545,6 +545,14 @@ Any message that uses this action should have `canCreateSelectableProfiles` as p
|
||||
|
||||
- args: (none)
|
||||
|
||||
### `RESET_PROFILE`
|
||||
|
||||
Opens the refresh confirmation dialog, which resets the current profile and restarts the browser
|
||||
|
||||
Any message that uses this action should have `canResetProfile` as part of the targeting, to ensure we don't show a message where the action will not work.
|
||||
|
||||
- args: (none)
|
||||
|
||||
### `SUBMIT_ONBOARDING_OPT_OUT_PING`
|
||||
|
||||
Submits a Glean `onboarding-opt-out` ping. Should only be used during preonboarding (but this is not enforced).
|
||||
|
||||
+2
@@ -88,6 +88,8 @@ run-if = [
|
||||
"os == 'linux'",
|
||||
]
|
||||
|
||||
["browser_sma_reset_profile.js"]
|
||||
|
||||
["browser_sma_restore_session.js"]
|
||||
|
||||
["browser_sma_set_bookmarks_toolbar_visibility.js"]
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { ResetProfile } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/ResetProfile.sys.mjs"
|
||||
);
|
||||
|
||||
add_task(async function test_RESET_PROFILE() {
|
||||
let sandbox = sinon.createSandbox();
|
||||
sandbox.stub(ResetProfile, "resetSupported").returns(true);
|
||||
let dialogStub = sandbox.stub(ResetProfile, "openConfirmationDialog");
|
||||
|
||||
await SMATestUtils.executeAndValidateAction({ type: "RESET_PROFILE" });
|
||||
|
||||
Assert.equal(
|
||||
dialogStub.callCount,
|
||||
1,
|
||||
"openConfirmationDialog called by the action"
|
||||
);
|
||||
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
add_task(async function test_RESET_PROFILE_unsupported() {
|
||||
let sandbox = sinon.createSandbox();
|
||||
sandbox.stub(ResetProfile, "resetSupported").returns(false);
|
||||
let dialogStub = sandbox.stub(ResetProfile, "openConfirmationDialog");
|
||||
|
||||
await Assert.rejects(
|
||||
SpecialMessageActions.handleAction({ type: "RESET_PROFILE" }, gBrowser),
|
||||
/Profile reset is not supported/,
|
||||
"should reject when reset is not supported"
|
||||
);
|
||||
|
||||
Assert.equal(
|
||||
dialogStub.callCount,
|
||||
0,
|
||||
"openConfirmationDialog not called when reset is unsupported"
|
||||
);
|
||||
|
||||
sandbox.restore();
|
||||
});
|
||||
@@ -1,14 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
# LOCALIZATION NOTE: These strings are used for profile reset.
|
||||
|
||||
# LOCALIZATION NOTE (resetUnusedProfile.message): %S is brandShortName.
|
||||
resetUnusedProfile.message=It looks like you haven’t started %S in a while. Do you want to clean it up for a fresh, like-new experience? And by the way, welcome back!
|
||||
# LOCALIZATION NOTE (resetUninstalled.message): %S is brandShortName.
|
||||
resetUninstalled.message=Looks like you’ve reinstalled %S. Want us to clean it up for a fresh, like-new experience?
|
||||
|
||||
# LOCALIZATION NOTE (refreshProfile.resetButton.label): %S is brandShortName.
|
||||
refreshProfile.resetButton.label=Refresh %S…
|
||||
refreshProfile.resetButton.accesskey=e
|
||||
@@ -33,7 +33,6 @@
|
||||
#if !defined(XP_WIN) && !defined(MOZ_GECKOVIEW)
|
||||
locale/@AB_CD@/global/printdialog.properties (%chrome/global/printdialog.properties)
|
||||
#endif
|
||||
locale/@AB_CD@/global/resetProfile.properties (%chrome/global/resetProfile.properties)
|
||||
locale/@AB_CD@/global/dialog.properties (%chrome/global/dialog.properties)
|
||||
locale/@AB_CD@/global/viewSource.properties (%chrome/global/viewSource.properties)
|
||||
locale/@AB_CD@/global/wizard.properties (%chrome/global/wizard.properties)
|
||||
|
||||
Reference in New Issue
Block a user