From cc31f1efc0d84e72197f501f9e715ce7a87403b9 Mon Sep 17 00:00:00 2001 From: Andreas Coroiu Date: Fri, 28 Apr 2023 09:20:42 +0200 Subject: [PATCH] [EC-598] feat: close popout directly from bg script --- .../src/fido2/popup/fido2/fido2.component.ts | 2 - .../src/popup/services/popup-utils.service.ts | 104 +++++++++++------- .../browser-fido2-user-interface.service.ts | 10 +- 3 files changed, 71 insertions(+), 45 deletions(-) diff --git a/apps/browser/src/fido2/popup/fido2/fido2.component.ts b/apps/browser/src/fido2/popup/fido2/fido2.component.ts index 7cd1616dcbf..b9ada0d9b58 100644 --- a/apps/browser/src/fido2/popup/fido2/fido2.component.ts +++ b/apps/browser/src/fido2/popup/fido2/fido2.component.ts @@ -103,8 +103,6 @@ export class Fido2Component implements OnInit, OnDestroy { return cipher.decrypt(); }) ); - } else if (message.type === "CloseRequest") { - window.close(); } return { diff --git a/apps/browser/src/popup/services/popup-utils.service.ts b/apps/browser/src/popup/services/popup-utils.service.ts index c91038b7d00..ca3b5ef7583 100644 --- a/apps/browser/src/popup/services/popup-utils.service.ts +++ b/apps/browser/src/popup/services/popup-utils.service.ts @@ -3,6 +3,16 @@ import { fromEvent, Subscription } from "rxjs"; import { BrowserApi } from "../../browser/browserApi"; +export type Popout = + | { + type: "window"; + window: chrome.windows.Window; + } + | { + type: "tab"; + tab: chrome.tabs.Tab; + }; + @Injectable() export class PopupUtilsService { private unloadSubscription: Subscription; @@ -45,49 +55,69 @@ export class PopupUtilsService { } } - popOut(win: Window, href: string = null, options: { center?: boolean } = {}): void { - if (href === null) { - href = win.location.href; - } + popOut(win: Window, href: string = null, options: { center?: boolean } = {}): Promise { + return new Promise((resolve, reject) => { + if (href === null) { + href = win.location.href; + } - if (typeof chrome !== "undefined" && chrome.windows && chrome.windows.create) { - if (href.indexOf("?uilocation=") > -1) { + if (typeof chrome !== "undefined" && chrome.windows && chrome.windows.create) { + if (href.indexOf("?uilocation=") > -1) { + href = href + .replace("uilocation=popup", "uilocation=popout") + .replace("uilocation=tab", "uilocation=popout") + .replace("uilocation=sidebar", "uilocation=popout"); + } else { + const hrefParts = href.split("#"); + href = + hrefParts[0] + "?uilocation=popout" + (hrefParts.length > 0 ? "#" + hrefParts[1] : ""); + } + + const bodyRect = document.querySelector("body").getBoundingClientRect(); + const width = Math.round(bodyRect.width ? bodyRect.width + 60 : 375); + const height = Math.round(bodyRect.height || 600); + const top = options.center ? Math.round((screen.height - height) / 2) : undefined; + const left = options.center ? Math.round((screen.width - width) / 2) : undefined; + chrome.windows.create( + { + url: href, + type: "popup", + width, + height, + top, + left, + }, + (window) => resolve({ type: "window", window }) + ); + + if (win && this.inPopup(win)) { + BrowserApi.closePopup(win); + } + } else if (typeof chrome !== "undefined" && chrome.tabs && chrome.tabs.create) { href = href - .replace("uilocation=popup", "uilocation=popout") - .replace("uilocation=tab", "uilocation=popout") - .replace("uilocation=sidebar", "uilocation=popout"); + .replace("uilocation=popup", "uilocation=tab") + .replace("uilocation=popout", "uilocation=tab") + .replace("uilocation=sidebar", "uilocation=tab"); + chrome.tabs.create( + { + url: href, + }, + (tab) => resolve({ type: "tab", tab }) + ); } else { - const hrefParts = href.split("#"); - href = - hrefParts[0] + "?uilocation=popout" + (hrefParts.length > 0 ? "#" + hrefParts[1] : ""); + reject(new Error("Cannot open tab or window")); } + }); + } - const bodyRect = document.querySelector("body").getBoundingClientRect(); - const width = Math.round(bodyRect.width ? bodyRect.width + 60 : 375); - const height = Math.round(bodyRect.height || 600); - const top = options.center ? Math.round((screen.height - height) / 2) : undefined; - const left = options.center ? Math.round((screen.width - width) / 2) : undefined; - chrome.windows.create({ - url: href, - type: "popup", - width, - height, - top, - left, - }); - - if (win && this.inPopup(win)) { - BrowserApi.closePopup(win); + closePopOut(popout: Popout): Promise { + return new Promise((resolve) => { + if (popout.type === "window") { + chrome.windows.remove(popout.window.id, resolve); + } else { + chrome.tabs.remove(popout.tab.id, resolve); } - } else if (typeof chrome !== "undefined" && chrome.tabs && chrome.tabs.create) { - href = href - .replace("uilocation=popup", "uilocation=tab") - .replace("uilocation=popout", "uilocation=tab") - .replace("uilocation=sidebar", "uilocation=tab"); - chrome.tabs.create({ - url: href, - }); - } + }); } /** diff --git a/apps/browser/src/services/fido2/browser-fido2-user-interface.service.ts b/apps/browser/src/services/fido2/browser-fido2-user-interface.service.ts index d420478a849..90d0d3a358e 100644 --- a/apps/browser/src/services/fido2/browser-fido2-user-interface.service.ts +++ b/apps/browser/src/services/fido2/browser-fido2-user-interface.service.ts @@ -20,7 +20,7 @@ import { import { Utils } from "@bitwarden/common/misc/utils"; import { BrowserApi } from "../../browser/browserApi"; -import { PopupUtilsService } from "../../popup/services/popup-utils.service"; +import { Popout, PopupUtilsService } from "../../popup/services/popup-utils.service"; const BrowserFido2MessageName = "BrowserFido2UserInterfaceServiceMessage"; @@ -89,9 +89,6 @@ export type BrowserFido2Message = { sessionId: string } & ( type: "AbortResponse"; fallbackRequested: boolean; } - | { - type: "CloseRequest"; - } ); export class BrowserFido2UserInterfaceService implements Fido2UserInterfaceServiceAbstraction { @@ -120,6 +117,7 @@ export class BrowserFido2UserInterfaceSession implements Fido2UserInterfaceSessi ); private connected$ = new BehaviorSubject(false); private destroy$ = new Subject(); + private popout?: Popout; private constructor( private readonly popupUtilsService: PopupUtilsService, @@ -252,7 +250,7 @@ export class BrowserFido2UserInterfaceSession implements Fido2UserInterfaceSessi } async close() { - await this.send({ type: "CloseRequest", sessionId: this.sessionId }); + this.popupUtilsService.closePopOut(this.popout); this.closed = true; this.destroy$.next(); this.destroy$.complete(); @@ -290,7 +288,7 @@ export class BrowserFido2UserInterfaceSession implements Fido2UserInterfaceSessi } const queryParams = new URLSearchParams({ sessionId: this.sessionId }).toString(); - this.popupUtilsService.popOut( + this.popout = await this.popupUtilsService.popOut( null, `popup/index.html?uilocation=popout#/fido2?${queryParams}`, { center: true }