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 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 
     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 storage {
     50 
     51 class QuotaDatabase;
     52 class QuotaManagerProxy;
     53 class QuotaTemporaryStorageEvictor;
     54 class StorageMonitor;
     55 class UsageTracker;
     56 
     57 struct QuotaManagerDeleter;
     58 
     59 struct 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.
     73 class 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 
     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 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 
    452 struct 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