Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / browser / appcache / appcache_update_job.h
blobe876ad07aa09786120aa3bec4f59871bd7b494c8
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.
5 #ifndef CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_JOB_H_
6 #define CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_JOB_H_
8 #include <deque>
9 #include <map>
10 #include <set>
11 #include <string>
12 #include <vector>
14 #include "base/gtest_prod_util.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/time/time.h"
18 #include "content/browser/appcache/appcache.h"
19 #include "content/browser/appcache/appcache_host.h"
20 #include "content/browser/appcache/appcache_response.h"
21 #include "content/browser/appcache/appcache_service_impl.h"
22 #include "content/browser/appcache/appcache_storage.h"
23 #include "content/common/appcache_interfaces.h"
24 #include "content/common/content_export.h"
25 #include "net/base/completion_callback.h"
26 #include "net/http/http_response_headers.h"
27 #include "net/url_request/url_request.h"
28 #include "url/gurl.h"
30 namespace content {
31 FORWARD_DECLARE_TEST(AppCacheGroupTest, QueueUpdate);
32 class AppCacheGroupTest;
33 class AppCacheUpdateJobTest;
34 class HostNotifier;
36 // Application cache Update algorithm and state.
37 class CONTENT_EXPORT AppCacheUpdateJob
38 : public AppCacheStorage::Delegate,
39 public AppCacheHost::Observer,
40 public AppCacheServiceImpl::Observer {
41 public:
42 // Used for uma stats only for now, so new values are append only.
43 enum ResultType {
44 UPDATE_OK, DB_ERROR, DISKCACHE_ERROR, QUOTA_ERROR, REDIRECT_ERROR,
45 MANIFEST_ERROR, NETWORK_ERROR, SERVER_ERROR, CANCELLED_ERROR,
46 SECURITY_ERROR, NUM_UPDATE_JOB_RESULT_TYPES
49 AppCacheUpdateJob(AppCacheServiceImpl* service, AppCacheGroup* group);
50 ~AppCacheUpdateJob() override;
52 // Triggers the update process or adds more info if this update is already
53 // in progress.
54 void StartUpdate(AppCacheHost* host, const GURL& new_master_resource);
56 private:
57 friend class content::AppCacheGroupTest;
58 friend class content::AppCacheUpdateJobTest;
59 class URLFetcher;
61 // Master entries have multiple hosts, for example, the same page is opened
62 // in different tabs.
63 typedef std::vector<AppCacheHost*> PendingHosts;
64 typedef std::map<GURL, PendingHosts> PendingMasters;
65 typedef std::map<GURL, URLFetcher*> PendingUrlFetches;
66 typedef std::map<int64, GURL> LoadingResponses;
68 static const int kRerunDelayMs = 1000;
70 // TODO(michaeln): Rework the set of states vs update types vs stored states.
71 // The NO_UPDATE state is really more of an update type. For all update types
72 // storing the results is relevant.
74 enum UpdateType {
75 UNKNOWN_TYPE,
76 UPGRADE_ATTEMPT,
77 CACHE_ATTEMPT,
80 enum InternalUpdateState {
81 FETCH_MANIFEST,
82 NO_UPDATE,
83 DOWNLOADING,
85 // Every state after this comment indicates the update is terminating.
86 REFETCH_MANIFEST,
87 CACHE_FAILURE,
88 CANCELLED,
89 COMPLETED,
92 enum StoredState {
93 UNSTORED,
94 STORING,
95 STORED,
98 struct UrlToFetch {
99 UrlToFetch(const GURL& url, bool checked, AppCacheResponseInfo* info);
100 ~UrlToFetch();
102 GURL url;
103 bool storage_checked;
104 scoped_refptr<AppCacheResponseInfo> existing_response_info;
107 class URLFetcher : public net::URLRequest::Delegate {
108 public:
109 enum FetchType {
110 MANIFEST_FETCH,
111 URL_FETCH,
112 MASTER_ENTRY_FETCH,
113 MANIFEST_REFETCH,
115 URLFetcher(const GURL& url,
116 FetchType fetch_type,
117 AppCacheUpdateJob* job);
118 ~URLFetcher() override;
119 void Start();
120 FetchType fetch_type() const { return fetch_type_; }
121 net::URLRequest* request() const { return request_.get(); }
122 const AppCacheEntry& existing_entry() const { return existing_entry_; }
123 const std::string& manifest_data() const { return manifest_data_; }
124 AppCacheResponseWriter* response_writer() const {
125 return response_writer_.get();
127 void set_existing_response_headers(net::HttpResponseHeaders* headers) {
128 existing_response_headers_ = headers;
130 void set_existing_entry(const AppCacheEntry& entry) {
131 existing_entry_ = entry;
133 ResultType result() const { return result_; }
134 int redirect_response_code() const { return redirect_response_code_; }
136 private:
137 // URLRequest::Delegate overrides
138 void OnReceivedRedirect(net::URLRequest* request,
139 const net::RedirectInfo& redirect_info,
140 bool* defer_redirect) override;
141 void OnResponseStarted(net::URLRequest* request) override;
142 void OnReadCompleted(net::URLRequest* request, int bytes_read) override;
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();
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
165 AppCacheResponseWriter* CreateResponseWriter();
167 // Methods for AppCacheStorage::Delegate.
168 void OnResponseInfoLoaded(AppCacheResponseInfo* response_info,
169 int64 response_id) override;
170 void OnGroupAndNewestCacheStored(AppCacheGroup* group,
171 AppCache* newest_cache,
172 bool success,
173 bool would_exceed_quota) override;
174 void OnGroupMadeObsolete(AppCacheGroup* group,
175 bool success,
176 int response_code) override;
178 // Methods for AppCacheHost::Observer.
179 void OnCacheSelectionComplete(AppCacheHost* host) override {} // N/A
180 void OnDestructionImminent(AppCacheHost* host) override;
182 // Methods for AppCacheServiceImpl::Observer.
183 void OnServiceReinitialized(AppCacheStorageReference* old_storage) override;
185 void HandleCacheFailure(const AppCacheErrorDetails& details,
186 ResultType result,
187 const GURL& failed_resource_url);
189 void FetchManifest(bool is_first_fetch);
190 void HandleManifestFetchCompleted(URLFetcher* fetcher);
191 void ContinueHandleManifestFetchCompleted(bool changed);
193 void HandleUrlFetchCompleted(URLFetcher* fetcher);
194 void HandleMasterEntryFetchCompleted(URLFetcher* fetcher);
196 void HandleManifestRefetchCompleted(URLFetcher* fetcher);
197 void OnManifestInfoWriteComplete(int result);
198 void OnManifestDataWriteComplete(int result);
200 void StoreGroupAndCache();
202 void NotifySingleHost(AppCacheHost* host, AppCacheEventID event_id);
203 void NotifyAllAssociatedHosts(AppCacheEventID event_id);
204 void NotifyAllProgress(const GURL& url);
205 void NotifyAllFinalProgress();
206 void NotifyAllError(const AppCacheErrorDetails& detals);
207 void LogConsoleMessageToAll(const std::string& message);
208 void AddAllAssociatedHostsToNotifier(HostNotifier* notifier);
210 // Checks if manifest is byte for byte identical with the manifest
211 // in the newest application cache.
212 void CheckIfManifestChanged();
213 void OnManifestDataReadComplete(int result);
215 // Creates the list of files that may need to be fetched and initiates
216 // fetches. Section 6.9.4 steps 12-17
217 void BuildUrlFileList(const AppCacheManifest& manifest);
218 void AddUrlToFileList(const GURL& url, int type);
219 void FetchUrls();
220 void CancelAllUrlFetches();
221 bool ShouldSkipUrlFetch(const AppCacheEntry& entry);
223 // If entry already exists in the cache currently being updated, merge
224 // the entry type information with the existing entry.
225 // Returns true if entry exists in cache currently being updated.
226 bool AlreadyFetchedEntry(const GURL& url, int entry_type);
228 // TODO(jennb): Delete when update no longer fetches master entries directly.
229 // Creates the list of master entries that need to be fetched and initiates
230 // fetches.
231 void AddMasterEntryToFetchList(AppCacheHost* host, const GURL& url,
232 bool is_new);
233 void FetchMasterEntries();
234 void CancelAllMasterEntryFetches(const AppCacheErrorDetails& details);
236 // Asynchronously loads the entry from the newest complete cache if the
237 // HTTP caching semantics allow.
238 // Returns false if immediately obvious that data cannot be loaded from
239 // newest complete cache.
240 bool MaybeLoadFromNewestCache(const GURL& url, AppCacheEntry& entry);
241 void LoadFromNewestCacheFailed(const GURL& url,
242 AppCacheResponseInfo* newest_response_info);
244 // Does nothing if update process is still waiting for pending master
245 // entries or URL fetches to complete downloading. Otherwise, completes
246 // the update process.
247 void MaybeCompleteUpdate();
249 // Schedules a rerun of the entire update with the same parameters as
250 // this update job after a short delay.
251 void ScheduleUpdateRetry(int delay_ms);
253 void Cancel();
254 void ClearPendingMasterEntries();
255 void DiscardInprogressCache();
256 void DiscardDuplicateResponses();
258 void LogHistogramStats(ResultType result, const GURL& failed_resource_url);
259 void MadeProgress() { last_progress_time_ = base::Time::Now(); }
261 // Deletes this object after letting the stack unwind.
262 void DeleteSoon();
264 bool IsTerminating() { return internal_state_ >= REFETCH_MANIFEST ||
265 stored_state_ != UNSTORED; }
267 AppCacheServiceImpl* service_;
268 const GURL manifest_url_; // here for easier access
270 // Defined prior to refs to AppCaches and Groups because destruction
271 // order matters, the disabled_storage_reference_ must outlive those
272 // objects.
273 scoped_refptr<AppCacheStorageReference> disabled_storage_reference_;
275 scoped_refptr<AppCache> inprogress_cache_;
277 AppCacheGroup* group_;
279 UpdateType update_type_;
280 InternalUpdateState internal_state_;
281 base::Time last_progress_time_;
282 bool doing_full_update_check_;
284 PendingMasters pending_master_entries_;
285 size_t master_entries_completed_;
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_;
295 // URLs of files to fetch along with their flags.
296 AppCache::EntryMap url_file_list_;
297 size_t url_fetches_completed_;
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_;
304 // Helper container to track which urls are being loaded from response
305 // storage.
306 LoadingResponses loading_responses_;
308 // Keep track of pending URL requests so we can cancel them if necessary.
309 URLFetcher* manifest_fetcher_;
310 PendingUrlFetches pending_url_fetches_;
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_;
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_;
325 // Response ids stored by this update job, used to cleanup in
326 // error conditions.
327 std::vector<int64> stored_response_ids_;
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_;
336 // Whether we've stored the resulting group/cache yet.
337 StoredState stored_state_;
339 AppCacheStorage* storage_;
340 base::WeakPtrFactory<AppCacheUpdateJob> weak_factory_;
342 FRIEND_TEST_ALL_PREFIXES(content::AppCacheGroupTest, QueueUpdate);
344 DISALLOW_COPY_AND_ASSIGN(AppCacheUpdateJob);
347 } // namespace content
349 #endif // CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_JOB_H_