chromium/components/download/internal/common/download_item_impl.cc

// 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.

// File method ordering: Methods in this file are in the same order as
// in download_item_impl.h, with the following exception: The public
// interface Start is placed in chronological order with the other
// (private) routines that together define a DownloadItem's state
// transitions as the download progresses.  See "Download progression
// cascade" later in this file.

// A regular DownloadItem (created for a download in this session of
// the browser) normally goes through the following states:
//      * Created (when download starts)
//      * Destination filename determined
//      * Entered into the history database.
//      * Made visible in the download shelf.
//      * All the data is saved.  Note that the actual data download occurs
//        in parallel with the above steps, but until those steps are
//        complete, the state of the data save will be ignored.
//      * Download file is renamed to its final name, and possibly
//        auto-opened.

#include "components/download/public/common/download_item_impl.h"

#include <memory>
#include <optional>
#include <utility>
#include <vector>

#include "base/files/file_util.h"
#include "base/format_macros.h"
#include "base/functional/bind.h"
#include "base/json/string_escape.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/observer_list.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/sequenced_task_runner.h"
#include "base/trace_event/memory_usage_estimator.h"
#include "base/trace_event/trace_event.h"
#include "base/uuid.h"
#include "build/build_config.h"
#include "components/download/internal/common/download_job_impl.h"
#include "components/download/internal/common/parallel_download_utils.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_impl_delegate.h"
#include "components/download/public/common/download_item_rename_handler.h"
#include "components/download/public/common/download_job_factory.h"
#include "components/download/public/common/download_stats.h"
#include "components/download/public/common/download_task_runner.h"
#include "components/download/public/common/download_ukm_helper.h"
#include "components/download/public/common/download_url_parameters.h"
#include "components/download/public/common/download_utils.h"
#include "net/base/network_change_notifier.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/referrer_policy.h"
#include "services/metrics/public/cpp/ukm_source_id.h"

#if BUILDFLAG(IS_ANDROID)
#include "components/download/internal/common/android/download_collection_bridge.h"
#endif  // BUILDFLAG(IS_ANDROID)

#if BUILDFLAG(IS_MAC)
#include "base/mac/mac_util.h"
#endif  // BUILDFLAG(IS_MAC)

