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

#include "content/browser/storage_partition_impl.h"

#include <stdint.h>

#include <functional>
#include <memory>
#include <set>
#include <utility>
#include <vector>

#include "base/barrier_callback.h"
#include "base/barrier_closure.h"
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/dcheck_is_on.h"
#include "base/feature_list.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback_forward.h"
#include "base/functional/callback_helpers.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/no_destructor.h"
#include "base/observer_list.h"
#include "base/run_loop.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/threading/sequence_local_storage_slot.h"
#include "base/time/default_clock.h"
#include "base/types/optional_util.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "components/attribution_reporting/features.h"
#include "components/leveldb_proto/public/proto_database_provider.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/cpp/constants.h"
#include "components/services/storage/public/cpp/filesystem/filesystem_impl.h"
#include "components/services/storage/public/mojom/filesystem/directory.mojom.h"
#include "components/services/storage/public/mojom/storage_service.mojom.h"
#include "components/services/storage/shared_storage/shared_storage_manager.h"
#include "components/services/storage/storage_service_impl.h"
#include "components/variations/net/variations_http_headers.h"
#include "content/browser/aggregation_service/aggregation_service.h"
#include "content/browser/aggregation_service/aggregation_service_features.h"
#include "content/browser/aggregation_service/aggregation_service_impl.h"
#include "content/browser/attribution_reporting/attribution_manager_impl.h"
#include "content/browser/background_fetch/background_fetch_context.h"
#include "content/browser/blob_storage/blob_registry_wrapper.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/bluetooth/bluetooth_allowed_devices_map.h"
#include "content/browser/broadcast_channel/broadcast_channel_service.h"
#include "content/browser/browsing_data/clear_site_data_handler.h"
#include "content/browser/browsing_data/storage_partition_code_cache_data_remover.h"
#include "content/browser/browsing_topics/browsing_topics_site_data_manager_impl.h"
#include "content/browser/buckets/bucket_manager.h"
#include "content/browser/cache_storage/cache_storage_control_wrapper.h"
#include "content/browser/code_cache/generated_code_cache.h"
#include "content/browser/code_cache/generated_code_cache_context.h"
#include "content/browser/cookie_deprecation_label/cookie_deprecation_label_manager_impl.h"
#include "content/browser/cookie_store/cookie_store_manager.h"
#include "content/browser/devtools/devtools_background_services_context_impl.h"
#include "content/browser/devtools/devtools_instrumentation.h"
#include "content/browser/devtools/devtools_url_loader_interceptor.h"
#include "content/browser/file_system/browser_file_system_helper.h"
#include "content/browser/file_system_access/file_system_access_manager_impl.h"
#include "content/browser/font_access/font_access_manager.h"
#include "content/browser/gpu/gpu_disk_cache_factory.h"
#include "content/browser/host_zoom_level_context.h"
#include "content/browser/indexed_db/indexed_db_control_wrapper.h"
#include "content/browser/interest_group/interest_group_manager_impl.h"
#include "content/browser/loader/keep_alive_url_loader_service.h"
#include "content/browser/loader/resource_cache_manager.h"
#include "content/browser/loader/subresource_proxying_url_loader_service.h"
#include "content/browser/locks/lock_manager.h"
#include "content/browser/navigation_or_document_handle.h"
#include "content/browser/network/shared_dictionary_util.h"
#include "content/browser/network_context_client_base_impl.h"
#include "content/browser/notifications/platform_notification_context_impl.h"
#include "content/browser/payments/payment_app_context_impl.h"
#include "content/browser/preloading/prerender/prerender_final_status.h"
#include "content/browser/private_aggregation/private_aggregation_manager.h"
#include "content/browser/private_aggregation/private_aggregation_manager_impl.h"
#include "content/browser/push_messaging/push_messaging_context.h"
#include "content/browser/quota/quota_context.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/runtime_feature_state/runtime_feature_state_document_data.h"
#include "content/browser/service_worker/service_worker_container_host.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/shared_storage/shared_storage_header_observer.h"
#include "content/browser/shared_storage/shared_storage_worklet_host_manager.h"
#include "content/browser/ssl/ssl_client_auth_handler.h"
#include "content/browser/ssl/ssl_error_handler.h"
#include "content/browser/ssl_private_key_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/worker_host/shared_worker_service_impl.h"
#include "content/common/features.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/browsing_data_filter_builder.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/dom_storage_context.h"
#include "content/public/browser/login_delegate.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/permission_controller.h"
#include "content/public/browser/permission_result.h"
#include "content/public/browser/private_aggregation_data_model.h"
#include "content/public/browser/private_network_device_delegate.h"
#include "content/public/browser/service_process_host.h"
#include "content/public/browser/session_storage_usage_info.h"
#include "content/public/browser/shared_cors_origin_access_list.h"
#include "content/public/browser/storage_notification_service.h"
#include "content/public/browser/storage_partition_config.h"
#include "content/public/browser/storage_usage_info.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "net/base/features.h"
#include "net/base/net_errors.h"
#include "net/cookies/cookie_setting_override.h"
#include "net/ssl/client_cert_store.h"
#include "ppapi/buildflags/buildflags.h"
#include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom.h"
#include "services/network/public/cpp/cors/origin_access_list.h"
#include "services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/cookie_access_observer.mojom.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/shared_dictionary_access_observer.mojom.h"
#include "services/network/public/mojom/trust_tokens.mojom.h"
#include "services/network/public/mojom/url_loader_network_service_observer.mojom.h"
#include "storage/browser/database/database_tracker.h"
#include "storage/browser/quota/quota_client_type.h"
#include "storage/browser/quota/quota_manager.h"
#include "storage/browser/quota/quota_manager_impl.h"
#include "storage/browser/quota/quota_settings.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/permissions/permission_utils.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/devtools/inspector_issue.mojom-shared.h"
#include "third_party/blink/public/mojom/private_network_device/private_network_device.mojom.h"
#include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
#include "url/scheme_host_port.h"

#if BUILDFLAG(IS_ANDROID)
#include "content/public/browser/android/java_interfaces.h"
#include "net/android/http_auth_negotiate_android.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#endif  // BUILDFLAG(IS_ANDROID)

#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
#include "content/browser/media/cdm_storage_common.h"
#include "content/browser/media/cdm_storage_manager.h"
#include "content/browser/media/media_license_manager.h"
#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)

using CookieDeletionFilter = network::mojom::CookieDeletionFilter;
using CookieDeletionFilterPtr = network::mojom::CookieDeletionFilterPtr;

namespace content {

namespace {

using Type = StoragePartitionImpl::URLLoaderNetworkContext::Type;

const storage::QuotaSettings* g_test_quota_settings;

// Timeout after which the
// History.ClearBrowsingData.Duration.SlowTasks180sStoragePartition histogram is
// recorded.
const base::TimeDelta kSlowTaskTimeout = base::Seconds(180);

// If true, Storage Service instances will always be started in-process.
bool g_force_in_process_storage_service = false;

mojo::Remote<storage::mojom::StorageService>& GetStorageServiceRemoteStorage() {
  // NOTE: This use of sequence-local storage is only to ensure that the Remote
  // only lives as long as the UI-thread sequence, since the UI-thread sequence
  // may be torn down and reinitialized e.g. between unit tests.
  static base::SequenceLocalStorageSlot<
      mojo::Remote<storage::mojom::StorageService>>
      remote_slot;
  return remote_slot.GetOrCreateValue();
}

void RunInProcessStorageService(
    mojo::PendingReceiver<storage::mojom::StorageService> receiver) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  static base::SequenceLocalStorageSlot<
      std::unique_ptr<storage::StorageServiceImpl>>
      service_storage_slot;
  service_storage_slot.GetOrCreateValue() =
      std::make_unique<storage::StorageServiceImpl>(std::move(receiver),
                                                    /*io_task_runner=*/nullptr);
}

#if !BUILDFLAG(IS_ANDROID)
void BindStorageServiceFilesystemImpl(
    const base::FilePath& directory_path,
    mojo::PendingReceiver<storage::mojom::Directory> receiver) {
  mojo::MakeSelfOwnedReceiver(
      std::make_unique<storage::FilesystemImpl>(
          directory_path, storage::FilesystemImpl::ClientType::kUntrusted),
      std::move(receiver));
}
#endif

mojo::Remote<storage::mojom::StorageService>& GetStorageServiceRemote() {
  mojo::Remote<storage::mojom::StorageService>& remote =
      GetStorageServiceRemoteStorage();
  if (!remote) {
#if !BUILDFLAG(IS_ANDROID)
    const base::FilePath sandboxed_data_dir =
        GetContentClient()
            ->browser()
            ->GetSandboxedStorageServiceDataDirectory();
    const bool single_process_mode =
        base::CommandLine::ForCurrentProcess()->HasSwitch(
            switches::kSingleProcess);
    const bool oop_storage_enabled = !sandboxed_data_dir.empty() &&
                                     !single_process_mode &&
                                     !g_force_in_process_storage_service;
    if (oop_storage_enabled) {
      DCHECK(sandboxed_data_dir.IsAbsolute())
          << "Storage Service data directory must be an absolute path, but \""
          << sandboxed_data_dir << "\" is not an absolute path.";
      remote = ServiceProcessHost::Launch<storage::mojom::StorageService>(
          ServiceProcessHost::Options()
              .WithDisplayName("Storage Service")
              .Pass());
      remote.reset_on_disconnect();

      // Provide the service with an API it can use to access filesystem
      // contents *only* within the embedder's specified data directory.
      mojo::PendingRemote<storage::mojom::Directory> directory;
      base::ThreadPool::CreateSequencedTaskRunner(
          {base::MayBlock(), base::TaskPriority::USER_VISIBLE})
          ->PostTask(FROM_HERE,
                     base::BindOnce(
                         &BindStorageServiceFilesystemImpl, sandboxed_data_dir,
                         directory.InitWithNewPipeAndPassReceiver()));
      remote->SetDataDirectory(sandboxed_data_dir, std::move(directory));
    } else
#endif  // !BUILDFLAG(IS_ANDROID)
    {
      GetIOThreadTaskRunner({})->PostTask(
          FROM_HERE, base::BindOnce(&RunInProcessStorageService,
                                    remote.BindNewPipeAndPassReceiver()));
    }

    if (base::CommandLine::ForCurrentProcess()->HasSwitch(
            switches::kEnableAggressiveDOMStorageFlushing)) {
      remote->EnableAggressiveDomStorageFlushing();
    }
  }
  return remote;
}

// A callback to create a URLLoaderFactory that is used in tests.
StoragePartitionImpl::CreateNetworkFactoryCallback&
GetCreateURLLoaderFactoryCallback() {
  static base::NoDestructor<StoragePartitionImpl::CreateNetworkFactoryCallback>
      create_factory_callback;
  return *create_factory_callback;
}

void OnClearedCookies(base::OnceClosure callback, uint32_t num_deleted) {
  // The final callback needs to happen from UI thread.
  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    GetUIThreadTaskRunner({})->PostTask(
        FROM_HERE,
        base::BindOnce(&OnClearedCookies, std::move(callback), num_deleted));
    return;
  }

  std::move(callback).Run();
}

void CheckQuotaManagedDataDeletionStatus(size_t* deletion_task_count,
                                         base::OnceClosure callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (*deletion_task_count == 0) {
    delete deletion_task_count;
    std::move(callback).Run();
  }
}

void OnQuotaManagedBucketDeleted(const storage::BucketLocator& bucket,
                                 size_t* deletion_task_count,
                                 base::OnceClosure callback,
                                 blink::mojom::QuotaStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  DCHECK_GT(*deletion_task_count, 0u);
  if (status != blink::mojom::QuotaStatusCode::kOk) {
    DLOG(ERROR) << "Couldn't remove data type " << static_cast<int>(bucket.type)
                << " for bucket with storage key "
                << bucket.storage_key.GetDebugString() << " is_default "
                << bucket.is_default << " and bucket id " << bucket.id
                << ". Status: " << static_cast<int>(status);
  }

  (*deletion_task_count)--;
  CheckQuotaManagedDataDeletionStatus(deletion_task_count, std::move(callback));
}

void PerformQuotaManagerStorageCleanup(
    const scoped_refptr<storage::QuotaManager>& quota_manager,
    blink::mojom::StorageType quota_storage_type,
    storage::QuotaClientTypes quota_client_types,
    base::OnceClosure callback) {
  quota_manager->PerformStorageCleanup(
      quota_storage_type, std::move(quota_client_types), std::move(callback));
}

void ClearedGpuCache(base::OnceClosure callback) {
  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    GetUIThreadTaskRunner({})->PostTask(
        FROM_HERE, base::BindOnce(&ClearedGpuCache, std::move(callback)));
    return;
  }
  std::move(callback).Run();
}

void OnLocalStorageUsageInfo(
    const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context,
    const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy,
    StoragePartition::StorageKeyPolicyMatcherFunction storage_key_matcher,
    bool perform_storage_cleanup,
    const base::Time delete_begin,
    const base::Time delete_end,
    base::OnceClosure callback,
    const std::vector<StorageUsageInfo>& infos) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  base::OnceClosure done_callback =
      perform_storage_cleanup
          ? base::BindOnce(
                &DOMStorageContextWrapper::PerformLocalStorageCleanup,
                dom_storage_context, std::move(callback))
          : std::move(callback);

  base::RepeatingClosure barrier =
      base::BarrierClosure(infos.size(), std::move(done_callback));
  for (const StorageUsageInfo& info : infos) {
    if (storage_key_matcher &&
        !storage_key_matcher.Run(info.storage_key,
                                 special_storage_policy.get())) {
      barrier.Run();
      continue;
    }

    if (info.last_modified >= delete_begin &&
        info.last_modified <= delete_end) {
      dom_storage_context->DeleteLocalStorage(info.storage_key, barrier);
    } else {
      barrier.Run();
    }
  }
}

void OnSessionStorageUsageInfo(
    const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context,
    const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy,
    StoragePartition::StorageKeyPolicyMatcherFunction storage_key_matcher,
    bool perform_storage_cleanup,
    base::OnceClosure callback,
    const std::vector<SessionStorageUsageInfo>& infos) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  base::OnceClosure done_callback =
      perform_storage_cleanup
          ? base::BindOnce(
                &DOMStorageContextWrapper::PerformSessionStorageCleanup,
                dom_storage_context, std::move(callback))
          : std::move(callback);

  base::RepeatingClosure barrier =
      base::BarrierClosure(infos.size(), std::move(done_callback));

  for (const SessionStorageUsageInfo& info : infos) {
    if (storage_key_matcher &&
        !storage_key_matcher.Run(info.storage_key,
                                 special_storage_policy.get())) {
      barrier.Run();
      continue;
    }
    dom_storage_context->DeleteSessionStorage(info, barrier);
  }
}

void ClearLocalStorageOnUIThread(
    const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context,
    const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy,
    StoragePartition::StorageKeyPolicyMatcherFunction storage_key_matcher,
    const blink::StorageKey& storage_key,
    bool perform_storage_cleanup,
    const base::Time begin,
    const base::Time end,
    base::OnceClosure callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (!storage_key.origin().opaque()) {
    bool can_delete =
        !storage_key_matcher ||
        storage_key_matcher.Run(storage_key, special_storage_policy.get());
    if (can_delete) {
      dom_storage_context->DeleteLocalStorage(storage_key, std::move(callback));
    } else {
      std::move(callback).Run();
    }
    return;
  }

  dom_storage_context->GetLocalStorageUsage(
      base::BindOnce(&OnLocalStorageUsageInfo, dom_storage_context,
                     special_storage_policy, std::move(storage_key_matcher),
                     perform_storage_cleanup, begin, end, std::move(callback)));
}

void ClearSessionStorageOnUIThread(
    const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context,
    const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy,
    StoragePartition::StorageKeyPolicyMatcherFunction storage_key_matcher,
    bool perform_storage_cleanup,
    base::OnceClosure callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  dom_storage_context->GetSessionStorageUsage(
      base::BindOnce(&OnSessionStorageUsageInfo, dom_storage_context,
                     special_storage_policy, std::move(storage_key_matcher),
                     perform_storage_cleanup, std::move(callback)));
}

BrowserContext* GetBrowserContextFromStoragePartition(
    base::WeakPtr<StoragePartitionImpl> weak_partition_ptr) {
  return weak_partition_ptr ? weak_partition_ptr->browser_context() : nullptr;
}

// Returns the WebContents corresponding to `context`.
WebContents* GetWebContents(
    StoragePartitionImpl::URLLoaderNetworkContext context) {
  if (!context.navigation_or_document()) {
    return nullptr;
  }
  return context.navigation_or_document()->GetWebContents();
}

// A getter for the context required for the SSLClientAuthHandler. If
// `BrowserContext` is null, it indicates the calling context is no longer
// valid. This assumes that if the WebContents goes away, the caller is no
// longer valid.
std::pair<BrowserContext*, WebContents*> GetContextFromNetworkContext(
    StoragePartitionImpl::URLLoaderNetworkContext context) {
  WebContents* web_contents = GetWebContents(context);
  if (!web_contents) {
    return std::make_pair(nullptr, nullptr);
  }
  return std::make_pair(web_contents->GetBrowserContext(), web_contents);
}

// A getter for the context required for the SSLClientAuthHandler. If
// `BrowserContext` is null, it indicates the calling context is no longer
// valid. This version allows for a null WebContents and is used in cases when
// the context is not associated with a document.
// TODO(devlin): This is used as a proxy for if a service worker requestor is
// still alive, but it's a pretty sorry excuse. The StoragePartition is owned by
// the BrowserContext, and can definitely outlive service workers.
// This seems to be okay, since in the request sites its used, we also have
// checks for if the mojo receiver goes away, but... eww.
std::pair<BrowserContext*, WebContents*> GetContextFromStoragePartition(
    base::WeakPtr<StoragePartitionImpl> storage_partition) {
  return std::make_pair(
      GetBrowserContextFromStoragePartition(storage_partition), nullptr);
}

