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

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: Incorporated comments and sync'd to r158560 Created 8 years, 2 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 as
6 // as in download_item_impl.h, with the following exception: The public 6 // in download_item_impl.h, with the following exception: The public
7 // interfaces DelayedDownloadOpened, OnDownloadTargetDetermined, and 7 // interfaces Start, DelayedDownloadOpened, and OnDownloadCompleting
8 // OnDownloadCompleting are placed in chronological order with the other 8 // are placed in chronological order with the other (private) routines
9 // (private) routines that together define a DownloadItem's state transitions 9 // that together define a DownloadItem's state transitions as the
10 // as the download progresses. See "Download progression cascade" later in 10 // 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.
18 // * Made visible in the download shelf. 18 // * Made visible in the download shelf.
19 // * All the data is saved. Note that the actual data download occurs 19 // * All the data is saved. Note that the actual data download occurs
20 // in parallel with the above steps, but until those steps are 20 // in parallel with the above steps, but until those steps are
21 // complete, the state of the data save will be ignored. 21 // complete, the state of the data save will be ignored.
22 // * Download file is renamed to its final name, and possibly 22 // * Download file is renamed to its final name, and possibly
23 // auto-opened. 23 // auto-opened.
24 24
25 #include "content/browser/download/download_item_impl.h" 25 #include "content/browser/download/download_item_impl.h"
26 26
27 #include <vector> 27 #include <vector>
28 28
29 #include "base/basictypes.h" 29 #include "base/basictypes.h"
30 #include "base/bind.h" 30 #include "base/bind.h"
31 #include "base/file_util.h" 31 #include "base/file_util.h"
32 #include "base/format_macros.h" 32 #include "base/format_macros.h"
33 #include "base/logging.h" 33 #include "base/logging.h"
34 #include "base/metrics/histogram.h" 34 #include "base/metrics/histogram.h"
35 #include "base/stl_util.h" 35 #include "base/stl_util.h"
36 #include "base/stringprintf.h" 36 #include "base/stringprintf.h"
37 #include "base/utf_string_conversions.h" 37 #include "base/utf_string_conversions.h"
38 #include "content/browser/download/download_create_info.h" 38 #include "content/browser/download/download_create_info.h"
39 #include "content/browser/download/download_file.h" 39 #include "content/browser/download/download_file.h"
40 #include "content/browser/download/download_file_manager.h"
41 #include "content/browser/download/download_interrupt_reasons_impl.h" 40 #include "content/browser/download/download_interrupt_reasons_impl.h"
42 #include "content/browser/download/download_item_impl_delegate.h" 41 #include "content/browser/download/download_item_impl_delegate.h"
43 #include "content/browser/download/download_request_handle.h" 42 #include "content/browser/download/download_request_handle.h"
44 #include "content/browser/download/download_stats.h" 43 #include "content/browser/download/download_stats.h"
45 #include "content/browser/web_contents/web_contents_impl.h" 44 #include "content/browser/web_contents/web_contents_impl.h"
46 #include "content/public/browser/browser_thread.h" 45 #include "content/public/browser/browser_thread.h"
47 #include "content/public/browser/content_browser_client.h" 46 #include "content/public/browser/content_browser_client.h"
48 #include "content/public/browser/download_persistent_store_info.h" 47 #include "content/public/browser/download_persistent_store_info.h"
49 #include "net/base/net_util.h" 48 #include "net/base/net_util.h"
50 49
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 return NULL; 96 return NULL;
98 } 97 }
99 virtual void PauseRequest() const OVERRIDE {} 98 virtual void PauseRequest() const OVERRIDE {}
100 virtual void ResumeRequest() const OVERRIDE {} 99 virtual void ResumeRequest() const OVERRIDE {}
101 virtual void CancelRequest() const OVERRIDE {} 100 virtual void CancelRequest() const OVERRIDE {}
102 virtual std::string DebugString() const OVERRIDE { 101 virtual std::string DebugString() const OVERRIDE {
103 return "Null DownloadRequestHandle"; 102 return "Null DownloadRequestHandle";
104 } 103 }
105 }; 104 };
106 105
106 // Wrapper around DownloadFile::Detach and DownloadFile::Cancel that
107 // takes ownership of the DownloadFile and hence implicitly destroys it
108 // at the end of the function.
109 static void DownloadFileDetach(
110 scoped_ptr<DownloadFile> download_file, base::Closure callback) {
111 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
112 download_file->Detach(callback);
113 }
114
115 static void DownloadFileCancel(scoped_ptr<DownloadFile> download_file) {
116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
117 download_file->Cancel();
118 }
119
107 } // namespace 120 } // namespace
108 121
109 namespace content { 122 namespace content {
110 123
111 // Our download table ID starts at 1, so we use 0 to represent a download that 124 // Our download table ID starts at 1, so we use 0 to represent a download that
112 // has started, but has not yet had its data persisted in the table. We use fake 125 // has started, but has not yet had its data persisted in the table. We use fake
113 // database handles in incognito mode starting at -1 and progressively getting 126 // database handles in incognito mode starting at -1 and progressively getting
114 // more negative. 127 // more negative.
115 // static 128 // static
116 const int DownloadItem::kUninitializedHandle = 0; 129 const int DownloadItem::kUninitializedHandle = 0;
117 130
118 const char DownloadItem::kEmptyFileHash[] = ""; 131 const char DownloadItem::kEmptyFileHash[] = "";
119 132
120 } 133 }
121 134
122 // Our download table ID starts at 1, so we use 0 to represent a download that 135 // Our download table ID starts at 1, so we use 0 to represent a download that
123 // has started, but has not yet had its data persisted in the table. We use fake 136 // has started, but has not yet had its data persisted in the table. We use fake
124 // database handles in incognito mode starting at -1 and progressively getting 137 // database handles in incognito mode starting at -1 and progressively getting
125 // more negative. 138 // more negative.
126 139
127 // Constructor for reading from the history service. 140 // Constructor for reading from the history service.
128 DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate, 141 DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate,
129 DownloadId download_id, 142 DownloadId download_id,
130 const DownloadPersistentStoreInfo& info, 143 const DownloadPersistentStoreInfo& info,
131 const net::BoundNetLog& bound_net_log) 144 const net::BoundNetLog& bound_net_log)
132 : download_id_(download_id), 145 : is_save_package_download_(false),
146 download_id_(download_id),
133 current_path_(info.path), 147 current_path_(info.path),
134 target_path_(info.path), 148 target_path_(info.path),
135 target_disposition_(TARGET_DISPOSITION_OVERWRITE), 149 target_disposition_(TARGET_DISPOSITION_OVERWRITE),
136 url_chain_(1, info.url), 150 url_chain_(1, info.url),
137 referrer_url_(info.referrer_url), 151 referrer_url_(info.referrer_url),
138 transition_type_(content::PAGE_TRANSITION_LINK), 152 transition_type_(content::PAGE_TRANSITION_LINK),
139 has_user_gesture_(false), 153 has_user_gesture_(false),
140 total_bytes_(info.total_bytes), 154 total_bytes_(info.total_bytes),
141 received_bytes_(info.received_bytes), 155 received_bytes_(info.received_bytes),
142 bytes_per_sec_(0), 156 bytes_per_sec_(0),
(...skipping 26 matching lines...) Expand all
169 Init(false /* not actively downloading */, 183 Init(false /* not actively downloading */,
170 download_net_logs::SRC_HISTORY_IMPORT); 184 download_net_logs::SRC_HISTORY_IMPORT);
171 } 185 }
172 186
173 // Constructing for a regular download: 187 // Constructing for a regular download:
174 DownloadItemImpl::DownloadItemImpl( 188 DownloadItemImpl::DownloadItemImpl(
175 DownloadItemImplDelegate* delegate, 189 DownloadItemImplDelegate* delegate,
176 const DownloadCreateInfo& info, 190 const DownloadCreateInfo& info,
177 scoped_ptr<DownloadRequestHandleInterface> request_handle, 191 scoped_ptr<DownloadRequestHandleInterface> request_handle,
178 const net::BoundNetLog& bound_net_log) 192 const net::BoundNetLog& bound_net_log)
179 : request_handle_(request_handle.Pass()), 193 : is_save_package_download_(false),
194 request_handle_(request_handle.Pass()),
180 download_id_(info.download_id), 195 download_id_(info.download_id),
181 target_disposition_( 196 target_disposition_(
182 (info.prompt_user_for_save_location) ? 197 (info.prompt_user_for_save_location) ?
183 TARGET_DISPOSITION_PROMPT : TARGET_DISPOSITION_OVERWRITE), 198 TARGET_DISPOSITION_PROMPT : TARGET_DISPOSITION_OVERWRITE),
184 url_chain_(info.url_chain), 199 url_chain_(info.url_chain),
185 referrer_url_(info.referrer_url), 200 referrer_url_(info.referrer_url),
186 suggested_filename_(UTF16ToUTF8(info.save_info.suggested_name)), 201 suggested_filename_(UTF16ToUTF8(info.save_info.suggested_name)),
187 forced_file_path_(info.save_info.file_path), 202 forced_file_path_(info.save_info.file_path),
188 transition_type_(info.transition_type), 203 transition_type_(info.transition_type),
189 has_user_gesture_(info.has_user_gesture), 204 has_user_gesture_(info.has_user_gesture),
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 bound_net_log_.source().ToEventParametersCallback()); 244 bound_net_log_.source().ToEventParametersCallback());
230 } 245 }
231 246
232 // Constructing for the "Save Page As..." feature: 247 // Constructing for the "Save Page As..." feature:
233 DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate, 248 DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate,
234 const FilePath& path, 249 const FilePath& path,
235 const GURL& url, 250 const GURL& url,
236 DownloadId download_id, 251 DownloadId download_id,
237 const std::string& mime_type, 252 const std::string& mime_type,
238 const net::BoundNetLog& bound_net_log) 253 const net::BoundNetLog& bound_net_log)
239 : request_handle_(new NullDownloadRequestHandle()), 254 : is_save_package_download_(true),
255 request_handle_(new NullDownloadRequestHandle()),
240 download_id_(download_id), 256 download_id_(download_id),
241 current_path_(path), 257 current_path_(path),
242 target_path_(path), 258 target_path_(path),
243 target_disposition_(TARGET_DISPOSITION_OVERWRITE), 259 target_disposition_(TARGET_DISPOSITION_OVERWRITE),
244 url_chain_(1, url), 260 url_chain_(1, url),
245 referrer_url_(GURL()), 261 referrer_url_(GURL()),
246 transition_type_(content::PAGE_TRANSITION_LINK), 262 transition_type_(content::PAGE_TRANSITION_LINK),
247 has_user_gesture_(false), 263 has_user_gesture_(false),
248 mime_type_(mime_type), 264 mime_type_(mime_type),
249 original_mime_type_(mime_type), 265 original_mime_type_(mime_type),
(...skipping 20 matching lines...) Expand all
270 delegate_delayed_complete_(false), 286 delegate_delayed_complete_(false),
271 bound_net_log_(bound_net_log), 287 bound_net_log_(bound_net_log),
272 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { 288 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
273 delegate_->Attach(); 289 delegate_->Attach();
274 Init(true /* actively downloading */, 290 Init(true /* actively downloading */,
275 download_net_logs::SRC_SAVE_PAGE_AS); 291 download_net_logs::SRC_SAVE_PAGE_AS);
276 } 292 }
277 293
278 DownloadItemImpl::~DownloadItemImpl() { 294 DownloadItemImpl::~DownloadItemImpl() {
279 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 295 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
296
297 // Should always have been nuked before now, at worst in
298 // DownloadManager shutdown.
299 DCHECK(!download_file_.get());
300
280 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadDestroyed(this)); 301 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadDestroyed(this));
281 delegate_->AssertStateConsistent(this); 302 delegate_->AssertStateConsistent(this);
282 delegate_->Detach(); 303 delegate_->Detach();
283 } 304 }
284 305
285 void DownloadItemImpl::AddObserver(Observer* observer) { 306 void DownloadItemImpl::AddObserver(Observer* observer) {
286 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 307 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
287 308
288 observers_.AddObserver(observer); 309 observers_.AddObserver(observer);
289 } 310 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true); 363 VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
343 if (state_ != IN_PROGRESS_INTERNAL) { 364 if (state_ != IN_PROGRESS_INTERNAL) {
344 // Small downloads might be complete before this method has 365 // Small downloads might be complete before this method has
345 // a chance to run. 366 // a chance to run.
346 return; 367 return;
347 } 368 }
348 369
349 download_stats::RecordDownloadCount(download_stats::CANCELLED_COUNT); 370 download_stats::RecordDownloadCount(download_stats::CANCELLED_COUNT);
350 371
351 TransitionTo(CANCELLED_INTERNAL); 372 TransitionTo(CANCELLED_INTERNAL);
373
374 // Cancel and remove the download file.
375 // TODO(rdsmith/benjhayden): Remove condition as part of
376 // SavePackage integration.
377 if (!is_save_package_download_) {
378 CHECK(download_file_.get());
379 BrowserThread::PostTask(
380 BrowserThread::FILE, FROM_HERE,
381 // Will be deleted at end of task execution.
382 base::Bind(&DownloadFileCancel, base::Passed(download_file_.Pass())));
383 }
384
385 // Cancel the originating URL request.
386 request_handle_->CancelRequest();
387
352 if (user_cancel) 388 if (user_cancel)
353 delegate_->DownloadStopped(this); 389 delegate_->DownloadStopped(this);
354 } 390 }
355 391
356 void DownloadItemImpl::Delete(DeleteReason reason) { 392 void DownloadItemImpl::Delete(DeleteReason reason) {
357 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 393 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
358 394
359 switch (reason) { 395 switch (reason) {
360 case DELETE_DUE_TO_USER_DISCARD: 396 case DELETE_DUE_TO_USER_DISCARD:
361 UMA_HISTOGRAM_ENUMERATION( 397 UMA_HISTOGRAM_ENUMERATION(
362 "Download.UserDiscard", GetDangerType(), 398 "Download.UserDiscard", GetDangerType(),
363 content::DOWNLOAD_DANGER_TYPE_MAX); 399 content::DOWNLOAD_DANGER_TYPE_MAX);
364 break; 400 break;
365 case DELETE_DUE_TO_BROWSER_SHUTDOWN: 401 case DELETE_DUE_TO_BROWSER_SHUTDOWN:
366 UMA_HISTOGRAM_ENUMERATION( 402 UMA_HISTOGRAM_ENUMERATION(
367 "Download.Discard", GetDangerType(), 403 "Download.Discard", GetDangerType(),
368 content::DOWNLOAD_DANGER_TYPE_MAX); 404 content::DOWNLOAD_DANGER_TYPE_MAX);
369 break; 405 break;
370 default: 406 default:
371 NOTREACHED(); 407 NOTREACHED();
372 } 408 }
373 409
374 // TODO(asanka): Avoid deleting a file that is still owned by DownloadFile. 410 // TODO(asanka): Avoid deleting a file that is still owned by DownloadFile.
375 if (!current_path_.empty()) 411 if (!current_path_.empty())
376 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 412 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
377 base::Bind(&DeleteDownloadedFile, current_path_)); 413 base::Bind(&DeleteDownloadedFile, current_path_));
asanka 2012/09/28 20:22:42 Since we can now readily tell whether the Download
Randy Smith (Not in Mondays) 2012/10/09 20:20:19 Done.
378 Remove(); 414 Remove();
379 // We have now been deleted. 415 // We have now been deleted.
380 } 416 }
381 417
382 void DownloadItemImpl::Remove() { 418 void DownloadItemImpl::Remove() {
383 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 419 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
384 420
385 delegate_->AssertStateConsistent(this); 421 delegate_->AssertStateConsistent(this);
386 Cancel(true); 422 Cancel(true);
387 delegate_->AssertStateConsistent(this); 423 delegate_->AssertStateConsistent(this);
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 " db_handle = %" PRId64 791 " db_handle = %" PRId64
756 " total = %" PRId64 792 " total = %" PRId64
757 " received = %" PRId64 793 " received = %" PRId64
758 " reason = %s" 794 " reason = %s"
759 " paused = %c" 795 " paused = %c"
760 " safety = %s" 796 " safety = %s"
761 " last_modified = '%s'" 797 " last_modified = '%s'"
762 " etag = '%s'" 798 " etag = '%s'"
763 " url_chain = \n\t\"%s\"\n\t" 799 " url_chain = \n\t\"%s\"\n\t"
764 " full_path = \"%" PRFilePath "\"" 800 " full_path = \"%" PRFilePath "\""
765 " target_path = \"%" PRFilePath "\"", 801 " target_path = \"%" PRFilePath "\""
802 " has download file = %s",
766 GetDbHandle(), 803 GetDbHandle(),
767 GetTotalBytes(), 804 GetTotalBytes(),
768 GetReceivedBytes(), 805 GetReceivedBytes(),
769 InterruptReasonDebugString(last_reason_).c_str(), 806 InterruptReasonDebugString(last_reason_).c_str(),
770 IsPaused() ? 'T' : 'F', 807 IsPaused() ? 'T' : 'F',
771 DebugSafetyStateString(GetSafetyState()), 808 DebugSafetyStateString(GetSafetyState()),
772 GetLastModifiedTime().c_str(), 809 GetLastModifiedTime().c_str(),
773 GetETag().c_str(), 810 GetETag().c_str(),
774 url_list.c_str(), 811 url_list.c_str(),
775 GetFullPath().value().c_str(), 812 GetFullPath().value().c_str(),
776 GetTargetFilePath().value().c_str()); 813 GetTargetFilePath().value().c_str(),
814 download_file_.get() ? "true" : "false");
777 } else { 815 } else {
778 description += base::StringPrintf(" url = \"%s\"", url_list.c_str()); 816 description += base::StringPrintf(" url = \"%s\"", url_list.c_str());
779 } 817 }
780 818
781 description += " }"; 819 description += " }";
782 820
783 return description; 821 return description;
784 } 822 }
785 823
786 void DownloadItemImpl::MockDownloadOpenForTesting() { 824 void DownloadItemImpl::MockDownloadOpenForTesting() {
787 open_enabled_ = false; 825 open_enabled_ = false;
788 } 826 }
789 827
790 void DownloadItemImpl::NotifyRemoved() { 828 void DownloadItemImpl::NotifyRemoved() {
791 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadRemoved(this)); 829 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadRemoved(this));
792 } 830 }
793 831
794 void DownloadItemImpl::OnDownloadedFileRemoved() { 832 void DownloadItemImpl::OnDownloadedFileRemoved() {
795 file_externally_removed_ = true; 833 file_externally_removed_ = true;
796 UpdateObservers(); 834 UpdateObservers();
797 } 835 }
798 836
799 void DownloadItemImpl::OffThreadCancel() {
800 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
801 request_handle_->CancelRequest();
802
803 BrowserThread::PostTask(
804 BrowserThread::FILE, FROM_HERE,
805 base::Bind(&DownloadFileManager::CancelDownload,
806 delegate_->GetDownloadFileManager(), download_id_));
807 }
808
809 // An error occurred somewhere. 837 // An error occurred somewhere.
810 void DownloadItemImpl::Interrupt(content::DownloadInterruptReason reason) { 838 void DownloadItemImpl::Interrupt(content::DownloadInterruptReason reason) {
811 // Somewhat counter-intuitively, it is possible for us to receive an 839 // Somewhat counter-intuitively, it is possible for us to receive an
812 // interrupt after we've already been interrupted. The generation of 840 // interrupt after we've already been interrupted. The generation of
813 // interrupts from the file thread Renames and the generation of 841 // interrupts from the file thread Renames and the generation of
814 // interrupts from disk writes go through two different mechanisms (driven 842 // interrupts from disk writes go through two different mechanisms (driven
815 // by rename requests from UI thread and by write requests from IO thread, 843 // by rename requests from UI thread and by write requests from IO thread,
816 // respectively), and since we choose not to keep state on the File thread, 844 // respectively), and since we choose not to keep state on the File thread,
817 // this is the place where the races collide. It's also possible for 845 // this is the place where the races collide. It's also possible for
818 // interrupts to race with cancels. 846 // interrupts to race with cancels.
819 847
820 // Whatever happens, the first one to hit the UI thread wins. 848 // Whatever happens, the first one to hit the UI thread wins.
821 if (state_ != IN_PROGRESS_INTERNAL) 849 if (state_ != IN_PROGRESS_INTERNAL)
822 return; 850 return;
823 851
824 last_reason_ = reason; 852 last_reason_ = reason;
825 TransitionTo(INTERRUPTED_INTERNAL); 853 TransitionTo(INTERRUPTED_INTERNAL);
854
855 // Cancel and remove the download file.
856 // TODO(rdsmith/benjhayden): Remove condition as part of
857 // SavePackage integration.
858 if (!is_save_package_download_) {
benjhayden 2012/09/28 20:49:42 Factor this out into a method and share with Cance
Randy Smith (Not in Mondays) 2012/10/09 20:20:19 Done.
859 CHECK(download_file_.get());
860 BrowserThread::PostTask(
861 BrowserThread::FILE, FROM_HERE,
862 // Will be deleted at end of task execution.
863 base::Bind(&DownloadFileCancel, base::Passed(download_file_.Pass())));
864 }
865
866 // Cancel the originating URL request.
867 request_handle_->CancelRequest();
868
826 download_stats::RecordDownloadInterrupted( 869 download_stats::RecordDownloadInterrupted(
827 reason, received_bytes_, total_bytes_); 870 reason, received_bytes_, total_bytes_);
828 delegate_->DownloadStopped(this); 871 delegate_->DownloadStopped(this);
829 } 872 }
830 873
874 base::WeakPtr<content::DownloadDestinationObserver>
875 DownloadItemImpl::DestinationObserverAsWeakPtr() {
876 return weak_ptr_factory_.GetWeakPtr();
877 }
878
879 bool DownloadItemImpl::IsSavePackageDownload() const {
880 return is_save_package_download_;
881 }
882
831 void DownloadItemImpl::SetTotalBytes(int64 total_bytes) { 883 void DownloadItemImpl::SetTotalBytes(int64 total_bytes) {
832 total_bytes_ = total_bytes; 884 total_bytes_ = total_bytes;
833 } 885 }
834 886
835 // Updates from the download thread may have been posted while this download 887 // Updates from the download thread may have been posted while this download
836 // was being cancelled in the UI thread, so we'll accept them unless we're 888 // was being cancelled in the UI thread, so we'll accept them unless we're
837 // complete. 889 // complete.
838 void DownloadItemImpl::UpdateProgress(int64 bytes_so_far, 890 void DownloadItemImpl::UpdateProgress(int64 bytes_so_far,
839 int64 bytes_per_sec, 891 int64 bytes_per_sec,
840 const std::string& hash_state) { 892 const std::string& hash_state) {
(...skipping 22 matching lines...) Expand all
863 915
864 if (bound_net_log_.IsLoggingAllEvents()) { 916 if (bound_net_log_.IsLoggingAllEvents()) {
865 bound_net_log_.AddEvent( 917 bound_net_log_.AddEvent(
866 net::NetLog::TYPE_DOWNLOAD_ITEM_UPDATED, 918 net::NetLog::TYPE_DOWNLOAD_ITEM_UPDATED,
867 net::NetLog::Int64Callback("bytes_so_far", received_bytes_)); 919 net::NetLog::Int64Callback("bytes_so_far", received_bytes_));
868 } 920 }
869 921
870 UpdateObservers(); 922 UpdateObservers();
871 } 923 }
872 924
873 void DownloadItemImpl::OnAllDataSaved( 925 void DownloadItemImpl::OnAllDataSaved(const std::string& final_hash) {
874 int64 size, const std::string& final_hash) {
875 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 926 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
876 927
928 DCHECK_EQ(IN_PROGRESS_INTERNAL, state_);
877 DCHECK(!all_data_saved_); 929 DCHECK(!all_data_saved_);
878 all_data_saved_ = true; 930 all_data_saved_ = true;
879 ProgressComplete(size, final_hash); 931
932 // Store final hash and null out intermediate serialized hash state.
933 hash_ = final_hash;
934 hash_state_ = "";
935
880 UpdateObservers(); 936 UpdateObservers();
881 } 937 }
882 938
883 void DownloadItemImpl::MarkAsComplete() { 939 void DownloadItemImpl::MarkAsComplete() {
884 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 940 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
885 941
886 DCHECK(all_data_saved_); 942 DCHECK(all_data_saved_);
887 end_time_ = base::Time::Now(); 943 end_time_ = base::Time::Now();
888 TransitionTo(COMPLETE_INTERNAL); 944 TransitionTo(COMPLETE_INTERNAL);
889 } 945 }
890 946
891 void DownloadItemImpl::SetIsPersisted() { 947 void DownloadItemImpl::SetIsPersisted() {
892 is_persisted_ = true; 948 is_persisted_ = true;
893 UpdateObservers(); 949 UpdateObservers();
894 } 950 }
895 951
896 void DownloadItemImpl::SetDbHandle(int64 handle) { 952 void DownloadItemImpl::SetDbHandle(int64 handle) {
897 db_handle_ = handle; 953 db_handle_ = handle;
898 954
899 bound_net_log_.AddEvent( 955 bound_net_log_.AddEvent(
900 net::NetLog::TYPE_DOWNLOAD_ITEM_IN_HISTORY, 956 net::NetLog::TYPE_DOWNLOAD_ITEM_IN_HISTORY,
901 net::NetLog::Int64Callback("db_handle", db_handle_)); 957 net::NetLog::Int64Callback("db_handle", db_handle_));
902 } 958 }
903 959
960 void DownloadItemImpl::DestinationUpdate(int64 bytes_so_far,
961 int64 bytes_per_sec,
962 const std::string& hash_state) {
963 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
964
965 if (!IsInProgress()) {
966 // Ignore if we're no longer in-progress. This can happen if we race a
967 // Cancel on the UI thread with an update on the FILE thread.
968 //
969 // TODO(rdsmith): Arguably we should let this go through, as this means
970 // the download really did get further than we know before it was
971 // cancelled. But the gain isn't very large, and the code is more
972 // fragile if it has to support in progress updates in a non-in-progress
973 // state. This issue should be readdressed when we revamp performance
974 // reporting.
975 return;
976 }
977 bytes_per_sec_ = bytes_per_sec;
978 hash_state_ = hash_state;
979 received_bytes_ = bytes_so_far;
980
981 // If we've received more data than we were expecting (bad server info?),
982 // revert to 'unknown size mode'.
983 if (received_bytes_ > total_bytes_)
984 total_bytes_ = 0;
985
986 if (bound_net_log_.IsLoggingAllEvents()) {
987 bound_net_log_.AddEvent(
988 net::NetLog::TYPE_DOWNLOAD_ITEM_UPDATED,
989 net::NetLog::Int64Callback("bytes_so_far", received_bytes_));
990 }
991
992 UpdateObservers();
993 }
994
995 void DownloadItemImpl::DestinationError(
996 content::DownloadInterruptReason reason) {
997 // The DestinationError and Interrupt routines are being kept separate
998 // to allow for a future merging of the Cancel and Interrupt routines..
999 Interrupt(reason);
1000 }
1001
1002 void DownloadItemImpl::DestinationCompleted(const std::string& final_hash) {
1003 if (!IsInProgress())
1004 return;
1005 OnAllDataSaved(final_hash);
1006 delegate_->MaybeCompleteDownload(this);
1007 }
1008
904 // **** Download progression cascade 1009 // **** Download progression cascade
905 1010
906 void DownloadItemImpl::Init(bool active, 1011 void DownloadItemImpl::Init(bool active,
907 download_net_logs::DownloadType download_type) { 1012 download_net_logs::DownloadType download_type) {
908 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1013 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
909 1014
910 if (active) 1015 if (active)
911 download_stats::RecordDownloadCount(download_stats::START_COUNT); 1016 download_stats::RecordDownloadCount(download_stats::START_COUNT);
912 1017
913 if (target_path_.empty()) 1018 if (target_path_.empty())
(...skipping 23 matching lines...) Expand all
937 bound_net_log_.AddEvent( 1042 bound_net_log_.AddEvent(
938 net::NetLog::TYPE_DOWNLOAD_ITEM_IN_HISTORY, 1043 net::NetLog::TYPE_DOWNLOAD_ITEM_IN_HISTORY,
939 net::NetLog::Int64Callback("db_handle", db_handle_)); 1044 net::NetLog::Int64Callback("db_handle", db_handle_));
940 1045
941 bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE); 1046 bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE);
942 } 1047 }
943 1048
944 VLOG(20) << __FUNCTION__ << "() " << DebugString(true); 1049 VLOG(20) << __FUNCTION__ << "() " << DebugString(true);
945 } 1050 }
946 1051
947 // Called by DownloadManagerImpl when the download target path has been 1052 // We're starting the download.
1053 void DownloadItemImpl::Start(scoped_ptr<content::DownloadFile> file) {
1054 DCHECK(!download_file_.get());
1055 DCHECK(file.get());
1056 download_file_ = file.Pass();
1057
1058 BrowserThread::PostTask(
1059 BrowserThread::FILE, FROM_HERE,
1060 base::Bind(&DownloadFile::Initialize,
1061 // Safe because we control download file lifetime.
1062 base::Unretained(download_file_.get()),
1063 base::Bind(&DownloadItemImpl::OnDownloadFileInitialized,
1064 weak_ptr_factory_.GetWeakPtr())));
1065 }
1066
1067 void DownloadItemImpl::OnDownloadFileInitialized(
1068 content::DownloadInterruptReason result) {
1069 if (result != content::DOWNLOAD_INTERRUPT_REASON_NONE) {
1070 Interrupt(result);
1071 // TODO(rdsmith): It makes no sense to continue along the
1072 // regular download path after we've gotten an error. But it's
1073 // the way the code has historically worked, and this allows us
1074 // to get the download persisted and observers of the download manager
1075 // notified, so tests work. When we execute all side effects of cancel
1076 // (including queue removal) immedately rather than waiting for
1077 // persistence we should replace this comment with a "return;".
1078 }
1079
1080 delegate_->DetermineDownloadTarget(
1081 this, base::Bind(&DownloadItemImpl::OnDownloadTargetDetermined,
1082 weak_ptr_factory_.GetWeakPtr()));
1083 }
1084
1085 // Called by delegate_ when the download target path has been
948 // determined. 1086 // determined.
949 void DownloadItemImpl::OnDownloadTargetDetermined( 1087 void DownloadItemImpl::OnDownloadTargetDetermined(
950 const FilePath& target_path, 1088 const FilePath& target_path,
951 TargetDisposition disposition, 1089 TargetDisposition disposition,
952 content::DownloadDangerType danger_type, 1090 content::DownloadDangerType danger_type,
953 const FilePath& intermediate_path) { 1091 const FilePath& intermediate_path) {
954 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1092 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
955 1093
956 // If the |target_path| is empty, then we consider this download to be 1094 // If the |target_path| is empty, then we consider this download to be
957 // canceled. 1095 // canceled.
(...skipping 20 matching lines...) Expand all
978 // whatever was recorded for consistency. 1116 // whatever was recorded for consistency.
979 OnDownloadRenamedToIntermediateName(last_reason_, FilePath()); 1117 OnDownloadRenamedToIntermediateName(last_reason_, FilePath());
980 return; 1118 return;
981 } 1119 }
982 1120
983 // Rename to intermediate name. 1121 // Rename to intermediate name.
984 // TODO(asanka): Skip this rename if AllDataSaved() is true. This avoids a 1122 // TODO(asanka): Skip this rename if AllDataSaved() is true. This avoids a
985 // spurious rename when we can just rename to the final 1123 // spurious rename when we can just rename to the final
986 // filename. Unnecessary renames may cause bugs like 1124 // filename. Unnecessary renames may cause bugs like
987 // http://crbug.com/74187. 1125 // http://crbug.com/74187.
988 DownloadFileManager::RenameCompletionCallback callback = 1126 DCHECK(!is_save_package_download_);
1127 CHECK(download_file_.get());
1128 DownloadFile::RenameCompletionCallback callback =
989 base::Bind(&DownloadItemImpl::OnDownloadRenamedToIntermediateName, 1129 base::Bind(&DownloadItemImpl::OnDownloadRenamedToIntermediateName,
990 weak_ptr_factory_.GetWeakPtr()); 1130 weak_ptr_factory_.GetWeakPtr());
991 BrowserThread::PostTask( 1131 BrowserThread::PostTask(
992 BrowserThread::FILE, FROM_HERE, 1132 BrowserThread::FILE, FROM_HERE,
993 base::Bind(&DownloadFileManager::RenameDownloadFile, 1133 base::Bind(&DownloadFile::Rename,
994 delegate_->GetDownloadFileManager(), GetGlobalId(), 1134 // Safe because we control download file lifetime.
1135 base::Unretained(download_file_.get()),
995 intermediate_path, false, callback)); 1136 intermediate_path, false, callback));
996 } 1137 }
997 1138
998 void DownloadItemImpl::OnDownloadRenamedToIntermediateName( 1139 void DownloadItemImpl::OnDownloadRenamedToIntermediateName(
999 content::DownloadInterruptReason reason, 1140 content::DownloadInterruptReason reason,
1000 const FilePath& full_path) { 1141 const FilePath& full_path) {
1001 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1142 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1002 if (content::DOWNLOAD_INTERRUPT_REASON_NONE != reason) { 1143 if (content::DOWNLOAD_INTERRUPT_REASON_NONE != reason) {
1003 Interrupt(reason); 1144 Interrupt(reason);
1004 } else { 1145 } else {
(...skipping 16 matching lines...) Expand all
1021 1162
1022 if (state_ != IN_PROGRESS_INTERNAL) 1163 if (state_ != IN_PROGRESS_INTERNAL)
1023 return; 1164 return;
1024 1165
1025 VLOG(20) << __FUNCTION__ << "()" 1166 VLOG(20) << __FUNCTION__ << "()"
1026 << " needs rename = " << NeedsRename() 1167 << " needs rename = " << NeedsRename()
1027 << " " << DebugString(true); 1168 << " " << DebugString(true);
1028 DCHECK(!GetTargetFilePath().empty()); 1169 DCHECK(!GetTargetFilePath().empty());
1029 DCHECK_NE(DANGEROUS, GetSafetyState()); 1170 DCHECK_NE(DANGEROUS, GetSafetyState());
1030 1171
1172 // TODO(rdsmith/benjhayden): Remove as part of SavePackage integration.
1173 if (is_save_package_download_) {
1174 // Avoid doing anything on the file thread; there's nothing we control
1175 // there.
1176 OnDownloadFileReleased();
1177 return;
1178 }
1179
1180 CHECK(download_file_.get());
1031 if (NeedsRename()) { 1181 if (NeedsRename()) {
1032 DownloadFileManager::RenameCompletionCallback callback = 1182 content::DownloadFile::RenameCompletionCallback callback =
1033 base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName, 1183 base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName,
1034 weak_ptr_factory_.GetWeakPtr()); 1184 weak_ptr_factory_.GetWeakPtr());
1035 BrowserThread::PostTask( 1185 BrowserThread::PostTask(
1036 BrowserThread::FILE, FROM_HERE, 1186 BrowserThread::FILE, FROM_HERE,
1037 base::Bind(&DownloadFileManager::RenameDownloadFile, 1187 base::Bind(&DownloadFile::Rename,
1038 delegate_->GetDownloadFileManager(), GetGlobalId(), 1188 base::Unretained(download_file_.get()),
1039 GetTargetFilePath(), true, callback)); 1189 GetTargetFilePath(), true, callback));
1040 } else { 1190 } else {
1041 // Complete the download and release the DownloadFile. 1191 ReleaseDownloadFile();
1042 BrowserThread::PostTask(
1043 BrowserThread::FILE, FROM_HERE,
1044 base::Bind(&DownloadFileManager::CompleteDownload,
1045 delegate_->GetDownloadFileManager(), GetGlobalId(),
1046 base::Bind(&DownloadItemImpl::OnDownloadFileReleased,
1047 weak_ptr_factory_.GetWeakPtr())));
1048 TransitionTo(COMPLETING_INTERNAL);
1049 } 1192 }
1050 } 1193 }
1051 1194
1052 void DownloadItemImpl::OnDownloadRenamedToFinalName( 1195 void DownloadItemImpl::OnDownloadRenamedToFinalName(
1053 content::DownloadInterruptReason reason, 1196 content::DownloadInterruptReason reason,
1054 const FilePath& full_path) { 1197 const FilePath& full_path) {
1055 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1056 1199
1057 // If a cancel or interrupt hit, we'll cancel the DownloadFile, which 1200 // If a cancel or interrupt hit, we'll cancel the DownloadFile, which
1058 // will result in deleting the file on the file thread. So we don't 1201 // will result in deleting the file on the file thread. So we don't
(...skipping 11 matching lines...) Expand all
1070 Interrupt(reason); 1213 Interrupt(reason);
1071 return; 1214 return;
1072 } 1215 }
1073 1216
1074 // full_path is now the current and target file path. 1217 // full_path is now the current and target file path.
1075 DCHECK(!full_path.empty()); 1218 DCHECK(!full_path.empty());
1076 target_path_ = full_path; 1219 target_path_ = full_path;
1077 SetFullPath(full_path); 1220 SetFullPath(full_path);
1078 delegate_->DownloadRenamedToFinalName(this); 1221 delegate_->DownloadRenamedToFinalName(this);
1079 1222
1223 ReleaseDownloadFile();
1224 }
1225
1226 void DownloadItemImpl::ReleaseDownloadFile() {
1080 // Complete the download and release the DownloadFile. 1227 // Complete the download and release the DownloadFile.
1228 DCHECK(!is_save_package_download_);
1229 CHECK(download_file_.get());
1081 BrowserThread::PostTask( 1230 BrowserThread::PostTask(
1082 BrowserThread::FILE, FROM_HERE, 1231 BrowserThread::FILE, FROM_HERE,
1083 base::Bind(&DownloadFileManager::CompleteDownload, 1232 base::Bind(&DownloadFileDetach, base::Passed(download_file_.Pass()),
1084 delegate_->GetDownloadFileManager(), GetGlobalId(),
1085 base::Bind(&DownloadItemImpl::OnDownloadFileReleased, 1233 base::Bind(&DownloadItemImpl::OnDownloadFileReleased,
1086 weak_ptr_factory_.GetWeakPtr()))); 1234 weak_ptr_factory_.GetWeakPtr())));
1235
1236 // We're not completely done with the download item yet, but at this
1237 // point we're committed to complete the download. Cancels (or Interrupts,
1238 // though it's not clear how they could happen) after this point will be
1239 // ignored.
1087 TransitionTo(COMPLETING_INTERNAL); 1240 TransitionTo(COMPLETING_INTERNAL);
1088 } 1241 }
1089 1242
1090 void DownloadItemImpl::OnDownloadFileReleased() { 1243 void DownloadItemImpl::OnDownloadFileReleased() {
1091 if (delegate_->ShouldOpenDownload(this)) 1244 if (delegate_->ShouldOpenDownload(this))
1092 Completed(); 1245 Completed();
1093 else 1246 else
1094 delegate_delayed_complete_ = true; 1247 delegate_delayed_complete_ = true;
1095 } 1248 }
1096 1249
1097 void DownloadItemImpl::DelayedDownloadOpened(bool auto_opened) { 1250 void DownloadItemImpl::DelayedDownloadOpened(bool auto_opened) {
1098 auto_opened_ = auto_opened; 1251 auto_opened_ = auto_opened;
1099 Completed(); 1252 Completed();
1253 UpdateObservers();
asanka 2012/09/28 20:22:42 Why is this call necessary?
Randy Smith (Not in Mondays) 2012/10/09 20:20:19 Hmmm. I think it's left-over from before the inte
1100 } 1254 }
1101 1255
1102 void DownloadItemImpl::Completed() { 1256 void DownloadItemImpl::Completed() {
1103 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1257 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1104 1258
1105 VLOG(20) << __FUNCTION__ << "() " << DebugString(false); 1259 VLOG(20) << __FUNCTION__ << "() " << DebugString(false);
1106 1260
1107 DCHECK(all_data_saved_); 1261 DCHECK(all_data_saved_);
1108 end_time_ = base::Time::Now(); 1262 end_time_ = base::Time::Now();
1109 TransitionTo(COMPLETE_INTERNAL); 1263 TransitionTo(COMPLETE_INTERNAL);
(...skipping 16 matching lines...) Expand all
1126 } 1280 }
1127 } 1281 }
1128 1282
1129 // **** End of Download progression cascade 1283 // **** End of Download progression cascade
1130 1284
1131 bool DownloadItemImpl::NeedsRename() const { 1285 bool DownloadItemImpl::NeedsRename() const {
1132 DCHECK(target_path_.DirName() == current_path_.DirName()); 1286 DCHECK(target_path_.DirName() == current_path_.DirName());
1133 return target_path_ != current_path_; 1287 return target_path_ != current_path_;
1134 } 1288 }
1135 1289
1136 void DownloadItemImpl::ProgressComplete(int64 bytes_so_far,
1137 const std::string& final_hash) {
1138 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1139
1140 hash_ = final_hash;
1141 hash_state_ = "";
1142
1143 received_bytes_ = bytes_so_far;
1144
1145 // If we've received more data than we were expecting (bad server info?),
1146 // revert to 'unknown size mode'.
1147 if (received_bytes_ > total_bytes_)
1148 total_bytes_ = 0;
1149 }
1150
1151 void DownloadItemImpl::TransitionTo(DownloadInternalState new_state) { 1290 void DownloadItemImpl::TransitionTo(DownloadInternalState new_state) {
1152 if (state_ == new_state) 1291 if (state_ == new_state)
1153 return; 1292 return;
1154 1293
1155 DownloadInternalState old_state = state_; 1294 DownloadInternalState old_state = state_;
1156 state_ = new_state; 1295 state_ = new_state;
1157 1296
1158 switch (state_) { 1297 switch (state_) {
1159 case COMPLETING_INTERNAL: 1298 case COMPLETING_INTERNAL:
1160 bound_net_log_.AddEvent( 1299 bound_net_log_.AddEvent(
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
1277 return "COMPLETE"; 1416 return "COMPLETE";
1278 case CANCELLED_INTERNAL: 1417 case CANCELLED_INTERNAL:
1279 return "CANCELLED"; 1418 return "CANCELLED";
1280 case INTERRUPTED_INTERNAL: 1419 case INTERRUPTED_INTERNAL:
1281 return "INTERRUPTED"; 1420 return "INTERRUPTED";
1282 default: 1421 default:
1283 NOTREACHED() << "Unknown download state " << state; 1422 NOTREACHED() << "Unknown download state " << state;
1284 return "unknown"; 1423 return "unknown";
1285 }; 1424 };
1286 } 1425 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698