Add ICU message format support
[chromium-blink-merge.git] / content / browser / session_history_browsertest.cc
blob6578676ff5bd4ca6e34d43b6ff1ac624dc2231e0
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 (!base::StartsWith(request.relative_url, echotitle_path,
32 base::CompareCase::SENSITIVE))
33 return scoped_ptr<net::test_server::HttpResponse>();
35 scoped_ptr<net::test_server::BasicHttpResponse> http_response(
36 new net::test_server::BasicHttpResponse);
37 http_response->set_code(net::HTTP_OK);
38 http_response->set_content(
39 base::StringPrintf(
40 "<html><head><title>%s</title></head></html>",
41 request.content.c_str()));
42 return http_response.Pass();
45 } // namespace
47 class SessionHistoryTest : public ContentBrowserTest {
48 protected:
49 SessionHistoryTest() {}
51 void SetUpOnMainThread() override {
52 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
53 embedded_test_server()->RegisterRequestHandler(
54 base::Bind(&HandleEchoTitleRequest, "/echotitle"));
56 NavigateToURL(shell(), GURL(url::kAboutBlankURL));
59 // Simulate clicking a link. Only works on the frames.html testserver page.
60 void ClickLink(std::string node_id) {
61 GURL url("javascript:clickLink('" + node_id + "')");
62 NavigateToURL(shell(), url);
65 // Simulate filling in form data. Only works on the frames.html page with
66 // subframe = form.html, and on form.html itself.
67 void FillForm(std::string node_id, std::string value) {
68 GURL url("javascript:fillForm('" + node_id + "', '" + value + "')");
69 // This will return immediately, but since the JS executes synchronously
70 // on the renderer, it will complete before the next navigate message is
71 // processed.
72 NavigateToURL(shell(), url);
75 // Simulate submitting a form. Only works on the frames.html page with
76 // subframe = form.html, and on form.html itself.
77 void SubmitForm(std::string node_id) {
78 GURL url("javascript:submitForm('" + node_id + "')");
79 NavigateToURL(shell(), url);
82 // Navigate session history using history.go(distance).
83 void JavascriptGo(std::string distance) {
84 GURL url("javascript:history.go('" + distance + "')");
85 NavigateToURL(shell(), url);
88 std::string GetTabTitle() {
89 return base::UTF16ToASCII(shell()->web_contents()->GetTitle());
92 GURL GetTabURL() {
93 return shell()->web_contents()->GetLastCommittedURL();
96 GURL GetURL(const std::string file) {
97 return embedded_test_server()->GetURL(
98 std::string("/session_history/") + file);
101 void NavigateAndCheckTitle(const char* filename,
102 const std::string& expected_title) {
103 base::string16 expected_title16(base::ASCIIToUTF16(expected_title));
104 TitleWatcher title_watcher(shell()->web_contents(), expected_title16);
105 NavigateToURL(shell(), GetURL(filename));
106 ASSERT_EQ(expected_title16, title_watcher.WaitAndGetTitle());
109 bool CanGoBack() {
110 return shell()->web_contents()->GetController().CanGoBack();
113 bool CanGoForward() {
114 return shell()->web_contents()->GetController().CanGoForward();
117 void GoBack() {
118 WindowedNotificationObserver load_stop_observer(
119 NOTIFICATION_LOAD_STOP,
120 NotificationService::AllSources());
121 shell()->web_contents()->GetController().GoBack();
122 load_stop_observer.Wait();
125 void GoForward() {
126 WindowedNotificationObserver load_stop_observer(
127 NOTIFICATION_LOAD_STOP,
128 NotificationService::AllSources());
129 shell()->web_contents()->GetController().GoForward();
130 load_stop_observer.Wait();
134 // If this flakes, use http://crbug.com/61619 on windows and
135 // http://crbug.com/102094 on mac.
136 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, BasicBackForward) {
137 ASSERT_FALSE(CanGoBack());
139 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot1.html", "bot1"));
140 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot2.html", "bot2"));
141 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot3.html", "bot3"));
143 // history is [blank, bot1, bot2, *bot3]
145 GoBack();
146 EXPECT_EQ("bot2", GetTabTitle());
148 GoBack();
149 EXPECT_EQ("bot1", GetTabTitle());
151 GoForward();
152 EXPECT_EQ("bot2", GetTabTitle());
154 GoBack();
155 EXPECT_EQ("bot1", GetTabTitle());
157 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot3.html", "bot3"));
159 // history is [blank, bot1, *bot3]
161 ASSERT_FALSE(CanGoForward());
162 EXPECT_EQ("bot3", GetTabTitle());
164 GoBack();
165 EXPECT_EQ("bot1", GetTabTitle());
167 GoBack();
168 EXPECT_EQ(std::string(url::kAboutBlankURL), GetTabTitle());
170 ASSERT_FALSE(CanGoBack());
171 EXPECT_EQ(std::string(url::kAboutBlankURL), GetTabTitle());
173 GoForward();
174 EXPECT_EQ("bot1", GetTabTitle());
176 GoForward();
177 EXPECT_EQ("bot3", GetTabTitle());
180 // Test that back/forward works when navigating in subframes.
181 // If this flakes, use http://crbug.com/48833
182 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, FrameBackForward) {
183 ASSERT_FALSE(CanGoBack());
185 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("frames.html", "bot1"));
187 ClickLink("abot2");
188 EXPECT_EQ("bot2", GetTabTitle());
189 GURL frames(GetURL("frames.html"));
190 EXPECT_EQ(frames, GetTabURL());
192 ClickLink("abot3");
193 EXPECT_EQ("bot3", GetTabTitle());
194 EXPECT_EQ(frames, GetTabURL());
196 // history is [blank, bot1, bot2, *bot3]
198 GoBack();
199 EXPECT_EQ("bot2", GetTabTitle());
200 EXPECT_EQ(frames, GetTabURL());
202 GoBack();
203 EXPECT_EQ("bot1", GetTabTitle());
204 EXPECT_EQ(frames, GetTabURL());
206 GoBack();
207 EXPECT_EQ(std::string(url::kAboutBlankURL), GetTabTitle());
208 EXPECT_EQ(GURL(url::kAboutBlankURL), GetTabURL());
210 GoForward();
211 EXPECT_EQ("bot1", GetTabTitle());
212 EXPECT_EQ(frames, GetTabURL());
214 GoForward();
215 EXPECT_EQ("bot2", GetTabTitle());
216 EXPECT_EQ(frames, GetTabURL());
218 ClickLink("abot1");
219 EXPECT_EQ("bot1", GetTabTitle());
220 EXPECT_EQ(frames, GetTabURL());
222 // history is [blank, bot1, bot2, *bot1]
224 ASSERT_FALSE(CanGoForward());
225 EXPECT_EQ("bot1", GetTabTitle());
226 EXPECT_EQ(frames, GetTabURL());
228 GoBack();
229 EXPECT_EQ("bot2", GetTabTitle());
230 EXPECT_EQ(frames, GetTabURL());
232 GoBack();
233 EXPECT_EQ("bot1", GetTabTitle());
234 EXPECT_EQ(frames, GetTabURL());
237 // Test that back/forward preserves POST data and document state in subframes.
238 // If this flakes use http://crbug.com/61619
239 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, FrameFormBackForward) {
240 ASSERT_FALSE(CanGoBack());
242 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("frames.html", "bot1"));
244 ClickLink("aform");
245 EXPECT_EQ("form", GetTabTitle());
246 GURL frames(GetURL("frames.html"));
247 EXPECT_EQ(frames, GetTabURL());
249 SubmitForm("isubmit");
250 EXPECT_EQ("text=&select=a", GetTabTitle());
251 EXPECT_EQ(frames, GetTabURL());
253 GoBack();
254 EXPECT_EQ("form", GetTabTitle());
255 EXPECT_EQ(frames, GetTabURL());
257 // history is [blank, bot1, *form, post]
259 ClickLink("abot2");
260 EXPECT_EQ("bot2", GetTabTitle());
261 EXPECT_EQ(frames, GetTabURL());
263 // history is [blank, bot1, form, *bot2]
265 GoBack();
266 EXPECT_EQ("form", GetTabTitle());
267 EXPECT_EQ(frames, GetTabURL());
269 SubmitForm("isubmit");
270 EXPECT_EQ("text=&select=a", GetTabTitle());
271 EXPECT_EQ(frames, GetTabURL());
273 // history is [blank, bot1, form, *post]
275 // TODO(mpcomplete): reenable this when WebKit bug 10199 is fixed:
276 // "returning to a POST result within a frame does a GET instead of a POST"
277 ClickLink("abot2");
278 EXPECT_EQ("bot2", GetTabTitle());
279 EXPECT_EQ(frames, GetTabURL());
281 GoBack();
282 EXPECT_EQ("text=&select=a", GetTabTitle());
283 EXPECT_EQ(frames, GetTabURL());
286 // TODO(mpcomplete): enable this when Bug 734372 is fixed:
287 // "Doing a session history navigation does not restore newly-created subframe
288 // document state"
289 // Test that back/forward preserves POST data and document state when navigating
290 // across frames (ie, from frame -> nonframe).
291 // Hangs, see http://crbug.com/45058.
292 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, CrossFrameFormBackForward) {
293 ASSERT_FALSE(CanGoBack());
295 GURL frames(GetURL("frames.html"));
296 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("frames.html", "bot1"));
298 ClickLink("aform");
299 EXPECT_EQ("form", GetTabTitle());
300 EXPECT_EQ(frames, GetTabURL());
302 SubmitForm("isubmit");
303 EXPECT_EQ("text=&select=a", GetTabTitle());
304 EXPECT_EQ(frames, GetTabURL());
306 GoBack();
307 EXPECT_EQ("form", GetTabTitle());
308 EXPECT_EQ(frames, GetTabURL());
310 // history is [blank, bot1, *form, post]
312 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot2.html", "bot2"));
314 // history is [blank, bot1, form, *bot2]
316 GoBack();
317 EXPECT_EQ("bot1", GetTabTitle());
318 EXPECT_EQ(frames, GetTabURL());
320 SubmitForm("isubmit");
321 EXPECT_EQ("text=&select=a", GetTabTitle());
322 EXPECT_EQ(frames, GetTabURL());
325 // Test that back/forward entries are created for reference fragment
326 // navigations. Bug 730379.
327 // If this flakes use http://crbug.com/61619.
328 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, FragmentBackForward) {
329 embedded_test_server()->RegisterRequestHandler(
330 base::Bind(&HandleEchoTitleRequest, "/echotitle"));
332 ASSERT_FALSE(CanGoBack());
334 GURL fragment(GetURL("fragment.html"));
335 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("fragment.html", "fragment"));
337 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("fragment.html#a", "fragment"));
338 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("fragment.html#b", "fragment"));
339 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("fragment.html#c", "fragment"));
341 // history is [blank, fragment, fragment#a, fragment#b, *fragment#c]
343 GoBack();
344 EXPECT_EQ(GetURL("fragment.html#b"), GetTabURL());
346 GoBack();
347 EXPECT_EQ(GetURL("fragment.html#a"), GetTabURL());
349 GoBack();
350 EXPECT_EQ(GetURL("fragment.html"), GetTabURL());
352 GoForward();
353 EXPECT_EQ(GetURL("fragment.html#a"), GetTabURL());
355 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot3.html", "bot3"));
357 // history is [blank, fragment, fragment#a, bot3]
359 ASSERT_FALSE(CanGoForward());
360 EXPECT_EQ(GetURL("bot3.html"), GetTabURL());
362 GoBack();
363 EXPECT_EQ(GetURL("fragment.html#a"), GetTabURL());
365 GoBack();
366 EXPECT_EQ(GetURL("fragment.html"), GetTabURL());
369 // Test that the javascript window.history object works.
370 // NOTE: history.go(N) does not do anything if N is outside the bounds of the
371 // back/forward list (such as trigger our start/stop loading events). This
372 // means the test will hang if it attempts to navigate too far forward or back,
373 // since we'll be waiting forever for a load stop event.
375 // TODO(brettw) bug 50648: fix flakyness. This test seems like it was failing
376 // about 1/4 of the time on Vista by failing to execute JavascriptGo (see bug).
377 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, JavascriptHistory) {
378 ASSERT_FALSE(CanGoBack());
380 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot1.html", "bot1"));
381 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot2.html", "bot2"));
382 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot3.html", "bot3"));
384 // history is [blank, bot1, bot2, *bot3]
386 JavascriptGo("-1");
387 EXPECT_EQ("bot2", GetTabTitle());
389 JavascriptGo("-1");
390 EXPECT_EQ("bot1", GetTabTitle());
392 JavascriptGo("1");
393 EXPECT_EQ("bot2", GetTabTitle());
395 JavascriptGo("-1");
396 EXPECT_EQ("bot1", GetTabTitle());
398 JavascriptGo("2");
399 EXPECT_EQ("bot3", GetTabTitle());
401 // history is [blank, bot1, bot2, *bot3]
403 JavascriptGo("-3");
404 EXPECT_EQ(std::string(url::kAboutBlankURL), GetTabTitle());
406 ASSERT_FALSE(CanGoBack());
407 EXPECT_EQ(std::string(url::kAboutBlankURL), GetTabTitle());
409 JavascriptGo("1");
410 EXPECT_EQ("bot1", GetTabTitle());
412 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot3.html", "bot3"));
414 // history is [blank, bot1, *bot3]
416 ASSERT_FALSE(CanGoForward());
417 EXPECT_EQ("bot3", GetTabTitle());
419 JavascriptGo("-1");
420 EXPECT_EQ("bot1", GetTabTitle());
422 JavascriptGo("-1");
423 EXPECT_EQ(std::string(url::kAboutBlankURL), GetTabTitle());
425 ASSERT_FALSE(CanGoBack());
426 EXPECT_EQ(std::string(url::kAboutBlankURL), GetTabTitle());
428 JavascriptGo("1");
429 EXPECT_EQ("bot1", GetTabTitle());
431 JavascriptGo("1");
432 EXPECT_EQ("bot3", GetTabTitle());
434 // TODO(creis): Test that JavaScript history navigations work across tab
435 // types. For example, load about:network in a tab, then a real page, then
436 // try to go back and forward with JavaScript. Bug 1136715.
437 // (Hard to test right now, because pages like about:network cause the
438 // TabProxy to hang. This is because they do not appear to use the
439 // NotificationService.)
442 // This test is failing consistently. See http://crbug.com/22560
443 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, LocationReplace) {
444 // Test that using location.replace doesn't leave the title of the old page
445 // visible.
446 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle(
447 "replace.html?bot1.html", "bot1"));
450 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, LocationChangeInSubframe) {
451 ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle(
452 "location_redirect.html", "Default Title"));
454 NavigateToURL(shell(), GURL("javascript:void(frames[0].navigate())"));
455 EXPECT_EQ("foo", GetTabTitle());
457 GoBack();
458 EXPECT_EQ("Default Title", GetTabTitle());
461 // http://code.google.com/p/chromium/issues/detail?id=56267
462 IN_PROC_BROWSER_TEST_F(SessionHistoryTest, HistoryLength) {
463 int length;
464 ASSERT_TRUE(ExecuteScriptAndExtractInt(
465 shell()->web_contents(),
466 "domAutomationController.send(history.length)",
467 &length));
468 EXPECT_EQ(1, length);
470 NavigateToURL(shell(), GetURL("title1.html"));
472 ASSERT_TRUE(ExecuteScriptAndExtractInt(
473 shell()->web_contents(),
474 "domAutomationController.send(history.length)",
475 &length));
476 EXPECT_EQ(2, length);
478 // Now test that history.length is updated when the navigation is committed.
479 NavigateToURL(shell(), GetURL("record_length.html"));
481 ASSERT_TRUE(ExecuteScriptAndExtractInt(
482 shell()->web_contents(),
483 "domAutomationController.send(history.length)",
484 &length));
485 EXPECT_EQ(3, length);
487 GoBack();
488 GoBack();
490 // Ensure history.length is properly truncated.
491 NavigateToURL(shell(), GetURL("title2.html"));
493 ASSERT_TRUE(ExecuteScriptAndExtractInt(
494 shell()->web_contents(),
495 "domAutomationController.send(history.length)",
496 &length));
497 EXPECT_EQ(2, length);
500 } // namespace content