// LoginHandlerDelegate manages HTTP auth. It is self-owning and deletes itself
// when the credentials are resolved or the AuthChallengeResponder is cancelled.
class LoginHandlerDelegate {
 public:
  LoginHandlerDelegate(
      mojo::PendingRemote<network::mojom::AuthChallengeResponder>
          auth_challenge_responder,
      WebContents::Getter web_contents_getter,
      const net::AuthChallengeInfo& auth_info,
      bool is_request_for_primary_main_frame,
      uint32_t process_id,
      uint32_t request_id,
      const GURL& url,
      scoped_refptr<net::HttpResponseHeaders> response_headers,
      bool first_auth_attempt)
      : auth_challenge_responder_(std::move(auth_challenge_responder)),
        auth_info_(auth_info),
        request_id_(process_id, request_id),
        is_request_for_primary_main_frame_(is_request_for_primary_main_frame),
        creating_login_delegate_(false),
        url_(url),
        response_headers_(std::move(response_headers)),
        first_auth_attempt_(first_auth_attempt),
        web_contents_getter_(web_contents_getter) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    auth_challenge_responder_.set_disconnect_handler(base::BindOnce(
        &LoginHandlerDelegate::OnRequestCancelled, base::Unretained(this)));

    DevToolsURLLoaderInterceptor::HandleAuthRequest(
        request_id_, auth_info_,
        base::BindOnce(&LoginHandlerDelegate::ContinueAfterInterceptor,
                       weak_factory_.GetWeakPtr()));
  }

 private:
  void OnRequestCancelled() {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    // This will destroy `login_handler_io_` on the IO thread and, if needed,
    // inform the delegate.
    delete this;
  }

  void ContinueAfterInterceptor(
      bool use_fallback,
      const absl::optional<net::AuthCredentials>& auth_credentials) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    DCHECK(!(use_fallback && auth_credentials.has_value()));
    if (!use_fallback) {
      OnAuthCredentials(auth_credentials);
      return;
    }

    WebContents* web_contents = web_contents_getter_.Run();
    if (!web_contents) {
      OnAuthCredentials(absl::nullopt);
      return;
    }

    // WeakPtr is not strictly necessary here due to OnRequestCancelled.
    creating_login_delegate_ = true;
    login_delegate_ = GetContentClient()->browser()->CreateLoginDelegate(
        auth_info_, web_contents, request_id_,
        is_request_for_primary_main_frame_, url_, response_headers_,
        first_auth_attempt_,
        base::BindOnce(&LoginHandlerDelegate::OnAuthCredentials,
                       weak_factory_.GetWeakPtr()));
    creating_login_delegate_ = false;
    if (!login_delegate_) {
      OnAuthCredentials(absl::nullopt);
      return;
    }
  }

  void OnAuthCredentials(
      const absl::optional<net::AuthCredentials>& auth_credentials) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    // CreateLoginDelegate must not call the callback reentrantly. For
    // robustness, detect this mistake.
    CHECK(!creating_login_delegate_);
    auth_challenge_responder_->OnAuthCredentials(auth_credentials);
    delete this;
  }

  mojo::Remote<network::mojom::AuthChallengeResponder>
      auth_challenge_responder_;
  net::AuthChallengeInfo auth_info_;
  const content::GlobalRequestID request_id_;
  bool is_request_for_primary_main_frame_;
  bool creating_login_delegate_;
  GURL url_;
  const scoped_refptr<net::HttpResponseHeaders> response_headers_;
  bool first_auth_attempt_;
  WebContents::Getter web_contents_getter_;
  std::unique_ptr<LoginDelegate> login_delegate_;
  base::WeakPtrFactory<LoginHandlerDelegate> weak_factory_{this};
};

void OnAuthRequiredContinuation(
    int32_t process_id,
    uint32_t request_id,
    const GURL& url,
    bool is_request_for_primary_main_frame,
    bool first_auth_attempt,
    const net::AuthChallengeInfo& auth_info,
    const scoped_refptr<net::HttpResponseHeaders>& head_headers,
    mojo::PendingRemote<network::mojom::AuthChallengeResponder>
        auth_challenge_responder,
    base::RepeatingCallback<WebContents*(void)> web_contents_getter) {
  if (!web_contents_getter || !web_contents_getter.Run()) {
    mojo::Remote<network::mojom::AuthChallengeResponder>
        auth_challenge_responder_remote(std::move(auth_challenge_responder));
    auth_challenge_responder_remote->OnAuthCredentials(absl::nullopt);
    return;
  }
  new LoginHandlerDelegate(
      std::move(auth_challenge_responder), std::move(web_contents_getter),
      auth_info, is_request_for_primary_main_frame, process_id, request_id, url,
      head_headers, first_auth_attempt);  // deletes self
}

// Returns true if the request is the primary main frame navigation.
bool IsPrimaryMainFrameRequest(
    const StoragePartitionImpl::URLLoaderNetworkContext& context) {
  if (!context.IsNavigationRequestContext()) {
    return false;
  }

  return context.navigation_or_document()->IsInPrimaryMainFrame();
}

// This class lives on the UI thread. It is self-owned and will delete itself
// after any of the SSLClientAuthHandler::Delegate methods are invoked (or when
// a mojo connection error occurs).
class SSLClientAuthDelegate : public SSLClientAuthHandler::Delegate {
 public:
  SSLClientAuthDelegate(
      mojo::PendingRemote<network::mojom::ClientCertificateResponder>
          client_cert_responder_remote,
      BrowserContext* browser_context,
      SSLClientAuthHandler::ContextGetter context_getter,
      const scoped_refptr<net::SSLCertRequestInfo>& cert_info)
      : client_cert_responder_(std::move(client_cert_responder_remote)),
        ssl_client_auth_handler_(std::make_unique<SSLClientAuthHandler>(
            GetContentClient()->browser()->CreateClientCertStore(
                browser_context),
            std::move(context_getter),
            std::move(cert_info.get()),
            this)) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    DCHECK(client_cert_responder_);
    client_cert_responder_.set_disconnect_handler(base::BindOnce(
        &SSLClientAuthDelegate::DeleteSelf, base::Unretained(this)));
    ssl_client_auth_handler_->SelectCertificate();
  }

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

  void DeleteSelf() { delete this; }

  // SSLClientAuthHandler::Delegate:
  void CancelCertificateSelection() override {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    client_cert_responder_->CancelRequest();
    DeleteSelf();
  }

  // SSLClientAuthHandler::Delegate:
  void ContinueWithCertificate(
      scoped_refptr<net::X509Certificate> cert,
      scoped_refptr<net::SSLPrivateKey> private_key) override {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    DCHECK((cert && private_key) || (!cert && !private_key));

    if (cert && private_key) {
      mojo::PendingRemote<network::mojom::SSLPrivateKey> ssl_private_key;

      mojo::MakeSelfOwnedReceiver(
          std::make_unique<SSLPrivateKeyImpl>(private_key),
          ssl_private_key.InitWithNewPipeAndPassReceiver());

      client_cert_responder_->ContinueWithCertificate(
          cert, private_key->GetProviderName(),
          private_key->GetAlgorithmPreferences(), std::move(ssl_private_key));
    } else {
      client_cert_responder_->ContinueWithoutCertificate();
    }

    DeleteSelf();
  }

 private:
  mojo::Remote<network::mojom::ClientCertificateResponder>
      client_cert_responder_;
  std::unique_ptr<SSLClientAuthHandler> ssl_client_auth_handler_;
};

void CallCancelRequest(
    mojo::PendingRemote<network::mojom::ClientCertificateResponder>
        client_cert_responder_remote) {
  DCHECK(client_cert_responder_remote);
  mojo::Remote<network::mojom::ClientCertificateResponder>
      client_cert_responder(std::move(client_cert_responder_remote));
  client_cert_responder->CancelRequest();
}

// Cancels prerendering if `navigation_or_document` is in a prerendered frame
// tree, using `final_status` as the cancellation reason. Returns true if
// cancelled.
bool CancelIfPrerendering(NavigationOrDocumentHandle* navigation_or_document,
                          PrerenderFinalStatus final_status) {
  FrameTreeNode* frame_tree_node = nullptr;
  // `navigation_or_document` can be null for `kServiceWorkerContext`.
  if (!navigation_or_document) {
    return false;
  }
  auto* navigation_request = navigation_or_document->GetNavigationRequest();
  if (navigation_request) {
    frame_tree_node = navigation_request->frame_tree_node();
  }
  auto* render_frame_host = navigation_or_document->GetDocument();
  if (render_frame_host) {
    frame_tree_node = FrameTreeNode::From(render_frame_host);
  }
  if (!frame_tree_node) {
    return false;
  }

  auto* web_contents = WebContentsImpl::FromFrameTreeNode(frame_tree_node);
  return web_contents->CancelPrerendering(frame_tree_node, final_status);
}

class SSLErrorDelegate : public SSLErrorHandler::Delegate {
 public:
  explicit SSLErrorDelegate(network::mojom::URLLoaderNetworkServiceObserver::
                                OnSSLCertificateErrorCallback response)
      : response_(std::move(response)) {}
  ~SSLErrorDelegate() override = default;
  void CancelSSLRequest(int error, const net::SSLInfo* ssl_info) override {
    std::move(response_).Run(error);
    delete this;
  }
  void ContinueSSLRequest() override {
    std::move(response_).Run(net::OK);
    delete this;
  }
  base::WeakPtr<SSLErrorDelegate> GetWeakPtr() {
    return weak_factory_.GetWeakPtr();
  }

 private:
  network::mojom::URLLoaderNetworkServiceObserver::OnSSLCertificateErrorCallback
      response_;
  base::WeakPtrFactory<SSLErrorDelegate> weak_factory_{this};
};

#if BUILDFLAG(IS_ANDROID)
void FinishGenerateNegotiateAuthToken(
    std::unique_ptr<net::android::HttpAuthNegotiateAndroid> auth_negotiate,
    std::unique_ptr<std::string> auth_token,
    std::unique_ptr<net::HttpAuthPreferences> prefs,
    network::mojom::NetworkContextClient::
        OnGenerateHttpNegotiateAuthTokenCallback callback,
    int result) {
  std::move(callback).Run(result, *auth_token);
}
#endif

// If both `storage_key_matcher` and `storage_key_policy_matcher` are null, this
// should return a null callback that indicates all StorageKeys should match.
// Otherwise, returns true if StorageKey matches both `storage_key_matcher` and
// `storage_key_policy_matcher` if not null.
StoragePartition::StorageKeyPolicyMatcherFunction
CombineStorageKeyMatcherFunctions(
    StoragePartition::StorageKeyMatcherFunction storage_key_matcher,
    StoragePartition::StorageKeyPolicyMatcherFunction
        storage_key_policy_matcher) {
  if (storage_key_matcher.is_null() && storage_key_policy_matcher.is_null()) {
    return base::NullCallback();
  }

  return base::BindRepeating(
      [](StoragePartition::StorageKeyMatcherFunction storage_key_matcher,
         StoragePartition::StorageKeyPolicyMatcherFunction
             storage_key_policy_matcher,
         const blink::StorageKey& storage_key,
         storage::SpecialStoragePolicy* policy) -> bool {
        return (!storage_key_matcher || storage_key_matcher.Run(storage_key)) &&
               (!storage_key_policy_matcher ||
                storage_key_policy_matcher.Run(storage_key, policy));
      },
      std::move(storage_key_matcher), std::move(storage_key_policy_matcher));
}

// Conceptually, many downstream interfaces don't need to know about the
// complexity of callers into StoragePartition, so this function reduces the API
// surface to something simple and generic. It is designed to be used by
// callsites in ClearDataImpl.
//
// Precondition: `storage_key_matcher`/`storage_key_policy_matcher` and
// `storage_key` cannot both be set. If all of `storage_key_matcher`,
// `storage_key_policy_matcher` and `storage_key` are null/empty, this should
// return a null callback that indicates all StorageKeys should match. This is
// an optimization for backends to efficiently clear all data.
//
// TODO(csharrison, mek): Right now, this is only used by a small set of storage
// backends, e.g. aggregation service. We should consider moving some of the
// backends to use this if they can, and additionally we should consider
// rethinking this approach if / when storage backends move out of process
// (see crbug.com/1016065 for initial work here).
StoragePartition::StorageKeyMatcherFunction CreateGenericStorageKeyMatcher(
    const blink::StorageKey& storage_key,
    StoragePartition::StorageKeyMatcherFunction storage_key_matcher,
    StoragePartition::StorageKeyPolicyMatcherFunction
        storage_key_policy_matcher,
    scoped_refptr<storage::SpecialStoragePolicy> policy) {
  const bool storage_key_origin_empty = storage_key.origin().opaque();
  DCHECK(storage_key_origin_empty || storage_key_matcher.is_null());
  DCHECK(storage_key_origin_empty || storage_key_policy_matcher.is_null());

  if (storage_key_origin_empty && storage_key_matcher.is_null() &&
      storage_key_policy_matcher.is_null()) {
    return base::NullCallback();
  }

  if (storage_key_matcher || storage_key_policy_matcher) {
    return base::BindRepeating(
        [](StoragePartition::StorageKeyPolicyMatcherFunction
               storage_key_policy_matcher,
           scoped_refptr<storage::SpecialStoragePolicy> policy,
           const blink::StorageKey& storage_key) -> bool {
          DCHECK(!storage_key_policy_matcher.is_null());
          return storage_key_policy_matcher.Run(storage_key, policy.get());
        },
        CombineStorageKeyMatcherFunctions(
            std::move(storage_key_matcher),
            std::move(storage_key_policy_matcher)),
        std::move(policy));
  }
  DCHECK(!storage_key_origin_empty);
  return base::BindRepeating(std::equal_to<const blink::StorageKey&>(),
                             storage_key);
}

}  // namespace

class StoragePartitionImpl::URLLoaderFactoryForBrowserProcess
    : public network::SharedURLLoaderFactory {
 public:
  explicit URLLoaderFactoryForBrowserProcess(
      StoragePartitionImpl* storage_partition)
      : storage_partition_(storage_partition) {}

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

  // mojom::URLLoaderFactory implementation:

  void CreateLoaderAndStart(
      mojo::PendingReceiver<network::mojom::URLLoader> receiver,
      int32_t request_id,
      uint32_t options,
      const network::ResourceRequest& url_request,
      mojo::PendingRemote<network::mojom::URLLoaderClient> client,
      const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
      override {
    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    if (!storage_partition_) {
      return;
    }
    storage_partition_->GetURLLoaderFactoryForBrowserProcessInternal()
        ->CreateLoaderAndStart(std::move(receiver), request_id, options,
                               url_request, std::move(client),
                               traffic_annotation);
  }

  void Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver)
      override {
    if (!storage_partition_) {
      return;
    }
    storage_partition_->GetURLLoaderFactoryForBrowserProcessInternal()->Clone(
        std::move(receiver));
  }

  // SharedURLLoaderFactory implementation:
  std::unique_ptr<network::PendingSharedURLLoaderFactory> Clone() override {
    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    return std::make_unique<network::CrossThreadPendingSharedURLLoaderFactory>(
        this);
  }

  void Shutdown() { storage_partition_ = nullptr; }

 private:
  friend class base::RefCounted<URLLoaderFactoryForBrowserProcess>;
  ~URLLoaderFactoryForBrowserProcess() override = default;

  raw_ptr<StoragePartitionImpl> storage_partition_;
};

// Static.
storage::QuotaClientTypes StoragePartitionImpl::GenerateQuotaClientTypes(
    uint32_t remove_mask) {
  storage::QuotaClientTypes quota_client_types;

  if (remove_mask & StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS) {
    quota_client_types.insert(storage::QuotaClientType::kFileSystem);
  }
  if (remove_mask & StoragePartition::REMOVE_DATA_MASK_WEBSQL) {
    quota_client_types.insert(storage::QuotaClientType::kDatabase);
  }
  if (remove_mask & StoragePartition::REMOVE_DATA_MASK_INDEXEDDB) {
    quota_client_types.insert(storage::QuotaClientType::kIndexedDatabase);
  }
  if (remove_mask & StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS) {
    quota_client_types.insert(storage::QuotaClientType::kServiceWorker);
  }
  if (remove_mask & StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE) {
    quota_client_types.insert(storage::QuotaClientType::kServiceWorkerCache);
  }
  if (remove_mask & StoragePartition::REMOVE_DATA_MASK_BACKGROUND_FETCH) {
    quota_client_types.insert(storage::QuotaClientType::kBackgroundFetch);
  }
  if (remove_mask & StoragePartition::REMOVE_DATA_MASK_MEDIA_LICENSES) {
    quota_client_types.insert(storage::QuotaClientType::kMediaLicense);
  }
  return quota_client_types;
}

// static
void StoragePartitionImpl::
    SetGetURLLoaderFactoryForBrowserProcessCallbackForTesting(
        CreateNetworkFactoryCallback url_loader_factory_callback) {
  DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
         BrowserThread::CurrentlyOn(BrowserThread::UI));
  DCHECK(!url_loader_factory_callback || !GetCreateURLLoaderFactoryCallback())
      << "It is not expected that this is called with non-null callback when "
      << "another overriding callback is already set.";
  GetCreateURLLoaderFactoryCallback() = std::move(url_loader_factory_callback);
}

