chromium/chrome/test/data/webui/settings/cookies_page_test.ts

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

// clang-format off
import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import type {SettingsCollapseRadioButtonElement, SettingsRadioGroupElement, SettingsCookiesPageElement} from 'chrome://settings/lazy_load.js';
import {CookieControlsMode, ContentSettingsTypes, SITE_EXCEPTION_WILDCARD, SiteSettingsPrefsBrowserProxyImpl} from 'chrome://settings/lazy_load.js';
import type {SettingsPrefsElement, SettingsToggleButtonElement} from 'chrome://settings/settings.js';
import {CrSettingsPrefs, MetricsBrowserProxyImpl, PrivacyElementInteractions, resetRouterForTesting, Router, routes} from 'chrome://settings/settings.js';
import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
import {eventToPromise, isChildVisible} from 'chrome://webui-test/test_util.js';
import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';

import {TestMetricsBrowserProxy} from './test_metrics_browser_proxy.js';
import {TestSiteSettingsPrefsBrowserProxy} from './test_site_settings_prefs_browser_proxy.js';
import {createContentSettingTypeToValuePair, createRawSiteException, createSiteSettingsPrefs} from './test_util.js';

// clang-format on

suite('CookiesPageTest', function() {
  let siteSettingsBrowserProxy: TestSiteSettingsPrefsBrowserProxy;
  let testMetricsBrowserProxy: TestMetricsBrowserProxy;
  let page: SettingsCookiesPageElement;
  let settingsPrefs: SettingsPrefsElement;

  function primarySettingGroup(): SettingsRadioGroupElement {
    const group = page.shadowRoot!.querySelector<SettingsRadioGroupElement>(
        '#primarySettingGroup');
    assertTrue(!!group);
    return group;
  }

  function blockThirdParty(): SettingsCollapseRadioButtonElement {
    return page.shadowRoot!.querySelector('#blockThirdParty')!;
  }

  function blockThirdPartyIncognito(): SettingsCollapseRadioButtonElement {
    return page.shadowRoot!.querySelector('#blockThirdPartyIncognito')!;
  }

  function allowThirdParty(): SettingsCollapseRadioButtonElement {
    return page.shadowRoot!.querySelector('#allowThirdParty')!;
  }

  suiteSetup(function() {
    // This test is for the pre-3PCD cookies page.
    loadTimeData.overrideValues({is3pcdCookieSettingsRedesignEnabled: false});
    resetRouterForTesting();

    settingsPrefs = document.createElement('settings-prefs');
    return CrSettingsPrefs.initialized;
  });

  setup(function() {
    document.body.innerHTML = window.trustedTypes!.emptyHTML;

    testMetricsBrowserProxy = new TestMetricsBrowserProxy();
    MetricsBrowserProxyImpl.setInstance(testMetricsBrowserProxy);
    siteSettingsBrowserProxy = new TestSiteSettingsPrefsBrowserProxy();
    SiteSettingsPrefsBrowserProxyImpl.setInstance(siteSettingsBrowserProxy);

    page = document.createElement('settings-cookies-page');
    page.prefs = settingsPrefs.prefs!;

    // Enable one of the PS APIs.
    page.set('prefs.privacy_sandbox.m1.topics_enabled.value', true);
    page.set(
        'prefs.profile.cookie_controls_mode.value', CookieControlsMode.OFF);
    document.body.appendChild(page);
    flush();
  });

  teardown(function() {
    page.remove();
    Router.getInstance().resetRouteForTesting();
  });

  test('ElementVisibility', async function() {
    await flushTasks();
    // Headers
    assertTrue(isChildVisible(page, '#explanationText'));
    assertTrue(isChildVisible(page, '#generalControls'));
    assertTrue(isChildVisible(page, '#additionalProtections'));
    assertTrue(isChildVisible(page, '#exceptionHeader3pcd'));
    assertTrue(isChildVisible(page, '#allow3pcExceptionsList'));
    // Settings
    assertTrue(isChildVisible(page, '#doNotTrack'));
    assertTrue(isChildVisible(page, '#allowThirdParty'));
    assertTrue(isChildVisible(page, '#blockThirdParty'));
    assertTrue(isChildVisible(page, '#blockThirdPartyIncognito'));
    // By default these toggles should be hidden.
    assertFalse(isChildVisible(page, '#blockThirdPartyToggle'));
    assertFalse(isChildVisible(page, '#ipProtectionToggle'));
    assertFalse(isChildVisible(page, '#fingerprintingProtectionToggle'));
  });

  test('ThirdPartyCookiesRadioClicksRecorded', async function() {
    blockThirdParty().click();
    await eventToPromise('selected-changed', primarySettingGroup());
    assertEquals(
        page.getPref('profile.cookie_controls_mode.value'),
        CookieControlsMode.BLOCK_THIRD_PARTY);
    let result =
        await testMetricsBrowserProxy.whenCalled('recordSettingsPageHistogram');
    assertEquals(PrivacyElementInteractions.THIRD_PARTY_COOKIES_BLOCK, result);
    testMetricsBrowserProxy.reset();

    blockThirdPartyIncognito().click();
    await eventToPromise('selected-changed', primarySettingGroup());
    assertEquals(
        page.getPref('profile.cookie_controls_mode.value'),
        CookieControlsMode.INCOGNITO_ONLY);
    result =
        await testMetricsBrowserProxy.whenCalled('recordSettingsPageHistogram');
    assertEquals(
        PrivacyElementInteractions.THIRD_PARTY_COOKIES_BLOCK_IN_INCOGNITO,
        result);
    testMetricsBrowserProxy.reset();

    allowThirdParty().click();
    await eventToPromise('selected-changed', primarySettingGroup());
    assertEquals(
        page.getPref('profile.cookie_controls_mode.value'),
        CookieControlsMode.OFF);
    result =
        await testMetricsBrowserProxy.whenCalled('recordSettingsPageHistogram');
    assertEquals(PrivacyElementInteractions.THIRD_PARTY_COOKIES_ALLOW, result);
    testMetricsBrowserProxy.reset();
  });

  test('privacySandboxToast', async function() {
    assertFalse(page.$.toast.open);

    // Disabling third-party cookies should display the privacy sandbox toast.
    blockThirdParty().click();
    await eventToPromise('selected-changed', primarySettingGroup());
    await flushTasks();
    assertEquals(
        page.getPref('profile.cookie_controls_mode.value'),
        CookieControlsMode.BLOCK_THIRD_PARTY);
    // TODO(crbug.com/40244046): Check historgrams.
    assertTrue(page.$.toast.open);

    // Clicking the toast link should be recorded in UMA and should dismiss
    // the toast.
    page.$.toast.querySelector('cr-button')!.click();
    // TODO(crbug.com/40244046): Check historgrams.
    assertFalse(page.$.toast.open);

    // Renabling 3P cookies for regular sessions should not display the toast.
    blockThirdPartyIncognito().click();
    await eventToPromise('selected-changed', primarySettingGroup());
    await flushTasks();
    assertEquals(
        page.getPref('profile.cookie_controls_mode.value'),
        CookieControlsMode.INCOGNITO_ONLY);
    assertFalse(page.$.toast.open);

    // The toast should not be displayed if the user has all privacy sandbox
    // APIs disabled.
    page.set('prefs.privacy_sandbox.m1.topics_enabled.value', false);
    blockThirdParty().click();
    await flushTasks();
    assertEquals(
        page.getPref('profile.cookie_controls_mode.value'),
        CookieControlsMode.BLOCK_THIRD_PARTY);
    assertFalse(page.$.toast.open);

    // Reset the state to show the toast.
    page.set('prefs.privacy_sandbox.m1.topics_enabled.value', true);
    page.set(
        'prefs.profile.cookie_controls_mode.value',
        CookieControlsMode.INCOGNITO_ONLY);
    blockThirdParty().click();
    await eventToPromise('selected-changed', primarySettingGroup());
    await flushTasks();
    assertEquals(
        page.getPref('profile.cookie_controls_mode.value'),
        CookieControlsMode.BLOCK_THIRD_PARTY);
    // TODO(crbug.com/40244046): Check historgrams.
    assertTrue(page.$.toast.open);

    // Reselecting a non-3P cookie blocking setting should hide the toast.
    allowThirdParty().click();
    await eventToPromise('selected-changed', primarySettingGroup());
    await flushTasks();
    assertEquals(
        page.getPref('profile.cookie_controls_mode.value'),
        CookieControlsMode.OFF);
    assertFalse(page.$.toast.open);

    // Navigating away from the page should hide the toast, even if navigated
    // back to.
    blockThirdParty().click();
    await eventToPromise('selected-changed', primarySettingGroup());
    await flushTasks();
    assertEquals(
        page.getPref('profile.cookie_controls_mode.value'),
        CookieControlsMode.BLOCK_THIRD_PARTY);
    assertTrue(page.$.toast.open);
    Router.getInstance().navigateTo(routes.BASIC);
    Router.getInstance().navigateTo(routes.COOKIES);
    await flushTasks();
    assertFalse(page.$.toast.open);
  });

  test('privacySandboxToast_restrictedSandbox', async function() {
    // No toast should be shown if the privacy sandbox is restricted
    loadTimeData.overrideValues({isPrivacySandboxRestricted: true});
    resetRouterForTesting();

    page.set('prefs.privacy_sandbox.m1.topics_enabled.value', true);
    blockThirdParty().click();
    assertEquals(
        'Settings.PrivacySandbox.Block3PCookies',
        await testMetricsBrowserProxy.whenCalled('recordAction'));
    testMetricsBrowserProxy.resetResolver('recordAction');
    assertFalse(page.$.toast.open);
  });

  test('disabledRWSToggle', async () => {
    // Confirm that when the user has not selected the block 3PC setting, the
    // RWS toggle is disabled.
    const relatedWebsiteSetsToggle =
        page.shadowRoot!.querySelector<SettingsToggleButtonElement>(
            '#relatedWebsiteSetsToggle')!;
    blockThirdParty().click();
    await eventToPromise('selected-changed', primarySettingGroup());
    assertEquals(
        CookieControlsMode.BLOCK_THIRD_PARTY,
        page.prefs.profile.cookie_controls_mode.value);
    assertFalse(
        relatedWebsiteSetsToggle.disabled, 'expect toggle to be enabled');

    allowThirdParty().click();
    await eventToPromise('selected-changed', primarySettingGroup());
    assertEquals(
        CookieControlsMode.OFF, page.prefs.profile.cookie_controls_mode.value);
    assertTrue(
        relatedWebsiteSetsToggle.disabled, 'expect toggle to be disabled');

    blockThirdPartyIncognito().click();
    await eventToPromise('selected-changed', primarySettingGroup());
    assertEquals(
        CookieControlsMode.INCOGNITO_ONLY,
        page.prefs.profile.cookie_controls_mode.value);
    assertTrue(
        relatedWebsiteSetsToggle.disabled, 'expect toggle to be disabled');
  });

  test('blockThirdPartyIncognitoSecondBulletPointText', function() {
    // Confirm the correct string is set.
    const cookiesPageBlockThirdPartyIncognitoBulTwoLabel =
        page.shadowRoot!
            .querySelector<HTMLElement>(
                '#blockThirdPartyIncognitoBulTwo')!.innerText.trim();
    assertEquals(
        loadTimeData.getString('cookiePageBlockThirdIncognitoBulTwoRws'),
        cookiesPageBlockThirdPartyIncognitoBulTwoLabel);
  });
});

