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

#include "android_webview/browser/cookie_manager.h"

#include <stdint.h>

#include <memory>
#include <optional>
#include <utility>
#include <vector>

#include "android_webview/browser/aw_browser_context.h"
#include "android_webview/browser/aw_browser_context_store.h"
#include "android_webview/browser/aw_client_hints_controller_delegate.h"
#include "android_webview/browser/aw_cookie_access_policy.h"
#include "android_webview/common/aw_switches.h"
#include "base/android/android_info.h"
#include "base/android/apk_info.h"
#include "base/android/callback_android.h"
#include "base/android/jni_string.h"
#include "base/android/path_utils.h"
#include "base/android/scoped_java_ref.h"
#include "base/command_line.h"
#include "base/containers/circular_deque.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/metrics/histogram_functions.h"
#include "base/no_destructor.h"
#include "base/path_service.h"
#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "base/values.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/cookie_store_factory.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_constants.h"
#include "net/cookies/cookie_monster.h"
#include "net/cookies/cookie_options.h"
#include "net/cookies/cookie_partition_key.h"
#include "net/cookies/cookie_store.h"
#include "net/cookies/cookie_util.h"
#include "net/cookies/parsed_cookie.h"
#include "net/url_request/url_request_context.h"
#include "services/network/cookie_access_delegate_impl.h"
#include "services/network/network_service.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
#include "url/url_constants.h"

// Must come after all headers that specialize FromJniType() / ToJniType().
#include "android_webview/browser_jni_headers/AwCookieManager_jni.h"

using base::WaitableEvent;
using base::android::ConvertJavaStringToUTF16;
using base::android::ConvertJavaStringToUTF8;
using base::android::JavaParamRef;
using base::android::ScopedJavaGlobalRef;
using base::android::ScopedJavaLocalRef;
using content::BrowserThread;
using net::CookieList;

// In the future, we may instead want to inject an explicit CookieStore
// dependency into this object during process initialization to avoid
// depending on the URLRequestContext.
// See issue http://crbug.com/157683

// On the CookieManager methods without a callback and methods with a callback
// when that callback is null can be called from any thread, including threads
// without a message loop. Methods with a non-null callback must be called on
// a thread with a running message loop.

