| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/password_manager/core/browser/password_sync_util.h" |
| |
| #include "base/strings/utf_string_conversions.h" |
| #include "build/build_config.h" |
| #include "components/autofill/core/common/password_form.h" |
| #include "components/sync/base/model_type.h" |
| #include "components/sync/driver/sync_user_settings.h" |
| #include "google_apis/gaia/gaia_auth_util.h" |
| #include "google_apis/gaia/gaia_urls.h" |
| #include "services/identity/public/cpp/identity_manager.h" |
| #include "url/origin.h" |
| |
| #if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED) |
| #include "components/safe_browsing/common/safe_browsing_prefs.h" |
| #endif // SYNC_PASSWORD_REUSE_DETECTION_ENABLED |
| |
| using autofill::PasswordForm; |
| using url::Origin; |
| |
| namespace { |
| |
| constexpr char kGoogleChangePasswordSignonRealm[] = |
| "https://myaccount.google.com/"; |
| |
| } // namespace |
| |
| namespace password_manager { |
| namespace sync_util { |
| |
| std::string GetSyncUsernameIfSyncingPasswords( |
| const syncer::SyncService* sync_service, |
| const identity::IdentityManager* identity_manager) { |
| if (!identity_manager) |
| return std::string(); |
| |
| // Return early if the user has explicitly disabled password sync. Note that |
| // this does not cover the case when sync as a whole is turned off. |
| if (sync_service && |
| !sync_service->GetUserSettings()->GetChosenDataTypes().Has( |
| syncer::PASSWORDS)) { |
| return std::string(); |
| } |
| |
| return identity_manager->GetPrimaryAccountInfo().email; |
| } |
| |
| bool IsSyncAccountCredential( |
| const autofill::PasswordForm& form, |
| const syncer::SyncService* sync_service, |
| const identity::IdentityManager* identity_manager) { |
| if (!IsGaiaCredentialPage(form.signon_realm)) |
| return false; |
| |
| // The empty username can mean that Chrome did not detect it correctly. For |
| // reasons described in http://crbug.com/636292#c1, the username is suspected |
| // to be the sync username unless proven otherwise. |
| if (form.username_value.empty()) |
| return true; |
| |
| return gaia::AreEmailsSame( |
| base::UTF16ToUTF8(form.username_value), |
| GetSyncUsernameIfSyncingPasswords(sync_service, identity_manager)); |
| } |
| |
| bool ShouldSavePasswordHash(const autofill::PasswordForm& form, |
| const identity::IdentityManager* identity_manager, |
| PrefService* prefs) { |
| #if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED) |
| bool is_protected_credential_url = |
| gaia::IsGaiaSignonRealm(GURL(form.signon_realm)) || |
| form.signon_realm == kGoogleChangePasswordSignonRealm || |
| safe_browsing::MatchesPasswordProtectionLoginURL(form.origin, *prefs) || |
| safe_browsing::MatchesPasswordProtectionChangePasswordURL(form.origin, |
| *prefs); |
| |
| if (!is_protected_credential_url) |
| return false; |
| |
| std::string sync_email = identity_manager->GetPrimaryAccountInfo().email; |
| std::string username = base::UTF16ToUTF8(form.username_value); |
| |
| if (sync_email.empty() || username.empty()) |
| return false; |
| |
| // Add @domain.name to the username if it is absent. |
| std::string email = |
| username + (username.find('@') == std::string::npos |
| ? "@" + gaia::ExtractDomainName(sync_email) |
| : std::string()); |
| |
| return email == sync_email; |
| #else |
| return false; |
| #endif // SYNC_PASSWORD_REUSE_DETECTION_ENABLED |
| } |
| |
| bool IsSyncAccountEmail(const std::string& username, |
| const identity::IdentityManager* identity_manager) { |
| // |identity_manager| can be null if user is not signed in. |
| if (!identity_manager) |
| return false; |
| |
| std::string sync_email = identity_manager->GetPrimaryAccountInfo().email; |
| |
| if (sync_email.empty() || username.empty()) |
| return false; |
| |
| if (username.find('@') == std::string::npos) |
| return false; |
| |
| return gaia::AreEmailsSame(username, sync_email); |
| } |
| |
| bool IsGaiaCredentialPage(const std::string& signon_realm) { |
| return gaia::IsGaiaSignonRealm(GURL(signon_realm)) || |
| signon_realm == kGoogleChangePasswordSignonRealm; |
| } |
| |
| bool ShouldSaveEnterprisePasswordHash(const autofill::PasswordForm& form, |
| const PrefService& prefs) { |
| #if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED) |
| return safe_browsing::MatchesPasswordProtectionLoginURL(form.origin, prefs) || |
| safe_browsing::MatchesPasswordProtectionChangePasswordURL(form.origin, |
| prefs); |
| #else |
| return false; |
| #endif // SYNC_PASSWORD_REUSE_DETECTION_ENABLED |
| } |
| |
| } // namespace sync_util |
| } // namespace password_manager |