| 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 |