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