autofill_manager.cc revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1// Copyright (c) 2010 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 "chrome/browser/autofill/autofill_manager.h" 6 7#include <string> 8 9#include "base/basictypes.h" 10#include "base/string16.h" 11#include "chrome/browser/autofill/autofill_dialog.h" 12#include "chrome/browser/autofill/autofill_cc_infobar_delegate.h" 13#include "chrome/browser/autofill/form_structure.h" 14#include "chrome/browser/pref_service.h" 15#include "chrome/browser/profile.h" 16#include "chrome/browser/renderer_host/render_view_host.h" 17#include "chrome/browser/tab_contents/tab_contents.h" 18#include "chrome/common/chrome_switches.h" 19#include "chrome/common/pref_names.h" 20#include "chrome/common/url_constants.h" 21#include "webkit/glue/form_data.h" 22#include "webkit/glue/form_field.h" 23 24using webkit_glue::FormData; 25using webkit_glue::FormField; 26 27namespace { 28 29// We only send a fraction of the forms to upload server. 30// The rate for positive/negative matches potentially could be different. 31const double kAutoFillPositiveUploadRateDefaultValue = 0.01; 32const double kAutoFillNegativeUploadRateDefaultValue = 0.01; 33 34// Size and offset of the prefix and suffix portions of phone numbers. 35const int kAutoFillPhoneNumberPrefixOffset = 0; 36const int kAutoFillPhoneNumberPrefixCount = 3; 37const int kAutoFillPhoneNumberSuffixOffset = 3; 38const int kAutoFillPhoneNumberSuffixCount = 4; 39 40const string16::value_type kLabelSeparator[] = {';',' ',0}; 41 42// Removes duplicate elements whilst preserving original order of |elements| and 43// |unique_ids|. 44void RemoveDuplicateElements( 45 std::vector<string16>* elements, std::vector<int>* unique_ids) { 46 std::vector<string16> copy; 47 for (size_t i = 0; i < elements->size(); ++i) { 48 const string16& element = (*elements)[i]; 49 50 bool unique = true; 51 for (std::vector<string16>::const_iterator copy_iter = copy.begin(); 52 copy_iter != copy.end(); ++copy_iter) { 53 if (element == *copy_iter) { 54 unique = false; 55 break; 56 } 57 } 58 59 if (unique) 60 copy.push_back(element); 61 else 62 unique_ids->erase(unique_ids->begin() + i); 63 } 64 65 elements->assign(copy.begin(), copy.end()); 66} 67 68bool FormIsHTTPS(FormStructure* form) { 69 return form->ConvertToFormData().origin.SchemeIs(chrome::kHttpsScheme); 70} 71 72} // namespace 73 74// TODO(jhawkins): Maybe this should be in a grd file? 75const char* kAutoFillLearnMoreUrl = 76 "http://www.google.com/support/chrome/bin/answer.py?answer=142893"; 77 78AutoFillManager::AutoFillManager(TabContents* tab_contents) 79 : tab_contents_(tab_contents), 80 personal_data_(NULL), 81 download_manager_(tab_contents_->profile()) { 82 DCHECK(tab_contents); 83 84 // |personal_data_| is NULL when using TestTabContents. 85 personal_data_ = 86 tab_contents_->profile()->GetOriginalProfile()->GetPersonalDataManager(); 87 download_manager_.SetObserver(this); 88} 89 90AutoFillManager::~AutoFillManager() { 91 download_manager_.SetObserver(NULL); 92} 93 94// static 95void AutoFillManager::RegisterBrowserPrefs(PrefService* prefs) { 96 prefs->RegisterDictionaryPref(prefs::kAutoFillDialogPlacement); 97} 98 99// static 100void AutoFillManager::RegisterUserPrefs(PrefService* prefs) { 101 prefs->RegisterBooleanPref(prefs::kAutoFillEnabled, true); 102#if defined(OS_MACOSX) 103 prefs->RegisterBooleanPref(prefs::kAutoFillAuxiliaryProfilesEnabled, true); 104#else 105 prefs->RegisterBooleanPref(prefs::kAutoFillAuxiliaryProfilesEnabled, false); 106#endif 107 prefs->RegisterRealPref(prefs::kAutoFillPositiveUploadRate, 108 kAutoFillPositiveUploadRateDefaultValue); 109 prefs->RegisterRealPref(prefs::kAutoFillNegativeUploadRate, 110 kAutoFillNegativeUploadRateDefaultValue); 111} 112 113void AutoFillManager::FormSubmitted(const FormData& form) { 114 if (!IsAutoFillEnabled()) 115 return; 116 117 if (tab_contents_->profile()->IsOffTheRecord()) 118 return; 119 120 // Grab a copy of the form data. 121 upload_form_structure_.reset(new FormStructure(form)); 122 123 if (!upload_form_structure_->IsAutoFillable()) 124 return; 125 126 // Determine the possible field types and upload the form structure to the 127 // PersonalDataManager. 128 DeterminePossibleFieldTypes(upload_form_structure_.get()); 129 HandleSubmit(); 130} 131 132void AutoFillManager::FormsSeen(const std::vector<FormData>& forms) { 133 if (!IsAutoFillEnabled()) 134 return; 135 136 // No profiles or credit cards, no need to parse the forms. 137 if (personal_data_->profiles().empty() && 138 personal_data_->credit_cards().empty()) 139 return; 140 141 ParseForms(forms); 142} 143 144bool AutoFillManager::GetAutoFillSuggestions(int query_id, 145 bool form_autofilled, 146 const FormField& field) { 147 if (!IsAutoFillEnabled()) 148 return false; 149 150 RenderViewHost* host = tab_contents_->render_view_host(); 151 if (!host) 152 return false; 153 154 if (personal_data_->profiles().empty() && 155 personal_data_->credit_cards().empty()) 156 return false; 157 158 // Loops through the cached FormStructures looking for the FormStructure that 159 // contains |field| and the associated AutoFillFieldType. 160 FormStructure* form = NULL; 161 AutoFillField* autofill_field = NULL; 162 for (std::vector<FormStructure*>::iterator form_iter = 163 form_structures_.begin(); 164 form_iter != form_structures_.end(); ++form_iter) { 165 form = *form_iter; 166 167 // Don't send suggestions for forms that aren't auto-fillable. 168 if (!form->IsAutoFillable()) 169 continue; 170 171 for (std::vector<AutoFillField*>::const_iterator iter = form->begin(); 172 iter != form->end(); ++iter) { 173 // The field list is terminated with a NULL AutoFillField, so don't try to 174 // dereference it. 175 if (!*iter) 176 break; 177 178 if ((**iter) == field) { 179 autofill_field = *iter; 180 break; 181 } 182 } 183 } 184 185 if (autofill_field == NULL) 186 return false; 187 188 std::vector<string16> values; 189 std::vector<string16> labels; 190 std::vector<int> unique_ids; 191 AutoFillType type(autofill_field->type()); 192 193 // If this form is non-HTTPS, treat billing address fields as regular address 194 // fields. 195 bool handle_billing = FormIsHTTPS(form); 196 197 if (type.group() == AutoFillType::CREDIT_CARD) 198 GetCreditCardSuggestions(form, field, type, &values, &labels, &unique_ids); 199 else if (type.group() == AutoFillType::ADDRESS_BILLING) 200 GetBillingProfileSuggestions( 201 form, field, type, &values, &labels, &unique_ids); 202 else 203 GetProfileSuggestions( 204 form, field, type, handle_billing, &values, &labels, &unique_ids); 205 206 DCHECK_EQ(values.size(), labels.size()); 207 DCHECK_EQ(values.size(), unique_ids.size()); 208 209 // No suggestions. 210 if (values.empty()) 211 return false; 212 213 // If the form is auto-filled and the renderer is querying for suggestions, 214 // then the user is editing the value of a field. In this case, don't display 215 // labels, as that information is redundant. In addition, remove duplicate 216 // values. 217 if (form_autofilled) { 218 RemoveDuplicateElements(&values, &unique_ids); 219 labels.resize(values.size()); 220 221 for (size_t i = 0; i < labels.size(); ++i) 222 labels[i] = string16(); 223 } 224 225 host->AutoFillSuggestionsReturned(query_id, values, labels, unique_ids); 226 return true; 227} 228 229// TODO(jhawkins): Remove the |value| parameter. 230bool AutoFillManager::FillAutoFillFormData(int query_id, 231 const FormData& form, 232 const string16& value, 233 const string16& label, 234 int unique_id) { 235 if (!IsAutoFillEnabled()) 236 return false; 237 238 RenderViewHost* host = tab_contents_->render_view_host(); 239 if (!host) 240 return false; 241 242 const std::vector<AutoFillProfile*>& profiles = personal_data_->profiles(); 243 const std::vector<CreditCard*>& credit_cards = personal_data_->credit_cards(); 244 245 // No data to return if the profiles are empty. 246 if (profiles.empty() && credit_cards.empty()) 247 return false; 248 249 // Find the FormStructure that corresponds to |form|. 250 FormData result = form; 251 FormStructure* form_structure = NULL; 252 for (std::vector<FormStructure*>::const_iterator iter = 253 form_structures_.begin(); 254 iter != form_structures_.end(); ++iter) { 255 if (**iter == form) { 256 form_structure = *iter; 257 break; 258 } 259 } 260 261 if (!form_structure) 262 return false; 263 264 // No data to return if there are no auto-fillable fields. 265 if (!form_structure->autofill_count()) 266 return false; 267 268 // |cc_digits| will contain the last four digits of a credit card number only 269 // if the form has billing fields. 270 string16 cc_digits; 271 272 // If the form has billing fields, |label| will contain at least one "; " 273 // followed by the last four digits of a credit card number. 274 if (form_structure->HasBillingFields()) { 275 // We must search for the last "; " as it's possible the profile label 276 // proper can contain this sequence of characters. 277 size_t index = label.find_last_of(kLabelSeparator); 278 if (index != string16::npos) { 279 size_t cc_index = index + 1; 280 cc_digits = label.substr(cc_index); 281 } 282 } 283 284 // Find the profile that matches the |unique_id|. 285 const AutoFillProfile* profile = NULL; 286 for (std::vector<AutoFillProfile*>::const_iterator iter = profiles.begin(); 287 iter != profiles.end(); ++iter) { 288 if ((*iter)->unique_id() == unique_id) { 289 profile = *iter; 290 } 291 } 292 293 // Don't look for a matching credit card if we fully-matched the profile using 294 // the entire label. 295 const CreditCard* credit_card = NULL; 296 if (!cc_digits.empty()) { 297 // Find the credit card that matches the |cc_label|. 298 for (std::vector<CreditCard*>::const_iterator iter = credit_cards.begin(); 299 iter != credit_cards.end(); ++iter) { 300 if ((*iter)->LastFourDigits() == cc_digits) { 301 credit_card = *iter; 302 break; 303 } 304 } 305 } 306 307 if (!profile && !credit_card) 308 return false; 309 310 // The list of fields in |form_structure| and |result.fields| often match 311 // directly and we can fill these corresponding fields; however, when the 312 // |form_structure| and |result.fields| do not match directly we search 313 // ahead in the |form_structure| for the matching field. 314 // See unit tests: AutoFillManagerTest.FormChangesRemoveField and 315 // AutoFillManagerTest.FormChangesAddField for usage. 316 for (size_t i = 0, j = 0; 317 i < form_structure->field_count() && j < result.fields.size(); 318 j++) { 319 size_t k = i; 320 321 // Search forward in the |form_structure| for a corresponding field. 322 while (k < form_structure->field_count() && 323 *form_structure->field(k) != result.fields[j]) { 324 k++; 325 } 326 327 // If we've found a match then fill the |result| field with the found 328 // field in the |form_structure|. 329 if (k >= form_structure->field_count()) 330 continue; 331 332 const AutoFillField* field = form_structure->field(k); 333 AutoFillType autofill_type(field->type()); 334 if (credit_card && 335 autofill_type.group() == AutoFillType::CREDIT_CARD) { 336 result.fields[i].set_value( 337 credit_card->GetFieldText(autofill_type)); 338 } else if (credit_card && 339 autofill_type.group() == AutoFillType::ADDRESS_BILLING) { 340 FillBillingFormField(credit_card, autofill_type, &result.fields[j]); 341 } else if (profile) { 342 FillFormField(profile, autofill_type, &result.fields[j]); 343 } 344 345 // We found a matching field in the |form_structure| so we 346 // proceed to the next |result| field, and the next |form_structure|. 347 ++i; 348 } 349 350 host->AutoFillFormDataFilled(query_id, result); 351 return true; 352} 353 354void AutoFillManager::ShowAutoFillDialog() { 355 ::ShowAutoFillDialog(tab_contents_->GetContentNativeView(), 356 personal_data_, 357 tab_contents_->profile()->GetOriginalProfile()); 358} 359 360void AutoFillManager::Reset() { 361 upload_form_structure_.reset(); 362 form_structures_.reset(); 363} 364 365void AutoFillManager::OnLoadedAutoFillHeuristics( 366 const std::string& heuristic_xml) { 367 // TODO(jhawkins): Store |upload_required| in the AutoFillManager. 368 UploadRequired upload_required; 369 FormStructure::ParseQueryResponse(heuristic_xml, 370 form_structures_.get(), 371 &upload_required); 372} 373 374void AutoFillManager::OnUploadedAutoFillHeuristics( 375 const std::string& form_signature) { 376} 377 378void AutoFillManager::OnHeuristicsRequestError( 379 const std::string& form_signature, 380 AutoFillDownloadManager::AutoFillRequestType request_type, 381 int http_error) { 382} 383 384bool AutoFillManager::IsAutoFillEnabled() const { 385 PrefService* prefs = tab_contents_->profile()->GetPrefs(); 386 387 // Migrate obsolete AutoFill pref. 388 if (prefs->FindPreference(prefs::kFormAutofillEnabled)) { 389 bool enabled = prefs->GetBoolean(prefs::kFormAutofillEnabled); 390 prefs->ClearPref(prefs::kFormAutofillEnabled); 391 prefs->SetBoolean(prefs::kAutoFillEnabled, enabled); 392 return enabled; 393 } 394 395 return prefs->GetBoolean(prefs::kAutoFillEnabled); 396} 397 398void AutoFillManager::DeterminePossibleFieldTypes( 399 FormStructure* form_structure) { 400 for (size_t i = 0; i < form_structure->field_count(); i++) { 401 const AutoFillField* field = form_structure->field(i); 402 FieldTypeSet field_types; 403 personal_data_->GetPossibleFieldTypes(field->value(), &field_types); 404 form_structure->set_possible_types(i, field_types); 405 } 406} 407 408void AutoFillManager::HandleSubmit() { 409 // If there wasn't enough data to import then we don't want to send an upload 410 // to the server. 411 // TODO(jhawkins): Import form data from |form_structures_|. That will 412 // require querying the FormManager for updated field values. 413 std::vector<FormStructure*> import; 414 import.push_back(upload_form_structure_.get()); 415 if (!personal_data_->ImportFormData(import, this)) 416 return; 417 418 // Did we get credit card info? 419 AutoFillProfile* profile; 420 CreditCard* credit_card; 421 personal_data_->GetImportedFormData(&profile, &credit_card); 422 423 if (credit_card) { 424 cc_infobar_.reset(new AutoFillCCInfoBarDelegate(tab_contents_, this)); 425 } else { 426 UploadFormData(); 427 } 428} 429 430void AutoFillManager::UploadFormData() { 431 // TODO(georgey): enable upload request when we make sure that our data is in 432 // line with toolbar data: 433 // download_manager_.StartUploadRequest(upload_form_structure_, 434 // form_is_autofilled); 435} 436 437void AutoFillManager::OnInfoBarClosed(bool should_save) { 438 if (should_save) 439 personal_data_->SaveImportedCreditCard(); 440 UploadFormData(); 441} 442 443AutoFillManager::AutoFillManager() 444 : tab_contents_(NULL), 445 personal_data_(NULL), 446 download_manager_(NULL) { 447} 448 449AutoFillManager::AutoFillManager(TabContents* tab_contents, 450 PersonalDataManager* personal_data) 451 : tab_contents_(tab_contents), 452 personal_data_(personal_data), 453 download_manager_(NULL) { 454 DCHECK(tab_contents); 455} 456 457void AutoFillManager::GetProfileSuggestions(FormStructure* form, 458 const FormField& field, 459 AutoFillType type, 460 bool include_cc_labels, 461 std::vector<string16>* values, 462 std::vector<string16>* labels, 463 std::vector<int>* unique_ids) { 464 const std::vector<AutoFillProfile*>& profiles = personal_data_->profiles(); 465 std::vector<AutoFillProfile*> matched_profiles; 466 for (std::vector<AutoFillProfile*>::const_iterator iter = profiles.begin(); 467 iter != profiles.end(); ++iter) { 468 AutoFillProfile* profile = *iter; 469 470 // The value of the stored data for this field type in the |profile|. 471 string16 profile_field_value = profile->GetFieldText(type); 472 473 if (!profile_field_value.empty() && 474 StartsWith(profile_field_value, field.value(), false)) { 475 matched_profiles.push_back(profile); 476 values->push_back(profile_field_value); 477 unique_ids->push_back(profile->unique_id()); 478 } 479 } 480 481 AutoFillProfile::CreateInferredLabels(&matched_profiles, labels, 0, 482 type.field_type()); 483 484 if (!include_cc_labels || !form->HasBillingFields() || !FormIsHTTPS(form)) 485 return; 486 487 size_t i = 0; 488 std::vector<string16> expanded_values; 489 std::vector<string16> expanded_labels; 490 for (std::vector<AutoFillProfile*>::const_iterator iter = 491 matched_profiles.begin(); iter != matched_profiles.end(); 492 ++iter, ++i) { 493 AutoFillProfile* profile = *iter; 494 for (std::vector<CreditCard*>::const_iterator cc = 495 personal_data_->credit_cards().begin(); 496 cc != personal_data_->credit_cards().end(); ++cc) { 497 expanded_values.push_back((*values)[i]); 498 string16 label = (*labels)[i] + kLabelSeparator + 499 (*cc)->LastFourDigits(); 500 expanded_labels.push_back(label); 501 unique_ids->push_back(profile->unique_id()); 502 } 503 } 504 expanded_labels.swap(*labels); 505 expanded_values.swap(*values); 506} 507 508void AutoFillManager::GetBillingProfileSuggestions( 509 FormStructure* form, 510 const FormField& field, 511 AutoFillType type, 512 std::vector<string16>* values, 513 std::vector<string16>* labels, 514 std::vector<int>* unique_ids) { 515 std::vector<CreditCard*> matching_creditcards; 516 std::vector<AutoFillProfile*> matching_profiles; 517 std::vector<string16> cc_values; 518 std::vector<string16> cc_labels; 519 520 // If the form is non-HTTPS, no CC suggestions are provided; however, give the 521 // user the option of filling the billing address fields with regular address 522 // data. 523 if (!FormIsHTTPS(form)) { 524 GetProfileSuggestions(form, field, type, false, values, labels, unique_ids); 525 return; 526 } 527 528 for (std::vector<CreditCard*>::const_iterator cc = 529 personal_data_->credit_cards().begin(); 530 cc != personal_data_->credit_cards().end(); ++cc) { 531 string16 label = (*cc)->billing_address(); 532 AutoFillProfile* billing_profile = NULL; 533 534 // The value of the stored data for this field type in the |profile|. 535 string16 profile_field_value; 536 537 for (std::vector<AutoFillProfile*>::const_iterator iter = 538 personal_data_->profiles().begin(); 539 iter != personal_data_->profiles().end(); ++iter) { 540 AutoFillProfile* profile = *iter; 541 542 // This assumes that labels are unique. 543 if (profile->Label() == label && 544 !profile->GetFieldText(type).empty() && 545 StartsWith(profile->GetFieldText(type), field.value(), false)) { 546 billing_profile = profile; 547 break; 548 } 549 } 550 551 if (!billing_profile) 552 continue; 553 554 for (std::vector<AutoFillProfile*>::const_iterator iter = 555 personal_data_->profiles().begin(); 556 iter != personal_data_->profiles().end(); ++iter) { 557 values->push_back(billing_profile->GetFieldText(type)); 558 559 string16 label = (*iter)->Label() + 560 ASCIIToUTF16("; ") + 561 (*cc)->LastFourDigits(); 562 labels->push_back(label); 563 unique_ids->push_back((*iter)->unique_id()); 564 } 565 } 566} 567 568void AutoFillManager::GetCreditCardSuggestions(FormStructure* form, 569 const FormField& field, 570 AutoFillType type, 571 std::vector<string16>* values, 572 std::vector<string16>* labels, 573 std::vector<int>* unique_ids) { 574 // Don't return CC suggestions for non-HTTPS pages. 575 if (!FormIsHTTPS(form)) 576 return; 577 578 for (std::vector<CreditCard*>::const_iterator iter = 579 personal_data_->credit_cards().begin(); 580 iter != personal_data_->credit_cards().end(); ++iter) { 581 CreditCard* credit_card = *iter; 582 583 // The value of the stored data for this field type in the |credit_card|. 584 string16 creditcard_field_value = 585 credit_card->GetFieldText(type); 586 if (!creditcard_field_value.empty() && 587 StartsWith(creditcard_field_value, field.value(), false)) { 588 if (type.field_type() == CREDIT_CARD_NUMBER) 589 creditcard_field_value = credit_card->ObfuscatedNumber(); 590 591 if (!form->HasNonBillingFields()) { 592 values->push_back(creditcard_field_value); 593 labels->push_back(credit_card->Label()); 594 unique_ids->push_back(credit_card->unique_id()); 595 } else { 596 for (std::vector<AutoFillProfile*>::const_iterator iter = 597 personal_data_->profiles().begin(); 598 iter != personal_data_->profiles().end(); ++iter) { 599 values->push_back(creditcard_field_value); 600 601 string16 label = (*iter)->Label() + 602 ASCIIToUTF16("; ") + 603 credit_card->LastFourDigits(); 604 labels->push_back(label); 605 unique_ids->push_back((*iter)->unique_id()); 606 } 607 } 608 } 609 } 610} 611 612void AutoFillManager::FillBillingFormField(const CreditCard* credit_card, 613 AutoFillType type, 614 webkit_glue::FormField* field) { 615 DCHECK(credit_card); 616 DCHECK(type.group() == AutoFillType::ADDRESS_BILLING); 617 DCHECK(field); 618 619 string16 billing_address = credit_card->billing_address(); 620 if (!billing_address.empty()) { 621 AutoFillProfile* profile = NULL; 622 const std::vector<AutoFillProfile*>& profiles = personal_data_->profiles(); 623 for (std::vector<AutoFillProfile*>::const_iterator iter = profiles.begin(); 624 iter != profiles.end(); ++iter) { 625 if ((*iter)->Label() == billing_address) { 626 profile = *iter; 627 break; 628 } 629 } 630 631 if (profile) { 632 FillFormField(profile, type, field); 633 } 634 } 635} 636 637void AutoFillManager::FillFormField(const AutoFillProfile* profile, 638 AutoFillType type, 639 webkit_glue::FormField* field) { 640 DCHECK(profile); 641 DCHECK(field); 642 643 if (type.subgroup() == AutoFillType::PHONE_NUMBER) { 644 FillPhoneNumberField(profile, field); 645 } else { 646 if (field->form_control_type() == ASCIIToUTF16("select-one")) 647 FillSelectOneField(profile, type, field); 648 else 649 field->set_value(profile->GetFieldText(type)); 650 } 651} 652 653void AutoFillManager::FillSelectOneField(const AutoFillProfile* profile, 654 AutoFillType type, 655 webkit_glue::FormField* field) { 656 DCHECK(profile); 657 DCHECK(field); 658 DCHECK(field->form_control_type() == ASCIIToUTF16("select-one")); 659 string16 selected_string = profile->GetFieldText(type); 660 std::string ascii_value = UTF16ToASCII(selected_string); 661 for (size_t i = 0; i < field->option_strings().size(); ++i) { 662 if (profile->GetFieldText(type) == field->option_strings()[i]) { 663 // An exact match - use it. 664 selected_string = profile->GetFieldText(type); 665 break; 666 } 667 if (!base::strcasecmp(UTF16ToASCII(field->option_strings()[i]).c_str(), 668 ascii_value.c_str())) { 669 // A match, but not in the same case - save it for the case we won't 670 // find an exact match. 671 selected_string = field->option_strings()[i]; 672 } 673 } 674 field->set_value(selected_string); 675} 676 677 678void AutoFillManager::FillPhoneNumberField(const AutoFillProfile* profile, 679 webkit_glue::FormField* field) { 680 // If we are filling a phone number, check to see if the size field 681 // matches the "prefix" or "suffix" sizes and fill accordingly. 682 string16 number = profile->GetFieldText(AutoFillType(PHONE_HOME_NUMBER)); 683 bool has_valid_suffix_and_prefix = (number.length() == 684 (kAutoFillPhoneNumberPrefixCount + kAutoFillPhoneNumberSuffixCount)); 685 if (has_valid_suffix_and_prefix && 686 field->size() == kAutoFillPhoneNumberPrefixCount) { 687 number = number.substr(kAutoFillPhoneNumberPrefixOffset, 688 kAutoFillPhoneNumberPrefixCount); 689 field->set_value(number); 690 } else if (has_valid_suffix_and_prefix && 691 field->size() == kAutoFillPhoneNumberSuffixCount) { 692 number = number.substr(kAutoFillPhoneNumberSuffixOffset, 693 kAutoFillPhoneNumberSuffixCount); 694 field->set_value(number); 695 } else { 696 field->set_value(number); 697 } 698} 699 700void AutoFillManager::ParseForms( 701 const std::vector<webkit_glue::FormData>& forms) { 702 for (std::vector<FormData>::const_iterator iter = 703 forms.begin(); 704 iter != forms.end(); ++iter) { 705 FormStructure* form_structure = new FormStructure(*iter); 706 if (!form_structure->ShouldBeParsed()) 707 continue; 708 709 DeterminePossibleFieldTypes(form_structure); 710 form_structures_.push_back(form_structure); 711 } 712 713 // If none of the forms were parsed, no use querying the server. 714 if (!form_structures_.empty()) 715 download_manager_.StartQueryRequest(form_structures_); 716} 717