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

#include "content/browser/devtools/protocol/storage_handler.h"

#include <stdint.h>

#include <memory>
#include <optional>
#include <string>
#include <unordered_set>
#include <utility>
#include <variant>
#include <vector>

#include "base/barrier_closure.h"
#include "base/functional/bind.h"
#include "base/notreached.h"
#include "base/scoped_observation.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/string_view_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "components/attribution_reporting/aggregatable_debug_reporting_config.h"
#include "components/attribution_reporting/aggregatable_dedup_key.h"
#include "components/attribution_reporting/aggregatable_named_budget_candidate.h"
#include "components/attribution_reporting/aggregatable_named_budget_defs.h"
#include "components/attribution_reporting/aggregatable_trigger_data.h"
#include "components/attribution_reporting/aggregatable_values.h"
#include "components/attribution_reporting/aggregation_keys.h"
#include "components/attribution_reporting/attribution_scopes_data.h"
#include "components/attribution_reporting/attribution_scopes_set.h"
#include "components/attribution_reporting/debug_types.h"
#include "components/attribution_reporting/destination_set.h"
#include "components/attribution_reporting/event_trigger_data.h"
#include "components/attribution_reporting/filters.h"
#include "components/attribution_reporting/max_event_level_reports.h"
#include "components/attribution_reporting/parsing_utils.h"
#include "components/attribution_reporting/source_registration.h"
#include "components/attribution_reporting/source_type.h"
#include "components/attribution_reporting/suitable_origin.h"
#include "components/attribution_reporting/trigger_config.h"
#include "components/attribution_reporting/trigger_data_matching.mojom.h"
#include "components/services/storage/privileged/mojom/indexed_db_control.mojom.h"
#include "components/services/storage/public/cpp/buckets/bucket_locator.h"
#include "components/services/storage/public/mojom/cache_storage_control.mojom.h"
#include "content/browser/attribution_reporting/aggregatable_result.mojom.h"
#include "content/browser/attribution_reporting/attribution_debug_report.h"
#include "content/browser/attribution_reporting/attribution_manager.h"
#include "content/browser/attribution_reporting/attribution_observer.h"
#include "content/browser/attribution_reporting/attribution_report.h"
#include "content/browser/attribution_reporting/attribution_trigger.h"
#include "content/browser/attribution_reporting/common_source_info.h"
#include "content/browser/attribution_reporting/create_report_result.h"
#include "content/browser/attribution_reporting/event_level_result.mojom.h"
#include "content/browser/attribution_reporting/send_result.h"
#include "content/browser/attribution_reporting/storable_source.h"
#include "content/browser/attribution_reporting/store_source_result.mojom.h"
#include "content/browser/devtools/dedicated_worker_devtools_agent_host.h"
#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/browser/devtools/protocol/browser_handler.h"
#include "content/browser/devtools/protocol/handler_helpers.h"
#include "content/browser/devtools/protocol/network.h"
#include "content/browser/devtools/protocol/network_handler.h"
#include "content/browser/devtools/protocol/storage.h"
#include "content/browser/devtools/service_worker_devtools_agent_host.h"
#include "content/browser/devtools/shared_worker_devtools_agent_host.h"
#include "content/browser/interest_group/interest_group_manager_impl.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/devtools_agent_host_client.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/storage_partition.h"
#include "net/base/net_errors.h"
#include "net/base/schemeful_site.h"
#include "services/network/public/mojom/trust_tokens.mojom.h"
#include "storage/browser/quota/quota_manager.h"
#include "storage/browser/quota/quota_manager_impl.h"
#include "storage/browser/quota/quota_manager_observer.mojom-forward.h"
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/browser/quota/quota_override_handle.h"
#include "third_party/abseil-cpp/absl/functional/overload.h"
#include "third_party/blink/public/common/interest_group/devtools_serialization.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/buckets/bucket_manager_host.mojom-shared.h"
#include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"

namespace content {
namespace protocol {

using ClearCookiesCallback = Storage::Backend::ClearCookiesCallback;
using GetCookiesCallback = Storage::Backend::GetCookiesCallback;
using SetCookiesCallback = Storage::Backend::SetCookiesCallback;

struct UsageListInitializer {
  const char* type;
  int64_t blink::mojom::UsageBreakdown::*usage_member;
};

UsageListInitializer initializers[] = {
    {Storage::StorageTypeEnum::File_systems,
     &blink::mojom::UsageBreakdown::fileSystem},
    {Storage::StorageTypeEnum::Indexeddb,
     &blink::mojom::UsageBreakdown::indexedDatabase},
    {Storage::StorageTypeEnum::Cache_storage,
     &blink::mojom::UsageBreakdown::serviceWorkerCache},
    {Storage::StorageTypeEnum::Service_workers,
     &blink::mojom::UsageBreakdown::serviceWorker},
};

namespace {

void ReportUsageAndQuotaDataOnUIThread(
    std::unique_ptr<StorageHandler::GetUsageAndQuotaCallback> callback,
    blink::mojom::QuotaStatusCode code,
    int64_t usage,
    int64_t quota,
    bool is_override_enabled,
    blink::mojom::UsageBreakdownPtr usage_breakdown) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (code != blink::mojom::QuotaStatusCode::kOk) {
    return callback->sendFailure(
        Response::ServerError("Quota information is not available"));
  }

  auto usageList = std::make_unique<Array<Storage::UsageForType>>();

  blink::mojom::UsageBreakdown* breakdown_ptr = usage_breakdown.get();
  for (const auto initializer : initializers) {
    std::unique_ptr<Storage::UsageForType> entry =
        Storage::UsageForType::Create()
            .SetStorageType(initializer.type)
            .SetUsage(breakdown_ptr->*(initializer.usage_member))
            .Build();
    usageList->emplace_back(std::move(entry));
  }

  callback->sendSuccess(usage, quota, is_override_enabled,
                        std::move(usageList));
}

void GotUsageAndQuotaDataCallback(
    std::unique_ptr<StorageHandler::GetUsageAndQuotaCallback> callback,
    blink::mojom::QuotaStatusCode code,
    int64_t usage,
    int64_t quota,
    bool is_override_enabled,
    blink::mojom::UsageBreakdownPtr usage_breakdown) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  GetUIThreadTaskRunner({})->PostTask(
      FROM_HERE,
      base::BindOnce(ReportUsageAndQuotaDataOnUIThread, std::move(callback),
                     code, usage, quota, is_override_enabled,
                     std::move(usage_breakdown)));
}

void GetUsageAndQuotaOnIOThread(
    storage::QuotaManager* manager,
    const blink::StorageKey& storage_key,
    std::unique_ptr<StorageHandler::GetUsageAndQuotaCallback> callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  manager->GetUsageAndQuotaForDevtools(
      storage_key,
      base::BindOnce(&GotUsageAndQuotaDataCallback, std::move(callback)));
}

std::unique_ptr<protocol::Storage::StorageBucketInfo> BuildBucketInfo(
    const storage::BucketInfo& bucket) {
  std::string durability_enum;
  switch (bucket.durability) {
    case blink::mojom::BucketDurability::kRelaxed:
      durability_enum = Storage::StorageBucketsDurabilityEnum::Relaxed;
      break;
    case blink::mojom::BucketDurability::kStrict:
      durability_enum = Storage::StorageBucketsDurabilityEnum::Strict;
      break;
  }

  std::unique_ptr<protocol::Storage::StorageBucket> storage_bucket;
  if (bucket.is_default()) {
    storage_bucket = protocol::Storage::StorageBucket::Create()
                         .SetStorageKey(bucket.storage_key.Serialize())
                         .Build();
  } else {
    storage_bucket = protocol::Storage::StorageBucket::Create()
                         .SetStorageKey(bucket.storage_key.Serialize())
                         .SetName(bucket.name)
                         .Build();
  }

  return protocol::Storage::StorageBucketInfo::Create()
      .SetBucket(std::move(storage_bucket))
      .SetId(base::NumberToString(bucket.id.value()))
      .SetExpiration(bucket.expiration.InSecondsFSinceUnixEpoch())
      .SetQuota(bucket.quota)
      .SetPersistent(bucket.persistent)
      .SetDurability(durability_enum)
      .Build();
}

}  // namespace

// Observer that listens on the UI thread for cache storage notifications and
// informs the StorageHandler on the UI thread for origins of interest.
// Created and used exclusively on the UI thread.
class StorageHandler::CacheStorageObserver
    : storage::mojom::CacheStorageObserver {
 public:
  CacheStorageObserver(
      base::WeakPtr<StorageHandler> owner_storage_handler,
      mojo::PendingReceiver<storage::mojom::CacheStorageObserver> observer)
      : owner_(owner_storage_handler), receiver_(this, std::move(observer)) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
  }

  CacheStorageObserver(const CacheStorageObserver&) = delete;
  CacheStorageObserver& operator=(const CacheStorageObserver&) = delete;

  ~CacheStorageObserver() override { DCHECK_CURRENTLY_ON(BrowserThread::UI); }

  void TrackStorageKey(const blink::StorageKey& storage_key) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    if (storage_keys_.find(storage_key) != storage_keys_.end()) {
      return;
    }
    storage_keys_.insert(storage_key);
  }

  void UntrackStorageKey(const blink::StorageKey& storage_key) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    storage_keys_.erase(storage_key);
  }

  void OnCacheListChanged(
      const storage::BucketLocator& bucket_locator) override {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    auto found = storage_keys_.find(bucket_locator.storage_key);
    if (found == storage_keys_.end()) {
      return;
    }
    owner_->NotifyCacheStorageListChanged(bucket_locator);
  }

  void OnCacheContentChanged(const storage::BucketLocator& bucket_locator,
                             const std::string& cache_name) override {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    if (storage_keys_.find(bucket_locator.storage_key) == storage_keys_.end()) {
      return;
    }
    owner_->NotifyCacheStorageContentChanged(bucket_locator, cache_name);
  }

 private:
  // Maintained on the IO thread to avoid thread contention.
  base::flat_set<blink::StorageKey> storage_keys_;

  base::WeakPtr<StorageHandler> owner_;
  mojo::Receiver<storage::mojom::CacheStorageObserver> receiver_;
};

// Observer that listens on the IDB thread for IndexedDB notifications and
// informs the StorageHandler on the UI thread for storage_keys of interest.
// Created on the UI thread but predominantly used and deleted on the IDB
// thread.
class StorageHandler::IndexedDBObserver
    : public storage::mojom::IndexedDBObserver {
 public:
  explicit IndexedDBObserver(
      base::WeakPtr<StorageHandler> owner_storage_handler)
      : owner_(owner_storage_handler), receiver_(this) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);

    ReconnectObserver();
  }

  IndexedDBObserver(const IndexedDBObserver&) = delete;
  IndexedDBObserver& operator=(const IndexedDBObserver&) = delete;

  ~IndexedDBObserver() override { DCHECK_CURRENTLY_ON(BrowserThread::UI); }

  void TrackStorageKey(const blink::StorageKey& storage_key) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    if (storage_keys_.find(storage_key) != storage_keys_.end()) {
      return;
    }
    storage_keys_.insert(storage_key);
  }

  void UntrackStorageKey(const blink::StorageKey& storage_key) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    storage_keys_.erase(storage_key);
  }

  void OnIndexedDBListChanged(
      const storage::BucketLocator& bucket_locator) override {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    if (!owner_) {
      return;
    }
    // TODO(crbug.com/40221733): Allow custom bucket names.
    auto found = storage_keys_.find(bucket_locator.storage_key);
    if (found == storage_keys_.end()) {
      return;
    }

    owner_->NotifyIndexedDBListChanged(bucket_locator);
  }

  void OnIndexedDBContentChanged(
      const storage::BucketLocator& bucket_locator,
      const std::u16string& database_name,
      const std::u16string& object_store_name) override {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    if (!owner_) {
      return;
    }
    // TODO(crbug.com/40221733): Allow custom bucket names.
    auto found = storage_keys_.find(bucket_locator.storage_key);
    if (found == storage_keys_.end()) {
      return;
    }

    owner_->NotifyIndexedDBContentChanged(bucket_locator, database_name,
                                          object_store_name);
  }

 private:
  void ReconnectObserver() {
    DCHECK(!receiver_.is_bound());
    if (!owner_) {
      return;
    }

    auto& control = owner_->storage_partition_->GetIndexedDBControl();
    mojo::PendingRemote<storage::mojom::IndexedDBObserver> remote;
    receiver_.Bind(remote.InitWithNewPipeAndPassReceiver());
    receiver_.set_disconnect_handler(base::BindOnce(
        [](IndexedDBObserver* observer) {
          // If this observer disconnects because IndexedDB or the storage
          // service goes away, reconnect again.
          observer->ReconnectObserver();
        },
        this));
    control.AddObserver(std::move(remote));
  }

  base::flat_set<blink::StorageKey> storage_keys_;
  base::WeakPtr<StorageHandler> owner_;
  mojo::Receiver<storage::mojom::IndexedDBObserver> receiver_;
};

