Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(301)

Side by Side Diff: webkit/plugins/ppapi/ppb_file_io_impl.cc

Issue 7433006: Pepper quota support (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/ppb_file_io_impl.h" 5 #include "webkit/plugins/ppapi/ppb_file_io_impl.h"
6 6
7 #include "base/callback.h"
8 #include "base/file_util.h" 7 #include "base/file_util.h"
9 #include "base/file_util_proxy.h" 8 #include "base/file_util_proxy.h"
10 #include "base/message_loop_proxy.h" 9 #include "base/message_loop_proxy.h"
11 #include "base/platform_file.h" 10 #include "base/platform_file.h"
12 #include "base/logging.h" 11 #include "base/logging.h"
13 #include "base/time.h" 12 #include "base/time.h"
14 #include "ppapi/c/ppb_file_io.h" 13 #include "ppapi/c/ppb_file_io.h"
15 #include "ppapi/c/trusted/ppb_file_io_trusted.h" 14 #include "ppapi/c/trusted/ppb_file_io_trusted.h"
16 #include "ppapi/c/pp_completion_callback.h" 15 #include "ppapi/c/pp_completion_callback.h"
17 #include "ppapi/c/pp_errors.h" 16 #include "ppapi/c/pp_errors.h"
18 #include "ppapi/shared_impl/time_conversion.h" 17 #include "ppapi/shared_impl/time_conversion.h"
19 #include "ppapi/thunk/enter.h" 18 #include "ppapi/thunk/enter.h"
20 #include "ppapi/thunk/ppb_file_ref_api.h" 19 #include "ppapi/thunk/ppb_file_ref_api.h"
20 #include "webkit/fileapi/file_system_util.h"
21 #include "webkit/plugins/ppapi/common.h" 21 #include "webkit/plugins/ppapi/common.h"
22 #include "webkit/plugins/ppapi/file_type_conversions.h" 22 #include "webkit/plugins/ppapi/file_type_conversions.h"
23 #include "webkit/plugins/ppapi/plugin_module.h" 23 #include "webkit/plugins/ppapi/plugin_module.h"
24 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" 24 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
25 #include "webkit/plugins/ppapi/ppb_file_ref_impl.h" 25 #include "webkit/plugins/ppapi/ppb_file_ref_impl.h"
26 #include "webkit/plugins/ppapi/resource_tracker.h" 26 #include "webkit/plugins/ppapi/resource_tracker.h"
27 #include "webkit/quota/quota_client.h"
27 28
28 using ppapi::PPTimeToTime; 29 using ppapi::PPTimeToTime;
29 using ppapi::TimeToPPTime; 30 using ppapi::TimeToPPTime;
30 using ppapi::thunk::EnterResourceNoLock; 31 using ppapi::thunk::EnterResourceNoLock;
31 using ppapi::thunk::PPB_FileIO_API; 32 using ppapi::thunk::PPB_FileIO_API;
32 using ppapi::thunk::PPB_FileRef_API; 33 using ppapi::thunk::PPB_FileRef_API;
33 34
34 namespace webkit { 35 namespace webkit {
35 namespace ppapi { 36 namespace ppapi {
36 37
38 namespace {
39 quota::StorageType PPFileSystemTypeToQuotaStorageType(PP_FileSystemType type) {
40 switch (type) {
41 case PP_FILESYSTEMTYPE_LOCALPERSISTENT:
42 return quota::kStorageTypePersistent;
43 case PP_FILESYSTEMTYPE_LOCALTEMPORARY:
44 return quota::kStorageTypeTemporary;
45 default:
46 return quota::kStorageTypeUnknown;
47 }
48 NOTREACHED();
49 }
50
51 bool DoesRequireQuotaCheck(PP_FileSystemType type) {
52 return (type == PP_FILESYSTEMTYPE_LOCALTEMPORARY ||
53 type == PP_FILESYSTEMTYPE_LOCALPERSISTENT);
54 }
55 } // anonymous namespace
56
37 PPB_FileIO_Impl::CallbackEntry::CallbackEntry() 57 PPB_FileIO_Impl::CallbackEntry::CallbackEntry()
38 : read_buffer(NULL) { 58 : read_buffer(NULL) {
39 } 59 }
40 60
41 PPB_FileIO_Impl::CallbackEntry::CallbackEntry(const CallbackEntry& entry) 61 PPB_FileIO_Impl::CallbackEntry::CallbackEntry(const CallbackEntry& entry)
42 : callback(entry.callback), 62 : callback(entry.callback),
43 read_buffer(entry.read_buffer) { 63 read_buffer(entry.read_buffer) {
44 } 64 }
45 65
46 PPB_FileIO_Impl::CallbackEntry::~CallbackEntry() { 66 PPB_FileIO_Impl::CallbackEntry::~CallbackEntry() {
47 } 67 }
48 68
49 PPB_FileIO_Impl::PPB_FileIO_Impl(PluginInstance* instance) 69 PPB_FileIO_Impl::PPB_FileIO_Impl(PluginInstance* instance)
50 : Resource(instance), 70 : Resource(instance),
51 ALLOW_THIS_IN_INITIALIZER_LIST(callback_factory_(this)), 71 ALLOW_THIS_IN_INITIALIZER_LIST(callback_factory_(this)),
52 file_(base::kInvalidPlatformFileValue), 72 file_(base::kInvalidPlatformFileValue),
53 pending_op_(OPERATION_NONE), 73 pending_op_(OPERATION_NONE),
54 info_(NULL) { 74 info_(NULL),
75 pending_setlength_length_(-1) {
55 } 76 }
56 77
57 PPB_FileIO_Impl::~PPB_FileIO_Impl() { 78 PPB_FileIO_Impl::~PPB_FileIO_Impl() {
58 Close(); 79 Close();
59 } 80 }
60 81
61 PPB_FileIO_API* PPB_FileIO_Impl::AsPPB_FileIO_API() { 82 PPB_FileIO_API* PPB_FileIO_Impl::AsPPB_FileIO_API() {
62 return this; 83 return this;
63 } 84 }
64 85
(...skipping 16 matching lines...) Expand all
81 file_system_type_ = file_ref->GetFileSystemType(); 102 file_system_type_ = file_ref->GetFileSystemType();
82 switch (file_system_type_) { 103 switch (file_system_type_) {
83 case PP_FILESYSTEMTYPE_EXTERNAL: 104 case PP_FILESYSTEMTYPE_EXTERNAL:
84 if (!instance()->delegate()->AsyncOpenFile( 105 if (!instance()->delegate()->AsyncOpenFile(
85 file_ref->GetSystemPath(), flags, 106 file_ref->GetSystemPath(), flags,
86 callback_factory_.NewCallback( 107 callback_factory_.NewCallback(
87 &PPB_FileIO_Impl::AsyncOpenFileCallback))) 108 &PPB_FileIO_Impl::AsyncOpenFileCallback)))
88 return PP_ERROR_FAILED; 109 return PP_ERROR_FAILED;
89 break; 110 break;
90 case PP_FILESYSTEMTYPE_LOCALPERSISTENT: 111 case PP_FILESYSTEMTYPE_LOCALPERSISTENT:
91 case PP_FILESYSTEMTYPE_LOCALTEMPORARY: 112 case PP_FILESYSTEMTYPE_LOCALTEMPORARY: {
113 GURL root_url = file_ref->GetFileSystemURL();
92 if (!instance()->delegate()->AsyncOpenFileSystemURL( 114 if (!instance()->delegate()->AsyncOpenFileSystemURL(
93 file_ref->GetFileSystemURL(), flags, 115 root_url, flags,
94 callback_factory_.NewCallback( 116 callback_factory_.NewCallback(
95 &PPB_FileIO_Impl::AsyncOpenFileCallback))) 117 &PPB_FileIO_Impl::AsyncOpenFileCallback)))
96 return PP_ERROR_FAILED; 118 return PP_ERROR_FAILED;
119 origin_url_ = GURL(root_url.path()).GetOrigin();
97 break; 120 break;
121 }
98 default: 122 default:
99 return PP_ERROR_FAILED; 123 return PP_ERROR_FAILED;
100 } 124 }
101 125
102 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL); 126 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL);
103 return PP_OK_COMPLETIONPENDING; 127 return PP_OK_COMPLETIONPENDING;
104 } 128 }
105 129
106 int32_t PPB_FileIO_Impl::Query(PP_FileInfo* info, 130 int32_t PPB_FileIO_Impl::Query(PP_FileInfo* info,
107 PP_CompletionCallback callback) { 131 PP_CompletionCallback callback) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 } 185 }
162 186
163 int32_t PPB_FileIO_Impl::Write(int64_t offset, 187 int32_t PPB_FileIO_Impl::Write(int64_t offset,
164 const char* buffer, 188 const char* buffer,
165 int32_t bytes_to_write, 189 int32_t bytes_to_write,
166 PP_CompletionCallback callback) { 190 PP_CompletionCallback callback) {
167 int32_t rv = CommonCallValidation(true, OPERATION_WRITE, callback); 191 int32_t rv = CommonCallValidation(true, OPERATION_WRITE, callback);
168 if (rv != PP_OK) 192 if (rv != PP_OK)
169 return rv; 193 return rv;
170 194
171 if (!base::FileUtilProxy::Write( 195 PendingWrite write;
172 instance()->delegate()->GetFileThreadMessageLoopProxy(), 196 write.offset = offset;
173 file_, offset, buffer, bytes_to_write, 197 write.buffer = buffer;
174 callback_factory_.NewCallback(&PPB_FileIO_Impl::WriteCallback))) 198 write.bytes_to_write = bytes_to_write;
175 return PP_ERROR_FAILED; 199
200 int64 expected_growth = offset + bytes_to_write - file_size_;
yzshen1 2011/07/19 17:41:55 It is possible that this method gets called for mu
michaeln 2011/07/19 22:01:45 I have these concerns too, keeping track of filesi
kinuko 2011/07/20 13:39:35 Putting aside the fact that the current design is
201 if (!DoesRequireQuotaCheck(file_system_type_) ||
202 expected_growth <= 0) {
203 // we're ok to go.
204 pending_write_callbacks_.push(write);
205 if (!base::FileUtilProxy::Write(
206 instance()->delegate()->GetFileThreadMessageLoopProxy(),
207 file_, offset, buffer, bytes_to_write,
208 callback_factory_.NewCallback(&PPB_FileIO_Impl::WriteCallback))) {
209 pending_write_callbacks_.pop();
210 return PP_ERROR_FAILED;
211 }
212 } else {
213 pending_writes_.push(write);
214 instance()->delegate()->CanWrite(
215 origin_url_,
216 PPFileSystemTypeToQuotaStorageType(file_system_type_),
217 expected_growth,
218 callback_factory_.NewCallback(&PPB_FileIO_Impl::DidCheckQuotaForWrite));
219 }
176 220
177 RegisterCallback(OPERATION_WRITE, callback, NULL); 221 RegisterCallback(OPERATION_WRITE, callback, NULL);
178 return PP_OK_COMPLETIONPENDING; 222 return PP_OK_COMPLETIONPENDING;
179 } 223 }
180 224
181 int32_t PPB_FileIO_Impl::SetLength(int64_t length, 225 int32_t PPB_FileIO_Impl::SetLength(int64_t length,
182 PP_CompletionCallback callback) { 226 PP_CompletionCallback callback) {
183 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback); 227 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback);
184 if (rv != PP_OK) 228 if (rv != PP_OK)
185 return rv; 229 return rv;
186 230
187 if (!base::FileUtilProxy::Truncate( 231 DCHECK_EQ(-1, pending_setlength_length_);
michaeln 2011/07/19 22:01:45 What guarantees are there that there's only one Se
kinuko 2011/07/20 13:39:35 Seems like EXCLUSIVE operations cannot run in para
yzshen1 2011/07/20 20:50:36 Yes, that is correct. On 2011/07/20 13:39:35, kin
188 instance()->delegate()->GetFileThreadMessageLoopProxy(), 232 pending_setlength_length_ = length;
189 file_, length, 233
190 callback_factory_.NewCallback(&PPB_FileIO_Impl::StatusCallback))) 234 int64 expected_growth = length - file_size_;
191 return PP_ERROR_FAILED; 235 if (!DoesRequireQuotaCheck(file_system_type_) ||
236 expected_growth <= 0) {
237 if (!base::FileUtilProxy::Truncate(
238 instance()->delegate()->GetFileThreadMessageLoopProxy(),
239 file_, length,
240 callback_factory_.NewCallback(
241 &PPB_FileIO_Impl::SetLengthCallback))) {
242 pending_setlength_length_ = -1;
243 return PP_ERROR_FAILED;
244 }
245 } else {
246 instance()->delegate()->CanWrite(
247 origin_url_,
248 PPFileSystemTypeToQuotaStorageType(file_system_type_),
249 expected_growth,
250 callback_factory_.NewCallback(
251 &PPB_FileIO_Impl::DidCheckQuotaForSetLength));
252 }
192 253
193 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL); 254 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL);
194 return PP_OK_COMPLETIONPENDING; 255 return PP_OK_COMPLETIONPENDING;
195 } 256 }
196 257
197 int32_t PPB_FileIO_Impl::Flush(PP_CompletionCallback callback) { 258 int32_t PPB_FileIO_Impl::Flush(PP_CompletionCallback callback) {
198 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback); 259 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback);
199 if (rv != PP_OK) 260 if (rv != PP_OK)
200 return rv; 261 return rv;
201 262
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty()) { 358 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty()) {
298 NOTREACHED(); 359 NOTREACHED();
299 return; 360 return;
300 } 361 }
301 362
302 RunAndRemoveFirstPendingCallback(PlatformFileErrorToPepperError(error_code)); 363 RunAndRemoveFirstPendingCallback(PlatformFileErrorToPepperError(error_code));
303 } 364 }
304 365
305 void PPB_FileIO_Impl::AsyncOpenFileCallback( 366 void PPB_FileIO_Impl::AsyncOpenFileCallback(
306 base::PlatformFileError error_code, 367 base::PlatformFileError error_code,
307 base::PassPlatformFile file) { 368 base::PassPlatformFile file,
369 int64_t file_size) {
308 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty()) { 370 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty()) {
309 NOTREACHED(); 371 NOTREACHED();
310 return; 372 return;
311 } 373 }
312 374
313 DCHECK(file_ == base::kInvalidPlatformFileValue); 375 DCHECK(file_ == base::kInvalidPlatformFileValue);
314 file_ = file.ReleaseValue(); 376 file_ = file.ReleaseValue();
377 file_size_ = file_size;
315 RunAndRemoveFirstPendingCallback(PlatformFileErrorToPepperError(error_code)); 378 RunAndRemoveFirstPendingCallback(PlatformFileErrorToPepperError(error_code));
316 } 379 }
317 380
318 void PPB_FileIO_Impl::QueryInfoCallback( 381 void PPB_FileIO_Impl::QueryInfoCallback(
319 base::PlatformFileError error_code, 382 base::PlatformFileError error_code,
320 const base::PlatformFileInfo& file_info) { 383 const base::PlatformFileInfo& file_info) {
321 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty()) { 384 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty()) {
322 NOTREACHED(); 385 NOTREACHED();
323 return; 386 return;
324 } 387 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 RunAndRemoveFirstPendingCallback(rv); 425 RunAndRemoveFirstPendingCallback(rv);
363 } 426 }
364 427
365 void PPB_FileIO_Impl::WriteCallback(base::PlatformFileError error_code, 428 void PPB_FileIO_Impl::WriteCallback(base::PlatformFileError error_code,
366 int bytes_written) { 429 int bytes_written) {
367 if (pending_op_ != OPERATION_WRITE || callbacks_.empty()) { 430 if (pending_op_ != OPERATION_WRITE || callbacks_.empty()) {
368 NOTREACHED(); 431 NOTREACHED();
369 return; 432 return;
370 } 433 }
371 434
435 DCHECK(!pending_write_callbacks_.empty());
436 PendingWrite write = pending_write_callbacks_.front();
437 pending_write_callbacks_.pop();
438
372 if (error_code != base::PLATFORM_FILE_OK) { 439 if (error_code != base::PLATFORM_FILE_OK) {
373 RunAndRemoveFirstPendingCallback( 440 RunAndRemoveFirstPendingCallback(
374 PlatformFileErrorToPepperError(error_code)); 441 PlatformFileErrorToPepperError(error_code));
375 } else { 442 } else {
443 int64 growth = write.offset + bytes_written - file_size_;
444 if (growth >= 0) {
445 if (DoesRequireQuotaCheck(file_system_type_)) {
446 instance()->delegate()->NotifyStorageModified(
447 quota::QuotaClient::kFileSystem,
448 origin_url_,
449 PPFileSystemTypeToQuotaStorageType(file_system_type_),
450 growth);
451 }
452 file_size_ += growth;
453 }
376 RunAndRemoveFirstPendingCallback(bytes_written); 454 RunAndRemoveFirstPendingCallback(bytes_written);
377 } 455 }
378 } 456 }
379 457
458 void PPB_FileIO_Impl::SetLengthCallback(
459 base::PlatformFileError error_code) {
460 if (callbacks_.empty()) {
461 NOTREACHED();
462 return;
463 }
464
465 DCHECK_NE(-1, pending_setlength_length_);
466
467 if (base::PLATFORM_FILE_OK == error_code &&
468 DoesRequireQuotaCheck(file_system_type_)) {
469 int64 delta = pending_setlength_length_ - file_size_;
470 instance()->delegate()->NotifyStorageModified(
471 quota::QuotaClient::kFileSystem,
472 origin_url_,
473 PPFileSystemTypeToQuotaStorageType(file_system_type_),
474 delta);
475 }
476
477 RunAndRemoveFirstPendingCallback(PlatformFileErrorToPepperError(error_code));
michaeln 2011/07/19 22:01:45 Now that some of these operations call out the the
yzshen1 2011/07/19 23:14:14 What is more, the order of multiple write operatio
kinuko 2011/07/20 13:39:35 I splitted the callbacks queue into two, one for r
478 file_size_ = pending_setlength_length_;
yzshen1 2011/07/19 17:41:55 Even if it failed, we still set file_size_ to pend
kinuko 2011/07/20 13:39:35 Good catch... fixed.
479 pending_setlength_length_ = -1;
480 }
481
482 void PPB_FileIO_Impl::DidCheckQuotaForWrite(bool success) {
yzshen1 2011/07/19 17:41:55 This method and DidCheckQuotaForSetLength ignore |
483 DCHECK(!pending_writes_.empty());
484 PendingWrite write = pending_writes_.front();
485 pending_writes_.pop();
486 pending_write_callbacks_.push(write);
487
488 if (!base::FileUtilProxy::Write(
489 instance()->delegate()->GetFileThreadMessageLoopProxy(),
490 file_, write.offset, write.buffer, write.bytes_to_write,
491 callback_factory_.NewCallback(&PPB_FileIO_Impl::WriteCallback))) {
492 RunAndRemoveFirstPendingCallback(PP_ERROR_FAILED);
493 }
494 }
495
496 void PPB_FileIO_Impl::DidCheckQuotaForSetLength(bool success) {
497 DCHECK(!pending_setlength_length_ != -1);
498 if (!base::FileUtilProxy::Truncate(
499 instance()->delegate()->GetFileThreadMessageLoopProxy(),
500 file_, pending_setlength_length_,
501 callback_factory_.NewCallback(
502 &PPB_FileIO_Impl::SetLengthCallback))) {
503 RunAndRemoveFirstPendingCallback(PP_ERROR_FAILED);
504 }
505 }
506
380 } // namespace ppapi 507 } // namespace ppapi
381 } // namespace webkit 508 } // namespace webkit
OLDNEW
« webkit/plugins/ppapi/ppb_file_io_impl.h ('K') | « webkit/plugins/ppapi/ppb_file_io_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698