Skip to content

Commit

Permalink
[Blink] Add FormControlType, is_content_editable to context menu params
Browse files Browse the repository at this point in the history
There's ongoing work to make the context menu an entry point for
Autofill.

This CL adds two new members to the context menu params for that
purpose:
- the clicked element's form control type, represented as
  Blink's form-control-type enum;
- a bool that indicates if the clicked element is contenteditable
  for Autofill's purposes.

The existing values in the ContextMenuParams did not suffice:
- ContextMenuParams::input_field_type is of type
  ContextMenuDataInputFieldType. This enum approximates
  FormControlType but lumps together <input type=text> and
  <textarea>.
- ContextMenuParams::is_editable is true for contenteditables
  but also in cases that Autofill wants to ignore.

A followup CL will remove the ContextMenuDataInputFieldType enum.

Bug: 1491569, 1484810
Change-Id: I1f14dfec6e6b36a42f263eb711d52c08510617ed
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4936654
Reviewed-by: Avi Drissman <avi@chromium.org>
Reviewed-by: Vidhan Jain <vidhanj@google.com>
Commit-Queue: Christoph Schwering <schwering@google.com>
Cr-Commit-Position: refs/heads/main@{#1212271}
  • Loading branch information
schwering authored and Chromium LUCI CQ committed Oct 19, 2023
1 parent 3c1935a commit 13c4d9d
Show file tree
Hide file tree
Showing 13 changed files with 165 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3297,7 +3297,7 @@ void RenderViewContextMenu::ExecuteCommand(int id, int event_flags) {
// TODO(b/305798770): Use appropriate parameters once the Autofill Form
// Extraction API is available.
compose_manager->OpenComposeFromContextMenu(
frame_token, autofill::FieldRendererId(*params_.field_renderer_id),
frame_token, autofill::FieldRendererId(params_.field_renderer_id),
gfx::RectF(params_.x, params_.y, 50, 50));
}
break;
Expand Down
49 changes: 33 additions & 16 deletions chrome/browser/ui/autofill/autofill_context_menu_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -49,24 +49,46 @@ constexpr char kFeedbackPlaceholder[] =
"\n"
"What happened instead? (Please include the screenshot below)";

bool ShouldShowAutofillContextMenu(const content::ContextMenuParams& params) {
if (!params.form_control_type) {
return false;
}
// Return true on text fields.
// TODO(crbug.com/1492339): Unify with functions from form_autofill_util.cc.
switch (*params.form_control_type) {
case blink::mojom::FormControlType::kInputEmail:
case blink::mojom::FormControlType::kInputMonth:
case blink::mojom::FormControlType::kInputNumber:
case blink::mojom::FormControlType::kInputPassword:
case blink::mojom::FormControlType::kInputSearch:
case blink::mojom::FormControlType::kInputTelephone:
case blink::mojom::FormControlType::kInputText:
case blink::mojom::FormControlType::kInputUrl:
case blink::mojom::FormControlType::kTextArea:
return true;
default:
return false;
}
}

base::Value::Dict LoadTriggerFormAndFieldLogs(
AutofillManager& manager,
const LocalFrameToken& frame_token,
const content::ContextMenuParams& params) {
if (!params.form_renderer_id) {
if (!ShouldShowAutofillContextMenu(params)) {
return base::Value::Dict();
}

FormGlobalId form_global_id = {frame_token,
FormRendererId(*params.form_renderer_id)};
FormRendererId(params.form_renderer_id)};

base::Value::Dict trigger_form_logs;
if (FormStructure* form = manager.FindCachedFormById(form_global_id)) {
trigger_form_logs.Set("triggerFormSignature", form->FormSignatureAsStr());

if (params.field_renderer_id) {
if (params.form_control_type) {
FieldGlobalId field_global_id = {
frame_token, FieldRendererId(*params.field_renderer_id)};
frame_token, FieldRendererId(params.field_renderer_id)};
auto field =
base::ranges::find_if(*form, [&field_global_id](const auto& field) {
return field->global_id() == field_global_id;
Expand Down Expand Up @@ -125,16 +147,12 @@ void AutofillContextMenuManager::AppendItems() {
if (!driver || !driver->CanShowAutofillUi())
return;

if (params_.field_renderer_id) {
if (ShouldShowAutofillContextMenu(params_)) {
const LocalFrameToken frame_token = driver->GetFrameToken();
// Formless fields have default form renderer id.
FormGlobalId form_global_id = {
frame_token, params_.form_renderer_id
? FormRendererId(*params_.form_renderer_id)
: FormRendererId()};
driver->OnContextMenuShownInField(
form_global_id,
{frame_token, FieldRendererId(*params_.field_renderer_id)});
{frame_token, FormRendererId(params_.form_renderer_id)},
{frame_token, FieldRendererId(params_.field_renderer_id)});
}

// Includes the option of submitting feedback on Autofill.
Expand Down Expand Up @@ -232,7 +250,7 @@ void AutofillContextMenuManager::

bool AutofillContextMenuManager::ShouldAddAutofillManualFallbackItem(
ContentAutofillDriver& driver) {
if (!params_.field_renderer_id) {
if (!ShouldShowAutofillContextMenu(params_)) {
// Autofill entries are only available in input or text area fields
return false;
}
Expand Down Expand Up @@ -286,12 +304,11 @@ void AutofillContextMenuManager::LogManualFallbackContextMenuEntryShown(
AutofillField* AutofillContextMenuManager::GetAutofillField(
AutofillManager& manager,
const LocalFrameToken& frame_token) const {
// Formless forms don't have a renderer ID.
CHECK(ShouldShowAutofillContextMenu(params_));
FormStructure* form = manager.FindCachedFormById(
{frame_token, FormRendererId(params_.form_renderer_id.value_or(0))});
CHECK(params_.field_renderer_id);
{frame_token, FormRendererId(params_.form_renderer_id)});
return form ? form->GetFieldById(
{frame_token, FieldRendererId(*params_.field_renderer_id)})
{frame_token, FieldRendererId(params_.field_renderer_id)})
: nullptr;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ content::ContextMenuParams CreateContextMenuParams(
rv.is_editable = true;
rv.page_url = GURL("http://test.page/");
rv.input_field_type = blink::mojom::ContextMenuDataInputFieldType::kPlainText;
rv.form_control_type = blink::mojom::FormControlType::kInputText;
if (form_renderer_id) {
rv.form_renderer_id = form_renderer_id->value();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ content::ContextMenuParams CreateContextMenuParams(
rv.is_editable = true;
rv.page_url = GURL("http://test.page/");
rv.input_field_type = blink::mojom::ContextMenuDataInputFieldType::kPlainText;
rv.form_control_type = blink::mojom::FormControlType::kInputText;
if (form_renderer_id) {
rv.form_renderer_id = form_renderer_id->value();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ bool StructTraits<blink::mojom::UntrustworthyContextMenuParamsDataView,
!data.ReadSourceType(&out->source_type) ||
!data.ReadInputFieldType(&out->input_field_type) ||
!data.ReadSelectionRect(&out->selection_rect) ||
!data.ReadFormRendererId(&out->form_renderer_id) ||
!data.ReadFieldRendererId(&out->field_renderer_id))
!data.ReadFormControlType(&out->form_control_type)) {
return false;
}

out->x = data.x();
out->y = data.y();
Expand All @@ -66,6 +66,10 @@ bool StructTraits<blink::mojom::UntrustworthyContextMenuParamsDataView,
out->selection_start_offset = data.selection_start_offset();
out->opened_from_highlight = data.opened_from_highlight();
out->is_password_type_by_heuristics = data.is_password_type_by_heuristics();
out->is_content_editable_for_autofill =
data.is_content_editable_for_autofill();
out->form_renderer_id = data.form_renderer_id();
out->field_renderer_id = data.field_renderer_id();
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,11 @@ UntrustworthyContextMenuParams ContextMenuParamsBuilder::Build(
if (data.impression)
params.impression = data.impression;

if (data.form_renderer_id)
params.form_renderer_id = data.form_renderer_id;

if (data.field_renderer_id)
params.field_renderer_id = data.field_renderer_id;
params.form_control_type = data.form_control_type;
params.is_content_editable_for_autofill =
data.is_content_editable_for_autofill;
params.field_renderer_id = data.field_renderer_id;
params.form_renderer_id = data.form_renderer_id;

params.source_type = static_cast<ui::MenuSourceType>(data.source_type);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,10 @@ void UntrustworthyContextMenuParams::Assign(
selection_rect = other.selection_rect;
selection_start_offset = other.selection_start_offset;
opened_from_highlight = other.opened_from_highlight;
form_renderer_id = other.form_renderer_id;
form_control_type = other.form_control_type;
is_content_editable_for_autofill = other.is_content_editable_for_autofill;
field_renderer_id = other.field_renderer_id;
form_renderer_id = other.form_renderer_id;
}

UntrustworthyContextMenuParams::~UntrustworthyContextMenuParams() = default;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "third_party/blink/public/common/input/web_menu_source_type.h"
#include "third_party/blink/public/common/navigation/impression.h"
#include "third_party/blink/public/mojom/context_menu/context_menu.mojom-shared.h"
#include "third_party/blink/public/mojom/forms/form_control_type.mojom-shared.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "url/gurl.h"
Expand Down Expand Up @@ -166,12 +167,27 @@ struct ContextMenuData {
// TextFragmentAnchor.
bool opened_from_highlight = false;

// The form's renderer id if the context menu is triggered on the form.
absl::optional<uint64_t> form_renderer_id;

// The field's renderer id if the context menu is triggered on an input
// field or a textarea field.
absl::optional<uint64_t> field_renderer_id;
// The type of the form control element on which the context menu is invoked,
// if any.
std::optional<mojom::FormControlType> form_control_type;

// Indicates whether the context menu is invoked on a non-form,
// non-form-control element that is contenteditable. Thus, it is mutually
// exclusive with `form_control_type`.
// TODO(crbug.com/1427131): Only true if AutofillUseDomNodeIdForRendererId
// is enabled.
bool is_content_editable_for_autofill = false;

// Identifies the element the context menu was invoked on if either
// `form_control_type` is engaged or `is_content_editable_for_autofill` is
// true.
// See `autofill::FieldRendererId` for the semantics of renderer IDs.
uint64_t field_renderer_id = 0;

// Identifies form to which the field identified by `field_renderer_id` is
// associated.
// See `autofill::FormRendererId` for the semantics of renderer IDs.
uint64_t form_renderer_id = 0;

ContextMenuData()
: media_type(blink::mojom::ContextMenuDataMediaType::kNone),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "third_party/blink/public/common/common_export.h"
#include "third_party/blink/public/common/context_menu_data/untrustworthy_context_menu_params.h"
#include "third_party/blink/public/mojom/context_menu/context_menu.mojom.h"
#include "third_party/blink/public/mojom/forms/form_control_type.mojom-shared.h"
#include "url/mojom/url_gurl_mojom_traits.h"

namespace mojo {
Expand Down Expand Up @@ -184,16 +185,26 @@ struct BLINK_COMMON_EXPORT
return r.opened_from_highlight;
}

static const absl::optional<uint64_t>& form_renderer_id(
static std::optional<blink::mojom::FormControlType> form_control_type(
const blink::UntrustworthyContextMenuParams& r) {
return r.form_renderer_id;
return r.form_control_type;
}

static bool is_content_editable_for_autofill(
const blink::UntrustworthyContextMenuParams& r) {
return r.is_content_editable_for_autofill;
}

static const absl::optional<uint64_t>& field_renderer_id(
static uint64_t field_renderer_id(
const blink::UntrustworthyContextMenuParams& r) {
return r.field_renderer_id;
}

static uint64_t form_renderer_id(
const blink::UntrustworthyContextMenuParams& r) {
return r.form_renderer_id;
}

static bool Read(blink::mojom::UntrustworthyContextMenuParamsDataView r,
blink::UntrustworthyContextMenuParams* out);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/navigation/impression.h"
#include "third_party/blink/public/mojom/context_menu/context_menu.mojom-forward.h"
#include "third_party/blink/public/mojom/forms/form_control_type.mojom-shared.h"
#include "ui/base/ui_base_types.h"
#include "ui/gfx/geometry/rect.h"
#include "url/gurl.h"
Expand Down Expand Up @@ -143,14 +144,27 @@ struct BLINK_COMMON_EXPORT UntrustworthyContextMenuParams {
// highlight/fragment.
bool opened_from_highlight = false;

// The context menu was opened on an input or textarea field. Denotes the
// renderer id of the form containing the input or the textarea field.
// `absl::nullopt` if the click was not on an input field or a formless field.
absl::optional<uint64_t> form_renderer_id;

// The context menu was opened on an input or textarea field.
// Otherwise, `absl::nullopt`.
absl::optional<uint64_t> field_renderer_id;
// The type of the form control element on which the context menu is invoked,
// if any.
std::optional<mojom::FormControlType> form_control_type;

// Indicates whether the context menu is invoked on a non-form,
// non-form-control element that is contenteditable. Thus, it is mutually
// exclusive with `form_control_type`.
// TODO(crbug.com/1427131): Only true if AutofillUseDomNodeIdForRendererId
// is enabled.
bool is_content_editable_for_autofill = false;

// Identifies the element the context menu was invoked on if either
// `form_control_type` is engaged or `is_content_editable_for_autofill` is
// true.
// See `autofill::FieldRendererId` for the semantics of renderer IDs.
uint64_t field_renderer_id = 0;

// Identifies form to which the field identified by `field_renderer_id` is
// associated.
// See `autofill::FormRendererId` for the semantics of renderer IDs.
uint64_t form_renderer_id = 0;

private:
void Assign(const UntrustworthyContextMenuParams& other);
Expand Down
29 changes: 22 additions & 7 deletions third_party/blink/public/mojom/context_menu/context_menu.mojom
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module blink.mojom;
import "mojo/public/mojom/base/string16.mojom";
import "services/network/public/mojom/referrer_policy.mojom";
import "third_party/blink/public/mojom/conversions/conversions.mojom";
import "third_party/blink/public/mojom/forms/form_control_type.mojom";
import "ui/base/mojom/ui_base_types.mojom";
import "ui/gfx/geometry/mojom/geometry.mojom";
import "url/mojom/url.mojom";
Expand Down Expand Up @@ -209,13 +210,27 @@ struct UntrustworthyContextMenuParams {
// See TextFragmentAnchor.
bool opened_from_highlight;

// The renderer id of the form that contains the input or textarea field.
// Not set if the initiating field is not an input or textarea field.
FormRendererId? form_renderer_id;

// The renderer id of the input or textarea field from where the context menu
// is opened. Not set if it is not an input or text area field.
FieldRendererId? field_renderer_id;
// The type of the form control element on which the context menu is invoked,
// if any.
FormControlType? form_control_type;

// Indicates whether the context menu is invoked on a non-form,
// non-form-control element that is contenteditable. Thus, it is mutually
// exclusive with `form_control_type`.
// Only true if AutofillUseDomNodeIdForRendererId (crbug.com/1427131) is
// enabled.
bool is_content_editable_for_autofill;

// Identifies the element the context menu was invoked on if either
// `form_control_type` is engaged or `is_content_editable_for_autofill` is
// true.
// See `autofill::FieldRendererId` for the semantics of renderer IDs.
uint64 field_renderer_id;

// Identifies form to which the field identified by `field_renderer_id` is
// associated.
// See `autofill::FormRendererId` for the semantics of renderer IDs.
uint64 form_renderer_id;
};

// Defines methods for Context menu to commnicate from the renderer to the
Expand Down

0 comments on commit 13c4d9d

Please sign in to comment.