components/autofill/README.md
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 ◄─────────────────────┐ │AutofillExternalDelegate│
│ │1 per WebContents│ │ │1 per RenderFrameHost ├─┐
│ └─▲───────────────┘ │ └─────▲──────────────────┘ │
│ │ events│ owns 1 │ events│
│ │ ┌─────────────────┐ ┌─┴──────────────┴─────┐ │
│ ├─►VotesUploader ◄───────────────┤BrowserAutofillManager│events │
│ │ │1 per WebContents│ votes│1 per RenderFrameHost ├────────────┐ │
│ │ └─┬───────────────┘ └─▲────────────────────┘ │ │
│ │ │posts │ │ │
│ │ │ │ ┌──────────────┐ │ │
│ │ ┌─▼──────────────────────────┐ │ │FormStructure │ │ │
│ ├─►AutofillCrowdsourcingManager│ │ │1 per FormData│ │ │
│ │ │1 per WebContents │ │ └─▲────────────┘ │ │
│ │ └─────────────────────▲──────┘ │ │sets types │ │
│ │owns 1 │ │events │owns N │ │
│ ┌─┴──────────────────┐ │queries ┌─┴────────────┴──────┐ │ │
└─┤ChromeAutofillClient│ └───────────┤AutofillManager │events │ │
│1 per WebContents │ │1 per RenderFrameHost┼───────────┐ │ │
└─┬──────────────────┘ └───────────────────▲─┘ │ │ │
│owns 1 │events │ │ │
│ │owns 1 │ │ │
┌───▼────────────────────────┐ ┌────────────────────┐ ┌─┴─────────────▼─▼─▼─┐
│ContentAutofillDriverFactory│ │AutofillDriverRouter│ │ContentAutofillDriver│
│1 per WebContents │ │1 per WebContents │ │1 per RenderFrameHost│
└──────────────────────────┬─┘ └─▲────────────────▲─┘ └─▲────▲──┬───────────┘
owns 1└───────┘ └───────┘ │ │fill form and
Browser events │ │other events
1 process │ │
─────────────────────────────────────────────────────────────────┼──┼─────────────
Renderer │ │
N processes events, often with│ │
FormData objects │ │
┌─────┴──▼────────┐
┌─────────────────────┐ calls│AutofillAgent │
│form_autofill_util.cc◄──────────┤1 per RenderFrame│
└─────────────────────┘ └─────────────────┘
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.| Platform | Uses Blink | AutofillClient Implementation | AutofillManager Implementation | AutofillDriver Implementation | AutofillAgent Implementation |
|---|---|---|---|---|---|
| Chrome Browser | Yes | ChromeAutofillClient | BrowserAutofillManager | ContentAutofillDriver | AutofillAgent (Blink) |
| Chrome for Android (Clank) | Yes | ChromeAutofillClient | BrowserAutofillManager, AndroidAutofillManager can also be used in Chrome on Android if it's using Android's Autofill | ContentAutofillDriver | AutofillAgent (Blink) |
| Android WebView | Yes | AndroidAutofillClient | AndroidAutofillManager | ContentAutofillDriver | AutofillAgent (Blink) |
| Chrome for iOS (Bling) | No - uses WebKit | ChromeAutofillClientIOS | BrowserAutofillManager | AutofillDriverIOS | AutofillAgent (iOS) |
| iOS WebView | No - uses WebKit | WebViewAutofillClientIOS | BrowserAutofillManager | AutofillDriverIOS | AutofillAgent (iOS) |
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.hautofill_external_delegate.hautofill_manager.h
browser_autofill_manager.h (Chrome specialization)//components/android_autofill/browser/android_autofill_manager.h (WebView specialization)crowdsourcing/autofill_crowdsourcing_manager.hdata_model/
form_data_importer.hform_structure.hpersonal_data_manager.hproto/ (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/autofillThis 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::AutofillDriverAutofillDriverIOS 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::WebFormElementFormFieldData
global_id() gives a globally unique and non-changing identifier of a
field in the renderer process.blink::WebFormControlElementFormStructure - corresponds to a FormData
FormFieldData objectsAutofillField - corresponds to a FormFieldData
FormFieldData and extends it by
FormGlobalId 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.
<!-- TODO: ## How are addresses compared, updated or added? * -->