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/website_settings/website_settings.h" 6 7 #include <string> 8 #include <vector> 9 10 #include "base/bind.h" 11 #include "base/bind_helpers.h" 12 #include "base/command_line.h" 13 #include "base/i18n/time_formatting.h" 14 #include "base/metrics/field_trial.h" 15 #include "base/metrics/histogram.h" 16 #include "base/strings/string_number_conversions.h" 17 #include "base/strings/utf_string_conversions.h" 18 #include "base/values.h" 19 #include "chrome/browser/browsing_data/browsing_data_channel_id_helper.h" 20 #include "chrome/browser/browsing_data/browsing_data_cookie_helper.h" 21 #include "chrome/browser/browsing_data/browsing_data_database_helper.h" 22 #include "chrome/browser/browsing_data/browsing_data_file_system_helper.h" 23 #include "chrome/browser/browsing_data/browsing_data_indexed_db_helper.h" 24 #include "chrome/browser/browsing_data/browsing_data_local_storage_helper.h" 25 #include "chrome/browser/content_settings/content_settings_utils.h" 26 #include "chrome/browser/content_settings/host_content_settings_map.h" 27 #include "chrome/browser/content_settings/local_shared_objects_container.h" 28 #include "chrome/browser/history/history_service_factory.h" 29 #include "chrome/browser/profiles/profile.h" 30 #include "chrome/browser/ssl/chrome_ssl_host_state_delegate.h" 31 #include "chrome/browser/ssl/chrome_ssl_host_state_delegate_factory.h" 32 #include "chrome/browser/ssl/ssl_error_info.h" 33 #include "chrome/browser/ui/website_settings/website_settings_infobar_delegate.h" 34 #include "chrome/browser/ui/website_settings/website_settings_ui.h" 35 #include "chrome/common/chrome_switches.h" 36 #include "chrome/grit/chromium_strings.h" 37 #include "chrome/grit/generated_resources.h" 38 #include "components/content_settings/core/common/content_settings_pattern.h" 39 #include "content/public/browser/browser_thread.h" 40 #include "content/public/browser/cert_store.h" 41 #include "content/public/browser/user_metrics.h" 42 #include "content/public/common/content_switches.h" 43 #include "content/public/common/ssl_status.h" 44 #include "content/public/common/url_constants.h" 45 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" 46 #include "net/cert/cert_status_flags.h" 47 #include "net/cert/x509_certificate.h" 48 #include "net/ssl/ssl_cipher_suite_names.h" 49 #include "net/ssl/ssl_connection_status_flags.h" 50 #include "ui/base/l10n/l10n_util.h" 51 52 #if defined(OS_CHROMEOS) 53 #include "chrome/browser/chromeos/policy/policy_cert_service.h" 54 #include "chrome/browser/chromeos/policy/policy_cert_service_factory.h" 55 #endif 56 57 using base::ASCIIToUTF16; 58 using base::UTF8ToUTF16; 59 using base::UTF16ToUTF8; 60 using content::BrowserThread; 61 62 namespace { 63 64 // Events for UMA. Do not reorder or change! 65 enum SSLCertificateDecisionsDidRevoke { 66 USER_CERT_DECISIONS_NOT_REVOKED = 0, 67 USER_CERT_DECISIONS_REVOKED, 68 END_OF_SSL_CERTIFICATE_DECISIONS_DID_REVOKE_ENUM 69 }; 70 71 // The list of content settings types to display on the Website Settings UI. 72 ContentSettingsType kPermissionType[] = { 73 CONTENT_SETTINGS_TYPE_IMAGES, 74 CONTENT_SETTINGS_TYPE_JAVASCRIPT, 75 CONTENT_SETTINGS_TYPE_PLUGINS, 76 CONTENT_SETTINGS_TYPE_POPUPS, 77 CONTENT_SETTINGS_TYPE_GEOLOCATION, 78 CONTENT_SETTINGS_TYPE_NOTIFICATIONS, 79 CONTENT_SETTINGS_TYPE_FULLSCREEN, 80 CONTENT_SETTINGS_TYPE_MOUSELOCK, 81 CONTENT_SETTINGS_TYPE_MEDIASTREAM, 82 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, 83 CONTENT_SETTINGS_TYPE_MIDI_SYSEX, 84 }; 85 86 bool CertificateTransparencyStatusMatch( 87 const content::SignedCertificateTimestampIDStatusList& scts, 88 net::ct::SCTVerifyStatus status) { 89 for (content::SignedCertificateTimestampIDStatusList::const_iterator it = 90 scts.begin(); 91 it != scts.end(); 92 ++it) { 93 if (it->status == status) 94 return true; 95 } 96 97 return false; 98 } 99 100 int GetSiteIdentityDetailsMessageByCTInfo( 101 const content::SignedCertificateTimestampIDStatusList& scts, 102 bool is_ev) { 103 // No SCTs - no CT information. 104 if (scts.empty()) 105 return (is_ev ? IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY_EV_NO_CT 106 : IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY_NO_CT); 107 108 if (CertificateTransparencyStatusMatch(scts, net::ct::SCT_STATUS_OK)) 109 return (is_ev ? IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY_EV_CT_VERIFIED 110 : IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY_CT_VERIFIED); 111 112 if (CertificateTransparencyStatusMatch(scts, net::ct::SCT_STATUS_INVALID)) 113 return (is_ev ? IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY_EV_CT_INVALID 114 : IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY_CT_INVALID); 115 116 // status is SCT_STATUS_LOG_UNKNOWN 117 return (is_ev ? IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY_EV_CT_UNVERIFIED 118 : IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY_CT_UNVERIFIED); 119 } 120 121 // This function will return SITE_IDENTITY_STATUS_CERT or 122 // SITE_IDENTITY_STATUS_EV_CERT depending on |is_ev| unless there are SCTs 123 // which failed verification, in which case it will return 124 // SITE_IDENTITY_STATUS_ERROR. 125 WebsiteSettings::SiteIdentityStatus GetSiteIdentityStatusByCTInfo( 126 const content::SignedCertificateTimestampIDStatusList& scts, 127 bool is_ev) { 128 if (CertificateTransparencyStatusMatch(scts, net::ct::SCT_STATUS_INVALID)) 129 return WebsiteSettings::SITE_IDENTITY_STATUS_ERROR; 130 131 return is_ev ? WebsiteSettings::SITE_IDENTITY_STATUS_EV_CERT 132 : WebsiteSettings::SITE_IDENTITY_STATUS_CERT; 133 } 134 135 const char kRememberCertificateErrorDecisionsFieldTrialName[] = 136 "RememberCertificateErrorDecisions"; 137 const char kRememberCertificateErrorDecisionsFieldTrialDefaultGroup[] = 138 "Default"; 139 const char kRememberCertificateErrorDecisionsFieldTrialDisableGroup[] = 140 "Disable"; 141 // Returns true if the user is in the experimental group or has the flag enabled 142 // for remembering SSL error decisions, otherwise false. 143 // 144 // TODO(jww): The field trial is scheduled to end 2015/02/28. This should be 145 // removed at that point unless the field trial or flag continues. 146 bool InRememberCertificateErrorDecisionsGroup() { 147 std::string group_name = base::FieldTrialList::FindFullName( 148 kRememberCertificateErrorDecisionsFieldTrialName); 149 150 // The Default and Disable groups are the "old-style" forget-at-session 151 // restart groups, so they do not get the button. 152 bool in_experimental_group = !group_name.empty() && 153 group_name.compare( 154 kRememberCertificateErrorDecisionsFieldTrialDefaultGroup) != 0 && 155 group_name.compare( 156 kRememberCertificateErrorDecisionsFieldTrialDisableGroup) != 0; 157 bool has_command_line_switch = CommandLine::ForCurrentProcess()->HasSwitch( 158 switches::kRememberCertErrorDecisions); 159 return in_experimental_group || has_command_line_switch; 160 } 161 162 } // namespace 163 164 WebsiteSettings::WebsiteSettings( 165 WebsiteSettingsUI* ui, 166 Profile* profile, 167 TabSpecificContentSettings* tab_specific_content_settings, 168 InfoBarService* infobar_service, 169 const GURL& url, 170 const content::SSLStatus& ssl, 171 content::CertStore* cert_store) 172 : TabSpecificContentSettings::SiteDataObserver( 173 tab_specific_content_settings), 174 ui_(ui), 175 infobar_service_(infobar_service), 176 show_info_bar_(false), 177 site_url_(url), 178 site_identity_status_(SITE_IDENTITY_STATUS_UNKNOWN), 179 cert_id_(0), 180 site_connection_status_(SITE_CONNECTION_STATUS_UNKNOWN), 181 cert_store_(cert_store), 182 content_settings_(profile->GetHostContentSettingsMap()), 183 chrome_ssl_host_state_delegate_( 184 ChromeSSLHostStateDelegateFactory::GetForProfile(profile)), 185 did_revoke_user_ssl_decisions_(false) { 186 Init(profile, url, ssl); 187 188 HistoryService* history_service = HistoryServiceFactory::GetForProfile( 189 profile, Profile::EXPLICIT_ACCESS); 190 if (history_service) { 191 history_service->GetVisibleVisitCountToHost( 192 site_url_, 193 base::Bind(&WebsiteSettings::OnGotVisitCountToHost, 194 base::Unretained(this)), 195 &visit_count_task_tracker_); 196 } 197 198 PresentSitePermissions(); 199 PresentSiteData(); 200 PresentSiteIdentity(); 201 PresentHistoryInfo(base::Time()); 202 203 // Every time the Website Settings UI is opened a |WebsiteSettings| object is 204 // created. So this counts how ofter the Website Settings UI is opened. 205 content::RecordAction(base::UserMetricsAction("WebsiteSettings_Opened")); 206 } 207 208 WebsiteSettings::~WebsiteSettings() { 209 } 210 211 void WebsiteSettings::OnSitePermissionChanged(ContentSettingsType type, 212 ContentSetting setting) { 213 // Count how often a permission for a specific content type is changed using 214 // the Website Settings UI. 215 UMA_HISTOGRAM_COUNTS("WebsiteSettings.PermissionChanged", type); 216 217 ContentSettingsPattern primary_pattern; 218 ContentSettingsPattern secondary_pattern; 219 switch (type) { 220 case CONTENT_SETTINGS_TYPE_GEOLOCATION: 221 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX: 222 // TODO(markusheintz): The rule we create here should also change the 223 // location permission for iframed content. 224 primary_pattern = ContentSettingsPattern::FromURLNoWildcard(site_url_); 225 secondary_pattern = ContentSettingsPattern::FromURLNoWildcard(site_url_); 226 break; 227 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: 228 primary_pattern = ContentSettingsPattern::FromURLNoWildcard(site_url_); 229 secondary_pattern = ContentSettingsPattern::Wildcard(); 230 break; 231 case CONTENT_SETTINGS_TYPE_IMAGES: 232 case CONTENT_SETTINGS_TYPE_JAVASCRIPT: 233 case CONTENT_SETTINGS_TYPE_PLUGINS: 234 case CONTENT_SETTINGS_TYPE_POPUPS: 235 case CONTENT_SETTINGS_TYPE_FULLSCREEN: 236 case CONTENT_SETTINGS_TYPE_MOUSELOCK: 237 case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS: 238 primary_pattern = ContentSettingsPattern::FromURL(site_url_); 239 secondary_pattern = ContentSettingsPattern::Wildcard(); 240 break; 241 case CONTENT_SETTINGS_TYPE_MEDIASTREAM: { 242 // We need to use the same same patterns as other places like infobar code 243 // to override the existing rule instead of creating the new one. 244 primary_pattern = ContentSettingsPattern::FromURLNoWildcard(site_url_); 245 secondary_pattern = ContentSettingsPattern::Wildcard(); 246 // Set permission for both microphone and camera. 247 content_settings_->SetContentSetting( 248 primary_pattern, 249 secondary_pattern, 250 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, 251 std::string(), 252 setting); 253 254 content_settings_->SetContentSetting( 255 primary_pattern, 256 secondary_pattern, 257 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, 258 std::string(), 259 setting); 260 break; 261 } 262 default: 263 NOTREACHED() << "ContentSettingsType " << type << "is not supported."; 264 break; 265 } 266 267 if (type != CONTENT_SETTINGS_TYPE_MEDIASTREAM) { 268 // Permission settings are specified via rules. There exists always at least 269 // one rule for the default setting. Get the rule that currently defines 270 // the permission for the given permission |type|. Then test whether the 271 // existing rule is more specific than the rule we are about to create. If 272 // the existing rule is more specific, than change the existing rule instead 273 // of creating a new rule that would be hidden behind the existing rule. 274 // This is not a concern for CONTENT_SETTINGS_TYPE_MEDIASTREAM since users 275 // can not create media settings exceptions by hand. 276 content_settings::SettingInfo info; 277 scoped_ptr<base::Value> v = 278 content_settings_->GetWebsiteSettingWithoutOverride( 279 site_url_, site_url_, type, std::string(), &info); 280 content_settings_->SetNarrowestWebsiteSetting( 281 primary_pattern, secondary_pattern, type, std::string(), setting, info); 282 } else { 283 base::Value* value = NULL; 284 if (setting != CONTENT_SETTING_DEFAULT) 285 value = new base::FundamentalValue(setting); 286 content_settings_->SetWebsiteSetting( 287 primary_pattern, secondary_pattern, type, std::string(), value); 288 } 289 290 show_info_bar_ = true; 291 292 // TODO(markusheintz): This is a temporary hack to fix issue: 293 // http://crbug.com/144203. 294 #if defined(OS_MACOSX) 295 // Refresh the UI to reflect the new setting. 296 PresentSitePermissions(); 297 #endif 298 } 299 300 void WebsiteSettings::OnGotVisitCountToHost(bool found_visits, 301 int visit_count, 302 base::Time first_visit) { 303 if (!found_visits) { 304 // This indicates an error, such as the page's URL scheme wasn't 305 // http/https. 306 first_visit = base::Time(); 307 } else if (visit_count == 0) { 308 first_visit = base::Time::Now(); 309 } 310 PresentHistoryInfo(first_visit); 311 } 312 313 void WebsiteSettings::OnSiteDataAccessed() { 314 PresentSiteData(); 315 } 316 317 void WebsiteSettings::OnUIClosing() { 318 if (show_info_bar_) 319 WebsiteSettingsInfoBarDelegate::Create(infobar_service_); 320 321 SSLCertificateDecisionsDidRevoke user_decision = 322 did_revoke_user_ssl_decisions_ ? USER_CERT_DECISIONS_REVOKED 323 : USER_CERT_DECISIONS_NOT_REVOKED; 324 325 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.did_user_revoke_decisions", 326 user_decision, 327 END_OF_SSL_CERTIFICATE_DECISIONS_DID_REVOKE_ENUM); 328 } 329 330 void WebsiteSettings::OnRevokeSSLErrorBypassButtonPressed() { 331 DCHECK(chrome_ssl_host_state_delegate_); 332 chrome_ssl_host_state_delegate_->RevokeUserAllowExceptionsHard( 333 site_url().host()); 334 did_revoke_user_ssl_decisions_ = true; 335 } 336 337 void WebsiteSettings::Init(Profile* profile, 338 const GURL& url, 339 const content::SSLStatus& ssl) { 340 if (url.SchemeIs(content::kChromeUIScheme)) { 341 site_identity_status_ = SITE_IDENTITY_STATUS_INTERNAL_PAGE; 342 site_identity_details_ = 343 l10n_util::GetStringUTF16(IDS_PAGE_INFO_INTERNAL_PAGE); 344 site_connection_status_ = SITE_CONNECTION_STATUS_INTERNAL_PAGE; 345 return; 346 } 347 348 scoped_refptr<net::X509Certificate> cert; 349 350 // Identity section. 351 base::string16 subject_name(UTF8ToUTF16(url.host())); 352 if (subject_name.empty()) { 353 subject_name.assign( 354 l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURITY_TAB_UNKNOWN_PARTY)); 355 } 356 357 cert_id_ = ssl.cert_id; 358 359 if (ssl.cert_id && !ssl.signed_certificate_timestamp_ids.empty()) { 360 signed_certificate_timestamp_ids_.assign( 361 ssl.signed_certificate_timestamp_ids.begin(), 362 ssl.signed_certificate_timestamp_ids.end()); 363 } 364 365 if (ssl.cert_id && 366 cert_store_->RetrieveCert(ssl.cert_id, &cert) && 367 (!net::IsCertStatusError(ssl.cert_status) || 368 net::IsCertStatusMinorError(ssl.cert_status))) { 369 // There are no major errors. Check for minor errors. 370 #if defined(OS_CHROMEOS) 371 policy::PolicyCertService* service = 372 policy::PolicyCertServiceFactory::GetForProfile(profile); 373 const bool used_policy_certs = service && service->UsedPolicyCertificates(); 374 #else 375 const bool used_policy_certs = false; 376 #endif 377 if (used_policy_certs) { 378 site_identity_status_ = SITE_IDENTITY_STATUS_ADMIN_PROVIDED_CERT; 379 site_identity_details_ = l10n_util::GetStringFUTF16( 380 IDS_CERT_POLICY_PROVIDED_CERT_MESSAGE, UTF8ToUTF16(url.host())); 381 } else if (net::IsCertStatusMinorError(ssl.cert_status)) { 382 site_identity_status_ = SITE_IDENTITY_STATUS_CERT_REVOCATION_UNKNOWN; 383 base::string16 issuer_name(UTF8ToUTF16(cert->issuer().GetDisplayName())); 384 if (issuer_name.empty()) { 385 issuer_name.assign(l10n_util::GetStringUTF16( 386 IDS_PAGE_INFO_SECURITY_TAB_UNKNOWN_PARTY)); 387 } 388 389 site_identity_details_.assign(l10n_util::GetStringFUTF16( 390 GetSiteIdentityDetailsMessageByCTInfo( 391 ssl.signed_certificate_timestamp_ids, false /* not EV */), 392 issuer_name)); 393 394 site_identity_details_ += ASCIIToUTF16("\n\n"); 395 if (ssl.cert_status & net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION) { 396 site_identity_details_ += l10n_util::GetStringUTF16( 397 IDS_PAGE_INFO_SECURITY_TAB_UNABLE_TO_CHECK_REVOCATION); 398 } else if (ssl.cert_status & net::CERT_STATUS_NO_REVOCATION_MECHANISM) { 399 site_identity_details_ += l10n_util::GetStringUTF16( 400 IDS_PAGE_INFO_SECURITY_TAB_NO_REVOCATION_MECHANISM); 401 } else { 402 NOTREACHED() << "Need to specify string for this warning"; 403 } 404 } else { 405 if (ssl.cert_status & net::CERT_STATUS_IS_EV) { 406 // EV HTTPS page. 407 site_identity_status_ = GetSiteIdentityStatusByCTInfo( 408 ssl.signed_certificate_timestamp_ids, true); 409 DCHECK(!cert->subject().organization_names.empty()); 410 organization_name_ = UTF8ToUTF16(cert->subject().organization_names[0]); 411 // An EV Cert is required to have a city (localityName) and country but 412 // state is "if any". 413 DCHECK(!cert->subject().locality_name.empty()); 414 DCHECK(!cert->subject().country_name.empty()); 415 base::string16 locality; 416 if (!cert->subject().state_or_province_name.empty()) { 417 locality = l10n_util::GetStringFUTF16( 418 IDS_PAGEINFO_ADDRESS, 419 UTF8ToUTF16(cert->subject().locality_name), 420 UTF8ToUTF16(cert->subject().state_or_province_name), 421 UTF8ToUTF16(cert->subject().country_name)); 422 } else { 423 locality = l10n_util::GetStringFUTF16( 424 IDS_PAGEINFO_PARTIAL_ADDRESS, 425 UTF8ToUTF16(cert->subject().locality_name), 426 UTF8ToUTF16(cert->subject().country_name)); 427 } 428 DCHECK(!cert->subject().organization_names.empty()); 429 site_identity_details_.assign(l10n_util::GetStringFUTF16( 430 GetSiteIdentityDetailsMessageByCTInfo( 431 ssl.signed_certificate_timestamp_ids, true /* is EV */), 432 UTF8ToUTF16(cert->subject().organization_names[0]), 433 locality, 434 UTF8ToUTF16(cert->issuer().GetDisplayName()))); 435 } else { 436 // Non-EV OK HTTPS page. 437 site_identity_status_ = GetSiteIdentityStatusByCTInfo( 438 ssl.signed_certificate_timestamp_ids, false); 439 base::string16 issuer_name( 440 UTF8ToUTF16(cert->issuer().GetDisplayName())); 441 if (issuer_name.empty()) { 442 issuer_name.assign(l10n_util::GetStringUTF16( 443 IDS_PAGE_INFO_SECURITY_TAB_UNKNOWN_PARTY)); 444 } 445 446 site_identity_details_.assign(l10n_util::GetStringFUTF16( 447 GetSiteIdentityDetailsMessageByCTInfo( 448 ssl.signed_certificate_timestamp_ids, false /* not EV */), 449 issuer_name)); 450 } 451 // The date after which no new SHA-1 certificates may be issued. 452 // 2016-01-01 00:00:00 UTC 453 static const int64_t kSHA1LastIssuanceDate = INT64_C(13096080000000000); 454 if ((ssl.cert_status & net::CERT_STATUS_SHA1_SIGNATURE_PRESENT) && 455 cert->valid_expiry() > 456 base::Time::FromInternalValue(kSHA1LastIssuanceDate) && 457 base::FieldTrialList::FindFullName("SHA1IdentityUIWarning") == 458 "Enabled") { 459 site_identity_status_ = 460 SITE_IDENTITY_STATUS_DEPRECATED_SIGNATURE_ALGORITHM; 461 site_identity_details_ += 462 UTF8ToUTF16("\n\n") + 463 l10n_util::GetStringUTF16( 464 IDS_PAGE_INFO_SECURITY_TAB_DEPRECATED_SIGNATURE_ALGORITHM); 465 } 466 } 467 } else { 468 // HTTP or HTTPS with errors (not warnings). 469 site_identity_details_.assign(l10n_util::GetStringUTF16( 470 IDS_PAGE_INFO_SECURITY_TAB_INSECURE_IDENTITY)); 471 if (ssl.security_style == content::SECURITY_STYLE_UNAUTHENTICATED) 472 site_identity_status_ = SITE_IDENTITY_STATUS_NO_CERT; 473 else 474 site_identity_status_ = SITE_IDENTITY_STATUS_ERROR; 475 476 const base::string16 bullet = UTF8ToUTF16("\n "); 477 std::vector<SSLErrorInfo> errors; 478 SSLErrorInfo::GetErrorsForCertStatus(ssl.cert_id, ssl.cert_status, 479 url, &errors); 480 for (size_t i = 0; i < errors.size(); ++i) { 481 site_identity_details_ += bullet; 482 site_identity_details_ += errors[i].short_description(); 483 } 484 485 if (ssl.cert_status & net::CERT_STATUS_NON_UNIQUE_NAME) { 486 site_identity_details_ += ASCIIToUTF16("\n\n"); 487 site_identity_details_ += l10n_util::GetStringUTF16( 488 IDS_PAGE_INFO_SECURITY_TAB_NON_UNIQUE_NAME); 489 } 490 } 491 492 // Site Connection 493 // We consider anything less than 80 bits encryption to be weak encryption. 494 // TODO(wtc): Bug 1198735: report mixed/unsafe content for unencrypted and 495 // weakly encrypted connections. 496 site_connection_status_ = SITE_CONNECTION_STATUS_UNKNOWN; 497 498 if (ssl.security_style == content::SECURITY_STYLE_UNKNOWN) { 499 // Page is still loading, so SSL status is not yet available. Say nothing. 500 DCHECK_EQ(ssl.security_bits, -1); 501 site_connection_status_ = SITE_CONNECTION_STATUS_UNENCRYPTED; 502 503 site_connection_details_.assign(l10n_util::GetStringFUTF16( 504 IDS_PAGE_INFO_SECURITY_TAB_NOT_ENCRYPTED_CONNECTION_TEXT, 505 subject_name)); 506 } else if (ssl.security_style == content::SECURITY_STYLE_UNAUTHENTICATED) { 507 // HTTPS without a certificate, or not HTTPS. 508 DCHECK(!ssl.cert_id); 509 site_connection_status_ = SITE_CONNECTION_STATUS_UNENCRYPTED; 510 511 site_connection_details_.assign(l10n_util::GetStringFUTF16( 512 IDS_PAGE_INFO_SECURITY_TAB_NOT_ENCRYPTED_CONNECTION_TEXT, 513 subject_name)); 514 } else if (ssl.security_bits < 0) { 515 // Security strength is unknown. Say nothing. 516 site_connection_status_ = SITE_CONNECTION_STATUS_ENCRYPTED_ERROR; 517 } else if (ssl.security_bits == 0) { 518 DCHECK_NE(ssl.security_style, content::SECURITY_STYLE_UNAUTHENTICATED); 519 site_connection_status_ = SITE_CONNECTION_STATUS_ENCRYPTED_ERROR; 520 site_connection_details_.assign(l10n_util::GetStringFUTF16( 521 IDS_PAGE_INFO_SECURITY_TAB_NOT_ENCRYPTED_CONNECTION_TEXT, 522 subject_name)); 523 } else if (ssl.security_bits < 80) { 524 site_connection_status_ = SITE_CONNECTION_STATUS_ENCRYPTED_ERROR; 525 site_connection_details_.assign(l10n_util::GetStringFUTF16( 526 IDS_PAGE_INFO_SECURITY_TAB_WEAK_ENCRYPTION_CONNECTION_TEXT, 527 subject_name)); 528 } else { 529 site_connection_status_ = SITE_CONNECTION_STATUS_ENCRYPTED; 530 site_connection_details_.assign(l10n_util::GetStringFUTF16( 531 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_CONNECTION_TEXT, 532 subject_name, 533 base::IntToString16(ssl.security_bits))); 534 if (ssl.content_status) { 535 bool ran_insecure_content = 536 !!(ssl.content_status & content::SSLStatus::RAN_INSECURE_CONTENT); 537 site_connection_status_ = ran_insecure_content ? 538 SITE_CONNECTION_STATUS_ENCRYPTED_ERROR 539 : SITE_CONNECTION_STATUS_MIXED_CONTENT; 540 site_connection_details_.assign(l10n_util::GetStringFUTF16( 541 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_SENTENCE_LINK, 542 site_connection_details_, 543 l10n_util::GetStringUTF16(ran_insecure_content ? 544 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_INSECURE_CONTENT_ERROR : 545 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_INSECURE_CONTENT_WARNING))); 546 } 547 } 548 549 uint16 cipher_suite = 550 net::SSLConnectionStatusToCipherSuite(ssl.connection_status); 551 if (ssl.security_bits > 0 && cipher_suite) { 552 int ssl_version = 553 net::SSLConnectionStatusToVersion(ssl.connection_status); 554 const char* ssl_version_str; 555 net::SSLVersionToString(&ssl_version_str, ssl_version); 556 site_connection_details_ += ASCIIToUTF16("\n\n"); 557 site_connection_details_ += l10n_util::GetStringFUTF16( 558 IDS_PAGE_INFO_SECURITY_TAB_SSL_VERSION, 559 ASCIIToUTF16(ssl_version_str)); 560 561 bool no_renegotiation = 562 (ssl.connection_status & 563 net::SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION) != 0; 564 const char *key_exchange, *cipher, *mac; 565 bool is_aead; 566 net::SSLCipherSuiteToStrings( 567 &key_exchange, &cipher, &mac, &is_aead, cipher_suite); 568 569 site_connection_details_ += ASCIIToUTF16("\n\n"); 570 if (is_aead) { 571 site_connection_details_ += l10n_util::GetStringFUTF16( 572 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTION_DETAILS_AEAD, 573 ASCIIToUTF16(cipher), ASCIIToUTF16(key_exchange)); 574 } else { 575 site_connection_details_ += l10n_util::GetStringFUTF16( 576 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTION_DETAILS, 577 ASCIIToUTF16(cipher), ASCIIToUTF16(mac), ASCIIToUTF16(key_exchange)); 578 } 579 580 if (ssl_version == net::SSL_CONNECTION_VERSION_SSL3 && 581 site_connection_status_ < SITE_CONNECTION_STATUS_MIXED_CONTENT) { 582 site_connection_status_ = SITE_CONNECTION_STATUS_ENCRYPTED_ERROR; 583 } 584 585 const bool did_fallback = 586 (ssl.connection_status & net::SSL_CONNECTION_VERSION_FALLBACK) != 0; 587 if (did_fallback) { 588 site_connection_details_ += ASCIIToUTF16("\n\n"); 589 site_connection_details_ += l10n_util::GetStringUTF16( 590 IDS_PAGE_INFO_SECURITY_TAB_FALLBACK_MESSAGE); 591 } 592 593 if (no_renegotiation) { 594 site_connection_details_ += ASCIIToUTF16("\n\n"); 595 site_connection_details_ += l10n_util::GetStringUTF16( 596 IDS_PAGE_INFO_SECURITY_TAB_RENEGOTIATION_MESSAGE); 597 } 598 } 599 600 // Check if a user decision has been made to allow or deny certificates with 601 // errors on this site. 602 ChromeSSLHostStateDelegate* delegate = 603 ChromeSSLHostStateDelegateFactory::GetForProfile(profile); 604 DCHECK(delegate); 605 // Only show an SSL decision revoke button if both the user has chosen to 606 // bypass SSL host errors for this host in the past and the user is not using 607 // the traditional "forget-at-session-restart" error decision memory. 608 show_ssl_decision_revoke_button_ = delegate->HasAllowException(url.host()) && 609 InRememberCertificateErrorDecisionsGroup(); 610 611 // By default select the permissions tab that displays all the site 612 // permissions. In case of a connection error or an issue with the 613 // certificate presented by the website, select the connection tab to draw 614 // the user's attention to the issue. If the site does not provide a 615 // certificate because it was loaded over an unencrypted connection, don't 616 // select the connection tab. 617 WebsiteSettingsUI::TabId tab_id = WebsiteSettingsUI::TAB_ID_PERMISSIONS; 618 if (site_connection_status_ == SITE_CONNECTION_STATUS_ENCRYPTED_ERROR || 619 site_connection_status_ == SITE_CONNECTION_STATUS_MIXED_CONTENT || 620 site_identity_status_ == SITE_IDENTITY_STATUS_ERROR || 621 site_identity_status_ == SITE_IDENTITY_STATUS_CERT_REVOCATION_UNKNOWN || 622 site_identity_status_ == SITE_IDENTITY_STATUS_ADMIN_PROVIDED_CERT || 623 site_identity_status_ == 624 SITE_IDENTITY_STATUS_DEPRECATED_SIGNATURE_ALGORITHM) 625 tab_id = WebsiteSettingsUI::TAB_ID_CONNECTION; 626 ui_->SetSelectedTab(tab_id); 627 } 628 629 void WebsiteSettings::PresentSitePermissions() { 630 PermissionInfoList permission_info_list; 631 632 WebsiteSettingsUI::PermissionInfo permission_info; 633 for (size_t i = 0; i < arraysize(kPermissionType); ++i) { 634 permission_info.type = kPermissionType[i]; 635 if (permission_info.type == CONTENT_SETTINGS_TYPE_MIDI_SYSEX) { 636 const CommandLine* command_line = CommandLine::ForCurrentProcess(); 637 if (!command_line->HasSwitch(switches::kEnableWebMIDI)) 638 continue; 639 } 640 641 content_settings::SettingInfo info; 642 if (permission_info.type == CONTENT_SETTINGS_TYPE_MEDIASTREAM) { 643 scoped_ptr<base::Value> mic_value = 644 content_settings_->GetWebsiteSettingWithoutOverride( 645 site_url_, 646 site_url_, 647 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, 648 std::string(), 649 &info); 650 ContentSetting mic_setting = 651 content_settings::ValueToContentSetting(mic_value.get()); 652 653 scoped_ptr<base::Value> camera_value = 654 content_settings_->GetWebsiteSettingWithoutOverride( 655 site_url_, 656 site_url_, 657 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, 658 std::string(), 659 &info); 660 ContentSetting camera_setting = 661 content_settings::ValueToContentSetting(camera_value.get()); 662 663 if (mic_setting != camera_setting || mic_setting == CONTENT_SETTING_ASK) 664 permission_info.setting = CONTENT_SETTING_DEFAULT; 665 else 666 permission_info.setting = mic_setting; 667 } else { 668 scoped_ptr<base::Value> value = 669 content_settings_->GetWebsiteSettingWithoutOverride( 670 site_url_, site_url_, permission_info.type, std::string(), &info); 671 DCHECK(value.get()); 672 if (value->GetType() == base::Value::TYPE_INTEGER) { 673 permission_info.setting = 674 content_settings::ValueToContentSetting(value.get()); 675 } else { 676 NOTREACHED(); 677 } 678 } 679 680 permission_info.source = info.source; 681 682 if (info.primary_pattern == ContentSettingsPattern::Wildcard() && 683 info.secondary_pattern == ContentSettingsPattern::Wildcard() && 684 permission_info.type != CONTENT_SETTINGS_TYPE_MEDIASTREAM) { 685 permission_info.default_setting = permission_info.setting; 686 permission_info.setting = CONTENT_SETTING_DEFAULT; 687 } else { 688 permission_info.default_setting = 689 content_settings_->GetDefaultContentSetting(permission_info.type, 690 NULL); 691 } 692 permission_info_list.push_back(permission_info); 693 } 694 695 ui_->SetPermissionInfo(permission_info_list); 696 } 697 698 void WebsiteSettings::PresentSiteData() { 699 CookieInfoList cookie_info_list; 700 const LocalSharedObjectsContainer& allowed_objects = 701 tab_specific_content_settings()->allowed_local_shared_objects(); 702 const LocalSharedObjectsContainer& blocked_objects = 703 tab_specific_content_settings()->blocked_local_shared_objects(); 704 705 // Add first party cookie and site data counts. 706 WebsiteSettingsUI::CookieInfo cookie_info; 707 std::string cookie_source = 708 net::registry_controlled_domains::GetDomainAndRegistry( 709 site_url_, 710 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); 711 if (cookie_source.empty()) 712 cookie_source = site_url_.host(); 713 cookie_info.cookie_source = cookie_source; 714 cookie_info.allowed = allowed_objects.GetObjectCountForDomain(site_url_); 715 cookie_info.blocked = blocked_objects.GetObjectCountForDomain(site_url_); 716 cookie_info_list.push_back(cookie_info); 717 718 // Add third party cookie counts. 719 cookie_info.cookie_source = l10n_util::GetStringUTF8( 720 IDS_WEBSITE_SETTINGS_THIRD_PARTY_SITE_DATA); 721 cookie_info.allowed = allowed_objects.GetObjectCount() - cookie_info.allowed; 722 cookie_info.blocked = blocked_objects.GetObjectCount() - cookie_info.blocked; 723 cookie_info_list.push_back(cookie_info); 724 725 ui_->SetCookieInfo(cookie_info_list); 726 } 727 728 void WebsiteSettings::PresentSiteIdentity() { 729 // After initialization the status about the site's connection 730 // and it's identity must be available. 731 DCHECK_NE(site_identity_status_, SITE_IDENTITY_STATUS_UNKNOWN); 732 DCHECK_NE(site_connection_status_, SITE_CONNECTION_STATUS_UNKNOWN); 733 WebsiteSettingsUI::IdentityInfo info; 734 if (site_identity_status_ == SITE_IDENTITY_STATUS_EV_CERT) 735 info.site_identity = UTF16ToUTF8(organization_name()); 736 else 737 info.site_identity = site_url_.host(); 738 739 info.connection_status = site_connection_status_; 740 info.connection_status_description = 741 UTF16ToUTF8(site_connection_details_); 742 info.identity_status = site_identity_status_; 743 info.identity_status_description = 744 UTF16ToUTF8(site_identity_details_); 745 info.cert_id = cert_id_; 746 info.signed_certificate_timestamp_ids.assign( 747 signed_certificate_timestamp_ids_.begin(), 748 signed_certificate_timestamp_ids_.end()); 749 info.show_ssl_decision_revoke_button = show_ssl_decision_revoke_button_; 750 ui_->SetIdentityInfo(info); 751 } 752 753 void WebsiteSettings::PresentHistoryInfo(base::Time first_visit) { 754 if (first_visit == base::Time()) { 755 ui_->SetFirstVisit(base::string16()); 756 return; 757 } 758 759 bool visited_before_today = false; 760 base::Time today = base::Time::Now().LocalMidnight(); 761 base::Time first_visit_midnight = first_visit.LocalMidnight(); 762 visited_before_today = (first_visit_midnight < today); 763 764 base::string16 first_visit_text; 765 if (visited_before_today) { 766 first_visit_text = l10n_util::GetStringFUTF16( 767 IDS_PAGE_INFO_SECURITY_TAB_VISITED_BEFORE_TODAY, 768 base::TimeFormatShortDate(first_visit)); 769 } else { 770 first_visit_text = l10n_util::GetStringUTF16( 771 IDS_PAGE_INFO_SECURITY_TAB_FIRST_VISITED_TODAY); 772 } 773 ui_->SetFirstVisit(first_visit_text); 774 } 775