chromium/chrome/test/data/webui/cr_components/certificate_manager/certificate_manager_v2_test.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.

// These test suites test the certificate-manager v2 component.

import 'chrome://resources/cr_components/certificate_manager/certificate_manager_v2.js';
import 'chrome://certificate-manager/strings.m.js';

import {PluralStringProxyImpl} from '//resources/js/plural_string_proxy.js';
import type {CertificateManagerV2Element} from 'chrome://resources/cr_components/certificate_manager/certificate_manager_v2.js';
import type {CertManagementMetadata} from 'chrome://resources/cr_components/certificate_manager/certificate_manager_v2.mojom-webui.js';
import type {CertificatePasswordDialogElement} from 'chrome://resources/cr_components/certificate_manager/certificate_password_dialog.js';
import {CertificatesV2BrowserProxy} from 'chrome://resources/cr_components/certificate_manager/certificates_v2_browser_proxy.js';
import {assertDeepEquals, assertEquals, assertFalse, assertNull, assertTrue} from 'chrome://webui-test/chai_assert.js';
import {TestPluralStringProxy} from 'chrome://webui-test/test_plural_string_proxy.js';
import {isVisible, microtasksFinished} from 'chrome://webui-test/test_util.js';

import {TestCertificateManagerProxy} from './certificate_manager_v2_test_support.js';

class CertManagerTestPluralStringProxy extends TestPluralStringProxy {
  override text: string = '';

  override getPluralString(messageName: string, itemCount: number) {
    if (messageName === 'certificateManagerV2NumCerts') {
      this.methodCalled('getPluralString', {messageName, itemCount});
    }
    return Promise.resolve(this.text);
  }
}

