Home | History | Annotate | Download | only in predictors
      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