| 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/sandbox_file_system_backend.h" | 5 #include "webkit/browser/fileapi/sandbox_file_system_backend.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/scoped_ptr.h" | |
| 11 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| 12 #include "base/stl_util.h" | |
| 13 #include "base/task_runner_util.h" | 11 #include "base/task_runner_util.h" |
| 14 #include "net/base/net_util.h" | 12 #include "net/base/net_util.h" |
| 15 #include "url/gurl.h" | 13 #include "url/gurl.h" |
| 16 #include "webkit/browser/fileapi/async_file_util_adapter.h" | 14 #include "webkit/browser/fileapi/async_file_util_adapter.h" |
| 17 #include "webkit/browser/fileapi/copy_or_move_file_validator.h" | 15 #include "webkit/browser/fileapi/copy_or_move_file_validator.h" |
| 18 #include "webkit/browser/fileapi/file_system_context.h" | 16 #include "webkit/browser/fileapi/file_system_context.h" |
| 19 #include "webkit/browser/fileapi/file_system_file_stream_reader.h" | 17 #include "webkit/browser/fileapi/file_system_file_stream_reader.h" |
| 20 #include "webkit/browser/fileapi/file_system_operation_context.h" | 18 #include "webkit/browser/fileapi/file_system_operation_context.h" |
| 21 #include "webkit/browser/fileapi/file_system_options.h" | 19 #include "webkit/browser/fileapi/file_system_options.h" |
| 22 #include "webkit/browser/fileapi/file_system_task_runners.h" | 20 #include "webkit/browser/fileapi/file_system_task_runners.h" |
| 23 #include "webkit/browser/fileapi/file_system_usage_cache.h" | |
| 24 #include "webkit/browser/fileapi/local_file_system_operation.h" | 21 #include "webkit/browser/fileapi/local_file_system_operation.h" |
| 25 #include "webkit/browser/fileapi/obfuscated_file_util.h" | 22 #include "webkit/browser/fileapi/obfuscated_file_util.h" |
| 26 #include "webkit/browser/fileapi/sandbox_context.h" | 23 #include "webkit/browser/fileapi/sandbox_context.h" |
| 27 #include "webkit/browser/fileapi/sandbox_file_stream_writer.h" | 24 #include "webkit/browser/fileapi/sandbox_file_stream_writer.h" |
| 28 #include "webkit/browser/fileapi/sandbox_quota_observer.h" | 25 #include "webkit/browser/fileapi/sandbox_quota_observer.h" |
| 29 #include "webkit/browser/fileapi/syncable/syncable_file_system_operation.h" | 26 #include "webkit/browser/fileapi/syncable/syncable_file_system_operation.h" |
| 30 #include "webkit/browser/fileapi/syncable/syncable_file_system_util.h" | 27 #include "webkit/browser/fileapi/syncable/syncable_file_system_util.h" |
| 31 #include "webkit/browser/quota/quota_manager.h" | 28 #include "webkit/browser/quota/quota_manager.h" |
| 32 #include "webkit/common/fileapi/file_system_types.h" | 29 #include "webkit/common/fileapi/file_system_types.h" |
| 33 #include "webkit/common/fileapi/file_system_util.h" | 30 #include "webkit/common/fileapi/file_system_util.h" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 51 kInvalidSchemeError, | 48 kInvalidSchemeError, |
| 52 kCreateDirectoryError, | 49 kCreateDirectoryError, |
| 53 kNotFound, | 50 kNotFound, |
| 54 kUnknownError, | 51 kUnknownError, |
| 55 kFileSystemErrorMax, | 52 kFileSystemErrorMax, |
| 56 }; | 53 }; |
| 57 | 54 |
| 58 const char kTemporaryOriginsCountLabel[] = "FileSystem.TemporaryOriginsCount"; | 55 const char kTemporaryOriginsCountLabel[] = "FileSystem.TemporaryOriginsCount"; |
| 59 const char kPersistentOriginsCountLabel[] = "FileSystem.PersistentOriginsCount"; | 56 const char kPersistentOriginsCountLabel[] = "FileSystem.PersistentOriginsCount"; |
| 60 | 57 |
| 61 // Restricted names. | |
| 62 // http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restrictions | |
| 63 const base::FilePath::CharType* const kRestrictedNames[] = { | |
| 64 FILE_PATH_LITERAL("."), FILE_PATH_LITERAL(".."), | |
| 65 }; | |
| 66 | |
| 67 // Restricted chars. | |
| 68 const base::FilePath::CharType kRestrictedChars[] = { | |
| 69 FILE_PATH_LITERAL('/'), FILE_PATH_LITERAL('\\'), | |
| 70 }; | |
| 71 | |
| 72 class ObfuscatedOriginEnumerator | |
| 73 : public SandboxFileSystemBackend::OriginEnumerator { | |
| 74 public: | |
| 75 explicit ObfuscatedOriginEnumerator(ObfuscatedFileUtil* file_util) { | |
| 76 enum_.reset(file_util->CreateOriginEnumerator()); | |
| 77 } | |
| 78 virtual ~ObfuscatedOriginEnumerator() {} | |
| 79 | |
| 80 virtual GURL Next() OVERRIDE { | |
| 81 return enum_->Next(); | |
| 82 } | |
| 83 | |
| 84 virtual bool HasFileSystemType(fileapi::FileSystemType type) const OVERRIDE { | |
| 85 return enum_->HasFileSystemType(type); | |
| 86 } | |
| 87 | |
| 88 private: | |
| 89 scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enum_; | |
| 90 }; | |
| 91 | |
| 92 void DidOpenFileSystem( | 58 void DidOpenFileSystem( |
| 93 base::WeakPtr<SandboxFileSystemBackend> sandbox_backend, | 59 base::WeakPtr<SandboxFileSystemBackend> sandbox_backend, |
| 94 const base::Callback<void(base::PlatformFileError error)>& callback, | 60 const base::Callback<void(base::PlatformFileError error)>& callback, |
| 95 base::PlatformFileError* error) { | 61 base::PlatformFileError* error) { |
| 96 if (sandbox_backend.get()) | 62 if (sandbox_backend.get()) |
| 97 sandbox_backend.get()->CollectOpenFileSystemMetrics(*error); | 63 sandbox_backend.get()->CollectOpenFileSystemMetrics(*error); |
| 98 callback.Run(*error); | 64 callback.Run(*error); |
| 99 } | 65 } |
| 100 | 66 |
| 101 void OpenFileSystemOnFileThread( | 67 void OpenFileSystemOnFileThread( |
| (...skipping 13 matching lines...) Expand all Loading... |
| 115 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemLabel, kOK, kFileSystemErrorMax); | 81 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemLabel, kOK, kFileSystemErrorMax); |
| 116 } | 82 } |
| 117 // The reference of file_util will be derefed on the FILE thread | 83 // The reference of file_util will be derefed on the FILE thread |
| 118 // when the storage of this callback gets deleted regardless of whether | 84 // when the storage of this callback gets deleted regardless of whether |
| 119 // this method is called or not. | 85 // this method is called or not. |
| 120 } | 86 } |
| 121 | 87 |
| 122 } // anonymous namespace | 88 } // anonymous namespace |
| 123 | 89 |
| 124 SandboxFileSystemBackend::SandboxFileSystemBackend( | 90 SandboxFileSystemBackend::SandboxFileSystemBackend( |
| 125 SandboxContext* sandbox_context, | 91 SandboxContext* sandbox_context) |
| 126 const FileSystemOptions& file_system_options) | 92 : sandbox_context_(sandbox_context), |
| 127 : file_system_options_(file_system_options), | |
| 128 sandbox_context_(sandbox_context), | |
| 129 enable_temporary_file_system_in_incognito_(false), | 93 enable_temporary_file_system_in_incognito_(false), |
| 130 weak_factory_(this) { | 94 weak_factory_(this) { |
| 131 } | 95 } |
| 132 | 96 |
| 133 SandboxFileSystemBackend::~SandboxFileSystemBackend() { | 97 SandboxFileSystemBackend::~SandboxFileSystemBackend() { |
| 134 } | 98 } |
| 135 | 99 |
| 136 bool SandboxFileSystemBackend::CanHandleType(FileSystemType type) const { | 100 bool SandboxFileSystemBackend::CanHandleType(FileSystemType type) const { |
| 137 return type == kFileSystemTypeTemporary || | 101 return type == kFileSystemTypeTemporary || |
| 138 type == kFileSystemTypePersistent || | 102 type == kFileSystemTypePersistent || |
| (...skipping 10 matching lines...) Expand all Loading... |
| 149 sandbox_context_->quota_observer(), NULL); | 113 sandbox_context_->quota_observer(), NULL); |
| 150 | 114 |
| 151 syncable_update_observers_ = update_observers_; | 115 syncable_update_observers_ = update_observers_; |
| 152 | 116 |
| 153 if (!sandbox_context_->file_task_runner()->RunsTasksOnCurrentThread()) { | 117 if (!sandbox_context_->file_task_runner()->RunsTasksOnCurrentThread()) { |
| 154 // Post prepopulate task only if it's not already running on | 118 // Post prepopulate task only if it's not already running on |
| 155 // file_task_runner (which implies running in tests). | 119 // file_task_runner (which implies running in tests). |
| 156 sandbox_context_->file_task_runner()->PostTask( | 120 sandbox_context_->file_task_runner()->PostTask( |
| 157 FROM_HERE, | 121 FROM_HERE, |
| 158 base::Bind(&ObfuscatedFileUtil::MaybePrepopulateDatabase, | 122 base::Bind(&ObfuscatedFileUtil::MaybePrepopulateDatabase, |
| 159 base::Unretained(sandbox_sync_file_util()))); | 123 base::Unretained(sandbox_context_->sync_file_util()))); |
| 160 } | 124 } |
| 161 } | 125 } |
| 162 | 126 |
| 163 void SandboxFileSystemBackend::OpenFileSystem( | 127 void SandboxFileSystemBackend::OpenFileSystem( |
| 164 const GURL& origin_url, | 128 const GURL& origin_url, |
| 165 fileapi::FileSystemType type, | 129 fileapi::FileSystemType type, |
| 166 OpenFileSystemMode mode, | 130 OpenFileSystemMode mode, |
| 167 const OpenFileSystemCallback& callback) { | 131 const OpenFileSystemCallback& callback) { |
| 168 if (file_system_options_.is_incognito() && | 132 DCHECK(CanHandleType(type)); |
| 133 DCHECK(sandbox_context_); |
| 134 if (sandbox_context_->file_system_options().is_incognito() && |
| 169 !(type == kFileSystemTypeTemporary && | 135 !(type == kFileSystemTypeTemporary && |
| 170 enable_temporary_file_system_in_incognito_)) { | 136 enable_temporary_file_system_in_incognito_)) { |
| 171 // TODO(kinuko): return an isolated temporary directory. | 137 // TODO(kinuko): return an isolated temporary directory. |
| 172 callback.Run(GURL(), std::string(), base::PLATFORM_FILE_ERROR_SECURITY); | 138 callback.Run(GURL(), std::string(), base::PLATFORM_FILE_ERROR_SECURITY); |
| 173 return; | 139 return; |
| 174 } | 140 } |
| 175 | 141 |
| 176 if (!IsAllowedScheme(origin_url)) { | 142 if (!sandbox_context_->IsAllowedScheme(origin_url)) { |
| 177 callback.Run(GURL(), std::string(), base::PLATFORM_FILE_ERROR_SECURITY); | 143 callback.Run(GURL(), std::string(), base::PLATFORM_FILE_ERROR_SECURITY); |
| 178 return; | 144 return; |
| 179 } | 145 } |
| 180 | 146 |
| 181 // TODO(nhiroki): Factor out SyncFS related code to SyncFileSystemBackend we | 147 // TODO(nhiroki): Factor out SyncFS related code to SyncFileSystemBackend we |
| 182 // plan to introduce. (http://crbug.com/242422/) | 148 // plan to introduce. (http://crbug.com/242422/) |
| 183 GURL root_url = (type == kFileSystemTypeSyncable) | 149 GURL root_url = (type == kFileSystemTypeSyncable) |
| 184 ? sync_file_system::GetSyncableFileSystemRootURI(origin_url) | 150 ? sync_file_system::GetSyncableFileSystemRootURI(origin_url) |
| 185 : GetFileSystemRootURI(origin_url, type); | 151 : GetFileSystemRootURI(origin_url, type); |
| 186 std::string name = GetFileSystemName(origin_url, type); | 152 std::string name = GetFileSystemName(origin_url, type); |
| 187 | 153 |
| 188 base::PlatformFileError* error_ptr = new base::PlatformFileError; | 154 base::PlatformFileError* error_ptr = new base::PlatformFileError; |
| 189 sandbox_context_->file_task_runner()->PostTaskAndReply( | 155 sandbox_context_->file_task_runner()->PostTaskAndReply( |
| 190 FROM_HERE, | 156 FROM_HERE, |
| 191 base::Bind(&OpenFileSystemOnFileThread, | 157 base::Bind(&OpenFileSystemOnFileThread, |
| 192 sandbox_sync_file_util(), | 158 sandbox_context_->sync_file_util(), |
| 193 origin_url, type, mode, | 159 origin_url, type, mode, |
| 194 base::Unretained(error_ptr)), | 160 base::Unretained(error_ptr)), |
| 195 base::Bind(&DidOpenFileSystem, | 161 base::Bind(&DidOpenFileSystem, |
| 196 weak_factory_.GetWeakPtr(), | 162 weak_factory_.GetWeakPtr(), |
| 197 base::Bind(callback, root_url, name), | 163 base::Bind(callback, root_url, name), |
| 198 base::Owned(error_ptr))); | 164 base::Owned(error_ptr))); |
| 199 }; | 165 }; |
| 200 | 166 |
| 201 FileSystemFileUtil* SandboxFileSystemBackend::GetFileUtil( | 167 FileSystemFileUtil* SandboxFileSystemBackend::GetFileUtil( |
| 202 FileSystemType type) { | 168 FileSystemType type) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 216 base::PlatformFileError* error_code) { | 182 base::PlatformFileError* error_code) { |
| 217 DCHECK(error_code); | 183 DCHECK(error_code); |
| 218 *error_code = base::PLATFORM_FILE_OK; | 184 *error_code = base::PLATFORM_FILE_OK; |
| 219 return NULL; | 185 return NULL; |
| 220 } | 186 } |
| 221 | 187 |
| 222 FileSystemOperation* SandboxFileSystemBackend::CreateFileSystemOperation( | 188 FileSystemOperation* SandboxFileSystemBackend::CreateFileSystemOperation( |
| 223 const FileSystemURL& url, | 189 const FileSystemURL& url, |
| 224 FileSystemContext* context, | 190 FileSystemContext* context, |
| 225 base::PlatformFileError* error_code) const { | 191 base::PlatformFileError* error_code) const { |
| 226 if (!IsAccessValid(url)) { | 192 DCHECK(CanHandleType(url.type())); |
| 193 DCHECK(sandbox_context_); |
| 194 if (!sandbox_context_->IsAccessValid(url)) { |
| 227 *error_code = base::PLATFORM_FILE_ERROR_SECURITY; | 195 *error_code = base::PLATFORM_FILE_ERROR_SECURITY; |
| 228 return NULL; | 196 return NULL; |
| 229 } | 197 } |
| 230 | 198 |
| 231 scoped_ptr<FileSystemOperationContext> operation_context( | 199 scoped_ptr<FileSystemOperationContext> operation_context( |
| 232 new FileSystemOperationContext(context)); | 200 new FileSystemOperationContext(context)); |
| 233 | 201 |
| 234 // Copy the observer lists (assuming we only have small number of observers). | 202 // Copy the observer lists (assuming we only have small number of observers). |
| 235 if (url.type() == kFileSystemTypeSyncable) { | 203 if (url.type() == kFileSystemTypeSyncable) { |
| 236 operation_context->set_update_observers(syncable_update_observers_); | 204 operation_context->set_update_observers(syncable_update_observers_); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 251 | 219 |
| 252 return new LocalFileSystemOperation(url, context, operation_context.Pass()); | 220 return new LocalFileSystemOperation(url, context, operation_context.Pass()); |
| 253 } | 221 } |
| 254 | 222 |
| 255 scoped_ptr<webkit_blob::FileStreamReader> | 223 scoped_ptr<webkit_blob::FileStreamReader> |
| 256 SandboxFileSystemBackend::CreateFileStreamReader( | 224 SandboxFileSystemBackend::CreateFileStreamReader( |
| 257 const FileSystemURL& url, | 225 const FileSystemURL& url, |
| 258 int64 offset, | 226 int64 offset, |
| 259 const base::Time& expected_modification_time, | 227 const base::Time& expected_modification_time, |
| 260 FileSystemContext* context) const { | 228 FileSystemContext* context) const { |
| 261 if (!IsAccessValid(url)) | 229 DCHECK(CanHandleType(url.type())); |
| 230 DCHECK(sandbox_context_); |
| 231 if (!sandbox_context_->IsAccessValid(url)) |
| 262 return scoped_ptr<webkit_blob::FileStreamReader>(); | 232 return scoped_ptr<webkit_blob::FileStreamReader>(); |
| 263 return scoped_ptr<webkit_blob::FileStreamReader>( | 233 return scoped_ptr<webkit_blob::FileStreamReader>( |
| 264 new FileSystemFileStreamReader( | 234 new FileSystemFileStreamReader( |
| 265 context, url, offset, expected_modification_time)); | 235 context, url, offset, expected_modification_time)); |
| 266 } | 236 } |
| 267 | 237 |
| 268 scoped_ptr<fileapi::FileStreamWriter> | 238 scoped_ptr<fileapi::FileStreamWriter> |
| 269 SandboxFileSystemBackend::CreateFileStreamWriter( | 239 SandboxFileSystemBackend::CreateFileStreamWriter( |
| 270 const FileSystemURL& url, | 240 const FileSystemURL& url, |
| 271 int64 offset, | 241 int64 offset, |
| 272 FileSystemContext* context) const { | 242 FileSystemContext* context) const { |
| 273 if (!IsAccessValid(url)) | 243 DCHECK(CanHandleType(url.type())); |
| 244 DCHECK(sandbox_context_); |
| 245 if (!sandbox_context_->IsAccessValid(url)) |
| 274 return scoped_ptr<fileapi::FileStreamWriter>(); | 246 return scoped_ptr<fileapi::FileStreamWriter>(); |
| 275 return scoped_ptr<fileapi::FileStreamWriter>( | 247 return scoped_ptr<fileapi::FileStreamWriter>( |
| 276 new SandboxFileStreamWriter(context, url, offset, update_observers_)); | 248 new SandboxFileStreamWriter(context, url, offset, update_observers_)); |
| 277 } | 249 } |
| 278 | 250 |
| 279 FileSystemQuotaUtil* SandboxFileSystemBackend::GetQuotaUtil() { | 251 FileSystemQuotaUtil* SandboxFileSystemBackend::GetQuotaUtil() { |
| 280 return this; | 252 return this; |
| 281 } | 253 } |
| 282 | 254 |
| 283 SandboxFileSystemBackend::OriginEnumerator* | 255 SandboxContext::OriginEnumerator* |
| 284 SandboxFileSystemBackend::CreateOriginEnumerator() { | 256 SandboxFileSystemBackend::CreateOriginEnumerator() { |
| 285 return new ObfuscatedOriginEnumerator(sandbox_sync_file_util()); | 257 DCHECK(sandbox_context_); |
| 286 } | 258 return sandbox_context_->CreateOriginEnumerator(); |
| 287 | |
| 288 base::FilePath SandboxFileSystemBackend::GetBaseDirectoryForOriginAndType( | |
| 289 const GURL& origin_url, fileapi::FileSystemType type, bool create) { | |
| 290 base::PlatformFileError error = base::PLATFORM_FILE_OK; | |
| 291 base::FilePath path = sandbox_sync_file_util()->GetDirectoryForOriginAndType( | |
| 292 origin_url, type, create, &error); | |
| 293 if (error != base::PLATFORM_FILE_OK) | |
| 294 return base::FilePath(); | |
| 295 return path; | |
| 296 } | 259 } |
| 297 | 260 |
| 298 base::PlatformFileError | 261 base::PlatformFileError |
| 299 SandboxFileSystemBackend::DeleteOriginDataOnFileThread( | 262 SandboxFileSystemBackend::DeleteOriginDataOnFileThread( |
| 300 FileSystemContext* file_system_context, | 263 FileSystemContext* file_system_context, |
| 301 QuotaManagerProxy* proxy, | 264 QuotaManagerProxy* proxy, |
| 302 const GURL& origin_url, | 265 const GURL& origin_url, |
| 303 fileapi::FileSystemType type) { | 266 fileapi::FileSystemType type) { |
| 304 int64 usage = GetOriginUsageOnFileThread(file_system_context, | 267 DCHECK(CanHandleType(type)); |
| 305 origin_url, type); | 268 DCHECK(sandbox_context_); |
| 306 | 269 return sandbox_context_->DeleteOriginDataOnFileThread( |
| 307 usage_cache()->CloseCacheFiles(); | 270 file_system_context, proxy, origin_url, type); |
| 308 bool result = sandbox_sync_file_util()->DeleteDirectoryForOriginAndType( | |
| 309 origin_url, type); | |
| 310 if (result && proxy) { | |
| 311 proxy->NotifyStorageModified( | |
| 312 quota::QuotaClient::kFileSystem, | |
| 313 origin_url, | |
| 314 FileSystemTypeToQuotaStorageType(type), | |
| 315 -usage); | |
| 316 } | |
| 317 | |
| 318 if (result) | |
| 319 return base::PLATFORM_FILE_OK; | |
| 320 return base::PLATFORM_FILE_ERROR_FAILED; | |
| 321 } | 271 } |
| 322 | 272 |
| 323 void SandboxFileSystemBackend::GetOriginsForTypeOnFileThread( | 273 void SandboxFileSystemBackend::GetOriginsForTypeOnFileThread( |
| 324 fileapi::FileSystemType type, std::set<GURL>* origins) { | 274 fileapi::FileSystemType type, std::set<GURL>* origins) { |
| 325 DCHECK(CanHandleType(type)); | 275 DCHECK(CanHandleType(type)); |
| 326 DCHECK(origins); | 276 DCHECK(sandbox_context_); |
| 327 scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator()); | 277 sandbox_context_->GetOriginsForTypeOnFileThread(type, origins); |
| 328 GURL origin; | |
| 329 while (!(origin = enumerator->Next()).is_empty()) { | |
| 330 if (enumerator->HasFileSystemType(type)) | |
| 331 origins->insert(origin); | |
| 332 } | |
| 333 switch (type) { | 278 switch (type) { |
| 334 case kFileSystemTypeTemporary: | 279 case kFileSystemTypeTemporary: |
| 335 UMA_HISTOGRAM_COUNTS(kTemporaryOriginsCountLabel, origins->size()); | 280 UMA_HISTOGRAM_COUNTS(kTemporaryOriginsCountLabel, origins->size()); |
| 336 break; | 281 break; |
| 337 case kFileSystemTypePersistent: | 282 case kFileSystemTypePersistent: |
| 338 UMA_HISTOGRAM_COUNTS(kPersistentOriginsCountLabel, origins->size()); | 283 UMA_HISTOGRAM_COUNTS(kPersistentOriginsCountLabel, origins->size()); |
| 339 break; | 284 break; |
| 340 default: | 285 default: |
| 341 break; | 286 break; |
| 342 } | 287 } |
| 343 } | 288 } |
| 344 | 289 |
| 345 void SandboxFileSystemBackend::GetOriginsForHostOnFileThread( | 290 void SandboxFileSystemBackend::GetOriginsForHostOnFileThread( |
| 346 fileapi::FileSystemType type, const std::string& host, | 291 fileapi::FileSystemType type, const std::string& host, |
| 347 std::set<GURL>* origins) { | 292 std::set<GURL>* origins) { |
| 348 DCHECK(CanHandleType(type)); | 293 DCHECK(CanHandleType(type)); |
| 349 DCHECK(origins); | 294 DCHECK(sandbox_context_); |
| 350 scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator()); | 295 sandbox_context_->GetOriginsForHostOnFileThread(type, host, origins); |
| 351 GURL origin; | |
| 352 while (!(origin = enumerator->Next()).is_empty()) { | |
| 353 if (host == net::GetHostOrSpecFromURL(origin) && | |
| 354 enumerator->HasFileSystemType(type)) | |
| 355 origins->insert(origin); | |
| 356 } | |
| 357 } | 296 } |
| 358 | 297 |
| 359 int64 SandboxFileSystemBackend::GetOriginUsageOnFileThread( | 298 int64 SandboxFileSystemBackend::GetOriginUsageOnFileThread( |
| 360 FileSystemContext* file_system_context, | 299 FileSystemContext* file_system_context, |
| 361 const GURL& origin_url, | 300 const GURL& origin_url, |
| 362 fileapi::FileSystemType type) { | 301 fileapi::FileSystemType type) { |
| 363 DCHECK(CanHandleType(type)); | 302 DCHECK(CanHandleType(type)); |
| 364 | 303 DCHECK(sandbox_context_); |
| 365 // Don't use usage cache and return recalculated usage for sticky invalidated | 304 return sandbox_context_->GetOriginUsageOnFileThread( |
| 366 // origins. | 305 file_system_context, origin_url, type); |
| 367 if (ContainsKey(sticky_dirty_origins_, std::make_pair(origin_url, type))) | |
| 368 return RecalculateUsage(file_system_context, origin_url, type); | |
| 369 | |
| 370 base::FilePath base_path = | |
| 371 GetBaseDirectoryForOriginAndType(origin_url, type, false); | |
| 372 if (base_path.empty() || !base::DirectoryExists(base_path)) | |
| 373 return 0; | |
| 374 base::FilePath usage_file_path = | |
| 375 base_path.Append(FileSystemUsageCache::kUsageFileName); | |
| 376 | |
| 377 bool is_valid = usage_cache()->IsValid(usage_file_path); | |
| 378 uint32 dirty_status = 0; | |
| 379 bool dirty_status_available = | |
| 380 usage_cache()->GetDirty(usage_file_path, &dirty_status); | |
| 381 bool visited = !visited_origins_.insert(origin_url).second; | |
| 382 if (is_valid && (dirty_status == 0 || (dirty_status_available && visited))) { | |
| 383 // The usage cache is clean (dirty == 0) or the origin is already | |
| 384 // initialized and running. Read the cache file to get the usage. | |
| 385 int64 usage = 0; | |
| 386 return usage_cache()->GetUsage(usage_file_path, &usage) ? usage : -1; | |
| 387 } | |
| 388 // The usage cache has not been initialized or the cache is dirty. | |
| 389 // Get the directory size now and update the cache. | |
| 390 usage_cache()->Delete(usage_file_path); | |
| 391 | |
| 392 int64 usage = RecalculateUsage(file_system_context, origin_url, type); | |
| 393 | |
| 394 // This clears the dirty flag too. | |
| 395 usage_cache()->UpdateUsage(usage_file_path, usage); | |
| 396 return usage; | |
| 397 } | 306 } |
| 398 | 307 |
| 399 void SandboxFileSystemBackend::InvalidateUsageCache( | 308 void SandboxFileSystemBackend::InvalidateUsageCache( |
| 400 const GURL& origin, | 309 const GURL& origin, |
| 401 fileapi::FileSystemType type) { | 310 fileapi::FileSystemType type) { |
| 402 DCHECK(CanHandleType(type)); | 311 DCHECK(CanHandleType(type)); |
| 403 base::PlatformFileError error = base::PLATFORM_FILE_OK; | 312 DCHECK(sandbox_context_); |
| 404 base::FilePath usage_file_path = GetUsageCachePathForOriginAndType( | 313 sandbox_context_->InvalidateUsageCache(origin, type); |
| 405 sandbox_sync_file_util(), origin, type, &error); | |
| 406 if (error != base::PLATFORM_FILE_OK) | |
| 407 return; | |
| 408 usage_cache()->IncrementDirty(usage_file_path); | |
| 409 } | 314 } |
| 410 | 315 |
| 411 void SandboxFileSystemBackend::StickyInvalidateUsageCache( | 316 void SandboxFileSystemBackend::StickyInvalidateUsageCache( |
| 412 const GURL& origin, | 317 const GURL& origin, |
| 413 fileapi::FileSystemType type) { | 318 fileapi::FileSystemType type) { |
| 414 DCHECK(CanHandleType(type)); | 319 DCHECK(CanHandleType(type)); |
| 415 sticky_dirty_origins_.insert(std::make_pair(origin, type)); | 320 DCHECK(sandbox_context_); |
| 416 sandbox_context_->quota_observer()->SetUsageCacheEnabled(origin, type, false); | 321 sandbox_context_->StickyInvalidateUsageCache(origin, type); |
| 417 InvalidateUsageCache(origin, type); | |
| 418 } | 322 } |
| 419 | 323 |
| 420 void SandboxFileSystemBackend::AddFileUpdateObserver( | 324 void SandboxFileSystemBackend::AddFileUpdateObserver( |
| 421 FileSystemType type, | 325 FileSystemType type, |
| 422 FileUpdateObserver* observer, | 326 FileUpdateObserver* observer, |
| 423 base::SequencedTaskRunner* task_runner) { | 327 base::SequencedTaskRunner* task_runner) { |
| 424 DCHECK(CanHandleType(type)); | 328 DCHECK(CanHandleType(type)); |
| 425 UpdateObserverList* list = &update_observers_; | 329 UpdateObserverList* list = &update_observers_; |
| 426 if (type == kFileSystemTypeSyncable) | 330 if (type == kFileSystemTypeSyncable) |
| 427 list = &syncable_update_observers_; | 331 list = &syncable_update_observers_; |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 499 REPORT(kNotFound); | 403 REPORT(kNotFound); |
| 500 break; | 404 break; |
| 501 case base::PLATFORM_FILE_ERROR_FAILED: | 405 case base::PLATFORM_FILE_ERROR_FAILED: |
| 502 default: | 406 default: |
| 503 REPORT(kUnknownError); | 407 REPORT(kUnknownError); |
| 504 break; | 408 break; |
| 505 } | 409 } |
| 506 #undef REPORT | 410 #undef REPORT |
| 507 } | 411 } |
| 508 | 412 |
| 509 bool SandboxFileSystemBackend::IsAccessValid( | |
| 510 const FileSystemURL& url) const { | |
| 511 if (!IsAllowedScheme(url.origin())) | |
| 512 return false; | |
| 513 | |
| 514 if (!CanHandleType(url.type())) | |
| 515 return false; | |
| 516 | |
| 517 if (url.path().ReferencesParent()) | |
| 518 return false; | |
| 519 | |
| 520 // Return earlier if the path is '/', because VirtualPath::BaseName() | |
| 521 // returns '/' for '/' and we fail the "basename != '/'" check below. | |
| 522 // (We exclude '.' because it's disallowed by spec.) | |
| 523 if (VirtualPath::IsRootPath(url.path()) && | |
| 524 url.path() != base::FilePath(base::FilePath::kCurrentDirectory)) | |
| 525 return true; | |
| 526 | |
| 527 // Restricted names specified in | |
| 528 // http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restriction
s | |
| 529 base::FilePath filename = VirtualPath::BaseName(url.path()); | |
| 530 // See if the name is allowed to create. | |
| 531 for (size_t i = 0; i < arraysize(kRestrictedNames); ++i) { | |
| 532 if (filename.value() == kRestrictedNames[i]) | |
| 533 return false; | |
| 534 } | |
| 535 for (size_t i = 0; i < arraysize(kRestrictedChars); ++i) { | |
| 536 if (filename.value().find(kRestrictedChars[i]) != | |
| 537 base::FilePath::StringType::npos) | |
| 538 return false; | |
| 539 } | |
| 540 | |
| 541 return true; | |
| 542 } | |
| 543 | |
| 544 base::FilePath SandboxFileSystemBackend::GetUsageCachePathForOriginAndType( | |
| 545 const GURL& origin_url, | |
| 546 FileSystemType type) { | |
| 547 base::PlatformFileError error; | |
| 548 base::FilePath path = GetUsageCachePathForOriginAndType( | |
| 549 sandbox_sync_file_util(), origin_url, type, &error); | |
| 550 if (error != base::PLATFORM_FILE_OK) | |
| 551 return base::FilePath(); | |
| 552 return path; | |
| 553 } | |
| 554 | |
| 555 // static | |
| 556 base::FilePath SandboxFileSystemBackend::GetUsageCachePathForOriginAndType( | |
| 557 ObfuscatedFileUtil* sandbox_file_util, | |
| 558 const GURL& origin_url, | |
| 559 fileapi::FileSystemType type, | |
| 560 base::PlatformFileError* error_out) { | |
| 561 DCHECK(error_out); | |
| 562 *error_out = base::PLATFORM_FILE_OK; | |
| 563 base::FilePath base_path = sandbox_file_util->GetDirectoryForOriginAndType( | |
| 564 origin_url, type, false /* create */, error_out); | |
| 565 if (*error_out != base::PLATFORM_FILE_OK) | |
| 566 return base::FilePath(); | |
| 567 return base_path.Append(FileSystemUsageCache::kUsageFileName); | |
| 568 } | |
| 569 | |
| 570 bool SandboxFileSystemBackend::IsAllowedScheme(const GURL& url) const { | |
| 571 // Basically we only accept http or https. We allow file:// URLs | |
| 572 // only if --allow-file-access-from-files flag is given. | |
| 573 if (url.SchemeIs("http") || url.SchemeIs("https")) | |
| 574 return true; | |
| 575 if (url.SchemeIsFileSystem()) | |
| 576 return url.inner_url() && IsAllowedScheme(*url.inner_url()); | |
| 577 | |
| 578 for (size_t i = 0; | |
| 579 i < file_system_options_.additional_allowed_schemes().size(); | |
| 580 ++i) { | |
| 581 if (url.SchemeIs( | |
| 582 file_system_options_.additional_allowed_schemes()[i].c_str())) | |
| 583 return true; | |
| 584 } | |
| 585 return false; | |
| 586 } | |
| 587 | |
| 588 ObfuscatedFileUtil* SandboxFileSystemBackend::sandbox_sync_file_util() { | |
| 589 DCHECK(sandbox_context_); | |
| 590 return sandbox_context_->sync_file_util(); | |
| 591 } | |
| 592 | |
| 593 FileSystemUsageCache* SandboxFileSystemBackend::usage_cache() { | |
| 594 DCHECK(sandbox_context_); | |
| 595 return sandbox_context_->usage_cache(); | |
| 596 } | |
| 597 | |
| 598 int64 SandboxFileSystemBackend::RecalculateUsage(FileSystemContext* context, | |
| 599 const GURL& origin, | |
| 600 FileSystemType type) { | |
| 601 FileSystemOperationContext operation_context(context); | |
| 602 FileSystemURL url = context->CreateCrackedFileSystemURL( | |
| 603 origin, type, base::FilePath()); | |
| 604 scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> enumerator( | |
| 605 sandbox_sync_file_util()->CreateFileEnumerator( | |
| 606 &operation_context, url, true)); | |
| 607 | |
| 608 base::FilePath file_path_each; | |
| 609 int64 usage = 0; | |
| 610 | |
| 611 while (!(file_path_each = enumerator->Next()).empty()) { | |
| 612 usage += enumerator->Size(); | |
| 613 usage += ObfuscatedFileUtil::ComputeFilePathCost(file_path_each); | |
| 614 } | |
| 615 | |
| 616 return usage; | |
| 617 } | |
| 618 | |
| 619 } // namespace fileapi | 413 } // namespace fileapi |
| OLD | NEW |