Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / captive_portal / captive_portal_tab_helper_unittest.cc
1 // Copyright (c) 2012 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 "chrome/browser/captive_portal/captive_portal_tab_helper.h"
6
7 #include "base/callback.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "chrome/browser/captive_portal/captive_portal_service.h"
10 #include "chrome/browser/captive_portal/captive_portal_tab_reloader.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
13 #include "content/public/browser/notification_details.h"
14 #include "content/public/browser/notification_service.h"
15 #include "content/public/browser/notification_source.h"
16 #include "content/public/browser/notification_types.h"
17 #include "content/public/browser/render_view_host.h"
18 #include "content/public/browser/render_process_host.h"
19 #include "content/public/browser/web_contents.h"
20 #include "net/base/net_errors.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23
24 using captive_portal::CaptivePortalResult;
25
26 namespace {
27
28 const char* const kHttpUrl = "http://whatever.com/";
29 const char* const kHttpsUrl = "https://whatever.com/";
30
31 // Used for cross-process navigations.  Shouldn't actually matter whether this
32 // is different from kHttpsUrl, but best to keep things consistent.
33 const char* const kHttpsUrl2 = "https://cross_process.com/";
34
35 // Error pages use a "data:" URL.  Shouldn't actually matter what this is.
36 const char* const kErrorPageUrl = "data:blah";
37
38 // Some navigations behave differently depending on if they're cross-process
39 // or not.
40 enum NavigationType {
41   kSameProcess,
42   kCrossProcess,
43 };
44
45 }  // namespace
46
47 class MockCaptivePortalTabReloader : public CaptivePortalTabReloader {
48  public:
49   MockCaptivePortalTabReloader()
50       : CaptivePortalTabReloader(NULL, NULL, base::Callback<void()>()) {
51   }
52
53   MOCK_METHOD1(OnLoadStart, void(bool));
54   MOCK_METHOD1(OnLoadCommitted, void(int));
55   MOCK_METHOD0(OnAbort, void());
56   MOCK_METHOD1(OnRedirect, void(bool));
57   MOCK_METHOD2(OnCaptivePortalResults,
58                void(CaptivePortalResult, CaptivePortalResult));
59 };
60
61 // Inherits from the ChromeRenderViewHostTestHarness to gain access to
62 // CreateTestWebContents.  Since the tests need to micromanage order of
63 // WebContentsObserver function calls, does not actually make sure of
64 // the harness in any other way.
65 class CaptivePortalTabHelperTest : public ChromeRenderViewHostTestHarness {
66  public:
67   CaptivePortalTabHelperTest()
68       : tab_helper_(NULL),
69         mock_reloader_(new testing::StrictMock<MockCaptivePortalTabReloader>) {
70     tab_helper_.SetTabReloaderForTest(mock_reloader_);
71   }
72   virtual ~CaptivePortalTabHelperTest() {}
73
74   virtual void SetUp() OVERRIDE {
75     ChromeRenderViewHostTestHarness::SetUp();
76     web_contents1_.reset(CreateTestWebContents());
77     web_contents2_.reset(CreateTestWebContents());
78   }
79
80   virtual void TearDown() OVERRIDE {
81     web_contents2_.reset(NULL);
82     web_contents1_.reset(NULL);
83     ChromeRenderViewHostTestHarness::TearDown();
84   }
85
86   // Simulates a successful load of |url|.
87   void SimulateSuccess(const GURL& url,
88                        content::RenderViewHost* render_view_host) {
89     EXPECT_CALL(mock_reloader(), OnLoadStart(url.SchemeIsSecure())).Times(1);
90     tab_helper().DidStartProvisionalLoadForFrame(
91         1, -1, true, url, false, false, render_view_host);
92
93     EXPECT_CALL(mock_reloader(), OnLoadCommitted(net::OK)).Times(1);
94     tab_helper().DidCommitProvisionalLoadForFrame(
95         1, base::string16(), true, url, content::PAGE_TRANSITION_LINK,
96         render_view_host);
97   }
98
99   // Simulates a connection timeout while requesting |url|.
100   void SimulateTimeout(const GURL& url,
101                        content::RenderViewHost* render_view_host) {
102     EXPECT_CALL(mock_reloader(), OnLoadStart(url.SchemeIsSecure())).Times(1);
103     tab_helper().DidStartProvisionalLoadForFrame(
104         1, -1, true, url, false, false, render_view_host);
105
106     tab_helper().DidFailProvisionalLoad(
107         1, base::string16(), true, url, net::ERR_TIMED_OUT, base::string16(),
108         render_view_host);
109
110     // Provisional load starts for the error page.
111     tab_helper().DidStartProvisionalLoadForFrame(
112         1, -1, true, GURL(kErrorPageUrl), true, false, render_view_host);
113
114     EXPECT_CALL(mock_reloader(), OnLoadCommitted(net::ERR_TIMED_OUT)).Times(1);
115     tab_helper().DidCommitProvisionalLoadForFrame(
116         1, base::string16(), true, GURL(kErrorPageUrl),
117         content::PAGE_TRANSITION_LINK, render_view_host);
118   }
119
120   // Simulates an abort while requesting |url|.
121   void SimulateAbort(const GURL& url,
122                      content::RenderViewHost* render_view_host,
123                      NavigationType navigation_type) {
124     EXPECT_CALL(mock_reloader(), OnLoadStart(url.SchemeIsSecure())).Times(1);
125     tab_helper().DidStartProvisionalLoadForFrame(
126         1, -1, true, url, false, false, render_view_host);
127
128     EXPECT_CALL(mock_reloader(), OnAbort()).Times(1);
129     if (navigation_type == kSameProcess) {
130       tab_helper().DidFailProvisionalLoad(
131           1, base::string16(), true, url, net::ERR_ABORTED, base::string16(),
132           render_view_host);
133     } else {
134       // For interrupted provisional cross-process navigations, the
135       // RenderViewHost is destroyed without sending a DidFailProvisionalLoad
136       // notification.
137       tab_helper().RenderViewDeleted(render_view_host);
138     }
139
140     // Make sure that above call resulted in abort, for tests that continue
141     // after the abort.
142     EXPECT_CALL(mock_reloader(), OnAbort()).Times(0);
143   }
144
145   // Simulates an abort while loading an error page.
146   void SimulateAbortTimeout(const GURL& url,
147                             content::RenderViewHost* render_view_host,
148                             NavigationType navigation_type) {
149     EXPECT_CALL(mock_reloader(), OnLoadStart(url.SchemeIsSecure())).Times(1);
150     tab_helper().DidStartProvisionalLoadForFrame(
151         1, -1, true, url, false, false, render_view_host);
152
153     tab_helper().DidFailProvisionalLoad(
154         1, base::string16(), true, url, net::ERR_TIMED_OUT, base::string16(),
155         render_view_host);
156
157     // Start event for the error page.
158     tab_helper().DidStartProvisionalLoadForFrame(
159         1, -1, true, url, true, false, render_view_host);
160
161     EXPECT_CALL(mock_reloader(), OnAbort()).Times(1);
162     if (navigation_type == kSameProcess) {
163       tab_helper().DidFailProvisionalLoad(
164           1, base::string16(), true, url, net::ERR_ABORTED, base::string16(),
165           render_view_host);
166     } else {
167       // For interrupted provisional cross-process navigations, the
168       // RenderViewHost is destroyed without sending a DidFailProvisionalLoad
169       // notification.
170       tab_helper().RenderViewDeleted(render_view_host);
171     }
172
173     // Make sure that above call resulted in abort, for tests that continue
174     // after the abort.
175     EXPECT_CALL(mock_reloader(), OnAbort()).Times(0);
176   }
177
178   CaptivePortalTabHelper& tab_helper() {
179     return tab_helper_;
180   }
181
182   // Simulates a captive portal redirect by calling the Observe method.
183   void ObservePortalResult(CaptivePortalResult previous_result,
184                            CaptivePortalResult result) {
185     content::Source<Profile> source_profile(NULL);
186
187     CaptivePortalService::Results results;
188     results.previous_result = previous_result;
189     results.result = result;
190     content::Details<CaptivePortalService::Results> details_results(&results);
191
192     EXPECT_CALL(mock_reloader(), OnCaptivePortalResults(previous_result,
193                                                         result)).Times(1);
194     tab_helper().Observe(chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT,
195                          source_profile,
196                          details_results);
197   }
198
199   // Simulates a redirect.  Uses OnRedirect rather than Observe, for simplicity.
200   void OnRedirect(ResourceType::Type type, const GURL& new_url, int child_id) {
201     tab_helper().OnRedirect(child_id, type, new_url);
202   }
203
204   MockCaptivePortalTabReloader& mock_reloader() { return *mock_reloader_; }
205
206   void SetIsLoginTab() {
207     tab_helper().SetIsLoginTab();
208   }
209
210   content::RenderViewHost* render_view_host1() {
211     return web_contents1_->GetRenderViewHost();
212   }
213
214   content::RenderViewHost* render_view_host2() {
215     return web_contents2_->GetRenderViewHost();
216   }
217
218  private:
219   // Only the RenderViewHosts are used.
220   scoped_ptr<content::WebContents> web_contents1_;
221   scoped_ptr<content::WebContents> web_contents2_;
222
223   CaptivePortalTabHelper tab_helper_;
224
225   // Owned by |tab_helper_|.
226   testing::StrictMock<MockCaptivePortalTabReloader>* mock_reloader_;
227
228   DISALLOW_COPY_AND_ASSIGN(CaptivePortalTabHelperTest);
229 };
230
231 TEST_F(CaptivePortalTabHelperTest, HttpSuccess) {
232   SimulateSuccess(GURL(kHttpUrl), render_view_host1());
233   tab_helper().DidStopLoading(render_view_host1());
234 }
235
236 TEST_F(CaptivePortalTabHelperTest, HttpTimeout) {
237   SimulateTimeout(GURL(kHttpUrl), render_view_host1());
238   tab_helper().DidStopLoading(render_view_host1());
239 }
240
241 // Same as above, but simulates what happens when the Link Doctor is enabled,
242 // which adds another provisional load/commit for the error page, after the
243 // first two.
244 TEST_F(CaptivePortalTabHelperTest, HttpTimeoutLinkDoctor) {
245   SimulateTimeout(GURL(kHttpUrl), render_view_host1());
246
247   EXPECT_CALL(mock_reloader(), OnLoadStart(false)).Times(1);
248   // Provisional load starts for the error page.
249   tab_helper().DidStartProvisionalLoadForFrame(
250       1, -1, true, GURL(kErrorPageUrl), true, false, render_view_host1());
251
252   EXPECT_CALL(mock_reloader(), OnLoadCommitted(net::OK)).Times(1);
253   tab_helper().DidCommitProvisionalLoadForFrame(
254       1, base::string16(), true, GURL(kErrorPageUrl),
255       content::PAGE_TRANSITION_LINK, render_view_host1());
256   tab_helper().DidStopLoading(render_view_host1());
257 }
258
259 TEST_F(CaptivePortalTabHelperTest, HttpsSuccess) {
260   SimulateSuccess(GURL(kHttpsUrl), render_view_host1());
261   tab_helper().DidStopLoading(render_view_host1());
262   EXPECT_FALSE(tab_helper().IsLoginTab());
263 }
264
265 TEST_F(CaptivePortalTabHelperTest, HttpsTimeout) {
266   SimulateTimeout(GURL(kHttpsUrl), render_view_host1());
267   // Make sure no state was carried over from the timeout.
268   SimulateSuccess(GURL(kHttpsUrl), render_view_host1());
269   EXPECT_FALSE(tab_helper().IsLoginTab());
270 }
271
272 TEST_F(CaptivePortalTabHelperTest, HttpsAbort) {
273   SimulateAbort(GURL(kHttpsUrl), render_view_host1(), kSameProcess);
274   // Make sure no state was carried over from the abort.
275   SimulateSuccess(GURL(kHttpsUrl), render_view_host1());
276   EXPECT_FALSE(tab_helper().IsLoginTab());
277 }
278
279 // A cross-process navigation is aborted by a same-site navigation.
280 TEST_F(CaptivePortalTabHelperTest, AbortCrossProcess) {
281   SimulateAbort(GURL(kHttpsUrl2), render_view_host2(), kCrossProcess);
282   // Make sure no state was carried over from the abort.
283   SimulateSuccess(GURL(kHttpUrl), render_view_host1());
284   EXPECT_FALSE(tab_helper().IsLoginTab());
285 }
286
287 // Abort while there's a provisional timeout error page loading.
288 TEST_F(CaptivePortalTabHelperTest, HttpsAbortTimeout) {
289   SimulateAbortTimeout(GURL(kHttpsUrl), render_view_host1(), kSameProcess);
290   // Make sure no state was carried over from the timeout or the abort.
291   SimulateSuccess(GURL(kHttpsUrl), render_view_host1());
292   EXPECT_FALSE(tab_helper().IsLoginTab());
293 }
294
295 // Abort a cross-process navigation while there's a provisional timeout error
296 // page loading.
297 TEST_F(CaptivePortalTabHelperTest, AbortTimeoutCrossProcess) {
298   SimulateAbortTimeout(GURL(kHttpsUrl2), render_view_host2(),
299                        kCrossProcess);
300   // Make sure no state was carried over from the timeout or the abort.
301   SimulateSuccess(GURL(kHttpsUrl), render_view_host1());
302   EXPECT_FALSE(tab_helper().IsLoginTab());
303 }
304
305 // Opposite case from above - a same-process error page is aborted in favor of
306 // a cross-process one.
307 TEST_F(CaptivePortalTabHelperTest, HttpsAbortTimeoutForCrossProcess) {
308   SimulateAbortTimeout(GURL(kHttpsUrl), render_view_host1(), kSameProcess);
309   // Make sure no state was carried over from the timeout or the abort.
310   SimulateSuccess(GURL(kHttpsUrl2), render_view_host2());
311   EXPECT_FALSE(tab_helper().IsLoginTab());
312 }
313
314 // A provisional same-site navigation is interrupted by a cross-process
315 // navigation without sending an abort first.
316 TEST_F(CaptivePortalTabHelperTest, UnexpectedProvisionalLoad) {
317   GURL same_site_url = GURL(kHttpUrl);
318   GURL cross_process_url = GURL(kHttpsUrl2);
319
320   // A same-site load for the original RenderViewHost starts.
321   EXPECT_CALL(mock_reloader(),
322               OnLoadStart(same_site_url.SchemeIsSecure())).Times(1);
323   tab_helper().DidStartProvisionalLoadForFrame(
324       1, -1, true, same_site_url, false, false, render_view_host1());
325
326   // It's unexpectedly interrupted by a cross-process navigation, which starts
327   // navigating before the old navigation cancels.  We generate an abort message
328   // for the old navigation.
329   EXPECT_CALL(mock_reloader(), OnAbort()).Times(1);
330   EXPECT_CALL(mock_reloader(),
331               OnLoadStart(cross_process_url.SchemeIsSecure())).Times(1);
332   tab_helper().DidStartProvisionalLoadForFrame(
333       1, -1, true, cross_process_url, false, false, render_view_host2());
334
335   // The cross-process navigation fails.
336   tab_helper().DidFailProvisionalLoad(
337       1, base::string16(), true, cross_process_url, net::ERR_FAILED,
338       base::string16(), render_view_host2());
339
340   // The same-site navigation finally is aborted.
341   tab_helper().DidFailProvisionalLoad(
342       1, base::string16(), true, same_site_url, net::ERR_ABORTED,
343       base::string16(), render_view_host1());
344
345   // The provisional load starts for the error page for the cross-process
346   // navigation.
347   tab_helper().DidStartProvisionalLoadForFrame(
348       1, -1, true, GURL(kErrorPageUrl), true, false, render_view_host2());
349
350   EXPECT_CALL(mock_reloader(), OnLoadCommitted(net::ERR_FAILED)).Times(1);
351   tab_helper().DidCommitProvisionalLoadForFrame(
352       1, base::string16(), true, GURL(kErrorPageUrl),
353       content::PAGE_TRANSITION_TYPED, render_view_host2());
354 }
355
356 // Similar to the above test, except the original RenderViewHost manages to
357 // commit before its navigation is aborted.
358 TEST_F(CaptivePortalTabHelperTest, UnexpectedCommit) {
359   GURL same_site_url = GURL(kHttpUrl);
360   GURL cross_process_url = GURL(kHttpsUrl2);
361
362   // A same-site load for the original RenderViewHost starts.
363   EXPECT_CALL(mock_reloader(),
364               OnLoadStart(same_site_url.SchemeIsSecure())).Times(1);
365   tab_helper().DidStartProvisionalLoadForFrame(
366       1, -1, true, same_site_url, false, false, render_view_host1());
367
368   // It's unexpectedly interrupted by a cross-process navigation, which starts
369   // navigating before the old navigation cancels.  We generate an abort message
370   // for the old navigation.
371   EXPECT_CALL(mock_reloader(), OnAbort()).Times(1);
372   EXPECT_CALL(mock_reloader(),
373               OnLoadStart(cross_process_url.SchemeIsSecure())).Times(1);
374   tab_helper().DidStartProvisionalLoadForFrame(
375       1, -1, true, cross_process_url, false, false, render_view_host2());
376
377   // The cross-process navigation fails.
378   tab_helper().DidFailProvisionalLoad(
379       1, base::string16(), true, cross_process_url, net::ERR_FAILED,
380       base::string16(),
381       render_view_host2());
382
383   // The same-site navigation succeeds.
384   EXPECT_CALL(mock_reloader(), OnAbort()).Times(1);
385   EXPECT_CALL(mock_reloader(),
386               OnLoadStart(same_site_url.SchemeIsSecure())).Times(1);
387   EXPECT_CALL(mock_reloader(), OnLoadCommitted(net::OK)).Times(1);
388   tab_helper().DidCommitProvisionalLoadForFrame(
389       1, base::string16(), true, same_site_url, content::PAGE_TRANSITION_LINK,
390       render_view_host1());
391 }
392
393 // Simulates navigations for a number of subframes, and makes sure no
394 // CaptivePortalTabHelper function is called.
395 TEST_F(CaptivePortalTabHelperTest, HttpsSubframe) {
396   GURL url = GURL(kHttpsUrl);
397   // Normal load.
398   tab_helper().DidStartProvisionalLoadForFrame(
399       1, -1, false, url, false, false, render_view_host1());
400   tab_helper().DidCommitProvisionalLoadForFrame(
401       1, base::string16(), false, url, content::PAGE_TRANSITION_LINK,
402       render_view_host1());
403
404   // Timeout.
405   tab_helper().DidStartProvisionalLoadForFrame(
406       2, -1, false, url, false, false, render_view_host1());
407   tab_helper().DidFailProvisionalLoad(
408       2, base::string16(), false, url, net::ERR_TIMED_OUT, base::string16(),
409       render_view_host1());
410   tab_helper().DidStartProvisionalLoadForFrame(
411       2, -1, false, url, true, false, render_view_host1());
412   tab_helper().DidFailProvisionalLoad(
413       2, base::string16(), false, url, net::ERR_ABORTED, base::string16(),
414       render_view_host1());
415
416   // Abort.
417   tab_helper().DidStartProvisionalLoadForFrame(
418       3, -1, false, url, false, false, render_view_host1());
419   tab_helper().DidFailProvisionalLoad(
420       3, base::string16(), false, url, net::ERR_ABORTED, base::string16(),
421       render_view_host1());
422 }
423
424 // Simulates a subframe erroring out at the same time as a provisional load,
425 // but with a different error code.  Make sure the TabHelper sees the correct
426 // error.
427 TEST_F(CaptivePortalTabHelperTest, HttpsSubframeParallelError) {
428   // URL used by both frames.
429   GURL url = GURL(kHttpsUrl);
430
431   int frame_id = 2;
432   int subframe_id = 1;
433
434   // Loads start.
435   EXPECT_CALL(mock_reloader(), OnLoadStart(url.SchemeIsSecure())).Times(1);
436   tab_helper().DidStartProvisionalLoadForFrame(
437       frame_id, -1, true, url, false, false, render_view_host1());
438   tab_helper().DidStartProvisionalLoadForFrame(
439       subframe_id, frame_id, false, url, false, false, render_view_host1());
440
441   // Loads return errors.
442   tab_helper().DidFailProvisionalLoad(
443       frame_id, base::string16(), true, url, net::ERR_UNEXPECTED,
444       base::string16(), render_view_host1());
445   tab_helper().DidFailProvisionalLoad(
446       subframe_id, base::string16(), false, url, net::ERR_TIMED_OUT,
447       base::string16(), render_view_host1());
448
449   // Provisional load starts for the error pages.
450   tab_helper().DidStartProvisionalLoadForFrame(
451       frame_id, -1, true, url, true, false, render_view_host1());
452   tab_helper().DidStartProvisionalLoadForFrame(
453       subframe_id, frame_id, false, url, true, false, render_view_host1());
454
455   // Error page load finishes.
456   tab_helper().DidCommitProvisionalLoadForFrame(
457       subframe_id, base::string16(), false, url,
458       content::PAGE_TRANSITION_AUTO_SUBFRAME, render_view_host1());
459   EXPECT_CALL(mock_reloader(), OnLoadCommitted(net::ERR_UNEXPECTED)).Times(1);
460   tab_helper().DidCommitProvisionalLoadForFrame(
461       frame_id, base::string16(), true, url, content::PAGE_TRANSITION_LINK,
462       render_view_host1());
463 }
464
465 // Simulates an HTTP to HTTPS redirect, which then times out.
466 TEST_F(CaptivePortalTabHelperTest, HttpToHttpsRedirectTimeout) {
467   GURL http_url(kHttpUrl);
468   EXPECT_CALL(mock_reloader(), OnLoadStart(false)).Times(1);
469   tab_helper().DidStartProvisionalLoadForFrame(
470       1, -1, true, http_url, false, false, render_view_host1());
471
472   GURL https_url(kHttpsUrl);
473   EXPECT_CALL(mock_reloader(), OnRedirect(true)).Times(1);
474   OnRedirect(ResourceType::MAIN_FRAME, https_url,
475              render_view_host1()->GetProcess()->GetID());
476
477   tab_helper().DidFailProvisionalLoad(
478       1, base::string16(), true, https_url, net::ERR_TIMED_OUT,
479       base::string16(), render_view_host1());
480
481   // Provisional load starts for the error page.
482   tab_helper().DidStartProvisionalLoadForFrame(
483       1, -1, true, GURL(kErrorPageUrl), true, false, render_view_host1());
484
485   EXPECT_CALL(mock_reloader(), OnLoadCommitted(net::ERR_TIMED_OUT)).Times(1);
486   tab_helper().DidCommitProvisionalLoadForFrame(
487       1, base::string16(), true, GURL(kErrorPageUrl),
488       content::PAGE_TRANSITION_LINK, render_view_host1());
489 }
490
491 // Simulates an HTTPS to HTTP redirect.
492 TEST_F(CaptivePortalTabHelperTest, HttpsToHttpRedirect) {
493   GURL https_url(kHttpsUrl);
494   EXPECT_CALL(mock_reloader(),
495               OnLoadStart(https_url.SchemeIsSecure())).Times(1);
496   tab_helper().DidStartProvisionalLoadForFrame(1, -1, true, https_url, false,
497                                                false, render_view_host1());
498
499   GURL http_url(kHttpUrl);
500   EXPECT_CALL(mock_reloader(), OnRedirect(http_url.SchemeIsSecure())).Times(1);
501   OnRedirect(ResourceType::MAIN_FRAME, http_url,
502              render_view_host1()->GetProcess()->GetID());
503
504   EXPECT_CALL(mock_reloader(), OnLoadCommitted(net::OK)).Times(1);
505   tab_helper().DidCommitProvisionalLoadForFrame(
506       1, base::string16(), true, http_url, content::PAGE_TRANSITION_LINK,
507       render_view_host1());
508 }
509
510 // Simulates an HTTPS to HTTPS redirect.
511 TEST_F(CaptivePortalTabHelperTest, HttpToHttpRedirect) {
512   GURL http_url(kHttpUrl);
513   EXPECT_CALL(mock_reloader(),
514               OnLoadStart(http_url.SchemeIsSecure())).Times(1);
515   tab_helper().DidStartProvisionalLoadForFrame(
516       1, -1, true, http_url, false, false, render_view_host1());
517
518   EXPECT_CALL(mock_reloader(), OnRedirect(http_url.SchemeIsSecure())).Times(1);
519   OnRedirect(ResourceType::MAIN_FRAME, http_url,
520              render_view_host1()->GetProcess()->GetID());
521
522   EXPECT_CALL(mock_reloader(), OnLoadCommitted(net::OK)).Times(1);
523   tab_helper().DidCommitProvisionalLoadForFrame(
524       1, base::string16(), true, http_url, content::PAGE_TRANSITION_LINK,
525       render_view_host1());
526 }
527
528 // Simulates redirect of a subframe.
529 TEST_F(CaptivePortalTabHelperTest, SubframeRedirect) {
530   GURL http_url(kHttpUrl);
531   EXPECT_CALL(mock_reloader(), OnLoadStart(false)).Times(1);
532   tab_helper().DidStartProvisionalLoadForFrame(
533       1, -1, true, http_url, false, false, render_view_host1());
534
535   GURL https_url(kHttpsUrl);
536   OnRedirect(ResourceType::SUB_FRAME, https_url,
537              render_view_host1()->GetProcess()->GetID());
538
539   EXPECT_CALL(mock_reloader(), OnLoadCommitted(net::OK)).Times(1);
540   tab_helper().DidCommitProvisionalLoadForFrame(
541       1, base::string16(), true, GURL(kErrorPageUrl),
542       content::PAGE_TRANSITION_LINK, render_view_host1());
543 }
544
545 // Simulates a redirect, for another RenderViewHost.
546 TEST_F(CaptivePortalTabHelperTest, OtherRenderViewHostRedirect) {
547   GURL http_url(kHttpUrl);
548   EXPECT_CALL(mock_reloader(), OnLoadStart(false)).Times(1);
549   tab_helper().DidStartProvisionalLoadForFrame(
550       1, -1, true, http_url, false, false, render_view_host1());
551
552   // Another RenderViewHost sees a redirect.  None of the reloader's functions
553   // should be called.
554   GURL https_url(kHttpsUrl);
555   OnRedirect(ResourceType::MAIN_FRAME, https_url,
556              render_view_host2()->GetProcess()->GetID());
557
558   tab_helper().DidFailProvisionalLoad(
559       1, base::string16(), true, https_url, net::ERR_TIMED_OUT,
560       base::string16(), render_view_host1());
561
562   // Provisional load starts for the error page.
563   tab_helper().DidStartProvisionalLoadForFrame(
564       1, -1, true, GURL(kErrorPageUrl), true, false, render_view_host1());
565
566   EXPECT_CALL(mock_reloader(), OnLoadCommitted(net::ERR_TIMED_OUT)).Times(1);
567   tab_helper().DidCommitProvisionalLoadForFrame(
568       1, base::string16(), true, GURL(kErrorPageUrl),
569       content::PAGE_TRANSITION_LINK, render_view_host1());
570 }
571
572 TEST_F(CaptivePortalTabHelperTest, LoginTabLogin) {
573   EXPECT_FALSE(tab_helper().IsLoginTab());
574   SetIsLoginTab();
575   EXPECT_TRUE(tab_helper().IsLoginTab());
576
577   ObservePortalResult(captive_portal::RESULT_INTERNET_CONNECTED,
578                       captive_portal::RESULT_INTERNET_CONNECTED);
579   EXPECT_FALSE(tab_helper().IsLoginTab());
580 }
581
582 TEST_F(CaptivePortalTabHelperTest, LoginTabError) {
583   EXPECT_FALSE(tab_helper().IsLoginTab());
584
585   SetIsLoginTab();
586   EXPECT_TRUE(tab_helper().IsLoginTab());
587
588   ObservePortalResult(captive_portal::RESULT_INTERNET_CONNECTED,
589                       captive_portal::RESULT_NO_RESPONSE);
590   EXPECT_FALSE(tab_helper().IsLoginTab());
591 }
592
593 TEST_F(CaptivePortalTabHelperTest, LoginTabMultipleResultsBeforeLogin) {
594   EXPECT_FALSE(tab_helper().IsLoginTab());
595
596   SetIsLoginTab();
597   EXPECT_TRUE(tab_helper().IsLoginTab());
598
599   ObservePortalResult(captive_portal::RESULT_INTERNET_CONNECTED,
600                       captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL);
601   EXPECT_TRUE(tab_helper().IsLoginTab());
602
603   ObservePortalResult(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL,
604                       captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL);
605   EXPECT_TRUE(tab_helper().IsLoginTab());
606
607   ObservePortalResult(captive_portal::RESULT_NO_RESPONSE,
608                       captive_portal::RESULT_INTERNET_CONNECTED);
609   EXPECT_FALSE(tab_helper().IsLoginTab());
610 }
611
612 TEST_F(CaptivePortalTabHelperTest, NoLoginTab) {
613   EXPECT_FALSE(tab_helper().IsLoginTab());
614
615   ObservePortalResult(captive_portal::RESULT_INTERNET_CONNECTED,
616                       captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL);
617   EXPECT_FALSE(tab_helper().IsLoginTab());
618
619   ObservePortalResult(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL,
620                       captive_portal::RESULT_NO_RESPONSE);
621   EXPECT_FALSE(tab_helper().IsLoginTab());
622
623   ObservePortalResult(captive_portal::RESULT_NO_RESPONSE,
624                       captive_portal::RESULT_INTERNET_CONNECTED);
625   EXPECT_FALSE(tab_helper().IsLoginTab());
626 }