1 // Copyright 2013 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 #ifndef STORAGE_BROWSER_QUOTA_QUOTA_MANAGER_H_ 6 #define STORAGE_BROWSER_QUOTA_QUOTA_MANAGER_H_ 7 8 #include <deque> 9 #include <list> 10 #include <map> 11 #include <set> 12 #include <string> 13 #include <utility> 14 #include <vector> 15 16 #include "base/basictypes.h" 17 #include "base/callback.h" 18 #include "base/files/file_path.h" 19 #include "base/memory/ref_counted.h" 20 #include "base/memory/scoped_ptr.h" 21 #include "base/memory/weak_ptr.h" 22 #include "base/sequenced_task_runner_helpers.h" 23 #include "storage/browser/quota/quota_callbacks.h" 24 #include "storage/browser/quota/quota_client.h" 25 #include "storage/browser/quota/quota_database.h" 26 #include "storage/browser/quota/quota_task.h" 27 #include "storage/browser/quota/special_storage_policy.h" 28 #include "storage/browser/quota/storage_observer.h" 29 #include "storage/browser/storage_browser_export.h" 30 31 namespace base { 32 class FilePath; 33 class SequencedTaskRunner; 34 class SingleThreadTaskRunner; 35 } 36 37 namespace quota_internals { 38 class QuotaInternalsProxy; 39 } 40 41 namespace content { 42 class MockQuotaManager; 43 class MockStorageClient; 44 class QuotaManagerTest; 45 class StorageMonitorTest; 46 47 } 48 49 namespace storage { 50 51 class QuotaDatabase; 52 class QuotaManagerProxy; 53 class QuotaTemporaryStorageEvictor; 54 class StorageMonitor; 55 class UsageTracker; 56 57 struct QuotaManagerDeleter; 58 59 struct STORAGE_EXPORT UsageAndQuota { 60 int64 usage; 61 int64 global_limited_usage; 62 int64 quota; 63 int64 available_disk_space; 64 65 UsageAndQuota(); 66 UsageAndQuota(int64 usage, 67 int64 global_limited_usage, 68 int64 quota, 69 int64 available_disk_space); 70 }; 71 72 // An interface called by QuotaTemporaryStorageEvictor. 73 class STORAGE_EXPORT QuotaEvictionHandler { 74 public: 75 typedef base::Callback<void(const GURL&)> GetLRUOriginCallback; 76 typedef StatusCallback EvictOriginDataCallback; 77 typedef base::Callback<void(QuotaStatusCode status, 78 const UsageAndQuota& usage_and_quota)> 79 UsageAndQuotaCallback; 80 81 // Returns the least recently used origin. It might return empty 82 // GURL when there are no evictable origins. 83 virtual void GetLRUOrigin( 84 StorageType type, 85 const GetLRUOriginCallback& callback) = 0; 86 87 virtual void EvictOriginData( 88 const GURL& origin, 89 StorageType type, 90 const EvictOriginDataCallback& callback) = 0; 91 92 virtual void GetUsageAndQuotaForEviction( 93 const UsageAndQuotaCallback& callback) = 0; 94 95 protected: 96 virtual ~QuotaEvictionHandler() {} 97 }; 98 99 struct UsageInfo { 100 UsageInfo(const std::string& host, StorageType type, int64 usage) 101 : host(host), 102 type(type), 103 usage(usage) {} 104 std::string host; 105 StorageType type; 106 int64 usage; 107 }; 108 109 // The quota manager class. This class is instantiated per profile and 110 // held by the profile. With the exception of the constructor and the 111 // proxy() method, all methods should only be called on the IO thread. 112 class STORAGE_EXPORT QuotaManager 113 : public QuotaTaskObserver, 114 public QuotaEvictionHandler, 115 public base::RefCountedThreadSafe<QuotaManager, QuotaManagerDeleter> { 116 public: 117 typedef base::Callback<void(QuotaStatusCode, 118 int64 /* usage */, 119 int64 /* quota */)> 120 GetUsageAndQuotaCallback; 121 122 static const int64 kIncognitoDefaultQuotaLimit; 123 static const int64 kNoLimit; 124 125 QuotaManager( 126 bool is_incognito, 127 const base::FilePath& profile_path, 128 const scoped_refptr<base::SingleThreadTaskRunner>& io_thread, 129 const scoped_refptr<base::SequencedTaskRunner>& db_thread, 130 const scoped_refptr<SpecialStoragePolicy>& special_storage_policy); 131 132 // Returns a proxy object that can be used on any thread. 133 QuotaManagerProxy* proxy() { return proxy_.get(); } 134 135 // Called by clients or webapps. Returns usage per host. 136 void GetUsageInfo(const GetUsageInfoCallback& callback); 137 138 // Called by Web Apps. 139 // This method is declared as virtual to allow test code to override it. 140 virtual void GetUsageAndQuotaForWebApps( 141 const GURL& origin, 142 StorageType type, 143 const GetUsageAndQuotaCallback& callback); 144 145 // Called by StorageClients. 146 // This method is declared as virtual to allow test code to override it. 147 // 148 // For UnlimitedStorage origins, this version skips usage and quota handling 149 // to avoid extra query cost. 150 // Do not call this method for apps/user-facing code. 151 virtual void GetUsageAndQuota( 152 const GURL& origin, 153 StorageType type, 154 const GetUsageAndQuotaCallback& callback); 155 156 // Called by clients via proxy. 157 // Client storage should call this method when storage is accessed. 158 // Used to maintain LRU ordering. 159 void NotifyStorageAccessed(QuotaClient::ID client_id, 160 const GURL& origin, 161 StorageType type); 162 163 // Called by clients via proxy. 164 // Client storage must call this method whenever they have made any 165 // modifications that change the amount of data stored in their storage. 166 void NotifyStorageModified(QuotaClient::ID client_id, 167 const GURL& origin, 168 StorageType type, 169 int64 delta); 170 171 // Used to avoid evicting origins with open pages. 172 // A call to NotifyOriginInUse must be balanced by a later call 173 // to NotifyOriginNoLongerInUse. 174 void NotifyOriginInUse(const GURL& origin); 175 void NotifyOriginNoLongerInUse(const GURL& origin); 176 bool IsOriginInUse(const GURL& origin) const { 177 return origins_in_use_.find(origin) != origins_in_use_.end(); 178 } 179 180 void SetUsageCacheEnabled(QuotaClient::ID client_id, 181 const GURL& origin, 182 StorageType type, 183 bool enabled); 184 185 // DeleteOriginData and DeleteHostData (surprisingly enough) delete data of a 186 // particular StorageType associated with either a specific origin or set of 187 // origins. Each method additionally requires a |quota_client_mask| which 188 // specifies the types of QuotaClients to delete from the origin. This is 189 // specified by the caller as a bitmask built from QuotaClient::IDs. Setting 190 // the mask to QuotaClient::kAllClientsMask will remove all clients from the 191 // origin, regardless of type. 192 virtual void DeleteOriginData(const GURL& origin, 193 StorageType type, 194 int quota_client_mask, 195 const StatusCallback& callback); 196 void DeleteHostData(const std::string& host, 197 StorageType type, 198 int quota_client_mask, 199 const StatusCallback& callback); 200 201 // Called by UI and internal modules. 202 void GetAvailableSpace(const AvailableSpaceCallback& callback); 203 void GetTemporaryGlobalQuota(const QuotaCallback& callback); 204 205 // Ok to call with NULL callback. 206 void SetTemporaryGlobalOverrideQuota(int64 new_quota, 207 const QuotaCallback& callback); 208 209 void GetPersistentHostQuota(const std::string& host, 210 const QuotaCallback& callback); 211 void SetPersistentHostQuota(const std::string& host, 212 int64 new_quota, 213 const QuotaCallback& callback); 214 void GetGlobalUsage(StorageType type, const GlobalUsageCallback& callback); 215 void GetHostUsage(const std::string& host, StorageType type, 216 const UsageCallback& callback); 217 void GetHostUsage(const std::string& host, StorageType type, 218 QuotaClient::ID client_id, 219 const UsageCallback& callback); 220 221 bool IsTrackingHostUsage(StorageType type, QuotaClient::ID client_id) const; 222 223 void GetStatistics(std::map<std::string, std::string>* statistics); 224 225 bool IsStorageUnlimited(const GURL& origin, StorageType type) const; 226 227 bool CanQueryDiskSize(const GURL& origin) const { 228 return special_storage_policy_.get() && 229 special_storage_policy_->CanQueryDiskSize(origin); 230 } 231 232 virtual void GetOriginsModifiedSince(StorageType type, 233 base::Time modified_since, 234 const GetOriginsCallback& callback); 235 236 bool ResetUsageTracker(StorageType type); 237 238 // Used to register/deregister observers that wish to monitor storage events. 239 void AddStorageObserver(StorageObserver* observer, 240 const StorageObserver::MonitorParams& params); 241 void RemoveStorageObserver(StorageObserver* observer); 242 void RemoveStorageObserverForFilter(StorageObserver* observer, 243 const StorageObserver::Filter& filter); 244 245 // Determines the portion of the temp pool that can be 246 // utilized by a single host (ie. 5 for 20%). 247 static const int kPerHostTemporaryPortion; 248 249 static const int64 kPerHostPersistentQuotaLimit; 250 251 static const char kDatabaseName[]; 252 253 static const int kThresholdOfErrorsToBeBlacklisted; 254 255 static const int kEvictionIntervalInMilliSeconds; 256 257 // These are kept non-const so that test code can change the value. 258 // TODO(kinuko): Make this a real const value and add a proper way to set 259 // the quota for syncable storage. (http://crbug.com/155488) 260 static int64 kMinimumPreserveForSystem; 261 static int64 kSyncableStorageDefaultHostQuota; 262 263 protected: 264 virtual ~QuotaManager(); 265 266 private: 267 friend class base::DeleteHelper<QuotaManager>; 268 friend class base::RefCountedThreadSafe<QuotaManager, QuotaManagerDeleter>; 269 friend class content::QuotaManagerTest; 270 friend class content::StorageMonitorTest; 271 friend class content::MockQuotaManager; 272 friend class content::MockStorageClient; 273 friend class quota_internals::QuotaInternalsProxy; 274 friend class QuotaManagerProxy; 275 friend class QuotaTemporaryStorageEvictor; 276 friend struct QuotaManagerDeleter; 277 278 class GetUsageInfoTask; 279 280 class OriginDataDeleter; 281 class HostDataDeleter; 282 283 class GetModifiedSinceHelper; 284 class DumpQuotaTableHelper; 285 class DumpOriginInfoTableHelper; 286 287 typedef QuotaDatabase::QuotaTableEntry QuotaTableEntry; 288 typedef QuotaDatabase::OriginInfoTableEntry OriginInfoTableEntry; 289 typedef std::vector<QuotaTableEntry> QuotaTableEntries; 290 typedef std::vector<OriginInfoTableEntry> OriginInfoTableEntries; 291 292 // Function pointer type used to store the function which returns the 293 // available disk space for the disk containing the given FilePath. 294 typedef int64 (*GetAvailableDiskSpaceFn)(const base::FilePath&); 295 296 typedef base::Callback<void(const QuotaTableEntries&)> 297 DumpQuotaTableCallback; 298 typedef base::Callback<void(const OriginInfoTableEntries&)> 299 DumpOriginInfoTableCallback; 300 301 struct EvictionContext { 302 EvictionContext(); 303 virtual ~EvictionContext(); 304 GURL evicted_origin; 305 StorageType evicted_type; 306 307 EvictOriginDataCallback evict_origin_data_callback; 308 }; 309 310 typedef QuotaEvictionHandler::UsageAndQuotaCallback 311 UsageAndQuotaDispatcherCallback; 312 313 // This initialization method is lazily called on the IO thread 314 // when the first quota manager API is called. 315 // Initialize must be called after all quota clients are added to the 316 // manager by RegisterStorage. 317 void LazyInitialize(); 318 319 // Called by clients via proxy. 320 // Registers a quota client to the manager. 321 // The client must remain valid until OnQuotaManagerDestored is called. 322 void RegisterClient(QuotaClient* client); 323 324 UsageTracker* GetUsageTracker(StorageType type) const; 325 326 // Extract cached origins list from the usage tracker. 327 // (Might return empty list if no origin is tracked by the tracker.) 328 void GetCachedOrigins(StorageType type, std::set<GURL>* origins); 329 330 // These internal methods are separately defined mainly for testing. 331 void NotifyStorageAccessedInternal( 332 QuotaClient::ID client_id, 333 const GURL& origin, 334 StorageType type, 335 base::Time accessed_time); 336 void NotifyStorageModifiedInternal( 337 QuotaClient::ID client_id, 338 const GURL& origin, 339 StorageType type, 340 int64 delta, 341 base::Time modified_time); 342 343 void DumpQuotaTable(const DumpQuotaTableCallback& callback); 344 void DumpOriginInfoTable(const DumpOriginInfoTableCallback& callback); 345 346 // Methods for eviction logic. 347 void StartEviction(); 348 void DeleteOriginFromDatabase(const GURL& origin, StorageType type); 349 350 void DidOriginDataEvicted(QuotaStatusCode status); 351 352 void ReportHistogram(); 353 void DidGetTemporaryGlobalUsageForHistogram(int64 usage, 354 int64 unlimited_usage); 355 void DidGetPersistentGlobalUsageForHistogram(int64 usage, 356 int64 unlimited_usage); 357 358 // QuotaEvictionHandler. 359 virtual void GetLRUOrigin( 360 StorageType type, 361 const GetLRUOriginCallback& callback) OVERRIDE; 362 virtual void EvictOriginData( 363 const GURL& origin, 364 StorageType type, 365 const EvictOriginDataCallback& callback) OVERRIDE; 366 virtual void GetUsageAndQuotaForEviction( 367 const UsageAndQuotaCallback& callback) OVERRIDE; 368 369 void DidSetTemporaryGlobalOverrideQuota(const QuotaCallback& callback, 370 const int64* new_quota, 371 bool success); 372 void DidGetPersistentHostQuota(const std::string& host, 373 const int64* quota, 374 bool success); 375 void DidSetPersistentHostQuota(const std::string& host, 376 const QuotaCallback& callback, 377 const int64* new_quota, 378 bool success); 379 void DidInitialize(int64* temporary_quota_override, 380 int64* desired_available_space, 381 bool success); 382 void DidGetLRUOrigin(const GURL* origin, 383 bool success); 384 void DidGetInitialTemporaryGlobalQuota(QuotaStatusCode status, 385 int64 quota_unused); 386 void DidInitializeTemporaryOriginsInfo(bool success); 387 void DidGetAvailableSpace(int64 space); 388 void DidDatabaseWork(bool success); 389 390 void DeleteOnCorrectThread() const; 391 392 void PostTaskAndReplyWithResultForDBThread( 393 const tracked_objects::Location& from_here, 394 const base::Callback<bool(QuotaDatabase*)>& task, 395 const base::Callback<void(bool)>& reply); 396 397 const bool is_incognito_; 398 const base::FilePath profile_path_; 399 400 scoped_refptr<QuotaManagerProxy> proxy_; 401 bool db_disabled_; 402 bool eviction_disabled_; 403 scoped_refptr<base::SingleThreadTaskRunner> io_thread_; 404 scoped_refptr<base::SequencedTaskRunner> db_thread_; 405 mutable scoped_ptr<QuotaDatabase> database_; 406 407 GetLRUOriginCallback lru_origin_callback_; 408 std::set<GURL> access_notified_origins_; 409 410 QuotaClientList clients_; 411 412 scoped_ptr<UsageTracker> temporary_usage_tracker_; 413 scoped_ptr<UsageTracker> persistent_usage_tracker_; 414 scoped_ptr<UsageTracker> syncable_usage_tracker_; 415 // TODO(michaeln): Need a way to clear the cache, drop and 416 // reinstantiate the trackers when they're not handling requests. 417 418 scoped_ptr<QuotaTemporaryStorageEvictor> temporary_storage_evictor_; 419 EvictionContext eviction_context_; 420 421 ClosureQueue db_initialization_callbacks_; 422 AvailableSpaceCallbackQueue available_space_callbacks_; 423 GlobalQuotaCallbackQueue temporary_global_quota_callbacks_; 424 HostQuotaCallbackMap persistent_host_quota_callbacks_; 425 426 bool temporary_quota_initialized_; 427 int64 temporary_quota_override_; 428 429 int64 desired_available_space_; 430 431 // Map from origin to count. 432 std::map<GURL, int> origins_in_use_; 433 // Map from origin to error count. 434 std::map<GURL, int> origins_in_error_; 435 436 scoped_refptr<SpecialStoragePolicy> special_storage_policy_; 437 438 base::RepeatingTimer<QuotaManager> histogram_timer_; 439 440 // Pointer to the function used to get the available disk space. This is 441 // overwritten by QuotaManagerTest in order to attain a deterministic reported 442 // value. The default value points to base::SysInfo::AmountOfFreeDiskSpace. 443 GetAvailableDiskSpaceFn get_disk_space_fn_; 444 445 scoped_ptr<StorageMonitor> storage_monitor_; 446 447 base::WeakPtrFactory<QuotaManager> weak_factory_; 448 449 DISALLOW_COPY_AND_ASSIGN(QuotaManager); 450 }; 451 452 struct QuotaManagerDeleter { 453 static void Destruct(const QuotaManager* manager) { 454 manager->DeleteOnCorrectThread(); 455 } 456 }; 457 458 } // namespace storage 459 460 #endif // STORAGE_BROWSER_QUOTA_QUOTA_MANAGER_H_ 461