// 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/download/download_manager_impl.h"

#include <iterator>
#include <utility>

#include "base/containers/contains.h"
#include "base/debug/alias.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/i18n/case_conversion.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/histogram_macros.h"
#include "base/observer_list.h"
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/supports_user_data.h"
#include "base/synchronization/lock.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/thread_pool.h"
#include "build/build_config.h"
#include "components/download/database/in_progress/download_entry.h"
#include "components/download/public/common/download_create_info.h"
#include "components/download/public/common/download_danger_type.h"
#include "components/download/public/common/download_features.h"
#include "components/download/public/common/download_file.h"
#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/download/public/common/download_item_factory.h"
#include "components/download/public/common/download_item_impl.h"
#include "components/download/public/common/download_item_rename_handler.h"
#include "components/download/public/common/download_stats.h"
#include "components/download/public/common/download_target_info.h"
#include "components/download/public/common/download_task_runner.h"
#include "components/download/public/common/download_url_parameters.h"
#include "components/download/public/common/download_utils.h"
#include "components/download/public/common/input_stream.h"
#include "components/download/public/common/url_download_handler_factory.h"
#include "content/browser/bad_message.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/data_url_loader_factory.h"
#include "content/browser/devtools/devtools_instrumentation.h"
#include "content/browser/download/embedder_download_data.pb.h"
#include "content/browser/file_system/file_system_url_loader_factory.h"
#include "content/browser/loader/file_url_loader_factory.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/site_info.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/device_service.h"
#include "content/public/browser/disallow_activation_reason.h"
#include "content/public/browser/download_item_utils.h"
#include "content/public/browser/download_manager_delegate.h"
#include "content/public/browser/download_request_utils.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/shared_cors_origin_access_list.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_ui_url_loader_factory.h"
#include "content/public/common/content_client.h"
#include "content/public/common/url_constants.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "net/base/elements_upload_data_stream.h"
#include "net/base/isolation_info.h"
#include "net/base/load_flags.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/base/request_priority.h"
#include "net/base/upload_bytes_element_reader.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/url_loader_factory_builder.h"
#include "services/network/public/cpp/url_util.h"
#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
#include "third_party/blink/public/common/loader/referrer_utils.h"
#include "third_party/blink/public/common/loader/throttling_url_loader.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "url/origin.h"

#if BUILDFLAG(IS_ANDROID)
#include "net/http/http_content_disposition.h"
#endif  // BUILDFLAG(IS_ANDROID)

namespace content {
namespace {
#if BUILDFLAG(IS_ANDROID)
// PDF MIME type.
constexpr char kPdfMimeType[] = "application/pdf";
#endif  // BUILDFLAG(IS_ANDROID)

void DeleteDownloadedFileOnUIThread(const base::FilePath& file_path) {
  if (!file_path.empty()) {
    download::GetDownloadTaskRunner()->PostTask(
        FROM_HERE,
        base::BindOnce(base::IgnoreResult(&download::DeleteDownloadedFile),
                       file_path));
  }
}

StoragePartitionImpl* GetStoragePartitionForConfig(
    BrowserContext* context,
    const StoragePartitionConfig& storage_partition_config) {
  return static_cast<StoragePartitionImpl*>(
      context->GetStoragePartition(storage_partition_config));
}

void OnDownloadStarted(
    download::DownloadItemImpl* download,
    download::DownloadUrlParameters::OnStartedCallback on_started) {
  if (on_started.is_null())
    return;

  if (!download || download->GetState() == download::DownloadItem::CANCELLED) {
    std::move(on_started)
        .Run(nullptr, download::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
  } else {
    std::move(on_started)
        .Run(download, download::DOWNLOAD_INTERRUPT_REASON_NONE);
  }
}

// Creates an interrupted download and calls StartDownload. Can be called on
// any thread.
void CreateInterruptedDownload(
    std::unique_ptr<download::DownloadUrlParameters> params,
    download::DownloadInterruptReason reason,
    base::WeakPtr<DownloadManagerImpl> download_manager) {
  std::unique_ptr<download::DownloadCreateInfo> failed_created_info(
      new download::DownloadCreateInfo(
          base::Time::Now(), base::WrapUnique(new download::DownloadSaveInfo)));
  failed_created_info->url_chain.push_back(params->url());
  failed_created_info->result = reason;
  GetUIThreadTaskRunner({})->PostTask(
      FROM_HERE,
      base::BindOnce(&DownloadManagerImpl::StartDownload, download_manager,
                     std::move(failed_created_info),
                     std::make_unique<download::InputStream>(),
                     std::move(params->callback())));
}

class DownloadItemFactoryImpl : public download::DownloadItemFactory {
 public:
  DownloadItemFactoryImpl() {}
  ~DownloadItemFactoryImpl() override {}

  download::DownloadItemImpl* CreatePersistedItem(
      download::DownloadItemImplDelegate* delegate,
      const std::string& guid,
      uint32_t download_id,
      const base::FilePath& current_path,
      const base::FilePath& target_path,
      const std::vector<GURL>& url_chain,
      const GURL& referrer_url,
      const std::string& serialized_embedder_download_data,
      const GURL& tab_url,
      const GURL& tab_refererr_url,
      const std::optional<url::Origin>& request_initiator,
      const std::string& mime_type,
      const std::string& original_mime_type,
      base::Time start_time,
      base::Time end_time,
      const std::string& etag,
      const std::string& last_modified,
      int64_t received_bytes,
      int64_t total_bytes,
      const std::string& hash,
      download::DownloadItem::DownloadState state,
      download::DownloadDangerType danger_type,
      download::DownloadInterruptReason interrupt_reason,
      bool opened,
      base::Time last_access_time,
      bool transient,
      const std::vector<download::DownloadItem::ReceivedSlice>& received_slices)
      override {
    // For history download only as history don't have auto resumption count
    // saved.
    int auto_resume_count = download::DownloadItemImpl::kMaxAutoResumeAttempts;

    return new download::DownloadItemImpl(
        delegate, guid, download_id, current_path, target_path, url_chain,
        referrer_url, serialized_embedder_download_data, tab_url,
        tab_refererr_url, request_initiator, mime_type, original_mime_type,
        start_time, end_time, etag, last_modified, received_bytes, total_bytes,
        auto_resume_count, hash, state, danger_type, interrupt_reason,
        false /* paused */, false /* allow_metered */, opened, last_access_time,
        transient, received_slices, download::kInvalidRange,
        download::kInvalidRange, nullptr /* download_entry */);
  }

  download::DownloadItemImpl* CreateActiveItem(
      download::DownloadItemImplDelegate* delegate,
      uint32_t download_id,
      const download::DownloadCreateInfo& info) override {
    return new download::DownloadItemImpl(delegate, download_id, info);
  }

  download::DownloadItemImpl* CreateSavePageItem(
      download::DownloadItemImplDelegate* delegate,
      uint32_t download_id,
      const base::FilePath& path,
      const base::FilePath& display_name,
      const GURL& url,
      const std::string& mime_type,
      download::DownloadJob::CancelRequestCallback cancel_request_callback)
      override {
    return new download::DownloadItemImpl(delegate, download_id, path,
                                          display_name, url, mime_type,
                                          std::move(cancel_request_callback));
  }
};

std::unique_ptr<network::PendingSharedURLLoaderFactory>
CreatePendingSharedURLLoaderFactory(StoragePartitionImpl* storage_partition,
                                    RenderFrameHost* rfh) {
  network::URLLoaderFactoryBuilder factory_builder;

  if (rfh) {
    // Allow DevTools to potentially inject itself into `factory_builder`.
    devtools_instrumentation::WillCreateURLLoaderFactoryParams::ForFrame(
        static_cast<RenderFrameHostImpl*>(rfh))
        .Run(/*is_navigation=*/true,
             /*is_download=*/true, factory_builder,
             nullptr /* factory_override */);

    // Also allow the Content embedder to inject itself if it wants to.
    GetContentClient()->browser()->WillCreateURLLoaderFactory(
        rfh->GetSiteInstance()->GetBrowserContext(), rfh,
        rfh->GetProcess()->GetDeprecatedID(),
        ContentBrowserClient::URLLoaderFactoryType::kDownload, url::Origin(),
        net::IsolationInfo(), /*navigation_id=*/std::nullopt,
        ukm::kInvalidSourceIdObj, factory_builder, /*header_client=*/nullptr,
        /*bypass_redirect_checks=*/nullptr, /*disable_secure_dns=*/nullptr,
        /*factory_override=*/nullptr,
        /*navigation_response_task_runner=*/nullptr);
  }

  return std::make_unique<network::PendingSharedURLLoaderFactoryWithBuilder>(
      std::move(factory_builder),
      storage_partition->GetURLLoaderFactoryForBrowserProcessIOThread());
}

void RecordDownloadOpenerType(RenderFrameHost* current,
                              RenderFrameHost* opener) {
  DCHECK(current);
  DCHECK(opener);
  if (!opener->GetLastCommittedURL().SchemeIsHTTPOrHTTPS() ||
      !current->GetLastCommittedURL().SchemeIsHTTPOrHTTPS()) {
    UMA_HISTOGRAM_ENUMERATION("Download.InitiatedByWindowOpener",
                              InitiatedByWindowOpenerType::kNonHTTPOrHTTPS);
    return;
  }
  if (opener->GetLastCommittedOrigin() == current->GetLastCommittedOrigin()) {
    UMA_HISTOGRAM_ENUMERATION("Download.InitiatedByWindowOpener",
                              InitiatedByWindowOpenerType::kSameOrigin);
    return;
  }
  if (net::registry_controlled_domains::SameDomainOrHost(
          opener->GetLastCommittedOrigin(), current->GetLastCommittedOrigin(),
          net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
    UMA_HISTOGRAM_ENUMERATION("Download.InitiatedByWindowOpener",
                              InitiatedByWindowOpenerType::kSameSite);
    return;
  }
  UMA_HISTOGRAM_ENUMERATION("Download.InitiatedByWindowOpener",
                            InitiatedByWindowOpenerType::kCrossOrigin);
}

}  // namespace

DownloadManagerImpl::DownloadManagerImpl(BrowserContext* browser_context)
    : item_factory_(new DownloadItemFactoryImpl()),
      shutdown_needed_(true),
      history_db_initialized_(false),
      in_progress_cache_initialized_(false),
      browser_context_(browser_context),
      delegate_(nullptr),
      in_progress_manager_(
          browser_context_->RetrieveInProgressDownloadManager()),
      next_download_id_(download::DownloadItem::kInvalidId),
      is_history_download_id_retrieved_(false),
      should_persist_new_download_(false),
      disk_access_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
          {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
           base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})) {
  DCHECK(browser_context);

  download::SetIOTaskRunner(GetIOThreadTaskRunner({}));

  if (!in_progress_manager_) {
    auto* proto_db_provider = browser_context->GetDefaultStoragePartition()
                                  ->GetProtoDatabaseProvider();
    in_progress_manager_ =
        std::make_unique<download::InProgressDownloadManager>(
            this, base::FilePath(), proto_db_provider,
            base::BindRepeating(&network::IsUrlPotentiallyTrustworthy),
            base::BindRepeating(&DownloadRequestUtils::IsURLSafe),
            /*wake_lock_provider_binder=*/base::NullCallback());
  } else {
    in_progress_manager_->SetDelegate(this);
    in_progress_manager_->set_download_start_observer(nullptr);
    in_progress_manager_->set_is_origin_secure_cb(
        base::BindRepeating(&network::IsUrlPotentiallyTrustworthy));
  }
}

DownloadManagerImpl::~DownloadManagerImpl() {
  DCHECK(!shutdown_needed_);
}

download::DownloadItemImpl* DownloadManagerImpl::CreateActiveItem(
    uint32_t id,
    const download::DownloadCreateInfo& info) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (base::Contains(downloads_by_guid_, info.guid))
    return nullptr;

