| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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_reader.h" | 5 #include "storage/browser/blob/blob_reader.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <limits> | 10 #include <limits> |
| 11 #include <utility> | 11 #include <utility> |
| 12 | 12 |
| 13 #include "base/bind.h" | 13 #include "base/bind.h" |
| 14 #include "base/callback_helpers.h" |
| 14 #include "base/sequenced_task_runner.h" | 15 #include "base/sequenced_task_runner.h" |
| 15 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
| 16 #include "base/time/time.h" | 17 #include "base/time/time.h" |
| 17 #include "base/trace_event/trace_event.h" | 18 #include "base/trace_event/trace_event.h" |
| 18 #include "net/base/io_buffer.h" | 19 #include "net/base/io_buffer.h" |
| 19 #include "net/base/net_errors.h" | 20 #include "net/base/net_errors.h" |
| 20 #include "net/disk_cache/disk_cache.h" | 21 #include "net/disk_cache/disk_cache.h" |
| 21 #include "storage/browser/blob/blob_data_handle.h" | 22 #include "storage/browser/blob/blob_data_handle.h" |
| 22 #include "storage/browser/blob/blob_data_snapshot.h" | 23 #include "storage/browser/blob/blob_data_snapshot.h" |
| 23 #include "storage/browser/fileapi/file_stream_reader.h" | 24 #include "storage/browser/fileapi/file_stream_reader.h" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 41 BlobReader::FileStreamReaderProvider::~FileStreamReaderProvider() {} | 42 BlobReader::FileStreamReaderProvider::~FileStreamReaderProvider() {} |
| 42 | 43 |
| 43 BlobReader::BlobReader( | 44 BlobReader::BlobReader( |
| 44 const BlobDataHandle* blob_handle, | 45 const BlobDataHandle* blob_handle, |
| 45 scoped_ptr<FileStreamReaderProvider> file_stream_provider, | 46 scoped_ptr<FileStreamReaderProvider> file_stream_provider, |
| 46 base::SequencedTaskRunner* file_task_runner) | 47 base::SequencedTaskRunner* file_task_runner) |
| 47 : file_stream_provider_(std::move(file_stream_provider)), | 48 : file_stream_provider_(std::move(file_stream_provider)), |
| 48 file_task_runner_(file_task_runner), | 49 file_task_runner_(file_task_runner), |
| 49 net_error_(net::OK), | 50 net_error_(net::OK), |
| 50 weak_factory_(this) { | 51 weak_factory_(this) { |
| 51 if (blob_handle) { | 52 if (blob_handle && !blob_handle->IsBroken()) { |
| 52 blob_data_ = blob_handle->CreateSnapshot(); | 53 blob_handle_.reset(new BlobDataHandle(*blob_handle)); |
| 53 } | 54 } |
| 54 } | 55 } |
| 55 | 56 |
| 56 BlobReader::~BlobReader() { | 57 BlobReader::~BlobReader() { |
| 57 STLDeleteValues(&index_to_reader_); | 58 STLDeleteValues(&index_to_reader_); |
| 58 } | 59 } |
| 59 | 60 |
| 60 BlobReader::Status BlobReader::CalculateSize( | 61 BlobReader::Status BlobReader::CalculateSize( |
| 61 const net::CompletionCallback& done) { | 62 const net::CompletionCallback& done) { |
| 62 DCHECK(!total_size_calculated_); | 63 DCHECK(!total_size_calculated_); |
| 63 DCHECK(size_callback_.is_null()); | 64 DCHECK(size_callback_.is_null()); |
| 64 if (!blob_data_.get()) { | 65 if (!blob_handle_.get() || blob_handle_->IsBroken()) { |
| 65 return ReportError(net::ERR_FILE_NOT_FOUND); | 66 return ReportError(net::ERR_FILE_NOT_FOUND); |
| 66 } | 67 } |
| 67 | 68 if (blob_handle_->IsBeingBuilt()) { |
| 68 net_error_ = net::OK; | 69 blob_handle_->RunOnConstructionComplete(base::Bind( |
| 69 total_size_ = 0; | 70 &BlobReader::AsyncCalculateSize, weak_factory_.GetWeakPtr(), done)); |
| 70 const auto& items = blob_data_->items(); | 71 return Status::IO_PENDING; |
| 71 item_length_list_.resize(items.size()); | |
| 72 pending_get_file_info_count_ = 0; | |
| 73 for (size_t i = 0; i < items.size(); ++i) { | |
| 74 const BlobDataItem& item = *items.at(i); | |
| 75 if (IsFileType(item.type())) { | |
| 76 ++pending_get_file_info_count_; | |
| 77 storage::FileStreamReader* const reader = GetOrCreateFileReaderAtIndex(i); | |
| 78 if (!reader) { | |
| 79 return ReportError(net::ERR_FAILED); | |
| 80 } | |
| 81 int64_t length_output = reader->GetLength(base::Bind( | |
| 82 &BlobReader::DidGetFileItemLength, weak_factory_.GetWeakPtr(), i)); | |
| 83 if (length_output == net::ERR_IO_PENDING) { | |
| 84 continue; | |
| 85 } | |
| 86 if (length_output < 0) { | |
| 87 return ReportError(length_output); | |
| 88 } | |
| 89 // We got the length right away | |
| 90 --pending_get_file_info_count_; | |
| 91 uint64_t resolved_length; | |
| 92 if (!ResolveFileItemLength(item, length_output, &resolved_length)) { | |
| 93 return ReportError(net::ERR_FILE_NOT_FOUND); | |
| 94 } | |
| 95 if (!AddItemLength(i, resolved_length)) { | |
| 96 return ReportError(net::ERR_FAILED); | |
| 97 } | |
| 98 continue; | |
| 99 } | |
| 100 | |
| 101 if (!AddItemLength(i, item.length())) | |
| 102 return ReportError(net::ERR_FAILED); | |
| 103 } | 72 } |
| 104 | 73 blob_data_ = blob_handle_->CreateSnapshot(); |
| 105 if (pending_get_file_info_count_ == 0) { | 74 return CalculateSizeImpl(done); |
| 106 DidCountSize(); | |
| 107 return Status::DONE; | |
| 108 } | |
| 109 // Note: We only set the callback if we know that we're an async operation. | |
| 110 size_callback_ = done; | |
| 111 return Status::IO_PENDING; | |
| 112 } | 75 } |
| 113 | 76 |
| 114 BlobReader::Status BlobReader::SetReadRange(uint64_t offset, uint64_t length) { | 77 BlobReader::Status BlobReader::SetReadRange(uint64_t offset, uint64_t length) { |
| 115 if (!blob_data_.get()) { | 78 if (!blob_handle_.get() || blob_handle_->IsBroken()) { |
| 116 return ReportError(net::ERR_FILE_NOT_FOUND); | 79 return ReportError(net::ERR_FILE_NOT_FOUND); |
| 117 } | 80 } |
| 118 if (!total_size_calculated_) { | 81 if (!total_size_calculated_) { |
| 119 return ReportError(net::ERR_FAILED); | 82 return ReportError(net::ERR_FAILED); |
| 120 } | 83 } |
| 121 if (offset + length > total_size_) { | 84 if (offset + length > total_size_) { |
| 122 return ReportError(net::ERR_FILE_NOT_FOUND); | 85 return ReportError(net::ERR_FILE_NOT_FOUND); |
| 123 } | 86 } |
| 124 // Skip the initial items that are not in the range. | 87 // Skip the initial items that are not in the range. |
| 125 remaining_bytes_ = length; | 88 remaining_bytes_ = length; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 read_callback_.Reset(); | 175 read_callback_.Reset(); |
| 213 read_buf_ = nullptr; | 176 read_buf_ = nullptr; |
| 214 done.Run(net_error); | 177 done.Run(net_error); |
| 215 } | 178 } |
| 216 | 179 |
| 217 BlobReader::Status BlobReader::ReportError(int net_error) { | 180 BlobReader::Status BlobReader::ReportError(int net_error) { |
| 218 net_error_ = net_error; | 181 net_error_ = net_error; |
| 219 return Status::NET_ERROR; | 182 return Status::NET_ERROR; |
| 220 } | 183 } |
| 221 | 184 |
| 185 void BlobReader::AsyncCalculateSize(const net::CompletionCallback& done, |
| 186 bool async_succeeded) { |
| 187 if (!async_succeeded) { |
| 188 InvalidateCallbacksAndDone(net::ERR_FAILED, done); |
| 189 return; |
| 190 } |
| 191 DCHECK(!blob_handle_->IsBroken()) << "Callback should have returned false."; |
| 192 blob_data_ = blob_handle_->CreateSnapshot(); |
| 193 Status size_status = CalculateSizeImpl(done); |
| 194 switch (size_status) { |
| 195 case Status::NET_ERROR: |
| 196 InvalidateCallbacksAndDone(net_error_, done); |
| 197 return; |
| 198 case Status::DONE: |
| 199 done.Run(net::OK); |
| 200 return; |
| 201 case Status::IO_PENDING: |
| 202 return; |
| 203 } |
| 204 } |
| 205 |
| 206 BlobReader::Status BlobReader::CalculateSizeImpl( |
| 207 const net::CompletionCallback& done) { |
| 208 DCHECK(!total_size_calculated_); |
| 209 DCHECK(size_callback_.is_null()); |
| 210 |
| 211 net_error_ = net::OK; |
| 212 total_size_ = 0; |
| 213 const auto& items = blob_data_->items(); |
| 214 item_length_list_.resize(items.size()); |
| 215 pending_get_file_info_count_ = 0; |
| 216 for (size_t i = 0; i < items.size(); ++i) { |
| 217 const BlobDataItem& item = *items.at(i); |
| 218 if (IsFileType(item.type())) { |
| 219 ++pending_get_file_info_count_; |
| 220 storage::FileStreamReader* const reader = GetOrCreateFileReaderAtIndex(i); |
| 221 if (!reader) { |
| 222 return ReportError(net::ERR_FAILED); |
| 223 } |
| 224 int64_t length_output = reader->GetLength(base::Bind( |
| 225 &BlobReader::DidGetFileItemLength, weak_factory_.GetWeakPtr(), i)); |
| 226 if (length_output == net::ERR_IO_PENDING) { |
| 227 continue; |
| 228 } |
| 229 if (length_output < 0) { |
| 230 return ReportError(length_output); |
| 231 } |
| 232 // We got the length right away |
| 233 --pending_get_file_info_count_; |
| 234 uint64_t resolved_length; |
| 235 if (!ResolveFileItemLength(item, length_output, &resolved_length)) { |
| 236 return ReportError(net::ERR_FILE_NOT_FOUND); |
| 237 } |
| 238 if (!AddItemLength(i, resolved_length)) { |
| 239 return ReportError(net::ERR_FAILED); |
| 240 } |
| 241 continue; |
| 242 } |
| 243 |
| 244 if (!AddItemLength(i, item.length())) |
| 245 return ReportError(net::ERR_FAILED); |
| 246 } |
| 247 |
| 248 if (pending_get_file_info_count_ == 0) { |
| 249 DidCountSize(); |
| 250 return Status::DONE; |
| 251 } |
| 252 // Note: We only set the callback if we know that we're an async operation. |
| 253 size_callback_ = done; |
| 254 return Status::IO_PENDING; |
| 255 } |
| 256 |
| 222 bool BlobReader::AddItemLength(size_t index, uint64_t item_length) { | 257 bool BlobReader::AddItemLength(size_t index, uint64_t item_length) { |
| 223 if (item_length > std::numeric_limits<uint64_t>::max() - total_size_) { | 258 if (item_length > std::numeric_limits<uint64_t>::max() - total_size_) { |
| 224 return false; | 259 return false; |
| 225 } | 260 } |
| 226 | 261 |
| 227 // Cache the size and add it to the total size. | 262 // Cache the size and add it to the total size. |
| 228 DCHECK_LT(index, item_length_list_.size()); | 263 DCHECK_LT(index, item_length_list_.size()); |
| 229 item_length_list_[index] = item_length; | 264 item_length_list_[index] = item_length; |
| 230 total_size_ += item_length; | 265 total_size_ += item_length; |
| 231 return true; | 266 return true; |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 index_to_reader_.erase(found); | 595 index_to_reader_.erase(found); |
| 561 return; | 596 return; |
| 562 } | 597 } |
| 563 found->second = reader.release(); | 598 found->second = reader.release(); |
| 564 } else if (reader.get()) { | 599 } else if (reader.get()) { |
| 565 index_to_reader_[current_item_index_] = reader.release(); | 600 index_to_reader_[current_item_index_] = reader.release(); |
| 566 } | 601 } |
| 567 } | 602 } |
| 568 | 603 |
| 569 } // namespace storage | 604 } // namespace storage |
| OLD | NEW |