| 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 |