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
|
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/autofill/android/touch_to_fill_keyboard_suppressor.h"
#include "base/check_op.h"
#include "components/autofill/content/browser/content_autofill_client.h"
#include "components/autofill/content/browser/content_autofill_driver.h"
#include "content/public/browser/render_widget_host.h"
namespace autofill {
TouchToFillKeyboardSuppressor::TouchToFillKeyboardSuppressor(
ContentAutofillClient* autofill_client,
base::RepeatingCallback<bool(AutofillManager&)> is_showing,
base::RepeatingCallback<
bool(AutofillManager&, FormGlobalId, FieldGlobalId, const FormData&)>
intends_to_show,
base::TimeDelta timeout)
: is_showing_(std::move(is_showing)),
intends_to_show_(std::move(intends_to_show)),
timeout_(timeout) {
// The keyboard suppressor behaves properly only if no AutofillDrivers (and no
// AutofillManagers) have been created yet.
CHECK_EQ(autofill_client->GetAutofillDriverFactory().num_drivers(), 0u);
driver_factory_observation_.Observe(
&autofill_client->GetAutofillDriverFactory());
}
TouchToFillKeyboardSuppressor::~TouchToFillKeyboardSuppressor() {
Unsuppress();
CHECK(!is_suppressing());
}
void TouchToFillKeyboardSuppressor::OnContentAutofillDriverFactoryDestroyed(
ContentAutofillDriverFactory& factory) {
Unsuppress();
driver_factory_observation_.Reset();
}
void TouchToFillKeyboardSuppressor::OnContentAutofillDriverCreated(
ContentAutofillDriverFactory& factory,
ContentAutofillDriver& driver) {
// GetRenderWidgetHost() returns the RWH attached to `rfh` or the nearest
// ancestor frame. Since the ancestor frames have been processed by this
// function already, the callback has been registered with `rwh` already iff
// the parent frame's RWH is identical to `rwh`.
content::RenderFrameHost* rfh = driver.render_frame_host();
DCHECK_EQ(rfh->GetParent() != nullptr, driver.GetParent() != nullptr);
content::RenderWidgetHost* rwh = rfh->GetRenderWidgetHost();
if (!rfh->GetParent() || rfh->GetParent()->GetRenderWidgetHost() != rwh) {
// We don't need to call RWH::RemoveSuppressShowingImeCallback(): it's
// memory-safe due to the WeakPtr, and it's not a memory leak because
// TouchToFillKeyboardSuppressor's lifecycle is aligned with the tab.
rwh->AddSuppressShowingImeCallback(base::BindRepeating(
[](base::WeakPtr<TouchToFillKeyboardSuppressor> self) {
return self && self->is_suppressing();
},
weak_ptr_factory_.GetWeakPtr()));
}
autofill_manager_observations_.AddObservation(&driver.GetAutofillManager());
}
void TouchToFillKeyboardSuppressor::OnAutofillManagerStateChanged(
AutofillManager& manager,
AutofillManager::LifecycleState old_state,
AutofillManager::LifecycleState new_state) {
switch (new_state) {
case AutofillManager::LifecycleState::kInactive:
case AutofillManager::LifecycleState::kActive:
case AutofillManager::LifecycleState::kPendingReset:
break;
case AutofillManager::LifecycleState::kPendingDeletion:
if (suppressed_manager_.get() == &manager) {
Unsuppress();
}
autofill_manager_observations_.RemoveObservation(&manager);
break;
}
}
void TouchToFillKeyboardSuppressor::OnBeforeAskForValuesToFill(
AutofillManager& manager,
FormGlobalId form_id,
FieldGlobalId field_id,
const FormData& form_data) {
if (is_showing_.Run(manager) ||
intends_to_show_.Run(manager, form_id, field_id, form_data)) {
Suppress(manager);
} else {
Unsuppress();
}
}
void TouchToFillKeyboardSuppressor::OnAfterAskForValuesToFill(
AutofillManager& manager,
FormGlobalId form_id,
FieldGlobalId field_id) {
if (is_showing_.Run(manager)) {
KeepSuppressing();
} else {
Unsuppress();
}
}
void TouchToFillKeyboardSuppressor::Suppress(AutofillManager& manager) {
if (suppressed_manager_.get() == &manager) {
return;
}
Unsuppress();
suppressed_manager_ = &manager;
unsuppress_timer_.Start(FROM_HERE, timeout_, this,
&TouchToFillKeyboardSuppressor::Unsuppress);
}
void TouchToFillKeyboardSuppressor::Unsuppress() {
if (!suppressed_manager_) {
return;
}
suppressed_manager_ = nullptr;
unsuppress_timer_.Stop();
}
} // namespace autofill
|