Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / packages / pass / lib / globals / browser.ts
blobe97fd80eafc3ac8fc06f710e5cd7e9953e4b565e
1 /* We create a proxy around the `chrome` or `browser` global object to hide them
2  * from the devtools of our extension. This is done to prevent developers from
3  * accidentally or intentionally modifying the extension's messaging system, which
4  * could cause unexpected behavior or security issues. By hiding these globals,
5  * we ensure that the extension's messaging system is only accessed through the
6  * provided APIs, and not directly through the devtools console or other means */
7 import browser, { type Browser } from 'webextension-polyfill';
9 import { logger } from '@proton/pass/utils/logger';
11 const self = globalThis as any;
12 const context = {
13     allowProxy: true,
14     globals: {
15         chrome: self.chrome,
16         browser: self.browser,
17     },
20 export const disableBrowserProxyTrap = () => (context.allowProxy = false);
22 /* To ensure that Sentry's internal checks involving the browser
23  * APIs don't interfere with the initialization of our apps, we
24  * wrap the proxy initialization in a setTimeout function, which
25  * delays the initialization until the next tick after our apps load.
26  * ⚠️ Make sure Sentry is always initialized on app boot. */
27 export default ((): Browser => {
28     if (BUILD_TARGET === 'safari') return self.browser;
30     const polyfill = browser;
32     setTimeout(
33         () =>
34             context.allowProxy &&
35             Object.entries(context.globals)
36                 .filter(([, value]) => value)
37                 .forEach(([key, value]) => {
38                     self[key] = new Proxy(value, {
39                         get(target, prop, receiver) {
40                             if (process.env.NODE_ENV !== 'development') {
41                                 /** Early return `undefined` for 'app' property to prevent
42                                  * Sentry's ChromeApp detection from generating errors */
43                                 if (prop === 'app') return undefined;
44                                 return logger.error(`[Extension::Error] extension API is protected`);
45                             }
47                             return Reflect.get(target, prop, receiver);
48                         },
49                         set() {
50                             logger.error(`[Extension::Error] extension API is read-only`);
51                             return false;
52                         },
53                     });
54                 }),
55         0
56     );
58     return polyfill;
59 })();
61 export const chromeAPI = context.globals.chrome as typeof chrome;