suite('ExceptionsList', function() {
  let siteSettingsBrowserProxy: TestSiteSettingsPrefsBrowserProxy;
  let page: SettingsCookiesPageElement;
  let settingsPrefs: SettingsPrefsElement;

  suiteSetup(function() {
    settingsPrefs = document.createElement('settings-prefs');
    return CrSettingsPrefs.initialized;
  });

  setup(function() {
    document.body.innerHTML = window.trustedTypes!.emptyHTML;

    siteSettingsBrowserProxy = new TestSiteSettingsPrefsBrowserProxy();
    SiteSettingsPrefsBrowserProxyImpl.setInstance(siteSettingsBrowserProxy);

    page = document.createElement('settings-cookies-page');
    page.prefs = settingsPrefs.prefs!;
    document.body.appendChild(page);
    flush();
  });

  test('ExceptionsSearch', async function() {
    await siteSettingsBrowserProxy.whenCalled('getExceptionList');
    siteSettingsBrowserProxy.resetResolver('getExceptionList');

    const exceptionPrefs = createSiteSettingsPrefs([], [
      createContentSettingTypeToValuePair(
          ContentSettingsTypes.COOKIES,
          [
            createRawSiteException(SITE_EXCEPTION_WILDCARD, {
              embeddingOrigin: 'foo-allow.com',
            }),
          ]),
    ]);
    page.searchTerm = 'foo';
    siteSettingsBrowserProxy.setPrefs(exceptionPrefs);
    await siteSettingsBrowserProxy.whenCalled('getExceptionList');
    flush();

    const exceptionList = page.shadowRoot!.querySelector('site-list');
    assertTrue(!!exceptionList);
    assertTrue(isChildVisible(exceptionList, 'site-list-entry'));

    page.searchTerm = 'unrelated.com';
    flush();

    assertFalse(isChildVisible(exceptionList, 'site-list-entry'));
  });

  test('ExceptionListHasCorrectCookieExceptionType', function() {
    const exceptionList = page.shadowRoot!.querySelector('site-list');
    assertTrue(!!exceptionList);
    assertEquals(
        'third-party', exceptionList.getAttribute('cookies-exception-type'));
  });
});

