Autofill is a layered component. It has the following structure:
core/
: Code shared by content/
and ios/
.content/
: Driver using the //content
layer (all platforms except iOS).ios/
: Driver using //ios
(as opposed to //content
).android/
: Java code for Android.The following architecture diagram shows instances of Autofill's core objects. For simplicity, we only consider the case of Chrome Autofill on non-iOS platforms. The diagram is best read bottom-up because every Autofill flow starts with AutofillAgent
extracting a form from the DOM.
┌────────────────────┐ ┌─►PersonalDataManager │────────┬──────────────────┐ │ │1 per BrowserContext│ owns N│ owns N│ │ └────────────────────┘ ┌─▼─────────────┐ ┌─▼────────┐ │weak ref │AutofillProfile│ │CreditCard│ │ └───────────────┘ └──────────┘ │ ┌─────────────────┐ │ │FormDataImporter ◄─────────────────────┐ │ │1 per WebContents│ events│ │ └─▲───────────────┘ │ │ │ │ │ │ ┌────────────────────────┐ ┌─┴────────────────────┐ │ │ │AutofillExternalDelegate◄────────┤BrowserAutofillManager│ │ │ │1 per RenderFrameHost │ owns 1│1 per RenderFrameHost │ │ │ └──────────────────────┬─┘ └─▲───┬──────────────┬─┘ │ │ │events │ │ events│ │ │ ┌─────────────────┐ │ │ │votes │ │ ├─►VotesUploader ◄────┼────────────┼───┘ │ │ │ │1 per WebContents│ │ │ │ │ │ └─┬───────────────┘ └────────┐ │ │ │ │ │posts │ │ │ │ │ ┌─▼──────────────────────────┐ │ │ │ │ ├─►AutofillCrowdsourcingManager│ │ │ │ ┌──────────────┐ │ │ │1 per WebContents │ │ │ │ │FormStructure │ │ │ └─────────────────────▲──────┘ │ │ │ │1 per FormData│ │ │ │ │ │ └──┐ └─▲────────────┘ │ │owns 1 │ │ │events │ │sets types │ ┌─┴──────────────────┐ │queries │ ┌─┴───────────────────┐ │ │owns N └─┤ChromeAutofillClient│ └─────────┼─┼AutofillManager ├─┼───┘ │1 per WebContents │ │ │1 per RenderFrameHost│ │ └─┬──────────────────┘ │ └─▲─────────────────┬─┘ │ │owns 1 │ │ events│ │ │ └───┼────────────────►│◄──┘ │ │ │ │ ┌────────────┼─────────────────┼────────────┐ │ │owns 1 │events │ │ │ │ │owns 1 │ │ ┌─▼────────────────────────┴─┐ ┌─┴─────────────────▼─┐ ┌─▼──────────────────┐ │ContentAutofillDriverFactory├────────►ContentAutofillDriver◄────────►AutofillDriverRouter│ │1 per WebContents │owns N │1 per RenderFrameHost│ events │1 per WebContents │ └────────────────────────────┘ └─▲─────────┬─────────┘ └────────────────────┘ │ │fill form and Browser │ │other events 1 process │ │ ────────────────────────────────────────┼─────────┼──────────────────────────────────────── Renderer │ │ N processes events, often with│ │ FormData objects │ │ ┌─┴─────────▼─────┐ ┌─────────────────────┐ │AutofillAgent ├───────►form_autofill_util.cc│ │1 per RenderFrame│calls └─────────────────────┘ └─────────────────┘
To edit the diagram, copy-paste it to asciiflow.com.
A WebContents
corresponds to a tab. A RenderFrameHost
roughly corresponds to a frame or a document (but to neither exactly; they differ in whether or not they survive navigations; details are here and here). A BrowserContext
corresponds to a Profile
.
//chrome
.AutofillManager
and everything north of it, but AutofillDriverIOS*
instead of ContentAutofill*
, and a different but identically named AutofillAgent
.AutofillManager
and everything south of it, but AndroidAutofillClient
instead of ChromeAutofillClient
, and AndroidAutofillManager
instead of BrowserAutofillManager
.core/
common/
browser/
autofill_client.h
//android_webview/browser/aw_autofill_client.h
(WebView implementation)//chrome/browser/ui/autofill/chrome_autofill_client.h
(Chrome implementation)autofill_driver.h
../../content/browser/content_autofill_driver.h
(non-iOS implementation)../../ios/browser/autofill_driver_ios.h
(iOS implementation)autofill_driver_router.h
autofill_external_delegate.h
autofill_manager.h
browser_autofill_manager.h
(Chrome specialization)//components/android_autofill/browser/android_autofill_manager.h
(WebView specialization)crowdsourcing/autofill_crowdsourcing_manager.h
data_model/
form_data_importer.h
form_structure.h
personal_data_manager.h
proto/
(Autofill server)content/
ios/
There are some closely related directories in //chrome
:
//chrome/browser/autofill
//chrome/browser/ui/android/autofill
//chrome/browser/ui/autofill
//chrome/browser/ui/views/autofill
This is a cheatsheet to navigate Autofill. It is not necessarily exhaustive and may sacrifice a little bit of correctness in favor of simplicity.
AutofillAgent
RenderFrame
(frame).blink::WebAutofillClient
to communicate with Blink.ContentAutofillDriver
RenderFrameHost
(frame), owned by ContentAutofillDriverFactory
.AutofillDriver
and mojom::AutofillDriver
AutofillDriverIOS
for iOSContentAutofillDriverFactory
WebContents
(tab).ContentAutofillDriver
and ensures that there is one Driver instance per renderer frame.AutofillDriverIOSFactory
for iOSAutofillDriverRouter
WebContents
(tab).FormData
.AutofillManager
and BrowserAutofillManager
RenderFrameHost
(frame), owned by AutofillDriver
.BrowserAutofillManager
extends the AutofillManager
base class.BrowserAutofillManager
has sibling AndroidAutofillManager
which is responsible for Android Autofill for WebViews.ChromeAutofillClient
WebContents
(tab).BrowserAutofillManager
to the OS specific logic.AutofillClient
interface.AndroidAutofillClient
, ChromeAutofillClientIOS
and WebViewAutofillClientIOS
.PersonalDataManager
BrowserContext
(Chrome profile). In incognito mode, the original profile's instance is used. This enables filling even in incognito mode. Imports are disabled in incognito mode by the BrowserAutofillManager
.AutofillTable
- an SQLite database used to persist data across browser shutdown.AutofillTable
's data in memory, making them available to the rest of Autofill.PersonalDataManager
generally happen asynchronously. For details, see go/pdm-autofill-table-interface.AutocompleteHistoryManager
.FormData
FormFieldData
).blink::WebFormElement
FormFieldData
global_id()
gives a globally unique and non-changing identifier of a field in the renderer process.blink::WebFormControlElement
FormStructure
- corresponds to a FormData
FormFieldData
objectsAutofillField
- corresponds to a FormFieldData
FormFieldData
and extends it byFormGlobalId
is a pair of a LocalFrameToken
and a FormRendererId
, which uniquely identify the frame and the form element in that frame.FieldGlobalId
is a pair of a LocalFrameToken
and a FieldRendererId
.FormSignature
is a 64 bit hash value of the form URL (target URL or location of the embedding website as a fallback) and normalized field names.FieldSignature
is a 32 bit hash value of the field name (name attribute, falling back to id attribute of the form control) and type (text, search, password, tel, ...)components/autofill/core/browser/form_parsing/
.FormField::ParseFormFields
is the global entry point for parsing fields with heuristics.ParseSingleFields
).components/autofill/core/browser/form_parsing/regex_patterns.h
and components/autofill/core/browser/form_parsing/*/*regex_patterns.json
.AutofillCrowdsourcingManager
is responsible for downloading field classifications and uploading type votes.
Crowd sourcing is applied (for lookups and voting) for forms of any size but the server can handle small forms differently, see http://cs/IsSmallForm%20file:autofill
.
Crowd sourcing trumps local heuristics.
For testing purposes, crowd sourcing can be overridden manually by command line parameter:
chrome --enable-features=AutofillOverridePredictions:spec/1_2_4-7_8_9
This creates two manual overrides that supersede server predictions as follows:
NAME_MIDDLE
).EMAIL_ADDRESS
). For more detail, see the documentation of ServerPredictionOverrides
.ParseAutocompleteAttribute
.off
).Predicted types are represented as FieldTypes and types derived from the autocomplete attribute are represented as HtmlFieldTypes.
AutofillDriverRouter
flattens each tree of forms by merging the fields of the FormData
nodes into the root FormData
, and routes events between the nodes' drivers to the root's driver and vice versa.AutofillAgent
only sees renderer forms, AutofillManager
only sees browser forms.Several important subsets of FieldTypes exist:
AutofillProfile::kDatabaseStoredTypes
.See go/autofill-new-fieldtypes-in-data-model-dd.
components/autofill/core/browser/data_model/
components/autofill/core/browser/data_model/autofill_structured_address.h
and components/autofill/core/browser/data_model/autofill_structured_address_name.h
.AddressComponent::ParseValueAndAssignSubcomponents()
.ParseValueAndAssignSubcomponentsByRegularExpressions()
ParseValueAndAssignSubcomponentsByFallbackMethod()
GetParseRegularExpressionsByRelevance()
.AddressComponent::FormatValueFromSubcomponents()
.GetBestFormatString()
, in particular StreetAddress::GetBestFormatString()
.AddressComponent::WipeInvalidStructure()
.The following situations are considered form submissions by Autofill and end up at AutofillManager::OnFormSubmitted()
with a submission source and an assessment whether the form submission should be considered successful (meaning that the website accepted the submitted values, not that the HTTP request succeeded):
FormTracker::WillSubmitForm()
).SubmissionSource::FORM_SUBMISSION
.FormTracker::DidStartNavigation()
) - only if the frame has a last_interacted_form_
or form-less element that the user interacted with.SubmissionSource::PROBABLY_FORM_SUBMITTED
.FormTracker::DidFinishSameDocumentNavigation()
), the last interacted form is/becomes unfocusable or removed. The former condition is tested via WebNode::IsFocusable()
and considers various styles (e.g. “display: none” on the node or a parent, “visibility: hidden”) and attributes (e.g. “inert”, tabindex=“-1”, “disabled”) which prevent focusability.SubmissionSource::SAME_DOCUMENT_NAVIGATION
.AutofillAgent::AjaxSucceeded()
), the last interacted form is/becomes unfocusable or removed.SubmissionSource::XHR_SUCCEEDED
if the form is already inaccessible or removed and the XHR succeeds.FormTracker::WillDetach()
)SubmissionSource::FRAME_DETACHED
.Autofill votes are theoretically uploaded
when a form is submitted (BrowserAutofillManager::OnFormSubmittedImpl()
).
In this case observed_submission=true
is passed to BrowserAutofillManager::MaybeStartVoteUploadProcess
.
when a the user removes focus from a form (this could happen because the user clicks on a custom autofill dropdown rendered by the website or if the user just clicks on the background). (BrowserAutofillManager::OnFocusOnNonFormFieldImpl()
-> BrowserAutofillManager::ProcessPendingFormForUpload()
).
observed_submission=false
is passed.
when a the form changes (the structure, not the values) and we notice it (BrowserAutofillManager::UpdatePendingForm()
-> BrowserAutofillManager::ProcessPendingFormForUpload()
).
observed_submission=false
is passed.
In practice we allow only one vote upload per (form x submission source) every kAutofillUploadThrottlingPeriodInDays
days.
In case observed_submission == true
, the votes are generated on a background thread and then passed to the AutofillCrowdsourcingManager
.
In case observed_submission == false
, the votes are not directly passed to the AutofillCrowdsourcingManager
. Instead they are cached until the cache is flushed. This enables us to override previous votes in case the user focuses and removes focus from a form multiple times while editing the fields' values. The cache is flushed on form submission.
As the votes generation is asynchronous, it is not guaranteed that the results are available by the time the upload cache is flushed. In this case, votes are only uploaded on the next navigation.