| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef WEBKIT_BROWSER_QUOTA_QUOTA_MANAGER_H_ | 5 #include "storage/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/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 // WEBKIT_BROWSER_QUOTA_QUOTA_MANAGER_H_ | |
| OLD | NEW |