Backed out changeset bd72ed21a114 (bug 1901308) for Doc failure on BackupUIChild.sys . CLOSED TREE

This commit is contained in:
Narcis Beleuzu
2024-08-06 20:46:23 +03:00
parent 07b4256f45
commit e69542173f
23 changed files with 298 additions and 402 deletions

View File

@@ -456,14 +456,12 @@ let JSWINDOWACTORS = {
esModuleURI: "resource:///actors/BackupUIChild.sys.mjs",
events: {
"BackupUI:InitWidget": { wantUntrusted: true },
"BackupUI:EnableScheduledBackups": { wantUntrusted: true },
"BackupUI:DisableScheduledBackups": { wantUntrusted: true },
"BackupUI:ToggleScheduledBackups": { wantUntrusted: true },
"BackupUI:ShowFilepicker": { wantUntrusted: true },
"BackupUI:GetBackupFileInfo": { wantUntrusted: true },
"BackupUI:RestoreFromBackupFile": { wantUntrusted: true },
"BackupUI:RestoreFromBackupChooseFile": { wantUntrusted: true },
"BackupUI:EnableEncryption": { wantUntrusted: true },
"BackupUI:DisableEncryption": { wantUntrusted: true },
"BackupUI:ToggleEncryption": { wantUntrusted: true },
"BackupUI:RerunEncryption": { wantUntrusted: true },
"BackupUI:ShowBackupLocation": { wantUntrusted: true },
"BackupUI:EditBackupLocation": { wantUntrusted: true },

View File

@@ -2753,7 +2753,6 @@ export class BackupService extends EventTarget {
lazy.logConsole.error(
`Failed to set parent directory ${parentDirPath}. ${e}`
);
throw e;
}
}

View File

@@ -29,28 +29,8 @@ export class BackupUIChild extends JSWindowActorChild {
if (event.type == "BackupUI:InitWidget") {
this.#inittedWidgets.add(event.target);
this.sendAsyncMessage("RequestState");
} else if (event.type == "BackupUI:EnableScheduledBackups") {
/** @type {import("../content/turn-on-scheduled-backups.mjs").default} */
const target = event.target;
const result = await this.sendQuery(
"EnableScheduledBackups",
event.detail
);
if (result.success) {
target.close();
} else {
target.enableBackupErrorCode = result.errorCode;
}
} else if (event.type == "BackupUI:DisableScheduledBackups") {
/** @type {import("../content/turn-off-scheduled-backups.mjs").default} */
const target = event.target;
this.sendAsyncMessage("DisableScheduledBackups", event.detail);
// backups will always end up disabled even if there was an error
// with other bookkeeping related to turning off backups
target.close();
} else if (event.type == "BackupUI:ToggleScheduledBackups") {
this.sendAsyncMessage("ToggleScheduledBackups", event.detail);
} else if (event.type == "BackupUI:ShowFilepicker") {
let targetNodeName = event.target.nodeName;
let { path, filename, iconURL } = await this.sendQuery("ShowFilepicker", {
@@ -99,36 +79,10 @@ export class BackupUIChild extends JSWindowActorChild {
}
} else if (event.type == "BackupUI:RestoreFromBackupChooseFile") {
this.sendAsyncMessage("RestoreFromBackupChooseFile");
} else if (event.type == "BackupUI:EnableEncryption") {
/** @type {import("../content/enable-backup-encryption.mjs").default} */
const target = event.target;
const result = await this.sendQuery("EnableEncryption", event.detail);
if (result.success) {
target.close();
} else {
target.enableEncryptionErrorCode = result.errorCode;
}
} else if (event.type == "BackupUI:DisableEncryption") {
/** @type {import("../content/disable-backup-encryption.mjs").default} */
const target = event.target;
const result = await this.sendQuery("DisableEncryption", event.detail);
if (result.success) {
target.close();
} else {
target.disableEncryptionErrorCode = result.errorCode;
}
} else if (event.type == "BackupUI:ToggleEncryption") {
this.sendAsyncMessage("ToggleEncryption", event.detail);
} else if (event.type == "BackupUI:RerunEncryption") {
/** @type {import("../content/enable-backup-encryption.mjs").default} */
const target = event.target;
const result = await this.sendQuery("RerunEncryption", event.detail);
if (result.success) {
target.close();
} else {
target.rerunEncryptionErrorCode = result.errorCode;
}
this.sendAsyncMessage("RerunEncryption", event.detail);
} else if (event.type == "BackupUI:ShowBackupLocation") {
this.sendAsyncMessage("ShowBackupLocation");
} else if (event.type == "BackupUI:EditBackupLocation") {

View File

@@ -82,28 +82,30 @@ export class BackupUIParent extends JSWindowActorParent {
async receiveMessage(message) {
if (message.name == "RequestState") {
this.sendState();
} else if (message.name == "EnableScheduledBackups") {
try {
let { parentDirPath, password } = message.data;
} else if (message.name == "ToggleScheduledBackups") {
let { isScheduledBackupsEnabled, parentDirPath, password } = message.data;
if (isScheduledBackupsEnabled) {
if (parentDirPath) {
this.#bs.setParentDirPath(parentDirPath);
}
if (password) {
await this.#bs.enableEncryption(password);
}
this.#bs.setScheduledBackups(true);
} catch (e) {
lazy.logConsole.error(`Failed to enable scheduled backups`, e);
return { success: false, errorCode: e.cause || lazy.ERRORS.UNKNOWN };
}
/**
* TODO: (Bug 1900125) we should create a backup at the specified dir path once we turn on
* scheduled backups. The backup folder in the chosen directory should contain
* the archive file, which we create using BackupService.createArchive implemented in
* Bug 1897498.
* TODO: display an error and do not attempt to toggle scheduled backups if there
* is a problem with setting the parent directory (bug 1901308).
*/
return { success: true };
} else if (message.name == "DisableScheduledBackups") {
}
if (password) {
try {
await this.#bs.enableEncryption(password);
} catch (e) {
/**
* TODO: display en error and do not attempt to toggle scheduled backups if there is a
* problem with enabling encryption (bug 1901308)
*/
return null;
}
}
} else {
try {
if (this.#bs.state.encryptionEnabled) {
await this.#bs.disableEncryption();
@@ -112,7 +114,18 @@ export class BackupUIParent extends JSWindowActorParent {
} catch (e) {
// no-op so that scheduled backups can still be turned off
}
this.#bs.setScheduledBackups(false);
}
this.#bs.setScheduledBackups(isScheduledBackupsEnabled);
return true;
/**
* TODO: (Bug 1900125) we should create a backup at the specified dir path once we turn on
* scheduled backups. The backup folder in the chosen directory should contain
* the archive file, which we create using BackupService.createArchive implemented in
* Bug 1897498.
*/
} else if (message.name == "ShowFilepicker") {
let { win, filter, displayDirectoryPath } = message.data;
@@ -178,45 +191,52 @@ export class BackupUIParent extends JSWindowActorParent {
return { success: false, errorCode: e.cause || lazy.ERRORS.UNKNOWN };
}
return { success: true };
} else if (message.name == "EnableEncryption") {
try {
await this.#bs.enableEncryption(message.data.password);
} catch (e) {
lazy.logConsole.error(`Failed to enable encryption`, e);
return { success: false, errorCode: e.cause || lazy.ERRORS.UNKNOWN };
}
/**
* TODO: (Bug 1901640) after enabling encryption, recreate the backup,
* this time with sensitive data.
*/
return { success: true };
} else if (message.name == "DisableEncryption") {
} else if (message.name == "ToggleEncryption") {
let { isEncryptionEnabled, password } = message.data;
if (!isEncryptionEnabled) {
try {
await this.#bs.disableEncryption();
} catch (e) {
lazy.logConsole.error(`Failed to disable encryption`, e);
return { success: false, errorCode: e.cause || lazy.ERRORS.UNKNOWN };
}
/**
* TODO: (Bug 1901640) after disabling encryption, recreate the backup,
* this time without sensitive data.
*/
return { success: true };
} else if (message.name == "RerunEncryption") {
} catch (e) {
/**
* TODO: (Bug 1901308) maybe display an error if there is a problem with
* disabling encryption.
*/
}
} else {
try {
await this.#bs.enableEncryption(password);
/**
* TODO: (Bug 1901640) after enabling encryption, recreate the backup,
* this time with sensitive data.
*/
} catch (e) {
/**
* TODO: (Bug 1901308) maybe display an error if there is a problem with
* enabling encryption.
*/
}
}
} else if (message.name == "RerunEncryption") {
let { password } = message.data;
try {
await this.#bs.disableEncryption();
await this.#bs.enableEncryption(password);
} catch (e) {
lazy.logConsole.error(`Failed to rerun encryption`, e);
return { success: false, errorCode: e.cause || lazy.ERRORS.UNKNOWN };
}
/**
* TODO: (Bug 1901640) after enabling encryption, recreate the backup,
* this time with the new password.
*/
return { success: true };
} catch (e) {
/**
* TODO: (Bug 1901308) maybe display an error if there is a problem with
* re-encryption.
*/
}
} else if (message.name == "ShowBackupLocation") {
this.#bs.showBackupLocation();
} else if (message.name == "EditBackupLocation") {

View File

@@ -93,14 +93,44 @@ export default class BackupSettings extends MozLitElement {
new CustomEvent("BackupUI:InitWidget", { bubbles: true })
);
this.addEventListener("turnOnScheduledBackups", this);
this.addEventListener("turnOffScheduledBackups", this);
this.addEventListener("dialogCancel", this);
this.addEventListener("getBackupFileInfo", this);
this.addEventListener("enableEncryption", this);
this.addEventListener("rerunEncryption", this);
this.addEventListener("disableEncryption", this);
this.addEventListener("restoreFromBackupConfirm", this);
this.addEventListener("restoreFromBackupChooseFile", this);
}
handleEvent(event) {
switch (event.type) {
case "turnOnScheduledBackups":
this.turnOnScheduledBackupsDialogEl.close();
this.dispatchEvent(
new CustomEvent("BackupUI:ToggleScheduledBackups", {
bubbles: true,
composed: true,
detail: {
...event.detail,
isScheduledBackupsEnabled: true,
},
})
);
break;
case "turnOffScheduledBackups":
this.turnOffScheduledBackupsDialogEl.close();
this.dispatchEvent(
new CustomEvent("BackupUI:ToggleScheduledBackups", {
bubbles: true,
composed: true,
detail: {
isScheduledBackupsEnabled: false,
},
})
);
break;
case "dialogCancel":
if (this.turnOnScheduledBackupsDialogEl.open) {
this.turnOnScheduledBackupsDialogEl.close();
@@ -145,6 +175,43 @@ export default class BackupSettings extends MozLitElement {
})
);
break;
case "enableEncryption":
this.enableBackupEncryptionDialogEl.close();
this.dispatchEvent(
new CustomEvent("BackupUI:ToggleEncryption", {
bubbles: true,
composed: true,
detail: {
...event.detail,
isEncryptionEnabled: true,
},
})
);
break;
case "rerunEncryption":
this.enableBackupEncryptionDialogEl.close();
this.dispatchEvent(
new CustomEvent("BackupUI:RerunEncryption", {
bubbles: true,
composed: true,
detail: {
...event.detail,
},
})
);
break;
case "disableEncryption":
this.disableBackupEncryptionDialogEl.close();
this.dispatchEvent(
new CustomEvent("BackupUI:ToggleEncryption", {
bubbles: true,
composed: true,
detail: {
isEncryptionEnabled: false,
},
})
);
break;
}
}

View File

@@ -5,66 +5,47 @@
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://global/content/elements/moz-message-bar.mjs";
const ERROR_L10N_ID = "backup-error-retry";
/**
* The widget for disabling password protection if the backup is already
* encrypted.
*/
export default class DisableBackupEncryption extends MozLitElement {
static properties = {
// managed by BackupUIChild
disableEncryptionErrorCode: { type: Number },
};
static get queries() {
return {
cancelButtonEl: "#backup-disable-encryption-cancel-button",
confirmButtonEl: "#backup-disable-encryption-confirm-button",
errorEl: "#disable-backup-encryption-error",
};
}
constructor() {
super();
this.disableEncryptionErrorCode = 0;
/**
* 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 })
);
}
close() {
handleCancel() {
this.dispatchEvent(
new CustomEvent("dialogCancel", {
bubbles: true,
composed: true,
})
);
this.reset();
}
reset() {
this.disableEncryptionErrorCode = 0;
}
handleConfirm() {
this.dispatchEvent(
new CustomEvent("BackupUI:DisableEncryption", {
new CustomEvent("disableEncryption", {
bubbles: true,
composed: true,
})
);
}
errorTemplate() {
return html`
<moz-message-bar
id="disable-backup-encryption-error"
type="error"
.messageL10nId="${ERROR_L10N_ID}"
></moz-message-bar>
`;
}
contentTemplate() {
return html`
<div
@@ -92,13 +73,12 @@ export default class DisableBackupEncryption extends MozLitElement {
data-l10n-id="disable-backup-encryption-support-link"
></a>
</div>
${this.disableEncryptionErrorCode ? this.errorTemplate() : null}
</main>
<moz-button-group id="backup-disable-encryption-button-group">
<moz-button
id="backup-disable-encryption-cancel-button"
@click=${this.close}
@click=${this.handleCancel}
data-l10n-id="disable-backup-encryption-cancel-button"
></moz-button>
<moz-button

View File

@@ -5,40 +5,21 @@
// eslint-disable-next-line import/no-unresolved
import { html } from "lit.all.mjs";
import "chrome://global/content/elements/moz-card.mjs";
import { ERRORS } from "chrome://browser/content/backup/backup-constants.mjs";
import "./disable-backup-encryption.mjs";
window.MozXULElement.insertFTLIfNeeded("locales-preview/backupSettings.ftl");
window.MozXULElement.insertFTLIfNeeded("branding/brand.ftl");
const SELECTABLE_ERRORS = {
"(none)": 0,
...ERRORS,
};
export default {
title: "Domain-specific UI Widgets/Backup/Disable Encryption",
component: "disable-backup-encryption",
argTypes: {
disableEncryptionErrorCode: {
options: Object.keys(SELECTABLE_ERRORS),
mapping: SELECTABLE_ERRORS,
control: { type: "select" },
},
},
argTypes: {},
};
const Template = ({ disableEncryptionErrorCode }) => html`
const Template = () => html`
<moz-card style="width: 23.94rem;">
<disable-backup-encryption
.disableEncryptionErrorCode=${disableEncryptionErrorCode}
></disable-backup-encryption>
<disable-backup-encryption></disable-backup-encryption>
</moz-card>
`;
export const Default = Template.bind({});
export const DisableError = Template.bind({});
DisableError.args = {
disableEncryptionErrorCode: ERRORS.UNKNOWN,
};

View File

@@ -5,13 +5,9 @@
import { html, ifDefined } 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://global/content/elements/moz-message-bar.mjs";
// eslint-disable-next-line import/no-unassigned-import
import "chrome://browser/content/backup/password-validation-inputs.mjs";
import { ERRORS } from "chrome://browser/content/backup/backup-constants.mjs";
/**
* Valid attributes for the enable-backup-encryption dialog type.
*
@@ -27,30 +23,14 @@ const VALID_L10N_IDS = new Map([
[VALID_TYPES.CHANGE_PASSWORD, "change-backup-encryption-header"],
]);
const ERROR_L10N_IDS = Object.freeze({
[ERRORS.INVALID_PASSWORD]: "backup-error-password-requirements",
[ERRORS.UNKNOWN]: "backup-error-retry",
});
/**
* @param {number} errorCode Error code from backup-constants.mjs
* @returns {string} Localization ID for error message
*/
function getErrorL10nId(errorCode) {
return ERROR_L10N_IDS[errorCode] ?? ERROR_L10N_IDS[ERRORS.UNKNOWN];
}
/**
* The widget for enabling password protection if the backup is not yet
* encrypted.
*/
export default class EnableBackupEncryption extends MozLitElement {
static properties = {
// internal state
_inputPassValue: { type: String, state: true },
_passwordsMatch: { type: Boolean, state: true },
// passed from parents
supportBaseLink: { type: String },
/**
* The "type" attribute changes the layout.
@@ -58,10 +38,6 @@ export default class EnableBackupEncryption extends MozLitElement {
* @see VALID_TYPES
*/
type: { type: String, reflect: true },
// managed by BackupUIChild
enableEncryptionErrorCode: { type: Number },
rerunEncryptionErrorCode: { type: Number },
};
static get queries() {
@@ -72,7 +48,6 @@ export default class EnableBackupEncryption extends MozLitElement {
textHeaderEl: "#backup-enable-encryption-header",
textDescriptionEl: "#backup-enable-encryption-description",
passwordInputsEl: "#backup-enable-encryption-password-inputs",
errorEl: "#enable-backup-encryption-error",
};
}
@@ -82,13 +57,18 @@ export default class EnableBackupEncryption extends MozLitElement {
this.type = VALID_TYPES.SET_PASSWORD;
this._inputPassValue = "";
this._passwordsMatch = false;
this.enableEncryptionErrorCode = 0;
this.rerunEncryptionErrorCode = 0;
}
/**
* Dispatches the BackupUI:InitWidget custom event upon being attached to the
* DOM, which registers with BackupUIChild for BackupService state updates.
*/
connectedCallback() {
super.connectedCallback();
// Listening to events from child <password-validation-inputs>
this.dispatchEvent(
new CustomEvent("BackupUI:InitWidget", { bubbles: true })
);
this.addEventListener("ValidPasswordsDetected", this);
this.addEventListener("InvalidPasswordsDetected", this);
}
@@ -104,29 +84,23 @@ export default class EnableBackupEncryption extends MozLitElement {
}
}
close() {
handleCancel() {
this.dispatchEvent(
new CustomEvent("dialogCancel", {
bubbles: true,
composed: true,
})
);
this.reset();
}
reset() {
this._inputPassValue = "";
this._passwordsMatch = false;
this.passwordInputsEl.reset();
this.enableEncryptionErrorCode = 0;
this.resetChanges();
}
handleConfirm() {
switch (this.type) {
case VALID_TYPES.SET_PASSWORD:
this.dispatchEvent(
new CustomEvent("BackupUI:EnableEncryption", {
new CustomEvent("enableEncryption", {
bubbles: true,
composed: true,
detail: {
password: this._inputPassValue,
},
@@ -135,8 +109,9 @@ export default class EnableBackupEncryption extends MozLitElement {
break;
case VALID_TYPES.CHANGE_PASSWORD:
this.dispatchEvent(
new CustomEvent("BackupUI:RerunEncryption", {
new CustomEvent("rerunEncryption", {
bubbles: true,
composed: true,
detail: {
password: this._inputPassValue,
},
@@ -144,6 +119,16 @@ export default class EnableBackupEncryption extends MozLitElement {
);
break;
}
this.resetChanges();
}
resetChanges() {
this._inputPassValue = "";
this._passwordsMatch = false;
this.passwordInputsEl.dispatchEvent(
new CustomEvent("resetInputs", { bubbles: true, composed: true })
);
}
descriptionTemplate() {
@@ -170,7 +155,7 @@ export default class EnableBackupEncryption extends MozLitElement {
<moz-button-group id="backup-enable-encryption-button-group">
<moz-button
id="backup-enable-encryption-cancel-button"
@click=${this.close}
@click=${this.handleCancel}
data-l10n-id="enable-backup-encryption-cancel-button"
></moz-button>
<moz-button
@@ -184,19 +169,6 @@ export default class EnableBackupEncryption extends MozLitElement {
`;
}
errorTemplate() {
let messageId = this.enableEncryptionErrorCode
? getErrorL10nId(this.enableEncryptionErrorCode)
: getErrorL10nId(this.rerunEncryptionErrorCode);
return html`
<moz-message-bar
id="enable-backup-encryption-error"
type="error"
.messageL10nId="${messageId}"
></moz-message-bar>
`;
}
contentTemplate() {
return html`
<div
@@ -218,10 +190,6 @@ export default class EnableBackupEncryption extends MozLitElement {
.supportBaseLink=${this.supportBaseLink}
>
</password-validation-inputs>
${this.enableEncryptionErrorCode || this.rerunEncryptionErrorCode
? this.errorTemplate()
: null}
</div>
${this.buttonGroupTemplate()}
</div>

View File

@@ -5,17 +5,11 @@
// eslint-disable-next-line import/no-unresolved
import { html } from "lit.all.mjs";
import "chrome://global/content/elements/moz-card.mjs";
import { ERRORS } from "chrome://browser/content/backup/backup-constants.mjs";
import "./enable-backup-encryption.mjs";
window.MozXULElement.insertFTLIfNeeded("locales-preview/backupSettings.ftl");
window.MozXULElement.insertFTLIfNeeded("branding/brand.ftl");
const SELECTABLE_ERRORS = {
"(none)": 0,
...ERRORS,
};
export default {
title: "Domain-specific UI Widgets/Backup/Enable Encryption",
component: "enable-backup-encryption",
@@ -24,30 +18,12 @@ export default {
control: { type: "select" },
options: ["set-password", "change-password"],
},
enableEncryptionErrorCode: {
options: Object.keys(SELECTABLE_ERRORS),
mapping: SELECTABLE_ERRORS,
control: { type: "select" },
},
rerunEncryptionErrorCode: {
options: Object.keys(SELECTABLE_ERRORS),
mapping: SELECTABLE_ERRORS,
control: { type: "select" },
},
},
};
const Template = ({
type,
enableEncryptionErrorCode,
rerunEncryptionErrorCode,
}) => html`
const Template = ({ type }) => html`
<moz-card style="width: 23.94rem; position: relative;">
<enable-backup-encryption
type=${type}
.enableEncryptionErrorCode=${enableEncryptionErrorCode}
.rerunEncryptionErrorCode=${rerunEncryptionErrorCode}
></enable-backup-encryption>
<enable-backup-encryption type=${type}></enable-backup-encryption>
</moz-card>
`;
@@ -60,15 +36,3 @@ export const ChangePassword = Template.bind({});
ChangePassword.args = {
type: "change-password",
};
export const SetPasswordError = Template.bind({});
SetPasswordError.args = {
type: "set-password",
enableEncryptionErrorCode: ERRORS.INVALID_PASSWORD,
};
export const ChangePasswordError = Template.bind({});
ChangePasswordError.args = {
type: "change-password",
rerunEncryptionErrorCode: ERRORS.INVALID_PASSWORD,
};

View File

@@ -48,7 +48,17 @@ export default class PasswordValidationInputs extends MozLitElement {
this._tooltipFocus = false;
}
reset() {
connectedCallback() {
super.connectedCallback();
this.addEventListener("resetInputs", this.handleReset);
}
disconnectedCallback() {
super.disconnectedCallback();
this.removeEventListener("resetInputs", this.handleReset);
}
handleReset() {
this.formEl.reset();
this._showRules = false;
this._hasCommon = false;

View File

@@ -17,7 +17,18 @@ export default class TurnOffScheduledBackups extends MozLitElement {
};
}
close() {
/**
* 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 })
);
}
handleCancel() {
this.dispatchEvent(
new CustomEvent("dialogCancel", {
bubbles: true,
@@ -28,8 +39,9 @@ export default class TurnOffScheduledBackups extends MozLitElement {
handleConfirm() {
this.dispatchEvent(
new CustomEvent("BackupUI:DisableScheduledBackups", {
new CustomEvent("turnOffScheduledBackups", {
bubbles: true,
composed: true,
})
);
}
@@ -65,7 +77,7 @@ export default class TurnOffScheduledBackups extends MozLitElement {
<moz-button-group id="backup-turn-off-scheduled-button-group">
<moz-button
id="backup-turn-off-scheduled-cancel-button"
@click=${this.close}
@click=${this.handleCancel}
data-l10n-id="turn-off-scheduled-backups-cancel-button"
></moz-button>
<moz-button

View File

@@ -5,29 +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://global/content/elements/moz-message-bar.mjs";
// eslint-disable-next-line import/no-unassigned-import
import "chrome://browser/content/backup/password-validation-inputs.mjs";
import { ERRORS } from "chrome://browser/content/backup/backup-constants.mjs";
const ENABLE_ERROR_L10N_IDS = Object.freeze({
[ERRORS.FILE_SYSTEM_ERROR]: "turn-on-scheduled-backups-error-file-system",
[ERRORS.INVALID_PASSWORD]: "backup-error-password-requirements",
[ERRORS.UNKNOWN]: "backup-error-retry",
});
/**
* @param {number} errorCode Error code from backup-constants.mjs
* @returns {string} Localization ID for error message
*/
function getEnableErrorL10nId(errorCode) {
return (
ENABLE_ERROR_L10N_IDS[errorCode] ?? ENABLE_ERROR_L10N_IDS[ERRORS.UNKNOWN]
);
}
/**
* The widget for showing available options when users want to turn on
* scheduled backups.
@@ -36,22 +16,16 @@ export default class TurnOnScheduledBackups extends MozLitElement {
#placeholderIconURL = "chrome://global/skin/icons/page-portrait.svg";
static properties = {
// passed in from parents
defaultIconURL: { type: String, reflect: true },
defaultLabel: { type: String, reflect: true },
defaultPath: { type: String, reflect: true },
supportBaseLink: { type: String },
// internal state
_newIconURL: { type: String, state: true },
_newLabel: { type: String, state: true },
_newPath: { type: String, state: true },
_newIconURL: { type: String },
_newLabel: { type: String },
_newPath: { type: String },
_showPasswordOptions: { type: Boolean, reflect: true, state: true },
_passwordsMatch: { type: Boolean, state: true },
_inputPassValue: { type: String, state: true },
// managed by BackupUIChild
enableBackupErrorCode: { type: Number },
supportBaseLink: { type: String },
};
static get queries() {
@@ -63,7 +37,6 @@ export default class TurnOnScheduledBackups extends MozLitElement {
filePathInputDefaultEl: "#backup-location-filepicker-input-default",
passwordOptionsCheckboxEl: "#sensitive-data-checkbox-input",
passwordOptionsExpandedEl: "#passwords",
errorEl: "#enable-backup-encryption-error",
};
}
@@ -77,19 +50,19 @@ export default class TurnOnScheduledBackups extends MozLitElement {
this._newPath = "";
this._showPasswordOptions = false;
this._passwordsMatch = false;
this.enableBackupErrorCode = 0;
}
/**
* 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 })
);
// listen to events from BackupUIChild
this.addEventListener("BackupUI:SelectNewFilepickerPath", this);
// listen to events from <password-validation-inputs>
this.addEventListener("ValidPasswordsDetected", this);
this.addEventListener("InvalidPasswordsDetected", this);
}
@@ -121,14 +94,14 @@ export default class TurnOnScheduledBackups extends MozLitElement {
);
}
close() {
handleCancel() {
this.dispatchEvent(
new CustomEvent("dialogCancel", {
bubbles: true,
composed: true,
})
);
this.reset();
this.resetChanges();
}
handleConfirm() {
@@ -141,11 +114,13 @@ export default class TurnOnScheduledBackups extends MozLitElement {
}
this.dispatchEvent(
new CustomEvent("BackupUI:EnableScheduledBackups", {
new CustomEvent("turnOnScheduledBackups", {
bubbles: true,
composed: true,
detail,
})
);
this.resetChanges();
}
handleTogglePasswordOptions() {
@@ -153,7 +128,7 @@ export default class TurnOnScheduledBackups extends MozLitElement {
this._passwordsMatch = false;
}
reset() {
resetChanges() {
this._newPath = "";
this._newIconURL = "";
this._newLabel = "";
@@ -161,12 +136,11 @@ export default class TurnOnScheduledBackups extends MozLitElement {
this.passwordOptionsCheckboxEl.checked = false;
this._passwordsMatch = false;
this._inputPassValue = "";
this.enableBackupErrorCode = 0;
if (this.passwordOptionsExpandedEl) {
/** @type {import("./password-validation-inputs.mjs").default} */
const passwordElement = this.passwordOptionsExpandedEl;
passwordElement.reset();
this.passwordOptionsExpandedEl.dispatchEvent(
new CustomEvent("resetInputs", { bubbles: true, composed: true })
);
}
}
@@ -206,16 +180,6 @@ export default class TurnOnScheduledBackups extends MozLitElement {
`;
}
errorTemplate() {
return html`
<moz-message-bar
id="enable-backup-encryption-error"
type="error"
.messageL10nId="${getEnableErrorL10nId(this.enableBackupErrorCode)}"
></moz-message-bar>
`;
}
allOptionsTemplate() {
return html`
<fieldset id="all-controls">
@@ -305,13 +269,12 @@ export default class TurnOnScheduledBackups extends MozLitElement {
></a>
</div>
${this.allOptionsTemplate()}
${this.enableBackupErrorCode ? this.errorTemplate() : null}
</main>
<moz-button-group id="backup-turn-on-scheduled-button-group">
<moz-button
id="backup-turn-on-scheduled-cancel-button"
@click=${this.close}
@click=${this.handleCancel}
data-l10n-id="turn-on-scheduled-backups-cancel-button"
></moz-button>
<moz-button

View File

@@ -5,43 +5,24 @@
// eslint-disable-next-line import/no-unresolved
import { html, ifDefined } from "lit.all.mjs";
import "chrome://global/content/elements/moz-card.mjs";
import { ERRORS } from "chrome://browser/content/backup/backup-constants.mjs";
import "./turn-on-scheduled-backups.mjs";
window.MozXULElement.insertFTLIfNeeded("locales-preview/backupSettings.ftl");
window.MozXULElement.insertFTLIfNeeded("branding/brand.ftl");
const SELECTABLE_ERRORS = {
"(none)": 0,
...ERRORS,
};
export default {
title: "Domain-specific UI Widgets/Backup/Turn On Scheduled Backups",
component: "turn-on-scheduled-backups",
argTypes: {
enableBackupErrorCode: {
options: Object.keys(SELECTABLE_ERRORS),
mapping: SELECTABLE_ERRORS,
control: { type: "select" },
},
},
argTypes: {},
};
const Template = ({
defaultPath,
_newPath,
defaultLabel,
_newLabel,
enableBackupErrorCode,
}) => html`
const Template = ({ defaultPath, _newPath, defaultLabel, _newLabel }) => html`
<moz-card style="width: 27.8rem; position: relative;">
<turn-on-scheduled-backups
defaultPath=${defaultPath}
_newPath=${ifDefined(_newPath)}
defaultLabel=${defaultLabel}
_newLabel=${ifDefined(_newLabel)}
.enableBackupErrorCode=${enableBackupErrorCode}
></turn-on-scheduled-backups>
</moz-card>
`;
@@ -58,9 +39,3 @@ CustomLocation.args = {
_newPath: "/Some/Test/Custom/Dir",
_newLabel: "Dir",
};
export const EnableError = Template.bind({});
EnableError.args = {
...CustomLocation.args,
enableBackupErrorCode: ERRORS.FILE_SYSTEM_ERROR,
};

View File

@@ -99,10 +99,7 @@ add_task(async function test_disable_backup_encryption_confirm() {
);
let confirmButton = disableBackupEncryption.confirmButtonEl;
let promise = BrowserTestUtils.waitForEvent(
window,
"BackupUI:DisableEncryption"
);
let promise = BrowserTestUtils.waitForEvent(window, "disableEncryption");
Assert.ok(confirmButton, "Confirm button should be found");

View File

@@ -91,7 +91,7 @@ add_task(async function test_enable_backup_encryption_checkbox_confirm() {
let encryptionPromise = BrowserTestUtils.waitForEvent(
window,
"BackupUI:EnableEncryption"
"enableEncryption"
);
confirmButton.click();
@@ -185,10 +185,7 @@ add_task(
await settings.updateComplete;
confirmButton = settings.enableBackupEncryptionEl.confirmButtonEl;
let promise = BrowserTestUtils.waitForEvent(
window,
"BackupUI:RerunEncryption"
);
let promise = BrowserTestUtils.waitForEvent(window, "rerunEncryption");
confirmButton.click();
await promise;

View File

@@ -37,7 +37,7 @@ async function turnOffScheduledBackupsHelper(browser, taskFn) {
let confirmButton = turnOffScheduledBackups.confirmButtonEl;
let promise = BrowserTestUtils.waitForEvent(
window,
"BackupUI:DisableScheduledBackups"
"turnOffScheduledBackups"
);
Assert.ok(confirmButton, "Confirm button should be found");

View File

@@ -3,10 +3,6 @@
"use strict";
const { ERRORS } = ChromeUtils.importESModule(
"chrome://browser/content/backup/backup-constants.mjs"
);
const SCHEDULED_BACKUPS_ENABLED_PREF = "browser.backup.scheduled.enabled";
add_setup(async () => {
@@ -47,7 +43,7 @@ add_task(async function test_turn_on_scheduled_backups_confirm() {
let confirmButton = turnOnScheduledBackups.confirmButtonEl;
let promise = BrowserTestUtils.waitForEvent(
window,
"BackupUI:EnableScheduledBackups"
"turnOnScheduledBackups"
);
Assert.ok(confirmButton, "Confirm button should be found");
@@ -90,7 +86,6 @@ add_task(async function test_turn_on_custom_location_filepicker() {
MockFilePicker.returnValue = MockFilePicker.returnOK;
// After setting up mocks, start testing components
/** @type {import("../../content/backup-settings.mjs").default} */
let settings = browser.contentDocument.querySelector("backup-settings");
let turnOnButton = settings.scheduledBackupsButtonEl;
@@ -153,7 +148,7 @@ add_task(async function test_turn_on_custom_location_filepicker() {
let confirmButtonPromise = BrowserTestUtils.waitForEvent(
window,
"BackupUI:EnableScheduledBackups"
"turnOnScheduledBackups"
);
confirmButton.click();
@@ -239,7 +234,7 @@ add_task(async function test_turn_on_scheduled_backups_encryption() {
let promise = BrowserTestUtils.waitForEvent(
window,
"BackupUI:EnableScheduledBackups"
"turnOnScheduledBackups"
);
confirmButton.click();
@@ -285,7 +280,7 @@ add_task(async function test_turn_on_scheduled_backups_encryption_error() {
let encryptionStub = sandbox
.stub(BackupService.prototype, "enableEncryption")
.throws(new Error("test error", { cause: ERRORS.INVALID_PASSWORD }));
.throws();
// Enable passwords
let passwordsCheckbox = turnOnScheduledBackups.passwordOptionsCheckboxEl;
@@ -322,7 +317,7 @@ add_task(async function test_turn_on_scheduled_backups_encryption_error() {
let promise = BrowserTestUtils.waitForEvent(
window,
"BackupUI:EnableScheduledBackups"
"turnOnScheduledBackups"
);
confirmButton.click();
@@ -344,16 +339,6 @@ add_task(async function test_turn_on_scheduled_backups_encryption_error() {
"Scheduled backups pref should still be false"
);
await BrowserTestUtils.waitForCondition(
() => !!turnOnScheduledBackups.errorEl,
"Error should be displayed to the user"
);
Assert.ok(
turnOnScheduledBackups.errorEl,
"Error should be displayed to the user"
);
sandbox.restore();
Services.prefs.clearUserPref(SCHEDULED_BACKUPS_ENABLED_PREF);
});

View File

@@ -9,7 +9,6 @@ const { BackupService } = ChromeUtils.importESModule(
const { MockFilePicker } = SpecialPowers;
/** @type {{sinon: import("@types/sinon").SinonApi}} */
const { sinon } = ChromeUtils.importESModule(
"resource://testing-common/Sinon.sys.mjs"
);

View File

@@ -16,6 +16,22 @@
"resource://testing-common/BrowserTestUtils.sys.mjs"
);
/**
* Tests that adding a disable-backup-encryption element to the DOM causes it to
* fire a BackupUI:InitWidget event.
*/
add_task(async function test_initWidget() {
let disableBackupEncryption = document.createElement("disable-backup-encryption");
let content = document.getElementById("content");
let sawInitWidget = BrowserTestUtils.waitForEvent(content, "BackupUI:InitWidget");
content.appendChild(disableBackupEncryption);
await sawInitWidget;
ok(true, "Saw BackupUI:InitWidget");
disableBackupEncryption.remove();
});
/**
* Tests that pressing the confirm button will dispatch the expected events.
*/
@@ -26,7 +42,7 @@
ok(confirmButton, "Confirm button should be found");
let content = document.getElementById("content");
let promise = BrowserTestUtils.waitForEvent(content, "BackupUI:DisableEncryption");
let promise = BrowserTestUtils.waitForEvent(content, "disableEncryption");
confirmButton.click()

View File

@@ -17,6 +17,22 @@
"resource://testing-common/BrowserTestUtils.sys.mjs"
);
/**
* Tests that adding a enable-backup-encryption element to the DOM causes it to
* fire a BackupUI:InitWidget event.
*/
add_task(async function test_initWidget() {
let enableBackupEncryption = document.createElement("enable-backup-encryption");
let content = document.getElementById("content");
let sawInitWidget = BrowserTestUtils.waitForEvent(content, "BackupUI:InitWidget");
content.appendChild(enableBackupEncryption);
await sawInitWidget;
ok(true, "Saw BackupUI:InitWidget");
enableBackupEncryption.remove();
});
/**
* Tests that pressing the confirm button for the set-password type dialog will dispatch the expected events.
*/
@@ -45,14 +61,12 @@
ok(!confirmButton.disabled, "Confirm button should no longer be disabled");
let content = document.getElementById("content");
let encryptionPromise = BrowserTestUtils.waitForEvent(content, "BackupUI:EnableEncryption");
let encryptionPromise = BrowserTestUtils.waitForEvent(content, "enableEncryption");
confirmButton.click()
await encryptionPromise;
ok(true, "Detected event after selecting the confirm button");
enableBackupEncryption.reset();
})
/**
@@ -85,14 +99,12 @@
ok(!confirmButton.disabled, "Confirm button should no longer be disabled");
let content = document.getElementById("content");
let encryptionPromise = BrowserTestUtils.waitForEvent(content, "BackupUI:RerunEncryption");
let encryptionPromise = BrowserTestUtils.waitForEvent(content, "rerunEncryption");
confirmButton.click()
await encryptionPromise;
ok(true, "Detected event after selecting the confirm button");
enableBackupEncryption.reset();
})
/**
@@ -114,8 +126,6 @@
await promise;
ok(true, "Detected event after selecting the cancel button");
enableBackupEncryption.reset();
})
</script>
</head>

View File

@@ -16,6 +16,22 @@
"resource://testing-common/BrowserTestUtils.sys.mjs"
);
/**
* Tests that adding a turn-off-scheduled-backups element to the DOM causes it to
* fire a BackupUI:InitWidget event.
*/
add_task(async function test_initWidget() {
let turnOffScheduledBackups = document.createElement("turn-off-scheduled-backups");
let content = document.getElementById("content");
let sawInitWidget = BrowserTestUtils.waitForEvent(content, "BackupUI:InitWidget");
content.appendChild(turnOffScheduledBackups);
await sawInitWidget;
ok(true, "Saw BackupUI:InitWidget");
turnOffScheduledBackups.remove();
});
/**
* Tests that pressing the confirm button will dispatch the expected events.
*/
@@ -26,7 +42,7 @@
ok(confirmButton, "Confirm button should be found");
let content = document.getElementById("content");
let promise = BrowserTestUtils.waitForEvent(content, "BackupUI:DisableScheduledBackups");
let promise = BrowserTestUtils.waitForEvent(content, "turnOffScheduledBackups");
confirmButton.click()

View File

@@ -45,7 +45,7 @@
ok(confirmButton, "Confirm button should be found");
let content = document.getElementById("content");
let promise = BrowserTestUtils.waitForEvent(content, "BackupUI:EnableScheduledBackups");
let promise = BrowserTestUtils.waitForEvent(content, "turnOnScheduledBackups");
confirmButton.click()

View File

@@ -81,10 +81,6 @@ 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
# Tell the user there was an error accessing the user's selected backup
# folder. The folder may be invalid or inaccessible.
turn-on-scheduled-backups-error-file-system = There was a problem with your selected backup folder. Choose a different folder and try again.
## These strings are displayed in a modal when users want to turn off scheduled backups.
turn-off-scheduled-backups-header = Turn off backup?
@@ -199,17 +195,6 @@ disable-backup-encryption-support-link = What will be backed up?
disable-backup-encryption-cancel-button = Cancel
disable-backup-encryption-confirm-button = Remove password
## These strings are used to tell users when errors occur when using
## the backup system
backup-error-password-requirements = Your password doesnt meet the requirements. Please try another password.
# This error message will be shown to the user when something went wrong with
# the backup system but we do not have any more specific idea of what went
# wrong. This message invites the user to try an action again because there
# is a chance that the action will succeed if retried.
backup-error-retry = Something went wrong. Please try again.
## These strings are inserted into the generated single-file backup archive.
## The single-file backup archive is a specially-crafted, static HTML file
## that is placed within a user specified directory (the Documents folder by