- add sources.
[platform/framework/web/crosswalk.git] / src / webkit / browser / appcache / appcache_host.h
1 // Copyright (c) 2011 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_HOST_H_
6 #define WEBKIT_BROWSER_APPCACHE_APPCACHE_HOST_H_
7
8 #include "base/callback.h"
9 #include "base/gtest_prod_util.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/observer_list.h"
12 #include "url/gurl.h"
13 #include "webkit/browser/appcache/appcache_group.h"
14 #include "webkit/browser/appcache/appcache_service.h"
15 #include "webkit/browser/appcache/appcache_storage.h"
16 #include "webkit/browser/webkit_storage_browser_export.h"
17 #include "webkit/common/appcache/appcache_interfaces.h"
18 #include "webkit/common/resource_type.h"
19
20 namespace net {
21 class URLRequest;
22 }  // namespace net
23
24 namespace appcache {
25
26 class AppCache;
27 class AppCacheFrontend;
28 class AppCacheRequestHandler;
29
30 typedef base::Callback<void(Status, void*)> GetStatusCallback;
31 typedef base::Callback<void(bool, void*)> StartUpdateCallback;
32 typedef base::Callback<void(bool, void*)> SwapCacheCallback;
33
34 // Server-side representation of an application cache host.
35 class WEBKIT_STORAGE_BROWSER_EXPORT AppCacheHost
36     : public AppCacheStorage::Delegate,
37       public AppCacheGroup::UpdateObserver,
38       public AppCacheService::Observer {
39  public:
40
41   class WEBKIT_STORAGE_BROWSER_EXPORT Observer {
42    public:
43     // Called just after the cache selection algorithm completes.
44     virtual void OnCacheSelectionComplete(AppCacheHost* host) = 0;
45
46     // Called just prior to the instance being deleted.
47     virtual void OnDestructionImminent(AppCacheHost* host) = 0;
48
49     virtual ~Observer() {}
50   };
51
52   AppCacheHost(int host_id, AppCacheFrontend* frontend,
53                AppCacheService* service);
54   virtual ~AppCacheHost();
55
56   // Adds/removes an observer, the AppCacheHost does not take
57   // ownership of the observer.
58   void AddObserver(Observer* observer);
59   void RemoveObserver(Observer* observer);
60
61   // Support for cache selection and scriptable method calls.
62   void SelectCache(const GURL& document_url,
63                    const int64 cache_document_was_loaded_from,
64                    const GURL& manifest_url);
65   void SelectCacheForWorker(int parent_process_id,
66                             int parent_host_id);
67   void SelectCacheForSharedWorker(int64 appcache_id);
68   void MarkAsForeignEntry(const GURL& document_url,
69                           int64 cache_document_was_loaded_from);
70   void GetStatusWithCallback(const GetStatusCallback& callback,
71                              void* callback_param);
72   void StartUpdateWithCallback(const StartUpdateCallback& callback,
73                                void* callback_param);
74   void SwapCacheWithCallback(const SwapCacheCallback& callback,
75                              void* callback_param);
76
77   // Called prior to the main resource load. When the system contains multiple
78   // candidates for a main resource load, the appcache preferred by the host
79   // that created this host is used to break ties.
80   void SetSpawningHostId(int spawning_process_id, int spawning_host_id);
81
82   // May return NULL if the spawning host context has been closed, or if a
83   // spawning host context was never identified.
84   const AppCacheHost* GetSpawningHost() const;
85
86   const GURL& preferred_manifest_url() const {
87     return preferred_manifest_url_;
88   }
89   void set_preferred_manifest_url(const GURL& url) {
90     preferred_manifest_url_ = url;
91   }
92
93   // Support for loading resources out of the appcache.
94   // May return NULL if the request isn't subject to retrieval from an appache.
95   AppCacheRequestHandler* CreateRequestHandler(
96       net::URLRequest* request, ResourceType::Type resource_type);
97
98   // Support for devtools inspecting appcache resources.
99   void GetResourceList(std::vector<AppCacheResourceInfo>* resource_infos);
100
101   // Breaks any existing association between this host and a cache.
102   // 'manifest_url' is sent to DevTools as the manifest url that could have
103   // been associated before or could be associated later with this host.
104   // Associations are broken either thru the cache selection algorithm
105   // implemented in this class, or by the update algorithm (see
106   // AppCacheUpdateJob).
107   void AssociateNoCache(const GURL& manifest_url);
108
109   // Establishes an association between this host and an incomplete cache.
110   // 'manifest_url' is manifest url of the cache group being updated.
111   // Associations with incomplete caches are established by the update algorithm
112   // (see AppCacheUpdateJob).
113   void AssociateIncompleteCache(AppCache* cache, const GURL& manifest_url);
114
115   // Establishes an association between this host and a complete cache.
116   // Associations with complete caches are established either thru the cache
117   // selection algorithm implemented (in this class), or by the update algorithm
118   // (see AppCacheUpdateJob).
119   void AssociateCompleteCache(AppCache* cache);
120
121   // Adds a reference to the newest complete cache in a group, unless it's the
122   // same as the cache that is currently associated with the host.
123   void SetSwappableCache(AppCacheGroup* group);
124
125   // Used to ensure that a loaded appcache survives a frame navigation.
126   void LoadMainResourceCache(int64 cache_id);
127
128   // Used to notify the host that a namespace resource is being delivered as
129   // the main resource of the page and to provide its url.
130   void NotifyMainResourceIsNamespaceEntry(const GURL& namespace_entry_url);
131
132   // Used to notify the host that the main resource was blocked by a policy. To
133   // work properly, this method needs to by invoked prior to cache selection.
134   void NotifyMainResourceBlocked(const GURL& manifest_url);
135
136   // Used by the update job to keep track of which hosts are associated
137   // with which pending master entries.
138   const GURL& pending_master_entry_url() const {
139     return new_master_entry_url_;
140   }
141
142   int host_id() const { return host_id_; }
143   AppCacheService* service() const { return service_; }
144   AppCacheStorage* storage() const { return storage_; }
145   AppCacheFrontend* frontend() const { return frontend_; }
146   AppCache* associated_cache() const { return associated_cache_.get(); }
147
148   bool is_selection_pending() const {
149     return pending_selected_cache_id_ != kNoCacheId ||
150            !pending_selected_manifest_url_.is_empty();
151   }
152
153   const GURL& first_party_url() const { return first_party_url_; }
154
155  private:
156   Status GetStatus();
157   void LoadSelectedCache(int64 cache_id);
158   void LoadOrCreateGroup(const GURL& manifest_url);
159
160   // See public Associate*Host() methods above.
161   void AssociateCacheHelper(AppCache* cache, const GURL& manifest_url);
162
163   // AppCacheStorage::Delegate impl
164   virtual void OnCacheLoaded(AppCache* cache, int64 cache_id) OVERRIDE;
165   virtual void OnGroupLoaded(AppCacheGroup* group,
166                              const GURL& manifest_url) OVERRIDE;
167   // AppCacheService::Observer impl
168   virtual void OnServiceReinitialized(
169       AppCacheStorageReference* old_storage_ref) OVERRIDE;
170
171   void FinishCacheSelection(AppCache* cache, AppCacheGroup* group);
172   void DoPendingGetStatus();
173   void DoPendingStartUpdate();
174   void DoPendingSwapCache();
175
176   void ObserveGroupBeingUpdated(AppCacheGroup* group);
177
178   // AppCacheGroup::UpdateObserver methods.
179   virtual void OnUpdateComplete(AppCacheGroup* group) OVERRIDE;
180
181   // Returns true if this host is for a dedicated worker context.
182   bool is_for_dedicated_worker() const {
183     return parent_host_id_ != kNoHostId;
184   }
185
186   // Returns the parent context's host instance. This is only valid
187   // to call when this instance is_for_dedicated_worker.
188   AppCacheHost* GetParentAppCacheHost() const;
189
190   // Identifies the corresponding appcache host in the child process.
191   int host_id_;
192
193   // Information about the host that created this one; the manifest
194   // preferred by our creator influences which cache our main resource
195   // should be loaded from.
196   int spawning_host_id_;
197   int spawning_process_id_;
198   GURL preferred_manifest_url_;
199
200   // Hosts for dedicated workers are special cased to shunt
201   // request handling off to the dedicated worker's parent.
202   // The scriptable api is not accessible in dedicated workers
203   // so the other aspects of this class are not relevant for
204   // these special case instances.
205   int parent_host_id_;
206   int parent_process_id_;
207
208   // The cache associated with this host, if any.
209   scoped_refptr<AppCache> associated_cache_;
210
211   // Hold a reference to the newest complete cache (if associated cache is
212   // not the newest) to keep the newest cache in existence while the app cache
213   // group is in use. The newest complete cache may have no associated hosts
214   // holding any references to it and would otherwise be deleted prematurely.
215   scoped_refptr<AppCache> swappable_cache_;
216
217   // Keep a reference to the group being updated until the update completes.
218   scoped_refptr<AppCacheGroup> group_being_updated_;
219
220   // Similarly, keep a reference to the newest cache of the group until the
221   // update completes. When adding a new master entry to a cache that is not
222   // in use in any other host, this reference keeps the cache in  memory.
223   scoped_refptr<AppCache> newest_cache_of_group_being_updated_;
224
225   // Keep a reference to the cache of the main resource so it survives frame
226   // navigations.
227   scoped_refptr<AppCache> main_resource_cache_;
228   int64 pending_main_resource_cache_id_;
229
230   // Cache loading is async, if we're loading a specific cache or group
231   // for the purposes of cache selection, one or the other of these will
232   // indicate which cache or group is being loaded.
233   int64 pending_selected_cache_id_;
234   GURL pending_selected_manifest_url_;
235
236   // A new master entry to be added to the cache, may be empty.
237   GURL new_master_entry_url_;
238
239   // The frontend proxy to deliver notifications to the child process.
240   AppCacheFrontend* frontend_;
241
242   // Our central service object.
243   AppCacheService* service_;
244
245   // And the equally central storage object, with a twist. In some error
246   // conditions the storage object gets recreated and reinitialized. The
247   // disabled_reference_ allows for cleanup of an instance that got disabled
248   // after we had latched onto it. In normal circumstances,
249   // disabled_reference_ is expected to be NULL. When non-NULL both
250   // storage_ and disabled_reference_ refer to the same instance.
251   AppCacheStorage* storage_;
252   scoped_refptr<AppCacheStorageReference> disabled_storage_reference_;
253
254   // Since these are synchronous scriptable API calls in the client, there can
255   // only be one type of callback pending. Also, we have to wait until we have a
256   // cache selection prior to responding to these calls, as cache selection
257   // involves async loading of a cache or a group from storage.
258   GetStatusCallback pending_get_status_callback_;
259   StartUpdateCallback pending_start_update_callback_;
260   SwapCacheCallback pending_swap_cache_callback_;
261   void* pending_callback_param_;
262
263   // True if an intercept or fallback namespace resource was
264   // delivered as the main resource.
265   bool main_resource_was_namespace_entry_;
266   GURL namespace_entry_url_;
267
268   // True if requests for this host were blocked by a policy.
269   bool main_resource_blocked_;
270   GURL blocked_manifest_url_;
271
272   // Tells if info about associated cache is pending. Info is pending
273   // when update job has not returned success yet.
274   bool associated_cache_info_pending_;
275
276   // List of objects observing us.
277   ObserverList<Observer> observers_;
278
279   // Used to inform the QuotaManager of what origins are currently in use.
280   GURL origin_in_use_;
281
282   // First party url to be used in policy checks.
283   GURL first_party_url_;
284
285   friend class AppCacheStorageImplTest;
286   friend class AppCacheRequestHandlerTest;
287   friend class AppCacheUpdateJobTest;
288   FRIEND_TEST_ALL_PREFIXES(AppCacheTest, CleanupUnusedCache);
289   FRIEND_TEST_ALL_PREFIXES(AppCacheGroupTest, CleanupUnusedGroup);
290   FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, Basic);
291   FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, SelectNoCache);
292   FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, ForeignEntry);
293   FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, FailedCacheLoad);
294   FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, FailedGroupLoad);
295   FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, SetSwappableCache);
296   FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, ForDedicatedWorker);
297   FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, SelectCacheAllowed);
298   FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, SelectCacheBlocked);
299   FRIEND_TEST_ALL_PREFIXES(AppCacheGroupTest, QueueUpdate);
300
301   DISALLOW_COPY_AND_ASSIGN(AppCacheHost);
302 };
303
304 }  // namespace appcache
305
306 #endif  // WEBKIT_BROWSER_APPCACHE_APPCACHE_HOST_H_