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

#include "net/cookies/cookie_monster_change_dispatcher.h"

#include <utility>

#include "base/functional/bind.h"
#include "base/strings/string_piece.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/task_runner.h"
#include "net/base/features.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_access_delegate.h"
#include "net/cookies/cookie_change_dispatcher.h"
#include "net/cookies/cookie_constants.h"
#include "net/cookies/cookie_monster.h"
#include "net/cookies/cookie_util.h"

namespace net {

namespace {

// Special key in GlobalDomainMap for global listeners.
constexpr base::StringPiece kGlobalDomainKey = base::StringPiece("\0", 1);

//
constexpr base::StringPiece kGlobalNameKey = base::StringPiece("\0", 1);

}  // anonymous namespace

CookieMonsterChangeDispatcher::Subscription::Subscription(
    base::WeakPtr<CookieMonsterChangeDispatcher> change_dispatcher,
    std::string domain_key,
    std::string name_key,
    GURL url,
    CookiePartitionKeyCollection cookie_partition_key_collection,
    bool same_party_attribute_enabled,
    net::CookieChangeCallback callback)
    : change_dispatcher_(std::move(change_dispatcher)),
      domain_key_(std::move(domain_key)),
      name_key_(std::move(name_key)),
      url_(std::move(url)),
      cookie_partition_key_collection_(
          std::move(cookie_partition_key_collection)),
      callback_(std::move(callback)),
      same_party_attribute_enabled_(same_party_attribute_enabled),
      task_runner_(base::SingleThreadTaskRunner::GetCurrentDefault()) {
  DCHECK(url_.is_valid() || url_.is_empty());
  DCHECK_EQ(url_.is_empty(), domain_key_ == kGlobalDomainKey);
}

CookieMonsterChangeDispatcher::Subscription::~Subscription() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  if (change_dispatcher_) {
    change_dispatcher_->UnlinkSubscription(this);
  }
}

void CookieMonsterChangeDispatcher::Subscription::DispatchChange(
    const CookieChangeInfo& change,
    const CookieAccessDelegate* cookie_access_delegate) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  const CanonicalCookie& cookie = change.cookie;

  // The net::CookieOptions are hard-coded for now, but future APIs may set
  // different options. For example, JavaScript observers will not be allowed to
  // see HTTP-only changes.
  if (!url_.is_empty()) {
    bool delegate_treats_url_as_trustworthy =
        cookie_access_delegate &&
        cookie_access_delegate->ShouldTreatUrlAsTrustworthy(url_);
    CookieOptions options = CookieOptions::MakeAllInclusive();
    CookieSamePartyStatus same_party_status = cookie_util::GetSamePartyStatus(
        cookie, options, same_party_attribute_enabled_);
    if (!cookie
             .IncludeForRequestURL(
                 url_, options,
                 CookieAccessParams{change.access_result.access_semantics,
                                    delegate_treats_url_as_trustworthy,
                                    same_party_status})
             .status.IsInclude()) {
      return;
    }
  }

  if (!cookie_partition_key_collection_.ContainsAllKeys()) {
    if (cookie_partition_key_collection_.PartitionKeys().empty()) {
      if (cookie.IsPartitioned()) {
        return;
      }
    } else {
      DCHECK_EQ(1u, cookie_partition_key_collection_.PartitionKeys().size());
      const CookiePartitionKey& key =
          *cookie_partition_key_collection_.PartitionKeys().begin();
      if (CookiePartitionKey::HasNonce(key) && !cookie.IsPartitioned()) {
        return;
      }
      if (cookie.IsPartitioned() && key != *cookie.PartitionKey()) {
        return;
      }
    }
  }

  // TODO(mmenke, pwnall): Run callbacks synchronously?
  task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&Subscription::DoDispatchChange,
                                weak_ptr_factory_.GetWeakPtr(), change));
}

void CookieMonsterChangeDispatcher::Subscription::DoDispatchChange(
    const CookieChangeInfo& change) const {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  callback_.Run(change);
}

CookieMonsterChangeDispatcher::CookieMonsterChangeDispatcher(
    const CookieMonster* cookie_monster,
    bool same_party_attribute_enabled)
    : cookie_monster_(cookie_monster),
      same_party_attribute_enabled_(same_party_attribute_enabled) {}

CookieMonsterChangeDispatcher::~CookieMonsterChangeDispatcher() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}

