electron/shell/renderer/electron_autofill_agent.cc
electron-roller[bot] 3da598015b
chore: bump chromium to 100.0.4894.0 (main) (#32852)
* chore: bump chromium in DEPS to 100.0.4880.0

* resolve conflicts

* chore: update patches

* fix patch

* PIP20: add a new DocumentOverlayWindowViews subtype

https://chromium-review.googlesource.com/c/chromium/src/+/3252789

* Clean up PictureInPictureWindowManager::EnterPictureInPicture()

https://chromium-review.googlesource.com/c/chromium/src/+/3424145

* Remove StoragePartitionId.

https://chromium-review.googlesource.com/c/chromium/src/+/2811120

* Remove FLoC code

https://chromium-review.googlesource.com/c/chromium/src/+/3424359

* media: Make AddSupportedKeySystems() Async

https://chromium-review.googlesource.com/c/chromium/src/+/3430502

* [Extensions] Move some l10n file util methods to //extensions/browser

https://chromium-review.googlesource.com/c/chromium/src/+/3408192

* chore: IWYU

* Reland "webhid: Grant permissions for policy-allowed devices"

https://chromium-review.googlesource.com/c/chromium/src/+/3444147

* Migrate base::Value::GetList() to base::Value::GetListDeprecated(): 2/N.

https://chromium-review.googlesource.com/c/chromium/src/+/3435727
https://chromium-review.googlesource.com/c/chromium/src/+/3440910
https://chromium-review.googlesource.com/c/chromium/src/+/3440088

* [text blink period] Cache blink period instead of fetching from defaults

https://chromium-review.googlesource.com/c/chromium/src/+/3419059

* chore: update picture-in-picture.patch

https://chromium-review.googlesource.com/c/chromium/src/+/3252789

* ci: update to Xcode 13.2.1

https://chromium-review.googlesource.com/c/chromium/src/+/3437552

* chore: bump chromium in DEPS to 100.0.4882.1

* chore: update patches

* chore: bump chromium in DEPS to 100.0.4884.0

* chore: update patches

* chore: bump chromium in DEPS to 100.0.4886.0

* chore: update patches

* Refactor DownloadManager to use StoragePartitionConfig

https://chromium-review.googlesource.com/c/chromium/src/+/3222011

* Remove ToWebInputElement() in favor of new WebNode::DynamicTo<> helpers.

https://chromium-review.googlesource.com/c/chromium/src/+/3433852

* refactor: autofill to use the color pipeline

https://bugs.chromium.org/p/chromium/issues/detail?id=1249558
https://bugs.chromium.org/p/chromium/issues/detail?id=1003612

* [ProcessSingleton] Add many more trace events to cover all scenarios

https://chromium-review.googlesource.com/c/chromium/src/+/3429325

* fixup! PIP20: add a new DocumentOverlayWindowViews subtype

* chore: bump chromium in DEPS to 100.0.4888.0

* chore: update patches

* chore: update picture-in-picture.patch

* fixup! refactor: autofill to use the color pipeline

* ci: fixup fix sync

(cherry picked from commit c1e3e395465739bce5ca8e1c5ec1f5bd72b99ebd)

* chore: bump chromium in DEPS to 100.0.4889.0

* chore: update patches

* chore: fix feat_add_data_transfer_to_requestsingleinstancelock.patch

* fixup! PIP20: add a new DocumentOverlayWindowViews subtype

* Remove remaining NativeTheme::GetSystemColor() machinery.

https://chromium-review.googlesource.com/c/chromium/src/+/3421719

* ci: fetch proper esbuild for macos

* ci: fixup fetch proper esbuild for macos

* fix: failing Node.js test on outdated CurrentValueSerializerFormatVersion

* chore: bump chromium in DEPS to 100.0.4892.0

* 3460365: Set V8 fatal error callbacks during Isolate initialization

https://chromium-review.googlesource.com/c/chromium/src/+/3460365

* 3454343: PIP20: use permanent top controls

https://chromium-review.googlesource.com/c/chromium/src/+/3454343

* 3465574: Move most of GTK color mixers to ui/color/.

https://chromium-review.googlesource.com/c/chromium/src/+/3465574

* chore: fixup patch indices

* 3445327: [locales] Remove locales reference

https://chromium-review.googlesource.com/c/chromium/src/+/3445327

* 3456548: [DBB][#7] Blue border falls back to all tab if cropped-to zero pixels

https://chromium-review.googlesource.com/c/chromium/src/+/3456548

* 3441196: Convert GuestView's remaining legacy IPC messages to Mojo

https://chromium-review.googlesource.com/c/chromium/src/+/3441196

* 3455491: Don't include run_loop.h in thread_task_runner_handle.h

https://chromium-review.googlesource.com/c/chromium/src/+/3455491

* fixup! 3454343: PIP20: use permanent top controls

* 3442501: Add missing includes of //base/observer_list.h

https://chromium-review.googlesource.com/c/chromium/src/+/3442501

* 3437552: mac: Deploy a new hermetic build of Xcode 13.2.1 13C100

https://chromium-review.googlesource.com/c/chromium/src/+/3437552

* chore: bump chromium in DEPS to 100.0.4894.0

* fixup! 3460365: Set V8 fatal error callbacks during Isolate initialization

* chore: update patches

* 3425231: Use DnsOverHttpsConfig where appropriate

https://chromium-review.googlesource.com/c/chromium/src/+/3425231

* test: disable test-heapsnapshot-near-heap-limit-worker.js

As a result of CLs linked in https://bugs.chromium.org/p/v8/issues/detail?id=12503,
heap snapshotting near the heap limit DCHECKS in Node.js specs. This will
likely require a larger refactor in Node.js so i've disabled the test for
now and opened an upstream issue on node-v8 issue
at https://github.com/nodejs/node-v8/issues/218.

* Port all usage of NativeTheme color IDs to color pipeline

https://bugs.chromium.org/p/chromium/issues/detail?id=1249558

* chore: update patches after rebase

* ci: use gen2 machine for more disk space

* ci: don't try to make root volume writeable

* ci: use older xcode/macos for tests

* fix: html fullscreen transitions stacking

(cherry picked from commit 5e10965cdd7b2a024def5fc568912cefd0f05b44)

* ci: speed up woa testing

(cherry picked from commit 75c33c48b032137794f5734348a9ee3daa60d9de)
(cherry picked from commit e81996234029669663bf0daaababd34684dcbb17)

* ci: disable flaky tests on WOA

* ci: run remote tests separately to isolate issue there

* tests: disable node test parallel/test-worker-debug for now

* revert: fix: html fullscreen transitions stacking

* tests: disable flaky test on macOS arm64

* fixup circleci config so build tools can find xcode version

* make sure the workspace is clean before job runs

(cherry picked from commit 75f713c9748ac1a356846c39f268886130554fd6)

* tests: disable flaky test on Linux

* ci: debug why windows i32 is crashing

* Revert "ci: debug why windows i32 is crashing"

This reverts commit 4c4bba87ea76f16ef3b304dadff59ad4d366f60f.

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: Jeremy Rose <nornagon@nornagon.net>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: deepak1556 <hop2deep@gmail.com>
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2022-02-25 13:17:35 -05:00

229 lines
7.4 KiB
C++

// Copyright (c) 2017 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "shell/renderer/electron_autofill_agent.h"
#include <utility>
#include <vector>
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/input/web_keyboard_event.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_option_element.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/geometry/rect_f.h"
namespace electron {
namespace {
const size_t kMaxDataLength = 1024;
const size_t kMaxListSize = 512;
void GetDataListSuggestions(const blink::WebInputElement& element,
std::vector<std::u16string>* values,
std::vector<std::u16string>* labels) {
for (const auto& option : element.FilteredDataListOptions()) {
values->push_back(option.Value().Utf16());
if (option.Value() != option.Label())
labels->push_back(option.Label().Utf16());
else
labels->push_back(std::u16string());
}
}
void TrimStringVectorForIPC(std::vector<std::u16string>* strings) {
// Limit the size of the vector.
if (strings->size() > kMaxListSize)
strings->resize(kMaxListSize);
// Limit the size of the strings in the vector.
for (auto& str : *strings) {
if (str.length() > kMaxDataLength)
str.resize(kMaxDataLength);
}
}
} // namespace
AutofillAgent::AutofillAgent(content::RenderFrame* frame,
blink::AssociatedInterfaceRegistry* registry)
: content::RenderFrameObserver(frame) {
render_frame()->GetWebFrame()->SetAutofillClient(this);
registry->AddInterface(base::BindRepeating(&AutofillAgent::BindReceiver,
base::Unretained(this)));
}
AutofillAgent::~AutofillAgent() = default;
void AutofillAgent::BindReceiver(
mojo::PendingAssociatedReceiver<mojom::ElectronAutofillAgent> receiver) {
receiver_.Bind(std::move(receiver));
}
void AutofillAgent::OnDestruct() {
delete this;
}
void AutofillAgent::DidChangeScrollOffset() {
HidePopup();
}
void AutofillAgent::FocusedElementChanged(const blink::WebElement&) {
focused_node_was_last_clicked_ = false;
was_focused_before_now_ = false;
HidePopup();
}
void AutofillAgent::TextFieldDidEndEditing(const blink::WebInputElement&) {
HidePopup();
}
void AutofillAgent::TextFieldDidChange(
const blink::WebFormControlElement& element) {
if (!IsUserGesture() && !render_frame()->IsPasting())
return;
weak_ptr_factory_.InvalidateWeakPtrs();
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&AutofillAgent::TextFieldDidChangeImpl,
weak_ptr_factory_.GetWeakPtr(), element));
}
void AutofillAgent::TextFieldDidChangeImpl(
const blink::WebFormControlElement& element) {
ShowSuggestionsOptions options;
options.requires_caret_at_end = true;
ShowSuggestions(element, options);
}
void AutofillAgent::TextFieldDidReceiveKeyDown(
const blink::WebInputElement& element,
const blink::WebKeyboardEvent& event) {
if (event.windows_key_code == ui::VKEY_DOWN ||
event.windows_key_code == ui::VKEY_UP) {
ShowSuggestionsOptions options;
options.autofill_on_empty_values = true;
options.requires_caret_at_end = true;
ShowSuggestions(element, options);
}
}
void AutofillAgent::OpenTextDataListChooser(
const blink::WebInputElement& element) {
ShowSuggestionsOptions options;
options.autofill_on_empty_values = true;
ShowSuggestions(element, options);
}
void AutofillAgent::DataListOptionsChanged(
const blink::WebInputElement& element) {
if (!element.Focused())
return;
ShowSuggestionsOptions options;
options.requires_caret_at_end = true;
ShowSuggestions(element, options);
}
AutofillAgent::ShowSuggestionsOptions::ShowSuggestionsOptions()
: autofill_on_empty_values(false), requires_caret_at_end(false) {}
void AutofillAgent::ShowSuggestions(const blink::WebFormControlElement& element,
const ShowSuggestionsOptions& options) {
if (!element.IsEnabled() || element.IsReadOnly())
return;
const blink::WebInputElement input_element =
element.DynamicTo<blink::WebInputElement>();
if (!input_element.IsNull()) {
if (!input_element.IsTextField())
return;
}
blink::WebString value = element.EditingValue();
if (value.length() > kMaxDataLength ||
(!options.autofill_on_empty_values && value.IsEmpty()) ||
(options.requires_caret_at_end &&
(element.SelectionStart() != element.SelectionEnd() ||
element.SelectionEnd() != static_cast<int>(value.length())))) {
HidePopup();
return;
}
std::vector<std::u16string> data_list_values;
std::vector<std::u16string> data_list_labels;
if (!input_element.IsNull()) {
GetDataListSuggestions(input_element, &data_list_values, &data_list_labels);
TrimStringVectorForIPC(&data_list_values);
TrimStringVectorForIPC(&data_list_labels);
}
ShowPopup(element, data_list_values, data_list_labels);
}
void AutofillAgent::DidReceiveLeftMouseDownOrGestureTapInNode(
const blink::WebNode& node) {
focused_node_was_last_clicked_ = !node.IsNull() && node.Focused();
}
void AutofillAgent::DidCompleteFocusChangeInFrame() {
DoFocusChangeComplete();
}
bool AutofillAgent::IsUserGesture() const {
return render_frame()->GetWebFrame()->HasTransientUserActivation();
}
void AutofillAgent::HidePopup() {
GetAutofillDriver()->HideAutofillPopup();
}
void AutofillAgent::ShowPopup(const blink::WebFormControlElement& element,
const std::vector<std::u16string>& values,
const std::vector<std::u16string>& labels) {
gfx::RectF bounds = render_frame()->ElementBoundsInWindow(element);
GetAutofillDriver()->ShowAutofillPopup(bounds, values, labels);
}
void AutofillAgent::AcceptDataListSuggestion(const std::u16string& suggestion) {
auto element = render_frame()->GetWebFrame()->GetDocument().FocusedElement();
if (element.IsFormControlElement()) {
blink::WebInputElement input_element =
element.DynamicTo<blink::WebInputElement>();
if (!input_element.IsNull())
input_element.SetAutofillValue(blink::WebString::FromUTF16(suggestion));
}
}
void AutofillAgent::DoFocusChangeComplete() {
auto element = render_frame()->GetWebFrame()->GetDocument().FocusedElement();
if (element.IsNull() || !element.IsFormControlElement())
return;
if (focused_node_was_last_clicked_ && was_focused_before_now_) {
ShowSuggestionsOptions options;
options.autofill_on_empty_values = true;
blink::WebInputElement input_element =
element.DynamicTo<blink::WebInputElement>();
if (!input_element.IsNull())
ShowSuggestions(input_element, options);
}
was_focused_before_now_ = true;
focused_node_was_last_clicked_ = false;
}
const mojo::AssociatedRemote<mojom::ElectronAutofillDriver>&
AutofillAgent::GetAutofillDriver() {
if (!autofill_driver_) {
render_frame()->GetRemoteAssociatedInterfaces()->GetInterface(
&autofill_driver_);
}
return autofill_driver_;
}
} // namespace electron