Fixing build: GetViewContainer changed name from under me. :)
[chromium-blink-merge.git] / chrome / browser / web_contents_unittest.cc
blob932af429c3deac3a30c0e363c9673eec5ff38c69
1 // Copyright (c) 2006-2008 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.
5 #include "base/logging.h"
6 #include "chrome/browser/interstitial_page.h"
7 #include "chrome/browser/navigation_controller.h"
8 #include "chrome/browser/navigation_entry.h"
9 #include "chrome/browser/render_view_host.h"
10 #include "chrome/browser/render_widget_host_view.h"
11 #include "chrome/browser/web_contents.h"
12 #include "chrome/common/chrome_paths.h"
13 #include "chrome/common/ipc_channel.h"
14 #include "chrome/common/pref_service.h"
15 #include "chrome/common/render_messages.h"
16 #include "chrome/test/testing_profile.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 // Subclass the RenderViewHost's view so that we can call Show(), etc.,
20 // without having side-effects.
21 class TestRenderWidgetHostView : public RenderWidgetHostView {
22 public:
23 TestRenderWidgetHostView() {}
24 void DidBecomeSelected() {}
25 void WasHidden() {}
26 void SetSize(const gfx::Size& size) {}
27 HWND GetPluginHWND() { return NULL; }
28 HANDLE ModalDialogEvent() { return NULL; }
29 void ForwardMouseEventToRenderer(UINT message,
30 WPARAM wparam,
31 LPARAM lparam) {}
32 void Focus() {}
33 void Blur() {}
34 bool HasFocus() { return true; }
35 void AdvanceFocus(bool reverse) {}
36 void Show() {}
37 void Hide() {}
38 gfx::Rect GetViewBounds() const { return gfx::Rect(); }
39 void UpdateCursor(const WebCursor& cursor) {}
40 void UpdateCursorIfOverSelf() {}
41 // Indicates if the page has finished loading.
42 virtual void SetIsLoading(bool is_loading) {}
43 void IMEUpdateStatus(ViewHostMsg_ImeControl control, int x, int y) {}
44 void DidPaintRect(const gfx::Rect& rect) {}
45 void DidScrollRect(const gfx::Rect& rect, int dx, int dy) {}
46 void RendererGone() {}
47 void Destroy() {}
48 void PrepareToDestroy() {}
49 void SetTooltipText(const std::wstring& tooltip_text) {}
52 // Subclass RenderViewHost so that it does not create a process.
53 class TestRenderViewHost : public RenderViewHost {
54 public:
55 TestRenderViewHost(
56 SiteInstance* instance,
57 RenderViewHostDelegate* delegate,
58 int routing_id,
59 HANDLE modal_dialog_event)
60 : RenderViewHost(instance, delegate, routing_id, modal_dialog_event),
61 is_loading(false),
62 is_created(false),
63 immediate_before_unload(true),
64 delete_counter_(NULL) {
65 set_view(new TestRenderWidgetHostView());
67 ~TestRenderViewHost() {
68 // Track the delete if we've been asked to.
69 if (delete_counter_)
70 ++*delete_counter_;
72 // Since this isn't a traditional view, we have to delete it.
73 delete view_;
76 // If set, *delete_counter is incremented when this object destructs.
77 void set_delete_counter(int* delete_counter) {
78 delete_counter_ = delete_counter;
81 bool CreateRenderView() {
82 is_created = true;
83 return true;
86 bool IsRenderViewLive() const { return is_created; }
88 bool IsNavigationSuspended() { return navigations_suspended_; }
90 void NavigateToEntry(const NavigationEntry& entry, bool is_reload) {
91 is_loading = true;
94 void LoadAlternateHTMLString(const std::string& html_text,
95 bool new_navigation,
96 const GURL& display_url,
97 const std::string& security_info) {
98 is_loading = true;
101 // Support for onbeforeunload, onunload
102 void FirePageBeforeUnload() {
103 is_waiting_for_unload_ack_ = true;
104 if (immediate_before_unload)
105 delegate()->ShouldClosePage(true);
107 void ClosePage(int new_render_process_host_id, int new_request_id) {
108 // Nothing to do here... This would cause a ClosePage_ACK to be sent to
109 // ResourceDispatcherHost, so we can simulate that manually.
111 void TestOnMsgShouldClose(bool proceed) {
112 OnMsgShouldCloseACK(proceed);
115 bool is_loading;
116 bool is_created;
117 bool immediate_before_unload;
118 int* delete_counter_;
121 // Factory to create TestRenderViewHosts.
122 class TestRenderViewHostFactory : public RenderViewHostFactory {
123 public:
124 static TestRenderViewHostFactory* GetInstance() {
125 static TestRenderViewHostFactory instance;
126 return &instance;
129 virtual RenderViewHost* CreateRenderViewHost(
130 SiteInstance* instance,
131 RenderViewHostDelegate* delegate,
132 int routing_id,
133 HANDLE modal_dialog_event) {
134 return new TestRenderViewHost(
135 instance, delegate, routing_id, modal_dialog_event);
138 private:
139 TestRenderViewHostFactory() {}
142 // Subclass the TestingProfile so that it can return certain services we need.
143 class WebContentsTestingProfile : public TestingProfile {
144 public:
145 WebContentsTestingProfile() : TestingProfile() { }
147 virtual PrefService* GetPrefs() {
148 if (!prefs_.get()) {
149 std::wstring source_path;
150 PathService::Get(chrome::DIR_TEST_DATA, &source_path);
151 file_util::AppendToPath(&source_path, L"profiles");
152 file_util::AppendToPath(&source_path, L"chrome_prefs");
153 file_util::AppendToPath(&source_path, L"Preferences");
155 prefs_.reset(new PrefService(source_path));
156 Profile::RegisterUserPrefs(prefs_.get());
157 browser::RegisterAllPrefs(prefs_.get(), prefs_.get());
159 return prefs_.get();
163 // Subclass WebContents to ensure it creates TestRenderViewHosts and does
164 // not do anything involving views.
165 class TestWebContents : public WebContents {
166 public:
167 TestWebContents(Profile* profile, SiteInstance* instance)
168 : WebContents(profile,
169 instance,
170 TestRenderViewHostFactory::GetInstance(),
171 MSG_ROUTING_NONE,
172 NULL),
173 transition_cross_site(false) {}
175 // Accessors for interesting fields
176 TestRenderViewHost* rvh() {
177 return static_cast<TestRenderViewHost*>(
178 render_manager_.render_view_host_);
180 TestRenderViewHost* pending_rvh() {
181 return static_cast<TestRenderViewHost*>(
182 render_manager_.pending_render_view_host_);
184 TestRenderViewHost* interstitial_rvh() {
185 return static_cast<TestRenderViewHost*>(
186 render_manager_.interstitial_render_view_host_);
188 TestRenderViewHost* original_rvh() {
189 return static_cast<TestRenderViewHost*>(
190 render_manager_.original_render_view_host_);
193 // State accessors.
194 bool state_is_normal() const {
195 return render_manager_.renderer_state_ == RenderViewHostManager::NORMAL;
197 bool state_is_pending() const {
198 return render_manager_.renderer_state_ == RenderViewHostManager::PENDING;
200 bool state_is_entering_interstitial() const {
201 return render_manager_.renderer_state_ ==
202 RenderViewHostManager::ENTERING_INTERSTITIAL;
204 bool state_is_interstitial() const {
205 return render_manager_.renderer_state_ ==
206 RenderViewHostManager::INTERSTITIAL;
208 bool state_is_leaving_interstitial() const {
209 return render_manager_.renderer_state_ ==
210 RenderViewHostManager::LEAVING_INTERSTITIAL;
213 // Ensure we create TestRenderViewHosts that don't spawn processes.
214 RenderViewHost* CreateRenderViewHost(SiteInstance* instance,
215 RenderViewHostDelegate* delegate,
216 int routing_id,
217 HANDLE modal_dialog_event) {
218 return new TestRenderViewHost(
219 instance, delegate, routing_id, modal_dialog_event);
222 // Overrides WebContents::ShouldTransitionCrossSite so that we can test both
223 // alternatives without using command-line switches.
224 bool ShouldTransitionCrossSite() { return transition_cross_site; }
226 // Promote DidNavigate to public.
227 void TestDidNavigate(TestRenderViewHost* render_view_host,
228 const ViewHostMsg_FrameNavigate_Params& params) {
229 DidNavigate(render_view_host, params);
230 render_view_host->is_loading = false;
233 // Promote GetWebkitPrefs to public.
234 WebPreferences TestGetWebkitPrefs() {
235 return GetWebkitPrefs();
238 // Prevent interaction with views.
239 bool CreateRenderViewForRenderManager(RenderViewHost* render_view_host) {
240 // This will go to a TestRenderViewHost.
241 render_view_host->CreateRenderView();
242 return true;
244 void UpdateRenderViewSizeForRenderManager() {}
246 // Set by individual tests.
247 bool transition_cross_site;
250 class WebContentsTest : public testing::Test {
251 public:
252 WebContentsTest() : contents(NULL) {}
254 void InitNavigateParams(ViewHostMsg_FrameNavigate_Params* params,
255 int pageID,
256 const GURL& url) {
257 params->page_id = pageID;
258 params->url = url;
259 params->referrer = GURL::EmptyGURL();
260 params->transition = PageTransition::TYPED;
261 params->redirects = std::vector<GURL>();
262 params->should_update_history = false;
263 params->searchable_form_url = GURL::EmptyGURL();
264 params->searchable_form_element_name = std::wstring();
265 params->searchable_form_encoding = std::string();
266 params->password_form = PasswordForm();
267 params->security_info = std::string();
268 params->gesture = NavigationGestureUser;
269 params->is_post = false;
272 // testing::Test methods:
274 virtual void SetUp() {
275 profile.reset(new WebContentsTestingProfile());
277 // This will be deleted when the WebContents goes away
278 SiteInstance* instance = SiteInstance::CreateSiteInstance(profile.get());
280 contents = new TestWebContents(profile.get(), instance);
281 contents->SetupController(profile.get());
284 virtual void TearDown() {
285 // This will delete the contents.
286 contents->CloseContents();
288 // Make sure that we flush any messages related to WebContents destruction
289 // before we destroy the profile.
290 MessageLoop::current()->RunAllPending();
293 scoped_ptr<WebContentsTestingProfile> profile;
294 TestWebContents* contents;
296 private:
297 MessageLoopForUI message_loop_;
300 // Test to make sure that title updates get stripped of whitespace.
301 TEST_F(WebContentsTest, UpdateTitle) {
302 ViewHostMsg_FrameNavigate_Params params;
303 InitNavigateParams(&params, 0, GURL("about:blank"));
305 NavigationController::LoadCommittedDetails details;
306 contents->controller()->RendererDidNavigate(params, false, &details);
308 contents->UpdateTitle(NULL, 0, L" Lots O' Whitespace\n");
309 EXPECT_EQ(std::wstring(L"Lots O' Whitespace"), contents->GetTitle());
312 // Test simple same-SiteInstance navigation.
313 TEST_F(WebContentsTest, SimpleNavigation) {
314 TestRenderViewHost* orig_rvh = contents->rvh();
315 SiteInstance* instance1 = contents->GetSiteInstance();
316 EXPECT_TRUE(contents->pending_rvh() == NULL);
317 EXPECT_TRUE(contents->original_rvh() == NULL);
318 EXPECT_TRUE(contents->interstitial_rvh() == NULL);
319 EXPECT_FALSE(orig_rvh->is_loading);
321 // Navigate to URL
322 const GURL url("http://www.google.com");
323 contents->controller()->LoadURL(url, PageTransition::TYPED);
324 EXPECT_TRUE(contents->state_is_normal());
325 EXPECT_TRUE(orig_rvh->is_loading);
326 EXPECT_EQ(instance1, orig_rvh->site_instance());
327 // Controller's pending entry will have a NULL site instance until we assign
328 // it in DidNavigate.
329 EXPECT_TRUE(
330 contents->controller()->GetActiveEntry()->site_instance() == NULL);
332 // DidNavigate from the page
333 ViewHostMsg_FrameNavigate_Params params;
334 InitNavigateParams(&params, 1, url);
335 contents->TestDidNavigate(orig_rvh, params);
336 EXPECT_TRUE(contents->state_is_normal());
337 EXPECT_EQ(orig_rvh, contents->render_view_host());
338 EXPECT_EQ(instance1, orig_rvh->site_instance());
339 // Controller's entry should now have the SiteInstance, or else we won't be
340 // able to find it later.
341 EXPECT_EQ(instance1,
342 contents->controller()->GetActiveEntry()->site_instance());
345 // Test navigating to a page that shows an interstitial, then hiding it
346 // without proceeding.
347 TEST_F(WebContentsTest, ShowInterstitialDontProceed) {
348 TestRenderViewHost* orig_rvh = contents->rvh();
349 EXPECT_TRUE(contents->pending_rvh() == NULL);
350 EXPECT_TRUE(contents->original_rvh() == NULL);
351 EXPECT_TRUE(contents->interstitial_rvh() == NULL);
352 EXPECT_FALSE(orig_rvh->is_loading);
354 // Navigate to URL
355 const GURL url("http://www.google.com");
356 contents->controller()->LoadURL(url, PageTransition::TYPED);
357 EXPECT_TRUE(contents->state_is_normal());
358 EXPECT_TRUE(orig_rvh->is_loading);
360 // Show interstitial
361 const GURL interstitial_url("http://interstitial");
362 InterstitialPage* interstitial = new InterstitialPage(contents,
363 true,
364 interstitial_url);
365 interstitial->Show();
366 EXPECT_TRUE(contents->state_is_entering_interstitial());
367 TestRenderViewHost* interstitial_rvh = contents->interstitial_rvh();
368 EXPECT_TRUE(orig_rvh->is_loading); // Still loading in the background
369 EXPECT_TRUE(interstitial_rvh->is_loading);
371 // DidNavigate from the interstitial
372 ViewHostMsg_FrameNavigate_Params params;
373 InitNavigateParams(&params, 1, url);
374 contents->TestDidNavigate(interstitial_rvh, params);
375 EXPECT_TRUE(contents->state_is_interstitial());
376 EXPECT_EQ(interstitial_rvh, contents->render_view_host());
377 EXPECT_EQ(orig_rvh, contents->original_rvh());
378 EXPECT_FALSE(interstitial_rvh->is_loading);
380 // Hide interstitial (don't proceed)
381 contents->HideInterstitialPage(false, false);
382 EXPECT_TRUE(contents->state_is_normal());
383 EXPECT_EQ(orig_rvh, contents->render_view_host());
384 EXPECT_TRUE(contents->original_rvh() == NULL);
385 EXPECT_TRUE(contents->interstitial_rvh() == NULL);
388 // Test navigating to a page that shows an interstitial, then proceeding.
389 TEST_F(WebContentsTest, ShowInterstitialProceed) {
390 TestRenderViewHost* orig_rvh = contents->rvh();
392 // The RenderViewHost's SiteInstance should not yet have a site.
393 EXPECT_EQ(GURL(), contents->rvh()->site_instance()->site());
395 // Navigate to URL
396 const GURL url("http://www.google.com");
397 contents->controller()->LoadURL(url, PageTransition::TYPED);
399 // Show interstitial
400 const GURL interstitial_url("http://interstitial");
401 InterstitialPage* interstitial = new InterstitialPage(contents,
402 true,
403 interstitial_url);
404 interstitial->Show();
405 TestRenderViewHost* interstitial_rvh = contents->interstitial_rvh();
407 // DidNavigate from the interstitial
408 ViewHostMsg_FrameNavigate_Params params;
409 InitNavigateParams(&params, 1, url);
410 contents->TestDidNavigate(interstitial_rvh, params);
412 // Ensure this DidNavigate hasn't changed the SiteInstance's site.
413 // Prevents regression for bug 1163298.
414 EXPECT_EQ(GURL(), contents->rvh()->site_instance()->site());
416 // Hide interstitial (proceed and wait)
417 contents->HideInterstitialPage(true, true);
418 EXPECT_TRUE(contents->state_is_leaving_interstitial());
419 EXPECT_EQ(interstitial_rvh, contents->render_view_host());
420 EXPECT_EQ(orig_rvh, contents->original_rvh());
422 // DidNavigate from the destination page
423 contents->TestDidNavigate(orig_rvh, params);
424 EXPECT_TRUE(contents->state_is_normal());
425 EXPECT_EQ(orig_rvh, contents->render_view_host());
426 EXPECT_TRUE(contents->original_rvh() == NULL);
427 EXPECT_TRUE(contents->interstitial_rvh() == NULL);
429 // The SiteInstance's site should now be updated.
430 EXPECT_EQ(GURL("http://google.com"),
431 contents->rvh()->site_instance()->site());
433 // Since we weren't viewing a page before, we shouldn't be able to go back.
434 EXPECT_FALSE(contents->controller()->CanGoBack());
437 // Test navigating to a page that shows an interstitial, then navigating away.
438 TEST_F(WebContentsTest, ShowInterstitialThenNavigate) {
439 TestRenderViewHost* orig_rvh = contents->rvh();
441 // Navigate to URL
442 const GURL url("http://www.google.com");
443 contents->controller()->LoadURL(url, PageTransition::TYPED);
445 // Show interstitial
446 const GURL interstitial_url("http://interstitial");
447 InterstitialPage* interstitial = new InterstitialPage(contents,
448 true,
449 interstitial_url);
450 interstitial->Show();
451 TestRenderViewHost* interstitial_rvh = contents->interstitial_rvh();
453 // DidNavigate from the interstitial
454 ViewHostMsg_FrameNavigate_Params params;
455 InitNavigateParams(&params, 1, url);
456 contents->TestDidNavigate(interstitial_rvh, params);
458 // While interstitial showing, navigate to a new URL.
459 const GURL url2("http://www.yahoo.com");
460 contents->controller()->LoadURL(url2, PageTransition::TYPED);
461 EXPECT_TRUE(contents->state_is_leaving_interstitial());
462 EXPECT_EQ(interstitial_rvh, contents->render_view_host());
463 EXPECT_TRUE(orig_rvh->is_loading);
464 EXPECT_FALSE(interstitial_rvh->is_loading);
466 // DidNavigate from the new URL. In the old process model, we'll still have
467 // the same RenderViewHost.
468 ViewHostMsg_FrameNavigate_Params params2;
469 InitNavigateParams(&params2, 2, url2);
470 contents->TestDidNavigate(orig_rvh, params2);
471 EXPECT_TRUE(contents->state_is_normal());
472 EXPECT_EQ(orig_rvh, contents->render_view_host());
473 EXPECT_FALSE(orig_rvh->is_loading);
476 // Ensures that an interstitial cannot be cancelled if a notification for a
477 // navigation from an IFrame from the previous page is received while the
478 // interstitial is being shown (bug #1182394).
479 TEST_F(WebContentsTest, ShowInterstitialIFrameNavigate) {
480 TestRenderViewHost* orig_rvh = contents->rvh();
481 EXPECT_TRUE(contents->pending_rvh() == NULL);
482 EXPECT_TRUE(contents->original_rvh() == NULL);
483 EXPECT_TRUE(contents->interstitial_rvh() == NULL);
484 EXPECT_FALSE(orig_rvh->is_loading);
486 // Navigate to URL.
487 const GURL url("http://www.google.com");
488 contents->controller()->LoadURL(url, PageTransition::TYPED);
489 EXPECT_TRUE(contents->state_is_normal());
490 EXPECT_TRUE(orig_rvh->is_loading);
491 ViewHostMsg_FrameNavigate_Params params1;
492 InitNavigateParams(&params1, 1, url);
493 contents->TestDidNavigate(orig_rvh, params1);
495 // Show interstitial (in real world would probably be triggered by a resource
496 // in the page).
497 const GURL interstitial_url("http://interstitial");
498 InterstitialPage* interstitial = new InterstitialPage(contents,
499 true,
500 interstitial_url);
501 interstitial->Show();
502 EXPECT_TRUE(contents->state_is_entering_interstitial());
503 TestRenderViewHost* interstitial_rvh = contents->interstitial_rvh();
504 EXPECT_TRUE(interstitial_rvh->is_loading);
506 // DidNavigate from an IFrame in the initial page.
507 ViewHostMsg_FrameNavigate_Params params2;
508 InitNavigateParams(&params2, 1, GURL("http://www.iframe.com"));
509 params2.transition = PageTransition::AUTO_SUBFRAME;
510 contents->TestDidNavigate(orig_rvh, params2);
512 // Now we get the DidNavigate from the interstitial.
513 ViewHostMsg_FrameNavigate_Params params3;
514 InitNavigateParams(&params3, 1, url);
515 contents->TestDidNavigate(interstitial_rvh, params3);
516 EXPECT_TRUE(contents->state_is_interstitial());
517 EXPECT_EQ(interstitial_rvh, contents->render_view_host());
518 EXPECT_EQ(orig_rvh, contents->original_rvh());
519 EXPECT_FALSE(interstitial_rvh->is_loading);
522 // Test navigating to an interstitial page from a normal page. Also test
523 // visiting the interstitial-inducing URL twice (bug 1079784), and test
524 // that going back shows the first page and not the interstitial.
525 TEST_F(WebContentsTest, VisitInterstitialURLTwice) {
526 TestRenderViewHost* orig_rvh = contents->rvh();
528 // Navigate to URL
529 const GURL url("http://www.google.com");
530 contents->controller()->LoadURL(url, PageTransition::TYPED);
531 ViewHostMsg_FrameNavigate_Params params1;
532 InitNavigateParams(&params1, 1, url);
533 contents->TestDidNavigate(orig_rvh, params1);
535 // Now navigate to an interstitial-inducing URL
536 const GURL url2("https://www.google.com");
537 contents->controller()->LoadURL(url2, PageTransition::TYPED);
538 const GURL interstitial_url("http://interstitial");
539 InterstitialPage* interstitial = new InterstitialPage(contents,
540 true,
541 interstitial_url);
542 interstitial->Show();
543 EXPECT_TRUE(contents->state_is_entering_interstitial());
544 int interstitial_delete_counter = 0;
545 TestRenderViewHost* interstitial_rvh = contents->interstitial_rvh();
546 interstitial_rvh->set_delete_counter(&interstitial_delete_counter);
548 // DidNavigate from the interstitial
549 ViewHostMsg_FrameNavigate_Params params2;
550 InitNavigateParams(&params2, 2, url2);
551 contents->TestDidNavigate(interstitial_rvh, params2);
552 EXPECT_TRUE(contents->state_is_interstitial());
553 EXPECT_EQ(interstitial_rvh, contents->render_view_host());
555 // While interstitial showing, navigate to the same URL.
556 contents->controller()->LoadURL(url2, PageTransition::TYPED);
557 EXPECT_TRUE(contents->state_is_leaving_interstitial());
558 EXPECT_EQ(interstitial_rvh, contents->render_view_host());
560 // Interstitial shown a second time in a different RenderViewHost.
561 interstitial = new InterstitialPage(contents, true, interstitial_url);
562 interstitial->Show();
563 EXPECT_TRUE(contents->state_is_entering_interstitial());
564 // We expect the original interstitial has been deleted.
565 EXPECT_EQ(interstitial_delete_counter, 1);
566 TestRenderViewHost* interstitial_rvh2 = contents->interstitial_rvh();
567 interstitial_rvh2->set_delete_counter(&interstitial_delete_counter);
569 // DidNavigate from the interstitial.
570 ViewHostMsg_FrameNavigate_Params params3;
571 InitNavigateParams(&params3, 3, url2);
572 contents->TestDidNavigate(interstitial_rvh2, params3);
573 EXPECT_TRUE(contents->state_is_interstitial());
574 EXPECT_EQ(interstitial_rvh2, contents->render_view_host());
576 // Proceed. In the old process model, we'll still have the same
577 // RenderViewHost.
578 contents->HideInterstitialPage(true, true);
579 EXPECT_TRUE(contents->state_is_leaving_interstitial());
580 ViewHostMsg_FrameNavigate_Params params4;
581 InitNavigateParams(&params4, 3, url2);
582 contents->TestDidNavigate(orig_rvh, params4);
583 EXPECT_TRUE(contents->state_is_normal());
584 // We expect the second interstitial has been deleted.
585 EXPECT_EQ(interstitial_delete_counter, 2);
587 // Now go back. Should take us back to the original page.
588 contents->controller()->GoBack();
589 EXPECT_TRUE(contents->state_is_normal());
591 // DidNavigate from going back.
592 contents->TestDidNavigate(orig_rvh, params1);
593 EXPECT_TRUE(contents->state_is_normal());
594 EXPECT_EQ(orig_rvh, contents->render_view_host());
595 EXPECT_TRUE(contents->original_rvh() == NULL);
596 EXPECT_TRUE(contents->interstitial_rvh() == NULL);
599 // Test that navigating across a site boundary creates a new RenderViewHost
600 // with a new SiteInstance. Going back should do the same.
601 TEST_F(WebContentsTest, CrossSiteBoundaries) {
602 contents->transition_cross_site = true;
603 TestRenderViewHost* orig_rvh = contents->rvh();
604 int orig_rvh_delete_count = 0;
605 orig_rvh->set_delete_counter(&orig_rvh_delete_count);
606 SiteInstance* instance1 = contents->GetSiteInstance();
608 // Navigate to URL. First URL should use first RenderViewHost.
609 const GURL url("http://www.google.com");
610 contents->controller()->LoadURL(url, PageTransition::TYPED);
611 ViewHostMsg_FrameNavigate_Params params1;
612 InitNavigateParams(&params1, 1, url);
613 contents->TestDidNavigate(orig_rvh, params1);
615 EXPECT_TRUE(contents->state_is_normal());
616 EXPECT_EQ(orig_rvh, contents->render_view_host());
617 EXPECT_TRUE(contents->original_rvh() == NULL);
618 EXPECT_TRUE(contents->interstitial_rvh() == NULL);
620 // Navigate to new site
621 const GURL url2("http://www.yahoo.com");
622 contents->controller()->LoadURL(url2, PageTransition::TYPED);
623 EXPECT_TRUE(contents->state_is_pending());
624 TestRenderViewHost* pending_rvh = contents->pending_rvh();
625 int pending_rvh_delete_count = 0;
626 pending_rvh->set_delete_counter(&pending_rvh_delete_count);
628 // DidNavigate from the pending page
629 ViewHostMsg_FrameNavigate_Params params2;
630 InitNavigateParams(&params2, 1, url2);
631 contents->TestDidNavigate(pending_rvh, params2);
632 SiteInstance* instance2 = contents->GetSiteInstance();
634 EXPECT_TRUE(contents->state_is_normal());
635 EXPECT_EQ(pending_rvh, contents->render_view_host());
636 EXPECT_NE(instance1, instance2);
637 EXPECT_TRUE(contents->pending_rvh() == NULL);
638 EXPECT_TRUE(contents->original_rvh() == NULL);
639 EXPECT_TRUE(contents->interstitial_rvh() == NULL);
640 EXPECT_EQ(orig_rvh_delete_count, 1);
642 // Going back should switch SiteInstances again. The first SiteInstance is
643 // stored in the NavigationEntry, so it should be the same as at the start.
644 contents->controller()->GoBack();
645 TestRenderViewHost* goback_rvh = contents->pending_rvh();
646 EXPECT_TRUE(contents->state_is_pending());
648 // DidNavigate from the back action
649 contents->TestDidNavigate(goback_rvh, params1);
650 EXPECT_TRUE(contents->state_is_normal());
651 EXPECT_EQ(goback_rvh, contents->render_view_host());
652 EXPECT_EQ(pending_rvh_delete_count, 1);
653 EXPECT_EQ(instance1, contents->GetSiteInstance());
656 // Test that navigating across a site boundary after a crash creates a new
657 // RVH without requiring a cross-site transition (i.e., PENDING state).
658 TEST_F(WebContentsTest, CrossSiteBoundariesAfterCrash) {
659 contents->transition_cross_site = true;
660 TestRenderViewHost* orig_rvh = contents->rvh();
661 int orig_rvh_delete_count = 0;
662 orig_rvh->set_delete_counter(&orig_rvh_delete_count);
663 SiteInstance* instance1 = contents->GetSiteInstance();
665 // Navigate to URL. First URL should use first RenderViewHost.
666 const GURL url("http://www.google.com");
667 contents->controller()->LoadURL(url, PageTransition::TYPED);
668 ViewHostMsg_FrameNavigate_Params params1;
669 InitNavigateParams(&params1, 1, url);
670 contents->TestDidNavigate(orig_rvh, params1);
672 EXPECT_TRUE(contents->state_is_normal());
673 EXPECT_EQ(orig_rvh, contents->render_view_host());
674 EXPECT_TRUE(contents->original_rvh() == NULL);
675 EXPECT_TRUE(contents->interstitial_rvh() == NULL);
677 // Crash the renderer.
678 orig_rvh->is_created = false;
680 // Navigate to new site. We should not go into PENDING.
681 const GURL url2("http://www.yahoo.com");
682 contents->controller()->LoadURL(url2, PageTransition::TYPED);
683 TestRenderViewHost* new_rvh = contents->rvh();
684 EXPECT_TRUE(contents->state_is_normal());
685 EXPECT_TRUE(contents->pending_rvh() == NULL);
686 EXPECT_TRUE(contents->original_rvh() == NULL);
687 EXPECT_TRUE(contents->interstitial_rvh() == NULL);
688 EXPECT_NE(orig_rvh, new_rvh);
689 EXPECT_EQ(orig_rvh_delete_count, 1);
691 // DidNavigate from the new page
692 ViewHostMsg_FrameNavigate_Params params2;
693 InitNavigateParams(&params2, 1, url2);
694 contents->TestDidNavigate(new_rvh, params2);
695 SiteInstance* instance2 = contents->GetSiteInstance();
697 EXPECT_TRUE(contents->state_is_normal());
698 EXPECT_EQ(new_rvh, contents->render_view_host());
699 EXPECT_NE(instance1, instance2);
700 EXPECT_TRUE(contents->pending_rvh() == NULL);
701 EXPECT_TRUE(contents->original_rvh() == NULL);
702 EXPECT_TRUE(contents->interstitial_rvh() == NULL);
705 // Test state transitions when showing an interstitial in the new process
706 // model, and then choosing DontProceed.
707 TEST_F(WebContentsTest, CrossSiteInterstitialDontProceed) {
708 contents->transition_cross_site = true;
709 TestRenderViewHost* orig_rvh = contents->rvh();
710 SiteInstance* instance1 = contents->GetSiteInstance();
712 // Navigate to URL. First URL should use first RenderViewHost.
713 const GURL url("http://www.google.com");
714 contents->controller()->LoadURL(url, PageTransition::TYPED);
715 ViewHostMsg_FrameNavigate_Params params1;
716 InitNavigateParams(&params1, 1, url);
717 contents->TestDidNavigate(orig_rvh, params1);
719 EXPECT_TRUE(contents->state_is_normal());
720 EXPECT_EQ(orig_rvh, contents->render_view_host());
722 // Navigate to new site
723 const GURL url2("https://www.google.com");
724 contents->controller()->LoadURL(url2, PageTransition::TYPED);
725 EXPECT_TRUE(contents->state_is_pending());
726 TestRenderViewHost* pending_rvh = contents->pending_rvh();
728 // Show an interstitial
729 const GURL interstitial_url("http://interstitial");
730 InterstitialPage* interstitial = new InterstitialPage(contents,
731 true,
732 interstitial_url);
733 interstitial->Show();
734 EXPECT_TRUE(contents->state_is_entering_interstitial());
735 EXPECT_EQ(orig_rvh, contents->render_view_host());
736 EXPECT_EQ(pending_rvh, contents->pending_rvh());
737 TestRenderViewHost* interstitial_rvh = contents->interstitial_rvh();
739 // DidNavigate from the interstitial
740 ViewHostMsg_FrameNavigate_Params params2;
741 InitNavigateParams(&params2, 2, url2);
742 contents->TestDidNavigate(interstitial_rvh, params2);
743 EXPECT_TRUE(contents->state_is_interstitial());
744 EXPECT_EQ(interstitial_rvh, contents->render_view_host());
745 EXPECT_EQ(orig_rvh, contents->original_rvh());
746 EXPECT_EQ(pending_rvh, contents->pending_rvh());
747 EXPECT_TRUE(contents->interstitial_rvh() == NULL);
749 // Hide interstitial (don't proceed)
750 contents->HideInterstitialPage(false, false);
751 EXPECT_TRUE(contents->state_is_normal());
752 EXPECT_EQ(orig_rvh, contents->render_view_host());
753 EXPECT_TRUE(contents->original_rvh() == NULL);
754 EXPECT_TRUE(contents->pending_rvh() == NULL);
755 EXPECT_TRUE(contents->interstitial_rvh() == NULL);
758 // Test state transitions when showing an interstitial in the new process
759 // model, and then choosing Proceed.
760 TEST_F(WebContentsTest, CrossSiteInterstitialProceed) {
761 contents->transition_cross_site = true;
762 int orig_rvh_delete_count = 0;
763 TestRenderViewHost* orig_rvh = contents->rvh();
764 orig_rvh->set_delete_counter(&orig_rvh_delete_count);
765 SiteInstance* instance1 = contents->GetSiteInstance();
767 // Navigate to URL. First URL should use first RenderViewHost.
768 const GURL url("http://www.google.com");
769 contents->controller()->LoadURL(url, PageTransition::TYPED);
770 ViewHostMsg_FrameNavigate_Params params1;
771 InitNavigateParams(&params1, 1, url);
772 contents->TestDidNavigate(orig_rvh, params1);
774 // Navigate to new site
775 const GURL url2("https://www.google.com");
776 contents->controller()->LoadURL(url2, PageTransition::TYPED);
777 TestRenderViewHost* pending_rvh = contents->pending_rvh();
778 int pending_rvh_delete_count = 0;
779 pending_rvh->set_delete_counter(&pending_rvh_delete_count);
781 // Show an interstitial
782 const GURL interstitial_url("http://interstitial");
783 InterstitialPage* interstitial = new InterstitialPage(contents,
784 true,
785 interstitial_url);
786 interstitial->Show();
787 TestRenderViewHost* interstitial_rvh = contents->interstitial_rvh();
789 // DidNavigate from the interstitial
790 ViewHostMsg_FrameNavigate_Params params2;
791 InitNavigateParams(&params2, 1, url2);
792 contents->TestDidNavigate(interstitial_rvh, params2);
793 EXPECT_TRUE(contents->state_is_interstitial());
794 EXPECT_EQ(interstitial_rvh, contents->render_view_host());
795 EXPECT_EQ(orig_rvh, contents->original_rvh());
796 EXPECT_EQ(pending_rvh, contents->pending_rvh());
797 EXPECT_TRUE(contents->interstitial_rvh() == NULL);
799 // Hide interstitial (proceed and wait)
800 contents->HideInterstitialPage(true, true);
801 EXPECT_TRUE(contents->state_is_leaving_interstitial());
802 EXPECT_EQ(interstitial_rvh, contents->render_view_host());
803 EXPECT_EQ(orig_rvh, contents->original_rvh());
804 EXPECT_EQ(pending_rvh, contents->pending_rvh());
805 EXPECT_TRUE(contents->interstitial_rvh() == NULL);
807 // DidNavigate from the destination page should transition to new renderer
808 ViewHostMsg_FrameNavigate_Params params3;
809 InitNavigateParams(&params3, 2, url2);
810 contents->TestDidNavigate(pending_rvh, params3);
811 SiteInstance* instance2 = contents->GetSiteInstance();
812 EXPECT_TRUE(contents->state_is_normal());
813 EXPECT_EQ(pending_rvh, contents->render_view_host());
814 EXPECT_TRUE(contents->original_rvh() == NULL);
815 EXPECT_TRUE(contents->pending_rvh() == NULL);
816 EXPECT_TRUE(contents->interstitial_rvh() == NULL);
817 EXPECT_NE(instance1, instance2);
818 EXPECT_EQ(orig_rvh_delete_count, 1); // The original should be gone.
820 // Since we were viewing a page before, we should be able to go back.
821 EXPECT_TRUE(contents->controller()->CanGoBack());
823 // Going back should switch SiteInstances again. The first SiteInstance is
824 // stored in the NavigationEntry, so it should be the same as at the start.
825 contents->controller()->GoBack();
826 TestRenderViewHost* goback_rvh = contents->pending_rvh();
827 EXPECT_TRUE(contents->state_is_pending());
829 // DidNavigate from the back action
830 contents->TestDidNavigate(goback_rvh, params1);
831 EXPECT_TRUE(contents->state_is_normal());
832 EXPECT_EQ(goback_rvh, contents->render_view_host());
833 EXPECT_EQ(instance1, contents->GetSiteInstance());
834 EXPECT_EQ(pending_rvh_delete_count, 1); // The second page's rvh should die.
837 // Tests that we can transition away from an interstitial page.
838 TEST_F(WebContentsTest, CrossSiteInterstitialThenNavigate) {
839 contents->transition_cross_site = true;
840 int orig_rvh_delete_count = 0;
841 TestRenderViewHost* orig_rvh = contents->rvh();
842 orig_rvh->set_delete_counter(&orig_rvh_delete_count);
844 // Navigate to URL. First URL should use first RenderViewHost.
845 const GURL url("http://www.google.com");
846 contents->controller()->LoadURL(url, PageTransition::TYPED);
847 ViewHostMsg_FrameNavigate_Params params1;
848 InitNavigateParams(&params1, 1, url);
849 contents->TestDidNavigate(orig_rvh, params1);
851 // Show an interstitial
852 const GURL interstitial_url("http://interstitial");
853 InterstitialPage* interstitial = new InterstitialPage(contents,
854 false,
855 interstitial_url);
856 interstitial->Show();
857 TestRenderViewHost* interstitial_rvh = contents->interstitial_rvh();
859 // DidNavigate from the interstitial
860 ViewHostMsg_FrameNavigate_Params params2;
861 InitNavigateParams(&params2, 1, url);
862 contents->TestDidNavigate(interstitial_rvh, params2);
863 EXPECT_TRUE(contents->state_is_interstitial());
864 EXPECT_EQ(interstitial_rvh, contents->render_view_host());
865 EXPECT_EQ(orig_rvh, contents->original_rvh());
866 EXPECT_TRUE(contents->interstitial_rvh() == NULL);
868 // Navigate to a new page.
869 const GURL url2("http://www.yahoo.com");
870 contents->controller()->LoadURL(url2, PageTransition::TYPED);
872 TestRenderViewHost* new_rvh = contents->pending_rvh();
873 ASSERT_TRUE(new_rvh != NULL);
874 // Make sure the RVH is not suspended (bug #1236441).
875 EXPECT_FALSE(new_rvh->IsNavigationSuspended());
876 EXPECT_TRUE(contents->state_is_leaving_interstitial());
877 EXPECT_EQ(interstitial_rvh, contents->render_view_host());
879 // DidNavigate from the new page
880 ViewHostMsg_FrameNavigate_Params params3;
881 InitNavigateParams(&params3, 1, url2);
882 contents->TestDidNavigate(new_rvh, params3);
883 EXPECT_TRUE(contents->state_is_normal());
884 EXPECT_EQ(new_rvh, contents->render_view_host());
885 EXPECT_TRUE(contents->pending_rvh() == NULL);
886 EXPECT_EQ(orig_rvh_delete_count, 1);
889 // Tests that we can transition away from an interstitial page even if the
890 // interstitial renderer has crashed.
891 TEST_F(WebContentsTest, CrossSiteInterstitialCrashThenNavigate) {
892 contents->transition_cross_site = true;
893 int orig_rvh_delete_count = 0;
894 TestRenderViewHost* orig_rvh = contents->rvh();
895 orig_rvh->set_delete_counter(&orig_rvh_delete_count);
897 // Navigate to URL. First URL should use first RenderViewHost.
898 const GURL url("http://www.google.com");
899 contents->controller()->LoadURL(url, PageTransition::TYPED);
900 ViewHostMsg_FrameNavigate_Params params1;
901 InitNavigateParams(&params1, 1, url);
902 contents->TestDidNavigate(orig_rvh, params1);
904 // Navigate to new site
905 const GURL url2("https://www.google.com");
906 contents->controller()->LoadURL(url2, PageTransition::TYPED);
907 TestRenderViewHost* pending_rvh = contents->pending_rvh();
908 int pending_rvh_delete_count = 0;
909 pending_rvh->set_delete_counter(&pending_rvh_delete_count);
911 // Show an interstitial
912 const GURL interstitial_url("http://interstitial");
913 InterstitialPage* interstitial = new InterstitialPage(contents,
914 true,
915 interstitial_url);
916 interstitial->Show();
917 TestRenderViewHost* interstitial_rvh = contents->interstitial_rvh();
919 // DidNavigate from the interstitial
920 ViewHostMsg_FrameNavigate_Params params2;
921 InitNavigateParams(&params2, 1, url2);
922 contents->TestDidNavigate(interstitial_rvh, params2);
923 EXPECT_TRUE(contents->state_is_interstitial());
924 EXPECT_EQ(interstitial_rvh, contents->render_view_host());
925 EXPECT_EQ(orig_rvh, contents->original_rvh());
926 EXPECT_EQ(pending_rvh, contents->pending_rvh());
927 EXPECT_TRUE(contents->interstitial_rvh() == NULL);
929 // Crash the interstitial RVH
930 // (by making IsRenderViewLive() == false)
931 interstitial_rvh->is_created = false;
933 // Navigate to a new page. Since interstitial RVH is dead, we should clean
934 // it up and go to a new PENDING state, showing the orig_rvh.
935 const GURL url3("http://www.yahoo.com");
936 contents->controller()->LoadURL(url3, PageTransition::TYPED);
937 TestRenderViewHost* new_rvh = contents->pending_rvh();
938 ASSERT_TRUE(new_rvh != NULL);
939 EXPECT_TRUE(contents->state_is_pending());
940 EXPECT_EQ(orig_rvh, contents->render_view_host());
941 EXPECT_EQ(pending_rvh_delete_count, 1);
942 EXPECT_NE(interstitial_rvh, new_rvh);
943 EXPECT_TRUE(contents->original_rvh() == NULL);
944 EXPECT_TRUE(contents->interstitial_rvh() == NULL);
946 // DidNavigate from the new page
947 ViewHostMsg_FrameNavigate_Params params3;
948 InitNavigateParams(&params3, 1, url3);
949 contents->TestDidNavigate(new_rvh, params3);
950 EXPECT_TRUE(contents->state_is_normal());
951 EXPECT_EQ(new_rvh, contents->render_view_host());
952 EXPECT_TRUE(contents->pending_rvh() == NULL);
953 EXPECT_EQ(orig_rvh_delete_count, 1);
956 // Tests that we can transition away from an interstitial page even if both the
957 // original and interstitial renderers have crashed.
958 TEST_F(WebContentsTest, CrossSiteInterstitialCrashesThenNavigate) {
959 contents->transition_cross_site = true;
960 int orig_rvh_delete_count = 0;
961 TestRenderViewHost* orig_rvh = contents->rvh();
962 orig_rvh->set_delete_counter(&orig_rvh_delete_count);
964 // Navigate to URL. First URL should use first RenderViewHost.
965 const GURL url("http://www.google.com");
966 contents->controller()->LoadURL(url, PageTransition::TYPED);
967 ViewHostMsg_FrameNavigate_Params params1;
968 InitNavigateParams(&params1, 1, url);
969 contents->TestDidNavigate(orig_rvh, params1);
971 // Navigate to new site
972 const GURL url2("https://www.google.com");
973 contents->controller()->LoadURL(url2, PageTransition::TYPED);
974 TestRenderViewHost* pending_rvh = contents->pending_rvh();
975 int pending_rvh_delete_count = 0;
976 pending_rvh->set_delete_counter(&pending_rvh_delete_count);
978 // Show an interstitial
979 const GURL interstitial_url("http://interstitial");
980 InterstitialPage* interstitial = new InterstitialPage(contents,
981 true,
982 interstitial_url);
983 interstitial->Show();
984 TestRenderViewHost* interstitial_rvh = contents->interstitial_rvh();
986 // DidNavigate from the interstitial
987 ViewHostMsg_FrameNavigate_Params params2;
988 InitNavigateParams(&params2, 1, url2);
989 contents->TestDidNavigate(interstitial_rvh, params2);
990 EXPECT_TRUE(contents->state_is_interstitial());
991 EXPECT_EQ(interstitial_rvh, contents->render_view_host());
992 EXPECT_EQ(orig_rvh, contents->original_rvh());
993 EXPECT_EQ(pending_rvh, contents->pending_rvh());
994 EXPECT_TRUE(contents->interstitial_rvh() == NULL);
996 // Crash both the original and interstitial RVHs
997 // (by making IsRenderViewLive() == false)
998 orig_rvh->is_created = false;
999 interstitial_rvh->is_created = false;
1001 // Navigate to a new page. Since both the interstitial and original RVHs are
1002 // dead, we should create a new RVH, jump back to NORMAL, and navigate.
1003 const GURL url3("http://www.yahoo.com");
1004 contents->controller()->LoadURL(url3, PageTransition::TYPED);
1005 TestRenderViewHost* new_rvh = contents->rvh();
1006 ASSERT_TRUE(new_rvh != NULL);
1007 EXPECT_TRUE(contents->state_is_normal());
1008 EXPECT_EQ(orig_rvh_delete_count, 1);
1009 EXPECT_EQ(pending_rvh_delete_count, 1);
1010 EXPECT_NE(interstitial_rvh, new_rvh);
1011 EXPECT_TRUE(contents->pending_rvh() == NULL);
1012 EXPECT_TRUE(contents->original_rvh() == NULL);
1013 EXPECT_TRUE(contents->interstitial_rvh() == NULL);
1015 // DidNavigate from the new page
1016 ViewHostMsg_FrameNavigate_Params params3;
1017 InitNavigateParams(&params3, 1, url3);
1018 contents->TestDidNavigate(new_rvh, params3);
1019 EXPECT_TRUE(contents->state_is_normal());
1020 EXPECT_EQ(new_rvh, contents->render_view_host());
1023 // Test that opening a new tab in the same SiteInstance and then navigating
1024 // both tabs to a new site will place both tabs in a single SiteInstance.
1025 TEST_F(WebContentsTest, NavigateTwoTabsCrossSite) {
1026 contents->transition_cross_site = true;
1027 TestRenderViewHost* orig_rvh = contents->rvh();
1028 SiteInstance* instance1 = contents->GetSiteInstance();
1030 // Navigate to URL. First URL should use first RenderViewHost.
1031 const GURL url("http://www.google.com");
1032 contents->controller()->LoadURL(url, PageTransition::TYPED);
1033 ViewHostMsg_FrameNavigate_Params params1;
1034 InitNavigateParams(&params1, 1, url);
1035 contents->TestDidNavigate(orig_rvh, params1);
1037 // Open a new tab with the same SiteInstance, navigated to the same site.
1038 TestWebContents* contents2 = new TestWebContents(profile.get(), instance1);
1039 params1.page_id = 2; // Need this since the site instance is the same (which
1040 // is the scope of page IDs) and we want to consider
1041 // this a new page.
1042 contents2->transition_cross_site = true;
1043 contents2->SetupController(profile.get());
1044 contents2->controller()->LoadURL(url, PageTransition::TYPED);
1045 contents2->TestDidNavigate(contents2->rvh(), params1);
1047 // Navigate first tab to a new site
1048 const GURL url2a("http://www.yahoo.com");
1049 contents->controller()->LoadURL(url2a, PageTransition::TYPED);
1050 TestRenderViewHost* pending_rvh_a = contents->pending_rvh();
1051 ViewHostMsg_FrameNavigate_Params params2a;
1052 InitNavigateParams(&params2a, 1, url2a);
1053 contents->TestDidNavigate(pending_rvh_a, params2a);
1054 SiteInstance* instance2a = contents->GetSiteInstance();
1055 EXPECT_NE(instance1, instance2a);
1057 // Navigate second tab to the same site as the first tab
1058 const GURL url2b("http://mail.yahoo.com");
1059 contents2->controller()->LoadURL(url2b, PageTransition::TYPED);
1060 TestRenderViewHost* pending_rvh_b = contents2->pending_rvh();
1061 EXPECT_TRUE(pending_rvh_b != NULL);
1062 EXPECT_TRUE(contents2->state_is_pending());
1064 // NOTE(creis): We used to be in danger of showing a sad tab page here if the
1065 // second tab hadn't navigated somewhere first (bug 1145430). That case is
1066 // now covered by the CrossSiteBoundariesAfterCrash test.
1068 ViewHostMsg_FrameNavigate_Params params2b;
1069 InitNavigateParams(&params2b, 2, url2b);
1070 contents2->TestDidNavigate(pending_rvh_b, params2b);
1071 SiteInstance* instance2b = contents2->GetSiteInstance();
1072 EXPECT_NE(instance1, instance2b);
1074 // Both tabs should now be in the same SiteInstance.
1075 EXPECT_EQ(instance2a, instance2b);
1077 contents2->CloseContents();
1080 // Tests that WebContents uses the current URL, not the SiteInstance's site, to
1081 // determine whether a navigation is cross-site.
1082 TEST_F(WebContentsTest, CrossSiteComparesAgainstCurrentPage) {
1083 contents->transition_cross_site = true;
1084 TestRenderViewHost* orig_rvh = contents->rvh();
1085 SiteInstance* instance1 = contents->GetSiteInstance();
1087 // Navigate to URL.
1088 const GURL url("http://www.google.com");
1089 contents->controller()->LoadURL(url, PageTransition::TYPED);
1090 ViewHostMsg_FrameNavigate_Params params1;
1091 InitNavigateParams(&params1, 1, url);
1092 contents->TestDidNavigate(orig_rvh, params1);
1094 // Open a related tab to a second site.
1095 TestWebContents* contents2 = new TestWebContents(profile.get(), instance1);
1096 contents2->transition_cross_site = true;
1097 contents2->SetupController(profile.get());
1098 const GURL url2("http://www.yahoo.com");
1099 contents2->controller()->LoadURL(url2, PageTransition::TYPED);
1100 // The first RVH in contents2 isn't live yet, so we shortcut the PENDING
1101 // state and go straight to NORMAL.
1102 TestRenderViewHost* rvh2 = contents2->rvh();
1103 EXPECT_TRUE(contents2->state_is_normal());
1104 ViewHostMsg_FrameNavigate_Params params2;
1105 InitNavigateParams(&params2, 2, url2);
1106 contents2->TestDidNavigate(rvh2, params2);
1107 SiteInstance* instance2 = contents2->GetSiteInstance();
1108 EXPECT_NE(instance1, instance2);
1109 EXPECT_TRUE(contents2->state_is_normal());
1111 // Simulate a link click in first tab to second site. Doesn't switch
1112 // SiteInstances, because we don't intercept WebKit navigations.
1113 ViewHostMsg_FrameNavigate_Params params3;
1114 InitNavigateParams(&params3, 2, url2);
1115 contents->TestDidNavigate(orig_rvh, params3);
1116 SiteInstance* instance3 = contents->GetSiteInstance();
1117 EXPECT_EQ(instance1, instance3);
1118 EXPECT_TRUE(contents->state_is_normal());
1120 // Navigate to the new site. Doesn't switch SiteInstancees, because we
1121 // compare against the current URL, not the SiteInstance's site.
1122 const GURL url3("http://mail.yahoo.com");
1123 contents->controller()->LoadURL(url3, PageTransition::TYPED);
1124 EXPECT_TRUE(contents->state_is_normal());
1125 ViewHostMsg_FrameNavigate_Params params4;
1126 InitNavigateParams(&params4, 3, url3);
1127 contents->TestDidNavigate(orig_rvh, params4);
1128 SiteInstance* instance4 = contents->GetSiteInstance();
1129 EXPECT_EQ(instance1, instance4);
1131 contents2->CloseContents();
1134 // Test that the onbeforeunload and onunload handlers run when navigating
1135 // across site boundaries.
1136 TEST_F(WebContentsTest, CrossSiteUnloadHandlers) {
1137 contents->transition_cross_site = true;
1138 TestRenderViewHost* orig_rvh = contents->rvh();
1139 SiteInstance* instance1 = contents->GetSiteInstance();
1141 // Navigate to URL. First URL should use first RenderViewHost.
1142 const GURL url("http://www.google.com");
1143 contents->controller()->LoadURL(url, PageTransition::TYPED);
1144 ViewHostMsg_FrameNavigate_Params params1;
1145 InitNavigateParams(&params1, 1, url);
1146 contents->TestDidNavigate(orig_rvh, params1);
1147 EXPECT_TRUE(contents->state_is_normal());
1148 EXPECT_EQ(orig_rvh, contents->render_view_host());
1150 // Navigate to new site, but simulate an onbeforeunload denial.
1151 const GURL url2("http://www.yahoo.com");
1152 orig_rvh->immediate_before_unload = false;
1153 contents->controller()->LoadURL(url2, PageTransition::TYPED);
1154 orig_rvh->TestOnMsgShouldClose(false);
1155 EXPECT_TRUE(contents->state_is_normal());
1156 EXPECT_EQ(orig_rvh, contents->render_view_host());
1158 // Navigate again, but simulate an onbeforeunload approval.
1159 contents->controller()->LoadURL(url2, PageTransition::TYPED);
1160 orig_rvh->TestOnMsgShouldClose(true);
1161 EXPECT_TRUE(contents->state_is_pending());
1162 TestRenderViewHost* pending_rvh = contents->pending_rvh();
1164 // We won't hear DidNavigate until the onunload handler has finished running.
1165 // (No way to simulate that here, but it involves a call from RDH to
1166 // WebContents::OnCrossSiteResponse.)
1168 // DidNavigate from the pending page
1169 ViewHostMsg_FrameNavigate_Params params2;
1170 InitNavigateParams(&params2, 1, url2);
1171 contents->TestDidNavigate(pending_rvh, params2);
1172 SiteInstance* instance2 = contents->GetSiteInstance();
1173 EXPECT_TRUE(contents->state_is_normal());
1174 EXPECT_EQ(pending_rvh, contents->render_view_host());
1175 EXPECT_NE(instance1, instance2);
1176 EXPECT_TRUE(contents->pending_rvh() == NULL);
1177 EXPECT_TRUE(contents->original_rvh() == NULL);
1178 EXPECT_TRUE(contents->interstitial_rvh() == NULL);
1181 // Test that NavigationEntries have the correct content state after going
1182 // forward and back. Prevents regression for bug 1116137.
1183 TEST_F(WebContentsTest, NavigationEntryContentState) {
1184 TestRenderViewHost* orig_rvh = contents->rvh();
1186 // Navigate to URL. There should be no committed entry yet.
1187 const GURL url("http://www.google.com");
1188 contents->controller()->LoadURL(url, PageTransition::TYPED);
1189 NavigationEntry* entry = contents->controller()->GetLastCommittedEntry();
1190 EXPECT_TRUE(entry == NULL);
1192 // Committed entry should have content state after DidNavigate.
1193 ViewHostMsg_FrameNavigate_Params params1;
1194 InitNavigateParams(&params1, 1, url);
1195 contents->TestDidNavigate(orig_rvh, params1);
1196 entry = contents->controller()->GetLastCommittedEntry();
1197 EXPECT_FALSE(entry->content_state().empty());
1199 // Navigate to same site.
1200 const GURL url2("http://images.google.com");
1201 contents->controller()->LoadURL(url2, PageTransition::TYPED);
1202 entry = contents->controller()->GetLastCommittedEntry();
1203 EXPECT_FALSE(entry->content_state().empty());
1205 // Committed entry should have content state after DidNavigate.
1206 ViewHostMsg_FrameNavigate_Params params2;
1207 InitNavigateParams(&params2, 2, url2);
1208 contents->TestDidNavigate(orig_rvh, params2);
1209 entry = contents->controller()->GetLastCommittedEntry();
1210 EXPECT_FALSE(entry->content_state().empty());
1212 // Now go back. Committed entry should still have content state.
1213 contents->controller()->GoBack();
1214 contents->TestDidNavigate(orig_rvh, params1);
1215 entry = contents->controller()->GetLastCommittedEntry();
1216 EXPECT_FALSE(entry->content_state().empty());
1219 // Test that NavigationEntries have the correct content state after opening
1220 // a new window to about:blank. Prevents regression for bug 1116137.
1221 TEST_F(WebContentsTest, NavigationEntryContentStateNewWindow) {
1222 TestRenderViewHost* orig_rvh = contents->rvh();
1224 // When opening a new window, it is navigated to about:blank internally.
1225 // Currently, this results in two DidNavigate events.
1226 const GURL url("about:blank");
1227 ViewHostMsg_FrameNavigate_Params params1;
1228 InitNavigateParams(&params1, 1, url);
1229 contents->TestDidNavigate(orig_rvh, params1);
1230 contents->TestDidNavigate(orig_rvh, params1);
1232 // Should have a content state here.
1233 NavigationEntry* entry = contents->controller()->GetLastCommittedEntry();
1234 EXPECT_FALSE(entry->content_state().empty());
1237 // Tests to see that webkit preferences are properly loaded and copied over
1238 // to a WebPreferences object.
1239 TEST_F(WebContentsTest, WebKitPrefs) {
1240 WebPreferences webkit_prefs = contents->TestGetWebkitPrefs();
1242 // These values have been overridden by the profile preferences.
1243 EXPECT_EQ(L"UTF-8", webkit_prefs.default_encoding);
1244 EXPECT_EQ(20, webkit_prefs.default_font_size);
1245 EXPECT_EQ(false, webkit_prefs.text_areas_are_resizable);
1246 EXPECT_EQ(true, webkit_prefs.uses_universal_detector);
1248 // These should still be the default values.
1249 EXPECT_EQ(L"Times New Roman", webkit_prefs.standard_font_family);
1250 EXPECT_EQ(true, webkit_prefs.javascript_enabled);