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

// Implements the Chrome Extensions Cookies API.

#include "chrome/browser/extensions/api/cookies/cookies_api.h"

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

#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/lazy_instance.h"
#include "base/time/time.h"
#include "chrome/browser/extensions/api/cookies/cookies_helpers.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/extensions/window_controller_list.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/api/cookies.h"
#include "components/safe_browsing/buildflags.h"
#include "components/safe_browsing/core/common/features.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_api_frame_id_map.h"
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/extension.h"
#include "extensions/common/permissions/permissions_data.h"
#include "extensions/common/stack_frame.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_constants.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"

#if !BUILDFLAG(IS_ANDROID) && BUILDFLAG(SAFE_BROWSING_AVAILABLE)
#include "chrome/browser/safe_browsing/extension_telemetry/cookies_get_all_signal.h"
#include "chrome/browser/safe_browsing/extension_telemetry/cookies_get_signal.h"
#include "chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.h"
#include "chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service_factory.h"
#endif

using content::BrowserThread;

namespace extensions {

namespace {

// Keys
constexpr char kCauseKey[] = "cause";
constexpr char kCookieKey[] = "cookie";
constexpr char kRemovedKey[] = "removed";

// Cause Constants
constexpr char kEvictedChangeCause[] = "evicted";
constexpr char kExpiredChangeCause[] = "expired";
constexpr char kExpiredOverwriteChangeCause[] = "expired_overwrite";
constexpr char kExplicitChangeCause[] = "explicit";
constexpr char kOverwriteChangeCause[] = "overwrite";

// Errors
constexpr char kCookieSetFailedError[] =
    "Failed to parse or set cookie named \"*\".";
constexpr char kInvalidStoreIdError[] = "Invalid cookie store id: \"*\".";
constexpr char kInvalidUrlError[] = "Invalid url: \"*\".";
constexpr char kNoHostPermissionsError[] =
    "No host permissions for cookies at url: \"*\".";

bool CheckHostPermissions(const Extension* extension,
                          const GURL& url,
                          std::string* error) {
  if (!extension->permissions_data()->HasHostPermission(url)) {
    *error =
        ErrorUtils::FormatErrorMessage(kNoHostPermissionsError, url.spec());
    return false;
  }
  return true;
}

bool ParseUrl(const Extension* extension,
              const std::string& url_string,
              GURL* url,
              bool check_host_permissions,
              std::string* error) {
  *url = GURL(url_string);
  if (!url->is_valid()) {
    *error = ErrorUtils::FormatErrorMessage(kInvalidUrlError, url_string);
    return false;
  }
  // Check against host permissions if needed.
  if (check_host_permissions && !CheckHostPermissions(extension, *url, error)) {
    return false;
  }
  return true;
}

network::mojom::CookieManager* ParseStoreCookieManager(
    content::BrowserContext* function_context,
    bool include_incognito,
    std::string* store_id,
    std::string* error) {
  Profile* function_profile = Profile::FromBrowserContext(function_context);
  Profile* store_profile = nullptr;
  if (!store_id->empty()) {
    store_profile = cookies_helpers::ChooseProfileFromStoreId(
        *store_id, function_profile, include_incognito);
    if (!store_profile) {
      *error = ErrorUtils::FormatErrorMessage(kInvalidStoreIdError, *store_id);
      return nullptr;
    }
  } else {
    store_profile = function_profile;
    *store_id = cookies_helpers::GetStoreIdFromProfile(store_profile);
  }

  return store_profile->GetDefaultStoragePartition()
      ->GetCookieManagerForBrowserProcess();
}

}  // namespace

CookiesEventRouter::CookieChangeListener::CookieChangeListener(
    CookiesEventRouter* router,
    bool otr)
    : router_(router), otr_(otr) {}
CookiesEventRouter::CookieChangeListener::~CookieChangeListener() = default;

void CookiesEventRouter::CookieChangeListener::OnCookieChange(
    const net::CookieChangeInfo& change) {
  router_->OnCookieChange(otr_, change);
}

CookiesEventRouter::CookiesEventRouter(content::BrowserContext* context)
    : profile_(Profile::FromBrowserContext(context)),
      profile_observation_(this),
      otr_profile_observation_(this) {
  MaybeStartListening();
  profile_observation_.Observe(profile_);
}

CookiesEventRouter::~CookiesEventRouter() = default;

void CookiesEventRouter::OnCookieChange(bool otr,
                                        const net::CookieChangeInfo& change) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  // There is no way to represent non-serializable
  // partition keys in JS so return to prevent a crash.
  if (change.cookie.IsPartitioned() &&
      !change.cookie.PartitionKey()->IsSerializeable()) {
    return;
  }
  base::Value::List args;
  base::Value::Dict dict;
  dict.Set(
      kRemovedKey,
      change.cause != net::CookieChangeCause::INSERTED &&
          change.cause != net::CookieChangeCause::INSERTED_NO_CHANGE_OVERWRITE);

