blob: 2177a2d22b41e95497c912b370683e058897ea89 [file]
// 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.
#include "chrome/browser/prerender/isolated/isolated_prerender_url_loader.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "net/base/load_flags.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/cpp/resource_request.h"
IsolatedPrerenderURLLoader::IsolatedPrerenderURLLoader(
const network::ResourceRequest& unused_request,
const scoped_refptr<network::SharedURLLoaderFactory>&
network_loader_factory,
int32_t routing_id,
int32_t request_id)
: network_loader_factory_(network_loader_factory),
routing_id_(routing_id),
request_id_(request_id) {
// |unused_request| is not used since it has not been acted on by
// URLLoaderThrottles yet.
}
IsolatedPrerenderURLLoader::~IsolatedPrerenderURLLoader() = default;
IsolatedPrerenderURLLoader::RequestHandler
IsolatedPrerenderURLLoader::ServingResponseHandler() {
return base::BindOnce(&IsolatedPrerenderURLLoader::BindAndStart,
weak_ptr_factory_.GetWeakPtr());
}
void IsolatedPrerenderURLLoader::BindAndStart(
const network::ResourceRequest& request,
mojo::PendingReceiver<network::mojom::URLLoader> receiver,
mojo::PendingRemote<network::mojom::URLLoaderClient> forwarding_client) {
// Bind to the underlying URLLoader.
DCHECK(!receiver_.is_bound());
receiver_.Bind(std::move(receiver));
receiver_.set_disconnect_handler(
base::BindOnce(&IsolatedPrerenderURLLoader::OnConnectionError,
weak_ptr_factory_.GetWeakPtr()));
forwarding_client_.Bind(std::move(forwarding_client));
network::ResourceRequest isolated_request = request;
// TODO(crbug/1023485): Set NIK, otherwise the loading initiated here will
// share the network stack with other browser-initiated loading.
isolated_request.load_flags = isolated_request.load_flags |
net::LOAD_DISABLE_CACHE | net::LOAD_PREFETCH;
isolated_request.credentials_mode = network::mojom::CredentialsMode::kOmit;
network_loader_factory_->CreateLoaderAndStart(
network_loader_.BindNewPipeAndPassReceiver(), routing_id_, request_id_,
network::mojom::kURLLoadOptionNone, isolated_request,
network_loader_client_.BindNewPipeAndPassRemote(
base::ThreadTaskRunnerHandle::Get()),
net::MutableNetworkTrafficAnnotationTag(
net::DefineNetworkTrafficAnnotation("isolated_prerender_loader", R"(
semantics {
sender: "Isolated Prerender Loader"
description:
"Loads a webpage resource during an isolated prerender. This is "
"a prerender which is done in total isolation from other user "
"browsing data like cookies or cache state. Such prerenders will "
"be used to prefetch render-blocking content before being "
"navigated by the user without impacting privacy."
trigger:
"Used for sites off of Google SRPs (Search Result Pages) only "
"for Lite mode users when the feature is enabled."
data: "None."
destination: WEBSITE
}
policy {
cookies_allowed: YES
cookies_store: "An ephemeral cookie jar used for only 1 page load."
setting:
"Users can control Lite mode on Android via the settings menu. "
"Lite mode is not available on iOS, and on desktop only for "
"developer testing."
policy_exception_justification: "Not implemented."
})")));
network_loader_client_.set_disconnect_handler(base::BindOnce(
&IsolatedPrerenderURLLoader::OnConnectionError, base::Unretained(this)));
}
void IsolatedPrerenderURLLoader::OnReceiveResponse(
network::mojom::URLResponseHeadPtr head) {
forwarding_client_->OnReceiveResponse(std::move(head));
}
void IsolatedPrerenderURLLoader::OnReceiveRedirect(
const net::RedirectInfo& redirect_info,
network::mojom::URLResponseHeadPtr head) {
forwarding_client_->OnReceiveRedirect(redirect_info, std::move(head));
}
void IsolatedPrerenderURLLoader::OnUploadProgress(
int64_t current_position,
int64_t total_size,
OnUploadProgressCallback callback) {
forwarding_client_->OnUploadProgress(current_position, total_size,
std::move(callback));
}
void IsolatedPrerenderURLLoader::OnReceiveCachedMetadata(
mojo_base::BigBuffer data) {
forwarding_client_->OnReceiveCachedMetadata(std::move(data));
}
void IsolatedPrerenderURLLoader::OnTransferSizeUpdated(
int32_t transfer_size_diff) {
forwarding_client_->OnTransferSizeUpdated(transfer_size_diff);
}
void IsolatedPrerenderURLLoader::OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) {
forwarding_client_->OnStartLoadingResponseBody(std::move(body));
}
void IsolatedPrerenderURLLoader::OnComplete(
const network::URLLoaderCompletionStatus& status) {
forwarding_client_->OnComplete(status);
}
void IsolatedPrerenderURLLoader::FollowRedirect(
const std::vector<std::string>& removed_headers,
const net::HttpRequestHeaders& modified_headers,
const base::Optional<GURL>& new_url) {
network_loader_->FollowRedirect(removed_headers, modified_headers, new_url);
}
void IsolatedPrerenderURLLoader::SetPriority(net::RequestPriority priority,
int32_t intra_priority_value) {
network_loader_->SetPriority(priority, intra_priority_value);
}
void IsolatedPrerenderURLLoader::PauseReadingBodyFromNet() {
network_loader_->PauseReadingBodyFromNet();
}
void IsolatedPrerenderURLLoader::ResumeReadingBodyFromNet() {
network_loader_->ResumeReadingBodyFromNet();
}
void IsolatedPrerenderURLLoader::OnConnectionError() {
network_loader_.reset();
network_loader_client_.reset();
receiver_.reset();
forwarding_client_.reset();
delete this;
}