namespace android_webview {

namespace {

void MaybeRunCookieCallback(base::OnceCallback<void(bool)> callback,
                            const bool& result) {
  if (callback)
    std::move(callback).Run(result);
}

const char kSecureCookieHistogramName[] = "Android.WebView.SecureCookieAction";

// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class SecureCookieAction {
  kInvalidUrl = 0,
  kAlreadySecureScheme = 1,
  kInvalidCookie = 2,
  kNotASecureCookie = 3,
  kFixedUp = 4,
  kDisallowedAndroidR = 5,
  kMaxValue = kDisallowedAndroidR,
};

GURL MaybeFixUpSchemeForSecureCookie(const GURL& host,
                                     const std::string& value,
                                     bool workaround_http_secure_cookies,
                                     bool* should_allow_cookie) {
  net::ParsedCookie parsed_cookie(value);

  *should_allow_cookie = true;

  // Log message for catching strict secure cookies related bugs.
  // TODO(ntfschr): try to remove this, based on UMA stats
  // (https://crbug.com/933981)
  if (!host.is_valid()) {
    base::UmaHistogramEnumeration(kSecureCookieHistogramName,
                                  SecureCookieAction::kInvalidUrl);
    return host;
  }
  if (host.has_scheme() && !host.SchemeIs(url::kHttpScheme)) {
    base::UmaHistogramEnumeration(kSecureCookieHistogramName,
                                  SecureCookieAction::kAlreadySecureScheme);
    return host;
  }
  if (!parsed_cookie.IsValid()) {
    base::UmaHistogramEnumeration(kSecureCookieHistogramName,
                                  SecureCookieAction::kInvalidCookie);
    return host;
  }
  if (!parsed_cookie.IsSecure()) {
    base::UmaHistogramEnumeration(kSecureCookieHistogramName,
                                  SecureCookieAction::kNotASecureCookie);
    return host;
  }

  LOG(ERROR) << "Strict Secure Cookie policy does not allow setting a "
                "secure cookie for "
             << host.spec()
             << " for apps targeting >= R. Please either use the 'https:' "
                "scheme for this URL or omit the 'Secure' directive in the "
                "cookie value.";
  if (!workaround_http_secure_cookies) {
    // Don't allow setting this cookie if we target >= R.
    *should_allow_cookie = false;
    base::UmaHistogramEnumeration(kSecureCookieHistogramName,
                                  SecureCookieAction::kDisallowedAndroidR);
    return host;
  }

  base::UmaHistogramEnumeration(kSecureCookieHistogramName,
                                SecureCookieAction::kFixedUp);
  GURL::Replacements replace_host;
  replace_host.SetSchemeStr(url::kHttpsScheme);
  return host.ReplaceComponents(replace_host);
}

// Construct a closure which signals a waitable event if and when the closure
// is called the waitable event must still exist.
static base::OnceClosure SignalEventClosure(WaitableEvent* completion) {
  return base::BindOnce(&WaitableEvent::Signal, base::Unretained(completion));
}

static void DiscardBool(base::OnceClosure f, bool b) {
  std::move(f).Run();
}

static base::OnceCallback<void(bool)> BoolCallbackAdapter(base::OnceClosure f) {
  return base::BindOnce(&DiscardBool, std::move(f));
}

static void DiscardInt(base::OnceClosure f, int i) {
  std::move(f).Run();
}

static base::OnceCallback<void(int)> IntCallbackAdapter(base::OnceClosure f) {
  return base::BindOnce(&DiscardInt, std::move(f));
}

// Are cookies allowed for file:// URLs by default?
const bool kDefaultFileSchemeAllowed = false;

}  // namespace

// static
CookieManager* CookieManager::GetDefaultInstance() {
  static base::NoDestructor<CookieManager> instance(nullptr);
  return instance.get();
}

namespace {
base::FilePath GetPathInAppDirectory(std::string path) {
  base::FilePath result;
  if (!base::PathService::Get(base::DIR_ANDROID_APP_DATA, &result)) {
    NOTREACHED() << "Failed to get app data directory for Android WebView";
  }
  result = result.Append(FILE_PATH_LITERAL(path));
  return result;
}
}  // namespace

CookieManager::CookieManager(AwBrowserContext* const parent_context)
    : parent_context_(parent_context),
      allow_file_scheme_cookies_(kDefaultFileSchemeAllowed),
      cookie_store_created_(false),
      workaround_http_secure_cookies_(
          base::android::apk_info::target_sdk_version() <
          base::android::android_info::SDK_VERSION_R),
      cookie_store_client_thread_("CookieMonsterClient"),
      cookie_store_backend_thread_("CookieMonsterBackend"),
      setting_new_mojo_cookie_manager_(false) {
  // Apps can specify a list of Profiles (BrowserContexts) to be initialized at
  // startup, meaning this can be called after thread restrictions are applied.
  base::ScopedAllowBlocking scoped_allow_blocking;
  cookie_store_client_thread_.Start();
  cookie_store_backend_thread_.Start();
  cookie_store_task_runner_ = cookie_store_client_thread_.task_runner();
  cookie_store_path_ = GetContextPath().Append(FILE_PATH_LITERAL("Cookies"));
  if (!parent_context_) {
    // Default profile
    MigrateCookieStorePath();
  }
}

CookieManager::~CookieManager() = default;

void CookieManager::MigrateCookieStorePath() {
  base::FilePath old_cookie_store_path = GetPathInAppDirectory("Cookies");
  base::FilePath old_cookie_journal_path =
      GetPathInAppDirectory("Cookies-journal");
  base::FilePath new_cookie_journal_path =
      GetPathInAppDirectory("Default/Cookies-journal");

  if (base::PathExists(old_cookie_store_path)) {
    base::CreateDirectory(cookie_store_path_.DirName());
    base::Move(old_cookie_store_path, cookie_store_path_);
    base::Move(old_cookie_journal_path, new_cookie_journal_path);
  }
}