  Profile* profile =
      otr ? profile_->GetPrimaryOTRProfile(/*create_if_needed=*/false)
          : profile_->GetOriginalProfile();
  // TODO(407373848): OTR profile must exist when the cookie change event
  // arrived.
  CHECK(profile);

  api::cookies::Cookie cookie = cookies_helpers::CreateCookie(
      change.cookie, cookies_helpers::GetStoreIdFromProfile(profile));
  dict.Set(kCookieKey, cookie.ToValue());

  // Map the internal cause to an external string.
  std::string cause_dict_entry;
  switch (change.cause) {
    // Report an inserted cookie as an "explicit" change cause. All other causes
    // only make sense for deletions.
    case net::CookieChangeCause::INSERTED:
    case net::CookieChangeCause::EXPLICIT:
    case net::CookieChangeCause::INSERTED_NO_CHANGE_OVERWRITE:
      cause_dict_entry = kExplicitChangeCause;
      break;

    case net::CookieChangeCause::OVERWRITE:
      cause_dict_entry = kOverwriteChangeCause;
      break;

    case net::CookieChangeCause::EXPIRED:
      cause_dict_entry = kExpiredChangeCause;
      break;

    case net::CookieChangeCause::EVICTED:
      cause_dict_entry = kEvictedChangeCause;
      break;

    case net::CookieChangeCause::EXPIRED_OVERWRITE:
      cause_dict_entry = kExpiredOverwriteChangeCause;
      break;

    case net::CookieChangeCause::UNKNOWN_DELETION:
      NOTREACHED();
  }
  dict.Set(kCauseKey, cause_dict_entry);

  args.Append(std::move(dict));

  DispatchEvent(profile, events::COOKIES_ON_CHANGED,
                api::cookies::OnChanged::kEventName, std::move(args),
                cookies_helpers::GetURLFromCanonicalCookie(change.cookie));
}

void CookiesEventRouter::OnOffTheRecordProfileCreated(Profile* off_the_record) {
  // When an off-the-record spinoff of |profile_| is created, start listening
  // for cookie changes there. The OTR receiver should never be bound, since
  // there wasn't previously an OTR profile.
  // TODO(crbug.com/417228685): Clank allows for multiple OTR profiles, unlike
  // desktop Chrome. Extensions APIs may have built-in assumptions that there
  // will only be one OTR profile. We need to determine how this will be handled
  // in Desktop Android.
  if (!off_the_record->IsPrimaryOTRProfile()) {
    return;
  }

  DCHECK(!otr_receiver_.is_bound());
  otr_profile_observation_.Observe(off_the_record);
  BindToCookieManager(&otr_receiver_, off_the_record);
}

void CookiesEventRouter::OnProfileWillBeDestroyed(Profile* profile) {
  Profile* original_profile = profile_->GetOriginalProfile();
  Profile* otr_profile =
      original_profile->HasPrimaryOTRProfile()
          ? original_profile->GetPrimaryOTRProfile(/*create_if_needed=*/true)
          : nullptr;
  if (profile == otr_profile) {
    otr_profile_observation_.Reset();
    otr_receiver_.reset();
  }
}

void CookiesEventRouter::MaybeStartListening() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK(profile_);

  Profile* original_profile = profile_->GetOriginalProfile();
  Profile* otr_profile =
      original_profile->HasPrimaryOTRProfile()
          ? original_profile->GetPrimaryOTRProfile(/*create_if_needed=*/true)
          : nullptr;

  if (!receiver_.is_bound()) {
    BindToCookieManager(&receiver_, original_profile);
  }

  if (!otr_receiver_.is_bound() && otr_profile) {
    otr_profile_observation_.Observe(otr_profile);
    BindToCookieManager(&otr_receiver_, otr_profile);
  }
}

