chromium/chrome/browser/resources/connectors_internals/managed_client_certificate.ts

// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import {CustomElement} from 'chrome://resources/js/custom_element.js';

import {BrowserProxy} from './browser_proxy.js';
import type {ClientCertificateState, ClientIdentity, PageHandlerInterface} from './connectors_internals.mojom-webui.js';
import * as utils from './connectors_utils.js';
import {getTemplate} from './managed_client_certificate.html.js';

export class ManagedClientCertificateElement extends CustomElement {
  static get is() {
    return 'managed-client-certificate';
  }

  static override get template() {
    return getTemplate();
  }

  private get pageHandler(): PageHandlerInterface {
    return BrowserProxy.getInstance().handler;
  }

  private set policyEnabledLevels(policyLevels: string[]) {
    if (policyLevels.length === 0) {
      this.setValueToElement('#policy-enabled-levels', 'None');
      return;
    }

    this.setValueToElement('#policy-enabled-levels', `${policyLevels}`);
  }

  private get managedIdentitiesSection(): HTMLElement|null {
    return this.$('#managed-identities');
  }

  constructor() {
    super();
    this.fetchClientCertificateValues();
  }

  private fetchClientCertificateValues() {
    this.pageHandler.getClientCertificateState().then(
        (response: {state: ClientCertificateState}) =>
            this.updateState(response?.state),
        err => console.error(
            `Failed to fetch client cert state: ${JSON.stringify(err)}`));
  }

  private updateState(state: ClientCertificateState|undefined) {
    const managedIdentitiesSection = this.managedIdentitiesSection;
    if (!managedIdentitiesSection) {
      // A critical element is missing from the page, so fail early.
      this.policyEnabledLevels = ['Error'];
      return;
    }

    // Clear managed identities.
    while (managedIdentitiesSection.firstChild) {
      managedIdentitiesSection.removeChild(managedIdentitiesSection.firstChild);
    }

    if (!state) {
      this.policyEnabledLevels = ['Error'];
      return;
    }

    this.policyEnabledLevels = state.policyEnabledLevels;

    if (state.managedProfileIdentity) {
      managedIdentitiesSection.appendChild(this.createManagedIdentityElement(
          'Profile', state.managedProfileIdentity));
    }

    if (state.managedBrowserIdentity) {
      managedIdentitiesSection.appendChild(this.createManagedIdentityElement(
          'Browser', state.managedBrowserIdentity));
    }
  }

  private setValueToElement(elementId: string, stringValue: string) {
    const htmlElement = this.$<HTMLElement>(elementId);
    if (htmlElement) {
      htmlElement.innerText = stringValue;
    } else {
      console.error(`Could not find ${elementId} element.`);
    }
  }

  private createManagedIdentityElement(
      prefix: string, managedIdentity: ClientIdentity): HTMLDivElement {
    const identityElement = document.createElement('div') as HTMLDivElement;

    let keyValuePairs =
        [{key: `${prefix} Identity Name`, value: managedIdentity.identityName}];

    if (managedIdentity.loadedKeyInfo) {
      keyValuePairs = keyValuePairs.concat([
        {
          key: 'Key Trust Level',
          value: utils.trustLevelToString(
              managedIdentity.loadedKeyInfo.trustLevel),
        },
        {
          key: 'Key Type',
          value: utils.keyTypeToString(managedIdentity.loadedKeyInfo.keyType),
        },
        {
          key: 'Public Key Hash',
          value: managedIdentity.loadedKeyInfo.encodedSpkiHash,
        },
      ]);

      if (managedIdentity.loadedKeyInfo.keyUploadStatus) {
        if (managedIdentity.loadedKeyInfo.keyUploadStatus.uploadClientError) {
          keyValuePairs.push({
            key: 'Key Upload Client Error',
            value:
                managedIdentity.loadedKeyInfo.keyUploadStatus.uploadClientError,
          });
        } else {
          keyValuePairs.push({
            key: 'Key Upload Response',
            value: utils.keySyncCodeToString(
                managedIdentity.loadedKeyInfo.keyUploadStatus
                    .syncKeyResponseCode),
          });
        }
      }
    }

    if (managedIdentity.certificateMetadata) {
      keyValuePairs = keyValuePairs.concat([
        {
          key: 'Subject',
          value: managedIdentity.certificateMetadata.subjectDisplayName,
        },
        {
          key: 'Issuer',
          value: managedIdentity.certificateMetadata.issuerDisplayName,
        },
        {
          key: 'Serial Number',
          value: managedIdentity.certificateMetadata.serialNumber,
        },
        {
          key: 'SHA-256 Fingerprint',
          value: managedIdentity.certificateMetadata.fingerprint,
        },
        {
          key: 'Creation Date',
          value: managedIdentity.certificateMetadata.creationDateString,
        },
        {
          key: 'Expiration Date',
          value: managedIdentity.certificateMetadata.expirationDateString,
        },
      ]);
    }

    for (const pair of keyValuePairs) {
      identityElement.appendChild(
          this.createLabelledValueElement(pair.key, pair.value));
    }

    return identityElement;
  }

  private createLabelledValueElement(label: string, text: string): HTMLElement {
    const nameSpan = document.createElement('span') as HTMLSpanElement;
    nameSpan.classList.add('bold');
    nameSpan.textContent = text;

    const containerElement = document.createElement('div') as HTMLDivElement;
    containerElement.appendChild(document.createTextNode(`${label}: `));
    containerElement.appendChild(nameSpan);
    return containerElement;
  }
}

customElements.define(
    ManagedClientCertificateElement.is, ManagedClientCertificateElement);