// static
void StoragePartitionImpl::ForceInProcessStorageServiceForTesting() {
  g_force_in_process_storage_service = true;
}

// Helper for deleting quota managed data from a partition.
//
// Most of the operations in this class are done on IO thread.
class StoragePartitionImpl::QuotaManagedDataDeletionHelper {
 public:
  QuotaManagedDataDeletionHelper(
      uint32_t remove_mask,
      uint32_t quota_storage_remove_mask,
      const absl::optional<blink::StorageKey>& storage_key,
      base::OnceClosure callback)
      : remove_mask_(remove_mask),
        quota_storage_remove_mask_(quota_storage_remove_mask),
        storage_key_(storage_key),
        callback_(std::move(callback)),
        task_count_(0) {
    DCHECK(!storage_key_.has_value() || !storage_key_->origin().opaque());
  }

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

  void IncrementTaskCountOnIO();
  void DecrementTaskCountOnIO();

  void ClearDataOnIOThread(
      const scoped_refptr<storage::QuotaManager>& quota_manager,
      const base::Time begin,
      const base::Time end,
      const scoped_refptr<storage::SpecialStoragePolicy>&
          special_storage_policy,
      StoragePartition::StorageKeyPolicyMatcherFunction storage_key_matcher,
      bool perform_storage_cleanup);

  void ClearBucketsOnIOThread(
      storage::QuotaManager* quota_manager,
      const scoped_refptr<storage::SpecialStoragePolicy>&
          special_storage_policy,
      StoragePartition::StorageKeyPolicyMatcherFunction storage_key_matcher,
      bool perform_storage_cleanup,
      base::OnceClosure callback,
      blink::mojom::StorageType quota_storage_type,
      const std::set<storage::BucketLocator>& buckets);

 private:
  // All of these data are accessed on IO thread.
  uint32_t remove_mask_;
  uint32_t quota_storage_remove_mask_;
  absl::optional<blink::StorageKey> storage_key_;
  base::OnceClosure callback_;
  int task_count_;
};

// Helper for deleting all sorts of data from a partition, keeps track of
// deletion status.
//
// StoragePartitionImpl creates an instance of this class to keep track of
// data deletion progress. Deletion requires deleting multiple bits of data
// (e.g. cookies, local storage, session storage etc.) and hopping between UI
// and IO thread. An instance of this class is created in the beginning of
// deletion process (StoragePartitionImpl::ClearDataImpl) and the instance is
// forwarded and updated on each (sub) deletion's callback. The instance is
// finally destroyed when deletion completes (and `callback` is invoked).
class StoragePartitionImpl::DataDeletionHelper {
 public:
  DataDeletionHelper(uint32_t remove_mask,
                     uint32_t quota_storage_remove_mask,
                     base::OnceClosure callback)
      : remove_mask_(remove_mask),
        quota_storage_remove_mask_(quota_storage_remove_mask),
        callback_(std::move(callback)) {}

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

  ~DataDeletionHelper() = default;

  void ClearDataOnUIThread(
      const blink::StorageKey& storage_key,
      BrowsingDataFilterBuilder* filter_builder,
      StorageKeyPolicyMatcherFunction storage_key_policy_matcher,
      CookieDeletionFilterPtr cookie_deletion_filter,
      const base::FilePath& path,
      DOMStorageContextWrapper* dom_storage_context,
      storage::QuotaManager* quota_manager,
      storage::SpecialStoragePolicy* special_storage_policy,
      storage::FileSystemContext* filesystem_context,
      network::mojom::CookieManager* cookie_manager,
      InterestGroupManagerImpl* interest_group_manager,
      AttributionManager* attribution_manager,
      AggregationService* aggregation_service,
      PrivateAggregationManagerImpl* private_aggregation_manager,
      storage::SharedStorageManager* shared_storage_manager,
#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
      CdmStorageManager* cdm_storage_manager,
#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)
      bool perform_storage_cleanup,
      const base::Time begin,
      const base::Time end);

  void ClearQuotaManagedDataOnIOThread(
      const scoped_refptr<storage::QuotaManager>& quota_manager,
      const base::Time begin,
      const base::Time end,
      const blink::StorageKey& storage_key,
      const scoped_refptr<storage::SpecialStoragePolicy>&
          special_storage_policy,
      StoragePartition::StorageKeyPolicyMatcherFunction storage_key_matcher,
      bool perform_storage_cleanup,
      base::OnceClosure callback);

 private:
  // For debugging purposes. Please add new deletion tasks at the end.
  // This enum is recorded in a histogram, so don't change or reuse ids.
  // Entries must also be added to StoragePartitionRemoverTasks in enums.xml.
  enum class TracingDataType {
    kSynchronous = 1,
    kCookies = 2,
    kQuota = 3,
    kLocalStorage = 4,
    kSessionStorage = 5,
    kShaderCache = 6,    // Deprecated in favor of using kGpuCache.
    kPluginPrivate = 7,  // Deprecated.
    kConversions = 8,
    kAggregationService = 9,
    kSharedStorage = 10,
    kGpuCache = 11,
    kPrivateAggregation = 12,
    kInterestGroups = 13,
    kMaxValue = kInterestGroups,
  };

  base::OnceClosure CreateTaskCompletionClosure(TracingDataType data_type);

  void OnTaskComplete(TracingDataType data_type,
                      int tracing_id);  // Callable on any thread.
  void RecordUnfinishedSubTasks();

  uint32_t remove_mask_;
  uint32_t quota_storage_remove_mask_;

  // Accessed on UI thread.
  base::OnceClosure callback_;
  // Accessed on UI thread.
  std::set<TracingDataType> pending_tasks_;

  base::WeakPtrFactory<StoragePartitionImpl::DataDeletionHelper> weak_factory_{
      this};
};

void StoragePartitionImpl::DataDeletionHelper::ClearQuotaManagedDataOnIOThread(
    const scoped_refptr<storage::QuotaManager>& quota_manager,
    const base::Time begin,
    const base::Time end,
    const blink::StorageKey& storage_key,
    const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy,
    StoragePartition::StorageKeyPolicyMatcherFunction storage_key_matcher,
    bool perform_storage_cleanup,
    base::OnceClosure callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  StoragePartitionImpl::QuotaManagedDataDeletionHelper* helper =
      new StoragePartitionImpl::QuotaManagedDataDeletionHelper(
          remove_mask_, quota_storage_remove_mask_,
          storage_key.origin().opaque() ? absl::nullopt
                                        : absl::make_optional(storage_key),
          std::move(callback));
  helper->ClearDataOnIOThread(quota_manager, begin, end, special_storage_policy,
                              std::move(storage_key_matcher),
                              perform_storage_cleanup);
}

class StoragePartitionImpl::ServiceWorkerCookieAccessObserver
    : public network::mojom::CookieAccessObserver {
 public:
  explicit ServiceWorkerCookieAccessObserver(
      StoragePartitionImpl* storage_partition)
      : storage_partition_(storage_partition) {}

 private:
  void Clone(mojo::PendingReceiver<network::mojom::CookieAccessObserver>
                 observer) override {
    storage_partition_->service_worker_cookie_observers_.Add(
        std::make_unique<ServiceWorkerCookieAccessObserver>(storage_partition_),
        std::move(observer));
  }

  void OnCookiesAccessed(std::vector<network::mojom::CookieAccessDetailsPtr>
                             details_vector) override {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    for (auto& details : details_vector) {
      scoped_refptr<ServiceWorkerContextWrapper> service_worker_context =
          storage_partition_->GetServiceWorkerContext();
      std::vector<GlobalRenderFrameHostId> destinations =
          *service_worker_context->GetWindowClientFrameRoutingIds(
              blink::StorageKey::CreateFirstParty(
                  url::Origin::Create(details->url)));
      if (destinations.empty()) {
        return;
      }

      for (GlobalRenderFrameHostId frame_id : destinations) {
        if (RenderFrameHostImpl* rfh = RenderFrameHostImpl::FromID(frame_id)) {
          rfh->OnCookiesAccessed(mojo::Clone(details_vector));
        }
      }
    }
  }

  // `storage_partition_` owns this object via UniqueReceiverSet
  // (service_worker_cookie_observers_).
  raw_ptr<StoragePartitionImpl> storage_partition_;
};

class StoragePartitionImpl::ServiceWorkerTrustTokenAccessObserver
    : public network::mojom::TrustTokenAccessObserver {
 public:
  explicit ServiceWorkerTrustTokenAccessObserver(
      StoragePartitionImpl* storage_partition)
      : storage_partition_(storage_partition) {}

 private:
  void Clone(mojo::PendingReceiver<network::mojom::TrustTokenAccessObserver>
                 observer) override {
    storage_partition_->service_worker_trust_token_observers_.Add(
        std::make_unique<ServiceWorkerTrustTokenAccessObserver>(
            storage_partition_),
        std::move(observer));
  }

  void OnTrustTokensAccessed(
      network::mojom::TrustTokenAccessDetailsPtr details) override {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    scoped_refptr<ServiceWorkerContextWrapper> service_worker_context =
        storage_partition_->GetServiceWorkerContext();

    url::Origin origin;
    switch (details->which()) {
      case network::mojom::TrustTokenAccessDetails::Tag::kIssuance:
        origin = details->get_issuance()->origin;
        break;
      case network::mojom::TrustTokenAccessDetails::Tag::kRedemption:
        origin = details->get_redemption()->origin;
        break;
      case network::mojom::TrustTokenAccessDetails::Tag::kSigning:
        origin = details->get_signing()->origin;
        break;
    }

    std::vector<GlobalRenderFrameHostId> destinations =
        *service_worker_context->GetWindowClientFrameRoutingIds(
            blink::StorageKey::CreateFirstParty(origin));
    if (destinations.empty()) {
      return;
    }

    for (GlobalRenderFrameHostId frame_id : destinations) {
      if (RenderFrameHostImpl* rfh = RenderFrameHostImpl::FromID(frame_id)) {
        rfh->OnTrustTokensAccessed(mojo::Clone(details));
      }
    }
  }

  // `storage_partition_` owns this object via UniqueReceiverSet
  // (service_worker_trust_token_observers_).
  raw_ptr<StoragePartitionImpl> storage_partition_;
};

class StoragePartitionImpl::ServiceWorkerSharedDictionaryAccessObserver
    : public network::mojom::SharedDictionaryAccessObserver {
 public:
  explicit ServiceWorkerSharedDictionaryAccessObserver(
      StoragePartitionImpl* storage_partition)
      : storage_partition_(storage_partition) {}

 private:
  void Clone(
      mojo::PendingReceiver<network::mojom::SharedDictionaryAccessObserver>
          observer) override {
    storage_partition_->service_worker_shared_dictionary_observers_.Add(
        std::make_unique<ServiceWorkerSharedDictionaryAccessObserver>(
            storage_partition_),
        std::move(observer));
  }

  void OnSharedDictionaryAccessed(
      network::mojom::SharedDictionaryAccessDetailsPtr details) override {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    scoped_refptr<ServiceWorkerContextWrapper> service_worker_context =
        storage_partition_->GetServiceWorkerContext();

    std::vector<GlobalRenderFrameHostId> destinations =
        *service_worker_context->GetWindowClientFrameRoutingIds(
            blink::StorageKey::CreateFirstParty(
                details->isolation_key.frame_origin()));
    if (destinations.empty()) {
      return;
    }

    for (GlobalRenderFrameHostId frame_id : destinations) {
      if (RenderFrameHostImpl* rfh = RenderFrameHostImpl::FromID(frame_id)) {
        rfh->OnSharedDictionaryAccessed(mojo::Clone(details));
      }
    }
  }

  // `storage_partition_` owns this object via UniqueReceiverSet
  // (service_worker_shared_dictionary_observers_).
  raw_ptr<StoragePartitionImpl> storage_partition_;
};

StoragePartitionImpl::StoragePartitionImpl(
    BrowserContext* browser_context,
    const StoragePartitionConfig& config,
    const base::FilePath& partition_path,
    const base::FilePath& relative_partition_path,
    storage::SpecialStoragePolicy* special_storage_policy)
    : browser_context_(browser_context),
      partition_path_(partition_path),
      config_(config),
      relative_partition_path_(relative_partition_path),
      special_storage_policy_(special_storage_policy),
      deletion_helpers_running_(0) {}

StoragePartitionImpl::~StoragePartitionImpl() {
#if DCHECK_IS_ON()
  DCHECK(on_browser_context_will_be_destroyed_called_);
#endif
  browser_context_ = nullptr;

  if (url_loader_factory_getter_) {
    url_loader_factory_getter_->OnStoragePartitionDestroyed();
  }

  if (shared_url_loader_factory_for_browser_process_) {
    shared_url_loader_factory_for_browser_process_->Shutdown();
  }

  scoped_refptr<storage::DatabaseTracker> database_tracker(
      GetDatabaseTracker());
  if (database_tracker) {
    storage::DatabaseTracker* database_tracker_ptr = database_tracker.get();
    database_tracker_ptr->task_runner()->PostTask(
        FROM_HERE, base::BindOnce(&storage::DatabaseTracker::Shutdown,
                                  std::move(database_tracker)));
  }

  if (GetFileSystemContext()) {
    GetFileSystemContext()->Shutdown();
  }

  if (GetDOMStorageContext()) {
    GetDOMStorageContext()->Shutdown();
  }

  if (GetServiceWorkerContext()) {
    GetServiceWorkerContext()->Shutdown();
  }

  if (GetPlatformNotificationContext()) {
    GetPlatformNotificationContext()->Shutdown();
  }

  if (GetBackgroundSyncContext()) {
    GetBackgroundSyncContext()->Shutdown();
  }

  if (GetBackgroundFetchContext()) {
    GetBackgroundFetchContext()->Shutdown();
  }

  if (GetGeneratedCodeCacheContext()) {
    GetGeneratedCodeCacheContext()->Shutdown();
  }
}

void StoragePartitionImpl::OnBrowserContextWillBeDestroyed() {
#if DCHECK_IS_ON()
  on_browser_context_will_be_destroyed_called_ = true;
#endif
  // These hold raw pointers to objects that are about to be destroyed, before
  // this object is destroyed. Shut them down now to avoid dangling pointers.
  if (GetFileSystemAccessManager()) {
    GetFileSystemAccessManager()->Shutdown();
  }

  if (GetContentIndexContext()) {
    GetContentIndexContext()->Shutdown();
  }
}

// static
std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
    BrowserContext* context,
    const StoragePartitionConfig& config,
    const base::FilePath& relative_partition_path) {
  // Ensure that these methods are called on the UI thread, except for
  // unittests where a UI thread might not have been created.
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
         !BrowserThread::IsThreadInitialized(BrowserThread::UI));

  base::FilePath partition_path =
      context->GetPath().Append(relative_partition_path);

  return base::WrapUnique(new StoragePartitionImpl(
      context, config, partition_path, relative_partition_path,
      context->GetSpecialStoragePolicy()));
}

