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