1 // Copyright (c) 2012 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 "ppapi/proxy/flash_file_resource.h" 6 7 #include "base/files/file_path.h" 8 #include "ipc/ipc_message.h" 9 #include "ppapi/c/pp_errors.h" 10 #include "ppapi/proxy/ppapi_messages.h" 11 #include "ppapi/shared_impl/file_type_conversion.h" 12 #include "ppapi/shared_impl/scoped_pp_var.h" 13 #include "ppapi/shared_impl/time_conversion.h" 14 #include "ppapi/shared_impl/var.h" 15 #include "ppapi/thunk/enter.h" 16 17 namespace ppapi { 18 namespace proxy { 19 20 namespace { 21 22 // Returns the path that a PPB_FileRef resource references as long as it is an 23 // PP_FILESYSTEMTYPE_EXTERNAL path. Returns an empty string on error. 24 std::string GetPathFromFileRef(PP_Resource file_ref) { 25 thunk::EnterResourceNoLock<thunk::PPB_FileRef_API> enter(file_ref, true); 26 if (enter.failed()) 27 return std::string(); 28 if (enter.object()->GetFileSystemType() != PP_FILESYSTEMTYPE_EXTERNAL) 29 return std::string(); 30 ScopedPPVar var(ScopedPPVar::PassRef(), enter.object()->GetAbsolutePath()); 31 StringVar* string_var = StringVar::FromPPVar(var.get()); 32 if (!string_var) 33 return std::string(); 34 return string_var->value(); 35 } 36 37 } // namespace 38 39 FlashFileResource::FlashFileResource(Connection connection, 40 PP_Instance instance) 41 : PluginResource(connection, instance) { 42 SendCreate(BROWSER, PpapiHostMsg_FlashFile_Create()); 43 } 44 45 FlashFileResource::~FlashFileResource() { 46 } 47 48 thunk::PPB_Flash_File_API* FlashFileResource::AsPPB_Flash_File_API() { 49 return this; 50 } 51 52 int32_t FlashFileResource::OpenFile(PP_Instance /*instance*/, 53 const char* path, 54 int32_t mode, 55 PP_FileHandle* file) { 56 return OpenFileHelper(path, PepperFilePath::DOMAIN_MODULE_LOCAL, mode, file); 57 } 58 59 int32_t FlashFileResource::RenameFile(PP_Instance /*instance*/, 60 const char* path_from, 61 const char* path_to) { 62 PepperFilePath pepper_from(PepperFilePath::DOMAIN_MODULE_LOCAL, 63 base::FilePath::FromUTF8Unsafe(path_from)); 64 PepperFilePath pepper_to(PepperFilePath::DOMAIN_MODULE_LOCAL, 65 base::FilePath::FromUTF8Unsafe(path_to)); 66 67 int32_t error = SyncCall<IPC::Message>( 68 BROWSER, PpapiHostMsg_FlashFile_RenameFile(pepper_from, pepper_to)); 69 70 return error; 71 } 72 73 int32_t FlashFileResource::DeleteFileOrDir(PP_Instance /*instance*/, 74 const char* path, 75 PP_Bool recursive) { 76 PepperFilePath pepper_path(PepperFilePath::DOMAIN_MODULE_LOCAL, 77 base::FilePath::FromUTF8Unsafe(path)); 78 79 int32_t error = SyncCall<IPC::Message>( 80 BROWSER, PpapiHostMsg_FlashFile_DeleteFileOrDir(pepper_path, 81 PP_ToBool(recursive))); 82 83 return error; 84 } 85 86 int32_t FlashFileResource::CreateDir(PP_Instance /*instance*/, 87 const char* path) { 88 PepperFilePath pepper_path(PepperFilePath::DOMAIN_MODULE_LOCAL, 89 base::FilePath::FromUTF8Unsafe(path)); 90 91 int32_t error = SyncCall<IPC::Message>(BROWSER, 92 PpapiHostMsg_FlashFile_CreateDir(pepper_path)); 93 94 return error; 95 } 96 97 int32_t FlashFileResource::QueryFile(PP_Instance /*instance*/, 98 const char* path, 99 PP_FileInfo* info) { 100 return QueryFileHelper(path, PepperFilePath::DOMAIN_MODULE_LOCAL, info); 101 } 102 103 int32_t FlashFileResource::GetDirContents(PP_Instance /*instance*/, 104 const char* path, 105 PP_DirContents_Dev** contents) { 106 ppapi::DirContents entries; 107 PepperFilePath pepper_path(PepperFilePath::DOMAIN_MODULE_LOCAL, 108 base::FilePath::FromUTF8Unsafe(path)); 109 110 int32_t error = SyncCall<PpapiPluginMsg_FlashFile_GetDirContentsReply>( 111 BROWSER, PpapiHostMsg_FlashFile_GetDirContents(pepper_path), &entries); 112 113 if (error == PP_OK) { 114 // Copy the serialized dir entries to the output struct. 115 *contents = new PP_DirContents_Dev; 116 (*contents)->count = static_cast<int32_t>(entries.size()); 117 (*contents)->entries = new PP_DirEntry_Dev[entries.size()]; 118 for (size_t i = 0; i < entries.size(); i++) { 119 const ppapi::DirEntry& source = entries[i]; 120 PP_DirEntry_Dev* dest = &(*contents)->entries[i]; 121 std::string name = source.name.AsUTF8Unsafe(); 122 char* name_copy = new char[name.size() + 1]; 123 memcpy(name_copy, name.c_str(), name.size() + 1); 124 dest->name = name_copy; 125 dest->is_dir = PP_FromBool(source.is_dir); 126 } 127 } 128 129 return error; 130 } 131 132 void FlashFileResource::FreeDirContents(PP_Instance /*instance*/, 133 PP_DirContents_Dev* contents) { 134 for (int32_t i = 0; i < contents->count; ++i) 135 delete[] contents->entries[i].name; 136 delete[] contents->entries; 137 delete contents; 138 } 139 140 int32_t FlashFileResource::CreateTemporaryFile(PP_Instance /*instance*/, 141 PP_FileHandle* file) { 142 if (!file) 143 return PP_ERROR_BADARGUMENT; 144 145 IPC::Message unused; 146 ResourceMessageReplyParams reply_params; 147 int32_t error = GenericSyncCall(BROWSER, 148 PpapiHostMsg_FlashFile_CreateTemporaryFile(), &unused, &reply_params); 149 if (error != PP_OK) 150 return error; 151 152 IPC::PlatformFileForTransit transit_file; 153 if (!reply_params.TakeFileHandleAtIndex(0, &transit_file)) 154 return PP_ERROR_FAILED; 155 156 *file = IPC::PlatformFileForTransitToPlatformFile(transit_file); 157 return PP_OK; 158 } 159 160 int32_t FlashFileResource::OpenFileRef(PP_Instance /*instance*/, 161 PP_Resource file_ref, 162 int32_t mode, 163 PP_FileHandle* file) { 164 return OpenFileHelper(GetPathFromFileRef(file_ref), 165 PepperFilePath::DOMAIN_ABSOLUTE, mode, file); 166 } 167 168 int32_t FlashFileResource::QueryFileRef(PP_Instance /*instance*/, 169 PP_Resource file_ref, 170 PP_FileInfo* info) { 171 return QueryFileHelper(GetPathFromFileRef(file_ref), 172 PepperFilePath::DOMAIN_ABSOLUTE, info); 173 } 174 175 int32_t FlashFileResource::OpenFileHelper(const std::string& path, 176 PepperFilePath::Domain domain_type, 177 int32_t mode, 178 PP_FileHandle* file) { 179 if (path.empty() || 180 !ppapi::PepperFileOpenFlagsToPlatformFileFlags(mode, NULL) || 181 !file) 182 return PP_ERROR_BADARGUMENT; 183 184 PepperFilePath pepper_path(domain_type, base::FilePath::FromUTF8Unsafe(path)); 185 186 IPC::Message unused; 187 ResourceMessageReplyParams reply_params; 188 int32_t error = GenericSyncCall(BROWSER, 189 PpapiHostMsg_FlashFile_OpenFile(pepper_path, mode), &unused, 190 &reply_params); 191 if (error != PP_OK) 192 return error; 193 194 IPC::PlatformFileForTransit transit_file; 195 if (!reply_params.TakeFileHandleAtIndex(0, &transit_file)) 196 return PP_ERROR_FAILED; 197 198 *file = IPC::PlatformFileForTransitToPlatformFile(transit_file); 199 return PP_OK; 200 } 201 202 int32_t FlashFileResource::QueryFileHelper(const std::string& path, 203 PepperFilePath::Domain domain_type, 204 PP_FileInfo* info) { 205 if (path.empty() || !info) 206 return PP_ERROR_BADARGUMENT; 207 208 base::PlatformFileInfo file_info; 209 PepperFilePath pepper_path(domain_type, base::FilePath::FromUTF8Unsafe(path)); 210 211 int32_t error = SyncCall<PpapiPluginMsg_FlashFile_QueryFileReply>(BROWSER, 212 PpapiHostMsg_FlashFile_QueryFile(pepper_path), &file_info); 213 214 if (error == PP_OK) { 215 info->size = file_info.size; 216 info->creation_time = TimeToPPTime(file_info.creation_time); 217 info->last_access_time = TimeToPPTime(file_info.last_accessed); 218 info->last_modified_time = TimeToPPTime(file_info.last_modified); 219 info->system_type = PP_FILESYSTEMTYPE_EXTERNAL; 220 if (file_info.is_directory) 221 info->type = PP_FILETYPE_DIRECTORY; 222 else 223 info->type = PP_FILETYPE_REGULAR; 224 } 225 226 return error; 227 } 228 229 } // namespace proxy 230 } // namespace ppapi 231