Home | History | Annotate | Download | only in website_settings
      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