signal-desktop/ts/updater/macos.ts

99 lines
2.8 KiB
TypeScript
Raw Normal View History

2023-01-03 19:55:46 +00:00
// Copyright 2019 Signal Messenger, LLC
2020-10-30 20:34:04 +00:00
// SPDX-License-Identifier: AGPL-3.0-only
import { pathToFileURL } from 'url';
import { autoUpdater } from 'electron';
2023-12-04 20:56:34 +00:00
import { writeFile } from 'fs/promises';
import { join } from 'path';
2023-12-04 21:57:08 +00:00
import { Updater, createTempDir, deleteTempDir } from './common';
import { explodePromise } from '../util/explodePromise';
import * as Errors from '../types/errors';
import { DialogType } from '../types/Dialogs';
export class MacOSUpdater extends Updater {
protected async deletePreviousInstallers(): Promise<void> {
// No installers are cache on macOS
}
protected async installUpdate(updateFilePath: string): Promise<void> {
const { logger } = this;
2023-01-23 16:56:39 +00:00
logger.info('downloadAndInstall: handing download to electron...');
try {
await this.handToAutoUpdate(updateFilePath);
} catch (error) {
const readOnly = 'Cannot update while running on a read-only volume';
const message: string = error.message || '';
this.markCannotUpdate(
error,
message.includes(readOnly)
? DialogType.MacOS_Read_Only
: DialogType.Cannot_Update
);
throw error;
}
// At this point, closing the app will cause the update to be installed automatically
// because Squirrel has cached the update file and will do the right thing.
this.setUpdateListener(async () => {
2023-01-23 16:56:39 +00:00
logger.info('downloadAndInstall: restarting...');
this.markRestarting();
2021-08-23 22:45:11 +00:00
autoUpdater.quitAndInstall();
});
}
private async handToAutoUpdate(filePath: string): Promise<void> {
const { logger } = this;
const { promise, resolve, reject } = explodePromise<void>();
2024-04-11 17:47:25 +00:00
const onError = (...args: Array<unknown>) => {
logger.error('autoUpdater: error', ...args.map(Errors.toLogFormat));
const [error] = args;
2024-04-11 17:47:25 +00:00
cleanup();
reject(error);
2024-04-11 17:47:25 +00:00
};
const onDownloaded = () => {
logger.info('autoUpdater: update-downloaded event fired');
2024-04-11 17:47:25 +00:00
cleanup();
resolve();
2024-04-11 17:47:25 +00:00
};
function cleanup() {
autoUpdater.removeListener('error', onError);
autoUpdater.removeListener('update-downloaded', onDownloaded);
}
autoUpdater.on('error', onError);
autoUpdater.on('update-downloaded', onDownloaded);
2023-12-04 20:56:34 +00:00
// See: https://github.com/electron/electron/issues/5020#issuecomment-477636990
const updateUrl = pathToFileURL(filePath).href;
2023-12-04 21:57:08 +00:00
const tempDir = await createTempDir();
try {
const feedPath = join(tempDir, 'feed.json');
await writeFile(
feedPath,
JSON.stringify({
url: updateUrl,
})
);
2023-12-04 20:56:34 +00:00
2023-12-04 21:57:08 +00:00
autoUpdater.setFeedURL({
url: pathToFileURL(feedPath).href,
serverType: 'json',
});
autoUpdater.checkForUpdates();
2023-12-04 21:57:08 +00:00
await promise;
} finally {
await deleteTempDir(this.logger, tempDir);
}
}
}