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 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