1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/command_line.h" 6 #include "base/strings/string_util.h" 7 #include "chrome/browser/browser_process.h" 8 #include "chrome/browser/policy/cloud/policy_header_service_factory.h" 9 #include "chrome/browser/profiles/profile.h" 10 #include "chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h" 11 #include "chrome/browser/ui/browser.h" 12 #include "chrome/test/base/in_process_browser_test.h" 13 #include "chrome/test/base/ui_test_utils.h" 14 #include "components/policy/core/common/cloud/cloud_policy_constants.h" 15 #include "components/policy/core/common/cloud/policy_header_io_helper.h" 16 #include "components/policy/core/common/cloud/policy_header_service.h" 17 #include "components/policy/core/common/policy_switches.h" 18 #include "content/public/browser/resource_dispatcher_host.h" 19 #include "net/http/http_request_headers.h" 20 #include "net/test/embedded_test_server/embedded_test_server.h" 21 #include "net/test/embedded_test_server/http_request.h" 22 #include "net/test/embedded_test_server/http_response.h" 23 #include "net/url_request/url_request.h" 24 25 using content::ResourceType; 26 27 namespace { 28 static const char kTestPolicyHeader[] = "test_header"; 29 static const char kServerRedirectUrl[] = "/server-redirect"; 30 31 scoped_ptr<net::test_server::HttpResponse> HandleTestRequest( 32 const net::test_server::HttpRequest& request) { 33 if (StartsWithASCII(request.relative_url, kServerRedirectUrl, true)) { 34 // Extract the target URL and redirect there. 35 size_t query_string_pos = request.relative_url.find('?'); 36 std::string redirect_target = 37 request.relative_url.substr(query_string_pos + 1); 38 39 scoped_ptr<net::test_server::BasicHttpResponse> http_response( 40 new net::test_server::BasicHttpResponse); 41 http_response->set_code(net::HTTP_MOVED_PERMANENTLY); 42 http_response->AddCustomHeader("Location", redirect_target); 43 return http_response.PassAs<net::test_server::HttpResponse>(); 44 } else { 45 scoped_ptr<net::test_server::BasicHttpResponse> http_response( 46 new net::test_server::BasicHttpResponse); 47 http_response->set_code(net::HTTP_OK); 48 http_response->set_content("Success"); 49 return http_response.PassAs<net::test_server::HttpResponse>(); 50 } 51 } 52 53 class TestDispatcherHostDelegate : public ChromeResourceDispatcherHostDelegate { 54 public: 55 explicit TestDispatcherHostDelegate( 56 prerender::PrerenderTracker* prerender_tracker) 57 : ChromeResourceDispatcherHostDelegate(prerender_tracker) { 58 } 59 60 virtual ~TestDispatcherHostDelegate() {} 61 62 virtual void RequestBeginning( 63 net::URLRequest* request, 64 content::ResourceContext* resource_context, 65 content::AppCacheService* appcache_service, 66 ResourceType resource_type, 67 ScopedVector<content::ResourceThrottle>* throttles) OVERRIDE { 68 ChromeResourceDispatcherHostDelegate::RequestBeginning( 69 request, 70 resource_context, 71 appcache_service, 72 resource_type, 73 throttles); 74 request_headers_.MergeFrom(request->extra_request_headers()); 75 } 76 77 virtual void OnRequestRedirected( 78 const GURL& redirect_url, 79 net::URLRequest* request, 80 content::ResourceContext* resource_context, 81 content::ResourceResponse* response) OVERRIDE { 82 ChromeResourceDispatcherHostDelegate::OnRequestRedirected( 83 redirect_url, 84 request, 85 resource_context, 86 response); 87 request_headers_.MergeFrom(request->extra_request_headers()); 88 } 89 90 net::HttpRequestHeaders request_headers_; 91 92 private: 93 DISALLOW_COPY_AND_ASSIGN(TestDispatcherHostDelegate); 94 }; 95 96 } // namespace 97 98 class ChromeResourceDispatcherHostDelegateBrowserTest : 99 public InProcessBrowserTest { 100 public: 101 ChromeResourceDispatcherHostDelegateBrowserTest() {} 102 103 virtual void SetUpOnMainThread() OVERRIDE { 104 InProcessBrowserTest::SetUpOnMainThread(); 105 // Hook navigations with our delegate. 106 dispatcher_host_delegate_.reset(new TestDispatcherHostDelegate( 107 g_browser_process->prerender_tracker())); 108 content::ResourceDispatcherHost::Get()->SetDelegate( 109 dispatcher_host_delegate_.get()); 110 111 embedded_test_server()->RegisterRequestHandler( 112 base::Bind(&HandleTestRequest)); 113 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 114 // Tell chrome that this is our DM server. 115 dm_url_ = embedded_test_server()->GetURL("/DeviceManagement"); 116 117 // At this point, the Profile is already initialized and it's too 118 // late to set the DMServer URL via command line flags, so directly 119 // inject it to the PolicyHeaderIOHelper. 120 policy::PolicyHeaderService* policy_header_service = 121 policy::PolicyHeaderServiceFactory::GetForBrowserContext( 122 browser()->profile()); 123 std::vector<policy::PolicyHeaderIOHelper*> helpers = 124 policy_header_service->GetHelpersForTest(); 125 for (std::vector<policy::PolicyHeaderIOHelper*>::const_iterator it = 126 helpers.begin(); 127 it != helpers.end(); ++it) { 128 (*it)->SetServerURLForTest(dm_url_.spec()); 129 (*it)->UpdateHeader(kTestPolicyHeader); 130 } 131 } 132 133 virtual void TearDownOnMainThread() OVERRIDE { 134 content::ResourceDispatcherHost::Get()->SetDelegate(NULL); 135 dispatcher_host_delegate_.reset(); 136 } 137 138 protected: 139 // The fake URL for DMServer we are using. 140 GURL dm_url_; 141 scoped_ptr<TestDispatcherHostDelegate> dispatcher_host_delegate_; 142 143 private: 144 DISALLOW_COPY_AND_ASSIGN(ChromeResourceDispatcherHostDelegateBrowserTest); 145 }; 146 147 148 IN_PROC_BROWSER_TEST_F(ChromeResourceDispatcherHostDelegateBrowserTest, 149 NoPolicyHeader) { 150 // When fetching non-DMServer URLs, we should not add a policy header to the 151 // request. 152 DCHECK(!embedded_test_server()->base_url().spec().empty()); 153 ui_test_utils::NavigateToURL(browser(), embedded_test_server()->base_url()); 154 ASSERT_FALSE(dispatcher_host_delegate_->request_headers_.HasHeader( 155 policy::kChromePolicyHeader)); 156 } 157 158 IN_PROC_BROWSER_TEST_F(ChromeResourceDispatcherHostDelegateBrowserTest, 159 PolicyHeader) { 160 // When fetching a DMServer URL, we should add a policy header to the 161 // request. 162 ui_test_utils::NavigateToURL(browser(), dm_url_); 163 std::string value; 164 ASSERT_TRUE(dispatcher_host_delegate_->request_headers_.GetHeader( 165 policy::kChromePolicyHeader, &value)); 166 ASSERT_EQ(kTestPolicyHeader, value); 167 } 168 169 IN_PROC_BROWSER_TEST_F(ChromeResourceDispatcherHostDelegateBrowserTest, 170 PolicyHeaderForRedirect) { 171 172 // Build up a URL that results in a redirect to the DMServer URL to make 173 // sure the policy header is still added. 174 std::string redirect_url; 175 redirect_url += kServerRedirectUrl; 176 redirect_url += "?"; 177 redirect_url += dm_url_.spec(); 178 ui_test_utils::NavigateToURL(browser(), embedded_test_server()->GetURL( 179 redirect_url)); 180 std::string value; 181 ASSERT_TRUE(dispatcher_host_delegate_->request_headers_.GetHeader( 182 policy::kChromePolicyHeader, &value)); 183 ASSERT_EQ(kTestPolicyHeader, value); 184 } 185