11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Copyright 2014 The Chromium Authors. All rights reserved.
21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Use of this source code is governed by a BSD-style license that can be
31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// found in the LICENSE file.
41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#ifndef CHROME_BROWSER_PREDICTORS_RESOURCE_PREFETCHER_H_
61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#define CHROME_BROWSER_PREDICTORS_RESOURCE_PREFETCHER_H_
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <list>
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <map>
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <vector>
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/gtest_prod_util.h"
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/memory/scoped_ptr.h"
141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/memory/scoped_vector.h"
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/threading/thread_checker.h"
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/predictors/resource_prefetch_common.h"
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/url_request/redirect_info.h"
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/url_request/url_request.h"
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "url/gurl.h"
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace net {
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass URLRequestContext;
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace predictors {
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Responsible for prefetching resources for a single navigation based on the
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// input list of resources.
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//  - Limits the max number of resources in flight for any host and also across
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//    hosts.
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//  - When stopped, will wait for the pending requests to finish.
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//  - Lives entirely on the IO thread.
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass ResourcePrefetcher : public net::URLRequest::Delegate {
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public:
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Denotes the prefetch request for a single subresource.
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  struct Request {
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    explicit Request(const GURL& i_resource_url);
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Request(const Request& other);
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    enum PrefetchStatus {
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      PREFETCH_STATUS_NOT_STARTED,
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      PREFETCH_STATUS_STARTED,
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Cancellation reasons.
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      PREFETCH_STATUS_REDIRECTED,
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      PREFETCH_STATUS_AUTH_REQUIRED,
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      PREFETCH_STATUS_CERT_REQUIRED,
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      PREFETCH_STATUS_CERT_ERROR,
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      PREFETCH_STATUS_CANCELLED,
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      PREFETCH_STATUS_FAILED,
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Successful prefetch states.
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      PREFETCH_STATUS_FROM_CACHE,
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      PREFETCH_STATUS_FROM_NETWORK
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    };
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    enum UsageStatus {
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      USAGE_STATUS_NOT_REQUESTED,
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      USAGE_STATUS_FROM_CACHE,
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      USAGE_STATUS_FROM_NETWORK,
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      USAGE_STATUS_NAVIGATION_ABANDONED
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    };
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    GURL resource_url;
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    PrefetchStatus prefetch_status;
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    UsageStatus usage_status;
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  };
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  typedef ScopedVector<Request> RequestVector;
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Used to communicate when the prefetching is done. All methods are invoked
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // on the IO thread.
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  class Delegate {
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci   public:
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    virtual ~Delegate() { }
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Called when the ResourcePrefetcher is finished, i.e. there is nothing
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // pending in flight. Should take ownership of |requests|.
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    virtual void ResourcePrefetcherFinished(
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        ResourcePrefetcher* prefetcher,
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        RequestVector* requests) = 0;
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    virtual net::URLRequestContext* GetURLRequestContext() = 0;
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  };
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // |delegate| has to outlive the ResourcePrefetcher. The ResourcePrefetcher
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // takes ownership of |requests|.
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ResourcePrefetcher(Delegate* delegate,
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     const ResourcePrefetchPredictorConfig& config,
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     const NavigationID& navigation_id,
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     PrefetchKeyType key_type,
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     scoped_ptr<RequestVector> requests);
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual ~ResourcePrefetcher();
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void Start();  // Kicks off the prefetching. Can only be called once.
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void Stop();   // No additional prefetches will be queued after this.
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const NavigationID& navigation_id() const { return navigation_id_; }
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  PrefetchKeyType key_type() const { return key_type_; }
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private:
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  friend class ResourcePrefetcherTest;
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  friend class TestResourcePrefetcher;
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Launches new prefetch requests if possible.
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void TryToLaunchPrefetchRequests();
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Starts a net::URLRequest for the input |request|.
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void SendRequest(Request* request);
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Called by |SendRequest| to start the |request|. This is necessary to stub
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // out the Start() call to net::URLRequest for unittesting.
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void StartURLRequest(net::URLRequest* request);
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Marks the request as finished, with the given status.
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void FinishRequest(net::URLRequest* request, Request::PrefetchStatus status);
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Reads the response data from the response - required for the resource to
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // be cached correctly. Stubbed out during testing.
1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void ReadFullResponse(net::URLRequest* request);
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Returns true if the request has more data that needs to be read. If it
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // returns false, the request should not be referenced again.
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool ShouldContinueReadingRequest(net::URLRequest* request, int bytes_read);
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // net::URLRequest::Delegate methods.
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void OnReceivedRedirect(net::URLRequest* request,
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  const net::RedirectInfo& redirect_info,
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  bool* defer_redirect) OVERRIDE;
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void OnAuthRequired(net::URLRequest* request,
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              net::AuthChallengeInfo* auth_info) OVERRIDE;
1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void OnCertificateRequested(
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      net::URLRequest* request,
1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      net::SSLCertRequestInfo* cert_request_info) OVERRIDE;
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void OnSSLCertificateError(net::URLRequest* request,
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                     const net::SSLInfo& ssl_info,
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                     bool fatal) OVERRIDE;
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE;
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void OnReadCompleted(net::URLRequest* request,
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               int bytes_read) OVERRIDE;
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  enum PrefetcherState {
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    INITIALIZED = 0,  // Prefetching hasn't started.
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    RUNNING = 1,      // Prefetching started, allowed to add more requests.
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    STOPPED = 2,      // Prefetching started, not allowed to add more requests.
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    FINISHED = 3      // No more inflight request, new requests not possible.
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  };
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::ThreadChecker thread_checker_;
1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  PrefetcherState state_;
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Delegate* const delegate_;
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ResourcePrefetchPredictorConfig const config_;
1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  NavigationID navigation_id_;
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  PrefetchKeyType key_type_;
1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<RequestVector> request_vector_;
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::map<net::URLRequest*, Request*> inflight_requests_;
1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::list<Request*> request_queue_;
1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::map<std::string, size_t> host_inflight_counts_;
1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DISALLOW_COPY_AND_ASSIGN(ResourcePrefetcher);
1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace predictors
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif  // CHROME_BROWSER_PREDICTORS_RESOURCE_PREFETCHER_H_
166