void StoragePartitionImpl::Initialize(
    StoragePartitionImpl* fallback_for_blob_urls) {
  // Ensure that these methods are called on the UI thread, except for
  // unittests where a UI thread might not have been created.
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
         !BrowserThread::IsThreadInitialized(BrowserThread::UI));
  DCHECK(!initialized_);
  initialized_ = true;

  // All of the clients have to be created and registered with the
  // QuotaManager prior to the QuotaManager being used. We do them
  // all together here prior to handing out a reference to anything
  // that utilizes the QuotaManager.
  quota_context_ = base::MakeRefCounted<QuotaContext>(
      is_in_memory(), partition_path_,
      browser_context_->GetSpecialStoragePolicy(),
      base::BindRepeating(&StoragePartitionImpl::GetQuotaSettings,
                          weak_factory_.GetWeakPtr()));
  quota_manager_ = quota_context_->quota_manager();
  scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy =
      quota_manager_->proxy();

  StorageNotificationService* storage_notification_service =
      browser_context_->GetStorageNotificationService();
  if (storage_notification_service) {
    // The weak ptr associated with the pressure notification callback will be
    // created and evaluated by a task runner on the UI thread, as confirmed by
    // the DCHECK's above, ensuring that the task runner does not attempt to run
    // the callback in the case that the storage notification service is already
    // destructed.
    quota_manager_->SetStoragePressureCallback(
        storage_notification_service
            ->CreateThreadSafePressureNotificationCallback());
  }

  // Each consumer is responsible for registering its QuotaClient during
  // its construction.
  filesystem_context_ = CreateFileSystemContext(
      browser_context_, partition_path_, is_in_memory(), quota_manager_proxy);

  database_tracker_ = storage::DatabaseTracker::Create(
      partition_path_, is_in_memory(),
      browser_context_->GetSpecialStoragePolicy(), quota_manager_proxy);

  dom_storage_context_ = DOMStorageContextWrapper::Create(
      this, browser_context_->GetSpecialStoragePolicy());

  lock_manager_ = std::make_unique<LockManager>();

  shared_storage_worklet_host_manager_ =
      std::make_unique<SharedStorageWorkletHostManager>();

  scoped_refptr<ChromeBlobStorageContext> blob_context =
      ChromeBlobStorageContext::GetFor(browser_context_);

  file_system_access_manager_ =
      base::MakeRefCounted<FileSystemAccessManagerImpl>(
          filesystem_context_, blob_context,
          browser_context_->GetFileSystemAccessPermissionContext(),
          browser_context_->IsOffTheRecord());

  mojo::PendingRemote<storage::mojom::FileSystemAccessContext>
      file_system_access_context;
  file_system_access_manager_->BindInternalsReceiver(
      file_system_access_context.InitWithNewPipeAndPassReceiver());
  base::FilePath path = is_in_memory() ? base::FilePath() : partition_path_;
  indexed_db_control_wrapper_ = std::make_unique<IndexedDBControlWrapper>(
      path, browser_context_->GetSpecialStoragePolicy(), quota_manager_proxy,
      base::DefaultClock::GetInstance(),
      ChromeBlobStorageContext::GetRemoteFor(browser_context_),
      std::move(file_system_access_context), GetIOThreadTaskRunner({}),
      /*task_runner=*/nullptr);

  cache_storage_control_wrapper_ = std::make_unique<CacheStorageControlWrapper>(
      GetIOThreadTaskRunner({}), path,
      browser_context_->GetSpecialStoragePolicy(), quota_manager_proxy,
      ChromeBlobStorageContext::GetRemoteFor(browser_context_));

  service_worker_context_ = new ServiceWorkerContextWrapper(browser_context_);
  service_worker_context_->set_storage_partition(this);

  dedicated_worker_service_ = std::make_unique<DedicatedWorkerServiceImpl>();

  shared_worker_service_ =
      std::make_unique<SharedWorkerServiceImpl>(this, service_worker_context_);

  push_messaging_context_ = std::make_unique<PushMessagingContext>(
      browser_context_, service_worker_context_);

  host_zoom_level_context_.reset(new HostZoomLevelContext(
      browser_context_->CreateZoomLevelDelegate(partition_path_)));

  platform_notification_context_ = new PlatformNotificationContextImpl(
      path, browser_context_, service_worker_context_);
  platform_notification_context_->Initialize();

  devtools_background_services_context_ =
      std::make_unique<DevToolsBackgroundServicesContextImpl>(
          browser_context_, service_worker_context_);

  content_index_context_ = base::MakeRefCounted<ContentIndexContextImpl>(
      browser_context_, service_worker_context_);

  background_fetch_context_ = base::MakeRefCounted<BackgroundFetchContext>(
      weak_factory_.GetWeakPtr(), service_worker_context_, quota_manager_proxy,
      *devtools_background_services_context_.get());

  background_sync_context_ = base::MakeRefCounted<BackgroundSyncContextImpl>();
  background_sync_context_->Init(service_worker_context_,
                                 *devtools_background_services_context_.get());

  payment_app_context_ = new PaymentAppContextImpl();
  payment_app_context_->Init(service_worker_context_);

  broadcast_channel_service_ = std::make_unique<BroadcastChannelService>();

  bluetooth_allowed_devices_map_ =
      std::make_unique<BluetoothAllowedDevicesMap>();

  // Must be initialized before the `url_loader_factory_getter_`.
  // Cookie deprecation traffic labels should not be sent for off-the-record
  // profiles, unless the "enable_otr_profiles" feature parameter is true.
  if (base::FeatureList::IsEnabled(
          features::kCookieDeprecationFacilitatedTesting) &&
      (!is_in_memory() ||
       features::kCookieDeprecationFacilitatedTestingEnableOTRProfiles.Get())) {
    cookie_deprecation_label_manager_ =
        std::make_unique<CookieDeprecationLabelManagerImpl>(browser_context_);
  }

  url_loader_factory_getter_ = new URLLoaderFactoryGetter();
  url_loader_factory_getter_->Initialize(this);

  service_worker_context_->Init(path, quota_manager_proxy.get(),
                                browser_context_->GetSpecialStoragePolicy(),
                                blob_context.get());

  blob_url_registry_ = std::make_unique<storage::BlobUrlRegistry>(
      fallback_for_blob_urls
          ? fallback_for_blob_urls->GetBlobUrlRegistry()->AsWeakPtr()
          : nullptr);

  if (base::FeatureList::IsEnabled(net::features::kSupportPartitionedBlobUrl)) {
    blob_registry_ = BlobRegistryWrapper::Create(blob_context);

  } else {
    blob_registry_ = BlobRegistryWrapper::Create(
        blob_context, blob_url_registry_->AsWeakPtr());
  }

  subresource_proxying_url_loader_service_ =
      std::make_unique<SubresourceProxyingURLLoaderService>(browser_context_);

  if (blink::features::IsKeepAliveURLLoaderServiceEnabled()) {
    keep_alive_url_loader_service_ =
        std::make_unique<KeepAliveURLLoaderService>(browser_context_);
  }

  cookie_store_manager_ =
      std::make_unique<CookieStoreManager>(service_worker_context_);
  // Unit tests use the LoadAllSubscriptions() callback to crash early if
  // restoring the CookieManagerStore's state from ServiceWorkerStorage fails.
  // Production and browser tests rely on CookieStoreManager's well-defined
  // behavior when restoring the state fails.
  cookie_store_manager_->LoadAllSubscriptions(base::DoNothing());

  bucket_manager_ = std::make_unique<BucketManager>(this);

  if (base::FeatureList::IsEnabled(
          attribution_reporting::features::kConversionMeasurement)) {
    // The Conversion Measurement API is not available in Incognito mode, but
    // this is enforced by the `AttributionManagerImpl` itself for better error
    // reporting and metrics.
    attribution_manager_ = std::make_unique<AttributionManagerImpl>(
        this, path, special_storage_policy_);
  }

  if (base::FeatureList::IsEnabled(blink::features::kInterestGroupStorage)) {
    // Auction worklets on non-Android use dedicated processes; on Android due
    // to high cost of process launch they try to reuse renderers.
    interest_group_manager_ = std::make_unique<InterestGroupManagerImpl>(
        path, is_in_memory(),
#if BUILDFLAG(IS_ANDROID)
        InterestGroupManagerImpl::ProcessMode::kInRenderer,
#else
        InterestGroupManagerImpl::ProcessMode::kDedicated,
#endif
        GetURLLoaderFactoryForBrowserProcess(),
        browser_context_->GetKAnonymityServiceDelegate());
  }

  // The Topics API is not available in Incognito mode.
  if (!is_in_memory() &&
      base::FeatureList::IsEnabled(blink::features::kBrowsingTopics)) {
    browsing_topics_site_data_manager_ =
        std::make_unique<BrowsingTopicsSiteDataManagerImpl>(path);
  }

  GeneratedCodeCacheSettings settings =
      GetContentClient()->browser()->GetGeneratedCodeCacheSettings(
          browser_context_);

  // For Incognito mode, we should not persist anything on the disk so
  // we do not create a code cache. Caching the generated code in memory
  // is not useful, since V8 already maintains one copy in memory.
  if (!is_in_memory() && settings.enabled()) {
    generated_code_cache_context_ =
        base::MakeRefCounted<GeneratedCodeCacheContext>();

    base::FilePath code_cache_path;
    if (config_.partition_domain().empty()) {
      code_cache_path = settings.path().AppendASCII("Code Cache");
    } else {
      // For site isolated partitions use the config directory.
      code_cache_path = settings.path()
                            .Append(relative_partition_path_)
                            .AppendASCII("Code Cache");
    }
    DCHECK_GE(settings.size_in_bytes(), 0);
    GetGeneratedCodeCacheContext()->Initialize(code_cache_path,
                                               settings.size_in_bytes());
  }

  font_access_manager_ = FontAccessManager::Create();

  if (base::FeatureList::IsEnabled(kPrivacySandboxAggregationService)) {
    aggregation_service_ =
        std::make_unique<AggregationServiceImpl>(is_in_memory(), path, this);
  }

#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
  if (base::FeatureList::IsEnabled(features::kCdmStorageDatabase)) {
    if (is_in_memory()) {
      // Pass an empty path if in_memory so that CdmStorage.db is not stored on
      // disk.
      cdm_storage_manager_ =
          std::make_unique<CdmStorageManager>(base::FilePath());
    } else {
      cdm_storage_manager_ = std::make_unique<CdmStorageManager>(
          partition_path_.Append(kCdmStorageDatabaseFileName));
    }
  }

  media_license_manager_ = std::make_unique<MediaLicenseManager>(
      is_in_memory(), browser_context_->GetSpecialStoragePolicy(),
      quota_manager_proxy);

  // When 'kCdmStorageDatabaseMigration' is enabled, in the
  // 'MediaLicenseStorageHost', when operations occur, we make sure to
  // update and reflect that in the CdmStorageDatabase as well.
  if (base::FeatureList::IsEnabled(features::kCdmStorageDatabase) &&
      base::FeatureList::IsEnabled(features::kCdmStorageDatabaseMigration)) {
    CHECK(cdm_storage_manager_);
    media_license_manager_->set_cdm_storage_manager(cdm_storage_manager_.get());
  }
#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)

  if (base::FeatureList::IsEnabled(blink::features::kSharedStorageAPI)) {
    base::FilePath shared_storage_path =
        is_in_memory() ? base::FilePath()
                       : path.Append(storage::kSharedStoragePath);
    shared_storage_manager_ = std::make_unique<storage::SharedStorageManager>(
        shared_storage_path, special_storage_policy_);
    if (base::FeatureList::IsEnabled(blink::features::kSharedStorageAPIM118)) {
      shared_storage_header_observer_ =
          std::make_unique<SharedStorageHeaderObserver>(this);
    }
  }

  if (base::FeatureList::IsEnabled(blink::features::kPrivateAggregationApi)) {
    private_aggregation_manager_ =
        std::make_unique<PrivateAggregationManagerImpl>(is_in_memory(), path,
                                                        this);
  }

  if (base::FeatureList::IsEnabled(blink::features::kRemoteResourceCache)) {
    resource_cache_manager_ = std::make_unique<ResourceCacheManager>();
  }
}

void StoragePartitionImpl::OnStorageServiceDisconnected() {
  // This will be lazily re-bound on next use.
  remote_partition_.reset();

  dom_storage_context_->RecoverFromStorageServiceCrash();
  for (const auto& client : dom_storage_clients_) {
    client.second->ResetStorageAreaAndNamespaceConnections();
  }
}

const StoragePartitionConfig& StoragePartitionImpl::GetConfig() {
  return config_;
}

base::FilePath StoragePartitionImpl::GetPath() {
  return partition_path_;
}

std::string StoragePartitionImpl::GetPartitionDomain() {
  return config_.partition_domain();
}

network::mojom::NetworkContext* StoragePartitionImpl::GetNetworkContext() {
  DCHECK(initialized_);
  if (!network_context_.is_bound()) {
    InitNetworkContext();
  }
  return network_context_.get();
}

scoped_refptr<network::SharedURLLoaderFactory>
StoragePartitionImpl::GetURLLoaderFactoryForBrowserProcess() {
  DCHECK(initialized_);
  if (!shared_url_loader_factory_for_browser_process_) {
    shared_url_loader_factory_for_browser_process_ =
        new URLLoaderFactoryForBrowserProcess(this);
  }
  return shared_url_loader_factory_for_browser_process_;
}

std::unique_ptr<network::PendingSharedURLLoaderFactory>
StoragePartitionImpl::GetURLLoaderFactoryForBrowserProcessIOThread() {
  DCHECK(initialized_);
  return url_loader_factory_getter_->GetPendingNetworkFactory();
}

network::mojom::CookieManager*
StoragePartitionImpl::GetCookieManagerForBrowserProcess() {
  DCHECK(initialized_);
  // Create the CookieManager as needed.
  if (!cookie_manager_for_browser_process_ ||
      !cookie_manager_for_browser_process_.is_connected()) {
    // Reset `cookie_manager_for_browser_process_` before binding it again.
    cookie_manager_for_browser_process_.reset();
    GetNetworkContext()->GetCookieManager(
        cookie_manager_for_browser_process_.BindNewPipeAndPassReceiver());
  }
  return cookie_manager_for_browser_process_.get();
}

void StoragePartitionImpl::CreateRestrictedCookieManager(
    network::mojom::RestrictedCookieManagerRole role,
    const url::Origin& origin,
    const net::IsolationInfo& isolation_info,
    bool is_service_worker,
    int process_id,
    int routing_id,
    net::CookieSettingOverrides cookie_setting_overrides,
    mojo::PendingReceiver<network::mojom::RestrictedCookieManager> receiver,
    mojo::PendingRemote<network::mojom::CookieAccessObserver> cookie_observer) {
  DCHECK(initialized_);
  if (!GetContentClient()->browser()->WillCreateRestrictedCookieManager(
          role, browser_context_, origin, isolation_info, is_service_worker,
          process_id, routing_id, &receiver)) {
    GetNetworkContext()->GetRestrictedCookieManager(
        std::move(receiver), role, origin, isolation_info,
        cookie_setting_overrides, std::move(cookie_observer));
  }
}

void StoragePartitionImpl::CreateTrustTokenQueryAnswerer(
    mojo::PendingReceiver<network::mojom::TrustTokenQueryAnswerer> receiver,
    const url::Origin& top_frame_origin) {
  DCHECK(initialized_);
  GetNetworkContext()->GetTrustTokenQueryAnswerer(std::move(receiver),
                                                  top_frame_origin);
}

storage::QuotaManager* StoragePartitionImpl::GetQuotaManager() {
  DCHECK(initialized_);
  return quota_manager_.get();
}

storage::QuotaManagerProxy* StoragePartitionImpl::GetQuotaManagerProxy() {
  DCHECK(initialized_);
  return quota_manager_->proxy();
}

BackgroundSyncContextImpl* StoragePartitionImpl::GetBackgroundSyncContext() {
  DCHECK(initialized_);
  return background_sync_context_.get();
}

storage::FileSystemContext* StoragePartitionImpl::GetFileSystemContext() {
  DCHECK(initialized_);
  return filesystem_context_.get();
}

storage::DatabaseTracker* StoragePartitionImpl::GetDatabaseTracker() {
  DCHECK(initialized_);
  return database_tracker_.get();
}

DOMStorageContextWrapper* StoragePartitionImpl::GetDOMStorageContext() {
  DCHECK(initialized_);
  return dom_storage_context_.get();
}

storage::mojom::LocalStorageControl*
StoragePartitionImpl::GetLocalStorageControl() {
  DCHECK(initialized_);
  return GetDOMStorageContext()->GetLocalStorageControl();
}

LockManager* StoragePartitionImpl::GetLockManager() {
  DCHECK(initialized_);
  return lock_manager_.get();
}

SharedStorageWorkletHostManager*
StoragePartitionImpl::GetSharedStorageWorkletHostManager() {
  DCHECK(initialized_);
  return shared_storage_worklet_host_manager_.get();
}

storage::mojom::IndexedDBControl& StoragePartitionImpl::GetIndexedDBControl() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  return *indexed_db_control_wrapper_.get();
}

FileSystemAccessEntryFactory*
StoragePartitionImpl::GetFileSystemAccessEntryFactory() {
  DCHECK(initialized_);
  return file_system_access_manager_.get();
}

QuotaContext* StoragePartitionImpl::GetQuotaContext() {
  DCHECK(initialized_);
  return quota_context_.get();
}

storage::mojom::CacheStorageControl*
StoragePartitionImpl::GetCacheStorageControl() {
  DCHECK(initialized_);
  return cache_storage_control_wrapper_.get();
}

ServiceWorkerContextWrapper* StoragePartitionImpl::GetServiceWorkerContext() {
  DCHECK(initialized_);
  return service_worker_context_.get();
}

DedicatedWorkerServiceImpl* StoragePartitionImpl::GetDedicatedWorkerService() {
  DCHECK(initialized_);
  return dedicated_worker_service_.get();
}

SharedWorkerService* StoragePartitionImpl::GetSharedWorkerService() {
  DCHECK(initialized_);
  return shared_worker_service_.get();
}

HostZoomMap* StoragePartitionImpl::GetHostZoomMap() {
  DCHECK(initialized_);
  DCHECK(host_zoom_level_context_.get());
  return host_zoom_level_context_->GetHostZoomMap();
}

HostZoomLevelContext* StoragePartitionImpl::GetHostZoomLevelContext() {
  DCHECK(initialized_);
  return host_zoom_level_context_.get();
}

ZoomLevelDelegate* StoragePartitionImpl::GetZoomLevelDelegate() {
  DCHECK(initialized_);
  DCHECK(host_zoom_level_context_.get());
  return host_zoom_level_context_->GetZoomLevelDelegate();
}

PlatformNotificationContextImpl*
StoragePartitionImpl::GetPlatformNotificationContext() {
  DCHECK(initialized_);
  return platform_notification_context_.get();
}

BackgroundFetchContext* StoragePartitionImpl::GetBackgroundFetchContext() {
  DCHECK(initialized_);
  return background_fetch_context_.get();
}

PaymentAppContextImpl* StoragePartitionImpl::GetPaymentAppContext() {
  DCHECK(initialized_);
  return payment_app_context_.get();
}

BroadcastChannelService* StoragePartitionImpl::GetBroadcastChannelService() {
  DCHECK(initialized_);
  return broadcast_channel_service_.get();
}

BluetoothAllowedDevicesMap*
StoragePartitionImpl::GetBluetoothAllowedDevicesMap() {
  DCHECK(initialized_);
  return bluetooth_allowed_devices_map_.get();
}

BlobRegistryWrapper* StoragePartitionImpl::GetBlobRegistry() {
  DCHECK(initialized_);
  return blob_registry_.get();
}

storage::BlobUrlRegistry* StoragePartitionImpl::GetBlobUrlRegistry() {
  DCHECK(initialized_);
  return blob_url_registry_.get();
}

SubresourceProxyingURLLoaderService*
StoragePartitionImpl::GetSubresourceProxyingURLLoaderService() {
  DCHECK(initialized_);
  return subresource_proxying_url_loader_service_.get();
}

KeepAliveURLLoaderService*
StoragePartitionImpl::GetKeepAliveURLLoaderService() {
  DCHECK(initialized_);
  return keep_alive_url_loader_service_.get();
}

