// 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 <optional>
#include <utility>
#include <vector>

#include "base/barrier_callback.h"
#include "base/barrier_closure.h"
#include "base/check_deref.h"
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/dcheck_is_on.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback_forward.h"
#include "base/functional/callback_helpers.h"
#include "base/functional/concurrent_closures.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/numerics/safe_conversions.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/types/optional_util.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
#include "components/attribution_reporting/features.h"
#include "components/leveldb_proto/public/proto_database_provider.h"
#include "components/services/storage/privileged/cpp/bucket_client_info.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/omnibox_autofocus_http_headers.h"
#include "components/variations/net/variations_http_headers.h"
#include "content/browser/aggregation_service/aggregation_service.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_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/guest_page_holder_impl.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/reconnectable_url_loader_factory.h"
#include "content/browser/loader/subresource_proxying_url_loader_service.h"
#include "content/browser/loader/url_loader_factory_utils.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/network_service_instance_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/renderer_host/navigation_state_keep_alive.h"
#include "content/browser/service_worker/service_worker_client.h"
#include "content/browser/service_worker/service_worker_context_core.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_runtime_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/cookie_access_details.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_descriptor_util.h"
#include "content/public/browser/permission_result.h"
#include "content/public/browser/private_aggregation_data_model.h"
#include "content/public/browser/runtime_feature_state/runtime_feature_state_document_data.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/disk_cache/buildflags.h"
#include "net/ssl/client_cert_store.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/features.h"
#include "services/network/public/cpp/ip_address_space_util.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
#include "services/network/public/cpp/url_loader_factory_builder.h"
#include "services/network/public/mojom/clear_data_filter.mojom.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/device_bound_sessions.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/blob/blob_url_registry.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/blink/public/common/features.h"
#include "third_party/blink/public/common/navigation/preloading_headers.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/use_counter/metrics/web_feature.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/public/browser/cdm_storage_data_model.h"
#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)

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

namespace content {

namespace {

using Type = StoragePartitionImpl::ContextType;

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;
}

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 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,
    storage::QuotaClientTypes quota_client_types,
    base::OnceClosure callback) {
  quota_manager->PerformStorageCleanup(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::ConcurrentClosures concurrent;
  for (const StorageUsageInfo& info : infos) {
    if (storage_key_matcher &&
        !storage_key_matcher.Run(info.storage_key,
                                 special_storage_policy.get())) {
      continue;
    }

    if (info.last_modified >= delete_begin &&
        info.last_modified <= delete_end) {
      dom_storage_context->DeleteLocalStorage(info.storage_key,
                                              concurrent.CreateClosure());
    }
  }
  std::move(concurrent).Done(std::move(done_callback));
}

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::ConcurrentClosures concurrent;
  for (const SessionStorageUsageInfo& info : infos) {
    if (storage_key_matcher &&
        !storage_key_matcher.Run(info.storage_key,
                                 special_storage_policy.get())) {
      continue;
    }
    dom_storage_context->DeleteSessionStorage(info, concurrent.CreateClosure());
  }
  std::move(concurrent).Done(std::move(done_callback));
}

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)));
}

// 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* web_contents,
      content::BrowserContext* browser_context,
      const net::AuthChallengeInfo& auth_info,
      bool is_request_for_primary_main_frame_navigation,
      bool is_request_for_navigation,
      base::StrictNumeric<int32_t> process_id,
      base::StrictNumeric<int32_t> request_id,
      const GURL& url,
      scoped_refptr<net::HttpResponseHeaders> response_headers,
      bool first_auth_attempt,
      FrameTreeNodeId frame_tree_node_id)
      : auth_challenge_responder_(std::move(auth_challenge_responder)),
        auth_info_(auth_info),
        request_id_(process_id, request_id),
        is_request_for_primary_main_frame_navigation_(
            is_request_for_primary_main_frame_navigation),
        is_request_for_navigation_(is_request_for_navigation),
        creating_login_delegate_(false),
        url_(url),
        response_headers_(std::move(response_headers)),
        first_auth_attempt_(first_auth_attempt),
        web_contents_(web_contents ? web_contents->GetWeakPtr() : nullptr),
        browser_context_(browser_context->GetWeakPtr()),
        frame_tree_node_id_(frame_tree_node_id) {
    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 std::optional<net::AuthCredentials>& auth_credentials) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    DCHECK(!(use_fallback && auth_credentials.has_value()));
    if (!use_fallback) {
      OnAuthCredentials(auth_credentials);
      return;
    }

    if (!browser_context_) {
      OnAuthCredentials(std::nullopt);
      return;
    }

    if (web_contents_) {
      CHECK_EQ(web_contents_->GetBrowserContext(), browser_context_.get());
    }

    FrameTreeNode* frame_tree_node =
        FrameTreeNode::GloballyFindByID(frame_tree_node_id_);
    GuestPageHolder* guest = nullptr;
    if (frame_tree_node) {
      guest = GuestPageHolderImpl::FromRenderFrameHost(
          *frame_tree_node->current_frame_host());
    }

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

  void OnAuthCredentials(
      const std::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_navigation_;
  bool is_request_for_navigation_;
  bool creating_login_delegate_;
  GURL url_;
  const scoped_refptr<net::HttpResponseHeaders> response_headers_;
  bool first_auth_attempt_;
  base::WeakPtr<WebContents> web_contents_;
  base::WeakPtr<BrowserContext> browser_context_;
  std::unique_ptr<LoginDelegate> login_delegate_;
  FrameTreeNodeId frame_tree_node_id_;
  base::WeakPtrFactory<LoginHandlerDelegate> weak_factory_{this};
};

// 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,
      int process_id,
      base::WeakPtr<WebContents> web_contents,
      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),
            browser_context->GetWeakPtr(),
            process_id,
            web_contents,
            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);

    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 `kSharedOrServiceWorkerContext`.
  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);
}

std::vector<GlobalRenderFrameHostId> GetRoutingIdsForOrigin(
    StoragePartitionImpl* storage_partition,
    const url::Origin& origin) {
  scoped_refptr<ServiceWorkerContextWrapper> service_worker_context =
      storage_partition->GetServiceWorkerContext();

  return *service_worker_context->GetWindowClientFrameRoutingIds(
      blink::StorageKey::CreateFirstParty(origin));
}

}  // namespace

// 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_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);
  }
  return quota_client_types;
}