  download::DownloadItemImpl* download =
      item_factory_->CreateActiveItem(this, id, info);

  downloads_[id] = base::WrapUnique(download);
  downloads_by_guid_[download->GetGuid()] = download;
  GlobalRenderFrameHostId global_id(info.render_process_id,
                                    info.render_frame_id);
  DownloadItemUtils::AttachInfo(
      download, GetBrowserContext(),
      WebContentsImpl::FromRenderFrameHostID(global_id), global_id);
  if (delegate_) {
    delegate_->AttachExtraInfo(download);
#if BUILDFLAG(IS_ANDROID)
    download->set_is_from_external_app(delegate_->IsFromExternalApp(download));
#endif  // BUILDFLAG(IS_ANDROID)
  }

  return download;
}

void DownloadManagerImpl::GetNextId(GetNextIdCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (IsNextIdInitialized()) {
    std::move(callback).Run(next_download_id_++);
    return;
  }

  id_callbacks_.emplace_back(
      std::make_unique<GetNextIdCallback>(std::move(callback)));
  // If we are first time here, call the delegate to get the next ID from
  // history db.
  if (!is_history_download_id_retrieved_ && id_callbacks_.size() == 1u) {
    if (delegate_) {
      delegate_->GetNextId(
          base::BindOnce(&DownloadManagerImpl::OnHistoryNextIdRetrieved,
                         weak_factory_.GetWeakPtr()));
    } else {
      OnHistoryNextIdRetrieved(download::DownloadItem::kInvalidId);
    }
  }
}

void DownloadManagerImpl::SetNextId(uint32_t next_id) {
  if (next_id > next_download_id_)
    next_download_id_ = next_id;
  if (!IsNextIdInitialized())
    return;

  for (auto& callback : id_callbacks_)
    std::move(*callback).Run(next_download_id_++);
  id_callbacks_.clear();
}

std::string
DownloadManagerImpl::StoragePartitionConfigToSerializedEmbedderDownloadData(
    const StoragePartitionConfig& storage_partition_config) {
  proto::EmbedderDownloadData embedder_download_data;
  proto::StoragePartitionConfig* config_proto =
      embedder_download_data.mutable_storage_partition_config();
  config_proto->set_partition_domain(
      storage_partition_config.partition_domain());
  config_proto->set_partition_name(storage_partition_config.partition_name());
  config_proto->set_in_memory(storage_partition_config.in_memory());

  switch (
      storage_partition_config.fallback_to_partition_domain_for_blob_urls()) {
    case StoragePartitionConfig::FallbackMode::kNone:
      config_proto->set_fallback_mode(
          proto::StoragePartitionConfig_FallbackMode_kNone);
      break;
    case StoragePartitionConfig::FallbackMode::kFallbackPartitionOnDisk:
      config_proto->set_fallback_mode(
          proto::StoragePartitionConfig_FallbackMode_kPartitionOnDisk);
      break;
    case StoragePartitionConfig::FallbackMode::kFallbackPartitionInMemory:
      config_proto->set_fallback_mode(
          proto::StoragePartitionConfig_FallbackMode_kPartitionInMemory);
      break;
    default:
      config_proto->set_fallback_mode(
          proto::StoragePartitionConfig_FallbackMode_kNone);
  }
  return embedder_download_data.SerializeAsString();
}

