OLD | NEW |
| (Empty) |
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/ui/page_info/website_settings.h" | |
6 | |
7 #include <stddef.h> | |
8 #include <stdint.h> | |
9 | |
10 #include <string> | |
11 #include <vector> | |
12 | |
13 #include "base/command_line.h" | |
14 #include "base/i18n/time_formatting.h" | |
15 #include "base/macros.h" | |
16 #include "base/memory/ptr_util.h" | |
17 #include "base/metrics/field_trial.h" | |
18 #include "base/metrics/histogram_macros.h" | |
19 #include "base/strings/string_number_conversions.h" | |
20 #include "base/strings/utf_string_conversions.h" | |
21 #include "base/values.h" | |
22 #include "build/build_config.h" | |
23 #include "chrome/browser/browser_process.h" | |
24 #include "chrome/browser/browsing_data/browsing_data_channel_id_helper.h" | |
25 #include "chrome/browser/browsing_data/browsing_data_cookie_helper.h" | |
26 #include "chrome/browser/browsing_data/browsing_data_database_helper.h" | |
27 #include "chrome/browser/browsing_data/browsing_data_file_system_helper.h" | |
28 #include "chrome/browser/browsing_data/browsing_data_indexed_db_helper.h" | |
29 #include "chrome/browser/browsing_data/browsing_data_local_storage_helper.h" | |
30 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" | |
31 #include "chrome/browser/content_settings/local_shared_objects_container.h" | |
32 #include "chrome/browser/history/history_service_factory.h" | |
33 #include "chrome/browser/infobars/infobar_service.h" | |
34 #include "chrome/browser/permissions/chooser_context_base.h" | |
35 #include "chrome/browser/permissions/permission_manager.h" | |
36 #include "chrome/browser/permissions/permission_result.h" | |
37 #include "chrome/browser/permissions/permission_uma_util.h" | |
38 #include "chrome/browser/permissions/permission_util.h" | |
39 #include "chrome/browser/profiles/profile.h" | |
40 #include "chrome/browser/ssl/chrome_ssl_host_state_delegate.h" | |
41 #include "chrome/browser/ssl/chrome_ssl_host_state_delegate_factory.h" | |
42 #include "chrome/browser/ui/page_info/website_settings_ui.h" | |
43 #include "chrome/browser/usb/usb_chooser_context.h" | |
44 #include "chrome/browser/usb/usb_chooser_context_factory.h" | |
45 #include "chrome/common/chrome_switches.h" | |
46 #include "chrome/common/url_constants.h" | |
47 #include "chrome/grit/chromium_strings.h" | |
48 #include "chrome/grit/generated_resources.h" | |
49 #include "chrome/grit/theme_resources.h" | |
50 #include "components/content_settings/core/browser/content_settings_utils.h" | |
51 #include "components/content_settings/core/browser/host_content_settings_map.h" | |
52 #include "components/content_settings/core/common/content_settings.h" | |
53 #include "components/content_settings/core/common/content_settings_pattern.h" | |
54 #include "components/rappor/public/rappor_utils.h" | |
55 #include "components/rappor/rappor_service_impl.h" | |
56 #include "components/ssl_errors/error_info.h" | |
57 #include "components/strings/grit/components_chromium_strings.h" | |
58 #include "components/strings/grit/components_strings.h" | |
59 #include "components/url_formatter/elide_url.h" | |
60 #include "content/public/browser/browser_thread.h" | |
61 #include "content/public/browser/user_metrics.h" | |
62 #include "content/public/common/content_switches.h" | |
63 #include "content/public/common/url_constants.h" | |
64 #include "net/cert/cert_status_flags.h" | |
65 #include "net/cert/x509_certificate.h" | |
66 #include "net/ssl/ssl_cipher_suite_names.h" | |
67 #include "net/ssl/ssl_connection_status_flags.h" | |
68 #include "third_party/boringssl/src/include/openssl/ssl.h" | |
69 #include "ui/base/l10n/l10n_util.h" | |
70 | |
71 #if defined(OS_CHROMEOS) | |
72 #include "chrome/browser/chromeos/policy/policy_cert_service.h" | |
73 #include "chrome/browser/chromeos/policy/policy_cert_service_factory.h" | |
74 #endif | |
75 | |
76 #if !defined(OS_ANDROID) | |
77 #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" | |
78 #include "chrome/browser/ui/page_info/website_settings_infobar_delegate.h" | |
79 #endif | |
80 | |
81 using base::ASCIIToUTF16; | |
82 using base::UTF8ToUTF16; | |
83 using base::UTF16ToUTF8; | |
84 using content::BrowserThread; | |
85 | |
86 namespace { | |
87 | |
88 // Events for UMA. Do not reorder or change! | |
89 enum SSLCertificateDecisionsDidRevoke { | |
90 USER_CERT_DECISIONS_NOT_REVOKED = 0, | |
91 USER_CERT_DECISIONS_REVOKED, | |
92 END_OF_SSL_CERTIFICATE_DECISIONS_DID_REVOKE_ENUM | |
93 }; | |
94 | |
95 // The list of content settings types to display on the Website Settings UI. THE | |
96 // ORDER OF THESE ITEMS IS IMPORTANT. To propose changing it, email | |
97 // security-dev@chromium.org. | |
98 ContentSettingsType kPermissionType[] = { | |
99 CONTENT_SETTINGS_TYPE_GEOLOCATION, | |
100 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, | |
101 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, | |
102 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, | |
103 CONTENT_SETTINGS_TYPE_JAVASCRIPT, | |
104 #if !defined(OS_ANDROID) | |
105 CONTENT_SETTINGS_TYPE_PLUGINS, | |
106 CONTENT_SETTINGS_TYPE_IMAGES, | |
107 #endif | |
108 CONTENT_SETTINGS_TYPE_POPUPS, | |
109 CONTENT_SETTINGS_TYPE_BACKGROUND_SYNC, | |
110 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, | |
111 CONTENT_SETTINGS_TYPE_AUTOPLAY, | |
112 CONTENT_SETTINGS_TYPE_MIDI_SYSEX, | |
113 }; | |
114 | |
115 // Determines whether to show permission |type| in the Website Settings UI. Only | |
116 // applies to permissions listed in |kPermissionType|. | |
117 bool ShouldShowPermission(ContentSettingsType type) { | |
118 #if !defined(OS_ANDROID) | |
119 // Autoplay is Android-only at the moment. | |
120 if (type == CONTENT_SETTINGS_TYPE_AUTOPLAY) | |
121 return false; | |
122 #endif | |
123 | |
124 return true; | |
125 } | |
126 | |
127 void CheckContentStatus(security_state::ContentStatus content_status, | |
128 bool* displayed, | |
129 bool* ran) { | |
130 switch (content_status) { | |
131 case security_state::CONTENT_STATUS_DISPLAYED: | |
132 *displayed = true; | |
133 break; | |
134 case security_state::CONTENT_STATUS_RAN: | |
135 *ran = true; | |
136 break; | |
137 case security_state::CONTENT_STATUS_DISPLAYED_AND_RAN: | |
138 *displayed = true; | |
139 *ran = true; | |
140 break; | |
141 case security_state::CONTENT_STATUS_UNKNOWN: | |
142 case security_state::CONTENT_STATUS_NONE: | |
143 break; | |
144 } | |
145 } | |
146 | |
147 void CheckForInsecureContent(const security_state::SecurityInfo& security_info, | |
148 bool* displayed, | |
149 bool* ran) { | |
150 CheckContentStatus(security_info.mixed_content_status, displayed, ran); | |
151 // Only consider subresources with certificate errors if the main | |
152 // resource was loaded over HTTPS without major certificate errors. If | |
153 // the main resource had a certificate error, then it would not be | |
154 // that useful (and would potentially be confusing) to warn about | |
155 // subesources that had certificate errors too. | |
156 if (net::IsCertStatusError(security_info.cert_status) && | |
157 !net::IsCertStatusMinorError(security_info.cert_status)) { | |
158 return; | |
159 } | |
160 CheckContentStatus(security_info.content_with_cert_errors_status, displayed, | |
161 ran); | |
162 } | |
163 | |
164 void GetSiteIdentityByMaliciousContentStatus( | |
165 security_state::MaliciousContentStatus malicious_content_status, | |
166 WebsiteSettings::SiteIdentityStatus* status, | |
167 base::string16* details) { | |
168 switch (malicious_content_status) { | |
169 case security_state::MALICIOUS_CONTENT_STATUS_NONE: | |
170 NOTREACHED(); | |
171 break; | |
172 case security_state::MALICIOUS_CONTENT_STATUS_MALWARE: | |
173 *status = WebsiteSettings::SITE_IDENTITY_STATUS_MALWARE; | |
174 *details = l10n_util::GetStringUTF16(IDS_PAGEINFO_MALWARE_DETAILS); | |
175 break; | |
176 case security_state::MALICIOUS_CONTENT_STATUS_SOCIAL_ENGINEERING: | |
177 *status = WebsiteSettings::SITE_IDENTITY_STATUS_SOCIAL_ENGINEERING; | |
178 *details = | |
179 l10n_util::GetStringUTF16(IDS_PAGEINFO_SOCIAL_ENGINEERING_DETAILS); | |
180 break; | |
181 case security_state::MALICIOUS_CONTENT_STATUS_UNWANTED_SOFTWARE: | |
182 *status = WebsiteSettings::SITE_IDENTITY_STATUS_UNWANTED_SOFTWARE; | |
183 *details = | |
184 l10n_util::GetStringUTF16(IDS_PAGEINFO_UNWANTED_SOFTWARE_DETAILS); | |
185 break; | |
186 } | |
187 } | |
188 | |
189 base::string16 GetSimpleSiteName(const GURL& url) { | |
190 return url_formatter::FormatUrlForSecurityDisplay( | |
191 url, url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS); | |
192 } | |
193 | |
194 ChooserContextBase* GetUsbChooserContext(Profile* profile) { | |
195 return UsbChooserContextFactory::GetForProfile(profile); | |
196 } | |
197 | |
198 // The list of chooser types that need to display entries in the Website | |
199 // Settings UI. THE ORDER OF THESE ITEMS IS IMPORTANT. To propose changing it, | |
200 // email security-dev@chromium.org. | |
201 WebsiteSettings::ChooserUIInfo kChooserUIInfo[] = { | |
202 {CONTENT_SETTINGS_TYPE_USB_CHOOSER_DATA, &GetUsbChooserContext, | |
203 IDR_BLOCKED_USB, IDR_ALLOWED_USB, IDS_WEBSITE_SETTINGS_USB_DEVICE_LABEL, | |
204 IDS_WEBSITE_SETTINGS_DELETE_USB_DEVICE, "name"}, | |
205 }; | |
206 | |
207 } // namespace | |
208 | |
209 WebsiteSettings::WebsiteSettings( | |
210 WebsiteSettingsUI* ui, | |
211 Profile* profile, | |
212 TabSpecificContentSettings* tab_specific_content_settings, | |
213 content::WebContents* web_contents, | |
214 const GURL& url, | |
215 const security_state::SecurityInfo& security_info) | |
216 : TabSpecificContentSettings::SiteDataObserver( | |
217 tab_specific_content_settings), | |
218 content::WebContentsObserver(web_contents), | |
219 ui_(ui), | |
220 show_info_bar_(false), | |
221 site_url_(url), | |
222 site_identity_status_(SITE_IDENTITY_STATUS_UNKNOWN), | |
223 site_connection_status_(SITE_CONNECTION_STATUS_UNKNOWN), | |
224 show_ssl_decision_revoke_button_(false), | |
225 content_settings_(HostContentSettingsMapFactory::GetForProfile(profile)), | |
226 chrome_ssl_host_state_delegate_( | |
227 ChromeSSLHostStateDelegateFactory::GetForProfile(profile)), | |
228 did_revoke_user_ssl_decisions_(false), | |
229 profile_(profile), | |
230 security_level_(security_state::NONE) { | |
231 Init(url, security_info); | |
232 | |
233 PresentSitePermissions(); | |
234 PresentSiteData(); | |
235 PresentSiteIdentity(); | |
236 | |
237 // Every time the Website Settings UI is opened a |WebsiteSettings| object is | |
238 // created. So this counts how ofter the Website Settings UI is opened. | |
239 RecordWebsiteSettingsAction(WEBSITE_SETTINGS_OPENED); | |
240 } | |
241 | |
242 WebsiteSettings::~WebsiteSettings() {} | |
243 | |
244 void WebsiteSettings::RecordWebsiteSettingsAction( | |
245 WebsiteSettingsAction action) { | |
246 UMA_HISTOGRAM_ENUMERATION("WebsiteSettings.Action", action, | |
247 WEBSITE_SETTINGS_COUNT); | |
248 | |
249 std::string histogram_name; | |
250 | |
251 if (site_url_.SchemeIsCryptographic()) { | |
252 if (security_level_ == security_state::SECURE || | |
253 security_level_ == security_state::EV_SECURE) { | |
254 UMA_HISTOGRAM_ENUMERATION("Security.PageInfo.Action.HttpsUrl.Valid", | |
255 action, WEBSITE_SETTINGS_COUNT); | |
256 } else if (security_level_ == security_state::NONE) { | |
257 UMA_HISTOGRAM_ENUMERATION("Security.PageInfo.Action.HttpsUrl.Downgraded", | |
258 action, WEBSITE_SETTINGS_COUNT); | |
259 } else if (security_level_ == security_state::DANGEROUS) { | |
260 UMA_HISTOGRAM_ENUMERATION("Security.PageInfo.Action.HttpsUrl.Dangerous", | |
261 action, WEBSITE_SETTINGS_COUNT); | |
262 } | |
263 return; | |
264 } | |
265 | |
266 if (security_level_ == security_state::HTTP_SHOW_WARNING) { | |
267 UMA_HISTOGRAM_ENUMERATION("Security.PageInfo.Action.HttpUrl.Warning", | |
268 action, WEBSITE_SETTINGS_COUNT); | |
269 } else if (security_level_ == security_state::DANGEROUS) { | |
270 UMA_HISTOGRAM_ENUMERATION("Security.PageInfo.Action.HttpUrl.Dangerous", | |
271 action, WEBSITE_SETTINGS_COUNT); | |
272 } else { | |
273 UMA_HISTOGRAM_ENUMERATION("Security.PageInfo.Action.HttpUrl.Neutral", | |
274 action, WEBSITE_SETTINGS_COUNT); | |
275 } | |
276 } | |
277 | |
278 void WebsiteSettings::OnSitePermissionChanged(ContentSettingsType type, | |
279 ContentSetting setting) { | |
280 // Count how often a permission for a specific content type is changed using | |
281 // the Website Settings UI. | |
282 size_t num_values; | |
283 int histogram_value = ContentSettingTypeToHistogramValue(type, &num_values); | |
284 UMA_HISTOGRAM_ENUMERATION("WebsiteSettings.OriginInfo.PermissionChanged", | |
285 histogram_value, num_values); | |
286 | |
287 if (setting == ContentSetting::CONTENT_SETTING_ALLOW) { | |
288 UMA_HISTOGRAM_ENUMERATION( | |
289 "WebsiteSettings.OriginInfo.PermissionChanged.Allowed", histogram_value, | |
290 num_values); | |
291 | |
292 if (type == CONTENT_SETTINGS_TYPE_PLUGINS) { | |
293 rappor::SampleDomainAndRegistryFromGURL( | |
294 g_browser_process->rappor_service(), | |
295 "ContentSettings.Plugins.AddedAllowException", site_url_); | |
296 } | |
297 } else if (setting == ContentSetting::CONTENT_SETTING_BLOCK) { | |
298 UMA_HISTOGRAM_ENUMERATION( | |
299 "WebsiteSettings.OriginInfo.PermissionChanged.Blocked", histogram_value, | |
300 num_values); | |
301 } | |
302 | |
303 // This is technically redundant given the histogram above, but putting the | |
304 // total count of permission changes in another histogram makes it easier to | |
305 // compare it against other kinds of actions in WebsiteSettings[PopupView]. | |
306 RecordWebsiteSettingsAction(WEBSITE_SETTINGS_CHANGED_PERMISSION); | |
307 | |
308 PermissionUtil::ScopedRevocationReporter scoped_revocation_reporter( | |
309 this->profile_, this->site_url_, this->site_url_, type, | |
310 PermissionSourceUI::OIB); | |
311 | |
312 content_settings_->SetNarrowestContentSetting(site_url_, site_url_, type, | |
313 setting); | |
314 | |
315 show_info_bar_ = true; | |
316 | |
317 // Refresh the UI to reflect the new setting. | |
318 PresentSitePermissions(); | |
319 } | |
320 | |
321 void WebsiteSettings::OnSiteChosenObjectDeleted( | |
322 const ChooserUIInfo& ui_info, | |
323 const base::DictionaryValue& object) { | |
324 // TODO(reillyg): Create metrics for revocations. crbug.com/556845 | |
325 ChooserContextBase* context = ui_info.get_context(profile_); | |
326 const GURL origin = site_url_.GetOrigin(); | |
327 context->RevokeObjectPermission(origin, origin, object); | |
328 | |
329 show_info_bar_ = true; | |
330 | |
331 // Refresh the UI to reflect the changed settings. | |
332 PresentSitePermissions(); | |
333 } | |
334 | |
335 void WebsiteSettings::OnSiteDataAccessed() { | |
336 PresentSiteData(); | |
337 } | |
338 | |
339 void WebsiteSettings::OnUIClosing() { | |
340 #if defined(OS_ANDROID) | |
341 NOTREACHED(); | |
342 #else | |
343 if (show_info_bar_ && web_contents() && !web_contents()->IsBeingDestroyed()) { | |
344 InfoBarService* infobar_service = | |
345 InfoBarService::FromWebContents(web_contents()); | |
346 if (infobar_service) | |
347 WebsiteSettingsInfoBarDelegate::Create(infobar_service); | |
348 } | |
349 | |
350 SSLCertificateDecisionsDidRevoke user_decision = | |
351 did_revoke_user_ssl_decisions_ ? USER_CERT_DECISIONS_REVOKED | |
352 : USER_CERT_DECISIONS_NOT_REVOKED; | |
353 | |
354 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.did_user_revoke_decisions", | |
355 user_decision, | |
356 END_OF_SSL_CERTIFICATE_DECISIONS_DID_REVOKE_ENUM); | |
357 #endif | |
358 } | |
359 | |
360 void WebsiteSettings::OnRevokeSSLErrorBypassButtonPressed() { | |
361 DCHECK(chrome_ssl_host_state_delegate_); | |
362 chrome_ssl_host_state_delegate_->RevokeUserAllowExceptionsHard( | |
363 site_url().host()); | |
364 did_revoke_user_ssl_decisions_ = true; | |
365 } | |
366 | |
367 void WebsiteSettings::Init(const GURL& url, | |
368 const security_state::SecurityInfo& security_info) { | |
369 #if !defined(OS_ANDROID) && !defined(OS_IOS) | |
370 // On desktop, internal URLs aren't handled by this class. Instead, a | |
371 // custom and simpler popup is shown. | |
372 DCHECK(!url.SchemeIs(content::kChromeUIScheme) && | |
373 !url.SchemeIs(content::kChromeDevToolsScheme) && | |
374 !url.SchemeIs(content::kViewSourceScheme) && | |
375 !url.SchemeIs(content_settings::kExtensionScheme)); | |
376 #endif | |
377 | |
378 bool isChromeUINativeScheme = false; | |
379 #if defined(OS_ANDROID) | |
380 isChromeUINativeScheme = url.SchemeIs(chrome::kChromeUINativeScheme); | |
381 #endif | |
382 | |
383 security_level_ = security_info.security_level; | |
384 | |
385 if (url.SchemeIs(url::kAboutScheme)) { | |
386 // All about: URLs except about:blank are redirected. | |
387 DCHECK_EQ(url::kAboutBlankURL, url.spec()); | |
388 site_identity_status_ = SITE_IDENTITY_STATUS_NO_CERT; | |
389 site_identity_details_ = | |
390 l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURITY_TAB_INSECURE_IDENTITY); | |
391 site_connection_status_ = SITE_CONNECTION_STATUS_UNENCRYPTED; | |
392 site_connection_details_ = l10n_util::GetStringFUTF16( | |
393 IDS_PAGE_INFO_SECURITY_TAB_NOT_ENCRYPTED_CONNECTION_TEXT, | |
394 UTF8ToUTF16(url.spec())); | |
395 return; | |
396 } | |
397 | |
398 if (url.SchemeIs(content::kChromeUIScheme) || isChromeUINativeScheme) { | |
399 site_identity_status_ = SITE_IDENTITY_STATUS_INTERNAL_PAGE; | |
400 site_identity_details_ = | |
401 l10n_util::GetStringUTF16(IDS_PAGE_INFO_INTERNAL_PAGE); | |
402 site_connection_status_ = SITE_CONNECTION_STATUS_INTERNAL_PAGE; | |
403 return; | |
404 } | |
405 | |
406 // Identity section. | |
407 certificate_ = security_info.certificate; | |
408 | |
409 if (security_info.malicious_content_status != | |
410 security_state::MALICIOUS_CONTENT_STATUS_NONE) { | |
411 // The site has been flagged by Safe Browsing as dangerous. | |
412 GetSiteIdentityByMaliciousContentStatus( | |
413 security_info.malicious_content_status, &site_identity_status_, | |
414 &site_identity_details_); | |
415 } else if (certificate_ && | |
416 (!net::IsCertStatusError(security_info.cert_status) || | |
417 net::IsCertStatusMinorError(security_info.cert_status))) { | |
418 // HTTPS with no or minor errors. | |
419 if (security_info.security_level == | |
420 security_state::SECURE_WITH_POLICY_INSTALLED_CERT) { | |
421 site_identity_status_ = SITE_IDENTITY_STATUS_ADMIN_PROVIDED_CERT; | |
422 site_identity_details_ = l10n_util::GetStringFUTF16( | |
423 IDS_CERT_POLICY_PROVIDED_CERT_MESSAGE, UTF8ToUTF16(url.host())); | |
424 } else if (net::IsCertStatusMinorError(security_info.cert_status)) { | |
425 site_identity_status_ = SITE_IDENTITY_STATUS_CERT_REVOCATION_UNKNOWN; | |
426 base::string16 issuer_name( | |
427 UTF8ToUTF16(certificate_->issuer().GetDisplayName())); | |
428 if (issuer_name.empty()) { | |
429 issuer_name.assign(l10n_util::GetStringUTF16( | |
430 IDS_PAGE_INFO_SECURITY_TAB_UNKNOWN_PARTY)); | |
431 } | |
432 | |
433 site_identity_details_.assign(l10n_util::GetStringFUTF16( | |
434 IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY_VERIFIED, issuer_name)); | |
435 | |
436 site_identity_details_ += ASCIIToUTF16("\n\n"); | |
437 if (security_info.cert_status & | |
438 net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION) { | |
439 site_identity_details_ += l10n_util::GetStringUTF16( | |
440 IDS_PAGE_INFO_SECURITY_TAB_UNABLE_TO_CHECK_REVOCATION); | |
441 } else if (security_info.cert_status & | |
442 net::CERT_STATUS_NO_REVOCATION_MECHANISM) { | |
443 site_identity_details_ += l10n_util::GetStringUTF16( | |
444 IDS_PAGE_INFO_SECURITY_TAB_NO_REVOCATION_MECHANISM); | |
445 } else { | |
446 NOTREACHED() << "Need to specify string for this warning"; | |
447 } | |
448 } else { | |
449 // No major or minor errors. | |
450 if (security_info.cert_status & net::CERT_STATUS_IS_EV) { | |
451 // EV HTTPS page. | |
452 site_identity_status_ = SITE_IDENTITY_STATUS_EV_CERT; | |
453 DCHECK(!certificate_->subject().organization_names.empty()); | |
454 organization_name_ = | |
455 UTF8ToUTF16(certificate_->subject().organization_names[0]); | |
456 // An EV Cert is required to have a city (localityName) and country but | |
457 // state is "if any". | |
458 DCHECK(!certificate_->subject().locality_name.empty()); | |
459 DCHECK(!certificate_->subject().country_name.empty()); | |
460 base::string16 locality; | |
461 if (!certificate_->subject().state_or_province_name.empty()) { | |
462 locality = l10n_util::GetStringFUTF16( | |
463 IDS_PAGEINFO_ADDRESS, | |
464 UTF8ToUTF16(certificate_->subject().locality_name), | |
465 UTF8ToUTF16(certificate_->subject().state_or_province_name), | |
466 UTF8ToUTF16(certificate_->subject().country_name)); | |
467 } else { | |
468 locality = l10n_util::GetStringFUTF16( | |
469 IDS_PAGEINFO_PARTIAL_ADDRESS, | |
470 UTF8ToUTF16(certificate_->subject().locality_name), | |
471 UTF8ToUTF16(certificate_->subject().country_name)); | |
472 } | |
473 DCHECK(!certificate_->subject().organization_names.empty()); | |
474 site_identity_details_.assign(l10n_util::GetStringFUTF16( | |
475 IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY_EV_VERIFIED, | |
476 UTF8ToUTF16(certificate_->subject().organization_names[0]), | |
477 locality, UTF8ToUTF16(certificate_->issuer().GetDisplayName()))); | |
478 } else { | |
479 // Non-EV OK HTTPS page. | |
480 site_identity_status_ = SITE_IDENTITY_STATUS_CERT; | |
481 base::string16 issuer_name( | |
482 UTF8ToUTF16(certificate_->issuer().GetDisplayName())); | |
483 if (issuer_name.empty()) { | |
484 issuer_name.assign(l10n_util::GetStringUTF16( | |
485 IDS_PAGE_INFO_SECURITY_TAB_UNKNOWN_PARTY)); | |
486 } | |
487 | |
488 site_identity_details_.assign(l10n_util::GetStringFUTF16( | |
489 IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY_VERIFIED, issuer_name)); | |
490 } | |
491 if (security_info.sha1_in_chain) { | |
492 site_identity_status_ = | |
493 SITE_IDENTITY_STATUS_DEPRECATED_SIGNATURE_ALGORITHM; | |
494 site_identity_details_ += | |
495 UTF8ToUTF16("\n\n") + | |
496 l10n_util::GetStringUTF16( | |
497 IDS_PAGE_INFO_SECURITY_TAB_DEPRECATED_SIGNATURE_ALGORITHM); | |
498 } | |
499 } | |
500 } else { | |
501 // HTTP or HTTPS with errors (not warnings). | |
502 site_identity_details_.assign(l10n_util::GetStringUTF16( | |
503 IDS_PAGE_INFO_SECURITY_TAB_INSECURE_IDENTITY)); | |
504 if (!security_info.scheme_is_cryptographic || !security_info.certificate) | |
505 site_identity_status_ = SITE_IDENTITY_STATUS_NO_CERT; | |
506 else | |
507 site_identity_status_ = SITE_IDENTITY_STATUS_ERROR; | |
508 | |
509 const base::string16 bullet = UTF8ToUTF16("\n • "); | |
510 std::vector<ssl_errors::ErrorInfo> errors; | |
511 ssl_errors::ErrorInfo::GetErrorsForCertStatus( | |
512 certificate_, security_info.cert_status, url, &errors); | |
513 for (size_t i = 0; i < errors.size(); ++i) { | |
514 site_identity_details_ += bullet; | |
515 site_identity_details_ += errors[i].short_description(); | |
516 } | |
517 | |
518 if (security_info.cert_status & net::CERT_STATUS_NON_UNIQUE_NAME) { | |
519 site_identity_details_ += ASCIIToUTF16("\n\n"); | |
520 site_identity_details_ += | |
521 l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURITY_TAB_NON_UNIQUE_NAME); | |
522 } | |
523 } | |
524 | |
525 // Site Connection | |
526 // We consider anything less than 80 bits encryption to be weak encryption. | |
527 // TODO(wtc): Bug 1198735: report mixed/unsafe content for unencrypted and | |
528 // weakly encrypted connections. | |
529 site_connection_status_ = SITE_CONNECTION_STATUS_UNKNOWN; | |
530 | |
531 base::string16 subject_name(GetSimpleSiteName(url)); | |
532 if (subject_name.empty()) { | |
533 subject_name.assign( | |
534 l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURITY_TAB_UNKNOWN_PARTY)); | |
535 } | |
536 | |
537 if (!security_info.certificate || !security_info.scheme_is_cryptographic) { | |
538 // Page is still loading (so SSL status is not yet available) or | |
539 // loaded over HTTP or loaded over HTTPS with no cert. | |
540 site_connection_status_ = SITE_CONNECTION_STATUS_UNENCRYPTED; | |
541 | |
542 site_connection_details_.assign(l10n_util::GetStringFUTF16( | |
543 IDS_PAGE_INFO_SECURITY_TAB_NOT_ENCRYPTED_CONNECTION_TEXT, | |
544 subject_name)); | |
545 } else if (security_info.security_bits < 0) { | |
546 // Security strength is unknown. Say nothing. | |
547 site_connection_status_ = SITE_CONNECTION_STATUS_ENCRYPTED_ERROR; | |
548 } else if (security_info.security_bits == 0) { | |
549 DCHECK_NE(security_info.security_level, security_state::NONE); | |
550 site_connection_status_ = SITE_CONNECTION_STATUS_ENCRYPTED_ERROR; | |
551 site_connection_details_.assign(l10n_util::GetStringFUTF16( | |
552 IDS_PAGE_INFO_SECURITY_TAB_NOT_ENCRYPTED_CONNECTION_TEXT, | |
553 subject_name)); | |
554 } else { | |
555 site_connection_status_ = SITE_CONNECTION_STATUS_ENCRYPTED; | |
556 | |
557 if (security_info.obsolete_ssl_status == net::OBSOLETE_SSL_NONE) { | |
558 site_connection_details_.assign(l10n_util::GetStringFUTF16( | |
559 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_CONNECTION_TEXT, subject_name)); | |
560 } else { | |
561 site_connection_details_.assign(l10n_util::GetStringFUTF16( | |
562 IDS_PAGE_INFO_SECURITY_TAB_WEAK_ENCRYPTION_CONNECTION_TEXT, | |
563 subject_name)); | |
564 } | |
565 | |
566 bool ran_insecure_content = false; | |
567 bool displayed_insecure_content = false; | |
568 CheckForInsecureContent(security_info, &displayed_insecure_content, | |
569 &ran_insecure_content); | |
570 if (ran_insecure_content || displayed_insecure_content) { | |
571 site_connection_status_ = | |
572 ran_insecure_content | |
573 ? SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE | |
574 : SITE_CONNECTION_STATUS_INSECURE_PASSIVE_SUBRESOURCE; | |
575 site_connection_details_.assign(l10n_util::GetStringFUTF16( | |
576 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_SENTENCE_LINK, | |
577 site_connection_details_, | |
578 l10n_util::GetStringUTF16( | |
579 ran_insecure_content | |
580 ? IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_INSECURE_CONTENT_ERROR | |
581 : IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_INSECURE_CONTENT_WARNIN
G))); | |
582 } | |
583 } | |
584 | |
585 uint16_t cipher_suite = | |
586 net::SSLConnectionStatusToCipherSuite(security_info.connection_status); | |
587 if (security_info.security_bits > 0 && cipher_suite) { | |
588 int ssl_version = | |
589 net::SSLConnectionStatusToVersion(security_info.connection_status); | |
590 const char* ssl_version_str; | |
591 net::SSLVersionToString(&ssl_version_str, ssl_version); | |
592 site_connection_details_ += ASCIIToUTF16("\n\n"); | |
593 site_connection_details_ += l10n_util::GetStringFUTF16( | |
594 IDS_PAGE_INFO_SECURITY_TAB_SSL_VERSION, ASCIIToUTF16(ssl_version_str)); | |
595 | |
596 const char *key_exchange, *cipher, *mac; | |
597 bool is_aead, is_tls13; | |
598 net::SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, | |
599 &is_tls13, cipher_suite); | |
600 | |
601 site_connection_details_ += ASCIIToUTF16("\n\n"); | |
602 if (is_aead) { | |
603 if (is_tls13) { | |
604 // For TLS 1.3 ciphers, report the group (historically, curve) as the | |
605 // key exchange. | |
606 key_exchange = SSL_get_curve_name(security_info.key_exchange_group); | |
607 if (!key_exchange) { | |
608 NOTREACHED(); | |
609 key_exchange = ""; | |
610 } | |
611 } | |
612 site_connection_details_ += l10n_util::GetStringFUTF16( | |
613 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTION_DETAILS_AEAD, | |
614 ASCIIToUTF16(cipher), ASCIIToUTF16(key_exchange)); | |
615 } else { | |
616 site_connection_details_ += l10n_util::GetStringFUTF16( | |
617 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTION_DETAILS, ASCIIToUTF16(cipher), | |
618 ASCIIToUTF16(mac), ASCIIToUTF16(key_exchange)); | |
619 } | |
620 | |
621 if (ssl_version == net::SSL_CONNECTION_VERSION_SSL3 && | |
622 site_connection_status_ < | |
623 SITE_CONNECTION_STATUS_INSECURE_PASSIVE_SUBRESOURCE) { | |
624 site_connection_status_ = SITE_CONNECTION_STATUS_ENCRYPTED_ERROR; | |
625 } | |
626 } | |
627 | |
628 // Check if a user decision has been made to allow or deny certificates with | |
629 // errors on this site. | |
630 ChromeSSLHostStateDelegate* delegate = | |
631 ChromeSSLHostStateDelegateFactory::GetForProfile(profile_); | |
632 DCHECK(delegate); | |
633 // Only show an SSL decision revoke button if the user has chosen to bypass | |
634 // SSL host errors for this host in the past. | |
635 show_ssl_decision_revoke_button_ = delegate->HasAllowException(url.host()); | |
636 } | |
637 | |
638 void WebsiteSettings::PresentSitePermissions() { | |
639 PermissionInfoList permission_info_list; | |
640 ChosenObjectInfoList chosen_object_info_list; | |
641 | |
642 WebsiteSettingsUI::PermissionInfo permission_info; | |
643 for (size_t i = 0; i < arraysize(kPermissionType); ++i) { | |
644 permission_info.type = kPermissionType[i]; | |
645 | |
646 if (!ShouldShowPermission(permission_info.type)) | |
647 continue; | |
648 | |
649 content_settings::SettingInfo info; | |
650 std::unique_ptr<base::Value> value = content_settings_->GetWebsiteSetting( | |
651 site_url_, site_url_, permission_info.type, std::string(), &info); | |
652 DCHECK(value.get()); | |
653 if (value->GetType() == base::Value::Type::INTEGER) { | |
654 permission_info.setting = | |
655 content_settings::ValueToContentSetting(value.get()); | |
656 } else { | |
657 NOTREACHED(); | |
658 } | |
659 | |
660 permission_info.source = info.source; | |
661 permission_info.is_incognito = profile_->IsOffTheRecord(); | |
662 | |
663 if (info.primary_pattern == ContentSettingsPattern::Wildcard() && | |
664 info.secondary_pattern == ContentSettingsPattern::Wildcard()) { | |
665 permission_info.default_setting = permission_info.setting; | |
666 permission_info.setting = CONTENT_SETTING_DEFAULT; | |
667 } else { | |
668 permission_info.default_setting = | |
669 content_settings_->GetDefaultContentSetting(permission_info.type, | |
670 NULL); | |
671 } | |
672 | |
673 // For permissions that are still prompting the user and haven't been | |
674 // explicitly set by another source, check its embargo status. | |
675 if (PermissionUtil::IsPermission(permission_info.type) && | |
676 permission_info.setting == CONTENT_SETTING_DEFAULT && | |
677 permission_info.source == | |
678 content_settings::SettingSource::SETTING_SOURCE_USER) { | |
679 // TODO(raymes): Use GetPermissionStatus() to retrieve information | |
680 // about *all* permissions once it has default behaviour implemented for | |
681 // ContentSettingTypes that aren't permissions. | |
682 PermissionResult permission_result = | |
683 PermissionManager::Get(profile_)->GetPermissionStatus( | |
684 permission_info.type, site_url_, site_url_); | |
685 | |
686 // If under embargo, update |permission_info| to reflect that. | |
687 if (permission_result.content_setting == CONTENT_SETTING_BLOCK && | |
688 (permission_result.source == | |
689 PermissionStatusSource::MULTIPLE_DISMISSALS || | |
690 permission_result.source == | |
691 PermissionStatusSource::SAFE_BROWSING_BLACKLIST)) | |
692 permission_info.setting = permission_result.content_setting; | |
693 } | |
694 | |
695 permission_info_list.push_back(permission_info); | |
696 } | |
697 | |
698 for (const ChooserUIInfo& ui_info : kChooserUIInfo) { | |
699 ChooserContextBase* context = ui_info.get_context(profile_); | |
700 const GURL origin = site_url_.GetOrigin(); | |
701 auto chosen_objects = context->GetGrantedObjects(origin, origin); | |
702 for (std::unique_ptr<base::DictionaryValue>& object : chosen_objects) { | |
703 chosen_object_info_list.push_back( | |
704 base::MakeUnique<WebsiteSettingsUI::ChosenObjectInfo>( | |
705 ui_info, std::move(object))); | |
706 } | |
707 } | |
708 | |
709 ui_->SetPermissionInfo(permission_info_list, | |
710 std::move(chosen_object_info_list)); | |
711 } | |
712 | |
713 void WebsiteSettings::PresentSiteData() { | |
714 CookieInfoList cookie_info_list; | |
715 const LocalSharedObjectsContainer& allowed_objects = | |
716 tab_specific_content_settings()->allowed_local_shared_objects(); | |
717 const LocalSharedObjectsContainer& blocked_objects = | |
718 tab_specific_content_settings()->blocked_local_shared_objects(); | |
719 | |
720 // Add first party cookie and site data counts. | |
721 WebsiteSettingsUI::CookieInfo cookie_info; | |
722 cookie_info.allowed = allowed_objects.GetObjectCountForDomain(site_url_); | |
723 cookie_info.blocked = blocked_objects.GetObjectCountForDomain(site_url_); | |
724 cookie_info.is_first_party = true; | |
725 cookie_info_list.push_back(cookie_info); | |
726 | |
727 // Add third party cookie counts. | |
728 cookie_info.allowed = allowed_objects.GetObjectCount() - cookie_info.allowed; | |
729 cookie_info.blocked = blocked_objects.GetObjectCount() - cookie_info.blocked; | |
730 cookie_info.is_first_party = false; | |
731 cookie_info_list.push_back(cookie_info); | |
732 | |
733 ui_->SetCookieInfo(cookie_info_list); | |
734 } | |
735 | |
736 void WebsiteSettings::PresentSiteIdentity() { | |
737 // After initialization the status about the site's connection and its | |
738 // identity must be available. | |
739 DCHECK_NE(site_identity_status_, SITE_IDENTITY_STATUS_UNKNOWN); | |
740 DCHECK_NE(site_connection_status_, SITE_CONNECTION_STATUS_UNKNOWN); | |
741 WebsiteSettingsUI::IdentityInfo info; | |
742 if (site_identity_status_ == SITE_IDENTITY_STATUS_EV_CERT) | |
743 info.site_identity = UTF16ToUTF8(organization_name()); | |
744 else | |
745 info.site_identity = UTF16ToUTF8(GetSimpleSiteName(site_url_)); | |
746 | |
747 info.connection_status = site_connection_status_; | |
748 info.connection_status_description = UTF16ToUTF8(site_connection_details_); | |
749 info.identity_status = site_identity_status_; | |
750 info.identity_status_description = UTF16ToUTF8(site_identity_details_); | |
751 info.certificate = certificate_; | |
752 info.show_ssl_decision_revoke_button = show_ssl_decision_revoke_button_; | |
753 ui_->SetIdentityInfo(info); | |
754 } | |
OLD | NEW |