#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "components/download/public/common/download_file_impl.h"
#include <algorithm>
#include <memory>
#include <string>
#include <utility>
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "build/build_config.h"
#include "components/download/internal/common/parallel_download_utils.h"
#include "components/download/public/common/download_create_info.h"
#include "components/download/public/common/download_destination_observer.h"
#include "components/download/public/common/download_features.h"
#include "components/download/public/common/download_interrupt_reasons_utils.h"
#include "components/download/public/common/download_stats.h"
#include "crypto/secure_hash.h"
#include "crypto/sha2.h"
#include "mojo/public/c/system/types.h"
#include "net/base/io_buffer.h"
#if BUILDFLAG(IS_ANDROID)
#include "base/android/content_uri_utils.h"
#include "components/download/internal/common/android/download_collection_bridge.h"
#endif
namespace download {
namespace {
const int kUpdatePeriodMs = …;
const int kMaxTimeBlockingFileThreadMs = …;
const int kInitialRenameRetryDelayMs = …;
const int kMaxRenameRetries = …;
const int kNoBytesToWrite = …;
const int kUnknownContentLength = …;
#if BUILDFLAG(IS_MAC)
void UnHideFile(const base::FilePath& path) {
base::stat_wrapper_t stat;
if (base::File::Stat(path, &stat) < 0) {
return;
}
if (!S_ISREG(stat.st_mode)) {
return;
}
if (base::StartsWith(path.BaseName().value(), ".")) {
return;
}
if (stat.st_flags & UF_HIDDEN) {
stat.st_flags ^= UF_HIDDEN;
chflags(path.value().c_str(), stat.st_flags);
}
}
#endif
}
DownloadFileImpl::SourceStream::SourceStream(
int64_t offset,
int64_t starting_file_write_offset,
std::unique_ptr<InputStream> stream)
: … { … }
DownloadFileImpl::SourceStream::~SourceStream() = default;
void DownloadFileImpl::SourceStream::Initialize() { … }
void DownloadFileImpl::SourceStream::OnBytesConsumed(int64_t bytes_read,
int64_t bytes_written) { … }
void DownloadFileImpl::SourceStream::TruncateLengthWithWrittenDataBlock(
int64_t received_slice_offset,
int64_t bytes_written) { … }
void DownloadFileImpl::SourceStream::RegisterDataReadyCallback(
const mojo::SimpleWatcher::ReadyCallback& callback) { … }
void DownloadFileImpl::SourceStream::ClearDataReadyCallback() { … }
DownloadInterruptReason DownloadFileImpl::SourceStream::GetCompletionStatus()
const { … }
void DownloadFileImpl::SourceStream::RegisterCompletionCallback(
DownloadFileImpl::SourceStream::CompletionCallback callback) { … }
InputStream::StreamState DownloadFileImpl::SourceStream::Read(
scoped_refptr<net::IOBuffer>* data,
size_t* length) { … }
size_t DownloadFileImpl::SourceStream::GetRemainingBytesToValidate() { … }
DownloadFileImpl::DownloadFileImpl(
std::unique_ptr<DownloadSaveInfo> save_info,
const base::FilePath& default_download_directory,
std::unique_ptr<InputStream> stream,
uint32_t download_id,
base::WeakPtr<DownloadDestinationObserver> observer)
: … { … }
DownloadFileImpl::~DownloadFileImpl() { … }
void DownloadFileImpl::Initialize(
InitializeCallback initialize_callback,
CancelRequestCallback cancel_request_callback,
const DownloadItem::ReceivedSlices& received_slices) { … }
void DownloadFileImpl::AddInputStream(std::unique_ptr<InputStream> stream,
int64_t offset) { … }
void DownloadFileImpl::OnSourceStreamAdded(SourceStream* source_stream) { … }
DownloadInterruptReason DownloadFileImpl::ValidateAndWriteDataToFile(
int64_t offset,
const char* data,
size_t bytes_to_validate,
size_t bytes_to_write) { … }
bool DownloadFileImpl::CalculateBytesToWrite(SourceStream* source_stream,
size_t bytes_available_to_write,
size_t* bytes_to_validate,
size_t* bytes_to_write) { … }
void DownloadFileImpl::RenameAndUniquify(const base::FilePath& full_path,
RenameCompletionCallback callback) { … }
void DownloadFileImpl::RenameAndAnnotate(
const base::FilePath& full_path,
const std::string& client_guid,
const GURL& source_url,
const GURL& referrer_url,
mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine,
RenameCompletionCallback callback) { … }
#if BUILDFLAG(IS_ANDROID)
void DownloadFileImpl::PublishDownload(RenameCompletionCallback callback) {
DownloadInterruptReason reason = file_.PublishDownload();
OnRenameComplete(file_.full_path(), std::move(callback), reason);
}
#endif
base::TimeDelta DownloadFileImpl::GetRetryDelayForFailedRename(
int attempt_number) { … }
bool DownloadFileImpl::ShouldRetryFailedRename(DownloadInterruptReason reason) { … }
DownloadInterruptReason DownloadFileImpl::HandleStreamCompletionStatus(
SourceStream* source_stream) { … }
void DownloadFileImpl::RenameWithRetryInternal(
std::unique_ptr<RenameParameters> parameters) { … }
void DownloadFileImpl::OnRenameComplete(const base::FilePath& new_path,
RenameCompletionCallback callback,
DownloadInterruptReason reason) { … }
void DownloadFileImpl::Detach() { … }
void DownloadFileImpl::Cancel() { … }
void DownloadFileImpl::SetPotentialFileLength(int64_t length) { … }
const base::FilePath& DownloadFileImpl::FullPath() const { … }
bool DownloadFileImpl::InProgress() const { … }
void DownloadFileImpl::Pause() { … }
void DownloadFileImpl::Resume() { … }
void DownloadFileImpl::StreamActive(SourceStream* source_stream,
MojoResult result) { … }
void DownloadFileImpl::OnStreamCompleted(SourceStream* source_stream) { … }
void DownloadFileImpl::NotifyObserver(SourceStream* source_stream,
DownloadInterruptReason reason,
InputStream::StreamState stream_state,
bool should_terminate) { … }
void DownloadFileImpl::OnDownloadCompleted() { … }
void DownloadFileImpl::RegisterAndActivateStream(SourceStream* source_stream) { … }
int64_t DownloadFileImpl::TotalBytesReceived() const { … }
void DownloadFileImpl::SendUpdate() { … }
void DownloadFileImpl::WillWriteToDisk(size_t data_len) { … }
void DownloadFileImpl::AddNewSlice(int64_t offset, int64_t length) { … }
bool DownloadFileImpl::IsDownloadCompleted() { … }
void DownloadFileImpl::HandleStreamError(SourceStream* source_stream,
DownloadInterruptReason reason) { … }
void DownloadFileImpl::SendErrorUpdateIfFinished(
DownloadInterruptReason reason) { … }
bool DownloadFileImpl::IsSparseFile() const { … }
DownloadFileImpl::SourceStream* DownloadFileImpl::FindPrecedingNeighbor(
SourceStream* source_stream) { … }
void DownloadFileImpl::CancelRequest(int64_t offset) { … }
void DownloadFileImpl::DebugStates() const { … }
void DownloadFileImpl::SetTaskRunnerForTesting(
scoped_refptr<base::SequencedTaskRunner> task_runner) { … }
DownloadFileImpl::RenameParameters::RenameParameters(
RenameOption option,
const base::FilePath& new_path,
RenameCompletionCallback completion_callback)
: … { … }
DownloadFileImpl::RenameParameters::~RenameParameters() { … }
}