class StorageHandler::QuotaManagerObserver
    : storage::mojom::QuotaManagerObserver {
 public:
  QuotaManagerObserver(base::WeakPtr<StorageHandler> owner_storage_handler,
                       storage::QuotaManagerProxy* quota_manager_proxy)
      : owner_(owner_storage_handler) {
    quota_manager_proxy->AddObserver(receiver_.BindNewPipeAndPassRemote());
  }

  QuotaManagerObserver(const QuotaManagerObserver&) = delete;
  QuotaManagerObserver& operator=(const QuotaManagerObserver&) = delete;

  ~QuotaManagerObserver() override = default;

  void TrackStorageKey(const blink::StorageKey& storage_key,
                       storage::QuotaManagerProxy* manager) {
    if (!storage_keys_.insert(storage_key).second) {
      return;
    }
    manager->GetBucketsForStorageKey(
        storage_key, /*delete_expired=*/false,
        base::SingleThreadTaskRunner::GetCurrentDefault(),
        base::BindOnce(
            [](base::WeakPtr<StorageHandler> owner_storage_handler,
               storage::QuotaErrorOr<std::set<storage::BucketInfo>> buckets) {
              if (!owner_storage_handler || !buckets.has_value()) {
                return;
              }

              for (const storage::BucketInfo& bucket : buckets.value()) {
                owner_storage_handler->NotifyCreateOrUpdateBucket(bucket);
              }
            },
            owner_));
  }

  void UntrackStorageKey(const blink::StorageKey& storage_key) {
    storage_keys_.erase(storage_key);
  }

 private:
  void OnCreateOrUpdateBucket(const storage::BucketInfo& bucket_info) override {
    auto found = storage_keys_.find(bucket_info.storage_key);
    if (found == storage_keys_.end()) {
      return;
    }
    owner_->NotifyCreateOrUpdateBucket(bucket_info);
  }

  void OnDeleteBucket(const storage::BucketLocator& bucket_locator) override {
    auto found = storage_keys_.find(bucket_locator.storage_key);
    if (found == storage_keys_.end()) {
      return;
    }
    owner_->NotifyDeleteBucket(bucket_locator);
  }

  base::flat_set<blink::StorageKey> storage_keys_;

  base::WeakPtr<StorageHandler> owner_;
  mojo::Receiver<storage::mojom::QuotaManagerObserver> receiver_{this};
};

StorageHandler::StorageHandler(DevToolsAgentHostImpl* host,
                               DevToolsAgentHostClient* client)
    : DevToolsDomainHandler(Storage::Metainfo::domainName),
      host_(host),
      client_(client) {}

StorageHandler::~StorageHandler() {
  DCHECK(!cache_storage_observer_);
  DCHECK(!indexed_db_observer_);
}

// static
std::vector<StorageHandler*> StorageHandler::ForAgentHost(
    DevToolsAgentHostImpl* host) {
  return host->HandlersByName<StorageHandler>(Storage::Metainfo::domainName);
}

void StorageHandler::Wire(UberDispatcher* dispatcher) {
  frontend_ = std::make_unique<Storage::Frontend>(dispatcher->channel());
  Storage::Dispatcher::wire(dispatcher, this);
}

void StorageHandler::SetRenderer(int process_host_id,
                                 RenderFrameHostImpl* frame_host) {
  RenderProcessHost* process = RenderProcessHost::FromID(process_host_id);
  StoragePartition* new_storage_partition =
      process ? process->GetStoragePartition() : nullptr;
  if (interest_group_tracking_enabled_) {
    // Transfer observer registration from old frame's StoragePartition to new;
    // SetInterestGroupTrackingInternal() will handle any nulls.
    SetInterestGroupTrackingInternal(storage_partition_, false);
    SetInterestGroupTrackingInternal(new_storage_partition, true);
  }
  storage_partition_ = new_storage_partition;
  frame_host_ = frame_host;
}

Response StorageHandler::Disable() {
  cache_storage_observer_.reset();
  indexed_db_observer_.reset();
  quota_override_handle_.reset();
  SetInterestGroupTracking(false);
  SetSharedStorageTracking(false);
  quota_manager_observer_.reset();
  ResetAttributionReporting();
  return Response::Success();
}