// 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 std::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,
      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_;
  std::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)
      network::mojom::DeviceBoundSessionManager* device_bound_session_manager,
      KeepAliveURLLoaderService* keep_alive_url_loader_service,
      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.
  // LINT.IfChange(TracingDataType)
  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,
    kCdmStorage = 14,
    kDeviceBoundSessions = 15,
    kMaxValue = kDeviceBoundSessions,
  };
  // LINT.ThenChange(//tools/metrics/histograms/metadata/history/enums.xml:StoragePartitionRemoverTasks)

  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() ? std::nullopt
                                        : std::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);
    // TODO(https://crbug.com/423472677): Group multiple cookie access details
    // with the same RenderFrameHost. This UMA metrics is to decide whether to
    // optimize this method or not.
    base::UmaHistogramCounts1M(
        "Cookie.OnCookiesAccessed.BatchSize.CookieAccessObserver",
        details_vector.size());
    std::optional<base::ElapsedTimer> timer;
    if (base::ShouldRecordSubsampledMetric(0.01)) {
      timer.emplace();
    }
    for (auto& details : details_vector) {
      for (GlobalRenderFrameHostId frame_id : GetRoutingIdsForOrigin(
               storage_partition_, url::Origin::Create(details->url))) {
        if (RenderFrameHostImpl* rfh = RenderFrameHostImpl::FromID(frame_id)) {
          std::vector<network::mojom::CookieAccessDetailsPtr> details_list;
          details_list.reserve(1);
          details_list.push_back(mojo::Clone(details));
          rfh->NotifyCookiesAccessed(
              std::move(details_list),
              CookieAccessDetails::Source::kNonNavigation);
        }
      }
    }
    if (timer) {
      base::UmaHistogramCustomMicrosecondsTimes(
          "Browser.CookieAccessObserver.StoragePartitionImpl.Duration."
          "Subsampled",
          timer->Elapsed(), base::Microseconds(1), base::Seconds(1), 100);
    }
  }

  // `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);

    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;
    }

    for (GlobalRenderFrameHostId frame_id :
         GetRoutingIdsForOrigin(storage_partition_, origin)) {
      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);
    for (GlobalRenderFrameHostId frame_id : GetRoutingIdsForOrigin(
             storage_partition_, details->isolation_key.frame_origin())) {
      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_;
};

class StoragePartitionImpl::ServiceWorkerDeviceBoundSessionAccessObserver
    : public network::mojom::DeviceBoundSessionAccessObserver {
 public:
  explicit ServiceWorkerDeviceBoundSessionAccessObserver(
      StoragePartitionImpl* storage_partition)
      : storage_partition_(storage_partition) {}

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

  void OnDeviceBoundSessionAccessed(
      const net::device_bound_sessions::SessionAccess& access) override {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    for (GlobalRenderFrameHostId frame_id : GetRoutingIdsForOrigin(
             storage_partition_,
             url::Origin::Create(access.session_key.site.GetURL()))) {
      if (RenderFrameHostImpl* rfh = RenderFrameHostImpl::FromID(frame_id)) {
        rfh->OnDeviceBoundSessionAccessed(access);
      }
    }
  }

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

struct StoragePartitionImpl::NetworkContextOwner {
  mojo::Remote<network::mojom::NetworkContext> network_context;
};

StoragePartitionImpl::StoragePartitionImpl(
    BrowserContext* browser_context,
    const StoragePartitionConfig& config,
    const base::FilePath& partition_path,
    const base::FilePath& relative_partition_path,
    storage::SpecialStoragePolicy* special_storage_policy)
    : performance_scenarios::MatchingScenarioObserver(
          performance_scenarios::kDefaultIdleScenarios),
      browser_context_(browser_context),
      partition_path_(partition_path),
      config_(config),
      relative_partition_path_(relative_partition_path),
      special_storage_policy_(special_storage_policy),
      network_context_owner_(std::make_unique<NetworkContextOwner>()),
      deletion_helpers_running_(0) {
#if BUILDFLAG(ENABLE_DISK_CACHE_SQL_BACKEND)
  // To run a database checkpoint when the browser is idle, the SQL disk cache
  // uses PerformanceScenarioObserverList to detect the idle state.
  if (base::FeatureList::IsEnabled(
          net::features::kDiskCacheBackendExperiment) &&
      net::features::kDiskCacheBackendParam.Get() ==
          net::features::DiskCacheBackend::kSql) {
    // `observer_list` may be null in tests.
    if (auto observer_list =
            performance_scenarios::PerformanceScenarioObserverList::GetForScope(
                performance_scenarios::ScenarioScope::kGlobal)) {
      performance_scenario_observation_.Observe(observer_list.get());
    }
  }
#endif  // ENABLE_DISK_CACHE_SQL_BACKEND
}

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

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

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

  if (GetServiceWorkerContext()) {
    GetServiceWorkerContext()->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

  // Shut down service worker and shared worker machinery because these can keep
  // RenderProcessHosts and SiteInstances alive, and the codebase assumes these
  // are destroyed before the BrowserContext is destroyed.
  GetServiceWorkerContext()->Shutdown();
  GetSharedWorkerService()->Shutdown();

  // 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();
  }

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

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

void StoragePartitionImpl::RegisterKeepAliveHandle(
    mojo::PendingReceiver<blink::mojom::NavigationStateKeepAliveHandle>
        receiver,
    std::unique_ptr<NavigationStateKeepAlive> handle) {
  navigation_state_keep_alive_map_.erase(handle->frame_token());
  navigation_state_keep_alive_map_.insert(
      std::make_pair(handle->frame_token(), handle.get()));

  keep_alive_handles_receiver_set_.Add(std::move(handle), std::move(receiver));
}

void StoragePartitionImpl::RevokeNetworkForNoncesInNetworkContext(
    const std::map<base::UnguessableToken, std::set<GURL>>& nonces_to_urls,
    base::OnceClosure callback) {
  std::vector<network::mojom::NonceAndAllowlistedUrlsPtr> dest_vector;
  for (const auto& pair : nonces_to_urls) {
    // Create a new Mojo struct pointer for each map entry.
    auto nonce_and_urls = network::mojom::NonceAndAllowlistedUrls::New();
    nonce_and_urls->nonce = pair.first;
    nonce_and_urls->allowlisted_urls.assign(pair.second.begin(),
                                            pair.second.end());
    dest_vector.push_back(std::move(nonce_and_urls));
  }
  GetNetworkContext()->RevokeNetworkForNonces(std::move(dest_vector),
                                              std::move(callback));

  // Save nonces and allowlisted URLs in `StoragePartitionImpl`. When there is a
  // crash of `NetworkService`, the network revocation nonces of
  // `NetworkContext` will be restored using this.
  network_revocation_nonces_.insert(nonces_to_urls.begin(),
                                    nonces_to_urls.end());
}

void StoragePartitionImpl::ClearNoncesInNetworkContextAfterDelay(
    const std::vector<base::UnguessableToken>& nonces) {
  GetUIThreadTaskRunner({})->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(
          &StoragePartitionImpl::ClearNoncesInNetworkContextAfterDelayCallback,
          weak_factory_.GetWeakPtr(), nonces),
      clear_nonces_in_network_context_delay_);
}

