blob: 60b056e7e22d92fa94a99b80edb7fa1a3048f78b [file] [log] [blame]
// Copyright 2017 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/android_autofill/browser/android_autofill_manager.h"
#include "base/containers/contains.h"
#include "base/memory/ptr_util.h"
#include "components/android_autofill/browser/autofill_provider.h"
#include "components/autofill/content/browser/content_autofill_driver.h"
#include "components/autofill/core/browser/metrics/form_events/form_event_logger_weblayer_android.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
namespace autofill {
using base::TimeTicks;
void AndroidDriverInitHook(AutofillClient* client,
ContentAutofillDriver* driver) {
driver->set_autofill_manager(
base::WrapUnique(new AndroidAutofillManager(driver, client)));
driver->GetAutofillAgent()->SetUserGestureRequired(false);
driver->GetAutofillAgent()->SetSecureContextRequired(true);
driver->GetAutofillAgent()->SetFocusRequiresScroll(false);
driver->GetAutofillAgent()->SetQueryPasswordSuggestion(true);
}
AndroidAutofillManager::AndroidAutofillManager(AutofillDriver* driver,
AutofillClient* client)
: AutofillManager(driver, client) {
StartNewLoggingSession();
}
AndroidAutofillManager::~AndroidAutofillManager() = default;
base::WeakPtr<AutofillManager> AndroidAutofillManager::GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
CreditCardAccessManager* AndroidAutofillManager::GetCreditCardAccessManager() {
return nullptr;
}
bool AndroidAutofillManager::ShouldClearPreviewedForm() {
return false;
}
void AndroidAutofillManager::FillCreditCardFormImpl(
const FormData& form,
const FormFieldData& field,
const CreditCard& credit_card,
const std::u16string& cvc,
AutofillTriggerSource trigger_source) {
NOTREACHED();
}
void AndroidAutofillManager::FillProfileFormImpl(
const FormData& form,
const FormFieldData& field,
const autofill::AutofillProfile& profile,
AutofillTriggerSource trigger_source) {
NOTREACHED();
}
void AndroidAutofillManager::OnFormSubmittedImpl(
const FormData& form,
bool known_success,
mojom::SubmissionSource source) {
address_logger_->OnWillSubmitForm();
payments_logger_->OnWillSubmitForm();
password_logger_->OnWillSubmitForm();
if (auto* provider = GetAutofillProvider())
provider->OnFormSubmitted(this, form, known_success, source);
}
void AndroidAutofillManager::OnTextFieldDidChangeImpl(
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box,
const TimeTicks timestamp) {
auto* provider = GetAutofillProvider();
if (!provider) {
return;
}
// We cannot use `field` is_autofilled state because it has already been
// cleared by blink. Check `provider` cache.
bool cached_is_autofilled = provider->GetCachedIsAutofilled(field);
provider->OnTextFieldDidChange(this, form, field, bounding_box, timestamp);
if (auto* logger = GetEventFormLogger(form, field)) {
if (cached_is_autofilled) {
logger->OnEditedAutofilledField();
} else {
logger->OnTypedIntoNonFilledField();
}
}
}
void AndroidAutofillManager::OnTextFieldDidScrollImpl(
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box) {
if (auto* provider = GetAutofillProvider())
provider->OnTextFieldDidScroll(this, form, field, bounding_box);
}
void AndroidAutofillManager::OnAskForValuesToFillImpl(
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box,
AutoselectFirstSuggestion autoselect_first_suggestion,
FormElementWasClicked form_element_was_clicked) {
auto* provider = GetAutofillProvider();
if (!provider) {
return;
}
provider->OnAskForValuesToFill(this, form, field, bounding_box,
autoselect_first_suggestion,
form_element_was_clicked);
if (auto* logger = GetEventFormLogger(form, field)) {
logger->OnDidInteractWithAutofillableForm();
}
}
void AndroidAutofillManager::OnFocusOnFormFieldImpl(
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box) {
if (auto* provider = GetAutofillProvider())
provider->OnFocusOnFormField(this, form, field, bounding_box);
}
void AndroidAutofillManager::OnSelectControlDidChangeImpl(
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box) {
if (auto* provider = GetAutofillProvider())
provider->OnSelectControlDidChange(this, form, field, bounding_box);
}
bool AndroidAutofillManager::ShouldParseForms() {
return true;
}
void AndroidAutofillManager::OnFocusNoLongerOnFormImpl(
bool had_interacted_form) {
if (auto* provider = GetAutofillProvider())
provider->OnFocusNoLongerOnForm(this, had_interacted_form);
}
void AndroidAutofillManager::OnDidFillAutofillFormDataImpl(
const FormData& form,
const base::TimeTicks timestamp) {
if (auto* provider = GetAutofillProvider())
provider->OnDidFillAutofillFormData(this, form, timestamp);
}
void AndroidAutofillManager::OnHidePopupImpl() {
if (auto* provider = GetAutofillProvider())
provider->OnHidePopup(this);
}
void AndroidAutofillManager::PropagateAutofillPredictions(
const std::vector<FormStructure*>& forms) {
has_server_prediction_ = true;
if (auto* provider = GetAutofillProvider())
provider->OnServerPredictionsAvailable(this);
}
void AndroidAutofillManager::OnFormProcessed(
const FormData& form,
const FormStructure& form_structure) {
DenseSet<FormType> form_types = form_structure.GetFormTypes();
for (FormType form_type : form_types) {
if (auto* logger = GetEventFormLogger(form_type)) {
logger->OnDidParseForm();
}
}
}
void AndroidAutofillManager::OnServerRequestError(
FormSignature form_signature,
AutofillDownloadManager::RequestType request_type,
int http_error) {
if (auto* provider = GetAutofillProvider())
provider->OnServerQueryRequestError(this, form_signature);
}
void AndroidAutofillManager::Reset() {
AutofillManager::Reset();
has_server_prediction_ = false;
if (auto* provider = GetAutofillProvider())
provider->Reset(this);
StartNewLoggingSession();
}
void AndroidAutofillManager::OnContextMenuShownInField(
const FormGlobalId& form_global_id,
const FieldGlobalId& field_global_id) {
// Not relevant for Android. Only called via context menu in Desktop.
NOTREACHED();
}
AutofillProvider* AndroidAutofillManager::GetAutofillProvider() {
if (autofill_provider_for_testing_)
return autofill_provider_for_testing_;
if (auto* rfh =
static_cast<ContentAutofillDriver*>(driver())->render_frame_host()) {
if (rfh->IsActive()) {
if (auto* web_contents = content::WebContents::FromRenderFrameHost(rfh)) {
return AutofillProvider::FromWebContents(web_contents);
}
}
}
return nullptr;
}
FieldTypeGroup AndroidAutofillManager::ComputeFieldTypeGroupForField(
const FormData& form,
const FormFieldData& field) {
FormStructure* form_structure = nullptr;
AutofillField* autofill_field = nullptr;
return GetCachedFormAndField(form, field, &form_structure, &autofill_field)
? autofill_field->Type().group()
: FieldTypeGroup::kNoGroup;
}
void AndroidAutofillManager::FillOrPreviewForm(
mojom::RendererFormDataAction action,
const FormData& form,
FieldTypeGroup field_type_group,
const url::Origin& triggered_origin) {
DCHECK_EQ(action, mojom::RendererFormDataAction::kFill);
driver()->FillOrPreviewForm(action, form, triggered_origin, {});
if (auto* logger = GetEventFormLogger(field_type_group)) {
logger->OnDidFillSuggestion();
}
}
void AndroidAutofillManager::StartNewLoggingSession() {
address_logger_ = std::make_unique<FormEventLoggerWeblayerAndroid>("Address");
payments_logger_ =
std::make_unique<FormEventLoggerWeblayerAndroid>("CreditCard");
password_logger_ =
std::make_unique<FormEventLoggerWeblayerAndroid>("Password");
}
FormEventLoggerWeblayerAndroid* AndroidAutofillManager::GetEventFormLogger(
const FormData& form,
const FormFieldData& field) {
return GetEventFormLogger(ComputeFieldTypeGroupForField(form, field));
}
FormEventLoggerWeblayerAndroid* AndroidAutofillManager::GetEventFormLogger(
FieldTypeGroup group) {
return GetEventFormLogger(FieldTypeGroupToFormType(group));
}
FormEventLoggerWeblayerAndroid* AndroidAutofillManager::GetEventFormLogger(
FormType form_type) {
switch (form_type) {
case FormType::kAddressForm:
return address_logger_.get();
case FormType::kCreditCardForm:
return payments_logger_.get();
case FormType::kPasswordForm:
return password_logger_.get();
case FormType::kUnknownFormType:
return nullptr;
}
NOTREACHED();
return nullptr;
}
} // namespace autofill