2016-01-11 9 views
17

Ich bin kürzlich auf ein Problem bezüglich der automatischen Vervollständigung von Browsern gestoßen. Man könnte es in Formularen auf Webseiten finden.Wie Browser Daten für Autocomplete speichern und wo?

Problem ist mit Daten, die in anderen Feldern je nach Auswahl der Autovervollständigung für ein Feld platziert werden. Im Detail ist es mit der Nutzung AngularJS verbunden.

Ich habe Themen in Bezug auf Workarounds für eckig gefunden, aber was mich interessiert, ist, wo gespeicherte Daten von Browser gehalten wird und welche Logik dahinter ist, diese Daten zu sammeln.

  • Gibt es eine bestimmte Liste von Feldern, die vom Browser überwacht werden?
  • Ist der Datenhost (Standort) spezifisch für das Feld?
  • Wann wird vom Browser gespeichert? Auf einem normalen Formular einreichen oder andere Events?

Vielen Dank im Voraus.

+0

Ist Dieser Artikel ist hilfreich? [AutoFill Ihre Informationen in Formularen in Chrome] (https://support.google.com/chrome/answer/142893?p=settings_autofill&rd=1) – cuixiping

Antwort

12

Die Implementierung von AutoFill-Funktionen ist dem Browser-Anbieter überlassen. Wenn sie den "Living HTML Standard" der Web Hypertext Application Technology Working Group implementieren, gilt Absatz 4.10.19.8.1 (AutoFilling-Formularsteuerelemente: das Autocomplete-Attribut).Dort werden die folgenden autofill field names definiert:

  • "name"
  • "honorific-Präfix"
  • "given-name"
  • "additional-name"
  • "Familiennamen"
  • "honorific-Suffix"
  • "Spitznamen"
  • "username"
  • "new-password"
  • "current-Passwort"
  • "organisations Titel"
  • "Organisation"
  • "street-Adresse"
  • "adress line1"
  • „-Adresse -line2"
  • "adress line3"
  • "adress level4"
  • "adress level3"
  • "adress Level2"
  • "adress ebenen1"
  • "Land"
  • "Land-name"
  • "Postcode"
  • "cc-name"
  • „cc -given-name“
  • "cc-Zusatznamen"
  • "cc-family-name"
  • "cc-Nummer"
  • "cc-exp"
  • "cc-exp-Monat"
  • "cc-exp-Jahr"
  • "cc-csc"
  • "cc-type"
  • „Transaktionswährung "
  • "Transaktionsbetrag"
  • "Sprache"
  • "bday"
  • "bday-Tag"
  • " bday-Monat“
  • "bday-Jahr"
  • "sex"
  • "url"
  • "Foto"

sich Chrom betrachtet, eine populärer Open-Source-Browser dieser Norm der Nutzung .

In src/components/autofill/core/browser/form_structure.cc ein Unter den vorgenannten autofill Feldnamen gesetzt werden verwendet, diese intern zur Karte:

// Returns the Chrome Autofill-supported field type corresponding to the given 
// |autocomplete_attribute_value|, if there is one, in the context of the given 
// |field|. Chrome Autofill supports a subset of the field types listed at 
// http://is.gd/whatwg_autocomplete 
HtmlFieldType FieldTypeFromAutocompleteAttributeValue(
    const std::string& autocomplete_attribute_value, 
    const AutofillField& field) { 
    if (autocomplete_attribute_value == "name") 
    return HTML_TYPE_NAME; 

    if (autocomplete_attribute_value == "given-name") 
    return HTML_TYPE_GIVEN_NAME; 

    if (autocomplete_attribute_value == "additional-name") { 
    if (field.max_length == 1) 
     return HTML_TYPE_ADDITIONAL_NAME_INITIAL; 
    else 
     return HTML_TYPE_ADDITIONAL_NAME; 
    } 

    if (autocomplete_attribute_value == "family-name") 
    return HTML_TYPE_FAMILY_NAME; 

    if (autocomplete_attribute_value == "organization") 
    return HTML_TYPE_ORGANIZATION; 

    if (autocomplete_attribute_value == "street-address") 
    return HTML_TYPE_STREET_ADDRESS; 

    if (autocomplete_attribute_value == "address-line1") 
    return HTML_TYPE_ADDRESS_LINE1; 

    if (autocomplete_attribute_value == "address-line2") 
    return HTML_TYPE_ADDRESS_LINE2; 

    if (autocomplete_attribute_value == "address-line3") 
    return HTML_TYPE_ADDRESS_LINE3; 

    // TODO(estade): remove support for "locality" and "region". 
    if (autocomplete_attribute_value == "locality") 
    return HTML_TYPE_ADDRESS_LEVEL2; 

    if (autocomplete_attribute_value == "region") 
    return HTML_TYPE_ADDRESS_LEVEL1; 

    if (autocomplete_attribute_value == "address-level1") 
    return HTML_TYPE_ADDRESS_LEVEL1; 

    if (autocomplete_attribute_value == "address-level2") 
    return HTML_TYPE_ADDRESS_LEVEL2; 

    if (autocomplete_attribute_value == "address-level3") 
    return HTML_TYPE_ADDRESS_LEVEL3; 

    if (autocomplete_attribute_value == "country") 
    return HTML_TYPE_COUNTRY_CODE; 

    if (autocomplete_attribute_value == "country-name") 
    return HTML_TYPE_COUNTRY_NAME; 

    if (autocomplete_attribute_value == "postal-code") 
    return HTML_TYPE_POSTAL_CODE; 

    // content_switches.h isn't accessible from here, hence we have 
    // to copy the string literal. This should be removed soon anyway. 
    if (autocomplete_attribute_value == "address" && 
     base::CommandLine::ForCurrentProcess()->HasSwitch(
      "enable-experimental-web-platform-features")) { 
    return HTML_TYPE_FULL_ADDRESS; 
    } 

    if (autocomplete_attribute_value == "cc-name") 
    return HTML_TYPE_CREDIT_CARD_NAME; 

    if (autocomplete_attribute_value == "cc-number") 
    return HTML_TYPE_CREDIT_CARD_NUMBER; 

    if (autocomplete_attribute_value == "cc-exp") { 
    if (field.max_length == 5) 
     return HTML_TYPE_CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR; 
    else if (field.max_length == 7) 
     return HTML_TYPE_CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR; 
    else 
     return HTML_TYPE_CREDIT_CARD_EXP; 
    } 

    if (autocomplete_attribute_value == "cc-exp-month") 
    return HTML_TYPE_CREDIT_CARD_EXP_MONTH; 

    if (autocomplete_attribute_value == "cc-exp-year") { 
    if (field.max_length == 2) 
     return HTML_TYPE_CREDIT_CARD_EXP_2_DIGIT_YEAR; 
    else if (field.max_length == 4) 
     return HTML_TYPE_CREDIT_CARD_EXP_4_DIGIT_YEAR; 
    else 
     return HTML_TYPE_CREDIT_CARD_EXP_YEAR; 
    } 

    if (autocomplete_attribute_value == "cc-csc") 
    return HTML_TYPE_CREDIT_CARD_VERIFICATION_CODE; 

    if (autocomplete_attribute_value == "cc-type") 
    return HTML_TYPE_CREDIT_CARD_TYPE; 

    if (autocomplete_attribute_value == "transaction-amount") 
    return HTML_TYPE_TRANSACTION_AMOUNT; 

    if (autocomplete_attribute_value == "transaction-currency") 
    return HTML_TYPE_TRANSACTION_CURRENCY; 

    if (autocomplete_attribute_value == "tel") 
    return HTML_TYPE_TEL; 

    if (autocomplete_attribute_value == "tel-country-code") 
    return HTML_TYPE_TEL_COUNTRY_CODE; 

    if (autocomplete_attribute_value == "tel-national") 
    return HTML_TYPE_TEL_NATIONAL; 

    if (autocomplete_attribute_value == "tel-area-code") 
    return HTML_TYPE_TEL_AREA_CODE; 

    if (autocomplete_attribute_value == "tel-local") 
    return HTML_TYPE_TEL_LOCAL; 

    if (autocomplete_attribute_value == "tel-local-prefix") 
    return HTML_TYPE_TEL_LOCAL_PREFIX; 

    if (autocomplete_attribute_value == "tel-local-suffix") 
    return HTML_TYPE_TEL_LOCAL_SUFFIX; 

    if (autocomplete_attribute_value == "email") 
    return HTML_TYPE_EMAIL; 

    return HTML_TYPE_UNKNOWN; 
} 

Diese Methode dann bei der Analyse der Formularfelder zu unterstützen, verwendet wird:

void FormStructure::ParseFieldTypesFromAutocompleteAttributes() { 
    const std::string kDefaultSection = "-default"; 

    has_author_specified_types_ = false; 
    has_author_specified_sections_ = false; 
    for (AutofillField* field : fields_) { 
    // To prevent potential section name collisions, add a default suffix for 
    // other fields. Without this, 'autocomplete' attribute values 
    // "section--shipping street-address" and "shipping street-address" would be 
    // parsed identically, given the section handling code below. We do this 
    // before any validation so that fields with invalid attributes still end up 
    // in the default section. These default section names will be overridden 
    // by subsequent heuristic parsing steps if there are no author-specified 
    // section names. 
    field->set_section(kDefaultSection); 

    // Canonicalize the attribute value by trimming whitespace, collapsing 
    // non-space characters (e.g. tab) to spaces, and converting to lowercase. 
    std::string autocomplete_attribute = 
     base::CollapseWhitespaceASCII(field->autocomplete_attribute, false); 
    autocomplete_attribute = base::ToLowerASCII(autocomplete_attribute); 

    // The autocomplete attribute is overloaded: it can specify either a field 
    // type hint or whether autocomplete should be enabled at all. Ignore the 
    // latter type of attribute value. 
    if (autocomplete_attribute.empty() || 
     autocomplete_attribute == "on" || 
     autocomplete_attribute == "off") { 
     continue; 
    } 

    // Any other value, even it is invalid, is considered to be a type hint. 
    // This allows a website's author to specify an attribute like 
    // autocomplete="other" on a field to disable all Autofill heuristics for 
    // the form. 
    has_author_specified_types_ = true; 

    // Tokenize the attribute value. Per the spec, the tokens are parsed in 
    // reverse order. 
    std::vector<std::string> tokens = base::SplitString(
     autocomplete_attribute, " ", base::KEEP_WHITESPACE, 
     base::SPLIT_WANT_NONEMPTY); 

    // The final token must be the field type. 
    // If it is not one of the known types, abort. 
    DCHECK(!tokens.empty()); 
    std::string field_type_token = tokens.back(); 
    tokens.pop_back(); 
    HtmlFieldType field_type = 
     FieldTypeFromAutocompleteAttributeValue(field_type_token, *field); 
    if (field_type == HTML_TYPE_UNKNOWN) 
     continue; 

    // The preceding token, if any, may be a type hint. 
    if (!tokens.empty() && IsContactTypeHint(tokens.back())) { 
     // If it is, it must match the field type; otherwise, abort. 
     // Note that an invalid token invalidates the entire attribute value, even 
     // if the other tokens are valid. 
     if (!ContactTypeHintMatchesFieldType(tokens.back(), field_type)) 
     continue; 

     // Chrome Autofill ignores these type hints. 
     tokens.pop_back(); 
    } 

    // The preceding token, if any, may be a fixed string that is either 
    // "shipping" or "billing". Chrome Autofill treats these as implicit 
    // section name suffixes. 
    DCHECK_EQ(kDefaultSection, field->section()); 
    std::string section = field->section(); 
    HtmlFieldMode mode = HTML_MODE_NONE; 
    if (!tokens.empty()) { 
     if (tokens.back() == kShippingMode) 
     mode = HTML_MODE_SHIPPING; 
     else if (tokens.back() == kBillingMode) 
     mode = HTML_MODE_BILLING; 
    } 

    if (mode != HTML_MODE_NONE) { 
     section = "-" + tokens.back(); 
     tokens.pop_back(); 
    } 

    // The preceding token, if any, may be a named section. 
    const std::string kSectionPrefix = "section-"; 
    if (!tokens.empty() && 
     base::StartsWith(tokens.back(), kSectionPrefix, 
         base::CompareCase::SENSITIVE)) { 
     // Prepend this section name to the suffix set in the preceding block. 
     section = tokens.back().substr(kSectionPrefix.size()) + section; 
     tokens.pop_back(); 
    } 

    // No other tokens are allowed. If there are any remaining, abort. 
    if (!tokens.empty()) 
     continue; 

    if (section != kDefaultSection) { 
     has_author_specified_sections_ = true; 
     field->set_section(section); 
    } 

    // No errors encountered while parsing! 
    // Update the |field|'s type based on what was parsed from the attribute. 
    field->SetHtmlType(field_type, mode); 
    } 

    was_parsed_for_autocomplete_attributes_ = true; 
} 
+0

In meinem Fall wird Chrome AutoFill für solche Felder wie 'zip',' email', 'phone' in mindestens einer Form vorgeschlagen. Ich habe solche Feldnamen in der obigen Liste nicht gefunden. Ist es ein anderer Fall von Autofill? – Eugene

+1

AFAIK Diese Feldnamen sind nicht Bestandteil eines Standards und unterliegen daher den vom Hersteller getroffenen Implementierungsentscheidungen. Für alle Browser ist das ein wenig breit. Wenn Sie interessiert sind, wie Chromium es macht, werfen Sie einen Blick auf die verlinkten Quellen. '' '' src/Komponenten/AutoFill/Core/Browser/Webdata/AutoFill_Webdata_Backend_Impl.h''' ist auch in dieser Hinsicht ziemlich interessant. –

-2

Meiner Erfahrung nach ist die automatische Vervollständigung normalerweise feldspezifisch und führt einen Ajax-Aufruf aus, wenn sie nach dem dritten Zeichen eingegeben werden.

if (input.length === 3) 
    //call server on keyup 

Dann speichert es das Ergebnis zwischen. Danach können Sie das Ergebnis nur auf der Client-Seite filtern. Wenn sie zurückgehen und einen neuen 3-Zeichen-Anfang eingeben, fragt sie erneut ab und speichert sie lokal. Ich hoffe, das beantwortet deine Frage.

+0

Sind Sie sicher, dass Sie über Browser-Form [Autocomplete] sprechen (http: //www.w3.org/TR/html5/forms.html#attr-form-autocomplete) Funktionalität? – Eugene

+0

Ignorieren Sie meine Antwort. Ich dachte, Sie sprechen über benutzerdefinierte dynamische Autovervollständigungsfelder, d. H. Wenn Sie einen Ihrer Kontakte in ein Textfeld einfügen, indem Sie Ihre eigene Datenbank abfragen und Abschlussoptionen anbieten. – gegillam

Verwandte Themen