chromium/chrome/browser/ash/app_list/search/essential_search/essential_search_manager_unittest.cc

// 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.

#include "chrome/browser/ash/app_list/search/essential_search/essential_search_manager.h"

#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "base/test/test_future.h"
#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "components/prefs/testing_pref_service.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/test/browser_task_environment.h"
#include "net/cookies/canonical_cookie.h"
#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace ash::test {
namespace {
constexpr char kEmail[] = "[email protected]";
constexpr char16_t kEmail16[] = u"[email protected]";
constexpr char kValidCookieHeader[] =
    "%s=%s; Domain=.google.com; Expires=Thu, 01-Jan-2026 00:00:00 GMT; Path=/; "
    "Secure; SameSite=lax";
constexpr char kCookieName[] = "SOCS";
constexpr char kCookieValue[] = "SOCS_VALUE";
}  // namespace

class EssentialSearchManagerTest : public testing::Test {
 protected:
  EssentialSearchManagerTest();
  ~EssentialSearchManagerTest() override;

  // testing::Test:
  void SetUp() override;

  void CreateEssentialSearchManager();
  void DestroyEssentialSearchManager();

  net::CookieList GetCookiesInUserProfile();

  void ExpectSocsCookieInUserProfile(const std::string& cookie_name,
                                     const std::string& cookie_value);

  content::BrowserTaskEnvironment task_environment_{
      base::test::TaskEnvironment::TimeSource::MOCK_TIME};

  std::unique_ptr<IdentityTestEnvironmentProfileAdaptor>
      identity_test_env_adaptor_;
  raw_ptr<signin::IdentityTestEnvironment> identity_test_env_;

  std::unique_ptr<TestingProfileManager> profile_manager_;
  raw_ptr<TestingProfile> profile_;

  std::unique_ptr<app_list::EssentialSearchManager> essential_search_manager_;
};

EssentialSearchManagerTest::EssentialSearchManagerTest()
    : essential_search_manager_(nullptr) {}

EssentialSearchManagerTest::~EssentialSearchManagerTest() = default;

void EssentialSearchManagerTest::SetUp() {
  profile_manager_ = std::make_unique<TestingProfileManager>(
      TestingBrowserProcess::GetGlobal());
  ASSERT_TRUE(profile_manager_->SetUp());
  profile_ = profile_manager_->CreateTestingProfile(
      kEmail, /*prefs=*/{}, kEmail16,
      /*avatar_id=*/0,
      IdentityTestEnvironmentProfileAdaptor::
          GetIdentityTestEnvironmentFactories());
  identity_test_env_adaptor_ =
      std::make_unique<IdentityTestEnvironmentProfileAdaptor>(profile_.get());
  identity_test_env_ = identity_test_env_adaptor_->identity_test_env();
}

void EssentialSearchManagerTest::CreateEssentialSearchManager() {
  essential_search_manager_ =
      std::make_unique<app_list::EssentialSearchManager>(profile_);
}

net::CookieList EssentialSearchManagerTest::GetCookiesInUserProfile() {
  base::test::TestFuture<const net::CookieList&> future;
  profile_->GetDefaultStoragePartition()
      ->GetCookieManagerForBrowserProcess()
      ->GetAllCookies(future.GetCallback());

  return future.Take();
}

void EssentialSearchManagerTest::ExpectSocsCookieInUserProfile(
    const std::string& cookie_name,
    const std::string& cookie_value) {
  net::CookieList cookie_list = GetCookiesInUserProfile();
  EXPECT_GT(cookie_list.size(), 0u);

  const auto socs_cookie_iterator = base::ranges::find(
      cookie_list, cookie_name,
      [](const net::CanonicalCookie& cookie) { return cookie.Name(); });
  ASSERT_NE(socs_cookie_iterator, cookie_list.end());
  EXPECT_EQ(cookie_value, socs_cookie_iterator->Value());
}

TEST_F(EssentialSearchManagerTest, OnCookieFetchedSucceed) {
  identity_test_env_->MakePrimaryAccountAvailable(kEmail,
                                                  signin::ConsentLevel::kSync);
  // Enable EssentialSearchEnabled policy
  profile_->GetTestingPrefService()->SetManagedPref(
      prefs::kEssentialSearchEnabled, base::Value(true));

  CreateEssentialSearchManager();

  base::RunLoop run_loop;
  essential_search_manager_->set_cookie_insertion_closure_for_test(
      run_loop.QuitClosure());

  // Add SOCS cookie to the user profile
  std::string cookie_header =
      base::StringPrintf(kValidCookieHeader, kCookieName, kCookieValue);
  essential_search_manager_->OnCookieFetched(cookie_header);
  run_loop.Run();

  ExpectSocsCookieInUserProfile(kCookieName, kCookieValue);
}

TEST_F(EssentialSearchManagerTest, PolicyDisabledWhileUserInSession) {
  identity_test_env_->MakePrimaryAccountAvailable(kEmail,
                                                  signin::ConsentLevel::kSync);
  // Enable EssentialSearchEnabled policy
  profile_->GetTestingPrefService()->SetManagedPref(
      prefs::kEssentialSearchEnabled, base::Value(true));

  CreateEssentialSearchManager();

  // Set run loops.
  base::RunLoop insertion_loop, deletion_loop;
  essential_search_manager_->set_cookie_insertion_closure_for_test(
      insertion_loop.QuitClosure());
  essential_search_manager_->set_cookie_deletion_closure_for_test(
      deletion_loop.QuitClosure());

  // Add SOCS cookie to the user profile
  std::string cookie_header =
      base::StringPrintf(kValidCookieHeader, kCookieName, kCookieValue);
  essential_search_manager_->OnCookieFetched(cookie_header);
  insertion_loop.Run();

  ExpectSocsCookieInUserProfile(kCookieName, kCookieValue);

  // Disable EssentialSearchEnabled policy
  profile_->GetTestingPrefService()->SetManagedPref(
      prefs::kEssentialSearchEnabled, base::Value(false));

  // Wait for cookie deletion.
  deletion_loop.Run();

  // Expect SOCS cookie being removed from user profile.
  net::CookieList cookie_list = GetCookiesInUserProfile();
  EXPECT_THAT(cookie_list, testing::IsEmpty());
}

TEST_F(EssentialSearchManagerTest, PolicyDisabledWhileFetchingCookie) {
  identity_test_env_->MakePrimaryAccountAvailable(kEmail,
                                                  signin::ConsentLevel::kSync);
  // Simulate policy being disabled while fetching the cookie.
  profile_->GetTestingPrefService()->SetManagedPref(
      prefs::kEssentialSearchEnabled, base::Value(false));

  CreateEssentialSearchManager();

  // Set run loops.
  base::RunLoop insertion_loop, deletion_loop;
  essential_search_manager_->set_cookie_insertion_closure_for_test(
      insertion_loop.QuitClosure());
  essential_search_manager_->set_cookie_deletion_closure_for_test(
      deletion_loop.QuitClosure());

  // Add SOCS cookie to the user profile.
  std::string cookie_header =
      base::StringPrintf(kValidCookieHeader, kCookieName, kCookieValue);
  essential_search_manager_->OnCookieFetched(cookie_header);
  insertion_loop.Run();

  // Wait for cookie deletion.
  deletion_loop.Run();

  // Expect SOCS cookie being removed from user profile.
  net::CookieList cookie_list = GetCookiesInUserProfile();
  EXPECT_EQ(cookie_list.size(), 0u);
}

}  // namespace ash::test