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