StoragePartitionConfig
DownloadManagerImpl::SerializedEmbedderDownloadDataToStoragePartitionConfig(
    const std::string& serialized_embedder_download_data) {
  proto::EmbedderDownloadData embedder_download_data;
  bool success =
      embedder_download_data.ParseFromString(serialized_embedder_download_data);
  DCHECK(success);

  StoragePartitionConfig::FallbackMode fallback_mode;
  switch (embedder_download_data.storage_partition_config().fallback_mode()) {
    case proto::StoragePartitionConfig_FallbackMode_kNone:
      fallback_mode = StoragePartitionConfig::FallbackMode::kNone;
      break;
    case proto::StoragePartitionConfig_FallbackMode_kPartitionOnDisk:
      fallback_mode =
          StoragePartitionConfig::FallbackMode::kFallbackPartitionOnDisk;
      break;
    case proto::StoragePartitionConfig_FallbackMode_kPartitionInMemory:
      fallback_mode =
          StoragePartitionConfig::FallbackMode::kFallbackPartitionInMemory;
      break;
    default:
      fallback_mode = StoragePartitionConfig::FallbackMode::kNone;
      break;
  }

  StoragePartitionConfig config;
  if (embedder_download_data.storage_partition_config()
          .partition_domain()
          .empty()) {
    config = StoragePartitionConfig::CreateDefault(browser_context_);
  } else {
    config = StoragePartitionConfig::Create(
        browser_context_,
        embedder_download_data.storage_partition_config().partition_domain(),
        embedder_download_data.storage_partition_config().partition_name(),
        embedder_download_data.storage_partition_config().in_memory());
  }
  config.set_fallback_to_partition_domain_for_blob_urls(fallback_mode);
  return config;
}

void DownloadManagerImpl::OnHistoryNextIdRetrieved(uint32_t next_id) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  is_history_download_id_retrieved_ = true;
  if (next_id == download::DownloadItem::kInvalidId)
    next_id++;
  else
    should_persist_new_download_ = true;
  SetNextId(next_id);
}

StoragePartitionConfig DownloadManagerImpl::GetStoragePartitionConfigForSiteUrl(
    const GURL& site_url) {
  return SiteInfo::GetStoragePartitionConfigForUrl(browser_context_, site_url);
}

