chromium/chrome/browser/safe_browsing/chrome_password_protection_service.cc

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/safe_browsing/chrome_password_protection_service.h"

#include <memory>
#include <string>

#include "base/containers/contains.h"
#include "base/functional/bind.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
#include "base/metrics/user_metrics_action.h"
#include "base/observer_list.h"
#include "base/rand_util.h"
#include "base/ranges/algorithm.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/password_manager/account_password_store_factory.h"
#include "chrome/browser/password_manager/password_reuse_manager_factory.h"
#include "chrome/browser/policy/chrome_browser_policy_connector.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/safe_browsing/advanced_protection_status_manager.h"
#include "chrome/browser/safe_browsing/advanced_protection_status_manager_factory.h"
#include "chrome/browser/safe_browsing/chrome_user_population_helper.h"
#include "chrome/browser/safe_browsing/safe_browsing_metrics_collector_factory.h"
#include "chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager_factory.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
#include "chrome/browser/safe_browsing/verdict_cache_manager_factory.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/sync/sync_service_factory.h"
#include "chrome/browser/sync/user_event_service_factory.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/google/core/common/google_util.h"
#include "components/omnibox/common/omnibox_features.h"
#include "components/password_manager/core/browser/form_parsing/form_data_parser.h"
#include "components/password_manager/core/browser/insecure_credentials_helper.h"
#include "components/password_manager/core/browser/leak_detection_dialog_utils.h"
#include "components/password_manager/core/browser/password_sync_util.h"
#include "components/password_manager/core/browser/ui/password_check_referrer.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/safe_browsing/content/browser/password_protection/password_protection_commit_deferring_condition.h"
#include "components/safe_browsing/content/browser/password_protection/password_protection_request_content.h"
#include "components/safe_browsing/content/browser/safe_browsing_navigation_observer_manager.h"
#include "components/safe_browsing/content/browser/triggers/trigger_throttler.h"
#include "components/safe_browsing/content/browser/ui_manager.h"
#include "components/safe_browsing/content/browser/unsafe_resource_util.h"
#include "components/safe_browsing/content/browser/web_contents_key.h"
#include "components/safe_browsing/content/browser/web_ui/safe_browsing_ui.h"
#include "components/safe_browsing/core/browser/db/database_manager.h"
#include "components/safe_browsing/core/browser/realtime/policy_engine.h"
#include "components/safe_browsing/core/browser/safe_browsing_metrics_collector.h"
#include "components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher.h"
#include "components/safe_browsing/core/browser/verdict_cache_manager.h"
#include "components/safe_browsing/core/common/features.h"
#include "components/safe_browsing/core/common/proto/csd.pb.h"
#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "components/safe_browsing/core/common/safebrowsing_constants.h"
#include "components/safe_browsing/core/common/utils.h"
#include "components/security_interstitials/core/unsafe_resource.h"
#include "components/signin/public/base/consent_level.h"
#include "components/signin/public/identity_manager/account_info.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/strings/grit/components_strings.h"
#include "components/sync/protocol/user_event_specifics.pb.h"
#include "components/sync/service/sync_service.h"
#include "components/sync_user_events/user_event_service.h"
#include "components/unified_consent/pref_names.h"
#include "components/variations/service/variations_service.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/geometry/size.h"
#include "url/gurl.h"
#include "url/url_util.h"

#if BUILDFLAG(FULL_SAFE_BROWSING)
#include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.h"
#include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_factory.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/chrome_pages.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#endif

#if BUILDFLAG(IS_ANDROID)
#include "chrome/browser/password_manager/android/password_checkup_launcher_helper_impl.h"
#include "chrome/browser/password_manager/android/password_manager_android_util.h"
#include "chrome/browser/safe_browsing/android/password_reuse_controller_android.h"
#include "chrome/browser/safe_browsing/android/safe_browsing_referring_app_bridge_android.h"
#include "components/password_manager/core/browser/password_check_referrer_android.h"
#include "components/password_manager/core/browser/split_stores_and_local_upm.h"
#include "ui/android/window_android.h"
#else
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/hats/trust_safety_sentiment_service.h"
#include "chrome/browser/ui/hats/trust_safety_sentiment_service_factory.h"
#endif