void StorageHandler::GetCookies(std::optional<std::string> browser_context_id,
                                std::unique_ptr<GetCookiesCallback> callback) {
  StoragePartition* storage_partition = nullptr;
  Response response = StorageHandler::FindStoragePartition(browser_context_id,
                                                           &storage_partition);
  if (!response.IsSuccess()) {
    callback->sendFailure(std::move(response));
    return;
  }

  storage_partition->GetCookieManagerForBrowserProcess()->GetAllCookies(
      base::BindOnce(&StorageHandler::GotAllCookies,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void StorageHandler::GotAllCookies(
    std::unique_ptr<GetCookiesCallback> callback,
    const std::vector<net::CanonicalCookie>& cookies) {
  bool is_webui = frame_host_ && frame_host_->web_ui();
  std::vector<net::CanonicalCookie> filtered_cookies;
  for (const auto& cookie : cookies) {
    if (client_->MayAttachToURL(
            GURL(base::StrCat({url::kHttpsScheme, url::kStandardSchemeSeparator,
                               cookie.DomainWithoutDot()})),
            is_webui) &&
        client_->MayAttachToURL(
            GURL(base::StrCat({url::kHttpScheme, url::kStandardSchemeSeparator,
                               cookie.DomainWithoutDot()})),
            is_webui)) {
      filtered_cookies.emplace_back(std::move(cookie));
    }
  }
  callback->sendSuccess(NetworkHandler::BuildCookieArray(filtered_cookies));
}

void StorageHandler::SetCookies(
    std::unique_ptr<protocol::Array<Network::CookieParam>> cookies,
    std::optional<std::string> browser_context_id,
    std::unique_ptr<SetCookiesCallback> callback) {
  StoragePartition* storage_partition = nullptr;
  Response response = StorageHandler::FindStoragePartition(browser_context_id,
                                                           &storage_partition);
  if (!response.IsSuccess()) {
    callback->sendFailure(std::move(response));
    return;
  }

  NetworkHandler::SetCookies(
      storage_partition, std::move(cookies),
      base::BindOnce(
          [](std::unique_ptr<SetCookiesCallback> callback, bool success) {
            if (success) {
              callback->sendSuccess();
            } else {
              callback->sendFailure(
                  Response::InvalidParams("Invalid cookie fields"));
            }
          },
          std::move(callback)));
}

void StorageHandler::ClearCookies(
    std::optional<std::string> browser_context_id,
    std::unique_ptr<ClearCookiesCallback> callback) {
  StoragePartition* storage_partition = nullptr;
  Response response = StorageHandler::FindStoragePartition(browser_context_id,
                                                           &storage_partition);
  if (!response.IsSuccess()) {
    callback->sendFailure(std::move(response));
    return;
  }

  storage_partition->GetCookieManagerForBrowserProcess()->DeleteCookies(
      network::mojom::CookieDeletionFilter::New(),
      base::BindOnce([](std::unique_ptr<ClearCookiesCallback> callback,
                        uint32_t) { callback->sendSuccess(); },
                     std::move(callback)));
}

Response StorageHandler::GetStorageKeyForFrameInternal(
    const std::string& frame_id,
    std::string* serialized_storage_key) {
  if (!frame_host_) {
    return Response::InvalidParams("Frame host not found");
  }
  FrameTreeNode* node = protocol::FrameTreeNodeFromDevToolsFrameToken(
      frame_host_->frame_tree_node(), frame_id);
  if (!node) {
    return Response::InvalidParams("Frame tree node for given frame not found");
  }
  RenderFrameHostImpl* rfh = node->current_frame_host();
  if (rfh->GetStorageKey().origin().opaque()) {
    return Response::ServerError(
        "Frame corresponds to an opaque origin and its storage key cannot be "
        "serialized");
  }
  *serialized_storage_key = rfh->GetStorageKey().Serialize();
  return Response::Success();
}

// TODO(crbug.com/445966299): This method is deprecated and
// will be removed once all clients, including the DevTools frontend, have
// migrated to using GetStorageKey.
Response StorageHandler::GetStorageKeyForFrame(
    const std::string& frame_id,
    std::string* serialized_storage_key) {
  return GetStorageKeyForFrameInternal(frame_id, serialized_storage_key);
}

Response StorageHandler::GetStorageKey(std::optional<std::string> frame_id,
                                       std::string* serialized_storage_key) {
  if (frame_id.has_value()) {
    return GetStorageKeyForFrameInternal(frame_id.value(),
                                         serialized_storage_key);
  }

  if (!host_) {
    return Response::InvalidParams("DevToolsAgentHost not found");
  }

  std::optional<blink::StorageKey> storage_key;

  const std::string& type = host_->GetType();

  if (type == content::DevToolsAgentHost::kTypeServiceWorker) {
    auto* service_worker_agent_host =
        static_cast<content::ServiceWorkerDevToolsAgentHost*>(host_.get());
    storage_key = service_worker_agent_host->GetStorageKey();
  } else if (type == content::DevToolsAgentHost::kTypeDedicatedWorker) {
    auto* dedicated_worker_agent_host =
        static_cast<content::DedicatedWorkerDevToolsAgentHost*>(host_.get());
    storage_key = dedicated_worker_agent_host->GetStorageKey();
  } else if (type == content::DevToolsAgentHost::kTypeSharedWorker) {
    auto* shared_worker_agent_host =
        static_cast<content::SharedWorkerDevToolsAgentHost*>(host_.get());
    storage_key = shared_worker_agent_host->GetStorageKey();
  } else {
    return Response::InvalidParams(
        "Target is not a supported worker type for storage inspection.");
  }

  if (!storage_key.has_value()) {
    return Response::ServerError(
        "Could not determine storage key for the target.");
  }
  if (storage_key->origin().opaque()) {
    return Response::ServerError(
        "Target corresponds to an opaque origin and its storage key cannot be "
        "serialized");
  }

  *serialized_storage_key = storage_key.value().Serialize();
  return Response::Success();
}

namespace {
uint32_t GetRemoveDataMask(const std::string& storage_types) {
  std::vector<std::string> types = base::SplitString(
      storage_types, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  std::unordered_set<std::string> set(types.begin(), types.end());
  uint32_t remove_mask = 0;
  if (set.count(Storage::StorageTypeEnum::Cookies)) {
    remove_mask |= StoragePartition::REMOVE_DATA_MASK_COOKIES;
  }
  if (set.count(Storage::StorageTypeEnum::File_systems)) {
    remove_mask |= StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS;
  }
  if (set.count(Storage::StorageTypeEnum::Indexeddb)) {
    remove_mask |= StoragePartition::REMOVE_DATA_MASK_INDEXEDDB;
  }
  if (set.count(Storage::StorageTypeEnum::Local_storage)) {
    remove_mask |= StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE;
  }
  if (set.count(Storage::StorageTypeEnum::Shader_cache)) {
    remove_mask |= StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE;
  }
  if (set.count(Storage::StorageTypeEnum::Service_workers)) {
    remove_mask |= StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS;
  }
  if (set.count(Storage::StorageTypeEnum::Cache_storage)) {
    remove_mask |= StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE;
  }
  if (set.count(Storage::StorageTypeEnum::Interest_groups)) {
    remove_mask |= StoragePartition::REMOVE_DATA_MASK_INTEREST_GROUPS;
  }
  if (set.count(Storage::StorageTypeEnum::Shared_storage)) {
    remove_mask |= StoragePartition::REMOVE_DATA_MASK_SHARED_STORAGE;
  }
  if (set.count(Storage::StorageTypeEnum::All)) {
    remove_mask |= StoragePartition::REMOVE_DATA_MASK_ALL;
  }
  return remove_mask;
}
}  // namespace

void StorageHandler::ClearDataForOrigin(
    const std::string& origin,
    const std::string& storage_types,
    std::unique_ptr<ClearDataForOriginCallback> callback) {
  if (!storage_partition_) {
    return callback->sendFailure(Response::InternalError());
  }

  uint32_t remove_mask = GetRemoveDataMask(storage_types);

  if (!remove_mask) {
    return callback->sendFailure(
        Response::InvalidParams("No valid storage type specified"));
  }

  storage_partition_->ClearData(
      remove_mask, StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
      blink::StorageKey::CreateFirstParty(url::Origin::Create(GURL(origin))),
      base::Time(), base::Time::Max(),
      base::BindOnce(&ClearDataForOriginCallback::sendSuccess,
                     std::move(callback)));
}

void StorageHandler::ClearDataForStorageKey(
    const std::string& storage_key,
    const std::string& storage_types,
    std::unique_ptr<ClearDataForStorageKeyCallback> callback) {
  if (!storage_partition_) {
    return callback->sendFailure(Response::InternalError());
  }

  uint32_t remove_mask = GetRemoveDataMask(storage_types);

  if (!remove_mask) {
    return callback->sendFailure(
        Response::InvalidParams("No valid storage type specified"));
  }

  std::optional<blink::StorageKey> key =
      blink::StorageKey::Deserialize(storage_key);
  if (!key) {
    return callback->sendFailure(
        Response::InvalidParams("Unable to deserialize storage key"));
  }
  storage_partition_->ClearData(
      remove_mask, StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, *key,
      base::Time(), base::Time::Max(),
      base::BindOnce(&ClearDataForStorageKeyCallback::sendSuccess,
                     std::move(callback)));
}

void StorageHandler::GetUsageAndQuota(
    const String& origin_string,
    std::unique_ptr<GetUsageAndQuotaCallback> callback) {
  if (!storage_partition_) {
    return callback->sendFailure(Response::InternalError());
  }

  GURL origin_url(origin_string);
  url::Origin origin = url::Origin::Create(origin_url);
  if (!origin_url.is_valid() || origin.opaque()) {
    return callback->sendFailure(
        Response::ServerError(origin_string + " is not a valid URL"));
  }

  storage::QuotaManager* manager = storage_partition_->GetQuotaManager();
  GetIOThreadTaskRunner({})->PostTask(
      FROM_HERE,
      base::BindOnce(&GetUsageAndQuotaOnIOThread, base::RetainedRef(manager),
                     blink::StorageKey::CreateFirstParty(origin),
                     std::move(callback)));
}

void StorageHandler::OverrideQuotaForOrigin(
    const String& origin_string,
    std::optional<double> quota_size,
    std::unique_ptr<OverrideQuotaForOriginCallback> callback) {
  if (!storage_partition_) {
    callback->sendFailure(Response::InternalError());
    return;
  }

  GURL url(origin_string);
  url::Origin origin = url::Origin::Create(url);
  if (!url.is_valid() || origin.opaque()) {
    callback->sendFailure(
        Response::InvalidParams(origin_string + " is not a valid URL"));
    return;
  }

  if (!quota_override_handle_) {
    scoped_refptr<storage::QuotaManagerProxy> manager_proxy =
        storage_partition_->GetQuotaManager()->proxy();
    quota_override_handle_ = manager_proxy->GetQuotaOverrideHandle();
  }

  quota_override_handle_->OverrideQuotaForStorageKey(
      blink::StorageKey::CreateFirstParty(origin),
      quota_size.has_value() ? std::make_optional(quota_size.value())
                             : std::nullopt,
      base::BindOnce(&OverrideQuotaForOriginCallback::sendSuccess,
                     std::move(callback)));
}

Response StorageHandler::TrackCacheStorageForOrigin(
    const std::string& origin_string) {
  if (!storage_partition_) {
    return Response::InternalError();
  }

  GURL origin_url(origin_string);
  url::Origin origin = url::Origin::Create(origin_url);
  if (!origin_url.is_valid() || origin.opaque()) {
    return Response::InvalidParams(origin_string + " is not a valid URL");
  }

  GetCacheStorageObserver()->TrackStorageKey(
      blink::StorageKey::CreateFirstParty(origin));
  return Response::Success();
}

Response StorageHandler::TrackCacheStorageForStorageKey(
    const std::string& storage_key) {
  if (!storage_partition_) {
    return Response::InternalError();
  }

  std::optional<blink::StorageKey> key =
      blink::StorageKey::Deserialize(storage_key);
  if (!key) {
    return Response::InvalidParams("Unable to deserialize storage key");
  }

  GetCacheStorageObserver()->TrackStorageKey(*key);
  return Response::Success();
}

Response StorageHandler::UntrackCacheStorageForOrigin(
    const std::string& origin_string) {
  if (!storage_partition_) {
    return Response::InternalError();
  }

  GURL origin_url(origin_string);
  url::Origin origin = url::Origin::Create(origin_url);
  if (!origin_url.is_valid() || origin.opaque()) {
    return Response::InvalidParams(origin_string + " is not a valid URL");
  }

  GetCacheStorageObserver()->UntrackStorageKey(
      blink::StorageKey::CreateFirstParty(origin));
  return Response::Success();
}

Response StorageHandler::UntrackCacheStorageForStorageKey(
    const std::string& storage_key) {
  if (!storage_partition_) {
    return Response::InternalError();
  }

  std::optional<blink::StorageKey> key =
      blink::StorageKey::Deserialize(storage_key);
  if (!key) {
    return Response::InvalidParams("Unable to deserialize storage key");
  }

  GetCacheStorageObserver()->UntrackStorageKey(*key);
  return Response::Success();
}

Response StorageHandler::TrackIndexedDBForOrigin(
    const std::string& origin_string) {
  if (!storage_partition_) {
    return Response::InternalError();
  }

  GURL origin_url(origin_string);
  url::Origin origin = url::Origin::Create(origin_url);
  if (!origin_url.is_valid() || origin.opaque()) {
    return Response::InvalidParams(origin_string + " is not a valid URL");
  }

  GetIndexedDBObserver()->TrackStorageKey(
      blink::StorageKey::CreateFirstParty(origin));
  return Response::Success();
}

Response StorageHandler::TrackIndexedDBForStorageKey(
    const std::string& storage_key) {
  if (!storage_partition_) {
    return Response::InternalError();
  }

  std::optional<blink::StorageKey> key =
      blink::StorageKey::Deserialize(storage_key);
  if (!key) {
    return Response::InvalidParams("Unable to deserialize storage key");
  }

  GetIndexedDBObserver()->TrackStorageKey(*key);
  return Response::Success();
}

Response StorageHandler::UntrackIndexedDBForOrigin(
    const std::string& origin_string) {
  if (!storage_partition_) {
    return Response::InternalError();
  }

  GURL origin_url(origin_string);
  url::Origin origin = url::Origin::Create(origin_url);
  if (!origin_url.is_valid() || origin.opaque()) {
    return Response::InvalidParams(origin_string + " is not a valid URL");
  }

  GetIndexedDBObserver()->UntrackStorageKey(
      blink::StorageKey::CreateFirstParty(origin));
  return Response::Success();
}

Response StorageHandler::UntrackIndexedDBForStorageKey(
    const std::string& storage_key) {
  if (!storage_partition_) {
    return Response::InternalError();
  }

  std::optional<blink::StorageKey> key =
      blink::StorageKey::Deserialize(storage_key);
  if (!key) {
    return Response::InvalidParams("Unable to deserialize storage key");
  }

  GetIndexedDBObserver()->UntrackStorageKey(*key);
  return Response::Success();
}

StorageHandler::CacheStorageObserver*
StorageHandler::GetCacheStorageObserver() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (!cache_storage_observer_) {
    mojo::PendingRemote<storage::mojom::CacheStorageObserver> observer;
    cache_storage_observer_ = std::make_unique<CacheStorageObserver>(
        weak_ptr_factory_.GetWeakPtr(),
        observer.InitWithNewPipeAndPassReceiver());
    storage_partition_->GetCacheStorageControl()->AddObserver(
        std::move(observer));
  }
  return cache_storage_observer_.get();
}

StorageHandler::IndexedDBObserver* StorageHandler::GetIndexedDBObserver() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (!indexed_db_observer_) {
    indexed_db_observer_ =
        std::make_unique<IndexedDBObserver>(weak_ptr_factory_.GetWeakPtr());
  }
  return indexed_db_observer_.get();
}

SharedStorageRuntimeManager* StorageHandler::GetSharedStorageRuntimeManager() {
  DCHECK(storage_partition_);
  return static_cast<StoragePartitionImpl*>(storage_partition_)
      ->GetSharedStorageRuntimeManager();
}

std::variant<protocol::Response, storage::SharedStorageManager*>
StorageHandler::GetSharedStorageManager() {
  if (!storage_partition_) {
    return Response::InternalError();
  }

  if (auto* manager = static_cast<StoragePartitionImpl*>(storage_partition_)
                          ->GetSharedStorageManager()) {
    return manager;
  }
  return Response::ServerError("Shared storage is disabled");
}

storage::QuotaManagerProxy* StorageHandler::GetQuotaManagerProxy() {
  DCHECK(storage_partition_);

  return static_cast<StoragePartitionImpl*>(storage_partition_)
      ->GetQuotaManagerProxy();
}

void StorageHandler::NotifyCacheStorageListChanged(
    const storage::BucketLocator& bucket_locator) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  frontend_->CacheStorageListUpdated(
      bucket_locator.storage_key.origin().Serialize(),
      bucket_locator.storage_key.Serialize(),
      base::NumberToString(bucket_locator.id.value()));
}

void StorageHandler::NotifyCacheStorageContentChanged(
    const storage::BucketLocator& bucket_locator,
    const std::string& name) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  frontend_->CacheStorageContentUpdated(
      bucket_locator.storage_key.origin().Serialize(),
      bucket_locator.storage_key.Serialize(),
      base::NumberToString(bucket_locator.id.value()), name);
}

void StorageHandler::NotifyIndexedDBListChanged(
    storage::BucketLocator bucket_locator) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  frontend_->IndexedDBListUpdated(
      bucket_locator.storage_key.origin().Serialize(),
      bucket_locator.storage_key.Serialize(),
      base::NumberToString(bucket_locator.id.value()));
}

void StorageHandler::NotifyIndexedDBContentChanged(
    storage::BucketLocator bucket_locator,
    const std::u16string& database_name,
    const std::u16string& object_store_name) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  frontend_->IndexedDBContentUpdated(
      bucket_locator.storage_key.origin().Serialize(),
      bucket_locator.storage_key.Serialize(),
      base::NumberToString(bucket_locator.id.value()),
      base::UTF16ToUTF8(database_name), base::UTF16ToUTF8(object_store_name));
}

Response StorageHandler::FindStoragePartition(
    const std::optional<std::string>& browser_context_id,
    StoragePartition** storage_partition) {
  BrowserContext* browser_context = nullptr;
  Response response =
      BrowserHandler::FindBrowserContext(browser_context_id, &browser_context);
  if (!response.IsSuccess()) {
    return response;
  }
  *storage_partition = browser_context->GetDefaultStoragePartition();
  if (!*storage_partition) {
    return Response::InternalError();
  }
  return Response::Success();
}

namespace {

void SendTrustTokens(
    std::unique_ptr<StorageHandler::GetTrustTokensCallback> callback,
    std::vector<::network::mojom::StoredTrustTokensForIssuerPtr> tokens) {
  auto result =
      std::make_unique<protocol::Array<protocol::Storage::TrustTokens>>();
  for (auto const& token : tokens) {
    auto protocol_token = protocol::Storage::TrustTokens::Create()
                              .SetIssuerOrigin(token->issuer.Serialize())
                              .SetCount(token->count)
                              .Build();
    result->push_back(std::move(protocol_token));
  }

  callback->sendSuccess(std::move(result));
}

}  // namespace

