chore: cleanup autofill agent shutdown sequence (#36954)

This commit is contained in:
Shelley Vohr 2023-01-20 23:35:06 +01:00 committed by GitHub
parent 3b018143b4
commit c3f02d7df2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 66 additions and 48 deletions

View file

@ -4,6 +4,7 @@
#include "shell/renderer/electron_autofill_agent.h" #include "shell/renderer/electron_autofill_agent.h"
#include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -20,9 +21,23 @@
namespace electron { namespace electron {
namespace { namespace {
const size_t kMaxDataLength = 1024; const size_t kMaxStringLength = 1024;
const size_t kMaxListSize = 512; const size_t kMaxListSize = 512;
// Copied from components/autofill/content/renderer/form_autofill_util.cc
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& string : *strings) {
if (string.length() > kMaxStringLength)
string.resize(kMaxStringLength);
}
}
// Copied from components/autofill/content/renderer/form_autofill_util.cc.
void GetDataListSuggestions(const blink::WebInputElement& element, void GetDataListSuggestions(const blink::WebInputElement& element,
std::vector<std::u16string>* values, std::vector<std::u16string>* values,
std::vector<std::u16string>* labels) { std::vector<std::u16string>* labels) {
@ -33,19 +48,11 @@ void GetDataListSuggestions(const blink::WebInputElement& element,
else else
labels->push_back(std::u16string()); labels->push_back(std::u16string());
} }
TrimStringVectorForIPC(values);
TrimStringVectorForIPC(labels);
} }
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 } // namespace
AutofillAgent::AutofillAgent(content::RenderFrame* frame, AutofillAgent::AutofillAgent(content::RenderFrame* frame,
@ -53,18 +60,26 @@ AutofillAgent::AutofillAgent(content::RenderFrame* frame,
: content::RenderFrameObserver(frame) { : content::RenderFrameObserver(frame) {
render_frame()->GetWebFrame()->SetAutofillClient(this); render_frame()->GetWebFrame()->SetAutofillClient(this);
registry->AddInterface<mojom::ElectronAutofillAgent>(base::BindRepeating( registry->AddInterface<mojom::ElectronAutofillAgent>(base::BindRepeating(
&AutofillAgent::BindReceiver, base::Unretained(this))); &AutofillAgent::BindPendingReceiver, base::Unretained(this)));
} }
AutofillAgent::~AutofillAgent() = default; AutofillAgent::~AutofillAgent() = default;
void AutofillAgent::BindReceiver( void AutofillAgent::BindPendingReceiver(
mojo::PendingAssociatedReceiver<mojom::ElectronAutofillAgent> receiver) { mojo::PendingAssociatedReceiver<mojom::ElectronAutofillAgent>
receiver_.Bind(std::move(receiver)); pending_receiver) {
receiver_.Bind(std::move(pending_receiver));
} }
void AutofillAgent::OnDestruct() { void AutofillAgent::OnDestruct() {
delete this; Shutdown();
base::SingleThreadTaskRunner::GetCurrentDefault()->DeleteSoon(FROM_HERE,
this);
}
void AutofillAgent::Shutdown() {
receiver_.reset();
weak_ptr_factory_.InvalidateWeakPtrs();
} }
void AutofillAgent::DidChangeScrollOffset() { void AutofillAgent::DidChangeScrollOffset() {
@ -94,9 +109,7 @@ void AutofillAgent::TextFieldDidChange(
void AutofillAgent::TextFieldDidChangeImpl( void AutofillAgent::TextFieldDidChangeImpl(
const blink::WebFormControlElement& element) { const blink::WebFormControlElement& element) {
ShowSuggestionsOptions options; ShowSuggestions(element, {.requires_caret_at_end = true});
options.requires_caret_at_end = true;
ShowSuggestions(element, options);
} }
void AutofillAgent::TextFieldDidReceiveKeyDown( void AutofillAgent::TextFieldDidReceiveKeyDown(
@ -104,18 +117,14 @@ void AutofillAgent::TextFieldDidReceiveKeyDown(
const blink::WebKeyboardEvent& event) { const blink::WebKeyboardEvent& event) {
if (event.windows_key_code == ui::VKEY_DOWN || if (event.windows_key_code == ui::VKEY_DOWN ||
event.windows_key_code == ui::VKEY_UP) { event.windows_key_code == ui::VKEY_UP) {
ShowSuggestionsOptions options; ShowSuggestions(element, {.autofill_on_empty_values = true,
options.autofill_on_empty_values = true; .requires_caret_at_end = true});
options.requires_caret_at_end = true;
ShowSuggestions(element, options);
} }
} }
void AutofillAgent::OpenTextDataListChooser( void AutofillAgent::OpenTextDataListChooser(
const blink::WebInputElement& element) { const blink::WebInputElement& element) {
ShowSuggestionsOptions options; ShowSuggestions(element, {.autofill_on_empty_values = true});
options.autofill_on_empty_values = true;
ShowSuggestions(element, options);
} }
void AutofillAgent::DataListOptionsChanged( void AutofillAgent::DataListOptionsChanged(
@ -123,31 +132,35 @@ void AutofillAgent::DataListOptionsChanged(
if (!element.Focused()) if (!element.Focused())
return; return;
ShowSuggestionsOptions options; ShowSuggestions(element, {.requires_caret_at_end = true});
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, void AutofillAgent::ShowSuggestions(const blink::WebFormControlElement& element,
const ShowSuggestionsOptions& options) { const ShowSuggestionsOptions& options) {
if (!element.IsEnabled() || element.IsReadOnly()) if (!element.IsEnabled() || element.IsReadOnly())
return; return;
if (!element.SuggestedValue().IsEmpty())
return;
const blink::WebInputElement input_element = const blink::WebInputElement input_element =
element.DynamicTo<blink::WebInputElement>(); element.DynamicTo<blink::WebInputElement>();
if (!input_element.IsNull()) { if (!input_element.IsNull()) {
if (!input_element.IsTextField()) if (!input_element.IsTextField())
return; return;
if (!input_element.SuggestedValue().IsEmpty())
return;
} }
// Don't attempt to autofill with values that are too large or if filling
// criteria are not met. Keyboard Accessory may still be shown when the
// |value| is empty, do not attempt to hide it.
blink::WebString value = element.EditingValue(); blink::WebString value = element.EditingValue();
if (value.length() > kMaxDataLength || if (value.length() > kMaxStringLength ||
(!options.autofill_on_empty_values && value.IsEmpty()) || (!options.autofill_on_empty_values && value.IsEmpty()) ||
(options.requires_caret_at_end && (options.requires_caret_at_end &&
(element.SelectionStart() != element.SelectionEnd() || (element.SelectionStart() != element.SelectionEnd() ||
element.SelectionEnd() != static_cast<int>(value.length())))) { element.SelectionEnd() != static_cast<int>(value.length())))) {
// Any popup currently showing is obsolete.
HidePopup(); HidePopup();
return; return;
} }
@ -156,8 +169,6 @@ void AutofillAgent::ShowSuggestions(const blink::WebFormControlElement& element,
std::vector<std::u16string> data_list_labels; std::vector<std::u16string> data_list_labels;
if (!input_element.IsNull()) { if (!input_element.IsNull()) {
GetDataListSuggestions(input_element, &data_list_values, &data_list_labels); 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); ShowPopup(element, data_list_values, data_list_labels);
@ -165,11 +176,12 @@ void AutofillAgent::ShowSuggestions(const blink::WebFormControlElement& element,
void AutofillAgent::DidReceiveLeftMouseDownOrGestureTapInNode( void AutofillAgent::DidReceiveLeftMouseDownOrGestureTapInNode(
const blink::WebNode& node) { const blink::WebNode& node) {
focused_node_was_last_clicked_ = !node.IsNull() && node.Focused(); DCHECK(!node.IsNull());
focused_node_was_last_clicked_ = node.Focused();
} }
void AutofillAgent::DidCompleteFocusChangeInFrame() { void AutofillAgent::DidCompleteFocusChangeInFrame() {
DoFocusChangeComplete(); HandleFocusChangeComplete();
} }
bool AutofillAgent::IsUserGesture() const { bool AutofillAgent::IsUserGesture() const {
@ -197,18 +209,16 @@ void AutofillAgent::AcceptDataListSuggestion(const std::u16string& suggestion) {
} }
} }
void AutofillAgent::DoFocusChangeComplete() { void AutofillAgent::HandleFocusChangeComplete() {
auto element = render_frame()->GetWebFrame()->GetDocument().FocusedElement(); auto element = render_frame()->GetWebFrame()->GetDocument().FocusedElement();
if (element.IsNull() || !element.IsFormControlElement()) if (element.IsNull() || !element.IsFormControlElement())
return; return;
if (focused_node_was_last_clicked_ && was_focused_before_now_) { if (focused_node_was_last_clicked_ && was_focused_before_now_) {
ShowSuggestionsOptions options;
options.autofill_on_empty_values = true;
blink::WebInputElement input_element = blink::WebInputElement input_element =
element.DynamicTo<blink::WebInputElement>(); element.DynamicTo<blink::WebInputElement>();
if (!input_element.IsNull()) if (!input_element.IsNull())
ShowSuggestions(input_element, options); ShowSuggestions(input_element, {.autofill_on_empty_values = true});
} }
was_focused_before_now_ = true; was_focused_before_now_ = true;

View file

@ -33,8 +33,9 @@ class AutofillAgent : public content::RenderFrameObserver,
AutofillAgent(const AutofillAgent&) = delete; AutofillAgent(const AutofillAgent&) = delete;
AutofillAgent& operator=(const AutofillAgent&) = delete; AutofillAgent& operator=(const AutofillAgent&) = delete;
void BindReceiver( void BindPendingReceiver(
mojo::PendingAssociatedReceiver<mojom::ElectronAutofillAgent> receiver); mojo::PendingAssociatedReceiver<mojom::ElectronAutofillAgent>
pending_receiver);
// content::RenderFrameObserver: // content::RenderFrameObserver:
void OnDestruct() override; void OnDestruct() override;
@ -47,11 +48,18 @@ class AutofillAgent : public content::RenderFrameObserver,
private: private:
struct ShowSuggestionsOptions { struct ShowSuggestionsOptions {
ShowSuggestionsOptions(); // Specifies that suggestions should be shown when |element| contains no
bool autofill_on_empty_values; // text.
bool requires_caret_at_end; bool autofill_on_empty_values{false};
// Specifies that suggestions should be shown when the caret is not
// after the last character in the element.
bool requires_caret_at_end{false};
}; };
// Shuts the AutofillAgent down on RenderFrame deletion. Safe to call multiple
// times.
void Shutdown();
// blink::WebAutofillClient: // blink::WebAutofillClient:
void TextFieldDidEndEditing(const blink::WebInputElement&) override; void TextFieldDidEndEditing(const blink::WebInputElement&) override;
void TextFieldDidChange(const blink::WebFormControlElement&) override; void TextFieldDidChange(const blink::WebFormControlElement&) override;
@ -72,7 +80,7 @@ class AutofillAgent : public content::RenderFrameObserver,
void ShowSuggestions(const blink::WebFormControlElement& element, void ShowSuggestions(const blink::WebFormControlElement& element,
const ShowSuggestionsOptions& options); const ShowSuggestionsOptions& options);
void DoFocusChangeComplete(); void HandleFocusChangeComplete();
const mojo::AssociatedRemote<mojom::ElectronAutofillDriver>& const mojo::AssociatedRemote<mojom::ElectronAutofillDriver>&
GetAutofillDriver(); GetAutofillDriver();