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 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/non_thread_safe.h" 16 #include "chrome/browser/predictors/resource_prefetch_common.h" 17 #include "net/url_request/url_request.h" 18 #include "url/gurl.h" 19 20 namespace net { 21 class URLRequestContext; 22 } 23 24 namespace predictors { 25 26 // Responsible for prefetching resources for a single navigation based on the 27 // input list of resources. 28 // - Limits the max number of resources in flight for any host and also across 29 // hosts. 30 // - When stopped, will wait for the pending requests to finish. 31 // - Lives entirely on the IO thread. 32 class ResourcePrefetcher : public base::NonThreadSafe, 33 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 GURL& new_url, 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 PrefetcherState state_; 149 Delegate* const delegate_; 150 ResourcePrefetchPredictorConfig const config_; 151 NavigationID navigation_id_; 152 PrefetchKeyType key_type_; 153 scoped_ptr<RequestVector> request_vector_; 154 155 std::map<net::URLRequest*, Request*> inflight_requests_; 156 std::list<Request*> request_queue_; 157 std::map<std::string, int> host_inflight_counts_; 158 159 DISALLOW_COPY_AND_ASSIGN(ResourcePrefetcher); 160 }; 161 162 } // namespace predictors 163 164 #endif // CHROME_BROWSER_PREDICTORS_RESOURCE_PREFETCHER_H_ 165