// Executes the |task| on |cookie_store_task_runner_| and waits for it to
// complete before returning.
//
// To execute a CookieTask synchronously you must arrange for Signal to be
// called on the waitable event at some point. You can call the bool or int
// versions of ExecCookieTaskSync, these will supply the caller with a
// placeholder callback which takes an int/bool, throws it away and calls
// Signal. Alternatively you can call the version which supplies a Closure in
// which case you must call Run on it when you want the unblock the calling
// code.
//
// Ignore a bool callback.
void CookieManager::ExecCookieTaskSync(
    base::OnceCallback<void(base::OnceCallback<void(bool)>)> task) {
  WaitableEvent completion(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                           base::WaitableEvent::InitialState::NOT_SIGNALED);
  ExecCookieTask(base::BindOnce(
      std::move(task), BoolCallbackAdapter(SignalEventClosure(&completion))));

  // Waiting is necessary when implementing synchronous APIs for the WebView
  // embedder.
  base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope wait;
  completion.Wait();
}

// Ignore an int callback.
void CookieManager::ExecCookieTaskSync(
    base::OnceCallback<void(base::OnceCallback<void(int)>)> task) {
  WaitableEvent completion(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                           base::WaitableEvent::InitialState::NOT_SIGNALED);
  ExecCookieTask(base::BindOnce(
      std::move(task), IntCallbackAdapter(SignalEventClosure(&completion))));
  base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope wait;
  completion.Wait();
}

// Call the supplied closure when you want to signal that the blocked code can
// continue.
void CookieManager::ExecCookieTaskSync(
    base::OnceCallback<void(base::OnceClosure)> task) {
  WaitableEvent completion(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                           base::WaitableEvent::InitialState::NOT_SIGNALED);
  ExecCookieTask(
      base::BindOnce(std::move(task), SignalEventClosure(&completion)));
  base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope wait;
  completion.Wait();
}

// Executes the |task| using |cookie_store_task_runner_|.
void CookieManager::ExecCookieTask(base::OnceClosure task) {
  base::AutoLock lock(task_queue_lock_);
  tasks_.push_back(std::move(task));
  // Unretained is safe, since android_webview::CookieManager is a singleton we
  // never destroy (we don't need PostTask to do any memory management).
  cookie_store_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&CookieManager::RunPendingCookieTasks,
                                base::Unretained(this)));
}

void CookieManager::RunPendingCookieTasks() {
  DCHECK(cookie_store_task_runner_->RunsTasksInCurrentSequence());
  // Don't do any cookie tasks if in the middle of setting a mojo CookieManager,
  // we'll call this method when that operation is finished.
  if (setting_new_mojo_cookie_manager_)
    return;

  // Copy tasks into temp_queue to minimize the amount of time in the critical
  // section, and to mitigate live-lock issues if these tasks append to the task
  // queue themselves.
  base::circular_deque<base::OnceClosure> temp_queue;
  {
    base::AutoLock lock(task_queue_lock_);
    temp_queue.swap(tasks_);
  }
  while (!temp_queue.empty()) {
    std::move(temp_queue.front()).Run();
    temp_queue.pop_front();
  }
}

base::FilePath CookieManager::GetCookieStorePath() {
  return cookie_store_path_;
}

