summaryrefslogtreecommitdiffstats
path: root/chrome
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
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')
-rw-r--r--chrome/browser/autofill_manager.cc81
-rw-r--r--chrome/browser/autofill_manager.h58
-rw-r--r--chrome/browser/browser.vcproj12
-rw-r--r--chrome/browser/render_view_host.cc7
-rw-r--r--chrome/browser/render_view_host.h2
-rw-r--r--chrome/browser/render_view_host_delegate.h3
-rw-r--r--chrome/browser/web_contents.cc12
-rw-r--r--chrome/browser/web_contents.h8
-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
-rw-r--r--chrome/common/render_messages.h33
-rw-r--r--chrome/common/render_messages_internal.h4
14 files changed, 595 insertions, 6 deletions
diff --git a/chrome/browser/autofill_manager.cc b/chrome/browser/autofill_manager.cc
new file mode 100644
index 0000000..af8589b
--- /dev/null
+++ b/chrome/browser/autofill_manager.cc
@@ -0,0 +1,81 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/autofill_manager.h"
+
+#include "base/string_util.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/web_contents.h"
+
+AutofillManager::~AutofillManager() {
+ ClearPendingQuery();
+}
+
+void AutofillManager::ClearPendingQuery() {
+ pending_query_name_.clear();
+ pending_query_prefix_.clear();
+
+ if (query_is_pending_) {
+ WebDataService* web_data_service =
+ profile()->GetWebDataService(Profile::EXPLICIT_ACCESS);
+ if (!web_data_service) {
+ NOTREACHED();
+ return;
+ }
+ web_data_service->CancelRequest(pending_query_handle_);
+ }
+ pending_query_handle_ = 0;
+ query_is_pending_ = false;
+}
+
+void AutofillManager::AutofillFormSubmitted(const AutofillForm& form) {
+ StoreFormEntriesInWebDatabase(form);
+}
+
+void AutofillManager::FetchValuesForName(const std::wstring& name,
+ const std::wstring& prefix,
+ int limit) {
+ WebDataService* web_data_service =
+ profile()->GetWebDataService(Profile::EXPLICIT_ACCESS);
+ if (!web_data_service) {
+ NOTREACHED();
+ return;
+ }
+
+ ClearPendingQuery();
+
+ pending_query_handle_ = web_data_service->
+ GetFormValuesForElementName(name, prefix, limit, this);
+ pending_query_name_ = name;
+ pending_query_prefix_ = prefix;
+}
+
+void AutofillManager::OnWebDataServiceRequestDone(WebDataService::Handle h,
+ const WDTypedResult* result) {
+ DCHECK(query_is_pending_);
+
+ DCHECK(result);
+ if (!result)
+ return;
+
+ switch (result->GetType()) {
+ case AUTOFILL_VALUE_RESULT: {
+ break;
+ }
+ default:
+ NOTREACHED();
+ break;
+ }
+
+ ClearPendingQuery();
+}
+
+void AutofillManager::StoreFormEntriesInWebDatabase(
+ const AutofillForm& form) {
+ if (profile()->IsOffTheRecord())
+ return;
+
+ profile()->GetWebDataService(Profile::EXPLICIT_ACCESS)->
+ AddAutofillFormElements(form.elements);
+}
diff --git a/chrome/browser/autofill_manager.h b/chrome/browser/autofill_manager.h
new file mode 100644
index 0000000..fac533f
--- /dev/null
+++ b/chrome/browser/autofill_manager.h
@@ -0,0 +1,58 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_AUTOFILL_MANAGER_H_
+#define CHROME_BROWSER_AUTOFILL_MANAGER_H_
+
+#include <map>
+#include <string>
+
+#include "chrome/browser/webdata/web_data_service.h"
+#include "chrome/browser/web_contents.h"
+#include "webkit/glue/autofill_form.h"
+
+class Profile;
+
+// Per-tab autofill manager. Handles receiving form data from the renderer and
+// the storing and retrieving of form data through WebDataService.
+class AutofillManager : public WebDataServiceConsumer {
+ public:
+ explicit AutofillManager(WebContents* web_contents)
+ : query_is_pending_(false), web_contents_(web_contents) {}
+ virtual ~AutofillManager();
+
+ void ClearPendingQuery();
+
+ Profile* profile() { return web_contents_->profile(); }
+
+ // Called when a form is submitted (i.e. when the user hits the submit button)
+ // to store the form entries in the profile's sql database.
+ void AutofillFormSubmitted(const AutofillForm& form);
+
+ // Starts a query into the database for the values corresponding to name.
+ // OnWebDataServiceRequestDone gets called when the query completes.
+ void FetchValuesForName(const std::wstring& name, const std::wstring& prefix,
+ int limit);
+
+ // WebDataServiceConsumer implementation.
+ virtual void OnWebDataServiceRequestDone(WebDataService::Handle h,
+ const WDTypedResult* result);
+
+ private:
+ void StoreFormEntriesInWebDatabase(const AutofillForm& form);
+
+ WebContents* web_contents_;
+
+ // When the manager makes a request from WebDataService, the database
+ // is queried on another thread, we record the query in this map until we
+ // get called back.
+ bool query_is_pending_;
+ WebDataService::Handle pending_query_handle_;
+ std::wstring pending_query_name_;
+ std::wstring pending_query_prefix_;
+
+ DISALLOW_COPY_AND_ASSIGN(AutofillManager);
+};
+
+#endif // CHROME_BROWSER_AUTOFILL_MANAGER_H_
diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj
index a39fe95..058b259 100644
--- a/chrome/browser/browser.vcproj
+++ b/chrome/browser/browser.vcproj
@@ -2126,6 +2126,18 @@
>
</File>
</Filter>
+ <Filter
+ Name="Autofill"
+ >
+ <File
+ RelativePath=".\autofill_manager.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\autofill_manager.h"
+ >
+ </File>
+ </Filter>
<File
RelativePath=".\browser_trial.cc"
>
diff --git a/chrome/browser/render_view_host.cc b/chrome/browser/render_view_host.cc
index 963acc9..84f5a7d 100644
--- a/chrome/browser/render_view_host.cc
+++ b/chrome/browser/render_view_host.cc
@@ -651,6 +651,8 @@ void RenderViewHost::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ShowModalHTMLDialog,
OnMsgShowModalHTMLDialog)
IPC_MESSAGE_HANDLER(ViewHostMsg_PasswordFormsSeen, OnMsgPasswordFormsSeen)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_AutofillFormSubmitted,
+ OnMsgAutofillFormSubmitted)
IPC_MESSAGE_HANDLER(ViewHostMsg_StartDragging, OnMsgStartDragging)
IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateDragCursor, OnUpdateDragCursor)
IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
@@ -1064,6 +1066,11 @@ void RenderViewHost::OnMsgPasswordFormsSeen(
delegate_->PasswordFormsSeen(forms);
}
+void RenderViewHost::OnMsgAutofillFormSubmitted(
+ const AutofillForm& form) {
+ delegate_->AutofillFormSubmitted(form);
+}
+
void RenderViewHost::OnMsgStartDragging(
const WebDropData& drop_data) {
RenderViewHostDelegate::View* view = delegate_->GetViewDelegate();
diff --git a/chrome/browser/render_view_host.h b/chrome/browser/render_view_host.h
index 551c5b8..7f7d298 100644
--- a/chrome/browser/render_view_host.h
+++ b/chrome/browser/render_view_host.h
@@ -16,6 +16,7 @@
#include "chrome/personalization/personalization.h"
#endif
#include "webkit/glue/password_form_dom_manager.h"
+#include "webkit/glue/autofill_form.h"
enum ConsoleMessageLevel;
class NavigationEntry;
@@ -462,6 +463,7 @@ class RenderViewHost : public RenderWidgetHost {
const std::string& json_arguments,
IPC::Message* reply_msg);
void OnMsgPasswordFormsSeen(const std::vector<PasswordForm>& forms);
+ void OnMsgAutofillFormSubmitted(const AutofillForm& forms);
void OnMsgStartDragging(const WebDropData& drop_data);
void OnUpdateDragCursor(bool is_drop_target);
void OnTakeFocus(bool reverse);
diff --git a/chrome/browser/render_view_host_delegate.h b/chrome/browser/render_view_host_delegate.h
index eea3113..e4aefb1 100644
--- a/chrome/browser/render_view_host_delegate.h
+++ b/chrome/browser/render_view_host_delegate.h
@@ -282,6 +282,9 @@ class RenderViewHostDelegate {
// Password forms have been detected in the page.
virtual void PasswordFormsSeen(const std::vector<PasswordForm>& forms) { }
+
+ // Forms fillable by autofill have been detected in the page.
+ virtual void AutofillFormSubmitted(const AutofillForm& form) { }
// Notification that the page has an OpenSearch description document.
virtual void PageHasOSDD(RenderViewHost* render_view_host,
diff --git a/chrome/browser/web_contents.cc b/chrome/browser/web_contents.cc
index 9a10c30..e454275 100644
--- a/chrome/browser/web_contents.cc
+++ b/chrome/browser/web_contents.cc
@@ -9,6 +9,7 @@
#include "base/file_version_info.h"
#include "base/process_util.h"
#include "chrome/app/locales/locale_settings.h"
+#include "chrome/browser/autofill_manager.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/cache_manager_host.h"
@@ -270,6 +271,12 @@ void WebContents::RegisterUserPrefs(PrefService* prefs) {
IDS_STATIC_ENCODING_LIST);
}
+AutofillManager* WebContents::GetAutofillManager() {
+ if (autofill_manager_.get() == NULL)
+ autofill_manager_.reset(new AutofillManager(this));
+ return autofill_manager_.get();
+}
+
PasswordManager* WebContents::GetPasswordManager() {
if (password_manager_.get() == NULL)
password_manager_.reset(new PasswordManager(this));
@@ -1113,6 +1120,11 @@ void WebContents::PasswordFormsSeen(
GetPasswordManager()->PasswordFormsSeen(forms);
}
+void WebContents::AutofillFormSubmitted(
+ const AutofillForm& form) {
+ GetAutofillManager()->AutofillFormSubmitted(form);
+}
+
// Checks to see if we should generate a keyword based on the OSDD, and if
// necessary uses TemplateURLFetcher to download the OSDD and create a keyword.
void WebContents::PageHasOSDD(RenderViewHost* render_view_host,
diff --git a/chrome/browser/web_contents.h b/chrome/browser/web_contents.h
index f907b6c..9804ac6 100644
--- a/chrome/browser/web_contents.h
+++ b/chrome/browser/web_contents.h
@@ -15,6 +15,7 @@
#include "chrome/browser/tab_contents.h"
#include "chrome/browser/web_app.h"
+class AutofillManager;
class InterstitialPageDelegate;
class PasswordManager;
class PluginInstaller;
@@ -47,6 +48,9 @@ class WebContents : public TabContents,
// Getters -------------------------------------------------------------------
+ // Returns the AutofillManager, creating it if necessary.
+ AutofillManager* GetAutofillManager();
+
// Returns the PasswordManager, creating it if necessary.
PasswordManager* GetPasswordManager();
@@ -284,6 +288,7 @@ class WebContents : public TabContents,
const std::string& json_arguments,
IPC::Message* reply_msg);
virtual void PasswordFormsSeen(const std::vector<PasswordForm>& forms);
+ virtual void AutofillFormSubmitted(const AutofillForm& form);
virtual void PageHasOSDD(RenderViewHost* render_view_host,
int32 page_id, const GURL& url, bool autodetected);
virtual void InspectElementReply(int num_resources);
@@ -514,6 +519,9 @@ class WebContents : public TabContents,
// they should pump messages then.
ScopedHandle message_box_active_;
+ // AutofillManager, lazily created.
+ scoped_ptr<AutofillManager> autofill_manager_;
+
// PasswordManager, lazily created.
scoped_ptr<PasswordManager> password_manager_;
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();
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index fbc1798..d50faa6 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -7,6 +7,7 @@
#include <string>
#include <vector>
+#include <map>
#include "base/basictypes.h"
#include "base/ref_counted.h"
@@ -18,6 +19,7 @@
#include "googleurl/src/gurl.h"
#include "net/base/upload_data.h"
#include "net/url_request/url_request_status.h"
+#include "webkit/glue/autofill_form.h"
#include "webkit/glue/cache_manager.h"
#include "webkit/glue/context_node_types.h"
#include "webkit/glue/form_data.h"
@@ -823,6 +825,37 @@ struct ParamTraits<PasswordForm> {
}
};
+// Traits for AutofillForm_Params structure to pack/unpack.
+template <>
+struct ParamTraits<AutofillForm> {
+ typedef AutofillForm param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.elements.size());
+ for (std::vector<AutofillForm::Element>::const_iterator itr =
+ p.elements.begin();
+ itr != p.elements.end();
+ itr++) {
+ WriteParam(m, itr->name);
+ WriteParam(m, itr->value);
+ }
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ bool result = true;
+ size_t elements_size = 0;
+ result = result && ReadParam(m, iter, &elements_size);
+ p->elements.resize(elements_size);
+ for (size_t i = 0; i < elements_size; i++) {
+ std::wstring s;
+ result = result && ReadParam(m, iter, &(p->elements[i].name));
+ result = result && ReadParam(m, iter, &(p->elements[i].value));
+ }
+ return result;
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"<AutofillForm>");
+ }
+};
+
// Traits for ViewHostMsg_FrameNavigate_Params structure to pack/unpack.
template <>
struct ParamTraits<ViewHostMsg_FrameNavigate_Params> {
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 4e7e3dc..286b2e5 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -838,6 +838,10 @@ IPC_BEGIN_MESSAGES(ViewHost, 2)
IPC_MESSAGE_ROUTED1(ViewHostMsg_PasswordFormsSeen,
std::vector<PasswordForm> /* forms */)
+ // Notification that a form has been submitted. The user hit the button.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_AutofillFormSubmitted,
+ AutofillForm /* form */)
+
// Used to tell the parent the user started dragging in the content area. The
// WebDropData struct contains contextual information about the pieces of the
// page the user dragged. The parent uses this notification to initiate a