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

Side by Side Diff: content/browser/download/download_item_impl.cc

Issue 10912173: Replace the DownloadFileManager with direct ownership of DownloadFileImpl (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Sync to LKGR (r156083) Created 8 years, 3 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 // File method ordering: Methods in this file are in the same order 5 // File method ordering: Methods in this file are in the same order
6 // as in download_item_impl.h, with the following exception: The public 6 // as in download_item_impl.h, with the following exception: The public
7 // interfaces DelayedDownloadOpened, OnDownloadTargetDetermined, and 7 // interfaces Start, DelayedDownloadOpened, OnDownloadTargetDetermined, and
8 // OnDownloadCompleting are placed in chronological order with the other 8 // OnDownloadCompleting are placed in chronological order with the other
9 // (private) routines that together define a DownloadItem's state transitions 9 // (private) routines that together define a DownloadItem's state transitions
10 // as the download progresses. See "Download progression cascade" later in 10 // as the download progresses. See "Download progression cascade" later in
11 // this file. 11 // this file.
12 12
13 // A regular DownloadItem (created for a download in this session of the 13 // A regular DownloadItem (created for a download in this session of the
14 // browser) normally goes through the following states: 14 // browser) normally goes through the following states:
15 // * Created (when download starts) 15 // * Created (when download starts)
16 // * Destination filename determined 16 // * Destination filename determined
17 // * Entered into the history database. 17 // * Entered into the history database.
(...skipping 14 matching lines...) Expand all
32 #include "base/format_macros.h" 32 #include "base/format_macros.h"
33 #include "base/i18n/case_conversion.h" 33 #include "base/i18n/case_conversion.h"
34 #include "base/i18n/string_search.h" 34 #include "base/i18n/string_search.h"
35 #include "base/logging.h" 35 #include "base/logging.h"
36 #include "base/metrics/histogram.h" 36 #include "base/metrics/histogram.h"
37 #include "base/stl_util.h" 37 #include "base/stl_util.h"
38 #include "base/stringprintf.h" 38 #include "base/stringprintf.h"
39 #include "base/utf_string_conversions.h" 39 #include "base/utf_string_conversions.h"
40 #include "content/browser/download/download_create_info.h" 40 #include "content/browser/download/download_create_info.h"
41 #include "content/browser/download/download_file.h" 41 #include "content/browser/download/download_file.h"
42 #include "content/browser/download/download_file_manager.h"
43 #include "content/browser/download/download_interrupt_reasons_impl.h" 42 #include "content/browser/download/download_interrupt_reasons_impl.h"
44 #include "content/browser/download/download_item_impl_delegate.h" 43 #include "content/browser/download/download_item_impl_delegate.h"
45 #include "content/browser/download/download_request_handle.h" 44 #include "content/browser/download/download_request_handle.h"
46 #include "content/browser/download/download_stats.h" 45 #include "content/browser/download/download_stats.h"
47 #include "content/browser/web_contents/web_contents_impl.h" 46 #include "content/browser/web_contents/web_contents_impl.h"
48 #include "content/public/browser/browser_thread.h" 47 #include "content/public/browser/browser_thread.h"
49 #include "content/public/browser/content_browser_client.h" 48 #include "content/public/browser/content_browser_client.h"
50 #include "content/public/browser/download_persistent_store_info.h" 49 #include "content/public/browser/download_persistent_store_info.h"
51 #include "net/base/net_util.h" 50 #include "net/base/net_util.h"
52 51
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 return NULL; 114 return NULL;
116 } 115 }
117 virtual void PauseRequest() const OVERRIDE {} 116 virtual void PauseRequest() const OVERRIDE {}
118 virtual void ResumeRequest() const OVERRIDE {} 117 virtual void ResumeRequest() const OVERRIDE {}
119 virtual void CancelRequest() const OVERRIDE {} 118 virtual void CancelRequest() const OVERRIDE {}
120 virtual std::string DebugString() const OVERRIDE { 119 virtual std::string DebugString() const OVERRIDE {
121 return "Null DownloadRequestHandle"; 120 return "Null DownloadRequestHandle";
122 } 121 }
123 }; 122 };
124 123
124 // Wrapper around DownloadFile::Detach and DownloadFile::Cancel that
125 // takes ownership of the DownloadFile and hence implicitly destroys it
126 // at the end of the function.
127 static void DownloadFileDetach(
128 scoped_ptr<DownloadFile> download_file, base::Closure callback) {
129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
130 download_file->Detach(callback);
131 }
132
133 static void DownloadFileCancel(scoped_ptr<DownloadFile> download_file) {
134 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
135 download_file->Cancel();
136 }
137
125 } // namespace 138 } // namespace
126 139
127 namespace content { 140 namespace content {
128 141
129 // Our download table ID starts at 1, so we use 0 to represent a download that 142 // Our download table ID starts at 1, so we use 0 to represent a download that
130 // has started, but has not yet had its data persisted in the table. We use fake 143 // has started, but has not yet had its data persisted in the table. We use fake
131 // database handles in incognito mode starting at -1 and progressively getting 144 // database handles in incognito mode starting at -1 and progressively getting
132 // more negative. 145 // more negative.
133 // static 146 // static
134 const int DownloadItem::kUninitializedHandle = 0; 147 const int DownloadItem::kUninitializedHandle = 0;
135 148
136 const char DownloadItem::kEmptyFileHash[] = ""; 149 const char DownloadItem::kEmptyFileHash[] = "";
137 150
138 } 151 }
139 152
140 // Our download table ID starts at 1, so we use 0 to represent a download that 153 // Our download table ID starts at 1, so we use 0 to represent a download that
141 // has started, but has not yet had its data persisted in the table. We use fake 154 // has started, but has not yet had its data persisted in the table. We use fake
142 // database handles in incognito mode starting at -1 and progressively getting 155 // database handles in incognito mode starting at -1 and progressively getting
143 // more negative. 156 // more negative.
144 157
145 // Constructor for reading from the history service. 158 // Constructor for reading from the history service.
146 DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate, 159 DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate,
147 DownloadId download_id, 160 DownloadId download_id,
148 const DownloadPersistentStoreInfo& info, 161 const DownloadPersistentStoreInfo& info,
149 const net::BoundNetLog& bound_net_log) 162 const net::BoundNetLog& bound_net_log)
150 : download_id_(download_id), 163 : is_save_package_download_(false),
164 download_id_(download_id),
151 current_path_(info.path), 165 current_path_(info.path),
152 target_path_(info.path), 166 target_path_(info.path),
153 target_disposition_(TARGET_DISPOSITION_OVERWRITE), 167 target_disposition_(TARGET_DISPOSITION_OVERWRITE),
154 url_chain_(1, info.url), 168 url_chain_(1, info.url),
155 referrer_url_(info.referrer_url), 169 referrer_url_(info.referrer_url),
156 transition_type_(content::PAGE_TRANSITION_LINK), 170 transition_type_(content::PAGE_TRANSITION_LINK),
157 has_user_gesture_(false), 171 has_user_gesture_(false),
158 total_bytes_(info.total_bytes), 172 total_bytes_(info.total_bytes),
159 received_bytes_(info.received_bytes), 173 received_bytes_(info.received_bytes),
160 bytes_per_sec_(0), 174 bytes_per_sec_(0),
(...skipping 26 matching lines...) Expand all
187 Init(false /* not actively downloading */, 201 Init(false /* not actively downloading */,
188 download_net_logs::SRC_HISTORY_IMPORT); 202 download_net_logs::SRC_HISTORY_IMPORT);
189 } 203 }
190 204
191 // Constructing for a regular download: 205 // Constructing for a regular download:
192 DownloadItemImpl::DownloadItemImpl( 206 DownloadItemImpl::DownloadItemImpl(
193 DownloadItemImplDelegate* delegate, 207 DownloadItemImplDelegate* delegate,
194 const DownloadCreateInfo& info, 208 const DownloadCreateInfo& info,
195 scoped_ptr<DownloadRequestHandleInterface> request_handle, 209 scoped_ptr<DownloadRequestHandleInterface> request_handle,
196 const net::BoundNetLog& bound_net_log) 210 const net::BoundNetLog& bound_net_log)
197 : request_handle_(request_handle.Pass()), 211 : is_save_package_download_(false),
212 request_handle_(request_handle.Pass()),
198 download_id_(info.download_id), 213 download_id_(info.download_id),
199 target_disposition_( 214 target_disposition_(
200 (info.prompt_user_for_save_location) ? 215 (info.prompt_user_for_save_location) ?
201 TARGET_DISPOSITION_PROMPT : TARGET_DISPOSITION_OVERWRITE), 216 TARGET_DISPOSITION_PROMPT : TARGET_DISPOSITION_OVERWRITE),
202 url_chain_(info.url_chain), 217 url_chain_(info.url_chain),
203 referrer_url_(info.referrer_url), 218 referrer_url_(info.referrer_url),
204 suggested_filename_(UTF16ToUTF8(info.save_info.suggested_name)), 219 suggested_filename_(UTF16ToUTF8(info.save_info.suggested_name)),
205 forced_file_path_(info.save_info.file_path), 220 forced_file_path_(info.save_info.file_path),
206 transition_type_(info.transition_type), 221 transition_type_(info.transition_type),
207 has_user_gesture_(info.has_user_gesture), 222 has_user_gesture_(info.has_user_gesture),
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 bound_net_log_.source().ToEventParametersCallback()); 262 bound_net_log_.source().ToEventParametersCallback());
248 } 263 }
249 264
250 // Constructing for the "Save Page As..." feature: 265 // Constructing for the "Save Page As..." feature:
251 DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate, 266 DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate,
252 const FilePath& path, 267 const FilePath& path,
253 const GURL& url, 268 const GURL& url,
254 DownloadId download_id, 269 DownloadId download_id,
255 const std::string& mime_type, 270 const std::string& mime_type,
256 const net::BoundNetLog& bound_net_log) 271 const net::BoundNetLog& bound_net_log)
257 : request_handle_(new NullDownloadRequestHandle()), 272 : is_save_package_download_(true),
273 request_handle_(new NullDownloadRequestHandle()),
258 download_id_(download_id), 274 download_id_(download_id),
259 current_path_(path), 275 current_path_(path),
260 target_path_(path), 276 target_path_(path),
261 target_disposition_(TARGET_DISPOSITION_OVERWRITE), 277 target_disposition_(TARGET_DISPOSITION_OVERWRITE),
262 url_chain_(1, url), 278 url_chain_(1, url),
263 referrer_url_(GURL()), 279 referrer_url_(GURL()),
264 transition_type_(content::PAGE_TRANSITION_LINK), 280 transition_type_(content::PAGE_TRANSITION_LINK),
265 has_user_gesture_(false), 281 has_user_gesture_(false),
266 mime_type_(mime_type), 282 mime_type_(mime_type),
267 original_mime_type_(mime_type), 283 original_mime_type_(mime_type),
(...skipping 20 matching lines...) Expand all
288 delegate_delayed_complete_(false), 304 delegate_delayed_complete_(false),
289 bound_net_log_(bound_net_log), 305 bound_net_log_(bound_net_log),
290 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { 306 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
291 delegate_->Attach(); 307 delegate_->Attach();
292 Init(true /* actively downloading */, 308 Init(true /* actively downloading */,
293 download_net_logs::SRC_SAVE_PAGE_AS); 309 download_net_logs::SRC_SAVE_PAGE_AS);
294 } 310 }
295 311
296 DownloadItemImpl::~DownloadItemImpl() { 312 DownloadItemImpl::~DownloadItemImpl() {
297 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 313 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
314
315 // Should always have been nuked before now, at worst in
316 // DownloadManager shutdown.
317 DCHECK(!download_file_.get());
318
298 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadDestroyed(this)); 319 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadDestroyed(this));
299 delegate_->AssertStateConsistent(this); 320 delegate_->AssertStateConsistent(this);
300 delegate_->Detach(); 321 delegate_->Detach();
301 } 322 }
302 323
303 void DownloadItemImpl::AddObserver(Observer* observer) { 324 void DownloadItemImpl::AddObserver(Observer* observer) {
304 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 325 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
305 326
306 observers_.AddObserver(observer); 327 observers_.AddObserver(observer);
307 } 328 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
360 VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true); 381 VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
361 if (!IsPartialDownload()) { 382 if (!IsPartialDownload()) {
362 // Small downloads might be complete before this method has 383 // Small downloads might be complete before this method has
363 // a chance to run. 384 // a chance to run.
364 return; 385 return;
365 } 386 }
366 387
367 download_stats::RecordDownloadCount(download_stats::CANCELLED_COUNT); 388 download_stats::RecordDownloadCount(download_stats::CANCELLED_COUNT);
368 389
369 TransitionTo(CANCELLED); 390 TransitionTo(CANCELLED);
391
392 // Cancel and remove the download file.
393 // TODO(rdsmith/benjhayden): Remove condition as part of
394 // SavePackage integration.
395 if (!is_save_package_download_) {
396 CHECK(download_file_.get());
397 BrowserThread::PostTask(
398 BrowserThread::FILE, FROM_HERE,
399 // Will be deleted at end of task execution.
400 base::Bind(&DownloadFileCancel, base::Passed(download_file_.Pass())));
401 }
402
403 // Cancel the originating URL request.
404 request_handle_->CancelRequest();
405
370 if (user_cancel) 406 if (user_cancel)
371 delegate_->DownloadStopped(this); 407 delegate_->DownloadStopped(this);
372 } 408 }
373 409
374 void DownloadItemImpl::Delete(DeleteReason reason) { 410 void DownloadItemImpl::Delete(DeleteReason reason) {
375 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 411 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
376 412
377 switch (reason) { 413 switch (reason) {
378 case DELETE_DUE_TO_USER_DISCARD: 414 case DELETE_DUE_TO_USER_DISCARD:
379 UMA_HISTOGRAM_ENUMERATION( 415 UMA_HISTOGRAM_ENUMERATION(
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after
810 " db_handle = %" PRId64 846 " db_handle = %" PRId64
811 " total = %" PRId64 847 " total = %" PRId64
812 " received = %" PRId64 848 " received = %" PRId64
813 " reason = %s" 849 " reason = %s"
814 " paused = %c" 850 " paused = %c"
815 " safety = %s" 851 " safety = %s"
816 " last_modified = '%s'" 852 " last_modified = '%s'"
817 " etag = '%s'" 853 " etag = '%s'"
818 " url_chain = \n\t\"%s\"\n\t" 854 " url_chain = \n\t\"%s\"\n\t"
819 " full_path = \"%" PRFilePath "\"" 855 " full_path = \"%" PRFilePath "\""
820 " target_path = \"%" PRFilePath "\"", 856 " target_path = \"%" PRFilePath "\""
857 " has download file = %s",
821 GetDbHandle(), 858 GetDbHandle(),
822 GetTotalBytes(), 859 GetTotalBytes(),
823 GetReceivedBytes(), 860 GetReceivedBytes(),
824 InterruptReasonDebugString(last_reason_).c_str(), 861 InterruptReasonDebugString(last_reason_).c_str(),
825 IsPaused() ? 'T' : 'F', 862 IsPaused() ? 'T' : 'F',
826 DebugSafetyStateString(GetSafetyState()), 863 DebugSafetyStateString(GetSafetyState()),
827 GetLastModifiedTime().c_str(), 864 GetLastModifiedTime().c_str(),
828 GetETag().c_str(), 865 GetETag().c_str(),
829 url_list.c_str(), 866 url_list.c_str(),
830 GetFullPath().value().c_str(), 867 GetFullPath().value().c_str(),
831 GetTargetFilePath().value().c_str()); 868 GetTargetFilePath().value().c_str(),
869 download_file_.get() ? "true" : "false");
832 } else { 870 } else {
833 description += base::StringPrintf(" url = \"%s\"", url_list.c_str()); 871 description += base::StringPrintf(" url = \"%s\"", url_list.c_str());
834 } 872 }
835 873
836 description += " }"; 874 description += " }";
837 875
838 return description; 876 return description;
839 } 877 }
840 878
841 void DownloadItemImpl::MockDownloadOpenForTesting() { 879 void DownloadItemImpl::MockDownloadOpenForTesting() {
842 open_enabled_ = false; 880 open_enabled_ = false;
843 } 881 }
844 882
845 void DownloadItemImpl::NotifyRemoved() { 883 void DownloadItemImpl::NotifyRemoved() {
846 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadRemoved(this)); 884 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadRemoved(this));
847 } 885 }
848 886
849 void DownloadItemImpl::OnDownloadedFileRemoved() { 887 void DownloadItemImpl::OnDownloadedFileRemoved() {
850 file_externally_removed_ = true; 888 file_externally_removed_ = true;
851 UpdateObservers(); 889 UpdateObservers();
852 } 890 }
853 891
854 void DownloadItemImpl::OffThreadCancel() {
855 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
856 request_handle_->CancelRequest();
857
858 BrowserThread::PostTask(
859 BrowserThread::FILE, FROM_HERE,
860 base::Bind(&DownloadFileManager::CancelDownload,
861 delegate_->GetDownloadFileManager(), download_id_));
862 }
863
864 // An error occurred somewhere. 892 // An error occurred somewhere.
865 void DownloadItemImpl::Interrupt(content::DownloadInterruptReason reason) { 893 void DownloadItemImpl::Interrupt(content::DownloadInterruptReason reason) {
866 // Somewhat counter-intuitively, it is possible for us to receive an 894 // Somewhat counter-intuitively, it is possible for us to receive an
867 // interrupt after we've already been interrupted. The generation of 895 // interrupt after we've already been interrupted. The generation of
868 // interrupts from the file thread Renames and the generation of 896 // interrupts from the file thread Renames and the generation of
869 // interrupts from disk writes go through two different mechanisms (driven 897 // interrupts from disk writes go through two different mechanisms (driven
870 // by rename requests from UI thread and by write requests from IO thread, 898 // by rename requests from UI thread and by write requests from IO thread,
871 // respectively), and since we choose not to keep state on the File thread, 899 // respectively), and since we choose not to keep state on the File thread,
872 // this is the place where the races collide. It's also possible for 900 // this is the place where the races collide. It's also possible for
873 // interrupts to race with cancels. 901 // interrupts to race with cancels.
874 902
875 // Whatever happens, the first one to hit the UI thread wins. 903 // Whatever happens, the first one to hit the UI thread wins.
876 if (!IsInProgress()) 904 if (!IsInProgress())
877 return; 905 return;
878 906
879 last_reason_ = reason; 907 last_reason_ = reason;
880 TransitionTo(INTERRUPTED); 908 TransitionTo(INTERRUPTED);
909
910 // Cancel and remove the download file.
911 // TODO(rdsmith/benjhayden): Remove condition as part of
912 // SavePackage integration.
913 if (!is_save_package_download_) {
914 CHECK(download_file_.get());
915 BrowserThread::PostTask(
916 BrowserThread::FILE, FROM_HERE,
917 // Will be deleted at end of task execution.
918 base::Bind(&DownloadFileCancel, base::Passed(download_file_.Pass())));
919 }
920
921 // Cancel the originating URL request.
922 request_handle_->CancelRequest();
923
881 download_stats::RecordDownloadInterrupted( 924 download_stats::RecordDownloadInterrupted(
882 reason, received_bytes_, total_bytes_); 925 reason, received_bytes_, total_bytes_);
883 delegate_->DownloadStopped(this); 926 delegate_->DownloadStopped(this);
884 } 927 }
885 928
929 base::WeakPtr<content::DownloadDestinationObserver>
930 DownloadItemImpl::DestinationObserverAsWeakPtr() {
931 // Return does private downcast.
benjhayden 2012/09/12 21:01:01 Actually, this is up-casting. And also obvious.
Randy Smith (Not in Mondays) 2012/09/13 20:15:12 The fact that it's private wasn't completely obvio
932 return weak_ptr_factory_.GetWeakPtr();
933 }
934
935 bool DownloadItemImpl::IsSavePackageDownload() const {
936 return is_save_package_download_;
937 }
938
886 void DownloadItemImpl::SetTotalBytes(int64 total_bytes) { 939 void DownloadItemImpl::SetTotalBytes(int64 total_bytes) {
887 total_bytes_ = total_bytes; 940 total_bytes_ = total_bytes;
888 } 941 }
889 942
890 // Updates from the download thread may have been posted while this download 943 // Updates from the download thread may have been posted while this download
891 // was being cancelled in the UI thread, so we'll accept them unless we're 944 // was being cancelled in the UI thread, so we'll accept them unless we're
892 // complete. 945 // complete.
893 void DownloadItemImpl::UpdateProgress(int64 bytes_so_far, 946 void DownloadItemImpl::UpdateProgress(int64 bytes_so_far,
894 int64 bytes_per_sec, 947 int64 bytes_per_sec,
895 const std::string& hash_state) { 948 const std::string& hash_state) {
(...skipping 22 matching lines...) Expand all
918 971
919 if (bound_net_log_.IsLoggingAllEvents()) { 972 if (bound_net_log_.IsLoggingAllEvents()) {
920 bound_net_log_.AddEvent( 973 bound_net_log_.AddEvent(
921 net::NetLog::TYPE_DOWNLOAD_ITEM_UPDATED, 974 net::NetLog::TYPE_DOWNLOAD_ITEM_UPDATED,
922 net::NetLog::Int64Callback("bytes_so_far", received_bytes_)); 975 net::NetLog::Int64Callback("bytes_so_far", received_bytes_));
923 } 976 }
924 977
925 UpdateObservers(); 978 UpdateObservers();
926 } 979 }
927 980
928 void DownloadItemImpl::OnAllDataSaved( 981 void DownloadItemImpl::OnAllDataSaved(const std::string& final_hash) {
929 int64 size, const std::string& final_hash) {
930 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 982 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
931 983
984 DCHECK_EQ(IN_PROGRESS, state_);
932 DCHECK(!all_data_saved_); 985 DCHECK(!all_data_saved_);
933 all_data_saved_ = true; 986 all_data_saved_ = true;
934 ProgressComplete(size, final_hash); 987
988 // Store final hash and null out intermediate serialized hash state.
989 hash_ = final_hash;
990 hash_state_ = "";
991
935 UpdateObservers(); 992 UpdateObservers();
936 } 993 }
937 994
938 void DownloadItemImpl::MarkAsComplete() { 995 void DownloadItemImpl::MarkAsComplete() {
939 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 996 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
940 997
941 DCHECK(all_data_saved_); 998 DCHECK(all_data_saved_);
942 end_time_ = base::Time::Now(); 999 end_time_ = base::Time::Now();
943 TransitionTo(COMPLETE); 1000 TransitionTo(COMPLETE);
944 } 1001 }
945 1002
946 void DownloadItemImpl::SetIsPersisted() { 1003 void DownloadItemImpl::SetIsPersisted() {
947 is_persisted_ = true; 1004 is_persisted_ = true;
1005 UpdateObservers();
948 } 1006 }
949 1007
950 void DownloadItemImpl::SetDbHandle(int64 handle) { 1008 void DownloadItemImpl::SetDbHandle(int64 handle) {
951 db_handle_ = handle; 1009 db_handle_ = handle;
952 1010
953 bound_net_log_.AddEvent( 1011 bound_net_log_.AddEvent(
954 net::NetLog::TYPE_DOWNLOAD_ITEM_IN_HISTORY, 1012 net::NetLog::TYPE_DOWNLOAD_ITEM_IN_HISTORY,
955 net::NetLog::Int64Callback("db_handle", db_handle_)); 1013 net::NetLog::Int64Callback("db_handle", db_handle_));
956 } 1014 }
957 1015
1016 void DownloadItemImpl::DestinationUpdate(int64 bytes_so_far,
1017 int64 bytes_per_sec,
1018 const std::string& hash_state) {
1019 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1020
1021 if (!IsInProgress()) {
1022 // Ignore if we're no longer in-progress. This can happen if we race a
1023 // Cancel on the UI thread with an update on the FILE thread.
1024 //
1025 // TODO(rdsmith): Arguably we should let this go through, as this means
1026 // the download really did get further than we know before it was
1027 // cancelled. But the gain isn't very large, and the code is more
1028 // fragile if it has to support in progress updates in a non-in-progress
1029 // state. This issue should be readdressed when we revamp performance
1030 // reporting.
1031 return;
1032 }
1033 bytes_per_sec_ = bytes_per_sec;
1034 hash_state_ = hash_state;
1035 received_bytes_ = bytes_so_far;
1036
1037 // If we've received more data than we were expecting (bad server info?),
1038 // revert to 'unknown size mode'.
1039 if (received_bytes_ > total_bytes_)
1040 total_bytes_ = 0;
1041
1042 if (bound_net_log_.IsLoggingAllEvents()) {
1043 bound_net_log_.AddEvent(
1044 net::NetLog::TYPE_DOWNLOAD_ITEM_UPDATED,
1045 net::NetLog::Int64Callback("bytes_so_far", received_bytes_));
1046 }
1047
1048 UpdateObservers();
1049 }
1050
1051 void DownloadItemImpl::DestinationError(
1052 content::DownloadInterruptReason reason) {
1053 // The DestinationError and Interrupt routines are being kept separate
1054 // to allow for a future merging of the Cancel and Interrupt routines..
1055 Interrupt(reason);
1056 }
1057
1058 void DownloadItemImpl::DestinationCompleted(const std::string& final_hash) {
1059 if (!IsInProgress())
1060 return;
1061 OnAllDataSaved(final_hash);
1062 delegate_->MaybeCompleteDownload(this);
1063 }
1064
958 // **** Download progression cascade 1065 // **** Download progression cascade
959 1066
960 void DownloadItemImpl::Init(bool active, 1067 void DownloadItemImpl::Init(bool active,
961 download_net_logs::DownloadType download_type) { 1068 download_net_logs::DownloadType download_type) {
962 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1069 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
963 1070
964 if (active) 1071 if (active)
965 download_stats::RecordDownloadCount(download_stats::START_COUNT); 1072 download_stats::RecordDownloadCount(download_stats::START_COUNT);
966 1073
967 if (target_path_.empty()) 1074 if (target_path_.empty())
(...skipping 23 matching lines...) Expand all
991 bound_net_log_.AddEvent( 1098 bound_net_log_.AddEvent(
992 net::NetLog::TYPE_DOWNLOAD_ITEM_IN_HISTORY, 1099 net::NetLog::TYPE_DOWNLOAD_ITEM_IN_HISTORY,
993 net::NetLog::Int64Callback("db_handle", db_handle_)); 1100 net::NetLog::Int64Callback("db_handle", db_handle_));
994 1101
995 bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE); 1102 bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE);
996 } 1103 }
997 1104
998 VLOG(20) << __FUNCTION__ << "() " << DebugString(true); 1105 VLOG(20) << __FUNCTION__ << "() " << DebugString(true);
999 } 1106 }
1000 1107
1001 // Called by DownloadManagerImpl when the download target path has been 1108 // We're starting the download.
1109 void DownloadItemImpl::Start(scoped_ptr<content::DownloadFile> download_file) {
1110 DCHECK(!download_file_.get());
1111 download_file_ = download_file.Pass();
benjhayden 2012/09/12 21:01:01 DCHECK(download_file_.get());?
Randy Smith (Not in Mondays) 2012/09/13 20:15:12 Equivalent done.
1112
1113 BrowserThread::PostTask(
1114 BrowserThread::FILE, FROM_HERE,
1115 base::Bind(&DownloadFile::Initialize,
1116 // Safe because we control download file lifetime.
1117 base::Unretained(download_file_.get()),
1118 base::Bind(&DownloadItemImpl::OnDownloadFileInitialized,
1119 weak_ptr_factory_.GetWeakPtr())));
1120 }
1121
1122 void DownloadItemImpl::OnDownloadFileInitialized(
1123 content::DownloadInterruptReason result) {
1124 if (result != content::DOWNLOAD_INTERRUPT_REASON_NONE) {
1125 Interrupt(result);
1126 // TODO(rdsmith): It makes no sense to continue along the
1127 // regular download path after we've gotten an error. But it's
1128 // the way the code has historically worked, and this allows us
1129 // to get the download persisted and observers of the download manager
1130 // notified, so tests work. When we execute all side effects of cancel
1131 // (including queue removal) immedately rather than waiting for
1132 // persistence we should replace this comment with a "return;".
1133 }
1134
1135 delegate_->DelegateStart(this);
1136 }
1137
1138 // Called by delegate_ when the download target path has been
1002 // determined. 1139 // determined.
1003 void DownloadItemImpl::OnDownloadTargetDetermined( 1140 void DownloadItemImpl::OnDownloadTargetDetermined(
1004 const FilePath& target_path, 1141 const FilePath& target_path,
1005 TargetDisposition disposition, 1142 TargetDisposition disposition,
1006 content::DownloadDangerType danger_type, 1143 content::DownloadDangerType danger_type,
1007 const FilePath& intermediate_path) { 1144 const FilePath& intermediate_path) {
1008 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1145 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1009 1146
1010 // If the |target_path| is empty, then we consider this download to be 1147 // If the |target_path| is empty, then we consider this download to be
1011 // canceled. 1148 // canceled.
1012 if (target_path.empty()) { 1149 if (target_path.empty()) {
1013 Cancel(true); 1150 Cancel(true);
1014 return; 1151 return;
1015 } 1152 }
1016 1153
1017 target_path_ = target_path; 1154 target_path_ = target_path;
1018 target_disposition_ = disposition; 1155 target_disposition_ = disposition;
1019 SetDangerType(danger_type); 1156 SetDangerType(danger_type);
1020 // TODO(asanka): SetDangerType() doesn't need to send a notification here. 1157 // TODO(asanka): SetDangerType() doesn't need to send a notification here.
1021 1158
1022 // We want the intermediate and target paths to refer to the same directory so 1159 // We want the intermediate and target paths to refer to the same directory so
1023 // that they are both on the same device and subject to same 1160 // that they are both on the same device and subject to same
1024 // space/permission/availability constraints. 1161 // space/permission/availability constraints.
1025 DCHECK(intermediate_path.DirName() == target_path.DirName()); 1162 DCHECK(intermediate_path.DirName() == target_path.DirName());
1026 1163
1164 if (!IsInProgress()) {
1165 // If we've been cancelled or interrupted while the target was being
1166 // determined, continue the cascade with a null name.
1167 // The error doesn't matter as the cause of download stoppaged
1168 // will already have been recorded.
1169 OnDownloadRenamedToIntermediateName(
1170 content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED, FilePath());
1171 return;
1172 }
1173
1027 // Rename to intermediate name. 1174 // Rename to intermediate name.
1028 // TODO(asanka): Skip this rename if AllDataSaved() is true. This avoids a 1175 // TODO(asanka): Skip this rename if AllDataSaved() is true. This avoids a
1029 // spurious rename when we can just rename to the final 1176 // spurious rename when we can just rename to the final
1030 // filename. Unnecessary renames may cause bugs like 1177 // filename. Unnecessary renames may cause bugs like
1031 // http://crbug.com/74187. 1178 // http://crbug.com/74187.
1032 DownloadFileManager::RenameCompletionCallback callback = 1179 DCHECK(!is_save_package_download_);
1180 CHECK(download_file_.get());
1181 DownloadFile::RenameCompletionCallback callback =
1033 base::Bind(&DownloadItemImpl::OnDownloadRenamedToIntermediateName, 1182 base::Bind(&DownloadItemImpl::OnDownloadRenamedToIntermediateName,
1034 weak_ptr_factory_.GetWeakPtr()); 1183 weak_ptr_factory_.GetWeakPtr());
1035 BrowserThread::PostTask( 1184 BrowserThread::PostTask(
1036 BrowserThread::FILE, FROM_HERE, 1185 BrowserThread::FILE, FROM_HERE,
1037 base::Bind(&DownloadFileManager::RenameDownloadFile, 1186 base::Bind(&DownloadFile::Rename,
1038 delegate_->GetDownloadFileManager(), GetGlobalId(), 1187 // Safe because we control download file lifetime.
1188 base::Unretained(download_file_.get()),
1039 intermediate_path, false, callback)); 1189 intermediate_path, false, callback));
1040 } 1190 }
1041 1191
1042 void DownloadItemImpl::OnDownloadRenamedToIntermediateName( 1192 void DownloadItemImpl::OnDownloadRenamedToIntermediateName(
1043 content::DownloadInterruptReason reason, 1193 content::DownloadInterruptReason reason,
1044 const FilePath& full_path) { 1194 const FilePath& full_path) {
1045 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1195 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1046 if (content::DOWNLOAD_INTERRUPT_REASON_NONE != reason) { 1196 if (content::DOWNLOAD_INTERRUPT_REASON_NONE != reason) {
1047 Interrupt(reason); 1197 Interrupt(reason);
1048 } else { 1198 } else {
1049 SetFullPath(full_path); 1199 SetFullPath(full_path);
1050 UpdateObservers(); 1200 UpdateObservers();
1051 } 1201 }
1052 1202
1053 delegate_->DownloadRenamedToIntermediateName(this); 1203 delegate_->DownloadRenamedToIntermediateName(this);
1054 } 1204 }
1055 1205
1056 void DownloadItemImpl::MaybeCompleteDownload() { 1206 void DownloadItemImpl::MaybeCompleteDownload() {
1057 // TODO(rdsmith): Move logic for this function here. 1207 // TODO(rdsmith): Move logic for this function here.
1058 delegate_->MaybeCompleteDownload(this); 1208 delegate_->MaybeCompleteDownload(this);
1059 } 1209 }
1060 1210
1061 // Called by DownloadManagerImpl::MaybeCompleteDownload() when it has 1211 // Called by DownloadManagerImpl::MaybeCompleteDownload() when it has
1062 // determined that the download is ready for completion. 1212 // determined that the download is ready for completion.
1063 void DownloadItemImpl::OnDownloadCompleting() { 1213 void DownloadItemImpl::OnDownloadCompleting() {
1064 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1214 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1065 1215
1216 if (!IsInProgress())
1217 return;
1218
1066 VLOG(20) << __FUNCTION__ << "()" 1219 VLOG(20) << __FUNCTION__ << "()"
1067 << " needs rename = " << NeedsRename() 1220 << " needs rename = " << NeedsRename()
1068 << " " << DebugString(true); 1221 << " " << DebugString(true);
1069 DCHECK(!GetTargetName().empty()); 1222 DCHECK(!GetTargetName().empty());
1070 DCHECK_NE(DANGEROUS, GetSafetyState()); 1223 DCHECK_NE(DANGEROUS, GetSafetyState());
1071 1224
1225 // TODO(rdsmith/benjhayden): Remove as part of SavePackage integration.
1226 if (is_save_package_download_) {
1227 // Avoid doing anything on the file thread; there's nothing we control
1228 // there.
1229 OnDownloadFileReleased();
1230 return;
1231 }
1232
1233 CHECK(download_file_.get());
1072 if (NeedsRename()) { 1234 if (NeedsRename()) {
1073 DownloadFileManager::RenameCompletionCallback callback = 1235 content::DownloadFile::RenameCompletionCallback callback =
1074 base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName, 1236 base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName,
1075 weak_ptr_factory_.GetWeakPtr()); 1237 weak_ptr_factory_.GetWeakPtr());
1076 BrowserThread::PostTask( 1238 BrowserThread::PostTask(
1077 BrowserThread::FILE, FROM_HERE, 1239 BrowserThread::FILE, FROM_HERE,
1078 base::Bind(&DownloadFileManager::RenameDownloadFile, 1240 base::Bind(&DownloadFile::Rename,
1079 delegate_->GetDownloadFileManager(), GetGlobalId(), 1241 base::Unretained(download_file_.get()),
1080 GetTargetFilePath(), true, callback)); 1242 GetTargetFilePath(), true, callback));
1081 } else { 1243 } else {
1082 // Complete the download and release the DownloadFile. 1244 ReleaseDownloadFile();
1083 BrowserThread::PostTask(
1084 BrowserThread::FILE, FROM_HERE,
1085 base::Bind(&DownloadFileManager::CompleteDownload,
1086 delegate_->GetDownloadFileManager(), GetGlobalId(),
1087 base::Bind(&DownloadItemImpl::OnDownloadFileReleased,
1088 weak_ptr_factory_.GetWeakPtr())));
1089 } 1245 }
1090 } 1246 }
1091 1247
1092 void DownloadItemImpl::OnDownloadRenamedToFinalName( 1248 void DownloadItemImpl::OnDownloadRenamedToFinalName(
1093 content::DownloadInterruptReason reason, 1249 content::DownloadInterruptReason reason,
1094 const FilePath& full_path) { 1250 const FilePath& full_path) {
1095 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1251 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1096 1252
1253 if (!IsInProgress())
1254 return;
1255
1097 VLOG(20) << __FUNCTION__ << "()" 1256 VLOG(20) << __FUNCTION__ << "()"
1098 << " full_path = \"" << full_path.value() << "\"" 1257 << " full_path = \"" << full_path.value() << "\""
1099 << " needed rename = " << NeedsRename() 1258 << " needed rename = " << NeedsRename()
1100 << " " << DebugString(false); 1259 << " " << DebugString(false);
1101 DCHECK(NeedsRename()); 1260 DCHECK(NeedsRename());
1102 1261
1103 if (content::DOWNLOAD_INTERRUPT_REASON_NONE != reason) { 1262 if (content::DOWNLOAD_INTERRUPT_REASON_NONE != reason) {
1104 Interrupt(reason); 1263 Interrupt(reason);
1105 return; 1264 return;
1106 } 1265 }
1107 1266
1108 // full_path is now the current and target file path. 1267 // full_path is now the current and target file path.
1109 DCHECK(!full_path.empty()); 1268 DCHECK(!full_path.empty());
1110 target_path_ = full_path; 1269 target_path_ = full_path;
1111 SetFullPath(full_path); 1270 SetFullPath(full_path);
1112 delegate_->DownloadRenamedToFinalName(this); 1271 delegate_->DownloadRenamedToFinalName(this);
1113 1272
1273 ReleaseDownloadFile();
1274 }
1275
1276 void DownloadItemImpl::ReleaseDownloadFile() {
1114 // Complete the download and release the DownloadFile. 1277 // Complete the download and release the DownloadFile.
1278 DCHECK(!is_save_package_download_);
1279 CHECK(download_file_.get());
1115 BrowserThread::PostTask( 1280 BrowserThread::PostTask(
1116 BrowserThread::FILE, FROM_HERE, 1281 BrowserThread::FILE, FROM_HERE,
1117 base::Bind(&DownloadFileManager::CompleteDownload, 1282 base::Bind(&DownloadFileDetach, base::Passed(download_file_.Pass()),
1118 delegate_->GetDownloadFileManager(), GetGlobalId(),
1119 base::Bind(&DownloadItemImpl::OnDownloadFileReleased, 1283 base::Bind(&DownloadItemImpl::OnDownloadFileReleased,
1120 weak_ptr_factory_.GetWeakPtr()))); 1284 weak_ptr_factory_.GetWeakPtr())));
1285
1286 // We're not completely done with the download item yet, but at this
1287 // point we're committed to complete the download. Cancels (or Interrupts,
1288 // though it's not clear how they could happen) after this point will be
1289 // ignored.
1290 TransitionTo(COMPLETE);
1291 delegate_->DownloadCompleted(this);
1121 } 1292 }
1122 1293
1123 void DownloadItemImpl::OnDownloadFileReleased() { 1294 void DownloadItemImpl::OnDownloadFileReleased() {
1124 if (delegate_->ShouldOpenDownload(this)) 1295 if (delegate_->ShouldOpenDownload(this))
1125 Completed(); 1296 Completed();
1126 else 1297 else
1127 delegate_delayed_complete_ = true; 1298 delegate_delayed_complete_ = true;
1128 } 1299 }
1129 1300
1130 void DownloadItemImpl::DelayedDownloadOpened(bool auto_opened) { 1301 void DownloadItemImpl::DelayedDownloadOpened(bool auto_opened) {
1131 auto_opened_ = auto_opened; 1302 auto_opened_ = auto_opened;
1132 Completed(); 1303 Completed();
1304 UpdateObservers();
1133 } 1305 }
1134 1306
1135 void DownloadItemImpl::Completed() { 1307 void DownloadItemImpl::Completed() {
1136 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1308 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1137 1309
1138 VLOG(20) << __FUNCTION__ << "() " << DebugString(false); 1310 VLOG(20) << __FUNCTION__ << "() " << DebugString(false);
1139 1311
1140 DCHECK(all_data_saved_); 1312 DCHECK(all_data_saved_);
1141 end_time_ = base::Time::Now(); 1313 end_time_ = base::Time::Now();
1142 TransitionTo(COMPLETE);
1143 delegate_->DownloadCompleted(this);
1144 download_stats::RecordDownloadCompleted(start_tick_, received_bytes_); 1314 download_stats::RecordDownloadCompleted(start_tick_, received_bytes_);
1145 1315
1146 if (auto_opened_) { 1316 if (auto_opened_) {
1147 // If it was already handled by the delegate, do nothing. 1317 // If it was already handled by the delegate, do nothing.
1148 } else if (GetOpenWhenComplete() || 1318 } else if (GetOpenWhenComplete() ||
1149 ShouldOpenFileBasedOnExtension() || 1319 ShouldOpenFileBasedOnExtension() ||
1150 IsTemporary()) { 1320 IsTemporary()) {
1151 // If the download is temporary, like in drag-and-drop, do not open it but 1321 // If the download is temporary, like in drag-and-drop, do not open it but
1152 // we still need to set it auto-opened so that it can be removed from the 1322 // we still need to set it auto-opened so that it can be removed from the
1153 // download shelf. 1323 // download shelf.
1154 if (!IsTemporary()) 1324 if (!IsTemporary())
1155 OpenDownload(); 1325 OpenDownload();
1156 1326
1157 auto_opened_ = true; 1327 auto_opened_ = true;
1158 UpdateObservers(); 1328 UpdateObservers();
1159 } 1329 }
1160 } 1330 }
1161 1331
1162 // **** End of Download progression cascade 1332 // **** End of Download progression cascade
1163 1333
1164 bool DownloadItemImpl::NeedsRename() const { 1334 bool DownloadItemImpl::NeedsRename() const {
1165 DCHECK(target_path_.DirName() == current_path_.DirName()); 1335 DCHECK(target_path_.DirName() == current_path_.DirName());
1166 return target_path_ != current_path_; 1336 return target_path_ != current_path_;
1167 } 1337 }
1168 1338
1169 void DownloadItemImpl::ProgressComplete(int64 bytes_so_far,
1170 const std::string& final_hash) {
1171 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1172
1173 hash_ = final_hash;
1174 hash_state_ = "";
1175
1176 received_bytes_ = bytes_so_far;
1177
1178 // If we've received more data than we were expecting (bad server info?),
1179 // revert to 'unknown size mode'.
1180 if (received_bytes_ > total_bytes_)
1181 total_bytes_ = 0;
1182 }
1183
1184 void DownloadItemImpl::TransitionTo(DownloadState new_state) { 1339 void DownloadItemImpl::TransitionTo(DownloadState new_state) {
1185 if (state_ == new_state) 1340 if (state_ == new_state)
1186 return; 1341 return;
1187 1342
1188 DownloadState old_state = state_; 1343 DownloadState old_state = state_;
1189 state_ = new_state; 1344 state_ = new_state;
1190 1345
1191 switch (state_) { 1346 switch (state_) {
1192 case COMPLETE: 1347 case COMPLETE:
1193 bound_net_log_.AddEvent( 1348 bound_net_log_.AddEvent(
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1242 << " new_path = \"" << new_path.value() << "\"" 1397 << " new_path = \"" << new_path.value() << "\""
1243 << " " << DebugString(true); 1398 << " " << DebugString(true);
1244 DCHECK(!new_path.empty()); 1399 DCHECK(!new_path.empty());
1245 current_path_ = new_path; 1400 current_path_ = new_path;
1246 1401
1247 bound_net_log_.AddEvent( 1402 bound_net_log_.AddEvent(
1248 net::NetLog::TYPE_DOWNLOAD_ITEM_RENAMED, 1403 net::NetLog::TYPE_DOWNLOAD_ITEM_RENAMED,
1249 base::Bind(&download_net_logs::ItemRenamedCallback, 1404 base::Bind(&download_net_logs::ItemRenamedCallback,
1250 &current_path_, &new_path)); 1405 &current_path_, &new_path));
1251 } 1406 }
1252
1253
1254
1255
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698