// Copyright 2021 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_DRIVER_ROUTER_H_ #define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_DRIVER_ROUTER_H_ #include <optional> #include <string> #include "base/containers/flat_map.h" #include "base/types/optional_ref.h" #include "components/autofill/core/browser/autofill_driver.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/form_forest.h" #include "components/autofill/core/common/form_data.h" #include "components/autofill/core/common/form_data_predictions.h" #include "components/autofill/core/common/form_field_data.h" #include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h" #include "ui/gfx/geometry/rect_f.h" namespace autofill { // AutofillDriverRouter routes events between AutofillDriver objects in order to // handle frame-transcending forms. // // A *frame-transcending* form is a form whose fields live in different frames. // For example, credit card forms often have the credit card number field in an // iframe hosted by a payment service provider. // // A frame-transcending form therefore consists of multiple *renderer forms*. // AutofillDriverRouter *flattens* these forms into a single *browser form*, // and maps all events concerning the renderer forms to that browser form, and // vice versa. // // That way, the collection of renderer forms appears as one ordinary form to // the browser. // // For example, consider the following pseudo HTML code: // <html> // <form id="Form-1"> // <input id="Field-1"> // <iframe id="Frame-1"> // <input id="Field-2"> // </iframe> // <iframe id="Frame-2"> // <iframe id="Frame-3"> // <form id="Form-2"> // <input id="Field-3"> // </form> // <form id="Form-3"> // <input id="Field-4"> // </form> // </iframe> // </iframe> // <input id="Field-5"> // </form> // // Forms can be actual <form> elements or synthetic forms: <input>, <select>, // and <iframe> elements that are not in the scope of any <form> belong to the // enclosing frame's synthetic form. // // The five renderer forms are therefore, in pseudo C++ code: // FormData{ // .host_frame = "Frame-0", // The main frame. // .name = "Form-1", // .fields = { "Field-1", "Field-5" }, // .child_frames = { "Frame-1", "Frame-2" } // } // FormData{ // .host_frame = "Frame-1", // .name = "synthetic", // .fields = { "Field-2" }, // .child_frames = { } // } // FormData{ // .host_frame = "Frame-2", // .name = "synthetic", // .fields = { }, // .child_frames = { "Frame-3" } // } // FormData{ // .host_frame = "Frame-3", // .name = "Form-2", // .fields = { "Field-3" }, // .child_frames = { } // } // FormData{ // .host_frame = "Frame-3", // .name = "Form-3", // .fields = { "Field-4" }, // .child_frames = { } // } // // The browser form of these renderer forms is obtained by flattening the fields // into the root form: // FormData{ // .name = "Form-1", // .fields = { "Field-1", "Field-2", "Field-3", "Field-4", "Field-5" } // } // // Let AutofillAgent-N, AutofillDriver-N, and AutofillManager-N correspond to // the Frame-N. AutofillDriverRouter would route an event concerning any of the // forms in Frame-3 from AutofillDriver-3 to AutofillDriver-0: // // +---Tab---+ +---Tab----+ +----Tab----+ // | Agent-0 | +---> | Driver-0 | ---------> | Manager-0 | // | | | | | | | // | Agent-1 | | | Driver-1 | | Manager-1 | // | | | | | | | // | Agent-2 | | | Driver-2 | | Manager-2 | // | | | | | | | // | Agent-3 | -----|---> | Driver-3 | -----+ | Manager-3 | // +---------+ | +----------+ | +-----------+ // | | // | +--Tab---+ | // +----- | Router | <-----+ // +--------+ // // If the event name is `Foo`, the control flow is as follows: // Driver-3.Foo(args1...) calls // Router.Foo(callback, args1...) calls // callback(Driver-0, args2...), // where `args2` are obtained by mapping renderer forms to browser forms and // vice versa. // // Events triggered by the renderer take a |source| parameter, which is the // driver of the frame whose DOM contains the renderer form. // // See ContentAutofillDriver for details on the naming pattern and an example. // // See FormForest for details on (un)flattening. class AutofillDriverRouter { … }; } // namespace autofill #endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_DRIVER_ROUTER_H_