1// Copyright (C) 2025 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import {defer} from './deferred'; 16 17const DEFAULT_TIMEOUT_MS = 30_000; 18 19export interface PopupArgs { 20 url: string; 21 width?: number; 22 height?: number; 23 timeoutMs?: number; // Defaults to DEFAULT_TIMEOUT_MS. 24} 25 26/** 27 * Opens a URL in a new popup-style tab. 28 * @returns A promise for a result that is resolved successfully if the popup 29 * closes, or unsuccessfully if popups are blocked or the timeout expires. 30 */ 31export function showPopupWindow(args: PopupArgs): Promise<boolean> { 32 const popup = window.open( 33 args.url, 34 '_blank', 35 `width=${args.width ?? 500},height=${args.height ?? 500},` + 36 'scrollbars=no,resizable=no,status=no,location=no,toolbar=no,menubar=no', 37 ); 38 const promise = defer<boolean>(); 39 if (popup === null) { 40 promise.resolve(false); 41 return promise; 42 } 43 const deadline = performance.now() + (args.timeoutMs ?? DEFAULT_TIMEOUT_MS); 44 const interval = setInterval(() => { 45 if (popup.closed) { 46 clearInterval(interval); 47 promise.resolve(true); 48 } 49 if (performance.now() >= deadline) { 50 clearInterval(interval); 51 promise.resolve(false); 52 } 53 }, 500); 54 return promise; 55} 56