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