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