void CookiesEventRouter::BindToCookieManager(
    mojo::Receiver<network::mojom::CookieChangeListener>* receiver,
    Profile* profile) {
  network::mojom::CookieManager* cookie_manager =
      profile->GetDefaultStoragePartition()
          ->GetCookieManagerForBrowserProcess();
  if (!cookie_manager)
    return;

  cookie_manager->AddGlobalChangeListener(receiver->BindNewPipeAndPassRemote());
  receiver->set_disconnect_handler(
      base::BindOnce(&CookiesEventRouter::OnConnectionError,
                     base::Unretained(this), receiver));
}

void CookiesEventRouter::OnConnectionError(
    mojo::Receiver<network::mojom::CookieChangeListener>* receiver) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  receiver->reset();
  MaybeStartListening();
}

void CookiesEventRouter::DispatchEvent(content::BrowserContext* context,
                                       events::HistogramValue histogram_value,
                                       const std::string& event_name,
                                       base::Value::List event_args,
                                       const GURL& cookie_domain) {
  EventRouter* router = context ? EventRouter::Get(context) : nullptr;
  if (!router)
    return;
  auto event = std::make_unique<Event>(histogram_value, event_name,
                                       std::move(event_args), context);
  event->event_url = cookie_domain;
  router->BroadcastEvent(std::move(event));
}

CookiesGetFunction::CookiesGetFunction() = default;
CookiesGetFunction::~CookiesGetFunction() = default;

ExtensionFunction::ResponseAction CookiesGetFunction::Run() {
  parsed_args_ = api::cookies::Get::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parsed_args_);

  // Read/validate input parameters.
  std::string error;
  if (!ParseUrl(extension(), parsed_args_->details.url, &url_, true, &error))
    return RespondNow(Error(std::move(error)));

  std::string store_id = parsed_args_->details.store_id.value_or(std::string());
  network::mojom::CookieManager* cookie_manager = ParseStoreCookieManager(
      browser_context(), include_incognito_information(), &store_id, &error);
  if (!cookie_manager)
    return RespondNow(Error(std::move(error)));

  if (parsed_args_->details.partition_key.has_value() &&
      !parsed_args_->details.partition_key->has_cross_site_ancestor
           .has_value() &&
      parsed_args_->details.partition_key->top_level_site.has_value()) {
    base::expected<bool, std::string> cross_site_ancestor =
        cookies_helpers::CalculateHasCrossSiteAncestor(
            parsed_args_->details.url, parsed_args_->details.partition_key);
    if (!cross_site_ancestor.has_value()) {
      return RespondNow(Error(std::move(cross_site_ancestor.error())));
    }
    parsed_args_->details.partition_key->has_cross_site_ancestor =
        cross_site_ancestor.value();
  }

  base::expected<std::optional<net::CookiePartitionKey>, std::string>
      partition_key = cookies_helpers::ToNetCookiePartitionKey(
          parsed_args_->details.partition_key);
  if (!partition_key.has_value()) {
    return RespondNow(Error(std::move(partition_key.error())));
  }

  if (!parsed_args_->details.store_id)
    parsed_args_->details.store_id = store_id;

  DCHECK(!url_.is_empty() && url_.is_valid());
  cookies_helpers::GetCookieListFromManager(
      cookie_manager, url_,
      net::CookiePartitionKeyCollection(std::move(partition_key).value()),
      base::BindOnce(&CookiesGetFunction::GetCookieListCallback, this));

  // Extension telemetry signal intercept
  NotifyExtensionTelemetry();

  // Will finish asynchronously.
  return RespondLater();
}

void CookiesGetFunction::GetCookieListCallback(
    const net::CookieAccessResultList& cookie_list,
    const net::CookieAccessResultList& excluded_cookies) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  for (const net::CookieWithAccessResult& cookie_with_access_result :
       cookie_list) {
    if (!cookies_helpers::
            CanonicalCookiePartitionKeyMatchesApiCookiePartitionKey(
                parsed_args_->details.partition_key,
                cookie_with_access_result.cookie.PartitionKey())) {
      continue;
    }

    // Return the first matching cookie. Relies on the fact that the
    // CookieManager interface returns them in canonical order (longest path,
    // then earliest creation time).
    if (cookie_with_access_result.cookie.Name() == parsed_args_->details.name) {
      api::cookies::Cookie api_cookie = cookies_helpers::CreateCookie(
          cookie_with_access_result.cookie, *parsed_args_->details.store_id);
      Respond(ArgumentList(api::cookies::Get::Results::Create(api_cookie)));
      return;
    }
  }

  // The cookie doesn't exist; return null.
  Respond(WithArguments(base::Value()));
}