CookieStoreManager* StoragePartitionImpl::GetCookieStoreManager() {
  DCHECK(initialized_);
  return cookie_store_manager_.get();
}

BucketManager* StoragePartitionImpl::GetBucketManager() {
  DCHECK(initialized_);
  return bucket_manager_.get();
}

GeneratedCodeCacheContext*
StoragePartitionImpl::GetGeneratedCodeCacheContext() {
  DCHECK(initialized_);
  return generated_code_cache_context_.get();
}

DevToolsBackgroundServicesContext*
StoragePartitionImpl::GetDevToolsBackgroundServicesContext() {
  DCHECK(initialized_);
  return devtools_background_services_context_.get();
}

FileSystemAccessManagerImpl*
StoragePartitionImpl::GetFileSystemAccessManager() {
  DCHECK(initialized_);
  return file_system_access_manager_.get();
}

AttributionManager* StoragePartitionImpl::GetAttributionManager() {
  DCHECK(initialized_);
  return attribution_manager_.get();
}

AttributionDataModel* StoragePartitionImpl::GetAttributionDataModel() {
  DCHECK(initialized_);
  return attribution_manager_.get();
}

FontAccessManager* StoragePartitionImpl::GetFontAccessManager() {
  DCHECK(initialized_);
  return font_access_manager_.get();
}

void StoragePartitionImpl::SetFontAccessManagerForTesting(
    std::unique_ptr<FontAccessManager> font_access_manager) {
  DCHECK(initialized_);
  DCHECK(font_access_manager);
  font_access_manager_ = std::move(font_access_manager);
}

#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
MediaLicenseManager* StoragePartitionImpl::GetMediaLicenseManager() {
  DCHECK(initialized_);
  return media_license_manager_.get();
}

CdmStorageManager* StoragePartitionImpl::GetCdmStorageManager() {
    return cdm_storage_manager_.get();
}
#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)

InterestGroupManager* StoragePartitionImpl::GetInterestGroupManager() {
  DCHECK(initialized_);
  return interest_group_manager_.get();
}

BrowsingTopicsSiteDataManager*
StoragePartitionImpl::GetBrowsingTopicsSiteDataManager() {
  DCHECK(initialized_);
  return browsing_topics_site_data_manager_.get();
}

ContentIndexContextImpl* StoragePartitionImpl::GetContentIndexContext() {
  DCHECK(initialized_);
  return content_index_context_.get();
}

AggregationService* StoragePartitionImpl::GetAggregationService() {
  DCHECK(initialized_);
  return aggregation_service_.get();
}

leveldb_proto::ProtoDatabaseProvider*
StoragePartitionImpl::GetProtoDatabaseProvider() {
  if (!proto_database_provider_) {
    proto_database_provider_ =
        std::make_unique<leveldb_proto::ProtoDatabaseProvider>(partition_path_,
                                                               is_in_memory());
  }
  return proto_database_provider_.get();
}

void StoragePartitionImpl::SetProtoDatabaseProvider(
    std::unique_ptr<leveldb_proto::ProtoDatabaseProvider> proto_db_provider) {
  DCHECK(!proto_database_provider_);
  proto_database_provider_ = std::move(proto_db_provider);
}

leveldb_proto::ProtoDatabaseProvider*
StoragePartitionImpl::GetProtoDatabaseProviderForTesting() {
  return proto_database_provider_.get();
}

storage::SharedStorageManager* StoragePartitionImpl::GetSharedStorageManager() {
  return shared_storage_manager_.get();
}

PrivateAggregationManager*
StoragePartitionImpl::GetPrivateAggregationManager() {
  DCHECK(initialized_);
  return private_aggregation_manager_.get();
}

PrivateAggregationDataModel*
StoragePartitionImpl::GetPrivateAggregationDataModel() {
  DCHECK(initialized_);
  return private_aggregation_manager_.get();
}

ResourceCacheManager* StoragePartitionImpl::GetResourceCacheManager() {
  CHECK(initialized_);
  return resource_cache_manager_.get();
}

CookieDeprecationLabelManager*
StoragePartitionImpl::GetCookieDeprecationLabelManager() {
  CHECK(initialized_);
  return cookie_deprecation_label_manager_.get();
}

void StoragePartitionImpl::OpenLocalStorage(
    const blink::StorageKey& storage_key,
    const blink::LocalFrameToken& local_frame_token,
    mojo::PendingReceiver<blink::mojom::StorageArea> receiver) {
  DCHECK(initialized_);
  ChildProcessSecurityPolicyImpl::Handle security_policy_handle =
      dom_storage_receivers_.current_context()->Duplicate();
  dom_storage_context_->OpenLocalStorage(
      storage_key, local_frame_token, std::move(receiver),
      std::move(security_policy_handle),
      dom_storage_receivers_.GetBadMessageCallback());
}

void StoragePartitionImpl::BindSessionStorageNamespace(
    const std::string& namespace_id,
    mojo::PendingReceiver<blink::mojom::SessionStorageNamespace> receiver) {
  DCHECK(initialized_);
  dom_storage_context_->BindNamespace(
      namespace_id, dom_storage_receivers_.GetBadMessageCallback(),
      std::move(receiver));
}

void StoragePartitionImpl::BindSessionStorageArea(
    const blink::StorageKey& storage_key,
    const blink::LocalFrameToken& local_frame_token,
    const std::string& namespace_id,
    mojo::PendingReceiver<blink::mojom::StorageArea> receiver) {
  DCHECK(initialized_);
  ChildProcessSecurityPolicyImpl::Handle security_policy_handle =
      dom_storage_receivers_.current_context()->Duplicate();
  dom_storage_context_->BindStorageArea(
      storage_key, local_frame_token, namespace_id, std::move(receiver),
      std::move(security_policy_handle),
      dom_storage_receivers_.GetBadMessageCallback());
}

void StoragePartitionImpl::OnAuthRequired(
    const absl::optional<base::UnguessableToken>& window_id,
    uint32_t request_id,
    const GURL& url,
    bool first_auth_attempt,
    const net::AuthChallengeInfo& auth_info,
    const scoped_refptr<net::HttpResponseHeaders>& head_headers,
    mojo::PendingRemote<network::mojom::AuthChallengeResponder>
        auth_challenge_responder) {
  URLLoaderNetworkContext context =
      url_loader_network_observers_.current_context();
  absl::optional<bool> is_primary_main_frame;

  if (window_id) {
    // Use `window_id` if it is provided, because this request was sent by a
    // service worker; service workers use `window_id` to identify the frame
    // that sends the request since a worker is shared among multiple frames.
    // TODO(https://crbug.com/1240483): Add a DCHECK here that process_id and
    // routing_id are invalid. It can't be added yet because somehow routing_id
    // is valid here.
    if (service_worker_context_->context()) {
      auto* container_host =
          service_worker_context_->context()->GetContainerHostByWindowId(
              *window_id);
      if (container_host) {
        if (container_host->GetRenderFrameHostId()) {
          // Use ServiceWorkerContainerHost's GlobalRenderFrameHostId when
          // the navigation commit has already started.
          GlobalRenderFrameHostId render_frame_host_id =
              container_host->GetRenderFrameHostId();
          context = URLLoaderNetworkContext::CreateForRenderFrameHost(
              render_frame_host_id);

          // TODO(crbug.com/963748, crbug.com/1251596): `is_primary_main_frame`
          // should be false because only the request for a sub resource
          // intercepted by a service worker reaches here.
          auto* render_frame_host_impl =
              RenderFrameHostImpl::FromID(render_frame_host_id);
          if (render_frame_host_impl) {
            is_primary_main_frame =
                render_frame_host_impl->IsInPrimaryMainFrame();
          }
        } else if (NavigationRequest* ongoing_navigation =
                       container_host->GetOngoingNavigationRequestBeforeCommit(
                           base::PassKey<StoragePartitionImpl>())) {
          // This auth request is for an ongoing navigation controlled
          // by service worker. The navigation request can be nullptr if user
          // has closed the WebContents.
          // Overwrite the context; set `type` to kNavigationRequestContext.
          // TODO(https://crbug.com/1239554): Optimize locating logic.
          context =
              URLLoaderNetworkContext::CreateForNavigation(*ongoing_navigation);
        }
      }
    }
  }

  // If the request is for a prerendering page, prerendering should be cancelled
  // because the embedder may show UI for auth requests, and it's unsuitable for
  // a hidden page.
  if (CancelIfPrerendering(context.navigation_or_document(),
                           PrerenderFinalStatus::kLoginAuthRequested)) {
    return;
  }

  if (!is_primary_main_frame.has_value()) {
    is_primary_main_frame = IsPrimaryMainFrameRequest(context);
  }
  auto web_contents_getter = base::BindRepeating(GetWebContents, context);
  int process_id = network::mojom::kBrowserProcessId;
  if (context.type() ==
      URLLoaderNetworkContext::Type::kRenderFrameHostContext) {
    // Set `process_id` to `kInvalidProcessId` considering `render_frame_host`
    // can be null when it's destroyed already. `process_id` is updated only if
    // `render_frame_host` is not null. If `render_frame_host` is null,
    // OnAuthRequiredContinuation() fails to get the web contents and calls
    // OnAuthCredentials() with a nullopt that triggers CancelAuth().
    process_id = network::mojom::kInvalidProcessId;

    // `navigation_or_document_` can be null when `context` is created with
    // an invalid RenderFrameHost after a page is destroyed.
    // It is currently possible for the ServiceWorker case above to use
    // kRenderFrameHostContext for the auth request, after the RenderFrameHost
    // has been deleted. Treating this as an invalid process ID will cancel the
    // auth, which is the same outcome as if the ServiceWorker's process were
    // used.
    // TODO(https://crbug.com/1322751): Update the ServiceWorker code to
    // recognize when the RenderFrameHost goes away and not use
    // CreateForRenderFrameHost above.
    if (context.navigation_or_document()) {
      auto* render_frame_host = context.navigation_or_document()->GetDocument();
      if (render_frame_host) {
        process_id = render_frame_host->GetGlobalId().child_id;
      }
    }
  }

  WebContents* current_web_contents = GetWebContents(context);
  if (current_web_contents) {
    // Evict all the BFCache entries that
    // 1): are stored in the same BrowserContext
    // 2): were loaded with the "Cache-control: no-store" header
    // 3): match the challenger information of the page that requires HTTP
    // authentication.
    for (WebContentsImpl* web_contents : WebContentsImpl::GetAllWebContents()) {
      if (web_contents->GetBrowserContext()->UniqueId() ==
          current_web_contents->GetBrowserContext()->UniqueId()) {
        for (const std::unique_ptr<BackForwardCacheImpl::Entry>& entry :
             web_contents->GetController().GetBackForwardCache().GetEntries()) {
          RenderFrameHostImpl* rfh = entry->render_frame_host();
          const GURL& last_committed_url = rfh->GetLastCommittedURL();
          if (rfh->LoadedWithCacheControlNoStoreHeader() &&
              auth_info.challenger ==
                  url::SchemeHostPort(last_committed_url.scheme(),
                                      last_committed_url.host(),
                                      last_committed_url.IntPort())) {
            BackForwardCacheCanStoreDocumentResult flattened_reasons;
            flattened_reasons.No(BackForwardCacheMetrics::NotRestoredReason::
                                     kCacheControlNoStore);
            flattened_reasons.No(
                BackForwardCacheMetrics::NotRestoredReason::kHTTPAuthRequired);
            rfh->EvictFromBackForwardCacheWithFlattenedReasons(
                flattened_reasons);
          }
        }
      }
    }
  }

  OnAuthRequiredContinuation(
      process_id, request_id, url, *is_primary_main_frame, first_auth_attempt,
      auth_info, head_headers, std::move(auth_challenge_responder),
      web_contents_getter);
}

void StoragePartitionImpl::OnPrivateNetworkAccessPermissionRequired(
    const GURL& url,
    const net::IPAddress& ip_address,
    const absl::optional<std::string>& private_network_device_id,
    const absl::optional<std::string>& private_network_device_name,
    OnPrivateNetworkAccessPermissionRequiredCallback callback) {
  if (!base::FeatureList::IsEnabled(
          network::features::kPrivateNetworkAccessPermissionPrompt)) {
    std::move(callback).Run(false);
    return;
  }

  if (url_loader_network_observers_.empty()) {
    std::move(callback).Run(false);
    return;
  }
  const URLLoaderNetworkContext& context =
      url_loader_network_observers_.current_context();

  if (context.type() !=
          URLLoaderNetworkContext::Type::kRenderFrameHostContext ||
      !context.navigation_or_document()) {
    std::move(callback).Run(false);
    return;
  }
  RenderFrameHost* render_frame_host =
      context.navigation_or_document()->GetDocument();
  if (!render_frame_host) {
    std::move(callback).Run(false);
    return;
  }
  auto device = blink::mojom::PrivateNetworkDevice::New(
      private_network_device_id, private_network_device_name, ip_address);

  PrivateNetworkDeviceDelegate* delegate =
      GetContentClient()->browser()->GetPrivateNetworkDeviceDelegate();
  if (!delegate) {
    std::move(callback).Run(false);
    return;
  }

  delegate->RequestPermission(*render_frame_host, std::move(device),
                              std::move(callback));
}

void StoragePartitionImpl::OnCertificateRequested(
    const absl::optional<base::UnguessableToken>& window_id,
    const scoped_refptr<net::SSLCertRequestInfo>& cert_info,
    mojo::PendingRemote<network::mojom::ClientCertificateResponder>
        cert_responder) {
  URLLoaderNetworkContext context =
      url_loader_network_observers_.current_context();

  if (window_id) {
    // Use `window_id` if it is provided, because this request was sent by a
    // service worker; service workers use `window_id` to identify the frame
    // that sends the request since a worker is shared among multiple frames.
    // TODO(https://crbug.com/1240483): Add a DCHECK here that process_id and
    // routing_id are invalid. It can't be added yet because somehow routing_id
    // is valid here.
    if (service_worker_context_->context()) {
      auto* container_host =
          service_worker_context_->context()->GetContainerHostByWindowId(
              *window_id);
      if (container_host) {
        if (container_host->GetRenderFrameHostId()) {
          // Use ServiceWorkerContainerHost's GlobalRenderFrameHostId when
          // the navigation commit has already started.
          GlobalRenderFrameHostId render_frame_host_id =
              container_host->GetRenderFrameHostId();
          context = URLLoaderNetworkContext::CreateForRenderFrameHost(
              render_frame_host_id);
        } else if (NavigationRequest* ongoing_navigation =
                       container_host->GetOngoingNavigationRequestBeforeCommit(
                           base::PassKey<StoragePartitionImpl>())) {
          // This certification request is for an ongoing navigation.
          // Overwrite the context; set `type` to kNavigationRequestContext.
          // TODO(https://crbug.com/1239554): Optimize locating logic.
          context =
              URLLoaderNetworkContext::CreateForNavigation(*ongoing_navigation);
        } else {
          // The navigation request was canceled since the WebContents was
          // discarded, so it is meaningless to continue the certification
          // request.
          CallCancelRequest(std::move(cert_responder));
          return;
        }
      }
    }
  }

  // If the request is for a prerendering page, prerendering should be cancelled
  // because the embedder may show a dialog and ask users to select client
  // certificates, and it's unsuitable for a hidden page.
  if (CancelIfPrerendering(context.navigation_or_document(),
                           PrerenderFinalStatus::kClientCertRequested)) {
    CallCancelRequest(std::move(cert_responder));
    return;
  }

  SSLClientAuthHandler::ContextGetter context_getter;

  if (context.type() == URLLoaderNetworkContext::Type::kServiceWorkerContext) {
    context_getter = base::BindRepeating(GetContextFromStoragePartition,
                                         weak_factory_.GetWeakPtr());
  } else {
    context_getter = base::BindRepeating(GetContextFromNetworkContext, context);
    // The WebContents is already invalid. Bail.
    if (!GetWebContents(context)) {
      CallCancelRequest(std::move(cert_responder));
      return;
    }
  }

  // SSLClientAuthDelegate handles its own lifetime.
  new SSLClientAuthDelegate(std::move(cert_responder), browser_context(),
                            std::move(context_getter), cert_info);
}

void StoragePartitionImpl::OnSSLCertificateError(
    const GURL& url,
    int net_error,
    const net::SSLInfo& ssl_info,
    bool fatal,
    OnSSLCertificateErrorCallback response) {
  URLLoaderNetworkContext context =
      url_loader_network_observers_.current_context();

  // Cancel this request and the prerendering if the request is for a
  // prerendering page, because prerendering pages are invisible and browser
  // cannot show errors on invisible pages.
  if (CancelIfPrerendering(context.navigation_or_document(),
                           PrerenderFinalStatus::kSslCertificateError)) {
    std::move(response).Run(net_error);
    return;
  }

  SSLErrorDelegate* delegate =
      new SSLErrorDelegate(std::move(response));  // deletes self
  bool is_primary_main_frame_request = IsPrimaryMainFrameRequest(context);
  SSLManager::OnSSLCertificateError(
      delegate->GetWeakPtr(), is_primary_main_frame_request, url,
      context.navigation_or_document(), net_error, ssl_info, fatal);
}

void StoragePartitionImpl::OnLoadingStateUpdate(
    network::mojom::LoadInfoPtr info,
    OnLoadingStateUpdateCallback callback) {
  auto* web_contents =
      GetWebContents(url_loader_network_observers_.current_context());
  if (web_contents) {
    static_cast<WebContentsImpl*>(web_contents)
        ->LoadStateChanged(std::move(info));
  }
  std::move(callback).Run();
}

