| 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/fileapi/sandbox_mount_point_provider.h" | 5 #include "webkit/fileapi/sandbox_mount_point_provider.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| 11 #include "base/message_loop.h" | 11 #include "base/message_loop.h" |
| 12 #include "base/message_loop_proxy.h" | 12 #include "base/message_loop_proxy.h" |
| 13 #include "base/rand_util.h" | 13 #include "base/rand_util.h" |
| 14 #include "base/string_util.h" | 14 #include "base/string_util.h" |
| 15 #include "base/stringprintf.h" | 15 #include "base/stringprintf.h" |
| 16 #include "base/metrics/histogram.h" | 16 #include "base/metrics/histogram.h" |
| 17 #include "googleurl/src/gurl.h" | 17 #include "googleurl/src/gurl.h" |
| 18 #include "net/base/net_util.h" | 18 #include "net/base/net_util.h" |
| 19 #include "webkit/fileapi/file_system_operation.h" |
| 19 #include "webkit/fileapi/file_system_operation_context.h" | 20 #include "webkit/fileapi/file_system_operation_context.h" |
| 20 #include "webkit/fileapi/file_system_options.h" | 21 #include "webkit/fileapi/file_system_options.h" |
| 21 #include "webkit/fileapi/file_system_types.h" | 22 #include "webkit/fileapi/file_system_types.h" |
| 22 #include "webkit/fileapi/file_system_usage_cache.h" | 23 #include "webkit/fileapi/file_system_usage_cache.h" |
| 23 #include "webkit/fileapi/file_system_util.h" | 24 #include "webkit/fileapi/file_system_util.h" |
| 24 #include "webkit/fileapi/obfuscated_file_util.h" | 25 #include "webkit/fileapi/obfuscated_file_util.h" |
| 25 #include "webkit/fileapi/quota_file_util.h" | 26 #include "webkit/fileapi/quota_file_util.h" |
| 26 #include "webkit/glue/webkit_glue.h" | 27 #include "webkit/glue/webkit_glue.h" |
| 27 #include "webkit/quota/quota_manager.h" | 28 #include "webkit/quota/quota_manager.h" |
| 28 | 29 |
| 29 using quota::QuotaManagerProxy; | 30 using quota::QuotaManagerProxy; |
| 30 | 31 |
| 32 namespace fileapi { |
| 33 |
| 31 namespace { | 34 namespace { |
| 32 | 35 |
| 33 const char kChromeScheme[] = "chrome"; | 36 const char kChromeScheme[] = "chrome"; |
| 34 const char kExtensionScheme[] = "chrome-extension"; | 37 const char kExtensionScheme[] = "chrome-extension"; |
| 35 | 38 |
| 36 const FilePath::CharType kOldFileSystemUniqueNamePrefix[] = | 39 const FilePath::CharType kOldFileSystemUniqueNamePrefix[] = |
| 37 FILE_PATH_LITERAL("chrome-"); | 40 FILE_PATH_LITERAL("chrome-"); |
| 38 const size_t kOldFileSystemUniqueLength = 16; | 41 const size_t kOldFileSystemUniqueLength = 16; |
| 39 const size_t kOldFileSystemUniqueDirectoryNameLength = | 42 const size_t kOldFileSystemUniqueDirectoryNameLength = |
| 40 kOldFileSystemUniqueLength + arraysize(kOldFileSystemUniqueNamePrefix) - 1; | 43 kOldFileSystemUniqueLength + arraysize(kOldFileSystemUniqueNamePrefix) - 1; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 } | 92 } |
| 90 found = true; | 93 found = true; |
| 91 *unique = current; | 94 *unique = current; |
| 92 } | 95 } |
| 93 if (unique->empty()) | 96 if (unique->empty()) |
| 94 return base::PLATFORM_FILE_ERROR_NOT_FOUND; | 97 return base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| 95 return base::PLATFORM_FILE_OK; | 98 return base::PLATFORM_FILE_OK; |
| 96 } | 99 } |
| 97 | 100 |
| 98 class ObfuscatedOriginEnumerator | 101 class ObfuscatedOriginEnumerator |
| 99 : public fileapi::SandboxMountPointProvider::OriginEnumerator { | 102 : public SandboxMountPointProvider::OriginEnumerator { |
| 100 public: | 103 public: |
| 101 explicit ObfuscatedOriginEnumerator( | 104 explicit ObfuscatedOriginEnumerator(ObfuscatedFileUtil* file_util) { |
| 102 fileapi::ObfuscatedFileUtil* file_util) { | |
| 103 enum_.reset(file_util->CreateOriginEnumerator()); | 105 enum_.reset(file_util->CreateOriginEnumerator()); |
| 104 } | 106 } |
| 105 virtual ~ObfuscatedOriginEnumerator() {} | 107 virtual ~ObfuscatedOriginEnumerator() {} |
| 106 | 108 |
| 107 virtual GURL Next() OVERRIDE { | 109 virtual GURL Next() OVERRIDE { |
| 108 return enum_->Next(); | 110 return enum_->Next(); |
| 109 } | 111 } |
| 110 | 112 |
| 111 virtual bool HasFileSystemType(fileapi::FileSystemType type) const OVERRIDE { | 113 virtual bool HasFileSystemType(fileapi::FileSystemType type) const OVERRIDE { |
| 112 return enum_->HasFileSystemType(type); | 114 return enum_->HasFileSystemType(type); |
| 113 } | 115 } |
| 114 | 116 |
| 115 private: | 117 private: |
| 116 scoped_ptr<fileapi::ObfuscatedFileUtil::AbstractOriginEnumerator> enum_; | 118 scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enum_; |
| 117 }; | 119 }; |
| 118 | 120 |
| 119 class OldSandboxOriginEnumerator | 121 class OldSandboxOriginEnumerator |
| 120 : public fileapi::SandboxMountPointProvider::OriginEnumerator { | 122 : public SandboxMountPointProvider::OriginEnumerator { |
| 121 public: | 123 public: |
| 122 explicit OldSandboxOriginEnumerator(const FilePath& base_path) | 124 explicit OldSandboxOriginEnumerator(const FilePath& base_path) |
| 123 : enumerator_(base_path, false /* recursive */, | 125 : enumerator_(base_path, false /* recursive */, |
| 124 file_util::FileEnumerator::DIRECTORIES) {} | 126 file_util::FileEnumerator::DIRECTORIES) {} |
| 125 virtual ~OldSandboxOriginEnumerator() {} | 127 virtual ~OldSandboxOriginEnumerator() {} |
| 126 | 128 |
| 127 virtual GURL Next() OVERRIDE { | 129 virtual GURL Next() OVERRIDE { |
| 128 current_ = enumerator_.Next(); | 130 current_ = enumerator_.Next(); |
| 129 if (current_.empty()) | 131 if (current_.empty()) |
| 130 return GURL(); | 132 return GURL(); |
| 131 return fileapi::GetOriginURLFromIdentifier( | 133 return GetOriginURLFromIdentifier(current_.BaseName().MaybeAsASCII()); |
| 132 current_.BaseName().MaybeAsASCII()); | |
| 133 } | 134 } |
| 134 | 135 |
| 135 virtual bool HasFileSystemType(fileapi::FileSystemType type) const OVERRIDE { | 136 virtual bool HasFileSystemType(fileapi::FileSystemType type) const OVERRIDE { |
| 136 if (current_.empty()) | 137 if (current_.empty()) |
| 137 return false; | 138 return false; |
| 138 std::string directory = GetFileSystemTypeString(type); | 139 std::string directory = GetFileSystemTypeString(type); |
| 139 DCHECK(!directory.empty()); | 140 DCHECK(!directory.empty()); |
| 140 return file_util::DirectoryExists(current_.AppendASCII(directory)); | 141 return file_util::DirectoryExists(current_.AppendASCII(directory)); |
| 141 } | 142 } |
| 142 | 143 |
| 143 private: | 144 private: |
| 144 file_util::FileEnumerator enumerator_; | 145 file_util::FileEnumerator enumerator_; |
| 145 FilePath current_; | 146 FilePath current_; |
| 146 }; | 147 }; |
| 147 | 148 |
| 148 FilePath OldGetBaseDirectoryForOrigin( | 149 FilePath OldGetBaseDirectoryForOrigin( |
| 149 const FilePath& old_base_path, | 150 const FilePath& old_base_path, |
| 150 const GURL& origin_url) { | 151 const GURL& origin_url) { |
| 151 std::string id = fileapi::GetOriginIdentifierFromURL(origin_url); | 152 std::string id = GetOriginIdentifierFromURL(origin_url); |
| 152 if (!id.empty()) | 153 if (!id.empty()) |
| 153 return old_base_path.AppendASCII(id); | 154 return old_base_path.AppendASCII(id); |
| 154 return FilePath(); | 155 return FilePath(); |
| 155 } | 156 } |
| 156 | 157 |
| 157 FilePath OldGetBaseDirectoryForOriginAndType( | 158 FilePath OldGetBaseDirectoryForOriginAndType( |
| 158 const FilePath& old_base_path, | 159 const FilePath& old_base_path, |
| 159 const GURL& origin_url, fileapi::FileSystemType type) { | 160 const GURL& origin_url, fileapi::FileSystemType type) { |
| 160 std::string type_string = GetFileSystemTypeString(type); | 161 std::string type_string = GetFileSystemTypeString(type); |
| 161 if (type_string.empty()) { | 162 if (type_string.empty()) { |
| 162 NOTREACHED(); | 163 NOTREACHED(); |
| 163 return FilePath(); | 164 return FilePath(); |
| 164 } | 165 } |
| 165 FilePath base_path = OldGetBaseDirectoryForOrigin( | 166 FilePath base_path = OldGetBaseDirectoryForOrigin( |
| 166 old_base_path, origin_url); | 167 old_base_path, origin_url); |
| 167 if (base_path.empty()) { | 168 if (base_path.empty()) { |
| 168 NOTREACHED(); | 169 NOTREACHED(); |
| 169 return FilePath(); | 170 return FilePath(); |
| 170 } | 171 } |
| 171 return base_path.AppendASCII(type_string); | 172 return base_path.AppendASCII(type_string); |
| 172 } | 173 } |
| 173 | 174 |
| 174 bool MigrateOneOldFileSystem( | 175 bool MigrateOneOldFileSystem( |
| 175 fileapi::ObfuscatedFileUtil* file_util, | 176 ObfuscatedFileUtil* file_util, |
| 176 const FilePath& old_base_path, const GURL& origin, | 177 const FilePath& old_base_path, const GURL& origin, |
| 177 fileapi::FileSystemType type) { | 178 fileapi::FileSystemType type) { |
| 178 FilePath base_path = OldGetBaseDirectoryForOriginAndType( | 179 FilePath base_path = OldGetBaseDirectoryForOriginAndType( |
| 179 old_base_path, origin, type); | 180 old_base_path, origin, type); |
| 180 if (base_path.empty()) | 181 if (base_path.empty()) |
| 181 return false; | 182 return false; |
| 182 | 183 |
| 183 FilePath root; | 184 FilePath root; |
| 184 base::PlatformFileError result = OldReadOriginDirectory(base_path, &root); | 185 base::PlatformFileError result = OldReadOriginDirectory(base_path, &root); |
| 185 if (base::PLATFORM_FILE_ERROR_NOT_FOUND == result) | 186 if (base::PLATFORM_FILE_ERROR_NOT_FOUND == result) |
| 186 return true; // There was nothing to migrate; call that a success. | 187 return true; // There was nothing to migrate; call that a success. |
| 187 | 188 |
| 188 // If we found more than one filesystem [a problem we don't know how to | 189 // If we found more than one filesystem [a problem we don't know how to |
| 189 // solve], the data is already not accessible through Chrome, so it won't do | 190 // solve], the data is already not accessible through Chrome, so it won't do |
| 190 // any harm not to migrate it. Just flag it as an error, so that we don't | 191 // any harm not to migrate it. Just flag it as an error, so that we don't |
| 191 // delete it. | 192 // delete it. |
| 192 if (base::PLATFORM_FILE_OK != result) | 193 if (base::PLATFORM_FILE_OK != result) |
| 193 return false; | 194 return false; |
| 194 | 195 |
| 195 if (!file_util->MigrateFromOldSandbox(origin, type, root)) { | 196 if (!file_util->MigrateFromOldSandbox(origin, type, root)) { |
| 196 LOG(WARNING) << "Failed to migrate filesystem for origin " << origin << | 197 LOG(WARNING) << "Failed to migrate filesystem for origin " << origin << |
| 197 " and type " << type; | 198 " and type " << type; |
| 198 return false; | 199 return false; |
| 199 } | 200 } |
| 200 return true; | 201 return true; |
| 201 } | 202 } |
| 202 | 203 |
| 203 void MigrateAllOldFileSystems( | 204 void MigrateAllOldFileSystems( |
| 204 fileapi::ObfuscatedFileUtil* file_util, | 205 ObfuscatedFileUtil* file_util, |
| 205 const FilePath& old_base_path) { | 206 const FilePath& old_base_path) { |
| 206 scoped_ptr<OldSandboxOriginEnumerator> old_origins( | 207 scoped_ptr<OldSandboxOriginEnumerator> old_origins( |
| 207 new OldSandboxOriginEnumerator(old_base_path)); | 208 new OldSandboxOriginEnumerator(old_base_path)); |
| 208 GURL origin; | 209 GURL origin; |
| 209 int failures = 0; | 210 int failures = 0; |
| 210 while (!(origin = old_origins->Next()).is_empty()) { | 211 while (!(origin = old_origins->Next()).is_empty()) { |
| 211 int failures_this_origin = 0; | 212 int failures_this_origin = 0; |
| 212 if (old_origins->HasFileSystemType(fileapi::kFileSystemTypeTemporary) && | 213 if (old_origins->HasFileSystemType(kFileSystemTypeTemporary) && |
| 213 !MigrateOneOldFileSystem( | 214 !MigrateOneOldFileSystem( |
| 214 file_util, old_base_path, origin, | 215 file_util, old_base_path, origin, |
| 215 fileapi::kFileSystemTypeTemporary)) | 216 kFileSystemTypeTemporary)) |
| 216 ++failures_this_origin; | 217 ++failures_this_origin; |
| 217 if (old_origins->HasFileSystemType(fileapi::kFileSystemTypePersistent) && | 218 if (old_origins->HasFileSystemType(kFileSystemTypePersistent) && |
| 218 !MigrateOneOldFileSystem( | 219 !MigrateOneOldFileSystem( |
| 219 file_util, old_base_path, origin, | 220 file_util, old_base_path, origin, |
| 220 fileapi::kFileSystemTypePersistent)) | 221 kFileSystemTypePersistent)) |
| 221 ++failures_this_origin; | 222 ++failures_this_origin; |
| 222 if (!failures_this_origin) { | 223 if (!failures_this_origin) { |
| 223 FilePath origin_base_path = | 224 FilePath origin_base_path = |
| 224 OldGetBaseDirectoryForOrigin(old_base_path, origin); | 225 OldGetBaseDirectoryForOrigin(old_base_path, origin); |
| 225 // Yes, that's an rm -rf. Make sure that path looks valid, just in case. | 226 // Yes, that's an rm -rf. Make sure that path looks valid, just in case. |
| 226 if (!origin_base_path.empty()) | 227 if (!origin_base_path.empty()) |
| 227 file_util::Delete(origin_base_path, true); | 228 file_util::Delete(origin_base_path, true); |
| 228 } | 229 } |
| 229 failures += failures_this_origin; | 230 failures += failures_this_origin; |
| 230 } | 231 } |
| 231 if (!failures) | 232 if (!failures) |
| 232 file_util::Delete(old_base_path, true); | 233 file_util::Delete(old_base_path, true); |
| 233 if (file_util::DirectoryExists(old_base_path)) { | 234 if (file_util::DirectoryExists(old_base_path)) { |
| 234 // Move it out of the way so that we won't keep trying to migrate it. You | 235 // Move it out of the way so that we won't keep trying to migrate it. You |
| 235 // get only one chance at this; the bits we couldn't do this time, we're | 236 // get only one chance at this; the bits we couldn't do this time, we're |
| 236 // unlikely to be able to do in the future. This way you can now use the | 237 // unlikely to be able to do in the future. This way you can now use the |
| 237 // new filesystem, but have a way to recover your old files if absolutely | 238 // new filesystem, but have a way to recover your old files if absolutely |
| 238 // necessary. | 239 // necessary. |
| 239 FilePath new_path = | 240 FilePath new_path = |
| 240 old_base_path.DirName().Append( | 241 old_base_path.DirName().Append( |
| 241 fileapi::SandboxMountPointProvider::kRenamedOldFileSystemDirectory); | 242 SandboxMountPointProvider::kRenamedOldFileSystemDirectory); |
| 242 file_util::ReplaceFile(old_base_path, new_path); | 243 file_util::ReplaceFile(old_base_path, new_path); |
| 243 } | 244 } |
| 244 } | 245 } |
| 245 | 246 |
| 246 // A migration, whether successful or not, will try to move this directory out | 247 // A migration, whether successful or not, will try to move this directory out |
| 247 // of the way so that we never try to migrate it again. We need to do this | 248 // of the way so that we never try to migrate it again. We need to do this |
| 248 // check on all public entry points in this file, so that it's guaranteed to be | 249 // check on all public entry points in this file, so that it's guaranteed to be |
| 249 // done before anyone looks up a filesystem. Most entry points start by trying | 250 // done before anyone looks up a filesystem. Most entry points start by trying |
| 250 // to look up the filesystem's root, so we can take care of most of them by | 251 // to look up the filesystem's root, so we can take care of most of them by |
| 251 // putting a check there. | 252 // putting a check there. |
| 252 void MigrateIfNeeded( | 253 void MigrateIfNeeded( |
| 253 fileapi::ObfuscatedFileUtil* file_util, | 254 ObfuscatedFileUtil* file_util, |
| 254 const FilePath& old_base_path) { | 255 const FilePath& old_base_path) { |
| 255 if (file_util::DirectoryExists(old_base_path)) | 256 if (file_util::DirectoryExists(old_base_path)) |
| 256 MigrateAllOldFileSystems(file_util, old_base_path); | 257 MigrateAllOldFileSystems(file_util, old_base_path); |
| 257 } | 258 } |
| 258 | 259 |
| 260 void PassPointerErrorByValue( |
| 261 const base::Callback<void(PlatformFileError)>& callback, |
| 262 PlatformFileError* error_ptr) { |
| 263 DCHECK(error_ptr); |
| 264 callback.Run(*error_ptr); |
| 265 } |
| 266 |
| 267 void ValidateRootOnFileThread(ObfuscatedFileUtil* file_util, |
| 268 const GURL& origin_url, |
| 269 FileSystemType type, |
| 270 const FilePath& old_base_path, |
| 271 bool create, |
| 272 base::PlatformFileError* error_ptr) { |
| 273 DCHECK(error_ptr); |
| 274 MigrateIfNeeded(file_util, old_base_path); |
| 275 FilePath root_path = |
| 276 file_util->GetDirectoryForOriginAndType(origin_url, type, create); |
| 277 if (root_path.empty()) { |
| 278 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystem, |
| 279 kCreateDirectoryError, |
| 280 kFileSystemErrorMax); |
| 281 // TODO(kinuko): We should return appropriate error code. |
| 282 *error_ptr = base::PLATFORM_FILE_ERROR_FAILED; |
| 283 } else { |
| 284 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystem, kOK, kFileSystemErrorMax); |
| 285 *error_ptr = base::PLATFORM_FILE_OK; |
| 286 } |
| 287 // The reference of file_util will be derefed on the FILE thread |
| 288 // when the storage of this callback gets deleted regardless of whether |
| 289 // this method is called or not. |
| 290 } |
| 291 |
| 259 } // anonymous namespace | 292 } // anonymous namespace |
| 260 | 293 |
| 261 namespace fileapi { | |
| 262 | |
| 263 const FilePath::CharType SandboxMountPointProvider::kOldFileSystemDirectory[] = | 294 const FilePath::CharType SandboxMountPointProvider::kOldFileSystemDirectory[] = |
| 264 FILE_PATH_LITERAL("FileSystem"); | 295 FILE_PATH_LITERAL("FileSystem"); |
| 265 | 296 |
| 266 const FilePath::CharType SandboxMountPointProvider::kNewFileSystemDirectory[] = | 297 const FilePath::CharType SandboxMountPointProvider::kNewFileSystemDirectory[] = |
| 267 FILE_PATH_LITERAL("File System"); | 298 FILE_PATH_LITERAL("File System"); |
| 268 | 299 |
| 269 const FilePath::CharType | 300 const FilePath::CharType |
| 270 SandboxMountPointProvider::kRenamedOldFileSystemDirectory[] = | 301 SandboxMountPointProvider::kRenamedOldFileSystemDirectory[] = |
| 271 FILE_PATH_LITERAL("FS.old"); | 302 FILE_PATH_LITERAL("FS.old"); |
| 272 | 303 |
| 273 class SandboxMountPointProvider::GetFileSystemRootPathTask | |
| 274 : public base::RefCountedThreadSafe< | |
| 275 SandboxMountPointProvider::GetFileSystemRootPathTask> { | |
| 276 public: | |
| 277 GetFileSystemRootPathTask( | |
| 278 scoped_refptr<base::MessageLoopProxy> file_message_loop, | |
| 279 const GURL& origin_url, | |
| 280 FileSystemType type, | |
| 281 ObfuscatedFileUtil* file_util, | |
| 282 const FilePath& old_base_path, | |
| 283 const FileSystemMountPointProvider::GetRootPathCallback& callback) | |
| 284 : file_message_loop_(file_message_loop), | |
| 285 origin_message_loop_proxy_( | |
| 286 base::MessageLoopProxy::current()), | |
| 287 origin_url_(origin_url), | |
| 288 type_(type), | |
| 289 file_util_(file_util), | |
| 290 old_base_path_(old_base_path), | |
| 291 callback_(callback) { | |
| 292 } | |
| 293 | |
| 294 virtual ~GetFileSystemRootPathTask() { | |
| 295 // Just in case we get deleted without running, make sure to clean up the | |
| 296 // file_util_ on the right thread. | |
| 297 if (file_util_.get() && !file_message_loop_->BelongsToCurrentThread()) | |
| 298 file_message_loop_->ReleaseSoon(FROM_HERE, file_util_.release()); | |
| 299 } | |
| 300 | |
| 301 void Start(bool create) { | |
| 302 file_message_loop_->PostTask( | |
| 303 FROM_HERE, | |
| 304 base::Bind( | |
| 305 &GetFileSystemRootPathTask::GetFileSystemRootPathOnFileThread, this, | |
| 306 create)); | |
| 307 } | |
| 308 | |
| 309 private: | |
| 310 void GetFileSystemRootPathOnFileThread(bool create) { | |
| 311 MigrateIfNeeded(file_util_, old_base_path_); | |
| 312 DispatchCallbackOnCallerThread( | |
| 313 file_util_->GetDirectoryForOriginAndType(origin_url_, type_, create)); | |
| 314 // We must clear the reference on the file thread. | |
| 315 file_util_ = NULL; | |
| 316 } | |
| 317 | |
| 318 void DispatchCallbackOnCallerThread(const FilePath& root_path) { | |
| 319 if (root_path.empty()) { | |
| 320 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystem, | |
| 321 kCreateDirectoryError, | |
| 322 kFileSystemErrorMax); | |
| 323 } | |
| 324 origin_message_loop_proxy_->PostTask( | |
| 325 FROM_HERE, | |
| 326 base::Bind(&GetFileSystemRootPathTask::DispatchCallback, this, | |
| 327 root_path)); | |
| 328 } | |
| 329 | |
| 330 void DispatchCallback(const FilePath& root_path) { | |
| 331 std::string origin_identifier = GetOriginIdentifierFromURL(origin_url_); | |
| 332 std::string type_string = GetFileSystemTypeString(type_); | |
| 333 DCHECK(!type_string.empty()); | |
| 334 std::string name = origin_identifier + ":" + type_string; | |
| 335 | |
| 336 if (!root_path.empty()) | |
| 337 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystem, kOK, kFileSystemErrorMax); | |
| 338 | |
| 339 callback_.Run(!root_path.empty(), root_path, name); | |
| 340 callback_.Reset(); | |
| 341 } | |
| 342 | |
| 343 scoped_refptr<base::MessageLoopProxy> file_message_loop_; | |
| 344 scoped_refptr<base::MessageLoopProxy> origin_message_loop_proxy_; | |
| 345 GURL origin_url_; | |
| 346 FileSystemType type_; | |
| 347 scoped_refptr<ObfuscatedFileUtil> file_util_; | |
| 348 FilePath old_base_path_; | |
| 349 FileSystemMountPointProvider::GetRootPathCallback callback_; | |
| 350 }; | |
| 351 | |
| 352 SandboxMountPointProvider::SandboxMountPointProvider( | 304 SandboxMountPointProvider::SandboxMountPointProvider( |
| 353 scoped_refptr<base::MessageLoopProxy> file_message_loop, | 305 scoped_refptr<base::MessageLoopProxy> file_message_loop, |
| 354 const FilePath& profile_path, | 306 const FilePath& profile_path, |
| 355 const FileSystemOptions& file_system_options) | 307 const FileSystemOptions& file_system_options) |
| 356 : FileSystemQuotaUtil(file_message_loop), | 308 : FileSystemQuotaUtil(file_message_loop), |
| 357 file_message_loop_(file_message_loop), | 309 file_message_loop_(file_message_loop), |
| 358 profile_path_(profile_path), | 310 profile_path_(profile_path), |
| 359 file_system_options_(file_system_options), | 311 file_system_options_(file_system_options), |
| 360 sandbox_file_util_( | 312 sandbox_file_util_( |
| 361 new ObfuscatedFileUtil( | 313 new ObfuscatedFileUtil( |
| 362 profile_path.Append(kNewFileSystemDirectory), | 314 profile_path.Append(kNewFileSystemDirectory), |
| 363 QuotaFileUtil::CreateDefault())) { | 315 QuotaFileUtil::CreateDefault())) { |
| 364 } | 316 } |
| 365 | 317 |
| 366 SandboxMountPointProvider::~SandboxMountPointProvider() { | 318 SandboxMountPointProvider::~SandboxMountPointProvider() { |
| 367 if (!file_message_loop_->BelongsToCurrentThread()) | 319 if (!file_message_loop_->BelongsToCurrentThread()) |
| 368 file_message_loop_->ReleaseSoon(FROM_HERE, sandbox_file_util_.release()); | 320 file_message_loop_->ReleaseSoon(FROM_HERE, sandbox_file_util_.release()); |
| 369 } | 321 } |
| 370 | 322 |
| 371 bool SandboxMountPointProvider::IsAccessAllowed(const GURL& origin_url, | 323 void SandboxMountPointProvider::ValidateFileSystemRoot( |
| 372 FileSystemType type, | |
| 373 const FilePath& unused) { | |
| 374 if (type != kFileSystemTypeTemporary && type != kFileSystemTypePersistent) | |
| 375 return false; | |
| 376 // We essentially depend on quota to do our access controls, so here | |
| 377 // we only check if the requested scheme is allowed or not. | |
| 378 return IsAllowedScheme(origin_url); | |
| 379 } | |
| 380 | |
| 381 void SandboxMountPointProvider::ValidateFileSystemRootAndGetURL( | |
| 382 const GURL& origin_url, fileapi::FileSystemType type, bool create, | 324 const GURL& origin_url, fileapi::FileSystemType type, bool create, |
| 383 const FileSystemMountPointProvider::GetRootPathCallback& callback) { | 325 const ValidateFileSystemCallback& callback) { |
| 384 FilePath origin_base_path; | |
| 385 | |
| 386 if (file_system_options_.is_incognito()) { | 326 if (file_system_options_.is_incognito()) { |
| 387 // TODO(kinuko): return an isolated temporary directory. | 327 // TODO(kinuko): return an isolated temporary directory. |
| 388 callback.Run(false, FilePath(), std::string()); | 328 callback.Run(base::PLATFORM_FILE_ERROR_SECURITY); |
| 389 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystem, | 329 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystem, |
| 390 kIncognito, | 330 kIncognito, |
| 391 kFileSystemErrorMax); | 331 kFileSystemErrorMax); |
| 392 return; | 332 return; |
| 393 } | 333 } |
| 394 | 334 |
| 395 if (!IsAllowedScheme(origin_url)) { | 335 if (!IsAllowedScheme(origin_url)) { |
| 396 callback.Run(false, FilePath(), std::string()); | 336 callback.Run(base::PLATFORM_FILE_ERROR_SECURITY); |
| 397 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystem, | 337 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystem, |
| 398 kInvalidScheme, | 338 kInvalidScheme, |
| 399 kFileSystemErrorMax); | 339 kFileSystemErrorMax); |
| 400 return; | 340 return; |
| 401 } | 341 } |
| 402 | 342 |
| 403 scoped_refptr<GetFileSystemRootPathTask> task( | 343 base::PlatformFileError* error_ptr = new base::PlatformFileError; |
| 404 new GetFileSystemRootPathTask( | 344 file_message_loop_->PostTaskAndReply( |
| 405 file_message_loop_, origin_url, type, sandbox_file_util_.get(), | 345 FROM_HERE, |
| 406 old_base_path(), callback)); | 346 base::Bind(&ValidateRootOnFileThread, |
| 407 task->Start(create); | 347 sandbox_file_util_, |
| 348 origin_url, type, old_base_path(), create, |
| 349 base::Unretained(error_ptr)), |
| 350 base::Bind(base::Bind(&PassPointerErrorByValue, callback), |
| 351 base::Owned(error_ptr))); |
| 408 }; | 352 }; |
| 409 | 353 |
| 410 FilePath | 354 FilePath |
| 411 SandboxMountPointProvider::ValidateFileSystemRootAndGetPathOnFileThread( | 355 SandboxMountPointProvider::GetFileSystemRootPathOnFileThread( |
| 412 const GURL& origin_url, FileSystemType type, const FilePath& unused, | 356 const GURL& origin_url, FileSystemType type, const FilePath& unused, |
| 413 bool create) { | 357 bool create) { |
| 414 if (file_system_options_.is_incognito()) | 358 if (file_system_options_.is_incognito()) |
| 415 // TODO(kinuko): return an isolated temporary directory. | 359 // TODO(kinuko): return an isolated temporary directory. |
| 416 return FilePath(); | 360 return FilePath(); |
| 417 | 361 |
| 418 if (!IsAllowedScheme(origin_url)) | 362 if (!IsAllowedScheme(origin_url)) |
| 419 return FilePath(); | 363 return FilePath(); |
| 420 | 364 |
| 421 MigrateIfNeeded(sandbox_file_util_, old_base_path()); | 365 MigrateIfNeeded(sandbox_file_util_, old_base_path()); |
| 422 | 366 |
| 423 return sandbox_file_util_->GetDirectoryForOriginAndType( | 367 return sandbox_file_util_->GetDirectoryForOriginAndType( |
| 424 origin_url, type, create); | 368 origin_url, type, create); |
| 425 } | 369 } |
| 426 | 370 |
| 371 bool SandboxMountPointProvider::IsAccessAllowed(const GURL& origin_url, |
| 372 FileSystemType type, |
| 373 const FilePath& unused) { |
| 374 if (type != kFileSystemTypeTemporary && type != kFileSystemTypePersistent) |
| 375 return false; |
| 376 // We essentially depend on quota to do our access controls, so here |
| 377 // we only check if the requested scheme is allowed or not. |
| 378 return IsAllowedScheme(origin_url); |
| 379 } |
| 380 |
| 427 bool SandboxMountPointProvider::IsRestrictedFileName(const FilePath& filename) | 381 bool SandboxMountPointProvider::IsRestrictedFileName(const FilePath& filename) |
| 428 const { | 382 const { |
| 429 if (filename.value().empty()) | 383 if (filename.value().empty()) |
| 430 return false; | 384 return false; |
| 431 | 385 |
| 432 for (size_t i = 0; i < arraysize(kRestrictedNames); ++i) { | 386 for (size_t i = 0; i < arraysize(kRestrictedNames); ++i) { |
| 433 // Exact match. | 387 // Exact match. |
| 434 if (filename.value() == kRestrictedNames[i]) | 388 if (filename.value() == kRestrictedNames[i]) |
| 435 return true; | 389 return true; |
| 436 } | 390 } |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 497 quota::QuotaClient::kFileSystem, | 451 quota::QuotaClient::kFileSystem, |
| 498 origin_url, | 452 origin_url, |
| 499 FileSystemTypeToQuotaStorageType(type), | 453 FileSystemTypeToQuotaStorageType(type), |
| 500 -usage); | 454 -usage); |
| 501 } | 455 } |
| 502 return result; | 456 return result; |
| 503 } | 457 } |
| 504 | 458 |
| 505 void SandboxMountPointProvider::GetOriginsForTypeOnFileThread( | 459 void SandboxMountPointProvider::GetOriginsForTypeOnFileThread( |
| 506 fileapi::FileSystemType type, std::set<GURL>* origins) { | 460 fileapi::FileSystemType type, std::set<GURL>* origins) { |
| 507 DCHECK(type == fileapi::kFileSystemTypeTemporary || | 461 DCHECK(type == kFileSystemTypeTemporary || |
| 508 type == fileapi::kFileSystemTypePersistent); | 462 type == kFileSystemTypePersistent); |
| 509 DCHECK(origins); | 463 DCHECK(origins); |
| 510 scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator()); | 464 scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator()); |
| 511 GURL origin; | 465 GURL origin; |
| 512 while (!(origin = enumerator->Next()).is_empty()) { | 466 while (!(origin = enumerator->Next()).is_empty()) { |
| 513 if (enumerator->HasFileSystemType(type)) | 467 if (enumerator->HasFileSystemType(type)) |
| 514 origins->insert(origin); | 468 origins->insert(origin); |
| 515 } | 469 } |
| 516 } | 470 } |
| 517 | 471 |
| 518 void SandboxMountPointProvider::GetOriginsForHostOnFileThread( | 472 void SandboxMountPointProvider::GetOriginsForHostOnFileThread( |
| 519 fileapi::FileSystemType type, const std::string& host, | 473 fileapi::FileSystemType type, const std::string& host, |
| 520 std::set<GURL>* origins) { | 474 std::set<GURL>* origins) { |
| 521 DCHECK(type == fileapi::kFileSystemTypeTemporary || | 475 DCHECK(type == kFileSystemTypeTemporary || |
| 522 type == fileapi::kFileSystemTypePersistent); | 476 type == kFileSystemTypePersistent); |
| 523 DCHECK(origins); | 477 DCHECK(origins); |
| 524 scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator()); | 478 scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator()); |
| 525 GURL origin; | 479 GURL origin; |
| 526 while (!(origin = enumerator->Next()).is_empty()) { | 480 while (!(origin = enumerator->Next()).is_empty()) { |
| 527 if (host == net::GetHostOrSpecFromURL(origin) && | 481 if (host == net::GetHostOrSpecFromURL(origin) && |
| 528 enumerator->HasFileSystemType(type)) | 482 enumerator->HasFileSystemType(type)) |
| 529 origins->insert(origin); | 483 origins->insert(origin); |
| 530 } | 484 } |
| 531 } | 485 } |
| 532 | 486 |
| 533 int64 SandboxMountPointProvider::GetOriginUsageOnFileThread( | 487 int64 SandboxMountPointProvider::GetOriginUsageOnFileThread( |
| 534 const GURL& origin_url, fileapi::FileSystemType type) { | 488 const GURL& origin_url, fileapi::FileSystemType type) { |
| 535 DCHECK(type == fileapi::kFileSystemTypeTemporary || | 489 DCHECK(type == kFileSystemTypeTemporary || |
| 536 type == fileapi::kFileSystemTypePersistent); | 490 type == kFileSystemTypePersistent); |
| 537 FilePath base_path = | 491 FilePath base_path = |
| 538 GetBaseDirectoryForOriginAndType(origin_url, type, false); | 492 GetBaseDirectoryForOriginAndType(origin_url, type, false); |
| 539 if (base_path.empty() || !file_util::DirectoryExists(base_path)) return 0; | 493 if (base_path.empty() || !file_util::DirectoryExists(base_path)) return 0; |
| 540 FilePath usage_file_path = | 494 FilePath usage_file_path = |
| 541 base_path.AppendASCII(FileSystemUsageCache::kUsageFileName); | 495 base_path.AppendASCII(FileSystemUsageCache::kUsageFileName); |
| 542 | 496 |
| 543 bool is_valid = FileSystemUsageCache::IsValid(usage_file_path); | 497 bool is_valid = FileSystemUsageCache::IsValid(usage_file_path); |
| 544 int32 dirty_status = FileSystemUsageCache::GetDirty(usage_file_path); | 498 int32 dirty_status = FileSystemUsageCache::GetDirty(usage_file_path); |
| 545 bool visited = (visited_origins_.find(origin_url) != visited_origins_.end()); | 499 bool visited = (visited_origins_.find(origin_url) != visited_origins_.end()); |
| 546 visited_origins_.insert(origin_url); | 500 visited_origins_.insert(origin_url); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 569 usage += ObfuscatedFileUtil::ComputeFilePathCost(file_path_each); | 523 usage += ObfuscatedFileUtil::ComputeFilePathCost(file_path_each); |
| 570 } | 524 } |
| 571 // This clears the dirty flag too. | 525 // This clears the dirty flag too. |
| 572 FileSystemUsageCache::UpdateUsage(usage_file_path, usage); | 526 FileSystemUsageCache::UpdateUsage(usage_file_path, usage); |
| 573 return usage; | 527 return usage; |
| 574 } | 528 } |
| 575 | 529 |
| 576 void SandboxMountPointProvider::NotifyOriginWasAccessedOnIOThread( | 530 void SandboxMountPointProvider::NotifyOriginWasAccessedOnIOThread( |
| 577 QuotaManagerProxy* proxy, const GURL& origin_url, | 531 QuotaManagerProxy* proxy, const GURL& origin_url, |
| 578 fileapi::FileSystemType type) { | 532 fileapi::FileSystemType type) { |
| 579 DCHECK(type == fileapi::kFileSystemTypeTemporary || | 533 DCHECK(type == kFileSystemTypeTemporary || |
| 580 type == fileapi::kFileSystemTypePersistent); | 534 type == kFileSystemTypePersistent); |
| 581 if (proxy) { | 535 if (proxy) { |
| 582 proxy->NotifyStorageAccessed( | 536 proxy->NotifyStorageAccessed( |
| 583 quota::QuotaClient::kFileSystem, | 537 quota::QuotaClient::kFileSystem, |
| 584 origin_url, | 538 origin_url, |
| 585 FileSystemTypeToQuotaStorageType(type)); | 539 FileSystemTypeToQuotaStorageType(type)); |
| 586 } | 540 } |
| 587 } | 541 } |
| 588 | 542 |
| 589 void SandboxMountPointProvider::UpdateOriginUsageOnFileThread( | 543 void SandboxMountPointProvider::UpdateOriginUsageOnFileThread( |
| 590 QuotaManagerProxy* proxy, const GURL& origin_url, | 544 QuotaManagerProxy* proxy, const GURL& origin_url, |
| 591 fileapi::FileSystemType type, int64 delta) { | 545 fileapi::FileSystemType type, int64 delta) { |
| 592 DCHECK(type == fileapi::kFileSystemTypeTemporary || | 546 DCHECK(type == kFileSystemTypeTemporary || |
| 593 type == fileapi::kFileSystemTypePersistent); | 547 type == kFileSystemTypePersistent); |
| 594 FilePath usage_file_path = GetUsageCachePathForOriginAndType( | 548 FilePath usage_file_path = GetUsageCachePathForOriginAndType( |
| 595 origin_url, type); | 549 origin_url, type); |
| 596 DCHECK(!usage_file_path.empty()); | 550 DCHECK(!usage_file_path.empty()); |
| 597 // TODO(dmikurbe): Make sure that usage_file_path is available. | 551 // TODO(dmikurbe): Make sure that usage_file_path is available. |
| 598 FileSystemUsageCache::AtomicUpdateUsageByDelta(usage_file_path, delta); | 552 FileSystemUsageCache::AtomicUpdateUsageByDelta(usage_file_path, delta); |
| 599 if (proxy) { | 553 if (proxy) { |
| 600 proxy->NotifyStorageModified( | 554 proxy->NotifyStorageModified( |
| 601 quota::QuotaClient::kFileSystem, | 555 quota::QuotaClient::kFileSystem, |
| 602 origin_url, | 556 origin_url, |
| 603 FileSystemTypeToQuotaStorageType(type), | 557 FileSystemTypeToQuotaStorageType(type), |
| 604 delta); | 558 delta); |
| 605 } | 559 } |
| 606 } | 560 } |
| 607 | 561 |
| 608 void SandboxMountPointProvider::StartUpdateOriginOnFileThread( | 562 void SandboxMountPointProvider::StartUpdateOriginOnFileThread( |
| 609 const GURL& origin_url, fileapi::FileSystemType type) { | 563 const GURL& origin_url, fileapi::FileSystemType type) { |
| 610 DCHECK(type == fileapi::kFileSystemTypeTemporary || | 564 DCHECK(type == kFileSystemTypeTemporary || |
| 611 type == fileapi::kFileSystemTypePersistent); | 565 type == kFileSystemTypePersistent); |
| 612 FilePath usage_file_path = GetUsageCachePathForOriginAndType( | 566 FilePath usage_file_path = GetUsageCachePathForOriginAndType( |
| 613 origin_url, type); | 567 origin_url, type); |
| 614 FileSystemUsageCache::IncrementDirty(usage_file_path); | 568 FileSystemUsageCache::IncrementDirty(usage_file_path); |
| 615 } | 569 } |
| 616 | 570 |
| 617 void SandboxMountPointProvider::EndUpdateOriginOnFileThread( | 571 void SandboxMountPointProvider::EndUpdateOriginOnFileThread( |
| 618 const GURL& origin_url, fileapi::FileSystemType type) { | 572 const GURL& origin_url, fileapi::FileSystemType type) { |
| 619 DCHECK(type == fileapi::kFileSystemTypeTemporary || | 573 DCHECK(type == kFileSystemTypeTemporary || |
| 620 type == fileapi::kFileSystemTypePersistent); | 574 type == kFileSystemTypePersistent); |
| 621 FilePath usage_file_path = GetUsageCachePathForOriginAndType( | 575 FilePath usage_file_path = GetUsageCachePathForOriginAndType( |
| 622 origin_url, type); | 576 origin_url, type); |
| 623 FileSystemUsageCache::DecrementDirty(usage_file_path); | 577 FileSystemUsageCache::DecrementDirty(usage_file_path); |
| 624 } | 578 } |
| 625 | 579 |
| 626 void SandboxMountPointProvider::InvalidateUsageCache( | 580 void SandboxMountPointProvider::InvalidateUsageCache( |
| 627 const GURL& origin_url, fileapi::FileSystemType type) { | 581 const GURL& origin_url, fileapi::FileSystemType type) { |
| 628 DCHECK(type == fileapi::kFileSystemTypeTemporary || | 582 DCHECK(type == kFileSystemTypeTemporary || |
| 629 type == fileapi::kFileSystemTypePersistent); | 583 type == kFileSystemTypePersistent); |
| 630 FilePath usage_file_path = GetUsageCachePathForOriginAndType( | 584 FilePath usage_file_path = GetUsageCachePathForOriginAndType( |
| 631 origin_url, type); | 585 origin_url, type); |
| 632 FileSystemUsageCache::IncrementDirty(usage_file_path); | 586 FileSystemUsageCache::IncrementDirty(usage_file_path); |
| 633 } | 587 } |
| 634 | 588 |
| 635 FilePath SandboxMountPointProvider::GetUsageCachePathForOriginAndType( | 589 FilePath SandboxMountPointProvider::GetUsageCachePathForOriginAndType( |
| 636 const GURL& origin_url, fileapi::FileSystemType type) const { | 590 const GURL& origin_url, fileapi::FileSystemType type) const { |
| 637 FilePath base_path = | 591 FilePath base_path = |
| 638 GetBaseDirectoryForOriginAndType(origin_url, type, false); | 592 GetBaseDirectoryForOriginAndType(origin_url, type, false); |
| 639 if (base_path.empty()) | 593 if (base_path.empty()) |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 675 i < file_system_options_.additional_allowed_schemes().size(); | 629 i < file_system_options_.additional_allowed_schemes().size(); |
| 676 ++i) { | 630 ++i) { |
| 677 if (url.SchemeIs( | 631 if (url.SchemeIs( |
| 678 file_system_options_.additional_allowed_schemes()[i].c_str())) | 632 file_system_options_.additional_allowed_schemes()[i].c_str())) |
| 679 return true; | 633 return true; |
| 680 } | 634 } |
| 681 return false; | 635 return false; |
| 682 } | 636 } |
| 683 | 637 |
| 684 } // namespace fileapi | 638 } // namespace fileapi |
| OLD | NEW |