1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-15 15:53:27 +00:00

[PM-22178] Add WebBrowserInteractionService (#15261)

* add `WebBrowserInteractionService` and check for the extension observable

* update checkForExtension to use observables rather than window timeouts

* add open extension to WebBrowserInteractionService

* add at-risk-passwords to `PopupPageUrls`

* refactor `PopupPageUrls` to `ExtensionPageUrls`

* add test for passing a page

* refactor `Default` to `Index`

* clean up complete/next issue using `race`

* refactor page to url

* continue listening for messages from the extension after subscribed

* mark risk passwords a deprecated

* remove takeUntilDestroyed

* add back `takeUntilDestroyed` for internal `messages`

* removed null filter - unneeded

* add tap to send message for extension installation

* add check for accepted urls to prevent any bad actors from opening the extension
This commit is contained in:
Nick Krantz
2025-06-27 12:55:20 -05:00
committed by GitHub
parent 4e3d83147e
commit cb36b96855
9 changed files with 250 additions and 2 deletions

View File

@@ -1,3 +1,5 @@
import { ExtensionPageUrls } from "@bitwarden/common/vault/enums";
type ContentMessageWindowData = {
command: string;
lastpass?: boolean;
@@ -5,6 +7,7 @@ type ContentMessageWindowData = {
state?: string;
data?: string;
remember?: boolean;
url?: ExtensionPageUrls;
};
type ContentMessageWindowEventParams = {
data: ContentMessageWindowData;

View File

@@ -1,3 +1,4 @@
import { ExtensionPageUrls } from "@bitwarden/common/vault/enums";
import { VaultMessages } from "@bitwarden/common/vault/enums/vault-messages.enum";
import {
@@ -18,6 +19,8 @@ const windowMessageHandlers: ContentMessageWindowEventHandlers = {
duoResult: ({ data, referrer }: { data: any; referrer: string }) =>
handleDuoResultMessage(data, referrer),
[VaultMessages.OpenAtRiskPasswords]: () => handleOpenAtRiskPasswordsMessage(),
[VaultMessages.OpenBrowserExtensionToUrl]: ({ data }) =>
handleOpenBrowserExtensionToUrlMessage(data),
};
/**
@@ -73,10 +76,15 @@ function handleWebAuthnResultMessage(data: ContentMessageWindowData, referrer: s
sendExtensionRuntimeMessage({ command, data: data.data, remember, referrer });
}
/** @deprecated use {@link handleOpenBrowserExtensionToUrlMessage} */
function handleOpenAtRiskPasswordsMessage() {
sendExtensionRuntimeMessage({ command: VaultMessages.OpenAtRiskPasswords });
}
function handleOpenBrowserExtensionToUrlMessage({ url }: { url?: ExtensionPageUrls }) {
sendExtensionRuntimeMessage({ command: VaultMessages.OpenBrowserExtensionToUrl, url });
}
/**
* Handles the window message event.
*

View File

@@ -191,6 +191,7 @@ import { InternalFolderService as InternalFolderServiceAbstraction } from "@bitw
import { SearchService as SearchServiceAbstraction } from "@bitwarden/common/vault/abstractions/search.service";
import { TotpService as TotpServiceAbstraction } from "@bitwarden/common/vault/abstractions/totp.service";
import { VaultSettingsService as VaultSettingsServiceAbstraction } from "@bitwarden/common/vault/abstractions/vault-settings/vault-settings.service";
import { ExtensionPageUrls } from "@bitwarden/common/vault/enums";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import {
DefaultEndUserNotificationService,
@@ -1694,14 +1695,44 @@ export default class MainBackground {
// Set route of the popup before attempting to open it.
// If the vault is locked, this won't have an effect as the auth guards will
// redirect the user to the login page.
await browserAction.setPopup({ popup: "popup/index.html#/at-risk-passwords" });
await browserAction.setPopup({ popup: ExtensionPageUrls.AtRiskPasswords });
await this.openPopup();
} finally {
// Reset the popup route to the default route so any subsequent
// popup openings will not open to the at-risk-passwords page.
await browserAction.setPopup({
popup: "popup/index.html#/",
popup: ExtensionPageUrls.Index,
});
}
}
/**
* Opens the popup to the given page
* @default ExtensionPageUrls.Index
*/
async openTheExtensionToPage(url: ExtensionPageUrls = ExtensionPageUrls.Index) {
const isValidUrl = Object.values(ExtensionPageUrls).includes(url);
// If a non-defined URL is provided, return early.
if (!isValidUrl) {
return;
}
const browserAction = BrowserApi.getBrowserAction();
try {
// Set route of the popup before attempting to open it.
// If the vault is locked, this won't have an effect as the auth guards will
// redirect the user to the login page.
await browserAction.setPopup({ popup: url });
await this.openPopup();
} finally {
// Reset the popup route to the default route so any subsequent
// popup openings will not open to the at-risk-passwords page.
await browserAction.setPopup({
popup: ExtensionPageUrls.Index,
});
}
}

View File

@@ -296,6 +296,10 @@ export default class RuntimeBackground {
await this.main.openAtRisksPasswordsPage();
this.announcePopupOpen();
break;
case VaultMessages.OpenBrowserExtensionToUrl:
await this.main.openTheExtensionToPage(msg.url);
this.announcePopupOpen();
break;
case "bgUpdateContextMenu":
case "editedCipher":
case "addedCipher":