From 66683481973978b766af5190cf5416c7d1a6b98a Mon Sep 17 00:00:00 2001 From: Evan Hahn <69474926+EvanHahn-Signal@users.noreply.github.com> Date: Tue, 31 May 2022 16:22:31 +0000 Subject: [PATCH] Rewrite `WallClockListener` as `onTimeTravel` --- js/wall_clock_listener.js | 28 --------- ts/background.ts | 6 +- .../util/startTimeTravelDetector_test.ts | 59 +++++++++++++++++++ ts/util/startTimeTravelDetector.ts | 18 ++++++ ts/window.d.ts | 1 - 5 files changed, 82 insertions(+), 30 deletions(-) delete mode 100644 js/wall_clock_listener.js create mode 100644 ts/test-both/util/startTimeTravelDetector_test.ts create mode 100644 ts/util/startTimeTravelDetector.ts diff --git a/js/wall_clock_listener.js b/js/wall_clock_listener.js deleted file mode 100644 index 4b4bf63b7..000000000 --- a/js/wall_clock_listener.js +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2017-2020 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -/* global Whisper */ - -// eslint-disable-next-line func-names -(function () { - window.Whisper = window.Whisper || {}; - - let lastTime; - const interval = 1000; - let events; - function checkTime() { - const currentTime = Date.now(); - if (currentTime > lastTime + interval * 2) { - events.trigger('timetravel'); - } - lastTime = currentTime; - } - - Whisper.WallClockListener = { - init(_events) { - events = _events; - lastTime = Date.now(); - setInterval(checkTime, interval); - }, - }; -})(); diff --git a/ts/background.ts b/ts/background.ts index f5fadea70..28eaa4942 100644 --- a/ts/background.ts +++ b/ts/background.ts @@ -55,6 +55,7 @@ import { removeStorageKeyJobQueue } from './jobs/removeStorageKeyJobQueue'; import { ourProfileKeyService } from './services/ourProfileKey'; import { notificationService } from './services/notifications'; import { areWeASubscriberService } from './services/areWeASubscriber'; +import { startTimeTravelDetector } from './util/startTimeTravelDetector'; import { shouldRespondWithProfileKey } from './util/shouldRespondWithProfileKey'; import { LatestQueue } from './util/LatestQueue'; import { parseIntOrThrow } from './util/parseIntOrThrow'; @@ -1726,7 +1727,10 @@ export async function startApp(): Promise { window.setAutoHideMenuBar(hideMenuBar); window.setMenuBarVisibility(!hideMenuBar); - window.Whisper.WallClockListener.init(window.Whisper.events); + startTimeTravelDetector(() => { + window.Whisper.events.trigger('timetravel'); + }); + window.Whisper.ExpiringMessagesListener.init(window.Whisper.events); window.Whisper.TapToViewMessagesListener.init(window.Whisper.events); diff --git a/ts/test-both/util/startTimeTravelDetector_test.ts b/ts/test-both/util/startTimeTravelDetector_test.ts new file mode 100644 index 000000000..6b720a0cb --- /dev/null +++ b/ts/test-both/util/startTimeTravelDetector_test.ts @@ -0,0 +1,59 @@ +// Copyright 2022 Signal Messenger, LLC +// SPDX-License-Identifier: AGPL-3.0-only + +import * as sinon from 'sinon'; + +import { startTimeTravelDetector } from '../../util/startTimeTravelDetector'; + +describe('startTimeTravelDetector', () => { + let sandbox: sinon.SinonSandbox; + + beforeEach(() => { + sandbox = sinon.createSandbox({ useFakeTimers: true }); + }); + + afterEach(() => { + sandbox.restore(); + }); + + it('calls the callback when the time between checks is more than 2 seconds', async function test() { + const callback = sandbox.fake(); + + startTimeTravelDetector(callback); + + // Normal clock behavior + await sandbox.clock.tickAsync(1234); + await sandbox.clock.tickAsync(5678); + sinon.assert.notCalled(callback); + + // Time travel ≤2s + sandbox.clock.setSystemTime(Date.now() + 1000); + await sandbox.clock.tickAsync(1000); + sinon.assert.notCalled(callback); + sandbox.clock.setSystemTime(Date.now() + 1999); + await sandbox.clock.tickAsync(1); + sinon.assert.notCalled(callback); + + // Time travel >2s + sandbox.clock.setSystemTime(Date.now() + 2001); + await sandbox.clock.nextAsync(); + sinon.assert.calledOnce(callback); + sandbox.clock.setSystemTime(Date.now() + 9999); + await sandbox.clock.nextAsync(); + sinon.assert.calledTwice(callback); + + // Normal clock behavior + await sandbox.clock.tickAsync(9876); + sinon.assert.calledTwice(callback); + }); + + it('can detect time travel right after initialization', async () => { + const callback = sandbox.fake(); + + startTimeTravelDetector(callback); + + sandbox.clock.setSystemTime(Date.now() + 2001); + await sandbox.clock.nextAsync(); + sinon.assert.calledOnce(callback); + }); +}); diff --git a/ts/util/startTimeTravelDetector.ts b/ts/util/startTimeTravelDetector.ts new file mode 100644 index 000000000..64107ae80 --- /dev/null +++ b/ts/util/startTimeTravelDetector.ts @@ -0,0 +1,18 @@ +// Copyright 2017-2022 Signal Messenger, LLC +// SPDX-License-Identifier: AGPL-3.0-only + +const INTERVAL = 1000; + +export function startTimeTravelDetector(callback: () => unknown): void { + let lastTime = Date.now(); + setInterval(() => { + const currentTime = Date.now(); + + const sinceLastTime = currentTime - lastTime; + if (sinceLastTime > INTERVAL * 2) { + callback(); + } + + lastTime = currentTime; + }, INTERVAL); +} diff --git a/ts/window.d.ts b/ts/window.d.ts index e160745c5..17b57ec1c 100644 --- a/ts/window.d.ts +++ b/ts/window.d.ts @@ -550,7 +550,6 @@ export type WhisperType = { MessageCollection: typeof MessageModelCollectionType; GroupMemberConversation: WhatIsThis; - WallClockListener: WhatIsThis; deliveryReceiptQueue: PQueue; deliveryReceiptBatcher: BatcherType;