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 STORAGE_BROWSER_QUOTA_QUOTA_MANAGER_H_
6#define STORAGE_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 "storage/browser/quota/quota_callbacks.h"
24#include "storage/browser/quota/quota_client.h"
25#include "storage/browser/quota/quota_database.h"
26#include "storage/browser/quota/quota_task.h"
27#include "storage/browser/quota/special_storage_policy.h"
28#include "storage/browser/quota/storage_observer.h"
29#include "storage/browser/storage_browser_export.h"
30
31namespace base {
32class FilePath;
33class SequencedTaskRunner;
34class SingleThreadTaskRunner;
35}
36
37namespace quota_internals {
38class QuotaInternalsProxy;
39}
40
41namespace content {
42class MockQuotaManager;
43class MockStorageClient;
44class QuotaManagerTest;
45class StorageMonitorTest;
46
47}
48
49namespace storage {
50
51class QuotaDatabase;
52class QuotaManagerProxy;
53class QuotaTemporaryStorageEvictor;
54class StorageMonitor;
55class UsageTracker;
56
57struct QuotaManagerDeleter;
58
59struct 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.
73class 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
99struct 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.
112class 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
452struct QuotaManagerDeleter {
453  static void Destruct(const QuotaManager* manager) {
454    manager->DeleteOnCorrectThread();
455  }
456};
457
458}  // namespace storage
459
460#endif  // STORAGE_BROWSER_QUOTA_QUOTA_MANAGER_H_
461