void CookiesGetFunction::NotifyExtensionTelemetry() {
  // TODO(crbug.com/371423073): Support telemetry on Android.
#if !BUILDFLAG(IS_ANDROID) && BUILDFLAG(SAFE_BROWSING_AVAILABLE)
  auto* telemetry_service =
      safe_browsing::ExtensionTelemetryServiceFactory::GetForProfile(
          Profile::FromBrowserContext(browser_context()));

  if (!telemetry_service || !telemetry_service->enabled()) {
    return;
  }

  auto cookies_get_signal = std::make_unique<safe_browsing::CookiesGetSignal>(
      extension_id(), parsed_args_->details.name,
      parsed_args_->details.store_id.value_or(std::string()),
      parsed_args_->details.url, js_callstack().value_or(StackTrace()));
  telemetry_service->AddSignal(std::move(cookies_get_signal));
#endif
}

CookiesGetAllFunction::CookiesGetAllFunction() = default;

CookiesGetAllFunction::~CookiesGetAllFunction() = default;

ExtensionFunction::ResponseAction CookiesGetAllFunction::Run() {
  parsed_args_ = api::cookies::GetAll::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parsed_args_);

  std::string error;
  if (parsed_args_->details.url &&
      !ParseUrl(extension(), *parsed_args_->details.url, &url_, false,
                &error)) {
    return RespondNow(Error(std::move(error)));
  }

  std::string store_id = parsed_args_->details.store_id.value_or(std::string());
  network::mojom::CookieManager* cookie_manager = ParseStoreCookieManager(
      browser_context(), include_incognito_information(), &store_id, &error);
  if (!cookie_manager)
    return RespondNow(Error(std::move(error)));

  // make sure user input is valid
  base::expected<std::optional<net::CookiePartitionKey>, std::string>
      partition_key = cookies_helpers::ToNetCookiePartitionKey(
          parsed_args_->details.partition_key);
  if (!partition_key.has_value()) {
    return RespondNow(Error(std::move(partition_key.error())));
  }

  if (!parsed_args_->details.store_id)
    parsed_args_->details.store_id = store_id;

  net::CookiePartitionKeyCollection cookie_partition_key_collection =
      cookies_helpers::CookiePartitionKeyCollectionFromApiPartitionKey(
          parsed_args_->details.partition_key);

  DCHECK(url_.is_empty() || url_.is_valid());
  if (url_.is_empty()) {
    cookies_helpers::GetAllCookiesFromManager(
        cookie_manager,
        base::BindOnce(&CookiesGetAllFunction::GetAllCookiesCallback, this));
  } else {
    cookies_helpers::GetCookieListFromManager(
        cookie_manager, url_, cookie_partition_key_collection,
        base::BindOnce(&CookiesGetAllFunction::GetCookieListCallback, this));
  }

  // Extension telemetry signal intercept
  NotifyExtensionTelemetry();

  return RespondLater();
}

void CookiesGetAllFunction::GetAllCookiesCallback(
    const net::CookieList& cookie_list) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (extension()) {
    net::CookiePartitionKeyCollection cookie_partition_key_collection =
        cookies_helpers::CookiePartitionKeyCollectionFromApiPartitionKey(
            parsed_args_->details.partition_key);
    std::vector<api::cookies::Cookie> match_vector;
    cookies_helpers::AppendMatchingCookiesFromCookieListToVector(
        cookie_list, &parsed_args_->details, extension(), &match_vector,
        cookie_partition_key_collection);

    Respond(ArgumentList(api::cookies::GetAll::Results::Create(match_vector)));
  } else {
    // TODO(devlin): When can |extension()| be null for this function?
    Respond(NoArguments());
  }
}

void CookiesGetAllFunction::GetCookieListCallback(
    const net::CookieAccessResultList& cookie_list,
    const net::CookieAccessResultList& excluded_cookies) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (extension()) {
    std::vector<api::cookies::Cookie> match_vector;
    cookies_helpers::AppendMatchingCookiesFromCookieAccessResultListToVector(
        cookie_list, &parsed_args_->details, extension(), &match_vector);

    Respond(ArgumentList(api::cookies::GetAll::Results::Create(match_vector)));
  } else {
    // TODO(devlin): When can |extension()| be null for this function?
    Respond(NoArguments());
  }
}

