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> |
(...skipping 30 matching lines...) Expand all Loading... |
41 BlobReader::FileStreamReaderProvider::~FileStreamReaderProvider() {} | 41 BlobReader::FileStreamReaderProvider::~FileStreamReaderProvider() {} |
42 | 42 |
43 BlobReader::BlobReader( | 43 BlobReader::BlobReader( |
44 const BlobDataHandle* blob_handle, | 44 const BlobDataHandle* blob_handle, |
45 scoped_ptr<FileStreamReaderProvider> file_stream_provider, | 45 scoped_ptr<FileStreamReaderProvider> file_stream_provider, |
46 base::SequencedTaskRunner* file_task_runner) | 46 base::SequencedTaskRunner* file_task_runner) |
47 : file_stream_provider_(std::move(file_stream_provider)), | 47 : file_stream_provider_(std::move(file_stream_provider)), |
48 file_task_runner_(file_task_runner), | 48 file_task_runner_(file_task_runner), |
49 net_error_(net::OK), | 49 net_error_(net::OK), |
50 weak_factory_(this) { | 50 weak_factory_(this) { |
51 if (blob_handle) { | 51 if (blob_handle && !blob_handle->IsBroken()) { |
52 blob_data_ = blob_handle->CreateSnapshot(); | 52 blob_handle_.reset(new BlobDataHandle(*blob_handle)); |
53 } | 53 } |
54 } | 54 } |
55 | 55 |
56 BlobReader::~BlobReader() { | 56 BlobReader::~BlobReader() { |
57 STLDeleteValues(&index_to_reader_); | 57 STLDeleteValues(&index_to_reader_); |
58 } | 58 } |
59 | 59 |
60 BlobReader::Status BlobReader::CalculateSize( | 60 BlobReader::Status BlobReader::CalculateSize( |
61 const net::CompletionCallback& done) { | 61 const net::CompletionCallback& done) { |
62 DCHECK(!total_size_calculated_); | 62 DCHECK(!total_size_calculated_); |
63 DCHECK(size_callback_.is_null()); | 63 DCHECK(size_callback_.is_null()); |
64 if (!blob_data_.get()) { | 64 if (!blob_handle_.get() || blob_handle_->IsBroken()) { |
65 return ReportError(net::ERR_FILE_NOT_FOUND); | 65 return ReportError(net::ERR_FILE_NOT_FOUND); |
66 } | 66 } |
67 | 67 if (blob_handle_->IsBeingBuilt()) { |
68 net_error_ = net::OK; | 68 blob_handle_->RunOnConstructionComplete(base::Bind( |
69 total_size_ = 0; | 69 &BlobReader::AsyncCalculateSize, weak_factory_.GetWeakPtr(), done)); |
70 const auto& items = blob_data_->items(); | 70 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 } | 71 } |
104 | 72 blob_data_ = blob_handle_->CreateSnapshot(); |
105 if (pending_get_file_info_count_ == 0) { | 73 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 } | 74 } |
113 | 75 |
114 BlobReader::Status BlobReader::SetReadRange(uint64_t offset, uint64_t length) { | 76 BlobReader::Status BlobReader::SetReadRange(uint64_t offset, uint64_t length) { |
115 if (!blob_data_.get()) { | 77 if (!blob_handle_.get() || blob_handle_->IsBroken()) { |
116 return ReportError(net::ERR_FILE_NOT_FOUND); | 78 return ReportError(net::ERR_FILE_NOT_FOUND); |
117 } | 79 } |
118 if (!total_size_calculated_) { | 80 if (!total_size_calculated_) { |
119 return ReportError(net::ERR_FAILED); | 81 return ReportError(net::ERR_FAILED); |
120 } | 82 } |
121 if (offset + length > total_size_) { | 83 if (offset + length > total_size_) { |
122 return ReportError(net::ERR_FILE_NOT_FOUND); | 84 return ReportError(net::ERR_FILE_NOT_FOUND); |
123 } | 85 } |
124 // Skip the initial items that are not in the range. | 86 // Skip the initial items that are not in the range. |
125 remaining_bytes_ = length; | 87 remaining_bytes_ = length; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 read_callback_.Reset(); | 174 read_callback_.Reset(); |
213 read_buf_ = nullptr; | 175 read_buf_ = nullptr; |
214 done.Run(net_error); | 176 done.Run(net_error); |
215 } | 177 } |
216 | 178 |
217 BlobReader::Status BlobReader::ReportError(int net_error) { | 179 BlobReader::Status BlobReader::ReportError(int net_error) { |
218 net_error_ = net_error; | 180 net_error_ = net_error; |
219 return Status::NET_ERROR; | 181 return Status::NET_ERROR; |
220 } | 182 } |
221 | 183 |
| 184 void BlobReader::AsyncCalculateSize(const net::CompletionCallback& done, |
| 185 bool async_succeeded) { |
| 186 if (!async_succeeded) { |
| 187 InvalidateCallbacksAndDone(net::ERR_FAILED, done); |
| 188 return; |
| 189 } |
| 190 DCHECK(!blob_handle_->IsBroken()) << "Callback should have returned false."; |
| 191 blob_data_ = blob_handle_->CreateSnapshot(); |
| 192 Status size_status = CalculateSizeImpl(done); |
| 193 if (size_status == Status::NET_ERROR) |
| 194 InvalidateCallbacksAndDone(net_error_, done); |
| 195 } |
| 196 |
| 197 BlobReader::Status BlobReader::CalculateSizeImpl( |
| 198 const net::CompletionCallback& done) { |
| 199 DCHECK(!total_size_calculated_); |
| 200 DCHECK(size_callback_.is_null()); |
| 201 |
| 202 net_error_ = net::OK; |
| 203 total_size_ = 0; |
| 204 const auto& items = blob_data_->items(); |
| 205 item_length_list_.resize(items.size()); |
| 206 pending_get_file_info_count_ = 0; |
| 207 for (size_t i = 0; i < items.size(); ++i) { |
| 208 const BlobDataItem& item = *items.at(i); |
| 209 if (IsFileType(item.type())) { |
| 210 ++pending_get_file_info_count_; |
| 211 storage::FileStreamReader* const reader = GetOrCreateFileReaderAtIndex(i); |
| 212 if (!reader) { |
| 213 return ReportError(net::ERR_FAILED); |
| 214 } |
| 215 int64_t length_output = reader->GetLength(base::Bind( |
| 216 &BlobReader::DidGetFileItemLength, weak_factory_.GetWeakPtr(), i)); |
| 217 if (length_output == net::ERR_IO_PENDING) { |
| 218 continue; |
| 219 } |
| 220 if (length_output < 0) { |
| 221 return ReportError(length_output); |
| 222 } |
| 223 // We got the length right away |
| 224 --pending_get_file_info_count_; |
| 225 uint64_t resolved_length; |
| 226 if (!ResolveFileItemLength(item, length_output, &resolved_length)) { |
| 227 return ReportError(net::ERR_FILE_NOT_FOUND); |
| 228 } |
| 229 if (!AddItemLength(i, resolved_length)) { |
| 230 return ReportError(net::ERR_FAILED); |
| 231 } |
| 232 continue; |
| 233 } |
| 234 |
| 235 if (!AddItemLength(i, item.length())) |
| 236 return ReportError(net::ERR_FAILED); |
| 237 } |
| 238 |
| 239 if (pending_get_file_info_count_ == 0) { |
| 240 DidCountSize(); |
| 241 return Status::DONE; |
| 242 } |
| 243 // Note: We only set the callback if we know that we're an async operation. |
| 244 size_callback_ = done; |
| 245 return Status::IO_PENDING; |
| 246 } |
| 247 |
222 bool BlobReader::AddItemLength(size_t index, uint64_t item_length) { | 248 bool BlobReader::AddItemLength(size_t index, uint64_t item_length) { |
223 if (item_length > std::numeric_limits<uint64_t>::max() - total_size_) { | 249 if (item_length > std::numeric_limits<uint64_t>::max() - total_size_) { |
224 return false; | 250 return false; |
225 } | 251 } |
226 | 252 |
227 // Cache the size and add it to the total size. | 253 // Cache the size and add it to the total size. |
228 DCHECK_LT(index, item_length_list_.size()); | 254 DCHECK_LT(index, item_length_list_.size()); |
229 item_length_list_[index] = item_length; | 255 item_length_list_[index] = item_length; |
230 total_size_ += item_length; | 256 total_size_ += item_length; |
231 return true; | 257 return true; |
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
560 index_to_reader_.erase(found); | 586 index_to_reader_.erase(found); |
561 return; | 587 return; |
562 } | 588 } |
563 found->second = reader.release(); | 589 found->second = reader.release(); |
564 } else if (reader.get()) { | 590 } else if (reader.get()) { |
565 index_to_reader_[current_item_index_] = reader.release(); | 591 index_to_reader_[current_item_index_] = reader.release(); |
566 } | 592 } |
567 } | 593 } |
568 | 594 |
569 } // namespace storage | 595 } // namespace storage |
OLD | NEW |