// TODO(crbug.com/40233724): Remove after crbug/1349370 is launched.
suite('FirstPartySetsUIDisabled', function() {
  let page: SettingsCookiesPageElement;
  let settingsPrefs: SettingsPrefsElement;

  suiteSetup(function() {
    loadTimeData.overrideValues({
      firstPartySetsUIEnabled: false,
      // FirstPartySetsUI does not exist in 3PCD.
      is3pcdCookieSettingsRedesignEnabled: false,
    });
    resetRouterForTesting();

    settingsPrefs = document.createElement('settings-prefs');
    return CrSettingsPrefs.initialized;
  });

  setup(function() {
    document.body.innerHTML = window.trustedTypes!.emptyHTML;

    page = document.createElement('settings-cookies-page');
    page.prefs = settingsPrefs.prefs!;
    document.body.appendChild(page);
    flush();
  });

  teardown(function() {
    page.remove();
  });

  test('blockThirdPartyIncognitoSecondBulletPointText', function() {
    // Confirm the correct string is set.
    const cookiesPageBlockThirdPartyIncognitoBulTwoLabel =
        page.shadowRoot!
            .querySelector<HTMLElement>(
                '#blockThirdPartyIncognitoBulTwo')!.innerText.trim();
    assertEquals(
        loadTimeData.getString('thirdPartyCookiesPageBlockIncognitoBulTwo'),
        cookiesPageBlockThirdPartyIncognitoBulTwoLabel);
  });
});

