summaryrefslogtreecommitdiffstats
path: root/chrome/browser/webdata
diff options
context:
space:
mode:
authorpetersont@google.com <petersont@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-11-05 20:26:28 +0000
committerpetersont@google.com <petersont@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-11-05 20:26:28 +0000
commit6f2ff8526c54090bf6afe9c80f2d63551231e997 (patch)
tree2cacbf423441a4f442e8ec01a176c519154c7112 /chrome/browser/webdata
parent2b481f8d533c08824d3aeeeb9a0407b596077c16 (diff)
downloadchromium_src-6f2ff8526c54090bf6afe9c80f2d63551231e997.zip
chromium_src-6f2ff8526c54090bf6afe9c80f2d63551231e997.tar.gz
chromium_src-6f2ff8526c54090bf6afe9c80f2d63551231e997.tar.bz2
Added functions to WebDatabase and WebDataService for recording frequent entries in text input elements in forms. Also added the class AutofillManager which gets instantiated once per WebContents and provides an API from which the database can be easily accessed to provide a list of possible desired values to be entered in a text field given what the user has already typed there.
Review URL: http://codereview.chromium.org/8845 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@4809 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/webdata')
-rw-r--r--chrome/browser/webdata/web_data_service.cc55
-rw-r--r--chrome/browser/webdata/web_data_service.h36
-rw-r--r--chrome/browser/webdata/web_database.cc247
-rw-r--r--chrome/browser/webdata/web_database.h43
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();