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.
5 #ifndef WEBKIT_BROWSER_QUOTA_QUOTA_MANAGER_H_
6 #define WEBKIT_BROWSER_QUOTA_QUOTA_MANAGER_H_
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"
32 class SequencedTaskRunner;
33 class SingleThreadTaskRunner;
36 namespace quota_internals {
37 class QuotaInternalsProxy;
42 class MockQuotaManager;
44 class QuotaManagerProxy;
45 class QuotaTemporaryStorageEvictor;
48 struct QuotaManagerDeleter;
50 struct WEBKIT_STORAGE_BROWSER_EXPORT UsageAndQuota {
52 int64 global_limited_usage;
54 int64 available_disk_space;
57 UsageAndQuota(int64 usage,
58 int64 global_limited_usage,
60 int64 available_disk_space);
63 // An interface called by QuotaTemporaryStorageEvictor.
64 class WEBKIT_STORAGE_BROWSER_EXPORT QuotaEvictionHandler {
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;
72 // Returns the least recently used origin. It might return empty
73 // GURL when there are no evictable origins.
74 virtual void GetLRUOrigin(
76 const GetLRUOriginCallback& callback) = 0;
78 virtual void EvictOriginData(
81 const EvictOriginDataCallback& callback) = 0;
83 virtual void GetUsageAndQuotaForEviction(
84 const UsageAndQuotaCallback& callback) = 0;
87 virtual ~QuotaEvictionHandler() {}
91 UsageInfo(const std::string& host, StorageType type, int64 usage)
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> {
108 typedef base::Callback<void(QuotaStatusCode,
111 GetUsageAndQuotaCallback;
113 static const int64 kIncognitoDefaultQuotaLimit;
114 static const int64 kNoLimit;
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);
122 // Returns a proxy object that can be used on any thread.
123 QuotaManagerProxy* proxy() { return proxy_.get(); }
125 // Called by clients or webapps. Returns usage per host.
126 void GetUsageInfo(const GetUsageInfoCallback& callback);
128 // Called by Web Apps.
129 // This method is declared as virtual to allow test code to override it.
130 virtual void GetUsageAndQuotaForWebApps(
133 const GetUsageAndQuotaCallback& callback);
135 // Called by StorageClients.
136 // This method is declared as virtual to allow test code to override it.
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(
144 const GetUsageAndQuotaCallback& callback);
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,
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,
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();
170 void SetUsageCacheEnabled(QuotaClient::ID client_id,
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,
184 int quota_client_mask,
185 const StatusCallback& callback);
186 void DeleteHostData(const std::string& host,
188 int quota_client_mask,
189 const StatusCallback& callback);
191 // Called by UI and internal modules.
192 void GetAvailableSpace(const AvailableSpaceCallback& callback);
193 void GetTemporaryGlobalQuota(const QuotaCallback& callback);
195 // Ok to call with NULL callback.
196 void SetTemporaryGlobalOverrideQuota(int64 new_quota,
197 const QuotaCallback& callback);
199 void GetPersistentHostQuota(const std::string& host,
200 const QuotaCallback& callback);
201 void SetPersistentHostQuota(const std::string& host,
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);
211 bool IsTrackingHostUsage(StorageType type, QuotaClient::ID client_id) const;
213 void GetStatistics(std::map<std::string, std::string>* statistics);
215 bool IsStorageUnlimited(const GURL& origin, StorageType type) const;
217 bool CanQueryDiskSize(const GURL& origin) const {
218 return special_storage_policy_.get() &&
219 special_storage_policy_->CanQueryDiskSize(origin);
222 virtual void GetOriginsModifiedSince(StorageType type,
223 base::Time modified_since,
224 const GetOriginsCallback& callback);
226 bool ResetUsageTracker(StorageType type);
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;
232 static const char kDatabaseName[];
234 static const int64 kMinimumPreserveForSystem;
236 static const int kThresholdOfErrorsToBeBlacklisted;
238 static const int kEvictionIntervalInMilliSeconds;
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;
246 virtual ~QuotaManager();
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;
259 class GetUsageInfoTask;
261 class OriginDataDeleter;
262 class HostDataDeleter;
264 class GetModifiedSinceHelper;
265 class DumpQuotaTableHelper;
266 class DumpOriginInfoTableHelper;
268 typedef QuotaDatabase::QuotaTableEntry QuotaTableEntry;
269 typedef QuotaDatabase::OriginInfoTableEntry OriginInfoTableEntry;
270 typedef std::vector<QuotaTableEntry> QuotaTableEntries;
271 typedef std::vector<OriginInfoTableEntry> OriginInfoTableEntries;
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&);
277 typedef base::Callback<void(const QuotaTableEntries&)>
278 DumpQuotaTableCallback;
279 typedef base::Callback<void(const OriginInfoTableEntries&)>
280 DumpOriginInfoTableCallback;
282 struct EvictionContext {
284 virtual ~EvictionContext();
286 StorageType evicted_type;
288 EvictOriginDataCallback evict_origin_data_callback;
291 typedef QuotaEvictionHandler::UsageAndQuotaCallback
292 UsageAndQuotaDispatcherCallback;
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();
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);
305 UsageTracker* GetUsageTracker(StorageType type) const;
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);
311 // These internal methods are separately defined mainly for testing.
312 void NotifyStorageAccessedInternal(
313 QuotaClient::ID client_id,
316 base::Time accessed_time);
317 void NotifyStorageModifiedInternal(
318 QuotaClient::ID client_id,
322 base::Time modified_time);
324 void DumpQuotaTable(const DumpQuotaTableCallback& callback);
325 void DumpOriginInfoTable(const DumpOriginInfoTableCallback& callback);
327 // Methods for eviction logic.
328 void StartEviction();
329 void DeleteOriginFromDatabase(const GURL& origin, StorageType type);
331 void DidOriginDataEvicted(QuotaStatusCode status);
333 void ReportHistogram();
334 void DidGetTemporaryGlobalUsageForHistogram(int64 usage,
335 int64 unlimited_usage);
336 void DidGetPersistentGlobalUsageForHistogram(int64 usage,
337 int64 unlimited_usage);
339 // QuotaEvictionHandler.
340 virtual void GetLRUOrigin(
342 const GetLRUOriginCallback& callback) OVERRIDE;
343 virtual void EvictOriginData(
346 const EvictOriginDataCallback& callback) OVERRIDE;
347 virtual void GetUsageAndQuotaForEviction(
348 const UsageAndQuotaCallback& callback) OVERRIDE;
350 void DidSetTemporaryGlobalOverrideQuota(const QuotaCallback& callback,
351 const int64* new_quota,
353 void DidGetPersistentHostQuota(const std::string& host,
356 void DidSetPersistentHostQuota(const std::string& host,
357 const QuotaCallback& callback,
358 const int64* new_quota,
360 void DidInitialize(int64* temporary_quota_override,
361 int64* desired_available_space,
363 void DidGetLRUOrigin(const GURL* origin,
365 void DidGetInitialTemporaryGlobalQuota(QuotaStatusCode status,
367 void DidInitializeTemporaryOriginsInfo(bool success);
368 void DidGetAvailableSpace(int64 space);
369 void DidDatabaseWork(bool success);
371 void DeleteOnCorrectThread() const;
373 void PostTaskAndReplyWithResultForDBThread(
374 const tracked_objects::Location& from_here,
375 const base::Callback<bool(QuotaDatabase*)>& task,
376 const base::Callback<void(bool)>& reply);
378 const bool is_incognito_;
379 const base::FilePath profile_path_;
381 scoped_refptr<QuotaManagerProxy> proxy_;
383 bool eviction_disabled_;
384 scoped_refptr<base::SingleThreadTaskRunner> io_thread_;
385 scoped_refptr<base::SequencedTaskRunner> db_thread_;
386 mutable scoped_ptr<QuotaDatabase> database_;
388 GetLRUOriginCallback lru_origin_callback_;
389 std::set<GURL> access_notified_origins_;
391 QuotaClientList clients_;
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.
399 scoped_ptr<QuotaTemporaryStorageEvictor> temporary_storage_evictor_;
400 EvictionContext eviction_context_;
402 ClosureQueue db_initialization_callbacks_;
403 AvailableSpaceCallbackQueue available_space_callbacks_;
404 GlobalQuotaCallbackQueue temporary_global_quota_callbacks_;
405 HostQuotaCallbackMap persistent_host_quota_callbacks_;
407 bool temporary_quota_initialized_;
408 int64 temporary_quota_override_;
410 int64 desired_available_space_;
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_;
417 scoped_refptr<SpecialStoragePolicy> special_storage_policy_;
419 base::RepeatingTimer<QuotaManager> histogram_timer_;
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_;
426 base::WeakPtrFactory<QuotaManager> weak_factory_;
428 DISALLOW_COPY_AND_ASSIGN(QuotaManager);
431 struct QuotaManagerDeleter {
432 static void Destruct(const QuotaManager* manager) {
433 manager->DeleteOnCorrectThread();
437 // The proxy may be called and finally released on any thread.
438 class WEBKIT_STORAGE_BROWSER_EXPORT QuotaManagerProxy
439 : public base::RefCountedThreadSafe<QuotaManagerProxy> {
441 virtual void RegisterClient(QuotaClient* client);
442 virtual void NotifyStorageAccessed(QuotaClient::ID client_id,
445 virtual void NotifyStorageModified(QuotaClient::ID client_id,
449 virtual void NotifyOriginInUse(const GURL& origin);
450 virtual void NotifyOriginNoLongerInUse(const GURL& origin);
452 virtual void SetUsageCacheEnabled(QuotaClient::ID client_id,
457 // This method may only be called on the IO thread.
458 // It may return NULL if the manager has already been deleted.
459 QuotaManager* quota_manager() const;
462 friend class QuotaManager;
463 friend class base::RefCountedThreadSafe<QuotaManagerProxy>;
465 QuotaManagerProxy(QuotaManager* manager,
466 base::SingleThreadTaskRunner* io_thread);
467 virtual ~QuotaManagerProxy();
469 QuotaManager* manager_; // only accessed on the io thread
470 scoped_refptr<base::SingleThreadTaskRunner> io_thread_;
472 DISALLOW_COPY_AND_ASSIGN(QuotaManagerProxy);
477 #endif // WEBKIT_BROWSER_QUOTA_QUOTA_MANAGER_H_