suite('TrackingProtectionSettings', function() {
  let page: SettingsCookiesPageElement;
  let settingsPrefs: SettingsPrefsElement;
  let testMetricsBrowserProxy: TestMetricsBrowserProxy;

  suiteSetup(function() {
    loadTimeData.overrideValues({is3pcdCookieSettingsRedesignEnabled: true});
    resetRouterForTesting();

    settingsPrefs = document.createElement('settings-prefs');
    return CrSettingsPrefs.initialized;
  });

  setup(function() {
    document.body.innerHTML = window.trustedTypes!.emptyHTML;

    testMetricsBrowserProxy = new TestMetricsBrowserProxy();
    MetricsBrowserProxyImpl.setInstance(testMetricsBrowserProxy);

    page = document.createElement('settings-cookies-page');
    page.prefs = settingsPrefs.prefs!;
    document.body.appendChild(page);
    flush();
  });

  test('CheckVisibility', function() {
    // Page description
    assertTrue(isChildVisible(page, '#default'));
    assertEquals(
        page.shadowRoot!.querySelector<HTMLAnchorElement>(
                            'a[href]')!.getAttribute('aria-description'),
        page.i18n('opensInNewTab'));

    // Additional toggles
    assertTrue(isChildVisible(page, '#blockThirdPartyToggle'));
    assertTrue(isChildVisible(page, '#doNotTrack'));

    // Site Exception list
    assertFalse(isChildVisible(page, '#exceptionHeader'));
    assertFalse(isChildVisible(page, '#exceptionHeaderSubLabel'));
    assertTrue(isChildVisible(page, '#exceptionHeader3pcd'));
    assertTrue(isChildVisible(page, '#allow3pcExceptionsList'));
  });

  test('BlockAll3pcToggle', async function() {
    page.set(
        'prefs.tracking_protection.block_all_3pc_toggle_enabled.value', false);
    const blockThirdPartyCookiesToggle =
        page.shadowRoot!.querySelector<SettingsToggleButtonElement>(
            '#blockThirdPartyToggle')!;
    assertTrue(!!blockThirdPartyCookiesToggle);

    blockThirdPartyCookiesToggle.click();
    const result =
        await testMetricsBrowserProxy.whenCalled('recordSettingsPageHistogram');
    assertEquals(
        PrivacyElementInteractions.BLOCK_ALL_THIRD_PARTY_COOKIES, result);
    assertEquals(
        'Settings.PrivacySandbox.Block3PCookies',
        await testMetricsBrowserProxy.whenCalled('recordAction'));
    assertEquals(
        page.getPref('tracking_protection.block_all_3pc_toggle_enabled.value'),
        true);
  });
});

