1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/page_info/page_info.h"
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/user_metrics.h"
19 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "base/values.h"
22 #include "build/build_config.h"
23 #include "components/browser_ui/util/android/url_constants.h"
24 #include "components/browsing_data/content/local_storage_helper.h"
25 #include "components/content_settings/browser/page_specific_content_settings.h"
26 #include "components/content_settings/browser/ui/cookie_controls_controller.h"
27 #include "components/content_settings/core/browser/content_settings_registry.h"
28 #include "components/content_settings/core/browser/content_settings_utils.h"
29 #include "components/content_settings/core/browser/host_content_settings_map.h"
30 #include "components/content_settings/core/common/content_settings.h"
31 #include "components/content_settings/core/common/content_settings_pattern.h"
32 #include "components/content_settings/core/common/content_settings_utils.h"
33 #include "components/page_info/page_info_delegate.h"
34 #include "components/page_info/page_info_ui.h"
35 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
36 #include "components/permissions/object_permission_context_base.h"
37 #include "components/permissions/permission_decision_auto_blocker.h"
38 #include "components/permissions/permission_manager.h"
39 #include "components/permissions/permission_result.h"
40 #include "components/permissions/permission_uma_util.h"
41 #include "components/permissions/permission_util.h"
42 #include "components/permissions/permissions_client.h"
43 #if BUILDFLAG(IS_ANDROID)
44 #include "components/resources/android/theme_resources.h"
46 #include "build/chromeos_buildflags.h"
47 #include "components/page_info/core/features.h"
48 #include "components/privacy_sandbox/privacy_sandbox_features.h"
49 #include "components/safe_browsing/buildflags.h"
50 #include "components/safe_browsing/content/browser/password_protection/password_protection_service.h"
51 #include "components/safe_browsing/core/browser/password_protection/metrics_util.h"
52 #include "components/safe_browsing/core/common/proto/csd.pb.h"
53 #include "components/security_interstitials/content/stateful_ssl_host_state_delegate.h"
54 #include "components/signin/public/identity_manager/account_info.h"
55 #include "components/ssl_errors/error_info.h"
56 #include "components/strings/grit/components_chromium_strings.h"
57 #include "components/strings/grit/components_strings.h"
58 #include "components/subresource_filter/core/browser/subresource_filter_features.h"
59 #include "components/url_formatter/elide_url.h"
60 #include "content/public/browser/browser_context.h"
61 #include "content/public/browser/browser_thread.h"
62 #include "content/public/common/content_features.h"
63 #include "content/public/common/url_constants.h"
64 #include "net/cert/cert_status_flags.h"
65 #include "net/cert/x509_certificate.h"
66 #include "net/ssl/ssl_cipher_suite_names.h"
67 #include "net/ssl/ssl_connection_status_flags.h"
68 #include "services/metrics/public/cpp/ukm_builders.h"
69 #include "services/metrics/public/cpp/ukm_recorder.h"
70 #include "third_party/boringssl/src/include/openssl/ssl.h"
71 #include "ui/base/l10n/l10n_util.h"
72 #include "url/origin.h"
74 using base::ASCIIToUTF16;
75 using base::UTF16ToUTF8;
76 using base::UTF8ToUTF16;
77 using content::BrowserThread;
78 using safe_browsing::LoginReputationClientResponse;
79 using safe_browsing::RequestOutcome;
83 // The list of content settings types to display on the Page Info UI. THE
84 // ORDER OF THESE ITEMS IS IMPORTANT and comes from https://crbug.com/610358. To
85 // propose changing it, email security-dev@chromium.org.
86 ContentSettingsType kPermissionType[] = {
87 ContentSettingsType::GEOLOCATION,
88 ContentSettingsType::MEDIASTREAM_CAMERA,
89 ContentSettingsType::CAMERA_PAN_TILT_ZOOM,
90 ContentSettingsType::MEDIASTREAM_MIC,
91 ContentSettingsType::SENSORS,
92 ContentSettingsType::NOTIFICATIONS,
93 ContentSettingsType::JAVASCRIPT,
94 #if !BUILDFLAG(IS_ANDROID)
95 ContentSettingsType::IMAGES,
97 ContentSettingsType::POPUPS,
98 ContentSettingsType::WINDOW_MANAGEMENT,
99 ContentSettingsType::ADS,
100 ContentSettingsType::BACKGROUND_SYNC,
101 ContentSettingsType::SOUND,
102 ContentSettingsType::AUTOMATIC_DOWNLOADS,
103 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
104 ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER,
106 ContentSettingsType::MIDI_SYSEX,
107 ContentSettingsType::CLIPBOARD_READ_WRITE,
108 #if BUILDFLAG(IS_ANDROID)
109 ContentSettingsType::NFC,
111 ContentSettingsType::USB_GUARD,
112 #if !BUILDFLAG(IS_ANDROID)
113 ContentSettingsType::HID_GUARD,
114 ContentSettingsType::SERIAL_GUARD,
115 ContentSettingsType::FILE_SYSTEM_WRITE_GUARD,
116 ContentSettingsType::LOCAL_FONTS,
118 ContentSettingsType::BLUETOOTH_GUARD,
119 ContentSettingsType::BLUETOOTH_SCANNING,
120 ContentSettingsType::VR,
121 ContentSettingsType::AR,
122 ContentSettingsType::IDLE_DETECTION,
123 ContentSettingsType::FEDERATED_IDENTITY_API,
126 // Determines whether to show permission |type| in the Page Info UI. Only
127 // applies to permissions listed in |kPermissionType|.
128 bool ShouldShowPermission(const PageInfo::PermissionInfo& info,
129 const GURL& site_url,
130 HostContentSettingsMap* content_settings,
131 content::WebContents* web_contents,
132 bool changed_since_last_page_load,
133 bool is_subresource_filter_activated) {
134 // Note |ContentSettingsType::ADS| will show up regardless of its default
135 // value when it has been activated on the current origin.
136 if (info.type == ContentSettingsType::ADS) {
137 if (!base::FeatureList::IsEnabled(
138 subresource_filter::kSafeBrowsingSubresourceFilter)) {
142 return is_subresource_filter_activated;
145 if (info.type == ContentSettingsType::SOUND) {
146 // The sound content setting should always show up when the tab has played
148 if (web_contents && web_contents->WasEverAudible())
152 const bool is_incognito = web_contents->GetBrowserContext()->IsOffTheRecord();
153 #if BUILDFLAG(IS_ANDROID)
154 // Special geolocation DSE settings apply only on Android, so make sure it
155 // gets checked there regardless of default setting on Desktop.
156 // DSE settings don't apply to incognito mode.
157 if (info.type == ContentSettingsType::GEOLOCATION && !is_incognito)
160 // The File System write permission is desktop only at the moment.
161 if (info.type == ContentSettingsType::FILE_SYSTEM_WRITE_GUARD)
164 // NFC is Android-only at the moment.
165 if (info.type == ContentSettingsType::NFC)
168 // Display the File System Access write permission if the File System Access
169 // API is currently being used.
170 if (info.type == ContentSettingsType::FILE_SYSTEM_WRITE_GUARD &&
171 web_contents->HasFileSystemAccessHandles()) {
175 // Hide camera if camera PTZ is granted or blocked.
176 if (info.type == ContentSettingsType::MEDIASTREAM_CAMERA) {
177 const base::Value value = content_settings->GetWebsiteSetting(
178 site_url, site_url, ContentSettingsType::CAMERA_PAN_TILT_ZOOM, nullptr);
179 DCHECK(value.is_int());
180 ContentSetting camera_ptz_setting =
181 content_settings::ValueToContentSetting(value);
182 if (camera_ptz_setting == CONTENT_SETTING_ALLOW ||
183 camera_ptz_setting == CONTENT_SETTING_BLOCK) {
189 // Show the content setting if it has been changed by the user since the last
191 if (changed_since_last_page_load) {
195 // Show the Bluetooth guard permission if the new permissions backend is
197 if (info.type == ContentSettingsType::BLUETOOTH_GUARD &&
198 base::FeatureList::IsEnabled(
199 features::kWebBluetoothNewPermissionsBackend) &&
200 !PageInfo::IsPermissionFactoryDefault(info, is_incognito)) {
204 // Show the content setting when it has a non-default value.
205 if (!PageInfo::IsPermissionFactoryDefault(info, is_incognito))
211 // If the |visible_security_state| indicates that mixed content or certificate
212 // errors were present, update |connection_status| and |connection_details|.
213 void ReportAnyInsecureContent(
214 const security_state::VisibleSecurityState& visible_security_state,
215 PageInfo::SiteConnectionStatus* connection_status,
216 std::u16string* connection_details) {
217 bool displayed_insecure_content =
218 visible_security_state.displayed_mixed_content;
219 bool ran_insecure_content = visible_security_state.ran_mixed_content;
220 // Only note subresources with certificate errors if the main resource was
221 // loaded without major certificate errors. If the main resource had a
222 // certificate error, then it would not be that useful (and could
223 // potentially be confusing) to warn about subresources that had certificate
225 if (!net::IsCertStatusError(visible_security_state.cert_status)) {
226 displayed_insecure_content =
227 displayed_insecure_content ||
228 visible_security_state.displayed_content_with_cert_errors;
229 ran_insecure_content = ran_insecure_content ||
230 visible_security_state.ran_content_with_cert_errors;
233 // Only one insecure content warning is displayed; show the most severe.
234 if (ran_insecure_content) {
236 PageInfo::SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE;
237 connection_details->assign(l10n_util::GetStringFUTF16(
238 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_SENTENCE_LINK, *connection_details,
239 l10n_util::GetStringUTF16(
240 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_INSECURE_CONTENT_ERROR)));
243 if (visible_security_state.contained_mixed_form) {
244 *connection_status = PageInfo::SITE_CONNECTION_STATUS_INSECURE_FORM_ACTION;
245 connection_details->assign(l10n_util::GetStringFUTF16(
246 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_SENTENCE_LINK, *connection_details,
247 l10n_util::GetStringUTF16(
248 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_INSECURE_FORM_WARNING)));
251 if (displayed_insecure_content) {
253 PageInfo::SITE_CONNECTION_STATUS_INSECURE_PASSIVE_SUBRESOURCE;
254 connection_details->assign(l10n_util::GetStringFUTF16(
255 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_SENTENCE_LINK, *connection_details,
256 l10n_util::GetStringUTF16(
257 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_INSECURE_CONTENT_WARNING)));
261 // The list of chooser types that need to display entries in the Website
262 // Settings UI. THE ORDER OF THESE ITEMS IS IMPORTANT. To propose changing it,
263 // email security-dev@chromium.org.
264 const PageInfo::ChooserUIInfo kChooserUIInfo[] = {
265 {ContentSettingsType::USB_CHOOSER_DATA,
266 IDS_PAGE_INFO_USB_DEVICE_SECONDARY_LABEL,
267 IDS_PAGE_INFO_USB_DEVICE_ALLOWED_BY_POLICY_LABEL,
268 IDS_PAGE_INFO_DELETE_USB_DEVICE},
269 #if !BUILDFLAG(IS_ANDROID)
270 {ContentSettingsType::HID_CHOOSER_DATA,
271 IDS_PAGE_INFO_HID_DEVICE_SECONDARY_LABEL,
272 IDS_PAGE_INFO_HID_DEVICE_ALLOWED_BY_POLICY_LABEL,
273 IDS_PAGE_INFO_DELETE_HID_DEVICE},
274 {ContentSettingsType::SERIAL_CHOOSER_DATA,
275 IDS_PAGE_INFO_SERIAL_PORT_SECONDARY_LABEL,
276 IDS_PAGE_INFO_SERIAL_PORT_ALLOWED_BY_POLICY_LABEL,
277 IDS_PAGE_INFO_DELETE_SERIAL_PORT},
279 {ContentSettingsType::BLUETOOTH_CHOOSER_DATA,
280 IDS_PAGE_INFO_BLUETOOTH_DEVICE_SECONDARY_LABEL,
281 /*allowed_by_policy_description_string_id=*/-1,
282 IDS_PAGE_INFO_DELETE_BLUETOOTH_DEVICE},
285 void LogTimeOpenHistogram(const std::string& name, base::TimeTicks start_time) {
286 base::UmaHistogramCustomTimes(name, base::TimeTicks::Now() - start_time,
287 base::Milliseconds(1), base::Hours(1), 100);
290 // Time open histogram prefixes.
291 const char kPageInfoTimePrefix[] = "Security.PageInfo.TimeOpen";
292 const char kPageInfoTimeActionPrefix[] = "Security.PageInfo.TimeOpen.Action";
293 const char kPageInfoTimeNoActionPrefix[] =
294 "Security.PageInfo.TimeOpen.NoAction";
298 PageInfo::PageInfo(std::unique_ptr<PageInfoDelegate> delegate,
299 content::WebContents* web_contents,
301 : web_contents_(web_contents->GetWeakPtr()),
302 delegate_(std::move(delegate)),
303 show_info_bar_(false),
305 site_identity_status_(SITE_IDENTITY_STATUS_UNKNOWN),
306 safe_browsing_status_(SAFE_BROWSING_STATUS_NONE),
307 safety_tip_info_({security_state::SafetyTipStatus::kUnknown, GURL()}),
308 site_connection_status_(SITE_CONNECTION_STATUS_UNKNOWN),
309 show_ssl_decision_revoke_button_(false),
310 did_revoke_user_ssl_decisions_(false),
311 show_change_password_buttons_(false),
312 did_perform_action_(false) {
314 security_level_ = delegate_->GetSecurityLevel();
315 visible_security_state_for_metrics_ = delegate_->GetVisibleSecurityState();
316 #if !BUILDFLAG(IS_ANDROID)
317 isolated_web_app_name_ = delegate_->GetWebAppShortName();
320 // TabSpecificContentSetting needs to be created before page load.
321 DCHECK(GetPageSpecificContentSettings());
322 ComputeUIInputs(site_url_);
324 // Every time this is created, page info dialog is opened.
325 // So this counts how often the page Info dialog is opened.
326 RecordPageInfoAction(PAGE_INFO_OPENED);
328 // Record the time when the page info dialog is opened so the total time it is
329 // open can be measured.
330 start_time_ = base::TimeTicks::Now();
332 #if !BUILDFLAG(IS_ANDROID)
334 controller_ = delegate_->CreateCookieControlsController();
335 observation_.Observe(controller_.get());
337 controller_->Update(web_contents);
342 PageInfo::~PageInfo() {
343 // Check if Re-enable warnings button was visible, if so, log on UMA whether
344 // it was clicked or not.
345 SSLCertificateDecisionsDidRevoke user_decision =
346 did_revoke_user_ssl_decisions_ ? USER_CERT_DECISIONS_REVOKED
347 : USER_CERT_DECISIONS_NOT_REVOKED;
348 if (show_ssl_decision_revoke_button_) {
349 base::UmaHistogramEnumeration(
350 "interstitial.ssl.did_user_revoke_decisions2", user_decision,
351 END_OF_SSL_CERTIFICATE_DECISIONS_DID_REVOKE_ENUM);
354 // Record the total time the Page Info UI was open for all opens as well as
355 // split between whether any action was taken.
356 LogTimeOpenHistogram(security_state::GetSecurityLevelHistogramName(
357 kPageInfoTimePrefix, security_level_),
359 LogTimeOpenHistogram(security_state::GetSafetyTipHistogramName(
360 kPageInfoTimePrefix, safety_tip_info_.status),
362 if (did_perform_action_) {
363 LogTimeOpenHistogram(security_state::GetSecurityLevelHistogramName(
364 kPageInfoTimeActionPrefix, security_level_),
366 LogTimeOpenHistogram(
367 security_state::GetSafetyTipHistogramName(kPageInfoTimeActionPrefix,
368 safety_tip_info_.status),
371 LogTimeOpenHistogram(security_state::GetSecurityLevelHistogramName(
372 kPageInfoTimeNoActionPrefix, security_level_),
374 LogTimeOpenHistogram(
375 security_state::GetSafetyTipHistogramName(kPageInfoTimeNoActionPrefix,
376 safety_tip_info_.status),
381 void PageInfo::OnStatusChanged(CookieControlsStatus status,
382 CookieControlsEnforcement enforcement,
384 int blocked_cookies) {
385 #if !BUILDFLAG(IS_ANDROID)
386 if (base::FeatureList::IsEnabled(page_info::kPageInfoCookiesSubpage)) {
387 if (status != status_ || enforcement != enforcement_) {
389 enforcement_ = enforcement;
390 PresentSiteData(base::DoNothing());
396 void PageInfo::OnCookiesCountChanged(int allowed_cookies, int blocked_cookies) {
399 void PageInfo::OnThirdPartyToggleClicked(bool block_third_party_cookies) {
400 DCHECK(status_ != CookieControlsStatus::kDisabled);
401 DCHECK(status_ != CookieControlsStatus::kUninitialized);
402 RecordPageInfoAction(block_third_party_cookies
403 ? PAGE_INFO_COOKIES_BLOCKED_FOR_SITE
404 : PAGE_INFO_COOKIES_ALLOWED_FOR_SITE);
405 controller_->OnCookieBlockingEnabledForSite(block_third_party_cookies);
409 bool PageInfo::IsPermissionFactoryDefault(const PermissionInfo& info,
411 const ContentSetting factory_default_setting =
412 content_settings::ContentSettingsRegistry::GetInstance()
414 ->GetInitialDefaultSetting();
416 // Settings that are granted in regular mode get reduced to ASK in incognito
417 // mode. These settings should not be displayed either.
418 const bool is_incognito_default =
419 is_incognito && info.setting == CONTENT_SETTING_ASK &&
420 factory_default_setting == CONTENT_SETTING_ASK;
422 return info.source == content_settings::SETTING_SOURCE_USER &&
423 factory_default_setting == info.default_setting &&
424 (info.setting == CONTENT_SETTING_DEFAULT || is_incognito_default);
428 bool PageInfo::IsFileOrInternalPage(const GURL& url) {
429 return url.SchemeIs(content::kChromeUIScheme) ||
430 url.SchemeIs(content::kChromeDevToolsScheme) ||
431 url.SchemeIs(content::kViewSourceScheme) ||
432 url.SchemeIs(url::kFileScheme);
435 void PageInfo::InitializeUiState(PageInfoUI* ui, base::OnceClosure done) {
439 PresentSitePermissions();
440 PresentSiteIdentity();
441 PresentPageFeatureInfo();
442 PresentSiteData(std::move(done));
443 PresentAdPersonalizationData();
446 void PageInfo::UpdateSecurityState() {
447 ComputeUIInputs(site_url_);
448 PresentSiteIdentity();
451 void PageInfo::RecordPageInfoAction(PageInfoAction action) {
452 if (action != PAGE_INFO_OPENED)
453 did_perform_action_ = true;
455 #if !BUILDFLAG(IS_ANDROID)
456 delegate_->OnPageInfoActionOccurred(action);
459 base::UmaHistogramEnumeration("WebsiteSettings.Action", action);
462 ukm::builders::PageInfoBubble(
463 web_contents_->GetPrimaryMainFrame()->GetPageUkmSourceId())
464 .SetActionTaken(action)
465 .Record(ukm::UkmRecorder::Get());
468 base::UmaHistogramEnumeration(
469 security_state::GetSafetyTipHistogramName(
470 "Security.SafetyTips.PageInfo.Action", safety_tip_info_.status),
473 auto* settings = GetPageSpecificContentSettings();
477 bool has_topic = settings->HasAccessedTopics();
478 bool has_fledge = settings->HasJoinedUserToInterestGroup();
480 case PageInfoAction::PAGE_INFO_OPENED:
481 base::RecordAction(base::UserMetricsAction("PageInfo.Opened"));
482 base::UmaHistogramBoolean("Security.PageInfo.AdPersonalizationRowShown",
483 has_fledge || has_topic);
485 case PageInfoAction::PAGE_INFO_AD_PERSONALIZATION_PAGE_OPENED:
486 if (has_fledge && has_topic) {
487 base::RecordAction(base::UserMetricsAction(
488 "PageInfo.AdPersonalization.OpenedWithFledgeAndTopics"));
489 } else if (has_fledge) {
490 base::RecordAction(base::UserMetricsAction(
491 "PageInfo.AdPersonalization.OpenedWithFledge"));
492 } else if (has_topic) {
493 base::RecordAction(base::UserMetricsAction(
494 "PageInfo.AdPersonalization.OpenedWithTopics"));
497 case PageInfoAction::PAGE_INFO_AD_PERSONALIZATION_SETTINGS_OPENED:
498 base::RecordAction(base::UserMetricsAction(
499 "PageInfo.AdPersonalization.ManageInterestClicked"));
501 case PAGE_INFO_CERTIFICATE_DIALOG_OPENED:
503 base::UserMetricsAction("PageInfo.Security.Certificate.Opened"));
505 case PAGE_INFO_CONNECTION_HELP_OPENED:
507 base::UserMetricsAction("PageInfo.Security.ConnectionHelp.Opened"));
509 case PAGE_INFO_SECURITY_DETAILS_OPENED:
510 base::RecordAction(base::UserMetricsAction("PageInfo.Security.Opened"));
512 case PAGE_INFO_SITE_SETTINGS_OPENED:
514 base::UserMetricsAction("PageInfo.SiteSettings.Opened"));
516 case PAGE_INFO_COOKIES_DIALOG_OPENED:
517 base::RecordAction(base::UserMetricsAction("PageInfo.Cookies.Opened"));
519 case PAGE_INFO_COOKIES_ALLOWED_FOR_SITE:
520 base::RecordAction(base::UserMetricsAction("PageInfo.Cookies.Allowed"));
522 case PAGE_INFO_COOKIES_BLOCKED_FOR_SITE:
523 base::RecordAction(base::UserMetricsAction("PageInfo.Cookies.Blocked"));
525 case PAGE_INFO_COOKIES_CLEARED:
526 base::RecordAction(base::UserMetricsAction("PageInfo.Cookies.Cleared"));
528 case PAGE_INFO_PERMISSION_DIALOG_OPENED:
529 base::RecordAction(base::UserMetricsAction("PageInfo.Permission.Opened"));
531 case PAGE_INFO_CHANGED_PERMISSION:
533 base::UserMetricsAction("PageInfo.Permission.Changed"));
535 case PAGE_INFO_PERMISSIONS_CLEARED:
537 base::UserMetricsAction("PageInfo.Permission.Cleared"));
539 case PAGE_INFO_CHOOSER_OBJECT_DELETED:
541 base::UserMetricsAction("PageInfo.Permission.ChooserObjectDeleted"));
543 case PAGE_INFO_RESET_DECISIONS_CLICKED:
545 base::UserMetricsAction("PageInfo.Permission.ResetDecisions"));
547 case PAGE_INFO_FORGET_SITE_OPENED:
548 base::RecordAction(base::UserMetricsAction("PageInfo.ForgetSite.Opened"));
550 case PAGE_INFO_FORGET_SITE_CLEARED:
552 base::UserMetricsAction("PageInfo.ForgetSite.Cleared"));
554 case PAGE_INFO_HISTORY_OPENED:
555 base::RecordAction(base::UserMetricsAction("PageInfo.History.Opened"));
557 case PAGE_INFO_HISTORY_ENTRY_REMOVED:
559 base::UserMetricsAction("PageInfo.History.EntryRemoved"));
561 case PAGE_INFO_HISTORY_ENTRY_CLICKED:
563 base::UserMetricsAction("PageInfo.History.EntryClicked"));
565 case PAGE_INFO_PASSWORD_REUSE_ALLOWED:
567 base::UserMetricsAction("PageInfo.PasswordReuseAllowed"));
569 case PAGE_INFO_CHANGE_PASSWORD_PRESSED:
571 base::UserMetricsAction("PageInfo.ChangePasswordPressed"));
573 case PAGE_INFO_SAFETY_TIP_HELP_OPENED:
575 base::UserMetricsAction("PageInfo.SafetyTip.HelpOpened"));
577 case PAGE_INFO_STORE_INFO_CLICKED:
578 base::RecordAction(base::UserMetricsAction("PageInfo.StoreInfo.Opened"));
580 case PAGE_INFO_ABOUT_THIS_SITE_PAGE_OPENED:
582 base::UserMetricsAction("PageInfo.AboutThisSite.Opened"));
584 case PAGE_INFO_ABOUT_THIS_SITE_SOURCE_LINK_CLICKED:
586 base::UserMetricsAction("PageInfo.AboutThisSite.SourceLinkClicked"));
588 case PAGE_INFO_ABOUT_THIS_SITE_MORE_ABOUT_CLICKED:
590 base::UserMetricsAction("PageInfo.AboutThisSite.MoreAboutClicked"));
592 case PAGE_INFO_COOKIES_PAGE_OPENED:
594 base::UserMetricsAction("PageInfo.CookiesSubpage.Opened"));
596 case PAGE_INFO_COOKIES_SETTINGS_OPENED:
597 base::RecordAction(base::UserMetricsAction(
598 "PageInfo.CookiesSubpage.SettingsLinkClicked"));
600 case PAGE_INFO_ALL_SITES_WITH_FPS_FILTER_OPENED:
601 base::RecordAction(base::UserMetricsAction(
602 "PageInfo.CookiesSubpage.AllSitesFilteredOpened"));
607 void PageInfo::UpdatePermissions() {
608 // Refresh the UI to reflect the new setting.
609 PresentSitePermissions();
612 void PageInfo::OnSitePermissionChanged(ContentSettingsType type,
613 ContentSetting setting,
615 ContentSettingChangedViaPageInfo(type);
617 // Count how often a permission for a specific content type is changed using
620 int histogram_value = ContentSettingTypeToHistogramValue(type, &num_values);
621 base::UmaHistogramExactLinear("WebsiteSettings.OriginInfo.PermissionChanged",
622 histogram_value, num_values);
624 if (setting == ContentSetting::CONTENT_SETTING_ALLOW) {
625 base::UmaHistogramExactLinear(
626 "WebsiteSettings.OriginInfo.PermissionChanged.Allowed", histogram_value,
628 } else if (setting == ContentSetting::CONTENT_SETTING_BLOCK) {
629 base::UmaHistogramExactLinear(
630 "WebsiteSettings.OriginInfo.PermissionChanged.Blocked", histogram_value,
634 // This is technically redundant given the histogram above, but putting the
635 // total count of permission changes in another histogram makes it easier to
636 // compare it against other kinds of actions in Page Info.
637 RecordPageInfoAction(PAGE_INFO_CHANGED_PERMISSION);
638 HostContentSettingsMap* content_settings = GetContentSettings();
639 if (type == ContentSettingsType::SOUND) {
640 ContentSetting default_setting = content_settings->GetDefaultContentSetting(
641 ContentSettingsType::SOUND, nullptr);
642 bool mute = (setting == CONTENT_SETTING_BLOCK) ||
643 (setting == CONTENT_SETTING_DEFAULT &&
644 default_setting == CONTENT_SETTING_BLOCK);
647 base::UserMetricsAction("SoundContentSetting.MuteBy.PageInfo"));
650 base::UserMetricsAction("SoundContentSetting.UnmuteBy.PageInfo"));
654 DCHECK(web_contents_);
655 permissions::PermissionUmaUtil::ScopedRevocationReporter
656 scoped_revocation_reporter(web_contents_->GetBrowserContext(), site_url_,
658 permissions::PermissionSourceUI::OIB);
660 // The permission may have been blocked due to being under embargo, so if it
661 // was changed away from BLOCK, clear embargo status if it exists.
662 if (setting != CONTENT_SETTING_BLOCK) {
663 delegate_->GetPermissionDecisionAutoblocker()->RemoveEmbargoAndResetCounts(
666 using Constraints = content_settings::ContentSettingConstraints;
667 content_settings->SetNarrowestContentSetting(
668 site_url_, site_url_, type, setting,
670 ? Constraints{base::Time(), content_settings::SessionModel::OneTime}
673 // When the sound setting is changed, no reload is necessary.
674 if (type != ContentSettingsType::SOUND)
675 show_info_bar_ = true;
677 // Refresh the UI to reflect the new setting.
678 PresentSitePermissions();
681 void PageInfo::OnSiteChosenObjectDeleted(const ChooserUIInfo& ui_info,
682 const base::Value& object) {
683 permissions::ObjectPermissionContextBase* context =
684 delegate_->GetChooserContext(ui_info.content_settings_type);
685 const auto origin = url::Origin::Create(site_url_);
686 context->RevokeObjectPermission(origin, object);
687 show_info_bar_ = true;
689 // Refresh the UI to reflect the changed settings.
690 PresentSitePermissions();
691 RecordPageInfoAction(PAGE_INFO_CHOOSER_OBJECT_DELETED);
694 void PageInfo::OnUIClosing(bool* reload_prompt) {
696 *reload_prompt = false;
697 #if BUILDFLAG(IS_ANDROID)
700 if (show_info_bar_ && web_contents_ && !web_contents_->IsBeingDestroyed()) {
701 if (delegate_->CreateInfoBarDelegate() && reload_prompt)
702 *reload_prompt = true;
704 delegate_->OnUIClosing();
708 void PageInfo::OnRevokeSSLErrorBypassButtonPressed() {
709 auto* stateful_ssl_host_state_delegate =
710 delegate_->GetStatefulSSLHostStateDelegate();
711 DCHECK(stateful_ssl_host_state_delegate);
712 stateful_ssl_host_state_delegate->RevokeUserAllowExceptionsHard(
714 did_revoke_user_ssl_decisions_ = true;
715 RecordPageInfoAction(PAGE_INFO_RESET_DECISIONS_CLICKED);
718 void PageInfo::OpenSiteSettingsView() {
719 #if BUILDFLAG(IS_ANDROID)
722 RecordPageInfoAction(PAGE_INFO_SITE_SETTINGS_OPENED);
723 delegate_->ShowSiteSettings(site_url());
727 void PageInfo::OpenCookiesSettingsView() {
728 #if BUILDFLAG(IS_ANDROID)
731 RecordPageInfoAction(PAGE_INFO_COOKIES_SETTINGS_OPENED);
732 delegate_->ShowCookiesSettings();
736 void PageInfo::OpenAllSitesViewFilteredToFps() {
737 #if BUILDFLAG(IS_ANDROID)
740 auto fps_owner = delegate_->GetFpsOwner(site_url_);
741 RecordPageInfoAction(PAGE_INFO_ALL_SITES_WITH_FPS_FILTER_OPENED);
743 delegate_->ShowAllSitesSettingsFilteredByFpsOwner(*fps_owner);
745 delegate_->ShowAllSitesSettingsFilteredByFpsOwner(std::u16string());
750 void PageInfo::OpenCookiesDialog() {
751 #if BUILDFLAG(IS_ANDROID)
754 if (!web_contents_ || web_contents_->IsBeingDestroyed())
757 RecordPageInfoAction(PAGE_INFO_COOKIES_DIALOG_OPENED);
758 delegate_->OpenCookiesDialog();
762 void PageInfo::OpenCertificateDialog(net::X509Certificate* certificate) {
763 #if BUILDFLAG(IS_ANDROID)
766 if (!web_contents_ || web_contents_->IsBeingDestroyed())
769 gfx::NativeWindow top_window = web_contents_->GetTopLevelNativeWindow();
770 if (certificate && top_window) {
771 RecordPageInfoAction(PAGE_INFO_CERTIFICATE_DIALOG_OPENED);
772 delegate_->OpenCertificateDialog(certificate);
777 void PageInfo::OpenSafetyTipHelpCenterPage() {
778 #if BUILDFLAG(IS_ANDROID)
781 RecordPageInfoAction(PAGE_INFO_SAFETY_TIP_HELP_OPENED);
782 delegate_->OpenSafetyTipHelpCenterPage();
786 void PageInfo::OpenConnectionHelpCenterPage(const ui::Event& event) {
787 #if BUILDFLAG(IS_ANDROID)
790 RecordPageInfoAction(PAGE_INFO_CONNECTION_HELP_OPENED);
791 delegate_->OpenConnectionHelpCenterPage(event);
795 void PageInfo::OpenContentSettingsExceptions(
796 ContentSettingsType content_settings_type) {
797 #if BUILDFLAG(IS_ANDROID)
800 RecordPageInfoAction(PAGE_INFO_CONNECTION_HELP_OPENED);
801 delegate_->OpenContentSettingsExceptions(content_settings_type);
805 void PageInfo::OnChangePasswordButtonPressed() {
806 #if BUILDFLAG(FULL_SAFE_BROWSING)
807 RecordPageInfoAction(PAGE_INFO_CHANGE_PASSWORD_PRESSED);
808 delegate_->OnUserActionOnPasswordUi(
809 safe_browsing::WarningAction::CHANGE_PASSWORD);
813 void PageInfo::OnAllowlistPasswordReuseButtonPressed() {
814 #if BUILDFLAG(FULL_SAFE_BROWSING)
815 RecordPageInfoAction(PAGE_INFO_PASSWORD_REUSE_ALLOWED);
816 delegate_->OnUserActionOnPasswordUi(
817 safe_browsing::WarningAction::MARK_AS_LEGITIMATE);
821 permissions::ObjectPermissionContextBase* PageInfo::GetChooserContextFromUIInfo(
822 const ChooserUIInfo& ui_info) const {
823 return delegate_->GetChooserContext(ui_info.content_settings_type);
826 std::u16string PageInfo::GetSimpleSiteName() const {
827 if (!site_name_for_testing_.empty())
828 return site_name_for_testing_;
830 return url_formatter::FormatUrlForDisplayOmitSchemePathAndTrivialSubdomains(
834 std::u16string PageInfo::GetSiteOriginOrAppNameToDisplay() const {
835 return IsIsolatedWebApp() && !isolated_web_app_name_.empty()
836 ? isolated_web_app_name_
837 : GetSimpleSiteName();
840 void PageInfo::ComputeUIInputs(const GURL& url) {
841 auto security_level = delegate_->GetSecurityLevel();
842 auto visible_security_state = delegate_->GetVisibleSecurityState();
843 #if !BUILDFLAG(IS_ANDROID)
844 // On desktop, internal URLs aren't handled by this class. Instead, a
845 // custom and simpler bubble is shown.
846 DCHECK(!url.SchemeIs(content::kChromeUIScheme) &&
847 !url.SchemeIs(content::kChromeDevToolsScheme) &&
848 !url.SchemeIs(content::kViewSourceScheme) &&
849 !url.SchemeIs(content_settings::kExtensionScheme));
852 bool is_chrome_ui_native_scheme = false;
853 #if BUILDFLAG(IS_ANDROID)
854 is_chrome_ui_native_scheme = url.SchemeIs(browser_ui::kChromeUINativeScheme);
857 if (url.SchemeIs(url::kAboutScheme)) {
858 // All about: URLs except about:blank are redirected.
859 DCHECK_EQ(url::kAboutBlankURL, url.spec());
860 site_identity_status_ = SITE_IDENTITY_STATUS_NO_CERT;
861 #if BUILDFLAG(IS_ANDROID)
862 identity_status_description_android_ =
863 l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURITY_TAB_INSECURE_IDENTITY);
865 site_connection_status_ = SITE_CONNECTION_STATUS_UNENCRYPTED;
866 site_connection_details_ = l10n_util::GetStringFUTF16(
867 IDS_PAGE_INFO_SECURITY_TAB_NOT_ENCRYPTED_CONNECTION_TEXT,
868 UTF8ToUTF16(url.spec()));
872 if (url.SchemeIs(content::kChromeUIScheme) || is_chrome_ui_native_scheme) {
873 site_identity_status_ = SITE_IDENTITY_STATUS_INTERNAL_PAGE;
874 #if BUILDFLAG(IS_ANDROID)
875 identity_status_description_android_ =
876 l10n_util::GetStringUTF16(IDS_PAGE_INFO_INTERNAL_PAGE);
878 site_connection_status_ = SITE_CONNECTION_STATUS_INTERNAL_PAGE;
883 certificate_ = visible_security_state.certificate;
886 (!net::IsCertStatusError(visible_security_state.cert_status))) {
887 // HTTPS with no or minor errors.
888 if (security_level == security_state::SECURE_WITH_POLICY_INSTALLED_CERT) {
889 #if BUILDFLAG(IS_CHROMEOS_ASH)
890 site_identity_status_ = SITE_IDENTITY_STATUS_ADMIN_PROVIDED_CERT;
892 DCHECK(false) << "Policy certificates exist only on ChromeOS";
895 // No major or minor errors.
896 if (visible_security_state.cert_status & net::CERT_STATUS_IS_EV) {
898 site_identity_status_ = SITE_IDENTITY_STATUS_EV_CERT;
900 // Non-EV OK HTTPS page.
901 site_identity_status_ = SITE_IDENTITY_STATUS_CERT;
902 std::u16string issuer_name(
903 UTF8ToUTF16(certificate_->issuer().GetDisplayName()));
904 if (issuer_name.empty()) {
905 issuer_name.assign(l10n_util::GetStringUTF16(
906 IDS_PAGE_INFO_SECURITY_TAB_UNKNOWN_PARTY));
909 #if BUILDFLAG(IS_ANDROID)
910 // This string is shown on all non-error HTTPS sites on Android when
911 // the user taps "Details" link on page info.
912 identity_status_description_android_.assign(l10n_util::GetStringFUTF16(
913 IDS_PAGE_INFO_SECURE_IDENTITY_VERIFIED,
914 delegate_->GetClientApplicationName(), issuer_name));
917 if (security_state::IsSHA1InChain(visible_security_state)) {
918 site_identity_status_ =
919 SITE_IDENTITY_STATUS_DEPRECATED_SIGNATURE_ALGORITHM;
921 #if BUILDFLAG(IS_ANDROID)
922 identity_status_description_android_ +=
924 l10n_util::GetStringUTF16(
925 IDS_PAGE_INFO_SECURITY_TAB_DEPRECATED_SIGNATURE_ALGORITHM);
930 // HTTP or HTTPS with errors (not warnings).
931 if (!security_state::IsSchemeCryptographic(visible_security_state.url) ||
932 !visible_security_state.certificate) {
933 site_identity_status_ = SITE_IDENTITY_STATUS_NO_CERT;
935 site_identity_status_ = SITE_IDENTITY_STATUS_ERROR;
937 #if BUILDFLAG(IS_ANDROID)
938 const std::u16string bullet = u"\n • ";
939 std::vector<ssl_errors::ErrorInfo> errors;
940 ssl_errors::ErrorInfo::GetErrorsForCertStatus(
941 certificate_, visible_security_state.cert_status, url, &errors);
943 identity_status_description_android_.assign(l10n_util::GetStringUTF16(
944 IDS_PAGE_INFO_SECURITY_TAB_INSECURE_IDENTITY));
945 for (const ssl_errors::ErrorInfo& error : errors) {
946 identity_status_description_android_ += bullet;
947 identity_status_description_android_ += error.short_description();
950 if (visible_security_state.cert_status & net::CERT_STATUS_NON_UNIQUE_NAME) {
951 identity_status_description_android_ += u"\n\n";
952 identity_status_description_android_ +=
953 l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURITY_TAB_NON_UNIQUE_NAME);
958 if (visible_security_state.malicious_content_status !=
959 security_state::MALICIOUS_CONTENT_STATUS_NONE) {
960 // The site has been flagged by Safe Browsing. Takes precedence over TLS.
961 GetSafeBrowsingStatusByMaliciousContentStatus(
962 visible_security_state.malicious_content_status, &safe_browsing_status_,
963 &safe_browsing_details_);
964 #if BUILDFLAG(IS_ANDROID)
965 identity_status_description_android_ = safe_browsing_details_;
968 #if BUILDFLAG(FULL_SAFE_BROWSING)
969 bool old_show_change_pw_buttons = show_change_password_buttons_;
971 show_change_password_buttons_ =
972 (visible_security_state.malicious_content_status ==
974 MALICIOUS_CONTENT_STATUS_SIGNED_IN_SYNC_PASSWORD_REUSE ||
975 visible_security_state.malicious_content_status ==
977 MALICIOUS_CONTENT_STATUS_SIGNED_IN_NON_SYNC_PASSWORD_REUSE ||
978 visible_security_state.malicious_content_status ==
980 MALICIOUS_CONTENT_STATUS_ENTERPRISE_PASSWORD_REUSE ||
981 visible_security_state.malicious_content_status ==
982 security_state::MALICIOUS_CONTENT_STATUS_SAVED_PASSWORD_REUSE);
983 #if BUILDFLAG(FULL_SAFE_BROWSING)
984 // Only record password reuse when adding the button, not on updates.
985 if (show_change_password_buttons_ && !old_show_change_pw_buttons) {
986 RecordPasswordReuseEvent();
991 safety_tip_info_ = visible_security_state.safety_tip_info;
992 #if BUILDFLAG(IS_ANDROID)
993 // identity_status_description_android_ is only displayed on Android when
994 // the user taps "Details" link on the page info. Reuse the description from
996 std::unique_ptr<PageInfoUI::SecurityDescription> security_description =
997 PageInfoUI::CreateSafetyTipSecurityDescription(safety_tip_info_);
998 if (security_description) {
999 identity_status_description_android_ = security_description->details;
1004 // We consider anything less than 80 bits encryption to be weak encryption.
1005 // TODO(wtc): Bug 1198735: report mixed/unsafe content for unencrypted and
1006 // weakly encrypted connections.
1007 site_connection_status_ = SITE_CONNECTION_STATUS_UNKNOWN;
1009 std::u16string subject_name(GetSimpleSiteName());
1010 if (subject_name.empty()) {
1011 subject_name.assign(
1012 l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURITY_TAB_UNKNOWN_PARTY));
1015 if (!visible_security_state.certificate ||
1016 !security_state::IsSchemeCryptographic(visible_security_state.url)) {
1017 // Page is still loading (so SSL status is not yet available) or
1018 // loaded over HTTP or loaded over HTTPS with no cert.
1019 site_connection_status_ = SITE_CONNECTION_STATUS_UNENCRYPTED;
1021 site_connection_details_.assign(l10n_util::GetStringFUTF16(
1022 IDS_PAGE_INFO_SECURITY_TAB_NOT_ENCRYPTED_CONNECTION_TEXT,
1024 } else if (!visible_security_state.connection_info_initialized) {
1025 DCHECK_NE(security_level, security_state::NONE);
1026 site_connection_status_ = SITE_CONNECTION_STATUS_ENCRYPTED_ERROR;
1028 site_connection_status_ = SITE_CONNECTION_STATUS_ENCRYPTED;
1030 if (net::ObsoleteSSLStatus(
1031 visible_security_state.connection_status,
1032 visible_security_state.peer_signature_algorithm) ==
1033 net::OBSOLETE_SSL_NONE) {
1034 site_connection_details_.assign(l10n_util::GetStringFUTF16(
1035 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_CONNECTION_TEXT, subject_name));
1037 site_connection_details_.assign(l10n_util::GetStringFUTF16(
1038 IDS_PAGE_INFO_SECURITY_TAB_WEAK_ENCRYPTION_CONNECTION_TEXT,
1042 ReportAnyInsecureContent(visible_security_state, &site_connection_status_,
1043 &site_connection_details_);
1046 uint16_t cipher_suite = net::SSLConnectionStatusToCipherSuite(
1047 visible_security_state.connection_status);
1048 if (visible_security_state.connection_info_initialized && cipher_suite) {
1049 int ssl_version = net::SSLConnectionStatusToVersion(
1050 visible_security_state.connection_status);
1051 const char* ssl_version_str;
1052 net::SSLVersionToString(&ssl_version_str, ssl_version);
1053 site_connection_details_ += u"\n\n";
1054 site_connection_details_ += l10n_util::GetStringFUTF16(
1055 IDS_PAGE_INFO_SECURITY_TAB_SSL_VERSION, ASCIIToUTF16(ssl_version_str));
1057 const char *key_exchange, *cipher, *mac;
1058 bool is_aead, is_tls13;
1059 net::SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead,
1060 &is_tls13, cipher_suite);
1062 site_connection_details_ += u"\n\n";
1065 // For TLS 1.3 ciphers, report the group (historically, curve) as the
1068 SSL_get_curve_name(visible_security_state.key_exchange_group);
1069 if (!key_exchange) {
1074 site_connection_details_ += l10n_util::GetStringFUTF16(
1075 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTION_DETAILS_AEAD,
1076 ASCIIToUTF16(cipher), ASCIIToUTF16(key_exchange));
1078 site_connection_details_ += l10n_util::GetStringFUTF16(
1079 IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTION_DETAILS, ASCIIToUTF16(cipher),
1080 ASCIIToUTF16(mac), ASCIIToUTF16(key_exchange));
1084 // Check if a user decision has been made to allow or deny certificates with
1085 // errors on this site.
1086 StatefulSSLHostStateDelegate* delegate =
1087 delegate_->GetStatefulSSLHostStateDelegate();
1089 // Only show an SSL decision revoke button if the user has chosen to bypass
1090 // SSL host errors for this host in the past, and we're not presently on a
1091 // Safe Browsing error (since otherwise it's confusing which warning you're
1093 DCHECK(web_contents_);
1094 show_ssl_decision_revoke_button_ =
1095 delegate->HasAllowException(
1097 web_contents_->GetPrimaryMainFrame()->GetStoragePartition()) &&
1098 visible_security_state.malicious_content_status ==
1099 security_state::MALICIOUS_CONTENT_STATUS_NONE;
1102 void PageInfo::PresentSitePermissions() {
1103 PermissionInfoList permission_info_list;
1104 ChosenObjectInfoList chosen_object_info_list;
1106 PermissionInfo permission_info;
1107 HostContentSettingsMap* content_settings = GetContentSettings();
1108 DCHECK(web_contents_);
1109 for (const ContentSettingsType type : kPermissionType) {
1110 permission_info.type = type;
1112 content_settings::SettingInfo info;
1114 // TODO(crbug.com/1030245) Investigate why the value is queried from the low
1115 // level routine GetWebsiteSettings.
1116 const base::Value value = content_settings->GetWebsiteSetting(
1117 site_url_, site_url_, permission_info.type, &info);
1118 if (value.is_int()) {
1119 permission_info.setting = content_settings::ValueToContentSetting(value);
1124 permission_info.source = info.source;
1125 permission_info.is_one_time = (info.metadata.session_model ==
1126 content_settings::SessionModel::OneTime);
1128 if (info.primary_pattern == ContentSettingsPattern::Wildcard() &&
1129 info.secondary_pattern == ContentSettingsPattern::Wildcard()) {
1130 permission_info.default_setting = permission_info.setting;
1131 permission_info.setting = CONTENT_SETTING_DEFAULT;
1133 permission_info.default_setting =
1134 content_settings->GetDefaultContentSetting(permission_info.type,
1138 // Check embargo status if the content setting supports embargo.
1139 if (permissions::PermissionDecisionAutoBlocker::IsEnabledForContentSetting(
1140 permission_info.type) &&
1141 permission_info.setting == CONTENT_SETTING_DEFAULT &&
1142 permission_info.source ==
1143 content_settings::SettingSource::SETTING_SOURCE_USER) {
1144 permissions::PermissionResult permission_result(
1145 CONTENT_SETTING_DEFAULT,
1146 permissions::PermissionStatusSource::UNSPECIFIED);
1147 if (permissions::PermissionUtil::IsPermission(permission_info.type)) {
1148 permission_result = delegate_->GetPermissionResult(
1149 permissions::PermissionUtil::ContentSettingTypeToPermissionType(
1150 permission_info.type),
1151 url::Origin::Create(site_url_));
1152 } else if (permission_info.type ==
1153 ContentSettingsType::FEDERATED_IDENTITY_API) {
1154 absl::optional<permissions::PermissionResult> embargo_result =
1155 delegate_->GetPermissionDecisionAutoblocker()->GetEmbargoResult(
1156 site_url_, permission_info.type);
1158 permission_result = *embargo_result;
1161 // If under embargo, update |permission_info| to reflect that.
1162 if (permission_result.content_setting == CONTENT_SETTING_BLOCK &&
1163 (permission_result.source ==
1164 permissions::PermissionStatusSource::MULTIPLE_DISMISSALS ||
1165 permission_result.source ==
1166 permissions::PermissionStatusSource::MULTIPLE_IGNORES)) {
1167 permission_info.setting = permission_result.content_setting;
1171 if (ShouldShowPermission(
1172 permission_info, site_url_, content_settings, web_contents_.get(),
1173 HasContentSettingChangedViaPageInfo(permission_info.type),
1174 delegate_->IsSubresourceFilterActivated(site_url_))) {
1175 permission_info_list.push_back(permission_info);
1179 const auto origin = url::Origin::Create(site_url_);
1180 for (const ChooserUIInfo& ui_info : kChooserUIInfo) {
1181 permissions::ObjectPermissionContextBase* context =
1182 delegate_->GetChooserContext(ui_info.content_settings_type);
1185 auto chosen_objects = context->GetGrantedObjects(origin);
1186 for (std::unique_ptr<permissions::ObjectPermissionContextBase::Object>&
1187 object : chosen_objects) {
1188 chosen_object_info_list.push_back(
1189 std::make_unique<PageInfoUI::ChosenObjectInfo>(ui_info,
1190 std::move(object)));
1194 ui_->SetPermissionInfo(permission_info_list,
1195 std::move(chosen_object_info_list));
1198 void PageInfo::PresentSiteDataInternal(base::OnceClosure done) {
1199 // Since this is called asynchronously, the associated `WebContents` object
1200 // might no longer be available.
1201 if (!web_contents_ || web_contents_->IsBeingDestroyed())
1204 bool is_cookies_subpage_enabled = false;
1205 #if !BUILDFLAG(IS_ANDROID)
1206 is_cookies_subpage_enabled =
1207 base::FeatureList::IsEnabled(page_info::kPageInfoCookiesSubpage);
1210 if (is_cookies_subpage_enabled) {
1211 // Add allowed sites count.
1212 PageInfoUI::CookiesNewInfo cookies_info;
1213 cookies_info.allowed_sites_count = GetSitesWithAllowedCookiesAccessCount();
1214 cookies_info.blocked_sites_count =
1215 GetThirdPartySitesWithBlockedCookiesAccessCount(site_url_);
1217 #if !BUILDFLAG(IS_ANDROID)
1218 if (base::FeatureList::IsEnabled(
1219 privacy_sandbox::kPrivacySandboxFirstPartySetsUI)) {
1220 auto fps_owner = delegate_->GetFpsOwner(site_url_);
1222 cookies_info.fps_info = PageInfoUI::CookiesFpsInfo(*fps_owner);
1223 cookies_info.fps_info->is_managed = delegate_->IsFpsManaged();
1228 cookies_info.status = status_;
1229 cookies_info.enforcement = enforcement_;
1230 ui_->SetCookieInfo(cookies_info);
1232 CookieInfoList cookie_info_list;
1234 // Add first party cookie and site data counts.
1235 PageInfoUI::CookieInfo cookie_info;
1236 cookie_info.allowed = GetFirstPartyAllowedCookiesCount(site_url_);
1237 cookie_info.blocked = GetFirstPartyBlockedCookiesCount(site_url_);
1238 cookie_info.is_first_party = true;
1239 cookie_info_list.push_back(cookie_info);
1241 // Add third party cookie counts.
1242 cookie_info.allowed = GetThirdPartyAllowedCookiesCount(site_url_);
1243 cookie_info.blocked = GetThirdPartyBlockedCookiesCount(site_url_);
1244 cookie_info.is_first_party = false;
1245 cookie_info_list.push_back(cookie_info);
1247 ui_->SetCookieInfo(cookie_info_list);
1250 std::move(done).Run();
1253 void PageInfo::PresentSiteData(base::OnceClosure done) {
1254 auto* settings = GetPageSpecificContentSettings();
1256 settings->allowed_local_shared_objects().UpdateIgnoredEmptyStorageKeys(
1257 base::BindOnce(&PageInfo::PresentSiteDataInternal,
1258 weak_factory_.GetWeakPtr(), std::move(done)));
1262 void PageInfo::PresentSiteIdentity() {
1263 // After initialization the status about the site's connection and its
1264 // identity must be available.
1265 DCHECK_NE(site_identity_status_, SITE_IDENTITY_STATUS_UNKNOWN);
1266 DCHECK_NE(site_connection_status_, SITE_CONNECTION_STATUS_UNKNOWN);
1267 PageInfoUI::IdentityInfo info;
1268 info.site_identity = UTF16ToUTF8(GetSimpleSiteName());
1270 info.connection_status = site_connection_status_;
1271 info.connection_status_description = UTF16ToUTF8(site_connection_details_);
1272 info.identity_status = site_identity_status_;
1273 info.safe_browsing_status = safe_browsing_status_;
1274 info.safe_browsing_details = safe_browsing_details_;
1275 info.safety_tip_info = safety_tip_info_;
1276 #if BUILDFLAG(IS_ANDROID)
1277 info.identity_status_description_android =
1278 UTF16ToUTF8(identity_status_description_android_);
1281 info.certificate = certificate_;
1282 info.show_ssl_decision_revoke_button = show_ssl_decision_revoke_button_;
1283 info.show_change_password_buttons = show_change_password_buttons_;
1284 ui_->SetIdentityInfo(info);
1287 void PageInfo::PresentPageFeatureInfo() {
1288 PageInfoUI::PageFeatureInfo info;
1289 info.is_vr_presentation_in_headset =
1290 delegate_->IsContentDisplayedInVrHeadset();
1292 ui_->SetPageFeatureInfo(info);
1295 void PageInfo::PresentAdPersonalizationData() {
1296 PageInfoUI::AdPersonalizationInfo info;
1297 auto* settings = GetPageSpecificContentSettings();
1301 info.has_joined_user_to_interest_group =
1302 settings->HasJoinedUserToInterestGroup();
1303 info.accessed_topics = settings->GetAccessedTopics();
1304 std::sort(info.accessed_topics.begin(), info.accessed_topics.end(),
1305 [](const privacy_sandbox::CanonicalTopic& a,
1306 const privacy_sandbox::CanonicalTopic& b) {
1307 return a.GetLocalizedRepresentation() <
1308 b.GetLocalizedRepresentation();
1310 ui_->SetAdPersonalizationInfo(info);
1313 #if BUILDFLAG(FULL_SAFE_BROWSING)
1314 void PageInfo::RecordPasswordReuseEvent() {
1315 auto* password_protection_service = delegate_->GetPasswordProtectionService();
1316 if (!password_protection_service) {
1319 safe_browsing::LogWarningAction(
1320 safe_browsing::WarningUIType::PAGE_INFO,
1321 safe_browsing::WarningAction::SHOWN,
1322 password_protection_service
1323 ->reused_password_account_type_for_last_shown_warning());
1327 HostContentSettingsMap* PageInfo::GetContentSettings() const {
1328 return delegate_->GetContentSettings();
1331 std::vector<ContentSettingsType> PageInfo::GetAllPermissionsForTesting() {
1332 std::vector<ContentSettingsType> permission_list;
1333 for (const ContentSettingsType type : kPermissionType)
1334 permission_list.push_back(type);
1336 return permission_list;
1339 void PageInfo::SetSiteNameForTesting(const std::u16string& site_name) {
1340 site_name_for_testing_ = site_name;
1341 PresentSiteIdentity();
1344 void PageInfo::SetIsolatedWebAppNameForTesting(
1345 const std::u16string& isolated_web_app_name) {
1346 is_isolated_web_app_for_testing_ = true;
1347 isolated_web_app_name_ = isolated_web_app_name;
1350 void PageInfo::GetSafeBrowsingStatusByMaliciousContentStatus(
1351 security_state::MaliciousContentStatus malicious_content_status,
1352 PageInfo::SafeBrowsingStatus* status,
1353 std::u16string* details) {
1354 switch (malicious_content_status) {
1355 case security_state::MALICIOUS_CONTENT_STATUS_NONE:
1358 case security_state::MALICIOUS_CONTENT_STATUS_MALWARE:
1359 *status = PageInfo::SAFE_BROWSING_STATUS_MALWARE;
1360 *details = l10n_util::GetStringUTF16(IDS_PAGE_INFO_MALWARE_DETAILS);
1362 case security_state::MALICIOUS_CONTENT_STATUS_SOCIAL_ENGINEERING:
1363 *status = PageInfo::SAFE_BROWSING_STATUS_SOCIAL_ENGINEERING;
1365 l10n_util::GetStringUTF16(IDS_PAGE_INFO_SOCIAL_ENGINEERING_DETAILS);
1367 case security_state::MALICIOUS_CONTENT_STATUS_UNWANTED_SOFTWARE:
1368 *status = PageInfo::SAFE_BROWSING_STATUS_UNWANTED_SOFTWARE;
1370 l10n_util::GetStringUTF16(IDS_PAGE_INFO_UNWANTED_SOFTWARE_DETAILS);
1372 case security_state::MALICIOUS_CONTENT_STATUS_SAVED_PASSWORD_REUSE:
1373 #if BUILDFLAG(FULL_SAFE_BROWSING)
1374 *status = PageInfo::SAFE_BROWSING_STATUS_SAVED_PASSWORD_REUSE;
1375 *details = delegate_->GetWarningDetailText();
1378 case security_state::MALICIOUS_CONTENT_STATUS_SIGNED_IN_SYNC_PASSWORD_REUSE:
1379 #if BUILDFLAG(FULL_SAFE_BROWSING)
1380 *status = PageInfo::SAFE_BROWSING_STATUS_SIGNED_IN_SYNC_PASSWORD_REUSE;
1381 *details = delegate_->GetWarningDetailText();
1384 case security_state::
1385 MALICIOUS_CONTENT_STATUS_SIGNED_IN_NON_SYNC_PASSWORD_REUSE:
1386 #if BUILDFLAG(FULL_SAFE_BROWSING)
1388 PageInfo::SAFE_BROWSING_STATUS_SIGNED_IN_NON_SYNC_PASSWORD_REUSE;
1389 *details = delegate_->GetWarningDetailText();
1392 case security_state::MALICIOUS_CONTENT_STATUS_ENTERPRISE_PASSWORD_REUSE:
1393 #if BUILDFLAG(FULL_SAFE_BROWSING)
1394 *status = PageInfo::SAFE_BROWSING_STATUS_ENTERPRISE_PASSWORD_REUSE;
1395 *details = delegate_->GetWarningDetailText();
1398 case security_state::MALICIOUS_CONTENT_STATUS_BILLING:
1399 *status = PageInfo::SAFE_BROWSING_STATUS_BILLING;
1400 *details = l10n_util::GetStringUTF16(IDS_PAGE_INFO_BILLING_DETAILS);
1405 content_settings::PageSpecificContentSettings*
1406 PageInfo::GetPageSpecificContentSettings() const {
1407 // TODO(https://crbug.com/1103176, https://crbug.com/1233122): PageInfo should
1408 // be per page. Why is it a WebContentsObserver if it is not observing
1410 DCHECK(web_contents_);
1411 return content_settings::PageSpecificContentSettings::GetForFrame(
1412 web_contents_->GetPrimaryMainFrame());
1415 bool PageInfo::HasContentSettingChangedViaPageInfo(ContentSettingsType type) {
1416 auto* settings = GetPageSpecificContentSettings();
1420 return settings->HasContentSettingChangedViaPageInfo(type);
1423 void PageInfo::ContentSettingChangedViaPageInfo(ContentSettingsType type) {
1424 auto* settings = GetPageSpecificContentSettings();
1428 return settings->ContentSettingChangedViaPageInfo(type);
1431 int PageInfo::GetFirstPartyAllowedCookiesCount(const GURL& site_url) {
1432 auto* settings = GetPageSpecificContentSettings();
1435 return settings->allowed_local_shared_objects().GetObjectCountForDomain(
1439 int PageInfo::GetSitesWithAllowedCookiesAccessCount() {
1440 auto* settings = GetPageSpecificContentSettings();
1443 return settings->allowed_local_shared_objects().GetHostCount();
1446 int PageInfo::GetThirdPartySitesWithBlockedCookiesAccessCount(
1447 const GURL& site_url) {
1448 auto* settings = GetPageSpecificContentSettings();
1451 return settings->blocked_local_shared_objects().GetHostCount() -
1452 settings->blocked_local_shared_objects().GetHostCountForDomain(
1456 int PageInfo::GetFirstPartyBlockedCookiesCount(const GURL& site_url) {
1457 auto* settings = GetPageSpecificContentSettings();
1461 return settings->blocked_local_shared_objects().GetObjectCountForDomain(
1465 int PageInfo::GetThirdPartyAllowedCookiesCount(const GURL& site_url) {
1466 auto* settings = GetPageSpecificContentSettings();
1470 return settings->allowed_local_shared_objects().GetObjectCount() -
1471 GetFirstPartyAllowedCookiesCount(site_url);
1474 int PageInfo::GetThirdPartyBlockedCookiesCount(const GURL& site_url) {
1475 auto* settings = GetPageSpecificContentSettings();
1479 return settings->blocked_local_shared_objects().GetObjectCount() -
1480 GetFirstPartyBlockedCookiesCount(site_url);
1483 bool PageInfo::IsIsolatedWebApp() const {
1484 if (is_isolated_web_app_for_testing_)
1487 return web_contents_ &&
1488 web_contents_->GetPrimaryMainFrame()->GetWebExposedIsolationLevel() >=
1489 content::RenderFrameHost::WebExposedIsolationLevel::
1490 kMaybeIsolatedApplication;