Enable subresource redirects to all schemes with network service
Previously, subresource requests could not redirect to schemes
other than http/https/data with the network service. Now they can
redirect to all schemes, and have proper safety checks.
This gets rid of the RedirectChecker class and instead just checks
the redirect in WebRequestProxyingURLLoaderFactory if the request
is being proxied. The checks farther downstream will be skipped if
the request is proxied. This should be simpler, and avoids complicated
logic with the RedirectChecker that would have been necessary for
subresource redirects.
The bypass_redirect_checks bit is set if the request is being proxied
by WebRequestProxyingURLLoaderFactory. In that case, all redirect
checks will happen in WebRequestProxyingURLLoaderFactory, because the
webRequest API has special permissions for allowing redirects. For
subresource requests, the bypass_redirect_checks bit is set on the
URLLoaderFactoryBundleInfo that is sent to the renderer from
RenderFrameHostImpl. This is used in ResourceDispatcher to ignore
redirect checks if necessary.
Bug: 868545
Cq-Include-Trybots: luci.chromium.try:linux_mojo
Change-Id: Ib11bf81e5b4b1ec9fa1b8d9178467322df91b30c
Reviewed-on: https://chromium-review.googlesource.com/1157549
Reviewed-by: Kinuko Yasuda <[email protected]>
Reviewed-by: John Abd-El-Malek <[email protected]>
Commit-Queue: Clark DuVall <[email protected]>
Cr-Commit-Position: refs/heads/master@{#582174}
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc
index e51aedd..e998b98f 100644
--- a/content/browser/loader/navigation_url_loader_impl.cc
+++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -52,7 +52,6 @@
#include "content/public/browser/navigation_data.h"
#include "content/public/browser/navigation_ui_data.h"
#include "content/public/browser/plugin_service.h"
-#include "content/public/browser/redirect_checker.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
#include "content/public/browser/ssl_status.h"
#include "content/public/browser/url_loader_request_interceptor.h"
@@ -312,14 +311,8 @@
}
// Determines whether it is safe to redirect to |url|.
-bool IsSafeRedirectTarget(const GURL& url, ResourceContext* resource_context) {
- static base::NoDestructor<std::set<std::string>> kUnsafeSchemes(
- std::set<std::string>({
- url::kAboutScheme, url::kDataScheme, url::kFileScheme,
- url::kFileSystemScheme,
- }));
- return !HasWebUIScheme(url) &&
- kUnsafeSchemes->find(url.scheme()) == kUnsafeSchemes->end() &&
+bool IsRedirectSafe(const GURL& url, ResourceContext* resource_context) {
+ return IsSafeRedirectTarget(url) &&
GetContentClient()->browser()->IsSafeRedirectTarget(url,
resource_context);
}
@@ -345,7 +338,7 @@
network::mojom::URLLoaderFactoryRequest proxied_factory_request,
network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info,
std::set<std::string> known_schemes,
- scoped_refptr<RedirectChecker> redirect_checker,
+ bool bypass_redirect_checks,
const base::WeakPtr<NavigationURLLoaderImpl>& owner)
: interceptors_(std::move(initial_interceptors)),
resource_request_(std::move(resource_request)),
@@ -356,7 +349,7 @@
proxied_factory_request_(std::move(proxied_factory_request)),
proxied_factory_info_(std::move(proxied_factory_info)),
known_schemes_(std::move(known_schemes)),
- redirect_checker_(std::move(redirect_checker)),
+ bypass_redirect_checks_(bypass_redirect_checks),
weak_factory_(this) {}
~URLLoaderRequestController() override {
@@ -1121,17 +1114,11 @@
void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& head) override {
- if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- bool bypass_safety_checks =
- redirect_checker_ &&
- redirect_checker_->ShouldAllowRedirect(global_request_id_.request_id,
- redirect_info);
- if (!bypass_safety_checks &&
- !IsSafeRedirectTarget(redirect_info.new_url, resource_context_)) {
- OnComplete(
- network::URLLoaderCompletionStatus(net::ERR_UNSAFE_REDIRECT));
- return;
- }
+ if (base::FeatureList::IsEnabled(network::features::kNetworkService) &&
+ !bypass_redirect_checks_ &&
+ !IsRedirectSafe(redirect_info.new_url, resource_context_)) {
+ OnComplete(network::URLLoaderCompletionStatus(net::ERR_UNSAFE_REDIRECT));
+ return;
}
if (--redirect_limit_ == 0) {
@@ -1340,7 +1327,8 @@
// protocol handlers.
std::set<std::string> known_schemes_;
- scoped_refptr<RedirectChecker> redirect_checker_;
+ // If true, redirect checks will be handled in a proxy, and not here.
+ bool bypass_redirect_checks_;
mutable base::WeakPtrFactory<URLLoaderRequestController> weak_factory_;
@@ -1391,7 +1379,7 @@
request_info->common_params.url,
/* proxied_url_loader_factory_request */ nullptr,
/* proxied_url_loader_factory_info */ nullptr, std::set<std::string>(),
- /* redirect_checker */ nullptr, weak_factory_.GetWeakPtr());
+ /* bypass_redirect_checks */ false, weak_factory_.GetWeakPtr());
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
@@ -1420,7 +1408,7 @@
network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info;
network::mojom::URLLoaderFactoryRequest proxied_factory_request;
- scoped_refptr<RedirectChecker> redirect_checker;
+ bool bypass_redirect_checks = false;
auto* partition = static_cast<StoragePartitionImpl*>(storage_partition);
if (frame_tree_node) {
// |frame_tree_node| may be null in some unit test environments.
@@ -1437,7 +1425,8 @@
auto factory_request = mojo::MakeRequest(&factory_info);
bool use_proxy = GetContentClient()->browser()->WillCreateURLLoaderFactory(
partition->browser_context(), frame_tree_node->current_frame_host(),
- true /* is_navigation */, &factory_request, &redirect_checker);
+ true /* is_navigation */, &factory_request);
+ bypass_redirect_checks = use_proxy;
if (RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
frame_tree_node->current_frame_host(), true, false,
&factory_request)) {
@@ -1471,7 +1460,7 @@
std::move(initial_interceptors), std::move(new_request), resource_context,
request_info->common_params.url, std::move(proxied_factory_request),
std::move(proxied_factory_info), std::move(known_schemes),
- std::move(redirect_checker), weak_factory_.GetWeakPtr());
+ bypass_redirect_checks, weak_factory_.GetWeakPtr());
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(
@@ -1569,7 +1558,7 @@
auto* frame = frame_tree_node->current_frame_host();
GetContentClient()->browser()->WillCreateURLLoaderFactory(
frame->GetSiteInstance()->GetBrowserContext(), frame,
- true /* is_navigation */, &factory, nullptr /* redirect_checker */);
+ true /* is_navigation */, &factory);
it->second->Clone(std::move(factory));
}