net::CookieStore* CookieManager::GetCookieStore() {
  // This should only be called for the default context.
  CHECK(!parent_context_);
  DCHECK(cookie_store_task_runner_->RunsTasksInCurrentSequence());

  if (!cookie_store_) {
    content::CookieStoreConfig cookie_config(
        cookie_store_path_, /* restore_old_session_cookies= */ true,
        /* persist_session_cookies= */ true);
    cookie_config.client_task_runner = cookie_store_task_runner_;
    cookie_config.background_task_runner =
        cookie_store_backend_thread_.task_runner();

    {
      base::AutoLock lock(allow_file_scheme_cookies_lock_);

      // There are some unknowns about how to correctly handle file:// cookies,
      // and our implementation for this is not robust.  http://crbug.com/582985
      //
      // TODO(mmenke): This call should be removed once we can deprecate and
      // remove the Android WebView 'CookieManager::SetAllowFileSchemeCookies'
      // method. Until then, note that this is just not a great idea.
      cookie_config.cookieable_schemes =
          net::CookieMonster::GetDefaultCookieableSchemes();
      if (allow_file_scheme_cookies_) {
        cookie_config.cookieable_schemes.emplace_back(url::kFileScheme);
      }
      cookie_store_created_ = true;
    }

    cookie_store_ =
        content::CreateCookieStore(std::move(cookie_config), nullptr);
    auto cookie_access_delegate_type =
        base::CommandLine::ForCurrentProcess()->HasSwitch(
            switches::kWebViewEnableModernCookieSameSite)
            ? network::mojom::CookieAccessDelegateType::ALWAYS_NONLEGACY
            : network::mojom::CookieAccessDelegateType::ALWAYS_LEGACY;
    cookie_store_->SetCookieAccessDelegate(
        std::make_unique<network::CookieAccessDelegateImpl>(
            cookie_access_delegate_type, nullptr /* first_party_sets */));
  }

  return cookie_store_.get();
}

network::mojom::CookieManager* CookieManager::GetMojoCookieManager() {
  DCHECK(cookie_store_task_runner_->RunsTasksInCurrentSequence());
  if (!mojo_cookie_manager_.is_bound())
    return nullptr;
  return mojo_cookie_manager_.get();
}

void CookieManager::SetMojoCookieManager(
    mojo::PendingRemote<network::mojom::CookieManager> cookie_manager_remote) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  ExecCookieTaskSync(base::BindOnce(&CookieManager::SetMojoCookieManagerAsync,
                                    base::Unretained(this),
                                    std::move(cookie_manager_remote)));
}

void CookieManager::SetMojoCookieManagerAsync(
    mojo::PendingRemote<network::mojom::CookieManager> cookie_manager_remote,
    base::OnceClosure complete) {
  DCHECK(cookie_store_task_runner_->RunsTasksInCurrentSequence());
  setting_new_mojo_cookie_manager_ = true;
  // For simplicity, only permit this method to be called once (otherwise, we
  // must sometimes flush the mojo_cookie_manager_ instead of cookie_store_).
  DCHECK(!mojo_cookie_manager_.is_bound());
  if (!cookie_store_created_) {
    SwapMojoCookieManagerAsync(std::move(cookie_manager_remote),
                               std::move(complete));
    return;
  }

  GetCookieStore()->FlushStore(base::BindOnce(
      &CookieManager::SwapMojoCookieManagerAsync, base::Unretained(this),
      std::move(cookie_manager_remote), std::move(complete)));
}

void CookieManager::SwapMojoCookieManagerAsync(
    mojo::PendingRemote<network::mojom::CookieManager> cookie_manager_remote,
    base::OnceClosure complete) {
  DCHECK(cookie_store_task_runner_->RunsTasksInCurrentSequence());
  mojo_cookie_manager_.Bind(std::move(cookie_manager_remote));
  setting_new_mojo_cookie_manager_ = false;
  content::GetUIThreadTaskRunner({})->PostTask(
      FROM_HERE,
      base::BindOnce(&CookieManager::ClearClientHintsCachedPerOriginMapIfNeeded,
                     base::Unretained(this)));
  std::move(complete).Run();  // unblock content initialization
  RunPendingCookieTasks();
}

base::android::ScopedJavaLocalRef<jobject>
CookieManager::GetJavaCookieManager() {
  if (!java_obj_) {
    JNIEnv* env = base::android::AttachCurrentThread();
    java_obj_ =
        Java_AwCookieManager_create(env, reinterpret_cast<intptr_t>(this));
  }
  return base::android::ScopedJavaLocalRef<jobject>(java_obj_);
}

