From b957a0c28f69ee22cb32ebfe4c9d52361322d90b Mon Sep 17 00:00:00 2001 From: Andreas Coroiu Date: Thu, 4 Sep 2025 08:21:50 +0200 Subject: [PATCH] [PM-24646] Add licensed browser builds (#16252) * feat: create separate bit licensed browser * feat: refactor webpack config * fix: mv2 build not working * feat: add bit versions of all commands * feat: add bit CI builds * fix: scss missing from build --- .github/workflows/build-browser.yml | 79 +++- apps/browser/package.json | 30 +- apps/browser/src/popup/app.component.html | 20 + apps/browser/src/popup/app.component.ts | 23 +- apps/browser/src/popup/main.ts | 7 +- apps/browser/src/popup/scss/index.ts | 4 + apps/browser/webpack.base.js | 443 ++++++++++++++++++ apps/browser/webpack.config.js | 421 +---------------- bitwarden_license/bit-browser/jest.config.js | 22 + .../src/background/main.background.ts | 9 + .../bit-browser/src/platform/background.ts | 7 + .../src/popup/app-routing.module.ts | 10 + .../bit-browser/src/popup/app.component.ts | 14 + .../bit-browser/src/popup/app.module.ts | 39 ++ .../bit-browser/src/popup/main.ts | 26 + bitwarden_license/bit-browser/tsconfig.json | 20 + .../bit-browser/tsconfig.spec.json | 8 + .../bit-browser/webpack.config.js | 13 + jest.config.js | 3 +- tsconfig.base.json | 1 + 20 files changed, 738 insertions(+), 461 deletions(-) create mode 100644 apps/browser/src/popup/app.component.html create mode 100644 apps/browser/src/popup/scss/index.ts create mode 100644 apps/browser/webpack.base.js create mode 100644 bitwarden_license/bit-browser/jest.config.js create mode 100644 bitwarden_license/bit-browser/src/background/main.background.ts create mode 100644 bitwarden_license/bit-browser/src/platform/background.ts create mode 100644 bitwarden_license/bit-browser/src/popup/app-routing.module.ts create mode 100644 bitwarden_license/bit-browser/src/popup/app.component.ts create mode 100644 bitwarden_license/bit-browser/src/popup/app.module.ts create mode 100644 bitwarden_license/bit-browser/src/popup/main.ts create mode 100644 bitwarden_license/bit-browser/tsconfig.json create mode 100644 bitwarden_license/bit-browser/tsconfig.spec.json create mode 100644 bitwarden_license/bit-browser/webpack.config.js diff --git a/.github/workflows/build-browser.yml b/.github/workflows/build-browser.yml index 43661d5091..823cb7e25e 100644 --- a/.github/workflows/build-browser.yml +++ b/.github/workflows/build-browser.yml @@ -123,11 +123,20 @@ jobs: build-source: - name: Build browser source + name: Build browser source - ${{matrix.license_type.readable}} runs-on: ubuntu-22.04 needs: - setup - locales-test + strategy: + matrix: + license_type: + - include_bitwarden_license_folder: false + archive_name_prefix: "" + readable: "open source license" + - include_bitwarden_license_folder: true + archive_name_prefix: "bit-" + readable: "commercial license" env: _BUILD_NUMBER: ${{ needs.setup.outputs.adj_build_number }} _NODE_VERSION: ${{ needs.setup.outputs.node_version }} @@ -166,6 +175,12 @@ jobs: mkdir -p browser-source/apps/browser cp -r apps/browser/* browser-source/apps/browser + # Copy bitwarden_license/bit-browser to the Browser source directory + if [[ ${{matrix.license_type.include_bitwarden_license_folder}} == "true" ]]; then + mkdir -p browser-source/bitwarden_license/bit-browser + cp -r bitwarden_license/bit-browser/* browser-source/bitwarden_license/bit-browser + fi + # Copy libs to Browser source directory mkdir browser-source/libs cp -r libs/* browser-source/libs @@ -175,13 +190,13 @@ jobs: - name: Upload browser source uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: - name: browser-source-${{ env._BUILD_NUMBER }}.zip + name: ${{matrix.license_type.archive_name_prefix}}browser-source-${{ env._BUILD_NUMBER }}.zip path: browser-source.zip if-no-files-found: error build: - name: Build + name: Build ${{ matrix.browser.name }} - ${{ matrix.license_type.readable }} runs-on: ubuntu-22.04 needs: - setup @@ -192,25 +207,38 @@ jobs: _NODE_VERSION: ${{ needs.setup.outputs.node_version }} strategy: matrix: - include: + license_type: + - build_prefix: "" + artifact_prefix: "" + source_archive_name_prefix: "" + archive_name_prefix: "" + npm_command_prefix: "dist:" + readable: "open source license" + - build_prefix: "bit-" + artifact_prefix: "bit-" + source_archive_name_prefix: "bit-" + archive_name_prefix: "bit-" + npm_command_prefix: "dist:bit:" + readable: "commercial license" + browser: - name: "chrome" - npm_command: "dist:chrome" + npm_command_suffix: "chrome" archive_name: "dist-chrome.zip" artifact_name: "dist-chrome-MV3" - name: "edge" - npm_command: "dist:edge" + npm_command_suffix: "edge" archive_name: "dist-edge.zip" artifact_name: "dist-edge-MV3" - name: "firefox" - npm_command: "dist:firefox" + npm_command_suffix: "firefox" archive_name: "dist-firefox.zip" artifact_name: "dist-firefox" - name: "firefox-mv3" - npm_command: "dist:firefox:mv3" + npm_command_suffix: "firefox:mv3" archive_name: "dist-firefox.zip" artifact_name: "DO-NOT-USE-FOR-PROD-dist-firefox-MV3" - name: "opera-mv3" - npm_command: "dist:opera:mv3" + npm_command_suffix: "opera:mv3" archive_name: "dist-opera.zip" artifact_name: "dist-opera-MV3" steps: @@ -234,7 +262,7 @@ jobs: - name: Download browser source uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 with: - name: browser-source-${{ env._BUILD_NUMBER }}.zip + name: ${{matrix.license_type.source_archive_name_prefix}}browser-source-${{ env._BUILD_NUMBER }}.zip - name: Unzip browser source artifact run: | @@ -264,7 +292,7 @@ jobs: run: npm link ../sdk-internal - name: Check source file size - if: ${{ startsWith(matrix.name, 'firefox') }} + if: ${{ startsWith(matrix.browser.name, 'firefox') }} run: | # Declare variable as indexed array declare -a FILES @@ -287,19 +315,19 @@ jobs: fi - name: Build extension - run: npm run ${{ matrix.npm_command }} + run: npm run ${{matrix.license_type.npm_command_prefix}}${{ matrix.browser.npm_command_suffix }} working-directory: browser-source/apps/browser - name: Upload extension artifact uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: - name: ${{ matrix.artifact_name }}-${{ env._BUILD_NUMBER }}.zip - path: browser-source/apps/browser/dist/${{ matrix.archive_name }} + name: ${{ matrix.license_type.artifact_prefix }}${{ matrix.browser.artifact_name }}-${{ env._BUILD_NUMBER }}.zip + path: browser-source/apps/browser/dist/${{matrix.license_type.archive_name_prefix}}${{ matrix.browser.archive_name }} if-no-files-found: error build-safari: - name: Build Safari + name: Build Safari - ${{ matrix.license_type.readable }} runs-on: macos-13 permissions: contents: read @@ -308,6 +336,19 @@ jobs: - setup - locales-test if: ${{ needs.setup.outputs.has_secrets == 'true' }} + strategy: + matrix: + license_type: + - build_prefix: "" + artifact_prefix: "" + archive_name_prefix: "" + npm_command_prefix: "dist:" + readable: "open source license" + - build_prefix: "bit-" + artifact_prefix: "bit-" + archive_name_prefix: "bit-" + npm_command_prefix: "dist:bit:" + readable: "commercial license" env: _BUILD_NUMBER: ${{ needs.setup.outputs.adj_build_number }} _NODE_VERSION: ${{ needs.setup.outputs.node_version }} @@ -433,21 +474,21 @@ jobs: npm link ../sdk-internal - name: Build Safari extension - run: npm run dist:safari + run: npm run ${{matrix.license_type.npm_command_prefix}}safari working-directory: apps/browser - name: Zip Safari build artifact run: | cd apps/browser/dist - zip dist-safari.zip ./Safari/**/build/Release/safari.appex -r + zip ${{matrix.license_type.archive_name_prefix }}dist-safari.zip ./Safari/**/build/Release/safari.appex -r pwd ls -la - name: Upload Safari artifact uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: - name: dist-safari-${{ env._BUILD_NUMBER }}.zip - path: apps/browser/dist/dist-safari.zip + name: ${{matrix.license_type.archive_name_prefix}}dist-safari-${{ env._BUILD_NUMBER }}.zip + path: apps/browser/dist/${{matrix.license_type.archive_name_prefix}}dist-safari.zip if-no-files-found: error crowdin-push: diff --git a/apps/browser/package.json b/apps/browser/package.json index 3cfc437722..bfa152f236 100644 --- a/apps/browser/package.json +++ b/apps/browser/package.json @@ -3,32 +3,58 @@ "version": "2025.8.2", "scripts": { "build": "npm run build:chrome", + "build:bit": "npm run build:bit:chrome", "build:chrome": "cross-env BROWSER=chrome MANIFEST_VERSION=3 NODE_OPTIONS=\"--max-old-space-size=8192\" webpack", + "build:bit:chrome": "cross-env BROWSER=chrome MANIFEST_VERSION=3 NODE_OPTIONS=\"--max-old-space-size=8192\" webpack -c ../../bitwarden_license/bit-browser/webpack.config.js", "build:edge": "cross-env BROWSER=edge MANIFEST_VERSION=3 NODE_OPTIONS=\"--max-old-space-size=8192\" webpack", + "build:bit:edge": "cross-env BROWSER=edge MANIFEST_VERSION=3 NODE_OPTIONS=\"--max-old-space-size=8192\" webpack -c ../../bitwarden_license/bit-browser/webpack.config.js", "build:firefox": "cross-env BROWSER=firefox NODE_OPTIONS=\"--max-old-space-size=8192\" webpack", + "build:bit:firefox": "cross-env BROWSER=firefox NODE_OPTIONS=\"--max-old-space-size=8192\" webpack -c ../../bitwarden_license/bit-browser/webpack.config.js", "build:opera": "cross-env BROWSER=opera MANIFEST_VERSION=3 NODE_OPTIONS=\"--max-old-space-size=8192\" webpack", + "build:bit:opera": "cross-env BROWSER=opera MANIFEST_VERSION=3 NODE_OPTIONS=\"--max-old-space-size=8192\" webpack -c ../../bitwarden_license/bit-browser/webpack.config.js", "build:safari": "cross-env BROWSER=safari NODE_OPTIONS=\"--max-old-space-size=8192\" webpack", + "build:bit:safari": "cross-env BROWSER=safari NODE_OPTIONS=\"--max-old-space-size=8192\" webpack -c ../../bitwarden_license/bit-browser/webpack.config.js", "build:watch": "npm run build:watch:chrome", "build:watch:chrome": "npm run build:chrome -- --watch", + "build:bit:watch:chrome": "npm run build:bit:chrome -- --watch", "build:watch:edge": "npm run build:edge -- --watch", + "build:bit:watch:edge": "npm run build:bit:edge -- --watch", "build:watch:firefox": "npm run build:firefox -- --watch", + "build:bit:watch:firefox": "npm run build:bit:firefox -- --watch", "build:watch:opera": "npm run build:opera -- --watch", + "build:bit:watch:opera": "npm run build:bit:opera -- --watch", "build:watch:safari": "npm run build:safari -- --watch", - "build:watch:firefox:mv3": "cross-env MANIFEST_VERSION=3 npm run build:firefox -- --watch", - "build:watch:safari:mv3": "cross-env MANIFEST_VERSION=3 npm run build:safari -- --watch", + "build:bit:watch:safari": "npm run build:bit:safari -- --watch", + "build:watch:firefox:mv3": "cross-env MANIFEST_VERSION=3 npm run build:watch:firefox", + "build:bit:watch:firefox:mv3": "cross-env MANIFEST_VERSION=3 npm run build:bit:watch:firefox", + "build:watch:safari:mv3": "cross-env MANIFEST_VERSION=3 npm run build:watch:safari", + "build:bit:watch:safari:mv3": "cross-env MANIFEST_VERSION=3 npm run build:bit:watch:safari", "build:prod:chrome": "cross-env NODE_ENV=production npm run build:chrome", + "build:bit:prod:chrome": "cross-env NODE_ENV=production npm run build:bit:chrome", "build:prod:edge": "cross-env NODE_ENV=production npm run build:edge", + "build:bit:prod:edge": "cross-env NODE_ENV=production npm run build:bit:edge", "build:prod:firefox": "cross-env NODE_ENV=production npm run build:firefox", + "build:bit:prod:firefox": "cross-env NODE_ENV=production npm run build:bit:firefox", "build:prod:opera": "cross-env NODE_ENV=production npm run build:opera", + "build:bit:prod:opera": "cross-env NODE_ENV=production npm run build:bit:opera", "build:prod:safari": "cross-env NODE_ENV=production npm run build:safari", + "build:bit:prod:safari": "cross-env NODE_ENV=production npm run build:bit:safari", "dist:chrome": "npm run build:prod:chrome && mkdir -p dist && ./scripts/compress.sh dist-chrome.zip", + "dist:bit:chrome": "npm run build:bit:prod:chrome && mkdir -p dist && ./scripts/compress.sh bit-dist-chrome.zip", "dist:edge": "npm run build:prod:edge && mkdir -p dist && ./scripts/compress.sh dist-edge.zip", + "dist:bit:edge": "npm run build:bit:prod:edge && mkdir -p dist && ./scripts/compress.sh bit-dist-edge.zip", "dist:firefox": "npm run build:prod:firefox && mkdir -p dist && ./scripts/compress.sh dist-firefox.zip", + "dist:bit:firefox": "npm run build:bit:prod:firefox && mkdir -p dist && ./scripts/compress.sh bit-dist-firefox.zip", "dist:opera": "npm run build:prod:opera && mkdir -p dist && ./scripts/compress.sh dist-opera.zip", + "dist:bit:opera": "npm run build:bit:prod:opera && mkdir -p dist && ./scripts/compress.sh bit-dist-opera.zip", "dist:safari": "npm run build:prod:safari && ./scripts/package-safari.ps1", + "dist:bit:safari": "npm run build:bit:prod:safari && ./scripts/package-safari.ps1", "dist:firefox:mv3": "cross-env MANIFEST_VERSION=3 npm run dist:firefox", + "dist:bit:firefox:mv3": "cross-env MANIFEST_VERSION=3 npm run dist:bit:firefox", "dist:opera:mv3": "cross-env MANIFEST_VERSION=3 npm run dist:opera", + "dist:bit:opera:mv3": "cross-env MANIFEST_VERSION=3 npm run dist:bit:opera", "dist:safari:mv3": "cross-env MANIFEST_VERSION=3 npm run dist:safari", + "dist:bit:safari:mv3": "cross-env MANIFEST_VERSION=3 npm run dist:bit:safari", "test": "jest", "test:watch": "jest --watch", "test:watch:all": "jest --watchAll", diff --git a/apps/browser/src/popup/app.component.html b/apps/browser/src/popup/app.component.html new file mode 100644 index 0000000000..3d81354ca3 --- /dev/null +++ b/apps/browser/src/popup/app.component.html @@ -0,0 +1,20 @@ +@if (showSdkWarning | async) { +
+ + {{ "wasmNotSupported" | i18n }} + + {{ "learnMore" | i18n }} + + +
+} @else { +
+ +
+ +} diff --git a/apps/browser/src/popup/app.component.ts b/apps/browser/src/popup/app.component.ts index ee75dbaf7a..4f46f889ea 100644 --- a/apps/browser/src/popup/app.component.ts +++ b/apps/browser/src/popup/app.component.ts @@ -57,28 +57,7 @@ import { DesktopSyncVerificationDialogComponent } from "./components/desktop-syn selector: "app-root", styles: [], animations: [routerTransition], - template: ` - @if (showSdkWarning | async) { -
- - {{ "wasmNotSupported" | i18n }} - - {{ "learnMore" | i18n }} - - -
- } @else { -
- -
- - } - `, + templateUrl: "app.component.html", standalone: false, }) export class AppComponent implements OnInit, OnDestroy { diff --git a/apps/browser/src/popup/main.ts b/apps/browser/src/popup/main.ts index bb975f48e5..fa6a07d031 100644 --- a/apps/browser/src/popup/main.ts +++ b/apps/browser/src/popup/main.ts @@ -4,13 +4,10 @@ import { platformBrowserDynamic } from "@angular/platform-browser-dynamic"; import { PopupSizeService } from "../platform/popup/layout/popup-size.service"; import { BrowserPlatformUtilsService } from "../platform/services/platform-utils/browser-platform-utils.service"; -// eslint-disable-next-line @typescript-eslint/no-require-imports -require("./scss/popup.scss"); -// eslint-disable-next-line @typescript-eslint/no-require-imports -require("./scss/tailwind.css"); - import { AppModule } from "./app.module"; +import "./scss"; + // We put these first to minimize the delay in window changing. PopupSizeService.initBodyWidthFromLocalStorage(); // Should be removed once we deprecate support for Safari 16.0 and older. See Jira ticket [PM-1861] diff --git a/apps/browser/src/popup/scss/index.ts b/apps/browser/src/popup/scss/index.ts new file mode 100644 index 0000000000..abb62fa0dd --- /dev/null +++ b/apps/browser/src/popup/scss/index.ts @@ -0,0 +1,4 @@ +// eslint-disable-next-line @typescript-eslint/no-require-imports +require("./popup.scss"); +// eslint-disable-next-line @typescript-eslint/no-require-imports +require("./tailwind.css"); diff --git a/apps/browser/webpack.base.js b/apps/browser/webpack.base.js new file mode 100644 index 0000000000..872da6600b --- /dev/null +++ b/apps/browser/webpack.base.js @@ -0,0 +1,443 @@ +const path = require("path"); +const webpack = require("webpack"); +const HtmlWebpackPlugin = require("html-webpack-plugin"); +const CopyWebpackPlugin = require("copy-webpack-plugin"); +const MiniCssExtractPlugin = require("mini-css-extract-plugin"); +const { AngularWebpackPlugin } = require("@ngtools/webpack"); +const TerserPlugin = require("terser-webpack-plugin"); +const { TsconfigPathsPlugin } = require("tsconfig-paths-webpack-plugin"); +const configurator = require("./config/config"); +const manifest = require("./webpack/manifest"); +const AngularCheckPlugin = require("./webpack/angular-check"); + +module.exports.getEnv = function getEnv() { + const ENV = (process.env.ENV = process.env.NODE_ENV); + const manifestVersion = process.env.MANIFEST_VERSION == 3 ? 3 : 2; + const browser = process.env.BROWSER ?? "chrome"; + + return { ENV, manifestVersion, browser }; +}; + +/** + * @param {{ + * configName: string; + * popup: { + * entry: string; + * entryModule: string; + * }; + * background: { + * entry: string; + * }; + * tsConfig: string; + * additionalEntries?: { [outputPath: string]: string } + * }} params - The input parameters for building the config. + */ +module.exports.buildConfig = function buildConfig(params) { + if (process.env.NODE_ENV == null) { + process.env.NODE_ENV = "development"; + } + + const { ENV, manifestVersion, browser } = module.exports.getEnv(); + + console.log(`Building Manifest Version ${manifestVersion} app - ${params.configName} version`); + + const envConfig = configurator.load(ENV); + configurator.log(envConfig); + + const moduleRules = [ + { + test: /\.(html)$/, + loader: "html-loader", + }, + { + test: /.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/, + exclude: /loading.svg/, + generator: { + filename: "popup/fonts/[name].[contenthash][ext]", + }, + type: "asset/resource", + }, + { + test: /\.(jpe?g|png|gif|svg)$/i, + exclude: /.*(bwi-font|glyphicons-halflings-regular)\.svg/, + generator: { + filename: "popup/images/[name][ext]", + }, + type: "asset/resource", + }, + { + test: /\.css$/, + use: [ + { + loader: MiniCssExtractPlugin.loader, + }, + "css-loader", + "resolve-url-loader", + { + loader: "postcss-loader", + options: { + sourceMap: true, + }, + }, + ], + }, + { + test: /\.scss$/, + use: [ + { + loader: MiniCssExtractPlugin.loader, + }, + "css-loader", + "resolve-url-loader", + { + loader: "sass-loader", + options: { + sourceMap: true, + }, + }, + ], + }, + { + test: /\.[cm]?js$/, + use: [ + { + loader: "babel-loader", + options: { + configFile: "../../babel.config.json", + cacheDirectory: ENV === "development", + compact: ENV !== "development", + }, + }, + ], + }, + { + test: /\.[jt]sx?$/, + loader: "@ngtools/webpack", + }, + ]; + + const requiredPlugins = [ + new webpack.DefinePlugin({ + "process.env": { + ENV: JSON.stringify(ENV), + }, + }), + new webpack.EnvironmentPlugin({ + FLAGS: envConfig.flags, + DEV_FLAGS: ENV === "development" ? envConfig.devFlags : {}, + }), + ]; + + const plugins = [ + new HtmlWebpackPlugin({ + template: "./src/popup/index.ejs", + filename: "popup/index.html", + chunks: ["popup/polyfills", "popup/vendor-angular", "popup/vendor", "popup/main"], + browser: browser, + }), + new HtmlWebpackPlugin({ + template: "./src/autofill/notification/bar.html", + filename: "notification/bar.html", + chunks: ["notification/bar"], + }), + new HtmlWebpackPlugin({ + template: "./src/autofill/overlay/inline-menu/pages/button/button.html", + filename: "overlay/menu-button.html", + chunks: ["overlay/menu-button"], + }), + new HtmlWebpackPlugin({ + template: "./src/autofill/overlay/inline-menu/pages/list/list.html", + filename: "overlay/menu-list.html", + chunks: ["overlay/menu-list"], + }), + new HtmlWebpackPlugin({ + template: "./src/autofill/overlay/inline-menu/pages/menu-container/menu-container.html", + filename: "overlay/menu.html", + chunks: ["overlay/menu"], + }), + new CopyWebpackPlugin({ + patterns: [ + { + from: manifestVersion == 3 ? "./src/manifest.v3.json" : "./src/manifest.json", + to: "manifest.json", + transform: manifest.transform(browser), + }, + { from: "./src/managed_schema.json", to: "managed_schema.json" }, + { from: "./src/_locales", to: "_locales" }, + { from: "./src/images", to: "images" }, + { from: "./src/popup/images", to: "popup/images" }, + { from: "./src/autofill/content/autofill.css", to: "content" }, + ], + }), + new MiniCssExtractPlugin({ + filename: "[name].css", + chunkFilename: "chunk-[id].css", + }), + new AngularWebpackPlugin({ + tsconfig: params.tsConfig, + entryModule: params.popup.entryModule, + sourceMap: true, + }), + new webpack.ProvidePlugin({ + process: "process/browser.js", + }), + new webpack.SourceMapDevToolPlugin({ + exclude: [/content\/.*/, /notification\/.*/, /overlay\/.*/], + filename: "[file].map", + }), + ...requiredPlugins, + ]; + + /** + * @type {import("webpack").Configuration} + * This config compiles everything but the background + */ + const mainConfig = { + name: "main", + mode: ENV, + devtool: false, + entry: { + "popup/polyfills": "./src/popup/polyfills.ts", + "popup/main": params.popup.entry, + "content/trigger-autofill-script-injection": + "./src/autofill/content/trigger-autofill-script-injection.ts", + "content/bootstrap-autofill": "./src/autofill/content/bootstrap-autofill.ts", + "content/bootstrap-autofill-overlay": "./src/autofill/content/bootstrap-autofill-overlay.ts", + "content/bootstrap-autofill-overlay-menu": + "./src/autofill/content/bootstrap-autofill-overlay-menu.ts", + "content/bootstrap-autofill-overlay-notifications": + "./src/autofill/content/bootstrap-autofill-overlay-notifications.ts", + "content/autofiller": "./src/autofill/content/autofiller.ts", + "content/auto-submit-login": "./src/autofill/content/auto-submit-login.ts", + "content/contextMenuHandler": "./src/autofill/content/context-menu-handler.ts", + "content/content-message-handler": "./src/autofill/content/content-message-handler.ts", + "content/fido2-content-script": "./src/autofill/fido2/content/fido2-content-script.ts", + "content/fido2-page-script": "./src/autofill/fido2/content/fido2-page-script.ts", + "content/ipc-content-script": "./src/platform/ipc/content/ipc-content-script.ts", + "notification/bar": "./src/autofill/notification/bar.ts", + "overlay/menu-button": + "./src/autofill/overlay/inline-menu/pages/button/bootstrap-autofill-inline-menu-button.ts", + "overlay/menu-list": + "./src/autofill/overlay/inline-menu/pages/list/bootstrap-autofill-inline-menu-list.ts", + "overlay/menu": + "./src/autofill/overlay/inline-menu/pages/menu-container/bootstrap-autofill-inline-menu-container.ts", + "content/send-on-installed-message": "./src/vault/content/send-on-installed-message.ts", + "content/send-popup-open-message": "./src/vault/content/send-popup-open-message.ts", + ...params.additionalEntries, + }, + cache: + ENV !== "development" + ? false + : { + type: "filesystem", + name: "main-cache", + cacheDirectory: path.resolve( + __dirname, + "../../node_modules/.cache/webpack-browser-main", + ), + buildDependencies: { + config: [__filename], + }, + }, + snapshot: { + unmanagedPaths: [path.resolve(__dirname, "../../node_modules/@bitwarden/")], + }, + optimization: { + minimize: ENV !== "development", + minimizer: [ + new TerserPlugin({ + exclude: [/content\/.*/, /notification\/.*/, /overlay\/.*/], + terserOptions: { + // Replicate Angular CLI behaviour + compress: { + global_defs: { + ngDevMode: false, + ngI18nClosureMode: false, + }, + }, + }, + }), + ], + splitChunks: { + cacheGroups: { + commons: { + test(module, chunks) { + return ( + module.resource != null && + module.resource.includes(`${path.sep}node_modules${path.sep}`) && + !module.resource.includes(`${path.sep}node_modules${path.sep}@angular${path.sep}`) + ); + }, + name: "popup/vendor", + chunks: (chunk) => { + return chunk.name === "popup/main"; + }, + }, + angular: { + test(module, chunks) { + return ( + module.resource != null && + module.resource.includes(`${path.sep}node_modules${path.sep}@angular${path.sep}`) + ); + }, + name: "popup/vendor-angular", + chunks: (chunk) => { + return chunk.name === "popup/main"; + }, + }, + }, + }, + }, + resolve: { + extensions: [".ts", ".js"], + symlinks: false, + modules: [path.resolve("../../node_modules")], + fallback: { + assert: false, + buffer: require.resolve("buffer/"), + util: require.resolve("util/"), + url: require.resolve("url/"), + fs: false, + path: require.resolve("path-browserify"), + }, + cache: true, + }, + output: { + filename: "[name].js", + chunkFilename: "assets/[name].js", + webassemblyModuleFilename: "assets/[modulehash].wasm", + path: path.resolve(__dirname, "build"), + clean: true, + }, + module: { + rules: moduleRules, + }, + experiments: { + asyncWebAssembly: true, + }, + plugins: plugins, + }; + + /** + * @type {import("webpack").Configuration[]} + */ + const configs = []; + + if (manifestVersion == 2) { + mainConfig.optimization.splitChunks.cacheGroups.commons2 = { + test: /[\\/]node_modules[\\/]/, + name: "vendor", + chunks: (chunk) => { + return chunk.name === "background"; + }, + }; + + // Manifest V2 uses Background Pages which requires a html page. + mainConfig.plugins.push( + new HtmlWebpackPlugin({ + template: "./src/platform/background.html", + filename: "background.html", + chunks: ["vendor", "background"], + }), + ); + + // Manifest V2 background pages can be run through the regular build pipeline. + // Since it's a standard webpage. + mainConfig.entry.background = params.background.entry; + mainConfig.entry["content/fido2-page-script-delay-append-mv2"] = + "./src/autofill/fido2/content/fido2-page-script-delay-append.mv2.ts"; + + configs.push(mainConfig); + } else { + // Firefox does not use the offscreen API + if (browser !== "firefox") { + mainConfig.entry["offscreen-document/offscreen-document"] = + "./src/platform/offscreen-document/offscreen-document.ts"; + + mainConfig.plugins.push( + new HtmlWebpackPlugin({ + template: "./src/platform/offscreen-document/index.html", + filename: "offscreen-document/index.html", + chunks: ["offscreen-document/offscreen-document"], + }), + ); + } + + const target = browser === "firefox" ? "web" : "webworker"; + + /** + * @type {import("webpack").Configuration} + */ + const backgroundConfig = { + name: "background", + mode: ENV, + devtool: false, + entry: params.background.entry, + target: target, + output: { + filename: "background.js", + path: path.resolve(__dirname, "build"), + }, + module: { + rules: [ + { + test: /\.tsx?$/, + loader: "ts-loader", + }, + ], + }, + cache: + ENV !== "development" + ? false + : { + type: "filesystem", + name: "background-cache", + cacheDirectory: path.resolve( + __dirname, + "../../node_modules/.cache/webpack-browser-background", + ), + buildDependencies: { + config: [__filename], + }, + }, + snapshot: { + unmanagedPaths: [path.resolve(__dirname, "../../node_modules/@bitwarden/")], + }, + experiments: { + asyncWebAssembly: true, + }, + resolve: { + extensions: [".ts", ".js"], + symlinks: false, + modules: [path.resolve("../../node_modules")], + plugins: [new TsconfigPathsPlugin()], + fallback: { + fs: false, + path: require.resolve("path-browserify"), + }, + cache: true, + }, + dependencies: ["main"], + plugins: [...requiredPlugins, new AngularCheckPlugin()], + }; + + // Safari's desktop build process requires a background.html and vendor.js file to exist + // within the root of the extension. This is a workaround to allow us to build Safari + // for manifest v2 and v3 without modifying the desktop project structure. + if (browser === "safari") { + backgroundConfig.plugins.push( + new CopyWebpackPlugin({ + patterns: [ + { from: "./src/safari/mv3/fake-background.html", to: "background.html" }, + { from: "./src/safari/mv3/fake-vendor.js", to: "vendor.js" }, + ], + }), + ); + } + + configs.push(mainConfig); + configs.push(backgroundConfig); + } + + return configs; +}; diff --git a/apps/browser/webpack.config.js b/apps/browser/webpack.config.js index e62f90354d..9eac990ab6 100644 --- a/apps/browser/webpack.config.js +++ b/apps/browser/webpack.config.js @@ -1,416 +1,13 @@ -const path = require("path"); -const webpack = require("webpack"); -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const CopyWebpackPlugin = require("copy-webpack-plugin"); -const MiniCssExtractPlugin = require("mini-css-extract-plugin"); -const { AngularWebpackPlugin } = require("@ngtools/webpack"); -const TerserPlugin = require("terser-webpack-plugin"); -const { TsconfigPathsPlugin } = require("tsconfig-paths-webpack-plugin"); -const configurator = require("./config/config"); -const manifest = require("./webpack/manifest"); -const AngularCheckPlugin = require("./webpack/angular-check"); +const { buildConfig } = require("./webpack.base"); -if (process.env.NODE_ENV == null) { - process.env.NODE_ENV = "development"; -} -const ENV = (process.env.ENV = process.env.NODE_ENV); -const manifestVersion = process.env.MANIFEST_VERSION == 3 ? 3 : 2; -const browser = process.env.BROWSER ?? "chrome"; - -console.log(`Building Manifest Version ${manifestVersion} app`); - -const envConfig = configurator.load(ENV); -configurator.log(envConfig); - -const moduleRules = [ - { - test: /\.(html)$/, - loader: "html-loader", - }, - { - test: /.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/, - exclude: /loading.svg/, - generator: { - filename: "popup/fonts/[name].[contenthash][ext]", - }, - type: "asset/resource", - }, - { - test: /\.(jpe?g|png|gif|svg)$/i, - exclude: /.*(bwi-font|glyphicons-halflings-regular)\.svg/, - generator: { - filename: "popup/images/[name][ext]", - }, - type: "asset/resource", - }, - { - test: /\.css$/, - use: [ - { - loader: MiniCssExtractPlugin.loader, - }, - "css-loader", - "resolve-url-loader", - { - loader: "postcss-loader", - options: { - sourceMap: true, - }, - }, - ], - }, - { - test: /\.scss$/, - use: [ - { - loader: MiniCssExtractPlugin.loader, - }, - "css-loader", - "resolve-url-loader", - { - loader: "sass-loader", - options: { - sourceMap: true, - }, - }, - ], - }, - { - test: /\.[cm]?js$/, - use: [ - { - loader: "babel-loader", - options: { - configFile: "../../babel.config.json", - cacheDirectory: ENV === "development", - compact: ENV !== "development", - }, - }, - ], - }, - { - test: /\.[jt]sx?$/, - loader: "@ngtools/webpack", - }, -]; - -const requiredPlugins = [ - new webpack.DefinePlugin({ - "process.env": { - ENV: JSON.stringify(ENV), - }, - }), - new webpack.EnvironmentPlugin({ - FLAGS: envConfig.flags, - DEV_FLAGS: ENV === "development" ? envConfig.devFlags : {}, - }), -]; - -const plugins = [ - new HtmlWebpackPlugin({ - template: "./src/popup/index.ejs", - filename: "popup/index.html", - chunks: ["popup/polyfills", "popup/vendor-angular", "popup/vendor", "popup/main"], - browser: browser, - }), - new HtmlWebpackPlugin({ - template: "./src/autofill/notification/bar.html", - filename: "notification/bar.html", - chunks: ["notification/bar"], - }), - new HtmlWebpackPlugin({ - template: "./src/autofill/overlay/inline-menu/pages/button/button.html", - filename: "overlay/menu-button.html", - chunks: ["overlay/menu-button"], - }), - new HtmlWebpackPlugin({ - template: "./src/autofill/overlay/inline-menu/pages/list/list.html", - filename: "overlay/menu-list.html", - chunks: ["overlay/menu-list"], - }), - new HtmlWebpackPlugin({ - template: "./src/autofill/overlay/inline-menu/pages/menu-container/menu-container.html", - filename: "overlay/menu.html", - chunks: ["overlay/menu"], - }), - new CopyWebpackPlugin({ - patterns: [ - { - from: manifestVersion == 3 ? "./src/manifest.v3.json" : "./src/manifest.json", - to: "manifest.json", - transform: manifest.transform(browser), - }, - { from: "./src/managed_schema.json", to: "managed_schema.json" }, - { from: "./src/_locales", to: "_locales" }, - { from: "./src/images", to: "images" }, - { from: "./src/popup/images", to: "popup/images" }, - { from: "./src/autofill/content/autofill.css", to: "content" }, - ], - }), - new MiniCssExtractPlugin({ - filename: "[name].css", - chunkFilename: "chunk-[id].css", - }), - new AngularWebpackPlugin({ - tsConfigPath: "tsconfig.json", +module.exports = buildConfig({ + configName: "OSS", + popup: { + entry: "./src/popup/main.ts", entryModule: "src/popup/app.module#AppModule", - sourceMap: true, - }), - new webpack.ProvidePlugin({ - process: "process/browser.js", - }), - new webpack.SourceMapDevToolPlugin({ - exclude: [/content\/.*/, /notification\/.*/, /overlay\/.*/], - filename: "[file].map", - }), - ...requiredPlugins, -]; - -/** - * @type {import("webpack").Configuration} - * This config compiles everything but the background - */ -const mainConfig = { - name: "main", - mode: ENV, - devtool: false, - entry: { - "popup/polyfills": "./src/popup/polyfills.ts", - "popup/main": "./src/popup/main.ts", - "content/trigger-autofill-script-injection": - "./src/autofill/content/trigger-autofill-script-injection.ts", - "content/bootstrap-autofill": "./src/autofill/content/bootstrap-autofill.ts", - "content/bootstrap-autofill-overlay": "./src/autofill/content/bootstrap-autofill-overlay.ts", - "content/bootstrap-autofill-overlay-menu": - "./src/autofill/content/bootstrap-autofill-overlay-menu.ts", - "content/bootstrap-autofill-overlay-notifications": - "./src/autofill/content/bootstrap-autofill-overlay-notifications.ts", - "content/autofiller": "./src/autofill/content/autofiller.ts", - "content/auto-submit-login": "./src/autofill/content/auto-submit-login.ts", - "content/contextMenuHandler": "./src/autofill/content/context-menu-handler.ts", - "content/content-message-handler": "./src/autofill/content/content-message-handler.ts", - "content/fido2-content-script": "./src/autofill/fido2/content/fido2-content-script.ts", - "content/fido2-page-script": "./src/autofill/fido2/content/fido2-page-script.ts", - "content/ipc-content-script": "./src/platform/ipc/content/ipc-content-script.ts", - "notification/bar": "./src/autofill/notification/bar.ts", - "overlay/menu-button": - "./src/autofill/overlay/inline-menu/pages/button/bootstrap-autofill-inline-menu-button.ts", - "overlay/menu-list": - "./src/autofill/overlay/inline-menu/pages/list/bootstrap-autofill-inline-menu-list.ts", - "overlay/menu": - "./src/autofill/overlay/inline-menu/pages/menu-container/bootstrap-autofill-inline-menu-container.ts", - "content/send-on-installed-message": "./src/vault/content/send-on-installed-message.ts", - "content/send-popup-open-message": "./src/vault/content/send-popup-open-message.ts", }, - cache: - ENV !== "development" - ? false - : { - type: "filesystem", - name: "main-cache", - cacheDirectory: path.resolve(__dirname, "../../node_modules/.cache/webpack-browser-main"), - buildDependencies: { - config: [__filename], - }, - }, - snapshot: { - unmanagedPaths: [path.resolve(__dirname, "../../node_modules/@bitwarden/")], - }, - optimization: { - minimize: ENV !== "development", - minimizer: [ - new TerserPlugin({ - exclude: [/content\/.*/, /notification\/.*/, /overlay\/.*/], - terserOptions: { - // Replicate Angular CLI behaviour - compress: { - global_defs: { - ngDevMode: false, - ngI18nClosureMode: false, - }, - }, - }, - }), - ], - splitChunks: { - cacheGroups: { - commons: { - test(module, chunks) { - return ( - module.resource != null && - module.resource.includes(`${path.sep}node_modules${path.sep}`) && - !module.resource.includes(`${path.sep}node_modules${path.sep}@angular${path.sep}`) - ); - }, - name: "popup/vendor", - chunks: (chunk) => { - return chunk.name === "popup/main"; - }, - }, - angular: { - test(module, chunks) { - return ( - module.resource != null && - module.resource.includes(`${path.sep}node_modules${path.sep}@angular${path.sep}`) - ); - }, - name: "popup/vendor-angular", - chunks: (chunk) => { - return chunk.name === "popup/main"; - }, - }, - }, - }, - }, - resolve: { - extensions: [".ts", ".js"], - symlinks: false, - modules: [path.resolve("../../node_modules")], - fallback: { - assert: false, - buffer: require.resolve("buffer/"), - util: require.resolve("util/"), - url: require.resolve("url/"), - fs: false, - path: require.resolve("path-browserify"), - }, - cache: true, - }, - output: { - filename: "[name].js", - chunkFilename: "assets/[name].js", - webassemblyModuleFilename: "assets/[modulehash].wasm", - path: path.resolve(__dirname, "build"), - clean: true, - }, - module: { - rules: moduleRules, - }, - experiments: { - asyncWebAssembly: true, - }, - plugins: plugins, -}; - -/** - * @type {import("webpack").Configuration[]} - */ -const configs = []; - -if (manifestVersion == 2) { - mainConfig.optimization.splitChunks.cacheGroups.commons2 = { - test: /[\\/]node_modules[\\/]/, - name: "vendor", - chunks: (chunk) => { - return chunk.name === "background"; - }, - }; - - // Manifest V2 uses Background Pages which requires a html page. - mainConfig.plugins.push( - new HtmlWebpackPlugin({ - template: "./src/platform/background.html", - filename: "background.html", - chunks: ["vendor", "background"], - }), - ); - - // Manifest V2 background pages can be run through the regular build pipeline. - // Since it's a standard webpage. - mainConfig.entry.background = "./src/platform/background.ts"; - mainConfig.entry["content/fido2-page-script-delay-append-mv2"] = - "./src/autofill/fido2/content/fido2-page-script-delay-append.mv2.ts"; - - configs.push(mainConfig); -} else { - // Firefox does not use the offscreen API - if (browser !== "firefox") { - mainConfig.entry["offscreen-document/offscreen-document"] = - "./src/platform/offscreen-document/offscreen-document.ts"; - - mainConfig.plugins.push( - new HtmlWebpackPlugin({ - template: "./src/platform/offscreen-document/index.html", - filename: "offscreen-document/index.html", - chunks: ["offscreen-document/offscreen-document"], - }), - ); - } - - const target = browser === "firefox" ? "web" : "webworker"; - - /** - * @type {import("webpack").Configuration} - */ - const backgroundConfig = { - name: "background", - mode: ENV, - devtool: false, + background: { entry: "./src/platform/background.ts", - target: target, - output: { - filename: "background.js", - path: path.resolve(__dirname, "build"), - }, - module: { - rules: [ - { - test: /\.tsx?$/, - loader: "ts-loader", - }, - ], - }, - cache: - ENV !== "development" - ? false - : { - type: "filesystem", - name: "background-cache", - cacheDirectory: path.resolve( - __dirname, - "../../node_modules/.cache/webpack-browser-background", - ), - buildDependencies: { - config: [__filename], - }, - }, - snapshot: { - unmanagedPaths: [path.resolve(__dirname, "../../node_modules/@bitwarden/")], - }, - experiments: { - asyncWebAssembly: true, - }, - resolve: { - extensions: [".ts", ".js"], - symlinks: false, - modules: [path.resolve("../../node_modules")], - plugins: [new TsconfigPathsPlugin()], - fallback: { - fs: false, - path: require.resolve("path-browserify"), - }, - cache: true, - }, - dependencies: ["main"], - plugins: [...requiredPlugins, new AngularCheckPlugin()], - }; - - // Safari's desktop build process requires a background.html and vendor.js file to exist - // within the root of the extension. This is a workaround to allow us to build Safari - // for manifest v2 and v3 without modifying the desktop project structure. - if (browser === "safari") { - backgroundConfig.plugins.push( - new CopyWebpackPlugin({ - patterns: [ - { from: "./src/safari/mv3/fake-background.html", to: "background.html" }, - { from: "./src/safari/mv3/fake-vendor.js", to: "vendor.js" }, - ], - }), - ); - } - - configs.push(mainConfig); - configs.push(backgroundConfig); -} - -module.exports = configs; + }, + tsConfig: "tsconfig.json", +}); diff --git a/bitwarden_license/bit-browser/jest.config.js b/bitwarden_license/bit-browser/jest.config.js new file mode 100644 index 0000000000..5451c15e47 --- /dev/null +++ b/bitwarden_license/bit-browser/jest.config.js @@ -0,0 +1,22 @@ +const { pathsToModuleNameMapper } = require("ts-jest"); + +const { compilerOptions } = require("../../tsconfig.base"); + +const sharedConfig = require("../../libs/shared/jest.config.angular"); + +/** @type {import('jest').Config} */ +module.exports = { + ...sharedConfig, + setupFilesAfterEnv: ["../../apps/browser/test.setup.ts"], + moduleNameMapper: pathsToModuleNameMapper( + { + "@bitwarden/common/spec": ["libs/common/spec"], + "@bitwarden/common": ["libs/common/src/*"], + "@bitwarden/admin-console/common": ["libs/admin-console/src/common"], + ...(compilerOptions?.paths ?? {}), + }, + { + prefix: "/../../", + }, + ), +}; diff --git a/bitwarden_license/bit-browser/src/background/main.background.ts b/bitwarden_license/bit-browser/src/background/main.background.ts new file mode 100644 index 0000000000..48efc8099e --- /dev/null +++ b/bitwarden_license/bit-browser/src/background/main.background.ts @@ -0,0 +1,9 @@ +import OssMainBackground from "@bitwarden/browser/background/main.background"; + +export default class MainBackground { + private ossMain = new OssMainBackground(); + + async bootstrap() { + await this.ossMain.bootstrap(); + } +} diff --git a/bitwarden_license/bit-browser/src/platform/background.ts b/bitwarden_license/bit-browser/src/platform/background.ts new file mode 100644 index 0000000000..0cd9b3285e --- /dev/null +++ b/bitwarden_license/bit-browser/src/platform/background.ts @@ -0,0 +1,7 @@ +import { ConsoleLogService } from "@bitwarden/common/platform/services/console-log.service"; + +import MainBackground from "../background/main.background"; + +const logService = new ConsoleLogService(false); +const bitwardenMain = ((self as any).bitwardenMain = new MainBackground()); +bitwardenMain.bootstrap().catch((error) => logService.error(error)); diff --git a/bitwarden_license/bit-browser/src/popup/app-routing.module.ts b/bitwarden_license/bit-browser/src/popup/app-routing.module.ts new file mode 100644 index 0000000000..7cabfb68e8 --- /dev/null +++ b/bitwarden_license/bit-browser/src/popup/app-routing.module.ts @@ -0,0 +1,10 @@ +import { NgModule } from "@angular/core"; +import { RouterModule, Routes } from "@angular/router"; + +const routes: Routes = []; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], +}) +export class AppRoutingModule {} diff --git a/bitwarden_license/bit-browser/src/popup/app.component.ts b/bitwarden_license/bit-browser/src/popup/app.component.ts new file mode 100644 index 0000000000..339681d66d --- /dev/null +++ b/bitwarden_license/bit-browser/src/popup/app.component.ts @@ -0,0 +1,14 @@ +import { Component, OnInit } from "@angular/core"; + +import { AppComponent as BaseAppComponent } from "@bitwarden/browser/popup/app.component"; + +@Component({ + selector: "app-root", + templateUrl: "../../../../apps/browser/src/popup/app.component.html", + standalone: false, +}) +export class AppComponent extends BaseAppComponent implements OnInit { + ngOnInit() { + return super.ngOnInit(); + } +} diff --git a/bitwarden_license/bit-browser/src/popup/app.module.ts b/bitwarden_license/bit-browser/src/popup/app.module.ts new file mode 100644 index 0000000000..589d779472 --- /dev/null +++ b/bitwarden_license/bit-browser/src/popup/app.module.ts @@ -0,0 +1,39 @@ +import { OverlayModule } from "@angular/cdk/overlay"; +import { CommonModule } from "@angular/common"; +import { NgModule } from "@angular/core"; +import { RouterModule } from "@angular/router"; + +import { JslibModule } from "@bitwarden/angular/jslib.module"; +// import { AppRoutingAnimationsModule } from "@bitwarden/browser/popup/app-routing-animations"; +import { AppRoutingModule as OssRoutingModule } from "@bitwarden/browser/popup/app-routing.module"; +import { AppModule as OssModule } from "@bitwarden/browser/popup/app.module"; +// import { WildcardRoutingModule } from "@bitwarden/browser/popup/wildcard-routing.module"; + +import { AppRoutingModule } from "./app-routing.module"; +import { AppComponent } from "./app.component"; +/** + * This is the AppModule for the commercial version of Bitwarden. + * `apps/browser/app.module.ts` contains the OSS version. + * + * You probably do not want to modify this file. Consider editing `oss.module.ts` instead. + */ +@NgModule({ + imports: [ + CommonModule, + OverlayModule, + OssModule, + JslibModule, + // BrowserAnimationsModule, + // FormsModule, + // ReactiveFormsModule, + // CoreModule, + // DragDropModule, + AppRoutingModule, + OssRoutingModule, + RouterModule, + // WildcardRoutingModule, // Needs to be last to catch all non-existing routes + ], + declarations: [AppComponent], + bootstrap: [AppComponent], +}) +export class AppModule {} diff --git a/bitwarden_license/bit-browser/src/popup/main.ts b/bitwarden_license/bit-browser/src/popup/main.ts new file mode 100644 index 0000000000..2c8c68e1a2 --- /dev/null +++ b/bitwarden_license/bit-browser/src/popup/main.ts @@ -0,0 +1,26 @@ +import { enableProdMode } from "@angular/core"; +import { platformBrowserDynamic } from "@angular/platform-browser-dynamic"; + +import { PopupSizeService } from "@bitwarden/browser/platform/popup/layout/popup-size.service"; +import { BrowserPlatformUtilsService } from "@bitwarden/browser/platform/services/platform-utils/browser-platform-utils.service"; + +import { AppModule } from "./app.module"; + +import "@bitwarden/browser/popup/scss"; + +// We put these first to minimize the delay in window changing. +PopupSizeService.initBodyWidthFromLocalStorage(); +// Should be removed once we deprecate support for Safari 16.0 and older. See Jira ticket [PM-1861] +if (BrowserPlatformUtilsService.shouldApplySafariHeightFix(window)) { + document.documentElement.classList.add("safari_height_fix"); +} + +if (process.env.ENV === "production") { + enableProdMode(); +} + +function init() { + void platformBrowserDynamic().bootstrapModule(AppModule); +} + +init(); diff --git a/bitwarden_license/bit-browser/tsconfig.json b/bitwarden_license/bit-browser/tsconfig.json new file mode 100644 index 0000000000..c3420e280b --- /dev/null +++ b/bitwarden_license/bit-browser/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../apps/browser/tsconfig", + "include": [ + "src", + + "../../apps/browser/src/**/*.d.ts", + + "../../apps/browser/src/autofill/content/*.ts", + "../../apps/browser/src/autofill/fido2/content/*.ts", + "../../apps/browser/src/autofill/notification/bar.ts", + "../../apps/browser/src/autofill/overlay/inline-menu/**/*.ts", + "../../apps/browser/src/platform/ipc/content/*.ts", + "../../apps/browser/src/platform/offscreen-document/offscreen-document.ts", + "../../apps/browser/src/popup/polyfills.ts", + "../../apps/browser/src/vault/content/*.ts", + + "../../libs/common/src/autofill/constants", + "../../libs/common/custom-matchers.d.ts" + ] +} diff --git a/bitwarden_license/bit-browser/tsconfig.spec.json b/bitwarden_license/bit-browser/tsconfig.spec.json new file mode 100644 index 0000000000..968309bca6 --- /dev/null +++ b/bitwarden_license/bit-browser/tsconfig.spec.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "isolatedModules": true, + "emitDecoratorMetadata": false + }, + "files": ["../../apps/browser/test.setup.ts"] +} diff --git a/bitwarden_license/bit-browser/webpack.config.js b/bitwarden_license/bit-browser/webpack.config.js new file mode 100644 index 0000000000..294e2f1625 --- /dev/null +++ b/bitwarden_license/bit-browser/webpack.config.js @@ -0,0 +1,13 @@ +const { buildConfig } = require("../../apps/browser/webpack.base"); + +module.exports = buildConfig({ + configName: "Commercial", + popup: { + entry: "../../bitwarden_license/bit-browser/src/popup/main.ts", + entryModule: "../../bitwarden_license/bit-browser/src/popup/app.module#AppModule", + }, + background: { + entry: "../../bitwarden_license/bit-browser/src/platform/background.ts", + }, + tsConfig: "../../bitwarden_license/bit-browser/tsconfig.json", +}); diff --git a/jest.config.js b/jest.config.js index 3e4fb665a8..9be54e9999 100644 --- a/jest.config.js +++ b/jest.config.js @@ -20,9 +20,10 @@ module.exports = { "/apps/cli/jest.config.js", "/apps/desktop/jest.config.js", "/apps/web/jest.config.js", - "/bitwarden_license/bit-web/jest.config.js", + "/bitwarden_license/bit-browser/jest.config.js", "/bitwarden_license/bit-cli/jest.config.js", "/bitwarden_license/bit-common/jest.config.js", + "/bitwarden_license/bit-web/jest.config.js", "/libs/admin-console/jest.config.js", "/libs/angular/jest.config.js", diff --git a/tsconfig.base.json b/tsconfig.base.json index 3d38f0f821..3d1d2915f6 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -26,6 +26,7 @@ "@bitwarden/auth/common": ["./libs/auth/src/common"], "@bitwarden/billing": ["./libs/billing/src"], "@bitwarden/bit-common/*": ["./bitwarden_license/bit-common/src/*"], + "@bitwarden/browser/*": ["./apps/browser/src/*"], "@bitwarden/cli/*": ["./apps/cli/src/*"], "@bitwarden/client-type": ["libs/client-type/src/index.ts"], "@bitwarden/common/*": ["./libs/common/src/*"],