Upstream version 9.37.195.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / download / download_target_determiner.cc
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.
4
5 #include "chrome/browser/download/download_target_determiner.h"
6
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/extensions/webstore_installer.h"
16 #include "chrome/browser/history/history_service.h"
17 #include "chrome/browser/history/history_service_factory.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/common/pref_names.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 "extensions/common/feature_switch.h"
25 #include "grit/generated_resources.h"
26 #include "net/base/filename_util.h"
27 #include "net/base/mime_util.h"
28 #include "ui/base/l10n/l10n_util.h"
29
30 #if defined(ENABLE_PLUGINS)
31 #include "chrome/browser/plugins/plugin_prefs.h"
32 #include "content/public/browser/plugin_service.h"
33 #include "content/public/common/webplugininfo.h"
34 #endif
35
36 #if defined(OS_WIN)
37 #include "chrome/browser/ui/pdf/adobe_reader_info_win.h"
38 #endif
39
40 using content::BrowserThread;
41 using content::DownloadItem;
42
43 namespace {
44
45 const base::FilePath::CharType kCrdownloadSuffix[] =
46     FILE_PATH_LITERAL(".crdownload");
47
48 // Condenses the results from HistoryService::GetVisibleVisitCountToHost() to a
49 // single bool. A host is considered visited before if prior visible visits were
50 // found in history and the first such visit was earlier than the most recent
51 // midnight.
52 void VisitCountsToVisitedBefore(
53     const base::Callback<void(bool)>& callback,
54     HistoryService::Handle unused_handle,
55     bool found_visits,
56     int count,
57     base::Time first_visit) {
58   callback.Run(
59       found_visits && count > 0 &&
60       (first_visit.LocalMidnight() < base::Time::Now().LocalMidnight()));
61 }
62
63 #if defined(OS_WIN)
64 // Keeps track of whether Adobe Reader is up to date.
65 bool g_is_adobe_reader_up_to_date_ = false;
66 #endif
67
68 }  // namespace
69
70 DownloadTargetInfo::DownloadTargetInfo()
71     : is_filetype_handled_safely(false) {}
72
73 DownloadTargetInfo::~DownloadTargetInfo() {}
74
75 DownloadTargetDeterminerDelegate::~DownloadTargetDeterminerDelegate() {
76 }
77
78 DownloadTargetDeterminer::DownloadTargetDeterminer(
79     DownloadItem* download,
80     const base::FilePath& initial_virtual_path,
81     DownloadPrefs* download_prefs,
82     DownloadTargetDeterminerDelegate* delegate,
83     const CompletionCallback& callback)
84     : next_state_(STATE_GENERATE_TARGET_PATH),
85       should_prompt_(false),
86       should_notify_extensions_(false),
87       create_target_directory_(false),
88       conflict_action_(DownloadPathReservationTracker::OVERWRITE),
89       danger_type_(download->GetDangerType()),
90       virtual_path_(initial_virtual_path),
91       is_filetype_handled_safely_(false),
92       download_(download),
93       is_resumption_(download_->GetLastReason() !=
94                          content::DOWNLOAD_INTERRUPT_REASON_NONE &&
95                      !initial_virtual_path.empty()),
96       download_prefs_(download_prefs),
97       delegate_(delegate),
98       completion_callback_(callback),
99       weak_ptr_factory_(this) {
100   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
101   DCHECK(download_);
102   DCHECK(delegate);
103   download_->AddObserver(this);
104
105   DoLoop();
106 }
107
108 DownloadTargetDeterminer::~DownloadTargetDeterminer() {
109   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
110   DCHECK(download_);
111   DCHECK(completion_callback_.is_null());
112   download_->RemoveObserver(this);
113 }
114
115 void DownloadTargetDeterminer::DoLoop() {
116   Result result = CONTINUE;
117   do {
118     State current_state = next_state_;
119     next_state_ = STATE_NONE;
120
121     switch (current_state) {
122       case STATE_GENERATE_TARGET_PATH:
123         result = DoGenerateTargetPath();
124         break;
125       case STATE_NOTIFY_EXTENSIONS:
126         result = DoNotifyExtensions();
127         break;
128       case STATE_RESERVE_VIRTUAL_PATH:
129         result = DoReserveVirtualPath();
130         break;
131       case STATE_PROMPT_USER_FOR_DOWNLOAD_PATH:
132         result = DoPromptUserForDownloadPath();
133         break;
134       case STATE_DETERMINE_LOCAL_PATH:
135         result = DoDetermineLocalPath();
136         break;
137       case STATE_DETERMINE_MIME_TYPE:
138         result = DoDetermineMimeType();
139         break;
140       case STATE_DETERMINE_IF_HANDLED_SAFELY_BY_BROWSER:
141         result = DoDetermineIfHandledSafely();
142         break;
143       case STATE_DETERMINE_IF_ADOBE_READER_UP_TO_DATE:
144         result = DoDetermineIfAdobeReaderUpToDate();
145         break;
146       case STATE_CHECK_DOWNLOAD_URL:
147         result = DoCheckDownloadUrl();
148         break;
149       case STATE_DETERMINE_INTERMEDIATE_PATH:
150         result = DoDetermineIntermediatePath();
151         break;
152       case STATE_CHECK_VISITED_REFERRER_BEFORE:
153         result = DoCheckVisitedReferrerBefore();
154         break;
155       case STATE_NONE:
156         NOTREACHED();
157         return;
158     }
159   } while (result == CONTINUE);
160   // Note that if a callback completes synchronously, the handler will still
161   // return QUIT_DOLOOP. In this case, an inner DoLoop() may complete the target
162   // determination and delete |this|.
163
164   if (result == COMPLETE)
165     ScheduleCallbackAndDeleteSelf();
166 }
167
168 DownloadTargetDeterminer::Result
169     DownloadTargetDeterminer::DoGenerateTargetPath() {
170   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
171   DCHECK(local_path_.empty());
172   DCHECK(!should_prompt_);
173   DCHECK(!should_notify_extensions_);
174   DCHECK_EQ(DownloadPathReservationTracker::OVERWRITE, conflict_action_);
175   bool is_forced_path = !download_->GetForcedFilePath().empty();
176
177   next_state_ = STATE_NOTIFY_EXTENSIONS;
178
179   if (!virtual_path_.empty() && HasPromptedForPath() && !is_forced_path) {
180     // The download is being resumed and the user has already been prompted for
181     // a path. Assume that it's okay to overwrite the file if there's a conflict
182     // and reuse the selection.
183     should_prompt_ = ShouldPromptForDownload(virtual_path_);
184   } else if (!is_forced_path) {
185     // If we don't have a forced path, we should construct a path for the
186     // download. Forced paths are only specified for programmatic downloads
187     // (WebStore, Drag&Drop). Treat the path as a virtual path. We will
188     // eventually determine whether this is a local path and if not, figure out
189     // a local path.
190     std::string default_filename(
191         l10n_util::GetStringUTF8(IDS_DEFAULT_DOWNLOAD_FILENAME));
192     base::FilePath generated_filename = net::GenerateFileName(
193         download_->GetURL(),
194         download_->GetContentDisposition(),
195         GetProfile()->GetPrefs()->GetString(prefs::kDefaultCharset),
196         download_->GetSuggestedFilename(),
197         download_->GetMimeType(),
198         default_filename);
199     should_prompt_ = ShouldPromptForDownload(generated_filename);
200     base::FilePath target_directory;
201     if (should_prompt_) {
202       DCHECK(!download_prefs_->IsDownloadPathManaged());
203       // If the user is going to be prompted and the user has been prompted
204       // before, then always prefer the last directory that the user selected.
205       target_directory = download_prefs_->SaveFilePath();
206     } else {
207       target_directory = download_prefs_->DownloadPath();
208     }
209     virtual_path_ = target_directory.Append(generated_filename);
210     conflict_action_ = DownloadPathReservationTracker::UNIQUIFY;
211     should_notify_extensions_ = true;
212   } else {
213     virtual_path_ = download_->GetForcedFilePath();
214     // If this is a resumed download which was previously interrupted due to an
215     // issue with the forced path, the user is still not prompted. If the path
216     // supplied to a programmatic download is invalid, then the caller needs to
217     // intervene.
218   }
219   DCHECK(virtual_path_.IsAbsolute());
220   DVLOG(20) << "Generated virtual path: " << virtual_path_.AsUTF8Unsafe();
221
222   // If the download is DOA, don't bother going any further. This would be the
223   // case for a download that failed to initialize (e.g. the initial temporary
224   // file couldn't be created because both the downloads directory and the
225   // temporary directory are unwriteable).
226   //
227   // A virtual path is determined for DOA downloads for display purposes. This
228   // is why this check is performed here instead of at the start.
229   if (download_->GetState() != DownloadItem::IN_PROGRESS)
230     return COMPLETE;
231   return CONTINUE;
232 }
233
234 DownloadTargetDeterminer::Result
235     DownloadTargetDeterminer::DoNotifyExtensions() {
236   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
237   DCHECK(!virtual_path_.empty());
238
239   next_state_ = STATE_RESERVE_VIRTUAL_PATH;
240
241   if (!should_notify_extensions_)
242     return CONTINUE;
243
244   delegate_->NotifyExtensions(download_, virtual_path_,
245       base::Bind(&DownloadTargetDeterminer::NotifyExtensionsDone,
246                  weak_ptr_factory_.GetWeakPtr()));
247   return QUIT_DOLOOP;
248 }
249
250 void DownloadTargetDeterminer::NotifyExtensionsDone(
251     const base::FilePath& suggested_path,
252     DownloadPathReservationTracker::FilenameConflictAction conflict_action) {
253   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
254   DVLOG(20) << "Extension suggested path: " << suggested_path.AsUTF8Unsafe();
255
256   // Extensions should not call back here more than once.
257   DCHECK_EQ(STATE_RESERVE_VIRTUAL_PATH, next_state_);
258
259   if (!suggested_path.empty()) {
260     // If an extension overrides the filename, then the target directory will be
261     // forced to download_prefs_->DownloadPath() since extensions cannot place
262     // downloaded files anywhere except there. This prevents subdirectories from
263     // accumulating: if an extension is allowed to say that a file should go in
264     // last_download_path/music/foo.mp3, then last_download_path will accumulate
265     // the subdirectory /music/ so that the next download may end up in
266     // Downloads/music/music/music/bar.mp3.
267     base::FilePath new_path(download_prefs_->DownloadPath().Append(
268         suggested_path).NormalizePathSeparators());
269     // Do not pass a mime type to GenerateSafeFileName so that it does not force
270     // the filename to have an extension if the (Chrome) extension does not
271     // suggest it.
272     net::GenerateSafeFileName(std::string(), false, &new_path);
273     virtual_path_ = new_path;
274     create_target_directory_ = true;
275   }
276   // An extension may set conflictAction without setting filename.
277   if (conflict_action != DownloadPathReservationTracker::UNIQUIFY)
278     conflict_action_ = conflict_action;
279
280   DoLoop();
281 }
282
283 DownloadTargetDeterminer::Result
284     DownloadTargetDeterminer::DoReserveVirtualPath() {
285   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
286   DCHECK(!virtual_path_.empty());
287
288   next_state_ = STATE_PROMPT_USER_FOR_DOWNLOAD_PATH;
289
290   delegate_->ReserveVirtualPath(
291       download_, virtual_path_, create_target_directory_, conflict_action_,
292       base::Bind(&DownloadTargetDeterminer::ReserveVirtualPathDone,
293                  weak_ptr_factory_.GetWeakPtr()));
294   return QUIT_DOLOOP;
295 }
296
297 void DownloadTargetDeterminer::ReserveVirtualPathDone(
298     const base::FilePath& path, bool verified) {
299   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
300   DVLOG(20) << "Reserved path: " << path.AsUTF8Unsafe()
301             << " Verified:" << verified;
302   DCHECK_EQ(STATE_PROMPT_USER_FOR_DOWNLOAD_PATH, next_state_);
303
304   should_prompt_ = (should_prompt_ || !verified);
305   virtual_path_ = path;
306   DoLoop();
307 }
308
309 DownloadTargetDeterminer::Result
310     DownloadTargetDeterminer::DoPromptUserForDownloadPath() {
311   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
312   DCHECK(!virtual_path_.empty());
313
314   next_state_ = STATE_DETERMINE_LOCAL_PATH;
315
316   if (should_prompt_) {
317     delegate_->PromptUserForDownloadPath(
318         download_,
319         virtual_path_,
320         base::Bind(&DownloadTargetDeterminer::PromptUserForDownloadPathDone,
321                    weak_ptr_factory_.GetWeakPtr()));
322     return QUIT_DOLOOP;
323   }
324   return CONTINUE;
325 }
326
327 void DownloadTargetDeterminer::PromptUserForDownloadPathDone(
328     const base::FilePath& virtual_path) {
329   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
330   DVLOG(20) << "User selected path:" << virtual_path.AsUTF8Unsafe();
331   if (virtual_path.empty()) {
332     CancelOnFailureAndDeleteSelf();
333     return;
334   }
335   DCHECK_EQ(STATE_DETERMINE_LOCAL_PATH, next_state_);
336
337   virtual_path_ = virtual_path;
338   download_prefs_->SetSaveFilePath(virtual_path_.DirName());
339   DoLoop();
340 }
341
342 DownloadTargetDeterminer::Result
343     DownloadTargetDeterminer::DoDetermineLocalPath() {
344   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
345   DCHECK(!virtual_path_.empty());
346   DCHECK(local_path_.empty());
347
348   next_state_ = STATE_DETERMINE_MIME_TYPE;
349
350   delegate_->DetermineLocalPath(
351       download_,
352       virtual_path_,
353       base::Bind(&DownloadTargetDeterminer::DetermineLocalPathDone,
354                  weak_ptr_factory_.GetWeakPtr()));
355   return QUIT_DOLOOP;
356 }
357
358 void DownloadTargetDeterminer::DetermineLocalPathDone(
359     const base::FilePath& local_path) {
360   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
361   DVLOG(20) << "Local path: " << local_path.AsUTF8Unsafe();
362   if (local_path.empty()) {
363     // Path subsitution failed.
364     CancelOnFailureAndDeleteSelf();
365     return;
366   }
367   DCHECK_EQ(STATE_DETERMINE_MIME_TYPE, next_state_);
368
369   local_path_ = local_path;
370   DoLoop();
371 }
372
373 DownloadTargetDeterminer::Result
374     DownloadTargetDeterminer::DoDetermineMimeType() {
375   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
376   DCHECK(!virtual_path_.empty());
377   DCHECK(!local_path_.empty());
378   DCHECK(mime_type_.empty());
379
380   next_state_ = STATE_DETERMINE_IF_HANDLED_SAFELY_BY_BROWSER;
381
382   if (virtual_path_ == local_path_) {
383     delegate_->GetFileMimeType(
384         local_path_,
385         base::Bind(&DownloadTargetDeterminer::DetermineMimeTypeDone,
386                    weak_ptr_factory_.GetWeakPtr()));
387     return QUIT_DOLOOP;
388   }
389   return CONTINUE;
390 }
391
392 void DownloadTargetDeterminer::DetermineMimeTypeDone(
393     const std::string& mime_type) {
394   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
395   DVLOG(20) << "MIME type: " << mime_type;
396   DCHECK_EQ(STATE_DETERMINE_IF_HANDLED_SAFELY_BY_BROWSER, next_state_);
397
398   mime_type_ = mime_type;
399   DoLoop();
400 }
401
402 #if defined(ENABLE_PLUGINS)
403 // The code below is used by DoDetermineIfHandledSafely to determine if the
404 // file type is handled by a sandboxed plugin.
405 namespace {
406
407 void InvokeClosureAfterGetPluginCallback(
408     const base::Closure& closure,
409     const std::vector<content::WebPluginInfo>& unused) {
410   closure.Run();
411 }
412
413 enum ActionOnStalePluginList {
414   RETRY_IF_STALE_PLUGIN_LIST,
415   IGNORE_IF_STALE_PLUGIN_LIST
416 };
417
418 void IsHandledBySafePlugin(content::ResourceContext* resource_context,
419                            const GURL& url,
420                            const std::string& mime_type,
421                            ActionOnStalePluginList stale_plugin_action,
422                            const base::Callback<void(bool)>& callback) {
423   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
424   DCHECK(!mime_type.empty());
425   using content::WebPluginInfo;
426
427   std::string actual_mime_type;
428   bool is_stale = false;
429   WebPluginInfo plugin_info;
430
431   content::PluginService* plugin_service =
432       content::PluginService::GetInstance();
433   bool plugin_found = plugin_service->GetPluginInfo(-1, -1, resource_context,
434                                                     url, GURL(), mime_type,
435                                                     false, &is_stale,
436                                                     &plugin_info,
437                                                     &actual_mime_type);
438   if (is_stale && stale_plugin_action == RETRY_IF_STALE_PLUGIN_LIST) {
439     // The GetPlugins call causes the plugin list to be refreshed. Once that's
440     // done we can retry the GetPluginInfo call. We break out of this cycle
441     // after a single retry in order to avoid retrying indefinitely.
442     plugin_service->GetPlugins(
443         base::Bind(&InvokeClosureAfterGetPluginCallback,
444                    base::Bind(&IsHandledBySafePlugin,
445                               resource_context,
446                               url,
447                               mime_type,
448                               IGNORE_IF_STALE_PLUGIN_LIST,
449                               callback)));
450     return;
451   }
452   // In practice, we assume that retrying once is enough.
453   DCHECK(!is_stale);
454   bool is_handled_safely =
455       plugin_found &&
456       (plugin_info.type == WebPluginInfo::PLUGIN_TYPE_PEPPER_IN_PROCESS ||
457        plugin_info.type == WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS);
458   BrowserThread::PostTask(
459       BrowserThread::UI, FROM_HERE, base::Bind(callback, is_handled_safely));
460 }
461
462 }  // namespace
463 #endif  // defined(ENABLE_PLUGINS)
464
465 DownloadTargetDeterminer::Result
466     DownloadTargetDeterminer::DoDetermineIfHandledSafely() {
467   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
468   DCHECK(!virtual_path_.empty());
469   DCHECK(!local_path_.empty());
470   DCHECK(!is_filetype_handled_safely_);
471
472   next_state_ = STATE_DETERMINE_IF_ADOBE_READER_UP_TO_DATE;
473
474   if (mime_type_.empty())
475     return CONTINUE;
476
477   if (net::IsSupportedMimeType(mime_type_)) {
478     is_filetype_handled_safely_ = true;
479     return CONTINUE;
480   }
481
482 #if defined(ENABLE_PLUGINS)
483   BrowserThread::PostTask(
484       BrowserThread::IO,
485       FROM_HERE,
486       base::Bind(
487           &IsHandledBySafePlugin,
488           GetProfile()->GetResourceContext(),
489           net::FilePathToFileURL(local_path_),
490           mime_type_,
491           RETRY_IF_STALE_PLUGIN_LIST,
492           base::Bind(&DownloadTargetDeterminer::DetermineIfHandledSafelyDone,
493                      weak_ptr_factory_.GetWeakPtr())));
494   return QUIT_DOLOOP;
495 #else
496   return CONTINUE;
497 #endif
498 }
499
500 #if defined(ENABLE_PLUGINS)
501 void DownloadTargetDeterminer::DetermineIfHandledSafelyDone(
502     bool is_handled_safely) {
503   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
504   DVLOG(20) << "Is file type handled safely: " << is_filetype_handled_safely_;
505   DCHECK_EQ(STATE_DETERMINE_IF_ADOBE_READER_UP_TO_DATE, next_state_);
506   is_filetype_handled_safely_ = is_handled_safely;
507   DoLoop();
508 }
509 #endif
510
511 DownloadTargetDeterminer::Result
512     DownloadTargetDeterminer::DoDetermineIfAdobeReaderUpToDate() {
513   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
514
515   next_state_ = STATE_CHECK_DOWNLOAD_URL;
516
517 #if defined(OS_WIN)
518   if (!local_path_.MatchesExtension(FILE_PATH_LITERAL(".pdf")))
519     return CONTINUE;
520   if (!IsAdobeReaderDefaultPDFViewer())
521     return CONTINUE;
522
523   base::PostTaskAndReplyWithResult(
524       BrowserThread::GetBlockingPool(),
525       FROM_HERE,
526       base::Bind(&::IsAdobeReaderUpToDate),
527       base::Bind(&DownloadTargetDeterminer::DetermineIfAdobeReaderUpToDateDone,
528                  weak_ptr_factory_.GetWeakPtr()));
529   return QUIT_DOLOOP;
530 #else
531   return CONTINUE;
532 #endif
533 }
534
535 #if defined(OS_WIN)
536 void DownloadTargetDeterminer::DetermineIfAdobeReaderUpToDateDone(
537     bool adobe_reader_up_to_date) {
538   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
539   DVLOG(20) << "Is Adobe Reader Up To Date: " << adobe_reader_up_to_date;
540   DCHECK_EQ(STATE_CHECK_DOWNLOAD_URL, next_state_);
541   g_is_adobe_reader_up_to_date_ = adobe_reader_up_to_date;
542   DoLoop();
543 }
544 #endif
545
546 DownloadTargetDeterminer::Result
547     DownloadTargetDeterminer::DoCheckDownloadUrl() {
548   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
549   DCHECK(!virtual_path_.empty());
550   next_state_ = STATE_CHECK_VISITED_REFERRER_BEFORE;
551   delegate_->CheckDownloadUrl(
552       download_,
553       virtual_path_,
554       base::Bind(&DownloadTargetDeterminer::CheckDownloadUrlDone,
555                  weak_ptr_factory_.GetWeakPtr()));
556   return QUIT_DOLOOP;
557 }
558
559 void DownloadTargetDeterminer::CheckDownloadUrlDone(
560     content::DownloadDangerType danger_type) {
561   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
562   DVLOG(20) << "URL Check Result:" << danger_type;
563   DCHECK_EQ(STATE_CHECK_VISITED_REFERRER_BEFORE, next_state_);
564   danger_type_ = danger_type;
565   DoLoop();
566 }
567
568 DownloadTargetDeterminer::Result
569     DownloadTargetDeterminer::DoCheckVisitedReferrerBefore() {
570   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
571
572   next_state_ = STATE_DETERMINE_INTERMEDIATE_PATH;
573
574   // Checking if there are prior visits to the referrer is only necessary if the
575   // danger level of the download depends on the file type. This excludes cases
576   // where the download has already been deemed dangerous, or where the user is
577   // going to be prompted or where this is a programmatic download.
578   if (danger_type_ != content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)
579     return CONTINUE;
580
581   // Assume that:
582   // IsDangerousFile(VISITED_REFERRER) => IsDangerousFile(NO_VISITS_...)
583   // I.e. having visited a referrer only lowers a file's danger level.
584   if (IsDangerousFile(NO_VISITS_TO_REFERRER)) {
585     // Only need to ping the history DB if the download would be considered safe
586     // if there are prior visits and is considered dangerous otherwise.
587     if (!IsDangerousFile(VISITED_REFERRER)) {
588       // HistoryServiceFactory redirects incognito profiles to on-record
589       // profiles.  There's no history for on-record profiles in unit_tests.
590       HistoryService* history_service = HistoryServiceFactory::GetForProfile(
591           GetProfile(), Profile::EXPLICIT_ACCESS);
592
593       if (history_service && download_->GetReferrerUrl().is_valid()) {
594         history_service->GetVisibleVisitCountToHost(
595             download_->GetReferrerUrl(), &history_consumer_,
596             base::Bind(&VisitCountsToVisitedBefore, base::Bind(
597                 &DownloadTargetDeterminer::CheckVisitedReferrerBeforeDone,
598                 weak_ptr_factory_.GetWeakPtr())));
599         return QUIT_DOLOOP;
600       }
601     }
602
603     // If the danger level doesn't depend on having visited the refererrer URL
604     // or if original profile doesn't have a HistoryService or the referrer url
605     // is invalid, then assume the referrer has not been visited before.
606     danger_type_ = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE;
607   }
608   return CONTINUE;
609 }
610
611 void DownloadTargetDeterminer::CheckVisitedReferrerBeforeDone(
612     bool visited_referrer_before) {
613   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
614   DCHECK_EQ(STATE_DETERMINE_INTERMEDIATE_PATH, next_state_);
615   if (IsDangerousFile(
616           visited_referrer_before ? VISITED_REFERRER : NO_VISITS_TO_REFERRER))
617     danger_type_ = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE;
618   DoLoop();
619 }
620
621 DownloadTargetDeterminer::Result
622     DownloadTargetDeterminer::DoDetermineIntermediatePath() {
623   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
624   DCHECK(!virtual_path_.empty());
625   DCHECK(!local_path_.empty());
626   DCHECK(intermediate_path_.empty());
627   DCHECK(!virtual_path_.MatchesExtension(kCrdownloadSuffix));
628   DCHECK(!local_path_.MatchesExtension(kCrdownloadSuffix));
629
630   next_state_ = STATE_NONE;
631
632   // Note that the intermediate filename is always uniquified (i.e. if a file by
633   // the same name exists, it is never overwritten). Therefore the code below
634   // does not attempt to find a name that doesn't conflict with an existing
635   // file.
636
637   // If the actual target of the download is a virtual path, then the local path
638   // is considered to point to a temporary path. A separate intermediate path is
639   // unnecessary since the local path already serves that purpose.
640   if (virtual_path_.BaseName() != local_path_.BaseName()) {
641     intermediate_path_ = local_path_;
642     return COMPLETE;
643   }
644
645   // If the download has a forced path and is safe, then just use the
646   // target path. In practice the temporary download file that was created prior
647   // to download filename determination is already named
648   // download_->GetForcedFilePath().
649   if (danger_type_ == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS &&
650       !download_->GetForcedFilePath().empty()) {
651     DCHECK_EQ(download_->GetForcedFilePath().value(), local_path_.value());
652     intermediate_path_ = local_path_;
653     return COMPLETE;
654   }
655
656   // Other safe downloads get a .crdownload suffix for their intermediate name.
657   if (danger_type_ == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) {
658     intermediate_path_ = GetCrDownloadPath(local_path_);
659     return COMPLETE;
660   }
661
662   // If this is a resumed download, then re-use the existing intermediate path
663   // if one is available. A resumed download shouldn't cause a non-dangerous
664   // download to be considered dangerous upon resumption. Therefore the
665   // intermediate file should already be in the correct form.
666   if (is_resumption_ && !download_->GetFullPath().empty() &&
667       local_path_.DirName() == download_->GetFullPath().DirName()) {
668     DCHECK_NE(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
669               download_->GetDangerType());
670     DCHECK_EQ(kCrdownloadSuffix, download_->GetFullPath().Extension());
671     intermediate_path_ = download_->GetFullPath();
672     return COMPLETE;
673   }
674
675   // Dangerous downloads receive a random intermediate name that looks like:
676   // 'Unconfirmed <random>.crdownload'.
677   const base::FilePath::CharType kUnconfirmedFormatSuffix[] =
678       FILE_PATH_LITERAL(" %d.crdownload");
679   // Range of the <random> uniquifier.
680   const int kUnconfirmedUniquifierRange = 1000000;
681 #if defined(OS_WIN)
682   base::string16 unconfirmed_format =
683       l10n_util::GetStringUTF16(IDS_DOWNLOAD_UNCONFIRMED_PREFIX);
684 #else
685   std::string unconfirmed_format =
686       l10n_util::GetStringUTF8(IDS_DOWNLOAD_UNCONFIRMED_PREFIX);
687 #endif
688   unconfirmed_format.append(kUnconfirmedFormatSuffix);
689
690   base::FilePath::StringType file_name = base::StringPrintf(
691       unconfirmed_format.c_str(),
692       base::RandInt(0, kUnconfirmedUniquifierRange));
693   intermediate_path_ = local_path_.DirName().Append(file_name);
694   return COMPLETE;
695 }
696
697 void DownloadTargetDeterminer::ScheduleCallbackAndDeleteSelf() {
698   DCHECK(download_);
699   DVLOG(20) << "Scheduling callback. Virtual:" << virtual_path_.AsUTF8Unsafe()
700             << " Local:" << local_path_.AsUTF8Unsafe()
701             << " Intermediate:" << intermediate_path_.AsUTF8Unsafe()
702             << " Should prompt:" << should_prompt_
703             << " Danger type:" << danger_type_;
704   scoped_ptr<DownloadTargetInfo> target_info(new DownloadTargetInfo);
705
706   target_info->target_path = local_path_;
707   target_info->target_disposition =
708       (HasPromptedForPath() || should_prompt_
709            ? DownloadItem::TARGET_DISPOSITION_PROMPT
710            : DownloadItem::TARGET_DISPOSITION_OVERWRITE);
711   target_info->danger_type = danger_type_;
712   target_info->intermediate_path = intermediate_path_;
713   target_info->mime_type = mime_type_;
714   target_info->is_filetype_handled_safely = is_filetype_handled_safely_;
715
716   base::MessageLoop::current()->PostTask(
717       FROM_HERE, base::Bind(completion_callback_, base::Passed(&target_info)));
718   completion_callback_.Reset();
719   delete this;
720 }
721
722 void DownloadTargetDeterminer::CancelOnFailureAndDeleteSelf() {
723   // Path substitution failed.
724   virtual_path_.clear();
725   local_path_.clear();
726   intermediate_path_.clear();
727   ScheduleCallbackAndDeleteSelf();
728 }
729
730 Profile* DownloadTargetDeterminer::GetProfile() {
731   DCHECK(download_->GetBrowserContext());
732   return Profile::FromBrowserContext(download_->GetBrowserContext());
733 }
734
735 bool DownloadTargetDeterminer::ShouldPromptForDownload(
736     const base::FilePath& filename) const {
737   if (is_resumption_) {
738     // For resumed downloads, if the target disposition or prefs require
739     // prompting, the user has already been prompted. Try to respect the user's
740     // selection, unless we've discovered that the target path cannot be used
741     // for some reason.
742     content::DownloadInterruptReason reason = download_->GetLastReason();
743     return (reason == content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED ||
744             reason == content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE ||
745             reason == content::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE);
746   }
747
748   // If the download path is forced, don't prompt.
749   if (!download_->GetForcedFilePath().empty()) {
750     // 'Save As' downloads shouldn't have a forced path.
751     DCHECK(DownloadItem::TARGET_DISPOSITION_PROMPT !=
752            download_->GetTargetDisposition());
753     return false;
754   }
755
756   // Don't ask where to save if the download path is managed. Even if the user
757   // wanted to be prompted for "all" downloads, or if this was a 'Save As'
758   // download.
759   if (download_prefs_->IsDownloadPathManaged())
760     return false;
761
762   // Prompt if this is a 'Save As' download.
763   if (download_->GetTargetDisposition() ==
764       DownloadItem::TARGET_DISPOSITION_PROMPT)
765     return true;
766
767   // Check if the user has the "Always prompt for download location" preference
768   // set. If so we prompt for most downloads except for the following scenarios:
769   // 1) Extension installation. Note that we only care here about the case where
770   //    an extension is installed, not when one is downloaded with "save as...".
771   // 2) Filetypes marked "always open." If the user just wants this file opened,
772   //    don't bother asking where to keep it.
773   if (download_prefs_->PromptForDownload() &&
774       !download_crx_util::IsExtensionDownload(*download_) &&
775       !filename.MatchesExtension(extensions::kExtensionFileExtension) &&
776       !download_prefs_->IsAutoOpenEnabledBasedOnExtension(filename))
777     return true;
778
779   // Otherwise, don't prompt. Note that the user might still be prompted if
780   // there are unresolved conflicts during path reservation (e.g. due to the
781   // target path being unwriteable or because there are too many conflicting
782   // files), or if an extension signals that the user be prompted on a filename
783   // conflict.
784   return false;
785 }
786
787 bool DownloadTargetDeterminer::HasPromptedForPath() const {
788   return (is_resumption_ && download_->GetTargetDisposition() ==
789                                 DownloadItem::TARGET_DISPOSITION_PROMPT);
790 }
791
792 bool DownloadTargetDeterminer::IsDangerousFile(PriorVisitsToReferrer visits) {
793   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
794
795   // If the user has has been prompted or will be, assume that the user has
796   // approved the download. A programmatic download is considered safe unless it
797   // contains malware.
798   if (HasPromptedForPath() || should_prompt_ ||
799       !download_->GetForcedFilePath().empty())
800     return false;
801
802   const bool is_extension_download =
803       download_crx_util::IsExtensionDownload(*download_);
804
805   // User-initiated extension downloads from pref-whitelisted sources are not
806   // considered dangerous.
807   if (download_->HasUserGesture() &&
808       is_extension_download &&
809       download_crx_util::OffStoreInstallAllowedByPrefs(
810           GetProfile(), *download_)) {
811     return false;
812   }
813
814   // Extensions that are not from the gallery are considered dangerous.
815   // When off-store install is disabled we skip this, since in this case, we
816   // will not offer to install the extension.
817   if (extensions::FeatureSwitch::easy_off_store_install()->IsEnabled() &&
818       is_extension_download &&
819       !extensions::WebstoreInstaller::GetAssociatedApproval(*download_)) {
820     return true;
821   }
822
823   // Anything the user has marked auto-open is OK if it's user-initiated.
824   if (download_prefs_->IsAutoOpenEnabledBasedOnExtension(virtual_path_) &&
825       download_->HasUserGesture())
826     return false;
827
828   switch (download_util::GetFileDangerLevel(virtual_path_.BaseName())) {
829     case download_util::NOT_DANGEROUS:
830       return false;
831
832     case download_util::ALLOW_ON_USER_GESTURE:
833       // "Allow on user gesture" is OK when we have a user gesture and the
834       // hosting page has been visited before today.
835       if (download_->GetTransitionType() &
836           content::PAGE_TRANSITION_FROM_ADDRESS_BAR) {
837         return false;
838       }
839       return !download_->HasUserGesture() || visits == NO_VISITS_TO_REFERRER;
840
841     case download_util::DANGEROUS:
842       return true;
843   }
844   NOTREACHED();
845   return false;
846 }
847
848 void DownloadTargetDeterminer::OnDownloadDestroyed(
849     DownloadItem* download) {
850   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
851   DCHECK_EQ(download_, download);
852   CancelOnFailureAndDeleteSelf();
853 }
854
855 // static
856 void DownloadTargetDeterminer::Start(content::DownloadItem* download,
857                                      const base::FilePath& initial_virtual_path,
858                                      DownloadPrefs* download_prefs,
859                                      DownloadTargetDeterminerDelegate* delegate,
860                                      const CompletionCallback& callback) {
861   // DownloadTargetDeterminer owns itself and will self destruct when the job is
862   // complete or the download item is destroyed. The callback is always invoked
863   // asynchronously.
864   new DownloadTargetDeterminer(download, initial_virtual_path, download_prefs,
865                                delegate, callback);
866 }
867
868 // static
869 base::FilePath DownloadTargetDeterminer::GetCrDownloadPath(
870     const base::FilePath& suggested_path) {
871   return base::FilePath(suggested_path.value() + kCrdownloadSuffix);
872 }
873
874 #if defined(OS_WIN)
875 // static
876 bool DownloadTargetDeterminer::IsAdobeReaderUpToDate() {
877   return g_is_adobe_reader_up_to_date_;
878 }
879 #endif