| // Copyright 2019 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'chrome://resources/cr_elements/cr_icon/cr_icon.js'; |
| import 'chrome://resources/cr_elements/icons.html.js'; |
| import '/strings.m.js'; |
| |
| import {I18nMixinLit} from 'chrome://resources/cr_elements/i18n_mixin_lit.js'; |
| import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; |
| import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js'; |
| |
| import {getCss} from './app.css.js'; |
| import {getHtml} from './app.html.js'; |
| import type {BrowserSwitchProxy} from './browser_switch_proxy.js'; |
| import {BrowserSwitchProxyImpl} from './browser_switch_proxy.js'; |
| |
| const MS_PER_SECOND: number = 1000; |
| |
| enum LaunchError { |
| GENERIC_ERROR = 'genericError', |
| PROTOCOL_ERROR = 'protocolError', |
| } |
| |
| const BrowserSwitchAppElementBase = I18nMixinLit(CrLitElement); |
| |
| export class BrowserSwitchAppElement extends BrowserSwitchAppElementBase { |
| static get is() { |
| return 'browser-switch-app'; |
| } |
| |
| static override get styles() { |
| return getCss(); |
| } |
| |
| override render() { |
| return getHtml.bind(this)(); |
| } |
| |
| static override get properties() { |
| return { |
| /** |
| * URL to launch in the alternative browser. |
| */ |
| url_: {type: String}, |
| |
| /** |
| * Error message, or empty string if no error has occurred (yet). |
| */ |
| error_: {type: String}, |
| |
| /** |
| * Countdown displayed to the user, number of seconds until launching. If |
| * 0 or less, doesn't get displayed at all. |
| */ |
| secondCounter_: {type: Number}, |
| }; |
| } |
| |
| private url_: string = |
| new URLSearchParams(window.location.search).get('url') || ''; |
| private error_: string = ''; |
| private secondCounter_: number = 0; |
| |
| override connectedCallback() { |
| super.connectedCallback(); |
| |
| // If '?done=...' is specified in the URL, this tab was-reopened, or the |
| // entire browser was closed by LBS and re-opened. In that case, go to NTP |
| // instead. |
| const done = (new URLSearchParams(window.location.search)).has('done'); |
| if (done) { |
| getProxy().gotoNewTabPage(); |
| return; |
| } |
| |
| // Sanity check the URL to make sure nothing really funky is going on. |
| const anchor = document.createElement('a'); |
| anchor.href = this.url_; |
| if (!/^(file|http|https):$/.test(anchor.protocol)) { |
| this.error_ = LaunchError.PROTOCOL_ERROR; |
| return; |
| } |
| |
| const milliseconds = loadTimeData.getInteger('launchDelay'); |
| setTimeout(this.launchAndCloseTab_.bind(this), milliseconds); |
| this.startCountdown_(Math.floor(milliseconds / 1000)); |
| } |
| |
| private launchAndCloseTab_() { |
| // Mark this page with '?done=...' so that restoring the tab doesn't |
| // immediately re-trigger LBS. |
| history.pushState({}, '', '/?done=true'); |
| |
| getProxy().launchAlternativeBrowserAndCloseTab(this.url_).catch(() => { |
| this.error_ = LaunchError.GENERIC_ERROR; |
| }); |
| } |
| |
| private startCountdown_(seconds: number) { |
| this.secondCounter_ = seconds; |
| const intervalId = setInterval(() => { |
| this.secondCounter_--; |
| if (this.secondCounter_ <= 0) { |
| clearInterval(intervalId); |
| } |
| }, 1 * MS_PER_SECOND); |
| } |
| |
| protected computeTitle_(): string { |
| if (this.error_) { |
| return this.i18n('errorTitle', getAltBrowserName()); |
| } |
| if (this.secondCounter_ > 0) { |
| return this.i18n( |
| 'countdownTitle', this.secondCounter_, getAltBrowserName()); |
| } |
| return this.i18n('openingTitle', getAltBrowserName()); |
| } |
| |
| protected computeDescription_(): TrustedHTML { |
| if (this.error_) { |
| return this.i18nAdvanced(this.error_, { |
| substitutions: [getUrlHostname(this.url_), getAltBrowserName()], |
| }); |
| } |
| return this.i18nAdvanced('description', { |
| substitutions: [getUrlHostname(this.url_), getAltBrowserName()], |
| }); |
| } |
| } |
| |
| customElements.define(BrowserSwitchAppElement.is, BrowserSwitchAppElement); |
| |
| function getAltBrowserName(): string { |
| return loadTimeData.getString('altBrowserName'); |
| } |
| |
| function getUrlHostname(url: string): string { |
| const anchor = document.createElement('a'); |
| anchor.href = url; |
| // Return entire url if parsing failed (which means the URL is bogus). |
| return anchor.hostname || encodeURI(url); |
| } |
| |
| function getProxy(): BrowserSwitchProxy { |
| return BrowserSwitchProxyImpl.getInstance(); |
| } |