void StorageHandler::GetTrustTokens(
    std::unique_ptr<GetTrustTokensCallback> callback) {
  if (!storage_partition_) {
    callback->sendFailure(Response::InternalError());
    return;
  }

  storage_partition_->GetNetworkContext()->GetStoredTrustTokenCounts(
      base::BindOnce(&SendTrustTokens, std::move(callback)));
}

namespace {

void SendClearTrustTokensStatus(
    std::unique_ptr<StorageHandler::ClearTrustTokensCallback> callback,
    network::mojom::DeleteStoredTrustTokensStatus status) {
  switch (status) {
    case network::mojom::DeleteStoredTrustTokensStatus::kSuccessTokensDeleted:
      callback->sendSuccess(/* didDeleteTokens */ true);
      break;
    case network::mojom::DeleteStoredTrustTokensStatus::kSuccessNoTokensDeleted:
      callback->sendSuccess(/* didDeleteTokens */ false);
      break;
    case network::mojom::DeleteStoredTrustTokensStatus::kFailureFeatureDisabled:
      callback->sendFailure(
          Response::ServerError("The Trust Tokens feature is disabled."));
      break;
    case network::mojom::DeleteStoredTrustTokensStatus::kFailureInvalidOrigin:
      callback->sendFailure(
          Response::InvalidParams("The provided issuerOrigin is invalid. It "
                                  "must be a HTTP/HTTPS trustworthy origin."));
      break;
  }
}

}  // namespace

void StorageHandler::ClearTrustTokens(
    const std::string& issuerOrigin,
    std::unique_ptr<ClearTrustTokensCallback> callback) {
  if (!storage_partition_) {
    callback->sendFailure(Response::InternalError());
    return;
  }

  storage_partition_->GetNetworkContext()->DeleteStoredTrustTokens(
      url::Origin::Create(GURL(issuerOrigin)),
      base::BindOnce(&SendClearTrustTokensStatus, std::move(callback)));
}

void StorageHandler::OnInterestGroupAccessed(
    base::optional_ref<const std::string> auction_id,
    base::Time access_time,
    InterestGroupManagerImpl::InterestGroupObserver::AccessType type,
    const url::Origin& owner_origin,
    const std::string& name,
    base::optional_ref<const url::Origin> component_seller_origin,
    std::optional<double> bid,
    base::optional_ref<const std::string> bid_currency) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  using AccessType =
      InterestGroupManagerImpl::InterestGroupObserver::AccessType;
  std::string type_enum;
  switch (type) {
    case AccessType::kJoin:
      type_enum = Storage::InterestGroupAccessTypeEnum::Join;
      break;
    case AccessType::kLeave:
      type_enum = Storage::InterestGroupAccessTypeEnum::Leave;
      break;
    case AccessType::kUpdate:
      type_enum = Storage::InterestGroupAccessTypeEnum::Update;
      break;
    case AccessType::kLoaded:
      type_enum = Storage::InterestGroupAccessTypeEnum::Loaded;
      break;
    case AccessType::kBid:
      type_enum = Storage::InterestGroupAccessTypeEnum::Bid;
      break;
    case AccessType::kAdditionalBid:
      type_enum = Storage::InterestGroupAccessTypeEnum::AdditionalBid;
      break;
    case AccessType::kWin:
      type_enum = Storage::InterestGroupAccessTypeEnum::Win;
      break;
    case AccessType::kAdditionalBidWin:
      type_enum = Storage::InterestGroupAccessTypeEnum::AdditionalBidWin;
      break;
    case AccessType::kClear:
      type_enum = Storage::InterestGroupAccessTypeEnum::Clear;
      break;
    case AccessType::kTopLevelBid:
      type_enum = Storage::InterestGroupAccessTypeEnum::TopLevelBid;
      break;
    case AccessType::kTopLevelAdditionalBid:
      type_enum = Storage::InterestGroupAccessTypeEnum::TopLevelAdditionalBid;
      break;
  };
  frontend_->InterestGroupAccessed(
      access_time.InSecondsFSinceUnixEpoch(), type_enum,
      owner_origin.Serialize(), name,
      component_seller_origin.has_value()
          ? std::optional<String>(component_seller_origin->Serialize())
          : std::nullopt,
      bid, bid_currency.CopyAsOptional(), auction_id.CopyAsOptional());
}

namespace {
void SendGetInterestGroup(
    std::unique_ptr<StorageHandler::GetInterestGroupDetailsCallback> callback,
    std::optional<SingleStorageInterestGroup> storage_group) {
  if (!storage_group) {
    callback->sendFailure(Response::ServerError("Interest group not found"));
    return;
  }

  base::Value::Dict ig_serialization =
      SerializeInterestGroupForDevtools(storage_group.value()->interest_group);

  // "joiningOrigin" is in StorageInterestGroup, not InterestGroup, so it needs
  // to be added in separately.
  ig_serialization.Set("joiningOrigin",
                       storage_group.value()->joining_origin.Serialize());
  callback->sendSuccess(
      std::make_unique<base::Value::Dict>(std::move(ig_serialization)));
}

}  // namespace

void StorageHandler::GetInterestGroupDetails(
    const std::string& owner_origin_string,
    const std::string& name,
    std::unique_ptr<GetInterestGroupDetailsCallback> callback) {
  if (!storage_partition_) {
    callback->sendFailure(Response::InternalError());
    return;
  }

  InterestGroupManagerImpl* manager = static_cast<InterestGroupManagerImpl*>(
      storage_partition_->GetInterestGroupManager());
  if (!manager) {
    callback->sendFailure(
        Response::ServerError("Interest group storage is disabled"));
    return;
  }

  GURL owner_origin_url(owner_origin_string);
  if (!owner_origin_url.is_valid()) {
    callback->sendFailure(Response::ServerError("Invalid Owner Origin"));
    return;
  }
  url::Origin owner_origin = url::Origin::Create(GURL(owner_origin_string));
  DCHECK(!owner_origin.opaque());

  manager->GetInterestGroup(
      owner_origin, name,
      base::BindOnce(&SendGetInterestGroup, std::move(callback)));
}

Response StorageHandler::SetInterestGroupTracking(bool enable) {
  interest_group_tracking_enabled_ = enable;
  return SetInterestGroupTrackingInternal(storage_partition_, enable);
}

Response StorageHandler::SetInterestGroupTrackingInternal(
    StoragePartition* storage_partition,
    bool enable) {
  if (!storage_partition) {
    return Response::InternalError();
  }

  InterestGroupManagerImpl* manager = static_cast<InterestGroupManagerImpl*>(
      storage_partition->GetInterestGroupManager());
  if (!manager) {
    return Response::ServerError("Interest group storage is disabled.");
  }

  if (enable) {
    // Only add if we are not already registered as an observer. We only
    // observe the interest group manager, so if we're observing anything then
    // we are already registered.
    if (!InterestGroupManagerImpl::InterestGroupObserver::IsInObserverList()) {
      manager->AddInterestGroupObserver(this);
    }
  } else {
    // Removal doesn't care if we are not registered.
    manager->RemoveInterestGroupObserver(this);
  }
  return Response::Success();
}

Response StorageHandler::SetInterestGroupAuctionTracking(bool enable) {
  interest_group_auction_tracking_enabled_ = enable;
  return Response::Success();
}

namespace {

void SendSharedStorageMetadata(
    std::unique_ptr<StorageHandler::GetSharedStorageMetadataCallback> callback,
    storage::SharedStorageManager::MetadataResult metadata) {
  if (metadata.time_result ==
      storage::SharedStorageManager::OperationResult::kNotFound) {
    callback->sendFailure(Response::ServerError("Origin not found."));
    return;
  }

  std::string error_message;

  if (metadata.length == -1) {
    error_message += "Unable to retrieve `length`. ";
  }

  if (metadata.time_result !=
      storage::SharedStorageManager::OperationResult::kSuccess) {
    error_message += "Unable to retrieve `creationTime`. ";
  }

  if (metadata.budget_result !=
      storage::SharedStorageManager::OperationResult::kSuccess) {
    error_message += "Unable to retrieve `remainingBudget`. ";
  }

  if (metadata.bytes_used == -1) {
    error_message += "Unable to retrieve `bytes_used`. ";
  }

  if (!error_message.empty()) {
    callback->sendFailure(Response::ServerError(error_message));
    return;
  }

  auto protocol_metadata =
      protocol::Storage::SharedStorageMetadata::Create()
          .SetLength(metadata.length)
          .SetCreationTime(metadata.creation_time.InSecondsFSinceUnixEpoch())
          .SetRemainingBudget(metadata.remaining_budget)
          .SetBytesUsed(metadata.bytes_used)
          .Build();

  callback->sendSuccess(std::move(protocol_metadata));
}

}  // namespace

void StorageHandler::GetSharedStorageMetadata(
    const std::string& owner_origin_string,
    std::unique_ptr<GetSharedStorageMetadataCallback> callback) {
  auto manager_or_response = GetSharedStorageManager();
  if (std::holds_alternative<protocol::Response>(manager_or_response)) {
    callback->sendFailure(std::get<protocol::Response>(manager_or_response));
    return;
  }

  storage::SharedStorageManager* manager =
      std::get<storage::SharedStorageManager*>(manager_or_response);
  DCHECK(manager);

  GURL owner_origin_url(owner_origin_string);
  if (!owner_origin_url.is_valid()) {
    callback->sendFailure(Response::InvalidParams("Invalid owner origin"));
    return;
  }
  url::Origin owner_origin = url::Origin::Create(owner_origin_url);
  DCHECK(!owner_origin.opaque());

  manager->GetMetadata(
      std::move(owner_origin),
      base::BindOnce(&SendSharedStorageMetadata, std::move(callback)));
}

namespace {

void RetrieveSharedStorageEntries(
    std::unique_ptr<StorageHandler::GetSharedStorageEntriesCallback> callback,
    storage::SharedStorageManager::EntriesResult entries_result) {
  if (entries_result.result !=
      storage::SharedStorageManager::OperationResult::kSuccess) {
    callback->sendFailure(Response::ServerError("Database error"));
    return;
  }

  auto entries = std::make_unique<
      protocol::Array<protocol::Storage::SharedStorageEntry>>();

  for (const auto& entry : entries_result.entries) {
    auto protocol_entry = protocol::Storage::SharedStorageEntry::Create()
                              .SetKey(entry.first)
                              .SetValue(entry.second)
                              .Build();
    entries->push_back(std::move(protocol_entry));
  }

  callback->sendSuccess(std::move(entries));
}

}  // namespace

void StorageHandler::GetSharedStorageEntries(
    const std::string& owner_origin_string,
    std::unique_ptr<GetSharedStorageEntriesCallback> callback) {
  auto manager_or_response = GetSharedStorageManager();
  if (std::holds_alternative<protocol::Response>(manager_or_response)) {
    callback->sendFailure(std::get<protocol::Response>(manager_or_response));
    return;
  }

  storage::SharedStorageManager* manager =
      std::get<storage::SharedStorageManager*>(manager_or_response);
  DCHECK(manager);

  GURL owner_origin_url(owner_origin_string);
  if (!owner_origin_url.is_valid()) {
    callback->sendFailure(Response::InvalidParams("Invalid owner origin"));
    return;
  }
  url::Origin owner_origin = url::Origin::Create(owner_origin_url);
  DCHECK(!owner_origin.opaque());

  manager->GetEntriesForDevTools(
      owner_origin,
      base::BindOnce(&RetrieveSharedStorageEntries, std::move(callback)));
}

namespace {

void DispatchSharedStorageSetCallback(
    std::unique_ptr<Storage::Backend::SetSharedStorageEntryCallback> callback,
    storage::SharedStorageManager::OperationResult result) {
  if (result != storage::SharedStorageManager::OperationResult::kSet &&
      result != storage::SharedStorageManager::OperationResult::kIgnored) {
    callback->sendFailure(Response::ServerError("Database error"));
    return;
  }

  callback->sendSuccess();
}

}  // namespace

