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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
62 using content::WebContents; | 63 using content::WebContents; |
63 using safe_browsing::DownloadProtectionService; | 64 using safe_browsing::DownloadProtectionService; |
64 | 65 |
65 namespace { | 66 namespace { |
66 | 67 |
67 // String pointer used for identifying safebrowing data associated with | 68 // String pointer used for identifying safebrowing data associated with |
68 // a download item. | 69 // a download item. |
69 static const char safe_browsing_id[] = "Safe Browsing ID"; | 70 static const char safe_browsing_id[] = "Safe Browsing ID"; |
70 | 71 |
71 // The state of a safebrowsing check. | 72 // The state of a safebrowsing check. |
72 struct SafeBrowsingState : public DownloadItem::ExternalData { | 73 class SafeBrowsingState : public DownloadCompletionBlocker { |
73 // If true the SafeBrowsing check is not done yet. | 74 public: |
74 bool pending; | 75 SafeBrowsingState() |
75 // The verdict that we got from calling CheckClientDownload. | 76 : verdict_(DownloadProtectionService::SAFE) { |
76 safe_browsing::DownloadProtectionService::DownloadCheckResult verdict; | 77 } |
78 | |
79 virtual ~SafeBrowsingState(); | |
80 | |
81 // The verdict that we got from calling CheckClientDownload. Only valid to | |
82 // call if |is_complete()|. | |
83 DownloadProtectionService::DownloadCheckResult verdict() const { | |
84 return verdict_; | |
85 } | |
86 | |
87 void SetVerdict(DownloadProtectionService::DownloadCheckResult result) { | |
88 verdict_ = result; | |
89 CompleteDownload(); | |
90 } | |
91 | |
92 private: | |
93 DownloadProtectionService::DownloadCheckResult verdict_; | |
94 | |
95 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingState); | |
77 }; | 96 }; |
78 | 97 |
98 SafeBrowsingState::~SafeBrowsingState() {} | |
99 | |
79 } // namespace | 100 } // namespace |
80 | 101 |
81 ChromeDownloadManagerDelegate::ChromeDownloadManagerDelegate(Profile* profile) | 102 ChromeDownloadManagerDelegate::ChromeDownloadManagerDelegate(Profile* profile) |
82 : profile_(profile), | 103 : profile_(profile), |
83 next_download_id_(0), | 104 next_download_id_(0), |
84 download_prefs_(new DownloadPrefs(profile->GetPrefs())) { | 105 download_prefs_(new DownloadPrefs(profile->GetPrefs())) { |
85 } | 106 } |
86 | 107 |
87 ChromeDownloadManagerDelegate::~ChromeDownloadManagerDelegate() { | 108 ChromeDownloadManagerDelegate::~ChromeDownloadManagerDelegate() { |
88 } | 109 } |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
195 DCHECK(extension[0] == FilePath::kExtensionSeparator); | 216 DCHECK(extension[0] == FilePath::kExtensionSeparator); |
196 extension.erase(0, 1); | 217 extension.erase(0, 1); |
197 return download_prefs_->IsAutoOpenEnabledForExtension(extension); | 218 return download_prefs_->IsAutoOpenEnabledForExtension(extension); |
198 } | 219 } |
199 | 220 |
200 // static | 221 // static |
201 void ChromeDownloadManagerDelegate::DisableSafeBrowsing(DownloadItem* item) { | 222 void ChromeDownloadManagerDelegate::DisableSafeBrowsing(DownloadItem* item) { |
202 #if defined(ENABLE_SAFE_BROWSING) | 223 #if defined(ENABLE_SAFE_BROWSING) |
203 SafeBrowsingState* state = static_cast<SafeBrowsingState*>( | 224 SafeBrowsingState* state = static_cast<SafeBrowsingState*>( |
204 item->GetExternalData(&safe_browsing_id)); | 225 item->GetExternalData(&safe_browsing_id)); |
205 DCHECK(state == NULL); | 226 DCHECK(!state); |
206 if (state == NULL) { | 227 if (!state) |
207 state = new SafeBrowsingState(); | 228 state = new SafeBrowsingState(); |
208 item->SetExternalData(&safe_browsing_id, state); | 229 state->SetVerdict(DownloadProtectionService::SAFE); |
209 } | 230 item->SetExternalData(&safe_browsing_id, state); |
210 state->pending = false; | |
211 state->verdict = DownloadProtectionService::SAFE; | |
212 #endif | 231 #endif |
213 } | 232 } |
214 | 233 |
215 bool ChromeDownloadManagerDelegate::ShouldCompleteDownload(DownloadItem* item) { | 234 bool ChromeDownloadManagerDelegate::IsDownloadReadyForCompletion( |
235 DownloadItem* item, | |
236 const base::Closure& internal_complete_callback) { | |
216 #if defined(ENABLE_SAFE_BROWSING) | 237 #if defined(ENABLE_SAFE_BROWSING) |
217 // See if there is already a pending SafeBrowsing check for that download. | |
218 SafeBrowsingState* state = static_cast<SafeBrowsingState*>( | 238 SafeBrowsingState* state = static_cast<SafeBrowsingState*>( |
219 item->GetExternalData(&safe_browsing_id)); | 239 item->GetExternalData(&safe_browsing_id)); |
220 // Don't complete the download until we have an answer. | 240 if (!state) { |
221 if (state && state->pending) | |
222 return false; | |
223 | |
224 if (state == NULL) { | |
225 // Begin the safe browsing download protection check. | 241 // Begin the safe browsing download protection check. |
226 DownloadProtectionService* service = GetDownloadProtectionService(); | 242 DownloadProtectionService* service = GetDownloadProtectionService(); |
227 if (service) { | 243 if (service) { |
228 VLOG(2) << __FUNCTION__ << "() Start SB download check for download = " | 244 VLOG(2) << __FUNCTION__ << "() Start SB download check for download = " |
229 << item->DebugString(false); | 245 << item->DebugString(false); |
230 state = new SafeBrowsingState(); | 246 state = new SafeBrowsingState(); |
231 state->pending = true; | 247 state->set_callback(internal_complete_callback); |
232 state->verdict = DownloadProtectionService::SAFE; | |
233 item->SetExternalData(&safe_browsing_id, state); | 248 item->SetExternalData(&safe_browsing_id, state); |
234 service->CheckClientDownload( | 249 service->CheckClientDownload( |
235 DownloadProtectionService::DownloadInfo::FromDownloadItem(*item), | 250 DownloadProtectionService::DownloadInfo::FromDownloadItem(*item), |
236 base::Bind( | 251 base::Bind( |
237 &ChromeDownloadManagerDelegate::CheckClientDownloadDone, | 252 &ChromeDownloadManagerDelegate::CheckClientDownloadDone, |
238 this, | 253 this, |
239 item->GetId())); | 254 item->GetId())); |
240 return false; | 255 return false; |
241 } | 256 } |
257 } else if (!state->is_complete()) { | |
258 // Don't complete the download until we have an answer. | |
259 state->set_callback(internal_complete_callback); | |
260 return false; | |
242 } | 261 } |
243 #endif | 262 #endif |
244 | 263 |
245 #if defined(OS_CHROMEOS) | 264 #if defined(OS_CHROMEOS) |
246 // If there's a GData upload associated with this download, we wait until that | 265 // If there's a GData upload associated with this download, we wait until that |
247 // is complete before allowing the download item to complete. | 266 // is complete before allowing the download item to complete. |
248 if (!gdata::GDataDownloadObserver::IsReadyToComplete(item)) | 267 if (!gdata::GDataDownloadObserver::IsReadyToComplete( |
268 item, internal_complete_callback)) | |
249 return false; | 269 return false; |
250 #endif | 270 #endif |
251 return true; | 271 return true; |
252 } | 272 } |
253 | 273 |
274 void ChromeDownloadManagerDelegate::ShouldCompleteDownloadInternal( | |
275 DownloadItem* item, | |
276 const base::Closure& user_complete_callback) { | |
277 if (IsDownloadReadyForCompletion(item, base::Bind( | |
278 &ChromeDownloadManagerDelegate::ShouldCompleteDownloadInternal, this, | |
279 item, user_complete_callback))) | |
asanka
2012/05/16 19:26:32
Is the DownloadItem* guaranteed to outlive the cal
benjhayden
2012/05/16 19:42:30
Good catch!
How're those weak pointers coming? :-)
| |
280 user_complete_callback.Run(); | |
281 } | |
282 | |
283 // ShouldCompleteDownloadInternal() will never be called directly by a user, it | |
284 // will only be called asynchronously, so it should run | |
285 // |user_complete_callback|. ShouldCompleteDownload() will only be called | |
286 // directly by a user, so it does not need to run |user_complete_callback| | |
287 // because it can return true synchronously. | |
Randy Smith (Not in Mondays)
2012/05/16 19:04:53
nit: Shouldn't this comment be in front of ShouldC
benjhayden
2012/05/16 19:42:30
Done.
| |
288 | |
289 bool ChromeDownloadManagerDelegate::ShouldCompleteDownload( | |
290 DownloadItem* item, | |
291 const base::Closure& user_complete_callback) { | |
292 return IsDownloadReadyForCompletion(item, base::Bind( | |
293 &ChromeDownloadManagerDelegate::ShouldCompleteDownloadInternal, this, | |
294 item, user_complete_callback)); | |
295 } | |
296 | |
254 bool ChromeDownloadManagerDelegate::ShouldOpenDownload(DownloadItem* item) { | 297 bool ChromeDownloadManagerDelegate::ShouldOpenDownload(DownloadItem* item) { |
255 if (IsExtensionDownload(item)) { | 298 if (IsExtensionDownload(item)) { |
256 scoped_refptr<CrxInstaller> crx_installer = | 299 scoped_refptr<CrxInstaller> crx_installer = |
257 download_crx_util::OpenChromeExtension(profile_, *item); | 300 download_crx_util::OpenChromeExtension(profile_, *item); |
258 | 301 |
259 // CRX_INSTALLER_DONE will fire when the install completes. Observe() | 302 // CRX_INSTALLER_DONE will fire when the install completes. Observe() |
260 // will call DelayedDownloadOpened() on this item. If this DownloadItem is | 303 // will call DelayedDownloadOpened() on this item. If this DownloadItem is |
261 // not around when CRX_INSTALLER_DONE fires, Complete() will not be called. | 304 // not around when CRX_INSTALLER_DONE fires, Complete() will not be called. |
262 registrar_.Add(this, | 305 registrar_.Add(this, |
263 chrome::NOTIFICATION_CRX_INSTALLER_DONE, | 306 chrome::NOTIFICATION_CRX_INSTALLER_DONE, |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
459 item->SetDangerType(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT); | 502 item->SetDangerType(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT); |
460 break; | 503 break; |
461 case DownloadProtectionService::UNCOMMON: | 504 case DownloadProtectionService::UNCOMMON: |
462 item->SetDangerType(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT); | 505 item->SetDangerType(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT); |
463 break; | 506 break; |
464 } | 507 } |
465 } | 508 } |
466 | 509 |
467 SafeBrowsingState* state = static_cast<SafeBrowsingState*>( | 510 SafeBrowsingState* state = static_cast<SafeBrowsingState*>( |
468 item->GetExternalData(&safe_browsing_id)); | 511 item->GetExternalData(&safe_browsing_id)); |
469 DCHECK(state); | 512 state->SetVerdict(result); |
470 if (state) { | |
471 state->pending = false; | |
472 state->verdict = result; | |
473 } | |
474 item->MaybeCompleteDownload(); | |
475 } | 513 } |
476 | 514 |
477 // content::NotificationObserver implementation. | 515 // content::NotificationObserver implementation. |
478 void ChromeDownloadManagerDelegate::Observe( | 516 void ChromeDownloadManagerDelegate::Observe( |
479 int type, | 517 int type, |
480 const content::NotificationSource& source, | 518 const content::NotificationSource& source, |
481 const content::NotificationDetails& details) { | 519 const content::NotificationDetails& details) { |
482 DCHECK(type == chrome::NOTIFICATION_CRX_INSTALLER_DONE); | 520 DCHECK(type == chrome::NOTIFICATION_CRX_INSTALLER_DONE); |
483 | 521 |
484 registrar_.Remove(this, | 522 registrar_.Remove(this, |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
719 int32 download_id, int64 db_handle) { | 757 int32 download_id, int64 db_handle) { |
720 // It's not immediately obvious, but HistoryBackend::CreateDownload() can | 758 // It's not immediately obvious, but HistoryBackend::CreateDownload() can |
721 // call this function with an invalid |db_handle|. For instance, this can | 759 // call this function with an invalid |db_handle|. For instance, this can |
722 // happen when the history database is offline. We cannot have multiple | 760 // happen when the history database is offline. We cannot have multiple |
723 // DownloadItems with the same invalid db_handle, so we need to assign a | 761 // DownloadItems with the same invalid db_handle, so we need to assign a |
724 // unique |db_handle| here. | 762 // unique |db_handle| here. |
725 if (db_handle == DownloadItem::kUninitializedHandle) | 763 if (db_handle == DownloadItem::kUninitializedHandle) |
726 db_handle = download_history_->GetNextFakeDbHandle(); | 764 db_handle = download_history_->GetNextFakeDbHandle(); |
727 download_manager_->OnItemAddedToPersistentStore(download_id, db_handle); | 765 download_manager_->OnItemAddedToPersistentStore(download_id, db_handle); |
728 } | 766 } |
OLD | NEW |