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.
5 #include "ppapi/proxy/flash_file_resource.h"
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"
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);
29 if (enter
.object()->GetFileSystemType() != PP_FILESYSTEMTYPE_EXTERNAL
)
31 ScopedPPVar
var(ScopedPPVar::PassRef(), enter
.object()->GetAbsolutePath());
32 StringVar
* string_var
= StringVar::FromPPVar(var
.get());
35 return string_var
->value();
40 FlashFileResource::FlashFileResource(Connection connection
,
42 : PluginResource(connection
, instance
) {
43 SendCreate(BROWSER
, PpapiHostMsg_FlashFile_Create());
46 FlashFileResource::~FlashFileResource() {
49 thunk::PPB_Flash_File_API
* FlashFileResource::AsPPB_Flash_File_API() {
53 int32_t FlashFileResource::OpenFile(PP_Instance
/*instance*/,
56 PP_FileHandle
* file
) {
57 return OpenFileHelper(path
, PepperFilePath::DOMAIN_MODULE_LOCAL
, mode
, file
);
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
));
68 int32_t error
= SyncCall
<IPC::Message
>(
69 BROWSER
, PpapiHostMsg_FlashFile_RenameFile(pepper_from
, pepper_to
));
74 int32_t FlashFileResource::DeleteFileOrDir(PP_Instance
/*instance*/,
77 PepperFilePath
pepper_path(PepperFilePath::DOMAIN_MODULE_LOCAL
,
78 base::FilePath::FromUTF8Unsafe(path
));
80 int32_t error
= SyncCall
<IPC::Message
>(
81 BROWSER
, PpapiHostMsg_FlashFile_DeleteFileOrDir(pepper_path
,
82 PP_ToBool(recursive
)));
87 int32_t FlashFileResource::CreateDir(PP_Instance
/*instance*/,
89 PepperFilePath
pepper_path(PepperFilePath::DOMAIN_MODULE_LOCAL
,
90 base::FilePath::FromUTF8Unsafe(path
));
92 int32_t error
= SyncCall
<IPC::Message
>(BROWSER
,
93 PpapiHostMsg_FlashFile_CreateDir(pepper_path
));
98 int32_t FlashFileResource::QueryFile(PP_Instance
/*instance*/,
101 return QueryFileHelper(path
, PepperFilePath::DOMAIN_MODULE_LOCAL
, info
);
104 int32_t FlashFileResource::GetDirContents(PP_Instance
/*instance*/,
106 PP_DirContents_Dev
** contents
) {
107 ppapi::DirContents entries
;
108 PepperFilePath
pepper_path(PepperFilePath::DOMAIN_MODULE_LOCAL
,
109 base::FilePath::FromUTF8Unsafe(path
));
111 int32_t error
= SyncCall
<PpapiPluginMsg_FlashFile_GetDirContentsReply
>(
112 BROWSER
, PpapiHostMsg_FlashFile_GetDirContents(pepper_path
), &entries
);
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
);
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
;
141 int32_t FlashFileResource::CreateTemporaryFile(PP_Instance
/*instance*/,
142 PP_FileHandle
* file
) {
144 return PP_ERROR_BADARGUMENT
;
147 ResourceMessageReplyParams reply_params
;
148 int32_t error
= GenericSyncCall(BROWSER
,
149 PpapiHostMsg_FlashFile_CreateTemporaryFile(), &unused
, &reply_params
);
153 IPC::PlatformFileForTransit transit_file
;
154 if (!reply_params
.TakeFileHandleAtIndex(0, &transit_file
))
155 return PP_ERROR_FAILED
;
157 *file
= IPC::PlatformFileForTransitToPlatformFile(transit_file
);
161 int32_t FlashFileResource::OpenFileRef(PP_Instance
/*instance*/,
162 PP_Resource file_ref
,
164 PP_FileHandle
* file
) {
165 return OpenFileHelper(GetPathFromFileRef(file_ref
),
166 PepperFilePath::DOMAIN_ABSOLUTE
, mode
, file
);
169 int32_t FlashFileResource::QueryFileRef(PP_Instance
/*instance*/,
170 PP_Resource file_ref
,
172 return QueryFileHelper(GetPathFromFileRef(file_ref
),
173 PepperFilePath::DOMAIN_ABSOLUTE
, info
);
176 int32_t FlashFileResource::OpenFileHelper(const std::string
& path
,
177 PepperFilePath::Domain domain_type
,
179 PP_FileHandle
* file
) {
181 !ppapi::PepperFileOpenFlagsToPlatformFileFlags(mode
, NULL
) ||
183 return PP_ERROR_BADARGUMENT
;
185 PepperFilePath
pepper_path(domain_type
, base::FilePath::FromUTF8Unsafe(path
));
188 ResourceMessageReplyParams reply_params
;
189 int32_t error
= GenericSyncCall(BROWSER
,
190 PpapiHostMsg_FlashFile_OpenFile(pepper_path
, mode
), &unused
,
195 IPC::PlatformFileForTransit transit_file
;
196 if (!reply_params
.TakeFileHandleAtIndex(0, &transit_file
))
197 return PP_ERROR_FAILED
;
199 *file
= IPC::PlatformFileForTransitToPlatformFile(transit_file
);
203 int32_t FlashFileResource::QueryFileHelper(const std::string
& path
,
204 PepperFilePath::Domain domain_type
,
206 if (path
.empty() || !info
)
207 return PP_ERROR_BADARGUMENT
;
209 base::File::Info file_info
;
210 PepperFilePath
pepper_path(domain_type
, base::FilePath::FromUTF8Unsafe(path
));
212 int32_t error
= SyncCall
<PpapiPluginMsg_FlashFile_QueryFileReply
>(BROWSER
,
213 PpapiHostMsg_FlashFile_QueryFile(pepper_path
), &file_info
);
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
;
224 info
->type
= PP_FILETYPE_REGULAR
;