Commit db67b537 authored by Kinuko Yasuda's avatar Kinuko Yasuda Committed by Commit Bot

Introduce prefetch urlloader

(Partly as a preparation to add more logic for htxg-specific prefetch
plumbing)

Introduce prefetch-specific URLLoader which does:
- Basically just forwards the request to the underlying network loader
- Doesn't forward back the data to the renderer process, which used to
  be just discarded in the renderer process anyways.

This is hooked as follows:
- When NetworkService is enabled LinkLoader gets PrefetchURLLoaderFactory
  via PrefetchURLLoaderService and sets it as ResourceLoaderOptions.
  url_loader_factory.
- When NetworkService is NOT enabled this is directly hooked from the
  ResourceMessageFilter.

In both cases the URLLoaderFactory is owned by StoragePartition,
partially because it makes various plumbing (including tests) easier.

Optionally we can make it live longer than the client process, though
it is not currently implemented. (So no behavior change is expected
with this one)

Bug: 803776
Change-Id: Ia4b33048a7c6d27a80044d99b62a1cc5faad5681
Reviewed-on: https://chromium-review.googlesource.com/912051
Commit-Queue: Kinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarTsuyoshi Horo <horo@chromium.org>
Reviewed-by: default avatarYutaka Hirano <yhirano@chromium.org>
Cr-Commit-Position: refs/heads/master@{#537605}
parent 5a894878
......@@ -1002,6 +1002,10 @@ jumbo_source_set("browser") {
"loader/navigation_url_loader_network_service.h",
"loader/null_resource_controller.cc",
"loader/null_resource_controller.h",
"loader/prefetch_url_loader.cc",
"loader/prefetch_url_loader.h",
"loader/prefetch_url_loader_factory.cc",
"loader/prefetch_url_loader_factory.h",
"loader/redirect_to_file_resource_handler.cc",
"loader/redirect_to_file_resource_handler.h",
"loader/resource_buffer.cc",
......
......@@ -51,6 +51,7 @@
#include "content/browser/installedapp/installed_app_provider_impl_default.h"
#include "content/browser/interface_provider_filtering.h"
#include "content/browser/keyboard_lock/keyboard_lock_service_impl.h"
#include "content/browser/loader/prefetch_url_loader_factory.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_scheduler_filter.h"
#include "content/browser/media/capture/audio_mirroring_manager.h"
......@@ -3231,6 +3232,15 @@ void RenderFrameHostImpl::RegisterMojoInterfaces() {
// TODO(crbug.com/775792): Move to RendererInterfaceBinders.
registry_->AddInterface(base::BindRepeating(
&QuotaDispatcherHost::CreateForFrame, GetProcess(), routing_id_));
if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
StoragePartitionImpl* storage_partition =
static_cast<StoragePartitionImpl*>(BrowserContext::GetStoragePartition(
GetSiteInstance()->GetBrowserContext(), GetSiteInstance()));
registry_->AddInterface(base::BindRepeating(
&PrefetchURLLoaderFactory::ConnectToService,
base::RetainedRef(storage_partition->GetPrefetchURLLoaderFactory())));
}
}
void RenderFrameHostImpl::ResetWaitingState() {
......
......@@ -11,6 +11,10 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "content/browser/loader/prefetch_url_loader_factory.h"
#include "content/browser/storage_partition_impl.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_features.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
......@@ -21,8 +25,18 @@
namespace content {
class PrefetchBrowserTest : public ContentBrowserTest,
public testing::WithParamInterface<bool> {
struct PrefetchBrowserTestParam {
PrefetchBrowserTestParam(bool network_service_enabled,
bool signed_exchange_enabled)
: network_service_enabled(network_service_enabled),
signed_exchange_enabled(signed_exchange_enabled) {}
const bool network_service_enabled;
const bool signed_exchange_enabled;
};
class PrefetchBrowserTest
: public ContentBrowserTest,
public testing::WithParamInterface<PrefetchBrowserTestParam> {
public:
struct ResponseEntry {
ResponseEntry() = default;
......@@ -41,11 +55,29 @@ class PrefetchBrowserTest : public ContentBrowserTest,
~PrefetchBrowserTest() = default;
void SetUp() override {
if (GetParam())
feature_list_.InitWithFeatures({network::features::kNetworkService}, {});
std::vector<base::Feature> enable_features;
if (GetParam().network_service_enabled)
enable_features.push_back(network::features::kNetworkService);
if (GetParam().signed_exchange_enabled)
enable_features.push_back(features::kSignedHTTPExchange);
feature_list_.InitWithFeatures(enable_features, {});
ContentBrowserTest::SetUp();
}
void SetUpOnMainThread() override {
ContentBrowserTest::SetUpOnMainThread();
StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
BrowserContext::GetDefaultStoragePartition(
shell()->web_contents()->GetBrowserContext()));
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
BindOnce(
&PrefetchURLLoaderFactory::RegisterPrefetchLoaderCallbackForTest,
base::RetainedRef(partition->GetPrefetchURLLoaderFactory()),
base::BindRepeating(&PrefetchBrowserTest::OnPrefetchURLLoaderCalled,
base::Unretained(this))));
}
void RegisterResponse(const std::string& url, const ResponseEntry& entry) {
response_map_[url] = entry;
}
......@@ -76,6 +108,17 @@ class PrefetchBrowserTest : public ContentBrowserTest,
}
}
void OnPrefetchURLLoaderCalled() { prefetch_url_loader_called_++; }
bool CheckPrefetchURLLoaderCountIfSupported(int expected) const {
if (!base::FeatureList::IsEnabled(features::kSignedHTTPExchange) &&
!base::FeatureList::IsEnabled(network::features::kNetworkService))
return true;
return prefetch_url_loader_called_ == expected;
}
int prefetch_url_loader_called_ = 0;
private:
base::test::ScopedFeatureList feature_list_;
std::map<std::string, ResponseEntry> response_map_;
......@@ -102,12 +145,14 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, Simple) {
&PrefetchBrowserTest::ServeResponses, base::Unretained(this)));
ASSERT_TRUE(embedded_test_server()->Start());
EXPECT_EQ(0, target_fetch_count);
EXPECT_TRUE(CheckPrefetchURLLoaderCountIfSupported(0));
// Loading a page that prefetches the target URL would increment the
// |target_fetch_count|.
NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_url));
prefetch_waiter.Run();
EXPECT_EQ(1, target_fetch_count);
EXPECT_TRUE(CheckPrefetchURLLoaderCountIfSupported(1));
// Subsequent navigation to the target URL wouldn't hit the network for
// the target URL (therefore not increment |target_fetch_count|.
......@@ -138,12 +183,14 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, DoublePrefetch) {
&PrefetchBrowserTest::ServeResponses, base::Unretained(this)));
ASSERT_TRUE(embedded_test_server()->Start());
EXPECT_EQ(0, target_fetch_count);
EXPECT_TRUE(CheckPrefetchURLLoaderCountIfSupported(0));
// Loading a page that prefetches the target URL would increment the
// |target_fetch_count|, but it should hit only once.
NavigateToURL(shell(), embedded_test_server()->GetURL(prefetch_url));
prefetch_waiter.Run();
EXPECT_EQ(1, target_fetch_count);
EXPECT_TRUE(CheckPrefetchURLLoaderCountIfSupported(1));
// Subsequent navigation to the target URL wouldn't hit the network for
// the target URL (therefore not increment |target_fetch_count|.
......@@ -153,6 +200,7 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, DoublePrefetch) {
NavigateToURL(shell(), embedded_test_server()->GetURL(target_url));
EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
EXPECT_EQ(1, target_fetch_count);
EXPECT_TRUE(CheckPrefetchURLLoaderCountIfSupported(1));
}
IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, NoCacheAndNoStore) {
......@@ -184,6 +232,7 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, NoCacheAndNoStore) {
embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
&PrefetchBrowserTest::ServeResponses, base::Unretained(this)));
ASSERT_TRUE(embedded_test_server()->Start());
EXPECT_TRUE(CheckPrefetchURLLoaderCountIfSupported(0));
// Loading a page that prefetches the target URL would increment the
// fetch count for the both targets.
......@@ -192,6 +241,7 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, NoCacheAndNoStore) {
nostore_waiter.Run();
EXPECT_EQ(1, nocache_fetch_count);
EXPECT_EQ(1, nostore_fetch_count);
EXPECT_TRUE(CheckPrefetchURLLoaderCountIfSupported(2));
{
// Subsequent navigation to the no-cache URL wouldn't hit the network,
......@@ -211,6 +261,7 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, NoCacheAndNoStore) {
EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
EXPECT_EQ(2, nostore_fetch_count);
}
EXPECT_TRUE(CheckPrefetchURLLoaderCountIfSupported(2));
}
IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, WithPreload) {
......@@ -241,6 +292,7 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, WithPreload) {
embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
&PrefetchBrowserTest::ServeResponses, base::Unretained(this)));
ASSERT_TRUE(embedded_test_server()->Start());
EXPECT_TRUE(CheckPrefetchURLLoaderCountIfSupported(0));
// Loading a page that prefetches the target URL would increment both
// |target_fetch_count| and |preload_fetch_count|.
......@@ -248,6 +300,7 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, WithPreload) {
preload_waiter.Run();
EXPECT_EQ(1, target_fetch_count);
EXPECT_EQ(1, preload_fetch_count);
EXPECT_TRUE(CheckPrefetchURLLoaderCountIfSupported(1));
int preload_url_entries = 0;
while (preload_url_entries == 0) {
......@@ -265,6 +318,10 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest, WithPreload) {
INSTANTIATE_TEST_CASE_P(PrefetchBrowserTest,
PrefetchBrowserTest,
testing::Bool());
testing::Values(PrefetchBrowserTestParam(true, true),
PrefetchBrowserTestParam(true, false),
PrefetchBrowserTestParam(false, true),
PrefetchBrowserTestParam(false,
false)));
} // namespace content
// Copyright 2018 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 "content/browser/loader/prefetch_url_loader.h"
namespace content {
PrefetchURLLoader::PrefetchURLLoader(
int32_t routing_id,
int32_t request_id,
uint32_t options,
const network::ResourceRequest& resource_request,
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
network::mojom::URLLoaderFactory* network_loader_factory)
: network_client_binding_(this), forwarding_client_(std::move(client)) {
DCHECK(network_loader_factory);
network::mojom::URLLoaderClientPtr network_client;
network_client_binding_.Bind(mojo::MakeRequest(&network_client));
network_client_binding_.set_connection_error_handler(base::BindOnce(
&PrefetchURLLoader::OnNetworkConnectionError, base::Unretained(this)));
network_loader_factory->CreateLoaderAndStart(
mojo::MakeRequest(&network_loader_), routing_id, request_id, options,
resource_request, std::move(network_client), traffic_annotation);
}
PrefetchURLLoader::~PrefetchURLLoader() = default;
void PrefetchURLLoader::FollowRedirect() {
network_loader_->FollowRedirect();
}
void PrefetchURLLoader::ProceedWithResponse() {
network_loader_->ProceedWithResponse();
}
void PrefetchURLLoader::SetPriority(net::RequestPriority priority,
int intra_priority_value) {
network_loader_->SetPriority(priority, intra_priority_value);
}
void PrefetchURLLoader::PauseReadingBodyFromNet() {
network_loader_->PauseReadingBodyFromNet();
}
void PrefetchURLLoader::ResumeReadingBodyFromNet() {
network_loader_->ResumeReadingBodyFromNet();
}
void PrefetchURLLoader::OnReceiveResponse(
const network::ResourceResponseHead& head,
const base::Optional<net::SSLInfo>& ssl_info,
network::mojom::DownloadedTempFilePtr downloaded_file) {
forwarding_client_->OnReceiveResponse(head, ssl_info,
std::move(downloaded_file));
}
void PrefetchURLLoader::OnReceiveRedirect(
const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& head) {
forwarding_client_->OnReceiveRedirect(redirect_info, head);
}
void PrefetchURLLoader::OnDataDownloaded(int64_t data_length,
int64_t encoded_length) {
forwarding_client_->OnDataDownloaded(data_length, encoded_length);
}
void PrefetchURLLoader::OnUploadProgress(int64_t current_position,
int64_t total_size,
base::OnceCallback<void()> callback) {
forwarding_client_->OnUploadProgress(current_position, total_size,
std::move(callback));
}
void PrefetchURLLoader::OnReceiveCachedMetadata(
const std::vector<uint8_t>& data) {
// Just drop this; we don't need to forward this to the renderer
// for prefetch.
}
void PrefetchURLLoader::OnTransferSizeUpdated(int32_t transfer_size_diff) {
forwarding_client_->OnTransferSizeUpdated(transfer_size_diff);
}
void PrefetchURLLoader::OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) {
// Just drain this here; we don't need to forward the body data to
// the renderer for prefetch.
DCHECK(!pipe_drainer_);
pipe_drainer_ =
std::make_unique<mojo::common::DataPipeDrainer>(this, std::move(body));
}
void PrefetchURLLoader::OnComplete(
const network::URLLoaderCompletionStatus& status) {
forwarding_client_->OnComplete(status);
}
void PrefetchURLLoader::OnNetworkConnectionError() {
// The network loader has an error; we should let the client know it's closed
// by dropping this, which will in turn make this loader destroyed.
forwarding_client_.reset();
}
} // namespace content
// Copyright 2018 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 CONTENT_BROWSER_LOADER_PREFETCH_URL_LOADER_H_
#define CONTENT_BROWSER_LOADER_PREFETCH_URL_LOADER_H_
#include <memory>
#include "base/macros.h"
#include "content/common/content_export.h"
#include "mojo/common/data_pipe_drainer.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "url/gurl.h"
namespace content {
// PrefetchURLLoader which basically just keeps draining the data.
class CONTENT_EXPORT PrefetchURLLoader
: public network::mojom::URLLoader,
public network::mojom::URLLoaderClient,
public mojo::common::DataPipeDrainer::Client {
public:
PrefetchURLLoader(
int32_t routing_id,
int32_t request_id,
uint32_t options,
const network::ResourceRequest& resource_request,
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
network::mojom::URLLoaderFactory* network_loader_factory);
~PrefetchURLLoader() override;
private:
// network::mojom::URLLoader overrides:
void FollowRedirect() override;
void ProceedWithResponse() override;
void SetPriority(net::RequestPriority priority,
int intra_priority_value) override;
void PauseReadingBodyFromNet() override;
void ResumeReadingBodyFromNet() override;
// network::mojom::URLLoaderClient overrides:
void OnReceiveResponse(
const network::ResourceResponseHead& head,
const base::Optional<net::SSLInfo>& ssl_info,
network::mojom::DownloadedTempFilePtr downloaded_file) override;
void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& head) override;
void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override;
void OnUploadProgress(int64_t current_position,
int64_t total_size,
base::OnceCallback<void()> callback) override;
void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override;
void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
void OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) override;
void OnComplete(const network::URLLoaderCompletionStatus& status) override;
// mojo::common::DataPipeDrainer::Client overrides:
// This just does nothing but keep reading.
void OnDataAvailable(const void* data, size_t num_bytes) override {}
void OnDataComplete() override {}
void OnNetworkConnectionError();
// For the actual request.
network::mojom::URLLoaderPtr network_loader_;
mojo::Binding<network::mojom::URLLoaderClient> network_client_binding_;
// To be a URLLoader for the client.
network::mojom::URLLoaderClientPtr forwarding_client_;
std::unique_ptr<mojo::common::DataPipeDrainer> pipe_drainer_;
DISALLOW_COPY_AND_ASSIGN(PrefetchURLLoader);
};
} // namespace content
#endif // CONTENT_BROWSER_LOADER_PREFETCH_URL_LOADER_H_
// Copyright 2018 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 "content/browser/loader/prefetch_url_loader_factory.h"
#include "base/feature_list.h"
#include "content/browser/loader/prefetch_url_loader.h"
#include "content/browser/url_loader_factory_getter.h"
#include "content/common/wrapper_shared_url_loader_factory.h"
#include "content/public/common/resource_type.h"
#include "content/public/common/shared_url_loader_factory.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/network/public/cpp/features.h"
namespace content {
PrefetchURLLoaderFactory::PrefetchURLLoaderFactory(
scoped_refptr<URLLoaderFactoryGetter> factory_getter)
: loader_factory_getter_(std::move(factory_getter)) {}
void PrefetchURLLoaderFactory::ConnectToService(
blink::mojom::PrefetchURLLoaderServiceRequest request) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
// TODO(https://crbug.com/813479): Investigate why we need this branch
// and remove it after we found the root cause. Bind calls to the
// BindRegistry should come on to the IO thread, but it looks we hit
// here in browser tests (but not in full chrome build), i.e.
// in content/browser/loader/prefetch_browsertest.cc.
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&PrefetchURLLoaderFactory::ConnectToService, this,
std::move(request)));
return;
}
service_bindings_.AddBinding(this, std::move(request));
}
void PrefetchURLLoaderFactory::GetFactory(
network::mojom::URLLoaderFactoryRequest request) {
Clone(std::move(request));
}
void PrefetchURLLoaderFactory::CreateLoaderAndStart(
network::mojom::URLLoaderRequest request,
int32_t routing_id,
int32_t request_id,
uint32_t options,
const network::ResourceRequest& resource_request,
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
network::mojom::URLLoaderFactory* network_loader_factory) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK_EQ(RESOURCE_TYPE_PREFETCH, resource_request.resource_type);
if (prefetch_load_callback_for_testing_)
prefetch_load_callback_for_testing_.Run();
// For now we strongly bind the loader to the request, while we can
// also possibly make the new loader owned by the factory so that
// they can live longer than the client (i.e. run in detached mode).
// TODO(kinuko): Revisit this.
mojo::MakeStrongBinding(
std::make_unique<PrefetchURLLoader>(
routing_id, request_id, options, resource_request, std::move(client),
traffic_annotation, network_loader_factory),
std::move(request));
}
PrefetchURLLoaderFactory::~PrefetchURLLoaderFactory() = default;
void PrefetchURLLoaderFactory::CreateLoaderAndStart(
network::mojom::URLLoaderRequest request,
int32_t routing_id,
int32_t request_id,
uint32_t options,
const network::ResourceRequest& resource_request,
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
if (!network_loader_factory_ || network_loader_factory_.encountered_error()) {
loader_factory_getter_->GetNetworkFactory()->Clone(
mojo::MakeRequest(&network_loader_factory_));
}
CreateLoaderAndStart(std::move(request), routing_id, request_id, options,
resource_request, std::move(client), traffic_annotation,
network_loader_factory_.get());
}
void PrefetchURLLoaderFactory::Clone(
network::mojom::URLLoaderFactoryRequest request) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
bindings_.AddBinding(this, std::move(request));
}
} // namespace content
// Copyright 2018 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 CONTENT_BROWSER_LOADER_PREFETCH_URL_LOADER_FACTORY_H_
#define CONTENT_BROWSER_LOADER_PREFETCH_URL_LOADER_FACTORY_H_
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_thread.h"
#include "mojo/public/cpp/bindings/strong_binding_set.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "third_party/WebKit/common/loader/prefetch_url_loader_service.mojom.h"
namespace content {
class URLLoaderFactoryGetter;
class CONTENT_EXPORT PrefetchURLLoaderFactory final
: public base::RefCountedThreadSafe<PrefetchURLLoaderFactory,
BrowserThread::DeleteOnIOThread>,
public network::mojom::URLLoaderFactory,
public blink::mojom::PrefetchURLLoaderService {
public:
// |factory_getter| could be null in non-NetworkService case.
explicit PrefetchURLLoaderFactory(
scoped_refptr<URLLoaderFactoryGetter> network_loader_factory);
void ConnectToService(blink::mojom::PrefetchURLLoaderServiceRequest request);
// blink::mojom::PrefetchURLLoaderService:
void GetFactory(network::mojom::URLLoaderFactoryRequest request) override;
// Used only when NetworkService is not enabled (or indirectly via the
// other CreateLoaderAndStart when NetworkService is enabled).
// This creates a loader and starts fetching using the given
// |network_lader_factory|.
void CreateLoaderAndStart(
network::mojom::URLLoaderRequest request,
int32_t routing_id,
int32_t request_id,
uint32_t options,
const network::ResourceRequest& resource_request,
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
network::mojom::URLLoaderFactory* factory);
// Register a callback that is fired right before a prefetch load is started
// by this factory.
void RegisterPrefetchLoaderCallbackForTest(
const base::RepeatingClosure& prefetch_load_callback) {
prefetch_load_callback_for_testing_ = prefetch_load_callback;
}
private:
friend class base::DeleteHelper<content::PrefetchURLLoaderFactory>;
friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
~PrefetchURLLoaderFactory() override;
// network::mojom::URLLoaderFactory:
void CreateLoaderAndStart(network::mojom::URLLoaderRequest request,
int32_t routing_id,
int32_t request_id,
uint32_t options,
const network::ResourceRequest& resource_request,
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag&
traffic_annotation) override;
void Clone(network::mojom::URLLoaderFactoryRequest request) override;
mojo::BindingSet<network::mojom::URLLoaderFactory> bindings_;
mojo::BindingSet<blink::mojom::PrefetchURLLoaderService> service_bindings_;
scoped_refptr<URLLoaderFactoryGetter> loader_factory_getter_;
network::mojom::URLLoaderFactoryPtr network_loader_factory_;
base::RepeatingClosure prefetch_load_callback_for_testing_;
DISALLOW_COPY_AND_ASSIGN(PrefetchURLLoaderFactory);
};
} // namespace content
#endif // CONTENT_BROWSER_LOADER_PREFETCH_URL_LOADER_FACTORY_H_
......@@ -127,6 +127,7 @@ class TestFilterSpecifyingChild : public ResourceMessageFilter {
nullptr,
nullptr,
nullptr,
nullptr,
base::Bind(&TestFilterSpecifyingChild::GetContexts,
base::Unretained(this)),
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)),
......
......@@ -8,13 +8,16 @@
#include "base/logging.h"
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/loader/prefetch_url_loader_factory.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_requester_info.h"
#include "content/browser/loader/url_loader_factory_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/common/resource_messages.h"
#include "content/common/weak_wrapper_shared_url_loader_factory.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_context.h"
#include "content/public/common/content_features.h"
#include "services/network/public/cpp/cors/cors_url_loader_factory.h"
#include "services/network/public/cpp/features.h"
#include "storage/browser/fileapi/file_system_context.h"
......@@ -31,6 +34,7 @@ ResourceMessageFilter::ResourceMessageFilter(
ChromeBlobStorageContext* blob_storage_context,
storage::FileSystemContext* file_system_context,
ServiceWorkerContextWrapper* service_worker_context,
PrefetchURLLoaderFactory* prefetch_url_loader_factory,
const GetContextsCallback& get_contexts_callback,
const scoped_refptr<base::SingleThreadTaskRunner>& io_thread_runner)
: BrowserMessageFilter(ResourceMsgStart),
......@@ -43,6 +47,7 @@ ResourceMessageFilter::ResourceMessageFilter(
file_system_context,
service_worker_context,
get_contexts_callback)),
prefetch_url_loader_factory_(prefetch_url_loader_factory),
io_thread_task_runner_(io_thread_runner),
weak_ptr_factory_(this) {}
......@@ -60,6 +65,7 @@ void ResourceMessageFilter::OnFilterAdded(IPC::Channel*) {
void ResourceMessageFilter::OnChannelClosing() {
DCHECK(io_thread_task_runner_->BelongsToCurrentThread());
prefetch_url_loader_factory_ = nullptr;
url_loader_factory_ = nullptr;
// Unhook us from all pending network requests so they don't get sent to a
......@@ -108,6 +114,17 @@ void ResourceMessageFilter::CreateLoaderAndStart(
return;
}
// TODO(kinuko): Remove this flag guard when we have more confidence, this
// doesn't need to be paired up with SignedExchange feature.
if (base::FeatureList::IsEnabled(features::kSignedHTTPExchange) &&
url_request.resource_type == RESOURCE_TYPE_PREFETCH &&
prefetch_url_loader_factory_) {
prefetch_url_loader_factory_->CreateLoaderAndStart(
std::move(request), routing_id, request_id, options, url_request,
std::move(client), traffic_annotation, url_loader_factory_.get());
return;
}
url_loader_factory_->CreateLoaderAndStart(
std::move(request), routing_id, request_id, options, url_request,
std::move(client), traffic_annotation);
......
......@@ -32,6 +32,7 @@ class URLRequestContext;
namespace content {
class ChromeAppCacheService;
class ChromeBlobStorageContext;
class PrefetchURLLoaderFactory;
class ResourceContext;
class ResourceRequesterInfo;
class ServiceWorkerContextWrapper;
......@@ -60,6 +61,7 @@ class CONTENT_EXPORT ResourceMessageFilter
ChromeBlobStorageContext* blob_storage_context,
storage::FileSystemContext* file_system_context,
ServiceWorkerContextWrapper* service_worker_context,
PrefetchURLLoaderFactory* prefetch_url_loader_factory,
const GetContextsCallback& get_contexts_callback,
const scoped_refptr<base::SingleThreadTaskRunner>& io_thread_runner);
......@@ -115,6 +117,8 @@ class CONTENT_EXPORT ResourceMessageFilter
std::unique_ptr<network::mojom::URLLoaderFactory> url_loader_factory_;
scoped_refptr<PrefetchURLLoaderFactory> prefetch_url_loader_factory_;
// Task runner for the IO thead.
scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner_;
......
......@@ -91,6 +91,7 @@ class URLLoaderFactoryImplTest : public ::testing::TestWithParam<size_t> {
nullptr,
nullptr,
nullptr,
nullptr,
base::Bind(&URLLoaderFactoryImplTest::GetContexts,
base::Unretained(this)),
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO))) {
......
......@@ -1723,7 +1723,9 @@ void RenderProcessHostImpl::CreateMessageFilters() {
GetID(), storage_partition_impl_->GetAppCacheService(),
blob_storage_context.get(),
storage_partition_impl_->GetFileSystemContext(),
storage_partition_impl_->GetServiceWorkerContext(), get_contexts_callback,
storage_partition_impl_->GetServiceWorkerContext(),
storage_partition_impl_->GetPrefetchURLLoaderFactory(),
get_contexts_callback,
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
AddFilter(resource_message_filter_.get());
......
......@@ -25,6 +25,7 @@
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/fileapi/browser_file_system_helper.h"
#include "content/browser/gpu/shader_cache_factory.h"
#include "content/browser/loader/prefetch_url_loader_factory.h"
#include "content/browser/notifications/platform_notification_context_impl.h"
#include "content/common/dom_storage/dom_storage_types.h"
#include "content/public/browser/browser_context.h"
......@@ -687,6 +688,10 @@ std::unique_ptr<StoragePartitionImpl> StoragePartitionImpl::Create(
partition->appcache_service_->set_url_loader_factory_getter(
partition->url_loader_factory_getter_.get());
partition->prefetch_url_loader_factory_ =
base::MakeRefCounted<PrefetchURLLoaderFactory>(
partition->url_loader_factory_getter_);
return partition;
}
......@@ -835,6 +840,10 @@ BlobRegistryWrapper* StoragePartitionImpl::GetBlobRegistry() {
return blob_registry_.get();
}
PrefetchURLLoaderFactory* StoragePartitionImpl::GetPrefetchURLLoaderFactory() {
return prefetch_url_loader_factory_.get();
}
void StoragePartitionImpl::OpenLocalStorage(
const url::Origin& origin,
mojo::InterfaceRequest<mojom::LevelDBWrapper> request) {
......
......@@ -49,6 +49,7 @@ namespace content {
class BackgroundFetchContext;
class BlobRegistryWrapper;
class BlobURLLoaderFactory;
class PrefetchURLLoaderFactory;
class CONTENT_EXPORT StoragePartitionImpl
: public StoragePartition,
......@@ -143,6 +144,7 @@ class CONTENT_EXPORT StoragePartitionImpl
BluetoothAllowedDevicesMap* GetBluetoothAllowedDevicesMap();
BlobURLLoaderFactory* GetBlobURLLoaderFactory();
BlobRegistryWrapper* GetBlobRegistry();
PrefetchURLLoaderFactory* GetPrefetchURLLoaderFactory();
// mojom::StoragePartitionService interface.
void OpenLocalStorage(
......@@ -308,6 +310,7 @@ class CONTENT_EXPORT StoragePartitionImpl
scoped_refptr<BluetoothAllowedDevicesMap> bluetooth_allowed_devices_map_;
scoped_refptr<BlobURLLoaderFactory> blob_url_loader_factory_;
scoped_refptr<BlobRegistryWrapper> blob_registry_;
scoped_refptr<PrefetchURLLoaderFactory> prefetch_url_loader_factory_;
// BindingSet for StoragePartitionService, using the process id as the
// binding context type. The process id can subsequently be used during
......
......@@ -139,6 +139,7 @@
"blink::mojom::MediaSessionService",
"blink::mojom::NotificationService",
"blink::mojom::PermissionService",
"blink::mojom::PrefetchURLLoaderService",
"blink::mojom::PresentationService",
"blink::mojom::QuotaDispatcherHost",
"blink::mojom::TextSuggestionHost",
......
......@@ -19,6 +19,7 @@ include_rules = [
"+public/platform",
"+public/web",
"+services/metrics/public",
"+services/network/public/cpp/features.h",
"+services/network/public/mojom",
"+services/resource_coordinator/public/cpp/resource_coordinator_features.h",
"+services/service_manager/public",
......
......@@ -102,6 +102,8 @@
#include "public/platform/InterfaceProvider.h"
#include "public/platform/InterfaceRegistry.h"
#include "public/platform/WebURLRequest.h"
#include "services/network/public/cpp/features.h"
#include "services/service_manager/public/cpp/interface_provider.h"
namespace blink {
......@@ -941,6 +943,16 @@ static bool CanAccessAncestor(const SecurityOrigin& active_security_origin,
return false;
}
blink::mojom::blink::PrefetchURLLoaderService*
LocalFrame::PrefetchURLLoaderService() {
if (!prefetch_loader_service_ &&
base::FeatureList::IsEnabled(network::features::kNetworkService)) {
GetInterfaceProvider().GetInterface(
mojo::MakeRequest(&prefetch_loader_service_));
}
return prefetch_loader_service_.get();
}
bool LocalFrame::CanNavigateWithoutFramebusting(const Frame& target_frame,
String& reason) {
if (&target_frame == this)
......
......@@ -44,6 +44,7 @@
#include "platform/Supplementable.h"
#include "platform/heap/Handle.h"
#include "platform/scroll/ScrollTypes.h"
#include "third_party/WebKit/common/loader/prefetch_url_loader_service.mojom-blink.h"
namespace service_manager {
class InterfaceProvider;
......@@ -307,6 +308,9 @@ class CORE_EXPORT LocalFrame final : public Frame,
// preview.
bool IsUsingDataSavingPreview() const;
// Prefetch URLLoader service. May return nullptr.
blink::mojom::blink::PrefetchURLLoaderService* PrefetchURLLoaderService();
private:
friend class FrameNavigationDisabler;
......@@ -373,6 +377,8 @@ class CORE_EXPORT LocalFrame final : public Frame,
// Per-frame URLLoader factory.
std::unique_ptr<WebURLLoaderFactory> url_loader_factory_;
blink::mojom::blink::PrefetchURLLoaderServicePtr prefetch_loader_service_;
};
inline FrameLoader& LocalFrame::Loader() const {
......
......@@ -524,6 +524,15 @@ static Resource* PrefetchIfNeeded(const LinkLoadParameters& params,
ResourceLoaderOptions options;
options.initiator_info.name = FetchInitiatorTypeNames::link;
auto service = document.GetFrame()->PrefetchURLLoaderService();
if (service) {
network::mojom::blink::URLLoaderFactoryPtr prefetch_url_loader_factory;
service->GetFactory(mojo::MakeRequest(&prefetch_url_loader_factory));
options.url_loader_factory = base::MakeRefCounted<
base::RefCountedData<network::mojom::blink::URLLoaderFactoryPtr>>(
std::move(prefetch_url_loader_factory));
}
FetchParameters link_fetch_params(resource_request, options);
if (params.cross_origin != kCrossOriginAttributeNotSet) {
link_fetch_params.SetCrossOriginAccessControl(
......
......@@ -116,7 +116,7 @@ struct ResourceLoaderOptions {
// If not null, this URLLoaderFactory should be used to load this resource
// rather than whatever factory the system might otherwise use.
// Used for example for loading blob: URLs.
// Used for example for loading blob: URLs and for prefetch loading.
scoped_refptr<
base::RefCountedData<network::mojom::blink::URLLoaderFactoryPtr>>
url_loader_factory;
......
......@@ -61,6 +61,9 @@ _CONFIG = [
# Debugging helpers from //base/debug are allowed everywhere.
'base::debug::.+',
# Feature list checking.
'base::FeatureList',
# Standalone utility libraries that only depend on //base
'skia::.+',
'url::.+',
......
......@@ -124,6 +124,7 @@ mojom("mojo_platform_bindings") {
"clipboard/clipboard.mojom",
"color_chooser/color_chooser.mojom",
"feature_policy/feature_policy.mojom",
"loader/prefetch_url_loader_service.mojom",
"net/ip_address_space.mojom",
"page/page_visibility_state.mojom",
"quota/quota_dispatcher_host.mojom",
......
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
# TEAM: loading-dev@chromium.org
# COMPONENT: Blink>Loader
// Copyright 2018 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.
module blink.mojom;
import "services/network/public/mojom/url_loader_factory.mojom";
// The browser-side interface that allows renderer processes to get
// access to a special URLLoaderFactory for prefetch requests.
// The URLLoaderFactory returned by this service can load the prefetched
// resources to populate disk cache without forwarding all the payload
// back to the renderer process.
interface PrefetchURLLoaderService {
GetFactory(network.mojom.URLLoaderFactory& factory);
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment