Index: components/password_manager/core/browser/login_database.cc |
diff --git a/components/password_manager/core/browser/login_database.cc b/components/password_manager/core/browser/login_database.cc |
index fea970287e5bab58ca16a73bec6511758e8e0c72..3c3019464b93bd877a459144f66cecb9f438f266 100644 |
--- a/components/password_manager/core/browser/login_database.cc |
+++ b/components/password_manager/core/browser/login_database.cc |
@@ -7,6 +7,7 @@ |
#include <algorithm> |
#include <limits> |
+#include "base/bind.h" |
#include "base/files/file_path.h" |
#include "base/logging.h" |
#include "base/metrics/histogram.h" |
@@ -49,6 +50,43 @@ enum LoginTableColumns { |
COLUMN_USE_ADDITIONAL_AUTH |
}; |
+void BindAddStatement(const PasswordForm& form, |
+ const std::string& encrypted_password, |
+ sql::Statement* s) { |
+ s->BindString(COLUMN_ORIGIN_URL, form.origin.spec()); |
+ s->BindString(COLUMN_ACTION_URL, form.action.spec()); |
+ s->BindString16(COLUMN_USERNAME_ELEMENT, form.username_element); |
+ s->BindString16(COLUMN_USERNAME_VALUE, form.username_value); |
+ s->BindString16(COLUMN_PASSWORD_ELEMENT, form.password_element); |
+ s->BindBlob(COLUMN_PASSWORD_VALUE, encrypted_password.data(), |
+ static_cast<int>(encrypted_password.length())); |
+ s->BindString16(COLUMN_SUBMIT_ELEMENT, form.submit_element); |
+ s->BindString(COLUMN_SIGNON_REALM, form.signon_realm); |
+ s->BindInt(COLUMN_SSL_VALID, form.ssl_valid); |
+ s->BindInt(COLUMN_PREFERRED, form.preferred); |
+ s->BindInt64(COLUMN_DATE_CREATED, form.date_created.ToTimeT()); |
+ s->BindInt(COLUMN_BLACKLISTED_BY_USER, form.blacklisted_by_user); |
+ s->BindInt(COLUMN_SCHEME, form.scheme); |
+ s->BindInt(COLUMN_PASSWORD_TYPE, form.type); |
+ Pickle usernames_pickle = |
+ LoginDatabase::SerializeVector(form.other_possible_usernames); |
+ s->BindBlob(COLUMN_POSSIBLE_USERNAMES, |
+ usernames_pickle.data(), |
+ usernames_pickle.size()); |
+ s->BindInt(COLUMN_TIMES_USED, form.times_used); |
+ Pickle form_data_pickle; |
+ autofill::SerializeFormData(form.form_data, &form_data_pickle); |
+ s->BindBlob(COLUMN_FORM_DATA, |
+ form_data_pickle.data(), |
+ form_data_pickle.size()); |
+ s->BindInt(COLUMN_USE_ADDITIONAL_AUTH, form.use_additional_authentication); |
+} |
+ |
+void AddCallback(int err, sql::Statement* /*stmt*/) { |
+ if (err == 19 /*SQLITE_CONSTRAINT*/) |
+ DLOG(WARNING) << "LoginDatabase::AddLogin updated an existing form"; |
+} |
+ |
} // namespace |
LoginDatabase::LoginDatabase() { |
@@ -238,14 +276,32 @@ void LoginDatabase::ReportMetrics() { |
} |
} |
-bool LoginDatabase::AddLogin(const PasswordForm& form) { |
+PasswordStoreChangeList LoginDatabase::AddLogin(const PasswordForm& form) { |
+ PasswordStoreChangeList list; |
std::string encrypted_password; |
if (EncryptedString(form.password_value, &encrypted_password) != |
ENCRYPTION_RESULT_SUCCESS) |
- return false; |
+ return list; |
// You *must* change LoginTableColumns if this query changes. |
sql::Statement s(db_.GetCachedStatement(SQL_FROM_HERE, |
+ "INSERT INTO logins " |
+ "(origin_url, action_url, username_element, username_value, " |
+ " password_element, password_value, submit_element, " |
+ " signon_realm, ssl_valid, preferred, date_created, blacklisted_by_user, " |
+ " scheme, password_type, possible_usernames, times_used, form_data, " |
+ " use_additional_auth) VALUES " |
+ "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")); |
+ BindAddStatement(form, encrypted_password, &s); |
+ db_.set_error_callback(base::Bind(&AddCallback)); |
+ const bool success = s.Run(); |
+ db_.reset_error_callback(); |
+ if (success) { |
+ list.push_back(PasswordStoreChange(PasswordStoreChange::ADD, form)); |
+ return list; |
+ } |
+ // Repeat the same statement but with REPLACE semantic. |
+ s.Assign(db_.GetCachedStatement(SQL_FROM_HERE, |
"INSERT OR REPLACE INTO logins " |
"(origin_url, action_url, username_element, username_value, " |
" password_element, password_value, submit_element, " |
@@ -253,34 +309,12 @@ bool LoginDatabase::AddLogin(const PasswordForm& form) { |
" scheme, password_type, possible_usernames, times_used, form_data, " |
" use_additional_auth) VALUES " |
"(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")); |
- s.BindString(COLUMN_ORIGIN_URL, form.origin.spec()); |
- s.BindString(COLUMN_ACTION_URL, form.action.spec()); |
- s.BindString16(COLUMN_USERNAME_ELEMENT, form.username_element); |
- s.BindString16(COLUMN_USERNAME_VALUE, form.username_value); |
- s.BindString16(COLUMN_PASSWORD_ELEMENT, form.password_element); |
- s.BindBlob(COLUMN_PASSWORD_VALUE, encrypted_password.data(), |
- static_cast<int>(encrypted_password.length())); |
- s.BindString16(COLUMN_SUBMIT_ELEMENT, form.submit_element); |
- s.BindString(COLUMN_SIGNON_REALM, form.signon_realm); |
- s.BindInt(COLUMN_SSL_VALID, form.ssl_valid); |
- s.BindInt(COLUMN_PREFERRED, form.preferred); |
- s.BindInt64(COLUMN_DATE_CREATED, form.date_created.ToTimeT()); |
- s.BindInt(COLUMN_BLACKLISTED_BY_USER, form.blacklisted_by_user); |
- s.BindInt(COLUMN_SCHEME, form.scheme); |
- s.BindInt(COLUMN_PASSWORD_TYPE, form.type); |
- Pickle usernames_pickle = SerializeVector(form.other_possible_usernames); |
- s.BindBlob(COLUMN_POSSIBLE_USERNAMES, |
- usernames_pickle.data(), |
- usernames_pickle.size()); |
- s.BindInt(COLUMN_TIMES_USED, form.times_used); |
- Pickle form_data_pickle; |
- autofill::SerializeFormData(form.form_data, &form_data_pickle); |
- s.BindBlob(COLUMN_FORM_DATA, |
- form_data_pickle.data(), |
- form_data_pickle.size()); |
- s.BindInt(COLUMN_USE_ADDITIONAL_AUTH, form.use_additional_authentication); |
- |
- return s.Run(); |
+ BindAddStatement(form, encrypted_password, &s); |
+ if (s.Run()) { |
+ list.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE, form)); |
+ list.push_back(PasswordStoreChange(PasswordStoreChange::ADD, form)); |
+ } |
+ return list; |
} |
bool LoginDatabase::UpdateLogin(const PasswordForm& form, int* items_changed) { |
@@ -585,8 +619,8 @@ bool LoginDatabase::DeleteAndRecreateDatabaseFile() { |
return Init(db_path_); |
} |
-Pickle LoginDatabase::SerializeVector( |
- const std::vector<base::string16>& vec) const { |
+// static |
+Pickle LoginDatabase::SerializeVector(const std::vector<base::string16>& vec) { |
Pickle p; |
for (size_t i = 0; i < vec.size(); ++i) { |
p.WriteString16(vec[i]); |
@@ -594,8 +628,8 @@ Pickle LoginDatabase::SerializeVector( |
return p; |
} |
-std::vector<base::string16> LoginDatabase::DeserializeVector( |
- const Pickle& p) const { |
+// static |
+std::vector<base::string16> LoginDatabase::DeserializeVector(const Pickle& p) { |
std::vector<base::string16> ret; |
base::string16 str; |