chromium/chrome/browser/trusted_vault/trusted_vault_encryption_keys_tab_helper_browsertest.cc

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/trusted_vault/trusted_vault_encryption_keys_tab_helper.h"

#include <string>
#include <tuple>
#include <vector>

#include "base/feature_list.h"
#include "base/path_service.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/trusted_vault/trusted_vault_service_factory.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/chrome_test_utils.h"
#include "chrome/test/base/platform_browser_test.h"
#include "components/metrics/content/subprocess_metrics_provider.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "components/signin/public/identity_manager/account_info.h"
#include "components/trusted_vault/features.h"
#include "components/trusted_vault/trusted_vault_client.h"
#include "components/trusted_vault/trusted_vault_server_constants.h"
#include "components/trusted_vault/trusted_vault_service.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/fenced_frame_test_util.h"
#include "content/public/test/prerender_test_util.h"
#include "device/fido/features.h"
#include "google_apis/gaia/gaia_switches.h"
#include "google_apis/gaia/gaia_urls.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "url/gurl.h"

#if BUILDFLAG(IS_ANDROID)
#include "components/site_isolation/features.h"
#else
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/webauthn/enclave_manager.h"
#include "chrome/browser/webauthn/enclave_manager_factory.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/signin/public/identity_manager/identity_test_utils.h"
#include "components/trusted_vault/standalone_trusted_vault_client.h"
#endif  // BUILDFLAG(IS_ANDROID)

#if BUILDFLAG(IS_CHROMEOS_LACROS)
#include "chromeos/crosapi/mojom/trusted_vault.mojom.h"
#include "chromeos/lacros/lacros_service.h"
#endif