void CookiesGetAllFunction::NotifyExtensionTelemetry() {
  // TODO(crbug.com/371423073): Support telemetry on Android.
#if !BUILDFLAG(IS_ANDROID) && BUILDFLAG(SAFE_BROWSING_AVAILABLE)
  auto* telemetry_service =
      safe_browsing::ExtensionTelemetryServiceFactory::GetForProfile(
          Profile::FromBrowserContext(browser_context()));

  if (!telemetry_service || !telemetry_service->enabled()) {
    return;
  }

  auto cookies_get_all_signal =
      std::make_unique<safe_browsing::CookiesGetAllSignal>(
          extension_id(), parsed_args_->details.domain.value_or(std::string()),
          parsed_args_->details.name.value_or(std::string()),
          parsed_args_->details.path.value_or(std::string()),
          parsed_args_->details.secure,
          parsed_args_->details.store_id.value_or(std::string()),
          parsed_args_->details.url.value_or(std::string()),
          parsed_args_->details.session, js_callstack().value_or(StackTrace()));
  telemetry_service->AddSignal(std::move(cookies_get_all_signal));
#endif
}

CookiesSetFunction::CookiesSetFunction()
    : state_(NO_RESPONSE), success_(false) {}

CookiesSetFunction::~CookiesSetFunction() = default;

ExtensionFunction::ResponseAction CookiesSetFunction::Run() {
  parsed_args_ = api::cookies::Set::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parsed_args_);

  // Read/validate input parameters.
  std::string error;
  if (!ParseUrl(extension(), parsed_args_->details.url, &url_, true, &error))
    return RespondNow(Error(std::move(error)));

  std::string store_id = parsed_args_->details.store_id.value_or(std::string());
  network::mojom::CookieManager* cookie_manager = ParseStoreCookieManager(
      browser_context(), include_incognito_information(), &store_id, &error);
  if (!cookie_manager)
    return RespondNow(Error(std::move(error)));

  // cookies.set api allows for an partitionKey with a `top_level_site` present
  // but no value for `has_cross_site_ancestor`. If that is the case, the
  // browser will calculate the value for `has_cross_site_ancestor`.
  std::optional<extensions::api::cookies::CookiePartitionKey> api_partition_key;
  if (parsed_args_->details.partition_key.has_value()) {
    api_partition_key = parsed_args_->details.partition_key->Clone();
    if (!api_partition_key->has_cross_site_ancestor.has_value() &&
        api_partition_key->top_level_site.has_value()) {
      base::expected<bool, std::string> cross_site_ancestor =
          cookies_helpers::CalculateHasCrossSiteAncestor(
              parsed_args_->details.url, api_partition_key);
      if (!cross_site_ancestor.has_value()) {
        return RespondNow(Error(std::move(cross_site_ancestor.error())));
      }
      api_partition_key->has_cross_site_ancestor = cross_site_ancestor.value();
    }
  }

  if (!cookies_helpers::ValidateCrossSiteAncestor(parsed_args_->details.url,
                                                  api_partition_key, &error)) {
    return RespondNow(Error(std::move(error)));
  }

  base::expected<std::optional<net::CookiePartitionKey>, std::string>
      net_partition_key =
          cookies_helpers::ToNetCookiePartitionKey(api_partition_key);
  if (!net_partition_key.has_value()) {
    return RespondNow(Error(std::move(net_partition_key.error())));
  }

  if (!parsed_args_->details.store_id)
    parsed_args_->details.store_id = store_id;

  base::Time expiration_time;
  if (parsed_args_->details.expiration_date) {
    // Time::FromSecondsSinceUnixEpoch converts double time 0 to empty Time
    // object. So we need to do special handling here.
    expiration_time = (*parsed_args_->details.expiration_date == 0)
                          ? base::Time::UnixEpoch()
                          : base::Time::FromSecondsSinceUnixEpoch(
                                *parsed_args_->details.expiration_date);
  }

  net::CookieSameSite same_site = net::CookieSameSite::UNSPECIFIED;
  switch (parsed_args_->details.same_site) {
    case api::cookies::SameSiteStatus::kNoRestriction:
      same_site = net::CookieSameSite::NO_RESTRICTION;
      break;
    case api::cookies::SameSiteStatus::kLax:
      same_site = net::CookieSameSite::LAX_MODE;
      break;
    case api::cookies::SameSiteStatus::kStrict:
      same_site = net::CookieSameSite::STRICT_MODE;
      break;
    // This is the case if the optional sameSite property is given as
    // "unspecified":
    case api::cookies::SameSiteStatus::kUnspecified:
    // This is the case if the optional sameSite property is left out:
    case api::cookies::SameSiteStatus::kNone:
      same_site = net::CookieSameSite::UNSPECIFIED;
      break;
  }

  std::unique_ptr<net::CanonicalCookie> cc(
      net::CanonicalCookie::CreateSanitizedCookie(
          url_,                                                  //
          parsed_args_->details.name.value_or(std::string()),    //
          parsed_args_->details.value.value_or(std::string()),   //
          parsed_args_->details.domain.value_or(std::string()),  //
          parsed_args_->details.path.value_or(std::string()),    //
          /*creation_time=*/base::Time(),                        //
          expiration_time,                                       //
          /*last_access_time=*/base::Time(),                     //
          parsed_args_->details.secure.value_or(false),          //
          parsed_args_->details.http_only.value_or(false),       //
          same_site,                                             //
          net::COOKIE_PRIORITY_DEFAULT,                          //
          net_partition_key.value(),                             //
          /*status=*/nullptr));
  if (!cc) {
    // Return error through callbacks so that the proper error message
    // is generated.
    success_ = false;
    state_ = SET_COMPLETED;
    GetCookieListCallback(net::CookieAccessResultList(),
                          net::CookieAccessResultList());
    return AlreadyResponded();
  }

  // Dispatch the setter, immediately followed by the getter.  This
  // plus FIFO ordering on the cookie_manager_ pipe means that no
  // other extension function will affect the get result.
  net::CookieOptions options;
  options.set_include_httponly();
  options.set_same_site_cookie_context(
      net::CookieOptions::SameSiteCookieContext::MakeInclusive());
  DCHECK(!url_.is_empty() && url_.is_valid());
  cookie_manager->SetCanonicalCookie(
      *cc, url_, options,
      base::BindOnce(&CookiesSetFunction::SetCanonicalCookieCallback, this));
  cookies_helpers::GetCookieListFromManager(
      cookie_manager, url_,
      net::CookiePartitionKeyCollection(std::move(net_partition_key).value()),
      base::BindOnce(&CookiesSetFunction::GetCookieListCallback, this));

  // Will finish asynchronously.
  return RespondLater();
}

