OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ssl/captive_portal_blocking_page.h" | 5 #include "chrome/browser/ssl/captive_portal_blocking_page.h" |
6 | 6 |
7 #include "base/i18n/rtl.h" | 7 #include "base/i18n/rtl.h" |
8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
9 #include "base/prefs/pref_service.h" | 9 #include "base/prefs/pref_service.h" |
10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
(...skipping 16 matching lines...) Expand all Loading... |
27 | 27 |
28 namespace { | 28 namespace { |
29 | 29 |
30 // Events for UMA. | 30 // Events for UMA. |
31 enum CaptivePortalBlockingPageEvent { | 31 enum CaptivePortalBlockingPageEvent { |
32 SHOW_ALL, | 32 SHOW_ALL, |
33 OPEN_LOGIN_PAGE, | 33 OPEN_LOGIN_PAGE, |
34 CAPTIVE_PORTAL_BLOCKING_PAGE_EVENT_COUNT | 34 CAPTIVE_PORTAL_BLOCKING_PAGE_EVENT_COUNT |
35 }; | 35 }; |
36 | 36 |
| 37 const char kOpenLoginPageCommand[] = "openLoginPage"; |
| 38 |
37 void RecordUMA(CaptivePortalBlockingPageEvent event) { | 39 void RecordUMA(CaptivePortalBlockingPageEvent event) { |
38 UMA_HISTOGRAM_ENUMERATION("interstitial.captive_portal", | 40 UMA_HISTOGRAM_ENUMERATION("interstitial.captive_portal", |
39 event, | 41 event, |
40 CAPTIVE_PORTAL_BLOCKING_PAGE_EVENT_COUNT); | 42 CAPTIVE_PORTAL_BLOCKING_PAGE_EVENT_COUNT); |
41 } | 43 } |
42 | 44 |
43 bool IsWifiConnection() { | 45 class ConnectionInfoDelegate : public CaptivePortalBlockingPage::Delegate { |
44 // |net::NetworkChangeNotifier::GetConnectionType| isn't accurate on Linux and | 46 public: |
45 // Windows. See https://crbug.com/160537 for details. | 47 ConnectionInfoDelegate() {} |
46 // TODO(meacer): Add heuristics to get a more accurate connection type on | 48 ~ConnectionInfoDelegate() override {} |
47 // these platforms. | |
48 return net::NetworkChangeNotifier::GetConnectionType() == | |
49 net::NetworkChangeNotifier::CONNECTION_WIFI; | |
50 } | |
51 | 49 |
52 std::string GetWiFiName() { | 50 bool IsWifiConnection() const override { |
53 std::string ssid; | 51 // |net::NetworkChangeNotifier::GetConnectionType| isn't accurate on Linux |
| 52 // and Windows. See https://crbug.com/160537 for details. |
| 53 // TODO(meacer): Add heuristics to get a more accurate connection type on |
| 54 // these platforms. |
| 55 return net::NetworkChangeNotifier::GetConnectionType() == |
| 56 net::NetworkChangeNotifier::CONNECTION_WIFI; |
| 57 } |
| 58 |
| 59 std::string GetWiFiSSID() const override { |
| 60 std::string ssid; |
54 #if defined(OS_WIN) || defined(OS_MACOSX) | 61 #if defined(OS_WIN) || defined(OS_MACOSX) |
55 scoped_ptr<wifi::WiFiService> wifi_service(wifi::WiFiService::Create()); | 62 scoped_ptr<wifi::WiFiService> wifi_service(wifi::WiFiService::Create()); |
56 wifi_service->Initialize(NULL); | 63 wifi_service->Initialize(NULL); |
57 std::string error; | 64 std::string error; |
58 wifi_service->GetConnectedNetworkSSID(&ssid, &error); | 65 wifi_service->GetConnectedNetworkSSID(&ssid, &error); |
59 if (!error.empty()) | 66 if (!error.empty()) |
60 return ""; | 67 return ""; |
61 #endif | 68 #endif |
62 // TODO(meacer): Handle non UTF8 SSIDs. | 69 // TODO(meacer): Handle non UTF8 SSIDs. |
63 if (!base::IsStringUTF8(ssid)) | 70 if (!base::IsStringUTF8(ssid)) |
64 return ""; | 71 return ""; |
65 return ssid; | 72 return ssid; |
66 } | 73 } |
67 | 74 }; |
68 const char kOpenLoginPageCommand[] = "openLoginPage"; | |
69 | 75 |
70 } // namespace | 76 } // namespace |
71 | 77 |
72 // static | 78 // static |
73 const void* CaptivePortalBlockingPage::kTypeForTesting = | 79 const void* CaptivePortalBlockingPage::kTypeForTesting = |
74 &CaptivePortalBlockingPage::kTypeForTesting; | 80 &CaptivePortalBlockingPage::kTypeForTesting; |
75 | 81 |
76 CaptivePortalBlockingPage::CaptivePortalBlockingPage( | 82 CaptivePortalBlockingPage::CaptivePortalBlockingPage( |
77 content::WebContents* web_contents, | 83 content::WebContents* web_contents, |
78 const GURL& request_url, | 84 const GURL& request_url, |
79 const GURL& login_url, | 85 const GURL& login_url, |
80 const base::Callback<void(bool)>& callback) | 86 const base::Callback<void(bool)>& callback) |
81 : SecurityInterstitialPage(web_contents, request_url), | 87 : SecurityInterstitialPage(web_contents, request_url), |
82 login_url_(login_url), | 88 login_url_(login_url), |
83 is_wifi_connection_(IsWifiConnection()), | 89 delegate_(new ConnectionInfoDelegate), |
84 callback_(callback) { | 90 callback_(callback) { |
85 DCHECK(login_url_.is_valid()); | 91 DCHECK(login_url_.is_valid()); |
86 RecordUMA(SHOW_ALL); | 92 RecordUMA(SHOW_ALL); |
87 } | 93 } |
88 | 94 |
89 CaptivePortalBlockingPage::~CaptivePortalBlockingPage() { | 95 CaptivePortalBlockingPage::~CaptivePortalBlockingPage() { |
90 // Need to explicity deny the certificate via the callback, otherwise memory | 96 // Need to explicity deny the certificate via the callback, otherwise memory |
91 // is leaked. | 97 // is leaked. |
92 if (!callback_.is_null()) { | 98 if (!callback_.is_null()) { |
93 callback_.Run(false); | 99 callback_.Run(false); |
94 callback_.Reset(); | 100 callback_.Reset(); |
95 } | 101 } |
96 } | 102 } |
97 | 103 |
98 const void* CaptivePortalBlockingPage::GetTypeForTesting() const { | 104 const void* CaptivePortalBlockingPage::GetTypeForTesting() const { |
99 return CaptivePortalBlockingPage::kTypeForTesting; | 105 return CaptivePortalBlockingPage::kTypeForTesting; |
100 } | 106 } |
101 | 107 |
102 bool CaptivePortalBlockingPage::ShouldCreateNewNavigation() const { | 108 bool CaptivePortalBlockingPage::ShouldCreateNewNavigation() const { |
103 return true; | 109 return true; |
104 } | 110 } |
105 | 111 |
106 void CaptivePortalBlockingPage::PopulateInterstitialStrings( | 112 void CaptivePortalBlockingPage::PopulateInterstitialStrings( |
107 base::DictionaryValue* load_time_data) { | 113 base::DictionaryValue* load_time_data) { |
108 load_time_data->SetString("iconClass", "icon-offline"); | 114 load_time_data->SetString("iconClass", "icon-offline"); |
109 load_time_data->SetString("type", "CAPTIVE_PORTAL"); | 115 load_time_data->SetString("type", "CAPTIVE_PORTAL"); |
110 load_time_data->SetBoolean("overridable", false); | 116 load_time_data->SetBoolean("overridable", false); |
111 | 117 |
| 118 // |IsWifiConnection| isn't accurate on some platforms, so always try to get |
| 119 // the Wi-Fi SSID even if |IsWifiConnection| is false. |
| 120 std::string wifi_ssid = delegate_.get()->GetWiFiSSID(); |
| 121 bool is_wifi_connection = !wifi_ssid.empty() || |
| 122 delegate_.get()->IsWifiConnection(); |
| 123 |
112 load_time_data->SetString( | 124 load_time_data->SetString( |
113 "primaryButtonText", | 125 "primaryButtonText", |
114 l10n_util::GetStringUTF16(IDS_CAPTIVE_PORTAL_BUTTON_OPEN_LOGIN_PAGE)); | 126 l10n_util::GetStringUTF16(IDS_CAPTIVE_PORTAL_BUTTON_OPEN_LOGIN_PAGE)); |
115 load_time_data->SetString("tabTitle", | 127 load_time_data->SetString( |
116 l10n_util::GetStringUTF16( | 128 "tabTitle", l10n_util::GetStringUTF16( |
117 is_wifi_connection_ ? | 129 is_wifi_connection ? IDS_CAPTIVE_PORTAL_HEADING_WIFI |
118 IDS_CAPTIVE_PORTAL_HEADING_WIFI : | 130 : IDS_CAPTIVE_PORTAL_HEADING_WIRED)); |
119 IDS_CAPTIVE_PORTAL_HEADING_WIRED)); | 131 load_time_data->SetString( |
120 load_time_data->SetString("heading", | 132 "heading", l10n_util::GetStringUTF16( |
121 l10n_util::GetStringUTF16( | 133 is_wifi_connection ? IDS_CAPTIVE_PORTAL_HEADING_WIFI |
122 is_wifi_connection_ ? | 134 : IDS_CAPTIVE_PORTAL_HEADING_WIRED)); |
123 IDS_CAPTIVE_PORTAL_HEADING_WIFI : | |
124 IDS_CAPTIVE_PORTAL_HEADING_WIRED)); | |
125 | 135 |
126 if (login_url_.spec() == captive_portal::CaptivePortalDetector::kDefaultURL) { | 136 if (login_url_.spec() == captive_portal::CaptivePortalDetector::kDefaultURL) { |
127 // Captive portal may intercept requests without HTTP redirects, in which | 137 // Captive portal may intercept requests without HTTP redirects, in which |
128 // case the login url would be the same as the captive portal detection url. | 138 // case the login url would be the same as the captive portal detection url. |
129 // Don't show the login url in that case. | 139 // Don't show the login url in that case. |
130 if (is_wifi_connection_) { | 140 if (wifi_ssid.empty()) { |
131 if (wifi_ssid_.empty()) | |
132 wifi_ssid_ = GetWiFiName(); | |
133 if (wifi_ssid_.empty()) { | |
134 load_time_data->SetString( | |
135 "primaryParagraph", | |
136 l10n_util::GetStringUTF16( | |
137 IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH_NO_LOGIN_URL_WIFI)); | |
138 } else { | |
139 load_time_data->SetString( | |
140 "primaryParagraph", | |
141 l10n_util::GetStringFUTF16( | |
142 IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH_NO_LOGIN_URL_WIFI_SSID, | |
143 net::EscapeForHTML(base::UTF8ToUTF16(wifi_ssid_)))); | |
144 } | |
145 } else { | |
146 // Non-WiFi connection: | |
147 load_time_data->SetString( | 141 load_time_data->SetString( |
148 "primaryParagraph", | 142 "primaryParagraph", |
149 l10n_util::GetStringUTF16( | 143 l10n_util::GetStringUTF16( |
150 IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH_NO_LOGIN_URL_WIRED)); | 144 is_wifi_connection |
| 145 ? IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH_NO_LOGIN_URL_WIFI |
| 146 : IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH_NO_LOGIN_URL_WIRED)); |
| 147 } else { |
| 148 load_time_data->SetString( |
| 149 "primaryParagraph", |
| 150 l10n_util::GetStringFUTF16( |
| 151 IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH_NO_LOGIN_URL_WIFI_SSID, |
| 152 net::EscapeForHTML(base::UTF8ToUTF16(wifi_ssid)))); |
151 } | 153 } |
152 } else { | 154 } else { |
153 // Portal redirection was done with HTTP redirects, show the login URL. | 155 // Portal redirection was done with HTTP redirects, so show the login URL. |
| 156 // If |languages| is empty, punycode in |login_host| will always be decoded. |
154 std::string languages; | 157 std::string languages; |
155 Profile* profile = Profile::FromBrowserContext( | 158 Profile* profile = Profile::FromBrowserContext( |
156 web_contents()->GetBrowserContext()); | 159 web_contents()->GetBrowserContext()); |
157 if (profile) | 160 if (profile) |
158 languages = profile->GetPrefs()->GetString(prefs::kAcceptLanguages); | 161 languages = profile->GetPrefs()->GetString(prefs::kAcceptLanguages); |
159 | |
160 base::string16 login_host = net::IDNToUnicode(login_url_.host(), languages); | 162 base::string16 login_host = net::IDNToUnicode(login_url_.host(), languages); |
161 if (base::i18n::IsRTL()) | 163 if (base::i18n::IsRTL()) |
162 base::i18n::WrapStringWithLTRFormatting(&login_host); | 164 base::i18n::WrapStringWithLTRFormatting(&login_host); |
163 | 165 |
164 if (is_wifi_connection_) { | 166 if (wifi_ssid.empty()) { |
165 if (wifi_ssid_.empty()) | |
166 wifi_ssid_ = GetWiFiName(); | |
167 if (wifi_ssid_.empty()) { | |
168 load_time_data->SetString( | |
169 "primaryParagraph", | |
170 l10n_util::GetStringFUTF16( | |
171 IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH_WIFI, | |
172 login_host)); | |
173 } else { | |
174 load_time_data->SetString( | |
175 "primaryParagraph", | |
176 l10n_util::GetStringFUTF16( | |
177 IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH_WIFI_SSID, | |
178 net::EscapeForHTML(base::UTF8ToUTF16(wifi_ssid_)), | |
179 login_host)); | |
180 } | |
181 } else { | |
182 // Non-WiFi connection: | |
183 load_time_data->SetString( | 167 load_time_data->SetString( |
184 "primaryParagraph", | 168 "primaryParagraph", |
185 l10n_util::GetStringFUTF16(IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH_WIRED, | 169 l10n_util::GetStringFUTF16( |
186 login_host)); | 170 is_wifi_connection ? IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH_WIFI |
| 171 : IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH_WIRED, |
| 172 login_host)); |
| 173 } else { |
| 174 load_time_data->SetString( |
| 175 "primaryParagraph", |
| 176 l10n_util::GetStringFUTF16( |
| 177 IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH_WIFI_SSID, |
| 178 net::EscapeForHTML(base::UTF8ToUTF16(wifi_ssid)), login_host)); |
187 } | 179 } |
188 } | 180 } |
189 | 181 |
190 // Fill the empty strings to avoid getting debug warnings. | 182 // Fill the empty strings to avoid getting debug warnings. |
191 load_time_data->SetString("openDetails", base::string16()); | 183 load_time_data->SetString("openDetails", base::string16()); |
192 load_time_data->SetString("closeDetails", base::string16()); | 184 load_time_data->SetString("closeDetails", base::string16()); |
193 load_time_data->SetString("explanationParagraph", base::string16()); | 185 load_time_data->SetString("explanationParagraph", base::string16()); |
194 load_time_data->SetString("finalParagraph", base::string16()); | 186 load_time_data->SetString("finalParagraph", base::string16()); |
195 } | 187 } |
196 | 188 |
197 void CaptivePortalBlockingPage::CommandReceived(const std::string& command) { | 189 void CaptivePortalBlockingPage::CommandReceived(const std::string& command) { |
198 // The response has quotes around it. | 190 // The response has quotes around it. |
199 if (command == std::string("\"") + kOpenLoginPageCommand + "\"") { | 191 if (command == std::string("\"") + kOpenLoginPageCommand + "\"") { |
200 RecordUMA(OPEN_LOGIN_PAGE); | 192 RecordUMA(OPEN_LOGIN_PAGE); |
201 CaptivePortalTabHelper::OpenLoginTabForWebContents(web_contents(), true); | 193 CaptivePortalTabHelper::OpenLoginTabForWebContents(web_contents(), true); |
202 } | 194 } |
203 } | 195 } |
OLD | NEW |