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

Side by Side Diff: components/autofill/browser/autofill_manager.cc

Issue 17392006: In components/autofill, move browser/ to core/browser/ (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase to fix conflicts Created 7 years, 6 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/autofill/browser/autofill_manager.h"
6
7 #include <stddef.h>
8
9 #include <limits>
10 #include <map>
11 #include <set>
12 #include <utility>
13
14 #include "base/bind.h"
15 #include "base/command_line.h"
16 #include "base/guid.h"
17 #include "base/logging.h"
18 #include "base/prefs/pref_service.h"
19 #include "base/strings/string16.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/threading/sequenced_worker_pool.h"
23 #include "components/autofill/browser/autocomplete_history_manager.h"
24 #include "components/autofill/browser/autofill_data_model.h"
25 #include "components/autofill/browser/autofill_driver.h"
26 #include "components/autofill/browser/autofill_external_delegate.h"
27 #include "components/autofill/browser/autofill_field.h"
28 #include "components/autofill/browser/autofill_manager_delegate.h"
29 #include "components/autofill/browser/autofill_manager_test_delegate.h"
30 #include "components/autofill/browser/autofill_metrics.h"
31 #include "components/autofill/browser/autofill_profile.h"
32 #include "components/autofill/browser/autofill_type.h"
33 #include "components/autofill/browser/credit_card.h"
34 #include "components/autofill/browser/form_structure.h"
35 #include "components/autofill/browser/personal_data_manager.h"
36 #include "components/autofill/browser/phone_number.h"
37 #include "components/autofill/browser/phone_number_i18n.h"
38 #include "components/autofill/content/browser/autocheckout/whitelist_manager.h"
39 #include "components/autofill/content/browser/autocheckout_manager.h"
40 #include "components/autofill/core/common/autofill_messages.h"
41 #include "components/autofill/core/common/autofill_pref_names.h"
42 #include "components/autofill/core/common/autofill_switches.h"
43 #include "components/autofill/core/common/form_data.h"
44 #include "components/autofill/core/common/form_data_predictions.h"
45 #include "components/autofill/core/common/form_field_data.h"
46 #include "components/autofill/core/common/password_form_fill_data.h"
47 #include "components/user_prefs/pref_registry_syncable.h"
48 #include "content/public/browser/browser_context.h"
49 #include "content/public/browser/browser_thread.h"
50 #include "content/public/browser/navigation_details.h"
51 #include "content/public/browser/render_view_host.h"
52 #include "content/public/browser/web_contents.h"
53 #include "content/public/browser/web_contents_view.h"
54 #include "content/public/common/frame_navigate_params.h"
55 #include "content/public/common/url_constants.h"
56 #include "googleurl/src/gurl.h"
57 #include "grit/component_strings.h"
58 #include "ipc/ipc_message_macros.h"
59 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAutofillClient.h"
60 #include "ui/base/l10n/l10n_util.h"
61 #include "ui/gfx/rect.h"
62
63 namespace autofill {
64
65 typedef PersonalDataManager::GUIDPair GUIDPair;
66
67 using base::TimeTicks;
68 using content::BrowserThread;
69 using content::RenderViewHost;
70 using WebKit::WebFormElement;
71
72 namespace {
73
74 // We only send a fraction of the forms to upload server.
75 // The rate for positive/negative matches potentially could be different.
76 const double kAutofillPositiveUploadRateDefaultValue = 0.20;
77 const double kAutofillNegativeUploadRateDefaultValue = 0.20;
78
79 const size_t kMaxRecentFormSignaturesToRemember = 3;
80
81 // Set a conservative upper bound on the number of forms we are willing to
82 // cache, simply to prevent unbounded memory consumption.
83 const size_t kMaxFormCacheSize = 100;
84
85 // Removes duplicate suggestions whilst preserving their original order.
86 void RemoveDuplicateSuggestions(std::vector<base::string16>* values,
87 std::vector<base::string16>* labels,
88 std::vector<base::string16>* icons,
89 std::vector<int>* unique_ids) {
90 DCHECK_EQ(values->size(), labels->size());
91 DCHECK_EQ(values->size(), icons->size());
92 DCHECK_EQ(values->size(), unique_ids->size());
93
94 std::set<std::pair<base::string16, base::string16> > seen_suggestions;
95 std::vector<base::string16> values_copy;
96 std::vector<base::string16> labels_copy;
97 std::vector<base::string16> icons_copy;
98 std::vector<int> unique_ids_copy;
99
100 for (size_t i = 0; i < values->size(); ++i) {
101 const std::pair<base::string16, base::string16> suggestion(
102 (*values)[i], (*labels)[i]);
103 if (seen_suggestions.insert(suggestion).second) {
104 values_copy.push_back((*values)[i]);
105 labels_copy.push_back((*labels)[i]);
106 icons_copy.push_back((*icons)[i]);
107 unique_ids_copy.push_back((*unique_ids)[i]);
108 }
109 }
110
111 values->swap(values_copy);
112 labels->swap(labels_copy);
113 icons->swap(icons_copy);
114 unique_ids->swap(unique_ids_copy);
115 }
116
117 // Precondition: |form_structure| and |form| should correspond to the same
118 // logical form. Returns true if any field in the given |section| within |form|
119 // is auto-filled.
120 bool SectionIsAutofilled(const FormStructure& form_structure,
121 const FormData& form,
122 const std::string& section) {
123 DCHECK_EQ(form_structure.field_count(), form.fields.size());
124 for (size_t i = 0; i < form_structure.field_count(); ++i) {
125 if (form_structure.field(i)->section() == section &&
126 form.fields[i].is_autofilled) {
127 return true;
128 }
129 }
130
131 return false;
132 }
133
134 bool FormIsHTTPS(const FormStructure& form) {
135 return form.source_url().SchemeIs(chrome::kHttpsScheme);
136 }
137
138 // Uses the existing personal data in |profiles| and |credit_cards| to determine
139 // possible field types for the |submitted_form|. This is potentially
140 // expensive -- on the order of 50ms even for a small set of |stored_data|.
141 // Hence, it should not run on the UI thread -- to avoid locking up the UI --
142 // nor on the IO thread -- to avoid blocking IPC calls.
143 void DeterminePossibleFieldTypesForUpload(
144 const std::vector<AutofillProfile>& profiles,
145 const std::vector<CreditCard>& credit_cards,
146 const std::string& app_locale,
147 FormStructure* submitted_form) {
148 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
149
150 // For each field in the |submitted_form|, extract the value. Then for each
151 // profile or credit card, identify any stored types that match the value.
152 for (size_t i = 0; i < submitted_form->field_count(); ++i) {
153 AutofillField* field = submitted_form->field(i);
154 base::string16 value = CollapseWhitespace(field->value, false);
155
156 FieldTypeSet matching_types;
157 for (std::vector<AutofillProfile>::const_iterator it = profiles.begin();
158 it != profiles.end(); ++it) {
159 it->GetMatchingTypes(value, app_locale, &matching_types);
160 }
161 for (std::vector<CreditCard>::const_iterator it = credit_cards.begin();
162 it != credit_cards.end(); ++it) {
163 it->GetMatchingTypes(value, app_locale, &matching_types);
164 }
165
166 if (matching_types.empty())
167 matching_types.insert(UNKNOWN_TYPE);
168
169 field->set_possible_types(matching_types);
170 }
171 }
172
173 // Returns true if server returned known field types to one or more fields in
174 // this form.
175 bool HasServerSpecifiedFieldTypes(const FormStructure& form_structure) {
176 for (size_t i = 0; i < form_structure.field_count(); ++i) {
177 if (form_structure.field(i)->server_type() != NO_SERVER_DATA)
178 return true;
179 }
180 return false;
181 }
182
183 } // namespace
184
185 AutofillManager::AutofillManager(
186 AutofillDriver* driver,
187 autofill::AutofillManagerDelegate* delegate,
188 const std::string& app_locale,
189 AutofillDownloadManagerState enable_download_manager)
190 : driver_(driver),
191 manager_delegate_(delegate),
192 app_locale_(app_locale),
193 personal_data_(delegate->GetPersonalDataManager()),
194 autocomplete_history_manager_(driver),
195 autocheckout_manager_(this),
196 metric_logger_(new AutofillMetrics),
197 has_logged_autofill_enabled_(false),
198 has_logged_address_suggestions_count_(false),
199 did_show_suggestions_(false),
200 user_did_type_(false),
201 user_did_autofill_(false),
202 user_did_edit_autofilled_field_(false),
203 external_delegate_(NULL),
204 test_delegate_(NULL),
205 weak_ptr_factory_(this) {
206 if (enable_download_manager == ENABLE_AUTOFILL_DOWNLOAD_MANAGER) {
207 download_manager_.reset(
208 new AutofillDownloadManager(
209 driver->GetWebContents()->GetBrowserContext(), this));
210 }
211 }
212
213 AutofillManager::~AutofillManager() {}
214
215 // static
216 void AutofillManager::RegisterUserPrefs(
217 user_prefs::PrefRegistrySyncable* registry) {
218 registry->RegisterBooleanPref(
219 prefs::kAutofillEnabled,
220 true,
221 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
222 #if defined(OS_MACOSX) || defined(OS_ANDROID)
223 registry->RegisterBooleanPref(
224 prefs::kAutofillAuxiliaryProfilesEnabled,
225 true,
226 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
227 #else
228 registry->RegisterBooleanPref(
229 prefs::kAutofillAuxiliaryProfilesEnabled,
230 false,
231 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
232 #endif
233 registry->RegisterDoublePref(
234 prefs::kAutofillPositiveUploadRate,
235 kAutofillPositiveUploadRateDefaultValue,
236 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
237 registry->RegisterDoublePref(
238 prefs::kAutofillNegativeUploadRate,
239 kAutofillNegativeUploadRateDefaultValue,
240 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
241 }
242
243 void AutofillManager::DidNavigateMainFrame(
244 const content::LoadCommittedDetails& details,
245 const content::FrameNavigateParams& params) {
246 if (details.is_navigation_to_different_page())
247 Reset();
248 }
249
250 void AutofillManager::SetExternalDelegate(AutofillExternalDelegate* delegate) {
251 // TODO(jrg): consider passing delegate into the ctor. That won't
252 // work if the delegate has a pointer to the AutofillManager, but
253 // future directions may not need such a pointer.
254 external_delegate_ = delegate;
255 autocomplete_history_manager_.SetExternalDelegate(delegate);
256 }
257
258 bool AutofillManager::IsNativeUiEnabled() {
259 return external_delegate_ != NULL;
260 }
261
262 bool AutofillManager::OnMessageReceived(const IPC::Message& message) {
263 bool handled = true;
264 IPC_BEGIN_MESSAGE_MAP(AutofillManager, message)
265 IPC_MESSAGE_HANDLER(AutofillHostMsg_FormsSeen, OnFormsSeen)
266 IPC_MESSAGE_HANDLER(AutofillHostMsg_FormSubmitted, OnFormSubmitted)
267 IPC_MESSAGE_HANDLER(AutofillHostMsg_TextFieldDidChange,
268 OnTextFieldDidChange)
269 IPC_MESSAGE_HANDLER(AutofillHostMsg_QueryFormFieldAutofill,
270 OnQueryFormFieldAutofill)
271 IPC_MESSAGE_HANDLER(AutofillHostMsg_ShowAutofillDialog,
272 OnShowAutofillDialog)
273 IPC_MESSAGE_HANDLER(AutofillHostMsg_FillAutofillFormData,
274 OnFillAutofillFormData)
275 IPC_MESSAGE_HANDLER(AutofillHostMsg_DidPreviewAutofillFormData,
276 OnDidPreviewAutofillFormData)
277 IPC_MESSAGE_HANDLER(AutofillHostMsg_DidFillAutofillFormData,
278 OnDidFillAutofillFormData)
279 IPC_MESSAGE_HANDLER(AutofillHostMsg_DidShowAutofillSuggestions,
280 OnDidShowAutofillSuggestions)
281 IPC_MESSAGE_HANDLER(AutofillHostMsg_DidEndTextFieldEditing,
282 OnDidEndTextFieldEditing)
283 IPC_MESSAGE_HANDLER(AutofillHostMsg_HideAutofillUi,
284 OnHideAutofillUi)
285 IPC_MESSAGE_HANDLER(AutofillHostMsg_AddPasswordFormMapping,
286 OnAddPasswordFormMapping)
287 IPC_MESSAGE_HANDLER(AutofillHostMsg_ShowPasswordSuggestions,
288 OnShowPasswordSuggestions)
289 IPC_MESSAGE_HANDLER(AutofillHostMsg_SetDataList,
290 OnSetDataList)
291 IPC_MESSAGE_HANDLER(AutofillHostMsg_RequestAutocomplete,
292 OnRequestAutocomplete)
293 IPC_MESSAGE_HANDLER(AutofillHostMsg_ClickFailed,
294 OnClickFailed)
295 IPC_MESSAGE_HANDLER(AutofillHostMsg_MaybeShowAutocheckoutBubble,
296 OnMaybeShowAutocheckoutBubble)
297 IPC_MESSAGE_HANDLER(AutofillHostMsg_RemoveAutocompleteEntry,
298 RemoveAutocompleteEntry)
299 IPC_MESSAGE_UNHANDLED(handled = false)
300 IPC_END_MESSAGE_MAP()
301
302 return handled;
303 }
304
305 bool AutofillManager::OnFormSubmitted(const FormData& form,
306 const TimeTicks& timestamp) {
307 // Let AutoComplete know as well.
308 autocomplete_history_manager_.OnFormSubmitted(form);
309
310 if (!IsAutofillEnabled())
311 return false;
312
313 if (driver_->GetWebContents()->GetBrowserContext()->IsOffTheRecord())
314 return false;
315
316 // Don't save data that was submitted through JavaScript.
317 if (!form.user_submitted)
318 return false;
319
320 // Grab a copy of the form data.
321 scoped_ptr<FormStructure> submitted_form(
322 new FormStructure(form, GetAutocheckoutURLPrefix()));
323
324 // Disregard forms that we wouldn't ever autofill in the first place.
325 if (!submitted_form->ShouldBeParsed(true))
326 return false;
327
328 // Ignore forms not present in our cache. These are typically forms with
329 // wonky JavaScript that also makes them not auto-fillable.
330 FormStructure* cached_submitted_form;
331 if (!FindCachedForm(form, &cached_submitted_form))
332 return false;
333
334 submitted_form->UpdateFromCache(*cached_submitted_form);
335 // Don't prompt the user to save data entered by Autocheckout.
336 if (submitted_form->IsAutofillable(true) &&
337 !submitted_form->filled_by_autocheckout())
338 ImportFormData(*submitted_form);
339
340 // Only upload server statistics and UMA metrics if at least some local data
341 // is available to use as a baseline.
342 const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles();
343 const std::vector<CreditCard*>& credit_cards =
344 personal_data_->GetCreditCards();
345 if (!profiles.empty() || !credit_cards.empty()) {
346 // Copy the profile and credit card data, so that it can be accessed on a
347 // separate thread.
348 std::vector<AutofillProfile> copied_profiles;
349 copied_profiles.reserve(profiles.size());
350 for (std::vector<AutofillProfile*>::const_iterator it = profiles.begin();
351 it != profiles.end(); ++it) {
352 copied_profiles.push_back(**it);
353 }
354
355 std::vector<CreditCard> copied_credit_cards;
356 copied_credit_cards.reserve(credit_cards.size());
357 for (std::vector<CreditCard*>::const_iterator it = credit_cards.begin();
358 it != credit_cards.end(); ++it) {
359 copied_credit_cards.push_back(**it);
360 }
361
362 // Note that ownership of |submitted_form| is passed to the second task,
363 // using |base::Owned|.
364 FormStructure* raw_submitted_form = submitted_form.get();
365 BrowserThread::GetBlockingPool()->PostTaskAndReply(
366 FROM_HERE,
367 base::Bind(&DeterminePossibleFieldTypesForUpload,
368 copied_profiles,
369 copied_credit_cards,
370 app_locale_,
371 raw_submitted_form),
372 base::Bind(&AutofillManager::UploadFormDataAsyncCallback,
373 weak_ptr_factory_.GetWeakPtr(),
374 base::Owned(submitted_form.release()),
375 forms_loaded_timestamp_,
376 initial_interaction_timestamp_,
377 timestamp));
378 }
379
380 return true;
381 }
382
383 void AutofillManager::OnFormsSeen(const std::vector<FormData>& forms,
384 const TimeTicks& timestamp,
385 autofill::FormsSeenState state) {
386 bool is_post_document_load = state == autofill::DYNAMIC_FORMS_SEEN;
387 bool has_more_forms = state == autofill::PARTIAL_FORMS_SEEN;
388 // If new forms were added via AJAX or DHML, treat as new page.
389 if (is_post_document_load)
390 Reset();
391
392 RenderViewHost* host = driver_->GetWebContents()->GetRenderViewHost();
393 if (!host)
394 return;
395
396 if (!GetAutocheckoutURLPrefix().empty()) {
397 // If whitelisted URL, fetch all the forms.
398 if (has_more_forms)
399 host->Send(new AutofillMsg_GetAllForms(host->GetRoutingID()));
400 if (!is_post_document_load) {
401 host->Send(
402 new AutofillMsg_AutocheckoutSupported(host->GetRoutingID()));
403 }
404 // Now return early, as OnFormsSeen will get called again with all forms.
405 if (has_more_forms)
406 return;
407 }
408
409 autocheckout_manager_.OnFormsSeen();
410 bool enabled = IsAutofillEnabled();
411 if (!has_logged_autofill_enabled_) {
412 metric_logger_->LogIsAutofillEnabledAtPageLoad(enabled);
413 has_logged_autofill_enabled_ = true;
414 }
415
416 if (!enabled)
417 return;
418
419 forms_loaded_timestamp_ = timestamp;
420 ParseForms(forms);
421 }
422
423 void AutofillManager::OnTextFieldDidChange(const FormData& form,
424 const FormFieldData& field,
425 const TimeTicks& timestamp) {
426 FormStructure* form_structure = NULL;
427 AutofillField* autofill_field = NULL;
428 if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
429 return;
430
431 if (!user_did_type_) {
432 user_did_type_ = true;
433 metric_logger_->LogUserHappinessMetric(AutofillMetrics::USER_DID_TYPE);
434 }
435
436 if (autofill_field->is_autofilled) {
437 autofill_field->is_autofilled = false;
438 metric_logger_->LogUserHappinessMetric(
439 AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD);
440
441 if (!user_did_edit_autofilled_field_) {
442 user_did_edit_autofilled_field_ = true;
443 metric_logger_->LogUserHappinessMetric(
444 AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD_ONCE);
445 }
446 }
447
448 UpdateInitialInteractionTimestamp(timestamp);
449 }
450
451 void AutofillManager::OnQueryFormFieldAutofill(int query_id,
452 const FormData& form,
453 const FormFieldData& field,
454 const gfx::RectF& bounding_box,
455 bool display_warning) {
456 if (autocheckout_manager_.is_autocheckout_bubble_showing())
457 return;
458
459 std::vector<base::string16> values;
460 std::vector<base::string16> labels;
461 std::vector<base::string16> icons;
462 std::vector<int> unique_ids;
463
464 if (external_delegate_) {
465 external_delegate_->OnQuery(query_id,
466 form,
467 field,
468 bounding_box,
469 display_warning);
470 }
471
472 RenderViewHost* host = NULL;
473 FormStructure* form_structure = NULL;
474 AutofillField* autofill_field = NULL;
475 if (GetHost(&host) &&
476 GetCachedFormAndField(form, field, &form_structure, &autofill_field) &&
477 // Don't send suggestions for forms that aren't auto-fillable.
478 form_structure->IsAutofillable(false)) {
479 AutofillFieldType type = autofill_field->type();
480 bool is_filling_credit_card =
481 (AutofillType(type).group() == AutofillType::CREDIT_CARD);
482 if (is_filling_credit_card) {
483 GetCreditCardSuggestions(
484 field, type, &values, &labels, &icons, &unique_ids);
485 } else {
486 GetProfileSuggestions(
487 form_structure, field, type, &values, &labels, &icons, &unique_ids);
488 }
489
490 DCHECK_EQ(values.size(), labels.size());
491 DCHECK_EQ(values.size(), icons.size());
492 DCHECK_EQ(values.size(), unique_ids.size());
493
494 if (!values.empty()) {
495 // Don't provide Autofill suggestions when Autofill is disabled, and don't
496 // provide credit card suggestions for non-HTTPS pages. However, provide a
497 // warning to the user in these cases.
498 int warning = 0;
499 if (!form_structure->IsAutofillable(true))
500 warning = IDS_AUTOFILL_WARNING_FORM_DISABLED;
501 else if (is_filling_credit_card && !FormIsHTTPS(*form_structure))
502 warning = IDS_AUTOFILL_WARNING_INSECURE_CONNECTION;
503 if (warning) {
504 values.assign(1, l10n_util::GetStringUTF16(warning));
505 labels.assign(1, base::string16());
506 icons.assign(1, base::string16());
507 unique_ids.assign(1,
508 WebKit::WebAutofillClient::MenuItemIDWarningMessage);
509 } else {
510 bool section_is_autofilled =
511 SectionIsAutofilled(*form_structure, form,
512 autofill_field->section());
513 if (section_is_autofilled) {
514 // If the relevant section is auto-filled and the renderer is querying
515 // for suggestions, then the user is editing the value of a field.
516 // In this case, mimic autocomplete: don't display labels or icons,
517 // as that information is redundant.
518 labels.assign(labels.size(), base::string16());
519 icons.assign(icons.size(), base::string16());
520 }
521
522 // When filling credit card suggestions, the values and labels are
523 // typically obfuscated, which makes detecting duplicates hard. Since
524 // duplicates only tend to be a problem when filling address forms
525 // anyway, only don't de-dup credit card suggestions.
526 if (!is_filling_credit_card)
527 RemoveDuplicateSuggestions(&values, &labels, &icons, &unique_ids);
528
529 // The first time we show suggestions on this page, log the number of
530 // suggestions shown.
531 if (!has_logged_address_suggestions_count_ && !section_is_autofilled) {
532 metric_logger_->LogAddressSuggestionsCount(values.size());
533 has_logged_address_suggestions_count_ = true;
534 }
535 }
536 }
537 }
538
539 // Add the results from AutoComplete. They come back asynchronously, so we
540 // hand off what we generated and they will send the results back to the
541 // renderer.
542 autocomplete_history_manager_.OnGetAutocompleteSuggestions(
543 query_id, field.name, field.value, values, labels, icons, unique_ids);
544 }
545
546 void AutofillManager::OnFillAutofillFormData(int query_id,
547 const FormData& form,
548 const FormFieldData& field,
549 int unique_id) {
550 RenderViewHost* host = NULL;
551 const AutofillDataModel* data_model = NULL;
552 size_t variant = 0;
553 FormStructure* form_structure = NULL;
554 AutofillField* autofill_field = NULL;
555 // NOTE: GetHost may invalidate |data_model| because it causes the
556 // PersonalDataManager to reload Mac address book entries. Thus it must
557 // come before GetProfileOrCreditCard.
558 if (!GetHost(&host) ||
559 !GetProfileOrCreditCard(unique_id, &data_model, &variant) ||
560 !GetCachedFormAndField(form, field, &form_structure, &autofill_field))
561 return;
562
563 DCHECK(host);
564 DCHECK(form_structure);
565 DCHECK(autofill_field);
566
567 FormData result = form;
568
569 // If the relevant section is auto-filled, we should fill |field| but not the
570 // rest of the form.
571 if (SectionIsAutofilled(*form_structure, form, autofill_field->section())) {
572 for (std::vector<FormFieldData>::iterator iter = result.fields.begin();
573 iter != result.fields.end(); ++iter) {
574 if ((*iter) == field) {
575 data_model->FillFormField(
576 *autofill_field, variant, app_locale_, &(*iter));
577 // Mark the cached field as autofilled, so that we can detect when a
578 // user edits an autofilled field (for metrics).
579 autofill_field->is_autofilled = true;
580 break;
581 }
582 }
583
584 host->Send(new AutofillMsg_FormDataFilled(host->GetRoutingID(), query_id,
585 result));
586 return;
587 }
588
589 // Cache the field type for the field from which the user initiated autofill.
590 FieldTypeGroup initiating_group_type =
591 AutofillType(autofill_field->type()).group();
592 DCHECK_EQ(form_structure->field_count(), form.fields.size());
593 for (size_t i = 0; i < form_structure->field_count(); ++i) {
594 if (form_structure->field(i)->section() != autofill_field->section())
595 continue;
596
597 DCHECK_EQ(*form_structure->field(i), result.fields[i]);
598
599 const AutofillField* cached_field = form_structure->field(i);
600 FieldTypeGroup field_group_type =
601 AutofillType(cached_field->type()).group();
602 if (field_group_type != AutofillType::NO_GROUP) {
603 // If the field being filled is either
604 // (a) the field that the user initiated the fill from, or
605 // (b) part of the same logical unit, e.g. name or phone number,
606 // then take the multi-profile "variant" into account.
607 // Otherwise fill with the default (zeroth) variant.
608 size_t use_variant = 0;
609 if (result.fields[i] == field ||
610 field_group_type == initiating_group_type) {
611 use_variant = variant;
612 }
613 data_model->FillFormField(*cached_field,
614 use_variant,
615 app_locale_,
616 &result.fields[i]);
617 // Mark the cached field as autofilled, so that we can detect when a user
618 // edits an autofilled field (for metrics).
619 form_structure->field(i)->is_autofilled = true;
620 }
621 }
622
623 autofilled_form_signatures_.push_front(form_structure->FormSignature());
624 // Only remember the last few forms that we've seen, both to avoid false
625 // positives and to avoid wasting memory.
626 if (autofilled_form_signatures_.size() > kMaxRecentFormSignaturesToRemember)
627 autofilled_form_signatures_.pop_back();
628
629 host->Send(new AutofillMsg_FormDataFilled(
630 host->GetRoutingID(), query_id, result));
631 }
632
633 void AutofillManager::OnShowAutofillDialog() {
634 manager_delegate_->ShowAutofillSettings();
635 }
636
637 void AutofillManager::OnDidPreviewAutofillFormData() {
638 if (test_delegate_)
639 test_delegate_->DidPreviewFormData();
640 }
641
642 void AutofillManager::OnDidFillAutofillFormData(const TimeTicks& timestamp) {
643 if (test_delegate_)
644 test_delegate_->DidFillFormData();
645
646 metric_logger_->LogUserHappinessMetric(AutofillMetrics::USER_DID_AUTOFILL);
647 if (!user_did_autofill_) {
648 user_did_autofill_ = true;
649 metric_logger_->LogUserHappinessMetric(
650 AutofillMetrics::USER_DID_AUTOFILL_ONCE);
651 }
652
653 UpdateInitialInteractionTimestamp(timestamp);
654 }
655
656 void AutofillManager::OnDidShowAutofillSuggestions(bool is_new_popup) {
657 if (test_delegate_)
658 test_delegate_->DidShowSuggestions();
659
660 if (is_new_popup) {
661 metric_logger_->LogUserHappinessMetric(AutofillMetrics::SUGGESTIONS_SHOWN);
662
663 if (!did_show_suggestions_) {
664 did_show_suggestions_ = true;
665 metric_logger_->LogUserHappinessMetric(
666 AutofillMetrics::SUGGESTIONS_SHOWN_ONCE);
667 }
668 }
669 }
670
671 void AutofillManager::OnHideAutofillUi() {
672 if (IsNativeUiEnabled())
673 manager_delegate_->HideAutofillPopup();
674 manager_delegate_->HideAutocheckoutBubble();
675 }
676
677 void AutofillManager::RemoveAutofillProfileOrCreditCard(int unique_id) {
678 const AutofillDataModel* data_model = NULL;
679 size_t variant = 0;
680 if (!GetProfileOrCreditCard(unique_id, &data_model, &variant)) {
681 NOTREACHED();
682 return;
683 }
684
685 // TODO(csharp): If we are dealing with a variant only the variant should
686 // be deleted, instead of doing nothing.
687 // http://crbug.com/124211
688 if (variant != 0)
689 return;
690
691 personal_data_->RemoveByGUID(data_model->guid());
692 }
693
694 void AutofillManager::RemoveAutocompleteEntry(const base::string16& name,
695 const base::string16& value) {
696 autocomplete_history_manager_.OnRemoveAutocompleteEntry(name, value);
697 }
698
699 content::WebContents* AutofillManager::GetWebContents() const {
700 return driver_->GetWebContents();
701 }
702
703 const std::vector<FormStructure*>& AutofillManager::GetFormStructures() {
704 return form_structures_.get();
705 }
706
707 void AutofillManager::ShowRequestAutocompleteDialog(
708 const FormData& form,
709 const GURL& source_url,
710 autofill::DialogType dialog_type,
711 const base::Callback<void(const FormStructure*,
712 const std::string&)>& callback) {
713 manager_delegate_->ShowRequestAutocompleteDialog(
714 form, source_url, dialog_type, callback);
715 }
716
717 void AutofillManager::SetTestDelegate(
718 autofill::AutofillManagerTestDelegate* delegate) {
719 test_delegate_ = delegate;
720 }
721
722 void AutofillManager::OnAddPasswordFormMapping(
723 const FormFieldData& form,
724 const PasswordFormFillData& fill_data) {
725 if (external_delegate_)
726 external_delegate_->AddPasswordFormMapping(form, fill_data);
727 }
728
729 void AutofillManager::OnShowPasswordSuggestions(
730 const FormFieldData& field,
731 const gfx::RectF& bounds,
732 const std::vector<base::string16>& suggestions) {
733 if (external_delegate_)
734 external_delegate_->OnShowPasswordSuggestions(suggestions, field, bounds);
735 }
736
737 void AutofillManager::OnSetDataList(const std::vector<base::string16>& values,
738 const std::vector<base::string16>& labels,
739 const std::vector<base::string16>& icons,
740 const std::vector<int>& unique_ids) {
741 if (labels.size() != values.size() ||
742 icons.size() != values.size() ||
743 unique_ids.size() != values.size()) {
744 return;
745 }
746 if (external_delegate_) {
747 external_delegate_->SetCurrentDataListValues(values,
748 labels,
749 icons,
750 unique_ids);
751 }
752 }
753
754 void AutofillManager::OnRequestAutocomplete(
755 const FormData& form,
756 const GURL& frame_url) {
757 if (!IsAutofillEnabled()) {
758 ReturnAutocompleteResult(WebFormElement::AutocompleteResultErrorDisabled,
759 FormData());
760 return;
761 }
762
763 base::Callback<void(const FormStructure*, const std::string&)> callback =
764 base::Bind(&AutofillManager::ReturnAutocompleteData,
765 weak_ptr_factory_.GetWeakPtr());
766 ShowRequestAutocompleteDialog(
767 form, frame_url, autofill::DIALOG_TYPE_REQUEST_AUTOCOMPLETE, callback);
768 }
769
770 void AutofillManager::ReturnAutocompleteResult(
771 WebFormElement::AutocompleteResult result, const FormData& form_data) {
772 // driver_->GetWebContents() will be NULL when the interactive autocomplete
773 // is closed due to a tab or browser window closing.
774 if (!driver_->GetWebContents())
775 return;
776
777 RenderViewHost* host = driver_->GetWebContents()->GetRenderViewHost();
778 if (!host)
779 return;
780
781 host->Send(new AutofillMsg_RequestAutocompleteResult(host->GetRoutingID(),
782 result,
783 form_data));
784 }
785
786 void AutofillManager::ReturnAutocompleteData(
787 const FormStructure* result,
788 const std::string& unused_transaction_id) {
789 if (!result) {
790 ReturnAutocompleteResult(WebFormElement::AutocompleteResultErrorCancel,
791 FormData());
792 } else {
793 ReturnAutocompleteResult(WebFormElement::AutocompleteResultSuccess,
794 result->ToFormData());
795 }
796 }
797
798 void AutofillManager::OnLoadedServerPredictions(
799 const std::string& response_xml) {
800 scoped_ptr<autofill::AutocheckoutPageMetaData> page_meta_data(
801 new autofill::AutocheckoutPageMetaData());
802
803 // Parse and store the server predictions.
804 FormStructure::ParseQueryResponse(response_xml,
805 form_structures_.get(),
806 page_meta_data.get(),
807 *metric_logger_);
808
809 if (page_meta_data->IsInAutofillableFlow()) {
810 RenderViewHost* host = driver_->GetWebContents()->GetRenderViewHost();
811 if (host)
812 host->Send(new AutofillMsg_AutocheckoutSupported(host->GetRoutingID()));
813 }
814
815 // TODO(ahutter): Remove this once Autocheckout is implemented on other
816 // platforms. See http://crbug.com/173416.
817 #if defined(TOOLKIT_VIEWS)
818 if (!GetAutocheckoutURLPrefix().empty())
819 autocheckout_manager_.OnLoadedPageMetaData(page_meta_data.Pass());
820 #endif // #if defined(TOOLKIT_VIEWS)
821
822 // If the corresponding flag is set, annotate forms with the predicted types.
823 SendAutofillTypePredictions(form_structures_.get());
824 }
825
826 void AutofillManager::OnDidEndTextFieldEditing() {
827 if (external_delegate_)
828 external_delegate_->DidEndTextFieldEditing();
829 }
830
831 void AutofillManager::OnClickFailed(autofill::AutocheckoutStatus status) {
832 autocheckout_manager_.OnClickFailed(status);
833 }
834
835 std::string AutofillManager::GetAutocheckoutURLPrefix() const {
836 if (!driver_->GetWebContents())
837 return std::string();
838
839 autofill::autocheckout::WhitelistManager* whitelist_manager =
840 manager_delegate_->GetAutocheckoutWhitelistManager();
841
842 return whitelist_manager->GetMatchedURLPrefix(
843 driver_->GetWebContents()->GetURL());
844 }
845
846 bool AutofillManager::IsAutofillEnabled() const {
847 return manager_delegate_->GetPrefs()->GetBoolean(prefs::kAutofillEnabled);
848 }
849
850 void AutofillManager::SendAutofillTypePredictions(
851 const std::vector<FormStructure*>& forms) const {
852 if (!CommandLine::ForCurrentProcess()->HasSwitch(
853 switches::kShowAutofillTypePredictions))
854 return;
855
856 RenderViewHost* host = driver_->GetWebContents()->GetRenderViewHost();
857 if (!host)
858 return;
859
860 std::vector<FormDataPredictions> type_predictions;
861 FormStructure::GetFieldTypePredictions(forms, &type_predictions);
862 host->Send(
863 new AutofillMsg_FieldTypePredictionsAvailable(host->GetRoutingID(),
864 type_predictions));
865 }
866
867 void AutofillManager::ImportFormData(const FormStructure& submitted_form) {
868 const CreditCard* imported_credit_card;
869 if (!personal_data_->ImportFormData(submitted_form, &imported_credit_card))
870 return;
871
872 // If credit card information was submitted, we need to confirm whether to
873 // save it.
874 if (imported_credit_card) {
875 manager_delegate_->ConfirmSaveCreditCard(
876 *metric_logger_,
877 *imported_credit_card,
878 base::Bind(&PersonalDataManager::SaveImportedCreditCard,
879 base::Unretained(personal_data_), *imported_credit_card));
880 }
881 }
882
883 // Note that |submitted_form| is passed as a pointer rather than as a reference
884 // so that we can get memory management right across threads. Note also that we
885 // explicitly pass in all the time stamps of interest, as the cached ones might
886 // get reset before this method executes.
887 void AutofillManager::UploadFormDataAsyncCallback(
888 const FormStructure* submitted_form,
889 const TimeTicks& load_time,
890 const TimeTicks& interaction_time,
891 const TimeTicks& submission_time) {
892 submitted_form->LogQualityMetrics(*metric_logger_,
893 load_time,
894 interaction_time,
895 submission_time);
896
897 if (submitted_form->ShouldBeCrowdsourced())
898 UploadFormData(*submitted_form);
899 }
900
901 void AutofillManager::OnMaybeShowAutocheckoutBubble(
902 const FormData& form,
903 const gfx::RectF& bounding_box) {
904 if (!IsAutofillEnabled())
905 return;
906
907 // Don't show bubble if corresponding FormStructure doesn't have anything to
908 // autofill.
909 FormStructure* cached_form;
910 if (!FindCachedForm(form, &cached_form))
911 return;
912
913 // Don't offer Autocheckout bubble if Autofill server is not aware of this
914 // form in the context of Autocheckout experiment.
915 if (!HasServerSpecifiedFieldTypes(*cached_form))
916 return;
917
918 autocheckout_manager_.MaybeShowAutocheckoutBubble(
919 form.origin,
920 form.ssl_status,
921 bounding_box);
922 }
923
924 void AutofillManager::UploadFormData(const FormStructure& submitted_form) {
925 if (!download_manager_)
926 return;
927
928 // Check if the form is among the forms that were recently auto-filled.
929 bool was_autofilled = false;
930 std::string form_signature = submitted_form.FormSignature();
931 for (std::list<std::string>::const_iterator it =
932 autofilled_form_signatures_.begin();
933 it != autofilled_form_signatures_.end() && !was_autofilled;
934 ++it) {
935 if (*it == form_signature)
936 was_autofilled = true;
937 }
938
939 FieldTypeSet non_empty_types;
940 personal_data_->GetNonEmptyTypes(&non_empty_types);
941
942 download_manager_->StartUploadRequest(submitted_form, was_autofilled,
943 non_empty_types);
944 }
945
946 void AutofillManager::Reset() {
947 form_structures_.clear();
948 has_logged_autofill_enabled_ = false;
949 has_logged_address_suggestions_count_ = false;
950 did_show_suggestions_ = false;
951 user_did_type_ = false;
952 user_did_autofill_ = false;
953 user_did_edit_autofilled_field_ = false;
954 forms_loaded_timestamp_ = TimeTicks();
955 initial_interaction_timestamp_ = TimeTicks();
956
957 if (external_delegate_)
958 external_delegate_->Reset();
959 }
960
961 AutofillManager::AutofillManager(AutofillDriver* driver,
962 autofill::AutofillManagerDelegate* delegate,
963 PersonalDataManager* personal_data)
964 : driver_(driver),
965 manager_delegate_(delegate),
966 app_locale_("en-US"),
967 personal_data_(personal_data),
968 autocomplete_history_manager_(driver),
969 autocheckout_manager_(this),
970 metric_logger_(new AutofillMetrics),
971 has_logged_autofill_enabled_(false),
972 has_logged_address_suggestions_count_(false),
973 did_show_suggestions_(false),
974 user_did_type_(false),
975 user_did_autofill_(false),
976 user_did_edit_autofilled_field_(false),
977 external_delegate_(NULL),
978 test_delegate_(NULL),
979 weak_ptr_factory_(this) {
980 DCHECK(driver_);
981 DCHECK(driver_->GetWebContents());
982 DCHECK(manager_delegate_);
983 }
984
985 void AutofillManager::set_metric_logger(const AutofillMetrics* metric_logger) {
986 metric_logger_.reset(metric_logger);
987 }
988
989 bool AutofillManager::GetHost(RenderViewHost** host) const {
990 if (!IsAutofillEnabled())
991 return false;
992
993 // No autofill data to return if the profiles are empty.
994 if (personal_data_->GetProfiles().empty() &&
995 personal_data_->GetCreditCards().empty()) {
996 return false;
997 }
998
999 *host = driver_->GetWebContents()->GetRenderViewHost();
1000 if (!*host)
1001 return false;
1002
1003 return true;
1004 }
1005
1006 bool AutofillManager::GetProfileOrCreditCard(
1007 int unique_id,
1008 const AutofillDataModel** data_model,
1009 size_t* variant) const {
1010 // Unpack the |unique_id| into component parts.
1011 GUIDPair credit_card_guid;
1012 GUIDPair profile_guid;
1013 UnpackGUIDs(unique_id, &credit_card_guid, &profile_guid);
1014 DCHECK(!base::IsValidGUID(credit_card_guid.first) ||
1015 !base::IsValidGUID(profile_guid.first));
1016
1017 // Find the profile that matches the |profile_guid|, if one is specified.
1018 // Otherwise find the credit card that matches the |credit_card_guid|,
1019 // if specified.
1020 if (base::IsValidGUID(profile_guid.first)) {
1021 *data_model = personal_data_->GetProfileByGUID(profile_guid.first);
1022 *variant = profile_guid.second;
1023 } else if (base::IsValidGUID(credit_card_guid.first)) {
1024 *data_model = personal_data_->GetCreditCardByGUID(credit_card_guid.first);
1025 *variant = credit_card_guid.second;
1026 }
1027
1028 return !!*data_model;
1029 }
1030
1031 bool AutofillManager::FindCachedForm(const FormData& form,
1032 FormStructure** form_structure) const {
1033 // Find the FormStructure that corresponds to |form|.
1034 // Scan backward through the cached |form_structures_|, as updated versions of
1035 // forms are added to the back of the list, whereas original versions of these
1036 // forms might appear toward the beginning of the list. The communication
1037 // protocol with the crowdsourcing server does not permit us to discard the
1038 // original versions of the forms.
1039 *form_structure = NULL;
1040 for (std::vector<FormStructure*>::const_reverse_iterator iter =
1041 form_structures_.rbegin();
1042 iter != form_structures_.rend(); ++iter) {
1043 if (**iter == form) {
1044 *form_structure = *iter;
1045
1046 // The same form might be cached with multiple field counts: in some
1047 // cases, non-autofillable fields are filtered out, whereas in other cases
1048 // they are not. To avoid thrashing the cache, keep scanning until we
1049 // find a cached version with the same number of fields, if there is one.
1050 if ((*iter)->field_count() == form.fields.size())
1051 break;
1052 }
1053 }
1054
1055 if (!(*form_structure))
1056 return false;
1057
1058 return true;
1059 }
1060
1061 bool AutofillManager::GetCachedFormAndField(const FormData& form,
1062 const FormFieldData& field,
1063 FormStructure** form_structure,
1064 AutofillField** autofill_field) {
1065 // Find the FormStructure that corresponds to |form|.
1066 // If we do not have this form in our cache but it is parseable, we'll add it
1067 // in the call to |UpdateCachedForm()|.
1068 if (!FindCachedForm(form, form_structure) &&
1069 !FormStructure(form, GetAutocheckoutURLPrefix()).ShouldBeParsed(false)) {
1070 return false;
1071 }
1072
1073 // Update the cached form to reflect any dynamic changes to the form data, if
1074 // necessary.
1075 if (!UpdateCachedForm(form, *form_structure, form_structure))
1076 return false;
1077
1078 // No data to return if there are no auto-fillable fields.
1079 if (!(*form_structure)->autofill_count())
1080 return false;
1081
1082 // Find the AutofillField that corresponds to |field|.
1083 *autofill_field = NULL;
1084 for (std::vector<AutofillField*>::const_iterator iter =
1085 (*form_structure)->begin();
1086 iter != (*form_structure)->end(); ++iter) {
1087 if ((**iter) == field) {
1088 *autofill_field = *iter;
1089 break;
1090 }
1091 }
1092
1093 // Even though we always update the cache, the field might not exist if the
1094 // website disables autocomplete while the user is interacting with the form.
1095 // See http://crbug.com/160476
1096 return *autofill_field != NULL;
1097 }
1098
1099 bool AutofillManager::UpdateCachedForm(const FormData& live_form,
1100 const FormStructure* cached_form,
1101 FormStructure** updated_form) {
1102 bool needs_update =
1103 (!cached_form ||
1104 live_form.fields.size() != cached_form->field_count());
1105 for (size_t i = 0; !needs_update && i < cached_form->field_count(); ++i) {
1106 needs_update = *cached_form->field(i) != live_form.fields[i];
1107 }
1108
1109 if (!needs_update)
1110 return true;
1111
1112 if (form_structures_.size() >= kMaxFormCacheSize)
1113 return false;
1114
1115 // Add the new or updated form to our cache.
1116 form_structures_.push_back(
1117 new FormStructure(live_form, GetAutocheckoutURLPrefix()));
1118 *updated_form = *form_structures_.rbegin();
1119 (*updated_form)->DetermineHeuristicTypes(*metric_logger_);
1120
1121 // If we have cached data, propagate it to the updated form.
1122 if (cached_form) {
1123 std::map<base::string16, const AutofillField*> cached_fields;
1124 for (size_t i = 0; i < cached_form->field_count(); ++i) {
1125 const AutofillField* field = cached_form->field(i);
1126 cached_fields[field->unique_name()] = field;
1127 }
1128
1129 for (size_t i = 0; i < (*updated_form)->field_count(); ++i) {
1130 AutofillField* field = (*updated_form)->field(i);
1131 std::map<base::string16, const AutofillField*>::iterator cached_field =
1132 cached_fields.find(field->unique_name());
1133 if (cached_field != cached_fields.end()) {
1134 field->set_server_type(cached_field->second->server_type());
1135 field->is_autofilled = cached_field->second->is_autofilled;
1136 }
1137 }
1138
1139 // Note: We _must not_ remove the original version of the cached form from
1140 // the list of |form_structures_|. Otherwise, we break parsing of the
1141 // crowdsourcing server's response to our query.
1142 }
1143
1144 // Annotate the updated form with its predicted types.
1145 std::vector<FormStructure*> forms(1, *updated_form);
1146 SendAutofillTypePredictions(forms);
1147
1148 return true;
1149 }
1150
1151 void AutofillManager::GetProfileSuggestions(
1152 FormStructure* form,
1153 const FormFieldData& field,
1154 AutofillFieldType type,
1155 std::vector<base::string16>* values,
1156 std::vector<base::string16>* labels,
1157 std::vector<base::string16>* icons,
1158 std::vector<int>* unique_ids) const {
1159 std::vector<AutofillFieldType> field_types(form->field_count());
1160 for (size_t i = 0; i < form->field_count(); ++i) {
1161 field_types[i] = form->field(i)->type();
1162 }
1163 std::vector<GUIDPair> guid_pairs;
1164
1165 personal_data_->GetProfileSuggestions(
1166 type, field.value, field.is_autofilled, field_types,
1167 values, labels, icons, &guid_pairs);
1168
1169 for (size_t i = 0; i < guid_pairs.size(); ++i) {
1170 unique_ids->push_back(PackGUIDs(GUIDPair(std::string(), 0),
1171 guid_pairs[i]));
1172 }
1173 }
1174
1175 void AutofillManager::GetCreditCardSuggestions(
1176 const FormFieldData& field,
1177 AutofillFieldType type,
1178 std::vector<base::string16>* values,
1179 std::vector<base::string16>* labels,
1180 std::vector<base::string16>* icons,
1181 std::vector<int>* unique_ids) const {
1182 std::vector<GUIDPair> guid_pairs;
1183 personal_data_->GetCreditCardSuggestions(
1184 type, field.value, values, labels, icons, &guid_pairs);
1185
1186 for (size_t i = 0; i < guid_pairs.size(); ++i) {
1187 unique_ids->push_back(PackGUIDs(guid_pairs[i], GUIDPair(std::string(), 0)));
1188 }
1189 }
1190
1191 void AutofillManager::ParseForms(const std::vector<FormData>& forms) {
1192 std::vector<FormStructure*> non_queryable_forms;
1193 std::string autocheckout_url_prefix = GetAutocheckoutURLPrefix();
1194 for (std::vector<FormData>::const_iterator iter = forms.begin();
1195 iter != forms.end(); ++iter) {
1196 scoped_ptr<FormStructure> form_structure(
1197 new FormStructure(*iter, autocheckout_url_prefix));
1198 if (!form_structure->ShouldBeParsed(false))
1199 continue;
1200
1201 form_structure->DetermineHeuristicTypes(*metric_logger_);
1202
1203 // Set aside forms with method GET or author-specified types, so that they
1204 // are not included in the query to the server.
1205 if (form_structure->ShouldBeCrowdsourced())
1206 form_structures_.push_back(form_structure.release());
1207 else
1208 non_queryable_forms.push_back(form_structure.release());
1209 }
1210
1211 if (form_structures_.empty()) {
1212 // Call OnLoadedPageMetaData with no page metadata immediately if there is
1213 // no form in the page. This give |autocheckout_manager| a chance to
1214 // terminate Autocheckout and send Autocheckout status.
1215 autocheckout_manager_.OnLoadedPageMetaData(
1216 scoped_ptr<autofill::AutocheckoutPageMetaData>());
1217 } else if (download_manager_) {
1218 // Query the server if we have at least one of the forms were parsed.
1219 download_manager_->StartQueryRequest(form_structures_.get(),
1220 *metric_logger_);
1221 }
1222
1223 for (std::vector<FormStructure*>::const_iterator iter =
1224 non_queryable_forms.begin();
1225 iter != non_queryable_forms.end(); ++iter) {
1226 form_structures_.push_back(*iter);
1227 }
1228
1229 if (!form_structures_.empty())
1230 metric_logger_->LogUserHappinessMetric(AutofillMetrics::FORMS_LOADED);
1231
1232 // For the |non_queryable_forms|, we have all the field type info we're ever
1233 // going to get about them. For the other forms, we'll wait until we get a
1234 // response from the server.
1235 SendAutofillTypePredictions(non_queryable_forms);
1236 }
1237
1238 int AutofillManager::GUIDToID(const GUIDPair& guid) const {
1239 if (!base::IsValidGUID(guid.first))
1240 return 0;
1241
1242 std::map<GUIDPair, int>::const_iterator iter = guid_id_map_.find(guid);
1243 if (iter == guid_id_map_.end()) {
1244 int id = guid_id_map_.size() + 1;
1245 guid_id_map_[guid] = id;
1246 id_guid_map_[id] = guid;
1247 return id;
1248 } else {
1249 return iter->second;
1250 }
1251 }
1252
1253 const GUIDPair AutofillManager::IDToGUID(int id) const {
1254 if (id == 0)
1255 return GUIDPair(std::string(), 0);
1256
1257 std::map<int, GUIDPair>::const_iterator iter = id_guid_map_.find(id);
1258 if (iter == id_guid_map_.end()) {
1259 NOTREACHED();
1260 return GUIDPair(std::string(), 0);
1261 }
1262
1263 return iter->second;
1264 }
1265
1266 // When sending IDs (across processes) to the renderer we pack credit card and
1267 // profile IDs into a single integer. Credit card IDs are sent in the high
1268 // word and profile IDs are sent in the low word.
1269 int AutofillManager::PackGUIDs(const GUIDPair& cc_guid,
1270 const GUIDPair& profile_guid) const {
1271 int cc_id = GUIDToID(cc_guid);
1272 int profile_id = GUIDToID(profile_guid);
1273
1274 DCHECK(cc_id <= std::numeric_limits<unsigned short>::max());
1275 DCHECK(profile_id <= std::numeric_limits<unsigned short>::max());
1276
1277 return cc_id << std::numeric_limits<unsigned short>::digits | profile_id;
1278 }
1279
1280 // When receiving IDs (across processes) from the renderer we unpack credit card
1281 // and profile IDs from a single integer. Credit card IDs are stored in the
1282 // high word and profile IDs are stored in the low word.
1283 void AutofillManager::UnpackGUIDs(int id,
1284 GUIDPair* cc_guid,
1285 GUIDPair* profile_guid) const {
1286 int cc_id = id >> std::numeric_limits<unsigned short>::digits &
1287 std::numeric_limits<unsigned short>::max();
1288 int profile_id = id & std::numeric_limits<unsigned short>::max();
1289
1290 *cc_guid = IDToGUID(cc_id);
1291 *profile_guid = IDToGUID(profile_id);
1292 }
1293
1294 void AutofillManager::UpdateInitialInteractionTimestamp(
1295 const TimeTicks& interaction_timestamp) {
1296 if (initial_interaction_timestamp_.is_null() ||
1297 interaction_timestamp < initial_interaction_timestamp_) {
1298 initial_interaction_timestamp_ = interaction_timestamp;
1299 }
1300 }
1301
1302 } // namespace autofill
OLDNEW
« no previous file with comments | « components/autofill/browser/autofill_manager.h ('k') | components/autofill/browser/autofill_manager_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698