Making Autofill Into a Layered Component

Objective

Restructure components/autofill into a layered component in order to enable iOS to cleanly share code in components/autofill/browser and components/autofill/common. Concretely, eliminate usage of the content layer from components/autofill code that iOS wishes to share (for details on why iOS will not be using the content layer, see the motivation and background sections of the layered components design document).

Analysis

On the browser side, Autofill's usage of the content layer falls into several broad categories:
  • Receiving communication from the renderer/external world.
    • Observing WebContents
    • Receiving IPC
    • Listening for notifications
  • Communicating to the renderer via IPC.
  • Querying the external world for information.
    • e.g., asking BrowserContext whether it is off-the-record
    • e.g., getting the values of UserPrefs
  • Convenience usages
    • The FormData struct has a content::SSLStatus field
    • AutofillManager uses a constant defined in the content layer to reference HTTPS scheme

Plan

  • Introduce AutofillDriver interface to abstract communication from autofill core code to the renderer
    • Features:
      • Interface declared in shared browser code
      • Content-based implementation will use IPC to communicate to the renderer
      • iOS-based implementation will forward calls directly to iOS autofill UI implementation
    • Content-based: AutofillDriverImpl class that will live in autofill's content driver and handle communication from the renderer/external world
      • Will implement the AutofillDriver interface
      • Will be a WebContentsObserver, using observations to drive flow of the shared browser code
      • Will be a WebContentsUserData, providing access to per-tab instances of shared browser classes
      • Will receive IPC, transforming the received messages into method calls on shared browser code
      • Will listen for notifications, transforming them into method calls on shared browser code
    • iOS-based: Introduce a conceptually-similar AutofillDriverIOS class that will live in autofill's iOS driver
  • Extend AutofillDriver interface to supply the information that shared code needs from the external world
    • New interfaces will replace direct calls that the shared code makes on the content API (e.g., to BrowserContext)
    • Content-based implementation will back these interfaces by content layer objects
    • iOS implementation will back these interfaces by iOS web layer objects
  • Eliminate convenience usages on a case-by-case basis
    • e.g., for SSLStatus, determine exactly what SSL information FormData needs and have FormData maintain just that information

Status

Help! How Do I Get My Autofill-Related Work Done?

The intended audience of this section is engineers working on components/autofill, and its purpose is to answer questions of the form "I need to do Foo, but I can't do it via Bar anymore! What do I do?".
  • How do I get an AutofillManager instance/AutofillExternalDelegate instance from a WebContents instance? Get the AutofillDriver instance (which is a WebContentsUserData) from the WebContents and then call the relevant accessor of AutofillDriver.
  • How do I take some action in shared code based on a new IPC message/WebContents observation/notification? Add a new method(s) as appropriate in shared code to implement the desired behavior; then have AutofillDriver listen for the IPC/observation/notification and invoke the new flow in shared code as appropriate.
  • Where are the common/ and browser/ directories under autofill/? Code that is shared with iOS has been moved to autofill/core/; code that is not shared with iOS has been moved to autofill/content/.
  • I need to use the content layer in foo.cc, but I'm getting a DEPS violation when I try to upload! The reason for the DEPS violation is that foo.cc is used on iOS and thus cannot use the content layer directly. See if you can implement your desired flow via one of the suggestions earlier in this set of questions. If not, consider whether the information that you need to obtain from the content layer can be done by extending one of the existing delegate interfaces via which shared code obtains information indirectly from the content layer. If all else fails, contact blundell@chromium.org to assist.
  • I want to add a new browser-side file; where should I put it? It depends on whether you think that the functionality of the file should be shared on iOS. If so, put it in autofill/core/browser, in which case it cannot reference the content layer directly. Otherwise, put it under autofill/content/browser/, in which case it can freely reference the content layer. In cases of doubt, feel free to contact blundell@chromium.org or stuartmorgan@chromium.org.



Comments