OLD | NEW |
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/path_service.h" | 13 #include "base/path_service.h" |
14 #include "base/rand_util.h" | 14 #include "base/rand_util.h" |
15 #include "base/stringprintf.h" | 15 #include "base/stringprintf.h" |
16 #include "base/time.h" | 16 #include "base/time.h" |
17 #include "base/utf_string_conversions.h" | 17 #include "base/utf_string_conversions.h" |
18 #include "chrome/browser/browser_process.h" | 18 #include "chrome/browser/browser_process.h" |
| 19 #include "chrome/browser/download/download_completion_blocker.h" |
19 #include "chrome/browser/download/download_crx_util.h" | 20 #include "chrome/browser/download/download_crx_util.h" |
20 #include "chrome/browser/download/download_extensions.h" | 21 #include "chrome/browser/download/download_extensions.h" |
21 #include "chrome/browser/download/download_file_picker.h" | 22 #include "chrome/browser/download/download_file_picker.h" |
22 #include "chrome/browser/download/download_history.h" | 23 #include "chrome/browser/download/download_history.h" |
23 #include "chrome/browser/download/download_prefs.h" | 24 #include "chrome/browser/download/download_prefs.h" |
24 #include "chrome/browser/download/download_status_updater.h" | 25 #include "chrome/browser/download/download_status_updater.h" |
25 #include "chrome/browser/download/download_util.h" | 26 #include "chrome/browser/download/download_util.h" |
26 #include "chrome/browser/download/save_package_file_picker.h" | 27 #include "chrome/browser/download/save_package_file_picker.h" |
27 #include "chrome/browser/extensions/crx_installer.h" | 28 #include "chrome/browser/extensions/crx_installer.h" |
28 #include "chrome/browser/extensions/extension_service.h" | 29 #include "chrome/browser/extensions/extension_service.h" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 using content::WebContents; | 64 using content::WebContents; |
64 using safe_browsing::DownloadProtectionService; | 65 using safe_browsing::DownloadProtectionService; |
65 | 66 |
66 namespace { | 67 namespace { |
67 | 68 |
68 // String pointer used for identifying safebrowing data associated with | 69 // String pointer used for identifying safebrowing data associated with |
69 // a download item. | 70 // a download item. |
70 static const char safe_browsing_id[] = "Safe Browsing ID"; | 71 static const char safe_browsing_id[] = "Safe Browsing ID"; |
71 | 72 |
72 // The state of a safebrowsing check. | 73 // The state of a safebrowsing check. |
73 struct SafeBrowsingState : public DownloadItem::ExternalData { | 74 class SafeBrowsingState : public DownloadCompletionBlocker { |
74 // If true the SafeBrowsing check is not done yet. | 75 public: |
75 bool pending; | 76 SafeBrowsingState() |
76 // The verdict that we got from calling CheckClientDownload. | 77 : verdict_(DownloadProtectionService::SAFE) { |
77 safe_browsing::DownloadProtectionService::DownloadCheckResult verdict; | 78 } |
| 79 |
| 80 virtual ~SafeBrowsingState(); |
| 81 |
| 82 // The verdict that we got from calling CheckClientDownload. Only valid to |
| 83 // call if |is_complete()|. |
| 84 DownloadProtectionService::DownloadCheckResult verdict() const { |
| 85 return verdict_; |
| 86 } |
| 87 |
| 88 void SetVerdict(DownloadProtectionService::DownloadCheckResult result) { |
| 89 verdict_ = result; |
| 90 CompleteDownload(); |
| 91 } |
| 92 |
| 93 private: |
| 94 DownloadProtectionService::DownloadCheckResult verdict_; |
| 95 |
| 96 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingState); |
78 }; | 97 }; |
79 | 98 |
| 99 SafeBrowsingState::~SafeBrowsingState() {} |
| 100 |
80 } // namespace | 101 } // namespace |
81 | 102 |
82 ChromeDownloadManagerDelegate::ChromeDownloadManagerDelegate(Profile* profile) | 103 ChromeDownloadManagerDelegate::ChromeDownloadManagerDelegate(Profile* profile) |
83 : profile_(profile), | 104 : profile_(profile), |
84 next_download_id_(0), | 105 next_download_id_(0), |
85 download_prefs_(new DownloadPrefs(profile->GetPrefs())) { | 106 download_prefs_(new DownloadPrefs(profile->GetPrefs())) { |
86 } | 107 } |
87 | 108 |
88 ChromeDownloadManagerDelegate::~ChromeDownloadManagerDelegate() { | 109 ChromeDownloadManagerDelegate::~ChromeDownloadManagerDelegate() { |
89 } | 110 } |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 DCHECK(extension[0] == FilePath::kExtensionSeparator); | 217 DCHECK(extension[0] == FilePath::kExtensionSeparator); |
197 extension.erase(0, 1); | 218 extension.erase(0, 1); |
198 return download_prefs_->IsAutoOpenEnabledForExtension(extension); | 219 return download_prefs_->IsAutoOpenEnabledForExtension(extension); |
199 } | 220 } |
200 | 221 |
201 // static | 222 // static |
202 void ChromeDownloadManagerDelegate::DisableSafeBrowsing(DownloadItem* item) { | 223 void ChromeDownloadManagerDelegate::DisableSafeBrowsing(DownloadItem* item) { |
203 #if defined(ENABLE_SAFE_BROWSING) | 224 #if defined(ENABLE_SAFE_BROWSING) |
204 SafeBrowsingState* state = static_cast<SafeBrowsingState*>( | 225 SafeBrowsingState* state = static_cast<SafeBrowsingState*>( |
205 item->GetExternalData(&safe_browsing_id)); | 226 item->GetExternalData(&safe_browsing_id)); |
206 DCHECK(state == NULL); | 227 DCHECK(!state); |
207 if (state == NULL) { | 228 if (!state) |
208 state = new SafeBrowsingState(); | 229 state = new SafeBrowsingState(); |
209 item->SetExternalData(&safe_browsing_id, state); | 230 state->SetVerdict(DownloadProtectionService::SAFE); |
210 } | 231 item->SetExternalData(&safe_browsing_id, state); |
211 state->pending = false; | |
212 state->verdict = DownloadProtectionService::SAFE; | |
213 #endif | 232 #endif |
214 } | 233 } |
215 | 234 |
216 bool ChromeDownloadManagerDelegate::ShouldCompleteDownload(DownloadItem* item) { | 235 bool ChromeDownloadManagerDelegate::IsDownloadReadyForCompletion( |
| 236 DownloadItem* item, |
| 237 const base::Closure& internal_complete_callback) { |
217 #if defined(ENABLE_SAFE_BROWSING) | 238 #if defined(ENABLE_SAFE_BROWSING) |
218 // See if there is already a pending SafeBrowsing check for that download. | |
219 SafeBrowsingState* state = static_cast<SafeBrowsingState*>( | 239 SafeBrowsingState* state = static_cast<SafeBrowsingState*>( |
220 item->GetExternalData(&safe_browsing_id)); | 240 item->GetExternalData(&safe_browsing_id)); |
221 // Don't complete the download until we have an answer. | 241 if (!state) { |
222 if (state && state->pending) | |
223 return false; | |
224 | |
225 if (state == NULL) { | |
226 // Begin the safe browsing download protection check. | 242 // Begin the safe browsing download protection check. |
227 DownloadProtectionService* service = GetDownloadProtectionService(); | 243 DownloadProtectionService* service = GetDownloadProtectionService(); |
228 if (service) { | 244 if (service) { |
229 VLOG(2) << __FUNCTION__ << "() Start SB download check for download = " | 245 VLOG(2) << __FUNCTION__ << "() Start SB download check for download = " |
230 << item->DebugString(false); | 246 << item->DebugString(false); |
231 state = new SafeBrowsingState(); | 247 state = new SafeBrowsingState(); |
232 state->pending = true; | 248 state->set_callback(internal_complete_callback); |
233 state->verdict = DownloadProtectionService::SAFE; | |
234 item->SetExternalData(&safe_browsing_id, state); | 249 item->SetExternalData(&safe_browsing_id, state); |
235 service->CheckClientDownload( | 250 service->CheckClientDownload( |
236 DownloadProtectionService::DownloadInfo::FromDownloadItem(*item), | 251 DownloadProtectionService::DownloadInfo::FromDownloadItem(*item), |
237 base::Bind( | 252 base::Bind( |
238 &ChromeDownloadManagerDelegate::CheckClientDownloadDone, | 253 &ChromeDownloadManagerDelegate::CheckClientDownloadDone, |
239 this, | 254 this, |
240 item->GetId())); | 255 item->GetId())); |
241 return false; | 256 return false; |
242 } | 257 } |
| 258 } else if (!state->is_complete()) { |
| 259 // Don't complete the download until we have an answer. |
| 260 state->set_callback(internal_complete_callback); |
| 261 return false; |
243 } | 262 } |
244 #endif | 263 #endif |
245 | 264 |
246 #if defined(OS_CHROMEOS) | 265 #if defined(OS_CHROMEOS) |
247 // If there's a GData upload associated with this download, we wait until that | 266 // If there's a GData upload associated with this download, we wait until that |
248 // is complete before allowing the download item to complete. | 267 // is complete before allowing the download item to complete. |
249 if (!gdata::GDataDownloadObserver::IsReadyToComplete(item)) | 268 if (!gdata::GDataDownloadObserver::IsReadyToComplete( |
| 269 item, internal_complete_callback)) |
250 return false; | 270 return false; |
251 #endif | 271 #endif |
252 return true; | 272 return true; |
253 } | 273 } |
254 | 274 |
| 275 // ShouldCompleteDownloadInternal() will never be called directly by a user, it |
| 276 // will only be called asynchronously, so it should run |
| 277 // |user_complete_callback|. ShouldCompleteDownload() will only be called |
| 278 // directly by a user, so it does not need to run |user_complete_callback| |
| 279 // because it can return true synchronously. The two methods look very similar, |
| 280 // but their semantics are very different. |
| 281 |
| 282 void ChromeDownloadManagerDelegate::ShouldCompleteDownloadInternal( |
| 283 int download_id, |
| 284 const base::Closure& user_complete_callback) { |
| 285 DownloadItem* item = download_manager_->GetActiveDownloadItem(download_id); |
| 286 if (!item) |
| 287 return; |
| 288 if (IsDownloadReadyForCompletion(item, base::Bind( |
| 289 &ChromeDownloadManagerDelegate::ShouldCompleteDownloadInternal, this, |
| 290 download_id, user_complete_callback))) |
| 291 user_complete_callback.Run(); |
| 292 } |
| 293 |
| 294 bool ChromeDownloadManagerDelegate::ShouldCompleteDownload( |
| 295 DownloadItem* item, |
| 296 const base::Closure& user_complete_callback) { |
| 297 return IsDownloadReadyForCompletion(item, base::Bind( |
| 298 &ChromeDownloadManagerDelegate::ShouldCompleteDownloadInternal, this, |
| 299 item->GetId(), user_complete_callback)); |
| 300 } |
| 301 |
255 bool ChromeDownloadManagerDelegate::ShouldOpenDownload(DownloadItem* item) { | 302 bool ChromeDownloadManagerDelegate::ShouldOpenDownload(DownloadItem* item) { |
256 if (IsExtensionDownload(item)) { | 303 if (IsExtensionDownload(item)) { |
257 // We can open extensions if either they came from the store, or | 304 // We can open extensions if either they came from the store, or |
258 // off-store-install is enabled. | 305 // off-store-install is enabled. |
259 if (extensions::switch_utils::IsOffStoreInstallEnabled() || | 306 if (extensions::switch_utils::IsOffStoreInstallEnabled() || |
260 WebstoreInstaller::GetAssociatedApproval(*item)) { | 307 WebstoreInstaller::GetAssociatedApproval(*item)) { |
261 scoped_refptr<CrxInstaller> crx_installer = | 308 scoped_refptr<CrxInstaller> crx_installer = |
262 download_crx_util::OpenChromeExtension(profile_, *item); | 309 download_crx_util::OpenChromeExtension(profile_, *item); |
263 | 310 |
264 // CRX_INSTALLER_DONE will fire when the install completes. Observe() | 311 // CRX_INSTALLER_DONE will fire when the install completes. Observe() |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
466 item->SetDangerType(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT); | 513 item->SetDangerType(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT); |
467 break; | 514 break; |
468 case DownloadProtectionService::UNCOMMON: | 515 case DownloadProtectionService::UNCOMMON: |
469 item->SetDangerType(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT); | 516 item->SetDangerType(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT); |
470 break; | 517 break; |
471 } | 518 } |
472 } | 519 } |
473 | 520 |
474 SafeBrowsingState* state = static_cast<SafeBrowsingState*>( | 521 SafeBrowsingState* state = static_cast<SafeBrowsingState*>( |
475 item->GetExternalData(&safe_browsing_id)); | 522 item->GetExternalData(&safe_browsing_id)); |
476 DCHECK(state); | 523 state->SetVerdict(result); |
477 if (state) { | |
478 state->pending = false; | |
479 state->verdict = result; | |
480 } | |
481 item->MaybeCompleteDownload(); | |
482 } | 524 } |
483 | 525 |
484 // content::NotificationObserver implementation. | 526 // content::NotificationObserver implementation. |
485 void ChromeDownloadManagerDelegate::Observe( | 527 void ChromeDownloadManagerDelegate::Observe( |
486 int type, | 528 int type, |
487 const content::NotificationSource& source, | 529 const content::NotificationSource& source, |
488 const content::NotificationDetails& details) { | 530 const content::NotificationDetails& details) { |
489 DCHECK(type == chrome::NOTIFICATION_CRX_INSTALLER_DONE); | 531 DCHECK(type == chrome::NOTIFICATION_CRX_INSTALLER_DONE); |
490 | 532 |
491 registrar_.Remove(this, | 533 registrar_.Remove(this, |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
727 int32 download_id, int64 db_handle) { | 769 int32 download_id, int64 db_handle) { |
728 // It's not immediately obvious, but HistoryBackend::CreateDownload() can | 770 // It's not immediately obvious, but HistoryBackend::CreateDownload() can |
729 // call this function with an invalid |db_handle|. For instance, this can | 771 // call this function with an invalid |db_handle|. For instance, this can |
730 // happen when the history database is offline. We cannot have multiple | 772 // happen when the history database is offline. We cannot have multiple |
731 // DownloadItems with the same invalid db_handle, so we need to assign a | 773 // DownloadItems with the same invalid db_handle, so we need to assign a |
732 // unique |db_handle| here. | 774 // unique |db_handle| here. |
733 if (db_handle == DownloadItem::kUninitializedHandle) | 775 if (db_handle == DownloadItem::kUninitializedHandle) |
734 db_handle = download_history_->GetNextFakeDbHandle(); | 776 db_handle = download_history_->GetNextFakeDbHandle(); |
735 download_manager_->OnItemAddedToPersistentStore(download_id, db_handle); | 777 download_manager_->OnItemAddedToPersistentStore(download_id, db_handle); |
736 } | 778 } |
OLD | NEW |