Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / ssl / ssl_blocking_page.cc
blob572ae9454c57d0064f8dde0173c1b3b76efd15ea
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.
5 #include "chrome/browser/ssl/ssl_blocking_page.h"
7 #include "base/i18n/rtl.h"
8 #include "base/metrics/histogram.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_piece.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h"
14 #include "chrome/browser/history/history_service_factory.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/renderer_preferences_util.h"
17 #include "chrome/browser/ssl/ssl_error_info.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/browser_finder.h"
20 #include "content/public/browser/cert_store.h"
21 #include "content/public/browser/interstitial_page.h"
22 #include "content/public/browser/navigation_controller.h"
23 #include "content/public/browser/navigation_entry.h"
24 #include "content/public/browser/notification_service.h"
25 #include "content/public/browser/notification_types.h"
26 #include "content/public/browser/render_process_host.h"
27 #include "content/public/browser/render_view_host.h"
28 #include "content/public/browser/web_contents.h"
29 #include "content/public/common/ssl_status.h"
30 #include "grit/app_locale_settings.h"
31 #include "grit/browser_resources.h"
32 #include "grit/generated_resources.h"
33 #include "net/base/hash_value.h"
34 #include "net/base/net_errors.h"
35 #include "net/base/net_util.h"
36 #include "ui/base/l10n/l10n_util.h"
37 #include "ui/base/resource/resource_bundle.h"
38 #include "ui/base/webui/jstemplate_builder.h"
40 #if defined(OS_WIN)
41 #include "base/win/windows_version.h"
42 #endif
44 using base::ASCIIToUTF16;
45 using base::TimeTicks;
46 using content::InterstitialPage;
47 using content::NavigationController;
48 using content::NavigationEntry;
50 namespace {
52 // These represent the commands sent by ssl_roadblock.html.
53 enum SSLBlockingPageCommands {
54 CMD_DONT_PROCEED,
55 CMD_PROCEED,
56 CMD_MORE,
57 CMD_RELOAD,
60 // Events for UMA.
61 enum SSLBlockingPageEvent {
62 SHOW_ALL,
63 SHOW_OVERRIDABLE,
64 PROCEED_OVERRIDABLE,
65 PROCEED_NAME,
66 PROCEED_DATE,
67 PROCEED_AUTHORITY,
68 DONT_PROCEED_OVERRIDABLE,
69 DONT_PROCEED_NAME,
70 DONT_PROCEED_DATE,
71 DONT_PROCEED_AUTHORITY,
72 MORE,
73 SHOW_UNDERSTAND, // Used by the summer 2013 Finch trial. Deprecated.
74 SHOW_INTERNAL_HOSTNAME,
75 PROCEED_INTERNAL_HOSTNAME,
76 SHOW_NEW_SITE,
77 PROCEED_NEW_SITE,
78 UNUSED_BLOCKING_PAGE_EVENT,
81 void RecordSSLBlockingPageEventStats(SSLBlockingPageEvent event) {
82 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl",
83 event,
84 UNUSED_BLOCKING_PAGE_EVENT);
87 void RecordSSLBlockingPageDetailedStats(
88 bool proceed,
89 int cert_error,
90 bool overridable,
91 bool internal,
92 int num_visits) {
93 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl_error_type",
94 SSLErrorInfo::NetErrorToErrorType(cert_error), SSLErrorInfo::END_OF_ENUM);
95 if (!overridable) {
96 // Overridable is false if the user didn't have any option except to turn
97 // back. If that's the case, don't record some of the metrics.
98 return;
100 if (num_visits == 0)
101 RecordSSLBlockingPageEventStats(SHOW_NEW_SITE);
102 if (proceed) {
103 RecordSSLBlockingPageEventStats(PROCEED_OVERRIDABLE);
104 if (internal)
105 RecordSSLBlockingPageEventStats(PROCEED_INTERNAL_HOSTNAME);
106 if (num_visits == 0)
107 RecordSSLBlockingPageEventStats(PROCEED_NEW_SITE);
108 } else if (!proceed) {
109 RecordSSLBlockingPageEventStats(DONT_PROCEED_OVERRIDABLE);
111 SSLErrorInfo::ErrorType type = SSLErrorInfo::NetErrorToErrorType(cert_error);
112 switch (type) {
113 case SSLErrorInfo::CERT_COMMON_NAME_INVALID: {
114 if (proceed)
115 RecordSSLBlockingPageEventStats(PROCEED_NAME);
116 else
117 RecordSSLBlockingPageEventStats(DONT_PROCEED_NAME);
118 break;
120 case SSLErrorInfo::CERT_DATE_INVALID: {
121 if (proceed)
122 RecordSSLBlockingPageEventStats(PROCEED_DATE);
123 else
124 RecordSSLBlockingPageEventStats(DONT_PROCEED_DATE);
125 break;
127 case SSLErrorInfo::CERT_AUTHORITY_INVALID: {
128 if (proceed)
129 RecordSSLBlockingPageEventStats(PROCEED_AUTHORITY);
130 else
131 RecordSSLBlockingPageEventStats(DONT_PROCEED_AUTHORITY);
132 break;
134 default: {
135 break;
140 } // namespace
142 // Note that we always create a navigation entry with SSL errors.
143 // No error happening loading a sub-resource triggers an interstitial so far.
144 SSLBlockingPage::SSLBlockingPage(
145 content::WebContents* web_contents,
146 int cert_error,
147 const net::SSLInfo& ssl_info,
148 const GURL& request_url,
149 bool overridable,
150 bool strict_enforcement,
151 const base::Callback<void(bool)>& callback)
152 : callback_(callback),
153 web_contents_(web_contents),
154 cert_error_(cert_error),
155 ssl_info_(ssl_info),
156 request_url_(request_url),
157 overridable_(overridable),
158 strict_enforcement_(strict_enforcement),
159 internal_(false),
160 num_visits_(-1) {
161 // For UMA stats.
162 if (net::IsHostnameNonUnique(request_url_.HostNoBrackets()))
163 internal_ = true;
164 RecordSSLBlockingPageEventStats(SHOW_ALL);
165 if (overridable_ && !strict_enforcement_) {
166 RecordSSLBlockingPageEventStats(SHOW_OVERRIDABLE);
167 if (internal_)
168 RecordSSLBlockingPageEventStats(SHOW_INTERNAL_HOSTNAME);
169 HistoryService* history_service = HistoryServiceFactory::GetForProfile(
170 Profile::FromBrowserContext(web_contents->GetBrowserContext()),
171 Profile::EXPLICIT_ACCESS);
172 if (history_service) {
173 history_service->GetVisibleVisitCountToHost(
174 request_url_,
175 &request_consumer_,
176 base::Bind(&SSLBlockingPage::OnGotHistoryCount,
177 base::Unretained(this)));
181 interstitial_page_ = InterstitialPage::Create(
182 web_contents_, true, request_url, this);
183 interstitial_page_->Show();
186 SSLBlockingPage::~SSLBlockingPage() {
187 if (!callback_.is_null()) {
188 RecordSSLBlockingPageDetailedStats(false,
189 cert_error_,
190 overridable_ && !strict_enforcement_,
191 internal_,
192 num_visits_);
193 // The page is closed without the user having chosen what to do, default to
194 // deny.
195 NotifyDenyCertificate();
199 std::string SSLBlockingPage::GetHTMLContents() {
200 base::DictionaryValue strings;
201 int resource_id;
202 if (overridable_ && !strict_enforcement_) {
203 // Let's build the overridable error page.
204 SSLErrorInfo error_info =
205 SSLErrorInfo::CreateError(
206 SSLErrorInfo::NetErrorToErrorType(cert_error_),
207 ssl_info_.cert.get(),
208 request_url_);
210 resource_id = IDR_SSL_ROAD_BLOCK_HTML;
211 strings.SetString("headLine", error_info.title());
212 strings.SetString("description", error_info.details());
213 strings.SetString("moreInfoTitle",
214 l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXTRA_INFO_TITLE));
215 SetExtraInfo(&strings, error_info.extra_information());
217 strings.SetString(
218 "exit", l10n_util::GetStringUTF16(IDS_SSL_OVERRIDABLE_PAGE_EXIT));
219 strings.SetString(
220 "title", l10n_util::GetStringUTF16(IDS_SSL_OVERRIDABLE_PAGE_TITLE));
221 strings.SetString(
222 "proceed", l10n_util::GetStringUTF16(IDS_SSL_OVERRIDABLE_PAGE_PROCEED));
223 strings.SetString(
224 "reasonForNotProceeding", l10n_util::GetStringUTF16(
225 IDS_SSL_OVERRIDABLE_PAGE_SHOULD_NOT_PROCEED));
226 strings.SetString("errorType", "overridable");
227 strings.SetString("textdirection", base::i18n::IsRTL() ? "rtl" : "ltr");
228 } else {
229 // Let's build the blocking error page.
230 resource_id = IDR_SSL_BLOCKING_HTML;
232 // Strings that are not dependent on the URL.
233 strings.SetString(
234 "title", l10n_util::GetStringUTF16(IDS_SSL_BLOCKING_PAGE_TITLE));
235 strings.SetString(
236 "reloadMsg", l10n_util::GetStringUTF16(IDS_ERRORPAGES_BUTTON_RELOAD));
237 strings.SetString(
238 "more", l10n_util::GetStringUTF16(IDS_ERRORPAGES_BUTTON_MORE));
239 strings.SetString(
240 "less", l10n_util::GetStringUTF16(IDS_ERRORPAGES_BUTTON_LESS));
241 strings.SetString(
242 "moreTitle",
243 l10n_util::GetStringUTF16(IDS_SSL_BLOCKING_PAGE_MORE_TITLE));
244 strings.SetString(
245 "techTitle",
246 l10n_util::GetStringUTF16(IDS_SSL_BLOCKING_PAGE_TECH_TITLE));
248 // Strings that are dependent on the URL.
249 base::string16 url(ASCIIToUTF16(request_url_.host()));
250 bool rtl = base::i18n::IsRTL();
251 strings.SetString("textDirection", rtl ? "rtl" : "ltr");
252 if (rtl)
253 base::i18n::WrapStringWithLTRFormatting(&url);
254 strings.SetString(
255 "headline", l10n_util::GetStringFUTF16(IDS_SSL_BLOCKING_PAGE_HEADLINE,
256 url.c_str()));
257 strings.SetString(
258 "message", l10n_util::GetStringFUTF16(IDS_SSL_BLOCKING_PAGE_BODY_TEXT,
259 url.c_str()));
260 strings.SetString(
261 "moreMessage",
262 l10n_util::GetStringFUTF16(IDS_SSL_BLOCKING_PAGE_MORE_TEXT,
263 url.c_str()));
264 strings.SetString("reloadUrl", request_url_.spec());
266 // Strings that are dependent on the error type.
267 SSLErrorInfo::ErrorType type =
268 SSLErrorInfo::NetErrorToErrorType(cert_error_);
269 base::string16 errorType;
270 if (type == SSLErrorInfo::CERT_REVOKED) {
271 errorType = base::string16(ASCIIToUTF16("Key revocation"));
272 strings.SetString(
273 "failure",
274 l10n_util::GetStringUTF16(IDS_SSL_BLOCKING_PAGE_REVOKED));
275 } else if (type == SSLErrorInfo::CERT_INVALID) {
276 errorType = base::string16(ASCIIToUTF16("Malformed certificate"));
277 strings.SetString(
278 "failure",
279 l10n_util::GetStringUTF16(IDS_SSL_BLOCKING_PAGE_FORMATTED));
280 } else if (type == SSLErrorInfo::CERT_PINNED_KEY_MISSING) {
281 errorType = base::string16(ASCIIToUTF16("Certificate pinning failure"));
282 strings.SetString(
283 "failure",
284 l10n_util::GetStringFUTF16(IDS_SSL_BLOCKING_PAGE_PINNING,
285 url.c_str()));
286 } else if (type == SSLErrorInfo::CERT_WEAK_KEY_DH) {
287 errorType = base::string16(ASCIIToUTF16("Weak DH public key"));
288 strings.SetString(
289 "failure",
290 l10n_util::GetStringFUTF16(IDS_SSL_BLOCKING_PAGE_WEAK_DH,
291 url.c_str()));
292 } else {
293 // HSTS failure.
294 errorType = base::string16(ASCIIToUTF16("HSTS failure"));
295 strings.SetString(
296 "failure",
297 l10n_util::GetStringFUTF16(IDS_SSL_BLOCKING_PAGE_HSTS, url.c_str()));
299 if (rtl)
300 base::i18n::WrapStringWithLTRFormatting(&errorType);
301 strings.SetString(
302 "errorType", l10n_util::GetStringFUTF16(IDS_SSL_BLOCKING_PAGE_ERROR,
303 errorType.c_str()));
305 // Strings that display the invalid cert.
306 base::string16 subject(
307 ASCIIToUTF16(ssl_info_.cert->subject().GetDisplayName()));
308 base::string16 issuer(
309 ASCIIToUTF16(ssl_info_.cert->issuer().GetDisplayName()));
310 std::string hashes;
311 for (std::vector<net::HashValue>::iterator it =
312 ssl_info_.public_key_hashes.begin();
313 it != ssl_info_.public_key_hashes.end();
314 ++it) {
315 base::StringAppendF(&hashes, "%s ", it->ToString().c_str());
317 base::string16 fingerprint(ASCIIToUTF16(hashes));
318 if (rtl) {
319 // These are always going to be LTR.
320 base::i18n::WrapStringWithLTRFormatting(&subject);
321 base::i18n::WrapStringWithLTRFormatting(&issuer);
322 base::i18n::WrapStringWithLTRFormatting(&fingerprint);
324 strings.SetString(
325 "subject", l10n_util::GetStringFUTF16(IDS_SSL_BLOCKING_PAGE_SUBJECT,
326 subject.c_str()));
327 strings.SetString(
328 "issuer", l10n_util::GetStringFUTF16(IDS_SSL_BLOCKING_PAGE_ISSUER,
329 issuer.c_str()));
330 strings.SetString(
331 "fingerprint",
332 l10n_util::GetStringFUTF16(IDS_SSL_BLOCKING_PAGE_HASHES,
333 fingerprint.c_str()));
336 base::StringPiece html(
337 ResourceBundle::GetSharedInstance().GetRawDataResource(
338 resource_id));
339 return webui::GetI18nTemplateHtml(html, &strings);
342 void SSLBlockingPage::OverrideEntry(NavigationEntry* entry) {
343 int cert_id = content::CertStore::GetInstance()->StoreCert(
344 ssl_info_.cert.get(), web_contents_->GetRenderProcessHost()->GetID());
346 entry->GetSSL().security_style =
347 content::SECURITY_STYLE_AUTHENTICATION_BROKEN;
348 entry->GetSSL().cert_id = cert_id;
349 entry->GetSSL().cert_status = ssl_info_.cert_status;
350 entry->GetSSL().security_bits = ssl_info_.security_bits;
351 #if !defined(OS_ANDROID)
352 Browser* browser = chrome::FindBrowserWithWebContents(web_contents_);
353 if (browser)
354 browser->VisibleSSLStateChanged(web_contents_);
355 #endif // !defined(OS_ANDROID)
358 // Matches events defined in ssl_error.html and ssl_roadblock.html.
359 void SSLBlockingPage::CommandReceived(const std::string& command) {
360 int cmd = atoi(command.c_str());
361 if (cmd == CMD_DONT_PROCEED) {
362 interstitial_page_->DontProceed();
363 } else if (cmd == CMD_PROCEED) {
364 interstitial_page_->Proceed();
365 } else if (cmd == CMD_MORE) {
366 RecordSSLBlockingPageEventStats(MORE);
367 } else if (cmd == CMD_RELOAD) {
368 // The interstitial can't refresh itself.
369 content::NavigationController* controller = &web_contents_->GetController();
370 controller->Reload(true);
374 void SSLBlockingPage::OverrideRendererPrefs(
375 content::RendererPreferences* prefs) {
376 Profile* profile = Profile::FromBrowserContext(
377 web_contents_->GetBrowserContext());
378 renderer_preferences_util::UpdateFromSystemSettings(prefs, profile);
381 void SSLBlockingPage::OnProceed() {
382 RecordSSLBlockingPageDetailedStats(true,
383 cert_error_,
384 overridable_ && !strict_enforcement_,
385 internal_,
386 num_visits_);
387 // Accepting the certificate resumes the loading of the page.
388 NotifyAllowCertificate();
391 void SSLBlockingPage::OnDontProceed() {
392 RecordSSLBlockingPageDetailedStats(false,
393 cert_error_,
394 overridable_ && !strict_enforcement_,
395 internal_,
396 num_visits_);
397 NotifyDenyCertificate();
400 void SSLBlockingPage::NotifyDenyCertificate() {
401 // It's possible that callback_ may not exist if the user clicks "Proceed"
402 // followed by pressing the back button before the interstitial is hidden.
403 // In that case the certificate will still be treated as allowed.
404 if (callback_.is_null())
405 return;
407 callback_.Run(false);
408 callback_.Reset();
411 void SSLBlockingPage::NotifyAllowCertificate() {
412 DCHECK(!callback_.is_null());
414 callback_.Run(true);
415 callback_.Reset();
418 // static
419 void SSLBlockingPage::SetExtraInfo(
420 base::DictionaryValue* strings,
421 const std::vector<base::string16>& extra_info) {
422 DCHECK_LT(extra_info.size(), 5U); // We allow 5 paragraphs max.
423 const char* keys[5] = {
424 "moreInfo1", "moreInfo2", "moreInfo3", "moreInfo4", "moreInfo5"
426 int i;
427 for (i = 0; i < static_cast<int>(extra_info.size()); i++) {
428 strings->SetString(keys[i], extra_info[i]);
430 for (; i < 5; i++) {
431 strings->SetString(keys[i], std::string());
435 void SSLBlockingPage::OnGotHistoryCount(HistoryService::Handle handle,
436 bool success,
437 int num_visits,
438 base::Time first_visit) {
439 num_visits_ = num_visits;