void StoragePartitionImpl::OnDataUseUpdate(
    int32_t network_traffic_annotation_id_hash,
    int64_t recv_bytes,
    int64_t sent_bytes) {
  URLLoaderNetworkContext context =
      url_loader_network_observers_.current_context();
  // `navigation_or_document()` can be null for `kServiceWorkerContext`.
  auto* render_frame_host =
      context.navigation_or_document()
          ? context.navigation_or_document()->GetDocument()
          : nullptr;
  // It can pass empty GlobalRenderFrameHostId() when the context type is
  // not `kRenderFrameHostContext`.
  GlobalRenderFrameHostId render_frame_host_id =
      render_frame_host ? render_frame_host->GetGlobalId()
                        : GlobalRenderFrameHostId();
  GetContentClient()->browser()->OnNetworkServiceDataUseUpdate(
      render_frame_host_id, network_traffic_annotation_id_hash, recv_bytes,
      sent_bytes);
}

void StoragePartitionImpl::OnSharedStorageHeaderReceived(
    const url::Origin& request_origin,
    std::vector<network::mojom::SharedStorageOperationPtr> operations,
    OnSharedStorageHeaderReceivedCallback callback) {
  if (!shared_storage_header_observer_) {
    std::move(callback).Run();
    return;
  }
  auto* navigation_or_document =
      url_loader_network_observers_.current_context().navigation_or_document();
  DCHECK(navigation_or_document);
  RenderFrameHost* rfh = navigation_or_document->GetDocument();
  shared_storage_header_observer_->HeaderReceived(
      request_origin, rfh, std::move(operations), std::move(callback));
}

void StoragePartitionImpl::Clone(
    mojo::PendingReceiver<network::mojom::URLLoaderNetworkServiceObserver>
        observer) {
  url_loader_network_observers_.Add(
      this, std::move(observer),
      url_loader_network_observers_.current_context());
}

mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver>
StoragePartitionImpl::CreateURLLoaderNetworkObserverForFrame(int process_id,
                                                             int routing_id) {
  mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver> remote;
  url_loader_network_observers_.Add(
      this, remote.InitWithNewPipeAndPassReceiver(),
      URLLoaderNetworkContext::CreateForRenderFrameHost(
          GlobalRenderFrameHostId(process_id, routing_id)));
  return remote;
}

mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver>
StoragePartitionImpl::CreateURLLoaderNetworkObserverForNavigationRequest(
    NavigationRequest& navigation_request) {
  mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver> remote;
  url_loader_network_observers_.Add(
      this, remote.InitWithNewPipeAndPassReceiver(),
      URLLoaderNetworkContext::CreateForNavigation(navigation_request));
  return remote;
}

mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver>
StoragePartitionImpl::CreateAuthCertObserverForServiceWorker() {
  mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver> remote;
  url_loader_network_observers_.Add(
      this, remote.InitWithNewPipeAndPassReceiver(),
      URLLoaderNetworkContext::CreateForServiceWorker());
  return remote;
}

void StoragePartitionImpl::OnFileUploadRequested(
    int32_t process_id,
    bool async,
    const std::vector<base::FilePath>& file_paths,
    const GURL& destination_url,
    OnFileUploadRequestedCallback callback) {
  NetworkContextOnFileUploadRequested(process_id, async, file_paths,
                                      destination_url, std::move(callback));
}

void StoragePartitionImpl::OnCanSendReportingReports(
    const std::vector<url::Origin>& origins,
    OnCanSendReportingReportsCallback callback) {
  DCHECK(initialized_);
  PermissionController* permission_controller =
      browser_context_->GetPermissionController();
  DCHECK(permission_controller);

  std::vector<url::Origin> origins_out;
  for (auto& origin : origins) {
    bool allowed = permission_controller
                       ->GetPermissionResultForOriginWithoutContext(
                           blink::PermissionType::BACKGROUND_SYNC, origin)
                       .status == blink::mojom::PermissionStatus::GRANTED;
    if (allowed) {
      origins_out.push_back(origin);
    }
  }

  std::move(callback).Run(origins_out);
}

void StoragePartitionImpl::OnCanSendDomainReliabilityUpload(
    const url::Origin& origin,
    OnCanSendDomainReliabilityUploadCallback callback) {
  DCHECK(initialized_);
  PermissionController* permission_controller =
      browser_context_->GetPermissionController();
  std::move(callback).Run(
      permission_controller
          ->GetPermissionResultForOriginWithoutContext(
              blink::PermissionType::BACKGROUND_SYNC, origin)
          .status == blink::mojom::PermissionStatus::GRANTED);
}

void StoragePartitionImpl::OnClearSiteData(
    const GURL& url,
    const std::string& header_value,
    int load_flags,
    const absl::optional<net::CookiePartitionKey>& cookie_partition_key,
    bool partitioned_state_allowed_only,
    OnClearSiteDataCallback callback) {
  DCHECK(initialized_);
  auto browser_context_getter = base::BindRepeating(
      GetBrowserContextFromStoragePartition, weak_factory_.GetWeakPtr());
  auto web_contents_getter = base::BindRepeating(
      GetWebContents, url_loader_network_observers_.current_context());

  absl::optional<blink::StorageKey> storage_key = CalculateStorageKey(
      url::Origin::Create(url),
      cookie_partition_key.has_value()
          ? base::OptionalToPtr(cookie_partition_key.value().nonce())
          : nullptr);

  ClearSiteDataHandler::HandleHeader(
      browser_context_getter, web_contents_getter, GetConfig(), url,
      header_value, load_flags, cookie_partition_key, storage_key,
      partitioned_state_allowed_only, std::move(callback));
}

#if BUILDFLAG(IS_ANDROID)
void StoragePartitionImpl::OnGenerateHttpNegotiateAuthToken(
    const std::string& server_auth_token,
    bool can_delegate,
    const std::string& auth_negotiate_android_account_type,
    const std::string& spn,
    OnGenerateHttpNegotiateAuthTokenCallback callback) {
  // The callback takes ownership of these unique_ptrs and destroys them when
  // run.
  auto prefs = std::make_unique<net::HttpAuthPreferences>();
  prefs->set_auth_android_negotiate_account_type(
      auth_negotiate_android_account_type);

  auto auth_negotiate =
      std::make_unique<net::android::HttpAuthNegotiateAndroid>(prefs.get());
  net::android::HttpAuthNegotiateAndroid* auth_negotiate_raw =
      auth_negotiate.get();
  auth_negotiate->set_server_auth_token(server_auth_token);
  auth_negotiate->set_can_delegate(can_delegate);

  auto auth_token = std::make_unique<std::string>();
  auth_negotiate_raw->GenerateAuthTokenAndroid(
      nullptr, spn, std::string(), auth_token.get(),
      base::BindOnce(&FinishGenerateNegotiateAuthToken,
                     std::move(auth_negotiate), std::move(auth_token),
                     std::move(prefs), std::move(callback)));
}
#endif

#if BUILDFLAG(IS_CHROMEOS)
void StoragePartitionImpl::OnTrustAnchorUsed() {
  GetContentClient()->browser()->OnTrustAnchorUsed(browser_context_);
}
#endif

#if BUILDFLAG(IS_CT_SUPPORTED)
void StoragePartitionImpl::OnCanSendSCTAuditingReport(
    OnCanSendSCTAuditingReportCallback callback) {
  bool allowed =
      GetContentClient()->browser()->CanSendSCTAuditingReport(browser_context_);
  std::move(callback).Run(allowed);
}

void StoragePartitionImpl::OnNewSCTAuditingReportSent() {
  GetContentClient()->browser()->OnNewSCTAuditingReportSent(browser_context_);
}
#endif

void StoragePartitionImpl::ClearDataImpl(
    uint32_t remove_mask,
    uint32_t quota_storage_remove_mask,
    const blink::StorageKey& storage_key,
    BrowsingDataFilterBuilder* filter_builder,
    StorageKeyPolicyMatcherFunction storage_key_policy_matcher,
    CookieDeletionFilterPtr cookie_deletion_filter,
    bool perform_storage_cleanup,
    const base::Time begin,
    const base::Time end,
    base::OnceClosure callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  bool storage_key_origin_empty = storage_key.origin().opaque();
  DCHECK(storage_key_origin_empty || !filter_builder);
  DCHECK(storage_key_origin_empty || storage_key_policy_matcher.is_null());

  StorageKeyMatcherFunction storage_key_matcher =
      filter_builder ? filter_builder->BuildStorageKeyFilter()
                     : StorageKeyMatcherFunction();

  for (auto& observer : data_removal_observers_) {
    auto filter = CreateGenericStorageKeyMatcher(
        storage_key, storage_key_matcher, storage_key_policy_matcher,
        special_storage_policy_);
    observer.OnStorageKeyDataCleared(remove_mask, std::move(filter), begin,
                                     end);
  }

  DataDeletionHelper* helper = new DataDeletionHelper(
      remove_mask, quota_storage_remove_mask,
      base::BindOnce(&StoragePartitionImpl::DeletionHelperDone,
                     weak_factory_.GetWeakPtr(), std::move(callback)));
  // `helper` deletes itself when done in
  // DataDeletionHelper::DecrementTaskCount().
  deletion_helpers_running_++;
  helper->ClearDataOnUIThread(
      storage_key, filter_builder, std::move(storage_key_policy_matcher),
      std::move(cookie_deletion_filter), GetPath(), dom_storage_context_.get(),
      quota_manager_.get(), special_storage_policy_.get(),
      filesystem_context_.get(), GetCookieManagerForBrowserProcess(),
      interest_group_manager_.get(), attribution_manager_.get(),
      aggregation_service_.get(), private_aggregation_manager_.get(),
      shared_storage_manager_.get(),
#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
      cdm_storage_manager_.get(),
#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)
      perform_storage_cleanup, begin, end);
}

void StoragePartitionImpl::DeletionHelperDone(base::OnceClosure callback) {
  std::move(callback).Run();
  deletion_helpers_running_--;
  if (on_deletion_helpers_done_callback_ && deletion_helpers_running_ == 0) {
    // Notify tests that storage partition is done with all deletion tasks.
    std::move(on_deletion_helpers_done_callback_).Run();
  }
}

void StoragePartitionImpl::QuotaManagedDataDeletionHelper::
    IncrementTaskCountOnIO() {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  ++task_count_;
}

void StoragePartitionImpl::QuotaManagedDataDeletionHelper::
    DecrementTaskCountOnIO() {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  DCHECK_GT(task_count_, 0);
  --task_count_;
  if (task_count_) {
    return;
  }

  std::move(callback_).Run();
  delete this;
}

void StoragePartitionImpl::QuotaManagedDataDeletionHelper::ClearDataOnIOThread(
    const scoped_refptr<storage::QuotaManager>& quota_manager,
    const base::Time begin,
    const base::Time end,
    const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy,
    StoragePartition::StorageKeyPolicyMatcherFunction storage_key_matcher,
    bool perform_storage_cleanup) {
  IncrementTaskCountOnIO();
  base::RepeatingClosure decrement_callback = base::BindRepeating(
      &QuotaManagedDataDeletionHelper::DecrementTaskCountOnIO,
      base::Unretained(this));

  // Ask the QuotaManager for all buckets with temporary quota modified
  // within the user-specified timeframe, and deal with the resulting set in
  // ClearBucketsOnIOThread().
  if (quota_storage_remove_mask_ & QUOTA_MANAGED_STORAGE_MASK_TEMPORARY) {
    IncrementTaskCountOnIO();
    quota_manager->GetBucketsModifiedBetween(
        blink::mojom::StorageType::kTemporary, begin, end,
        base::BindOnce(&QuotaManagedDataDeletionHelper::ClearBucketsOnIOThread,
                       base::Unretained(this), base::RetainedRef(quota_manager),
                       special_storage_policy, storage_key_matcher,
                       perform_storage_cleanup, decrement_callback,
                       blink::mojom::StorageType::kTemporary));
  }

  // Do the same for syncable quota.
  if (quota_storage_remove_mask_ & QUOTA_MANAGED_STORAGE_MASK_SYNCABLE) {
    IncrementTaskCountOnIO();
    quota_manager->GetBucketsModifiedBetween(
        blink::mojom::StorageType::kSyncable, begin, end,
        base::BindOnce(&QuotaManagedDataDeletionHelper::ClearBucketsOnIOThread,
                       base::Unretained(this), base::RetainedRef(quota_manager),
                       special_storage_policy, std::move(storage_key_matcher),
                       perform_storage_cleanup, decrement_callback,
                       blink::mojom::StorageType::kSyncable));
  }

  DecrementTaskCountOnIO();
}

void StoragePartitionImpl::QuotaManagedDataDeletionHelper::
    ClearBucketsOnIOThread(
        storage::QuotaManager* quota_manager,
        const scoped_refptr<storage::SpecialStoragePolicy>&
            special_storage_policy,
        StoragePartition::StorageKeyPolicyMatcherFunction storage_key_matcher,
        bool perform_storage_cleanup,
        base::OnceClosure callback,
        blink::mojom::StorageType quota_storage_type,
        const std::set<storage::BucketLocator>& buckets) {
  // The QuotaManager manages all storage other than cookies, LocalStorage,
  // and SessionStorage. This loop wipes out most HTML5 storage for the given
  // storage keys.
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (buckets.empty()) {
    std::move(callback).Run();
    return;
  }

  storage::QuotaClientTypes quota_client_types =
      StoragePartitionImpl::GenerateQuotaClientTypes(remove_mask_);

  // The logic below (via CheckQuotaManagedDataDeletionStatus) only
  // invokes the callback when all processing is complete.
  base::OnceClosure done_callback =
      perform_storage_cleanup
          ? base::BindOnce(&PerformQuotaManagerStorageCleanup,
                           base::WrapRefCounted(quota_manager),
                           quota_storage_type, quota_client_types,
                           std::move(callback))
          : std::move(callback);

  size_t* deletion_task_count = new size_t(0u);
  (*deletion_task_count)++;
  for (const auto& bucket : buckets) {
    // TODO(mkwst): Clean this up, it's slow. http://crbug.com/130746
    if (storage_key_.has_value() && bucket.storage_key != *storage_key_) {
      continue;
    }

    if (storage_key_matcher &&
        !storage_key_matcher.Run(bucket.storage_key,
                                 special_storage_policy.get())) {
      continue;
    }

    auto split_callback = base::SplitOnceCallback(std::move(done_callback));
    done_callback = std::move(split_callback.first);

    (*deletion_task_count)++;
    quota_manager->DeleteBucketData(
        bucket, quota_client_types,
        base::BindOnce(&OnQuotaManagedBucketDeleted, bucket,
                       deletion_task_count, std::move(split_callback.second)));
  }
  (*deletion_task_count)--;

  CheckQuotaManagedDataDeletionStatus(deletion_task_count,
                                      std::move(done_callback));
}

base::OnceClosure
StoragePartitionImpl::DataDeletionHelper::CreateTaskCompletionClosure(
    TracingDataType data_type) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  auto result = pending_tasks_.insert(data_type);
  DCHECK(result.second) << "Task already started: "
                        << static_cast<int>(data_type);

  static int tracing_id = 0;
  TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
      "browsing_data", "StoragePartitionImpl",
      TRACE_ID_WITH_SCOPE("StoragePartitionImpl", ++tracing_id), "data_type",
      static_cast<int>(data_type));
  return base::BindOnce(
      &StoragePartitionImpl::DataDeletionHelper::OnTaskComplete,
      base::Unretained(this), data_type, tracing_id);
}

void StoragePartitionImpl::DataDeletionHelper::OnTaskComplete(
    TracingDataType data_type,
    int tracing_id) {
  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    GetUIThreadTaskRunner({})->PostTask(
        FROM_HERE,
        base::BindOnce(&DataDeletionHelper::OnTaskComplete,
                       base::Unretained(this), data_type, tracing_id));
    return;
  }
  size_t num_erased = pending_tasks_.erase(data_type);
  DCHECK_EQ(num_erased, 1U) << static_cast<int>(data_type);
  TRACE_EVENT_NESTABLE_ASYNC_END0(
      "browsing_data", "StoragePartitionImpl",
      TRACE_ID_WITH_SCOPE("StoragePartitionImpl", tracing_id));

  if (pending_tasks_.empty()) {
    std::move(callback_).Run();
    delete this;
  }
}

void StoragePartitionImpl::DataDeletionHelper::RecordUnfinishedSubTasks() {
  DCHECK(!pending_tasks_.empty());
  for (TracingDataType task : pending_tasks_) {
    base::UmaHistogramEnumeration(
        "History.ClearBrowsingData.Duration.SlowTasks180sStoragePartition",
        task);
  }
}

