| // 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 './shimless_rma_shared.css.js'; |
| import './base_page.js'; |
| import 'chrome://resources/ash/common/cr_elements/cr_dialog/cr_dialog.js'; |
| import 'chrome://resources/ash/common/cr_elements/cr_input/cr_input.js'; |
| |
| import {assert} from 'chrome://resources/js/assert.js'; |
| import {CrDialogElement} from 'chrome://resources/ash/common/cr_elements/cr_dialog/cr_dialog.js'; |
| import {CrInputElement} from 'chrome://resources/ash/common/cr_elements/cr_input/cr_input.js'; |
| import {I18nMixin} from 'chrome://resources/ash/common/cr_elements/i18n_mixin.js'; |
| import {afterNextRender, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; |
| |
| import {getShimlessRmaService} from './mojo_interface_provider.js'; |
| import {getTemplate} from './onboarding_enter_rsu_wp_disable_code_page.html.js'; |
| import {RmadErrorCode, ShimlessRmaServiceInterface, StateResult} from './shimless_rma.mojom-webui.js'; |
| import {dispatchNextButtonClick, enableNextButton} from './shimless_rma_util.js'; |
| |
| // The number of characters in an RSU code. |
| const RSU_CODE_EXPECTED_LENGTH = 8; |
| |
| /** |
| * @fileoverview |
| * 'onboarding-enter-rsu-wp-disable-code-page' asks the user for the RSU disable |
| * code. |
| */ |
| |
| const OnboardingEnterRsuWpDisableCodePageBase = I18nMixin(PolymerElement); |
| |
| export class OnboardingEnterRsuWpDisableCodePage extends |
| OnboardingEnterRsuWpDisableCodePageBase { |
| static get is() { |
| return 'onboarding-enter-rsu-wp-disable-code-page' as const; |
| } |
| |
| static get template() { |
| return getTemplate(); |
| } |
| |
| static get properties() { |
| return { |
| /** |
| * Set by shimless_rma.ts. |
| */ |
| allButtonsDisabled: Boolean, |
| |
| /** |
| * Set by shimless_rma.ts. |
| */ |
| errorCode: { |
| type: Object, |
| observer: |
| OnboardingEnterRsuWpDisableCodePage.prototype.onErrorCodeChanged, |
| }, |
| |
| canvasSize: { |
| type: Number, |
| value: 0, |
| }, |
| |
| rsuChallenge: { |
| type: String, |
| value: '', |
| }, |
| |
| rsuHwid: { |
| type: String, |
| value: '', |
| }, |
| |
| rsuCode: { |
| type: String, |
| value: '', |
| observer: |
| OnboardingEnterRsuWpDisableCodePage.prototype.onRsuCodeChanged, |
| }, |
| |
| rsuCodeExpectedLength: { |
| type: Number, |
| value: RSU_CODE_EXPECTED_LENGTH, |
| readOnly: true, |
| }, |
| |
| rsuInstructionsText: { |
| type: String, |
| value: '', |
| }, |
| |
| qrCodeUrl: { |
| type: String, |
| value: '', |
| }, |
| |
| rsuChallengeLinkText: { |
| type: String, |
| value: '', |
| computed: 'computeRsuChallengeLinkText(rsuHwid, rsuChallenge)', |
| }, |
| |
| rsuCodeValidationRegex: { |
| type: String, |
| value: '.{1,8}', |
| readOnly: true, |
| }, |
| |
| rsuCodeInvalid: { |
| type: Boolean, |
| value: false, |
| reflectToAttribute: true, |
| }, |
| }; |
| } |
| |
| shimlessRmaService: ShimlessRmaServiceInterface = getShimlessRmaService(); |
| allButtonsDisabled: boolean; |
| errorCode: RmadErrorCode; |
| protected canvasSize: number; |
| protected rsuChallenge: string; |
| protected rsuHwid: string; |
| protected rsuCode: string; |
| protected rsuCodeExpectedLength: number; |
| protected rsuInstructionsText: TrustedHTML; |
| protected qrCodeUrl: string; |
| protected rsuChallengeLinkText: string; |
| protected rsuCodeValidationRegex: string; |
| protected rsuCodeInvalid: boolean; |
| |
| override ready() { |
| super.ready(); |
| this.getRsuChallengeAndHwid(); |
| this.setRsuInstructionsText(); |
| enableNextButton(this); |
| |
| afterNextRender(this, () => { |
| const codeInput: CrInputElement|null = this.shadowRoot!.querySelector('#rsuCode'); |
| assert(codeInput); |
| codeInput.focus(); |
| }); |
| } |
| |
| private getRsuChallengeAndHwid(): void { |
| this.shimlessRmaService.getRsuDisableWriteProtectChallenge().then( |
| (result: {challenge: string}) => this.rsuChallenge = result.challenge); |
| this.shimlessRmaService.getRsuDisableWriteProtectHwid().then((result: {hwid: string}) => { |
| this.rsuHwid = result.hwid; |
| }); |
| this.shimlessRmaService.getRsuDisableWriteProtectChallengeQrCode().then( |
| this.updateQrCode.bind(this)); |
| } |
| |
| private updateQrCode(response: {qrCodeData: number[]}): void { |
| const blob = |
| new Blob([Uint8Array.from(response.qrCodeData)], {'type': 'image/png'}); |
| this.qrCodeUrl = URL.createObjectURL(blob); |
| } |
| |
| private rsuCodeIsPlausible(): boolean { |
| return !!this.rsuCode && this.rsuCode.length === RSU_CODE_EXPECTED_LENGTH; |
| } |
| |
| protected onRsuCodeChanged(): void { |
| // Set to false whenever the user changes the code to remove the red invalid |
| // warning. |
| this.rsuCodeInvalid = false; |
| this.rsuCode = this.rsuCode.toUpperCase(); |
| } |
| |
| protected onKeyDown(event: KeyboardEvent): void { |
| if (event.key === 'Enter') { |
| dispatchNextButtonClick(this); |
| } |
| } |
| |
| onNextButtonClick(): Promise<{stateResult: StateResult}> { |
| if (this.rsuCode.length !== this.rsuCodeExpectedLength) { |
| this.rsuCodeInvalid = true; |
| return Promise.reject(new Error('No RSU code set')); |
| } |
| |
| return this.shimlessRmaService.setRsuDisableWriteProtectCode(this.rsuCode); |
| } |
| |
| private setRsuInstructionsText(): void { |
| this.rsuInstructionsText = |
| this.i18nAdvanced('rsuCodeInstructionsText', {attrs: ['id']}); |
| const linkElement: HTMLAnchorElement|null = this.shadowRoot!.querySelector('#rsuCodeDialogLink'); |
| assert(linkElement); |
| linkElement.setAttribute('href', '#'); |
| linkElement.addEventListener('click', () => { |
| if (this.allButtonsDisabled) { |
| return; |
| } |
| |
| const dialog: CrDialogElement|null = this.shadowRoot!.querySelector('#rsuChallengeDialog'); |
| assert(dialog); |
| dialog.showModal(); |
| }); |
| } |
| |
| private computeRsuChallengeLinkText(): string { |
| const unlockPageUrl = |
| 'https://chromeos.google.com/partner/console/cr50reset?challenge='; |
| return unlockPageUrl + this.rsuChallenge + '&hwid=' + this.rsuHwid; |
| } |
| |
| private closeDialog(): void { |
| const dialog: CrDialogElement|null = this.shadowRoot!.querySelector('#rsuChallengeDialog'); |
| assert(dialog); |
| dialog.close(); |
| } |
| |
| private onErrorCodeChanged(): void { |
| if (this.errorCode === RmadErrorCode.kWriteProtectDisableRsuCodeInvalid) { |
| this.rsuCodeInvalid = true; |
| } |
| } |
| |
| protected getRsuCodeLabelText(): string { |
| return this.rsuCodeInvalid ? this.i18n('rsuCodeErrorLabelText') : |
| this.i18n('rsuCodeLabelText'); |
| } |
| |
| protected getRsuAriaDescription(): string { |
| return `${this.getRsuCodeLabelText()} ${ |
| this.i18n('rsuCodeInstructionsAriaText')}`; |
| } |
| } |
| |
| declare global { |
| interface HTMLElementTagNameMap { |
| [OnboardingEnterRsuWpDisableCodePage.is]: OnboardingEnterRsuWpDisableCodePage; |
| } |
| } |
| |
| customElements.define( |
| OnboardingEnterRsuWpDisableCodePage.is, |
| OnboardingEnterRsuWpDisableCodePage); |