void CookieManager::SetWorkaroundHttpSecureCookiesForTesting(
    JNIEnv* env,
    jboolean allow) {
  ExecCookieTaskSync(
      base::BindOnce(&CookieManager::SetWorkaroundHttpSecureCookiesAsyncHelper,
                     base::Unretained(this), allow));
}

void CookieManager::SetWorkaroundHttpSecureCookiesAsyncHelper(
    bool allow,
    base::OnceClosure complete) {
  DCHECK(cookie_store_task_runner_->RunsTasksInCurrentSequence());
  workaround_http_secure_cookies_ = allow;
  std::move(complete).Run();
}

void CookieManager::SetShouldAcceptCookies(JNIEnv* env,
                                           jboolean accept) {
  cookie_access_policy_.SetShouldAcceptCookies(accept);
}

jboolean CookieManager::GetShouldAcceptCookies(JNIEnv* env) {
  return cookie_access_policy_.GetShouldAcceptCookies();
}

void CookieManager::SetCookie(JNIEnv* env,
                              const JavaParamRef<jstring>& url,
                              std::string& cookie_value,
                              const JavaParamRef<jobject>& java_callback) {
  DCHECK(java_callback) << "Unexpected null Java callback";
  GURL host(ConvertJavaStringToUTF16(env, url));
  base::OnceCallback<void(bool)> callback =
      base::BindOnce(&base::android::RunBooleanCallbackAndroid,
                     ScopedJavaGlobalRef<jobject>(java_callback));

  ExecCookieTask(base::BindOnce(&CookieManager::SetCookieHelper,
                                base::Unretained(this), host, cookie_value,
                                std::move(callback)));
}

void CookieManager::SetCookieSync(JNIEnv* env,
                                  const JavaParamRef<jstring>& url,
                                  std::string& value) {
  GURL host(ConvertJavaStringToUTF16(env, url));
  std::string cookie_value(value);

  ExecCookieTaskSync(base::BindOnce(&CookieManager::SetCookieHelper,
                                    base::Unretained(this), host,
                                    cookie_value));
}

void CookieManager::SetCookieHelper(const GURL& host,
                                    const std::string& value,
                                    base::OnceCallback<void(bool)> callback) {
  DCHECK(cookie_store_task_runner_->RunsTasksInCurrentSequence());

  bool should_allow_cookie = true;
  const GURL& new_host = MaybeFixUpSchemeForSecureCookie(
      host, value, workaround_http_secure_cookies_, &should_allow_cookie);
  std::optional<net::CookiePartitionKey> cookie_partition_key =
      net::CookiePartitionKey::IsPartitioningDisabledInWebView()
          ? std::nullopt
          : std::make_optional(net::CookiePartitionKey::FromWire(
                net::SchemefulSite(new_host),
                net::CookiePartitionKey::AncestorChainBit::kSameSite));

  std::unique_ptr<net::CanonicalCookie> cc(net::CanonicalCookie::Create(
      new_host, value, base::Time::Now(), std::nullopt /* server_time */,
      cookie_partition_key, net::CookieSourceType::kOther,
      /*status=*/nullptr));

  if (!cc || !should_allow_cookie) {
    MaybeRunCookieCallback(std::move(callback), false);
    return;
  }

  // Note: CookieStore and network::CookieManager both accept a
  // CookieAccessResult callback. WebView only cares about boolean success,
  // which is why we use |AdaptCookieAccessResultToBool|. This is temporary
  // technical debt until we fully launch the Network Service code path.
  if (GetMojoCookieManager()) {
    // *cc.get() is safe, because network::CookieManager::SetCanonicalCookie
    // will make a copy before our smart pointer goes out of scope.
    GetMojoCookieManager()->SetCanonicalCookie(
        *cc.get(), new_host, net::CookieOptions::MakeAllInclusive(),
        base::BindOnce(net::cookie_util::IsCookieAccessResultInclude)
            .Then(std::move(callback)));
  } else {
    GetCookieStore()->SetCanonicalCookieAsync(
        std::move(cc), new_host, net::CookieOptions::MakeAllInclusive(),
        base::BindOnce(net::cookie_util::IsCookieAccessResultInclude)
            .Then(std::move(callback)));
  }
}

