summaryrefslogtreecommitdiff
path: root/chromium/content/browser/loader
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/content/browser/loader')
-rw-r--r--chromium/content/browser/loader/cached_navigation_url_loader.cc5
-rw-r--r--chromium/content/browser/loader/cross_origin_read_blocking_checker.cc16
-rw-r--r--chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc9
-rw-r--r--chromium/content/browser/loader/loader_browsertest.cc13
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl.cc1744
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl.h232
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc3
-rw-r--r--chromium/content/browser/loader/prefetch_browsertest.cc9
-rw-r--r--chromium/content/browser/loader/prefetch_url_loader.cc2
-rw-r--r--chromium/content/browser/loader/prefetch_url_loader.h8
-rw-r--r--chromium/content/browser/loader/prefetch_url_loader_service.cc7
-rw-r--r--chromium/content/browser/loader/prefetch_url_loader_service.h12
-rw-r--r--chromium/content/browser/loader/quic_transport_browsertest.cc48
-rw-r--r--chromium/content/browser/loader/url_loader_throttles.cc2
-rw-r--r--chromium/content/browser/loader/url_loader_throttles.h36
15 files changed, 1050 insertions, 1096 deletions
diff --git a/chromium/content/browser/loader/cached_navigation_url_loader.cc b/chromium/content/browser/loader/cached_navigation_url_loader.cc
index 54c58fdb6ba..4f387dd0f7e 100644
--- a/chromium/content/browser/loader/cached_navigation_url_loader.cc
+++ b/chromium/content/browser/loader/cached_navigation_url_loader.cc
@@ -4,7 +4,6 @@
#include "content/browser/loader/cached_navigation_url_loader.h"
-#include "base/task/post_task.h"
#include "content/browser/frame_host/navigation_request_info.h"
#include "content/browser/loader/navigation_url_loader_delegate.h"
#include "content/browser/loader/navigation_url_loader_impl.h"
@@ -28,8 +27,8 @@ CachedNavigationURLLoader::CachedNavigationURLLoader(
// Normal navigations never call OnResponseStarted on the same message loop
// iteration that the NavigationURLLoader is created, because they have to
// make a network request.
- base::PostTask(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&CachedNavigationURLLoader::OnResponseStarted,
+ GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&CachedNavigationURLLoader::OnResponseStarted,
weak_factory_.GetWeakPtr()));
}
diff --git a/chromium/content/browser/loader/cross_origin_read_blocking_checker.cc b/chromium/content/browser/loader/cross_origin_read_blocking_checker.cc
index 3b4298fff67..003f89024a5 100644
--- a/chromium/content/browser/loader/cross_origin_read_blocking_checker.cc
+++ b/chromium/content/browser/loader/cross_origin_read_blocking_checker.cc
@@ -5,8 +5,8 @@
#include "content/browser/loader/cross_origin_read_blocking_checker.h"
#include "base/callback.h"
-#include "base/task/post_task.h"
#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
#include "net/base/io_buffer.h"
#include "net/base/mime_sniffer.h"
#include "services/network/cross_origin_read_blocking.h"
@@ -71,14 +71,14 @@ class CrossOriginReadBlockingChecker::BlobIOState {
}
void OnNetError() {
- base::PostTask(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&CrossOriginReadBlockingChecker::OnNetError,
+ GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&CrossOriginReadBlockingChecker::OnNetError,
checker_, blob_reader_->net_error()));
}
void OnReadComplete(int bytes_read) {
- base::PostTask(
- FROM_HERE, {BrowserThread::UI},
+ GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&CrossOriginReadBlockingChecker::OnReadComplete,
checker_, bytes_read, buffer_,
blob_reader_->net_error()));
@@ -127,8 +127,8 @@ CrossOriginReadBlockingChecker::CrossOriginReadBlockingChecker(
std::make_unique<storage::BlobDataHandle>(blob_data_handle));
// base::Unretained is safe because |blob_io_state_| will be deleted on
// the IO thread.
- base::PostTask(FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&BlobIOState::StartSniffing,
+ GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&BlobIOState::StartSniffing,
base::Unretained(blob_io_state_.get())));
return;
}
@@ -137,7 +137,7 @@ CrossOriginReadBlockingChecker::CrossOriginReadBlockingChecker(
}
CrossOriginReadBlockingChecker::~CrossOriginReadBlockingChecker() {
- base::DeleteSoon(FROM_HERE, {BrowserThread::IO}, std::move(blob_io_state_));
+ GetIOThreadTaskRunner({})->DeleteSoon(FROM_HERE, std::move(blob_io_state_));
}
int CrossOriginReadBlockingChecker::GetNetError() {
diff --git a/chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc b/chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc
index 7e630c8000f..bc26b111691 100644
--- a/chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc
+++ b/chromium/content/browser/loader/cross_site_document_blocking_browsertest.cc
@@ -17,10 +17,10 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_restrictions.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "content/browser/site_instance_impl.h"
#include "content/public/browser/browser_task_traits.h"
@@ -310,9 +310,10 @@ class RequestInterceptor {
}
if (!got_all_data) {
- base::PostTask(FROM_HERE, base::BindOnce(&RequestInterceptor::ReadBody,
- base::Unretained(this),
- std::move(completion_callback)));
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&RequestInterceptor::ReadBody, base::Unretained(this),
+ std::move(completion_callback)));
} else {
std::move(completion_callback).Run();
}
diff --git a/chromium/content/browser/loader/loader_browsertest.cc b/chromium/content/browser/loader/loader_browsertest.cc
index f82d19ea842..a229d260140 100644
--- a/chromium/content/browser/loader/loader_browsertest.cc
+++ b/chromium/content/browser/loader/loader_browsertest.cc
@@ -15,7 +15,6 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
#include "base/test/bind_test_util.h"
#include "build/build_config.h"
#include "content/browser/download/download_manager_impl.h"
@@ -68,11 +67,11 @@ class LoaderBrowserTest : public ContentBrowserTest,
protected:
void SetUpOnMainThread() override {
base::FilePath path = GetTestFilePath("", "");
- base::PostTask(
- FROM_HERE, {BrowserThread::IO},
+ GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&net::URLRequestMockHTTPJob::AddUrlHandlers, path));
- base::PostTask(FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&net::URLRequestFailedJob::AddUrlHandler));
+ GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&net::URLRequestFailedJob::AddUrlHandler));
host_resolver()->AddRule("*", "127.0.0.1");
}
@@ -281,8 +280,8 @@ std::unique_ptr<net::test_server::HttpResponse> CancelOnRequest(
if (request.relative_url != relative_url)
return nullptr;
- base::PostTask(FROM_HERE, {content::BrowserThread::UI},
- crash_network_service_callback);
+ content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE,
+ crash_network_service_callback);
return std::make_unique<net::test_server::HungResponse>();
}
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl.cc b/chromium/content/browser/loader/navigation_url_loader_impl.cc
index 9ecb16d776d..6eb68513704 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_impl.cc
@@ -16,7 +16,6 @@
#include "base/metrics/histogram_macros.h"
#include "base/optional.h"
#include "base/stl_util.h"
-#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
@@ -35,13 +34,11 @@
#include "content/browser/loader/navigation_loader_interceptor.h"
#include "content/browser/loader/navigation_url_loader_delegate.h"
#include "content/browser/loader/prefetch_url_loader_service.h"
-#include "content/browser/loader/single_request_url_loader_factory.h"
-#include "content/browser/loader/url_loader_throttles.h"
#include "content/browser/navigation_subresource_loader_params.h"
#include "content/browser/service_worker/service_worker_container_host.h"
#include "content/browser/service_worker/service_worker_main_resource_handle.h"
#include "content/browser/service_worker/service_worker_main_resource_handle_core.h"
-#include "content/browser/service_worker/service_worker_navigation_loader_interceptor.h"
+#include "content/browser/service_worker/service_worker_main_resource_loader_interceptor.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/url_loader_factory_getter.h"
#include "content/browser/web_contents/web_contents_impl.h"
@@ -62,6 +59,7 @@
#include "content/public/browser/shared_cors_origin_access_list.h"
#include "content/public/browser/ssl_status.h"
#include "content/public/browser/url_loader_request_interceptor.h"
+#include "content/public/browser/url_loader_throttles.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
@@ -142,7 +140,6 @@ class NavigationLoaderInterceptorBrowserContainer
std::unique_ptr<URLLoaderRequestInterceptor> browser_interceptor_;
};
-// Only used on the IO thread.
base::LazyInstance<NavigationURLLoaderImpl::URLLoaderFactoryInterceptor>::Leaky
g_loader_factory_interceptor = LAZY_INSTANCE_INITIALIZER;
@@ -191,11 +188,11 @@ const net::NetworkTrafficAnnotationTag kNavigationUrlLoaderTrafficAnnotation =
"combination of both) limits the scope of these requests."
)");
+// TODO(kinuko): |request_info| can likely be given as a const ref.
std::unique_ptr<network::ResourceRequest> CreateResourceRequest(
NavigationRequestInfo* request_info,
int frame_tree_node_id,
mojo::PendingRemote<network::mojom::CookieAccessObserver> cookie_observer) {
- // TODO(scottmg): Port over stuff from RDHI::BeginNavigationRequest() here.
auto new_request = std::make_unique<network::ResourceRequest>();
new_request->method = request_info->common_params->method;
@@ -250,41 +247,7 @@ std::unique_ptr<network::ResourceRequest> CreateResourceRequest(
new_request->has_user_gesture = request_info->common_params->has_user_gesture;
new_request->enable_load_timing = true;
new_request->mode = network::mojom::RequestMode::kNavigate;
-
- FrameTreeNode* frame_tree_node =
- FrameTreeNode::GloballyFindByID(frame_tree_node_id);
- if (request_info->is_main_frame) {
- new_request->destination =
- frame_tree_node &&
- WebContentsImpl::FromFrameTreeNode(frame_tree_node)->IsPortal()
- ? network::mojom::RequestDestination::kIframe
- : network::mojom::RequestDestination::kDocument;
- } else {
- if (frame_tree_node) {
- switch (frame_tree_node->frame_owner_element_type()) {
- case blink::mojom::FrameOwnerElementType::kObject:
- new_request->destination =
- network::mojom::RequestDestination::kObject;
- break;
- case blink::mojom::FrameOwnerElementType::kEmbed:
- new_request->destination = network::mojom::RequestDestination::kEmbed;
- break;
- case blink::mojom::FrameOwnerElementType::kIframe:
- new_request->destination =
- network::mojom::RequestDestination::kIframe;
- break;
- case blink::mojom::FrameOwnerElementType::kFrame:
- new_request->destination = network::mojom::RequestDestination::kFrame;
- break;
- case blink::mojom::FrameOwnerElementType::kPortal:
- case blink::mojom::FrameOwnerElementType::kNone:
- NOTREACHED();
- break;
- }
- } else {
- new_request->destination = network::mojom::RequestDestination::kDocument;
- }
- }
+ new_request->destination = request_info->begin_params->request_destination;
if (ui::PageTransitionIsWebTriggerable(
request_info->common_params->transition)) {
@@ -338,578 +301,506 @@ const char* FrameAcceptHeaderValue() {
} // namespace
-// Kept around during the lifetime of the navigation request, and is
-// responsible for dispatching a ResourceRequest to the appropriate
-// URLLoader. In order to get the right URLLoader it builds a vector
-// of NavigationLoaderInterceptors and successively calls MaybeCreateLoader
-// on each until the request is successfully handled. The same sequence
-// may be performed multiple times when redirects happen.
-// TODO(michaeln): Expose this class and add more unittests.
-class NavigationURLLoaderImpl::URLLoaderRequestController
- : public network::mojom::URLLoaderClient {
- public:
- URLLoaderRequestController(
- std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
- initial_interceptors,
- std::unique_ptr<network::ResourceRequest> resource_request,
- BrowserContext* browser_context,
- StoragePartitionImpl* storage_partition,
- const GURL& url,
- mojo::PendingReceiver<network::mojom::URLLoaderFactory>
- proxied_factory_receiver,
- mojo::PendingRemote<network::mojom::URLLoaderFactory>
- proxied_factory_remote,
- std::set<std::string> known_schemes,
- bool bypass_redirect_checks,
- const base::WeakPtr<NavigationURLLoaderImpl>& owner)
- : interceptors_(std::move(initial_interceptors)),
- resource_request_(std::move(resource_request)),
- url_(url),
- owner_(owner),
- proxied_factory_receiver_(std::move(proxied_factory_receiver)),
- proxied_factory_remote_(std::move(proxied_factory_remote)),
- known_schemes_(std::move(known_schemes)),
- bypass_redirect_checks_(bypass_redirect_checks),
- browser_context_(browser_context),
- storage_partition_(storage_partition),
- head_(network::mojom::URLResponseHead::New()) {}
-
- ~URLLoaderRequestController() override {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- // If neither OnCompleted nor OnReceivedResponse has been invoked, the
- // request was canceled before receiving a response, so log a cancellation.
- // Results after receiving a non-error response are logged in the renderer,
- // if the request is passed to one. If it's a download, or not passed to a
- // renderer for some other reason, results will not be logged for the
- // request. The net::OK check may not be necessary - the case where OK is
- // received without receiving any headers looks broken, anyways.
- if (!received_response_ && (!status_ || status_->error_code != net::OK)) {
- RecordLoadHistograms(url::Origin::Create(url_),
- resource_request_->destination,
- status_ ? status_->error_code : net::ERR_ABORTED);
- }
+// TODO(kinuko): Fix the method ordering and move these methods after the ctor.
+NavigationURLLoaderImpl::~NavigationURLLoaderImpl() {
+ // If neither OnCompleted nor OnReceivedResponse has been invoked, the
+ // request was canceled before receiving a response, so log a cancellation.
+ // Results after receiving a non-error response are logged in the renderer,
+ // if the request is passed to one. If it's a download, or not passed to a
+ // renderer for some other reason, results will not be logged for the
+ // request. The net::OK check may not be necessary - the case where OK is
+ // received without receiving any headers looks broken, anyways.
+ if (!received_response_ && (!status_ || status_->error_code != net::OK)) {
+ RecordLoadHistograms(url::Origin::Create(url_),
+ resource_request_->destination,
+ status_ ? status_->error_code : net::ERR_ABORTED);
}
+}
- static uint32_t GetURLLoaderOptions(bool is_main_frame) {
- uint32_t options = network::mojom::kURLLoadOptionNone;
-
- // Ensure that Mime sniffing works.
- options |= network::mojom::kURLLoadOptionSniffMimeType;
+uint32_t NavigationURLLoaderImpl::GetURLLoaderOptions(bool is_main_frame) {
+ uint32_t options = network::mojom::kURLLoadOptionNone;
- if (is_main_frame) {
- // SSLInfo is not needed on subframe responses because users can inspect
- // only the certificate for the main frame when using the info bubble.
- options |= network::mojom::kURLLoadOptionSendSSLInfoWithResponse;
- options |= network::mojom::kURLLoadOptionSendSSLInfoForCertificateError;
- }
+ // Ensure that Mime sniffing works.
+ options |= network::mojom::kURLLoadOptionSniffMimeType;
- return options;
+ if (is_main_frame) {
+ // SSLInfo is not needed on subframe responses because users can inspect
+ // only the certificate for the main frame when using the info bubble.
+ options |= network::mojom::kURLLoadOptionSendSSLInfoWithResponse;
+ options |= network::mojom::kURLLoadOptionSendSSLInfoForCertificateError;
}
- void Start(
- std::unique_ptr<network::PendingSharedURLLoaderFactory>
- pending_network_loader_factory,
- ServiceWorkerMainResourceHandle*
- service_worker_handle /* for UI thread only */,
- ServiceWorkerMainResourceHandleCore*
- service_worker_handle_core /* for IO thread only */,
- AppCacheNavigationHandle* appcache_handle,
- scoped_refptr<PrefetchedSignedExchangeCache>
- prefetched_signed_exchange_cache,
- scoped_refptr<SignedExchangePrefetchMetricRecorder>
- signed_exchange_prefetch_metric_recorder,
- std::unique_ptr<NavigationRequestInfo> request_info,
- std::unique_ptr<NavigationUIData> navigation_ui_data,
- mojo::PendingRemote<network::mojom::URLLoaderFactory> factory_for_webui,
- bool needs_loader_factory_interceptor,
- base::Time ui_post_time,
- std::string accept_langs) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(!started_);
- ui_to_io_time_ += (base::Time::Now() - ui_post_time);
- global_request_id_ = GlobalRequestID::MakeBrowserInitiated();
- frame_tree_node_id_ = request_info->frame_tree_node_id;
- started_ = true;
- web_contents_getter_ = base::BindRepeating(
- &WebContents::FromFrameTreeNodeId, frame_tree_node_id_);
- navigation_ui_data_ = std::move(navigation_ui_data);
- service_worker_handle_ = service_worker_handle;
-
- base::PostTask(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&NavigationURLLoaderImpl::OnRequestStarted,
- owner_, base::TimeTicks::Now()));
-
- DCHECK(pending_network_loader_factory);
- network_loader_factory_ = network::SharedURLLoaderFactory::Create(
- std::move(pending_network_loader_factory));
- if (needs_loader_factory_interceptor &&
- g_loader_factory_interceptor.Get()) {
- mojo::PendingRemote<network::mojom::URLLoaderFactory> factory;
- mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver =
- factory.InitWithNewPipeAndPassReceiver();
- g_loader_factory_interceptor.Get().Run(&receiver);
- network_loader_factory_->Clone(std::move(receiver));
- network_loader_factory_ =
- base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
- std::move(factory));
- }
+ return options;
+}
- std::string accept_value = FrameAcceptHeaderValue();
- if (signed_exchange_utils::IsSignedExchangeHandlingEnabled(
- browser_context_)) {
- accept_value.append(kAcceptHeaderSignedExchangeSuffix);
- }
- resource_request_->headers.SetHeader(net::HttpRequestHeaders::kAccept,
- accept_value);
+void NavigationURLLoaderImpl::Start(
+ std::unique_ptr<network::PendingSharedURLLoaderFactory>
+ pending_network_loader_factory,
+ AppCacheNavigationHandle* appcache_handle,
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache,
+ scoped_refptr<SignedExchangePrefetchMetricRecorder>
+ signed_exchange_prefetch_metric_recorder,
+ mojo::PendingRemote<network::mojom::URLLoaderFactory> factory_for_webui,
+ std::string accept_langs,
+ bool needs_loader_factory_interceptor) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(!started_);
+ DCHECK(!head_);
+ head_ = network::mojom::URLResponseHead::New();
+ started_ = true;
+
+ GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
+ base::BindOnce(&NavigationURLLoaderImpl::NotifyRequestStarted,
+ weak_factory_.GetWeakPtr(), base::TimeTicks::Now()));
+
+ // TODO(kinuko): This can likely be initialized in the ctor.
+ network_loader_factory_ = network::SharedURLLoaderFactory::Create(
+ std::move(pending_network_loader_factory));
+ if (needs_loader_factory_interceptor && g_loader_factory_interceptor.Get()) {
+ mojo::PendingRemote<network::mojom::URLLoaderFactory> factory;
+ mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver =
+ factory.InitWithNewPipeAndPassReceiver();
+ g_loader_factory_interceptor.Get().Run(&receiver);
+ network_loader_factory_->Clone(std::move(receiver));
+ network_loader_factory_ =
+ base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
+ std::move(factory));
+ }
- // NetworkService cases only.
- // Requests to WebUI scheme won't get redirected to/from other schemes
- // or be intercepted, so we just let it go here.
- if (factory_for_webui.is_valid()) {
- url_loader_ = blink::ThrottlingURLLoader::CreateLoaderAndStart(
- base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
- std::move(factory_for_webui)),
- CreateURLLoaderThrottles(), 0 /* routing_id */,
- global_request_id_.request_id, network::mojom::kURLLoadOptionNone,
- resource_request_.get(), this, kNavigationUrlLoaderTrafficAnnotation,
- base::ThreadTaskRunnerHandle::Get());
- return;
- }
+ std::string accept_header_value = FrameAcceptHeaderValue();
+ if (signed_exchange_utils::IsSignedExchangeHandlingEnabled(
+ browser_context_)) {
+ accept_header_value.append(kAcceptHeaderSignedExchangeSuffix);
+ }
+ resource_request_->headers.SetHeader(net::HttpRequestHeaders::kAccept,
+ accept_header_value);
- // Requests to Blob scheme won't get redirected to/from other schemes
- // or be intercepted, so we just let it go here.
- if (request_info->common_params->url.SchemeIsBlob() &&
- request_info->blob_url_loader_factory) {
- url_loader_ = blink::ThrottlingURLLoader::CreateLoaderAndStart(
- network::SharedURLLoaderFactory::Create(
- std::move(request_info->blob_url_loader_factory)),
- CreateURLLoaderThrottles(), 0 /* routing_id */,
- global_request_id_.request_id, network::mojom::kURLLoadOptionNone,
- resource_request_.get(), this, kNavigationUrlLoaderTrafficAnnotation,
- base::ThreadTaskRunnerHandle::Get());
- return;
- }
+ // Requests to WebUI scheme won't get redirected to/from other schemes
+ // or be intercepted, so we just let it go here.
+ if (factory_for_webui.is_valid()) {
+ url_loader_ = blink::ThrottlingURLLoader::CreateLoaderAndStart(
+ base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
+ std::move(factory_for_webui)),
+ CreateURLLoaderThrottles(), 0 /* routing_id */,
+ global_request_id_.request_id, network::mojom::kURLLoadOptionNone,
+ resource_request_.get(), this, kNavigationUrlLoaderTrafficAnnotation,
+ base::ThreadTaskRunnerHandle::Get());
+ return;
+ }
- CreateInterceptors(request_info.get(), appcache_handle,
- prefetched_signed_exchange_cache,
- signed_exchange_prefetch_metric_recorder, accept_langs);
- Restart();
+ // Requests to Blob scheme won't get redirected to/from other schemes
+ // or be intercepted, so we just let it go here.
+ if (request_info_->common_params->url.SchemeIsBlob() &&
+ request_info_->blob_url_loader_factory) {
+ url_loader_ = blink::ThrottlingURLLoader::CreateLoaderAndStart(
+ network::SharedURLLoaderFactory::Create(
+ std::move(request_info_->blob_url_loader_factory)),
+ CreateURLLoaderThrottles(), 0 /* routing_id */,
+ global_request_id_.request_id, network::mojom::kURLLoadOptionNone,
+ resource_request_.get(), this, kNavigationUrlLoaderTrafficAnnotation,
+ base::ThreadTaskRunnerHandle::Get());
+ return;
}
- void CreateInterceptors(NavigationRequestInfo* request_info,
- AppCacheNavigationHandle* appcache_handle,
- scoped_refptr<PrefetchedSignedExchangeCache>
- prefetched_signed_exchange_cache,
- scoped_refptr<SignedExchangePrefetchMetricRecorder>
- signed_exchange_prefetch_metric_recorder,
- const std::string& accept_langs) {
- if (prefetched_signed_exchange_cache) {
- std::unique_ptr<NavigationLoaderInterceptor>
- prefetched_signed_exchange_interceptor =
- prefetched_signed_exchange_cache->MaybeCreateInterceptor(
- request_info->common_params->url);
- if (prefetched_signed_exchange_interceptor) {
- interceptors_.push_back(
- std::move(prefetched_signed_exchange_interceptor));
- }
- }
+ CreateInterceptors(appcache_handle, prefetched_signed_exchange_cache,
+ signed_exchange_prefetch_metric_recorder, accept_langs);
+ Restart();
+}
- // Set up an interceptor for service workers.
- if (service_worker_handle_) {
- auto service_worker_interceptor =
- ServiceWorkerNavigationLoaderInterceptor::CreateForNavigation(
- resource_request_->url, service_worker_handle_->AsWeakPtr(),
- *request_info);
- // The interceptor may not be created in certain cases (e.g., the origin
- // is not secure).
- if (service_worker_interceptor)
- interceptors_.push_back(std::move(service_worker_interceptor));
+void NavigationURLLoaderImpl::CreateInterceptors(
+ AppCacheNavigationHandle* appcache_handle,
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache,
+ scoped_refptr<SignedExchangePrefetchMetricRecorder>
+ signed_exchange_prefetch_metric_recorder,
+ const std::string& accept_langs) {
+ if (prefetched_signed_exchange_cache) {
+ std::unique_ptr<NavigationLoaderInterceptor>
+ prefetched_signed_exchange_interceptor =
+ prefetched_signed_exchange_cache->MaybeCreateInterceptor(url_);
+ if (prefetched_signed_exchange_interceptor) {
+ interceptors_.push_back(
+ std::move(prefetched_signed_exchange_interceptor));
}
+ }
- // Set-up an interceptor for AppCache if non-null |appcache_handle| is
- // given.
- if (appcache_handle) {
- CHECK(appcache_handle->host());
- std::unique_ptr<NavigationLoaderInterceptor> appcache_interceptor =
- AppCacheRequestHandler::InitializeForMainResourceNetworkService(
- *resource_request_, appcache_handle->host()->GetWeakPtr());
- if (appcache_interceptor)
- interceptors_.push_back(std::move(appcache_interceptor));
- }
+ // Set up an interceptor for service workers.
+ if (service_worker_handle_) {
+ auto service_worker_interceptor =
+ ServiceWorkerMainResourceLoaderInterceptor::CreateForNavigation(
+ resource_request_->url, service_worker_handle_->AsWeakPtr(),
+ *request_info_);
+ // The interceptor may not be created in certain cases (e.g., the origin
+ // is not secure).
+ if (service_worker_interceptor)
+ interceptors_.push_back(std::move(service_worker_interceptor));
+ }
- // Set-up an interceptor for SignedExchange handling if it is enabled.
- if (signed_exchange_utils::IsSignedExchangeHandlingEnabled(
- browser_context_)) {
- interceptors_.push_back(CreateSignedExchangeRequestHandler(
- *request_info, network_loader_factory_,
- std::move(signed_exchange_prefetch_metric_recorder),
- std::move(accept_langs)));
- }
+ // Set-up an interceptor for AppCache if non-null |appcache_handle| is
+ // given.
+ if (appcache_handle) {
+ CHECK(appcache_handle->host());
+ std::unique_ptr<NavigationLoaderInterceptor> appcache_interceptor =
+ AppCacheRequestHandler::InitializeForMainResourceNetworkService(
+ *resource_request_, appcache_handle->host()->GetWeakPtr());
+ if (appcache_interceptor)
+ interceptors_.push_back(std::move(appcache_interceptor));
+ }
- // See if embedders want to add interceptors.
- std::vector<std::unique_ptr<URLLoaderRequestInterceptor>>
- browser_interceptors =
- GetContentClient()
- ->browser()
- ->WillCreateURLLoaderRequestInterceptors(
- navigation_ui_data_.get(), request_info->frame_tree_node_id,
- network_loader_factory_);
- if (!browser_interceptors.empty()) {
- for (auto& browser_interceptor : browser_interceptors) {
- interceptors_.push_back(
- std::make_unique<NavigationLoaderInterceptorBrowserContainer>(
- std::move(browser_interceptor)));
- }
- }
+ // Set-up an interceptor for SignedExchange handling if it is enabled.
+ if (signed_exchange_utils::IsSignedExchangeHandlingEnabled(
+ browser_context_)) {
+ interceptors_.push_back(CreateSignedExchangeRequestHandler(
+ *request_info_, network_loader_factory_,
+ std::move(signed_exchange_prefetch_metric_recorder),
+ std::move(accept_langs)));
}
- // This could be called multiple times to follow a chain of redirects.
- void Restart() {
- // Clear |url_loader_| if it's not the default one (network). This allows
- // the restarted request to use a new loader, instead of, e.g., reusing the
- // AppCache or service worker loader. For an optimization, we keep and reuse
- // the default url loader if the all |interceptors_| doesn't handle the
- // redirected request. If the network service is enabled, reset the loader
- // if the redirected URL's scheme and the previous URL scheme don't match in
- // their use or disuse of the network service loader.
- if (!default_loader_used_ ||
- (url_chain_.size() > 1 &&
- IsURLHandledByNetworkService(url_chain_[url_chain_.size() - 1]) !=
- IsURLHandledByNetworkService(url_chain_[url_chain_.size() - 2]))) {
- if (url_loader_)
- url_loader_->ResetForFollowRedirect();
- url_loader_.reset();
+ // See if embedders want to add interceptors.
+ std::vector<std::unique_ptr<URLLoaderRequestInterceptor>>
+ browser_interceptors =
+ GetContentClient()->browser()->WillCreateURLLoaderRequestInterceptors(
+ navigation_ui_data_.get(), frame_tree_node_id_,
+ network_loader_factory_);
+ if (!browser_interceptors.empty()) {
+ for (auto& browser_interceptor : browser_interceptors) {
+ interceptors_.push_back(
+ std::make_unique<NavigationLoaderInterceptorBrowserContainer>(
+ std::move(browser_interceptor)));
}
- interceptor_index_ = 0;
- received_response_ = false;
- head_ = network::mojom::URLResponseHead::New();
- MaybeStartLoader(nullptr /* interceptor */,
- {} /* single_request_factory */);
}
+}
- // |interceptor| is non-null if this is called by one of the interceptors
- // (via a LoaderCallback).
- // |single_request_handler| is the RequestHandler given by the |interceptor|,
- // non-null if the interceptor wants to handle the request.
- void MaybeStartLoader(
- NavigationLoaderInterceptor* interceptor,
- scoped_refptr<network::SharedURLLoaderFactory> single_request_factory) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(started_);
-
- if (single_request_factory) {
- // |interceptor| wants to handle the request with
- // |single_request_handler|.
- DCHECK(interceptor);
-
- std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles =
- CreateURLLoaderThrottles();
- // Intercepted requests need MimeSniffingThrottle to do mime sniffing.
- // Non-intercepted requests usually go through the regular network
- // URLLoader, which does mime sniffing.
- throttles.push_back(std::make_unique<blink::MimeSniffingThrottle>(
- base::ThreadTaskRunnerHandle::Get()));
+void NavigationURLLoaderImpl::Restart() {
+ // Clear |url_loader_| if it's not the default one (network). This allows
+ // the restarted request to use a new loader, instead of, e.g., reusing the
+ // AppCache or service worker loader. For an optimization, we keep and reuse
+ // the default url loader if the all |interceptors_| doesn't handle the
+ // redirected request. If the network service is enabled, reset the loader
+ // if the redirected URL's scheme and the previous URL scheme don't match in
+ // their use or disuse of the network service loader.
+ if (!default_loader_used_ ||
+ (url_chain_.size() > 1 &&
+ IsURLHandledByNetworkService(url_chain_[url_chain_.size() - 1]) !=
+ IsURLHandledByNetworkService(url_chain_[url_chain_.size() - 2]))) {
+ if (url_loader_)
+ url_loader_->ResetForFollowRedirect();
+ url_loader_.reset();
+ }
+ interceptor_index_ = 0;
+ received_response_ = false;
+ head_ = network::mojom::URLResponseHead::New();
+ MaybeStartLoader(nullptr /* interceptor */, {} /* single_request_factory */);
+}
- default_loader_used_ = false;
- // If |url_loader_| already exists, this means we are following a redirect
- // using an interceptor. In this case we should make sure to reset the
- // loader, similar to what is done in Restart().
- if (url_loader_)
- url_loader_->ResetForFollowRedirect();
- url_loader_ = blink::ThrottlingURLLoader::CreateLoaderAndStart(
- std::move(single_request_factory), std::move(throttles),
- frame_tree_node_id_, global_request_id_.request_id,
- network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
- kNavigationUrlLoaderTrafficAnnotation,
- base::ThreadTaskRunnerHandle::Get());
-
- subresource_loader_params_ =
- interceptor->MaybeCreateSubresourceLoaderParams();
- if (interceptor->ShouldBypassRedirectChecks())
- bypass_redirect_checks_ = true;
- return;
- }
+void NavigationURLLoaderImpl::MaybeStartLoader(
+ NavigationLoaderInterceptor* interceptor,
+ scoped_refptr<network::SharedURLLoaderFactory> single_request_factory) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(started_);
+
+ if (single_request_factory) {
+ // |interceptor| wants to handle the request with
+ // |single_request_handler|.
+ DCHECK(interceptor);
+
+ std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles =
+ CreateURLLoaderThrottles();
+ // Intercepted requests need MimeSniffingThrottle to do mime sniffing.
+ // Non-intercepted requests usually go through the regular network
+ // URLLoader, which does mime sniffing.
+ throttles.push_back(std::make_unique<blink::MimeSniffingThrottle>(
+ base::ThreadTaskRunnerHandle::Get()));
+
+ default_loader_used_ = false;
+ // If |url_loader_| already exists, this means we are following a redirect
+ // using an interceptor. In this case we should make sure to reset the
+ // loader, similar to what is done in Restart().
+ if (url_loader_)
+ url_loader_->ResetForFollowRedirect();
+ url_loader_ = blink::ThrottlingURLLoader::CreateLoaderAndStart(
+ std::move(single_request_factory), std::move(throttles),
+ frame_tree_node_id_, global_request_id_.request_id,
+ network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
+ kNavigationUrlLoaderTrafficAnnotation,
+ base::ThreadTaskRunnerHandle::Get());
- // Before falling back to the next interceptor, see if |interceptor| still
- // wants to give additional info to the frame for subresource loading. In
- // that case we will just fall back to the default loader (i.e. won't go on
- // to the next interceptors) but send the subresource_loader_params to the
- // child process. This is necessary for correctness in the cases where, e.g.
- // there's a controlling service worker that doesn't have a fetch event
- // handler so it doesn't intercept requests. In that case we still want to
- // skip AppCache.
- if (interceptor) {
- subresource_loader_params_ =
- interceptor->MaybeCreateSubresourceLoaderParams();
-
- // If non-null |subresource_loader_params_| is returned, make sure
- // we skip the next interceptors.
- if (subresource_loader_params_)
- interceptor_index_ = interceptors_.size();
- }
+ subresource_loader_params_ =
+ interceptor->MaybeCreateSubresourceLoaderParams();
+ if (interceptor->ShouldBypassRedirectChecks())
+ bypass_redirect_checks_ = true;
+ return;
+ }
- // See if the next interceptor wants to handle the request.
- if (interceptor_index_ < interceptors_.size()) {
- auto* next_interceptor = interceptors_[interceptor_index_++].get();
- next_interceptor->MaybeCreateLoader(
- *resource_request_, browser_context_,
- base::BindOnce(&URLLoaderRequestController::MaybeStartLoader,
- base::Unretained(this), next_interceptor),
- base::BindOnce(
- &URLLoaderRequestController::FallbackToNonInterceptedRequest,
- base::Unretained(this)));
- return;
- }
+ // Before falling back to the next interceptor, see if |interceptor| still
+ // wants to give additional info to the frame for subresource loading. In
+ // that case we will just fall back to the default loader (i.e. won't go on
+ // to the next interceptors) but send the subresource_loader_params to the
+ // child process. This is necessary for correctness in the cases where, e.g.
+ // there's a controlling service worker that doesn't have a fetch event
+ // handler so it doesn't intercept requests. In that case we still want to
+ // skip AppCache.
+ if (interceptor) {
+ subresource_loader_params_ =
+ interceptor->MaybeCreateSubresourceLoaderParams();
+
+ // If non-null |subresource_loader_params_| is returned, make sure
+ // we skip the next interceptors.
+ if (subresource_loader_params_)
+ interceptor_index_ = interceptors_.size();
+ }
- // If we already have the default |url_loader_| we must come here after a
- // redirect. No interceptors wanted to intercept the redirected request, so
- // let the loader just follow the redirect.
- if (url_loader_) {
- DCHECK(!redirect_info_.new_url.is_empty());
- url_loader_->FollowRedirect(
- std::move(url_loader_removed_headers_),
- std::move(url_loader_modified_headers_),
- std::move(url_loader_modified_cors_exempt_headers_));
- return;
- }
+ // See if the next interceptor wants to handle the request.
+ if (interceptor_index_ < interceptors_.size()) {
+ auto* next_interceptor = interceptors_[interceptor_index_++].get();
+ next_interceptor->MaybeCreateLoader(
+ *resource_request_, browser_context_,
+ base::BindOnce(&NavigationURLLoaderImpl::MaybeStartLoader,
+ base::Unretained(this), next_interceptor),
+ base::BindOnce(
+ &NavigationURLLoaderImpl::FallbackToNonInterceptedRequest,
+ base::Unretained(this)));
+ return;
+ }
+
+ // If we already have the default |url_loader_| we must come here after a
+ // redirect. No interceptors wanted to intercept the redirected request, so
+ // let the loader just follow the redirect.
+ if (url_loader_) {
+ DCHECK(!redirect_info_.new_url.is_empty());
+ url_loader_->FollowRedirect(
+ std::move(url_loader_removed_headers_),
+ std::move(url_loader_modified_headers_),
+ std::move(url_loader_modified_cors_exempt_headers_));
+ return;
+ }
+
+ // No interceptors wanted to handle this request.
+ uint32_t options = network::mojom::kURLLoadOptionNone;
+ scoped_refptr<network::SharedURLLoaderFactory> factory =
+ PrepareForNonInterceptedRequest(&options);
+ url_loader_ = blink::ThrottlingURLLoader::CreateLoaderAndStart(
+ std::move(factory), CreateURLLoaderThrottles(), frame_tree_node_id_,
+ global_request_id_.request_id, options, resource_request_.get(),
+ this /* client */, kNavigationUrlLoaderTrafficAnnotation,
+ base::ThreadTaskRunnerHandle::Get());
+}
- // No interceptors wanted to handle this request.
- uint32_t options = network::mojom::kURLLoadOptionNone;
- scoped_refptr<network::SharedURLLoaderFactory> factory =
- PrepareForNonInterceptedRequest(&options);
+void NavigationURLLoaderImpl::FallbackToNonInterceptedRequest(
+ bool reset_subresource_loader_params) {
+ if (reset_subresource_loader_params)
+ subresource_loader_params_.reset();
+
+ uint32_t options = network::mojom::kURLLoadOptionNone;
+ scoped_refptr<network::SharedURLLoaderFactory> factory =
+ PrepareForNonInterceptedRequest(&options);
+ if (url_loader_) {
+ // |url_loader_| is using the factory for the interceptor that decided to
+ // fallback, so restart it with the non-interceptor factory.
+ url_loader_->RestartWithFactory(std::move(factory), options);
+ } else {
+ // In SXG cases we don't have |url_loader_| because it was reset when the
+ // SXG interceptor intercepted the response in
+ // MaybeCreateLoaderForResponse.
+ DCHECK(response_loader_receiver_.is_bound());
+ response_loader_receiver_.reset();
url_loader_ = blink::ThrottlingURLLoader::CreateLoaderAndStart(
std::move(factory), CreateURLLoaderThrottles(), frame_tree_node_id_,
global_request_id_.request_id, options, resource_request_.get(),
this /* client */, kNavigationUrlLoaderTrafficAnnotation,
base::ThreadTaskRunnerHandle::Get());
}
+}
- // This is the |fallback_callback| passed to
- // NavigationLoaderInterceptor::MaybeCreateLoader. It allows an interceptor
- // to initially elect to handle a request, and later decide to fallback to
- // the default behavior. This is needed for service worker network fallback
- // and signed exchange (SXG) fallback redirect.
- void FallbackToNonInterceptedRequest(bool reset_subresource_loader_params) {
- if (reset_subresource_loader_params)
- subresource_loader_params_.reset();
-
- uint32_t options = network::mojom::kURLLoadOptionNone;
- scoped_refptr<network::SharedURLLoaderFactory> factory =
- PrepareForNonInterceptedRequest(&options);
- if (url_loader_) {
- // |url_loader_| is using the factory for the interceptor that decided to
- // fallback, so restart it with the non-interceptor factory.
- url_loader_->RestartWithFactory(std::move(factory), options);
- } else {
- // In SXG cases we don't have |url_loader_| because it was reset when the
- // SXG interceptor intercepted the response in
- // MaybeCreateLoaderForResponse.
- DCHECK(response_loader_receiver_.is_bound());
- response_loader_receiver_.reset();
- url_loader_ = blink::ThrottlingURLLoader::CreateLoaderAndStart(
- std::move(factory), CreateURLLoaderThrottles(), frame_tree_node_id_,
- global_request_id_.request_id, options, resource_request_.get(),
- this /* client */, kNavigationUrlLoaderTrafficAnnotation,
- base::ThreadTaskRunnerHandle::Get());
- }
- }
-
- scoped_refptr<network::SharedURLLoaderFactory>
- PrepareForNonInterceptedRequest(uint32_t* out_options) {
- // TODO(https://crbug.com/796425): We temporarily wrap raw
- // mojom::URLLoaderFactory pointers into SharedURLLoaderFactory. Need to
- // further refactor the factory getters to avoid this.
- scoped_refptr<network::SharedURLLoaderFactory> factory;
-
- if (!IsURLHandledByNetworkService(resource_request_->url)) {
- if (known_schemes_.find(resource_request_->url.scheme()) ==
- known_schemes_.end()) {
- mojo::PendingRemote<network::mojom::URLLoaderFactory> loader_factory;
- bool handled = GetContentClient()->browser()->HandleExternalProtocol(
- resource_request_->url, web_contents_getter_,
- ChildProcessHost::kInvalidUniqueID, navigation_ui_data_.get(),
- resource_request_->resource_type ==
- static_cast<int>(blink::mojom::ResourceType::kMainFrame),
- static_cast<ui::PageTransition>(resource_request_->transition_type),
- resource_request_->has_user_gesture,
- resource_request_->request_initiator, &loader_factory);
-
- if (loader_factory) {
- factory =
- base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
- std::move(loader_factory));
- } else {
- factory = base::MakeRefCounted<SingleRequestURLLoaderFactory>(
- base::BindOnce(UnknownSchemeCallback, handled));
- }
- } else {
- mojo::Remote<network::mojom::URLLoaderFactory>& non_network_factory =
- non_network_url_loader_factories_[resource_request_->url.scheme()];
- if (!non_network_factory.is_bound()) {
- owner_->BindNonNetworkURLLoaderFactoryReceiver(
- frame_tree_node_id_, resource_request_->url,
- non_network_factory.BindNewPipeAndPassReceiver());
- }
- factory =
- base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
- non_network_factory.get());
- }
-
- if (g_loader_factory_interceptor.Get()) {
- mojo::PendingRemote<network::mojom::URLLoaderFactory> factory_remote;
- mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver =
- factory_remote.InitWithNewPipeAndPassReceiver();
- g_loader_factory_interceptor.Get().Run(&receiver);
- factory->Clone(std::move(receiver));
+scoped_refptr<network::SharedURLLoaderFactory>
+NavigationURLLoaderImpl::PrepareForNonInterceptedRequest(
+ uint32_t* out_options) {
+ // TODO(https://crbug.com/796425): We temporarily wrap raw
+ // mojom::URLLoaderFactory pointers into SharedURLLoaderFactory. Need to
+ // further refactor the factory getters to avoid this.
+ scoped_refptr<network::SharedURLLoaderFactory> factory;
+
+ if (!IsURLHandledByNetworkService(resource_request_->url)) {
+ if (known_schemes_.find(resource_request_->url.scheme()) ==
+ known_schemes_.end()) {
+ mojo::PendingRemote<network::mojom::URLLoaderFactory> loader_factory;
+ bool handled = GetContentClient()->browser()->HandleExternalProtocol(
+ resource_request_->url, web_contents_getter_,
+ ChildProcessHost::kInvalidUniqueID, navigation_ui_data_.get(),
+ resource_request_->resource_type ==
+ static_cast<int>(blink::mojom::ResourceType::kMainFrame),
+ static_cast<ui::PageTransition>(resource_request_->transition_type),
+ resource_request_->has_user_gesture,
+ resource_request_->request_initiator, &loader_factory);
+
+ if (loader_factory) {
factory = base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
- std::move(factory_remote));
+ std::move(loader_factory));
+ } else {
+ factory = base::MakeRefCounted<SingleRequestURLLoaderFactory>(
+ base::BindOnce(UnknownSchemeCallback, handled));
}
} else {
- default_loader_used_ = true;
-
- // NOTE: We only support embedders proxying network-service-bound requests
- // not handled by NavigationLoaderInterceptors above (e.g. Service Worker
- // or AppCache). Hence this code is only reachable when one of the above
- // interceptors isn't used and the URL is either a data URL or has a
- // scheme which is handled by the network service.
- if (proxied_factory_receiver_.is_valid()) {
- DCHECK(proxied_factory_remote_.is_valid());
- // We don't worry about reconnection since it's a single navigation.
- network_loader_factory_->Clone(std::move(proxied_factory_receiver_));
- // Replace the network factory with the proxied version since this may
- // need to be used in redirects, and we've already consumed
- // |proxied_factory_receiver_|.
- network_loader_factory_ =
- base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
- std::move(proxied_factory_remote_));
+ mojo::Remote<network::mojom::URLLoaderFactory>& non_network_factory =
+ non_network_url_loader_factory_remotes_[resource_request_->url
+ .scheme()];
+ if (!non_network_factory.is_bound()) {
+ BindNonNetworkURLLoaderFactoryReceiver(
+ resource_request_->url,
+ non_network_factory.BindNewPipeAndPassReceiver());
}
- factory = network_loader_factory_;
+ factory =
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+ non_network_factory.get());
}
- url_chain_.push_back(resource_request_->url);
- *out_options = GetURLLoaderOptions(
- resource_request_->resource_type ==
- static_cast<int>(blink::mojom::ResourceType::kMainFrame));
- return factory;
- }
- void FollowRedirect(
- const std::vector<std::string>& removed_headers,
- const net::HttpRequestHeaders& modified_headers,
- const net::HttpRequestHeaders& modified_cors_exempt_headers,
- PreviewsState new_previews_state,
- base::Time ui_post_time) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(!redirect_info_.new_url.is_empty());
- ui_to_io_time_ += (base::Time::Now() - ui_post_time);
-
- // Update |resource_request_| and call Restart to give our |interceptors_| a
- // chance at handling the new location. If no interceptor wants to take
- // over, we'll use the existing url_loader to follow the redirect, see
- // MaybeStartLoader.
- // TODO(michaeln): This is still WIP and is based on URLRequest::Redirect,
- // there likely remains more to be done.
- // a. For subframe navigations, the Origin header may need to be modified
- // differently?
-
- bool should_clear_upload = false;
- net::RedirectUtil::UpdateHttpRequest(
- resource_request_->url, resource_request_->method, redirect_info_,
- removed_headers, modified_headers, &resource_request_->headers,
- &should_clear_upload);
- if (should_clear_upload) {
- // The request body is no longer applicable.
- resource_request_->request_body.reset();
+ if (g_loader_factory_interceptor.Get()) {
+ mojo::PendingRemote<network::mojom::URLLoaderFactory> factory_remote;
+ mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver =
+ factory_remote.InitWithNewPipeAndPassReceiver();
+ g_loader_factory_interceptor.Get().Run(&receiver);
+ factory->Clone(std::move(receiver));
+ factory = base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
+ std::move(factory_remote));
}
-
- resource_request_->url = redirect_info_.new_url;
- resource_request_->method = redirect_info_.new_method;
- resource_request_->site_for_cookies = redirect_info_.new_site_for_cookies;
-
- // See if navigation network isolation key needs to be updated.
- resource_request_->trusted_params->isolation_info =
- resource_request_->trusted_params->isolation_info.CreateForRedirect(
- url::Origin::Create(resource_request_->url));
-
- resource_request_->referrer = GURL(redirect_info_.new_referrer);
- resource_request_->referrer_policy = redirect_info_.new_referrer_policy;
- resource_request_->previews_state = new_previews_state;
- url_chain_.push_back(redirect_info_.new_url);
-
- // Need to cache modified headers for |url_loader_| since it doesn't use
- // |resource_request_| during redirect.
- url_loader_removed_headers_ = removed_headers;
- url_loader_modified_headers_ = modified_headers;
- url_loader_modified_cors_exempt_headers_ = modified_cors_exempt_headers;
-
- // Don't send Accept: application/signed-exchange for fallback redirects.
- if (redirect_info_.is_signed_exchange_fallback_redirect) {
- url_loader_modified_headers_.SetHeader(net::HttpRequestHeaders::kAccept,
- FrameAcceptHeaderValue());
- resource_request_->headers.SetHeader(net::HttpRequestHeaders::kAccept,
- FrameAcceptHeaderValue());
+ } else {
+ default_loader_used_ = true;
+
+ // NOTE: We only support embedders proxying network-service-bound requests
+ // not handled by NavigationLoaderInterceptors above (e.g. Service Worker
+ // or AppCache). Hence this code is only reachable when one of the above
+ // interceptors isn't used and the URL is either a data URL or has a
+ // scheme which is handled by the network service.
+ if (proxied_factory_receiver_.is_valid()) {
+ DCHECK(proxied_factory_remote_.is_valid());
+ // We don't worry about reconnection since it's a single navigation.
+ network_loader_factory_->Clone(std::move(proxied_factory_receiver_));
+ // Replace the network factory with the proxied version since this may
+ // need to be used in redirects, and we've already consumed
+ // |proxied_factory_receiver_|.
+ network_loader_factory_ =
+ base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
+ std::move(proxied_factory_remote_));
}
-
- Restart();
+ factory = network_loader_factory_;
}
+ url_chain_.push_back(resource_request_->url);
+ *out_options = GetURLLoaderOptions(
+ resource_request_->resource_type ==
+ static_cast<int>(blink::mojom::ResourceType::kMainFrame));
+ return factory;
+}
- base::Optional<SubresourceLoaderParams> TakeSubresourceLoaderParams() {
- return std::move(subresource_loader_params_);
+void NavigationURLLoaderImpl::FollowRedirectInternal(
+ const std::vector<std::string>& removed_headers,
+ const net::HttpRequestHeaders& modified_headers,
+ const net::HttpRequestHeaders& modified_cors_exempt_headers,
+ PreviewsState new_previews_state,
+ base::Time ui_post_time) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(!redirect_info_.new_url.is_empty());
+
+ // Update |resource_request_| and call Restart to give our |interceptors_| a
+ // chance at handling the new location. If no interceptor wants to take
+ // over, we'll use the existing url_loader to follow the redirect, see
+ // MaybeStartLoader.
+ // TODO(michaeln): This is still WIP and is based on URLRequest::Redirect,
+ // there likely remains more to be done.
+ // a. For subframe navigations, the Origin header may need to be modified
+ // differently?
+
+ bool should_clear_upload = false;
+ net::RedirectUtil::UpdateHttpRequest(
+ resource_request_->url, resource_request_->method, redirect_info_,
+ removed_headers, modified_headers, &resource_request_->headers,
+ &should_clear_upload);
+ if (should_clear_upload) {
+ // The request body is no longer applicable.
+ resource_request_->request_body.reset();
}
- private:
- // network::mojom::URLLoaderClient implementation:
- void OnReceiveResponse(network::mojom::URLResponseHeadPtr head) override {
- head_ = std::move(head);
- on_receive_response_time_ = base::TimeTicks::Now();
+ resource_request_->url = redirect_info_.new_url;
+ resource_request_->method = redirect_info_.new_method;
+ resource_request_->site_for_cookies = redirect_info_.new_site_for_cookies;
+
+ // See if navigation network isolation key needs to be updated.
+ resource_request_->trusted_params->isolation_info =
+ resource_request_->trusted_params->isolation_info.CreateForRedirect(
+ url::Origin::Create(resource_request_->url));
+
+ resource_request_->referrer = GURL(redirect_info_.new_referrer);
+ resource_request_->referrer_policy = redirect_info_.new_referrer_policy;
+ resource_request_->previews_state = new_previews_state;
+ url_chain_.push_back(redirect_info_.new_url);
+
+ // Need to cache modified headers for |url_loader_| since it doesn't use
+ // |resource_request_| during redirect.
+ url_loader_removed_headers_ = removed_headers;
+ url_loader_modified_headers_ = modified_headers;
+ url_loader_modified_cors_exempt_headers_ = modified_cors_exempt_headers;
+
+ // Don't send Accept: application/signed-exchange for fallback redirects.
+ if (redirect_info_.is_signed_exchange_fallback_redirect) {
+ url_loader_modified_headers_.SetHeader(net::HttpRequestHeaders::kAccept,
+ FrameAcceptHeaderValue());
+ resource_request_->headers.SetHeader(net::HttpRequestHeaders::kAccept,
+ FrameAcceptHeaderValue());
}
- // network::mojom::URLLoaderClient implementation:
- void OnStartLoadingResponseBody(
- mojo::ScopedDataPipeConsumerHandle response_body) override {
- if (!on_receive_response_time_.is_null()) {
- UMA_HISTOGRAM_TIMES(
- "Navigation.OnReceiveResponseToOnStartLoadingResponseBody",
- base::TimeTicks::Now() - on_receive_response_time_);
- }
+ Restart();
+}
+
+void NavigationURLLoaderImpl::OnReceiveResponse(
+ network::mojom::URLResponseHeadPtr head) {
+ head_ = std::move(head);
+ on_receive_response_time_ = base::TimeTicks::Now();
+}
- response_body_ = std::move(response_body);
- received_response_ = true;
+void NavigationURLLoaderImpl::OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle response_body) {
+ if (!on_receive_response_time_.is_null()) {
+ UMA_HISTOGRAM_TIMES(
+ "Navigation.OnReceiveResponseToOnStartLoadingResponseBody",
+ base::TimeTicks::Now() - on_receive_response_time_);
+ }
- // If the default loader (network) was used to handle the URL load request
- // we need to see if the interceptors want to potentially create a new
- // loader for the response. e.g. AppCache.
- if (MaybeCreateLoaderForResponse(&head_))
- return;
+ response_body_ = std::move(response_body);
+ received_response_ = true;
- network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints;
+ // If the default loader (network) was used to handle the URL load request
+ // we need to see if the interceptors want to potentially create a new
+ // loader for the response. e.g. AppCache.
+ if (MaybeCreateLoaderForResponse(&head_))
+ return;
- if (url_loader_) {
- url_loader_client_endpoints = url_loader_->Unbind();
- } else {
- url_loader_client_endpoints =
- network::mojom::URLLoaderClientEndpoints::New(
- std::move(response_url_loader_),
- response_loader_receiver_.Unbind());
- }
+ network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints;
- // 304 responses should abort the navigation, rather than display the page.
- // This needs to be after the URLLoader has been moved to
- // |url_loader_client_endpoints| in order to abort the request, to avoid
- // receiving unexpected call.
- if (head_->headers &&
- head_->headers->response_code() == net::HTTP_NOT_MODIFIED) {
- // Call CancelWithError instead of OnComplete so that if there is an
- // intercepting URLLoaderFactory it gets notified.
- url_loader_->CancelWithError(
- net::ERR_ABORTED,
- base::StringPiece(base::NumberToString(net::ERR_ABORTED)));
- return;
- }
+ if (url_loader_) {
+ url_loader_client_endpoints = url_loader_->Unbind();
+ } else {
+ url_loader_client_endpoints = network::mojom::URLLoaderClientEndpoints::New(
+ std::move(response_url_loader_), response_loader_receiver_.Unbind());
+ }
+
+ // 304 responses should abort the navigation, rather than display the page.
+ // This needs to be after the URLLoader has been moved to
+ // |url_loader_client_endpoints| in order to abort the request, to avoid
+ // receiving unexpected call.
+ if (head_->headers &&
+ head_->headers->response_code() == net::HTTP_NOT_MODIFIED) {
+ // Call CancelWithError instead of OnComplete so that if there is an
+ // intercepting URLLoaderFactory it gets notified.
+ url_loader_->CancelWithError(
+ net::ERR_ABORTED,
+ base::StringPiece(base::NumberToString(net::ERR_ABORTED)));
+ return;
+ }
- bool must_download = download_utils::MustDownload(
- url_, head_->headers.get(), head_->mime_type);
- bool known_mime_type = blink::IsSupportedMimeType(head_->mime_type);
+ bool must_download = download_utils::MustDownload(url_, head_->headers.get(),
+ head_->mime_type);
+ bool known_mime_type = blink::IsSupportedMimeType(head_->mime_type);
#if BUILDFLAG(ENABLE_PLUGINS)
if (!head_->intercepted_by_plugin && !must_download && !known_mime_type) {
@@ -929,389 +820,273 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
CallOnReceivedResponse(std::move(head_),
std::move(url_loader_client_endpoints), is_download);
- }
+}
#if BUILDFLAG(ENABLE_PLUGINS)
- void CheckPluginAndContinueOnReceiveResponse(
- network::mojom::URLResponseHeadPtr head,
- network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
- bool is_download_if_not_handled_by_plugin,
- const std::vector<WebPluginInfo>& plugins) {
- bool stale;
- WebPluginInfo plugin;
- FrameTreeNode* frame_tree_node =
- FrameTreeNode::GloballyFindByID(frame_tree_node_id_);
- int render_process_id =
- frame_tree_node->current_frame_host()->GetProcess()->GetID();
- int routing_id = frame_tree_node->current_frame_host()->GetRoutingID();
- bool has_plugin = PluginService::GetInstance()->GetPluginInfo(
- render_process_id, routing_id, resource_request_->url, url::Origin(),
- head->mime_type, false /* allow_wildcard */, &stale, &plugin, nullptr);
-
- if (stale) {
- // Refresh the plugins asynchronously.
- PluginService::GetInstance()->GetPlugins(base::BindOnce(
- &URLLoaderRequestController::CheckPluginAndContinueOnReceiveResponse,
- weak_factory_.GetWeakPtr(), std::move(head),
- std::move(url_loader_client_endpoints),
- is_download_if_not_handled_by_plugin));
- return;
- }
-
- bool is_download = !has_plugin && is_download_if_not_handled_by_plugin;
-
- CallOnReceivedResponse(std::move(head),
- std::move(url_loader_client_endpoints), is_download);
+void NavigationURLLoaderImpl::CheckPluginAndContinueOnReceiveResponse(
+ network::mojom::URLResponseHeadPtr head,
+ network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
+ bool is_download_if_not_handled_by_plugin,
+ const std::vector<WebPluginInfo>& plugins) {
+ bool stale;
+ WebPluginInfo plugin;
+ FrameTreeNode* frame_tree_node =
+ FrameTreeNode::GloballyFindByID(frame_tree_node_id_);
+ int render_process_id =
+ frame_tree_node->current_frame_host()->GetProcess()->GetID();
+ int routing_id = frame_tree_node->current_frame_host()->GetRoutingID();
+ bool has_plugin = PluginService::GetInstance()->GetPluginInfo(
+ render_process_id, routing_id, resource_request_->url, url::Origin(),
+ head->mime_type, false /* allow_wildcard */, &stale, &plugin, nullptr);
+
+ if (stale) {
+ // Refresh the plugins asynchronously.
+ PluginService::GetInstance()->GetPlugins(base::BindOnce(
+ &NavigationURLLoaderImpl::CheckPluginAndContinueOnReceiveResponse,
+ weak_factory_.GetWeakPtr(), std::move(head),
+ std::move(url_loader_client_endpoints),
+ is_download_if_not_handled_by_plugin));
+ return;
}
+
+ bool is_download = !has_plugin && is_download_if_not_handled_by_plugin;
+ CallOnReceivedResponse(std::move(head),
+ std::move(url_loader_client_endpoints), is_download);
+}
#endif
- void CallOnReceivedResponse(
- network::mojom::URLResponseHeadPtr head,
- network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
- bool is_download) {
- network::mojom::URLResponseHead* head_ptr = head.get();
- auto on_receive_response = base::BindOnce(
- &NavigationURLLoaderImpl::OnReceiveResponse, owner_, std::move(head),
- std::move(url_loader_client_endpoints), std::move(response_body_),
- global_request_id_, is_download, ui_to_io_time_, base::Time::Now());
-
- ParseHeaders(url_, head_ptr, std::move(on_receive_response));
- }
+void NavigationURLLoaderImpl::CallOnReceivedResponse(
+ network::mojom::URLResponseHeadPtr head,
+ network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
+ bool is_download) {
+ network::mojom::URLResponseHead* head_ptr = head.get();
+ auto on_receive_response = base::BindOnce(
+ &NavigationURLLoaderImpl::NotifyResponseStarted,
+ weak_factory_.GetWeakPtr(), std::move(head),
+ std::move(url_loader_client_endpoints), std::move(response_body_),
+ global_request_id_, is_download);
+
+ ParseHeaders(url_, head_ptr, std::move(on_receive_response));
+}
- void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
- network::mojom::URLResponseHeadPtr head) override {
- net::Error error = net::OK;
- if (!bypass_redirect_checks_ &&
- !IsSafeRedirectTarget(url_, redirect_info.new_url)) {
- error = net::ERR_UNSAFE_REDIRECT;
- } else if (--redirect_limit_ == 0) {
- error = net::ERR_TOO_MANY_REDIRECTS;
- if (redirect_info.is_signed_exchange_fallback_redirect)
- UMA_HISTOGRAM_BOOLEAN("SignedExchange.FallbackRedirectLoop", true);
- }
- if (error != net::OK) {
- if (url_loader_) {
- // Call CancelWithError instead of OnComplete so that if there is an
- // intercepting URLLoaderFactory (created through the embedder's
- // ContentBrowserClient::WillCreateURLLoaderFactory) it gets notified.
- url_loader_->CancelWithError(
- error, base::StringPiece(base::NumberToString(error)));
- } else {
- // TODO(crbug.com/1052242): Make sure ResetWithReason() is called on the
- // original url_loader_.
- OnComplete(network::URLLoaderCompletionStatus(error));
- }
- return;
+void NavigationURLLoaderImpl::OnReceiveRedirect(
+ const net::RedirectInfo& redirect_info,
+ network::mojom::URLResponseHeadPtr head) {
+ net::Error error = net::OK;
+ if (!bypass_redirect_checks_ &&
+ !IsSafeRedirectTarget(url_, redirect_info.new_url)) {
+ error = net::ERR_UNSAFE_REDIRECT;
+ } else if (--redirect_limit_ == 0) {
+ error = net::ERR_TOO_MANY_REDIRECTS;
+ if (redirect_info.is_signed_exchange_fallback_redirect)
+ UMA_HISTOGRAM_BOOLEAN("SignedExchange.FallbackRedirectLoop", true);
+ }
+ if (error != net::OK) {
+ if (url_loader_) {
+ // Call CancelWithError instead of OnComplete so that if there is an
+ // intercepting URLLoaderFactory (created through the embedder's
+ // ContentBrowserClient::WillCreateURLLoaderFactory) it gets notified.
+ url_loader_->CancelWithError(
+ error, base::StringPiece(base::NumberToString(error)));
+ } else {
+ // TODO(crbug.com/1052242): Make sure ResetWithReason() is called on the
+ // original url_loader_.
+ OnComplete(network::URLLoaderCompletionStatus(error));
}
-
- // Store the redirect_info for later use in FollowRedirect where we give
- // our interceptors_ a chance to intercept the request for the new location.
- redirect_info_ = redirect_info;
-
- url_ = redirect_info.new_url;
-
- network::mojom::URLResponseHead* head_ptr = head.get();
- auto on_receive_redirect =
- base::BindOnce(&NavigationURLLoaderImpl::OnReceiveRedirect, owner_,
- redirect_info, std::move(head), base::Time::Now());
- ParseHeaders(url_, head_ptr, std::move(on_receive_redirect));
+ return;
}
- void OnUploadProgress(int64_t current_position,
- int64_t total_size,
- OnUploadProgressCallback callback) override {
- NOTREACHED();
- }
+ // Store the redirect_info for later use in FollowRedirect where we give
+ // our interceptors_ a chance to intercept the request for the new location.
+ redirect_info_ = redirect_info;
- void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override {
- NOTREACHED();
- }
+ url_ = redirect_info.new_url;
- void OnTransferSizeUpdated(int32_t transfer_size_diff) override {}
+ network::mojom::URLResponseHead* head_ptr = head.get();
+ auto on_receive_redirect = base::BindOnce(
+ &NavigationURLLoaderImpl::NotifyRequestRedirected,
+ weak_factory_.GetWeakPtr(), redirect_info, std::move(head));
+ ParseHeaders(url_, head_ptr, std::move(on_receive_redirect));
+}
- void OnComplete(const network::URLLoaderCompletionStatus& status) override {
- UMA_HISTOGRAM_BOOLEAN(
- "Navigation.URLLoaderNetworkService.OnCompleteHasSSLInfo",
- status.ssl_info.has_value());
+void NavigationURLLoaderImpl::OnUploadProgress(
+ int64_t current_position,
+ int64_t total_size,
+ OnUploadProgressCallback callback) {
+ NOTREACHED();
+}
- // Successful load must have used OnResponseStarted first. In this case, the
- // URLLoaderClient has already been transferred to the renderer process and
- // OnComplete is not expected to be called here.
- if (status.error_code == net::OK) {
- base::debug::DumpWithoutCrashing();
- return;
- }
+void NavigationURLLoaderImpl::OnReceiveCachedMetadata(
+ mojo_base::BigBuffer data) {
+ NOTREACHED();
+}
- if (status.ssl_info.has_value()) {
- UMA_HISTOGRAM_MEMORY_KB(
- "Navigation.URLLoaderNetworkService.OnCompleteCertificateChainsSize",
- GetCertificateChainsSizeInKB(status.ssl_info.value()));
- }
+void NavigationURLLoaderImpl::OnComplete(
+ const network::URLLoaderCompletionStatus& status) {
+ UMA_HISTOGRAM_BOOLEAN(
+ "Navigation.URLLoaderNetworkService.OnCompleteHasSSLInfo",
+ status.ssl_info.has_value());
+
+ // Successful load must have used OnResponseStarted first. In this case, the
+ // URLLoaderClient has already been transferred to the renderer process and
+ // OnComplete is not expected to be called here.
+ if (status.error_code == net::OK) {
+ base::debug::DumpWithoutCrashing();
+ return;
+ }
- // If the default loader (network) was used to handle the URL load request
- // we need to see if the interceptors want to potentially create a new
- // loader for the response. e.g. AppCache.
- //
- // Note: Despite having received a response, the HTTP_NOT_MODIFIED(304) ones
- // are ignored using OnComplete(net::ERR_ABORTED). No interceptor must
- // be used in this case.
- if (!received_response_) {
- auto response = network::mojom::URLResponseHead::New();
- if (MaybeCreateLoaderForResponse(&response))
- return;
- }
+ if (status.ssl_info.has_value()) {
+ UMA_HISTOGRAM_MEMORY_KB(
+ "Navigation.URLLoaderNetworkService.OnCompleteCertificateChainsSize",
+ GetCertificateChainsSizeInKB(status.ssl_info.value()));
+ }
- status_ = status;
- base::PostTask(
- FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&NavigationURLLoaderImpl::OnComplete, owner_, status));
+ // If the default loader (network) was used to handle the URL load request
+ // we need to see if the interceptors want to potentially create a new
+ // loader for the response. e.g. AppCache.
+ //
+ // Note: Despite having received a response, the HTTP_NOT_MODIFIED(304) ones
+ // are ignored using OnComplete(net::ERR_ABORTED). No interceptor must
+ // be used in this case.
+ if (!received_response_) {
+ auto response = network::mojom::URLResponseHead::New();
+ if (MaybeCreateLoaderForResponse(&response))
+ return;
}
+ status_ = status;
+ GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&NavigationURLLoaderImpl::NotifyRequestFailed,
+ weak_factory_.GetWeakPtr(), status));
+}
+
// Returns true if an interceptor wants to handle the response, i.e. return a
// different response. For e.g. AppCache may have fallback content.
- bool MaybeCreateLoaderForResponse(
- network::mojom::URLResponseHeadPtr* response) {
- if (!default_loader_used_ &&
- !web_bundle_utils::CanLoadAsWebBundle(url_, (*response)->mime_type)) {
- return false;
- }
- for (size_t i = 0u; i < interceptors_.size(); ++i) {
- NavigationLoaderInterceptor* interceptor = interceptors_[i].get();
- mojo::PendingReceiver<network::mojom::URLLoaderClient>
- response_client_receiver;
- bool skip_other_interceptors = false;
- bool will_return_unsafe_redirect = false;
- if (interceptor->MaybeCreateLoaderForResponse(
- *resource_request_, response, &response_body_,
- &response_url_loader_, &response_client_receiver,
- url_loader_.get(), &skip_other_interceptors,
- &will_return_unsafe_redirect)) {
- if (will_return_unsafe_redirect)
- bypass_redirect_checks_ = true;
- response_loader_receiver_.reset();
- response_loader_receiver_.Bind(std::move(response_client_receiver));
- default_loader_used_ = false;
- url_loader_.reset(); // Consumed above.
- response_body_.reset(); // Consumed above.
- if (skip_other_interceptors) {
- std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
- new_interceptors;
- new_interceptors.push_back(std::move(interceptors_[i]));
- new_interceptors.swap(interceptors_);
- // Reset the state of ServiceWorkerContainerHost.
- // Currently we don't support Service Worker in Signed Exchange
- // pages. The page will not be controlled by service workers. And
- // Service Worker related APIs will fail with NoDocumentURL error.
- // TODO(crbug/898733): Support SignedExchange loading and Service
- // Worker integration.
- if (service_worker_handle_) {
- RunOrPostTaskOnThread(
- FROM_HERE, ServiceWorkerContext::GetCoreThreadId(),
- base::BindOnce(
- [](ServiceWorkerMainResourceHandleCore* core) {
- base::WeakPtr<ServiceWorkerContainerHost> container_host =
- core->container_host();
- if (container_host) {
- container_host->SetControllerRegistration(
- nullptr, false /* notify_controllerchange */);
- container_host->UpdateUrls(
- GURL(), net::SiteForCookies(), base::nullopt);
- }
- },
- // Unretained() is safe because the handle owns the core,
- // and core gets deleted on the core thread in a task that
- // must occur after this task.
- base::Unretained(service_worker_handle_->core())));
- }
+bool NavigationURLLoaderImpl::MaybeCreateLoaderForResponse(
+ network::mojom::URLResponseHeadPtr* response) {
+ if (!default_loader_used_ &&
+ !web_bundle_utils::CanLoadAsWebBundle(url_, (*response)->mime_type)) {
+ return false;
+ }
+ for (auto& interceptor : interceptors_) {
+ mojo::PendingReceiver<network::mojom::URLLoaderClient>
+ response_client_receiver;
+ bool skip_other_interceptors = false;
+ bool will_return_unsafe_redirect = false;
+ if (interceptor->MaybeCreateLoaderForResponse(
+ *resource_request_, response, &response_body_,
+ &response_url_loader_, &response_client_receiver, url_loader_.get(),
+ &skip_other_interceptors, &will_return_unsafe_redirect)) {
+ if (will_return_unsafe_redirect)
+ bypass_redirect_checks_ = true;
+ response_loader_receiver_.reset();
+ response_loader_receiver_.Bind(std::move(response_client_receiver));
+ default_loader_used_ = false;
+ url_loader_.reset(); // Consumed above.
+ response_body_.reset(); // Consumed above.
+ if (skip_other_interceptors) {
+ std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
+ new_interceptors;
+ new_interceptors.push_back(std::move(interceptor));
+ new_interceptors.swap(interceptors_);
+ // Reset the state of ServiceWorkerContainerHost.
+ // Currently we don't support Service Worker in Signed Exchange
+ // pages. The page will not be controlled by service workers. And
+ // Service Worker related APIs will fail with NoDocumentURL error.
+ // TODO(crbug/898733): Support SignedExchange loading and Service
+ // Worker integration.
+ if (service_worker_handle_) {
+ RunOrPostTaskOnThread(
+ FROM_HERE, ServiceWorkerContext::GetCoreThreadId(),
+ base::BindOnce(
+ [](ServiceWorkerMainResourceHandleCore* core) {
+ base::WeakPtr<ServiceWorkerContainerHost> container_host =
+ core->container_host();
+ if (container_host) {
+ container_host->SetControllerRegistration(
+ nullptr, false /* notify_controllerchange */);
+ container_host->UpdateUrls(GURL(), net::SiteForCookies(),
+ base::nullopt);
+ }
+ },
+ // Unretained() is safe because the handle owns the core,
+ // and core gets deleted on the core thread in a task that
+ // must occur after this task.
+ base::Unretained(service_worker_handle_->core())));
}
- return true;
}
+ return true;
}
- return false;
- }
-
- std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
- CreateURLLoaderThrottles() {
- return CreateContentBrowserURLLoaderThrottles(
- *resource_request_, browser_context_, web_contents_getter_,
- navigation_ui_data_.get(), frame_tree_node_id_);
- }
-
- std::unique_ptr<SignedExchangeRequestHandler>
- CreateSignedExchangeRequestHandler(
- const NavigationRequestInfo& request_info,
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
- scoped_refptr<SignedExchangePrefetchMetricRecorder>
- signed_exchange_prefetch_metric_recorder,
- std::string accept_langs) {
- // It is safe to pass the callback of CreateURLLoaderThrottles with the
- // unretained |this|, because the passed callback will be used by a
- // SignedExchangeHandler which is indirectly owned by |this| until its
- // header is verified and parsed, that's where the getter is used.
- return std::make_unique<SignedExchangeRequestHandler>(
- GetURLLoaderOptions(request_info.is_main_frame),
- request_info.frame_tree_node_id, request_info.devtools_navigation_token,
- std::move(url_loader_factory),
- base::BindRepeating(
- &URLLoaderRequestController::CreateURLLoaderThrottles,
- base::Unretained(this)),
- std::move(signed_exchange_prefetch_metric_recorder),
- std::move(accept_langs));
}
+ return false;
+}
- void ParseHeaders(const GURL& url,
- network::mojom::URLResponseHead* head,
- base::OnceClosure continuation) {
- // The main path:
- // --------------
- // The ParsedHeaders are already provided. No more work needed.
- //
- // Currently used when the response is coming from:
- // - Network
- // - ServiceWorker
- // - WebUI
- if (head->parsed_headers) {
- std::move(continuation).Run();
- return;
- }
-
- // As an optimization, when we know the parsed headers will be empty, we can
- // skip the network process roundtrip.
- // TODO(arthursonzogni): If there are any performance issues, consider
- // checking the |head->headers| contains at least one header to be parsed.
- if (!head->headers) {
- head->parsed_headers = network::mojom::ParsedHeaders::New();
- std::move(continuation).Run();
- return;
- }
-
- auto assign = [](base::OnceClosure continuation,
- network::mojom::URLResponseHead* head,
- network::mojom::ParsedHeadersPtr parsed_headers) {
- head->parsed_headers = std::move(parsed_headers);
- std::move(continuation).Run();
- };
+std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
+NavigationURLLoaderImpl::CreateURLLoaderThrottles() {
+ return CreateContentBrowserURLLoaderThrottles(
+ *resource_request_, browser_context_, web_contents_getter_,
+ navigation_ui_data_.get(), frame_tree_node_id_);
+}
- storage_partition_->GetNetworkContext()->ParseHeaders(
- url, head->headers,
- base::BindOnce(assign, std::move(continuation), head));
- }
+std::unique_ptr<SignedExchangeRequestHandler>
+NavigationURLLoaderImpl::CreateSignedExchangeRequestHandler(
+ const NavigationRequestInfo& request_info,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ scoped_refptr<SignedExchangePrefetchMetricRecorder>
+ signed_exchange_prefetch_metric_recorder,
+ std::string accept_langs) {
+ // It is safe to pass the callback of CreateURLLoaderThrottles with the
+ // unretained |this|, because the passed callback will be used by a
+ // SignedExchangeHandler which is indirectly owned by |this| until its
+ // header is verified and parsed, that's where the getter is used.
+ return std::make_unique<SignedExchangeRequestHandler>(
+ GetURLLoaderOptions(request_info.is_main_frame),
+ request_info.frame_tree_node_id, request_info.devtools_navigation_token,
+ std::move(url_loader_factory),
+ base::BindRepeating(&NavigationURLLoaderImpl::CreateURLLoaderThrottles,
+ base::Unretained(this)),
+ std::move(signed_exchange_prefetch_metric_recorder),
+ std::move(accept_langs));
+}
- std::vector<std::unique_ptr<NavigationLoaderInterceptor>> interceptors_;
- size_t interceptor_index_ = 0;
-
- std::unique_ptr<network::ResourceRequest> resource_request_;
- // Non-NetworkService: |request_info_| is updated along with
- // |resource_request_| on redirects.
- std::unique_ptr<NavigationRequestInfo> request_info_;
- int frame_tree_node_id_ = 0;
- GlobalRequestID global_request_id_;
- net::RedirectInfo redirect_info_;
- int redirect_limit_ = net::URLRequest::kMaxRedirects;
- base::RepeatingCallback<WebContents*()> web_contents_getter_;
- std::unique_ptr<NavigationUIData> navigation_ui_data_;
- scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory_;
-
- std::unique_ptr<blink::ThrottlingURLLoader> url_loader_;
-
- // Caches the modified request headers provided by clients during redirect,
- // will be consumed by next |url_loader_->FollowRedirect()|.
- std::vector<std::string> url_loader_removed_headers_;
- net::HttpRequestHeaders url_loader_modified_headers_;
- net::HttpRequestHeaders url_loader_modified_cors_exempt_headers_;
-
- std::vector<GURL> url_chain_;
-
- // Current URL that is being navigated, updated after redirection.
- GURL url_;
-
- // Currently used by the AppCache loader to pass its factory to the
- // renderer which enables it to handle subresources.
- base::Optional<SubresourceLoaderParams> subresource_loader_params_;
-
- // This is referenced only on the UI thread.
- base::WeakPtr<NavigationURLLoaderImpl> owner_;
-
- // Set to true if the default URLLoader (network service) was used for the
- // current navigation.
- bool default_loader_used_ = false;
-
- // URLLoaderClient receiver for loaders created for responses received from
- // the network loader.
- mojo::Receiver<network::mojom::URLLoaderClient> response_loader_receiver_{
- this};
-
- // URLLoader instance for response loaders, i.e loaders created for handling
- // responses received from the network URLLoader.
- mojo::PendingRemote<network::mojom::URLLoader> response_url_loader_;
-
- // Set to true if we receive a valid response from a URLLoader, i.e.
- // URLLoaderClient::OnStartLoadingResponseBody() is called.
- bool received_response_ = false;
-
- // When URLLoaderClient::OnReceiveResponse() is called. For UMA.
- base::TimeTicks on_receive_response_time_;
-
- bool started_ = false;
-
- // Lazily initialized and used in the case of non-network resource
- // navigations. Keyed by URL scheme.
- std::map<std::string, mojo::Remote<network::mojom::URLLoaderFactory>>
- non_network_url_loader_factories_;
-
- // Non-NetworkService:
- // Generator of a request handler for sending request to the network. This
- // captures all of parameters to create a
- // SingleRequestURLLoaderFactory::RequestHandler. Used only when
- // NetworkService is disabled.
- // Set |was_request_intercepted| to true if the request was intercepted by an
- // interceptor and the request is falling back to the network. In that case,
- // any interceptors won't intercept the request.
- base::RepeatingCallback<SingleRequestURLLoaderFactory::RequestHandler(
- bool /* was_request_intercepted */)>
- default_request_handler_factory_;
-
- // The completion status if it has been received. This is needed to handle
- // the case that the response is intercepted by download, and OnComplete() is
- // already called while we are transferring the |url_loader_| and response
- // body to download code.
- base::Optional<network::URLLoaderCompletionStatus> status_;
-
- // Before creating this URLLoaderRequestController on UI thread, the embedder
- // may have elected to proxy the URLLoaderFactory receiver, in which case
- // these fields will contain input (remote) and output (receiver) endpoints
- // for the proxy. If this controller is handling a receiver for which proxying
- // is supported, receivers will be plumbed through these endpoints.
+void NavigationURLLoaderImpl::ParseHeaders(
+ const GURL& url,
+ network::mojom::URLResponseHead* head,
+ base::OnceClosure continuation) {
+ // The main path:
+ // --------------
+ // The ParsedHeaders are already provided. No more work needed.
//
- // Note that these are only used for receivers that go to the Network Service.
- mojo::PendingReceiver<network::mojom::URLLoaderFactory>
- proxied_factory_receiver_;
- mojo::PendingRemote<network::mojom::URLLoaderFactory> proxied_factory_remote_;
-
- // The schemes that this loader can use. For anything else we'll try external
- // protocol handlers.
- std::set<std::string> known_schemes_;
-
- // True when a proxy will handle the redirect checks, or when an interceptor
- // intentionally returned unsafe redirect response
- // (eg: NavigationLoaderInterceptor for loading a local Web Bundle file).
- bool bypass_redirect_checks_;
-
- ServiceWorkerMainResourceHandle* service_worker_handle_ = nullptr;
-
- // Counts the time overhead of all the hops from the UI to the IO threads.
- base::TimeDelta ui_to_io_time_;
-
- BrowserContext* browser_context_;
- StoragePartitionImpl* storage_partition_;
+ // Currently used when the response is coming from:
+ // - Network
+ // - ServiceWorker
+ // - WebUI
+ if (head->parsed_headers) {
+ std::move(continuation).Run();
+ return;
+ }
- network::mojom::URLResponseHeadPtr head_;
- mojo::ScopedDataPipeConsumerHandle response_body_;
+ // As an optimization, when we know the parsed headers will be empty, we can
+ // skip the network process roundtrip.
+ // TODO(arthursonzogni): If there are any performance issues, consider
+ // checking the |head->headers| contains at least one header to be parsed.
+ if (!head->headers) {
+ head->parsed_headers = network::mojom::ParsedHeaders::New();
+ std::move(continuation).Run();
+ return;
+ }
- mutable base::WeakPtrFactory<URLLoaderRequestController> weak_factory_{this};
+ auto assign = [](base::OnceClosure continuation,
+ network::mojom::URLResponseHead* head,
+ network::mojom::ParsedHeadersPtr parsed_headers) {
+ head->parsed_headers = std::move(parsed_headers);
+ std::move(continuation).Run();
+ };
- DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController);
-};
+ storage_partition_->GetNetworkContext()->ParseHeaders(
+ url, head->headers,
+ base::BindOnce(assign, std::move(continuation), head));
+}
// TODO(https://crbug.com/790734): pass |navigation_ui_data| along with the
// request so that it could be modified.
@@ -1329,42 +1104,49 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
initial_interceptors)
: delegate_(delegate),
- download_policy_(request_info->common_params->download_policy) {
+ browser_context_(browser_context),
+ storage_partition_(static_cast<StoragePartitionImpl*>(storage_partition)),
+ service_worker_handle_(service_worker_handle),
+ request_info_(std::move(request_info)),
+ url_(request_info_->common_params->url),
+ frame_tree_node_id_(request_info_->frame_tree_node_id),
+ global_request_id_(GlobalRequestID::MakeBrowserInitiated()),
+ web_contents_getter_(
+ base::BindRepeating(&WebContents::FromFrameTreeNodeId,
+ frame_tree_node_id_)),
+ navigation_ui_data_(std::move(navigation_ui_data)),
+ interceptors_(std::move(initial_interceptors)),
+ download_policy_(request_info_->common_params->download_policy) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- int frame_tree_node_id = request_info->frame_tree_node_id;
TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1(
"navigation", "Navigation timeToResponseStarted", this,
- request_info->common_params->navigation_start, "FrameTreeNode id",
- frame_tree_node_id);
+ request_info_->common_params->navigation_start, "FrameTreeNode id",
+ frame_tree_node_id_);
- ServiceWorkerMainResourceHandleCore* service_worker_handle_core =
- service_worker_handle ? service_worker_handle->core() : nullptr;
-
- auto* partition = static_cast<StoragePartitionImpl*>(storage_partition);
scoped_refptr<SignedExchangePrefetchMetricRecorder>
signed_exchange_prefetch_metric_recorder =
- partition->GetPrefetchURLLoaderService()
+ storage_partition_->GetPrefetchURLLoaderService()
->signed_exchange_prefetch_metric_recorder();
- std::unique_ptr<network::ResourceRequest> new_request = CreateResourceRequest(
- request_info.get(), frame_tree_node_id, std::move(cookie_observer));
+ resource_request_ = CreateResourceRequest(
+ request_info_.get(), frame_tree_node_id_, std::move(cookie_observer));
- std::string accept_langs = GetContentClient()->browser()->GetAcceptLangs(
- partition->browser_context());
+ std::string accept_langs =
+ GetContentClient()->browser()->GetAcceptLangs(browser_context_);
// Check if a web UI scheme wants to handle this request.
FrameTreeNode* frame_tree_node =
- FrameTreeNode::GloballyFindByID(frame_tree_node_id);
+ FrameTreeNode::GloballyFindByID(frame_tree_node_id_);
const auto& schemes = URLDataManagerBackend::GetWebUISchemes();
- std::string scheme = new_request->url.scheme();
+ std::string scheme = resource_request_->url.scheme();
mojo::PendingRemote<network::mojom::URLLoaderFactory> factory_for_webui;
if (base::Contains(schemes, scheme)) {
DCHECK(frame_tree_node);
DCHECK(frame_tree_node->navigation_request());
auto factory_receiver = factory_for_webui.InitWithNewPipeAndPassReceiver();
GetContentClient()->browser()->WillCreateURLLoaderFactory(
- partition->browser_context(), frame_tree_node->current_frame_host(),
+ browser_context_, frame_tree_node->current_frame_host(),
frame_tree_node->current_frame_host()->GetProcess()->GetID(),
ContentBrowserClient::URLLoaderFactoryType::kNavigation, url::Origin(),
frame_tree_node->navigation_request()->GetNavigationId(),
@@ -1375,35 +1157,32 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
std::move(factory_receiver));
}
- mojo::PendingRemote<network::mojom::URLLoaderFactory> proxied_factory_remote;
- mojo::PendingReceiver<network::mojom::URLLoaderFactory>
- proxied_factory_receiver;
mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>
header_client;
- bool bypass_redirect_checks = false;
if (frame_tree_node) {
+ // Initialize proxied factory remote/receiver if necessary.
+ // This also populates |bypass_redirect_checks_|.
DCHECK(frame_tree_node->navigation_request());
// |frame_tree_node| may be null in some unit test environments.
GetContentClient()
->browser()
->RegisterNonNetworkNavigationURLLoaderFactories(
- frame_tree_node_id, &non_network_url_loader_factories_);
+ frame_tree_node_id_, &non_network_url_loader_factories_);
// The embedder may want to proxy all network-bound URLLoaderFactory
- // receivers that it can. If it elects to do so, we'll pass its proxy
- // endpoints off to the URLLoaderRequestController where wthey will be
- // connected if the request type supports proxying.
+ // receivers that it can. If it elects to do so, those proxies will be
+ // connected when loader is created if the request type supports proxying.
mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_factory;
auto factory_receiver = pending_factory.InitWithNewPipeAndPassReceiver();
// Here we give nullptr for |factory_override|, because CORS is no-op for
// navigations.
bool use_proxy = GetContentClient()->browser()->WillCreateURLLoaderFactory(
- partition->browser_context(), frame_tree_node->current_frame_host(),
+ browser_context_, frame_tree_node->current_frame_host(),
frame_tree_node->current_frame_host()->GetProcess()->GetID(),
ContentBrowserClient::URLLoaderFactoryType::kNavigation, url::Origin(),
frame_tree_node->navigation_request()->GetNavigationId(),
- &factory_receiver, &header_client, &bypass_redirect_checks,
+ &factory_receiver, &header_client, &bypass_redirect_checks_,
nullptr /* disable_secure_dns */, nullptr /* factory_override */);
if (devtools_instrumentation::WillCreateURLLoaderFactory(
frame_tree_node->current_frame_host(), true /* is_navigation */,
@@ -1412,17 +1191,17 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
use_proxy = true;
}
if (use_proxy) {
- proxied_factory_receiver = std::move(factory_receiver);
- proxied_factory_remote = std::move(pending_factory);
+ proxied_factory_receiver_ = std::move(factory_receiver);
+ proxied_factory_remote_ = std::move(pending_factory);
}
const std::string storage_domain;
non_network_url_loader_factories_.emplace(
url::kFileSystemScheme,
- CreateFileSystemURLLoaderFactory(ChildProcessHost::kInvalidUniqueID,
- frame_tree_node->frame_tree_node_id(),
- partition->GetFileSystemContext(),
- storage_domain));
+ CreateFileSystemURLLoaderFactory(
+ ChildProcessHost::kInvalidUniqueID,
+ frame_tree_node->frame_tree_node_id(),
+ storage_partition_->GetFileSystemContext(), storage_domain));
}
non_network_url_loader_factories_.emplace(
@@ -1433,8 +1212,8 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
std::unique_ptr<network::mojom::URLLoaderFactory> file_url_loader_factory =
std::make_unique<FileURLLoaderFactory>(
- partition->browser_context()->GetPath(),
- partition->browser_context()->GetSharedCorsOriginAccessList(),
+ browser_context_->GetPath(),
+ browser_context_->GetSharedCorsOriginAccessList(),
// USER_VISIBLE because loaded file resources may affect the UI.
base::TaskPriority::USER_VISIBLE);
@@ -1456,43 +1235,29 @@ NavigationURLLoaderImpl::NavigationURLLoaderImpl(
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})));
#endif
- std::set<std::string> known_schemes;
for (auto& iter : non_network_url_loader_factories_)
- known_schemes.insert(iter.first);
+ known_schemes_.insert(iter.first);
bool needs_loader_factory_interceptor = false;
std::unique_ptr<network::PendingSharedURLLoaderFactory>
pending_network_factory =
- partition->GetURLLoaderFactoryForBrowserProcess()->Clone();
+ storage_partition_->GetURLLoaderFactoryForBrowserProcess()->Clone();
if (header_client) {
needs_loader_factory_interceptor = true;
mojo::PendingRemote<network::mojom::URLLoaderFactory> factory_remote;
CreateURLLoaderFactoryWithHeaderClient(
std::move(header_client),
- factory_remote.InitWithNewPipeAndPassReceiver(), partition);
+ factory_remote.InitWithNewPipeAndPassReceiver(), storage_partition_);
pending_network_factory =
std::make_unique<network::WrapperPendingSharedURLLoaderFactory>(
std::move(factory_remote));
}
- DCHECK(!request_controller_);
- request_controller_ = std::make_unique<URLLoaderRequestController>(
- std::move(initial_interceptors), std::move(new_request), browser_context,
- partition, request_info->common_params->url,
- std::move(proxied_factory_receiver), std::move(proxied_factory_remote),
- std::move(known_schemes), bypass_redirect_checks,
- weak_factory_.GetWeakPtr());
- request_controller_->Start(
- std::move(pending_network_factory), service_worker_handle,
- service_worker_handle_core, appcache_handle,
- std::move(prefetched_signed_exchange_cache),
- std::move(signed_exchange_prefetch_metric_recorder),
- std::move(request_info), std::move(navigation_ui_data),
- std::move(factory_for_webui), needs_loader_factory_interceptor,
- base::Time::Now(), std::move(accept_langs));
-}
-
-NavigationURLLoaderImpl::~NavigationURLLoaderImpl() {
+ Start(std::move(pending_network_factory), appcache_handle,
+ std::move(prefetched_signed_exchange_cache),
+ std::move(signed_exchange_prefetch_metric_recorder),
+ std::move(factory_for_webui), std::move(accept_langs),
+ needs_loader_factory_interceptor);
}
void NavigationURLLoaderImpl::FollowRedirect(
@@ -1500,26 +1265,24 @@ void NavigationURLLoaderImpl::FollowRedirect(
const net::HttpRequestHeaders& modified_headers,
const net::HttpRequestHeaders& modified_cors_exempt_headers,
PreviewsState new_previews_state) {
- request_controller_->FollowRedirect(removed_headers, modified_headers,
- modified_cors_exempt_headers,
- new_previews_state, base::Time::Now());
+ FollowRedirectInternal(removed_headers, modified_headers,
+ modified_cors_exempt_headers, new_previews_state,
+ base::Time::Now());
}
-void NavigationURLLoaderImpl::OnReceiveResponse(
+void NavigationURLLoaderImpl::NotifyRequestStarted(base::TimeTicks timestamp) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ delegate_->OnRequestStarted(timestamp);
+}
+
+void NavigationURLLoaderImpl::NotifyResponseStarted(
network::mojom::URLResponseHeadPtr response_head,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
mojo::ScopedDataPipeConsumerHandle response_body,
const GlobalRequestID& global_request_id,
- bool is_download,
- base::TimeDelta total_ui_to_io_time,
- base::Time io_post_time) {
- const base::TimeDelta kMinTime = base::TimeDelta::FromMicroseconds(1);
- const base::TimeDelta kMaxTime = base::TimeDelta::FromMilliseconds(100);
- const int kBuckets = 50;
- io_to_ui_time_ += (base::Time::Now() - io_post_time);
- UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
- "Navigation.NavigationURLLoaderImplIOPostTime",
- io_to_ui_time_ + total_ui_to_io_time, kMinTime, kMaxTime, kBuckets);
+ bool is_download) {
+ // TODO(https://crbug.com/1068896): Remove
+ // "Navigation.NavigationURLLoaderImplIOPostTime" histogram as well.
TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this,
"&NavigationURLLoaderImpl", this, "success", true);
@@ -1533,20 +1296,17 @@ void NavigationURLLoaderImpl::OnReceiveResponse(
std::move(url_loader_client_endpoints), std::move(response_head),
std::move(response_body),
GlobalRequestID(global_request_id.child_id, global_request_id.request_id),
- is_download, download_policy_,
- request_controller_->TakeSubresourceLoaderParams());
+ is_download, download_policy_, std::move(subresource_loader_params_));
}
-void NavigationURLLoaderImpl::OnReceiveRedirect(
+void NavigationURLLoaderImpl::NotifyRequestRedirected(
net::RedirectInfo redirect_info,
- network::mojom::URLResponseHeadPtr response_head,
- base::Time io_post_time) {
+ network::mojom::URLResponseHeadPtr response_head) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- io_to_ui_time_ += (base::Time::Now() - io_post_time);
delegate_->OnRequestRedirected(redirect_info, std::move(response_head));
}
-void NavigationURLLoaderImpl::OnComplete(
+void NavigationURLLoaderImpl::NotifyRequestFailed(
const network::URLLoaderCompletionStatus& status) {
TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this,
"&NavigationURLLoaderImpl", this, "success", false);
@@ -1582,13 +1342,7 @@ void NavigationURLLoaderImpl::CreateURLLoaderFactoryWithHeaderClient(
std::move(factory_receiver), std::move(params));
}
-void NavigationURLLoaderImpl::OnRequestStarted(base::TimeTicks timestamp) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- delegate_->OnRequestStarted(timestamp);
-}
-
void NavigationURLLoaderImpl::BindNonNetworkURLLoaderFactoryReceiver(
- int frame_tree_node_id,
const GURL& url,
mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory_receiver) {
auto it = non_network_url_loader_factories_.find(url.scheme());
@@ -1598,7 +1352,7 @@ void NavigationURLLoaderImpl::BindNonNetworkURLLoaderFactoryReceiver(
}
FrameTreeNode* frame_tree_node =
- FrameTreeNode::GloballyFindByID(frame_tree_node_id);
+ FrameTreeNode::GloballyFindByID(frame_tree_node_id_);
DCHECK(frame_tree_node);
DCHECK(frame_tree_node->navigation_request());
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl.h b/chromium/content/browser/loader/navigation_url_loader_impl.h
index 0d856e83a47..fea2619adc1 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl.h
+++ b/chromium/content/browser/loader/navigation_url_loader_impl.h
@@ -10,8 +10,11 @@
#include "base/optional.h"
#include "base/time/time.h"
#include "content/browser/loader/navigation_url_loader.h"
+#include "content/browser/loader/single_request_url_loader_factory.h"
+#include "content/browser/navigation_subresource_loader_params.h"
#include "content/common/navigation_params.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/global_request_id.h"
#include "content/public/browser/ssl_status.h"
#include "content/public/common/previews_state.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -29,11 +32,15 @@ namespace content {
class BrowserContext;
class NavigationLoaderInterceptor;
class PrefetchedSignedExchangeCache;
+class SignedExchangePrefetchMetricRecorder;
+class SignedExchangeRequestHandler;
class StoragePartition;
class StoragePartitionImpl;
-struct GlobalRequestID;
+struct WebPluginInfo;
-class CONTENT_EXPORT NavigationURLLoaderImpl : public NavigationURLLoader {
+class CONTENT_EXPORT NavigationURLLoaderImpl
+ : public NavigationURLLoader,
+ public network::mojom::URLLoaderClient {
public:
// The caller is responsible for ensuring that |delegate| outlives the loader.
// Note |initial_interceptors| is there for test purposes only.
@@ -52,6 +59,101 @@ class CONTENT_EXPORT NavigationURLLoaderImpl : public NavigationURLLoader {
initial_interceptors);
~NavigationURLLoaderImpl() override;
+ // TODO(kinuko): Make most of these methods private.
+ // TODO(kinuko): Some method parameters can probably be just kept as
+ // member variables rather than being passed around.
+
+ // Starts the loader by finalizing loader factories initialization and
+ // calling Restart().
+ // This is called only once (while Restart can be called multiple times).
+ // Sets |started_| true.
+ void Start(
+ std::unique_ptr<network::PendingSharedURLLoaderFactory>
+ pending_network_loader_factory,
+ AppCacheNavigationHandle* appcache_handle,
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache,
+ scoped_refptr<SignedExchangePrefetchMetricRecorder>
+ signed_exchange_prefetch_metric_recorder,
+ mojo::PendingRemote<network::mojom::URLLoaderFactory> factory_for_webui,
+ std::string accept_langs,
+ bool needs_loader_factory_interceptor);
+ void CreateInterceptors(AppCacheNavigationHandle* appcache_handle,
+ scoped_refptr<PrefetchedSignedExchangeCache>
+ prefetched_signed_exchange_cache,
+ scoped_refptr<SignedExchangePrefetchMetricRecorder>
+ signed_exchange_prefetch_metric_recorder,
+ const std::string& accept_langs);
+
+ // This could be called multiple times to follow a chain of redirects.
+ void Restart();
+
+ // |interceptor| is non-null if this is called by one of the interceptors
+ // (via a LoaderCallback).
+ // |single_request_handler| is the RequestHandler given by the
+ // |interceptor|, non-null if the interceptor wants to handle the request.
+ void MaybeStartLoader(
+ NavigationLoaderInterceptor* interceptor,
+ scoped_refptr<network::SharedURLLoaderFactory> single_request_factory);
+
+ // This is the |fallback_callback| passed to
+ // NavigationLoaderInterceptor::MaybeCreateLoader. It allows an interceptor
+ // to initially elect to handle a request, and later decide to fallback to
+ // the default behavior. This is needed for service worker network fallback
+ // and signed exchange (SXG) fallback redirect.
+ void FallbackToNonInterceptedRequest(bool reset_subresource_loader_params);
+
+ scoped_refptr<network::SharedURLLoaderFactory>
+ PrepareForNonInterceptedRequest(uint32_t* out_options);
+
+ // TODO(kinuko): Merge this back to FollowRedirect().
+ void FollowRedirectInternal(
+ const std::vector<std::string>& removed_headers,
+ const net::HttpRequestHeaders& modified_headers,
+ const net::HttpRequestHeaders& modified_cors_exempt_headers,
+ PreviewsState new_previews_state,
+ base::Time ui_post_time);
+
+ // network::mojom::URLLoaderClient implementation:
+ void OnReceiveResponse(network::mojom::URLResponseHeadPtr head) override;
+ void OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle response_body) override;
+ void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
+ network::mojom::URLResponseHeadPtr head) override;
+ void OnUploadProgress(int64_t current_position,
+ int64_t total_size,
+ OnUploadProgressCallback callback) override;
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override;
+ void OnTransferSizeUpdated(int32_t transfer_size_diff) override {}
+ void OnComplete(const network::URLLoaderCompletionStatus& status) override;
+
+#if BUILDFLAG(ENABLE_PLUGINS)
+ void CheckPluginAndContinueOnReceiveResponse(
+ network::mojom::URLResponseHeadPtr head,
+ network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
+ bool is_download_if_not_handled_by_plugin,
+ const std::vector<WebPluginInfo>& plugins);
+#endif
+
+ void CallOnReceivedResponse(
+ network::mojom::URLResponseHeadPtr head,
+ network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
+ bool is_download);
+ bool MaybeCreateLoaderForResponse(
+ network::mojom::URLResponseHeadPtr* response);
+ std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
+ CreateURLLoaderThrottles();
+ std::unique_ptr<SignedExchangeRequestHandler>
+ CreateSignedExchangeRequestHandler(
+ const NavigationRequestInfo& request_info,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ scoped_refptr<SignedExchangePrefetchMetricRecorder>
+ signed_exchange_prefetch_metric_recorder,
+ std::string accept_langs);
+ void ParseHeaders(const GURL& url,
+ network::mojom::URLResponseHead* head,
+ base::OnceClosure continuation);
+
// NavigationURLLoader implementation:
void FollowRedirect(
const std::vector<std::string>& removed_headers,
@@ -59,31 +161,29 @@ class CONTENT_EXPORT NavigationURLLoaderImpl : public NavigationURLLoader {
const net::HttpRequestHeaders& modified_cors_exempt_headers,
PreviewsState new_previews_state) override;
- void OnReceiveResponse(
+ void NotifyRequestStarted(base::TimeTicks timestamp);
+ void NotifyResponseStarted(
network::mojom::URLResponseHeadPtr response_head,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
mojo::ScopedDataPipeConsumerHandle response_body,
const GlobalRequestID& global_request_id,
- bool is_download,
- base::TimeDelta total_ui_to_io_time,
- base::Time io_post_time);
- void OnReceiveRedirect(net::RedirectInfo redirect_info,
- network::mojom::URLResponseHeadPtr response,
- base::Time io_post_time);
- void OnComplete(const network::URLLoaderCompletionStatus& status);
+ bool is_download);
+ void NotifyRequestRedirected(net::RedirectInfo redirect_info,
+ network::mojom::URLResponseHeadPtr response);
+ void NotifyRequestFailed(const network::URLLoaderCompletionStatus& status);
// Intercepts loading of frame requests when network service is enabled and
- // either a network::mojom::TrustedURLLoaderHeaderClient is being used or for
- // schemes not handled by network service (e.g. files). This must be called on
- // the UI thread or before threads start.
+ // either a network::mojom::TrustedURLLoaderHeaderClient is being used or
+ // for schemes not handled by network service (e.g. files). This must be
+ // called on the UI thread or before threads start.
using URLLoaderFactoryInterceptor = base::RepeatingCallback<void(
mojo::PendingReceiver<network::mojom::URLLoaderFactory>* receiver)>;
static void SetURLLoaderFactoryInterceptorForTesting(
const URLLoaderFactoryInterceptor& interceptor);
// Creates a URLLoaderFactory for a navigation. The factory uses
- // |header_client|. This should have the same settings as the factory from the
- // URLLoaderFactoryGetter. Called on the UI thread.
+ // |header_client|. This should have the same settings as the factory from
+ // the URLLoaderFactoryGetter. Called on the UI thread.
static void CreateURLLoaderFactoryWithHeaderClient(
mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>
header_client,
@@ -91,18 +191,102 @@ class CONTENT_EXPORT NavigationURLLoaderImpl : public NavigationURLLoader {
StoragePartitionImpl* partition);
private:
- class URLLoaderRequestController;
- void OnRequestStarted(base::TimeTicks timestamp);
+ // TODO(kinuko): This can be a file-local private anonymous function.
+ static uint32_t GetURLLoaderOptions(bool is_main_frame);
void BindNonNetworkURLLoaderFactoryReceiver(
- int frame_tree_node_id,
const GURL& url,
mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory_receiver);
NavigationURLLoaderDelegate* delegate_;
+ BrowserContext* browser_context_;
+ StoragePartitionImpl* storage_partition_;
+ ServiceWorkerMainResourceHandle* service_worker_handle_;
+
+ std::unique_ptr<network::ResourceRequest> resource_request_;
+ std::unique_ptr<NavigationRequestInfo> request_info_;
- // Lives on the IO thread.
- std::unique_ptr<URLLoaderRequestController> request_controller_;
+ // Current URL that is being navigated, updated after redirection.
+ GURL url_;
+
+ // Redirect URL chain.
+ std::vector<GURL> url_chain_;
+
+ const int frame_tree_node_id_;
+ const GlobalRequestID global_request_id_;
+ net::RedirectInfo redirect_info_;
+ int redirect_limit_ = net::URLRequest::kMaxRedirects;
+ base::RepeatingCallback<WebContents*()> web_contents_getter_;
+ std::unique_ptr<NavigationUIData> navigation_ui_data_;
+
+ scoped_refptr<network::SharedURLLoaderFactory> network_loader_factory_;
+ std::unique_ptr<blink::ThrottlingURLLoader> url_loader_;
+
+ // Caches the modified request headers provided by clients during redirect,
+ // will be consumed by next |url_loader_->FollowRedirect()|.
+ std::vector<std::string> url_loader_removed_headers_;
+ net::HttpRequestHeaders url_loader_modified_headers_;
+ net::HttpRequestHeaders url_loader_modified_cors_exempt_headers_;
+
+ // Currently used by the AppCache loader to pass its factory to the
+ // renderer which enables it to handle subresources.
+ base::Optional<SubresourceLoaderParams> subresource_loader_params_;
+
+ std::vector<std::unique_ptr<NavigationLoaderInterceptor>> interceptors_;
+ size_t interceptor_index_ = 0;
+
+ // Set to true if the default URLLoader (network service) was used for the
+ // current navigation.
+ bool default_loader_used_ = false;
+
+ // URLLoaderClient receiver for loaders created for responses received from
+ // the network loader.
+ mojo::Receiver<network::mojom::URLLoaderClient> response_loader_receiver_{
+ this};
+
+ // URLLoader instance for response loaders, i.e loaders created for handling
+ // responses received from the network URLLoader.
+ mojo::PendingRemote<network::mojom::URLLoader> response_url_loader_;
+
+ // Set to true if we receive a valid response from a URLLoader, i.e.
+ // URLLoaderClient::OnStartLoadingResponseBody() is called.
+ bool received_response_ = false;
+
+ // When URLLoaderClient::OnReceiveResponse() is called. For UMA.
+ base::TimeTicks on_receive_response_time_;
+
+ bool started_ = false;
+
+ // The completion status if it has been received. This is needed to handle
+ // the case that the response is intercepted by download, and OnComplete()
+ // is already called while we are transferring the |url_loader_| and
+ // response body to download code.
+ base::Optional<network::URLLoaderCompletionStatus> status_;
+
+ // Before creating this URLLoaderRequestController on UI thread, the
+ // embedder may have elected to proxy the URLLoaderFactory receiver, in
+ // which case these fields will contain input (remote) and output (receiver)
+ // endpoints for the proxy. If this controller is handling a receiver for
+ // which proxying is supported, receivers will be plumbed through these
+ // endpoints.
+ //
+ // Note that these are only used for receivers that go to the Network
+ // Service.
+ mojo::PendingReceiver<network::mojom::URLLoaderFactory>
+ proxied_factory_receiver_;
+ mojo::PendingRemote<network::mojom::URLLoaderFactory> proxied_factory_remote_;
+
+ // The schemes that this loader can use. For anything else we'll try
+ // external protocol handlers.
+ std::set<std::string> known_schemes_;
+
+ // True when a proxy will handle the redirect checks, or when an interceptor
+ // intentionally returned unsafe redirect response
+ // (eg: NavigationLoaderInterceptor for loading a local Web Bundle file).
+ bool bypass_redirect_checks_ = false;
+
+ network::mojom::URLResponseHeadPtr head_;
+ mojo::ScopedDataPipeConsumerHandle response_body_;
NavigationDownloadPolicy download_policy_;
@@ -110,6 +294,14 @@ class CONTENT_EXPORT NavigationURLLoaderImpl : public NavigationURLLoader {
ContentBrowserClient::NonNetworkURLLoaderFactoryMap
non_network_url_loader_factories_;
+ // Lazily initialized and used in the case of non-network resource
+ // navigations. Keyed by URL scheme.
+ // (These are cloned by entries populated in
+ // non_network_url_loader_factories_ and are ready to use, i.e. preparation
+ // calls like WillCreateURLLoaderFactory are already called)
+ std::map<std::string, mojo::Remote<network::mojom::URLLoaderFactory>>
+ non_network_url_loader_factory_remotes_;
+
// Counts the time overhead of all the hops from the IO to the UI threads.
base::TimeDelta io_to_ui_time_;
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc b/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc
index 82ebc55f63f..c474d0e8fab 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_impl_unittest.cc
@@ -97,7 +97,8 @@ class TestNavigationLoaderInterceptor : public NavigationLoaderInterceptor {
base::BindOnce(&TestNavigationLoaderInterceptor::DeleteURLLoader,
base::Unretained(this)),
std::move(receiver), 0 /* options */, resource_request,
- std::move(client), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ std::move(client), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0, /* request_id */
0 /* keepalive_request_size */, resource_scheduler_client_,
nullptr /* keepalive_statistics_recorder */,
diff --git a/chromium/content/browser/loader/prefetch_browsertest.cc b/chromium/content/browser/loader/prefetch_browsertest.cc
index 387af864050..3244122bd0f 100644
--- a/chromium/content/browser/loader/prefetch_browsertest.cc
+++ b/chromium/content/browser/loader/prefetch_browsertest.cc
@@ -249,6 +249,15 @@ IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest,
}
IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest,
+ CrossOriginDocumentFromOpaqueOrigin) {
+ // Prefetching as=document from a data: URL does not crash the renderer.
+ EXPECT_TRUE(NavigateToURL(
+ shell(),
+ GURL("data:text/html,<title>Data URL Prefetch Target</title><link "
+ "rel=prefetch as=document href=https://google.com>")));
+}
+
+IN_PROC_BROWSER_TEST_P(PrefetchBrowserTest,
CrossOriginDocumentNotReusedAsNestedFrameNavigation) {
// This test is relevant only with SplitCache.
// TODO(crbug.com/910708): Remove this early-return when SplitCache is enabled
diff --git a/chromium/content/browser/loader/prefetch_url_loader.cc b/chromium/content/browser/loader/prefetch_url_loader.cc
index 4b652887ba2..9c4462083d2 100644
--- a/chromium/content/browser/loader/prefetch_url_loader.cc
+++ b/chromium/content/browser/loader/prefetch_url_loader.cc
@@ -12,6 +12,7 @@
#include "content/browser/web_package/signed_exchange_prefetch_handler.h"
#include "content/browser/web_package/signed_exchange_prefetch_metric_recorder.h"
#include "content/browser/web_package/signed_exchange_utils.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/common/content_features.h"
#include "net/base/load_flags.h"
#include "net/http/http_request_headers.h"
@@ -43,7 +44,6 @@ PrefetchURLLoader::PrefetchURLLoader(
signed_exchange_prefetch_metric_recorder,
scoped_refptr<PrefetchedSignedExchangeCache>
prefetched_signed_exchange_cache,
- base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
const std::string& accept_langs,
RecursivePrefetchTokenGenerator recursive_prefetch_token_generator)
: frame_tree_node_id_(frame_tree_node_id),
diff --git a/chromium/content/browser/loader/prefetch_url_loader.h b/chromium/content/browser/loader/prefetch_url_loader.h
index d2ecfa5cac5..342a8e5090a 100644
--- a/chromium/content/browser/loader/prefetch_url_loader.h
+++ b/chromium/content/browser/loader/prefetch_url_loader.h
@@ -24,10 +24,6 @@
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "url/gurl.h"
-namespace storage {
-class BlobStorageContext;
-} // namespace storage
-
namespace network {
class SharedURLLoaderFactory;
}
@@ -43,7 +39,8 @@ class PrefetchedSignedExchangeCacheAdapter;
class SignedExchangePrefetchHandler;
class SignedExchangePrefetchMetricRecorder;
-// PrefetchURLLoader which basically just keeps draining the data.
+// A URLLoader for loading a prefetch request, including <link rel="prefetch">.
+// It basically just keeps draining the data.
class CONTENT_EXPORT PrefetchURLLoader : public network::mojom::URLLoader,
public network::mojom::URLLoaderClient,
public mojo::DataPipeDrainer::Client {
@@ -72,7 +69,6 @@ class CONTENT_EXPORT PrefetchURLLoader : public network::mojom::URLLoader,
signed_exchange_prefetch_metric_recorder,
scoped_refptr<PrefetchedSignedExchangeCache>
prefetched_signed_exchange_cache,
- base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
const std::string& accept_langs,
RecursivePrefetchTokenGenerator recursive_prefetch_token_generator);
~PrefetchURLLoader() override;
diff --git a/chromium/content/browser/loader/prefetch_url_loader_service.cc b/chromium/content/browser/loader/prefetch_url_loader_service.cc
index 8e8dfa97694..7f222002556 100644
--- a/chromium/content/browser/loader/prefetch_url_loader_service.cc
+++ b/chromium/content/browser/loader/prefetch_url_loader_service.cc
@@ -7,13 +7,12 @@
#include "base/bind.h"
#include "base/feature_list.h"
#include "base/time/default_tick_clock.h"
-#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/loader/prefetch_url_loader.h"
-#include "content/browser/loader/url_loader_throttles.h"
#include "content/browser/url_loader_factory_getter.h"
#include "content/browser/web_package/prefetched_signed_exchange_cache.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/url_loader_throttles.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
#include "mojo/public/cpp/bindings/message.h"
@@ -23,7 +22,6 @@
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
-#include "storage/browser/blob/blob_storage_context.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/loader/url_loader_throttle.h"
#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
@@ -218,8 +216,7 @@ void PrefetchURLLoaderService::CreateLoaderAndStart(
&PrefetchURLLoaderService::CreateURLLoaderThrottles, this,
resource_request, current_context.frame_tree_node_id),
browser_context_, signed_exchange_prefetch_metric_recorder_,
- std::move(prefetched_signed_exchange_cache), blob_storage_context_,
- accept_langs_,
+ std::move(prefetched_signed_exchange_cache), accept_langs_,
base::BindOnce(
&PrefetchURLLoaderService::GenerateRecursivePrefetchToken, this,
current_context.weak_ptr_factory.GetWeakPtr())),
diff --git a/chromium/content/browser/loader/prefetch_url_loader_service.h b/chromium/content/browser/loader/prefetch_url_loader_service.h
index 98e29f04230..f9305193991 100644
--- a/chromium/content/browser/loader/prefetch_url_loader_service.h
+++ b/chromium/content/browser/loader/prefetch_url_loader_service.h
@@ -20,10 +20,6 @@
#include "third_party/blink/public/common/loader/url_loader_factory_bundle.h"
#include "third_party/blink/public/mojom/renderer_preference_watcher.mojom.h"
-namespace storage {
-class BlobStorageContext;
-}
-
namespace blink {
class URLLoaderThrottle;
}
@@ -35,6 +31,9 @@ class PrefetchedSignedExchangeCache;
class RenderFrameHostImpl;
class URLLoaderFactoryGetter;
+// A URLLoaderFactory that can be passed to a renderer to use for performing
+// prefetches. The renderer uses it for prefetch requests including <link
+// rel="prefetch">.
class CONTENT_EXPORT PrefetchURLLoaderService final
: public base::RefCountedThreadSafe<
PrefetchURLLoaderService,
@@ -127,11 +126,6 @@ class CONTENT_EXPORT PrefetchURLLoaderService final
std::string accept_langs_;
- // Used to create a BlobDataHandle from a DataPipe of signed exchange's inner
- // response body to store to |prefetched_signed_exchange_cache_| when
- // SignedExchangeSubresourcePrefetch is enabled.
- base::WeakPtr<storage::BlobStorageContext> blob_storage_context_;
-
DISALLOW_COPY_AND_ASSIGN(PrefetchURLLoaderService);
};
diff --git a/chromium/content/browser/loader/quic_transport_browsertest.cc b/chromium/content/browser/loader/quic_transport_browsertest.cc
index cc588e56f18..91a6797255b 100644
--- a/chromium/content/browser/loader/quic_transport_browsertest.cc
+++ b/chromium/content/browser/loader/quic_transport_browsertest.cc
@@ -335,5 +335,53 @@ IN_PROC_BROWSER_TEST_F(QuicTransportBrowserTest, BidirectionalStream) {
ASSERT_TRUE(WaitForTitle(ASCIIToUTF16("PASS"), {ASCIIToUTF16("FAIL")}));
}
+IN_PROC_BROWSER_TEST_F(QuicTransportBrowserTest, CertificateFingerprint) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ ASSERT_TRUE(
+ NavigateToURL(shell(), embedded_test_server()->GetURL("/title2.html")));
+
+ ASSERT_TRUE(WaitForTitle(ASCIIToUTF16("Title Of Awesomeness")));
+
+ ASSERT_TRUE(ExecuteScript(
+ shell(), base::StringPrintf(R"JS(
+ async function run() {
+ // The connection fails because the fingerprint does not match.
+ const transport = new QuicTransport(
+ 'quic-transport://localhost:%d/echo', {
+ serverCertificateFingerprints: [
+ {
+ algorithm: "sha-256",
+ value: "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:" +
+ "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00",
+ },
+ ],
+ });
+
+ let fulfilled = false;
+ try {
+ await transport.ready;
+ fulfilled = true
+ } catch {}
+
+ if (fulfilled) {
+ throw Error('ready should be rejected');
+ }
+
+ try {
+ await transport.closed;
+ } catch (e) {
+ return;
+ }
+ throw Error('closed should be rejected');
+ }
+
+ run().then(() => { document.title = 'PASS'; },
+ (e) => { console.log(e); document.title = 'FAIL'; });
+)JS",
+ server_.server_address().port())));
+
+ ASSERT_TRUE(WaitForTitle(ASCIIToUTF16("PASS"), {ASCIIToUTF16("FAIL")}));
+}
+
} // namespace
} // namespace content
diff --git a/chromium/content/browser/loader/url_loader_throttles.cc b/chromium/content/browser/loader/url_loader_throttles.cc
index 5861a44ba28..3ab0ea5b489 100644
--- a/chromium/content/browser/loader/url_loader_throttles.cc
+++ b/chromium/content/browser/loader/url_loader_throttles.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/loader/url_loader_throttles.h"
+#include "content/public/browser/url_loader_throttles.h"
#include "components/variations/net/omnibox_url_loader_throttle.h"
#include "components/variations/net/variations_url_loader_throttle.h"
diff --git a/chromium/content/browser/loader/url_loader_throttles.h b/chromium/content/browser/loader/url_loader_throttles.h
deleted file mode 100644
index dadf9544f09..00000000000
--- a/chromium/content/browser/loader/url_loader_throttles.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// 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 CONTENT_BROWSER_LOADER_URL_LOADER_THROTTLES_H_
-#define CONTENT_BROWSER_LOADER_URL_LOADER_THROTTLES_H_
-
-#include "base/callback.h"
-
-namespace blink {
-class URLLoaderThrottle;
-} // namespace blink
-
-namespace network {
-struct ResourceRequest;
-} // namespace network
-
-namespace content {
-
-class BrowserContext;
-class NavigationUIData;
-class WebContents;
-
-// Wrapper around ContentBrowserClient::CreateURLLoaderThrottles which inserts
-// additional content specific throttles.
-std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
-CreateContentBrowserURLLoaderThrottles(
- const network::ResourceRequest& request,
- BrowserContext* browser_context,
- const base::RepeatingCallback<WebContents*()>& wc_getter,
- NavigationUIData* navigation_ui_data,
- int frame_tree_node_id);
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_LOADER_URL_LOADER_THROTTLES_H_