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│
└─▲──────────────────┘ ┌─▼─────────────┐ ┌─▼────────┐
│ │AutofillProfile│ │CreditCard│
│weak ref └───────────────┘ └──────────┘
┌─┴───────────────┐
│FormDataImporter ◄─────────────────────┐
│1 per WebContents│ events│
└─▲───────────────┘ │
│ │
│ ┌────────────────────────┐ ┌─┴────────────────────┐
│ │AutofillExternalDelegate◄────────┤BrowserAutofillManager├───────┐ ┌───────────────┐
│ │1 per RenderFrameHost │ owns 1│1 per RenderFrameHost │ votes│ │Autofill server│
│ └──────────────────────┬─┘ └─▲──────────────────┬─┘ │ └─────────────▲─┘
│ events│ │ events│ │ HTTP│
│ │ │ │ ┌─▼───────────────────▼─┐
├────────────────────────┼────────────┼──────────────────┼───────►AutofillDownloadManager│
│ │ │ │ │1 per WebContents │
│ │ │ │ └─────────────────────▲─┘
│ │ │ │ │
│ │ │ │ ┌──────────────┐ │
│ │ │ │ │FormStructure │ │
│ │ │ │ │1 per FormData│ │
│ │ │ └──┐ └─▲────────────┘ │
│owns 1 │ │events │ │sets types │
┌─┴──────────────────┐ │ ┌─┴───────────────────┐ │ │owns N queries│
│ChromeAutofillClient◄─────┼──────────┤AutofillManager ├─┼───┴──────────────────────┘
│1 per WebContents │ │ weak ref│1 per RenderFrameHost│ │
└─┬──────────────────┘ │ └─▲─────────────────┬─┘ │
│owns 1 │ │ events│ │
│ └────────────┼────────────────►│◄──┘
│ │ │
│ ┌────────────┼─────────────────┼────────────┐
│ │owns 1 │events │ │
│ │ │owns 1 │ │
┌─▼────────────────────────┴─┐ ┌─┴─────────────────▼─┐ ┌─▼───────────────────┐
│ContentAutofillDriverFactory├────────►ContentAutofillDriver◄────────►ContentAutofillRouter│
│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 AwAutofillClient 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_download_manager.hautofill_driver.h../../content/browser/content_autofill_driver.h (non-iOS implementation)../../ios/browser/autofill_driver_ios.h (iOS implementation)autofill_external_delegate.hautofill_manager.hbrowser_autofill_manager.h (Chrome specialization)//components/android_autofill/browser/android_autofill_manager.h (WebView specialization)data_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.
AutofillAgentRenderFrame (frame).blink::WebAutofillClient to communicate with Blink.ContentAutofillDriverRenderFrameHost (frame), owned by ContentAutofillDriverFactoryAutofillDriver and mojom::AutofillDriverAutofillDriverIOS for iOSContentAutofillDriverFactoryWebContents (tab)ContentAutofillDriver and ensures that there is one Driver instance per renderer frame.AutofillDriverIOSFactory for iOSAutofillManager and BrowserAutofillManagerRenderFrameHost (frame), owned by AutofillDriver.BrowserAutofillManager extends the AutofillManager base class.BrowserAutofillManager has sibling AndroidAutofillManager which is responsible for Android Autofill for WebViews.ChromeAutofillClientWebContents (tab)BrowserAutofillManager to the OS specific logic.AutofillClient interface.AwAutofillClient, ChromeAutofillClientIOS and WebViewAutofillClientIOS.AutocompleteHistoryManager.FormDataFormFieldData).blink::WebFormElementFormFieldDataglobal_id() gives a globally unique and non-changing identifier of a field in the renderer process.blink::WebFormControlElementFormStructure - corresponds to a FormDataFormFieldData objectsAutofillField - corresponds to a FormFieldDataFormFieldData 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.ParseSingleFieldForms).components/autofill/core/common/autofill_regex_constants.h or components/autofill/core/browser/form_parsing/regex_patterns.h if features::kAutofillParsingPatternProvider is enabled.AutofillDownloadManager is responsible for downloading field classifications.http://cs/IsSmallForm%20file:autofill.ParseAutocompleteAttribute.off).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().ParseValueAndAssignSubcomponentsByMethod()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 with known_success=false.FormTracker::DidStartNavigation()) - only if the frame has a last_interacted_form_ or form-less element that the user interacted with.SubmissionSource::PROBABLY_FORM_SUBMITTED with known_success=false.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 with known_success=true.AutofillAgent::AjaxSucceeded()), the last interacted form is/becomes unfocusable or removed.SubmissionSource::XHR_SUCCEEDED if the form is already inaccessible or removed when the XHR succeeds (known_success=true).SubmissionSource::DOM_MUTATION_AFTER_XHR if the form becomes inaccessible or removed after a successful XHR and the user does not interact with any other forms in between (known_success=true).FormTracker::WillDetach())SubmissionSource::FRAME_DETACHED with known_success=true.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::OnFocusNoLongerOnFormImpl() -> 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 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 AutofillDownloadManager.
In case observed_submission == false, the votes are not directly passed to the AutofillDownloadManager. 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.