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