OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "webkit/plugins/ppapi/quota_file_io.h" | 5 #include "webkit/plugins/ppapi/quota_file_io.h" |
6 | 6 |
7 #include "base/stl_util.h" | 7 #include "base/stl_util.h" |
8 #include "base/message_loop_proxy.h" | 8 #include "base/message_loop_proxy.h" |
9 #include "base/task.h" | 9 #include "base/task.h" |
10 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" | 10 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 } | 76 } |
77 virtual ~WriteOperation() {} | 77 virtual ~WriteOperation() {} |
78 virtual void Run() OVERRIDE { | 78 virtual void Run() OVERRIDE { |
79 DCHECK(quota_io_); | 79 DCHECK(quota_io_); |
80 if (quota_io_->CheckIfExceedsQuota(offset_ + bytes_to_write_)) { | 80 if (quota_io_->CheckIfExceedsQuota(offset_ + bytes_to_write_)) { |
81 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); | 81 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); |
82 return; | 82 return; |
83 } | 83 } |
84 if (is_will_operation_) { | 84 if (is_will_operation_) { |
85 // Assuming the write will succeed. | 85 // Assuming the write will succeed. |
86 base::MessageLoopProxy::CreateForCurrentThread()->PostTask( | 86 DidFinish(base::PLATFORM_FILE_OK, bytes_to_write_); |
87 FROM_HERE, runnable_factory_.NewRunnableMethod( | |
88 &WriteOperation::DidFinish, | |
89 base::PLATFORM_FILE_OK, bytes_to_write_)); | |
90 return; | 87 return; |
91 } | 88 } |
92 DCHECK(buffer_.get()); | 89 DCHECK(buffer_.get()); |
93 if (!base::FileUtilProxy::Write( | 90 if (!base::FileUtilProxy::Write( |
94 quota_io_->instance_->delegate()->GetFileThreadMessageLoopProxy(), | 91 quota_io_->instance_->delegate()->GetFileThreadMessageLoopProxy(), |
95 quota_io_->file_, offset_, buffer_.get(), bytes_to_write_, | 92 quota_io_->file_, offset_, buffer_.get(), bytes_to_write_, |
96 callback_factory_.NewCallback(&WriteOperation::DidFinish))) { | 93 callback_factory_.NewCallback(&WriteOperation::DidFinish))) { |
97 DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 94 DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
98 return; | 95 return; |
99 } | 96 } |
100 } | 97 } |
101 | 98 |
102 virtual void DidFail(PlatformFileError error) OVERRIDE { | 99 virtual void DidFail(PlatformFileError error) OVERRIDE { |
103 base::MessageLoopProxy::CreateForCurrentThread()->PostTask( | 100 DidFinish(error, 0); |
104 FROM_HERE, runnable_factory_.NewRunnableMethod( | |
105 &WriteOperation::DidFinish, error, 0)); | |
106 } | 101 } |
107 | 102 |
108 bool finished() const { return finished_; } | 103 bool finished() const { return finished_; } |
109 | 104 |
110 void RunCallback() { | 105 virtual void WillRunCallback() { |
111 DCHECK(callback_.get()); | 106 base::MessageLoopProxy::CreateForCurrentThread()->PostTask( |
112 callback_->Run(status_, bytes_written_); | 107 FROM_HERE, runnable_factory_.NewRunnableMethod( |
113 callback_.reset(); | 108 &WriteOperation::RunCallback)); |
114 delete this; | |
115 } | 109 } |
116 | 110 |
117 private: | 111 private: |
118 void DidFinish(PlatformFileError status, int bytes_written) { | 112 void DidFinish(PlatformFileError status, int bytes_written) { |
119 finished_ = true; | 113 finished_ = true; |
120 status_ = status; | 114 status_ = status; |
121 bytes_written_ = bytes_written; | 115 bytes_written_ = bytes_written; |
122 int64_t max_offset = | 116 int64_t max_offset = |
123 (status != base::PLATFORM_FILE_OK) ? 0 : offset_ + bytes_written; | 117 (status != base::PLATFORM_FILE_OK) ? 0 : offset_ + bytes_written; |
124 // This may delete itself by calling RunCallback. | 118 // This may delete itself by calling RunCallback. |
125 quota_io_->DidWrite(this, max_offset); | 119 quota_io_->DidWrite(this, max_offset); |
126 } | 120 } |
127 | 121 |
| 122 virtual void RunCallback() { |
| 123 DCHECK(callback_.get()); |
| 124 callback_->Run(status_, bytes_written_); |
| 125 callback_.reset(); |
| 126 delete this; |
| 127 } |
| 128 |
128 const int64_t offset_; | 129 const int64_t offset_; |
129 scoped_array<char> buffer_; | 130 scoped_array<char> buffer_; |
130 const int32_t bytes_to_write_; | 131 const int32_t bytes_to_write_; |
131 scoped_ptr<WriteCallback> callback_; | 132 scoped_ptr<WriteCallback> callback_; |
132 bool finished_; | 133 bool finished_; |
133 PlatformFileError status_; | 134 PlatformFileError status_; |
134 int64_t bytes_written_; | 135 int64_t bytes_written_; |
135 base::ScopedCallbackFactory<QuotaFileIO::WriteOperation> callback_factory_; | 136 base::ScopedCallbackFactory<WriteOperation> callback_factory_; |
136 ScopedRunnableMethodFactory<QuotaFileIO::WriteOperation> runnable_factory_; | 137 ScopedRunnableMethodFactory<WriteOperation> runnable_factory_; |
137 }; | 138 }; |
138 | 139 |
139 class QuotaFileIO::SetLengthOperation : public PendingOperationBase { | 140 class QuotaFileIO::SetLengthOperation : public PendingOperationBase { |
140 public: | 141 public: |
141 SetLengthOperation(QuotaFileIO* quota_io, | 142 SetLengthOperation(QuotaFileIO* quota_io, |
142 bool is_will_operation, | 143 bool is_will_operation, |
143 int64_t length, | 144 int64_t length, |
144 StatusCallback* callback) | 145 StatusCallback* callback) |
145 : PendingOperationBase(quota_io, is_will_operation), | 146 : PendingOperationBase(quota_io, is_will_operation), |
146 length_(length), | 147 length_(length), |
147 callback_(callback), | 148 callback_(callback), |
148 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | 149 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {} |
149 runnable_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {} | 150 |
150 virtual ~SetLengthOperation() {} | 151 virtual ~SetLengthOperation() {} |
151 | 152 |
152 virtual void Run() OVERRIDE { | 153 virtual void Run() OVERRIDE { |
153 DCHECK(quota_io_); | 154 DCHECK(quota_io_); |
154 if (quota_io_->CheckIfExceedsQuota(length_)) { | 155 if (quota_io_->CheckIfExceedsQuota(length_)) { |
155 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); | 156 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); |
156 return; | 157 return; |
157 } | 158 } |
158 if (is_will_operation_) { | 159 if (is_will_operation_) { |
159 base::MessageLoopProxy::CreateForCurrentThread()->PostTask( | 160 DidFinish(base::PLATFORM_FILE_OK); |
160 FROM_HERE, runnable_factory_.NewRunnableMethod( | |
161 &SetLengthOperation::DidFinish, | |
162 base::PLATFORM_FILE_OK)); | |
163 return; | 161 return; |
164 } | 162 } |
165 if (!base::FileUtilProxy::Truncate( | 163 if (!base::FileUtilProxy::Truncate( |
166 quota_io_->instance_->delegate()->GetFileThreadMessageLoopProxy(), | 164 quota_io_->instance_->delegate()->GetFileThreadMessageLoopProxy(), |
167 quota_io_->file_, length_, | 165 quota_io_->file_, length_, |
168 callback_factory_.NewCallback(&SetLengthOperation::DidFinish))) { | 166 callback_factory_.NewCallback(&SetLengthOperation::DidFinish))) { |
169 DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 167 DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
170 return; | 168 return; |
171 } | 169 } |
172 } | 170 } |
173 | 171 |
174 virtual void DidFail(PlatformFileError error) OVERRIDE { | 172 virtual void DidFail(PlatformFileError error) OVERRIDE { |
175 base::MessageLoopProxy::CreateForCurrentThread()->PostTask( | 173 DidFinish(error); |
176 FROM_HERE, runnable_factory_.NewRunnableMethod( | |
177 &SetLengthOperation::DidFinish, error)); | |
178 } | 174 } |
179 | 175 |
180 private: | 176 private: |
181 void DidFinish(PlatformFileError status) { | 177 void DidFinish(PlatformFileError status) { |
182 quota_io_->DidSetLength(status, length_); | 178 quota_io_->DidSetLength(status, length_); |
183 DCHECK(callback_.get()); | 179 DCHECK(callback_.get()); |
184 callback_->Run(status); | 180 callback_->Run(status); |
185 callback_.reset(); | 181 callback_.reset(); |
186 delete this; | 182 delete this; |
187 } | 183 } |
188 | 184 |
189 int64_t length_; | 185 int64_t length_; |
190 scoped_ptr<StatusCallback> callback_; | 186 scoped_ptr<StatusCallback> callback_; |
191 base::ScopedCallbackFactory<QuotaFileIO::SetLengthOperation> | 187 base::ScopedCallbackFactory<SetLengthOperation> callback_factory_; |
192 callback_factory_; | |
193 ScopedRunnableMethodFactory<QuotaFileIO::SetLengthOperation> | |
194 runnable_factory_; | |
195 }; | 188 }; |
196 | 189 |
197 // QuotaFileIO -------------------------------------------------------------- | 190 // QuotaFileIO -------------------------------------------------------------- |
198 | 191 |
199 QuotaFileIO::QuotaFileIO( | 192 QuotaFileIO::QuotaFileIO( |
200 PluginInstance* instance, | 193 PluginInstance* instance, |
201 PlatformFile file, | 194 PlatformFile file, |
202 const GURL& file_url, | 195 const GURL& file_url, |
203 PP_FileSystemType type) | 196 PP_FileSystemType type) |
204 : instance_(instance), | 197 : instance_(instance), |
205 file_(file), | 198 file_(file), |
206 file_url_(file_url), | 199 file_url_(file_url), |
207 storage_type_(PPFileSystemTypeToQuotaStorageType(type)), | 200 storage_type_(PPFileSystemTypeToQuotaStorageType(type)), |
208 cached_file_size_(0), | 201 cached_file_size_(0), |
209 cached_available_space_(0), | 202 cached_available_space_(0), |
210 outstanding_quota_queries_(0), | 203 outstanding_quota_queries_(0), |
211 outstanding_errors_(0), | 204 outstanding_errors_(0), |
212 max_written_offset_(0), | 205 max_written_offset_(0), |
213 inflight_operations_(0), | 206 inflight_operations_(0), |
214 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 207 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
215 DCHECK(instance_); | 208 DCHECK(instance_); |
216 DCHECK_NE(base::kInvalidPlatformFileValue, file_); | 209 DCHECK_NE(base::kInvalidPlatformFileValue, file_); |
217 DCHECK_NE(quota::kStorageTypeUnknown, storage_type_); | 210 DCHECK_NE(quota::kStorageTypeUnknown, storage_type_); |
218 } | 211 } |
219 | 212 |
220 QuotaFileIO::~QuotaFileIO() { | 213 QuotaFileIO::~QuotaFileIO() { |
221 // Note that this doesn't dispatch pending callbacks. | 214 // Note that this doesn't dispatch pending callbacks. |
222 STLDeleteContainerPointers(pending_operations_.begin(), | 215 STLDeleteContainerPointers(pending_operations_.begin(), |
223 pending_operations_.end()); | 216 pending_operations_.end()); |
| 217 STLDeleteContainerPointers(pending_callbacks_.begin(), |
| 218 pending_callbacks_.end()); |
224 } | 219 } |
225 | 220 |
226 bool QuotaFileIO::Write( | 221 bool QuotaFileIO::Write( |
227 int64_t offset, const char* buffer, int32_t bytes_to_write, | 222 int64_t offset, const char* buffer, int32_t bytes_to_write, |
228 WriteCallback* callback) { | 223 WriteCallback* callback) { |
229 WriteOperation* op = new WriteOperation( | 224 WriteOperation* op = new WriteOperation( |
230 this, false, offset, buffer, bytes_to_write, callback); | 225 this, false, offset, buffer, bytes_to_write, callback); |
231 return RegisterOperationForQuotaChecks(op); | 226 return RegisterOperationForQuotaChecks(op); |
232 } | 227 } |
233 | 228 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 void QuotaFileIO::DidQueryAvailableSpace(int64_t avail_space) { | 290 void QuotaFileIO::DidQueryAvailableSpace(int64_t avail_space) { |
296 cached_available_space_ = avail_space; | 291 cached_available_space_ = avail_space; |
297 DCHECK_GT(outstanding_quota_queries_, 0); | 292 DCHECK_GT(outstanding_quota_queries_, 0); |
298 if (--outstanding_quota_queries_ == 0) | 293 if (--outstanding_quota_queries_ == 0) |
299 DidQueryForQuotaCheck(); | 294 DidQueryForQuotaCheck(); |
300 } | 295 } |
301 | 296 |
302 void QuotaFileIO::DidQueryForQuotaCheck() { | 297 void QuotaFileIO::DidQueryForQuotaCheck() { |
303 DCHECK(!pending_operations_.empty()); | 298 DCHECK(!pending_operations_.empty()); |
304 DCHECK_GT(inflight_operations_, 0); | 299 DCHECK_GT(inflight_operations_, 0); |
305 for (std::deque<PendingOperationBase*>::iterator iter = | 300 while (!pending_operations_.empty()) { |
306 pending_operations_.begin(); | 301 PendingOperationBase* op = pending_operations_.front(); |
307 iter != pending_operations_.end(); | 302 pending_operations_.pop_front(); |
308 ++iter) { | 303 pending_callbacks_.push_back(op); |
309 PendingOperationBase* op = *iter; | |
310 if (outstanding_errors_ > 0) { | 304 if (outstanding_errors_ > 0) { |
311 op->DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 305 op->DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
312 continue; | 306 continue; |
313 } | 307 } |
314 op->Run(); | 308 op->Run(); |
315 } | 309 } |
316 } | 310 } |
317 | 311 |
318 bool QuotaFileIO::CheckIfExceedsQuota(int64_t new_file_size) const { | 312 bool QuotaFileIO::CheckIfExceedsQuota(int64_t new_file_size) const { |
319 DCHECK_GE(cached_file_size_, 0); | 313 DCHECK_GE(cached_file_size_, 0); |
320 DCHECK_GE(cached_available_space_, 0); | 314 DCHECK_GE(cached_available_space_, 0); |
321 return new_file_size - cached_file_size_ > cached_available_space_; | 315 return new_file_size - cached_file_size_ > cached_available_space_; |
322 } | 316 } |
323 | 317 |
324 void QuotaFileIO::WillUpdate() { | 318 void QuotaFileIO::WillUpdate() { |
325 if (inflight_operations_++ == 0) { | 319 if (inflight_operations_++ == 0) { |
326 instance_->delegate()->WillUpdateFile(file_url_); | 320 instance_->delegate()->WillUpdateFile(file_url_); |
327 DCHECK_EQ(0, max_written_offset_); | 321 DCHECK_EQ(0, max_written_offset_); |
328 } | 322 } |
329 } | 323 } |
330 | 324 |
331 void QuotaFileIO::DidWrite(WriteOperation* op, | 325 void QuotaFileIO::DidWrite(WriteOperation* op, |
332 int64_t written_offset_end) { | 326 int64_t written_offset_end) { |
333 max_written_offset_ = std::max(max_written_offset_, written_offset_end); | 327 max_written_offset_ = std::max(max_written_offset_, written_offset_end); |
334 DCHECK_GT(inflight_operations_, 0); | 328 DCHECK_GT(inflight_operations_, 0); |
335 DCHECK(!pending_operations_.empty()); | 329 DCHECK(!pending_callbacks_.empty()); |
336 // Fire callbacks for finished operations. | 330 // Fire callbacks for finished operations. |
337 while (!pending_operations_.empty()) { | 331 while (!pending_callbacks_.empty()) { |
338 WriteOperation* op = static_cast<WriteOperation*>( | 332 WriteOperation* op = static_cast<WriteOperation*>( |
339 pending_operations_.front()); | 333 pending_callbacks_.front()); |
340 if (!op->finished()) | 334 if (!op->finished()) |
341 break; | 335 break; |
342 op->RunCallback(); | 336 pending_callbacks_.pop_front(); |
343 pending_operations_.pop_front(); | 337 op->WillRunCallback(); |
344 } | 338 } |
345 // If we have no more pending writes, notify the browser that we did | 339 // If we have no more pending writes, notify the browser that we did |
346 // update the file. | 340 // update the file. |
347 if (--inflight_operations_ == 0) { | 341 if (--inflight_operations_ == 0) { |
348 DCHECK(pending_operations_.empty()); | 342 DCHECK(pending_operations_.empty()); |
349 int64_t growth = max_written_offset_ - cached_file_size_; | 343 int64_t growth = max_written_offset_ - cached_file_size_; |
350 growth = growth < 0 ? 0 : growth; | 344 growth = growth < 0 ? 0 : growth; |
351 instance_->delegate()->DidUpdateFile(file_url_, growth); | 345 instance_->delegate()->DidUpdateFile(file_url_, growth); |
352 max_written_offset_ = 0; | 346 max_written_offset_ = 0; |
353 } | 347 } |
354 } | 348 } |
355 | 349 |
356 void QuotaFileIO::DidSetLength(PlatformFileError error, int64_t new_file_size) { | 350 void QuotaFileIO::DidSetLength(PlatformFileError error, int64_t new_file_size) { |
357 DCHECK_EQ(1, inflight_operations_); | 351 DCHECK_EQ(1, inflight_operations_); |
358 pending_operations_.pop_front(); | 352 pending_callbacks_.pop_front(); |
359 DCHECK(pending_operations_.empty()); | 353 DCHECK(pending_callbacks_.empty()); |
360 int64_t delta = (error != base::PLATFORM_FILE_OK) ? 0 : | 354 int64_t delta = (error != base::PLATFORM_FILE_OK) ? 0 : |
361 new_file_size - cached_file_size_; | 355 new_file_size - cached_file_size_; |
362 instance_->delegate()->DidUpdateFile(file_url_, delta); | 356 instance_->delegate()->DidUpdateFile(file_url_, delta); |
363 inflight_operations_ = 0; | 357 inflight_operations_ = 0; |
364 } | 358 } |
365 | 359 |
366 } // namespace ppapi | 360 } // namespace ppapi |
367 } // namespace webkit | 361 } // namespace webkit |
OLD | NEW |