1 // Copyright (c) 2012 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/bind.h"
6 #include "base/strings/string_number_conversions.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/app/chrome_command_ids.h"
9 #include "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/tab_contents/render_view_context_menu.h"
11 #include "chrome/browser/tab_contents/render_view_context_menu_browsertest_util.h"
12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/browser_commands.h"
14 #include "chrome/browser/ui/tabs/tab_strip_model.h"
15 #include "chrome/test/base/in_process_browser_test.h"
16 #include "chrome/test/base/ui_test_utils.h"
17 #include "content/public/browser/notification_service.h"
18 #include "content/public/browser/render_view_host.h"
19 #include "content/public/browser/web_contents.h"
20 #include "content/public/test/browser_test_utils.h"
21 #include "net/test/spawned_test_server/spawned_test_server.h"
22 #include "third_party/WebKit/public/web/WebInputEvent.h"
23
24 // GTK requires a X11-level mouse event to open a context menu correctly.
25 #if defined(TOOLKIT_GTK)
26 #define MAYBE_ContextMenuOrigin DISABLED_ContextMenuOrigin
27 #define MAYBE_HttpsContextMenuOrigin DISABLED_HttpsContextMenuOrigin
28 #define MAYBE_ContextMenuRedirect DISABLED_ContextMenuRedirect
29 #define MAYBE_HttpsContextMenuRedirect DISABLED_HttpsContextMenuRedirect
30 #else
31 #define MAYBE_ContextMenuOrigin ContextMenuOrigin
32 #define MAYBE_HttpsContextMenuOrigin HttpsContextMenuOrigin
33 #define MAYBE_ContextMenuRedirect ContextMenuRedirect
34 #define MAYBE_HttpsContextMenuRedirect HttpsContextMenuRedirect
35 #endif
36
37 namespace {
38
39 const base::FilePath::CharType kDocRoot[] =
40 FILE_PATH_LITERAL("chrome/test/data/referrer_policy");
41
42 } // namespace
43
44 class ReferrerPolicyTest : public InProcessBrowserTest {
45 public:
ReferrerPolicyTest()46 ReferrerPolicyTest() {}
~ReferrerPolicyTest()47 virtual ~ReferrerPolicyTest() {}
48
SetUp()49 virtual void SetUp() OVERRIDE {
50 test_server_.reset(new net::SpawnedTestServer(
51 net::SpawnedTestServer::TYPE_HTTP,
52 net::SpawnedTestServer::kLocalhost,
53 base::FilePath(kDocRoot)));
54 ASSERT_TRUE(test_server_->Start());
55 ssl_test_server_.reset(new net::SpawnedTestServer(
56 net::SpawnedTestServer::TYPE_HTTPS,
57 net::SpawnedTestServer::kLocalhost,
58 base::FilePath(kDocRoot)));
59 ASSERT_TRUE(ssl_test_server_->Start());
60
61 InProcessBrowserTest::SetUp();
62 }
63
64 protected:
65 enum ExpectedReferrer {
66 EXPECT_EMPTY_REFERRER,
67 EXPECT_FULL_REFERRER,
68 EXPECT_ORIGIN_AS_REFERRER
69 };
70
71 // Returns the expected title for the tab with the given (full) referrer and
72 // the expected modification of it.
GetExpectedTitle(const GURL & url,ExpectedReferrer expected_referrer)73 base::string16 GetExpectedTitle(const GURL& url,
74 ExpectedReferrer expected_referrer) {
75 std::string referrer;
76 switch (expected_referrer) {
77 case EXPECT_EMPTY_REFERRER:
78 referrer = "Referrer is empty";
79 break;
80 case EXPECT_FULL_REFERRER:
81 referrer = "Referrer is " + url.spec();
82 break;
83 case EXPECT_ORIGIN_AS_REFERRER:
84 referrer = "Referrer is " + url.GetWithEmptyPath().spec();
85 break;
86 }
87 return ASCIIToUTF16(referrer);
88 }
89
90 // Adds all possible titles to the TitleWatcher, so we don't time out
91 // waiting for the title if the test fails.
AddAllPossibleTitles(const GURL & url,content::TitleWatcher * title_watcher)92 void AddAllPossibleTitles(const GURL& url,
93 content::TitleWatcher* title_watcher) {
94 title_watcher->AlsoWaitForTitle(
95 GetExpectedTitle(url, EXPECT_EMPTY_REFERRER));
96 title_watcher->AlsoWaitForTitle(
97 GetExpectedTitle(url, EXPECT_FULL_REFERRER));
98 title_watcher->AlsoWaitForTitle(
99 GetExpectedTitle(url, EXPECT_ORIGIN_AS_REFERRER));
100 }
101
102 // Navigates from a page with a given |referrer_policy| and checks that the
103 // reported referrer matches the expectation.
104 // Parameters:
105 // referrer_policy: The referrer policy to test ("default", "always",
106 // "origin", "never")
107 // start_on_https: True if the test should start on an HTTPS page.
108 // target_blank: True if the link that is generated should have the
109 // attribute target=_blank
110 // redirect: True if the link target should first do a server
111 // redirect before evaluating the passed referrer.
112 // opens_new_tab: True if this test opens a new tab.
113 // button: If not WebMouseEvent::ButtonNone, click on the
114 // link with the specified mouse button.
115 // expected_referrer: The kind of referrer to expect.
116 //
117 // Returns:
118 // The URL of the first page navigated to.
RunReferrerTest(const std::string referrer_policy,bool start_on_https,bool target_blank,bool redirect,bool opens_new_tab,blink::WebMouseEvent::Button button,ExpectedReferrer expected_referrer)119 GURL RunReferrerTest(const std::string referrer_policy,
120 bool start_on_https,
121 bool target_blank,
122 bool redirect,
123 bool opens_new_tab,
124 blink::WebMouseEvent::Button button,
125 ExpectedReferrer expected_referrer) {
126 GURL start_url;
127 net::SpawnedTestServer* start_server =
128 start_on_https ? ssl_test_server_.get() : test_server_.get();
129 start_url = start_server->GetURL(
130 std::string("files/referrer-policy-start.html?") +
131 "policy=" + referrer_policy +
132 "&port=" + base::IntToString(test_server_->host_port_pair().port()) +
133 "&ssl_port=" +
134 base::IntToString(ssl_test_server_->host_port_pair().port()) +
135 "&redirect=" + (redirect ? "true" : "false") +
136 "&link=" +
137 (button == blink::WebMouseEvent::ButtonNone ? "false" : "true") +
138 "&target=" + (target_blank ? "_blank" : ""));
139
140 ui_test_utils::WindowedTabAddedNotificationObserver tab_added_observer(
141 content::NotificationService::AllSources());
142
143 base::string16 expected_title =
144 GetExpectedTitle(start_url, expected_referrer);
145 content::WebContents* tab =
146 browser()->tab_strip_model()->GetActiveWebContents();
147 content::TitleWatcher title_watcher(tab, expected_title);
148
149 // Watch for all possible outcomes to avoid timeouts if something breaks.
150 AddAllPossibleTitles(start_url, &title_watcher);
151
152 ui_test_utils::NavigateToURL(browser(), start_url);
153
154 if (button != blink::WebMouseEvent::ButtonNone) {
155 blink::WebMouseEvent mouse_event;
156 mouse_event.type = blink::WebInputEvent::MouseDown;
157 mouse_event.button = button;
158 mouse_event.x = 15;
159 mouse_event.y = 15;
160 mouse_event.clickCount = 1;
161 tab->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
162 mouse_event.type = blink::WebInputEvent::MouseUp;
163 tab->GetRenderViewHost()->ForwardMouseEvent(mouse_event);
164 }
165
166 if (opens_new_tab) {
167 tab_added_observer.Wait();
168 tab = tab_added_observer.GetTab();
169 EXPECT_TRUE(tab);
170 content::WaitForLoadStop(tab);
171 EXPECT_EQ(expected_title, tab->GetTitle());
172 } else {
173 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
174 }
175
176 return start_url;
177 }
178
179 scoped_ptr<net::SpawnedTestServer> test_server_;
180 scoped_ptr<net::SpawnedTestServer> ssl_test_server_;
181 };
182
183 // The basic behavior of referrer policies is covered by layout tests in
184 // http/tests/security/referrer-policy-*. These tests cover (hopefully) all
185 // code paths chrome uses to navigate. To keep the number of combinations down,
186 // we only test the "origin" policy here.
187 //
188 // Some tests are marked as FAILS, see http://crbug.com/124750
189
190 // Content initiated navigation, from HTTP to HTTP.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,Origin)191 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest, Origin) {
192 RunReferrerTest("origin", false, false, false, false,
193 blink::WebMouseEvent::ButtonNone,
194 EXPECT_ORIGIN_AS_REFERRER);
195 }
196
197 // Content initiated navigation, from HTTPS to HTTP.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,HttpsDefault)198 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest, HttpsDefault) {
199 RunReferrerTest("origin", true, false, false, false,
200 blink::WebMouseEvent::ButtonNone,
201 EXPECT_ORIGIN_AS_REFERRER);
202 }
203
204 // User initiated navigation, from HTTP to HTTP.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,LeftClickOrigin)205 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest, LeftClickOrigin) {
206 RunReferrerTest("origin", false, false, false, false,
207 blink::WebMouseEvent::ButtonLeft,
208 EXPECT_ORIGIN_AS_REFERRER);
209 }
210
211 // User initiated navigation, from HTTPS to HTTP.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,HttpsLeftClickOrigin)212 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest, HttpsLeftClickOrigin) {
213 RunReferrerTest("origin", true, false, false, false,
214 blink::WebMouseEvent::ButtonLeft,
215 EXPECT_ORIGIN_AS_REFERRER);
216 }
217
218 // User initiated navigation, middle click, from HTTP to HTTP.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,MiddleClickOrigin)219 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest, MiddleClickOrigin) {
220 RunReferrerTest("origin", false, false, false, true,
221 blink::WebMouseEvent::ButtonMiddle,
222 EXPECT_ORIGIN_AS_REFERRER);
223 }
224
225 // User initiated navigation, middle click, from HTTPS to HTTP.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,HttpsMiddleClickOrigin)226 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest, HttpsMiddleClickOrigin) {
227 RunReferrerTest("origin", true, false, false, true,
228 blink::WebMouseEvent::ButtonMiddle,
229 EXPECT_ORIGIN_AS_REFERRER);
230 }
231
232 // User initiated navigation, target blank, from HTTP to HTTP.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,TargetBlankOrigin)233 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest, TargetBlankOrigin) {
234 RunReferrerTest("origin", false, true, false, true,
235 blink::WebMouseEvent::ButtonLeft,
236 EXPECT_ORIGIN_AS_REFERRER);
237 }
238
239 // User initiated navigation, target blank, from HTTPS to HTTP.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,HttpsTargetBlankOrigin)240 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest, HttpsTargetBlankOrigin) {
241 RunReferrerTest("origin", true, true, false, true,
242 blink::WebMouseEvent::ButtonLeft,
243 EXPECT_ORIGIN_AS_REFERRER);
244 }
245
246 // User initiated navigation, middle click, target blank, from HTTP to HTTP.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,MiddleClickTargetBlankOrigin)247 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest, MiddleClickTargetBlankOrigin) {
248 RunReferrerTest("origin", false, true, false, true,
249 blink::WebMouseEvent::ButtonMiddle,
250 EXPECT_ORIGIN_AS_REFERRER);
251 }
252
253 // User initiated navigation, middle click, target blank, from HTTPS to HTTP.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,HttpsMiddleClickTargetBlankOrigin)254 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest, HttpsMiddleClickTargetBlankOrigin) {
255 RunReferrerTest("origin", true, true, false, true,
256 blink::WebMouseEvent::ButtonMiddle,
257 EXPECT_ORIGIN_AS_REFERRER);
258 }
259
260 // Context menu, from HTTP to HTTP.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,MAYBE_ContextMenuOrigin)261 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest, MAYBE_ContextMenuOrigin) {
262 ContextMenuNotificationObserver context_menu_observer(
263 IDC_CONTENT_CONTEXT_OPENLINKNEWTAB);
264 RunReferrerTest("origin", false, false, false, true,
265 blink::WebMouseEvent::ButtonRight,
266 EXPECT_ORIGIN_AS_REFERRER);
267 }
268
269 // Context menu, from HTTPS to HTTP.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,MAYBE_HttpsContextMenuOrigin)270 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest, MAYBE_HttpsContextMenuOrigin) {
271 ContextMenuNotificationObserver context_menu_observer(
272 IDC_CONTENT_CONTEXT_OPENLINKNEWTAB);
273 RunReferrerTest("origin", true, false, false, true,
274 blink::WebMouseEvent::ButtonRight,
275 EXPECT_ORIGIN_AS_REFERRER);
276 }
277
278 // Content initiated navigation, from HTTP to HTTP via server redirect.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,Redirect)279 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest, Redirect) {
280 RunReferrerTest("origin", false, false, true, false,
281 blink::WebMouseEvent::ButtonNone,
282 EXPECT_ORIGIN_AS_REFERRER);
283 }
284
285 // Content initiated navigation, from HTTPS to HTTP via server redirect.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,HttpsRedirect)286 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest, HttpsRedirect) {
287 RunReferrerTest("origin", true, false, true, false,
288 blink::WebMouseEvent::ButtonNone,
289 EXPECT_ORIGIN_AS_REFERRER);
290 }
291
292 // User initiated navigation, from HTTP to HTTP via server redirect.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,LeftClickRedirect)293 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest, LeftClickRedirect) {
294 RunReferrerTest("origin", false, false, true, false,
295 blink::WebMouseEvent::ButtonLeft,
296 EXPECT_ORIGIN_AS_REFERRER);
297 }
298
299 // User initiated navigation, from HTTPS to HTTP via server redirect.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,HttpsLeftClickRedirect)300 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest, HttpsLeftClickRedirect) {
301 RunReferrerTest("origin", true, false, true, false,
302 blink::WebMouseEvent::ButtonLeft,
303 EXPECT_ORIGIN_AS_REFERRER);
304 }
305
306 // User initiated navigation, middle click, from HTTP to HTTP via server
307 // redirect.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,MiddleClickRedirect)308 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest, MiddleClickRedirect) {
309 RunReferrerTest("origin", false, false, true, true,
310 blink::WebMouseEvent::ButtonMiddle,
311 EXPECT_ORIGIN_AS_REFERRER);
312 }
313
314 // User initiated navigation, middle click, from HTTPS to HTTP via server
315 // redirect.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,HttpsMiddleClickRedirect)316 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest, HttpsMiddleClickRedirect) {
317 RunReferrerTest("origin", true, false, true, true,
318 blink::WebMouseEvent::ButtonMiddle,
319 EXPECT_ORIGIN_AS_REFERRER);
320 }
321
322 // User initiated navigation, target blank, from HTTP to HTTP via server
323 // redirect.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,TargetBlankRedirect)324 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest, TargetBlankRedirect) {
325 RunReferrerTest("origin", false, true, true, true,
326 blink::WebMouseEvent::ButtonLeft,
327 EXPECT_ORIGIN_AS_REFERRER);
328 }
329
330 // User initiated navigation, target blank, from HTTPS to HTTP via server
331 // redirect.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,HttpsTargetBlankRedirect)332 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest, HttpsTargetBlankRedirect) {
333 RunReferrerTest("origin", true, true, true, true,
334 blink::WebMouseEvent::ButtonLeft,
335 EXPECT_ORIGIN_AS_REFERRER);
336 }
337
338 // User initiated navigation, middle click, target blank, from HTTP to HTTP via
339 // server redirect.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,MiddleClickTargetBlankRedirect)340 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest, MiddleClickTargetBlankRedirect) {
341 RunReferrerTest("origin", false, true, true, true,
342 blink::WebMouseEvent::ButtonMiddle,
343 EXPECT_ORIGIN_AS_REFERRER);
344 }
345
346 // User initiated navigation, middle click, target blank, from HTTPS to HTTP
347 // via server redirect.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,HttpsMiddleClickTargetBlankRedirect)348 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,
349 HttpsMiddleClickTargetBlankRedirect) {
350 RunReferrerTest("origin", true, true, true, true,
351 blink::WebMouseEvent::ButtonMiddle,
352 EXPECT_ORIGIN_AS_REFERRER);
353 }
354
355 // Context menu, from HTTP to HTTP via server redirect.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,MAYBE_ContextMenuRedirect)356 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest, MAYBE_ContextMenuRedirect) {
357 ContextMenuNotificationObserver context_menu_observer(
358 IDC_CONTENT_CONTEXT_OPENLINKNEWTAB);
359 RunReferrerTest("origin", false, false, true, true,
360 blink::WebMouseEvent::ButtonRight,
361 EXPECT_ORIGIN_AS_REFERRER);
362 }
363
364 // Context menu, from HTTPS to HTTP via server redirect.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,MAYBE_HttpsContextMenuRedirect)365 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest, MAYBE_HttpsContextMenuRedirect) {
366 ContextMenuNotificationObserver context_menu_observer(
367 IDC_CONTENT_CONTEXT_OPENLINKNEWTAB);
368 RunReferrerTest("origin", true, false, true, true,
369 blink::WebMouseEvent::ButtonRight,
370 EXPECT_ORIGIN_AS_REFERRER);
371 }
372
373 // Tests history navigation actions: Navigate from A to B with a referrer
374 // policy, then navigate to C, back to B, and reload.
IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest,History)375 IN_PROC_BROWSER_TEST_F(ReferrerPolicyTest, History) {
376 // Navigate from A to B.
377 GURL start_url = RunReferrerTest("origin", true, false, true, false,
378 blink::WebMouseEvent::ButtonLeft,
379 EXPECT_ORIGIN_AS_REFERRER);
380
381 // Navigate to C.
382 ui_test_utils::NavigateToURL(browser(), test_server_->GetURL(std::string()));
383
384 base::string16 expected_title =
385 GetExpectedTitle(start_url, EXPECT_ORIGIN_AS_REFERRER);
386 content::WebContents* tab =
387 browser()->tab_strip_model()->GetActiveWebContents();
388 scoped_ptr<content::TitleWatcher> title_watcher(
389 new content::TitleWatcher(tab, expected_title));
390
391 // Watch for all possible outcomes to avoid timeouts if something breaks.
392 AddAllPossibleTitles(start_url, title_watcher.get());
393
394 // Go back to B.
395 chrome::GoBack(browser(), CURRENT_TAB);
396 EXPECT_EQ(expected_title, title_watcher->WaitAndGetTitle());
397
398 title_watcher.reset(new content::TitleWatcher(tab, expected_title));
399 AddAllPossibleTitles(start_url, title_watcher.get());
400
401 // Reload to B.
402 chrome::Reload(browser(), CURRENT_TAB);
403 EXPECT_EQ(expected_title, title_watcher->WaitAndGetTitle());
404
405 title_watcher.reset(new content::TitleWatcher(tab, expected_title));
406 AddAllPossibleTitles(start_url, title_watcher.get());
407
408 // Shift-reload to B.
409 chrome::ReloadIgnoringCache(browser(), CURRENT_TAB);
410 EXPECT_EQ(expected_title, title_watcher->WaitAndGetTitle());
411 }
412