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

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: Address comments. 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" 31 #include "chrome/browser/extensions/api/downloads/downloads_api.h"
33 #include "chrome/browser/extensions/crx_installer.h" 32 #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" 33 #include "chrome/browser/platform_util.h"
39 #include "chrome/browser/profiles/profile.h" 34 #include "chrome/browser/profiles/profile.h"
40 #include "chrome/browser/safe_browsing/safe_browsing_service.h" 35 #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" 36 #include "chrome/common/chrome_notification_types.h"
44 #include "chrome/common/extensions/feature_switch.h" 37 #include "chrome/common/extensions/extension.h"
45 #include "chrome/common/extensions/user_script.h"
46 #include "chrome/common/pref_names.h" 38 #include "chrome/common/pref_names.h"
47 #include "components/user_prefs/pref_registry_syncable.h" 39 #include "components/user_prefs/pref_registry_syncable.h"
48 #include "content/public/browser/download_item.h" 40 #include "content/public/browser/download_item.h"
49 #include "content/public/browser/download_manager.h" 41 #include "content/public/browser/download_manager.h"
50 #include "content/public/browser/notification_source.h" 42 #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 43
57 #if defined(OS_CHROMEOS) 44 #if defined(OS_CHROMEOS)
58 #include "chrome/browser/chromeos/drive/drive_download_handler.h" 45 #include "chrome/browser/chromeos/drive/drive_download_handler.h"
59 #include "chrome/browser/chromeos/drive/drive_file_system_util.h" 46 #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" 47 #include "chrome/browser/download/save_package_file_picker_chromeos.h"
62 #endif 48 #endif
63 49
64 using content::BrowserContext; 50 using content::BrowserContext;
65 using content::BrowserThread; 51 using content::BrowserThread;
66 using content::DownloadId; 52 using content::DownloadId;
67 using content::DownloadItem; 53 using content::DownloadItem;
68 using content::DownloadManager; 54 using content::DownloadManager;
69 using content::WebContents;
70 using safe_browsing::DownloadProtectionService; 55 using safe_browsing::DownloadProtectionService;
71 56
72 namespace { 57 namespace {
73 58
74 // String pointer used for identifying safebrowing data associated with 59 // String pointer used for identifying safebrowing data associated with
75 // a download item. 60 // a download item.
76 static const char safe_browsing_id[] = "Safe Browsing ID"; 61 static const char safe_browsing_id[] = "Safe Browsing ID";
77 62
78 // The state of a safebrowsing check. 63 // The state of a safebrowsing check.
79 class SafeBrowsingState : public DownloadCompletionBlocker { 64 class SafeBrowsingState : public DownloadCompletionBlocker {
(...skipping 16 matching lines...) Expand all
96 } 81 }
97 82
98 private: 83 private:
99 DownloadProtectionService::DownloadCheckResult verdict_; 84 DownloadProtectionService::DownloadCheckResult verdict_;
100 85
101 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingState); 86 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingState);
102 }; 87 };
103 88
104 SafeBrowsingState::~SafeBrowsingState() {} 89 SafeBrowsingState::~SafeBrowsingState() {}
105 90
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 91 // Returns a file path in the form that is expected by
169 // platform_util::OpenItem/ShowItemInFolder, including any transformation 92 // platform_util::OpenItem/ShowItemInFolder, including any transformation
170 // required for download abstractions layered on top of the core system, 93 // required for download abstractions layered on top of the core system,
171 // e.g. download to Drive. 94 // e.g. download to Drive.
172 base::FilePath GetPlatformDownloadPath(Profile* profile, 95 base::FilePath GetPlatformDownloadPath(Profile* profile,
173 const DownloadItem* download) { 96 const DownloadItem* download) {
174 #if defined(OS_CHROMEOS) 97 #if defined(OS_CHROMEOS)
175 drive::DriveDownloadHandler* drive_download_handler = 98 drive::DriveDownloadHandler* drive_download_handler =
176 drive::DriveDownloadHandler::GetForProfile(profile); 99 drive::DriveDownloadHandler::GetForProfile(profile);
177 if (drive_download_handler && 100 if (drive_download_handler &&
178 drive_download_handler->IsDriveDownload(download)) 101 drive_download_handler->IsDriveDownload(download))
179 return drive_download_handler->GetTargetPath(download); 102 return drive_download_handler->GetTargetPath(download);
180 #endif 103 #endif
181 return download->GetFullPath(); 104 return download->GetFullPath();
182 } 105 }
183 106
107 // Callback invoked by DownloadProtectionService::CheckClientDownload.
108 // |is_content_check_supported| is true if the SB service supports scanning the
109 // download for malicious content.
110 // |callback| is invoked with a danger type determined as follows:
111 //
112 // Danger type is (in order of preference):
113 // * DANGEROUS_URL, if the URL is a known malware site.
114 // * MAYBE_DANGEROUS_CONTENT, if the content will be scanned for
115 // malware. I.e. |is_content_check_supported| is true.
116 // * NOT_DANGEROUS.
117 void CheckDownloadUrlDone(
118 const DownloadTargetDeterminerDelegate::CheckDownloadUrlCallback& callback,
119 bool is_content_check_supported,
120 DownloadProtectionService::DownloadCheckResult result) {
121 content::DownloadDangerType danger_type;
122 if (result == DownloadProtectionService::SAFE) {
123 // If this type of files is handled by the enhanced SafeBrowsing download
124 // protection, mark it as potentially dangerous content until we are done
125 // with scanning it.
126 if (is_content_check_supported)
127 danger_type = content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT;
128 else
129 danger_type = content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS;
130 } else {
131 // If the URL is malicious, we'll use that as the danger type. The results
132 // of the content check, if one is performed, will be ignored.
133 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL;
134 }
135 callback.Run(danger_type);
136 }
137
184 } // namespace 138 } // namespace
185 139
186 // static 140 // static
187 void ChromeDownloadManagerDelegate::RegisterUserPrefs( 141 void ChromeDownloadManagerDelegate::RegisterUserPrefs(
188 PrefRegistrySyncable* registry) { 142 PrefRegistrySyncable* registry) {
189 const base::FilePath& default_download_path = 143 const base::FilePath& default_download_path =
190 download_util::GetDefaultDownloadDirectory(); 144 download_util::GetDefaultDownloadDirectory();
191 registry->RegisterFilePathPref(prefs::kSaveFileDefaultDirectory, 145 registry->RegisterFilePathPref(prefs::kSaveFileDefaultDirectory,
192 default_download_path, 146 default_download_path,
193 PrefRegistrySyncable::UNSYNCABLE_PREF); 147 PrefRegistrySyncable::UNSYNCABLE_PREF);
(...skipping 20 matching lines...) Expand all
214 if (!profile_->IsOffTheRecord()) 168 if (!profile_->IsOffTheRecord())
215 return DownloadId(this, next_download_id_++); 169 return DownloadId(this, next_download_id_++);
216 170
217 return BrowserContext::GetDownloadManager(profile_->GetOriginalProfile())-> 171 return BrowserContext::GetDownloadManager(profile_->GetOriginalProfile())->
218 GetDelegate()->GetNextId(); 172 GetDelegate()->GetNextId();
219 } 173 }
220 174
221 bool ChromeDownloadManagerDelegate::DetermineDownloadTarget( 175 bool ChromeDownloadManagerDelegate::DetermineDownloadTarget(
222 DownloadItem* download, 176 DownloadItem* download,
223 const content::DownloadTargetCallback& callback) { 177 const content::DownloadTargetCallback& callback) {
224 #if defined(FULL_SAFE_BROWSING) 178 DownloadTargetDeterminer::Start(download,
225 DownloadProtectionService* service = GetDownloadProtectionService(); 179 download_prefs_.get(),
226 if (service) { 180 last_download_path_,
227 VLOG(2) << __FUNCTION__ << "() Start SB URL check for download = " 181 this,
228 << download->DebugString(false); 182 callback);
229 service->CheckDownloadUrl(
230 *download,
231 base::Bind(
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; 183 return true;
242 } 184 }
243 185
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( 186 bool ChromeDownloadManagerDelegate::ShouldOpenFileBasedOnExtension(
260 const base::FilePath& path) { 187 const base::FilePath& path) {
261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
262 base::FilePath::StringType extension = path.Extension(); 189 if (path.Extension().empty())
263 if (extension.empty())
264 return false; 190 return false;
191 // TODO(asanka): This determination is done based on |path|, while
192 // ShouldOpenDownload() detects extension downloads based on the
193 // characteristics of the download. Reconcile this. http://crbug.com/167702
265 if (extensions::Extension::IsExtension(path)) 194 if (extensions::Extension::IsExtension(path))
266 return false; 195 return false;
267 DCHECK(extension[0] == base::FilePath::kExtensionSeparator); 196 return download_prefs_->IsAutoOpenEnabledBasedOnExtension(path);
268 extension.erase(0, 1);
269 return download_prefs_->IsAutoOpenEnabledForExtension(extension);
270 } 197 }
271 198
272 // static 199 // static
273 void ChromeDownloadManagerDelegate::DisableSafeBrowsing(DownloadItem* item) { 200 void ChromeDownloadManagerDelegate::DisableSafeBrowsing(DownloadItem* item) {
274 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 201 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
275 #if defined(FULL_SAFE_BROWSING) 202 #if defined(FULL_SAFE_BROWSING)
276 SafeBrowsingState* state = static_cast<SafeBrowsingState*>( 203 SafeBrowsingState* state = static_cast<SafeBrowsingState*>(
277 item->GetUserData(&safe_browsing_id)); 204 item->GetUserData(&safe_browsing_id));
278 if (!state) { 205 if (!state) {
279 state = new SafeBrowsingState(); 206 state = new SafeBrowsingState();
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 321
395 *download_save_dir = prefs->GetFilePath(prefs::kDownloadDefaultDirectory); 322 *download_save_dir = prefs->GetFilePath(prefs::kDownloadDefaultDirectory);
396 323
397 *skip_dir_check = false; 324 *skip_dir_check = false;
398 #if defined(OS_CHROMEOS) 325 #if defined(OS_CHROMEOS)
399 *skip_dir_check = drive::util::IsUnderDriveMountPoint(*website_save_dir); 326 *skip_dir_check = drive::util::IsUnderDriveMountPoint(*website_save_dir);
400 #endif 327 #endif
401 } 328 }
402 329
403 void ChromeDownloadManagerDelegate::ChooseSavePath( 330 void ChromeDownloadManagerDelegate::ChooseSavePath(
404 WebContents* web_contents, 331 content::WebContents* web_contents,
405 const base::FilePath& suggested_path, 332 const base::FilePath& suggested_path,
406 const base::FilePath::StringType& default_extension, 333 const base::FilePath::StringType& default_extension,
407 bool can_save_as_complete, 334 bool can_save_as_complete,
408 const content::SavePackagePathPickedCallback& callback) { 335 const content::SavePackagePathPickedCallback& callback) {
409 // Deletes itself. 336 // Deletes itself.
410 #if defined(OS_CHROMEOS) 337 #if defined(OS_CHROMEOS)
411 new SavePackageFilePickerChromeOS( 338 new SavePackageFilePickerChromeOS(
412 web_contents, 339 web_contents,
413 suggested_path, 340 suggested_path,
414 can_save_as_complete, 341 can_save_as_complete,
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 download->GetFullPath()), 377 download->GetFullPath()),
451 callback); 378 callback);
452 } 379 }
453 380
454 void ChromeDownloadManagerDelegate::ClearLastDownloadPath() { 381 void ChromeDownloadManagerDelegate::ClearLastDownloadPath() {
455 last_download_path_.clear(); 382 last_download_path_.clear();
456 } 383 }
457 384
458 DownloadProtectionService* 385 DownloadProtectionService*
459 ChromeDownloadManagerDelegate::GetDownloadProtectionService() { 386 ChromeDownloadManagerDelegate::GetDownloadProtectionService() {
387 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
460 #if defined(FULL_SAFE_BROWSING) 388 #if defined(FULL_SAFE_BROWSING)
461 SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service(); 389 SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service();
462 if (sb_service && sb_service->download_protection_service() && 390 if (sb_service && sb_service->download_protection_service() &&
463 profile_->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) { 391 profile_->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) {
464 return sb_service->download_protection_service(); 392 return sb_service->download_protection_service();
465 } 393 }
466 #endif 394 #endif
467 return NULL; 395 return NULL;
468 } 396 }
469 397
470 // TODO(phajdan.jr): This is apparently not being exercised in tests. 398 void ChromeDownloadManagerDelegate::NotifyExtensions(
471 bool ChromeDownloadManagerDelegate::IsDangerousFile( 399 DownloadItem* download,
472 const DownloadItem& download, 400 const base::FilePath& virtual_path,
473 const base::FilePath& suggested_path, 401 const NotifyExtensionsCallback& callback) {
474 bool visited_referrer_before) {
475 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 402 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
476 const bool is_extension_download = 403 #if !defined(OS_ANDROID)
477 download_crx_util::IsExtensionDownload(download); 404 ExtensionDownloadsEventRouter* router =
478 405 DownloadServiceFactory::GetForProfile(profile_)->
479 // User-initiated extension downloads from pref-whitelisted sources are not 406 GetExtensionEventRouter();
480 // considered dangerous. 407 if (router) {
481 if (download.HasUserGesture() && 408 base::Closure original_path_callback =
482 is_extension_download && 409 base::Bind(callback, base::FilePath(),
483 download_crx_util::OffStoreInstallAllowedByPrefs(profile_, download)) { 410 DownloadPathReservationTracker::UNIQUIFY);
484 return false; 411 router->OnDeterminingFilename(download, virtual_path.BaseName(),
412 original_path_callback,
413 callback);
414 return;
485 } 415 }
486 416 #endif
487 // Extensions that are not from the gallery are considered dangerous. 417 callback.Run(base::FilePath(), DownloadPathReservationTracker::UNIQUIFY);
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 } 418 }
515 419
516 void ChromeDownloadManagerDelegate::GetReservedPath( 420 void ChromeDownloadManagerDelegate::ReserveVirtualPath(
517 DownloadItem& download, 421 content::DownloadItem* download,
518 const base::FilePath& target_path, 422 const base::FilePath& virtual_path,
519 const base::FilePath& default_download_path,
520 DownloadPathReservationTracker::FilenameConflictAction conflict_action, 423 DownloadPathReservationTracker::FilenameConflictAction conflict_action,
521 const DownloadPathReservationTracker::ReservedPathCallback& callback) { 424 const DownloadTargetDeterminerDelegate::ReservedPathCallback& callback) {
425 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
426 DCHECK(!virtual_path.empty());
427 #if defined(OS_CHROMEOS)
428 // TODO(asanka): Handle path reservations for virtual paths as well.
429 // http://crbug.com/151618
430 if (drive::util::IsUnderDriveMountPoint(virtual_path)) {
431 callback.Run(virtual_path, true);
432 return;
433 }
434 #endif
522 DownloadPathReservationTracker::GetReservedPath( 435 DownloadPathReservationTracker::GetReservedPath(
523 download, target_path, default_download_path, conflict_action, callback); 436 *download, virtual_path, download_prefs_->DownloadPath(),
437 conflict_action, callback);
524 } 438 }
525 439
526 void ChromeDownloadManagerDelegate::CheckDownloadUrlDone( 440 void ChromeDownloadManagerDelegate::PromptUserForDownloadPath(
527 int32 download_id, 441 DownloadItem* download,
528 const content::DownloadTargetCallback& callback, 442 const base::FilePath& suggested_path,
529 DownloadProtectionService::DownloadCheckResult result) { 443 const DownloadTargetDeterminerDelegate::FileSelectedCallback& callback) {
530 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 444 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
531 DownloadItem* download = download_manager_->GetDownload(download_id); 445 DownloadFilePicker::ShowFilePicker(
532 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS)) 446 download,
533 return; 447 suggested_path,
448 base::Bind(&ChromeDownloadManagerDelegate::OnDownloadPathSelected,
449 this,
450 callback));
451 }
534 452
535 VLOG(2) << __FUNCTION__ << "() download = " << download->DebugString(false) 453 void ChromeDownloadManagerDelegate::DetermineLocalPath(
536 << " verdict = " << result; 454 DownloadItem* download,
537 content::DownloadDangerType danger_type = download->GetDangerType(); 455 const base::FilePath& virtual_path,
538 if (result != DownloadProtectionService::SAFE) 456 const DownloadTargetDeterminerDelegate::LocalPathCallback& callback) {
539 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL; 457 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
540 458 #if defined(OS_CHROMEOS)
541 // HistoryServiceFactory redirects incognito profiles to on-record profiles. 459 drive::DriveDownloadHandler* drive_download_handler =
542 HistoryService* history = HistoryServiceFactory::GetForProfile( 460 drive::DriveDownloadHandler::GetForProfile(profile_);
543 profile_, Profile::EXPLICIT_ACCESS); 461 if (drive_download_handler) {
544 if (!history || !download->GetReferrerUrl().is_valid()) { 462 drive_download_handler->SubstituteDriveDownloadPath(
545 // If the original profile doesn't have a HistoryService or the referrer url 463 virtual_path, download, callback);
546 // is invalid, then give up and assume the referrer has not been visited
547 // before. There's no history for on-record profiles in unit_tests, for
548 // example.
549 CheckVisitedReferrerBeforeDone(download_id, callback, danger_type, false);
550 return; 464 return;
551 } 465 }
552 history->GetVisibleVisitCountToHost( 466 #endif
553 download->GetReferrerUrl(), &history_consumer_, 467 callback.Run(virtual_path);
554 base::Bind(&VisitCountsToVisitedBefore, base::Bind( 468 }
555 &ChromeDownloadManagerDelegate::CheckVisitedReferrerBeforeDone, 469
556 this, download_id, callback, danger_type))); 470 void ChromeDownloadManagerDelegate::CheckDownloadUrl(
471 DownloadItem* download,
472 const base::FilePath& suggested_path,
473 const CheckDownloadUrlCallback& callback) {
474 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
475
476 #if defined(FULL_SAFE_BROWSING)
477 safe_browsing::DownloadProtectionService* service =
478 GetDownloadProtectionService();
479 if (service) {
480 bool is_content_check_supported =
481 service->IsSupportedDownload(*download, suggested_path);
482 VLOG(2) << __FUNCTION__ << "() Start SB URL check for download = "
483 << download->DebugString(false);
484 service->CheckDownloadUrl(*download,
485 base::Bind(&CheckDownloadUrlDone,
486 callback,
487 is_content_check_supported));
488 return;
489 }
490 #endif
491 callback.Run(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
492 }
493
494 void ChromeDownloadManagerDelegate::OnDownloadPathSelected(
Randy Smith (Not in Mondays) 2013/04/26 19:05:46 Any reason not to put this next to PromptUserForDo
asanka 2013/04/29 18:43:20 Moved it next to PromptUserForDownloadPath(). I or
495 const DownloadTargetDeterminerDelegate::FileSelectedCallback& callback,
496 const base::FilePath& virtual_path) {
497 if (!virtual_path.empty())
498 last_download_path_ = virtual_path.DirName();
499 callback.Run(virtual_path);
557 } 500 }
558 501
559 void ChromeDownloadManagerDelegate::CheckClientDownloadDone( 502 void ChromeDownloadManagerDelegate::CheckClientDownloadDone(
560 int32 download_id, 503 int32 download_id,
561 DownloadProtectionService::DownloadCheckResult result) { 504 DownloadProtectionService::DownloadCheckResult result) {
562 DownloadItem* item = download_manager_->GetDownload(download_id); 505 DownloadItem* item = download_manager_->GetDownload(download_id);
563 if (!item || (item->GetState() != DownloadItem::IN_PROGRESS)) 506 if (!item || (item->GetState() != DownloadItem::IN_PROGRESS))
564 return; 507 return;
565 508
566 VLOG(2) << __FUNCTION__ << "() download = " << item->DebugString(false) 509 VLOG(2) << __FUNCTION__ << "() download = " << item->DebugString(false)
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
604 registrar_.Remove(this, 547 registrar_.Remove(this,
605 chrome::NOTIFICATION_CRX_INSTALLER_DONE, 548 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
606 source); 549 source);
607 550
608 scoped_refptr<extensions::CrxInstaller> installer = 551 scoped_refptr<extensions::CrxInstaller> installer =
609 content::Source<extensions::CrxInstaller>(source).ptr(); 552 content::Source<extensions::CrxInstaller>(source).ptr();
610 content::DownloadOpenDelayedCallback callback = crx_installers_[installer]; 553 content::DownloadOpenDelayedCallback callback = crx_installers_[installer];
611 crx_installers_.erase(installer.get()); 554 crx_installers_.erase(installer.get());
612 callback.Run(installer->did_handle_successfully()); 555 callback.Run(installer->did_handle_successfully());
613 } 556 }
614
615 struct ChromeDownloadManagerDelegate::ContinueFilenameDeterminationInfo {
616 ContinueFilenameDeterminationInfo();
617 ~ContinueFilenameDeterminationInfo();
618
619 int32 download_id;
620 content::DownloadTargetCallback callback;
621 content::DownloadDangerType danger_type;
622 bool visited_referrer_before;
623 bool should_prompt;
624 };
625
626 ChromeDownloadManagerDelegate::ContinueFilenameDeterminationInfo::
627 ContinueFilenameDeterminationInfo() {}
628 ChromeDownloadManagerDelegate::ContinueFilenameDeterminationInfo::
629 ~ContinueFilenameDeterminationInfo() {}
630
631 void ChromeDownloadManagerDelegate::CheckVisitedReferrerBeforeDone(
632 int32 download_id,
633 const content::DownloadTargetCallback& callback,
634 content::DownloadDangerType danger_type,
635 bool visited_referrer_before) {
636 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
637
638 DownloadItem* download =
639 download_manager_->GetDownload(download_id);
640 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS))
641 return;
642
643 bool should_prompt = (download->GetTargetDisposition() ==
644 DownloadItem::TARGET_DISPOSITION_PROMPT);
645 bool is_forced_path = !download->GetForcedFilePath().empty();
646 base::FilePath generated_name;
647 base::FilePath suggested_path;
648
649 // Check whether this download is for an extension install or not.
650 // Allow extensions to be explicitly saved.
651 if (!is_forced_path) {
652 GenerateFileNameFromRequest(
653 *download,
654 &generated_name,
655 profile_->GetPrefs()->GetString(prefs::kDefaultCharset));
656
657 // Freeze the user's preference for showing a Save As dialog. We're going
658 // to bounce around a bunch of threads and we don't want to worry about race
659 // conditions where the user changes this pref out from under us.
660 if (download_prefs_->PromptForDownload()) {
661 // But ignore the user's preference for the following scenarios:
662 // 1) Extension installation. Note that we only care here about the case
663 // where an extension is installed, not when one is downloaded with
664 // "save as...".
665 // 2) Filetypes marked "always open." If the user just wants this file
666 // opened, don't bother asking where to keep it.
667 if (!download_crx_util::IsExtensionDownload(*download) &&
668 !ShouldOpenFileBasedOnExtension(generated_name))
669 should_prompt = true;
670 }
671 if (download_prefs_->IsDownloadPathManaged())
672 should_prompt = false;
673
674 // Determine the proper path for a download, by either one of the following:
675 // 1) using the default download directory.
676 // 2) prompting the user.
677 base::FilePath target_directory;
678 if (should_prompt && !last_download_path_.empty())
679 target_directory = last_download_path_;
680 else
681 target_directory = download_prefs_->DownloadPath();
682 suggested_path = target_directory.Append(generated_name);
683 } else {
684 DCHECK(!should_prompt);
685 suggested_path = download->GetForcedFilePath();
686 }
687
688 ContinueFilenameDeterminationInfo continue_info;
689 continue_info.download_id = download_id;
690 continue_info.callback = callback;
691 continue_info.danger_type = danger_type;
692 continue_info.visited_referrer_before = visited_referrer_before;
693 continue_info.should_prompt = should_prompt;
694
695 DownloadPathReservationTracker::FilenameConflictAction conflict_action = (
696 is_forced_path ?
697 DownloadPathReservationTracker::OVERWRITE :
698 DownloadPathReservationTracker::UNIQUIFY);
699 base::Closure filename_determined = base::Bind(
700 &ChromeDownloadManagerDelegate::ContinueDeterminingFilename,
701 this, continue_info, suggested_path, conflict_action);
702 #if defined(OS_ANDROID)
703 filename_determined.Run();
704 #else
705 if (is_forced_path ||
706 !DownloadServiceFactory::GetForProfile(profile_)
707 ->GetExtensionEventRouter()) {
708 filename_determined.Run();
709 } else {
710 DownloadService* service = DownloadServiceFactory::GetForProfile(profile_);
711 ExtensionDownloadsEventRouter* router = service->GetExtensionEventRouter();
712 ExtensionDownloadsEventRouter::FilenameChangedCallback overriding =
713 base::Bind(&ChromeDownloadManagerDelegate::OnExtensionOverridingFilename,
714 this, continue_info);
715 router->OnDeterminingFilename(
716 download, generated_name, filename_determined, overriding);
717 }
718 #endif
719 }
720
721 void ChromeDownloadManagerDelegate::OnExtensionOverridingFilename(
722 const ContinueFilenameDeterminationInfo& continue_info,
723 const base::FilePath& changed_filename,
724 DownloadPathReservationTracker::FilenameConflictAction conflict_action) {
725 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
726 DownloadItem* download =
727 download_manager_->GetDownload(continue_info.download_id);
728 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS))
729 return;
730
731 // If an extension overrides the filename, then the target directory will be
732 // forced to download_prefs_->DownloadPath() since extensions cannot place
733 // downloaded files anywhere except there. This prevents subdirectories from
734 // accumulating: if an extension is allowed to say that a file should go in
735 // last_download_path/music/foo.mp3, then last_download_path will accumulate
736 // the subdirectory /music/ so that the next download may end up in
737 // Downloads/music/music/music/bar.mp3.
738 base::FilePath temp_filename(download_prefs_->DownloadPath().Append(
739 changed_filename).NormalizePathSeparators());
740 // Do not pass a mime type to GenerateSafeFileName so that it does not force
741 // the filename to have an extension if the (chrome) extension does not
742 // suggest it.
743 net::GenerateSafeFileName(std::string(), false, &temp_filename);
744
745 ContinueDeterminingFilename(continue_info, temp_filename, conflict_action);
746 }
747
748 void ChromeDownloadManagerDelegate::ContinueDeterminingFilename(
749 const ContinueFilenameDeterminationInfo& continue_info,
750 const base::FilePath& suggested_path,
751 DownloadPathReservationTracker::FilenameConflictAction conflict_action) {
752 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
753 int32 download_id = continue_info.download_id;
754 const content::DownloadTargetCallback& callback = continue_info.callback;
755 content::DownloadDangerType danger_type = continue_info.danger_type;
756 bool visited_referrer_before = continue_info.visited_referrer_before;
757 bool should_prompt = continue_info.should_prompt;
758 DownloadItem* download =
759 download_manager_->GetDownload(download_id);
760 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS))
761 return;
762
763 // If the download hasn't already been marked dangerous (could be
764 // DANGEROUS_URL), check if it is a dangerous file.
765 if (danger_type == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) {
766 if (!should_prompt &&
767 download->GetForcedFilePath().empty() &&
768 IsDangerousFile(*download, suggested_path, visited_referrer_before)) {
769 danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE;
770 }
771
772 #if defined(FULL_SAFE_BROWSING)
773 DownloadProtectionService* service = GetDownloadProtectionService();
774 // If this type of files is handled by the enhanced SafeBrowsing download
775 // protection, mark it as potentially dangerous content until we are done
776 // with scanning it.
777 if (service && service->enabled()) {
778 // TODO(noelutz): if the user changes the extension name in the UI to
779 // something like .exe SafeBrowsing will currently *not* check if the
780 // download is malicious.
781 if (service->IsSupportedDownload(*download, suggested_path))
782 danger_type = content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT;
783 }
784 #endif
785 } else {
786 // Currently we only expect this case.
787 DCHECK_EQ(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL, danger_type);
788 }
789
790 #if defined (OS_CHROMEOS)
791 drive::DriveDownloadHandler* drive_download_handler =
792 drive::DriveDownloadHandler::GetForProfile(profile_);
793 if (drive_download_handler) {
794 drive_download_handler->SubstituteDriveDownloadPath(
795 suggested_path, download,
796 base::Bind(
797 &ChromeDownloadManagerDelegate::SubstituteDriveDownloadPathCallback,
798 this, download->GetId(), callback, should_prompt, conflict_action,
799 danger_type));
800 return;
801 }
802 #endif
803 GetReservedPath(
804 *download, suggested_path, download_prefs_->DownloadPath(),
805 conflict_action,
806 base::Bind(&ChromeDownloadManagerDelegate::OnPathReservationAvailable,
807 this, download->GetId(), callback, should_prompt,
808 danger_type));
809 }
810
811 #if defined (OS_CHROMEOS)
812 // TODO(asanka): Merge this logic with the logic in DownloadFilePickerChromeOS.
813 void ChromeDownloadManagerDelegate::SubstituteDriveDownloadPathCallback(
814 int32 download_id,
815 const content::DownloadTargetCallback& callback,
816 bool should_prompt,
817 DownloadPathReservationTracker::FilenameConflictAction conflict_action,
818 content::DownloadDangerType danger_type,
819 const base::FilePath& suggested_path) {
820 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
821 DownloadItem* download =
822 download_manager_->GetDownload(download_id);
823 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS))
824 return;
825
826 if (suggested_path.empty()) {
827 // Substitution failed.
828 callback.Run(base::FilePath(),
829 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
830 danger_type,
831 base::FilePath());
832 return;
833 }
834
835 GetReservedPath(
836 *download, suggested_path, download_prefs_->DownloadPath(),
837 conflict_action,
838 base::Bind(&ChromeDownloadManagerDelegate::OnPathReservationAvailable,
839 this, download->GetId(), callback, should_prompt,
840 danger_type));
841 }
842 #endif
843
844 void ChromeDownloadManagerDelegate::OnPathReservationAvailable(
845 int32 download_id,
846 const content::DownloadTargetCallback& callback,
847 bool should_prompt,
848 content::DownloadDangerType danger_type,
849 const base::FilePath& reserved_path,
850 bool reserved_path_verified) {
851 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
852 DownloadItem* download =
853 download_manager_->GetDownload(download_id);
854 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS))
855 return;
856 if (should_prompt || !reserved_path_verified) {
857 // If the target path could not be verified then the path was non-existant,
858 // non writeable or could not be uniquified. Prompt the user.
859 ChooseDownloadPath(
860 download, reserved_path,
861 base::Bind(&ChromeDownloadManagerDelegate::OnTargetPathDetermined,
862 this, download_id, callback,
863 DownloadItem::TARGET_DISPOSITION_PROMPT, danger_type));
864 } else {
865 OnTargetPathDetermined(download_id, callback,
866 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
867 danger_type, reserved_path);
868 }
869 }
870
871 void ChromeDownloadManagerDelegate::OnTargetPathDetermined(
872 int32 download_id,
873 const content::DownloadTargetCallback& callback,
874 DownloadItem::TargetDisposition disposition,
875 content::DownloadDangerType danger_type,
876 const base::FilePath& target_path) {
877 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
878 base::FilePath intermediate_path;
879 DownloadItem* download =
880 download_manager_->GetDownload(download_id);
881 if (!download || (download->GetState() != DownloadItem::IN_PROGRESS))
882 return;
883
884 // If |target_path| is empty, then that means that the user wants to cancel
885 // the download.
886 if (!target_path.empty()) {
887 intermediate_path = GetIntermediatePath(
888 target_path, danger_type, !download->GetForcedFilePath().empty());
889
890 // Retain the last directory. Exclude temporary downloads since the path
891 // likely points at the location of a temporary file.
892 // TODO(asanka): This logic is a hack. DownloadFilePicker should give us a
893 // directory to persist. Or perhaps, if the Drive path
894 // substitution logic is moved here, then we would have a
895 // persistable path after the DownloadFilePicker is done.
896 if (disposition == DownloadItem::TARGET_DISPOSITION_PROMPT &&
897 !download->IsTemporary())
898 last_download_path_ = target_path.DirName();
899 }
900 callback.Run(target_path, disposition, danger_type, intermediate_path);
901 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698