void DownloadManagerImpl::DetermineDownloadTarget(
    download::DownloadItemImpl* item,
    download::DownloadTargetCallback callback) {
  if (!delegate_ || !delegate_->DetermineDownloadTarget(item, &callback)) {
    base::FilePath target_path = item->GetForcedFilePath();
    // TODO(asanka): Determine a useful path if |target_path| is empty.
    download::DownloadTargetInfo target_info;
    target_info.target_path = target_path;
    target_info.intermediate_path = target_path;

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

bool DownloadManagerImpl::ShouldCompleteDownload(
    download::DownloadItemImpl* item,
    base::OnceClosure complete_callback) {
  if (!delegate_ ||
      delegate_->ShouldCompleteDownload(item, std::move(complete_callback))) {
    return true;
  }
  // Otherwise, the delegate has accepted responsibility to run the
  // callback when the download is ready for completion.
  // TODO(qinmin): When returning false, the |complete_callback| should
  // be run by this class eventually. To do so we can't pass ownership
  // to |delegate_| unconditionally.
  return false;
}

bool DownloadManagerImpl::ShouldAutomaticallyOpenFile(
    const GURL& url,
    const base::FilePath& path) {
  if (!delegate_)
    return false;

  return delegate_->ShouldAutomaticallyOpenFile(url, path);
}

bool DownloadManagerImpl::ShouldAutomaticallyOpenFileByPolicy(
    const GURL& url,
    const base::FilePath& path) {
  if (!delegate_)
    return false;

  return delegate_->ShouldAutomaticallyOpenFileByPolicy(url, path);
}

bool DownloadManagerImpl::ShouldOpenDownload(
    download::DownloadItemImpl* item,
    ShouldOpenDownloadCallback callback) {
  if (!delegate_)
    return true;

  // Relies on DownloadItemImplDelegate::ShouldOpenDownloadCallback and
  // DownloadManagerDelegate::DownloadOpenDelayedCallback "just happening"
  // to have the same type :-}.
  return delegate_->ShouldOpenDownload(item, std::move(callback));
}

void DownloadManagerImpl::SetDelegate(DownloadManagerDelegate* delegate) {
  delegate_ = delegate;
}

DownloadManagerDelegate* DownloadManagerImpl::GetDelegate() {
  return delegate_;
}

void DownloadManagerImpl::Shutdown() {
  DVLOG(20) << __func__ << "() shutdown_needed_ = " << shutdown_needed_;
  if (!shutdown_needed_)
    return;
  shutdown_needed_ = false;

  for (auto& observer : observers_)
    observer.ManagerGoingDown(this);
  // TODO(benjhayden): Consider clearing observers_.

  // If there are in-progress downloads, cancel them. This also goes for
  // dangerous downloads which will remain in history if they aren't explicitly
  // accepted or discarded. Canceling will remove the intermediate download
  // file.
  for (const auto& it : downloads_by_guid_) {
    download::DownloadItemImpl* download = it.second;
    if (download->GetState() == download::DownloadItem::IN_PROGRESS) {
      download->Cancel(false);
      if (delegate_) {
        delegate_->OnDownloadCanceledAtShutdown(download);
      }
    }
  }

  downloads_by_guid_.clear();
  downloads_.clear();

  // We'll have nothing more to report to the observers after this point.
  observers_.Clear();

  if (in_progress_manager_)
    in_progress_manager_->ShutDown();

  if (delegate_)
    delegate_->Shutdown();
  delegate_ = nullptr;
}

bool DownloadManagerImpl::InterceptDownload(
    const download::DownloadCreateInfo& info) {
  WebContents* web_contents = WebContentsImpl::FromRenderFrameHostID(
      info.render_process_id, info.render_frame_id);
  if (info.is_new_download &&
      info.result ==
          download::DOWNLOAD_INTERRUPT_REASON_SERVER_CROSS_ORIGIN_REDIRECT) {
    std::vector<GURL> url_chain(info.url_chain);
    GURL url = url_chain.back();
    if ((url.SchemeIsHTTPOrHTTPS() ||
         GetContentClient()->browser()->IsHandledURL(url)) &&
        web_contents) {
      url_chain.pop_back();
      NavigationController::LoadURLParams params(url);
      params.has_user_gesture = info.has_user_gesture;
      params.referrer = Referrer(
          info.referrer_url,
          blink::ReferrerUtils::NetToMojoReferrerPolicy(info.referrer_policy));
      params.redirect_chain = url_chain;
      params.frame_tree_node_id =
          RenderFrameHost::GetFrameTreeNodeIdForRoutingId(
              info.render_process_id, info.render_frame_id);
      params.from_download_cross_origin_redirect = true;
      params.initiator_origin = info.request_initiator;
      params.is_renderer_initiated = info.is_content_initiated;

      // Ensure the method is called from an active document.
      // If inactive documents start download, it can be a security risk.
      // Call ReceiveBadMessage to terminate such a renderer.
      // TODO(crbug.com/40201479): confirm if fenced frames are allowed to start
      // downloads.
      if (!RenderFrameHost::FromID(info.render_process_id, info.render_frame_id)
               ->IsActive()) {
        bad_message::ReceivedBadMessage(
            info.render_process_id,
            bad_message::RFH_INTERECEPT_DOWNLOAD_WHILE_INACTIVE);
        return false;
      }

      web_contents->GetController().LoadURLWithParams(params);
    }
    return true;
  }

  std::string user_agent;
  for (const auto& header : info.request_headers) {
    if (header.first == net::HttpRequestHeaders::kUserAgent) {
      user_agent = header.second;
      break;
    }
  }

  if (delegate_ &&
      delegate_->InterceptDownloadIfApplicable(
          info.url(), user_agent, info.content_disposition, info.mime_type,
          info.request_origin, info.total_bytes, info.transient,
          info.is_content_initiated, web_contents)) {
    DropDownload();
    return true;
  }
  return false;
}

base::FilePath DownloadManagerImpl::GetDefaultDownloadDirectory() {
  base::FilePath default_download_directory;

  if (delegate_ && default_download_directory.empty()) {
    base::FilePath website_save_directory;  // Unused
    delegate_->GetSaveDir(GetBrowserContext(), &website_save_directory,
                          &default_download_directory);
  }

  if (default_download_directory.empty()) {
    // |default_download_directory| can still be empty if ContentBrowserClient
    // returned an empty path for the downloads directory.
    default_download_directory =
        GetContentClient()->browser()->GetDefaultDownloadDirectory();
  }

  return default_download_directory;
}

void DownloadManagerImpl::OnDownloadsInitialized() {
  in_progress_downloads_ = in_progress_manager_->TakeInProgressDownloads();
  uint32_t max_id = download::DownloadItem::kInvalidId;
  for (auto it = in_progress_downloads_.begin();
       it != in_progress_downloads_.end();) {
    download::DownloadItemImpl* download = it->get();
    uint32_t id = download->GetId();
    if (id > max_id)
      max_id = id;

    // Clean up cancelled and non resumable interrupted downloads.
    if (ShouldClearDownloadFromDB(download->GetURL(), download->GetState(),
                                  download->GetLastReason(),
                                  download->GetStartTime())) {
      cleared_download_guids_on_startup_.insert(download->GetGuid());
      DeleteDownloadedFileOnUIThread(download->GetFullPath());
      it = in_progress_downloads_.erase(it);
      continue;
    }
    ++it;
  }
  PostInitialization(DOWNLOAD_INITIALIZATION_DEPENDENCY_IN_PROGRESS_CACHE);
  SetNextId(max_id + 1);
}

void DownloadManagerImpl::StartDownloadItem(
    std::unique_ptr<download::DownloadCreateInfo> info,
    download::DownloadUrlParameters::OnStartedCallback on_started,
    download::InProgressDownloadManager::StartDownloadItemCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  download::DownloadItemImpl* download =
      static_cast<download::DownloadItemImpl*>(GetDownloadByGuid(info->guid));
  if (!info->is_new_download) {
    if (!download || download->GetState() == download::DownloadItem::CANCELLED)
      download = nullptr;
    std::move(callback).Run(std::move(info), download, base::FilePath(),
                            should_persist_new_download_);
    OnDownloadStarted(download, std::move(on_started));
  } else {
    // If the download already in system, it can only be resumed.
    if (!info->guid.empty() && download) {
      LOG(WARNING) << "A download with the same GUID already exists, the new "
                      "request is ignored.";
      return;
    }
    GetNextId(base::BindOnce(&DownloadManagerImpl::OnNewDownloadIdRetrieved,
                             weak_factory_.GetWeakPtr(), std::move(info),
                             std::move(on_started), std::move(callback)));
  }
}

void DownloadManagerImpl::OnNewDownloadIdRetrieved(
    std::unique_ptr<download::DownloadCreateInfo> info,
    download::DownloadUrlParameters::OnStartedCallback on_started,
    download::InProgressDownloadManager::StartDownloadItemCallback callback,
    uint32_t id) {
#if BUILDFLAG(IS_ANDROID)
  if (info->transient && info->allow_auto_open_after_completion &&
      delegate_->ShouldOpenPdfInline() &&
      base::EqualsCaseInsensitiveASCII(info->mime_type, kPdfMimeType)) {
    if (IsOffTheRecord()) {
      info->save_info->use_in_memory_file = true;
    } else {
      for (const auto& iter : downloads_by_guid_) {
        download::DownloadItem* item = iter.second;
        if (item->GetFileExternallyRemoved() ||
            item->GetState() != download::DownloadItem::COMPLETE) {
          continue;
        }

        if (item->GetMimeType() != kPdfMimeType ||
            item->GetUrlChain() != info->url_chain) {
          continue;
        }

        if (!item->IsTransient() || !item->AllowAutoOpenAfterCompletion()) {
          continue;
        }

        disk_access_task_runner_->PostTaskAndReplyWithResult(
            FROM_HERE,
            base::BindOnce(&base::PathExists, item->GetTargetFilePath()),
            base::BindOnce(&DownloadManagerImpl::CreateNewDownloadItemToStart,
                           weak_factory_.GetWeakPtr(), std::move(info),
                           std::move(on_started), std::move(callback), id,
                           item->GetTargetFilePath()));
        return;
      }
    }
  }
#endif  // BUILDFLAG(IS_ANDROID)
  CreateNewDownloadItemToStart(std::move(info), std::move(on_started),
                               std::move(callback), id, base::FilePath(),
                               false);
}

void DownloadManagerImpl::CreateNewDownloadItemToStart(
    std::unique_ptr<download::DownloadCreateInfo> info,
    download::DownloadUrlParameters::OnStartedCallback on_started,
    download::InProgressDownloadManager::StartDownloadItemCallback callback,
    uint32_t id,
    const base::FilePath& duplicate_download_file_path,
    bool duplicate_file_exists) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  download::DownloadItemImpl* download = CreateActiveItem(id, *info);
  if (delegate_ && info->save_info) {
    info->save_info->needs_obfuscation =
        delegate_->ShouldObfuscateDownload(download);
    info->save_info->total_bytes = info->total_bytes;
  }
  content::devtools_instrumentation::WillBeginDownload(info.get(), download);
  // Check if the download is a duplicate. Only GET download URL that has
  // existed are considered duplicate.
  bool is_duplicate = duplicate_file_exists && (info->method == "GET");
  if (is_duplicate) {
    bool found_same_url = false;
    // If there is another download with the same path, the download is
    // not a duplicate.
    for (auto it = downloads_.begin(); it != downloads_.end(); ++it) {
      if (it->second->GetTargetFilePath() == duplicate_download_file_path) {
        if (it->second->GetURL() != info->url()) {
          is_duplicate = false;
          break;
        } else {
          found_same_url = true;
        }
      }
    }
    is_duplicate = is_duplicate && found_same_url;
  }
  std::move(callback).Run(
      std::move(info), download,
      is_duplicate ? duplicate_download_file_path : base::FilePath(),
      should_persist_new_download_);
  if (download) {
    // For new downloads, we notify here, rather than earlier, so that
    // the download_file is bound to download and all the usual
    // setters (e.g. Cancel) work.
    for (auto& observer : observers_)
      observer.OnDownloadCreated(this, download);
    OnNewDownloadCreated(download);
  }

  OnDownloadStarted(download, std::move(on_started));
}

void DownloadManagerImpl::BindWakeLockProvider(
    mojo::PendingReceiver<device::mojom::WakeLockProvider> receiver) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  GetDeviceService().BindWakeLockProvider(std::move(receiver));
}

download::QuarantineConnectionCallback
DownloadManagerImpl::GetQuarantineConnectionCallback() {
  if (!delegate_)
    return base::NullCallback();

  return delegate_->GetQuarantineConnectionCallback();
}

std::unique_ptr<download::DownloadItemRenameHandler>
DownloadManagerImpl::GetRenameHandlerForDownload(
    download::DownloadItemImpl* download_item) {
  if (!delegate_) {
    return nullptr;
  }

  return delegate_->GetRenameHandlerForDownload(download_item);
}

