1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ssl/captive_portal_blocking_page.h"
9 #include "base/callback.h"
10 #include "base/logging.h"
11 #include "base/macros.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/strings/stringprintf.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "chrome/browser/ui/tabs/tab_strip_model.h"
17 #include "chrome/common/pref_names.h"
18 #include "chrome/test/base/in_process_browser_test.h"
19 #include "components/captive_portal/captive_portal_detector.h"
20 #include "content/public/browser/interstitial_page.h"
21 #include "content/public/browser/web_contents.h"
22 #include "content/public/test/browser_test_utils.h"
23 #include "testing/gtest/include/gtest/gtest.h"
27 // Partial text in the captive portal interstitial's main paragraph when the
28 // login domain isn't displayed.
29 const char kGenericLoginURLText
[] = "its login page";
30 const char kBrokenSSL
[] = "https://broken.ssl";
31 const char kWiFiSSID
[] = "WiFiSSID";
33 // Returns true if the interstitial contains |text| in its body.
34 bool IsInterstitialDisplayingText(content::InterstitialPage
* interstitial
,
35 const std::string
& text
) {
36 // It's valid for |text| to contain "\'", but simply look for "'" instead
37 // since this function is used for searching host names and a predefined
39 DCHECK(text
.find("\'") == std::string::npos
);
40 std::string command
= base::StringPrintf(
41 "var hasText = document.body.textContent.indexOf('%s') >= 0;"
42 "window.domAutomationController.send(hasText);",
45 EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
46 interstitial
->GetMainFrame(), command
, &result
));
67 class FakeConnectionInfoDelegate
: public CaptivePortalBlockingPage::Delegate
{
69 FakeConnectionInfoDelegate(bool is_wifi_connection
, std::string wifi_ssid
)
70 : is_wifi_connection_(is_wifi_connection
), wifi_ssid_(wifi_ssid
) {}
71 ~FakeConnectionInfoDelegate() override
{}
73 bool IsWifiConnection() const override
{ return is_wifi_connection_
; }
74 std::string
GetWiFiSSID() const override
{ return wifi_ssid_
; }
77 const bool is_wifi_connection_
;
78 const std::string wifi_ssid_
;
80 DISALLOW_COPY_AND_ASSIGN(FakeConnectionInfoDelegate
);
83 class CaptivePortalBlockingPageTest
: public InProcessBrowserTest
{
85 CaptivePortalBlockingPageTest() {}
87 void TestInterstitial(bool is_wifi_connection
,
88 const std::string
& wifi_ssid
,
89 const GURL
& login_url
,
90 ExpectWiFi expect_wifi
,
91 ExpectWiFiSSID expect_wifi_ssid
,
92 ExpectLoginURL expect_login_url
,
93 const std::string
& expected_login_hostname
);
95 void TestInterstitial(bool is_wifi_connection
,
96 const std::string
& wifi_ssid
,
97 const GURL
& login_url
,
98 ExpectWiFi expect_wifi
,
99 ExpectWiFiSSID expect_wifi_ssid
,
100 ExpectLoginURL expect_login_url
);
103 DISALLOW_COPY_AND_ASSIGN(CaptivePortalBlockingPageTest
);
106 void CaptivePortalBlockingPageTest::TestInterstitial(
107 bool is_wifi_connection
,
108 const std::string
& wifi_ssid
,
109 const GURL
& login_url
,
110 ExpectWiFi expect_wifi
,
111 ExpectWiFiSSID expect_wifi_ssid
,
112 ExpectLoginURL expect_login_url
,
113 const std::string
& expected_login_hostname
) {
114 content::WebContents
* contents
=
115 browser()->tab_strip_model()->GetActiveWebContents();
117 // Delegate is owned by the blocking page.
118 FakeConnectionInfoDelegate
* delegate
=
119 new FakeConnectionInfoDelegate(is_wifi_connection
, wifi_ssid
);
120 // Blocking page is owned by the interstitial.
121 CaptivePortalBlockingPage
* blocking_page
= new CaptivePortalBlockingPage(
122 contents
, GURL(kBrokenSSL
), login_url
, base::Callback
<void(bool)>());
123 blocking_page
->SetDelegateForTesting(delegate
);
124 blocking_page
->Show();
126 WaitForInterstitialAttach(contents
);
128 WaitForRenderFrameReady(contents
->GetInterstitialPage()->GetMainFrame()));
129 EXPECT_EQ(expect_wifi
== EXPECT_WIFI_YES
,
130 IsInterstitialDisplayingText(contents
->GetInterstitialPage(),
132 if (!wifi_ssid
.empty()) {
133 EXPECT_EQ(expect_wifi_ssid
== EXPECT_WIFI_SSID_YES
,
134 IsInterstitialDisplayingText(contents
->GetInterstitialPage(),
137 EXPECT_EQ(expect_login_url
== EXPECT_LOGIN_URL_YES
,
138 IsInterstitialDisplayingText(contents
->GetInterstitialPage(),
139 expected_login_hostname
));
140 EXPECT_EQ(expect_login_url
== EXPECT_LOGIN_URL_NO
,
141 IsInterstitialDisplayingText(contents
->GetInterstitialPage(),
142 kGenericLoginURLText
));
145 void CaptivePortalBlockingPageTest::TestInterstitial(
146 bool is_wifi_connection
,
147 const std::string
& wifi_ssid
,
148 const GURL
& login_url
,
149 ExpectWiFi expect_wifi
,
150 ExpectWiFiSSID expect_wifi_ssid
,
151 ExpectLoginURL expect_login_url
) {
152 TestInterstitial(is_wifi_connection
, wifi_ssid
, login_url
,
153 expect_wifi
, expect_wifi_ssid
, expect_login_url
,
157 // If the connection is not a Wi-Fi connection, the wired network version of the
158 // captive portal interstitial should be displayed.
159 IN_PROC_BROWSER_TEST_F(CaptivePortalBlockingPageTest
,
160 WiredNetwork_LoginURL
) {
161 TestInterstitial(false, "", GURL("http://captive.portal/landing_url"),
162 EXPECT_WIFI_NO
, EXPECT_WIFI_SSID_NO
, EXPECT_LOGIN_URL_YES
);
165 // Same as above, but SSID is available, so the connection should be assumed to
167 IN_PROC_BROWSER_TEST_F(CaptivePortalBlockingPageTest
,
168 WiredNetwork_LoginURL_With_SSID
) {
169 TestInterstitial(false, kWiFiSSID
, GURL("http://captive.portal/landing_url"),
170 EXPECT_WIFI_YES
, EXPECT_WIFI_SSID_YES
, EXPECT_LOGIN_URL_YES
);
173 // Same as above, expect the login URL is the same as the captive portal ping
174 // url (i.e. the portal intercepts requests without using HTTP redirects), in
175 // which case the login URL shouldn't be displayed.
176 IN_PROC_BROWSER_TEST_F(CaptivePortalBlockingPageTest
,
177 WiredNetwork_NoLoginURL
) {
178 const GURL
kLandingUrl(captive_portal::CaptivePortalDetector::kDefaultURL
);
179 TestInterstitial(false, "", kLandingUrl
, EXPECT_WIFI_NO
, EXPECT_WIFI_SSID_NO
,
180 EXPECT_LOGIN_URL_NO
);
183 // Same as above, but SSID is available, so the connection should be assumed to
185 IN_PROC_BROWSER_TEST_F(CaptivePortalBlockingPageTest
,
186 WiredNetwork_NoLoginURL_With_SSID
) {
187 const GURL
kLandingUrl(captive_portal::CaptivePortalDetector::kDefaultURL
);
188 TestInterstitial(false, kWiFiSSID
, kLandingUrl
, EXPECT_WIFI_YES
,
189 EXPECT_WIFI_SSID_YES
, EXPECT_LOGIN_URL_NO
);
192 // If the connection is a Wi-Fi connection, the Wi-Fi version of the captive
193 // portal interstitial should be displayed.
194 IN_PROC_BROWSER_TEST_F(CaptivePortalBlockingPageTest
,
195 WiFi_SSID_LoginURL
) {
196 TestInterstitial(true, kWiFiSSID
, GURL("http://captive.portal/landing_url"),
197 EXPECT_WIFI_YES
, EXPECT_WIFI_SSID_YES
, EXPECT_LOGIN_URL_YES
);
200 // Same as above, with login URL but no SSID.
201 IN_PROC_BROWSER_TEST_F(CaptivePortalBlockingPageTest
,
202 WiFi_NoSSID_LoginURL
) {
203 TestInterstitial(true, "", GURL("http://captive.portal/landing_url"),
204 EXPECT_WIFI_YES
, EXPECT_WIFI_SSID_NO
, EXPECT_LOGIN_URL_YES
);
207 // Same as above, with SSID but no login URL.
208 IN_PROC_BROWSER_TEST_F(CaptivePortalBlockingPageTest
,
209 WiFi_SSID_NoLoginURL
) {
210 const GURL
kLandingUrl(captive_portal::CaptivePortalDetector::kDefaultURL
);
211 TestInterstitial(true, kWiFiSSID
, kLandingUrl
,
212 EXPECT_WIFI_YES
, EXPECT_WIFI_SSID_YES
, EXPECT_LOGIN_URL_NO
);
215 // Same as above, with no SSID and no login URL.
216 IN_PROC_BROWSER_TEST_F(CaptivePortalBlockingPageTest
,
217 WiFi_NoSSID_NoLoginURL
) {
218 const GURL
kLandingUrl(captive_portal::CaptivePortalDetector::kDefaultURL
);
219 TestInterstitial(true, "", kLandingUrl
,
220 EXPECT_WIFI_YES
, EXPECT_WIFI_SSID_NO
, EXPECT_LOGIN_URL_NO
);
223 class CaptivePortalBlockingPageIDNTest
: public CaptivePortalBlockingPageTest
{
225 // InProcessBrowserTest:
226 void SetUpOnMainThread() override
{
227 // Clear AcceptLanguages to force punycode decoding.
228 browser()->profile()->GetPrefs()->SetString(prefs::kAcceptLanguages
,
233 // Same as CaptivePortalBlockingPageTest.WiredNetwork_LoginURL, except the login
235 IN_PROC_BROWSER_TEST_F(CaptivePortalBlockingPageIDNTest
,
236 ShowLoginIDNIfPortalRedirectsDetectionURL
) {
237 const char kHostname
[] =
238 "xn--d1abbgf6aiiy.xn--p1ai";
239 const char kHostnameJSUnicode
[] =
240 "\\u043f\\u0440\\u0435\\u0437\\u0438\\u0434\\u0435\\u043d\\u0442."
242 std::string landing_url_spec
=
243 base::StringPrintf("http://%s/landing_url", kHostname
);
244 GURL
landing_url(landing_url_spec
);
246 TestInterstitial(false, "", landing_url
, EXPECT_WIFI_NO
, EXPECT_WIFI_SSID_NO
,
247 EXPECT_LOGIN_URL_YES
, kHostnameJSUnicode
);