OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include <algorithm> |
| 6 #include <chrono> |
| 7 #include <deque> |
| 8 #include <map> |
| 9 #include <set> |
| 10 #include <sstream> |
| 11 #include <string.h> |
| 12 |
| 13 #include "memfilesystem.h" |
| 14 #include "ppapi/c/pp_errors.h" |
| 15 #include "ppapi/cpp/dev/filesystem_provider.h" |
| 16 #include "ppapi/cpp/instance.h" |
| 17 #include "ppapi/cpp/module.h" |
| 18 #include "ppapi/cpp/var.h" |
| 19 #include "ppapi/utility/completion_callback_factory.h" |
| 20 #include "ppapi/cpp/input_event.h" |
| 21 |
| 22 namespace { |
| 23 template<class T> |
| 24 class FilesystemHelper { |
| 25 public: |
| 26 FilesystemHelper() |
| 27 : callback_fact_(this) { |
| 28 Init(); |
| 29 } |
| 30 virtual ~FilesystemHelper(){} |
| 31 virtual void OnUnmountRequest(int32_t request_id)=0; |
| 32 virtual void OnMetadataRequest( |
| 33 const std::string& file_path, bool thumbnail, int32_t request_id)=0; |
| 34 virtual void OnReadDirectoryRequest( |
| 35 const std::string& directory_path, int32_t request_id)=0; |
| 36 virtual void OnOpenFileRequest( |
| 37 const std::string& file_path, const PP_OpenFileMode_Dev& file_mode, |
| 38 int32_t request_id)=0; |
| 39 virtual void OnCloseFileRequest( |
| 40 int32_t request_id, int32_t open_request_id)=0; |
| 41 virtual void OnReadFileRequest( |
| 42 int32_t open_request_id, |
| 43 uint64_t offset, |
| 44 uint64_t length, |
| 45 int32_t request_id)=0; |
| 46 virtual void OnCreateDirectoryRequest( |
| 47 const std::string& directory_path, |
| 48 bool recursive, int32_t request_id)=0; |
| 49 virtual void OnDeleteEntryRequest( |
| 50 const std::string& file_entry, bool recursive, int32_t request_id)=0; |
| 51 virtual void OnCreateFileRequest( |
| 52 const std::string& file_path, int32_t request_id)=0; |
| 53 virtual void OnCopyEntryRequest( |
| 54 const std::string& source_path, |
| 55 const std::string& target_path, |
| 56 int32_t request_id)=0; |
| 57 virtual void OnMoveEntryRequest( |
| 58 const std::string& source_path, |
| 59 const std::string& target_path, int32_t request_id)=0; |
| 60 virtual void OnTruncateRequest( |
| 61 const std::string& file_path, int32_t offset, int32_t request_id)=0; |
| 62 virtual void OnWriteRequest(int32_t, uint64_t, uint64_t, |
| 63 const char*, int32_t)=0; |
| 64 virtual void OnAbortRequest(int32_t request_id, int32_t open_request_id)=0; |
| 65 private: |
| 66 bool Init(){ |
| 67 static_cast<T*>(this)->GetNextRequest( |
| 68 callback_fact_.NewCallbackWithOutput( |
| 69 &FilesystemHelper::OnRequestReceived)); |
| 70 return true; |
| 71 } |
| 72 // Dispatcher |
| 73 void OnRequestReceived(int32_t result, PP_FilesystemRequest request){ |
| 74 if (result==PP_OK) { |
| 75 switch (request.operation_type) { |
| 76 case PP_OperationType_UNMOUNT: |
| 77 static_cast<T*>(this)->OnUnmountRequest(request.request_id); |
| 78 break; |
| 79 case PP_OperationType_GETMETADATA: |
| 80 static_cast<T*>(this)->OnMetadataRequest( |
| 81 request.value.as_metadata.entry_path, |
| 82 request.value.as_metadata.thumbnail, |
| 83 request.request_id); |
| 84 break; |
| 85 case PP_OperationType_READDIRECTORY: |
| 86 static_cast<T*>(this)->OnReadDirectoryRequest( |
| 87 request.value.as_read_directory.directory_path, |
| 88 request.request_id); |
| 89 break; |
| 90 case PP_OperationType_OPENFILE: |
| 91 static_cast<T*>(this)->OnOpenFileRequest( |
| 92 request.value.as_open_file.file_path, |
| 93 request.value.as_open_file.mode, request.request_id); |
| 94 break; |
| 95 case PP_OperationType_CLOSEFILE: |
| 96 static_cast<T*>(this)->OnCloseFileRequest( |
| 97 request.value.as_close_file.open_request_id, |
| 98 request.request_id); |
| 99 break; |
| 100 case PP_OperationType_READFILE: |
| 101 static_cast<T*>(this)->OnReadFileRequest( |
| 102 request.value.as_read_file.open_request_id, |
| 103 request.value.as_read_file.offset, |
| 104 request.value.as_read_file.length, |
| 105 request.request_id); |
| 106 break; |
| 107 case PP_OperationType_CREATEDIRECTORY: |
| 108 static_cast<T*>(this)->OnCreateDirectoryRequest( |
| 109 request.value.as_create_directory.directory_path, |
| 110 request.value.as_create_directory.recursive, |
| 111 request.request_id); |
| 112 break; |
| 113 case PP_OperationType_DELETEENTRY: |
| 114 static_cast<T*>(this)->OnDeleteEntryRequest( |
| 115 request.value.as_delete_entry.entry_path, |
| 116 request.value.as_delete_entry.recursive,request.request_id); |
| 117 break; |
| 118 case PP_OperationType_CREATEFILE: |
| 119 static_cast<T*>(this)->OnCreateFileRequest( |
| 120 request.value.as_create_file.file_path, request.request_id); |
| 121 break; |
| 122 case PP_OperationType_COPYENTRY: |
| 123 static_cast<T*>(this)->OnCopyEntryRequest( |
| 124 request.value.as_copy_entry.source_path, |
| 125 request.value.as_copy_entry.target_path, |
| 126 request.request_id); |
| 127 break; |
| 128 case PP_OperationType_MOVEENTRY: |
| 129 static_cast<T*>(this)->OnMoveEntryRequest( |
| 130 request.value.as_move_entry.source_path, |
| 131 request.value.as_move_entry.target_path, |
| 132 request.request_id); |
| 133 break; |
| 134 case PP_OperationType_TRUNCATEENTRY: |
| 135 static_cast<T*>(this)->OnTruncateRequest( |
| 136 request.value.as_truncate.file_path, |
| 137 request.value.as_truncate.length, |
| 138 request.request_id); |
| 139 break; |
| 140 case PP_OperationType_WRITEFILE: |
| 141 static_cast<T*>(this)->OnWriteRequest( |
| 142 request.value.as_write_file.open_request_id, |
| 143 request.value.as_write_file.offset, |
| 144 request.value.as_write_file.data_size, |
| 145 (char*)request.value.as_write_file.data, |
| 146 request.request_id); |
| 147 break; |
| 148 case PP_OperationType_ABORT: |
| 149 static_cast<T*>(this)->OnAbortRequest( |
| 150 request.value.as_abort.operation_request_id, |
| 151 request.request_id); |
| 152 break; |
| 153 default: |
| 154 break; |
| 155 } |
| 156 } |
| 157 // Re-register the callback |
| 158 static_cast<T*>(this)->GetNextRequest( |
| 159 callback_fact_.NewCallbackWithOutput( |
| 160 &FilesystemHelper::OnRequestReceived)); |
| 161 } |
| 162 private: |
| 163 pp::CompletionCallbackFactory< FilesystemHelper<T> > callback_fact_; |
| 164 }; |
| 165 }// namespace |
| 166 class MyInstance : |
| 167 public pp::Instance, |
| 168 public pp::Filesystem_Provider_Dev, |
| 169 public FilesystemHelper<MyInstance> { |
| 170 public: |
| 171 MyInstance(PP_Instance instance) |
| 172 :pp::Instance(instance), |
| 173 Filesystem_Provider_Dev(this), |
| 174 callback_factory_(this), |
| 175 filesystem_id_("in-memory-fs"), |
| 176 display_name_("Test-Filesystem"), |
| 177 mounted_(false) { |
| 178 Initialize(); |
| 179 } |
| 180 |
| 181 virtual ~MyInstance() { |
| 182 } |
| 183 |
| 184 void Initialize() { |
| 185 Mount(filesystem_id_, display_name_, true, 0, |
| 186 callback_factory_.NewCallbackWithOutput( |
| 187 &MyInstance::OnMountCompletion)); |
| 188 } |
| 189 void OnMountCompletion(int32_t result, PP_ProviderError_Dev error ) { |
| 190 if ( result!=PP_OK || |
| 191 error!=PP_ProviderError_OK) { |
| 192 return; |
| 193 } |
| 194 mounted_ = true; |
| 195 } |
| 196 |
| 197 // Filesystem_Provider_Dev interfaces |
| 198 void OnUnmountRequest(int32_t request_id) { |
| 199 // close connections, clean caches |
| 200 SendSuccessResponse(PP_OperationType_UNMOUNT,request_id); |
| 201 } |
| 202 |
| 203 void OnMetadataRequest( |
| 204 const std::string &entry_path, |
| 205 bool thumbnail, int32_t request_id) { |
| 206 |
| 207 filesystem::Filesystem::NameInodePair meta; |
| 208 if( filesystem_.GetMetadata(entry_path,meta)== |
| 209 filesystem::Filesystem::File_System_Error_NOT_FOUND ) { |
| 210 SendErrorResponse( |
| 211 PP_OperationType_GETMETADATA, |
| 212 PP_ProviderError_NOT_FOUND, |
| 213 request_id ); |
| 214 } else { |
| 215 PP_EntryMetadata_Dev metadata; |
| 216 memset(&metadata, 0x0, sizeof(metadata)); |
| 217 metadata.is_directory = PP_FromBool(meta.second->file_type()== |
| 218 filesystem::Inode::FILE_TYPE_DIR); |
| 219 // Should check result |
| 220 snprintf(metadata.name, |
| 221 sizeof(metadata.name), |
| 222 "%s", meta.first.c_str()); |
| 223 snprintf( metadata.modification_time, |
| 224 sizeof(metadata.modification_time), |
| 225 "%s",meta.second->file_modified().c_str()); |
| 226 metadata.size = meta.second->size(); |
| 227 SendMetadataSuccessResponse(metadata,request_id); |
| 228 } |
| 229 } |
| 230 |
| 231 void OnReadDirectoryRequest( |
| 232 const std::string &directory_path, |
| 233 int32_t request_id) { |
| 234 std::vector<filesystem::Filesystem::NameInodePair> metas; |
| 235 |
| 236 if ( filesystem_.ReadDirectory(directory_path,metas)== |
| 237 filesystem::Filesystem::File_System_Error_NONE ) { |
| 238 std::vector<PP_EntryMetadata_Dev> metadatas; |
| 239 PP_EntryMetadata_Dev metadata; |
| 240 for(std::vector<filesystem::Filesystem::NameInodePair>::iterator |
| 241 it = metas.begin(); |
| 242 it != metas.end(); |
| 243 ++it) |
| 244 { |
| 245 memset(&metadata, 0x0, sizeof(metadata)); |
| 246 metadata.is_directory = PP_FromBool(it->second->file_type()== |
| 247 filesystem::Inode::FILE_TYPE_DIR); |
| 248 snprintf(metadata.name, |
| 249 sizeof(metadata.name), |
| 250 "%s", it->first.c_str()); |
| 251 snprintf( metadata.modification_time, |
| 252 sizeof(metadata.modification_time), |
| 253 "%s",it->second->file_modified().c_str()); |
| 254 metadata.size = it->second->size(); |
| 255 metadatas.push_back(metadata); |
| 256 } |
| 257 SendReadDirectorySuccessResponse(metadatas,false, request_id); |
| 258 } else { |
| 259 SendErrorResponse( |
| 260 PP_OperationType_READDIRECTORY, |
| 261 PP_ProviderError_FAILED, request_id ); |
| 262 } |
| 263 } |
| 264 void OnOpenFileRequest( |
| 265 const std::string &file_path, |
| 266 const PP_OpenFileMode_Dev &mode, |
| 267 int32_t request_id) { |
| 268 filesystem::Filesystem::NameInodePair meta; |
| 269 if (filesystem_.GetMetadata(file_path,meta)== |
| 270 filesystem::Filesystem::File_System_Error_NONE) { |
| 271 opened_files_.insert( std::pair<int,std::string>(request_id, file_path)); |
| 272 SendSuccessResponse( |
| 273 PP_OperationType_OPENFILE, |
| 274 request_id ); |
| 275 } else { |
| 276 SendErrorResponse( |
| 277 PP_OperationType_OPENFILE, |
| 278 PP_ProviderError_FAILED,request_id); |
| 279 } |
| 280 } |
| 281 |
| 282 void OnCloseFileRequest(int32_t open_request_id,int32_t request_id) { |
| 283 ListOfOpenedFilesIterator it = opened_files_.find(open_request_id); |
| 284 if (it==opened_files_.end()) {// no open request |
| 285 SendErrorResponse( |
| 286 PP_OperationType_CLOSEFILE, |
| 287 PP_ProviderError_FAILED, |
| 288 request_id ); |
| 289 } else { |
| 290 SendSuccessResponse(PP_OperationType_CLOSEFILE, request_id); |
| 291 } |
| 292 } |
| 293 |
| 294 void OnReadFileRequest( |
| 295 int32_t open_request_id, |
| 296 uint64_t offset, |
| 297 uint64_t length, |
| 298 int32_t request_id) { |
| 299 ListOfOpenedFilesIterator it = opened_files_.find(open_request_id); |
| 300 if (it==opened_files_.end()) { |
| 301 SendErrorResponse( |
| 302 PP_OperationType_READFILE, |
| 303 PP_ProviderError_FAILED, |
| 304 request_id); |
| 305 } else { |
| 306 size_t in_out_length=length; |
| 307 const char *out_data = nullptr; |
| 308 if(filesystem::Filesystem::File_System_Error_FAILED == |
| 309 filesystem_.ReadFromFile( |
| 310 it->second, |
| 311 offset, |
| 312 &in_out_length, &out_data ) ) { |
| 313 SendErrorResponse( |
| 314 PP_OperationType_READFILE, |
| 315 PP_ProviderError_FAILED, |
| 316 request_id); |
| 317 } else { |
| 318 SendReadFileSuccessResponse( |
| 319 in_out_length, out_data, false, request_id ); |
| 320 } |
| 321 } |
| 322 } |
| 323 void OnCreateDirectoryRequest ( |
| 324 const std::string &directory_path, |
| 325 bool recursive, int32_t request_id) { |
| 326 if(filesystem::Filesystem::File_System_Error_NONE == |
| 327 filesystem_.CreateDirectory(directory_path,recursive)) |
| 328 SendSuccessResponse(PP_OperationType_CREATEDIRECTORY,request_id); |
| 329 else |
| 330 SendErrorResponse(PP_OperationType_CREATEDIRECTORY, |
| 331 PP_ProviderError_FAILED, request_id); |
| 332 } |
| 333 void OnDeleteEntryRequest( |
| 334 const std::string &entry_path, |
| 335 bool recursive, int32_t request_id) { |
| 336 |
| 337 if(filesystem::Filesystem::File_System_Error_NONE== |
| 338 filesystem_.DeleteEntry(entry_path,recursive)) |
| 339 SendSuccessResponse(PP_OperationType_DELETEENTRY,request_id); |
| 340 else |
| 341 SendErrorResponse( |
| 342 PP_OperationType_DELETEENTRY, |
| 343 PP_ProviderError_NOT_FOUND, |
| 344 request_id); |
| 345 } |
| 346 |
| 347 void OnCreateFileRequest( |
| 348 const std::string &file_path, int32_t request_id) { |
| 349 if(filesystem::Filesystem::File_System_Error_NONE== |
| 350 filesystem_.CreateFile(file_path)) |
| 351 SendSuccessResponse(PP_OperationType_CREATEFILE,request_id); |
| 352 else |
| 353 SendErrorResponse( |
| 354 PP_OperationType_CREATEFILE, |
| 355 PP_ProviderError_FAILED, |
| 356 request_id); |
| 357 } |
| 358 void OnCopyEntryRequest( |
| 359 const std::string &source_path, |
| 360 const std::string &target_path, |
| 361 int32_t request_id) { |
| 362 if(filesystem::Filesystem::File_System_Error_NONE== |
| 363 filesystem_.CopyEntry(source_path,target_path)) |
| 364 SendSuccessResponse(PP_OperationType_COPYENTRY,request_id); |
| 365 else |
| 366 SendErrorResponse(PP_OperationType_COPYENTRY, |
| 367 PP_ProviderError_FAILED, request_id ); |
| 368 } |
| 369 void OnMoveEntryRequest( |
| 370 const std::string &source_path, |
| 371 const std::string &target_path, |
| 372 int32_t request_id) { |
| 373 if ( filesystem::Filesystem::File_System_Error_NONE== |
| 374 filesystem_.MoveEntry(source_path,target_path)) |
| 375 SendSuccessResponse(PP_OperationType_MOVEENTRY, request_id); |
| 376 else |
| 377 SendErrorResponse( |
| 378 PP_OperationType_MOVEENTRY, |
| 379 PP_ProviderError_FAILED, |
| 380 request_id ); |
| 381 } |
| 382 void OnTruncateRequest( |
| 383 const std::string &file_path, |
| 384 int32_t length, |
| 385 int32_t request_id) { |
| 386 if (filesystem::Filesystem::File_System_Error_NONE== |
| 387 filesystem_.Truncate(file_path, length)) |
| 388 SendSuccessResponse(PP_OperationType_TRUNCATEENTRY,request_id); |
| 389 else |
| 390 SendErrorResponse(PP_OperationType_TRUNCATEENTRY, |
| 391 PP_ProviderError_FAILED,request_id ); |
| 392 } |
| 393 void OnWriteRequest(int32_t open_request_id, uint64_t offset, |
| 394 uint64_t data_size, const char *data, |
| 395 int32_t request_id) { |
| 396 ListOfOpenedFilesIterator it = opened_files_.find(open_request_id); |
| 397 if (it==opened_files_.end()){ |
| 398 SendErrorResponse( |
| 399 PP_OperationType_WRITEFILE, |
| 400 PP_ProviderError_FAILED, |
| 401 request_id); |
| 402 } else { |
| 403 if (filesystem::Filesystem::File_System_Error_NONE!= |
| 404 filesystem_.WriteToFile(it->second, offset, data_size, data)) { |
| 405 SendErrorResponse( |
| 406 PP_OperationType_WRITEFILE, |
| 407 PP_ProviderError_FAILED, |
| 408 request_id ); |
| 409 } else { |
| 410 SendSuccessResponse(PP_OperationType_WRITEFILE,request_id); |
| 411 } |
| 412 } |
| 413 // Free buffer |
| 414 FreeWriteRequestBuffer(data); |
| 415 } |
| 416 void OnAbortRequest( |
| 417 int32_t operation_request_id, int32_t request_id) { |
| 418 SendSuccessResponse(PP_OperationType_ABORT,request_id); |
| 419 } |
| 420 private: |
| 421 typedef std::map<int,std::string> ListOfOpenedFiles; |
| 422 typedef ListOfOpenedFiles::iterator ListOfOpenedFilesIterator; |
| 423 ListOfOpenedFiles opened_files_; |
| 424 pp::CompletionCallbackFactory<MyInstance> callback_factory_; |
| 425 // Filesystem properties |
| 426 filesystem::Filesystem filesystem_; |
| 427 std::string filesystem_id_; |
| 428 std::string display_name_; |
| 429 bool mounted_; |
| 430 }; |
| 431 |
| 432 class MyModule : public pp::Module { |
| 433 public: |
| 434 virtual pp::Instance* CreateInstance(PP_Instance instance) { |
| 435 return new MyInstance(instance); |
| 436 } |
| 437 }; |
| 438 |
| 439 namespace pp { |
| 440 |
| 441 // Factory function for your specialization of the Module object. |
| 442 Module* CreateModule() { |
| 443 return new MyModule(); |
| 444 } |
| 445 |
| 446 } // namespace pp |
OLD | NEW |