void DownloadManagerImpl::StartDownload(
    std::unique_ptr<download::DownloadCreateInfo> info,
    std::unique_ptr<download::InputStream> stream,
    download::DownloadUrlParameters::OnStartedCallback on_started) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(info);
  in_progress_manager_->StartDownload(
      std::move(info), std::move(stream),
      download::URLLoaderFactoryProvider::GetNullPtr(), base::DoNothing(),
      std::move(on_started));
}

void DownloadManagerImpl::CheckForHistoryFilesRemoval() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  for (const auto& it : downloads_by_guid_) {
    CheckForFileRemoval(it.second);
  }
}

void DownloadManagerImpl::OnHistoryQueryComplete(
    base::OnceClosure load_history_downloads_cb) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (!in_progress_cache_initialized_)
    load_history_downloads_cb_ = std::move(load_history_downloads_cb);
  else
    std::move(load_history_downloads_cb).Run();
}

void DownloadManagerImpl::CheckForFileRemoval(
    download::DownloadItemImpl* download_item) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if ((download_item->GetState() != download::DownloadItem::COMPLETE) ||
      download_item->GetFileExternallyRemoved()) {
    return;
  }

  // Check whether an task is already queued or running for the current download
  // and skip this check if it is the case.
  if (!pending_disk_access_query_.insert(download_item->GetGuid()).second)
    return;

  disk_access_task_runner_->PostTaskAndReplyWithResult(
      FROM_HERE,
      base::BindOnce(&base::PathExists, download_item->GetTargetFilePath()),
      base::BindOnce(&DownloadManagerImpl::OnFileExistenceChecked,
                     weak_factory_.GetWeakPtr(), download_item->GetGuid()));
}

void DownloadManagerImpl::OnFileExistenceChecked(const std::string& guid,
                                                 bool result) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // Remove the pending check flag for this download to allow new requests.
  pending_disk_access_query_.erase(guid);

  if (!result) {  // File does not exist.
    auto it = downloads_by_guid_.find(guid);
    if (it != downloads_by_guid_.end())
      it->second->OnDownloadedFileRemoved();
  }
}

std::string DownloadManagerImpl::GetApplicationClientIdForFileScanning() const {
  if (delegate_)
    return delegate_->ApplicationClientIdForFileScanning();
  return std::string();
}

BrowserContext* DownloadManagerImpl::GetBrowserContext() {
  return browser_context_;
}

void DownloadManagerImpl::CreateSavePackageDownloadItem(
    const base::FilePath& main_file_path,
    const base::FilePath& main_file_display_name,
    const GURL& page_url,
    const std::string& mime_type,
    int render_process_id,
    int render_frame_id,
    download::DownloadJob::CancelRequestCallback cancel_request_callback,
    DownloadItemImplCreated item_created) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  GetNextId(base::BindOnce(
      &DownloadManagerImpl::CreateSavePackageDownloadItemWithId,
      weak_factory_.GetWeakPtr(), main_file_path, main_file_display_name,
      page_url, mime_type, render_process_id, render_frame_id,
      std::move(cancel_request_callback), std::move(item_created)));
}

void DownloadManagerImpl::CreateSavePackageDownloadItemWithId(
    const base::FilePath& main_file_path,
    const base::FilePath& main_file_display_name,
    const GURL& page_url,
    const std::string& mime_type,
    int render_process_id,
    int render_frame_id,
    download::DownloadJob::CancelRequestCallback cancel_request_callback,
    DownloadItemImplCreated item_created,
    uint32_t id) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK_NE(download::DownloadItem::kInvalidId, id);
  DCHECK(!base::Contains(downloads_, id));

  download::DownloadItemImpl* download_item = item_factory_->CreateSavePageItem(
      this, id, main_file_path, main_file_display_name, page_url, mime_type,
      std::move(cancel_request_callback));

  GlobalRenderFrameHostId global_id(render_process_id, render_frame_id);
  DownloadItemUtils::AttachInfo(
      download_item, GetBrowserContext(),
      WebContentsImpl::FromRenderFrameHostID(global_id), global_id);
  if (delegate_) {
    delegate_->AttachExtraInfo(download_item);
  }

  OnDownloadCreated(base::WrapUnique(download_item));
  if (!item_created.is_null())
    std::move(item_created).Run(download_item);
}

// Resume a download of a specific URL. We send the request to the
// ResourceDispatcherHost, and let it send us responses like a regular
// download.
void DownloadManagerImpl::ResumeInterruptedDownload(
    std::unique_ptr<download::DownloadUrlParameters> params,
    const std::string& serialized_embedder_download_data) {
  BeginDownloadInternal(std::move(params),
                        nullptr /* blob_url_loader_factory */, false,
                        serialized_embedder_download_data);
}

void DownloadManagerImpl::SetDownloadItemFactoryForTesting(
    std::unique_ptr<download::DownloadItemFactory> item_factory) {
  item_factory_ = std::move(item_factory);
}

void DownloadManagerImpl::SetDownloadFileFactoryForTesting(
    std::unique_ptr<download::DownloadFileFactory> file_factory) {
  in_progress_manager_->set_file_factory(std::move(file_factory));
}

download::DownloadFileFactory*
DownloadManagerImpl::GetDownloadFileFactoryForTesting() {
  return in_progress_manager_->file_factory();
}

void DownloadManagerImpl::DownloadRemoved(
    download::DownloadItemImpl* download) {
  if (!download)
    return;

  downloads_by_guid_.erase(download->GetGuid());
  downloads_.erase(download->GetId());
}

void DownloadManagerImpl::DownloadInterrupted(
    download::DownloadItemImpl* download) {
  WebContents* web_contents = DownloadItemUtils::GetWebContents(download);
  if (!web_contents) {
    download::RecordDownloadCountWithSource(
        download::INTERRUPTED_WITHOUT_WEBCONTENTS,
        download->GetDownloadSource());
  }
}

bool DownloadManagerImpl::IsOffTheRecord() const {
  return browser_context_->IsOffTheRecord();
}

void DownloadManagerImpl::ReportBytesWasted(
    download::DownloadItemImpl* download) {
  in_progress_manager_->ReportBytesWasted(download);
}

void DownloadManagerImpl::InterceptNavigation(
    std::unique_ptr<network::ResourceRequest> resource_request,
    std::vector<GURL> url_chain,
    network::mojom::URLResponseHeadPtr response_head,
    mojo::ScopedDataPipeConsumerHandle response_body,
    network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
    net::CertStatus cert_status,
    FrameTreeNodeId frame_tree_node_id,
    bool from_download_cross_origin_redirect) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (!delegate_) {
    DropDownload();
    return;
  }

  const GURL& url = resource_request->url;
  const std::string& method = resource_request->method;
  std::optional<url::Origin> request_initiator =
      resource_request->request_initiator;
  std::string mime_type = response_head->mime_type;
  ui::PageTransition transition_type =
      static_cast<ui::PageTransition>(resource_request->transition_type);

  WebContents::Getter web_contents_getter =
      base::BindRepeating(WebContents::FromFrameTreeNodeId, frame_tree_node_id);

  base::OnceCallback<void(bool /* download allowed */)>
      on_download_checks_done = base::BindOnce(
          &DownloadManagerImpl::InterceptNavigationOnChecksComplete,
          weak_factory_.GetWeakPtr(), frame_tree_node_id,
          std::move(resource_request), std::move(url_chain), cert_status,
          std::move(response_head), std::move(response_body),
          std::move(url_loader_client_endpoints));

  delegate_->CheckDownloadAllowed(
      std::move(web_contents_getter), url, method, std::move(request_initiator),
      from_download_cross_origin_redirect, false /*content_initiated*/,
      mime_type, transition_type, std::move(on_download_checks_done));
}

