diff options
Diffstat (limited to 'chromium/content/browser/session_history_browsertest.cc')
-rw-r--r-- | chromium/content/browser/session_history_browsertest.cc | 499 |
1 files changed, 499 insertions, 0 deletions
diff --git a/chromium/content/browser/session_history_browsertest.cc b/chromium/content/browser/session_history_browsertest.cc new file mode 100644 index 00000000000..966ccc7d941 --- /dev/null +++ b/chromium/content/browser/session_history_browsertest.cc @@ -0,0 +1,499 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" +#include "content/public/browser/navigation_controller.h" +#include "content/public/browser/notification_service.h" +#include "content/public/browser/notification_types.h" +#include "content/public/browser/web_contents.h" +#include "content/public/common/url_constants.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/test_utils.h" +#include "content/shell/shell.h" +#include "content/test/content_browser_test.h" +#include "content/test/content_browser_test_utils.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "net/test/embedded_test_server/http_request.h" +#include "net/test/embedded_test_server/http_response.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace content { + +namespace { + +// Handles |request| by serving a response with title set to request contents. +scoped_ptr<net::test_server::HttpResponse> HandleEchoTitleRequest( + const std::string& echotitle_path, + const net::test_server::HttpRequest& request) { + if (!StartsWithASCII(request.relative_url, echotitle_path, true)) + return scoped_ptr<net::test_server::HttpResponse>(); + + scoped_ptr<net::test_server::BasicHttpResponse> http_response( + new net::test_server::BasicHttpResponse); + http_response->set_code(net::HTTP_OK); + http_response->set_content( + base::StringPrintf( + "<html><head><title>%s</title></head></html>", + request.content.c_str())); + return http_response.PassAs<net::test_server::HttpResponse>(); +} + +} // namespace + +class SessionHistoryTest : public ContentBrowserTest { + protected: + SessionHistoryTest() {} + + virtual void SetUpOnMainThread() OVERRIDE { + ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + embedded_test_server()->RegisterRequestHandler( + base::Bind(&HandleEchoTitleRequest, "/echotitle")); + + NavigateToURL(shell(), GURL(kAboutBlankURL)); + } + + // Simulate clicking a link. Only works on the frames.html testserver page. + void ClickLink(std::string node_id) { + GURL url("javascript:clickLink('" + node_id + "')"); + NavigateToURL(shell(), url); + } + + // Simulate filling in form data. Only works on the frames.html page with + // subframe = form.html, and on form.html itself. + void FillForm(std::string node_id, std::string value) { + GURL url("javascript:fillForm('" + node_id + "', '" + value + "')"); + // This will return immediately, but since the JS executes synchronously + // on the renderer, it will complete before the next navigate message is + // processed. + NavigateToURL(shell(), url); + } + + // Simulate submitting a form. Only works on the frames.html page with + // subframe = form.html, and on form.html itself. + void SubmitForm(std::string node_id) { + GURL url("javascript:submitForm('" + node_id + "')"); + NavigateToURL(shell(), url); + } + + // Navigate session history using history.go(distance). + void JavascriptGo(std::string distance) { + GURL url("javascript:history.go('" + distance + "')"); + NavigateToURL(shell(), url); + } + + std::string GetTabTitle() { + return UTF16ToASCII(shell()->web_contents()->GetTitle()); + } + + GURL GetTabURL() { + return shell()->web_contents()->GetLastCommittedURL(); + } + + GURL GetURL(const std::string file) { + return embedded_test_server()->GetURL( + std::string("/session_history/") + file); + } + + void NavigateAndCheckTitle(const char* filename, + const std::string& expected_title) { + string16 expected_title16(ASCIIToUTF16(expected_title)); + TitleWatcher title_watcher(shell()->web_contents(), expected_title16); + NavigateToURL(shell(), GetURL(filename)); + ASSERT_EQ(expected_title16, title_watcher.WaitAndGetTitle()); + } + + bool CanGoBack() { + return shell()->web_contents()->GetController().CanGoBack(); + } + + bool CanGoForward() { + return shell()->web_contents()->GetController().CanGoForward(); + } + + void GoBack() { + WindowedNotificationObserver load_stop_observer( + NOTIFICATION_LOAD_STOP, + NotificationService::AllSources()); + shell()->web_contents()->GetController().GoBack(); + load_stop_observer.Wait(); + } + + void GoForward() { + WindowedNotificationObserver load_stop_observer( + NOTIFICATION_LOAD_STOP, + NotificationService::AllSources()); + shell()->web_contents()->GetController().GoForward(); + load_stop_observer.Wait(); + } +}; + +// If this flakes, use http://crbug.com/61619 on windows and +// http://crbug.com/102094 on mac. +IN_PROC_BROWSER_TEST_F(SessionHistoryTest, BasicBackForward) { + ASSERT_FALSE(CanGoBack()); + + ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot1.html", "bot1")); + ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot2.html", "bot2")); + ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot3.html", "bot3")); + + // history is [blank, bot1, bot2, *bot3] + + GoBack(); + EXPECT_EQ("bot2", GetTabTitle()); + + GoBack(); + EXPECT_EQ("bot1", GetTabTitle()); + + GoForward(); + EXPECT_EQ("bot2", GetTabTitle()); + + GoBack(); + EXPECT_EQ("bot1", GetTabTitle()); + + ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot3.html", "bot3")); + + // history is [blank, bot1, *bot3] + + ASSERT_FALSE(CanGoForward()); + EXPECT_EQ("bot3", GetTabTitle()); + + GoBack(); + EXPECT_EQ("bot1", GetTabTitle()); + + GoBack(); + EXPECT_EQ(std::string(kAboutBlankURL), GetTabTitle()); + + ASSERT_FALSE(CanGoBack()); + EXPECT_EQ(std::string(kAboutBlankURL), GetTabTitle()); + + GoForward(); + EXPECT_EQ("bot1", GetTabTitle()); + + GoForward(); + EXPECT_EQ("bot3", GetTabTitle()); +} + +// Test that back/forward works when navigating in subframes. +// If this flakes, use http://crbug.com/48833 +IN_PROC_BROWSER_TEST_F(SessionHistoryTest, FrameBackForward) { + ASSERT_FALSE(CanGoBack()); + + ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("frames.html", "bot1")); + + ClickLink("abot2"); + EXPECT_EQ("bot2", GetTabTitle()); + GURL frames(GetURL("frames.html")); + EXPECT_EQ(frames, GetTabURL()); + + ClickLink("abot3"); + EXPECT_EQ("bot3", GetTabTitle()); + EXPECT_EQ(frames, GetTabURL()); + + // history is [blank, bot1, bot2, *bot3] + + GoBack(); + EXPECT_EQ("bot2", GetTabTitle()); + EXPECT_EQ(frames, GetTabURL()); + + GoBack(); + EXPECT_EQ("bot1", GetTabTitle()); + EXPECT_EQ(frames, GetTabURL()); + + GoBack(); + EXPECT_EQ(std::string(kAboutBlankURL), GetTabTitle()); + EXPECT_EQ(GURL(kAboutBlankURL), GetTabURL()); + + GoForward(); + EXPECT_EQ("bot1", GetTabTitle()); + EXPECT_EQ(frames, GetTabURL()); + + GoForward(); + EXPECT_EQ("bot2", GetTabTitle()); + EXPECT_EQ(frames, GetTabURL()); + + ClickLink("abot1"); + EXPECT_EQ("bot1", GetTabTitle()); + EXPECT_EQ(frames, GetTabURL()); + + // history is [blank, bot1, bot2, *bot1] + + ASSERT_FALSE(CanGoForward()); + EXPECT_EQ("bot1", GetTabTitle()); + EXPECT_EQ(frames, GetTabURL()); + + GoBack(); + EXPECT_EQ("bot2", GetTabTitle()); + EXPECT_EQ(frames, GetTabURL()); + + GoBack(); + EXPECT_EQ("bot1", GetTabTitle()); + EXPECT_EQ(frames, GetTabURL()); +} + +// Test that back/forward preserves POST data and document state in subframes. +// If this flakes use http://crbug.com/61619 +IN_PROC_BROWSER_TEST_F(SessionHistoryTest, FrameFormBackForward) { + ASSERT_FALSE(CanGoBack()); + + ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("frames.html", "bot1")); + + ClickLink("aform"); + EXPECT_EQ("form", GetTabTitle()); + GURL frames(GetURL("frames.html")); + EXPECT_EQ(frames, GetTabURL()); + + SubmitForm("isubmit"); + EXPECT_EQ("text=&select=a", GetTabTitle()); + EXPECT_EQ(frames, GetTabURL()); + + GoBack(); + EXPECT_EQ("form", GetTabTitle()); + EXPECT_EQ(frames, GetTabURL()); + + // history is [blank, bot1, *form, post] + + ClickLink("abot2"); + EXPECT_EQ("bot2", GetTabTitle()); + EXPECT_EQ(frames, GetTabURL()); + + // history is [blank, bot1, form, *bot2] + + GoBack(); + EXPECT_EQ("form", GetTabTitle()); + EXPECT_EQ(frames, GetTabURL()); + + SubmitForm("isubmit"); + EXPECT_EQ("text=&select=a", GetTabTitle()); + EXPECT_EQ(frames, GetTabURL()); + + // history is [blank, bot1, form, *post] + + // TODO(mpcomplete): reenable this when WebKit bug 10199 is fixed: + // "returning to a POST result within a frame does a GET instead of a POST" + ClickLink("abot2"); + EXPECT_EQ("bot2", GetTabTitle()); + EXPECT_EQ(frames, GetTabURL()); + + GoBack(); + EXPECT_EQ("text=&select=a", GetTabTitle()); + EXPECT_EQ(frames, GetTabURL()); +} + +// TODO(mpcomplete): enable this when Bug 734372 is fixed: +// "Doing a session history navigation does not restore newly-created subframe +// document state" +// Test that back/forward preserves POST data and document state when navigating +// across frames (ie, from frame -> nonframe). +// Hangs, see http://crbug.com/45058. +IN_PROC_BROWSER_TEST_F(SessionHistoryTest, CrossFrameFormBackForward) { + ASSERT_FALSE(CanGoBack()); + + GURL frames(GetURL("frames.html")); + ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("frames.html", "bot1")); + + ClickLink("aform"); + EXPECT_EQ("form", GetTabTitle()); + EXPECT_EQ(frames, GetTabURL()); + + SubmitForm("isubmit"); + EXPECT_EQ("text=&select=a", GetTabTitle()); + EXPECT_EQ(frames, GetTabURL()); + + GoBack(); + EXPECT_EQ("form", GetTabTitle()); + EXPECT_EQ(frames, GetTabURL()); + + // history is [blank, bot1, *form, post] + + ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot2.html", "bot2")); + + // history is [blank, bot1, form, *bot2] + + GoBack(); + EXPECT_EQ("bot1", GetTabTitle()); + EXPECT_EQ(frames, GetTabURL()); + + SubmitForm("isubmit"); + EXPECT_EQ("text=&select=a", GetTabTitle()); + EXPECT_EQ(frames, GetTabURL()); +} + +// Test that back/forward entries are created for reference fragment +// navigations. Bug 730379. +// If this flakes use http://crbug.com/61619. +IN_PROC_BROWSER_TEST_F(SessionHistoryTest, FragmentBackForward) { + embedded_test_server()->RegisterRequestHandler( + base::Bind(&HandleEchoTitleRequest, "/echotitle")); + + ASSERT_FALSE(CanGoBack()); + + GURL fragment(GetURL("fragment.html")); + ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("fragment.html", "fragment")); + + ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("fragment.html#a", "fragment")); + ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("fragment.html#b", "fragment")); + ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("fragment.html#c", "fragment")); + + // history is [blank, fragment, fragment#a, fragment#b, *fragment#c] + + GoBack(); + EXPECT_EQ(GetURL("fragment.html#b"), GetTabURL()); + + GoBack(); + EXPECT_EQ(GetURL("fragment.html#a"), GetTabURL()); + + GoBack(); + EXPECT_EQ(GetURL("fragment.html"), GetTabURL()); + + GoForward(); + EXPECT_EQ(GetURL("fragment.html#a"), GetTabURL()); + + ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot3.html", "bot3")); + + // history is [blank, fragment, fragment#a, bot3] + + ASSERT_FALSE(CanGoForward()); + EXPECT_EQ(GetURL("bot3.html"), GetTabURL()); + + GoBack(); + EXPECT_EQ(GetURL("fragment.html#a"), GetTabURL()); + + GoBack(); + EXPECT_EQ(GetURL("fragment.html"), GetTabURL()); +} + +// Test that the javascript window.history object works. +// NOTE: history.go(N) does not do anything if N is outside the bounds of the +// back/forward list (such as trigger our start/stop loading events). This +// means the test will hang if it attempts to navigate too far forward or back, +// since we'll be waiting forever for a load stop event. +// +// TODO(brettw) bug 50648: fix flakyness. This test seems like it was failing +// about 1/4 of the time on Vista by failing to execute JavascriptGo (see bug). +IN_PROC_BROWSER_TEST_F(SessionHistoryTest, JavascriptHistory) { + ASSERT_FALSE(CanGoBack()); + + ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot1.html", "bot1")); + ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot2.html", "bot2")); + ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot3.html", "bot3")); + + // history is [blank, bot1, bot2, *bot3] + + JavascriptGo("-1"); + EXPECT_EQ("bot2", GetTabTitle()); + + JavascriptGo("-1"); + EXPECT_EQ("bot1", GetTabTitle()); + + JavascriptGo("1"); + EXPECT_EQ("bot2", GetTabTitle()); + + JavascriptGo("-1"); + EXPECT_EQ("bot1", GetTabTitle()); + + JavascriptGo("2"); + EXPECT_EQ("bot3", GetTabTitle()); + + // history is [blank, bot1, bot2, *bot3] + + JavascriptGo("-3"); + EXPECT_EQ(std::string(kAboutBlankURL), GetTabTitle()); + + ASSERT_FALSE(CanGoBack()); + EXPECT_EQ(std::string(kAboutBlankURL), GetTabTitle()); + + JavascriptGo("1"); + EXPECT_EQ("bot1", GetTabTitle()); + + ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle("bot3.html", "bot3")); + + // history is [blank, bot1, *bot3] + + ASSERT_FALSE(CanGoForward()); + EXPECT_EQ("bot3", GetTabTitle()); + + JavascriptGo("-1"); + EXPECT_EQ("bot1", GetTabTitle()); + + JavascriptGo("-1"); + EXPECT_EQ(std::string(kAboutBlankURL), GetTabTitle()); + + ASSERT_FALSE(CanGoBack()); + EXPECT_EQ(std::string(kAboutBlankURL), GetTabTitle()); + + JavascriptGo("1"); + EXPECT_EQ("bot1", GetTabTitle()); + + JavascriptGo("1"); + EXPECT_EQ("bot3", GetTabTitle()); + + // TODO(creis): Test that JavaScript history navigations work across tab + // types. For example, load about:network in a tab, then a real page, then + // try to go back and forward with JavaScript. Bug 1136715. + // (Hard to test right now, because pages like about:network cause the + // TabProxy to hang. This is because they do not appear to use the + // NotificationService.) +} + +// This test is failing consistently. See http://crbug.com/22560 +IN_PROC_BROWSER_TEST_F(SessionHistoryTest, LocationReplace) { + // Test that using location.replace doesn't leave the title of the old page + // visible. + ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle( + "replace.html?bot1.html", "bot1")); +} + +IN_PROC_BROWSER_TEST_F(SessionHistoryTest, LocationChangeInSubframe) { + ASSERT_NO_FATAL_FAILURE(NavigateAndCheckTitle( + "location_redirect.html", "Default Title")); + + NavigateToURL(shell(), GURL("javascript:void(frames[0].navigate())")); + EXPECT_EQ("foo", GetTabTitle()); + + GoBack(); + EXPECT_EQ("Default Title", GetTabTitle()); +} + +// http://code.google.com/p/chromium/issues/detail?id=56267 +IN_PROC_BROWSER_TEST_F(SessionHistoryTest, HistoryLength) { + int length; + ASSERT_TRUE(ExecuteScriptAndExtractInt( + shell()->web_contents(), + "domAutomationController.send(history.length)", + &length)); + EXPECT_EQ(1, length); + + NavigateToURL(shell(), GetURL("title1.html")); + + ASSERT_TRUE(ExecuteScriptAndExtractInt( + shell()->web_contents(), + "domAutomationController.send(history.length)", + &length)); + EXPECT_EQ(2, length); + + // Now test that history.length is updated when the navigation is committed. + NavigateToURL(shell(), GetURL("record_length.html")); + + ASSERT_TRUE(ExecuteScriptAndExtractInt( + shell()->web_contents(), + "domAutomationController.send(history.length)", + &length)); + EXPECT_EQ(3, length); + + GoBack(); + GoBack(); + + // Ensure history.length is properly truncated. + NavigateToURL(shell(), GetURL("title2.html")); + + ASSERT_TRUE(ExecuteScriptAndExtractInt( + shell()->web_contents(), + "domAutomationController.send(history.length)", + &length)); + EXPECT_EQ(2, length); +} + +} // namespace content |