diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js
index 932bd49d749f..12eb28acb447 100644
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -3052,6 +3052,8 @@ pref("browser.mailto.prompt.os", true);
// Pref to initialize the BackupService soon after startup.
pref("browser.backup.enabled", true);
+// Pref to control whether scheduled backups run or not.
+pref("browser.backup.scheduled.enabled", false);
// Pref to control the visibility of the backup section in about:preferences
pref("browser.backup.preferences.ui.enabled", false);
// The number of SQLite database pages to backup per step.
diff --git a/browser/components/BrowserGlue.sys.mjs b/browser/components/BrowserGlue.sys.mjs
index 050e9c9554d9..c913509fd70c 100644
--- a/browser/components/BrowserGlue.sys.mjs
+++ b/browser/components/BrowserGlue.sys.mjs
@@ -439,6 +439,7 @@ let JSWINDOWACTORS = {
esModuleURI: "resource:///actors/BackupUIChild.sys.mjs",
events: {
"BackupUI:InitWidget": { wantUntrusted: true },
+ "BackupUI:ScheduledBackupsConfirm": { wantUntrusted: true },
},
},
matches: ["about:preferences*", "about:settings*"],
diff --git a/browser/components/backup/BackupService.sys.mjs b/browser/components/backup/BackupService.sys.mjs
index 44745dca41b0..8ed2238222e7 100644
--- a/browser/components/backup/BackupService.sys.mjs
+++ b/browser/components/backup/BackupService.sys.mjs
@@ -4,7 +4,9 @@
import * as DefaultBackupResources from "resource:///modules/backup/BackupResources.sys.mjs";
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
+import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
+const SCHEDULED_BACKUPS_ENABLED_PREF_NAME = "browser.backup.scheduled.enabled";
const lazy = {};
ChromeUtils.defineLazyGetter(lazy, "logConsole", function () {
@@ -33,6 +35,19 @@ ChromeUtils.defineLazyGetter(lazy, "ZipWriter", () =>
Components.Constructor("@mozilla.org/zipwriter;1", "nsIZipWriter", "open")
);
+XPCOMUtils.defineLazyPreferenceGetter(
+ lazy,
+ "scheduledBackupsPref",
+ SCHEDULED_BACKUPS_ENABLED_PREF_NAME,
+ false,
+ function onUpdateScheduledBackups(_pref, _prevVal, newVal) {
+ let bs = BackupService.get();
+ if (bs) {
+ bs.onUpdateScheduledBackups(newVal);
+ }
+ }
+);
+
/**
* The BackupService class orchestrates the scheduling and creation of profile
* backups. It also does most of the heavy lifting for the restoration of a
@@ -94,7 +109,11 @@ export class BackupService extends EventTarget {
*
* @type {object}
*/
- #_state = { backupInProgress: false };
+ #_state = {
+ backupFilePath: "Documents", // TODO: make save location configurable (bug 1895943)
+ backupInProgress: false,
+ scheduledBackupsEnabled: lazy.scheduledBackupsPref,
+ };
/**
* A Promise that will resolve once the postRecovery steps are done. It will
@@ -844,6 +863,35 @@ export class BackupService extends EventTarget {
}
}
+ /**
+ * Sets browser.backup.scheduled.enabled to true or false.
+ *
+ * @param { boolean } shouldEnableScheduledBackups true if scheduled backups should be enabled. Else, false.
+ */
+ setScheduledBackups(shouldEnableScheduledBackups) {
+ Services.prefs.setBoolPref(
+ SCHEDULED_BACKUPS_ENABLED_PREF_NAME,
+ shouldEnableScheduledBackups
+ );
+ }
+
+ /**
+ * Updates scheduledBackupsEnabled in the backup service state. Should be called every time
+ * the value for browser.backup.scheduled.enabled changes.
+ *
+ * @param {boolean} isScheduledBackupsEnabled True if scheduled backups are enabled. Else false.
+ */
+ onUpdateScheduledBackups(isScheduledBackupsEnabled) {
+ if (this.#_state.scheduledBackupsEnabled != isScheduledBackupsEnabled) {
+ lazy.logConsole.debug(
+ "Updating scheduled backups",
+ isScheduledBackupsEnabled
+ );
+ this.#_state.scheduledBackupsEnabled = isScheduledBackupsEnabled;
+ this.stateUpdate();
+ }
+ }
+
/**
* Take measurements of the current profile state for Telemetry.
*
diff --git a/browser/components/backup/actors/BackupUIChild.sys.mjs b/browser/components/backup/actors/BackupUIChild.sys.mjs
index 25d013fa8ecf..668debaa6ee0 100644
--- a/browser/components/backup/actors/BackupUIChild.sys.mjs
+++ b/browser/components/backup/actors/BackupUIChild.sys.mjs
@@ -13,20 +13,24 @@ export class BackupUIChild extends JSWindowActorChild {
#inittedWidgets = new WeakSet();
/**
- * Handles BackupUI:InitWidget custom events fired by widgets that want to
- * register with BackupUIChild. Firing this event sends a message to the
- * parent to request the BackupService state which will result in a
- * `backupServiceState` property of the widget to be set when that state is
- * received. Subsequent state updates will also cause that state property to
- * be set.
+ * Handles custom events fired by widgets that want to register with
+ * BackupUIChild.
*
* @param {Event} event
- * The BackupUI:InitWidget custom event that the widget fired.
+ * The custom event that the widget fired.
*/
handleEvent(event) {
+ /**
+ * BackupUI:InitWidget sends a message to the parent to request the BackupService state
+ * which will result in a `backupServiceState` property of the widget to be set when that
+ * state is received. Subsequent state updates will also cause that state property to
+ * be set.
+ */
if (event.type == "BackupUI:InitWidget") {
this.#inittedWidgets.add(event.target);
this.sendAsyncMessage("RequestState");
+ } else if (event.type == "BackupUI:ScheduledBackupsConfirm") {
+ this.sendAsyncMessage("ScheduledBackupsConfirm");
}
}
diff --git a/browser/components/backup/actors/BackupUIParent.sys.mjs b/browser/components/backup/actors/BackupUIParent.sys.mjs
index e4d0f3aace85..f97d00cbdc8c 100644
--- a/browser/components/backup/actors/BackupUIParent.sys.mjs
+++ b/browser/components/backup/actors/BackupUIParent.sys.mjs
@@ -69,6 +69,8 @@ export class BackupUIParent extends JSWindowActorParent {
receiveMessage(message) {
if (message.name == "RequestState") {
this.sendState();
+ } else if (message.name == "ScheduledBackupsConfirm") {
+ this.#bs.setScheduledBackups(true);
}
}
diff --git a/browser/components/backup/content/backup-settings.css b/browser/components/backup/content/backup-settings.css
new file mode 100644
index 000000000000..e78596b00a76
--- /dev/null
+++ b/browser/components/backup/content/backup-settings.css
@@ -0,0 +1,7 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+#turn-on-scheduled-backups-dialog {
+ width: 27.8rem;
+}
diff --git a/browser/components/backup/content/backup-settings.mjs b/browser/components/backup/content/backup-settings.mjs
index c34d87dbc7a8..2992a7e1e7e1 100644
--- a/browser/components/backup/content/backup-settings.mjs
+++ b/browser/components/backup/content/backup-settings.mjs
@@ -5,6 +5,9 @@
import { html } from "chrome://global/content/vendor/lit.all.mjs";
import { MozLitElement } from "chrome://global/content/lit-utils.mjs";
+// eslint-disable-next-line import/no-unassigned-import
+import "chrome://browser/content/backup/turn-on-scheduled-backups.mjs";
+
/**
* The widget for managing the BackupService that is embedded within the main
* document of about:settings / about:preferences.
@@ -14,14 +17,24 @@ export default class BackupSettings extends MozLitElement {
backupServiceState: { type: Object },
};
+ static get queries() {
+ return {
+ scheduledBackupsButtonEl: "#backup-toggle-scheduled-button",
+ turnOnScheduledBackupsDialogEl: "#turn-on-scheduled-backups-dialog",
+ turnOnScheduledBackupsEl: "turn-on-scheduled-backups",
+ };
+ }
+
/**
- * Creates a BackupSettings instance and sets the initial default
+ * Creates a BackupPreferences instance and sets the initial default
* state.
*/
constructor() {
super();
this.backupServiceState = {
+ backupFilePath: "Documents", // TODO: make save location configurable (bug 1895943)
backupInProgress: false,
+ scheduledBackupsEnabled: false,
};
}
@@ -34,13 +47,68 @@ export default class BackupSettings extends MozLitElement {
this.dispatchEvent(
new CustomEvent("BackupUI:InitWidget", { bubbles: true })
);
+
+ this.addEventListener("scheduledBackupsCancel", this);
+ this.addEventListener("scheduledBackupsConfirm", this);
+ }
+
+ handleEvent(event) {
+ switch (event.type) {
+ case "scheduledBackupsConfirm":
+ this.turnOnScheduledBackupsDialogEl.close();
+ this.dispatchEvent(
+ new CustomEvent("BackupUI:ScheduledBackupsConfirm", {
+ bubbles: true,
+ composed: true,
+ })
+ );
+ break;
+ case "scheduledBackupsCancel":
+ this.turnOnScheduledBackupsDialogEl.close();
+ break;
+ }
+ }
+
+ handleShowScheduledBackups() {
+ if (
+ !this.backupServiceState.scheduledBackupsEnabled &&
+ this.turnOnScheduledBackupsDialogEl
+ ) {
+ this.turnOnScheduledBackupsDialogEl.showModal();
+ }
+ }
+
+ turnOnScheduledBackupsDialogTemplate() {
+ return html``;
}
render() {
- return html`
`;
}
}
diff --git a/browser/components/backup/content/backup-settings.stories.mjs b/browser/components/backup/content/backup-settings.stories.mjs
index e125cfbeff70..dafd8193cf54 100644
--- a/browser/components/backup/content/backup-settings.stories.mjs
+++ b/browser/components/backup/content/backup-settings.stories.mjs
@@ -6,6 +6,9 @@
import { html } from "lit.all.mjs";
import "./backup-settings.mjs";
+window.MozXULElement.insertFTLIfNeeded("locales-preview/backupSettings.ftl");
+window.MozXULElement.insertFTLIfNeeded("branding/brand.ftl");
+
export default {
title: "Domain-specific UI Widgets/Backup/Backup Settings",
component: "backup-settings",
@@ -19,13 +22,17 @@ const Template = ({ backupServiceState }) => html`
export const BackingUpNotInProgress = Template.bind({});
BackingUpNotInProgress.args = {
backupServiceState: {
+ backupFilePath: "Documents",
backupInProgress: false,
+ scheduledBackupsEnabled: false,
},
};
export const BackingUpInProgress = Template.bind({});
BackingUpInProgress.args = {
backupServiceState: {
+ backupFilePath: "Documents",
backupInProgress: true,
+ scheduledBackupsEnabled: false,
},
};
diff --git a/browser/components/backup/content/turn-on-scheduled-backups.css b/browser/components/backup/content/turn-on-scheduled-backups.css
new file mode 100644
index 000000000000..baa5d61776b9
--- /dev/null
+++ b/browser/components/backup/content/turn-on-scheduled-backups.css
@@ -0,0 +1,109 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+@import url("chrome://global/skin/in-content/common.css");
+
+:host {
+ --margin-inline-start-checkbox-content: calc(var(--checkbox-margin-inline) + var(--checkbox-size));
+}
+
+#backup-turn-on-scheduled-wrapper {
+ display: grid;
+ grid-template-areas:
+ "header"
+ "content"
+ "button-group";
+ grid-template-rows: auto auto auto;
+ line-height: 1.5;
+
+ #backup-turn-on-scheduled-header {
+ grid-area: header;
+ font-size: var(--font-size-large);
+ font-weight: var(--font-weight);
+ margin: 0;
+ }
+
+ & fieldset {
+ border: none;
+ margin: 0;
+ padding: 0;
+ }
+
+ #backup-turn-on-scheduled-content {
+ display: flex;
+ flex-direction: column;
+ grid-area: content;
+ margin-block-start: var(--space-small);
+ margin-block-end: var(--space-large);
+ row-gap: var(--space-large);
+ }
+
+ #all-controls {
+ display: flex;
+ flex-direction: column;
+ row-gap: var(--space-xlarge);
+ }
+
+ #backup-location-controls {
+ display: flex;
+ flex-direction: column;
+ row-gap: var(--space-xsmall);
+
+ #backup-location-filepicker {
+ display: flex;
+ column-gap: var(--space-small);
+ align-items: center;
+ }
+
+ #backup-location-filepicker-input {
+ margin: 0;
+ flex: 1;
+ }
+ }
+
+ #sensitive-data-controls {
+ display: flex;
+ flex-direction: column;
+ row-gap: var(--space-large);
+
+ #sensitive-data-checkbox-label {
+ display: flex;
+ gap: var(--checkbox-margin-inline);
+ align-items: center;
+ }
+
+ #sensitive-data-checkbox-label > input {
+ margin: 0;
+ }
+
+ #sensitive-data-checkbox {
+ display: flex;
+ flex-direction: column;
+ row-gap: var(--space-xsmall);
+ }
+
+ #sensitive-data-checkbox > span {
+ margin-inline-start: var(--margin-inline-start-checkbox-content);
+ }
+ }
+
+ #passwords {
+ display: flex;
+ flex-direction: column;
+ margin-inline-start: var(--margin-inline-start-checkbox-content);
+
+ & > #new-password-label, #repeat-password-label {
+ display: flex;
+ flex-direction: column;
+ }
+
+ & > #new-password-label > input, #repeat-password-label > input {
+ margin-inline-start: 0px;
+ }
+ }
+
+ #backup-turn-on-scheduled-button-group {
+ grid-area: button-group;
+ }
+}
diff --git a/browser/components/backup/content/turn-on-scheduled-backups.mjs b/browser/components/backup/content/turn-on-scheduled-backups.mjs
new file mode 100644
index 000000000000..02ebc7dcd8eb
--- /dev/null
+++ b/browser/components/backup/content/turn-on-scheduled-backups.mjs
@@ -0,0 +1,212 @@
+/* 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 { html } from "chrome://global/content/vendor/lit.all.mjs";
+import { MozLitElement } from "chrome://global/content/lit-utils.mjs";
+
+/**
+ * The widget for showing available options when users want to turn on
+ * scheduled backups.
+ */
+export default class TurnOnScheduledBackups extends MozLitElement {
+ static properties = {
+ backupFilePath: { type: String },
+ showPasswordOptions: { type: Boolean, reflect: true },
+ };
+
+ static get queries() {
+ return {
+ cancelButtonEl: "#backup-turn-on-scheduled-cancel-button",
+ confirmButtonEl: "#backup-turn-on-scheduled-confirm-button",
+ passwordOptionsCheckboxEl: "#sensitive-data-checkbox-input",
+ passwordOptionsExpandedEl: "#passwords",
+ recommendedFolderInputEl: "#backup-location-filepicker-input",
+ };
+ }
+
+ constructor() {
+ super();
+ this.backupFilePath = null;
+ this.showPasswordOptions = false;
+ }
+
+ /**
+ * Dispatches the BackupUI:InitWidget custom event upon being attached to the
+ * DOM, which registers with BackupUIChild for BackupService state updates.
+ */
+ connectedCallback() {
+ super.connectedCallback();
+ this.dispatchEvent(
+ new CustomEvent("BackupUI:InitWidget", { bubbles: true })
+ );
+ }
+
+ handleChooseLocation() {
+ // TODO: show file picker (bug 1895943)
+ }
+
+ handleCancel() {
+ this.dispatchEvent(
+ new CustomEvent("scheduledBackupsCancel", {
+ bubbles: true,
+ composed: true,
+ })
+ );
+ this.showPasswordOptions = false;
+ this.passwordOptionsCheckboxEl.checked = false;
+ }
+
+ handleConfirm() {
+ /**
+ * TODO:
+ * We should pass save location to BackupUIParent here (bug 1895943).
+ * If encryption is enabled via this dialog, ensure a password is set and pass it to BackupUIParent (bug 1895981).
+ * Before confirmation, verify passwords match and FxA format rules (bug 1896772).
+ */
+ this.dispatchEvent(
+ new CustomEvent("scheduledBackupsConfirm", {
+ bubbles: true,
+ composed: true,
+ })
+ );
+ this.showPasswordOptions = false;
+ this.passwordOptionsCheckboxEl.checked = false;
+ }
+
+ handleTogglePasswordOptions() {
+ this.showPasswordOptions = this.passwordOptionsCheckboxEl?.checked;
+ }
+
+ allOptionsTemplate() {
+ return html`
+
+ `;
+ }
+
+ passwordOptionsTemplate() {
+ return html`
+
+
+
+
+ `;
+ }
+
+ contentTemplate() {
+ return html`
+
+
+
+
+
+
+
+ ${this.allOptionsTemplate()}
+
+
+
+
+
+
+
+ `;
+ }
+
+ render() {
+ return html`
+
+ ${this.contentTemplate()}
+ `;
+ }
+}
+
+customElements.define("turn-on-scheduled-backups", TurnOnScheduledBackups);
diff --git a/browser/components/backup/content/turn-on-scheduled-backups.stories.mjs b/browser/components/backup/content/turn-on-scheduled-backups.stories.mjs
new file mode 100644
index 000000000000..865bf65068f5
--- /dev/null
+++ b/browser/components/backup/content/turn-on-scheduled-backups.stories.mjs
@@ -0,0 +1,30 @@
+/* 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/. */
+
+// eslint-disable-next-line import/no-unresolved
+import { html } from "lit.all.mjs";
+import "chrome://global/content/elements/moz-card.mjs";
+import "./turn-on-scheduled-backups.mjs";
+
+window.MozXULElement.insertFTLIfNeeded("locales-preview/backupSettings.ftl");
+window.MozXULElement.insertFTLIfNeeded("branding/brand.ftl");
+
+export default {
+ title: "Domain-specific UI Widgets/Backup/Turn On Scheduled Backups",
+ component: "turn-on-scheduled-backups",
+ argTypes: {},
+};
+
+const Template = ({ backupFilePath }) => html`
+
+
+
+`;
+
+export const RecommendedFolder = Template.bind({});
+RecommendedFolder.args = {
+ backupFilePath: "Documents",
+};
diff --git a/browser/components/backup/jar.mn b/browser/components/backup/jar.mn
index 94c670afaf5e..aaeb2b807151 100644
--- a/browser/components/backup/jar.mn
+++ b/browser/components/backup/jar.mn
@@ -8,4 +8,7 @@ browser.jar:
content/browser/backup/debug.js (content/debug.js)
#endif
content/browser/backup/BackupManifest.1.schema.json (content/BackupManifest.1.schema.json)
+ content/browser/backup/backup-settings.css (content/backup-settings.css)
content/browser/backup/backup-settings.mjs (content/backup-settings.mjs)
+ content/browser/backup/turn-on-scheduled-backups.css (content/turn-on-scheduled-backups.css)
+ content/browser/backup/turn-on-scheduled-backups.mjs (content/turn-on-scheduled-backups.mjs)
diff --git a/browser/components/backup/tests/browser/browser.toml b/browser/components/backup/tests/browser/browser.toml
index f222c3b82549..2fec03c48fc5 100644
--- a/browser/components/backup/tests/browser/browser.toml
+++ b/browser/components/backup/tests/browser/browser.toml
@@ -2,6 +2,7 @@
prefs = [
"browser.backup.enabled=true",
"browser.backup.preferences.ui.enabled=true",
+ "browser.backup.scheduled.enabled=false",
]
["browser_settings.js"]
diff --git a/browser/components/backup/tests/browser/browser_settings.js b/browser/components/backup/tests/browser/browser_settings.js
index b33dbec7bdf6..2dddc9d15c72 100644
--- a/browser/components/backup/tests/browser/browser_settings.js
+++ b/browser/components/backup/tests/browser/browser_settings.js
@@ -38,3 +38,51 @@ add_task(async function test_preferences_visibility() {
await SpecialPowers.popPrefEnv();
});
+
+/**
+ * Tests that the turn on scheduled backups dialog can set
+ * browser.backup.scheduled.enabled to true from the settings page.
+ */
+add_task(async function test_turn_on_scheduled_backups_confirm() {
+ await BrowserTestUtils.withNewTab("about:preferences", async browser => {
+ let settings = browser.contentDocument.querySelector("backup-settings");
+
+ await settings.updateComplete;
+
+ let turnOnButton = settings.scheduledBackupsButtonEl;
+
+ Assert.ok(
+ turnOnButton,
+ "Button to turn on scheduled backups should be found"
+ );
+
+ turnOnButton.click();
+
+ await settings.updateComplete;
+
+ let turnOnScheduledBackups = settings.turnOnScheduledBackupsEl;
+
+ Assert.ok(
+ turnOnScheduledBackups,
+ "turn-on-scheduled-backups should be found"
+ );
+
+ let confirmButton = turnOnScheduledBackups.confirmButtonEl;
+ let promise = BrowserTestUtils.waitForEvent(
+ window,
+ "scheduledBackupsConfirm"
+ );
+
+ Assert.ok(confirmButton, "Confirm button should be found");
+
+ confirmButton.click();
+
+ await promise;
+ await settings.updateComplete;
+
+ let scheduledPrefVal = Services.prefs.getBoolPref(
+ "browser.backup.scheduled.enabled"
+ );
+ Assert.ok(scheduledPrefVal, "Scheduled backups pref should be true");
+ });
+});
diff --git a/browser/components/backup/tests/chrome/chrome.toml b/browser/components/backup/tests/chrome/chrome.toml
index b0c01b336f64..0e1cc0dc14aa 100644
--- a/browser/components/backup/tests/chrome/chrome.toml
+++ b/browser/components/backup/tests/chrome/chrome.toml
@@ -1,4 +1,9 @@
[DEFAULT]
+prefs = [
+ "browser.backup.scheduled.enabled=false",
+]
skip-if = ["os == 'android'"]
["test_backup_settings.html"]
+
+["test_turn_on_scheduled_backups.html"]
diff --git a/browser/components/backup/tests/chrome/test_backup_settings.html b/browser/components/backup/tests/chrome/test_backup_settings.html
index 3619f8a1f4bc..fad7137d5151 100644
--- a/browser/components/backup/tests/chrome/test_backup_settings.html
+++ b/browser/components/backup/tests/chrome/test_backup_settings.html
@@ -31,6 +31,41 @@
settings.remove();
});
+
+ /**
+ * Tests that the dialog for turning on scheduled backups can be displayed
+ * from settings, or hidden if cancelled.
+ */
+ add_task(async function test_turnOnScheduledBackupsDialog() {
+ let settings = document.getElementById("test-backup-settings");
+ settings.backupServiceState = {
+ scheduledBackupsEnabled: false,
+ }
+
+ await settings.updateComplete;
+
+ let turnOnButton = settings.scheduledBackupsButtonEl;
+ let dialog = settings.turnOnScheduledBackupsDialogEl;
+
+ ok(turnOnButton, "Button to turn on scheduled backups should be found");
+ ok(!dialog.open, "Dialog should not be open");
+
+ turnOnButton.click();
+ await settings.updateComplete;
+
+ ok(dialog?.open, "Dialog should be open");
+
+ let turnOnScheduledBackups = dialog.querySelector("turn-on-scheduled-backups");
+ ok(turnOnScheduledBackups, "turn-on-scheduled-backups should be found");
+
+ let cancelButton = turnOnScheduledBackups.shadowRoot.getElementById("backup-turn-on-scheduled-cancel-button");
+ ok(cancelButton, "Cancel button should be found");
+
+ cancelButton.click();
+ await settings.updateComplete;
+
+ ok(!dialog.open, "Dialog should not be open");
+ });
diff --git a/browser/components/backup/tests/chrome/test_turn_on_scheduled_backups.html b/browser/components/backup/tests/chrome/test_turn_on_scheduled_backups.html
new file mode 100644
index 000000000000..054df24ff756
--- /dev/null
+++ b/browser/components/backup/tests/chrome/test_turn_on_scheduled_backups.html
@@ -0,0 +1,96 @@
+
+
+
+
+ Tests for the turn-on-scheduled-backups component
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/browser/locales-preview/backupSettings.ftl b/browser/locales-preview/backupSettings.ftl
index 351a60998bda..f3d36f9c28d6 100644
--- a/browser/locales-preview/backupSettings.ftl
+++ b/browser/locales-preview/backupSettings.ftl
@@ -3,3 +3,33 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
settings-data-backup-header = Backup
+settings-data-backup-toggle = Manage backup
+
+## These strings are displayed in a modal when users want to turn on scheduled backups.
+
+turn-on-scheduled-backups-header = Turn on backup
+turn-on-scheduled-backups-description = { -brand-short-name } will create a snapshot of your data every 60 minutes. You can restore it if there’s a problem or you get a new device.
+turn-on-scheduled-backups-support-link = What will be backed up?
+
+# "Location" refers to the save location or a folder where users want backups stored.
+turn-on-scheduled-backups-location-label = Location
+# Variables:
+# $recommendedFolder (String) - Name of the recommended folder for saving backups
+turn-on-scheduled-backups-location-default-folder =
+ .value = { $recommendedFolder } (recommended)
+turn-on-scheduled-backups-location-choose-button =
+ { PLATFORM() ->
+ [macos] Choose…
+ *[other] Browse…
+ }
+
+turn-on-scheduled-backups-encryption-label = Back up your sensitive data
+turn-on-scheduled-backups-encryption-description = Back up your passwords, payment methods, and cookies with encryption.
+turn-on-scheduled-backups-encryption-create-password-label = Password
+# Users will be prompted to re-type a password, to ensure that the password is entered correctly.
+turn-on-scheduled-backups-encryption-repeat-password-label = Repeat password
+
+turn-on-scheduled-backups-cancel-button = Cancel
+turn-on-scheduled-backups-confirm-button = Turn on backup
+
+##