OLD | NEW |
---|---|
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 "storage/browser/blob/blob_url_request_job.h" | 5 #include "storage/browser/blob/blob_url_request_job.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
(...skipping 16 matching lines...) Expand all Loading... | |
27 #include "net/http/http_response_headers.h" | 27 #include "net/http/http_response_headers.h" |
28 #include "net/http/http_response_info.h" | 28 #include "net/http/http_response_info.h" |
29 #include "net/http/http_util.h" | 29 #include "net/http/http_util.h" |
30 #include "net/url_request/url_request.h" | 30 #include "net/url_request/url_request.h" |
31 #include "net/url_request/url_request_context.h" | 31 #include "net/url_request/url_request_context.h" |
32 #include "net/url_request/url_request_error_job.h" | 32 #include "net/url_request/url_request_error_job.h" |
33 #include "net/url_request/url_request_status.h" | 33 #include "net/url_request/url_request_status.h" |
34 #include "storage/browser/blob/file_stream_reader.h" | 34 #include "storage/browser/blob/file_stream_reader.h" |
35 #include "storage/browser/fileapi/file_system_context.h" | 35 #include "storage/browser/fileapi/file_system_context.h" |
36 #include "storage/browser/fileapi/file_system_url.h" | 36 #include "storage/browser/fileapi/file_system_url.h" |
37 #include "storage/common/data_element.h" | |
37 | 38 |
38 namespace storage { | 39 namespace storage { |
39 | 40 |
40 namespace { | 41 namespace { |
41 | 42 |
42 bool IsFileType(BlobData::Item::Type type) { | 43 bool IsFileType(DataElement::Type type) { |
43 switch (type) { | 44 switch (type) { |
44 case BlobData::Item::TYPE_FILE: | 45 case DataElement::TYPE_FILE: |
45 case BlobData::Item::TYPE_FILE_FILESYSTEM: | 46 case DataElement::TYPE_FILE_FILESYSTEM: |
46 return true; | 47 return true; |
47 default: | 48 default: |
48 return false; | 49 return false; |
49 } | 50 } |
50 } | 51 } |
51 | 52 |
52 } // namespace | 53 } // namespace |
53 | 54 |
54 BlobURLRequestJob::BlobURLRequestJob( | 55 BlobURLRequestJob::BlobURLRequestJob( |
55 net::URLRequest* request, | 56 net::URLRequest* request, |
56 net::NetworkDelegate* network_delegate, | 57 net::NetworkDelegate* network_delegate, |
57 const scoped_refptr<BlobData>& blob_data, | 58 scoped_ptr<BlobDataSnapshot> blob_data, |
58 storage::FileSystemContext* file_system_context, | 59 storage::FileSystemContext* file_system_context, |
59 base::MessageLoopProxy* file_thread_proxy) | 60 base::MessageLoopProxy* file_thread_proxy) |
60 : net::URLRequestJob(request, network_delegate), | 61 : net::URLRequestJob(request, network_delegate), |
61 blob_data_(blob_data), | 62 blob_data_(blob_data.Pass()), |
62 file_system_context_(file_system_context), | 63 file_system_context_(file_system_context), |
63 file_thread_proxy_(file_thread_proxy), | 64 file_thread_proxy_(file_thread_proxy), |
64 total_size_(0), | 65 total_size_(0), |
65 remaining_bytes_(0), | 66 remaining_bytes_(0), |
66 pending_get_file_info_count_(0), | 67 pending_get_file_info_count_(0), |
67 current_item_index_(0), | 68 current_item_index_(0), |
68 current_item_offset_(0), | 69 current_item_offset_(0), |
69 error_(false), | 70 error_(false), |
70 byte_range_set_(false), | 71 byte_range_set_(false), |
71 weak_factory_(this) { | 72 weak_factory_(this) { |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
167 void BlobURLRequestJob::DidStart() { | 168 void BlobURLRequestJob::DidStart() { |
168 error_ = false; | 169 error_ = false; |
169 | 170 |
170 // We only support GET request per the spec. | 171 // We only support GET request per the spec. |
171 if (request()->method() != "GET") { | 172 if (request()->method() != "GET") { |
172 NotifyFailure(net::ERR_METHOD_NOT_SUPPORTED); | 173 NotifyFailure(net::ERR_METHOD_NOT_SUPPORTED); |
173 return; | 174 return; |
174 } | 175 } |
175 | 176 |
176 // If the blob data is not present, bail out. | 177 // If the blob data is not present, bail out. |
177 if (!blob_data_.get()) { | 178 if (!blob_data_) { |
178 NotifyFailure(net::ERR_FILE_NOT_FOUND); | 179 NotifyFailure(net::ERR_FILE_NOT_FOUND); |
179 return; | 180 return; |
180 } | 181 } |
181 | 182 |
182 CountSize(); | 183 CountSize(); |
183 } | 184 } |
184 | 185 |
185 bool BlobURLRequestJob::AddItemLength(size_t index, int64 item_length) { | 186 bool BlobURLRequestJob::AddItemLength(size_t index, int64 item_length) { |
186 if (item_length > kint64max - total_size_) { | 187 if (item_length > kint64max - total_size_) { |
187 NotifyFailure(net::ERR_FAILED); | 188 NotifyFailure(net::ERR_FAILED); |
188 return false; | 189 return false; |
189 } | 190 } |
190 | 191 |
191 // Cache the size and add it to the total size. | 192 // Cache the size and add it to the total size. |
192 DCHECK_LT(index, item_length_list_.size()); | 193 DCHECK_LT(index, item_length_list_.size()); |
193 item_length_list_[index] = item_length; | 194 item_length_list_[index] = item_length; |
194 total_size_ += item_length; | 195 total_size_ += item_length; |
195 return true; | 196 return true; |
196 } | 197 } |
197 | 198 |
198 void BlobURLRequestJob::CountSize() { | 199 void BlobURLRequestJob::CountSize() { |
199 pending_get_file_info_count_ = 0; | 200 pending_get_file_info_count_ = 0; |
200 total_size_ = 0; | 201 total_size_ = 0; |
201 item_length_list_.resize(blob_data_->items().size()); | 202 const auto& items = blob_data_->items(); |
203 item_length_list_.resize(items.size()); | |
202 | 204 |
203 for (size_t i = 0; i < blob_data_->items().size(); ++i) { | 205 for (size_t i = 0; i < items.size(); ++i) { |
204 const BlobData::Item& item = blob_data_->items().at(i); | 206 const BlobDataItem& item = *items.at(i); |
205 if (IsFileType(item.type())) { | 207 if (IsFileType(item.type())) { |
206 ++pending_get_file_info_count_; | 208 ++pending_get_file_info_count_; |
207 GetFileStreamReader(i)->GetLength( | 209 GetFileStreamReader(i)->GetLength( |
208 base::Bind(&BlobURLRequestJob::DidGetFileItemLength, | 210 base::Bind(&BlobURLRequestJob::DidGetFileItemLength, |
209 weak_factory_.GetWeakPtr(), i)); | 211 weak_factory_.GetWeakPtr(), i)); |
210 continue; | 212 continue; |
211 } | 213 } |
212 | 214 |
213 if (!AddItemLength(i, item.length())) | 215 if (!AddItemLength(i, item.length())) |
214 return; | 216 return; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
250 return; | 252 return; |
251 | 253 |
252 if (result == net::ERR_UPLOAD_FILE_CHANGED) { | 254 if (result == net::ERR_UPLOAD_FILE_CHANGED) { |
253 NotifyFailure(net::ERR_FILE_NOT_FOUND); | 255 NotifyFailure(net::ERR_FILE_NOT_FOUND); |
254 return; | 256 return; |
255 } else if (result < 0) { | 257 } else if (result < 0) { |
256 NotifyFailure(result); | 258 NotifyFailure(result); |
257 return; | 259 return; |
258 } | 260 } |
259 | 261 |
260 DCHECK_LT(index, blob_data_->items().size()); | 262 auto& items = blob_data_->items(); |
michaeln
2015/01/22 02:18:09
const auto here too and below? (not sure the local
dmurph
2015/01/23 00:10:18
Changed here and elsewhere.
| |
261 const BlobData::Item& item = blob_data_->items().at(index); | 263 DCHECK_LT(index, items.size()); |
264 const BlobDataItem& item = *items.at(index); | |
262 DCHECK(IsFileType(item.type())); | 265 DCHECK(IsFileType(item.type())); |
263 | 266 |
264 uint64 file_length = result; | 267 uint64 file_length = result; |
265 uint64 item_offset = item.offset(); | 268 uint64 item_offset = item.offset(); |
266 uint64 item_length = item.length(); | 269 uint64 item_length = item.length(); |
267 | 270 |
268 if (item_offset > file_length) { | 271 if (item_offset > file_length) { |
269 NotifyFailure(net::ERR_FILE_NOT_FOUND); | 272 NotifyFailure(net::ERR_FILE_NOT_FOUND); |
270 return; | 273 return; |
271 } | 274 } |
(...skipping 11 matching lines...) Expand all Loading... | |
283 | 286 |
284 if (!AddItemLength(index, item_length)) | 287 if (!AddItemLength(index, item_length)) |
285 return; | 288 return; |
286 | 289 |
287 if (--pending_get_file_info_count_ == 0) | 290 if (--pending_get_file_info_count_ == 0) |
288 DidCountSize(net::OK); | 291 DidCountSize(net::OK); |
289 } | 292 } |
290 | 293 |
291 void BlobURLRequestJob::Seek(int64 offset) { | 294 void BlobURLRequestJob::Seek(int64 offset) { |
292 // Skip the initial items that are not in the range. | 295 // Skip the initial items that are not in the range. |
296 auto& items = blob_data_->items(); | |
293 for (current_item_index_ = 0; | 297 for (current_item_index_ = 0; |
294 current_item_index_ < blob_data_->items().size() && | 298 current_item_index_ < items.size() && |
295 offset >= item_length_list_[current_item_index_]; | 299 offset >= item_length_list_[current_item_index_]; |
296 ++current_item_index_) { | 300 ++current_item_index_) { |
297 offset -= item_length_list_[current_item_index_]; | 301 offset -= item_length_list_[current_item_index_]; |
298 } | 302 } |
299 | 303 |
300 // Set the offset that need to jump to for the first item in the range. | 304 // Set the offset that need to jump to for the first item in the range. |
301 current_item_offset_ = offset; | 305 current_item_offset_ = offset; |
302 | 306 |
303 if (offset == 0) | 307 if (offset == 0) |
304 return; | 308 return; |
305 | 309 |
306 // Adjust the offset of the first stream if it is of file type. | 310 // Adjust the offset of the first stream if it is of file type. |
307 const BlobData::Item& item = blob_data_->items().at(current_item_index_); | 311 const BlobDataItem& item = *items.at(current_item_index_); |
308 if (IsFileType(item.type())) { | 312 if (IsFileType(item.type())) { |
309 DeleteCurrentFileReader(); | 313 DeleteCurrentFileReader(); |
310 CreateFileStreamReader(current_item_index_, offset); | 314 CreateFileStreamReader(current_item_index_, offset); |
311 } | 315 } |
312 } | 316 } |
313 | 317 |
314 bool BlobURLRequestJob::ReadItem() { | 318 bool BlobURLRequestJob::ReadItem() { |
315 // Are we done with reading all the blob data? | 319 // Are we done with reading all the blob data? |
316 if (remaining_bytes_ == 0) | 320 if (remaining_bytes_ == 0) |
317 return true; | 321 return true; |
318 | 322 |
323 auto& items = blob_data_->items(); | |
319 // If we get to the last item but still expect something to read, bail out | 324 // If we get to the last item but still expect something to read, bail out |
320 // since something is wrong. | 325 // since something is wrong. |
321 if (current_item_index_ >= blob_data_->items().size()) { | 326 if (current_item_index_ >= items.size()) { |
322 NotifyFailure(net::ERR_FAILED); | 327 NotifyFailure(net::ERR_FAILED); |
323 return false; | 328 return false; |
324 } | 329 } |
325 | 330 |
326 // Compute the bytes to read for current item. | 331 // Compute the bytes to read for current item. |
327 int bytes_to_read = ComputeBytesToRead(); | 332 int bytes_to_read = ComputeBytesToRead(); |
328 | 333 |
329 // If nothing to read for current item, advance to next item. | 334 // If nothing to read for current item, advance to next item. |
330 if (bytes_to_read == 0) { | 335 if (bytes_to_read == 0) { |
331 AdvanceItem(); | 336 AdvanceItem(); |
332 return ReadItem(); | 337 return ReadItem(); |
333 } | 338 } |
334 | 339 |
335 // Do the reading. | 340 // Do the reading. |
336 const BlobData::Item& item = blob_data_->items().at(current_item_index_); | 341 const BlobDataItem& item = *items.at(current_item_index_); |
337 if (item.type() == BlobData::Item::TYPE_BYTES) | 342 if (item.type() == DataElement::TYPE_BYTES) |
338 return ReadBytesItem(item, bytes_to_read); | 343 return ReadBytesItem(item, bytes_to_read); |
339 if (IsFileType(item.type())) { | 344 if (IsFileType(item.type())) { |
340 return ReadFileItem(GetFileStreamReader(current_item_index_), | 345 return ReadFileItem(GetFileStreamReader(current_item_index_), |
341 bytes_to_read); | 346 bytes_to_read); |
342 } | 347 } |
343 NOTREACHED(); | 348 NOTREACHED(); |
344 return false; | 349 return false; |
345 } | 350 } |
346 | 351 |
347 void BlobURLRequestJob::AdvanceItem() { | 352 void BlobURLRequestJob::AdvanceItem() { |
(...skipping 15 matching lines...) Expand all Loading... | |
363 | 368 |
364 // Subtract the remaining bytes. | 369 // Subtract the remaining bytes. |
365 remaining_bytes_ -= result; | 370 remaining_bytes_ -= result; |
366 DCHECK_GE(remaining_bytes_, 0); | 371 DCHECK_GE(remaining_bytes_, 0); |
367 | 372 |
368 // Adjust the read buffer. | 373 // Adjust the read buffer. |
369 read_buf_->DidConsume(result); | 374 read_buf_->DidConsume(result); |
370 DCHECK_GE(read_buf_->BytesRemaining(), 0); | 375 DCHECK_GE(read_buf_->BytesRemaining(), 0); |
371 } | 376 } |
372 | 377 |
373 bool BlobURLRequestJob::ReadBytesItem(const BlobData::Item& item, | 378 bool BlobURLRequestJob::ReadBytesItem(const BlobDataItem& item, |
374 int bytes_to_read) { | 379 int bytes_to_read) { |
375 DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read); | 380 DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read); |
376 | 381 |
377 memcpy(read_buf_->data(), | 382 memcpy(read_buf_->data(), |
378 item.bytes() + item.offset() + current_item_offset_, | 383 item.bytes() + item.offset() + current_item_offset_, |
379 bytes_to_read); | 384 bytes_to_read); |
380 | 385 |
381 AdvanceBytesRead(bytes_to_read); | 386 AdvanceBytesRead(bytes_to_read); |
382 return true; | 387 return true; |
383 } | 388 } |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
548 | 553 |
549 response_info_.reset(new net::HttpResponseInfo()); | 554 response_info_.reset(new net::HttpResponseInfo()); |
550 response_info_->headers = headers; | 555 response_info_->headers = headers; |
551 | 556 |
552 set_expected_content_size(remaining_bytes_); | 557 set_expected_content_size(remaining_bytes_); |
553 | 558 |
554 NotifyHeadersComplete(); | 559 NotifyHeadersComplete(); |
555 } | 560 } |
556 | 561 |
557 FileStreamReader* BlobURLRequestJob::GetFileStreamReader(size_t index) { | 562 FileStreamReader* BlobURLRequestJob::GetFileStreamReader(size_t index) { |
558 DCHECK_LT(index, blob_data_->items().size()); | 563 auto& items = blob_data_->items(); |
559 const BlobData::Item& item = blob_data_->items().at(index); | 564 DCHECK_LT(index, items.size()); |
565 const BlobDataItem& item = *items.at(index); | |
560 if (!IsFileType(item.type())) | 566 if (!IsFileType(item.type())) |
561 return NULL; | 567 return NULL; |
562 if (index_to_reader_.find(index) == index_to_reader_.end()) | 568 if (index_to_reader_.find(index) == index_to_reader_.end()) |
563 CreateFileStreamReader(index, 0); | 569 CreateFileStreamReader(index, 0); |
564 DCHECK(index_to_reader_[index]); | 570 DCHECK(index_to_reader_[index]); |
565 return index_to_reader_[index]; | 571 return index_to_reader_[index]; |
566 } | 572 } |
567 | 573 |
568 void BlobURLRequestJob::CreateFileStreamReader(size_t index, | 574 void BlobURLRequestJob::CreateFileStreamReader(size_t index, |
569 int64 additional_offset) { | 575 int64 additional_offset) { |
570 DCHECK_LT(index, blob_data_->items().size()); | 576 auto& items = blob_data_->items(); |
571 const BlobData::Item& item = blob_data_->items().at(index); | 577 DCHECK_LT(index, items.size()); |
578 const BlobDataItem& item = *items.at(index); | |
572 DCHECK(IsFileType(item.type())); | 579 DCHECK(IsFileType(item.type())); |
573 DCHECK_EQ(0U, index_to_reader_.count(index)); | 580 DCHECK_EQ(0U, index_to_reader_.count(index)); |
574 | 581 |
575 FileStreamReader* reader = NULL; | 582 FileStreamReader* reader = NULL; |
576 switch (item.type()) { | 583 switch (item.type()) { |
577 case BlobData::Item::TYPE_FILE: | 584 case DataElement::TYPE_FILE: |
578 reader = FileStreamReader::CreateForLocalFile( | 585 reader = FileStreamReader::CreateForLocalFile( |
579 file_thread_proxy_.get(), | 586 file_thread_proxy_.get(), |
580 item.path(), | 587 item.path(), |
581 item.offset() + additional_offset, | 588 item.offset() + additional_offset, |
582 item.expected_modification_time()); | 589 item.expected_modification_time()); |
583 break; | 590 break; |
584 case BlobData::Item::TYPE_FILE_FILESYSTEM: | 591 case DataElement::TYPE_FILE_FILESYSTEM: |
585 reader = file_system_context_ | 592 reader = file_system_context_ |
586 ->CreateFileStreamReader( | 593 ->CreateFileStreamReader( |
587 storage::FileSystemURL(file_system_context_->CrackURL( | 594 storage::FileSystemURL(file_system_context_->CrackURL( |
588 item.filesystem_url())), | 595 item.filesystem_url())), |
589 item.offset() + additional_offset, | 596 item.offset() + additional_offset, |
590 item.length() == std::numeric_limits<uint64>::max() | 597 item.length() == std::numeric_limits<uint64>::max() |
591 ? storage::kMaximumLength | 598 ? storage::kMaximumLength |
592 : item.length() - additional_offset, | 599 : item.length() - additional_offset, |
593 item.expected_modification_time()) | 600 item.expected_modification_time()) |
594 .release(); | 601 .release(); |
595 break; | 602 break; |
596 default: | 603 default: |
597 NOTREACHED(); | 604 NOTREACHED(); |
598 } | 605 } |
599 DCHECK(reader); | 606 DCHECK(reader); |
600 index_to_reader_[index] = reader; | 607 index_to_reader_[index] = reader; |
601 } | 608 } |
602 | 609 |
603 } // namespace storage | 610 } // namespace storage |
OLD | NEW |