void CookiesSetFunction::SetCanonicalCookieCallback(
    net::CookieAccessResult set_cookie_result) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK_EQ(NO_RESPONSE, state_);
  state_ = SET_COMPLETED;
  success_ = set_cookie_result.status.IsInclude();
}

void CookiesSetFunction::GetCookieListCallback(
    const net::CookieAccessResultList& cookie_list,
    const net::CookieAccessResultList& excluded_cookies) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK_EQ(SET_COMPLETED, state_);
  state_ = GET_COMPLETED;

  if (!success_) {
    std::string name = parsed_args_->details.name.value_or(std::string());
    Respond(Error(ErrorUtils::FormatErrorMessage(kCookieSetFailedError, name)));
    return;
  }

  std::optional<ResponseValue> value;
  for (const net::CookieWithAccessResult& cookie_with_access_result :
       cookie_list) {
    // Return the first matching cookie. Relies on the fact that the
    // CookieMonster returns them in canonical order (longest path, then
    // earliest creation time).

    if (!extensions::cookies_helpers::
            CanonicalCookiePartitionKeyMatchesApiCookiePartitionKey(
                parsed_args_->details.partition_key,
                cookie_with_access_result.cookie.PartitionKey())) {
      continue;
    }

    std::string name = parsed_args_->details.name.value_or(std::string());

    if (cookie_with_access_result.cookie.Name() == name) {
      api::cookies::Cookie api_cookie = cookies_helpers::CreateCookie(
          cookie_with_access_result.cookie, *parsed_args_->details.store_id);
      value.emplace(
          ArgumentList(api::cookies::Set::Results::Create(api_cookie)));
      break;
    }
  }

  Respond(value ? std::move(*value) : NoArguments());
}

