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/webkit_storage_browser_export.h"
     29 
     30 namespace base {
     31 class FilePath;
     32 class SequencedTaskRunner;
     33 class SingleThreadTaskRunner;
     34 }
     35 
     36 namespace quota_internals {
     37 class QuotaInternalsProxy;
     38 }
     39 
     40 namespace quota {
     41 
     42 class MockQuotaManager;
     43 class QuotaDatabase;
     44 class QuotaManagerProxy;
     45 class QuotaTemporaryStorageEvictor;
     46 class UsageTracker;
     47 
     48 struct QuotaManagerDeleter;
     49 
     50 struct WEBKIT_STORAGE_BROWSER_EXPORT UsageAndQuota {
     51   int64 usage;
     52   int64 global_limited_usage;
     53   int64 quota;
     54   int64 available_disk_space;
     55 
     56   UsageAndQuota();
     57   UsageAndQuota(int64 usage,
     58                 int64 global_limited_usage,
     59                 int64 quota,
     60                 int64 available_disk_space);
     61 };
     62 
     63 // An interface called by QuotaTemporaryStorageEvictor.
     64 class WEBKIT_STORAGE_BROWSER_EXPORT QuotaEvictionHandler {
     65  public:
     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;
     71 
     72   // Returns the least recently used origin.  It might return empty
     73   // GURL when there are no evictable origins.
     74   virtual void GetLRUOrigin(
     75       StorageType type,
     76       const GetLRUOriginCallback& callback) = 0;
     77 
     78   virtual void EvictOriginData(
     79       const GURL& origin,
     80       StorageType type,
     81       const EvictOriginDataCallback& callback) = 0;
     82 
     83   virtual void GetUsageAndQuotaForEviction(
     84       const UsageAndQuotaCallback& callback) = 0;
     85 
     86  protected:
     87   virtual ~QuotaEvictionHandler() {}
     88 };
     89 
     90 struct UsageInfo {
     91   UsageInfo(const std::string& host, StorageType type, int64 usage)
     92       : host(host),
     93         type(type),
     94         usage(usage) {}
     95   std::string host;
     96   StorageType type;
     97   int64 usage;
     98 };
     99 
    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> {
    107  public:
    108   typedef base::Callback<void(QuotaStatusCode,
    109                               int64 /* usage */,
    110                               int64 /* quota */)>
    111       GetUsageAndQuotaCallback;
    112 
    113   static const int64 kIncognitoDefaultQuotaLimit;
    114   static const int64 kNoLimit;
    115 
    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);
    121 
    122   // Returns a proxy object that can be used on any thread.
    123   QuotaManagerProxy* proxy() { return proxy_.get(); }
    124 
    125   // Called by clients or webapps. Returns usage per host.
    126   void GetUsageInfo(const GetUsageInfoCallback& callback);
    127 
    128   // Called by Web Apps.
    129   // This method is declared as virtual to allow test code to override it.
    130   virtual void GetUsageAndQuotaForWebApps(
    131       const GURL& origin,
    132       StorageType type,
    133       const GetUsageAndQuotaCallback& callback);
    134 
    135   // Called by StorageClients.
    136   // This method is declared as virtual to allow test code to override it.
    137   //
    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(
    142       const GURL& origin,
    143       StorageType type,
    144       const GetUsageAndQuotaCallback& callback);
    145 
    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,
    150                              const GURL& origin,
    151                              StorageType type);
    152 
    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,
    157                              const GURL& origin,
    158                              StorageType type,
    159                              int64 delta);
    160 
    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();
    168   }
    169 
    170   void SetUsageCacheEnabled(QuotaClient::ID client_id,
    171                             const GURL& origin,
    172                             StorageType type,
    173                             bool enabled);
    174 
    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,
    183                                 StorageType type,
    184                                 int quota_client_mask,
    185                                 const StatusCallback& callback);
    186   void DeleteHostData(const std::string& host,
    187                       StorageType type,
    188                       int quota_client_mask,
    189                       const StatusCallback& callback);
    190 
    191   // Called by UI and internal modules.
    192   void GetAvailableSpace(const AvailableSpaceCallback& callback);
    193   void GetTemporaryGlobalQuota(const QuotaCallback& callback);
    194 
    195   // Ok to call with NULL callback.
    196   void SetTemporaryGlobalOverrideQuota(int64 new_quota,
    197                                        const QuotaCallback& callback);
    198 
    199   void GetPersistentHostQuota(const std::string& host,
    200                               const QuotaCallback& callback);
    201   void SetPersistentHostQuota(const std::string& host,
    202                               int64 new_quota,
    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);
    210 
    211   bool IsTrackingHostUsage(StorageType type, QuotaClient::ID client_id) const;
    212 
    213   void GetStatistics(std::map<std::string, std::string>* statistics);
    214 
    215   bool IsStorageUnlimited(const GURL& origin, StorageType type) const;
    216 
    217   bool CanQueryDiskSize(const GURL& origin) const {
    218     return special_storage_policy_.get() &&
    219            special_storage_policy_->CanQueryDiskSize(origin);
    220   }
    221 
    222   virtual void GetOriginsModifiedSince(StorageType type,
    223                                        base::Time modified_since,
    224                                        const GetOriginsCallback& callback);
    225 
    226   bool ResetUsageTracker(StorageType type);
    227 
    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;
    231 
    232   static const char kDatabaseName[];
    233 
    234   static const int64 kMinimumPreserveForSystem;
    235 
    236   static const int kThresholdOfErrorsToBeBlacklisted;
    237 
    238   static const int kEvictionIntervalInMilliSeconds;
    239 
    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;
    244 
    245  protected:
    246   virtual ~QuotaManager();
    247 
    248  private:
    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;
    258 
    259   class GetUsageInfoTask;
    260 
    261   class OriginDataDeleter;
    262   class HostDataDeleter;
    263 
    264   class GetModifiedSinceHelper;
    265   class DumpQuotaTableHelper;
    266   class DumpOriginInfoTableHelper;
    267 
    268   typedef QuotaDatabase::QuotaTableEntry QuotaTableEntry;
    269   typedef QuotaDatabase::OriginInfoTableEntry OriginInfoTableEntry;
    270   typedef std::vector<QuotaTableEntry> QuotaTableEntries;
    271   typedef std::vector<OriginInfoTableEntry> OriginInfoTableEntries;
    272 
    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&);
    276 
    277   typedef base::Callback<void(const QuotaTableEntries&)>
    278       DumpQuotaTableCallback;
    279   typedef base::Callback<void(const OriginInfoTableEntries&)>
    280       DumpOriginInfoTableCallback;
    281 
    282   struct EvictionContext {
    283     EvictionContext();
    284     virtual ~EvictionContext();
    285     GURL evicted_origin;
    286     StorageType evicted_type;
    287 
    288     EvictOriginDataCallback evict_origin_data_callback;
    289   };
    290 
    291   typedef QuotaEvictionHandler::UsageAndQuotaCallback
    292       UsageAndQuotaDispatcherCallback;
    293 
    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();
    299 
    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);
    304 
    305   UsageTracker* GetUsageTracker(StorageType type) const;
    306 
    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);
    310 
    311   // These internal methods are separately defined mainly for testing.
    312   void NotifyStorageAccessedInternal(
    313       QuotaClient::ID client_id,
    314       const GURL& origin,
    315       StorageType type,
    316       base::Time accessed_time);
    317   void NotifyStorageModifiedInternal(
    318       QuotaClient::ID client_id,
    319       const GURL& origin,
    320       StorageType type,
    321       int64 delta,
    322       base::Time modified_time);
    323 
    324   void DumpQuotaTable(const DumpQuotaTableCallback& callback);
    325   void DumpOriginInfoTable(const DumpOriginInfoTableCallback& callback);
    326 
    327   // Methods for eviction logic.
    328   void StartEviction();
    329   void DeleteOriginFromDatabase(const GURL& origin, StorageType type);
    330 
    331   void DidOriginDataEvicted(QuotaStatusCode status);
    332 
    333   void ReportHistogram();
    334   void DidGetTemporaryGlobalUsageForHistogram(int64 usage,
    335                                               int64 unlimited_usage);
    336   void DidGetPersistentGlobalUsageForHistogram(int64 usage,
    337                                                int64 unlimited_usage);
    338 
    339   // QuotaEvictionHandler.
    340   virtual void GetLRUOrigin(
    341       StorageType type,
    342       const GetLRUOriginCallback& callback) OVERRIDE;
    343   virtual void EvictOriginData(
    344       const GURL& origin,
    345       StorageType type,
    346       const EvictOriginDataCallback& callback) OVERRIDE;
    347   virtual void GetUsageAndQuotaForEviction(
    348       const UsageAndQuotaCallback& callback) OVERRIDE;
    349 
    350   void DidSetTemporaryGlobalOverrideQuota(const QuotaCallback& callback,
    351                                           const int64* new_quota,
    352                                           bool success);
    353   void DidGetPersistentHostQuota(const std::string& host,
    354                                  const int64* quota,
    355                                  bool success);
    356   void DidSetPersistentHostQuota(const std::string& host,
    357                                  const QuotaCallback& callback,
    358                                  const int64* new_quota,
    359                                  bool success);
    360   void DidInitialize(int64* temporary_quota_override,
    361                      int64* desired_available_space,
    362                      bool success);
    363   void DidGetLRUOrigin(const GURL* origin,
    364                        bool success);
    365   void DidGetInitialTemporaryGlobalQuota(QuotaStatusCode status,
    366                                          int64 quota_unused);
    367   void DidInitializeTemporaryOriginsInfo(bool success);
    368   void DidGetAvailableSpace(int64 space);
    369   void DidDatabaseWork(bool success);
    370 
    371   void DeleteOnCorrectThread() const;
    372 
    373   void PostTaskAndReplyWithResultForDBThread(
    374       const tracked_objects::Location& from_here,
    375       const base::Callback<bool(QuotaDatabase*)>& task,
    376       const base::Callback<void(bool)>& reply);
    377 
    378   const bool is_incognito_;
    379   const base::FilePath profile_path_;
    380 
    381   scoped_refptr<QuotaManagerProxy> proxy_;
    382   bool db_disabled_;
    383   bool eviction_disabled_;
    384   scoped_refptr<base::SingleThreadTaskRunner> io_thread_;
    385   scoped_refptr<base::SequencedTaskRunner> db_thread_;
    386   mutable scoped_ptr<QuotaDatabase> database_;
    387 
    388   GetLRUOriginCallback lru_origin_callback_;
    389   std::set<GURL> access_notified_origins_;
    390 
    391   QuotaClientList clients_;
    392 
    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.
    398 
    399   scoped_ptr<QuotaTemporaryStorageEvictor> temporary_storage_evictor_;
    400   EvictionContext eviction_context_;
    401 
    402   ClosureQueue db_initialization_callbacks_;
    403   AvailableSpaceCallbackQueue available_space_callbacks_;
    404   GlobalQuotaCallbackQueue temporary_global_quota_callbacks_;
    405   HostQuotaCallbackMap persistent_host_quota_callbacks_;
    406 
    407   bool temporary_quota_initialized_;
    408   int64 temporary_quota_override_;
    409 
    410   int64 desired_available_space_;
    411 
    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_;
    416 
    417   scoped_refptr<SpecialStoragePolicy> special_storage_policy_;
    418 
    419   base::RepeatingTimer<QuotaManager> histogram_timer_;
    420 
    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_;
    425 
    426   base::WeakPtrFactory<QuotaManager> weak_factory_;
    427 
    428   DISALLOW_COPY_AND_ASSIGN(QuotaManager);
    429 };
    430 
    431 struct QuotaManagerDeleter {
    432   static void Destruct(const QuotaManager* manager) {
    433     manager->DeleteOnCorrectThread();
    434   }
    435 };
    436 
    437 // The proxy may be called and finally released on any thread.
    438 class WEBKIT_STORAGE_BROWSER_EXPORT QuotaManagerProxy
    439     : public base::RefCountedThreadSafe<QuotaManagerProxy> {
    440  public:
    441   typedef QuotaManager::GetUsageAndQuotaCallback
    442       GetUsageAndQuotaCallback;
    443 
    444   virtual void RegisterClient(QuotaClient* client);
    445   virtual void NotifyStorageAccessed(QuotaClient::ID client_id,
    446                                      const GURL& origin,
    447                                      StorageType type);
    448   virtual void NotifyStorageModified(QuotaClient::ID client_id,
    449                                      const GURL& origin,
    450                                      StorageType type,
    451                                      int64 delta);
    452   virtual void NotifyOriginInUse(const GURL& origin);
    453   virtual void NotifyOriginNoLongerInUse(const GURL& origin);
    454 
    455   virtual void SetUsageCacheEnabled(QuotaClient::ID client_id,
    456                                     const GURL& origin,
    457                                     StorageType type,
    458                                     bool enabled);
    459   virtual void GetUsageAndQuota(
    460       base::SequencedTaskRunner* original_task_runner,
    461       const GURL& origin,
    462       StorageType type,
    463       const GetUsageAndQuotaCallback& callback);
    464 
    465   // This method may only be called on the IO thread.
    466   // It may return NULL if the manager has already been deleted.
    467   QuotaManager* quota_manager() const;
    468 
    469  protected:
    470   friend class QuotaManager;
    471   friend class base::RefCountedThreadSafe<QuotaManagerProxy>;
    472 
    473   QuotaManagerProxy(QuotaManager* manager,
    474                     base::SingleThreadTaskRunner* io_thread);
    475   virtual ~QuotaManagerProxy();
    476 
    477   QuotaManager* manager_;  // only accessed on the io thread
    478   scoped_refptr<base::SingleThreadTaskRunner> io_thread_;
    479 
    480   DISALLOW_COPY_AND_ASSIGN(QuotaManagerProxy);
    481 };
    482 
    483 }  // namespace quota
    484 
    485 #endif  // WEBKIT_BROWSER_QUOTA_QUOTA_MANAGER_H_
    486