void StorageHandler::SetSharedStorageEntry(
    const std::string& owner_origin_string,
    const std::string& key,
    const std::string& value,
    std::optional<bool> ignore_if_present,
    std::unique_ptr<SetSharedStorageEntryCallback> callback) {
  auto manager_or_response = GetSharedStorageManager();
  if (std::holds_alternative<protocol::Response>(manager_or_response)) {
    callback->sendFailure(std::get<protocol::Response>(manager_or_response));
    return;
  }

  storage::SharedStorageManager* manager =
      std::get<storage::SharedStorageManager*>(manager_or_response);
  DCHECK(manager);

  GURL owner_origin_url(owner_origin_string);
  if (!owner_origin_url.is_valid()) {
    callback->sendFailure(Response::InvalidParams("Invalid owner origin"));
    return;
  }
  url::Origin owner_origin = url::Origin::Create(owner_origin_url);
  DCHECK(!owner_origin.opaque());

  auto set_behavior =
      ignore_if_present.value_or(false)
          ? storage::SharedStorageManager::SetBehavior::kIgnoreIfPresent
          : storage::SharedStorageManager::SetBehavior::kDefault;

  manager->Set(
      owner_origin, base::UTF8ToUTF16(key), base::UTF8ToUTF16(value),
      base::BindOnce(&DispatchSharedStorageSetCallback, std::move(callback)),
      set_behavior);
}

namespace {

template <typename CallbackType>
void DispatchSharedStorageCallback(
    std::unique_ptr<CallbackType> callback,
    storage::SharedStorageManager::OperationResult result) {
  if (result != storage::SharedStorageManager::OperationResult::kSuccess) {
    callback->sendFailure(Response::ServerError("Database error"));
    return;
  }

  callback->sendSuccess();
}

}  // namespace

void StorageHandler::DeleteSharedStorageEntry(
    const std::string& owner_origin_string,
    const std::string& key,
    std::unique_ptr<DeleteSharedStorageEntryCallback> callback) {
  auto manager_or_response = GetSharedStorageManager();
  if (std::holds_alternative<protocol::Response>(manager_or_response)) {
    callback->sendFailure(std::get<protocol::Response>(manager_or_response));
    return;
  }

  storage::SharedStorageManager* manager =
      std::get<storage::SharedStorageManager*>(manager_or_response);
  DCHECK(manager);

  GURL owner_origin_url(owner_origin_string);
  if (!owner_origin_url.is_valid()) {
    callback->sendFailure(Response::InvalidParams("Invalid owner origin"));
    return;
  }
  url::Origin owner_origin = url::Origin::Create(owner_origin_url);
  DCHECK(!owner_origin.opaque());

  manager->Delete(
      owner_origin, base::UTF8ToUTF16(key),
      base::BindOnce(
          &DispatchSharedStorageCallback<DeleteSharedStorageEntryCallback>,
          std::move(callback)));
}

void StorageHandler::ClearSharedStorageEntries(
    const std::string& owner_origin_string,
    std::unique_ptr<ClearSharedStorageEntriesCallback> callback) {
  auto manager_or_response = GetSharedStorageManager();
  if (std::holds_alternative<protocol::Response>(manager_or_response)) {
    callback->sendFailure(std::get<protocol::Response>(manager_or_response));
    return;
  }

  storage::SharedStorageManager* manager =
      std::get<storage::SharedStorageManager*>(manager_or_response);
  DCHECK(manager);

  GURL owner_origin_url(owner_origin_string);
  if (!owner_origin_url.is_valid()) {
    callback->sendFailure(Response::InvalidParams("Invalid owner origin"));
    return;
  }
  url::Origin owner_origin = url::Origin::Create(owner_origin_url);
  DCHECK(!owner_origin.opaque());

  manager->Clear(
      owner_origin,
      base::BindOnce(
          &DispatchSharedStorageCallback<ClearSharedStorageEntriesCallback>,
          std::move(callback)));
}

Response StorageHandler::SetSharedStorageTracking(bool enable) {
  if (enable) {
    auto* manager = GetSharedStorageRuntimeManager();
    if (!manager) {
      return Response::ServerError("Shared storage is disabled.");
    }
    // Only enable tracking if this handler is associated with a main render
    // frame host, and if tracking isn't already enabled.
    if (frame_host_ && frame_host_->IsOutermostMainFrame() &&
        !shared_storage_observation_.IsObserving()) {
      shared_storage_observation_.Observe(manager);
    }
  } else {
    shared_storage_observation_.Reset();
  }
  return Response::Success();
}

void StorageHandler::ResetSharedStorageBudget(
    const std::string& owner_origin_string,
    std::unique_ptr<ResetSharedStorageBudgetCallback> callback) {
  auto manager_or_response = GetSharedStorageManager();
  if (std::holds_alternative<protocol::Response>(manager_or_response)) {
    callback->sendFailure(std::get<protocol::Response>(manager_or_response));
    return;
  }

  storage::SharedStorageManager* manager =
      std::get<storage::SharedStorageManager*>(manager_or_response);
  DCHECK(manager);

  GURL owner_origin_url(owner_origin_string);
  if (!owner_origin_url.is_valid()) {
    callback->sendFailure(Response::InvalidParams("Invalid owner origin"));
    return;
  }
  url::Origin owner_origin = url::Origin::Create(owner_origin_url);
  DCHECK(!owner_origin.opaque());

  manager->ResetBudgetForDevTools(
      owner_origin,
      base::BindOnce(
          &DispatchSharedStorageCallback<ResetSharedStorageBudgetCallback>,
          std::move(callback)));
}

GlobalRenderFrameHostId StorageHandler::AssociatedFrameHostId() const {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  return frame_host_ ? frame_host_->GetGlobalId() : GlobalRenderFrameHostId();
}

bool StorageHandler::ShouldReceiveAllSharedStorageReports() const {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  return false;
}

namespace {

std::string GetFrameTokenFromGlobalRenderFrameHostId(
    GlobalRenderFrameHostId frame_id) {
  auto* rfh = frame_id ? RenderFrameHostImpl::FromID(frame_id) : nullptr;
  return rfh ? rfh->devtools_frame_token().ToString() : std::string();
}

const char* GetSharedStorageAccessMethodEnum(
    SharedStorageRuntimeManager::SharedStorageObserverInterface::AccessMethod
        method) {
  using AccessMethod =
      SharedStorageRuntimeManager::SharedStorageObserverInterface::AccessMethod;
  switch (method) {
    case AccessMethod::kAddModule:
      return Storage::SharedStorageAccessMethodEnum::AddModule;
    case AccessMethod::kCreateWorklet:
      return Storage::SharedStorageAccessMethodEnum::CreateWorklet;
    case AccessMethod::kSelectURL:
      return Storage::SharedStorageAccessMethodEnum::SelectURL;
    case AccessMethod::kRun:
      return Storage::SharedStorageAccessMethodEnum::Run;
    case AccessMethod::kBatchUpdate:
      return Storage::SharedStorageAccessMethodEnum::BatchUpdate;
    case AccessMethod::kSet:
      return Storage::SharedStorageAccessMethodEnum::Set;
    case AccessMethod::kAppend:
      return Storage::SharedStorageAccessMethodEnum::Append;
    case AccessMethod::kDelete:
      return Storage::SharedStorageAccessMethodEnum::Delete;
    case AccessMethod::kClear:
      return Storage::SharedStorageAccessMethodEnum::Clear;
    case AccessMethod::kGet:
      return Storage::SharedStorageAccessMethodEnum::Get;
    case AccessMethod::kKeys:
      return Storage::SharedStorageAccessMethodEnum::Keys;
    case AccessMethod::kValues:
      return Storage::SharedStorageAccessMethodEnum::Values;
    case AccessMethod::kEntries:
      return Storage::SharedStorageAccessMethodEnum::Entries;
    case AccessMethod::kLength:
      return Storage::SharedStorageAccessMethodEnum::Length;
    case AccessMethod::kRemainingBudget:
      return Storage::SharedStorageAccessMethodEnum::RemainingBudget;
  };
  NOTREACHED();
}

}  // namespace

void StorageHandler::OnSharedStorageAccessed(
    base::Time access_time,
    blink::SharedStorageAccessScope scope,
    SharedStorageRuntimeManager::SharedStorageObserverInterface::AccessMethod
        method,
    GlobalRenderFrameHostId main_frame_id,
    const std::string& owner_origin,
    const SharedStorageEventParams& params) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  using AccessScope = blink::SharedStorageAccessScope;

  std::string scope_enum;
  switch (scope) {
    case AccessScope::kWindow:
      scope_enum = Storage::SharedStorageAccessScopeEnum::Window;
      break;
    case AccessScope::kSharedStorageWorklet:
      scope_enum = Storage::SharedStorageAccessScopeEnum::SharedStorageWorklet;
      break;
    case AccessScope::kProtectedAudienceWorklet:
      scope_enum =
          Storage::SharedStorageAccessScopeEnum::ProtectedAudienceWorklet;
      break;
    case AccessScope::kHeader:
      scope_enum = Storage::SharedStorageAccessScopeEnum::Header;
      break;
  };

  auto protocol_params =
      protocol::Storage::SharedStorageAccessParams::Create().Build();

  if (params.script_source_url) {
    protocol_params->SetScriptSourceUrl(*params.script_source_url);
  }
  if (params.data_origin) {
    protocol_params->SetDataOrigin(*params.data_origin);
  }
  if (params.operation_name) {
    protocol_params->SetOperationName(*params.operation_name);
  }
  if (params.operation_id) {
    protocol_params->SetOperationId(base::NumberToString(*params.operation_id));
  }
  if (params.keep_alive) {
    protocol_params->SetKeepAlive(*params.keep_alive);
  }
  if (params.serialized_data) {
    protocol_params->SetSerializedData(*params.serialized_data);
  }
  if (params.urn_uuid) {
    protocol_params->SetUrnUuid(*params.urn_uuid);
  }
  if (params.key) {
    protocol_params->SetKey(*params.key);
  }
  if (params.value) {
    protocol_params->SetValue(*params.value);
  }
  if (params.ignore_if_present) {
    protocol_params->SetIgnoreIfPresent(*params.ignore_if_present);
  }
  if (params.worklet_ordinal) {
    protocol_params->SetWorkletOrdinal(*params.worklet_ordinal);
  }
  if (!params.worklet_devtools_token.is_empty()) {
    protocol_params->SetWorkletTargetId(
        params.worklet_devtools_token.ToString());
  }
  if (params.with_lock) {
    protocol_params->SetWithLock(*params.with_lock);
  }
  if (params.batch_update_id) {
    protocol_params->SetBatchUpdateId(
        base::NumberToString(*params.batch_update_id));
  }
  if (params.batch_size) {
    protocol_params->SetBatchSize(*params.batch_size);
  }

  if (params.private_aggregation_config) {
    auto protocol_private_aggregation_config =
        protocol::Storage::SharedStoragePrivateAggregationConfig::Create()
            .SetFilteringIdMaxBytes(params.private_aggregation_config->config
                                        ->filtering_id_max_bytes)
            .Build();
    if (params.private_aggregation_config->config
            ->aggregation_coordinator_origin) {
      protocol_private_aggregation_config->SetAggregationCoordinatorOrigin(
          params.private_aggregation_config->config
              ->aggregation_coordinator_origin->Serialize());
    }
    if (params.private_aggregation_config->config->context_id) {
      protocol_private_aggregation_config->SetContextId(
          params.private_aggregation_config->config->context_id.value());
    }
    if (params.private_aggregation_config->config->max_contributions) {
      protocol_private_aggregation_config->SetMaxContributions(
          params.private_aggregation_config->config->max_contributions.value());
    }

    protocol_params->SetPrivateAggregationConfig(
        std::move(protocol_private_aggregation_config));
  }

  if (params.urls_with_metadata) {
    auto protocol_urls = std::make_unique<
        protocol::Array<protocol::Storage::SharedStorageUrlWithMetadata>>();

    for (const auto& url_with_metadata : *params.urls_with_metadata) {
      auto reporting_metadata = std::make_unique<
          protocol::Array<protocol::Storage::SharedStorageReportingMetadata>>();

      for (const auto& metadata_pair : url_with_metadata.reporting_metadata) {
        auto reporting_pair =
            protocol::Storage::SharedStorageReportingMetadata::Create()
                .SetEventType(metadata_pair.first)
                .SetReportingUrl(metadata_pair.second)
                .Build();
        reporting_metadata->push_back(std::move(reporting_pair));
      }

      auto protocol_url =
          protocol::Storage::SharedStorageUrlWithMetadata::Create()
              .SetUrl(url_with_metadata.url)
              .SetReportingMetadata(std::move(reporting_metadata))
              .Build();
      protocol_urls->push_back(std::move(protocol_url));
    }

    protocol_params->SetUrlsWithMetadata(std::move(protocol_urls));
  }

  frontend_->SharedStorageAccessed(
      access_time.InSecondsFSinceUnixEpoch(), scope_enum,
      GetSharedStorageAccessMethodEnum(method),
      GetFrameTokenFromGlobalRenderFrameHostId(main_frame_id), owner_origin,
      net::SchemefulSite(GURL(owner_origin)).Serialize(),
      std::move(protocol_params));
}