CookiesRemoveFunction::CookiesRemoveFunction() = default;

CookiesRemoveFunction::~CookiesRemoveFunction() = default;

ExtensionFunction::ResponseAction CookiesRemoveFunction::Run() {
  parsed_args_ = api::cookies::Remove::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parsed_args_);

  // Read/validate input parameters.
  std::string error;
  if (!ParseUrl(extension(), parsed_args_->details.url, &url_, true, &error))
    return RespondNow(Error(std::move(error)));

  std::string store_id = parsed_args_->details.store_id.value_or(std::string());
  network::mojom::CookieManager* cookie_manager = ParseStoreCookieManager(
      browser_context(), include_incognito_information(), &store_id, &error);
  if (!cookie_manager)
    return RespondNow(Error(std::move(error)));

  base::expected<std::optional<net::CookiePartitionKey>, std::string>
      partition_key = cookies_helpers::ToNetCookiePartitionKey(
          parsed_args_->details.partition_key);
  if (!partition_key.has_value()) {
    return RespondNow(Error(std::move(partition_key.error())));
  }

  if (!parsed_args_->details.store_id)
    parsed_args_->details.store_id = store_id;

  network::mojom::CookieDeletionFilterPtr filter(
      network::mojom::CookieDeletionFilter::New());

  filter->cookie_partition_key_collection =
      net::CookiePartitionKeyCollection(std::move(partition_key).value());
  filter->url = url_;
  filter->cookie_name = parsed_args_->details.name;
  cookie_manager->DeleteCookies(
      std::move(filter),
      base::BindOnce(&CookiesRemoveFunction::RemoveCookieCallback, this));

  // Will return asynchronously.
  return RespondLater();
}

void CookiesRemoveFunction::RemoveCookieCallback(uint32_t /* num_deleted */) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // Build the callback result
  api::cookies::Remove::Results::Details details;
  details.name = parsed_args_->details.name;
  details.url = url_.spec();
  details.store_id = *parsed_args_->details.store_id;
  if (parsed_args_->details.partition_key) {
    details.partition_key = parsed_args_->details.partition_key->Clone();
  }

  Respond(ArgumentList(api::cookies::Remove::Results::Create(details)));
}

CookiesGetPartitionKeyFunction::CookiesGetPartitionKeyFunction() = default;

CookiesGetPartitionKeyFunction::~CookiesGetPartitionKeyFunction() = default;

ExtensionFunction::ResponseAction CookiesGetPartitionKeyFunction::Run() {
  parsed_args_ = api::cookies::GetPartitionKey::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(parsed_args_);

  content::RenderFrameHost* render_frame_host = nullptr;
  content::WebContents* web_contents = nullptr;
  std::optional<int> frame_id = parsed_args_->details.frame_id;
  std::optional<ExtensionApiFrameIdMap::DocumentId> document_id;
  std::optional<int> tab_id = parsed_args_->details.tab_id;

  if (parsed_args_->details.document_id.has_value()) {
    document_id = ExtensionApiFrameIdMap::DocumentIdFromString(
        *parsed_args_->details.document_id);
    render_frame_host =
        ExtensionApiFrameIdMap::Get()->GetRenderFrameHostByDocumentId(
            document_id.value());
    web_contents = content::WebContents::FromRenderFrameHost(render_frame_host);
  } else if (tab_id.has_value()) {
    if (!frame_id.has_value()) {
      // Default to main frame if no frame is provided.
      frame_id = 0;
    }

    if (!ExtensionTabUtil::GetTabById(tab_id.value(), browser_context(),
                                      include_incognito_information(),
                                      &web_contents) ||
        !web_contents) {
      return RespondNow(Error("Invalid `tabId`."));
    }
    render_frame_host = ExtensionApiFrameIdMap::GetRenderFrameHostById(
        web_contents, frame_id.value());
  } else if (frame_id.has_value()) {
    if (frame_id.value() == 0) {
      return RespondNow(
          Error("`frameId` may not be 0 if no `tabId` is present."));
    }

    render_frame_host =
        ExtensionApiFrameIdMap::Get()->GetRenderFrameHostByFrameId(
            frame_id.value());
  } else {
    return RespondNow(
        Error("Either `documentId` or `tabId` must be specified."));
  }

  if (!render_frame_host) {
    return RespondNow(document_id.has_value() ? Error("Invalid `documentId`.")
                                              : Error("Invalid `frameId`."));
  }

  // If both document_id and tab_id are provided, make sure they match.
  if (document_id.has_value() && tab_id.has_value()) {
    if (ExtensionTabUtil::GetTabId(web_contents) != tab_id.value() ||
        ExtensionApiFrameIdMap::GetFrameId(render_frame_host) !=
            frame_id.value()) {
      return RespondNow(
          Error("Provided `tabId` and `frameId` do not match the frame."));
    }
  }

  base::expected<net::CookiePartitionKey::SerializedCookiePartitionKey,
                 std::string>
      serialized_key = net::CookiePartitionKey::Serialize(
          render_frame_host->GetStorageKey().ToCookiePartitionKey());
  if (!serialized_key.has_value()) {
    return RespondNow(Error("PartitionKey requested is not serializable."));
  }

  std::string error;
  if (!CheckHostPermissions(extension(), GURL(serialized_key->TopLevelSite()),
                            &error) ||
      !CheckHostPermissions(extension(),
                            render_frame_host->GetLastCommittedURL(), &error)) {
    return RespondNow(Error(error));
  }

  api::cookies::CookiePartitionKey partition_key;
  partition_key.has_cross_site_ancestor =
      serialized_key->has_cross_site_ancestor();
  partition_key.top_level_site = serialized_key->TopLevelSite();

  api::cookies::GetPartitionKey::Results::Details details =
      api::cookies::GetPartitionKey::Results::Details();
  details.partition_key = partition_key.Clone();
  return RespondNow(WithArguments(details.ToValue()));
}

