Chromium Code Reviews| 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/ppb_file_io_impl.h" | 5 #include "webkit/plugins/ppapi/ppb_file_io_impl.h" |
| 6 | 6 |
| 7 #include "base/callback.h" | 7 #include "base/callback.h" |
| 8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
| 9 #include "base/file_util_proxy.h" | 9 #include "base/file_util_proxy.h" |
| 10 #include "base/message_loop_proxy.h" | 10 #include "base/message_loop_proxy.h" |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 27 | 27 |
| 28 using ppapi::PPTimeToTime; | 28 using ppapi::PPTimeToTime; |
| 29 using ppapi::TimeToPPTime; | 29 using ppapi::TimeToPPTime; |
| 30 using ppapi::thunk::EnterResourceNoLock; | 30 using ppapi::thunk::EnterResourceNoLock; |
| 31 using ppapi::thunk::PPB_FileIO_API; | 31 using ppapi::thunk::PPB_FileIO_API; |
| 32 using ppapi::thunk::PPB_FileRef_API; | 32 using ppapi::thunk::PPB_FileRef_API; |
| 33 | 33 |
| 34 namespace webkit { | 34 namespace webkit { |
| 35 namespace ppapi { | 35 namespace ppapi { |
| 36 | 36 |
| 37 namespace { | |
| 38 quota::StorageType PPFileSystemTypeToQuotaStorageType(PP_FileSystemType type) { | |
| 39 switch (type) { | |
| 40 case PP_FILESYSTEMTYPE_LOCALPERSISTENT: | |
| 41 return quota::kStorageTypePersistent; | |
| 42 case PP_FILESYSTEMTYPE_LOCALTEMPORARY: | |
| 43 return quota::kStorageTypeTemporary; | |
| 44 default: | |
| 45 return quota::kStorageTypeUnknown; | |
| 46 } | |
| 47 NOTREACHED(); | |
| 48 } | |
| 49 } // namespace | |
| 50 | |
| 51 PPB_FileIO_Impl::PendingOperation::PendingOperation() | |
|
yzshen1
2011/07/21 22:23:34
Please use the same order as they are declared in
| |
| 52 : type(UNKNOWN), offset(0), buffer(NULL), bytes_to_write(0) {} | |
|
yzshen1
2011/07/21 22:23:34
You miss |length|.
| |
| 53 | |
| 37 PPB_FileIO_Impl::CallbackEntry::CallbackEntry() | 54 PPB_FileIO_Impl::CallbackEntry::CallbackEntry() |
| 38 : read_buffer(NULL) { | 55 : read_buffer(NULL) { |
| 39 } | 56 } |
| 40 | 57 |
| 41 PPB_FileIO_Impl::CallbackEntry::CallbackEntry(const CallbackEntry& entry) | 58 PPB_FileIO_Impl::CallbackEntry::CallbackEntry(const CallbackEntry& entry) |
| 42 : callback(entry.callback), | 59 : callback(entry.callback), |
| 43 read_buffer(entry.read_buffer) { | 60 read_buffer(entry.read_buffer) { |
| 44 } | 61 } |
| 45 | 62 |
| 46 PPB_FileIO_Impl::CallbackEntry::~CallbackEntry() { | 63 PPB_FileIO_Impl::CallbackEntry::~CallbackEntry() { |
| 47 } | 64 } |
| 48 | 65 |
| 49 PPB_FileIO_Impl::PPB_FileIO_Impl(PluginInstance* instance) | 66 PPB_FileIO_Impl::PPB_FileIO_Impl(PluginInstance* instance) |
| 50 : Resource(instance), | 67 : Resource(instance), |
| 51 ALLOW_THIS_IN_INITIALIZER_LIST(callback_factory_(this)), | 68 ALLOW_THIS_IN_INITIALIZER_LIST(callback_factory_(this)), |
| 52 file_(base::kInvalidPlatformFileValue), | 69 file_(base::kInvalidPlatformFileValue), |
| 53 pending_op_(OPERATION_NONE), | 70 pending_op_(OPERATION_NONE), |
| 54 info_(NULL) { | 71 info_(NULL), |
| 72 cached_available_space_(0), | |
|
yzshen1
2011/07/21 22:23:34
You miss quite a few members. Please initialize al
| |
| 73 did_notify_will_update_(false), | |
| 74 pending_setlength_length_(-1) { | |
| 55 } | 75 } |
| 56 | 76 |
| 57 PPB_FileIO_Impl::~PPB_FileIO_Impl() { | 77 PPB_FileIO_Impl::~PPB_FileIO_Impl() { |
| 58 Close(); | 78 Close(); |
| 59 } | 79 } |
| 60 | 80 |
| 61 PPB_FileIO_API* PPB_FileIO_Impl::AsPPB_FileIO_API() { | 81 PPB_FileIO_API* PPB_FileIO_Impl::AsPPB_FileIO_API() { |
| 62 return this; | 82 return this; |
| 63 } | 83 } |
| 64 | 84 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 82 switch (file_system_type_) { | 102 switch (file_system_type_) { |
| 83 case PP_FILESYSTEMTYPE_EXTERNAL: | 103 case PP_FILESYSTEMTYPE_EXTERNAL: |
| 84 if (!instance()->delegate()->AsyncOpenFile( | 104 if (!instance()->delegate()->AsyncOpenFile( |
| 85 file_ref->GetSystemPath(), flags, | 105 file_ref->GetSystemPath(), flags, |
| 86 callback_factory_.NewCallback( | 106 callback_factory_.NewCallback( |
| 87 &PPB_FileIO_Impl::AsyncOpenFileCallback))) | 107 &PPB_FileIO_Impl::AsyncOpenFileCallback))) |
| 88 return PP_ERROR_FAILED; | 108 return PP_ERROR_FAILED; |
| 89 break; | 109 break; |
| 90 case PP_FILESYSTEMTYPE_LOCALPERSISTENT: | 110 case PP_FILESYSTEMTYPE_LOCALPERSISTENT: |
| 91 case PP_FILESYSTEMTYPE_LOCALTEMPORARY: | 111 case PP_FILESYSTEMTYPE_LOCALTEMPORARY: |
| 112 path_url_ = file_ref->GetFileSystemURL(); | |
| 92 if (!instance()->delegate()->AsyncOpenFileSystemURL( | 113 if (!instance()->delegate()->AsyncOpenFileSystemURL( |
| 93 file_ref->GetFileSystemURL(), flags, | 114 path_url_, flags, |
| 94 callback_factory_.NewCallback( | 115 callback_factory_.NewCallback( |
| 95 &PPB_FileIO_Impl::AsyncOpenFileCallback))) | 116 &PPB_FileIO_Impl::AsyncOpenFileCallback))) |
| 96 return PP_ERROR_FAILED; | 117 return PP_ERROR_FAILED; |
| 97 break; | 118 break; |
| 98 default: | 119 default: |
| 99 return PP_ERROR_FAILED; | 120 return PP_ERROR_FAILED; |
| 100 } | 121 } |
| 101 | 122 |
| 102 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL); | 123 RegisterCallback(&callbacks_, OPERATION_EXCLUSIVE, callback, NULL); |
| 103 return PP_OK_COMPLETIONPENDING; | 124 return PP_OK_COMPLETIONPENDING; |
| 104 } | 125 } |
| 105 | 126 |
| 106 int32_t PPB_FileIO_Impl::Query(PP_FileInfo* info, | 127 int32_t PPB_FileIO_Impl::Query(PP_FileInfo* info, |
| 107 PP_CompletionCallback callback) { | 128 PP_CompletionCallback callback) { |
| 108 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback); | 129 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback); |
| 109 if (rv != PP_OK) | 130 if (rv != PP_OK) |
| 110 return rv; | 131 return rv; |
| 111 | 132 |
| 112 if (!info) | 133 if (!info) |
| 113 return PP_ERROR_BADARGUMENT; | 134 return PP_ERROR_BADARGUMENT; |
| 114 | 135 |
| 115 DCHECK(!info_); // If |info_|, a callback should be pending (caught above). | 136 DCHECK(!info_); // If |info_|, a callback should be pending (caught above). |
| 116 info_ = info; | 137 info_ = info; |
| 117 | 138 |
| 118 if (!base::FileUtilProxy::GetFileInfoFromPlatformFile( | 139 if (!base::FileUtilProxy::GetFileInfoFromPlatformFile( |
| 119 instance()->delegate()->GetFileThreadMessageLoopProxy(), file_, | 140 instance()->delegate()->GetFileThreadMessageLoopProxy(), file_, |
| 120 callback_factory_.NewCallback(&PPB_FileIO_Impl::QueryInfoCallback))) | 141 callback_factory_.NewCallback(&PPB_FileIO_Impl::QueryInfoCallback))) |
| 121 return PP_ERROR_FAILED; | 142 return PP_ERROR_FAILED; |
| 122 | 143 |
| 123 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL); | 144 RegisterCallback(&callbacks_, OPERATION_EXCLUSIVE, callback, NULL); |
| 124 return PP_OK_COMPLETIONPENDING; | 145 return PP_OK_COMPLETIONPENDING; |
| 125 } | 146 } |
| 126 | 147 |
| 127 int32_t PPB_FileIO_Impl::Touch(PP_Time last_access_time, | 148 int32_t PPB_FileIO_Impl::Touch(PP_Time last_access_time, |
| 128 PP_Time last_modified_time, | 149 PP_Time last_modified_time, |
| 129 PP_CompletionCallback callback) { | 150 PP_CompletionCallback callback) { |
| 130 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback); | 151 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback); |
| 131 if (rv != PP_OK) | 152 if (rv != PP_OK) |
| 132 return rv; | 153 return rv; |
| 133 | 154 |
| 134 if (!base::FileUtilProxy::Touch( | 155 if (!base::FileUtilProxy::Touch( |
| 135 instance()->delegate()->GetFileThreadMessageLoopProxy(), | 156 instance()->delegate()->GetFileThreadMessageLoopProxy(), |
| 136 file_, PPTimeToTime(last_access_time), | 157 file_, PPTimeToTime(last_access_time), |
| 137 PPTimeToTime(last_modified_time), | 158 PPTimeToTime(last_modified_time), |
| 138 callback_factory_.NewCallback(&PPB_FileIO_Impl::StatusCallback))) | 159 callback_factory_.NewCallback(&PPB_FileIO_Impl::StatusCallback))) |
| 139 return PP_ERROR_FAILED; | 160 return PP_ERROR_FAILED; |
| 140 | 161 |
| 141 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL); | 162 RegisterCallback(&callbacks_, OPERATION_EXCLUSIVE, callback, NULL); |
| 142 return PP_OK_COMPLETIONPENDING; | 163 return PP_OK_COMPLETIONPENDING; |
| 143 } | 164 } |
| 144 | 165 |
| 145 int32_t PPB_FileIO_Impl::Read(int64_t offset, | 166 int32_t PPB_FileIO_Impl::Read(int64_t offset, |
| 146 char* buffer, | 167 char* buffer, |
| 147 int32_t bytes_to_read, | 168 int32_t bytes_to_read, |
| 148 PP_CompletionCallback callback) { | 169 PP_CompletionCallback callback) { |
| 149 int32_t rv = CommonCallValidation(true, OPERATION_READ, callback); | 170 int32_t rv = CommonCallValidation(true, OPERATION_READ, callback); |
| 150 if (rv != PP_OK) | 171 if (rv != PP_OK) |
| 151 return rv; | 172 return rv; |
| 152 | 173 |
| 153 if (!base::FileUtilProxy::Read( | 174 if (!base::FileUtilProxy::Read( |
| 154 instance()->delegate()->GetFileThreadMessageLoopProxy(), | 175 instance()->delegate()->GetFileThreadMessageLoopProxy(), |
| 155 file_, offset, bytes_to_read, | 176 file_, offset, bytes_to_read, |
| 156 callback_factory_.NewCallback(&PPB_FileIO_Impl::ReadCallback))) | 177 callback_factory_.NewCallback(&PPB_FileIO_Impl::ReadCallback))) |
| 157 return PP_ERROR_FAILED; | 178 return PP_ERROR_FAILED; |
| 158 | 179 |
| 159 RegisterCallback(OPERATION_READ, callback, buffer); | 180 RegisterCallback(&callbacks_, OPERATION_READ, callback, buffer); |
| 160 return PP_OK_COMPLETIONPENDING; | 181 return PP_OK_COMPLETIONPENDING; |
| 161 } | 182 } |
| 162 | 183 |
| 163 int32_t PPB_FileIO_Impl::Write(int64_t offset, | 184 int32_t PPB_FileIO_Impl::Write(int64_t offset, |
| 164 const char* buffer, | 185 const char* buffer, |
| 165 int32_t bytes_to_write, | 186 int32_t bytes_to_write, |
| 166 PP_CompletionCallback callback) { | 187 PP_CompletionCallback callback) { |
| 167 int32_t rv = CommonCallValidation(true, OPERATION_WRITE, callback); | 188 int32_t rv = CommonCallValidation(true, OPERATION_WRITE, callback); |
| 168 if (rv != PP_OK) | 189 if (rv != PP_OK) |
| 169 return rv; | 190 return rv; |
| 170 | 191 |
| 171 if (!base::FileUtilProxy::Write( | 192 if (!DoesRequireQuotaCheck()) { |
| 172 instance()->delegate()->GetFileThreadMessageLoopProxy(), | 193 if (!base::FileUtilProxy::Write( |
| 173 file_, offset, buffer, bytes_to_write, | 194 instance()->delegate()->GetFileThreadMessageLoopProxy(), |
| 174 callback_factory_.NewCallback(&PPB_FileIO_Impl::WriteCallback))) | 195 file_, offset, buffer, bytes_to_write, |
| 196 callback_factory_.NewCallback(&PPB_FileIO_Impl::WriteCallback))) { | |
| 197 return PP_ERROR_FAILED; | |
| 198 } | |
| 199 RegisterCallback(&callbacks_, OPERATION_WRITE, callback, NULL); | |
| 200 return PP_OK_COMPLETIONPENDING; | |
| 201 } | |
| 202 | |
| 203 // Enqueue this request and query the quota. | |
| 204 PendingOperation op; | |
| 205 op.type = PendingOperation::WRITE; | |
| 206 op.offset = offset; | |
| 207 op.buffer = buffer; | |
| 208 op.bytes_to_write = bytes_to_write; | |
| 209 if (!QueryFileSizeAndQuota(op)) | |
| 175 return PP_ERROR_FAILED; | 210 return PP_ERROR_FAILED; |
| 176 | 211 |
| 177 RegisterCallback(OPERATION_WRITE, callback, NULL); | 212 RegisterCallback(&pending_quota_check_callbacks_, |
| 213 OPERATION_WRITE, callback, NULL); | |
| 178 return PP_OK_COMPLETIONPENDING; | 214 return PP_OK_COMPLETIONPENDING; |
| 179 } | 215 } |
| 180 | 216 |
| 181 int32_t PPB_FileIO_Impl::SetLength(int64_t length, | 217 int32_t PPB_FileIO_Impl::SetLength(int64_t length, |
| 182 PP_CompletionCallback callback) { | 218 PP_CompletionCallback callback) { |
| 183 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback); | 219 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback); |
| 184 if (rv != PP_OK) | 220 if (rv != PP_OK) |
| 185 return rv; | 221 return rv; |
| 186 | 222 |
| 187 if (!base::FileUtilProxy::Truncate( | 223 if (!DoesRequireQuotaCheck()) { |
| 188 instance()->delegate()->GetFileThreadMessageLoopProxy(), | 224 if (!base::FileUtilProxy::Truncate( |
| 189 file_, length, | 225 instance()->delegate()->GetFileThreadMessageLoopProxy(), |
| 190 callback_factory_.NewCallback(&PPB_FileIO_Impl::StatusCallback))) | 226 file_, length, |
| 227 callback_factory_.NewCallback( | |
| 228 &PPB_FileIO_Impl::SetLengthCallback))) { | |
| 229 return PP_ERROR_FAILED; | |
| 230 } | |
| 231 RegisterCallback(&callbacks_, OPERATION_EXCLUSIVE, callback, NULL); | |
| 232 return PP_OK_COMPLETIONPENDING; | |
| 233 } | |
| 234 | |
| 235 // Enqueue this request and query the quota. | |
| 236 PendingOperation op; | |
| 237 op.type = PendingOperation::SETLENGTH; | |
| 238 op.length = length; | |
| 239 if (!QueryFileSizeAndQuota(op)) | |
| 191 return PP_ERROR_FAILED; | 240 return PP_ERROR_FAILED; |
| 192 | 241 |
| 193 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL); | 242 RegisterCallback(&pending_quota_check_callbacks_, |
| 243 OPERATION_EXCLUSIVE, callback, NULL); | |
| 194 return PP_OK_COMPLETIONPENDING; | 244 return PP_OK_COMPLETIONPENDING; |
| 195 } | 245 } |
| 196 | 246 |
| 197 int32_t PPB_FileIO_Impl::Flush(PP_CompletionCallback callback) { | 247 int32_t PPB_FileIO_Impl::Flush(PP_CompletionCallback callback) { |
| 198 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback); | 248 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback); |
| 199 if (rv != PP_OK) | 249 if (rv != PP_OK) |
| 200 return rv; | 250 return rv; |
| 201 | 251 |
| 202 if (!base::FileUtilProxy::Flush( | 252 if (!base::FileUtilProxy::Flush( |
| 203 instance()->delegate()->GetFileThreadMessageLoopProxy(), file_, | 253 instance()->delegate()->GetFileThreadMessageLoopProxy(), file_, |
| 204 callback_factory_.NewCallback(&PPB_FileIO_Impl::StatusCallback))) | 254 callback_factory_.NewCallback(&PPB_FileIO_Impl::StatusCallback))) |
| 205 return PP_ERROR_FAILED; | 255 return PP_ERROR_FAILED; |
| 206 | 256 |
| 207 RegisterCallback(OPERATION_EXCLUSIVE, callback, NULL); | 257 RegisterCallback(&callbacks_, OPERATION_EXCLUSIVE, callback, NULL); |
| 208 return PP_OK_COMPLETIONPENDING; | 258 return PP_OK_COMPLETIONPENDING; |
| 209 } | 259 } |
| 210 | 260 |
| 211 void PPB_FileIO_Impl::Close() { | 261 void PPB_FileIO_Impl::Close() { |
| 212 if (file_ != base::kInvalidPlatformFileValue) { | 262 if (file_ != base::kInvalidPlatformFileValue) { |
| 213 base::FileUtilProxy::Close( | 263 base::FileUtilProxy::Close( |
| 214 instance()->delegate()->GetFileThreadMessageLoopProxy(), file_, NULL); | 264 instance()->delegate()->GetFileThreadMessageLoopProxy(), file_, NULL); |
| 215 file_ = base::kInvalidPlatformFileValue; | 265 file_ = base::kInvalidPlatformFileValue; |
| 216 } | 266 } |
| 217 } | 267 } |
| 218 | 268 |
| 219 int32_t PPB_FileIO_Impl::GetOSFileDescriptor() { | 269 int32_t PPB_FileIO_Impl::GetOSFileDescriptor() { |
| 220 #if defined(OS_POSIX) | 270 #if defined(OS_POSIX) |
| 221 return file_; | 271 return file_; |
| 222 #elif defined(OS_WIN) | 272 #elif defined(OS_WIN) |
| 223 return reinterpret_cast<uintptr_t>(file_); | 273 return reinterpret_cast<uintptr_t>(file_); |
| 224 #else | 274 #else |
| 225 #error "Platform not supported." | 275 #error "Platform not supported." |
| 226 #endif | 276 #endif |
| 227 } | 277 } |
| 228 | 278 |
| 229 int32_t PPB_FileIO_Impl::WillWrite(int64_t offset, | 279 int32_t PPB_FileIO_Impl::WillWrite(int64_t offset, |
| 230 int32_t bytes_to_write, | 280 int32_t bytes_to_write, |
| 231 PP_CompletionCallback callback) { | 281 PP_CompletionCallback callback) { |
| 232 // TODO(dumi): implement me | 282 int32_t rv = CommonCallValidation(true, OPERATION_WRITE, callback); |
| 233 return PP_OK; | 283 if (rv != PP_OK) |
| 284 return rv; | |
| 285 | |
| 286 if (!DoesRequireQuotaCheck()) { | |
| 287 PP_RunCompletionCallback(&callback, PP_OK); | |
| 288 return PP_OK; | |
| 289 } | |
| 290 | |
| 291 PendingOperation op; | |
| 292 op.type = PendingOperation::WILL_WRITE; | |
| 293 op.offset = offset; | |
| 294 op.bytes_to_write = bytes_to_write; | |
| 295 if (!QueryFileSizeAndQuota(op)) | |
| 296 return PP_ERROR_FAILED; | |
| 297 | |
| 298 RegisterCallback(&pending_quota_check_callbacks_, | |
| 299 OPERATION_WRITE, callback, NULL); | |
| 300 return PP_OK_COMPLETIONPENDING; | |
| 234 } | 301 } |
| 235 | 302 |
| 236 int32_t PPB_FileIO_Impl::WillSetLength(int64_t length, | 303 int32_t PPB_FileIO_Impl::WillSetLength(int64_t length, |
| 237 PP_CompletionCallback callback) { | 304 PP_CompletionCallback callback) { |
| 238 // TODO(dumi): implement me | 305 int32_t rv = CommonCallValidation(true, OPERATION_EXCLUSIVE, callback); |
| 239 return PP_OK; | 306 if (rv != PP_OK) |
| 307 return rv; | |
| 308 | |
| 309 if (!DoesRequireQuotaCheck()) { | |
| 310 PP_RunCompletionCallback(&callback, PP_OK); | |
| 311 return PP_OK; | |
| 312 } | |
| 313 | |
| 314 PendingOperation op; | |
| 315 op.type = PendingOperation::WILL_SETLENGTH; | |
| 316 op.length = length; | |
| 317 if (!QueryFileSizeAndQuota(op)) | |
| 318 return PP_ERROR_FAILED; | |
| 319 | |
| 320 RegisterCallback(&pending_quota_check_callbacks_, | |
| 321 OPERATION_EXCLUSIVE, callback, NULL); | |
| 322 return PP_OK_COMPLETIONPENDING; | |
| 240 } | 323 } |
| 241 | 324 |
| 242 int32_t PPB_FileIO_Impl::CommonCallValidation(bool should_be_open, | 325 int32_t PPB_FileIO_Impl::CommonCallValidation(bool should_be_open, |
| 243 OperationType new_op, | 326 OperationType new_op, |
| 244 PP_CompletionCallback callback) { | 327 PP_CompletionCallback callback) { |
| 245 // Only asynchronous operation is supported. | 328 // Only asynchronous operation is supported. |
| 246 if (!callback.func) { | 329 if (!callback.func) { |
| 247 NOTIMPLEMENTED(); | 330 NOTIMPLEMENTED(); |
| 248 return PP_ERROR_BADARGUMENT; | 331 return PP_ERROR_BADARGUMENT; |
| 249 } | 332 } |
| 250 | 333 |
| 251 if (should_be_open) { | 334 if (should_be_open) { |
| 252 if (file_ == base::kInvalidPlatformFileValue) | 335 if (file_ == base::kInvalidPlatformFileValue) |
| 253 return PP_ERROR_FAILED; | 336 return PP_ERROR_FAILED; |
| 254 } else { | 337 } else { |
| 255 if (file_ != base::kInvalidPlatformFileValue) | 338 if (file_ != base::kInvalidPlatformFileValue) |
| 256 return PP_ERROR_FAILED; | 339 return PP_ERROR_FAILED; |
| 257 } | 340 } |
| 258 | 341 |
| 259 if (pending_op_ != OPERATION_NONE && | 342 if (pending_op_ != OPERATION_NONE && |
| 260 (pending_op_ != new_op || pending_op_ == OPERATION_EXCLUSIVE)) { | 343 (pending_op_ != new_op || pending_op_ == OPERATION_EXCLUSIVE)) { |
| 261 return PP_ERROR_INPROGRESS; | 344 return PP_ERROR_INPROGRESS; |
| 262 } | 345 } |
| 263 | 346 |
| 264 return PP_OK; | 347 return PP_OK; |
| 265 } | 348 } |
| 266 | 349 |
| 267 void PPB_FileIO_Impl::RegisterCallback(OperationType op, | 350 void PPB_FileIO_Impl::RegisterCallback(std::queue<CallbackEntry>* callbacks, |
| 351 OperationType op, | |
| 268 PP_CompletionCallback callback, | 352 PP_CompletionCallback callback, |
| 269 char* read_buffer) { | 353 char* read_buffer) { |
| 270 DCHECK(callback.func); | 354 DCHECK(callback.func); |
| 271 DCHECK(pending_op_ == OPERATION_NONE || | 355 DCHECK(pending_op_ == OPERATION_NONE || |
| 272 (pending_op_ != OPERATION_EXCLUSIVE && pending_op_ == op)); | 356 (pending_op_ != OPERATION_EXCLUSIVE && pending_op_ == op)); |
| 273 | 357 |
| 274 CallbackEntry entry; | 358 CallbackEntry entry; |
| 275 PP_Resource resource_id = GetReferenceNoAddRef(); | 359 PP_Resource resource_id = GetReferenceNoAddRef(); |
| 276 CHECK(resource_id); | 360 CHECK(resource_id); |
| 277 entry.callback = new TrackedCompletionCallback( | 361 entry.callback = new TrackedCompletionCallback( |
| 278 instance()->module()->GetCallbackTracker(), resource_id, callback); | 362 instance()->module()->GetCallbackTracker(), resource_id, callback); |
| 279 entry.read_buffer = read_buffer; | 363 entry.read_buffer = read_buffer; |
| 280 | 364 |
| 281 callbacks_.push(entry); | 365 callbacks->push(entry); |
| 282 pending_op_ = op; | 366 pending_op_ = op; |
| 283 } | 367 } |
| 284 | 368 |
| 285 void PPB_FileIO_Impl::RunAndRemoveFirstPendingCallback(int32_t result) { | 369 void PPB_FileIO_Impl::RunAndRemoveFirstPendingCallback( |
| 286 DCHECK(!callbacks_.empty()); | 370 std::queue<CallbackEntry>* callbacks, int32_t result) { |
| 371 DCHECK(!callbacks->empty()); | |
| 287 | 372 |
| 288 CallbackEntry front = callbacks_.front(); | 373 CallbackEntry front = callbacks->front(); |
| 289 callbacks_.pop(); | 374 callbacks->pop(); |
| 290 if (callbacks_.empty()) | 375 if (callbacks->empty()) |
|
yzshen1
2011/07/21 22:23:34
pending_op_ can be set incorrectly.
Consider the f
| |
| 291 pending_op_ = OPERATION_NONE; | 376 pending_op_ = OPERATION_NONE; |
| 292 | 377 |
| 293 front.callback->Run(result); // Will complete abortively if necessary. | 378 front.callback->Run(result); // Will complete abortively if necessary. |
| 294 } | 379 } |
| 295 | 380 |
| 296 void PPB_FileIO_Impl::StatusCallback(base::PlatformFileError error_code) { | 381 void PPB_FileIO_Impl::StatusCallback(base::PlatformFileError error_code) { |
| 297 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty()) { | 382 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty()) { |
| 298 NOTREACHED(); | 383 NOTREACHED(); |
| 299 return; | 384 return; |
| 300 } | 385 } |
| 301 | 386 |
| 302 RunAndRemoveFirstPendingCallback(PlatformFileErrorToPepperError(error_code)); | 387 RunAndRemoveFirstPendingCallback( |
| 388 &callbacks_, PlatformFileErrorToPepperError(error_code)); | |
| 303 } | 389 } |
| 304 | 390 |
| 305 void PPB_FileIO_Impl::AsyncOpenFileCallback( | 391 void PPB_FileIO_Impl::AsyncOpenFileCallback( |
| 306 base::PlatformFileError error_code, | 392 base::PlatformFileError error_code, |
| 307 base::PassPlatformFile file) { | 393 base::PassPlatformFile file) { |
| 308 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty()) { | 394 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty()) { |
| 309 NOTREACHED(); | 395 NOTREACHED(); |
| 310 return; | 396 return; |
| 311 } | 397 } |
| 312 | 398 |
| 313 DCHECK(file_ == base::kInvalidPlatformFileValue); | 399 DCHECK(file_ == base::kInvalidPlatformFileValue); |
| 314 file_ = file.ReleaseValue(); | 400 file_ = file.ReleaseValue(); |
| 315 RunAndRemoveFirstPendingCallback(PlatformFileErrorToPepperError(error_code)); | 401 RunAndRemoveFirstPendingCallback( |
| 402 &callbacks_, PlatformFileErrorToPepperError(error_code)); | |
| 316 } | 403 } |
| 317 | 404 |
| 318 void PPB_FileIO_Impl::QueryInfoCallback( | 405 void PPB_FileIO_Impl::QueryInfoCallback( |
| 319 base::PlatformFileError error_code, | 406 base::PlatformFileError error_code, |
| 320 const base::PlatformFileInfo& file_info) { | 407 const base::PlatformFileInfo& file_info) { |
| 321 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty()) { | 408 if (pending_op_ != OPERATION_EXCLUSIVE || callbacks_.empty()) { |
| 322 NOTREACHED(); | 409 NOTREACHED(); |
| 323 return; | 410 return; |
| 324 } | 411 } |
| 325 | 412 |
| 326 DCHECK(info_); | 413 DCHECK(info_); |
| 327 if (error_code == base::PLATFORM_FILE_OK) { | 414 if (error_code == base::PLATFORM_FILE_OK) { |
| 328 info_->size = file_info.size; | 415 info_->size = file_info.size; |
| 329 info_->creation_time = TimeToPPTime(file_info.creation_time); | 416 info_->creation_time = TimeToPPTime(file_info.creation_time); |
| 330 info_->last_access_time = TimeToPPTime(file_info.last_accessed); | 417 info_->last_access_time = TimeToPPTime(file_info.last_accessed); |
| 331 info_->last_modified_time = TimeToPPTime(file_info.last_modified); | 418 info_->last_modified_time = TimeToPPTime(file_info.last_modified); |
| 332 info_->system_type = file_system_type_; | 419 info_->system_type = file_system_type_; |
| 333 if (file_info.is_directory) | 420 if (file_info.is_directory) |
| 334 info_->type = PP_FILETYPE_DIRECTORY; | 421 info_->type = PP_FILETYPE_DIRECTORY; |
| 335 else | 422 else |
| 336 info_->type = PP_FILETYPE_REGULAR; | 423 info_->type = PP_FILETYPE_REGULAR; |
| 337 } | 424 } |
| 338 info_ = NULL; | 425 info_ = NULL; |
| 339 RunAndRemoveFirstPendingCallback(PlatformFileErrorToPepperError(error_code)); | 426 RunAndRemoveFirstPendingCallback( |
| 427 &callbacks_, PlatformFileErrorToPepperError(error_code)); | |
| 340 } | 428 } |
| 341 | 429 |
| 342 void PPB_FileIO_Impl::ReadCallback(base::PlatformFileError error_code, | 430 void PPB_FileIO_Impl::ReadCallback(base::PlatformFileError error_code, |
| 343 const char* data, int bytes_read) { | 431 const char* data, int bytes_read) { |
| 344 if (pending_op_ != OPERATION_READ || callbacks_.empty()) { | 432 if (pending_op_ != OPERATION_READ || callbacks_.empty()) { |
| 345 NOTREACHED(); | 433 NOTREACHED(); |
| 346 return; | 434 return; |
| 347 } | 435 } |
| 348 | 436 |
| 349 char* read_buffer = callbacks_.front().read_buffer; | 437 char* read_buffer = callbacks_.front().read_buffer; |
| 350 DCHECK(data); | 438 DCHECK(data); |
| 351 DCHECK(read_buffer); | 439 DCHECK(read_buffer); |
| 352 | 440 |
| 353 int rv; | 441 int rv; |
| 354 if (error_code == base::PLATFORM_FILE_OK) { | 442 if (error_code == base::PLATFORM_FILE_OK) { |
| 355 rv = bytes_read; | 443 rv = bytes_read; |
| 356 if (file_ != base::kInvalidPlatformFileValue) | 444 if (file_ != base::kInvalidPlatformFileValue) |
| 357 memcpy(read_buffer, data, bytes_read); | 445 memcpy(read_buffer, data, bytes_read); |
| 358 } else { | 446 } else { |
| 359 rv = PlatformFileErrorToPepperError(error_code); | 447 rv = PlatformFileErrorToPepperError(error_code); |
| 360 } | 448 } |
| 361 | 449 |
| 362 RunAndRemoveFirstPendingCallback(rv); | 450 RunAndRemoveFirstPendingCallback(&callbacks_, rv); |
| 363 } | 451 } |
| 364 | 452 |
| 365 void PPB_FileIO_Impl::WriteCallback(base::PlatformFileError error_code, | 453 void PPB_FileIO_Impl::WriteCallback(base::PlatformFileError error_code, |
| 366 int bytes_written) { | 454 int bytes_written) { |
| 367 if (pending_op_ != OPERATION_WRITE || callbacks_.empty()) { | 455 if (pending_op_ != OPERATION_WRITE || callbacks_.empty()) { |
| 368 NOTREACHED(); | 456 NOTREACHED(); |
| 369 return; | 457 return; |
| 370 } | 458 } |
| 371 | 459 |
| 460 if (DoesRequireQuotaCheck()) { | |
| 461 DCHECK(did_notify_will_update_); | |
| 462 DCHECK(!pending_write_offset_.empty()); | |
| 463 | |
| 464 // Update possible max file offset. | |
| 465 int64_t offset = pending_write_offset_.front(); | |
| 466 pending_write_offset_.pop(); | |
| 467 if (error_code == base::PLATFORM_FILE_OK) | |
| 468 max_written_offset_ = std::max(max_written_offset_, | |
| 469 offset + bytes_written); | |
| 470 | |
| 471 // If we have no more pending writes, notify the browser that we did | |
| 472 // update the file. | |
| 473 if (pending_quota_checks_.empty() && | |
| 474 pending_write_offset_.empty()) { | |
| 475 int64_t growth = max_written_offset_ - cached_file_size_; | |
| 476 if (growth > 0) | |
| 477 instance()->delegate()->DidUpdateFile(path_url_, growth); | |
| 478 did_notify_will_update_ = false; | |
| 479 } | |
| 480 } | |
| 481 | |
| 372 if (error_code != base::PLATFORM_FILE_OK) { | 482 if (error_code != base::PLATFORM_FILE_OK) { |
| 373 RunAndRemoveFirstPendingCallback( | 483 RunAndRemoveFirstPendingCallback( |
| 374 PlatformFileErrorToPepperError(error_code)); | 484 &callbacks_, PlatformFileErrorToPepperError(error_code)); |
| 375 } else { | 485 } else { |
| 376 RunAndRemoveFirstPendingCallback(bytes_written); | 486 RunAndRemoveFirstPendingCallback(&callbacks_, bytes_written); |
| 377 } | 487 } |
| 488 } | |
| 489 | |
| 490 void PPB_FileIO_Impl::SetLengthCallback( | |
| 491 base::PlatformFileError error_code) { | |
| 492 if (callbacks_.empty()) { | |
| 493 NOTREACHED(); | |
| 494 return; | |
| 495 } | |
| 496 | |
| 497 if (DoesRequireQuotaCheck()) { | |
| 498 DCHECK_NE(-1, pending_setlength_length_); | |
| 499 DCHECK(did_notify_will_update_); | |
| 500 if (base::PLATFORM_FILE_OK == error_code) { | |
| 501 instance()->delegate()->DidUpdateFile( | |
| 502 path_url_, pending_setlength_length_ - cached_file_size_); | |
| 503 } | |
| 504 pending_setlength_length_ = -1; | |
| 505 did_notify_will_update_ = false; | |
| 506 } | |
| 507 | |
| 508 RunAndRemoveFirstPendingCallback( | |
| 509 &callbacks_, PlatformFileErrorToPepperError(error_code)); | |
| 510 } | |
| 511 | |
| 512 bool PPB_FileIO_Impl::DoesRequireQuotaCheck() const { | |
| 513 return (file_system_type_ == PP_FILESYSTEMTYPE_LOCALTEMPORARY || | |
| 514 file_system_type_ == PP_FILESYSTEMTYPE_LOCALPERSISTENT); | |
| 515 } | |
| 516 | |
| 517 bool PPB_FileIO_Impl::QueryFileSizeAndQuota(const PendingOperation& op) { | |
| 518 pending_quota_checks_.push(op); | |
| 519 if (pending_quota_checks_.size() == 1) { | |
| 520 // This is the first call. | |
| 521 DCHECK(!did_notify_will_update_); | |
| 522 outstanding_quota_queries_ = 0; | |
| 523 outstanding_errors_ = 0; | |
| 524 | |
| 525 // Query the file size. | |
| 526 ++outstanding_quota_queries_; | |
| 527 if (!base::FileUtilProxy::GetFileInfoFromPlatformFile( | |
| 528 instance()->delegate()->GetFileThreadMessageLoopProxy(), file_, | |
| 529 callback_factory_.NewCallback( | |
| 530 &PPB_FileIO_Impl::DidQueryInfoForQuota))) { | |
| 531 pending_quota_checks_.pop(); | |
|
yzshen1
2011/07/21 22:23:34
Maybe you could push at the end of the method, so
kinuko
2011/07/26 16:27:46
Done (in quota_file_io.cc)
| |
| 532 return false; | |
| 533 } | |
| 534 | |
| 535 // Query the current available space. | |
| 536 ++outstanding_quota_queries_; | |
| 537 instance()->delegate()->QueryAvailableSpace( | |
| 538 GURL(path_url_.path()).GetOrigin(), | |
| 539 PPFileSystemTypeToQuotaStorageType(file_system_type_), | |
| 540 callback_factory_.NewCallback( | |
| 541 &PPB_FileIO_Impl::DidQueryAvailableSpace)); | |
| 542 } | |
| 543 return true; | |
| 544 } | |
| 545 | |
| 546 void PPB_FileIO_Impl::DidQueryInfoForQuota( | |
| 547 base::PlatformFileError error_code, | |
| 548 const base::PlatformFileInfo& file_info) { | |
| 549 if (error_code != base::PLATFORM_FILE_OK) | |
| 550 ++outstanding_errors_; | |
| 551 cached_file_size_ = max_written_offset_ = file_info.size; | |
| 552 DCHECK_GT(outstanding_quota_queries_, 0); | |
| 553 if (--outstanding_quota_queries_ == 0) | |
| 554 DidQueryFileSizeAndQuota(); | |
| 555 } | |
| 556 | |
| 557 void PPB_FileIO_Impl::DidQueryAvailableSpace(int64_t avail_space) { | |
| 558 cached_available_space_ = avail_space; | |
| 559 DCHECK_GT(outstanding_quota_queries_, 0); | |
| 560 if (--outstanding_quota_queries_ == 0) | |
| 561 DidQueryFileSizeAndQuota(); | |
| 562 } | |
| 563 | |
| 564 void PPB_FileIO_Impl::DidQueryFileSizeAndQuota() { | |
| 565 DCHECK(!pending_quota_checks_.empty()); | |
| 566 while (!pending_quota_checks_.empty()) { | |
| 567 PendingOperation op = pending_quota_checks_.front(); | |
| 568 pending_quota_checks_.pop(); | |
| 569 | |
| 570 switch (op.type) { | |
| 571 case PendingOperation::WRITE: { | |
| 572 int64_t growth = op.offset + op.bytes_to_write - cached_file_size_; | |
| 573 if (!CommonQuotaCheck(growth)) | |
| 574 continue; | |
| 575 if (!base::FileUtilProxy::Write( | |
| 576 instance()->delegate()->GetFileThreadMessageLoopProxy(), | |
| 577 file_, op.offset, op.buffer, op.bytes_to_write, | |
| 578 callback_factory_.NewCallback( | |
| 579 &PPB_FileIO_Impl::WriteCallback))) { | |
| 580 RunAndRemoveFirstPendingCallback( | |
| 581 &pending_quota_check_callbacks_, PP_ERROR_FAILED); | |
| 582 continue; | |
| 583 } | |
| 584 pending_write_offset_.push(op.offset); | |
| 585 break; | |
| 586 } | |
| 587 | |
| 588 case PendingOperation::SETLENGTH: { | |
| 589 int64_t growth = op.length - cached_file_size_; | |
| 590 if (!CommonQuotaCheck(growth)) | |
| 591 continue; | |
| 592 if (!base::FileUtilProxy::Truncate( | |
| 593 instance()->delegate()->GetFileThreadMessageLoopProxy(), | |
| 594 file_, op.length, | |
| 595 callback_factory_.NewCallback( | |
| 596 &PPB_FileIO_Impl::SetLengthCallback))) { | |
| 597 RunAndRemoveFirstPendingCallback( | |
| 598 &pending_quota_check_callbacks_, PP_ERROR_FAILED); | |
| 599 continue; | |
| 600 } | |
| 601 DCHECK_EQ(-1, pending_setlength_length_); | |
| 602 pending_setlength_length_ = op.length; | |
| 603 break; | |
| 604 } | |
| 605 | |
| 606 case PendingOperation::WILL_WRITE: { | |
| 607 int64_t growth = op.offset + op.bytes_to_write - cached_file_size_; | |
| 608 if (!CommonQuotaCheck(growth)) | |
| 609 continue; | |
| 610 // TODO(kinuko) we should have a way to handle failure cases; | |
| 611 // currently we always update the usage upfront even if the actual | |
| 612 // write (which will be called after we run the callback) may fail. | |
| 613 pending_write_offset_.push(op.offset); | |
| 614 WriteCallback(base::PLATFORM_FILE_OK, op.bytes_to_write); | |
|
yzshen1
2011/07/21 22:23:34
You shouldn't call WriteCallback before moving the
| |
| 615 break; | |
| 616 } | |
| 617 | |
| 618 case PendingOperation::WILL_SETLENGTH: { | |
| 619 int64_t growth = op.length - cached_file_size_; | |
| 620 if (!CommonQuotaCheck(growth)) | |
| 621 continue; | |
| 622 // TODO(kinuko) we should have a way to handle failure cases; | |
| 623 // currently we always update the usage upfront even if the actual | |
| 624 // truncate (which will be called after we run the callback) may fail. | |
| 625 pending_setlength_length_ = op.length; | |
| 626 SetLengthCallback(base::PLATFORM_FILE_OK); | |
|
yzshen1
2011/07/21 22:23:34
You shouldn't call SetLengthCallback before moving
kinuko
2011/07/26 16:27:46
Added tests that call WillWrite/WillSetLength in p
| |
| 627 break; | |
| 628 } | |
| 629 | |
| 630 default: | |
| 631 NOTREACHED(); | |
| 632 continue; | |
| 633 } | |
| 634 | |
| 635 DCHECK(did_notify_will_update_); | |
| 636 CallbackEntry entry = pending_quota_check_callbacks_.front(); | |
| 637 pending_quota_check_callbacks_.pop(); | |
| 638 callbacks_.push(entry); | |
| 639 } | |
| 640 } | |
| 641 | |
| 642 bool PPB_FileIO_Impl::CommonQuotaCheck(int64_t growth) { | |
| 643 DCHECK(!pending_quota_check_callbacks_.empty()); | |
| 644 if (outstanding_errors_ || growth > cached_available_space_) { | |
| 645 RunAndRemoveFirstPendingCallback( | |
| 646 &pending_quota_check_callbacks_, | |
| 647 PP_ERROR_NOQUOTA); | |
| 648 return false; | |
| 649 } | |
| 650 if (!did_notify_will_update_) { | |
| 651 instance()->delegate()->WillUpdateFile(path_url_); | |
| 652 did_notify_will_update_ = true; | |
| 653 } | |
| 654 return true; | |
| 378 } | 655 } |
| 379 | 656 |
| 380 } // namespace ppapi | 657 } // namespace ppapi |
| 381 } // namespace webkit | 658 } // namespace webkit |
| OLD | NEW |