blob: bdb6dd098c6757e2b0cdea4f3ba38ca1e977880f [file] [log] [blame]
[email protected]03ef4b2a2012-03-06 15:04:201// 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
[email protected]4237dd52012-06-05 00:00:325#include "chrome/browser/ui/website_settings/website_settings.h"
[email protected]03ef4b2a2012-03-06 15:04:206
7#include <string>
8#include <vector>
9
[email protected]15b092542012-05-16 13:08:1410#include "base/bind.h"
11#include "base/bind_helpers.h"
[email protected]eb2140c2013-07-29 12:37:3412#include "base/command_line.h"
[email protected]15b092542012-05-16 13:08:1413#include "base/i18n/time_formatting.h"
[email protected]71cd5ef2014-08-13 21:22:0414#include "base/metrics/field_trial.h"
[email protected]3ea1b182013-02-08 22:38:4115#include "base/metrics/histogram.h"
16#include "base/strings/string_number_conversions.h"
[email protected]774cc3c2013-06-07 20:26:4517#include "base/strings/utf_string_conversions.h"
[email protected]0b9fdd72012-04-04 10:00:3318#include "base/values.h"
[email protected]6b8a3c742014-07-25 00:25:3519#include "chrome/browser/browsing_data/browsing_data_channel_id_helper.h"
[email protected]b0cb5e82012-07-19 19:22:4720#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"
[email protected]0b9fdd72012-04-04 10:00:3325#include "chrome/browser/content_settings/content_settings_utils.h"
26#include "chrome/browser/content_settings/host_content_settings_map.h"
[email protected]df818272012-04-20 13:10:5027#include "chrome/browser/content_settings/local_shared_objects_container.h"
[email protected]77a91c72012-08-13 16:19:3428#include "chrome/browser/history/history_service_factory.h"
[email protected]03ef4b2a2012-03-06 15:04:2029#include "chrome/browser/profiles/profile.h"
[email protected]71cd5ef2014-08-13 21:22:0430#include "chrome/browser/ssl/chrome_ssl_host_state_delegate.h"
31#include "chrome/browser/ssl/chrome_ssl_host_state_delegate_factory.h"
[email protected]03ef4b2a2012-03-06 15:04:2032#include "chrome/browser/ssl/ssl_error_info.h"
[email protected]66f157312012-08-01 13:50:2633#include "chrome/browser/ui/website_settings/website_settings_infobar_delegate.h"
[email protected]4237dd52012-06-05 00:00:3234#include "chrome/browser/ui/website_settings/website_settings_ui.h"
[email protected]71cd5ef2014-08-13 21:22:0435#include "chrome/common/chrome_switches.h"
[email protected]0b9fdd72012-04-04 10:00:3336#include "chrome/common/content_settings_pattern.h"
37#include "content/public/browser/browser_thread.h"
[email protected]b59c6cf02012-03-12 20:51:4238#include "content/public/browser/cert_store.h"
[email protected]e22d64f2012-09-10 09:03:2339#include "content/public/browser/user_metrics.h"
[email protected]eb2140c2013-07-29 12:37:3440#include "content/public/common/content_switches.h"
[email protected]03ef4b2a2012-03-06 15:04:2041#include "content/public/common/ssl_status.h"
42#include "content/public/common/url_constants.h"
43#include "grit/chromium_strings.h"
44#include "grit/generated_resources.h"
[email protected]be28b5f42012-07-20 11:31:2545#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
[email protected]6e7845ae2013-03-29 21:48:1146#include "net/cert/cert_status_flags.h"
47#include "net/cert/x509_certificate.h"
[email protected]536fd0b2013-03-14 17:41:5748#include "net/ssl/ssl_cipher_suite_names.h"
49#include "net/ssl/ssl_connection_status_flags.h"
[email protected]03ef4b2a2012-03-06 15:04:2050#include "ui/base/l10n/l10n_util.h"
[email protected]03ef4b2a2012-03-06 15:04:2051
[email protected]24a9f1c92013-11-13 12:33:3752#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
[email protected]ab6df3b12013-12-24 23:32:2657using base::ASCIIToUTF16;
58using base::UTF8ToUTF16;
[email protected]f729d7a2013-12-26 07:07:5659using base::UTF16ToUTF8;
[email protected]0b9fdd72012-04-04 10:00:3360using content::BrowserThread;
61
62namespace {
63
[email protected]b1d113d2012-06-27 21:27:3464// The list of content settings types to display on the Website Settings UI.
[email protected]0b9fdd72012-04-04 10:00:3365ContentSettingsType kPermissionType[] = {
[email protected]b1d113d2012-06-27 21:27:3466 CONTENT_SETTINGS_TYPE_IMAGES,
67 CONTENT_SETTINGS_TYPE_JAVASCRIPT,
[email protected]0b9fdd72012-04-04 10:00:3368 CONTENT_SETTINGS_TYPE_PLUGINS,
[email protected]b1d113d2012-06-27 21:27:3469 CONTENT_SETTINGS_TYPE_POPUPS,
[email protected]0b9fdd72012-04-04 10:00:3370 CONTENT_SETTINGS_TYPE_GEOLOCATION,
[email protected]b1d113d2012-06-27 21:27:3471 CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
72 CONTENT_SETTINGS_TYPE_FULLSCREEN,
73 CONTENT_SETTINGS_TYPE_MOUSELOCK,
74 CONTENT_SETTINGS_TYPE_MEDIASTREAM,
[email protected]62167c12013-07-10 23:02:0875 CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS,
[email protected]eb2140c2013-07-29 12:37:3476 CONTENT_SETTINGS_TYPE_MIDI_SYSEX,
[email protected]0b9fdd72012-04-04 10:00:3377};
78
[email protected]94c74b42013-12-02 15:19:4979bool CertificateTransparencyStatusMatch(
80 const content::SignedCertificateTimestampIDStatusList& scts,
81 net::ct::SCTVerifyStatus status) {
82 for (content::SignedCertificateTimestampIDStatusList::const_iterator it =
83 scts.begin();
84 it != scts.end();
85 ++it) {
86 if (it->status == status)
87 return true;
88 }
89
90 return false;
91}
92
93int GetSiteIdentityDetailsMessageByCTInfo(
94 const content::SignedCertificateTimestampIDStatusList& scts,
95 bool is_ev) {
96 // No SCTs - no CT information.
97 if (scts.empty())
98 return (is_ev ? IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY_EV_NO_CT
99 : IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY_NO_CT);
100
101 if (CertificateTransparencyStatusMatch(scts, net::ct::SCT_STATUS_OK))
102 return (is_ev ? IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY_EV_CT_VERIFIED
103 : IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY_CT_VERIFIED);
104
105 if (CertificateTransparencyStatusMatch(scts, net::ct::SCT_STATUS_INVALID))
106 return (is_ev ? IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY_EV_CT_INVALID
107 : IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY_CT_INVALID);
108
109 // status is SCT_STATUS_LOG_UNKNOWN
110 return (is_ev ? IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY_EV_CT_UNVERIFIED
111 : IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY_CT_UNVERIFIED);
112}
113
114// This function will return SITE_IDENTITY_STATUS_CERT or
115// SITE_IDENTITY_STATUS_EV_CERT depending on |is_ev| unless there are SCTs
116// which failed verification, in which case it will return
117// SITE_IDENTITY_STATUS_ERROR.
118WebsiteSettings::SiteIdentityStatus GetSiteIdentityStatusByCTInfo(
119 const content::SignedCertificateTimestampIDStatusList& scts,
120 bool is_ev) {
121 if (CertificateTransparencyStatusMatch(scts, net::ct::SCT_STATUS_INVALID))
122 return WebsiteSettings::SITE_IDENTITY_STATUS_ERROR;
123
124 return is_ev ? WebsiteSettings::SITE_IDENTITY_STATUS_EV_CERT
125 : WebsiteSettings::SITE_IDENTITY_STATUS_CERT;
126}
127
[email protected]71cd5ef2014-08-13 21:22:04128const char kRememberCertificateErrorDecisionsFieldTrialName[] =
129 "RememberCertificateErrorDecisions";
130const char kRememberCertificateErrorDecisionsFieldTrialDefaultGroup[] =
131 "Default";
132const char kRememberCertificateErrorDecisionsFieldTrialDisableGroup[] =
133 "Disable";
134// Returns true if the user is in the experimental group or has the flag enabled
135// for remembering SSL error decisions, otherwise false.
136//
137// TODO(jww): The field trial is scheduled to end 2015/02/28. This should be
138// removed at that point unless the field trial or flag continues.
139bool InRememberCertificateErrorDecisionsGroup() {
140 std::string group_name = base::FieldTrialList::FindFullName(
141 kRememberCertificateErrorDecisionsFieldTrialName);
142
143 // The Default and Disable groups are the "old-style" forget-at-session
144 // restart groups, so they do not get the button.
145 bool in_experimental_group = !group_name.empty() &&
146 group_name.compare(
147 kRememberCertificateErrorDecisionsFieldTrialDefaultGroup) != 0 &&
148 group_name.compare(
149 kRememberCertificateErrorDecisionsFieldTrialDisableGroup) != 0;
150 bool has_command_line_switch = CommandLine::ForCurrentProcess()->HasSwitch(
151 switches::kRememberCertErrorDecisions);
152 return in_experimental_group || has_command_line_switch;
153}
154
[email protected]0b9fdd72012-04-04 10:00:33155} // namespace
156
157WebsiteSettings::WebsiteSettings(
158 WebsiteSettingsUI* ui,
159 Profile* profile,
[email protected]df818272012-04-20 13:10:50160 TabSpecificContentSettings* tab_specific_content_settings,
[email protected]4f822f022012-12-20 19:11:42161 InfoBarService* infobar_service,
[email protected]0b9fdd72012-04-04 10:00:33162 const GURL& url,
163 const content::SSLStatus& ssl,
164 content::CertStore* cert_store)
[email protected]df818272012-04-20 13:10:50165 : TabSpecificContentSettings::SiteDataObserver(
166 tab_specific_content_settings),
167 ui_(ui),
[email protected]4f822f022012-12-20 19:11:42168 infobar_service_(infobar_service),
[email protected]66f157312012-08-01 13:50:26169 show_info_bar_(false),
[email protected]0b9fdd72012-04-04 10:00:33170 site_url_(url),
171 site_identity_status_(SITE_IDENTITY_STATUS_UNKNOWN),
[email protected]f61c1ce2012-05-09 13:55:11172 cert_id_(0),
[email protected]03ef4b2a2012-03-06 15:04:20173 site_connection_status_(SITE_CONNECTION_STATUS_UNKNOWN),
[email protected]0b9fdd72012-04-04 10:00:33174 cert_store_(cert_store),
[email protected]71cd5ef2014-08-13 21:22:04175 content_settings_(profile->GetHostContentSettingsMap()),
176 chrome_ssl_host_state_delegate_(
177 ChromeSSLHostStateDelegateFactory::GetForProfile(profile)) {
[email protected]03ef4b2a2012-03-06 15:04:20178 Init(profile, url, ssl);
[email protected]0b9fdd72012-04-04 10:00:33179
[email protected]78a1fd90a2012-07-19 08:11:25180 HistoryService* history_service = HistoryServiceFactory::GetForProfile(
181 profile, Profile::EXPLICIT_ACCESS);
[email protected]15b092542012-05-16 13:08:14182 if (history_service) {
183 history_service->GetVisibleVisitCountToHost(
184 site_url_,
[email protected]15b092542012-05-16 13:08:14185 base::Bind(&WebsiteSettings::OnGotVisitCountToHost,
[email protected]e800fe742014-07-01 10:38:19186 base::Unretained(this)),
187 &visit_count_task_tracker_);
[email protected]15b092542012-05-16 13:08:14188 }
189
[email protected]0b9fdd72012-04-04 10:00:33190 PresentSitePermissions();
[email protected]df818272012-04-20 13:10:50191 PresentSiteData();
[email protected]24c8818c2012-04-25 09:57:41192 PresentSiteIdentity();
[email protected]15b092542012-05-16 13:08:14193 PresentHistoryInfo(base::Time());
[email protected]e22d64f2012-09-10 09:03:23194
195 // Every time the Website Settings UI is opened a |WebsiteSettings| object is
196 // created. So this counts how ofter the Website Settings UI is opened.
[email protected]e6e30ac2014-01-13 21:24:39197 content::RecordAction(base::UserMetricsAction("WebsiteSettings_Opened"));
[email protected]03ef4b2a2012-03-06 15:04:20198}
199
[email protected]0b9fdd72012-04-04 10:00:33200WebsiteSettings::~WebsiteSettings() {
[email protected]03ef4b2a2012-03-06 15:04:20201}
202
[email protected]df818272012-04-20 13:10:50203void WebsiteSettings::OnSitePermissionChanged(ContentSettingsType type,
204 ContentSetting setting) {
[email protected]e22d64f2012-09-10 09:03:23205 // Count how often a permission for a specific content type is changed using
206 // the Website Settings UI.
207 UMA_HISTOGRAM_COUNTS("WebsiteSettings.PermissionChanged", type);
208
[email protected]df818272012-04-20 13:10:50209 ContentSettingsPattern primary_pattern;
210 ContentSettingsPattern secondary_pattern;
211 switch (type) {
212 case CONTENT_SETTINGS_TYPE_GEOLOCATION:
[email protected]eb2140c2013-07-29 12:37:34213 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
[email protected]df818272012-04-20 13:10:50214 // TODO(markusheintz): The rule we create here should also change the
215 // location permission for iframed content.
216 primary_pattern = ContentSettingsPattern::FromURLNoWildcard(site_url_);
217 secondary_pattern = ContentSettingsPattern::FromURLNoWildcard(site_url_);
218 break;
219 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
220 primary_pattern = ContentSettingsPattern::FromURLNoWildcard(site_url_);
221 secondary_pattern = ContentSettingsPattern::Wildcard();
222 break;
[email protected]b1d113d2012-06-27 21:27:34223 case CONTENT_SETTINGS_TYPE_IMAGES:
224 case CONTENT_SETTINGS_TYPE_JAVASCRIPT:
[email protected]df818272012-04-20 13:10:50225 case CONTENT_SETTINGS_TYPE_PLUGINS:
226 case CONTENT_SETTINGS_TYPE_POPUPS:
[email protected]b1d113d2012-06-27 21:27:34227 case CONTENT_SETTINGS_TYPE_FULLSCREEN:
228 case CONTENT_SETTINGS_TYPE_MOUSELOCK:
[email protected]ad635b12013-07-22 21:53:27229 case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS:
[email protected]df818272012-04-20 13:10:50230 primary_pattern = ContentSettingsPattern::FromURL(site_url_);
231 secondary_pattern = ContentSettingsPattern::Wildcard();
232 break;
[email protected]0bacc1912012-12-11 11:05:34233 case CONTENT_SETTINGS_TYPE_MEDIASTREAM: {
234 // We need to use the same same patterns as other places like infobar code
235 // to override the existing rule instead of creating the new one.
236 primary_pattern = ContentSettingsPattern::FromURLNoWildcard(site_url_);
237 secondary_pattern = ContentSettingsPattern::Wildcard();
238 // Set permission for both microphone and camera.
239 content_settings_->SetContentSetting(
[email protected]007b3f82013-04-09 08:46:45240 primary_pattern,
241 secondary_pattern,
242 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
243 std::string(),
244 setting);
[email protected]0bacc1912012-12-11 11:05:34245
246 content_settings_->SetContentSetting(
[email protected]007b3f82013-04-09 08:46:45247 primary_pattern,
248 secondary_pattern,
249 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
250 std::string(),
251 setting);
[email protected]0bacc1912012-12-11 11:05:34252 break;
253 }
[email protected]df818272012-04-20 13:10:50254 default:
255 NOTREACHED() << "ContentSettingsType " << type << "is not supported.";
256 break;
[email protected]0b9fdd72012-04-04 10:00:33257 }
258
[email protected]0bacc1912012-12-11 11:05:34259 if (type != CONTENT_SETTINGS_TYPE_MEDIASTREAM) {
260 // Permission settings are specified via rules. There exists always at least
261 // one rule for the default setting. Get the rule that currently defines
262 // the permission for the given permission |type|. Then test whether the
263 // existing rule is more specific than the rule we are about to create. If
264 // the existing rule is more specific, than change the existing rule instead
265 // of creating a new rule that would be hidden behind the existing rule.
266 // This is not a concern for CONTENT_SETTINGS_TYPE_MEDIASTREAM since users
267 // can not create media settings exceptions by hand.
268 content_settings::SettingInfo info;
[email protected]2c95d102013-12-23 20:42:16269 scoped_ptr<base::Value> v(content_settings_->GetWebsiteSetting(
[email protected]007b3f82013-04-09 08:46:45270 site_url_, site_url_, type, std::string(), &info));
[email protected]0bacc1912012-12-11 11:05:34271 DCHECK(info.source == content_settings::SETTING_SOURCE_USER);
272 ContentSettingsPattern::Relation r1 =
273 info.primary_pattern.Compare(primary_pattern);
274 DCHECK(r1 != ContentSettingsPattern::DISJOINT_ORDER_POST &&
275 r1 != ContentSettingsPattern::DISJOINT_ORDER_PRE);
276 if (r1 == ContentSettingsPattern::PREDECESSOR) {
277 primary_pattern = info.primary_pattern;
278 } else if (r1 == ContentSettingsPattern::IDENTITY) {
279 ContentSettingsPattern::Relation r2 =
280 info.secondary_pattern.Compare(secondary_pattern);
281 DCHECK(r2 != ContentSettingsPattern::DISJOINT_ORDER_POST &&
282 r2 != ContentSettingsPattern::DISJOINT_ORDER_PRE);
283 if (r2 == ContentSettingsPattern::PREDECESSOR)
284 secondary_pattern = info.secondary_pattern;
285 }
286
[email protected]2c95d102013-12-23 20:42:16287 base::Value* value = NULL;
[email protected]0bacc1912012-12-11 11:05:34288 if (setting != CONTENT_SETTING_DEFAULT)
[email protected]a7965a42014-07-22 02:35:56289 value = new base::FundamentalValue(setting);
[email protected]0bacc1912012-12-11 11:05:34290 content_settings_->SetWebsiteSetting(
[email protected]007b3f82013-04-09 08:46:45291 primary_pattern, secondary_pattern, type, std::string(), value);
[email protected]df818272012-04-20 13:10:50292 }
293
[email protected]66f157312012-08-01 13:50:26294 show_info_bar_ = true;
[email protected]2f45d542012-08-22 08:47:24295
[email protected]76955932012-12-06 11:01:10296// TODO(markusheintz): This is a temporary hack to fix issue:
297// http://crbug.com/144203.
[email protected]e379ba42012-08-22 22:40:25298#if defined(OS_MACOSX)
[email protected]2f45d542012-08-22 08:47:24299 // Refresh the UI to reflect the new setting.
300 PresentSitePermissions();
[email protected]e379ba42012-08-22 22:40:25301#endif
[email protected]df818272012-04-20 13:10:50302}
303
[email protected]e800fe742014-07-01 10:38:19304void WebsiteSettings::OnGotVisitCountToHost(bool found_visits,
[email protected]15b092542012-05-16 13:08:14305 int visit_count,
306 base::Time first_visit) {
307 if (!found_visits) {
308 // This indicates an error, such as the page's URL scheme wasn't
309 // http/https.
310 first_visit = base::Time();
311 } else if (visit_count == 0) {
312 first_visit = base::Time::Now();
313 }
314 PresentHistoryInfo(first_visit);
315}
316
[email protected]df818272012-04-20 13:10:50317void WebsiteSettings::OnSiteDataAccessed() {
318 PresentSiteData();
[email protected]0b9fdd72012-04-04 10:00:33319}
320
[email protected]66f157312012-08-01 13:50:26321void WebsiteSettings::OnUIClosing() {
[email protected]0be09932013-01-08 02:03:50322 if (show_info_bar_)
[email protected]ed9bc652013-07-11 17:17:36323 WebsiteSettingsInfoBarDelegate::Create(infobar_service_);
[email protected]66f157312012-08-01 13:50:26324}
325
[email protected]0b9fdd72012-04-04 10:00:33326void WebsiteSettings::Init(Profile* profile,
327 const GURL& url,
328 const content::SSLStatus& ssl) {
[email protected]2d9748b22014-02-11 00:17:29329 if (url.SchemeIs(content::kChromeUIScheme)) {
[email protected]03ef4b2a2012-03-06 15:04:20330 site_identity_status_ = SITE_IDENTITY_STATUS_INTERNAL_PAGE;
331 site_identity_details_ =
332 l10n_util::GetStringUTF16(IDS_PAGE_INFO_INTERNAL_PAGE);
333 site_connection_status_ = SITE_CONNECTION_STATUS_INTERNAL_PAGE;
334 return;
335 }
336
337 scoped_refptr<net::X509Certificate> cert;
338
339 // Identity section.
[email protected]a04db822013-12-11 19:14:40340 base::string16 subject_name(UTF8ToUTF16(url.host()));
[email protected]03ef4b2a2012-03-06 15:04:20341 if (subject_name.empty()) {
342 subject_name.assign(
343 l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURITY_TAB_UNKNOWN_PARTY));
[email protected]03ef4b2a2012-03-06 15:04:20344 }
345
[email protected]f61c1ce2012-05-09 13:55:11346 cert_id_ = ssl.cert_id;
347
[email protected]3d6d34b12013-12-23 00:34:02348 if (ssl.cert_id && !ssl.signed_certificate_timestamp_ids.empty()) {
349 signed_certificate_timestamp_ids_.assign(
350 ssl.signed_certificate_timestamp_ids.begin(),
351 ssl.signed_certificate_timestamp_ids.end());
352 }
353
[email protected]03ef4b2a2012-03-06 15:04:20354 if (ssl.cert_id &&
355 cert_store_->RetrieveCert(ssl.cert_id, &cert) &&
356 (!net::IsCertStatusError(ssl.cert_status) ||
357 net::IsCertStatusMinorError(ssl.cert_status))) {
358 // There are no major errors. Check for minor errors.
[email protected]24a9f1c92013-11-13 12:33:37359#if defined(OS_CHROMEOS)
360 policy::PolicyCertService* service =
361 policy::PolicyCertServiceFactory::GetForProfile(profile);
362 const bool used_policy_certs = service && service->UsedPolicyCertificates();
363#else
364 const bool used_policy_certs = false;
365#endif
366 if (used_policy_certs) {
[email protected]eaf3f322013-04-25 21:53:59367 site_identity_status_ = SITE_IDENTITY_STATUS_ADMIN_PROVIDED_CERT;
[email protected]24a9f1c92013-11-13 12:33:37368 site_identity_details_ = l10n_util::GetStringFUTF16(
369 IDS_CERT_POLICY_PROVIDED_CERT_MESSAGE, UTF8ToUTF16(url.host()));
[email protected]eaf3f322013-04-25 21:53:59370 } else if (net::IsCertStatusMinorError(ssl.cert_status)) {
[email protected]03ef4b2a2012-03-06 15:04:20371 site_identity_status_ = SITE_IDENTITY_STATUS_CERT_REVOCATION_UNKNOWN;
[email protected]a04db822013-12-11 19:14:40372 base::string16 issuer_name(UTF8ToUTF16(cert->issuer().GetDisplayName()));
[email protected]03ef4b2a2012-03-06 15:04:20373 if (issuer_name.empty()) {
374 issuer_name.assign(l10n_util::GetStringUTF16(
375 IDS_PAGE_INFO_SECURITY_TAB_UNKNOWN_PARTY));
376 }
[email protected]94c74b42013-12-02 15:19:49377
[email protected]03ef4b2a2012-03-06 15:04:20378 site_identity_details_.assign(l10n_util::GetStringFUTF16(
[email protected]94c74b42013-12-02 15:19:49379 GetSiteIdentityDetailsMessageByCTInfo(
380 ssl.signed_certificate_timestamp_ids, false /* not EV */),
381 issuer_name));
[email protected]03ef4b2a2012-03-06 15:04:20382
383 site_identity_details_ += ASCIIToUTF16("\n\n");
384 if (ssl.cert_status & net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION) {
385 site_identity_details_ += l10n_util::GetStringUTF16(
386 IDS_PAGE_INFO_SECURITY_TAB_UNABLE_TO_CHECK_REVOCATION);
387 } else if (ssl.cert_status & net::CERT_STATUS_NO_REVOCATION_MECHANISM) {
388 site_identity_details_ += l10n_util::GetStringUTF16(
389 IDS_PAGE_INFO_SECURITY_TAB_NO_REVOCATION_MECHANISM);
390 } else {
391 NOTREACHED() << "Need to specify string for this warning";
392 }
393 } else if (ssl.cert_status & net::CERT_STATUS_IS_EV) {
394 // EV HTTPS page.
[email protected]94c74b42013-12-02 15:19:49395 site_identity_status_ = GetSiteIdentityStatusByCTInfo(
396 ssl.signed_certificate_timestamp_ids, true);
[email protected]03ef4b2a2012-03-06 15:04:20397 DCHECK(!cert->subject().organization_names.empty());
398 organization_name_ = UTF8ToUTF16(cert->subject().organization_names[0]);
399 // An EV Cert is required to have a city (localityName) and country but
400 // state is "if any".
401 DCHECK(!cert->subject().locality_name.empty());
402 DCHECK(!cert->subject().country_name.empty());
[email protected]a04db822013-12-11 19:14:40403 base::string16 locality;
[email protected]03ef4b2a2012-03-06 15:04:20404 if (!cert->subject().state_or_province_name.empty()) {
405 locality = l10n_util::GetStringFUTF16(
406 IDS_PAGEINFO_ADDRESS,
407 UTF8ToUTF16(cert->subject().locality_name),
408 UTF8ToUTF16(cert->subject().state_or_province_name),
409 UTF8ToUTF16(cert->subject().country_name));
410 } else {
411 locality = l10n_util::GetStringFUTF16(
412 IDS_PAGEINFO_PARTIAL_ADDRESS,
413 UTF8ToUTF16(cert->subject().locality_name),
414 UTF8ToUTF16(cert->subject().country_name));
415 }
416 DCHECK(!cert->subject().organization_names.empty());
417 site_identity_details_.assign(l10n_util::GetStringFUTF16(
[email protected]94c74b42013-12-02 15:19:49418 GetSiteIdentityDetailsMessageByCTInfo(
419 ssl.signed_certificate_timestamp_ids, true /* is EV */),
[email protected]03ef4b2a2012-03-06 15:04:20420 UTF8ToUTF16(cert->subject().organization_names[0]),
421 locality,
422 UTF8ToUTF16(cert->issuer().GetDisplayName())));
[email protected]03ef4b2a2012-03-06 15:04:20423 } else {
424 // Non-EV OK HTTPS page.
[email protected]94c74b42013-12-02 15:19:49425 site_identity_status_ = GetSiteIdentityStatusByCTInfo(
426 ssl.signed_certificate_timestamp_ids, false);
[email protected]a04db822013-12-11 19:14:40427 base::string16 issuer_name(UTF8ToUTF16(cert->issuer().GetDisplayName()));
[email protected]03ef4b2a2012-03-06 15:04:20428 if (issuer_name.empty()) {
429 issuer_name.assign(l10n_util::GetStringUTF16(
430 IDS_PAGE_INFO_SECURITY_TAB_UNKNOWN_PARTY));
431 }
[email protected]94c74b42013-12-02 15:19:49432
[email protected]03ef4b2a2012-03-06 15:04:20433 site_identity_details_.assign(l10n_util::GetStringFUTF16(
[email protected]94c74b42013-12-02 15:19:49434 GetSiteIdentityDetailsMessageByCTInfo(
435 ssl.signed_certificate_timestamp_ids, false /* not EV */),
436 issuer_name));
[email protected]03ef4b2a2012-03-06 15:04:20437 }
438 } else {
439 // HTTP or HTTPS with errors (not warnings).
440 site_identity_details_.assign(l10n_util::GetStringUTF16(
441 IDS_PAGE_INFO_SECURITY_TAB_INSECURE_IDENTITY));
442 if (ssl.security_style == content::SECURITY_STYLE_UNAUTHENTICATED)
443 site_identity_status_ = SITE_IDENTITY_STATUS_NO_CERT;
444 else
445 site_identity_status_ = SITE_IDENTITY_STATUS_ERROR;
446
[email protected]a04db822013-12-11 19:14:40447 const base::string16 bullet = UTF8ToUTF16("\n • ");
[email protected]03ef4b2a2012-03-06 15:04:20448 std::vector<SSLErrorInfo> errors;
449 SSLErrorInfo::GetErrorsForCertStatus(ssl.cert_id, ssl.cert_status,
450 url, &errors);
451 for (size_t i = 0; i < errors.size(); ++i) {
452 site_identity_details_ += bullet;
453 site_identity_details_ += errors[i].short_description();
454 }
455
456 if (ssl.cert_status & net::CERT_STATUS_NON_UNIQUE_NAME) {
457 site_identity_details_ += ASCIIToUTF16("\n\n");
458 site_identity_details_ += l10n_util::GetStringUTF16(
459 IDS_PAGE_INFO_SECURITY_TAB_NON_UNIQUE_NAME);
460 }
461 }
462
463 // Site Connection
464 // We consider anything less than 80 bits encryption to be weak encryption.
465 // TODO(wtc): Bug 1198735: report mixed/unsafe content for unencrypted and
466 // weakly encrypted connections.
467 site_connection_status_ = SITE_CONNECTION_STATUS_UNKNOWN;
468
[email protected]1c1051d2014-05-10 11:39:58469 if (ssl.security_style == content::SECURITY_STYLE_UNKNOWN) {
470 // Page is still loading, so SSL status is not yet available. Say nothing.
471 DCHECK_EQ(ssl.security_bits, -1);
472 site_connection_status_ = SITE_CONNECTION_STATUS_UNENCRYPTED;
473
474 site_connection_details_.assign(l10n_util::GetStringFUTF16(
475 IDS_PAGE_INFO_SECURITY_TAB_NOT_ENCRYPTED_CONNECTION_TEXT,
476 subject_name));
477 } else if (ssl.security_style == content::SECURITY_STYLE_UNAUTHENTICATED) {
478 // HTTPS without a certificate, or not HTTPS.
479 DCHECK(!ssl.cert_id);
480 site_connection_status_ = SITE_CONNECTION_STATUS_UNENCRYPTED;
[email protected]03ef4b2a2012-03-06 15:04:20481
482 site_connection_details_.assign(l10n_util::GetStringFUTF16(
483 IDS_PAGE_INFO_SECURITY_TAB_NOT_ENCRYPTED_CONNECTION_TEXT,
484 subject_name));
485 } else if (ssl.security_bits < 0) {
486 // Security strength is unknown. Say nothing.
487 site_connection_status_ = SITE_CONNECTION_STATUS_ENCRYPTED_ERROR;
488 } else if (ssl.security_bits == 0) {
489 DCHECK_NE(ssl.security_style, content::SECURITY_STYLE_UNAUTHENTICATED);
490 site_connection_status_ = SITE_CONNECTION_STATUS_ENCRYPTED_ERROR;
491 site_connection_details_.assign(l10n_util::GetStringFUTF16(
492 IDS_PAGE_INFO_SECURITY_TAB_NOT_ENCRYPTED_CONNECTION_TEXT,
493 subject_name));
494 } else if (ssl.security_bits < 80) {
495 site_connection_status_ = SITE_CONNECTION_STATUS_ENCRYPTED_ERROR;
496 site_connection_details_.assign(l10n_util::GetStringFUTF16(
497 IDS_PAGE_INFO_SECURITY_TAB_WEAK_ENCRYPTION_CONNECTION_TEXT,
498 subject_name));
499 } else {
500 site_connection_status_ = SITE_CONNECTION_STATUS_ENCRYPTED;
501 site_connection_details_.assign(l10n_util::GetStringFUTF16(
502 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_CONNECTION_TEXT,
503 subject_name,
504 base::IntToString16(ssl.security_bits)));
505 if (ssl.content_status) {
506 bool ran_insecure_content =
507 !!(ssl.content_status & content::SSLStatus::RAN_INSECURE_CONTENT);
508 site_connection_status_ = ran_insecure_content ?
509 SITE_CONNECTION_STATUS_ENCRYPTED_ERROR
510 : SITE_CONNECTION_STATUS_MIXED_CONTENT;
511 site_connection_details_.assign(l10n_util::GetStringFUTF16(
512 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_SENTENCE_LINK,
513 site_connection_details_,
514 l10n_util::GetStringUTF16(ran_insecure_content ?
515 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_INSECURE_CONTENT_ERROR :
516 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_INSECURE_CONTENT_WARNING)));
517 }
518 }
519
520 uint16 cipher_suite =
521 net::SSLConnectionStatusToCipherSuite(ssl.connection_status);
522 if (ssl.security_bits > 0 && cipher_suite) {
523 int ssl_version =
524 net::SSLConnectionStatusToVersion(ssl.connection_status);
525 const char* ssl_version_str;
526 net::SSLVersionToString(&ssl_version_str, ssl_version);
527 site_connection_details_ += ASCIIToUTF16("\n\n");
528 site_connection_details_ += l10n_util::GetStringFUTF16(
529 IDS_PAGE_INFO_SECURITY_TAB_SSL_VERSION,
530 ASCIIToUTF16(ssl_version_str));
531
532 bool did_fallback = (ssl.connection_status &
[email protected]80c75f682012-05-26 16:22:17533 net::SSL_CONNECTION_VERSION_FALLBACK) != 0;
[email protected]03ef4b2a2012-03-06 15:04:20534 bool no_renegotiation =
535 (ssl.connection_status &
536 net::SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION) != 0;
537 const char *key_exchange, *cipher, *mac;
[email protected]b6c1d9e82013-06-12 17:26:57538 bool is_aead;
539 net::SSLCipherSuiteToStrings(
540 &key_exchange, &cipher, &mac, &is_aead, cipher_suite);
[email protected]03ef4b2a2012-03-06 15:04:20541
542 site_connection_details_ += ASCIIToUTF16("\n\n");
[email protected]b6c1d9e82013-06-12 17:26:57543 if (is_aead) {
544 site_connection_details_ += l10n_util::GetStringFUTF16(
545 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTION_DETAILS_AEAD,
546 ASCIIToUTF16(cipher), ASCIIToUTF16(key_exchange));
547 } else {
548 site_connection_details_ += l10n_util::GetStringFUTF16(
549 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTION_DETAILS,
550 ASCIIToUTF16(cipher), ASCIIToUTF16(mac), ASCIIToUTF16(key_exchange));
551 }
[email protected]03ef4b2a2012-03-06 15:04:20552
[email protected]03ef4b2a2012-03-06 15:04:20553 if (did_fallback) {
554 // For now, only SSLv3 fallback will trigger a warning icon.
555 if (site_connection_status_ < SITE_CONNECTION_STATUS_MIXED_CONTENT)
556 site_connection_status_ = SITE_CONNECTION_STATUS_MIXED_CONTENT;
557 site_connection_details_ += ASCIIToUTF16("\n\n");
558 site_connection_details_ += l10n_util::GetStringUTF16(
559 IDS_PAGE_INFO_SECURITY_TAB_FALLBACK_MESSAGE);
560 }
561 if (no_renegotiation) {
562 site_connection_details_ += ASCIIToUTF16("\n\n");
563 site_connection_details_ += l10n_util::GetStringUTF16(
564 IDS_PAGE_INFO_SECURITY_TAB_RENEGOTIATION_MESSAGE);
565 }
566 }
[email protected]e583f752012-08-30 13:26:21567
[email protected]71cd5ef2014-08-13 21:22:04568 // Check if a user decision has been made to allow or deny certificates with
569 // errors on this site.
570 ChromeSSLHostStateDelegate* delegate =
571 ChromeSSLHostStateDelegateFactory::GetForProfile(profile);
572 DCHECK(delegate);
573 // Only show an SSL decision revoke button if both the user has chosen to
574 // bypass SSL host errors for this host in the past and the user is not using
575 // the traditional "forget-at-session-restart" error decision memory.
576 show_ssl_decision_revoke_button_ = delegate->HasUserDecision(url.host()) &&
577 InRememberCertificateErrorDecisionsGroup();
578
[email protected]e583f752012-08-30 13:26:21579 // By default select the permissions tab that displays all the site
580 // permissions. In case of a connection error or an issue with the
581 // certificate presented by the website, select the connection tab to draw
582 // the user's attention to the issue. If the site does not provide a
583 // certificate because it was loaded over an unencrypted connection, don't
584 // select the connection tab.
585 WebsiteSettingsUI::TabId tab_id = WebsiteSettingsUI::TAB_ID_PERMISSIONS;
586 if (site_connection_status_ == SITE_CONNECTION_STATUS_ENCRYPTED_ERROR ||
587 site_connection_status_ == SITE_CONNECTION_STATUS_MIXED_CONTENT ||
588 site_identity_status_ == SITE_IDENTITY_STATUS_ERROR ||
[email protected]eaf3f322013-04-25 21:53:59589 site_identity_status_ == SITE_IDENTITY_STATUS_CERT_REVOCATION_UNKNOWN ||
590 site_identity_status_ == SITE_IDENTITY_STATUS_ADMIN_PROVIDED_CERT)
[email protected]e583f752012-08-30 13:26:21591 tab_id = WebsiteSettingsUI::TAB_ID_CONNECTION;
592 ui_->SetSelectedTab(tab_id);
[email protected]03ef4b2a2012-03-06 15:04:20593}
[email protected]0b9fdd72012-04-04 10:00:33594
[email protected]df818272012-04-20 13:10:50595void WebsiteSettings::PresentSitePermissions() {
596 PermissionInfoList permission_info_list;
597
598 WebsiteSettingsUI::PermissionInfo permission_info;
599 for (size_t i = 0; i < arraysize(kPermissionType); ++i) {
600 permission_info.type = kPermissionType[i];
[email protected]eb2140c2013-07-29 12:37:34601 if (permission_info.type == CONTENT_SETTINGS_TYPE_MIDI_SYSEX) {
602 const CommandLine* command_line = CommandLine::ForCurrentProcess();
603 if (!command_line->HasSwitch(switches::kEnableWebMIDI))
604 continue;
605 }
[email protected]df818272012-04-20 13:10:50606
607 content_settings::SettingInfo info;
[email protected]0bacc1912012-12-11 11:05:34608 if (permission_info.type == CONTENT_SETTINGS_TYPE_MEDIASTREAM) {
609 scoped_ptr<base::Value> mic_value(content_settings_->GetWebsiteSetting(
[email protected]007b3f82013-04-09 08:46:45610 site_url_,
611 site_url_,
612 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
613 std::string(),
614 &info));
[email protected]0bacc1912012-12-11 11:05:34615 ContentSetting mic_setting =
616 content_settings::ValueToContentSetting(mic_value.get());
617
618 scoped_ptr<base::Value> camera_value(content_settings_->GetWebsiteSetting(
[email protected]007b3f82013-04-09 08:46:45619 site_url_,
620 site_url_,
621 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
622 std::string(),
623 &info));
[email protected]0bacc1912012-12-11 11:05:34624 ContentSetting camera_setting =
625 content_settings::ValueToContentSetting(camera_value.get());
626
627 if (mic_setting != camera_setting || mic_setting == CONTENT_SETTING_ASK)
628 permission_info.setting = CONTENT_SETTING_DEFAULT;
629 else
630 permission_info.setting = mic_setting;
[email protected]fe4686a2012-10-19 15:38:26631 } else {
[email protected]2c95d102013-12-23 20:42:16632 scoped_ptr<base::Value> value(content_settings_->GetWebsiteSetting(
[email protected]007b3f82013-04-09 08:46:45633 site_url_, site_url_, permission_info.type, std::string(), &info));
[email protected]0bacc1912012-12-11 11:05:34634 DCHECK(value.get());
[email protected]2c95d102013-12-23 20:42:16635 if (value->GetType() == base::Value::TYPE_INTEGER) {
[email protected]0bacc1912012-12-11 11:05:34636 permission_info.setting =
637 content_settings::ValueToContentSetting(value.get());
638 } else {
639 NOTREACHED();
640 }
[email protected]fe4686a2012-10-19 15:38:26641 }
642
[email protected]8bdf45c32012-08-04 00:12:55643 permission_info.source = info.source;
[email protected]df818272012-04-20 13:10:50644
[email protected]b1d113d2012-06-27 21:27:34645 if (info.primary_pattern == ContentSettingsPattern::Wildcard() &&
[email protected]0bacc1912012-12-11 11:05:34646 info.secondary_pattern == ContentSettingsPattern::Wildcard() &&
647 permission_info.type != CONTENT_SETTINGS_TYPE_MEDIASTREAM) {
[email protected]b1d113d2012-06-27 21:27:34648 permission_info.default_setting = permission_info.setting;
649 permission_info.setting = CONTENT_SETTING_DEFAULT;
650 } else {
651 permission_info.default_setting =
652 content_settings_->GetDefaultContentSetting(permission_info.type,
653 NULL);
[email protected]df818272012-04-20 13:10:50654 }
[email protected]b1d113d2012-06-27 21:27:34655 permission_info_list.push_back(permission_info);
[email protected]df818272012-04-20 13:10:50656 }
657
658 ui_->SetPermissionInfo(permission_info_list);
[email protected]0b9fdd72012-04-04 10:00:33659}
660
[email protected]df818272012-04-20 13:10:50661void WebsiteSettings::PresentSiteData() {
662 CookieInfoList cookie_info_list;
[email protected]e0ac35892012-05-15 12:53:34663 const LocalSharedObjectsContainer& allowed_objects =
664 tab_specific_content_settings()->allowed_local_shared_objects();
665 const LocalSharedObjectsContainer& blocked_objects =
666 tab_specific_content_settings()->blocked_local_shared_objects();
667
668 // Add first party cookie and site data counts.
[email protected]df818272012-04-20 13:10:50669 WebsiteSettingsUI::CookieInfo cookie_info;
[email protected]e0ac35892012-05-15 12:53:34670 std::string cookie_source =
[email protected]ed32c212013-05-14 20:49:29671 net::registry_controlled_domains::GetDomainAndRegistry(
672 site_url_,
[email protected]aabe1792014-01-30 21:37:46673 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
[email protected]e0ac35892012-05-15 12:53:34674 if (cookie_source.empty())
675 cookie_source = site_url_.host();
676 cookie_info.cookie_source = cookie_source;
677 cookie_info.allowed = allowed_objects.GetObjectCountForDomain(site_url_);
678 cookie_info.blocked = blocked_objects.GetObjectCountForDomain(site_url_);
679 cookie_info_list.push_back(cookie_info);
680
681 // Add third party cookie counts.
682 cookie_info.cookie_source = l10n_util::GetStringUTF8(
683 IDS_WEBSITE_SETTINGS_THIRD_PARTY_SITE_DATA);
684 cookie_info.allowed = allowed_objects.GetObjectCount() - cookie_info.allowed;
685 cookie_info.blocked = blocked_objects.GetObjectCount() - cookie_info.blocked;
[email protected]df818272012-04-20 13:10:50686 cookie_info_list.push_back(cookie_info);
[email protected]0b9fdd72012-04-04 10:00:33687
[email protected]df818272012-04-20 13:10:50688 ui_->SetCookieInfo(cookie_info_list);
[email protected]0b9fdd72012-04-04 10:00:33689}
[email protected]16de6de2012-04-04 12:24:14690
[email protected]24c8818c2012-04-25 09:57:41691void WebsiteSettings::PresentSiteIdentity() {
692 // After initialization the status about the site's connection
693 // and it's identity must be available.
694 DCHECK_NE(site_identity_status_, SITE_IDENTITY_STATUS_UNKNOWN);
695 DCHECK_NE(site_connection_status_, SITE_CONNECTION_STATUS_UNKNOWN);
696 WebsiteSettingsUI::IdentityInfo info;
697 if (site_identity_status_ == SITE_IDENTITY_STATUS_EV_CERT)
698 info.site_identity = UTF16ToUTF8(organization_name());
699 else
700 info.site_identity = site_url_.host();
701
702 info.connection_status = site_connection_status_;
703 info.connection_status_description =
704 UTF16ToUTF8(site_connection_details_);
705 info.identity_status = site_identity_status_;
706 info.identity_status_description =
707 UTF16ToUTF8(site_identity_details_);
[email protected]f61c1ce2012-05-09 13:55:11708 info.cert_id = cert_id_;
[email protected]3d6d34b12013-12-23 00:34:02709 info.signed_certificate_timestamp_ids.assign(
710 signed_certificate_timestamp_ids_.begin(),
711 signed_certificate_timestamp_ids_.end());
[email protected]71cd5ef2014-08-13 21:22:04712 info.show_ssl_decision_revoke_button = show_ssl_decision_revoke_button_;
[email protected]24c8818c2012-04-25 09:57:41713 ui_->SetIdentityInfo(info);
714}
715
[email protected]15b092542012-05-16 13:08:14716void WebsiteSettings::PresentHistoryInfo(base::Time first_visit) {
717 if (first_visit == base::Time()) {
[email protected]b959d7d42013-12-13 17:26:37718 ui_->SetFirstVisit(base::string16());
[email protected]15b092542012-05-16 13:08:14719 return;
720 }
721
722 bool visited_before_today = false;
723 base::Time today = base::Time::Now().LocalMidnight();
724 base::Time first_visit_midnight = first_visit.LocalMidnight();
725 visited_before_today = (first_visit_midnight < today);
726
[email protected]a04db822013-12-11 19:14:40727 base::string16 first_visit_text;
[email protected]15b092542012-05-16 13:08:14728 if (visited_before_today) {
729 first_visit_text = l10n_util::GetStringFUTF16(
730 IDS_PAGE_INFO_SECURITY_TAB_VISITED_BEFORE_TODAY,
731 base::TimeFormatShortDate(first_visit));
732 } else {
733 first_visit_text = l10n_util::GetStringUTF16(
734 IDS_PAGE_INFO_SECURITY_TAB_FIRST_VISITED_TODAY);
[email protected]15b092542012-05-16 13:08:14735 }
736 ui_->SetFirstVisit(first_visit_text);
737}