ExtensionFunction::ResponseAction CookiesGetAllCookieStoresFunction::Run() {
  Profile* original_profile = Profile::FromBrowserContext(browser_context());
  DCHECK(original_profile);
  base::Value::List original_tab_ids;
  Profile* incognito_profile = nullptr;
  base::Value::List incognito_tab_ids;
  if (include_incognito_information() &&
      original_profile->HasPrimaryOTRProfile()) {
    incognito_profile =
        original_profile->GetPrimaryOTRProfile(/*create_if_needed=*/true);
  }
  DCHECK(original_profile != incognito_profile);

  // Iterate through all browser instances, and for each browser,
  // add its tab IDs to either the regular or incognito tab ID list depending
  // whether the browser is regular or incognito.
  for (WindowController* window : *WindowControllerList::GetInstance()) {
    if (window->profile() == original_profile) {
      cookies_helpers::AppendToTabIdList(window, original_tab_ids);
    } else if (window->profile() == incognito_profile) {
      cookies_helpers::AppendToTabIdList(window, incognito_tab_ids);
    }
  }
  // Return a list of all cookie stores with at least one open tab.
  std::vector<api::cookies::CookieStore> cookie_stores;
  if (!original_tab_ids.empty()) {
    cookie_stores.push_back(cookies_helpers::CreateCookieStore(
        original_profile, std::move(original_tab_ids)));
  }
  if (incognito_profile && !incognito_tab_ids.empty()) {
    cookie_stores.push_back(cookies_helpers::CreateCookieStore(
        incognito_profile, std::move(incognito_tab_ids)));
  }
  return RespondNow(ArgumentList(
      api::cookies::GetAllCookieStores::Results::Create(cookie_stores)));
}

CookiesAPI::CookiesAPI(content::BrowserContext* context)
    : browser_context_(context) {
  EventRouter::Get(browser_context_)
      ->RegisterObserver(this, api::cookies::OnChanged::kEventName);
}

CookiesAPI::~CookiesAPI() = default;

void CookiesAPI::Shutdown() {
  EventRouter::Get(browser_context_)->UnregisterObserver(this);
}

static base::LazyInstance<BrowserContextKeyedAPIFactory<CookiesAPI>>::
    DestructorAtExit g_cookies_api_factory = LAZY_INSTANCE_INITIALIZER;

// static
BrowserContextKeyedAPIFactory<CookiesAPI>* CookiesAPI::GetFactoryInstance() {
  return g_cookies_api_factory.Pointer();
}

void CookiesAPI::OnListenerAdded(const EventListenerInfo& details) {
  DCHECK(!cookies_event_router_);
  cookies_event_router_ =
      std::make_unique<CookiesEventRouter>(browser_context_);
  EventRouter::Get(browser_context_)->UnregisterObserver(this);
}

}  // namespace extensions
