mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-21 16:18:28 +01:00
[PM-14485] Remove manifest and index.html logic from gulp (#11861)
Refactor the remaining logic from gulp. Part of the browser build script refactor effort. Webpack is now responsible for performing most of the operations previously done by gulp. This includes: - Setting browser specific class - Building the manifest file The `package.json` is modified to include browser specific commands for `build`, `build:prod`, `build:watch` and `dist`. # Manifests Manifests now uses the `copy-webpack-plugin` `transform` feature. The logic is located in `apps/browser/webpack/manifest.js`. It reads a template, which supports some basic operations primarily overriding with browser specific fields using `__browser__`. The `manifest.json` for both regular and mv3 builds are identical to our existing manifests except: - `applications` renamed to `browser_specific_settings`. - `permissions` sorted alphabetically. # Safari build Safari requires additional packaging commands. This is implemented as a powershell script due to the cross-platform nature, and since we generally require powershell in our distribution pipelines. An alternative would be to write it in bash, but bash is less powerful and would require some additional commands like `jq`. Another alternative is to write it using js, but that would require additional dependencies.
This commit is contained in:
parent
ea5f492fd1
commit
c388697fdf
@ -12,6 +12,7 @@ storybook-static
|
||||
|
||||
apps/browser/config/config.js
|
||||
apps/browser/src/auth/scripts/duo.js
|
||||
apps/browser/webpack/manifest.js
|
||||
|
||||
apps/desktop/desktop_native
|
||||
apps/desktop/src/auth/scripts/duo.js
|
||||
|
114
.github/workflows/build-browser.yml
vendored
114
.github/workflows/build-browser.yml
vendored
@ -164,16 +164,74 @@ jobs:
|
||||
|
||||
zip -r browser-source.zip browser-source
|
||||
|
||||
- name: Upload browser source
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: browser-source-${{ env._BUILD_NUMBER }}.zip
|
||||
path: browser-source.zip
|
||||
if-no-files-found: error
|
||||
|
||||
- name: NPM setup
|
||||
run: npm ci
|
||||
working-directory: browser-source/
|
||||
|
||||
- name: Build
|
||||
run: npm run dist
|
||||
- name: Build Chrome
|
||||
run: npm run dist:chrome
|
||||
working-directory: browser-source/apps/browser
|
||||
|
||||
- name: Build Manifest v3
|
||||
run: npm run dist:mv3
|
||||
- name: Upload Chrome MV3 artifact
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: dist-chrome-MV3-${{ env._BUILD_NUMBER }}.zip
|
||||
path: browser-source/apps/browser/dist/dist-chrome.zip
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Build Edge
|
||||
run: npm run dist:edge
|
||||
working-directory: browser-source/apps/browser
|
||||
|
||||
- name: Upload Edge artifact
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: dist-edge-${{ env._BUILD_NUMBER }}.zip
|
||||
path: browser-source/apps/browser/dist/dist-edge.zip
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Build Edge (MV3)
|
||||
run: npm run dist:edge:mv3
|
||||
working-directory: browser-source/apps/browser
|
||||
|
||||
- name: Upload Edge MV3 artifact (DO NOT USE FOR PROD)
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: DO-NOT-USE-FOR-PROD-dist-edge-MV3-${{ env._BUILD_NUMBER }}.zip
|
||||
path: browser-source/apps/browser/dist/dist-edge.zip
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Build Firefox
|
||||
run: npm run dist:firefox
|
||||
working-directory: browser-source/apps/browser
|
||||
|
||||
- name: Upload Firefox artifact
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: dist-firefox-${{ env._BUILD_NUMBER }}.zip
|
||||
path: browser-source/apps/browser/dist/dist-firefox.zip
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Build Firefox (MV3)
|
||||
run: npm run dist:firefox:mv3
|
||||
working-directory: browser-source/apps/browser
|
||||
|
||||
- name: Upload Firefox MV3 artifact (DO NOT USE FOR PROD)
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: DO-NOT-USE-FOR-PROD-dist-firefox-MV3-${{ env._BUILD_NUMBER }}.zip
|
||||
path: browser-source/apps/browser/dist/dist-firefox.zip
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Build Opera
|
||||
run: npm run dist:opera
|
||||
working-directory: browser-source/apps/browser
|
||||
|
||||
- name: Upload Opera artifact
|
||||
@ -183,53 +241,15 @@ jobs:
|
||||
path: browser-source/apps/browser/dist/dist-opera.zip
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Build Opera (MV3)
|
||||
run: npm run dist:opera:mv3
|
||||
working-directory: browser-source/apps/browser
|
||||
|
||||
- name: Upload Opera MV3 artifact (DO NOT USE FOR PROD)
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: DO-NOT-USE-FOR-PROD-dist-opera-MV3-${{ env._BUILD_NUMBER }}.zip
|
||||
path: browser-source/apps/browser/dist/dist-opera-mv3.zip
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload Chrome MV3 artifact
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: dist-chrome-MV3-${{ env._BUILD_NUMBER }}.zip
|
||||
path: browser-source/apps/browser/dist/dist-chrome-mv3.zip
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload Firefox artifact
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: dist-firefox-${{ env._BUILD_NUMBER }}.zip
|
||||
path: browser-source/apps/browser/dist/dist-firefox.zip
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload Firefox MV3 artifact (DO NOT USE FOR PROD)
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: DO-NOT-USE-FOR-PROD-dist-firefox-MV3-${{ env._BUILD_NUMBER }}.zip
|
||||
path: browser-source/apps/browser/dist/dist-firefox-mv3.zip
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload Edge artifact
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: dist-edge-${{ env._BUILD_NUMBER }}.zip
|
||||
path: browser-source/apps/browser/dist/dist-edge.zip
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload Edge MV3 artifact (DO NOT USE FOR PROD)
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: DO-NOT-USE-FOR-PROD-dist-edge-MV3-${{ env._BUILD_NUMBER }}.zip
|
||||
path: browser-source/apps/browser/dist/dist-edge-mv3.zip
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload browser source
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
with:
|
||||
name: browser-source-${{ env._BUILD_NUMBER }}.zip
|
||||
path: browser-source.zip
|
||||
path: browser-source/apps/browser/dist/dist-opera.zip
|
||||
if-no-files-found: error
|
||||
|
||||
build-safari:
|
||||
|
2
.github/workflows/release-browser.yml
vendored
2
.github/workflows/release-browser.yml
vendored
@ -121,7 +121,7 @@ jobs:
|
||||
PACKAGE_VERSION: ${{ needs.setup.outputs.release-version }}
|
||||
run: |
|
||||
mv browser-source.zip browser-source-$PACKAGE_VERSION.zip
|
||||
mv dist-chrome-mv3.zip dist-chrome-$PACKAGE_VERSION.zip
|
||||
mv dist-chrome.zip dist-chrome-$PACKAGE_VERSION.zip
|
||||
mv dist-opera.zip dist-opera-$PACKAGE_VERSION.zip
|
||||
mv dist-firefox.zip dist-firefox-$PACKAGE_VERSION.zip
|
||||
mv dist-edge.zip dist-edge-$PACKAGE_VERSION.zip
|
||||
|
@ -1,233 +0,0 @@
|
||||
const child = require("child_process");
|
||||
const fs = require("fs");
|
||||
|
||||
const { rimraf } = require("rimraf");
|
||||
const gulp = require("gulp");
|
||||
const gulpif = require("gulp-if");
|
||||
const jeditor = require("gulp-json-editor");
|
||||
const replace = require("gulp-replace");
|
||||
|
||||
const manifest = require("./src/manifest.json");
|
||||
const manifestVersion = parseInt(process.env.MANIFEST_VERSION || manifest.version);
|
||||
|
||||
const paths = {
|
||||
build: "./build/",
|
||||
dist: "./dist/",
|
||||
safari: "./src/safari/",
|
||||
};
|
||||
|
||||
function buildString() {
|
||||
var build = "";
|
||||
if (process.env.MANIFEST_VERSION) {
|
||||
build = `-mv${process.env.MANIFEST_VERSION}`;
|
||||
}
|
||||
if (process.env.BUILD_NUMBER && process.env.BUILD_NUMBER !== "") {
|
||||
build = `-${process.env.BUILD_NUMBER}`;
|
||||
}
|
||||
return build;
|
||||
}
|
||||
|
||||
function distFileName(browserName, ext) {
|
||||
return `dist-${browserName}${buildString()}.${ext}`;
|
||||
}
|
||||
|
||||
async function dist(browserName, manifest) {
|
||||
const { default: zip } = await import("gulp-zip");
|
||||
|
||||
return gulp
|
||||
.src(paths.build + "**/*")
|
||||
.pipe(gulpif("popup/index.html", replace("__BROWSER__", "browser_" + browserName)))
|
||||
.pipe(gulpif("manifest.json", jeditor(manifest)))
|
||||
.pipe(zip(distFileName(browserName, "zip")))
|
||||
.pipe(gulp.dest(paths.dist));
|
||||
}
|
||||
|
||||
function distFirefox() {
|
||||
return dist("firefox", (manifest) => {
|
||||
if (manifestVersion === 3) {
|
||||
const backgroundScript = manifest.background.service_worker;
|
||||
delete manifest.background.service_worker;
|
||||
manifest.background.scripts = [backgroundScript];
|
||||
}
|
||||
delete manifest.storage;
|
||||
delete manifest.sandbox;
|
||||
manifest.optional_permissions = manifest.optional_permissions.filter(
|
||||
(permission) => permission !== "privacy",
|
||||
);
|
||||
return manifest;
|
||||
});
|
||||
}
|
||||
|
||||
function distOpera() {
|
||||
return dist("opera", (manifest) => {
|
||||
delete manifest.applications;
|
||||
|
||||
// Mv3 on Opera does seem to have sidebar support, however it is not working as expected.
|
||||
// On install, the extension will crash the browser entirely if the sidebar_action key is set.
|
||||
// We will remove the sidebar_action key for now until opera implements a fix.
|
||||
if (manifestVersion === 3) {
|
||||
delete manifest.sidebar_action;
|
||||
delete manifest.commands._execute_sidebar_action;
|
||||
}
|
||||
|
||||
return manifest;
|
||||
});
|
||||
}
|
||||
|
||||
function distChrome() {
|
||||
return dist("chrome", (manifest) => {
|
||||
delete manifest.applications;
|
||||
delete manifest.sidebar_action;
|
||||
delete manifest.commands._execute_sidebar_action;
|
||||
return manifest;
|
||||
});
|
||||
}
|
||||
|
||||
function distEdge() {
|
||||
return dist("edge", (manifest) => {
|
||||
delete manifest.applications;
|
||||
delete manifest.sidebar_action;
|
||||
delete manifest.commands._execute_sidebar_action;
|
||||
return manifest;
|
||||
});
|
||||
}
|
||||
|
||||
function distSafariMas(cb) {
|
||||
return distSafariApp(cb, "mas");
|
||||
}
|
||||
|
||||
function distSafariMasDev(cb) {
|
||||
return distSafariApp(cb, "masdev");
|
||||
}
|
||||
|
||||
function distSafariDmg(cb) {
|
||||
return distSafariApp(cb, "dmg");
|
||||
}
|
||||
|
||||
function distSafariApp(cb, subBuildPath) {
|
||||
const buildPath = paths.dist + "Safari/" + subBuildPath + "/";
|
||||
const builtAppexPath = buildPath + "build/Release/safari.appex";
|
||||
const builtAppexFrameworkPath = buildPath + "build/Release/safari.appex/Contents/Frameworks/";
|
||||
const entitlementsPath = paths.safari + "safari/safari.entitlements";
|
||||
var args = [
|
||||
"--verbose",
|
||||
"--force",
|
||||
"-o",
|
||||
"runtime",
|
||||
"--sign",
|
||||
"Developer ID Application: 8bit Solutions LLC",
|
||||
"--entitlements",
|
||||
entitlementsPath,
|
||||
];
|
||||
if (subBuildPath !== "dmg") {
|
||||
args = [
|
||||
"--verbose",
|
||||
"--force",
|
||||
"--sign",
|
||||
subBuildPath === "mas"
|
||||
? "3rd Party Mac Developer Application: Bitwarden Inc"
|
||||
: "E7C9978F6FBCE0553429185C405E61F5380BE8EB",
|
||||
"--entitlements",
|
||||
entitlementsPath,
|
||||
];
|
||||
}
|
||||
|
||||
return rimraf([buildPath + "**/*"], { glob: true })
|
||||
.then(() => safariCopyAssets(paths.safari + "**/*", buildPath))
|
||||
.then(() => safariCopyBuild(paths.build + "**/*", buildPath + "safari/app"))
|
||||
.then(() => {
|
||||
const proc = child.spawn("xcodebuild", [
|
||||
"-project",
|
||||
buildPath + "desktop.xcodeproj",
|
||||
"-alltargets",
|
||||
"-configuration",
|
||||
"Release",
|
||||
]);
|
||||
stdOutProc(proc);
|
||||
return new Promise((resolve) => proc.on("close", resolve));
|
||||
})
|
||||
.then(async () => {
|
||||
const libs = fs
|
||||
.readdirSync(builtAppexFrameworkPath)
|
||||
.filter((p) => p.endsWith(".dylib"))
|
||||
.map((p) => builtAppexFrameworkPath + p);
|
||||
const libPromises = [];
|
||||
libs.forEach((i) => {
|
||||
const proc = child.spawn("codesign", args.concat([i]));
|
||||
stdOutProc(proc);
|
||||
libPromises.push(new Promise((resolve) => proc.on("close", resolve)));
|
||||
});
|
||||
return Promise.all(libPromises);
|
||||
})
|
||||
.then(() => {
|
||||
const proc = child.spawn("codesign", args.concat([builtAppexPath]));
|
||||
stdOutProc(proc);
|
||||
return new Promise((resolve) => proc.on("close", resolve));
|
||||
})
|
||||
.then(
|
||||
() => {
|
||||
return cb;
|
||||
},
|
||||
() => {
|
||||
return cb;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
function safariCopyAssets(source, dest) {
|
||||
return new Promise((resolve, reject) => {
|
||||
gulp
|
||||
.src(source)
|
||||
.on("error", reject)
|
||||
.pipe(gulpif("safari/Info.plist", replace("0.0.1", manifest.version)))
|
||||
.pipe(
|
||||
gulpif("safari/Info.plist", replace("0.0.2", process.env.BUILD_NUMBER || manifest.version)),
|
||||
)
|
||||
.pipe(gulpif("desktop.xcodeproj/project.pbxproj", replace("../../../build", "../safari/app")))
|
||||
.pipe(gulp.dest(dest))
|
||||
.on("end", resolve);
|
||||
});
|
||||
}
|
||||
|
||||
async function safariCopyBuild(source, dest) {
|
||||
return new Promise((resolve, reject) => {
|
||||
gulp
|
||||
.src(source)
|
||||
.on("error", reject)
|
||||
.pipe(gulpif("popup/index.html", replace("__BROWSER__", "browser_safari")))
|
||||
.pipe(
|
||||
gulpif(
|
||||
"manifest.json",
|
||||
jeditor((manifest) => {
|
||||
if (manifestVersion === 3) {
|
||||
const backgroundScript = manifest.background.service_worker;
|
||||
delete manifest.background.service_worker;
|
||||
manifest.background.scripts = [backgroundScript];
|
||||
}
|
||||
delete manifest.sidebar_action;
|
||||
delete manifest.commands._execute_sidebar_action;
|
||||
delete manifest.optional_permissions;
|
||||
manifest.permissions.push("nativeMessaging");
|
||||
return manifest;
|
||||
}),
|
||||
),
|
||||
)
|
||||
.pipe(gulp.dest(dest))
|
||||
.on("end", resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function stdOutProc(proc) {
|
||||
proc.stdout.on("data", (data) => console.log(data.toString()));
|
||||
proc.stderr.on("data", (data) => console.error(data.toString()));
|
||||
}
|
||||
|
||||
exports["dist:firefox"] = distFirefox;
|
||||
exports["dist:chrome"] = distChrome;
|
||||
exports["dist:opera"] = distOpera;
|
||||
exports["dist:edge"] = distEdge;
|
||||
exports["dist:safari"] = gulp.parallel(distSafariMas, distSafariMasDev, distSafariDmg);
|
||||
exports["dist:safari:mas"] = distSafariMas;
|
||||
exports["dist:safari:masdev"] = distSafariMasDev;
|
||||
exports["dist:safari:dmg"] = distSafariDmg;
|
||||
exports.dist = gulp.parallel(distFirefox, distChrome, distOpera, distEdge);
|
@ -2,26 +2,32 @@
|
||||
"name": "@bitwarden/browser",
|
||||
"version": "2024.11.1",
|
||||
"scripts": {
|
||||
"build": "cross-env MANIFEST_VERSION=3 webpack",
|
||||
"build:mv2": "webpack",
|
||||
"build": "npm run build:chrome",
|
||||
"build:chrome": "cross-env BROWSER=chrome MANIFEST_VERSION=3 webpack",
|
||||
"build:edge": "cross-env BROWSER=edge webpack",
|
||||
"build:firefox": "cross-env BROWSER=firefox webpack",
|
||||
"build:opera": "cross-env BROWSER=opera webpack",
|
||||
"build:safari": "cross-env BROWSER=safari webpack",
|
||||
"build:watch": "npm run build:watch:chrome",
|
||||
"build:watch:chrome": "cross-env MANIFEST_VERSION=3 BROWSER=chrome webpack --watch",
|
||||
"build:watch:firefox": "cross-env MANIFEST_VERSION=3 BROWSER=firefox webpack --watch",
|
||||
"build:watch:safari": "cross-env MANIFEST_VERSION=3 BROWSER=safari webpack --watch",
|
||||
"build:watch:mv2": "webpack --watch",
|
||||
"build:prod": "cross-env NODE_ENV=production NODE_OPTIONS=\"--max-old-space-size=4096\" webpack",
|
||||
"build:prod:watch": "cross-env NODE_ENV=production webpack --watch",
|
||||
"dist": "npm run build:prod && gulp dist",
|
||||
"dist:mv3": "cross-env MANIFEST_VERSION=3 npm run build:prod && cross-env MANIFEST_VERSION=3 gulp dist",
|
||||
"dist:chrome": "npm run build:prod && gulp dist:chrome",
|
||||
"dist:chrome:beta": "cross-env MANIFEST_VERSION=3 npm run build:prod:beta && cross-env MANIFEST_VERSION=3 BETA_BUILD=1 gulp dist:chrome",
|
||||
"dist:firefox": "npm run build:prod && gulp dist:firefox",
|
||||
"dist:opera": "npm run build:prod && gulp dist:opera",
|
||||
"dist:safari": "cross-env BROWSER=safari npm run build:prod && gulp dist:safari",
|
||||
"dist:safari:mv3": "cross-env MANIFEST_VERSION=3 BROWSER=safari run build:prod && cross-env MANIFEST_VERSION=3 BROWSER=safari gulp dist:safari",
|
||||
"dist:safari:mas": "npm run build:prod && gulp dist:safari:mas",
|
||||
"dist:safari:masdev": "npm run build:prod && gulp dist:safari:masdev",
|
||||
"dist:safari:dmg": "npm run build:prod && gulp dist:safari:dmg",
|
||||
"build:watch:chrome": "npm run build:chrome -- --watch",
|
||||
"build:watch:edge": "npm run build:edge -- --watch",
|
||||
"build:watch:firefox": "npm run build:firefox -- --watch",
|
||||
"build:watch:opera": "npm run build:opera -- --watch",
|
||||
"build:watch:safari": "npm run build:safari -- --watch",
|
||||
"build:prod:chrome": "cross-env NODE_ENV=production NODE_OPTIONS=\"--max-old-space-size=4096\" npm run build:chrome",
|
||||
"build:prod:edge": "cross-env NODE_ENV=production NODE_OPTIONS=\"--max-old-space-size=4096\" npm run build:edge",
|
||||
"build:prod:firefox": "cross-env NODE_ENV=production NODE_OPTIONS=\"--max-old-space-size=4096\" npm run build:firefox",
|
||||
"build:prod:opera": "cross-env NODE_ENV=production NODE_OPTIONS=\"--max-old-space-size=4096\" npm run build:opera",
|
||||
"build:prod:safari": "cross-env NODE_ENV=production NODE_OPTIONS=\"--max-old-space-size=4096\" npm run build:safari",
|
||||
"dist:chrome": "npm run build:prod:chrome && mkdir -p dist && tar -C ./build -acf dist/dist-chrome.zip ./",
|
||||
"dist:edge": "npm run build:prod:edge && mkdir -p dist && tar -C ./build -acf dist/dist-edge.zip ./",
|
||||
"dist:firefox": "npm run build:prod:firefox && mkdir -p dist && tar -C ./build -acf dist/dist-firefox.zip ./",
|
||||
"dist:opera": "npm run build:prod:opera && mkdir -p dist && tar -C ./build -acf dist/dist-opera.zip ./",
|
||||
"dist:safari": "npm run build:prod:safari && ./scripts/package-safari.ps1",
|
||||
"dist:edge:mv3": "cross-env MANIFEST_VERSION=3 npm run dist:edge",
|
||||
"dist:firefox:mv3": "cross-env MANIFEST_VERSION=3 npm run dist:firefox",
|
||||
"dist:opera:mv3": "cross-env MANIFEST_VERSION=3 npm run dist:opera",
|
||||
"dist:safari:mv3": "cross-env MANIFEST_VERSION=3 npm run dist:safari",
|
||||
"test": "jest",
|
||||
"test:watch": "jest --watch",
|
||||
"test:watch:all": "jest --watchAll"
|
||||
|
112
apps/browser/scripts/package-safari.ps1
Executable file
112
apps/browser/scripts/package-safari.ps1
Executable file
@ -0,0 +1,112 @@
|
||||
#!/usr/bin/env pwsh
|
||||
|
||||
####
|
||||
# Builds the safari appex.
|
||||
####
|
||||
|
||||
$buildDir = Join-Path $PSScriptRoot "../build"
|
||||
$distDir = Join-Path $PSScriptRoot "../dist"
|
||||
|
||||
Write-Output $PSScriptRoot
|
||||
|
||||
if (-not (Test-Path $buildDir)) {
|
||||
Write-Output "No build directory found. Exiting..."
|
||||
exit
|
||||
}
|
||||
|
||||
# Create dist directory if it doesn't exist
|
||||
if (-not (Test-Path $distDir)) {
|
||||
New-Item -ItemType Directory -Path $distDir
|
||||
}
|
||||
|
||||
$subBuildPaths = @("mas", "masdev", "dmg")
|
||||
$safariSrc = Join-Path $PSScriptRoot "../src/safari"
|
||||
$safariDistPath = Join-Path -Path $distDir -ChildPath "Safari"
|
||||
|
||||
if (-not (Test-Path $safariDistPath)) {
|
||||
New-Item -ItemType Directory -Path $safariDistPath
|
||||
}
|
||||
|
||||
# Delete old safari dists
|
||||
Remove-Item -LiteralPath $safariDistPath -Force -Recurse
|
||||
|
||||
foreach ($subBuildPath in $subBuildPaths) {
|
||||
$safariBuildPath = Join-Path -Path $safariDistPath -ChildPath $subBuildPath
|
||||
$builtAppexPath = Join-Path -Path $safariBuildPath -ChildPath "build/Release/safari.appex"
|
||||
$builtAppexFrameworkPath = Join-Path -Path $safariBuildPath -ChildPath "build/Release/safari.appex/Contents/Frameworks/"
|
||||
$entitlementsPath = Join-Path -Path $safariSrc -ChildPath "safari/safari.entitlements"
|
||||
|
||||
switch ($subBuildPath) {
|
||||
"mas" {
|
||||
$codesignArgs = @(
|
||||
"--verbose",
|
||||
"--force",
|
||||
"--sign",
|
||||
"3rd Party Mac Developer Application: Bitwarden Inc",
|
||||
"--entitlements",
|
||||
$entitlementsPath
|
||||
)
|
||||
}
|
||||
"masdev" {
|
||||
$codesignArgs = @(
|
||||
"--verbose",
|
||||
"--force",
|
||||
"--sign",
|
||||
"E7C9978F6FBCE0553429185C405E61F5380BE8EB",
|
||||
"--entitlements",
|
||||
$entitlementsPath
|
||||
)
|
||||
}
|
||||
"dmg" {
|
||||
$codesignArgs = @(
|
||||
"--verbose",
|
||||
"--force",
|
||||
"-o",
|
||||
"runtime",
|
||||
"--sign",
|
||||
"Developer ID Application: 8bit Solutions LLC",
|
||||
"--entitlements",
|
||||
$entitlementsPath
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
# Copy safari src
|
||||
Copy-Item -Path $safariSrc -Destination $safariBuildPath -Recurse
|
||||
|
||||
# Copy build
|
||||
$target = Join-Path -Path $safariBuildPath -ChildPath "safari/app"
|
||||
Copy-Item -Path $buildDir -Destination $target -Recurse
|
||||
|
||||
# Update versions
|
||||
$jsonFilePath = Join-Path $buildDir "manifest.json"
|
||||
$jsonContent = Get-Content -Path $jsonFilePath -Raw
|
||||
$jsonObject = $jsonContent | ConvertFrom-Json
|
||||
|
||||
$infoFile = Join-Path -Path $safariBuildPath -ChildPath "safari/Info.plist"
|
||||
(Get-Content $infoFile).Replace('0.0.1', $jsonObject.version).Replace('0.0.2', $jsonObject.version) | Set-Content $infoFile
|
||||
|
||||
$projectFile = Join-Path -Path $safariBuildPath -ChildPath "desktop.xcodeproj/project.pbxproj"
|
||||
(Get-Content $projectFile).Replace('../../../build', "../safari/app") | Set-Content $projectFile
|
||||
|
||||
# Build using xcode
|
||||
$xcodeBuildArgs = @(
|
||||
"-project",
|
||||
(Join-Path $safariBuildPath "desktop.xcodeproj"),
|
||||
"-alltargets",
|
||||
"-configuration",
|
||||
"Release"
|
||||
)
|
||||
$proc = Start-Process "xcodebuild" -ArgumentList $xcodeBuildArgs -NoNewWindow -PassThru
|
||||
$proc.WaitForExit()
|
||||
|
||||
# Codesign
|
||||
$libs = Get-ChildItem -Path $builtAppexFrameworkPath -Filter "*.dylib"
|
||||
foreach ($lib in $libs) {
|
||||
$proc = Start-Process "codesign" -ArgumentList ($codesignArgs + $lib.FullName) -NoNewWindow -PassThru
|
||||
$proc.WaitForExit()
|
||||
}
|
||||
|
||||
$proc = Start-Process "codesign" -ArgumentList ($codesignArgs + $builtAppexPath) -NoNewWindow -PassThru
|
||||
$proc.WaitForExit()
|
||||
}
|
@ -52,19 +52,37 @@
|
||||
"permissions": [
|
||||
"<all_urls>",
|
||||
"*://*/*",
|
||||
"tabs",
|
||||
"contextMenus",
|
||||
"storage",
|
||||
"unlimitedStorage",
|
||||
"alarms",
|
||||
"clipboardRead",
|
||||
"clipboardWrite",
|
||||
"contextMenus",
|
||||
"idle",
|
||||
"alarms",
|
||||
"storage",
|
||||
"tabs",
|
||||
"unlimitedStorage",
|
||||
"webNavigation",
|
||||
"webRequest",
|
||||
"webRequestBlocking",
|
||||
"webNavigation"
|
||||
"webRequestBlocking"
|
||||
],
|
||||
"__safari__permissions": [
|
||||
"<all_urls>",
|
||||
"*://*/*",
|
||||
"alarms",
|
||||
"clipboardRead",
|
||||
"clipboardWrite",
|
||||
"contextMenus",
|
||||
"idle",
|
||||
"nativeMessaging",
|
||||
"storage",
|
||||
"tabs",
|
||||
"unlimitedStorage",
|
||||
"webNavigation",
|
||||
"webRequest",
|
||||
"webRequestBlocking"
|
||||
],
|
||||
"optional_permissions": ["nativeMessaging", "privacy"],
|
||||
"__firefox__optional_permissions": ["nativeMessaging"],
|
||||
"__safari__optional_permissions": null,
|
||||
"content_security_policy": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'",
|
||||
"sandbox": {
|
||||
"pages": [
|
||||
@ -75,6 +93,7 @@
|
||||
],
|
||||
"content_security_policy": "sandbox allow-scripts; script-src 'self'"
|
||||
},
|
||||
"__firefox__sandbox": null,
|
||||
"commands": {
|
||||
"_execute_browser_action": {
|
||||
"suggested_key": {
|
||||
@ -83,7 +102,14 @@
|
||||
},
|
||||
"description": "__MSG_commandOpenPopup__"
|
||||
},
|
||||
"_execute_sidebar_action": {
|
||||
"__firefox___execute_sidebar_action": {
|
||||
"suggested_key": {
|
||||
"default": "Alt+Shift+Y",
|
||||
"linux": "Alt+Shift+U"
|
||||
},
|
||||
"description": "__MSG_commandOpenSidebar__"
|
||||
},
|
||||
"__opera___execute_sidebar_action": {
|
||||
"suggested_key": {
|
||||
"default": "Alt+Shift+Y",
|
||||
"linux": "Alt+Shift+U"
|
||||
@ -125,20 +151,26 @@
|
||||
"overlay/list.html",
|
||||
"popup/fonts/*"
|
||||
],
|
||||
"applications": {
|
||||
"__firefox__browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "{446900e4-71c2-419f-a6a7-df9c091e268b}",
|
||||
"strict_min_version": "91.0"
|
||||
}
|
||||
},
|
||||
"sidebar_action": {
|
||||
"__firefox__sidebar_action": {
|
||||
"default_title": "Bitwarden",
|
||||
"default_panel": "popup/index.html?uilocation=sidebar",
|
||||
"default_icon": "images/icon19.png",
|
||||
"open_at_install": false,
|
||||
"browser_style": false
|
||||
},
|
||||
"storage": {
|
||||
"managed_schema": "managed_schema.json"
|
||||
}
|
||||
"__opera__sidebar_action": {
|
||||
"default_title": "Bitwarden",
|
||||
"default_panel": "popup/index.html?uilocation=sidebar",
|
||||
"default_icon": "images/icon19.png",
|
||||
"open_at_install": false,
|
||||
"browser_style": false
|
||||
},
|
||||
"storage": { "managed_schema": "managed_schema.json" },
|
||||
"__firefox__storage": null
|
||||
}
|
||||
|
@ -41,6 +41,9 @@
|
||||
"background": {
|
||||
"service_worker": "background.js"
|
||||
},
|
||||
"__firefox__background": {
|
||||
"scripts": ["background.js"]
|
||||
},
|
||||
"action": {
|
||||
"default_icon": {
|
||||
"19": "images/icon19.png",
|
||||
@ -51,21 +54,40 @@
|
||||
},
|
||||
"permissions": [
|
||||
"activeTab",
|
||||
"tabs",
|
||||
"contextMenus",
|
||||
"storage",
|
||||
"unlimitedStorage",
|
||||
"alarms",
|
||||
"clipboardRead",
|
||||
"clipboardWrite",
|
||||
"contextMenus",
|
||||
"idle",
|
||||
"alarms",
|
||||
"scripting",
|
||||
"offscreen",
|
||||
"scripting",
|
||||
"storage",
|
||||
"tabs",
|
||||
"unlimitedStorage",
|
||||
"webNavigation",
|
||||
"webRequest",
|
||||
"webRequestAuthProvider",
|
||||
"webNavigation"
|
||||
"webRequestAuthProvider"
|
||||
],
|
||||
"__safari__permissions": [
|
||||
"activeTab",
|
||||
"alarms",
|
||||
"clipboardRead",
|
||||
"clipboardWrite",
|
||||
"contextMenus",
|
||||
"idle",
|
||||
"nativeMessaging",
|
||||
"offscreen",
|
||||
"scripting",
|
||||
"storage",
|
||||
"tabs",
|
||||
"unlimitedStorage",
|
||||
"webNavigation",
|
||||
"webRequest",
|
||||
"webRequestAuthProvider"
|
||||
],
|
||||
"optional_permissions": ["nativeMessaging", "privacy"],
|
||||
"__firefox__optional_permissions": ["nativeMessaging"],
|
||||
"__safari__optional_permissions": null,
|
||||
"host_permissions": ["https://*/*", "http://*/*"],
|
||||
"content_security_policy": {
|
||||
"extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'",
|
||||
@ -79,6 +101,7 @@
|
||||
"overlay/list.html"
|
||||
]
|
||||
},
|
||||
"__firefox__sandbox": null,
|
||||
"commands": {
|
||||
"_execute_action": {
|
||||
"suggested_key": {
|
||||
@ -87,7 +110,7 @@
|
||||
},
|
||||
"description": "__MSG_commandOpenPopup__"
|
||||
},
|
||||
"_execute_sidebar_action": {
|
||||
"__firefox___execute_sidebar_action": {
|
||||
"suggested_key": {
|
||||
"default": "Alt+Shift+Y",
|
||||
"linux": "Alt+Shift+U"
|
||||
@ -133,13 +156,13 @@
|
||||
"matches": ["<all_urls>"]
|
||||
}
|
||||
],
|
||||
"applications": {
|
||||
"__firefox__browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "{446900e4-71c2-419f-a6a7-df9c091e268b}",
|
||||
"strict_min_version": "91.0"
|
||||
}
|
||||
},
|
||||
"sidebar_action": {
|
||||
"__firefox__sidebar_action": {
|
||||
"default_title": "Bitwarden",
|
||||
"default_panel": "popup/index.html?uilocation=sidebar",
|
||||
"default_icon": "images/icon19.png",
|
||||
@ -147,5 +170,6 @@
|
||||
},
|
||||
"storage": {
|
||||
"managed_schema": "managed_schema.json"
|
||||
}
|
||||
},
|
||||
"__firefox__storage": null
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!doctype html>
|
||||
<html class="__BROWSER__">
|
||||
<html class="browser_<%= htmlWebpackPlugin.options.browser %>">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
@ -7,58 +7,14 @@ 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");
|
||||
|
||||
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;
|
||||
|
||||
function modifyManifestV3(buffer) {
|
||||
if (manifestVersion === 2 || !browser) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const manifest = JSON.parse(buffer.toString());
|
||||
|
||||
if (browser === "chrome") {
|
||||
// Remove unsupported properties
|
||||
delete manifest.applications;
|
||||
delete manifest.sidebar_action;
|
||||
delete manifest.commands._execute_sidebar_action;
|
||||
|
||||
return JSON.stringify(manifest, null, 2);
|
||||
}
|
||||
|
||||
// Update the background script reference to be an event page
|
||||
const backgroundScript = manifest.background.service_worker;
|
||||
delete manifest.background.service_worker;
|
||||
manifest.background.scripts = [backgroundScript];
|
||||
|
||||
// Remove unsupported properties
|
||||
delete manifest.content_security_policy.sandbox;
|
||||
delete manifest.sandbox;
|
||||
delete manifest.applications;
|
||||
|
||||
manifest.permissions = manifest.permissions.filter((permission) => permission !== "offscreen");
|
||||
|
||||
if (browser === "safari") {
|
||||
delete manifest.sidebar_action;
|
||||
delete manifest.commands._execute_sidebar_action;
|
||||
delete manifest.optional_permissions;
|
||||
manifest.permissions.push("nativeMessaging");
|
||||
}
|
||||
|
||||
if (browser === "firefox") {
|
||||
delete manifest.storage;
|
||||
manifest.optional_permissions = manifest.optional_permissions.filter(
|
||||
(permission) => permission !== "privacy",
|
||||
);
|
||||
}
|
||||
|
||||
return JSON.stringify(manifest, null, 2);
|
||||
}
|
||||
const browser = process.env.BROWSER ?? "chrome";
|
||||
|
||||
console.log(`Building Manifest Version ${manifestVersion} app`);
|
||||
|
||||
@ -142,9 +98,10 @@ const requiredPlugins = [
|
||||
|
||||
const plugins = [
|
||||
new HtmlWebpackPlugin({
|
||||
template: "./src/popup/index.html",
|
||||
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",
|
||||
@ -178,13 +135,11 @@ const plugins = [
|
||||
}),
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
manifestVersion == 3
|
||||
? {
|
||||
from: "./src/manifest.v3.json",
|
||||
to: "manifest.json",
|
||||
transform: (content) => modifyManifestV3(content),
|
||||
}
|
||||
: "./src/manifest.json",
|
||||
{
|
||||
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" },
|
||||
|
72
apps/browser/webpack/manifest.js
Normal file
72
apps/browser/webpack/manifest.js
Normal file
@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Transform the manifest template into a browser specific manifest.
|
||||
*
|
||||
* We support a simple browser prefix to the manifest keys. Example:
|
||||
*
|
||||
* ```json
|
||||
* {
|
||||
* "name": "Default name",
|
||||
* "__chrome__name": "Chrome override"
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Will result in the following manifest:
|
||||
*
|
||||
* ```json
|
||||
* {
|
||||
* "name": "Chrome override"
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* for Chrome.
|
||||
*/
|
||||
function transform(browser) {
|
||||
return (buffer) => {
|
||||
let manifest = JSON.parse(buffer.toString());
|
||||
|
||||
manifest = transformPrefixes(manifest, browser);
|
||||
|
||||
return JSON.stringify(manifest, null, 2);
|
||||
};
|
||||
}
|
||||
|
||||
const browsers = ["chrome", "edge", "firefox", "opera", "safari"];
|
||||
|
||||
/**
|
||||
* Flatten the browser prefixes in the manifest.
|
||||
*
|
||||
* - Removes unrelated browser prefixes.
|
||||
* - A null value deletes the non prefixed key.
|
||||
*/
|
||||
function transformPrefixes(manifest, browser) {
|
||||
const prefix = `__${browser}__`;
|
||||
|
||||
function transformObject(obj) {
|
||||
return Object.keys(obj).reduce((acc, key) => {
|
||||
// Determine if we need to recurse into the object.
|
||||
const nested = typeof obj[key] === "object" && obj[key] !== null && !Array.isArray(obj[key]);
|
||||
|
||||
if (key.startsWith(prefix)) {
|
||||
const newKey = key.slice(prefix.length);
|
||||
|
||||
// Null values are used to remove keys.
|
||||
if (obj[key] == null) {
|
||||
delete acc[newKey];
|
||||
return acc;
|
||||
}
|
||||
|
||||
acc[newKey] = nested ? transformObject(obj[key]) : obj[key];
|
||||
} else if (!browsers.some((b) => key.startsWith(`__${b}__`))) {
|
||||
acc[key] = nested ? transformObject(obj[key]) : obj[key];
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
return transformObject(manifest);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
transform,
|
||||
};
|
5009
package-lock.json
generated
5009
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -107,11 +107,6 @@
|
||||
"eslint-plugin-rxjs-angular": "2.0.1",
|
||||
"eslint-plugin-storybook": "0.8.0",
|
||||
"eslint-plugin-tailwindcss": "3.17.4",
|
||||
"gulp": "4.0.2",
|
||||
"gulp-if": "3.0.0",
|
||||
"gulp-json-editor": "2.6.0",
|
||||
"gulp-replace": "1.1.4",
|
||||
"gulp-zip": "6.0.0",
|
||||
"html-loader": "5.1.0",
|
||||
"html-webpack-injector": "1.1.4",
|
||||
"html-webpack-plugin": "5.6.3",
|
||||
|
Loading…
Reference in New Issue
Block a user