void StoragePartitionImpl::ClearNoncesInNetworkContextAfterDelayCallback(
    const std::vector<base::UnguessableToken>& nonces) {
  GetNetworkContext()->ClearNonces(nonces);

  for (const auto& nonce : nonces) {
    network_revocation_nonces_.erase(nonce);
  }

  clear_nonces_in_network_context_callback_for_testing_.Run();
}

void StoragePartitionImpl::RemoveKeepAliveHandleFromMap(
    blink::LocalFrameToken frame_token,
    NavigationStateKeepAlive* keep_alive) {
  // The NavigationStateKeepAlive associated with `frame_token` may have
  // changed. Make sure the specified one is removed from the map.
  auto it = navigation_state_keep_alive_map_.find(frame_token);
  if (it != navigation_state_keep_alive_map_.end() &&
      it->second == keep_alive) {
    navigation_state_keep_alive_map_.erase(it);
  }
}

NavigationStateKeepAlive* StoragePartitionImpl::GetNavigationStateKeepAlive(
    blink::LocalFrameToken frame_token) {
  auto it = navigation_state_keep_alive_map_.find(frame_token);
  if (it == navigation_state_keep_alive_map_.end()) {
    return nullptr;
  }
  return it->second;
}

// 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);

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

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

  shared_storage_runtime_manager_ =
      std::make_unique<SharedStorageRuntimeManager>(*this);

  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<indexed_db::IndexedDBControlWrapper>(
          path, browser_context_->GetSpecialStoragePolicy(),
          quota_manager_proxy,
          ChromeBlobStorageContext::GetRemoteFor(browser_context_),
          std::move(file_system_access_context), GetIOThreadTaskRunner({}));

  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>();

  shared_url_loader_factory_for_browser_process_ = std::make_unique<
      ReconnectableURLLoaderFactoryForIOThreadWrapper>(base::BindRepeating(
      &StoragePartitionImpl::CreateURLLoaderFactoryForBrowserProcessInternal,
      GetWeakPtr()));
  shared_url_loader_factory_for_browser_process_->factory_for_io_thread()
      ->Initialize();

  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);

  blob_registry_ = BlobRegistryWrapper::Create(blob_context);

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

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

  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(network::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(),
        base::BindRepeating(&BrowserContext::GetKAnonymityServiceDelegate,
                            // This use of Unretained is safe since the browser
                            // context owns this storage partition.
                            base::Unretained(browser_context_)));
  }

  // The Topics API is not available in Incognito mode.
  if (!is_in_memory() &&
      base::FeatureList::IsEnabled(network::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();

  aggregation_service_ =
      std::make_unique<AggregationServiceImpl>(is_in_memory(), path, this);

#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
  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));
  }
#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)

  if (base::FeatureList::IsEnabled(network::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_);
    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);
  }
}

void StoragePartitionImpl::ResetSessionStorageConnections() {
  for (const auto& client : dom_storage_clients_) {
    client.second->ResetSessionStorageConnections();
  }
}

void StoragePartitionImpl::ResetLocalStorageConnections() {
  for (const auto& client : dom_storage_clients_) {
    client.second->ResetLocalStorageConnections();
  }
}

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

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

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

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

cert_verifier::mojom::CertVerifierServiceUpdater*
StoragePartitionImpl::GetCertVerifierServiceUpdater() {
  DCHECK(initialized_);
  if (!cert_verifier_service_updater_.is_bound()) {
    InitNetworkContext();
  }
  return cert_verifier_service_updater_.get();
}

scoped_refptr<network::SharedURLLoaderFactory>
StoragePartitionImpl::GetURLLoaderFactoryForBrowserProcess() {
  CHECK(shared_url_loader_factory_for_browser_process_);
  return shared_url_loader_factory_for_browser_process_->factory();
}

std::unique_ptr<network::PendingSharedURLLoaderFactory>
StoragePartitionImpl::GetURLLoaderFactoryForBrowserProcessIOThread() {
  CHECK(shared_url_loader_factory_for_browser_process_);
  return shared_url_loader_factory_for_browser_process_->factory_for_io_thread()
      ->CloneForIOThread();
}

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,
    net::CookieSettingOverrides devtools_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, devtools_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();
}

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

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

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

SharedStorageRuntimeManager*
StoragePartitionImpl::GetSharedStorageRuntimeManager() {
  DCHECK(initialized_);
  return shared_storage_runtime_manager_.get();
}

storage::mojom::IndexedDBControl& StoragePartitionImpl::GetIndexedDBControl() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  return indexed_db_control_wrapper_->GetIndexedDBControl();
}

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)
CdmStorageDataModel* StoragePartitionImpl::GetCdmStorageDataModel() {
  DCHECK(initialized_);
  return cdm_storage_manager_.get();
}
#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)

network::mojom::DeviceBoundSessionManager*
StoragePartitionImpl::GetDeviceBoundSessionManager() {
  DCHECK(initialized_);
#if BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS)
  if (!device_bound_session_manager_ ||
      !device_bound_session_manager_.is_connected()) {
    // Reset `device_bound_session_manager_` before binding it again.
    device_bound_session_manager_.reset();
    GetNetworkContext()->GetDeviceBoundSessionManager(
        device_bound_session_manager_.BindNewPipeAndPassReceiver());
  }

  return device_bound_session_manager_.get();
#else
  return nullptr;
#endif  // BUILDFLAG(ENABLE_DEVICE_BOUND_SESSIONS)
}

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();
}

void StoragePartitionImpl::DeleteStaleSessionData() {
  GetDOMStorageContext()->StartScavengingUnusedSessionStorage();
  // We need to delay deleting stale session cookies until after the cookie db
  // has initialized, otherwise we will bypass lazy loading and block.
  // See crbug.com/40285083 for more info.
  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  GetUIThreadTaskRunner({})->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(
          &StoragePartitionImpl::DeleteStaleSessionOnlyCookiesAfterDelay,
          weak_factory_.GetWeakPtr()),
      delete_stale_session_only_cookies_delay_);
}