void StoragePartitionImpl::DataDeletionHelper::ClearDataOnUIThread(
    const blink::StorageKey& storage_key,
    BrowsingDataFilterBuilder* filter_builder,
    StorageKeyPolicyMatcherFunction storage_key_policy_matcher,
    CookieDeletionFilterPtr cookie_deletion_filter,
    const base::FilePath& path,
    DOMStorageContextWrapper* dom_storage_context,
    storage::QuotaManager* quota_manager,
    storage::SpecialStoragePolicy* special_storage_policy,
    storage::FileSystemContext* filesystem_context,
    network::mojom::CookieManager* cookie_manager,
    InterestGroupManagerImpl* interest_group_manager,
    AttributionManager* attribution_manager,
    AggregationService* aggregation_service,
    PrivateAggregationManagerImpl* private_aggregation_manager,
    storage::SharedStorageManager* shared_storage_manager,
#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
    CdmStorageManager* cdm_storage_manager,
#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)
    bool perform_storage_cleanup,
    const base::Time begin,
    const base::Time end) {
  DCHECK_NE(remove_mask_, 0u);
  DCHECK(callback_);

  // Only one of `storage_key`'s origin and
  // `filter_builder`/`storage_key_policy_matcher` can be set.
  const bool storage_key_origin_empty = storage_key.origin().opaque();
  DCHECK(storage_key_origin_empty || !filter_builder);
  DCHECK(storage_key_origin_empty || storage_key_policy_matcher.is_null());

  GetUIThreadTaskRunner({})->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(
          &StoragePartitionImpl::DataDeletionHelper::RecordUnfinishedSubTasks,
          weak_factory_.GetWeakPtr()),
      kSlowTaskTimeout);

  base::ScopedClosureRunner synchronous_clear_operations(
      CreateTaskCompletionClosure(TracingDataType::kSynchronous));

  scoped_refptr<storage::SpecialStoragePolicy> storage_policy_ref =
      base::WrapRefCounted(special_storage_policy);

  StorageKeyMatcherFunction storage_key_matcher =
      filter_builder ? filter_builder->BuildStorageKeyFilter()
                     : StorageKeyMatcherFunction();

  // This is preferred for new storage APIs to reduce the complexity.
  auto generic_filter = CreateGenericStorageKeyMatcher(
      storage_key, storage_key_matcher, storage_key_policy_matcher,
      storage_policy_ref);

  auto combined_storage_key_matcher = CombineStorageKeyMatcherFunctions(
      storage_key_matcher, storage_key_policy_matcher);

  if (remove_mask_ & REMOVE_DATA_MASK_COOKIES) {
    // The CookieDeletionFilter has a redundant time interval to `begin` and
    // `end`. Ensure that the filter has no time interval specified to help
    // callers detect when they are using the wrong interval values.
    DCHECK(!cookie_deletion_filter->created_after_time.has_value());
    DCHECK(!cookie_deletion_filter->created_before_time.has_value());

    if (!begin.is_null()) {
      cookie_deletion_filter->created_after_time = begin;
    }
    if (!end.is_null()) {
      cookie_deletion_filter->created_before_time = end;
    }

    cookie_manager->DeleteCookies(
        std::move(cookie_deletion_filter),
        base::BindOnce(
            &OnClearedCookies,
            // Handle the cookie store being destroyed and the callback thus not
            // being called.
            mojo::WrapCallbackWithDefaultInvokeIfNotRun(
                CreateTaskCompletionClosure(TracingDataType::kCookies))));
  }

  // It is not expected to only delete internal interest group data.
  DCHECK(!(remove_mask_ & REMOVE_DATA_MASK_INTEREST_GROUPS_INTERNAL) ||
         remove_mask_ & REMOVE_DATA_MASK_INTEREST_GROUPS);
  if (remove_mask_ & REMOVE_DATA_MASK_INTEREST_GROUPS) {
    if (interest_group_manager) {
      // The internal interest group data is not specific to a site so it only
      // makes sense to delete it for all sites (i.e. when
      // generic_filter.is_null()).
      if ((remove_mask_ & REMOVE_DATA_MASK_INTEREST_GROUPS_INTERNAL) &&
          generic_filter.is_null()) {
        interest_group_manager->DeleteAllInterestGroupData(
            mojo::WrapCallbackWithDefaultInvokeIfNotRun(
                CreateTaskCompletionClosure(TracingDataType::kInterestGroups)));
      } else {
        interest_group_manager->DeleteInterestGroupData(
            generic_filter,
            mojo::WrapCallbackWithDefaultInvokeIfNotRun(
                CreateTaskCompletionClosure(TracingDataType::kInterestGroups)));
      }
    }
  }

  if (remove_mask_ & REMOVE_DATA_MASK_INTEREST_GROUP_PERMISSIONS_CACHE) {
    if (interest_group_manager) {
      interest_group_manager->ClearPermissionsCache();
    }
  }

#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
  if ((remove_mask_ & REMOVE_DATA_MASK_MEDIA_LICENSES) && cdm_storage_manager) {
    // If no storage key specified, then delete the CdmStorage.db.
    if (storage_key_origin_empty) {
      cdm_storage_manager->DeleteDatabase();
    } else {
      // TODO(crbug.com/1454512): Investigate and add logic to handle
      // filter_builder and storage_key_policy_matcher.
      cdm_storage_manager->DeleteDataForStorageKey(storage_key,
                                                   base::DoNothing());
    }
  }
#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)

  // TODO(crbug.com/1454512): Remove REMOVE_DATA_MASK_MEDIA_LICENSES from here
  // when MediaLicense is removed from Quota types.
  if (remove_mask_ & REMOVE_DATA_MASK_INDEXEDDB ||
      remove_mask_ & REMOVE_DATA_MASK_WEBSQL ||
      remove_mask_ & REMOVE_DATA_MASK_FILE_SYSTEMS ||
      remove_mask_ & REMOVE_DATA_MASK_SERVICE_WORKERS ||
      remove_mask_ & REMOVE_DATA_MASK_CACHE_STORAGE ||
      remove_mask_ & REMOVE_DATA_MASK_MEDIA_LICENSES) {
    GetIOThreadTaskRunner({})->PostTask(
        FROM_HERE,
        base::BindOnce(&DataDeletionHelper::ClearQuotaManagedDataOnIOThread,
                       base::Unretained(this),
                       base::WrapRefCounted(quota_manager), begin, end,
                       storage_key, storage_policy_ref,
                       combined_storage_key_matcher, perform_storage_cleanup,
                       CreateTaskCompletionClosure(TracingDataType::kQuota)));
  }

  if (remove_mask_ & REMOVE_DATA_MASK_LOCAL_STORAGE) {
    ClearLocalStorageOnUIThread(
        base::WrapRefCounted(dom_storage_context), storage_policy_ref,
        combined_storage_key_matcher, storage_key, perform_storage_cleanup,
        begin, end,
        mojo::WrapCallbackWithDefaultInvokeIfNotRun(
            CreateTaskCompletionClosure(TracingDataType::kLocalStorage)));

    // ClearDataImpl cannot clear session storage data when a particular origin
    // is specified. Therefore we ignore clearing session storage in this case.
    // TODO(lazyboy): Fix.
    if (storage_key_origin_empty) {
      // TODO(crbug.com/960325): Sometimes SessionStorage fails to call its
      // callback. Figure out why.
      ClearSessionStorageOnUIThread(
          base::WrapRefCounted(dom_storage_context), storage_policy_ref,
          combined_storage_key_matcher, perform_storage_cleanup,
          mojo::WrapCallbackWithDefaultInvokeIfNotRun(
              CreateTaskCompletionClosure(TracingDataType::kSessionStorage)));
    }
  }

  if (remove_mask_ & REMOVE_DATA_MASK_SHADER_CACHE) {
    gpu::GpuDiskCacheFactory* gpu_cache_factory =
        GetGpuDiskCacheFactorySingleton();
    // May be null in tests where it is difficult to plumb through a test
    // storage partition.
    if (!path.empty() && gpu_cache_factory) {
      // Clear the path for all the different GPU cache sub-types.
      base::RepeatingClosure barrier = base::BarrierClosure(
          gpu::kGpuDiskCacheTypes.size(),
          CreateTaskCompletionClosure(TracingDataType::kGpuCache));
      for (gpu::GpuDiskCacheType type : gpu::kGpuDiskCacheTypes) {
        gpu_cache_factory->ClearByPath(
            path.Append(gpu::GetGpuDiskCacheSubdir(type)), begin, end,
            base::BindOnce(&ClearedGpuCache, barrier));
      }
    }
  }

  // It is not expected to only delete internal attribution reporting data.
  DCHECK(!(remove_mask_ & REMOVE_DATA_MASK_ATTRIBUTION_REPORTING_INTERNAL) ||
         remove_mask_ & REMOVE_DATA_MASK_ATTRIBUTION_REPORTING_SITE_CREATED);
  if (attribution_manager &&
      (remove_mask_ & REMOVE_DATA_MASK_ATTRIBUTION_REPORTING_SITE_CREATED)) {
    if (storage_key_origin_empty) {
      attribution_manager->ClearData(
          begin, end, generic_filter, filter_builder,
          remove_mask_ & REMOVE_DATA_MASK_ATTRIBUTION_REPORTING_INTERNAL,
          mojo::WrapCallbackWithDefaultInvokeIfNotRun(
              CreateTaskCompletionClosure(TracingDataType::kConversions)));
    } else if (storage_key.IsFirstPartyContext()) {
      // Attribution Reporting API doesn't support cross-site data deletion.
      std::unique_ptr<BrowsingDataFilterBuilder> effective_filter_builder =
          BrowsingDataFilterBuilder::Create(
              BrowsingDataFilterBuilder::Mode::kDelete);
      effective_filter_builder->AddOrigin(storage_key.origin());
      attribution_manager->ClearData(
          begin, end, generic_filter, effective_filter_builder.get(),
          remove_mask_ & REMOVE_DATA_MASK_ATTRIBUTION_REPORTING_INTERNAL,
          mojo::WrapCallbackWithDefaultInvokeIfNotRun(
              CreateTaskCompletionClosure(TracingDataType::kConversions)));
    }
  }

  if (aggregation_service &&
      (remove_mask_ & REMOVE_DATA_MASK_AGGREGATION_SERVICE)) {
    // Currently the aggregation service only stores public keys and we don't
    // have information on the page/context that uses the public key origin,
    // therefore we don't check origins and instead just delete all rows in the
    // given time range.
    // TODO(crbug.com/1284971): Consider fine-grained deletion of public keys.
    // TODO(crbug.com/1286173): Consider adding aggregation service origins to
    // `CookiesTreeModel`.
    aggregation_service->ClearData(
        begin, end, generic_filter,
        mojo::WrapCallbackWithDefaultInvokeIfNotRun(
            CreateTaskCompletionClosure(TracingDataType::kAggregationService)));
  }

  if (private_aggregation_manager &&
      (remove_mask_ & REMOVE_DATA_MASK_PRIVATE_AGGREGATION_INTERNAL)) {
    private_aggregation_manager->ClearBudgetData(
        begin, end, generic_filter,

        // Wrapping the callback ensures that the callback is still run in the
        // case that the storage partition is deleted before the task is posted.
        mojo::WrapCallbackWithDefaultInvokeIfNotRun(
            CreateTaskCompletionClosure(TracingDataType::kPrivateAggregation)));
  }

  if (base::FeatureList::IsEnabled(blink::features::kSharedStorageAPI) &&
      shared_storage_manager &&
      (remove_mask_ & REMOVE_DATA_MASK_SHARED_STORAGE)) {
    auto shared_storage_purge_callback = base::BindOnce(
        [](base::WeakPtr<storage::SharedStorageManager> manager,
           base::OnceClosure callback,
           storage::SharedStorageDatabase::OperationResult result) {
          if (manager) {
            manager->OnOperationResult(result);
          }
          std::move(callback).Run();
        },
        shared_storage_manager->GetWeakPtr(),
        CreateTaskCompletionClosure(TracingDataType::kSharedStorage));

    shared_storage_manager->PurgeMatchingOrigins(
        combined_storage_key_matcher, begin, end,
        std::move(shared_storage_purge_callback), perform_storage_cleanup);
  }
}

void StoragePartitionImpl::ClearDataForOrigin(
    uint32_t remove_mask,
    uint32_t quota_storage_remove_mask,
    const GURL& storage_origin,
    base::OnceClosure callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(initialized_);
  CookieDeletionFilterPtr deletion_filter = CookieDeletionFilter::New();
  if (!storage_origin.host().empty()) {
    deletion_filter->host_name = storage_origin.host();
  }
  // Construct a |BrowsingDataFilterBuilder| instead of just passing a storage
  // key based on the origin directly. This is needed to be able to delete the
  // associated 3P data embedded on the origin.
  auto filter_builder = BrowsingDataFilterBuilder::Create(
      content::BrowsingDataFilterBuilder::Mode::kDelete);
  filter_builder->AddOrigin(url::Origin::Create(storage_origin));
  ClearDataImpl(remove_mask, quota_storage_remove_mask, blink::StorageKey(),
                filter_builder.get(), StorageKeyPolicyMatcherFunction(),
                std::move(deletion_filter), false, base::Time(),
                base::Time::Max(), std::move(callback));
}

void StoragePartitionImpl::ClearDataForBuckets(
    const blink::StorageKey& storage_key,
    const std::set<std::string>& storage_buckets,
    base::OnceClosure callback) {
  DCHECK(initialized_);

  const auto remove_buckets_done =
      base::BarrierCallback<blink::mojom::QuotaStatusCode>(
          storage_buckets.size(),
          BindPostTaskToCurrentDefault(
              base::BindOnce(&StoragePartitionImpl::ClearDataForBucketsDone,
                             base::Unretained(this), storage_key,
                             storage_buckets, std::move(callback))));

  storage::QuotaManagerProxy* quota_manager_proxy = GetQuotaManagerProxy();

  for (const auto& bucket : storage_buckets) {
    quota_manager_proxy->DeleteBucket(
        storage_key, bucket, base::SequencedTaskRunner::GetCurrentDefault(),
        remove_buckets_done);
  }
}

void StoragePartitionImpl::ClearDataForBucketsDone(
    const blink::StorageKey& storage_key,
    const std::set<std::string>& storage_buckets,
    base::OnceClosure callback,
    const std::vector<blink::mojom::QuotaStatusCode>& status_codes) {
  auto bucket_iterator = storage_buckets.begin();

  for (const auto status_code : status_codes) {
    if (bucket_iterator == storage_buckets.end()) {
      break;
    }

    const std::string bucket_name = *bucket_iterator;

    if (status_code != blink::mojom::QuotaStatusCode::kOk) {
      DLOG(ERROR) << "Couldn't remove bucket with name" << bucket_name
                  << " with storage key " << storage_key.GetDebugString()
                  << ". Status: " << static_cast<int>(status_code);
    }

    ++bucket_iterator;
  }

  std::move(callback).Run();
}

void StoragePartitionImpl::ClearData(uint32_t remove_mask,
                                     uint32_t quota_storage_remove_mask,
                                     const blink::StorageKey& storage_key,
                                     const base::Time begin,
                                     const base::Time end,
                                     base::OnceClosure callback) {
  DCHECK(initialized_);
  CookieDeletionFilterPtr deletion_filter = CookieDeletionFilter::New();
  if (!storage_key.origin().host().empty()) {
    deletion_filter->host_name = storage_key.origin().host();
  }
  bool perform_storage_cleanup =
      begin.is_null() && end.is_max() && storage_key.origin().opaque();
  ClearDataImpl(remove_mask, quota_storage_remove_mask, storage_key,
                /*filter_builder=*/nullptr, StorageKeyPolicyMatcherFunction(),
                std::move(deletion_filter), perform_storage_cleanup, begin, end,
                std::move(callback));
}

void StoragePartitionImpl::ClearData(
    uint32_t remove_mask,
    uint32_t quota_storage_remove_mask,
    BrowsingDataFilterBuilder* filter_builder,
    StorageKeyPolicyMatcherFunction storage_key_policy_matcher,
    network::mojom::CookieDeletionFilterPtr cookie_deletion_filter,
    bool perform_storage_cleanup,
    const base::Time begin,
    const base::Time end,
    base::OnceClosure callback) {
  DCHECK(initialized_);
  ClearDataImpl(remove_mask, quota_storage_remove_mask, blink::StorageKey(),
                filter_builder, std::move(storage_key_policy_matcher),
                std::move(cookie_deletion_filter), perform_storage_cleanup,
                begin, end, std::move(callback));
}

void StoragePartitionImpl::ClearCodeCaches(
    const base::Time begin,
    const base::Time end,
    const base::RepeatingCallback<bool(const GURL&)>& url_matcher,
    base::OnceClosure callback) {
  DCHECK(initialized_);
  // StoragePartitionCodeCacheDataRemover deletes itself when it is done.
  StoragePartitionCodeCacheDataRemover::Create(this, url_matcher, begin, end)
      ->Remove(std::move(callback));
}

void StoragePartitionImpl::Flush() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(initialized_);
  if (GetDOMStorageContext()) {
    GetDOMStorageContext()->Flush();
  }
}

void StoragePartitionImpl::ResetURLLoaderFactories() {
  DCHECK(initialized_);
  GetNetworkContext()->ResetURLLoaderFactories();
  url_loader_factory_for_browser_process_.reset();
  url_loader_factory_getter_->Initialize(this);
}

void StoragePartitionImpl::ClearBluetoothAllowedDevicesMapForTesting() {
  DCHECK(initialized_);
  bluetooth_allowed_devices_map_->Clear();
}

void StoragePartitionImpl::AddObserver(DataRemovalObserver* observer) {
  data_removal_observers_.AddObserver(observer);
}

void StoragePartitionImpl::RemoveObserver(DataRemovalObserver* observer) {
  data_removal_observers_.RemoveObserver(observer);
}

void StoragePartitionImpl::FlushNetworkInterfaceForTesting() {
  DCHECK(initialized_);
  DCHECK(network_context_);
  network_context_.FlushForTesting();
  if (url_loader_factory_for_browser_process_) {
    url_loader_factory_for_browser_process_.FlushForTesting();
  }
  if (cookie_manager_for_browser_process_) {
    cookie_manager_for_browser_process_.FlushForTesting();
  }
}

void StoragePartitionImpl::WaitForDeletionTasksForTesting() {
  DCHECK(initialized_);
  if (deletion_helpers_running_) {
    base::RunLoop loop;
    on_deletion_helpers_done_callback_ = loop.QuitClosure();
    loop.Run();
  }
}

