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 3 // found in the LICENSE file. 4 5 #include "webkit/browser/fileapi/sandbox_quota_observer.h" 6 7 #include "base/sequenced_task_runner.h" 8 #include "webkit/browser/fileapi/file_system_url.h" 9 #include "webkit/browser/fileapi/file_system_usage_cache.h" 10 #include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h" 11 #include "webkit/browser/fileapi/timed_task_helper.h" 12 #include "webkit/browser/quota/quota_client.h" 13 #include "webkit/browser/quota/quota_manager.h" 14 #include "webkit/common/fileapi/file_system_util.h" 15 16 namespace fileapi { 17 18 SandboxQuotaObserver::SandboxQuotaObserver( 19 quota::QuotaManagerProxy* quota_manager_proxy, 20 base::SequencedTaskRunner* update_notify_runner, 21 ObfuscatedFileUtil* sandbox_file_util, 22 FileSystemUsageCache* file_system_usage_cache) 23 : quota_manager_proxy_(quota_manager_proxy), 24 update_notify_runner_(update_notify_runner), 25 sandbox_file_util_(sandbox_file_util), 26 file_system_usage_cache_(file_system_usage_cache) {} 27 28 SandboxQuotaObserver::~SandboxQuotaObserver() {} 29 30 void SandboxQuotaObserver::OnStartUpdate(const FileSystemURL& url) { 31 DCHECK(update_notify_runner_->RunsTasksOnCurrentThread()); 32 base::FilePath usage_file_path = GetUsageCachePath(url); 33 if (usage_file_path.empty()) 34 return; 35 file_system_usage_cache_->IncrementDirty(usage_file_path); 36 } 37 38 void SandboxQuotaObserver::OnUpdate(const FileSystemURL& url, 39 int64 delta) { 40 DCHECK(update_notify_runner_->RunsTasksOnCurrentThread()); 41 42 if (quota_manager_proxy_.get()) { 43 quota_manager_proxy_->NotifyStorageModified( 44 quota::QuotaClient::kFileSystem, 45 url.origin(), 46 FileSystemTypeToQuotaStorageType(url.type()), 47 delta); 48 } 49 50 base::FilePath usage_file_path = GetUsageCachePath(url); 51 if (usage_file_path.empty()) 52 return; 53 54 pending_update_notification_[usage_file_path] += delta; 55 if (!delayed_cache_update_helper_) { 56 delayed_cache_update_helper_.reset( 57 new TimedTaskHelper(update_notify_runner_.get())); 58 delayed_cache_update_helper_->Start( 59 FROM_HERE, 60 base::TimeDelta(), // No delay. 61 base::Bind(&SandboxQuotaObserver::ApplyPendingUsageUpdate, 62 base::Unretained(this))); 63 } 64 } 65 66 void SandboxQuotaObserver::OnEndUpdate(const FileSystemURL& url) { 67 DCHECK(update_notify_runner_->RunsTasksOnCurrentThread()); 68 69 base::FilePath usage_file_path = GetUsageCachePath(url); 70 if (usage_file_path.empty()) 71 return; 72 73 PendingUpdateNotificationMap::iterator found = 74 pending_update_notification_.find(usage_file_path); 75 if (found != pending_update_notification_.end()) { 76 UpdateUsageCacheFile(found->first, found->second); 77 pending_update_notification_.erase(found); 78 } 79 80 file_system_usage_cache_->DecrementDirty(usage_file_path); 81 } 82 83 void SandboxQuotaObserver::OnAccess(const FileSystemURL& url) { 84 if (quota_manager_proxy_.get()) { 85 quota_manager_proxy_->NotifyStorageAccessed( 86 quota::QuotaClient::kFileSystem, 87 url.origin(), 88 FileSystemTypeToQuotaStorageType(url.type())); 89 } 90 } 91 92 void SandboxQuotaObserver::SetUsageCacheEnabled( 93 const GURL& origin, 94 FileSystemType type, 95 bool enabled) { 96 if (quota_manager_proxy_.get()) { 97 quota_manager_proxy_->SetUsageCacheEnabled( 98 quota::QuotaClient::kFileSystem, 99 origin, 100 FileSystemTypeToQuotaStorageType(type), 101 enabled); 102 } 103 } 104 105 base::FilePath SandboxQuotaObserver::GetUsageCachePath( 106 const FileSystemURL& url) { 107 DCHECK(sandbox_file_util_); 108 base::PlatformFileError error = base::PLATFORM_FILE_OK; 109 base::FilePath path = 110 SandboxFileSystemBackendDelegate::GetUsageCachePathForOriginAndType( 111 sandbox_file_util_, url.origin(), url.type(), &error); 112 if (error != base::PLATFORM_FILE_OK) { 113 LOG(WARNING) << "Could not get usage cache path for: " 114 << url.DebugString(); 115 return base::FilePath(); 116 } 117 return path; 118 } 119 120 void SandboxQuotaObserver::ApplyPendingUsageUpdate() { 121 delayed_cache_update_helper_.reset(); 122 for (PendingUpdateNotificationMap::iterator itr = 123 pending_update_notification_.begin(); 124 itr != pending_update_notification_.end(); 125 ++itr) { 126 UpdateUsageCacheFile(itr->first, itr->second); 127 } 128 pending_update_notification_.clear(); 129 } 130 131 void SandboxQuotaObserver::UpdateUsageCacheFile( 132 const base::FilePath& usage_file_path, 133 int64 delta) { 134 DCHECK(!usage_file_path.empty()); 135 if (!usage_file_path.empty() && delta != 0) 136 file_system_usage_cache_->AtomicUpdateUsageByDelta(usage_file_path, delta); 137 } 138 139 } // namespace fileapi 140