| // 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/icons.html.js'; |
| import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; |
| import 'chrome://resources/polymer/v3_0/paper-spinner/paper-spinner-lite.js'; |
| import 'chrome://resources/ash/common/cr_elements/cr_button/cr_button.js'; |
| import './shimless_rma_shared.css.js'; |
| import './base_page.js'; |
| import './icons.html.js'; |
| |
| import {assert} from 'chrome://resources/js/assert.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 {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js'; |
| import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; |
| |
| import {getShimlessRmaService} from './mojo_interface_provider.js'; |
| import {getTemplate} from './onboarding_update_page.html.js'; |
| import {HardwareVerificationStatusObserverReceiver, OsUpdateObserverReceiver, OsUpdateOperation, ShimlessRmaServiceInterface, StateResult, UpdateErrorCode} from './shimless_rma.mojom-webui.js'; |
| import {disableAllButtons, enableAllButtons, enableNextButton, focusPageTitle} from './shimless_rma_util.js'; |
| |
| /** |
| * @fileoverview |
| * 'onboarding-update-page' is the page shown when there is an Chrome OS update |
| * available on the device for the user to install before the RMA process. |
| */ |
| |
| const OnboardingUpdatePageElementBase = I18nMixin(PolymerElement); |
| |
| export class OnboardingUpdatePageElement extends |
| OnboardingUpdatePageElementBase { |
| static get is() { |
| return 'onboarding-update-page' as const; |
| } |
| |
| static get template() { |
| return getTemplate(); |
| } |
| |
| static get properties() { |
| return { |
| /** |
| * Set by shimless_rma.ts. |
| */ |
| allButtonsDisabled: Boolean, |
| |
| currentVersionText: { |
| type: String, |
| value: '', |
| }, |
| |
| updateVersionButtonLabel: { |
| type: String, |
| value: '', |
| }, |
| |
| updateInProgress: { |
| type: Boolean, |
| value: false, |
| observer: |
| OnboardingUpdatePageElement.prototype.onUpdateInProgressChange, |
| }, |
| |
| verificationFailedMessage: { |
| type: String, |
| value: '', |
| }, |
| |
| /** |
| * A string containing a list of the unqualified component identifiers |
| * separated by new lines. |
| */ |
| unqualifiedComponentsText: { |
| type: String, |
| value: '', |
| }, |
| |
| |
| osUpdateEncounteredError: { |
| type: Boolean, |
| value: false, |
| }, |
| }; |
| } |
| |
| allButtonsDisabled: boolean; |
| shimlessRmaService: ShimlessRmaServiceInterface; |
| isCompliant: boolean; |
| protected currentVersionText: string; |
| protected updateVersionButtonLabel: string; |
| protected updateInProgress: boolean; |
| protected verificationFailedMessage: TrustedHTML; |
| protected unqualifiedComponentsText: string; |
| protected osUpdateEncounteredError: boolean; |
| protected currentVersion: string; |
| protected osUpdateObserverReceiver: OsUpdateObserverReceiver|null; |
| protected hwVerificationObserverReceiver: HardwareVerificationStatusObserverReceiver|null; |
| |
| constructor() { |
| super(); |
| if (!loadTimeData.getBoolean('osUpdateEnabled')) { |
| return; |
| } |
| |
| this.shimlessRmaService = getShimlessRmaService(); |
| this.currentVersion = ''; |
| this.osUpdateObserverReceiver = new OsUpdateObserverReceiver(this); |
| |
| this.shimlessRmaService.observeOsUpdateProgress( |
| this.osUpdateObserverReceiver.$.bindNewPipeAndPassRemote()); |
| |
| // We assume it's compliant until updated in onHardwareVerificationResult(). |
| this.isCompliant = true; |
| this.hwVerificationObserverReceiver = new HardwareVerificationStatusObserverReceiver(this); |
| |
| this.shimlessRmaService.observeHardwareVerificationStatus( |
| this.hwVerificationObserverReceiver.$.bindNewPipeAndPassRemote()); |
| } |
| |
| override ready() { |
| super.ready(); |
| if (!loadTimeData.getBoolean('osUpdateEnabled')) { |
| return; |
| } |
| this.getCurrentVersionText(); |
| this.getUpdateVersionNumber(); |
| enableNextButton(this); |
| |
| focusPageTitle(this); |
| } |
| |
| private getCurrentVersionText(): void { |
| if (!loadTimeData.getBoolean('osUpdateEnabled')) { |
| return; |
| } |
| this.shimlessRmaService.getCurrentOsVersion().then((res: {version: string|null}) => { |
| if (res.version != null) { |
| this.currentVersion = res.version; |
| } else { |
| this.currentVersion = '0.0.0.0'; |
| } |
| this.currentVersionText = |
| this.i18n('currentVersionOutOfDateText', this.currentVersion); |
| }); |
| } |
| |
| private getUpdateVersionNumber(): void { |
| if (!loadTimeData.getBoolean('osUpdateEnabled')) { |
| return; |
| } |
| this.shimlessRmaService.checkForOsUpdates().then((res: {updateAvailable: boolean, version: string|null}) => { |
| assert(res.updateAvailable); |
| this.updateVersionButtonLabel = |
| this.i18n('updateVersionRestartLabel', res?.version || ''); |
| }); |
| } |
| |
| private updateOs(): void { |
| this.updateInProgress = true; |
| this.shimlessRmaService.updateOs().then((res: {updateStarted: boolean}) => { |
| if (!res.updateStarted) { |
| this.updateInProgress = false; |
| } |
| }); |
| } |
| |
| protected onUpdateButtonClicked(): void { |
| if (!loadTimeData.getBoolean('osUpdateEnabled')) { |
| return; |
| } |
| |
| this.updateOs(); |
| } |
| |
| protected onRetryUpdateButtonClicked(): void { |
| if (!loadTimeData.getBoolean('osUpdateEnabled')) { |
| return; |
| } |
| |
| assert(this.osUpdateEncounteredError); |
| this.osUpdateEncounteredError = false; |
| |
| this.updateOs(); |
| } |
| |
| onNextButtonClick(): Promise<{stateResult: StateResult}> { |
| return this.shimlessRmaService.updateOsSkipped(); |
| } |
| |
| /** |
| * Implements OsUpdateObserver.onOsUpdateProgressUpdated() |
| */ |
| onOsUpdateProgressUpdated(operation: OsUpdateOperation, _progress: number, error: UpdateErrorCode): void { |
| if (!loadTimeData.getBoolean('osUpdateEnabled')) { |
| return; |
| } |
| // Ignore progress when not updating, it is just the update available check. |
| if (!this.updateInProgress) { |
| return; |
| } |
| |
| if (operation === OsUpdateOperation.kIdle || |
| operation === OsUpdateOperation.kReportingErrorEvent || |
| operation === OsUpdateOperation.kNeedPermissionToUpdate || |
| operation === OsUpdateOperation.kDisabled) { |
| this.updateInProgress = false; |
| |
| if (error !== UpdateErrorCode.kSuccess) { |
| this.osUpdateEncounteredError = true; |
| } |
| } |
| } |
| |
| /** |
| * Implements |
| * HardwareVerificationStatusObserver.onHardwareVerificationResult() |
| */ |
| onHardwareVerificationResult(isCompliant: boolean, errorMessage: string): void { |
| if (!loadTimeData.getBoolean('osUpdateEnabled')) { |
| return; |
| } |
| this.isCompliant = isCompliant; |
| |
| if (!this.isCompliant) { |
| this.unqualifiedComponentsText = errorMessage; |
| this.setVerificationFailedMessage(); |
| } |
| } |
| |
| private setVerificationFailedMessage(): void { |
| if (!loadTimeData.getBoolean('osUpdateEnabled')) { |
| return; |
| } |
| this.verificationFailedMessage = this.i18nAdvanced( |
| 'osUpdateUnqualifiedComponentsTopText', {attrs: ['id']}); |
| |
| // The #unqualifiedComponentsLink identifier is sourced from the string |
| // attached to `osUpdateUnqualifiedComponentsTopText` in the related .grd |
| // file. |
| const linkElement: HTMLAnchorElement|null = |
| this.shadowRoot!.querySelector('#unqualifiedComponentsLink'); |
| assert(linkElement); |
| linkElement.setAttribute('href', '#'); |
| const dialog: CrDialogElement|null = this.shadowRoot!.querySelector('#unqualifiedComponentsDialog'); |
| assert(dialog); |
| linkElement.addEventListener('click', () => dialog.showModal()); |
| } |
| |
| private closeDialog(): void { |
| if (!loadTimeData.getBoolean('osUpdateEnabled')) { |
| return; |
| } |
| const dialog: CrDialogElement|null = this.shadowRoot!.querySelector('#unqualifiedComponentsDialog'); |
| assert(dialog); |
| dialog.close(); |
| } |
| |
| private onUpdateInProgressChange(): void { |
| if (!loadTimeData.getBoolean('osUpdateEnabled')) { |
| return; |
| } |
| if (this.updateInProgress) { |
| disableAllButtons(this, /*showBusyStateOverlay=*/ false); |
| } else { |
| enableAllButtons(this); |
| } |
| } |
| |
| protected shouldShowUpdateInstructions(): boolean { |
| return !this.updateInProgress && !this.osUpdateEncounteredError; |
| } |
| } |
| |
| declare global { |
| interface HTMLElementTagNameMap { |
| [OnboardingUpdatePageElement.is]: OnboardingUpdatePageElement; |
| } |
| } |
| |
| customElements.define( |
| OnboardingUpdatePageElement.is, OnboardingUpdatePageElement); |