Commit d669835e authored by Andy Paicu's avatar Andy Paicu Committed by Commit Bot

Origin policy fetching is now triggered from the network service

This represents steps 7 and 8 of:
https://docs.google.com/document/d/1heiIgNdO7kbaU9BLOPO4wZ9maHScB87cGT5lyjeBVAM/edit#heading=h.4en9va43fgfj
Bug: 950905

I have combined these two steps as they make a lot of sense together.

1) A new bool `obey_origin_policy` has been added to ResourceRequest
2) Based on its presence:
 a) The `Sec-Origin-Policy` HTTP header is set
 b) The OriginPolicyManager is used to retrieve the policy
 c) The policy is saved on the ResourceRequest
3) The OriginPolicyThrottle has all the necessary information to
trigger the interstitial or allow the navigation.

Change-Id: I75b4da55f01c0eff461e005a92f24b28925eef62
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1706428Reviewed-by: default avatarMatt Menke <mmenke@chromium.org>
Reviewed-by: default avatarDaniel Vogelheim <vogelheim@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarAlex Moshchuk <alexmos@chromium.org>
Commit-Queue: Andy Paicu <andypaicu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#686411}
parent 0f5259c3
...@@ -314,12 +314,6 @@ void AddAdditionalRequestHeaders(net::HttpRequestHeaders* headers, ...@@ -314,12 +314,6 @@ void AddAdditionalRequestHeaders(net::HttpRequestHeaders* headers,
// Sec-Fetch-Site is covered by network::SetSecFetchSiteHeader function. // Sec-Fetch-Site is covered by network::SetSecFetchSiteHeader function.
} }
// Ask whether we should request a policy.
if (OriginPolicyThrottle::ShouldRequestOriginPolicy(url)) {
headers->SetHeader(net::HttpRequestHeaders::kSecOriginPolicy,
kDefaultOriginPolicyVersion);
}
// Next, set the HTTP Origin if needed. // Next, set the HTTP Origin if needed.
if (!NeedsHTTPOrigin(headers, method)) if (!NeedsHTTPOrigin(headers, method))
return; return;
...@@ -1217,10 +1211,6 @@ mojom::NavigationClient* NavigationRequest::GetCommitNavigationClient() { ...@@ -1217,10 +1211,6 @@ mojom::NavigationClient* NavigationRequest::GetCommitNavigationClient() {
return commit_navigation_client_.get(); return commit_navigation_client_.get();
} }
void NavigationRequest::SetOriginPolicy(const network::OriginPolicy& policy) {
response_head_->head.origin_policy = policy;
}
void NavigationRequest::OnRequestRedirected( void NavigationRequest::OnRequestRedirected(
const net::RedirectInfo& redirect_info, const net::RedirectInfo& redirect_info,
const scoped_refptr<network::ResourceResponse>& response_head) { const scoped_refptr<network::ResourceResponse>& response_head) {
...@@ -1915,7 +1905,7 @@ void NavigationRequest::OnStartChecksComplete( ...@@ -1915,7 +1905,7 @@ void NavigationRequest::OnStartChecksComplete(
loader_ = NavigationURLLoader::Create( loader_ = NavigationURLLoader::Create(
browser_context, partition, browser_context, partition,
std::make_unique<NavigationRequestInfo>( std::make_unique<NavigationRequestInfo>(
common_params_.Clone(), begin_params_.Clone(), site_for_cookies, common_params_->Clone(), begin_params_.Clone(), site_for_cookies,
net::NetworkIsolationKey(top_frame_origin, frame_origin), net::NetworkIsolationKey(top_frame_origin, frame_origin),
frame_tree_node_->IsMainFrame(), parent_is_main_frame, frame_tree_node_->IsMainFrame(), parent_is_main_frame,
IsSecureFrame(frame_tree_node_->parent()), IsSecureFrame(frame_tree_node_->parent()),
...@@ -1926,8 +1916,8 @@ void NavigationRequest::OnStartChecksComplete( ...@@ -1926,8 +1916,8 @@ void NavigationRequest::OnStartChecksComplete(
upgrade_if_insecure_, upgrade_if_insecure_,
blob_url_loader_factory_ ? blob_url_loader_factory_->Clone() blob_url_loader_factory_ ? blob_url_loader_factory_->Clone()
: nullptr, : nullptr,
devtools_navigation_token(), devtools_navigation_token(), frame_tree_node_->devtools_frame_token(),
frame_tree_node_->devtools_frame_token()), OriginPolicyThrottle::ShouldRequestOriginPolicy(common_params_->url)),
std::move(navigation_ui_data), service_worker_handle_.get(), std::move(navigation_ui_data), service_worker_handle_.get(),
appcache_handle_.get(), std::move(prefetched_signed_exchange_cache_), appcache_handle_.get(), std::move(prefetched_signed_exchange_cache_),
this, is_served_from_back_forward_cache(), std::move(interceptor)); this, is_served_from_back_forward_cache(), std::move(interceptor));
...@@ -2199,7 +2189,7 @@ void NavigationRequest::CommitNavigation() { ...@@ -2199,7 +2189,7 @@ void NavigationRequest::CommitNavigation() {
render_frame_host_->GetProcess()->GetID(), render_frame_host_->GetProcess()->GetID(),
render_frame_host_->GetRoutingID(), &service_worker_provider_info); render_frame_host_->GetRoutingID(), &service_worker_provider_info);
} }
auto common_params = common_params_.Clone(); auto common_params = common_params_->Clone();
auto commit_params = commit_params_.Clone(); auto commit_params = commit_params_.Clone();
if (subresource_loader_params_ && if (subresource_loader_params_ &&
!subresource_loader_params_->prefetched_signed_exchanges.empty()) { !subresource_loader_params_->prefetched_signed_exchanges.empty()) {
......
...@@ -323,11 +323,6 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate, ...@@ -323,11 +323,6 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate,
// for commit. Only used with PerNavigationMojoInterface enabled. // for commit. Only used with PerNavigationMojoInterface enabled.
mojom::NavigationClient* GetCommitNavigationClient(); mojom::NavigationClient* GetCommitNavigationClient();
// TODO(andypaicu): Currently the origin_policy_throttle is responsible for
// setting the origin policy. Remove this function after this is done inside
// the network service.
void SetOriginPolicy(const network::OriginPolicy& policy);
void set_transition(ui::PageTransition transition) { void set_transition(ui::PageTransition transition) {
common_params_->transition = transition; common_params_->transition = transition;
} }
......
...@@ -22,7 +22,8 @@ NavigationRequestInfo::NavigationRequestInfo( ...@@ -22,7 +22,8 @@ NavigationRequestInfo::NavigationRequestInfo(
std::unique_ptr<network::SharedURLLoaderFactoryInfo> std::unique_ptr<network::SharedURLLoaderFactoryInfo>
blob_url_loader_factory, blob_url_loader_factory,
const base::UnguessableToken& devtools_navigation_token, const base::UnguessableToken& devtools_navigation_token,
const base::UnguessableToken& devtools_frame_token) const base::UnguessableToken& devtools_frame_token,
bool obey_origin_policy)
: common_params(std::move(common_params)), : common_params(std::move(common_params)),
begin_params(std::move(begin_params)), begin_params(std::move(begin_params)),
site_for_cookies(site_for_cookies), site_for_cookies(site_for_cookies),
...@@ -37,7 +38,8 @@ NavigationRequestInfo::NavigationRequestInfo( ...@@ -37,7 +38,8 @@ NavigationRequestInfo::NavigationRequestInfo(
upgrade_if_insecure(upgrade_if_insecure), upgrade_if_insecure(upgrade_if_insecure),
blob_url_loader_factory(std::move(blob_url_loader_factory)), blob_url_loader_factory(std::move(blob_url_loader_factory)),
devtools_navigation_token(devtools_navigation_token), devtools_navigation_token(devtools_navigation_token),
devtools_frame_token(devtools_frame_token) {} devtools_frame_token(devtools_frame_token),
obey_origin_policy(obey_origin_policy) {}
NavigationRequestInfo::~NavigationRequestInfo() {} NavigationRequestInfo::~NavigationRequestInfo() {}
......
...@@ -38,7 +38,8 @@ struct CONTENT_EXPORT NavigationRequestInfo { ...@@ -38,7 +38,8 @@ struct CONTENT_EXPORT NavigationRequestInfo {
std::unique_ptr<network::SharedURLLoaderFactoryInfo> std::unique_ptr<network::SharedURLLoaderFactoryInfo>
blob_url_loader_factory, blob_url_loader_factory,
const base::UnguessableToken& devtools_navigation_token, const base::UnguessableToken& devtools_navigation_token,
const base::UnguessableToken& devtools_frame_token); const base::UnguessableToken& devtools_frame_token,
bool obey_origin_policy);
NavigationRequestInfo(const NavigationRequestInfo& other) = delete; NavigationRequestInfo(const NavigationRequestInfo& other) = delete;
~NavigationRequestInfo(); ~NavigationRequestInfo();
...@@ -78,6 +79,11 @@ struct CONTENT_EXPORT NavigationRequestInfo { ...@@ -78,6 +79,11 @@ struct CONTENT_EXPORT NavigationRequestInfo {
const base::UnguessableToken devtools_navigation_token; const base::UnguessableToken devtools_navigation_token;
const base::UnguessableToken devtools_frame_token; const base::UnguessableToken devtools_frame_token;
// If set, the network service will attempt to retrieve the appropriate origin
// policy, if necessary, and attach it to the ResourceResponseHead.
// Spec: https://wicg.github.io/origin-policy/
const bool obey_origin_policy;
}; };
} // namespace content } // namespace content
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "content/browser/frame_host/navigation_request.h" #include "content/browser/frame_host/navigation_request.h"
#include "content/browser/storage_partition_impl.h" #include "content/browser/storage_partition_impl.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/storage_partition.h" #include "content/public/browser/storage_partition.h"
#include "content/public/common/content_features.h" #include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h" #include "content/public/common/content_switches.h"
...@@ -52,16 +53,9 @@ OriginPolicyThrottle::MaybeCreateThrottleFor(NavigationHandle* handle) { ...@@ -52,16 +53,9 @@ OriginPolicyThrottle::MaybeCreateThrottleFor(NavigationHandle* handle) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(handle); DCHECK(handle);
// We use presence of the origin policy request header to determine if (!ShouldRequestOriginPolicy(handle->GetURL()))
// whether we should create the throttle.
if (!handle->GetRequestHeaders().HasHeader(
net::HttpRequestHeaders::kSecOriginPolicy))
return nullptr; return nullptr;
// TODO(vogelheim): Rewrite & hoist up this DCHECK to ensure that ..HasHeader
// and ShouldRequestOriginPolicy are always equal on entry to the method.
// This depends on https://crbug.com/881234 being fixed.
DCHECK(OriginPolicyThrottle::ShouldRequestOriginPolicy(handle->GetURL()));
return base::WrapUnique(new OriginPolicyThrottle(handle)); return base::WrapUnique(new OriginPolicyThrottle(handle));
} }
...@@ -93,78 +87,62 @@ NavigationThrottle::ThrottleCheckResult ...@@ -93,78 +87,62 @@ NavigationThrottle::ThrottleCheckResult
OriginPolicyThrottle::WillProcessResponse() { OriginPolicyThrottle::WillProcessResponse() {
DCHECK(navigation_handle()); DCHECK(navigation_handle());
// Per spec, Origin Policies are only fetched for https:-requests. So we // If no test origin policy is set, look at the actual origin policy from the
// should always have HTTP headers at this point. // response.
// However, some unit tests generate responses without headers, so we still const base::Optional<network::OriginPolicy>& origin_policy =
// need to check. GetTestOriginPolicy().has_value()
if (!navigation_handle()->GetResponseHeaders()) ? GetTestOriginPolicy()
: static_cast<NavigationHandleImpl*>(navigation_handle())
->navigation_request()
->response()
->head.origin_policy;
// If there is no origin_policy, treat this case as
// network::OriginPolicyState::kNoPolicyApplies.
if (!origin_policy.has_value()) {
return NavigationThrottle::PROCEED; return NavigationThrottle::PROCEED;
}
std::string header; switch (origin_policy->state) {
navigation_handle()->GetResponseHeaders()->GetNormalizedHeader( case network::OriginPolicyState::kCannotLoadPolicy:
net::HttpRequestHeaders::kSecOriginPolicy, &header); case network::OriginPolicyState::kInvalidRedirect:
case network::OriginPolicyState::kOther:
network::mojom::OriginPolicyManager::RetrieveOriginPolicyCallback return NavigationThrottle::ThrottleCheckResult(
origin_policy_manager_done = base::BindOnce( NavigationThrottle::CANCEL, net::ERR_BLOCKED_BY_CLIENT,
&OriginPolicyThrottle::OnOriginPolicyManagerRetrieveDone, GetContentClient()->browser()->GetOriginPolicyErrorPage(
weak_factory_.GetWeakPtr()); origin_policy->state, navigation_handle()));
SiteInstance* site_instance = navigation_handle()->GetStartingSiteInstance();
StoragePartitionImpl* storage_partition =
static_cast<StoragePartitionImpl*>(BrowserContext::GetStoragePartition(
site_instance->GetBrowserContext(), site_instance));
network::mojom::OriginPolicyManager* origin_policy_manager =
storage_partition->GetOriginPolicyManagerForBrowserProcess();
origin_policy_manager->RetrieveOriginPolicy(
GetRequestOrigin(), header, std::move(origin_policy_manager_done));
return NavigationThrottle::DEFER; case network::OriginPolicyState::kNoPolicyApplies:
case network::OriginPolicyState::kLoaded:
return NavigationThrottle::PROCEED;
}
} }
const char* OriginPolicyThrottle::GetNameForLogging() { const char* OriginPolicyThrottle::GetNameForLogging() {
return "OriginPolicyThrottle"; return "OriginPolicyThrottle";
} }
OriginPolicyThrottle::OriginPolicyThrottle(NavigationHandle* handle) // static
: NavigationThrottle(handle) {} void OriginPolicyThrottle::SetOriginPolicyForTesting(
const network::OriginPolicy& origin_policy) {
const url::Origin OriginPolicyThrottle::GetRequestOrigin() const { base::Optional<network::OriginPolicy> new_test_origin_policy = origin_policy;
return url::Origin::Create(navigation_handle()->GetURL()); GetTestOriginPolicy().swap(new_test_origin_policy);
} }
void OriginPolicyThrottle::CancelNavigation(network::OriginPolicyState state, // static
const GURL& policy_url) { void OriginPolicyThrottle::ResetOriginPolicyForTesting() {
base::Optional<std::string> error_page = GetTestOriginPolicy().reset();
GetContentClient()->browser()->GetOriginPolicyErrorPage(
state, navigation_handle());
CancelDeferredNavigation(NavigationThrottle::ThrottleCheckResult(
NavigationThrottle::CANCEL, net::ERR_BLOCKED_BY_CLIENT, error_page));
} }
void OriginPolicyThrottle::OnOriginPolicyManagerRetrieveDone( OriginPolicyThrottle::OriginPolicyThrottle(NavigationHandle* handle)
const network::OriginPolicy& origin_policy) { : NavigationThrottle(handle) {}
switch (origin_policy.state) {
case network::OriginPolicyState::kCannotLoadPolicy:
case network::OriginPolicyState::kInvalidRedirect:
CancelNavigation(origin_policy.state, origin_policy.policy_url);
return;
case network::OriginPolicyState::kNoPolicyApplies:
Resume();
return;
case network::OriginPolicyState::kLoaded: // static
DCHECK(origin_policy.contents); base::Optional<network::OriginPolicy>&
static_cast<NavigationHandleImpl*>(navigation_handle()) OriginPolicyThrottle::GetTestOriginPolicy() {
->navigation_request() static base::NoDestructor<base::Optional<network::OriginPolicy>>
->SetOriginPolicy(origin_policy); test_origin_policy;
Resume(); return *test_origin_policy;
return;
default:
NOTREACHED();
}
} }
} // namespace content } // namespace content
...@@ -15,16 +15,9 @@ ...@@ -15,16 +15,9 @@
class GURL; class GURL;
namespace url {
class Origin;
}
namespace content { namespace content {
class NavigationHandle; class NavigationHandle;
// Constant derived from the spec, https://github.com/WICG/origin-policy
static constexpr const char* kDefaultOriginPolicyVersion = "0";
// The OriginPolicyThrottle is responsible for deciding whether an origin // The OriginPolicyThrottle is responsible for deciding whether an origin
// policy should be fetched, and doing so when that is positive. // policy should be fetched, and doing so when that is positive.
// //
...@@ -59,18 +52,14 @@ class CONTENT_EXPORT OriginPolicyThrottle : public NavigationThrottle { ...@@ -59,18 +52,14 @@ class CONTENT_EXPORT OriginPolicyThrottle : public NavigationThrottle {
ThrottleCheckResult WillProcessResponse() override; ThrottleCheckResult WillProcessResponse() override;
const char* GetNameForLogging() override; const char* GetNameForLogging() override;
static void SetOriginPolicyForTesting(
const network::OriginPolicy& origin_policy);
static void ResetOriginPolicyForTesting();
private: private:
explicit OriginPolicyThrottle(NavigationHandle* handle); explicit OriginPolicyThrottle(NavigationHandle* handle);
const url::Origin GetRequestOrigin() const; static base::Optional<network::OriginPolicy>& GetTestOriginPolicy();
void CancelNavigation(network::OriginPolicyState state,
const GURL& policy_url);
void OnOriginPolicyManagerRetrieveDone(
const network::OriginPolicy& origin_policy);
base::WeakPtrFactory<OriginPolicyThrottle> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(OriginPolicyThrottle); DISALLOW_COPY_AND_ASSIGN(OriginPolicyThrottle);
}; };
......
...@@ -26,15 +26,6 @@ ...@@ -26,15 +26,6 @@
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
namespace {
const network::OriginPolicyContentsPtr kExamplePolicyContents =
std::make_unique<network::OriginPolicyContents>(
std::vector<std::string>(
{"geolocation http://example.com"}) /* features */,
std::vector<std::string>() /* content_security_policies */,
std::vector<std::string>() /* content_security_policies_report_only */);
}
namespace content { namespace content {
class OriginPolicyThrottleTest : public RenderViewHostTestHarness, class OriginPolicyThrottleTest : public RenderViewHostTestHarness,
...@@ -72,52 +63,6 @@ class OriginPolicyThrottleTest : public RenderViewHostTestHarness, ...@@ -72,52 +63,6 @@ class OriginPolicyThrottleTest : public RenderViewHostTestHarness,
base::test::ScopedFeatureList features_; base::test::ScopedFeatureList features_;
}; };
class TestOriginPolicyManager : public network::mojom::OriginPolicyManager {
public:
void RetrieveOriginPolicy(const url::Origin& origin,
const std::string& header_value,
RetrieveOriginPolicyCallback callback) override {
network::OriginPolicy result;
if (origin_exceptions_.find(origin) == origin_exceptions_.end()) {
result.state = network::OriginPolicyState::kLoaded;
result.contents = kExamplePolicyContents->ClonePtr();
result.policy_url = origin.GetURL();
} else {
result.state = network::OriginPolicyState::kNoPolicyApplies;
result.policy_url = origin.GetURL();
}
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&TestOriginPolicyManager::RunCallback,
base::Unretained(this), std::move(callback), result));
}
void RunCallback(RetrieveOriginPolicyCallback callback,
const network::OriginPolicy& result) {
std::move(callback).Run(result);
}
network::mojom::OriginPolicyManagerPtr GetPtr() {
network::mojom::OriginPolicyManagerPtr ptr;
auto request = mojo::MakeRequest(&ptr);
binding_ =
std::make_unique<mojo::Binding<network::mojom::OriginPolicyManager>>(
this, std::move(request));
return ptr;
}
void AddExceptionFor(const url::Origin& origin) override {
origin_exceptions_.insert(origin);
}
private:
std::unique_ptr<mojo::Binding<network::mojom::OriginPolicyManager>> binding_;
std::set<url::Origin> origin_exceptions_;
};
INSTANTIATE_TEST_SUITE_P(OriginPolicyThrottleTests, INSTANTIATE_TEST_SUITE_P(OriginPolicyThrottleTests,
OriginPolicyThrottleTest, OriginPolicyThrottleTest,
testing::Bool()); testing::Bool());
...@@ -150,118 +95,42 @@ TEST_P(OriginPolicyThrottleTest, MaybeCreateThrottleFor) { ...@@ -150,118 +95,42 @@ TEST_P(OriginPolicyThrottleTest, MaybeCreateThrottleFor) {
!!OriginPolicyThrottle::MaybeCreateThrottleFor(nav_handle_.get())); !!OriginPolicyThrottle::MaybeCreateThrottleFor(nav_handle_.get()));
} }
TEST_P(OriginPolicyThrottleTest, RunRequestEndToEnd) { TEST_P(OriginPolicyThrottleTest, WillProcessResponse) {
if (!enabled()) if (!enabled())
return; return;
// Start the navigation. struct {
auto navigation = NavigationSimulator::CreateBrowserInitiated( // The state of the origin policy returned in the response.
GURL("https://example.org/bla"), web_contents()); network::OriginPolicyState state;
navigation->SetAutoAdvance(false); // The expected navigation thottle action.
navigation->Start(); NavigationThrottle::ThrottleAction expected_action;
EXPECT_FALSE(navigation->IsDeferred()); } test_cases[] = {
EXPECT_EQ(NavigationThrottle::PROCEED, {network::OriginPolicyState::kLoaded,
navigation->GetLastThrottleCheckResult().action()); NavigationThrottle::ThrottleAction::PROCEED},
{network::OriginPolicyState::kNoPolicyApplies,
// Fake a response with a policy header. Check whether the navigation NavigationThrottle::ThrottleAction::PROCEED},
// is deferred. {network::OriginPolicyState::kInvalidRedirect,
const char* raw_headers = NavigationThrottle::ThrottleAction::CANCEL},
"HTTP/1.1 200 OK\nSec-Origin-Policy: policy=policy-1\n\n"; {network::OriginPolicyState::kCannotLoadPolicy,
auto headers = base::MakeRefCounted<net::HttpResponseHeaders>( NavigationThrottle::ThrottleAction::CANCEL},
net::HttpUtil::AssembleRawHeaders(raw_headers)); };
// We set a test origin policy manager as during unit tests we can't reach
// the network service to retrieve a valid origin policy manager.
TestOriginPolicyManager test_origin_policy_manager;
NavigationHandleImpl* nav_handle =
static_cast<NavigationHandleImpl*>(navigation->GetNavigationHandle());
SiteInstance* site_instance = nav_handle->GetStartingSiteInstance();
static_cast<StoragePartitionImpl*>(
BrowserContext::GetStoragePartition(site_instance->GetBrowserContext(),
site_instance))
->SetOriginPolicyManagerForBrowserProcessForTesting(
test_origin_policy_manager.GetPtr());
nav_handle->navigation_request()->set_response_headers_for_testing(headers);
navigation->ReadyToCommit();
EXPECT_TRUE(navigation->IsDeferred());
OriginPolicyThrottle* policy_throttle = static_cast<OriginPolicyThrottle*>(
nav_handle->GetDeferringThrottleForTesting());
EXPECT_TRUE(policy_throttle);
// Wait until the navigation has been allowed to proceed.
navigation->Wait();
// At the end of the navigation, the navigation handle should have a copy
// of the origin policy.
EXPECT_TRUE(nav_handle->navigation_request()
->response()
->head.origin_policy.has_value());
EXPECT_EQ(kExamplePolicyContents, nav_handle->navigation_request()
->response()
->head.origin_policy.value()
.contents);
static_cast<StoragePartitionImpl*>(
BrowserContext::GetStoragePartition(site_instance->GetBrowserContext(),
site_instance))
->ResetOriginPolicyManagerForBrowserProcessForTesting();
}
TEST_P(OriginPolicyThrottleTest, AddExceptionEndToEnd) {
if (!enabled())
return;
// Start the navigation.
auto navigation = NavigationSimulator::CreateBrowserInitiated(
GURL("https://example.org/bla"), web_contents());
navigation->SetAutoAdvance(false);
navigation->Start();
EXPECT_FALSE(navigation->IsDeferred());
EXPECT_EQ(NavigationThrottle::PROCEED,
navigation->GetLastThrottleCheckResult().action());
// We set a test origin policy manager as during unit tests we can't reach
// the network service to retrieve a valid origin policy manager.
TestOriginPolicyManager test_origin_policy_manager;
test_origin_policy_manager.AddExceptionFor(
url::Origin::Create(GURL("https://example.org/blubb")));
NavigationHandleImpl* nav_handle =
static_cast<NavigationHandleImpl*>(navigation->GetNavigationHandle());
SiteInstance* site_instance = nav_handle->GetStartingSiteInstance();
static_cast<StoragePartitionImpl*>(
BrowserContext::GetStoragePartition(site_instance->GetBrowserContext(),
site_instance))
->SetOriginPolicyManagerForBrowserProcessForTesting(
test_origin_policy_manager.GetPtr());
// Fake a response with a policy header. for (const auto& test : test_cases) {
const char* raw_headers = network::OriginPolicy result;
"HTTP/1.1 200 OK\nSec-Origin-Policy: policy=policy-1\n\n"; result.state = test.state;
auto headers = base::MakeRefCounted<net::HttpResponseHeaders>(
net::HttpUtil::AssembleRawHeaders(raw_headers));
nav_handle->navigation_request()->set_response_headers_for_testing(headers);
navigation->ReadyToCommit();
// The policy manager has to be called even though this is an exception OriginPolicyThrottle::SetOriginPolicyForTesting(result);
// because the throttle has no way of knowing that.
EXPECT_TRUE(navigation->IsDeferred());
OriginPolicyThrottle* policy_throttle = static_cast<OriginPolicyThrottle*>(
nav_handle->GetDeferringThrottleForTesting());
EXPECT_TRUE(policy_throttle);
// Wait until the navigation has been allowed to proceed. auto navigation = NavigationSimulator::CreateBrowserInitiated(
navigation->Wait(); GURL("https://example.org/bla"), web_contents());
// At the end of the navigation, the navigation handle should have no policy navigation->Start();
// as this origin should be exempted. navigation->ReadyToCommit();
EXPECT_FALSE(nav_handle->navigation_request()
->response()
->head.origin_policy.has_value());
static_cast<StoragePartitionImpl*>( EXPECT_EQ(test.expected_action,
BrowserContext::GetStoragePartition(site_instance->GetBrowserContext(), navigation->GetLastThrottleCheckResult().action());
site_instance)) OriginPolicyThrottle::ResetOriginPolicyForTesting();
->ResetOriginPolicyManagerForBrowserProcessForTesting(); }
} }
} // namespace content } // namespace content
...@@ -238,6 +238,7 @@ std::unique_ptr<network::ResourceRequest> CreateResourceRequest( ...@@ -238,6 +238,7 @@ std::unique_ptr<network::ResourceRequest> CreateResourceRequest(
new_request->previews_state = request_info->common_params->previews_state; new_request->previews_state = request_info->common_params->previews_state;
new_request->devtools_request_id = new_request->devtools_request_id =
request_info->devtools_navigation_token.ToString(); request_info->devtools_navigation_token.ToString();
new_request->obey_origin_policy = request_info->obey_origin_policy;
return new_request; return new_request;
} }
......
...@@ -96,7 +96,8 @@ class TestNavigationLoaderInterceptor : public NavigationLoaderInterceptor { ...@@ -96,7 +96,8 @@ class TestNavigationLoaderInterceptor : public NavigationLoaderInterceptor {
std::move(client), TRAFFIC_ANNOTATION_FOR_TESTS, &params, std::move(client), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
0, /* request_id */ 0, /* request_id */
resource_scheduler_client_, nullptr /* keepalive_statistics_recorder */, resource_scheduler_client_, nullptr /* keepalive_statistics_recorder */,
nullptr /* network_usage_accumulator */, nullptr /* header_client */); nullptr /* network_usage_accumulator */, nullptr /* header_client */,
nullptr /* origin_policy_manager */);
} }
bool MaybeCreateLoaderForResponse( bool MaybeCreateLoaderForResponse(
...@@ -191,7 +192,8 @@ class NavigationURLLoaderImplTest : public testing::Test { ...@@ -191,7 +192,8 @@ class NavigationURLLoaderImplTest : public testing::Test {
upgrade_if_insecure /* upgrade_if_insecure */, upgrade_if_insecure /* upgrade_if_insecure */,
nullptr /* blob_url_loader_factory */, nullptr /* blob_url_loader_factory */,
base::UnguessableToken::Create() /* devtools_navigation_token */, base::UnguessableToken::Create() /* devtools_navigation_token */,
base::UnguessableToken::Create() /* devtools_frame_token */)); base::UnguessableToken::Create() /* devtools_frame_token */,
false /* obey_origin_policy */));
std::vector<std::unique_ptr<NavigationLoaderInterceptor>> interceptors; std::vector<std::unique_ptr<NavigationLoaderInterceptor>> interceptors;
most_recent_resource_request_ = base::nullopt; most_recent_resource_request_ = base::nullopt;
interceptors.push_back(std::make_unique<TestNavigationLoaderInterceptor>( interceptors.push_back(std::make_unique<TestNavigationLoaderInterceptor>(
......
...@@ -75,10 +75,15 @@ class NavigationURLLoaderTest : public testing::Test { ...@@ -75,10 +75,15 @@ class NavigationURLLoaderTest : public testing::Test {
std::unique_ptr<NavigationRequestInfo> request_info( std::unique_ptr<NavigationRequestInfo> request_info(
new NavigationRequestInfo( new NavigationRequestInfo(
std::move(common_params), std::move(begin_params), url, std::move(common_params), std::move(begin_params), url,
net::NetworkIsolationKey(origin, origin), true, false, false, -1, net::NetworkIsolationKey(origin, origin), true /* is_main_frame */,
false, false, false, false, nullptr, false /* parent_is_main_frame */, false /* are_ancestors_secure */,
base::UnguessableToken::Create(), -1 /* frame_tree_node_id */, false /* is_for_guests_only */,
base::UnguessableToken::Create())); false /* report_raw_headers */, false /* is_prerendering */,
false /* upgrade_if_insecure */,
nullptr /* blob_url_loader_factory */,
base::UnguessableToken::Create() /* devtools_navigation_token */,
base::UnguessableToken::Create() /* devtools_frame_token */,
false /* obey_origin_policy */));
return NavigationURLLoader::Create( return NavigationURLLoader::Create(
browser_context_.get(), browser_context_.get(),
BrowserContext::GetDefaultStoragePartition(browser_context_.get()), BrowserContext::GetDefaultStoragePartition(browser_context_.get()),
......
...@@ -69,7 +69,8 @@ class ServiceWorkerRequestHandlerTest : public testing::Test { ...@@ -69,7 +69,8 @@ class ServiceWorkerRequestHandlerTest : public testing::Test {
false /* report_raw_headers */, false /* is_prerendering */, false /* report_raw_headers */, false /* is_prerendering */,
false /* upgrade_if_insecure */, nullptr /* blob_url_loader_factory */, false /* upgrade_if_insecure */, nullptr /* blob_url_loader_factory */,
base::UnguessableToken::Create() /* devtools_navigation_token */, base::UnguessableToken::Create() /* devtools_navigation_token */,
base::UnguessableToken::Create() /* devtools_frame_token */); base::UnguessableToken::Create() /* devtools_frame_token */,
false /* obey_origin_policy */);
std::unique_ptr<NavigationLoaderInterceptor> interceptor = std::unique_ptr<NavigationLoaderInterceptor> interceptor =
ServiceWorkerRequestHandler::CreateForNavigation( ServiceWorkerRequestHandler::CreateForNavigation(
gurl, navigation_handle->AsWeakPtr(), request_info); gurl, navigation_handle->AsWeakPtr(), request_info);
......
...@@ -401,6 +401,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext ...@@ -401,6 +401,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
// inside the network service. // inside the network service.
mojom::URLLoaderFactoryPtr CreateUrlLoaderFactoryForNetworkService(); mojom::URLLoaderFactoryPtr CreateUrlLoaderFactoryForNetworkService();
mojom::OriginPolicyManager* origin_policy_manager() const {
return origin_policy_manager_.get();
}
private: private:
class ContextNetworkDelegate; class ContextNetworkDelegate;
......
...@@ -10,6 +10,7 @@ const char kOriginPolicyWellKnown[] = "/.well-known/origin-policy"; ...@@ -10,6 +10,7 @@ const char kOriginPolicyWellKnown[] = "/.well-known/origin-policy";
const char kOriginPolicyDeletePolicy[] = "0"; const char kOriginPolicyDeletePolicy[] = "0";
const char kOriginPolicyReportTo[] = "report-to"; const char kOriginPolicyReportTo[] = "report-to";
const char kOriginPolicyPolicy[] = "policy"; const char kOriginPolicyPolicy[] = "policy";
const char kDefaultOriginPolicyVersion[] = "0";
// Maximum policy size (implementation-defined limit in bytes). // Maximum policy size (implementation-defined limit in bytes).
// (Limit copied from network::SimpleURLLoader::kMaxBoundedStringDownloadSize.) // (Limit copied from network::SimpleURLLoader::kMaxBoundedStringDownloadSize.)
......
...@@ -349,6 +349,7 @@ TEST_F(OriginPolicyManagerTest, CacheStatesAfterPolicyFetches) { ...@@ -349,6 +349,7 @@ TEST_F(OriginPolicyManagerTest, CacheStatesAfterPolicyFetches) {
OriginPolicyState expected_state; OriginPolicyState expected_state;
std::string expected_raw_policy; std::string expected_raw_policy;
const url::Origin& origin; const url::Origin& origin;
bool add_exception_first = false;
} kTests[] = { } kTests[] = {
// The order of these tests is important as the cache is not cleared in // The order of these tests is important as the cache is not cleared in
// between tests and some tests rely on the state left over by previous // between tests and some tests rely on the state left over by previous
...@@ -361,6 +362,10 @@ TEST_F(OriginPolicyManagerTest, CacheStatesAfterPolicyFetches) { ...@@ -361,6 +362,10 @@ TEST_F(OriginPolicyManagerTest, CacheStatesAfterPolicyFetches) {
{"invalid", OriginPolicyState::kCannotLoadPolicy, "", {"invalid", OriginPolicyState::kCannotLoadPolicy, "",
test_server_origin()}, test_server_origin()},
// The invalid policy header has not been kept in the cache, an empty
// policy still means no policy applies.
{"", OriginPolicyState::kNoPolicyApplies, "", test_server_origin()},
// A valid header results in loaded policy. // A valid header results in loaded policy.
{"policy=policy-1", OriginPolicyState::kLoaded, {"policy=policy-1", OriginPolicyState::kLoaded,
R"({ "feature-policy": ["geolocation http://example1.com"] })", R"({ "feature-policy": ["geolocation http://example1.com"] })",
...@@ -423,9 +428,58 @@ TEST_F(OriginPolicyManagerTest, CacheStatesAfterPolicyFetches) { ...@@ -423,9 +428,58 @@ TEST_F(OriginPolicyManagerTest, CacheStatesAfterPolicyFetches) {
{"", OriginPolicyState::kLoaded, {"", OriginPolicyState::kLoaded,
R"({ "feature-policy": ["geolocation http://example1.com"] })", R"({ "feature-policy": ["geolocation http://example1.com"] })",
test_server_origin()}, test_server_origin()},
// Start testing exception logic.
// Adding an exception means a kNoPolicyApplies state will be returned,
// without attempting to retrieve a policy.
{"policy=policy-1", OriginPolicyState::kNoPolicyApplies, "",
test_server_origin(), true /* add_exception_first */},
// And it will still be exempted in further calls, even if a valid policy
// header is present.
{"policy=policy-1", OriginPolicyState::kNoPolicyApplies, "",
test_server_origin()},
// And also if an invalid header is present.
{"invalid", OriginPolicyState::kNoPolicyApplies, "",
test_server_origin()},
// This only affects the specified origin, a second origin should be
// unaffected.
{"policy=policy-2", OriginPolicyState::kLoaded,
R"({ "feature-policy": ["geolocation http://example2.com"] })",
test_server_origin_2()},
// Adding an exception will work for the second origin as well.
{"invalid", OriginPolicyState::kNoPolicyApplies, "",
test_server_origin_2(), true /* add_exception_first */},
// And future calls on the second origin will now return a
// kNoPolicyApplies
// state.
{"invalid", OriginPolicyState::kNoPolicyApplies, "",
test_server_origin_2()},
// Deleting a policy will delete the exception (which will become apparent
// in subsequent calls).
{kOriginPolicyDeletePolicy, OriginPolicyState::kNoPolicyApplies, "",
test_server_origin()},
// Now attempting to load a policy will proceed as normal.
{"policy=policy-1", OriginPolicyState::kLoaded,
R"({ "feature-policy": ["geolocation http://example1.com"] })",
test_server_origin()},
// But the second origin is unaffected by the deletion and still exempted.
{"invalid", OriginPolicyState::kNoPolicyApplies, "",
test_server_origin_2()},
}; };
for (const auto& test : kTests) { for (const auto& test : kTests) {
if (test.add_exception_first)
manager()->AddExceptionFor(test.origin);
TestOriginPolicyManagerResult tester(this); TestOriginPolicyManagerResult tester(this);
tester.RetrieveOriginPolicy(test.header, &test.origin); tester.RetrieveOriginPolicy(test.header, &test.origin);
EXPECT_EQ(test.expected_state, tester.origin_policy_result()->state); EXPECT_EQ(test.expected_state, tester.origin_policy_result()->state);
......
...@@ -69,7 +69,8 @@ bool ResourceRequest::EqualsForTesting(const ResourceRequest& request) const { ...@@ -69,7 +69,8 @@ bool ResourceRequest::EqualsForTesting(const ResourceRequest& request) const {
fetch_window_id == request.fetch_window_id && fetch_window_id == request.fetch_window_id &&
devtools_request_id == request.devtools_request_id && devtools_request_id == request.devtools_request_id &&
is_signed_exchange_prefetch_cache_enabled == is_signed_exchange_prefetch_cache_enabled ==
request.is_signed_exchange_prefetch_cache_enabled; request.is_signed_exchange_prefetch_cache_enabled &&
obey_origin_policy == request.obey_origin_policy;
} }
bool ResourceRequest::SendsCookies() const { bool ResourceRequest::SendsCookies() const {
......
...@@ -90,6 +90,7 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequest { ...@@ -90,6 +90,7 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequest {
base::Optional<base::UnguessableToken> fetch_window_id; base::Optional<base::UnguessableToken> fetch_window_id;
base::Optional<std::string> devtools_request_id; base::Optional<std::string> devtools_request_id;
bool is_signed_exchange_prefetch_cache_enabled = false; bool is_signed_exchange_prefetch_cache_enabled = false;
bool obey_origin_policy = false;
}; };
} // namespace network } // namespace network
......
...@@ -211,6 +211,7 @@ bool StructTraits< ...@@ -211,6 +211,7 @@ bool StructTraits<
data.should_also_use_factory_bound_origin_for_cors(); data.should_also_use_factory_bound_origin_for_cors();
out->is_signed_exchange_prefetch_cache_enabled = out->is_signed_exchange_prefetch_cache_enabled =
data.is_signed_exchange_prefetch_cache_enabled(); data.is_signed_exchange_prefetch_cache_enabled();
out->obey_origin_policy = data.obey_origin_policy();
return true; return true;
} }
......
...@@ -221,6 +221,9 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ...@@ -221,6 +221,9 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
const network::ResourceRequest& request) { const network::ResourceRequest& request) {
return request.is_signed_exchange_prefetch_cache_enabled; return request.is_signed_exchange_prefetch_cache_enabled;
} }
static bool obey_origin_policy(const network::ResourceRequest& request) {
return request.obey_origin_policy;
}
static bool Read(network::mojom::URLRequestDataView data, static bool Read(network::mojom::URLRequestDataView data,
network::ResourceRequest* out); network::ResourceRequest* out);
......
...@@ -16,9 +16,11 @@ struct OriginPolicy; ...@@ -16,9 +16,11 @@ struct OriginPolicy;
interface OriginPolicyManager { interface OriginPolicyManager {
// Attempts to retrieve the origin policy for an origin and // Attempts to retrieve the origin policy for an origin and
// `Sec-Origin-Policy` HTTP header value. Calls back with the result. // `Sec-Origin-Policy` HTTP header value. Calls back with the result.
// The header_value needs to contain a proper policy version or be empty. An // The header_value needs to contain a proper policy version or be empty. If
// invalid header_value will result in a returned empty policy with the state // the header is not present, callers should call with an empty header_value.
// of `kCannotLoadPolicy`. // An invalid header_value will result in a returned empty policy with the
// state of `kCannotLoadPolicy` (unless a valid policy version has been
// previously cached).
// https://wicg.github.io/origin-policy/#origin-policy-header // https://wicg.github.io/origin-policy/#origin-policy-header
RetrieveOriginPolicy(url.mojom.Origin origin, string header_value) RetrieveOriginPolicy(url.mojom.Origin origin, string header_value)
=> (OriginPolicy origin_policy); => (OriginPolicy origin_policy);
......
...@@ -340,6 +340,11 @@ struct URLRequest { ...@@ -340,6 +340,11 @@ struct URLRequest {
// enabled by flags, or OriginTrial. TODO(horo): Remove this when these // enabled by flags, or OriginTrial. TODO(horo): Remove this when these
// features are enabled by default. // features are enabled by default.
bool is_signed_exchange_prefetch_cache_enabled; bool is_signed_exchange_prefetch_cache_enabled;
// If set, the network service will attempt to retrieve the appropriate origin
// policy, if necessary, and attach it to the ResourceResponseHead.
// Spec: https://wicg.github.io/origin-policy/
bool obey_origin_policy;
}; };
// URLRequestBody represents body (i.e. upload data) of a HTTP request. // URLRequestBody represents body (i.e. upload data) of a HTTP request.
......
...@@ -43,13 +43,17 @@ ...@@ -43,13 +43,17 @@
#include "services/network/empty_url_loader_client.h" #include "services/network/empty_url_loader_client.h"
#include "services/network/loader_util.h" #include "services/network/loader_util.h"
#include "services/network/network_usage_accumulator.h" #include "services/network/network_usage_accumulator.h"
#include "services/network/origin_policy/origin_policy_constants.h"
#include "services/network/origin_policy/origin_policy_manager.h"
#include "services/network/public/cpp/constants.h" #include "services/network/public/cpp/constants.h"
#include "services/network/public/cpp/features.h" #include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/header_util.h" #include "services/network/public/cpp/header_util.h"
#include "services/network/public/cpp/net_adapters.h" #include "services/network/public/cpp/net_adapters.h"
#include "services/network/public/cpp/network_switches.h" #include "services/network/public/cpp/network_switches.h"
#include "services/network/public/cpp/origin_policy.h"
#include "services/network/public/cpp/resource_request.h" #include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/resource_response.h" #include "services/network/public/cpp/resource_response.h"
#include "services/network/public/mojom/origin_policy_manager.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h" #include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/resource_scheduler/resource_scheduler_client.h" #include "services/network/resource_scheduler/resource_scheduler_client.h"
#include "services/network/sec_header_helpers.h" #include "services/network/sec_header_helpers.h"
...@@ -340,7 +344,8 @@ URLLoader::URLLoader( ...@@ -340,7 +344,8 @@ URLLoader::URLLoader(
scoped_refptr<ResourceSchedulerClient> resource_scheduler_client, scoped_refptr<ResourceSchedulerClient> resource_scheduler_client,
base::WeakPtr<KeepaliveStatisticsRecorder> keepalive_statistics_recorder, base::WeakPtr<KeepaliveStatisticsRecorder> keepalive_statistics_recorder,
base::WeakPtr<NetworkUsageAccumulator> network_usage_accumulator, base::WeakPtr<NetworkUsageAccumulator> network_usage_accumulator,
mojom::TrustedURLLoaderHeaderClient* url_loader_header_client) mojom::TrustedURLLoaderHeaderClient* url_loader_header_client,
mojom::OriginPolicyManager* origin_policy_manager)
: url_request_context_(url_request_context), : url_request_context_(url_request_context),
network_service_client_(network_service_client), network_service_client_(network_service_client),
network_context_client_(network_context_client), network_context_client_(network_context_client),
...@@ -377,7 +382,8 @@ URLLoader::URLLoader( ...@@ -377,7 +382,8 @@ URLLoader::URLLoader(
request.custom_proxy_use_alternate_proxy_list), request.custom_proxy_use_alternate_proxy_list),
fetch_window_id_(request.fetch_window_id), fetch_window_id_(request.fetch_window_id),
update_network_isolation_key_on_redirect_( update_network_isolation_key_on_redirect_(
request.update_network_isolation_key_on_redirect) { request.update_network_isolation_key_on_redirect),
origin_policy_manager_(nullptr) {
DCHECK(delete_callback_); DCHECK(delete_callback_);
DCHECK(factory_params_); DCHECK(factory_params_);
if (url_loader_header_client && if (url_loader_header_client &&
...@@ -423,6 +429,12 @@ URLLoader::URLLoader( ...@@ -423,6 +429,12 @@ URLLoader::URLLoader(
// they should be ignored by CORS checks. // they should be ignored by CORS checks.
net::HttpRequestHeaders merged_headers = request.headers; net::HttpRequestHeaders merged_headers = request.headers;
merged_headers.MergeFrom(request.cors_exempt_headers); merged_headers.MergeFrom(request.cors_exempt_headers);
if (request.obey_origin_policy) {
DCHECK(origin_policy_manager);
origin_policy_manager_ = origin_policy_manager;
merged_headers.SetHeader(net::HttpRequestHeaders::kSecOriginPolicy,
kDefaultOriginPolicyVersion);
}
// This should be ensured by the CorsURLLoaderFactory(), which is called // This should be ensured by the CorsURLLoaderFactory(), which is called
// before URLLoaders are created. // before URLLoaders are created.
DCHECK(AreRequestHeadersSafe(merged_headers)); DCHECK(AreRequestHeadersSafe(merged_headers));
...@@ -997,17 +1009,31 @@ void URLLoader::OnResponseStarted(net::URLRequest* url_request, int net_error) { ...@@ -997,17 +1009,31 @@ void URLLoader::OnResponseStarted(net::URLRequest* url_request, int net_error) {
response_->head.mime_type.assign("text/plain"); response_->head.mime_type.assign("text/plain");
} }
} }
if (!is_more_mime_sniffing_needed_ && !is_more_corb_sniffing_needed_) {
// Treat feed types as text/plain. // If necessary, retrieve the associated origin policy, before sending the
if (response_->head.mime_type == "application/rss+xml" || // response to the client.
response_->head.mime_type == "application/atom+xml") { if (origin_policy_manager_ && url_request_->response_headers()) {
response_->head.mime_type.assign("text/plain"); std::string sec_origin_policy_header;
} url_request_->response_headers()->GetNormalizedHeader(
SendResponseToClient(); net::HttpRequestHeaders::kSecOriginPolicy, &sec_origin_policy_header);
OriginPolicyManager::RetrieveOriginPolicyCallback
origin_policy_manager_done =
base::BindOnce(&URLLoader::OnOriginPolicyManagerRetrieveDone,
weak_ptr_factory_.GetWeakPtr());
// Passing an empty string if no header is present is intentional as the
// origin policy manager needs to also handle an empty header.
origin_policy_manager_->RetrieveOriginPolicy(
url::Origin::Create(url_request_->url()), sec_origin_policy_header,
std::move(origin_policy_manager_done));
// The callback will continue by calling
// `StartReading()` after retrieving the origin
// policy.
return;
} }
// Start reading... StartReading();
ReadMore();
} }
void URLLoader::ReadMore() { void URLLoader::ReadMore() {
...@@ -1647,4 +1673,25 @@ void URLLoader::ReportFlaggedResponseCookies() { ...@@ -1647,4 +1673,25 @@ void URLLoader::ReportFlaggedResponseCookies() {
} }
} }
void URLLoader::StartReading() {
if (!is_more_mime_sniffing_needed_ && !is_more_corb_sniffing_needed_) {
// Treat feed types as text/plain.
if (response_->head.mime_type == "application/rss+xml" ||
response_->head.mime_type == "application/atom+xml") {
response_->head.mime_type.assign("text/plain");
}
SendResponseToClient();
}
// Start reading...
ReadMore();
}
void URLLoader::OnOriginPolicyManagerRetrieveDone(
const OriginPolicy& origin_policy) {
response_->head.origin_policy = origin_policy;
StartReading();
}
} // namespace network } // namespace network
...@@ -41,6 +41,10 @@ class URLRequestContext; ...@@ -41,6 +41,10 @@ class URLRequestContext;
namespace network { namespace network {
namespace mojom {
class OriginPolicyManager;
}
constexpr size_t kMaxFileUploadRequestsPerBatch = 64; constexpr size_t kMaxFileUploadRequestsPerBatch = 64;
class NetToMojoPendingBuffer; class NetToMojoPendingBuffer;
...@@ -48,6 +52,7 @@ class NetworkUsageAccumulator; ...@@ -48,6 +52,7 @@ class NetworkUsageAccumulator;
class KeepaliveStatisticsRecorder; class KeepaliveStatisticsRecorder;
struct ResourceResponse; struct ResourceResponse;
class ScopedThrottlingToken; class ScopedThrottlingToken;
struct OriginPolicy;
class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
: public mojom::URLLoader, : public mojom::URLLoader,
...@@ -59,6 +64,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader ...@@ -59,6 +64,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
// |delete_callback| tells the URLLoader's owner to destroy the URLLoader. // |delete_callback| tells the URLLoader's owner to destroy the URLLoader.
// The URLLoader must be destroyed before the |url_request_context|. // The URLLoader must be destroyed before the |url_request_context|.
// The |origin_policy_manager| must always be provided for requests that
// have the |obey_origin_policy| flag set.
URLLoader( URLLoader(
net::URLRequestContext* url_request_context, net::URLRequestContext* url_request_context,
mojom::NetworkServiceClient* network_service_client, mojom::NetworkServiceClient* network_service_client,
...@@ -74,7 +81,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader ...@@ -74,7 +81,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
scoped_refptr<ResourceSchedulerClient> resource_scheduler_client, scoped_refptr<ResourceSchedulerClient> resource_scheduler_client,
base::WeakPtr<KeepaliveStatisticsRecorder> keepalive_statistics_recorder, base::WeakPtr<KeepaliveStatisticsRecorder> keepalive_statistics_recorder,
base::WeakPtr<NetworkUsageAccumulator> network_usage_accumulator, base::WeakPtr<NetworkUsageAccumulator> network_usage_accumulator,
mojom::TrustedURLLoaderHeaderClient* url_loader_header_client); mojom::TrustedURLLoaderHeaderClient* url_loader_header_client,
mojom::OriginPolicyManager* origin_policy_manager);
~URLLoader() override; ~URLLoader() override;
// mojom::URLLoader implementation: // mojom::URLLoader implementation:
...@@ -233,6 +241,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader ...@@ -233,6 +241,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
BlockResponseForCorbResult BlockResponseForCorb(); BlockResponseForCorbResult BlockResponseForCorb();
void ReportFlaggedResponseCookies(); void ReportFlaggedResponseCookies();
void StartReading();
void OnOriginPolicyManagerRetrieveDone(const OriginPolicy& origin_policy);
net::URLRequestContext* url_request_context_; net::URLRequestContext* url_request_context_;
mojom::NetworkServiceClient* network_service_client_; mojom::NetworkServiceClient* network_service_client_;
...@@ -357,6 +367,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader ...@@ -357,6 +367,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
mojom::UpdateNetworkIsolationKeyOnRedirect mojom::UpdateNetworkIsolationKeyOnRedirect
update_network_isolation_key_on_redirect_; update_network_isolation_key_on_redirect_;
// Will only be set for requests that have |obey_origin_policy| set.
mojom::OriginPolicyManager* origin_policy_manager_;
base::WeakPtrFactory<URLLoader> weak_ptr_factory_{this}; base::WeakPtrFactory<URLLoader> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(URLLoader); DISALLOW_COPY_AND_ASSIGN(URLLoader);
......
...@@ -156,7 +156,8 @@ void URLLoaderFactory::CreateLoaderAndStart( ...@@ -156,7 +156,8 @@ void URLLoaderFactory::CreateLoaderAndStart(
static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation), static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation),
params_.get(), request_id, resource_scheduler_client_, params_.get(), request_id, resource_scheduler_client_,
std::move(keepalive_statistics_recorder), std::move(keepalive_statistics_recorder),
std::move(network_usage_accumulator), header_client_.get()); std::move(network_usage_accumulator), header_client_.get(),
context_->origin_policy_manager());
cors_url_loader_factory_->OnLoaderCreated(std::move(loader)); cors_url_loader_factory_->OnLoaderCreated(std::move(loader));
} }
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment