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

Side by Side Diff: net/url_request/url_request_file_job.cc

Issue 1439953006: Reland: URLRequestJob: change ReadRawData contract (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address David's comment Created 5 years, 1 month 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
« no previous file with comments | « net/url_request/url_request_file_job.h ('k') | net/url_request/url_request_ftp_job.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 // For loading files, we make use of overlapped i/o to ensure that reading from 5 // For loading files, we make use of overlapped i/o to ensure that reading from
6 // the filesystem (e.g., a network filesystem) does not block the calling 6 // the filesystem (e.g., a network filesystem) does not block the calling
7 // thread. An alternative approach would be to use a background thread or pool 7 // thread. An alternative approach would be to use a background thread or pool
8 // of threads, but it seems better to leverage the operating system's ability 8 // of threads, but it seems better to leverage the operating system's ability
9 // to do background file reads for us. 9 // to do background file reads for us.
10 // 10 //
(...skipping 15 matching lines...) Expand all
26 #include "base/strings/string_util.h" 26 #include "base/strings/string_util.h"
27 #include "base/synchronization/lock.h" 27 #include "base/synchronization/lock.h"
28 #include "base/task_runner.h" 28 #include "base/task_runner.h"
29 #include "base/threading/thread_restrictions.h" 29 #include "base/threading/thread_restrictions.h"
30 #include "build/build_config.h" 30 #include "build/build_config.h"
31 #include "net/base/file_stream.h" 31 #include "net/base/file_stream.h"
32 #include "net/base/filename_util.h" 32 #include "net/base/filename_util.h"
33 #include "net/base/io_buffer.h" 33 #include "net/base/io_buffer.h"
34 #include "net/base/load_flags.h" 34 #include "net/base/load_flags.h"
35 #include "net/base/mime_util.h" 35 #include "net/base/mime_util.h"
36 #include "net/base/net_errors.h"
37 #include "net/filter/filter.h" 36 #include "net/filter/filter.h"
38 #include "net/http/http_util.h" 37 #include "net/http/http_util.h"
39 #include "net/url_request/url_request_error_job.h" 38 #include "net/url_request/url_request_error_job.h"
40 #include "net/url_request/url_request_file_dir_job.h" 39 #include "net/url_request/url_request_file_dir_job.h"
41 #include "url/gurl.h" 40 #include "url/gurl.h"
42 41
43 #if defined(OS_WIN) 42 #if defined(OS_WIN)
44 #include "base/win/shortcut.h" 43 #include "base/win/shortcut.h"
45 #endif 44 #endif
46 45
47 namespace net { 46 namespace net {
48 47
49 URLRequestFileJob::FileMetaInfo::FileMetaInfo() 48 URLRequestFileJob::FileMetaInfo::FileMetaInfo()
50 : file_size(0), 49 : file_size(0),
51 mime_type_result(false), 50 mime_type_result(false),
52 file_exists(false), 51 file_exists(false),
53 is_directory(false) { 52 is_directory(false) {
54 } 53 }
55 54
56 URLRequestFileJob::URLRequestFileJob( 55 URLRequestFileJob::URLRequestFileJob(
57 URLRequest* request, 56 URLRequest* request,
58 NetworkDelegate* network_delegate, 57 NetworkDelegate* network_delegate,
59 const base::FilePath& file_path, 58 const base::FilePath& file_path,
60 const scoped_refptr<base::TaskRunner>& file_task_runner) 59 const scoped_refptr<base::TaskRunner>& file_task_runner)
61 : URLRequestJob(request, network_delegate), 60 : URLRequestJob(request, network_delegate),
62 file_path_(file_path), 61 file_path_(file_path),
63 stream_(new FileStream(file_task_runner)), 62 stream_(new FileStream(file_task_runner)),
64 file_task_runner_(file_task_runner), 63 file_task_runner_(file_task_runner),
65 remaining_bytes_(0), 64 remaining_bytes_(0),
65 range_parse_result_(OK),
66 weak_ptr_factory_(this) {} 66 weak_ptr_factory_(this) {}
67 67
68 void URLRequestFileJob::Start() { 68 void URLRequestFileJob::Start() {
69 FileMetaInfo* meta_info = new FileMetaInfo(); 69 FileMetaInfo* meta_info = new FileMetaInfo();
70 file_task_runner_->PostTaskAndReply( 70 file_task_runner_->PostTaskAndReply(
71 FROM_HERE, 71 FROM_HERE,
72 base::Bind(&URLRequestFileJob::FetchMetaInfo, file_path_, 72 base::Bind(&URLRequestFileJob::FetchMetaInfo, file_path_,
73 base::Unretained(meta_info)), 73 base::Unretained(meta_info)),
74 base::Bind(&URLRequestFileJob::DidFetchMetaInfo, 74 base::Bind(&URLRequestFileJob::DidFetchMetaInfo,
75 weak_ptr_factory_.GetWeakPtr(), 75 weak_ptr_factory_.GetWeakPtr(),
76 base::Owned(meta_info))); 76 base::Owned(meta_info)));
77 } 77 }
78 78
79 void URLRequestFileJob::Kill() { 79 void URLRequestFileJob::Kill() {
80 stream_.reset(); 80 stream_.reset();
81 weak_ptr_factory_.InvalidateWeakPtrs(); 81 weak_ptr_factory_.InvalidateWeakPtrs();
82 82
83 URLRequestJob::Kill(); 83 URLRequestJob::Kill();
84 } 84 }
85 85
86 bool URLRequestFileJob::ReadRawData(IOBuffer* dest, 86 int URLRequestFileJob::ReadRawData(IOBuffer* dest, int dest_size) {
87 int dest_size,
88 int* bytes_read) {
89 DCHECK_NE(dest_size, 0); 87 DCHECK_NE(dest_size, 0);
90 DCHECK(bytes_read);
91 DCHECK_GE(remaining_bytes_, 0); 88 DCHECK_GE(remaining_bytes_, 0);
92 89
93 if (remaining_bytes_ < dest_size) 90 if (remaining_bytes_ < dest_size)
94 dest_size = static_cast<int>(remaining_bytes_); 91 dest_size = remaining_bytes_;
95 92
96 // If we should copy zero bytes because |remaining_bytes_| is zero, short 93 // If we should copy zero bytes because |remaining_bytes_| is zero, short
97 // circuit here. 94 // circuit here.
98 if (!dest_size) { 95 if (!dest_size)
99 *bytes_read = 0; 96 return 0;
100 return true;
101 }
102 97
103 int rv = stream_->Read(dest, 98 int rv = stream_->Read(dest,
104 dest_size, 99 dest_size,
105 base::Bind(&URLRequestFileJob::DidRead, 100 base::Bind(&URLRequestFileJob::DidRead,
106 weak_ptr_factory_.GetWeakPtr(), 101 weak_ptr_factory_.GetWeakPtr(),
107 make_scoped_refptr(dest))); 102 make_scoped_refptr(dest)));
108 if (rv >= 0) { 103 if (rv >= 0) {
109 // Data is immediately available.
110 *bytes_read = rv;
111 remaining_bytes_ -= rv; 104 remaining_bytes_ -= rv;
112 DCHECK_GE(remaining_bytes_, 0); 105 DCHECK_GE(remaining_bytes_, 0);
113 return true;
114 } 106 }
115 107
116 // Otherwise, a read error occured. We may just need to wait... 108 return rv;
117 if (rv == ERR_IO_PENDING) {
118 SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
119 } else {
120 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv));
121 }
122 return false;
123 } 109 }
124 110
125 bool URLRequestFileJob::IsRedirectResponse(GURL* location, 111 bool URLRequestFileJob::IsRedirectResponse(GURL* location,
126 int* http_status_code) { 112 int* http_status_code) {
127 if (meta_info_.is_directory) { 113 if (meta_info_.is_directory) {
128 // This happens when we discovered the file is a directory, so needs a 114 // This happens when we discovered the file is a directory, so needs a
129 // slash at the end of the path. 115 // slash at the end of the path.
130 std::string new_path = request_->url().path(); 116 std::string new_path = request_->url().path();
131 new_path.push_back('/'); 117 new_path.push_back('/');
132 GURL::Replacements replacements; 118 GURL::Replacements replacements;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 *mime_type = meta_info_.mime_type; 158 *mime_type = meta_info_.mime_type;
173 return true; 159 return true;
174 } 160 }
175 return false; 161 return false;
176 } 162 }
177 163
178 void URLRequestFileJob::SetExtraRequestHeaders( 164 void URLRequestFileJob::SetExtraRequestHeaders(
179 const HttpRequestHeaders& headers) { 165 const HttpRequestHeaders& headers) {
180 std::string range_header; 166 std::string range_header;
181 if (headers.GetHeader(HttpRequestHeaders::kRange, &range_header)) { 167 if (headers.GetHeader(HttpRequestHeaders::kRange, &range_header)) {
182 // We only care about "Range" header here. 168 // This job only cares about the Range header. This method stashes the value
169 // for later use in DidOpen(), which is responsible for some of the range
170 // validation as well. NotifyStartError is not legal to call here since
171 // the job has not started.
183 std::vector<HttpByteRange> ranges; 172 std::vector<HttpByteRange> ranges;
184 if (HttpUtil::ParseRangeHeader(range_header, &ranges)) { 173 if (HttpUtil::ParseRangeHeader(range_header, &ranges)) {
185 if (ranges.size() == 1) { 174 if (ranges.size() == 1) {
186 byte_range_ = ranges[0]; 175 byte_range_ = ranges[0];
187 } else { 176 } else {
188 // We don't support multiple range requests in one single URL request, 177 // We don't support multiple range requests in one single URL request,
189 // because we need to do multipart encoding here. 178 // because we need to do multipart encoding here.
190 // TODO(hclam): decide whether we want to support multiple range 179 // TODO(hclam): decide whether we want to support multiple range
191 // requests. 180 // requests.
192 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, 181 range_parse_result_ = net::ERR_REQUEST_RANGE_NOT_SATISFIABLE;
193 ERR_REQUEST_RANGE_NOT_SATISFIABLE));
194 } 182 }
195 } 183 }
196 } 184 }
197 } 185 }
198 186
199 void URLRequestFileJob::OnSeekComplete(int64 result) { 187 void URLRequestFileJob::OnSeekComplete(int64 result) {
200 } 188 }
201 189
202 void URLRequestFileJob::OnReadComplete(IOBuffer* buf, int result) { 190 void URLRequestFileJob::OnReadComplete(IOBuffer* buf, int result) {
203 } 191 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 base::File::FLAG_ASYNC; 232 base::File::FLAG_ASYNC;
245 int rv = stream_->Open(file_path_, flags, 233 int rv = stream_->Open(file_path_, flags,
246 base::Bind(&URLRequestFileJob::DidOpen, 234 base::Bind(&URLRequestFileJob::DidOpen,
247 weak_ptr_factory_.GetWeakPtr())); 235 weak_ptr_factory_.GetWeakPtr()));
248 if (rv != ERR_IO_PENDING) 236 if (rv != ERR_IO_PENDING)
249 DidOpen(rv); 237 DidOpen(rv);
250 } 238 }
251 239
252 void URLRequestFileJob::DidOpen(int result) { 240 void URLRequestFileJob::DidOpen(int result) {
253 if (result != OK) { 241 if (result != OK) {
254 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result)); 242 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result));
243 return;
244 }
245
246 if (range_parse_result_ != net::OK) {
247 NotifyStartError(
248 URLRequestStatus(URLRequestStatus::FAILED, range_parse_result_));
255 return; 249 return;
256 } 250 }
257 251
258 if (!byte_range_.ComputeBounds(meta_info_.file_size)) { 252 if (!byte_range_.ComputeBounds(meta_info_.file_size)) {
259 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, 253 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED,
260 ERR_REQUEST_RANGE_NOT_SATISFIABLE)); 254 net::ERR_REQUEST_RANGE_NOT_SATISFIABLE));
261 return; 255 return;
262 } 256 }
263 257
264 remaining_bytes_ = byte_range_.last_byte_position() - 258 remaining_bytes_ = byte_range_.last_byte_position() -
265 byte_range_.first_byte_position() + 1; 259 byte_range_.first_byte_position() + 1;
266 DCHECK_GE(remaining_bytes_, 0); 260 DCHECK_GE(remaining_bytes_, 0);
267 261
268 if (remaining_bytes_ > 0 && byte_range_.first_byte_position() != 0) { 262 if (remaining_bytes_ > 0 && byte_range_.first_byte_position() != 0) {
269 int rv = stream_->Seek(byte_range_.first_byte_position(), 263 int rv = stream_->Seek(byte_range_.first_byte_position(),
270 base::Bind(&URLRequestFileJob::DidSeek, 264 base::Bind(&URLRequestFileJob::DidSeek,
271 weak_ptr_factory_.GetWeakPtr())); 265 weak_ptr_factory_.GetWeakPtr()));
272 if (rv != ERR_IO_PENDING) { 266 if (rv != ERR_IO_PENDING) {
273 // stream_->Seek() failed, so pass an intentionally erroneous value 267 // stream_->Seek() failed, so pass an intentionally erroneous value
274 // into DidSeek(). 268 // into DidSeek().
275 DidSeek(-1); 269 DidSeek(-1);
276 } 270 }
277 } else { 271 } else {
278 // We didn't need to call stream_->Seek() at all, so we pass to DidSeek() 272 // We didn't need to call stream_->Seek() at all, so we pass to DidSeek()
279 // the value that would mean seek success. This way we skip the code 273 // the value that would mean seek success. This way we skip the code
280 // handling seek failure. 274 // handling seek failure.
281 DidSeek(byte_range_.first_byte_position()); 275 DidSeek(byte_range_.first_byte_position());
282 } 276 }
283 } 277 }
284 278
285 void URLRequestFileJob::DidSeek(int64 result) { 279 void URLRequestFileJob::DidSeek(int64 result) {
286 OnSeekComplete(result); 280 OnSeekComplete(result);
287 if (result != byte_range_.first_byte_position()) { 281 if (result != byte_range_.first_byte_position()) {
288 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, 282 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED,
289 ERR_REQUEST_RANGE_NOT_SATISFIABLE)); 283 ERR_REQUEST_RANGE_NOT_SATISFIABLE));
290 return; 284 return;
291 } 285 }
292 286
293 set_expected_content_size(remaining_bytes_); 287 set_expected_content_size(remaining_bytes_);
294 NotifyHeadersComplete(); 288 NotifyHeadersComplete();
295 } 289 }
296 290
297 void URLRequestFileJob::DidRead(scoped_refptr<IOBuffer> buf, int result) { 291 void URLRequestFileJob::DidRead(scoped_refptr<IOBuffer> buf, int result) {
298 if (result > 0) { 292 if (result >= 0) {
299 SetStatus(URLRequestStatus()); // Clear the IO_PENDING status
300 remaining_bytes_ -= result; 293 remaining_bytes_ -= result;
301 DCHECK_GE(remaining_bytes_, 0); 294 DCHECK_GE(remaining_bytes_, 0);
302 } 295 }
303 296
304 OnReadComplete(buf.get(), result); 297 OnReadComplete(buf.get(), result);
305 buf = NULL; 298 buf = NULL;
306 299
307 if (result == 0) { 300 ReadRawDataComplete(result);
308 NotifyDone(URLRequestStatus());
309 } else if (result < 0) {
310 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result));
311 }
312
313 NotifyReadComplete(result);
314 } 301 }
315 302
316 } // namespace net 303 } // namespace net
OLDNEW
« no previous file with comments | « net/url_request/url_request_file_job.h ('k') | net/url_request/url_request_ftp_job.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698