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 "storage/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/files/file_util.h" | 11 #include "base/files/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/string_util.h" |
18 #include "base/strings/stringprintf.h" | 19 #include "base/strings/stringprintf.h" |
19 #include "base/strings/sys_string_conversions.h" | 20 #include "base/strings/sys_string_conversions.h" |
20 #include "base/strings/utf_string_conversions.h" | 21 #include "base/strings/utf_string_conversions.h" |
21 #include "base/time/time.h" | 22 #include "base/time/time.h" |
22 #include "storage/browser/fileapi/file_observers.h" | 23 #include "storage/browser/fileapi/file_observers.h" |
23 #include "storage/browser/fileapi/file_system_context.h" | 24 #include "storage/browser/fileapi/file_system_context.h" |
24 #include "storage/browser/fileapi/file_system_operation_context.h" | 25 #include "storage/browser/fileapi/file_system_operation_context.h" |
25 #include "storage/browser/fileapi/file_system_url.h" | 26 #include "storage/browser/fileapi/file_system_url.h" |
26 #include "storage/browser/fileapi/native_file_util.h" | 27 #include "storage/browser/fileapi/native_file_util.h" |
27 #include "storage/browser/fileapi/sandbox_file_system_backend.h" | 28 #include "storage/browser/fileapi/sandbox_file_system_backend.h" |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 } | 61 } |
61 | 62 |
62 // Costs computed as per crbug.com/86114, based on the LevelDB implementation of | 63 // 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 | 64 // 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 | 65 // 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 | 66 // 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. | 67 // 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. | 68 const int64 kPathCreationQuotaCost = 146; // Bytes per inode, basically. |
68 const int64 kPathByteQuotaCost = 2; // Bytes per byte of path length in UTF-8. | 69 const int64 kPathByteQuotaCost = 2; // Bytes per byte of path length in UTF-8. |
69 | 70 |
| 71 const char kDirectoryDatabaseKeySeparator = ' '; |
| 72 |
70 int64 UsageForPath(size_t length) { | 73 int64 UsageForPath(size_t length) { |
71 return kPathCreationQuotaCost + | 74 return kPathCreationQuotaCost + |
72 static_cast<int64>(length) * kPathByteQuotaCost; | 75 static_cast<int64>(length) * kPathByteQuotaCost; |
73 } | 76 } |
74 | 77 |
75 bool AllocateQuota(FileSystemOperationContext* context, int64 growth) { | 78 bool AllocateQuota(FileSystemOperationContext* context, int64 growth) { |
76 if (context->allowed_bytes_growth() == storage::QuotaManager::kNoLimit) | 79 if (context->allowed_bytes_growth() == storage::QuotaManager::kNoLimit) |
77 return true; | 80 return true; |
78 | 81 |
79 int64 new_quota = context->allowed_bytes_growth() - growth; | 82 int64 new_quota = context->allowed_bytes_growth() - growth; |
(...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
848 } | 851 } |
849 | 852 |
850 if (error_code) | 853 if (error_code) |
851 *error_code = error; | 854 *error_code = error; |
852 return path; | 855 return path; |
853 } | 856 } |
854 | 857 |
855 bool ObfuscatedFileUtil::DeleteDirectoryForOriginAndType( | 858 bool ObfuscatedFileUtil::DeleteDirectoryForOriginAndType( |
856 const GURL& origin, | 859 const GURL& origin, |
857 const std::string& type_string) { | 860 const std::string& type_string) { |
858 base::File::Error error = base::File::FILE_OK; | 861 DestroyDirectoryDatabase(origin, type_string); |
859 base::FilePath origin_type_path = GetDirectoryForOriginAndType( | 862 |
860 origin, type_string, false, &error); | 863 const base::FilePath origin_path = GetDirectoryForOrigin(origin, false, NULL); |
861 if (origin_type_path.empty()) | 864 if (!type_string.empty()) { |
862 return true; | 865 // Delete the filesystem type directory. |
863 if (error != base::File::FILE_ERROR_NOT_FOUND) { | 866 base::File::Error error = base::File::FILE_OK; |
864 // TODO(dmikurube): Consider the return value of DestroyDirectoryDatabase. | 867 const base::FilePath origin_type_path = |
865 // We ignore its error now since 1) it doesn't matter the final result, and | 868 GetDirectoryForOriginAndType(origin, type_string, false, &error); |
866 // 2) it always returns false in Windows because of LevelDB's | 869 if (error == base::File::FILE_ERROR_FAILED) |
867 // implementation. | |
868 // Information about failure would be useful for debugging. | |
869 if (!type_string.empty()) | |
870 DestroyDirectoryDatabase(origin, type_string); | |
871 if (!base::DeleteFile(origin_type_path, true /* recursive */)) | |
872 return false; | 870 return false; |
873 } | 871 if (error == base::File::FILE_OK && |
| 872 !origin_type_path.empty() && |
| 873 !base::DeleteFile(origin_type_path, true /* recursive */)) { |
| 874 return false; |
| 875 } |
874 | 876 |
875 base::FilePath origin_path = VirtualPath::DirName(origin_type_path); | |
876 DCHECK_EQ(origin_path.value(), | |
877 GetDirectoryForOrigin(origin, false, NULL).value()); | |
878 | |
879 if (!type_string.empty()) { | |
880 // At this point we are sure we had successfully deleted the origin/type | 877 // At this point we are sure we had successfully deleted the origin/type |
881 // directory (i.e. we're ready to just return true). | 878 // directory (i.e. we're ready to just return true). |
882 // See if we have other directories in this origin directory. | 879 // See if we have other directories in this origin directory. |
883 for (std::set<std::string>::iterator iter = known_type_strings_.begin(); | 880 for (std::set<std::string>::iterator iter = known_type_strings_.begin(); |
884 iter != known_type_strings_.end(); | 881 iter != known_type_strings_.end(); |
885 ++iter) { | 882 ++iter) { |
886 if (*iter == type_string) | 883 if (*iter == type_string) |
887 continue; | 884 continue; |
888 if (base::DirectoryExists(origin_path.AppendASCII(*iter))) { | 885 if (base::DirectoryExists(origin_path.AppendASCII(*iter))) { |
889 // Other type's directory exists; just return true here. | 886 // Other type's directory exists; just return true here. |
890 return true; | 887 return true; |
891 } | 888 } |
892 } | 889 } |
893 } | 890 } |
894 | 891 |
895 // No other directories seem exist. Try deleting the entire origin directory. | 892 // No other directories seem exist. Try deleting the entire origin directory. |
896 InitOriginDatabase(origin, false); | 893 InitOriginDatabase(origin, false); |
897 if (origin_database_) { | 894 if (origin_database_) { |
898 origin_database_->RemovePathForOrigin( | 895 origin_database_->RemovePathForOrigin( |
899 storage::GetIdentifierFromOrigin(origin)); | 896 storage::GetIdentifierFromOrigin(origin)); |
900 } | 897 } |
901 if (!base::DeleteFile(origin_path, true /* recursive */)) | 898 return base::DeleteFile(origin_path, true /* recursive */); |
902 return false; | |
903 | |
904 return true; | |
905 } | 899 } |
906 | 900 |
907 ObfuscatedFileUtil::AbstractOriginEnumerator* | 901 ObfuscatedFileUtil::AbstractOriginEnumerator* |
908 ObfuscatedFileUtil::CreateOriginEnumerator() { | 902 ObfuscatedFileUtil::CreateOriginEnumerator() { |
909 std::vector<SandboxOriginDatabase::OriginRecord> origins; | 903 std::vector<SandboxOriginDatabase::OriginRecord> origins; |
910 | 904 |
911 InitOriginDatabase(GURL(), false); | 905 InitOriginDatabase(GURL(), false); |
912 return new ObfuscatedOriginEnumerator( | 906 return new ObfuscatedOriginEnumerator( |
913 origin_database_.get(), file_system_directory_); | 907 origin_database_.get(), file_system_directory_); |
914 } | 908 } |
915 | 909 |
916 bool ObfuscatedFileUtil::DestroyDirectoryDatabase( | 910 void ObfuscatedFileUtil::DestroyDirectoryDatabase( |
917 const GURL& origin, | 911 const GURL& origin, |
918 const std::string& type_string) { | 912 const std::string& type_string) { |
919 std::string key = GetDirectoryDatabaseKey(origin, type_string); | 913 // If |type_string| is empty, delete all filesystem types under |origin|. |
920 if (key.empty()) | 914 const std::string key_prefix = GetDirectoryDatabaseKey(origin, type_string); |
921 return true; | 915 for (DirectoryMap::iterator iter = directories_.lower_bound(key_prefix); |
922 DirectoryMap::iterator iter = directories_.find(key); | 916 iter != directories_.end();) { |
923 if (iter == directories_.end()) | 917 if (!StartsWithASCII(iter->first, key_prefix, true)) |
924 return true; | 918 break; |
925 scoped_ptr<SandboxDirectoryDatabase> database(iter->second); | 919 DCHECK(type_string.empty() || iter->first == key_prefix); |
926 directories_.erase(iter); | 920 scoped_ptr<SandboxDirectoryDatabase> database(iter->second); |
927 return database->DestroyDatabase(); | 921 directories_.erase(iter++); |
| 922 |
| 923 // Continue to destroy databases even if it failed because it doesn't affect |
| 924 // the final result. |
| 925 database->DestroyDatabase(); |
| 926 } |
928 } | 927 } |
929 | 928 |
930 // static | 929 // static |
931 int64 ObfuscatedFileUtil::ComputeFilePathCost(const base::FilePath& path) { | 930 int64 ObfuscatedFileUtil::ComputeFilePathCost(const base::FilePath& path) { |
932 return UsageForPath(VirtualPath::BaseName(path).value().size()); | 931 return UsageForPath(VirtualPath::BaseName(path).value().size()); |
933 } | 932 } |
934 | 933 |
935 void ObfuscatedFileUtil::MaybePrepopulateDatabase( | 934 void ObfuscatedFileUtil::MaybePrepopulateDatabase( |
936 const std::vector<std::string>& type_strings_to_prepopulate) { | 935 const std::vector<std::string>& type_strings_to_prepopulate) { |
937 SandboxPrioritizedOriginDatabase database(file_system_directory_, | 936 SandboxPrioritizedOriginDatabase database(file_system_directory_, |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1129 const FileSystemURL& url, const base::FilePath& data_path) { | 1128 const FileSystemURL& url, const base::FilePath& data_path) { |
1130 base::File::Error error = base::File::FILE_OK; | 1129 base::File::Error error = base::File::FILE_OK; |
1131 base::FilePath root = GetDirectoryForURL(url, false, &error); | 1130 base::FilePath root = GetDirectoryForURL(url, false, &error); |
1132 if (error != base::File::FILE_OK) | 1131 if (error != base::File::FILE_OK) |
1133 return base::FilePath(); | 1132 return base::FilePath(); |
1134 return root.Append(data_path); | 1133 return root.Append(data_path); |
1135 } | 1134 } |
1136 | 1135 |
1137 std::string ObfuscatedFileUtil::GetDirectoryDatabaseKey( | 1136 std::string ObfuscatedFileUtil::GetDirectoryDatabaseKey( |
1138 const GURL& origin, const std::string& type_string) { | 1137 const GURL& origin, const std::string& type_string) { |
1139 if (type_string.empty()) { | |
1140 LOG(WARNING) << "Unknown filesystem type requested:" << type_string; | |
1141 return std::string(); | |
1142 } | |
1143 // For isolated origin we just use a type string as a key. | 1138 // For isolated origin we just use a type string as a key. |
1144 return storage::GetIdentifierFromOrigin(origin) + type_string; | 1139 return storage::GetIdentifierFromOrigin(origin) + |
| 1140 kDirectoryDatabaseKeySeparator + type_string; |
1145 } | 1141 } |
1146 | 1142 |
1147 // TODO(ericu): How to do the whole validation-without-creation thing? | 1143 // TODO(ericu): How to do the whole validation-without-creation thing? |
1148 // We may not have quota even to create the database. | 1144 // We may not have quota even to create the database. |
1149 // Ah, in that case don't even get here? | 1145 // Ah, in that case don't even get here? |
1150 // Still doesn't answer the quota issue, though. | 1146 // Still doesn't answer the quota issue, though. |
1151 SandboxDirectoryDatabase* ObfuscatedFileUtil::GetDirectoryDatabase( | 1147 SandboxDirectoryDatabase* ObfuscatedFileUtil::GetDirectoryDatabase( |
1152 const FileSystemURL& url, bool create) { | 1148 const FileSystemURL& url, bool create) { |
1153 std::string key = GetDirectoryDatabaseKey( | 1149 std::string key = GetDirectoryDatabaseKey( |
1154 url.origin(), CallGetTypeStringForURL(url)); | 1150 url.origin(), CallGetTypeStringForURL(url)); |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1406 } | 1402 } |
1407 return file.Pass(); | 1403 return file.Pass(); |
1408 } | 1404 } |
1409 | 1405 |
1410 bool ObfuscatedFileUtil::HasIsolatedStorage(const GURL& origin) { | 1406 bool ObfuscatedFileUtil::HasIsolatedStorage(const GURL& origin) { |
1411 return special_storage_policy_.get() && | 1407 return special_storage_policy_.get() && |
1412 special_storage_policy_->HasIsolatedStorage(origin); | 1408 special_storage_policy_->HasIsolatedStorage(origin); |
1413 } | 1409 } |
1414 | 1410 |
1415 } // namespace storage | 1411 } // namespace storage |
OLD | NEW |