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

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: 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"
11 #include "content/public/browser/browser_thread.h" 13 #include "content/public/browser/browser_thread.h"
14 #include "content/browser/download/download_interrupt_reasons_impl.h"
12 #include "content/public/browser/download_manager.h" 15 #include "content/public/browser/download_manager.h"
16 #include "content/browser/download/download_stats.h"
17 #include "net/base/io_buffer.h"
13 18
14 using content::BrowserThread; 19 using content::BrowserThread;
15 using content::DownloadId; 20 using content::DownloadId;
16 using content::DownloadManager; 21 using content::DownloadManager;
17 22
18 DownloadFileImpl::DownloadFileImpl( 23 DownloadFileImpl::DownloadFileImpl(
19 const DownloadCreateInfo* info, 24 const DownloadCreateInfo* info,
20 DownloadRequestHandleInterface* request_handle, 25 DownloadRequestHandleInterface* request_handle,
21 DownloadManager* download_manager, 26 DownloadManager* download_manager,
22 bool calculate_hash, 27 bool calculate_hash,
23 const net::BoundNetLog& bound_net_log) 28 const net::BoundNetLog& bound_net_log)
24 : file_(info->save_info.file_path, 29 : file_(info->save_info.file_path,
25 info->url(), 30 info->url(),
26 info->referrer_url, 31 info->referrer_url,
27 info->received_bytes, 32 info->received_bytes,
28 calculate_hash, 33 calculate_hash,
29 info->save_info.hash_state, 34 info->save_info.hash_state,
30 info->save_info.file_stream, 35 info->save_info.file_stream,
31 bound_net_log), 36 bound_net_log),
37 input_pipe_(info->pipe),
32 id_(info->download_id), 38 id_(info->download_id),
33 request_handle_(request_handle), 39 request_handle_(request_handle),
34 download_manager_(download_manager) { 40 download_manager_(download_manager) {
35 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 41 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
36 } 42 }
37 43
38 DownloadFileImpl::~DownloadFileImpl() { 44 DownloadFileImpl::~DownloadFileImpl() {
39 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 45 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
46 // Prevent any future callbacks from reaching us.
47 if (input_pipe_.get())
48 input_pipe_->RegisterSinkCallback(scoped_refptr<base::TaskRunner>(),
49 base::Closure());
40 } 50 }
41 51
42 // BaseFile delegated functions. 52 // BaseFile delegated functions.
43 net::Error DownloadFileImpl::Initialize() { 53 net::Error DownloadFileImpl::Initialize() {
44 return file_.Initialize(); 54 net::Error result = file_.Initialize();
55 if (result != net::OK)
56 return result;
57
58 input_pipe_->RegisterSinkCallback(
59 base::MessageLoopProxy::current(),
60 // Unretained is safe because the callback is nulled in the
61 // destructor.
62 base::Bind(&DownloadFileImpl::PipeActive, base::Unretained(this)));
63
64 // Initial pull from the straw.
65 PipeActive();
66
67 return result;
45 } 68 }
46 69
47 net::Error DownloadFileImpl::AppendDataToFile(const char* data, 70 net::Error DownloadFileImpl::AppendDataToFile(const char* data,
48 size_t data_len) { 71 size_t data_len) {
49 return file_.AppendDataToFile(data, data_len); 72 return file_.AppendDataToFile(data, data_len);
50 } 73 }
51 74
52 net::Error DownloadFileImpl::Rename(const FilePath& full_path) { 75 net::Error DownloadFileImpl::Rename(const FilePath& full_path) {
53 return file_.Rename(full_path); 76 return file_.Rename(full_path);
54 } 77 }
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 std::string DownloadFileImpl::DebugString() const { 138 std::string DownloadFileImpl::DebugString() const {
116 return base::StringPrintf("{" 139 return base::StringPrintf("{"
117 " id_ = " "%d" 140 " id_ = " "%d"
118 " request_handle = %s" 141 " request_handle = %s"
119 " Base File = %s" 142 " Base File = %s"
120 " }", 143 " }",
121 id_.local(), 144 id_.local(),
122 request_handle_->DebugString().c_str(), 145 request_handle_->DebugString().c_str(),
123 file_.DebugString().c_str()); 146 file_.DebugString().c_str());
124 } 147 }
148
149 void DownloadFileImpl::PipeActive() {
150 scoped_refptr<net::IOBuffer> incoming_data;
151 size_t length = 0;
152 size_t total_length = 0;
153 content::ByteStream::StreamState state(content::ByteStream::STREAM_EMPTY);
154 content::DownloadInterruptReason reason =
155 content::DOWNLOAD_INTERRUPT_REASON_NONE;
156
157 // Take care of any file local activity required.
158 do {
159 state = input_pipe_->GetData(&incoming_data, &length);
160
161 net::Error result = net::OK;
162 switch (state) {
163 case content::ByteStream::STREAM_EMPTY:
164 break;
165 case content::ByteStream::STREAM_NON_EMPTY:
166 result = AppendDataToFile(incoming_data.get()->data(), length);
167 total_length += length;
168 reason = content::ConvertNetErrorToInterruptReason(
169 result, content::DOWNLOAD_INTERRUPT_FROM_DISK);
170 break;
171 case content::ByteStream::STREAM_COMPLETE:
172 reason = input_pipe_->GetSourceResult();
173 if (reason != content::DOWNLOAD_INTERRUPT_REASON_NONE)
174 Finish();
175 break;
176 default:
177 NOTREACHED();
178 break;
179 }
180 } while (state == content::ByteStream::STREAM_NON_EMPTY &&
181 reason == content::DOWNLOAD_INTERRUPT_REASON_NONE);
182
183 if (total_length)
184 download_stats::RecordFileThreadReceiveBuffers(total_length);
185
186 // Take care of communication with our controller.
187 if (reason != content::DOWNLOAD_INTERRUPT_REASON_NONE) {
188 // Error case for both upstream source and file write.
189 // Shut down processing and signal an error to our controller.
190 // Our controller will clean us up.
191 input_pipe_->RegisterSinkCallback(scoped_refptr<base::TaskRunner>(),
192 base::Closure());
193 if (download_manager_.get()) {
194 BrowserThread::PostTask(
195 BrowserThread::UI, FROM_HERE,
196 base::Bind(&DownloadManager::OnDownloadInterrupted,
197 download_manager_, id_.local(),
198 BytesSoFar(), GetHashState(), reason));
199 }
200 } else if (state == content::ByteStream::STREAM_COMPLETE) {
201 // Signal successful completion. Processing shutdown shouldn't
202 // be necessary, but it can't hurt to make sure.
203 input_pipe_->RegisterSinkCallback(scoped_refptr<base::TaskRunner>(),
204 base::Closure());
205 if (download_manager_.get()) {
206 std::string hash;
207 if (!GetHash(&hash) || file_.IsEmptyHash(hash))
208 hash.clear();
209 BrowserThread::PostTask(
210 BrowserThread::UI, FROM_HERE,
211 base::Bind(&DownloadManager::OnResponseCompleted,
212 download_manager_, id_.local(),
213 BytesSoFar(), hash));
214 }
215 }
216 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698