1 // Copyright (c) 2011 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 14 namespace { 15 16 class 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 89 TEST_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"about:blank", 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"about:blank", GetTabTitle()); 136 137 ASSERT_FALSE(tab_->GoBack()); 138 EXPECT_EQ(L"about:blank", 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. 155 TEST_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"about:blank", 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"about:blank", 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 // See http://crbug.com/61619 219 // Test that back/forward preserves POST data and document state in subframes. 220 TEST_F(SessionHistoryTest, FLAKY_FrameFormBackForward) { 221 ASSERT_TRUE(test_server_.Start()); 222 223 // about:blank should be loaded first. 224 ASSERT_FALSE(tab_->GoBack()); 225 EXPECT_EQ(L"", GetTabTitle()); 226 227 GURL frames(test_server_.GetURL("files/session_history/frames.html")); 228 ASSERT_TRUE(tab_->NavigateToURL(frames)); 229 EXPECT_EQ(L"bot1", GetTabTitle()); 230 231 ClickLink("aform"); 232 EXPECT_EQ(L"form", GetTabTitle()); 233 EXPECT_EQ(frames, GetTabURL()); 234 235 SubmitForm("isubmit"); 236 EXPECT_EQ(L"text=&select=a", GetTabTitle()); 237 EXPECT_EQ(frames, GetTabURL()); 238 239 ASSERT_TRUE(tab_->GoBack()); 240 EXPECT_EQ(L"form", GetTabTitle()); 241 EXPECT_EQ(frames, GetTabURL()); 242 243 // history is [blank, bot1, *form, post] 244 245 ClickLink("abot2"); 246 EXPECT_EQ(L"bot2", GetTabTitle()); 247 EXPECT_EQ(frames, GetTabURL()); 248 249 // history is [blank, bot1, form, *bot2] 250 251 ASSERT_TRUE(tab_->GoBack()); 252 EXPECT_EQ(L"form", GetTabTitle()); 253 EXPECT_EQ(frames, GetTabURL()); 254 255 SubmitForm("isubmit"); 256 EXPECT_EQ(L"text=&select=a", GetTabTitle()); 257 EXPECT_EQ(frames, GetTabURL()); 258 259 // history is [blank, bot1, form, *post] 260 261 if (false) { 262 // TODO(mpcomplete): reenable this when WebKit bug 10199 is fixed: 263 // "returning to a POST result within a frame does a GET instead of a POST" 264 ClickLink("abot2"); 265 EXPECT_EQ(L"bot2", GetTabTitle()); 266 EXPECT_EQ(frames, GetTabURL()); 267 268 ASSERT_TRUE(tab_->GoBack()); 269 EXPECT_EQ(L"text=&select=a", GetTabTitle()); 270 EXPECT_EQ(frames, GetTabURL()); 271 } 272 } 273 274 // TODO(mpcomplete): enable this when Bug 734372 is fixed: 275 // "Doing a session history navigation does not restore newly-created subframe 276 // document state" 277 // Test that back/forward preserves POST data and document state when navigating 278 // across frames (ie, from frame -> nonframe). 279 // Hangs, see http://crbug.com/45058. 280 TEST_F(SessionHistoryTest, DISABLED_CrossFrameFormBackForward) { 281 ASSERT_TRUE(test_server_.Start()); 282 283 // about:blank should be loaded first. 284 ASSERT_FALSE(tab_->GoBack()); 285 EXPECT_EQ(L"", GetTabTitle()); 286 287 GURL frames(test_server_.GetURL("files/session_history/frames.html")); 288 ASSERT_TRUE(tab_->NavigateToURL(frames)); 289 EXPECT_EQ(L"bot1", GetTabTitle()); 290 291 ClickLink("aform"); 292 EXPECT_EQ(L"form", GetTabTitle()); 293 EXPECT_EQ(frames, GetTabURL()); 294 295 SubmitForm("isubmit"); 296 EXPECT_EQ(L"text=&select=a", GetTabTitle()); 297 EXPECT_EQ(frames, GetTabURL()); 298 299 ASSERT_TRUE(tab_->GoBack()); 300 EXPECT_EQ(L"form", GetTabTitle()); 301 EXPECT_EQ(frames, GetTabURL()); 302 303 // history is [blank, bot1, *form, post] 304 305 // ClickLink(L"abot2"); 306 GURL bot2("files/session_history/bot2.html"); 307 ASSERT_TRUE(tab_->NavigateToURL(bot2)); 308 EXPECT_EQ(L"bot2", GetTabTitle()); 309 EXPECT_EQ(bot2, GetTabURL()); 310 311 // history is [blank, bot1, form, *bot2] 312 313 ASSERT_TRUE(tab_->GoBack()); 314 EXPECT_EQ(L"form", GetTabTitle()); 315 EXPECT_EQ(frames, GetTabURL()); 316 317 SubmitForm("isubmit"); 318 EXPECT_EQ(L"text=&select=a", GetTabTitle()); 319 EXPECT_EQ(frames, GetTabURL()); 320 } 321 322 323 #if defined(OS_WIN) 324 // See http://crbug.com/61619 325 #define MAYBE_FragmentBackForward FLAKY_FragmentBackForward 326 #else 327 #define MAYBE_FragmentBackForward FragmentBackForward 328 #endif 329 330 // Test that back/forward entries are created for reference fragment 331 // navigations. Bug 730379. 332 TEST_F(SessionHistoryTest, MAYBE_FragmentBackForward) { 333 ASSERT_TRUE(test_server_.Start()); 334 335 // about:blank should be loaded first. 336 ASSERT_FALSE(tab_->GoBack()); 337 EXPECT_EQ(L"about:blank", GetTabTitle()); 338 339 GURL fragment(test_server_.GetURL("files/session_history/fragment.html")); 340 ASSERT_TRUE(tab_->NavigateToURL(fragment)); 341 EXPECT_EQ(L"fragment", GetTabTitle()); 342 EXPECT_EQ(fragment, GetTabURL()); 343 344 GURL::Replacements ref_params; 345 346 ref_params.SetRef("a", url_parse::Component(0, 1)); 347 GURL fragment_a(fragment.ReplaceComponents(ref_params)); 348 ASSERT_TRUE(tab_->NavigateToURL(fragment_a)); 349 EXPECT_EQ(L"fragment", GetTabTitle()); 350 EXPECT_EQ(fragment_a, GetTabURL()); 351 352 ref_params.SetRef("b", url_parse::Component(0, 1)); 353 GURL fragment_b(fragment.ReplaceComponents(ref_params)); 354 ASSERT_TRUE(tab_->NavigateToURL(fragment_b)); 355 EXPECT_EQ(L"fragment", GetTabTitle()); 356 EXPECT_EQ(fragment_b, GetTabURL()); 357 358 ref_params.SetRef("c", url_parse::Component(0, 1)); 359 GURL fragment_c(fragment.ReplaceComponents(ref_params)); 360 ASSERT_TRUE(tab_->NavigateToURL(fragment_c)); 361 EXPECT_EQ(L"fragment", GetTabTitle()); 362 EXPECT_EQ(fragment_c, GetTabURL()); 363 364 // history is [blank, fragment, fragment#a, fragment#b, *fragment#c] 365 366 ASSERT_TRUE(tab_->GoBack()); 367 EXPECT_EQ(fragment_b, GetTabURL()); 368 369 ASSERT_TRUE(tab_->GoBack()); 370 EXPECT_EQ(fragment_a, GetTabURL()); 371 372 ASSERT_TRUE(tab_->GoBack()); 373 EXPECT_EQ(fragment, GetTabURL()); 374 375 ASSERT_TRUE(tab_->GoForward()); 376 EXPECT_EQ(fragment_a, GetTabURL()); 377 378 GURL bot3(test_server_.GetURL("files/session_history/bot3.html")); 379 ASSERT_TRUE(tab_->NavigateToURL(bot3)); 380 EXPECT_EQ(L"bot3", GetTabTitle()); 381 EXPECT_EQ(bot3, GetTabURL()); 382 383 // history is [blank, fragment, fragment#a, bot3] 384 385 ASSERT_FALSE(tab_->GoForward()); 386 EXPECT_EQ(bot3, GetTabURL()); 387 388 ASSERT_TRUE(tab_->GoBack()); 389 EXPECT_EQ(fragment_a, GetTabURL()); 390 391 ASSERT_TRUE(tab_->GoBack()); 392 EXPECT_EQ(fragment, GetTabURL()); 393 } 394 395 // Test that the javascript window.history object works. 396 // NOTE: history.go(N) does not do anything if N is outside the bounds of the 397 // back/forward list (such as trigger our start/stop loading events). This 398 // means the test will hang if it attempts to navigate too far forward or back, 399 // since we'll be waiting forever for a load stop event. 400 // 401 // TODO(brettw) bug 50648: fix flakyness. This test seems like it was failing 402 // about 1/4 of the time on Vista by failing to execute JavascriptGo (see bug). 403 TEST_F(SessionHistoryTest, FLAKY_JavascriptHistory) { 404 ASSERT_TRUE(test_server_.Start()); 405 406 // about:blank should be loaded first. 407 ASSERT_FALSE(tab_->GoBack()); 408 EXPECT_EQ(L"about:blank", GetTabTitle()); 409 410 ASSERT_TRUE(tab_->NavigateToURL( 411 test_server_.GetURL("files/session_history/bot1.html"))); 412 EXPECT_EQ(L"bot1", GetTabTitle()); 413 414 ASSERT_TRUE(tab_->NavigateToURL( 415 test_server_.GetURL("files/session_history/bot2.html"))); 416 EXPECT_EQ(L"bot2", GetTabTitle()); 417 418 ASSERT_TRUE(tab_->NavigateToURL( 419 test_server_.GetURL("files/session_history/bot3.html"))); 420 EXPECT_EQ(L"bot3", GetTabTitle()); 421 422 // history is [blank, bot1, bot2, *bot3] 423 424 JavascriptGo("-1"); 425 EXPECT_EQ(L"bot2", GetTabTitle()); 426 427 JavascriptGo("-1"); 428 EXPECT_EQ(L"bot1", GetTabTitle()); 429 430 JavascriptGo("1"); 431 EXPECT_EQ(L"bot2", GetTabTitle()); 432 433 JavascriptGo("-1"); 434 EXPECT_EQ(L"bot1", GetTabTitle()); 435 436 JavascriptGo("2"); 437 EXPECT_EQ(L"bot3", GetTabTitle()); 438 439 // history is [blank, bot1, bot2, *bot3] 440 441 JavascriptGo("-3"); 442 EXPECT_EQ(L"about:blank", GetTabTitle()); 443 444 ASSERT_FALSE(tab_->GoBack()); 445 EXPECT_EQ(L"about:blank", GetTabTitle()); 446 447 JavascriptGo("1"); 448 EXPECT_EQ(L"bot1", GetTabTitle()); 449 450 ASSERT_TRUE(tab_->NavigateToURL( 451 test_server_.GetURL("files/session_history/bot3.html"))); 452 EXPECT_EQ(L"bot3", GetTabTitle()); 453 454 // history is [blank, bot1, *bot3] 455 456 ASSERT_FALSE(tab_->GoForward()); 457 EXPECT_EQ(L"bot3", GetTabTitle()); 458 459 JavascriptGo("-1"); 460 EXPECT_EQ(L"bot1", GetTabTitle()); 461 462 JavascriptGo("-1"); 463 EXPECT_EQ(L"about:blank", GetTabTitle()); 464 465 ASSERT_FALSE(tab_->GoBack()); 466 EXPECT_EQ(L"about:blank", GetTabTitle()); 467 468 JavascriptGo("1"); 469 EXPECT_EQ(L"bot1", GetTabTitle()); 470 471 JavascriptGo("1"); 472 EXPECT_EQ(L"bot3", GetTabTitle()); 473 474 // TODO(creis): Test that JavaScript history navigations work across tab 475 // types. For example, load about:network in a tab, then a real page, then 476 // try to go back and forward with JavaScript. Bug 1136715. 477 // (Hard to test right now, because pages like about:network cause the 478 // TabProxy to hang. This is because they do not appear to use the 479 // NotificationService.) 480 } 481 482 // This test is failing consistently. See http://crbug.com/22560 483 TEST_F(SessionHistoryTest, FAILS_LocationReplace) { 484 ASSERT_TRUE(test_server_.Start()); 485 486 // Test that using location.replace doesn't leave the title of the old page 487 // visible. 488 ASSERT_TRUE(tab_->NavigateToURL(test_server_.GetURL( 489 "files/session_history/replace.html?no-title.html"))); 490 EXPECT_EQ(L"", GetTabTitle()); 491 } 492 493 // This test is flaky. See bug 22111. 494 TEST_F(SessionHistoryTest, FLAKY_HistorySearchXSS) { 495 // about:blank should be loaded first. 496 ASSERT_FALSE(tab_->GoBack()); 497 EXPECT_EQ(L"about:blank", GetTabTitle()); 498 499 GURL url(std::string(chrome::kChromeUIHistoryURL) + 500 "#q=%3Cimg%20src%3Dx%3Ax%20onerror%3D%22document.title%3D'XSS'%22%3E"); 501 ASSERT_TRUE(tab_->NavigateToURL(url)); 502 // Mainly, this is to ensure we send a synchronous message to the renderer 503 // so that we're not susceptible (less susceptible?) to a race condition. 504 // Should a race condition ever trigger, it won't result in flakiness. 505 int num = tab_->FindInPage(L"<img", FWD, CASE_SENSITIVE, false, NULL); 506 EXPECT_GT(num, 0); 507 EXPECT_EQ(L"History", GetTabTitle()); 508 } 509 510 #if defined(OS_WIN) 511 // See http://crbug.com/61619 512 #define MAYBE_LocationChangeInSubframe FLAKY_LocationChangeInSubframe 513 #else 514 #define MAYBE_LocationChangeInSubframe LocationChangeInSubframe 515 #endif 516 517 TEST_F(SessionHistoryTest, MAYBE_LocationChangeInSubframe) { 518 ASSERT_TRUE(test_server_.Start()); 519 520 ASSERT_TRUE(tab_->NavigateToURL(test_server_.GetURL( 521 "files/session_history/location_redirect.html"))); 522 EXPECT_EQ(L"Default Title", GetTabTitle()); 523 524 ASSERT_TRUE(tab_->NavigateToURL(GURL( 525 "javascript:void(frames[0].navigate())"))); 526 EXPECT_EQ(L"foo", GetTabTitle()); 527 528 ASSERT_TRUE(tab_->GoBack()); 529 EXPECT_EQ(L"Default Title", GetTabTitle()); 530 } 531 532 // http://code.google.com/p/chromium/issues/detail?id=56267 533 TEST_F(SessionHistoryTest, DISABLED_HistoryLength) { 534 ASSERT_TRUE(test_server_.Start()); 535 536 int length; 537 ASSERT_TRUE(tab_->ExecuteAndExtractInt( 538 L"", L"domAutomationController.send(history.length)", &length)); 539 EXPECT_EQ(1, length); 540 541 ASSERT_TRUE(tab_->NavigateToURL(test_server_.GetURL("files/title1.html"))); 542 543 ASSERT_TRUE(tab_->ExecuteAndExtractInt( 544 L"", L"domAutomationController.send(history.length)", &length)); 545 EXPECT_EQ(2, length); 546 547 // Now test that history.length is updated when the navigation is committed. 548 ASSERT_TRUE(tab_->NavigateToURL(test_server_.GetURL( 549 "files/session_history/record_length.html"))); 550 ASSERT_TRUE(tab_->ExecuteAndExtractInt( 551 L"", L"domAutomationController.send(history.length)", &length)); 552 EXPECT_EQ(3, length); 553 ASSERT_TRUE(tab_->ExecuteAndExtractInt( 554 L"", L"domAutomationController.send(history_length)", &length)); 555 EXPECT_EQ(3, length); 556 557 ASSERT_TRUE(tab_->GoBack()); 558 ASSERT_TRUE(tab_->GoBack()); 559 560 // Ensure history.length is properly truncated. 561 ASSERT_TRUE(tab_->NavigateToURL(test_server_.GetURL("files/title2.html"))); 562 ASSERT_TRUE(tab_->ExecuteAndExtractInt( 563 L"", L"domAutomationController.send(history.length)", &length)); 564 EXPECT_EQ(2, length); 565 } 566 567 } // namespace 568