diff --git a/electron-builder.yml b/electron-builder.yml index ceefba352..984a390b5 100644 --- a/electron-builder.yml +++ b/electron-builder.yml @@ -14,6 +14,8 @@ files: - './package.json' - '!app/electron-main-e2e.js' - '!app/electron-preload/browser-window-e2e.js' + - '!app/electron-preload/webview/calendar-e2e.js' + - '!app/electron-preload/webview/primary-e2e.js' - '!node_modules/rxjs/{_esm5,_esm2015,src,bundles}' - '!node_modules/pureimage/{firstimages,tests}' # sodium-native TODO: include into the package only needed prebuilds for the platform is being built diff --git a/package.json b/package.json index 01798c4b5..3093faad4 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "lint:ts:eslint": "yarn lint:ts:base:eslint \"./src/**/*.ts\" \"./scripts/**/*.ts\" \"./webpack-configs/**/*.ts\"", "start:electron": "electron ./app/electron-main.js", "start:electron:dev": "electron ./app-dev/electron-main.js", - "test:e2e:build-code": "cross-env NODE_ENV=e2e npm-run-all build:electron-main build:electron-preload:browser-window", + "test:e2e:build-code": "cross-env NODE_ENV=e2e npm-run-all build:electron-main build:electron-preload:browser-window build:electron-preload:webview-primary build:electron-preload:webview-calendar", "test:e2e:run": "cross-env TS_NODE_FILES=true DEBUG=pw:api npm exec --package=ava --node-options=\"--require tsconfig-paths/register --require ts-node/register\" -- ava \"./src/e2e/**/*.{spec,test}.ts\"", "test:e2e": "npm-run-all test:e2e:build-code test:e2e:run", "scripts/code-generation/electron-main": "yarn ts-node:shortcut ./scripts/code-generation/electron-main.ts", diff --git a/src/electron-main/context.ts b/src/electron-main/context.ts index a23972f5f..4ba56cc88 100644 --- a/src/electron-main/context.ts +++ b/src/electron-main/context.ts @@ -130,12 +130,11 @@ function initLocations( searchInPageBrowserViewPage: appRelativePath("./web/", WEBPACK_WEB_CHUNK_NAMES["search-in-page-browser-view"], "index.html"), preload: { aboutBrowserWindow: appRelativePath("./electron-preload/about.js"), - browserWindow: appRelativePath("./electron-preload/browser-window.js"), - browserWindowE2E: appRelativePath("./electron-preload/browser-window-e2e.js"), + browserWindow: appRelativePath(`./electron-preload/browser-window${BUILD_ENVIRONMENT === "e2e" ? "-e2e" : ""}.js`), searchInPageBrowserView: appRelativePath("./electron-preload/search-in-page-browser-view.js"), fullTextSearchBrowserWindow: appRelativePath("./electron-preload/database-indexer.js"), - primary: formatFileUrl(appRelativePath("./electron-preload/webview/primary.js")), - calendar: formatFileUrl(appRelativePath("./electron-preload/webview/calendar.js")), + primary: formatFileUrl(appRelativePath(`./electron-preload/webview/primary${BUILD_ENVIRONMENT === "e2e" ? "-e2e" : ""}.js`)), + calendar: formatFileUrl(appRelativePath(`./electron-preload/webview/calendar${BUILD_ENVIRONMENT === "e2e" ? "-e2e" : ""}.js`)), }, // TODO electron: get rid of "baseURLForDataURL" workaround, see https://github.com/electron/electron/issues/20700 vendorsAppCssLinkHrefs: ["shared-vendor-dark", "shared-vendor-light"] diff --git a/src/electron-main/window/main.ts b/src/electron-main/window/main.ts index 5b8f5705f..3e063e601 100644 --- a/src/electron-main/window/main.ts +++ b/src/electron-main/window/main.ts @@ -129,9 +129,7 @@ export async function initMainBrowserWindow(ctx: Context): Promise void + readonly enable: (logger: Logger) => void readonly setNotification$: Observable<{ url: string, cookieString: string }> } = (() => { // we don't need all the values but just to be able to send a signal, so "buffer = 1" should be enough const setNotificationSubject$ = new ReplaySubject<{ url: string, cookieString: string }>(1); const result: typeof documentCookiesForCustomScheme = { setNotification$: setNotificationSubject$.asObservable(), - enable(logger, persist) { + enable(logger) { logger.verbose(nameof(documentCookiesForCustomScheme), nameof(result.enable)); const {document, location} = window; const getUrl = (): string => resolveApiUrlByPackagedWebClientUrlSafe(location.toString()); - const store = new WebStorageCookieStore(window.sessionStorage); - const cookieJar = persist - ? new CookieJar(store) + // TODO (electron) drop BUILD_ENVIRONMENT !== "e2e" condition: + // electron v13 throws "window.sessionStorage" access denied error in e2e/playwright mode + const cookieJar = BUILD_ENVIRONMENT !== "e2e" + ? new CookieJar(new WebStorageCookieStore(window.sessionStorage)) : new CookieJar(); Object.defineProperty(document, "cookie", { @@ -341,9 +342,7 @@ export const documentCookiesForCustomScheme: { set(cookieString: typeof document.cookie) { const url = getUrl(); cookieJar.setCookieSync(cookieString, url); - if (persist) { - setNotificationSubject$.next({url, cookieString}); - } + setNotificationSubject$.next({url, cookieString}); }, }); }, diff --git a/src/electron-preload/webview/primary/index.ts b/src/electron-preload/webview/primary/index.ts index beb480ccb..dac9ac4df 100644 --- a/src/electron-preload/webview/primary/index.ts +++ b/src/electron-preload/webview/primary/index.ts @@ -1,30 +1,55 @@ -import {WEBVIEW_LOGGERS} from "src/electron-preload/webview/lib/const"; -import {curryFunctionMembers, testProtonMailAppPage} from "src/shared/util"; -import {documentCookiesForCustomScheme, getLocationHref} from "src/electron-preload/webview/lib/util"; -import {initProviderApi} from "./provider-api"; -import {registerApi} from "./api"; -import {setupProtonOpenNewTabEventHandler} from "src/electron-preload/webview/lib/custom-event"; -import {setupProviderIntegration} from "./provider-api/setup"; +const main = async (): Promise => { + const [ + {WEBVIEW_LOGGERS}, + {curryFunctionMembers, testProtonMailAppPage}, + {documentCookiesForCustomScheme, getLocationHref}, + {initProviderApi}, + {registerApi}, + {setupProtonOpenNewTabEventHandler}, + {setupProviderIntegration}, + ] = await Promise.all([ + import("src/electron-preload/webview/lib/const"), + import("src/shared/util"), + import("src/electron-preload/webview/lib/util"), + import("./provider-api"), + import("./api"), + import("src/electron-preload/webview/lib/custom-event"), + import("./provider-api/setup"), + ]); -const logger = curryFunctionMembers(WEBVIEW_LOGGERS.primary, __filename); -const protonAppPageStatus = testProtonMailAppPage({url: getLocationHref(), logger}); + const logger = curryFunctionMembers(WEBVIEW_LOGGERS.primary, __filename); + const protonAppPageStatus = testProtonMailAppPage({url: getLocationHref(), logger}); -documentCookiesForCustomScheme.enable(logger, true); -setupProtonOpenNewTabEventHandler(logger); -setupProviderIntegration(protonAppPageStatus); + documentCookiesForCustomScheme.enable(logger); + setupProtonOpenNewTabEventHandler(logger); + setupProviderIntegration(protonAppPageStatus); -if (protonAppPageStatus.shouldInitProviderApi) { - // TODO set up timeout - initProviderApi() - .then(registerApi) - .catch((error) => { - logger.error(error); - throw error; - }); -} + if (!protonAppPageStatus.shouldInitProviderApi) { + return; + } -if (BUILD_ENVIRONMENT === "development") { - window.addEventListener("error", (event) => { - console.log("window.error event:", event); // eslint-disable-line no-console - }); -} + try { + // TODO set up timeout + registerApi( + await initProviderApi(), + ); + } catch (error) { + logger.error(error); + throw error; + } +}; + +(async () => { + await main(); +})().catch((error) => { + console.error( // eslint-disable-line no-console + typeof error === "object" + ? ( + new Error( + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + JSON.stringify({name: String(error.name), message: String(error.message), stack: String(error.stack)}), + ) + ) + : error, + ); +}); diff --git a/src/shared/model/electron.ts b/src/shared/model/electron.ts index 6af683356..43d6f9b05 100644 --- a/src/shared/model/electron.ts +++ b/src/shared/model/electron.ts @@ -24,7 +24,6 @@ export type ElectronContextLocations = Readonly<{ preload: Readonly<{ aboutBrowserWindow: string; browserWindow: string; - browserWindowE2E: string; searchInPageBrowserView: string; fullTextSearchBrowserWindow: string; primary: string; diff --git a/webpack-configs/preload/webview-calendar.ts b/webpack-configs/preload/webview-calendar.ts index 45d6ccae0..0073f05d0 100644 --- a/webpack-configs/preload/webview-calendar.ts +++ b/webpack-configs/preload/webview-calendar.ts @@ -1,9 +1,14 @@ +import path from "path"; + +import {ENVIRONMENT_STATE, srcRelativePath} from "webpack-configs/lib"; import {buildRendererConfig} from "./lib"; -import {srcRelativePath} from "webpack-configs/lib"; + +const baseEntryName = "electron-preload/webview/calendar"; +const src = (value: string): string => path.join(srcRelativePath(baseEntryName), value); export default buildRendererConfig( { - "electron-preload/webview/calendar": srcRelativePath("./electron-preload/webview/calendar/index.ts"), + [`${baseEntryName}${ENVIRONMENT_STATE.e2e ? "-e2e" : ""}`]: src("./index.ts"), }, - srcRelativePath("./electron-preload/webview/calendar/tsconfig.json"), + src("./tsconfig.json"), ); diff --git a/webpack-configs/preload/webview-primary.ts b/webpack-configs/preload/webview-primary.ts index 946affa7c..3988165e5 100644 --- a/webpack-configs/preload/webview-primary.ts +++ b/webpack-configs/preload/webview-primary.ts @@ -1,9 +1,14 @@ +import path from "path"; + +import {ENVIRONMENT_STATE, srcRelativePath} from "webpack-configs/lib"; import {buildRendererConfig} from "./lib"; -import {srcRelativePath} from "webpack-configs/lib"; + +const baseEntryName = "electron-preload/webview/primary"; +const src = (value: string): string => path.join(srcRelativePath(baseEntryName), value); export default buildRendererConfig( { - "electron-preload/webview/primary": srcRelativePath("./electron-preload/webview/primary/index.ts"), + [`${baseEntryName}${ENVIRONMENT_STATE.e2e ? "-e2e" : ""}`]: src("./index.ts"), }, - srcRelativePath("./electron-preload/webview/primary/tsconfig.json"), + src("./tsconfig.json"), );