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