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 |