std::string CookieManager::GetCookie(JNIEnv* env,
                                     const JavaParamRef<jstring>& url) {
  GURL host(ConvertJavaStringToUTF16(env, url));

  net::CookieList cookie_list;
  ExecCookieTaskSync(base::BindOnce(&CookieManager::GetCookieListAsyncHelper,
                                    base::Unretained(this), host,
                                    &cookie_list));

  return net::CanonicalCookie::BuildCookieLine(cookie_list);
}

ScopedJavaLocalRef<jobjectArray> CookieManager::GetCookieInfo(
    JNIEnv* env,
    const JavaParamRef<jstring>& url) {
  GURL host(ConvertJavaStringToUTF16(env, url));

  net::CookieList cookie_list;
  ExecCookieTaskSync(base::BindOnce(&CookieManager::GetCookieListAsyncHelper,
                                    base::Unretained(this), host,
                                    &cookie_list));
  std::vector<std::string> cookie_attributes;
  for (net::CanonicalCookie cookie : cookie_list) {
    cookie_attributes.push_back(
        net::CanonicalCookie::BuildCookieAttributesLine(cookie));
  }
  return base::android::ToJavaArrayOfStrings(
      env, base::span<const std::string>(cookie_attributes));
}

void CookieManager::GetCookieListAsyncHelper(const GURL& host,
                                             net::CookieList* result,
                                             base::OnceClosure complete) {
  net::CookieOptions options = net::CookieOptions::MakeAllInclusive();

  // TODO(crbug.com/40188414): Complete partitioned cookies implementation for
  // WebView. The current implementation is a temporary fix for
  // crbug.com/1442333 to let the app access its 1p partitioned cookie.
  if (GetMojoCookieManager()) {
    GetMojoCookieManager()->GetCookieList(
        host, options,
        net::CookiePartitionKeyCollection(net::CookiePartitionKey::FromWire(
            net::SchemefulSite(host),
            net::CookiePartitionKey::AncestorChainBit::kSameSite)),
        base::BindOnce(&CookieManager::GetCookieListCompleted,
                       base::Unretained(this), std::move(complete), result));
  } else {
    GetCookieStore()->GetCookieListWithOptionsAsync(
        host, options,
        net::CookiePartitionKeyCollection(net::CookiePartitionKey::FromWire(
            net::SchemefulSite(host),
            net::CookiePartitionKey::AncestorChainBit::kSameSite)),
        base::BindOnce(&CookieManager::GetCookieListCompleted,
                       base::Unretained(this), std::move(complete), result));
  }
}

void CookieManager::GetCookieListCompleted(
    base::OnceClosure complete,
    net::CookieList* result,
    const net::CookieAccessResultList& value,
    const net::CookieAccessResultList& excluded_cookies) {
  *result = net::cookie_util::StripAccessResults(value);
  std::move(complete).Run();
}

void CookieManager::RemoveSessionCookies(
    JNIEnv* env,
    const JavaParamRef<jobject>& java_callback) {
  DCHECK(java_callback) << "Unexpected null Java callback";
  base::OnceCallback<void(bool)> callback =
      base::BindOnce(&base::android::RunBooleanCallbackAndroid,
                     ScopedJavaGlobalRef<jobject>(java_callback));

  ExecCookieTask(base::BindOnce(&CookieManager::RemoveSessionCookiesHelper,
                                base::Unretained(this), std::move(callback)));
}

void CookieManager::RemoveSessionCookiesSync(JNIEnv* env) {
  ExecCookieTaskSync(base::BindOnce(&CookieManager::RemoveSessionCookiesHelper,
                                    base::Unretained(this)));
}

