diff options
Diffstat (limited to 'chrome/browser/webdata')
-rw-r--r-- | chrome/browser/webdata/web_data_service.cc | 55 | ||||
-rw-r--r-- | chrome/browser/webdata/web_data_service.h | 36 | ||||
-rw-r--r-- | chrome/browser/webdata/web_database.cc | 247 | ||||
-rw-r--r-- | chrome/browser/webdata/web_database.h | 43 |
4 files changed, 375 insertions, 6 deletions
diff --git a/chrome/browser/webdata/web_data_service.cc b/chrome/browser/webdata/web_data_service.cc index fd0e60a..002977c 100644 --- a/chrome/browser/webdata/web_data_service.cc +++ b/chrome/browser/webdata/web_data_service.cc @@ -13,6 +13,7 @@ #include "chrome/browser/template_url.h" #include "chrome/common/chrome_constants.h" #include "webkit/glue/password_form.h" +#include "webkit/glue/autofill_form.h" //////////////////////////////////////////////////////////////////////////////// // @@ -114,6 +115,33 @@ void WebDataService::CancelRequest(Handle h) { i->second->Cancel(); } +void WebDataService::AddAutofillFormElements( + const std::vector<AutofillForm::Element>& element) { + GenericRequest<std::vector<AutofillForm::Element> >* request = + new GenericRequest<std::vector<AutofillForm::Element> >( + this, GetNextRequestHandle(), NULL, element); + RegisterRequest(request); + ScheduleTask(NewRunnableMethod(this, + &WebDataService::AddAutofillFormElementsImpl, + request)); +} + +WebDataService::Handle WebDataService::GetFormValuesForElementName( + const std::wstring& name, const std::wstring& prefix, int limit, + WebDataServiceConsumer* consumer) { + WebDataRequest* request = + new WebDataRequest(this, GetNextRequestHandle(), consumer); + RegisterRequest(request); + ScheduleTask( + NewRunnableMethod(this, + &WebDataService::GetFormValuesForElementNameImpl, + request, + name, + prefix, + limit)); + return request->GetHandle(); +} + void WebDataService::RequestCompleted(Handle h) { pending_lock_.Acquire(); RequestMap::iterator i = pending_requests_.find(h); @@ -562,6 +590,33 @@ void WebDataService::GetAllLoginsImpl(WebDataRequest* request) { //////////////////////////////////////////////////////////////////////////////// // +// Autofill support. +// +//////////////////////////////////////////////////////////////////////////////// + +void WebDataService::AddAutofillFormElementsImpl( + GenericRequest<std::vector<AutofillForm::Element> >* request) { + if (db_ && !request->IsCancelled()) { + if (db_->AddAutofillFormElements(request->GetArgument())) + ScheduleCommit(); + } + request->RequestComplete(); +} + +void WebDataService::GetFormValuesForElementNameImpl(WebDataRequest* request, + const std::wstring& name, const std::wstring& prefix, int limit) { + if (db_ && !request->IsCancelled()) { + std::vector<std::wstring> values; + db_->GetFormValuesForElementName(name, prefix, &values, limit); + request->SetResult( + new WDResult<std::vector<std::wstring> >(AUTOFILL_VALUE_RESULT, + values)); + } + request->RequestComplete(); +} + +//////////////////////////////////////////////////////////////////////////////// +// // Web Apps implementation. // //////////////////////////////////////////////////////////////////////////////// diff --git a/chrome/browser/webdata/web_data_service.h b/chrome/browser/webdata/web_data_service.h index 25a4e27..86a7af88 100644 --- a/chrome/browser/webdata/web_data_service.h +++ b/chrome/browser/webdata/web_data_service.h @@ -14,9 +14,11 @@ #include "chrome/common/scoped_vector.h" #include <map> -class GURL; -struct PasswordForm; +struct AutofillForm::Element; struct IE7PasswordInfo; +struct PasswordForm; +class AutofillForm; +class GURL; class ShutdownTask; class TemplateURL; @@ -46,6 +48,7 @@ typedef enum { PASSWORD_RESULT, // WDResult<std::vector<PasswordForm*>> PASSWORD_IE7_RESULT, // WDResult<IE7PasswordInfo> WEB_APP_IMAGES, // WDResult<WDAppImagesResult> + AUTOFILL_VALUE_RESULT, // WDResult<std::vector<std::wstring>> } WDResultType; // Result from GetWebAppImages. @@ -350,6 +353,25 @@ class WebDataService : public base::RefCountedThreadSafe<WebDataService> { // WebDataServiceConsumer is about to be deleted. void CancelRequest(Handle h); + ////////////////////////////////////////////////////////////////////////////// + // + // Autofill. + // + ////////////////////////////////////////////////////////////////////////////// + + // Schedules a task to add form elements to the web database. + void AddAutofillFormElements( + const std::vector<AutofillForm::Element>& elements); + + // Initiates the request for a vector of values which have been entered in + // form input fields named |name|. The method OnWebDataServiceRequestDone of + // |consumer| gets called back when the request is finished, with the vector + // included in the argument |result|. + Handle GetFormValuesForElementName(const std::wstring& name, + const std::wstring& prefix, + int limit, + WebDataServiceConsumer* consumer); + protected: friend class TemplateURLModelTest; friend class TemplateURLModelTestingProfile; @@ -416,6 +438,16 @@ class WebDataService : public base::RefCountedThreadSafe<WebDataService> { ////////////////////////////////////////////////////////////////////////////// // + // Autofill. + // + ////////////////////////////////////////////////////////////////////////////// + void AddAutofillFormElementsImpl( + GenericRequest<std::vector<AutofillForm::Element> >* request); + void GetFormValuesForElementNameImpl(WebDataRequest* request, + const std::wstring& name, const std::wstring& prefix, int limit); + + ////////////////////////////////////////////////////////////////////////////// + // // Web Apps. // ////////////////////////////////////////////////////////////////////////////// diff --git a/chrome/browser/webdata/web_database.cc b/chrome/browser/webdata/web_database.cc index dca2924..c22990c 100644 --- a/chrome/browser/webdata/web_database.cc +++ b/chrome/browser/webdata/web_database.cc @@ -16,6 +16,7 @@ #include "chrome/browser/ie7_password.h" #include "chrome/browser/template_url.h" #include "chrome/browser/encryptor.h" +#include "chrome/common/l10n_util.h" #include "chrome/common/scoped_vector.h" #include "webkit/glue/password_form.h" @@ -61,6 +62,21 @@ // remember' // passwords for this site. // +// autofill +// name The name of the input as specified in the html. +// value The literal contents of the text field. +// value_lower The contents of the text field made lower_case. +// pair_id An ID number unique to the row in the table. +// count How many times the user has entered the string |value| +// in a field of name |name|. +// +// autofill_dates This table associates a row to each separate time the +// user submits a form containing a certain name/value +// pair. The |pair_id| should match the |pair_id| field +// in the appropriate row of the autofill table. +// pair_id +// date_created +// // web_app_icons // url URL of the web app. // width Width of the image. @@ -161,7 +177,8 @@ bool WebDatabase::Init(const std::wstring& db_name) { // Initialize the tables. if (!InitKeywordsTable() || !InitLoginsTable() || !InitWebAppIconsTable() || - !InitWebAppsTable()) { + !InitWebAppsTable() || !InitAutofillTable() || + !InitAutofillDatesTable()) { LOG(WARNING) << "Unable to initialize the web database."; return false; } @@ -345,6 +362,58 @@ bool WebDatabase::InitLoginsTable() { return true; } +bool WebDatabase::InitAutofillTable() { + if (!DoesSqliteTableExist(db_, "autofill")) { + if (sqlite3_exec(db_, + "CREATE TABLE autofill (" + "name VARCHAR, " + "value VARCHAR, " + "value_lower VARCHAR, " + "pair_id INTEGER PRIMARY KEY, " + "count INTEGER DEFAULT 1)", + NULL, NULL, NULL) != SQLITE_OK) { + NOTREACHED(); + return false; + } + if (sqlite3_exec(db_, + "CREATE INDEX autofill_name ON " + "autofill (name)", + NULL, NULL, NULL) != SQLITE_OK) { + NOTREACHED(); + return false; + } + if (sqlite3_exec(db_, + "CREATE INDEX autofill_name_value_lower ON " + "autofill (name, value_lower)", + NULL, NULL, NULL) != SQLITE_OK) { + NOTREACHED(); + return false; + } + } + return true; +} + +bool WebDatabase::InitAutofillDatesTable() { + if (!DoesSqliteTableExist(db_, "autofill_dates")) { + if (sqlite3_exec(db_, + "CREATE TABLE autofill_dates ( " + "pair_id INTEGER DEFAULT 0, " + "date_created INTEGER DEFAULT 0)", + NULL, NULL, NULL) != SQLITE_OK) { + NOTREACHED(); + return false; + } + if (sqlite3_exec(db_, + "CREATE INDEX autofill_dates_pair_id ON " + "autofill (pair_id)", + NULL, NULL, NULL) != SQLITE_OK) { + NOTREACHED(); + return false; + } + } + return true; +} + bool WebDatabase::InitWebAppIconsTable() { if (!DoesSqliteTableExist(db_, "web_app_icons")) { if (sqlite3_exec(db_, "CREATE TABLE web_app_icons (" @@ -457,7 +526,7 @@ bool WebDatabase::GetKeywords(std::vector<TemplateURL*>* urls) { NOTREACHED() << "Statement prepare failed"; return false; } - int64 result; + int result; while ((result = s.step()) == SQLITE_ROW) { TemplateURL* template_url = new TemplateURL(); std::wstring tmp; @@ -791,7 +860,7 @@ bool WebDatabase::GetLogins(const PasswordForm& form, s.bind_string(0, form.signon_realm); - int64 result; + int result; while ((result = s.step()) == SQLITE_ROW) { PasswordForm* new_form = new PasswordForm(); InitPasswordFormFromStatement(new_form, &s); @@ -842,7 +911,7 @@ bool WebDatabase::GetAllLogins(std::vector<PasswordForm*>* forms, return false; } - int64 result; + int result; while ((result = s.step()) == SQLITE_ROW) { PasswordForm* new_form = new PasswordForm(); InitPasswordFormFromStatement(new_form, &s); @@ -852,6 +921,176 @@ bool WebDatabase::GetAllLogins(std::vector<PasswordForm*>* forms, return result == SQLITE_DONE; } +bool WebDatabase::AddAutofillFormElements( + const std::vector<AutofillForm::Element>& elements) { + bool result = true; + for (std::vector<AutofillForm::Element>::const_iterator + itr = elements.begin(); + itr != elements.end(); + itr++) { + result = result && AddAutofillFormElement(*itr); + } + return result; +} + +bool WebDatabase::GetIDAndCountOfFormElement( + const AutofillForm::Element& element, int64* pair_id, int* count) { + SQLStatement s; + + if (s.prepare(db_, "SELECT pair_id, count FROM autofill " + " WHERE name = ? AND value = ?") != SQLITE_OK) { + NOTREACHED() << "Statement prepare failed"; + return false; + } + + s.bind_wstring(0, element.name); + s.bind_wstring(1, element.value); + + int result; + + *count = 0; + + if ((result = s.step()) == SQLITE_ROW) { + *pair_id = s.column_int64(0); + *count = s.column_int(1); + } + + return true; +} + +bool WebDatabase::InsertFormElement(const AutofillForm::Element& element, + int64* pair_id) { + SQLStatement s; + + if (s.prepare(db_, "INSERT INTO autofill " + "(name, value, value_lower) " + "VALUES (?, ?, ?)") + != SQLITE_OK) { + NOTREACHED() << "Statement prepare failed"; + return false; + } + + s.bind_wstring(0, element.name); + s.bind_wstring(1, element.value); + s.bind_wstring(2, l10n_util::ToLower(element.value)); + + if (s.step() != SQLITE_DONE) { + NOTREACHED(); + return false; + } + + *pair_id = sqlite3_last_insert_rowid(db_); + + return true; +} + +bool WebDatabase::InsertPairIDAndDate(int64 pair_id, + const Time& date_created) { + SQLStatement s; + + if (s.prepare(db_, + "INSERT INTO autofill_dates " + "(pair_id, date_created) VALUES (?, ?)") + != SQLITE_OK) { + NOTREACHED() << "Statement prepare failed"; + return false; + } + + s.bind_int64(0, pair_id); + s.bind_int64(1, date_created.ToTimeT()); + + if (s.step() != SQLITE_DONE) { + NOTREACHED(); + return false; + } + + return true; +} + +bool WebDatabase::SetCountOfFormElement(int64 pair_id, int count) { + SQLStatement s; + + if (s.prepare(db_, + "UPDATE autofill SET count = ? " + "WHERE pair_id = ?") + != SQLITE_OK) { + NOTREACHED() << "Statement prepare failed"; + return false; + } + + s.bind_int(0, count); + s.bind_int64(1, pair_id); + + if (s.step() != SQLITE_DONE) { + NOTREACHED(); + return false; + } + + return true; +} + +bool WebDatabase::AddAutofillFormElement(const AutofillForm::Element& element) { + SQLStatement s; + int count = 0; + int64 pair_id; + + if (!GetIDAndCountOfFormElement(element, &pair_id, &count)) + return false; + + if (count == 0 && !InsertFormElement(element, &pair_id)) + return false; + + return SetCountOfFormElement(pair_id, count + 1) && + InsertPairIDAndDate(pair_id, Time::Now()); +} + +bool WebDatabase::GetFormValuesForElementName(const std::wstring& name, + const std::wstring& prefix, + std::vector<std::wstring>* values, + int limit) { + DCHECK(values); + SQLStatement s; + + if (prefix.empty()) { + if (s.prepare(db_, "SELECT value FROM autofill " + "WHERE name = ? " + "ORDER BY count DESC " + "LIMIT ?") != SQLITE_OK) { + NOTREACHED() << "Statement prepare failed"; + return false; + } + + s.bind_wstring(0, name); + s.bind_int(1, limit); + } else { + std::wstring prefix_lower = l10n_util::ToLower(prefix); + std::wstring next_prefix = prefix_lower; + next_prefix[next_prefix.length() - 1]++; + + if (s.prepare(db_, "SELECT value FROM autofill " + "WHERE name = ? AND " + "value_lower >= ? AND " + "value_lower < ? " + "ORDER BY count DESC " + "LIMIT ?") != SQLITE_OK) { + NOTREACHED() << "Statement prepare failed"; + return false; + } + + s.bind_wstring(0, name); + s.bind_wstring(1, prefix_lower); + s.bind_wstring(2, next_prefix); + s.bind_int(3, limit); + } + + int result; + values->clear(); + while ((result = s.step()) == SQLITE_ROW) + values->push_back(s.column_string16(0)); + + return result == SQLITE_DONE; +} + void WebDatabase::MigrateOldVersionsAsNeeded() { // Migrate if necessary. int current_version = meta_table_.GetVersionNumber(); diff --git a/chrome/browser/webdata/web_database.h b/chrome/browser/webdata/web_database.h index cff9c88..3b5c660 100644 --- a/chrome/browser/webdata/web_database.h +++ b/chrome/browser/webdata/web_database.h @@ -13,6 +13,7 @@ #include "chrome/browser/template_url.h" #include "chrome/common/sqlite_utils.h" #include "skia/include/SkBitmap.h" +#include "webkit/glue/autofill_form.h" namespace base { class Time; @@ -113,6 +114,46 @@ class WebDatabase { ////////////////////////////////////////////////////////////////////////////// // + // Autofill + // + ////////////////////////////////////////////////////////////////////////////// + + + + // Records the form elements in |elements| in the database in the autofill + // table. + bool AddAutofillFormElements( + const std::vector<AutofillForm::Element>& elements); + + // Records a single form element in in the database in the autofill table. + bool AddAutofillFormElement(const AutofillForm::Element& element); + + // Retrieves a vector of all values which have been recorded in the autofill + // table as the value in a form element with name |name| and which start with + // |prefix|. The comparison of the prefix is case insensitive. + bool GetFormValuesForElementName(const std::wstring& name, + const std::wstring& prefix, + std::vector<std::wstring>* values, + int limit); + + // Gets the pair_id and count entries from name and value specified in + // |element|. Sets *count to 0 if there is no such row in the table. + bool GetIDAndCountOfFormElement(const AutofillForm::Element& element, + int64* pair_id, + int* count); + + // Updates the count entry in the row corresponding to |pair_id| to |count|. + bool SetCountOfFormElement(int64 pair_id, int count); + + // Adds a new row to the autofill table with name and value given in + // |element|. Sets *pair_id to the pair_id of the new row. + bool InsertFormElement(const AutofillForm::Element& element, int64* pair_id); + + // Adds a new row to the autofill_dates table. + bool InsertPairIDAndDate(int64 pair_id, const base::Time& date_created); + + ////////////////////////////////////////////////////////////////////////////// + // // Web Apps // ////////////////////////////////////////////////////////////////////////////// @@ -130,6 +171,8 @@ class WebDatabase { bool InitKeywordsTable(); bool InitLoginsTable(); + bool InitAutofillTable(); + bool InitAutofillDatesTable(); bool InitWebAppIconsTable(); bool InitWebAppsTable(); |