|
| 1 | +const child = require("child_process"); |
| 2 | +const fs = require("fs"); |
| 3 | + |
| 4 | +const { rimraf } = require("rimraf"); |
| 5 | +const gulp = require("gulp"); |
| 6 | +const gulpif = require("gulp-if"); |
| 7 | +const jeditor = require("gulp-json-editor"); |
| 8 | +const replace = require("gulp-replace"); |
| 9 | + |
| 10 | +const manifest = require("./src/manifest.json"); |
| 11 | +const manifestVersion = parseInt(process.env.MANIFEST_VERSION || manifest.version); |
| 12 | + |
| 13 | +const paths = { |
| 14 | + build: "./build/", |
| 15 | + dist: "./dist/", |
| 16 | + safari: "./src/safari/", |
| 17 | +}; |
| 18 | + |
| 19 | +function buildString() { |
| 20 | + var build = ""; |
| 21 | + if (process.env.MANIFEST_VERSION) { |
| 22 | + build = `-mv${process.env.MANIFEST_VERSION}`; |
| 23 | + } |
| 24 | + if (process.env.BUILD_NUMBER && process.env.BUILD_NUMBER !== "") { |
| 25 | + build = `-${process.env.BUILD_NUMBER}`; |
| 26 | + } |
| 27 | + return build; |
| 28 | +} |
| 29 | + |
| 30 | +function distFileName(browserName, ext) { |
| 31 | + return `dist-${browserName}${buildString()}.${ext}`; |
| 32 | +} |
| 33 | + |
| 34 | +async function dist(browserName, manifest) { |
| 35 | + const { default: zip } = await import("gulp-zip"); |
| 36 | + |
| 37 | + return gulp |
| 38 | + .src(paths.build + "**/*") |
| 39 | + .pipe(gulpif("popup/index.html", replace("__BROWSER__", "browser_" + browserName))) |
| 40 | + .pipe(gulpif("manifest.json", jeditor(manifest))) |
| 41 | + .pipe(zip(distFileName(browserName, "zip"))) |
| 42 | + .pipe(gulp.dest(paths.dist)); |
| 43 | +} |
| 44 | + |
| 45 | +function distFirefox() { |
| 46 | + return dist("firefox", (manifest) => { |
| 47 | + if (manifestVersion === 3) { |
| 48 | + const backgroundScript = manifest.background.service_worker; |
| 49 | + delete manifest.background.service_worker; |
| 50 | + manifest.background.scripts = [backgroundScript]; |
| 51 | + } |
| 52 | + delete manifest.storage; |
| 53 | + delete manifest.sandbox; |
| 54 | + manifest.optional_permissions = manifest.optional_permissions.filter( |
| 55 | + (permission) => permission !== "privacy", |
| 56 | + ); |
| 57 | + return manifest; |
| 58 | + }); |
| 59 | +} |
| 60 | + |
| 61 | +function distOpera() { |
| 62 | + return dist("opera", (manifest) => { |
| 63 | + delete manifest.applications; |
| 64 | + |
| 65 | + // Mv3 on Opera does seem to have sidebar support, however it is not working as expected. |
| 66 | + // On install, the extension will crash the browser entirely if the sidebar_action key is set. |
| 67 | + // We will remove the sidebar_action key for now until opera implements a fix. |
| 68 | + if (manifestVersion === 3) { |
| 69 | + delete manifest.sidebar_action; |
| 70 | + delete manifest.commands._execute_sidebar_action; |
| 71 | + } |
| 72 | + |
| 73 | + return manifest; |
| 74 | + }); |
| 75 | +} |
| 76 | + |
| 77 | +function distChrome() { |
| 78 | + return dist("chrome", (manifest) => { |
| 79 | + delete manifest.applications; |
| 80 | + delete manifest.sidebar_action; |
| 81 | + delete manifest.commands._execute_sidebar_action; |
| 82 | + return manifest; |
| 83 | + }); |
| 84 | +} |
| 85 | + |
| 86 | +function distEdge() { |
| 87 | + return dist("edge", (manifest) => { |
| 88 | + delete manifest.applications; |
| 89 | + delete manifest.sidebar_action; |
| 90 | + delete manifest.commands._execute_sidebar_action; |
| 91 | + return manifest; |
| 92 | + }); |
| 93 | +} |
| 94 | + |
| 95 | +function distSafariMas(cb) { |
| 96 | + return distSafariApp(cb, "mas"); |
| 97 | +} |
| 98 | + |
| 99 | +function distSafariMasDev(cb) { |
| 100 | + return distSafariApp(cb, "masdev"); |
| 101 | +} |
| 102 | + |
| 103 | +function distSafariDmg(cb) { |
| 104 | + return distSafariApp(cb, "dmg"); |
| 105 | +} |
| 106 | + |
| 107 | +function distSafariApp(cb, subBuildPath) { |
| 108 | + const buildPath = paths.dist + "Safari/" + subBuildPath + "/"; |
| 109 | + const builtAppexPath = buildPath + "build/Release/safari.appex"; |
| 110 | + const builtAppexFrameworkPath = buildPath + "build/Release/safari.appex/Contents/Frameworks/"; |
| 111 | + const entitlementsPath = paths.safari + "safari/safari.entitlements"; |
| 112 | + var args = [ |
| 113 | + "--verbose", |
| 114 | + "--force", |
| 115 | + "-o", |
| 116 | + "runtime", |
| 117 | + "--sign", |
| 118 | + "Developer ID Application: 8bit Solutions LLC", |
| 119 | + "--entitlements", |
| 120 | + entitlementsPath, |
| 121 | + ]; |
| 122 | + if (subBuildPath !== "dmg") { |
| 123 | + args = [ |
| 124 | + "--verbose", |
| 125 | + "--force", |
| 126 | + "--sign", |
| 127 | + subBuildPath === "mas" |
| 128 | + ? "3rd Party Mac Developer Application: Bitwarden Inc" |
| 129 | + : "E7C9978F6FBCE0553429185C405E61F5380BE8EB", |
| 130 | + "--entitlements", |
| 131 | + entitlementsPath, |
| 132 | + ]; |
| 133 | + } |
| 134 | + |
| 135 | + return rimraf([buildPath + "**/*"], { glob: true }) |
| 136 | + .then(() => safariCopyAssets(paths.safari + "**/*", buildPath)) |
| 137 | + .then(() => safariCopyBuild(paths.build + "**/*", buildPath + "safari/app")) |
| 138 | + .then(() => { |
| 139 | + const proc = child.spawn("xcodebuild", [ |
| 140 | + "-project", |
| 141 | + buildPath + "desktop.xcodeproj", |
| 142 | + "-alltargets", |
| 143 | + "-configuration", |
| 144 | + "Release", |
| 145 | + ]); |
| 146 | + stdOutProc(proc); |
| 147 | + return new Promise((resolve) => proc.on("close", resolve)); |
| 148 | + }) |
| 149 | + .then(async () => { |
| 150 | + const libs = fs |
| 151 | + .readdirSync(builtAppexFrameworkPath) |
| 152 | + .filter((p) => p.endsWith(".dylib")) |
| 153 | + .map((p) => builtAppexFrameworkPath + p); |
| 154 | + const libPromises = []; |
| 155 | + libs.forEach((i) => { |
| 156 | + const proc = child.spawn("codesign", args.concat([i])); |
| 157 | + stdOutProc(proc); |
| 158 | + libPromises.push(new Promise((resolve) => proc.on("close", resolve))); |
| 159 | + }); |
| 160 | + return Promise.all(libPromises); |
| 161 | + }) |
| 162 | + .then(() => { |
| 163 | + const proc = child.spawn("codesign", args.concat([builtAppexPath])); |
| 164 | + stdOutProc(proc); |
| 165 | + return new Promise((resolve) => proc.on("close", resolve)); |
| 166 | + }) |
| 167 | + .then( |
| 168 | + () => { |
| 169 | + return cb; |
| 170 | + }, |
| 171 | + () => { |
| 172 | + return cb; |
| 173 | + }, |
| 174 | + ); |
| 175 | +} |
| 176 | + |
| 177 | +function safariCopyAssets(source, dest) { |
| 178 | + return new Promise((resolve, reject) => { |
| 179 | + gulp |
| 180 | + .src(source) |
| 181 | + .on("error", reject) |
| 182 | + .pipe(gulpif("safari/Info.plist", replace("0.0.1", manifest.version))) |
| 183 | + .pipe( |
| 184 | + gulpif("safari/Info.plist", replace("0.0.2", process.env.BUILD_NUMBER || manifest.version)), |
| 185 | + ) |
| 186 | + .pipe(gulpif("desktop.xcodeproj/project.pbxproj", replace("../../../build", "../safari/app"))) |
| 187 | + .pipe(gulp.dest(dest)) |
| 188 | + .on("end", resolve); |
| 189 | + }); |
| 190 | +} |
| 191 | + |
| 192 | +async function safariCopyBuild(source, dest) { |
| 193 | + return new Promise((resolve, reject) => { |
| 194 | + gulp |
| 195 | + .src(source) |
| 196 | + .on("error", reject) |
| 197 | + .pipe(gulpif("popup/index.html", replace("__BROWSER__", "browser_safari"))) |
| 198 | + .pipe( |
| 199 | + gulpif( |
| 200 | + "manifest.json", |
| 201 | + jeditor((manifest) => { |
| 202 | + if (manifestVersion === 3) { |
| 203 | + const backgroundScript = manifest.background.service_worker; |
| 204 | + delete manifest.background.service_worker; |
| 205 | + manifest.background.scripts = [backgroundScript]; |
| 206 | + } |
| 207 | + delete manifest.sidebar_action; |
| 208 | + delete manifest.commands._execute_sidebar_action; |
| 209 | + delete manifest.optional_permissions; |
| 210 | + manifest.permissions.push("nativeMessaging"); |
| 211 | + return manifest; |
| 212 | + }), |
| 213 | + ), |
| 214 | + ) |
| 215 | + .pipe(gulp.dest(dest)) |
| 216 | + .on("end", resolve); |
| 217 | + }); |
| 218 | +} |
| 219 | + |
| 220 | +function stdOutProc(proc) { |
| 221 | + proc.stdout.on("data", (data) => console.log(data.toString())); |
| 222 | + proc.stderr.on("data", (data) => console.error(data.toString())); |
| 223 | +} |
| 224 | + |
| 225 | +exports["dist:firefox"] = distFirefox; |
| 226 | +exports["dist:chrome"] = distChrome; |
| 227 | +exports["dist:opera"] = distOpera; |
| 228 | +exports["dist:edge"] = distEdge; |
| 229 | +exports["dist:safari"] = gulp.parallel(distSafariMas, distSafariMasDev, distSafariDmg); |
| 230 | +exports["dist:safari:mas"] = distSafariMas; |
| 231 | +exports["dist:safari:masdev"] = distSafariMasDev; |
| 232 | +exports["dist:safari:dmg"] = distSafariDmg; |
| 233 | +exports.dist = gulp.parallel(distFirefox, distChrome, distOpera, distEdge); |
0 commit comments