suite('CertificateManagerV2Test', () => {
  let certManager: CertificateManagerV2Element;
  let testProxy: TestCertificateManagerProxy;

  setup(async () => {
    document.body.innerHTML = window.trustedTypes!.emptyHTML;
    testProxy = new TestCertificateManagerProxy();
    CertificatesV2BrowserProxy.setInstance(testProxy);
  });

  function initializeElement() {
    certManager = document.createElement('certificate-manager-v2');
    document.body.appendChild(certManager);
  }

  // <if expr="not (is_win or is_macosx or is_linux)">
  test('provisioned client certs not present', async () => {
    initializeElement();
    await microtasksFinished();

    const parentElement =
        certManager.shadowRoot!.querySelector('#provisionedClientCerts');
    // The provisioned client certs section should not be present on other OSes.
    assertFalse(
        !!parentElement,
        'provisionedClientCerts element was unexpectedly found');
  });
  // </if>

  test('Policy - OS certs number string', async () => {
    const pluralStringProxy = new CertManagerTestPluralStringProxy();
    PluralStringProxyImpl.setInstance(pluralStringProxy);
    pluralStringProxy.text = '5 certificates';
    const metadata: CertManagementMetadata = {
      includeSystemTrustStore: true,
      numUserAddedSystemCerts: 5,
      isIncludeSystemTrustStoreManaged: true,
      numPolicyCerts: 0,
    };
    testProxy.handler.setCertManagementMetadata(metadata);
    initializeElement();

    await testProxy.handler.whenCalled('getCertManagementMetadata');
    await pluralStringProxy.whenCalled('getPluralString');
    await microtasksFinished();

    assertEquals(
        '5 certificates', certManager.$.numSystemCerts.innerText,
        'num system certs string incorrect');
    assertTrue(isVisible(certManager.$.numSystemCerts));
  });

  test('Policy - OS certs imported and managed', async () => {
    const metadata: CertManagementMetadata = {
      includeSystemTrustStore: true,
      numUserAddedSystemCerts: 0,
      isIncludeSystemTrustStoreManaged: true,
      numPolicyCerts: 0,
    };
    testProxy.handler.setCertManagementMetadata(metadata);
    initializeElement();

    await testProxy.handler.whenCalled('getCertManagementMetadata');
    await microtasksFinished();

    assertTrue(certManager.$.importOsCerts.checked, 'os toggle state wrong');
    assertTrue(
        isVisible(certManager.$.importOsCertsManagedIcon),
        'enterprise managed icon visibility wrong');
    assertTrue(
        isVisible(certManager.$.viewOsImportedCerts),
        'view imported os certs link visibility wrong');
    // <if expr="is_win or is_macosx">
    assertTrue(
        isVisible(certManager.$.manageOsImportedCerts),
        'imported os certs external link visibility wrong');
    // </if>
  });

  test('Policy - OS certs imported but not managed', async () => {
    const metadata: CertManagementMetadata = {
      includeSystemTrustStore: true,
      numUserAddedSystemCerts: 0,
      isIncludeSystemTrustStoreManaged: false,
      numPolicyCerts: 0,
    };
    testProxy.handler.setCertManagementMetadata(metadata);
    initializeElement();

    await testProxy.handler.whenCalled('getCertManagementMetadata');
    await microtasksFinished();

    assertTrue(
        certManager.$.importOsCerts.checked, 'os import toggle state wrong');
    assertFalse(
        isVisible(certManager.$.importOsCertsManagedIcon),
        'enterprise managed icon visibility wrong');
    assertTrue(
        isVisible(certManager.$.viewOsImportedCerts),
        'view imported os certs link visibility wrong');
    // <if expr="is_win or is_macosx">
    assertTrue(
        isVisible(certManager.$.manageOsImportedCerts),
        'imported os certs external link visibility wrong');
    // </if>
  });

  test('Policy - OS certs not imported but managed', async () => {
    const metadata: CertManagementMetadata = {
      includeSystemTrustStore: false,
      numUserAddedSystemCerts: 0,
      isIncludeSystemTrustStoreManaged: true,
      numPolicyCerts: 0,
    };
    testProxy.handler.setCertManagementMetadata(metadata);
    initializeElement();

    await testProxy.handler.whenCalled('getCertManagementMetadata');
    await microtasksFinished();

    assertFalse(
        certManager.$.importOsCerts.checked, 'os import toggle state wrong');
    assertFalse(isVisible(certManager.$.numSystemCerts));
    assertTrue(
        isVisible(certManager.$.importOsCertsManagedIcon),
        'enterprise managed icon visibility wrong');
    assertFalse(
        isVisible(certManager.$.viewOsImportedCerts),
        'view imported os certs link visibility wrong');
    // <if expr="is_win or is_macosx">
    assertFalse(
        isVisible(certManager.$.manageOsImportedCerts),
        'imported os certs external link visibility wrong');
    // </if>
  });

  test('Policy - OS certs not imported and not managed', async () => {
    const metadata: CertManagementMetadata = {
      includeSystemTrustStore: false,
      numUserAddedSystemCerts: 0,
      isIncludeSystemTrustStoreManaged: false,
      numPolicyCerts: 0,
    };
    testProxy.handler.setCertManagementMetadata(metadata);
    initializeElement();

    await testProxy.handler.whenCalled('getCertManagementMetadata');
    await microtasksFinished();

    assertFalse(
        certManager.$.importOsCerts.checked, 'os import toggle state wrong');
    assertFalse(isVisible(certManager.$.numSystemCerts));
    assertFalse(
        isVisible(certManager.$.importOsCertsManagedIcon),
        'enterprise managed icon visibility wrong');
    assertFalse(
        isVisible(certManager.$.viewOsImportedCerts),
        'view imported os certs link visibility wrong');
    // <if expr="is_win or is_macosx">
    assertFalse(
        isVisible(certManager.$.manageOsImportedCerts),
        'imported os certs external link visibility wrong');
    // </if>
  });

  // <if expr="is_win or is_macosx">
  test('Open native certificate management', async () => {
    const metadata: CertManagementMetadata = {
      includeSystemTrustStore: true,
      numUserAddedSystemCerts: 0,
      isIncludeSystemTrustStoreManaged: true,
      numPolicyCerts: 0,
    };
    testProxy.handler.setCertManagementMetadata(metadata);
    initializeElement();

    await testProxy.handler.whenCalled('getCertManagementMetadata');
    certManager.$.localMenuItem.click();
    await microtasksFinished();
    assertTrue(
        isVisible(certManager.$.manageOsImportedCerts),
        'imported os certs external link visibility wrong');
    certManager.$.manageOsImportedCerts.click();
    await testProxy.handler.whenCalled('showNativeManageCertificates');
  });

  test('Open native client certificate management', async () => {
    initializeElement();
    certManager.$.clientMenuItem.click();

    await microtasksFinished();
    assertTrue(
        isVisible(certManager.$.manageOsImportedClientCerts),
        'imported os certs external link visibility wrong');
    certManager.$.manageOsImportedClientCerts.click();
    await testProxy.handler.whenCalled('showNativeManageCertificates');
  });
  // </if>

  test('no admin certs, hide custom section', async () => {
    const metadata: CertManagementMetadata = {
      includeSystemTrustStore: true,
      numUserAddedSystemCerts: 0,
      isIncludeSystemTrustStoreManaged: true,
      numPolicyCerts: 0,
    };
    testProxy.handler.setCertManagementMetadata(metadata);
    initializeElement();

    await testProxy.handler.whenCalled('getCertManagementMetadata');
    await microtasksFinished();
    const customSection =
        certManager.shadowRoot!.querySelector('#customCertsSection');
    assertNull(customSection, 'custom certs section not hidden');
  });

  test('have admin certs, show custom section', async () => {
    const metadata: CertManagementMetadata = {
      includeSystemTrustStore: true,
      numUserAddedSystemCerts: 0,
      isIncludeSystemTrustStoreManaged: true,
      numPolicyCerts: 5,
    };
    testProxy.handler.setCertManagementMetadata(metadata);
    initializeElement();

    await testProxy.handler.whenCalled('getCertManagementMetadata');
    await microtasksFinished();
    const customSection =
        certManager.shadowRoot!.querySelector('#customCertsSection');
    const linkRow = customSection!.querySelector('cr-link-row');
    assertEquals('5 certificates', linkRow!.subLabel);
  });

  test('show admin certs', async () => {
    const metadata: CertManagementMetadata = {
      includeSystemTrustStore: true,
      numUserAddedSystemCerts: 0,
      isIncludeSystemTrustStoreManaged: true,
      numPolicyCerts: 5,
    };
    testProxy.handler.setCertManagementMetadata(metadata);
    initializeElement();

    await testProxy.handler.whenCalled('getCertManagementMetadata');
    await microtasksFinished();
    const customSection =
        certManager.shadowRoot!.querySelector('#customCertsSection');
    const linkRow = customSection!.querySelector('cr-link-row');
    linkRow!.click();
    await microtasksFinished();
    assertTrue(certManager.$.adminCertsSection.classList.contains('selected'));
  });

  test('navigate back from admin certs', async () => {
    const metadata: CertManagementMetadata = {
      includeSystemTrustStore: true,
      numUserAddedSystemCerts: 0,
      isIncludeSystemTrustStoreManaged: true,
      numPolicyCerts: 5,
    };
    testProxy.handler.setCertManagementMetadata(metadata);
    initializeElement();

    await testProxy.handler.whenCalled('getCertManagementMetadata');
    await microtasksFinished();
    const customSection =
        certManager.shadowRoot!.querySelector('#customCertsSection');
    const linkRow = customSection!.querySelector('cr-link-row');
    linkRow!.click();
    await microtasksFinished();
    assertTrue(certManager.$.adminCertsSection.classList.contains('selected'));
    certManager.$.adminCertsSection.$.backButton.click();
    await microtasksFinished();
    assertFalse(certManager.$.adminCertsSection.classList.contains('selected'));
    assertTrue(certManager.$.localCertSection.classList.contains('selected'));
  });

  test('show platform certs', async () => {
    initializeElement();
    await microtasksFinished();
    assertFalse(
        certManager.$.platformCertsSection.classList.contains('selected'));
    certManager.$.viewOsImportedCerts.click();
    await microtasksFinished();
    assertTrue(
        certManager.$.platformCertsSection.classList.contains('selected'));
  });

  test('navigate back from platform certs', async () => {
    initializeElement();
    await microtasksFinished();
    certManager.$.viewOsImportedCerts.click();
    await microtasksFinished();
    assertTrue(
        certManager.$.platformCertsSection.classList.contains('selected'));
    certManager.$.platformCertsSection.$.backButton.click();
    await microtasksFinished();
    assertFalse(
        certManager.$.platformCertsSection.classList.contains('selected'));
    assertTrue(certManager.$.localCertSection.classList.contains('selected'));
  });

  test('show platform client certs then navigate back', async () => {
    initializeElement();
    // Go to client section.
    certManager.$.clientMenuItem.click();
    await microtasksFinished();
    assertTrue(certManager.$.clientCertSection.classList.contains('selected'));
    assertFalse(certManager.$.platformClientCertsSection.classList.contains(
        'selected'));

    // Click into client platform certs section.
    certManager.$.viewOsImportedClientCerts.click();
    await microtasksFinished();
    assertTrue(
        certManager.$.platformClientCertsSection.classList.contains('selected'),
        'not visible after click');

    // Go back to client certs.
    certManager.$.platformClientCertsSection.$.backButton.click();
    await microtasksFinished();
    assertFalse(
        certManager.$.platformClientCertsSection.classList.contains('selected'),
        'visible after click');
    assertTrue(
        certManager.$.clientCertSection.classList.contains('selected'),
        'main pane not visible');
  });

  test('click local certs section', async () => {
    initializeElement();
    certManager.$.localMenuItem.click();
    await microtasksFinished();
    assertTrue(certManager.$.localCertSection.classList.contains('selected'));
  });

  test('click client certs section', async () => {
    initializeElement();
    certManager.$.clientMenuItem.click();
    await microtasksFinished();
    assertTrue(certManager.$.clientCertSection.classList.contains('selected'));
  });

  test('click crs certs section', async () => {
    initializeElement();
    certManager.$.crsMenuItem.click();
    await microtasksFinished();
    assertTrue(certManager.$.crsCertSection.classList.contains('selected'));
  });

  // Tests opening the password dialog through the mojo interface and
  // retrieving the result of the mojo call, as well as testing that the dialog
  // is added and removed from the DOM as necessary.
  test('askForImportPassword ok', async () => {
    initializeElement();
    await microtasksFinished();

    const doTest = async (expectedPassword: string) => {
      // The password dialog should not be present in the DOM initially.
      assertNull(certManager.shadowRoot!.querySelector('#passwordDialog'));

      const promise = testProxy.callbackRouterRemote.askForImportPassword();
      await microtasksFinished();

      const passwordDialog =
          certManager.shadowRoot!
              .querySelector<CertificatePasswordDialogElement>(
                  '#passwordDialog');
      assertTrue(!!passwordDialog);
      assertTrue(passwordDialog.$.dialog.open);
      assertEquals('', passwordDialog.$.password.value);
      passwordDialog.$.password.value = expectedPassword;
      passwordDialog.$.ok.click();

      assertDeepEquals({password: expectedPassword}, await promise);
    };

    await doTest('something secret');

    // Try showing the dialog again - the dialog should work multiple times,
    // and the password field should be cleared (not still containing the value
    // previously entered).
    await doTest('something different');

    // The password dialog should no longer be present in the DOM.
    assertNull(certManager.shadowRoot!.querySelector('#passwordDialog'));
  });

  // Tests that cancelling the password dialog is signalled through the mojo
  // interface by returning a null result.
  test('askForImportPassword cancel', async () => {
    initializeElement();
    await microtasksFinished();

    // The password dialog should not be present in the DOM initially.
    assertNull(certManager.shadowRoot!.querySelector('#passwordDialog'));

    {
      const promise = testProxy.callbackRouterRemote.askForImportPassword();
      await microtasksFinished();

      const passwordDialog =
          certManager.shadowRoot!
              .querySelector<CertificatePasswordDialogElement>(
                  '#passwordDialog');
      assertTrue(!!passwordDialog);
      assertTrue(passwordDialog.$.dialog.open);
      assertEquals('', passwordDialog.$.password.value);
      passwordDialog.$.password.value = 'something secret';
      passwordDialog.$.cancel.click();

      assertDeepEquals({password: null}, await promise);
    }

    // The password dialog should no longer be present in the DOM.
    assertNull(certManager.shadowRoot!.querySelector('#passwordDialog'));

    // Try showing the dialog again - the dialog should work multiple times,
    // and the password field should be cleared (not still containing the value
    // previously entered).
    {
      const promise = testProxy.callbackRouterRemote.askForImportPassword();
      await microtasksFinished();

      const passwordDialog =
          certManager.shadowRoot!
              .querySelector<CertificatePasswordDialogElement>(
                  '#passwordDialog');
      assertTrue(!!passwordDialog);
      assertTrue(passwordDialog.$.dialog.open);
      assertEquals('', passwordDialog.$.password.value);
      passwordDialog.$.password.value = 'something different';
      passwordDialog.$.ok.click();

      assertDeepEquals({password: 'something different'}, await promise);
    }

    // The password dialog should no longer be present in the DOM.
    assertNull(certManager.shadowRoot!.querySelector('#passwordDialog'));
  });
});