namespace download {

namespace {

void DeleteDownloadedFileDone(base::WeakPtr<DownloadItemImpl> item,
                              base::OnceCallback<void(bool)> callback,
                              bool success) {}

// Wrapper around DownloadFile::Detach and DownloadFile::Cancel that
// takes ownership of the DownloadFile and hence implicitly destroys it
// at the end of the function.
base::FilePath DownloadFileDetach(std::unique_ptr<DownloadFile> download_file) {}

base::FilePath MakeCopyOfDownloadFile(DownloadFile* download_file) {}

void DownloadFileCancel(std::unique_ptr<DownloadFile> download_file) {}

// Most of the cancellation pathways behave the same whether the cancellation
// was initiated by ther user (CANCELED) or initiated due to browser context
// shutdown (SHUTDOWN).
bool IsCancellation(DownloadInterruptReason reason) {}

std::string GetDownloadCreationTypeNames(
    DownloadItem::DownloadCreationType type) {}

std::string GetDownloadDangerNames(DownloadDangerType type) {}

class DownloadItemActivatedData
    : public base::trace_event::ConvertableToTraceFormat {};

}  // namespace

// The maximum number of attempts we will make to resume automatically.
const int DownloadItemImpl::kMaxAutoResumeAttempts =;

DownloadItemImpl::RequestInfo::RequestInfo(
    const std::vector<GURL>& url_chain,
    const GURL& referrer_url,
    const std::string& serialized_embedder_download_data,
    const GURL& tab_url,
    const GURL& tab_referrer_url,
    const std::optional<url::Origin>& request_initiator,
    const std::string& suggested_filename,
    const base::FilePath& forced_file_path,
    ui::PageTransition transition_type,
    bool has_user_gesture,
    const std::string& remote_address,
    base::Time start_time,
    ::network::mojom::CredentialsMode credentials_mode,
    const std::optional<net::IsolationInfo>& isolation_info,
    int64_t range_request_from,
    int64_t range_request_to)
    :{}

DownloadItemImpl::RequestInfo::RequestInfo(const GURL& url)
    :{}

DownloadItemImpl::RequestInfo::RequestInfo() = default;

DownloadItemImpl::RequestInfo::RequestInfo(
    const DownloadItemImpl::RequestInfo& other) = default;

DownloadItemImpl::RequestInfo::~RequestInfo() = default;

DownloadItemImpl::DestinationInfo::DestinationInfo(
    const base::FilePath& target_path,
    const base::FilePath& current_path,
    int64_t received_bytes,
    bool all_data_saved,
    const std::string& hash,
    base::Time end_time)
    :{}

DownloadItemImpl::DestinationInfo::DestinationInfo(
    TargetDisposition target_disposition)
    :{}

DownloadItemImpl::DestinationInfo::DestinationInfo() = default;

DownloadItemImpl::DestinationInfo::DestinationInfo(
    const DownloadItemImpl::DestinationInfo& other) = default;

DownloadItemImpl::DestinationInfo::~DestinationInfo() = default;

// Constructor for reading from the history service.
DownloadItemImpl::DownloadItemImpl(
    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,
    int32_t auto_resume_count,
    const std::string& hash,
    DownloadItem::DownloadState state,
    DownloadDangerType danger_type,
    DownloadInterruptReason interrupt_reason,
    bool paused,
    bool allow_metered,
    bool opened,
    base::Time last_access_time,
    bool transient,
    const std::vector<DownloadItem::ReceivedSlice>& received_slices,
    int64_t range_request_from,
    int64_t range_request_to,
    std::unique_ptr<DownloadEntry> download_entry)
    :{}

// Constructing for a regular download:
DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate,
                                   uint32_t download_id,
                                   const DownloadCreateInfo& info)
    :{}

// Constructing for the "Save Page As..." feature:
DownloadItemImpl::DownloadItemImpl(
    DownloadItemImplDelegate* delegate,
    uint32_t download_id,
    const base::FilePath& path,
    const GURL& url,
    const std::string& mime_type,
    DownloadJob::CancelRequestCallback cancel_request_callback)
    :{}

DownloadItemImpl::~DownloadItemImpl() {}

void DownloadItemImpl::AddObserver(Observer* observer) {}

void DownloadItemImpl::RemoveObserver(Observer* observer) {}

void DownloadItemImpl::UpdateObservers() {}

void DownloadItemImpl::ValidateDangerousDownload() {}

void DownloadItemImpl::ValidateInsecureDownload() {}

void DownloadItemImpl::StealDangerousDownload(bool delete_file_afterward,
                                              AcquireFileCallback callback) {}

void DownloadItemImpl::Pause() {}

void DownloadItemImpl::Resume(bool user_resume) {}

void DownloadItemImpl::UpdateResumptionInfo(bool user_resume) {}

void DownloadItemImpl::Cancel(bool user_cancel) {}

void DownloadItemImpl::Remove() {}

void DownloadItemImpl::OpenDownload() {}

void DownloadItemImpl::ShowDownloadInShell() {}

void DownloadItemImpl::RenameDownloadedFileDone(
    RenameDownloadCallback callback,
    const base::FilePath& display_name,
    DownloadRenameResult result) {}

void DownloadItemImpl::Rename(const base::FilePath& display_name,
                              DownloadItem::RenameDownloadCallback callback) {}

uint32_t DownloadItemImpl::GetId() const {}

const std::string& DownloadItemImpl::GetGuid() const {}

DownloadItem::DownloadState DownloadItemImpl::GetState() const {}

DownloadInterruptReason DownloadItemImpl::GetLastReason() const {}

bool DownloadItemImpl::IsPaused() const {}

bool DownloadItemImpl::AllowMetered() const {}

bool DownloadItemImpl::IsTemporary() const {}