int DownloadManagerImpl::RemoveDownloadsByURLAndTime(
    const base::RepeatingCallback<bool(const GURL&)>& url_filter,
    base::Time remove_begin,
    base::Time remove_end) {
  int count = 0;
  auto it = downloads_by_guid_.begin();
  while (it != downloads_by_guid_.end()) {
    download::DownloadItemImpl* download = it->second;

    // Increment done here to protect against invalidation below.
    ++it;

    if (download->GetState() != download::DownloadItem::IN_PROGRESS &&
        url_filter.Run(download->GetURL()) &&
        download->GetStartTime() >= remove_begin &&
        (remove_end.is_null() || download->GetStartTime() < remove_end)) {
      download->Remove();
      count++;
    }
  }
  return count;
}

bool DownloadManagerImpl::CanDownload(
    download::DownloadUrlParameters* parameters) {
  return true;
}

void DownloadManagerImpl::DownloadUrl(
    std::unique_ptr<download::DownloadUrlParameters> params) {
  DownloadUrl(std::move(params), nullptr /* blob_url_loader_factory */);
}

void DownloadManagerImpl::DownloadUrl(
    std::unique_ptr<download::DownloadUrlParameters> params,
    scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory) {
  if (params->post_id() >= 0) {
    // Check this here so that the traceback is more useful.
    DCHECK(params->prefer_cache());
    DCHECK_EQ("POST", params->method());
  }

  if (delegate_)
    delegate_->SanitizeDownloadParameters(params.get());

  download::RecordDownloadCountWithSource(
      download::DownloadCountTypes::DOWNLOAD_TRIGGERED_COUNT,
      params->download_source());
  BeginDownloadInternal(std::move(params), std::move(blob_url_loader_factory),
                        /*is_new_download=*/true,
                        /*serialized_embedder_download_data=*/std::string());
}

void DownloadManagerImpl::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void DownloadManagerImpl::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

download::DownloadItem* DownloadManagerImpl::CreateDownloadItem(
    const std::string& guid,
    uint32_t id,
    const base::FilePath& current_path,
    const base::FilePath& target_path,
    const std::vector<GURL>& url_chain,
    const GURL& referrer_url,
    const StoragePartitionConfig& storage_partition_config,
    const GURL& tab_url,
    const GURL& tab_refererr_url,
    const std::optional<url::Origin>& request_initiator,
    const std::string& mime_type,
    const std::string& original_mime_type,
    base::Time start_time,
    base::Time end_time,
    const std::string& etag,
    const std::string& last_modified,
    int64_t received_bytes,
    int64_t total_bytes,
    const std::string& hash,
    download::DownloadItem::DownloadState state,
    download::DownloadDangerType danger_type,
    download::DownloadInterruptReason interrupt_reason,
    bool opened,
    base::Time last_access_time,
    bool transient,
    const std::vector<download::DownloadItem::ReceivedSlice>& received_slices) {
  // Retrieve the in-progress download if it exists. Notice that this also
  // removes it from |in_progress_downloads_|.
  auto in_progress_download = RetrieveInProgressDownload(id);

  // Return null to clear cancelled or non-resumable download.
  if (base::Contains(cleared_download_guids_on_startup_, guid)) {
    return nullptr;
  }

  if (url_chain.empty() ||
      ShouldClearDownloadFromDB(url_chain.back(), state, interrupt_reason,
                                start_time)) {
    DeleteDownloadedFileOnUIThread(current_path);
    return nullptr;
  }
  auto item = base::WrapUnique(item_factory_->CreatePersistedItem(
      this, guid, id, current_path, target_path, url_chain, referrer_url,
      StoragePartitionConfigToSerializedEmbedderDownloadData(
          storage_partition_config),
      tab_url, tab_refererr_url, request_initiator, mime_type,
      original_mime_type, start_time, end_time, etag, last_modified,
      received_bytes, total_bytes, hash, state, danger_type, interrupt_reason,
      opened, last_access_time, transient, received_slices));
  if (in_progress_download) {
    // If a download is in both history DB and in-progress DB, we should
    // be able to remove the in-progress entry if the following 2 conditions
    // are both met:
    // 1. The download state in the history DB is a terminal state.
    // 2. The download is not currently in progress.
    // The situation could happen when browser crashes when download just
    // reaches a terminal state. If the download is already in progress, we
    // should wait for it to complete so that both DBs will be updated
    // afterwards.
    if (item->IsDone() && in_progress_download->GetState() !=
                              download::DownloadItem::IN_PROGRESS) {
      in_progress_manager_->RemoveInProgressDownload(guid);
    } else {
      // If one of the conditions are not met, use the in-progress download
      // entry.
      // TODO(qinmin): return nullptr so that the history DB will delete
      // the download.
      item = std::move(in_progress_download);
      item->SetDelegate(this);
    }
  }
#if BUILDFLAG(IS_ANDROID)
  if (target_path.IsContentUri()) {
    base::FilePath android_display_name =
        in_progress_manager_->GetDownloadDisplayName(target_path);
    if (!android_display_name.empty())
      item->SetDisplayName(android_display_name);
    else
      return nullptr;
  }
#endif
  download::DownloadItemImpl* download = item.get();
  DownloadItemUtils::AttachInfo(download, GetBrowserContext(), nullptr,
                                GlobalRenderFrameHostId());
  if (delegate_) {
    delegate_->AttachExtraInfo(download);
  }
  OnDownloadCreated(std::move(item));
  return download;
}

void DownloadManagerImpl::OnDownloadCreated(
    std::unique_ptr<download::DownloadItemImpl> download) {
  DCHECK(!base::Contains(downloads_, download->GetId()));
  DCHECK(!base::Contains(downloads_by_guid_, download->GetGuid()));
  download::DownloadItemImpl* item = download.get();
  downloads_[item->GetId()] = std::move(download);
  downloads_by_guid_[item->GetGuid()] = item;
  for (auto& observer : observers_)
    observer.OnDownloadCreated(this, item);
  OnNewDownloadCreated(item);
  DVLOG(20) << __func__ << "() download = " << item->DebugString(true);
}

void DownloadManagerImpl::PostInitialization(
    DownloadInitializationDependency dependency) {
  // If initialization has occurred (ie. in tests), skip post init steps.
  if (initialized_)
    return;

  switch (dependency) {
    case DOWNLOAD_INITIALIZATION_DEPENDENCY_HISTORY_DB:
      history_db_initialized_ = true;
      break;
    case DOWNLOAD_INITIALIZATION_DEPENDENCY_IN_PROGRESS_CACHE:
      in_progress_cache_initialized_ = true;
      // Post a task to load downloads from history db.
      if (load_history_downloads_cb_) {
        base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
            FROM_HERE, std::move(load_history_downloads_cb_));
      }
      break;
    case DOWNLOAD_INITIALIZATION_DEPENDENCY_NONE:
    default:
      NOTREACHED();
  }

  // Download manager is only initialized if both history db and in progress
  // cache are initialized.
  bool history_loaded = history_db_initialized_ || IsOffTheRecord();
  if (!history_loaded || !in_progress_cache_initialized_)
    return;

  for (const auto& guid : cleared_download_guids_on_startup_) {
    in_progress_manager_->RemoveInProgressDownload(guid);
  }

  if (in_progress_downloads_.empty()) {
    OnDownloadManagerInitialized();
  } else {
    GetNextId(base::BindOnce(&DownloadManagerImpl::ImportInProgressDownloads,
                             weak_factory_.GetWeakPtr()));
  }
}

