This source file includes following definitions.
- VisitCountsToVisitedBefore
- weak_ptr_factory_
- DoLoop
- DoGenerateTargetPath
- DoNotifyExtensions
- NotifyExtensionsDone
- DoReserveVirtualPath
- ReserveVirtualPathDone
- DoPromptUserForDownloadPath
- PromptUserForDownloadPathDone
- DoDetermineLocalPath
- DetermineLocalPathDone
- DoDetermineMimeType
- DetermineMimeTypeDone
- InvokeClosureAfterGetPluginCallback
- IsHandledBySafePlugin
- DoDetermineIfHandledSafely
- DetermineIfHandledSafelyDone
- DoCheckDownloadUrl
- CheckDownloadUrlDone
- DoCheckVisitedReferrerBefore
- CheckVisitedReferrerBeforeDone
- DoDetermineIntermediatePath
- ScheduleCallbackAndDeleteSelf
- CancelOnFailureAndDeleteSelf
- GetProfile
- ShouldPromptForDownload
- HasPromptedForPath
- IsDangerousFile
- OnDownloadDestroyed
- Start
- GetCrDownloadPath
#include "chrome/browser/download/download_target_determiner.h"
#include "base/prefs/pref_service.h"
#include "base/rand_util.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "chrome/browser/download/chrome_download_manager_delegate.h"
#include "chrome/browser/download/download_crx_util.h"
#include "chrome/browser/download/download_extensions.h"
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/extensions/webstore_installer.h"
#include "chrome/browser/history/history_service.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_interrupt_reasons.h"
#include "extensions/common/constants.h"
#include "extensions/common/feature_switch.h"
#include "grit/generated_resources.h"
#include "net/base/mime_util.h"
#include "net/base/net_util.h"
#include "ui/base/l10n/l10n_util.h"
#if defined(ENABLE_PLUGINS)
#include "chrome/browser/plugins/plugin_prefs.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/common/webplugininfo.h"
#endif
using content::BrowserThread;
using content::DownloadItem;
namespace {
const base::FilePath::CharType kCrdownloadSuffix[] =
FILE_PATH_LITERAL(".crdownload");
void VisitCountsToVisitedBefore(
const base::Callback<void(bool)>& callback,
HistoryService::Handle unused_handle,
bool found_visits,
int count,
base::Time first_visit) {
callback.Run(
found_visits && count > 0 &&
(first_visit.LocalMidnight() < base::Time::Now().LocalMidnight()));
}
}
DownloadTargetInfo::DownloadTargetInfo()
: is_filetype_handled_safely(false) {}
DownloadTargetInfo::~DownloadTargetInfo() {}
DownloadTargetDeterminerDelegate::~DownloadTargetDeterminerDelegate() {
}
DownloadTargetDeterminer::DownloadTargetDeterminer(
DownloadItem* download,
const base::FilePath& initial_virtual_path,
DownloadPrefs* download_prefs,
DownloadTargetDeterminerDelegate* delegate,
const CompletionCallback& callback)
: next_state_(STATE_GENERATE_TARGET_PATH),
should_prompt_(false),
should_notify_extensions_(false),
create_target_directory_(false),
conflict_action_(DownloadPathReservationTracker::OVERWRITE),
danger_type_(download->GetDangerType()),
virtual_path_(initial_virtual_path),
is_filetype_handled_safely_(false),
download_(download),
is_resumption_(download_->GetLastReason() !=
content::DOWNLOAD_INTERRUPT_REASON_NONE &&
!initial_virtual_path.empty()),
download_prefs_(download_prefs),
delegate_(delegate),
completion_callback_(callback),
weak_ptr_factory_(this) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(download_);
DCHECK(delegate);
download_->AddObserver(this);
DoLoop();
}
DownloadTargetDeterminer::~DownloadTargetDeterminer() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(download_);
DCHECK(completion_callback_.is_null());
download_->RemoveObserver(this);
}
void DownloadTargetDeterminer::DoLoop() {
Result result = CONTINUE;
do {
State current_state = next_state_;
next_state_ = STATE_NONE;
switch (current_state) {
case STATE_GENERATE_TARGET_PATH:
result = DoGenerateTargetPath();
break;
case STATE_NOTIFY_EXTENSIONS:
result = DoNotifyExtensions();
break;
case STATE_RESERVE_VIRTUAL_PATH:
result = DoReserveVirtualPath();
break;
case STATE_PROMPT_USER_FOR_DOWNLOAD_PATH:
result = DoPromptUserForDownloadPath();
break;
case STATE_DETERMINE_LOCAL_PATH:
result = DoDetermineLocalPath();
break;
case STATE_DETERMINE_MIME_TYPE:
result = DoDetermineMimeType();
break;
case STATE_DETERMINE_IF_HANDLED_SAFELY_BY_BROWSER:
result = DoDetermineIfHandledSafely();
break;
case STATE_CHECK_DOWNLOAD_URL:
result = DoCheckDownloadUrl();
break;
case STATE_DETERMINE_INTERMEDIATE_PATH:
result = DoDetermineIntermediatePath();
break;
case STATE_CHECK_VISITED_REFERRER_BEFORE:
result = DoCheckVisitedReferrerBefore();
break;
case STATE_NONE:
NOTREACHED();
return;
}
} while (result == CONTINUE);
if (result == COMPLETE)
ScheduleCallbackAndDeleteSelf();
}
DownloadTargetDeterminer::Result
DownloadTargetDeterminer::DoGenerateTargetPath() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(local_path_.empty());
DCHECK(!should_prompt_);
DCHECK(!should_notify_extensions_);
DCHECK_EQ(DownloadPathReservationTracker::OVERWRITE, conflict_action_);
bool is_forced_path = !download_->GetForcedFilePath().empty();
next_state_ = STATE_NOTIFY_EXTENSIONS;
if (!virtual_path_.empty() && HasPromptedForPath() && !is_forced_path) {
should_prompt_ = ShouldPromptForDownload(virtual_path_);
} else if (!is_forced_path) {
std::string default_filename(
l10n_util::GetStringUTF8(IDS_DEFAULT_DOWNLOAD_FILENAME));
base::FilePath generated_filename = net::GenerateFileName(
download_->GetURL(),
download_->GetContentDisposition(),
GetProfile()->GetPrefs()->GetString(prefs::kDefaultCharset),
download_->GetSuggestedFilename(),
download_->GetMimeType(),
default_filename);
should_prompt_ = ShouldPromptForDownload(generated_filename);
base::FilePath target_directory;
if (should_prompt_) {
DCHECK(!download_prefs_->IsDownloadPathManaged());
target_directory = download_prefs_->SaveFilePath();
} else {
target_directory = download_prefs_->DownloadPath();
}
virtual_path_ = target_directory.Append(generated_filename);
conflict_action_ = DownloadPathReservationTracker::UNIQUIFY;
should_notify_extensions_ = true;
} else {
virtual_path_ = download_->GetForcedFilePath();
}
DCHECK(virtual_path_.IsAbsolute());
DVLOG(20) << "Generated virtual path: " << virtual_path_.AsUTF8Unsafe();
if (download_->GetState() != DownloadItem::IN_PROGRESS)
return COMPLETE;
return CONTINUE;
}
DownloadTargetDeterminer::Result
DownloadTargetDeterminer::DoNotifyExtensions() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!virtual_path_.empty());
next_state_ = STATE_RESERVE_VIRTUAL_PATH;
if (!should_notify_extensions_)
return CONTINUE;
delegate_->NotifyExtensions(download_, virtual_path_,
base::Bind(&DownloadTargetDeterminer::NotifyExtensionsDone,
weak_ptr_factory_.GetWeakPtr()));
return QUIT_DOLOOP;
}
void DownloadTargetDeterminer::NotifyExtensionsDone(
const base::FilePath& suggested_path,
DownloadPathReservationTracker::FilenameConflictAction conflict_action) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DVLOG(20) << "Extension suggested path: " << suggested_path.AsUTF8Unsafe();
if (!suggested_path.empty()) {
base::FilePath new_path(download_prefs_->DownloadPath().Append(
suggested_path).NormalizePathSeparators());
net::GenerateSafeFileName(std::string(), false, &new_path);
virtual_path_ = new_path;
create_target_directory_ = true;
conflict_action_ = conflict_action;
}
DoLoop();
}
DownloadTargetDeterminer::Result
DownloadTargetDeterminer::DoReserveVirtualPath() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!virtual_path_.empty());
next_state_ = STATE_PROMPT_USER_FOR_DOWNLOAD_PATH;
delegate_->ReserveVirtualPath(
download_, virtual_path_, create_target_directory_, conflict_action_,
base::Bind(&DownloadTargetDeterminer::ReserveVirtualPathDone,
weak_ptr_factory_.GetWeakPtr()));
return QUIT_DOLOOP;
}
void DownloadTargetDeterminer::ReserveVirtualPathDone(
const base::FilePath& path, bool verified) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DVLOG(20) << "Reserved path: " << path.AsUTF8Unsafe()
<< " Verified:" << verified;
should_prompt_ = (should_prompt_ || !verified);
virtual_path_ = path;
DoLoop();
}
DownloadTargetDeterminer::Result
DownloadTargetDeterminer::DoPromptUserForDownloadPath() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!virtual_path_.empty());
next_state_ = STATE_DETERMINE_LOCAL_PATH;
if (should_prompt_) {
delegate_->PromptUserForDownloadPath(
download_,
virtual_path_,
base::Bind(&DownloadTargetDeterminer::PromptUserForDownloadPathDone,
weak_ptr_factory_.GetWeakPtr()));
return QUIT_DOLOOP;
}
return CONTINUE;
}
void DownloadTargetDeterminer::PromptUserForDownloadPathDone(
const base::FilePath& virtual_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DVLOG(20) << "User selected path:" << virtual_path.AsUTF8Unsafe();
if (virtual_path.empty()) {
CancelOnFailureAndDeleteSelf();
return;
}
virtual_path_ = virtual_path;
download_prefs_->SetSaveFilePath(virtual_path_.DirName());
DoLoop();
}
DownloadTargetDeterminer::Result
DownloadTargetDeterminer::DoDetermineLocalPath() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!virtual_path_.empty());
DCHECK(local_path_.empty());
next_state_ = STATE_DETERMINE_MIME_TYPE;
delegate_->DetermineLocalPath(
download_,
virtual_path_,
base::Bind(&DownloadTargetDeterminer::DetermineLocalPathDone,
weak_ptr_factory_.GetWeakPtr()));
return QUIT_DOLOOP;
}
void DownloadTargetDeterminer::DetermineLocalPathDone(
const base::FilePath& local_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DVLOG(20) << "Local path: " << local_path.AsUTF8Unsafe();
if (local_path.empty()) {
CancelOnFailureAndDeleteSelf();
return;
}
local_path_ = local_path;
DoLoop();
}
DownloadTargetDeterminer::Result
DownloadTargetDeterminer::DoDetermineMimeType() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!virtual_path_.empty());
DCHECK(!local_path_.empty());
DCHECK(mime_type_.empty());
next_state_ = STATE_DETERMINE_IF_HANDLED_SAFELY_BY_BROWSER;
if (virtual_path_ == local_path_) {
delegate_->GetFileMimeType(
local_path_,
base::Bind(&DownloadTargetDeterminer::DetermineMimeTypeDone,
weak_ptr_factory_.GetWeakPtr()));
return QUIT_DOLOOP;
}
return CONTINUE;
}
void DownloadTargetDeterminer::DetermineMimeTypeDone(
const std::string& mime_type) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DVLOG(20) << "MIME type: " << mime_type;
mime_type_ = mime_type;
DoLoop();
}
#if defined(ENABLE_PLUGINS)
namespace {
void InvokeClosureAfterGetPluginCallback(
const base::Closure& closure,
const std::vector<content::WebPluginInfo>& unused) {
closure.Run();
}
enum ActionOnStalePluginList {
RETRY_IF_STALE_PLUGIN_LIST,
IGNORE_IF_STALE_PLUGIN_LIST
};
void IsHandledBySafePlugin(content::ResourceContext* resource_context,
const GURL& url,
const std::string& mime_type,
ActionOnStalePluginList stale_plugin_action,
const base::Callback<void(bool)>& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(!mime_type.empty());
using content::WebPluginInfo;
std::string actual_mime_type;
bool is_stale = false;
WebPluginInfo plugin_info;
content::PluginService* plugin_service =
content::PluginService::GetInstance();
bool plugin_found = plugin_service->GetPluginInfo(-1, -1, resource_context,
url, GURL(), mime_type,
false, &is_stale,
&plugin_info,
&actual_mime_type);
if (is_stale && stale_plugin_action == RETRY_IF_STALE_PLUGIN_LIST) {
plugin_service->GetPlugins(
base::Bind(&InvokeClosureAfterGetPluginCallback,
base::Bind(&IsHandledBySafePlugin,
resource_context,
url,
mime_type,
IGNORE_IF_STALE_PLUGIN_LIST,
callback)));
return;
}
DCHECK(!is_stale);
bool is_handled_safely =
plugin_found &&
(plugin_info.type == WebPluginInfo::PLUGIN_TYPE_PEPPER_IN_PROCESS ||
plugin_info.type == WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE, base::Bind(callback, is_handled_safely));
}
}
#endif
DownloadTargetDeterminer::Result
DownloadTargetDeterminer::DoDetermineIfHandledSafely() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!virtual_path_.empty());
DCHECK(!local_path_.empty());
DCHECK(!is_filetype_handled_safely_);
next_state_ = STATE_CHECK_DOWNLOAD_URL;
if (mime_type_.empty())
return CONTINUE;
if (net::IsSupportedMimeType(mime_type_)) {
is_filetype_handled_safely_ = true;
return CONTINUE;
}
#if defined(ENABLE_PLUGINS)
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
base::Bind(
&IsHandledBySafePlugin,
GetProfile()->GetResourceContext(),
net::FilePathToFileURL(local_path_),
mime_type_,
RETRY_IF_STALE_PLUGIN_LIST,
base::Bind(&DownloadTargetDeterminer::DetermineIfHandledSafelyDone,
weak_ptr_factory_.GetWeakPtr())));
return QUIT_DOLOOP;
#else
return CONTINUE;
#endif
}
void DownloadTargetDeterminer::DetermineIfHandledSafelyDone(
bool is_handled_safely) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
is_filetype_handled_safely_ = is_handled_safely;
DVLOG(20) << "Is file type handled safely: " << is_filetype_handled_safely_;
DoLoop();
}
DownloadTargetDeterminer::Result
DownloadTargetDeterminer::DoCheckDownloadUrl() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!virtual_path_.empty());
next_state_ = STATE_CHECK_VISITED_REFERRER_BEFORE;
delegate_->CheckDownloadUrl(
download_,
virtual_path_,
base::Bind(&DownloadTargetDeterminer::CheckDownloadUrlDone,
weak_ptr_factory_.GetWeakPtr()));
return QUIT_DOLOOP;
}
void DownloadTargetDeterminer::CheckDownloadUrlDone(
content::DownloadDangerType danger_type) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DVLOG(20) << "URL Check Result:" << danger_type;
danger_type_ = danger_type;
DoLoop();
}
DownloadTargetDeterminer::Result
DownloadTargetDeterminer::DoCheckVisitedReferrerBefore() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
next_state_ = STATE_DETERMINE_INTERMEDIATE_PATH;
if (danger_type_ != content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)
return CONTINUE;
if (IsDangerousFile(NO_VISITS_TO_REFERRER)) {
if (!IsDangerousFile(VISITED_REFERRER)) {
HistoryService* history_service = HistoryServiceFactory::GetForProfile(
GetProfile(), Profile::EXPLICIT_ACCESS);
if (history_service && download_->GetReferrerUrl().is_valid()) {
history_service->GetVisibleVisitCountToHost(
download_->GetReferrerUrl(), &history_consumer_,
base::Bind(&VisitCountsToVisitedBefore, base::Bind(
&DownloadTargetDeterminer::CheckVisitedReferrerBeforeDone,
weak_ptr_factory_.GetWeakPtr())));
return QUIT_DOLOOP;
}
}
danger_type_ = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE;
}
return CONTINUE;
}
void DownloadTargetDeterminer::CheckVisitedReferrerBeforeDone(
bool visited_referrer_before) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (IsDangerousFile(
visited_referrer_before ? VISITED_REFERRER : NO_VISITS_TO_REFERRER))
danger_type_ = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE;
DoLoop();
}
DownloadTargetDeterminer::Result
DownloadTargetDeterminer::DoDetermineIntermediatePath() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!virtual_path_.empty());
DCHECK(!local_path_.empty());
DCHECK(intermediate_path_.empty());
DCHECK(!virtual_path_.MatchesExtension(kCrdownloadSuffix));
DCHECK(!local_path_.MatchesExtension(kCrdownloadSuffix));
next_state_ = STATE_NONE;
if (virtual_path_.BaseName() != local_path_.BaseName()) {
intermediate_path_ = local_path_;
return COMPLETE;
}
if (danger_type_ == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS &&
!download_->GetForcedFilePath().empty()) {
DCHECK_EQ(download_->GetForcedFilePath().value(), local_path_.value());
intermediate_path_ = local_path_;
return COMPLETE;
}
if (danger_type_ == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) {
intermediate_path_ = GetCrDownloadPath(local_path_);
return COMPLETE;
}
if (is_resumption_ && !download_->GetFullPath().empty() &&
local_path_.DirName() == download_->GetFullPath().DirName()) {
DCHECK_NE(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
download_->GetDangerType());
DCHECK_EQ(kCrdownloadSuffix, download_->GetFullPath().Extension());
intermediate_path_ = download_->GetFullPath();
return COMPLETE;
}
const base::FilePath::CharType kUnconfirmedFormatSuffix[] =
FILE_PATH_LITERAL(" %d.crdownload");
const int kUnconfirmedUniquifierRange = 1000000;
#if defined(OS_WIN)
base::string16 unconfirmed_format =
l10n_util::GetStringUTF16(IDS_DOWNLOAD_UNCONFIRMED_PREFIX);
#else
std::string unconfirmed_format =
l10n_util::GetStringUTF8(IDS_DOWNLOAD_UNCONFIRMED_PREFIX);
#endif
unconfirmed_format.append(kUnconfirmedFormatSuffix);
base::FilePath::StringType file_name = base::StringPrintf(
unconfirmed_format.c_str(),
base::RandInt(0, kUnconfirmedUniquifierRange));
intermediate_path_ = local_path_.DirName().Append(file_name);
return COMPLETE;
}
void DownloadTargetDeterminer::ScheduleCallbackAndDeleteSelf() {
DCHECK(download_);
DVLOG(20) << "Scheduling callback. Virtual:" << virtual_path_.AsUTF8Unsafe()
<< " Local:" << local_path_.AsUTF8Unsafe()
<< " Intermediate:" << intermediate_path_.AsUTF8Unsafe()
<< " Should prompt:" << should_prompt_
<< " Danger type:" << danger_type_;
scoped_ptr<DownloadTargetInfo> target_info(new DownloadTargetInfo);
target_info->target_path = local_path_;
target_info->target_disposition =
(HasPromptedForPath() || should_prompt_
? DownloadItem::TARGET_DISPOSITION_PROMPT
: DownloadItem::TARGET_DISPOSITION_OVERWRITE);
target_info->danger_type = danger_type_;
target_info->intermediate_path = intermediate_path_;
target_info->mime_type = mime_type_;
target_info->is_filetype_handled_safely = is_filetype_handled_safely_;
base::MessageLoop::current()->PostTask(
FROM_HERE, base::Bind(completion_callback_, base::Passed(&target_info)));
completion_callback_.Reset();
delete this;
}
void DownloadTargetDeterminer::CancelOnFailureAndDeleteSelf() {
virtual_path_.clear();
local_path_.clear();
intermediate_path_.clear();
ScheduleCallbackAndDeleteSelf();
}
Profile* DownloadTargetDeterminer::GetProfile() {
DCHECK(download_->GetBrowserContext());
return Profile::FromBrowserContext(download_->GetBrowserContext());
}
bool DownloadTargetDeterminer::ShouldPromptForDownload(
const base::FilePath& filename) const {
if (is_resumption_) {
content::DownloadInterruptReason reason = download_->GetLastReason();
return (reason == content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED ||
reason == content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE ||
reason == content::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE);
}
if (!download_->GetForcedFilePath().empty()) {
DCHECK(DownloadItem::TARGET_DISPOSITION_PROMPT !=
download_->GetTargetDisposition());
return false;
}
if (download_prefs_->IsDownloadPathManaged())
return false;
if (download_->GetTargetDisposition() ==
DownloadItem::TARGET_DISPOSITION_PROMPT)
return true;
if (download_prefs_->PromptForDownload() &&
!download_crx_util::IsExtensionDownload(*download_) &&
!filename.MatchesExtension(extensions::kExtensionFileExtension) &&
!download_prefs_->IsAutoOpenEnabledBasedOnExtension(filename))
return true;
return false;
}
bool DownloadTargetDeterminer::HasPromptedForPath() const {
return (is_resumption_ && download_->GetTargetDisposition() ==
DownloadItem::TARGET_DISPOSITION_PROMPT);
}
bool DownloadTargetDeterminer::IsDangerousFile(PriorVisitsToReferrer visits) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (HasPromptedForPath() || should_prompt_ ||
!download_->GetForcedFilePath().empty())
return false;
const bool is_extension_download =
download_crx_util::IsExtensionDownload(*download_);
if (download_->HasUserGesture() &&
is_extension_download &&
download_crx_util::OffStoreInstallAllowedByPrefs(
GetProfile(), *download_)) {
return false;
}
if (extensions::FeatureSwitch::easy_off_store_install()->IsEnabled() &&
is_extension_download &&
!extensions::WebstoreInstaller::GetAssociatedApproval(*download_)) {
return true;
}
if (download_prefs_->IsAutoOpenEnabledBasedOnExtension(virtual_path_) &&
download_->HasUserGesture())
return false;
switch (download_util::GetFileDangerLevel(virtual_path_.BaseName())) {
case download_util::NOT_DANGEROUS:
return false;
case download_util::ALLOW_ON_USER_GESTURE:
if (download_->GetTransitionType() &
content::PAGE_TRANSITION_FROM_ADDRESS_BAR) {
return false;
}
return !download_->HasUserGesture() || visits == NO_VISITS_TO_REFERRER;
case download_util::DANGEROUS:
return true;
}
NOTREACHED();
return false;
}
void DownloadTargetDeterminer::OnDownloadDestroyed(
DownloadItem* download) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK_EQ(download_, download);
CancelOnFailureAndDeleteSelf();
}
void DownloadTargetDeterminer::Start(content::DownloadItem* download,
const base::FilePath& initial_virtual_path,
DownloadPrefs* download_prefs,
DownloadTargetDeterminerDelegate* delegate,
const CompletionCallback& callback) {
new DownloadTargetDeterminer(download, initial_virtual_path, download_prefs,
delegate, callback);
}
base::FilePath DownloadTargetDeterminer::GetCrDownloadPath(
const base::FilePath& suggested_path) {
return base::FilePath(suggested_path.value() + kCrdownloadSuffix);
}