Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(258)

Side by Side Diff: components/password_manager/core/browser/login_database.cc

Issue 283563002: Password Login Database: report correct changes from AddLogin(). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: unused variable Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/password_manager/core/browser/login_database.h" 5 #include "components/password_manager/core/browser/login_database.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 9
10 #include "base/bind.h"
10 #include "base/files/file_path.h" 11 #include "base/files/file_path.h"
11 #include "base/logging.h" 12 #include "base/logging.h"
12 #include "base/metrics/histogram.h" 13 #include "base/metrics/histogram.h"
13 #include "base/pickle.h" 14 #include "base/pickle.h"
14 #include "base/strings/string_util.h" 15 #include "base/strings/string_util.h"
15 #include "base/time/time.h" 16 #include "base/time/time.h"
16 #include "components/autofill/core/common/password_form.h" 17 #include "components/autofill/core/common/password_form.h"
17 #include "sql/connection.h" 18 #include "sql/connection.h"
18 #include "sql/statement.h" 19 #include "sql/statement.h"
19 #include "sql/transaction.h" 20 #include "sql/transaction.h"
20 21
21 using autofill::PasswordForm; 22 using autofill::PasswordForm;
22 23
23 namespace password_manager { 24 namespace password_manager {
24 25
25 static const int kCurrentVersionNumber = 5; 26 static const int kCurrentVersionNumber = 5;
26 static const int kCompatibleVersionNumber = 1; 27 static const int kCompatibleVersionNumber = 1;
27 28
29 Pickle SerializeVector(const std::vector<base::string16>& vec) {
30 Pickle p;
31 for (size_t i = 0; i < vec.size(); ++i) {
32 p.WriteString16(vec[i]);
33 }
34 return p;
35 }
36
37 std::vector<base::string16> DeserializeVector(const Pickle& p) {
38 std::vector<base::string16> ret;
39 base::string16 str;
40
41 PickleIterator iterator(p);
42 while (iterator.ReadString16(&str)) {
43 ret.push_back(str);
44 }
45 return ret;
46 }
47
28 namespace { 48 namespace {
29 49
30 // Convenience enum for interacting with SQL queries that use all the columns. 50 // Convenience enum for interacting with SQL queries that use all the columns.
31 enum LoginTableColumns { 51 enum LoginTableColumns {
32 COLUMN_ORIGIN_URL = 0, 52 COLUMN_ORIGIN_URL = 0,
33 COLUMN_ACTION_URL, 53 COLUMN_ACTION_URL,
34 COLUMN_USERNAME_ELEMENT, 54 COLUMN_USERNAME_ELEMENT,
35 COLUMN_USERNAME_VALUE, 55 COLUMN_USERNAME_VALUE,
36 COLUMN_PASSWORD_ELEMENT, 56 COLUMN_PASSWORD_ELEMENT,
37 COLUMN_PASSWORD_VALUE, 57 COLUMN_PASSWORD_VALUE,
38 COLUMN_SUBMIT_ELEMENT, 58 COLUMN_SUBMIT_ELEMENT,
39 COLUMN_SIGNON_REALM, 59 COLUMN_SIGNON_REALM,
40 COLUMN_SSL_VALID, 60 COLUMN_SSL_VALID,
41 COLUMN_PREFERRED, 61 COLUMN_PREFERRED,
42 COLUMN_DATE_CREATED, 62 COLUMN_DATE_CREATED,
43 COLUMN_BLACKLISTED_BY_USER, 63 COLUMN_BLACKLISTED_BY_USER,
44 COLUMN_SCHEME, 64 COLUMN_SCHEME,
45 COLUMN_PASSWORD_TYPE, 65 COLUMN_PASSWORD_TYPE,
46 COLUMN_POSSIBLE_USERNAMES, 66 COLUMN_POSSIBLE_USERNAMES,
47 COLUMN_TIMES_USED, 67 COLUMN_TIMES_USED,
48 COLUMN_FORM_DATA, 68 COLUMN_FORM_DATA,
49 COLUMN_USE_ADDITIONAL_AUTH 69 COLUMN_USE_ADDITIONAL_AUTH
50 }; 70 };
51 71
72 void BindAddStatement(const PasswordForm& form,
73 const std::string& encrypted_password,
74 sql::Statement* s) {
75 s->BindString(COLUMN_ORIGIN_URL, form.origin.spec());
76 s->BindString(COLUMN_ACTION_URL, form.action.spec());
77 s->BindString16(COLUMN_USERNAME_ELEMENT, form.username_element);
78 s->BindString16(COLUMN_USERNAME_VALUE, form.username_value);
79 s->BindString16(COLUMN_PASSWORD_ELEMENT, form.password_element);
80 s->BindBlob(COLUMN_PASSWORD_VALUE, encrypted_password.data(),
81 static_cast<int>(encrypted_password.length()));
82 s->BindString16(COLUMN_SUBMIT_ELEMENT, form.submit_element);
83 s->BindString(COLUMN_SIGNON_REALM, form.signon_realm);
84 s->BindInt(COLUMN_SSL_VALID, form.ssl_valid);
85 s->BindInt(COLUMN_PREFERRED, form.preferred);
86 s->BindInt64(COLUMN_DATE_CREATED, form.date_created.ToTimeT());
87 s->BindInt(COLUMN_BLACKLISTED_BY_USER, form.blacklisted_by_user);
88 s->BindInt(COLUMN_SCHEME, form.scheme);
89 s->BindInt(COLUMN_PASSWORD_TYPE, form.type);
90 Pickle usernames_pickle = SerializeVector(form.other_possible_usernames);
91 s->BindBlob(COLUMN_POSSIBLE_USERNAMES,
92 usernames_pickle.data(),
93 usernames_pickle.size());
94 s->BindInt(COLUMN_TIMES_USED, form.times_used);
95 Pickle form_data_pickle;
96 autofill::SerializeFormData(form.form_data, &form_data_pickle);
97 s->BindBlob(COLUMN_FORM_DATA,
98 form_data_pickle.data(),
99 form_data_pickle.size());
100 s->BindInt(COLUMN_USE_ADDITIONAL_AUTH, form.use_additional_authentication);
101 }
102
103 void AddCallback(int err, sql::Statement* /*stmt*/) {
104 if (err == 19 /*SQLITE_CONSTRAINT*/)
105 DLOG(WARNING) << "LoginDatabase::AddLogin updated an existing form";
106 }
107
52 } // namespace 108 } // namespace
53 109
54 LoginDatabase::LoginDatabase() { 110 LoginDatabase::LoginDatabase() {
55 } 111 }
56 112
57 LoginDatabase::~LoginDatabase() { 113 LoginDatabase::~LoginDatabase() {
58 } 114 }
59 115
60 bool LoginDatabase::Init(const base::FilePath& db_path) { 116 bool LoginDatabase::Init(const base::FilePath& db_path) {
61 // Set pragmas for a small, private database (based on WebDatabase). 117 // Set pragmas for a small, private database (based on WebDatabase).
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 "PasswordManager.TimesGeneratedPasswordUsed", 287 "PasswordManager.TimesGeneratedPasswordUsed",
232 usage_statement.ColumnInt(1), 0, 100, 10); 288 usage_statement.ColumnInt(1), 0, 100, 10);
233 } else { 289 } else {
234 UMA_HISTOGRAM_CUSTOM_COUNTS( 290 UMA_HISTOGRAM_CUSTOM_COUNTS(
235 "PasswordManager.TimesPasswordUsed", 291 "PasswordManager.TimesPasswordUsed",
236 usage_statement.ColumnInt(1), 0, 100, 10); 292 usage_statement.ColumnInt(1), 0, 100, 10);
237 } 293 }
238 } 294 }
239 } 295 }
240 296
241 bool LoginDatabase::AddLogin(const PasswordForm& form) { 297 PasswordStoreChangeList LoginDatabase::AddLogin(const PasswordForm& form) {
298 PasswordStoreChangeList list;
242 std::string encrypted_password; 299 std::string encrypted_password;
243 if (EncryptedString(form.password_value, &encrypted_password) != 300 if (EncryptedString(form.password_value, &encrypted_password) !=
244 ENCRYPTION_RESULT_SUCCESS) 301 ENCRYPTION_RESULT_SUCCESS)
245 return false; 302 return list;
246 303
247 // You *must* change LoginTableColumns if this query changes. 304 // You *must* change LoginTableColumns if this query changes.
248 sql::Statement s(db_.GetCachedStatement(SQL_FROM_HERE, 305 sql::Statement s(db_.GetCachedStatement(SQL_FROM_HERE,
306 "INSERT INTO logins "
307 "(origin_url, action_url, username_element, username_value, "
308 " password_element, password_value, submit_element, "
309 " signon_realm, ssl_valid, preferred, date_created, blacklisted_by_user, "
310 " scheme, password_type, possible_usernames, times_used, form_data, "
311 " use_additional_auth) VALUES "
312 "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"));
313 BindAddStatement(form, encrypted_password, &s);
314 db_.set_error_callback(base::Bind(&AddCallback));
315 const bool success = s.Run();
316 db_.reset_error_callback();
317 if (success) {
318 list.push_back(PasswordStoreChange(PasswordStoreChange::ADD, form));
319 return list;
320 }
321 // Repeat the same statement but with REPLACE semantic.
322 s.Assign(db_.GetCachedStatement(SQL_FROM_HERE,
249 "INSERT OR REPLACE INTO logins " 323 "INSERT OR REPLACE INTO logins "
250 "(origin_url, action_url, username_element, username_value, " 324 "(origin_url, action_url, username_element, username_value, "
251 " password_element, password_value, submit_element, " 325 " password_element, password_value, submit_element, "
252 " signon_realm, ssl_valid, preferred, date_created, blacklisted_by_user, " 326 " signon_realm, ssl_valid, preferred, date_created, blacklisted_by_user, "
253 " scheme, password_type, possible_usernames, times_used, form_data, " 327 " scheme, password_type, possible_usernames, times_used, form_data, "
254 " use_additional_auth) VALUES " 328 " use_additional_auth) VALUES "
255 "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")); 329 "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"));
256 s.BindString(COLUMN_ORIGIN_URL, form.origin.spec()); 330 BindAddStatement(form, encrypted_password, &s);
257 s.BindString(COLUMN_ACTION_URL, form.action.spec()); 331 if (s.Run()) {
258 s.BindString16(COLUMN_USERNAME_ELEMENT, form.username_element); 332 list.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE, form));
259 s.BindString16(COLUMN_USERNAME_VALUE, form.username_value); 333 list.push_back(PasswordStoreChange(PasswordStoreChange::ADD, form));
260 s.BindString16(COLUMN_PASSWORD_ELEMENT, form.password_element); 334 }
261 s.BindBlob(COLUMN_PASSWORD_VALUE, encrypted_password.data(), 335 return list;
262 static_cast<int>(encrypted_password.length()));
263 s.BindString16(COLUMN_SUBMIT_ELEMENT, form.submit_element);
264 s.BindString(COLUMN_SIGNON_REALM, form.signon_realm);
265 s.BindInt(COLUMN_SSL_VALID, form.ssl_valid);
266 s.BindInt(COLUMN_PREFERRED, form.preferred);
267 s.BindInt64(COLUMN_DATE_CREATED, form.date_created.ToTimeT());
268 s.BindInt(COLUMN_BLACKLISTED_BY_USER, form.blacklisted_by_user);
269 s.BindInt(COLUMN_SCHEME, form.scheme);
270 s.BindInt(COLUMN_PASSWORD_TYPE, form.type);
271 Pickle usernames_pickle = SerializeVector(form.other_possible_usernames);
272 s.BindBlob(COLUMN_POSSIBLE_USERNAMES,
273 usernames_pickle.data(),
274 usernames_pickle.size());
275 s.BindInt(COLUMN_TIMES_USED, form.times_used);
276 Pickle form_data_pickle;
277 autofill::SerializeFormData(form.form_data, &form_data_pickle);
278 s.BindBlob(COLUMN_FORM_DATA,
279 form_data_pickle.data(),
280 form_data_pickle.size());
281 s.BindInt(COLUMN_USE_ADDITIONAL_AUTH, form.use_additional_authentication);
282
283 return s.Run();
284 } 336 }
285 337
286 bool LoginDatabase::UpdateLogin(const PasswordForm& form, int* items_changed) { 338 bool LoginDatabase::UpdateLogin(const PasswordForm& form, int* items_changed) {
287 std::string encrypted_password; 339 std::string encrypted_password;
288 if (EncryptedString(form.password_value, &encrypted_password) != 340 if (EncryptedString(form.password_value, &encrypted_password) !=
289 ENCRYPTION_RESULT_SUCCESS) 341 ENCRYPTION_RESULT_SUCCESS)
290 return false; 342 return false;
291 343
292 // Replacement is necessary to deal with updating imported credentials. See 344 // Replacement is necessary to deal with updating imported credentials. See
293 // crbug.com/349138 for details. 345 // crbug.com/349138 for details.
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
578 } 630 }
579 631
580 bool LoginDatabase::DeleteAndRecreateDatabaseFile() { 632 bool LoginDatabase::DeleteAndRecreateDatabaseFile() {
581 DCHECK(db_.is_open()); 633 DCHECK(db_.is_open());
582 meta_table_.Reset(); 634 meta_table_.Reset();
583 db_.Close(); 635 db_.Close();
584 sql::Connection::Delete(db_path_); 636 sql::Connection::Delete(db_path_);
585 return Init(db_path_); 637 return Init(db_path_);
586 } 638 }
587 639
588 Pickle LoginDatabase::SerializeVector(
589 const std::vector<base::string16>& vec) const {
590 Pickle p;
591 for (size_t i = 0; i < vec.size(); ++i) {
592 p.WriteString16(vec[i]);
593 }
594 return p;
595 }
596
597 std::vector<base::string16> LoginDatabase::DeserializeVector(
598 const Pickle& p) const {
599 std::vector<base::string16> ret;
600 base::string16 str;
601
602 PickleIterator iterator(p);
603 while (iterator.ReadString16(&str)) {
604 ret.push_back(str);
605 }
606 return ret;
607 }
608
609 } // namespace password_manager 640 } // namespace password_manager
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698