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