RecordAction;
UserMetricsAction;
BrowserThread;
using enum safe_browsing::ExtendedReportingLevel;
GaiaPasswordReuse;
UserEventSpecifics;
GaiaPasswordCaptured;
PasswordReuseDialogInteraction;
PasswordReuseLookup;
PasswordReuseEvent;
SafeBrowsingStatus;

namespace safe_browsing {

ReusedPasswordAccountType;

namespace {

// The number of user gestures we trace back for login event attribution.
const int kPasswordEventAttributionUserGestureLimit =;

// Probability for sending password protection reports for domains on the
// allowlist for users opted into extended reporting, from non-incognito window.
const float kProbabilityForSendingReportsFromSafeURLs =;

// If user specifically mark a site as legitimate, we will keep this decision
// for 2 days.
const int kOverrideVerdictCacheDurationSec =;

// Frequency to log PasswordCapture event log. Random 24-28 days.
const int kPasswordCaptureEventLogFreqDaysMin =;
const int kPasswordCaptureEventLogFreqDaysExtra =;

int64_t GetMicrosecondsSinceWindowsEpoch(base::Time time) {}

PasswordReuseLookup::ReputationVerdict GetVerdictToLogFromResponse(
    LoginReputationClientResponse::VerdictType response_verdict) {}

// Given a |web_contents|, returns the navigation id of its last committed
// navigation.
int64_t GetLastCommittedNavigationID(content::WebContents* web_contents) {}

// Opens a |url| from |current_web_contents| with |referrer|. |in_new_tab|
// indicates if opening in a new foreground tab or in current tab.
void OpenUrl(content::WebContents* current_web_contents,
             const GURL& url,
             const content::Referrer& referrer,
             bool in_new_tab) {}

int64_t GetNavigationIDFromPrefsByOrigin(PrefService* prefs,
                                         const Origin& origin) {}

// Return a new UserEventSpecifics w/o the navigation_id populated
std::unique_ptr<UserEventSpecifics> GetNewUserEventSpecifics() {}

// Return a new UserEventSpecifics w/ the navigation_id populated
std::unique_ptr<UserEventSpecifics> GetUserEventSpecificsWithNavigationId(
    int64_t navigation_id) {}

// Return a new UserEventSpecifics populated from the web_contents
std::unique_ptr<UserEventSpecifics> GetUserEventSpecifics(
    content::WebContents* web_contents) {}

#if BUILDFLAG(IS_ANDROID)
struct CredentialFoundInStore {
  bool is_account_store;
  bool is_profile_store;
};

// Check whether the compromised credential is saved in the account or
// profile store.
CredentialFoundInStore CheckCredentialsStore(
    const std::vector<password_manager::MatchingReusedCredential>&
        matching_reused_credentials) {
  bool is_account_credential = false;
  bool is_profile_credential = false;

  for (const password_manager::MatchingReusedCredential& credential :
       matching_reused_credentials) {
    // After the store split, the same credential could be stored in both
    // account and profile store, so both checks are necessary.
    if ((credential.in_store &
         password_manager::PasswordForm::Store::kAccountStore) ==
        password_manager::PasswordForm::Store::kAccountStore) {
      is_account_credential = true;
    }
    if ((credential.in_store &
         password_manager::PasswordForm::Store::kProfileStore) ==
        password_manager::PasswordForm::Store::kProfileStore) {
      is_profile_credential = true;
    }
  }

  return CredentialFoundInStore(is_account_credential, is_profile_credential);
}
#endif

}  // namespace

ChromePasswordProtectionService::ChromePasswordProtectionService(
    SafeBrowsingService* sb_service,
    Profile* profile)
    :{}

void ChromePasswordProtectionService::Init() {}

void ChromePasswordProtectionService::Shutdown() {}

ChromePasswordProtectionService::~ChromePasswordProtectionService() = default;

// static
ChromePasswordProtectionService*
ChromePasswordProtectionService::GetPasswordProtectionService(
    Profile* profile) {}

// static
bool ChromePasswordProtectionService::ShouldShowPasswordReusePageInfoBubble(
    content::WebContents* web_contents,
    PasswordType password_type) {}

safe_browsing::LoginReputationClientRequest::UrlDisplayExperiment
ChromePasswordProtectionService::GetUrlDisplayExperiment() const {}

void ChromePasswordProtectionService::ShowModalWarning(
    PasswordProtectionRequest* request,
    LoginReputationClientResponse::VerdictType verdict_type,
    const std::string& verdict_token,
    ReusedPasswordAccountType password_type) {}

void ChromePasswordProtectionService::OnModalWarningShownForSavedPassword(
    content::WebContents* web_contents,
    ReusedPasswordAccountType password_type,
    const std::string& verdict_token) {}

void ChromePasswordProtectionService::OnModalWarningShownForGaiaPassword(
    content::WebContents* web_contents,
    ReusedPasswordAccountType password_type,
    const std::string& verdict_token) {}

void ChromePasswordProtectionService::OnModalWarningShownForEnterprisePassword(
    content::WebContents* web_contents,
    ReusedPasswordAccountType password_type,
    const std::string& verdict_token) {}

void ChromePasswordProtectionService::ShowInterstitial(
    content::WebContents* web_contents,
    ReusedPasswordAccountType password_type) {}

void ChromePasswordProtectionService::OnUserAction(
    content::WebContents* web_contents,
    ReusedPasswordAccountType password_type,
    RequestOutcome outcome,
    LoginReputationClientResponse::VerdictType verdict_type,
    const std::string& verdict_token,
    WarningUIType ui_type,
    WarningAction action) {}

void ChromePasswordProtectionService::AddObserver(Observer* observer) {}

void ChromePasswordProtectionService::RemoveObserver(Observer* observer) {}

void ChromePasswordProtectionService::MaybeStartThreatDetailsCollection(
    content::WebContents* web_contents,
    const std::string& token,
    ReusedPasswordAccountType password_type) {}

void ChromePasswordProtectionService::MaybeFinishCollectingThreatDetails(
    content::WebContents* web_contents,
    bool did_proceed) {}

void ChromePasswordProtectionService::MaybeLogPasswordReuseDetectedEvent(
    content::WebContents* web_contents) {}

void ChromePasswordProtectionService::MaybeLogPasswordReuseDialogInteraction(
    int64_t navigation_id,
    PasswordReuseDialogInteraction::InteractionResult interaction_result) {}

void ChromePasswordProtectionService::MaybeLogPasswordReuseLookupResult(
    content::WebContents* web_contents,
    PasswordReuseLookup::LookupResult result) {}

void ChromePasswordProtectionService::
    MaybeLogPasswordReuseLookupResultWithVerdict(
        content::WebContents* web_contents,
        PasswordType password_type,
        PasswordReuseLookup::LookupResult result,
        PasswordReuseLookup::ReputationVerdict verdict,
        const std::string& verdict_token) {}

void ChromePasswordProtectionService::MaybeLogPasswordReuseLookupEvent(
    content::WebContents* web_contents,
    RequestOutcome outcome,
    PasswordType password_type,
    const LoginReputationClientResponse* response) {}

void ChromePasswordProtectionService::
    CheckGaiaPasswordChangeForAllSignedInUsers(const std::string& username) {}

void ChromePasswordProtectionService::OnGaiaPasswordChanged(
    const std::string& username,
    bool is_other_gaia_password) {}

GURL ChromePasswordProtectionService::GetEnterpriseChangePasswordURL() const {}

GURL ChromePasswordProtectionService::GetDefaultChangePasswordURL() const {}

void ChromePasswordProtectionService::HandleUserActionOnModalWarning(
    content::WebContents* web_contents,
    ReusedPasswordAccountType password_type,
    RequestOutcome outcome,
    LoginReputationClientResponse::VerdictType verdict_type,
    const std::string& verdict_token,
    WarningAction action) {}

void ChromePasswordProtectionService::LogDialogMetricsOnChangePassword(
    content::WebContents* web_contents,
    ReusedPasswordAccountType password_type,
    int64_t navigation_id,
    RequestOutcome outcome,
    LoginReputationClientResponse::VerdictType verdict_type,
    const std::string& verdict_token) {}

void ChromePasswordProtectionService::AddModelWarningBypasstoPref() {}

void ChromePasswordProtectionService::OpenPasswordCheck(
    content::WebContents* web_contents,
    ReusedPasswordAccountType password_type) {}

void ChromePasswordProtectionService::HandleUserActionOnPageInfo(
    content::WebContents* web_contents,
    ReusedPasswordAccountType password_type,
    WarningAction action) {}

void ChromePasswordProtectionService::HandleResetPasswordOnInterstitial(
    content::WebContents* web_contents,
    WarningAction action) {}

std::u16string ChromePasswordProtectionService::GetWarningDetailText(
    ReusedPasswordAccountType password_type) const {}

std::string ChromePasswordProtectionService::GetOrganizationName(
    ReusedPasswordAccountType password_type) const {}

// Disabled on Android, because enterprise reporting extension is not supported.
#if !BUILDFLAG(IS_ANDROID)
void ChromePasswordProtectionService::MaybeReportPasswordReuseDetected(
    const GURL& main_frame_url,
    const std::string& username,
    PasswordType password_type,
    bool is_phishing_url,
    bool warning_shown) {}

void ChromePasswordProtectionService::ReportPasswordChanged() {}
#endif

bool ChromePasswordProtectionService::HasUnhandledEnterprisePasswordReuse(
    content::WebContents* web_contents) const {}

void ChromePasswordProtectionService::OnWarningTriggerChanged() {}

void ChromePasswordProtectionService::OnEnterprisePasswordUrlChanged() {}

bool ChromePasswordProtectionService::CanShowInterstitial(
    ReusedPasswordAccountType password_type,
    const GURL& main_frame_url) {}

void ChromePasswordProtectionService::SetLogPasswordCaptureTimer(
    const base::TimeDelta& delay) {}

void ChromePasswordProtectionService::MaybeLogPasswordCapture(bool did_log_in) {}

void ChromePasswordProtectionService::UpdateSecurityState(
    SBThreatType threat_type,
    ReusedPasswordAccountType password_type,
    content::WebContents* web_contents) {}

void ChromePasswordProtectionService::FillReferrerChain(
    const GURL& event_url,
    SessionID event_tab_id,
    LoginReputationClientRequest::Frame* frame) {}

std::string ChromePasswordProtectionService::GetSyncPasswordHashFromPrefs() {}

PrefService* ChromePasswordProtectionService::GetPrefs() {}

bool ChromePasswordProtectionService::IsSafeBrowsingEnabled() {}

bool ChromePasswordProtectionService::IsExtendedReporting() {}

bool ChromePasswordProtectionService::IsIncognito() {}

bool ChromePasswordProtectionService::IsInPasswordAlertMode(
    ReusedPasswordAccountType password_type) {}

bool ChromePasswordProtectionService::IsPingingEnabled(
    LoginReputationClientRequest::TriggerType trigger_type,
    ReusedPasswordAccountType password_type) {}

RequestOutcome ChromePasswordProtectionService::GetPingNotSentReason(
    LoginReputationClientRequest::TriggerType trigger_type,
    const GURL& url,
    ReusedPasswordAccountType password_type) {}

void ChromePasswordProtectionService::FillUserPopulation(
    const GURL& main_frame_url,
    LoginReputationClientRequest* request_proto) {}

bool ChromePasswordProtectionService::IsPrimaryAccountSyncingHistory() const {}

bool ChromePasswordProtectionService::IsPrimaryAccountSignedIn() const {}

bool ChromePasswordProtectionService::IsAccountGmail(
    const std::string& username) const {}

AccountInfo ChromePasswordProtectionService::GetAccountInfoForUsername(
    const std::string& username) const {}

bool ChromePasswordProtectionService::IsInExcludedCountry() {}

PasswordReuseEvent::SyncAccountType
ChromePasswordProtectionService::GetSyncAccountType() const {}

void ChromePasswordProtectionService::
    RemoveUnhandledSyncPasswordReuseOnURLsDeleted(
        bool all_history,
        const history::URLRows& deleted_rows) {}

bool ChromePasswordProtectionService::UserClickedThroughSBInterstitial(
    PasswordProtectionRequest* request) {}

AccountInfo ChromePasswordProtectionService::GetAccountInfo() const {}

ChromeUserPopulation::UserPopulation
ChromePasswordProtectionService::GetUserPopulationPref() const {}

ChromePasswordProtectionService::ChromePasswordProtectionService(
    Profile* profile,
    scoped_refptr<SafeBrowsingUIManager> ui_manager,
    StringProvider sync_password_hash_provider,
    VerdictCacheManager* cache_manager,
    ChangePhishedCredentialsCallback add_phished_credentials,
    ChangePhishedCredentialsCallback remove_phished_credentials)
    :{}

#if BUILDFLAG(IS_ANDROID)
ChromePasswordProtectionService::ChromePasswordProtectionService(
    Profile* profile,
    scoped_refptr<SafeBrowsingUIManager> ui_manager,
    StringProvider sync_password_hash_provider,
    VerdictCacheManager* cache_manager,
    ChangePhishedCredentialsCallback add_phished_credentials,
    ChangePhishedCredentialsCallback remove_phished_credentials,
    std::unique_ptr<PasswordCheckupLauncherHelper> checkup_launcher)
    : PasswordProtectionService(
          nullptr,
          nullptr,
          nullptr,
          nullptr,
          nullptr,
          false,
          nullptr,
          /*try_token_fetch=*/false,
          SafeBrowsingMetricsCollectorFactory::GetForProfile(profile)),
      ui_manager_(ui_manager),
      trigger_manager_(nullptr),
      profile_(profile),
      cache_manager_(cache_manager),
      add_phished_credentials_(std::move(add_phished_credentials)),
      remove_phished_credentials_(std::move(remove_phished_credentials)),
      sync_password_hash_provider_for_testing_(sync_password_hash_provider),
      checkup_launcher_(std::move(checkup_launcher)) {
  Init();
}
#endif

std::unique_ptr<PasswordProtectionCommitDeferringCondition>
MaybeCreateCommitDeferringCondition(
    content::NavigationHandle& navigation_handle) {}

PasswordProtectionTrigger
ChromePasswordProtectionService::GetPasswordProtectionWarningTriggerPref(
    ReusedPasswordAccountType password_type) const {}

bool ChromePasswordProtectionService::IsURLAllowlistedForPasswordEntry(
    const GURL& url) const {}

void ChromePasswordProtectionService::PersistPhishedSavedPasswordCredential(
    const std::vector<password_manager::MatchingReusedCredential>&
        matching_reused_credentials) {}

void ChromePasswordProtectionService::RemovePhishedSavedPasswordCredential(
    const std::vector<password_manager::MatchingReusedCredential>&
        matching_reused_credentials) {}

#if BUILDFLAG(IS_ANDROID)
LoginReputationClientRequest::ReferringAppInfo
ChromePasswordProtectionService::GetReferringAppInfo(
    content::WebContents* web_contents) {
  ReferringAppInfo info_struct =
      safe_browsing::GetReferringAppInfo(web_contents);
  LoginReputationClientRequest::ReferringAppInfo info_proto;
  info_proto.set_referring_app_source(info_struct.referring_app_source);
  info_proto.set_referring_app_name(info_struct.referring_app_name);
  return info_proto;
}
#endif

password_manager::PasswordReuseManager*
ChromePasswordProtectionService::GetPasswordReuseManager() const {}

password_manager::PasswordStoreInterface*
ChromePasswordProtectionService::GetProfilePasswordStore() const {}

password_manager::PasswordStoreInterface*
ChromePasswordProtectionService::GetAccountPasswordStore() const {}

void ChromePasswordProtectionService::SanitizeReferrerChain(
    ReferrerChain* referrer_chain) {}

bool ChromePasswordProtectionService::CanSendSamplePing() {}

// Stores |verdict| in |settings| based on its |trigger_type|, |url|,
// reused |password_type|, |verdict| and |receive_time|.
void ChromePasswordProtectionService::CacheVerdict(
    const GURL& url,
    LoginReputationClientRequest::TriggerType trigger_type,
    ReusedPasswordAccountType password_type,
    const LoginReputationClientResponse& verdict,
    const base::Time& receive_time) {}

// Looks up |settings| to find the cached verdict response. If verdict is not
// available or is expired, return VERDICT_TYPE_UNSPECIFIED. Can be called on
// any thread.
LoginReputationClientResponse::VerdictType
ChromePasswordProtectionService::GetCachedVerdict(
    const GURL& url,
    LoginReputationClientRequest::TriggerType trigger_type,
    ReusedPasswordAccountType password_type,
    LoginReputationClientResponse* out_response) {}

int ChromePasswordProtectionService::GetStoredVerdictCount(
    LoginReputationClientRequest::TriggerType trigger_type) {}

#if BUILDFLAG(FULL_SAFE_BROWSING)
gfx::Size ChromePasswordProtectionService::GetCurrentContentAreaSize() const {}
#endif  // FULL_SAFE_BROWSING

password_manager::PasswordStoreInterface*
ChromePasswordProtectionService::GetStoreForReusedCredential(
    const password_manager::MatchingReusedCredential& reused_credential) {}

}  // namespace safe_browsing