namespace {

ElementsAre;
ElementsAreArray;
Eq;
IsEmpty;

constexpr char kFakeGaiaId[] =;

#if !BUILDFLAG(IS_ANDROID)
const AccountInfo& FakeAccount() {}
#endif

const char kConsoleSuccessMessage[] =;
const char kConsoleFailureMessage[] =;
#if !BUILDFLAG(IS_ANDROID)
const char kConsoleUncaughtTypeErrorMessagePattern[] =;
#endif

// Executes JS to call chrome.setSyncEncryptionKeys(). Either
// |kConsoleSuccessMessage| or |kConsoleFailureMessage| is logged to the console
// upon completion.
void ExecJsSetSyncEncryptionKeys(content::RenderFrameHost* render_frame_host,
                                 const std::vector<uint8_t>& key,
                                 int key_version) {}

void ExecJsSetClientEncryptionKeysForSecurityDomain(
    content::RenderFrameHost* render_frame_host,
    const char* security_domain_name,
    const std::vector<uint8_t>& key) {}

void ExecJsSetClientEncryptionKeys(content::RenderFrameHost* render_frame_host,
                                   const std::vector<uint8_t>& key) {}

#if !BUILDFLAG(IS_ANDROID)
void ExecJsSetClientEncryptionKeysForInvalidSecurityDomain(
    content::RenderFrameHost* render_frame_host,
    const std::vector<uint8_t>& key) {}

void ExecJsSetClientEncryptionKeysWithIllformedArgs(
    content::RenderFrameHost* render_frame_host) {}
#endif

// Executes JS to call chrome.addTrustedSyncEncryptionRecoveryMethod. Either
// |kConsoleSuccessMessage| or |kConsoleFailureMessage| is logged to the console
// upon completion.
void ExecJsAddTrustedSyncEncryptionRecoveryMethod(
    content::RenderFrameHost* render_frame_host,
    const std::vector<uint8_t>& public_key) {}

// Key retrieval doesn't exist on Android and cannot be verified.
#if !BUILDFLAG(IS_ANDROID)
std::vector<std::vector<uint8_t>> FetchTrustedVaultKeysForProfile(
    Profile* profile,
    trusted_vault::SecurityDomainId security_domain,
    const AccountInfo& account_info) {}

int FetchLastTrustedVaultKeyVersionForProfile(
    Profile* profile,
    trusted_vault::SecurityDomainId security_domain,
    const AccountInfo& account_info) {}

#endif  // !BUILDFLAG(IS_ANDROID)

class TrustedVaultEncryptionKeysTabHelperBrowserTest
    : public PlatformBrowserTest {};

class TrustedVaultEncryptionKeysTabHelperWithEnclaveBrowserTest
    : public TrustedVaultEncryptionKeysTabHelperBrowserTest {};

// Tests that chrome.setSyncEncryptionKeys() works in the main frame, except on
// Android. On Android, this particular Javascript API isn't defined.
#if BUILDFLAG(IS_ANDROID)

IN_PROC_BROWSER_TEST_F(TrustedVaultEncryptionKeysTabHelperBrowserTest,
                       ShouldNotBindEncryptionKeysApiOnAndroid) {
  const GURL initial_url =
      https_server()->GetURL("accounts.google.com", "/title1.html");
  ASSERT_TRUE(content::NavigateToURL(web_contents(), initial_url));
  // EncryptionKeysApi is created for the primary page as the origin is allowed.
  EXPECT_TRUE(HasEncryptionKeysApi(web_contents()->GetPrimaryMainFrame()));

  content::WebContentsConsoleObserver console_observer(web_contents());
  console_observer.SetPattern(kConsoleFailureMessage);

  // Calling setSyncEncryptionKeys() or setClientEncryptionKeys() in the main
  // frame shouldn't work.
  const std::vector<uint8_t> kEncryptionKey = {7};
  ExecJsSetSyncEncryptionKeys(web_contents()->GetPrimaryMainFrame(),
                              kEncryptionKey, /*key_version=*/1);
  ASSERT_TRUE(console_observer.Wait());
  EXPECT_EQ(1u, console_observer.messages().size());
  ExecJsSetClientEncryptionKeys(web_contents()->GetPrimaryMainFrame(),
                                kEncryptionKey);
  ASSERT_TRUE(console_observer.Wait());
  EXPECT_EQ(2u, console_observer.messages().size());
}

#else

void ExecJsSetClientEncryptionKeysWithMultipleKeys(
    content::RenderFrameHost* render_frame_host,
    const std::vector<uint8_t>& key1,
    const std::vector<uint8_t>& key2) {}

IN_PROC_BROWSER_TEST_F(TrustedVaultEncryptionKeysTabHelperBrowserTest,
                       ShouldBindSyncEncryptionKeysApiInMainFrame) {}

IN_PROC_BROWSER_TEST_F(TrustedVaultEncryptionKeysTabHelperBrowserTest,
                       ShouldBindClientEncryptionKeysApiInMainFrame) {}

IN_PROC_BROWSER_TEST_F(TrustedVaultEncryptionKeysTabHelperBrowserTest,
                       ClientEncryptionKeysApiShouldSetMultipleKeys) {}

#if !BUILDFLAG(IS_CHROMEOS)
IN_PROC_BROWSER_TEST_F(
    TrustedVaultEncryptionKeysTabHelperWithEnclaveBrowserTest,
    SetPasskeysKeyInEnclaveManager) {}
#endif  // !BUILDFLAG(IS_CHROMEOS)

IN_PROC_BROWSER_TEST_F(
    TrustedVaultEncryptionKeysTabHelperBrowserTest,
    ShouldIgnoreClientEncryptionKeysForInvalidSecurityDomain) {}

IN_PROC_BROWSER_TEST_F(TrustedVaultEncryptionKeysTabHelperBrowserTest,
                       ShouldIgnoreClientEncryptionKeysWithIllformedArgs) {}

// Tests that chrome.setSyncEncryptionKeys() works in a fenced frame.
IN_PROC_BROWSER_TEST_F(TrustedVaultEncryptionKeysTabHelperBrowserTest,
                       ShouldBindSyncEncryptionKeysApiInFencedFrame) {}

// Tests that chrome.setClientEncryptionKeys() works in a fenced frame.
IN_PROC_BROWSER_TEST_F(TrustedVaultEncryptionKeysTabHelperBrowserTest,
                       ShouldBindClientEncryptionKeysApiInFencedFrame) {}

IN_PROC_BROWSER_TEST_F(TrustedVaultEncryptionKeysTabHelperBrowserTest,
                       ShouldIgnoreSyncEncryptionsKeysInIncognito) {}

IN_PROC_BROWSER_TEST_F(TrustedVaultEncryptionKeysTabHelperBrowserTest,
                       ShouldIgnoreClientEncryptionsKeysInIncognito) {}

IN_PROC_BROWSER_TEST_F(TrustedVaultEncryptionKeysTabHelperBrowserTest,
                       ShouldIgnoreRecoveryMethodInIncognito) {}

#endif  // BUILDFLAG(IS_ANDROID)

// Tests that chrome.addTrustedSyncEncryptionRecoveryMethod() works in the main
// frame.
IN_PROC_BROWSER_TEST_F(TrustedVaultEncryptionKeysTabHelperBrowserTest,
                       ShouldBindAddRecoveryMethodApiInMainFrame) {}

// Tests that chrome.setSyncEncryptionKeys() doesn't work in prerendering.
// If it is called in prerendering, it triggers canceling the prerendering
// and EncryptionKeyApi is not bound.
IN_PROC_BROWSER_TEST_F(TrustedVaultEncryptionKeysTabHelperBrowserTest,
                       ShouldNotBindEncryptionKeysApiInPrerendering) {}

// Same as SyncEncryptionKeysTabHelperBrowserTest but switches::kGaiaUrl does
// NOT point to the embedded test server, which means it gets treated as
// disallowed origin.
class TrustedVaultEncryptionKeysTabHelperWithoutAllowedOriginBrowserTest
    : public TrustedVaultEncryptionKeysTabHelperBrowserTest {};

// Tests that chrome.setSyncEncryptionKeys() and
// chrome.setClientEncryptionKeys() doesn't work in disallowed origins.
IN_PROC_BROWSER_TEST_F(
    TrustedVaultEncryptionKeysTabHelperWithoutAllowedOriginBrowserTest,
    ShouldNotBindEncryptionKeys) {}

}  // namespace