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