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 "components/page_info/page_info.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <memory>
11 #include <string>
12 #include <utility>
13 #include <vector>
14
15 #include "base/i18n/time_formatting.h"
16 #include "base/metrics/field_trial.h"
17 #include "base/metrics/histogram_functions.h"
18 #include "base/metrics/histogram_macros.h"
19 #include "base/metrics/user_metrics.h"
20 #include "base/stl_util.h"
21 #include "base/strings/string_number_conversions.h"
22 #include "base/strings/utf_string_conversions.h"
23 #include "base/values.h"
24 #include "build/build_config.h"
25 #include "components/browser_ui/util/android/url_constants.h"
26 #include "components/browsing_data/content/local_storage_helper.h"
27 #include "components/content_settings/browser/page_specific_content_settings.h"
28 #include "components/content_settings/core/browser/content_settings_registry.h"
29 #include "components/content_settings/core/browser/content_settings_utils.h"
30 #include "components/content_settings/core/browser/host_content_settings_map.h"
31 #include "components/content_settings/core/common/content_settings.h"
32 #include "components/content_settings/core/common/content_settings_pattern.h"
33 #include "components/content_settings/core/common/content_settings_utils.h"
34 #include "components/page_info/page_info_delegate.h"
35 #include "components/page_info/page_info_ui.h"
36 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
37 #include "components/permissions/chooser_context_base.h"
38 #include "components/permissions/permission_decision_auto_blocker.h"
39 #include "components/permissions/permission_manager.h"
40 #include "components/permissions/permission_result.h"
41 #include "components/permissions/permission_uma_util.h"
42 #include "components/permissions/permission_util.h"
43 #if defined(OS_ANDROID)
44 #include "components/resources/android/theme_resources.h"
45 #endif
46 #include "components/safe_browsing/buildflags.h"
47 #include "components/safe_browsing/content/password_protection/metrics_util.h"
48 #include "components/safe_browsing/content/password_protection/password_protection_service.h"
49 #include "components/safe_browsing/core/proto/csd.pb.h"
50 #include "components/security_interstitials/content/stateful_ssl_host_state_delegate.h"
51 #include "components/signin/public/identity_manager/account_info.h"
52 #include "components/ssl_errors/error_info.h"
53 #include "components/strings/grit/components_chromium_strings.h"
54 #include "components/strings/grit/components_strings.h"
55 #include "components/subresource_filter/core/browser/subresource_filter_features.h"
56 #include "components/ukm/content/source_url_recorder.h"
57 #include "components/url_formatter/elide_url.h"
58 #include "content/public/browser/browser_context.h"
59 #include "content/public/browser/browser_thread.h"
60 #include "content/public/browser/web_contents.h"
61 #include "content/public/common/content_features.h"
62 #include "content/public/common/url_constants.h"
63 #include "net/cert/cert_status_flags.h"
64 #include "net/cert/x509_certificate.h"
65 #include "net/ssl/ssl_cipher_suite_names.h"
66 #include "net/ssl/ssl_connection_status_flags.h"
67 #include "services/metrics/public/cpp/ukm_builders.h"
68 #include "services/metrics/public/cpp/ukm_recorder.h"
69 #include "third_party/boringssl/src/include/openssl/ssl.h"
70 #include "ui/base/l10n/l10n_util.h"
71 #include "url/origin.h"
72
73 using base::ASCIIToUTF16;
74 using base::UTF16ToUTF8;
75 using base::UTF8ToUTF16;
76 using content::BrowserThread;
77 using safe_browsing::LoginReputationClientResponse;
78 using safe_browsing::RequestOutcome;
79
80 namespace {
81
82 // The list of content settings types to display on the Page Info UI. THE
83 // ORDER OF THESE ITEMS IS IMPORTANT and comes from https://crbug.com/610358. To
84 // propose changing it, email security-dev@chromium.org.
85 ContentSettingsType kPermissionType[] = {
86 ContentSettingsType::GEOLOCATION,
87 ContentSettingsType::MEDIASTREAM_CAMERA,
88 ContentSettingsType::CAMERA_PAN_TILT_ZOOM,
89 ContentSettingsType::MEDIASTREAM_MIC,
90 ContentSettingsType::SENSORS,
91 ContentSettingsType::NOTIFICATIONS,
92 ContentSettingsType::JAVASCRIPT,
93 #if !defined(OS_ANDROID)
94 ContentSettingsType::PLUGINS,
95 ContentSettingsType::IMAGES,
96 #endif
97 ContentSettingsType::POPUPS,
98 ContentSettingsType::WINDOW_PLACEMENT,
99 ContentSettingsType::ADS,
100 ContentSettingsType::BACKGROUND_SYNC,
101 ContentSettingsType::SOUND,
102 ContentSettingsType::AUTOMATIC_DOWNLOADS,
103 #if defined(OS_ANDROID) || defined(OS_CHROMEOS)
104 ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER,
105 #endif
106 ContentSettingsType::MIDI_SYSEX,
107 ContentSettingsType::CLIPBOARD_READ_WRITE,
108 #if defined(OS_ANDROID)
109 ContentSettingsType::NFC,
110 #endif
111 ContentSettingsType::USB_GUARD,
112 #if !defined(OS_ANDROID)
113 ContentSettingsType::HID_GUARD,
114 ContentSettingsType::SERIAL_GUARD,
115 ContentSettingsType::FILE_SYSTEM_WRITE_GUARD,
116 ContentSettingsType::FONT_ACCESS,
117 #endif
118 ContentSettingsType::BLUETOOTH_GUARD,
119 ContentSettingsType::BLUETOOTH_SCANNING,
120 ContentSettingsType::VR,
121 ContentSettingsType::AR,
122 ContentSettingsType::IDLE_DETECTION,
123 };
124
125 // Determines whether to show permission |type| in the Page Info UI. Only
126 // applies to permissions listed in |kPermissionType|.
ShouldShowPermission(const PageInfo::PermissionInfo & info,const GURL & site_url,HostContentSettingsMap * content_settings,content::WebContents * web_contents,bool changed_since_last_page_load,bool is_subresource_filter_activated)127 bool ShouldShowPermission(const PageInfo::PermissionInfo& info,
128 const GURL& site_url,
129 HostContentSettingsMap* content_settings,
130 content::WebContents* web_contents,
131 bool changed_since_last_page_load,
132 bool is_subresource_filter_activated) {
133 // Note |ContentSettingsType::ADS| will show up regardless of its default
134 // value when it has been activated on the current origin.
135 if (info.type == ContentSettingsType::ADS) {
136 if (!base::FeatureList::IsEnabled(
137 subresource_filter::kSafeBrowsingSubresourceFilter)) {
138 return false;
139 }
140
141 return is_subresource_filter_activated;
142 }
143
144 if (info.type == ContentSettingsType::SOUND) {
145 // The sound content setting should always show up when the tab has played
146 // audio.
147 if (web_contents && web_contents->WasEverAudible())
148 return true;
149 }
150
151 #if defined(OS_ANDROID)
152 // Special geolocation DSE settings apply only on Android, so make sure it
153 // gets checked there regardless of default setting on Desktop.
154 // DSE settings don't apply to incognito mode.
155 if (info.type == ContentSettingsType::GEOLOCATION && !info.is_incognito)
156 return true;
157
158 // The File System write permission is desktop only at the moment.
159 if (info.type == ContentSettingsType::FILE_SYSTEM_WRITE_GUARD)
160 return false;
161 #else
162 // Flash is deprecated and should never be shown.
163 if (info.type == ContentSettingsType::PLUGINS) {
164 return false;
165 }
166
167 // NFC is Android-only at the moment.
168 if (info.type == ContentSettingsType::NFC)
169 return false;
170
171 // Display the File System write permission if the File System API is
172 // currently being used.
173 if (info.type == ContentSettingsType::FILE_SYSTEM_WRITE_GUARD &&
174 web_contents->HasNativeFileSystemHandles()) {
175 return true;
176 }
177
178 // Hide camera if camera PTZ is granted or blocked.
179 if (info.type == ContentSettingsType::MEDIASTREAM_CAMERA) {
180 std::unique_ptr<base::Value> value = content_settings->GetWebsiteSetting(
181 site_url, site_url, ContentSettingsType::CAMERA_PAN_TILT_ZOOM, nullptr);
182 DCHECK(value.get());
183 ContentSetting camera_ptz_setting =
184 content_settings::ValueToContentSetting(value.get());
185 if (camera_ptz_setting == CONTENT_SETTING_ALLOW ||
186 camera_ptz_setting == CONTENT_SETTING_BLOCK) {
187 return false;
188 }
189 }
190 #endif
191
192 // Show the content setting if it has been changed by the user since the last
193 // page load.
194 if (changed_since_last_page_load) {
195 return true;
196 }
197
198 // Show the Bluetooth guard permission if the new permissions backend is
199 // enabled.
200 if (info.type == ContentSettingsType::BLUETOOTH_GUARD &&
201 base::FeatureList::IsEnabled(
202 features::kWebBluetoothNewPermissionsBackend) &&
203 !PageInfo::IsPermissionFactoryDefault(info)) {
204 return true;
205 }
206
207 // Show the content setting when it has a non-default value.
208 if (!PageInfo::IsPermissionFactoryDefault(info))
209 return true;
210
211 return false;
212 }
213
214 // If the |visible_security_state| indicates that mixed content or certificate
215 // errors were present, update |connection_status| and |connection_details|.
ReportAnyInsecureContent(const security_state::VisibleSecurityState & visible_security_state,PageInfo::SiteConnectionStatus * connection_status,base::string16 * connection_details)216 void ReportAnyInsecureContent(
217 const security_state::VisibleSecurityState& visible_security_state,
218 PageInfo::SiteConnectionStatus* connection_status,
219 base::string16* connection_details) {
220 bool displayed_insecure_content =
221 visible_security_state.displayed_mixed_content;
222 bool ran_insecure_content = visible_security_state.ran_mixed_content;
223 // Only note subresources with certificate errors if the main resource was
224 // loaded without major certificate errors. If the main resource had a
225 // certificate error, then it would not be that useful (and could
226 // potentially be confusing) to warn about subresources that had certificate
227 // errors too.
228 if (!net::IsCertStatusError(visible_security_state.cert_status)) {
229 displayed_insecure_content =
230 displayed_insecure_content ||
231 visible_security_state.displayed_content_with_cert_errors;
232 ran_insecure_content = ran_insecure_content ||
233 visible_security_state.ran_content_with_cert_errors;
234 }
235
236 // Only one insecure content warning is displayed; show the most severe.
237 if (ran_insecure_content) {
238 *connection_status =
239 PageInfo::SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE;
240 connection_details->assign(l10n_util::GetStringFUTF16(
241 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_SENTENCE_LINK, *connection_details,
242 l10n_util::GetStringUTF16(
243 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_INSECURE_CONTENT_ERROR)));
244 return;
245 }
246 if (visible_security_state.contained_mixed_form) {
247 *connection_status = PageInfo::SITE_CONNECTION_STATUS_INSECURE_FORM_ACTION;
248 connection_details->assign(l10n_util::GetStringFUTF16(
249 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_SENTENCE_LINK, *connection_details,
250 l10n_util::GetStringUTF16(
251 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_INSECURE_FORM_WARNING)));
252 return;
253 }
254 if (displayed_insecure_content) {
255 *connection_status =
256 PageInfo::SITE_CONNECTION_STATUS_INSECURE_PASSIVE_SUBRESOURCE;
257 connection_details->assign(l10n_util::GetStringFUTF16(
258 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_SENTENCE_LINK, *connection_details,
259 l10n_util::GetStringUTF16(
260 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_INSECURE_CONTENT_WARNING)));
261 }
262 }
263
GetSimpleSiteName(const GURL & url)264 base::string16 GetSimpleSiteName(const GURL& url) {
265 return url_formatter::FormatUrlForSecurityDisplay(
266 url, url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS);
267 }
268
269 // The list of chooser types that need to display entries in the Website
270 // Settings UI. THE ORDER OF THESE ITEMS IS IMPORTANT. To propose changing it,
271 // email security-dev@chromium.org.
272 const PageInfo::ChooserUIInfo kChooserUIInfo[] = {
273 {ContentSettingsType::USB_CHOOSER_DATA,
274 IDS_PAGE_INFO_USB_DEVICE_SECONDARY_LABEL,
275 IDS_PAGE_INFO_USB_DEVICE_ALLOWED_BY_POLICY_LABEL,
276 IDS_PAGE_INFO_DELETE_USB_DEVICE},
277 #if !defined(OS_ANDROID)
278 {ContentSettingsType::HID_CHOOSER_DATA,
279 IDS_PAGE_INFO_HID_DEVICE_SECONDARY_LABEL,
280 /*allowed_by_policy_description_string_id=*/-1,
281 IDS_PAGE_INFO_DELETE_HID_DEVICE},
282 {ContentSettingsType::SERIAL_CHOOSER_DATA,
283 IDS_PAGE_INFO_SERIAL_PORT_SECONDARY_LABEL,
284 /*allowed_by_policy_description_string_id=*/-1,
285 IDS_PAGE_INFO_DELETE_SERIAL_PORT},
286 #endif
287 {ContentSettingsType::BLUETOOTH_CHOOSER_DATA,
288 IDS_PAGE_INFO_BLUETOOTH_DEVICE_SECONDARY_LABEL,
289 /*allowed_by_policy_description_string_id=*/-1,
290 IDS_PAGE_INFO_DELETE_BLUETOOTH_DEVICE},
291 };
292
293 // Time open histogram prefixes.
294 const char kPageInfoTimePrefix[] = "Security.PageInfo.TimeOpen";
295 const char kPageInfoTimeActionPrefix[] = "Security.PageInfo.TimeOpen.Action";
296 const char kPageInfoTimeNoActionPrefix[] =
297 "Security.PageInfo.TimeOpen.NoAction";
298
299 } // namespace
300
PageInfo(std::unique_ptr<PageInfoDelegate> delegate,content::WebContents * web_contents,const GURL & url)301 PageInfo::PageInfo(std::unique_ptr<PageInfoDelegate> delegate,
302 content::WebContents* web_contents,
303 const GURL& url)
304 : content::WebContentsObserver(web_contents),
305 delegate_(std::move(delegate)),
306 show_info_bar_(false),
307 site_url_(url),
308 site_identity_status_(SITE_IDENTITY_STATUS_UNKNOWN),
309 safe_browsing_status_(SAFE_BROWSING_STATUS_NONE),
310 safety_tip_info_({security_state::SafetyTipStatus::kUnknown, GURL()}),
311 site_connection_status_(SITE_CONNECTION_STATUS_UNKNOWN),
312 show_ssl_decision_revoke_button_(false),
313 did_revoke_user_ssl_decisions_(false),
314 show_change_password_buttons_(false),
315 did_perform_action_(false) {
316 DCHECK(delegate_);
317 security_level_ = delegate_->GetSecurityLevel();
318 visible_security_state_for_metrics_ = delegate_->GetVisibleSecurityState();
319 }
320
~PageInfo()321 PageInfo::~PageInfo() {
322 // Check if Re-enable warnings button was visible, if so, log on UMA whether
323 // it was clicked or not.
324 SSLCertificateDecisionsDidRevoke user_decision =
325 did_revoke_user_ssl_decisions_ ? USER_CERT_DECISIONS_REVOKED
326 : USER_CERT_DECISIONS_NOT_REVOKED;
327 if (show_ssl_decision_revoke_button_) {
328 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl.did_user_revoke_decisions2",
329 user_decision,
330 END_OF_SSL_CERTIFICATE_DECISIONS_DID_REVOKE_ENUM);
331 }
332
333 // Record the total time the Page Info UI was open for all opens as well as
334 // split between whether any action was taken.
335 base::UmaHistogramCustomTimes(security_state::GetSecurityLevelHistogramName(
336 kPageInfoTimePrefix, security_level_),
337 base::TimeTicks::Now() - start_time_,
338 base::TimeDelta::FromMilliseconds(1),
339 base::TimeDelta::FromHours(1), 100);
340 base::UmaHistogramCustomTimes(
341 security_state::GetSafetyTipHistogramName(kPageInfoTimePrefix,
342 safety_tip_info_.status),
343 base::TimeTicks::Now() - start_time_,
344 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromHours(1), 100);
345 base::UmaHistogramCustomTimes(
346 security_state::GetLegacyTLSHistogramName(
347 kPageInfoTimePrefix, visible_security_state_for_metrics_),
348 base::TimeTicks::Now() - start_time_,
349 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromHours(1), 100);
350
351 if (did_perform_action_) {
352 base::UmaHistogramCustomTimes(
353 security_state::GetSecurityLevelHistogramName(kPageInfoTimeActionPrefix,
354 security_level_),
355 base::TimeTicks::Now() - start_time_,
356 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromHours(1),
357 100);
358 base::UmaHistogramCustomTimes(
359 security_state::GetSafetyTipHistogramName(kPageInfoTimeActionPrefix,
360 safety_tip_info_.status),
361 base::TimeTicks::Now() - start_time_,
362 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromHours(1),
363 100);
364 base::UmaHistogramCustomTimes(
365 security_state::GetLegacyTLSHistogramName(
366 kPageInfoTimeActionPrefix, visible_security_state_for_metrics_),
367 base::TimeTicks::Now() - start_time_,
368 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromHours(1),
369 100);
370 } else {
371 base::UmaHistogramCustomTimes(
372 security_state::GetSecurityLevelHistogramName(
373 kPageInfoTimeNoActionPrefix, security_level_),
374 base::TimeTicks::Now() - start_time_,
375 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromHours(1),
376 100);
377 base::UmaHistogramCustomTimes(
378 security_state::GetSafetyTipHistogramName(kPageInfoTimeNoActionPrefix,
379 safety_tip_info_.status),
380 base::TimeTicks::Now() - start_time_,
381 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromHours(1),
382 100);
383 base::UmaHistogramCustomTimes(
384 security_state::GetLegacyTLSHistogramName(
385 kPageInfoTimeNoActionPrefix, visible_security_state_for_metrics_),
386 base::TimeTicks::Now() - start_time_,
387 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromHours(1),
388 100);
389 }
390 }
391
392 // static
IsPermissionFactoryDefault(const PermissionInfo & info)393 bool PageInfo::IsPermissionFactoryDefault(const PermissionInfo& info) {
394 const ContentSetting factory_default_setting =
395 content_settings::ContentSettingsRegistry::GetInstance()
396 ->Get(info.type)
397 ->GetInitialDefaultSetting();
398
399 // Settings that are granted in regular mode get reduced to ASK in incognito
400 // mode. These settings should not be displayed either.
401 const bool is_incognito_default =
402 info.is_incognito && info.setting == CONTENT_SETTING_ASK &&
403 factory_default_setting == CONTENT_SETTING_ASK;
404
405 return info.source == content_settings::SETTING_SOURCE_USER &&
406 factory_default_setting == info.default_setting &&
407 (info.setting == CONTENT_SETTING_DEFAULT || is_incognito_default);
408 }
409
410 // static
IsFileOrInternalPage(const GURL & url)411 bool PageInfo::IsFileOrInternalPage(const GURL& url) {
412 return url.SchemeIs(content::kChromeUIScheme) ||
413 url.SchemeIs(content::kChromeDevToolsScheme) ||
414 url.SchemeIs(content::kViewSourceScheme) ||
415 url.SchemeIs(url::kFileScheme);
416 }
417
InitializeUiState(PageInfoUI * ui)418 void PageInfo::InitializeUiState(PageInfoUI* ui) {
419 ui_ = ui;
420 DCHECK(ui_);
421 // TabSpecificContentSetting needs to be created before page load.
422 DCHECK(GetPageSpecificContentSettings());
423
424 ComputeUIInputs(site_url_);
425 PresentSitePermissions();
426 PresentSiteIdentity();
427 PresentSiteData();
428 PresentPageFeatureInfo();
429
430 // Every time the Page Info UI is opened, this method is called.
431 // So this counts how often the Page Info UI is opened.
432 RecordPageInfoAction(PAGE_INFO_OPENED);
433
434 // Record the time when the Page Info UI is opened so the total time it is
435 // open can be measured.
436 start_time_ = base::TimeTicks::Now();
437 }
438
UpdateSecurityState()439 void PageInfo::UpdateSecurityState() {
440 ComputeUIInputs(site_url_);
441 PresentSiteIdentity();
442 }
443
RecordPageInfoAction(PageInfoAction action)444 void PageInfo::RecordPageInfoAction(PageInfoAction action) {
445 if (action != PAGE_INFO_OPENED)
446 did_perform_action_ = true;
447
448 UMA_HISTOGRAM_ENUMERATION("WebsiteSettings.Action", action, PAGE_INFO_COUNT);
449
450 if (web_contents()) {
451 ukm::builders::PageInfoBubble(
452 ukm::GetSourceIdForWebContentsDocument(web_contents()))
453 .SetActionTaken(action)
454 .Record(ukm::UkmRecorder::Get());
455 }
456
457 base::UmaHistogramEnumeration(
458 security_state::GetSafetyTipHistogramName(
459 "Security.SafetyTips.PageInfo.Action", safety_tip_info_.status),
460 action, PAGE_INFO_COUNT);
461
462 base::UmaHistogramEnumeration(security_state::GetLegacyTLSHistogramName(
463 "Security.LegacyTLS.PageInfo.Action",
464 visible_security_state_for_metrics_),
465 action, PAGE_INFO_COUNT);
466
467 std::string histogram_name;
468 if (site_url_.SchemeIsCryptographic()) {
469 if (security_level_ == security_state::SECURE) {
470 if (visible_security_state_for_metrics_.cert_status &
471 net::CERT_STATUS_IS_EV) {
472 UMA_HISTOGRAM_ENUMERATION("Security.PageInfo.Action.HttpsUrl.ValidEV",
473 action, PAGE_INFO_COUNT);
474 } else {
475 UMA_HISTOGRAM_ENUMERATION(
476 "Security.PageInfo.Action.HttpsUrl.ValidNonEV", action,
477 PAGE_INFO_COUNT);
478 }
479 } else if (security_level_ == security_state::NONE) {
480 UMA_HISTOGRAM_ENUMERATION("Security.PageInfo.Action.HttpsUrl.Downgraded",
481 action, PAGE_INFO_COUNT);
482 } else if (security_level_ == security_state::DANGEROUS) {
483 UMA_HISTOGRAM_ENUMERATION("Security.PageInfo.Action.HttpsUrl.Dangerous",
484 action, PAGE_INFO_COUNT);
485 }
486 return;
487 }
488
489 if (security_level_ == security_state::WARNING) {
490 UMA_HISTOGRAM_ENUMERATION("Security.PageInfo.Action.HttpUrl.Warning",
491 action, PAGE_INFO_COUNT);
492 } else if (security_level_ == security_state::DANGEROUS) {
493 UMA_HISTOGRAM_ENUMERATION("Security.PageInfo.Action.HttpUrl.Dangerous",
494 action, PAGE_INFO_COUNT);
495 } else {
496 UMA_HISTOGRAM_ENUMERATION("Security.PageInfo.Action.HttpUrl.Neutral",
497 action, PAGE_INFO_COUNT);
498 }
499 }
500
UpdatePermissions()501 void PageInfo::UpdatePermissions() {
502 // Refresh the UI to reflect the new setting.
503 PresentSitePermissions();
504 }
505
OnSitePermissionChanged(ContentSettingsType type,ContentSetting setting,bool is_one_time)506 void PageInfo::OnSitePermissionChanged(ContentSettingsType type,
507 ContentSetting setting,
508 bool is_one_time) {
509 ContentSettingChangedViaPageInfo(type);
510
511 // Count how often a permission for a specific content type is changed using
512 // the Page Info UI.
513 size_t num_values;
514 int histogram_value = ContentSettingTypeToHistogramValue(type, &num_values);
515 UMA_HISTOGRAM_EXACT_LINEAR("WebsiteSettings.OriginInfo.PermissionChanged",
516 histogram_value, num_values);
517
518 if (setting == ContentSetting::CONTENT_SETTING_ALLOW) {
519 UMA_HISTOGRAM_EXACT_LINEAR(
520 "WebsiteSettings.OriginInfo.PermissionChanged.Allowed", histogram_value,
521 num_values);
522 } else if (setting == ContentSetting::CONTENT_SETTING_BLOCK) {
523 UMA_HISTOGRAM_EXACT_LINEAR(
524 "WebsiteSettings.OriginInfo.PermissionChanged.Blocked", histogram_value,
525 num_values);
526 }
527
528 // This is technically redundant given the histogram above, but putting the
529 // total count of permission changes in another histogram makes it easier to
530 // compare it against other kinds of actions in Page Info.
531 RecordPageInfoAction(PAGE_INFO_CHANGED_PERMISSION);
532 HostContentSettingsMap* content_settings = GetContentSettings();
533 if (type == ContentSettingsType::SOUND) {
534 ContentSetting default_setting = content_settings->GetDefaultContentSetting(
535 ContentSettingsType::SOUND, nullptr);
536 bool mute = (setting == CONTENT_SETTING_BLOCK) ||
537 (setting == CONTENT_SETTING_DEFAULT &&
538 default_setting == CONTENT_SETTING_BLOCK);
539 if (mute) {
540 base::RecordAction(
541 base::UserMetricsAction("SoundContentSetting.MuteBy.PageInfo"));
542 } else {
543 base::RecordAction(
544 base::UserMetricsAction("SoundContentSetting.UnmuteBy.PageInfo"));
545 }
546 }
547
548 permissions::PermissionUmaUtil::ScopedRevocationReporter
549 scoped_revocation_reporter(web_contents()->GetBrowserContext(), site_url_,
550 site_url_, type,
551 permissions::PermissionSourceUI::OIB);
552
553 // The permission may have been blocked due to being under embargo, so if it
554 // was changed away from BLOCK, clear embargo status if it exists.
555 if (setting != CONTENT_SETTING_BLOCK) {
556 delegate_->GetPermissionDecisionAutoblocker()->RemoveEmbargoAndResetCounts(
557 site_url_, type);
558 }
559 using Constraints = content_settings::ContentSettingConstraints;
560 content_settings->SetNarrowestContentSetting(
561 site_url_, site_url_, type, setting,
562 is_one_time
563 ? Constraints{base::Time(), content_settings::SessionModel::OneTime}
564 : Constraints{});
565
566 // When the sound setting is changed, no reload is necessary.
567 if (type != ContentSettingsType::SOUND)
568 show_info_bar_ = true;
569
570 // Refresh the UI to reflect the new setting.
571 PresentSitePermissions();
572 }
573
OnSiteChosenObjectDeleted(const ChooserUIInfo & ui_info,const base::Value & object)574 void PageInfo::OnSiteChosenObjectDeleted(const ChooserUIInfo& ui_info,
575 const base::Value& object) {
576 // TODO(reillyg): Create metrics for revocations. crbug.com/556845
577 permissions::ChooserContextBase* context =
578 delegate_->GetChooserContext(ui_info.content_settings_type);
579 const auto origin = url::Origin::Create(site_url_);
580 context->RevokeObjectPermission(origin, origin, object);
581 show_info_bar_ = true;
582
583 // Refresh the UI to reflect the changed settings.
584 PresentSitePermissions();
585 }
586
OnUIClosing(bool * reload_prompt)587 void PageInfo::OnUIClosing(bool* reload_prompt) {
588 if (reload_prompt)
589 *reload_prompt = false;
590 #if defined(OS_ANDROID)
591 NOTREACHED();
592 #else
593 if (show_info_bar_ && web_contents() && !web_contents()->IsBeingDestroyed()) {
594 if (delegate_->CreateInfoBarDelegate() && reload_prompt)
595 *reload_prompt = true;
596 }
597 #endif
598 }
599
OnRevokeSSLErrorBypassButtonPressed()600 void PageInfo::OnRevokeSSLErrorBypassButtonPressed() {
601 auto* stateful_ssl_host_state_delegate =
602 delegate_->GetStatefulSSLHostStateDelegate();
603 DCHECK(stateful_ssl_host_state_delegate);
604 stateful_ssl_host_state_delegate->RevokeUserAllowExceptionsHard(
605 site_url().host());
606 did_revoke_user_ssl_decisions_ = true;
607 }
608
OpenSiteSettingsView()609 void PageInfo::OpenSiteSettingsView() {
610 #if defined(OS_ANDROID)
611 NOTREACHED();
612 #else
613 delegate_->ShowSiteSettings(site_url());
614 RecordPageInfoAction(PAGE_INFO_SITE_SETTINGS_OPENED);
615 #endif
616 }
617
OnChangePasswordButtonPressed(content::WebContents * web_contents)618 void PageInfo::OnChangePasswordButtonPressed(
619 content::WebContents* web_contents) {
620 #if BUILDFLAG(FULL_SAFE_BROWSING)
621 delegate_->OnUserActionOnPasswordUi(
622 web_contents, safe_browsing::WarningAction::CHANGE_PASSWORD);
623 #endif
624 }
625
OnWhitelistPasswordReuseButtonPressed(content::WebContents * web_contents)626 void PageInfo::OnWhitelistPasswordReuseButtonPressed(
627 content::WebContents* web_contents) {
628 #if BUILDFLAG(FULL_SAFE_BROWSING)
629 delegate_->OnUserActionOnPasswordUi(
630 web_contents, safe_browsing::WarningAction::MARK_AS_LEGITIMATE);
631 #endif
632 }
633
GetChooserContextFromUIInfo(const ChooserUIInfo & ui_info) const634 permissions::ChooserContextBase* PageInfo::GetChooserContextFromUIInfo(
635 const ChooserUIInfo& ui_info) const {
636 return delegate_->GetChooserContext(ui_info.content_settings_type);
637 }
638
ComputeUIInputs(const GURL & url)639 void PageInfo::ComputeUIInputs(const GURL& url) {
640 auto security_level = delegate_->GetSecurityLevel();
641 auto visible_security_state = delegate_->GetVisibleSecurityState();
642 #if !defined(OS_ANDROID)
643 // On desktop, internal URLs aren't handled by this class. Instead, a
644 // custom and simpler bubble is shown.
645 DCHECK(!url.SchemeIs(content::kChromeUIScheme) &&
646 !url.SchemeIs(content::kChromeDevToolsScheme) &&
647 !url.SchemeIs(content::kViewSourceScheme) &&
648 !url.SchemeIs(content_settings::kExtensionScheme));
649 #endif
650
651 bool is_chrome_ui_native_scheme = false;
652 #if defined(OS_ANDROID)
653 is_chrome_ui_native_scheme = url.SchemeIs(browser_ui::kChromeUINativeScheme);
654 #endif
655
656 if (url.SchemeIs(url::kAboutScheme)) {
657 // All about: URLs except about:blank are redirected.
658 DCHECK_EQ(url::kAboutBlankURL, url.spec());
659 site_identity_status_ = SITE_IDENTITY_STATUS_NO_CERT;
660 #if defined(OS_ANDROID)
661 identity_status_description_android_ =
662 l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURITY_TAB_INSECURE_IDENTITY);
663 #endif
664 site_connection_status_ = SITE_CONNECTION_STATUS_UNENCRYPTED;
665 site_connection_details_ = l10n_util::GetStringFUTF16(
666 IDS_PAGE_INFO_SECURITY_TAB_NOT_ENCRYPTED_CONNECTION_TEXT,
667 UTF8ToUTF16(url.spec()));
668 return;
669 }
670
671 if (url.SchemeIs(content::kChromeUIScheme) || is_chrome_ui_native_scheme) {
672 site_identity_status_ = SITE_IDENTITY_STATUS_INTERNAL_PAGE;
673 #if defined(OS_ANDROID)
674 identity_status_description_android_ =
675 l10n_util::GetStringUTF16(IDS_PAGE_INFO_INTERNAL_PAGE);
676 #endif
677 site_connection_status_ = SITE_CONNECTION_STATUS_INTERNAL_PAGE;
678 return;
679 }
680
681 // Identity section.
682 certificate_ = visible_security_state.certificate;
683
684 // TODO(crbug.com/1044747): This conditional special-cases
685 // CERT_STATUS_LEGACY_TLS to avoid marking the certificate as "Invalid" in
686 // Page Info, but once we clean up the overloading of CertStatus for Legacy
687 // TLS we can remove this.
688 if (certificate_ &&
689 (!net::IsCertStatusError(visible_security_state.cert_status &
690 ~net::CERT_STATUS_LEGACY_TLS))) {
691 // HTTPS with no or minor errors.
692 if (security_level == security_state::SECURE_WITH_POLICY_INSTALLED_CERT) {
693 #if defined(OS_CHROMEOS)
694 site_identity_status_ = SITE_IDENTITY_STATUS_ADMIN_PROVIDED_CERT;
695 #else
696 DCHECK(false) << "Policy certificates exist only on ChromeOS";
697 #endif
698 } else {
699 // No major or minor errors.
700 if (visible_security_state.cert_status & net::CERT_STATUS_IS_EV) {
701 // EV HTTPS page.
702 site_identity_status_ = SITE_IDENTITY_STATUS_EV_CERT;
703 } else {
704 // Non-EV OK HTTPS page.
705 site_identity_status_ = SITE_IDENTITY_STATUS_CERT;
706 base::string16 issuer_name(
707 UTF8ToUTF16(certificate_->issuer().GetDisplayName()));
708 if (issuer_name.empty()) {
709 issuer_name.assign(l10n_util::GetStringUTF16(
710 IDS_PAGE_INFO_SECURITY_TAB_UNKNOWN_PARTY));
711 }
712
713 #if defined(OS_ANDROID)
714 // This string is shown on all non-error HTTPS sites on Android when
715 // the user taps "Details" link on page info.
716 identity_status_description_android_.assign(l10n_util::GetStringFUTF16(
717 IDS_PAGE_INFO_SECURE_IDENTITY_VERIFIED,
718 delegate_->GetClientApplicationName(), issuer_name));
719 #endif
720 }
721 if (security_state::IsSHA1InChain(visible_security_state)) {
722 site_identity_status_ =
723 SITE_IDENTITY_STATUS_DEPRECATED_SIGNATURE_ALGORITHM;
724
725 #if defined(OS_ANDROID)
726 identity_status_description_android_ +=
727 UTF8ToUTF16("\n\n") +
728 l10n_util::GetStringUTF16(
729 IDS_PAGE_INFO_SECURITY_TAB_DEPRECATED_SIGNATURE_ALGORITHM);
730 #endif
731 }
732 }
733 } else {
734 // HTTP or HTTPS with errors (not warnings).
735 if (!security_state::IsSchemeCryptographic(visible_security_state.url) ||
736 !visible_security_state.certificate) {
737 site_identity_status_ = SITE_IDENTITY_STATUS_NO_CERT;
738 } else {
739 site_identity_status_ = SITE_IDENTITY_STATUS_ERROR;
740 }
741 #if defined(OS_ANDROID)
742 const base::string16 bullet = UTF8ToUTF16("\n • ");
743 std::vector<ssl_errors::ErrorInfo> errors;
744 ssl_errors::ErrorInfo::GetErrorsForCertStatus(
745 certificate_, visible_security_state.cert_status, url, &errors);
746
747 identity_status_description_android_.assign(l10n_util::GetStringUTF16(
748 IDS_PAGE_INFO_SECURITY_TAB_INSECURE_IDENTITY));
749 for (const ssl_errors::ErrorInfo& error : errors) {
750 identity_status_description_android_ += bullet;
751 identity_status_description_android_ += error.short_description();
752 }
753
754 if (visible_security_state.cert_status & net::CERT_STATUS_NON_UNIQUE_NAME) {
755 identity_status_description_android_ += ASCIIToUTF16("\n\n");
756 identity_status_description_android_ +=
757 l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURITY_TAB_NON_UNIQUE_NAME);
758 }
759 #endif
760 }
761
762 if (visible_security_state.malicious_content_status !=
763 security_state::MALICIOUS_CONTENT_STATUS_NONE) {
764 // The site has been flagged by Safe Browsing. Takes precedence over TLS.
765 base::string16 safe_browsing_details;
766 GetSafeBrowsingStatusByMaliciousContentStatus(
767 visible_security_state.malicious_content_status, &safe_browsing_status_,
768 &safe_browsing_details);
769 #if defined(OS_ANDROID)
770 identity_status_description_android_ = safe_browsing_details;
771 #endif
772
773 #if BUILDFLAG(FULL_SAFE_BROWSING)
774 bool old_show_change_pw_buttons = show_change_password_buttons_;
775 #endif
776 show_change_password_buttons_ =
777 (visible_security_state.malicious_content_status ==
778 security_state::
779 MALICIOUS_CONTENT_STATUS_SIGNED_IN_SYNC_PASSWORD_REUSE ||
780 visible_security_state.malicious_content_status ==
781 security_state::
782 MALICIOUS_CONTENT_STATUS_SIGNED_IN_NON_SYNC_PASSWORD_REUSE ||
783 visible_security_state.malicious_content_status ==
784 security_state::
785 MALICIOUS_CONTENT_STATUS_ENTERPRISE_PASSWORD_REUSE ||
786 visible_security_state.malicious_content_status ==
787 security_state::MALICIOUS_CONTENT_STATUS_SAVED_PASSWORD_REUSE);
788 #if BUILDFLAG(FULL_SAFE_BROWSING)
789 // Only record password reuse when adding the button, not on updates.
790 if (show_change_password_buttons_ && !old_show_change_pw_buttons) {
791 RecordPasswordReuseEvent();
792 }
793 #endif
794 }
795
796 safety_tip_info_ = visible_security_state.safety_tip_info;
797 #if defined(OS_ANDROID)
798 if (security_state::IsSafetyTipUIFeatureEnabled()) {
799 // identity_status_description_android_ is only displayed on Android when
800 // the user taps "Details" link on the page info. Reuse the description from
801 // page info UI.
802 std::unique_ptr<PageInfoUI::SecurityDescription> security_description =
803 PageInfoUI::CreateSafetyTipSecurityDescription(safety_tip_info_);
804 if (security_description) {
805 identity_status_description_android_ = security_description->details;
806 }
807 }
808 #endif
809
810 // Site Connection
811 // We consider anything less than 80 bits encryption to be weak encryption.
812 // TODO(wtc): Bug 1198735: report mixed/unsafe content for unencrypted and
813 // weakly encrypted connections.
814 site_connection_status_ = SITE_CONNECTION_STATUS_UNKNOWN;
815
816 base::string16 subject_name(GetSimpleSiteName(url));
817 if (subject_name.empty()) {
818 subject_name.assign(
819 l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURITY_TAB_UNKNOWN_PARTY));
820 }
821
822 if (!visible_security_state.certificate ||
823 !security_state::IsSchemeCryptographic(visible_security_state.url)) {
824 // Page is still loading (so SSL status is not yet available) or
825 // loaded over HTTP or loaded over HTTPS with no cert.
826 site_connection_status_ = SITE_CONNECTION_STATUS_UNENCRYPTED;
827
828 site_connection_details_.assign(l10n_util::GetStringFUTF16(
829 IDS_PAGE_INFO_SECURITY_TAB_NOT_ENCRYPTED_CONNECTION_TEXT,
830 subject_name));
831 } else if (!visible_security_state.connection_info_initialized) {
832 DCHECK_NE(security_level, security_state::NONE);
833 site_connection_status_ = SITE_CONNECTION_STATUS_ENCRYPTED_ERROR;
834 } else {
835 site_connection_status_ = SITE_CONNECTION_STATUS_ENCRYPTED;
836
837 if (net::ObsoleteSSLStatus(
838 visible_security_state.connection_status,
839 visible_security_state.peer_signature_algorithm) ==
840 net::OBSOLETE_SSL_NONE) {
841 site_connection_details_.assign(l10n_util::GetStringFUTF16(
842 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_CONNECTION_TEXT, subject_name));
843 } else {
844 site_connection_details_.assign(l10n_util::GetStringFUTF16(
845 IDS_PAGE_INFO_SECURITY_TAB_WEAK_ENCRYPTION_CONNECTION_TEXT,
846 subject_name));
847 }
848
849 if (visible_security_state.connection_used_legacy_tls &&
850 !visible_security_state.should_suppress_legacy_tls_warning) {
851 site_connection_status_ = SITE_CONNECTION_STATUS_LEGACY_TLS;
852 }
853
854 ReportAnyInsecureContent(visible_security_state, &site_connection_status_,
855 &site_connection_details_);
856 }
857
858 uint16_t cipher_suite = net::SSLConnectionStatusToCipherSuite(
859 visible_security_state.connection_status);
860 if (visible_security_state.connection_info_initialized && cipher_suite) {
861 int ssl_version = net::SSLConnectionStatusToVersion(
862 visible_security_state.connection_status);
863 const char* ssl_version_str;
864 net::SSLVersionToString(&ssl_version_str, ssl_version);
865 site_connection_details_ += ASCIIToUTF16("\n\n");
866 site_connection_details_ += l10n_util::GetStringFUTF16(
867 IDS_PAGE_INFO_SECURITY_TAB_SSL_VERSION, ASCIIToUTF16(ssl_version_str));
868
869 const char *key_exchange, *cipher, *mac;
870 bool is_aead, is_tls13;
871 net::SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead,
872 &is_tls13, cipher_suite);
873
874 site_connection_details_ += ASCIIToUTF16("\n\n");
875 if (is_aead) {
876 if (is_tls13) {
877 // For TLS 1.3 ciphers, report the group (historically, curve) as the
878 // key exchange.
879 key_exchange =
880 SSL_get_curve_name(visible_security_state.key_exchange_group);
881 if (!key_exchange) {
882 NOTREACHED();
883 key_exchange = "";
884 }
885 }
886 site_connection_details_ += l10n_util::GetStringFUTF16(
887 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTION_DETAILS_AEAD,
888 ASCIIToUTF16(cipher), ASCIIToUTF16(key_exchange));
889 } else {
890 site_connection_details_ += l10n_util::GetStringFUTF16(
891 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTION_DETAILS, ASCIIToUTF16(cipher),
892 ASCIIToUTF16(mac), ASCIIToUTF16(key_exchange));
893 }
894 }
895
896 // Check if a user decision has been made to allow or deny certificates with
897 // errors on this site.
898 StatefulSSLHostStateDelegate* delegate =
899 delegate_->GetStatefulSSLHostStateDelegate();
900 DCHECK(delegate);
901 // Only show an SSL decision revoke button if the user has chosen to bypass
902 // SSL host errors for this host in the past, and we're not presently on a
903 // Safe Browsing error (since otherwise it's confusing which warning you're
904 // re-enabling).
905 show_ssl_decision_revoke_button_ =
906 delegate->HasAllowException(url.host(), web_contents()) &&
907 visible_security_state.malicious_content_status ==
908 security_state::MALICIOUS_CONTENT_STATUS_NONE;
909 }
910
PresentSitePermissions()911 void PageInfo::PresentSitePermissions() {
912 PermissionInfoList permission_info_list;
913 ChosenObjectInfoList chosen_object_info_list;
914
915 PermissionInfo permission_info;
916 HostContentSettingsMap* content_settings = GetContentSettings();
917 for (const ContentSettingsType type : kPermissionType) {
918 permission_info.type = type;
919
920 content_settings::SettingInfo info;
921
922 // TODO(crbug.com/1030245) Investigate why the value is queried from the low
923 // level routine GetWebsiteSettings.
924 std::unique_ptr<base::Value> value = content_settings->GetWebsiteSetting(
925 site_url_, site_url_, permission_info.type, &info);
926 DCHECK(value.get());
927 if (value->type() == base::Value::Type::INTEGER) {
928 permission_info.setting =
929 content_settings::ValueToContentSetting(value.get());
930 } else {
931 NOTREACHED();
932 }
933
934 permission_info.source = info.source;
935 permission_info.is_incognito =
936 web_contents()->GetBrowserContext()->IsOffTheRecord();
937 permission_info.is_one_time =
938 (info.session_model == content_settings::SessionModel::OneTime);
939
940 if (info.primary_pattern == ContentSettingsPattern::Wildcard() &&
941 info.secondary_pattern == ContentSettingsPattern::Wildcard()) {
942 permission_info.default_setting = permission_info.setting;
943 permission_info.setting = CONTENT_SETTING_DEFAULT;
944 } else {
945 permission_info.default_setting =
946 content_settings->GetDefaultContentSetting(permission_info.type,
947 nullptr);
948 }
949
950 // For permissions that are still prompting the user and haven't been
951 // explicitly set by another source, check its embargo status.
952 if (permissions::PermissionUtil::IsPermission(permission_info.type) &&
953 permission_info.setting == CONTENT_SETTING_DEFAULT &&
954 permission_info.source ==
955 content_settings::SettingSource::SETTING_SOURCE_USER) {
956 permissions::PermissionResult permission_result =
957 delegate_->GetPermissionStatus(permission_info.type, site_url_);
958
959 // If under embargo, update |permission_info| to reflect that.
960 if (permission_result.content_setting == CONTENT_SETTING_BLOCK &&
961 (permission_result.source ==
962 permissions::PermissionStatusSource::MULTIPLE_DISMISSALS ||
963 permission_result.source ==
964 permissions::PermissionStatusSource::MULTIPLE_IGNORES)) {
965 permission_info.setting = permission_result.content_setting;
966 }
967 }
968
969 if (ShouldShowPermission(
970 permission_info, site_url_, content_settings, web_contents(),
971 HasContentSettingChangedViaPageInfo(permission_info.type),
972 delegate_->IsSubresourceFilterActivated(site_url_))) {
973 permission_info_list.push_back(permission_info);
974 }
975 }
976
977 const auto origin = url::Origin::Create(site_url_);
978 for (const ChooserUIInfo& ui_info : kChooserUIInfo) {
979 permissions::ChooserContextBase* context =
980 delegate_->GetChooserContext(ui_info.content_settings_type);
981 if (!context)
982 continue;
983 auto chosen_objects = context->GetGrantedObjects(origin, origin);
984 for (std::unique_ptr<permissions::ChooserContextBase::Object>& object :
985 chosen_objects) {
986 chosen_object_info_list.push_back(
987 std::make_unique<PageInfoUI::ChosenObjectInfo>(ui_info,
988 std::move(object)));
989 }
990 }
991
992 ui_->SetPermissionInfo(permission_info_list,
993 std::move(chosen_object_info_list));
994 }
995
PresentSiteData()996 void PageInfo::PresentSiteData() {
997 CookieInfoList cookie_info_list;
998
999 // Add first party cookie and site data counts.
1000 // TODO(crbug.com/1058597): Remove the calls to the |delegate_| once
1001 // PageSpecificContentSettings has been componentized.
1002 PageInfoUI::CookieInfo cookie_info;
1003 cookie_info.allowed = GetFirstPartyAllowedCookiesCount(site_url_);
1004 cookie_info.blocked = GetFirstPartyBlockedCookiesCount(site_url_);
1005 cookie_info.is_first_party = true;
1006 cookie_info_list.push_back(cookie_info);
1007
1008 // Add third party cookie counts.
1009 cookie_info.allowed = GetThirdPartyAllowedCookiesCount(site_url_);
1010 cookie_info.blocked = GetThirdPartyBlockedCookiesCount(site_url_);
1011 cookie_info.is_first_party = false;
1012 cookie_info_list.push_back(cookie_info);
1013
1014 ui_->SetCookieInfo(cookie_info_list);
1015 }
1016
PresentSiteIdentity()1017 void PageInfo::PresentSiteIdentity() {
1018 // After initialization the status about the site's connection and its
1019 // identity must be available.
1020 DCHECK_NE(site_identity_status_, SITE_IDENTITY_STATUS_UNKNOWN);
1021 DCHECK_NE(site_connection_status_, SITE_CONNECTION_STATUS_UNKNOWN);
1022 PageInfoUI::IdentityInfo info;
1023 info.site_identity = UTF16ToUTF8(GetSimpleSiteName(site_url_));
1024
1025 info.connection_status = site_connection_status_;
1026 info.connection_status_description = UTF16ToUTF8(site_connection_details_);
1027 info.identity_status = site_identity_status_;
1028 info.safe_browsing_status = safe_browsing_status_;
1029 if (security_state::IsSafetyTipUIFeatureEnabled()) {
1030 info.safety_tip_info = safety_tip_info_;
1031 }
1032 #if defined(OS_ANDROID)
1033 info.identity_status_description_android =
1034 UTF16ToUTF8(identity_status_description_android_);
1035 #endif
1036
1037 info.certificate = certificate_;
1038 info.show_ssl_decision_revoke_button = show_ssl_decision_revoke_button_;
1039 info.show_change_password_buttons = show_change_password_buttons_;
1040 ui_->SetIdentityInfo(info);
1041 }
1042
PresentPageFeatureInfo()1043 void PageInfo::PresentPageFeatureInfo() {
1044 PageInfoUI::PageFeatureInfo info;
1045 info.is_vr_presentation_in_headset =
1046 delegate_->IsContentDisplayedInVrHeadset();
1047
1048 ui_->SetPageFeatureInfo(info);
1049 }
1050
1051 #if BUILDFLAG(FULL_SAFE_BROWSING)
RecordPasswordReuseEvent()1052 void PageInfo::RecordPasswordReuseEvent() {
1053 auto* password_protection_service = delegate_->GetPasswordProtectionService();
1054 if (!password_protection_service) {
1055 return;
1056 }
1057 safe_browsing::LogWarningAction(
1058 safe_browsing::WarningUIType::PAGE_INFO,
1059 safe_browsing::WarningAction::SHOWN,
1060 password_protection_service
1061 ->reused_password_account_type_for_last_shown_warning());
1062 }
1063 #endif
1064
GetContentSettings() const1065 HostContentSettingsMap* PageInfo::GetContentSettings() const {
1066 return delegate_->GetContentSettings();
1067 }
1068
GetAllPermissionsForTesting()1069 std::vector<ContentSettingsType> PageInfo::GetAllPermissionsForTesting() {
1070 std::vector<ContentSettingsType> permission_list;
1071 for (const ContentSettingsType type : kPermissionType)
1072 permission_list.push_back(type);
1073
1074 return permission_list;
1075 }
1076
GetSafeBrowsingStatusByMaliciousContentStatus(security_state::MaliciousContentStatus malicious_content_status,PageInfo::SafeBrowsingStatus * status,base::string16 * details)1077 void PageInfo::GetSafeBrowsingStatusByMaliciousContentStatus(
1078 security_state::MaliciousContentStatus malicious_content_status,
1079 PageInfo::SafeBrowsingStatus* status,
1080 base::string16* details) {
1081 switch (malicious_content_status) {
1082 case security_state::MALICIOUS_CONTENT_STATUS_NONE:
1083 NOTREACHED();
1084 break;
1085 case security_state::MALICIOUS_CONTENT_STATUS_MALWARE:
1086 *status = PageInfo::SAFE_BROWSING_STATUS_MALWARE;
1087 *details = l10n_util::GetStringUTF16(IDS_PAGE_INFO_MALWARE_DETAILS);
1088 break;
1089 case security_state::MALICIOUS_CONTENT_STATUS_SOCIAL_ENGINEERING:
1090 *status = PageInfo::SAFE_BROWSING_STATUS_SOCIAL_ENGINEERING;
1091 *details =
1092 l10n_util::GetStringUTF16(IDS_PAGE_INFO_SOCIAL_ENGINEERING_DETAILS);
1093 break;
1094 case security_state::MALICIOUS_CONTENT_STATUS_UNWANTED_SOFTWARE:
1095 *status = PageInfo::SAFE_BROWSING_STATUS_UNWANTED_SOFTWARE;
1096 *details =
1097 l10n_util::GetStringUTF16(IDS_PAGE_INFO_UNWANTED_SOFTWARE_DETAILS);
1098 break;
1099 case security_state::MALICIOUS_CONTENT_STATUS_SAVED_PASSWORD_REUSE:
1100 #if BUILDFLAG(FULL_SAFE_BROWSING)
1101 *status = PageInfo::SAFE_BROWSING_STATUS_SAVED_PASSWORD_REUSE;
1102 *details = delegate_->GetWarningDetailText();
1103 #endif
1104 break;
1105 case security_state::MALICIOUS_CONTENT_STATUS_SIGNED_IN_SYNC_PASSWORD_REUSE:
1106 #if BUILDFLAG(FULL_SAFE_BROWSING)
1107 *status = PageInfo::SAFE_BROWSING_STATUS_SIGNED_IN_SYNC_PASSWORD_REUSE;
1108 *details = delegate_->GetWarningDetailText();
1109 #endif
1110 break;
1111 case security_state::
1112 MALICIOUS_CONTENT_STATUS_SIGNED_IN_NON_SYNC_PASSWORD_REUSE:
1113 #if BUILDFLAG(FULL_SAFE_BROWSING)
1114 *status =
1115 PageInfo::SAFE_BROWSING_STATUS_SIGNED_IN_NON_SYNC_PASSWORD_REUSE;
1116 *details = delegate_->GetWarningDetailText();
1117 #endif
1118 break;
1119 case security_state::MALICIOUS_CONTENT_STATUS_ENTERPRISE_PASSWORD_REUSE:
1120 #if BUILDFLAG(FULL_SAFE_BROWSING)
1121 *status = PageInfo::SAFE_BROWSING_STATUS_ENTERPRISE_PASSWORD_REUSE;
1122 *details = delegate_->GetWarningDetailText();
1123 #endif
1124 break;
1125 case security_state::MALICIOUS_CONTENT_STATUS_BILLING:
1126 *status = PageInfo::SAFE_BROWSING_STATUS_BILLING;
1127 *details = l10n_util::GetStringUTF16(IDS_PAGE_INFO_BILLING_DETAILS);
1128 break;
1129 }
1130 }
1131
1132 content_settings::PageSpecificContentSettings*
GetPageSpecificContentSettings() const1133 PageInfo::GetPageSpecificContentSettings() const {
1134 // TODO(https://crbug.com/1103176): PageInfo should be per page. Why is it
1135 // a WebContentsObserver if it is not observing anything?
1136 return content_settings::PageSpecificContentSettings::GetForFrame(
1137 web_contents()->GetMainFrame());
1138 }
1139
HasContentSettingChangedViaPageInfo(ContentSettingsType type)1140 bool PageInfo::HasContentSettingChangedViaPageInfo(ContentSettingsType type) {
1141 auto* settings = GetPageSpecificContentSettings();
1142 if (!settings)
1143 return false;
1144
1145 return settings->HasContentSettingChangedViaPageInfo(type);
1146 }
1147
ContentSettingChangedViaPageInfo(ContentSettingsType type)1148 void PageInfo::ContentSettingChangedViaPageInfo(ContentSettingsType type) {
1149 auto* settings = GetPageSpecificContentSettings();
1150 if (!settings)
1151 return;
1152
1153 return settings->ContentSettingChangedViaPageInfo(type);
1154 }
1155
GetFirstPartyAllowedCookiesCount(const GURL & site_url)1156 int PageInfo::GetFirstPartyAllowedCookiesCount(const GURL& site_url) {
1157 auto* settings = GetPageSpecificContentSettings();
1158 if (!settings)
1159 return 0;
1160 return settings->allowed_local_shared_objects().GetObjectCountForDomain(
1161 site_url);
1162 }
1163
GetFirstPartyBlockedCookiesCount(const GURL & site_url)1164 int PageInfo::GetFirstPartyBlockedCookiesCount(const GURL& site_url) {
1165 auto* settings = GetPageSpecificContentSettings();
1166 if (!settings)
1167 return 0;
1168
1169 return settings->blocked_local_shared_objects().GetObjectCountForDomain(
1170 site_url);
1171 }
1172
GetThirdPartyAllowedCookiesCount(const GURL & site_url)1173 int PageInfo::GetThirdPartyAllowedCookiesCount(const GURL& site_url) {
1174 auto* settings = GetPageSpecificContentSettings();
1175 if (!settings)
1176 return 0;
1177
1178 return settings->allowed_local_shared_objects().GetObjectCount() -
1179 GetFirstPartyAllowedCookiesCount(site_url);
1180 }
1181
GetThirdPartyBlockedCookiesCount(const GURL & site_url)1182 int PageInfo::GetThirdPartyBlockedCookiesCount(const GURL& site_url) {
1183 auto* settings = GetPageSpecificContentSettings();
1184 if (!settings)
1185 return 0;
1186
1187 return settings->blocked_local_shared_objects().GetObjectCount() -
1188 GetFirstPartyBlockedCookiesCount(site_url);
1189 }
1190