session_history_uitest.cc revision 3f50c38dc070f4bb515c1b64450dae14f316474e
1// Copyright (c) 2010 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/string_util.h" 6#include "chrome/common/url_constants.h" 7#include "chrome/test/automation/tab_proxy.h" 8#include "chrome/test/automation/browser_proxy.h" 9#include "chrome/test/ui/ui_test.h" 10#include "grit/generated_resources.h" 11#include "net/base/net_util.h" 12#include "net/test/test_server.h" 13 14namespace { 15 16class SessionHistoryTest : public UITest { 17 protected: 18 SessionHistoryTest() 19 : test_server_(net::TestServer::TYPE_HTTP, 20 FilePath(FILE_PATH_LITERAL("chrome/test/data"))) { 21 dom_automation_enabled_ = true; 22 } 23 24 virtual void SetUp() { 25 UITest::SetUp(); 26 27 window_ = automation()->GetBrowserWindow(0); 28 ASSERT_TRUE(window_.get()); 29 30 tab_ = window_->GetActiveTab(); 31 ASSERT_TRUE(tab_.get()); 32 } 33 34 // Simulate clicking a link. Only works on the frames.html testserver page. 35 void ClickLink(std::string node_id) { 36 GURL url("javascript:clickLink('" + node_id + "')"); 37 ASSERT_TRUE(tab_->NavigateToURL(url)); 38 } 39 40 // Simulate filling in form data. Only works on the frames.html page with 41 // subframe = form.html, and on form.html itself. 42 void FillForm(std::string node_id, std::string value) { 43 GURL url("javascript:fillForm('" + node_id + "', '" + value + "')"); 44 // This will return immediately, but since the JS executes synchronously 45 // on the renderer, it will complete before the next navigate message is 46 // processed. 47 ASSERT_TRUE(tab_->NavigateToURLAsync(url)); 48 } 49 50 // Simulate submitting a form. Only works on the frames.html page with 51 // subframe = form.html, and on form.html itself. 52 void SubmitForm(std::string node_id) { 53 GURL url("javascript:submitForm('" + node_id + "')"); 54 ASSERT_TRUE(tab_->NavigateToURL(url)); 55 } 56 57 // Navigate session history using history.go(distance). 58 void JavascriptGo(std::string distance) { 59 GURL url("javascript:history.go('" + distance + "')"); 60 ASSERT_TRUE(tab_->NavigateToURL(url)); 61 } 62 63 std::wstring GetTabTitle() { 64 std::wstring title; 65 EXPECT_TRUE(tab_->GetTabTitle(&title)); 66 return title; 67 } 68 69 GURL GetTabURL() { 70 GURL url; 71 EXPECT_TRUE(tab_->GetCurrentURL(&url)); 72 return url; 73 } 74 75 protected: 76 scoped_refptr<BrowserProxy> window_; 77 scoped_refptr<TabProxy> tab_; 78 79 net::TestServer test_server_; 80}; 81 82#if defined(OS_WIN) 83// See http://crbug.com/61619 84#define MAYBE_BasicBackForward FLAKY_BasicBackForward 85#else 86#define MAYBE_BasicBackForward BasicBackForward 87#endif 88 89TEST_F(SessionHistoryTest, MAYBE_BasicBackForward) { 90 ASSERT_TRUE(test_server_.Start()); 91 92 // about:blank should be loaded first. 93 ASSERT_FALSE(tab_->GoBack()); 94 EXPECT_EQ(L"", GetTabTitle()); 95 96 ASSERT_TRUE(tab_->NavigateToURL( 97 test_server_.GetURL("files/session_history/bot1.html"))); 98 EXPECT_EQ(L"bot1", GetTabTitle()); 99 100 ASSERT_TRUE(tab_->NavigateToURL( 101 test_server_.GetURL("files/session_history/bot2.html"))); 102 EXPECT_EQ(L"bot2", GetTabTitle()); 103 104 ASSERT_TRUE(tab_->NavigateToURL( 105 test_server_.GetURL("files/session_history/bot3.html"))); 106 EXPECT_EQ(L"bot3", GetTabTitle()); 107 108 // history is [blank, bot1, bot2, *bot3] 109 110 ASSERT_TRUE(tab_->GoBack()); 111 EXPECT_EQ(L"bot2", GetTabTitle()); 112 113 ASSERT_TRUE(tab_->GoBack()); 114 EXPECT_EQ(L"bot1", GetTabTitle()); 115 116 ASSERT_TRUE(tab_->GoForward()); 117 EXPECT_EQ(L"bot2", GetTabTitle()); 118 119 ASSERT_TRUE(tab_->GoBack()); 120 EXPECT_EQ(L"bot1", GetTabTitle()); 121 122 ASSERT_TRUE(tab_->NavigateToURL( 123 test_server_.GetURL("files/session_history/bot3.html"))); 124 EXPECT_EQ(L"bot3", GetTabTitle()); 125 126 // history is [blank, bot1, *bot3] 127 128 ASSERT_FALSE(tab_->GoForward()); 129 EXPECT_EQ(L"bot3", GetTabTitle()); 130 131 ASSERT_TRUE(tab_->GoBack()); 132 EXPECT_EQ(L"bot1", GetTabTitle()); 133 134 ASSERT_TRUE(tab_->GoBack()); 135 EXPECT_EQ(L"", GetTabTitle()); 136 137 ASSERT_FALSE(tab_->GoBack()); 138 EXPECT_EQ(L"", GetTabTitle()); 139 140 ASSERT_TRUE(tab_->GoForward()); 141 EXPECT_EQ(L"bot1", GetTabTitle()); 142 143 ASSERT_TRUE(tab_->GoForward()); 144 EXPECT_EQ(L"bot3", GetTabTitle()); 145} 146 147#if defined(OS_WIN) 148// See http://crbug.com/61619 149#define MAYBE_FrameBackForward FLAKY_FrameBackForward 150#else 151#define MAYBE_FrameBackForward FrameBackForward 152#endif 153 154// Test that back/forward works when navigating in subframes. 155TEST_F(SessionHistoryTest, MAYBE_FrameBackForward) { 156 ASSERT_TRUE(test_server_.Start()); 157 158 // about:blank should be loaded first. 159 GURL home(homepage()); 160 ASSERT_FALSE(tab_->GoBack()); 161 EXPECT_EQ(L"", GetTabTitle()); 162 EXPECT_EQ(home, GetTabURL()); 163 164 GURL frames(test_server_.GetURL("files/session_history/frames.html")); 165 ASSERT_TRUE(tab_->NavigateToURL(frames)); 166 EXPECT_EQ(L"bot1", GetTabTitle()); 167 EXPECT_EQ(frames, GetTabURL()); 168 169 ClickLink("abot2"); 170 EXPECT_EQ(L"bot2", GetTabTitle()); 171 EXPECT_EQ(frames, GetTabURL()); 172 173 ClickLink("abot3"); 174 EXPECT_EQ(L"bot3", GetTabTitle()); 175 EXPECT_EQ(frames, GetTabURL()); 176 177 // history is [blank, bot1, bot2, *bot3] 178 179 ASSERT_TRUE(tab_->GoBack()); 180 EXPECT_EQ(L"bot2", GetTabTitle()); 181 EXPECT_EQ(frames, GetTabURL()); 182 183 ASSERT_TRUE(tab_->GoBack()); 184 EXPECT_EQ(L"bot1", GetTabTitle()); 185 EXPECT_EQ(frames, GetTabURL()); 186 187 ASSERT_TRUE(tab_->GoBack()); 188 EXPECT_EQ(L"", GetTabTitle()); 189 EXPECT_EQ(home, GetTabURL()); 190 191 ASSERT_TRUE(tab_->GoForward()); 192 EXPECT_EQ(L"bot1", GetTabTitle()); 193 EXPECT_EQ(frames, GetTabURL()); 194 195 ASSERT_TRUE(tab_->GoForward()); 196 EXPECT_EQ(L"bot2", GetTabTitle()); 197 EXPECT_EQ(frames, GetTabURL()); 198 199 ClickLink("abot1"); 200 EXPECT_EQ(L"bot1", GetTabTitle()); 201 EXPECT_EQ(frames, GetTabURL()); 202 203 // history is [blank, bot1, bot2, *bot1] 204 205 ASSERT_FALSE(tab_->GoForward()); 206 EXPECT_EQ(L"bot1", GetTabTitle()); 207 EXPECT_EQ(frames, GetTabURL()); 208 209 ASSERT_TRUE(tab_->GoBack()); 210 EXPECT_EQ(L"bot2", GetTabTitle()); 211 EXPECT_EQ(frames, GetTabURL()); 212 213 ASSERT_TRUE(tab_->GoBack()); 214 EXPECT_EQ(L"bot1", GetTabTitle()); 215 EXPECT_EQ(frames, GetTabURL()); 216} 217 218#if defined(OS_WIN) 219// See http://crbug.com/61619 220#define MAYBE_FrameFormBackForward FLAKY_FrameFormBackForward 221#else 222#define MAYBE_FrameFormBackForward FrameFormBackForward 223#endif 224 225// Test that back/forward preserves POST data and document state in subframes. 226TEST_F(SessionHistoryTest, MAYBE_FrameFormBackForward) { 227 ASSERT_TRUE(test_server_.Start()); 228 229 // about:blank should be loaded first. 230 ASSERT_FALSE(tab_->GoBack()); 231 EXPECT_EQ(L"", GetTabTitle()); 232 233 GURL frames(test_server_.GetURL("files/session_history/frames.html")); 234 ASSERT_TRUE(tab_->NavigateToURL(frames)); 235 EXPECT_EQ(L"bot1", GetTabTitle()); 236 237 ClickLink("aform"); 238 EXPECT_EQ(L"form", GetTabTitle()); 239 EXPECT_EQ(frames, GetTabURL()); 240 241 SubmitForm("isubmit"); 242 EXPECT_EQ(L"text=&select=a", GetTabTitle()); 243 EXPECT_EQ(frames, GetTabURL()); 244 245 ASSERT_TRUE(tab_->GoBack()); 246 EXPECT_EQ(L"form", GetTabTitle()); 247 EXPECT_EQ(frames, GetTabURL()); 248 249 // history is [blank, bot1, *form, post] 250 251 ClickLink("abot2"); 252 EXPECT_EQ(L"bot2", GetTabTitle()); 253 EXPECT_EQ(frames, GetTabURL()); 254 255 // history is [blank, bot1, form, *bot2] 256 257 ASSERT_TRUE(tab_->GoBack()); 258 EXPECT_EQ(L"form", GetTabTitle()); 259 EXPECT_EQ(frames, GetTabURL()); 260 261 SubmitForm("isubmit"); 262 EXPECT_EQ(L"text=&select=a", GetTabTitle()); 263 EXPECT_EQ(frames, GetTabURL()); 264 265 // history is [blank, bot1, form, *post] 266 267 if (false) { 268 // TODO(mpcomplete): reenable this when WebKit bug 10199 is fixed: 269 // "returning to a POST result within a frame does a GET instead of a POST" 270 ClickLink("abot2"); 271 EXPECT_EQ(L"bot2", GetTabTitle()); 272 EXPECT_EQ(frames, GetTabURL()); 273 274 ASSERT_TRUE(tab_->GoBack()); 275 EXPECT_EQ(L"text=&select=a", GetTabTitle()); 276 EXPECT_EQ(frames, GetTabURL()); 277 } 278} 279 280// TODO(mpcomplete): enable this when Bug 734372 is fixed: 281// "Doing a session history navigation does not restore newly-created subframe 282// document state" 283// Test that back/forward preserves POST data and document state when navigating 284// across frames (ie, from frame -> nonframe). 285// Hangs, see http://crbug.com/45058. 286TEST_F(SessionHistoryTest, DISABLED_CrossFrameFormBackForward) { 287 ASSERT_TRUE(test_server_.Start()); 288 289 // about:blank should be loaded first. 290 ASSERT_FALSE(tab_->GoBack()); 291 EXPECT_EQ(L"", GetTabTitle()); 292 293 GURL frames(test_server_.GetURL("files/session_history/frames.html")); 294 ASSERT_TRUE(tab_->NavigateToURL(frames)); 295 EXPECT_EQ(L"bot1", GetTabTitle()); 296 297 ClickLink("aform"); 298 EXPECT_EQ(L"form", GetTabTitle()); 299 EXPECT_EQ(frames, GetTabURL()); 300 301 SubmitForm("isubmit"); 302 EXPECT_EQ(L"text=&select=a", GetTabTitle()); 303 EXPECT_EQ(frames, GetTabURL()); 304 305 ASSERT_TRUE(tab_->GoBack()); 306 EXPECT_EQ(L"form", GetTabTitle()); 307 EXPECT_EQ(frames, GetTabURL()); 308 309 // history is [blank, bot1, *form, post] 310 311 // ClickLink(L"abot2"); 312 GURL bot2("files/session_history/bot2.html"); 313 ASSERT_TRUE(tab_->NavigateToURL(bot2)); 314 EXPECT_EQ(L"bot2", GetTabTitle()); 315 EXPECT_EQ(bot2, GetTabURL()); 316 317 // history is [blank, bot1, form, *bot2] 318 319 ASSERT_TRUE(tab_->GoBack()); 320 EXPECT_EQ(L"form", GetTabTitle()); 321 EXPECT_EQ(frames, GetTabURL()); 322 323 SubmitForm("isubmit"); 324 EXPECT_EQ(L"text=&select=a", GetTabTitle()); 325 EXPECT_EQ(frames, GetTabURL()); 326} 327 328 329#if defined(OS_WIN) 330// See http://crbug.com/61619 331#define MAYBE_FragmentBackForward FLAKY_FragmentBackForward 332#else 333#define MAYBE_FragmentBackForward FragmentBackForward 334#endif 335 336// Test that back/forward entries are created for reference fragment 337// navigations. Bug 730379. 338TEST_F(SessionHistoryTest, MAYBE_FragmentBackForward) { 339 ASSERT_TRUE(test_server_.Start()); 340 341 // about:blank should be loaded first. 342 ASSERT_FALSE(tab_->GoBack()); 343 EXPECT_EQ(L"", GetTabTitle()); 344 345 GURL fragment(test_server_.GetURL("files/session_history/fragment.html")); 346 ASSERT_TRUE(tab_->NavigateToURL(fragment)); 347 EXPECT_EQ(L"fragment", GetTabTitle()); 348 EXPECT_EQ(fragment, GetTabURL()); 349 350 GURL::Replacements ref_params; 351 352 ref_params.SetRef("a", url_parse::Component(0, 1)); 353 GURL fragment_a(fragment.ReplaceComponents(ref_params)); 354 ASSERT_TRUE(tab_->NavigateToURL(fragment_a)); 355 EXPECT_EQ(L"fragment", GetTabTitle()); 356 EXPECT_EQ(fragment_a, GetTabURL()); 357 358 ref_params.SetRef("b", url_parse::Component(0, 1)); 359 GURL fragment_b(fragment.ReplaceComponents(ref_params)); 360 ASSERT_TRUE(tab_->NavigateToURL(fragment_b)); 361 EXPECT_EQ(L"fragment", GetTabTitle()); 362 EXPECT_EQ(fragment_b, GetTabURL()); 363 364 ref_params.SetRef("c", url_parse::Component(0, 1)); 365 GURL fragment_c(fragment.ReplaceComponents(ref_params)); 366 ASSERT_TRUE(tab_->NavigateToURL(fragment_c)); 367 EXPECT_EQ(L"fragment", GetTabTitle()); 368 EXPECT_EQ(fragment_c, GetTabURL()); 369 370 // history is [blank, fragment, fragment#a, fragment#b, *fragment#c] 371 372 ASSERT_TRUE(tab_->GoBack()); 373 EXPECT_EQ(fragment_b, GetTabURL()); 374 375 ASSERT_TRUE(tab_->GoBack()); 376 EXPECT_EQ(fragment_a, GetTabURL()); 377 378 ASSERT_TRUE(tab_->GoBack()); 379 EXPECT_EQ(fragment, GetTabURL()); 380 381 ASSERT_TRUE(tab_->GoForward()); 382 EXPECT_EQ(fragment_a, GetTabURL()); 383 384 GURL bot3(test_server_.GetURL("files/session_history/bot3.html")); 385 ASSERT_TRUE(tab_->NavigateToURL(bot3)); 386 EXPECT_EQ(L"bot3", GetTabTitle()); 387 EXPECT_EQ(bot3, GetTabURL()); 388 389 // history is [blank, fragment, fragment#a, bot3] 390 391 ASSERT_FALSE(tab_->GoForward()); 392 EXPECT_EQ(bot3, GetTabURL()); 393 394 ASSERT_TRUE(tab_->GoBack()); 395 EXPECT_EQ(fragment_a, GetTabURL()); 396 397 ASSERT_TRUE(tab_->GoBack()); 398 EXPECT_EQ(fragment, GetTabURL()); 399} 400 401// Test that the javascript window.history object works. 402// NOTE: history.go(N) does not do anything if N is outside the bounds of the 403// back/forward list (such as trigger our start/stop loading events). This 404// means the test will hang if it attempts to navigate too far forward or back, 405// since we'll be waiting forever for a load stop event. 406// 407// TODO(brettw) bug 50648: fix flakyness. This test seems like it was failing 408// about 1/4 of the time on Vista by failing to execute JavascriptGo (see bug). 409TEST_F(SessionHistoryTest, FLAKY_JavascriptHistory) { 410 ASSERT_TRUE(test_server_.Start()); 411 412 // about:blank should be loaded first. 413 ASSERT_FALSE(tab_->GoBack()); 414 EXPECT_EQ(L"", GetTabTitle()); 415 416 ASSERT_TRUE(tab_->NavigateToURL( 417 test_server_.GetURL("files/session_history/bot1.html"))); 418 EXPECT_EQ(L"bot1", GetTabTitle()); 419 420 ASSERT_TRUE(tab_->NavigateToURL( 421 test_server_.GetURL("files/session_history/bot2.html"))); 422 EXPECT_EQ(L"bot2", GetTabTitle()); 423 424 ASSERT_TRUE(tab_->NavigateToURL( 425 test_server_.GetURL("files/session_history/bot3.html"))); 426 EXPECT_EQ(L"bot3", GetTabTitle()); 427 428 // history is [blank, bot1, bot2, *bot3] 429 430 JavascriptGo("-1"); 431 EXPECT_EQ(L"bot2", GetTabTitle()); 432 433 JavascriptGo("-1"); 434 EXPECT_EQ(L"bot1", GetTabTitle()); 435 436 JavascriptGo("1"); 437 EXPECT_EQ(L"bot2", GetTabTitle()); 438 439 JavascriptGo("-1"); 440 EXPECT_EQ(L"bot1", GetTabTitle()); 441 442 JavascriptGo("2"); 443 EXPECT_EQ(L"bot3", GetTabTitle()); 444 445 // history is [blank, bot1, bot2, *bot3] 446 447 JavascriptGo("-3"); 448 EXPECT_EQ(L"", GetTabTitle()); 449 450 ASSERT_FALSE(tab_->GoBack()); 451 EXPECT_EQ(L"", GetTabTitle()); 452 453 JavascriptGo("1"); 454 EXPECT_EQ(L"bot1", GetTabTitle()); 455 456 ASSERT_TRUE(tab_->NavigateToURL( 457 test_server_.GetURL("files/session_history/bot3.html"))); 458 EXPECT_EQ(L"bot3", GetTabTitle()); 459 460 // history is [blank, bot1, *bot3] 461 462 ASSERT_FALSE(tab_->GoForward()); 463 EXPECT_EQ(L"bot3", GetTabTitle()); 464 465 JavascriptGo("-1"); 466 EXPECT_EQ(L"bot1", GetTabTitle()); 467 468 JavascriptGo("-1"); 469 EXPECT_EQ(L"", GetTabTitle()); 470 471 ASSERT_FALSE(tab_->GoBack()); 472 EXPECT_EQ(L"", GetTabTitle()); 473 474 JavascriptGo("1"); 475 EXPECT_EQ(L"bot1", GetTabTitle()); 476 477 JavascriptGo("1"); 478 EXPECT_EQ(L"bot3", GetTabTitle()); 479 480 // TODO(creis): Test that JavaScript history navigations work across tab 481 // types. For example, load about:network in a tab, then a real page, then 482 // try to go back and forward with JavaScript. Bug 1136715. 483 // (Hard to test right now, because pages like about:network cause the 484 // TabProxy to hang. This is because they do not appear to use the 485 // NotificationService.) 486} 487 488// This test is failing consistently. See http://crbug.com/22560 489TEST_F(SessionHistoryTest, FAILS_LocationReplace) { 490 ASSERT_TRUE(test_server_.Start()); 491 492 // Test that using location.replace doesn't leave the title of the old page 493 // visible. 494 ASSERT_TRUE(tab_->NavigateToURL(test_server_.GetURL( 495 "files/session_history/replace.html?no-title.html"))); 496 EXPECT_EQ(L"", GetTabTitle()); 497} 498 499// This test is flaky. See bug 22111. 500TEST_F(SessionHistoryTest, FLAKY_HistorySearchXSS) { 501 // about:blank should be loaded first. 502 ASSERT_FALSE(tab_->GoBack()); 503 EXPECT_EQ(L"", GetTabTitle()); 504 505 GURL url(std::string(chrome::kChromeUIHistoryURL) + 506 "#q=%3Cimg%20src%3Dx%3Ax%20onerror%3D%22document.title%3D'XSS'%22%3E"); 507 ASSERT_TRUE(tab_->NavigateToURL(url)); 508 // Mainly, this is to ensure we send a synchronous message to the renderer 509 // so that we're not susceptible (less susceptible?) to a race condition. 510 // Should a race condition ever trigger, it won't result in flakiness. 511 int num = tab_->FindInPage(L"<img", FWD, CASE_SENSITIVE, false, NULL); 512 EXPECT_GT(num, 0); 513 EXPECT_EQ(L"History", GetTabTitle()); 514} 515 516#if defined(OS_WIN) 517// See http://crbug.com/61619 518#define MAYBE_LocationChangeInSubframe FLAKY_LocationChangeInSubframe 519#else 520#define MAYBE_LocationChangeInSubframe LocationChangeInSubframe 521#endif 522 523TEST_F(SessionHistoryTest, MAYBE_LocationChangeInSubframe) { 524 ASSERT_TRUE(test_server_.Start()); 525 526 ASSERT_TRUE(tab_->NavigateToURL(test_server_.GetURL( 527 "files/session_history/location_redirect.html"))); 528 EXPECT_EQ(L"Default Title", GetTabTitle()); 529 530 ASSERT_TRUE(tab_->NavigateToURL(GURL( 531 "javascript:void(frames[0].navigate())"))); 532 EXPECT_EQ(L"foo", GetTabTitle()); 533 534 ASSERT_TRUE(tab_->GoBack()); 535 EXPECT_EQ(L"Default Title", GetTabTitle()); 536} 537 538// http://code.google.com/p/chromium/issues/detail?id=56267 539TEST_F(SessionHistoryTest, DISABLED_HistoryLength) { 540 ASSERT_TRUE(test_server_.Start()); 541 542 int length; 543 ASSERT_TRUE(tab_->ExecuteAndExtractInt( 544 L"", L"domAutomationController.send(history.length)", &length)); 545 EXPECT_EQ(1, length); 546 547 ASSERT_TRUE(tab_->NavigateToURL(test_server_.GetURL("files/title1.html"))); 548 549 ASSERT_TRUE(tab_->ExecuteAndExtractInt( 550 L"", L"domAutomationController.send(history.length)", &length)); 551 EXPECT_EQ(2, length); 552 553 // Now test that history.length is updated when the navigation is committed. 554 ASSERT_TRUE(tab_->NavigateToURL(test_server_.GetURL( 555 "files/session_history/record_length.html"))); 556 ASSERT_TRUE(tab_->ExecuteAndExtractInt( 557 L"", L"domAutomationController.send(history.length)", &length)); 558 EXPECT_EQ(3, length); 559 ASSERT_TRUE(tab_->ExecuteAndExtractInt( 560 L"", L"domAutomationController.send(history_length)", &length)); 561 EXPECT_EQ(3, length); 562 563 ASSERT_TRUE(tab_->GoBack()); 564 ASSERT_TRUE(tab_->GoBack()); 565 566 // Ensure history.length is properly truncated. 567 ASSERT_TRUE(tab_->NavigateToURL(test_server_.GetURL("files/title2.html"))); 568 ASSERT_TRUE(tab_->ExecuteAndExtractInt( 569 L"", L"domAutomationController.send(history.length)", &length)); 570 EXPECT_EQ(2, length); 571} 572 573} // namespace 574