void StoragePartitionImpl::DeleteStaleSessionOnlyCookiesAfterDelay() {
  GetCookieManagerForBrowserProcess()->DeleteStaleSessionOnlyCookies(
      base::BindOnce([](const uint32_t num_deleted) {
        base::UmaHistogramCounts10M(
            "Cookie.StaleSessionCookiesDeletedOnStartup", num_deleted);
      }));
}

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 std::optional<base::UnguessableToken>& window_id,
    int32_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();
  std::optional<bool> is_primary_main_frame_navigation;
  std::optional<bool> is_navigation_request;

  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(crbug.com/40194275): 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* service_worker_client =
          service_worker_context_->context()
              ->service_worker_client_owner()
              .GetServiceWorkerClientByWindowId(*window_id);
      if (service_worker_client) {
        if (service_worker_client->GetRenderFrameHostId()) {
          // Use ServiceWorkerClient's GlobalRenderFrameHostId when the
          // navigation commit has already started.
          GlobalRenderFrameHostId render_frame_host_id =
              service_worker_client->GetRenderFrameHostId();
          context = URLLoaderNetworkContext::CreateForRenderFrameHost(
              render_frame_host_id);

          // Only the request for a sub resource intercepted by a service worker
          // reaches here.
          is_primary_main_frame_navigation = false;
          is_navigation_request = false;
        } else if (service_worker_client->is_initiated_by_prefetch()) {
          // Do not process auth requests associated with prefetching clients
          // because there are no corresponding Window yet.
          // `is_initiated_by_prefetch()` can be true here (and similarly at
          // `OnCertificateRequested()`) e.g. when a speculation rules prefetch
          // request is intercepted by a ServiceWorker fetch handler and then
          // is fetched as a ServiceWorker subresource via
          // `event.respondWith(fetch(event.request))`.
          static_cast<mojo::Remote<network::mojom::AuthChallengeResponder>>(
              std::move(auth_challenge_responder))
              ->OnAuthCredentials(std::nullopt);
          return;
        } else if (NavigationRequest* ongoing_navigation =
                       service_worker_client
                           ->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(crbug.com/40784852): 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_navigation.has_value()) {
    is_primary_main_frame_navigation = context.IsPrimaryMainFrameRequest();
  }
  if (!is_navigation_request.has_value()) {
    is_navigation_request = context.IsNavigationRequestContext();
  }
  int process_id = network::mojom::kBrowserProcessId;
  if (context.type() == ContextType::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,
    // later logic will call 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(crbug.com/40224422): 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;
      }
    }
  } else if (context.type() == ContextType::kSharedOrServiceWorkerContext) {
    process_id = context.process_id();
  }

  FrameTreeNodeId frame_tree_node_id;
  if (auto* navigation_or_document = context.navigation_or_document()) {
    if (auto* frame_tree_node = navigation_or_document->GetFrameTreeNode()) {
      frame_tree_node_id = frame_tree_node->frame_tree_node_id();
    }
  }

  WebContents* current_web_contents = context.GetWebContents();
  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.GetScheme(),
                                      last_committed_url.GetHost(),
                                      last_committed_url.IntPort())) {
            BackForwardCacheCanStoreDocumentResult flattened_reasons;
            flattened_reasons.No(BackForwardCacheMetrics::NotRestoredReason::
                                     kCacheControlNoStore);
            flattened_reasons.No(
                BackForwardCacheMetrics::NotRestoredReason::kHTTPAuthRequired);
            rfh->EvictFromBackForwardCacheWithFlattenedReasons(
                flattened_reasons);
          }
        }
      }
    }
  }

  new LoginHandlerDelegate(
      std::move(auth_challenge_responder), current_web_contents,
      browser_context_, auth_info, *is_primary_main_frame_navigation,
      *is_navigation_request, process_id, request_id, url, head_headers,
      first_auth_attempt, frame_tree_node_id);  // deletes self
}

