Home | History | Annotate | Download | only in appcache
      1 // Copyright 2014 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 CONTENT_BROWSER_APPCACHE_APPCACHE_SERVICE_IMPL_H_
      6 #define CONTENT_BROWSER_APPCACHE_APPCACHE_SERVICE_IMPL_H_
      7 
      8 #include <map>
      9 #include <set>
     10 
     11 #include "base/gtest_prod_util.h"
     12 #include "base/memory/ref_counted.h"
     13 #include "base/memory/scoped_ptr.h"
     14 #include "base/observer_list.h"
     15 #include "base/time/time.h"
     16 #include "base/timer/timer.h"
     17 #include "content/common/appcache_interfaces.h"
     18 #include "content/common/content_export.h"
     19 #include "content/public/browser/appcache_service.h"
     20 #include "net/base/completion_callback.h"
     21 #include "net/base/net_errors.h"
     22 #include "storage/browser/quota/quota_manager_proxy.h"
     23 
     24 namespace base {
     25 class FilePath;
     26 class SingleThreadTaskRunner;
     27 }  // namespace base
     28 
     29 namespace net {
     30 class URLRequestContext;
     31 }  // namespace net
     32 
     33 namespace storage {
     34 class SpecialStoragePolicy;
     35 }  // namespace storage
     36 
     37 namespace content {
     38 FORWARD_DECLARE_TEST(AppCacheServiceImplTest, ScheduleReinitialize);
     39 class AppCacheBackendImpl;
     40 class AppCacheExecutableHandlerFactory;
     41 class AppCacheQuotaClient;
     42 class AppCachePolicy;
     43 class AppCacheServiceImplTest;
     44 class AppCacheStorageImplTest;
     45 class AppCacheStorage;
     46 
     47 // Refcounted container to manage the lifetime of the old storage instance
     48 // during Reinitialization.
     49 class CONTENT_EXPORT AppCacheStorageReference
     50     : public base::RefCounted<AppCacheStorageReference> {
     51 public:
     52   AppCacheStorage* storage() const { return storage_.get(); }
     53 private:
     54   friend class AppCacheServiceImpl;
     55   friend class base::RefCounted<AppCacheStorageReference>;
     56   AppCacheStorageReference(scoped_ptr<AppCacheStorage> storage);
     57   ~AppCacheStorageReference();
     58 
     59   scoped_ptr<AppCacheStorage> storage_;
     60 };
     61 
     62 // Class that manages the application cache service. Sends notifications
     63 // to many frontends.  One instance per user-profile. Each instance has
     64 // exclusive access to its cache_directory on disk.
     65 class CONTENT_EXPORT AppCacheServiceImpl
     66     : public AppCacheService {
     67  public:
     68 
     69   class CONTENT_EXPORT Observer {
     70    public:
     71     // An observer method to inform consumers of reinitialzation. Managing
     72     // the lifetime of the old storage instance is a delicate process.
     73     // Consumers can keep the old disabled instance alive by hanging on to the
     74     // ref provided.
     75     virtual void OnServiceReinitialized(
     76         AppCacheStorageReference* old_storage_ref) = 0;
     77     virtual ~Observer() {}
     78   };
     79 
     80   // If not using quota management, the proxy may be NULL.
     81   explicit AppCacheServiceImpl(storage::QuotaManagerProxy* quota_manager_proxy);
     82   virtual ~AppCacheServiceImpl();
     83 
     84   void Initialize(
     85       const base::FilePath& cache_directory,
     86       const scoped_refptr<base::SingleThreadTaskRunner>& db_thread,
     87       const scoped_refptr<base::SingleThreadTaskRunner>& cache_thread);
     88 
     89   void AddObserver(Observer* observer) {
     90     observers_.AddObserver(observer);
     91   }
     92 
     93   void RemoveObserver(Observer* observer) {
     94     observers_.RemoveObserver(observer);
     95   }
     96 
     97   // For use in catastrophic failure modes to reboot the appcache system
     98   // without relaunching the browser.
     99   void ScheduleReinitialize();
    100 
    101   // AppCacheService implementation:
    102   virtual void CanHandleMainResourceOffline(
    103       const GURL& url,
    104       const GURL& first_party,
    105       const net::CompletionCallback& callback) OVERRIDE;
    106   virtual void GetAllAppCacheInfo(
    107       AppCacheInfoCollection* collection,
    108       const net::CompletionCallback& callback) OVERRIDE;
    109   virtual void DeleteAppCacheGroup(
    110       const GURL& manifest_url,
    111       const net::CompletionCallback& callback) OVERRIDE;
    112 
    113   // Deletes all appcaches for the origin, 'callback' is invoked upon
    114   // completion. This method always completes asynchronously.
    115   // (virtual for unit testing)
    116   virtual void DeleteAppCachesForOrigin(
    117       const GURL& origin, const net::CompletionCallback& callback);
    118 
    119   // Checks the integrity of 'response_id' by reading the headers and data.
    120   // If it cannot be read, the cache group for 'manifest_url' is deleted.
    121   void CheckAppCacheResponse(const GURL& manifest_url, int64 cache_id,
    122                              int64 response_id);
    123 
    124   // Context for use during cache updates, should only be accessed
    125   // on the IO thread. We do NOT add a reference to the request context,
    126   // it is the callers responsibility to ensure that the pointer
    127   // remains valid while set.
    128   net::URLRequestContext* request_context() const { return request_context_; }
    129   void set_request_context(net::URLRequestContext* context) {
    130     request_context_ = context;
    131   }
    132 
    133   // The appcache policy, may be null, in which case access is always allowed.
    134   // The service does NOT assume ownership of the policy, it is the callers
    135   // responsibility to ensure that the pointer remains valid while set.
    136   AppCachePolicy* appcache_policy() const { return appcache_policy_; }
    137   void set_appcache_policy(AppCachePolicy* policy) {
    138     appcache_policy_ = policy;
    139   }
    140 
    141   // The factory may be null, in which case invocations of exe handlers
    142   // will result in an error response.
    143   // The service does NOT assume ownership of the factory, it is the callers
    144   // responsibility to ensure that the pointer remains valid while set.
    145   AppCacheExecutableHandlerFactory* handler_factory() const {
    146     return handler_factory_;
    147   }
    148   void set_handler_factory(
    149       AppCacheExecutableHandlerFactory* factory) {
    150     handler_factory_ = factory;
    151   }
    152 
    153   storage::SpecialStoragePolicy* special_storage_policy() const {
    154     return special_storage_policy_.get();
    155   }
    156   void set_special_storage_policy(storage::SpecialStoragePolicy* policy);
    157 
    158   storage::QuotaManagerProxy* quota_manager_proxy() const {
    159     return quota_manager_proxy_.get();
    160   }
    161 
    162   AppCacheQuotaClient* quota_client() const {
    163     return quota_client_;
    164   }
    165 
    166   // Each child process in chrome uses a distinct backend instance.
    167   // See chrome/browser/AppCacheDispatcherHost.
    168   void RegisterBackend(AppCacheBackendImpl* backend_impl);
    169   void UnregisterBackend(AppCacheBackendImpl* backend_impl);
    170   AppCacheBackendImpl* GetBackend(int id) const {
    171     BackendMap::const_iterator it = backends_.find(id);
    172     return (it != backends_.end()) ? it->second : NULL;
    173   }
    174 
    175   AppCacheStorage* storage() const { return storage_.get(); }
    176 
    177   // Disables the exit-time deletion of session-only data.
    178   void set_force_keep_session_state() { force_keep_session_state_ = true; }
    179   bool force_keep_session_state() const { return force_keep_session_state_; }
    180 
    181  protected:
    182   friend class content::AppCacheServiceImplTest;
    183   friend class content::AppCacheStorageImplTest;
    184   FRIEND_TEST_ALL_PREFIXES(content::AppCacheServiceImplTest,
    185       ScheduleReinitialize);
    186 
    187   class AsyncHelper;
    188   class CanHandleOfflineHelper;
    189   class DeleteHelper;
    190   class DeleteOriginHelper;
    191   class GetInfoHelper;
    192   class CheckResponseHelper;
    193 
    194   typedef std::set<AsyncHelper*> PendingAsyncHelpers;
    195   typedef std::map<int, AppCacheBackendImpl*> BackendMap;
    196 
    197   void Reinitialize();
    198 
    199   base::FilePath cache_directory_;
    200   scoped_refptr<base::SingleThreadTaskRunner> db_thread_;
    201   scoped_refptr<base::SingleThreadTaskRunner> cache_thread_;
    202   AppCachePolicy* appcache_policy_;
    203   AppCacheQuotaClient* quota_client_;
    204   AppCacheExecutableHandlerFactory* handler_factory_;
    205   scoped_ptr<AppCacheStorage> storage_;
    206   scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
    207   scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
    208   PendingAsyncHelpers pending_helpers_;
    209   BackendMap backends_;  // One 'backend' per child process.
    210   // Context for use during cache updates.
    211   net::URLRequestContext* request_context_;
    212   // If true, nothing (not even session-only data) should be deleted on exit.
    213   bool force_keep_session_state_;
    214   base::Time last_reinit_time_;
    215   base::TimeDelta next_reinit_delay_;
    216   base::OneShotTimer<AppCacheServiceImpl> reinit_timer_;
    217   ObserverList<Observer> observers_;
    218 
    219   DISALLOW_COPY_AND_ASSIGN(AppCacheServiceImpl);
    220 };
    221 
    222 }  // namespace content
    223 
    224 #endif  // CONTENT_BROWSER_APPCACHE_APPCACHE_SERVICE_IMPL_H_
    225