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