void DownloadManagerImpl::ImportInProgressDownloads(uint32_t id) {
  auto download = in_progress_downloads_.begin();
  while (download != in_progress_downloads_.end()) {
    auto item = std::move(*download);
    // If the in-progress download doesn't have an ID, generate new IDs for it.
    if (item->GetId() == download::DownloadItem::kInvalidId) {
      item->SetDownloadId(id++);
      next_download_id_++;
      if (!should_persist_new_download_)
        in_progress_manager_->RemoveInProgressDownload(item->GetGuid());
    }
    item->SetDelegate(this);
    DownloadItemUtils::AttachInfo(item.get(), GetBrowserContext(), nullptr,
                                  GlobalRenderFrameHostId());
    if (delegate_) {
      delegate_->AttachExtraInfo(item.get());
    }
    download = in_progress_downloads_.erase(download);
    OnDownloadCreated(std::move(item));
  }
  OnDownloadManagerInitialized();
}

void DownloadManagerImpl::OnDownloadManagerInitialized() {
  OnInitialized();
  in_progress_manager_->OnAllInprogressDownloadsLoaded();
  for (auto& observer : observers_)
    observer.OnManagerInitialized();
}

bool DownloadManagerImpl::IsManagerInitialized() {
  return initialized_;
}

int DownloadManagerImpl::InProgressCount() {
  int count = 0;
  for (const auto& it : downloads_by_guid_) {
    if (it.second->GetState() == download::DownloadItem::IN_PROGRESS) {
      ++count;
    }
  }
  return count;
}

int DownloadManagerImpl::BlockingShutdownCount() {
  int count = 0;
  for (const auto& it : downloads_by_guid_) {
    download::DownloadItemImpl* download = it.second;
    if (download->IsTransient()) {
      continue;
    }
    if (download->GetState() == download::DownloadItem::IN_PROGRESS &&
        !download->IsDangerous() && !download->IsInsecure()) {
      ++count;
    }
  }
  return count;
}

download::DownloadItem* DownloadManagerImpl::GetDownload(uint32_t download_id) {
  auto it = downloads_.find(download_id);
  return it != downloads_.end() ? it->second.get() : nullptr;
}

download::DownloadItem* DownloadManagerImpl::GetDownloadByGuid(
    const std::string& guid) {
  if (!in_progress_downloads_.empty()) {
    for (const auto& it : in_progress_downloads_) {
      if (it->GetGuid() == guid)
        return it.get();
    }
  }
  auto it = downloads_by_guid_.find(guid);
  return it != downloads_by_guid_.end() ? it->second : nullptr;
}

void DownloadManagerImpl::GetAllDownloads(
    download::SimpleDownloadManager::DownloadVector* downloads) {
  for (const auto& it : downloads_by_guid_) {
    downloads->push_back(it.second);
  }
}

void DownloadManagerImpl::GetUninitializedActiveDownloadsIfAny(
    download::SimpleDownloadManager::DownloadVector* downloads) {
  for (const auto& it : in_progress_downloads_)
    downloads->push_back(it.get());
}

void DownloadManagerImpl::OpenDownload(download::DownloadItemImpl* download) {
  if (delegate_)
    delegate_->OpenDownload(download);
}

void DownloadManagerImpl::ShowDownloadInShell(
    download::DownloadItemImpl* download) {
  if (delegate_)
    delegate_->ShowDownloadInShell(download);
}

void DownloadManagerImpl::DropDownload() {
  download::RecordDownloadCount(download::DOWNLOAD_DROPPED_COUNT);
  for (auto& observer : observers_)
    observer.OnDownloadDropped(this);
}

void DownloadManagerImpl::InterceptNavigationOnChecksComplete(
    FrameTreeNodeId frame_tree_node_id,
    std::unique_ptr<network::ResourceRequest> resource_request,
    std::vector<GURL> url_chain,
    net::CertStatus cert_status,
    network::mojom::URLResponseHeadPtr response_head,
    mojo::ScopedDataPipeConsumerHandle response_body,
    network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
    bool is_download_allowed) {
  if (!is_download_allowed) {
    DropDownload();
    return;
  }

  int render_process_id = -1;
  int render_frame_id = -1;
  GURL site_url, tab_url, tab_referrer_url;
  RenderFrameHost* render_frame_host = nullptr;
  auto storage_partition_config =
      StoragePartitionConfig::CreateDefault(browser_context_);
  auto* ftn = FrameTreeNode::GloballyFindByID(frame_tree_node_id);
  if (ftn) {
    render_frame_host = ftn->current_frame_host();
    if (render_frame_host) {
      render_process_id = render_frame_host->GetProcess()->GetDeprecatedID();
      render_frame_id = render_frame_host->GetRoutingID();
      storage_partition_config =
          render_frame_host->GetSiteInstance()->GetStoragePartitionConfig();
    }
    auto* web_contents = WebContentsImpl::FromFrameTreeNode(ftn);
    DCHECK(web_contents);
    NavigationEntry* entry = web_contents->GetController().GetVisibleEntry();
    if (entry) {
      tab_url = entry->GetURL();
      tab_referrer_url = entry->GetReferrer().url;
    }
    RenderFrameHost* opener = web_contents->GetOpener();
    if (opener) {
      RecordDownloadOpenerType(render_frame_host, opener);
    }
  }

  bool is_transient = false;
#if BUILDFLAG(IS_ANDROID)
  if (!download::IsContentDispositionAttachmentInHead(*response_head)) {
    is_transient = delegate_->ShouldOpenPdfInline() &&
                   base::EqualsCaseInsensitiveASCII(response_head->mime_type,
                                                    kPdfMimeType);
  }
#endif  // BUILDFLAG(IS_ANDROID)

  StoragePartitionImpl* storage_partition =
      GetStoragePartitionForConfig(browser_context_, storage_partition_config);
  in_progress_manager_->InterceptDownloadFromNavigation(
      std::move(resource_request), render_process_id, render_frame_id,
      StoragePartitionConfigToSerializedEmbedderDownloadData(
          storage_partition_config),
      tab_url, tab_referrer_url, std::move(url_chain), std::move(cert_status),
      std::move(response_head), std::move(response_body),
      std::move(url_loader_client_endpoints),
      CreatePendingSharedURLLoaderFactory(storage_partition, render_frame_host),
      is_transient);
}

