Fix breakages in https://codereview.chromium.org/1155713003/
[chromium-blink-merge.git] / ios / web / net / request_tracker_impl.h
blob45aaa0361b195c8309904c2e20dc8c4a432de5f6
1 // Copyright 2014 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 IOS_WEB_NET_REQUEST_TRACKER_IMPL_H_
6 #define IOS_WEB_NET_REQUEST_TRACKER_IMPL_H_
8 #import <Foundation/Foundation.h>
9 #include <map>
10 #include <set>
12 #include "base/callback_forward.h"
13 #include "base/mac/scoped_nsobject.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/memory/scoped_vector.h"
16 #include "base/memory/weak_ptr.h"
17 #import "ios/net/request_tracker.h"
18 #import "ios/web/net/crw_request_tracker_delegate.h"
19 #include "ios/web/public/web_thread.h"
20 #include "net/url_request/url_request_context_getter.h"
21 #include "url/gurl.h"
23 @class SSLCarrier;
24 @class CRWSSLCarrier;
25 class SSLErrorInfo;
26 struct TrackerCounts;
28 namespace content {
29 struct SSLStatus;
32 namespace net {
33 class HttpResponseHeaders;
34 class URLRequest;
35 class URLRequestContext;
36 class SSLInfo;
37 class X509Certificate;
40 namespace web {
42 class BrowserState;
43 class CertificatePolicyCache;
45 // Structure to capture the current state of a page.
46 struct PageCounts {
47 public:
48 PageCounts() : finished(0),
49 finished_bytes(0),
50 unfinished(0),
51 unfinished_no_estimate(0),
52 unfinished_no_estimate_bytes_done(0),
53 unfinished_estimated_bytes_left(0),
54 unfinished_estimate_bytes_done(0),
55 largest_byte_size_known(0) {
58 // Count of finished requests.
59 uint64_t finished;
60 // Total bytes count dowloaded for all finished requests.
61 uint64_t finished_bytes;
62 // Count of unfinished requests.
63 uint64_t unfinished;
64 // Count of unfinished requests with unknown size.
65 uint64_t unfinished_no_estimate;
66 // Total bytes count dowloaded for unfinished requests of unknown size.
67 uint64_t unfinished_no_estimate_bytes_done;
68 // Count of unfinished requests with an estimated size.
69 uint64_t unfinished_estimated_bytes_left;
70 // Total bytes count dowloaded for unfinished requests with an estimated size.
71 uint64_t unfinished_estimate_bytes_done;
72 // Size of the request with the most bytes on the page.
73 uint64_t largest_byte_size_known;
76 // RequestTrackerImpl captures and stores all the network requests that
77 // initiated from a particular tab. It only keeps the URLs and eventually, if
78 // available, the expected length of the result and the length of the received
79 // data so far as this is used to build a progress bar for a page.
80 // Note that the Request tracker has no notion of a page, it only tracks the
81 // requests by tab. In order for the tracker to know that a request is for a
82 // page or a subresource it is necessary for the tab to call StartPageLoad()
83 // with the URL of the page once it is known to avoid storing all the requests
84 // forever.
86 // The consumer needs to implement the CRWRequestTrackerImplDelegate protocol
87 // and needs to call StartPageLoad() and FinishPageLoad() to indicate the page
88 // boundaries. StartPageLoad() will also have the side effect of clearing past
89 // requests from memory. The consumer is assumed to be on the UI thread at all
90 // times.
92 // RequestTrackerImpl objects are created and destroyed on the UI thread and
93 // must be owned by some other object on the UI thread by way of a
94 // scoped_refptr, as returned by the public static constructor method,
95 // CreateTrackerForRequestGroupID. All consumer API methods will be called
96 // through this pointer.
98 class RequestTrackerImpl;
100 struct RequestTrackerImplTraits {
101 static void Destruct(const RequestTrackerImpl* t);
104 class RequestTrackerImpl
105 : public base::RefCountedThreadSafe<RequestTrackerImpl,
106 RequestTrackerImplTraits>,
107 public net::RequestTracker {
108 public:
109 #pragma mark Public Consumer API
110 // Consumer API methods should only be called on the UI thread.
112 // Create a new RequestTrackerImpl associated with a particular tab. The
113 // profile must be the one associated to the given tab. This method has to be
114 // called *once* per tab and needs to be called before triggering any network
115 // request. The caller of CreateTrackerForRequestGroupID owns the tracker, and
116 // this class also keeps a global map of all active trackers. When the owning
117 // object releases it, the class removes it from the global map.
118 static scoped_refptr<RequestTrackerImpl> CreateTrackerForRequestGroupID(
119 NSString* request_group_id,
120 BrowserState* browser_state,
121 net::URLRequestContextGetter* context_getter,
122 id<CRWRequestTrackerDelegate> delegate);
124 // The network layer has no way to know which network request is the primary
125 // one for a page load. The tab knows, either because it initiated the page
126 // load via the URL or received a callback informing it of the page change.
127 // Every time this happens the tab should call this method to clear the
128 // resources tracked.
129 // This will forget all the finished requests made before this URL in history.
130 // user_info is to be used by the consumer to store more additional specific
131 // info about the page, as an URL is not unique.
132 void StartPageLoad(const GURL& url, id user_info);
134 // In order to properly provide progress information the tracker needs to know
135 // when the page is fully loaded. |load_success| indicates if the page
136 // successfully loaded.
137 void FinishPageLoad(const GURL& url, bool load_success);
139 // Tells the tracker that history.pushState() or history.replaceState()
140 // changed the page URL.
141 void HistoryStateChange(const GURL& url);
143 // Marks the tracker as closed. An owner must call this before the tracker is
144 // deleted. Once closed, no further calls will be made to the delegate.
145 void Close();
147 // Call |callback| on the UI thread after any pending request cancellations
148 // have completed on the IO thread.
149 // This should be used to delete a profile for which all of the trackers
150 // that use the profile's request context are closed.
151 static void RunAfterRequestsCancel(const base::Closure& callback);
153 // Block until all pending IO thread activity has completed. This should only
154 // be used when Chrome is shutting down, and after all request trackers have
155 // had Close() called on them.
156 static void BlockUntilTrackersShutdown();
158 #pragma mark Client utility methods.
160 // Finds the tracker given the tab ID. As calling this method involves a lock
161 // it is expected that the provider will call it only once.
162 // Returns a weak pointer, which should only be dereferenced on the IO thread.
163 // Returns NULL if no tracker exists for |request_group_id|.
164 static RequestTrackerImpl* GetTrackerForRequestGroupID(
165 NSString* request_group_id);
167 // Callback from the UI to allow or deny a particular certificate.
168 void ErrorCallback(CRWSSLCarrier* carrier, bool allow);
170 // Utility method for clients to post tasks to the IO thread from the UI
171 // thread.
172 void PostIOTask(const base::Closure& task);
174 // Utility method for clients to post tasks to the IO thread from the IO
175 // thread.
176 void ScheduleIOTask(const base::Closure& task);
178 // Utility method for clients to conditionally post tasks to the UI thread
179 // from the IO thread. The task will not be posted if the request tracker
180 // is in the process of closing (thus it "is open").
181 void PostUITaskIfOpen(const base::Closure& task);
182 // Static version of the method, where |tracker| is a RequestTrackerImpl
183 // passed as a base::WeakPtr<RequestTracker>.
184 static void PostUITaskIfOpen(const base::WeakPtr<RequestTracker> tracker,
185 const base::Closure& task);
187 // Sets the cache mode. Must be called from the UI thread.
188 void SetCacheModeFromUIThread(RequestTracker::CacheMode mode);
190 #pragma mark Testing methods
192 void SetCertificatePolicyCacheForTest(web::CertificatePolicyCache* cache);
194 #pragma mark Accessors used by internal classes and network clients.
195 int identifier() { return identifier_; }
196 bool has_mixed_content() { return has_mixed_content_; }
198 // RequestTracker implementation.
199 void StartRequest(net::URLRequest* request) override;
200 void CaptureHeaders(net::URLRequest* request) override;
201 void CaptureExpectedLength(const net::URLRequest* request,
202 uint64_t length) override;
203 void CaptureReceivedBytes(const net::URLRequest* request,
204 uint64_t byte_count) override;
205 void CaptureCertificatePolicyCache(
206 const net::URLRequest* request,
207 const SSLCallback& should_continue) override;
208 void StopRequest(net::URLRequest* request) override;
209 void StopRedirectedRequest(net::URLRequest* request) override;
210 void OnSSLCertificateError(const net::URLRequest* request,
211 const net::SSLInfo& ssl_info,
212 bool recoverable,
213 const SSLCallback& should_continue) override;
214 net::URLRequestContext* GetRequestContext() override;
216 private:
217 friend class base::RefCountedThreadSafe<RequestTrackerImpl>;
218 friend struct RequestTrackerImplTraits;
220 #pragma mark Object lifecycle API
221 // Private. RequestTrackerImpls are created through
222 // CreateTrackerForRequestGroupID().
223 RequestTrackerImpl(NSString* request_group_id,
224 net::URLRequestContextGetter* context_getter,
225 id<CRWRequestTrackerDelegate> delegate);
227 void InitOnIOThread(
228 const scoped_refptr<web::CertificatePolicyCache>& policy_cache);
230 // Private destructor because the object is reference counted. A no-op; the
231 // useful destruction work happens in Destruct().
232 ~RequestTrackerImpl() override;
234 // Handles pre-destruction destruction tasks. This is invoked by
235 // RequestTrackerImplTraits::Destruct whenever the reference count of a
236 // RequestTrackerImpl is zero, and this will untimately delete the
237 // RequestTrackerImpl.
238 void Destruct();
240 #pragma mark Private Provider API
241 // Private methods that implement provider API features. All are only called
242 // on the IO thread.
244 // Called when something has changed (network load progress or SSL status)
245 // that the consumer should know about. Notifications are asynchronous and
246 // batched.
247 void Notify();
249 // If no other notifications are pending, notifies the consumer of SSL status
250 // and load progress.
251 void StackNotification();
253 // Notify the consumer about the SSL status of this tracker's page load.
254 void SSLNotify();
256 // If the counts is for a request currently waiting for the user to approve it
257 // will reevaluate the approval.
258 void EvaluateSSLCallbackForCounts(TrackerCounts* counts);
260 // Loop through all the requests waiting for approval and invoke
261 // |-evaluateSSLCallbackForCounts:| on all the ones with an |UNKNOWN|
262 // judgment.
263 void ReevaluateCallbacksForAllCounts();
265 // To cancel a rejected request due to a SSL issue.
266 void CancelRequestForCounts(TrackerCounts* counts);
268 // Estimate the page load progress. Returns -1 if the progress didn't change
269 // since the last time this method was invoked.
270 float EstimatedProgress();
272 // The URL change notification is often late, therefore the mixed content
273 // status and the certificate policies may need to be recomputed.
274 void RecomputeMixedContent(const TrackerCounts* split_position);
275 void RecomputeCertificatePolicy(const TrackerCounts* split_position);
277 // Remove all finished request up to the last instance of |url|. If url is not
278 // found, this will clear all the requests.
279 void TrimToURL(const GURL& url, id user_info);
281 // Sets page_url_ to the new URL if it's a valid history state change (i.e.
282 // the URL's have the same origin) and if the tab is currently loading.
283 void HistoryStateChangeToURL(const GURL& full_url);
285 // Note that the page started by a call to Trim is no longer loading.
286 // |load_success| indicates if the page successfully loaded.
287 void StopPageLoad(const GURL& url, bool load_success);
289 // Cancels all the requests in |live_requests_|.
290 void CancelRequests();
292 #pragma mark Private Consumer API
293 // Private methods that call into delegate methods.
295 // Notify* methods are posted to the UI thread by the provider API
296 // methods.
298 // Has the delegate handle |headers| for |request_url|.
299 void NotifyResponseHeaders(net::HttpResponseHeaders* headers,
300 const GURL& request_url);
302 // Notifies the deleage of certificate use.
303 void NotifyCertificateUsed(net::X509Certificate* certificate,
304 const std::string& host,
305 net::CertStatus status);
307 // Notifies the deleate of a load completion estimate.
308 void NotifyUpdatedProgress(float estimate);
310 // Has the delegate clear SSL certificates.
311 void NotifyClearCertificates();
313 // Notifies the delegate of an SSL status update.
314 void NotifyUpdatedSSLStatus(base::scoped_nsobject<CRWSSLCarrier> carrier);
316 // Calls the delegate method to present an SSL error interstitial.
317 void NotifyPresentSSLError(base::scoped_nsobject<CRWSSLCarrier> carrier,
318 bool recoverable);
320 #pragma mark Internal utilities for task posting
321 // Posts |task| to |thread|. Must not be called from |thread|. If |thread| is
322 // the IO thread, silently returns if |is_closing_| is true.
323 void PostTask(const base::Closure& task, web::WebThread::ID thread);
325 // Posts |block| to |thread|, safely passing in |caller| to |block|.
326 void PostBlock(id caller, void (^block)(id), web::WebThread::ID thread);
328 #pragma mark Other internal methods.
329 // Returns the current state of the page.
330 PageCounts pageCounts();
332 // Like description, but cannot be called from any thread. It must be called
333 // only from the IO thread.
334 NSString* UnsafeDescription();
336 // Generates a string unique to this RequestTrackerImpl to use with the
337 // CRWNetworkActivityIndicatorManager.
338 NSString* GetNetworkActivityKey();
340 #pragma mark Non thread-safe fields, only accessed from the main thread.
341 // The RequestTrackerImpl delegate. All changes and access to this object
342 // should be done on the main thread.
343 id<CRWRequestTrackerDelegate> delegate_; // Weak.
345 #pragma mark Non thread-safe fields, only accessed from the IO thread.
346 // All the tracked requests for the page, indexed by net::URLRequest (Cast as
347 // a void* to avoid the temptation of accessing it from the wrong thread).
348 // This map is not exhaustive: it is only meant to estimate the loading
349 // progress, and thus requests corresponding to old navigation events are not
350 // in it.
351 std::map<const void*, TrackerCounts*> counts_by_request_;
352 // All the live requests associated with the tracker.
353 std::set<net::URLRequest*> live_requests_;
354 // A list of all the TrackerCounts, including the finished ones.
355 ScopedVector<TrackerCounts> counts_;
356 // The system shall never allow the page load estimate to go back.
357 float previous_estimate_;
358 // Index of the first request to consider for building the estimation.
359 unsigned int estimate_start_index_;
360 // How many notifications are currently queued, to avoid notifying too often.
361 int notification_depth_;
362 // The tracker containing the error currently presented to the user.
363 TrackerCounts* current_ssl_error_;
364 // Set to |YES| if the page has mixed content
365 bool has_mixed_content_;
366 // Set to true if between TrimToURL and StopPageLoad.
367 bool is_loading_;
368 // Set to true in TrimToURL if starting a new estimate round. Set to false by
369 // StartRequest once the new round is started.
370 bool new_estimate_round_;
372 #pragma mark Other fields.
373 scoped_refptr<web::CertificatePolicyCache> policy_cache_;
374 // If |true| all the requests should be static file requests, otherwise all
375 // the requests should be network requests. This is a constant initialized
376 // in the constructor and read in IO and UI threads.
377 const bool is_for_static_file_requests_;
379 scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
380 // Current page URL, as far as we know.
381 GURL page_url_;
382 // Userinfo attached to the page, passed back by the delegate.
383 base::scoped_nsobject<id> user_info_;
384 // A tracker identifier (a simple increasing number) used to store
385 // certificates.
386 int identifier_;
387 // The string that identifies the tab this tracker serves. Used to index
388 // g_trackers.
389 base::scoped_nsobject<NSString> request_group_id_;
390 // Flag to synchronize deletion and callback creation. Lives on the IO thread.
391 // True when this tracker has beed Close()d. If this is the case, no further
392 // references to it should be generated (for example by binding it into a
393 // callback), and the expectation is that it will soon be deleted.
394 bool is_closing_;
397 } // namespace web
399 #endif // IOS_WEB_NET_REQUEST_TRACKER_IMPL_H_