Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(205)

Side by Side Diff: chrome/browser/download/chrome_download_manager_delegate.cc

Issue 12850002: Move download filename determintion into a separate class. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/chrome_download_manager_delegate.h" 5 #include "chrome/browser/download/chrome_download_manager_delegate.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
11 #include "base/callback.h" 11 #include "base/callback.h"
12 #include "base/file_util.h" 12 #include "base/file_util.h"
13 #include "base/prefs/pref_member.h" 13 #include "base/prefs/pref_member.h"
14 #include "base/prefs/pref_service.h" 14 #include "base/prefs/pref_service.h"
15 #include "base/rand_util.h" 15 #include "base/rand_util.h"
16 #include "base/stringprintf.h" 16 #include "base/stringprintf.h"
17 #include "base/time.h" 17 #include "base/time.h"
18 #include "base/utf_string_conversions.h" 18 #include "base/utf_string_conversions.h"
19 #include "chrome/browser/browser_process.h" 19 #include "chrome/browser/browser_process.h"
20 #include "chrome/browser/download/download_completion_blocker.h" 20 #include "chrome/browser/download/download_completion_blocker.h"
21 #include "chrome/browser/download/download_crx_util.h" 21 #include "chrome/browser/download/download_crx_util.h"
22 #include "chrome/browser/download/download_extensions.h"
23 #include "chrome/browser/download/download_file_picker.h" 22 #include "chrome/browser/download/download_file_picker.h"
24 #include "chrome/browser/download/download_history.h" 23 #include "chrome/browser/download/download_history.h"
25 #include "chrome/browser/download/download_path_reservation_tracker.h" 24 #include "chrome/browser/download/download_path_reservation_tracker.h"
26 #include "chrome/browser/download/download_prefs.h" 25 #include "chrome/browser/download/download_prefs.h"
27 #include "chrome/browser/download/download_service.h" 26 #include "chrome/browser/download/download_service.h"
28 #include "chrome/browser/download/download_service_factory.h" 27 #include "chrome/browser/download/download_service_factory.h"
29 #include "chrome/browser/download/download_status_updater.h" 28 #include "chrome/browser/download/download_target_determiner.h"
30 #include "chrome/browser/download/download_util.h" 29 #include "chrome/browser/download/download_util.h"
31 #include "chrome/browser/download/save_package_file_picker.h" 30 #include "chrome/browser/download/save_package_file_picker.h"
32 #include "chrome/browser/extensions/api/downloads/downloads_api.h"
33 #include "chrome/browser/extensions/crx_installer.h" 31 #include "chrome/browser/extensions/crx_installer.h"
34 #include "chrome/browser/extensions/extension_service.h"
35 #include "chrome/browser/extensions/extension_system.h"
36 #include "chrome/browser/history/history_service.h"
37 #include "chrome/browser/history/history_service_factory.h"
38 #include "chrome/browser/platform_util.h" 32 #include "chrome/browser/platform_util.h"
39 #include "chrome/browser/profiles/profile.h" 33 #include "chrome/browser/profiles/profile.h"
40 #include "chrome/browser/safe_browsing/safe_browsing_service.h" 34 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
41 #include "chrome/browser/ui/host_desktop.h"
42 #include "chrome/browser/ui/tabs/tab_strip_model.h"
43 #include "chrome/common/chrome_notification_types.h" 35 #include "chrome/common/chrome_notification_types.h"
44 #include "chrome/common/extensions/feature_switch.h" 36 #include "chrome/common/extensions/extension.h"
45 #include "chrome/common/extensions/user_script.h"
46 #include "chrome/common/pref_names.h" 37 #include "chrome/common/pref_names.h"
47 #include "components/user_prefs/pref_registry_syncable.h" 38 #include "components/user_prefs/pref_registry_syncable.h"
48 #include "content/public/browser/download_item.h" 39 #include "content/public/browser/download_item.h"
49 #include "content/public/browser/download_manager.h" 40 #include "content/public/browser/download_manager.h"
50 #include "content/public/browser/notification_source.h" 41 #include "content/public/browser/notification_source.h"
51 #include "content/public/browser/web_contents.h"
52 #include "content/public/browser/web_contents_delegate.h"
53 #include "grit/generated_resources.h"
54 #include "net/base/net_util.h"
55 #include "ui/base/l10n/l10n_util.h"
56 42
57 #if defined(OS_CHROMEOS) 43 #if defined(OS_CHROMEOS)
58 #include "chrome/browser/chromeos/drive/drive_download_handler.h" 44 #include "chrome/browser/chromeos/drive/drive_download_handler.h"
59 #include "chrome/browser/chromeos/drive/drive_file_system_util.h" 45 #include "chrome/browser/chromeos/drive/drive_file_system_util.h"
60 #include "chrome/browser/download/download_file_picker_chromeos.h"
61 #include "chrome/browser/download/save_package_file_picker_chromeos.h" 46 #include "chrome/browser/download/save_package_file_picker_chromeos.h"
62 #endif 47 #endif
63 48
64 using content::BrowserContext; 49 using content::BrowserContext;
65 using content::BrowserThread; 50 using content::BrowserThread;
66 using content::DownloadId; 51 using content::DownloadId;
67 using content::DownloadItem; 52 using content::DownloadItem;
68 using content::DownloadManager; 53 using content::DownloadManager;
69 using content::WebContents;
70 using safe_browsing::DownloadProtectionService; 54 using safe_browsing::DownloadProtectionService;
71 55
72 namespace { 56 namespace {
73 57
74 // String pointer used for identifying safebrowing data associated with 58 // String pointer used for identifying safebrowing data associated with
75 // a download item. 59 // a download item.
76 static const char safe_browsing_id[] = "Safe Browsing ID"; 60 static const char safe_browsing_id[] = "Safe Browsing ID";
77 61
78 // The state of a safebrowsing check. 62 // The state of a safebrowsing check.
79 class SafeBrowsingState : public DownloadCompletionBlocker { 63 class SafeBrowsingState : public DownloadCompletionBlocker {
(...skipping 16 matching lines...) Expand all
96 } 80 }
97 81
98 private: 82 private:
99 DownloadProtectionService::DownloadCheckResult verdict_; 83 DownloadProtectionService::DownloadCheckResult verdict_;
100 84
101 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingState); 85 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingState);
102 }; 86 };
103 87
104 SafeBrowsingState::~SafeBrowsingState() {} 88 SafeBrowsingState::~SafeBrowsingState() {}
105 89
106 // Generate a filename based on the response from the server. Similar
107 // in operation to net::GenerateFileName(), but uses a localized
108 // default name.
109 void GenerateFileNameFromRequest(const DownloadItem& download_item,
110 base::FilePath* generated_name,
111 std::string referrer_charset) {
112 std::string default_file_name(
113 l10n_util::GetStringUTF8(IDS_DEFAULT_DOWNLOAD_FILENAME));
114
115 *generated_name = net::GenerateFileName(download_item.GetURL(),
116 download_item.GetContentDisposition(),
117 referrer_charset,
118 download_item.GetSuggestedFilename(),
119 download_item.GetMimeType(),
120 default_file_name);
121 }
122
123 typedef base::Callback<void(bool)> VisitedBeforeCallback;
124
125 // Condenses the results from HistoryService::GetVisibleVisitCountToHost() to a
126 // single bool so that VisitedBeforeCallback can curry up to 5 other parameters
127 // without a struct.
128 void VisitCountsToVisitedBefore(
129 const VisitedBeforeCallback& callback,
130 HistoryService::Handle unused_handle,
131 bool found_visits,
132 int count,
133 base::Time first_visit) {
134 callback.Run(found_visits && count &&
135 (first_visit.LocalMidnight() < base::Time::Now().LocalMidnight()));
136 }
137
138 base::FilePath GetIntermediatePath(const base::FilePath& target_path,
139 content::DownloadDangerType danger_type,
140 bool is_forced_path) {
141 // If the download is not dangerous, just append .crdownload to the target
142 // path.
143 if (danger_type == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) {
144 if (is_forced_path)
145 return target_path;
146 return download_util::GetCrDownloadPath(target_path);
147 }
148
149 // If the download is potentially dangerous we create a filename of the form
150 // 'Unconfirmed <random>.crdownload'.
151 base::FilePath::StringType file_name;
152 base::FilePath dir = target_path.DirName();
153 #if defined(OS_WIN)
154 string16 unconfirmed_prefix =
155 l10n_util::GetStringUTF16(IDS_DOWNLOAD_UNCONFIRMED_PREFIX);
156 #else
157 std::string unconfirmed_prefix =
158 l10n_util::GetStringUTF8(IDS_DOWNLOAD_UNCONFIRMED_PREFIX);
159 #endif
160 base::SStringPrintf(
161 &file_name,
162 unconfirmed_prefix.append(
163 FILE_PATH_LITERAL(" %d.crdownload")).c_str(),
164 base::RandInt(0, 1000000));
165 return dir.Append(file_name);
166 }
167
168 // Returns a file path in the form that is expected by 90 // Returns a file path in the form that is expected by
169 // platform_util::OpenItem/ShowItemInFolder, including any transformation 91 // platform_util::OpenItem/ShowItemInFolder, including any transformation
170 // required for download abstractions layered on top of the core system, 92 // required for download abstractions layered on top of the core system,
171 // e.g. download to Drive. 93 // e.g. download to Drive.
172 base::FilePath GetPlatformDownloadPath(Profile* profile, 94 base::FilePath GetPlatformDownloadPath(Profile* profile,
173 const DownloadItem* download) { 95 const DownloadItem* download) {
174 #if defined(OS_CHROMEOS) 96 #if defined(OS_CHROMEOS)
175 drive::DriveDownloadHandler* drive_download_handler = 97 drive::DriveDownloadHandler* drive_download_handler =
176 drive::DriveDownloadHandler::GetForProfile(profile); 98 drive::DriveDownloadHandler::GetForProfile(profile);
177 if (drive_download_handler && 99 if (drive_download_handler &&
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 if (!profile_->IsOffTheRecord()) 136 if (!profile_->IsOffTheRecord())
215 return DownloadId(this, next_download_id_++); 137 return DownloadId(this, next_download_id_++);
216 138
217 return BrowserContext::GetDownloadManager(profile_->GetOriginalProfile())-> 139 return BrowserContext::GetDownloadManager(profile_->GetOriginalProfile())->
218 GetDelegate()->GetNextId(); 140 GetDelegate()->GetNextId();
219 } 141 }
220 142
221 bool ChromeDownloadManagerDelegate::DetermineDownloadTarget( 143 bool ChromeDownloadManagerDelegate::DetermineDownloadTarget(
222 DownloadItem* download, 144 DownloadItem* download,
223 const content::DownloadTargetCallback& callback) { 145 const content::DownloadTargetCallback& callback) {
224 #if defined(FULL_SAFE_BROWSING) 146 DownloadTargetDeterminer::CompletionCallback destination_callback =
225 DownloadProtectionService* service = GetDownloadProtectionService(); 147 base::Bind(&ChromeDownloadManagerDelegate::OnDetermineDownloadTargetDone,
226 if (service) { 148 this, callback);
227 VLOG(2) << __FUNCTION__ << "() Start SB URL check for download = " 149 DownloadTargetDeterminer::Start(download,
228 << download->DebugString(false); 150 download_prefs_.get(),
229 service->CheckDownloadUrl( 151 last_download_path_,
230 *download, 152 this,
231 base::Bind( 153 destination_callback);
232 &ChromeDownloadManagerDelegate::CheckDownloadUrlDone,
233 this,
234 download->GetId(),
235 callback));
236 return true;
237 }
238 #endif
239 CheckDownloadUrlDone(download->GetId(), callback,
240 DownloadProtectionService::SAFE);
241 return true; 154 return true;
242 } 155 }
243 156
244 void ChromeDownloadManagerDelegate::ChooseDownloadPath(
245 DownloadItem* item,
246 const base::FilePath& suggested_path,
247 const FileSelectedCallback& file_selected_callback) {
248 // Deletes itself.
249 DownloadFilePicker* file_picker =
250 #if defined(OS_CHROMEOS)
251 new DownloadFilePickerChromeOS();
252 #else
253 new DownloadFilePicker();
254 #endif
255 file_picker->Init(download_manager_, item, suggested_path,
256 file_selected_callback);
257 }
258
259 bool ChromeDownloadManagerDelegate::ShouldOpenFileBasedOnExtension( 157 bool ChromeDownloadManagerDelegate::ShouldOpenFileBasedOnExtension(
260 const base::FilePath& path) { 158 const base::FilePath& path) {
261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 159 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
262 base::FilePath::StringType extension = path.Extension(); 160 if (path.Extension().empty())
263 if (extension.empty())
264 return false; 161 return false;
162 // TODO(asanka): This determination is done based on |path|, while elsewhere
benjhayden 2013/04/09 15:46:32 Where else?
asanka 2013/04/16 20:34:01 Updated comment.
163 // an extension download is recognized based on characteristics of the
164 // DownloadItem other than the path. Reconcile this.
265 if (extensions::Extension::IsExtension(path)) 165 if (extensions::Extension::IsExtension(path))
266 return false; 166 return false;
267 DCHECK(extension[0] == base::FilePath::kExtensionSeparator); 167 return download_prefs_->IsAutoOpenEnabledBasedOnExtension(path);
268 extension.erase(0, 1);
269 return download_prefs_->IsAutoOpenEnabledForExtension(extension);
270 } 168 }
271 169
272 // static 170 // static
273 void ChromeDownloadManagerDelegate::DisableSafeBrowsing(DownloadItem* item) { 171 void ChromeDownloadManagerDelegate::DisableSafeBrowsing(DownloadItem* item) {
274 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
275 #if defined(FULL_SAFE_BROWSING) 173 #if defined(FULL_SAFE_BROWSING)
276 SafeBrowsingState* state = static_cast<SafeBrowsingState*>( 174 SafeBrowsingState* state = static_cast<SafeBrowsingState*>(
277 item->GetUserData(&safe_browsing_id)); 175 item->GetUserData(&safe_browsing_id));
278 if (!state) { 176 if (!state) {
279 state = new SafeBrowsingState(); 177 state = new SafeBrowsingState();
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 292
395 *download_save_dir = prefs->GetFilePath(prefs::kDownloadDefaultDirectory); 293 *download_save_dir = prefs->GetFilePath(prefs::kDownloadDefaultDirectory);
396 294
397 *skip_dir_check = false; 295 *skip_dir_check = false;
398 #if defined(OS_CHROMEOS) 296 #if defined(OS_CHROMEOS)
399 *skip_dir_check = drive::util::IsUnderDriveMountPoint(*website_save_dir); 297 *skip_dir_check = drive::util::IsUnderDriveMountPoint(*website_save_dir);
400 #endif 298 #endif
401 } 299 }
402 300
403 void ChromeDownloadManagerDelegate::ChooseSavePath( 301 void ChromeDownloadManagerDelegate::ChooseSavePath(
404 WebContents* web_contents, 302 content::WebContents* web_contents,
405 const base::FilePath& suggested_path, 303 const base::FilePath& suggested_path,
406 const base::FilePath::StringType& default_extension, 304 const base::FilePath::StringType& default_extension,
407 bool can_save_as_complete, 305 bool can_save_as_complete,
408 const content::SavePackagePathPickedCallback& callback) { 306 const content::SavePackagePathPickedCallback& callback) {
409 // Deletes itself. 307 // Deletes itself.
410 #if defined(OS_CHROMEOS) 308 #if defined(OS_CHROMEOS)
411 new SavePackageFilePickerChromeOS( 309 new SavePackageFilePickerChromeOS(
412 web_contents, 310 web_contents,
413 suggested_path, 311 suggested_path,
414 can_save_as_complete, 312 can_save_as_complete,
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 download->GetFullPath()), 348 download->GetFullPath()),
451 callback); 349 callback);
452 } 350 }
453 351
454 void ChromeDownloadManagerDelegate::ClearLastDownloadPath() { 352 void ChromeDownloadManagerDelegate::ClearLastDownloadPath() {
455 last_download_path_.clear(); 353 last_download_path_.clear();
456 } 354 }
457 355
458 DownloadProtectionService* 356 DownloadProtectionService*
459 ChromeDownloadManagerDelegate::GetDownloadProtectionService() { 357 ChromeDownloadManagerDelegate::GetDownloadProtectionService() {
358 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
460 #if defined(FULL_SAFE_BROWSING) 359 #if defined(FULL_SAFE_BROWSING)
461 SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service(); 360 SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service();
462 if (sb_service && sb_service->download_protection_service() && 361 if (sb_service && sb_service->download_protection_service() &&
463 profile_->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) { 362 profile_->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) {
464 return sb_service->download_protection_service(); 363 return sb_service->download_protection_service();
465 } 364 }
466 #endif 365 #endif
467 return NULL; 366 return NULL;
468 } 367 }
469 368
470 // TODO(phajdan.jr): This is apparently not being exercised in tests. 369 void ChromeDownloadManagerDelegate::PromptUserForDownloadPath(
471 bool ChromeDownloadManagerDelegate::IsDangerousFile( 370 DownloadItem* download,
472 const DownloadItem& download,
473 const base::FilePath& suggested_path, 371 const base::FilePath& suggested_path,
474 bool visited_referrer_before) { 372 const DownloadTargetDeterminerDelegate::FileSelectedCallback& callback) {
475 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 373 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
476 const bool is_extension_download = 374 DownloadFilePicker::ShowFilePicker(
477 download_crx_util::IsExtensionDownload(download); 375 download,
478 376 suggested_path,
479 // User-initiated extension downloads from pref-whitelisted sources are not 377 base::Bind(&ChromeDownloadManagerDelegate::OnDownloadPathSelected,
480 // considered dangerous. 378 this,
481 if (download.HasUserGesture() && 379 callback));
482 is_extension_download &&
483 download_crx_util::OffStoreInstallAllowedByPrefs(profile_, download)) {
484 return false;
485 }
486
487 // Extensions that are not from the gallery are considered dangerous.
488 // When off-store install is disabled we skip this, since in this case, we
489 // will not offer to install the extension.
490 if (extensions::FeatureSwitch::easy_off_store_install()->IsEnabled() &&
491 is_extension_download &&
492 !extensions::WebstoreInstaller::GetAssociatedApproval(download)) {
493 return true;
494 }
495
496 // Anything the user has marked auto-open is OK if it's user-initiated.
497 if (ShouldOpenFileBasedOnExtension(suggested_path) &&
498 download.HasUserGesture())
499 return false;
500
501 // "Allow on user gesture" is OK when we have a user gesture and the hosting
502 // page has been visited before today.
503 download_util::DownloadDangerLevel danger_level =
504 download_util::GetFileDangerLevel(suggested_path.BaseName());
505 if (danger_level == download_util::AllowOnUserGesture) {
506 if (download.GetTransitionType() &
507 content::PAGE_TRANSITION_FROM_ADDRESS_BAR) {
508 return false;
509 }
510 return !download.HasUserGesture() || !visited_referrer_before;
511 }
512
513 return danger_level == download_util::Dangerous;
514 } 380 }
515 381
516 void ChromeDownloadManagerDelegate::GetReservedPath( 382 ExtensionDownloadsEventRouter*
517 DownloadItem& download, 383 ChromeDownloadManagerDelegate::GetExtensionEventRouter() {
518 const base::FilePath& target_path, 384 return DownloadServiceFactory::GetForProfile(profile_)->
519 const base::FilePath& default_download_path, 385 GetExtensionEventRouter();
520 bool should_uniquify_path,
521 const DownloadPathReservationTracker::ReservedPathCallback& callback) {
522 DownloadPathReservationTracker::GetReservedPath(
523 download, target_path, default_download_path, should_uniquify_path,
524 callback);
525 } 386 }
526 387
527 void ChromeDownloadManagerDelegate::CheckDownloadUrlDone( 388 void ChromeDownloadManagerDelegate::DetermineLocalPath(
528 int32 download_id, 389 DownloadItem* download,
529 const content::DownloadTargetCallback& callback, 390 const base::FilePath& virtual_path,
530 DownloadProtectionService::DownloadCheckResult result) { 391 const DownloadTargetDeterminerDelegate::LocalPathCallback& callback) {
531 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 392 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
532 DownloadItem* download = download_manager_->GetDownload(download_id); 393 #if defined(OS_CHROMEOS)
533 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS)) 394 drive::DriveDownloadHandler* drive_download_handler =
534 return; 395 drive::DriveDownloadHandler::GetForProfile(GetProfile());
535 396 if (drive_download_handler) {
536 VLOG(2) << __FUNCTION__ << "() download = " << download->DebugString(false) 397 drive_download_handler->SubstituteDriveDownloadPath(
537 << " verdict = " << result; 398 virtual_path_, download_,
538 content::DownloadDangerType danger_type = download->GetDangerType(); 399 base::Bind(
539 if (result != DownloadProtectionService::SAFE) 400 &DownloadTargetDeterminer::DetermineLocalPathDone,
540 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL; 401 weak_ptr_factory_.GetWeakPtr()));
541
542 // HistoryServiceFactory redirects incognito profiles to on-record profiles.
543 HistoryService* history = HistoryServiceFactory::GetForProfile(
544 profile_, Profile::EXPLICIT_ACCESS);
545 if (!history || !download->GetReferrerUrl().is_valid()) {
546 // If the original profile doesn't have a HistoryService or the referrer url
547 // is invalid, then give up and assume the referrer has not been visited
548 // before. There's no history for on-record profiles in unit_tests, for
549 // example.
550 CheckVisitedReferrerBeforeDone(download_id, callback, danger_type, false);
551 return; 402 return;
552 } 403 }
553 history->GetVisibleVisitCountToHost( 404 #endif
554 download->GetReferrerUrl(), &history_consumer_, 405 callback.Run(virtual_path);
555 base::Bind(&VisitCountsToVisitedBefore, base::Bind( 406 }
556 &ChromeDownloadManagerDelegate::CheckVisitedReferrerBeforeDone, 407
557 this, download_id, callback, danger_type))); 408 void ChromeDownloadManagerDelegate::ReserveVirtualPath(
409 content::DownloadItem* download,
410 const base::FilePath& virtual_path,
411 bool should_uniquify_path,
412 const DownloadTargetDeterminerDelegate::ReservedPathCallback& callback) {
413 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
414 DCHECK(!virtual_path.empty());
415 #if defined(OS_CHROMEOS)
416 // TODO(asanka): Handle path reservations for virtual paths as well.
417 // http://crbug.com/151618
418 if (drive::util::IsUnderDriveMountPoint(virtual_path)) {
419 callback.Run(virtual_path, true);
420 return;
421 }
422 #endif
423 DownloadPathReservationTracker::GetReservedPath(
424 *download, virtual_path, download_prefs_->DownloadPath(),
425 should_uniquify_path, callback);
426 }
427
428 void ChromeDownloadManagerDelegate::OnDownloadPathSelected(
429 const DownloadTargetDeterminerDelegate::FileSelectedCallback& callback,
430 const base::FilePath& virtual_path,
431 const base::FilePath& local_path) {
432 if (!virtual_path.empty())
433 last_download_path_ = virtual_path.DirName();
434 callback.Run(virtual_path, local_path);
435 }
436
437 void ChromeDownloadManagerDelegate::OnDetermineDownloadTargetDone(
438 const content::DownloadTargetCallback& callback,
439 const base::FilePath& virtual_path,
benjhayden 2013/04/09 15:46:32 I spent a few seconds looking for where this was u
440 const base::FilePath& local_path,
441 const base::FilePath& intermediate_path,
442 content::DownloadItem::TargetDisposition target_disposition,
443 content::DownloadDangerType danger_type) {
444 callback.Run(local_path, target_disposition, danger_type, intermediate_path);
558 } 445 }
559 446
560 void ChromeDownloadManagerDelegate::CheckClientDownloadDone( 447 void ChromeDownloadManagerDelegate::CheckClientDownloadDone(
561 int32 download_id, 448 int32 download_id,
562 DownloadProtectionService::DownloadCheckResult result) { 449 DownloadProtectionService::DownloadCheckResult result) {
563 DownloadItem* item = download_manager_->GetDownload(download_id); 450 DownloadItem* item = download_manager_->GetDownload(download_id);
564 if (!item || (item->GetState() != DownloadItem::IN_PROGRESS)) 451 if (!item || (item->GetState() != DownloadItem::IN_PROGRESS))
565 return; 452 return;
566 453
567 VLOG(2) << __FUNCTION__ << "() download = " << item->DebugString(false) 454 VLOG(2) << __FUNCTION__ << "() download = " << item->DebugString(false)
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 registrar_.Remove(this, 492 registrar_.Remove(this,
606 chrome::NOTIFICATION_CRX_INSTALLER_DONE, 493 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
607 source); 494 source);
608 495
609 scoped_refptr<extensions::CrxInstaller> installer = 496 scoped_refptr<extensions::CrxInstaller> installer =
610 content::Source<extensions::CrxInstaller>(source).ptr(); 497 content::Source<extensions::CrxInstaller>(source).ptr();
611 content::DownloadOpenDelayedCallback callback = crx_installers_[installer]; 498 content::DownloadOpenDelayedCallback callback = crx_installers_[installer];
612 crx_installers_.erase(installer.get()); 499 crx_installers_.erase(installer.get());
613 callback.Run(installer->did_handle_successfully()); 500 callback.Run(installer->did_handle_successfully());
614 } 501 }
615
616 struct ChromeDownloadManagerDelegate::ContinueFilenameDeterminationInfo {
617 ContinueFilenameDeterminationInfo();
618 ~ContinueFilenameDeterminationInfo();
619
620 int32 download_id;
621 content::DownloadTargetCallback callback;
622 content::DownloadDangerType danger_type;
623 bool visited_referrer_before;
624 bool should_prompt;
625 };
626
627 ChromeDownloadManagerDelegate::ContinueFilenameDeterminationInfo::
628 ContinueFilenameDeterminationInfo() {}
629 ChromeDownloadManagerDelegate::ContinueFilenameDeterminationInfo::
630 ~ContinueFilenameDeterminationInfo() {}
631
632 void ChromeDownloadManagerDelegate::CheckVisitedReferrerBeforeDone(
633 int32 download_id,
634 const content::DownloadTargetCallback& callback,
635 content::DownloadDangerType danger_type,
636 bool visited_referrer_before) {
637 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
638
639 DownloadItem* download =
640 download_manager_->GetDownload(download_id);
641 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS))
642 return;
643
644 bool should_prompt = (download->GetTargetDisposition() ==
645 DownloadItem::TARGET_DISPOSITION_PROMPT);
646 bool is_forced_path = !download->GetForcedFilePath().empty();
647 base::FilePath generated_name;
648 base::FilePath suggested_path;
649
650 // Check whether this download is for an extension install or not.
651 // Allow extensions to be explicitly saved.
652 if (!is_forced_path) {
653 GenerateFileNameFromRequest(
654 *download,
655 &generated_name,
656 profile_->GetPrefs()->GetString(prefs::kDefaultCharset));
657
658 // Freeze the user's preference for showing a Save As dialog. We're going
659 // to bounce around a bunch of threads and we don't want to worry about race
660 // conditions where the user changes this pref out from under us.
661 if (download_prefs_->PromptForDownload()) {
662 // But ignore the user's preference for the following scenarios:
663 // 1) Extension installation. Note that we only care here about the case
664 // where an extension is installed, not when one is downloaded with
665 // "save as...".
666 // 2) Filetypes marked "always open." If the user just wants this file
667 // opened, don't bother asking where to keep it.
668 if (!download_crx_util::IsExtensionDownload(*download) &&
669 !ShouldOpenFileBasedOnExtension(generated_name))
670 should_prompt = true;
671 }
672 if (download_prefs_->IsDownloadPathManaged())
673 should_prompt = false;
674
675 // Determine the proper path for a download, by either one of the following:
676 // 1) using the default download directory.
677 // 2) prompting the user.
678 base::FilePath target_directory;
679 if (should_prompt && !last_download_path_.empty())
680 target_directory = last_download_path_;
681 else
682 target_directory = download_prefs_->DownloadPath();
683 suggested_path = target_directory.Append(generated_name);
684 } else {
685 DCHECK(!should_prompt);
686 suggested_path = download->GetForcedFilePath();
687 }
688
689 ContinueFilenameDeterminationInfo continue_info;
690 continue_info.download_id = download_id;
691 continue_info.callback = callback;
692 continue_info.danger_type = danger_type;
693 continue_info.visited_referrer_before = visited_referrer_before;
694 continue_info.should_prompt = should_prompt;
695
696 base::Closure filename_determined = base::Bind(
697 &ChromeDownloadManagerDelegate::ContinueDeterminingFilename,
698 this, continue_info, suggested_path, is_forced_path);
699 #if defined(OS_ANDROID)
700 filename_determined.Run();
701 #else
702 if (is_forced_path ||
703 !DownloadServiceFactory::GetForProfile(profile_)
704 ->GetExtensionEventRouter()) {
705 filename_determined.Run();
706 } else {
707 DownloadService* service = DownloadServiceFactory::GetForProfile(profile_);
708 ExtensionDownloadsEventRouter* router = service->GetExtensionEventRouter();
709 ExtensionDownloadsEventRouter::FilenameChangedCallback overriding =
710 base::Bind(&ChromeDownloadManagerDelegate::OnExtensionOverridingFilename,
711 this, continue_info);
712 router->OnDeterminingFilename(
713 download, generated_name, filename_determined, overriding);
714 }
715 #endif
716 }
717
718 void ChromeDownloadManagerDelegate::OnExtensionOverridingFilename(
719 const ContinueFilenameDeterminationInfo& continue_info,
720 const base::FilePath& changed_filename,
721 bool overwrite) {
722 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
723 DownloadItem* download =
724 download_manager_->GetDownload(continue_info.download_id);
725 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS))
726 return;
727 // If an extension overrides the filename, then the target directory will be
728 // forced to download_prefs_->DownloadPath() since extensions cannot place
729 // downloaded files anywhere except there. This prevents subdirectories from
730 // accumulating: if an extension is allowed to say that a file should go in
731 // last_download_path/music/foo.mp3, then last_download_path will accumulate
732 // the subdirectory /music/ so that the next download may end up in
733 // Downloads/music/music/music/bar.mp3.
734 base::FilePath temp_filename(download_prefs_->DownloadPath().Append(
735 changed_filename).NormalizePathSeparators());
736 // Do not pass a mime type to GenerateSafeFileName so that it does not force
737 // the filename to have an extension if the (chrome) extension does not
738 // suggest it.
739 net::GenerateSafeFileName(std::string(), false, &temp_filename);
740 // If |is_forced_path| were true, then extensions would not have been
741 // consulted, so use |overwrite| instead of |is_forced_path|. This does NOT
742 // set DownloadItem::GetForcedFilePath()!
743 ContinueDeterminingFilename(continue_info, temp_filename, overwrite);
744 }
745
746 void ChromeDownloadManagerDelegate::ContinueDeterminingFilename(
747 const ContinueFilenameDeterminationInfo& continue_info,
748 const base::FilePath& suggested_path,
749 bool is_forced_path) {
750 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
751 int32 download_id = continue_info.download_id;
752 const content::DownloadTargetCallback& callback = continue_info.callback;
753 content::DownloadDangerType danger_type = continue_info.danger_type;
754 bool visited_referrer_before = continue_info.visited_referrer_before;
755 bool should_prompt = continue_info.should_prompt;
756 DownloadItem* download =
757 download_manager_->GetDownload(download_id);
758 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS))
759 return;
760
761 // If the download hasn't already been marked dangerous (could be
762 // DANGEROUS_URL), check if it is a dangerous file.
763 if (danger_type == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) {
764 if (!should_prompt && !is_forced_path &&
765 IsDangerousFile(*download, suggested_path, visited_referrer_before)) {
766 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE;
767 }
768
769 #if defined(FULL_SAFE_BROWSING)
770 DownloadProtectionService* service = GetDownloadProtectionService();
771 // If this type of files is handled by the enhanced SafeBrowsing download
772 // protection, mark it as potentially dangerous content until we are done
773 // with scanning it.
774 if (service && service->enabled()) {
775 // TODO(noelutz): if the user changes the extension name in the UI to
776 // something like .exe SafeBrowsing will currently *not* check if the
777 // download is malicious.
778 if (service->IsSupportedDownload(*download, suggested_path))
779 danger_type = content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT;
780 }
781 #endif
782 } else {
783 // Currently we only expect this case.
784 DCHECK_EQ(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL, danger_type);
785 }
786
787 #if defined (OS_CHROMEOS)
788 drive::DriveDownloadHandler* drive_download_handler =
789 drive::DriveDownloadHandler::GetForProfile(profile_);
790 if (drive_download_handler) {
791 drive_download_handler->SubstituteDriveDownloadPath(
792 suggested_path, download,
793 base::Bind(
794 &ChromeDownloadManagerDelegate::SubstituteDriveDownloadPathCallback,
795 this, download->GetId(), callback, should_prompt, is_forced_path,
796 danger_type));
797 return;
798 }
799 #endif
800 GetReservedPath(
801 *download, suggested_path, download_prefs_->DownloadPath(),
802 !is_forced_path,
803 base::Bind(&ChromeDownloadManagerDelegate::OnPathReservationAvailable,
804 this, download->GetId(), callback, should_prompt,
805 danger_type));
806 }
807
808 #if defined (OS_CHROMEOS)
809 // TODO(asanka): Merge this logic with the logic in DownloadFilePickerChromeOS.
810 void ChromeDownloadManagerDelegate::SubstituteDriveDownloadPathCallback(
811 int32 download_id,
812 const content::DownloadTargetCallback& callback,
813 bool should_prompt,
814 bool is_forced_path,
815 content::DownloadDangerType danger_type,
816 const base::FilePath& suggested_path) {
817 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
818 DownloadItem* download =
819 download_manager_->GetDownload(download_id);
820 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS))
821 return;
822
823 if (suggested_path.empty()) {
824 // Substitution failed.
825 callback.Run(base::FilePath(),
826 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
827 danger_type,
828 base::FilePath());
829 return;
830 }
831
832 GetReservedPath(
833 *download, suggested_path, download_prefs_->DownloadPath(),
834 !is_forced_path,
835 base::Bind(&ChromeDownloadManagerDelegate::OnPathReservationAvailable,
836 this, download->GetId(), callback, should_prompt,
837 danger_type));
838 }
839 #endif
840
841 void ChromeDownloadManagerDelegate::OnPathReservationAvailable(
842 int32 download_id,
843 const content::DownloadTargetCallback& callback,
844 bool should_prompt,
845 content::DownloadDangerType danger_type,
846 const base::FilePath& reserved_path,
847 bool reserved_path_verified) {
848 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
849 DownloadItem* download =
850 download_manager_->GetDownload(download_id);
851 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS))
852 return;
853 if (should_prompt || !reserved_path_verified) {
854 // If the target path could not be verified then the path was non-existant,
855 // non writeable or could not be uniquified. Prompt the user.
856 ChooseDownloadPath(
857 download, reserved_path,
858 base::Bind(&ChromeDownloadManagerDelegate::OnTargetPathDetermined,
859 this, download_id, callback,
860 DownloadItem::TARGET_DISPOSITION_PROMPT, danger_type));
861 } else {
862 OnTargetPathDetermined(download_id, callback,
863 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
864 danger_type, reserved_path);
865 }
866 }
867
868 void ChromeDownloadManagerDelegate::OnTargetPathDetermined(
869 int32 download_id,
870 const content::DownloadTargetCallback& callback,
871 DownloadItem::TargetDisposition disposition,
872 content::DownloadDangerType danger_type,
873 const base::FilePath& target_path) {
874 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
875 base::FilePath intermediate_path;
876 DownloadItem* download =
877 download_manager_->GetDownload(download_id);
878 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS))
879 return;
880
881 // If |target_path| is empty, then that means that the user wants to cancel
882 // the download.
883 if (!target_path.empty()) {
884 intermediate_path = GetIntermediatePath(
885 target_path, danger_type, !download->GetForcedFilePath().empty());
886
887 // Retain the last directory. Exclude temporary downloads since the path
888 // likely points at the location of a temporary file.
889 // TODO(asanka): This logic is a hack. DownloadFilePicker should give us a
890 // directory to persist. Or perhaps, if the Drive path
891 // substitution logic is moved here, then we would have a
892 // persistable path after the DownloadFilePicker is done.
893 if (disposition == DownloadItem::TARGET_DISPOSITION_PROMPT &&
894 !download->IsTemporary())
895 last_download_path_ = target_path.DirName();
896 }
897 callback.Run(target_path, disposition, danger_type, intermediate_path);
898 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698