void StoragePartitionImpl::OnLocalNetworkAccessPermissionRequired(
    OnLocalNetworkAccessPermissionRequiredCallback callback) {
  if (!base::FeatureList::IsEnabled(
          network::features::kLocalNetworkAccessChecks) &&
      !network::features::kLocalNetworkAccessChecksWarn.Get()) {
    // If LNA checks are not enabled, just allow the request by default.
    std::move(callback).Run(true);
    return;
  }

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

  // Three different cases are handled here depending on the request context:
  //   1. Document context (ContextType::kRenderFrameHostContext) covers fetch()
  //      and subresource requests. These should check for existing permission
  //      state, and if the state is ASK trigger the permission prompt. These
  //      should also handle being delegated into subframe documents.
  //   2. Navigation context (ContextType::kNavigationRequestContext) covers
  //      all navigations. If the navigation is in a subframe, these should
  //      check for existing permission state, and if the state is ASK trigger
  //      the permission prompt. Nested subframes should be allowed iff
  //      permission policy delegated the permission into the embedding frame.
  //   3. Worker context (ContextType::kSharedOrServiceWorkerContext) covers
  //      requests from service workers and shared workers. These may not have
  //      an existing document around. These should check for the permission
  //      state, but NOT trigger the permission prompt.

  // Currently requesting the Local Network Access permission is restricted to
  // subresource requests and subframe navigation requests.

  // Handle document (Case 1) and navigation (Case 2) contexts.
  if (context.navigation_or_document()) {
    RenderFrameHost* rfh = nullptr;
    if (context.navigation_or_document()->GetDocument()) {
      // Get the document that is making the request.
      rfh = context.navigation_or_document()->GetDocument();
    } else if (context.navigation_or_document()->GetNavigationRequest()) {
      // Currently the LNA permission only applies to subframe navigations.
      // See content/browser/renderer_host/private_network_access_util.cc for
      // current feature state to policy mapping logic.
      //
      // For other types of navigation, we either default-allow or default-block
      // local network requests:
      //  - Primary main frame: default-allow.
      //  - Guest view main frame: default-allow.
      //  - Prerender: default-block.
      //  - Fenced frame: default-block. (See crbug.com/409303581.)
      auto* request = context.navigation_or_document()->GetNavigationRequest();
      switch (request->GetNavigatingFrameType()) {
        case FrameType::kPrimaryMainFrame:
        case FrameType::kGuestMainFrame:
          std::move(callback).Run(true);
          return;
        case FrameType::kFencedFrameRoot:
        case FrameType::kPrerenderMainFrame:
          std::move(callback).Run(false);
          return;
        case FrameType::kSubframe:
          // Get the document that initiated the navigation. Can be nullptr if
          // the initiator has gone away, in which case we should just block the
          // navigation.
          //
          // TODO(crbug.com/450007796): Figure out why this sometimes returns
          // the parent frame instead of the iframe that is being navigated.
          RenderFrameHost* initiating_rfh =
              request->GetInitiatorFrameToken().has_value()
                  ? RenderFrameHost::FromFrameToken(
                        content::GlobalRenderFrameHostToken(
                            request->GetInitiatorProcessId(),
                            request->GetInitiatorFrameToken().value()))
                  : nullptr;

          // We additionally check that the initiator is the current frame or a
          // frame ancestor of the frame that is navigating, so that we don't
          // try to pop up a permission prompt on a different tab/window than
          // the one where the navigation is occurring.
          RenderFrameHostImpl* current_frame =
              request->frame_tree_node()->current_frame_host();
          while (current_frame) {
            if (current_frame == initiating_rfh) {
              rfh = initiating_rfh;
              break;
            }
            current_frame = current_frame->GetParent();
          }
          break;
      }
    }
    if (!rfh) {
      std::move(callback).Run(false);
      return;
    }

    PermissionController& permission_controller =
        CHECK_DEREF(browser_context_->GetPermissionController());
    auto status = permission_controller.GetPermissionStatusForCurrentDocument(
        content::PermissionDescriptorUtil::
            CreatePermissionDescriptorForPermissionType(
                blink::PermissionType::LOCAL_NETWORK_ACCESS),
        rfh);
    if (status == blink::mojom::PermissionStatus::GRANTED) {
      std::move(callback).Run(true);
      return;
    } else if (status == blink::mojom::PermissionStatus::DENIED) {
      std::move(callback).Run(false);
      return;
    } else {
      // PermissionStatus is ASK, so request the permission. Converts the result
      // into a boolean to pass back to `callback`, capturing whether the
      // permission is granted or not.
      permission_controller.RequestPermissionFromCurrentDocument(
          rfh,
          PermissionRequestDescription(
              content::PermissionDescriptorUtil::
                  CreatePermissionDescriptorForPermissionType(
                      blink::PermissionType::LOCAL_NETWORK_ACCESS)),
          base::BindOnce(
              [](OnLocalNetworkAccessPermissionRequiredCallback cb,
                 PermissionResult permission_result) {
                std::move(cb).Run(permission_result.status ==
                                  blink::mojom::PermissionStatus::GRANTED);
              },
              std::move(callback)));
      return;
    }
  } else if (context.type() == ContextType::kSharedOrServiceWorkerContext) {
    // TODO(crbug.com/404887282): Plumb the `frame_window_id` of the worker,
    // if it exists, to allow this to identify the hosting frame of the worker,
    // when available. This would allow us to additionally _request_ the
    // permission when a fetch that happens to go through a service worker would
    // trigger this check. This is beneficial for developers as they can use
    // caching service workers "as expected" without needing to re-engineer
    // their code to do a special "non-cached request" just to trigger the
    // permission prompt. The `frame_window_id` approach is used by other
    // methods in this file, such as OnCertificateRequested(), which require UI
    // dialogs to handle the event. This may also be useful for handling
    // other types of Workers that always have an associated frame (such as
    // Dedicated Worker).

    // If there is no associated worker origin, there is nothing that can be
    // granted a permission, so just deny the permission request. This can
    // potentially happen for things like workers loaded from data: URLs, which
    // are opaque (but workers loaded from blob: URLs should have the origin
    // which created the blob: URL).
    // TODO(crbug.com/404887282): Revisit if opaque origins support is needed.
    CHECK(context.worker_origin());
    if (context.worker_origin()->opaque()) {
      std::move(callback).Run(false);
      return;
    }

    PermissionController& permission_controller =
        CHECK_DEREF(browser_context_->GetPermissionController());
    auto status = permission_controller.GetPermissionStatusForWorker(
        content::PermissionDescriptorUtil::
            CreatePermissionDescriptorForPermissionType(
                blink::PermissionType::LOCAL_NETWORK_ACCESS),
        content::RenderProcessHost::FromID(context.process_id()),
        context.worker_origin().value());
    std::move(callback).Run(status == blink::mojom::PermissionStatus::GRANTED);
    return;
  }

  // Otherwise default to denying local network access.
  std::move(callback).Run(false);
  return;
}

