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