| // Copyright 2021 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/ash/common/cr_elements/cr_button/cr_button.js'; |
| import 'chrome://resources/ash/common/cr_elements/cr_dialog/cr_dialog.js'; |
| import 'chrome://resources/polymer/v3_0/paper-tooltip/paper-tooltip.js'; |
| import './base_page.js'; |
| import './shimless_rma_shared.css.js'; |
| |
| import {CrDialogElement} from 'chrome://resources/ash/common/cr_elements/cr_dialog/cr_dialog.js'; |
| import {I18nMixin} from 'chrome://resources/ash/common/cr_elements/i18n_mixin.js'; |
| import {assert} from 'chrome://resources/js/assert.js'; |
| import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; |
| |
| import {createCustomEvent, OPEN_LOGS_DIALOG, OpenLogsDialogEvent} from './events.js'; |
| import {getShimlessRmaService} from './mojo_interface_provider.js'; |
| import {PowerCableStateObserverReceiver, ShimlessRmaServiceInterface, ShutdownMethod} from './shimless_rma.mojom-webui.js'; |
| import {executeThenTransitionState, focusPageTitle} from './shimless_rma_util.js'; |
| import {getTemplate} from './wrapup_repair_complete_page.html.js'; |
| |
| declare global { |
| interface HTMLElementEventMap { |
| [OPEN_LOGS_DIALOG]: OpenLogsDialogEvent; |
| } |
| } |
| |
| /** |
| * @fileoverview |
| * 'wrapup-repair-complete-page' is the main landing page for the shimless rma |
| * process. |
| */ |
| |
| const WrapupRepairCompletePageBase = I18nMixin(PolymerElement); |
| |
| /** |
| * Supported options for finishing RMA. |
| */ |
| enum FinishRmaOption { |
| SHUTDOWN = 'shutdown', |
| REBOOT = 'reboot', |
| } |
| |
| export class WrapupRepairCompletePage extends WrapupRepairCompletePageBase { |
| static get is() { |
| return 'wrapup-repair-complete-page' as const; |
| } |
| |
| static get template() { |
| return getTemplate(); |
| } |
| |
| static get properties() { |
| return { |
| /** |
| * Set by shimless_rma.ts. |
| */ |
| allButtonsDisabled: { |
| reflectToAttribute: true, |
| type: Boolean, |
| }, |
| |
| /** |
| * Keeps the shutdown and reboot buttons disabled after the response from |
| * the service to prevent successive shutdown or reboot attempts. |
| */ |
| shutdownButtonsDisabled: { |
| type: Boolean, |
| value: false, |
| }, |
| |
| /** |
| * Assume plugged in is true until first observation. |
| */ |
| pluggedIn: { |
| reflectToAttribute: true, |
| type: Boolean, |
| value: true, |
| }, |
| |
| selectedFinishRmaOption: { |
| type: String, |
| value: '', |
| }, |
| |
| /** |
| * This variable needs to remain public because the unit tests need to |
| * check its value. |
| * TODO(b:315002705): Make this property protected and add a test for it. |
| */ |
| batteryTimeoutID: { |
| type: Number, |
| value: -1, |
| }, |
| |
| /** |
| * This variable needs to remain public because the unit tests need to |
| * set it to 0. |
| * TODO(b:315002705): Make this property protected and add a test for it. |
| */ |
| batteryTimeoutInMs: { |
| type: Number, |
| value: 5000, |
| }, |
| }; |
| } |
| |
| allButtonsDisabled: boolean; |
| batteryTimeoutID: number; |
| batteryTimeoutInMs: number; |
| protected shutdownButtonsDisabled: boolean; |
| protected pluggedIn: boolean; |
| protected selectedFinishRmaOption: string; |
| private shimlessRmaService: ShimlessRmaServiceInterface = |
| getShimlessRmaService(); |
| powerCableStateReceiver: PowerCableStateObserverReceiver; |
| |
| constructor() { |
| super(); |
| |
| this.powerCableStateReceiver = new PowerCableStateObserverReceiver(this); |
| |
| this.shimlessRmaService.observePowerCableState( |
| this.powerCableStateReceiver.$.bindNewPipeAndPassRemote()); |
| } |
| |
| override ready() { |
| super.ready(); |
| |
| focusPageTitle(this); |
| } |
| |
| protected onDiagnosticsButtonClick(): void { |
| this.shimlessRmaService.launchDiagnostics(); |
| } |
| |
| protected onShutDownButtonClick(e: Event): void { |
| e.preventDefault(); |
| this.selectedFinishRmaOption = FinishRmaOption.SHUTDOWN; |
| this.shimlessRmaService.getPowerwashRequired().then( |
| (result: {powerwashRequired: boolean}) => { |
| this.handlePowerwash(result.powerwashRequired); |
| }); |
| } |
| |
| /** |
| * Handles the response to getPowerwashRequired from the backend. |
| */ |
| private handlePowerwash(powerwashRequired: boolean): void { |
| if (powerwashRequired) { |
| const dialog: CrDialogElement|null = |
| this.shadowRoot!.querySelector('#powerwashDialog'); |
| assert(dialog); |
| if (!dialog.open) { |
| dialog.showModal(); |
| } |
| } else { |
| this.shutDownOrReboot(); |
| } |
| } |
| |
| private shutDownOrReboot(): void { |
| // Keeps the buttons disabled until the device is shutdown. |
| this.shutdownButtonsDisabled = true; |
| |
| if (this.selectedFinishRmaOption === FinishRmaOption.SHUTDOWN) { |
| this.endRmaAndShutdown(); |
| } else { |
| this.endRmaAndReboot(); |
| } |
| } |
| |
| /** |
| * Sends a shutdown request to the backend. |
| */ |
| private endRmaAndShutdown(): void { |
| executeThenTransitionState( |
| this, () => this.shimlessRmaService.endRma(ShutdownMethod.kShutdown)); |
| } |
| |
| protected getPowerwashDescriptionString(): string { |
| return this.selectedFinishRmaOption === FinishRmaOption.SHUTDOWN ? |
| this.i18n('powerwashDialogShutdownDescription') : |
| this.i18n('powerwashDialogRebootDescription'); |
| } |
| |
| protected onPowerwashButtonClick(e: Event): void { |
| e.preventDefault(); |
| const dialog: CrDialogElement|null = |
| this.shadowRoot!.querySelector('#powerwashDialog'); |
| assert(dialog); |
| dialog.close(); |
| this.shutDownOrReboot(); |
| } |
| |
| protected onRebootButtonClick(e: Event): void { |
| e.preventDefault(); |
| this.selectedFinishRmaOption = FinishRmaOption.REBOOT; |
| this.shimlessRmaService.getPowerwashRequired().then( |
| (result: {powerwashRequired: boolean}) => { |
| this.handlePowerwash(result.powerwashRequired); |
| }); |
| } |
| |
| /** |
| * Sends a reboot request to the backend. |
| */ |
| private endRmaAndReboot(): void { |
| executeThenTransitionState( |
| this, () => this.shimlessRmaService.endRma(ShutdownMethod.kReboot)); |
| } |
| |
| protected onRmaLogButtonClick(): void { |
| this.dispatchEvent(createCustomEvent(OPEN_LOGS_DIALOG, {})); |
| } |
| |
| protected onBatteryCutButtonClick(): void { |
| const dialog: CrDialogElement|null = |
| this.shadowRoot!.querySelector('#batteryCutoffDialog'); |
| assert(dialog); |
| if (!dialog.open) { |
| dialog.showModal(); |
| } |
| |
| // This is necessary because after the timeout "this" will be the window, |
| // and not WrapupRepairCompletePage. |
| const cutoffBattery = function(wrapupRepairCompletePage: HTMLElement| |
| null): void { |
| assert(wrapupRepairCompletePage); |
| const dialog: CrDialogElement|null = |
| wrapupRepairCompletePage.shadowRoot!.querySelector( |
| '#batteryCutoffDialog'); |
| assert(dialog); |
| dialog.close(); |
| executeThenTransitionState( |
| wrapupRepairCompletePage, |
| () => (wrapupRepairCompletePage as HTMLElement & { |
| shimlessRmaService: ShimlessRmaServiceInterface, |
| }).shimlessRmaService.endRma(ShutdownMethod.kBatteryCutoff)); |
| }; |
| |
| if (this.batteryTimeoutID === -1) { |
| this.batteryTimeoutID = |
| setTimeout(() => cutoffBattery(this), this.batteryTimeoutInMs); |
| } |
| } |
| |
| private cutoffBattery(): void { |
| const dialog: CrDialogElement|null = |
| this.shadowRoot!.querySelector('#batteryCutoffDialog'); |
| assert(dialog); |
| dialog.close(); |
| executeThenTransitionState( |
| this, |
| () => this.shimlessRmaService.endRma(ShutdownMethod.kBatteryCutoff)); |
| } |
| |
| protected onCutoffShutdownButtonClick(): void { |
| this.cutoffBattery(); |
| } |
| |
| protected closePowerwashDialog(): void { |
| const dialog: CrDialogElement|null = |
| this.shadowRoot!.querySelector('#powerwashDialog'); |
| assert(dialog); |
| dialog.close(); |
| } |
| |
| protected onCutoffCancelClick(): void { |
| this.cancelBatteryCutoff(); |
| } |
| |
| private cancelBatteryCutoff(): void { |
| const batteryCutoffDialog: CrDialogElement|null = |
| this.shadowRoot!.querySelector('#batteryCutoffDialog'); |
| assert(batteryCutoffDialog); |
| batteryCutoffDialog.close(); |
| |
| if (this.batteryTimeoutID !== -1) { |
| clearTimeout(this.batteryTimeoutID); |
| this.batteryTimeoutID = -1; |
| } |
| } |
| |
| /** |
| * Implements PowerCableStateObserver.onPowerCableStateChanged() |
| */ |
| onPowerCableStateChanged(pluggedIn: boolean): void { |
| this.pluggedIn = pluggedIn; |
| |
| if (this.pluggedIn) { |
| this.cancelBatteryCutoff(); |
| } |
| |
| const icon: HTMLElement|null = |
| this.shadowRoot!.querySelector('#batteryCutoffIcon'); |
| assert(icon); |
| icon.setAttribute( |
| 'icon', |
| this.pluggedIn ? 'shimless-icon:battery-cutoff-disabled' : |
| 'shimless-icon:battery-cutoff'); |
| } |
| |
| protected disableBatteryCutButton(): boolean { |
| return this.pluggedIn || this.allButtonsDisabled; |
| } |
| |
| protected getDiagnosticsIcon(): string { |
| return this.allButtonsDisabled ? 'shimless-icon:diagnostics-disabled' : |
| 'shimless-icon:diagnostics'; |
| } |
| |
| protected getRmaLogIcon(): string { |
| return this.allButtonsDisabled ? 'shimless-icon:rma-log-disabled' : |
| 'shimless-icon:rma-log'; |
| } |
| |
| protected getBatteryCutoffIcon(): string { |
| return this.allButtonsDisabled ? 'shimless-icon:battery-cutoff-disabled' : |
| 'shimless-icon:battery-cutoff'; |
| } |
| |
| protected disableShutdownButtons(): boolean { |
| return this.shutdownButtonsDisabled || this.allButtonsDisabled; |
| } |
| |
| protected getRepairCompletedShutoffText(): string { |
| return this.pluggedIn ? |
| this.i18n('repairCompletedShutoffInstructionsText') : |
| this.i18n('repairCompletedShutoffDescriptionText'); |
| } |
| } |
| |
| declare global { |
| interface HTMLElementTagNameMap { |
| [WrapupRepairCompletePage.is]: WrapupRepairCompletePage; |
| } |
| } |
| |
| customElements.define(WrapupRepairCompletePage.is, WrapupRepairCompletePage); |