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 <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
10 #include "base/message_loop_proxy.h" | 10 #include "base/message_loop_proxy.h" |
11 #include "base/task.h" | 11 #include "base/task.h" |
12 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" | 12 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" |
| 13 #include "webkit/plugins/ppapi/resource_helper.h" |
| 14 #include "webkit/plugins/ppapi/resource_tracker.h" |
13 | 15 |
14 using base::PlatformFile; | 16 using base::PlatformFile; |
15 using base::PlatformFileError; | 17 using base::PlatformFileError; |
16 using quota::StorageType; | 18 using quota::StorageType; |
17 | 19 |
18 namespace webkit { | 20 namespace webkit { |
19 namespace ppapi { | 21 namespace ppapi { |
20 | 22 |
21 namespace { | 23 namespace { |
22 StorageType PPFileSystemTypeToQuotaStorageType(PP_FileSystemType type) { | 24 StorageType PPFileSystemTypeToQuotaStorageType(PP_FileSystemType type) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 if (quota_io_->CheckIfExceedsQuota(offset_ + bytes_to_write_)) { | 85 if (quota_io_->CheckIfExceedsQuota(offset_ + bytes_to_write_)) { |
84 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); | 86 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); |
85 return; | 87 return; |
86 } | 88 } |
87 if (is_will_operation_) { | 89 if (is_will_operation_) { |
88 // Assuming the write will succeed. | 90 // Assuming the write will succeed. |
89 DidFinish(base::PLATFORM_FILE_OK, bytes_to_write_); | 91 DidFinish(base::PLATFORM_FILE_OK, bytes_to_write_); |
90 return; | 92 return; |
91 } | 93 } |
92 DCHECK(buffer_.get()); | 94 DCHECK(buffer_.get()); |
| 95 |
| 96 PluginDelegate* plugin_delegate = quota_io_->GetPluginDelegate(); |
| 97 if (!plugin_delegate) { |
| 98 DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
| 99 return; |
| 100 } |
| 101 |
93 if (!base::FileUtilProxy::Write( | 102 if (!base::FileUtilProxy::Write( |
94 quota_io_->instance_->delegate()->GetFileThreadMessageLoopProxy(), | 103 plugin_delegate->GetFileThreadMessageLoopProxy(), |
95 quota_io_->file_, offset_, buffer_.get(), bytes_to_write_, | 104 quota_io_->file_, offset_, buffer_.get(), bytes_to_write_, |
96 callback_factory_.NewCallback(&WriteOperation::DidFinish))) { | 105 callback_factory_.NewCallback(&WriteOperation::DidFinish))) { |
97 DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 106 DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
98 return; | 107 return; |
99 } | 108 } |
100 } | 109 } |
101 | 110 |
102 virtual void DidFail(PlatformFileError error) OVERRIDE { | 111 virtual void DidFail(PlatformFileError error) OVERRIDE { |
103 DidFinish(error, 0); | 112 DidFinish(error, 0); |
104 } | 113 } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 virtual void Run() OVERRIDE { | 165 virtual void Run() OVERRIDE { |
157 DCHECK(quota_io_); | 166 DCHECK(quota_io_); |
158 if (quota_io_->CheckIfExceedsQuota(length_)) { | 167 if (quota_io_->CheckIfExceedsQuota(length_)) { |
159 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); | 168 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); |
160 return; | 169 return; |
161 } | 170 } |
162 if (is_will_operation_) { | 171 if (is_will_operation_) { |
163 DidFinish(base::PLATFORM_FILE_OK); | 172 DidFinish(base::PLATFORM_FILE_OK); |
164 return; | 173 return; |
165 } | 174 } |
| 175 |
| 176 PluginDelegate* plugin_delegate = quota_io_->GetPluginDelegate(); |
| 177 if (!plugin_delegate) { |
| 178 DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
| 179 return; |
| 180 } |
| 181 |
166 if (!base::FileUtilProxy::Truncate( | 182 if (!base::FileUtilProxy::Truncate( |
167 quota_io_->instance_->delegate()->GetFileThreadMessageLoopProxy(), | 183 plugin_delegate->GetFileThreadMessageLoopProxy(), |
168 quota_io_->file_, length_, | 184 quota_io_->file_, length_, |
169 callback_factory_.NewCallback(&SetLengthOperation::DidFinish))) { | 185 callback_factory_.NewCallback(&SetLengthOperation::DidFinish))) { |
170 DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 186 DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
171 return; | 187 return; |
172 } | 188 } |
173 } | 189 } |
174 | 190 |
175 virtual void DidFail(PlatformFileError error) OVERRIDE { | 191 virtual void DidFail(PlatformFileError error) OVERRIDE { |
176 DidFinish(error); | 192 DidFinish(error); |
177 } | 193 } |
178 | 194 |
179 private: | 195 private: |
180 void DidFinish(PlatformFileError status) { | 196 void DidFinish(PlatformFileError status) { |
181 quota_io_->DidSetLength(status, length_); | 197 quota_io_->DidSetLength(status, length_); |
182 DCHECK(callback_.get()); | 198 DCHECK(callback_.get()); |
183 callback_->Run(status); | 199 callback_->Run(status); |
184 callback_.reset(); | 200 callback_.reset(); |
185 delete this; | 201 delete this; |
186 } | 202 } |
187 | 203 |
188 int64_t length_; | 204 int64_t length_; |
189 scoped_ptr<StatusCallback> callback_; | 205 scoped_ptr<StatusCallback> callback_; |
190 base::ScopedCallbackFactory<SetLengthOperation> callback_factory_; | 206 base::ScopedCallbackFactory<SetLengthOperation> callback_factory_; |
191 }; | 207 }; |
192 | 208 |
193 // QuotaFileIO -------------------------------------------------------------- | 209 // QuotaFileIO -------------------------------------------------------------- |
194 | 210 |
195 QuotaFileIO::QuotaFileIO( | 211 QuotaFileIO::QuotaFileIO( |
196 PluginInstance* instance, | 212 PP_Instance instance, |
197 PlatformFile file, | 213 PlatformFile file, |
198 const GURL& file_url, | 214 const GURL& file_url, |
199 PP_FileSystemType type) | 215 PP_FileSystemType type) |
200 : instance_(instance), | 216 : pp_instance_(instance), |
201 file_(file), | 217 file_(file), |
202 file_url_(file_url), | 218 file_url_(file_url), |
203 storage_type_(PPFileSystemTypeToQuotaStorageType(type)), | 219 storage_type_(PPFileSystemTypeToQuotaStorageType(type)), |
204 cached_file_size_(0), | 220 cached_file_size_(0), |
205 cached_available_space_(0), | 221 cached_available_space_(0), |
206 outstanding_quota_queries_(0), | 222 outstanding_quota_queries_(0), |
207 outstanding_errors_(0), | 223 outstanding_errors_(0), |
208 max_written_offset_(0), | 224 max_written_offset_(0), |
209 inflight_operations_(0), | 225 inflight_operations_(0), |
210 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 226 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
211 DCHECK(instance_); | |
212 DCHECK_NE(base::kInvalidPlatformFileValue, file_); | 227 DCHECK_NE(base::kInvalidPlatformFileValue, file_); |
213 DCHECK_NE(quota::kStorageTypeUnknown, storage_type_); | 228 DCHECK_NE(quota::kStorageTypeUnknown, storage_type_); |
214 } | 229 } |
215 | 230 |
216 QuotaFileIO::~QuotaFileIO() { | 231 QuotaFileIO::~QuotaFileIO() { |
217 // Note that this doesn't dispatch pending callbacks. | 232 // Note that this doesn't dispatch pending callbacks. |
218 STLDeleteContainerPointers(pending_operations_.begin(), | 233 STLDeleteContainerPointers(pending_operations_.begin(), |
219 pending_operations_.end()); | 234 pending_operations_.end()); |
220 STLDeleteContainerPointers(pending_callbacks_.begin(), | 235 STLDeleteContainerPointers(pending_callbacks_.begin(), |
221 pending_callbacks_.end()); | 236 pending_callbacks_.end()); |
(...skipping 24 matching lines...) Expand all Loading... |
246 this, true, offset, NULL, bytes_to_write, callback); | 261 this, true, offset, NULL, bytes_to_write, callback); |
247 return RegisterOperationForQuotaChecks(op); | 262 return RegisterOperationForQuotaChecks(op); |
248 } | 263 } |
249 | 264 |
250 bool QuotaFileIO::WillSetLength(int64_t length, StatusCallback* callback) { | 265 bool QuotaFileIO::WillSetLength(int64_t length, StatusCallback* callback) { |
251 DCHECK(pending_operations_.empty()); | 266 DCHECK(pending_operations_.empty()); |
252 SetLengthOperation* op = new SetLengthOperation(this, true, length, callback); | 267 SetLengthOperation* op = new SetLengthOperation(this, true, length, callback); |
253 return RegisterOperationForQuotaChecks(op); | 268 return RegisterOperationForQuotaChecks(op); |
254 } | 269 } |
255 | 270 |
| 271 PluginDelegate* QuotaFileIO::GetPluginDelegate() const { |
| 272 PluginInstance* instance = ResourceTracker::Get()->GetInstance(pp_instance_); |
| 273 if (instance) |
| 274 return instance->delegate(); |
| 275 return NULL; |
| 276 } |
| 277 |
256 bool QuotaFileIO::RegisterOperationForQuotaChecks( | 278 bool QuotaFileIO::RegisterOperationForQuotaChecks( |
257 PendingOperationBase* op_ptr) { | 279 PendingOperationBase* op_ptr) { |
258 scoped_ptr<PendingOperationBase> op(op_ptr); | 280 scoped_ptr<PendingOperationBase> op(op_ptr); |
259 if (pending_operations_.empty()) { | 281 if (pending_operations_.empty()) { |
260 // This is the first pending quota check. Run querying the file size | 282 // This is the first pending quota check. Run querying the file size |
261 // and available space. | 283 // and available space. |
262 outstanding_quota_queries_ = 0; | 284 outstanding_quota_queries_ = 0; |
263 outstanding_errors_ = 0; | 285 outstanding_errors_ = 0; |
264 | 286 |
| 287 PluginDelegate* plugin_delegate = GetPluginDelegate(); |
| 288 if (!plugin_delegate) |
| 289 return false; |
| 290 |
265 // Query the file size. | 291 // Query the file size. |
266 ++outstanding_quota_queries_; | 292 ++outstanding_quota_queries_; |
267 if (!base::FileUtilProxy::GetFileInfoFromPlatformFile( | 293 if (!base::FileUtilProxy::GetFileInfoFromPlatformFile( |
268 instance_->delegate()->GetFileThreadMessageLoopProxy(), file_, | 294 plugin_delegate->GetFileThreadMessageLoopProxy(), file_, |
269 callback_factory_.NewCallback( | 295 callback_factory_.NewCallback( |
270 &QuotaFileIO::DidQueryInfoForQuota))) { | 296 &QuotaFileIO::DidQueryInfoForQuota))) { |
271 // This makes the call fail synchronously; we do not fire the callback | 297 // This makes the call fail synchronously; we do not fire the callback |
272 // here but just delete the operation and return false. | 298 // here but just delete the operation and return false. |
273 return false; | 299 return false; |
274 } | 300 } |
275 | 301 |
276 // Query the current available space. | 302 // Query the current available space. |
277 ++outstanding_quota_queries_; | 303 ++outstanding_quota_queries_; |
278 instance_->delegate()->QueryAvailableSpace( | 304 plugin_delegate->QueryAvailableSpace( |
279 GURL(file_url_.path()).GetOrigin(), storage_type_, | 305 GURL(file_url_.path()).GetOrigin(), storage_type_, |
280 callback_factory_.NewCallback(&QuotaFileIO::DidQueryAvailableSpace)); | 306 callback_factory_.NewCallback(&QuotaFileIO::DidQueryAvailableSpace)); |
281 } | 307 } |
282 pending_operations_.push_back(op.release()); | 308 pending_operations_.push_back(op.release()); |
283 return true; | 309 return true; |
284 } | 310 } |
285 | 311 |
286 void QuotaFileIO::DidQueryInfoForQuota( | 312 void QuotaFileIO::DidQueryInfoForQuota( |
287 base::PlatformFileError error_code, | 313 base::PlatformFileError error_code, |
288 const base::PlatformFileInfo& file_info) { | 314 const base::PlatformFileInfo& file_info) { |
(...skipping 28 matching lines...) Expand all Loading... |
317 } | 343 } |
318 | 344 |
319 bool QuotaFileIO::CheckIfExceedsQuota(int64_t new_file_size) const { | 345 bool QuotaFileIO::CheckIfExceedsQuota(int64_t new_file_size) const { |
320 DCHECK_GE(cached_file_size_, 0); | 346 DCHECK_GE(cached_file_size_, 0); |
321 DCHECK_GE(cached_available_space_, 0); | 347 DCHECK_GE(cached_available_space_, 0); |
322 return new_file_size - cached_file_size_ > cached_available_space_; | 348 return new_file_size - cached_file_size_ > cached_available_space_; |
323 } | 349 } |
324 | 350 |
325 void QuotaFileIO::WillUpdate() { | 351 void QuotaFileIO::WillUpdate() { |
326 if (inflight_operations_++ == 0) { | 352 if (inflight_operations_++ == 0) { |
327 instance_->delegate()->WillUpdateFile(file_url_); | 353 PluginDelegate* plugin_delegate = GetPluginDelegate(); |
| 354 if (plugin_delegate) |
| 355 plugin_delegate->WillUpdateFile(file_url_); |
328 DCHECK_EQ(0, max_written_offset_); | 356 DCHECK_EQ(0, max_written_offset_); |
329 } | 357 } |
330 } | 358 } |
331 | 359 |
332 void QuotaFileIO::DidWrite(WriteOperation* op, | 360 void QuotaFileIO::DidWrite(WriteOperation* op, |
333 int64_t written_offset_end) { | 361 int64_t written_offset_end) { |
334 max_written_offset_ = std::max(max_written_offset_, written_offset_end); | 362 max_written_offset_ = std::max(max_written_offset_, written_offset_end); |
335 DCHECK_GT(inflight_operations_, 0); | 363 DCHECK_GT(inflight_operations_, 0); |
336 DCHECK(!pending_callbacks_.empty()); | 364 DCHECK(!pending_callbacks_.empty()); |
337 // Fire callbacks for finished operations. | 365 // Fire callbacks for finished operations. |
338 while (!pending_callbacks_.empty()) { | 366 while (!pending_callbacks_.empty()) { |
339 WriteOperation* op = static_cast<WriteOperation*>( | 367 WriteOperation* op = static_cast<WriteOperation*>( |
340 pending_callbacks_.front()); | 368 pending_callbacks_.front()); |
341 if (!op->finished()) | 369 if (!op->finished()) |
342 break; | 370 break; |
343 pending_callbacks_.pop_front(); | 371 pending_callbacks_.pop_front(); |
344 op->WillRunCallback(); | 372 op->WillRunCallback(); |
345 } | 373 } |
346 // If we have no more pending writes, notify the browser that we did | 374 // If we have no more pending writes, notify the browser that we did |
347 // update the file. | 375 // update the file. |
348 if (--inflight_operations_ == 0) { | 376 if (--inflight_operations_ == 0) { |
349 DCHECK(pending_operations_.empty()); | 377 DCHECK(pending_operations_.empty()); |
350 int64_t growth = max_written_offset_ - cached_file_size_; | 378 int64_t growth = max_written_offset_ - cached_file_size_; |
351 growth = growth < 0 ? 0 : growth; | 379 growth = growth < 0 ? 0 : growth; |
352 instance_->delegate()->DidUpdateFile(file_url_, growth); | 380 |
| 381 PluginDelegate* plugin_delegate = GetPluginDelegate(); |
| 382 if (plugin_delegate) |
| 383 plugin_delegate->DidUpdateFile(file_url_, growth); |
353 max_written_offset_ = 0; | 384 max_written_offset_ = 0; |
354 } | 385 } |
355 } | 386 } |
356 | 387 |
357 void QuotaFileIO::DidSetLength(PlatformFileError error, int64_t new_file_size) { | 388 void QuotaFileIO::DidSetLength(PlatformFileError error, int64_t new_file_size) { |
358 DCHECK_EQ(1, inflight_operations_); | 389 DCHECK_EQ(1, inflight_operations_); |
359 pending_callbacks_.pop_front(); | 390 pending_callbacks_.pop_front(); |
360 DCHECK(pending_callbacks_.empty()); | 391 DCHECK(pending_callbacks_.empty()); |
361 int64_t delta = (error != base::PLATFORM_FILE_OK) ? 0 : | 392 int64_t delta = (error != base::PLATFORM_FILE_OK) ? 0 : |
362 new_file_size - cached_file_size_; | 393 new_file_size - cached_file_size_; |
363 instance_->delegate()->DidUpdateFile(file_url_, delta); | 394 |
| 395 |
| 396 PluginDelegate* plugin_delegate = GetPluginDelegate(); |
| 397 if (plugin_delegate) |
| 398 plugin_delegate->DidUpdateFile(file_url_, delta); |
364 inflight_operations_ = 0; | 399 inflight_operations_ = 0; |
365 } | 400 } |
366 | 401 |
367 } // namespace ppapi | 402 } // namespace ppapi |
368 } // namespace webkit | 403 } // namespace webkit |
OLD | NEW |