void StorageHandler::OnSharedStorageSelectUrlUrnUuidGenerated(
    const GURL& urn_uuid) {}
void StorageHandler::OnSharedStorageSelectUrlConfigPopulated(
    const std::optional<FencedFrameConfig>& config) {}

void StorageHandler::OnSharedStorageWorkletOperationExecutionFinished(
    base::Time finished_time,
    base::TimeDelta execution_time,
    SharedStorageRuntimeManager::SharedStorageObserverInterface::AccessMethod
        method,
    int operation_id,
    const base::UnguessableToken& worklet_devtools_token,
    GlobalRenderFrameHostId main_frame_id,
    const std::string& owner_origin) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  frontend_->SharedStorageWorkletOperationExecutionFinished(
      finished_time.InSecondsFSinceUnixEpoch(), execution_time.InMicroseconds(),
      GetSharedStorageAccessMethodEnum(method),
      base::NumberToString(operation_id), worklet_devtools_token.ToString(),
      GetFrameTokenFromGlobalRenderFrameHostId(main_frame_id), owner_origin);
}

DispatchResponse StorageHandler::SetStorageBucketTracking(
    const std::string& serialized_storage_key,
    bool enable) {
  auto storage_key = blink::StorageKey::Deserialize(serialized_storage_key);
  if (!storage_key.has_value()) {
    return Response::InvalidParams("Invalid Storage Key given.");
  }

  if (enable) {
    storage::QuotaManagerProxy* manager = GetQuotaManagerProxy();
    if (!quota_manager_observer_) {
      quota_manager_observer_ =
          std::make_unique<StorageHandler::QuotaManagerObserver>(
              weak_ptr_factory_.GetWeakPtr(), manager);
    }
    quota_manager_observer_->TrackStorageKey(storage_key.value(), manager);
  } else if (quota_manager_observer_) {
    quota_manager_observer_->UntrackStorageKey(storage_key.value());
  }
  return Response::Success();
}

DispatchResponse StorageHandler::DeleteStorageBucket(
    std::unique_ptr<protocol::Storage::StorageBucket> bucket) {
  storage::QuotaManagerProxy* manager = GetQuotaManagerProxy();
  DCHECK(manager);

  if (!bucket->HasName()) {
    return Response::InvalidParams("Can't delete the default bucket.");
  }

  auto storage_key = blink::StorageKey::Deserialize(bucket->GetStorageKey());
  if (!storage_key.has_value()) {
    return Response::InvalidParams("Invalid Storage Key given.");
  }

  manager->DeleteBucket(storage_key.value(), bucket->GetName(""),
                        base::SingleThreadTaskRunner::GetCurrentDefault(),
                        base::DoNothing());
  return Response::Success();
}

void StorageHandler::NotifyCreateOrUpdateBucket(
    const storage::BucketInfo& bucket_info) {
  frontend_->StorageBucketCreatedOrUpdated(BuildBucketInfo(bucket_info));
}

void StorageHandler::NotifyDeleteBucket(
    const storage::BucketLocator& bucket_locator) {
  frontend_->StorageBucketDeleted(
      base::NumberToString(bucket_locator.id.value()));
}

AttributionManager* StorageHandler::GetAttributionManager() {
  if (!storage_partition_) {
    return nullptr;
  }
  return static_cast<StoragePartitionImpl*>(storage_partition_)
      ->GetAttributionManager();
}

void StorageHandler::SetAttributionReportingLocalTestingMode(
    bool enabled,
    std::unique_ptr<SetAttributionReportingLocalTestingModeCallback> callback) {
  auto* manager = GetAttributionManager();
  if (!manager) {
    callback->sendFailure(Response::InternalError());
    return;
  }

  manager->SetDebugMode(
      enabled,
      base::BindOnce(
          &SetAttributionReportingLocalTestingModeCallback::sendSuccess,
          std::move(callback)));
}

