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

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

Issue 10074001: Initial implementation of the ByteStream refactor. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Checkpoint and merge to LKGR. Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/download/download_file_impl.h" 5 #include "content/browser/download/download_file_impl.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/bind.h"
9 #include "base/file_util.h" 10 #include "base/file_util.h"
11 #include "base/message_loop_proxy.h"
10 #include "content/browser/download/download_create_info.h" 12 #include "content/browser/download/download_create_info.h"
13 #include "content/browser/download/download_interrupt_reasons_impl.h"
14 #include "content/browser/download/download_net_log_parameters.h"
11 #include "content/browser/power_save_blocker.h" 15 #include "content/browser/power_save_blocker.h"
12 #include "content/public/browser/browser_thread.h" 16 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/download_manager.h" 17 #include "content/public/browser/download_manager.h"
18 #include "content/browser/download/download_stats.h"
19 #include "net/base/io_buffer.h"
14 20
15 using content::BrowserThread; 21 using content::BrowserThread;
16 using content::DownloadId; 22 using content::DownloadId;
17 using content::DownloadManager; 23 using content::DownloadManager;
18 24
19 const int kUpdatePeriodMs = 500; 25 const int kUpdatePeriodMs = 500;
20 26
21 DownloadFileImpl::DownloadFileImpl( 27 DownloadFileImpl::DownloadFileImpl(
22 const DownloadCreateInfo* info, 28 const DownloadCreateInfo* info,
23 DownloadRequestHandleInterface* request_handle, 29 DownloadRequestHandleInterface* request_handle,
24 DownloadManager* download_manager, 30 DownloadManager* download_manager,
25 bool calculate_hash, 31 bool calculate_hash,
26 scoped_ptr<PowerSaveBlocker> power_save_blocker, 32 scoped_ptr<PowerSaveBlocker> power_save_blocker,
27 const net::BoundNetLog& bound_net_log) 33 const net::BoundNetLog& bound_net_log)
28 : file_(info->save_info.file_path, 34 : file_(info->save_info.file_path,
29 info->url(), 35 info->url(),
30 info->referrer_url, 36 info->referrer_url,
31 info->received_bytes, 37 info->received_bytes,
32 calculate_hash, 38 calculate_hash,
33 info->save_info.hash_state, 39 info->save_info.hash_state,
34 info->save_info.file_stream, 40 info->save_info.file_stream,
35 bound_net_log), 41 bound_net_log),
42 input_pipe_(info->pipe),
36 id_(info->download_id), 43 id_(info->download_id),
37 request_handle_(request_handle), 44 request_handle_(request_handle),
38 download_manager_(download_manager), 45 download_manager_(download_manager),
46 bound_net_log_(bound_net_log),
47 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
39 power_save_blocker_(power_save_blocker.Pass()) { 48 power_save_blocker_(power_save_blocker.Pass()) {
40 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
41 } 50 }
42 51
43 DownloadFileImpl::~DownloadFileImpl() { 52 DownloadFileImpl::~DownloadFileImpl() {
44 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 53 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
54 // Prevent any future callbacks from reaching us.
55 if (input_pipe_.get())
56 input_pipe_->RegisterSinkCallback(scoped_refptr<base::TaskRunner>(),
57 base::Closure(), 0);
45 } 58 }
46 59
47 // BaseFile delegated functions. 60 // BaseFile delegated functions.
48 net::Error DownloadFileImpl::Initialize() { 61 net::Error DownloadFileImpl::Initialize() {
49 update_timer_.reset(new base::RepeatingTimer<DownloadFileImpl>()); 62 update_timer_.reset(new base::RepeatingTimer<DownloadFileImpl>());
50 return file_.Initialize(); 63 net::Error result = file_.Initialize();
64 if (result != net::OK)
65 return result;
66
67 input_pipe_->RegisterSinkCallback(
68 base::MessageLoopProxy::current(),
69 // Unretained is safe because the callback is nulled in the
70 // destructor.
71 base::Bind(&DownloadFileImpl::PipeActive, base::Unretained(this)),
72 33);
73
74 // Initial pull from the straw.
75 PipeActive();
76
77 return result;
51 } 78 }
52 79
53 net::Error DownloadFileImpl::AppendDataToFile(const char* data, 80 net::Error DownloadFileImpl::AppendDataToFile(const char* data,
54 size_t data_len) { 81 size_t data_len) {
55 if (!update_timer_->IsRunning()) { 82 if (!update_timer_->IsRunning()) {
56 update_timer_->Start(FROM_HERE, 83 update_timer_->Start(FROM_HERE,
57 base::TimeDelta::FromMilliseconds(kUpdatePeriodMs), 84 base::TimeDelta::FromMilliseconds(kUpdatePeriodMs),
58 this, &DownloadFileImpl::SendUpdate); 85 this, &DownloadFileImpl::SendUpdate);
59 } 86 }
60 return file_.AppendDataToFile(data, data_len); 87 return file_.AppendDataToFile(data, data_len);
61 } 88 }
62 89
63 net::Error DownloadFileImpl::Rename(const FilePath& full_path) { 90 net::Error DownloadFileImpl::Rename(const FilePath& full_path) {
64 return file_.Rename(full_path); 91 return file_.Rename(full_path);
65 } 92 }
66 93
67 void DownloadFileImpl::Detach() { 94 void DownloadFileImpl::Detach() {
68 file_.Detach(); 95 file_.Detach();
69 } 96 }
70 97
71 void DownloadFileImpl::Cancel() { 98 void DownloadFileImpl::Cancel() {
72 file_.Cancel(); 99 file_.Cancel();
73 } 100 }
74 101
75 void DownloadFileImpl::Finish() {
76 file_.Finish();
77 update_timer_.reset();
78 }
79
80 void DownloadFileImpl::AnnotateWithSourceInformation() { 102 void DownloadFileImpl::AnnotateWithSourceInformation() {
81 file_.AnnotateWithSourceInformation(); 103 file_.AnnotateWithSourceInformation();
82 } 104 }
83 105
84 FilePath DownloadFileImpl::FullPath() const { 106 FilePath DownloadFileImpl::FullPath() const {
85 return file_.full_path(); 107 return file_.full_path();
86 } 108 }
87 109
88 bool DownloadFileImpl::InProgress() const { 110 bool DownloadFileImpl::InProgress() const {
89 return file_.in_progress(); 111 return file_.in_progress();
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 return base::StringPrintf("{" 150 return base::StringPrintf("{"
129 " id_ = " "%d" 151 " id_ = " "%d"
130 " request_handle = %s" 152 " request_handle = %s"
131 " Base File = %s" 153 " Base File = %s"
132 " }", 154 " }",
133 id_.local(), 155 id_.local(),
134 request_handle_->DebugString().c_str(), 156 request_handle_->DebugString().c_str(),
135 file_.DebugString().c_str()); 157 file_.DebugString().c_str());
136 } 158 }
137 159
160 void DownloadFileImpl::PipeActive() {
161 base::Time start(base::Time::Now());
162 base::Time now;
163 scoped_refptr<net::IOBuffer> incoming_data;
164 size_t length = 0;
165 size_t total_length = 0;
166 size_t num_buffers = 0;
167 content::ByteStream::StreamState state(content::ByteStream::STREAM_EMPTY);
168 content::DownloadInterruptReason reason =
169 content::DOWNLOAD_INTERRUPT_REASON_NONE;
170 base::TimeDelta delta(base::TimeDelta::FromMilliseconds(1000));
171
172 // Take care of any file local activity required.
173 do {
174 state = input_pipe_->GetData(&incoming_data, &length);
175
176 net::Error result = net::OK;
177 switch (state) {
178 case content::ByteStream::STREAM_EMPTY:
179 break;
180 case content::ByteStream::STREAM_HAS_DATA:
181 ++num_buffers;
182 result = AppendDataToFile(incoming_data.get()->data(), length);
183 total_length += length;
184 reason = content::ConvertNetErrorToInterruptReason(
185 result, content::DOWNLOAD_INTERRUPT_FROM_DISK);
186 break;
187 case content::ByteStream::STREAM_COMPLETE:
188 reason = input_pipe_->GetSourceResult();
189 SendUpdate();
190 file_.Finish();
191 update_timer_.reset();
192 break;
193 default:
194 NOTREACHED();
195 break;
196 }
197 now = base::Time::Now();
198 } while (state == content::ByteStream::STREAM_HAS_DATA &&
199 reason == content::DOWNLOAD_INTERRUPT_REASON_NONE &&
200 now - start <= delta);
201
202 // If we're stopping to yield the thread, post a task so we come back.
203 if (state == content::ByteStream::STREAM_HAS_DATA && now - start > delta) {
204 BrowserThread::PostTask(
205 BrowserThread::FILE, FROM_HERE,
206 base::Bind(&DownloadFileImpl::PipeActive, weak_factory_.GetWeakPtr()));
207 }
208
209 if (total_length)
210 download_stats::RecordFileThreadReceiveBuffers(total_length);
211
212 download_stats::RecordContiguousWriteTime(now - start);
213
214 // Take care of communication with our controller.
215 if (reason != content::DOWNLOAD_INTERRUPT_REASON_NONE) {
216 // Error case for both upstream source and file write.
217 // Shut down processing and signal an error to our controller.
218 // Our controller will clean us up.
219 input_pipe_->RegisterSinkCallback(scoped_refptr<base::TaskRunner>(),
220 base::Closure(), 0);
221 weak_factory_.InvalidateWeakPtrs();
222 if (download_manager_.get()) {
223 BrowserThread::PostTask(
224 BrowserThread::UI, FROM_HERE,
225 base::Bind(&DownloadManager::OnDownloadInterrupted,
226 download_manager_, id_.local(),
227 BytesSoFar(), GetHashState(), reason));
228 }
229 } else if (state == content::ByteStream::STREAM_COMPLETE) {
230 // Signal successful completion and shut down processing.
231 input_pipe_->RegisterSinkCallback(scoped_refptr<base::TaskRunner>(),
232 base::Closure(), 0);
233 weak_factory_.InvalidateWeakPtrs();
234 if (download_manager_.get()) {
235 std::string hash;
236 if (!GetHash(&hash) || file_.IsEmptyHash(hash))
237 hash.clear();
238 BrowserThread::PostTask(
239 BrowserThread::UI, FROM_HERE,
240 base::Bind(&DownloadManager::OnResponseCompleted,
241 download_manager_, id_.local(),
242 BytesSoFar(), hash));
243 }
244 }
245 if (bound_net_log_.IsLoggingAllEvents()) {
246 bound_net_log_.AddEvent(
247 net::NetLog::TYPE_DOWNLOAD_PIPE_DRAINED,
248 make_scoped_refptr(new download_net_logs::FilePipeDrainedParameters(
249 total_length, num_buffers)));
250 }
251 }
252
138 void DownloadFileImpl::SendUpdate() { 253 void DownloadFileImpl::SendUpdate() {
139 if (download_manager_.get()) { 254 if (download_manager_.get()) {
140 BrowserThread::PostTask( 255 BrowserThread::PostTask(
141 BrowserThread::UI, FROM_HERE, 256 BrowserThread::UI, FROM_HERE,
142 base::Bind(&DownloadManager::UpdateDownload, 257 base::Bind(&DownloadManager::UpdateDownload,
143 download_manager_, id_.local(), 258 download_manager_, id_.local(),
144 BytesSoFar(), CurrentSpeed(), GetHashState())); 259 BytesSoFar(), CurrentSpeed(), GetHashState()));
145 } 260 }
146 } 261 }
OLDNEW
« no previous file with comments | « content/browser/download/download_file_impl.h ('k') | content/browser/download/download_file_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698