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. 4 5 #ifndef CHROME_BROWSER_PREDICTORS_RESOURCE_PREFETCHER_H_ 6 #define CHROME_BROWSER_PREDICTORS_RESOURCE_PREFETCHER_H_ 7 8 #include <list> 9 #include <map> 10 #include <vector> 11 12 #include "base/gtest_prod_util.h" 13 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/scoped_vector.h" 15 #include "base/threading/thread_checker.h" 16 #include "chrome/browser/predictors/resource_prefetch_common.h" 17 #include "net/url_request/redirect_info.h" 18 #include "net/url_request/url_request.h" 19 #include "url/gurl.h" 20 21 namespace net { 22 class URLRequestContext; 23 } 24 25 namespace predictors { 26 27 // Responsible for prefetching resources for a single navigation based on the 28 // input list of resources. 29 // - Limits the max number of resources in flight for any host and also across 30 // hosts. 31 // - When stopped, will wait for the pending requests to finish. 32 // - Lives entirely on the IO thread. 33 class ResourcePrefetcher : public net::URLRequest::Delegate { 34 public: 35 // Denotes the prefetch request for a single subresource. 36 struct Request { 37 explicit Request(const GURL& i_resource_url); 38 Request(const Request& other); 39 40 enum PrefetchStatus { 41 PREFETCH_STATUS_NOT_STARTED, 42 PREFETCH_STATUS_STARTED, 43 44 // Cancellation reasons. 45 PREFETCH_STATUS_REDIRECTED, 46 PREFETCH_STATUS_AUTH_REQUIRED, 47 PREFETCH_STATUS_CERT_REQUIRED, 48 PREFETCH_STATUS_CERT_ERROR, 49 PREFETCH_STATUS_CANCELLED, 50 PREFETCH_STATUS_FAILED, 51 52 // Successful prefetch states. 53 PREFETCH_STATUS_FROM_CACHE, 54 PREFETCH_STATUS_FROM_NETWORK 55 }; 56 57 enum UsageStatus { 58 USAGE_STATUS_NOT_REQUESTED, 59 USAGE_STATUS_FROM_CACHE, 60 USAGE_STATUS_FROM_NETWORK, 61 USAGE_STATUS_NAVIGATION_ABANDONED 62 }; 63 64 GURL resource_url; 65 PrefetchStatus prefetch_status; 66 UsageStatus usage_status; 67 }; 68 typedef ScopedVector<Request> RequestVector; 69 70 // Used to communicate when the prefetching is done. All methods are invoked 71 // on the IO thread. 72 class Delegate { 73 public: 74 virtual ~Delegate() { } 75 76 // Called when the ResourcePrefetcher is finished, i.e. there is nothing 77 // pending in flight. Should take ownership of |requests|. 78 virtual void ResourcePrefetcherFinished( 79 ResourcePrefetcher* prefetcher, 80 RequestVector* requests) = 0; 81 82 virtual net::URLRequestContext* GetURLRequestContext() = 0; 83 }; 84 85 // |delegate| has to outlive the ResourcePrefetcher. The ResourcePrefetcher 86 // takes ownership of |requests|. 87 ResourcePrefetcher(Delegate* delegate, 88 const ResourcePrefetchPredictorConfig& config, 89 const NavigationID& navigation_id, 90 PrefetchKeyType key_type, 91 scoped_ptr<RequestVector> requests); 92 virtual ~ResourcePrefetcher(); 93 94 void Start(); // Kicks off the prefetching. Can only be called once. 95 void Stop(); // No additional prefetches will be queued after this. 96 97 const NavigationID& navigation_id() const { return navigation_id_; } 98 PrefetchKeyType key_type() const { return key_type_; } 99 100 private: 101 friend class ResourcePrefetcherTest; 102 friend class TestResourcePrefetcher; 103 104 // Launches new prefetch requests if possible. 105 void TryToLaunchPrefetchRequests(); 106 107 // Starts a net::URLRequest for the input |request|. 108 void SendRequest(Request* request); 109 110 // Called by |SendRequest| to start the |request|. This is necessary to stub 111 // out the Start() call to net::URLRequest for unittesting. 112 virtual void StartURLRequest(net::URLRequest* request); 113 114 // Marks the request as finished, with the given status. 115 void FinishRequest(net::URLRequest* request, Request::PrefetchStatus status); 116 117 // Reads the response data from the response - required for the resource to 118 // be cached correctly. Stubbed out during testing. 119 virtual void ReadFullResponse(net::URLRequest* request); 120 121 // Returns true if the request has more data that needs to be read. If it 122 // returns false, the request should not be referenced again. 123 bool ShouldContinueReadingRequest(net::URLRequest* request, int bytes_read); 124 125 // net::URLRequest::Delegate methods. 126 virtual void OnReceivedRedirect(net::URLRequest* request, 127 const net::RedirectInfo& redirect_info, 128 bool* defer_redirect) OVERRIDE; 129 virtual void OnAuthRequired(net::URLRequest* request, 130 net::AuthChallengeInfo* auth_info) OVERRIDE; 131 virtual void OnCertificateRequested( 132 net::URLRequest* request, 133 net::SSLCertRequestInfo* cert_request_info) OVERRIDE; 134 virtual void OnSSLCertificateError(net::URLRequest* request, 135 const net::SSLInfo& ssl_info, 136 bool fatal) OVERRIDE; 137 virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE; 138 virtual void OnReadCompleted(net::URLRequest* request, 139 int bytes_read) OVERRIDE; 140 141 enum PrefetcherState { 142 INITIALIZED = 0, // Prefetching hasn't started. 143 RUNNING = 1, // Prefetching started, allowed to add more requests. 144 STOPPED = 2, // Prefetching started, not allowed to add more requests. 145 FINISHED = 3 // No more inflight request, new requests not possible. 146 }; 147 148 base::ThreadChecker thread_checker_; 149 PrefetcherState state_; 150 Delegate* const delegate_; 151 ResourcePrefetchPredictorConfig const config_; 152 NavigationID navigation_id_; 153 PrefetchKeyType key_type_; 154 scoped_ptr<RequestVector> request_vector_; 155 156 std::map<net::URLRequest*, Request*> inflight_requests_; 157 std::list<Request*> request_queue_; 158 std::map<std::string, size_t> host_inflight_counts_; 159 160 DISALLOW_COPY_AND_ASSIGN(ResourcePrefetcher); 161 }; 162 163 } // namespace predictors 164 165 #endif // CHROME_BROWSER_PREDICTORS_RESOURCE_PREFETCHER_H_ 166