A Credential Does Not Travel Straight from Browser to Field
This chapter follows one Android Autofill Framework request from a focused web field to a password manager and back to the browser. The goal is to identify who creates the request, who transforms it, who decides which credential fits, and who finally writes the value. That sequence matters because the browser is not handing the password manager the page itself; it is handing over a translated description whose missing context can change the security decision.
A useful starting example is an ordinary login form. A user taps the password field in a mobile browser. The browser must describe that field to Android, Android must deliver the description to the selected autofill service, and the service must return something the browser can use. The visible result may look like a single action, but the decision crosses several ownership boundaries.
From focus to a fill response
An autofill request can begin when a view gains focus. The application can also call AutofillManager.requestAutofill directly. In a browser, the relevant “view” is not a native password box in the Android sense; it is part of a rendered web page. The browser starts by preparing an autofill representation of what it believes is relevant to the request.
Android groups the client application's visible structure into an AssistStructure, made up of ViewStructure nodes. For ordinary native controls, the framework can derive much of that structure by traversing the application's view hierarchy. A browser has to provide the web portion itself. It does this by overriding View.onProvideAutofillVirtualStructure and creating virtual nodes corresponding to elements in the DOM.
That first transition already assigns responsibility. The browser owns the interpretation of the web page: which HTML elements count as fields, how they are related, which one is focused, and what web context they belong to. Android does not reconstruct those facts from the original page. It receives the structure that the client supplies.
Once the structure is ready, it goes to the Android system. The system adds the package name of the requesting application and forwards the resulting request to the user's selected AutofillService, often a password manager. The package name answers an app-level question— which application is making the request—but it is not a substitute for the web origin of every field inside a browser. The password manager must use the structure's web-related metadata to decide whether one of its stored credentials is appropriate.
The service processes the request and returns a FillResponse. Android uses that response to render a dedicated suggestion interface, such as a dropdown or a keyboard-associated prompt. At this point, the password manager has made a recommendation, but the credential has not necessarily been written into the page. The user selects an item in the autofill interface. The system then releases the selected values to the client, and the browser uses the autofill client to populate the target fields through View.autofill.
The arrows also show where the outcome can stop. If no stored credential matches, the password manager may return no useful suggestion. If the service returns a response but the user does not select an item, the described release-and-injection step does not occur. If a credential is selected, the browser becomes responsible for applying the returned values to the intended fields. A secure lifecycle therefore needs more than a correct match in the password manager: it needs a trustworthy representation on the way in and a properly scoped write on the way out.
The important distinction is between a recommendation and a write. The password manager decides what it believes should be filled. The browser ultimately owns the page and performs the injection. If the browser gives the service an over-broad structure, the service may make a response that includes fields outside the user's immediate context. If the browser then accepts that response without checking the target fields, the last step can turn an earlier ambiguity into a disclosure.
The sequence also separates two kinds of state that are easy to conflate. The browser owns the page state: which document is active, which field has focus, and how the fields relate in the DOM. Android owns the mediation state: which application requested autofill, which service is selected, and what response is displayed. The password manager owns its credential state and the matching decision. A field is safe to fill only when those states agree about the same destination. A package name can identify the browser process without proving that every field in its structure belongs to the same web origin; a credential match can identify a saved site without proving that every returned field is inside that site.
The structure is therefore both a snapshot and a promise. It is a snapshot of what the browser chose to expose at the moment of the request. It is a promise that the fields and relationships described to the service are the ones the final response is allowed to affect. The study's pipeline analysis is concerned with failures of that promise. If the browser includes fields from a wider scope than the focused context, the service may receive information it does not need. If the browser leaves out the relationship between a parent and an embedded document, the service may make a decision that is reasonable for the snapshot it sees but unsafe for the page the user sees. If the browser accepts a response without validating its destinations, the promise is broken again at the final transition.
This helps explain why the user action in the middle is not the entire authorization story. Tapping a suggestion confirms that the user wants some credential filled, but it does not by itself tell the system whether the suggestion was matched to the right origin or whether the response contains fields from an unrelated context. User selection is a meaningful gate in the lifecycle, yet it cannot compensate for a message that has already lost the facts needed to make the choice safe. The later security question is therefore not simply “did the user tap?” but “what did every participant believe that tap authorized?”
A small change in the page can also change the message without changing the visible login experience. A top-level page may contain a login form directly, or it may place an apparently identical form inside a child browsing context. The browser still displays a username box and a password box, but the virtual structure may now need to encode an ancestor, a different domain, and a different policy relationship. If those details are represented inconsistently, the password manager is not comparing like with like. It is comparing a fully described direct form with a partial description of an embedded form, then trying to apply one credential rule to both.
Why web content needs a virtual structure
Native Android views and browser-rendered HTML have different starting points. A native app may expose an EditText whose place in the view hierarchy is already meaningful to Android. A browser, by contrast, renders a DOM inside a general-purpose application. The Android autofill service does not automatically receive that DOM. The browser must create a virtual structure that acts as a message about the page.
That message can contain a field's type, its value-related metadata, whether it is focused, its webDomain, its scheme, and its position among other virtual nodes. It can also contain unrelated browser UI nodes. The structure is not a clean copy of the page's DOM; it is a selection and translation made for a particular Android interface. That difference is central to the security question. A DOM node has meaning in a particular browsing context. A virtual node has meaning only to the extent that the browser's translation and the password manager's interpretation agree.
Consider the information needed for a simple credential decision. The manager may need to know that the focused node is a password field, that it belongs to login.example, and that the relevant fields are its nearby username and password siblings. It may also need to know whether those fields sit inside another document embedded by a different site. A representation that preserves only “password field” and “login.example” can support a basic suggestion while hiding the relationship that should restrict where the value may be written.
The browser therefore owns a difficult conversion. It has to reduce a rich, nested web document to a structure that a separate service can consume, without erasing the facts that make the field trustworthy. The AutoFail analysis found that Android's interface does not provide one universal representation for all web cases. The meaning of webDomain, the treatment of hierarchy, and the handling of embedded content can vary by browser. There is no dedicated port field in the structure described by the study, and the interface does not fully specify how every frame or isolation case should be represented.
This is where a normal abstraction boundary becomes a security boundary. An abstraction is useful when the receiving component needs only a simplified view. A password manager can safely ignore many page details, such as color or layout. It cannot safely ignore which origin owns a field, which ancestors contain it, or whether the browser marked the context as opaque or ephemeral. Those facts determine whether the service is being asked to fill a credential into the place where it was saved.
The system's package name illustrates the difference between layers. Android can attach the identity of the browser application to the request, but the browser package does not tell the password manager which of several web documents supplied a field. The password manager needs web context inside the structure, while the system's app identity answers a different question about the caller. Treating one as a replacement for the other would collapse the app boundary and the web boundary into one label.
The same applies to hierarchy. The browser may represent a top-level document, an embedded document, and individual fields as a tree. If intermediate nodes are omitted or fields from different contexts are flattened together, the password manager may see the right strings but the wrong relationship. A field can still look like a password field, and a domain value can still be present somewhere in the structure, while the information needed to limit the fill has disappeared.
A successful path therefore has three properties. First, the browser's structure must identify the relevant field and preserve enough of its web context. Second, the password manager must interpret that structure conservatively rather than filling every field associated with a convenient domain label. Third, the browser must validate the returned field targets when it performs the write. Failure at any one point can undermine the others. A strict password manager cannot recover context that the browser never transmitted; a detailed structure cannot protect the user if the final injection accepts any response; and a browser-side check cannot undo a credential that was already disclosed through an over-broad response.
This distributed responsibility also explains why a password manager's visible behavior can vary with the browser. The same stored credential may be offered in one browser and withheld in another, not because the password changed, but because the two browsers supplied different virtual structures. Conversely, the same browser structure can produce different results across password managers because their matching heuristics and scope rules differ. The user sees one autofill surface, but the security decision is the product of several implementations interpreting one another's assumptions.
The next question is what those assumptions must preserve. Web security distinguishes an exact origin from a broader site relationship, and it gives special meaning to embedded, opaque, or temporary contexts. Once those distinctions are compared with the fields available to Android autofill, the later failures become easier to locate: some are omissions in the browser's message, some are guesses by the password manager, and some are unsafe writes after the decision has already been made.