| OLD | NEW |
| (Empty) |
| 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 "webkit/support/simple_file_system.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/files/file_path.h" | |
| 9 #include "base/message_loop.h" | |
| 10 #include "base/message_loop/message_loop_proxy.h" | |
| 11 #include "base/strings/utf_string_conversions.h" | |
| 12 #include "base/time.h" | |
| 13 #include "googleurl/src/gurl.h" | |
| 14 #include "net/base/mime_util.h" | |
| 15 #include "third_party/WebKit/public/platform/WebFileInfo.h" | |
| 16 #include "third_party/WebKit/public/platform/WebURL.h" | |
| 17 #include "third_party/WebKit/public/platform/WebVector.h" | |
| 18 #include "third_party/WebKit/public/web/WebDocument.h" | |
| 19 #include "third_party/WebKit/public/web/WebFileSystemCallbacks.h" | |
| 20 #include "third_party/WebKit/public/web/WebFileSystemEntry.h" | |
| 21 #include "third_party/WebKit/public/web/WebFrame.h" | |
| 22 #include "webkit/base/file_path_string_conversions.h" | |
| 23 #include "webkit/browser/blob/blob_storage_controller.h" | |
| 24 #include "webkit/browser/fileapi/file_permission_policy.h" | |
| 25 #include "webkit/browser/fileapi/file_system_mount_point_provider.h" | |
| 26 #include "webkit/browser/fileapi/file_system_operation_runner.h" | |
| 27 #include "webkit/browser/fileapi/file_system_url.h" | |
| 28 #include "webkit/browser/fileapi/mock_file_system_context.h" | |
| 29 #include "webkit/common/fileapi/directory_entry.h" | |
| 30 #include "webkit/common/fileapi/file_system_util.h" | |
| 31 #include "webkit/support/simple_file_writer.h" | |
| 32 | |
| 33 using base::WeakPtr; | |
| 34 | |
| 35 using WebKit::WebFileInfo; | |
| 36 using WebKit::WebFileSystem; | |
| 37 using WebKit::WebFileSystemCallbacks; | |
| 38 using WebKit::WebFileSystemEntry; | |
| 39 using WebKit::WebFileWriter; | |
| 40 using WebKit::WebFileWriterClient; | |
| 41 using WebKit::WebFrame; | |
| 42 using WebKit::WebString; | |
| 43 using WebKit::WebURL; | |
| 44 using WebKit::WebVector; | |
| 45 | |
| 46 using webkit_blob::BlobData; | |
| 47 using webkit_blob::BlobStorageController; | |
| 48 using fileapi::DirectoryEntry; | |
| 49 using fileapi::FileSystemContext; | |
| 50 using fileapi::FileSystemOperation; | |
| 51 using fileapi::FileSystemTaskRunners; | |
| 52 using fileapi::FileSystemURL; | |
| 53 | |
| 54 namespace { | |
| 55 base::MessageLoop* g_io_thread; | |
| 56 webkit_blob::BlobStorageController* g_blob_storage_controller; | |
| 57 | |
| 58 void RegisterBlob(const GURL& blob_url, const base::FilePath& file_path) { | |
| 59 DCHECK(g_blob_storage_controller); | |
| 60 | |
| 61 base::FilePath::StringType extension = file_path.Extension(); | |
| 62 if (!extension.empty()) | |
| 63 extension = extension.substr(1); // Strip leading ".". | |
| 64 | |
| 65 // This may fail, but then we'll be just setting the empty mime type. | |
| 66 std::string mime_type; | |
| 67 net::GetWellKnownMimeTypeFromExtension(extension, &mime_type); | |
| 68 | |
| 69 BlobData::Item item; | |
| 70 item.SetToFilePathRange(file_path, 0, -1, base::Time()); | |
| 71 g_blob_storage_controller->StartBuildingBlob(blob_url); | |
| 72 g_blob_storage_controller->AppendBlobDataItem(blob_url, item); | |
| 73 g_blob_storage_controller->FinishBuildingBlob(blob_url, mime_type); | |
| 74 } | |
| 75 | |
| 76 } // namespace | |
| 77 | |
| 78 SimpleFileSystem::SimpleFileSystem() { | |
| 79 if (file_system_dir_.CreateUniqueTempDir()) { | |
| 80 file_system_context_ = fileapi::CreateFileSystemContextForTesting( | |
| 81 NULL /* quota manager */, | |
| 82 file_system_dir_.path()); | |
| 83 } else { | |
| 84 LOG(WARNING) << "Failed to create a temp dir for the filesystem." | |
| 85 "FileSystem feature will be disabled."; | |
| 86 } | |
| 87 } | |
| 88 | |
| 89 SimpleFileSystem::~SimpleFileSystem() { | |
| 90 } | |
| 91 | |
| 92 void SimpleFileSystem::OpenFileSystem( | |
| 93 WebFrame* frame, | |
| 94 WebKit::WebFileSystemType type, | |
| 95 long long, bool create, | |
| 96 WebFileSystemCallbacks* callbacks) { | |
| 97 if (!frame || !file_system_context_.get()) { | |
| 98 // The FileSystem temp directory was not initialized successfully. | |
| 99 callbacks->didFail(WebKit::WebFileErrorSecurity); | |
| 100 return; | |
| 101 } | |
| 102 | |
| 103 fileapi::OpenFileSystemMode mode = | |
| 104 create ? fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT | |
| 105 : fileapi::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT; | |
| 106 GURL origin_url(frame->document().securityOrigin().toString()); | |
| 107 file_system_context_->OpenFileSystem( | |
| 108 origin_url, static_cast<fileapi::FileSystemType>(type), mode, | |
| 109 OpenFileSystemHandler(callbacks)); | |
| 110 } | |
| 111 | |
| 112 void SimpleFileSystem::DeleteFileSystem( | |
| 113 WebFrame* frame, | |
| 114 WebKit::WebFileSystemType type, | |
| 115 WebFileSystemCallbacks* callbacks) { | |
| 116 if (!frame || !file_system_context_.get()) { | |
| 117 callbacks->didFail(WebKit::WebFileErrorSecurity); | |
| 118 return; | |
| 119 } | |
| 120 | |
| 121 GURL origin_url(frame->document().securityOrigin().toString()); | |
| 122 file_system_context_->DeleteFileSystem( | |
| 123 origin_url, static_cast<fileapi::FileSystemType>(type), | |
| 124 DeleteFileSystemHandler(callbacks)); | |
| 125 } | |
| 126 | |
| 127 void SimpleFileSystem::move( | |
| 128 const WebURL& src_path, | |
| 129 const WebURL& dest_path, WebFileSystemCallbacks* callbacks) { | |
| 130 FileSystemURL src_url(file_system_context()->CrackURL(src_path)); | |
| 131 FileSystemURL dest_url(file_system_context()->CrackURL(dest_path)); | |
| 132 if (!HasFilePermission(src_url, fileapi::kWriteFilePermissions) || | |
| 133 !HasFilePermission(dest_url, fileapi::kCreateFilePermissions)) { | |
| 134 callbacks->didFail(WebKit::WebFileErrorSecurity); | |
| 135 return; | |
| 136 } | |
| 137 file_system_context_->operation_runner()->Move( | |
| 138 src_url, dest_url, FinishHandler(callbacks)); | |
| 139 } | |
| 140 | |
| 141 void SimpleFileSystem::copy( | |
| 142 const WebURL& src_path, const WebURL& dest_path, | |
| 143 WebFileSystemCallbacks* callbacks) { | |
| 144 FileSystemURL src_url(file_system_context()->CrackURL(src_path)); | |
| 145 FileSystemURL dest_url(file_system_context()->CrackURL(dest_path)); | |
| 146 if (!HasFilePermission(src_url, fileapi::kReadFilePermissions) || | |
| 147 !HasFilePermission(dest_url, fileapi::kCreateFilePermissions)) { | |
| 148 callbacks->didFail(WebKit::WebFileErrorSecurity); | |
| 149 return; | |
| 150 } | |
| 151 file_system_context_->operation_runner()->Copy( | |
| 152 src_url, dest_url, FinishHandler(callbacks)); | |
| 153 } | |
| 154 | |
| 155 void SimpleFileSystem::remove( | |
| 156 const WebURL& path, WebFileSystemCallbacks* callbacks) { | |
| 157 FileSystemURL url(file_system_context()->CrackURL(path)); | |
| 158 if (!HasFilePermission(url, fileapi::kWriteFilePermissions)) { | |
| 159 callbacks->didFail(WebKit::WebFileErrorSecurity); | |
| 160 return; | |
| 161 } | |
| 162 file_system_context_->operation_runner()->Remove( | |
| 163 url, false /* recursive */, FinishHandler(callbacks)); | |
| 164 } | |
| 165 | |
| 166 void SimpleFileSystem::removeRecursively( | |
| 167 const WebURL& path, WebFileSystemCallbacks* callbacks) { | |
| 168 FileSystemURL url(file_system_context()->CrackURL(path)); | |
| 169 if (!HasFilePermission(url, fileapi::kWriteFilePermissions)) { | |
| 170 callbacks->didFail(WebKit::WebFileErrorSecurity); | |
| 171 return; | |
| 172 } | |
| 173 file_system_context_->operation_runner()->Remove( | |
| 174 url, true /* recursive */, FinishHandler(callbacks)); | |
| 175 } | |
| 176 | |
| 177 void SimpleFileSystem::readMetadata( | |
| 178 const WebURL& path, WebFileSystemCallbacks* callbacks) { | |
| 179 FileSystemURL url(file_system_context()->CrackURL(path)); | |
| 180 if (!HasFilePermission(url, fileapi::kReadFilePermissions)) { | |
| 181 callbacks->didFail(WebKit::WebFileErrorSecurity); | |
| 182 return; | |
| 183 } | |
| 184 file_system_context_->operation_runner()->GetMetadata( | |
| 185 url, GetMetadataHandler(callbacks)); | |
| 186 } | |
| 187 | |
| 188 void SimpleFileSystem::createFile( | |
| 189 const WebURL& path, bool exclusive, WebFileSystemCallbacks* callbacks) { | |
| 190 FileSystemURL url(file_system_context()->CrackURL(path)); | |
| 191 if (!HasFilePermission(url, fileapi::kCreateFilePermissions)) { | |
| 192 callbacks->didFail(WebKit::WebFileErrorSecurity); | |
| 193 return; | |
| 194 } | |
| 195 file_system_context_->operation_runner()->CreateFile( | |
| 196 url, exclusive, FinishHandler(callbacks)); | |
| 197 } | |
| 198 | |
| 199 void SimpleFileSystem::createDirectory( | |
| 200 const WebURL& path, bool exclusive, WebFileSystemCallbacks* callbacks) { | |
| 201 FileSystemURL url(file_system_context()->CrackURL(path)); | |
| 202 if (!HasFilePermission(url, fileapi::kCreateFilePermissions)) { | |
| 203 callbacks->didFail(WebKit::WebFileErrorSecurity); | |
| 204 return; | |
| 205 } | |
| 206 file_system_context_->operation_runner()->CreateDirectory( | |
| 207 url, exclusive, false, FinishHandler(callbacks)); | |
| 208 } | |
| 209 | |
| 210 void SimpleFileSystem::fileExists( | |
| 211 const WebURL& path, WebFileSystemCallbacks* callbacks) { | |
| 212 FileSystemURL url(file_system_context()->CrackURL(path)); | |
| 213 if (!HasFilePermission(url, fileapi::kReadFilePermissions)) { | |
| 214 callbacks->didFail(WebKit::WebFileErrorSecurity); | |
| 215 return; | |
| 216 } | |
| 217 file_system_context_->operation_runner()->FileExists( | |
| 218 url, FinishHandler(callbacks)); | |
| 219 } | |
| 220 | |
| 221 void SimpleFileSystem::directoryExists( | |
| 222 const WebURL& path, WebFileSystemCallbacks* callbacks) { | |
| 223 FileSystemURL url(file_system_context()->CrackURL(path)); | |
| 224 if (!HasFilePermission(url, fileapi::kReadFilePermissions)) { | |
| 225 callbacks->didFail(WebKit::WebFileErrorSecurity); | |
| 226 return; | |
| 227 } | |
| 228 file_system_context_->operation_runner()->DirectoryExists( | |
| 229 url, FinishHandler(callbacks)); | |
| 230 } | |
| 231 | |
| 232 void SimpleFileSystem::readDirectory( | |
| 233 const WebURL& path, WebFileSystemCallbacks* callbacks) { | |
| 234 FileSystemURL url(file_system_context()->CrackURL(path)); | |
| 235 if (!HasFilePermission(url, fileapi::kReadFilePermissions)) { | |
| 236 callbacks->didFail(WebKit::WebFileErrorSecurity); | |
| 237 return; | |
| 238 } | |
| 239 file_system_context_->operation_runner()->ReadDirectory( | |
| 240 url, ReadDirectoryHandler(callbacks)); | |
| 241 } | |
| 242 | |
| 243 WebFileWriter* SimpleFileSystem::createFileWriter( | |
| 244 const WebURL& path, WebFileWriterClient* client) { | |
| 245 return new SimpleFileWriter(path, client, file_system_context_.get()); | |
| 246 } | |
| 247 | |
| 248 void SimpleFileSystem::createSnapshotFileAndReadMetadata( | |
| 249 const WebURL& path, | |
| 250 WebFileSystemCallbacks* callbacks) { | |
| 251 FileSystemURL url(file_system_context()->CrackURL(path)); | |
| 252 if (!HasFilePermission(url, fileapi::kReadFilePermissions)) { | |
| 253 callbacks->didFail(WebKit::WebFileErrorSecurity); | |
| 254 return; | |
| 255 } | |
| 256 file_system_context_->operation_runner()->CreateSnapshotFile( | |
| 257 url, SnapshotFileHandler(callbacks)); | |
| 258 } | |
| 259 | |
| 260 // static | |
| 261 void SimpleFileSystem::InitializeOnIOThread( | |
| 262 webkit_blob::BlobStorageController* blob_storage_controller) { | |
| 263 g_io_thread = base::MessageLoop::current(); | |
| 264 g_blob_storage_controller = blob_storage_controller; | |
| 265 } | |
| 266 | |
| 267 // static | |
| 268 void SimpleFileSystem::CleanupOnIOThread() { | |
| 269 g_io_thread = NULL; | |
| 270 g_blob_storage_controller = NULL; | |
| 271 } | |
| 272 | |
| 273 bool SimpleFileSystem::HasFilePermission( | |
| 274 const fileapi::FileSystemURL& url, int permissions) { | |
| 275 if (!url.is_valid()) | |
| 276 return false; | |
| 277 fileapi::FileSystemMountPointProvider* mount_point_provider = | |
| 278 file_system_context_->GetMountPointProvider(url.type()); | |
| 279 DCHECK(mount_point_provider); | |
| 280 // In test_shell we don't perform further detailed security checks if it's | |
| 281 // not specifically forbidden by ALWAYS_DENY. | |
| 282 return (mount_point_provider->GetPermissionPolicy(url, permissions) | |
| 283 != fileapi::FILE_PERMISSION_ALWAYS_DENY); | |
| 284 } | |
| 285 | |
| 286 FileSystemOperation::StatusCallback | |
| 287 SimpleFileSystem::FinishHandler(WebFileSystemCallbacks* callbacks) { | |
| 288 return base::Bind(&SimpleFileSystem::DidFinish, | |
| 289 AsWeakPtr(), base::Unretained(callbacks)); | |
| 290 } | |
| 291 | |
| 292 FileSystemOperation::ReadDirectoryCallback | |
| 293 SimpleFileSystem::ReadDirectoryHandler(WebFileSystemCallbacks* callbacks) { | |
| 294 return base::Bind(&SimpleFileSystem::DidReadDirectory, | |
| 295 AsWeakPtr(), base::Unretained(callbacks)); | |
| 296 } | |
| 297 | |
| 298 FileSystemOperation::GetMetadataCallback | |
| 299 SimpleFileSystem::GetMetadataHandler(WebFileSystemCallbacks* callbacks) { | |
| 300 return base::Bind(&SimpleFileSystem::DidGetMetadata, | |
| 301 AsWeakPtr(), base::Unretained(callbacks)); | |
| 302 } | |
| 303 | |
| 304 FileSystemContext::OpenFileSystemCallback | |
| 305 SimpleFileSystem::OpenFileSystemHandler(WebFileSystemCallbacks* callbacks) { | |
| 306 return base::Bind(&SimpleFileSystem::DidOpenFileSystem, | |
| 307 AsWeakPtr(), base::Unretained(callbacks)); | |
| 308 } | |
| 309 | |
| 310 FileSystemContext::DeleteFileSystemCallback | |
| 311 SimpleFileSystem::DeleteFileSystemHandler(WebFileSystemCallbacks* callbacks) { | |
| 312 return base::Bind(&SimpleFileSystem::DidDeleteFileSystem, | |
| 313 AsWeakPtr(), callbacks); | |
| 314 } | |
| 315 | |
| 316 FileSystemOperation::SnapshotFileCallback | |
| 317 SimpleFileSystem::SnapshotFileHandler( | |
| 318 WebFileSystemCallbacks* callbacks) { | |
| 319 return base::Bind(&SimpleFileSystem::DidCreateSnapshotFile, | |
| 320 AsWeakPtr(), base::Unretained(callbacks)); | |
| 321 } | |
| 322 | |
| 323 void SimpleFileSystem::DidFinish(WebFileSystemCallbacks* callbacks, | |
| 324 base::PlatformFileError result) { | |
| 325 if (result == base::PLATFORM_FILE_OK) | |
| 326 callbacks->didSucceed(); | |
| 327 else | |
| 328 callbacks->didFail(fileapi::PlatformFileErrorToWebFileError(result)); | |
| 329 } | |
| 330 | |
| 331 void SimpleFileSystem::DidGetMetadata(WebFileSystemCallbacks* callbacks, | |
| 332 base::PlatformFileError result, | |
| 333 const base::PlatformFileInfo& info) { | |
| 334 if (result == base::PLATFORM_FILE_OK) { | |
| 335 WebFileInfo web_file_info; | |
| 336 web_file_info.length = info.size; | |
| 337 web_file_info.modificationTime = info.last_modified.ToDoubleT(); | |
| 338 web_file_info.type = info.is_directory ? | |
| 339 WebFileInfo::TypeDirectory : WebFileInfo::TypeFile; | |
| 340 callbacks->didReadMetadata(web_file_info); | |
| 341 } else { | |
| 342 callbacks->didFail(fileapi::PlatformFileErrorToWebFileError(result)); | |
| 343 } | |
| 344 } | |
| 345 | |
| 346 void SimpleFileSystem::DidReadDirectory( | |
| 347 WebFileSystemCallbacks* callbacks, | |
| 348 base::PlatformFileError result, | |
| 349 const std::vector<DirectoryEntry>& entries, | |
| 350 bool has_more) { | |
| 351 if (result == base::PLATFORM_FILE_OK) { | |
| 352 std::vector<WebFileSystemEntry> web_entries_vector; | |
| 353 for (std::vector<DirectoryEntry>::const_iterator it = entries.begin(); | |
| 354 it != entries.end(); ++it) { | |
| 355 WebFileSystemEntry entry; | |
| 356 entry.name = webkit_base::FilePathStringToWebString(it->name); | |
| 357 entry.isDirectory = it->is_directory; | |
| 358 web_entries_vector.push_back(entry); | |
| 359 } | |
| 360 WebVector<WebKit::WebFileSystemEntry> web_entries = web_entries_vector; | |
| 361 callbacks->didReadDirectory(web_entries, has_more); | |
| 362 } else { | |
| 363 callbacks->didFail(fileapi::PlatformFileErrorToWebFileError(result)); | |
| 364 } | |
| 365 } | |
| 366 | |
| 367 void SimpleFileSystem::DidOpenFileSystem( | |
| 368 WebFileSystemCallbacks* callbacks, | |
| 369 base::PlatformFileError result, | |
| 370 const std::string& name, const GURL& root) { | |
| 371 if (result == base::PLATFORM_FILE_OK) { | |
| 372 if (!root.is_valid()) | |
| 373 callbacks->didFail(WebKit::WebFileErrorSecurity); | |
| 374 else | |
| 375 callbacks->didOpenFileSystem(WebString::fromUTF8(name), root); | |
| 376 } else { | |
| 377 callbacks->didFail(fileapi::PlatformFileErrorToWebFileError(result)); | |
| 378 } | |
| 379 } | |
| 380 | |
| 381 void SimpleFileSystem::DidDeleteFileSystem( | |
| 382 WebFileSystemCallbacks* callbacks, | |
| 383 base::PlatformFileError result) { | |
| 384 if (result == base::PLATFORM_FILE_OK) | |
| 385 callbacks->didSucceed(); | |
| 386 else | |
| 387 callbacks->didFail(fileapi::PlatformFileErrorToWebFileError(result)); | |
| 388 } | |
| 389 | |
| 390 void SimpleFileSystem::DidCreateSnapshotFile( | |
| 391 WebFileSystemCallbacks* callbacks, | |
| 392 base::PlatformFileError result, | |
| 393 const base::PlatformFileInfo& info, | |
| 394 const base::FilePath& platform_path, | |
| 395 const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { | |
| 396 if (result == base::PLATFORM_FILE_OK) { | |
| 397 WebFileInfo web_file_info; | |
| 398 web_file_info.length = info.size; | |
| 399 web_file_info.modificationTime = info.last_modified.ToDoubleT(); | |
| 400 web_file_info.type = info.is_directory ? | |
| 401 WebFileInfo::TypeDirectory : WebFileInfo::TypeFile; | |
| 402 web_file_info.platformPath = | |
| 403 webkit_base::FilePathToWebString(platform_path); | |
| 404 callbacks->didCreateSnapshotFile(web_file_info); | |
| 405 } else { | |
| 406 callbacks->didFail(fileapi::PlatformFileErrorToWebFileError(result)); | |
| 407 } | |
| 408 } | |
| OLD | NEW |