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 void GetHostUsage(const std::string& host, StorageType type, 208 QuotaClient::ID client_id, 209 const UsageCallback& callback); 210 211 bool IsTrackingHostUsage(StorageType type, QuotaClient::ID client_id) const; 212 213 void GetStatistics(std::map<std::string, std::string>* statistics); 214 215 bool IsStorageUnlimited(const GURL& origin, StorageType type) const; 216 217 bool CanQueryDiskSize(const GURL& origin) const { 218 return special_storage_policy_.get() && 219 special_storage_policy_->CanQueryDiskSize(origin); 220 } 221 222 virtual void GetOriginsModifiedSince(StorageType type, 223 base::Time modified_since, 224 const GetOriginsCallback& callback); 225 226 bool ResetUsageTracker(StorageType type); 227 228 // Determines the portion of the temp pool that can be 229 // utilized by a single host (ie. 5 for 20%). 230 static const int kPerHostTemporaryPortion; 231 232 static const char kDatabaseName[]; 233 234 static const int64 kMinimumPreserveForSystem; 235 236 static const int kThresholdOfErrorsToBeBlacklisted; 237 238 static const int kEvictionIntervalInMilliSeconds; 239 240 // This is kept non-const so that test code can change the value. 241 // TODO(kinuko): Make this a real const value and add a proper way to set 242 // the quota for syncable storage. (http://crbug.com/155488) 243 static int64 kSyncableStorageDefaultHostQuota; 244 245 protected: 246 virtual ~QuotaManager(); 247 248 private: 249 friend class base::DeleteHelper<QuotaManager>; 250 friend class base::RefCountedThreadSafe<QuotaManager, QuotaManagerDeleter>; 251 friend class MockQuotaManager; 252 friend class MockStorageClient; 253 friend class quota_internals::QuotaInternalsProxy; 254 friend class QuotaManagerProxy; 255 friend class QuotaManagerTest; 256 friend class QuotaTemporaryStorageEvictor; 257 friend struct QuotaManagerDeleter; 258 259 class GetUsageInfoTask; 260 261 class OriginDataDeleter; 262 class HostDataDeleter; 263 264 class GetModifiedSinceHelper; 265 class DumpQuotaTableHelper; 266 class DumpOriginInfoTableHelper; 267 268 typedef QuotaDatabase::QuotaTableEntry QuotaTableEntry; 269 typedef QuotaDatabase::OriginInfoTableEntry OriginInfoTableEntry; 270 typedef std::vector<QuotaTableEntry> QuotaTableEntries; 271 typedef std::vector<OriginInfoTableEntry> OriginInfoTableEntries; 272 273 // Function pointer type used to store the function which returns the 274 // available disk space for the disk containing the given FilePath. 275 typedef int64 (*GetAvailableDiskSpaceFn)(const base::FilePath&); 276 277 typedef base::Callback<void(const QuotaTableEntries&)> 278 DumpQuotaTableCallback; 279 typedef base::Callback<void(const OriginInfoTableEntries&)> 280 DumpOriginInfoTableCallback; 281 282 struct EvictionContext { 283 EvictionContext(); 284 virtual ~EvictionContext(); 285 GURL evicted_origin; 286 StorageType evicted_type; 287 288 EvictOriginDataCallback evict_origin_data_callback; 289 }; 290 291 typedef QuotaEvictionHandler::UsageAndQuotaCallback 292 UsageAndQuotaDispatcherCallback; 293 294 // This initialization method is lazily called on the IO thread 295 // when the first quota manager API is called. 296 // Initialize must be called after all quota clients are added to the 297 // manager by RegisterStorage. 298 void LazyInitialize(); 299 300 // Called by clients via proxy. 301 // Registers a quota client to the manager. 302 // The client must remain valid until OnQuotaManagerDestored is called. 303 void RegisterClient(QuotaClient* client); 304 305 UsageTracker* GetUsageTracker(StorageType type) const; 306 307 // Extract cached origins list from the usage tracker. 308 // (Might return empty list if no origin is tracked by the tracker.) 309 void GetCachedOrigins(StorageType type, std::set<GURL>* origins); 310 311 // These internal methods are separately defined mainly for testing. 312 void NotifyStorageAccessedInternal( 313 QuotaClient::ID client_id, 314 const GURL& origin, 315 StorageType type, 316 base::Time accessed_time); 317 void NotifyStorageModifiedInternal( 318 QuotaClient::ID client_id, 319 const GURL& origin, 320 StorageType type, 321 int64 delta, 322 base::Time modified_time); 323 324 void DumpQuotaTable(const DumpQuotaTableCallback& callback); 325 void DumpOriginInfoTable(const DumpOriginInfoTableCallback& callback); 326 327 // Methods for eviction logic. 328 void StartEviction(); 329 void DeleteOriginFromDatabase(const GURL& origin, StorageType type); 330 331 void DidOriginDataEvicted(QuotaStatusCode status); 332 333 void ReportHistogram(); 334 void DidGetTemporaryGlobalUsageForHistogram(int64 usage, 335 int64 unlimited_usage); 336 void DidGetPersistentGlobalUsageForHistogram(int64 usage, 337 int64 unlimited_usage); 338 339 // QuotaEvictionHandler. 340 virtual void GetLRUOrigin( 341 StorageType type, 342 const GetLRUOriginCallback& callback) OVERRIDE; 343 virtual void EvictOriginData( 344 const GURL& origin, 345 StorageType type, 346 const EvictOriginDataCallback& callback) OVERRIDE; 347 virtual void GetUsageAndQuotaForEviction( 348 const UsageAndQuotaCallback& callback) OVERRIDE; 349 350 void DidSetTemporaryGlobalOverrideQuota(const QuotaCallback& callback, 351 const int64* new_quota, 352 bool success); 353 void DidGetPersistentHostQuota(const std::string& host, 354 const int64* quota, 355 bool success); 356 void DidSetPersistentHostQuota(const std::string& host, 357 const QuotaCallback& callback, 358 const int64* new_quota, 359 bool success); 360 void DidInitialize(int64* temporary_quota_override, 361 int64* desired_available_space, 362 bool success); 363 void DidGetLRUOrigin(const GURL* origin, 364 bool success); 365 void DidGetInitialTemporaryGlobalQuota(QuotaStatusCode status, 366 int64 quota_unused); 367 void DidInitializeTemporaryOriginsInfo(bool success); 368 void DidGetAvailableSpace(int64 space); 369 void DidDatabaseWork(bool success); 370 371 void DeleteOnCorrectThread() const; 372 373 void PostTaskAndReplyWithResultForDBThread( 374 const tracked_objects::Location& from_here, 375 const base::Callback<bool(QuotaDatabase*)>& task, 376 const base::Callback<void(bool)>& reply); 377 378 const bool is_incognito_; 379 const base::FilePath profile_path_; 380 381 scoped_refptr<QuotaManagerProxy> proxy_; 382 bool db_disabled_; 383 bool eviction_disabled_; 384 scoped_refptr<base::SingleThreadTaskRunner> io_thread_; 385 scoped_refptr<base::SequencedTaskRunner> db_thread_; 386 mutable scoped_ptr<QuotaDatabase> database_; 387 388 GetLRUOriginCallback lru_origin_callback_; 389 std::set<GURL> access_notified_origins_; 390 391 QuotaClientList clients_; 392 393 scoped_ptr<UsageTracker> temporary_usage_tracker_; 394 scoped_ptr<UsageTracker> persistent_usage_tracker_; 395 scoped_ptr<UsageTracker> syncable_usage_tracker_; 396 // TODO(michaeln): Need a way to clear the cache, drop and 397 // reinstantiate the trackers when they're not handling requests. 398 399 scoped_ptr<QuotaTemporaryStorageEvictor> temporary_storage_evictor_; 400 EvictionContext eviction_context_; 401 402 ClosureQueue db_initialization_callbacks_; 403 AvailableSpaceCallbackQueue available_space_callbacks_; 404 GlobalQuotaCallbackQueue temporary_global_quota_callbacks_; 405 HostQuotaCallbackMap persistent_host_quota_callbacks_; 406 407 bool temporary_quota_initialized_; 408 int64 temporary_quota_override_; 409 410 int64 desired_available_space_; 411 412 // Map from origin to count. 413 std::map<GURL, int> origins_in_use_; 414 // Map from origin to error count. 415 std::map<GURL, int> origins_in_error_; 416 417 scoped_refptr<SpecialStoragePolicy> special_storage_policy_; 418 419 base::RepeatingTimer<QuotaManager> histogram_timer_; 420 421 // Pointer to the function used to get the available disk space. This is 422 // overwritten by QuotaManagerTest in order to attain a deterministic reported 423 // value. The default value points to base::SysInfo::AmountOfFreeDiskSpace. 424 GetAvailableDiskSpaceFn get_disk_space_fn_; 425 426 base::WeakPtrFactory<QuotaManager> weak_factory_; 427 428 DISALLOW_COPY_AND_ASSIGN(QuotaManager); 429 }; 430 431 struct QuotaManagerDeleter { 432 static void Destruct(const QuotaManager* manager) { 433 manager->DeleteOnCorrectThread(); 434 } 435 }; 436 437 // The proxy may be called and finally released on any thread. 438 class WEBKIT_STORAGE_BROWSER_EXPORT QuotaManagerProxy 439 : public base::RefCountedThreadSafe<QuotaManagerProxy> { 440 public: 441 typedef QuotaManager::GetUsageAndQuotaCallback 442 GetUsageAndQuotaCallback; 443 444 virtual void RegisterClient(QuotaClient* client); 445 virtual void NotifyStorageAccessed(QuotaClient::ID client_id, 446 const GURL& origin, 447 StorageType type); 448 virtual void NotifyStorageModified(QuotaClient::ID client_id, 449 const GURL& origin, 450 StorageType type, 451 int64 delta); 452 virtual void NotifyOriginInUse(const GURL& origin); 453 virtual void NotifyOriginNoLongerInUse(const GURL& origin); 454 455 virtual void SetUsageCacheEnabled(QuotaClient::ID client_id, 456 const GURL& origin, 457 StorageType type, 458 bool enabled); 459 virtual void GetUsageAndQuota( 460 base::SequencedTaskRunner* original_task_runner, 461 const GURL& origin, 462 StorageType type, 463 const GetUsageAndQuotaCallback& callback); 464 465 // This method may only be called on the IO thread. 466 // It may return NULL if the manager has already been deleted. 467 QuotaManager* quota_manager() const; 468 469 protected: 470 friend class QuotaManager; 471 friend class base::RefCountedThreadSafe<QuotaManagerProxy>; 472 473 QuotaManagerProxy(QuotaManager* manager, 474 base::SingleThreadTaskRunner* io_thread); 475 virtual ~QuotaManagerProxy(); 476 477 QuotaManager* manager_; // only accessed on the io thread 478 scoped_refptr<base::SingleThreadTaskRunner> io_thread_; 479 480 DISALLOW_COPY_AND_ASSIGN(QuotaManagerProxy); 481 }; 482 483 } // namespace quota 484 485 #endif // WEBKIT_BROWSER_QUOTA_QUOTA_MANAGER_H_ 486