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