void StorageHandler::SendPendingAttributionReports(
    std::unique_ptr<SendPendingAttributionReportsCallback> callback) {
  auto* manager = GetAttributionManager();
  if (!manager) {
    callback->sendFailure(Response::InternalError());
    return;
  }
  manager->GetPendingReportsForInternalUse(
      /*limit=*/-1,
      base::BindOnce(
          [](base::WeakPtr<StorageHandler> storage_handler,
             std::unique_ptr<SendPendingAttributionReportsCallback> callback,
             std::vector<AttributionReport> reports) {
            if (!storage_handler) {
              callback->sendFailure(Response::InternalError());
              return;
            }
            auto* manager = storage_handler->GetAttributionManager();
            if (!manager) {
              callback->sendFailure(Response::InternalError());
              return;
            }
            auto barrier = base::BarrierClosure(
                reports.size(),
                base::BindOnce(
                    &SendPendingAttributionReportsCallback::sendSuccess,
                    std::move(callback), reports.size()));
            for (const auto& report : reports) {
              manager->SendReportForWebUI(report.id(), barrier);
            }
          },
          weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void StorageHandler::ResetAttributionReporting() {
  attribution_observation_.Reset();

  auto* manager = GetAttributionManager();
  if (!manager) {
    return;
  }

  manager->SetDebugMode(/*enabled=*/std::nullopt, base::DoNothing());
}

namespace {

using ::attribution_reporting::mojom::AggregatableResult;
using ::attribution_reporting::mojom::EventLevelResult;
using ::attribution_reporting::mojom::StoreSourceResult;

Storage::AttributionReportingSourceRegistrationResult
ToSourceRegistrationResult(StoreSourceResult result) {
  switch (result) {
    case StoreSourceResult::kSuccess:
      return Storage::AttributionReportingSourceRegistrationResultEnum::Success;
    case StoreSourceResult::kInternalError:
      return Storage::AttributionReportingSourceRegistrationResultEnum::
          InternalError;
    case StoreSourceResult::kInsufficientSourceCapacity:
      return Storage::AttributionReportingSourceRegistrationResultEnum::
          InsufficientSourceCapacity;
    case StoreSourceResult::kInsufficientUniqueDestinationCapacity:
      return Storage::AttributionReportingSourceRegistrationResultEnum::
          InsufficientUniqueDestinationCapacity;
    case StoreSourceResult::kExcessiveReportingOrigins:
      return Storage::AttributionReportingSourceRegistrationResultEnum::
          ExcessiveReportingOrigins;
    case StoreSourceResult::kProhibitedByBrowserPolicy:
      return Storage::AttributionReportingSourceRegistrationResultEnum::
          ProhibitedByBrowserPolicy;
    case StoreSourceResult::kSuccessNoised:
      return Storage::AttributionReportingSourceRegistrationResultEnum::
          SuccessNoised;
    case StoreSourceResult::kDestinationReportingLimitReached:
      return Storage::AttributionReportingSourceRegistrationResultEnum::
          DestinationReportingLimitReached;
    case StoreSourceResult::kDestinationGlobalLimitReached:
      return Storage::AttributionReportingSourceRegistrationResultEnum::
          DestinationGlobalLimitReached;
    case StoreSourceResult::kDestinationBothLimitsReached:
      return Storage::AttributionReportingSourceRegistrationResultEnum::
          DestinationBothLimitsReached;
    case StoreSourceResult::kReportingOriginsPerSiteLimitReached:
      return Storage::AttributionReportingSourceRegistrationResultEnum::
          ReportingOriginsPerSiteLimitReached;
    case StoreSourceResult::kExceedsMaxChannelCapacity:
      return Storage::AttributionReportingSourceRegistrationResultEnum::
          ExceedsMaxChannelCapacity;
    case StoreSourceResult::kExceedsMaxScopesChannelCapacity:
      return Storage::AttributionReportingSourceRegistrationResultEnum::
          ExceedsMaxScopesChannelCapacity;
    case StoreSourceResult::kExceedsMaxTriggerStateCardinality:
      return Storage::AttributionReportingSourceRegistrationResultEnum::
          ExceedsMaxTriggerStateCardinality;
    case StoreSourceResult::kExceedsMaxEventStatesLimit:
      return Storage::AttributionReportingSourceRegistrationResultEnum::
          ExceedsMaxEventStatesLimit;
    case StoreSourceResult::kDestinationPerDayReportingLimitReached:
      return Storage::AttributionReportingSourceRegistrationResultEnum::
          DestinationPerDayReportingLimitReached;
  }
}

Storage::AttributionReportingEventLevelResult ToEventLevelResult(
    EventLevelResult result) {
  switch (result) {
    case EventLevelResult::kSuccess:
      return Storage::AttributionReportingEventLevelResultEnum::Success;
    case EventLevelResult::kSuccessDroppedLowerPriority:
      return Storage::AttributionReportingEventLevelResultEnum::
          SuccessDroppedLowerPriority;
    case EventLevelResult::kInternalError:
      return Storage::AttributionReportingEventLevelResultEnum::InternalError;
    case EventLevelResult::kNoCapacityForConversionDestination:
      return Storage::AttributionReportingEventLevelResultEnum::
          NoCapacityForAttributionDestination;
    case EventLevelResult::kNoMatchingImpressions:
      return Storage::AttributionReportingEventLevelResultEnum::
          NoMatchingSources;
    case EventLevelResult::kDeduplicated:
      return Storage::AttributionReportingEventLevelResultEnum::Deduplicated;
    case EventLevelResult::kExcessiveAttributions:
      return Storage::AttributionReportingEventLevelResultEnum::
          ExcessiveAttributions;
    case EventLevelResult::kPriorityTooLow:
      return Storage::AttributionReportingEventLevelResultEnum::PriorityTooLow;
    case EventLevelResult::kNeverAttributedSource:
      return Storage::AttributionReportingEventLevelResultEnum::
          NeverAttributedSource;
    case EventLevelResult::kExcessiveReportingOrigins:
      return Storage::AttributionReportingEventLevelResultEnum::
          ExcessiveReportingOrigins;
    case EventLevelResult::kNoMatchingSourceFilterData:
      return Storage::AttributionReportingEventLevelResultEnum::
          NoMatchingSourceFilterData;
    case EventLevelResult::kProhibitedByBrowserPolicy:
      return Storage::AttributionReportingEventLevelResultEnum::
          ProhibitedByBrowserPolicy;
    case EventLevelResult::kNoMatchingConfigurations:
      return Storage::AttributionReportingEventLevelResultEnum::
          NoMatchingConfigurations;
    case EventLevelResult::kExcessiveReports:
      return Storage::AttributionReportingEventLevelResultEnum::
          ExcessiveReports;
    case EventLevelResult::kFalselyAttributedSource:
      return Storage::AttributionReportingEventLevelResultEnum::
          FalselyAttributedSource;
    case EventLevelResult::kReportWindowPassed:
      return Storage::AttributionReportingEventLevelResultEnum::
          ReportWindowPassed;
    case EventLevelResult::kNotRegistered:
      return Storage::AttributionReportingEventLevelResultEnum::NotRegistered;
    case EventLevelResult::kReportWindowNotStarted:
      return Storage::AttributionReportingEventLevelResultEnum::
          ReportWindowNotStarted;
    case EventLevelResult::kNoMatchingTriggerData:
      return Storage::AttributionReportingEventLevelResultEnum::
          NoMatchingTriggerData;
  }
}

Storage::AttributionReportingAggregatableResult ToAggregatableResult(
    AggregatableResult result) {
  switch (result) {
    case AggregatableResult::kSuccess:
      return Storage::AttributionReportingAggregatableResultEnum::Success;
    case AggregatableResult::kInternalError:
      return Storage::AttributionReportingAggregatableResultEnum::InternalError;
    case AggregatableResult::kNoCapacityForConversionDestination:
      return Storage::AttributionReportingAggregatableResultEnum::
          NoCapacityForAttributionDestination;
    case AggregatableResult::kNoMatchingImpressions:
      return Storage::AttributionReportingAggregatableResultEnum::
          NoMatchingSources;
    case AggregatableResult::kExcessiveAttributions:
      return Storage::AttributionReportingAggregatableResultEnum::
          ExcessiveAttributions;
    case AggregatableResult::kExcessiveReportingOrigins:
      return Storage::AttributionReportingAggregatableResultEnum::
          ExcessiveReportingOrigins;
    case AggregatableResult::kNoHistograms:
      return Storage::AttributionReportingAggregatableResultEnum::NoHistograms;
    case AggregatableResult::kInsufficientBudget:
      return Storage::AttributionReportingAggregatableResultEnum::
          InsufficientBudget;
    case AggregatableResult::kInsufficientNamedBudget:
      return Storage::AttributionReportingAggregatableResultEnum::
          InsufficientNamedBudget;
    case AggregatableResult::kNoMatchingSourceFilterData:
      return Storage::AttributionReportingAggregatableResultEnum::
          NoMatchingSourceFilterData;
    case AggregatableResult::kNotRegistered:
      return Storage::AttributionReportingAggregatableResultEnum::NotRegistered;
    case AggregatableResult::kProhibitedByBrowserPolicy:
      return Storage::AttributionReportingAggregatableResultEnum::
          ProhibitedByBrowserPolicy;
    case AggregatableResult::kDeduplicated:
      return Storage::AttributionReportingAggregatableResultEnum::Deduplicated;
    case AggregatableResult::kReportWindowPassed:
      return Storage::AttributionReportingAggregatableResultEnum::
          ReportWindowPassed;
    case AggregatableResult::kExcessiveReports:
      return Storage::AttributionReportingAggregatableResultEnum::
          ExcessiveReports;
  }
}

std::unique_ptr<Array<Storage::AttributionReportingFilterDataEntry>>
ToFilterDataEntries(const attribution_reporting::FilterData& filter_data) {
  auto out =
      std::make_unique<Array<Storage::AttributionReportingFilterDataEntry>>();

  for (const auto& [key, values] : filter_data.filter_values()) {
    out->emplace_back(Storage::AttributionReportingFilterDataEntry::Create()
                          .SetKey(key)
                          .SetValues(std::make_unique<Array<String>>(values))
                          .Build());
  }

  return out;
}

std::unique_ptr<Array<Storage::AttributionReportingFilterConfig>>
ToFilterConfigs(
    const std::vector<attribution_reporting::FilterConfig>& filter_configs) {
  auto out =
      std::make_unique<Array<Storage::AttributionReportingFilterConfig>>();

  for (const auto& config : filter_configs) {
    auto filter_data =
        std::make_unique<Array<Storage::AttributionReportingFilterDataEntry>>();
    for (const auto& [key, values] : config.filter_values()) {
      filter_data->emplace_back(
          Storage::AttributionReportingFilterDataEntry::Create()
              .SetKey(key)
              .SetValues(std::make_unique<Array<String>>(values))
              .Build());
    }

    auto config_entry = Storage::AttributionReportingFilterConfig::Create()
                            .SetFilterValues(std::move(filter_data))
                            .Build();
    if (auto lookback_window = config.lookback_window();
        lookback_window.has_value()) {
      config_entry->SetLookbackWindow(lookback_window->InSeconds());
    }

    out->emplace_back(std::move(config_entry));
  }

  return out;
}

std::unique_ptr<Storage::AttributionReportingFilterPair> ToFilterPair(
    const attribution_reporting::FilterPair& filters) {
  return Storage::AttributionReportingFilterPair::Create()
      .SetFilters(ToFilterConfigs(filters.positive))
      .SetNotFilters(ToFilterConfigs(filters.negative))
      .Build();
}

std::unique_ptr<Array<Storage::AttributionReportingAggregationKeysEntry>>
ToAggregationKeysEntries(const attribution_reporting::AggregationKeys& keys) {
  auto out = std::make_unique<
      Array<Storage::AttributionReportingAggregationKeysEntry>>();

  for (const auto& [key, value] : keys.keys()) {
    out->emplace_back(
        Storage::AttributionReportingAggregationKeysEntry::Create()
            .SetKey(key)
            .SetValue(attribution_reporting::HexEncodeAggregationKey(value))
            .Build());
  }

  return out;
}

std::unique_ptr<Storage::AttributionReportingEventReportWindows>
ToEventReportWindows(const attribution_reporting::EventReportWindows& windows) {
  auto end_times = std::make_unique<Array<int>>();
  for (base::TimeDelta end_time : windows.end_times()) {
    end_times->emplace_back(end_time.InSeconds());
  }
  return Storage::AttributionReportingEventReportWindows::Create()
      .SetStart(windows.start_time().InSeconds())
      .SetEnds(std::move(end_times))
      .Build();
}

std::unique_ptr<Array<double>> ToTriggerData(
    const attribution_reporting::TriggerDataSet::TriggerData& trigger_data) {
  return std::make_unique<Array<double>>(trigger_data.begin(),
                                         trigger_data.end());
}

Storage::AttributionReportingTriggerDataMatching ToTriggerDataMatching(
    attribution_reporting::mojom::TriggerDataMatching value) {
  switch (value) {
    case attribution_reporting::mojom::TriggerDataMatching::kExact:
      return Storage::AttributionReportingTriggerDataMatchingEnum::Exact;
    case attribution_reporting::mojom::TriggerDataMatching::kModulus:
      return Storage::AttributionReportingTriggerDataMatchingEnum::Modulus;
  }
}

std::unique_ptr<Array<Storage::AttributionReportingAggregatableDedupKey>>
ToAggregatableDedupKeys(
    const std::vector<attribution_reporting::AggregatableDedupKey>&
        dedup_keys) {
  auto out = std::make_unique<
      Array<Storage::AttributionReportingAggregatableDedupKey>>();
  for (const auto& dedup_key : dedup_keys) {
    auto dedup_key_entry =
        Storage::AttributionReportingAggregatableDedupKey::Create()
            .SetFilters(ToFilterPair(dedup_key.filters))
            .Build();
    if (dedup_key.dedup_key.has_value()) {
      dedup_key_entry->SetDedupKey(base::NumberToString(*dedup_key.dedup_key));
    }
    out->push_back(std::move(dedup_key_entry));
  }

  return out;
}

std::unique_ptr<Array<Storage::AttributionReportingEventTriggerData>>
ToEventTriggerData(const std::vector<attribution_reporting::EventTriggerData>&
                       event_triggers) {
  auto out =
      std::make_unique<Array<Storage::AttributionReportingEventTriggerData>>();
  for (const auto& event_trigger : event_triggers) {
    auto event_trigger_entry =
        Storage::AttributionReportingEventTriggerData::Create()
            .SetData(base::NumberToString(event_trigger.data))
            .SetPriority(base::NumberToString(event_trigger.priority))
            .SetFilters(ToFilterPair(event_trigger.filters))
            .Build();
    if (event_trigger.dedup_key.has_value()) {
      event_trigger_entry->SetDedupKey(
          base::NumberToString(*event_trigger.dedup_key));
    }
    out->push_back(std::move(event_trigger_entry));
  }

  return out;
}

std::unique_ptr<Array<Storage::AttributionReportingAggregatableTriggerData>>
ToAggregatableTriggerData(
    const std::vector<attribution_reporting::AggregatableTriggerData>&
        aggregatable_triggers) {
  auto out = std::make_unique<
      Array<Storage::AttributionReportingAggregatableTriggerData>>();
  for (const auto& aggregatable_trigger : aggregatable_triggers) {
    out->emplace_back(
        Storage::AttributionReportingAggregatableTriggerData::Create()
            .SetKeyPiece(attribution_reporting::HexEncodeAggregationKey(
                aggregatable_trigger.key_piece()))
            .SetSourceKeys(std::make_unique<Array<String>>(
                aggregatable_trigger.source_keys().begin(),
                aggregatable_trigger.source_keys().end()))
            .SetFilters(ToFilterPair(aggregatable_trigger.filters()))
            .Build());
  }

  return out;
}

std::unique_ptr<Array<Storage::AttributionReportingAggregatableValueDictEntry>>
ToAggregatableValueDictEntries(
    const attribution_reporting::AggregatableValues::Values&
        aggregatable_value) {
  auto out = std::make_unique<
      Array<Storage::AttributionReportingAggregatableValueDictEntry>>();
  out->reserve(aggregatable_value.size());
  for (const auto& [key, value] : aggregatable_value) {
    out->emplace_back(
        Storage::AttributionReportingAggregatableValueDictEntry::Create()
            .SetKey(key)
            .SetValue(value.value())
            .SetFilteringId(base::NumberToString(value.filtering_id()))
            .Build());
  }

  return out;
}

std::unique_ptr<Array<Storage::AttributionReportingAggregatableValueEntry>>
ToAggregatableValueEntries(
    const std::vector<attribution_reporting::AggregatableValues>&
        aggregatable_values) {
  auto out = std::make_unique<
      Array<Storage::AttributionReportingAggregatableValueEntry>>();
  out->reserve(aggregatable_values.size());
  for (const auto& aggregatable_value : aggregatable_values) {
    out->emplace_back(
        Storage::AttributionReportingAggregatableValueEntry::Create()
            .SetValues(
                ToAggregatableValueDictEntries(aggregatable_value.values()))
            .SetFilters(ToFilterPair(aggregatable_value.filters()))
            .Build());
  }

  return out;
}

Storage::AttributionReportingSourceRegistrationTimeConfig
ToSourceRegistrationTimeConfig(
    attribution_reporting::mojom::SourceRegistrationTimeConfig
        source_registration_time_config) {
  switch (source_registration_time_config) {
    case attribution_reporting::mojom::SourceRegistrationTimeConfig::kInclude:
      return Storage::AttributionReportingSourceRegistrationTimeConfigEnum::
          Include;
    case attribution_reporting::mojom::SourceRegistrationTimeConfig::kExclude:
      return Storage::AttributionReportingSourceRegistrationTimeConfigEnum::
          Exclude;
  }
}

std::unique_ptr<
    Array<Storage::AttributionReportingAggregatableDebugReportingData>>
ToAggregatableDebugReportingDataArray(
    const attribution_reporting::AggregatableDebugReportingConfig::DebugData&
        data) {
  auto out = std::make_unique<
      Array<Storage::AttributionReportingAggregatableDebugReportingData>>();
  for (const auto& [type, contribution] : data) {
    auto types = std::make_unique<Array<String>>();
    types->emplace_back(attribution_reporting::SerializeDebugDataType(type));
    out->emplace_back(
        Storage::AttributionReportingAggregatableDebugReportingData::Create()
            .SetKeyPiece(attribution_reporting::HexEncodeAggregationKey(
                contribution.key_piece()))
            .SetValue(contribution.value())
            .SetTypes(std::move(types))
            .Build());
  }
  return out;
}

std::unique_ptr<Storage::AttributionReportingAggregatableDebugReportingConfig>
ToAggregatableDebugReportingConfig(
    std::optional<double> budget,
    const attribution_reporting::AggregatableDebugReportingConfig& config) {
  auto out_config =
      Storage::AttributionReportingAggregatableDebugReportingConfig::Create()
          .SetKeyPiece(
              attribution_reporting::HexEncodeAggregationKey(config.key_piece))
          .SetDebugData(
              ToAggregatableDebugReportingDataArray(config.debug_data))
          .Build();
  if (budget.has_value()) {
    out_config->SetBudget(*budget);
  }
  if (config.aggregation_coordinator_origin.has_value()) {
    out_config->SetAggregationCoordinatorOrigin(
        config.aggregation_coordinator_origin->Serialize());
  }
  return out_config;
}

std::unique_ptr<Array<Storage::AttributionReportingNamedBudgetDef>>
ToNamedBudgetDefs(
    const attribution_reporting::AggregatableNamedBudgetDefs& budgets) {
  auto out =
      std::make_unique<Array<Storage::AttributionReportingNamedBudgetDef>>();
  for (const auto& [name, budget] : budgets.budgets()) {
    out->emplace_back(Storage::AttributionReportingNamedBudgetDef::Create()
                          .SetName(name)
                          .SetBudget(budget)
                          .Build());
  }
  return out;
}

std::unique_ptr<Array<Storage::AttributionReportingNamedBudgetCandidate>>
ToNamedBudgetCandidates(
    const std::vector<attribution_reporting::AggregatableNamedBudgetCandidate>&
        candidates) {
  auto out = std::make_unique<
      Array<Storage::AttributionReportingNamedBudgetCandidate>>();
  for (const auto& candidate : candidates) {
    auto& out_candidate = out->emplace_back(
        Storage::AttributionReportingNamedBudgetCandidate::Create()
            .SetFilters(ToFilterPair(candidate.filters()))
            .Build());

    if (const std::optional<std::string>& name = candidate.name()) {
      out_candidate->SetName(*name);
    }
  }
  return out;
}

}  // namespace

void StorageHandler::OnSourceHandled(
    const StorableSource& source,
    base::Time source_time,
    std::optional<uint64_t> cleared_debug_key,
    attribution_reporting::mojom::StoreSourceResult result) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  const auto& registration = source.registration();

  auto destination_sites = std::make_unique<Array<String>>();
  for (const auto& site : registration.destination_set.destinations()) {
    destination_sites->emplace_back(site.Serialize());
  }

  const auto& common_info = source.common_info();
  const auto& aggregatable_debug_reporting_config =
      registration.aggregatable_debug_reporting_config;
  auto out_source =
      Storage::AttributionReportingSourceRegistration::Create()
          .SetTime(source_time.InSecondsFSinceUnixEpoch())
          .SetType(
              attribution_reporting::SourceTypeName(common_info.source_type()))
          .SetSourceOrigin(common_info.source_origin()->Serialize())
          .SetReportingOrigin(common_info.reporting_origin()->Serialize())
          .SetDestinationSites(std::move(destination_sites))
          .SetEventId(base::NumberToString(registration.source_event_id))
          .SetPriority(base::NumberToString(registration.priority))
          .SetFilterData(ToFilterDataEntries(registration.filter_data))
          .SetAggregationKeys(
              ToAggregationKeysEntries(registration.aggregation_keys))
          .SetExpiry(registration.expiry.InSeconds())
          .SetTriggerData(
              ToTriggerData(registration.trigger_data.trigger_data()))
          .SetEventReportWindows(
              ToEventReportWindows(registration.event_report_windows))
          .SetAggregatableReportWindow(
              registration.aggregatable_report_window.InSeconds())
          .SetTriggerDataMatching(
              ToTriggerDataMatching(registration.trigger_data_matching))
          .SetDestinationLimitPriority(
              base::NumberToString(registration.destination_limit_priority))
          .SetAggregatableDebugReportingConfig(
              ToAggregatableDebugReportingConfig(
                  aggregatable_debug_reporting_config.budget(),
                  aggregatable_debug_reporting_config.config()))
          .SetMaxEventLevelReports(registration.max_event_level_reports)
          .SetNamedBudgets(
              ToNamedBudgetDefs(registration.aggregatable_named_budget_defs))
          .SetDebugReporting(registration.debug_reporting)
          .SetEventLevelEpsilon(registration.event_level_epsilon)
          .Build();

  if (registration.debug_key.has_value()) {
    out_source->SetDebugKey(base::NumberToString(*registration.debug_key));
  }

  if (const std::optional<attribution_reporting::AttributionScopesData>&
          attribution_scopes_data = registration.attribution_scopes_data) {
    out_source->SetScopesData(
        Storage::AttributionScopesData::Create()
            .SetValues(std::make_unique<Array<String>>(
                attribution_scopes_data->attribution_scopes_set()
                    .scopes()
                    .begin(),
                attribution_scopes_data->attribution_scopes_set()
                    .scopes()
                    .end()))
            .SetLimit(attribution_scopes_data->attribution_scope_limit())
            .SetMaxEventStates(attribution_scopes_data->max_event_states())
            .Build());
  }

  frontend_->AttributionReportingSourceRegistered(
      std::move(out_source), ToSourceRegistrationResult(result));
}

void StorageHandler::OnTriggerHandled(std::optional<uint64_t> cleared_debug_key,
                                      const CreateReportResult& result) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  const auto& registration = result.trigger().registration();

  auto out_trigger =
      Storage::AttributionReportingTriggerRegistration::Create()
          .SetFilters(ToFilterPair(registration.filters))
          .SetAggregatableDedupKeys(
              ToAggregatableDedupKeys(registration.aggregatable_dedup_keys))
          .SetEventTriggerData(ToEventTriggerData(registration.event_triggers))
          .SetAggregatableTriggerData(
              ToAggregatableTriggerData(registration.aggregatable_trigger_data))
          .SetAggregatableValues(
              ToAggregatableValueEntries(registration.aggregatable_values))
          .SetAggregatableFilteringIdMaxBytes(
              registration.aggregatable_trigger_config
                  .aggregatable_filtering_id_max_bytes()
                  .value())
          .SetDebugReporting(registration.debug_reporting)
          .SetSourceRegistrationTimeConfig(ToSourceRegistrationTimeConfig(
              registration.aggregatable_trigger_config
                  .source_registration_time_config()))
          .SetAggregatableDebugReportingConfig(
              ToAggregatableDebugReportingConfig(
                  /*budget=*/std::nullopt,
                  registration.aggregatable_debug_reporting_config))
          .SetScopes(std::make_unique<Array<String>>(
              registration.attribution_scopes.scopes().begin(),
              registration.attribution_scopes.scopes().end()))
          .SetNamedBudgets(ToNamedBudgetCandidates(
              registration.aggregatable_named_budget_candidates))
          .Build();

  if (registration.debug_key.has_value()) {
    out_trigger->SetDebugKey(base::NumberToString(*registration.debug_key));
  }
  if (registration.aggregation_coordinator_origin.has_value()) {
    out_trigger->SetAggregationCoordinatorOrigin(
        registration.aggregation_coordinator_origin->Serialize());
  }
  if (registration.aggregatable_trigger_config.trigger_context_id()
          .has_value()) {
    out_trigger->SetTriggerContextId(
        *registration.aggregatable_trigger_config.trigger_context_id());
  }

  frontend_->AttributionReportingTriggerRegistered(
      std::move(out_trigger), ToEventLevelResult(result.event_level_status()),
      ToAggregatableResult(result.aggregatable_status()));
}

void StorageHandler::OnReportSent(const AttributionReport& report,
                                  bool is_debug_report,
                                  const SendResult& result) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  std::optional<int> net_error;
  std::optional<std::string> net_error_name;
  std::optional<int> http_status_code;
  Storage::AttributionReportingReportResult out_result = std::visit(
      absl::Overload{
          [&](SendResult::Sent result) {
            if (result.status > 0) {
              http_status_code = result.status;
            } else {
              net_error = result.status;
              net_error_name = net::ErrorToShortString(result.status);
            }
            return Storage::AttributionReportingReportResultEnum::Sent;
          },
          [](SendResult::Dropped) {
            return Storage::AttributionReportingReportResultEnum::Prohibited;
          },
          [](SendResult::Expired) {
            return Storage::AttributionReportingReportResultEnum::Expired;
          },
          [](SendResult::AssemblyFailure) {
            return Storage::AttributionReportingReportResultEnum::
                FailedToAssemble;
          },
      },
      result.result);

  frontend_->AttributionReportingReportSent(
      report.ReportURL(is_debug_report).spec(),
      std::make_unique<base::Value::Dict>(report.ReportBody()), out_result,
      net_error, std::move(net_error_name), http_status_code);
}