void CookieManager::RemoveSessionCookiesHelper(
    base::OnceCallback<void(bool)> callback) {
  if (GetMojoCookieManager()) {
    auto match_session_cookies = network::mojom::CookieDeletionFilter::New();
    match_session_cookies->session_control =
        network::mojom::CookieDeletionSessionControl::SESSION_COOKIES;
    GetMojoCookieManager()->DeleteCookies(
        std::move(match_session_cookies),
        base::BindOnce(&CookieManager::RemoveCookiesCompleted,
                       base::Unretained(this), std::move(callback)));
  } else {
    GetCookieStore()->DeleteSessionCookiesAsync(
        base::BindOnce(&CookieManager::RemoveCookiesCompleted,
                       base::Unretained(this), std::move(callback)));
  }
}

void CookieManager::RemoveCookiesCompleted(
    base::OnceCallback<void(bool)> callback,
    uint32_t num_deleted) {
  std::move(callback).Run(num_deleted > 0u);
}

void CookieManager::RemoveAllCookies(
    JNIEnv* env,
    const JavaParamRef<jobject>& java_callback) {
  DCHECK(java_callback) << "Unexpected null Java callback";

  base::OnceCallback<void(bool)> callback =
      base::BindOnce(&base::android::RunBooleanCallbackAndroid,
                     ScopedJavaGlobalRef<jobject>(java_callback));

  ExecCookieTask(base::BindOnce(&CookieManager::RemoveAllCookiesHelper,
                                base::Unretained(this), std::move(callback)));
}

void CookieManager::RemoveAllCookiesSync(JNIEnv* env) {
  ExecCookieTaskSync(base::BindOnce(&CookieManager::RemoveAllCookiesHelper,
                                    base::Unretained(this)));
}

void CookieManager::RemoveAllCookiesHelper(
    base::OnceCallback<void(bool)> callback) {
  // Clear client hints preferences when all cookies are cleared.
  should_clear_client_hints_cached_per_origin_map_ = true;
  if (GetMojoCookieManager()) {
    content::GetUIThreadTaskRunner({})->PostTask(
        FROM_HERE,
        base::BindOnce(
            &CookieManager::ClearClientHintsCachedPerOriginMapIfNeeded,
            base::Unretained(this)));
    // An empty filter matches all cookies.
    auto match_all_cookies = network::mojom::CookieDeletionFilter::New();
    GetMojoCookieManager()->DeleteCookies(
        std::move(match_all_cookies),
        base::BindOnce(&CookieManager::RemoveCookiesCompleted,
                       base::Unretained(this), std::move(callback)));
  } else {
    // TODO(crbug.com/40609350): Support clearing client hints here as well.
    GetCookieStore()->DeleteAllAsync(
        base::BindOnce(&CookieManager::RemoveCookiesCompleted,
                       base::Unretained(this), std::move(callback)));
  }
}

void CookieManager::RemoveExpiredCookies(JNIEnv* env) {
  // HasCookies will call GetAllCookiesAsync, which in turn will force a GC.
  HasCookies(env);
}

void CookieManager::FlushCookieStore(JNIEnv* env) {
  ExecCookieTaskSync(base::BindOnce(&CookieManager::FlushCookieStoreAsyncHelper,
                                    base::Unretained(this)));
}

void CookieManager::FlushCookieStoreAsyncHelper(base::OnceClosure complete) {
  if (GetMojoCookieManager()) {
    GetMojoCookieManager()->FlushCookieStore(std::move(complete));
  } else {
    GetCookieStore()->FlushStore(std::move(complete));
  }
}

jboolean CookieManager::HasCookies(JNIEnv* env) {
  bool has_cookies;
  ExecCookieTaskSync(base::BindOnce(&CookieManager::HasCookiesAsyncHelper,
                                    base::Unretained(this), &has_cookies));
  return has_cookies;
}

