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