summaryrefslogtreecommitdiff
path: root/chromium/components/password_manager/sync/browser/sync_credentials_filter.cc
blob: 04eb1cd3acc6dba5f7e3d3c8f09c625181b39164 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// 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/sync/browser/sync_credentials_filter.h"

#include <algorithm>

#include "base/macros.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
#include "components/password_manager/core/browser/password_form_manager.h"
#include "components/password_manager/core/browser/password_manager_util.h"
#include "components/password_manager/core/common/password_manager_features.h"
#include "components/password_manager/sync/browser/password_sync_util.h"
#include "google_apis/gaia/gaia_urls.h"
#include "net/base/url_util.h"

using autofill::PasswordForm;

namespace password_manager {

namespace {

// Returns true if the last loaded page was for transactional re-auth on a
// Google property.
bool LastLoadWasTransactionalReauthPage(const GURL& last_load_url) {
  if (last_load_url.GetOrigin() !=
      GaiaUrls::GetInstance()->gaia_url().GetOrigin())
    return false;

  // TODO(vabr): GAIA stops using the "rart" URL param, and instead includes a
  // hidden form field with name "rart". http://crbug.com/543085
  // "rart" is the transactional reauth paramter.
  std::string ignored_value;
  return net::GetValueForKeyInQuery(last_load_url, "rart", &ignored_value);
}

}  // namespace

SyncCredentialsFilter::SyncCredentialsFilter(
    const PasswordManagerClient* client,
    SyncServiceFactoryFunction sync_service_factory_function,
    SigninManagerFactoryFunction signin_manager_factory_function)
    : client_(client),
      sync_service_factory_function_(sync_service_factory_function),
      signin_manager_factory_function_(signin_manager_factory_function) {}

SyncCredentialsFilter::~SyncCredentialsFilter() {}

std::vector<std::unique_ptr<PasswordForm>> SyncCredentialsFilter::FilterResults(
    std::vector<std::unique_ptr<PasswordForm>> results) const {
  const AutofillForSyncCredentialsState autofill_sync_state =
      GetAutofillForSyncCredentialsState();

  if (autofill_sync_state != DISALLOW_SYNC_CREDENTIALS &&
      (autofill_sync_state != DISALLOW_SYNC_CREDENTIALS_FOR_REAUTH ||
       !LastLoadWasTransactionalReauthPage(
           client_->GetLastCommittedEntryURL()))) {
    return results;
  }

  auto begin_of_removed =
      std::partition(results.begin(), results.end(),
                     [this](const std::unique_ptr<PasswordForm>& form) {
                       return ShouldSave(*form);
                     });

  UMA_HISTOGRAM_BOOLEAN("PasswordManager.SyncCredentialFiltered",
                        begin_of_removed != results.end());

  results.erase(begin_of_removed, results.end());

  return results;
}

bool SyncCredentialsFilter::ShouldSave(
    const autofill::PasswordForm& form) const {
  return !form.is_gaia_with_skip_save_password_form &&
         !sync_util::IsSyncAccountCredential(
             form, sync_service_factory_function_.Run(),
             signin_manager_factory_function_.Run());
}

bool SyncCredentialsFilter::ShouldSavePasswordHash(
    const autofill::PasswordForm& form) const {
  return sync_util::ShouldSavePasswordHash(
      form, signin_manager_factory_function_.Run(), client_->GetPrefs());
}

void SyncCredentialsFilter::ReportFormLoginSuccess(
    const PasswordFormManager& form_manager) const {
  if (!form_manager.IsNewLogin() &&
      sync_util::IsSyncAccountCredential(
          form_manager.GetPendingCredentials(),
          sync_service_factory_function_.Run(),
          signin_manager_factory_function_.Run())) {
    base::RecordAction(base::UserMetricsAction(
        "PasswordManager_SyncCredentialFilledAndLoginSuccessfull"));
  }
}

// static
SyncCredentialsFilter::AutofillForSyncCredentialsState
SyncCredentialsFilter::GetAutofillForSyncCredentialsState() {
  bool protect_sync_credential_enabled =
      base::FeatureList::IsEnabled(features::kProtectSyncCredential);
  bool protect_sync_credential_on_reauth_enabled =
      base::FeatureList::IsEnabled(features::kProtectSyncCredentialOnReauth);

  if (protect_sync_credential_enabled) {
    if (protect_sync_credential_on_reauth_enabled) {
      // Both the features are enabled, do not ever fill the sync credential.
      return DISALLOW_SYNC_CREDENTIALS;
    }

    // Only 'ProtectSyncCredentialOnReauth' feature is kept disabled. This
    // is "illegal", emit a warning and do not ever fill the sync credential.
    LOG(WARNING) << "This is illegal! Feature "
                    "'ProtectSyncCredentialOnReauth' cannot be kept "
                    "disabled if 'protect-sync-credential' feature is enabled. "
                    "We shall not ever fill the sync credential is such cases.";
    return DISALLOW_SYNC_CREDENTIALS;
  }

  if (protect_sync_credential_on_reauth_enabled) {
    // Only 'ProtectSyncCredentialOnReauth' feature is kept enabled, fill
    // the sync credential everywhere but on reauth.
    return DISALLOW_SYNC_CREDENTIALS_FOR_REAUTH;
  }

  // Both the features are disabled, fill the sync credential everywhere.
  return ALLOW_SYNC_CREDENTIALS;
}

}  // namespace password_manager