// TODO(kristianm): Simplify this, copying the entire list around
// should not be needed.
void CookieManager::HasCookiesAsyncHelper(bool* result,
                                          base::OnceClosure complete) {
  if (GetMojoCookieManager()) {
    GetMojoCookieManager()->GetAllCookies(
        base::BindOnce(&CookieManager::HasCookiesCompleted,
                       base::Unretained(this), std::move(complete), result));
  } else {
    GetCookieStore()->GetAllCookiesAsync(
        base::BindOnce(&CookieManager::HasCookiesCompleted,
                       base::Unretained(this), std::move(complete), result));
  }
}

void CookieManager::HasCookiesCompleted(base::OnceClosure complete,
                                        bool* result,
                                        const CookieList& cookies) {
  *result = cookies.size() != 0;
  std::move(complete).Run();
}

bool CookieManager::GetAllowFileSchemeCookies() {
  base::AutoLock lock(allow_file_scheme_cookies_lock_);
  return allow_file_scheme_cookies_;
}

jboolean CookieManager::GetAllowFileSchemeCookies(JNIEnv* env) {
  return GetAllowFileSchemeCookies();
}

void CookieManager::SetAllowFileSchemeCookies(JNIEnv* env,
                                              jboolean allow) {
  ExecCookieTaskSync(
      base::BindOnce(&CookieManager::SetAllowFileSchemeCookiesAsyncHelper,
                     base::Unretained(this), allow));
}

void CookieManager::SetAllowFileSchemeCookiesAsyncHelper(
    bool allow,
    base::OnceClosure complete) {
  DCHECK(cookie_store_task_runner_->RunsTasksInCurrentSequence());
  if (GetMojoCookieManager()) {
    GetMojoCookieManager()->AllowFileSchemeCookies(
        allow,
        base::BindOnce(&CookieManager::SetAllowFileSchemeCookiesCompleted,
                       base::Unretained(this), std::move(complete), allow));
  } else {
    // If we have neither a Network Service CookieManager nor have created the
    // CookieStore, we may modify |allow_file_scheme_cookies_|.
    bool can_change_schemes = !cookie_store_created_;
    SetAllowFileSchemeCookiesCompleted(std::move(complete), allow,
                                       can_change_schemes);
  }
}

void CookieManager::SetAllowFileSchemeCookiesCompleted(
    base::OnceClosure complete,
    bool allow,
    bool can_change_schemes) {
  // Should only update |allow_file_scheme_cookies_| if
  // SetAllowFileSchemeCookiesAsyncHelper said this is OK.
  if (can_change_schemes) {
    base::AutoLock lock(allow_file_scheme_cookies_lock_);
    allow_file_scheme_cookies_ = allow;
  }
  std::move(complete).Run();
}

void CookieManager::ClearClientHintsCachedPerOriginMapIfNeeded() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  // If we had a client hint cache clear pending, we should do it as soon as we
  // next check and see that the browser has been started.
  if (should_clear_client_hints_cached_per_origin_map_) {
    GetContext()->GetPrefService()->SetDict(
        prefs::kClientHintsCachedPerOriginMap, base::Value::Dict());
    should_clear_client_hints_cached_per_origin_map_ = false;
  }
}

static jlong JNI_AwCookieManager_GetDefaultCookieManager(JNIEnv* env) {
  return reinterpret_cast<intptr_t>(CookieManager::GetDefaultInstance());
}

AwBrowserContext* CookieManager::GetContext() const {
  if (parent_context_) {
    return parent_context_;
  } else {
    return AwBrowserContext::GetDefault();
  }
}

base::FilePath CookieManager::GetContextPath() const {
  if (parent_context_) {
    // Non-default profile
    return parent_context_->GetPath();
  } else {
    // Default profile
    return AwBrowserContext::BuildStoragePath(
        base::FilePath(AwBrowserContextStore::kDefaultContextPath));
  }
}

void JNI_AwCookieManager_DisablePartitionedCookies(JNIEnv* env) {
  net::CookiePartitionKey::DisablePartitioningInWebView();
}

}  // namespace android_webview
