| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "webkit/browser/fileapi/obfuscated_file_util.h" | 5 #include "storage/browser/fileapi/obfuscated_file_util.h" |
| 6 | 6 |
| 7 #include <queue> | 7 #include <queue> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "base/file_util.h" | 11 #include "base/file_util.h" |
| 12 #include "base/format_macros.h" | 12 #include "base/format_macros.h" |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/message_loop/message_loop.h" | 14 #include "base/message_loop/message_loop.h" |
| 15 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
| 16 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
| 17 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
| 18 #include "base/strings/stringprintf.h" | 18 #include "base/strings/stringprintf.h" |
| 19 #include "base/strings/sys_string_conversions.h" | 19 #include "base/strings/sys_string_conversions.h" |
| 20 #include "base/strings/utf_string_conversions.h" | 20 #include "base/strings/utf_string_conversions.h" |
| 21 #include "base/time/time.h" | 21 #include "base/time/time.h" |
| 22 #include "url/gurl.h" | 22 #include "url/gurl.h" |
| 23 #include "webkit/browser/fileapi/file_observers.h" | 23 #include "storage/browser/fileapi/file_observers.h" |
| 24 #include "webkit/browser/fileapi/file_system_context.h" | 24 #include "storage/browser/fileapi/file_system_context.h" |
| 25 #include "webkit/browser/fileapi/file_system_operation_context.h" | 25 #include "storage/browser/fileapi/file_system_operation_context.h" |
| 26 #include "webkit/browser/fileapi/file_system_url.h" | 26 #include "storage/browser/fileapi/file_system_url.h" |
| 27 #include "webkit/browser/fileapi/native_file_util.h" | 27 #include "storage/browser/fileapi/native_file_util.h" |
| 28 #include "webkit/browser/fileapi/sandbox_file_system_backend.h" | 28 #include "storage/browser/fileapi/sandbox_file_system_backend.h" |
| 29 #include "webkit/browser/fileapi/sandbox_isolated_origin_database.h" | 29 #include "storage/browser/fileapi/sandbox_isolated_origin_database.h" |
| 30 #include "webkit/browser/fileapi/sandbox_origin_database.h" | 30 #include "storage/browser/fileapi/sandbox_origin_database.h" |
| 31 #include "webkit/browser/fileapi/sandbox_prioritized_origin_database.h" | 31 #include "storage/browser/fileapi/sandbox_prioritized_origin_database.h" |
| 32 #include "webkit/browser/fileapi/timed_task_helper.h" | 32 #include "storage/browser/fileapi/timed_task_helper.h" |
| 33 #include "webkit/browser/quota/quota_manager.h" | 33 #include "storage/browser/quota/quota_manager.h" |
| 34 #include "webkit/common/database/database_identifier.h" | 34 #include "storage/common/database/database_identifier.h" |
| 35 #include "webkit/common/fileapi/file_system_util.h" | 35 #include "storage/common/fileapi/file_system_util.h" |
| 36 | 36 |
| 37 // Example of various paths: | 37 // Example of various paths: |
| 38 // void ObfuscatedFileUtil::DoSomething(const FileSystemURL& url) { | 38 // void ObfuscatedFileUtil::DoSomething(const FileSystemURL& url) { |
| 39 // base::FilePath virtual_path = url.path(); | 39 // base::FilePath virtual_path = url.path(); |
| 40 // base::FilePath local_path = GetLocalFilePath(url); | 40 // base::FilePath local_path = GetLocalFilePath(url); |
| 41 // | 41 // |
| 42 // NativeFileUtil::DoSomething(local_path); | 42 // NativeFileUtil::DoSomething(local_path); |
| 43 // file_util::DoAnother(local_path); | 43 // file_util::DoAnother(local_path); |
| 44 // } | 44 // } |
| 45 | 45 |
| 46 namespace fileapi { | 46 namespace storage { |
| 47 | 47 |
| 48 namespace { | 48 namespace { |
| 49 | 49 |
| 50 typedef SandboxDirectoryDatabase::FileId FileId; | 50 typedef SandboxDirectoryDatabase::FileId FileId; |
| 51 typedef SandboxDirectoryDatabase::FileInfo FileInfo; | 51 typedef SandboxDirectoryDatabase::FileInfo FileInfo; |
| 52 | 52 |
| 53 void InitFileInfo( | 53 void InitFileInfo(SandboxDirectoryDatabase::FileInfo* file_info, |
| 54 SandboxDirectoryDatabase::FileInfo* file_info, | 54 SandboxDirectoryDatabase::FileId parent_id, |
| 55 SandboxDirectoryDatabase::FileId parent_id, | 55 const base::FilePath::StringType& file_name) { |
| 56 const base::FilePath::StringType& file_name) { | |
| 57 DCHECK(file_info); | 56 DCHECK(file_info); |
| 58 file_info->parent_id = parent_id; | 57 file_info->parent_id = parent_id; |
| 59 file_info->name = file_name; | 58 file_info->name = file_name; |
| 60 } | 59 } |
| 61 | 60 |
| 62 // Costs computed as per crbug.com/86114, based on the LevelDB implementation of | 61 // Costs computed as per crbug.com/86114, based on the LevelDB implementation of |
| 63 // path storage under Linux. It's not clear if that will differ on Windows, on | 62 // path storage under Linux. It's not clear if that will differ on Windows, on |
| 64 // which base::FilePath uses wide chars [since they're converted to UTF-8 for | 63 // which base::FilePath uses wide chars [since they're converted to UTF-8 for |
| 65 // storage anyway], but as long as the cost is high enough that one can't cheat | 64 // storage anyway], but as long as the cost is high enough that one can't cheat |
| 66 // on quota by storing data in paths, it doesn't need to be all that accurate. | 65 // on quota by storing data in paths, it doesn't need to be all that accurate. |
| 67 const int64 kPathCreationQuotaCost = 146; // Bytes per inode, basically. | 66 const int64 kPathCreationQuotaCost = 146; // Bytes per inode, basically. |
| 68 const int64 kPathByteQuotaCost = 2; // Bytes per byte of path length in UTF-8. | 67 const int64 kPathByteQuotaCost = 2; // Bytes per byte of path length in UTF-8. |
| 69 | 68 |
| 70 int64 UsageForPath(size_t length) { | 69 int64 UsageForPath(size_t length) { |
| 71 return kPathCreationQuotaCost + | 70 return kPathCreationQuotaCost + |
| 72 static_cast<int64>(length) * kPathByteQuotaCost; | 71 static_cast<int64>(length) * kPathByteQuotaCost; |
| 73 } | 72 } |
| 74 | 73 |
| 75 bool AllocateQuota(FileSystemOperationContext* context, int64 growth) { | 74 bool AllocateQuota(FileSystemOperationContext* context, int64 growth) { |
| 76 if (context->allowed_bytes_growth() == quota::QuotaManager::kNoLimit) | 75 if (context->allowed_bytes_growth() == quota::QuotaManager::kNoLimit) |
| 77 return true; | 76 return true; |
| 78 | 77 |
| 79 int64 new_quota = context->allowed_bytes_growth() - growth; | 78 int64 new_quota = context->allowed_bytes_growth() - growth; |
| 80 if (growth > 0 && new_quota < 0) | 79 if (growth > 0 && new_quota < 0) |
| 81 return false; | 80 return false; |
| 82 context->set_allowed_bytes_growth(new_quota); | 81 context->set_allowed_bytes_growth(new_quota); |
| 83 return true; | 82 return true; |
| 84 } | 83 } |
| 85 | 84 |
| 86 void UpdateUsage( | 85 void UpdateUsage(FileSystemOperationContext* context, |
| 87 FileSystemOperationContext* context, | 86 const FileSystemURL& url, |
| 88 const FileSystemURL& url, | 87 int64 growth) { |
| 89 int64 growth) { | 88 context->update_observers()->Notify(&FileUpdateObserver::OnUpdate, |
| 90 context->update_observers()->Notify( | 89 MakeTuple(url, growth)); |
| 91 &FileUpdateObserver::OnUpdate, MakeTuple(url, growth)); | |
| 92 } | 90 } |
| 93 | 91 |
| 94 void TouchDirectory(SandboxDirectoryDatabase* db, FileId dir_id) { | 92 void TouchDirectory(SandboxDirectoryDatabase* db, FileId dir_id) { |
| 95 DCHECK(db); | 93 DCHECK(db); |
| 96 if (!db->UpdateModificationTime(dir_id, base::Time::Now())) | 94 if (!db->UpdateModificationTime(dir_id, base::Time::Now())) |
| 97 NOTREACHED(); | 95 NOTREACHED(); |
| 98 } | 96 } |
| 99 | 97 |
| 100 enum IsolatedOriginStatus { | 98 enum IsolatedOriginStatus { |
| 101 kIsolatedOriginMatch, | 99 kIsolatedOriginMatch, |
| 102 kIsolatedOriginDontMatch, | 100 kIsolatedOriginDontMatch, |
| 103 kIsolatedOriginStatusMax, | 101 kIsolatedOriginStatusMax, |
| 104 }; | 102 }; |
| 105 | 103 |
| 106 } // namespace | 104 } // namespace |
| 107 | 105 |
| 108 class ObfuscatedFileEnumerator | 106 class ObfuscatedFileEnumerator |
| 109 : public FileSystemFileUtil::AbstractFileEnumerator { | 107 : public FileSystemFileUtil::AbstractFileEnumerator { |
| 110 public: | 108 public: |
| 111 ObfuscatedFileEnumerator( | 109 ObfuscatedFileEnumerator(SandboxDirectoryDatabase* db, |
| 112 SandboxDirectoryDatabase* db, | 110 FileSystemOperationContext* context, |
| 113 FileSystemOperationContext* context, | 111 ObfuscatedFileUtil* obfuscated_file_util, |
| 114 ObfuscatedFileUtil* obfuscated_file_util, | 112 const FileSystemURL& root_url, |
| 115 const FileSystemURL& root_url, | 113 bool recursive) |
| 116 bool recursive) | |
| 117 : db_(db), | 114 : db_(db), |
| 118 context_(context), | 115 context_(context), |
| 119 obfuscated_file_util_(obfuscated_file_util), | 116 obfuscated_file_util_(obfuscated_file_util), |
| 120 root_url_(root_url), | 117 root_url_(root_url), |
| 121 recursive_(recursive), | 118 recursive_(recursive), |
| 122 current_file_id_(0) { | 119 current_file_id_(0) { |
| 123 base::FilePath root_virtual_path = root_url.path(); | 120 base::FilePath root_virtual_path = root_url.path(); |
| 124 FileId file_id; | 121 FileId file_id; |
| 125 | 122 |
| 126 if (!db_->GetFileWithPath(root_virtual_path, &file_id)) | 123 if (!db_->GetFileWithPath(root_virtual_path, &file_id)) |
| 127 return; | 124 return; |
| 128 | 125 |
| 129 FileRecord record = { file_id, root_virtual_path }; | 126 FileRecord record = {file_id, root_virtual_path}; |
| 130 recurse_queue_.push(record); | 127 recurse_queue_.push(record); |
| 131 } | 128 } |
| 132 | 129 |
| 133 virtual ~ObfuscatedFileEnumerator() {} | 130 virtual ~ObfuscatedFileEnumerator() {} |
| 134 | 131 |
| 135 virtual base::FilePath Next() OVERRIDE { | 132 virtual base::FilePath Next() OVERRIDE { |
| 136 ProcessRecurseQueue(); | 133 ProcessRecurseQueue(); |
| 137 if (display_stack_.empty()) | 134 if (display_stack_.empty()) |
| 138 return base::FilePath(); | 135 return base::FilePath(); |
| 139 | 136 |
| 140 current_file_id_ = display_stack_.back(); | 137 current_file_id_ = display_stack_.back(); |
| 141 display_stack_.pop_back(); | 138 display_stack_.pop_back(); |
| 142 | 139 |
| 143 FileInfo file_info; | 140 FileInfo file_info; |
| 144 base::FilePath platform_file_path; | 141 base::FilePath platform_file_path; |
| 145 base::File::Error error = | 142 base::File::Error error = |
| 146 obfuscated_file_util_->GetFileInfoInternal( | 143 obfuscated_file_util_->GetFileInfoInternal(db_, |
| 147 db_, context_, root_url_, current_file_id_, | 144 context_, |
| 148 &file_info, ¤t_platform_file_info_, &platform_file_path); | 145 root_url_, |
| 146 current_file_id_, |
| 147 &file_info, |
| 148 ¤t_platform_file_info_, |
| 149 &platform_file_path); |
| 149 if (error != base::File::FILE_OK) | 150 if (error != base::File::FILE_OK) |
| 150 return Next(); | 151 return Next(); |
| 151 | 152 |
| 152 base::FilePath virtual_path = | 153 base::FilePath virtual_path = |
| 153 current_parent_virtual_path_.Append(file_info.name); | 154 current_parent_virtual_path_.Append(file_info.name); |
| 154 if (recursive_ && file_info.is_directory()) { | 155 if (recursive_ && file_info.is_directory()) { |
| 155 FileRecord record = { current_file_id_, virtual_path }; | 156 FileRecord record = {current_file_id_, virtual_path}; |
| 156 recurse_queue_.push(record); | 157 recurse_queue_.push(record); |
| 157 } | 158 } |
| 158 return virtual_path; | 159 return virtual_path; |
| 159 } | 160 } |
| 160 | 161 |
| 161 virtual int64 Size() OVERRIDE { | 162 virtual int64 Size() OVERRIDE { return current_platform_file_info_.size; } |
| 162 return current_platform_file_info_.size; | |
| 163 } | |
| 164 | 163 |
| 165 virtual base::Time LastModifiedTime() OVERRIDE { | 164 virtual base::Time LastModifiedTime() OVERRIDE { |
| 166 return current_platform_file_info_.last_modified; | 165 return current_platform_file_info_.last_modified; |
| 167 } | 166 } |
| 168 | 167 |
| 169 virtual bool IsDirectory() OVERRIDE { | 168 virtual bool IsDirectory() OVERRIDE { |
| 170 return current_platform_file_info_.is_directory; | 169 return current_platform_file_info_.is_directory; |
| 171 } | 170 } |
| 172 | 171 |
| 173 private: | 172 private: |
| (...skipping 28 matching lines...) Expand all Loading... |
| 202 base::FilePath current_parent_virtual_path_; | 201 base::FilePath current_parent_virtual_path_; |
| 203 | 202 |
| 204 FileId current_file_id_; | 203 FileId current_file_id_; |
| 205 base::File::Info current_platform_file_info_; | 204 base::File::Info current_platform_file_info_; |
| 206 }; | 205 }; |
| 207 | 206 |
| 208 class ObfuscatedOriginEnumerator | 207 class ObfuscatedOriginEnumerator |
| 209 : public ObfuscatedFileUtil::AbstractOriginEnumerator { | 208 : public ObfuscatedFileUtil::AbstractOriginEnumerator { |
| 210 public: | 209 public: |
| 211 typedef SandboxOriginDatabase::OriginRecord OriginRecord; | 210 typedef SandboxOriginDatabase::OriginRecord OriginRecord; |
| 212 ObfuscatedOriginEnumerator( | 211 ObfuscatedOriginEnumerator(SandboxOriginDatabaseInterface* origin_database, |
| 213 SandboxOriginDatabaseInterface* origin_database, | 212 const base::FilePath& base_file_path) |
| 214 const base::FilePath& base_file_path) | |
| 215 : base_file_path_(base_file_path) { | 213 : base_file_path_(base_file_path) { |
| 216 if (origin_database) | 214 if (origin_database) |
| 217 origin_database->ListAllOrigins(&origins_); | 215 origin_database->ListAllOrigins(&origins_); |
| 218 } | 216 } |
| 219 | 217 |
| 220 virtual ~ObfuscatedOriginEnumerator() {} | 218 virtual ~ObfuscatedOriginEnumerator() {} |
| 221 | 219 |
| 222 // Returns the next origin. Returns empty if there are no more origins. | 220 // Returns the next origin. Returns empty if there are no more origins. |
| 223 virtual GURL Next() OVERRIDE { | 221 virtual GURL Next() OVERRIDE { |
| 224 OriginRecord record; | 222 OriginRecord record; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 file_task_runner_(file_task_runner), | 262 file_task_runner_(file_task_runner), |
| 265 get_type_string_for_url_(get_type_string_for_url), | 263 get_type_string_for_url_(get_type_string_for_url), |
| 266 known_type_strings_(known_type_strings), | 264 known_type_strings_(known_type_strings), |
| 267 sandbox_delegate_(sandbox_delegate) { | 265 sandbox_delegate_(sandbox_delegate) { |
| 268 } | 266 } |
| 269 | 267 |
| 270 ObfuscatedFileUtil::~ObfuscatedFileUtil() { | 268 ObfuscatedFileUtil::~ObfuscatedFileUtil() { |
| 271 DropDatabases(); | 269 DropDatabases(); |
| 272 } | 270 } |
| 273 | 271 |
| 274 base::File ObfuscatedFileUtil::CreateOrOpen( | 272 base::File ObfuscatedFileUtil::CreateOrOpen(FileSystemOperationContext* context, |
| 275 FileSystemOperationContext* context, | 273 const FileSystemURL& url, |
| 276 const FileSystemURL& url, int file_flags) { | 274 int file_flags) { |
| 277 base::File file = CreateOrOpenInternal(context, url, file_flags); | 275 base::File file = CreateOrOpenInternal(context, url, file_flags); |
| 278 if (file.IsValid() && file_flags & base::File::FLAG_WRITE && | 276 if (file.IsValid() && file_flags & base::File::FLAG_WRITE && |
| 279 context->quota_limit_type() == quota::kQuotaLimitTypeUnlimited && | 277 context->quota_limit_type() == quota::kQuotaLimitTypeUnlimited && |
| 280 sandbox_delegate_) { | 278 sandbox_delegate_) { |
| 281 sandbox_delegate_->StickyInvalidateUsageCache(url.origin(), url.type()); | 279 sandbox_delegate_->StickyInvalidateUsageCache(url.origin(), url.type()); |
| 282 } | 280 } |
| 283 return file.Pass(); | 281 return file.Pass(); |
| 284 } | 282 } |
| 285 | 283 |
| 286 base::File::Error ObfuscatedFileUtil::EnsureFileExists( | 284 base::File::Error ObfuscatedFileUtil::EnsureFileExists( |
| (...skipping 15 matching lines...) Expand all Loading... |
| 302 return base::File::FILE_ERROR_NOT_A_FILE; | 300 return base::File::FILE_ERROR_NOT_A_FILE; |
| 303 if (created) | 301 if (created) |
| 304 *created = false; | 302 *created = false; |
| 305 return base::File::FILE_OK; | 303 return base::File::FILE_OK; |
| 306 } | 304 } |
| 307 FileId parent_id; | 305 FileId parent_id; |
| 308 if (!db->GetFileWithPath(VirtualPath::DirName(url.path()), &parent_id)) | 306 if (!db->GetFileWithPath(VirtualPath::DirName(url.path()), &parent_id)) |
| 309 return base::File::FILE_ERROR_NOT_FOUND; | 307 return base::File::FILE_ERROR_NOT_FOUND; |
| 310 | 308 |
| 311 FileInfo file_info; | 309 FileInfo file_info; |
| 312 InitFileInfo(&file_info, parent_id, | 310 InitFileInfo( |
| 313 VirtualPath::BaseName(url.path()).value()); | 311 &file_info, parent_id, VirtualPath::BaseName(url.path()).value()); |
| 314 | 312 |
| 315 int64 growth = UsageForPath(file_info.name.size()); | 313 int64 growth = UsageForPath(file_info.name.size()); |
| 316 if (!AllocateQuota(context, growth)) | 314 if (!AllocateQuota(context, growth)) |
| 317 return base::File::FILE_ERROR_NO_SPACE; | 315 return base::File::FILE_ERROR_NO_SPACE; |
| 318 base::File::Error error = CreateFile(context, base::FilePath(), url, | 316 base::File::Error error = |
| 319 &file_info); | 317 CreateFile(context, base::FilePath(), url, &file_info); |
| 320 if (created && base::File::FILE_OK == error) { | 318 if (created && base::File::FILE_OK == error) { |
| 321 *created = true; | 319 *created = true; |
| 322 UpdateUsage(context, url, growth); | 320 UpdateUsage(context, url, growth); |
| 323 context->change_observers()->Notify( | 321 context->change_observers()->Notify(&FileChangeObserver::OnCreateFile, |
| 324 &FileChangeObserver::OnCreateFile, MakeTuple(url)); | 322 MakeTuple(url)); |
| 325 } | 323 } |
| 326 return error; | 324 return error; |
| 327 } | 325 } |
| 328 | 326 |
| 329 base::File::Error ObfuscatedFileUtil::CreateDirectory( | 327 base::File::Error ObfuscatedFileUtil::CreateDirectory( |
| 330 FileSystemOperationContext* context, | 328 FileSystemOperationContext* context, |
| 331 const FileSystemURL& url, | 329 const FileSystemURL& url, |
| 332 bool exclusive, | 330 bool exclusive, |
| 333 bool recursive) { | 331 bool recursive) { |
| 334 SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, true); | 332 SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, true); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 372 continue; | 370 continue; |
| 373 file_info.modification_time = base::Time::Now(); | 371 file_info.modification_time = base::Time::Now(); |
| 374 file_info.parent_id = parent_id; | 372 file_info.parent_id = parent_id; |
| 375 int64 growth = UsageForPath(file_info.name.size()); | 373 int64 growth = UsageForPath(file_info.name.size()); |
| 376 if (!AllocateQuota(context, growth)) | 374 if (!AllocateQuota(context, growth)) |
| 377 return base::File::FILE_ERROR_NO_SPACE; | 375 return base::File::FILE_ERROR_NO_SPACE; |
| 378 base::File::Error error = db->AddFileInfo(file_info, &parent_id); | 376 base::File::Error error = db->AddFileInfo(file_info, &parent_id); |
| 379 if (error != base::File::FILE_OK) | 377 if (error != base::File::FILE_OK) |
| 380 return error; | 378 return error; |
| 381 UpdateUsage(context, url, growth); | 379 UpdateUsage(context, url, growth); |
| 382 context->change_observers()->Notify( | 380 context->change_observers()->Notify(&FileChangeObserver::OnCreateDirectory, |
| 383 &FileChangeObserver::OnCreateDirectory, MakeTuple(url)); | 381 MakeTuple(url)); |
| 384 if (first) { | 382 if (first) { |
| 385 first = false; | 383 first = false; |
| 386 TouchDirectory(db, file_info.parent_id); | 384 TouchDirectory(db, file_info.parent_id); |
| 387 } | 385 } |
| 388 } | 386 } |
| 389 return base::File::FILE_OK; | 387 return base::File::FILE_OK; |
| 390 } | 388 } |
| 391 | 389 |
| 392 base::File::Error ObfuscatedFileUtil::GetFileInfo( | 390 base::File::Error ObfuscatedFileUtil::GetFileInfo( |
| 393 FileSystemOperationContext* context, | 391 FileSystemOperationContext* context, |
| 394 const FileSystemURL& url, | 392 const FileSystemURL& url, |
| 395 base::File::Info* file_info, | 393 base::File::Info* file_info, |
| 396 base::FilePath* platform_file_path) { | 394 base::FilePath* platform_file_path) { |
| 397 SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, false); | 395 SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, false); |
| 398 if (!db) | 396 if (!db) |
| 399 return base::File::FILE_ERROR_NOT_FOUND; | 397 return base::File::FILE_ERROR_NOT_FOUND; |
| 400 FileId file_id; | 398 FileId file_id; |
| 401 if (!db->GetFileWithPath(url.path(), &file_id)) | 399 if (!db->GetFileWithPath(url.path(), &file_id)) |
| 402 return base::File::FILE_ERROR_NOT_FOUND; | 400 return base::File::FILE_ERROR_NOT_FOUND; |
| 403 FileInfo local_info; | 401 FileInfo local_info; |
| 404 return GetFileInfoInternal(db, context, url, | 402 return GetFileInfoInternal( |
| 405 file_id, &local_info, | 403 db, context, url, file_id, &local_info, file_info, platform_file_path); |
| 406 file_info, platform_file_path); | |
| 407 } | 404 } |
| 408 | 405 |
| 409 scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> | 406 scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> |
| 410 ObfuscatedFileUtil::CreateFileEnumerator( | 407 ObfuscatedFileUtil::CreateFileEnumerator(FileSystemOperationContext* context, |
| 411 FileSystemOperationContext* context, | 408 const FileSystemURL& root_url) { |
| 412 const FileSystemURL& root_url) { | |
| 413 return CreateFileEnumerator(context, root_url, false /* recursive */); | 409 return CreateFileEnumerator(context, root_url, false /* recursive */); |
| 414 } | 410 } |
| 415 | 411 |
| 416 base::File::Error ObfuscatedFileUtil::GetLocalFilePath( | 412 base::File::Error ObfuscatedFileUtil::GetLocalFilePath( |
| 417 FileSystemOperationContext* context, | 413 FileSystemOperationContext* context, |
| 418 const FileSystemURL& url, | 414 const FileSystemURL& url, |
| 419 base::FilePath* local_path) { | 415 base::FilePath* local_path) { |
| 420 SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, false); | 416 SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, false); |
| 421 if (!db) | 417 if (!db) |
| 422 return base::File::FILE_ERROR_NOT_FOUND; | 418 return base::File::FILE_ERROR_NOT_FOUND; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 451 FileInfo file_info; | 447 FileInfo file_info; |
| 452 if (!db->GetFileInfo(file_id, &file_info)) { | 448 if (!db->GetFileInfo(file_id, &file_info)) { |
| 453 NOTREACHED(); | 449 NOTREACHED(); |
| 454 return base::File::FILE_ERROR_FAILED; | 450 return base::File::FILE_ERROR_FAILED; |
| 455 } | 451 } |
| 456 if (file_info.is_directory()) { | 452 if (file_info.is_directory()) { |
| 457 if (!db->UpdateModificationTime(file_id, last_modified_time)) | 453 if (!db->UpdateModificationTime(file_id, last_modified_time)) |
| 458 return base::File::FILE_ERROR_FAILED; | 454 return base::File::FILE_ERROR_FAILED; |
| 459 return base::File::FILE_OK; | 455 return base::File::FILE_OK; |
| 460 } | 456 } |
| 461 return NativeFileUtil::Touch( | 457 return NativeFileUtil::Touch(DataPathToLocalPath(url, file_info.data_path), |
| 462 DataPathToLocalPath(url, file_info.data_path), | 458 last_access_time, |
| 463 last_access_time, last_modified_time); | 459 last_modified_time); |
| 464 } | 460 } |
| 465 | 461 |
| 466 base::File::Error ObfuscatedFileUtil::Truncate( | 462 base::File::Error ObfuscatedFileUtil::Truncate( |
| 467 FileSystemOperationContext* context, | 463 FileSystemOperationContext* context, |
| 468 const FileSystemURL& url, | 464 const FileSystemURL& url, |
| 469 int64 length) { | 465 int64 length) { |
| 470 base::File::Info file_info; | 466 base::File::Info file_info; |
| 471 base::FilePath local_path; | 467 base::FilePath local_path; |
| 472 base::File::Error error = | 468 base::File::Error error = GetFileInfo(context, url, &file_info, &local_path); |
| 473 GetFileInfo(context, url, &file_info, &local_path); | |
| 474 if (error != base::File::FILE_OK) | 469 if (error != base::File::FILE_OK) |
| 475 return error; | 470 return error; |
| 476 | 471 |
| 477 int64 growth = length - file_info.size; | 472 int64 growth = length - file_info.size; |
| 478 if (!AllocateQuota(context, growth)) | 473 if (!AllocateQuota(context, growth)) |
| 479 return base::File::FILE_ERROR_NO_SPACE; | 474 return base::File::FILE_ERROR_NO_SPACE; |
| 480 error = NativeFileUtil::Truncate(local_path, length); | 475 error = NativeFileUtil::Truncate(local_path, length); |
| 481 if (error == base::File::FILE_OK) { | 476 if (error == base::File::FILE_OK) { |
| 482 UpdateUsage(context, url, growth); | 477 UpdateUsage(context, url, growth); |
| 483 context->change_observers()->Notify( | 478 context->change_observers()->Notify(&FileChangeObserver::OnModifyFile, |
| 484 &FileChangeObserver::OnModifyFile, MakeTuple(url)); | 479 MakeTuple(url)); |
| 485 } | 480 } |
| 486 return error; | 481 return error; |
| 487 } | 482 } |
| 488 | 483 |
| 489 base::File::Error ObfuscatedFileUtil::CopyOrMoveFile( | 484 base::File::Error ObfuscatedFileUtil::CopyOrMoveFile( |
| 490 FileSystemOperationContext* context, | 485 FileSystemOperationContext* context, |
| 491 const FileSystemURL& src_url, | 486 const FileSystemURL& src_url, |
| 492 const FileSystemURL& dest_url, | 487 const FileSystemURL& dest_url, |
| 493 CopyOrMoveOption option, | 488 CopyOrMoveOption option, |
| 494 bool copy) { | 489 bool copy) { |
| 495 // Cross-filesystem copies and moves should be handled via CopyInForeignFile. | 490 // Cross-filesystem copies and moves should be handled via CopyInForeignFile. |
| 496 DCHECK(src_url.origin() == dest_url.origin()); | 491 DCHECK(src_url.origin() == dest_url.origin()); |
| 497 DCHECK(src_url.type() == dest_url.type()); | 492 DCHECK(src_url.type() == dest_url.type()); |
| 498 | 493 |
| 499 SandboxDirectoryDatabase* db = GetDirectoryDatabase(src_url, true); | 494 SandboxDirectoryDatabase* db = GetDirectoryDatabase(src_url, true); |
| 500 if (!db) | 495 if (!db) |
| 501 return base::File::FILE_ERROR_FAILED; | 496 return base::File::FILE_ERROR_FAILED; |
| 502 | 497 |
| 503 FileId src_file_id; | 498 FileId src_file_id; |
| 504 if (!db->GetFileWithPath(src_url.path(), &src_file_id)) | 499 if (!db->GetFileWithPath(src_url.path(), &src_file_id)) |
| 505 return base::File::FILE_ERROR_NOT_FOUND; | 500 return base::File::FILE_ERROR_NOT_FOUND; |
| 506 | 501 |
| 507 FileId dest_file_id; | 502 FileId dest_file_id; |
| 508 bool overwrite = db->GetFileWithPath(dest_url.path(), | 503 bool overwrite = db->GetFileWithPath(dest_url.path(), &dest_file_id); |
| 509 &dest_file_id); | |
| 510 | 504 |
| 511 FileInfo src_file_info; | 505 FileInfo src_file_info; |
| 512 base::File::Info src_platform_file_info; | 506 base::File::Info src_platform_file_info; |
| 513 base::FilePath src_local_path; | 507 base::FilePath src_local_path; |
| 514 base::File::Error error = GetFileInfoInternal( | 508 base::File::Error error = GetFileInfoInternal(db, |
| 515 db, context, src_url, src_file_id, | 509 context, |
| 516 &src_file_info, &src_platform_file_info, &src_local_path); | 510 src_url, |
| 511 src_file_id, |
| 512 &src_file_info, |
| 513 &src_platform_file_info, |
| 514 &src_local_path); |
| 517 if (error != base::File::FILE_OK) | 515 if (error != base::File::FILE_OK) |
| 518 return error; | 516 return error; |
| 519 if (src_file_info.is_directory()) | 517 if (src_file_info.is_directory()) |
| 520 return base::File::FILE_ERROR_NOT_A_FILE; | 518 return base::File::FILE_ERROR_NOT_A_FILE; |
| 521 | 519 |
| 522 FileInfo dest_file_info; | 520 FileInfo dest_file_info; |
| 523 base::File::Info dest_platform_file_info; // overwrite case only | 521 base::File::Info dest_platform_file_info; // overwrite case only |
| 524 base::FilePath dest_local_path; // overwrite case only | 522 base::FilePath dest_local_path; // overwrite case only |
| 525 if (overwrite) { | 523 if (overwrite) { |
| 526 base::File::Error error = GetFileInfoInternal( | 524 base::File::Error error = GetFileInfoInternal(db, |
| 527 db, context, dest_url, dest_file_id, | 525 context, |
| 528 &dest_file_info, &dest_platform_file_info, &dest_local_path); | 526 dest_url, |
| 527 dest_file_id, |
| 528 &dest_file_info, |
| 529 &dest_platform_file_info, |
| 530 &dest_local_path); |
| 529 if (error == base::File::FILE_ERROR_NOT_FOUND) | 531 if (error == base::File::FILE_ERROR_NOT_FOUND) |
| 530 overwrite = false; // fallback to non-overwrite case | 532 overwrite = false; // fallback to non-overwrite case |
| 531 else if (error != base::File::FILE_OK) | 533 else if (error != base::File::FILE_OK) |
| 532 return error; | 534 return error; |
| 533 else if (dest_file_info.is_directory()) | 535 else if (dest_file_info.is_directory()) |
| 534 return base::File::FILE_ERROR_INVALID_OPERATION; | 536 return base::File::FILE_ERROR_INVALID_OPERATION; |
| 535 } | 537 } |
| 536 if (!overwrite) { | 538 if (!overwrite) { |
| 537 FileId dest_parent_id; | 539 FileId dest_parent_id; |
| 538 if (!db->GetFileWithPath(VirtualPath::DirName(dest_url.path()), | 540 if (!db->GetFileWithPath(VirtualPath::DirName(dest_url.path()), |
| 539 &dest_parent_id)) { | 541 &dest_parent_id)) { |
| 540 return base::File::FILE_ERROR_NOT_FOUND; | 542 return base::File::FILE_ERROR_NOT_FOUND; |
| 541 } | 543 } |
| 542 | 544 |
| 543 dest_file_info = src_file_info; | 545 dest_file_info = src_file_info; |
| 544 dest_file_info.parent_id = dest_parent_id; | 546 dest_file_info.parent_id = dest_parent_id; |
| 545 dest_file_info.name = | 547 dest_file_info.name = VirtualPath::BaseName(dest_url.path()).value(); |
| 546 VirtualPath::BaseName(dest_url.path()).value(); | |
| 547 } | 548 } |
| 548 | 549 |
| 549 int64 growth = 0; | 550 int64 growth = 0; |
| 550 if (copy) | 551 if (copy) |
| 551 growth += src_platform_file_info.size; | 552 growth += src_platform_file_info.size; |
| 552 else | 553 else |
| 553 growth -= UsageForPath(src_file_info.name.size()); | 554 growth -= UsageForPath(src_file_info.name.size()); |
| 554 if (overwrite) | 555 if (overwrite) |
| 555 growth -= dest_platform_file_info.size; | 556 growth -= dest_platform_file_info.size; |
| 556 else | 557 else |
| (...skipping 15 matching lines...) Expand all Loading... |
| 572 * Move-without-overwrite | 573 * Move-without-overwrite |
| 573 * Just update metadata | 574 * Just update metadata |
| 574 */ | 575 */ |
| 575 error = base::File::FILE_ERROR_FAILED; | 576 error = base::File::FILE_ERROR_FAILED; |
| 576 if (copy) { | 577 if (copy) { |
| 577 if (overwrite) { | 578 if (overwrite) { |
| 578 error = NativeFileUtil::CopyOrMoveFile( | 579 error = NativeFileUtil::CopyOrMoveFile( |
| 579 src_local_path, | 580 src_local_path, |
| 580 dest_local_path, | 581 dest_local_path, |
| 581 option, | 582 option, |
| 582 fileapi::NativeFileUtil::CopyOrMoveModeForDestination( | 583 storage::NativeFileUtil::CopyOrMoveModeForDestination( |
| 583 dest_url, true /* copy */)); | 584 dest_url, true /* copy */)); |
| 584 } else { // non-overwrite | 585 } else { // non-overwrite |
| 585 error = CreateFile(context, src_local_path, dest_url, &dest_file_info); | 586 error = CreateFile(context, src_local_path, dest_url, &dest_file_info); |
| 586 } | 587 } |
| 587 } else { | 588 } else { |
| 588 if (overwrite) { | 589 if (overwrite) { |
| 589 if (db->OverwritingMoveFile(src_file_id, dest_file_id)) { | 590 if (db->OverwritingMoveFile(src_file_id, dest_file_id)) { |
| 590 if (base::File::FILE_OK != | 591 if (base::File::FILE_OK != NativeFileUtil::DeleteFile(dest_local_path)) |
| 591 NativeFileUtil::DeleteFile(dest_local_path)) | |
| 592 LOG(WARNING) << "Leaked a backing file."; | 592 LOG(WARNING) << "Leaked a backing file."; |
| 593 error = base::File::FILE_OK; | 593 error = base::File::FILE_OK; |
| 594 } else { | 594 } else { |
| 595 error = base::File::FILE_ERROR_FAILED; | 595 error = base::File::FILE_ERROR_FAILED; |
| 596 } | 596 } |
| 597 } else { // non-overwrite | 597 } else { // non-overwrite |
| 598 if (db->UpdateFileInfo(src_file_id, dest_file_info)) | 598 if (db->UpdateFileInfo(src_file_id, dest_file_info)) |
| 599 error = base::File::FILE_OK; | 599 error = base::File::FILE_OK; |
| 600 else | 600 else |
| 601 error = base::File::FILE_ERROR_FAILED; | 601 error = base::File::FILE_ERROR_FAILED; |
| 602 } | 602 } |
| 603 } | 603 } |
| 604 | 604 |
| 605 if (error != base::File::FILE_OK) | 605 if (error != base::File::FILE_OK) |
| 606 return error; | 606 return error; |
| 607 | 607 |
| 608 if (overwrite) { | 608 if (overwrite) { |
| 609 context->change_observers()->Notify( | 609 context->change_observers()->Notify(&FileChangeObserver::OnModifyFile, |
| 610 &FileChangeObserver::OnModifyFile, | 610 MakeTuple(dest_url)); |
| 611 MakeTuple(dest_url)); | |
| 612 } else { | 611 } else { |
| 613 context->change_observers()->Notify( | 612 context->change_observers()->Notify(&FileChangeObserver::OnCreateFileFrom, |
| 614 &FileChangeObserver::OnCreateFileFrom, | 613 MakeTuple(dest_url, src_url)); |
| 615 MakeTuple(dest_url, src_url)); | |
| 616 } | 614 } |
| 617 | 615 |
| 618 if (!copy) { | 616 if (!copy) { |
| 619 context->change_observers()->Notify( | 617 context->change_observers()->Notify(&FileChangeObserver::OnRemoveFile, |
| 620 &FileChangeObserver::OnRemoveFile, MakeTuple(src_url)); | 618 MakeTuple(src_url)); |
| 621 TouchDirectory(db, src_file_info.parent_id); | 619 TouchDirectory(db, src_file_info.parent_id); |
| 622 } | 620 } |
| 623 | 621 |
| 624 TouchDirectory(db, dest_file_info.parent_id); | 622 TouchDirectory(db, dest_file_info.parent_id); |
| 625 | 623 |
| 626 UpdateUsage(context, dest_url, growth); | 624 UpdateUsage(context, dest_url, growth); |
| 627 return error; | 625 return error; |
| 628 } | 626 } |
| 629 | 627 |
| 630 base::File::Error ObfuscatedFileUtil::CopyInForeignFile( | 628 base::File::Error ObfuscatedFileUtil::CopyInForeignFile( |
| 631 FileSystemOperationContext* context, | 629 FileSystemOperationContext* context, |
| 632 const base::FilePath& src_file_path, | 630 const base::FilePath& src_file_path, |
| 633 const FileSystemURL& dest_url) { | 631 const FileSystemURL& dest_url) { |
| 634 SandboxDirectoryDatabase* db = GetDirectoryDatabase(dest_url, true); | 632 SandboxDirectoryDatabase* db = GetDirectoryDatabase(dest_url, true); |
| 635 if (!db) | 633 if (!db) |
| 636 return base::File::FILE_ERROR_FAILED; | 634 return base::File::FILE_ERROR_FAILED; |
| 637 | 635 |
| 638 base::File::Info src_platform_file_info; | 636 base::File::Info src_platform_file_info; |
| 639 if (!base::GetFileInfo(src_file_path, &src_platform_file_info)) | 637 if (!base::GetFileInfo(src_file_path, &src_platform_file_info)) |
| 640 return base::File::FILE_ERROR_NOT_FOUND; | 638 return base::File::FILE_ERROR_NOT_FOUND; |
| 641 | 639 |
| 642 FileId dest_file_id; | 640 FileId dest_file_id; |
| 643 bool overwrite = db->GetFileWithPath(dest_url.path(), | 641 bool overwrite = db->GetFileWithPath(dest_url.path(), &dest_file_id); |
| 644 &dest_file_id); | |
| 645 | 642 |
| 646 FileInfo dest_file_info; | 643 FileInfo dest_file_info; |
| 647 base::File::Info dest_platform_file_info; // overwrite case only | 644 base::File::Info dest_platform_file_info; // overwrite case only |
| 648 if (overwrite) { | 645 if (overwrite) { |
| 649 base::FilePath dest_local_path; | 646 base::FilePath dest_local_path; |
| 650 base::File::Error error = GetFileInfoInternal( | 647 base::File::Error error = GetFileInfoInternal(db, |
| 651 db, context, dest_url, dest_file_id, | 648 context, |
| 652 &dest_file_info, &dest_platform_file_info, &dest_local_path); | 649 dest_url, |
| 650 dest_file_id, |
| 651 &dest_file_info, |
| 652 &dest_platform_file_info, |
| 653 &dest_local_path); |
| 653 if (error == base::File::FILE_ERROR_NOT_FOUND) | 654 if (error == base::File::FILE_ERROR_NOT_FOUND) |
| 654 overwrite = false; // fallback to non-overwrite case | 655 overwrite = false; // fallback to non-overwrite case |
| 655 else if (error != base::File::FILE_OK) | 656 else if (error != base::File::FILE_OK) |
| 656 return error; | 657 return error; |
| 657 else if (dest_file_info.is_directory()) | 658 else if (dest_file_info.is_directory()) |
| 658 return base::File::FILE_ERROR_INVALID_OPERATION; | 659 return base::File::FILE_ERROR_INVALID_OPERATION; |
| 659 } | 660 } |
| 660 if (!overwrite) { | 661 if (!overwrite) { |
| 661 FileId dest_parent_id; | 662 FileId dest_parent_id; |
| 662 if (!db->GetFileWithPath(VirtualPath::DirName(dest_url.path()), | 663 if (!db->GetFileWithPath(VirtualPath::DirName(dest_url.path()), |
| 663 &dest_parent_id)) { | 664 &dest_parent_id)) { |
| 664 return base::File::FILE_ERROR_NOT_FOUND; | 665 return base::File::FILE_ERROR_NOT_FOUND; |
| 665 } | 666 } |
| 666 if (!dest_file_info.is_directory()) | 667 if (!dest_file_info.is_directory()) |
| 667 return base::File::FILE_ERROR_FAILED; | 668 return base::File::FILE_ERROR_FAILED; |
| 668 InitFileInfo(&dest_file_info, dest_parent_id, | 669 InitFileInfo(&dest_file_info, |
| 670 dest_parent_id, |
| 669 VirtualPath::BaseName(dest_url.path()).value()); | 671 VirtualPath::BaseName(dest_url.path()).value()); |
| 670 } | 672 } |
| 671 | 673 |
| 672 int64 growth = src_platform_file_info.size; | 674 int64 growth = src_platform_file_info.size; |
| 673 if (overwrite) | 675 if (overwrite) |
| 674 growth -= dest_platform_file_info.size; | 676 growth -= dest_platform_file_info.size; |
| 675 else | 677 else |
| 676 growth += UsageForPath(dest_file_info.name.size()); | 678 growth += UsageForPath(dest_file_info.name.size()); |
| 677 if (!AllocateQuota(context, growth)) | 679 if (!AllocateQuota(context, growth)) |
| 678 return base::File::FILE_ERROR_NO_SPACE; | 680 return base::File::FILE_ERROR_NO_SPACE; |
| 679 | 681 |
| 680 base::File::Error error; | 682 base::File::Error error; |
| 681 if (overwrite) { | 683 if (overwrite) { |
| 682 base::FilePath dest_local_path = | 684 base::FilePath dest_local_path = |
| 683 DataPathToLocalPath(dest_url, dest_file_info.data_path); | 685 DataPathToLocalPath(dest_url, dest_file_info.data_path); |
| 684 error = NativeFileUtil::CopyOrMoveFile( | 686 error = NativeFileUtil::CopyOrMoveFile( |
| 685 src_file_path, dest_local_path, | 687 src_file_path, |
| 688 dest_local_path, |
| 686 FileSystemOperation::OPTION_NONE, | 689 FileSystemOperation::OPTION_NONE, |
| 687 fileapi::NativeFileUtil::CopyOrMoveModeForDestination(dest_url, | 690 storage::NativeFileUtil::CopyOrMoveModeForDestination(dest_url, |
| 688 true /* copy */)); | 691 true /* copy */)); |
| 689 } else { | 692 } else { |
| 690 error = CreateFile(context, src_file_path, dest_url, &dest_file_info); | 693 error = CreateFile(context, src_file_path, dest_url, &dest_file_info); |
| 691 } | 694 } |
| 692 | 695 |
| 693 if (error != base::File::FILE_OK) | 696 if (error != base::File::FILE_OK) |
| 694 return error; | 697 return error; |
| 695 | 698 |
| 696 if (overwrite) { | 699 if (overwrite) { |
| 697 context->change_observers()->Notify( | 700 context->change_observers()->Notify(&FileChangeObserver::OnModifyFile, |
| 698 &FileChangeObserver::OnModifyFile, MakeTuple(dest_url)); | 701 MakeTuple(dest_url)); |
| 699 } else { | 702 } else { |
| 700 context->change_observers()->Notify( | 703 context->change_observers()->Notify(&FileChangeObserver::OnCreateFile, |
| 701 &FileChangeObserver::OnCreateFile, MakeTuple(dest_url)); | 704 MakeTuple(dest_url)); |
| 702 } | 705 } |
| 703 | 706 |
| 704 UpdateUsage(context, dest_url, growth); | 707 UpdateUsage(context, dest_url, growth); |
| 705 TouchDirectory(db, dest_file_info.parent_id); | 708 TouchDirectory(db, dest_file_info.parent_id); |
| 706 return base::File::FILE_OK; | 709 return base::File::FILE_OK; |
| 707 } | 710 } |
| 708 | 711 |
| 709 base::File::Error ObfuscatedFileUtil::DeleteFile( | 712 base::File::Error ObfuscatedFileUtil::DeleteFile( |
| 710 FileSystemOperationContext* context, | 713 FileSystemOperationContext* context, |
| 711 const FileSystemURL& url) { | 714 const FileSystemURL& url) { |
| 712 SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, true); | 715 SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, true); |
| 713 if (!db) | 716 if (!db) |
| 714 return base::File::FILE_ERROR_FAILED; | 717 return base::File::FILE_ERROR_FAILED; |
| 715 FileId file_id; | 718 FileId file_id; |
| 716 if (!db->GetFileWithPath(url.path(), &file_id)) | 719 if (!db->GetFileWithPath(url.path(), &file_id)) |
| 717 return base::File::FILE_ERROR_NOT_FOUND; | 720 return base::File::FILE_ERROR_NOT_FOUND; |
| 718 | 721 |
| 719 FileInfo file_info; | 722 FileInfo file_info; |
| 720 base::File::Info platform_file_info; | 723 base::File::Info platform_file_info; |
| 721 base::FilePath local_path; | 724 base::FilePath local_path; |
| 722 base::File::Error error = GetFileInfoInternal( | 725 base::File::Error error = GetFileInfoInternal( |
| 723 db, context, url, file_id, &file_info, &platform_file_info, &local_path); | 726 db, context, url, file_id, &file_info, &platform_file_info, &local_path); |
| 724 if (error != base::File::FILE_ERROR_NOT_FOUND && | 727 if (error != base::File::FILE_ERROR_NOT_FOUND && error != base::File::FILE_OK) |
| 725 error != base::File::FILE_OK) | |
| 726 return error; | 728 return error; |
| 727 | 729 |
| 728 if (file_info.is_directory()) | 730 if (file_info.is_directory()) |
| 729 return base::File::FILE_ERROR_NOT_A_FILE; | 731 return base::File::FILE_ERROR_NOT_A_FILE; |
| 730 | 732 |
| 731 int64 growth = -UsageForPath(file_info.name.size()) - platform_file_info.size; | 733 int64 growth = -UsageForPath(file_info.name.size()) - platform_file_info.size; |
| 732 AllocateQuota(context, growth); | 734 AllocateQuota(context, growth); |
| 733 if (!db->RemoveFileInfo(file_id)) { | 735 if (!db->RemoveFileInfo(file_id)) { |
| 734 NOTREACHED(); | 736 NOTREACHED(); |
| 735 return base::File::FILE_ERROR_FAILED; | 737 return base::File::FILE_ERROR_FAILED; |
| 736 } | 738 } |
| 737 UpdateUsage(context, url, growth); | 739 UpdateUsage(context, url, growth); |
| 738 TouchDirectory(db, file_info.parent_id); | 740 TouchDirectory(db, file_info.parent_id); |
| 739 | 741 |
| 740 context->change_observers()->Notify( | 742 context->change_observers()->Notify(&FileChangeObserver::OnRemoveFile, |
| 741 &FileChangeObserver::OnRemoveFile, MakeTuple(url)); | 743 MakeTuple(url)); |
| 742 | 744 |
| 743 if (error == base::File::FILE_ERROR_NOT_FOUND) | 745 if (error == base::File::FILE_ERROR_NOT_FOUND) |
| 744 return base::File::FILE_OK; | 746 return base::File::FILE_OK; |
| 745 | 747 |
| 746 error = NativeFileUtil::DeleteFile(local_path); | 748 error = NativeFileUtil::DeleteFile(local_path); |
| 747 if (base::File::FILE_OK != error) | 749 if (base::File::FILE_OK != error) |
| 748 LOG(WARNING) << "Leaked a backing file."; | 750 LOG(WARNING) << "Leaked a backing file."; |
| 749 return base::File::FILE_OK; | 751 return base::File::FILE_OK; |
| 750 } | 752 } |
| 751 | 753 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 765 return base::File::FILE_ERROR_FAILED; | 767 return base::File::FILE_ERROR_FAILED; |
| 766 } | 768 } |
| 767 if (!file_info.is_directory()) | 769 if (!file_info.is_directory()) |
| 768 return base::File::FILE_ERROR_NOT_A_DIRECTORY; | 770 return base::File::FILE_ERROR_NOT_A_DIRECTORY; |
| 769 if (!db->RemoveFileInfo(file_id)) | 771 if (!db->RemoveFileInfo(file_id)) |
| 770 return base::File::FILE_ERROR_NOT_EMPTY; | 772 return base::File::FILE_ERROR_NOT_EMPTY; |
| 771 int64 growth = -UsageForPath(file_info.name.size()); | 773 int64 growth = -UsageForPath(file_info.name.size()); |
| 772 AllocateQuota(context, growth); | 774 AllocateQuota(context, growth); |
| 773 UpdateUsage(context, url, growth); | 775 UpdateUsage(context, url, growth); |
| 774 TouchDirectory(db, file_info.parent_id); | 776 TouchDirectory(db, file_info.parent_id); |
| 775 context->change_observers()->Notify( | 777 context->change_observers()->Notify(&FileChangeObserver::OnRemoveDirectory, |
| 776 &FileChangeObserver::OnRemoveDirectory, MakeTuple(url)); | 778 MakeTuple(url)); |
| 777 return base::File::FILE_OK; | 779 return base::File::FILE_OK; |
| 778 } | 780 } |
| 779 | 781 |
| 780 webkit_blob::ScopedFile ObfuscatedFileUtil::CreateSnapshotFile( | 782 storage::ScopedFile ObfuscatedFileUtil::CreateSnapshotFile( |
| 781 FileSystemOperationContext* context, | 783 FileSystemOperationContext* context, |
| 782 const FileSystemURL& url, | 784 const FileSystemURL& url, |
| 783 base::File::Error* error, | 785 base::File::Error* error, |
| 784 base::File::Info* file_info, | 786 base::File::Info* file_info, |
| 785 base::FilePath* platform_path) { | 787 base::FilePath* platform_path) { |
| 786 // We're just returning the local file information. | 788 // We're just returning the local file information. |
| 787 *error = GetFileInfo(context, url, file_info, platform_path); | 789 *error = GetFileInfo(context, url, file_info, platform_path); |
| 788 if (*error == base::File::FILE_OK && file_info->is_directory) { | 790 if (*error == base::File::FILE_OK && file_info->is_directory) { |
| 789 *file_info = base::File::Info(); | 791 *file_info = base::File::Info(); |
| 790 *error = base::File::FILE_ERROR_NOT_A_FILE; | 792 *error = base::File::FILE_ERROR_NOT_A_FILE; |
| 791 } | 793 } |
| 792 return webkit_blob::ScopedFile(); | 794 return storage::ScopedFile(); |
| 793 } | 795 } |
| 794 | 796 |
| 795 scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> | 797 scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> |
| 796 ObfuscatedFileUtil::CreateFileEnumerator( | 798 ObfuscatedFileUtil::CreateFileEnumerator(FileSystemOperationContext* context, |
| 797 FileSystemOperationContext* context, | 799 const FileSystemURL& root_url, |
| 798 const FileSystemURL& root_url, | 800 bool recursive) { |
| 799 bool recursive) { | |
| 800 SandboxDirectoryDatabase* db = GetDirectoryDatabase(root_url, false); | 801 SandboxDirectoryDatabase* db = GetDirectoryDatabase(root_url, false); |
| 801 if (!db) { | 802 if (!db) { |
| 802 return scoped_ptr<AbstractFileEnumerator>(new EmptyFileEnumerator()); | 803 return scoped_ptr<AbstractFileEnumerator>(new EmptyFileEnumerator()); |
| 803 } | 804 } |
| 804 return scoped_ptr<AbstractFileEnumerator>( | 805 return scoped_ptr<AbstractFileEnumerator>( |
| 805 new ObfuscatedFileEnumerator(db, context, this, root_url, recursive)); | 806 new ObfuscatedFileEnumerator(db, context, this, root_url, recursive)); |
| 806 } | 807 } |
| 807 | 808 |
| 808 bool ObfuscatedFileUtil::IsDirectoryEmpty( | 809 bool ObfuscatedFileUtil::IsDirectoryEmpty(FileSystemOperationContext* context, |
| 809 FileSystemOperationContext* context, | 810 const FileSystemURL& url) { |
| 810 const FileSystemURL& url) { | |
| 811 SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, false); | 811 SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, false); |
| 812 if (!db) | 812 if (!db) |
| 813 return true; // Not a great answer, but it's what others do. | 813 return true; // Not a great answer, but it's what others do. |
| 814 FileId file_id; | 814 FileId file_id; |
| 815 if (!db->GetFileWithPath(url.path(), &file_id)) | 815 if (!db->GetFileWithPath(url.path(), &file_id)) |
| 816 return true; // Ditto. | 816 return true; // Ditto. |
| 817 FileInfo file_info; | 817 FileInfo file_info; |
| 818 if (!db->GetFileInfo(file_id, &file_info)) { | 818 if (!db->GetFileInfo(file_id, &file_info)) { |
| 819 DCHECK(!file_id); | 819 DCHECK(!file_id); |
| 820 // It's the root directory and the database hasn't been initialized yet. | 820 // It's the root directory and the database hasn't been initialized yet. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 836 base::File::Error* error_code) { | 836 base::File::Error* error_code) { |
| 837 base::FilePath origin_dir = GetDirectoryForOrigin(origin, create, error_code); | 837 base::FilePath origin_dir = GetDirectoryForOrigin(origin, create, error_code); |
| 838 if (origin_dir.empty()) | 838 if (origin_dir.empty()) |
| 839 return base::FilePath(); | 839 return base::FilePath(); |
| 840 if (type_string.empty()) | 840 if (type_string.empty()) |
| 841 return origin_dir; | 841 return origin_dir; |
| 842 base::FilePath path = origin_dir.AppendASCII(type_string); | 842 base::FilePath path = origin_dir.AppendASCII(type_string); |
| 843 base::File::Error error = base::File::FILE_OK; | 843 base::File::Error error = base::File::FILE_OK; |
| 844 if (!base::DirectoryExists(path) && | 844 if (!base::DirectoryExists(path) && |
| 845 (!create || !base::CreateDirectory(path))) { | 845 (!create || !base::CreateDirectory(path))) { |
| 846 error = create ? | 846 error = create ? base::File::FILE_ERROR_FAILED |
| 847 base::File::FILE_ERROR_FAILED : | 847 : base::File::FILE_ERROR_NOT_FOUND; |
| 848 base::File::FILE_ERROR_NOT_FOUND; | |
| 849 } | 848 } |
| 850 | 849 |
| 851 if (error_code) | 850 if (error_code) |
| 852 *error_code = error; | 851 *error_code = error; |
| 853 return path; | 852 return path; |
| 854 } | 853 } |
| 855 | 854 |
| 856 bool ObfuscatedFileUtil::DeleteDirectoryForOriginAndType( | 855 bool ObfuscatedFileUtil::DeleteDirectoryForOriginAndType( |
| 857 const GURL& origin, | 856 const GURL& origin, |
| 858 const std::string& type_string) { | 857 const std::string& type_string) { |
| 859 base::File::Error error = base::File::FILE_OK; | 858 base::File::Error error = base::File::FILE_OK; |
| 860 base::FilePath origin_type_path = GetDirectoryForOriginAndType( | 859 base::FilePath origin_type_path = |
| 861 origin, type_string, false, &error); | 860 GetDirectoryForOriginAndType(origin, type_string, false, &error); |
| 862 if (origin_type_path.empty()) | 861 if (origin_type_path.empty()) |
| 863 return true; | 862 return true; |
| 864 if (error != base::File::FILE_ERROR_NOT_FOUND) { | 863 if (error != base::File::FILE_ERROR_NOT_FOUND) { |
| 865 // TODO(dmikurube): Consider the return value of DestroyDirectoryDatabase. | 864 // TODO(dmikurube): Consider the return value of DestroyDirectoryDatabase. |
| 866 // We ignore its error now since 1) it doesn't matter the final result, and | 865 // We ignore its error now since 1) it doesn't matter the final result, and |
| 867 // 2) it always returns false in Windows because of LevelDB's | 866 // 2) it always returns false in Windows because of LevelDB's |
| 868 // implementation. | 867 // implementation. |
| 869 // Information about failure would be useful for debugging. | 868 // Information about failure would be useful for debugging. |
| 870 if (!type_string.empty()) | 869 if (!type_string.empty()) |
| 871 DestroyDirectoryDatabase(origin, type_string); | 870 DestroyDirectoryDatabase(origin, type_string); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 903 return false; | 902 return false; |
| 904 | 903 |
| 905 return true; | 904 return true; |
| 906 } | 905 } |
| 907 | 906 |
| 908 ObfuscatedFileUtil::AbstractOriginEnumerator* | 907 ObfuscatedFileUtil::AbstractOriginEnumerator* |
| 909 ObfuscatedFileUtil::CreateOriginEnumerator() { | 908 ObfuscatedFileUtil::CreateOriginEnumerator() { |
| 910 std::vector<SandboxOriginDatabase::OriginRecord> origins; | 909 std::vector<SandboxOriginDatabase::OriginRecord> origins; |
| 911 | 910 |
| 912 InitOriginDatabase(GURL(), false); | 911 InitOriginDatabase(GURL(), false); |
| 913 return new ObfuscatedOriginEnumerator( | 912 return new ObfuscatedOriginEnumerator(origin_database_.get(), |
| 914 origin_database_.get(), file_system_directory_); | 913 file_system_directory_); |
| 915 } | 914 } |
| 916 | 915 |
| 917 bool ObfuscatedFileUtil::DestroyDirectoryDatabase( | 916 bool ObfuscatedFileUtil::DestroyDirectoryDatabase( |
| 918 const GURL& origin, | 917 const GURL& origin, |
| 919 const std::string& type_string) { | 918 const std::string& type_string) { |
| 920 std::string key = GetDirectoryDatabaseKey(origin, type_string); | 919 std::string key = GetDirectoryDatabaseKey(origin, type_string); |
| 921 if (key.empty()) | 920 if (key.empty()) |
| 922 return true; | 921 return true; |
| 923 DirectoryMap::iterator iter = directories_.find(key); | 922 DirectoryMap::iterator iter = directories_.find(key); |
| 924 if (iter != directories_.end()) { | 923 if (iter != directories_.end()) { |
| 925 SandboxDirectoryDatabase* database = iter->second; | 924 SandboxDirectoryDatabase* database = iter->second; |
| 926 directories_.erase(iter); | 925 directories_.erase(iter); |
| 927 delete database; | 926 delete database; |
| 928 } | 927 } |
| 929 | 928 |
| 930 base::File::Error error = base::File::FILE_OK; | 929 base::File::Error error = base::File::FILE_OK; |
| 931 base::FilePath path = GetDirectoryForOriginAndType( | 930 base::FilePath path = |
| 932 origin, type_string, false, &error); | 931 GetDirectoryForOriginAndType(origin, type_string, false, &error); |
| 933 if (path.empty() || error == base::File::FILE_ERROR_NOT_FOUND) | 932 if (path.empty() || error == base::File::FILE_ERROR_NOT_FOUND) |
| 934 return true; | 933 return true; |
| 935 return SandboxDirectoryDatabase::DestroyDatabase(path, env_override_); | 934 return SandboxDirectoryDatabase::DestroyDatabase(path, env_override_); |
| 936 } | 935 } |
| 937 | 936 |
| 938 // static | 937 // static |
| 939 int64 ObfuscatedFileUtil::ComputeFilePathCost(const base::FilePath& path) { | 938 int64 ObfuscatedFileUtil::ComputeFilePathCost(const base::FilePath& path) { |
| 940 return UsageForPath(VirtualPath::BaseName(path).value().size()); | 939 return UsageForPath(VirtualPath::BaseName(path).value().size()); |
| 941 } | 940 } |
| 942 | 941 |
| 943 void ObfuscatedFileUtil::MaybePrepopulateDatabase( | 942 void ObfuscatedFileUtil::MaybePrepopulateDatabase( |
| 944 const std::vector<std::string>& type_strings_to_prepopulate) { | 943 const std::vector<std::string>& type_strings_to_prepopulate) { |
| 945 SandboxPrioritizedOriginDatabase database(file_system_directory_, | 944 SandboxPrioritizedOriginDatabase database(file_system_directory_, |
| 946 env_override_); | 945 env_override_); |
| 947 std::string origin_string = database.GetPrimaryOrigin(); | 946 std::string origin_string = database.GetPrimaryOrigin(); |
| 948 if (origin_string.empty() || !database.HasOriginPath(origin_string)) | 947 if (origin_string.empty() || !database.HasOriginPath(origin_string)) |
| 949 return; | 948 return; |
| 950 const GURL origin = webkit_database::GetOriginFromIdentifier(origin_string); | 949 const GURL origin = webkit_database::GetOriginFromIdentifier(origin_string); |
| 951 | 950 |
| 952 // Prepopulate the directory database(s) if and only if this instance | 951 // Prepopulate the directory database(s) if and only if this instance |
| 953 // has primary origin and the directory database is already there. | 952 // has primary origin and the directory database is already there. |
| 954 for (size_t i = 0; i < type_strings_to_prepopulate.size(); ++i) { | 953 for (size_t i = 0; i < type_strings_to_prepopulate.size(); ++i) { |
| 955 const std::string type_string = type_strings_to_prepopulate[i]; | 954 const std::string type_string = type_strings_to_prepopulate[i]; |
| 956 // Only handles known types. | 955 // Only handles known types. |
| 957 if (!ContainsKey(known_type_strings_, type_string)) | 956 if (!ContainsKey(known_type_strings_, type_string)) |
| 958 continue; | 957 continue; |
| 959 base::File::Error error = base::File::FILE_ERROR_FAILED; | 958 base::File::Error error = base::File::FILE_ERROR_FAILED; |
| 960 base::FilePath path = GetDirectoryForOriginAndType( | 959 base::FilePath path = |
| 961 origin, type_string, false, &error); | 960 GetDirectoryForOriginAndType(origin, type_string, false, &error); |
| 962 if (error != base::File::FILE_OK) | 961 if (error != base::File::FILE_OK) |
| 963 continue; | 962 continue; |
| 964 scoped_ptr<SandboxDirectoryDatabase> db( | 963 scoped_ptr<SandboxDirectoryDatabase> db( |
| 965 new SandboxDirectoryDatabase(path, env_override_)); | 964 new SandboxDirectoryDatabase(path, env_override_)); |
| 966 if (db->Init(SandboxDirectoryDatabase::FAIL_ON_CORRUPTION)) { | 965 if (db->Init(SandboxDirectoryDatabase::FAIL_ON_CORRUPTION)) { |
| 967 directories_[GetDirectoryDatabaseKey(origin, type_string)] = db.release(); | 966 directories_[GetDirectoryDatabaseKey(origin, type_string)] = db.release(); |
| 968 MarkUsed(); | 967 MarkUsed(); |
| 969 // Don't populate more than one database, as it may rather hurt | 968 // Don't populate more than one database, as it may rather hurt |
| 970 // performance. | 969 // performance. |
| 971 break; | 970 break; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1010 file_info->is_directory = true; | 1009 file_info->is_directory = true; |
| 1011 file_info->is_symbolic_link = false; | 1010 file_info->is_symbolic_link = false; |
| 1012 file_info->last_modified = local_info->modification_time; | 1011 file_info->last_modified = local_info->modification_time; |
| 1013 *platform_file_path = base::FilePath(); | 1012 *platform_file_path = base::FilePath(); |
| 1014 // We don't fill in ctime or atime. | 1013 // We don't fill in ctime or atime. |
| 1015 return base::File::FILE_OK; | 1014 return base::File::FILE_OK; |
| 1016 } | 1015 } |
| 1017 if (local_info->data_path.empty()) | 1016 if (local_info->data_path.empty()) |
| 1018 return base::File::FILE_ERROR_INVALID_OPERATION; | 1017 return base::File::FILE_ERROR_INVALID_OPERATION; |
| 1019 base::FilePath local_path = DataPathToLocalPath(url, local_info->data_path); | 1018 base::FilePath local_path = DataPathToLocalPath(url, local_info->data_path); |
| 1020 base::File::Error error = NativeFileUtil::GetFileInfo( | 1019 base::File::Error error = NativeFileUtil::GetFileInfo(local_path, file_info); |
| 1021 local_path, file_info); | |
| 1022 // We should not follow symbolic links in sandboxed file system. | 1020 // We should not follow symbolic links in sandboxed file system. |
| 1023 if (base::IsLink(local_path)) { | 1021 if (base::IsLink(local_path)) { |
| 1024 LOG(WARNING) << "Found a symbolic file."; | 1022 LOG(WARNING) << "Found a symbolic file."; |
| 1025 error = base::File::FILE_ERROR_NOT_FOUND; | 1023 error = base::File::FILE_ERROR_NOT_FOUND; |
| 1026 } | 1024 } |
| 1027 if (error == base::File::FILE_OK) { | 1025 if (error == base::File::FILE_OK) { |
| 1028 *platform_file_path = local_path; | 1026 *platform_file_path = local_path; |
| 1029 } else if (error == base::File::FILE_ERROR_NOT_FOUND) { | 1027 } else if (error == base::File::FILE_ERROR_NOT_FOUND) { |
| 1030 LOG(WARNING) << "Lost a backing file."; | 1028 LOG(WARNING) << "Lost a backing file."; |
| 1031 InvalidateUsageCache(context, url.origin(), url.type()); | 1029 InvalidateUsageCache(context, url.origin(), url.type()); |
| 1032 if (!db->RemoveFileInfo(file_id)) | 1030 if (!db->RemoveFileInfo(file_id)) |
| 1033 return base::File::FILE_ERROR_FAILED; | 1031 return base::File::FILE_ERROR_FAILED; |
| 1034 } | 1032 } |
| 1035 return error; | 1033 return error; |
| 1036 } | 1034 } |
| 1037 | 1035 |
| 1038 base::File ObfuscatedFileUtil::CreateAndOpenFile( | 1036 base::File ObfuscatedFileUtil::CreateAndOpenFile( |
| 1039 FileSystemOperationContext* context, | 1037 FileSystemOperationContext* context, |
| 1040 const FileSystemURL& dest_url, | 1038 const FileSystemURL& dest_url, |
| 1041 FileInfo* dest_file_info, int file_flags) { | 1039 FileInfo* dest_file_info, |
| 1040 int file_flags) { |
| 1042 SandboxDirectoryDatabase* db = GetDirectoryDatabase(dest_url, true); | 1041 SandboxDirectoryDatabase* db = GetDirectoryDatabase(dest_url, true); |
| 1043 | 1042 |
| 1044 base::FilePath root, dest_local_path; | 1043 base::FilePath root, dest_local_path; |
| 1045 base::File::Error error = GenerateNewLocalPath(db, context, dest_url, &root, | 1044 base::File::Error error = |
| 1046 &dest_local_path); | 1045 GenerateNewLocalPath(db, context, dest_url, &root, &dest_local_path); |
| 1047 if (error != base::File::FILE_OK) | 1046 if (error != base::File::FILE_OK) |
| 1048 return base::File(error); | 1047 return base::File(error); |
| 1049 | 1048 |
| 1050 if (base::PathExists(dest_local_path)) { | 1049 if (base::PathExists(dest_local_path)) { |
| 1051 if (!base::DeleteFile(dest_local_path, true /* recursive */)) | 1050 if (!base::DeleteFile(dest_local_path, true /* recursive */)) |
| 1052 return base::File(base::File::FILE_ERROR_FAILED); | 1051 return base::File(base::File::FILE_ERROR_FAILED); |
| 1053 LOG(WARNING) << "A stray file detected"; | 1052 LOG(WARNING) << "A stray file detected"; |
| 1054 InvalidateUsageCache(context, dest_url.origin(), dest_url.type()); | 1053 InvalidateUsageCache(context, dest_url.origin(), dest_url.type()); |
| 1055 } | 1054 } |
| 1056 | 1055 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1075 } | 1074 } |
| 1076 | 1075 |
| 1077 base::File::Error ObfuscatedFileUtil::CreateFile( | 1076 base::File::Error ObfuscatedFileUtil::CreateFile( |
| 1078 FileSystemOperationContext* context, | 1077 FileSystemOperationContext* context, |
| 1079 const base::FilePath& src_file_path, | 1078 const base::FilePath& src_file_path, |
| 1080 const FileSystemURL& dest_url, | 1079 const FileSystemURL& dest_url, |
| 1081 FileInfo* dest_file_info) { | 1080 FileInfo* dest_file_info) { |
| 1082 SandboxDirectoryDatabase* db = GetDirectoryDatabase(dest_url, true); | 1081 SandboxDirectoryDatabase* db = GetDirectoryDatabase(dest_url, true); |
| 1083 | 1082 |
| 1084 base::FilePath root, dest_local_path; | 1083 base::FilePath root, dest_local_path; |
| 1085 base::File::Error error = GenerateNewLocalPath(db, context, dest_url, &root, | 1084 base::File::Error error = |
| 1086 &dest_local_path); | 1085 GenerateNewLocalPath(db, context, dest_url, &root, &dest_local_path); |
| 1087 if (error != base::File::FILE_OK) | 1086 if (error != base::File::FILE_OK) |
| 1088 return error; | 1087 return error; |
| 1089 | 1088 |
| 1090 bool created = false; | 1089 bool created = false; |
| 1091 if (src_file_path.empty()) { | 1090 if (src_file_path.empty()) { |
| 1092 if (base::PathExists(dest_local_path)) { | 1091 if (base::PathExists(dest_local_path)) { |
| 1093 if (!base::DeleteFile(dest_local_path, true /* recursive */)) | 1092 if (!base::DeleteFile(dest_local_path, true /* recursive */)) |
| 1094 return base::File::FILE_ERROR_FAILED; | 1093 return base::File::FILE_ERROR_FAILED; |
| 1095 LOG(WARNING) << "A stray file detected"; | 1094 LOG(WARNING) << "A stray file detected"; |
| 1096 InvalidateUsageCache(context, dest_url.origin(), dest_url.type()); | 1095 InvalidateUsageCache(context, dest_url.origin(), dest_url.type()); |
| 1097 } | 1096 } |
| 1098 | 1097 |
| 1099 error = NativeFileUtil::EnsureFileExists(dest_local_path, &created); | 1098 error = NativeFileUtil::EnsureFileExists(dest_local_path, &created); |
| 1100 } else { | 1099 } else { |
| 1101 error = NativeFileUtil::CopyOrMoveFile( | 1100 error = NativeFileUtil::CopyOrMoveFile( |
| 1102 src_file_path, dest_local_path, | 1101 src_file_path, |
| 1102 dest_local_path, |
| 1103 FileSystemOperation::OPTION_NONE, | 1103 FileSystemOperation::OPTION_NONE, |
| 1104 fileapi::NativeFileUtil::CopyOrMoveModeForDestination(dest_url, | 1104 storage::NativeFileUtil::CopyOrMoveModeForDestination(dest_url, |
| 1105 true /* copy */)); | 1105 true /* copy */)); |
| 1106 created = true; | 1106 created = true; |
| 1107 } | 1107 } |
| 1108 if (error != base::File::FILE_OK) | 1108 if (error != base::File::FILE_OK) |
| 1109 return error; | 1109 return error; |
| 1110 if (!created) | 1110 if (!created) |
| 1111 return base::File::FILE_ERROR_FAILED; | 1111 return base::File::FILE_ERROR_FAILED; |
| 1112 | 1112 |
| 1113 return CommitCreateFile(root, dest_local_path, db, dest_file_info); | 1113 return CommitCreateFile(root, dest_local_path, db, dest_file_info); |
| 1114 } | 1114 } |
| 1115 | 1115 |
| 1116 base::File::Error ObfuscatedFileUtil::CommitCreateFile( | 1116 base::File::Error ObfuscatedFileUtil::CommitCreateFile( |
| 1117 const base::FilePath& root, | 1117 const base::FilePath& root, |
| 1118 const base::FilePath& local_path, | 1118 const base::FilePath& local_path, |
| 1119 SandboxDirectoryDatabase* db, | 1119 SandboxDirectoryDatabase* db, |
| 1120 FileInfo* dest_file_info) { | 1120 FileInfo* dest_file_info) { |
| 1121 // This removes the root, including the trailing slash, leaving a relative | 1121 // This removes the root, including the trailing slash, leaving a relative |
| 1122 // path. | 1122 // path. |
| 1123 dest_file_info->data_path = base::FilePath( | 1123 dest_file_info->data_path = |
| 1124 local_path.value().substr(root.value().length() + 1)); | 1124 base::FilePath(local_path.value().substr(root.value().length() + 1)); |
| 1125 | 1125 |
| 1126 FileId file_id; | 1126 FileId file_id; |
| 1127 base::File::Error error = db->AddFileInfo(*dest_file_info, &file_id); | 1127 base::File::Error error = db->AddFileInfo(*dest_file_info, &file_id); |
| 1128 if (error != base::File::FILE_OK) | 1128 if (error != base::File::FILE_OK) |
| 1129 return error; | 1129 return error; |
| 1130 | 1130 |
| 1131 TouchDirectory(db, dest_file_info->parent_id); | 1131 TouchDirectory(db, dest_file_info->parent_id); |
| 1132 return base::File::FILE_OK; | 1132 return base::File::FILE_OK; |
| 1133 } | 1133 } |
| 1134 | 1134 |
| 1135 base::FilePath ObfuscatedFileUtil::DataPathToLocalPath( | 1135 base::FilePath ObfuscatedFileUtil::DataPathToLocalPath( |
| 1136 const FileSystemURL& url, const base::FilePath& data_path) { | 1136 const FileSystemURL& url, |
| 1137 const base::FilePath& data_path) { |
| 1137 base::File::Error error = base::File::FILE_OK; | 1138 base::File::Error error = base::File::FILE_OK; |
| 1138 base::FilePath root = GetDirectoryForURL(url, false, &error); | 1139 base::FilePath root = GetDirectoryForURL(url, false, &error); |
| 1139 if (error != base::File::FILE_OK) | 1140 if (error != base::File::FILE_OK) |
| 1140 return base::FilePath(); | 1141 return base::FilePath(); |
| 1141 return root.Append(data_path); | 1142 return root.Append(data_path); |
| 1142 } | 1143 } |
| 1143 | 1144 |
| 1144 std::string ObfuscatedFileUtil::GetDirectoryDatabaseKey( | 1145 std::string ObfuscatedFileUtil::GetDirectoryDatabaseKey( |
| 1145 const GURL& origin, const std::string& type_string) { | 1146 const GURL& origin, |
| 1147 const std::string& type_string) { |
| 1146 if (type_string.empty()) { | 1148 if (type_string.empty()) { |
| 1147 LOG(WARNING) << "Unknown filesystem type requested:" << type_string; | 1149 LOG(WARNING) << "Unknown filesystem type requested:" << type_string; |
| 1148 return std::string(); | 1150 return std::string(); |
| 1149 } | 1151 } |
| 1150 // For isolated origin we just use a type string as a key. | 1152 // For isolated origin we just use a type string as a key. |
| 1151 return webkit_database::GetIdentifierFromOrigin(origin) + | 1153 return webkit_database::GetIdentifierFromOrigin(origin) + type_string; |
| 1152 type_string; | |
| 1153 } | 1154 } |
| 1154 | 1155 |
| 1155 // TODO(ericu): How to do the whole validation-without-creation thing? | 1156 // TODO(ericu): How to do the whole validation-without-creation thing? |
| 1156 // We may not have quota even to create the database. | 1157 // We may not have quota even to create the database. |
| 1157 // Ah, in that case don't even get here? | 1158 // Ah, in that case don't even get here? |
| 1158 // Still doesn't answer the quota issue, though. | 1159 // Still doesn't answer the quota issue, though. |
| 1159 SandboxDirectoryDatabase* ObfuscatedFileUtil::GetDirectoryDatabase( | 1160 SandboxDirectoryDatabase* ObfuscatedFileUtil::GetDirectoryDatabase( |
| 1160 const FileSystemURL& url, bool create) { | 1161 const FileSystemURL& url, |
| 1161 std::string key = GetDirectoryDatabaseKey( | 1162 bool create) { |
| 1162 url.origin(), CallGetTypeStringForURL(url)); | 1163 std::string key = |
| 1164 GetDirectoryDatabaseKey(url.origin(), CallGetTypeStringForURL(url)); |
| 1163 if (key.empty()) | 1165 if (key.empty()) |
| 1164 return NULL; | 1166 return NULL; |
| 1165 | 1167 |
| 1166 DirectoryMap::iterator iter = directories_.find(key); | 1168 DirectoryMap::iterator iter = directories_.find(key); |
| 1167 if (iter != directories_.end()) { | 1169 if (iter != directories_.end()) { |
| 1168 MarkUsed(); | 1170 MarkUsed(); |
| 1169 return iter->second; | 1171 return iter->second; |
| 1170 } | 1172 } |
| 1171 | 1173 |
| 1172 base::File::Error error = base::File::FILE_OK; | 1174 base::File::Error error = base::File::FILE_OK; |
| 1173 base::FilePath path = GetDirectoryForURL(url, create, &error); | 1175 base::FilePath path = GetDirectoryForURL(url, create, &error); |
| 1174 if (error != base::File::FILE_OK) { | 1176 if (error != base::File::FILE_OK) { |
| 1175 LOG(WARNING) << "Failed to get origin+type directory: " | 1177 LOG(WARNING) << "Failed to get origin+type directory: " << url.DebugString() |
| 1176 << url.DebugString() << " error:" << error; | 1178 << " error:" << error; |
| 1177 return NULL; | 1179 return NULL; |
| 1178 } | 1180 } |
| 1179 MarkUsed(); | 1181 MarkUsed(); |
| 1180 SandboxDirectoryDatabase* database = | 1182 SandboxDirectoryDatabase* database = |
| 1181 new SandboxDirectoryDatabase(path, env_override_); | 1183 new SandboxDirectoryDatabase(path, env_override_); |
| 1182 directories_[key] = database; | 1184 directories_[key] = database; |
| 1183 return database; | 1185 return database; |
| 1184 } | 1186 } |
| 1185 | 1187 |
| 1186 base::FilePath ObfuscatedFileUtil::GetDirectoryForOrigin( | 1188 base::FilePath ObfuscatedFileUtil::GetDirectoryForOrigin( |
| 1187 const GURL& origin, bool create, base::File::Error* error_code) { | 1189 const GURL& origin, |
| 1190 bool create, |
| 1191 base::File::Error* error_code) { |
| 1188 if (!InitOriginDatabase(origin, create)) { | 1192 if (!InitOriginDatabase(origin, create)) { |
| 1189 if (error_code) { | 1193 if (error_code) { |
| 1190 *error_code = create ? | 1194 *error_code = create ? base::File::FILE_ERROR_FAILED |
| 1191 base::File::FILE_ERROR_FAILED : | 1195 : base::File::FILE_ERROR_NOT_FOUND; |
| 1192 base::File::FILE_ERROR_NOT_FOUND; | |
| 1193 } | 1196 } |
| 1194 return base::FilePath(); | 1197 return base::FilePath(); |
| 1195 } | 1198 } |
| 1196 base::FilePath directory_name; | 1199 base::FilePath directory_name; |
| 1197 std::string id = webkit_database::GetIdentifierFromOrigin(origin); | 1200 std::string id = webkit_database::GetIdentifierFromOrigin(origin); |
| 1198 | 1201 |
| 1199 bool exists_in_db = origin_database_->HasOriginPath(id); | 1202 bool exists_in_db = origin_database_->HasOriginPath(id); |
| 1200 if (!exists_in_db && !create) { | 1203 if (!exists_in_db && !create) { |
| 1201 if (error_code) | 1204 if (error_code) |
| 1202 *error_code = base::File::FILE_ERROR_NOT_FOUND; | 1205 *error_code = base::File::FILE_ERROR_NOT_FOUND; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1215 if (error_code) | 1218 if (error_code) |
| 1216 *error_code = base::File::FILE_ERROR_FAILED; | 1219 *error_code = base::File::FILE_ERROR_FAILED; |
| 1217 return base::FilePath(); | 1220 return base::FilePath(); |
| 1218 } | 1221 } |
| 1219 exists_in_fs = false; | 1222 exists_in_fs = false; |
| 1220 } | 1223 } |
| 1221 | 1224 |
| 1222 if (!exists_in_fs) { | 1225 if (!exists_in_fs) { |
| 1223 if (!create || !base::CreateDirectory(path)) { | 1226 if (!create || !base::CreateDirectory(path)) { |
| 1224 if (error_code) | 1227 if (error_code) |
| 1225 *error_code = create ? | 1228 *error_code = create ? base::File::FILE_ERROR_FAILED |
| 1226 base::File::FILE_ERROR_FAILED : | 1229 : base::File::FILE_ERROR_NOT_FOUND; |
| 1227 base::File::FILE_ERROR_NOT_FOUND; | |
| 1228 return base::FilePath(); | 1230 return base::FilePath(); |
| 1229 } | 1231 } |
| 1230 } | 1232 } |
| 1231 | 1233 |
| 1232 if (error_code) | 1234 if (error_code) |
| 1233 *error_code = base::File::FILE_OK; | 1235 *error_code = base::File::FILE_OK; |
| 1234 | 1236 |
| 1235 return path; | 1237 return path; |
| 1236 } | 1238 } |
| 1237 | 1239 |
| 1238 void ObfuscatedFileUtil::InvalidateUsageCache( | 1240 void ObfuscatedFileUtil::InvalidateUsageCache( |
| 1239 FileSystemOperationContext* context, | 1241 FileSystemOperationContext* context, |
| 1240 const GURL& origin, | 1242 const GURL& origin, |
| 1241 FileSystemType type) { | 1243 FileSystemType type) { |
| 1242 if (sandbox_delegate_) | 1244 if (sandbox_delegate_) |
| 1243 sandbox_delegate_->InvalidateUsageCache(origin, type); | 1245 sandbox_delegate_->InvalidateUsageCache(origin, type); |
| 1244 } | 1246 } |
| 1245 | 1247 |
| 1246 void ObfuscatedFileUtil::MarkUsed() { | 1248 void ObfuscatedFileUtil::MarkUsed() { |
| 1247 if (!timer_) | 1249 if (!timer_) |
| 1248 timer_.reset(new TimedTaskHelper(file_task_runner_.get())); | 1250 timer_.reset(new TimedTaskHelper(file_task_runner_.get())); |
| 1249 | 1251 |
| 1250 if (timer_->IsRunning()) { | 1252 if (timer_->IsRunning()) { |
| 1251 timer_->Reset(); | 1253 timer_->Reset(); |
| 1252 } else { | 1254 } else { |
| 1253 timer_->Start(FROM_HERE, | 1255 timer_->Start( |
| 1254 base::TimeDelta::FromSeconds(db_flush_delay_seconds_), | 1256 FROM_HERE, |
| 1255 base::Bind(&ObfuscatedFileUtil::DropDatabases, | 1257 base::TimeDelta::FromSeconds(db_flush_delay_seconds_), |
| 1256 base::Unretained(this))); | 1258 base::Bind(&ObfuscatedFileUtil::DropDatabases, base::Unretained(this))); |
| 1257 } | 1259 } |
| 1258 } | 1260 } |
| 1259 | 1261 |
| 1260 void ObfuscatedFileUtil::DropDatabases() { | 1262 void ObfuscatedFileUtil::DropDatabases() { |
| 1261 origin_database_.reset(); | 1263 origin_database_.reset(); |
| 1262 STLDeleteContainerPairSecondPointers( | 1264 STLDeleteContainerPairSecondPointers(directories_.begin(), |
| 1263 directories_.begin(), directories_.end()); | 1265 directories_.end()); |
| 1264 directories_.clear(); | 1266 directories_.clear(); |
| 1265 timer_.reset(); | 1267 timer_.reset(); |
| 1266 } | 1268 } |
| 1267 | 1269 |
| 1268 bool ObfuscatedFileUtil::InitOriginDatabase(const GURL& origin_hint, | 1270 bool ObfuscatedFileUtil::InitOriginDatabase(const GURL& origin_hint, |
| 1269 bool create) { | 1271 bool create) { |
| 1270 if (origin_database_) | 1272 if (origin_database_) |
| 1271 return true; | 1273 return true; |
| 1272 | 1274 |
| 1273 if (!create && !base::DirectoryExists(file_system_directory_)) | 1275 if (!create && !base::DirectoryExists(file_system_directory_)) |
| 1274 return false; | 1276 return false; |
| 1275 if (!base::CreateDirectory(file_system_directory_)) { | 1277 if (!base::CreateDirectory(file_system_directory_)) { |
| 1276 LOG(WARNING) << "Failed to create FileSystem directory: " << | 1278 LOG(WARNING) << "Failed to create FileSystem directory: " |
| 1277 file_system_directory_.value(); | 1279 << file_system_directory_.value(); |
| 1278 return false; | 1280 return false; |
| 1279 } | 1281 } |
| 1280 | 1282 |
| 1281 SandboxPrioritizedOriginDatabase* prioritized_origin_database = | 1283 SandboxPrioritizedOriginDatabase* prioritized_origin_database = |
| 1282 new SandboxPrioritizedOriginDatabase(file_system_directory_, | 1284 new SandboxPrioritizedOriginDatabase(file_system_directory_, |
| 1283 env_override_); | 1285 env_override_); |
| 1284 origin_database_.reset(prioritized_origin_database); | 1286 origin_database_.reset(prioritized_origin_database); |
| 1285 | 1287 |
| 1286 if (origin_hint.is_empty() || !HasIsolatedStorage(origin_hint)) | 1288 if (origin_hint.is_empty() || !HasIsolatedStorage(origin_hint)) |
| 1287 return true; | 1289 return true; |
| 1288 | 1290 |
| 1289 const std::string isolated_origin_string = | 1291 const std::string isolated_origin_string = |
| 1290 webkit_database::GetIdentifierFromOrigin(origin_hint); | 1292 webkit_database::GetIdentifierFromOrigin(origin_hint); |
| 1291 | 1293 |
| 1292 // TODO(kinuko): Deprecate this after a few release cycles, e.g. around M33. | 1294 // TODO(kinuko): Deprecate this after a few release cycles, e.g. around M33. |
| 1293 base::FilePath isolated_origin_dir = file_system_directory_.Append( | 1295 base::FilePath isolated_origin_dir = file_system_directory_.Append( |
| 1294 SandboxIsolatedOriginDatabase::kObsoleteOriginDirectory); | 1296 SandboxIsolatedOriginDatabase::kObsoleteOriginDirectory); |
| 1295 if (base::DirectoryExists(isolated_origin_dir) && | 1297 if (base::DirectoryExists(isolated_origin_dir) && |
| 1296 prioritized_origin_database->GetSandboxOriginDatabase()) { | 1298 prioritized_origin_database->GetSandboxOriginDatabase()) { |
| 1297 SandboxIsolatedOriginDatabase::MigrateBackFromObsoleteOriginDatabase( | 1299 SandboxIsolatedOriginDatabase::MigrateBackFromObsoleteOriginDatabase( |
| 1298 isolated_origin_string, | 1300 isolated_origin_string, |
| 1299 file_system_directory_, | 1301 file_system_directory_, |
| 1300 prioritized_origin_database->GetSandboxOriginDatabase()); | 1302 prioritized_origin_database->GetSandboxOriginDatabase()); |
| 1301 } | 1303 } |
| 1302 | 1304 |
| 1303 prioritized_origin_database->InitializePrimaryOrigin( | 1305 prioritized_origin_database->InitializePrimaryOrigin(isolated_origin_string); |
| 1304 isolated_origin_string); | |
| 1305 | 1306 |
| 1306 return true; | 1307 return true; |
| 1307 } | 1308 } |
| 1308 | 1309 |
| 1309 base::File::Error ObfuscatedFileUtil::GenerateNewLocalPath( | 1310 base::File::Error ObfuscatedFileUtil::GenerateNewLocalPath( |
| 1310 SandboxDirectoryDatabase* db, | 1311 SandboxDirectoryDatabase* db, |
| 1311 FileSystemOperationContext* context, | 1312 FileSystemOperationContext* context, |
| 1312 const FileSystemURL& url, | 1313 const FileSystemURL& url, |
| 1313 base::FilePath* root, | 1314 base::FilePath* root, |
| 1314 base::FilePath* local_path) { | 1315 base::FilePath* local_path) { |
| 1315 DCHECK(local_path); | 1316 DCHECK(local_path); |
| 1316 int64 number; | 1317 int64 number; |
| 1317 if (!db || !db->GetNextInteger(&number)) | 1318 if (!db || !db->GetNextInteger(&number)) |
| 1318 return base::File::FILE_ERROR_FAILED; | 1319 return base::File::FILE_ERROR_FAILED; |
| 1319 | 1320 |
| 1320 base::File::Error error = base::File::FILE_OK; | 1321 base::File::Error error = base::File::FILE_OK; |
| 1321 *root = GetDirectoryForURL(url, false, &error); | 1322 *root = GetDirectoryForURL(url, false, &error); |
| 1322 if (error != base::File::FILE_OK) | 1323 if (error != base::File::FILE_OK) |
| 1323 return error; | 1324 return error; |
| 1324 | 1325 |
| 1325 // We use the third- and fourth-to-last digits as the directory. | 1326 // We use the third- and fourth-to-last digits as the directory. |
| 1326 int64 directory_number = number % 10000 / 100; | 1327 int64 directory_number = number % 10000 / 100; |
| 1327 base::FilePath new_local_path = root->AppendASCII( | 1328 base::FilePath new_local_path = |
| 1328 base::StringPrintf("%02" PRId64, directory_number)); | 1329 root->AppendASCII(base::StringPrintf("%02" PRId64, directory_number)); |
| 1329 | 1330 |
| 1330 error = NativeFileUtil::CreateDirectory( | 1331 error = NativeFileUtil::CreateDirectory( |
| 1331 new_local_path, false /* exclusive */, false /* recursive */); | 1332 new_local_path, false /* exclusive */, false /* recursive */); |
| 1332 if (error != base::File::FILE_OK) | 1333 if (error != base::File::FILE_OK) |
| 1333 return error; | 1334 return error; |
| 1334 | 1335 |
| 1335 *local_path = | 1336 *local_path = |
| 1336 new_local_path.AppendASCII(base::StringPrintf("%08" PRId64, number)); | 1337 new_local_path.AppendASCII(base::StringPrintf("%08" PRId64, number)); |
| 1337 return base::File::FILE_OK; | 1338 return base::File::FILE_OK; |
| 1338 } | 1339 } |
| 1339 | 1340 |
| 1340 base::File ObfuscatedFileUtil::CreateOrOpenInternal( | 1341 base::File ObfuscatedFileUtil::CreateOrOpenInternal( |
| 1341 FileSystemOperationContext* context, | 1342 FileSystemOperationContext* context, |
| 1342 const FileSystemURL& url, int file_flags) { | 1343 const FileSystemURL& url, |
| 1343 DCHECK(!(file_flags & (base::File::FLAG_DELETE_ON_CLOSE | | 1344 int file_flags) { |
| 1344 base::File::FLAG_HIDDEN | base::File::FLAG_EXCLUSIVE_READ | | 1345 DCHECK( |
| 1345 base::File::FLAG_EXCLUSIVE_WRITE))); | 1346 !(file_flags & |
| 1347 (base::File::FLAG_DELETE_ON_CLOSE | base::File::FLAG_HIDDEN | |
| 1348 base::File::FLAG_EXCLUSIVE_READ | base::File::FLAG_EXCLUSIVE_WRITE))); |
| 1346 SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, true); | 1349 SandboxDirectoryDatabase* db = GetDirectoryDatabase(url, true); |
| 1347 if (!db) | 1350 if (!db) |
| 1348 return base::File(base::File::FILE_ERROR_FAILED); | 1351 return base::File(base::File::FILE_ERROR_FAILED); |
| 1349 FileId file_id; | 1352 FileId file_id; |
| 1350 if (!db->GetFileWithPath(url.path(), &file_id)) { | 1353 if (!db->GetFileWithPath(url.path(), &file_id)) { |
| 1351 // The file doesn't exist. | 1354 // The file doesn't exist. |
| 1352 if (!(file_flags & (base::File::FLAG_CREATE | | 1355 if (!(file_flags & |
| 1353 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_OPEN_ALWAYS))) { | 1356 (base::File::FLAG_CREATE | base::File::FLAG_CREATE_ALWAYS | |
| 1357 base::File::FLAG_OPEN_ALWAYS))) { |
| 1354 return base::File(base::File::FILE_ERROR_NOT_FOUND); | 1358 return base::File(base::File::FILE_ERROR_NOT_FOUND); |
| 1355 } | 1359 } |
| 1356 FileId parent_id; | 1360 FileId parent_id; |
| 1357 if (!db->GetFileWithPath(VirtualPath::DirName(url.path()), &parent_id)) | 1361 if (!db->GetFileWithPath(VirtualPath::DirName(url.path()), &parent_id)) |
| 1358 return base::File(base::File::FILE_ERROR_NOT_FOUND); | 1362 return base::File(base::File::FILE_ERROR_NOT_FOUND); |
| 1359 FileInfo file_info; | 1363 FileInfo file_info; |
| 1360 InitFileInfo(&file_info, parent_id, | 1364 InitFileInfo( |
| 1361 VirtualPath::BaseName(url.path()).value()); | 1365 &file_info, parent_id, VirtualPath::BaseName(url.path()).value()); |
| 1362 | 1366 |
| 1363 int64 growth = UsageForPath(file_info.name.size()); | 1367 int64 growth = UsageForPath(file_info.name.size()); |
| 1364 if (!AllocateQuota(context, growth)) | 1368 if (!AllocateQuota(context, growth)) |
| 1365 return base::File(base::File::FILE_ERROR_NO_SPACE); | 1369 return base::File(base::File::FILE_ERROR_NO_SPACE); |
| 1366 base::File file = CreateAndOpenFile(context, url, &file_info, file_flags); | 1370 base::File file = CreateAndOpenFile(context, url, &file_info, file_flags); |
| 1367 if (file.IsValid()) { | 1371 if (file.IsValid()) { |
| 1368 UpdateUsage(context, url, growth); | 1372 UpdateUsage(context, url, growth); |
| 1369 context->change_observers()->Notify( | 1373 context->change_observers()->Notify(&FileChangeObserver::OnCreateFile, |
| 1370 &FileChangeObserver::OnCreateFile, MakeTuple(url)); | 1374 MakeTuple(url)); |
| 1371 } | 1375 } |
| 1372 return file.Pass(); | 1376 return file.Pass(); |
| 1373 } | 1377 } |
| 1374 | 1378 |
| 1375 if (file_flags & base::File::FLAG_CREATE) | 1379 if (file_flags & base::File::FLAG_CREATE) |
| 1376 return base::File(base::File::FILE_ERROR_EXISTS); | 1380 return base::File(base::File::FILE_ERROR_EXISTS); |
| 1377 | 1381 |
| 1378 base::File::Info platform_file_info; | 1382 base::File::Info platform_file_info; |
| 1379 base::FilePath local_path; | 1383 base::FilePath local_path; |
| 1380 FileInfo file_info; | 1384 FileInfo file_info; |
| 1381 base::File::Error error = GetFileInfoInternal( | 1385 base::File::Error error = GetFileInfoInternal( |
| 1382 db, context, url, file_id, &file_info, &platform_file_info, &local_path); | 1386 db, context, url, file_id, &file_info, &platform_file_info, &local_path); |
| 1383 if (error != base::File::FILE_OK) | 1387 if (error != base::File::FILE_OK) |
| 1384 return base::File(error); | 1388 return base::File(error); |
| 1385 if (file_info.is_directory()) | 1389 if (file_info.is_directory()) |
| 1386 return base::File(base::File::FILE_ERROR_NOT_A_FILE); | 1390 return base::File(base::File::FILE_ERROR_NOT_A_FILE); |
| 1387 | 1391 |
| 1388 int64 delta = 0; | 1392 int64 delta = 0; |
| 1389 if (file_flags & (base::File::FLAG_CREATE_ALWAYS | | 1393 if (file_flags & |
| 1390 base::File::FLAG_OPEN_TRUNCATED)) { | 1394 (base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_OPEN_TRUNCATED)) { |
| 1391 // The file exists and we're truncating. | 1395 // The file exists and we're truncating. |
| 1392 delta = -platform_file_info.size; | 1396 delta = -platform_file_info.size; |
| 1393 AllocateQuota(context, delta); | 1397 AllocateQuota(context, delta); |
| 1394 } | 1398 } |
| 1395 | 1399 |
| 1396 base::File file = NativeFileUtil::CreateOrOpen(local_path, file_flags); | 1400 base::File file = NativeFileUtil::CreateOrOpen(local_path, file_flags); |
| 1397 if (!file.IsValid()) { | 1401 if (!file.IsValid()) { |
| 1398 error = file.error_details(); | 1402 error = file.error_details(); |
| 1399 if (error == base::File::FILE_ERROR_NOT_FOUND) { | 1403 if (error == base::File::FILE_ERROR_NOT_FOUND) { |
| 1400 // TODO(tzik): Also invalidate on-memory usage cache in UsageTracker. | 1404 // TODO(tzik): Also invalidate on-memory usage cache in UsageTracker. |
| 1401 // TODO(tzik): Delete database entry after ensuring the file lost. | 1405 // TODO(tzik): Delete database entry after ensuring the file lost. |
| 1402 InvalidateUsageCache(context, url.origin(), url.type()); | 1406 InvalidateUsageCache(context, url.origin(), url.type()); |
| 1403 LOG(WARNING) << "Lost a backing file."; | 1407 LOG(WARNING) << "Lost a backing file."; |
| 1404 return base::File(base::File::FILE_ERROR_FAILED); | 1408 return base::File(base::File::FILE_ERROR_FAILED); |
| 1405 } | 1409 } |
| 1406 return file.Pass(); | 1410 return file.Pass(); |
| 1407 } | 1411 } |
| 1408 | 1412 |
| 1409 // If truncating we need to update the usage. | 1413 // If truncating we need to update the usage. |
| 1410 if (delta) { | 1414 if (delta) { |
| 1411 UpdateUsage(context, url, delta); | 1415 UpdateUsage(context, url, delta); |
| 1412 context->change_observers()->Notify( | 1416 context->change_observers()->Notify(&FileChangeObserver::OnModifyFile, |
| 1413 &FileChangeObserver::OnModifyFile, MakeTuple(url)); | 1417 MakeTuple(url)); |
| 1414 } | 1418 } |
| 1415 return file.Pass(); | 1419 return file.Pass(); |
| 1416 } | 1420 } |
| 1417 | 1421 |
| 1418 bool ObfuscatedFileUtil::HasIsolatedStorage(const GURL& origin) { | 1422 bool ObfuscatedFileUtil::HasIsolatedStorage(const GURL& origin) { |
| 1419 return special_storage_policy_.get() && | 1423 return special_storage_policy_.get() && |
| 1420 special_storage_policy_->HasIsolatedStorage(origin); | 1424 special_storage_policy_->HasIsolatedStorage(origin); |
| 1421 } | 1425 } |
| 1422 | 1426 |
| 1423 } // namespace fileapi | 1427 } // namespace storage |
| OLD | NEW |