OLD | NEW |
| (Empty) |
1 // Copyright (c) 2010 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 "webkit/glue/plugins/pepper_file_ref.h" | |
6 | |
7 #include "base/string_util.h" | |
8 #include "base/utf_string_conversions.h" | |
9 #include "ppapi/c/pp_errors.h" | |
10 #include "webkit/glue/plugins/pepper_common.h" | |
11 #include "webkit/glue/plugins/pepper_directory_reader.h" | |
12 #include "webkit/glue/plugins/pepper_file_callbacks.h" | |
13 #include "webkit/glue/plugins/pepper_file_system.h" | |
14 #include "webkit/glue/plugins/pepper_plugin_delegate.h" | |
15 #include "webkit/glue/plugins/pepper_plugin_instance.h" | |
16 #include "webkit/glue/plugins/pepper_plugin_module.h" | |
17 #include "webkit/glue/plugins/pepper_var.h" | |
18 | |
19 namespace pepper { | |
20 | |
21 namespace { | |
22 | |
23 bool IsValidLocalPath(const std::string& path) { | |
24 // The path must start with '/' | |
25 if (path.empty() || path[0] != '/') | |
26 return false; | |
27 | |
28 // The path must contain valid UTF-8 characters. | |
29 if (!IsStringUTF8(path)) | |
30 return false; | |
31 | |
32 return true; | |
33 } | |
34 | |
35 void TrimTrailingSlash(std::string* path) { | |
36 // If this path ends with a slash, then normalize it away unless path is the | |
37 // root path. | |
38 if (path->size() > 1 && path->at(path->size() - 1) == '/') | |
39 path->erase(path->size() - 1, 1); | |
40 } | |
41 | |
42 PP_Resource Create(PP_Resource file_system_id, const char* path) { | |
43 scoped_refptr<FileSystem> file_system( | |
44 Resource::GetAs<FileSystem>(file_system_id)); | |
45 if (!file_system) | |
46 return 0; | |
47 | |
48 if (!file_system->instance()) | |
49 return 0; | |
50 | |
51 std::string validated_path(path); | |
52 if (!IsValidLocalPath(validated_path)) | |
53 return 0; | |
54 TrimTrailingSlash(&validated_path); | |
55 | |
56 FileRef* file_ref = new FileRef(file_system->instance()->module(), | |
57 file_system, | |
58 validated_path); | |
59 return file_ref->GetReference(); | |
60 } | |
61 | |
62 PP_Bool IsFileRef(PP_Resource resource) { | |
63 return BoolToPPBool(!!Resource::GetAs<FileRef>(resource)); | |
64 } | |
65 | |
66 PP_FileSystemType_Dev GetFileSystemType(PP_Resource file_ref_id) { | |
67 scoped_refptr<FileRef> file_ref(Resource::GetAs<FileRef>(file_ref_id)); | |
68 if (!file_ref) | |
69 return PP_FILESYSTEMTYPE_EXTERNAL; | |
70 return file_ref->GetFileSystemType(); | |
71 } | |
72 | |
73 PP_Var GetName(PP_Resource file_ref_id) { | |
74 scoped_refptr<FileRef> file_ref(Resource::GetAs<FileRef>(file_ref_id)); | |
75 if (!file_ref) | |
76 return PP_MakeUndefined(); | |
77 return StringVar::StringToPPVar(file_ref->module(), file_ref->GetName()); | |
78 } | |
79 | |
80 PP_Var GetPath(PP_Resource file_ref_id) { | |
81 scoped_refptr<FileRef> file_ref(Resource::GetAs<FileRef>(file_ref_id)); | |
82 if (!file_ref) | |
83 return PP_MakeUndefined(); | |
84 | |
85 if (file_ref->GetFileSystemType() == PP_FILESYSTEMTYPE_EXTERNAL) | |
86 return PP_MakeUndefined(); | |
87 | |
88 return StringVar::StringToPPVar(file_ref->module(), file_ref->GetPath()); | |
89 } | |
90 | |
91 PP_Resource GetParent(PP_Resource file_ref_id) { | |
92 scoped_refptr<FileRef> file_ref(Resource::GetAs<FileRef>(file_ref_id)); | |
93 if (!file_ref) | |
94 return 0; | |
95 | |
96 if (file_ref->GetFileSystemType() == PP_FILESYSTEMTYPE_EXTERNAL) | |
97 return 0; | |
98 | |
99 scoped_refptr<FileRef> parent_ref(file_ref->GetParent()); | |
100 if (!parent_ref) | |
101 return 0; | |
102 | |
103 return parent_ref->GetReference(); | |
104 } | |
105 | |
106 int32_t MakeDirectory(PP_Resource directory_ref_id, | |
107 PP_Bool make_ancestors, | |
108 PP_CompletionCallback callback) { | |
109 scoped_refptr<FileRef> directory_ref( | |
110 Resource::GetAs<FileRef>(directory_ref_id)); | |
111 if (!directory_ref) | |
112 return PP_ERROR_BADRESOURCE; | |
113 | |
114 scoped_refptr<FileSystem> file_system = directory_ref->GetFileSystem(); | |
115 if (!file_system || !file_system->opened() || | |
116 (file_system->type() == PP_FILESYSTEMTYPE_EXTERNAL)) | |
117 return PP_ERROR_NOACCESS; | |
118 | |
119 PluginInstance* instance = file_system->instance(); | |
120 if (!instance->delegate()->MakeDirectory( | |
121 directory_ref->GetSystemPath(), PPBoolToBool(make_ancestors), | |
122 new FileCallbacks(instance->module()->AsWeakPtr(), | |
123 callback, NULL, NULL, NULL))) | |
124 return PP_ERROR_FAILED; | |
125 | |
126 return PP_ERROR_WOULDBLOCK; | |
127 } | |
128 | |
129 int32_t Query(PP_Resource file_ref_id, | |
130 PP_FileInfo_Dev* info, | |
131 PP_CompletionCallback callback) { | |
132 scoped_refptr<FileRef> file_ref(Resource::GetAs<FileRef>(file_ref_id)); | |
133 if (!file_ref) | |
134 return PP_ERROR_BADRESOURCE; | |
135 | |
136 scoped_refptr<FileSystem> file_system = file_ref->GetFileSystem(); | |
137 if (!file_system || !file_system->opened() || | |
138 (file_system->type() == PP_FILESYSTEMTYPE_EXTERNAL)) | |
139 return PP_ERROR_NOACCESS; | |
140 | |
141 PluginInstance* instance = file_system->instance(); | |
142 if (!instance->delegate()->Query( | |
143 file_ref->GetSystemPath(), | |
144 new FileCallbacks(instance->module()->AsWeakPtr(), | |
145 callback, info, file_system, NULL))) | |
146 return PP_ERROR_FAILED; | |
147 | |
148 return PP_ERROR_WOULDBLOCK; | |
149 } | |
150 | |
151 int32_t Touch(PP_Resource file_ref_id, | |
152 PP_Time last_access_time, | |
153 PP_Time last_modified_time, | |
154 PP_CompletionCallback callback) { | |
155 scoped_refptr<FileRef> file_ref(Resource::GetAs<FileRef>(file_ref_id)); | |
156 if (!file_ref) | |
157 return PP_ERROR_BADRESOURCE; | |
158 | |
159 scoped_refptr<FileSystem> file_system = file_ref->GetFileSystem(); | |
160 if (!file_system || !file_system->opened() || | |
161 (file_system->type() == PP_FILESYSTEMTYPE_EXTERNAL)) | |
162 return PP_ERROR_NOACCESS; | |
163 | |
164 PluginInstance* instance = file_system->instance(); | |
165 if (!instance->delegate()->Touch( | |
166 file_ref->GetSystemPath(), base::Time::FromDoubleT(last_access_time), | |
167 base::Time::FromDoubleT(last_modified_time), | |
168 new FileCallbacks(instance->module()->AsWeakPtr(), | |
169 callback, NULL, NULL, NULL))) | |
170 return PP_ERROR_FAILED; | |
171 | |
172 return PP_ERROR_WOULDBLOCK; | |
173 } | |
174 | |
175 int32_t Delete(PP_Resource file_ref_id, | |
176 PP_CompletionCallback callback) { | |
177 scoped_refptr<FileRef> file_ref(Resource::GetAs<FileRef>(file_ref_id)); | |
178 if (!file_ref) | |
179 return PP_ERROR_BADRESOURCE; | |
180 | |
181 scoped_refptr<FileSystem> file_system = file_ref->GetFileSystem(); | |
182 if (!file_system || !file_system->opened() || | |
183 (file_system->type() == PP_FILESYSTEMTYPE_EXTERNAL)) | |
184 return PP_ERROR_NOACCESS; | |
185 | |
186 PluginInstance* instance = file_system->instance(); | |
187 if (!instance->delegate()->Delete( | |
188 file_ref->GetSystemPath(), | |
189 new FileCallbacks(instance->module()->AsWeakPtr(), | |
190 callback, NULL, NULL, NULL))) | |
191 return PP_ERROR_FAILED; | |
192 | |
193 return PP_ERROR_WOULDBLOCK; | |
194 } | |
195 | |
196 int32_t Rename(PP_Resource file_ref_id, | |
197 PP_Resource new_file_ref_id, | |
198 PP_CompletionCallback callback) { | |
199 scoped_refptr<FileRef> file_ref(Resource::GetAs<FileRef>(file_ref_id)); | |
200 if (!file_ref) | |
201 return PP_ERROR_BADRESOURCE; | |
202 | |
203 scoped_refptr<FileRef> new_file_ref( | |
204 Resource::GetAs<FileRef>(new_file_ref_id)); | |
205 if (!new_file_ref) | |
206 return PP_ERROR_BADRESOURCE; | |
207 | |
208 scoped_refptr<FileSystem> file_system = file_ref->GetFileSystem(); | |
209 if (!file_system || !file_system->opened() || | |
210 (file_system != new_file_ref->GetFileSystem()) || | |
211 (file_system->type() == PP_FILESYSTEMTYPE_EXTERNAL)) | |
212 return PP_ERROR_NOACCESS; | |
213 | |
214 PluginInstance* instance = file_system->instance(); | |
215 if (!instance->delegate()->Rename( | |
216 file_ref->GetSystemPath(), new_file_ref->GetSystemPath(), | |
217 new FileCallbacks(instance->module()->AsWeakPtr(), | |
218 callback, NULL, NULL, NULL))) | |
219 return PP_ERROR_FAILED; | |
220 | |
221 return PP_ERROR_WOULDBLOCK; | |
222 } | |
223 | |
224 const PPB_FileRef_Dev ppb_fileref = { | |
225 &Create, | |
226 &IsFileRef, | |
227 &GetFileSystemType, | |
228 &GetName, | |
229 &GetPath, | |
230 &GetParent, | |
231 &MakeDirectory, | |
232 &Query, | |
233 &Touch, | |
234 &Delete, | |
235 &Rename | |
236 }; | |
237 | |
238 } // namespace | |
239 | |
240 FileRef::FileRef() | |
241 : Resource(NULL), | |
242 file_system_(NULL) { | |
243 } | |
244 | |
245 FileRef::FileRef(PluginModule* module, | |
246 scoped_refptr<FileSystem> file_system, | |
247 const std::string& validated_path) | |
248 : Resource(module), | |
249 file_system_(file_system), | |
250 virtual_path_(validated_path) { | |
251 } | |
252 | |
253 FileRef::FileRef(PluginModule* module, | |
254 const FilePath& external_file_path) | |
255 : Resource(module), | |
256 file_system_(NULL), | |
257 system_path_(external_file_path) { | |
258 } | |
259 | |
260 FileRef::~FileRef() { | |
261 } | |
262 | |
263 // static | |
264 const PPB_FileRef_Dev* FileRef::GetInterface() { | |
265 return &ppb_fileref; | |
266 } | |
267 | |
268 FileRef* FileRef::AsFileRef() { | |
269 return this; | |
270 } | |
271 | |
272 std::string FileRef::GetName() const { | |
273 if (GetFileSystemType() == PP_FILESYSTEMTYPE_EXTERNAL) { | |
274 FilePath::StringType path = system_path_.value(); | |
275 size_t pos = path.rfind(FilePath::kSeparators[0]); | |
276 DCHECK(pos != FilePath::StringType::npos); | |
277 #if defined(OS_WIN) | |
278 return WideToUTF8(path.substr(pos + 1)); | |
279 #elif defined(OS_POSIX) | |
280 return path.substr(pos + 1); | |
281 #else | |
282 #error "Unsupported platform." | |
283 #endif | |
284 } | |
285 | |
286 if (virtual_path_.size() == 1 && virtual_path_[0] == '/') | |
287 return virtual_path_; | |
288 | |
289 // There should always be a leading slash at least! | |
290 size_t pos = virtual_path_.rfind('/'); | |
291 DCHECK(pos != std::string::npos); | |
292 | |
293 return virtual_path_.substr(pos + 1); | |
294 } | |
295 | |
296 scoped_refptr<FileRef> FileRef::GetParent() { | |
297 if (GetFileSystemType() == PP_FILESYSTEMTYPE_EXTERNAL) | |
298 return new FileRef(); | |
299 | |
300 // There should always be a leading slash at least! | |
301 size_t pos = virtual_path_.rfind('/'); | |
302 DCHECK(pos != std::string::npos); | |
303 | |
304 // If the path is "/foo", then we want to include the slash. | |
305 if (pos == 0) | |
306 pos++; | |
307 std::string parent_path = virtual_path_.substr(0, pos); | |
308 | |
309 FileRef* parent_ref = new FileRef(module(), file_system_, parent_path); | |
310 return parent_ref; | |
311 } | |
312 | |
313 scoped_refptr<FileSystem> FileRef::GetFileSystem() const { | |
314 return file_system_; | |
315 } | |
316 | |
317 PP_FileSystemType_Dev FileRef::GetFileSystemType() const { | |
318 if (!file_system_) | |
319 return PP_FILESYSTEMTYPE_EXTERNAL; | |
320 | |
321 return file_system_->type(); | |
322 } | |
323 | |
324 std::string FileRef::GetPath() const { | |
325 return virtual_path_; | |
326 } | |
327 | |
328 FilePath FileRef::GetSystemPath() const { | |
329 if (GetFileSystemType() == PP_FILESYSTEMTYPE_EXTERNAL) | |
330 return system_path_; | |
331 | |
332 // Since |virtual_path_| starts with a '/', it is considered an absolute path | |
333 // on POSIX systems. We need to remove the '/' before calling Append() or we | |
334 // will run into a DCHECK. | |
335 FilePath virtual_file_path( | |
336 #if defined(OS_WIN) | |
337 UTF8ToWide(virtual_path_.substr(1)) | |
338 #elif defined(OS_POSIX) | |
339 virtual_path_.substr(1) | |
340 #else | |
341 #error "Unsupported platform." | |
342 #endif | |
343 ); | |
344 return file_system_->root_path().Append(virtual_file_path); | |
345 } | |
346 | |
347 } // namespace pepper | |
OLD | NEW |