void DownloadManagerImpl::BeginResourceDownloadOnChecksComplete(
    std::unique_ptr<download::DownloadUrlParameters> params,
    scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
    bool is_new_download,
    const StoragePartitionConfig& storage_partition_config,
    bool is_download_allowed) {
  if (!is_download_allowed) {
    DropDownload();
    return;
  }

  GURL tab_url, tab_referrer_url;
  auto* rfh = RenderFrameHost::FromID(params->render_process_host_id(),
                                      params->render_frame_host_routing_id());
  if (rfh) {
    auto* web_contents = WebContents::FromRenderFrameHost(rfh);
    NavigationEntry* entry = web_contents->GetController().GetVisibleEntry();
    if (entry) {
      tab_url = entry->GetURL();
      tab_referrer_url = entry->GetReferrer().url;
    }
  }

  DCHECK_EQ(params->url().SchemeIsBlob(), bool{blob_url_loader_factory});
  std::unique_ptr<network::PendingSharedURLLoaderFactory>
      pending_url_loader_factory;
  if (blob_url_loader_factory) {
    DCHECK(params->url().SchemeIsBlob());
    pending_url_loader_factory = blob_url_loader_factory->Clone();
  } else if (params->url().SchemeIsFile()) {
    pending_url_loader_factory =
        std::make_unique<network::WrapperPendingSharedURLLoaderFactory>(
            FileURLLoaderFactory::Create(
                browser_context_->GetPath(),
                browser_context_->GetSharedCorsOriginAccessList(),
                // USER_VISIBLE because download should progress
                // even when there is high priority work to do.
                base::TaskPriority::USER_VISIBLE));
  } else if (rfh && params->url().SchemeIs(content::kChromeUIScheme)) {
    pending_url_loader_factory =
        std::make_unique<network::WrapperPendingSharedURLLoaderFactory>(
            CreateWebUIURLLoaderFactory(rfh, params->url().GetScheme(),
                                        base::flat_set<std::string>()));
  } else if (rfh && params->url().SchemeIsFileSystem()) {
    StoragePartitionImpl* storage_partition = GetStoragePartitionForConfig(
        browser_context_, storage_partition_config);
    pending_url_loader_factory =
        std::make_unique<network::WrapperPendingSharedURLLoaderFactory>(
            CreateFileSystemURLLoaderFactory(
                rfh->GetProcess()->GetDeprecatedID(), rfh->GetFrameTreeNodeId(),
                storage_partition->GetFileSystemContext(),
                storage_partition->GetPartitionDomain(),
                static_cast<RenderFrameHostImpl*>(rfh)->GetStorageKey()));
  } else if (params->url().SchemeIs(url::kDataScheme)) {
    pending_url_loader_factory =
        std::make_unique<network::WrapperPendingSharedURLLoaderFactory>(
            DataURLLoaderFactory::CreateForOneSpecificUrl(params->url()));
  } else if (rfh && !network::IsURLHandledByNetworkService(params->url())) {
    ContentBrowserClient::NonNetworkURLLoaderFactoryMap
        non_network_url_loader_factories;
    GetContentClient()
        ->browser()
        ->RegisterNonNetworkSubresourceURLLoaderFactories(
            params->render_process_host_id(),
            params->render_frame_host_routing_id(), params->initiator(),
            &non_network_url_loader_factories);
    auto it = non_network_url_loader_factories.find(params->url().GetScheme());
    if (it != non_network_url_loader_factories.end()) {
      pending_url_loader_factory =
          std::make_unique<network::WrapperPendingSharedURLLoaderFactory>(
              std::move(it->second));
    } else {
      DLOG(ERROR) << "No URLLoaderFactory found to download " << params->url();
      return;
    }
  } else {
    StoragePartitionImpl* storage_partition = GetStoragePartitionForConfig(
        browser_context_, storage_partition_config);
    pending_url_loader_factory =
        CreatePendingSharedURLLoaderFactory(storage_partition, rfh);
  }

  in_progress_manager_->BeginDownload(
      std::move(params), std::move(pending_url_loader_factory), is_new_download,
      StoragePartitionConfigToSerializedEmbedderDownloadData(
          storage_partition_config),
      tab_url, tab_referrer_url);
}

void DownloadManagerImpl::BeginDownloadInternal(
    std::unique_ptr<download::DownloadUrlParameters> params,
    scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
    bool is_new_download,
    const std::string& serialized_embedder_download_data) {
  // Check if the renderer is permitted to request the requested URL.
  if (params->render_process_host_id() >= 0 &&
      !DownloadRequestUtils::IsURLSafe(params->render_process_host_id(),
                                       params->url())) {
    CreateInterruptedDownload(
        std::move(params),
        download::DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST,
        weak_factory_.GetWeakPtr());
    return;
  }

  auto* rfh = RenderFrameHost::FromID(params->render_process_host_id(),
                                      params->render_frame_host_routing_id());

  StoragePartitionConfig storage_partition_config;
  if (rfh && serialized_embedder_download_data.empty()) {
    storage_partition_config =
        rfh->GetSiteInstance()->GetStoragePartitionConfig();
  } else {
    storage_partition_config =
        SerializedEmbedderDownloadDataToStoragePartitionConfig(
            serialized_embedder_download_data);
  }

  // Ideally everywhere a blob: URL is downloaded a URLLoaderFactory for that
  // blob URL is also passed, but since that isn't always the case, create
  // a new factory if we don't have one already.
  if (!blob_url_loader_factory && params->url().SchemeIsBlob()) {
    blob_url_loader_factory = ChromeBlobStorageContext::URLLoaderFactoryForUrl(
        GetStoragePartitionForConfig(browser_context_,
                                     storage_partition_config),
        params->url());
  }

  bool content_initiated = params->content_initiated();
  if (rfh && content_initiated) {
    // Cancel downloads from non-active documents (e.g prerendered, bfcached) or
    // fenced frames.
    if (rfh->IsInactiveAndDisallowActivation(
            DisallowActivationReasonId::kBeginDownload) ||
        rfh->IsNestedWithinFencedFrame()) {
      DropDownload();
      return;
    }

    // Push the throttle on the web-initiated downloads before allowing them to
    // proceed.
    if (delegate_) {
      WebContents::Getter web_contents_getter = base::BindRepeating(
          WebContents::FromFrameTreeNodeId, rfh->GetFrameTreeNodeId());
      const GURL& url = params->url();
      const std::string& method = params->method();
      std::optional<url::Origin> initiator = params->initiator();
      base::OnceCallback<void(bool /* download allowed */)>
          on_can_download_checks_done = base::BindOnce(
              &DownloadManagerImpl::BeginResourceDownloadOnChecksComplete,
              weak_factory_.GetWeakPtr(), std::move(params),
              std::move(blob_url_loader_factory), is_new_download,
              storage_partition_config);
      delegate_->CheckDownloadAllowed(
          std::move(web_contents_getter), url, method, std::move(initiator),
          false /* from_download_cross_origin_redirect */, content_initiated,
          /* mime_type= */ std::string(),
          /* page_transition= */ std::nullopt,
          std::move(on_can_download_checks_done));
      return;
    }
  }

  BeginResourceDownloadOnChecksComplete(
      std::move(params), std::move(blob_url_loader_factory), is_new_download,
      storage_partition_config, rfh ? !content_initiated : true);
}

bool DownloadManagerImpl::IsNextIdInitialized() const {
  return is_history_download_id_retrieved_ && in_progress_cache_initialized_;
}

bool DownloadManagerImpl::ShouldClearDownloadFromDB(
    const GURL& url,
    download::DownloadItem::DownloadState state,
    download::DownloadInterruptReason reason,
    const base::Time& start_time) {
  if (!base::FeatureList::IsEnabled(
          download::features::kDeleteExpiredDownloads)) {
    return false;
  }

  // Use system time to determine if the download is expired. Manually setting
  // the system time can affect this.
  bool expired = base::Time::Now() - start_time >=
                 download::GetExpiredDownloadDeleteTime();
  if (state == download::DownloadItem::CANCELLED && expired)
    return true;

  if (reason != download::DOWNLOAD_INTERRUPT_REASON_NONE &&
      state == download::DownloadItem::INTERRUPTED && expired) {
    return true;
  }

  return false;
}

std::unique_ptr<download::DownloadItemImpl>
DownloadManagerImpl::RetrieveInProgressDownload(uint32_t id) {
  // In case the history DB has some invalid IDs, skip them.
  if (id == download::DownloadItem::kInvalidId)
    return nullptr;

  for (auto it = in_progress_downloads_.begin();
       it != in_progress_downloads_.end(); ++it) {
    if ((*it)->GetId() == id) {
      auto download = std::move(*it);
      in_progress_downloads_.erase(it);
      return download;
    }
  }

  return nullptr;
}

}  // namespace content
