| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/download/download_target_determiner.h" | 5 #include "chrome/browser/download/download_target_determiner.h" |
| 6 | 6 |
| 7 #include "base/prefs/pref_service.h" | 7 #include "base/prefs/pref_service.h" |
| 8 #include "base/rand_util.h" | 8 #include "base/rand_util.h" |
| 9 #include "base/strings/stringprintf.h" | 9 #include "base/strings/stringprintf.h" |
| 10 #include "base/time/time.h" | 10 #include "base/time/time.h" |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 } else { | 200 } else { |
| 201 virtual_path_ = download_->GetForcedFilePath(); | 201 virtual_path_ = download_->GetForcedFilePath(); |
| 202 // If this is a resumed download which was previously interrupted due to an | 202 // If this is a resumed download which was previously interrupted due to an |
| 203 // issue with the forced path, the user is still not prompted. If the path | 203 // issue with the forced path, the user is still not prompted. If the path |
| 204 // supplied to a programmatic download is invalid, then the caller needs to | 204 // supplied to a programmatic download is invalid, then the caller needs to |
| 205 // intervene. | 205 // intervene. |
| 206 } | 206 } |
| 207 DCHECK(virtual_path_.IsAbsolute()); | 207 DCHECK(virtual_path_.IsAbsolute()); |
| 208 DVLOG(20) << "Generated virtual path: " << virtual_path_.AsUTF8Unsafe(); | 208 DVLOG(20) << "Generated virtual path: " << virtual_path_.AsUTF8Unsafe(); |
| 209 | 209 |
| 210 // If the download is DOA, don't bother going any further. This would be the | |
| 211 // case for a download that failed to initialize (e.g. the initial temporary | |
| 212 // file couldn't be created because both the downloads directory and the | |
| 213 // temporary directory are unwriteable). | |
| 214 // | |
| 215 // A virtual path is determined for DOA downloads for display purposes. This | |
| 216 // is why this check is performed here instead of at the start. | |
| 217 if (download_->GetState() != DownloadItem::IN_PROGRESS) | |
| 218 return COMPLETE; | |
| 219 return CONTINUE; | 210 return CONTINUE; |
| 220 } | 211 } |
| 221 | 212 |
| 222 DownloadTargetDeterminer::Result | 213 DownloadTargetDeterminer::Result |
| 223 DownloadTargetDeterminer::DoNotifyExtensions() { | 214 DownloadTargetDeterminer::DoNotifyExtensions() { |
| 224 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 225 DCHECK(!virtual_path_.empty()); | 216 DCHECK(!virtual_path_.empty()); |
| 226 | 217 |
| 227 next_state_ = STATE_RESERVE_VIRTUAL_PATH; | 218 next_state_ = STATE_RESERVE_VIRTUAL_PATH; |
| 228 | 219 |
| 229 if (!should_notify_extensions_) | 220 if (!should_notify_extensions_ || |
| 221 download_->GetState() != DownloadItem::IN_PROGRESS) |
| 230 return CONTINUE; | 222 return CONTINUE; |
| 231 | 223 |
| 232 delegate_->NotifyExtensions(download_, virtual_path_, | 224 delegate_->NotifyExtensions(download_, virtual_path_, |
| 233 base::Bind(&DownloadTargetDeterminer::NotifyExtensionsDone, | 225 base::Bind(&DownloadTargetDeterminer::NotifyExtensionsDone, |
| 234 weak_ptr_factory_.GetWeakPtr())); | 226 weak_ptr_factory_.GetWeakPtr())); |
| 235 return QUIT_DOLOOP; | 227 return QUIT_DOLOOP; |
| 236 } | 228 } |
| 237 | 229 |
| 238 void DownloadTargetDeterminer::NotifyExtensionsDone( | 230 void DownloadTargetDeterminer::NotifyExtensionsDone( |
| 239 const base::FilePath& suggested_path, | 231 const base::FilePath& suggested_path, |
| (...skipping 22 matching lines...) Expand all Loading... |
| 262 | 254 |
| 263 DoLoop(); | 255 DoLoop(); |
| 264 } | 256 } |
| 265 | 257 |
| 266 DownloadTargetDeterminer::Result | 258 DownloadTargetDeterminer::Result |
| 267 DownloadTargetDeterminer::DoReserveVirtualPath() { | 259 DownloadTargetDeterminer::DoReserveVirtualPath() { |
| 268 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 260 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 269 DCHECK(!virtual_path_.empty()); | 261 DCHECK(!virtual_path_.empty()); |
| 270 | 262 |
| 271 next_state_ = STATE_PROMPT_USER_FOR_DOWNLOAD_PATH; | 263 next_state_ = STATE_PROMPT_USER_FOR_DOWNLOAD_PATH; |
| 264 if (download_->GetState() != DownloadItem::IN_PROGRESS) |
| 265 return CONTINUE; |
| 272 | 266 |
| 273 delegate_->ReserveVirtualPath( | 267 delegate_->ReserveVirtualPath( |
| 274 download_, virtual_path_, create_target_directory_, conflict_action_, | 268 download_, virtual_path_, create_target_directory_, conflict_action_, |
| 275 base::Bind(&DownloadTargetDeterminer::ReserveVirtualPathDone, | 269 base::Bind(&DownloadTargetDeterminer::ReserveVirtualPathDone, |
| 276 weak_ptr_factory_.GetWeakPtr())); | 270 weak_ptr_factory_.GetWeakPtr())); |
| 277 return QUIT_DOLOOP; | 271 return QUIT_DOLOOP; |
| 278 } | 272 } |
| 279 | 273 |
| 280 void DownloadTargetDeterminer::ReserveVirtualPathDone( | 274 void DownloadTargetDeterminer::ReserveVirtualPathDone( |
| 281 const base::FilePath& path, bool verified) { | 275 const base::FilePath& path, bool verified) { |
| 282 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 276 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 283 DVLOG(20) << "Reserved path: " << path.AsUTF8Unsafe() | 277 DVLOG(20) << "Reserved path: " << path.AsUTF8Unsafe() |
| 284 << " Verified:" << verified; | 278 << " Verified:" << verified; |
| 285 should_prompt_ = (should_prompt_ || !verified); | 279 should_prompt_ = (should_prompt_ || !verified); |
| 286 virtual_path_ = path; | 280 virtual_path_ = path; |
| 287 DoLoop(); | 281 DoLoop(); |
| 288 } | 282 } |
| 289 | 283 |
| 290 DownloadTargetDeterminer::Result | 284 DownloadTargetDeterminer::Result |
| 291 DownloadTargetDeterminer::DoPromptUserForDownloadPath() { | 285 DownloadTargetDeterminer::DoPromptUserForDownloadPath() { |
| 292 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 286 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 293 DCHECK(!virtual_path_.empty()); | 287 DCHECK(!virtual_path_.empty()); |
| 294 | 288 |
| 295 next_state_ = STATE_DETERMINE_LOCAL_PATH; | 289 next_state_ = STATE_DETERMINE_LOCAL_PATH; |
| 296 | 290 |
| 297 if (should_prompt_) { | 291 // Avoid prompting for a download if it isn't in-progress. The user will be |
| 292 // prompted once the download is resumed and headers are available. |
| 293 if (should_prompt_ && download_->GetState() == DownloadItem::IN_PROGRESS) { |
| 298 delegate_->PromptUserForDownloadPath( | 294 delegate_->PromptUserForDownloadPath( |
| 299 download_, | 295 download_, |
| 300 virtual_path_, | 296 virtual_path_, |
| 301 base::Bind(&DownloadTargetDeterminer::PromptUserForDownloadPathDone, | 297 base::Bind(&DownloadTargetDeterminer::PromptUserForDownloadPathDone, |
| 302 weak_ptr_factory_.GetWeakPtr())); | 298 weak_ptr_factory_.GetWeakPtr())); |
| 303 return QUIT_DOLOOP; | 299 return QUIT_DOLOOP; |
| 304 } | 300 } |
| 305 return CONTINUE; | 301 return CONTINUE; |
| 306 } | 302 } |
| 307 | 303 |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 478 is_filetype_handled_safely_ = is_handled_safely; | 474 is_filetype_handled_safely_ = is_handled_safely; |
| 479 DVLOG(20) << "Is file type handled safely: " << is_filetype_handled_safely_; | 475 DVLOG(20) << "Is file type handled safely: " << is_filetype_handled_safely_; |
| 480 DoLoop(); | 476 DoLoop(); |
| 481 } | 477 } |
| 482 | 478 |
| 483 DownloadTargetDeterminer::Result | 479 DownloadTargetDeterminer::Result |
| 484 DownloadTargetDeterminer::DoCheckDownloadUrl() { | 480 DownloadTargetDeterminer::DoCheckDownloadUrl() { |
| 485 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 481 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 486 DCHECK(!virtual_path_.empty()); | 482 DCHECK(!virtual_path_.empty()); |
| 487 next_state_ = STATE_CHECK_VISITED_REFERRER_BEFORE; | 483 next_state_ = STATE_CHECK_VISITED_REFERRER_BEFORE; |
| 484 |
| 485 // Downloads that are already interrupted aren't checked for malicious URLs. |
| 486 // Such downloads were unsuccessful at initiation and there should be no data |
| 487 // saved at this point for the user to discard. If the download is |
| 488 // subsequently resumed, DownloadTargetDeterminer would be invoked again and |
| 489 // the URL check would be performed if the resumption was successful. |
| 490 if (download_->GetState() != DownloadItem::IN_PROGRESS) { |
| 491 DCHECK(download_->GetFullPath().empty()); |
| 492 return CONTINUE; |
| 493 } |
| 494 |
| 488 delegate_->CheckDownloadUrl( | 495 delegate_->CheckDownloadUrl( |
| 489 download_, | 496 download_, |
| 490 virtual_path_, | 497 virtual_path_, |
| 491 base::Bind(&DownloadTargetDeterminer::CheckDownloadUrlDone, | 498 base::Bind(&DownloadTargetDeterminer::CheckDownloadUrlDone, |
| 492 weak_ptr_factory_.GetWeakPtr())); | 499 weak_ptr_factory_.GetWeakPtr())); |
| 493 return QUIT_DOLOOP; | 500 return QUIT_DOLOOP; |
| 494 } | 501 } |
| 495 | 502 |
| 496 void DownloadTargetDeterminer::CheckDownloadUrlDone( | 503 void DownloadTargetDeterminer::CheckDownloadUrlDone( |
| 497 content::DownloadDangerType danger_type) { | 504 content::DownloadDangerType danger_type) { |
| 498 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 505 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 499 DVLOG(20) << "URL Check Result:" << danger_type; | 506 DVLOG(20) << "URL Check Result:" << danger_type; |
| 500 danger_type_ = danger_type; | 507 danger_type_ = danger_type; |
| 501 DoLoop(); | 508 DoLoop(); |
| 502 } | 509 } |
| 503 | 510 |
| 504 DownloadTargetDeterminer::Result | 511 DownloadTargetDeterminer::Result |
| 505 DownloadTargetDeterminer::DoCheckVisitedReferrerBefore() { | 512 DownloadTargetDeterminer::DoCheckVisitedReferrerBefore() { |
| 506 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 513 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 507 | 514 |
| 508 next_state_ = STATE_DETERMINE_INTERMEDIATE_PATH; | 515 next_state_ = STATE_DETERMINE_INTERMEDIATE_PATH; |
| 509 | 516 |
| 517 // If the download is already interrupted, there should be no download file |
| 518 // on-disk. So skip the danger type determination since there's no file for |
| 519 // the user to discard. Also the absence of a on-disk file prevents a filename |
| 520 // based attack (e.g. creating a foo.exe.local file). If the download is |
| 521 // successfully resumed, then DownloadTargetDeterminer would be invoked again |
| 522 // at which point the danger level would be determined again. |
| 523 if (download_->GetState() != DownloadItem::IN_PROGRESS) |
| 524 return CONTINUE; |
| 525 |
| 510 // Checking if there are prior visits to the referrer is only necessary if the | 526 // Checking if there are prior visits to the referrer is only necessary if the |
| 511 // danger level of the download depends on the file type. This excludes cases | 527 // danger level of the download depends on the file type. This excludes cases |
| 512 // where the download has already been deemed dangerous, or where the user is | 528 // where the download has already been deemed dangerous, or where the user is |
| 513 // going to be prompted or where this is a programmatic download. | 529 // going to be prompted or where this is a programmatic download. |
| 514 if (danger_type_ != content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) | 530 if (danger_type_ != content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) |
| 515 return CONTINUE; | 531 return CONTINUE; |
| 516 | 532 |
| 517 // Assume that: | 533 // Assume that: |
| 518 // IsDangerousFile(VISITED_REFERRER) => IsDangerousFile(NO_VISITS_...) | 534 // IsDangerousFile(VISITED_REFERRER) => IsDangerousFile(NO_VISITS_...) |
| 519 // I.e. having visited a referrer only lowers a file's danger level. | 535 // I.e. having visited a referrer only lowers a file's danger level. |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 798 // asynchronously. | 814 // asynchronously. |
| 799 new DownloadTargetDeterminer(download, initial_virtual_path, download_prefs, | 815 new DownloadTargetDeterminer(download, initial_virtual_path, download_prefs, |
| 800 delegate, callback); | 816 delegate, callback); |
| 801 } | 817 } |
| 802 | 818 |
| 803 // static | 819 // static |
| 804 base::FilePath DownloadTargetDeterminer::GetCrDownloadPath( | 820 base::FilePath DownloadTargetDeterminer::GetCrDownloadPath( |
| 805 const base::FilePath& suggested_path) { | 821 const base::FilePath& suggested_path) { |
| 806 return base::FilePath(suggested_path.value() + kCrdownloadSuffix); | 822 return base::FilePath(suggested_path.value() + kCrdownloadSuffix); |
| 807 } | 823 } |
| OLD | NEW |