Skip to content

Commit

Permalink
revert: prefix cache changes
Browse files Browse the repository at this point in the history
  • Loading branch information
ioanmo226 committed May 8, 2024
1 parent 5b4c8ac commit 84b7be4
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 110 deletions.
6 changes: 3 additions & 3 deletions extension/js/common/browser/browser-msg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ export namespace Bm {
export type Ajax = { req: ApiAjax; resFmt: ResFmt };
export type AjaxProgress = { operationId: string; percent?: number; loaded: number; total: number; expectedTransferSize: number };
export type AjaxGmailAttachmentGetChunk = { acctEmail: string; msgId: string; attachmentId: string; treatAs: string };
export type ExpirationCacheGet = { key: string; prefix: string; expirationTicks: number };
export type ExpirationCacheSet<V> = { key: string; prefix: string; value: V | undefined; expirationTicks: number; expiration?: number };
export type ExpirationCacheDeleteExpired = { prefix: string; expirationTicks: number };
export type ExpirationCacheGet = { key: string; expirationTicks: number };
export type ExpirationCacheSet<V> = { key: string; value: V | undefined; expirationTicks: number; expiration?: number };
export type ExpirationCacheDeleteExpired = { expirationTicks: number };
export type ShowAttachmentPreview = { iframeUrl: string };
export type ShowConfirmation = { text: string; isHTML: boolean; messageSender: Dest; requestUid: string; footer?: string };
export type ReRenderRecipient = { email: string };
Expand Down
28 changes: 8 additions & 20 deletions extension/js/common/core/expiration-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,14 @@ import { Env } from '../browser/env.js';
*/
type ExpirationCacheType<V> = { value: V; expiration: number };
export class ExpirationCache<V> {
public constructor(
public prefix: string,
public expirationTicks: number
) {}
public constructor(public expirationTicks: number) {}

public set = async (key: string, value?: V, expiration?: number) => {
if (Env.isContentScript()) {
// Get chrome storage data from content script not allowed
// Need to get data from service worker
await BrowserMsg.send.bg.await.expirationCacheSet<V>({
key,
prefix: this.prefix,
value,
expirationTicks: this.expirationTicks,
expiration,
Expand All @@ -29,9 +25,9 @@ export class ExpirationCache<V> {
}
if (value) {
const expirationVal = { value, expiration: expiration || Date.now() + this.expirationTicks };
await storageSet('session', { [this.getPrefixedKey(key)]: expirationVal });
await storageSet('session', { [`${key}`]: expirationVal });
} else {
await storageRemove('session', [this.getPrefixedKey(key)]);
await storageRemove('session', [key]);
}
};

Expand All @@ -44,19 +40,17 @@ export class ExpirationCache<V> {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return await BrowserMsg.send.bg.await.expirationCacheGet<V>({
key,
prefix: this.prefix,
expirationTicks: this.expirationTicks,
});
}
const prefixedKey = this.getPrefixedKey(key);
const result = await storageGet('session', [prefixedKey]);
const found = result[prefixedKey] as ExpirationCacheType<V>;
const result = await storageGet('session', [key]);
const found = result[key] as ExpirationCacheType<V>;
if (found) {
if (found.expiration > Date.now()) {
return found.value;
} else {
// expired, so delete it and return as if not found
await storageRemove('session', [prefixedKey]);
await storageRemove('session', [key]);
}
}
return undefined;
Expand All @@ -66,10 +60,8 @@ export class ExpirationCache<V> {
if (Env.isContentScript()) {
// Get chrome storage data from content script not allowed
// Need to get data from service worker
await BrowserMsg.retryOnBgNotReadyErr(() =>
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
BrowserMsg.send.bg.await.expirationCacheDeleteExpired({ prefix: this.prefix, expirationTicks: this.expirationTicks })
);
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
await BrowserMsg.retryOnBgNotReadyErr(() => BrowserMsg.send.bg.await.expirationCacheDeleteExpired({ expirationTicks: this.expirationTicks }));
return;
}

Expand All @@ -96,8 +88,4 @@ export class ExpirationCache<V> {
return Promise.reject(e);
}
};

private getPrefixedKey = (key: string) => {
return `${this.prefix}_${key}`;
};
}
6 changes: 3 additions & 3 deletions extension/js/common/downloader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import { ExpirationCache } from './core/expiration-cache.js';
import { Catch } from './platform/catch.js';

export class Downloader {
private readonly chunkDownloads = new ExpirationCache<Promise<Buf>>('chunk', 2 * 60 * 60 * 1000); // 2 hours
private readonly fullMessages = new ExpirationCache<Promise<GmailRes.GmailMsg>>('full_message', 24 * 60 * 60 * 1000); // 24 hours
private readonly rawMessages = new ExpirationCache<Promise<GmailRes.GmailMsg>>('raw_message', 24 * 60 * 60 * 1000); // 24 hours
private readonly chunkDownloads = new ExpirationCache<Promise<Buf>>(2 * 60 * 60 * 1000); // 2 hours
private readonly fullMessages = new ExpirationCache<Promise<GmailRes.GmailMsg>>(24 * 60 * 60 * 1000); // 24 hours
private readonly rawMessages = new ExpirationCache<Promise<GmailRes.GmailMsg>>(24 * 60 * 60 * 1000); // 24 hours

public constructor(private readonly gmail: Gmail) {}

Expand Down
2 changes: 1 addition & 1 deletion extension/js/common/message-renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ type ProcessedMessage = {

export class MessageRenderer {
public readonly downloader: Downloader;
private readonly processedMessages = new ExpirationCache<Promise<ProcessedMessage>>('processed_message', 24 * 60 * 60 * 1000); // 24 hours
private readonly processedMessages = new ExpirationCache<Promise<ProcessedMessage>>(24 * 60 * 60 * 1000); // 24 hours

private constructor(
private readonly acctEmail: string,
Expand Down
2 changes: 1 addition & 1 deletion extension/js/service_worker/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ console.info('background.js service worker starting');
(async () => {
let db: IDBDatabase;
let storage: GlobalStoreDict;
const inMemoryStore = new ExpirationCache<string>('in_memory_store', 4 * 60 * 60 * 1000); // 4 hours
const inMemoryStore = new ExpirationCache<string>(4 * 60 * 60 * 1000); // 4 hours
BrowserMsg.createIntervalAlarm('delete_expired', 1); // each minute

try {
Expand Down
6 changes: 3 additions & 3 deletions extension/js/service_worker/bg-handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,17 @@ export class BgHandlers {
};

public static expirationCacheGetHandler = async <V>(r: Bm.ExpirationCacheGet): Promise<Bm.Res.ExpirationCacheGet<V>> => {
const expirationCache = new ExpirationCache<V>(r.prefix, r.expirationTicks);
const expirationCache = new ExpirationCache<V>(r.expirationTicks);
return await expirationCache.get(r.key);
};

public static expirationCacheSetHandler = async <V>(r: Bm.ExpirationCacheSet<V>): Promise<Bm.Res.ExpirationCacheSet> => {
const expirationCache = new ExpirationCache<V>(r.prefix, r.expirationTicks);
const expirationCache = new ExpirationCache<V>(r.expirationTicks);
await expirationCache.set(r.key, r.value, r.expiration);
};

public static expirationCacheDeleteExpiredHandler = async (r: Bm.ExpirationCacheDeleteExpired): Promise<Bm.Res.ExpirationCacheDeleteExpired> => {
const expirationCache = new ExpirationCache(r.prefix, r.expirationTicks);
const expirationCache = new ExpirationCache(r.expirationTicks);
await expirationCache.deleteExpired();
};

Expand Down
4 changes: 2 additions & 2 deletions test/source/tests/browser-unit-tests/unit-ExpirationCache.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ BROWSER_UNIT_TEST_NAME(`[unit][ExpirationCache] entry expires after configured i
const sleep = async seconds => {
return await new Promise(resolve => setTimeout(resolve, seconds * 1000));
};
const cache = new ExpirationCache('test-cache', 2000); // 2 seconds
const cache = new ExpirationCache(2000); // 2 seconds
await cache.set('test-key', 'test-value');
let cacheValue = await cache.get('test-key');
if (cacheValue !== 'test-value') {
Expand All @@ -22,7 +22,7 @@ BROWSER_UNIT_TEST_NAME(`[unit][ExpirationCache] entry expires after configured i

BROWSER_UNIT_TEST_NAME(`[unit][ExpirationCache.await] removes rejected promises from cache`);
(async () => {
const cache = new ExpirationCache('test-cache-promise', 24 * 60 * 60 * 1000); // 24 hours
const cache = new ExpirationCache(24 * 60 * 60 * 1000); // 24 hours
const rejectionPromise = Promise.reject(Error('test-error'));
cache.set('test-key', rejectionPromise);
let cacheValue = cache.get('test-key');
Expand Down
142 changes: 65 additions & 77 deletions test/source/tests/gmail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,28 +120,24 @@ export const defineGmailTests = (testVariant: TestVariant, testWithBrowser: Test

test(
'mail.google.com - send rich-text encrypted message',
testWithBrowser(
async (t, browser) => {
const acctEmail = '[email protected]';
await BrowserRecipe.setUpCommonAcct(t, browser, 'ci.tests.gmail');
const gmailPage = await BrowserRecipe.openGmailPageAndVerifyComposeBtnPresent(t, browser);
const composePage = await GmailPageRecipe.openSecureComposeWithRichTextWorkaround(t, gmailPage, browser);
const subject = `New Rich Text Message ${Util.lousyRandom()}`;
await ComposePageRecipe.fillMsg(composePage, { to: acctEmail }, subject, undefined, {
richtext: true,
});
await ComposePageRecipe.sendAndClose(composePage);
await GmailPageRecipe.expandMainMenuIfNeeded(gmailPage);
await gmailPage.waitAndClick('[aria-label^="Inbox"]');
await gmailPage.waitAndClick('[role="row"]:first-of-type'); // click the first message
await gmailPage.waitForContent('.nH h2.hP', `Automated puppeteer test: ${subject}`);
const urls = await gmailPage.getFramesUrls(['/chrome/elements/pgp_block.htm'], { sleep: 1 });
await GmailPageRecipe.deleteThread(gmailPage);
expect(urls.length).to.eq(1);
},
undefined,
minutes(7)
)
testWithBrowser(async (t, browser) => {
const acctEmail = '[email protected]';
await BrowserRecipe.setUpCommonAcct(t, browser, 'ci.tests.gmail');
const gmailPage = await BrowserRecipe.openGmailPageAndVerifyComposeBtnPresent(t, browser);
const composePage = await GmailPageRecipe.openSecureComposeWithRichTextWorkaround(t, gmailPage, browser);
const subject = `New Rich Text Message ${Util.lousyRandom()}`;
await ComposePageRecipe.fillMsg(composePage, { to: acctEmail }, subject, undefined, {
richtext: true,
});
await ComposePageRecipe.sendAndClose(composePage);
await GmailPageRecipe.expandMainMenuIfNeeded(gmailPage);
await gmailPage.waitAndClick('[aria-label^="Inbox"]');
await gmailPage.waitAndClick('[role="row"]:first-of-type'); // click the first message
await gmailPage.waitForContent('.nH h2.hP', `Automated puppeteer test: ${subject}`);
const urls = await gmailPage.getFramesUrls(['/chrome/elements/pgp_block.htm'], { sleep: 1 });
await GmailPageRecipe.deleteThread(gmailPage);
expect(urls.length).to.eq(1);
})
);

test(
Expand Down Expand Up @@ -378,65 +374,57 @@ export const defineGmailTests = (testVariant: TestVariant, testWithBrowser: Test

test(
'mail.google.com - plain reply to encrypted and signed messages',
testWithBrowser(
async (t, browser) => {
await BrowserRecipe.setUpCommonAcct(t, browser, 'ci.tests.gmail');
const gmailPage = await openGmailPage(t, browser);
await gotoGmailPage(gmailPage, '/FMfcgzGkbDRNgcQxLmkhBCKVSFwkfdvV'); // plain convo
await gmailPage.waitAndClick('[data-tooltip="Reply"]', { delay: 1 });
await gotoGmailPage(gmailPage, '/181d226b4e69f172'); // go to encrypted convo
await gmailPage.waitAndClick('[data-tooltip="Reply"]', { delay: 1 });
await gmailPage.waitTillGone('.reply_message');
await gmailPage.waitAll('[data-tooltip^="Send"]'); // The Send button from the Standard reply box
await gmailPage.waitForContent(
'.reply_message_evaluated .error_notification',
'The last message was encrypted, but you are composing a reply without encryption.'
);
await gmailPage.waitAndClick('[data-tooltip="Secure Reply"]'); // Switch to encrypted reply
await gmailPage.waitAll('.reply_message');
await pageHasSecureReplyContainer(t, browser, gmailPage, { isReplyPromptAccepted: true });
await gotoGmailPage(gmailPage, '/FMfcgzGkbDRNpjDdNvCrwzqvXspZZxvh'); // go to signed convo
await gmailPage.waitAndClick('[data-tooltip="Reply"]', { delay: 1 });
await gmailPage.waitTillGone('.reply_message');
await gmailPage.waitAll('[data-tooltip^="Send"]'); // The Send button from the Standard reply box
await gmailPage.notPresent('.reply_message_evaluated .error_notification'); // should not show the warning about switching to encrypted reply
},
undefined,
minutes(6)
)
testWithBrowser(async (t, browser) => {
await BrowserRecipe.setUpCommonAcct(t, browser, 'ci.tests.gmail');
const gmailPage = await openGmailPage(t, browser);
await gotoGmailPage(gmailPage, '/FMfcgzGkbDRNgcQxLmkhBCKVSFwkfdvV'); // plain convo
await gmailPage.waitAndClick('[data-tooltip="Reply"]', { delay: 1 });
await gotoGmailPage(gmailPage, '/181d226b4e69f172'); // go to encrypted convo
await gmailPage.waitAndClick('[data-tooltip="Reply"]', { delay: 1 });
await gmailPage.waitTillGone('.reply_message');
await gmailPage.waitAll('[data-tooltip^="Send"]'); // The Send button from the Standard reply box
await gmailPage.waitForContent(
'.reply_message_evaluated .error_notification',
'The last message was encrypted, but you are composing a reply without encryption.'
);
await gmailPage.waitAndClick('[data-tooltip="Secure Reply"]'); // Switch to encrypted reply
await gmailPage.waitAll('.reply_message');
await pageHasSecureReplyContainer(t, browser, gmailPage, { isReplyPromptAccepted: true });
await gotoGmailPage(gmailPage, '/FMfcgzGkbDRNpjDdNvCrwzqvXspZZxvh'); // go to signed convo
await gmailPage.waitAndClick('[data-tooltip="Reply"]', { delay: 1 });
await gmailPage.waitTillGone('.reply_message');
await gmailPage.waitAll('[data-tooltip^="Send"]'); // The Send button from the Standard reply box
await gmailPage.notPresent('.reply_message_evaluated .error_notification'); // should not show the warning about switching to encrypted reply
})
);

test(
'mail.google.com - switch to encrypted reply for middle message',
testWithBrowser(
async (t, browser) => {
await BrowserRecipe.setUpCommonAcct(t, browser, 'ci.tests.gmail');
const gmailPage = await openGmailPage(t, browser);
await gotoGmailPage(gmailPage, '/FMfcgzGqRGfPBbNLWvfPvDbxnHBwkdGf'); // plain convo
await gmailPage.waitAndClick('[role="listitem"] .adf.ads', { delay: 1 }); // click first message of thread
await Util.sleep(3);
const messages = await gmailPage.target.$$('[role="listitem"] .adn.ads');
expect(messages.length).to.equal(2);

const plainReplyButton = await messages[0].$('[data-tooltip="Reply"]');
expect(plainReplyButton).to.be.ok;
await Util.sleep(1);
await plainReplyButton!.click();
await gmailPage.waitAll('[data-tooltip^="Send"]'); // The Send button from the Standard reply box
await gmailPage.waitForContent(
'.reply_message_evaluated .error_notification',
'The last message was encrypted, but you are composing a reply without encryption.'
);

const secureReplyButton = await messages[0].$('[data-tooltip="Secure Reply"]');
expect(secureReplyButton).to.be.ok;
await secureReplyButton!.click(); // Switch to encrypted reply
await gmailPage.waitAll('.reply_message');
await pageHasSecureReplyContainer(t, browser, gmailPage, { isReplyPromptAccepted: true, composeFrameCount: 2 });
},
undefined,
minutes(6)
)
testWithBrowser(async (t, browser) => {
await BrowserRecipe.setUpCommonAcct(t, browser, 'ci.tests.gmail');
const gmailPage = await openGmailPage(t, browser);
await gotoGmailPage(gmailPage, '/FMfcgzGqRGfPBbNLWvfPvDbxnHBwkdGf'); // plain convo
await gmailPage.waitAndClick('[role="listitem"] .adf.ads', { delay: 1 }); // click first message of thread
await Util.sleep(3);
const messages = await gmailPage.target.$$('[role="listitem"] .adn.ads');
expect(messages.length).to.equal(2);

const plainReplyButton = await messages[0].$('[data-tooltip="Reply"]');
expect(plainReplyButton).to.be.ok;
await Util.sleep(1);
await plainReplyButton!.click();
await gmailPage.waitAll('[data-tooltip^="Send"]'); // The Send button from the Standard reply box
await gmailPage.waitForContent(
'.reply_message_evaluated .error_notification',
'The last message was encrypted, but you are composing a reply without encryption.'
);

const secureReplyButton = await messages[0].$('[data-tooltip="Secure Reply"]');
expect(secureReplyButton).to.be.ok;
await secureReplyButton!.click(); // Switch to encrypted reply
await gmailPage.waitAll('.reply_message');
await pageHasSecureReplyContainer(t, browser, gmailPage, { isReplyPromptAccepted: true, composeFrameCount: 2 });
})
);

test(
Expand Down

0 comments on commit 84b7be4

Please sign in to comment.