blob: 0b5287b0f4b3f0831087222a9a27967ab8a88c64 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_PREDICTORS_PRECONNECT_MANAGER_H_
#define CHROME_BROWSER_PREDICTORS_PRECONNECT_MANAGER_H_
#include <list>
#include <map>
#include <memory>
#include <vector>
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "net/base/completion_callback.h"
#include "net/http/http_request_info.h"
#include "net/url_request/url_request_context_getter.h"
#include "url/gurl.h"
namespace predictors {
// Stores the status of all preconnects associated with a given |url|.
struct PreresolveInfo {
PreresolveInfo(const GURL& url, size_t count);
PreresolveInfo(const PreresolveInfo& other);
~PreresolveInfo();
bool is_done() const { return queued_count == 0 && inflight_count == 0; }
GURL url;
size_t queued_count;
size_t inflight_count = 0;
bool was_canceled = false;
};
// Stores all data need for running a preresolve and a subsequent optional
// preconnect for a |url|.
struct PreresolveJob {
PreresolveJob(const GURL& url, bool need_preconnect, PreresolveInfo* info);
PreresolveJob(const PreresolveJob& other);
~PreresolveJob();
GURL url;
bool need_preconnect;
// Raw pointer usage is fine here because even though PreresolveJob can
// outlive PreresolveInfo it's only accessed on PreconnectManager class
// context and PreresolveInfo lifetime is tied to PreconnectManager.
PreresolveInfo* info;
};
// PreconnectManager is responsible for preresolving and preconnecting to
// origins based on the input list of URLs.
// - The input list of URLs is associated with a main frame url that can be
// used for cancelling.
// - Limits the total number of preresolves in flight.
// - Preresolves an URL before preconnecting to it to have a better control on
// number of speculative dns requests in flight.
// - When stopped, waits for the pending preresolve requests to finish without
// issuing preconnects for them.
// - All methods of the class except the constructor must be called on the IO
// thread. The constructor must be called on the UI thread.
class PreconnectManager {
public:
class Delegate {
public:
virtual ~Delegate() {}
// Called when all preresolve jobs for the |url| are finished. Note that
// some preconnect jobs can be still in progress, because they are
// fire-and-forget.
// Is called on the UI thread.
virtual void PreconnectFinished(const GURL& url) = 0;
};
static const size_t kMaxInflightPreresolves = 3;
PreconnectManager(base::WeakPtr<Delegate> delegate,
scoped_refptr<net::URLRequestContextGetter> context_getter);
virtual ~PreconnectManager();
// Starts preconnect and preresolve jobs keyed by |url|.
void Start(const GURL& url,
const std::vector<GURL>& preconnect_origins,
const std::vector<GURL>& preresolve_hosts);
// No additional jobs keyed by the |url| will be queued after this.
void Stop(const GURL& url);
// Public for mocking in unit tests. Don't use, internal only.
virtual void PreconnectUrl(const GURL& url,
const GURL& first_party_for_cookies) const;
virtual int PreresolveUrl(const GURL& url,
const net::CompletionCallback& callback) const;
private:
void TryToLaunchPreresolveJobs();
void OnPreresolveFinished(const PreresolveJob& job, int result);
void FinishPreresolve(const PreresolveJob& job, bool found);
void AllPreresolvesForUrlFinished(PreresolveInfo* info);
base::WeakPtr<Delegate> delegate_;
scoped_refptr<net::URLRequestContextGetter> context_getter_;
std::list<PreresolveJob> queued_jobs_;
std::map<GURL, std::unique_ptr<PreresolveInfo>> preresolve_info_;
size_t inflight_preresolves_count_ = 0;
base::WeakPtrFactory<PreconnectManager> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(PreconnectManager);
};
} // namespace predictors
#endif // CHROME_BROWSER_PREDICTORS_PRECONNECT_MANAGER_H_