Commit afe93f45 authored by Daniel Vogelheim's avatar Daniel Vogelheim Committed by Commit Bot

Origin Policy: Implement throttle and "plumbing" to the renderer.

This implements a throttle that will advertise origin policy
support to the server, and will request an policy if necessary.

(This CL doesn't do anything with the manifest yet. That is coming in
 subsequent CLs.)

Gated on --enable-features=OriginManifest.

Bug: 751996
Change-Id: I3ebfa834c29f3eb17568917d1eff83a9261529ac
Reviewed-on: https://chromium-review.googlesource.com/1088918
Commit-Queue: Daniel Vogelheim <vogelheim@chromium.org>
Reviewed-by: default avatarAlex Moshchuk <alexmos@chromium.org>
Reviewed-by: default avatarMike West <mkwst@chromium.org>
Reviewed-by: default avatarNick Harper <nharper@chromium.org>
Cr-Commit-Position: refs/heads/master@{#569582}
parent 44e1ecc1
...@@ -832,6 +832,8 @@ jumbo_source_set("browser") { ...@@ -832,6 +832,8 @@ jumbo_source_set("browser") {
"frame_host/navigator_delegate.h", "frame_host/navigator_delegate.h",
"frame_host/navigator_impl.cc", "frame_host/navigator_impl.cc",
"frame_host/navigator_impl.h", "frame_host/navigator_impl.h",
"frame_host/origin_policy_throttle.cc",
"frame_host/origin_policy_throttle.h",
"frame_host/popup_menu_helper_mac.h", "frame_host/popup_menu_helper_mac.h",
"frame_host/popup_menu_helper_mac.mm", "frame_host/popup_menu_helper_mac.mm",
"frame_host/render_frame_host_delegate.cc", "frame_host/render_frame_host_delegate.cc",
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "content/browser/frame_host/navigation_entry_impl.h" #include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/frame_host/navigator.h" #include "content/browser/frame_host/navigator.h"
#include "content/browser/frame_host/navigator_delegate.h" #include "content/browser/frame_host/navigator_delegate.h"
#include "content/browser/frame_host/origin_policy_throttle.h"
#include "content/browser/frame_host/webui_navigation_throttle.h" #include "content/browser/frame_host/webui_navigation_throttle.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h" #include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/service_worker/service_worker_context_wrapper.h"
...@@ -1309,6 +1310,9 @@ void NavigationHandleImpl::RegisterNavigationThrottles() { ...@@ -1309,6 +1310,9 @@ void NavigationHandleImpl::RegisterNavigationThrottles() {
AddThrottle( AddThrottle(
MixedContentNavigationThrottle::CreateThrottleForNavigation(this)); MixedContentNavigationThrottle::CreateThrottleForNavigation(this));
// Handle Origin Policy (if enabled)
AddThrottle(OriginPolicyThrottle::MaybeCreateThrottleFor(this));
for (auto& throttle : for (auto& throttle :
RenderFrameDevToolsAgentHost::CreateNavigationThrottles(this)) { RenderFrameDevToolsAgentHost::CreateNavigationThrottles(this)) {
AddThrottle(std::move(throttle)); AddThrottle(std::move(throttle));
......
...@@ -160,6 +160,11 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle { ...@@ -160,6 +160,11 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
bool IsDownload() override; bool IsDownload() override;
bool IsFormSubmission() override; bool IsFormSubmission() override;
const std::string& origin_policy() const { return origin_policy_; }
void set_origin_policy(const std::string& origin_policy) {
origin_policy_ = origin_policy;
}
// Resume and CancelDeferredNavigation must only be called by the // Resume and CancelDeferredNavigation must only be called by the
// NavigationThrottle that is currently deferring the navigation. // NavigationThrottle that is currently deferring the navigation.
// |resuming_throttle| and |cancelling_throttle| are the throttles calling // |resuming_throttle| and |cancelling_throttle| are the throttles calling
...@@ -368,6 +373,10 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle { ...@@ -368,6 +373,10 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
// url we're navigating to. // url we're navigating to.
void SetExpectedProcess(RenderProcessHost* expected_process); void SetExpectedProcess(RenderProcessHost* expected_process);
NavigationThrottle* GetDeferringThrottleForTesting() const {
return GetDeferringThrottle();
}
private: private:
friend class NavigationHandleImplTest; friend class NavigationHandleImplTest;
...@@ -557,6 +566,9 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle { ...@@ -557,6 +566,9 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
// in it. // in it.
int expected_render_process_host_id_; int expected_render_process_host_id_;
// The origin policy that applies to this navigation. Empty if none applies.
std::string origin_policy_;
// Whether the navigation is in the middle of a transfer. Set to false when // Whether the navigation is in the middle of a transfer. Set to false when
// the DidStartProvisionalLoad is received from the new renderer. // the DidStartProvisionalLoad is received from the new renderer.
bool is_transferring_; bool is_transferring_;
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "content/browser/frame_host/navigation_request_info.h" #include "content/browser/frame_host/navigation_request_info.h"
#include "content/browser/frame_host/navigator.h" #include "content/browser/frame_host/navigator.h"
#include "content/browser/frame_host/navigator_impl.h" #include "content/browser/frame_host/navigator_impl.h"
#include "content/browser/frame_host/origin_policy_throttle.h"
#include "content/browser/frame_host/render_frame_host_impl.h" #include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/loader/navigation_url_loader.h" #include "content/browser/loader/navigation_url_loader.h"
#include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/renderer_host/render_process_host_impl.h"
...@@ -214,6 +215,14 @@ void AddAdditionalRequestHeaders( ...@@ -214,6 +215,14 @@ void AddAdditionalRequestHeaders(
headers->SetHeaderIfMissing("Sec-Metadata", value); headers->SetHeaderIfMissing("Sec-Metadata", value);
} }
// Ask whether we should request a policy.
std::string origin_policy_request;
if (OriginPolicyThrottle::ShouldRequestOriginPolicy(url,
&origin_policy_request)) {
headers->SetHeader(net::HttpRequestHeaders::kSecOriginPolicy,
origin_policy_request);
}
// Next, set the HTTP Origin if needed. // Next, set the HTTP Origin if needed.
if (!NeedsHTTPOrigin(headers, method)) if (!NeedsHTTPOrigin(headers, method))
return; return;
...@@ -1560,6 +1569,11 @@ void NavigationRequest::CommitNavigation() { ...@@ -1560,6 +1569,11 @@ void NavigationRequest::CommitNavigation() {
navigation_handle_->IsSameDocument()); navigation_handle_->IsSameDocument());
DCHECK(!common_params_.url.SchemeIs(url::kJavaScriptScheme)); DCHECK(!common_params_.url.SchemeIs(url::kJavaScriptScheme));
// Send the applicable origin policy (if any) along with the request.
// (The policy is fetched by a throttle and is thus available only now.)
DCHECK(common_params_.origin_policy.empty());
common_params_.origin_policy = navigation_handle_->origin_policy();
// Retrieve the RenderFrameHost that needs to commit the navigation. // Retrieve the RenderFrameHost that needs to commit the navigation.
RenderFrameHostImpl* render_frame_host = RenderFrameHostImpl* render_frame_host =
navigation_handle_->GetRenderFrameHost(); navigation_handle_->GetRenderFrameHost();
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/frame_host/origin_policy_throttle.h"
#include "base/feature_list.h"
#include "base/no_destructor.h"
#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/common/content_features.h"
#include "net/http/http_request_headers.h"
#include "services/network/network_context.h"
#include "services/network/network_service.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "url/origin.h"
namespace {
// Constants derived from the spec, https://github.com/WICG/origin-policy
static const char* kDefaultPolicy = "1";
static const char* kDeletePolicy = "0";
static const char* kWellKnown = "/.well-known/origin-policy/";
// Maximum policy size (implementation-defined limit in bytes).
// (Limit copied from network::SimpleURLLoader::kMaxBoundedStringDownloadSize.)
static const size_t kMaxPolicySize = 1024 * 1024;
} // namespace
namespace content {
// static
bool OriginPolicyThrottle::ShouldRequestOriginPolicy(
const GURL& url,
std::string* request_version) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (!base::FeatureList::IsEnabled(features::kOriginManifest))
return false;
if (!url.SchemeIs(url::kHttpsScheme))
return false;
if (request_version) {
const KnownVersionMap& versions = GetKnownVersions();
const auto iter = versions.find(url::Origin::Create(url));
*request_version =
iter == versions.end() ? std::string(kDefaultPolicy) : iter->second;
}
return true;
}
// static
std::unique_ptr<NavigationThrottle>
OriginPolicyThrottle::MaybeCreateThrottleFor(NavigationHandle* handle) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK(handle);
// We use presence of the origin policy request header to determine
// whether we should create the throttle.
if (!handle->GetRequestHeaders().HasHeader(
net::HttpRequestHeaders::kSecOriginPolicy))
return nullptr;
DCHECK(base::FeatureList::IsEnabled(features::kOriginManifest));
return base::WrapUnique(new OriginPolicyThrottle(handle));
}
OriginPolicyThrottle::~OriginPolicyThrottle() {}
NavigationThrottle::ThrottleCheckResult
OriginPolicyThrottle::WillStartRequest() {
// TODO(vogelheim): It might be faster in the common case to optimistically
// fetch the policy indicated in the request already here. This would
// be faster if the last known version is the current version, but
// slower (and wasteful of bandwidth) if the server sends us a new
// version. It's unclear how much the upside is, though.
return NavigationThrottle::PROCEED;
}
NavigationThrottle::ThrottleCheckResult
OriginPolicyThrottle::WillProcessResponse() {
DCHECK(navigation_handle());
// Per spec, Origin Policies are only fetched for https:-requests. So we
// should always have HTTP headers at this point.
// However, some unit tests generate responses without headers, so we still
// need to check.
if (!navigation_handle()->GetResponseHeaders())
return NavigationThrottle::PROCEED;
// This determines whether and which policy version applies and fetches it.
//
// Inputs are the kSecOriginPolicy HTTP header, and the version
// we've last seen from this particular origin.
//
// - header with kDeletePolicy received: No policy applies, and delete the
// last-known policy for this origin.
// - header received: Use header version and update last-known policy.
// - no header received, last-known version exists: Use last-known version
// - no header, no last-known version: No policy applies.
std::string response_version;
bool header_found =
navigation_handle()->GetResponseHeaders()->GetNormalizedHeader(
net::HttpRequestHeaders::kSecOriginPolicy, &response_version);
url::Origin origin = GetRequestOrigin();
DCHECK(!origin.Serialize().empty());
DCHECK(!origin.unique());
KnownVersionMap& versions = GetKnownVersions();
KnownVersionMap::iterator iter = versions.find(origin);
// Process policy deletion first!
if (header_found && response_version == kDeletePolicy) {
if (iter != versions.end())
versions.erase(iter);
return NavigationThrottle::PROCEED;
}
// No policy applies to this request?
if (!header_found && iter == versions.end()) {
return NavigationThrottle::PROCEED;
}
if (!header_found)
response_version = iter->second;
else if (iter == versions.end())
versions.insert(std::make_pair(origin, response_version));
else
iter->second = response_version;
GURL policy = GURL(origin.Serialize() + kWellKnown + response_version);
FetchCallback done =
base::BindOnce(&OriginPolicyThrottle::OnTheGloriousPolicyHasArrived,
base::Unretained(this));
FetchPolicy(policy, std::move(done));
return NavigationThrottle::DEFER;
}
const char* OriginPolicyThrottle::GetNameForLogging() {
return "OriginPolicyThrottle";
}
// static
OriginPolicyThrottle::KnownVersionMap&
OriginPolicyThrottle::GetKnownVersionsForTesting() {
return GetKnownVersions();
}
OriginPolicyThrottle::OriginPolicyThrottle(NavigationHandle* handle)
: NavigationThrottle(handle) {}
OriginPolicyThrottle::KnownVersionMap&
OriginPolicyThrottle::GetKnownVersions() {
static base::NoDestructor<KnownVersionMap> map_instance;
return *map_instance;
}
const url::Origin OriginPolicyThrottle::GetRequestOrigin() {
return url::Origin::Create(navigation_handle()->GetURL());
}
void OriginPolicyThrottle::FetchPolicy(const GURL& url, FetchCallback done) {
// Obtain a network context from the network service.
network::mojom::NetworkContextParamsPtr context_params =
network::mojom::NetworkContextParams::New();
content::GetNetworkService()->CreateNetworkContext(
mojo::MakeRequest(&network_context_ptr_), std::move(context_params));
// Create URLLoaderFactory
network::mojom::URLLoaderFactoryParamsPtr url_loader_factory_params =
network::mojom::URLLoaderFactoryParams::New();
url_loader_factory_params->process_id = network::mojom::kBrowserProcessId;
url_loader_factory_params->is_corb_enabled = false;
network_context_ptr_->CreateURLLoaderFactory(
mojo::MakeRequest(&url_loader_factory_),
std::move(url_loader_factory_params));
// Create the traffic annotation
net::NetworkTrafficAnnotationTag traffic_annotation =
net::DefineNetworkTrafficAnnotation("origin_policy_loader", R"(
semantics {
sender: "Origin Policy URL Loader Throttle"
description:
"Fetches the Origin Policy with a given version from an origin."
trigger:
"In case the Origin Policy with a given version does not "
"exist in the cache, it is fetched from the origin at a "
"well-known location."
data:
"None, the URL itself contains the origin and Origin Policy "
"version."
destination: OTHER
}
policy {
cookies_allowed: NO
setting: "This feature cannot be disabled by settings. Server "
"opt-in or out of this mechanism."
policy_exception_justification:
"Not implemented, considered not useful."})");
// Create the SimpleURLLoader for the policy.
std::unique_ptr<network::ResourceRequest> policy_request =
std::make_unique<network::ResourceRequest>();
policy_request->url = url;
policy_request->fetch_redirect_mode =
network::mojom::FetchRedirectMode::kError;
url_loader_ = network::SimpleURLLoader::Create(std::move(policy_request),
traffic_annotation);
url_loader_->SetAllowHttpErrorResults(false);
// Start the download, and pass the callback for when we're finished.
url_loader_->DownloadToString(url_loader_factory_.get(), std::move(done),
kMaxPolicySize);
}
void OriginPolicyThrottle::InjectPolicyForTesting(
const std::string& policy_content) {
OnTheGloriousPolicyHasArrived(std::make_unique<std::string>(policy_content));
}
void OriginPolicyThrottle::OnTheGloriousPolicyHasArrived(
std::unique_ptr<std::string> policy_content) {
// Release resources associated with the loading.
url_loader_.reset();
url_loader_factory_.reset();
network_context_ptr_.reset();
// Fail hard if the policy could not be loaded.
if (!policy_content) {
CancelDeferredNavigation(NavigationThrottle::CANCEL_AND_IGNORE);
return;
}
// TODO(vogelheim): Determine whether we need to parse or sanity check
// the policy content at this point.
static_cast<NavigationHandleImpl*>(navigation_handle())
->set_origin_policy(*policy_content);
Resume();
}
} // namespace content
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_FRAME_HOST_ORIGIN_POLICY_THROTTLE_H_
#define CONTENT_BROWSER_FRAME_HOST_ORIGIN_POLICY_THROTTLE_H_
#include <map>
#include <string>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "content/public/browser/navigation_throttle.h"
#include "services/network/public/mojom/network_service.mojom.h"
class GURL;
namespace url {
class Origin;
}
namespace network {
class SimpleURLLoader;
} // namespace network
namespace content {
class NavigationHandle;
// The OriginPolicyThrottle is responsible for deciding whether an origin
// policy should be fetched, and doing so when that is positive.
//
// The intended use is that the navigation request will
// - call OriginPolicyThrottle::ShouldRequestOriginPolicy to determine whether
// a policy should be requested and which version, and should add the
// appropriate SecOriginPolicy: header.
// - call OriginPolicyThrottle::MaybeCreateThrottleFor a given navigation.
// This will use presence of the header to decide whether to create a
// throttle or not.
class CONTENT_EXPORT OriginPolicyThrottle : public NavigationThrottle {
public:
// Determine whether to request a policy (or advertise origin policy
// support) and which version.
// Returns whether the policy header should be sent. It it returns true,
// |version| will contain the policy version to use.
static bool ShouldRequestOriginPolicy(const GURL& url, std::string* version);
// Create a throttle (if the request contains the appropriate header.
// The throttle will handle fetching of the policy and updating the
// navigation request with the result.
static std::unique_ptr<NavigationThrottle> MaybeCreateThrottleFor(
NavigationHandle* handle);
~OriginPolicyThrottle() override;
ThrottleCheckResult WillStartRequest() override;
ThrottleCheckResult WillProcessResponse() override;
const char* GetNameForLogging() override;
using KnownVersionMap = std::map<url::Origin, std::string>;
static KnownVersionMap& GetKnownVersionsForTesting();
void InjectPolicyForTesting(const std::string& policy_content);
private:
using FetchCallback = base::OnceCallback<void(std::unique_ptr<std::string>)>;
explicit OriginPolicyThrottle(NavigationHandle* handle);
static KnownVersionMap& GetKnownVersions();
const url::Origin GetRequestOrigin();
void FetchPolicy(const GURL& url, FetchCallback done);
void OnTheGloriousPolicyHasArrived(
std::unique_ptr<std::string> policy_content);
// We may need the SimpleURLLoader to download the policy.
// The network context and url loader must be kept alive while the load is
// ongoing.
network::mojom::NetworkContextPtr network_context_ptr_;
network::mojom::URLLoaderFactoryPtr url_loader_factory_;
std::unique_ptr<network::SimpleURLLoader> url_loader_;
DISALLOW_COPY_AND_ASSIGN(OriginPolicyThrottle);
};
} // namespace content
#endif // CONTENT_BROWSER_FRAME_HOST_ORIGIN_POLICY_THROTTLE_H_
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/frame_host/origin_policy_throttle.h"
#include "base/feature_list.h"
#include "base/macros.h"
#include "base/test/scoped_feature_list.h"
#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/common/content_features.h"
#include "content/public/test/test_renderer_host.h"
#include "net/http/http_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
class OriginPolicyThrottleTest : public RenderViewHostTestHarness,
public testing::WithParamInterface<bool> {
public:
void SetUp() override {
// Some tests below should be run with the feature en- and disabled, since
// they test the feature functionality when enabled and feature
// non-funcionality (that is, that the feature is inert) when disabled.
// Hence, we run this test in both variants.
features_.InitWithFeatureState(features::kOriginManifest, GetParam());
RenderViewHostTestHarness::SetUp();
OriginPolicyThrottle::GetKnownVersionsForTesting().clear();
}
void TearDown() override {
OriginPolicyThrottle::GetKnownVersionsForTesting().clear();
nav_handle_.reset();
RenderViewHostTestHarness::TearDown();
}
bool enabled() {
return base::FeatureList::IsEnabled(features::kOriginManifest);
}
void CreateHandleFor(const GURL& url) {
net::HttpRequestHeaders headers;
if (OriginPolicyThrottle::ShouldRequestOriginPolicy(url, nullptr))
headers.SetHeader(net::HttpRequestHeaders::kSecOriginPolicy, "1");
// Except for url and headers (which are determined by the test case)
// all parameters below are cargo-culted from
// NavigationHandleImplTest::CreateNavigationHandle.
nav_handle_ = NavigationHandleImpl::Create(
url, // url, as requested by caller
std::vector<GURL>(), // redirect chain
static_cast<WebContentsImpl*>(web_contents())
->GetFrameTree()
->root(), // render_tree_node
true, // is_renderer_initialized
false, // is_same_document
base::TimeTicks::Now(), // navigation_start
0, // pending_nav_entry_id
false, // started_from_context_menu
CSPDisposition::CHECK, // should_check_main_world_csp
false, // is_form_submission
nullptr, // navigation_ui_data
"GET", // HTTP method
headers); // headers, as created above
}
protected:
std::unique_ptr<NavigationHandleImpl> nav_handle_;
base::test::ScopedFeatureList features_;
};
INSTANTIATE_TEST_CASE_P(OriginPolicyThrottleTests,
OriginPolicyThrottleTest,
testing::Bool());
TEST_P(OriginPolicyThrottleTest, ShouldRequestOriginPolicy) {
struct {
const char* url;
bool expect;
} test_cases[] = {
{"https://example.org/bla", true},
{"http://example.org/bla", false},
{"file:///etc/passwd", false},
};
for (const auto& test_case : test_cases) {
SCOPED_TRACE(testing::Message() << "URL: " << test_case.url);
EXPECT_EQ(enabled() && test_case.expect,
OriginPolicyThrottle::ShouldRequestOriginPolicy(
GURL(test_case.url), nullptr));
}
}
TEST_P(OriginPolicyThrottleTest, ShouldRequestLastKnownVersion) {
if (!enabled())
return;
GURL url("https://example.org/bla");
EXPECT_TRUE(OriginPolicyThrottle::ShouldRequestOriginPolicy(url, nullptr));
std::string version;
OriginPolicyThrottle::ShouldRequestOriginPolicy(url, &version);
EXPECT_EQ(version, "1");
OriginPolicyThrottle::GetKnownVersionsForTesting()[url::Origin::Create(url)] =
"abcd";
OriginPolicyThrottle::ShouldRequestOriginPolicy(url, &version);
EXPECT_EQ(version, "abcd");
}
TEST_P(OriginPolicyThrottleTest, MaybeCreateThrottleFor) {
CreateHandleFor(GURL("https://example.org/bla"));
EXPECT_EQ(enabled(),
!!OriginPolicyThrottle::MaybeCreateThrottleFor(nav_handle_.get()));
CreateHandleFor(GURL("http://insecure.org/bla"));
EXPECT_FALSE(
!!OriginPolicyThrottle::MaybeCreateThrottleFor(nav_handle_.get()));
}
TEST_P(OriginPolicyThrottleTest, RunRequestEndToEnd) {
if (!enabled())
return;
// Create a handle and start the request.
CreateHandleFor(GURL("https://example.org/bla"));
EXPECT_EQ(NavigationThrottle::PROCEED,
nav_handle_->CallWillStartRequestForTesting().action());
// Fake a response with a policy header. Check whether the navigation
// is deferred.
const char* headers = "HTTP/1.1 200 OK\nSec-Origin-Policy: policy-1\n\n";
EXPECT_EQ(NavigationThrottle::DEFER,
nav_handle_
->CallWillProcessResponseForTesting(
main_rfh(),
net::HttpUtil::AssembleRawHeaders(headers, strlen(headers)))
.action());
EXPECT_EQ(NavigationHandleImpl::DEFERRING_RESPONSE,
nav_handle_->state_for_testing());
// For the purpose of this unit test we don't care about policy content,
// only that it's non-empty. We check whether the throttle will pass it on.
const char* policy = "{}";
static_cast<OriginPolicyThrottle*>(
nav_handle_->GetDeferringThrottleForTesting())
->InjectPolicyForTesting(policy);
// At the end of the navigation, the navigation handle should have a copy
// of the origin policy.
EXPECT_EQ(policy, nav_handle_->origin_policy());
}
} // namespace content
...@@ -480,6 +480,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::CommonNavigationParams) ...@@ -480,6 +480,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::CommonNavigationParams)
IPC_STRUCT_TRAITS_MEMBER(started_from_context_menu) IPC_STRUCT_TRAITS_MEMBER(started_from_context_menu)
IPC_STRUCT_TRAITS_MEMBER(initiator_csp) IPC_STRUCT_TRAITS_MEMBER(initiator_csp)
IPC_STRUCT_TRAITS_MEMBER(initiator_self_source) IPC_STRUCT_TRAITS_MEMBER(initiator_self_source)
IPC_STRUCT_TRAITS_MEMBER(origin_policy)
IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(content::NavigationTiming) IPC_STRUCT_TRAITS_BEGIN(content::NavigationTiming)
......
...@@ -156,6 +156,10 @@ struct CONTENT_EXPORT CommonNavigationParams { ...@@ -156,6 +156,10 @@ struct CONTENT_EXPORT CommonNavigationParams {
// We require a copy of the relevant CSP to perform navigation checks. // We require a copy of the relevant CSP to perform navigation checks.
std::vector<ContentSecurityPolicy> initiator_csp; std::vector<ContentSecurityPolicy> initiator_csp;
base::Optional<CSPSource> initiator_self_source; base::Optional<CSPSource> initiator_self_source;
// The current origin policy for this request's origin.
// (Empty if none applies.)
std::string origin_policy;
}; };
// Provided by the browser ----------------------------------------------------- // Provided by the browser -----------------------------------------------------
......
...@@ -466,6 +466,8 @@ WebURLRequest CreateURLRequestForNavigation( ...@@ -466,6 +466,8 @@ WebURLRequest CreateURLRequestForNavigation(
request.SetPreviewsState( request.SetPreviewsState(
static_cast<WebURLRequest::PreviewsState>(common_params.previews_state)); static_cast<WebURLRequest::PreviewsState>(common_params.previews_state));
request.SetOriginPolicy(WebString::FromUTF8(common_params.origin_policy));
auto extra_data = std::make_unique<RequestExtraData>(); auto extra_data = std::make_unique<RequestExtraData>();
extra_data->set_navigation_response_override(std::move(response_override)); extra_data->set_navigation_response_override(std::move(response_override));
extra_data->set_navigation_initiated_by_renderer( extra_data->set_navigation_initiated_by_renderer(
......
...@@ -1317,6 +1317,7 @@ test("content_unittests") { ...@@ -1317,6 +1317,7 @@ test("content_unittests") {
"../browser/frame_host/navigation_entry_impl_unittest.cc", "../browser/frame_host/navigation_entry_impl_unittest.cc",
"../browser/frame_host/navigation_handle_impl_unittest.cc", "../browser/frame_host/navigation_handle_impl_unittest.cc",
"../browser/frame_host/navigator_impl_unittest.cc", "../browser/frame_host/navigator_impl_unittest.cc",
"../browser/frame_host/origin_policy_throttle_unittest.cc",
"../browser/frame_host/render_frame_host_feature_policy_unittest.cc", "../browser/frame_host/render_frame_host_feature_policy_unittest.cc",
"../browser/frame_host/render_frame_host_manager_unittest.cc", "../browser/frame_host/render_frame_host_manager_unittest.cc",
"../browser/frame_host/render_widget_host_view_guest_unittest.cc", "../browser/frame_host/render_widget_host_view_guest_unittest.cc",
......
...@@ -40,6 +40,7 @@ const char HttpRequestHeaders::kProxyAuthorization[] = "Proxy-Authorization"; ...@@ -40,6 +40,7 @@ const char HttpRequestHeaders::kProxyAuthorization[] = "Proxy-Authorization";
const char HttpRequestHeaders::kProxyConnection[] = "Proxy-Connection"; const char HttpRequestHeaders::kProxyConnection[] = "Proxy-Connection";
const char HttpRequestHeaders::kRange[] = "Range"; const char HttpRequestHeaders::kRange[] = "Range";
const char HttpRequestHeaders::kReferer[] = "Referer"; const char HttpRequestHeaders::kReferer[] = "Referer";
const char HttpRequestHeaders::kSecOriginPolicy[] = "Sec-Origin-Policy";
const char HttpRequestHeaders::kTransferEncoding[] = "Transfer-Encoding"; const char HttpRequestHeaders::kTransferEncoding[] = "Transfer-Encoding";
const char HttpRequestHeaders::kTokenBinding[] = "Sec-Token-Binding"; const char HttpRequestHeaders::kTokenBinding[] = "Sec-Token-Binding";
const char HttpRequestHeaders::kUserAgent[] = "User-Agent"; const char HttpRequestHeaders::kUserAgent[] = "User-Agent";
......
...@@ -84,6 +84,7 @@ class NET_EXPORT HttpRequestHeaders { ...@@ -84,6 +84,7 @@ class NET_EXPORT HttpRequestHeaders {
static const char kProxyConnection[]; static const char kProxyConnection[];
static const char kRange[]; static const char kRange[];
static const char kReferer[]; static const char kReferer[];
static const char kSecOriginPolicy[];
static const char kTransferEncoding[]; static const char kTransferEncoding[];
static const char kTokenBinding[]; static const char kTokenBinding[];
static const char kUserAgent[]; static const char kUserAgent[];
......
...@@ -346,6 +346,10 @@ class WebURLRequest { ...@@ -346,6 +346,10 @@ class WebURLRequest {
BLINK_PLATFORM_EXPORT const base::Optional<base::UnguessableToken>& BLINK_PLATFORM_EXPORT const base::Optional<base::UnguessableToken>&
GetDevToolsToken() const; GetDevToolsToken() const;
// Set the applicable Origin Policy.
BLINK_PLATFORM_EXPORT const WebString GetOriginPolicy() const;
BLINK_PLATFORM_EXPORT void SetOriginPolicy(const WebString& policy);
#if INSIDE_BLINK #if INSIDE_BLINK
BLINK_PLATFORM_EXPORT ResourceRequest& ToMutableResourceRequest(); BLINK_PLATFORM_EXPORT ResourceRequest& ToMutableResourceRequest();
BLINK_PLATFORM_EXPORT const ResourceRequest& ToResourceRequest() const; BLINK_PLATFORM_EXPORT const ResourceRequest& ToResourceRequest() const;
......
...@@ -416,6 +416,14 @@ const base::Optional<base::UnguessableToken>& WebURLRequest::GetDevToolsToken() ...@@ -416,6 +416,14 @@ const base::Optional<base::UnguessableToken>& WebURLRequest::GetDevToolsToken()
return resource_request_->GetDevToolsToken(); return resource_request_->GetDevToolsToken();
} }
void WebURLRequest::SetOriginPolicy(const WebString& policy) {
resource_request_->SetOriginPolicy(policy);
}
const WebString WebURLRequest::GetOriginPolicy() const {
return resource_request_->GetOriginPolicy();
}
const ResourceRequest& WebURLRequest::ToResourceRequest() const { const ResourceRequest& WebURLRequest::ToResourceRequest() const {
DCHECK(resource_request_); DCHECK(resource_request_);
return *resource_request_; return *resource_request_;
......
...@@ -369,6 +369,9 @@ class PLATFORM_EXPORT ResourceRequest final { ...@@ -369,6 +369,9 @@ class PLATFORM_EXPORT ResourceRequest final {
devtools_token_ = devtools_token; devtools_token_ = devtools_token;
} }
void SetOriginPolicy(const String& policy) { origin_policy_ = policy; }
const String& GetOriginPolicy() const { return origin_policy_; }
private: private:
using SharableExtraData = using SharableExtraData =
base::RefCountedData<std::unique_ptr<WebURLRequest::ExtraData>>; base::RefCountedData<std::unique_ptr<WebURLRequest::ExtraData>>;
...@@ -438,6 +441,7 @@ class PLATFORM_EXPORT ResourceRequest final { ...@@ -438,6 +441,7 @@ class PLATFORM_EXPORT ResourceRequest final {
bool upgrade_if_insecure_ = false; bool upgrade_if_insecure_ = false;
base::Optional<base::UnguessableToken> devtools_token_; base::Optional<base::UnguessableToken> devtools_token_;
String origin_policy_;
}; };
// This class is needed to copy a ResourceRequest across threads, because it // This class is needed to copy a ResourceRequest across threads, because it
......
...@@ -162,6 +162,7 @@ Refer to README.md for content description and update process. ...@@ -162,6 +162,7 @@ Refer to README.md for content description and update process.
<item id="omnibox_zerosuggest_experimental" hash_code="3813491" type="0" content_hash_code="22929259" os_list="linux,windows" file_path="components/omnibox/browser/contextual_suggestions_service.cc"/> <item id="omnibox_zerosuggest_experimental" hash_code="3813491" type="0" content_hash_code="22929259" os_list="linux,windows" file_path="components/omnibox/browser/contextual_suggestions_service.cc"/>
<item id="one_google_bar_service" hash_code="78917933" type="0" content_hash_code="46527252" os_list="linux,windows" file_path="chrome/browser/search/one_google_bar/one_google_bar_loader_impl.cc"/> <item id="one_google_bar_service" hash_code="78917933" type="0" content_hash_code="46527252" os_list="linux,windows" file_path="chrome/browser/search/one_google_bar/one_google_bar_loader_impl.cc"/>
<item id="open_search" hash_code="107267424" type="0" content_hash_code="25715812" os_list="linux,windows" file_path="components/search_engines/template_url_fetcher.cc"/> <item id="open_search" hash_code="107267424" type="0" content_hash_code="25715812" os_list="linux,windows" file_path="components/search_engines/template_url_fetcher.cc"/>
<item id="origin_policy_loader" hash_code="6483617" type="0" content_hash_code="20680909" os_list="linux,windows" file_path="content/browser/frame_host/origin_policy_throttle.cc"/>
<item id="p2p_invalidator" hash_code="84201371" type="0" content_hash_code="117416248" os_list="linux,windows" file_path="components/invalidation/impl/p2p_invalidator.cc"/> <item id="p2p_invalidator" hash_code="84201371" type="0" content_hash_code="117416248" os_list="linux,windows" file_path="components/invalidation/impl/p2p_invalidator.cc"/>
<item id="parallel_download_job" hash_code="135118587" type="0" content_hash_code="105330419" os_list="linux,windows" file_path="components/download/internal/common/parallel_download_job.cc"/> <item id="parallel_download_job" hash_code="135118587" type="0" content_hash_code="105330419" os_list="linux,windows" file_path="components/download/internal/common/parallel_download_job.cc"/>
<item id="password_protection_request" hash_code="66322287" type="0" content_hash_code="25596947" os_list="linux,windows" file_path="components/safe_browsing/password_protection/password_protection_request.cc"/> <item id="password_protection_request" hash_code="66322287" type="0" content_hash_code="25596947" os_list="linux,windows" file_path="components/safe_browsing/password_protection/password_protection_request.cc"/>
......
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