bool DownloadItemImpl::CanResume() const {}

bool DownloadItemImpl::IsDone() const {}

int64_t DownloadItemImpl::GetBytesWasted() const {}

int32_t DownloadItemImpl::GetAutoResumeCount() const {}

const GURL& DownloadItemImpl::GetURL() const {}

const std::vector<GURL>& DownloadItemImpl::GetUrlChain() const {}

const GURL& DownloadItemImpl::GetOriginalUrl() const {}

const GURL& DownloadItemImpl::GetReferrerUrl() const {}

const std::string& DownloadItemImpl::GetSerializedEmbedderDownloadData() const {}

const GURL& DownloadItemImpl::GetTabUrl() const {}

const GURL& DownloadItemImpl::GetTabReferrerUrl() const {}

const std::optional<url::Origin>& DownloadItemImpl::GetRequestInitiator()
    const {}

std::string DownloadItemImpl::GetSuggestedFilename() const {}

const scoped_refptr<const net::HttpResponseHeaders>&
DownloadItemImpl::GetResponseHeaders() const {}

std::string DownloadItemImpl::GetContentDisposition() const {}

std::string DownloadItemImpl::GetMimeType() const {}

std::string DownloadItemImpl::GetOriginalMimeType() const {}

std::string DownloadItemImpl::GetRemoteAddress() const {}

bool DownloadItemImpl::HasUserGesture() const {}

ui::PageTransition DownloadItemImpl::GetTransitionType() const {}

const std::string& DownloadItemImpl::GetLastModifiedTime() const {}

const std::string& DownloadItemImpl::GetETag() const {}

bool DownloadItemImpl::IsSavePackageDownload() const {}

DownloadSource DownloadItemImpl::GetDownloadSource() const {}

const base::FilePath& DownloadItemImpl::GetFullPath() const {}

const base::FilePath& DownloadItemImpl::GetTargetFilePath() const {}

const base::FilePath& DownloadItemImpl::GetForcedFilePath() const {}

base::FilePath DownloadItemImpl::GetTemporaryFilePath() const {}

base::FilePath DownloadItemImpl::GetFileNameToReportUser() const {}

DownloadItem::TargetDisposition DownloadItemImpl::GetTargetDisposition() const {}

const std::string& DownloadItemImpl::GetHash() const {}

bool DownloadItemImpl::GetFileExternallyRemoved() const {}

void DownloadItemImpl::DeleteFile(base::OnceCallback<void(bool)> callback) {}

DownloadFile* DownloadItemImpl::GetDownloadFile() {}

DownloadItemRenameHandler* DownloadItemImpl::GetRenameHandler() {}

#if BUILDFLAG(IS_ANDROID)
bool DownloadItemImpl::IsFromExternalApp() {
  return is_from_external_app_;
}

bool DownloadItemImpl::IsMustDownload() {
  return is_must_download_;
}
#endif  // BUILDFLAG(IS_ANDROID)

bool DownloadItemImpl::IsDangerous() const {}

bool DownloadItemImpl::IsInsecure() const {}

DownloadDangerType DownloadItemImpl::GetDangerType() const {}

DownloadItem::InsecureDownloadStatus
DownloadItemImpl::GetInsecureDownloadStatus() const {}

bool DownloadItemImpl::TimeRemaining(base::TimeDelta* remaining) const {}

int64_t DownloadItemImpl::CurrentSpeed() const {}

int DownloadItemImpl::PercentComplete() const {}

bool DownloadItemImpl::AllDataSaved() const {}

int64_t DownloadItemImpl::GetTotalBytes() const {}

int64_t DownloadItemImpl::GetReceivedBytes() const {}

const std::vector<DownloadItem::ReceivedSlice>&
DownloadItemImpl::GetReceivedSlices() const {}

int64_t DownloadItemImpl::GetUploadedBytes() const {}

base::Time DownloadItemImpl::GetStartTime() const {}

base::Time DownloadItemImpl::GetEndTime() const {}

bool DownloadItemImpl::CanShowInFolder() {}

bool DownloadItemImpl::CanOpenDownload() {}

bool DownloadItemImpl::ShouldOpenFileBasedOnExtension() {}

bool DownloadItemImpl::ShouldOpenFileByPolicyBasedOnExtension() {}

bool DownloadItemImpl::GetOpenWhenComplete() const {}

bool DownloadItemImpl::GetAutoOpened() {}

bool DownloadItemImpl::GetOpened() const {}

base::Time DownloadItemImpl::GetLastAccessTime() const {}

bool DownloadItemImpl::IsTransient() const {}

bool DownloadItemImpl::RequireSafetyChecks() const {}

bool DownloadItemImpl::IsParallelDownload() const {}

DownloadItem::DownloadCreationType DownloadItemImpl::GetDownloadCreationType()
    const {}

::network::mojom::CredentialsMode DownloadItemImpl::GetCredentialsMode() const {}

const std::optional<net::IsolationInfo>& DownloadItemImpl::GetIsolationInfo()
    const {}

void DownloadItemImpl::OnContentCheckCompleted(DownloadDangerType danger_type,
                                               DownloadInterruptReason reason) {}

void DownloadItemImpl::OnAsyncScanningCompleted(
    DownloadDangerType danger_type) {}

void DownloadItemImpl::SetOpenWhenComplete(bool open) {}

void DownloadItemImpl::SetOpened(bool opened) {}

void DownloadItemImpl::SetLastAccessTime(base::Time last_access_time) {}

void DownloadItemImpl::SetDisplayName(const base::FilePath& name) {}

std::string DownloadItemImpl::DebugString(bool verbose) const {}

void DownloadItemImpl::SimulateErrorForTesting(DownloadInterruptReason reason) {}

ResumeMode DownloadItemImpl::GetResumeMode() const {}

bool DownloadItemImpl::HasStrongValidators() const {}

void DownloadItemImpl::BindWakeLockProvider(
    mojo::PendingReceiver<device::mojom::WakeLockProvider> receiver) {}

void DownloadItemImpl::UpdateValidatorsOnResumption(
    const DownloadCreateInfo& new_create_info) {}

void DownloadItemImpl::NotifyRemoved() {}

void DownloadItemImpl::OnDownloadedFileRemoved() {}

base::WeakPtr<DownloadDestinationObserver>
DownloadItemImpl::DestinationObserverAsWeakPtr() {}

void DownloadItemImpl::SetTotalBytes(int64_t total_bytes) {}

void DownloadItemImpl::OnAllDataSaved(
    int64_t total_bytes,
    std::unique_ptr<crypto::SecureHash> hash_state) {}

void DownloadItemImpl::MarkAsComplete() {}

void DownloadItemImpl::DestinationUpdate(
    int64_t bytes_so_far,
    int64_t bytes_per_sec,
    const std::vector<DownloadItem::ReceivedSlice>& received_slices) {}

void DownloadItemImpl::DestinationError(
    DownloadInterruptReason reason,
    int64_t bytes_so_far,
    std::unique_ptr<crypto::SecureHash> secure_hash) {}

void DownloadItemImpl::DestinationCompleted(
    int64_t total_bytes,
    std::unique_ptr<crypto::SecureHash> secure_hash) {}

void DownloadItemImpl::SetDelegate(DownloadItemImplDelegate* delegate) {}

void DownloadItemImpl::SetDownloadId(uint32_t download_id) {}

void DownloadItemImpl::SetAutoResumeCountForTesting(int32_t auto_resume_count) {}

// **** Download progression cascade

void DownloadItemImpl::Init(bool active,
                            DownloadItem::DownloadCreationType download_type) {}

// We're starting the download.
void DownloadItemImpl::Start(
    std::unique_ptr<DownloadFile> file,
    DownloadJob::CancelRequestCallback cancel_request_callback,
    const DownloadCreateInfo& new_create_info,
    URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr
        url_loader_factory_provider) {}

