diff --git a/preload.js b/preload.js index 994ddd509..fe079f40d 100644 --- a/preload.js +++ b/preload.js @@ -60,13 +60,18 @@ try { window.getAppInstance = () => config.appInstance; window.getVersion = () => config.version; window.getExpiration = () => { + const sixtyDays = 60 * 86400 * 1000; const remoteBuildExpiration = window.storage.get('remoteBuildExpiration'); + const localBuildExpiration = window.Events.getAutoDownloadUpdate() + ? config.buildExpiration + : config.buildExpiration - sixtyDays; + if (remoteBuildExpiration) { return remoteBuildExpiration < config.buildExpiration ? remoteBuildExpiration - : config.buildExpiration; + : localBuildExpiration; } - return config.buildExpiration; + return localBuildExpiration; }; window.getNodeVersion = () => config.node_version; window.getHostName = () => config.hostname; diff --git a/ts/updater/macos.ts b/ts/updater/macos.ts index ea5d16c24..48a7409c2 100644 --- a/ts/updater/macos.ts +++ b/ts/updater/macos.ts @@ -20,7 +20,6 @@ import { getPrintableError, setUpdateListener, UpdaterInterface, - UpdateInformationType, } from './common'; import { LoggerType } from '../types/Logging'; import { hexToBinary, verifySignature } from './signature'; @@ -75,13 +74,23 @@ async function checkForUpdatesMaybeInstall( const { fileName: newFileName, version: newVersion } = result; - setUpdateListener(createUpdater(getMainWindow, result, logger)); - if (fileName !== newFileName || !version || gt(newVersion, version)) { const autoDownloadUpdates = await getAutoDownloadUpdateSetting( getMainWindow() ); if (!autoDownloadUpdates) { + setUpdateListener(async () => { + logger.info( + 'performUpdate: have not downloaded update, going to download' + ); + await downloadAndInstall( + newFileName, + newVersion, + getMainWindow, + logger, + true + ); + }); getMainWindow().webContents.send( 'show-update-dialog', DialogType.DownloadReady, @@ -166,6 +175,11 @@ async function downloadAndInstall( // because Squirrel has cached the update file and will do the right thing. logger.info('downloadAndInstall: showing update dialog...'); + setUpdateListener(() => { + logger.info('performUpdate: calling quitAndInstall...'); + markShouldQuit(); + autoUpdater.quitAndInstall(); + }); getMainWindow().webContents.send('show-update-dialog', DialogType.Update, { version, }); @@ -380,28 +394,3 @@ function shutdown( ); } } - -function createUpdater( - getMainWindow: () => BrowserWindow, - info: Pick, - logger: LoggerType -) { - return async () => { - if (updateFilePath) { - logger.info('performUpdate: calling quitAndInstall...'); - markShouldQuit(); - autoUpdater.quitAndInstall(); - } else { - logger.info( - 'performUpdate: have not downloaded update, going to download' - ); - await downloadAndInstall( - info.fileName, - info.version, - getMainWindow, - logger, - true - ); - } - }; -} diff --git a/ts/updater/windows.ts b/ts/updater/windows.ts index 3d401e7e1..e81083da9 100644 --- a/ts/updater/windows.ts +++ b/ts/updater/windows.ts @@ -18,7 +18,6 @@ import { getPrintableError, setUpdateListener, UpdaterInterface, - UpdateInformationType, } from './common'; import { LoggerType } from '../types/Logging'; import { hexToBinary, verifySignature } from './signature'; @@ -78,13 +77,23 @@ async function checkForUpdatesMaybeInstall( const { fileName: newFileName, version: newVersion } = result; - setUpdateListener(createUpdater(getMainWindow, result, logger)); - if (fileName !== newFileName || !version || gt(newVersion, version)) { const autoDownloadUpdates = await getAutoDownloadUpdateSetting( getMainWindow() ); if (!autoDownloadUpdates) { + setUpdateListener(async () => { + logger.info( + 'performUpdate: have not downloaded update, going to download' + ); + await downloadAndInstall( + newFileName, + newVersion, + getMainWindow, + logger, + true + ); + }); getMainWindow().webContents.send( 'show-update-dialog', DialogType.DownloadReady, @@ -138,6 +147,23 @@ async function downloadAndInstall( } logger.info('downloadAndInstall: showing dialog...'); + setUpdateListener(async () => { + try { + await verifyAndInstall(updateFilePath, newVersion, logger); + installing = true; + } catch (error) { + logger.info('createUpdater: showing general update failure dialog...'); + getMainWindow().webContents.send( + 'show-update-dialog', + DialogType.Cannot_Update + ); + + throw error; + } + + markShouldQuit(); + app.quit(); + }); getMainWindow().webContents.send('show-update-dialog', DialogType.Update, { version, }); @@ -253,40 +279,3 @@ async function spawn( setTimeout(resolve, 200); }); } - -function createUpdater( - getMainWindow: () => BrowserWindow, - info: Pick, - logger: LoggerType -) { - return async () => { - if (updateFilePath) { - try { - await verifyAndInstall(updateFilePath, version, logger); - installing = true; - } catch (error) { - logger.info('createUpdater: showing general update failure dialog...'); - getMainWindow().webContents.send( - 'show-update-dialog', - DialogType.Cannot_Update - ); - - throw error; - } - - markShouldQuit(); - app.quit(); - } else { - logger.info( - 'performUpdate: have not downloaded update, going to download' - ); - await downloadAndInstall( - info.fileName, - info.version, - getMainWindow, - logger, - true - ); - } - }; -} diff --git a/ts/util/hasExpired.ts b/ts/util/hasExpired.ts index 750b9be92..744fa3dd9 100644 --- a/ts/util/hasExpired.ts +++ b/ts/util/hasExpired.ts @@ -1,9 +1,12 @@ // Copyright 2020 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -const env = window.getEnvironment(); +import { Environment, getEnvironment } from '../environment'; +import { isInPast } from './timestamp'; -const NINETY_ONE_DAYS = 86400 * 91 * 1000; +const ONE_DAY_MS = 86400 * 1000; +const NINETY_ONE_DAYS = 91 * ONE_DAY_MS; +const THIRTY_ONE_DAYS = 31 * ONE_DAY_MS; export function hasExpired(): boolean { const { getExpiration, log } = window; @@ -21,18 +24,23 @@ export function hasExpired(): boolean { return true; } - const tooFarIntoFuture = Date.now() + NINETY_ONE_DAYS < buildExpiration; + if (getEnvironment() === Environment.Production) { + const safeExpirationMs = window.Events.getAutoDownloadUpdate() + ? NINETY_ONE_DAYS + : THIRTY_ONE_DAYS; - if (tooFarIntoFuture) { - log.error( - 'Build expiration is set too far into the future', - buildExpiration - ); + const buildExpirationDuration = buildExpiration - Date.now(); + const tooFarIntoFuture = buildExpirationDuration > safeExpirationMs; + + if (tooFarIntoFuture) { + log.error( + 'Build expiration is set too far into the future', + buildExpiration + ); + } + + return tooFarIntoFuture || isInPast(buildExpiration); } - if (env === 'production') { - return Date.now() > buildExpiration && tooFarIntoFuture; - } - - return buildExpiration !== 0 && Date.now() > buildExpiration; + return buildExpiration !== 0 && isInPast(buildExpiration); } diff --git a/ts/util/timestamp.ts b/ts/util/timestamp.ts index d2f924017..5fdf406ac 100644 --- a/ts/util/timestamp.ts +++ b/ts/util/timestamp.ts @@ -8,3 +8,11 @@ export function isMoreRecentThan(timestamp: number, delta: number): boolean { export function isOlderThan(timestamp: number, delta: number): boolean { return timestamp <= Date.now() - delta; } + +export function isInPast(timestamp: number): boolean { + return isOlderThan(timestamp, 0); +} + +export function isInFuture(timestamp: number): boolean { + return isMoreRecentThan(timestamp, 0); +}