| 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" | 10 #include "base/memory/scoped_ptr.h" |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 kCreateDirectoryError, | 55 kCreateDirectoryError, |
| 56 kNotFound, | 56 kNotFound, |
| 57 kUnknownError, | 57 kUnknownError, |
| 58 kFileSystemErrorMax, | 58 kFileSystemErrorMax, |
| 59 }; | 59 }; |
| 60 | 60 |
| 61 const char kTemporaryOriginsCountLabel[] = "FileSystem.TemporaryOriginsCount"; | 61 const char kTemporaryOriginsCountLabel[] = "FileSystem.TemporaryOriginsCount"; |
| 62 const char kPersistentOriginsCountLabel[] = "FileSystem.PersistentOriginsCount"; | 62 const char kPersistentOriginsCountLabel[] = "FileSystem.PersistentOriginsCount"; |
| 63 const char kSyncableOriginsCountLabel[] = "FileSystem.SyncableOriginsCount"; | 63 const char kSyncableOriginsCountLabel[] = "FileSystem.SyncableOriginsCount"; |
| 64 | 64 |
| 65 // Restricted names. | |
| 66 // http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restrictions | |
| 67 const base::FilePath::CharType* const kRestrictedNames[] = { | |
| 68 FILE_PATH_LITERAL("."), FILE_PATH_LITERAL(".."), | |
| 69 }; | |
| 70 | |
| 71 // Restricted chars. | |
| 72 const base::FilePath::CharType kRestrictedChars[] = { | |
| 73 FILE_PATH_LITERAL('/'), FILE_PATH_LITERAL('\\'), | |
| 74 }; | |
| 75 | |
| 76 class ObfuscatedOriginEnumerator | |
| 77 : public SandboxFileSystemBackend::OriginEnumerator { | |
| 78 public: | |
| 79 explicit ObfuscatedOriginEnumerator(ObfuscatedFileUtil* file_util) { | |
| 80 enum_.reset(file_util->CreateOriginEnumerator()); | |
| 81 } | |
| 82 virtual ~ObfuscatedOriginEnumerator() {} | |
| 83 | |
| 84 virtual GURL Next() OVERRIDE { | |
| 85 return enum_->Next(); | |
| 86 } | |
| 87 | |
| 88 virtual bool HasFileSystemType(fileapi::FileSystemType type) const OVERRIDE { | |
| 89 return enum_->HasFileSystemType(type); | |
| 90 } | |
| 91 | |
| 92 private: | |
| 93 scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enum_; | |
| 94 }; | |
| 95 | |
| 96 void DidOpenFileSystem( | 65 void DidOpenFileSystem( |
| 97 base::WeakPtr<SandboxFileSystemBackend> sandbox_backend, | 66 base::WeakPtr<SandboxFileSystemBackend> sandbox_backend, |
| 98 const base::Callback<void(base::PlatformFileError error)>& callback, | 67 const base::Callback<void(base::PlatformFileError error)>& callback, |
| 99 base::PlatformFileError* error) { | 68 base::PlatformFileError* error) { |
| 100 if (sandbox_backend.get()) | 69 if (sandbox_backend.get()) |
| 101 sandbox_backend.get()->CollectOpenFileSystemMetrics(*error); | 70 sandbox_backend.get()->CollectOpenFileSystemMetrics(*error); |
| 102 callback.Run(*error); | 71 callback.Run(*error); |
| 103 } | 72 } |
| 104 | 73 |
| 105 void OpenFileSystemOnFileThread( | 74 void OpenFileSystemOnFileThread( |
| (...skipping 16 matching lines...) Expand all Loading... |
| 122 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemLabel, kOK, kFileSystemErrorMax); | 91 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemLabel, kOK, kFileSystemErrorMax); |
| 123 } | 92 } |
| 124 // The reference of file_util will be derefed on the FILE thread | 93 // The reference of file_util will be derefed on the FILE thread |
| 125 // when the storage of this callback gets deleted regardless of whether | 94 // when the storage of this callback gets deleted regardless of whether |
| 126 // this method is called or not. | 95 // this method is called or not. |
| 127 } | 96 } |
| 128 | 97 |
| 129 } // anonymous namespace | 98 } // anonymous namespace |
| 130 | 99 |
| 131 SandboxFileSystemBackend::SandboxFileSystemBackend( | 100 SandboxFileSystemBackend::SandboxFileSystemBackend( |
| 132 SandboxContext* sandbox_context, | 101 SandboxContext* sandbox_context) |
| 133 const FileSystemOptions& file_system_options) | 102 : sandbox_context_(sandbox_context), |
| 134 : file_system_options_(file_system_options), | |
| 135 sandbox_context_(sandbox_context), | |
| 136 enable_temporary_file_system_in_incognito_(false), | 103 enable_temporary_file_system_in_incognito_(false), |
| 137 weak_factory_(this) { | 104 weak_factory_(this) { |
| 138 } | 105 } |
| 139 | 106 |
| 140 SandboxFileSystemBackend::~SandboxFileSystemBackend() { | 107 SandboxFileSystemBackend::~SandboxFileSystemBackend() { |
| 141 } | 108 } |
| 142 | 109 |
| 143 bool SandboxFileSystemBackend::CanHandleType(FileSystemType type) const { | 110 bool SandboxFileSystemBackend::CanHandleType(FileSystemType type) const { |
| 144 return type == kFileSystemTypeTemporary || | 111 return type == kFileSystemTypeTemporary || |
| 145 type == kFileSystemTypePersistent || | 112 type == kFileSystemTypePersistent || |
| (...skipping 21 matching lines...) Expand all Loading... |
| 167 base::Bind(&ObfuscatedFileUtil::MaybePrepopulateDatabase, | 134 base::Bind(&ObfuscatedFileUtil::MaybePrepopulateDatabase, |
| 168 base::Unretained(sandbox_sync_file_util()))); | 135 base::Unretained(sandbox_sync_file_util()))); |
| 169 } | 136 } |
| 170 } | 137 } |
| 171 | 138 |
| 172 void SandboxFileSystemBackend::OpenFileSystem( | 139 void SandboxFileSystemBackend::OpenFileSystem( |
| 173 const GURL& origin_url, | 140 const GURL& origin_url, |
| 174 fileapi::FileSystemType type, | 141 fileapi::FileSystemType type, |
| 175 OpenFileSystemMode mode, | 142 OpenFileSystemMode mode, |
| 176 const OpenFileSystemCallback& callback) { | 143 const OpenFileSystemCallback& callback) { |
| 177 if (file_system_options_.is_incognito() && | 144 DCHECK(sandbox_context_); |
| 145 if (sandbox_context_->file_system_options().is_incognito() && |
| 178 !(type == kFileSystemTypeTemporary && | 146 !(type == kFileSystemTypeTemporary && |
| 179 enable_temporary_file_system_in_incognito_)) { | 147 enable_temporary_file_system_in_incognito_)) { |
| 180 // TODO(kinuko): return an isolated temporary directory. | 148 // TODO(kinuko): return an isolated temporary directory. |
| 181 callback.Run(GURL(), std::string(), base::PLATFORM_FILE_ERROR_SECURITY); | 149 callback.Run(GURL(), std::string(), base::PLATFORM_FILE_ERROR_SECURITY); |
| 182 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemLabel, | 150 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemLabel, |
| 183 kIncognito, | 151 kIncognito, |
| 184 kFileSystemErrorMax); | 152 kFileSystemErrorMax); |
| 185 return; | 153 return; |
| 186 } | 154 } |
| 187 | 155 |
| 188 if (!IsAllowedScheme(origin_url)) { | 156 if (!sandbox_context_->IsAllowedScheme(origin_url)) { |
| 189 callback.Run(GURL(), std::string(), base::PLATFORM_FILE_ERROR_SECURITY); | 157 callback.Run(GURL(), std::string(), base::PLATFORM_FILE_ERROR_SECURITY); |
| 190 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemLabel, | 158 UMA_HISTOGRAM_ENUMERATION(kOpenFileSystemLabel, |
| 191 kInvalidSchemeError, | 159 kInvalidSchemeError, |
| 192 kFileSystemErrorMax); | 160 kFileSystemErrorMax); |
| 193 return; | 161 return; |
| 194 } | 162 } |
| 195 | 163 |
| 196 // TODO(nhiroki): Factor out SyncFS related code to SyncFileSystemBackend we | 164 // TODO(nhiroki): Factor out SyncFS related code to SyncFileSystemBackend we |
| 197 // plan to introduce. (http://crbug.com/242422/) | 165 // plan to introduce. (http://crbug.com/242422/) |
| 198 GURL root_url = (type == kFileSystemTypeSyncable) | 166 GURL root_url = (type == kFileSystemTypeSyncable) |
| 199 ? sync_file_system::GetSyncableFileSystemRootURI(origin_url) | 167 ? sync_file_system::GetSyncableFileSystemRootURI(origin_url) |
| 200 : GetFileSystemRootURI(origin_url, type); | 168 : GetFileSystemRootURI(origin_url, type); |
| 201 std::string name = GetFileSystemName(origin_url, type); | 169 std::string name = GetFileSystemName(origin_url, type); |
| 202 | 170 |
| 203 base::PlatformFileError* error_ptr = new base::PlatformFileError; | 171 base::PlatformFileError* error_ptr = new base::PlatformFileError; |
| 204 sandbox_context_->file_task_runner()->PostTaskAndReply( | 172 sandbox_context_->file_task_runner()->PostTaskAndReply( |
| 205 FROM_HERE, | 173 FROM_HERE, |
| 206 base::Bind(&OpenFileSystemOnFileThread, | 174 base::Bind(&OpenFileSystemOnFileThread, |
| 207 sandbox_sync_file_util(), | 175 sandbox_sync_file_util(), |
| 208 origin_url, type, mode, | 176 origin_url, type, mode, |
| 209 base::Unretained(error_ptr)), | 177 base::Unretained(error_ptr)), |
| 210 base::Bind(&DidOpenFileSystem, | 178 base::Bind(&DidOpenFileSystem, |
| 211 weak_factory_.GetWeakPtr(), | 179 weak_factory_.GetWeakPtr(), |
| 212 base::Bind(callback, root_url, name), | 180 base::Bind(callback, root_url, name), |
| 213 base::Owned(error_ptr))); | 181 base::Owned(error_ptr))); |
| 214 | |
| 215 if (sandbox_context_->is_usage_tracking_enabled()) | |
| 216 return; | |
| 217 | |
| 218 // Schedule full usage recalculation on the next launch without | |
| 219 // --disable-file-system-usage-tracking. | |
| 220 sandbox_context_->file_task_runner()->PostTask( | |
| 221 FROM_HERE, | |
| 222 base::Bind(&SandboxFileSystemBackend::InvalidateUsageCacheOnFileThread, | |
| 223 sandbox_sync_file_util(), origin_url, type, usage_cache())); | |
| 224 }; | 182 }; |
| 225 | 183 |
| 226 FileSystemFileUtil* SandboxFileSystemBackend::GetFileUtil( | 184 FileSystemFileUtil* SandboxFileSystemBackend::GetFileUtil( |
| 227 FileSystemType type) { | 185 FileSystemType type) { |
| 228 DCHECK(sandbox_context_); | 186 DCHECK(sandbox_context_); |
| 229 return sandbox_context_->sync_file_util(); | 187 return sandbox_context_->sync_file_util(); |
| 230 } | 188 } |
| 231 | 189 |
| 232 AsyncFileUtil* SandboxFileSystemBackend::GetAsyncFileUtil( | 190 AsyncFileUtil* SandboxFileSystemBackend::GetAsyncFileUtil( |
| 233 FileSystemType type) { | 191 FileSystemType type) { |
| 234 DCHECK(sandbox_context_); | 192 DCHECK(sandbox_context_); |
| 235 return sandbox_context_->file_util(); | 193 return sandbox_context_->file_util(); |
| 236 } | 194 } |
| 237 | 195 |
| 238 CopyOrMoveFileValidatorFactory* | 196 CopyOrMoveFileValidatorFactory* |
| 239 SandboxFileSystemBackend::GetCopyOrMoveFileValidatorFactory( | 197 SandboxFileSystemBackend::GetCopyOrMoveFileValidatorFactory( |
| 240 FileSystemType type, | 198 FileSystemType type, |
| 241 base::PlatformFileError* error_code) { | 199 base::PlatformFileError* error_code) { |
| 242 DCHECK(error_code); | 200 DCHECK(error_code); |
| 243 *error_code = base::PLATFORM_FILE_OK; | 201 *error_code = base::PLATFORM_FILE_OK; |
| 244 return NULL; | 202 return NULL; |
| 245 } | 203 } |
| 246 | 204 |
| 247 FileSystemOperation* SandboxFileSystemBackend::CreateFileSystemOperation( | 205 FileSystemOperation* SandboxFileSystemBackend::CreateFileSystemOperation( |
| 248 const FileSystemURL& url, | 206 const FileSystemURL& url, |
| 249 FileSystemContext* context, | 207 FileSystemContext* context, |
| 250 base::PlatformFileError* error_code) const { | 208 base::PlatformFileError* error_code) const { |
| 251 if (!IsAccessValid(url)) { | 209 DCHECK(sandbox_context_); |
| 210 if (!sandbox_context_->IsAccessValid(url)) { |
| 252 *error_code = base::PLATFORM_FILE_ERROR_SECURITY; | 211 *error_code = base::PLATFORM_FILE_ERROR_SECURITY; |
| 253 return NULL; | 212 return NULL; |
| 254 } | 213 } |
| 255 | 214 |
| 256 scoped_ptr<FileSystemOperationContext> operation_context( | 215 scoped_ptr<FileSystemOperationContext> operation_context( |
| 257 new FileSystemOperationContext(context)); | 216 new FileSystemOperationContext(context)); |
| 258 | 217 |
| 259 // Copy the observer lists (assuming we only have small number of observers). | 218 // Copy the observer lists (assuming we only have small number of observers). |
| 260 if (url.type() == kFileSystemTypeSyncable) { | 219 if (url.type() == kFileSystemTypeSyncable) { |
| 261 operation_context->set_update_observers(syncable_update_observers_); | 220 operation_context->set_update_observers(syncable_update_observers_); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 276 | 235 |
| 277 return new LocalFileSystemOperation(url, context, operation_context.Pass()); | 236 return new LocalFileSystemOperation(url, context, operation_context.Pass()); |
| 278 } | 237 } |
| 279 | 238 |
| 280 scoped_ptr<webkit_blob::FileStreamReader> | 239 scoped_ptr<webkit_blob::FileStreamReader> |
| 281 SandboxFileSystemBackend::CreateFileStreamReader( | 240 SandboxFileSystemBackend::CreateFileStreamReader( |
| 282 const FileSystemURL& url, | 241 const FileSystemURL& url, |
| 283 int64 offset, | 242 int64 offset, |
| 284 const base::Time& expected_modification_time, | 243 const base::Time& expected_modification_time, |
| 285 FileSystemContext* context) const { | 244 FileSystemContext* context) const { |
| 286 if (!IsAccessValid(url)) | 245 DCHECK(sandbox_context_); |
| 246 if (!sandbox_context_->IsAccessValid(url)) |
| 287 return scoped_ptr<webkit_blob::FileStreamReader>(); | 247 return scoped_ptr<webkit_blob::FileStreamReader>(); |
| 288 return scoped_ptr<webkit_blob::FileStreamReader>( | 248 return scoped_ptr<webkit_blob::FileStreamReader>( |
| 289 new FileSystemFileStreamReader( | 249 new FileSystemFileStreamReader( |
| 290 context, url, offset, expected_modification_time)); | 250 context, url, offset, expected_modification_time)); |
| 291 } | 251 } |
| 292 | 252 |
| 293 scoped_ptr<fileapi::FileStreamWriter> | 253 scoped_ptr<fileapi::FileStreamWriter> |
| 294 SandboxFileSystemBackend::CreateFileStreamWriter( | 254 SandboxFileSystemBackend::CreateFileStreamWriter( |
| 295 const FileSystemURL& url, | 255 const FileSystemURL& url, |
| 296 int64 offset, | 256 int64 offset, |
| 297 FileSystemContext* context) const { | 257 FileSystemContext* context) const { |
| 298 if (!IsAccessValid(url)) | 258 DCHECK(sandbox_context_); |
| 259 if (!sandbox_context_->IsAccessValid(url)) |
| 299 return scoped_ptr<fileapi::FileStreamWriter>(); | 260 return scoped_ptr<fileapi::FileStreamWriter>(); |
| 300 return scoped_ptr<fileapi::FileStreamWriter>( | 261 return scoped_ptr<fileapi::FileStreamWriter>( |
| 301 new SandboxFileStreamWriter(context, url, offset, update_observers_)); | 262 new SandboxFileStreamWriter(context, url, offset, update_observers_)); |
| 302 } | 263 } |
| 303 | 264 |
| 304 FileSystemQuotaUtil* SandboxFileSystemBackend::GetQuotaUtil() { | 265 FileSystemQuotaUtil* SandboxFileSystemBackend::GetQuotaUtil() { |
| 305 return this; | 266 return this; |
| 306 } | 267 } |
| 307 | 268 |
| 308 SandboxFileSystemBackend::OriginEnumerator* | 269 SandboxContext::OriginEnumerator* |
| 309 SandboxFileSystemBackend::CreateOriginEnumerator() { | 270 SandboxFileSystemBackend::CreateOriginEnumerator() { |
| 310 return new ObfuscatedOriginEnumerator(sandbox_sync_file_util()); | 271 DCHECK(sandbox_context_); |
| 311 } | 272 return sandbox_context_->CreateOriginEnumerator(); |
| 312 | |
| 313 base::FilePath SandboxFileSystemBackend::GetBaseDirectoryForOriginAndType( | |
| 314 const GURL& origin_url, fileapi::FileSystemType type, bool create) { | |
| 315 base::PlatformFileError error = base::PLATFORM_FILE_OK; | |
| 316 base::FilePath path = sandbox_sync_file_util()->GetDirectoryForOriginAndType( | |
| 317 origin_url, type, create, &error); | |
| 318 if (error != base::PLATFORM_FILE_OK) | |
| 319 return base::FilePath(); | |
| 320 return path; | |
| 321 } | 273 } |
| 322 | 274 |
| 323 base::PlatformFileError | 275 base::PlatformFileError |
| 324 SandboxFileSystemBackend::DeleteOriginDataOnFileThread( | 276 SandboxFileSystemBackend::DeleteOriginDataOnFileThread( |
| 325 FileSystemContext* file_system_context, | 277 FileSystemContext* file_system_context, |
| 326 QuotaManagerProxy* proxy, | 278 QuotaManagerProxy* proxy, |
| 327 const GURL& origin_url, | 279 const GURL& origin_url, |
| 328 fileapi::FileSystemType type) { | 280 fileapi::FileSystemType type) { |
| 329 int64 usage = GetOriginUsageOnFileThread(file_system_context, | 281 DCHECK(sandbox_context_); |
| 330 origin_url, type); | 282 return sandbox_context_->DeleteOriginDataOnFileThreadImpl( |
| 331 | 283 file_system_context, proxy, origin_url, type); |
| 332 usage_cache()->CloseCacheFiles(); | |
| 333 bool result = sandbox_sync_file_util()->DeleteDirectoryForOriginAndType( | |
| 334 origin_url, type); | |
| 335 if (result && proxy) { | |
| 336 proxy->NotifyStorageModified( | |
| 337 quota::QuotaClient::kFileSystem, | |
| 338 origin_url, | |
| 339 FileSystemTypeToQuotaStorageType(type), | |
| 340 -usage); | |
| 341 } | |
| 342 | |
| 343 if (result) | |
| 344 return base::PLATFORM_FILE_OK; | |
| 345 return base::PLATFORM_FILE_ERROR_FAILED; | |
| 346 } | 284 } |
| 347 | 285 |
| 348 void SandboxFileSystemBackend::GetOriginsForTypeOnFileThread( | 286 void SandboxFileSystemBackend::GetOriginsForTypeOnFileThread( |
| 349 fileapi::FileSystemType type, std::set<GURL>* origins) { | 287 fileapi::FileSystemType type, std::set<GURL>* origins) { |
| 350 DCHECK(CanHandleType(type)); | 288 DCHECK(sandbox_context_); |
| 351 DCHECK(origins); | 289 sandbox_context_->GetOriginsForTypeOnFileThreadImpl(type, origins); |
| 352 scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator()); | |
| 353 GURL origin; | |
| 354 while (!(origin = enumerator->Next()).is_empty()) { | |
| 355 if (enumerator->HasFileSystemType(type)) | |
| 356 origins->insert(origin); | |
| 357 } | |
| 358 switch (type) { | 290 switch (type) { |
| 359 case kFileSystemTypeTemporary: | 291 case kFileSystemTypeTemporary: |
| 360 UMA_HISTOGRAM_COUNTS(kTemporaryOriginsCountLabel, origins->size()); | 292 UMA_HISTOGRAM_COUNTS(kTemporaryOriginsCountLabel, origins->size()); |
| 361 break; | 293 break; |
| 362 case kFileSystemTypePersistent: | 294 case kFileSystemTypePersistent: |
| 363 UMA_HISTOGRAM_COUNTS(kPersistentOriginsCountLabel, origins->size()); | 295 UMA_HISTOGRAM_COUNTS(kPersistentOriginsCountLabel, origins->size()); |
| 364 break; | 296 break; |
| 365 case kFileSystemTypeSyncable: | 297 case kFileSystemTypeSyncable: |
| 366 UMA_HISTOGRAM_COUNTS(kSyncableOriginsCountLabel, origins->size()); | 298 UMA_HISTOGRAM_COUNTS(kSyncableOriginsCountLabel, origins->size()); |
| 367 break; | 299 break; |
| 368 default: | 300 default: |
| 369 break; | 301 break; |
| 370 } | 302 } |
| 371 } | 303 } |
| 372 | 304 |
| 373 void SandboxFileSystemBackend::GetOriginsForHostOnFileThread( | 305 void SandboxFileSystemBackend::GetOriginsForHostOnFileThread( |
| 374 fileapi::FileSystemType type, const std::string& host, | 306 fileapi::FileSystemType type, const std::string& host, |
| 375 std::set<GURL>* origins) { | 307 std::set<GURL>* origins) { |
| 376 DCHECK(CanHandleType(type)); | 308 DCHECK(sandbox_context_); |
| 377 DCHECK(origins); | 309 sandbox_context_->GetOriginsForHostOnFileThreadImpl(type, host, origins); |
| 378 scoped_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator()); | |
| 379 GURL origin; | |
| 380 while (!(origin = enumerator->Next()).is_empty()) { | |
| 381 if (host == net::GetHostOrSpecFromURL(origin) && | |
| 382 enumerator->HasFileSystemType(type)) | |
| 383 origins->insert(origin); | |
| 384 } | |
| 385 } | 310 } |
| 386 | 311 |
| 387 int64 SandboxFileSystemBackend::GetOriginUsageOnFileThread( | 312 int64 SandboxFileSystemBackend::GetOriginUsageOnFileThread( |
| 388 FileSystemContext* file_system_context, | 313 FileSystemContext* file_system_context, |
| 389 const GURL& origin_url, | 314 const GURL& origin_url, |
| 390 fileapi::FileSystemType type) { | 315 fileapi::FileSystemType type) { |
| 391 DCHECK(CanHandleType(type)); | 316 DCHECK(sandbox_context_); |
| 392 if (!sandbox_context_->is_usage_tracking_enabled()) | 317 return sandbox_context_->GetOriginUsageOnFileThreadImpl( |
| 393 return 0; | 318 file_system_context, origin_url, type); |
| 394 | |
| 395 // Don't use usage cache and return recalculated usage for sticky invalidated | |
| 396 // origins. | |
| 397 if (ContainsKey(sticky_dirty_origins_, std::make_pair(origin_url, type))) | |
| 398 return RecalculateUsage(file_system_context, origin_url, type); | |
| 399 | |
| 400 base::FilePath base_path = | |
| 401 GetBaseDirectoryForOriginAndType(origin_url, type, false); | |
| 402 if (base_path.empty() || !base::DirectoryExists(base_path)) | |
| 403 return 0; | |
| 404 base::FilePath usage_file_path = | |
| 405 base_path.Append(FileSystemUsageCache::kUsageFileName); | |
| 406 | |
| 407 bool is_valid = usage_cache()->IsValid(usage_file_path); | |
| 408 uint32 dirty_status = 0; | |
| 409 bool dirty_status_available = | |
| 410 usage_cache()->GetDirty(usage_file_path, &dirty_status); | |
| 411 bool visited = !visited_origins_.insert(origin_url).second; | |
| 412 if (is_valid && (dirty_status == 0 || (dirty_status_available && visited))) { | |
| 413 // The usage cache is clean (dirty == 0) or the origin is already | |
| 414 // initialized and running. Read the cache file to get the usage. | |
| 415 int64 usage = 0; | |
| 416 return usage_cache()->GetUsage(usage_file_path, &usage) ? usage : -1; | |
| 417 } | |
| 418 // The usage cache has not been initialized or the cache is dirty. | |
| 419 // Get the directory size now and update the cache. | |
| 420 usage_cache()->Delete(usage_file_path); | |
| 421 | |
| 422 int64 usage = RecalculateUsage(file_system_context, origin_url, type); | |
| 423 | |
| 424 // This clears the dirty flag too. | |
| 425 usage_cache()->UpdateUsage(usage_file_path, usage); | |
| 426 return usage; | |
| 427 } | 319 } |
| 428 | 320 |
| 429 void SandboxFileSystemBackend::InvalidateUsageCache( | 321 void SandboxFileSystemBackend::InvalidateUsageCache( |
| 430 const GURL& origin, | 322 const GURL& origin, |
| 431 fileapi::FileSystemType type) { | 323 fileapi::FileSystemType type) { |
| 432 DCHECK(CanHandleType(type)); | 324 DCHECK(sandbox_context_); |
| 433 base::PlatformFileError error = base::PLATFORM_FILE_OK; | 325 sandbox_context_->InvalidateUsageCacheImpl(origin, type); |
| 434 base::FilePath usage_file_path = GetUsageCachePathForOriginAndType( | |
| 435 sandbox_sync_file_util(), origin, type, &error); | |
| 436 if (error != base::PLATFORM_FILE_OK) | |
| 437 return; | |
| 438 usage_cache()->IncrementDirty(usage_file_path); | |
| 439 } | 326 } |
| 440 | 327 |
| 441 void SandboxFileSystemBackend::StickyInvalidateUsageCache( | 328 void SandboxFileSystemBackend::StickyInvalidateUsageCache( |
| 442 const GURL& origin, | 329 const GURL& origin, |
| 443 fileapi::FileSystemType type) { | 330 fileapi::FileSystemType type) { |
| 444 DCHECK(CanHandleType(type)); | 331 DCHECK(sandbox_context_); |
| 445 sticky_dirty_origins_.insert(std::make_pair(origin, type)); | 332 sandbox_context_->StickyInvalidateUsageCacheImpl(origin, type); |
| 446 sandbox_context_->quota_observer()->SetUsageCacheEnabled(origin, type, false); | |
| 447 InvalidateUsageCache(origin, type); | |
| 448 } | 333 } |
| 449 | 334 |
| 450 void SandboxFileSystemBackend::AddFileUpdateObserver( | 335 void SandboxFileSystemBackend::AddFileUpdateObserver( |
| 451 FileSystemType type, | 336 FileSystemType type, |
| 452 FileUpdateObserver* observer, | 337 FileUpdateObserver* observer, |
| 453 base::SequencedTaskRunner* task_runner) { | 338 base::SequencedTaskRunner* task_runner) { |
| 454 DCHECK(CanHandleType(type)); | 339 DCHECK(CanHandleType(type)); |
| 455 UpdateObserverList* list = &update_observers_; | 340 UpdateObserverList* list = &update_observers_; |
| 456 if (type == kFileSystemTypeSyncable) | 341 if (type == kFileSystemTypeSyncable) |
| 457 list = &syncable_update_observers_; | 342 list = &syncable_update_observers_; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 492 return &syncable_change_observers_; | 377 return &syncable_change_observers_; |
| 493 return &change_observers_; | 378 return &change_observers_; |
| 494 } | 379 } |
| 495 | 380 |
| 496 const AccessObserverList* SandboxFileSystemBackend::GetAccessObservers( | 381 const AccessObserverList* SandboxFileSystemBackend::GetAccessObservers( |
| 497 FileSystemType type) const { | 382 FileSystemType type) const { |
| 498 DCHECK(CanHandleType(type)); | 383 DCHECK(CanHandleType(type)); |
| 499 return &access_observers_; | 384 return &access_observers_; |
| 500 } | 385 } |
| 501 | 386 |
| 387 ObfuscatedFileUtil* SandboxFileSystemBackend::sandbox_sync_file_util() { |
| 388 DCHECK(sandbox_context_); |
| 389 return sandbox_context_->sync_file_util(); |
| 390 } |
| 391 |
| 502 void SandboxFileSystemBackend::CollectOpenFileSystemMetrics( | 392 void SandboxFileSystemBackend::CollectOpenFileSystemMetrics( |
| 503 base::PlatformFileError error_code) { | 393 base::PlatformFileError error_code) { |
| 504 base::Time now = base::Time::Now(); | 394 base::Time now = base::Time::Now(); |
| 505 bool throttled = now < next_release_time_for_open_filesystem_stat_; | 395 bool throttled = now < next_release_time_for_open_filesystem_stat_; |
| 506 if (!throttled) { | 396 if (!throttled) { |
| 507 next_release_time_for_open_filesystem_stat_ = | 397 next_release_time_for_open_filesystem_stat_ = |
| 508 now + base::TimeDelta::FromHours(kMinimumStatsCollectionIntervalHours); | 398 now + base::TimeDelta::FromHours(kMinimumStatsCollectionIntervalHours); |
| 509 } | 399 } |
| 510 | 400 |
| 511 #define REPORT(report_value) \ | 401 #define REPORT(report_value) \ |
| (...skipping 17 matching lines...) Expand all Loading... |
| 529 REPORT(kNotFound); | 419 REPORT(kNotFound); |
| 530 break; | 420 break; |
| 531 case base::PLATFORM_FILE_ERROR_FAILED: | 421 case base::PLATFORM_FILE_ERROR_FAILED: |
| 532 default: | 422 default: |
| 533 REPORT(kUnknownError); | 423 REPORT(kUnknownError); |
| 534 break; | 424 break; |
| 535 } | 425 } |
| 536 #undef REPORT | 426 #undef REPORT |
| 537 } | 427 } |
| 538 | 428 |
| 539 bool SandboxFileSystemBackend::IsAccessValid( | |
| 540 const FileSystemURL& url) const { | |
| 541 if (!IsAllowedScheme(url.origin())) | |
| 542 return false; | |
| 543 | |
| 544 if (!CanHandleType(url.type())) | |
| 545 return false; | |
| 546 | |
| 547 if (url.path().ReferencesParent()) | |
| 548 return false; | |
| 549 | |
| 550 // Return earlier if the path is '/', because VirtualPath::BaseName() | |
| 551 // returns '/' for '/' and we fail the "basename != '/'" check below. | |
| 552 // (We exclude '.' because it's disallowed by spec.) | |
| 553 if (VirtualPath::IsRootPath(url.path()) && | |
| 554 url.path() != base::FilePath(base::FilePath::kCurrentDirectory)) | |
| 555 return true; | |
| 556 | |
| 557 // Restricted names specified in | |
| 558 // http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restriction
s | |
| 559 base::FilePath filename = VirtualPath::BaseName(url.path()); | |
| 560 // See if the name is allowed to create. | |
| 561 for (size_t i = 0; i < arraysize(kRestrictedNames); ++i) { | |
| 562 if (filename.value() == kRestrictedNames[i]) | |
| 563 return false; | |
| 564 } | |
| 565 for (size_t i = 0; i < arraysize(kRestrictedChars); ++i) { | |
| 566 if (filename.value().find(kRestrictedChars[i]) != | |
| 567 base::FilePath::StringType::npos) | |
| 568 return false; | |
| 569 } | |
| 570 | |
| 571 return true; | |
| 572 } | |
| 573 | |
| 574 base::FilePath SandboxFileSystemBackend::GetUsageCachePathForOriginAndType( | |
| 575 const GURL& origin_url, | |
| 576 FileSystemType type) { | |
| 577 base::PlatformFileError error; | |
| 578 base::FilePath path = GetUsageCachePathForOriginAndType( | |
| 579 sandbox_sync_file_util(), origin_url, type, &error); | |
| 580 if (error != base::PLATFORM_FILE_OK) | |
| 581 return base::FilePath(); | |
| 582 return path; | |
| 583 } | |
| 584 | |
| 585 // static | |
| 586 base::FilePath SandboxFileSystemBackend::GetUsageCachePathForOriginAndType( | |
| 587 ObfuscatedFileUtil* sandbox_file_util, | |
| 588 const GURL& origin_url, | |
| 589 fileapi::FileSystemType type, | |
| 590 base::PlatformFileError* error_out) { | |
| 591 DCHECK(error_out); | |
| 592 *error_out = base::PLATFORM_FILE_OK; | |
| 593 base::FilePath base_path = sandbox_file_util->GetDirectoryForOriginAndType( | |
| 594 origin_url, type, false /* create */, error_out); | |
| 595 if (*error_out != base::PLATFORM_FILE_OK) | |
| 596 return base::FilePath(); | |
| 597 return base_path.Append(FileSystemUsageCache::kUsageFileName); | |
| 598 } | |
| 599 | |
| 600 bool SandboxFileSystemBackend::IsAllowedScheme(const GURL& url) const { | |
| 601 // Basically we only accept http or https. We allow file:// URLs | |
| 602 // only if --allow-file-access-from-files flag is given. | |
| 603 if (url.SchemeIs("http") || url.SchemeIs("https")) | |
| 604 return true; | |
| 605 if (url.SchemeIsFileSystem()) | |
| 606 return url.inner_url() && IsAllowedScheme(*url.inner_url()); | |
| 607 | |
| 608 for (size_t i = 0; | |
| 609 i < file_system_options_.additional_allowed_schemes().size(); | |
| 610 ++i) { | |
| 611 if (url.SchemeIs( | |
| 612 file_system_options_.additional_allowed_schemes()[i].c_str())) | |
| 613 return true; | |
| 614 } | |
| 615 return false; | |
| 616 } | |
| 617 | |
| 618 ObfuscatedFileUtil* SandboxFileSystemBackend::sandbox_sync_file_util() { | |
| 619 DCHECK(sandbox_context_); | |
| 620 return sandbox_context_->sync_file_util(); | |
| 621 } | |
| 622 | |
| 623 FileSystemUsageCache* SandboxFileSystemBackend::usage_cache() { | |
| 624 DCHECK(sandbox_context_); | |
| 625 return sandbox_context_->usage_cache(); | |
| 626 } | |
| 627 | |
| 628 // static | |
| 629 void SandboxFileSystemBackend::InvalidateUsageCacheOnFileThread( | |
| 630 ObfuscatedFileUtil* file_util, | |
| 631 const GURL& origin, | |
| 632 FileSystemType type, | |
| 633 FileSystemUsageCache* usage_cache) { | |
| 634 base::PlatformFileError error = base::PLATFORM_FILE_OK; | |
| 635 base::FilePath usage_cache_path = GetUsageCachePathForOriginAndType( | |
| 636 file_util, origin, type, &error); | |
| 637 if (error == base::PLATFORM_FILE_OK) | |
| 638 usage_cache->IncrementDirty(usage_cache_path); | |
| 639 } | |
| 640 | |
| 641 int64 SandboxFileSystemBackend::RecalculateUsage(FileSystemContext* context, | |
| 642 const GURL& origin, | |
| 643 FileSystemType type) { | |
| 644 FileSystemOperationContext operation_context(context); | |
| 645 FileSystemURL url = context->CreateCrackedFileSystemURL( | |
| 646 origin, type, base::FilePath()); | |
| 647 scoped_ptr<FileSystemFileUtil::AbstractFileEnumerator> enumerator( | |
| 648 sandbox_sync_file_util()->CreateFileEnumerator( | |
| 649 &operation_context, url, true)); | |
| 650 | |
| 651 base::FilePath file_path_each; | |
| 652 int64 usage = 0; | |
| 653 | |
| 654 while (!(file_path_each = enumerator->Next()).empty()) { | |
| 655 usage += enumerator->Size(); | |
| 656 usage += ObfuscatedFileUtil::ComputeFilePathCost(file_path_each); | |
| 657 } | |
| 658 | |
| 659 return usage; | |
| 660 } | |
| 661 | |
| 662 } // namespace fileapi | 429 } // namespace fileapi |
| OLD | NEW |