Home | History | Annotate | Download | only in download
      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
    880