Convert remaining WebContentsObservers loading callbacks to use RFH.
[chromium-blink-merge.git] / content / browser / session_history_browsertest.cc
blob4465510ec38177b48824ef371ad54d380b1b8588
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.
5 #include "base/strings/string_util.h"
6 #include "base/strings/stringprintf.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "content/public/browser/navigation_controller.h"
9 #include "content/public/browser/notification_service.h"
10 #include "content/public/browser/notification_types.h"
11 #include "content/public/browser/web_contents.h"
12 #include "content/public/common/url_constants.h"
13 #include "content/public/test/browser_test_utils.h"
14 #include "content/public/test/content_browser_test.h"
15 #include "content/public/test/content_browser_test_utils.h"
16 #include "content/public/test/test_utils.h"
17 #include "content/shell/browser/shell.h"
18 #include "net/test/embedded_test_server/embedded_test_server.h"
19 #include "net/test/embedded_test_server/http_request.h"
20 #include "net/test/embedded_test_server/http_response.h"
21 #include "testing/gtest/include/gtest/gtest.h"
23 namespace content {
25 namespace {
27 // Handles |request| by serving a response with title set to request contents.
28 scoped_ptr<net::test_server::HttpResponse> HandleEchoTitleRequest(
29 const std::string& echotitle_path,
30 const net::test_server::HttpRequest& request) {
31 if (!StartsWithASCII(request.relative_url, echotitle_path, true))
32 return scoped_ptr<net::test_server::HttpResponse>();
34 scoped_ptr<net::test_server::BasicHttpResponse> http_response(
35 new net::test_server::BasicHttpResponse);
36 http_response->set_code(net::HTTP_OK);
37 http_response->set_content(
38 base::StringPrintf(
39 "<html><head><title>%s</title></head></html>",
40 request.content.c_str()));
41 return http_response.PassAs<net::test_server::HttpResponse>();
44 } // namespace
46 class SessionHistoryTest : public ContentBrowserTest {
47 protected:
48 SessionHistoryTest() {}
50 virtual void SetUpOnMainThread() OVERRIDE {
51 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
52 embedded_test_server()->RegisterRequestHandler(
53 base::Bind(&HandleEchoTitleRequest, "/echotitle"));
55 NavigateToURL(shell(), GURL(url::kAboutBlankURL));
58 // Simulate clicking a link. Only works on the frames.html testserver page.
59 void ClickLink(std::string node_id) {
60 GURL url("javascript:clickLink('" + node_id + "')");
61 NavigateToURL(shell(), url);
64 // Simulate filling in form data. Only works on the frames.html page with
65 // subframe = form.html, and on form.html itself.
66 void FillForm(std::string node_id, std::string value) {
67 GURL url("javascript:fillForm('" + node_id + "', '" + value + "')");
68 // This will return immediately, but since the JS executes synchronously
69 // on the renderer, it will complete before the next navigate message is
70 // processed.
71 NavigateToURL(shell(), url);
74 // Simulate submitting a form. Only works on the frames.html page with
75 // subframe = form.html, and on form.html itself.
76 void SubmitForm(std::string node_id) {
77 GURL url("javascript:submitForm('" + node_id + "')");
78 NavigateToURL(shell(), url);
81 // Navigate session history using history.go(distance).
82 void JavascriptGo(std::string distance) {
83 GURL url("javascript:history.go('" + distance + "')");
84 NavigateToURL(shell(), url);
87 std::string GetTabTitle() {
88 return base::UTF16ToASCII(shell()->web_contents()->GetTitle());
91 GURL GetTabURL() {
92 return shell()->web_contents()->GetLastCommittedURL();
95 GURL GetURL(const std::string file) {
96 return embedded_test_server()->GetURL(
97 std::string("/session_history/") + file);
100 void NavigateAndCheckTitle(const char* filename,
101 const std::string& expected_title) {
102 base::string16 expected_title16(base::ASCIIToUTF16(expected_title));
103 TitleWatcher title_watcher(shell()->web_contents(), expected_title16);
104 NavigateToURL(shell(), GetURL(filename));
105 ASSERT_EQ(expected_title16, title_watcher.WaitAndGetTitle());
108 bool CanGoBack() {
109 return shell()->web_contents()->GetController().CanGoBack();
112 bool CanGoForward() {
113 return shell()->web_contents()->GetController().CanGoForward();
116 void GoBack() {
117 WindowedNotificationObserver load_stop_observer(
118 NOTIFICATION_LOAD_STOP,
119 NotificationService::AllSources());
120 shell()->web_contents()->GetController().GoBack();
121 load_stop_observer.Wait();
124 void GoForward() {
125 WindowedNotificationObserver load_stop_observer(
126 NOTIFICATION_LOAD_STOP,
127 NotificationService::AllSources());
128 shell()->web_contents()->GetController().GoForward();
129 load_stop_observer.Wait();
133 // If this flakes, use http://crbug.com/61619 on windows and
134 // http://crbug.com/102094 on mac.
135 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, BasicBackForward) {
136 ASSERT_FALSE(CanGoBack());
138 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot1.html", "bot1"));
139 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot2.html", "bot2"));
140 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot3.html", "bot3"));
142 // history is [blank, bot1, bot2, *bot3]
144 GoBack();
145 EXPECT_EQ("bot2", GetTabTitle());
147 GoBack();
148 EXPECT_EQ("bot1", GetTabTitle());
150 GoForward();
151 EXPECT_EQ("bot2", GetTabTitle());
153 GoBack();
154 EXPECT_EQ("bot1", GetTabTitle());
156 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot3.html", "bot3"));
158 // history is [blank, bot1, *bot3]
160 ASSERT_FALSE(CanGoForward());
161 EXPECT_EQ("bot3", GetTabTitle());
163 GoBack();
164 EXPECT_EQ("bot1", GetTabTitle());
166 GoBack();
167 EXPECT_EQ(std::string(url::kAboutBlankURL), GetTabTitle());
169 ASSERT_FALSE(CanGoBack());
170 EXPECT_EQ(std::string(url::kAboutBlankURL), GetTabTitle());
172 GoForward();
173 EXPECT_EQ("bot1", GetTabTitle());
175 GoForward();
176 EXPECT_EQ("bot3", GetTabTitle());
179 // Test that back/forward works when navigating in subframes.
180 // If this flakes, use http://crbug.com/48833
181 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, FrameBackForward) {
182 ASSERT_FALSE(CanGoBack());
184 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("frames.html", "bot1"));
186 ClickLink("abot2");
187 EXPECT_EQ("bot2", GetTabTitle());
188 GURL frames(GetURL("frames.html"));
189 EXPECT_EQ(frames, GetTabURL());
191 ClickLink("abot3");
192 EXPECT_EQ("bot3", GetTabTitle());
193 EXPECT_EQ(frames, GetTabURL());
195 // history is [blank, bot1, bot2, *bot3]
197 GoBack();
198 EXPECT_EQ("bot2", GetTabTitle());
199 EXPECT_EQ(frames, GetTabURL());
201 GoBack();
202 EXPECT_EQ("bot1", GetTabTitle());
203 EXPECT_EQ(frames, GetTabURL());
205 GoBack();
206 EXPECT_EQ(std::string(url::kAboutBlankURL), GetTabTitle());
207 EXPECT_EQ(GURL(url::kAboutBlankURL), GetTabURL());
209 GoForward();
210 EXPECT_EQ("bot1", GetTabTitle());
211 EXPECT_EQ(frames, GetTabURL());
213 GoForward();
214 EXPECT_EQ("bot2", GetTabTitle());
215 EXPECT_EQ(frames, GetTabURL());
217 ClickLink("abot1");
218 EXPECT_EQ("bot1", GetTabTitle());
219 EXPECT_EQ(frames, GetTabURL());
221 // history is [blank, bot1, bot2, *bot1]
223 ASSERT_FALSE(CanGoForward());
224 EXPECT_EQ("bot1", GetTabTitle());
225 EXPECT_EQ(frames, GetTabURL());
227 GoBack();
228 EXPECT_EQ("bot2", GetTabTitle());
229 EXPECT_EQ(frames, GetTabURL());
231 GoBack();
232 EXPECT_EQ("bot1", GetTabTitle());
233 EXPECT_EQ(frames, GetTabURL());
236 // Test that back/forward preserves POST data and document state in subframes.
237 // If this flakes use http://crbug.com/61619
238 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, FrameFormBackForward) {
239 ASSERT_FALSE(CanGoBack());
241 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("frames.html", "bot1"));
243 ClickLink("aform");
244 EXPECT_EQ("form", GetTabTitle());
245 GURL frames(GetURL("frames.html"));
246 EXPECT_EQ(frames, GetTabURL());
248 SubmitForm("isubmit");
249 EXPECT_EQ("text=&select=a", GetTabTitle());
250 EXPECT_EQ(frames, GetTabURL());
252 GoBack();
253 EXPECT_EQ("form", GetTabTitle());
254 EXPECT_EQ(frames, GetTabURL());
256 // history is [blank, bot1, *form, post]
258 ClickLink("abot2");
259 EXPECT_EQ("bot2", GetTabTitle());
260 EXPECT_EQ(frames, GetTabURL());
262 // history is [blank, bot1, form, *bot2]
264 GoBack();
265 EXPECT_EQ("form", GetTabTitle());
266 EXPECT_EQ(frames, GetTabURL());
268 SubmitForm("isubmit");
269 EXPECT_EQ("text=&select=a", GetTabTitle());
270 EXPECT_EQ(frames, GetTabURL());
272 // history is [blank, bot1, form, *post]
274 // TODO(mpcomplete): reenable this when WebKit bug 10199 is fixed:
275 // "returning to a POST result within a frame does a GET instead of a POST"
276 ClickLink("abot2");
277 EXPECT_EQ("bot2", GetTabTitle());
278 EXPECT_EQ(frames, GetTabURL());
280 GoBack();
281 EXPECT_EQ("text=&select=a", GetTabTitle());
282 EXPECT_EQ(frames, GetTabURL());
285 // TODO(mpcomplete): enable this when Bug 734372 is fixed:
286 // "Doing a session history navigation does not restore newly-created subframe
287 // document state"
288 // Test that back/forward preserves POST data and document state when navigating
289 // across frames (ie, from frame -> nonframe).
290 // Hangs, see http://crbug.com/45058.
291 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, CrossFrameFormBackForward) {
292 ASSERT_FALSE(CanGoBack());
294 GURL frames(GetURL("frames.html"));
295 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("frames.html", "bot1"));
297 ClickLink("aform");
298 EXPECT_EQ("form", GetTabTitle());
299 EXPECT_EQ(frames, GetTabURL());
301 SubmitForm("isubmit");
302 EXPECT_EQ("text=&select=a", GetTabTitle());
303 EXPECT_EQ(frames, GetTabURL());
305 GoBack();
306 EXPECT_EQ("form", GetTabTitle());
307 EXPECT_EQ(frames, GetTabURL());
309 // history is [blank, bot1, *form, post]
311 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot2.html", "bot2"));
313 // history is [blank, bot1, form, *bot2]
315 GoBack();
316 EXPECT_EQ("bot1", GetTabTitle());
317 EXPECT_EQ(frames, GetTabURL());
319 SubmitForm("isubmit");
320 EXPECT_EQ("text=&select=a", GetTabTitle());
321 EXPECT_EQ(frames, GetTabURL());
324 // Test that back/forward entries are created for reference fragment
325 // navigations. Bug 730379.
326 // If this flakes use http://crbug.com/61619.
327 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, FragmentBackForward) {
328 embedded_test_server()->RegisterRequestHandler(
329 base::Bind(&HandleEchoTitleRequest, "/echotitle"));
331 ASSERT_FALSE(CanGoBack());
333 GURL fragment(GetURL("fragment.html"));
334 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("fragment.html", "fragment"));
336 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("fragment.html#a", "fragment"));
337 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("fragment.html#b", "fragment"));
338 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("fragment.html#c", "fragment"));
340 // history is [blank, fragment, fragment#a, fragment#b, *fragment#c]
342 GoBack();
343 EXPECT_EQ(GetURL("fragment.html#b"), GetTabURL());
345 GoBack();
346 EXPECT_EQ(GetURL("fragment.html#a"), GetTabURL());
348 GoBack();
349 EXPECT_EQ(GetURL("fragment.html"), GetTabURL());
351 GoForward();
352 EXPECT_EQ(GetURL("fragment.html#a"), GetTabURL());
354 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot3.html", "bot3"));
356 // history is [blank, fragment, fragment#a, bot3]
358 ASSERT_FALSE(CanGoForward());
359 EXPECT_EQ(GetURL("bot3.html"), GetTabURL());
361 GoBack();
362 EXPECT_EQ(GetURL("fragment.html#a"), GetTabURL());
364 GoBack();
365 EXPECT_EQ(GetURL("fragment.html"), GetTabURL());
368 // Test that the javascript window.history object works.
369 // NOTE: history.go(N) does not do anything if N is outside the bounds of the
370 // back/forward list (such as trigger our start/stop loading events). This
371 // means the test will hang if it attempts to navigate too far forward or back,
372 // since we'll be waiting forever for a load stop event.
374 // TODO(brettw) bug 50648: fix flakyness. This test seems like it was failing
375 // about 1/4 of the time on Vista by failing to execute JavascriptGo (see bug).
376 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, JavascriptHistory) {
377 ASSERT_FALSE(CanGoBack());
379 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot1.html", "bot1"));
380 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot2.html", "bot2"));
381 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot3.html", "bot3"));
383 // history is [blank, bot1, bot2, *bot3]
385 JavascriptGo("-1");
386 EXPECT_EQ("bot2", GetTabTitle());
388 JavascriptGo("-1");
389 EXPECT_EQ("bot1", GetTabTitle());
391 JavascriptGo("1");
392 EXPECT_EQ("bot2", GetTabTitle());
394 JavascriptGo("-1");
395 EXPECT_EQ("bot1", GetTabTitle());
397 JavascriptGo("2");
398 EXPECT_EQ("bot3", GetTabTitle());
400 // history is [blank, bot1, bot2, *bot3]
402 JavascriptGo("-3");
403 EXPECT_EQ(std::string(url::kAboutBlankURL), GetTabTitle());
405 ASSERT_FALSE(CanGoBack());
406 EXPECT_EQ(std::string(url::kAboutBlankURL), GetTabTitle());
408 JavascriptGo("1");
409 EXPECT_EQ("bot1", GetTabTitle());
411 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot3.html", "bot3"));
413 // history is [blank, bot1, *bot3]
415 ASSERT_FALSE(CanGoForward());
416 EXPECT_EQ("bot3", GetTabTitle());
418 JavascriptGo("-1");
419 EXPECT_EQ("bot1", GetTabTitle());
421 JavascriptGo("-1");
422 EXPECT_EQ(std::string(url::kAboutBlankURL), GetTabTitle());
424 ASSERT_FALSE(CanGoBack());
425 EXPECT_EQ(std::string(url::kAboutBlankURL), GetTabTitle());
427 JavascriptGo("1");
428 EXPECT_EQ("bot1", GetTabTitle());
430 JavascriptGo("1");
431 EXPECT_EQ("bot3", GetTabTitle());
433 // TODO(creis): Test that JavaScript history navigations work across tab
434 // types. For example, load about:network in a tab, then a real page, then
435 // try to go back and forward with JavaScript. Bug 1136715.
436 // (Hard to test right now, because pages like about:network cause the
437 // TabProxy to hang. This is because they do not appear to use the
438 // NotificationService.)
441 // This test is failing consistently. See http://crbug.com/22560
442 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, LocationReplace) {
443 // Test that using location.replace doesn't leave the title of the old page
444 // visible.
445 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle(
446 "replace.html?bot1.html", "bot1"));
449 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, LocationChangeInSubframe) {
450 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle(
451 "location_redirect.html", "Default Title"));
453 NavigateToURL(shell(), GURL("javascript:void(frames[0].navigate())"));
454 EXPECT_EQ("foo", GetTabTitle());
456 GoBack();
457 EXPECT_EQ("Default Title", GetTabTitle());
460 // http://code.google.com/p/chromium/issues/detail?id=56267
461 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, HistoryLength) {
462 int length;
463 ASSERT_TRUE(ExecuteScriptAndExtractInt(
464 shell()->web_contents(),
465 "domAutomationController.send(history.length)",
466 &length));
467 EXPECT_EQ(1, length);
469 NavigateToURL(shell(), GetURL("title1.html"));
471 ASSERT_TRUE(ExecuteScriptAndExtractInt(
472 shell()->web_contents(),
473 "domAutomationController.send(history.length)",
474 &length));
475 EXPECT_EQ(2, length);
477 // Now test that history.length is updated when the navigation is committed.
478 NavigateToURL(shell(), GetURL("record_length.html"));
480 ASSERT_TRUE(ExecuteScriptAndExtractInt(
481 shell()->web_contents(),
482 "domAutomationController.send(history.length)",
483 &length));
484 EXPECT_EQ(3, length);
486 GoBack();
487 GoBack();
489 // Ensure history.length is properly truncated.
490 NavigateToURL(shell(), GetURL("title2.html"));
492 ASSERT_TRUE(ExecuteScriptAndExtractInt(
493 shell()->web_contents(),
494 "domAutomationController.send(history.length)",
495 &length));
496 EXPECT_EQ(2, length);
499 } // namespace content