From 3abf78ed047d5a3b32c371f9e5ad38299be94124 Mon Sep 17 00:00:00 2001 From: martgil Date: Sat, 27 Apr 2024 14:50:04 +0800 Subject: [PATCH 01/11] Better FlowCrypt set up flow for Thunderbird --- extension/chrome/settings/initial.htm | 6 +++++- extension/chrome/settings/initial.ts | 5 ++++- extension/js/common/platform/catch.ts | 4 +++- scripts/build.sh | 4 +++- test/source/patterns.ts | 4 ++-- tooling/build-types-and-manifests.ts | 28 +++++++++++++++++++++++++++ 6 files changed, 45 insertions(+), 6 deletions(-) diff --git a/extension/chrome/settings/initial.htm b/extension/chrome/settings/initial.htm index e59cf22de70..a5c9158bbd6 100644 --- a/extension/chrome/settings/initial.htm +++ b/extension/chrome/settings/initial.htm @@ -36,9 +36,13 @@ Click the button in the corner
+ - + diff --git a/extension/chrome/settings/initial.ts b/extension/chrome/settings/initial.ts index 67e53d17512..4895ad61d28 100644 --- a/extension/chrome/settings/initial.ts +++ b/extension/chrome/settings/initial.ts @@ -8,7 +8,10 @@ import { View } from '../../js/common/view.js'; View.run( class InitialView extends View { public render = async () => { - const browserName = Catch.browser().name === 'chrome' && Number(Catch.browser().v) >= 76 ? 'chrome' : 'firefox'; + const browserName = Catch.browser().name === 'chrome' && Number(Catch.browser().v) >= 76 ? 'chrome' : Catch.browser().name; + if (browserName === 'thunderbird') { + $('#img-setup-arrow').hide(); + } const stepsEl = document.getElementById(`${browserName}-steps`); if (stepsEl) { stepsEl.style.display = 'block'; diff --git a/extension/js/common/platform/catch.ts b/extension/js/common/platform/catch.ts index d07944afebd..98529b66355 100644 --- a/extension/js/common/platform/catch.ts +++ b/extension/js/common/platform/catch.ts @@ -148,12 +148,14 @@ export class Catch { } public static browser(): { - name: 'firefox' | 'ie' | 'chrome' | 'opera' | 'safari' | 'unknown'; + name: 'firefox' | 'thunderbird' | 'ie' | 'chrome' | 'opera' | 'safari' | 'unknown'; v: number | undefined; } { // http://stackoverflow.com/questions/4825498/how-can-i-find-out-which-browser-a-user-is-using if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent)) { return { name: 'firefox', v: Number(RegExp.$1) }; + } else if (/Thunderbird[\/\s](\d+\.\d+)/.test(navigator.userAgent)) { + return { name: 'thunderbird', v: Number(RegExp.$1) }; } else if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) { return { name: 'ie', v: Number(RegExp.$1) }; } else if (/Chrome[\/\s](\d+\.\d+)/.test(navigator.userAgent)) { diff --git a/scripts/build.sh b/scripts/build.sh index 2c40f8ad152..30c7d461b8e 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -78,12 +78,13 @@ main() { synchronize_files "build/chrome-enterprise" synchronize_files "build/chrome-consumer" synchronize_files "build/firefox-consumer" + synchronize_files "build/thunderbird-consumer" } exit 0 fi if [[ "$#" == 1 ]] && [[ "$1" == "--incremental" ]]; then - delete_directories $BUILD_DIRECTORY/firefox-consumer $BUILD_DIRECTORY/chrome-consumer $BUILD_DIRECTORY/chrome-consumer-mock $BUILD_DIRECTORY/chrome-enterprise $BUILD_DIRECTORY/chrome-enterprise-mock $BUILD_DIRECTORY/generic-extension-wip/js/content_scripts + delete_directories $BUILD_DIRECTORY/firefox-consumer $BUILD_DIRECTORY/thunderbird-consumer $BUILD_DIRECTORY/chrome-consumer $BUILD_DIRECTORY/chrome-consumer-mock $BUILD_DIRECTORY/chrome-enterprise $BUILD_DIRECTORY/chrome-enterprise-mock $BUILD_DIRECTORY/generic-extension-wip/js/content_scripts # build concurrently - using standard typescript compiler with --incremental flag mkdir -p $BUILD_DIRECTORY build_typescript_project false "./tsconfig.json" true "$BUILD_DIRECTORY/tsconfig.tsbuildinfo" @@ -148,6 +149,7 @@ main() { cp -r $OUTPUT_DIRECTORY ./build/chrome-enterprise cp -r $OUTPUT_DIRECTORY ./build/chrome-consumer cp -r $OUTPUT_DIRECTORY ./build/firefox-consumer + cp -r $OUTPUT_DIRECTORY ./build/thunderbird-consumer node ./build/tooling/build-types-and-manifests } diff --git a/test/source/patterns.ts b/test/source/patterns.ts index ab66afab694..2d57d2e19ad 100644 --- a/test/source/patterns.ts +++ b/test/source/patterns.ts @@ -96,12 +96,12 @@ const expectedEnterprisePermissions = [ 'https://flowcrypt.com/*', 'unlimitedStorage', ]; -for (const buildType of ['chrome-consumer', 'chrome-enterprise', 'firefox-consumer']) { +for (const buildType of ['chrome-consumer', 'chrome-enterprise', 'firefox-consumer', 'thunderbird-consumer']) { const manifest = JSON.parse(readFileSync(`./build/${buildType}/manifest.json`).toString()); const expectedPermissions = buildType.includes('consumer') ? expectedConsumerPermissions : expectedEnterprisePermissions; for (const expectedPermission of expectedPermissions) { if (!manifest.permissions.includes(expectedPermission)) { - if (!(expectedPermission === 'unlimitedStorage' && buildType === 'firefox-consumer')) { + if (!(expectedPermission === 'unlimitedStorage' && (buildType === 'firefox-consumer' || buildType === 'thunderbird-consumer'))) { console.error(`Missing permission '${expectedPermission}' in ${buildType}/manifest.json`); errsFound++; } diff --git a/tooling/build-types-and-manifests.ts b/tooling/build-types-and-manifests.ts index 49e9ae392ba..5718ca85f46 100644 --- a/tooling/build-types-and-manifests.ts +++ b/tooling/build-types-and-manifests.ts @@ -38,6 +38,34 @@ addManifest('firefox-consumer', manifest => { delete manifest.minimum_chrome_version; }); +addManifest('thunderbird-consumer', manifest => { + manifest.version = version; + manifest.applications = { + gecko: { + id: 'firefox@cryptup.io', + update_url: 'https://flowcrypt.com/api/update/firefox', // eslint-disable-line @typescript-eslint/naming-convention + strict_min_version: '102.0', // eslint-disable-line @typescript-eslint/naming-convention + }, + }; + manifest.name = 'FlowCrypt Encryption for Thunderbird'; + manifest.browser_action.default_title = 'FlowCrypt Encryption for Thunderbird'; + delete manifest.permissions; + manifest.permissions = ['storage', 'tabs', 'https://www.googleapis.com/*', 'https://flowcrypt.com/*', 'https://*.google.com/*']; + manifest.compose_action = { + default_title: 'FlowCrypt', // eslint-disable-line @typescript-eslint/naming-convention + default_icon: '/img/logo/flowcrypt-logo-64-64.png', // eslint-disable-line @typescript-eslint/naming-convention + // default_popup will be updated later + default_popup: 'chrome/popups/default.htm', // eslint-disable-line @typescript-eslint/naming-convention + }; + manifest.message_display_action = { + default_title: 'FlowCrypt', // eslint-disable-line @typescript-eslint/naming-convention + default_icon: '/img/logo/flowcrypt-logo-64-64.png', // eslint-disable-line @typescript-eslint/naming-convention + // default_popup will be updated later + default_popup: 'chrome/popups/default.htm', // eslint-disable-line @typescript-eslint/naming-convention + }; + delete manifest.minimum_chrome_version; +}); + addManifest('chrome-enterprise', manifest => { manifest.version = version; manifest.name = 'FlowCrypt for Enterprise'; From 3cd22c25957c60f44567dcd66d5707b56817d5d2 Mon Sep 17 00:00:00 2001 From: martgil Date: Sat, 27 Apr 2024 15:32:27 +0800 Subject: [PATCH 02/11] Update app description for Thunderbird --- tooling/build-types-and-manifests.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tooling/build-types-and-manifests.ts b/tooling/build-types-and-manifests.ts index 5718ca85f46..d38dd236355 100644 --- a/tooling/build-types-and-manifests.ts +++ b/tooling/build-types-and-manifests.ts @@ -49,6 +49,7 @@ addManifest('thunderbird-consumer', manifest => { }; manifest.name = 'FlowCrypt Encryption for Thunderbird'; manifest.browser_action.default_title = 'FlowCrypt Encryption for Thunderbird'; + manifest.description = 'Secure end-to-end encryption with FlowCrypt'; // needs to updated later delete manifest.permissions; manifest.permissions = ['storage', 'tabs', 'https://www.googleapis.com/*', 'https://flowcrypt.com/*', 'https://*.google.com/*']; manifest.compose_action = { From 1d274f402b9737ad59c3e097a28d71dd8cdb9ee3 Mon Sep 17 00:00:00 2001 From: martgil Date: Sat, 27 Apr 2024 19:46:17 +0800 Subject: [PATCH 03/11] Fix paths on manifest.json --- tooling/build-types-and-manifests.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tooling/build-types-and-manifests.ts b/tooling/build-types-and-manifests.ts index d38dd236355..09be9b3debc 100644 --- a/tooling/build-types-and-manifests.ts +++ b/tooling/build-types-and-manifests.ts @@ -56,13 +56,13 @@ addManifest('thunderbird-consumer', manifest => { default_title: 'FlowCrypt', // eslint-disable-line @typescript-eslint/naming-convention default_icon: '/img/logo/flowcrypt-logo-64-64.png', // eslint-disable-line @typescript-eslint/naming-convention // default_popup will be updated later - default_popup: 'chrome/popups/default.htm', // eslint-disable-line @typescript-eslint/naming-convention + default_popup: '/chrome/popups/default.htm', // eslint-disable-line @typescript-eslint/naming-convention }; manifest.message_display_action = { default_title: 'FlowCrypt', // eslint-disable-line @typescript-eslint/naming-convention default_icon: '/img/logo/flowcrypt-logo-64-64.png', // eslint-disable-line @typescript-eslint/naming-convention // default_popup will be updated later - default_popup: 'chrome/popups/default.htm', // eslint-disable-line @typescript-eslint/naming-convention + default_popup: '/chrome/popups/default.htm', // eslint-disable-line @typescript-eslint/naming-convention }; delete manifest.minimum_chrome_version; }); From 56f731ff6d5701a13150466be22d5d49fa6bc970 Mon Sep 17 00:00:00 2001 From: martgil Date: Wed, 15 May 2024 18:11:10 +0800 Subject: [PATCH 04/11] Update manifest.json build for thunderbird --- tooling/build-types-and-manifests.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tooling/build-types-and-manifests.ts b/tooling/build-types-and-manifests.ts index 0ea8153d3f1..270adbc5685 100644 --- a/tooling/build-types-and-manifests.ts +++ b/tooling/build-types-and-manifests.ts @@ -59,10 +59,11 @@ addManifest('thunderbird-consumer', manifest => { }, }; manifest.name = 'FlowCrypt Encryption for Thunderbird'; + manifest.browser_action = manifest.action; + delete manifest.action; manifest.browser_action.default_title = 'FlowCrypt Encryption for Thunderbird'; manifest.description = 'Secure end-to-end encryption with FlowCrypt'; // needs to updated later - delete manifest.permissions; - manifest.permissions = ['storage', 'tabs', 'https://www.googleapis.com/*', 'https://flowcrypt.com/*', 'https://*.google.com/*']; + manifest.permissions = manifest.permissions.filter((p: string) => p !== 'unlimitedStorage'); manifest.compose_action = { default_title: 'FlowCrypt', // eslint-disable-line @typescript-eslint/naming-convention default_icon: '/img/logo/flowcrypt-logo-64-64.png', // eslint-disable-line @typescript-eslint/naming-convention @@ -75,6 +76,7 @@ addManifest('thunderbird-consumer', manifest => { // default_popup will be updated later default_popup: '/chrome/popups/default.htm', // eslint-disable-line @typescript-eslint/naming-convention }; + delete manifest.background.service_worker; delete manifest.minimum_chrome_version; }); From ea52711bf264df6e7ef200247e7c435258a78b88 Mon Sep 17 00:00:00 2001 From: martgil Date: Mon, 3 Jun 2024 18:11:18 +0800 Subject: [PATCH 05/11] Pre-configure setup for content scripts --- extension/js/common/browser/env.ts | 2 +- extension/js/common/inject.ts | 3 ++ .../thunderbird-element-replacer.ts | 13 +++++++ .../thunderbird-webmail-startup.ts | 38 +++++++++++++++++++ .../js/content_scripts/webmail/webmail.ts | 8 +++- test/source/patterns.ts | 2 +- tooling/build-types-and-manifests.ts | 9 ++++- 7 files changed, 70 insertions(+), 5 deletions(-) create mode 100644 extension/js/content_scripts/webmail/thunderbird/thunderbird-element-replacer.ts create mode 100644 extension/js/content_scripts/webmail/thunderbird/thunderbird-webmail-startup.ts diff --git a/extension/js/common/browser/env.ts b/extension/js/common/browser/env.ts index 89512c0e290..1a81c2c075c 100644 --- a/extension/js/common/browser/env.ts +++ b/extension/js/common/browser/env.ts @@ -7,7 +7,7 @@ import { Url } from '../core/common.js'; -export type WebMailName = 'gmail' | 'outlook' | 'settings'; +export type WebMailName = 'gmail' | 'thunderbird' | 'outlook' | 'settings'; export type WebMailVersion = 'generic' | 'gmail2020' | 'gmail2022'; export class Env { diff --git a/extension/js/common/inject.ts b/extension/js/common/inject.ts index ad166535a7c..c2aa2ec1a66 100644 --- a/extension/js/common/inject.ts +++ b/extension/js/common/inject.ts @@ -14,6 +14,7 @@ import { PassphraseStore } from './platform/store/passphrase-store.js'; type Host = { gmail: string; + thunderbird: string; outlook: string; settings: string; }; @@ -26,11 +27,13 @@ export class Injector { private container: { [key: string]: Host } = { composeBtnSel: { gmail: 'div.aeN, div.aBO', // .aeN for normal look, .aBO for new look https://github.com/FlowCrypt/flowcrypt-browser/issues/4099 + thunderbird: '', // todo in another issue outlook: 'div._fce_b', settings: '#does_not_have', }, finishSesionBtnSel: { gmail: 'body', + thunderbird: '', // todo in another issue outlook: '#does_not_have', settings: '#settings > div.header', }, diff --git a/extension/js/content_scripts/webmail/thunderbird/thunderbird-element-replacer.ts b/extension/js/content_scripts/webmail/thunderbird/thunderbird-element-replacer.ts new file mode 100644 index 00000000000..fc286d6e341 --- /dev/null +++ b/extension/js/content_scripts/webmail/thunderbird/thunderbird-element-replacer.ts @@ -0,0 +1,13 @@ +/* ©️ 2016 - present FlowCrypt a.s. Limitations apply. Contact human@flowcrypt.com */ + +'use strict'; + +import { IntervalFunction, WebmailElementReplacer } from '../generic/webmail-element-replacer'; + +export class ThunderbirdElementReplacer extends WebmailElementReplacer { + public getIntervalFunctions: () => IntervalFunction[]; + public setReplyBoxEditable: () => Promise; + public reinsertReplyBox: (replyMsgId: string) => void; + public scrollToReplyBox: (replyMsgId: string) => void; + public scrollToCursorInReplyBox: (replyMsgId: string, cursorOffsetTop: number) => void; +} diff --git a/extension/js/content_scripts/webmail/thunderbird/thunderbird-webmail-startup.ts b/extension/js/content_scripts/webmail/thunderbird/thunderbird-webmail-startup.ts new file mode 100644 index 00000000000..862fd56fd6e --- /dev/null +++ b/extension/js/content_scripts/webmail/thunderbird/thunderbird-webmail-startup.ts @@ -0,0 +1,38 @@ +/* ©️ 2016 - present FlowCrypt a.s. Limitations apply. Contact human@flowcrypt.com */ +import { ClientConfiguration } from '../../../common/client-configuration'; +import { Injector } from '../../../common/inject'; +import { Notifications } from '../../../common/notifications'; +import { contentScriptSetupIfVacant } from '../generic/setup-webmail-content-script'; +import { GmailElementReplacer } from '../gmail/gmail-element-replacer'; +import { ThunderbirdElementReplacer } from './thunderbird-element-replacer'; + +export class ThunderbirdWebmailStartup { + private replacer: GmailElementReplacer; + + public asyncConstructor = async () => { + await contentScriptSetupIfVacant({ + name: 'thunderbird', + variant: undefined, + getUserAccountEmail: () => undefined, // todo, but can start with undefined + getUserFullName: () => undefined, // todo, but can start with undefined + getReplacer: () => new ThunderbirdElementReplacer(), // todo - add this class empty, methods do nothing + start: this.start, + }); + }; + + private start = async ( + acctEmail: string, + clientConfiguration: ClientConfiguration, + injector: Injector, + notifications: Notifications + // factory: XssSafeFactory, // todo in another issue + // relayManager: RelayManager // todo in another issue + ) => { + // injector.btns(); // todo in another issue - add compose button + this.replacer.runIntervalFunctionsPeriodically(); + await notifications.showInitial(acctEmail); + await notifications.show( + 'FlowCrypt Thunderbird support is still in early development, and not expected to function properly yet. Support will be gradually added in upcoming versions.' + ); + }; +} diff --git a/extension/js/content_scripts/webmail/webmail.ts b/extension/js/content_scripts/webmail/webmail.ts index 5e5d6adf937..beadcc1047f 100644 --- a/extension/js/content_scripts/webmail/webmail.ts +++ b/extension/js/content_scripts/webmail/webmail.ts @@ -6,6 +6,7 @@ import { Catch } from '../../common/platform/catch.js'; import { GmailWebmailStartup } from './gmail/gmail-webmail-startup.js'; +import { ThunderbirdWebmailStartup } from './thunderbird/thunderbird-webmail-startup.js'; declare global { interface Window { @@ -16,5 +17,10 @@ declare global { Catch.try(async () => { // when we support more webmails, there will be if/else here to figure out which one to run - await new GmailWebmailStartup().asyncConstructor(); + const browserName = Catch.browser().name; + if (browserName === 'thunderbird') { + await new ThunderbirdWebmailStartup().asyncConstructor(); + } else { + await new GmailWebmailStartup().asyncConstructor(); + } })(); diff --git a/test/source/patterns.ts b/test/source/patterns.ts index 982980f67f1..cb8a4ed9459 100644 --- a/test/source/patterns.ts +++ b/test/source/patterns.ts @@ -83,7 +83,7 @@ for (const srcFilePath of getAllFilesInDir('./extension', /\.ts$/)) { const expectedPermissions = ['alarms', 'scripting', 'storage', 'tabs', 'unlimitedStorage']; const expectedConsumerHostPermissions = ['https://*.google.com/*', 'https://www.googleapis.com/*', 'https://flowcrypt.com/*']; const expectedEnterpriseHostPermissions = ['https://*.google.com/*', 'https://*.googleapis.com/*', 'https://flowcrypt.com/*']; -for (const buildType of ['chrome-consumer', 'chrome-enterprise', 'thunderbird-consumer']) { +for (const buildType of ['chrome-consumer', 'chrome-enterprise']) { const manifest = JSON.parse(readFileSync(`./build/${buildType}/manifest.json`).toString()); const expectedHostPermissions = buildType.includes('consumer') ? expectedConsumerHostPermissions : expectedEnterpriseHostPermissions; for (const expectedHostPermission of expectedHostPermissions) { diff --git a/tooling/build-types-and-manifests.ts b/tooling/build-types-and-manifests.ts index 270adbc5685..d44a9851262 100644 --- a/tooling/build-types-and-manifests.ts +++ b/tooling/build-types-and-manifests.ts @@ -51,17 +51,18 @@ addManifest('firefox-consumer', manifest => { addManifest('thunderbird-consumer', manifest => { manifest.version = version; - manifest.applications = { + manifest.manifest_version = 2; + manifest.browser_specific_settings = { gecko: { id: 'firefox@cryptup.io', update_url: 'https://flowcrypt.com/api/update/firefox', // eslint-disable-line @typescript-eslint/naming-convention strict_min_version: '102.0', // eslint-disable-line @typescript-eslint/naming-convention }, }; - manifest.name = 'FlowCrypt Encryption for Thunderbird'; manifest.browser_action = manifest.action; delete manifest.action; manifest.browser_action.default_title = 'FlowCrypt Encryption for Thunderbird'; + manifest.name = 'FlowCrypt Encryption for Thunderbird'; manifest.description = 'Secure end-to-end encryption with FlowCrypt'; // needs to updated later manifest.permissions = manifest.permissions.filter((p: string) => p !== 'unlimitedStorage'); manifest.compose_action = { @@ -76,6 +77,10 @@ addManifest('thunderbird-consumer', manifest => { // default_popup will be updated later default_popup: '/chrome/popups/default.htm', // eslint-disable-line @typescript-eslint/naming-convention }; + manifest.web_accessible_resources = manifest.web_accessible_resources[0].resources; + manifest.content_security_policy = manifest.content_security_policy.extension_pages; + manifest.background.scripts = ['/js/service_worker/background.js']; + delete manifest.host_permissions; delete manifest.background.service_worker; delete manifest.minimum_chrome_version; }); From 456841773e512f96da72a075ae3498718422ffbd Mon Sep 17 00:00:00 2001 From: martgil Date: Tue, 4 Jun 2024 13:23:22 +0800 Subject: [PATCH 06/11] Deprecated Browser.openExtensionTab and use modern BgUtils.openExtensionTab --- extension/js/common/browser/browser.ts | 14 ++++---------- extension/js/common/settings.ts | 3 ++- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/extension/js/common/browser/browser.ts b/extension/js/common/browser/browser.ts index deab0720340..a7023d06d16 100644 --- a/extension/js/common/browser/browser.ts +++ b/extension/js/common/browser/browser.ts @@ -9,6 +9,7 @@ import { Attachment } from '../core/attachment.js'; import { Catch } from '../platform/catch.js'; import { Dict, Url, UrlParam } from '../core/common.js'; import { GlobalStore } from '../platform/store/global-store.js'; +import { BgUtils } from '../../service_worker/bgutils.js'; export class Browser { public static objUrlCreate = (content: Uint8Array | string) => { @@ -56,19 +57,12 @@ export class Browser { const basePath = chrome.runtime.getURL(`chrome/settings/${path}`); const pageUrlParams = rawPageUrlParams ? JSON.stringify(rawPageUrlParams) : undefined; if (acctEmail || path === 'fatal.htm') { - Browser.openExtensionTab(Url.create(basePath, { acctEmail, page, pageUrlParams })); + await BgUtils.openExtensionTab(Url.create(basePath, { acctEmail, page, pageUrlParams })); } else if (addNewAcct) { - Browser.openExtensionTab(Url.create(basePath, { addNewAcct })); + await BgUtils.openExtensionTab(Url.create(basePath, { addNewAcct })); } else { const acctEmails = await GlobalStore.acctEmailsGet(); - Browser.openExtensionTab(Url.create(basePath, { acctEmail: acctEmails[0], page, pageUrlParams })); - } - }; - - public static openExtensionTab = (url: string) => { - const tab = window.open(url, 'flowcrypt'); - if (tab) { - tab.focus(); + await BgUtils.openExtensionTab(Url.create(basePath, { acctEmail: acctEmails[0], page, pageUrlParams })); } }; } diff --git a/extension/js/common/settings.ts b/extension/js/common/settings.ts index 176c9586ccd..94fd2d4cf10 100644 --- a/extension/js/common/settings.ts +++ b/extension/js/common/settings.ts @@ -28,6 +28,7 @@ import { Api } from './api/shared/api.js'; import { Time } from './browser/time.js'; import { Google } from './api/email-provider/gmail/google.js'; import { ConfiguredIdpOAuth } from './api/authentication/configured-idp-oauth.js'; +import { BgUtils } from '../service_worker/bgutils.js'; declare const zxcvbn: Function; // eslint-disable-line @typescript-eslint/ban-types @@ -431,7 +432,7 @@ export class Settings { public static async loginWithPopupShowModalOnErr(acctEmail: string, then: () => void = () => undefined) { if (window !== window.top && !chrome.windows) { // Firefox, chrome.windows isn't available in iframes - Browser.openExtensionTab(Url.create(chrome.runtime.getURL(`chrome/settings/index.htm`), { acctEmail })); + await BgUtils.openExtensionTab(Url.create(chrome.runtime.getURL(`chrome/settings/index.htm`), { acctEmail })); await Ui.modal.info(`Reload after logging in.`); return window.location.reload(); } From 9c06611591b2af04c123804ec6b1bac1878526ce Mon Sep 17 00:00:00 2001 From: martgil Date: Tue, 4 Jun 2024 15:56:55 +0800 Subject: [PATCH 07/11] Fix code that results to a failing test --- extension/js/common/browser/browser.ts | 14 +++++++++++--- extension/js/common/settings.ts | 3 ++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/extension/js/common/browser/browser.ts b/extension/js/common/browser/browser.ts index a7023d06d16..d1c1fad7c22 100644 --- a/extension/js/common/browser/browser.ts +++ b/extension/js/common/browser/browser.ts @@ -56,13 +56,21 @@ export class Browser { public static openSettingsPage = async (path = 'index.htm', acctEmail?: string, page = '', rawPageUrlParams?: Dict, addNewAcct = false) => { const basePath = chrome.runtime.getURL(`chrome/settings/${path}`); const pageUrlParams = rawPageUrlParams ? JSON.stringify(rawPageUrlParams) : undefined; + const preferedLinkOpener = Catch.browser().name === 'thunderbird' ? BgUtils : Browser; if (acctEmail || path === 'fatal.htm') { - await BgUtils.openExtensionTab(Url.create(basePath, { acctEmail, page, pageUrlParams })); + await preferedLinkOpener.openExtensionTab(Url.create(basePath, { acctEmail, page, pageUrlParams })); } else if (addNewAcct) { - await BgUtils.openExtensionTab(Url.create(basePath, { addNewAcct })); + await preferedLinkOpener.openExtensionTab(Url.create(basePath, { addNewAcct })); } else { const acctEmails = await GlobalStore.acctEmailsGet(); - await BgUtils.openExtensionTab(Url.create(basePath, { acctEmail: acctEmails[0], page, pageUrlParams })); + await preferedLinkOpener.openExtensionTab(Url.create(basePath, { acctEmail: acctEmails[0], page, pageUrlParams })); + } + }; + + public static openExtensionTab = (url: string) => { + const tab = window.open(url, 'flowcrypt'); + if (tab) { + tab.focus(); } }; } diff --git a/extension/js/common/settings.ts b/extension/js/common/settings.ts index 94fd2d4cf10..2165532b68d 100644 --- a/extension/js/common/settings.ts +++ b/extension/js/common/settings.ts @@ -431,8 +431,9 @@ export class Settings { public static async loginWithPopupShowModalOnErr(acctEmail: string, then: () => void = () => undefined) { if (window !== window.top && !chrome.windows) { + const preferedLinkOpener = Catch.browser().name === 'thunderbird' ? BgUtils : Browser; // Firefox, chrome.windows isn't available in iframes - await BgUtils.openExtensionTab(Url.create(chrome.runtime.getURL(`chrome/settings/index.htm`), { acctEmail })); + await preferedLinkOpener.openExtensionTab(Url.create(chrome.runtime.getURL(`chrome/settings/index.htm`), { acctEmail })); await Ui.modal.info(`Reload after logging in.`); return window.location.reload(); } From c2752b920160aae4771ac62bfbb2c9e7a1e62c64 Mon Sep 17 00:00:00 2001 From: martgil Date: Tue, 4 Jun 2024 16:22:59 +0800 Subject: [PATCH 08/11] Adjust manifest.json permissions for XHR requests --- tooling/build-types-and-manifests.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tooling/build-types-and-manifests.ts b/tooling/build-types-and-manifests.ts index d44a9851262..efe4706fee7 100644 --- a/tooling/build-types-and-manifests.ts +++ b/tooling/build-types-and-manifests.ts @@ -64,6 +64,7 @@ addManifest('thunderbird-consumer', manifest => { manifest.browser_action.default_title = 'FlowCrypt Encryption for Thunderbird'; manifest.name = 'FlowCrypt Encryption for Thunderbird'; manifest.description = 'Secure end-to-end encryption with FlowCrypt'; // needs to updated later + manifest.permissions = [...manifest.permissions, ...manifest.host_permissions]; manifest.permissions = manifest.permissions.filter((p: string) => p !== 'unlimitedStorage'); manifest.compose_action = { default_title: 'FlowCrypt', // eslint-disable-line @typescript-eslint/naming-convention From c4678707635fa14f80337559037497fde669cd17 Mon Sep 17 00:00:00 2001 From: martgil Date: Wed, 5 Jun 2024 13:54:10 +0800 Subject: [PATCH 09/11] Pr review: improved way of opening extensions link per browser --- extension/js/common/browser/browser.ts | 19 +++++++++++-------- extension/js/common/settings.ts | 4 +--- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/extension/js/common/browser/browser.ts b/extension/js/common/browser/browser.ts index d1c1fad7c22..cd22fa31225 100644 --- a/extension/js/common/browser/browser.ts +++ b/extension/js/common/browser/browser.ts @@ -56,21 +56,24 @@ export class Browser { public static openSettingsPage = async (path = 'index.htm', acctEmail?: string, page = '', rawPageUrlParams?: Dict, addNewAcct = false) => { const basePath = chrome.runtime.getURL(`chrome/settings/${path}`); const pageUrlParams = rawPageUrlParams ? JSON.stringify(rawPageUrlParams) : undefined; - const preferedLinkOpener = Catch.browser().name === 'thunderbird' ? BgUtils : Browser; if (acctEmail || path === 'fatal.htm') { - await preferedLinkOpener.openExtensionTab(Url.create(basePath, { acctEmail, page, pageUrlParams })); + await Browser.openExtensionTab(Url.create(basePath, { acctEmail, page, pageUrlParams })); } else if (addNewAcct) { - await preferedLinkOpener.openExtensionTab(Url.create(basePath, { addNewAcct })); + await Browser.openExtensionTab(Url.create(basePath, { addNewAcct })); } else { const acctEmails = await GlobalStore.acctEmailsGet(); - await preferedLinkOpener.openExtensionTab(Url.create(basePath, { acctEmail: acctEmails[0], page, pageUrlParams })); + await Browser.openExtensionTab(Url.create(basePath, { acctEmail: acctEmails[0], page, pageUrlParams })); } }; - public static openExtensionTab = (url: string) => { - const tab = window.open(url, 'flowcrypt'); - if (tab) { - tab.focus(); + public static openExtensionTab = async (url: string) => { + if (Catch.browser().name === 'thunderbird') { + await BgUtils.openExtensionTab(url); + } else { + const tab = window.open(url, 'flowcrypt'); + if (tab) { + tab.focus(); + } } }; } diff --git a/extension/js/common/settings.ts b/extension/js/common/settings.ts index 2165532b68d..74e5432fc9e 100644 --- a/extension/js/common/settings.ts +++ b/extension/js/common/settings.ts @@ -28,7 +28,6 @@ import { Api } from './api/shared/api.js'; import { Time } from './browser/time.js'; import { Google } from './api/email-provider/gmail/google.js'; import { ConfiguredIdpOAuth } from './api/authentication/configured-idp-oauth.js'; -import { BgUtils } from '../service_worker/bgutils.js'; declare const zxcvbn: Function; // eslint-disable-line @typescript-eslint/ban-types @@ -431,9 +430,8 @@ export class Settings { public static async loginWithPopupShowModalOnErr(acctEmail: string, then: () => void = () => undefined) { if (window !== window.top && !chrome.windows) { - const preferedLinkOpener = Catch.browser().name === 'thunderbird' ? BgUtils : Browser; // Firefox, chrome.windows isn't available in iframes - await preferedLinkOpener.openExtensionTab(Url.create(chrome.runtime.getURL(`chrome/settings/index.htm`), { acctEmail })); + await Browser.openExtensionTab(Url.create(chrome.runtime.getURL(`chrome/settings/index.htm`), { acctEmail })); await Ui.modal.info(`Reload after logging in.`); return window.location.reload(); } From ca6b352d178af0a66c486cc9312fa09c1425204b Mon Sep 17 00:00:00 2001 From: martgil Date: Wed, 5 Jun 2024 14:22:14 +0800 Subject: [PATCH 10/11] Pr review: enable manifest.json reuse --- tooling/build-types-and-manifests.ts | 62 +++++++++++----------------- 1 file changed, 24 insertions(+), 38 deletions(-) diff --git a/tooling/build-types-and-manifests.ts b/tooling/build-types-and-manifests.ts index efe4706fee7..d613e94efe1 100644 --- a/tooling/build-types-and-manifests.ts +++ b/tooling/build-types-and-manifests.ts @@ -15,8 +15,8 @@ const DIR = './build'; const version: string = JSON.parse(readFileSync('./package.json').toString()).version; // eslint-disable-next-line @typescript-eslint/no-explicit-any -const addManifest = (toBuildType: string, transform: (manifest: { [k: string]: any }) => void) => { - const manifest = JSON.parse(readFileSync(`${DIR}/generic-extension-wip/manifest.json`).toString()); +const addManifest = (toBuildType: string, transform: (manifest: { [k: string]: any }) => void, fromBuildType = 'generic-extension-wip') => { + const manifest = JSON.parse(readFileSync(`${DIR}/${fromBuildType}/manifest.json`).toString()); transform(manifest); writeFileSync(`${DIR}/${toBuildType}/manifest.json`, JSON.stringify(manifest, undefined, 2)); }; @@ -49,42 +49,28 @@ addManifest('firefox-consumer', manifest => { delete manifest.minimum_chrome_version; }); -addManifest('thunderbird-consumer', manifest => { - manifest.version = version; - manifest.manifest_version = 2; - manifest.browser_specific_settings = { - gecko: { - id: 'firefox@cryptup.io', - update_url: 'https://flowcrypt.com/api/update/firefox', // eslint-disable-line @typescript-eslint/naming-convention - strict_min_version: '102.0', // eslint-disable-line @typescript-eslint/naming-convention - }, - }; - manifest.browser_action = manifest.action; - delete manifest.action; - manifest.browser_action.default_title = 'FlowCrypt Encryption for Thunderbird'; - manifest.name = 'FlowCrypt Encryption for Thunderbird'; - manifest.description = 'Secure end-to-end encryption with FlowCrypt'; // needs to updated later - manifest.permissions = [...manifest.permissions, ...manifest.host_permissions]; - manifest.permissions = manifest.permissions.filter((p: string) => p !== 'unlimitedStorage'); - manifest.compose_action = { - default_title: 'FlowCrypt', // eslint-disable-line @typescript-eslint/naming-convention - default_icon: '/img/logo/flowcrypt-logo-64-64.png', // eslint-disable-line @typescript-eslint/naming-convention - // default_popup will be updated later - default_popup: '/chrome/popups/default.htm', // eslint-disable-line @typescript-eslint/naming-convention - }; - manifest.message_display_action = { - default_title: 'FlowCrypt', // eslint-disable-line @typescript-eslint/naming-convention - default_icon: '/img/logo/flowcrypt-logo-64-64.png', // eslint-disable-line @typescript-eslint/naming-convention - // default_popup will be updated later - default_popup: '/chrome/popups/default.htm', // eslint-disable-line @typescript-eslint/naming-convention - }; - manifest.web_accessible_resources = manifest.web_accessible_resources[0].resources; - manifest.content_security_policy = manifest.content_security_policy.extension_pages; - manifest.background.scripts = ['/js/service_worker/background.js']; - delete manifest.host_permissions; - delete manifest.background.service_worker; - delete manifest.minimum_chrome_version; -}); +addManifest( + 'thunderbird-consumer', + manifest => { + manifest.browser_specific_settings.strict_min_version = '102.0'; + manifest.browser_action.default_title = 'FlowCrypt Encryption for Thunderbird'; + manifest.name = 'FlowCrypt Encryption for Thunderbird'; + manifest.description = 'Secure end-to-end encryption with FlowCrypt'; // needs to updated later + manifest.compose_action = { + default_title: 'FlowCrypt', // eslint-disable-line @typescript-eslint/naming-convention + default_icon: '/img/logo/flowcrypt-logo-64-64.png', // eslint-disable-line @typescript-eslint/naming-convention + // default_popup will be updated later + default_popup: '/chrome/popups/default.htm', // eslint-disable-line @typescript-eslint/naming-convention + }; + manifest.message_display_action = { + default_title: 'FlowCrypt', // eslint-disable-line @typescript-eslint/naming-convention + default_icon: '/img/logo/flowcrypt-logo-64-64.png', // eslint-disable-line @typescript-eslint/naming-convention + // default_popup will be updated later + default_popup: '/chrome/popups/default.htm', // eslint-disable-line @typescript-eslint/naming-convention + }; + }, + 'firefox-consumer' +); addManifest('chrome-enterprise', manifest => { manifest.version = version; From fda413ed5c558ae364979a8e1fe46a62d4cdd4a8 Mon Sep 17 00:00:00 2001 From: martgil Date: Wed, 5 Jun 2024 16:55:46 +0800 Subject: [PATCH 11/11] Pr review: cleanup --- .../webmail/thunderbird/thunderbird-webmail-startup.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extension/js/content_scripts/webmail/thunderbird/thunderbird-webmail-startup.ts b/extension/js/content_scripts/webmail/thunderbird/thunderbird-webmail-startup.ts index 862fd56fd6e..2e0b16a4d84 100644 --- a/extension/js/content_scripts/webmail/thunderbird/thunderbird-webmail-startup.ts +++ b/extension/js/content_scripts/webmail/thunderbird/thunderbird-webmail-startup.ts @@ -31,7 +31,7 @@ export class ThunderbirdWebmailStartup { // injector.btns(); // todo in another issue - add compose button this.replacer.runIntervalFunctionsPeriodically(); await notifications.showInitial(acctEmail); - await notifications.show( + notifications.show( 'FlowCrypt Thunderbird support is still in early development, and not expected to function properly yet. Support will be gradually added in upcoming versions.' ); };