void StoragePartitionImpl::OnCertificateRequested(
    const std::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(crbug.com/40194275): 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* service_worker_client =
          service_worker_context_->context()
              ->service_worker_client_owner()
              .GetServiceWorkerClientByWindowId(*window_id);
      if (service_worker_client) {
        if (service_worker_client->GetRenderFrameHostId()) {
          // Use ServiceWorkerClient's GlobalRenderFrameHostId when the
          // navigation commit has already started.
          GlobalRenderFrameHostId render_frame_host_id =
              service_worker_client->GetRenderFrameHostId();
          context = URLLoaderNetworkContext::CreateForRenderFrameHost(
              render_frame_host_id);
        } else if (service_worker_client->is_initiated_by_prefetch()) {
          // Do not process certification requests associated with prefetching
          // clients because there are no corresponding Window yet. See also the
          // comment at `OnAuthRequired()` for when `is_initiated_by_prefetch()`
          // can be true here.
          CallCancelRequest(std::move(cert_responder));
          return;
        } else if (NavigationRequest* ongoing_navigation =
                       service_worker_client
                           ->GetOngoingNavigationRequestBeforeCommit(
                               base::PassKey<StoragePartitionImpl>())) {
          // This certification request is for an ongoing navigation.
          // Overwrite the context; set `type` to kNavigationRequestContext.
          // TODO(crbug.com/40784852): 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;
  }

  base::WeakPtr<WebContents> web_contents_weak;
  int process_id = network::mojom::kInvalidProcessId;
  if (context.type() == ContextType::kSharedOrServiceWorkerContext) {
    process_id = context.process_id();
  } else {
    WebContents* web_contents = context.GetWebContents();
    // The WebContents is already invalid. Bail.
    if (!web_contents) {
      CallCancelRequest(std::move(cert_responder));
      return;
    }
    CHECK_EQ(web_contents->GetBrowserContext(), browser_context_.get());
    web_contents_weak = web_contents->GetWeakPtr();

    if (context.navigation_or_document()) {
      auto* render_frame_host = context.navigation_or_document()->GetDocument();
      if (render_frame_host) {
        process_id = render_frame_host->GetProcess()->GetDeprecatedID();
      }
    }
  }

  // SSLClientAuthDelegate handles its own lifetime.
  new SSLClientAuthDelegate(std::move(cert_responder), browser_context(),
                            process_id, web_contents_weak, 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 = context.IsPrimaryMainFrameRequest();
  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 =
      url_loader_network_observers_.current_context().GetWebContents();
  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) {
  GlobalRenderFrameHostId render_frame_host_id =
      GetRenderFrameHostIdFromNetworkContext();
  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::SharedStorageModifierMethodWithOptionsPtr>
        methods_with_options,
    const std::optional<std::string>& with_lock,
    OnSharedStorageHeaderReceivedCallback callback) {
  if (!shared_storage_header_observer_) {
    std::move(callback).Run();
    return;
  }

  // Currently, shared-storage-writable headers aren't available for requests
  // initiated by service workers, so `navigation_or_document` should be
  // non-null.
  //
  // TODO(cammie): If we handle the service worker case by allowing service
  // workers to initiate shared-storage-writable requests, the assumption that
  // `navigation_or_document` must be non-null may become incorrect.
  auto* navigation_or_document =
      url_loader_network_observers_.current_context().navigation_or_document();
  DCHECK(navigation_or_document);

  shared_storage_header_observer_->HeaderReceived(
      request_origin, url_loader_network_observers_.current_context().type(),
      navigation_or_document, std::move(methods_with_options), with_lock,
      std::move(callback), mojo::GetBadMessageCallback(), /*can_defer=*/true);
}

void StoragePartitionImpl::OnAdAuctionEventRecordHeaderReceived(
    network::AdAuctionEventRecord event_record,
    const std::optional<url::Origin>& top_frame_origin) {
  DCHECK(browser_context());
  interest_group_manager_->RecordViewClick(
      *browser_context(),
      url_loader_network_observers_.current_context().navigation_or_document(),
      top_frame_origin, std::move(event_record));
}

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

void StoragePartitionImpl::OnWebSocketConnectedToPrivateNetwork(
    const GURL& request_url,
    network::mojom::IPAddressSpace ip_address_space) {
  RenderFrameHostImpl* render_frame_host_impl =
      RenderFrameHostImpl::FromID(GetRenderFrameHostIdFromNetworkContext());

  if (render_frame_host_impl &&
      network::IsLessPublicAddressSpace(
          ip_address_space, render_frame_host_impl->BuildClientSecurityState()
                                ->ip_address_space)) {
    GetContentClient()->browser()->LogWebFeatureForCurrentPage(
        render_frame_host_impl,
        blink::mojom::WebFeature::kPrivateNetworkAccessWebSocketConnected);

    // Log a UseCounter for potential LNA breakage, where we cannot auto-detect
    // a mixed content bypass situation. This is similar to the check below in
    // StoragePartitionImpl::OnUrlLoaderConnectedToPrivateNetwork.
    if (!network::IsUrlPotentiallyTrustworthy(request_url) &&
        !request_url.HostIsIPAddress() && !request_url.DomainIs("local")) {
      GetContentClient()->browser()->LogWebFeatureForCurrentPage(
          render_frame_host_impl,
          blink::mojom::WebFeature::
              kLocalNetworkAccessWebSocketResourceNotKnownPrivate);
    }
  }
}

void StoragePartitionImpl::OnUrlLoaderConnectedToPrivateNetwork(
    const GURL& request_url,
    network::mojom::IPAddressSpace response_address_space,
    network::mojom::IPAddressSpace client_address_space,
    network::mojom::IPAddressSpace target_address_space) {
  RenderFrameHostImpl* render_frame_host_impl =
      RenderFrameHostImpl::FromID(GetRenderFrameHostIdFromNetworkContext());
  if (!render_frame_host_impl) {
    return;
  }
  // Log a UseCounter for potential PNA 2.0 breakage. We are interested in the
  // case where post-PNA 2.0 this request would fail due to mixed content
  // blocking:
  // 1. The request was to a private or local address space,
  // 2. The request was from non-secure context,
  // 3. The request was to a URL that is not potentially trustworthy,
  // 4. The request is to a less public address space than the client making the
  //   request, and
  // 5. The request was _not_ a priori private. We a priori know a request is
  //   private (and thus can trigger permission prompts _before_ mixed content
  //   checks) if the target address space is specified, if the request is to a
  //   `.local` domain, or if the request is to a private IP address literal.
  //
  // (1) is checked by the caller in the network service. (2) is implied because
  // if it was from a secure context then the request to a not potentially
  // trustworthy URL would have been blocked as mixed content. (3-5) are checked
  // below.
  //
  // This may be called multiple times over the lifetime of resource load (due
  // to redirect hops), as we want to consider every redirect hop for this
  // metric as breakage may occur at the initial request or at any hop in the
  // redirect chain. This is logged as a UseCounter for the current page, which
  // "deduplicates" these repeated calls.
  if (!network::IsUrlPotentiallyTrustworthy(request_url) &&
      network::IsLessPublicAddressSpace(response_address_space,
                                        client_address_space) &&
      // Not a priori known to be private.
      target_address_space == network::mojom::IPAddressSpace::kUnknown &&
      !request_url.HostIsIPAddress() && !request_url.DomainIs("local")) {
    GetContentClient()->browser()->LogWebFeatureForCurrentPage(
        render_frame_host_impl,
        blink::mojom::WebFeature::
            kPrivateNetworkAccessInsecureResourceNotKnownPrivate);
  }
}

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::CreateURLLoaderNetworkObserverForServiceOrSharedWorker(
    int process_id,
    const url::Origin& worker_origin) {
  mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver> remote;
  url_loader_network_observers_.Add(
      this, remote.InitWithNewPipeAndPassReceiver(),
      URLLoaderNetworkContext(process_id, worker_origin));
  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 =
      CHECK_DEREF(browser_context_->GetPermissionController());

  std::vector<url::Origin> origins_out;
  for (auto& origin : origins) {
    bool allowed = permission_controller
                       .GetPermissionResultForOriginWithoutContext(
                           content::PermissionDescriptorUtil::
                               CreatePermissionDescriptorForPermissionType(
                                   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 =
      CHECK_DEREF(browser_context_->GetPermissionController());
  std::move(callback).Run(
      permission_controller
          .GetPermissionResultForOriginWithoutContext(
              content::PermissionDescriptorUtil::
                  CreatePermissionDescriptorForPermissionType(
                      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 std::optional<net::CookiePartitionKey>& cookie_partition_key,
    bool partitioned_state_allowed_only,
    OnClearSiteDataCallback callback) {
  DCHECK(initialized_);

  base::WeakPtr<WebContents> weak_web_contents;
  WebContents* web_contents =
      url_loader_network_observers_.current_context().GetWebContents();
  if (web_contents) {
    weak_web_contents = web_contents->GetWeakPtr();
    GetContentClient()->browser()->LogWebFeatureForCurrentPage(
        web_contents->GetPrimaryMainFrame(),
        blink::mojom::WebFeature::kClearSiteData);
  }

  std::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()->GetWeakPtr(), weak_web_contents, 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_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)
      GetDeviceBoundSessionManager(), GetKeepAliveURLLoaderService(),
      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 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(
        begin, end,
        base::BindOnce(&QuotaManagedDataDeletionHelper::ClearBucketsOnIOThread,
                       base::Unretained(this), base::RetainedRef(quota_manager),
                       special_storage_policy, storage_key_matcher,
                       perform_storage_cleanup, decrement_callback));
  }

  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,
        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_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_BEGIN("browsing_data", "StoragePartitionImpl",
                    perfetto::NamedTrack("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);
  // StoragePartitionImpl
  TRACE_EVENT_END("browsing_data",
                  perfetto::NamedTrack("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)
    network::mojom::DeviceBoundSessionManager* device_bound_session_manager,
    KeepAliveURLLoaderService* keep_alive_url_loader_service,
    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;
    }
    if (!storage_key_origin_empty) {
      cookie_deletion_filter->cookie_partition_key_collection =
          net::CookiePartitionKeyCollection(storage_key.ToCookiePartitionKey());
    }

    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, or to
  // request interest group removal to be extra-thorough w/o asking for
  // interest group removal.
  DCHECK(!(remove_mask_ & REMOVE_DATA_MASK_INTEREST_GROUPS_INTERNAL) ||
         remove_mask_ & REMOVE_DATA_MASK_INTEREST_GROUPS);
  DCHECK(!(remove_mask_ & REMOVE_DATA_MASK_INTEREST_GROUPS_USER_CLEAR) ||
         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,
            remove_mask_ & REMOVE_DATA_MASK_INTEREST_GROUPS_USER_CLEAR,
            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)) {
    auto cdm_deletion_callback = base::BindOnce(
        base::IgnoreArgs<bool>(mojo::WrapCallbackWithDefaultInvokeIfNotRun(
            CreateTaskCompletionClosure(TracingDataType::kCdmStorage))));

    cdm_storage_manager->DeleteData(generic_filter, storage_key, begin, end,
                                    std::move(cdm_deletion_callback));
  }
#endif  // BUILDFLAG(ENABLE_LIBRARY_CDMS)

  if (remove_mask_ & REMOVE_DATA_MASK_INDEXEDDB ||
      remove_mask_ & REMOVE_DATA_MASK_FILE_SYSTEMS ||
      remove_mask_ & REMOVE_DATA_MASK_SERVICE_WORKERS ||
      remove_mask_ & REMOVE_DATA_MASK_CACHE_STORAGE) {
    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/41457196): 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) &&
      // Old behavior: Always execute the code block below.
      // New behavior: If kDisablePartialStorageCleanupForGPUDiskCache == true
      // then consider the behavior of perform_storage_cleanup
      // in executing the code. Note that the feature flag is only relevant
      // when perform_storage_cleanup is false.
      (!base::FeatureList::IsEnabled(
           features::kDisablePartialStorageCleanupForGPUDiskCache) ||
       perform_storage_cleanup)) {
    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/40210305): Consider fine-grained deletion of public keys.
    // TODO(crbug.com/40815455): 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(network::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);
  }

  if (remove_mask_ & REMOVE_DATA_MASK_DEVICE_BOUND_SESSIONS &&
      device_bound_session_manager) {
    device_bound_session_manager->DeleteAllSessions(
        net::device_bound_sessions::DeletionReason::kStoragePartitionCleared,
        begin, end,
        filter_builder ? filter_builder->BuildNetworkServiceFilter() : nullptr,
        mojo::WrapCallbackWithDefaultInvokeIfNotRun(CreateTaskCompletionClosure(
            TracingDataType::kDeviceBoundSessions)));
  }

  if (remove_mask_ & REMOVE_KEEPALIVE_LOADS_ATTEMPTING_RETRY &&
      keep_alive_url_loader_service) {
    keep_alive_url_loader_service->ClearKeepAliveURLLoadersAttemptingRetry();
  }
}

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.GetHost().empty()) {
    deletion_filter->host_name = storage_origin.GetHost();
  }
  // 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() {
  CHECK(initialized_);
  GetNetworkContext()->ResetURLLoaderFactories();
  shared_url_loader_factory_for_browser_process_->factory()->Reset();
  shared_url_loader_factory_for_browser_process_->factory_for_io_thread()
      ->Reset();
}

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() {
  CHECK(initialized_);
  DCHECK(network_context_owner_->network_context);
  network_context_owner_->network_context.FlushForTesting();  // IN-TEST
  shared_url_loader_factory_for_browser_process_->factory()
      ->FlushForTesting();  // IN-TEST
  if (cookie_manager_for_browser_process_) {
    cookie_manager_for_browser_process_.FlushForTesting();  // IN-TEST
  }
}

void StoragePartitionImpl::FlushNetworkInterfaceOnIOThreadForTesting() {
  CHECK(initialized_);
  CHECK(shared_url_loader_factory_for_browser_process_);
  shared_url_loader_factory_for_browser_process_->factory_for_io_thread()
      ->FlushForTesting();  // IN-TEST
}

void StoragePartitionImpl::FlushCertVerifierInterfaceForTesting() {
  DCHECK(initialized_);
  DCHECK(cert_verifier_service_updater_);
  cert_verifier_service_updater_.FlushForTesting();  // IN-TEST
}

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

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

void StoragePartitionImpl::OverrideDeleteStaleSessionOnlyCookiesDelayForTesting(
    const base::TimeDelta& delay) {
  delete_stale_session_only_cookies_delay_ = delay;
}

void StoragePartitionImpl::SetClearNoncesInNetworkContextParamsForTesting(
    const base::TimeDelta& delay,
    base::RepeatingClosure callback) {
  clear_nonces_in_network_context_delay_ = delay;
  clear_nonces_in_network_context_callback_for_testing_ = callback;
}

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

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

std::optional<base::FilePath> StoragePartitionImpl::GetStoragePartitionPath()
    const {
  if (is_in_memory()) {
    return std::nullopt;
  }
  return browser_context_->GetPath().Append(relative_partition_path_);
}

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

void StoragePartitionImpl::BindIndexedDB(
    const storage::BucketLocator& bucket_locator,
    const storage::BucketClientInfo& client_info,
    mojo::PendingRemote<storage::mojom::IndexedDBClientStateChecker>
        client_state_checker_remote,
    mojo::PendingReceiver<blink::mojom::IDBFactory> receiver) {
  indexed_db_control_wrapper_->BindIndexedDB(
      bucket_locator, client_info, std::move(client_state_checker_remote),
      std::move(receiver));
}

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::OverrideSharedStorageRuntimeManagerForTesting(
    std::unique_ptr<SharedStorageRuntimeManager>
        shared_storage_runtime_manager) {
  DCHECK(initialized_);
  shared_storage_runtime_manager_ = std::move(shared_storage_runtime_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::OverrideDeviceBoundSessionManagerForTesting(
    std::unique_ptr<network::mojom::DeviceBoundSessionManager>
        device_bound_session_manager) {
  DCHECK(initialized_);
  mojo::MakeSelfOwnedReceiver(
      std::move(device_bound_session_manager),
      device_bound_session_manager_.BindNewPipeAndPassReceiver());
}

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.";

  cert_verifier_service_updater_.reset();
  context_params->cert_verifier_params = GetCertVerifierParamsWithUpdater(
      std::move(cert_verifier_creation_params),
      cert_verifier_service_updater_.BindNewPipeAndPassReceiver());

  // 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(blink::kPurposeHeaderName);
  context_params->cors_exempt_header_list.push_back(
      GetCorsExemptRequestedWithHeaderName());
  variations::UpdateCorsExemptHeaderForVariations(context_params.get());
  variations::UpdateCorsExemptHeaderForOmniboxAutofocus(context_params.get());
  cors_exempt_header_list_ = context_params->cors_exempt_header_list;

  if (base::FeatureList::IsEnabled(
          network::features::kCompressionDictionaryTransport) &&
      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_);
    }
  }

  network_context_owner_->network_context.reset();
  CreateNetworkContextInNetworkService(
      network_context_owner_->network_context.BindNewPipeAndPassReceiver(),
      std::move(context_params));
  DCHECK(network_context_owner_->network_context);

  // Restore the saved network revocation nonces. This allows network access
  // states to be persisted in case of a `NetworkService` crash.
  std::vector<network::mojom::NonceAndAllowlistedUrlsPtr> dest_vector;
  for (const auto& pair : network_revocation_nonces_) {
    // Create a new Mojo struct pointer for each map entry.
    auto nonce_and_urls = network::mojom::NonceAndAllowlistedUrls::New();
    nonce_and_urls->nonce = pair.first;
    nonce_and_urls->allowlisted_urls.assign(pair.second.begin(),
                                            pair.second.end());
    dest_vector.push_back(std::move(nonce_and_urls));
  }

  network_context_owner_->network_context->RevokeNetworkForNonces(
      std::move(dest_vector), base::NullCallback());

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

network::mojom::URLLoaderFactoryParamsPtr
StoragePartitionImpl::CreateURLLoaderFactoryParams() {
  network::mojom::URLLoaderFactoryParamsPtr params =
      network::mojom::URLLoaderFactoryParams::New();
  // This method is used for browser-process initiated requests for which there
  // is no corresponding RenderProcessHost.
  params->process_id = network::mojom::kBrowserProcessId;
  params->automatically_assign_isolation_info = true;
  params->is_orb_enabled = false;
  params->is_trusted = true;
  // For browser-process initiated requests there is no corresponding service
  // worker origin, so just pass an opaque origin.
  params->url_loader_network_observer =
      CreateURLLoaderNetworkObserverForServiceOrSharedWorker(params->process_id,
                                                             url::Origin());
  params->disable_web_security =
      base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableWebSecurity);
  return params;
}

void StoragePartitionImpl::CreateURLLoaderFactoryForBrowserProcessInternal(
    mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory) {
  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  network::URLLoaderFactoryBuilder factory_builder;
  if (url_loader_factory::GetTestingInterceptor()) {
    url_loader_factory::GetTestingInterceptor().Run(
        network::mojom::kBrowserProcessId, factory_builder);
  }
  *out_factory =
      std::move(factory_builder)
          .Finish<mojo::PendingRemote<network::mojom::URLLoaderFactory>>(
              GetNetworkContext(), CreateURLLoaderFactoryParams());
}

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;
}

mojo::PendingRemote<network::mojom::DeviceBoundSessionAccessObserver>
StoragePartitionImpl::CreateDeviceBoundSessionObserverForServiceWorker() {
  mojo::PendingRemote<network::mojom::DeviceBoundSessionAccessObserver> remote;
  service_worker_device_bound_session_observers_.Add(
      std::make_unique<ServiceWorkerDeviceBoundSessionAccessObserver>(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, std::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, std::nullopt, namespace_id,
                                        std::move(receiver), std::move(handle),
                                        base::DoNothing());
}

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

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

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

GlobalRenderFrameHostId
StoragePartitionImpl::GetRenderFrameHostIdFromNetworkContext() {
  URLLoaderNetworkContext context =
      url_loader_network_observers_.current_context();

  // `navigation_or_document()` can be null for `kSharedOrServiceWorkerContext`.
  RenderFrameHost* 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`.
  return render_frame_host ? render_frame_host->GetGlobalId()
                           : GlobalRenderFrameHostId();
}

void StoragePartitionImpl::IncrementActiveDocumentCount(
    const net::NetworkIsolationKey& nik) {
  if (auto it = active_document_per_nik_count_.find(nik);
      it != active_document_per_nik_count_.end()) {
    it->second++;
    CHECK_GT(it->second, 1);
  } else {
    active_document_per_nik_count_.emplace(nik, 1);
    if (keep_alive_url_loader_service_) {
      keep_alive_url_loader_service_->DidObserveNewlyActiveDocumentWithNIK(nik);
    }
  }
}

void StoragePartitionImpl::DecrementActiveDocumentCount(
    const net::NetworkIsolationKey& nik) {
  auto it = active_document_per_nik_count_.find(nik);
  CHECK(it != active_document_per_nik_count_.end());
  it->second--;
  if (it->second == 0) {
    active_document_per_nik_count_.erase(it);
  }
}

int StoragePartitionImpl::GetActiveDocumentCount(
    const net::NetworkIsolationKey& nik) {
  auto it = active_document_per_nik_count_.find(nik);
  if (it == active_document_per_nik_count_.end()) {
    return 0;
  }
  return it->second;
}

base::UnguessableToken StoragePartitionImpl::GetPartitionUUIDPerStorageKey(
    const blink::StorageKey& storage_key) {
  auto uuid = partition_uuid_per_storage_key_.find(storage_key);
  return uuid == partition_uuid_per_storage_key_.end()
             ? partition_uuid_per_storage_key_[storage_key] =
                   base::UnguessableToken::Create()
             : uuid->second;
}

void StoragePartitionImpl::OnScenarioMatchChanged(
    performance_scenarios::ScenarioScope scope,
    bool matches_pattern) {
  // If the scenario matches `performance_scenarios::kDefaultIdleScenarios` and
  // the network context is available, call `NotifyBrowserIdle()`. It's
  // possible to miss an idle notification if the browser becomes idle before
  // the network context is initialized. This is not a problem because the idle
  // state is also checked when data is committed to the cache, so a checkpoint
  // will eventually be triggered.
  if (matches_pattern && network_context_owner_->network_context.get()) {
    network_context_owner_->network_context->NotifyBrowserIdle();
  }
}

StoragePartitionImpl::URLLoaderNetworkContext::URLLoaderNetworkContext(
    GlobalRenderFrameHostId render_frame_host_id)
    : type_(Type::kRenderFrameHostContext) {
  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(
    int process_id,
    const url::Origin& worker_origin)
    : type_(Type::kSharedOrServiceWorkerContext),
      process_id_(process_id),
      worker_origin_(worker_origin) {}

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(render_frame_host_id);
}

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

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

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

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

  return navigation_or_document()->IsInPrimaryMainFrame();
}

}  // namespace content