void StoragePartitionImpl::WaitForCodeCacheShutdownForTesting() {
  DCHECK(initialized_);
  if (generated_code_cache_context_) {
    // If this is still running its initialization task it may check
    // enabled features on a sequenced worker pool which could race
    // between ScopedFeatureList destruction.
    base::RunLoop loop;
    GeneratedCodeCacheContext::RunOrPostTask(
        generated_code_cache_context_, FROM_HERE,
        base::BindOnce(
            [](scoped_refptr<GeneratedCodeCacheContext> context,
               base::OnceClosure quit) {
              context->generated_js_code_cache()->GetBackend(base::BindOnce(
                  [](base::OnceClosure quit, disk_cache::Backend*) {
                    std::move(quit).Run();
                  },
                  std::move(quit)));
            },
            generated_code_cache_context_, loop.QuitClosure()));
    loop.Run();
    generated_code_cache_context_->Shutdown();
  }
}

void StoragePartitionImpl::SetNetworkContextForTesting(
    mojo::PendingRemote<network::mojom::NetworkContext>
        network_context_remote) {
  network_context_.reset();
  network_context_.Bind(std::move(network_context_remote));
}

base::WeakPtr<StoragePartitionImpl> StoragePartitionImpl::GetWeakPtr() {
  return weak_factory_.GetWeakPtr();
}

BrowserContext* StoragePartitionImpl::browser_context() const {
  return browser_context_;
}

storage::mojom::Partition* StoragePartitionImpl::GetStorageServicePartition() {
  if (!remote_partition_) {
    absl::optional<base::FilePath> storage_path;
    if (!is_in_memory()) {
      storage_path =
          browser_context_->GetPath().Append(relative_partition_path_);
    }
    GetStorageServiceRemote()->BindPartition(
        storage_path, remote_partition_.BindNewPipeAndPassReceiver());
    remote_partition_.set_disconnect_handler(
        base::BindOnce(&StoragePartitionImpl::OnStorageServiceDisconnected,
                       base::Unretained(this)));
  }
  return remote_partition_.get();
}

// static
mojo::Remote<storage::mojom::StorageService>&
StoragePartitionImpl::GetStorageServiceForTesting() {
  return GetStorageServiceRemote();
}

mojo::ReceiverId StoragePartitionImpl::BindDomStorage(
    int process_id,
    mojo::PendingReceiver<blink::mojom::DomStorage> receiver,
    mojo::PendingRemote<blink::mojom::DomStorageClient> client) {
  DCHECK(initialized_);
  auto handle =
      ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(process_id);
  mojo::ReceiverId id = dom_storage_receivers_.Add(
      this, std::move(receiver),
      std::make_unique<SecurityPolicyHandle>(std::move(handle)));
  dom_storage_clients_[id].Bind(std::move(client));
  return id;
}

void StoragePartitionImpl::UnbindDomStorage(mojo::ReceiverId receiver_id) {
  DCHECK(initialized_);
  dom_storage_receivers_.Remove(receiver_id);
  dom_storage_clients_.erase(receiver_id);
}

void StoragePartitionImpl::OverrideQuotaManagerForTesting(
    storage::QuotaManager* quota_manager) {
  DCHECK(initialized_);
  quota_manager_ = quota_manager;
}

void StoragePartitionImpl::OverrideSpecialStoragePolicyForTesting(
    storage::SpecialStoragePolicy* special_storage_policy) {
  DCHECK(initialized_);
  special_storage_policy_ = special_storage_policy;
}

void StoragePartitionImpl::ShutdownBackgroundSyncContextForTesting() {
  DCHECK(initialized_);
  if (GetBackgroundSyncContext()) {
    GetBackgroundSyncContext()->Shutdown();
  }
}

void StoragePartitionImpl::OverrideBackgroundSyncContextForTesting(
    BackgroundSyncContextImpl* background_sync_context) {
  DCHECK(initialized_);
  DCHECK(!GetBackgroundSyncContext() ||
         !GetBackgroundSyncContext()->background_sync_manager());
  background_sync_context_ = background_sync_context;
}

void StoragePartitionImpl::OverrideSharedWorkerServiceForTesting(
    std::unique_ptr<SharedWorkerServiceImpl> shared_worker_service) {
  DCHECK(initialized_);
  shared_worker_service_ = std::move(shared_worker_service);
}

void StoragePartitionImpl::OverrideSharedStorageWorkletHostManagerForTesting(
    std::unique_ptr<SharedStorageWorkletHostManager>
        shared_storage_worklet_host_manager) {
  DCHECK(initialized_);
  shared_storage_worklet_host_manager_ =
      std::move(shared_storage_worklet_host_manager);
}

void StoragePartitionImpl::OverrideSharedStorageHeaderObserverForTesting(
    std::unique_ptr<SharedStorageHeaderObserver>
        shared_storage_header_observer) {
  DCHECK(initialized_);
  shared_storage_header_observer_ = std::move(shared_storage_header_observer);
}

void StoragePartitionImpl::OverrideAggregationServiceForTesting(
    std::unique_ptr<AggregationService> aggregation_service) {
  DCHECK(initialized_);
  aggregation_service_ = std::move(aggregation_service);
}

void StoragePartitionImpl::OverrideAttributionManagerForTesting(
    std::unique_ptr<AttributionManager> attribution_manager) {
  DCHECK(initialized_);
  attribution_manager_ = std::move(attribution_manager);
}

void StoragePartitionImpl::OverridePrivateAggregationManagerForTesting(
    std::unique_ptr<PrivateAggregationManagerImpl>
        private_aggregation_manager) {
  DCHECK(initialized_);
  private_aggregation_manager_ = std::move(private_aggregation_manager);
}

void StoragePartitionImpl::GetQuotaSettings(
    storage::OptionalQuotaSettingsCallback callback) {
  if (g_test_quota_settings) {
    // For debugging tests harness can inject settings.
    std::move(callback).Run(*g_test_quota_settings);
    return;
  }

  storage::GetNominalDynamicSettings(
      GetPath(), browser_context_->IsOffTheRecord(),
      storage::GetDefaultDeviceInfoHelper(), std::move(callback));
}

void StoragePartitionImpl::InitNetworkContext() {
  network::mojom::NetworkContextParamsPtr context_params =
      network::mojom::NetworkContextParams::New();
  cert_verifier::mojom::CertVerifierCreationParamsPtr
      cert_verifier_creation_params =
          cert_verifier::mojom::CertVerifierCreationParams::New();
  GetContentClient()->browser()->ConfigureNetworkContextParams(
      browser_context_, is_in_memory(), relative_partition_path_,
      context_params.get(), cert_verifier_creation_params.get());
  // Should be initialized with existing per-profile CORS access lists.
  DCHECK(context_params->cors_origin_access_list.empty())
      << "NetworkContextParams::cors_origin_access_list should be populated "
         "via SharedCorsOriginAccessList";
  context_params->cors_origin_access_list =
      browser_context_->GetSharedCorsOriginAccessList()
          ->GetOriginAccessList()
          .CreateCorsOriginAccessPatternsList();
  devtools_instrumentation::ApplyNetworkContextParamsOverrides(
      browser_context_, context_params.get());
  DCHECK(!context_params->cert_verifier_params)
      << "`cert_verifier_params` should not be set in the "
         "NetworkContextParams, as they will be replaced with a new pipe to "
         "the CertVerifierService.";

  context_params->cert_verifier_params =
      GetCertVerifierParams(std::move(cert_verifier_creation_params));

  // This mechanisms should be used only for legacy internal headers. You can
  // find a recommended alternative approach on URLRequest::cors_exempt_headers
  // at services/network/public/mojom/url_loader.mojom.
  context_params->cors_exempt_header_list.push_back(
      kCorsExemptPurposeHeaderName);
  context_params->cors_exempt_header_list.push_back(
      GetCorsExemptRequestedWithHeaderName());
  variations::UpdateCorsExemptHeaderForVariations(context_params.get());

  cors_exempt_header_list_ = context_params->cors_exempt_header_list;

  if (base::FeatureList::IsEnabled(
          network::features::kCompressionDictionaryTransportBackend) &&
      GetContentClient()->browser()->AllowCompressionDictionaryTransport(
          browser_context_)) {
    context_params->shared_dictionary_enabled = true;
    if (!is_in_memory()) {
      // Some callers may already initialize NetworkContextFilePaths, and we
      // don't want to overwrite them.
      if (!context_params->file_paths) {
        context_params->file_paths =
            network::mojom::NetworkContextFilePaths::New();
      }
      context_params->file_paths->shared_dictionary_directory =
          partition_path_.Append(FILE_PATH_LITERAL("Shared Dictionary"));
    }
    if (context_params->shared_dictionary_cache_max_size == 0u) {
      CalculateAndSetSharedDictionaryCacheMaxSize(
          GetWeakPtr(), is_in_memory() ? base::FilePath() : partition_path_);
    }
  }

  if (cookie_deprecation_label_manager_) {
    context_params->cookie_deprecation_label =
        cookie_deprecation_label_manager_->GetValue();
  }

  network_context_.reset();
  CreateNetworkContextInNetworkService(
      network_context_.BindNewPipeAndPassReceiver(), std::move(context_params));
  DCHECK(network_context_);

  network_context_client_receiver_.reset();
  network_context_->SetClient(
      network_context_client_receiver_.BindNewPipeAndPassRemote());
  network_context_.set_disconnect_handler(base::BindOnce(
      &StoragePartitionImpl::InitNetworkContext, weak_factory_.GetWeakPtr()));

  if (base::FeatureList::IsEnabled(features::kPreloadCookies)) {
    mojo::Remote<::network::mojom::CookieManager> cookie_manager;
    mojo::PendingRemote<::network::mojom::CookieManager> cookie_manager_remote;
    network_context_->GetCookieManager(
        cookie_manager_remote.InitWithNewPipeAndPassReceiver());
    cookie_manager.Bind(std::move(cookie_manager_remote));
    cookie_manager->GetAllCookies(base::NullCallback());
  }
}

network::mojom::URLLoaderFactoryParamsPtr
StoragePartitionImpl::CreateURLLoaderFactoryParams() {
  network::mojom::URLLoaderFactoryParamsPtr params =
      network::mojom::URLLoaderFactoryParams::New();
  params->process_id = network::mojom::kBrowserProcessId;
  params->automatically_assign_isolation_info = true;
  params->is_corb_enabled = false;
  params->is_trusted = true;
  params->url_loader_network_observer =
      CreateAuthCertObserverForServiceWorker();
  params->disable_web_security =
      base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableWebSecurity);
  return params;
}

network::mojom::URLLoaderFactory*
StoragePartitionImpl::GetURLLoaderFactoryForBrowserProcessInternal() {
  // Create the URLLoaderFactory as needed, but make sure not to reuse a
  // previously created one if the test override has changed.
  if (url_loader_factory_for_browser_process_ &&
      url_loader_factory_for_browser_process_.is_connected() &&
      is_test_url_loader_factory_for_browser_process_ !=
          !GetCreateURLLoaderFactoryCallback()) {
    return url_loader_factory_for_browser_process_.get();
  }

  network::mojom::URLLoaderFactoryParamsPtr params =
      CreateURLLoaderFactoryParams();
  url_loader_factory_for_browser_process_.reset();
  if (!GetCreateURLLoaderFactoryCallback()) {
    GetNetworkContext()->CreateURLLoaderFactory(
        url_loader_factory_for_browser_process_.BindNewPipeAndPassReceiver(),
        std::move(params));
    is_test_url_loader_factory_for_browser_process_ = false;
    return url_loader_factory_for_browser_process_.get();
  }

  mojo::PendingRemote<network::mojom::URLLoaderFactory> original_factory;
  GetNetworkContext()->CreateURLLoaderFactory(
      original_factory.InitWithNewPipeAndPassReceiver(), std::move(params));
  url_loader_factory_for_browser_process_.Bind(
      GetCreateURLLoaderFactoryCallback().Run(std::move(original_factory)));
  is_test_url_loader_factory_for_browser_process_ = true;
  return url_loader_factory_for_browser_process_.get();
}

void StoragePartition::SetDefaultQuotaSettingsForTesting(
    const storage::QuotaSettings* settings) {
  g_test_quota_settings = settings;
}

mojo::PendingRemote<network::mojom::CookieAccessObserver>
StoragePartitionImpl::CreateCookieAccessObserverForServiceWorker() {
  mojo::PendingRemote<network::mojom::CookieAccessObserver> remote;
  service_worker_cookie_observers_.Add(
      std::make_unique<ServiceWorkerCookieAccessObserver>(this),
      remote.InitWithNewPipeAndPassReceiver());
  return remote;
}

mojo::PendingRemote<network::mojom::TrustTokenAccessObserver>
StoragePartitionImpl::CreateTrustTokenAccessObserverForServiceWorker() {
  mojo::PendingRemote<network::mojom::TrustTokenAccessObserver> remote;
  service_worker_trust_token_observers_.Add(
      std::make_unique<ServiceWorkerTrustTokenAccessObserver>(this),
      remote.InitWithNewPipeAndPassReceiver());
  return remote;
}

mojo::PendingRemote<network::mojom::SharedDictionaryAccessObserver>
StoragePartitionImpl::CreateSharedDictionaryAccessObserverForServiceWorker() {
  mojo::PendingRemote<network::mojom::SharedDictionaryAccessObserver> remote;
  service_worker_shared_dictionary_observers_.Add(
      std::make_unique<ServiceWorkerSharedDictionaryAccessObserver>(this),
      remote.InitWithNewPipeAndPassReceiver());
  return remote;
}

void StoragePartitionImpl::OpenLocalStorageForProcess(
    int process_id,
    const blink::StorageKey& storage_key,
    mojo::PendingReceiver<blink::mojom::StorageArea> receiver) {
  DCHECK(initialized_);
  auto handle =
      ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(process_id);
  dom_storage_context_->OpenLocalStorage(storage_key, absl::nullopt,
                                         std::move(receiver), std::move(handle),
                                         base::DoNothing());
}

void StoragePartitionImpl::BindSessionStorageAreaForProcess(
    int process_id,
    const blink::StorageKey& storage_key,
    const std::string& namespace_id,
    mojo::PendingReceiver<blink::mojom::StorageArea> receiver) {
  DCHECK(initialized_);
  auto handle =
      ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(process_id);
  dom_storage_context_->BindStorageArea(storage_key, absl::nullopt,
                                        namespace_id, std::move(receiver),
                                        std::move(handle), base::DoNothing());
}

absl::optional<blink::StorageKey> StoragePartitionImpl::CalculateStorageKey(
    const url::Origin& origin,
    const base::UnguessableToken* nonce) {
  if (!blink::StorageKey::IsThirdPartyStoragePartitioningEnabled()) {
    return absl::nullopt;
  }

  NavigationOrDocumentHandle* handle =
      url_loader_network_observers_.current_context().navigation_or_document();
  if (!handle) {
    return absl::nullopt;
  }
  FrameTreeNode* node = handle->GetFrameTreeNode();
  if (!node) {
    return absl::nullopt;
  }
  RenderFrameHostImpl* frame_host = node->current_frame_host();
  if (!frame_host) {
    return absl::nullopt;
  }

  return frame_host->CalculateStorageKey(origin, nonce);
}

StoragePartitionImpl::URLLoaderNetworkContext::URLLoaderNetworkContext(
    URLLoaderNetworkContext::Type type,
    GlobalRenderFrameHostId render_frame_host_id)
    : type_(type) {
  // `render_frame_host_id` can be invalid for `kServiceWorkerContext`.
  if (!render_frame_host_id) {
    return;
  }
  auto* render_frame_host = RenderFrameHostImpl::FromID(render_frame_host_id);
  if (!render_frame_host) {
    return;
  }

  navigation_or_document_ = render_frame_host->GetNavigationOrDocumentHandle();
}

StoragePartitionImpl::URLLoaderNetworkContext::URLLoaderNetworkContext(
    NavigationRequest& navigation_request)
    : type_(Type::kNavigationRequestContext) {
  navigation_or_document_ = navigation_request.navigation_or_document_handle();
}

StoragePartitionImpl::URLLoaderNetworkContext::URLLoaderNetworkContext(
    const URLLoaderNetworkContext& other) = default;

StoragePartitionImpl::URLLoaderNetworkContext&
StoragePartitionImpl::URLLoaderNetworkContext::operator=(
    const URLLoaderNetworkContext& other) = default;

StoragePartitionImpl::URLLoaderNetworkContext::~URLLoaderNetworkContext() =
    default;

StoragePartitionImpl::URLLoaderNetworkContext
StoragePartitionImpl::URLLoaderNetworkContext::CreateForRenderFrameHost(
    GlobalRenderFrameHostId render_frame_host_id) {
  return StoragePartitionImpl::URLLoaderNetworkContext(
      URLLoaderNetworkContext::Type::kRenderFrameHostContext,
      render_frame_host_id);
}

StoragePartitionImpl::URLLoaderNetworkContext
StoragePartitionImpl::URLLoaderNetworkContext::CreateForNavigation(
    NavigationRequest& navigation_request) {
  return StoragePartitionImpl::URLLoaderNetworkContext(navigation_request);
}

StoragePartitionImpl::URLLoaderNetworkContext
StoragePartitionImpl::URLLoaderNetworkContext::CreateForServiceWorker() {
  return StoragePartitionImpl::URLLoaderNetworkContext(
      URLLoaderNetworkContext::Type::kServiceWorkerContext,
      GlobalRenderFrameHostId());
}

bool StoragePartitionImpl::URLLoaderNetworkContext::IsNavigationRequestContext()
    const {
  return type_ == URLLoaderNetworkContext::Type::kNavigationRequestContext;
}

}  // namespace content
