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