Chromium Code Reviews| Index: chrome/browser/webdata/autofill_table.cc |
| diff --git a/chrome/browser/webdata/autofill_table.cc b/chrome/browser/webdata/autofill_table.cc |
| index bba0b838df6c3ad84e9f2455f43bf373ae87ceed..eb3fc0376be75513417d26b00590bd5240c003b7 100644 |
| --- a/chrome/browser/webdata/autofill_table.cc |
| +++ b/chrome/browser/webdata/autofill_table.cc |
| @@ -23,6 +23,7 @@ |
| #include "chrome/browser/autofill/personal_data_manager.h" |
| #include "chrome/browser/password_manager/encryptor.h" |
| #include "chrome/browser/webdata/autofill_change.h" |
| +#include "chrome/browser/webdata/autofill_entry.h" |
| #include "chrome/common/guid.h" |
| #include "sql/statement.h" |
| #include "ui/base/l10n/l10n_util.h" |
| @@ -418,15 +419,24 @@ bool AutofillTable::RemoveFormElementsAddedBetween( |
| return false; |
| for (AutofillElementList::iterator itr = elements.begin(); |
| - itr != elements.end(); itr++) { |
| + itr != elements.end(); ++itr) { |
| int how_many = 0; |
| if (!RemoveFormElementForTimeRange(itr->a, delete_begin, delete_end, |
| &how_many)) { |
| return false; |
| } |
| bool was_removed = false; |
| - if (!AddToCountOfFormElement(itr->a, -how_many, &was_removed)) |
| - return false; |
| + // We store at most 2 time stamps. If we remove both of them we should |
| + // delete the corresponding data. if we delete only one it could still be |
| + // the last timestamp for the data. |
| + if (how_many == 2 || (how_many == 1 && CountTimestampsData(itr->a) == 0)) { |
| + was_removed = true; |
| + if (!RemoveFormElementForID(itr->a)) |
| + return false; |
| + } else { |
| + if (!AddToCountOfFormElement(itr->a, -how_many, &was_removed)) |
|
Ilya Sherman
2012/03/21 21:20:53
As we discussed offline, I don't think we want to
GeorgeY
2012/03/21 22:10:56
Done.
|
| + return false; |
| + } |
| AutofillChange::Type change_type = |
| was_removed ? AutofillChange::REMOVE : AutofillChange::UPDATE; |
| changes->push_back(AutofillChange(change_type, |
| @@ -436,6 +446,77 @@ bool AutofillTable::RemoveFormElementsAddedBetween( |
| return true; |
| } |
| +bool AutofillTable::RemoveExpiredFormElements( |
| + std::vector<AutofillChange>* changes) { |
| + DCHECK(changes); |
| + |
| + base::Time delete_end = AutofillEntry::ExpirationTime(); |
| + // Query for the pair_id, name, and value of all form elements that |
| + // were last used before the |delete_end|. |
| + sql::Statement select_for_delete(db_->GetUniqueStatement( |
| + "SELECT DISTINCT pair_id, name, value " |
| + "FROM autofill WHERE pair_id NOT IN " |
| + "(SELECT DISTINCT pair_id " |
| + "FROM autofill_dates WHERE date_created >= ?)")); |
| + select_for_delete.BindInt64(0, delete_end.ToTimeT()); |
| + AutofillElementList entries_to_delete; |
| + while (select_for_delete.Step()) { |
| + entries_to_delete.push_back(MakeTuple(select_for_delete.ColumnInt64(0), |
| + select_for_delete.ColumnString16(1), |
| + select_for_delete.ColumnString16(2))); |
| + } |
| + |
| + if (!select_for_delete.Succeeded()) |
| + return false; |
| + |
| + sql::Statement delete_data_statement(db_->GetUniqueStatement( |
| + "DELETE FROM autofill WHERE pair_id NOT IN (" |
| + "SELECT pair_id FROM autofill_dates WHERE date_created >= ?)")); |
| + delete_data_statement.BindInt64(0, delete_end.ToTimeT()); |
| + if (!delete_data_statement.Run()) |
| + return false; |
| + |
| + sql::Statement delete_times_statement(db_->GetUniqueStatement( |
| + "DELETE FROM autofill_dates WHERE pair_id NOT IN (" |
| + "SELECT pair_id FROM autofill_dates WHERE date_created >= ?)")); |
| + delete_times_statement.BindInt64(0, delete_end.ToTimeT()); |
| + if (!delete_times_statement.Run()) |
| + return false; |
| + |
| + // Cull remaining entries' timestamps. |
| + std::vector<AutofillEntry> entries; |
| + if (!GetAllAutofillEntries(&entries)) |
| + return false; |
| + sql::Statement cull_date_entry(db_->GetUniqueStatement( |
| + "DELETE FROM autofill_dates " |
| + "WHERE pair_id == (SELECT pair_id FROM autofill " |
| + "WHERE name = ? and value = ?)" |
| + "AND date_created != ? AND date_created != ?")); |
| + for (size_t i = 0; i < entries.size(); ++i) { |
| + cull_date_entry.BindString16(0, entries[i].key().name()); |
| + cull_date_entry.BindString16(1, entries[i].key().value()); |
| + cull_date_entry.BindInt64(2, |
| + entries[i].timestamps().empty() ? 0 : |
| + entries[i].timestamps().front().ToTimeT()); |
| + cull_date_entry.BindInt64(3, |
| + entries[i].timestamps().empty() ? 0 : |
| + entries[i].timestamps().back().ToTimeT()); |
| + if (!cull_date_entry.Run()) |
| + return false; |
| + cull_date_entry.Reset(); |
| + } |
| + |
| + changes->clear(); |
| + changes->reserve(entries_to_delete.size()); |
| + |
| + for (AutofillElementList::iterator it = entries_to_delete.begin(); |
| + it != entries_to_delete.end(); ++it) { |
| + changes->push_back(AutofillChange( |
| + AutofillChange::REMOVE, AutofillKey(it->b, it->c))); |
| + } |
| + return true; |
| +} |
| + |
| bool AutofillTable::RemoveFormElementForTimeRange(int64 pair_id, |
| const Time& delete_begin, |
| const Time& delete_end, |
| @@ -455,6 +536,18 @@ bool AutofillTable::RemoveFormElementForTimeRange(int64 pair_id, |
| return result; |
| } |
| +int AutofillTable::CountTimestampsData(int64 pair_id) { |
| + sql::Statement s(db_->GetUniqueStatement( |
| + "SELECT COUNT(*) FROM autofill_dates WHERE pair_id = ?")); |
| + s.BindInt64(0, pair_id); |
| + if (!s.Step()) { |
| + NOTREACHED(); |
| + return 0; |
| + } else { |
| + return s.ColumnInt(0); |
| + } |
| +} |
| + |
| bool AutofillTable::AddToCountOfFormElement(int64 pair_id, |
| int delta, |
| bool* was_removed) { |
| @@ -552,6 +645,19 @@ bool AutofillTable::InsertPairIDAndDate(int64 pair_id, |
| return s.Run(); |
| } |
| +bool AutofillTable::DeleteLastAccess(int64 pair_id) { |
| + // Inner SELECT selects the newest |date_created| for a given |pair_id|. |
| + // DELETE deletes only that entry. |
| + sql::Statement s(db_->GetUniqueStatement( |
| + "DELETE FROM autofill_dates WHERE pair_id = ? and date_created IN " |
| + "(SELECT date_created FROM autofill_dates WHERE pair_id = ? " |
| + "ORDER BY date_created DESC LIMIT 1)")); |
| + s.BindInt64(0, pair_id); |
| + s.BindInt64(1, pair_id); |
| + |
| + return s.Run(); |
| +} |
| + |
| bool AutofillTable::AddFormFieldValuesTime( |
| const std::vector<FormField>& elements, |
| std::vector<AutofillChange>* changes, |
| @@ -561,10 +667,8 @@ bool AutofillTable::AddFormFieldValuesTime( |
| const size_t kMaximumUniqueNames = 256; |
| std::set<string16> seen_names; |
| bool result = true; |
| - for (std::vector<FormField>::const_iterator |
| - itr = elements.begin(); |
| - itr != elements.end(); |
| - itr++) { |
| + for (std::vector<FormField>::const_iterator itr = elements.begin(); |
| + itr != elements.end(); ++itr) { |
| if (seen_names.size() >= kMaximumUniqueNames) |
| break; |
| if (seen_names.find(itr->name) != seen_names.end()) |
| @@ -733,6 +837,11 @@ bool AutofillTable::AddFormFieldValueTime(const FormField& element, |
| if (!SetCountOfFormElement(pair_id, count + 1)) |
| return false; |
| + // If we already have more than 2 times delete last one, before adding new |
| + // one. |
| + if (count >= 2 && !DeleteLastAccess(pair_id)) |
| + return false; |
| + |
| if (!InsertPairIDAndDate(pair_id, time)) |
| return false; |