Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / content / browser / appcache / appcache_update_job.h
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 CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_JOB_H_
6 #define CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_JOB_H_
7
8 #include <deque>
9 #include <map>
10 #include <set>
11 #include <string>
12 #include <vector>
13
14 #include "base/gtest_prod_util.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/time/time.h"
17 #include "content/browser/appcache/appcache.h"
18 #include "content/browser/appcache/appcache_host.h"
19 #include "content/browser/appcache/appcache_response.h"
20 #include "content/browser/appcache/appcache_service_impl.h"
21 #include "content/browser/appcache/appcache_storage.h"
22 #include "content/common/appcache_interfaces.h"
23 #include "content/common/content_export.h"
24 #include "net/base/completion_callback.h"
25 #include "net/http/http_response_headers.h"
26 #include "net/url_request/url_request.h"
27 #include "url/gurl.h"
28
29 namespace content {
30 FORWARD_DECLARE_TEST(AppCacheGroupTest, QueueUpdate);
31 class AppCacheGroupTest;
32 class AppCacheUpdateJobTest;
33 class HostNotifier;
34
35 // Application cache Update algorithm and state.
36 class CONTENT_EXPORT AppCacheUpdateJob
37     : public AppCacheStorage::Delegate,
38       public AppCacheHost::Observer,
39       public AppCacheServiceImpl::Observer {
40  public:
41   // Used for uma stats only for now, so new values are append only.
42   enum ResultType {
43     UPDATE_OK, DB_ERROR, DISKCACHE_ERROR, QUOTA_ERROR, REDIRECT_ERROR,
44     MANIFEST_ERROR, NETWORK_ERROR, SERVER_ERROR, CANCELLED_ERROR,
45     NUM_UPDATE_JOB_RESULT_TYPES
46   };
47
48   AppCacheUpdateJob(AppCacheServiceImpl* service, AppCacheGroup* group);
49   virtual ~AppCacheUpdateJob();
50
51   // Triggers the update process or adds more info if this update is already
52   // in progress.
53   void StartUpdate(AppCacheHost* host, const GURL& new_master_resource);
54
55  private:
56   friend class content::AppCacheGroupTest;
57   friend class content::AppCacheUpdateJobTest;
58   class URLFetcher;
59
60   // Master entries have multiple hosts, for example, the same page is opened
61   // in different tabs.
62   typedef std::vector<AppCacheHost*> PendingHosts;
63   typedef std::map<GURL, PendingHosts> PendingMasters;
64   typedef std::map<GURL, URLFetcher*> PendingUrlFetches;
65   typedef std::map<int64, GURL> LoadingResponses;
66
67   static const int kRerunDelayMs = 1000;
68
69   // TODO(michaeln): Rework the set of states vs update types vs stored states.
70   // The NO_UPDATE state is really more of an update type. For all update types
71   // storing the results is relevant.
72
73   enum UpdateType {
74     UNKNOWN_TYPE,
75     UPGRADE_ATTEMPT,
76     CACHE_ATTEMPT,
77   };
78
79   enum InternalUpdateState {
80     FETCH_MANIFEST,
81     NO_UPDATE,
82     DOWNLOADING,
83
84     // Every state after this comment indicates the update is terminating.
85     REFETCH_MANIFEST,
86     CACHE_FAILURE,
87     CANCELLED,
88     COMPLETED,
89   };
90
91   enum StoredState {
92     UNSTORED,
93     STORING,
94     STORED,
95   };
96
97   struct UrlToFetch {
98     UrlToFetch(const GURL& url, bool checked, AppCacheResponseInfo* info);
99     ~UrlToFetch();
100
101     GURL url;
102     bool storage_checked;
103     scoped_refptr<AppCacheResponseInfo> existing_response_info;
104   };
105
106   class URLFetcher : public net::URLRequest::Delegate {
107    public:
108     enum FetchType {
109       MANIFEST_FETCH,
110       URL_FETCH,
111       MASTER_ENTRY_FETCH,
112       MANIFEST_REFETCH,
113     };
114     URLFetcher(const GURL& url,
115                FetchType fetch_type,
116                AppCacheUpdateJob* job);
117     virtual ~URLFetcher();
118     void Start();
119     FetchType fetch_type() const { return fetch_type_; }
120     net::URLRequest* request() const { return request_.get(); }
121     const AppCacheEntry& existing_entry() const { return existing_entry_; }
122     const std::string& manifest_data() const { return manifest_data_; }
123     AppCacheResponseWriter* response_writer() const {
124       return response_writer_.get();
125     }
126     void set_existing_response_headers(net::HttpResponseHeaders* headers) {
127       existing_response_headers_ = headers;
128     }
129     void set_existing_entry(const AppCacheEntry& entry) {
130       existing_entry_ = entry;
131     }
132     ResultType result() const { return result_; }
133     int redirect_response_code() const { return redirect_response_code_; }
134
135    private:
136     // URLRequest::Delegate overrides
137     virtual void OnReceivedRedirect(net::URLRequest* request,
138                                     const net::RedirectInfo& redirect_info,
139                                     bool* defer_redirect) OVERRIDE;
140     virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE;
141     virtual void OnReadCompleted(net::URLRequest* request,
142                                  int bytes_read) OVERRIDE;
143
144     void AddConditionalHeaders(const net::HttpResponseHeaders* headers);
145     void OnWriteComplete(int result);
146     void ReadResponseData();
147     bool ConsumeResponseData(int bytes_read);
148     void OnResponseCompleted();
149     bool MaybeRetryRequest();
150
151     GURL url_;
152     AppCacheUpdateJob* job_;
153     FetchType fetch_type_;
154     int retry_503_attempts_;
155     scoped_refptr<net::IOBuffer> buffer_;
156     scoped_ptr<net::URLRequest> request_;
157     AppCacheEntry existing_entry_;
158     scoped_refptr<net::HttpResponseHeaders> existing_response_headers_;
159     std::string manifest_data_;
160     ResultType result_;
161     int redirect_response_code_;
162     scoped_ptr<AppCacheResponseWriter> response_writer_;
163   };  // class URLFetcher
164
165   AppCacheResponseWriter* CreateResponseWriter();
166
167   // Methods for AppCacheStorage::Delegate.
168   virtual void OnResponseInfoLoaded(AppCacheResponseInfo* response_info,
169                                     int64 response_id) OVERRIDE;
170   virtual void OnGroupAndNewestCacheStored(AppCacheGroup* group,
171                                            AppCache* newest_cache,
172                                            bool success,
173                                            bool would_exceed_quota) OVERRIDE;
174   virtual void OnGroupMadeObsolete(AppCacheGroup* group,
175                                    bool success,
176                                    int response_code) OVERRIDE;
177
178   // Methods for AppCacheHost::Observer.
179   virtual void OnCacheSelectionComplete(AppCacheHost* host) OVERRIDE {}  // N/A
180   virtual void OnDestructionImminent(AppCacheHost* host) OVERRIDE;
181
182   // Methods for AppCacheServiceImpl::Observer.
183   virtual void OnServiceReinitialized(
184       AppCacheStorageReference* old_storage) OVERRIDE;
185
186   void HandleCacheFailure(const AppCacheErrorDetails& details,
187                           ResultType result,
188                           const GURL& failed_resource_url);
189
190   void FetchManifest(bool is_first_fetch);
191   void HandleManifestFetchCompleted(URLFetcher* fetcher);
192   void ContinueHandleManifestFetchCompleted(bool changed);
193
194   void HandleUrlFetchCompleted(URLFetcher* fetcher);
195   void HandleMasterEntryFetchCompleted(URLFetcher* fetcher);
196
197   void HandleManifestRefetchCompleted(URLFetcher* fetcher);
198   void OnManifestInfoWriteComplete(int result);
199   void OnManifestDataWriteComplete(int result);
200
201   void StoreGroupAndCache();
202
203   void NotifySingleHost(AppCacheHost* host, AppCacheEventID event_id);
204   void NotifyAllAssociatedHosts(AppCacheEventID event_id);
205   void NotifyAllProgress(const GURL& url);
206   void NotifyAllFinalProgress();
207   void NotifyAllError(const AppCacheErrorDetails& detals);
208   void LogConsoleMessageToAll(const std::string& message);
209   void AddAllAssociatedHostsToNotifier(HostNotifier* notifier);
210
211   // Checks if manifest is byte for byte identical with the manifest
212   // in the newest application cache.
213   void CheckIfManifestChanged();
214   void OnManifestDataReadComplete(int result);
215
216   // Creates the list of files that may need to be fetched and initiates
217   // fetches. Section 6.9.4 steps 12-17
218   void BuildUrlFileList(const AppCacheManifest& manifest);
219   void AddUrlToFileList(const GURL& url, int type);
220   void FetchUrls();
221   void CancelAllUrlFetches();
222   bool ShouldSkipUrlFetch(const AppCacheEntry& entry);
223
224   // If entry already exists in the cache currently being updated, merge
225   // the entry type information with the existing entry.
226   // Returns true if entry exists in cache currently being updated.
227   bool AlreadyFetchedEntry(const GURL& url, int entry_type);
228
229   // TODO(jennb): Delete when update no longer fetches master entries directly.
230   // Creates the list of master entries that need to be fetched and initiates
231   // fetches.
232   void AddMasterEntryToFetchList(AppCacheHost* host, const GURL& url,
233                                  bool is_new);
234   void FetchMasterEntries();
235   void CancelAllMasterEntryFetches(const AppCacheErrorDetails& details);
236
237   // Asynchronously loads the entry from the newest complete cache if the
238   // HTTP caching semantics allow.
239   // Returns false if immediately obvious that data cannot be loaded from
240   // newest complete cache.
241   bool MaybeLoadFromNewestCache(const GURL& url, AppCacheEntry& entry);
242   void LoadFromNewestCacheFailed(const GURL& url,
243                                  AppCacheResponseInfo* newest_response_info);
244
245   // Does nothing if update process is still waiting for pending master
246   // entries or URL fetches to complete downloading. Otherwise, completes
247   // the update process.
248   void MaybeCompleteUpdate();
249
250   // Schedules a rerun of the entire update with the same parameters as
251   // this update job after a short delay.
252   void ScheduleUpdateRetry(int delay_ms);
253
254   void Cancel();
255   void ClearPendingMasterEntries();
256   void DiscardInprogressCache();
257   void DiscardDuplicateResponses();
258
259   void LogHistogramStats(ResultType result, const GURL& failed_resource_url);
260   void MadeProgress() { last_progress_time_ = base::Time::Now(); }
261
262   // Deletes this object after letting the stack unwind.
263   void DeleteSoon();
264
265   bool IsTerminating() { return internal_state_ >= REFETCH_MANIFEST ||
266                                 stored_state_ != UNSTORED; }
267
268   AppCacheServiceImpl* service_;
269   const GURL manifest_url_;  // here for easier access
270
271   // Defined prior to refs to AppCaches and Groups because destruction
272   // order matters, the disabled_storage_reference_ must outlive those
273   // objects.
274   scoped_refptr<AppCacheStorageReference> disabled_storage_reference_;
275
276   scoped_refptr<AppCache> inprogress_cache_;
277
278   AppCacheGroup* group_;
279
280   UpdateType update_type_;
281   InternalUpdateState internal_state_;
282   base::Time last_progress_time_;
283
284   PendingMasters pending_master_entries_;
285   size_t master_entries_completed_;
286
287   // TODO(jennb): Delete when update no longer fetches master entries directly.
288   // Helper containers to track which pending master entries have yet to be
289   // fetched and which are currently being fetched. Master entries that
290   // are listed in the manifest may be fetched as a regular URL instead of
291   // as a separate master entry fetch to optimize against duplicate fetches.
292   std::set<GURL> master_entries_to_fetch_;
293   PendingUrlFetches master_entry_fetches_;
294
295   // URLs of files to fetch along with their flags.
296   AppCache::EntryMap url_file_list_;
297   size_t url_fetches_completed_;
298
299   // Helper container to track which urls have not been fetched yet. URLs are
300   // removed when the fetch is initiated. Flag indicates whether an attempt
301   // to load the URL from storage has already been tried and failed.
302   std::deque<UrlToFetch> urls_to_fetch_;
303
304   // Helper container to track which urls are being loaded from response
305   // storage.
306   LoadingResponses loading_responses_;
307
308   // Keep track of pending URL requests so we can cancel them if necessary.
309   URLFetcher* manifest_fetcher_;
310   PendingUrlFetches pending_url_fetches_;
311
312   // Temporary storage of manifest response data for parsing and comparison.
313   std::string manifest_data_;
314   scoped_ptr<net::HttpResponseInfo> manifest_response_info_;
315   scoped_ptr<AppCacheResponseWriter> manifest_response_writer_;
316   scoped_refptr<net::IOBuffer> read_manifest_buffer_;
317   std::string loaded_manifest_data_;
318   scoped_ptr<AppCacheResponseReader> manifest_response_reader_;
319   bool manifest_has_valid_mime_type_;
320
321   // New master entries added to the cache by this job, used to cleanup
322   // in error conditions.
323   std::vector<GURL> added_master_entries_;
324
325   // Response ids stored by this update job, used to cleanup in
326   // error conditions.
327   std::vector<int64> stored_response_ids_;
328
329   // In some cases we fetch the same resource multiple times, and then
330   // have to delete the duplicates upon successful update. These ids
331   // are also in the stored_response_ids_ collection so we only schedule
332   // these for deletion on success.
333   // TODO(michaeln): Rework when we no longer fetches master entries directly.
334   std::vector<int64> duplicate_response_ids_;
335
336   // Whether we've stored the resulting group/cache yet.
337   StoredState stored_state_;
338
339   AppCacheStorage* storage_;
340
341   FRIEND_TEST_ALL_PREFIXES(content::AppCacheGroupTest, QueueUpdate);
342
343   DISALLOW_COPY_AND_ASSIGN(AppCacheUpdateJob);
344 };
345
346 }  // namespace content
347
348 #endif  // CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_JOB_H_