Commit a4e12afa authored by Chong Zhang's avatar Chong Zhang Committed by Commit Bot

[NetworkService] Support adding policy headers for DMServer

This CL:
1. Allows chrome to add policy headers for navigations and redirects
   via content API.
2. Removes the old |PolicyHeaderIOHelper| codepath and moves policy
   header tests to a new location.
3. Adds a move constructor/assignment for |net::HttpRequestHeaders|.

Bug: 832749,845683
Cq-Include-Trybots: luci.chromium.try:linux_mojo
Change-Id: I713ed30da33ba5feb5f437f8927b173c2f84d91a
Reviewed-on: https://chromium-review.googlesource.com/1100393
Commit-Queue: Chong Zhang <chongz@chromium.org>
Reviewed-by: default avatarJohn Abd-El-Malek <jam@chromium.org>
Reviewed-by: default avatarMaks Orlovich <morlovich@chromium.org>
Reviewed-by: default avatarDrew Wilson <atwilson@chromium.org>
Cr-Commit-Position: refs/heads/master@{#569503}
parent 3c724bcd
......@@ -74,6 +74,7 @@
#include "chrome/browser/permissions/permission_request_manager.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/plugins/pdf_iframe_navigation_throttle.h"
#include "chrome/browser/policy/cloud/policy_header_service_factory.h"
#include "chrome/browser/predictors/loading_predictor.h"
#include "chrome/browser/predictors/loading_predictor_factory.h"
#include "chrome/browser/prerender/prerender_final_status.h"
......@@ -180,6 +181,7 @@
#include "components/password_manager/content/browser/content_password_manager_driver_factory.h"
#include "components/payments/content/payment_request_display_manager.h"
#include "components/policy/content/policy_blacklist_navigation_throttle.h"
#include "components/policy/core/common/cloud/policy_header_service.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
......@@ -2160,9 +2162,10 @@ void ChromeContentBrowserClient::NavigationRequestStarted(
int* extra_load_flags) {
WebContents* web_contents =
WebContents::FromFrameTreeNodeId(frame_tree_node_id);
content::BrowserContext* browser_context = web_contents->GetBrowserContext();
*extra_headers =
client_hints::GetAdditionalNavigationRequestClientHintsHeaders(
web_contents->GetBrowserContext(), url);
browser_context, url);
prerender::PrerenderContents* prerender_contents =
prerender::PrerenderContents::FromWebContents(web_contents);
if (prerender_contents &&
......@@ -2173,6 +2176,37 @@ void ChromeContentBrowserClient::NavigationRequestStarted(
extra_headers->get()->SetHeader(prerender::kPurposeHeaderName,
prerender::kPurposeHeaderValue);
}
if (!browser_context->IsOffTheRecord()) {
// Add policy headers for non-incognito requests.
policy::PolicyHeaderService* policy_header_service =
policy::PolicyHeaderServiceFactory::GetForBrowserContext(
browser_context);
if (policy_header_service)
policy_header_service->AddPolicyHeaders(url, extra_headers);
}
}
void ChromeContentBrowserClient::NavigationRequestRedirected(
int frame_tree_node_id,
const GURL& url,
base::Optional<net::HttpRequestHeaders>* modified_request_headers) {
WebContents* web_contents =
WebContents::FromFrameTreeNodeId(frame_tree_node_id);
content::BrowserContext* browser_context = web_contents->GetBrowserContext();
if (!browser_context->IsOffTheRecord()) {
// Add policy headers for non-incognito requests.
policy::PolicyHeaderService* policy_header_service =
policy::PolicyHeaderServiceFactory::GetForBrowserContext(
browser_context);
if (policy_header_service) {
std::unique_ptr<net::HttpRequestHeaders> extra_headers;
policy_header_service->AddPolicyHeaders(url, &extra_headers);
if (extra_headers)
*modified_request_headers = std::move(*extra_headers);
}
}
}
bool ChromeContentBrowserClient::AllowAppCache(
......
......@@ -171,6 +171,10 @@ class ChromeContentBrowserClient : public content::ContentBrowserClient {
const GURL& url,
std::unique_ptr<net::HttpRequestHeaders>* extra_headers,
int* extra_load_flags) override;
void NavigationRequestRedirected(int frame_tree_node_id,
const GURL& url,
base::Optional<net::HttpRequestHeaders>*
modified_request_headers) override;
bool AllowAppCache(const GURL& manifest_url,
const GURL& first_party,
content::ResourceContext* context) override;
......
......@@ -8,6 +8,7 @@
#include "base/command_line.h"
#include "base/macros.h"
#include "base/sys_info.h"
#include "chrome/browser/policy/cloud/policy_header_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search/instant_service.h"
#include "chrome/browser/search/instant_service_factory.h"
......@@ -21,6 +22,8 @@
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "components/policy/core/common/cloud/policy_header_service.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/render_frame_host.h"
......@@ -30,11 +33,26 @@
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_status_code.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "url/gurl.h"
namespace content {
namespace {
const char kTestPolicyHeader[] = "test_header";
const char kServerRedirectUrl[] = "/server-redirect";
enum class NetworkServiceState {
kDisabled,
kEnabled,
};
} // namespace
// Use a test class with SetUpCommandLine to ensure the flag is sent to the
// first renderer process.
class ChromeContentBrowserClientBrowserTest : public InProcessBrowserTest {
......@@ -281,4 +299,104 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessMemoryThresholdBrowserTest,
content::SiteIsolationPolicy::UseDedicatedProcessesForAllSites());
}
class PolicyHeaderServiceBrowserTest : public InProcessBrowserTest {
public:
PolicyHeaderServiceBrowserTest() = default;
void SetUpOnMainThread() override {
embedded_test_server()->RegisterRequestHandler(
base::BindRepeating(&PolicyHeaderServiceBrowserTest::HandleTestRequest,
base::Unretained(this)));
ASSERT_TRUE(embedded_test_server()->Start());
// Forge a dummy DMServer URL.
dm_url_ = embedded_test_server()->GetURL("/DeviceManagement");
// At this point, the Profile is already initialized and it's too
// late to set the DMServer URL via command line flags, so directly
// inject it to the PolicyHeaderService.
policy::PolicyHeaderService* policy_header_service =
policy::PolicyHeaderServiceFactory::GetForBrowserContext(
browser()->profile());
policy_header_service->SetServerURLForTest(dm_url_.spec());
policy_header_service->SetHeaderForTest(kTestPolicyHeader);
}
std::unique_ptr<net::test_server::HttpResponse> HandleTestRequest(
const net::test_server::HttpRequest& request) {
last_request_headers_ = request.headers;
if (base::StartsWith(request.relative_url, kServerRedirectUrl,
base::CompareCase::SENSITIVE)) {
// Extract the target URL and redirect there.
size_t query_string_pos = request.relative_url.find('?');
std::string redirect_target =
request.relative_url.substr(query_string_pos + 1);
std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
new net::test_server::BasicHttpResponse);
http_response->set_code(net::HTTP_MOVED_PERMANENTLY);
http_response->AddCustomHeader("Location", redirect_target);
return std::move(http_response);
} else if (request.relative_url == "/") {
std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
new net::test_server::BasicHttpResponse);
http_response->set_code(net::HTTP_OK);
http_response->set_content("Success");
return std::move(http_response);
}
return nullptr;
}
const GURL& dm_url() const { return dm_url_; }
const net::test_server::HttpRequest::HeaderMap& last_request_headers() const {
return last_request_headers_;
}
private:
// The dummy URL for DMServer.
GURL dm_url_;
// List of request headers received by the embedded server.
net::test_server::HttpRequest::HeaderMap last_request_headers_;
DISALLOW_COPY_AND_ASSIGN(PolicyHeaderServiceBrowserTest);
};
IN_PROC_BROWSER_TEST_F(PolicyHeaderServiceBrowserTest, NoPolicyHeader) {
// When fetching non-DMServer URLs, we should not add a policy header to the
// request.
DCHECK(!embedded_test_server()->base_url().spec().empty());
ui_test_utils::NavigateToURL(browser(), embedded_test_server()->base_url());
auto iter = last_request_headers().find(policy::kChromePolicyHeader);
EXPECT_EQ(iter, last_request_headers().end());
}
IN_PROC_BROWSER_TEST_F(PolicyHeaderServiceBrowserTest, PolicyHeader) {
// When fetching a DMServer URL, we should add a policy header to the
// request.
ui_test_utils::NavigateToURL(browser(), dm_url());
auto iter = last_request_headers().find(policy::kChromePolicyHeader);
ASSERT_NE(iter, last_request_headers().end());
EXPECT_EQ(iter->second, kTestPolicyHeader);
}
IN_PROC_BROWSER_TEST_F(PolicyHeaderServiceBrowserTest,
PolicyHeaderForRedirect) {
// Build up a URL that results in a redirect to the DMServer URL to make
// sure the policy header is still added.
std::string redirect_url;
redirect_url += kServerRedirectUrl;
redirect_url += "?";
redirect_url += dm_url().spec();
ui_test_utils::NavigateToURL(browser(),
embedded_test_server()->GetURL(redirect_url));
auto iter = last_request_headers().find(policy::kChromePolicyHeader);
ASSERT_NE(iter, last_request_headers().end());
EXPECT_EQ(iter->second, kTestPolicyHeader);
}
} // namespace content
......@@ -54,7 +54,6 @@
#include "components/offline_pages/buildflags/buildflags.h"
#include "components/offline_pages/core/request_header/offline_page_navigation_ui_data.h"
#include "components/policy/content/policy_blacklist_navigation_throttle.h"
#include "components/policy/core/common/cloud/policy_header_io_helper.h"
#include "components/previews/content/previews_content_util.h"
#include "components/previews/content/previews_io_data.h"
#include "components/previews/core/previews_decider.h"
......@@ -427,9 +426,6 @@ void ChromeResourceDispatcherHostDelegate::RequestBeginning(
request->SetExtraRequestHeaders(headers);
}
if (io_data->policy_header_helper())
io_data->policy_header_helper()->AddPolicyHeaders(request->url(), request);
signin::ChromeRequestAdapter signin_request_adapter(request);
signin::FixAccountConsistencyRequestHeader(
&signin_request_adapter, GURL() /* redirect_url */, io_data);
......@@ -684,9 +680,6 @@ void ChromeResourceDispatcherHostDelegate::OnRequestRedirected(
signin::ResponseAdapter signin_response_adapter(request);
signin::ProcessAccountConsistencyResponseHeaders(
&signin_response_adapter, redirect_url, io_data->IsOffTheRecord());
if (io_data->policy_header_helper())
io_data->policy_header_helper()->AddPolicyHeaders(redirect_url, request);
}
// Notification that a request has completed.
......
......@@ -35,7 +35,6 @@
#include "chrome/test/base/ui_test_utils.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "components/policy/core/common/cloud/policy_header_io_helper.h"
#include "components/policy/core/common/cloud/policy_header_service.h"
#include "components/policy/core/common/policy_switches.h"
#include "components/prefs/pref_service.h"
......@@ -67,24 +66,9 @@ using testing::Not;
namespace {
static const char kTestPolicyHeader[] = "test_header";
static const char kServerRedirectUrl[] = "/server-redirect";
std::unique_ptr<net::test_server::HttpResponse> HandleTestRequest(
const net::test_server::HttpRequest& request) {
if (base::StartsWith(request.relative_url, kServerRedirectUrl,
base::CompareCase::SENSITIVE)) {
// Extract the target URL and redirect there.
size_t query_string_pos = request.relative_url.find('?');
std::string redirect_target =
request.relative_url.substr(query_string_pos + 1);
std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
new net::test_server::BasicHttpResponse);
http_response->set_code(net::HTTP_MOVED_PERMANENTLY);
http_response->AddCustomHeader("Location", redirect_target);
return std::move(http_response);
} else if (request.relative_url == "/") {
if (request.relative_url == "/") {
std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
new net::test_server::BasicHttpResponse);
http_response->set_code(net::HTTP_OK);
......@@ -220,23 +204,6 @@ class ChromeResourceDispatcherHostDelegateBrowserTest :
embedded_test_server()->RegisterRequestHandler(
base::Bind(&HandleTestRequest));
ASSERT_TRUE(embedded_test_server()->Start());
// Tell chrome that this is our DM server.
dm_url_ = embedded_test_server()->GetURL("/DeviceManagement");
// At this point, the Profile is already initialized and it's too
// late to set the DMServer URL via command line flags, so directly
// inject it to the PolicyHeaderIOHelper.
policy::PolicyHeaderService* policy_header_service =
policy::PolicyHeaderServiceFactory::GetForBrowserContext(
browser()->profile());
std::vector<policy::PolicyHeaderIOHelper*> helpers =
policy_header_service->GetHelpersForTest();
for (std::vector<policy::PolicyHeaderIOHelper*>::const_iterator it =
helpers.begin();
it != helpers.end(); ++it) {
(*it)->SetServerURLForTest(dm_url_.spec());
(*it)->UpdateHeader(kTestPolicyHeader);
}
}
void TearDownOnMainThread() override {
......@@ -263,52 +230,12 @@ class ChromeResourceDispatcherHostDelegateBrowserTest :
}
protected:
// The fake URL for DMServer we are using.
GURL dm_url_;
std::unique_ptr<TestDispatcherHostDelegate> dispatcher_host_delegate_;
private:
DISALLOW_COPY_AND_ASSIGN(ChromeResourceDispatcherHostDelegateBrowserTest);
};
IN_PROC_BROWSER_TEST_F(ChromeResourceDispatcherHostDelegateBrowserTest,
NoPolicyHeader) {
// When fetching non-DMServer URLs, we should not add a policy header to the
// request.
DCHECK(!embedded_test_server()->base_url().spec().empty());
ui_test_utils::NavigateToURL(browser(), embedded_test_server()->base_url());
ASSERT_FALSE(dispatcher_host_delegate_->request_headers().HasHeader(
policy::kChromePolicyHeader));
}
IN_PROC_BROWSER_TEST_F(ChromeResourceDispatcherHostDelegateBrowserTest,
PolicyHeader) {
// When fetching a DMServer URL, we should add a policy header to the
// request.
ui_test_utils::NavigateToURL(browser(), dm_url_);
std::string value;
ASSERT_TRUE(dispatcher_host_delegate_->request_headers().GetHeader(
policy::kChromePolicyHeader, &value));
ASSERT_EQ(kTestPolicyHeader, value);
}
IN_PROC_BROWSER_TEST_F(ChromeResourceDispatcherHostDelegateBrowserTest,
PolicyHeaderForRedirect) {
// Build up a URL that results in a redirect to the DMServer URL to make
// sure the policy header is still added.
std::string redirect_url;
redirect_url += kServerRedirectUrl;
redirect_url += "?";
redirect_url += dm_url_.spec();
ui_test_utils::NavigateToURL(browser(), embedded_test_server()->GetURL(
redirect_url));
std::string value;
ASSERT_TRUE(dispatcher_host_delegate_->request_headers().GetHeader(
policy::kChromePolicyHeader, &value));
ASSERT_EQ(kTestPolicyHeader, value);
}
IN_PROC_BROWSER_TEST_F(ChromeResourceDispatcherHostDelegateBrowserTest,
NavigationDataProcessed) {
ui_test_utils::NavigateToURL(browser(), embedded_test_server()->base_url());
......
......@@ -59,7 +59,6 @@
#include "components/metrics/metrics_pref_names.h"
#include "components/metrics/metrics_service.h"
#include "components/net_log/chrome_net_log.h"
#include "components/policy/core/common/cloud/policy_header_io_helper.h"
#include "components/policy/core/common/cloud/policy_header_service.h"
#include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
#include "components/prefs/pref_service.h"
......@@ -534,16 +533,6 @@ void ProfileIOData::InitializeOnUIThread(Profile* profile) {
}
#endif
if (!IsOffTheRecord()) {
// Add policy headers for non-incognito requests.
policy::PolicyHeaderService* policy_header_service =
policy::PolicyHeaderServiceFactory::GetForBrowserContext(profile);
if (policy_header_service) {
policy_header_helper_ =
policy_header_service->CreatePolicyHeaderIOHelper(io_task_runner);
}
}
incognito_availibility_pref_.Init(
prefs::kIncognitoModeAvailability, pref_service);
incognito_availibility_pref_.MoveToThread(io_task_runner);
......
......@@ -82,7 +82,6 @@ class ReportingService;
namespace policy {
class PolicyCertVerifier;
class PolicyHeaderIOHelper;
} // namespace policy
namespace previews {
......@@ -216,10 +215,6 @@ class ProfileIOData {
}
#endif
policy::PolicyHeaderIOHelper* policy_header_helper() const {
return policy_header_helper_.get();
}
// Initialize the member needed to track the metrics enabled state. This is
// only to be called on the UI thread.
void InitializeMetricsEnabledStateOnUIThread();
......@@ -577,9 +572,6 @@ class ProfileIOData {
BooleanPrefMember enable_metrics_;
// Pointed to by NetworkDelegate.
mutable std::unique_ptr<policy::PolicyHeaderIOHelper> policy_header_helper_;
// Pointed to by URLRequestContext.
#if BUILDFLAG(ENABLE_EXTENSIONS)
mutable scoped_refptr<extensions::InfoMap> extension_info_map_;
......
......@@ -69,8 +69,6 @@ source_set("internal") {
"cloud/machine_level_user_cloud_policy_metrics.h",
"cloud/machine_level_user_cloud_policy_store.cc",
"cloud/machine_level_user_cloud_policy_store.h",
"cloud/policy_header_io_helper.cc",
"cloud/policy_header_io_helper.h",
"cloud/policy_header_service.cc",
"cloud/policy_header_service.h",
"cloud/resource_cache.cc",
......@@ -307,7 +305,6 @@ source_set("unit_tests") {
"cloud/cloud_policy_service_unittest.cc",
"cloud/cloud_policy_validator_unittest.cc",
"cloud/device_management_service_unittest.cc",
"cloud/policy_header_io_helper_unittest.cc",
"cloud/policy_header_service_unittest.cc",
"cloud/user_info_fetcher_unittest.cc",
"generate_policy_source_unittest.cc",
......
// Copyright 2013 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 "components/policy/core/common/cloud/policy_header_io_helper.h"
#include "base/bind.h"
#include "base/location.h"
#include "base/sequenced_task_runner.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "net/url_request/url_request.h"
namespace policy {
PolicyHeaderIOHelper::PolicyHeaderIOHelper(
const std::string& server_url,
const std::string& initial_header_value,
const scoped_refptr<base::SequencedTaskRunner>& task_runner)
: server_url_(server_url),
io_task_runner_(task_runner),
policy_header_(initial_header_value) {
}
PolicyHeaderIOHelper::~PolicyHeaderIOHelper() {
}
// Sets any necessary policy headers on the passed request.
void PolicyHeaderIOHelper::AddPolicyHeaders(const GURL& url,
net::URLRequest* request) const {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
if (!policy_header_.empty() &&
url.spec().compare(0, server_url_.size(), server_url_) == 0) {
request->SetExtraRequestHeaderByName(kChromePolicyHeader,
policy_header_,
true /* overwrite */);
}
}
void PolicyHeaderIOHelper::UpdateHeader(const std::string& new_header) {
// Post a task to the IO thread to modify this.
io_task_runner_->PostTask(
FROM_HERE,
base::Bind(&PolicyHeaderIOHelper::UpdateHeaderOnIOThread,
base::Unretained(this), new_header));
}
void PolicyHeaderIOHelper::UpdateHeaderOnIOThread(
const std::string& new_header) {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
policy_header_ = new_header;
}
void PolicyHeaderIOHelper::SetServerURLForTest(const std::string& server_url) {
io_task_runner_->PostTask(
FROM_HERE,
base::Bind(&PolicyHeaderIOHelper::SetServerURLOnIOThread,
base::Unretained(this), server_url));
}
void PolicyHeaderIOHelper::SetServerURLOnIOThread(
const std::string& server_url) {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
server_url_ = server_url;
}
} // namespace policy
// Copyright 2013 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 COMPONENTS_POLICY_CORE_COMMON_CLOUD_POLICY_HEADER_IO_HELPER_H_
#define COMPONENTS_POLICY_CORE_COMMON_CLOUD_POLICY_HEADER_IO_HELPER_H_
#include <string>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner.h"
#include "components/policy/policy_export.h"
#include "url/gurl.h"
namespace net {
class URLRequest;
}
namespace policy {
// Helper class that lives on the I/O thread and adds policy headers to
// outgoing requests. Instances of this class are created by
// PolicyHeaderService on the UI thread, and that class is responsible for
// notifying this class via UpdateHeaderFromUI() when the header changes.
// Ownership is transferred to ProfileIOData, and this object is run and
// destroyed on the I/O thread.
class POLICY_EXPORT PolicyHeaderIOHelper {
public:
PolicyHeaderIOHelper(
const std::string& server_url,
const std::string& initial_header_value,
const scoped_refptr<base::SequencedTaskRunner>& task_runner);
~PolicyHeaderIOHelper();
// Sets any necessary policy headers for the specified URL on the passed
// request. Should be invoked only from the I/O thread.
void AddPolicyHeaders(const GURL& url,
net::URLRequest* request) const;
// API invoked when the header changes. Can be called from any thread - calls
// are marshalled via the TaskRunner to run on the appropriate thread.
// If |new_header| is the empty string, no header will be added to
// outgoing requests.
void UpdateHeader(const std::string& new_header);
// Test-only routine used to inject the server URL at runtime - this is
// required because PolicyHeaderIOHelper is created very early in BrowserTest
// initialization, before we startup the EmbeddedTestServer.
void SetServerURLForTest(const std::string& server_url);
private:
// API invoked via the TaskRunner to update the header.
void UpdateHeaderOnIOThread(const std::string& new_header);
// Helper routine invoked via the TaskRunner to update the cached server URL.
void SetServerURLOnIOThread(const std::string& new_header);
// The URL we should add policy headers to.
std::string server_url_;
// The task runner associated with the I/O thread that runs this object.
scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
// The current policy header value.
std::string policy_header_;
DISALLOW_COPY_AND_ASSIGN(PolicyHeaderIOHelper);
};
} // namespace policy
#endif // COMPONENTS_POLICY_CORE_COMMON_CLOUD_POLICY_HEADER_IO_HELPER_H_
// Copyright 2013 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 "components/policy/core/common/cloud/policy_header_io_helper.h"
#include <memory>
#include "base/message_loop/message_loop.h"
#include "base/test/test_simple_task_runner.h"
#include "net/http/http_request_headers.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace policy {
namespace {
const char kDMServerURL[] = "http://server_url";
const char kPolicyHeaderName[] = "Chrome-Policy-Posture";
const char kInitialPolicyHeader[] = "initial_header";
class PolicyHeaderIOHelperTest : public testing::Test {
public:
PolicyHeaderIOHelperTest() {
task_runner_ = base::MakeRefCounted<base::TestSimpleTaskRunner>();
}
~PolicyHeaderIOHelperTest() override {}
void SetUp() override {
helper_ = std::make_unique<PolicyHeaderIOHelper>(
kDMServerURL, kInitialPolicyHeader, task_runner_);
task_runner_->RunUntilIdle();
}
void TearDown() override {
task_runner_->RunUntilIdle();
helper_.reset();
}
void ValidateHeader(const net::HttpRequestHeaders& headers,
const std::string& expected) {
std::string header;
EXPECT_TRUE(headers.GetHeader(kPolicyHeaderName, &header));
EXPECT_EQ(header, expected);
}
base::MessageLoop loop_;
std::unique_ptr<PolicyHeaderIOHelper> helper_;
net::TestURLRequestContext context_;
scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
};
} // namespace
TEST_F(PolicyHeaderIOHelperTest, InitialHeader) {
std::unique_ptr<net::URLRequest> request(
context_.CreateRequest(GURL(kDMServerURL), net::DEFAULT_PRIORITY, nullptr,
TRAFFIC_ANNOTATION_FOR_TESTS));
helper_->AddPolicyHeaders(request->url(), request.get());
ValidateHeader(request->extra_request_headers(), kInitialPolicyHeader);
}
TEST_F(PolicyHeaderIOHelperTest, NoHeaderOnNonMatchingURL) {
std::unique_ptr<net::URLRequest> request(context_.CreateRequest(
GURL("http://non-matching.com"), net::DEFAULT_PRIORITY, nullptr,
TRAFFIC_ANNOTATION_FOR_TESTS));
helper_->AddPolicyHeaders(request->url(), request.get());
EXPECT_TRUE(request->extra_request_headers().IsEmpty());
}
TEST_F(PolicyHeaderIOHelperTest, HeaderChange) {
std::string new_header = "new_header";
helper_->UpdateHeader(new_header);
task_runner_->RunUntilIdle();
std::unique_ptr<net::URLRequest> request(
context_.CreateRequest(GURL(kDMServerURL), net::DEFAULT_PRIORITY, nullptr,
TRAFFIC_ANNOTATION_FOR_TESTS));
helper_->AddPolicyHeaders(request->url(), request.get());
ValidateHeader(request->extra_request_headers(), new_header);
}
TEST_F(PolicyHeaderIOHelperTest, ChangeToNoHeader) {
helper_->UpdateHeader("");
task_runner_->RunUntilIdle();
std::unique_ptr<net::URLRequest> request(
context_.CreateRequest(GURL(kDMServerURL), net::DEFAULT_PRIORITY, nullptr,
TRAFFIC_ANNOTATION_FOR_TESTS));
helper_->AddPolicyHeaders(request->url(), request.get());
EXPECT_TRUE(request->extra_request_headers().IsEmpty());
}
} // namespace policy
......@@ -8,8 +8,9 @@
#include "base/json/json_writer.h"
#include "base/sequenced_task_runner.h"
#include "base/values.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "components/policy/core/common/cloud/cloud_policy_store.h"
#include "components/policy/core/common/cloud/policy_header_io_helper.h"
#include "net/http/http_request_headers.h"
namespace {
const char kUserDMTokenKey[] = "user_dmtoken";
......@@ -27,21 +28,23 @@ PolicyHeaderService::PolicyHeaderService(
verification_key_hash_(verification_key_hash),
user_policy_store_(user_policy_store) {
user_policy_store_->AddObserver(this);
policy_header_ = CreateHeaderValue();
}
PolicyHeaderService::~PolicyHeaderService() {
user_policy_store_->RemoveObserver(this);
}
std::unique_ptr<PolicyHeaderIOHelper>
PolicyHeaderService::CreatePolicyHeaderIOHelper(
scoped_refptr<base::SequencedTaskRunner> task_runner) {
std::string initial_header_value = CreateHeaderValue();
std::unique_ptr<PolicyHeaderIOHelper> helper =
std::make_unique<PolicyHeaderIOHelper>(server_url_, initial_header_value,
task_runner);
helpers_.push_back(helper.get());
return helper;
void PolicyHeaderService::AddPolicyHeaders(
const GURL& url,
std::unique_ptr<net::HttpRequestHeaders>* extra_headers) const {
DCHECK(extra_headers);
if (!policy_header_.empty() &&
url.spec().compare(0, server_url_.size(), server_url_) == 0) {
if (!extra_headers->get())
(*extra_headers) = std::make_unique<net::HttpRequestHeaders>();
(*extra_headers)->SetHeader(kChromePolicyHeader, policy_header_);
}
}
std::string PolicyHeaderService::CreateHeaderValue() {
......@@ -80,22 +83,19 @@ std::string PolicyHeaderService::CreateHeaderValue() {
}
void PolicyHeaderService::OnStoreLoaded(CloudPolicyStore* store) {
// If we have a PolicyHeaderIOHelper, notify it of the new header value.
if (!helpers_.empty()) {
std::string new_header = CreateHeaderValue();
for (std::vector<PolicyHeaderIOHelper*>::const_iterator it =
helpers_.begin(); it != helpers_.end(); ++it) {
(*it)->UpdateHeader(new_header);
}
}
policy_header_ = CreateHeaderValue();
}
void PolicyHeaderService::OnStoreError(CloudPolicyStore* store) {
// Do nothing on errors.
}
std::vector<PolicyHeaderIOHelper*> PolicyHeaderService::GetHelpersForTest() {
return helpers_;
void PolicyHeaderService::SetHeaderForTest(const std::string& new_header) {
policy_header_ = new_header;
}
void PolicyHeaderService::SetServerURLForTest(const std::string& server_url) {
server_url_ = server_url;
}
} // namespace policy
......@@ -13,17 +13,15 @@
#include "base/memory/ref_counted.h"
#include "components/policy/core/common/cloud/cloud_policy_store.h"
#include "components/policy/policy_export.h"
#include "url/gurl.h"
namespace base {
class SequencedTaskRunner;
namespace net {
class HttpRequestHeaders;
}
namespace policy {
class PolicyHeaderIOHelper;
// Per-profile service used to generate PolicyHeaderIOHelper objects, and
// keep them up to date as policy changes.
// Per-profile service used to keep track of policy changes.
// TODO(atwilson): Move to components/policy once CloudPolicyStore is moved.
class POLICY_EXPORT PolicyHeaderService : public CloudPolicyStore::Observer {
public:
......@@ -35,27 +33,26 @@ class POLICY_EXPORT PolicyHeaderService : public CloudPolicyStore::Observer {
CloudPolicyStore* user_policy_store);
~PolicyHeaderService() override;
// Creates a PolicyHeaderIOHelper object to be run on the IO thread and
// add policy headers to outgoing requests. The caller takes ownership of
// this object and must ensure it outlives ProfileHeaderService (in practice,
// this is called by ProfileIOData, which is shutdown *after* all
// ProfileKeyedServices are shutdown).
std::unique_ptr<PolicyHeaderIOHelper> CreatePolicyHeaderIOHelper(
scoped_refptr<base::SequencedTaskRunner> task_runner);
// Update |*extra_headers| (allocate if necessary) with the policy header if
// |url| matches |server_url_|. Otherwise |extra_headers| remains unchanged.
void AddPolicyHeaders(
const GURL& url,
std::unique_ptr<net::HttpRequestHeaders>* extra_headers) const;
// Overridden CloudPolicyStore::Observer methods:
void OnStoreLoaded(CloudPolicyStore* store) override;
void OnStoreError(CloudPolicyStore* store) override;
// Returns a list of all PolicyHeaderIOHelpers created by this object.
std::vector<PolicyHeaderIOHelper*> GetHelpersForTest();
// Test-only routines used to inject the server URL/headers at runtime.
void SetHeaderForTest(const std::string& new_header);
void SetServerURLForTest(const std::string& server_url);
private:
// Generate a policy header based on the currently loaded policy.
std::string CreateHeaderValue();
// Weak pointer to created PolicyHeaderIOHelper objects.
std::vector<PolicyHeaderIOHelper*> helpers_;
// The current policy header value.
std::string policy_header_;
// URL of the policy server.
std::string server_url_;
......
......@@ -14,7 +14,6 @@
#include "base/values.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "components/policy/core/common/cloud/mock_cloud_policy_store.h"
#include "components/policy/core/common/cloud/policy_header_io_helper.h"
#include "net/http/http_request_headers.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request.h"
......@@ -48,14 +47,19 @@ class PolicyHeaderServiceTest : public testing::Test {
service_.reset(new PolicyHeaderService(kDMServerURL,
kPolicyVerificationKeyHash,
&user_store_));
helper_ = service_->CreatePolicyHeaderIOHelper(task_runner_);
}
void TearDown() override {
task_runner_->RunUntilIdle();
// Helper should outlive the service.
service_.reset();
helper_.reset();
}
void ValidateHeader(const net::HttpRequestHeaders& headers,
const std::string& expected) {
std::string header;
EXPECT_TRUE(headers.GetHeader(kPolicyHeaderName, &header));
EXPECT_EQ(header, expected);
}
void ValidateHeader(const net::HttpRequestHeaders& headers,
......@@ -88,7 +92,6 @@ class PolicyHeaderServiceTest : public testing::Test {
base::MessageLoop loop_;
std::unique_ptr<PolicyHeaderService> service_;
TestCloudPolicyStore user_store_;
std::unique_ptr<PolicyHeaderIOHelper> helper_;
scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
};
......@@ -97,11 +100,10 @@ class PolicyHeaderServiceTest : public testing::Test {
TEST_F(PolicyHeaderServiceTest, TestCreationAndShutdown) {
// Just tests that the objects can be created and shutdown properly.
EXPECT_TRUE(service_);
EXPECT_TRUE(helper_);
}
TEST_F(PolicyHeaderServiceTest, TestWithAndWithoutPolicyHeader) {
// Set policy - this should push a header to the PolicyHeaderIOHelper.
// Set policy.
std::unique_ptr<PolicyData> policy(new PolicyData());
std::string expected_dmtoken = "expected_dmtoken";
std::string expected_policy_token = "expected_dmtoken";
......@@ -111,22 +113,44 @@ TEST_F(PolicyHeaderServiceTest, TestWithAndWithoutPolicyHeader) {
task_runner_->RunUntilIdle();
net::TestURLRequestContext context;
std::unique_ptr<net::URLRequest> request(
context.CreateRequest(GURL(kDMServerURL), net::DEFAULT_PRIORITY, nullptr,
TRAFFIC_ANNOTATION_FOR_TESTS));
helper_->AddPolicyHeaders(request->url(), request.get());
ValidateHeader(request->extra_request_headers(), expected_dmtoken,
expected_policy_token);
std::unique_ptr<net::HttpRequestHeaders> extra_headers =
std::make_unique<net::HttpRequestHeaders>();
service_->AddPolicyHeaders(GURL(kDMServerURL), &extra_headers);
ValidateHeader(*extra_headers, expected_dmtoken, expected_policy_token);
// Now blow away the policy data.
user_store_.SetPolicy(std::unique_ptr<PolicyData>());
task_runner_->RunUntilIdle();
std::unique_ptr<net::URLRequest> request2(
context.CreateRequest(GURL(kDMServerURL), net::DEFAULT_PRIORITY, nullptr,
TRAFFIC_ANNOTATION_FOR_TESTS));
helper_->AddPolicyHeaders(request2->url(), request2.get());
ValidateHeader(request2->extra_request_headers(), "", "");
std::unique_ptr<net::HttpRequestHeaders> extra_headers2 =
std::make_unique<net::HttpRequestHeaders>();
service_->AddPolicyHeaders(GURL(kDMServerURL), &extra_headers2);
ValidateHeader(*extra_headers2, "", "");
}
TEST_F(PolicyHeaderServiceTest, NoHeaderOnNonMatchingURL) {
service_->SetHeaderForTest("new_header");
std::unique_ptr<net::HttpRequestHeaders> extra_headers =
std::make_unique<net::HttpRequestHeaders>();
service_->AddPolicyHeaders(GURL("http://non-matching.com"), &extra_headers);
EXPECT_TRUE(extra_headers->IsEmpty());
}
TEST_F(PolicyHeaderServiceTest, HeaderChange) {
std::string new_header = "new_header";
service_->SetHeaderForTest(new_header);
std::unique_ptr<net::HttpRequestHeaders> extra_headers =
std::make_unique<net::HttpRequestHeaders>();
service_->AddPolicyHeaders(GURL(kDMServerURL), &extra_headers);
ValidateHeader(*extra_headers, new_header);
}
TEST_F(PolicyHeaderServiceTest, ChangeToNoHeader) {
service_->SetHeaderForTest("");
std::unique_ptr<net::HttpRequestHeaders> extra_headers =
std::make_unique<net::HttpRequestHeaders>();
service_->AddPolicyHeaders(GURL(kDMServerURL), &extra_headers);
EXPECT_TRUE(extra_headers->IsEmpty());
}
} // namespace policy
......@@ -1385,7 +1385,13 @@ void NavigationRequest::OnRedirectChecksComplete(
RenderFrameDevToolsAgentHost::OnNavigationRequestWillBeSent(*this);
loader_->FollowRedirect(base::nullopt, base::nullopt);
base::Optional<net::HttpRequestHeaders> embedder_additional_headers;
GetContentClient()->browser()->NavigationRequestRedirected(
frame_tree_node_->frame_tree_node_id(), common_params_.url,
&embedder_additional_headers);
loader_->FollowRedirect(base::nullopt,
std::move(embedder_additional_headers));
}
void NavigationRequest::OnFailureChecksComplete(
......
......@@ -166,6 +166,14 @@ class CrossSiteDocumentResourceHandler::Controller : public ResourceController {
}
}
void ResumeForRedirect(const base::Optional<net::HttpRequestHeaders>&
modified_request_headers) override {
DCHECK(!modified_request_headers.has_value())
<< "Redirect with modified headers was not supported yet. "
"crbug.com/845683";
Resume();
}
void Cancel() override {
MarkAsUsed();
document_handler_->Cancel();
......
......@@ -38,6 +38,14 @@ class DetachableResourceHandler::Controller : public ResourceController {
detachable_handler_->ResumeInternal();
}
void ResumeForRedirect(const base::Optional<net::HttpRequestHeaders>&
modified_request_headers) override {
DCHECK(!modified_request_headers.has_value())
<< "Redirect with modified headers was not supported yet. "
"crbug.com/845683";
Resume();
}
void Cancel() override {
MarkAsUsed();
detachable_handler_->Cancel();
......
......@@ -29,6 +29,14 @@ class InterceptingResourceHandler::Controller : public ResourceController {
intercepting_handler_->ResumeInternal();
}
void ResumeForRedirect(const base::Optional<net::HttpRequestHeaders>&
modified_request_headers) override {
DCHECK(!modified_request_headers.has_value())
<< "Redirect with modified headers was not supported yet. "
"crbug.com/845683";
Resume();
}
void Cancel() override {
MarkAsUsed();
intercepting_handler_->Cancel();
......
......@@ -74,6 +74,14 @@ class MimeSniffingResourceHandler::Controller : public ResourceController {
mime_handler_->ResumeInternal();
}
void ResumeForRedirect(const base::Optional<net::HttpRequestHeaders>&
modified_request_headers) override {
DCHECK(!modified_request_headers.has_value())
<< "Redirect with modified headers was not supported yet. "
"crbug.com/845683";
Resume();
}
void Cancel() override {
MarkAsUsed();
mime_handler_->Cancel();
......
......@@ -10,6 +10,7 @@
#include "content/browser/loader/resource_controller.h"
#include "content/browser/loader/resource_handler.h"
#include "net/base/io_buffer.h"
#include "net/http/http_request_headers.h"
#include "net/url_request/url_request_status.h"
#include "services/network/public/cpp/resource_response.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -24,6 +25,14 @@ class MockResourceLoader::TestResourceController : public ResourceController {
void Resume() override { mock_loader_->OnResume(); }
void ResumeForRedirect(const base::Optional<net::HttpRequestHeaders>&
modified_request_headers) override {
DCHECK(!modified_request_headers.has_value())
<< "Redirect with modified headers was not supported yet. "
"crbug.com/845683";
Resume();
}
void Cancel() override { CancelWithError(net::ERR_ABORTED); }
void CancelWithError(int error_code) override {
......
......@@ -349,9 +349,6 @@ void MojoAsyncResourceHandler::FollowRedirect(
const base::Optional<std::vector<std::string>>&
to_be_removed_request_headers,
const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
DCHECK(!modified_request_headers.has_value()) << "Redirect with modified "
"headers was not supported "
"yet. crbug.com/845683";
if (!request()->status().is_success()) {
DVLOG(1) << "FollowRedirect for invalid request";
return;
......@@ -366,7 +363,7 @@ void MojoAsyncResourceHandler::FollowRedirect(
DCHECK(!did_defer_on_writing_);
did_defer_on_redirect_ = false;
request()->LogUnblocked();
Resume();
ResumeForRedirect(modified_request_headers);
}
void MojoAsyncResourceHandler::ProceedWithResponse() {
......
......@@ -5,6 +5,7 @@
#include "content/browser/loader/null_resource_controller.h"
#include "base/logging.h"
#include "net/http/http_request_headers.h"
namespace content {
......@@ -27,4 +28,12 @@ void NullResourceController::Resume() {
*was_resumed_ = true;
}
void NullResourceController::ResumeForRedirect(
const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
DCHECK(!modified_request_headers.has_value()) << "Redirect with modified "
"headers was not supported "
"yet. crbug.com/845683";
Resume();
}
} // namespace content
......@@ -23,6 +23,8 @@ class NullResourceController : public ResourceController {
void Cancel() override;
void CancelWithError(int error_code) override;
void Resume() override;
void ResumeForRedirect(const base::Optional<net::HttpRequestHeaders>&
modified_request_headers) override;
private:
bool* was_resumed_;
......
......@@ -5,8 +5,13 @@
#ifndef CONTENT_BROWSER_LOADER_RESOURCE_CONTROLLER_H_
#define CONTENT_BROWSER_LOADER_RESOURCE_CONTROLLER_H_
#include "base/optional.h"
#include "content/common/content_export.h"
namespace net {
class HttpRequestHeaders;
};
namespace content {
// Used to either resume a deferred resource load or cancel a resource load at
......@@ -25,6 +30,12 @@ class CONTENT_EXPORT ResourceController {
// deferred. Guaranteed not to call back into the ResourceHandler, or destroy
// it, synchronously.
virtual void Resume() = 0;
// Similar to |Resume()| but can only be called if the request was previously
// redirected. |modified_request_headers| are changes applied to the request
// headers after updating them for the redirect.
virtual void ResumeForRedirect(const base::Optional<net::HttpRequestHeaders>&
modified_request_headers) = 0;
};
} // namespace content
......
......@@ -44,6 +44,11 @@ void ResourceHandler::Resume() {
ReleaseController()->Resume();
}
void ResourceHandler::ResumeForRedirect(
const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
ReleaseController()->ResumeForRedirect(modified_request_headers);
}
void ResourceHandler::Cancel() {
ReleaseController()->Cancel();
}
......
......@@ -159,6 +159,8 @@ class CONTENT_EXPORT ResourceHandler {
// These call the corresponding methods on the ResourceController previously
// passed to HoldController and then destroy it.
void Resume();
void ResumeForRedirect(
const base::Optional<net::HttpRequestHeaders>& modified_request_headers);
void Cancel();
void CancelWithError(int error_code);
......
......@@ -155,7 +155,15 @@ class ResourceLoader::Controller : public ResourceController {
// ResourceController implementation:
void Resume() override {
MarkAsUsed();
resource_loader_->Resume(true /* called_from_resource_controller */);
resource_loader_->Resume(true /* called_from_resource_controller */,
base::nullopt);
}
void ResumeForRedirect(const base::Optional<net::HttpRequestHeaders>&
modified_request_headers) override {
MarkAsUsed();
resource_loader_->Resume(true /* called_from_resource_controller */,
modified_request_headers);
}
void Cancel() override {
......@@ -212,7 +220,8 @@ class ResourceLoader::ScopedDeferral {
// If Resume() was called, it just advanced the state without doing
// anything. Go ahead and resume the request now.
if (old_deferred_stage == DEFERRED_NONE)
resource_loader_->Resume(false /* called_from_resource_controller */);
resource_loader_->Resume(false /* called_from_resource_controller */,
base::nullopt);
}
private:
......@@ -521,9 +530,13 @@ void ResourceLoader::CancelCertificateSelection() {
request_->CancelWithError(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
}
void ResourceLoader::Resume(bool called_from_resource_controller) {
void ResourceLoader::Resume(
bool called_from_resource_controller,
const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
DeferredStage stage = deferred_stage_;
deferred_stage_ = DEFERRED_NONE;
DCHECK(!modified_request_headers.has_value() || stage == DEFERRED_REDIRECT)
<< "modified_request_headers can only be used with redirects";
switch (stage) {
case DEFERRED_NONE:
NOTREACHED();
......@@ -542,7 +555,7 @@ void ResourceLoader::Resume(bool called_from_resource_controller) {
// URLRequest::Start completes asynchronously, so starting the request now
// won't result in synchronously calling into a ResourceHandler, if this
// was called from Resume().
FollowDeferredRedirectInternal();
FollowDeferredRedirectInternal(modified_request_headers);
break;
case DEFERRED_ON_WILL_READ:
// Always post a task, as synchronous resumes don't go through this
......@@ -670,15 +683,18 @@ void ResourceLoader::CancelRequestInternal(int error, bool from_renderer) {
}
}
void ResourceLoader::FollowDeferredRedirectInternal() {
void ResourceLoader::FollowDeferredRedirectInternal(
const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
DCHECK(!deferred_redirect_url_.is_empty());
GURL redirect_url = deferred_redirect_url_;
deferred_redirect_url_ = GURL();
if (delegate_->HandleExternalProtocol(this, redirect_url)) {
DCHECK(!modified_request_headers.has_value())
<< "ResourceLoaderDelegate::HandleExternalProtocol() with modified "
"headers was not supported yet. crbug.com/845683";
Cancel();
} else {
request_->FollowDeferredRedirect(
base::nullopt /* modified_request_headers */);
request_->FollowDeferredRedirect(modified_request_headers);
}
}
......
......@@ -98,14 +98,17 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
// |called_from_resource_controller| is true if called directly from a
// ResourceController, in which case |resource_handler_| must not be invoked
// or destroyed synchronously to avoid re-entrancy issues, and false
// otherwise.
void Resume(bool called_from_resource_controller);
// otherwise. |modified_request_headers| is used for redirects only.
void Resume(
bool called_from_resource_controller,
const base::Optional<net::HttpRequestHeaders>& modified_request_headers);
void Cancel();
void CancelWithError(int error_code);
void StartRequestInternal();
void CancelRequestInternal(int error, bool from_renderer);
void FollowDeferredRedirectInternal();
void FollowDeferredRedirectInternal(
const base::Optional<net::HttpRequestHeaders>& modified_request_headers);
void CompleteResponseStarted();
// If |handle_result_async| is true, the result of the following read will be
// handled asynchronously if it completes synchronously, unless it's EOF or an
......
......@@ -470,6 +470,14 @@ class CONTENT_EXPORT ContentBrowserClient {
std::unique_ptr<net::HttpRequestHeaders>* extra_headers,
int* extra_load_flags) {}
// Allow the embedder to modify headers for a redirect. If non-nullopt,
// |*modified_request_headers| are applied to the request headers after
// updating them for the redirect.
virtual void NavigationRequestRedirected(
int frame_tree_node_id,
const GURL& url,
base::Optional<net::HttpRequestHeaders>* modified_request_headers) {}
// Allow the embedder to control if the given cookie can be read.
// This is called on the IO thread.
virtual bool AllowGetCookie(const GURL& url,
......
......@@ -75,8 +75,14 @@ bool HttpRequestHeaders::Iterator::GetNext() {
HttpRequestHeaders::HttpRequestHeaders() = default;
HttpRequestHeaders::HttpRequestHeaders(const HttpRequestHeaders& other) =
default;
HttpRequestHeaders::HttpRequestHeaders(HttpRequestHeaders&& other) = default;
HttpRequestHeaders::~HttpRequestHeaders() = default;
HttpRequestHeaders& HttpRequestHeaders::operator=(
const HttpRequestHeaders& other) = default;
HttpRequestHeaders& HttpRequestHeaders::operator=(HttpRequestHeaders&& other) =
default;
bool HttpRequestHeaders::GetHeader(const base::StringPiece& key,
std::string* out) const {
HeaderVector::const_iterator it = FindHeader(key);
......
......@@ -90,8 +90,12 @@ class NET_EXPORT HttpRequestHeaders {
HttpRequestHeaders();
HttpRequestHeaders(const HttpRequestHeaders& other);
HttpRequestHeaders(HttpRequestHeaders&& other);
~HttpRequestHeaders();
HttpRequestHeaders& operator=(const HttpRequestHeaders& other);
HttpRequestHeaders& operator=(HttpRequestHeaders&& other);
bool IsEmpty() const { return headers_.empty(); }
bool HasHeader(const base::StringPiece& key) const {
......
......@@ -370,11 +370,6 @@
-PredictorBrowserTest.SubframeInitiatesPreconnects
-PredictorBrowserTest.SubframeLearning
# https://crbug.com/832749
# Add DMServer header
-ChromeResourceDispatcherHostDelegateBrowserTest.PolicyHeader
-ChromeResourceDispatcherHostDelegateBrowserTest.PolicyHeaderForRedirect
# Requires a replacement for ChromeNetworkDelegate.
# http://crbug.com/841309
-VariationsHttpHeadersBrowserTest.TestStrippingHeadersFromInternalRequest
......
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