Skip to content

Commit

Permalink
Add timestamp utilities with helpful names
Browse files Browse the repository at this point in the history
  • Loading branch information
indutny-signal committed Mar 22, 2021
1 parent 9fa3359 commit a75402d
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 17 deletions.
5 changes: 3 additions & 2 deletions ts/LibSignalStore.ts
Expand Up @@ -5,6 +5,7 @@

import { fromEncodedBinaryToArrayBuffer, constantTimeEqual } from './Crypto';
import { isNotNil } from './util/isNotNil';
import { isMoreRecentThan } from './util/timestamp';

const TIMESTAMP_THRESHOLD = 5 * 1000; // 5 seconds
const Direction = {
Expand Down Expand Up @@ -839,7 +840,7 @@ export class SignalProtocolStore extends EventsMixin {
isNonBlockingApprovalRequired(identityRecord: IdentityKeyType): boolean {
return (
!identityRecord.firstUse &&
Date.now() - identityRecord.timestamp < TIMESTAMP_THRESHOLD &&
isMoreRecentThan(identityRecord.timestamp, TIMESTAMP_THRESHOLD) &&
!identityRecord.nonblockingApproval
);
}
Expand Down Expand Up @@ -1138,7 +1139,7 @@ export class SignalProtocolStore extends EventsMixin {
}

if (
Date.now() - identityRecord.timestamp < TIMESTAMP_THRESHOLD &&
isMoreRecentThan(identityRecord.timestamp, TIMESTAMP_THRESHOLD) &&
!identityRecord.nonblockingApproval &&
!identityRecord.firstUse
) {
Expand Down
12 changes: 8 additions & 4 deletions ts/background.ts
Expand Up @@ -8,6 +8,9 @@ import { getTitleBarVisibility, TitleBarVisibility } from './types/Settings';
import { isWindowDragElement } from './util/isWindowDragElement';
import { assert } from './util/assert';
import { routineProfileRefresh } from './routineProfileRefresh';
import { isMoreRecentThan, isOlderThan } from './util/timestamp';

const MAX_ATTACHMENT_DOWNLOAD_AGE = 3600 * 72 * 1000;

export async function startApp(): Promise<void> {
window.startupProcessingQueue = new window.Signal.Util.StartupQueue();
Expand Down Expand Up @@ -555,12 +558,11 @@ export async function startApp(): Promise<void> {
};

// How long since we were last running?
const now = Date.now();
const lastHeartbeat = window.storage.get('lastHeartbeat');
await window.storage.put('lastStartup', Date.now());

const THIRTY_DAYS = 30 * 24 * 60 * 60 * 1000;
if (lastHeartbeat > 0 && now - lastHeartbeat > THIRTY_DAYS) {
if (lastHeartbeat > 0 && isOlderThan(lastHeartbeat, THIRTY_DAYS)) {
await unlinkAndDisconnect();
}

Expand Down Expand Up @@ -2097,12 +2099,14 @@ export async function startApp(): Promise<void> {
// once we stop processing the queue.
window.attachmentDownloadQueue = undefined;

const THREE_DAYS_AGO = Date.now() - 3600 * 72 * 1000;
const MAX_ATTACHMENT_MSGS_TO_DOWNLOAD = 250;
const attachmentsToDownload = attachmentDownloadQueue.filter(
(message, index) =>
index <= MAX_ATTACHMENT_MSGS_TO_DOWNLOAD ||
message.getReceivedAt() > THREE_DAYS_AGO ||
isMoreRecentThan(
message.getReceivedAt(),
MAX_ATTACHMENT_DOWNLOAD_AGE
) ||
// Stickers and long text attachments has to be downloaded for UI
// to display the message properly.
message.hasRequiredAttachmentDownloads()
Expand Down
5 changes: 3 additions & 2 deletions ts/routineProfileRefresh.ts
Expand Up @@ -8,12 +8,14 @@ import { assert } from './util/assert';
import { missingCaseError } from './util/missingCaseError';
import { isNormalNumber } from './util/isNormalNumber';
import { map, take } from './util/iterables';
import { isOlderThan } from './util/timestamp';
import { ConversationModel } from './models/conversations';

const STORAGE_KEY = 'lastAttemptedToRefreshProfilesAt';
const MAX_AGE_TO_BE_CONSIDERED_ACTIVE = 30 * 24 * 60 * 60 * 1000;
const MAX_AGE_TO_BE_CONSIDERED_RECENTLY_REFRESHED = 1 * 24 * 60 * 60 * 1000;
const MAX_CONVERSATIONS_TO_REFRESH = 50;
const MIN_ELAPSED_DURATION_TO_REFRESH_AGAIN = 12 * 3600 * 1000;

// This type is a little stricter than what's on `window.storage`, and only requires what
// we need for easier testing.
Expand Down Expand Up @@ -81,8 +83,7 @@ function hasEnoughTimeElapsedSinceLastRefresh(storage: StorageType): boolean {
}

if (isNormalNumber(storedValue)) {
const twelveHoursAgo = Date.now() - 43200000;
return storedValue < twelveHoursAgo;
return isOlderThan(storedValue, MIN_ELAPSED_DURATION_TO_REFRESH_AGAIN);
}

assert(
Expand Down
37 changes: 37 additions & 0 deletions ts/test-both/util/timestamp_test.ts
@@ -0,0 +1,37 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only

import { assert } from 'chai';

import { isOlderThan, isMoreRecentThan } from '../../util/timestamp';

const ONE_HOUR = 3600 * 1000;
const ONE_DAY = 24 * ONE_HOUR;

describe('timestamp', () => {
describe('isOlderThan', () => {
it('returns false on recent and future timestamps', () => {
assert.isFalse(isOlderThan(Date.now(), ONE_DAY));
assert.isFalse(isOlderThan(Date.now() + ONE_DAY, ONE_DAY));
});

it('returns true on old enough timestamps', () => {
assert.isFalse(isOlderThan(Date.now() - ONE_DAY + ONE_HOUR, ONE_DAY));
assert.isTrue(isOlderThan(Date.now() - ONE_DAY - ONE_HOUR, ONE_DAY));
});
});

describe('isMoreRecentThan', () => {
it('returns true on recent and future timestamps', () => {
assert.isTrue(isMoreRecentThan(Date.now(), ONE_DAY));
assert.isTrue(isMoreRecentThan(Date.now() + ONE_DAY, ONE_DAY));
});

it('returns false on old enough timestamps', () => {
assert.isTrue(isMoreRecentThan(Date.now() - ONE_DAY + ONE_HOUR, ONE_DAY));
assert.isFalse(
isMoreRecentThan(Date.now() - ONE_DAY - ONE_HOUR, ONE_DAY)
);
});
});
});
11 changes: 5 additions & 6 deletions ts/textsecure/AccountManager.ts
Expand Up @@ -17,8 +17,10 @@ import ProvisioningCipher from './ProvisioningCipher';
import WebSocketResource, {
IncomingWebSocketRequest,
} from './WebsocketResources';
import { isMoreRecentThan, isOlderThan } from '../util/timestamp';

const ARCHIVE_AGE = 30 * 24 * 60 * 60 * 1000;
const PREKEY_ROTATION_AGE = 24 * 60 * 60 * 1000;

function getIdentifier(id: string) {
if (!id || !id.length) {
Expand Down Expand Up @@ -321,10 +323,9 @@ export default class AccountManager extends EventTarget {
existingKeys.sort((a, b) => (b.created_at || 0) - (a.created_at || 0));
const confirmedKeys = existingKeys.filter(key => key.confirmed);

const ONE_DAY_AGO = Date.now() - 24 * 60 * 60 * 1000;
if (
confirmedKeys.length >= 3 &&
confirmedKeys[0].created_at > ONE_DAY_AGO
isMoreRecentThan(confirmedKeys[0].created_at, PREKEY_ROTATION_AGE)
) {
window.log.warn(
'rotateSignedPreKey: 3+ confirmed keys, most recent is less than a day old. Cancelling rotation.'
Expand Down Expand Up @@ -437,9 +438,8 @@ export default class AccountManager extends EventTarget {
return;
}
const createdAt = key.created_at || 0;
const age = Date.now() - createdAt;

if (age > ARCHIVE_AGE) {
if (isOlderThan(createdAt, ARCHIVE_AGE)) {
window.log.info(
'Removing confirmed signed prekey:',
key.keyId,
Expand All @@ -463,8 +463,7 @@ export default class AccountManager extends EventTarget {
}

const createdAt = key.created_at || 0;
const age = Date.now() - createdAt;
if (age > ARCHIVE_AGE) {
if (isOlderThan(createdAt, ARCHIVE_AGE)) {
window.log.info(
'Removing unconfirmed signed prekey:',
key.keyId,
Expand Down
4 changes: 3 additions & 1 deletion ts/util/isConversationUnregistered.ts
@@ -1,13 +1,15 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only

import { isMoreRecentThan } from './timestamp';

const SIX_HOURS = 1000 * 60 * 60 * 6;

export function isConversationUnregistered({
discoveredUnregisteredAt,
}: Readonly<{ discoveredUnregisteredAt?: number }>): boolean {
return Boolean(
discoveredUnregisteredAt &&
discoveredUnregisteredAt > Date.now() - SIX_HOURS
isMoreRecentThan(discoveredUnregisteredAt, SIX_HOURS)
);
}
4 changes: 2 additions & 2 deletions ts/util/lint/exceptions.json
Expand Up @@ -14026,15 +14026,15 @@
"rule": "jQuery-load(",
"path": "ts/LibSignalStore.js",
"line": " await window.ConversationController.load();",
"lineNumber": 810,
"lineNumber": 811,
"reasonCategory": "falseMatch",
"updated": "2021-02-27T00:48:49.313Z"
},
{
"rule": "jQuery-load(",
"path": "ts/LibSignalStore.ts",
"line": " await window.ConversationController.load();",
"lineNumber": 1221,
"lineNumber": 1222,
"reasonCategory": "falseMatch",
"updated": "2021-02-27T00:48:49.313Z"
},
Expand Down
10 changes: 10 additions & 0 deletions ts/util/timestamp.ts
@@ -0,0 +1,10 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only

export function isMoreRecentThan(timestamp: number, delta: number): boolean {
return timestamp > Date.now() - delta;
}

export function isOlderThan(timestamp: number, delta: number): boolean {
return timestamp <= Date.now() - delta;
}

0 comments on commit a75402d

Please sign in to comment.