#include "chrome/browser/download/download_target_determiner.h"
#include <optional>
#include <string>
#include <vector>
#include "base/files/file_path.h"
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/metrics/histogram_functions.h"
#include "base/rand_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "chrome/browser/download/chrome_download_manager_delegate.h"
#include "chrome/browser/download/download_confirmation_reason.h"
#include "chrome/browser/download/download_crx_util.h"
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/download/download_stats.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/safe_browsing/safe_browsing_metrics_collector_factory.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
#include "chrome/grit/generated_resources.h"
#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/download/public/common/download_item.h"
#include "components/download/public/common/download_target_info.h"
#include "components/history/core/browser/history_service.h"
#include "components/prefs/pref_service.h"
#include "components/safe_browsing/content/browser/download/download_stats.h"
#include "components/safe_browsing/content/common/file_type_policies.h"
#include "components/safe_browsing/core/browser/safe_browsing_metrics_collector.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/download_item_utils.h"
#include "extensions/buildflags/buildflags.h"
#include "extensions/common/constants.h"
#include "net/base/filename_util.h"
#include "net/http/http_content_disposition.h"
#include "ppapi/buildflags/buildflags.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/origin.h"
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "chrome/browser/extensions/webstore_installer.h"
#include "extensions/common/feature_switch.h"
#endif
#if BUILDFLAG(ENABLE_PLUGINS)
#include "chrome/browser/plugins/plugin_prefs.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/webplugininfo.h"
#endif
#if BUILDFLAG(IS_WIN)
#include "ui/shell_dialogs/select_file_utils_win.h"
#endif
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chrome/browser/ash/policy/dlp/dlp_files_controller_ash.h"
#include "chrome/browser/chromeos/policy/dlp/dlp_file_destination.h"
#include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h"
#include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager_factory.h"
#endif
#if BUILDFLAG(IS_ANDROID)
#include "components/safe_browsing/android/safe_browsing_api_handler_bridge.h"
#endif
BrowserThread;
DownloadItem;
DownloadPathReservationTracker;
DownloadFileType;
namespace {
const base::FilePath::CharType kCrdownloadSuffix[] = …);
void VisitCountsToVisitedBefore(base::OnceCallback<void(bool)> callback,
history::VisibleVisitCountToHostResult result) { … }
void GenerateSafeFileName(base::FilePath* new_path,
const base::FilePath::StringType& old_extension,
const std::string& mime_type) { … }
}
DownloadTargetDeterminerDelegate::~DownloadTargetDeterminerDelegate() = default;
DownloadTargetDeterminer::DownloadTargetDeterminer(
DownloadItem* download,
const base::FilePath& initial_virtual_path,
DownloadPathReservationTracker::FilenameConflictAction conflict_action,
DownloadPrefs* download_prefs,
DownloadTargetDeterminerDelegate* delegate,
CompletionCallback callback)
: … { … }
DownloadTargetDeterminer::~DownloadTargetDeterminer() { … }
void DownloadTargetDeterminer::DoLoop() { … }
DownloadTargetDeterminer::Result
DownloadTargetDeterminer::DoGenerateTargetPath() { … }
base::FilePath DownloadTargetDeterminer::GenerateFileName() const { … }
DownloadTargetDeterminer::Result
DownloadTargetDeterminer::DoSetInsecureDownloadStatus() { … }
void DownloadTargetDeterminer::GetInsecureDownloadStatusDone(
download::DownloadItem::InsecureDownloadStatus status) { … }
DownloadTargetDeterminer::Result
DownloadTargetDeterminer::DoNotifyExtensions() { … }
void DownloadTargetDeterminer::NotifyExtensionsDone(
const base::FilePath& suggested_path,
DownloadPathReservationTracker::FilenameConflictAction conflict_action) { … }
DownloadTargetDeterminer::Result
DownloadTargetDeterminer::DoReserveVirtualPath() { … }
void DownloadTargetDeterminer::ReserveVirtualPathDone(
download::PathValidationResult result,
const base::FilePath& path) { … }
#if BUILDFLAG(IS_ANDROID)
void DownloadTargetDeterminer::RequestIncognitoWarningConfirmationDone(
bool accepted) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (accepted) {
DoLoop();
} else {
ScheduleCallbackAndDeleteSelf(
download::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
return;
}
}
#endif
DownloadTargetDeterminer::Result
DownloadTargetDeterminer::DoRequestConfirmation() { … }
void DownloadTargetDeterminer::RequestConfirmationDone(
DownloadConfirmationResult result,
const ui::SelectedFileInfo& selected_file_info) { … }
DownloadTargetDeterminer::Result
DownloadTargetDeterminer::DoDetermineLocalPath() { … }
void DownloadTargetDeterminer::DetermineLocalPathDone(
const base::FilePath& local_path,
const base::FilePath& file_name) { … }
DownloadTargetDeterminer::Result
DownloadTargetDeterminer::DoDetermineMimeType() { … }
void DownloadTargetDeterminer::DetermineMimeTypeDone(
const std::string& mime_type) { … }
#if BUILDFLAG(ENABLE_PLUGINS)
namespace {
void InvokeClosureAfterGetPluginCallback(
base::OnceClosure closure,
const std::vector<content::WebPluginInfo>& unused) { … }
enum ActionOnStalePluginList { … };
void IsHandledBySafePlugin(content::BrowserContext* browser_context,
const GURL& url,
const std::string& mime_type,
ActionOnStalePluginList stale_plugin_action,
base::OnceCallback<void(bool)> callback) { … }
bool IsHandledBySafePluginSynchronous(content::BrowserContext* browser_context,
const GURL& url,
const std::string& mime_type) { … }
}
#endif
void DownloadTargetDeterminer::DetermineIfHandledSafelyHelper(
download::DownloadItem* download,
const base::FilePath& local_path,
const std::string& mime_type,
base::OnceCallback<void(bool)> callback) { … }
bool DownloadTargetDeterminer::DetermineIfHandledSafelyHelperSynchronous(
download::DownloadItem* download,
const base::FilePath& local_path,
const std::string& mime_type) { … }
DownloadTargetDeterminer::Result
DownloadTargetDeterminer::DoDetermineIfHandledSafely() { … }
void DownloadTargetDeterminer::DetermineIfHandledSafelyDone(
bool is_handled_safely) { … }
DownloadTargetDeterminer::Result
DownloadTargetDeterminer::DoCheckDownloadUrl() { … }
void DownloadTargetDeterminer::CheckDownloadUrlDone(
download::DownloadDangerType danger_type) { … }
#if BUILDFLAG(IS_ANDROID)
DownloadTargetDeterminer::Result
DownloadTargetDeterminer::DoCheckAppVerification() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
next_state_ = STATE_CHECK_VISITED_REFERRER_BEFORE;
safe_browsing::SafeBrowsingApiHandlerBridge::GetInstance()
.StartIsVerifyAppsEnabled(
base::BindOnce(&DownloadTargetDeterminer::CheckAppVerificationDone,
weak_ptr_factory_.GetWeakPtr()));
return QUIT_DOLOOP;
}
void DownloadTargetDeterminer::CheckAppVerificationDone(
safe_browsing::VerifyAppsEnabledResult result) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK_EQ(STATE_CHECK_VISITED_REFERRER_BEFORE, next_state_);
base::UmaHistogramEnumeration("SBClientDownload.AndroidAppVerificationResult",
result);
is_app_verification_enabled_ =
result == safe_browsing::VerifyAppsEnabledResult::SUCCESS_ENABLED;
DoLoop();
}
#endif
DownloadTargetDeterminer::Result
DownloadTargetDeterminer::DoCheckVisitedReferrerBefore() { … }
void DownloadTargetDeterminer::CheckVisitedReferrerBeforeDone(
bool visited_referrer_before) { … }
DownloadTargetDeterminer::Result
DownloadTargetDeterminer::DoDetermineIntermediatePath() { … }
void DownloadTargetDeterminer::ScheduleCallbackAndDeleteSelf(
download::DownloadInterruptReason interrupt_reason) { … }
Profile* DownloadTargetDeterminer::GetProfile() const { … }
DownloadConfirmationReason DownloadTargetDeterminer::NeedsConfirmation(
const base::FilePath& filename) const { … }
bool DownloadTargetDeterminer::IsDownloadDlpBlocked(
const base::FilePath& download_path) const { … }
bool DownloadTargetDeterminer::HasPromptedForPath() const { … }
DownloadFileType::DangerLevel DownloadTargetDeterminer::GetDangerLevel(
PriorVisitsToReferrer visits) const { … }
std::optional<base::Time>
DownloadTargetDeterminer::GetLastDownloadBypassTimestamp() const { … }
void DownloadTargetDeterminer::OnDownloadDestroyed(
DownloadItem* download) { … }
void DownloadTargetDeterminer::Start(
download::DownloadItem* download,
const base::FilePath& initial_virtual_path,
DownloadPathReservationTracker::FilenameConflictAction conflict_action,
DownloadPrefs* download_prefs,
DownloadTargetDeterminerDelegate* delegate,
CompletionCallback callback) { … }
base::FilePath DownloadTargetDeterminer::GetCrDownloadPath(
const base::FilePath& suggested_path) { … }