blob: bcd3d04089159ae3d79f3e9a70061b036351ef15 [file] [log] [blame]
// Copyright 2020 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_PREFETCH_PREFETCH_PROXY_PREFETCH_PROXY_SUBRESOURCE_MANAGER_H_
#define CHROME_BROWSER_PREFETCH_PREFETCH_PROXY_PREFETCH_PROXY_SUBRESOURCE_MANAGER_H_
#include <memory>
#include <set>
#include "base/callback.h"
#include "base/containers/unique_ptr_adapters.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_proxying_url_loader_factory.h"
#include "components/no_state_prefetch/browser/no_state_prefetch_handle.h"
#include "content/public/browser/content_browser_client.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/isolation_info.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace content {
class RenderFrameHost;
}
namespace prerender {
class NoStatePrefetchHandle;
}
class PrefetchedMainframeResponseContainer;
class PrefetchProxyPrefetchMetricsCollector;
class PrefetchProxyProxyingURLLoaderFactory;
// This class manages the prefetch proxy of a page and its subresources.
class PrefetchProxySubresourceManager
: public prerender::NoStatePrefetchHandle::Observer,
public PrefetchProxyProxyingURLLoaderFactory::ResourceMetricsObserver {
public:
// A callback to create new URL Loader Factories for subresources.
using CreateIsolatedLoaderFactoryRepeatingCallback =
base::RepeatingCallback<void(
mojo::PendingReceiver<network::mojom::URLLoaderFactory>
pending_receiver,
base::Optional<net::IsolationInfo> isolation_info)>;
explicit PrefetchProxySubresourceManager(
const GURL& url,
std::unique_ptr<PrefetchedMainframeResponseContainer> mainframe_response);
~PrefetchProxySubresourceManager() override;
// Passes ownership of |handle| to |this|, calling |on_nsp_done_callback| when
// the NSP is done.
void ManageNoStatePrefetch(
std::unique_ptr<prerender::NoStatePrefetchHandle> handle,
base::OnceClosure on_nsp_done_callback);
bool has_nsp_handle() const { return !!nsp_handle_; }
const std::set<GURL>& successfully_loaded_subresources() const {
return successfully_loaded_subresources_;
}
// Sets the prefetch metrics collector to report subresource fetches to.
void SetPrefetchMetricsCollector(
scoped_refptr<PrefetchProxyPrefetchMetricsCollector> collector);
// Takes ownership of |mainframe_response_|.
std::unique_ptr<PrefetchedMainframeResponseContainer> TakeMainframeResponse();
// Gives |this| a callback to create the isolated URL Loader factory to use
// for Prefetch Proxy.
void SetCreateIsolatedLoaderFactoryCallback(
CreateIsolatedLoaderFactoryRepeatingCallback callback);
// Called on commit to allow |this| to setup an intermediary (AKA: proxy, not
// to be confused with a proxy server) URLLoaderFactory between the renderer
// and network stack. Returns true when |factory_receiver| is proxied.
bool MaybeProxyURLLoaderFactory(
content::RenderFrameHost* frame,
int render_process_id,
content::ContentBrowserClient::URLLoaderFactoryType type,
mojo::PendingReceiver<network::mojom::URLLoaderFactory>*
factory_receiver);
// Informs |this| that a navigation has taken place to this' |url_| and any
// prefetched subresources should be loaded from cache.
void NotifyPageNavigatedToAfterSRP();
// Informs |this| that the origin probe to this' |url_| failed and no
// prefetched subresources should be loaded from cache.
void NotifyProbeFailed();
// prerender::NoStatePrefetchHandle::Observer:
void OnPrefetchStop(prerender::NoStatePrefetchHandle* handle) override;
void OnPrefetchNetworkBytesChanged(
prerender::NoStatePrefetchHandle* handle) override {}
// PrefetchProxyProxyingURLLoaderFactory::ResourceMetricsObserver:
void OnResourceFetchComplete(
const GURL& url,
network::mojom::URLResponseHeadPtr head,
const network::URLLoaderCompletionStatus& status) override;
void OnResourceNotEligible(const GURL& url,
PrefetchProxyPrefetchStatus status) override;
void OnResourceThrottled(const GURL& url) override;
void OnProxyUnavailableForResource(const GURL& url) override;
void OnResourceUsedFromCache(const GURL& url) override;
PrefetchProxySubresourceManager(const PrefetchProxySubresourceManager&) =
delete;
PrefetchProxySubresourceManager& operator=(
const PrefetchProxySubresourceManager&) = delete;
private:
// Returns true if |MaybeProxyURLLoaderFactory| should proxy subresource loads
// for a NSP.
bool ShouldProxyForPrerenderNavigation(
int render_process_id,
content::ContentBrowserClient::URLLoaderFactoryType type);
// Returns true if |MaybeProxyURLLoaderFactory| should proxy subresource loads
// for a navigation was that previously prerendered.
bool ShouldProxyForAfterSRPNavigation() const;
// Called when the given factory is done serving all requests and can be
// destroyed.
void RemoveProxiedURLLoaderFactory(
PrefetchProxyProxyingURLLoaderFactory* factory);
// Used as
// |PrefetchProxyProxyingURLLoaderFactory::ResourceLoadSuccessfulCallback|
// to report a subresource was successfully loaded during the NSP.
void OnSubresourceLoadSuccessful(const GURL& url);
// The page that is being prerendered.
const GURL url_;
// Set in |NotifyPageNavigatedToAfterSRP| to signify that any subresource
// loads in |successfully_loaded_subresources_| should be loaded from
// |isolated_loader_factory_|'s cache but otherwise this is a normal page load
// that can use the normal Profile's network context.
bool was_navigated_to_after_srp_ = false;
// All the subresources that have been successfully loaded during the NSP.
// Each step in a subresource's redirect chain is also added here so that
// those steps can be used from the network cache later as well.
std::set<GURL> successfully_loaded_subresources_;
// The mainframe response headers and body.
std::unique_ptr<PrefetchedMainframeResponseContainer> mainframe_response_;
// Collects metrics from the implementation of
// |PrefetchProxyProxyingURLLoaderFactory::ResourceMetricsObserver|.
scoped_refptr<PrefetchProxyPrefetchMetricsCollector> metrics_collector_;
// State for managing the NoStatePrerender when it is running. If
// |nsp_handle_| is set, then |on_nsp_done_callback_| is also set and vise
// versa.
std::unique_ptr<prerender::NoStatePrefetchHandle> nsp_handle_;
base::OnceClosure on_nsp_done_callback_;
// All owned proxying URL Loader Factories.
std::set<std::unique_ptr<PrefetchProxyProxyingURLLoaderFactory>,
base::UniquePtrComparator>
proxied_loader_factories_;
// A callback to create new URL Loader Factories for loading subresources.
CreateIsolatedLoaderFactoryRepeatingCallback
create_isolated_loader_factory_callback_;
base::WeakPtrFactory<PrefetchProxySubresourceManager> weak_factory_{this};
};
#endif // CHROME_BROWSER_PREFETCH_PREFETCH_PROXY_PREFETCH_PROXY_SUBRESOURCE_MANAGER_H_