[PM-10667] Implement manifest v3 POC for remaining browsers (#10419)

* [PM-10667] Implement manifest v3 on Firefox and Safari

* [PM-10667] Fixing issues with CORS present in sandboxed iframe on Firefox

* [PM-10667] Updating gulp build process to ensure dist files are created correctly

* [PM-10667] Adding build processes to the Github workflow

* [PM-10667] Removing faulty Safari mv3 build workflow

* [PM-10667] Fixing jest tests

* [PM-10667] Reworking logic within inline menu

* Update apps/browser/webpack.config.js

Co-authored-by: Jonathan Prusik <jprusik@users.noreply.github.com>

---------

Co-authored-by: Jonathan Prusik <jprusik@users.noreply.github.com>
This commit is contained in:
Cesar Gonzalez 2024-08-15 09:54:18 -05:00 committed by GitHub
parent 72767dec74
commit 8fbdd8d22e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 608 additions and 43 deletions

View File

@ -179,12 +179,12 @@ jobs:
path: browser-source/apps/browser/dist/dist-opera.zip
if-no-files-found: error
# - name: Upload Opera MV3 artifact
# uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
# with:
# name: dist-opera-MV3-${{ env._BUILD_NUMBER }}.zip
# path: browser-source/apps/browser/dist/dist-opera-mv3.zip
# if-no-files-found: error
- name: Upload Opera MV3 artifact (DO NOT USE FOR PROD)
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
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@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
@ -207,6 +207,13 @@ jobs:
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@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
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@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with:
@ -214,12 +221,12 @@ jobs:
path: browser-source/apps/browser/dist/dist-edge.zip
if-no-files-found: error
# - name: Upload Edge MV3 artifact
# uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
# with:
# name: dist-edge-MV3-${{ env._BUILD_NUMBER }}.zip
# path: browser-source/apps/browser/dist/dist-edge-mv3.zip
# if-no-files-found: error
- name: Upload Edge MV3 artifact (DO NOT USE FOR PROD)
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
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@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1

View File

@ -8,6 +8,8 @@ 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 betaBuild = process.env.BETA_BUILD === "1";
const paths = {
build: "./build/",
@ -48,7 +50,7 @@ function buildString() {
if (process.env.MANIFEST_VERSION) {
build = `-mv${process.env.MANIFEST_VERSION}`;
}
if (process.env.BETA_BUILD === "1") {
if (betaBuild) {
build += "-beta";
}
if (process.env.BUILD_NUMBER && process.env.BUILD_NUMBER !== "") {
@ -76,12 +78,17 @@ async function dist(browserName, manifest) {
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",
);
if (process.env.BETA_BUILD === "1") {
if (betaBuild) {
manifest = applyBetaLabels(manifest);
}
return manifest;
@ -91,7 +98,16 @@ function distFirefox() {
function distOpera() {
return dist("opera", (manifest) => {
delete manifest.applications;
if (process.env.BETA_BUILD === "1") {
// 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;
}
if (betaBuild) {
manifest = applyBetaLabels(manifest);
}
return manifest;
@ -103,7 +119,7 @@ function distChrome() {
delete manifest.applications;
delete manifest.sidebar_action;
delete manifest.commands._execute_sidebar_action;
if (process.env.BETA_BUILD === "1") {
if (betaBuild) {
manifest = applyBetaLabels(manifest);
}
return manifest;
@ -115,7 +131,7 @@ function distEdge() {
delete manifest.applications;
delete manifest.sidebar_action;
delete manifest.commands._execute_sidebar_action;
if (process.env.BETA_BUILD === "1") {
if (betaBuild) {
manifest = applyBetaLabels(manifest);
}
return manifest;
@ -234,11 +250,16 @@ async function safariCopyBuild(source, dest) {
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");
if (process.env.BETA_BUILD === "1") {
if (betaBuild) {
manifest = applyBetaLabels(manifest);
}
return manifest;

View File

@ -4,7 +4,10 @@
"scripts": {
"build": "cross-env MANIFEST_VERSION=3 webpack",
"build:mv2": "webpack",
"build:watch": "cross-env MANIFEST_VERSION=3 webpack --watch",
"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:beta": "cross-env BETA_BUILD=1 NODE_ENV=production webpack",
@ -17,7 +20,8 @@
"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": "npm run build:prod && gulp dist:safari",
"dist:safari": "cross-env MANIFEST_VERSION=3 npm run build:prod && cross-env MANIFEST_VERSION=3 gulp dist:safari",
"dist:safari:mv3": "npm run build:prod && 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",

View File

@ -395,6 +395,16 @@ class AutofillOverlayList extends AutofillOverlayPageElement {
try {
const url = new URL(cipher.icon.image);
cipherIcon.style.backgroundImage = `url(${url.href})`;
const dummyImageElement = globalThis.document.createElement("img");
dummyImageElement.src = url.href;
dummyImageElement.addEventListener("error", () => {
cipherIcon.style.backgroundImage = "";
cipherIcon.classList.add("cipher-icon");
cipherIcon.append(buildSvgDomElement(globeIcon));
});
dummyImageElement.remove();
return cipherIcon;
} catch {
// Silently default to the globe icon element if the image URL is invalid
@ -402,7 +412,9 @@ class AutofillOverlayList extends AutofillOverlayPageElement {
}
if (cipher.icon?.icon) {
cipherIcon.classList.add("cipher-icon", "bwi", cipher.icon.icon);
const iconClasses = cipher.icon.icon.split(" ");
cipherIcon.classList.add("cipher-icon", "bwi", ...iconClasses);
return cipherIcon;
}

View File

@ -1,5 +1,4 @@
@import "../../../../../../../../libs/angular/src/scss/webfonts.css";
@import "../../../../../../../../libs/angular/src/scss/bwicons/styles/style";
@import "../../../../shared/styles/webfonts";
@import "../../../../shared/styles/variables";
@import "../../../../../../../../libs/angular/src/scss/icons";

View File

@ -226,8 +226,22 @@ exports[`AutofillInlineMenuList initAutofillInlineMenuList the list of ciphers f
>
<span
aria-hidden="true"
class="cipher-icon bwi bwi-id-card"
class="cipher-icon"
>
<svg
aria-hidden="true"
fill="none"
height="24"
viewBox="0 0 23 24"
width="23"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M9.465 12.038c.316-.283.544-.664.652-1.091.108-.427.092-.88-.047-1.297a2.145 2.145 0 0 0-.731-1.032 1.91 1.91 0 0 0-1.149-.394 1.909 1.909 0 0 0-1.15.386 2.143 2.143 0 0 0-.737 1.028 2.305 2.305 0 0 0-.055 1.295c.106.428.331.81.646 1.096-.485.22-.913.563-1.249 1a3.641 3.641 0 0 0-.678 1.508 1.005 1.005 0 0 0 .18.796.877.877 0 0 0 .302.257c.117.06.245.091.375.091h4.693c.13 0 .258-.031.375-.091a.882.882 0 0 0 .302-.256 1.015 1.015 0 0 0 .18-.797 3.636 3.636 0 0 0-.672-1.5 3.313 3.313 0 0 0-1.237-1ZM8.184 9.089c.24 0 .474.077.674.22.2.143.355.347.447.586.092.238.115.5.068.754a1.337 1.337 0 0 1-.332.668 1.19 1.19 0 0 1-.62.357c-.236.05-.48.024-.702-.074a1.238 1.238 0 0 1-.544-.48 1.377 1.377 0 0 1-.205-.725c0-.347.128-.678.356-.923.228-.244.536-.382.857-.382l.001-.001Zm2.333 5.742H5.824l-.083-.121c.12-.597.427-1.132.868-1.515a2.378 2.378 0 0 1 1.56-.592c.568 0 1.119.209 1.56.592.442.383.749.917.869 1.515l-.081.121Zm2.76-4.912h2.833a.384.384 0 0 0 .261-.136.445.445 0 0 0 .106-.29.444.444 0 0 0-.106-.29.387.387 0 0 0-.26-.135h-2.835a.387.387 0 0 0-.26.136.443.443 0 0 0-.106.29c0 .107.037.211.105.29a.39.39 0 0 0 .261.135ZM17.337 14h-4.066a.385.385 0 0 0-.261.136.445.445 0 0 0-.106.29c0 .107.038.21.106.29.068.078.16.126.26.135h4.067a.387.387 0 0 0 .261-.136.442.442 0 0 0 .106-.29.444.444 0 0 0-.106-.29.387.387 0 0 0-.26-.135Zm0-2.466h-4.066a.382.382 0 0 0-.28.124.442.442 0 0 0-.116.301c0 .113.042.221.116.3.074.08.175.125.28.125h4.066a.382.382 0 0 0 .28-.124.442.442 0 0 0 .116-.3.442.442 0 0 0-.116-.302.382.382 0 0 0-.28-.124ZM19.44 5.28H3.627c-.3 0-.587.128-.799.356a1.264 1.264 0 0 0-.33.859V17.43c0 .322.119.631.33.859.212.228.5.356.8.356H19.44c.299 0 .586-.128.798-.356.212-.228.331-.537.331-.859V6.495c0-.322-.12-.631-.33-.859a1.091 1.091 0 0 0-.8-.356Zm-.564 12.15H4.19a.544.544 0 0 1-.4-.178.634.634 0 0 1-.165-.43v-9.72a.63.63 0 0 1 .166-.429.547.547 0 0 1 .399-.178h14.77c.099.024.472.14.48.525v9.803a.63.63 0 0 1-.166.429.547.547 0 0 1-.4.178Z"
fill="#868E96"
/>
</svg>
</span>
<span
class="cipher-details"
>

View File

@ -7,7 +7,9 @@ import { CipherType } from "@bitwarden/common/vault/enums";
import { InlineMenuCipherData } from "../../../../background/abstractions/overlay.background";
import { buildSvgDomElement, throttle } from "../../../../utils";
import {
creditCardIcon,
globeIcon,
idCardIcon,
lockIcon,
plusIcon,
viewCipherIcon,
@ -747,8 +749,8 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement {
dummyImageElement.src = url.href;
dummyImageElement.addEventListener("error", () => {
cipherIcon.style.backgroundImage = "";
const iconClasses = cipher.icon.icon.split(" ");
cipherIcon.classList.add("cipher-icon", "bwi", ...iconClasses);
cipherIcon.classList.add("cipher-icon");
cipherIcon.append(buildSvgDomElement(globeIcon));
});
dummyImageElement.remove();
@ -758,13 +760,23 @@ export class AutofillInlineMenuList extends AutofillInlineMenuPageElement {
}
}
if (cipher.icon?.icon) {
const iconClasses = cipher.icon.icon.split(" ");
cipherIcon.classList.add("cipher-icon", "bwi", ...iconClasses);
if (!cipher.icon?.icon) {
cipherIcon.append(buildSvgDomElement(globeIcon));
return cipherIcon;
}
cipherIcon.append(buildSvgDomElement(globeIcon));
if (cipher.icon.icon.includes("bwi-credit-card")) {
cipherIcon.append(buildSvgDomElement(creditCardIcon));
return cipherIcon;
}
if (cipher.icon.icon.includes("bwi-id-card")) {
cipherIcon.append(buildSvgDomElement(idCardIcon));
return cipherIcon;
}
const iconClasses = cipher.icon.icon.split(" ");
cipherIcon.classList.add("cipher-icon", "bwi", ...iconClasses);
return cipherIcon;
}

View File

@ -1,5 +1,4 @@
@import "../../../../../../../../libs/angular/src/scss/webfonts.css";
@import "../../../../../../../../libs/angular/src/scss/bwicons/styles/style";
@import "../../../../shared/styles/webfonts";
@import "../../../../shared/styles/variables";
@import "../../../../../../../../libs/angular/src/scss/icons";

File diff suppressed because one or more lines are too long

View File

@ -7,6 +7,12 @@ export const logoLockedIcon =
export const globeIcon =
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="25" viewBox="0 0 24 25" fill="none"><path fill="#777" fill-rule="evenodd" d="M18.026 17.842c-1.418 1.739-3.517 2.84-5.86 2.84a7.364 7.364 0 0 1-3.431-.848l.062-.15.062-.151.063-.157c.081-.203.17-.426.275-.646.133-.28.275-.522.426-.68.026-.028.101-.075.275-.115.165-.037.376-.059.629-.073.138-.008.288-.014.447-.02.399-.016.847-.034 1.266-.092.314-.044.566-.131.755-.271a.884.884 0 0 0 .352-.555c.037-.2.008-.392-.03-.543-.035-.135-.084-.264-.12-.355l-.01-.03a4.26 4.26 0 0 0-.145-.33c-.126-.264-.237-.497-.288-1.085-.03-.344.09-.73.251-1.138l.089-.22c.05-.123.1-.247.14-.355.064-.171.129-.375.129-.566a1.51 1.51 0 0 0-.134-.569 2.573 2.573 0 0 0-.319-.547c-.246-.323-.635-.669-1.093-.669-.44 0-1.006.169-1.487.368-.246.102-.48.216-.68.33-.192.111-.372.235-.492.359-.93.96-1.48 1.239-1.81 1.258-.277.017-.478-.15-.736-.525a9.738 9.738 0 0 1-.19-.29l-.006-.01a11.568 11.568 0 0 0-.198-.305 2.76 2.76 0 0 0-.521-.6 1.39 1.39 0 0 0-1.088-.314 8.302 8.302 0 0 1 1.987-3.936c.055.342.146.626.272.856.23.42.561.64.926.716.406.086.857-.061 1.26-.216.125-.047.248-.097.372-.147.309-.125.618-.25.947-.341.26-.072.581-.057.959.012.264.049.529.118.8.19l.36.091c.379.094.782.178 1.135.148.374-.032.733-.197.934-.623a.874.874 0 0 0 .024-.752c-.087-.197-.24-.355-.35-.47-.26-.267-.412-.427-.412-.685 0-.125.037-.2.09-.263a.982.982 0 0 1 .303-.211c.059-.03.119-.058.183-.089l.036-.016a3.79 3.79 0 0 0 .236-.118c.047-.026.098-.056.148-.093 1.936.747 3.51 2.287 4.368 4.249a7.739 7.739 0 0 0-.031-.004c-.38-.047-.738-.056-1.063.061-.34.123-.603.368-.817.74-.122.211-.284.43-.463.67l-.095.129c-.207.281-.431.595-.58.92-.15.326-.245.705-.142 1.103.104.397.387.738.837 1.036.099.065.225.112.314.145l.02.008c.108.04.195.074.268.117.07.042.106.08.124.114.017.03.037.087.022.206-.047.376-.069.73-.052 1.034.017.292.071.59.218.809.118.174.12.421.108.786v.01a2.46 2.46 0 0 0 .021.518.809.809 0 0 0 .15.35Zm1.357.059a9.654 9.654 0 0 0 1.62-5.386c0-5.155-3.957-9.334-8.836-9.334-4.88 0-8.836 4.179-8.836 9.334 0 3.495 1.82 6.543 4.513 8.142v.093h.161a8.426 8.426 0 0 0 4.162 1.098c2.953 0 5.568-1.53 7.172-3.882a.569.569 0 0 0 .048-.062l-.004-.003ZM8.152 19.495a43.345 43.345 0 0 1 .098-.238l.057-.142c.082-.205.182-.455.297-.698.143-.301.323-.624.552-.864.163-.172.392-.254.602-.302.219-.05.473-.073.732-.088.162-.01.328-.016.495-.023.386-.015.782-.03 1.168-.084.255-.036.392-.099.461-.15.06-.045.076-.084.083-.12a.534.534 0 0 0-.02-.223 2.552 2.552 0 0 0-.095-.278l-.01-.027a3.128 3.128 0 0 0-.104-.232c-.134-.282-.31-.65-.374-1.381-.046-.533.138-1.063.3-1.472.035-.09.069-.172.1-.249.046-.11.086-.21.123-.31.062-.169.083-.264.083-.312a.812.812 0 0 0-.076-.283 1.867 1.867 0 0 0-.23-.394c-.21-.274-.428-.408-.577-.408-.315 0-.788.13-1.246.32a5.292 5.292 0 0 0-.603.293 1.727 1.727 0 0 0-.347.244c-.936.968-1.641 1.421-2.235 1.457-.646.04-1.036-.413-1.31-.813-.07-.103-.139-.21-.203-.311l-.005-.007c-.064-.101-.125-.197-.188-.29a2.098 2.098 0 0 0-.387-.453.748.748 0 0 0-.436-.18c-.1-.006-.22.005-.365.046a8.707 8.707 0 0 0-.056.992c0 2.957 1.488 5.547 3.716 6.98Zm10.362-2.316.003-.192.002-.046c.01-.305.026-.786-.232-1.169-.036-.054-.082-.189-.096-.444-.014-.243.003-.55.047-.9a1.051 1.051 0 0 0-.105-.649.987.987 0 0 0-.374-.374 2.285 2.285 0 0 0-.367-.166h-.003a1.243 1.243 0 0 1-.205-.088c-.369-.244-.505-.46-.549-.629-.044-.168-.015-.364.099-.61.115-.25.297-.511.507-.796l.089-.12c.178-.239.368-.495.512-.745.152-.263.302-.382.466-.441.18-.065.416-.073.77-.03.142.018.275.04.397.063.274.837.423 1.736.423 2.671a8.45 8.45 0 0 1-1.384 4.665Zm-4.632-12.63a7.362 7.362 0 0 0-1.715-.201c-1.89 0-3.621.716-4.965 1.905.025.54.12.887.24 1.105.13.238.295.34.482.38.2.042.484-.027.905-.188l.328-.13c.32-.13.681-.275 1.048-.377.398-.111.833-.075 1.24 0 .289.053.59.132.871.205l.326.084c.383.094.694.151.932.13.216-.017.326-.092.395-.237.039-.083.027-.114.014-.144-.027-.062-.088-.136-.212-.264l-.043-.044c-.218-.222-.567-.578-.567-1.142 0-.305.101-.547.262-.734.137-.159.308-.267.46-.347Z" clip-rule="evenodd"/></svg>';
export const creditCardIcon =
'<svg xmlns="http://www.w3.org/2000/svg" width="23" height="24" viewBox="0 0 23 24" fill="none"><path fill="#868E96" d="M19.05 5.52H4.02a1.589 1.589 0 0 0-1.11.56c-.286.333-.433.77-.413 1.218v9.48c-.02.447.127.884.413 1.217.285.333.684.534 1.11.56h15.024a1.588 1.588 0 0 0 1.113-.558c.286-.333.435-.772.414-1.22v-9.48a1.748 1.748 0 0 0-.412-1.217 1.589 1.589 0 0 0-1.11-.56ZM4.025 6.705h15.023a.53.53 0 0 1 .37.187c.094.111.143.257.136.405v1.067a.497.497 0 0 1-.117.35.458.458 0 0 1-.319.16H3.95a.458.458 0 0 1-.317-.16.496.496 0 0 1-.117-.35V7.297a.583.583 0 0 1 .137-.405.53.53 0 0 1 .37-.187h.004Zm15.023 10.658H4.021a.53.53 0 0 1-.366-.185.581.581 0 0 1-.14-.4v-6.2a.5.5 0 0 1 .118-.35.458.458 0 0 1 .318-.161h15.17a.453.453 0 0 1 .32.161.499.499 0 0 1 .117.35v6.2a.584.584 0 0 1-.138.405.532.532 0 0 1-.37.187v-.007Zm-1.354-2.18h-2.658a.395.395 0 0 0-.248.14.432.432 0 0 0 0 .552.392.392 0 0 0 .248.138h2.662a.395.395 0 0 0 .248-.139.432.432 0 0 0 0-.552.392.392 0 0 0-.248-.138h-.004Z"/></svg>';
export const idCardIcon =
'<svg xmlns="http://www.w3.org/2000/svg" width="23" height="24" viewBox="0 0 23 24" fill="none"><path fill="#868E96" d="M9.465 12.038c.316-.283.544-.664.652-1.091.108-.427.092-.88-.047-1.297a2.145 2.145 0 0 0-.731-1.032 1.91 1.91 0 0 0-1.149-.394 1.909 1.909 0 0 0-1.15.386 2.143 2.143 0 0 0-.737 1.028 2.305 2.305 0 0 0-.055 1.295c.106.428.331.81.646 1.096-.485.22-.913.563-1.249 1a3.641 3.641 0 0 0-.678 1.508 1.005 1.005 0 0 0 .18.796.877.877 0 0 0 .302.257c.117.06.245.091.375.091h4.693c.13 0 .258-.031.375-.091a.882.882 0 0 0 .302-.256 1.015 1.015 0 0 0 .18-.797 3.636 3.636 0 0 0-.672-1.5 3.313 3.313 0 0 0-1.237-1ZM8.184 9.089c.24 0 .474.077.674.22.2.143.355.347.447.586.092.238.115.5.068.754a1.337 1.337 0 0 1-.332.668 1.19 1.19 0 0 1-.62.357c-.236.05-.48.024-.702-.074a1.238 1.238 0 0 1-.544-.48 1.377 1.377 0 0 1-.205-.725c0-.347.128-.678.356-.923.228-.244.536-.382.857-.382l.001-.001Zm2.333 5.742H5.824l-.083-.121c.12-.597.427-1.132.868-1.515a2.378 2.378 0 0 1 1.56-.592c.568 0 1.119.209 1.56.592.442.383.749.917.869 1.515l-.081.121Zm2.76-4.912h2.833a.384.384 0 0 0 .261-.136.445.445 0 0 0 .106-.29.444.444 0 0 0-.106-.29.387.387 0 0 0-.26-.135h-2.835a.387.387 0 0 0-.26.136.443.443 0 0 0-.106.29c0 .107.037.211.105.29a.39.39 0 0 0 .261.135ZM17.337 14h-4.066a.385.385 0 0 0-.261.136.445.445 0 0 0-.106.29c0 .107.038.21.106.29.068.078.16.126.26.135h4.067a.387.387 0 0 0 .261-.136.442.442 0 0 0 .106-.29.444.444 0 0 0-.106-.29.387.387 0 0 0-.26-.135Zm0-2.466h-4.066a.382.382 0 0 0-.28.124.442.442 0 0 0-.116.301c0 .113.042.221.116.3.074.08.175.125.28.125h4.066a.382.382 0 0 0 .28-.124.442.442 0 0 0 .116-.3.442.442 0 0 0-.116-.302.382.382 0 0 0-.28-.124ZM19.44 5.28H3.627c-.3 0-.587.128-.799.356a1.264 1.264 0 0 0-.33.859V17.43c0 .322.119.631.33.859.212.228.5.356.8.356H19.44c.299 0 .586-.128.798-.356.212-.228.331-.537.331-.859V6.495c0-.322-.12-.631-.33-.859a1.091 1.091 0 0 0-.8-.356Zm-.564 12.15H4.19a.544.544 0 0 1-.4-.178.634.634 0 0 1-.165-.43v-9.72a.63.63 0 0 1 .166-.429.547.547 0 0 1 .399-.178h14.77c.099.024.472.14.48.525v9.803a.63.63 0 0 1-.166.429.547.547 0 0 1-.4.178Z"/></svg>';
export const lockIcon =
'<svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 17 17" fill="none"><g clip-path="url(#a)"><path fill="#175DDC" d="M8.799 11.633a.68.68 0 0 0-.639.422.695.695 0 0 0-.054.264.682.682 0 0 0 .374.6v1.13a.345.345 0 1 0 .693 0v-1.17a.68.68 0 0 0 .315-.56.695.695 0 0 0-.204-.486.682.682 0 0 0-.485-.2Zm4.554-4.657h-7.11a.438.438 0 0 1-.406-.26A3.81 3.81 0 0 1 5.584 4.3c.112-.435.312-.842.588-1.195A3.196 3.196 0 0 1 7.19 2.25a3.468 3.468 0 0 1 3.225-.059A3.62 3.62 0 0 1 11.94 3.71l.327.59a.502.502 0 1 0 .885-.483l-.307-.552a4.689 4.689 0 0 0-2.209-2.078 4.466 4.466 0 0 0-3.936.185A4.197 4.197 0 0 0 5.37 2.49a4.234 4.234 0 0 0-.768 1.565 4.714 4.714 0 0 0 .162 2.682.182.182 0 0 1-.085.22.173.173 0 0 1-.082.02h-.353a1.368 1.368 0 0 0-1.277.842c-.07.168-.107.348-.109.53v7.1a1.392 1.392 0 0 0 .412.974 1.352 1.352 0 0 0 .974.394h9.117c.363.001.711-.142.97-.4a1.39 1.39 0 0 0 .407-.972v-7.1a1.397 1.397 0 0 0-.414-.973 1.368 1.368 0 0 0-.972-.396Zm.37 8.469a.373.373 0 0 1-.11.26.364.364 0 0 1-.26.107H4.246a.366.366 0 0 1-.26-.107.374.374 0 0 1-.11-.261V8.349a.374.374 0 0 1 .11-.26.366.366 0 0 1 .26-.108h9.116a.366.366 0 0 1 .37.367l-.008 7.097Z"/></g><defs><clipPath id="a"><path fill="#fff" d="M.798.817h16v16h-16z"/></clipPath></defs></svg>';

View File

@ -424,7 +424,6 @@ describe("BrowserApi", () => {
target: {
tabId: tabId,
allFrames: injectDetails.allFrames,
frameIds: null,
},
files: [injectDetails.file],
injectImmediately: true,
@ -450,7 +449,6 @@ describe("BrowserApi", () => {
expect(chrome.scripting.executeScript).toHaveBeenCalledWith({
target: {
tabId: tabId,
allFrames: injectDetails.allFrames,
frameIds: [frameId],
},
files: [injectDetails.file],
@ -477,7 +475,6 @@ describe("BrowserApi", () => {
target: {
tabId: tabId,
allFrames: injectDetails.allFrames,
frameIds: null,
},
files: null,
injectImmediately: true,

View File

@ -522,12 +522,20 @@ export class BrowserApi {
},
): Promise<unknown> {
if (BrowserApi.isManifestVersion(3)) {
const target: chrome.scripting.InjectionTarget = {
tabId,
};
if (typeof details.frameId === "number") {
target.frameIds = [details.frameId];
}
if (!target.frameIds?.length && details.allFrames) {
target.allFrames = details.allFrames;
}
return chrome.scripting.executeScript({
target: {
tabId: tabId,
allFrames: details.allFrames,
frameIds: details.frameId ? [details.frameId] : null,
},
target,
files: details.file ? [details.file] : null,
injectImmediately: details.runAt === "document_start",
world: scriptingApiDetails?.world || "ISOLATED",

View File

@ -86,7 +86,7 @@ class BrowserPopupUtils {
* Identifies if the background page needs to be initialized.
*/
static backgroundInitializationRequired() {
return !BrowserApi.getBackgroundPage();
return !BrowserApi.getBackgroundPage() || BrowserApi.isManifestVersion(3);
}
/**

View File

@ -0,0 +1,4 @@
<!--
Empty file set for the Safari build process for mv3 to ensure backwards compatibility with mv2.
Will be removed once we fully migrate Safari to mv3.
-->

View File

@ -0,0 +1,2 @@
// Empty file set for the Safari build process for mv3 to ensure backwards compatibility with mv2.
// Will be removed once we fully migrate Safari to mv3.

View File

@ -13,6 +13,52 @@ if (process.env.NODE_ENV == null) {
}
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);
}
console.log(`Building Manifest Version ${manifestVersion} app`);
@ -133,7 +179,11 @@ const plugins = [
new CopyWebpackPlugin({
patterns: [
manifestVersion == 3
? { from: "./src/manifest.v3.json", to: "manifest.json" }
? {
from: "./src/manifest.v3.json",
to: "manifest.json",
transform: (content) => modifyManifestV3(content),
}
: "./src/manifest.json",
{ from: "./src/managed_schema.json", to: "managed_schema.json" },
{ from: "./src/_locales", to: "_locales" },
@ -362,6 +412,20 @@ if (manifestVersion == 2) {
plugins: [...requiredPlugins],
};
// 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);
}