suite('ActSettings', function() {
  let page: SettingsCookiesPageElement;
  let settingsPrefs: SettingsPrefsElement;
  let testMetricsBrowserProxy: TestMetricsBrowserProxy;

  suiteSetup(function() {
    loadTimeData.overrideValues({
      isIpProtectionUxEnabled: true,
      isFingerprintingProtectionUxEnabled: true,
    });
    resetRouterForTesting();

    settingsPrefs = document.createElement('settings-prefs');
    return CrSettingsPrefs.initialized;
  });

  setup(function() {
    document.body.innerHTML = window.trustedTypes!.emptyHTML;

    testMetricsBrowserProxy = new TestMetricsBrowserProxy();
    MetricsBrowserProxyImpl.setInstance(testMetricsBrowserProxy);

    page = document.createElement('settings-cookies-page');
    page.prefs = settingsPrefs.prefs!;
    document.body.appendChild(page);
    flush();
  });

  test('CheckVisibility', function() {
    // Settings are visible
    assertTrue(isChildVisible(page, '#ipProtectionToggle'));
    assertTrue(isChildVisible(page, '#fingerprintingProtectionToggle'));
  });

  test('ToggleIpProtection', async function() {
    page.set('prefs.tracking_protection.ip_protection_enabled.value', false);
    const ipProtectionToggle =
        page.shadowRoot!.querySelector<SettingsToggleButtonElement>(
            '#ipProtectionToggle')!;
    assertTrue(!!ipProtectionToggle);

    ipProtectionToggle.click();
    const result =
        await testMetricsBrowserProxy.whenCalled('recordSettingsPageHistogram');
    assertEquals(PrivacyElementInteractions.IP_PROTECTION, result);
    assertEquals(
        page.getPref('tracking_protection.ip_protection_enabled.value'), true);
  });

  test('ToggleFingerprintingProtection', async function() {
    page.set(
        'prefs.tracking_protection.fingerprinting_protection_enabled.value',
        false);
    const fingerprintingProtectionToggle =
        page.shadowRoot!.querySelector<SettingsToggleButtonElement>(
            '#fingerprintingProtectionToggle')!;
    assertTrue(!!fingerprintingProtectionToggle);

    fingerprintingProtectionToggle.click();
    const result =
        await testMetricsBrowserProxy.whenCalled('recordSettingsPageHistogram');
    assertEquals(PrivacyElementInteractions.FINGERPRINTING_PROTECTION, result);
    assertEquals(
        page.getPref(
            'tracking_protection.fingerprinting_protection_enabled.value'),
        true);
  });
});