void DownloadItemImpl::OnDownloadFileInitialized(DownloadInterruptReason result,
                                                 int64_t bytes_wasted) {}

void DownloadItemImpl::DetermineDownloadTarget() {}

// Called by delegate_ when the download target path has been determined.
void DownloadItemImpl::OnDownloadTargetDetermined(
    DownloadTargetInfo target_info) {}

void DownloadItemImpl::OnDownloadRenamedToIntermediateName(
    DownloadInterruptReason reason,
    const base::FilePath& full_path) {}

void DownloadItemImpl::OnTargetResolved() {}

// When SavePackage downloads MHTML to GData (see
// SavePackageFilePickerChromeOS), GData calls MaybeCompleteDownload() like it
// does for non-SavePackage downloads, but SavePackage downloads never satisfy
// IsDownloadReadyForCompletion(). GDataDownloadObserver manually calls
// DownloadItem::UpdateObservers() when the upload completes so that
// SavePackage notices that the upload has completed and runs its normal
// Finish() pathway. MaybeCompleteDownload() is never the mechanism by which
// SavePackage completes downloads. SavePackage always uses its own Finish() to
// mark downloads complete.
void DownloadItemImpl::MaybeCompleteDownload() {}

// Called by MaybeCompleteDownload() when it has determined that the download
// is ready for completion.
void DownloadItemImpl::OnDownloadCompleting() {}

void DownloadItemImpl::OnRenameAndAnnotateDone(
    DownloadInterruptReason reason,
    const base::FilePath& full_path) {}

void DownloadItemImpl::OnDownloadRenamedToFinalName(
    DownloadInterruptReason reason,
    const base::FilePath& full_path) {}

void DownloadItemImpl::DelayedDownloadOpened(bool auto_opened) {}

void DownloadItemImpl::Completed() {}

// **** End of Download progression cascade

void DownloadItemImpl::InterruptAndDiscardPartialState(
    DownloadInterruptReason reason) {}

void DownloadItemImpl::InterruptWithPartialState(
    int64_t bytes_so_far,
    std::unique_ptr<crypto::SecureHash> hash_state,
    DownloadInterruptReason reason) {}

void DownloadItemImpl::UpdateProgress(int64_t bytes_so_far,
                                      int64_t bytes_per_sec) {}

void DownloadItemImpl::SetHashState(
    std::unique_ptr<crypto::SecureHash> hash_state) {}

void DownloadItemImpl::ReleaseDownloadFile(bool destroy_file) {}

void DownloadItemImpl::DeleteDownloadFile() {}

bool DownloadItemImpl::IsDownloadReadyForCompletion(
    base::OnceClosure state_change_notification) {}

void DownloadItemImpl::TransitionTo(DownloadInternalState new_state) {}

void DownloadItemImpl::SetDangerType(DownloadDangerType danger_type) {}

void DownloadItemImpl::SetFullPath(const base::FilePath& new_path) {}

void DownloadItemImpl::AutoResumeIfValid() {}

void DownloadItemImpl::ResumeInterruptedDownload(
    ResumptionRequestSource source) {}

// static
DownloadItem::DownloadState DownloadItemImpl::InternalToExternalState(
    DownloadInternalState internal_state) {}

// static
DownloadItemImpl::DownloadInternalState
DownloadItemImpl::ExternalToInternalState(DownloadState external_state) {}

// static
bool DownloadItemImpl::IsValidSavePackageStateTransition(
    DownloadInternalState from,
    DownloadInternalState to) {}

// static
bool DownloadItemImpl::IsValidStateTransition(DownloadInternalState from,
                                              DownloadInternalState to) {}

const char* DownloadItemImpl::DebugDownloadStateString(
    DownloadInternalState state) {}

const char* DownloadItemImpl::DebugResumeModeString(ResumeMode mode) {}

std::pair<int64_t, int64_t> DownloadItemImpl::GetRangeRequestOffset() const {}

void DownloadItemImpl::UpdateRenameProgress(int64_t bytes_so_far,
                                            int64_t bytes_per_sec) {}

}  // namespace download