1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
|
// 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_FOUNDATIONS_AUTOFILL_DRIVER_ROUTER_H_
#define COMPONENTS_AUTOFILL_CORE_BROWSER_FOUNDATIONS_AUTOFILL_DRIVER_ROUTER_H_
#include <optional>
#include <string>
#include "base/containers/flat_map.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/foundations/autofill_driver.h"
#include "components/autofill/core/browser/foundations/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 "components/autofill/core/common/password_form_fill_data.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 {
public:
template <typename... Args>
using RoutedCallback = base::FunctionRef<void(AutofillDriver&, Args...)>;
AutofillDriverRouter();
AutofillDriverRouter(const AutofillDriverRouter&) = delete;
AutofillDriverRouter& operator=(const AutofillDriverRouter&) = delete;
~AutofillDriverRouter();
// Deletes all forms and fields related to |driver| (and this driver only).
// Must be called whenever |driver| is destroyed.
//
// |driver_is_dying| indicates if the |driver| is being destructed or about to
// be destructed. Typically, the driver dies on cross-origin navigations but
// survives same-origin navigations (but more precisely this depends on the
// lifecycle of the content::RenderFrameHost). If the driver survives, the
// router may keep the meta data is collected about the frame (in particular,
// the parent frame).
void UnregisterDriver(AutofillDriver& driver, bool driver_is_dying);
// Events called by the renderer, passed to the browser:
// Keep in alphabetic order.
void FormsSeen(RoutedCallback<const std::vector<FormData>&,
const std::vector<FormGlobalId>&> callback,
AutofillDriver& source,
std::vector<FormData> updated_forms,
const std::vector<FormGlobalId>& removed_forms);
void FormSubmitted(
RoutedCallback<const FormData&, mojom::SubmissionSource> callback,
AutofillDriver& source,
FormData form,
mojom::SubmissionSource submission_source);
void CaretMovedInFormField(
RoutedCallback<const FormData&, const FieldGlobalId&, const gfx::Rect&>
callback,
AutofillDriver& source,
FormData form,
const FieldGlobalId& field_id,
const gfx::Rect& caret_bounds);
void TextFieldValueChanged(
RoutedCallback<const FormData&, const FieldGlobalId&, base::TimeTicks>
callback,
AutofillDriver& source,
FormData form,
const FieldGlobalId& field_id,
base::TimeTicks timestamp);
void TextFieldDidScroll(
RoutedCallback<const FormData&, const FieldGlobalId&> callback,
AutofillDriver& source,
FormData form,
const FieldGlobalId& field_id);
void SelectControlSelectionChanged(
RoutedCallback<const FormData&, const FieldGlobalId&> callback,
AutofillDriver& source,
FormData form,
const FieldGlobalId& field_id);
void AskForValuesToFill(
RoutedCallback<const FormData&,
const FieldGlobalId&,
const gfx::Rect&,
AutofillSuggestionTriggerSource,
std::optional<PasswordSuggestionRequest>> callback,
AutofillDriver& source,
FormData form,
const FieldGlobalId& field_id,
const gfx::Rect& caret_bounds,
AutofillSuggestionTriggerSource trigger_source,
std::optional<PasswordSuggestionRequest> password_request);
// This event is broadcast to all drivers.
void DidEndTextFieldEditing(RoutedCallback<> callback,
AutofillDriver& source);
void DidFillAutofillFormData(
RoutedCallback<const FormData&, base::TimeTicks> callback,
AutofillDriver& source,
FormData form,
base::TimeTicks timestamp);
void FocusOnFormField(
RoutedCallback<const FormData&, const FieldGlobalId&> callback,
AutofillDriver& source,
FormData form,
const FieldGlobalId& field_id,
RoutedCallback<> focus_no_longer_on_form);
// This event is broadcast to all drivers.
void FocusOnNonFormField(RoutedCallback<> callback, AutofillDriver& source);
// This event is broadcast to all drivers.
void HidePopup(RoutedCallback<> callback, AutofillDriver& source);
void JavaScriptChangedAutofilledValue(
RoutedCallback<const FormData&,
const FieldGlobalId&,
const std::u16string&> callback,
AutofillDriver& source,
FormData form,
const FieldGlobalId& field_id,
const std::u16string& old_value);
void SelectFieldOptionsDidChange(RoutedCallback<const FormData&> callback,
AutofillDriver& source,
FormData form);
// Events called by the browser, passed to the renderer:
// Keep in alphabetic order.
base::flat_set<FieldGlobalId> ApplyFormAction(
RoutedCallback<mojom::FormActionType,
mojom::ActionPersistence,
const std::vector<FormFieldData::FillData>&> callback,
mojom::FormActionType action_type,
mojom::ActionPersistence action_persistence,
base::span<const FormFieldData> data,
const url::Origin& main_origin,
const url::Origin& triggered_origin,
const base::flat_map<FieldGlobalId, FieldType>& field_type_map);
void ApplyFieldAction(RoutedCallback<mojom::FieldActionType,
mojom::ActionPersistence,
FieldRendererId,
const std::u16string&> callback,
mojom::FieldActionType action_type,
mojom::ActionPersistence action_persistence,
const FieldGlobalId& field_id,
const std::u16string& value);
using BrowserFormHandler = AutofillDriver::BrowserFormHandler;
using RendererFormHandler =
base::OnceCallback<void(const std::optional<FormData>&)>;
// Routes both the request *and* the response: it calls `callback` with
// - the `target` driver that shall extract the form,
// - the `form_id` to be extracted, and
// - the `renderer_form_handler` that processes the extracted form.
//
// Processing the extracted form means to call the callback
// `browser_form_handler`. For that to happen, the extracted renderer form
// must be mapped to a browser form. The `renderer_form_handler` performs this
// conversion and then passes the result to `browser_form_handler` together
// with the driver that manages the browser form (i.e., the driver whose
// AutofillDriver::GetFrameToken() is equal to the browser form's
// FormData::host_frame`).
//
// It is the responsibility of `callback` to call `renderer_form_handler`
// with the extracted renderer form so that the mapping and callback can
// happen.
//
// So intuitively, `callback` should do something like
// `target->autofill_agent()->ExtractForm(form_id, renderer_form_handler)`.
//
// If routing the request fails, ExtractForm() calls `browser_form_handler`
// right away with nullptr and std::nullopt.
void ExtractForm(RoutedCallback<FormRendererId, RendererFormHandler> callback,
FormGlobalId form_id,
BrowserFormHandler browser_form_handler);
void RendererShouldAcceptDataListSuggestion(
RoutedCallback<FieldRendererId, const std::u16string&> callback,
const FieldGlobalId& field_id,
const std::u16string& value);
void RendererShouldClearPreviewedForm(RoutedCallback<> callback);
void RendererShouldSetSuggestionAvailability(
RoutedCallback<FieldRendererId, mojom::AutofillSuggestionAvailability>
callback,
const FieldGlobalId& field_id,
mojom::AutofillSuggestionAvailability suggestion_availability);
void RendererShouldTriggerSuggestions(
RoutedCallback<FieldRendererId, AutofillSuggestionTriggerSource> callback,
const FieldGlobalId& field_id,
AutofillSuggestionTriggerSource trigger_source);
void SendTypePredictionsToRenderer(
RoutedCallback<const std::vector<FormDataPredictions>&> callback,
const FormDataPredictions& type_predictions);
// Returns the underlying renderer forms of `browser_form`.
// Note that this function is intended for use outside of the `autofill`
// component to ensure compatibility with callers whose concept of a form
// does not include frame-transcending forms. It returns the constituent
// renderer forms regardless of their frames' origins and the field types.
std::vector<FormData> GetRendererForms(const FormData& browser_form) const;
private:
// Returns the driver of |frame| stored in |form_forest_|.
// Does not invalidate any forms in the FormForest.
AutofillDriver* DriverOfFrame(LocalFrameToken frame);
// Calls AutofillDriver::TriggerFormExtractionInDriverFrame() for all
// drivers in |form_forest_| except for |exception|.
void TriggerFormExtractionExcept(AutofillDriver& exception);
// The forest of forms. See its documentation for the usage protocol.
internal::FormForest form_forest_;
// When the focus moves to a different frame, the order of the events
// FocusOnNonFormField() and FocusOnFormField() may be reversed due to race
// conditions. We use these members to correct the order of the events.
LocalFrameToken focused_frame_;
bool focus_no_longer_on_form_has_fired_ = true;
// The maximum number of coexisting FormForest::FrameDatas over the lifetime
// of this factory.
// TODO: crbug.com/342132628 - Remove the counter and the metric.
size_t max_frame_datas_ = 0;
};
} // namespace autofill
#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_FOUNDATIONS_AUTOFILL_DRIVER_ROUTER_H_
|