blob: 3de4f34722e24adb5beafe096879917bd5e3f118 [file] [log] [blame]
// Copyright 2019 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_PREVIEWS_PREVIEWS_LITE_PAGE_REDIRECT_URL_LOADER_INTERCEPTOR_H_
#define CHROME_BROWSER_PREVIEWS_PREVIEWS_LITE_PAGE_REDIRECT_URL_LOADER_INTERCEPTOR_H_
#include <stdint.h>
#include <memory>
#include <set>
#include "base/memory/scoped_refptr.h"
#include "base/sequence_checker.h"
#include "chrome/browser/previews/previews_lite_page_redirect_serving_url_loader.h"
#include "chrome/browser/previews/previews_lite_page_redirect_url_loader.h"
#include "components/previews/content/previews_user_data.h"
#include "content/public/browser/url_loader_request_interceptor.h"
#include "net/http/http_request_headers.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "url/gurl.h"
namespace content {
class BrowserContext;
class NavigationHandle;
} // namespace content
class PreviewsLitePageRedirectDecider;
namespace previews {
// Reasons that a navigation is blacklisted from a lite page redirect preview.
// This enum must remain synchronized with the enum
// |PreviewsServerLitePageBlacklistReason| in
// tools/metrics/histograms/enums.xml.
enum class LitePageRedirectBlacklistReason {
// DEPRECATED: kPathSuffixBlacklisted = 0,
kNavigationToPreviewsDomain = 1,
kNavigationToPrivateDomain = 2,
kHostBypassBlacklisted = 3,
kMaxValue = kHostBypassBlacklisted,
};
// Reasons that a navigation is not eligible for a lite page redirect preview.
// This enum must remain synchronized with the enum
// |PreviewsServerLitePageIneligibleReason| in
// tools/metrics/histograms/enums.xml.
enum class LitePageRedirectIneligibleReason {
kNonHttpsScheme = 0,
// DEPRECATED: kHttpPost = 1,
kSubframeNavigation = 2,
kServerUnavailable = 3,
kInfoBarNotSeen = 4,
// DEPRECATED: kNetworkNotSlow = 5,
kLoadOriginalReload = 6,
kCookiesBlocked = 7,
// DEPRECATED: kECTUnknown = 8,
kExceededMaxNavigationRestarts = 9,
// DEPRECATED: kPreviewsState = 10,
kInvalidProxyHeaders = 11,
kServiceProbeIncomplete = 12,
kServiceProbeFailed = 13,
kMaxValue = kServiceProbeFailed,
};
// The response type from the previews server. This enum must
// remain synchronized with the enum |PreviewsServerLitePageServerResponse| in
// tools/metrics/histograms/enums.xml.
enum class LitePageRedirectServerResponse {
// A preview was served (HTTP 200).
kOk = 0,
// The client was redirected to another page (HTTP 307).
kRedirect = 1,
// The requested preview was not available (HTTP 307).
kPreviewUnavailable = 2,
// The previews server is not available (HTTP 503).
kServiceUnavailable = 3,
// The previews server responded with some other HTTP code.
kOther = 4,
// There was some network error and we did not get a response from the
// previews server.
kFailed = 5,
// The previews server did not respond after a timeout.
kTimeout = 6,
// The previews server rejected our authentication (HTTP 403).
kAuthFailure = 7,
// No response headers were available from the preview server.
kNoResponseHeaders = 8,
// The connection was closed without getting a response.
kOnCompleteBeforeOnResponse = 9,
// There was an error connecting to the previews server.
kConnectionError = 10,
kMaxValue = kConnectionError,
};
// Records an entry in the lite page redirect ineligibility histogram.
void LogLitePageRedirectIneligibleReason(
LitePageRedirectIneligibleReason reason);
// If the given URL is a LitePage Preview URL, this returns true but does not
// change the |url|. This will set |update_virtual_url_with_url| on
// NavigationEntry so that |HandlePreviewsLitePageRedirectURLRewriteReverse| is
// called when the navigation finishes. Note: This means the virtual URL will
// not be set during the navigation load. This is handled separately in UI on
// Android.
bool HandlePreviewsLitePageRedirectURLRewrite(
GURL* url,
content::BrowserContext* browser_context);
// Handles translating the given Lite Page URL to the original URL. Returns true
// if the given |url| was a preview, otherwise returns false and does not change
// |url|.
bool HandlePreviewsLitePageRedirectURLRewriteReverse(
GURL* url,
content::BrowserContext* browser_context);
// Returns the URL for a preview given by the url.
GURL GetLitePageRedirectURLForURL(const GURL& original_url);
// A class that attempts to intercept requests and fetch the Lite Page version
// of the request. Its lifetime matches that of the content/ navigation loader
// code. Currently, not fully implemented.
class PreviewsLitePageRedirectURLLoaderInterceptor
: public content::URLLoaderRequestInterceptor {
public:
PreviewsLitePageRedirectURLLoaderInterceptor(
const scoped_refptr<network::SharedURLLoaderFactory>&
network_loader_factory,
uint64_t page_id,
int frame_tree_node_id);
~PreviewsLitePageRedirectURLLoaderInterceptor() override;
// Gets the ServerLitePageInfo struct from an existing attempted lite page
// navigation, if there is one. If not, returns a new ServerLitePageInfo
// initialized with metadata from navigation_handle() and |this| that is owned
// by the PreviewsUserData associated with navigation_handle().
static PreviewsUserData::ServerLitePageInfo* GetOrCreateServerLitePageInfo(
content::NavigationHandle* navigation_handle,
PreviewsLitePageRedirectDecider* manager);
// content::URLLaoderRequestInterceptor:
void MaybeCreateLoader(
const network::ResourceRequest& tentative_resource_request,
content::BrowserContext* browser_context,
content::URLLoaderRequestInterceptor::LoaderCallback callback) override;
private:
// Begins an attempt at fetching the lite page version of the URL.
void CreateRedirectLoader(
const network::ResourceRequest& tentative_resource_request,
content::BrowserContext* browser_context,
content::URLLoaderRequestInterceptor::LoaderCallback callback);
// Creates a redirect URL loader that immediately serves a redirect to
// |original_url|.
void CreateOriginalURLLoader(
const network::ResourceRequest& tentative_resource_request,
const GURL& original_url,
content::URLLoaderRequestInterceptor::LoaderCallback callback);
// Runs |callback| with |handler| and stores |serving_url_loader|.
void HandleRedirectLoader(
content::URLLoaderRequestInterceptor::LoaderCallback callback,
std::unique_ptr<PreviewsLitePageRedirectServingURLLoader>
serving_url_loader,
RequestHandler handler);
// All URLs already seen in this navigation. This prevents redirect loops,
// etc.
std::set<GURL> urls_processed_;
// While attempting to fetch a lite page, this object manages communication
// with the lite page server and serving redirects. Once, a decision has been
// made regarding serving the preview, this object will be null.
std::unique_ptr<PreviewsLitePageRedirectURLLoader> redirect_url_loader_;
// Once a decision to serve the lite page has been made (based on server
// response), this object will exist until a redirect to the lite page URL has
// been handed off to the navigation stack and the next request is being
// handled.
std::unique_ptr<PreviewsLitePageRedirectServingURLLoader> serving_url_loader_;
// Factory to create a network service URLLoader.
scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory_;
// Used in the chrome-proxy header if a preview is attempted.
uint64_t page_id_;
// Used to create the network service URLLoader.
int frame_tree_node_id_;
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(PreviewsLitePageRedirectURLLoaderInterceptor);
};
} // namespace previews
#endif // CHROME_BROWSER_PREVIEWS_PREVIEWS_LITE_PAGE_REDIRECT_URL_LOADER_INTERCEPTOR_H_