blob: b617c4a516239b9ce2833a2ced105c261473b908 [file] [log] [blame]
/* Copyright 2017 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_button/cr_button.js';
import 'chrome://resources/cr_elements/cr_icon/cr_icon.js';
import 'chrome://resources/cr_elements/icons.html.js';
import 'chrome://resources/cr_components/localized_link/localized_link.js';
import '/icons.html.js';
import '/strings.m.js';
import {I18nMixinLit} from 'chrome://resources/cr_elements/i18n_mixin_lit.js';
import {WebUiListenerMixinLit} from 'chrome://resources/cr_elements/web_ui_listener_mixin_lit.js';
import {assert, assertNotReached} from 'chrome://resources/js/assert.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 './sync_confirmation_app.css.js';
import {getHtml} from './sync_confirmation_app.html.js';
import {ScreenMode} from './sync_confirmation_browser_proxy.js';
import type {SyncBenefit, SyncConfirmationBrowserProxy} from './sync_confirmation_browser_proxy.js';
import {SyncConfirmationBrowserProxyImpl} from './sync_confirmation_browser_proxy.js';
interface AccountInfo {
src: string;
showEnterpriseBadge: boolean;
}
const SyncConfirmationAppElementBase =
WebUiListenerMixinLit(I18nMixinLit(CrLitElement));
export class SyncConfirmationAppElement extends SyncConfirmationAppElementBase {
static get is() {
return 'sync-confirmation-app';
}
static override get styles() {
return getCss();
}
override render() {
return getHtml.bind(this)();
}
static override get properties() {
return {
accountImageSrc_: {type: String},
anyButtonClicked_: {type: Boolean},
isModalDialog_: {type: Boolean},
showEnterpriseBadge_: {type: Boolean},
syncBenefitsList_: {type: Array},
/**
* Whether to show the new UI for Browser Sync Settings and which include
* sublabel and Apps toggle shared between Ash and Lacros.
*/
useClickableSyncInfoDesc_: {type: Boolean},
/** Determines the screen mode. */
screenMode_: {type: Number},
};
}
protected accountImageSrc_: string =
loadTimeData.getString('accountPictureUrl');
protected anyButtonClicked_: boolean = false;
protected isModalDialog_: boolean = loadTimeData.getBoolean('isModalDialog');
private showEnterpriseBadge_: boolean = false;
protected syncBenefitsList_: SyncBenefit[] =
JSON.parse(loadTimeData.getString('syncBenefitsList'));
private syncConfirmationBrowserProxy_: SyncConfirmationBrowserProxy =
SyncConfirmationBrowserProxyImpl.getInstance();
protected useClickableSyncInfoDesc_: boolean =
loadTimeData.getBoolean('useClickableSyncInfoDesc');
private screenMode_: ScreenMode = ScreenMode.PENDING;
override connectedCallback() {
super.connectedCallback();
this.addWebUiListener(
'account-info-changed', this.handleAccountInfoChanged_.bind(this));
this.addWebUiListener(
'screen-mode-changed', this.handleScreenModeChanged_.bind(this));
this.syncConfirmationBrowserProxy_.requestAccountInfo();
}
protected onConfirm_(e: Event) {
this.anyButtonClicked_ = true;
this.syncConfirmationBrowserProxy_.confirm(
this.getConsentDescription_(),
this.getConsentConfirmation_(e.composedPath() as HTMLElement[]),
this.screenMode_);
}
protected onUndo_() {
this.anyButtonClicked_ = true;
this.syncConfirmationBrowserProxy_.undo(this.screenMode_);
}
protected onGoToSettings_(e: Event) {
this.anyButtonClicked_ = true;
this.syncConfirmationBrowserProxy_.goToSettings(
this.getConsentDescription_(),
this.getConsentConfirmation_(e.composedPath() as HTMLElement[]),
this.screenMode_);
}
/**
* @param path Path of the click event. Must contain a consent confirmation
* element.
* @return The text of the consent confirmation element.
*/
private getConsentConfirmation_(path: HTMLElement[]): string {
for (const element of path) {
if (element.nodeType !== Node.DOCUMENT_FRAGMENT_NODE &&
element.hasAttribute('consent-confirmation')) {
return element.textContent!.trim();
}
}
assertNotReached('No consent confirmation element found.');
}
/** @return Text of the consent description elements. */
private getConsentDescription_(): string[] {
const consentDescription =
Array.from(this.shadowRoot!.querySelectorAll('[consent-description]'))
.filter(
element => element.getBoundingClientRect().width *
element.getBoundingClientRect().height >
0)
.map(
element => element.hasAttribute('localized-string') ?
element.getAttribute('localized-string')! :
element.textContent!.trim());
assert(consentDescription.length);
return consentDescription;
}
// Called when the account information changes: it might be either the image
// or determined mode of screen restriction (derived from the
// canShowHistorySyncOptInsWithoutMinorModeRestriction capability).
private handleAccountInfoChanged_(accountInfo: AccountInfo) {
this.accountImageSrc_ = accountInfo.src;
this.showEnterpriseBadge_ = accountInfo.showEnterpriseBadge;
}
private handleScreenModeChanged_(screenMode: ScreenMode) {
this.screenMode_ = screenMode;
}
protected getConfirmButtonClass_(): string {
// TODO(b/326912202): Replace with observer pattern on screenMode_.
switch (this.screenMode_) {
case ScreenMode.UNRESTRICTED:
return 'action-button';
case ScreenMode.PENDING:
return 'visibility-hidden';
default:
// All other cases have no special appearance.
return '';
}
}
protected getNotNowButtonClass_(): string {
return this.screenMode_ === ScreenMode.PENDING ? 'visibility-hidden' : '';
}
protected isPending_(): boolean {
return this.screenMode_ === ScreenMode.PENDING;
}
protected shouldHideEnterpriseBadge_(): boolean {
return !this.showEnterpriseBadge_ ||
this.screenMode_ === ScreenMode.PENDING;
}
/**
* Called when the link to the device's sync settings is clicked.
*/
protected onDisclaimerClicked_(event: CustomEvent<{event: Event}>) {
// Prevent the default link click behavior.
event.detail.event.preventDefault();
// Programmatically open device's sync settings.
this.syncConfirmationBrowserProxy_.openDeviceSyncSettings();
}
/**
* Returns the name of class to apply on some tags to enable animations.
* May be empty if no animations should be added.
*/
protected getAnimationClass_(): string {
return !this.isModalDialog_ ? 'fade-in' : '';
}
/**
* Returns either "dialog" or an empty string.
*
* The returned value is intended to be added as a class on the root tags of
* the element. Some styles from `tangible_sync_style_shared.css` rely on the
* presence of this "dialog" class.
*/
protected getMaybeDialogClass_(): string {
return this.isModalDialog_ ? 'dialog' : '';
}
}
declare global {
interface HTMLElementTagNameMap {
'sync-confirmation-app': SyncConfirmationAppElement;
}
}
customElements.define(
SyncConfirmationAppElement.is, SyncConfirmationAppElement);