OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/autofill/autofill_manager.h" | 5 #include "chrome/browser/autofill/autofill_manager.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <limits> | 9 #include <limits> |
10 #include <map> | 10 #include <map> |
11 #include <set> | 11 #include <set> |
12 #include <utility> | 12 #include <utility> |
13 | 13 |
| 14 #include "base/bind.h" |
14 #include "base/command_line.h" | 15 #include "base/command_line.h" |
15 #include "base/logging.h" | 16 #include "base/logging.h" |
16 #include "base/string16.h" | 17 #include "base/string16.h" |
17 #include "base/string_util.h" | 18 #include "base/string_util.h" |
18 #include "base/utf_string_conversions.h" | 19 #include "base/utf_string_conversions.h" |
19 #include "chrome/browser/autocomplete_history_manager.h" | 20 #include "chrome/browser/autocomplete_history_manager.h" |
20 #include "chrome/browser/autofill/autofill_cc_infobar_delegate.h" | 21 #include "chrome/browser/autofill/autofill_cc_infobar_delegate.h" |
21 #include "chrome/browser/autofill/autofill_feedback_infobar_delegate.h" | 22 #include "chrome/browser/autofill/autofill_feedback_infobar_delegate.h" |
22 #include "chrome/browser/autofill/autofill_external_delegate.h" | 23 #include "chrome/browser/autofill/autofill_external_delegate.h" |
23 #include "chrome/browser/autofill/autofill_field.h" | 24 #include "chrome/browser/autofill/autofill_field.h" |
(...skipping 13 matching lines...) Expand all Loading... |
37 #include "chrome/browser/ui/browser.h" | 38 #include "chrome/browser/ui/browser.h" |
38 #include "chrome/browser/ui/browser_list.h" | 39 #include "chrome/browser/ui/browser_list.h" |
39 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 40 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
40 #include "chrome/common/autofill_messages.h" | 41 #include "chrome/common/autofill_messages.h" |
41 #include "chrome/common/chrome_notification_types.h" | 42 #include "chrome/common/chrome_notification_types.h" |
42 #include "chrome/common/chrome_switches.h" | 43 #include "chrome/common/chrome_switches.h" |
43 #include "chrome/common/guid.h" | 44 #include "chrome/common/guid.h" |
44 #include "chrome/common/pref_names.h" | 45 #include "chrome/common/pref_names.h" |
45 #include "chrome/common/url_constants.h" | 46 #include "chrome/common/url_constants.h" |
46 #include "content/browser/renderer_host/render_view_host.h" | 47 #include "content/browser/renderer_host/render_view_host.h" |
| 48 #include "content/public/browser/browser_thread.h" |
47 #include "content/public/browser/notification_service.h" | 49 #include "content/public/browser/notification_service.h" |
48 #include "content/public/browser/notification_source.h" | 50 #include "content/public/browser/notification_source.h" |
49 #include "googleurl/src/gurl.h" | 51 #include "googleurl/src/gurl.h" |
50 #include "grit/generated_resources.h" | 52 #include "grit/generated_resources.h" |
51 #include "ipc/ipc_message_macros.h" | 53 #include "ipc/ipc_message_macros.h" |
52 #include "ui/base/l10n/l10n_util.h" | 54 #include "ui/base/l10n/l10n_util.h" |
53 #include "webkit/glue/form_data.h" | 55 #include "webkit/glue/form_data.h" |
54 #include "webkit/glue/form_data_predictions.h" | 56 #include "webkit/glue/form_data_predictions.h" |
55 #include "webkit/glue/form_field.h" | 57 #include "webkit/glue/form_field.h" |
56 | 58 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 } | 122 } |
121 } | 123 } |
122 | 124 |
123 return false; | 125 return false; |
124 } | 126 } |
125 | 127 |
126 bool FormIsHTTPS(const FormStructure& form) { | 128 bool FormIsHTTPS(const FormStructure& form) { |
127 return form.source_url().SchemeIs(chrome::kHttpsScheme); | 129 return form.source_url().SchemeIs(chrome::kHttpsScheme); |
128 } | 130 } |
129 | 131 |
| 132 // Uses the existing personal data in |profiles| and |credit_cards| to determine |
| 133 // possible field types for the |submitted_form|. This is potentially |
| 134 // expensive -- on the order of 50ms even for a small set of |stored_data|. |
| 135 // Hence, it should not run on the UI thread -- to avoid locking up the UI -- |
| 136 // nor on the IO thread -- to avoid blocking IPC calls. |
| 137 void DeterminePossibleFieldTypesForUpload( |
| 138 const std::vector<AutofillProfile>& profiles, |
| 139 const std::vector<CreditCard>& credit_cards, |
| 140 FormStructure* submitted_form) { |
| 141 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 142 |
| 143 // For each field in the |submitted_form|, extract the value. Then for each |
| 144 // profile or credit card, identify any stored types that match the value. |
| 145 for (size_t i = 0; i < submitted_form->field_count(); ++i) { |
| 146 AutofillField* field = submitted_form->field(i); |
| 147 string16 value = CollapseWhitespace(field->value, false); |
| 148 |
| 149 FieldTypeSet matching_types; |
| 150 for (std::vector<AutofillProfile>::const_iterator it = profiles.begin(); |
| 151 it != profiles.end(); ++it) { |
| 152 it->GetMatchingTypes(value, &matching_types); |
| 153 } |
| 154 for (std::vector<CreditCard>::const_iterator it = credit_cards.begin(); |
| 155 it != credit_cards.end(); ++it) { |
| 156 it->GetMatchingTypes(value, &matching_types); |
| 157 } |
| 158 |
| 159 if (matching_types.empty()) |
| 160 matching_types.insert(UNKNOWN_TYPE); |
| 161 |
| 162 field->set_possible_types(matching_types); |
| 163 } |
| 164 } |
| 165 |
130 // Check for unidentified forms among those with the most query or upload | 166 // Check for unidentified forms among those with the most query or upload |
131 // requests. If found, present an infobar prompting the user to send Google | 167 // requests. If found, present an infobar prompting the user to send Google |
132 // Feedback identifying these forms. Only executes if the appropriate flag is | 168 // Feedback identifying these forms. Only executes if the appropriate flag is |
133 // set in about:flags. | 169 // set in about:flags. |
134 const char* kPopularFormSignatures[] = { | 170 const char* kPopularFormSignatures[] = { |
135 "10135289994685082173", | 171 "10135289994685082173", |
136 "7883844738557049416", | 172 "7883844738557049416", |
137 "14651966297402649464", | 173 "14651966297402649464", |
138 "17177862793067325164", | 174 "17177862793067325164", |
139 "15222964025577790589", | 175 "15222964025577790589", |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 download_manager_(tab_contents->profile(), this), | 248 download_manager_(tab_contents->profile(), this), |
213 disable_download_manager_requests_(false), | 249 disable_download_manager_requests_(false), |
214 metric_logger_(new AutofillMetrics), | 250 metric_logger_(new AutofillMetrics), |
215 has_logged_autofill_enabled_(false), | 251 has_logged_autofill_enabled_(false), |
216 has_logged_address_suggestions_count_(false), | 252 has_logged_address_suggestions_count_(false), |
217 did_show_suggestions_(false), | 253 did_show_suggestions_(false), |
218 user_did_type_(false), | 254 user_did_type_(false), |
219 user_did_autofill_(false), | 255 user_did_autofill_(false), |
220 user_did_edit_autofilled_field_(false), | 256 user_did_edit_autofilled_field_(false), |
221 external_delegate_(NULL) { | 257 external_delegate_(NULL) { |
222 DCHECK(tab_contents); | |
223 | |
224 // |personal_data_| is NULL when using TestTabContents. | 258 // |personal_data_| is NULL when using TestTabContents. |
225 personal_data_ = PersonalDataManagerFactory::GetForProfile( | 259 personal_data_ = PersonalDataManagerFactory::GetForProfile( |
226 tab_contents->profile()->GetOriginalProfile()); | 260 tab_contents->profile()->GetOriginalProfile()); |
227 } | 261 } |
228 | 262 |
229 AutofillManager::~AutofillManager() { | 263 AutofillManager::~AutofillManager() { |
230 } | 264 } |
231 | 265 |
232 // static | 266 // static |
233 void AutofillManager::RegisterUserPrefs(PrefService* prefs) { | 267 void AutofillManager::RegisterUserPrefs(PrefService* prefs) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 IPC_MESSAGE_HANDLER(AutofillHostMsg_DidFillAutofillFormData, | 309 IPC_MESSAGE_HANDLER(AutofillHostMsg_DidFillAutofillFormData, |
276 OnDidFillAutofillFormData) | 310 OnDidFillAutofillFormData) |
277 IPC_MESSAGE_HANDLER(AutofillHostMsg_DidShowAutofillSuggestions, | 311 IPC_MESSAGE_HANDLER(AutofillHostMsg_DidShowAutofillSuggestions, |
278 OnDidShowAutofillSuggestions) | 312 OnDidShowAutofillSuggestions) |
279 IPC_MESSAGE_UNHANDLED(handled = false) | 313 IPC_MESSAGE_UNHANDLED(handled = false) |
280 IPC_END_MESSAGE_MAP() | 314 IPC_END_MESSAGE_MAP() |
281 | 315 |
282 return handled; | 316 return handled; |
283 } | 317 } |
284 | 318 |
285 void AutofillManager::OnFormSubmitted(const FormData& form, | 319 bool AutofillManager::OnFormSubmitted(const FormData& form, |
286 const TimeTicks& timestamp) { | 320 const TimeTicks& timestamp) { |
287 // Let AutoComplete know as well. | 321 // Let AutoComplete know as well. |
288 tab_contents_wrapper_->autocomplete_history_manager()->OnFormSubmitted(form); | 322 tab_contents_wrapper_->autocomplete_history_manager()->OnFormSubmitted(form); |
289 | 323 |
290 if (!IsAutofillEnabled()) | 324 if (!IsAutofillEnabled()) |
291 return; | 325 return false; |
292 | 326 |
293 if (tab_contents()->browser_context()->IsOffTheRecord()) | 327 if (tab_contents()->browser_context()->IsOffTheRecord()) |
294 return; | 328 return false; |
295 | 329 |
296 // Don't save data that was submitted through JavaScript. | 330 // Don't save data that was submitted through JavaScript. |
297 if (!form.user_submitted) | 331 if (!form.user_submitted) |
298 return; | 332 return false; |
299 | 333 |
300 // Grab a copy of the form data. | 334 // Grab a copy of the form data. |
301 FormStructure submitted_form(form); | 335 scoped_ptr<FormStructure> submitted_form(new FormStructure(form)); |
302 | 336 |
303 // Disregard forms that we wouldn't ever autofill in the first place. | 337 // Disregard forms that we wouldn't ever autofill in the first place. |
304 if (!submitted_form.ShouldBeParsed(true)) | 338 if (!submitted_form->ShouldBeParsed(true)) |
305 return; | 339 return false; |
306 | 340 |
307 // Ignore forms not present in our cache. These are typically forms with | 341 // Ignore forms not present in our cache. These are typically forms with |
308 // wonky JavaScript that also makes them not auto-fillable. | 342 // wonky JavaScript that also makes them not auto-fillable. |
309 FormStructure* cached_submitted_form; | 343 FormStructure* cached_submitted_form; |
310 if (!FindCachedForm(form, &cached_submitted_form)) | 344 if (!FindCachedForm(form, &cached_submitted_form)) |
311 return; | 345 return false; |
312 submitted_form.UpdateFromCache(*cached_submitted_form); | 346 |
| 347 submitted_form->UpdateFromCache(*cached_submitted_form); |
| 348 if (submitted_form->IsAutofillable(true)) |
| 349 ImportFormData(*submitted_form); |
313 | 350 |
314 // Only upload server statistics and UMA metrics if at least some local data | 351 // Only upload server statistics and UMA metrics if at least some local data |
315 // is available to use as a baseline. | 352 // is available to use as a baseline. |
316 if (!personal_data_->profiles().empty() || | 353 const std::vector<AutofillProfile*>& profiles = personal_data_->profiles(); |
317 !personal_data_->credit_cards().empty()) { | 354 const std::vector<CreditCard*>& credit_cards = personal_data_->credit_cards(); |
318 DeterminePossibleFieldTypesForUpload(&submitted_form); | 355 if (!profiles.empty() || !credit_cards.empty()) { |
319 submitted_form.LogQualityMetrics(*metric_logger_, | 356 // Copy the profile and credit card data, so that it can be accessed on a |
320 forms_loaded_timestamp_, | 357 // separate thread. |
321 initial_interaction_timestamp_, | 358 std::vector<AutofillProfile> copied_profiles; |
322 timestamp); | 359 copied_profiles.reserve(profiles.size()); |
| 360 for (std::vector<AutofillProfile*>::const_iterator it = profiles.begin(); |
| 361 it != profiles.end(); ++it) { |
| 362 copied_profiles.push_back(**it); |
| 363 } |
323 | 364 |
324 if (submitted_form.ShouldBeCrowdsourced()) | 365 std::vector<CreditCard> copied_credit_cards; |
325 UploadFormData(submitted_form); | 366 copied_credit_cards.reserve(credit_cards.size()); |
| 367 for (std::vector<CreditCard*>::const_iterator it = credit_cards.begin(); |
| 368 it != credit_cards.end(); ++it) { |
| 369 copied_credit_cards.push_back(**it); |
| 370 } |
| 371 |
| 372 // TODO(isherman): Ideally, we should not be using the FILE thread here. |
| 373 // Per jar@, this is a good compromise for now, as we don't currently have a |
| 374 // broad consensus on how to support such one-off background tasks. |
| 375 |
| 376 // Note that ownership of |submitted_form| is passed to the second task, |
| 377 // using |base::Owned|. |
| 378 FormStructure* raw_submitted_form = submitted_form.get(); |
| 379 BrowserThread::PostTaskAndReply( |
| 380 BrowserThread::FILE, FROM_HERE, |
| 381 base::Bind(&DeterminePossibleFieldTypesForUpload, |
| 382 copied_profiles, |
| 383 copied_credit_cards, |
| 384 raw_submitted_form), |
| 385 base::Bind(&AutofillManager::UploadFormDataAsyncCallback, |
| 386 this, |
| 387 base::Owned(submitted_form.release()), |
| 388 forms_loaded_timestamp_, |
| 389 initial_interaction_timestamp_, |
| 390 timestamp)); |
326 } | 391 } |
327 | 392 |
328 if (!submitted_form.IsAutofillable(true)) | 393 return true; |
329 return; | |
330 | |
331 ImportFormData(submitted_form); | |
332 } | 394 } |
333 | 395 |
334 void AutofillManager::OnFormsSeen(const std::vector<FormData>& forms, | 396 void AutofillManager::OnFormsSeen(const std::vector<FormData>& forms, |
335 const TimeTicks& timestamp) { | 397 const TimeTicks& timestamp) { |
336 bool enabled = IsAutofillEnabled(); | 398 bool enabled = IsAutofillEnabled(); |
337 if (!has_logged_autofill_enabled_) { | 399 if (!has_logged_autofill_enabled_) { |
338 metric_logger_->LogIsAutofillEnabledAtPageLoad(enabled); | 400 metric_logger_->LogIsAutofillEnabledAtPageLoad(enabled); |
339 has_logged_autofill_enabled_ = true; | 401 has_logged_autofill_enabled_ = true; |
340 } | 402 } |
341 | 403 |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
620 // If the corresponding flag is set, annotate forms with the predicted types. | 682 // If the corresponding flag is set, annotate forms with the predicted types. |
621 SendAutofillTypePredictions(form_structures_.get()); | 683 SendAutofillTypePredictions(form_structures_.get()); |
622 } | 684 } |
623 | 685 |
624 bool AutofillManager::IsAutofillEnabled() const { | 686 bool AutofillManager::IsAutofillEnabled() const { |
625 Profile* profile = Profile::FromBrowserContext( | 687 Profile* profile = Profile::FromBrowserContext( |
626 const_cast<AutofillManager*>(this)->tab_contents()->browser_context()); | 688 const_cast<AutofillManager*>(this)->tab_contents()->browser_context()); |
627 return profile->GetPrefs()->GetBoolean(prefs::kAutofillEnabled); | 689 return profile->GetPrefs()->GetBoolean(prefs::kAutofillEnabled); |
628 } | 690 } |
629 | 691 |
630 void AutofillManager::DeterminePossibleFieldTypesForUpload( | |
631 FormStructure* submitted_form) { | |
632 // Combine all the profiles and credit cards stored in |personal_data_| into | |
633 // one vector for ease of iteration. | |
634 const std::vector<AutofillProfile*>& profiles = personal_data_->profiles(); | |
635 const std::vector<CreditCard*>& credit_cards = personal_data_->credit_cards(); | |
636 std::vector<FormGroup*> stored_data; | |
637 stored_data.insert(stored_data.end(), profiles.begin(), profiles.end()); | |
638 stored_data.insert(stored_data.end(), credit_cards.begin(), | |
639 credit_cards.end()); | |
640 | |
641 // For each field in the |submitted_form|, extract the value. Then for each | |
642 // profile or credit card, identify any stored types that match the value. | |
643 for (size_t i = 0; i < submitted_form->field_count(); i++) { | |
644 AutofillField* field = submitted_form->field(i); | |
645 string16 value = CollapseWhitespace(field->value, false); | |
646 FieldTypeSet matching_types; | |
647 for (std::vector<FormGroup*>::const_iterator it = stored_data.begin(); | |
648 it != stored_data.end(); ++it) { | |
649 (*it)->GetMatchingTypes(value, &matching_types); | |
650 } | |
651 | |
652 if (matching_types.empty()) | |
653 matching_types.insert(UNKNOWN_TYPE); | |
654 | |
655 field->set_possible_types(matching_types); | |
656 } | |
657 } | |
658 | |
659 void AutofillManager::SendAutofillTypePredictions( | 692 void AutofillManager::SendAutofillTypePredictions( |
660 const std::vector<FormStructure*>& forms) const { | 693 const std::vector<FormStructure*>& forms) const { |
661 if (!CommandLine::ForCurrentProcess()->HasSwitch( | 694 if (!CommandLine::ForCurrentProcess()->HasSwitch( |
662 switches::kShowAutofillTypePredictions)) | 695 switches::kShowAutofillTypePredictions)) |
663 return; | 696 return; |
664 | 697 |
665 RenderViewHost* host = tab_contents()->render_view_host(); | 698 RenderViewHost* host = tab_contents()->render_view_host(); |
666 if (!host) | 699 if (!host) |
667 return; | 700 return; |
668 | 701 |
(...skipping 15 matching lines...) Expand all Loading... |
684 InfoBarTabHelper* infobar_helper = | 717 InfoBarTabHelper* infobar_helper = |
685 tab_contents_wrapper_->infobar_tab_helper(); | 718 tab_contents_wrapper_->infobar_tab_helper(); |
686 infobar_helper->AddInfoBar( | 719 infobar_helper->AddInfoBar( |
687 new AutofillCCInfoBarDelegate(infobar_helper, | 720 new AutofillCCInfoBarDelegate(infobar_helper, |
688 scoped_credit_card.release(), | 721 scoped_credit_card.release(), |
689 personal_data_, | 722 personal_data_, |
690 metric_logger_.get())); | 723 metric_logger_.get())); |
691 } | 724 } |
692 } | 725 } |
693 | 726 |
| 727 // Note that |submitted_form| is passed as a pointer rather than as a reference |
| 728 // so that we can get memory management right across threads. Note also that we |
| 729 // explicitly pass in all the time stamps of interest, as the cached ones might |
| 730 // get reset before this method executes. |
| 731 void AutofillManager::UploadFormDataAsyncCallback( |
| 732 const FormStructure* submitted_form, |
| 733 const TimeTicks& load_time, |
| 734 const TimeTicks& interaction_time, |
| 735 const TimeTicks& submission_time) { |
| 736 submitted_form->LogQualityMetrics(*metric_logger_, |
| 737 load_time, |
| 738 interaction_time, |
| 739 submission_time); |
| 740 |
| 741 if (submitted_form->ShouldBeCrowdsourced()) |
| 742 UploadFormData(*submitted_form); |
| 743 } |
| 744 |
694 void AutofillManager::UploadFormData(const FormStructure& submitted_form) { | 745 void AutofillManager::UploadFormData(const FormStructure& submitted_form) { |
695 if (disable_download_manager_requests_) | 746 if (disable_download_manager_requests_) |
696 return; | 747 return; |
697 | 748 |
698 // Check if the form is among the forms that were recently auto-filled. | 749 // Check if the form is among the forms that were recently auto-filled. |
699 bool was_autofilled = false; | 750 bool was_autofilled = false; |
700 std::string form_signature = submitted_form.FormSignature(); | 751 std::string form_signature = submitted_form.FormSignature(); |
701 for (std::list<std::string>::const_iterator it = | 752 for (std::list<std::string>::const_iterator it = |
702 autofilled_form_signatures_.begin(); | 753 autofilled_form_signatures_.begin(); |
703 it != autofilled_form_signatures_.end() && !was_autofilled; | 754 it != autofilled_form_signatures_.end() && !was_autofilled; |
(...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1225 *profile_guid = IDToGUID(profile_id); | 1276 *profile_guid = IDToGUID(profile_id); |
1226 } | 1277 } |
1227 | 1278 |
1228 void AutofillManager::UpdateInitialInteractionTimestamp( | 1279 void AutofillManager::UpdateInitialInteractionTimestamp( |
1229 const TimeTicks& interaction_timestamp) { | 1280 const TimeTicks& interaction_timestamp) { |
1230 if (initial_interaction_timestamp_.is_null() || | 1281 if (initial_interaction_timestamp_.is_null() || |
1231 interaction_timestamp < initial_interaction_timestamp_) { | 1282 interaction_timestamp < initial_interaction_timestamp_) { |
1232 initial_interaction_timestamp_ = interaction_timestamp; | 1283 initial_interaction_timestamp_ = interaction_timestamp; |
1233 } | 1284 } |
1234 } | 1285 } |
OLD | NEW |