// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/logging.h" #include "chrome/browser/interstitial_page.h" #include "chrome/browser/navigation_controller.h" #include "chrome/browser/navigation_entry.h" #include "chrome/browser/render_view_host.h" #include "chrome/browser/render_widget_host_view.h" #include "chrome/browser/web_contents.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/ipc_channel.h" #include "chrome/common/pref_service.h" #include "chrome/common/render_messages.h" #include "chrome/test/testing_profile.h" #include "testing/gtest/include/gtest/gtest.h" // Subclass the RenderViewHost's view so that we can call Show(), etc., // without having side-effects. class TestRenderWidgetHostView : public RenderWidgetHostView { public: TestRenderWidgetHostView() {} virtual RenderWidgetHost* GetRenderWidgetHost() const { return NULL; } virtual void DidBecomeSelected() {} virtual void WasHidden() {} virtual void SetSize(const gfx::Size& size) {} virtual HWND GetPluginHWND() { return NULL; } virtual HANDLE ModalDialogEvent() { return NULL; } virtual void ForwardMouseEventToRenderer(UINT message, WPARAM wparam, LPARAM lparam) {} virtual void Focus() {} virtual void Blur() {} virtual bool HasFocus() { return true; } virtual void AdvanceFocus(bool reverse) {} virtual void Show() {} virtual void Hide() {} virtual gfx::Rect GetViewBounds() const { return gfx::Rect(); } virtual void UpdateCursor(const WebCursor& cursor) {} virtual void UpdateCursorIfOverSelf() {} // Indicates if the page has finished loading. virtual void SetIsLoading(bool is_loading) {} virtual void IMEUpdateStatus(ViewHostMsg_ImeControl control, const gfx::Rect& caret_rect) {} virtual void DidPaintRect(const gfx::Rect& rect) {} virtual void DidScrollRect(const gfx::Rect& rect, int dx, int dy) {} virtual void RendererGone() {} virtual void Destroy() {} virtual void PrepareToDestroy() {} virtual void SetTooltipText(const std::wstring& tooltip_text) {} }; // Subclass RenderViewHost so that it does not create a process. class TestRenderViewHost : public RenderViewHost { public: TestRenderViewHost( SiteInstance* instance, RenderViewHostDelegate* delegate, int routing_id, HANDLE modal_dialog_event) : RenderViewHost(instance, delegate, routing_id, modal_dialog_event), is_loading(false), is_created(false), immediate_before_unload(true), delete_counter_(NULL) { set_view(new TestRenderWidgetHostView()); } ~TestRenderViewHost() { // Track the delete if we've been asked to. if (delete_counter_) ++*delete_counter_; // Since this isn't a traditional view, we have to delete it. delete view_; } // If set, *delete_counter is incremented when this object destructs. void set_delete_counter(int* delete_counter) { delete_counter_ = delete_counter; } bool CreateRenderView() { is_created = true; return true; } bool IsRenderViewLive() const { return is_created; } bool IsNavigationSuspended() { return navigations_suspended_; } void NavigateToEntry(const NavigationEntry& entry, bool is_reload) { is_loading = true; } void LoadAlternateHTMLString(const std::string& html_text, bool new_navigation, const GURL& display_url, const std::string& security_info) { is_loading = true; } // Support for onbeforeunload, onunload void FirePageBeforeUnload() { is_waiting_for_unload_ack_ = true; if (immediate_before_unload) delegate()->ShouldClosePage(true); } void ClosePage(int new_render_process_host_id, int new_request_id) { // Nothing to do here... This would cause a ClosePage_ACK to be sent to // ResourceDispatcherHost, so we can simulate that manually. } void TestOnMsgShouldClose(bool proceed) { OnMsgShouldCloseACK(proceed); } bool is_loading; bool is_created; bool immediate_before_unload; int* delete_counter_; }; // Factory to create TestRenderViewHosts. class TestRenderViewHostFactory : public RenderViewHostFactory { public: static TestRenderViewHostFactory* GetInstance() { static TestRenderViewHostFactory instance; return &instance; } virtual RenderViewHost* CreateRenderViewHost( SiteInstance* instance, RenderViewHostDelegate* delegate, int routing_id, HANDLE modal_dialog_event) { return new TestRenderViewHost( instance, delegate, routing_id, modal_dialog_event); } private: TestRenderViewHostFactory() {} }; // Subclass the TestingProfile so that it can return certain services we need. class WebContentsTestingProfile : public TestingProfile { public: WebContentsTestingProfile() : TestingProfile() { } virtual PrefService* GetPrefs() { if (!prefs_.get()) { std::wstring source_path; PathService::Get(chrome::DIR_TEST_DATA, &source_path); file_util::AppendToPath(&source_path, L"profiles"); file_util::AppendToPath(&source_path, L"chrome_prefs"); file_util::AppendToPath(&source_path, L"Preferences"); prefs_.reset(new PrefService(source_path)); Profile::RegisterUserPrefs(prefs_.get()); browser::RegisterAllPrefs(prefs_.get(), prefs_.get()); } return prefs_.get(); } }; // Subclass WebContents to ensure it creates TestRenderViewHosts and does // not do anything involving views. class TestWebContents : public WebContents { public: TestWebContents(Profile* profile, SiteInstance* instance) : WebContents(profile, instance, TestRenderViewHostFactory::GetInstance(), MSG_ROUTING_NONE, NULL), transition_cross_site(false) {} // Accessors for interesting fields TestRenderViewHost* rvh() { return static_cast( render_manager_.render_view_host_); } TestRenderViewHost* pending_rvh() { return static_cast( render_manager_.pending_render_view_host_); } TestRenderViewHost* interstitial_rvh() { return static_cast( render_manager_.interstitial_render_view_host_); } TestRenderViewHost* original_rvh() { return static_cast( render_manager_.original_render_view_host_); } // State accessors. bool state_is_normal() const { return render_manager_.renderer_state_ == RenderViewHostManager::NORMAL; } bool state_is_pending() const { return render_manager_.renderer_state_ == RenderViewHostManager::PENDING; } bool state_is_entering_interstitial() const { return render_manager_.renderer_state_ == RenderViewHostManager::ENTERING_INTERSTITIAL; } bool state_is_interstitial() const { return render_manager_.renderer_state_ == RenderViewHostManager::INTERSTITIAL; } bool state_is_leaving_interstitial() const { return render_manager_.renderer_state_ == RenderViewHostManager::LEAVING_INTERSTITIAL; } // Ensure we create TestRenderViewHosts that don't spawn processes. RenderViewHost* CreateRenderViewHost(SiteInstance* instance, RenderViewHostDelegate* delegate, int routing_id, HANDLE modal_dialog_event) { return new TestRenderViewHost( instance, delegate, routing_id, modal_dialog_event); } // Overrides WebContents::ShouldTransitionCrossSite so that we can test both // alternatives without using command-line switches. bool ShouldTransitionCrossSite() { return transition_cross_site; } // Promote DidNavigate to public. void TestDidNavigate(TestRenderViewHost* render_view_host, const ViewHostMsg_FrameNavigate_Params& params) { DidNavigate(render_view_host, params); render_view_host->is_loading = false; } // Promote GetWebkitPrefs to public. WebPreferences TestGetWebkitPrefs() { return GetWebkitPrefs(); } // Prevent interaction with views. bool CreateRenderViewForRenderManager(RenderViewHost* render_view_host) { // This will go to a TestRenderViewHost. render_view_host->CreateRenderView(); return true; } void UpdateRenderViewSizeForRenderManager() {} // Set by individual tests. bool transition_cross_site; }; class WebContentsTest : public testing::Test { public: WebContentsTest() : contents(NULL) {} void InitNavigateParams(ViewHostMsg_FrameNavigate_Params* params, int pageID, const GURL& url) { params->page_id = pageID; params->url = url; params->referrer = GURL::EmptyGURL(); params->transition = PageTransition::TYPED; params->redirects = std::vector(); params->should_update_history = false; params->searchable_form_url = GURL::EmptyGURL(); params->searchable_form_element_name = std::wstring(); params->searchable_form_encoding = std::string(); params->password_form = PasswordForm(); params->security_info = std::string(); params->gesture = NavigationGestureUser; params->is_post = false; } // testing::Test methods: virtual void SetUp() { profile.reset(new WebContentsTestingProfile()); // This will be deleted when the WebContents goes away SiteInstance* instance = SiteInstance::CreateSiteInstance(profile.get()); contents = new TestWebContents(profile.get(), instance); contents->SetupController(profile.get()); } virtual void TearDown() { // This will delete the contents. contents->CloseContents(); // Make sure that we flush any messages related to WebContents destruction // before we destroy the profile. MessageLoop::current()->RunAllPending(); } scoped_ptr profile; TestWebContents* contents; private: MessageLoopForUI message_loop_; }; // Test to make sure that title updates get stripped of whitespace. TEST_F(WebContentsTest, UpdateTitle) { ViewHostMsg_FrameNavigate_Params params; InitNavigateParams(¶ms, 0, GURL("about:blank")); NavigationController::LoadCommittedDetails details; contents->controller()->RendererDidNavigate(params, false, &details); contents->UpdateTitle(NULL, 0, L" Lots O' Whitespace\n"); EXPECT_EQ(std::wstring(L"Lots O' Whitespace"), contents->GetTitle()); } // Test simple same-SiteInstance navigation. TEST_F(WebContentsTest, SimpleNavigation) { TestRenderViewHost* orig_rvh = contents->rvh(); SiteInstance* instance1 = contents->GetSiteInstance(); EXPECT_TRUE(contents->pending_rvh() == NULL); EXPECT_TRUE(contents->original_rvh() == NULL); EXPECT_TRUE(contents->interstitial_rvh() == NULL); EXPECT_FALSE(orig_rvh->is_loading); // Navigate to URL const GURL url("http://www.google.com"); contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); EXPECT_TRUE(contents->state_is_normal()); EXPECT_TRUE(orig_rvh->is_loading); EXPECT_EQ(instance1, orig_rvh->site_instance()); // Controller's pending entry will have a NULL site instance until we assign // it in DidNavigate. EXPECT_TRUE( contents->controller()->GetActiveEntry()->site_instance() == NULL); // DidNavigate from the page ViewHostMsg_FrameNavigate_Params params; InitNavigateParams(¶ms, 1, url); contents->TestDidNavigate(orig_rvh, params); EXPECT_TRUE(contents->state_is_normal()); EXPECT_EQ(orig_rvh, contents->render_view_host()); EXPECT_EQ(instance1, orig_rvh->site_instance()); // Controller's entry should now have the SiteInstance, or else we won't be // able to find it later. EXPECT_EQ(instance1, contents->controller()->GetActiveEntry()->site_instance()); } // Test navigating to a page that shows an interstitial, then hiding it // without proceeding. TEST_F(WebContentsTest, ShowInterstitialDontProceed) { TestRenderViewHost* orig_rvh = contents->rvh(); EXPECT_TRUE(contents->pending_rvh() == NULL); EXPECT_TRUE(contents->original_rvh() == NULL); EXPECT_TRUE(contents->interstitial_rvh() == NULL); EXPECT_FALSE(orig_rvh->is_loading); // Navigate to URL const GURL url("http://www.google.com"); contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); EXPECT_TRUE(contents->state_is_normal()); EXPECT_TRUE(orig_rvh->is_loading); // Show interstitial const GURL interstitial_url("http://interstitial"); InterstitialPage* interstitial = new InterstitialPage(contents, true, interstitial_url); interstitial->Show(); EXPECT_TRUE(contents->state_is_entering_interstitial()); TestRenderViewHost* interstitial_rvh = contents->interstitial_rvh(); EXPECT_TRUE(orig_rvh->is_loading); // Still loading in the background EXPECT_TRUE(interstitial_rvh->is_loading); // DidNavigate from the interstitial ViewHostMsg_FrameNavigate_Params params; InitNavigateParams(¶ms, 1, url); contents->TestDidNavigate(interstitial_rvh, params); EXPECT_TRUE(contents->state_is_interstitial()); EXPECT_EQ(interstitial_rvh, contents->render_view_host()); EXPECT_EQ(orig_rvh, contents->original_rvh()); EXPECT_FALSE(interstitial_rvh->is_loading); // Hide interstitial (don't proceed) contents->HideInterstitialPage(false, false); EXPECT_TRUE(contents->state_is_normal()); EXPECT_EQ(orig_rvh, contents->render_view_host()); EXPECT_TRUE(contents->original_rvh() == NULL); EXPECT_TRUE(contents->interstitial_rvh() == NULL); } // Test navigating to a page that shows an interstitial, then proceeding. TEST_F(WebContentsTest, ShowInterstitialProceed) { TestRenderViewHost* orig_rvh = contents->rvh(); // The RenderViewHost's SiteInstance should not yet have a site. EXPECT_EQ(GURL(), contents->rvh()->site_instance()->site()); // Navigate to URL const GURL url("http://www.google.com"); contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); // Show interstitial const GURL interstitial_url("http://interstitial"); InterstitialPage* interstitial = new InterstitialPage(contents, true, interstitial_url); interstitial->Show(); TestRenderViewHost* interstitial_rvh = contents->interstitial_rvh(); // DidNavigate from the interstitial ViewHostMsg_FrameNavigate_Params params; InitNavigateParams(¶ms, 1, url); contents->TestDidNavigate(interstitial_rvh, params); // Ensure this DidNavigate hasn't changed the SiteInstance's site. // Prevents regression for bug 1163298. EXPECT_EQ(GURL(), contents->rvh()->site_instance()->site()); // Hide interstitial (proceed and wait) contents->HideInterstitialPage(true, true); EXPECT_TRUE(contents->state_is_leaving_interstitial()); EXPECT_EQ(interstitial_rvh, contents->render_view_host()); EXPECT_EQ(orig_rvh, contents->original_rvh()); // DidNavigate from the destination page contents->TestDidNavigate(orig_rvh, params); EXPECT_TRUE(contents->state_is_normal()); EXPECT_EQ(orig_rvh, contents->render_view_host()); EXPECT_TRUE(contents->original_rvh() == NULL); EXPECT_TRUE(contents->interstitial_rvh() == NULL); // The SiteInstance's site should now be updated. EXPECT_EQ(GURL("http://google.com"), contents->rvh()->site_instance()->site()); // Since we weren't viewing a page before, we shouldn't be able to go back. EXPECT_FALSE(contents->controller()->CanGoBack()); } // Test navigating to a page that shows an interstitial, then navigating away. TEST_F(WebContentsTest, ShowInterstitialThenNavigate) { TestRenderViewHost* orig_rvh = contents->rvh(); // Navigate to URL const GURL url("http://www.google.com"); contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); // Show interstitial const GURL interstitial_url("http://interstitial"); InterstitialPage* interstitial = new InterstitialPage(contents, true, interstitial_url); interstitial->Show(); TestRenderViewHost* interstitial_rvh = contents->interstitial_rvh(); // DidNavigate from the interstitial ViewHostMsg_FrameNavigate_Params params; InitNavigateParams(¶ms, 1, url); contents->TestDidNavigate(interstitial_rvh, params); // While interstitial showing, navigate to a new URL. const GURL url2("http://www.yahoo.com"); contents->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); EXPECT_TRUE(contents->state_is_leaving_interstitial()); EXPECT_EQ(interstitial_rvh, contents->render_view_host()); EXPECT_TRUE(orig_rvh->is_loading); EXPECT_FALSE(interstitial_rvh->is_loading); // DidNavigate from the new URL. In the old process model, we'll still have // the same RenderViewHost. ViewHostMsg_FrameNavigate_Params params2; InitNavigateParams(¶ms2, 2, url2); contents->TestDidNavigate(orig_rvh, params2); EXPECT_TRUE(contents->state_is_normal()); EXPECT_EQ(orig_rvh, contents->render_view_host()); EXPECT_FALSE(orig_rvh->is_loading); } // Ensures that an interstitial cannot be cancelled if a notification for a // navigation from an IFrame from the previous page is received while the // interstitial is being shown (bug #1182394). TEST_F(WebContentsTest, ShowInterstitialIFrameNavigate) { TestRenderViewHost* orig_rvh = contents->rvh(); EXPECT_TRUE(contents->pending_rvh() == NULL); EXPECT_TRUE(contents->original_rvh() == NULL); EXPECT_TRUE(contents->interstitial_rvh() == NULL); EXPECT_FALSE(orig_rvh->is_loading); // Navigate to URL. const GURL url("http://www.google.com"); contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); EXPECT_TRUE(contents->state_is_normal()); EXPECT_TRUE(orig_rvh->is_loading); ViewHostMsg_FrameNavigate_Params params1; InitNavigateParams(¶ms1, 1, url); contents->TestDidNavigate(orig_rvh, params1); // Show interstitial (in real world would probably be triggered by a resource // in the page). const GURL interstitial_url("http://interstitial"); InterstitialPage* interstitial = new InterstitialPage(contents, true, interstitial_url); interstitial->Show(); EXPECT_TRUE(contents->state_is_entering_interstitial()); TestRenderViewHost* interstitial_rvh = contents->interstitial_rvh(); EXPECT_TRUE(interstitial_rvh->is_loading); // DidNavigate from an IFrame in the initial page. ViewHostMsg_FrameNavigate_Params params2; InitNavigateParams(¶ms2, 1, GURL("http://www.iframe.com")); params2.transition = PageTransition::AUTO_SUBFRAME; contents->TestDidNavigate(orig_rvh, params2); // Now we get the DidNavigate from the interstitial. ViewHostMsg_FrameNavigate_Params params3; InitNavigateParams(¶ms3, 1, url); contents->TestDidNavigate(interstitial_rvh, params3); EXPECT_TRUE(contents->state_is_interstitial()); EXPECT_EQ(interstitial_rvh, contents->render_view_host()); EXPECT_EQ(orig_rvh, contents->original_rvh()); EXPECT_FALSE(interstitial_rvh->is_loading); } // Test navigating to an interstitial page from a normal page. Also test // visiting the interstitial-inducing URL twice (bug 1079784), and test // that going back shows the first page and not the interstitial. TEST_F(WebContentsTest, VisitInterstitialURLTwice) { TestRenderViewHost* orig_rvh = contents->rvh(); // Navigate to URL const GURL url("http://www.google.com"); contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); ViewHostMsg_FrameNavigate_Params params1; InitNavigateParams(¶ms1, 1, url); contents->TestDidNavigate(orig_rvh, params1); // Now navigate to an interstitial-inducing URL const GURL url2("https://www.google.com"); contents->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); const GURL interstitial_url("http://interstitial"); InterstitialPage* interstitial = new InterstitialPage(contents, true, interstitial_url); interstitial->Show(); EXPECT_TRUE(contents->state_is_entering_interstitial()); int interstitial_delete_counter = 0; TestRenderViewHost* interstitial_rvh = contents->interstitial_rvh(); interstitial_rvh->set_delete_counter(&interstitial_delete_counter); // DidNavigate from the interstitial ViewHostMsg_FrameNavigate_Params params2; InitNavigateParams(¶ms2, 2, url2); contents->TestDidNavigate(interstitial_rvh, params2); EXPECT_TRUE(contents->state_is_interstitial()); EXPECT_EQ(interstitial_rvh, contents->render_view_host()); // While interstitial showing, navigate to the same URL. contents->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); EXPECT_TRUE(contents->state_is_leaving_interstitial()); EXPECT_EQ(interstitial_rvh, contents->render_view_host()); // Interstitial shown a second time in a different RenderViewHost. interstitial = new InterstitialPage(contents, true, interstitial_url); interstitial->Show(); EXPECT_TRUE(contents->state_is_entering_interstitial()); // We expect the original interstitial has been deleted. EXPECT_EQ(interstitial_delete_counter, 1); TestRenderViewHost* interstitial_rvh2 = contents->interstitial_rvh(); interstitial_rvh2->set_delete_counter(&interstitial_delete_counter); // DidNavigate from the interstitial. ViewHostMsg_FrameNavigate_Params params3; InitNavigateParams(¶ms3, 3, url2); contents->TestDidNavigate(interstitial_rvh2, params3); EXPECT_TRUE(contents->state_is_interstitial()); EXPECT_EQ(interstitial_rvh2, contents->render_view_host()); // Proceed. In the old process model, we'll still have the same // RenderViewHost. contents->HideInterstitialPage(true, true); EXPECT_TRUE(contents->state_is_leaving_interstitial()); ViewHostMsg_FrameNavigate_Params params4; InitNavigateParams(¶ms4, 3, url2); contents->TestDidNavigate(orig_rvh, params4); EXPECT_TRUE(contents->state_is_normal()); // We expect the second interstitial has been deleted. EXPECT_EQ(interstitial_delete_counter, 2); // Now go back. Should take us back to the original page. contents->controller()->GoBack(); EXPECT_TRUE(contents->state_is_normal()); // DidNavigate from going back. contents->TestDidNavigate(orig_rvh, params1); EXPECT_TRUE(contents->state_is_normal()); EXPECT_EQ(orig_rvh, contents->render_view_host()); EXPECT_TRUE(contents->original_rvh() == NULL); EXPECT_TRUE(contents->interstitial_rvh() == NULL); } // Test that navigating across a site boundary creates a new RenderViewHost // with a new SiteInstance. Going back should do the same. TEST_F(WebContentsTest, CrossSiteBoundaries) { contents->transition_cross_site = true; TestRenderViewHost* orig_rvh = contents->rvh(); int orig_rvh_delete_count = 0; orig_rvh->set_delete_counter(&orig_rvh_delete_count); SiteInstance* instance1 = contents->GetSiteInstance(); // Navigate to URL. First URL should use first RenderViewHost. const GURL url("http://www.google.com"); contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); ViewHostMsg_FrameNavigate_Params params1; InitNavigateParams(¶ms1, 1, url); contents->TestDidNavigate(orig_rvh, params1); EXPECT_TRUE(contents->state_is_normal()); EXPECT_EQ(orig_rvh, contents->render_view_host()); EXPECT_TRUE(contents->original_rvh() == NULL); EXPECT_TRUE(contents->interstitial_rvh() == NULL); // Navigate to new site const GURL url2("http://www.yahoo.com"); contents->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); EXPECT_TRUE(contents->state_is_pending()); TestRenderViewHost* pending_rvh = contents->pending_rvh(); int pending_rvh_delete_count = 0; pending_rvh->set_delete_counter(&pending_rvh_delete_count); // DidNavigate from the pending page ViewHostMsg_FrameNavigate_Params params2; InitNavigateParams(¶ms2, 1, url2); contents->TestDidNavigate(pending_rvh, params2); SiteInstance* instance2 = contents->GetSiteInstance(); EXPECT_TRUE(contents->state_is_normal()); EXPECT_EQ(pending_rvh, contents->render_view_host()); EXPECT_NE(instance1, instance2); EXPECT_TRUE(contents->pending_rvh() == NULL); EXPECT_TRUE(contents->original_rvh() == NULL); EXPECT_TRUE(contents->interstitial_rvh() == NULL); EXPECT_EQ(orig_rvh_delete_count, 1); // Going back should switch SiteInstances again. The first SiteInstance is // stored in the NavigationEntry, so it should be the same as at the start. contents->controller()->GoBack(); TestRenderViewHost* goback_rvh = contents->pending_rvh(); EXPECT_TRUE(contents->state_is_pending()); // DidNavigate from the back action contents->TestDidNavigate(goback_rvh, params1); EXPECT_TRUE(contents->state_is_normal()); EXPECT_EQ(goback_rvh, contents->render_view_host()); EXPECT_EQ(pending_rvh_delete_count, 1); EXPECT_EQ(instance1, contents->GetSiteInstance()); } // Test that navigating across a site boundary after a crash creates a new // RVH without requiring a cross-site transition (i.e., PENDING state). TEST_F(WebContentsTest, CrossSiteBoundariesAfterCrash) { contents->transition_cross_site = true; TestRenderViewHost* orig_rvh = contents->rvh(); int orig_rvh_delete_count = 0; orig_rvh->set_delete_counter(&orig_rvh_delete_count); SiteInstance* instance1 = contents->GetSiteInstance(); // Navigate to URL. First URL should use first RenderViewHost. const GURL url("http://www.google.com"); contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); ViewHostMsg_FrameNavigate_Params params1; InitNavigateParams(¶ms1, 1, url); contents->TestDidNavigate(orig_rvh, params1); EXPECT_TRUE(contents->state_is_normal()); EXPECT_EQ(orig_rvh, contents->render_view_host()); EXPECT_TRUE(contents->original_rvh() == NULL); EXPECT_TRUE(contents->interstitial_rvh() == NULL); // Crash the renderer. orig_rvh->is_created = false; // Navigate to new site. We should not go into PENDING. const GURL url2("http://www.yahoo.com"); contents->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); TestRenderViewHost* new_rvh = contents->rvh(); EXPECT_TRUE(contents->state_is_normal()); EXPECT_TRUE(contents->pending_rvh() == NULL); EXPECT_TRUE(contents->original_rvh() == NULL); EXPECT_TRUE(contents->interstitial_rvh() == NULL); EXPECT_NE(orig_rvh, new_rvh); EXPECT_EQ(orig_rvh_delete_count, 1); // DidNavigate from the new page ViewHostMsg_FrameNavigate_Params params2; InitNavigateParams(¶ms2, 1, url2); contents->TestDidNavigate(new_rvh, params2); SiteInstance* instance2 = contents->GetSiteInstance(); EXPECT_TRUE(contents->state_is_normal()); EXPECT_EQ(new_rvh, contents->render_view_host()); EXPECT_NE(instance1, instance2); EXPECT_TRUE(contents->pending_rvh() == NULL); EXPECT_TRUE(contents->original_rvh() == NULL); EXPECT_TRUE(contents->interstitial_rvh() == NULL); } // Test state transitions when showing an interstitial in the new process // model, and then choosing DontProceed. TEST_F(WebContentsTest, CrossSiteInterstitialDontProceed) { contents->transition_cross_site = true; TestRenderViewHost* orig_rvh = contents->rvh(); SiteInstance* instance1 = contents->GetSiteInstance(); // Navigate to URL. First URL should use first RenderViewHost. const GURL url("http://www.google.com"); contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); ViewHostMsg_FrameNavigate_Params params1; InitNavigateParams(¶ms1, 1, url); contents->TestDidNavigate(orig_rvh, params1); EXPECT_TRUE(contents->state_is_normal()); EXPECT_EQ(orig_rvh, contents->render_view_host()); // Navigate to new site const GURL url2("https://www.google.com"); contents->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); EXPECT_TRUE(contents->state_is_pending()); TestRenderViewHost* pending_rvh = contents->pending_rvh(); // Show an interstitial const GURL interstitial_url("http://interstitial"); InterstitialPage* interstitial = new InterstitialPage(contents, true, interstitial_url); interstitial->Show(); EXPECT_TRUE(contents->state_is_entering_interstitial()); EXPECT_EQ(orig_rvh, contents->render_view_host()); EXPECT_EQ(pending_rvh, contents->pending_rvh()); TestRenderViewHost* interstitial_rvh = contents->interstitial_rvh(); // DidNavigate from the interstitial ViewHostMsg_FrameNavigate_Params params2; InitNavigateParams(¶ms2, 2, url2); contents->TestDidNavigate(interstitial_rvh, params2); EXPECT_TRUE(contents->state_is_interstitial()); EXPECT_EQ(interstitial_rvh, contents->render_view_host()); EXPECT_EQ(orig_rvh, contents->original_rvh()); EXPECT_EQ(pending_rvh, contents->pending_rvh()); EXPECT_TRUE(contents->interstitial_rvh() == NULL); // Hide interstitial (don't proceed) contents->HideInterstitialPage(false, false); EXPECT_TRUE(contents->state_is_normal()); EXPECT_EQ(orig_rvh, contents->render_view_host()); EXPECT_TRUE(contents->original_rvh() == NULL); EXPECT_TRUE(contents->pending_rvh() == NULL); EXPECT_TRUE(contents->interstitial_rvh() == NULL); } // Test state transitions when showing an interstitial in the new process // model, and then choosing Proceed. TEST_F(WebContentsTest, CrossSiteInterstitialProceed) { contents->transition_cross_site = true; int orig_rvh_delete_count = 0; TestRenderViewHost* orig_rvh = contents->rvh(); orig_rvh->set_delete_counter(&orig_rvh_delete_count); SiteInstance* instance1 = contents->GetSiteInstance(); // Navigate to URL. First URL should use first RenderViewHost. const GURL url("http://www.google.com"); contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); ViewHostMsg_FrameNavigate_Params params1; InitNavigateParams(¶ms1, 1, url); contents->TestDidNavigate(orig_rvh, params1); // Navigate to new site const GURL url2("https://www.google.com"); contents->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); TestRenderViewHost* pending_rvh = contents->pending_rvh(); int pending_rvh_delete_count = 0; pending_rvh->set_delete_counter(&pending_rvh_delete_count); // Show an interstitial const GURL interstitial_url("http://interstitial"); InterstitialPage* interstitial = new InterstitialPage(contents, true, interstitial_url); interstitial->Show(); TestRenderViewHost* interstitial_rvh = contents->interstitial_rvh(); // DidNavigate from the interstitial ViewHostMsg_FrameNavigate_Params params2; InitNavigateParams(¶ms2, 1, url2); contents->TestDidNavigate(interstitial_rvh, params2); EXPECT_TRUE(contents->state_is_interstitial()); EXPECT_EQ(interstitial_rvh, contents->render_view_host()); EXPECT_EQ(orig_rvh, contents->original_rvh()); EXPECT_EQ(pending_rvh, contents->pending_rvh()); EXPECT_TRUE(contents->interstitial_rvh() == NULL); // Hide interstitial (proceed and wait) contents->HideInterstitialPage(true, true); EXPECT_TRUE(contents->state_is_leaving_interstitial()); EXPECT_EQ(interstitial_rvh, contents->render_view_host()); EXPECT_EQ(orig_rvh, contents->original_rvh()); EXPECT_EQ(pending_rvh, contents->pending_rvh()); EXPECT_TRUE(contents->interstitial_rvh() == NULL); // DidNavigate from the destination page should transition to new renderer ViewHostMsg_FrameNavigate_Params params3; InitNavigateParams(¶ms3, 2, url2); contents->TestDidNavigate(pending_rvh, params3); SiteInstance* instance2 = contents->GetSiteInstance(); EXPECT_TRUE(contents->state_is_normal()); EXPECT_EQ(pending_rvh, contents->render_view_host()); EXPECT_TRUE(contents->original_rvh() == NULL); EXPECT_TRUE(contents->pending_rvh() == NULL); EXPECT_TRUE(contents->interstitial_rvh() == NULL); EXPECT_NE(instance1, instance2); EXPECT_EQ(orig_rvh_delete_count, 1); // The original should be gone. // Since we were viewing a page before, we should be able to go back. EXPECT_TRUE(contents->controller()->CanGoBack()); // Going back should switch SiteInstances again. The first SiteInstance is // stored in the NavigationEntry, so it should be the same as at the start. contents->controller()->GoBack(); TestRenderViewHost* goback_rvh = contents->pending_rvh(); EXPECT_TRUE(contents->state_is_pending()); // DidNavigate from the back action contents->TestDidNavigate(goback_rvh, params1); EXPECT_TRUE(contents->state_is_normal()); EXPECT_EQ(goback_rvh, contents->render_view_host()); EXPECT_EQ(instance1, contents->GetSiteInstance()); EXPECT_EQ(pending_rvh_delete_count, 1); // The second page's rvh should die. } // Tests that we can transition away from an interstitial page. TEST_F(WebContentsTest, CrossSiteInterstitialThenNavigate) { contents->transition_cross_site = true; int orig_rvh_delete_count = 0; TestRenderViewHost* orig_rvh = contents->rvh(); orig_rvh->set_delete_counter(&orig_rvh_delete_count); // Navigate to URL. First URL should use first RenderViewHost. const GURL url("http://www.google.com"); contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); ViewHostMsg_FrameNavigate_Params params1; InitNavigateParams(¶ms1, 1, url); contents->TestDidNavigate(orig_rvh, params1); // Show an interstitial const GURL interstitial_url("http://interstitial"); InterstitialPage* interstitial = new InterstitialPage(contents, false, interstitial_url); interstitial->Show(); TestRenderViewHost* interstitial_rvh = contents->interstitial_rvh(); // DidNavigate from the interstitial ViewHostMsg_FrameNavigate_Params params2; InitNavigateParams(¶ms2, 1, url); contents->TestDidNavigate(interstitial_rvh, params2); EXPECT_TRUE(contents->state_is_interstitial()); EXPECT_EQ(interstitial_rvh, contents->render_view_host()); EXPECT_EQ(orig_rvh, contents->original_rvh()); EXPECT_TRUE(contents->interstitial_rvh() == NULL); // Navigate to a new page. const GURL url2("http://www.yahoo.com"); contents->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); TestRenderViewHost* new_rvh = contents->pending_rvh(); ASSERT_TRUE(new_rvh != NULL); // Make sure the RVH is not suspended (bug #1236441). EXPECT_FALSE(new_rvh->IsNavigationSuspended()); EXPECT_TRUE(contents->state_is_leaving_interstitial()); EXPECT_EQ(interstitial_rvh, contents->render_view_host()); // DidNavigate from the new page ViewHostMsg_FrameNavigate_Params params3; InitNavigateParams(¶ms3, 1, url2); contents->TestDidNavigate(new_rvh, params3); EXPECT_TRUE(contents->state_is_normal()); EXPECT_EQ(new_rvh, contents->render_view_host()); EXPECT_TRUE(contents->pending_rvh() == NULL); EXPECT_EQ(orig_rvh_delete_count, 1); } // Tests that we can transition away from an interstitial page even if the // interstitial renderer has crashed. TEST_F(WebContentsTest, CrossSiteInterstitialCrashThenNavigate) { contents->transition_cross_site = true; int orig_rvh_delete_count = 0; TestRenderViewHost* orig_rvh = contents->rvh(); orig_rvh->set_delete_counter(&orig_rvh_delete_count); // Navigate to URL. First URL should use first RenderViewHost. const GURL url("http://www.google.com"); contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); ViewHostMsg_FrameNavigate_Params params1; InitNavigateParams(¶ms1, 1, url); contents->TestDidNavigate(orig_rvh, params1); // Navigate to new site const GURL url2("https://www.google.com"); contents->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); TestRenderViewHost* pending_rvh = contents->pending_rvh(); int pending_rvh_delete_count = 0; pending_rvh->set_delete_counter(&pending_rvh_delete_count); // Show an interstitial const GURL interstitial_url("http://interstitial"); InterstitialPage* interstitial = new InterstitialPage(contents, true, interstitial_url); interstitial->Show(); TestRenderViewHost* interstitial_rvh = contents->interstitial_rvh(); // DidNavigate from the interstitial ViewHostMsg_FrameNavigate_Params params2; InitNavigateParams(¶ms2, 1, url2); contents->TestDidNavigate(interstitial_rvh, params2); EXPECT_TRUE(contents->state_is_interstitial()); EXPECT_EQ(interstitial_rvh, contents->render_view_host()); EXPECT_EQ(orig_rvh, contents->original_rvh()); EXPECT_EQ(pending_rvh, contents->pending_rvh()); EXPECT_TRUE(contents->interstitial_rvh() == NULL); // Crash the interstitial RVH // (by making IsRenderViewLive() == false) interstitial_rvh->is_created = false; // Navigate to a new page. Since interstitial RVH is dead, we should clean // it up and go to a new PENDING state, showing the orig_rvh. const GURL url3("http://www.yahoo.com"); contents->controller()->LoadURL(url3, GURL(), PageTransition::TYPED); TestRenderViewHost* new_rvh = contents->pending_rvh(); ASSERT_TRUE(new_rvh != NULL); EXPECT_TRUE(contents->state_is_pending()); EXPECT_EQ(orig_rvh, contents->render_view_host()); EXPECT_EQ(pending_rvh_delete_count, 1); EXPECT_NE(interstitial_rvh, new_rvh); EXPECT_TRUE(contents->original_rvh() == NULL); EXPECT_TRUE(contents->interstitial_rvh() == NULL); // DidNavigate from the new page ViewHostMsg_FrameNavigate_Params params3; InitNavigateParams(¶ms3, 1, url3); contents->TestDidNavigate(new_rvh, params3); EXPECT_TRUE(contents->state_is_normal()); EXPECT_EQ(new_rvh, contents->render_view_host()); EXPECT_TRUE(contents->pending_rvh() == NULL); EXPECT_EQ(orig_rvh_delete_count, 1); } // Tests that we can transition away from an interstitial page even if both the // original and interstitial renderers have crashed. TEST_F(WebContentsTest, CrossSiteInterstitialCrashesThenNavigate) { contents->transition_cross_site = true; int orig_rvh_delete_count = 0; TestRenderViewHost* orig_rvh = contents->rvh(); orig_rvh->set_delete_counter(&orig_rvh_delete_count); // Navigate to URL. First URL should use first RenderViewHost. const GURL url("http://www.google.com"); contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); ViewHostMsg_FrameNavigate_Params params1; InitNavigateParams(¶ms1, 1, url); contents->TestDidNavigate(orig_rvh, params1); // Navigate to new site const GURL url2("https://www.google.com"); contents->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); TestRenderViewHost* pending_rvh = contents->pending_rvh(); int pending_rvh_delete_count = 0; pending_rvh->set_delete_counter(&pending_rvh_delete_count); // Show an interstitial const GURL interstitial_url("http://interstitial"); InterstitialPage* interstitial = new InterstitialPage(contents, true, interstitial_url); interstitial->Show(); TestRenderViewHost* interstitial_rvh = contents->interstitial_rvh(); // DidNavigate from the interstitial ViewHostMsg_FrameNavigate_Params params2; InitNavigateParams(¶ms2, 1, url2); contents->TestDidNavigate(interstitial_rvh, params2); EXPECT_TRUE(contents->state_is_interstitial()); EXPECT_EQ(interstitial_rvh, contents->render_view_host()); EXPECT_EQ(orig_rvh, contents->original_rvh()); EXPECT_EQ(pending_rvh, contents->pending_rvh()); EXPECT_TRUE(contents->interstitial_rvh() == NULL); // Crash both the original and interstitial RVHs // (by making IsRenderViewLive() == false) orig_rvh->is_created = false; interstitial_rvh->is_created = false; // Navigate to a new page. Since both the interstitial and original RVHs are // dead, we should create a new RVH, jump back to NORMAL, and navigate. const GURL url3("http://www.yahoo.com"); contents->controller()->LoadURL(url3, GURL(), PageTransition::TYPED); TestRenderViewHost* new_rvh = contents->rvh(); ASSERT_TRUE(new_rvh != NULL); EXPECT_TRUE(contents->state_is_normal()); EXPECT_EQ(orig_rvh_delete_count, 1); EXPECT_EQ(pending_rvh_delete_count, 1); EXPECT_NE(interstitial_rvh, new_rvh); EXPECT_TRUE(contents->pending_rvh() == NULL); EXPECT_TRUE(contents->original_rvh() == NULL); EXPECT_TRUE(contents->interstitial_rvh() == NULL); // DidNavigate from the new page ViewHostMsg_FrameNavigate_Params params3; InitNavigateParams(¶ms3, 1, url3); contents->TestDidNavigate(new_rvh, params3); EXPECT_TRUE(contents->state_is_normal()); EXPECT_EQ(new_rvh, contents->render_view_host()); } // Test that opening a new tab in the same SiteInstance and then navigating // both tabs to a new site will place both tabs in a single SiteInstance. TEST_F(WebContentsTest, NavigateTwoTabsCrossSite) { contents->transition_cross_site = true; TestRenderViewHost* orig_rvh = contents->rvh(); SiteInstance* instance1 = contents->GetSiteInstance(); // Navigate to URL. First URL should use first RenderViewHost. const GURL url("http://www.google.com"); contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); ViewHostMsg_FrameNavigate_Params params1; InitNavigateParams(¶ms1, 1, url); contents->TestDidNavigate(orig_rvh, params1); // Open a new tab with the same SiteInstance, navigated to the same site. TestWebContents* contents2 = new TestWebContents(profile.get(), instance1); params1.page_id = 2; // Need this since the site instance is the same (which // is the scope of page IDs) and we want to consider // this a new page. contents2->transition_cross_site = true; contents2->SetupController(profile.get()); contents2->controller()->LoadURL(url, GURL(), PageTransition::TYPED); contents2->TestDidNavigate(contents2->rvh(), params1); // Navigate first tab to a new site const GURL url2a("http://www.yahoo.com"); contents->controller()->LoadURL(url2a, GURL(), PageTransition::TYPED); TestRenderViewHost* pending_rvh_a = contents->pending_rvh(); ViewHostMsg_FrameNavigate_Params params2a; InitNavigateParams(¶ms2a, 1, url2a); contents->TestDidNavigate(pending_rvh_a, params2a); SiteInstance* instance2a = contents->GetSiteInstance(); EXPECT_NE(instance1, instance2a); // Navigate second tab to the same site as the first tab const GURL url2b("http://mail.yahoo.com"); contents2->controller()->LoadURL(url2b, GURL(), PageTransition::TYPED); TestRenderViewHost* pending_rvh_b = contents2->pending_rvh(); EXPECT_TRUE(pending_rvh_b != NULL); EXPECT_TRUE(contents2->state_is_pending()); // NOTE(creis): We used to be in danger of showing a sad tab page here if the // second tab hadn't navigated somewhere first (bug 1145430). That case is // now covered by the CrossSiteBoundariesAfterCrash test. ViewHostMsg_FrameNavigate_Params params2b; InitNavigateParams(¶ms2b, 2, url2b); contents2->TestDidNavigate(pending_rvh_b, params2b); SiteInstance* instance2b = contents2->GetSiteInstance(); EXPECT_NE(instance1, instance2b); // Both tabs should now be in the same SiteInstance. EXPECT_EQ(instance2a, instance2b); contents2->CloseContents(); } // Tests that WebContents uses the current URL, not the SiteInstance's site, to // determine whether a navigation is cross-site. TEST_F(WebContentsTest, CrossSiteComparesAgainstCurrentPage) { contents->transition_cross_site = true; TestRenderViewHost* orig_rvh = contents->rvh(); SiteInstance* instance1 = contents->GetSiteInstance(); // Navigate to URL. const GURL url("http://www.google.com"); contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); ViewHostMsg_FrameNavigate_Params params1; InitNavigateParams(¶ms1, 1, url); contents->TestDidNavigate(orig_rvh, params1); // Open a related tab to a second site. TestWebContents* contents2 = new TestWebContents(profile.get(), instance1); contents2->transition_cross_site = true; contents2->SetupController(profile.get()); const GURL url2("http://www.yahoo.com"); contents2->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); // The first RVH in contents2 isn't live yet, so we shortcut the PENDING // state and go straight to NORMAL. TestRenderViewHost* rvh2 = contents2->rvh(); EXPECT_TRUE(contents2->state_is_normal()); ViewHostMsg_FrameNavigate_Params params2; InitNavigateParams(¶ms2, 2, url2); contents2->TestDidNavigate(rvh2, params2); SiteInstance* instance2 = contents2->GetSiteInstance(); EXPECT_NE(instance1, instance2); EXPECT_TRUE(contents2->state_is_normal()); // Simulate a link click in first tab to second site. Doesn't switch // SiteInstances, because we don't intercept WebKit navigations. ViewHostMsg_FrameNavigate_Params params3; InitNavigateParams(¶ms3, 2, url2); contents->TestDidNavigate(orig_rvh, params3); SiteInstance* instance3 = contents->GetSiteInstance(); EXPECT_EQ(instance1, instance3); EXPECT_TRUE(contents->state_is_normal()); // Navigate to the new site. Doesn't switch SiteInstancees, because we // compare against the current URL, not the SiteInstance's site. const GURL url3("http://mail.yahoo.com"); contents->controller()->LoadURL(url3, GURL(), PageTransition::TYPED); EXPECT_TRUE(contents->state_is_normal()); ViewHostMsg_FrameNavigate_Params params4; InitNavigateParams(¶ms4, 3, url3); contents->TestDidNavigate(orig_rvh, params4); SiteInstance* instance4 = contents->GetSiteInstance(); EXPECT_EQ(instance1, instance4); contents2->CloseContents(); } // Test that the onbeforeunload and onunload handlers run when navigating // across site boundaries. TEST_F(WebContentsTest, CrossSiteUnloadHandlers) { contents->transition_cross_site = true; TestRenderViewHost* orig_rvh = contents->rvh(); SiteInstance* instance1 = contents->GetSiteInstance(); // Navigate to URL. First URL should use first RenderViewHost. const GURL url("http://www.google.com"); contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); ViewHostMsg_FrameNavigate_Params params1; InitNavigateParams(¶ms1, 1, url); contents->TestDidNavigate(orig_rvh, params1); EXPECT_TRUE(contents->state_is_normal()); EXPECT_EQ(orig_rvh, contents->render_view_host()); // Navigate to new site, but simulate an onbeforeunload denial. const GURL url2("http://www.yahoo.com"); orig_rvh->immediate_before_unload = false; contents->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); orig_rvh->TestOnMsgShouldClose(false); EXPECT_TRUE(contents->state_is_normal()); EXPECT_EQ(orig_rvh, contents->render_view_host()); // Navigate again, but simulate an onbeforeunload approval. contents->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); orig_rvh->TestOnMsgShouldClose(true); EXPECT_TRUE(contents->state_is_pending()); TestRenderViewHost* pending_rvh = contents->pending_rvh(); // We won't hear DidNavigate until the onunload handler has finished running. // (No way to simulate that here, but it involves a call from RDH to // WebContents::OnCrossSiteResponse.) // DidNavigate from the pending page ViewHostMsg_FrameNavigate_Params params2; InitNavigateParams(¶ms2, 1, url2); contents->TestDidNavigate(pending_rvh, params2); SiteInstance* instance2 = contents->GetSiteInstance(); EXPECT_TRUE(contents->state_is_normal()); EXPECT_EQ(pending_rvh, contents->render_view_host()); EXPECT_NE(instance1, instance2); EXPECT_TRUE(contents->pending_rvh() == NULL); EXPECT_TRUE(contents->original_rvh() == NULL); EXPECT_TRUE(contents->interstitial_rvh() == NULL); } // Test that NavigationEntries have the correct content state after going // forward and back. Prevents regression for bug 1116137. TEST_F(WebContentsTest, NavigationEntryContentState) { TestRenderViewHost* orig_rvh = contents->rvh(); // Navigate to URL. There should be no committed entry yet. const GURL url("http://www.google.com"); contents->controller()->LoadURL(url, GURL(), PageTransition::TYPED); NavigationEntry* entry = contents->controller()->GetLastCommittedEntry(); EXPECT_TRUE(entry == NULL); // Committed entry should have content state after DidNavigate. ViewHostMsg_FrameNavigate_Params params1; InitNavigateParams(¶ms1, 1, url); contents->TestDidNavigate(orig_rvh, params1); entry = contents->controller()->GetLastCommittedEntry(); EXPECT_FALSE(entry->content_state().empty()); // Navigate to same site. const GURL url2("http://images.google.com"); contents->controller()->LoadURL(url2, GURL(), PageTransition::TYPED); entry = contents->controller()->GetLastCommittedEntry(); EXPECT_FALSE(entry->content_state().empty()); // Committed entry should have content state after DidNavigate. ViewHostMsg_FrameNavigate_Params params2; InitNavigateParams(¶ms2, 2, url2); contents->TestDidNavigate(orig_rvh, params2); entry = contents->controller()->GetLastCommittedEntry(); EXPECT_FALSE(entry->content_state().empty()); // Now go back. Committed entry should still have content state. contents->controller()->GoBack(); contents->TestDidNavigate(orig_rvh, params1); entry = contents->controller()->GetLastCommittedEntry(); EXPECT_FALSE(entry->content_state().empty()); } // Test that NavigationEntries have the correct content state after opening // a new window to about:blank. Prevents regression for bug 1116137. TEST_F(WebContentsTest, NavigationEntryContentStateNewWindow) { TestRenderViewHost* orig_rvh = contents->rvh(); // When opening a new window, it is navigated to about:blank internally. // Currently, this results in two DidNavigate events. const GURL url("about:blank"); ViewHostMsg_FrameNavigate_Params params1; InitNavigateParams(¶ms1, 1, url); contents->TestDidNavigate(orig_rvh, params1); contents->TestDidNavigate(orig_rvh, params1); // Should have a content state here. NavigationEntry* entry = contents->controller()->GetLastCommittedEntry(); EXPECT_FALSE(entry->content_state().empty()); } // Tests to see that webkit preferences are properly loaded and copied over // to a WebPreferences object. TEST_F(WebContentsTest, WebKitPrefs) { WebPreferences webkit_prefs = contents->TestGetWebkitPrefs(); // These values have been overridden by the profile preferences. EXPECT_EQ(L"UTF-8", webkit_prefs.default_encoding); EXPECT_EQ(20, webkit_prefs.default_font_size); EXPECT_EQ(false, webkit_prefs.text_areas_are_resizable); EXPECT_EQ(true, webkit_prefs.uses_universal_detector); // These should still be the default values. EXPECT_EQ(L"Times New Roman", webkit_prefs.standard_font_family); EXPECT_EQ(true, webkit_prefs.javascript_enabled); }