Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Side by Side Diff: chrome/browser/tab_contents/web_contents_unittest.cc

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

Powered by Google App Engine
This is Rietveld 408576698