Skip to content

Commit

Permalink
prevent "window.sessionStorage" access denied error
Browse files Browse the repository at this point in the history
* @electron v13 => v14-beta upgrade resolves the error but @electron v14-beta (more likely its @chromium part) at the moment has problems of displaying the https://github.com/ProtonMail/react-components/blob/master/components/select/Select.tsx component in its dropdown state (clicking on this "select" control doesn't open the options list)
  • Loading branch information
vladimiry committed Jun 20, 2021
1 parent 3cbcd2d commit 11c25fa
Show file tree
Hide file tree
Showing 10 changed files with 82 additions and 50 deletions.
2 changes: 2 additions & 0 deletions electron-builder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
7 changes: 3 additions & 4 deletions src/electron-main/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
4 changes: 1 addition & 3 deletions src/electron-main/window/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,7 @@ export async function initMainBrowserWindow(ctx: Context): Promise<BrowserWindow
webPreferences: {
...DEFAULT_WEB_PREFERENCES,
webviewTag: true,
preload: BUILD_ENVIRONMENT === "e2e"
? ctx.locations.preload.browserWindowE2E
: ctx.locations.preload.browserWindow,
preload: ctx.locations.preload.browserWindow,
},
title: PRODUCT_NAME,
icon: ctx.locations.icon,
Expand Down
2 changes: 1 addition & 1 deletion src/electron-preload/webview/calendar/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {setupProtonOpenNewTabEventHandler} from "src/electron-preload/webview/li
const logger = curryFunctionMembers(WEBVIEW_LOGGERS.calendar, __filename);
const protonAppPageStatus = testProtonCalendarAppPage({url: getLocationHref(), logger});

documentCookiesForCustomScheme.enable(logger, true);
documentCookiesForCustomScheme.enable(logger);
setupProtonOpenNewTabEventHandler(logger);

// TODO throw error if "not calendar or blank.html" page loaded
Expand Down
15 changes: 7 additions & 8 deletions src/electron-preload/webview/lib/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,21 +311,22 @@ export const fetchEvents = async (
// https://github.com/electron/electron/issues/27981
// https://github.com/ProtonMail/react-components/commit/0558e441583029f644d1a17b68743436a29d5db2#commitcomment-52005249
export const documentCookiesForCustomScheme: {
readonly enable: (logger: Logger, persist: boolean) => 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", {
Expand All @@ -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});
},
});
},
Expand Down
77 changes: 51 additions & 26 deletions src/electron-preload/webview/primary/index.ts
Original file line number Diff line number Diff line change
@@ -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<void> => {
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,
);
});
1 change: 0 additions & 1 deletion src/shared/model/electron.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ export type ElectronContextLocations = Readonly<{
preload: Readonly<{
aboutBrowserWindow: string;
browserWindow: string;
browserWindowE2E: string;
searchInPageBrowserView: string;
fullTextSearchBrowserWindow: string;
primary: string;
Expand Down
11 changes: 8 additions & 3 deletions webpack-configs/preload/webview-calendar.ts
Original file line number Diff line number Diff line change
@@ -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"),
);
11 changes: 8 additions & 3 deletions webpack-configs/preload/webview-primary.ts
Original file line number Diff line number Diff line change
@@ -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"),
);

0 comments on commit 11c25fa

Please sign in to comment.