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: 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; 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 94 void AddObserver(Observer* observer) { 95 observers_.AddObserver(observer); 96 } 97 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. 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. 148 net::URLRequestContext* request_context() const { return request_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. 156 AppCachePolicy* appcache_policy() const { return appcache_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. 165 AppCacheExecutableHandlerFactory* handler_factory() const { 166 return handler_factory_; 167 } 168 void set_handler_factory( 169 AppCacheExecutableHandlerFactory* factory) { 170 handler_factory_ = factory; 171 } 172 173 quota::SpecialStoragePolicy* special_storage_policy() const { 174 return special_storage_policy_.get(); 175 } 176 void set_special_storage_policy(quota::SpecialStoragePolicy* policy); 177 178 quota::QuotaManagerProxy* quota_manager_proxy() const { 179 return quota_manager_proxy_.get(); 180 } 181 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); 190 AppCacheBackendImpl* GetBackend(int id) const { 191 BackendMap::const_iterator it = backends_.find(id); 192 return (it != backends_.end()) ? it->second : NULL; 193 } 194 195 AppCacheStorage* storage() const { return storage_.get(); } 196 197 // Disables the exit-time deletion of session-only data. 198 void set_force_keep_session_state() { force_keep_session_state_ = true; } 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