Home | History | Annotate | Download | only in quota
      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:
     96   virtual ~QuotaEvictionHandler() {}
     97 };
     98 
     99 struct 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.
    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.
    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);
    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 
    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 {
    452   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