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.
5 #ifndef WEBKIT_QUOTA_QUOTA_MANAGER_H_
6 #define WEBKIT_QUOTA_QUOTA_MANAGER_H_
16 #include "base/basictypes.h"
17 #include "base/callback.h"
18 #include "base/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_client.h"
24 #include "webkit/quota/quota_database.h"
25 #include "webkit/quota/quota_task.h"
26 #include "webkit/quota/special_storage_policy.h"
27 #include "webkit/storage/webkit_storage_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 QuotaAndUsage
{
52 int64 unlimited_usage
;
54 int64 available_disk_space
;
57 // An interface called by QuotaTemporaryStorageEvictor.
58 class WEBKIT_STORAGE_EXPORT QuotaEvictionHandler
{
60 typedef base::Callback
<void(const GURL
&)> GetLRUOriginCallback
;
61 typedef StatusCallback EvictOriginDataCallback
;
62 typedef base::Callback
<void(QuotaStatusCode
,
63 const QuotaAndUsage
& quota_and_usage
)>
64 GetUsageAndQuotaForEvictionCallback
;
66 // Returns the least recently used origin. It might return empty
67 // GURL when there are no evictable origins.
68 virtual void GetLRUOrigin(
70 const GetLRUOriginCallback
& callback
) = 0;
72 virtual void EvictOriginData(
75 const EvictOriginDataCallback
& callback
) = 0;
77 virtual void GetUsageAndQuotaForEviction(
78 const GetUsageAndQuotaForEvictionCallback
& callback
) = 0;
81 virtual ~QuotaEvictionHandler() {}
85 UsageInfo(const std::string
& host
, StorageType type
, int64 usage
)
94 // The quota manager class. This class is instantiated per profile and
95 // held by the profile. With the exception of the constructor and the
96 // proxy() method, all methods should only be called on the IO thread.
97 class WEBKIT_STORAGE_EXPORT QuotaManager
98 : public QuotaTaskObserver
,
99 public QuotaEvictionHandler
,
100 public base::RefCountedThreadSafe
<QuotaManager
, QuotaManagerDeleter
> {
102 typedef base::Callback
<void(QuotaStatusCode
,
105 GetUsageAndQuotaCallback
;
106 static const int64 kNoLimit
;
108 QuotaManager(bool is_incognito
,
109 const FilePath
& profile_path
,
110 base::SingleThreadTaskRunner
* io_thread
,
111 base::SequencedTaskRunner
* db_thread
,
112 SpecialStoragePolicy
* special_storage_policy
);
114 // Returns a proxy object that can be used on any thread.
115 QuotaManagerProxy
* proxy() { return proxy_
.get(); }
117 // Called by clients or webapps. Returns usage per host.
118 void GetUsageInfo(const GetUsageInfoCallback
& callback
);
120 // Called by clients or webapps.
121 // This method is declared as virtual to allow test code to override it.
122 // note: returns host usage and quota
123 virtual void GetUsageAndQuota(const GURL
& origin
,
125 const GetUsageAndQuotaCallback
& callback
);
127 // Called by clients via proxy.
128 // Client storage should call this method when storage is accessed.
129 // Used to maintain LRU ordering.
130 void NotifyStorageAccessed(QuotaClient::ID client_id
,
134 // Called by clients via proxy.
135 // Client storage must call this method whenever they have made any
136 // modifications that change the amount of data stored in their storage.
137 void NotifyStorageModified(QuotaClient::ID client_id
,
142 // Used to avoid evicting origins with open pages.
143 // A call to NotifyOriginInUse must be balanced by a later call
144 // to NotifyOriginNoLongerInUse.
145 void NotifyOriginInUse(const GURL
& origin
);
146 void NotifyOriginNoLongerInUse(const GURL
& origin
);
147 bool IsOriginInUse(const GURL
& origin
) const {
148 return origins_in_use_
.find(origin
) != origins_in_use_
.end();
151 // DeleteOriginData and DeleteHostData (surprisingly enough) delete data of a
152 // particular StorageType associated with either a specific origin or set of
153 // origins. Each method additionally requires a |quota_client_mask| which
154 // specifies the types of QuotaClients to delete from the origin. This is
155 // specified by the caller as a bitmask built from QuotaClient::IDs. Setting
156 // the mask to QuotaClient::kAllClientsMask will remove all clients from the
157 // origin, regardless of type.
158 virtual void DeleteOriginData(const GURL
& origin
,
160 int quota_client_mask
,
161 const StatusCallback
& callback
);
162 void DeleteHostData(const std::string
& host
,
164 int quota_client_mask
,
165 const StatusCallback
& callback
);
167 // Called by UI and internal modules.
168 void GetAvailableSpace(const AvailableSpaceCallback
& callback
);
169 void GetTemporaryGlobalQuota(const QuotaCallback
& callback
);
171 // Ok to call with NULL callback.
172 void SetTemporaryGlobalOverrideQuota(int64 new_quota
,
173 const QuotaCallback
& callback
);
175 void GetPersistentHostQuota(const std::string
& host
,
176 const QuotaCallback
& callback
);
177 void SetPersistentHostQuota(const std::string
& host
,
179 const QuotaCallback
& callback
);
180 void GetGlobalUsage(StorageType type
, const GlobalUsageCallback
& callback
);
181 void GetHostUsage(const std::string
& host
, StorageType type
,
182 const UsageCallback
& callback
);
184 void GetStatistics(std::map
<std::string
, std::string
>* statistics
);
186 bool IsStorageUnlimited(const GURL
& origin
, StorageType type
) const;
188 bool IsInstalledApp(const GURL
& origin
) const {
189 return special_storage_policy_
.get() &&
190 special_storage_policy_
->IsInstalledApp(origin
);
193 virtual void GetOriginsModifiedSince(StorageType type
,
194 base::Time modified_since
,
195 const GetOriginsCallback
& callback
);
197 bool ResetUsageTracker(StorageType type
);
199 // Determines the portion of the temp pool that can be
200 // utilized by a single host (ie. 5 for 20%).
201 static const int kPerHostTemporaryPortion
;
203 static const char kDatabaseName
[];
205 static const int kThresholdOfErrorsToBeBlacklisted
;
207 static const int kEvictionIntervalInMilliSeconds
;
209 // This is kept non-const so that test code can change the value.
210 // TODO(kinuko): Make this a real const value and add a proper way to set
211 // the quota for syncable storage. (http://crbug.com/155488)
212 static int64 kSyncableStorageDefaultHostQuota
;
215 virtual ~QuotaManager();
218 friend class base::DeleteHelper
<QuotaManager
>;
219 friend class base::RefCountedThreadSafe
<QuotaManager
, QuotaManagerDeleter
>;
220 friend class MockQuotaManager
;
221 friend class MockStorageClient
;
222 friend class quota_internals::QuotaInternalsProxy
;
223 friend class QuotaManagerProxy
;
224 friend class QuotaManagerTest
;
225 friend class QuotaTemporaryStorageEvictor
;
226 friend struct QuotaManagerDeleter
;
228 class GetUsageInfoTask
;
229 class UsageAndQuotaDispatcherTask
;
230 class UsageAndQuotaDispatcherTaskForTemporary
;
231 class UsageAndQuotaDispatcherTaskForPersistent
;
232 class UsageAndQuotaDispatcherTaskForSyncable
;
233 class UsageAndQuotaDispatcherTaskForTemporaryGlobal
;
235 class OriginDataDeleter
;
236 class HostDataDeleter
;
238 class GetModifiedSinceHelper
;
239 class DumpQuotaTableHelper
;
240 class DumpOriginInfoTableHelper
;
242 typedef QuotaDatabase::QuotaTableEntry QuotaTableEntry
;
243 typedef QuotaDatabase::OriginInfoTableEntry OriginInfoTableEntry
;
244 typedef std::vector
<QuotaTableEntry
> QuotaTableEntries
;
245 typedef std::vector
<OriginInfoTableEntry
> OriginInfoTableEntries
;
247 // Function pointer type used to store the function which returns the
248 // available disk space for the disk containing the given FilePath.
249 typedef int64 (*GetAvailableDiskSpaceFn
)(const FilePath
&);
251 typedef base::Callback
<void(const QuotaTableEntries
&)>
252 DumpQuotaTableCallback
;
253 typedef base::Callback
<void(const OriginInfoTableEntries
&)>
254 DumpOriginInfoTableCallback
;
256 struct EvictionContext
{
258 virtual ~EvictionContext();
260 StorageType evicted_type
;
262 EvictOriginDataCallback evict_origin_data_callback
;
265 typedef std::pair
<std::string
, StorageType
> HostAndType
;
266 typedef std::map
<HostAndType
, UsageAndQuotaDispatcherTask
*>
267 UsageAndQuotaDispatcherTaskMap
;
269 typedef QuotaEvictionHandler::GetUsageAndQuotaForEvictionCallback
270 UsageAndQuotaDispatcherCallback
;
272 // This initialization method is lazily called on the IO thread
273 // when the first quota manager API is called.
274 // Initialize must be called after all quota clients are added to the
275 // manager by RegisterStorage.
276 void LazyInitialize();
278 // Called by clients via proxy.
279 // Registers a quota client to the manager.
280 // The client must remain valid until OnQuotaManagerDestored is called.
281 void RegisterClient(QuotaClient
* client
);
283 UsageTracker
* GetUsageTracker(StorageType type
) const;
285 // Extract cached origins list from the usage tracker.
286 // (Might return empty list if no origin is tracked by the tracker.)
287 void GetCachedOrigins(StorageType type
, std::set
<GURL
>* origins
);
289 // These internal methods are separately defined mainly for testing.
290 void NotifyStorageAccessedInternal(
291 QuotaClient::ID client_id
,
294 base::Time accessed_time
);
295 void NotifyStorageModifiedInternal(
296 QuotaClient::ID client_id
,
300 base::Time modified_time
);
302 // |origin| can be empty if |global| is true.
303 void GetUsageAndQuotaInternal(
307 const UsageAndQuotaDispatcherCallback
& callback
);
309 void DumpQuotaTable(const DumpQuotaTableCallback
& callback
);
310 void DumpOriginInfoTable(const DumpOriginInfoTableCallback
& callback
);
312 // Methods for eviction logic.
313 void StartEviction();
314 void DeleteOriginFromDatabase(const GURL
& origin
, StorageType type
);
316 void DidOriginDataEvicted(QuotaStatusCode status
);
318 void ReportHistogram();
319 void DidGetTemporaryGlobalUsageForHistogram(StorageType type
,
321 int64 unlimited_usage
);
322 void DidGetPersistentGlobalUsageForHistogram(StorageType type
,
324 int64 unlimited_usage
);
326 // QuotaEvictionHandler.
327 virtual void GetLRUOrigin(
329 const GetLRUOriginCallback
& callback
) OVERRIDE
;
330 virtual void EvictOriginData(
333 const EvictOriginDataCallback
& callback
) OVERRIDE
;
334 virtual void GetUsageAndQuotaForEviction(
335 const GetUsageAndQuotaForEvictionCallback
& callback
) OVERRIDE
;
337 void DidSetTemporaryGlobalOverrideQuota(const QuotaCallback
& callback
,
338 const int64
* new_quota
,
340 void DidGetPersistentHostQuota(const QuotaCallback
& callback
,
341 const std::string
& host
,
344 void DidSetPersistentHostQuota(const std::string
& host
,
345 const QuotaCallback
& callback
,
346 const int64
* new_quota
,
348 void DidInitialize(int64
* temporary_quota_override
,
349 int64
* desired_available_space
,
351 void DidGetLRUOrigin(const GURL
* origin
,
353 void DidGetInitialTemporaryGlobalQuota(QuotaStatusCode status
,
355 void DidInitializeTemporaryOriginsInfo(bool success
);
356 void DidGetAvailableSpace(const AvailableSpaceCallback
& callback
,
358 void DidDatabaseWork(bool success
);
360 void DeleteOnCorrectThread() const;
362 void PostTaskAndReplyWithResultForDBThread(
363 const tracked_objects::Location
& from_here
,
364 const base::Callback
<bool(QuotaDatabase
*)>& task
,
365 const base::Callback
<void(bool)>& reply
);
367 const bool is_incognito_
;
368 const FilePath profile_path_
;
370 scoped_refptr
<QuotaManagerProxy
> proxy_
;
372 bool eviction_disabled_
;
373 scoped_refptr
<base::SingleThreadTaskRunner
> io_thread_
;
374 scoped_refptr
<base::SequencedTaskRunner
> db_thread_
;
375 mutable scoped_ptr
<QuotaDatabase
> database_
;
377 GetLRUOriginCallback lru_origin_callback_
;
378 std::set
<GURL
> access_notified_origins_
;
380 QuotaClientList clients_
;
382 scoped_ptr
<UsageTracker
> temporary_usage_tracker_
;
383 scoped_ptr
<UsageTracker
> persistent_usage_tracker_
;
384 scoped_ptr
<UsageTracker
> syncable_usage_tracker_
;
385 // TODO(michaeln): Need a way to clear the cache, drop and
386 // reinstantiate the trackers when they're not handling requests.
388 scoped_ptr
<QuotaTemporaryStorageEvictor
> temporary_storage_evictor_
;
389 EvictionContext eviction_context_
;
391 UsageAndQuotaDispatcherTaskMap usage_and_quota_dispatchers_
;
393 bool temporary_quota_initialized_
;
394 int64 temporary_quota_override_
;
396 int64 desired_available_space_
;
398 // Map from origin to count.
399 std::map
<GURL
, int> origins_in_use_
;
400 // Map from origin to error count.
401 std::map
<GURL
, int> origins_in_error_
;
403 scoped_refptr
<SpecialStoragePolicy
> special_storage_policy_
;
405 base::WeakPtrFactory
<QuotaManager
> weak_factory_
;
406 base::RepeatingTimer
<QuotaManager
> histogram_timer_
;
408 // Pointer to the function used to get the available disk space. This is
409 // overwritten by QuotaManagerTest in order to attain a deterministic reported
410 // value. The default value points to base::SysInfo::AmountOfFreeDiskSpace.
411 GetAvailableDiskSpaceFn get_disk_space_fn_
;
413 DISALLOW_COPY_AND_ASSIGN(QuotaManager
);
416 struct QuotaManagerDeleter
{
417 static void Destruct(const QuotaManager
* manager
) {
418 manager
->DeleteOnCorrectThread();
422 // The proxy may be called and finally released on any thread.
423 class WEBKIT_STORAGE_EXPORT QuotaManagerProxy
424 : public base::RefCountedThreadSafe
<QuotaManagerProxy
> {
426 virtual void RegisterClient(QuotaClient
* client
);
427 virtual void NotifyStorageAccessed(QuotaClient::ID client_id
,
430 virtual void NotifyStorageModified(QuotaClient::ID client_id
,
434 virtual void NotifyOriginInUse(const GURL
& origin
);
435 virtual void NotifyOriginNoLongerInUse(const GURL
& origin
);
437 // This method may only be called on the IO thread.
438 // It may return NULL if the manager has already been deleted.
439 QuotaManager
* quota_manager() const;
442 friend class QuotaManager
;
443 friend class base::RefCountedThreadSafe
<QuotaManagerProxy
>;
445 QuotaManagerProxy(QuotaManager
* manager
,
446 base::SingleThreadTaskRunner
* io_thread
);
447 virtual ~QuotaManagerProxy();
449 QuotaManager
* manager_
; // only accessed on the io thread
450 scoped_refptr
<base::SingleThreadTaskRunner
> io_thread_
;
452 DISALLOW_COPY_AND_ASSIGN(QuotaManagerProxy
);
457 #endif // WEBKIT_QUOTA_QUOTA_MANAGER_H_