chrome_resource_dispatcher_host_delegate_browsertest.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
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
25namespace {
26static const char kTestPolicyHeader[] = "test_header";
27static const char kServerRedirectUrl[] = "/server-redirect";
28
29scoped_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
51class 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
100class 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
151IN_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
161IN_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
172IN_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