1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/download/download_target_determiner.h"
7 #include "base/prefs/pref_service.h"
8 #include "base/rand_util.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/time/time.h"
11 #include "chrome/browser/download/chrome_download_manager_delegate.h"
12 #include "chrome/browser/download/download_crx_util.h"
13 #include "chrome/browser/download/download_extensions.h"
14 #include "chrome/browser/download/download_prefs.h"
15 #include "chrome/browser/history/history_service_factory.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/common/pref_names.h"
18 #include "chrome/grit/generated_resources.h"
19 #include "components/history/core/browser/history_service.h"
20 #include "content/public/browser/browser_context.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/browser/download_interrupt_reasons.h"
23 #include "extensions/common/constants.h"
24 #include "net/base/filename_util.h"
25 #include "net/base/mime_util.h"
26 #include "ui/base/l10n/l10n_util.h"
28 #if defined(ENABLE_EXTENSIONS)
29 #include "chrome/browser/extensions/webstore_installer.h"
30 #include "extensions/common/feature_switch.h"
33 #if defined(ENABLE_PLUGINS)
34 #include "chrome/browser/plugins/plugin_prefs.h"
35 #include "content/public/browser/plugin_service.h"
36 #include "content/public/common/webplugininfo.h"
40 #include "chrome/browser/ui/pdf/adobe_reader_info_win.h"
43 using content::BrowserThread
;
44 using content::DownloadItem
;
48 const base::FilePath::CharType kCrdownloadSuffix
[] =
49 FILE_PATH_LITERAL(".crdownload");
51 // Condenses the results from HistoryService::GetVisibleVisitCountToHost() to a
52 // single bool. A host is considered visited before if prior visible visits were
53 // found in history and the first such visit was earlier than the most recent
55 void VisitCountsToVisitedBefore(
56 const base::Callback
<void(bool)>& callback
,
59 base::Time first_visit
) {
61 found_visits
&& count
> 0 &&
62 (first_visit
.LocalMidnight() < base::Time::Now().LocalMidnight()));
66 // Keeps track of whether Adobe Reader is up to date.
67 bool g_is_adobe_reader_up_to_date_
= false;
72 DownloadTargetInfo::DownloadTargetInfo()
73 : is_filetype_handled_safely(false) {}
75 DownloadTargetInfo::~DownloadTargetInfo() {}
77 DownloadTargetDeterminerDelegate::~DownloadTargetDeterminerDelegate() {
80 DownloadTargetDeterminer::DownloadTargetDeterminer(
81 DownloadItem
* download
,
82 const base::FilePath
& initial_virtual_path
,
83 DownloadPrefs
* download_prefs
,
84 DownloadTargetDeterminerDelegate
* delegate
,
85 const CompletionCallback
& callback
)
86 : next_state_(STATE_GENERATE_TARGET_PATH
),
87 should_prompt_(false),
88 should_notify_extensions_(false),
89 create_target_directory_(false),
90 conflict_action_(DownloadPathReservationTracker::OVERWRITE
),
91 danger_type_(download
->GetDangerType()),
92 is_dangerous_file_(false),
93 virtual_path_(initial_virtual_path
),
94 is_filetype_handled_safely_(false),
96 is_resumption_(download_
->GetLastReason() !=
97 content::DOWNLOAD_INTERRUPT_REASON_NONE
&&
98 !initial_virtual_path
.empty()),
99 download_prefs_(download_prefs
),
101 completion_callback_(callback
),
102 weak_ptr_factory_(this) {
103 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
106 download_
->AddObserver(this);
111 DownloadTargetDeterminer::~DownloadTargetDeterminer() {
112 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
114 DCHECK(completion_callback_
.is_null());
115 download_
->RemoveObserver(this);
118 void DownloadTargetDeterminer::DoLoop() {
119 Result result
= CONTINUE
;
121 State current_state
= next_state_
;
122 next_state_
= STATE_NONE
;
124 switch (current_state
) {
125 case STATE_GENERATE_TARGET_PATH
:
126 result
= DoGenerateTargetPath();
128 case STATE_NOTIFY_EXTENSIONS
:
129 result
= DoNotifyExtensions();
131 case STATE_RESERVE_VIRTUAL_PATH
:
132 result
= DoReserveVirtualPath();
134 case STATE_PROMPT_USER_FOR_DOWNLOAD_PATH
:
135 result
= DoPromptUserForDownloadPath();
137 case STATE_DETERMINE_LOCAL_PATH
:
138 result
= DoDetermineLocalPath();
140 case STATE_DETERMINE_MIME_TYPE
:
141 result
= DoDetermineMimeType();
143 case STATE_DETERMINE_IF_HANDLED_SAFELY_BY_BROWSER
:
144 result
= DoDetermineIfHandledSafely();
146 case STATE_DETERMINE_IF_ADOBE_READER_UP_TO_DATE
:
147 result
= DoDetermineIfAdobeReaderUpToDate();
149 case STATE_CHECK_DOWNLOAD_URL
:
150 result
= DoCheckDownloadUrl();
152 case STATE_DETERMINE_INTERMEDIATE_PATH
:
153 result
= DoDetermineIntermediatePath();
155 case STATE_CHECK_VISITED_REFERRER_BEFORE
:
156 result
= DoCheckVisitedReferrerBefore();
162 } while (result
== CONTINUE
);
163 // Note that if a callback completes synchronously, the handler will still
164 // return QUIT_DOLOOP. In this case, an inner DoLoop() may complete the target
165 // determination and delete |this|.
167 if (result
== COMPLETE
)
168 ScheduleCallbackAndDeleteSelf();
171 DownloadTargetDeterminer::Result
172 DownloadTargetDeterminer::DoGenerateTargetPath() {
173 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
174 DCHECK(local_path_
.empty());
175 DCHECK(!should_prompt_
);
176 DCHECK(!should_notify_extensions_
);
177 DCHECK_EQ(DownloadPathReservationTracker::OVERWRITE
, conflict_action_
);
178 bool is_forced_path
= !download_
->GetForcedFilePath().empty();
180 next_state_
= STATE_NOTIFY_EXTENSIONS
;
182 if (!virtual_path_
.empty() && HasPromptedForPath() && !is_forced_path
) {
183 // The download is being resumed and the user has already been prompted for
184 // a path. Assume that it's okay to overwrite the file if there's a conflict
185 // and reuse the selection.
186 should_prompt_
= ShouldPromptForDownload(virtual_path_
);
187 } else if (!is_forced_path
) {
188 // If we don't have a forced path, we should construct a path for the
189 // download. Forced paths are only specified for programmatic downloads
190 // (WebStore, Drag&Drop). Treat the path as a virtual path. We will
191 // eventually determine whether this is a local path and if not, figure out
193 std::string
default_filename(
194 l10n_util::GetStringUTF8(IDS_DEFAULT_DOWNLOAD_FILENAME
));
195 base::FilePath generated_filename
= net::GenerateFileName(
197 download_
->GetContentDisposition(),
198 GetProfile()->GetPrefs()->GetString(prefs::kDefaultCharset
),
199 download_
->GetSuggestedFilename(),
200 download_
->GetMimeType(),
202 should_prompt_
= ShouldPromptForDownload(generated_filename
);
203 base::FilePath target_directory
;
204 if (should_prompt_
) {
205 DCHECK(!download_prefs_
->IsDownloadPathManaged());
206 // If the user is going to be prompted and the user has been prompted
207 // before, then always prefer the last directory that the user selected.
208 target_directory
= download_prefs_
->SaveFilePath();
210 target_directory
= download_prefs_
->DownloadPath();
212 virtual_path_
= target_directory
.Append(generated_filename
);
213 #if defined(OS_ANDROID)
214 conflict_action_
= DownloadPathReservationTracker::PROMPT
;
216 conflict_action_
= DownloadPathReservationTracker::UNIQUIFY
;
218 should_notify_extensions_
= true;
220 virtual_path_
= download_
->GetForcedFilePath();
221 // If this is a resumed download which was previously interrupted due to an
222 // issue with the forced path, the user is still not prompted. If the path
223 // supplied to a programmatic download is invalid, then the caller needs to
226 DCHECK(virtual_path_
.IsAbsolute());
227 DVLOG(20) << "Generated virtual path: " << virtual_path_
.AsUTF8Unsafe();
229 // If the download is DOA, don't bother going any further. This would be the
230 // case for a download that failed to initialize (e.g. the initial temporary
231 // file couldn't be created because both the downloads directory and the
232 // temporary directory are unwriteable).
234 // A virtual path is determined for DOA downloads for display purposes. This
235 // is why this check is performed here instead of at the start.
236 if (download_
->GetState() != DownloadItem::IN_PROGRESS
)
241 DownloadTargetDeterminer::Result
242 DownloadTargetDeterminer::DoNotifyExtensions() {
243 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
244 DCHECK(!virtual_path_
.empty());
246 next_state_
= STATE_RESERVE_VIRTUAL_PATH
;
248 if (!should_notify_extensions_
)
251 delegate_
->NotifyExtensions(download_
, virtual_path_
,
252 base::Bind(&DownloadTargetDeterminer::NotifyExtensionsDone
,
253 weak_ptr_factory_
.GetWeakPtr()));
257 void DownloadTargetDeterminer::NotifyExtensionsDone(
258 const base::FilePath
& suggested_path
,
259 DownloadPathReservationTracker::FilenameConflictAction conflict_action
) {
260 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
261 DVLOG(20) << "Extension suggested path: " << suggested_path
.AsUTF8Unsafe();
263 // Extensions should not call back here more than once.
264 DCHECK_EQ(STATE_RESERVE_VIRTUAL_PATH
, next_state_
);
266 if (!suggested_path
.empty()) {
267 // If an extension overrides the filename, then the target directory will be
268 // forced to download_prefs_->DownloadPath() since extensions cannot place
269 // downloaded files anywhere except there. This prevents subdirectories from
270 // accumulating: if an extension is allowed to say that a file should go in
271 // last_download_path/music/foo.mp3, then last_download_path will accumulate
272 // the subdirectory /music/ so that the next download may end up in
273 // Downloads/music/music/music/bar.mp3.
274 base::FilePath
new_path(download_prefs_
->DownloadPath().Append(
275 suggested_path
).NormalizePathSeparators());
276 // Do not pass a mime type to GenerateSafeFileName so that it does not force
277 // the filename to have an extension if the (Chrome) extension does not
279 net::GenerateSafeFileName(std::string(), false, &new_path
);
280 virtual_path_
= new_path
;
281 create_target_directory_
= true;
283 // An extension may set conflictAction without setting filename.
284 if (conflict_action
!= DownloadPathReservationTracker::UNIQUIFY
)
285 conflict_action_
= conflict_action
;
290 DownloadTargetDeterminer::Result
291 DownloadTargetDeterminer::DoReserveVirtualPath() {
292 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
293 DCHECK(!virtual_path_
.empty());
295 next_state_
= STATE_PROMPT_USER_FOR_DOWNLOAD_PATH
;
297 delegate_
->ReserveVirtualPath(
298 download_
, virtual_path_
, create_target_directory_
, conflict_action_
,
299 base::Bind(&DownloadTargetDeterminer::ReserveVirtualPathDone
,
300 weak_ptr_factory_
.GetWeakPtr()));
304 void DownloadTargetDeterminer::ReserveVirtualPathDone(
305 const base::FilePath
& path
, bool verified
) {
306 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
307 DVLOG(20) << "Reserved path: " << path
.AsUTF8Unsafe()
308 << " Verified:" << verified
;
309 DCHECK_EQ(STATE_PROMPT_USER_FOR_DOWNLOAD_PATH
, next_state_
);
311 should_prompt_
= (should_prompt_
|| !verified
);
312 virtual_path_
= path
;
316 DownloadTargetDeterminer::Result
317 DownloadTargetDeterminer::DoPromptUserForDownloadPath() {
318 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
319 DCHECK(!virtual_path_
.empty());
321 next_state_
= STATE_DETERMINE_LOCAL_PATH
;
323 if (should_prompt_
) {
324 delegate_
->PromptUserForDownloadPath(
327 base::Bind(&DownloadTargetDeterminer::PromptUserForDownloadPathDone
,
328 weak_ptr_factory_
.GetWeakPtr()));
334 void DownloadTargetDeterminer::PromptUserForDownloadPathDone(
335 const base::FilePath
& virtual_path
) {
336 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
337 DVLOG(20) << "User selected path:" << virtual_path
.AsUTF8Unsafe();
338 if (virtual_path
.empty()) {
339 CancelOnFailureAndDeleteSelf();
342 DCHECK_EQ(STATE_DETERMINE_LOCAL_PATH
, next_state_
);
344 virtual_path_
= virtual_path
;
345 download_prefs_
->SetSaveFilePath(virtual_path_
.DirName());
349 DownloadTargetDeterminer::Result
350 DownloadTargetDeterminer::DoDetermineLocalPath() {
351 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
352 DCHECK(!virtual_path_
.empty());
353 DCHECK(local_path_
.empty());
355 next_state_
= STATE_DETERMINE_MIME_TYPE
;
357 delegate_
->DetermineLocalPath(
360 base::Bind(&DownloadTargetDeterminer::DetermineLocalPathDone
,
361 weak_ptr_factory_
.GetWeakPtr()));
365 void DownloadTargetDeterminer::DetermineLocalPathDone(
366 const base::FilePath
& local_path
) {
367 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
368 DVLOG(20) << "Local path: " << local_path
.AsUTF8Unsafe();
369 if (local_path
.empty()) {
370 // Path subsitution failed.
371 CancelOnFailureAndDeleteSelf();
374 DCHECK_EQ(STATE_DETERMINE_MIME_TYPE
, next_state_
);
376 local_path_
= local_path
;
380 DownloadTargetDeterminer::Result
381 DownloadTargetDeterminer::DoDetermineMimeType() {
382 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
383 DCHECK(!virtual_path_
.empty());
384 DCHECK(!local_path_
.empty());
385 DCHECK(mime_type_
.empty());
387 next_state_
= STATE_DETERMINE_IF_HANDLED_SAFELY_BY_BROWSER
;
389 if (virtual_path_
== local_path_
) {
390 delegate_
->GetFileMimeType(
392 base::Bind(&DownloadTargetDeterminer::DetermineMimeTypeDone
,
393 weak_ptr_factory_
.GetWeakPtr()));
399 void DownloadTargetDeterminer::DetermineMimeTypeDone(
400 const std::string
& mime_type
) {
401 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
402 DVLOG(20) << "MIME type: " << mime_type
;
403 DCHECK_EQ(STATE_DETERMINE_IF_HANDLED_SAFELY_BY_BROWSER
, next_state_
);
405 mime_type_
= mime_type
;
409 #if defined(ENABLE_PLUGINS)
410 // The code below is used by DoDetermineIfHandledSafely to determine if the
411 // file type is handled by a sandboxed plugin.
414 void InvokeClosureAfterGetPluginCallback(
415 const base::Closure
& closure
,
416 const std::vector
<content::WebPluginInfo
>& unused
) {
420 enum ActionOnStalePluginList
{
421 RETRY_IF_STALE_PLUGIN_LIST
,
422 IGNORE_IF_STALE_PLUGIN_LIST
425 void IsHandledBySafePlugin(content::ResourceContext
* resource_context
,
427 const std::string
& mime_type
,
428 ActionOnStalePluginList stale_plugin_action
,
429 const base::Callback
<void(bool)>& callback
) {
430 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
431 DCHECK(!mime_type
.empty());
432 using content::WebPluginInfo
;
434 std::string actual_mime_type
;
435 bool is_stale
= false;
436 WebPluginInfo plugin_info
;
438 content::PluginService
* plugin_service
=
439 content::PluginService::GetInstance();
440 bool plugin_found
= plugin_service
->GetPluginInfo(-1, -1, resource_context
,
441 url
, GURL(), mime_type
,
445 if (is_stale
&& stale_plugin_action
== RETRY_IF_STALE_PLUGIN_LIST
) {
446 // The GetPlugins call causes the plugin list to be refreshed. Once that's
447 // done we can retry the GetPluginInfo call. We break out of this cycle
448 // after a single retry in order to avoid retrying indefinitely.
449 plugin_service
->GetPlugins(
450 base::Bind(&InvokeClosureAfterGetPluginCallback
,
451 base::Bind(&IsHandledBySafePlugin
,
455 IGNORE_IF_STALE_PLUGIN_LIST
,
459 // In practice, we assume that retrying once is enough.
461 bool is_handled_safely
=
463 (plugin_info
.type
== WebPluginInfo::PLUGIN_TYPE_PEPPER_IN_PROCESS
||
464 plugin_info
.type
== WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS
);
465 BrowserThread::PostTask(
466 BrowserThread::UI
, FROM_HERE
, base::Bind(callback
, is_handled_safely
));
470 #endif // defined(ENABLE_PLUGINS)
472 DownloadTargetDeterminer::Result
473 DownloadTargetDeterminer::DoDetermineIfHandledSafely() {
474 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
475 DCHECK(!virtual_path_
.empty());
476 DCHECK(!local_path_
.empty());
477 DCHECK(!is_filetype_handled_safely_
);
479 next_state_
= STATE_DETERMINE_IF_ADOBE_READER_UP_TO_DATE
;
481 if (mime_type_
.empty())
484 if (net::IsSupportedMimeType(mime_type_
)) {
485 is_filetype_handled_safely_
= true;
489 #if defined(ENABLE_PLUGINS)
490 BrowserThread::PostTask(
494 &IsHandledBySafePlugin
,
495 GetProfile()->GetResourceContext(),
496 net::FilePathToFileURL(local_path_
),
498 RETRY_IF_STALE_PLUGIN_LIST
,
499 base::Bind(&DownloadTargetDeterminer::DetermineIfHandledSafelyDone
,
500 weak_ptr_factory_
.GetWeakPtr())));
507 #if defined(ENABLE_PLUGINS)
508 void DownloadTargetDeterminer::DetermineIfHandledSafelyDone(
509 bool is_handled_safely
) {
510 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
511 DVLOG(20) << "Is file type handled safely: " << is_filetype_handled_safely_
;
512 DCHECK_EQ(STATE_DETERMINE_IF_ADOBE_READER_UP_TO_DATE
, next_state_
);
513 is_filetype_handled_safely_
= is_handled_safely
;
518 DownloadTargetDeterminer::Result
519 DownloadTargetDeterminer::DoDetermineIfAdobeReaderUpToDate() {
520 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
522 next_state_
= STATE_CHECK_DOWNLOAD_URL
;
525 if (!local_path_
.MatchesExtension(FILE_PATH_LITERAL(".pdf")))
527 if (!IsAdobeReaderDefaultPDFViewer()) {
528 g_is_adobe_reader_up_to_date_
= false;
532 base::PostTaskAndReplyWithResult(
533 BrowserThread::GetBlockingPool(),
535 base::Bind(&::IsAdobeReaderUpToDate
),
536 base::Bind(&DownloadTargetDeterminer::DetermineIfAdobeReaderUpToDateDone
,
537 weak_ptr_factory_
.GetWeakPtr()));
545 void DownloadTargetDeterminer::DetermineIfAdobeReaderUpToDateDone(
546 bool adobe_reader_up_to_date
) {
547 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
548 DVLOG(20) << "Is Adobe Reader Up To Date: " << adobe_reader_up_to_date
;
549 DCHECK_EQ(STATE_CHECK_DOWNLOAD_URL
, next_state_
);
550 g_is_adobe_reader_up_to_date_
= adobe_reader_up_to_date
;
555 DownloadTargetDeterminer::Result
556 DownloadTargetDeterminer::DoCheckDownloadUrl() {
557 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
558 DCHECK(!virtual_path_
.empty());
559 next_state_
= STATE_CHECK_VISITED_REFERRER_BEFORE
;
560 delegate_
->CheckDownloadUrl(
563 base::Bind(&DownloadTargetDeterminer::CheckDownloadUrlDone
,
564 weak_ptr_factory_
.GetWeakPtr()));
568 void DownloadTargetDeterminer::CheckDownloadUrlDone(
569 content::DownloadDangerType danger_type
) {
570 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
571 DVLOG(20) << "URL Check Result:" << danger_type
;
572 DCHECK_EQ(STATE_CHECK_VISITED_REFERRER_BEFORE
, next_state_
);
573 danger_type_
= danger_type
;
577 DownloadTargetDeterminer::Result
578 DownloadTargetDeterminer::DoCheckVisitedReferrerBefore() {
579 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
581 next_state_
= STATE_DETERMINE_INTERMEDIATE_PATH
;
583 // Checking if there are prior visits to the referrer is only necessary if the
584 // danger level of the download depends on the file type.
585 if (danger_type_
!= content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
&&
586 danger_type_
!= content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT
)
590 // IsDangerousFile(VISITED_REFERRER) => IsDangerousFile(NO_VISITS_...)
591 // I.e. having visited a referrer only lowers a file's danger level.
592 if (IsDangerousFile(NO_VISITS_TO_REFERRER
)) {
593 // Only need to ping the history DB if the download would be considered safe
594 // if there are prior visits and is considered dangerous otherwise.
595 if (!IsDangerousFile(VISITED_REFERRER
)) {
596 // HistoryServiceFactory redirects incognito profiles to on-record
597 // profiles. There's no history for on-record profiles in unit_tests.
598 history::HistoryService
* history_service
=
599 HistoryServiceFactory::GetForProfile(
600 GetProfile(), ServiceAccessType::EXPLICIT_ACCESS
);
602 if (history_service
&& download_
->GetReferrerUrl().is_valid()) {
603 history_service
->GetVisibleVisitCountToHost(
604 download_
->GetReferrerUrl(),
606 &VisitCountsToVisitedBefore
,
608 &DownloadTargetDeterminer::CheckVisitedReferrerBeforeDone
,
609 weak_ptr_factory_
.GetWeakPtr())),
615 // If the danger level doesn't depend on having visited the refererrer URL
616 // or if original profile doesn't have a HistoryService or the referrer url
617 // is invalid, then assume the referrer has not been visited before.
618 is_dangerous_file_
= true;
619 if (danger_type_
== content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
)
620 danger_type_
= content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE
;
625 void DownloadTargetDeterminer::CheckVisitedReferrerBeforeDone(
626 bool visited_referrer_before
) {
627 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
628 DCHECK_EQ(STATE_DETERMINE_INTERMEDIATE_PATH
, next_state_
);
629 if (IsDangerousFile(visited_referrer_before
? VISITED_REFERRER
630 : NO_VISITS_TO_REFERRER
)) {
631 is_dangerous_file_
= true;
632 if (danger_type_
== content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
)
633 danger_type_
= content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE
;
638 DownloadTargetDeterminer::Result
639 DownloadTargetDeterminer::DoDetermineIntermediatePath() {
640 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
641 DCHECK(!virtual_path_
.empty());
642 DCHECK(!local_path_
.empty());
643 DCHECK(intermediate_path_
.empty());
644 DCHECK(!virtual_path_
.MatchesExtension(kCrdownloadSuffix
));
645 DCHECK(!local_path_
.MatchesExtension(kCrdownloadSuffix
));
647 next_state_
= STATE_NONE
;
649 // Note that the intermediate filename is always uniquified (i.e. if a file by
650 // the same name exists, it is never overwritten). Therefore the code below
651 // does not attempt to find a name that doesn't conflict with an existing
654 // If the actual target of the download is a virtual path, then the local path
655 // is considered to point to a temporary path. A separate intermediate path is
656 // unnecessary since the local path already serves that purpose.
657 if (virtual_path_
.BaseName() != local_path_
.BaseName()) {
658 intermediate_path_
= local_path_
;
662 // If the download has a forced path and is safe, then just use the
663 // target path. In practice the temporary download file that was created prior
664 // to download filename determination is already named
665 // download_->GetForcedFilePath().
666 if (danger_type_
== content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
&&
667 !download_
->GetForcedFilePath().empty()) {
668 DCHECK_EQ(download_
->GetForcedFilePath().value(), local_path_
.value());
669 intermediate_path_
= local_path_
;
673 // Other safe downloads get a .crdownload suffix for their intermediate name.
674 if (danger_type_
== content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
) {
675 intermediate_path_
= GetCrDownloadPath(local_path_
);
679 // If this is a resumed download, then re-use the existing intermediate path
680 // if one is available. A resumed download shouldn't cause a non-dangerous
681 // download to be considered dangerous upon resumption. Therefore the
682 // intermediate file should already be in the correct form.
683 if (is_resumption_
&& !download_
->GetFullPath().empty() &&
684 local_path_
.DirName() == download_
->GetFullPath().DirName()) {
685 DCHECK_NE(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS
,
686 download_
->GetDangerType());
687 DCHECK_EQ(kCrdownloadSuffix
, download_
->GetFullPath().Extension());
688 intermediate_path_
= download_
->GetFullPath();
692 // Dangerous downloads receive a random intermediate name that looks like:
693 // 'Unconfirmed <random>.crdownload'.
694 const base::FilePath::CharType kUnconfirmedFormatSuffix
[] =
695 FILE_PATH_LITERAL(" %d.crdownload");
696 // Range of the <random> uniquifier.
697 const int kUnconfirmedUniquifierRange
= 1000000;
699 base::string16 unconfirmed_format
=
700 l10n_util::GetStringUTF16(IDS_DOWNLOAD_UNCONFIRMED_PREFIX
);
702 std::string unconfirmed_format
=
703 l10n_util::GetStringUTF8(IDS_DOWNLOAD_UNCONFIRMED_PREFIX
);
705 unconfirmed_format
.append(kUnconfirmedFormatSuffix
);
707 base::FilePath::StringType file_name
= base::StringPrintf(
708 unconfirmed_format
.c_str(),
709 base::RandInt(0, kUnconfirmedUniquifierRange
));
710 intermediate_path_
= local_path_
.DirName().Append(file_name
);
714 void DownloadTargetDeterminer::ScheduleCallbackAndDeleteSelf() {
716 DVLOG(20) << "Scheduling callback. Virtual:" << virtual_path_
.AsUTF8Unsafe()
717 << " Local:" << local_path_
.AsUTF8Unsafe()
718 << " Intermediate:" << intermediate_path_
.AsUTF8Unsafe()
719 << " Should prompt:" << should_prompt_
720 << " Danger type:" << danger_type_
721 << " Is dangerous file:" << is_dangerous_file_
;
722 scoped_ptr
<DownloadTargetInfo
> target_info(new DownloadTargetInfo
);
724 target_info
->target_path
= local_path_
;
725 target_info
->target_disposition
=
726 (HasPromptedForPath() || should_prompt_
727 ? DownloadItem::TARGET_DISPOSITION_PROMPT
728 : DownloadItem::TARGET_DISPOSITION_OVERWRITE
);
729 target_info
->danger_type
= danger_type_
;
730 target_info
->is_dangerous_file
= is_dangerous_file_
;
731 target_info
->intermediate_path
= intermediate_path_
;
732 target_info
->mime_type
= mime_type_
;
733 target_info
->is_filetype_handled_safely
= is_filetype_handled_safely_
;
735 base::MessageLoop::current()->PostTask(
736 FROM_HERE
, base::Bind(completion_callback_
, base::Passed(&target_info
)));
737 completion_callback_
.Reset();
741 void DownloadTargetDeterminer::CancelOnFailureAndDeleteSelf() {
742 // Path substitution failed.
743 virtual_path_
.clear();
745 intermediate_path_
.clear();
746 ScheduleCallbackAndDeleteSelf();
749 Profile
* DownloadTargetDeterminer::GetProfile() {
750 DCHECK(download_
->GetBrowserContext());
751 return Profile::FromBrowserContext(download_
->GetBrowserContext());
754 bool DownloadTargetDeterminer::ShouldPromptForDownload(
755 const base::FilePath
& filename
) const {
756 if (is_resumption_
) {
757 // For resumed downloads, if the target disposition or prefs require
758 // prompting, the user has already been prompted. Try to respect the user's
759 // selection, unless we've discovered that the target path cannot be used
761 content::DownloadInterruptReason reason
= download_
->GetLastReason();
762 return (reason
== content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED
||
763 reason
== content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
||
764 reason
== content::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE
);
767 // If the download path is forced, don't prompt.
768 if (!download_
->GetForcedFilePath().empty()) {
769 // 'Save As' downloads shouldn't have a forced path.
770 DCHECK(DownloadItem::TARGET_DISPOSITION_PROMPT
!=
771 download_
->GetTargetDisposition());
775 // Don't ask where to save if the download path is managed. Even if the user
776 // wanted to be prompted for "all" downloads, or if this was a 'Save As'
778 if (download_prefs_
->IsDownloadPathManaged())
781 // Prompt if this is a 'Save As' download.
782 if (download_
->GetTargetDisposition() ==
783 DownloadItem::TARGET_DISPOSITION_PROMPT
)
786 // Check if the user has the "Always prompt for download location" preference
787 // set. If so we prompt for most downloads except for the following scenarios:
788 // 1) Extension installation. Note that we only care here about the case where
789 // an extension is installed, not when one is downloaded with "save as...".
790 // 2) Filetypes marked "always open." If the user just wants this file opened,
791 // don't bother asking where to keep it.
792 if (download_prefs_
->PromptForDownload() &&
793 !download_crx_util::IsExtensionDownload(*download_
) &&
794 !filename
.MatchesExtension(extensions::kExtensionFileExtension
) &&
795 !download_prefs_
->IsAutoOpenEnabledBasedOnExtension(filename
))
798 // Otherwise, don't prompt. Note that the user might still be prompted if
799 // there are unresolved conflicts during path reservation (e.g. due to the
800 // target path being unwriteable or because there are too many conflicting
801 // files), or if an extension signals that the user be prompted on a filename
806 bool DownloadTargetDeterminer::HasPromptedForPath() const {
807 return (is_resumption_
&& download_
->GetTargetDisposition() ==
808 DownloadItem::TARGET_DISPOSITION_PROMPT
);
811 bool DownloadTargetDeterminer::IsDangerousFile(PriorVisitsToReferrer visits
) {
812 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
814 // If the user has has been prompted or will be, assume that the user has
815 // approved the download. A programmatic download is considered safe unless it
817 if (HasPromptedForPath() || should_prompt_
||
818 !download_
->GetForcedFilePath().empty())
821 const bool is_extension_download
=
822 download_crx_util::IsExtensionDownload(*download_
);
824 // User-initiated extension downloads from pref-whitelisted sources are not
825 // considered dangerous.
826 if (download_
->HasUserGesture() &&
827 is_extension_download
&&
828 download_crx_util::OffStoreInstallAllowedByPrefs(
829 GetProfile(), *download_
)) {
833 #if defined(ENABLE_EXTENSIONS)
834 // Extensions that are not from the gallery are considered dangerous.
835 // When off-store install is disabled we skip this, since in this case, we
836 // will not offer to install the extension.
837 if (extensions::FeatureSwitch::easy_off_store_install()->IsEnabled() &&
838 is_extension_download
&&
839 !extensions::WebstoreInstaller::GetAssociatedApproval(*download_
)) {
844 // Anything the user has marked auto-open is OK if it's user-initiated.
845 if (download_prefs_
->IsAutoOpenEnabledBasedOnExtension(virtual_path_
) &&
846 download_
->HasUserGesture())
849 switch (download_util::GetFileDangerLevel(virtual_path_
.BaseName())) {
850 case download_util::NOT_DANGEROUS
:
853 case download_util::ALLOW_ON_USER_GESTURE
:
854 // "Allow on user gesture" is OK when we have a user gesture and the
855 // hosting page has been visited before today.
856 if (download_
->GetTransitionType() &
857 ui::PAGE_TRANSITION_FROM_ADDRESS_BAR
) {
860 return !download_
->HasUserGesture() || visits
== NO_VISITS_TO_REFERRER
;
862 case download_util::DANGEROUS
:
869 void DownloadTargetDeterminer::OnDownloadDestroyed(
870 DownloadItem
* download
) {
871 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
872 DCHECK_EQ(download_
, download
);
873 CancelOnFailureAndDeleteSelf();
877 void DownloadTargetDeterminer::Start(content::DownloadItem
* download
,
878 const base::FilePath
& initial_virtual_path
,
879 DownloadPrefs
* download_prefs
,
880 DownloadTargetDeterminerDelegate
* delegate
,
881 const CompletionCallback
& callback
) {
882 // DownloadTargetDeterminer owns itself and will self destruct when the job is
883 // complete or the download item is destroyed. The callback is always invoked
885 new DownloadTargetDeterminer(download
, initial_virtual_path
, download_prefs
,
890 base::FilePath
DownloadTargetDeterminer::GetCrDownloadPath(
891 const base::FilePath
& suggested_path
) {
892 return base::FilePath(suggested_path
.value() + kCrdownloadSuffix
);
897 bool DownloadTargetDeterminer::IsAdobeReaderUpToDate() {
898 return g_is_adobe_reader_up_to_date_
;