Skip to content

Commit

Permalink
Issue 1509 window messaging from iframe to parent live test (#5320)
Browse files Browse the repository at this point in the history
* frame-level dest and listener for confirmation_result and pgp_block_render

* fix

* helpers for getting async results from content-script, window postMessage support

* prepare test infrastructure to test passphrase dialog on gmail page

* refactor RelayManager to track reloaded frames, disabled test

* restartable relays

* tidy up, less dependency on frameId, protection against unexpected progress callbacks

* removed unnecessary async

* tidy up

* stricter _tab_ detection

* registry of content scripts in background page

* prevent content script setup for non-top frame

* Revert "prevent content script setup for non-top frame"

This reverts commit 9d11287.

* fixed wiring to window messages

* rename

* pgp_block_retry handling with window messaging and actual frame check

---------

Co-authored-by: Roman Shevchenko <[email protected]>
  • Loading branch information
rrrooommmaaa and Roman Shevchenko authored Jul 25, 2023
1 parent e4dee98 commit 6d6a340
Show file tree
Hide file tree
Showing 27 changed files with 560 additions and 403 deletions.
9 changes: 4 additions & 5 deletions extension/chrome/elements/attachment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@ import { AttachmentWarnings } from './shared/attachment_warnings.js';

export class AttachmentDownloadView extends View {
public fesUrl?: string;
public confirmationResultResolver?: (confirm: boolean) => void;
public readonly parentTabId: string;
protected readonly acctEmail: string;
protected readonly parentTabId: string;
protected readonly frameId: string;
protected readonly origNameBasedOnFilename: string;
protected readonly isEncrypted: boolean;
Expand Down Expand Up @@ -85,8 +84,8 @@ export class AttachmentDownloadView extends View {
this.gmail = new Gmail(this.acctEmail);
}

public getParentTabId = () => {
return this.parentTabId;
public getDest = () => {
return this.tabId;
};

public render = async () => {
Expand Down Expand Up @@ -151,7 +150,7 @@ export class AttachmentDownloadView extends View {
this.ppChangedPromiseCancellation = { cancel: false }; // set to a new, not yet used object
}
});
BrowserMsg.addListener('confirmation_result', CommonHandlers.createConfirmationResultHandler(this));
BrowserMsg.addListener('confirmation_result', CommonHandlers.createAsyncResultHandler());
BrowserMsg.listen(this.tabId);
};

Expand Down
30 changes: 15 additions & 15 deletions extension/chrome/elements/pgp_block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@

import { Url } from '../../js/common/core/common.js';
import { Assert } from '../../js/common/assert.js';
import { RenderMessage, RenderMessageWithFrameId } from '../../js/common/render-message.js';
import { RenderMessage } from '../../js/common/render-message.js';
import { Attachment } from '../../js/common/core/attachment.js';
import { Xss } from '../../js/common/platform/xss.js';
import { PgpBlockViewAttachmentsModule } from './pgp_block_modules/pgp-block-attachmens-module.js';
import { PgpBlockViewErrorModule } from './pgp_block_modules/pgp-block-error-module.js';
import { PgpBlockViewPrintModule } from './pgp_block_modules/pgp-block-print-module.js';
import { PgpBlockViewQuoteModule } from './pgp_block_modules/pgp-block-quote-module.js';
import { PgpBlockViewRenderModule } from './pgp_block_modules/pgp-block-render-module.js';
import { Ui } from '../../js/common/browser/ui.js';
import { CommonHandlers, Ui } from '../../js/common/browser/ui.js';
import { View } from '../../js/common/view.js';
import { Bm } from '../../js/common/browser/browser-msg.js';
import { BrowserMsg } from '../../js/common/browser/browser-msg.js';

export class PgpBlockView extends View {
public readonly acctEmail: string; // needed for attachment decryption, probably should be refactored out
Expand All @@ -27,6 +27,7 @@ export class PgpBlockView extends View {
public readonly errorModule: PgpBlockViewErrorModule;
public readonly renderModule: PgpBlockViewRenderModule;
public readonly printModule = new PgpBlockViewPrintModule();
private tabId!: string;

public constructor() {
super();
Expand All @@ -41,28 +42,27 @@ export class PgpBlockView extends View {
this.quoteModule = new PgpBlockViewQuoteModule(this);
this.errorModule = new PgpBlockViewErrorModule(this);
this.renderModule = new PgpBlockViewRenderModule(this);
chrome.runtime.onMessage.addListener((message: Bm.Raw) => {
if (message.name === 'pgp_block_render') {
const msg = message.data.bm as RenderMessageWithFrameId;
if (msg.frameId === this.frameId) {
this.processMessage(msg);
return true;
}
}
return false;
});
window.addEventListener('load', () => window.parent.postMessage({ readyToReceive: this.frameId }, '*'));
}

public getDest = () => {
return this.tabId;
};

public render = async () => {
//
this.tabId = await BrowserMsg.requiredTabId();
};

public setHandlers = () => {
$('.pgp_print_button').on(
'click',
this.setHandler(() => this.printModule.printPGPBlock())
);
BrowserMsg.addListener('pgp_block_render', async (msg: RenderMessage) => {
this.processMessage(msg);
});
BrowserMsg.addListener('confirmation_result', CommonHandlers.createAsyncResultHandler());
BrowserMsg.listen(this.tabId);
BrowserMsg.send.pgpBlockReady({ frameId: this.frameId, messageSender: this.tabId });
};

private processMessage = (data: RenderMessage) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Attachment } from '../../../js/common/core/attachment.js';
import { Browser } from '../../../js/common/browser/browser.js';
import { BrowserMsg } from '../../../js/common/browser/browser-msg.js';
import { PgpBlockView } from '../pgp_block.js';
import { CommonHandlers, Ui } from '../../../js/common/browser/ui.js';
import { Ui } from '../../../js/common/browser/ui.js';
import { Xss } from '../../../js/common/platform/xss.js';
import { KeyStore } from '../../../js/common/platform/store/key-store.js';
import { XssSafeFactory } from '../../../js/common/xss-safe-factory.js';
Expand All @@ -21,10 +21,6 @@ export class PgpBlockViewAttachmentsModule {

public constructor(private view: PgpBlockView) {}

public getParentTabId = () => {
return this.view.parentTabId;
};

public renderInnerAttachments = (attachments: Attachment[], isEncrypted: boolean) => {
Xss.sanitizeAppend('#pgp_block', '<div id="attachments"></div>');
this.includedAttachments = attachments;
Expand Down Expand Up @@ -78,8 +74,6 @@ export class PgpBlockViewAttachmentsModule {
}
})
);
BrowserMsg.addListener('confirmation_result', CommonHandlers.createConfirmationResultHandler(this));
BrowserMsg.listen(this.view.parentTabId);
};

private previewAttachmentClickedHandler = async (attachment: Attachment) => {
Expand All @@ -102,7 +96,7 @@ export class PgpBlockViewAttachmentsModule {
type: encrypted.type,
data: decrypted.content,
});
if (await AttachmentWarnings.confirmSaveToDownloadsIfNeeded(attachment, this)) {
if (await AttachmentWarnings.confirmSaveToDownloadsIfNeeded(attachment, this.view)) {
Browser.saveToDownloads(attachment);
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ export class PgpBlockViewRenderModule {
public renderSignatureOffline = () => {
this.renderSignatureStatus('error verifying signature: offline, click to retry').on(
'click',
this.view.setHandler(() => window.parent.postMessage({ retry: this.view.frameId }, '*'))
this.view.setHandler(() => BrowserMsg.send.pgpBlockRetry({ frameId: this.view.frameId, messageSender: this.view.getDest() }))
);
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ export class InboxActiveThreadModule extends ViewModule<InboxView> {
loaderContext.getRenderedMessageXssSafe() +
loaderContext.getRenderedAttachmentsXssSafe();
$('.thread').append(this.wrapMsg(htmlId, r)); // xss-safe-value
await this.view.messageRenderer.startProcessingInlineBlocks(this.view.relayManager, this.view.factory, messageInfo, blocksInFrames);
this.view.messageRenderer.startProcessingInlineBlocks(this.view.relayManager, this.view.factory, messageInfo, blocksInFrames);
if (exportBtn) {
$('.action-export').on(
'click',
Expand Down
17 changes: 9 additions & 8 deletions extension/chrome/settings/inbox/inbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import { XssSafeFactory } from '../../../js/common/xss-safe-factory.js';
import { AcctStore } from '../../../js/common/platform/store/acct-store.js';
import { RelayManager } from '../../../js/common/relay-manager.js';
import { MessageRenderer } from '../../../js/common/message-renderer.js';
import { Env } from '../../../js/common/browser/env.js';

export class InboxView extends View {
public readonly inboxMenuModule: InboxMenuModule;
Expand Down Expand Up @@ -62,16 +61,11 @@ export class InboxView extends View {
this.inboxNotificationModule = new InboxNotificationModule(this);
this.inboxActiveThreadModule = new InboxActiveThreadModule(this);
this.inboxListThreadsModule = new InboxListThreadsModule(this);
window.addEventListener('message', e => {
if (e.origin === Env.getExtensionOrigin()) {
this.relayManager.handleMessageFromFrame(e.data);
}
});
}

public render = async () => {
this.tabId = await BrowserMsg.requiredTabId();
this.relayManager = new RelayManager(this.tabId, this.debug);
this.relayManager = new RelayManager(this.debug);
this.factory = new XssSafeFactory(this.acctEmail, this.tabId);
this.injector = new Injector('settings', undefined, this.factory);
this.webmailCommon = new WebmailCommon(this.acctEmail, this.injector);
Expand Down Expand Up @@ -105,7 +99,9 @@ export class InboxView extends View {

public setHandlers = () => {
// BrowserMsg.addPgpListeners(); // todo - re-allow when https://github.com/FlowCrypt/flowcrypt-browser/issues/2560 fixed
this.addBrowserMsgListeners();
BrowserMsg.listen(this.tabId);
BrowserMsg.listenForWindowMessages(); // listen for direct messages from child iframes
Catch.setHandledInterval(this.webmailCommon.addOrRemoveEndSessionBtnIfNeeded, 30000);
$('.action_open_settings').on(
'click',
Expand All @@ -122,7 +118,6 @@ export class InboxView extends View {
'click',
this.setHandlerPrevent('double', async () => await Settings.newGoogleAcctAuthPromptThenAlertOrForward(this.tabId))
);
this.addBrowserMsgListeners();
};

public redirectToUrl = (params: UrlParams) => {
Expand Down Expand Up @@ -182,6 +177,12 @@ export class InboxView extends View {
await Ui.modal.attachmentPreview(iframeUrl);
});
BrowserMsg.addListener('confirmation_show', CommonHandlers.showConfirmationHandler);
BrowserMsg.addListener('pgp_block_ready', async ({ frameId, messageSender }: Bm.PgpBlockReady) => {
this.relayManager.associate(frameId, messageSender);
});
BrowserMsg.addListener('pgp_block_retry', async ({ frameId, messageSender }: Bm.PgpBlockRetry) => {
this.relayManager.retry(frameId, messageSender);
});
if (this.debug) {
BrowserMsg.addListener('open_compose_window', async ({ draftId }: Bm.ComposeWindowOpenDraft) => {
console.log('received open_compose_window');
Expand Down
16 changes: 10 additions & 6 deletions extension/js/background_page/bg-handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export class BgHandlers {
};

public static ajaxHandler = async (r: Bm.Ajax, sender: Bm.Sender): Promise<Bm.Res.Ajax> => {
if (r.req.context?.frameId) {
if (r.req.context?.operationId) {
// progress updates were requested via messages
let dest = r.req.context.tabId;
if (typeof dest === 'undefined') {
Expand All @@ -43,10 +43,10 @@ export class BgHandlers {
}
if (typeof dest !== 'undefined') {
const destination = dest;
const frameId = r.req.context.frameId;
const operationId = r.req.context.operationId;
const expectedTransferSize = r.req.context.expectedTransferSize;
r.req.xhr = Api.getAjaxProgressXhrFactory({
download: (percent, loaded, total) => BrowserMsg.send.ajaxProgress(destination, { percent, loaded, total, expectedTransferSize, frameId }),
download: (percent, loaded, total) => BrowserMsg.send.ajaxProgress(destination, { percent, loaded, total, expectedTransferSize, operationId }),
});
}
}
Expand Down Expand Up @@ -91,11 +91,15 @@ export class BgHandlers {
});
});

public static respondWithSenderTabId = async (r: unknown, sender: Bm.Sender): Promise<Bm.Res._tab_> => {
public static respondWithSenderTabId = async (r: Bm._tab_, sender: Bm.Sender): Promise<Bm.Res._tab_> => {
if (sender === 'background') {
return { tabId: null }; // eslint-disable-line no-null/no-null
} else if (sender.tab) {
return { tabId: `${sender.tab.id}:${sender.frameId}` };
} else if (typeof sender.tab?.id === 'number' && sender.tab.id > 0) {
const tabId = `${sender.tab.id}:${sender.frameId}`;
if (r.contentScript) {
BrowserMsg.contentScriptsRegistry.add(tabId);
}
return { tabId };
} else {
// sender.tab: "This property will only be present when the connection was opened from a tab (including content scripts)"
// https://developers.chrome.com/extensions/runtime#type-MessageSender
Expand Down
2 changes: 1 addition & 1 deletion extension/js/common/api/email-provider/gmail/google.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export class Google {
// eslint-disable-next-line @typescript-eslint/naming-convention
const headers = { Authorization: await GoogleAuth.googleApiAuthHeader(acctEmail) };
const context =
'frameId' in progress ? { frameId: progress.frameId, expectedTransferSize: progress.expectedTransferSize, tabId: progress.tabId } : undefined;
'operationId' in progress ? { operationId: progress.operationId, expectedTransferSize: progress.expectedTransferSize, tabId: progress.tabId } : undefined;
const xhr = Api.getAjaxProgressXhrFactory('download' in progress || 'upload' in progress ? progress : {});
const request = { xhr, context, url, method, data, headers, crossDomain: true, contentType, async: true };
return (await GoogleAuth.apiGoogleCallRetryAuthErrorOneTime(acctEmail, request)) as RT;
Expand Down
2 changes: 1 addition & 1 deletion extension/js/common/api/shared/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type RawAjaxErr = {
status?: number;
statusText?: string;
};
export type ProgressDestFrame = { frameId: string; expectedTransferSize: number; tabId?: string };
export type ProgressDestFrame = { operationId: string; expectedTransferSize: number; tabId?: string };
export type ApiCallContext = ProgressDestFrame | undefined;

export type ChunkedCb = (r: ProviderContactsResults) => Promise<void>;
Expand Down
Loading

0 comments on commit 6d6a340

Please sign in to comment.