diff --git a/packages/yoroi-extension/app/api/thunk.js b/packages/yoroi-extension/app/api/thunk.js index 2299cf5b1a..a9fbce2733 100644 --- a/packages/yoroi-extension/app/api/thunk.js +++ b/packages/yoroi-extension/app/api/thunk.js @@ -164,8 +164,8 @@ export async function getWallets(walletId?: number): Promise> return resp; } -export async function subscribe(activeWalletId: ?number): Promise { - await callBackground({ type: 'subscribe', request: { activeWalletId } }); +export async function subscribe(activeWalletId: ?number, changed?: boolean): Promise { + await callBackground({ type: 'subscribe', request: { activeWalletId, changed: changed === true } }); } export const createWallet: GetEntryFuncType = async (request) => { diff --git a/packages/yoroi-extension/app/stores/toplevel/WalletStore.js b/packages/yoroi-extension/app/stores/toplevel/WalletStore.js index 1bca0fbb65..c102b993bb 100644 --- a/packages/yoroi-extension/app/stores/toplevel/WalletStore.js +++ b/packages/yoroi-extension/app/stores/toplevel/WalletStore.js @@ -182,11 +182,11 @@ export default class WalletStore extends Store { runInAction(() => { this.wallets.push(newWallet); + this.initialSyncingWalletIds.add(newWallet.publicDeriverId); this._setActiveWallet({ publicDeriverId: newWallet.publicDeriverId, }); this.actions.dialogs.closeActiveDialog.trigger(); - this.initialSyncingWalletIds.add(newWallet.publicDeriverId); this.actions.router.goToRoute.trigger({ route: ROUTES.WALLETS.ROOT }); }); }; @@ -286,11 +286,15 @@ export default class WalletStore extends Store { this.actions.profile.setSelectedNetwork.trigger( getNetworkById(this.wallets[walletIndex].networkId) ); + const changed = (this.selectedIndex != null) && (this.selectedIndex !== walletIndex) + // This flag is used to determine whether to send the active-wallet-open event to Bring's content script. + // Don't send it here when we are creating a new wallet because the wallet hasn't been synced. + && !this.isInitialSyncing(publicDeriverId); this.selectedIndex = walletIndex; this.selectedWalletName = this.wallets[walletIndex].name; // Cache select wallet this.api.localStorage.setSelectedWalletId(publicDeriverId); - subscribe(publicDeriverId); + subscribe(publicDeriverId, changed); }; getLastSelectedWallet: void => ?WalletState = () => { diff --git a/packages/yoroi-extension/chrome/content-scripts/bringInject.js b/packages/yoroi-extension/chrome/content-scripts/bringInject.js new file mode 100644 index 0000000000..7aa32587f9 --- /dev/null +++ b/packages/yoroi-extension/chrome/content-scripts/bringInject.js @@ -0,0 +1,180 @@ +// @flow + +import { bringInitContentScript } from "@bringweb3/chrome-extension-kit"; + +(async () => { + await bringInitContentScript({ + iframeEndpoint: process.env.IFRAME_ENDPOINT, + getWalletAddress: async () => await new Promise(resolve => setTimeout(() => resolve(''), 200)),// Async function that returns the current user's wallet address + promptLogin: () => { return window.prompt('login'); }, // Function that prompts a UI element asking the user to login + walletAddressListeners: ["customEvent:addressChanged"], // A list of custom events that dispatched when the user's wallet address had changed + customTheme: { + // font + fontUrl: 'https://fonts.googleapis.com/css2?family=Matemasie&display=swap', + fontFamily: "'Matemasie', system-ui", + // Popup + popupBg: "#192E34", + popupShadow: "", + // Primary button + primaryBtnBg: "linear-gradient(135deg, #5DEB5A 0%, #FDFC47 100%)", + primaryBtnFC: "#041417", + primaryBtnFW: "600", + primaryBtnFS: "14px", + primaryBtnBorderC: "transparent", + primaryBtnBorderW: "0", + primaryBtnRadius: "8px", + // Secondary button + secondaryBtnBg: "transparent", + secondaryBtnFS: "12px", + secondaryBtnFW: "500", + secondaryBtnFC: "white", + secondaryBtnBorderC: "rgba(149, 176, 178, 0.50)", + secondaryBtnBorderW: "2px", + secondaryBtnRadius: "8px", + // Markdown + markdownBg: "#07131766", + markdownFS: "12px", + markdownFC: "#DADCE5", + markdownBorderW: "0", + markdownRadius: "4px", + markdownBorderC: "black", + markdownScrollbarC: "#DADCE5", + // Wallet address + walletBg: "#33535B", + walletFS: "10px", + walletFW: "400", + walletFC: "white", + walletBorderC: "white", + walletBorderW: "0", + walletRadius: "4px", + // Details of offering + detailsBg: "#33535B", + detailsTitleFS: "15px", + detailsTitleFW: "600", + detailsTitleFC: "white", + detailsSubtitleFS: "14px", + detailsSubtitleFW: "500", + detailsSubtitleFC: "#A8ADBF", + detailsRadius: "8px", + detailsBorderW: "0", + detailsBorderC: "transparent", + detailsAmountFC: "#5DEB5A", + detailsAmountFW: "700", + // Overlay + overlayBg: "#192E34E6", + overlayFS: "13px", + overlayFW: "400", + overlayFC: "#DADCE5", + loaderBg: "#0A2EC0", + // Optout \ Turn off + optoutBg: "#192E34", + optoutFS: "14px", + optoutFW: "400", + optoutFC: "white", + optoutRadius: "56px", + // X Button and close buttons + closeFS: "9px", + closeFW: "300", + closeFC: "#B9BBBF", + // Token name + tokenBg: "transparent", + tokenFS: "13px", + tokenFW: "600", + tokenFC: "#DADCE5", + tokenBorderW: "2px", + tokenBorderC: "#DADCE5", + // Notification popup + notificationFS: "14px", + notificationFW: "500", + notificationFC: "white", + notificationBtnBg: "linear-gradient(135deg, #5DEB5A 0%, #FDFC47 100%)", + notificationBtnFS: "12px", + notificationBtnFW: "500", + notificationBtnFC: "#041417", + notificationBtnBorderW: "0", + notificationBtnBorderC: "transparent", + notificationBtnRadius: "8px", + activateTitleFS: "--activate-title-f-s", + activateTitleFW: "--activate-title-f-w", + activateTitleFC: "--activate-title-f-c", + activateTitleBoldFS: "--activate-title-bold-f-s", + activateTitleBoldFW: "--activate-title-bold-f-w", + activateTitleBoldFC: "--activate-title-bold-f-c", + } + }); +})().catch(console.error); + +function getFromBackground(functionName: string, params: andy): Promise { + const uid = Math.random(); + return new Promise((resolve, reject) => { + chrome.runtime.onMessage.addListener((msg, sender) => { + if (msg.type === 'connector_rpc_response' && msg.uid === uid) { + if (msg.return.ok) { + resolve(msg.return.ok); + } else { + reject(new Error(msg.return.err)); + } + } + }); + + window.postMessage({ + type: "connector_rpc_request", + url: location.hostname, + uid, + function: functionName, + params, + returnType: 'json', + }); + }); +} + +async function getFirstAddress(): Promise { + const usedAddresses = await getFromBackground('get_used_addresses', [undefined]); + if (usedAddresses.length > 0) { + return usedAddresses[0]; + } + const unusedAddresses = await getFromBackground('get_unused_addresses', [undefined]); + return unusedAddresses[0]; +} + +function getTheme(): Promise<'light' | 'dark'> { + return getFromBackground('get-theme-mode', [undefined]); +} + +function popUpWalletCreation(): void { + getFromBackground('pop-up-wallet-creation'); +} + +function listenForActiveWalletOpen(callback) { + // todo: verify sender extension id + chrome.runtime.onMessage.addListener((msg, sender) => { + if (msg.type === 'active-wallet-open') { + callback(msg.activeWalletId); + } + }); +} + +async function example() { + try { + const addr = await getFirstAddress(); + console.log('address', addr); + } catch (error) { + if (error.message === 'no wallet') { + console.log('no wallet'); + if (window.confirm('no wallet, click OK to create')) { + popUpWalletCreation(); + } + } else { + throw error; + } + } + + const theme = await getTheme(); + console.log('theme:', theme); + + listenForActiveWalletOpen((walletId: ?number) => { + console.log('active wallet ID is:', walletId); + }); +} + +example().catch(console.error); diff --git a/packages/yoroi-extension/chrome/extension/background/handlers/content/rpc.js b/packages/yoroi-extension/chrome/extension/background/handlers/content/rpc.js index 313c481050..ea440ae3a9 100644 --- a/packages/yoroi-extension/chrome/extension/background/handlers/content/rpc.js +++ b/packages/yoroi-extension/chrome/extension/background/handlers/content/rpc.js @@ -65,6 +65,7 @@ import { } from './connect'; import type { CardanoTxRequest } from '../../../../../app/api/ada'; import type { NFTMetadata } from '../../../../../app/api/ada/lib/storage/database/primitives/tables'; +import { getPublicDeriverById } from '../yoroi/utils'; import { getProtocolParameters } from '../yoroi/protocolParameters'; import { hexToBytes } from '../../../../../app/coreUtils'; @@ -641,6 +642,25 @@ const Handlers = Object.freeze({ ); } }), + + 'get-theme-mode': NewHandler.basic< + void, + 'dark' | 'light' + >(async () => { + const localStorageApi = new LocalStorageApi(); + let theme = await localStorageApi.getUserThemeMode(); + if (theme !== 'light' && theme !== 'dark') { + theme = 'light'; + } + return { ok: theme }; + }), + + 'pop-up-wallet-creation': NewHandler.basic< + void, + void, + >(async () => { + chrome.tabs.create({ url: 'main_window.html' }); + }), }); function sendRpcResponse(response: Object, tabId: number, messageUid: number) { @@ -688,7 +708,26 @@ export async function handleRpc(message: Object, sender: Object) { let connectedWallet = undefined; if (handler.needConnectedWallet) { - connectedWallet = await getConnectedWallet(tabId, handler.syncConnectedWallet); + try { + connectedWallet = await getConnectedWallet(tabId, handler.syncConnectedWallet); + } catch (error) { + // fixme: unsafe + const localStorageApi = new LocalStorageApi(); + const publicDeriverId = await localStorageApi.getSelectedWalletId(); + if (publicDeriverId != null) { + connectedWallet = await getPublicDeriverById(publicDeriverId); + } + if (connectedWallet == null) { + sendRpcResponse( + { + err: 'no wallet', + }, + tabId, + message.uid, + ); + return; + } + } } const result = await handler.handle({ diff --git a/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/connector.js b/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/connector.js index 6cfcf85512..3d9f8c3a21 100644 --- a/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/connector.js +++ b/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/connector.js @@ -448,7 +448,6 @@ export const RemoveWalletFromWhiteList: HandlerType< const site = connectedSites[tabId]; if (site.url === request.url) { sendToInjector(Number(tabId), { type: 'disconnect' }); - break; } } }, diff --git a/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/index.js b/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/index.js index f935d3711a..69a96dc247 100644 --- a/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/index.js +++ b/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/index.js @@ -43,6 +43,7 @@ import { } from './connector'; import { GetProtocolParameters } from './protocolParameters'; import { subscribe } from '../../subscriptionManager'; +import { notifyAllTabsActiveWalletOpen } from './utils'; const handlerMap = Object.freeze({ [GetHistoricalCoinPrices.typeTag]: GetHistoricalCoinPrices.handle, @@ -98,6 +99,10 @@ export function getHandler(typeTag: string): ?Handler { if (typeTag === 'subscribe') { return async (request, sender, sendResponse) => { subscribe(sender.tab.id, request.request.activeWalletId); + if (request.request.changed) { + // notify content scripts in all tabs + notifyAllTabsActiveWalletOpen(request.request.activeWalletId); + } sendResponse(undefined); }; } diff --git a/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/utils.js b/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/utils.js index bd914dbfff..82b7ba02c6 100644 --- a/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/utils.js +++ b/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/utils.js @@ -12,3 +12,18 @@ export async function getPublicDeriverById(publicDeriverId: number): Promise { + for (const tab of tabs) { + chrome.tabs.sendMessage( + tab.id, + { + type: 'active-wallet-open', + activeWalletId, + } + ); + } + }); +} diff --git a/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/wallet.js b/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/wallet.js index 71724c3768..8f14fcb0a3 100644 --- a/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/wallet.js +++ b/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/wallet.js @@ -13,7 +13,7 @@ import { getCardanoStateFetcher } from '../../utils'; import LocalStorageApi, { loadSubmittedTransactions, persistSubmittedTransactions } from '../../../../../app/api/localStorage'; -import { getPublicDeriverById } from './utils'; +import { getPublicDeriverById, notifyAllTabsActiveWalletOpen } from './utils'; import { removePublicDeriver } from '../../../../../app/api/ada/lib/storage/bridge/walletBuilder/remove'; import { loadWalletsFromStorage } from '../../../../../app/api/ada/lib/storage/models/load'; import { @@ -57,15 +57,18 @@ export const CreateWallet: HandlerType { + notifyAllTabsActiveWalletOpen(publicDeriverId); + }); return await getPlaceHolderWalletState(publicDerivers[0]); }, }); @@ -103,15 +106,18 @@ export const CreateHardwareWallet: HandlerType< checkAddressesInUse: stateFetcher.checkAddressesInUse, addressing: request.addressing, }); + const publicDeriverId = publicDeriver.getPublicDeriverId(); emitUpdateToSubscriptions({ type: 'wallet-state-update', params: { eventType: 'new', - publicDeriverId: publicDeriver.getPublicDeriverId(), + publicDeriverId, } }); - syncWallet(publicDeriver, 'new wallet', 1); + syncWallet(publicDeriver, 'new wallet', 1).then(() => { + notifyAllTabsActiveWalletOpen(publicDeriverId); + });; return await getPlaceHolderWalletState(publicDeriver); }, diff --git a/packages/yoroi-extension/chrome/manifest-mv2.template.js b/packages/yoroi-extension/chrome/manifest-mv2.template.js index 0790a7ed93..277201c79e 100644 --- a/packages/yoroi-extension/chrome/manifest-mv2.template.js +++ b/packages/yoroi-extension/chrome/manifest-mv2.template.js @@ -76,6 +76,18 @@ export default ({ matches: ['*://connect.trezor.io/*/popup.html'], js: ['js/trezor-content-script.js'], }, + { + matches: [ + 'file://*/*', + 'http://*/*', + 'https://*/*', + ], + js: [ + 'js/bringInject.js', + ], + run_at: 'document_start', + all_frames: true, + } ], content_security_policy: contentSecurityPolicy, protocol_handlers: !enableProtocolHandlers @@ -87,7 +99,9 @@ export default ({ uriTemplate: 'main_window.html#/send-from-uri?q=%s', }, ], - web_accessible_resources: [], + web_accessible_resources: [ + 'js/bringInject.js', + ], }; if (shouldInjectConnector) { diff --git a/packages/yoroi-extension/chrome/manifest.template.js b/packages/yoroi-extension/chrome/manifest.template.js index c9aff95ea4..88a46ab4bc 100644 --- a/packages/yoroi-extension/chrome/manifest.template.js +++ b/packages/yoroi-extension/chrome/manifest.template.js @@ -78,6 +78,18 @@ export default ({ matches: ['*://connect.trezor.io/*/popup.html'], js: ['js/trezor-content-script.js'], }, + { + matches: [ + 'file://*/*', + 'http://*/*', + 'https://*/*', + ], + js: [ + 'js/bringInject.js', + ], + run_at: 'document_start', + all_frames: true, + } ], content_security_policy: { extension_pages: contentSecurityPolicy diff --git a/packages/yoroi-extension/package-lock.json b/packages/yoroi-extension/package-lock.json index fea3b28558..44e0d5f621 100644 --- a/packages/yoroi-extension/package-lock.json +++ b/packages/yoroi-extension/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "@amplitude/analytics-browser": "^2.1.3", "@babel/preset-typescript": "^7.24.7", + "@bringweb3/chrome-extension-kit": "^1.0.12", "@cardano-foundation/ledgerjs-hw-app-cardano": "7.1.3", "@emotion/react": "^11.4.1", "@emotion/styled": "^11.3.0", @@ -2136,6 +2137,11 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "node_modules/@bringweb3/chrome-extension-kit": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@bringweb3/chrome-extension-kit/-/chrome-extension-kit-1.0.12.tgz", + "integrity": "sha512-Q+p5Q8fqB4YD0vXZPlo773zvrij0BRtmpkMGZiefjyOq5mqfJcdYGrFg0hJGFwVLH8QYVlaI/wBVvSOdpNxxow==" + }, "node_modules/@cardano-foundation/ledgerjs-hw-app-cardano": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@cardano-foundation/ledgerjs-hw-app-cardano/-/ledgerjs-hw-app-cardano-7.1.3.tgz", diff --git a/packages/yoroi-extension/package.json b/packages/yoroi-extension/package.json index 18219ed01e..c9a26cf2be 100644 --- a/packages/yoroi-extension/package.json +++ b/packages/yoroi-extension/package.json @@ -6,8 +6,9 @@ "dev-mv2": "rimraf dev/ && NODE_OPTIONS=--openssl-legacy-provider babel-node scripts-mv2/build --type=debug --env 'mainnet'", "dev:main": "NODE_OPTIONS=--openssl-legacy-provider babel-node scripts/dev main --env mainnet", "dev:background": "NODE_OPTIONS=--openssl-legacy-provider babel-node scripts/dev background --env mainnet", - "dev:stable": "rimraf dev/ && concurrently -c auto -n extension,background \"npm run dev:main\" \"npm run dev:background\"", - "dev:nightly": "rimraf dev/ && concurrently -n extension,background \"npm run dev:main --nightly\" \"npm run dev:background --nightly\" ", + "dev:bring": "NODE_OPTIONS=--openssl-legacy-provider babel-node scripts/dev bring --env mainnet", + "dev:stable": "rimraf dev/ && concurrently -c auto -n extension,background,bring \"npm run dev:main\" \"npm run dev:background\" \"npm run dev:bring\"", + "dev:nightly": "rimraf dev/ && concurrently -c auto -n extension,background,bring \"npm run dev:main --nightly\" \"npm run dev:background --nightly\" \"npm run dev:bring --nightly \"", "prod:build-mv2": "rimraf build/ && NODE_OPTIONS=--openssl-legacy-provider NODE_ENV=production babel-node scripts-mv2/build --type=prod", "prod:build": "rimraf build/ && NODE_OPTIONS=--openssl-legacy-provider NODE_ENV=production babel-node scripts/build", "prod:build:light": "rimraf build/ && NODE_OPTIONS=--openssl-legacy-provider NODE_ENV=production babel-node scripts/build --dontInjectConnector", @@ -149,6 +150,7 @@ "dependencies": { "@amplitude/analytics-browser": "^2.1.3", "@babel/preset-typescript": "^7.24.7", + "@bringweb3/chrome-extension-kit": "^1.0.12", "@cardano-foundation/ledgerjs-hw-app-cardano": "7.1.3", "@emotion/react": "^11.4.1", "@emotion/styled": "^11.3.0", diff --git a/packages/yoroi-extension/scripts-mv2/build.js b/packages/yoroi-extension/scripts-mv2/build.js index bffd6a7928..03b3bdb85f 100644 --- a/packages/yoroi-extension/scripts-mv2/build.js +++ b/packages/yoroi-extension/scripts-mv2/build.js @@ -92,6 +92,16 @@ export function buildDev(env: string) { webpackHotMiddleware, serverOpts ); + + const Webpack = require('webpack'); + const WebpackDevServer = require('webpack-dev-server'); + const webpackConfig = config.contentScriptConfig( + argv.env, + isNightly, + !shouldInjectConnector + ); + const server = new WebpackDevServer(webpackConfig.devServer, Webpack(webpackConfig)); + server.start(); } if (argv.type === 'debug') { diff --git a/packages/yoroi-extension/scripts/dev.js b/packages/yoroi-extension/scripts/dev.js index 213d8a674c..12117eb0ef 100644 --- a/packages/yoroi-extension/scripts/dev.js +++ b/packages/yoroi-extension/scripts/dev.js @@ -4,7 +4,11 @@ const webpack = require('webpack'); const WebpackDevServer = require('webpack-dev-server'); const tasks = require('./tasks'); -const { baseDevConfig, backgroundServiceWorkerConfig } = require(`../webpack/devConfig`); +const { + baseDevConfig, + backgroundServiceWorkerConfig, + bringContentScriptConfig, +} = require(`../webpack/devConfig`); const { argv, shouldInjectConnector, isNightly, buildAndCopyInjector } = require('./utils'); // override NODE_ENV for ConfigWebpackPlugin @@ -51,10 +55,25 @@ function devBackgroundServiceWorker() { server.start(); } +function devBringContentScript() { + const config = bringContentScriptConfig( + argv.env, + isNightly, + !shouldInjectConnector + ); + + const compiler = webpack(config); + + const server = new WebpackDevServer(config.devServer, compiler); + server.start(); +} + if (argv._[0] === 'main') { devMainWindow(argv.env); } else if (argv._[0] === 'background') { devBackgroundServiceWorker(); +} else if (argv._[0] === 'bring') { + devBringContentScript(); } else { console.error('unknown component'); process.exit(1); diff --git a/packages/yoroi-extension/webpack-mv2/devConfig.js b/packages/yoroi-extension/webpack-mv2/devConfig.js index 90a83e5e32..8078c99a1c 100644 --- a/packages/yoroi-extension/webpack-mv2/devConfig.js +++ b/packages/yoroi-extension/webpack-mv2/devConfig.js @@ -108,4 +108,58 @@ const baseDevConfig = ( } }); -module.exports = { baseDevConfig }; +const contentScriptConfig = ( + networkName /*: string */, + isNightly /*: boolean */, + isLight /* : ?boolean */ = false +) /*: * */ => ({ + mode: 'development', + resolve: commonConfig.resolve(), + devtool: 'source-map', + entry: { + contentScript: [ + path.join(__dirname, '../chrome/content-scripts/bringInject.js'), + ] + }, + devServer: { + devMiddleware: { + writeToDisk: true, + }, + hot: false, + liveReload: false, + // HTTP is not actually used because injected code must always be written to `dev` dir + port: 3001, + }, + output: { + path: path.join(__dirname, '../dev/js'), + filename: 'bringInject.js', + }, + + plugins: [ + new webpack.optimize.LimitChunkCountPlugin({ + maxChunks: 1 + }), + new webpack.DefinePlugin(commonConfig.definePlugin( + networkName, + false, + isNightly, + Boolean(isLight), + )), + new webpack.IgnorePlugin(/[^/]+\/[\S]+.dev$/), + ], + module: { + rules: [ + ...commonConfig.rules(false), + { + test: /\.js$/, + loader: 'babel-loader', + exclude: /node_modules/, + options: { + presets: [] + } + }, + ] + }, +}); + +module.exports = { baseDevConfig, contentScriptConfig }; diff --git a/packages/yoroi-extension/webpack-mv2/prodConfig.js b/packages/yoroi-extension/webpack-mv2/prodConfig.js index cdbc02d9e0..161757f942 100644 --- a/packages/yoroi-extension/webpack-mv2/prodConfig.js +++ b/packages/yoroi-extension/webpack-mv2/prodConfig.js @@ -17,6 +17,49 @@ type EnvParams = {| isLight: "true" | "false" |}; */ +const contentScriptConfig = (env /*: EnvParams */) /*: * */ => ({ + mode: 'production', + optimization: commonConfig.optimization, + experiments: commonConfig.experiments, + resolve: commonConfig.resolve(), + entry: { + contentScript: [ + path.join(__dirname, '../chrome/content-scripts/bringInject.js'), + ] + }, + output: { + path: path.join(__dirname, '../build/js'), + filename: 'bringInject.js', + }, + + plugins: [ + ...commonConfig.plugins('build', env.networkName), + new webpack.optimize.LimitChunkCountPlugin({ + maxChunks: 1 + }), + new webpack.DefinePlugin(commonConfig.definePlugin( + env.networkName, + true, + JSON.parse(env.nightly), + JSON.parse(env.isLight) + )), + new webpack.IgnorePlugin(/[^/]+\/[\S]+.dev$/), + ], + module: { + rules: [ + ...commonConfig.rules(false), + { + test: /\.js$/, + loader: 'babel-loader', + exclude: /node_modules/, + options: { + presets: [] + } + }, + ] + }, +}); + const baseProdConfig = (env /*: EnvParams */) /*: * */ => ({ mode: 'production', optimization: commonConfig.optimization, @@ -86,4 +129,4 @@ const baseProdConfig = (env /*: EnvParams */) /*: * */ => ({ }); // export a callable function so we can swap out the network to use -module.exports = baseProdConfig; +module.exports = [ contentScriptConfig, baseProdConfig ]; diff --git a/packages/yoroi-extension/webpack/devConfig.js b/packages/yoroi-extension/webpack/devConfig.js index 76450f93ce..67e3bda8ce 100644 --- a/packages/yoroi-extension/webpack/devConfig.js +++ b/packages/yoroi-extension/webpack/devConfig.js @@ -170,4 +170,58 @@ const backgroundServiceWorkerConfig = ( } }); -module.exports = { baseDevConfig, backgroundServiceWorkerConfig }; +const bringContentScriptConfig = ( + networkName /*: string */, + isNightly /*: boolean */, + isLight /* : ?boolean */ = false +) /*: * */ => ({ + mode: 'development', + resolve: commonConfig.resolve(), + devtool: 'source-map', + entry: { + contentScript: [ + path.join(__dirname, '../chrome/content-scripts/bringInject.js'), + ] + }, + devServer: { + devMiddleware: { + writeToDisk: true, + }, + hot: false, + liveReload: false, + // HTTP is not actually used because injected code must always be written to `dev` dir + port: 8003, + }, + output: { + path: path.join(__dirname, '../dev/js'), + filename: 'bringInject.js', + }, + + plugins: [ + new webpack.optimize.LimitChunkCountPlugin({ + maxChunks: 1 + }), + new webpack.DefinePlugin(commonConfig.definePlugin( + networkName, + false, + isNightly, + Boolean(isLight), + )), + new webpack.IgnorePlugin(/[^/]+\/[\S]+.dev$/), + ], + module: { + rules: [ + ...commonConfig.rules(false), + { + test: /\.js$/, + loader: 'babel-loader', + exclude: /node_modules/, + options: { + presets: [] + } + }, + ] + }, +}); + +module.exports = { baseDevConfig, backgroundServiceWorkerConfig, bringContentScriptConfig }; diff --git a/packages/yoroi-extension/webpack/prodConfig.js b/packages/yoroi-extension/webpack/prodConfig.js index 336efbb255..947692b9f5 100644 --- a/packages/yoroi-extension/webpack/prodConfig.js +++ b/packages/yoroi-extension/webpack/prodConfig.js @@ -143,5 +143,48 @@ const backgroundServiceWorkerConfig = (env /*: EnvParams */) /*: * */ => ({ } }); +const bringContentScriptConfig = (env /*: EnvParams */) /*: * */ => ({ + mode: 'production', + optimization: commonConfig.optimization, + experiments: commonConfig.experiments, + resolve: commonConfig.resolve(), + entry: { + contentScript: [ + path.join(__dirname, '../chrome/content-scripts/bringInject.js'), + ] + }, + output: { + path: path.join(__dirname, '../build/js'), + filename: 'bringInject.js', + }, + + plugins: [ + ...commonConfig.plugins('build', env.networkName), + new webpack.optimize.LimitChunkCountPlugin({ + maxChunks: 1 + }), + new webpack.DefinePlugin(commonConfig.definePlugin( + env.networkName, + true, + JSON.parse(env.nightly), + JSON.parse(env.isLight) + )), + new webpack.IgnorePlugin(/[^/]+\/[\S]+.dev$/), + ], + module: { + rules: [ + ...commonConfig.rules(false), + { + test: /\.js$/, + loader: 'babel-loader', + exclude: /node_modules/, + options: { + presets: [] + } + }, + ] + }, +}); + // export a callable function so we can swap out the network to use -module.exports = [baseProdConfig, backgroundServiceWorkerConfig]; +module.exports = [baseProdConfig, backgroundServiceWorkerConfig, bringContentScriptConfig];