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

Unified Diff: chrome/browser/autofill/autofill_manager.cc

Issue 8387016: Move some Autofill processing logic on form submit to a background thread. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Don't rely on any particular order of evaluation for the arguments to PostTaskAndReply Created 9 years, 2 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/autofill/autofill_manager.h ('k') | chrome/browser/autofill/autofill_manager_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/autofill/autofill_manager.cc
diff --git a/chrome/browser/autofill/autofill_manager.cc b/chrome/browser/autofill/autofill_manager.cc
index 9b8ec0b5083b65f35e46be78e697e7faa477e709..e5754a70045626fddc7ecdceadeef96aa03b16ea 100644
--- a/chrome/browser/autofill/autofill_manager.cc
+++ b/chrome/browser/autofill/autofill_manager.cc
@@ -11,6 +11,7 @@
#include <set>
#include <utility>
+#include "base/bind.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/string16.h"
@@ -44,6 +45,7 @@
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "content/browser/renderer_host/render_view_host.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "googleurl/src/gurl.h"
@@ -127,6 +129,40 @@ bool FormIsHTTPS(const FormStructure& form) {
return form.source_url().SchemeIs(chrome::kHttpsScheme);
}
+// Uses the existing personal data in |profiles| and |credit_cards| to determine
+// possible field types for the |submitted_form|. This is potentially
+// expensive -- on the order of 50ms even for a small set of |stored_data|.
+// Hence, it should not run on the UI thread -- to avoid locking up the UI --
+// nor on the IO thread -- to avoid blocking IPC calls.
+void DeterminePossibleFieldTypesForUpload(
+ const std::vector<AutofillProfile>& profiles,
+ const std::vector<CreditCard>& credit_cards,
+ FormStructure* submitted_form) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
+ // For each field in the |submitted_form|, extract the value. Then for each
+ // profile or credit card, identify any stored types that match the value.
+ for (size_t i = 0; i < submitted_form->field_count(); ++i) {
+ AutofillField* field = submitted_form->field(i);
+ string16 value = CollapseWhitespace(field->value, false);
+
+ FieldTypeSet matching_types;
+ for (std::vector<AutofillProfile>::const_iterator it = profiles.begin();
+ it != profiles.end(); ++it) {
+ it->GetMatchingTypes(value, &matching_types);
+ }
+ for (std::vector<CreditCard>::const_iterator it = credit_cards.begin();
+ it != credit_cards.end(); ++it) {
+ it->GetMatchingTypes(value, &matching_types);
+ }
+
+ if (matching_types.empty())
+ matching_types.insert(UNKNOWN_TYPE);
+
+ field->set_possible_types(matching_types);
+ }
+}
+
// Check for unidentified forms among those with the most query or upload
// requests. If found, present an infobar prompting the user to send Google
// Feedback identifying these forms. Only executes if the appropriate flag is
@@ -219,8 +255,6 @@ AutofillManager::AutofillManager(TabContentsWrapper* tab_contents)
user_did_autofill_(false),
user_did_edit_autofilled_field_(false),
external_delegate_(NULL) {
- DCHECK(tab_contents);
-
// |personal_data_| is NULL when using TestTabContents.
personal_data_ = PersonalDataManagerFactory::GetForProfile(
tab_contents->profile()->GetOriginalProfile());
@@ -282,53 +316,81 @@ bool AutofillManager::OnMessageReceived(const IPC::Message& message) {
return handled;
}
-void AutofillManager::OnFormSubmitted(const FormData& form,
+bool AutofillManager::OnFormSubmitted(const FormData& form,
const TimeTicks& timestamp) {
// Let AutoComplete know as well.
tab_contents_wrapper_->autocomplete_history_manager()->OnFormSubmitted(form);
if (!IsAutofillEnabled())
- return;
+ return false;
if (tab_contents()->browser_context()->IsOffTheRecord())
- return;
+ return false;
// Don't save data that was submitted through JavaScript.
if (!form.user_submitted)
- return;
+ return false;
// Grab a copy of the form data.
- FormStructure submitted_form(form);
+ scoped_ptr<FormStructure> submitted_form(new FormStructure(form));
// Disregard forms that we wouldn't ever autofill in the first place.
- if (!submitted_form.ShouldBeParsed(true))
- return;
+ if (!submitted_form->ShouldBeParsed(true))
+ return false;
// Ignore forms not present in our cache. These are typically forms with
// wonky JavaScript that also makes them not auto-fillable.
FormStructure* cached_submitted_form;
if (!FindCachedForm(form, &cached_submitted_form))
- return;
- submitted_form.UpdateFromCache(*cached_submitted_form);
+ return false;
+
+ submitted_form->UpdateFromCache(*cached_submitted_form);
+ if (submitted_form->IsAutofillable(true))
+ ImportFormData(*submitted_form);
// Only upload server statistics and UMA metrics if at least some local data
// is available to use as a baseline.
- if (!personal_data_->profiles().empty() ||
- !personal_data_->credit_cards().empty()) {
- DeterminePossibleFieldTypesForUpload(&submitted_form);
- submitted_form.LogQualityMetrics(*metric_logger_,
- forms_loaded_timestamp_,
- initial_interaction_timestamp_,
- timestamp);
-
- if (submitted_form.ShouldBeCrowdsourced())
- UploadFormData(submitted_form);
- }
+ const std::vector<AutofillProfile*>& profiles = personal_data_->profiles();
+ const std::vector<CreditCard*>& credit_cards = personal_data_->credit_cards();
+ if (!profiles.empty() || !credit_cards.empty()) {
+ // Copy the profile and credit card data, so that it can be accessed on a
+ // separate thread.
+ std::vector<AutofillProfile> copied_profiles;
+ copied_profiles.reserve(profiles.size());
+ for (std::vector<AutofillProfile*>::const_iterator it = profiles.begin();
+ it != profiles.end(); ++it) {
+ copied_profiles.push_back(**it);
+ }
- if (!submitted_form.IsAutofillable(true))
- return;
+ std::vector<CreditCard> copied_credit_cards;
+ copied_credit_cards.reserve(credit_cards.size());
+ for (std::vector<CreditCard*>::const_iterator it = credit_cards.begin();
+ it != credit_cards.end(); ++it) {
+ copied_credit_cards.push_back(**it);
+ }
- ImportFormData(submitted_form);
+ // TODO(isherman): Ideally, we should not be using the FILE thread here.
+ // Per jar@, this is a good compromise for now, as we don't currently have a
+ // broad consensus on how to support such one-off background tasks.
+
+ // Note that ownership of |submitted_form| is passed to the second task,
+ // using |base::Owned|.
+ FormStructure* raw_submitted_form = submitted_form.get();
+ BrowserThread::PostTaskAndReply(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&DeterminePossibleFieldTypesForUpload,
+ copied_profiles,
+ copied_credit_cards,
+ raw_submitted_form),
+ base::Bind(&AutofillManager::UploadFormDataAsyncCallback,
+ this,
+ base::Owned(submitted_form.release()),
+ forms_loaded_timestamp_,
+ initial_interaction_timestamp_,
+ timestamp));
+ }
+
+ return true;
}
void AutofillManager::OnFormsSeen(const std::vector<FormData>& forms,
@@ -627,35 +689,6 @@ bool AutofillManager::IsAutofillEnabled() const {
return profile->GetPrefs()->GetBoolean(prefs::kAutofillEnabled);
}
-void AutofillManager::DeterminePossibleFieldTypesForUpload(
- FormStructure* submitted_form) {
- // Combine all the profiles and credit cards stored in |personal_data_| into
- // one vector for ease of iteration.
- const std::vector<AutofillProfile*>& profiles = personal_data_->profiles();
- const std::vector<CreditCard*>& credit_cards = personal_data_->credit_cards();
- std::vector<FormGroup*> stored_data;
- stored_data.insert(stored_data.end(), profiles.begin(), profiles.end());
- stored_data.insert(stored_data.end(), credit_cards.begin(),
- credit_cards.end());
-
- // For each field in the |submitted_form|, extract the value. Then for each
- // profile or credit card, identify any stored types that match the value.
- for (size_t i = 0; i < submitted_form->field_count(); i++) {
- AutofillField* field = submitted_form->field(i);
- string16 value = CollapseWhitespace(field->value, false);
- FieldTypeSet matching_types;
- for (std::vector<FormGroup*>::const_iterator it = stored_data.begin();
- it != stored_data.end(); ++it) {
- (*it)->GetMatchingTypes(value, &matching_types);
- }
-
- if (matching_types.empty())
- matching_types.insert(UNKNOWN_TYPE);
-
- field->set_possible_types(matching_types);
- }
-}
-
void AutofillManager::SendAutofillTypePredictions(
const std::vector<FormStructure*>& forms) const {
if (!CommandLine::ForCurrentProcess()->HasSwitch(
@@ -691,6 +724,24 @@ void AutofillManager::ImportFormData(const FormStructure& submitted_form) {
}
}
+// Note that |submitted_form| is passed as a pointer rather than as a reference
+// so that we can get memory management right across threads. Note also that we
+// explicitly pass in all the time stamps of interest, as the cached ones might
+// get reset before this method executes.
+void AutofillManager::UploadFormDataAsyncCallback(
+ const FormStructure* submitted_form,
+ const TimeTicks& load_time,
+ const TimeTicks& interaction_time,
+ const TimeTicks& submission_time) {
+ submitted_form->LogQualityMetrics(*metric_logger_,
+ load_time,
+ interaction_time,
+ submission_time);
+
+ if (submitted_form->ShouldBeCrowdsourced())
+ UploadFormData(*submitted_form);
+}
+
void AutofillManager::UploadFormData(const FormStructure& submitted_form) {
if (disable_download_manager_requests_)
return;
« no previous file with comments | « chrome/browser/autofill/autofill_manager.h ('k') | chrome/browser/autofill/autofill_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698