| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "components/autofill/core/browser/autofill_manager.h" | 5 #include "components/autofill/core/browser/autofill_manager.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <limits> | 10 #include <limits> |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 autofill_field->Type().GetStorableType() != CREDIT_CARD_NUMBER) { | 219 autofill_field->Type().GetStorableType() != CREDIT_CARD_NUMBER) { |
| 220 return false; | 220 return false; |
| 221 } | 221 } |
| 222 | 222 |
| 223 static const int kShowScanCreditCardMaxValueLength = 6; | 223 static const int kShowScanCreditCardMaxValueLength = 6; |
| 224 return field.value.size() <= kShowScanCreditCardMaxValueLength && | 224 return field.value.size() <= kShowScanCreditCardMaxValueLength && |
| 225 base::ContainsOnlyChars(CreditCard::StripSeparators(field.value), | 225 base::ContainsOnlyChars(CreditCard::StripSeparators(field.value), |
| 226 base::ASCIIToUTF16("0123456789")); | 226 base::ASCIIToUTF16("0123456789")); |
| 227 } | 227 } |
| 228 | 228 |
| 229 void AutofillManager::OnFormsSeen(const std::vector<FormData>& forms, |
| 230 const TimeTicks& timestamp) { |
| 231 if (!IsValidFormDataVector(forms)) |
| 232 return; |
| 233 |
| 234 if (!driver_->RendererIsAvailable()) |
| 235 return; |
| 236 |
| 237 bool enabled = IsAutofillEnabled(); |
| 238 if (!has_logged_autofill_enabled_) { |
| 239 AutofillMetrics::LogIsAutofillEnabledAtPageLoad(enabled); |
| 240 has_logged_autofill_enabled_ = true; |
| 241 } |
| 242 |
| 243 if (!enabled) |
| 244 return; |
| 245 |
| 246 for (const FormData& form : forms) { |
| 247 forms_loaded_timestamps_[form] = timestamp; |
| 248 } |
| 249 |
| 250 ParseForms(forms); |
| 251 } |
| 252 |
| 229 bool AutofillManager::OnWillSubmitForm(const FormData& form, | 253 bool AutofillManager::OnWillSubmitForm(const FormData& form, |
| 230 const TimeTicks& timestamp) { | 254 const TimeTicks& timestamp) { |
| 231 if (!IsValidFormData(form)) | 255 if (!IsValidFormData(form)) |
| 232 return false; | 256 return false; |
| 233 | 257 |
| 234 // We will always give Autocomplete a chance to save the data. | 258 // We will always give Autocomplete a chance to save the data. |
| 235 scoped_ptr<FormStructure> submitted_form = ValidateSubmittedForm(form); | 259 scoped_ptr<FormStructure> submitted_form = ValidateSubmittedForm(form); |
| 236 if (!submitted_form) { | 260 if (!submitted_form) { |
| 237 autocomplete_history_manager_->OnWillSubmitForm(form); | 261 autocomplete_history_manager_->OnWillSubmitForm(form); |
| 238 return false; | 262 return false; |
| 239 } | 263 } |
| 240 | 264 |
| 241 // However, if Autofill has recognized a field as CVC, that shouldn't be | 265 // However, if Autofill has recognized a field as CVC, that shouldn't be |
| 242 // saved. | 266 // saved. |
| 243 FormData form_for_autocomplete = submitted_form->ToFormData(); | 267 FormData form_for_autocomplete = submitted_form->ToFormData(); |
| 244 for (size_t i = 0; i < submitted_form->field_count(); ++i) { | 268 for (size_t i = 0; i < submitted_form->field_count(); ++i) { |
| 245 if (submitted_form->field(i)->Type().GetStorableType() == | 269 if (submitted_form->field(i)->Type().GetStorableType() == |
| 246 CREDIT_CARD_VERIFICATION_CODE) { | 270 CREDIT_CARD_VERIFICATION_CODE) { |
| 247 form_for_autocomplete.fields[i].should_autocomplete = false; | 271 form_for_autocomplete.fields[i].should_autocomplete = false; |
| 248 } | 272 } |
| 249 } | 273 } |
| 250 autocomplete_history_manager_->OnWillSubmitForm(form_for_autocomplete); | 274 autocomplete_history_manager_->OnWillSubmitForm(form_for_autocomplete); |
| 251 | 275 |
| 252 address_form_event_logger_->OnWillSubmitForm(); | 276 address_form_event_logger_->OnWillSubmitForm(); |
| 253 credit_card_form_event_logger_->OnWillSubmitForm(); | 277 credit_card_form_event_logger_->OnWillSubmitForm(); |
| 254 | 278 |
| 279 StartUploadProcess(std::move(submitted_form), timestamp, true); |
| 280 |
| 281 return true; |
| 282 } |
| 283 |
| 284 bool AutofillManager::OnFormSubmitted(const FormData& form) { |
| 285 if (!IsValidFormData(form)) |
| 286 return false; |
| 287 |
| 288 // We will always give Autocomplete a chance to save the data. |
| 289 scoped_ptr<FormStructure> submitted_form = ValidateSubmittedForm(form); |
| 290 if (!submitted_form) { |
| 291 return false; |
| 292 } |
| 293 |
| 294 address_form_event_logger_->OnFormSubmitted(); |
| 295 credit_card_form_event_logger_->OnFormSubmitted(); |
| 296 |
| 297 // Update Personal Data with the form's submitted data. |
| 298 if (submitted_form->IsAutofillable()) |
| 299 ImportFormData(*submitted_form); |
| 300 |
| 301 recently_unmasked_cards_.clear(); |
| 302 |
| 303 return true; |
| 304 } |
| 305 |
| 306 void AutofillManager::StartUploadProcess( |
| 307 scoped_ptr<FormStructure> form_structure, |
| 308 const TimeTicks& timestamp, |
| 309 bool observed_submission) { |
| 255 // Only upload server statistics and UMA metrics if at least some local data | 310 // Only upload server statistics and UMA metrics if at least some local data |
| 256 // is available to use as a baseline. | 311 // is available to use as a baseline. |
| 257 const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles(); | 312 const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles(); |
| 258 if (submitted_form->IsAutofillable()) { | 313 if (observed_submission && form_structure->IsAutofillable()) { |
| 314 // TODO(mathp): provide metrics for non-submission uploads. |
| 259 AutofillMetrics::LogNumberOfProfilesAtAutofillableFormSubmission( | 315 AutofillMetrics::LogNumberOfProfilesAtAutofillableFormSubmission( |
| 260 personal_data_->GetProfiles().size()); | 316 personal_data_->GetProfiles().size()); |
| 261 } | 317 } |
| 262 const std::vector<CreditCard*>& credit_cards = | 318 const std::vector<CreditCard*>& credit_cards = |
| 263 personal_data_->GetCreditCards(); | 319 personal_data_->GetCreditCards(); |
| 264 if (!profiles.empty() || !credit_cards.empty()) { | 320 if (!profiles.empty() || !credit_cards.empty()) { |
| 265 // Copy the profile and credit card data, so that it can be accessed on a | 321 // Copy the profile and credit card data, so that it can be accessed on a |
| 266 // separate thread. | 322 // separate thread. |
| 267 std::vector<AutofillProfile> copied_profiles; | 323 std::vector<AutofillProfile> copied_profiles; |
| 268 copied_profiles.reserve(profiles.size()); | 324 copied_profiles.reserve(profiles.size()); |
| 269 for (const AutofillProfile* profile : profiles) | 325 for (const AutofillProfile* profile : profiles) |
| 270 copied_profiles.push_back(*profile); | 326 copied_profiles.push_back(*profile); |
| 271 | 327 |
| 272 std::vector<CreditCard> copied_credit_cards; | 328 std::vector<CreditCard> copied_credit_cards; |
| 273 copied_credit_cards.reserve(credit_cards.size()); | 329 copied_credit_cards.reserve(credit_cards.size()); |
| 274 for (const CreditCard* card : credit_cards) | 330 for (const CreditCard* card : credit_cards) |
| 275 copied_credit_cards.push_back(*card); | 331 copied_credit_cards.push_back(*card); |
| 276 | 332 |
| 277 // Note that ownership of |submitted_form| is passed to the second task, | 333 // Note that ownership of |form_structure| is passed to the second task, |
| 278 // using |base::Owned|. | 334 // using |base::Owned|. |
| 279 FormStructure* raw_submitted_form = submitted_form.get(); | 335 FormStructure* raw_form = form_structure.get(); |
| 336 TimeTicks loaded_timestamp = |
| 337 forms_loaded_timestamps_[raw_form->ToFormData()]; |
| 280 driver_->GetBlockingPool()->PostTaskAndReply( | 338 driver_->GetBlockingPool()->PostTaskAndReply( |
| 281 FROM_HERE, | 339 FROM_HERE, |
| 282 base::Bind(&DeterminePossibleFieldTypesForUpload, | 340 base::Bind(&DeterminePossibleFieldTypesForUpload, copied_profiles, |
| 283 copied_profiles, | 341 copied_credit_cards, app_locale_, raw_form), |
| 284 copied_credit_cards, | |
| 285 app_locale_, | |
| 286 raw_submitted_form), | |
| 287 base::Bind(&AutofillManager::UploadFormDataAsyncCallback, | 342 base::Bind(&AutofillManager::UploadFormDataAsyncCallback, |
| 288 weak_ptr_factory_.GetWeakPtr(), | 343 weak_ptr_factory_.GetWeakPtr(), |
| 289 base::Owned(submitted_form.release()), | 344 base::Owned(form_structure.release()), loaded_timestamp, |
| 290 forms_loaded_timestamps_[form], | 345 initial_interaction_timestamp_, timestamp, |
| 291 initial_interaction_timestamp_, | 346 observed_submission)); |
| 292 timestamp)); | |
| 293 } | 347 } |
| 294 | |
| 295 return true; | |
| 296 } | 348 } |
| 297 | 349 |
| 298 bool AutofillManager::OnFormSubmitted(const FormData& form) { | 350 void AutofillManager::UpdatePendingForm(const FormData& form) { |
| 299 if (!IsValidFormData(form)) | 351 // Process the current pending form if different than supplied |form|. |
| 300 return false; | 352 if (pending_form_data_ && !pending_form_data_->SameFormAs(form)) { |
| 301 | 353 ProcessPendingFormForUpload(); |
| 302 // We will always give Autocomplete a chance to save the data. | |
| 303 scoped_ptr<FormStructure> submitted_form = ValidateSubmittedForm(form); | |
| 304 if (!submitted_form) { | |
| 305 return false; | |
| 306 } | 354 } |
| 307 | 355 // A new pending form is assigned. |
| 308 address_form_event_logger_->OnFormSubmitted(); | 356 pending_form_data_.reset(new FormData(form)); |
| 309 credit_card_form_event_logger_->OnFormSubmitted(); | |
| 310 | |
| 311 // Update Personal Data with the form's submitted data. | |
| 312 if (submitted_form->IsAutofillable()) | |
| 313 ImportFormData(*submitted_form); | |
| 314 | |
| 315 recently_unmasked_cards_.clear(); | |
| 316 | |
| 317 return true; | |
| 318 } | 357 } |
| 319 | 358 |
| 320 void AutofillManager::OnFormsSeen(const std::vector<FormData>& forms, | 359 void AutofillManager::ProcessPendingFormForUpload() { |
| 321 const TimeTicks& timestamp) { | 360 if (!pending_form_data_) |
| 322 if (!IsValidFormDataVector(forms)) | |
| 323 return; | 361 return; |
| 324 | 362 |
| 325 if (!driver_->RendererIsAvailable()) | 363 // We copy |pending_form_data_| to a new FormStructure to be consumed by the |
| 326 return; | 364 // upload process and reset |pending_form_data_|. |
| 365 scoped_ptr<FormStructure> upload_form(new FormStructure(*pending_form_data_)); |
| 366 pending_form_data_.reset(); |
| 327 | 367 |
| 328 bool enabled = IsAutofillEnabled(); | 368 StartUploadProcess(std::move(upload_form), base::TimeTicks::Now(), false); |
| 329 if (!has_logged_autofill_enabled_) { | |
| 330 AutofillMetrics::LogIsAutofillEnabledAtPageLoad(enabled); | |
| 331 has_logged_autofill_enabled_ = true; | |
| 332 } | |
| 333 | |
| 334 if (!enabled) | |
| 335 return; | |
| 336 | |
| 337 for (size_t i = 0; i < forms.size(); ++i) { | |
| 338 forms_loaded_timestamps_[forms[i]] = timestamp; | |
| 339 } | |
| 340 | |
| 341 ParseForms(forms); | |
| 342 } | 369 } |
| 343 | 370 |
| 344 void AutofillManager::OnTextFieldDidChange(const FormData& form, | 371 void AutofillManager::OnTextFieldDidChange(const FormData& form, |
| 345 const FormFieldData& field, | 372 const FormFieldData& field, |
| 346 const TimeTicks& timestamp) { | 373 const TimeTicks& timestamp) { |
| 347 if (!IsValidFormData(form) || !IsValidFormFieldData(field)) | 374 if (!IsValidFormData(form) || !IsValidFormFieldData(field)) |
| 348 return; | 375 return; |
| 349 | 376 |
| 350 FormStructure* form_structure = NULL; | 377 FormStructure* form_structure = NULL; |
| 351 AutofillField* autofill_field = NULL; | 378 AutofillField* autofill_field = NULL; |
| 352 if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field)) | 379 if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field)) |
| 353 return; | 380 return; |
| 354 | 381 |
| 382 UpdatePendingForm(form); |
| 383 |
| 355 if (!user_did_type_) { | 384 if (!user_did_type_) { |
| 356 user_did_type_ = true; | 385 user_did_type_ = true; |
| 357 AutofillMetrics::LogUserHappinessMetric(AutofillMetrics::USER_DID_TYPE); | 386 AutofillMetrics::LogUserHappinessMetric(AutofillMetrics::USER_DID_TYPE); |
| 358 } | 387 } |
| 359 | 388 |
| 360 if (autofill_field->is_autofilled) { | 389 if (autofill_field->is_autofilled) { |
| 361 autofill_field->is_autofilled = false; | 390 autofill_field->is_autofilled = false; |
| 362 autofill_field->set_previously_autofilled(true); | 391 autofill_field->set_previously_autofilled(true); |
| 363 AutofillMetrics::LogUserHappinessMetric( | 392 AutofillMetrics::LogUserHappinessMetric( |
| 364 AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD); | 393 AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD); |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 const CreditCard& credit_card) { | 606 const CreditCard& credit_card) { |
| 578 if (!IsValidFormData(form) || !IsValidFormFieldData(field) || | 607 if (!IsValidFormData(form) || !IsValidFormFieldData(field) || |
| 579 !driver_->RendererIsAvailable()) { | 608 !driver_->RendererIsAvailable()) { |
| 580 return; | 609 return; |
| 581 } | 610 } |
| 582 | 611 |
| 583 FillOrPreviewDataModelForm(AutofillDriver::FORM_DATA_ACTION_FILL, query_id, | 612 FillOrPreviewDataModelForm(AutofillDriver::FORM_DATA_ACTION_FILL, query_id, |
| 584 form, field, credit_card, true); | 613 form, field, credit_card, true); |
| 585 } | 614 } |
| 586 | 615 |
| 616 void AutofillManager::OnFocusNoLongerOnForm() { |
| 617 ProcessPendingFormForUpload(); |
| 618 } |
| 619 |
| 587 void AutofillManager::OnDidPreviewAutofillFormData() { | 620 void AutofillManager::OnDidPreviewAutofillFormData() { |
| 588 if (test_delegate_) | 621 if (test_delegate_) |
| 589 test_delegate_->DidPreviewFormData(); | 622 test_delegate_->DidPreviewFormData(); |
| 590 } | 623 } |
| 591 | 624 |
| 592 void AutofillManager::OnDidFillAutofillFormData(const TimeTicks& timestamp) { | 625 void AutofillManager::OnDidFillAutofillFormData(const FormData& form, |
| 626 const TimeTicks& timestamp) { |
| 593 if (test_delegate_) | 627 if (test_delegate_) |
| 594 test_delegate_->DidFillFormData(); | 628 test_delegate_->DidFillFormData(); |
| 595 | 629 |
| 630 UpdatePendingForm(form); |
| 631 |
| 596 AutofillMetrics::LogUserHappinessMetric(AutofillMetrics::USER_DID_AUTOFILL); | 632 AutofillMetrics::LogUserHappinessMetric(AutofillMetrics::USER_DID_AUTOFILL); |
| 597 if (!user_did_autofill_) { | 633 if (!user_did_autofill_) { |
| 598 user_did_autofill_ = true; | 634 user_did_autofill_ = true; |
| 599 AutofillMetrics::LogUserHappinessMetric( | 635 AutofillMetrics::LogUserHappinessMetric( |
| 600 AutofillMetrics::USER_DID_AUTOFILL_ONCE); | 636 AutofillMetrics::USER_DID_AUTOFILL_ONCE); |
| 601 } | 637 } |
| 602 | 638 |
| 603 UpdateInitialInteractionTimestamp(timestamp); | 639 UpdateInitialInteractionTimestamp(timestamp); |
| 604 } | 640 } |
| 605 | 641 |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 997 } | 1033 } |
| 998 | 1034 |
| 999 // Note that |submitted_form| is passed as a pointer rather than as a reference | 1035 // Note that |submitted_form| is passed as a pointer rather than as a reference |
| 1000 // so that we can get memory management right across threads. Note also that we | 1036 // so that we can get memory management right across threads. Note also that we |
| 1001 // explicitly pass in all the time stamps of interest, as the cached ones might | 1037 // explicitly pass in all the time stamps of interest, as the cached ones might |
| 1002 // get reset before this method executes. | 1038 // get reset before this method executes. |
| 1003 void AutofillManager::UploadFormDataAsyncCallback( | 1039 void AutofillManager::UploadFormDataAsyncCallback( |
| 1004 const FormStructure* submitted_form, | 1040 const FormStructure* submitted_form, |
| 1005 const TimeTicks& load_time, | 1041 const TimeTicks& load_time, |
| 1006 const TimeTicks& interaction_time, | 1042 const TimeTicks& interaction_time, |
| 1007 const TimeTicks& submission_time) { | 1043 const TimeTicks& submission_time, |
| 1008 submitted_form->LogQualityMetrics( | 1044 bool observed_submission) { |
| 1009 load_time, interaction_time, submission_time, client_->GetRapporService(), | 1045 // TODO(mathp): Have different set of metrics for non-submission uploads. |
| 1010 did_show_suggestions_); | 1046 if (observed_submission) { |
| 1047 submitted_form->LogQualityMetrics( |
| 1048 load_time, interaction_time, submission_time, |
| 1049 client_->GetRapporService(), did_show_suggestions_); |
| 1050 } |
| 1011 | 1051 |
| 1052 // TODO(crbug.com/555015): Differentiate non-submission uploads in the |
| 1053 // uploaded payload. |
| 1012 if (submitted_form->ShouldBeCrowdsourced()) | 1054 if (submitted_form->ShouldBeCrowdsourced()) |
| 1013 UploadFormData(*submitted_form); | 1055 UploadFormData(*submitted_form); |
| 1014 } | 1056 } |
| 1015 | 1057 |
| 1016 void AutofillManager::UploadFormData(const FormStructure& submitted_form) { | 1058 void AutofillManager::UploadFormData(const FormStructure& submitted_form) { |
| 1017 if (!download_manager_) | 1059 if (!download_manager_) |
| 1018 return; | 1060 return; |
| 1019 | 1061 |
| 1020 // Check if the form is among the forms that were recently auto-filled. | 1062 // Check if the form is among the forms that were recently auto-filled. |
| 1021 bool was_autofilled = false; | 1063 bool was_autofilled = false; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1042 address_form_event_logger_.reset( | 1084 address_form_event_logger_.reset( |
| 1043 new AutofillMetrics::FormEventLogger(false /* is_for_credit_card */)); | 1085 new AutofillMetrics::FormEventLogger(false /* is_for_credit_card */)); |
| 1044 credit_card_form_event_logger_.reset( | 1086 credit_card_form_event_logger_.reset( |
| 1045 new AutofillMetrics::FormEventLogger(true /* is_for_credit_card */)); | 1087 new AutofillMetrics::FormEventLogger(true /* is_for_credit_card */)); |
| 1046 has_logged_autofill_enabled_ = false; | 1088 has_logged_autofill_enabled_ = false; |
| 1047 has_logged_address_suggestions_count_ = false; | 1089 has_logged_address_suggestions_count_ = false; |
| 1048 did_show_suggestions_ = false; | 1090 did_show_suggestions_ = false; |
| 1049 user_did_type_ = false; | 1091 user_did_type_ = false; |
| 1050 user_did_autofill_ = false; | 1092 user_did_autofill_ = false; |
| 1051 user_did_edit_autofilled_field_ = false; | 1093 user_did_edit_autofilled_field_ = false; |
| 1094 ProcessPendingFormForUpload(); |
| 1095 DCHECK(!pending_form_data_); |
| 1052 unmask_request_ = payments::PaymentsClient::UnmaskRequestDetails(); | 1096 unmask_request_ = payments::PaymentsClient::UnmaskRequestDetails(); |
| 1053 unmasking_query_id_ = -1; | 1097 unmasking_query_id_ = -1; |
| 1054 unmasking_form_ = FormData(); | 1098 unmasking_form_ = FormData(); |
| 1055 unmasking_field_ = FormFieldData(); | 1099 unmasking_field_ = FormFieldData(); |
| 1056 forms_loaded_timestamps_.clear(); | 1100 forms_loaded_timestamps_.clear(); |
| 1057 initial_interaction_timestamp_ = TimeTicks(); | 1101 initial_interaction_timestamp_ = TimeTicks(); |
| 1058 external_delegate_->Reset(); | 1102 external_delegate_->Reset(); |
| 1059 } | 1103 } |
| 1060 | 1104 |
| 1061 AutofillManager::AutofillManager(AutofillDriver* driver, | 1105 AutofillManager::AutofillManager(AutofillDriver* driver, |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1484 | 1528 |
| 1485 void AutofillManager::ParseForms(const std::vector<FormData>& forms) { | 1529 void AutofillManager::ParseForms(const std::vector<FormData>& forms) { |
| 1486 if (forms.empty()) | 1530 if (forms.empty()) |
| 1487 return; | 1531 return; |
| 1488 | 1532 |
| 1489 std::vector<FormStructure*> non_queryable_forms; | 1533 std::vector<FormStructure*> non_queryable_forms; |
| 1490 std::vector<FormStructure*> queryable_forms; | 1534 std::vector<FormStructure*> queryable_forms; |
| 1491 for (const FormData& form : forms) { | 1535 for (const FormData& form : forms) { |
| 1492 scoped_ptr<FormStructure> form_structure(new FormStructure(form)); | 1536 scoped_ptr<FormStructure> form_structure(new FormStructure(form)); |
| 1493 form_structure->ParseFieldTypesFromAutocompleteAttributes(); | 1537 form_structure->ParseFieldTypesFromAutocompleteAttributes(); |
| 1494 | |
| 1495 if (!form_structure->ShouldBeParsed()) | 1538 if (!form_structure->ShouldBeParsed()) |
| 1496 continue; | 1539 continue; |
| 1497 | 1540 |
| 1498 form_structure->DetermineHeuristicTypes(); | 1541 form_structure->DetermineHeuristicTypes(); |
| 1499 | 1542 |
| 1500 // Ownership is transferred to |form_structures_| which maintains it until | 1543 // Ownership is transferred to |form_structures_| which maintains it until |
| 1501 // the manager is Reset() or destroyed. It is safe to use references below | 1544 // the manager is Reset() or destroyed. It is safe to use references below |
| 1502 // as long as receivers don't take ownership. | 1545 // as long as receivers don't take ownership. |
| 1503 form_structures_.push_back(form_structure.Pass()); | 1546 form_structures_.push_back(form_structure.Pass()); |
| 1504 | 1547 |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1631 if (i > 0) | 1674 if (i > 0) |
| 1632 fputs("Next oldest form:\n", file); | 1675 fputs("Next oldest form:\n", file); |
| 1633 } | 1676 } |
| 1634 fputs("\n", file); | 1677 fputs("\n", file); |
| 1635 | 1678 |
| 1636 fclose(file); | 1679 fclose(file); |
| 1637 } | 1680 } |
| 1638 #endif // ENABLE_FORM_DEBUG_DUMP | 1681 #endif // ENABLE_FORM_DEBUG_DUMP |
| 1639 | 1682 |
| 1640 } // namespace autofill | 1683 } // namespace autofill |
| OLD | NEW |