// static
std::string CookieMonsterChangeDispatcher::DomainKey(
    const std::string& domain) {
  std::string domain_key =
      net::registry_controlled_domains::GetDomainAndRegistry(
          domain, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
  DCHECK_NE(domain_key, kGlobalDomainKey);
  return domain_key;
}

// static
std::string CookieMonsterChangeDispatcher::DomainKey(const GURL& url) {
  std::string domain_key =
      net::registry_controlled_domains::GetDomainAndRegistry(
          url, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
  DCHECK_NE(domain_key, kGlobalDomainKey);
  return domain_key;
}

// static
std::string CookieMonsterChangeDispatcher::NameKey(std::string name) {
  DCHECK_NE(name, kGlobalNameKey);
  return name;
}

std::unique_ptr<CookieChangeSubscription>
CookieMonsterChangeDispatcher::AddCallbackForCookie(
    const GURL& url,
    const std::string& name,
    const absl::optional<CookiePartitionKey>& cookie_partition_key,
    CookieChangeCallback callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  std::unique_ptr<Subscription> subscription = std::make_unique<Subscription>(
      weak_ptr_factory_.GetWeakPtr(), DomainKey(url), NameKey(name), url,
      CookiePartitionKeyCollection::FromOptional(cookie_partition_key),
      same_party_attribute_enabled_, std::move(callback));

  LinkSubscription(subscription.get());
  return subscription;
}

std::unique_ptr<CookieChangeSubscription>
CookieMonsterChangeDispatcher::AddCallbackForUrl(
    const GURL& url,
    const absl::optional<CookiePartitionKey>& cookie_partition_key,
    CookieChangeCallback callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  std::unique_ptr<Subscription> subscription = std::make_unique<Subscription>(
      weak_ptr_factory_.GetWeakPtr(), DomainKey(url),
      std::string(kGlobalNameKey), url,
      CookiePartitionKeyCollection::FromOptional(cookie_partition_key),
      same_party_attribute_enabled_, std::move(callback));

  LinkSubscription(subscription.get());
  return subscription;
}

std::unique_ptr<CookieChangeSubscription>
CookieMonsterChangeDispatcher::AddCallbackForAllChanges(
    CookieChangeCallback callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  std::unique_ptr<Subscription> subscription = std::make_unique<Subscription>(
      weak_ptr_factory_.GetWeakPtr(), std::string(kGlobalDomainKey),
      std::string(kGlobalNameKey), GURL(""),
      CookiePartitionKeyCollection::ContainsAll(),
      same_party_attribute_enabled_, std::move(callback));

  LinkSubscription(subscription.get());
  return subscription;
}

void CookieMonsterChangeDispatcher::DispatchChange(
    const CookieChangeInfo& change,
    bool notify_global_hooks) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  DispatchChangeToDomainKey(change, DomainKey(change.cookie.Domain()));
  if (notify_global_hooks)
    DispatchChangeToDomainKey(change, std::string(kGlobalDomainKey));
}

void CookieMonsterChangeDispatcher::DispatchChangeToDomainKey(
    const CookieChangeInfo& change,
    const std::string& domain_key) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  auto it = cookie_domain_map_.find(domain_key);
  if (it == cookie_domain_map_.end())
    return;

  DispatchChangeToNameKey(change, it->second, NameKey(change.cookie.Name()));
  DispatchChangeToNameKey(change, it->second, std::string(kGlobalNameKey));
}

void CookieMonsterChangeDispatcher::DispatchChangeToNameKey(
    const CookieChangeInfo& change,
    CookieNameMap& cookie_name_map,
    const std::string& name_key) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  auto it = cookie_name_map.find(name_key);
  if (it == cookie_name_map.end())
    return;

  SubscriptionList& subscription_list = it->second;
  for (base::LinkNode<Subscription>* node = subscription_list.head();
       node != subscription_list.end(); node = node->next()) {
    node->value()->DispatchChange(change,
                                  cookie_monster_->cookie_access_delegate());
  }
}

void CookieMonsterChangeDispatcher::LinkSubscription(
    Subscription* subscription) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  // The subscript operator creates empty maps if the lookups fail. This is
  // exactly what this method needs.
  CookieNameMap& cookie_name_map =
      cookie_domain_map_[subscription->domain_key()];
  SubscriptionList& subscription_list =
      cookie_name_map[subscription->name_key()];
  subscription_list.Append(subscription);
}

void CookieMonsterChangeDispatcher::UnlinkSubscription(
    Subscription* subscription) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  auto cookie_domain_map_iterator =
      cookie_domain_map_.find(subscription->domain_key());
  DCHECK(cookie_domain_map_iterator != cookie_domain_map_.end());

  CookieNameMap& cookie_name_map = cookie_domain_map_iterator->second;
  auto cookie_name_map_iterator =
      cookie_name_map.find(subscription->name_key());
  DCHECK(cookie_name_map_iterator != cookie_name_map.end());

  SubscriptionList& subscription_list = cookie_name_map_iterator->second;
  subscription->RemoveFromList();
  if (!subscription_list.empty())
    return;

  cookie_name_map.erase(cookie_name_map_iterator);
  if (!cookie_name_map.empty())
    return;

  cookie_domain_map_.erase(cookie_domain_map_iterator);
}

}  // namespace net
