| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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_QUOTA_QUOTA_MANAGER_H_ | |
| 6 #define WEBKIT_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/quota/quota_callbacks.h" | |
| 24 #include "webkit/quota/quota_client.h" | |
| 25 #include "webkit/quota/quota_database.h" | |
| 26 #include "webkit/quota/quota_task.h" | |
| 27 #include "webkit/quota/special_storage_policy.h" | |
| 28 #include "webkit/storage/webkit_storage_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_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_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_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_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_QUOTA_QUOTA_MANAGER_H_ | |
| OLD | NEW |