| 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/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| 11 #include "base/message_loop_proxy.h" | 11 #include "base/message_loop_proxy.h" |
| 12 #include "base/task.h" | 12 #include "base/task.h" |
| 13 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" | 13 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" |
| 14 #include "webkit/plugins/ppapi/resource_helper.h" | 14 #include "webkit/plugins/ppapi/resource_helper.h" |
| 15 #include "webkit/plugins/ppapi/resource_tracker.h" | 15 #include "webkit/plugins/ppapi/resource_tracker.h" |
| 16 | 16 |
| 17 using base::FileUtilProxy; |
| 17 using base::PlatformFile; | 18 using base::PlatformFile; |
| 18 using base::PlatformFileError; | 19 using base::PlatformFileError; |
| 19 using quota::StorageType; | 20 using quota::StorageType; |
| 20 | 21 |
| 21 namespace webkit { | 22 namespace webkit { |
| 22 namespace ppapi { | 23 namespace ppapi { |
| 23 | 24 |
| 24 namespace { | 25 namespace { |
| 25 StorageType PPFileSystemTypeToQuotaStorageType(PP_FileSystemType type) { | 26 StorageType PPFileSystemTypeToQuotaStorageType(PP_FileSystemType type) { |
| 26 switch (type) { | 27 switch (type) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 56 const bool is_will_operation_; | 57 const bool is_will_operation_; |
| 57 }; | 58 }; |
| 58 | 59 |
| 59 class QuotaFileIO::WriteOperation : public PendingOperationBase { | 60 class QuotaFileIO::WriteOperation : public PendingOperationBase { |
| 60 public: | 61 public: |
| 61 WriteOperation(QuotaFileIO* quota_io, | 62 WriteOperation(QuotaFileIO* quota_io, |
| 62 bool is_will_operation, | 63 bool is_will_operation, |
| 63 int64_t offset, | 64 int64_t offset, |
| 64 const char* buffer, | 65 const char* buffer, |
| 65 int32_t bytes_to_write, | 66 int32_t bytes_to_write, |
| 66 WriteCallback* callback) | 67 const WriteCallback& callback) |
| 67 : PendingOperationBase(quota_io, is_will_operation), | 68 : PendingOperationBase(quota_io, is_will_operation), |
| 68 offset_(offset), | 69 offset_(offset), |
| 69 bytes_to_write_(bytes_to_write), | 70 bytes_to_write_(bytes_to_write), |
| 70 callback_(callback), | 71 callback_(callback), |
| 71 finished_(false), | 72 finished_(false), |
| 72 status_(base::PLATFORM_FILE_OK), | 73 status_(base::PLATFORM_FILE_OK), |
| 73 bytes_written_(0), | 74 bytes_written_(0), |
| 74 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | 75 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| 75 runnable_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | |
| 76 if (!is_will_operation) { | 76 if (!is_will_operation) { |
| 77 // TODO(kinuko): check the API convention if we really need to keep a | 77 // TODO(kinuko): check the API convention if we really need to keep a |
| 78 // copy of the buffer during the async write operations. | 78 // copy of the buffer during the async write operations. |
| 79 buffer_.reset(new char[bytes_to_write]); | 79 buffer_.reset(new char[bytes_to_write]); |
| 80 memcpy(buffer_.get(), buffer, bytes_to_write); | 80 memcpy(buffer_.get(), buffer, bytes_to_write); |
| 81 } | 81 } |
| 82 } | 82 } |
| 83 virtual ~WriteOperation() {} | 83 virtual ~WriteOperation() {} |
| 84 virtual void Run() OVERRIDE { | 84 virtual void Run() OVERRIDE { |
| 85 DCHECK(quota_io_); | 85 DCHECK(quota_io_); |
| 86 if (quota_io_->CheckIfExceedsQuota(offset_ + bytes_to_write_)) { | 86 if (quota_io_->CheckIfExceedsQuota(offset_ + bytes_to_write_)) { |
| 87 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); | 87 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); |
| 88 return; | 88 return; |
| 89 } | 89 } |
| 90 if (is_will_operation_) { | 90 if (is_will_operation_) { |
| 91 // Assuming the write will succeed. | 91 // Assuming the write will succeed. |
| 92 DidFinish(base::PLATFORM_FILE_OK, bytes_to_write_); | 92 DidFinish(base::PLATFORM_FILE_OK, bytes_to_write_); |
| 93 return; | 93 return; |
| 94 } | 94 } |
| 95 DCHECK(buffer_.get()); | 95 DCHECK(buffer_.get()); |
| 96 | 96 |
| 97 PluginDelegate* plugin_delegate = quota_io_->GetPluginDelegate(); | 97 PluginDelegate* plugin_delegate = quota_io_->GetPluginDelegate(); |
| 98 if (!plugin_delegate) { | 98 if (!plugin_delegate) { |
| 99 DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 99 DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
| 100 return; | 100 return; |
| 101 } | 101 } |
| 102 | 102 |
| 103 if (!base::FileUtilProxy::Write( | 103 if (!FileUtilProxy::Write( |
| 104 plugin_delegate->GetFileThreadMessageLoopProxy(), | 104 plugin_delegate->GetFileThreadMessageLoopProxy(), |
| 105 quota_io_->file_, offset_, buffer_.get(), bytes_to_write_, | 105 quota_io_->file_, offset_, buffer_.get(), bytes_to_write_, |
| 106 callback_factory_.NewCallback(&WriteOperation::DidFinish))) { | 106 base::Bind(&WriteOperation::DidFinish, |
| 107 weak_ptr_factory_.GetWeakPtr()))) { |
| 107 DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 108 DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
| 108 return; | 109 return; |
| 109 } | 110 } |
| 110 } | 111 } |
| 111 | 112 |
| 112 virtual void DidFail(PlatformFileError error) OVERRIDE { | 113 virtual void DidFail(PlatformFileError error) OVERRIDE { |
| 113 DidFinish(error, 0); | 114 DidFinish(error, 0); |
| 114 } | 115 } |
| 115 | 116 |
| 116 bool finished() const { return finished_; } | 117 bool finished() const { return finished_; } |
| 117 | 118 |
| 118 virtual void WillRunCallback() { | 119 virtual void WillRunCallback() { |
| 119 base::MessageLoopProxy::current()->PostTask( | 120 base::MessageLoopProxy::current()->PostTask( |
| 120 FROM_HERE, runnable_factory_.NewRunnableMethod( | 121 FROM_HERE, |
| 121 &WriteOperation::RunCallback)); | 122 base::Bind(&WriteOperation::RunCallback, |
| 123 weak_ptr_factory_.GetWeakPtr())); |
| 122 } | 124 } |
| 123 | 125 |
| 124 private: | 126 private: |
| 125 void DidFinish(PlatformFileError status, int bytes_written) { | 127 void DidFinish(PlatformFileError status, int bytes_written) { |
| 126 finished_ = true; | 128 finished_ = true; |
| 127 status_ = status; | 129 status_ = status; |
| 128 bytes_written_ = bytes_written; | 130 bytes_written_ = bytes_written; |
| 129 int64_t max_offset = | 131 int64_t max_offset = |
| 130 (status != base::PLATFORM_FILE_OK) ? 0 : offset_ + bytes_written; | 132 (status != base::PLATFORM_FILE_OK) ? 0 : offset_ + bytes_written; |
| 131 // This may delete itself by calling RunCallback. | 133 // This may delete itself by calling RunCallback. |
| 132 quota_io_->DidWrite(this, max_offset); | 134 quota_io_->DidWrite(this, max_offset); |
| 133 } | 135 } |
| 134 | 136 |
| 135 virtual void RunCallback() { | 137 virtual void RunCallback() { |
| 136 DCHECK(callback_.get()); | 138 DCHECK(!callback_.is_null()); |
| 137 callback_->Run(status_, bytes_written_); | 139 callback_.Run(status_, bytes_written_); |
| 138 callback_.reset(); | |
| 139 delete this; | |
| 140 } | 140 } |
| 141 | 141 |
| 142 const int64_t offset_; | 142 const int64_t offset_; |
| 143 scoped_array<char> buffer_; | 143 scoped_array<char> buffer_; |
| 144 const int32_t bytes_to_write_; | 144 const int32_t bytes_to_write_; |
| 145 scoped_ptr<WriteCallback> callback_; | 145 WriteCallback callback_; |
| 146 bool finished_; | 146 bool finished_; |
| 147 PlatformFileError status_; | 147 PlatformFileError status_; |
| 148 int64_t bytes_written_; | 148 int64_t bytes_written_; |
| 149 base::ScopedCallbackFactory<WriteOperation> callback_factory_; | 149 base::WeakPtrFactory<WriteOperation> weak_ptr_factory_; |
| 150 ScopedRunnableMethodFactory<WriteOperation> runnable_factory_; | |
| 151 }; | 150 }; |
| 152 | 151 |
| 153 class QuotaFileIO::SetLengthOperation : public PendingOperationBase { | 152 class QuotaFileIO::SetLengthOperation : public PendingOperationBase { |
| 154 public: | 153 public: |
| 155 SetLengthOperation(QuotaFileIO* quota_io, | 154 SetLengthOperation(QuotaFileIO* quota_io, |
| 156 bool is_will_operation, | 155 bool is_will_operation, |
| 157 int64_t length, | 156 int64_t length, |
| 158 StatusCallback* callback) | 157 const StatusCallback& callback) |
| 159 : PendingOperationBase(quota_io, is_will_operation), | 158 : PendingOperationBase(quota_io, is_will_operation), |
| 160 length_(length), | 159 length_(length), |
| 161 callback_(callback), | 160 callback_(callback), |
| 162 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {} | 161 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {} |
| 163 | 162 |
| 164 virtual ~SetLengthOperation() {} | 163 virtual ~SetLengthOperation() {} |
| 165 | 164 |
| 166 virtual void Run() OVERRIDE { | 165 virtual void Run() OVERRIDE { |
| 167 DCHECK(quota_io_); | 166 DCHECK(quota_io_); |
| 168 if (quota_io_->CheckIfExceedsQuota(length_)) { | 167 if (quota_io_->CheckIfExceedsQuota(length_)) { |
| 169 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); | 168 DidFail(base::PLATFORM_FILE_ERROR_NO_SPACE); |
| 170 return; | 169 return; |
| 171 } | 170 } |
| 172 if (is_will_operation_) { | 171 if (is_will_operation_) { |
| 173 DidFinish(base::PLATFORM_FILE_OK); | 172 DidFinish(base::PLATFORM_FILE_OK); |
| 174 return; | 173 return; |
| 175 } | 174 } |
| 176 | 175 |
| 177 PluginDelegate* plugin_delegate = quota_io_->GetPluginDelegate(); | 176 PluginDelegate* plugin_delegate = quota_io_->GetPluginDelegate(); |
| 178 if (!plugin_delegate) { | 177 if (!plugin_delegate) { |
| 179 DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 178 DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
| 180 return; | 179 return; |
| 181 } | 180 } |
| 182 | 181 |
| 183 if (!base::FileUtilProxy::Truncate( | 182 if (!FileUtilProxy::PostFileTaskAndReplyStatus<bool, PlatformFileError>( |
| 184 plugin_delegate->GetFileThreadMessageLoopProxy(), | 183 plugin_delegate->GetFileThreadMessageLoopProxy(), |
| 185 quota_io_->file_, length_, | 184 FROM_HERE, |
| 186 callback_factory_.NewCallback(&SetLengthOperation::DidFinish))) { | 185 base::Bind(&base::TruncatePlatformFile, |
| 186 quota_io_->file_, length_), |
| 187 base::Bind(&SetLengthOperation::DidFinish, |
| 188 weak_ptr_factory_.GetWeakPtr()))) { |
| 187 DidFail(base::PLATFORM_FILE_ERROR_FAILED); | 189 DidFail(base::PLATFORM_FILE_ERROR_FAILED); |
| 188 return; | 190 return; |
| 189 } | 191 } |
| 190 } | 192 } |
| 191 | 193 |
| 192 virtual void DidFail(PlatformFileError error) OVERRIDE { | 194 virtual void DidFail(PlatformFileError error) OVERRIDE { |
| 193 DidFinish(error); | 195 DidFinish(error); |
| 194 } | 196 } |
| 195 | 197 |
| 196 private: | 198 private: |
| 197 void DidFinish(PlatformFileError status) { | 199 void DidFinish(PlatformFileError status) { |
| 198 quota_io_->DidSetLength(status, length_); | 200 quota_io_->DidSetLength(status, length_); |
| 199 DCHECK(callback_.get()); | 201 DCHECK(!callback_.is_null()); |
| 200 callback_->Run(status); | 202 callback_.Run(status); |
| 201 callback_.reset(); | |
| 202 delete this; | |
| 203 } | 203 } |
| 204 | 204 |
| 205 int64_t length_; | 205 int64_t length_; |
| 206 scoped_ptr<StatusCallback> callback_; | 206 StatusCallback callback_; |
| 207 base::ScopedCallbackFactory<SetLengthOperation> callback_factory_; | 207 base::WeakPtrFactory<SetLengthOperation> weak_ptr_factory_; |
| 208 }; | 208 }; |
| 209 | 209 |
| 210 // QuotaFileIO -------------------------------------------------------------- | 210 // QuotaFileIO -------------------------------------------------------------- |
| 211 | 211 |
| 212 QuotaFileIO::QuotaFileIO( | 212 QuotaFileIO::QuotaFileIO( |
| 213 PP_Instance instance, | 213 PP_Instance instance, |
| 214 PlatformFile file, | 214 PlatformFile file, |
| 215 const GURL& file_url, | 215 const GURL& file_url, |
| 216 PP_FileSystemType type) | 216 PP_FileSystemType type) |
| 217 : pp_instance_(instance), | 217 : pp_instance_(instance), |
| 218 file_(file), | 218 file_(file), |
| 219 file_url_(file_url), | 219 file_url_(file_url), |
| 220 storage_type_(PPFileSystemTypeToQuotaStorageType(type)), | 220 storage_type_(PPFileSystemTypeToQuotaStorageType(type)), |
| 221 cached_file_size_(0), | 221 cached_file_size_(0), |
| 222 cached_available_space_(0), | 222 cached_available_space_(0), |
| 223 outstanding_quota_queries_(0), | 223 outstanding_quota_queries_(0), |
| 224 outstanding_errors_(0), | 224 outstanding_errors_(0), |
| 225 max_written_offset_(0), | 225 max_written_offset_(0), |
| 226 inflight_operations_(0), | 226 inflight_operations_(0), |
| 227 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | |
| 228 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 227 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| 229 DCHECK_NE(base::kInvalidPlatformFileValue, file_); | 228 DCHECK_NE(base::kInvalidPlatformFileValue, file_); |
| 230 DCHECK_NE(quota::kStorageTypeUnknown, storage_type_); | 229 DCHECK_NE(quota::kStorageTypeUnknown, storage_type_); |
| 231 } | 230 } |
| 232 | 231 |
| 233 QuotaFileIO::~QuotaFileIO() { | 232 QuotaFileIO::~QuotaFileIO() { |
| 234 // Note that this doesn't dispatch pending callbacks. | 233 // Note that this doesn't dispatch pending callbacks. |
| 235 STLDeleteContainerPointers(pending_operations_.begin(), | 234 STLDeleteContainerPointers(pending_operations_.begin(), |
| 236 pending_operations_.end()); | 235 pending_operations_.end()); |
| 237 STLDeleteContainerPointers(pending_callbacks_.begin(), | 236 STLDeleteContainerPointers(pending_callbacks_.begin(), |
| 238 pending_callbacks_.end()); | 237 pending_callbacks_.end()); |
| 239 } | 238 } |
| 240 | 239 |
| 241 bool QuotaFileIO::Write( | 240 bool QuotaFileIO::Write( |
| 242 int64_t offset, const char* buffer, int32_t bytes_to_write, | 241 int64_t offset, const char* buffer, int32_t bytes_to_write, |
| 243 WriteCallback* callback) { | 242 const WriteCallback& callback) { |
| 244 if (bytes_to_write <= 0) { | 243 if (bytes_to_write <= 0) { |
| 245 delete callback; | |
| 246 return false; | 244 return false; |
| 247 } | 245 } |
| 248 WriteOperation* op = new WriteOperation( | 246 WriteOperation* op = new WriteOperation( |
| 249 this, false, offset, buffer, bytes_to_write, callback); | 247 this, false, offset, buffer, bytes_to_write, callback); |
| 250 return RegisterOperationForQuotaChecks(op); | 248 return RegisterOperationForQuotaChecks(op); |
| 251 } | 249 } |
| 252 | 250 |
| 253 bool QuotaFileIO::SetLength(int64_t length, StatusCallback* callback) { | 251 bool QuotaFileIO::SetLength(int64_t length, const StatusCallback& callback) { |
| 254 DCHECK(pending_operations_.empty()); | 252 DCHECK(pending_operations_.empty()); |
| 255 SetLengthOperation* op = new SetLengthOperation( | 253 SetLengthOperation* op = new SetLengthOperation( |
| 256 this, false, length, callback); | 254 this, false, length, callback); |
| 257 return RegisterOperationForQuotaChecks(op); | 255 return RegisterOperationForQuotaChecks(op); |
| 258 } | 256 } |
| 259 | 257 |
| 260 bool QuotaFileIO::WillWrite( | 258 bool QuotaFileIO::WillWrite( |
| 261 int64_t offset, int32_t bytes_to_write, WriteCallback* callback) { | 259 int64_t offset, int32_t bytes_to_write, const WriteCallback& callback) { |
| 262 WriteOperation* op = new WriteOperation( | 260 WriteOperation* op = new WriteOperation( |
| 263 this, true, offset, NULL, bytes_to_write, callback); | 261 this, true, offset, NULL, bytes_to_write, callback); |
| 264 return RegisterOperationForQuotaChecks(op); | 262 return RegisterOperationForQuotaChecks(op); |
| 265 } | 263 } |
| 266 | 264 |
| 267 bool QuotaFileIO::WillSetLength(int64_t length, StatusCallback* callback) { | 265 bool QuotaFileIO::WillSetLength( |
| 266 int64_t length, const StatusCallback& callback) { |
| 268 DCHECK(pending_operations_.empty()); | 267 DCHECK(pending_operations_.empty()); |
| 269 SetLengthOperation* op = new SetLengthOperation(this, true, length, callback); | 268 SetLengthOperation* op = new SetLengthOperation(this, true, length, callback); |
| 270 return RegisterOperationForQuotaChecks(op); | 269 return RegisterOperationForQuotaChecks(op); |
| 271 } | 270 } |
| 272 | 271 |
| 273 PluginDelegate* QuotaFileIO::GetPluginDelegate() const { | 272 PluginDelegate* QuotaFileIO::GetPluginDelegate() const { |
| 274 PluginInstance* instance = ResourceTracker::Get()->GetInstance(pp_instance_); | 273 PluginInstance* instance = ResourceTracker::Get()->GetInstance(pp_instance_); |
| 275 if (instance) | 274 if (instance) |
| 276 return instance->delegate(); | 275 return instance->delegate(); |
| 277 return NULL; | 276 return NULL; |
| 278 } | 277 } |
| 279 | 278 |
| 280 bool QuotaFileIO::RegisterOperationForQuotaChecks( | 279 bool QuotaFileIO::RegisterOperationForQuotaChecks( |
| 281 PendingOperationBase* op_ptr) { | 280 PendingOperationBase* op_ptr) { |
| 282 scoped_ptr<PendingOperationBase> op(op_ptr); | 281 scoped_ptr<PendingOperationBase> op(op_ptr); |
| 283 if (pending_operations_.empty()) { | 282 if (pending_operations_.empty()) { |
| 284 // This is the first pending quota check. Run querying the file size | 283 // This is the first pending quota check. Run querying the file size |
| 285 // and available space. | 284 // and available space. |
| 286 outstanding_quota_queries_ = 0; | 285 outstanding_quota_queries_ = 0; |
| 287 outstanding_errors_ = 0; | 286 outstanding_errors_ = 0; |
| 288 | 287 |
| 289 PluginDelegate* plugin_delegate = GetPluginDelegate(); | 288 PluginDelegate* plugin_delegate = GetPluginDelegate(); |
| 290 if (!plugin_delegate) | 289 if (!plugin_delegate) |
| 291 return false; | 290 return false; |
| 292 | 291 |
| 293 // Query the file size. | 292 // Query the file size. |
| 294 ++outstanding_quota_queries_; | 293 ++outstanding_quota_queries_; |
| 295 if (!base::FileUtilProxy::GetFileInfoFromPlatformFile( | 294 if (!FileUtilProxy::GetFileInfoFromPlatformFile( |
| 296 plugin_delegate->GetFileThreadMessageLoopProxy(), file_, | 295 plugin_delegate->GetFileThreadMessageLoopProxy(), file_, |
| 297 callback_factory_.NewCallback( | 296 base::Bind(&QuotaFileIO::DidQueryInfoForQuota, |
| 298 &QuotaFileIO::DidQueryInfoForQuota))) { | 297 weak_ptr_factory_.GetWeakPtr()))) { |
| 299 // This makes the call fail synchronously; we do not fire the callback | 298 // This makes the call fail synchronously; we do not fire the callback |
| 300 // here but just delete the operation and return false. | 299 // here but just delete the operation and return false. |
| 301 return false; | 300 return false; |
| 302 } | 301 } |
| 303 | 302 |
| 304 // Query the current available space. | 303 // Query the current available space. |
| 305 ++outstanding_quota_queries_; | 304 ++outstanding_quota_queries_; |
| 306 plugin_delegate->QueryAvailableSpace( | 305 plugin_delegate->QueryAvailableSpace( |
| 307 GURL(file_url_.path()).GetOrigin(), storage_type_, | 306 GURL(file_url_.path()).GetOrigin(), storage_type_, |
| 308 base::Bind(&QuotaFileIO::DidQueryAvailableSpace, | 307 base::Bind(&QuotaFileIO::DidQueryAvailableSpace, |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 | 396 |
| 398 | 397 |
| 399 PluginDelegate* plugin_delegate = GetPluginDelegate(); | 398 PluginDelegate* plugin_delegate = GetPluginDelegate(); |
| 400 if (plugin_delegate) | 399 if (plugin_delegate) |
| 401 plugin_delegate->DidUpdateFile(file_url_, delta); | 400 plugin_delegate->DidUpdateFile(file_url_, delta); |
| 402 inflight_operations_ = 0; | 401 inflight_operations_ = 0; |
| 403 } | 402 } |
| 404 | 403 |
| 405 } // namespace ppapi | 404 } // namespace ppapi |
| 406 } // namespace webkit | 405 } // namespace webkit |
| OLD | NEW |