mirror of
https://github.com/bitwarden/browser.git
synced 2025-01-02 18:17:46 +01:00
[PM-5881] Adjust usage of the chrome.extension.getViews
API to ensure expected behavior in mv3 is not modified (#7842)
* [PM-5742] Rework Usage of Extension APIs that Cannot be Called with the Background Service Worker * [PM-5742] Implementing jest tests for the updated BrowserApi methods * [PM-5742] Implementing jest tests to validate logic within added API calls * [PM-5742] Implementing jest tests to validate logic within added API calls * [PM-5742] Fixing broken Jest tests * [PM-5742] Fixing linter error * [PM-5881] Adjust usage of the `chrome.extension.getViews` API to ensure expected behavior in manifest v3 * [PM-5881] Reworking how we handle early returns from `reloadOpenWindows` * [PM-5881] Implementing jest test to validate changes within BrowserApi.reloadOpenWindows
This commit is contained in:
parent
34a8d9af86
commit
968355d820
@ -219,6 +219,18 @@ describe("BrowserApi", () => {
|
|||||||
window.location.reload = reload;
|
window.location.reload = reload;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("skips reloading any windows if no views can be found", () => {
|
||||||
|
Object.defineProperty(window, "location", {
|
||||||
|
value: { reload: jest.fn(), href: "chrome-extension://id-value/background.html" },
|
||||||
|
writable: true,
|
||||||
|
});
|
||||||
|
chrome.extension.getViews = jest.fn().mockReturnValue([]);
|
||||||
|
|
||||||
|
BrowserApi.reloadOpenWindows();
|
||||||
|
|
||||||
|
expect(window.location.reload).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
it("reloads all open windows", () => {
|
it("reloads all open windows", () => {
|
||||||
Object.defineProperty(window, "location", {
|
Object.defineProperty(window, "location", {
|
||||||
value: { reload: jest.fn(), href: "chrome-extension://id-value/index.html" },
|
value: { reload: jest.fn(), href: "chrome-extension://id-value/index.html" },
|
||||||
|
@ -404,8 +404,12 @@ export class BrowserApi {
|
|||||||
* @param exemptCurrentHref - Whether to exempt the current window location from the reload.
|
* @param exemptCurrentHref - Whether to exempt the current window location from the reload.
|
||||||
*/
|
*/
|
||||||
static reloadOpenWindows(exemptCurrentHref = false) {
|
static reloadOpenWindows(exemptCurrentHref = false) {
|
||||||
const currentHref = window?.location.href;
|
|
||||||
const views = BrowserApi.getExtensionViews();
|
const views = BrowserApi.getExtensionViews();
|
||||||
|
if (!views.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentHref = window.location.href;
|
||||||
views
|
views
|
||||||
.filter((w) => w.location.href != null && !w.location.href.includes("background.html"))
|
.filter((w) => w.location.href != null && !w.location.href.includes("background.html"))
|
||||||
.filter((w) => !exemptCurrentHref || w.location.href !== currentHref)
|
.filter((w) => !exemptCurrentHref || w.location.href !== currentHref)
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import { DeviceType } from "@bitwarden/common/enums";
|
import { DeviceType } from "@bitwarden/common/enums";
|
||||||
|
|
||||||
|
import { BrowserApi } from "../browser/browser-api";
|
||||||
|
|
||||||
import BrowserPlatformUtilsService from "./browser-platform-utils.service";
|
import BrowserPlatformUtilsService from "./browser-platform-utils.service";
|
||||||
|
|
||||||
describe("Browser Utils Service", () => {
|
describe("Browser Utils Service", () => {
|
||||||
@ -91,41 +93,24 @@ describe("Browser Utils Service", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("isViewOpen", () => {
|
describe("isViewOpen", () => {
|
||||||
beforeEach(() => {
|
it("returns false if a heartbeat response is not received", async () => {
|
||||||
globalThis.chrome = {
|
BrowserApi.sendMessageWithResponse = jest.fn().mockResolvedValueOnce(undefined);
|
||||||
// eslint-disable-next-line
|
|
||||||
// @ts-ignore
|
const isViewOpen = await browserPlatformUtilsService.isViewOpen();
|
||||||
extension: {
|
|
||||||
getViews: jest.fn(),
|
expect(isViewOpen).toBe(false);
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("returns true if the user is on Firefox and the sidebar is open", async () => {
|
it("returns true if a heartbeat response is received", async () => {
|
||||||
chrome.extension.getViews = jest.fn().mockReturnValueOnce([window]);
|
BrowserApi.sendMessageWithResponse = jest
|
||||||
jest
|
.fn()
|
||||||
.spyOn(browserPlatformUtilsService, "getDevice")
|
.mockImplementationOnce((subscriber) =>
|
||||||
.mockReturnValueOnce(DeviceType.FirefoxExtension);
|
Promise.resolve((subscriber === "checkVaultPopupHeartbeat") as any),
|
||||||
|
);
|
||||||
|
|
||||||
const result = await browserPlatformUtilsService.isViewOpen();
|
const isViewOpen = await browserPlatformUtilsService.isViewOpen();
|
||||||
|
|
||||||
expect(result).toBe(true);
|
expect(isViewOpen).toBe(true);
|
||||||
});
|
|
||||||
|
|
||||||
it("returns true if a extension view is open as a tab", async () => {
|
|
||||||
chrome.extension.getViews = jest.fn().mockReturnValueOnce([window]);
|
|
||||||
|
|
||||||
const result = await browserPlatformUtilsService.isViewOpen();
|
|
||||||
|
|
||||||
expect(result).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("returns false if no extension view is open", async () => {
|
|
||||||
chrome.extension.getViews = jest.fn().mockReturnValue([]);
|
|
||||||
|
|
||||||
const result = await browserPlatformUtilsService.isViewOpen();
|
|
||||||
|
|
||||||
expect(result).toBe(false);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -150,23 +150,13 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies if the vault popup is currently open. This is done by sending a
|
||||||
|
* message to the popup and waiting for a response. If a response is received,
|
||||||
|
* the view is open.
|
||||||
|
*/
|
||||||
async isViewOpen(): Promise<boolean> {
|
async isViewOpen(): Promise<boolean> {
|
||||||
if (await BrowserApi.isPopupOpen()) {
|
return Boolean(await BrowserApi.sendMessageWithResponse("checkVaultPopupHeartbeat"));
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isSafari()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Opera has "sidebar_panel" as a ViewType but doesn't currently work
|
|
||||||
if (this.isFirefox() && BrowserApi.getExtensionViews({ type: "sidebar" }).length > 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Opera sidebar has type of "tab" (will stick around for a while after closing sidebar)
|
|
||||||
const tabOpen = BrowserApi.getExtensionViews({ type: "tab" }).length > 0;
|
|
||||||
return tabOpen;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lockTimeout(): number {
|
lockTimeout(): number {
|
||||||
|
@ -6,6 +6,7 @@ import { LogService as LogServiceAbstraction } from "@bitwarden/common/platform/
|
|||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
import { ConfigService } from "@bitwarden/common/platform/services/config/config.service";
|
import { ConfigService } from "@bitwarden/common/platform/services/config/config.service";
|
||||||
|
|
||||||
|
import { BrowserApi } from "../../platform/browser/browser-api";
|
||||||
import BrowserPopupUtils from "../../platform/popup/browser-popup-utils";
|
import BrowserPopupUtils from "../../platform/popup/browser-popup-utils";
|
||||||
import { BrowserStateService as StateServiceAbstraction } from "../../platform/services/abstractions/browser-state.service";
|
import { BrowserStateService as StateServiceAbstraction } from "../../platform/services/abstractions/browser-state.service";
|
||||||
|
|
||||||
@ -52,6 +53,25 @@ export class InitService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.configService.init();
|
this.configService.init();
|
||||||
|
this.setupVaultPopupHeartbeat();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up a runtime message listener to indicate to the background
|
||||||
|
* script that the extension popup is open in some manner.
|
||||||
|
*/
|
||||||
|
private setupVaultPopupHeartbeat() {
|
||||||
|
const respondToHeartbeat = (
|
||||||
|
message: { command: string },
|
||||||
|
_sender: chrome.runtime.MessageSender,
|
||||||
|
sendResponse: (response?: any) => void,
|
||||||
|
) => {
|
||||||
|
if (message?.command === "checkVaultPopupHeartbeat") {
|
||||||
|
sendResponse(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BrowserApi.messageListener("vaultPopupHeartbeat", respondToHeartbeat);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user