1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-21 02:33:46 +00:00

[PM-8297][PM-955] Improve updater behavior (#14732)

* [PM-8297] Improve updater behavior

* Remove logs

* Unused args

* Test version number

* Revert "Test version number"

This reverts commit 39ef057662.
This commit is contained in:
Daniel García
2025-05-15 13:28:04 +02:00
committed by GitHub
parent 5b864e4a73
commit 0b65861cb1
3 changed files with 56 additions and 37 deletions

View File

@@ -1,6 +1,6 @@
import { dialog, shell } from "electron"; import { dialog, shell } from "electron";
import log from "electron-log"; import log from "electron-log";
import { autoUpdater } from "electron-updater"; import { autoUpdater, UpdateDownloadedEvent, VerifyUpdateSupport } from "electron-updater";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
@@ -15,6 +15,8 @@ export class UpdaterMain {
private doingUpdateCheck = false; private doingUpdateCheck = false;
private doingUpdateCheckWithFeedback = false; private doingUpdateCheckWithFeedback = false;
private canUpdate = false; private canUpdate = false;
private updateDownloaded: UpdateDownloadedEvent = null;
private originalRolloutFunction: VerifyUpdateSupport = null;
constructor( constructor(
private i18nService: I18nService, private i18nService: I18nService,
@@ -22,6 +24,8 @@ export class UpdaterMain {
) { ) {
autoUpdater.logger = log; autoUpdater.logger = log;
this.originalRolloutFunction = autoUpdater.isUserWithinRollout;
const linuxCanUpdate = process.platform === "linux" && isAppImage(); const linuxCanUpdate = process.platform === "linux" && isAppImage();
const windowsCanUpdate = const windowsCanUpdate =
process.platform === "win32" && !isWindowsStore() && !isWindowsPortable(); process.platform === "win32" && !isWindowsStore() && !isWindowsPortable();
@@ -57,20 +61,16 @@ export class UpdaterMain {
}); });
if (result.response === 0) { if (result.response === 0) {
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. await autoUpdater.downloadUpdate();
// eslint-disable-next-line @typescript-eslint/no-floating-promises
autoUpdater.downloadUpdate();
} else { } else {
this.reset(); this.reset();
} }
} }
}); });
autoUpdater.on("update-not-available", () => { autoUpdater.on("update-not-available", async () => {
if (this.doingUpdateCheckWithFeedback && this.windowMain.win != null) { if (this.doingUpdateCheckWithFeedback && this.windowMain.win != null) {
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. await dialog.showMessageBox(this.windowMain.win, {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
dialog.showMessageBox(this.windowMain.win, {
message: this.i18nService.t("noUpdatesAvailable"), message: this.i18nService.t("noUpdatesAvailable"),
buttons: [this.i18nService.t("ok")], buttons: [this.i18nService.t("ok")],
defaultId: 0, defaultId: 0,
@@ -86,22 +86,8 @@ export class UpdaterMain {
return; return;
} }
const result = await dialog.showMessageBox(this.windowMain.win, { this.updateDownloaded = info;
type: "info", await this.promptRestartUpdate(info);
title: this.i18nService.t("bitwarden") + " - " + this.i18nService.t("restartToUpdate"),
message: this.i18nService.t("restartToUpdate"),
detail: this.i18nService.t("restartToUpdateDesc", info.version),
buttons: [this.i18nService.t("restart"), this.i18nService.t("later")],
cancelId: 1,
defaultId: 0,
noLink: true,
});
if (result.response === 0) {
// Quit and install have a different window logic, setting `isQuitting` just to be safe.
this.windowMain.isQuitting = true;
autoUpdater.quitAndInstall(true, true);
}
}); });
autoUpdater.on("error", (error) => { autoUpdater.on("error", (error) => {
@@ -117,15 +103,22 @@ export class UpdaterMain {
} }
async checkForUpdate(withFeedback = false) { async checkForUpdate(withFeedback = false) {
if (this.doingUpdateCheck || isDev()) { if (isDev()) {
return;
}
if (this.updateDownloaded && withFeedback) {
await this.promptRestartUpdate(this.updateDownloaded);
return;
}
if (this.doingUpdateCheck) {
return; return;
} }
if (!this.canUpdate) { if (!this.canUpdate) {
if (withFeedback) { if (withFeedback) {
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. void shell.openExternal("https://github.com/bitwarden/clients/releases");
// eslint-disable-next-line @typescript-eslint/no-floating-promises
shell.openExternal("https://github.com/bitwarden/clients/releases");
} }
return; return;
@@ -134,6 +127,10 @@ export class UpdaterMain {
this.doingUpdateCheckWithFeedback = withFeedback; this.doingUpdateCheckWithFeedback = withFeedback;
if (withFeedback) { if (withFeedback) {
autoUpdater.autoDownload = false; autoUpdater.autoDownload = false;
// If the user has explicitly checked for updates, we want to bypass
// the current staging rollout percentage
autoUpdater.isUserWithinRollout = (info) => true;
} }
await autoUpdater.checkForUpdates(); await autoUpdater.checkForUpdates();
@@ -141,7 +138,29 @@ export class UpdaterMain {
private reset() { private reset() {
autoUpdater.autoDownload = true; autoUpdater.autoDownload = true;
// Reset the rollout check to the default behavior
autoUpdater.isUserWithinRollout = this.originalRolloutFunction;
this.doingUpdateCheck = false; this.doingUpdateCheck = false;
this.updateDownloaded = null;
}
private async promptRestartUpdate(info: UpdateDownloadedEvent) {
const result = await dialog.showMessageBox(this.windowMain.win, {
type: "info",
title: this.i18nService.t("bitwarden") + " - " + this.i18nService.t("restartToUpdate"),
message: this.i18nService.t("restartToUpdate"),
detail: this.i18nService.t("restartToUpdateDesc", info.version),
buttons: [this.i18nService.t("restart"), this.i18nService.t("later")],
cancelId: 1,
defaultId: 0,
noLink: true,
});
if (result.response === 0) {
// Quit and install have a different window logic, setting `isQuitting` just to be safe.
this.windowMain.isQuitting = true;
autoUpdater.quitAndInstall(true, true);
}
} }
private userDisabledUpdates(): boolean { private userDisabledUpdates(): boolean {

16
package-lock.json generated
View File

@@ -135,7 +135,7 @@
"electron-log": "5.2.4", "electron-log": "5.2.4",
"electron-reload": "2.0.0-alpha.1", "electron-reload": "2.0.0-alpha.1",
"electron-store": "8.2.0", "electron-store": "8.2.0",
"electron-updater": "6.3.9", "electron-updater": "6.6.4",
"eslint": "8.57.1", "eslint": "8.57.1",
"eslint-config-prettier": "10.1.2", "eslint-config-prettier": "10.1.2",
"eslint-import-resolver-typescript": "4.3.4", "eslint-import-resolver-typescript": "4.3.4",
@@ -18500,13 +18500,13 @@
"license": "ISC" "license": "ISC"
}, },
"node_modules/electron-updater": { "node_modules/electron-updater": {
"version": "6.3.9", "version": "6.6.4",
"resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.3.9.tgz", "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.6.4.tgz",
"integrity": "sha512-2PJNONi+iBidkoC5D1nzT9XqsE8Q1X28Fn6xRQhO3YX8qRRyJ3mkV4F1aQsuRnYPqq6Hw+E51y27W75WgDoofw==", "integrity": "sha512-RcuWXbXTQkI5X3vir/eJ9S0VZQJ73eaQdlrA2J0mVrb0sbkHtnkjBMGo9umFtX8axn6r/pShN3CORxdmiF4OOw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"builder-util-runtime": "9.2.10", "builder-util-runtime": "9.3.2",
"fs-extra": "^10.1.0", "fs-extra": "^10.1.0",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"lazy-val": "^1.0.5", "lazy-val": "^1.0.5",
@@ -18517,9 +18517,9 @@
} }
}, },
"node_modules/electron-updater/node_modules/builder-util-runtime": { "node_modules/electron-updater/node_modules/builder-util-runtime": {
"version": "9.2.10", "version": "9.3.2",
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.10.tgz", "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.3.2.tgz",
"integrity": "sha512-6p/gfG1RJSQeIbz8TK5aPNkoztgY1q5TgmGFMAXcY8itsGW6Y2ld1ALsZ5UJn8rog7hKF3zHx5iQbNQ8uLcRlw==", "integrity": "sha512-7QDXJ1FwT6d9ZhG4kuObUUPY8/ENBS/Ky26O4hR5vbeoRGavgekS2Jxv+8sCn/v23aPGU2DXRWEeJuijN2ooYA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {

View File

@@ -101,7 +101,7 @@
"electron-log": "5.2.4", "electron-log": "5.2.4",
"electron-reload": "2.0.0-alpha.1", "electron-reload": "2.0.0-alpha.1",
"electron-store": "8.2.0", "electron-store": "8.2.0",
"electron-updater": "6.3.9", "electron-updater": "6.6.4",
"eslint": "8.57.1", "eslint": "8.57.1",
"eslint-config-prettier": "10.1.2", "eslint-config-prettier": "10.1.2",
"eslint-import-resolver-typescript": "4.3.4", "eslint-import-resolver-typescript": "4.3.4",