void StorageHandler::OnDebugReportSent(const AttributionDebugReport& report,
                                       int status,
                                       base::Time time) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  std::optional<int> net_error;
  std::optional<std::string> net_error_name;
  std::optional<int> http_status_code;

  if (status > 0) {
    http_status_code = status;
  } else {
    net_error = status;
    net_error_name = net::ErrorToShortString(status);
  }

  auto body = std::make_unique<Array<Value::Dict>>();
  for (const auto& item : report.ReportBody()) {
    const auto* as_dict = item.GetIfDict();
    CHECK(as_dict);
    body->push_back(std::make_unique<Value::Dict>(as_dict->Clone()));
  }

  frontend_->AttributionReportingVerboseDebugReportSent(
      report.ReportUrl().spec(), std::move(body), net_error,
      std::move(net_error_name), http_status_code);
}

Response StorageHandler::SetAttributionReportingTracking(bool enable) {
  if (enable) {
    auto* manager = GetAttributionManager();
    if (!manager) {
      return Response::ServerError("Attribution Reporting is disabled.");
    }
    // Prevent `DCHECK` crashes in `base::ScopedObservation::Observe()` when we
    // are already observing.
    if (!attribution_observation_.IsObserving()) {
      attribution_observation_.Observe(manager);
    }
  } else {
    attribution_observation_.Reset();
  }
  return Response::Success();
}

void StorageHandler::NotifyInterestGroupAuctionEventOccurred(
    base::Time event_time,
    content::InterestGroupAuctionEventType type,
    const std::string& unique_auction_id,
    base::optional_ref<const std::string> parent_auction_id,
    const base::Value::Dict& auction_config) {
  if (!interest_group_auction_tracking_enabled_) {
    return;
  }
  std::string type_enum;
  switch (type) {
    case content::InterestGroupAuctionEventType::kStarted:
      type_enum = Storage::InterestGroupAuctionEventTypeEnum::Started;
      break;
    case content::InterestGroupAuctionEventType::kConfigResolved:
      type_enum = Storage::InterestGroupAuctionEventTypeEnum::ConfigResolved;
      break;
  };
  frontend_->InterestGroupAuctionEventOccurred(
      event_time.InSecondsFSinceUnixEpoch(), type_enum, unique_auction_id,
      parent_auction_id.CopyAsOptional(),
      std::make_unique<base::Value::Dict>(auction_config.Clone()));
}

void StorageHandler::NotifyInterestGroupAuctionNetworkRequestCreated(
    content::InterestGroupAuctionFetchType type,
    const std::string& request_id,
    const std::vector<std::string>& devtools_auction_ids) {
  if (!interest_group_auction_tracking_enabled_) {
    return;
  }
  std::string type_enum;
  switch (type) {
    case content::InterestGroupAuctionFetchType::kBidderJs:
      type_enum = Storage::InterestGroupAuctionFetchTypeEnum::BidderJs;
      break;
    case content::InterestGroupAuctionFetchType::kBidderWasm:
      type_enum = Storage::InterestGroupAuctionFetchTypeEnum::BidderWasm;
      break;
    case content::InterestGroupAuctionFetchType::kSellerJs:
      type_enum = Storage::InterestGroupAuctionFetchTypeEnum::SellerJs;
      break;
    case content::InterestGroupAuctionFetchType::kBidderTrustedSignals:
      type_enum =
          Storage::InterestGroupAuctionFetchTypeEnum::BidderTrustedSignals;
      break;
    case content::InterestGroupAuctionFetchType::kSellerTrustedSignals:
      type_enum =
          Storage::InterestGroupAuctionFetchTypeEnum::SellerTrustedSignals;
      break;
  };
  frontend_->InterestGroupAuctionNetworkRequestCreated(
      type_enum, request_id,
      std::make_unique<std::vector<std::string>>(devtools_auction_ids));
}

Response StorageHandler::SetProtectedAudienceKAnonymity(
    const std::string& in_owner_origin,
    const std::string& in_group_name,
    std::unique_ptr<std::vector<Binary>> in_hashes) {
  url::Origin owner_origin = url::Origin::Create(GURL(in_owner_origin));

  // Ensure we are in "test" mode.
  // For now we just make sure the interest group owner is a .test domain.
  if (!base::EndsWith(owner_origin.host(), ".test")) {
    return Response::ServerError("owner origin must be on a .test domain");
  }

  std::vector<std::string> hashes;
  for (const auto& in_hash : *in_hashes) {
    hashes.emplace_back(base::as_string_view(in_hash));
  }

  InterestGroupManagerImpl* manager = static_cast<InterestGroupManagerImpl*>(
      storage_partition_->GetInterestGroupManager());
  if (!manager) {
    return Response::ServerError("Protected Audience not enabled");
  }
  manager->UpdateKAnonymity(
      blink::InterestGroupKey(std::move(owner_origin), in_group_name),
      /*positive_hashed_keys=*/std::move(hashes),
      /*update_time=*/base::Time::Now(),
      /*replace_existing_values=*/true);
  return Response::Success();
}

}  // namespace protocol
}  // namespace content
