• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
~QuotaEvictionHandler()96   virtual ~QuotaEvictionHandler() {}
97 };
98 
99 struct UsageInfo {
UsageInfoUsageInfo100   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.
proxy()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);
IsOriginInUse(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 
CanQueryDiskSize(const GURL & origin)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 {
DestructQuotaManagerDeleter452   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