| OLD | NEW |
| (Empty) |
| 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/logging.h" | |
| 6 #include "base/utf_string_conversions.h" | |
| 7 #include "chrome/browser/prefs/pref_service.h" | |
| 8 #include "chrome/common/pref_names.h" | |
| 9 #include "chrome/test/base/chrome_render_view_host_test_harness.h" | |
| 10 #include "chrome/test/base/testing_pref_service.h" | |
| 11 #include "chrome/test/base/testing_profile.h" | |
| 12 #include "content/browser/renderer_host/render_view_host.h" | |
| 13 #include "content/browser/renderer_host/render_widget_host_view.h" | |
| 14 #include "content/browser/site_instance.h" | |
| 15 #include "content/browser/tab_contents/interstitial_page.h" | |
| 16 #include "content/browser/tab_contents/navigation_details.h" | |
| 17 #include "content/browser/tab_contents/navigation_entry.h" | |
| 18 #include "content/browser/tab_contents/test_tab_contents.h" | |
| 19 #include "content/common/view_messages.h" | |
| 20 #include "content/public/browser/notification_details.h" | |
| 21 #include "content/public/browser/notification_source.h" | |
| 22 #include "content/public/browser/notification_source.h" | |
| 23 #include "content/public/common/bindings_policy.h" | |
| 24 #include "content/public/common/content_constants.h" | |
| 25 #include "content/public/common/url_constants.h" | |
| 26 #include "content/test/test_browser_thread.h" | |
| 27 #include "testing/gtest/include/gtest/gtest.h" | |
| 28 #include "ui/base/message_box_flags.h" | |
| 29 #include "webkit/glue/webkit_glue.h" | |
| 30 | |
| 31 using content::BrowserThread; | |
| 32 using webkit_glue::PasswordForm; | |
| 33 | |
| 34 class TestInterstitialPage : public InterstitialPage { | |
| 35 public: | |
| 36 enum InterstitialState { | |
| 37 UNDECIDED = 0, // No decision taken yet. | |
| 38 OKED, // Proceed was called. | |
| 39 CANCELED // DontProceed was called. | |
| 40 }; | |
| 41 | |
| 42 class Delegate { | |
| 43 public: | |
| 44 virtual void TestInterstitialPageDeleted( | |
| 45 TestInterstitialPage* interstitial) = 0; | |
| 46 | |
| 47 protected: | |
| 48 virtual ~Delegate() {} | |
| 49 }; | |
| 50 | |
| 51 // IMPORTANT NOTE: if you pass stack allocated values for |state| and | |
| 52 // |deleted| (like all interstitial related tests do at this point), make sure | |
| 53 // to create an instance of the TestInterstitialPageStateGuard class on the | |
| 54 // stack in your test. This will ensure that the TestInterstitialPage states | |
| 55 // are cleared when the test finishes. | |
| 56 // Not doing so will cause stack trashing if your test does not hide the | |
| 57 // interstitial, as in such a case it will be destroyed in the test TearDown | |
| 58 // method and will dereference the |deleted| local variable which by then is | |
| 59 // out of scope. | |
| 60 TestInterstitialPage(TabContents* tab, | |
| 61 bool new_navigation, | |
| 62 const GURL& url, | |
| 63 InterstitialState* state, | |
| 64 bool* deleted) | |
| 65 : InterstitialPage(tab, new_navigation, url), | |
| 66 state_(state), | |
| 67 deleted_(deleted), | |
| 68 command_received_count_(0), | |
| 69 delegate_(NULL) { | |
| 70 *state_ = UNDECIDED; | |
| 71 *deleted_ = false; | |
| 72 } | |
| 73 | |
| 74 virtual ~TestInterstitialPage() { | |
| 75 if (deleted_) | |
| 76 *deleted_ = true; | |
| 77 if (delegate_) | |
| 78 delegate_->TestInterstitialPageDeleted(this); | |
| 79 } | |
| 80 | |
| 81 virtual void DontProceed() { | |
| 82 if (state_) | |
| 83 *state_ = CANCELED; | |
| 84 InterstitialPage::DontProceed(); | |
| 85 } | |
| 86 virtual void Proceed() { | |
| 87 if (state_) | |
| 88 *state_ = OKED; | |
| 89 InterstitialPage::Proceed(); | |
| 90 } | |
| 91 | |
| 92 int command_received_count() const { | |
| 93 return command_received_count_; | |
| 94 } | |
| 95 | |
| 96 void TestDomOperationResponse(const std::string& json_string) { | |
| 97 if (enabled()) | |
| 98 CommandReceived(json_string); | |
| 99 } | |
| 100 | |
| 101 void TestDidNavigate(int page_id, const GURL& url) { | |
| 102 ViewHostMsg_FrameNavigate_Params params; | |
| 103 InitNavigateParams(¶ms, page_id, url, content::PAGE_TRANSITION_TYPED); | |
| 104 DidNavigate(render_view_host(), params); | |
| 105 } | |
| 106 | |
| 107 void TestRenderViewGone(base::TerminationStatus status, int error_code) { | |
| 108 RenderViewGone(render_view_host(), status, error_code); | |
| 109 } | |
| 110 | |
| 111 bool is_showing() const { | |
| 112 return static_cast<TestRenderWidgetHostView*>(render_view_host()->view())-> | |
| 113 is_showing(); | |
| 114 } | |
| 115 | |
| 116 void ClearStates() { | |
| 117 state_ = NULL; | |
| 118 deleted_ = NULL; | |
| 119 delegate_ = NULL; | |
| 120 } | |
| 121 | |
| 122 void set_delegate(Delegate* delegate) { | |
| 123 delegate_ = delegate; | |
| 124 } | |
| 125 | |
| 126 protected: | |
| 127 virtual RenderViewHost* CreateRenderViewHost() { | |
| 128 return new TestRenderViewHost( | |
| 129 SiteInstance::CreateSiteInstance(tab()->browser_context()), | |
| 130 this, MSG_ROUTING_NONE); | |
| 131 } | |
| 132 | |
| 133 virtual TabContentsView* CreateTabContentsView() { return NULL; } | |
| 134 | |
| 135 | |
| 136 virtual void CommandReceived(const std::string& command) { | |
| 137 command_received_count_++; | |
| 138 } | |
| 139 | |
| 140 private: | |
| 141 InterstitialState* state_; | |
| 142 bool* deleted_; | |
| 143 int command_received_count_; | |
| 144 Delegate* delegate_; | |
| 145 }; | |
| 146 | |
| 147 class TestInterstitialPageStateGuard : public TestInterstitialPage::Delegate { | |
| 148 public: | |
| 149 explicit TestInterstitialPageStateGuard( | |
| 150 TestInterstitialPage* interstitial_page) | |
| 151 : interstitial_page_(interstitial_page) { | |
| 152 DCHECK(interstitial_page_); | |
| 153 interstitial_page_->set_delegate(this); | |
| 154 } | |
| 155 ~TestInterstitialPageStateGuard() { | |
| 156 if (interstitial_page_) | |
| 157 interstitial_page_->ClearStates(); | |
| 158 } | |
| 159 | |
| 160 virtual void TestInterstitialPageDeleted(TestInterstitialPage* interstitial) { | |
| 161 DCHECK(interstitial_page_ == interstitial); | |
| 162 interstitial_page_ = NULL; | |
| 163 } | |
| 164 | |
| 165 private: | |
| 166 TestInterstitialPage* interstitial_page_; | |
| 167 }; | |
| 168 | |
| 169 class TabContentsTest : public ChromeRenderViewHostTestHarness { | |
| 170 public: | |
| 171 TabContentsTest() : ui_thread_(BrowserThread::UI, &message_loop_) { | |
| 172 } | |
| 173 | |
| 174 private: | |
| 175 // Supply our own profile so we use the correct profile data. The test harness | |
| 176 // is not supposed to overwrite a profile if it's already created. | |
| 177 virtual void SetUp() { | |
| 178 ChromeRenderViewHostTestHarness::SetUp(); | |
| 179 | |
| 180 // Set some (WebKit) user preferences. | |
| 181 TestingPrefService* pref_services = profile()->GetTestingPrefService(); | |
| 182 #if defined(TOOLKIT_USES_GTK) | |
| 183 pref_services->SetUserPref(prefs::kUsesSystemTheme, | |
| 184 Value::CreateBooleanValue(false)); | |
| 185 #endif | |
| 186 pref_services->SetUserPref(prefs::kDefaultCharset, | |
| 187 Value::CreateStringValue("utf8")); | |
| 188 pref_services->SetUserPref(prefs::kWebKitDefaultFontSize, | |
| 189 Value::CreateIntegerValue(20)); | |
| 190 pref_services->SetUserPref(prefs::kWebKitTextAreasAreResizable, | |
| 191 Value::CreateBooleanValue(false)); | |
| 192 pref_services->SetUserPref(prefs::kWebKitUsesUniversalDetector, | |
| 193 Value::CreateBooleanValue(true)); | |
| 194 pref_services->SetUserPref("webkit.webprefs.foo", | |
| 195 Value::CreateStringValue("bar")); | |
| 196 } | |
| 197 | |
| 198 content::TestBrowserThread ui_thread_; | |
| 199 }; | |
| 200 | |
| 201 // Test to make sure that title updates get stripped of whitespace. | |
| 202 TEST_F(TabContentsTest, UpdateTitle) { | |
| 203 ViewHostMsg_FrameNavigate_Params params; | |
| 204 InitNavigateParams(¶ms, 0, GURL(chrome::kAboutBlankURL), | |
| 205 content::PAGE_TRANSITION_TYPED); | |
| 206 | |
| 207 content::LoadCommittedDetails details; | |
| 208 controller().RendererDidNavigate(params, &details); | |
| 209 | |
| 210 contents()->UpdateTitle(rvh(), 0, ASCIIToUTF16(" Lots O' Whitespace\n"), | |
| 211 base::i18n::LEFT_TO_RIGHT); | |
| 212 EXPECT_EQ(ASCIIToUTF16("Lots O' Whitespace"), contents()->GetTitle()); | |
| 213 } | |
| 214 | |
| 215 // Test view source mode for the new tabs page. | |
| 216 TEST_F(TabContentsTest, NTPViewSource) { | |
| 217 const char kUrl[] = "view-source:chrome://newtab"; | |
| 218 const GURL kGURL(kUrl); | |
| 219 | |
| 220 process()->sink().ClearMessages(); | |
| 221 | |
| 222 controller().LoadURL( | |
| 223 kGURL, content::Referrer(), content::PAGE_TRANSITION_TYPED, | |
| 224 std::string()); | |
| 225 rvh()->delegate()->RenderViewCreated(rvh()); | |
| 226 // Did we get the expected message? | |
| 227 EXPECT_TRUE(process()->sink().GetFirstMessageMatching( | |
| 228 ViewMsg_EnableViewSourceMode::ID)); | |
| 229 | |
| 230 ViewHostMsg_FrameNavigate_Params params; | |
| 231 InitNavigateParams(¶ms, 0, kGURL, content::PAGE_TRANSITION_TYPED); | |
| 232 content::LoadCommittedDetails details; | |
| 233 controller().RendererDidNavigate(params, &details); | |
| 234 // Also check title and url. | |
| 235 EXPECT_EQ(ASCIIToUTF16(kUrl), contents()->GetTitle()); | |
| 236 } | |
| 237 | |
| 238 // Test simple same-SiteInstance navigation. | |
| 239 TEST_F(TabContentsTest, SimpleNavigation) { | |
| 240 TestRenderViewHost* orig_rvh = rvh(); | |
| 241 SiteInstance* instance1 = contents()->GetSiteInstance(); | |
| 242 EXPECT_TRUE(contents()->pending_rvh() == NULL); | |
| 243 | |
| 244 // Navigate to URL | |
| 245 const GURL url("http://www.google.com"); | |
| 246 controller().LoadURL( | |
| 247 url, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 248 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 249 EXPECT_EQ(instance1, orig_rvh->site_instance()); | |
| 250 // Controller's pending entry will have a NULL site instance until we assign | |
| 251 // it in DidNavigate. | |
| 252 EXPECT_TRUE(controller().GetActiveEntry()->site_instance() == NULL); | |
| 253 | |
| 254 // DidNavigate from the page | |
| 255 contents()->TestDidNavigate(orig_rvh, 1, url, content::PAGE_TRANSITION_TYPED); | |
| 256 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 257 EXPECT_EQ(orig_rvh, contents()->render_view_host()); | |
| 258 EXPECT_EQ(instance1, orig_rvh->site_instance()); | |
| 259 // Controller's entry should now have the SiteInstance, or else we won't be | |
| 260 // able to find it later. | |
| 261 EXPECT_EQ(instance1, controller().GetActiveEntry()->site_instance()); | |
| 262 } | |
| 263 | |
| 264 // Test that we reject NavigateToEntry if the url is over content::kMaxURLChars. | |
| 265 TEST_F(TabContentsTest, NavigateToExcessivelyLongURL) { | |
| 266 // Construct a URL that's kMaxURLChars + 1 long of all 'a's. | |
| 267 const GURL url(std::string("http://example.org/").append( | |
| 268 content::kMaxURLChars + 1, 'a')); | |
| 269 | |
| 270 controller().LoadURL( | |
| 271 url, content::Referrer(), content::PAGE_TRANSITION_GENERATED, | |
| 272 std::string()); | |
| 273 EXPECT_TRUE(controller().GetActiveEntry() == NULL); | |
| 274 } | |
| 275 | |
| 276 // Test that navigating across a site boundary creates a new RenderViewHost | |
| 277 // with a new SiteInstance. Going back should do the same. | |
| 278 TEST_F(TabContentsTest, CrossSiteBoundaries) { | |
| 279 contents()->transition_cross_site = true; | |
| 280 TestRenderViewHost* orig_rvh = rvh(); | |
| 281 int orig_rvh_delete_count = 0; | |
| 282 orig_rvh->set_delete_counter(&orig_rvh_delete_count); | |
| 283 SiteInstance* instance1 = contents()->GetSiteInstance(); | |
| 284 | |
| 285 // Navigate to URL. First URL should use first RenderViewHost. | |
| 286 const GURL url("http://www.google.com"); | |
| 287 controller().LoadURL( | |
| 288 url, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 289 contents()->TestDidNavigate(orig_rvh, 1, url, content::PAGE_TRANSITION_TYPED); | |
| 290 | |
| 291 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 292 EXPECT_EQ(orig_rvh, contents()->render_view_host()); | |
| 293 | |
| 294 // Navigate to new site | |
| 295 const GURL url2("http://www.yahoo.com"); | |
| 296 controller().LoadURL( | |
| 297 url2, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 298 EXPECT_TRUE(contents()->cross_navigation_pending()); | |
| 299 TestRenderViewHost* pending_rvh = contents()->pending_rvh(); | |
| 300 int pending_rvh_delete_count = 0; | |
| 301 pending_rvh->set_delete_counter(&pending_rvh_delete_count); | |
| 302 | |
| 303 // Navigations should be suspended in pending_rvh until ShouldCloseACK. | |
| 304 EXPECT_TRUE(pending_rvh->are_navigations_suspended()); | |
| 305 orig_rvh->SendShouldCloseACK(true); | |
| 306 EXPECT_FALSE(pending_rvh->are_navigations_suspended()); | |
| 307 | |
| 308 // DidNavigate from the pending page | |
| 309 contents()->TestDidNavigate( | |
| 310 pending_rvh, 1, url2, content::PAGE_TRANSITION_TYPED); | |
| 311 SiteInstance* instance2 = contents()->GetSiteInstance(); | |
| 312 | |
| 313 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 314 EXPECT_EQ(pending_rvh, contents()->render_view_host()); | |
| 315 EXPECT_NE(instance1, instance2); | |
| 316 EXPECT_TRUE(contents()->pending_rvh() == NULL); | |
| 317 // We keep the original RVH around, swapped out. | |
| 318 EXPECT_TRUE(contents()->render_manager_for_testing()->IsSwappedOut(orig_rvh)); | |
| 319 EXPECT_EQ(orig_rvh_delete_count, 0); | |
| 320 | |
| 321 // Going back should switch SiteInstances again. The first SiteInstance is | |
| 322 // stored in the NavigationEntry, so it should be the same as at the start. | |
| 323 // We should use the same RVH as before, swapping it back in. | |
| 324 controller().GoBack(); | |
| 325 TestRenderViewHost* goback_rvh = contents()->pending_rvh(); | |
| 326 EXPECT_EQ(orig_rvh, goback_rvh); | |
| 327 EXPECT_TRUE(contents()->cross_navigation_pending()); | |
| 328 | |
| 329 // Navigations should be suspended in goback_rvh until ShouldCloseACK. | |
| 330 EXPECT_TRUE(goback_rvh->are_navigations_suspended()); | |
| 331 pending_rvh->SendShouldCloseACK(true); | |
| 332 EXPECT_FALSE(goback_rvh->are_navigations_suspended()); | |
| 333 | |
| 334 // DidNavigate from the back action | |
| 335 contents()->TestDidNavigate( | |
| 336 goback_rvh, 1, url2, content::PAGE_TRANSITION_TYPED); | |
| 337 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 338 EXPECT_EQ(goback_rvh, contents()->render_view_host()); | |
| 339 EXPECT_EQ(instance1, contents()->GetSiteInstance()); | |
| 340 // The pending RVH should now be swapped out, not deleted. | |
| 341 EXPECT_TRUE(contents()->render_manager_for_testing()-> | |
| 342 IsSwappedOut(pending_rvh)); | |
| 343 EXPECT_EQ(pending_rvh_delete_count, 0); | |
| 344 | |
| 345 // Close tab and ensure RVHs are deleted. | |
| 346 DeleteContents(); | |
| 347 EXPECT_EQ(orig_rvh_delete_count, 1); | |
| 348 EXPECT_EQ(pending_rvh_delete_count, 1); | |
| 349 } | |
| 350 | |
| 351 // Test that navigating across a site boundary after a crash creates a new | |
| 352 // RVH without requiring a cross-site transition (i.e., PENDING state). | |
| 353 TEST_F(TabContentsTest, CrossSiteBoundariesAfterCrash) { | |
| 354 contents()->transition_cross_site = true; | |
| 355 TestRenderViewHost* orig_rvh = rvh(); | |
| 356 int orig_rvh_delete_count = 0; | |
| 357 orig_rvh->set_delete_counter(&orig_rvh_delete_count); | |
| 358 SiteInstance* instance1 = contents()->GetSiteInstance(); | |
| 359 | |
| 360 // Navigate to URL. First URL should use first RenderViewHost. | |
| 361 const GURL url("http://www.google.com"); | |
| 362 controller().LoadURL( | |
| 363 url, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 364 contents()->TestDidNavigate(orig_rvh, 1, url, content::PAGE_TRANSITION_TYPED); | |
| 365 | |
| 366 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 367 EXPECT_EQ(orig_rvh, contents()->render_view_host()); | |
| 368 | |
| 369 // Crash the renderer. | |
| 370 orig_rvh->set_render_view_created(false); | |
| 371 | |
| 372 // Navigate to new site. We should not go into PENDING. | |
| 373 const GURL url2("http://www.yahoo.com"); | |
| 374 controller().LoadURL( | |
| 375 url2, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 376 TestRenderViewHost* new_rvh = rvh(); | |
| 377 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 378 EXPECT_TRUE(contents()->pending_rvh() == NULL); | |
| 379 EXPECT_NE(orig_rvh, new_rvh); | |
| 380 EXPECT_EQ(orig_rvh_delete_count, 1); | |
| 381 | |
| 382 // DidNavigate from the new page | |
| 383 contents()->TestDidNavigate(new_rvh, 1, url2, content::PAGE_TRANSITION_TYPED); | |
| 384 SiteInstance* instance2 = contents()->GetSiteInstance(); | |
| 385 | |
| 386 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 387 EXPECT_EQ(new_rvh, rvh()); | |
| 388 EXPECT_NE(instance1, instance2); | |
| 389 EXPECT_TRUE(contents()->pending_rvh() == NULL); | |
| 390 | |
| 391 // Close tab and ensure RVHs are deleted. | |
| 392 DeleteContents(); | |
| 393 EXPECT_EQ(orig_rvh_delete_count, 1); | |
| 394 } | |
| 395 | |
| 396 // Test that opening a new tab in the same SiteInstance and then navigating | |
| 397 // both tabs to a new site will place both tabs in a single SiteInstance. | |
| 398 TEST_F(TabContentsTest, NavigateTwoTabsCrossSite) { | |
| 399 contents()->transition_cross_site = true; | |
| 400 TestRenderViewHost* orig_rvh = rvh(); | |
| 401 SiteInstance* instance1 = contents()->GetSiteInstance(); | |
| 402 | |
| 403 // Navigate to URL. First URL should use first RenderViewHost. | |
| 404 const GURL url("http://www.google.com"); | |
| 405 controller().LoadURL( | |
| 406 url, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 407 contents()->TestDidNavigate(orig_rvh, 1, url, content::PAGE_TRANSITION_TYPED); | |
| 408 | |
| 409 // Open a new tab with the same SiteInstance, navigated to the same site. | |
| 410 TestTabContents contents2(profile(), instance1); | |
| 411 contents2.transition_cross_site = true; | |
| 412 contents2.controller().LoadURL(url, content::Referrer(), | |
| 413 content::PAGE_TRANSITION_TYPED, | |
| 414 std::string()); | |
| 415 // Need this page id to be 2 since the site instance is the same (which is the | |
| 416 // scope of page IDs) and we want to consider this a new page. | |
| 417 contents2.TestDidNavigate( | |
| 418 contents2.render_view_host(), 2, url, content::PAGE_TRANSITION_TYPED); | |
| 419 | |
| 420 // Navigate first tab to a new site | |
| 421 const GURL url2a("http://www.yahoo.com"); | |
| 422 controller().LoadURL( | |
| 423 url2a, content::Referrer(), content::PAGE_TRANSITION_TYPED, | |
| 424 std::string()); | |
| 425 orig_rvh->SendShouldCloseACK(true); | |
| 426 TestRenderViewHost* pending_rvh_a = contents()->pending_rvh(); | |
| 427 contents()->TestDidNavigate( | |
| 428 pending_rvh_a, 1, url2a, content::PAGE_TRANSITION_TYPED); | |
| 429 SiteInstance* instance2a = contents()->GetSiteInstance(); | |
| 430 EXPECT_NE(instance1, instance2a); | |
| 431 | |
| 432 // Navigate second tab to the same site as the first tab | |
| 433 const GURL url2b("http://mail.yahoo.com"); | |
| 434 contents2.controller().LoadURL(url2b, content::Referrer(), | |
| 435 content::PAGE_TRANSITION_TYPED, | |
| 436 std::string()); | |
| 437 TestRenderViewHost* rvh2 = | |
| 438 static_cast<TestRenderViewHost*>(contents2.render_view_host()); | |
| 439 rvh2->SendShouldCloseACK(true); | |
| 440 TestRenderViewHost* pending_rvh_b = contents2.pending_rvh(); | |
| 441 EXPECT_TRUE(pending_rvh_b != NULL); | |
| 442 EXPECT_TRUE(contents2.cross_navigation_pending()); | |
| 443 | |
| 444 // NOTE(creis): We used to be in danger of showing a sad tab page here if the | |
| 445 // second tab hadn't navigated somewhere first (bug 1145430). That case is | |
| 446 // now covered by the CrossSiteBoundariesAfterCrash test. | |
| 447 contents2.TestDidNavigate( | |
| 448 pending_rvh_b, 2, url2b, content::PAGE_TRANSITION_TYPED); | |
| 449 SiteInstance* instance2b = contents2.GetSiteInstance(); | |
| 450 EXPECT_NE(instance1, instance2b); | |
| 451 | |
| 452 // Both tabs should now be in the same SiteInstance. | |
| 453 EXPECT_EQ(instance2a, instance2b); | |
| 454 } | |
| 455 | |
| 456 // Tests that TabContents uses the current URL, not the SiteInstance's site, to | |
| 457 // determine whether a navigation is cross-site. | |
| 458 TEST_F(TabContentsTest, CrossSiteComparesAgainstCurrentPage) { | |
| 459 contents()->transition_cross_site = true; | |
| 460 TestRenderViewHost* orig_rvh = rvh(); | |
| 461 SiteInstance* instance1 = contents()->GetSiteInstance(); | |
| 462 | |
| 463 // Navigate to URL. | |
| 464 const GURL url("http://www.google.com"); | |
| 465 controller().LoadURL( | |
| 466 url, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 467 contents()->TestDidNavigate( | |
| 468 orig_rvh, 1, url, content::PAGE_TRANSITION_TYPED); | |
| 469 | |
| 470 // Open a related tab to a second site. | |
| 471 TestTabContents contents2(profile(), instance1); | |
| 472 contents2.transition_cross_site = true; | |
| 473 const GURL url2("http://www.yahoo.com"); | |
| 474 contents2.controller().LoadURL(url2, content::Referrer(), | |
| 475 content::PAGE_TRANSITION_TYPED, | |
| 476 std::string()); | |
| 477 // The first RVH in contents2 isn't live yet, so we shortcut the cross site | |
| 478 // pending. | |
| 479 TestRenderViewHost* rvh2 = static_cast<TestRenderViewHost*>( | |
| 480 contents2.render_view_host()); | |
| 481 EXPECT_FALSE(contents2.cross_navigation_pending()); | |
| 482 contents2.TestDidNavigate(rvh2, 2, url2, content::PAGE_TRANSITION_TYPED); | |
| 483 SiteInstance* instance2 = contents2.GetSiteInstance(); | |
| 484 EXPECT_NE(instance1, instance2); | |
| 485 EXPECT_FALSE(contents2.cross_navigation_pending()); | |
| 486 | |
| 487 // Simulate a link click in first tab to second site. Doesn't switch | |
| 488 // SiteInstances, because we don't intercept WebKit navigations. | |
| 489 contents()->TestDidNavigate( | |
| 490 orig_rvh, 2, url2, content::PAGE_TRANSITION_TYPED); | |
| 491 SiteInstance* instance3 = contents()->GetSiteInstance(); | |
| 492 EXPECT_EQ(instance1, instance3); | |
| 493 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 494 | |
| 495 // Navigate to the new site. Doesn't switch SiteInstancees, because we | |
| 496 // compare against the current URL, not the SiteInstance's site. | |
| 497 const GURL url3("http://mail.yahoo.com"); | |
| 498 controller().LoadURL( | |
| 499 url3, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 500 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 501 contents()->TestDidNavigate( | |
| 502 orig_rvh, 3, url3, content::PAGE_TRANSITION_TYPED); | |
| 503 SiteInstance* instance4 = contents()->GetSiteInstance(); | |
| 504 EXPECT_EQ(instance1, instance4); | |
| 505 } | |
| 506 | |
| 507 // Test that the onbeforeunload and onunload handlers run when navigating | |
| 508 // across site boundaries. | |
| 509 TEST_F(TabContentsTest, CrossSiteUnloadHandlers) { | |
| 510 contents()->transition_cross_site = true; | |
| 511 TestRenderViewHost* orig_rvh = rvh(); | |
| 512 SiteInstance* instance1 = contents()->GetSiteInstance(); | |
| 513 | |
| 514 // Navigate to URL. First URL should use first RenderViewHost. | |
| 515 const GURL url("http://www.google.com"); | |
| 516 controller().LoadURL( | |
| 517 url, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 518 contents()->TestDidNavigate(orig_rvh, 1, url, content::PAGE_TRANSITION_TYPED); | |
| 519 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 520 EXPECT_EQ(orig_rvh, contents()->render_view_host()); | |
| 521 | |
| 522 // Navigate to new site, but simulate an onbeforeunload denial. | |
| 523 const GURL url2("http://www.yahoo.com"); | |
| 524 controller().LoadURL( | |
| 525 url2, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 526 EXPECT_TRUE(orig_rvh->is_waiting_for_beforeunload_ack()); | |
| 527 orig_rvh->TestOnMessageReceived(ViewHostMsg_ShouldClose_ACK(0, false)); | |
| 528 EXPECT_FALSE(orig_rvh->is_waiting_for_beforeunload_ack()); | |
| 529 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 530 EXPECT_EQ(orig_rvh, contents()->render_view_host()); | |
| 531 | |
| 532 // Navigate again, but simulate an onbeforeunload approval. | |
| 533 controller().LoadURL( | |
| 534 url2, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 535 EXPECT_TRUE(orig_rvh->is_waiting_for_beforeunload_ack()); | |
| 536 orig_rvh->TestOnMessageReceived(ViewHostMsg_ShouldClose_ACK(0, true)); | |
| 537 EXPECT_FALSE(orig_rvh->is_waiting_for_beforeunload_ack()); | |
| 538 EXPECT_TRUE(contents()->cross_navigation_pending()); | |
| 539 TestRenderViewHost* pending_rvh = static_cast<TestRenderViewHost*>( | |
| 540 contents()->pending_rvh()); | |
| 541 | |
| 542 // We won't hear DidNavigate until the onunload handler has finished running. | |
| 543 // (No way to simulate that here, but it involves a call from RDH to | |
| 544 // TabContents::OnCrossSiteResponse.) | |
| 545 | |
| 546 // DidNavigate from the pending page | |
| 547 contents()->TestDidNavigate( | |
| 548 pending_rvh, 1, url2, content::PAGE_TRANSITION_TYPED); | |
| 549 SiteInstance* instance2 = contents()->GetSiteInstance(); | |
| 550 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 551 EXPECT_EQ(pending_rvh, rvh()); | |
| 552 EXPECT_NE(instance1, instance2); | |
| 553 EXPECT_TRUE(contents()->pending_rvh() == NULL); | |
| 554 } | |
| 555 | |
| 556 // Test that during a slow cross-site navigation, the original renderer can | |
| 557 // navigate to a different URL and have it displayed, canceling the slow | |
| 558 // navigation. | |
| 559 TEST_F(TabContentsTest, CrossSiteNavigationPreempted) { | |
| 560 contents()->transition_cross_site = true; | |
| 561 TestRenderViewHost* orig_rvh = rvh(); | |
| 562 SiteInstance* instance1 = contents()->GetSiteInstance(); | |
| 563 | |
| 564 // Navigate to URL. First URL should use first RenderViewHost. | |
| 565 const GURL url("http://www.google.com"); | |
| 566 controller().LoadURL( | |
| 567 url, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 568 contents()->TestDidNavigate(orig_rvh, 1, url, content::PAGE_TRANSITION_TYPED); | |
| 569 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 570 EXPECT_EQ(orig_rvh, contents()->render_view_host()); | |
| 571 | |
| 572 // Navigate to new site, simulating an onbeforeunload approval. | |
| 573 const GURL url2("http://www.yahoo.com"); | |
| 574 controller().LoadURL( | |
| 575 url2, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 576 EXPECT_TRUE(orig_rvh->is_waiting_for_beforeunload_ack()); | |
| 577 orig_rvh->TestOnMessageReceived(ViewHostMsg_ShouldClose_ACK(0, true)); | |
| 578 EXPECT_TRUE(contents()->cross_navigation_pending()); | |
| 579 | |
| 580 // Suppose the original renderer navigates before the new one is ready. | |
| 581 orig_rvh->SendNavigate(2, GURL("http://www.google.com/foo")); | |
| 582 | |
| 583 // Verify that the pending navigation is cancelled. | |
| 584 EXPECT_FALSE(orig_rvh->is_waiting_for_beforeunload_ack()); | |
| 585 SiteInstance* instance2 = contents()->GetSiteInstance(); | |
| 586 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 587 EXPECT_EQ(orig_rvh, rvh()); | |
| 588 EXPECT_EQ(instance1, instance2); | |
| 589 EXPECT_TRUE(contents()->pending_rvh() == NULL); | |
| 590 } | |
| 591 | |
| 592 TEST_F(TabContentsTest, CrossSiteNavigationBackPreempted) { | |
| 593 contents()->transition_cross_site = true; | |
| 594 | |
| 595 // Start with NTP, which gets a new RVH with WebUI bindings. | |
| 596 const GURL url1("chrome://newtab"); | |
| 597 controller().LoadURL( | |
| 598 url1, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 599 TestRenderViewHost* ntp_rvh = rvh(); | |
| 600 contents()->TestDidNavigate(ntp_rvh, 1, url1, content::PAGE_TRANSITION_TYPED); | |
| 601 NavigationEntry* entry1 = controller().GetLastCommittedEntry(); | |
| 602 SiteInstance* instance1 = contents()->GetSiteInstance(); | |
| 603 | |
| 604 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 605 EXPECT_EQ(ntp_rvh, contents()->render_view_host()); | |
| 606 EXPECT_EQ(url1, entry1->url()); | |
| 607 EXPECT_EQ(instance1, entry1->site_instance()); | |
| 608 EXPECT_TRUE(ntp_rvh->enabled_bindings() & content::BINDINGS_POLICY_WEB_UI); | |
| 609 | |
| 610 // Navigate to new site. | |
| 611 const GURL url2("http://www.google.com"); | |
| 612 controller().LoadURL( | |
| 613 url2, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 614 EXPECT_TRUE(contents()->cross_navigation_pending()); | |
| 615 TestRenderViewHost* google_rvh = contents()->pending_rvh(); | |
| 616 | |
| 617 // Simulate beforeunload approval. | |
| 618 EXPECT_TRUE(ntp_rvh->is_waiting_for_beforeunload_ack()); | |
| 619 ntp_rvh->TestOnMessageReceived(ViewHostMsg_ShouldClose_ACK(0, true)); | |
| 620 | |
| 621 // DidNavigate from the pending page. | |
| 622 contents()->TestDidNavigate( | |
| 623 google_rvh, 1, url2, content::PAGE_TRANSITION_TYPED); | |
| 624 NavigationEntry* entry2 = controller().GetLastCommittedEntry(); | |
| 625 SiteInstance* instance2 = contents()->GetSiteInstance(); | |
| 626 | |
| 627 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 628 EXPECT_EQ(google_rvh, contents()->render_view_host()); | |
| 629 EXPECT_NE(instance1, instance2); | |
| 630 EXPECT_FALSE(contents()->pending_rvh()); | |
| 631 EXPECT_EQ(url2, entry2->url()); | |
| 632 EXPECT_EQ(instance2, entry2->site_instance()); | |
| 633 EXPECT_FALSE(google_rvh->enabled_bindings() & | |
| 634 content::BINDINGS_POLICY_WEB_UI); | |
| 635 | |
| 636 // Navigate to third page on same site. | |
| 637 const GURL url3("http://news.google.com"); | |
| 638 controller().LoadURL( | |
| 639 url3, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 640 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 641 contents()->TestDidNavigate( | |
| 642 google_rvh, 2, url3, content::PAGE_TRANSITION_TYPED); | |
| 643 NavigationEntry* entry3 = controller().GetLastCommittedEntry(); | |
| 644 SiteInstance* instance3 = contents()->GetSiteInstance(); | |
| 645 | |
| 646 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 647 EXPECT_EQ(google_rvh, contents()->render_view_host()); | |
| 648 EXPECT_EQ(instance2, instance3); | |
| 649 EXPECT_FALSE(contents()->pending_rvh()); | |
| 650 EXPECT_EQ(url3, entry3->url()); | |
| 651 EXPECT_EQ(instance3, entry3->site_instance()); | |
| 652 | |
| 653 // Go back within the site. | |
| 654 controller().GoBack(); | |
| 655 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 656 EXPECT_EQ(entry2, controller().pending_entry()); | |
| 657 | |
| 658 // Before that commits, go back again. | |
| 659 controller().GoBack(); | |
| 660 EXPECT_TRUE(contents()->cross_navigation_pending()); | |
| 661 EXPECT_TRUE(contents()->pending_rvh()); | |
| 662 EXPECT_EQ(entry1, controller().pending_entry()); | |
| 663 | |
| 664 // Simulate beforeunload approval. | |
| 665 EXPECT_TRUE(google_rvh->is_waiting_for_beforeunload_ack()); | |
| 666 google_rvh->TestOnMessageReceived(ViewHostMsg_ShouldClose_ACK(0, true)); | |
| 667 | |
| 668 // DidNavigate from the first back. This aborts the second back's pending RVH. | |
| 669 contents()->TestDidNavigate( | |
| 670 google_rvh, 1, url2, content::PAGE_TRANSITION_TYPED); | |
| 671 | |
| 672 // We should commit this page and forget about the second back. | |
| 673 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 674 EXPECT_FALSE(controller().pending_entry()); | |
| 675 EXPECT_EQ(google_rvh, contents()->render_view_host()); | |
| 676 EXPECT_EQ(url2, controller().GetLastCommittedEntry()->url()); | |
| 677 | |
| 678 // We should not have corrupted the NTP entry. | |
| 679 EXPECT_EQ(instance3, entry3->site_instance()); | |
| 680 EXPECT_EQ(instance2, entry2->site_instance()); | |
| 681 EXPECT_EQ(instance1, entry1->site_instance()); | |
| 682 EXPECT_EQ(url1, entry1->url()); | |
| 683 } | |
| 684 | |
| 685 // Test that during a slow cross-site navigation, a sub-frame navigation in the | |
| 686 // original renderer will not cancel the slow navigation (bug 42029). | |
| 687 TEST_F(TabContentsTest, CrossSiteNavigationNotPreemptedByFrame) { | |
| 688 contents()->transition_cross_site = true; | |
| 689 TestRenderViewHost* orig_rvh = rvh(); | |
| 690 | |
| 691 // Navigate to URL. First URL should use first RenderViewHost. | |
| 692 const GURL url("http://www.google.com"); | |
| 693 controller().LoadURL( | |
| 694 url, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 695 contents()->TestDidNavigate(orig_rvh, 1, url, content::PAGE_TRANSITION_TYPED); | |
| 696 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 697 EXPECT_EQ(orig_rvh, contents()->render_view_host()); | |
| 698 | |
| 699 // Start navigating to new site. | |
| 700 const GURL url2("http://www.yahoo.com"); | |
| 701 controller().LoadURL( | |
| 702 url2, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 703 | |
| 704 // Simulate a sub-frame navigation arriving and ensure the RVH is still | |
| 705 // waiting for a before unload response. | |
| 706 orig_rvh->SendNavigateWithTransition(1, GURL("http://google.com/frame"), | |
| 707 content::PAGE_TRANSITION_AUTO_SUBFRAME); | |
| 708 EXPECT_TRUE(orig_rvh->is_waiting_for_beforeunload_ack()); | |
| 709 | |
| 710 // Now simulate the onbeforeunload approval and verify the navigation is | |
| 711 // not canceled. | |
| 712 orig_rvh->TestOnMessageReceived(ViewHostMsg_ShouldClose_ACK(0, true)); | |
| 713 EXPECT_FALSE(orig_rvh->is_waiting_for_beforeunload_ack()); | |
| 714 EXPECT_TRUE(contents()->cross_navigation_pending()); | |
| 715 } | |
| 716 | |
| 717 // Test that a cross-site navigation is not preempted if the previous | |
| 718 // renderer sends a FrameNavigate message just before being told to stop. | |
| 719 // We should only preempt the cross-site navigation if the previous renderer | |
| 720 // has started a new navigation. See http://crbug.com/79176. | |
| 721 TEST_F(TabContentsTest, CrossSiteNotPreemptedDuringBeforeUnload) { | |
| 722 contents()->transition_cross_site = true; | |
| 723 | |
| 724 // Navigate to NTP URL. | |
| 725 const GURL url("chrome://newtab"); | |
| 726 controller().LoadURL( | |
| 727 url, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 728 TestRenderViewHost* orig_rvh = rvh(); | |
| 729 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 730 | |
| 731 // Navigate to new site, with the beforeunload request in flight. | |
| 732 const GURL url2("http://www.yahoo.com"); | |
| 733 controller().LoadURL( | |
| 734 url2, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 735 TestRenderViewHost* pending_rvh = contents()->pending_rvh(); | |
| 736 EXPECT_TRUE(contents()->cross_navigation_pending()); | |
| 737 EXPECT_TRUE(orig_rvh->is_waiting_for_beforeunload_ack()); | |
| 738 | |
| 739 // Suppose the first navigation tries to commit now, with a | |
| 740 // ViewMsg_Stop in flight. This should not cancel the pending navigation, | |
| 741 // but it should act as if the beforeunload ack arrived. | |
| 742 orig_rvh->SendNavigate(1, GURL("chrome://newtab")); | |
| 743 EXPECT_TRUE(contents()->cross_navigation_pending()); | |
| 744 EXPECT_EQ(orig_rvh, contents()->render_view_host()); | |
| 745 EXPECT_FALSE(orig_rvh->is_waiting_for_beforeunload_ack()); | |
| 746 | |
| 747 // The pending navigation should be able to commit successfully. | |
| 748 contents()->TestDidNavigate( | |
| 749 pending_rvh, 1, url2, content::PAGE_TRANSITION_TYPED); | |
| 750 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 751 EXPECT_EQ(pending_rvh, contents()->render_view_host()); | |
| 752 } | |
| 753 | |
| 754 // Test that the original renderer cannot preempt a cross-site navigation once | |
| 755 // the unload request has been made. At this point, the cross-site navigation | |
| 756 // is almost ready to be displayed, and the original renderer is only given a | |
| 757 // short chance to run an unload handler. Prevents regression of bug 23942. | |
| 758 TEST_F(TabContentsTest, CrossSiteCantPreemptAfterUnload) { | |
| 759 contents()->transition_cross_site = true; | |
| 760 TestRenderViewHost* orig_rvh = rvh(); | |
| 761 SiteInstance* instance1 = contents()->GetSiteInstance(); | |
| 762 | |
| 763 // Navigate to URL. First URL should use first RenderViewHost. | |
| 764 const GURL url("http://www.google.com"); | |
| 765 controller().LoadURL( | |
| 766 url, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 767 contents()->TestDidNavigate(orig_rvh, 1, url, content::PAGE_TRANSITION_TYPED); | |
| 768 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 769 EXPECT_EQ(orig_rvh, contents()->render_view_host()); | |
| 770 | |
| 771 // Navigate to new site, simulating an onbeforeunload approval. | |
| 772 const GURL url2("http://www.yahoo.com"); | |
| 773 controller().LoadURL( | |
| 774 url2, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 775 orig_rvh->TestOnMessageReceived(ViewHostMsg_ShouldClose_ACK(0, true)); | |
| 776 EXPECT_TRUE(contents()->cross_navigation_pending()); | |
| 777 TestRenderViewHost* pending_rvh = static_cast<TestRenderViewHost*>( | |
| 778 contents()->pending_rvh()); | |
| 779 | |
| 780 // Simulate the pending renderer's response, which leads to an unload request | |
| 781 // being sent to orig_rvh. | |
| 782 contents()->render_manager_for_testing()->OnCrossSiteResponse(0, 0); | |
| 783 | |
| 784 // Suppose the original renderer navigates now, while the unload request is in | |
| 785 // flight. We should ignore it, wait for the unload ack, and let the pending | |
| 786 // request continue. Otherwise, the tab may close spontaneously or stop | |
| 787 // responding to navigation requests. (See bug 23942.) | |
| 788 ViewHostMsg_FrameNavigate_Params params1a; | |
| 789 InitNavigateParams(¶ms1a, 2, GURL("http://www.google.com/foo"), | |
| 790 content::PAGE_TRANSITION_TYPED); | |
| 791 orig_rvh->SendNavigate(2, GURL("http://www.google.com/foo")); | |
| 792 | |
| 793 // Verify that the pending navigation is still in progress. | |
| 794 EXPECT_TRUE(contents()->cross_navigation_pending()); | |
| 795 EXPECT_TRUE(contents()->pending_rvh() != NULL); | |
| 796 | |
| 797 // DidNavigate from the pending page should commit it. | |
| 798 contents()->TestDidNavigate( | |
| 799 pending_rvh, 1, url2, content::PAGE_TRANSITION_TYPED); | |
| 800 SiteInstance* instance2 = contents()->GetSiteInstance(); | |
| 801 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 802 EXPECT_EQ(pending_rvh, rvh()); | |
| 803 EXPECT_NE(instance1, instance2); | |
| 804 EXPECT_TRUE(contents()->pending_rvh() == NULL); | |
| 805 } | |
| 806 | |
| 807 // Test that a cross-site navigation that doesn't commit after the unload | |
| 808 // handler doesn't leave the tab in a stuck state. http://crbug.com/88562. | |
| 809 TEST_F(TabContentsTest, CrossSiteNavigationCanceled) { | |
| 810 contents()->transition_cross_site = true; | |
| 811 TestRenderViewHost* orig_rvh = rvh(); | |
| 812 SiteInstance* instance1 = contents()->GetSiteInstance(); | |
| 813 | |
| 814 // Navigate to URL. First URL should use first RenderViewHost. | |
| 815 const GURL url("http://www.google.com"); | |
| 816 controller().LoadURL( | |
| 817 url, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 818 contents()->TestDidNavigate(orig_rvh, 1, url, content::PAGE_TRANSITION_TYPED); | |
| 819 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 820 EXPECT_EQ(orig_rvh, contents()->render_view_host()); | |
| 821 | |
| 822 // Navigate to new site, simulating an onbeforeunload approval. | |
| 823 const GURL url2("http://www.yahoo.com"); | |
| 824 controller().LoadURL( | |
| 825 url2, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 826 EXPECT_TRUE(orig_rvh->is_waiting_for_beforeunload_ack()); | |
| 827 orig_rvh->TestOnMessageReceived(ViewHostMsg_ShouldClose_ACK(0, true)); | |
| 828 EXPECT_TRUE(contents()->cross_navigation_pending()); | |
| 829 | |
| 830 // Simulate swap out message when the response arrives. | |
| 831 orig_rvh->set_is_swapped_out(true); | |
| 832 | |
| 833 // Suppose the navigation doesn't get a chance to commit, and the user | |
| 834 // navigates in the current RVH's SiteInstance. | |
| 835 controller().LoadURL( | |
| 836 url, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 837 | |
| 838 // Verify that the pending navigation is cancelled and the renderer is no | |
| 839 // longer swapped out. | |
| 840 EXPECT_FALSE(orig_rvh->is_waiting_for_beforeunload_ack()); | |
| 841 SiteInstance* instance2 = contents()->GetSiteInstance(); | |
| 842 EXPECT_FALSE(contents()->cross_navigation_pending()); | |
| 843 EXPECT_EQ(orig_rvh, rvh()); | |
| 844 EXPECT_FALSE(orig_rvh->is_swapped_out()); | |
| 845 EXPECT_EQ(instance1, instance2); | |
| 846 EXPECT_TRUE(contents()->pending_rvh() == NULL); | |
| 847 } | |
| 848 | |
| 849 // Test that NavigationEntries have the correct content state after going | |
| 850 // forward and back. Prevents regression for bug 1116137. | |
| 851 TEST_F(TabContentsTest, NavigationEntryContentState) { | |
| 852 TestRenderViewHost* orig_rvh = rvh(); | |
| 853 | |
| 854 // Navigate to URL. There should be no committed entry yet. | |
| 855 const GURL url("http://www.google.com"); | |
| 856 controller().LoadURL( | |
| 857 url, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 858 NavigationEntry* entry = controller().GetLastCommittedEntry(); | |
| 859 EXPECT_TRUE(entry == NULL); | |
| 860 | |
| 861 // Committed entry should have content state after DidNavigate. | |
| 862 contents()->TestDidNavigate(orig_rvh, 1, url, content::PAGE_TRANSITION_TYPED); | |
| 863 entry = controller().GetLastCommittedEntry(); | |
| 864 EXPECT_FALSE(entry->content_state().empty()); | |
| 865 | |
| 866 // Navigate to same site. | |
| 867 const GURL url2("http://images.google.com"); | |
| 868 controller().LoadURL( | |
| 869 url2, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 870 entry = controller().GetLastCommittedEntry(); | |
| 871 EXPECT_FALSE(entry->content_state().empty()); | |
| 872 | |
| 873 // Committed entry should have content state after DidNavigate. | |
| 874 contents()->TestDidNavigate( | |
| 875 orig_rvh, 2, url2, content::PAGE_TRANSITION_TYPED); | |
| 876 entry = controller().GetLastCommittedEntry(); | |
| 877 EXPECT_FALSE(entry->content_state().empty()); | |
| 878 | |
| 879 // Now go back. Committed entry should still have content state. | |
| 880 controller().GoBack(); | |
| 881 contents()->TestDidNavigate(orig_rvh, 1, url, content::PAGE_TRANSITION_TYPED); | |
| 882 entry = controller().GetLastCommittedEntry(); | |
| 883 EXPECT_FALSE(entry->content_state().empty()); | |
| 884 } | |
| 885 | |
| 886 // Test that NavigationEntries have the correct content state after opening | |
| 887 // a new window to about:blank. Prevents regression for bug 1116137. | |
| 888 TEST_F(TabContentsTest, NavigationEntryContentStateNewWindow) { | |
| 889 TestRenderViewHost* orig_rvh = rvh(); | |
| 890 | |
| 891 // When opening a new window, it is navigated to about:blank internally. | |
| 892 // Currently, this results in two DidNavigate events. | |
| 893 const GURL url(chrome::kAboutBlankURL); | |
| 894 contents()->TestDidNavigate(orig_rvh, 1, url, content::PAGE_TRANSITION_TYPED); | |
| 895 contents()->TestDidNavigate(orig_rvh, 1, url, content::PAGE_TRANSITION_TYPED); | |
| 896 | |
| 897 // Should have a content state here. | |
| 898 NavigationEntry* entry = controller().GetLastCommittedEntry(); | |
| 899 EXPECT_FALSE(entry->content_state().empty()); | |
| 900 } | |
| 901 | |
| 902 // Tests to see that webkit preferences are properly loaded and copied over | |
| 903 // to a WebPreferences object. | |
| 904 TEST_F(TabContentsTest, WebKitPrefs) { | |
| 905 WebPreferences webkit_prefs = contents()->TestGetWebkitPrefs(); | |
| 906 | |
| 907 // These values have been overridden by the profile preferences. | |
| 908 EXPECT_EQ("UTF-8", webkit_prefs.default_encoding); | |
| 909 EXPECT_EQ(20, webkit_prefs.default_font_size); | |
| 910 EXPECT_FALSE(webkit_prefs.text_areas_are_resizable); | |
| 911 EXPECT_TRUE(webkit_prefs.uses_universal_detector); | |
| 912 | |
| 913 // These should still be the default values. | |
| 914 #if defined(OS_MACOSX) | |
| 915 const char kDefaultFont[] = "Times"; | |
| 916 #elif defined(OS_CHROMEOS) | |
| 917 const char kDefaultFont[] = "Tinos"; | |
| 918 #else | |
| 919 const char kDefaultFont[] = "Times New Roman"; | |
| 920 #endif | |
| 921 EXPECT_EQ(ASCIIToUTF16(kDefaultFont), webkit_prefs.standard_font_family); | |
| 922 EXPECT_TRUE(webkit_prefs.javascript_enabled); | |
| 923 } | |
| 924 | |
| 925 //////////////////////////////////////////////////////////////////////////////// | |
| 926 // Interstitial Tests | |
| 927 //////////////////////////////////////////////////////////////////////////////// | |
| 928 | |
| 929 // Test navigating to a page (with the navigation initiated from the browser, | |
| 930 // as when a URL is typed in the location bar) that shows an interstitial and | |
| 931 // creates a new navigation entry, then hiding it without proceeding. | |
| 932 TEST_F(TabContentsTest, | |
| 933 ShowInterstitialFromBrowserWithNewNavigationDontProceed) { | |
| 934 // Navigate to a page. | |
| 935 GURL url1("http://www.google.com"); | |
| 936 rvh()->SendNavigate(1, url1); | |
| 937 EXPECT_EQ(1, controller().entry_count()); | |
| 938 | |
| 939 // Initiate a browser navigation that will trigger the interstitial | |
| 940 controller().LoadURL(GURL("http://www.evil.com"), content::Referrer(), | |
| 941 content::PAGE_TRANSITION_TYPED, std::string()); | |
| 942 | |
| 943 // Show an interstitial. | |
| 944 TestInterstitialPage::InterstitialState state = | |
| 945 TestInterstitialPage::UNDECIDED; | |
| 946 bool deleted = false; | |
| 947 GURL url2("http://interstitial"); | |
| 948 TestInterstitialPage* interstitial = | |
| 949 new TestInterstitialPage(contents(), true, url2, &state, &deleted); | |
| 950 TestInterstitialPageStateGuard state_guard(interstitial); | |
| 951 interstitial->Show(); | |
| 952 // The interstitial should not show until its navigation has committed. | |
| 953 EXPECT_FALSE(interstitial->is_showing()); | |
| 954 EXPECT_FALSE(contents()->showing_interstitial_page()); | |
| 955 EXPECT_TRUE(contents()->interstitial_page() == NULL); | |
| 956 // Let's commit the interstitial navigation. | |
| 957 interstitial->TestDidNavigate(1, url2); | |
| 958 EXPECT_TRUE(interstitial->is_showing()); | |
| 959 EXPECT_TRUE(contents()->showing_interstitial_page()); | |
| 960 EXPECT_TRUE(contents()->interstitial_page() == interstitial); | |
| 961 NavigationEntry* entry = controller().GetActiveEntry(); | |
| 962 ASSERT_TRUE(entry != NULL); | |
| 963 EXPECT_TRUE(entry->url() == url2); | |
| 964 | |
| 965 // Now don't proceed. | |
| 966 interstitial->DontProceed(); | |
| 967 EXPECT_TRUE(deleted); | |
| 968 EXPECT_EQ(TestInterstitialPage::CANCELED, state); | |
| 969 EXPECT_FALSE(contents()->showing_interstitial_page()); | |
| 970 EXPECT_TRUE(contents()->interstitial_page() == NULL); | |
| 971 entry = controller().GetActiveEntry(); | |
| 972 ASSERT_TRUE(entry != NULL); | |
| 973 EXPECT_TRUE(entry->url() == url1); | |
| 974 EXPECT_EQ(1, controller().entry_count()); | |
| 975 } | |
| 976 | |
| 977 // Test navigating to a page (with the navigation initiated from the renderer, | |
| 978 // as when clicking on a link in the page) that shows an interstitial and | |
| 979 // creates a new navigation entry, then hiding it without proceeding. | |
| 980 TEST_F(TabContentsTest, | |
| 981 ShowInterstitiaFromRendererlWithNewNavigationDontProceed) { | |
| 982 // Navigate to a page. | |
| 983 GURL url1("http://www.google.com"); | |
| 984 rvh()->SendNavigate(1, url1); | |
| 985 EXPECT_EQ(1, controller().entry_count()); | |
| 986 | |
| 987 // Show an interstitial (no pending entry, the interstitial would have been | |
| 988 // triggered by clicking on a link). | |
| 989 TestInterstitialPage::InterstitialState state = | |
| 990 TestInterstitialPage::UNDECIDED; | |
| 991 bool deleted = false; | |
| 992 GURL url2("http://interstitial"); | |
| 993 TestInterstitialPage* interstitial = | |
| 994 new TestInterstitialPage(contents(), true, url2, &state, &deleted); | |
| 995 TestInterstitialPageStateGuard state_guard(interstitial); | |
| 996 interstitial->Show(); | |
| 997 // The interstitial should not show until its navigation has committed. | |
| 998 EXPECT_FALSE(interstitial->is_showing()); | |
| 999 EXPECT_FALSE(contents()->showing_interstitial_page()); | |
| 1000 EXPECT_TRUE(contents()->interstitial_page() == NULL); | |
| 1001 // Let's commit the interstitial navigation. | |
| 1002 interstitial->TestDidNavigate(1, url2); | |
| 1003 EXPECT_TRUE(interstitial->is_showing()); | |
| 1004 EXPECT_TRUE(contents()->showing_interstitial_page()); | |
| 1005 EXPECT_TRUE(contents()->interstitial_page() == interstitial); | |
| 1006 NavigationEntry* entry = controller().GetActiveEntry(); | |
| 1007 ASSERT_TRUE(entry != NULL); | |
| 1008 EXPECT_TRUE(entry->url() == url2); | |
| 1009 | |
| 1010 // Now don't proceed. | |
| 1011 interstitial->DontProceed(); | |
| 1012 EXPECT_TRUE(deleted); | |
| 1013 EXPECT_EQ(TestInterstitialPage::CANCELED, state); | |
| 1014 EXPECT_FALSE(contents()->showing_interstitial_page()); | |
| 1015 EXPECT_TRUE(contents()->interstitial_page() == NULL); | |
| 1016 entry = controller().GetActiveEntry(); | |
| 1017 ASSERT_TRUE(entry != NULL); | |
| 1018 EXPECT_TRUE(entry->url() == url1); | |
| 1019 EXPECT_EQ(1, controller().entry_count()); | |
| 1020 } | |
| 1021 | |
| 1022 // Test navigating to a page that shows an interstitial without creating a new | |
| 1023 // navigation entry (this happens when the interstitial is triggered by a | |
| 1024 // sub-resource in the page), then hiding it without proceeding. | |
| 1025 TEST_F(TabContentsTest, ShowInterstitialNoNewNavigationDontProceed) { | |
| 1026 // Navigate to a page. | |
| 1027 GURL url1("http://www.google.com"); | |
| 1028 rvh()->SendNavigate(1, url1); | |
| 1029 EXPECT_EQ(1, controller().entry_count()); | |
| 1030 | |
| 1031 // Show an interstitial. | |
| 1032 TestInterstitialPage::InterstitialState state = | |
| 1033 TestInterstitialPage::UNDECIDED; | |
| 1034 bool deleted = false; | |
| 1035 GURL url2("http://interstitial"); | |
| 1036 TestInterstitialPage* interstitial = | |
| 1037 new TestInterstitialPage(contents(), false, url2, &state, &deleted); | |
| 1038 TestInterstitialPageStateGuard state_guard(interstitial); | |
| 1039 interstitial->Show(); | |
| 1040 // The interstitial should not show until its navigation has committed. | |
| 1041 EXPECT_FALSE(interstitial->is_showing()); | |
| 1042 EXPECT_FALSE(contents()->showing_interstitial_page()); | |
| 1043 EXPECT_TRUE(contents()->interstitial_page() == NULL); | |
| 1044 // Let's commit the interstitial navigation. | |
| 1045 interstitial->TestDidNavigate(1, url2); | |
| 1046 EXPECT_TRUE(interstitial->is_showing()); | |
| 1047 EXPECT_TRUE(contents()->showing_interstitial_page()); | |
| 1048 EXPECT_TRUE(contents()->interstitial_page() == interstitial); | |
| 1049 NavigationEntry* entry = controller().GetActiveEntry(); | |
| 1050 ASSERT_TRUE(entry != NULL); | |
| 1051 // The URL specified to the interstitial should have been ignored. | |
| 1052 EXPECT_TRUE(entry->url() == url1); | |
| 1053 | |
| 1054 // Now don't proceed. | |
| 1055 interstitial->DontProceed(); | |
| 1056 EXPECT_TRUE(deleted); | |
| 1057 EXPECT_EQ(TestInterstitialPage::CANCELED, state); | |
| 1058 EXPECT_FALSE(contents()->showing_interstitial_page()); | |
| 1059 EXPECT_TRUE(contents()->interstitial_page() == NULL); | |
| 1060 entry = controller().GetActiveEntry(); | |
| 1061 ASSERT_TRUE(entry != NULL); | |
| 1062 EXPECT_TRUE(entry->url() == url1); | |
| 1063 EXPECT_EQ(1, controller().entry_count()); | |
| 1064 } | |
| 1065 | |
| 1066 // Test navigating to a page (with the navigation initiated from the browser, | |
| 1067 // as when a URL is typed in the location bar) that shows an interstitial and | |
| 1068 // creates a new navigation entry, then proceeding. | |
| 1069 TEST_F(TabContentsTest, | |
| 1070 ShowInterstitialFromBrowserNewNavigationProceed) { | |
| 1071 // Navigate to a page. | |
| 1072 GURL url1("http://www.google.com"); | |
| 1073 rvh()->SendNavigate(1, url1); | |
| 1074 EXPECT_EQ(1, controller().entry_count()); | |
| 1075 | |
| 1076 // Initiate a browser navigation that will trigger the interstitial | |
| 1077 controller().LoadURL(GURL("http://www.evil.com"), content::Referrer(), | |
| 1078 content::PAGE_TRANSITION_TYPED, std::string()); | |
| 1079 | |
| 1080 // Show an interstitial. | |
| 1081 TestInterstitialPage::InterstitialState state = | |
| 1082 TestInterstitialPage::UNDECIDED; | |
| 1083 bool deleted = false; | |
| 1084 GURL url2("http://interstitial"); | |
| 1085 TestInterstitialPage* interstitial = | |
| 1086 new TestInterstitialPage(contents(), true, url2, &state, &deleted); | |
| 1087 TestInterstitialPageStateGuard state_guard(interstitial); | |
| 1088 interstitial->Show(); | |
| 1089 // The interstitial should not show until its navigation has committed. | |
| 1090 EXPECT_FALSE(interstitial->is_showing()); | |
| 1091 EXPECT_FALSE(contents()->showing_interstitial_page()); | |
| 1092 EXPECT_TRUE(contents()->interstitial_page() == NULL); | |
| 1093 // Let's commit the interstitial navigation. | |
| 1094 interstitial->TestDidNavigate(1, url2); | |
| 1095 EXPECT_TRUE(interstitial->is_showing()); | |
| 1096 EXPECT_TRUE(contents()->showing_interstitial_page()); | |
| 1097 EXPECT_TRUE(contents()->interstitial_page() == interstitial); | |
| 1098 NavigationEntry* entry = controller().GetActiveEntry(); | |
| 1099 ASSERT_TRUE(entry != NULL); | |
| 1100 EXPECT_TRUE(entry->url() == url2); | |
| 1101 | |
| 1102 // Then proceed. | |
| 1103 interstitial->Proceed(); | |
| 1104 // The interstitial should show until the new navigation commits. | |
| 1105 ASSERT_FALSE(deleted); | |
| 1106 EXPECT_EQ(TestInterstitialPage::OKED, state); | |
| 1107 EXPECT_TRUE(contents()->showing_interstitial_page()); | |
| 1108 EXPECT_TRUE(contents()->interstitial_page() == interstitial); | |
| 1109 | |
| 1110 // Simulate the navigation to the page, that's when the interstitial gets | |
| 1111 // hidden. | |
| 1112 GURL url3("http://www.thepage.com"); | |
| 1113 rvh()->SendNavigate(2, url3); | |
| 1114 | |
| 1115 EXPECT_TRUE(deleted); | |
| 1116 EXPECT_FALSE(contents()->showing_interstitial_page()); | |
| 1117 EXPECT_TRUE(contents()->interstitial_page() == NULL); | |
| 1118 entry = controller().GetActiveEntry(); | |
| 1119 ASSERT_TRUE(entry != NULL); | |
| 1120 EXPECT_TRUE(entry->url() == url3); | |
| 1121 | |
| 1122 EXPECT_EQ(2, controller().entry_count()); | |
| 1123 } | |
| 1124 | |
| 1125 // Test navigating to a page (with the navigation initiated from the renderer, | |
| 1126 // as when clicking on a link in the page) that shows an interstitial and | |
| 1127 // creates a new navigation entry, then proceeding. | |
| 1128 TEST_F(TabContentsTest, | |
| 1129 ShowInterstitialFromRendererNewNavigationProceed) { | |
| 1130 // Navigate to a page. | |
| 1131 GURL url1("http://www.google.com"); | |
| 1132 rvh()->SendNavigate(1, url1); | |
| 1133 EXPECT_EQ(1, controller().entry_count()); | |
| 1134 | |
| 1135 // Show an interstitial. | |
| 1136 TestInterstitialPage::InterstitialState state = | |
| 1137 TestInterstitialPage::UNDECIDED; | |
| 1138 bool deleted = false; | |
| 1139 GURL url2("http://interstitial"); | |
| 1140 TestInterstitialPage* interstitial = | |
| 1141 new TestInterstitialPage(contents(), true, url2, &state, &deleted); | |
| 1142 TestInterstitialPageStateGuard state_guard(interstitial); | |
| 1143 interstitial->Show(); | |
| 1144 // The interstitial should not show until its navigation has committed. | |
| 1145 EXPECT_FALSE(interstitial->is_showing()); | |
| 1146 EXPECT_FALSE(contents()->showing_interstitial_page()); | |
| 1147 EXPECT_TRUE(contents()->interstitial_page() == NULL); | |
| 1148 // Let's commit the interstitial navigation. | |
| 1149 interstitial->TestDidNavigate(1, url2); | |
| 1150 EXPECT_TRUE(interstitial->is_showing()); | |
| 1151 EXPECT_TRUE(contents()->showing_interstitial_page()); | |
| 1152 EXPECT_TRUE(contents()->interstitial_page() == interstitial); | |
| 1153 NavigationEntry* entry = controller().GetActiveEntry(); | |
| 1154 ASSERT_TRUE(entry != NULL); | |
| 1155 EXPECT_TRUE(entry->url() == url2); | |
| 1156 | |
| 1157 // Then proceed. | |
| 1158 interstitial->Proceed(); | |
| 1159 // The interstitial should show until the new navigation commits. | |
| 1160 ASSERT_FALSE(deleted); | |
| 1161 EXPECT_EQ(TestInterstitialPage::OKED, state); | |
| 1162 EXPECT_TRUE(contents()->showing_interstitial_page()); | |
| 1163 EXPECT_TRUE(contents()->interstitial_page() == interstitial); | |
| 1164 | |
| 1165 // Simulate the navigation to the page, that's when the interstitial gets | |
| 1166 // hidden. | |
| 1167 GURL url3("http://www.thepage.com"); | |
| 1168 rvh()->SendNavigate(2, url3); | |
| 1169 | |
| 1170 EXPECT_TRUE(deleted); | |
| 1171 EXPECT_FALSE(contents()->showing_interstitial_page()); | |
| 1172 EXPECT_TRUE(contents()->interstitial_page() == NULL); | |
| 1173 entry = controller().GetActiveEntry(); | |
| 1174 ASSERT_TRUE(entry != NULL); | |
| 1175 EXPECT_TRUE(entry->url() == url3); | |
| 1176 | |
| 1177 EXPECT_EQ(2, controller().entry_count()); | |
| 1178 } | |
| 1179 | |
| 1180 // Test navigating to a page that shows an interstitial without creating a new | |
| 1181 // navigation entry (this happens when the interstitial is triggered by a | |
| 1182 // sub-resource in the page), then proceeding. | |
| 1183 TEST_F(TabContentsTest, ShowInterstitialNoNewNavigationProceed) { | |
| 1184 // Navigate to a page so we have a navigation entry in the controller. | |
| 1185 GURL url1("http://www.google.com"); | |
| 1186 rvh()->SendNavigate(1, url1); | |
| 1187 EXPECT_EQ(1, controller().entry_count()); | |
| 1188 | |
| 1189 // Show an interstitial. | |
| 1190 TestInterstitialPage::InterstitialState state = | |
| 1191 TestInterstitialPage::UNDECIDED; | |
| 1192 bool deleted = false; | |
| 1193 GURL url2("http://interstitial"); | |
| 1194 TestInterstitialPage* interstitial = | |
| 1195 new TestInterstitialPage(contents(), false, url2, &state, &deleted); | |
| 1196 TestInterstitialPageStateGuard state_guard(interstitial); | |
| 1197 interstitial->Show(); | |
| 1198 // The interstitial should not show until its navigation has committed. | |
| 1199 EXPECT_FALSE(interstitial->is_showing()); | |
| 1200 EXPECT_FALSE(contents()->showing_interstitial_page()); | |
| 1201 EXPECT_TRUE(contents()->interstitial_page() == NULL); | |
| 1202 // Let's commit the interstitial navigation. | |
| 1203 interstitial->TestDidNavigate(1, url2); | |
| 1204 EXPECT_TRUE(interstitial->is_showing()); | |
| 1205 EXPECT_TRUE(contents()->showing_interstitial_page()); | |
| 1206 EXPECT_TRUE(contents()->interstitial_page() == interstitial); | |
| 1207 NavigationEntry* entry = controller().GetActiveEntry(); | |
| 1208 ASSERT_TRUE(entry != NULL); | |
| 1209 // The URL specified to the interstitial should have been ignored. | |
| 1210 EXPECT_TRUE(entry->url() == url1); | |
| 1211 | |
| 1212 // Then proceed. | |
| 1213 interstitial->Proceed(); | |
| 1214 // Since this is not a new navigation, the previous page is dismissed right | |
| 1215 // away and shows the original page. | |
| 1216 EXPECT_TRUE(deleted); | |
| 1217 EXPECT_EQ(TestInterstitialPage::OKED, state); | |
| 1218 EXPECT_FALSE(contents()->showing_interstitial_page()); | |
| 1219 EXPECT_TRUE(contents()->interstitial_page() == NULL); | |
| 1220 entry = controller().GetActiveEntry(); | |
| 1221 ASSERT_TRUE(entry != NULL); | |
| 1222 EXPECT_TRUE(entry->url() == url1); | |
| 1223 | |
| 1224 EXPECT_EQ(1, controller().entry_count()); | |
| 1225 } | |
| 1226 | |
| 1227 // Test navigating to a page that shows an interstitial, then navigating away. | |
| 1228 TEST_F(TabContentsTest, ShowInterstitialThenNavigate) { | |
| 1229 // Show interstitial. | |
| 1230 TestInterstitialPage::InterstitialState state = | |
| 1231 TestInterstitialPage::UNDECIDED; | |
| 1232 bool deleted = false; | |
| 1233 GURL url("http://interstitial"); | |
| 1234 TestInterstitialPage* interstitial = | |
| 1235 new TestInterstitialPage(contents(), true, url, &state, &deleted); | |
| 1236 TestInterstitialPageStateGuard state_guard(interstitial); | |
| 1237 interstitial->Show(); | |
| 1238 interstitial->TestDidNavigate(1, url); | |
| 1239 | |
| 1240 // While interstitial showing, navigate to a new URL. | |
| 1241 const GURL url2("http://www.yahoo.com"); | |
| 1242 rvh()->SendNavigate(1, url2); | |
| 1243 | |
| 1244 EXPECT_TRUE(deleted); | |
| 1245 EXPECT_EQ(TestInterstitialPage::CANCELED, state); | |
| 1246 } | |
| 1247 | |
| 1248 // Test navigating to a page that shows an interstitial, then going back. | |
| 1249 TEST_F(TabContentsTest, ShowInterstitialThenGoBack) { | |
| 1250 // Navigate to a page so we have a navigation entry in the controller. | |
| 1251 GURL url1("http://www.google.com"); | |
| 1252 rvh()->SendNavigate(1, url1); | |
| 1253 EXPECT_EQ(1, controller().entry_count()); | |
| 1254 | |
| 1255 // Show interstitial. | |
| 1256 TestInterstitialPage::InterstitialState state = | |
| 1257 TestInterstitialPage::UNDECIDED; | |
| 1258 bool deleted = false; | |
| 1259 GURL interstitial_url("http://interstitial"); | |
| 1260 TestInterstitialPage* interstitial = | |
| 1261 new TestInterstitialPage(contents(), true, interstitial_url, | |
| 1262 &state, &deleted); | |
| 1263 TestInterstitialPageStateGuard state_guard(interstitial); | |
| 1264 interstitial->Show(); | |
| 1265 interstitial->TestDidNavigate(2, interstitial_url); | |
| 1266 | |
| 1267 // While the interstitial is showing, go back. | |
| 1268 controller().GoBack(); | |
| 1269 rvh()->SendNavigate(1, url1); | |
| 1270 | |
| 1271 // Make sure we are back to the original page and that the interstitial is | |
| 1272 // gone. | |
| 1273 EXPECT_TRUE(deleted); | |
| 1274 EXPECT_EQ(TestInterstitialPage::CANCELED, state); | |
| 1275 NavigationEntry* entry = controller().GetActiveEntry(); | |
| 1276 ASSERT_TRUE(entry); | |
| 1277 EXPECT_EQ(url1.spec(), entry->url().spec()); | |
| 1278 } | |
| 1279 | |
| 1280 // Test navigating to a page that shows an interstitial, has a renderer crash, | |
| 1281 // and then goes back. | |
| 1282 TEST_F(TabContentsTest, ShowInterstitialCrashRendererThenGoBack) { | |
| 1283 // Navigate to a page so we have a navigation entry in the controller. | |
| 1284 GURL url1("http://www.google.com"); | |
| 1285 rvh()->SendNavigate(1, url1); | |
| 1286 EXPECT_EQ(1, controller().entry_count()); | |
| 1287 | |
| 1288 // Show interstitial. | |
| 1289 TestInterstitialPage::InterstitialState state = | |
| 1290 TestInterstitialPage::UNDECIDED; | |
| 1291 bool deleted = false; | |
| 1292 GURL interstitial_url("http://interstitial"); | |
| 1293 TestInterstitialPage* interstitial = | |
| 1294 new TestInterstitialPage(contents(), true, interstitial_url, | |
| 1295 &state, &deleted); | |
| 1296 TestInterstitialPageStateGuard state_guard(interstitial); | |
| 1297 interstitial->Show(); | |
| 1298 interstitial->TestDidNavigate(2, interstitial_url); | |
| 1299 | |
| 1300 // Crash the renderer | |
| 1301 rvh()->TestOnMessageReceived( | |
| 1302 ViewHostMsg_RenderViewGone( | |
| 1303 0, base::TERMINATION_STATUS_PROCESS_CRASHED, -1)); | |
| 1304 | |
| 1305 // While the interstitial is showing, go back. | |
| 1306 controller().GoBack(); | |
| 1307 rvh()->SendNavigate(1, url1); | |
| 1308 | |
| 1309 // Make sure we are back to the original page and that the interstitial is | |
| 1310 // gone. | |
| 1311 EXPECT_TRUE(deleted); | |
| 1312 EXPECT_EQ(TestInterstitialPage::CANCELED, state); | |
| 1313 NavigationEntry* entry = controller().GetActiveEntry(); | |
| 1314 ASSERT_TRUE(entry); | |
| 1315 EXPECT_EQ(url1.spec(), entry->url().spec()); | |
| 1316 } | |
| 1317 | |
| 1318 // Test navigating to a page that shows an interstitial, has the renderer crash, | |
| 1319 // and then navigates to the interstitial. | |
| 1320 TEST_F(TabContentsTest, ShowInterstitialCrashRendererThenNavigate) { | |
| 1321 // Navigate to a page so we have a navigation entry in the controller. | |
| 1322 GURL url1("http://www.google.com"); | |
| 1323 rvh()->SendNavigate(1, url1); | |
| 1324 EXPECT_EQ(1, controller().entry_count()); | |
| 1325 | |
| 1326 // Show interstitial. | |
| 1327 TestInterstitialPage::InterstitialState state = | |
| 1328 TestInterstitialPage::UNDECIDED; | |
| 1329 bool deleted = false; | |
| 1330 GURL interstitial_url("http://interstitial"); | |
| 1331 TestInterstitialPage* interstitial = | |
| 1332 new TestInterstitialPage(contents(), true, interstitial_url, | |
| 1333 &state, &deleted); | |
| 1334 TestInterstitialPageStateGuard state_guard(interstitial); | |
| 1335 interstitial->Show(); | |
| 1336 | |
| 1337 // Crash the renderer | |
| 1338 rvh()->TestOnMessageReceived( | |
| 1339 ViewHostMsg_RenderViewGone( | |
| 1340 0, base::TERMINATION_STATUS_PROCESS_CRASHED, -1)); | |
| 1341 | |
| 1342 interstitial->TestDidNavigate(2, interstitial_url); | |
| 1343 } | |
| 1344 | |
| 1345 // Test navigating to a page that shows an interstitial, then close the tab. | |
| 1346 TEST_F(TabContentsTest, ShowInterstitialThenCloseTab) { | |
| 1347 // Show interstitial. | |
| 1348 TestInterstitialPage::InterstitialState state = | |
| 1349 TestInterstitialPage::UNDECIDED; | |
| 1350 bool deleted = false; | |
| 1351 GURL url("http://interstitial"); | |
| 1352 TestInterstitialPage* interstitial = | |
| 1353 new TestInterstitialPage(contents(), true, url, &state, &deleted); | |
| 1354 TestInterstitialPageStateGuard state_guard(interstitial); | |
| 1355 interstitial->Show(); | |
| 1356 interstitial->TestDidNavigate(1, url); | |
| 1357 | |
| 1358 // Now close the tab. | |
| 1359 DeleteContents(); | |
| 1360 EXPECT_TRUE(deleted); | |
| 1361 EXPECT_EQ(TestInterstitialPage::CANCELED, state); | |
| 1362 } | |
| 1363 | |
| 1364 // Test that after Proceed is called and an interstitial is still shown, no more | |
| 1365 // commands get executed. | |
| 1366 TEST_F(TabContentsTest, ShowInterstitialProceedMultipleCommands) { | |
| 1367 // Navigate to a page so we have a navigation entry in the controller. | |
| 1368 GURL url1("http://www.google.com"); | |
| 1369 rvh()->SendNavigate(1, url1); | |
| 1370 EXPECT_EQ(1, controller().entry_count()); | |
| 1371 | |
| 1372 // Show an interstitial. | |
| 1373 TestInterstitialPage::InterstitialState state = | |
| 1374 TestInterstitialPage::UNDECIDED; | |
| 1375 bool deleted = false; | |
| 1376 GURL url2("http://interstitial"); | |
| 1377 TestInterstitialPage* interstitial = | |
| 1378 new TestInterstitialPage(contents(), true, url2, &state, &deleted); | |
| 1379 TestInterstitialPageStateGuard state_guard(interstitial); | |
| 1380 interstitial->Show(); | |
| 1381 interstitial->TestDidNavigate(1, url2); | |
| 1382 | |
| 1383 // Run a command. | |
| 1384 EXPECT_EQ(0, interstitial->command_received_count()); | |
| 1385 interstitial->TestDomOperationResponse("toto"); | |
| 1386 EXPECT_EQ(1, interstitial->command_received_count()); | |
| 1387 | |
| 1388 // Then proceed. | |
| 1389 interstitial->Proceed(); | |
| 1390 ASSERT_FALSE(deleted); | |
| 1391 | |
| 1392 // While the navigation to the new page is pending, send other commands, they | |
| 1393 // should be ignored. | |
| 1394 interstitial->TestDomOperationResponse("hello"); | |
| 1395 interstitial->TestDomOperationResponse("hi"); | |
| 1396 EXPECT_EQ(1, interstitial->command_received_count()); | |
| 1397 } | |
| 1398 | |
| 1399 // Test showing an interstitial while another interstitial is already showing. | |
| 1400 TEST_F(TabContentsTest, ShowInterstitialOnInterstitial) { | |
| 1401 // Navigate to a page so we have a navigation entry in the controller. | |
| 1402 GURL start_url("http://www.google.com"); | |
| 1403 rvh()->SendNavigate(1, start_url); | |
| 1404 EXPECT_EQ(1, controller().entry_count()); | |
| 1405 | |
| 1406 // Show an interstitial. | |
| 1407 TestInterstitialPage::InterstitialState state1 = | |
| 1408 TestInterstitialPage::UNDECIDED; | |
| 1409 bool deleted1 = false; | |
| 1410 GURL url1("http://interstitial1"); | |
| 1411 TestInterstitialPage* interstitial1 = | |
| 1412 new TestInterstitialPage(contents(), true, url1, &state1, &deleted1); | |
| 1413 TestInterstitialPageStateGuard state_guard1(interstitial1); | |
| 1414 interstitial1->Show(); | |
| 1415 interstitial1->TestDidNavigate(1, url1); | |
| 1416 | |
| 1417 // Now show another interstitial. | |
| 1418 TestInterstitialPage::InterstitialState state2 = | |
| 1419 TestInterstitialPage::UNDECIDED; | |
| 1420 bool deleted2 = false; | |
| 1421 GURL url2("http://interstitial2"); | |
| 1422 TestInterstitialPage* interstitial2 = | |
| 1423 new TestInterstitialPage(contents(), true, url2, &state2, &deleted2); | |
| 1424 TestInterstitialPageStateGuard state_guard2(interstitial2); | |
| 1425 interstitial2->Show(); | |
| 1426 interstitial2->TestDidNavigate(1, url2); | |
| 1427 | |
| 1428 // Showing interstitial2 should have caused interstitial1 to go away. | |
| 1429 EXPECT_TRUE(deleted1); | |
| 1430 EXPECT_EQ(TestInterstitialPage::CANCELED, state1); | |
| 1431 | |
| 1432 // Let's make sure interstitial2 is working as intended. | |
| 1433 ASSERT_FALSE(deleted2); | |
| 1434 EXPECT_EQ(TestInterstitialPage::UNDECIDED, state2); | |
| 1435 interstitial2->Proceed(); | |
| 1436 GURL landing_url("http://www.thepage.com"); | |
| 1437 rvh()->SendNavigate(2, landing_url); | |
| 1438 | |
| 1439 EXPECT_TRUE(deleted2); | |
| 1440 EXPECT_FALSE(contents()->showing_interstitial_page()); | |
| 1441 EXPECT_TRUE(contents()->interstitial_page() == NULL); | |
| 1442 NavigationEntry* entry = controller().GetActiveEntry(); | |
| 1443 ASSERT_TRUE(entry != NULL); | |
| 1444 EXPECT_TRUE(entry->url() == landing_url); | |
| 1445 EXPECT_EQ(2, controller().entry_count()); | |
| 1446 } | |
| 1447 | |
| 1448 // Test showing an interstitial, proceeding and then navigating to another | |
| 1449 // interstitial. | |
| 1450 TEST_F(TabContentsTest, ShowInterstitialProceedShowInterstitial) { | |
| 1451 // Navigate to a page so we have a navigation entry in the controller. | |
| 1452 GURL start_url("http://www.google.com"); | |
| 1453 rvh()->SendNavigate(1, start_url); | |
| 1454 EXPECT_EQ(1, controller().entry_count()); | |
| 1455 | |
| 1456 // Show an interstitial. | |
| 1457 TestInterstitialPage::InterstitialState state1 = | |
| 1458 TestInterstitialPage::UNDECIDED; | |
| 1459 bool deleted1 = false; | |
| 1460 GURL url1("http://interstitial1"); | |
| 1461 TestInterstitialPage* interstitial1 = | |
| 1462 new TestInterstitialPage(contents(), true, url1, &state1, &deleted1); | |
| 1463 TestInterstitialPageStateGuard state_guard1(interstitial1); | |
| 1464 interstitial1->Show(); | |
| 1465 interstitial1->TestDidNavigate(1, url1); | |
| 1466 | |
| 1467 // Take action. The interstitial won't be hidden until the navigation is | |
| 1468 // committed. | |
| 1469 interstitial1->Proceed(); | |
| 1470 EXPECT_EQ(TestInterstitialPage::OKED, state1); | |
| 1471 | |
| 1472 // Now show another interstitial (simulating the navigation causing another | |
| 1473 // interstitial). | |
| 1474 TestInterstitialPage::InterstitialState state2 = | |
| 1475 TestInterstitialPage::UNDECIDED; | |
| 1476 bool deleted2 = false; | |
| 1477 GURL url2("http://interstitial2"); | |
| 1478 TestInterstitialPage* interstitial2 = | |
| 1479 new TestInterstitialPage(contents(), true, url2, &state2, &deleted2); | |
| 1480 TestInterstitialPageStateGuard state_guard2(interstitial2); | |
| 1481 interstitial2->Show(); | |
| 1482 interstitial2->TestDidNavigate(1, url2); | |
| 1483 | |
| 1484 // Showing interstitial2 should have caused interstitial1 to go away. | |
| 1485 EXPECT_TRUE(deleted1); | |
| 1486 | |
| 1487 // Let's make sure interstitial2 is working as intended. | |
| 1488 ASSERT_FALSE(deleted2); | |
| 1489 EXPECT_EQ(TestInterstitialPage::UNDECIDED, state2); | |
| 1490 interstitial2->Proceed(); | |
| 1491 GURL landing_url("http://www.thepage.com"); | |
| 1492 rvh()->SendNavigate(2, landing_url); | |
| 1493 | |
| 1494 EXPECT_TRUE(deleted2); | |
| 1495 EXPECT_FALSE(contents()->showing_interstitial_page()); | |
| 1496 EXPECT_TRUE(contents()->interstitial_page() == NULL); | |
| 1497 NavigationEntry* entry = controller().GetActiveEntry(); | |
| 1498 ASSERT_TRUE(entry != NULL); | |
| 1499 EXPECT_TRUE(entry->url() == landing_url); | |
| 1500 EXPECT_EQ(2, controller().entry_count()); | |
| 1501 } | |
| 1502 | |
| 1503 // Test that navigating away from an interstitial while it's loading cause it | |
| 1504 // not to show. | |
| 1505 TEST_F(TabContentsTest, NavigateBeforeInterstitialShows) { | |
| 1506 // Show an interstitial. | |
| 1507 TestInterstitialPage::InterstitialState state = | |
| 1508 TestInterstitialPage::UNDECIDED; | |
| 1509 bool deleted = false; | |
| 1510 GURL interstitial_url("http://interstitial"); | |
| 1511 TestInterstitialPage* interstitial = | |
| 1512 new TestInterstitialPage(contents(), true, interstitial_url, | |
| 1513 &state, &deleted); | |
| 1514 TestInterstitialPageStateGuard state_guard(interstitial); | |
| 1515 interstitial->Show(); | |
| 1516 | |
| 1517 // Let's simulate a navigation initiated from the browser before the | |
| 1518 // interstitial finishes loading. | |
| 1519 const GURL url("http://www.google.com"); | |
| 1520 controller().LoadURL( | |
| 1521 url, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); | |
| 1522 ASSERT_FALSE(deleted); | |
| 1523 EXPECT_FALSE(interstitial->is_showing()); | |
| 1524 | |
| 1525 // Now let's make the interstitial navigation commit. | |
| 1526 interstitial->TestDidNavigate(1, interstitial_url); | |
| 1527 | |
| 1528 // After it loaded the interstitial should be gone. | |
| 1529 EXPECT_TRUE(deleted); | |
| 1530 EXPECT_EQ(TestInterstitialPage::CANCELED, state); | |
| 1531 } | |
| 1532 | |
| 1533 // Test that a new request to show an interstitial while an interstitial is | |
| 1534 // pending does not cause problems. htp://crbug/29655 and htp://crbug/9442. | |
| 1535 TEST_F(TabContentsTest, TwoQuickInterstitials) { | |
| 1536 GURL interstitial_url("http://interstitial"); | |
| 1537 | |
| 1538 // Show a first interstitial. | |
| 1539 TestInterstitialPage::InterstitialState state1 = | |
| 1540 TestInterstitialPage::UNDECIDED; | |
| 1541 bool deleted1 = false; | |
| 1542 TestInterstitialPage* interstitial1 = | |
| 1543 new TestInterstitialPage(contents(), true, interstitial_url, | |
| 1544 &state1, &deleted1); | |
| 1545 TestInterstitialPageStateGuard state_guard1(interstitial1); | |
| 1546 interstitial1->Show(); | |
| 1547 | |
| 1548 // Show another interstitial on that same tab before the first one had time | |
| 1549 // to load. | |
| 1550 TestInterstitialPage::InterstitialState state2 = | |
| 1551 TestInterstitialPage::UNDECIDED; | |
| 1552 bool deleted2 = false; | |
| 1553 TestInterstitialPage* interstitial2 = | |
| 1554 new TestInterstitialPage(contents(), true, interstitial_url, | |
| 1555 &state2, &deleted2); | |
| 1556 TestInterstitialPageStateGuard state_guard2(interstitial2); | |
| 1557 interstitial2->Show(); | |
| 1558 | |
| 1559 // The first interstitial should have been closed and deleted. | |
| 1560 EXPECT_TRUE(deleted1); | |
| 1561 EXPECT_EQ(TestInterstitialPage::CANCELED, state1); | |
| 1562 | |
| 1563 // The 2nd one should still be OK. | |
| 1564 ASSERT_FALSE(deleted2); | |
| 1565 EXPECT_EQ(TestInterstitialPage::UNDECIDED, state2); | |
| 1566 | |
| 1567 // Make the interstitial navigation commit it should be showing. | |
| 1568 interstitial2->TestDidNavigate(1, interstitial_url); | |
| 1569 EXPECT_EQ(interstitial2, contents()->interstitial_page()); | |
| 1570 } | |
| 1571 | |
| 1572 // Test showing an interstitial and have its renderer crash. | |
| 1573 TEST_F(TabContentsTest, InterstitialCrasher) { | |
| 1574 // Show an interstitial. | |
| 1575 TestInterstitialPage::InterstitialState state = | |
| 1576 TestInterstitialPage::UNDECIDED; | |
| 1577 bool deleted = false; | |
| 1578 GURL url("http://interstitial"); | |
| 1579 TestInterstitialPage* interstitial = | |
| 1580 new TestInterstitialPage(contents(), true, url, &state, &deleted); | |
| 1581 TestInterstitialPageStateGuard state_guard(interstitial); | |
| 1582 interstitial->Show(); | |
| 1583 // Simulate a renderer crash before the interstitial is shown. | |
| 1584 interstitial->TestRenderViewGone( | |
| 1585 base::TERMINATION_STATUS_PROCESS_CRASHED, -1); | |
| 1586 // The interstitial should have been dismissed. | |
| 1587 EXPECT_TRUE(deleted); | |
| 1588 EXPECT_EQ(TestInterstitialPage::CANCELED, state); | |
| 1589 | |
| 1590 // Now try again but this time crash the intersitial after it was shown. | |
| 1591 interstitial = | |
| 1592 new TestInterstitialPage(contents(), true, url, &state, &deleted); | |
| 1593 interstitial->Show(); | |
| 1594 interstitial->TestDidNavigate(1, url); | |
| 1595 // Simulate a renderer crash. | |
| 1596 interstitial->TestRenderViewGone( | |
| 1597 base::TERMINATION_STATUS_PROCESS_CRASHED, -1); | |
| 1598 // The interstitial should have been dismissed. | |
| 1599 EXPECT_TRUE(deleted); | |
| 1600 EXPECT_EQ(TestInterstitialPage::CANCELED, state); | |
| 1601 } | |
| 1602 | |
| 1603 // Tests that showing an interstitial as a result of a browser initiated | |
| 1604 // navigation while an interstitial is showing does not remove the pending | |
| 1605 // entry (see http://crbug.com/9791). | |
| 1606 TEST_F(TabContentsTest, NewInterstitialDoesNotCancelPendingEntry) { | |
| 1607 const char kUrl[] = "http://www.badguys.com/"; | |
| 1608 const GURL kGURL(kUrl); | |
| 1609 | |
| 1610 // Start a navigation to a page | |
| 1611 contents()->controller().LoadURL( | |
| 1612 kGURL, content::Referrer(), content::PAGE_TRANSITION_TYPED, | |
| 1613 std::string()); | |
| 1614 | |
| 1615 // Simulate that navigation triggering an interstitial. | |
| 1616 TestInterstitialPage::InterstitialState state = | |
| 1617 TestInterstitialPage::UNDECIDED; | |
| 1618 bool deleted = false; | |
| 1619 TestInterstitialPage* interstitial = | |
| 1620 new TestInterstitialPage(contents(), true, kGURL, &state, &deleted); | |
| 1621 TestInterstitialPageStateGuard state_guard(interstitial); | |
| 1622 interstitial->Show(); | |
| 1623 interstitial->TestDidNavigate(1, kGURL); | |
| 1624 | |
| 1625 // Initiate a new navigation from the browser that also triggers an | |
| 1626 // interstitial. | |
| 1627 contents()->controller().LoadURL( | |
| 1628 kGURL, content::Referrer(), content::PAGE_TRANSITION_TYPED, | |
| 1629 std::string()); | |
| 1630 TestInterstitialPage::InterstitialState state2 = | |
| 1631 TestInterstitialPage::UNDECIDED; | |
| 1632 bool deleted2 = false; | |
| 1633 TestInterstitialPage* interstitial2 = | |
| 1634 new TestInterstitialPage(contents(), true, kGURL, &state, &deleted); | |
| 1635 TestInterstitialPageStateGuard state_guard2(interstitial2); | |
| 1636 interstitial2->Show(); | |
| 1637 interstitial2->TestDidNavigate(1, kGURL); | |
| 1638 | |
| 1639 // Make sure we still have an entry. | |
| 1640 NavigationEntry* entry = contents()->controller().pending_entry(); | |
| 1641 ASSERT_TRUE(entry); | |
| 1642 EXPECT_EQ(kUrl, entry->url().spec()); | |
| 1643 | |
| 1644 // And that the first interstitial is gone, but not the second. | |
| 1645 EXPECT_TRUE(deleted); | |
| 1646 EXPECT_EQ(TestInterstitialPage::CANCELED, state); | |
| 1647 EXPECT_FALSE(deleted2); | |
| 1648 EXPECT_EQ(TestInterstitialPage::UNDECIDED, state2); | |
| 1649 } | |
| 1650 | |
| 1651 // Tests that Javascript messages are not shown while an interstitial is | |
| 1652 // showing. | |
| 1653 TEST_F(TabContentsTest, NoJSMessageOnInterstitials) { | |
| 1654 const char kUrl[] = "http://www.badguys.com/"; | |
| 1655 const GURL kGURL(kUrl); | |
| 1656 | |
| 1657 // Start a navigation to a page | |
| 1658 contents()->controller().LoadURL( | |
| 1659 kGURL, content::Referrer(), content::PAGE_TRANSITION_TYPED, | |
| 1660 std::string()); | |
| 1661 // DidNavigate from the page | |
| 1662 contents()->TestDidNavigate(rvh(), 1, kGURL, content::PAGE_TRANSITION_TYPED); | |
| 1663 | |
| 1664 // Simulate showing an interstitial while the page is showing. | |
| 1665 TestInterstitialPage::InterstitialState state = | |
| 1666 TestInterstitialPage::UNDECIDED; | |
| 1667 bool deleted = false; | |
| 1668 TestInterstitialPage* interstitial = | |
| 1669 new TestInterstitialPage(contents(), true, kGURL, &state, &deleted); | |
| 1670 TestInterstitialPageStateGuard state_guard(interstitial); | |
| 1671 interstitial->Show(); | |
| 1672 interstitial->TestDidNavigate(1, kGURL); | |
| 1673 | |
| 1674 // While the interstitial is showing, let's simulate the hidden page | |
| 1675 // attempting to show a JS message. | |
| 1676 IPC::Message* dummy_message = new IPC::Message; | |
| 1677 bool did_suppress_message = false; | |
| 1678 contents()->RunJavaScriptMessage(contents()->render_view_host(), | |
| 1679 ASCIIToUTF16("This is an informative message"), ASCIIToUTF16("OK"), | |
| 1680 kGURL, ui::MessageBoxFlags::kIsJavascriptAlert, dummy_message, | |
| 1681 &did_suppress_message); | |
| 1682 EXPECT_TRUE(did_suppress_message); | |
| 1683 } | |
| 1684 | |
| 1685 // Makes sure that if the source passed to CopyStateFromAndPrune has an | |
| 1686 // interstitial it isn't copied over to the destination. | |
| 1687 TEST_F(TabContentsTest, CopyStateFromAndPruneSourceInterstitial) { | |
| 1688 // Navigate to a page. | |
| 1689 GURL url1("http://www.google.com"); | |
| 1690 rvh()->SendNavigate(1, url1); | |
| 1691 EXPECT_EQ(1, controller().entry_count()); | |
| 1692 | |
| 1693 // Initiate a browser navigation that will trigger the interstitial | |
| 1694 controller().LoadURL(GURL("http://www.evil.com"), content::Referrer(), | |
| 1695 content::PAGE_TRANSITION_TYPED, std::string()); | |
| 1696 | |
| 1697 // Show an interstitial. | |
| 1698 TestInterstitialPage::InterstitialState state = | |
| 1699 TestInterstitialPage::UNDECIDED; | |
| 1700 bool deleted = false; | |
| 1701 GURL url2("http://interstitial"); | |
| 1702 TestInterstitialPage* interstitial = | |
| 1703 new TestInterstitialPage(contents(), true, url2, &state, &deleted); | |
| 1704 TestInterstitialPageStateGuard state_guard(interstitial); | |
| 1705 interstitial->Show(); | |
| 1706 interstitial->TestDidNavigate(1, url2); | |
| 1707 EXPECT_TRUE(interstitial->is_showing()); | |
| 1708 EXPECT_EQ(2, controller().entry_count()); | |
| 1709 | |
| 1710 // Create another NavigationController. | |
| 1711 GURL url3("http://foo2"); | |
| 1712 scoped_ptr<TestTabContents> other_contents(CreateTestTabContents()); | |
| 1713 NavigationController& other_controller = other_contents->controller(); | |
| 1714 other_contents->NavigateAndCommit(url3); | |
| 1715 other_contents->ExpectSetHistoryLengthAndPrune( | |
| 1716 other_controller.GetEntryAtIndex(0)->site_instance(), 1, | |
| 1717 other_controller.GetEntryAtIndex(0)->page_id()); | |
| 1718 other_controller.CopyStateFromAndPrune(&controller()); | |
| 1719 | |
| 1720 // The merged controller should only have two entries: url1 and url2. | |
| 1721 ASSERT_EQ(2, other_controller.entry_count()); | |
| 1722 EXPECT_EQ(1, other_controller.GetCurrentEntryIndex()); | |
| 1723 EXPECT_EQ(url1, other_controller.GetEntryAtIndex(0)->url()); | |
| 1724 EXPECT_EQ(url3, other_controller.GetEntryAtIndex(1)->url()); | |
| 1725 | |
| 1726 // And the merged controller shouldn't be showing an interstitial. | |
| 1727 EXPECT_FALSE(other_contents->showing_interstitial_page()); | |
| 1728 } | |
| 1729 | |
| 1730 // Makes sure that CopyStateFromAndPrune does the right thing if the object | |
| 1731 // CopyStateFromAndPrune is invoked on is showing an interstitial. | |
| 1732 TEST_F(TabContentsTest, CopyStateFromAndPruneTargetInterstitial) { | |
| 1733 // Navigate to a page. | |
| 1734 GURL url1("http://www.google.com"); | |
| 1735 contents()->NavigateAndCommit(url1); | |
| 1736 | |
| 1737 // Create another NavigationController. | |
| 1738 scoped_ptr<TestTabContents> other_contents(CreateTestTabContents()); | |
| 1739 NavigationController& other_controller = other_contents->controller(); | |
| 1740 | |
| 1741 // Navigate it to url2. | |
| 1742 GURL url2("http://foo2"); | |
| 1743 other_contents->NavigateAndCommit(url2); | |
| 1744 | |
| 1745 // Show an interstitial. | |
| 1746 TestInterstitialPage::InterstitialState state = | |
| 1747 TestInterstitialPage::UNDECIDED; | |
| 1748 bool deleted = false; | |
| 1749 GURL url3("http://interstitial"); | |
| 1750 TestInterstitialPage* interstitial = | |
| 1751 new TestInterstitialPage(other_contents.get(), true, url3, &state, | |
| 1752 &deleted); | |
| 1753 TestInterstitialPageStateGuard state_guard(interstitial); | |
| 1754 interstitial->Show(); | |
| 1755 interstitial->TestDidNavigate(1, url3); | |
| 1756 EXPECT_TRUE(interstitial->is_showing()); | |
| 1757 EXPECT_EQ(2, other_controller.entry_count()); | |
| 1758 other_contents->ExpectSetHistoryLengthAndPrune( | |
| 1759 other_controller.GetEntryAtIndex(0)->site_instance(), 1, | |
| 1760 other_controller.GetEntryAtIndex(0)->page_id()); | |
| 1761 other_controller.CopyStateFromAndPrune(&controller()); | |
| 1762 | |
| 1763 // The merged controller should only have two entries: url1 and url2. | |
| 1764 ASSERT_EQ(2, other_controller.entry_count()); | |
| 1765 EXPECT_EQ(1, other_controller.GetCurrentEntryIndex()); | |
| 1766 EXPECT_EQ(url1, other_controller.GetEntryAtIndex(0)->url()); | |
| 1767 EXPECT_EQ(url3, other_controller.GetEntryAtIndex(1)->url()); | |
| 1768 | |
| 1769 // It should have a transient entry. | |
| 1770 EXPECT_TRUE(other_controller.GetTransientEntry()); | |
| 1771 | |
| 1772 // And the interstitial should be showing. | |
| 1773 EXPECT_TRUE(other_contents->showing_interstitial_page()); | |
| 1774 | |
| 1775 // And the interstitial should do a reload on don't proceed. | |
| 1776 EXPECT_TRUE(other_contents->interstitial_page()->reload_on_dont_proceed()); | |
| 1777 } | |
| OLD | NEW |