chromium/components/android_autofill/browser/test_support/autofill_provider_test_helper.cc

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.


#include <iterator>
#include <string>

#include "base/android/jni_array.h"
#include "base/base64.h"
#include "base/ranges/algorithm.h"
#include "components/android_autofill/browser/autofill_provider.h"
#include "components/autofill/content/browser/content_autofill_driver.h"
#include "components/autofill/content/browser/content_autofill_driver_factory.h"
#include "components/autofill/content/browser/content_autofill_driver_factory_test_api.h"
#include "components/autofill/core/browser/autofill_manager.h"
#include "components/autofill/core/browser/autofill_manager_test_api.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/field_types.h"
#include "content/public/browser/web_contents.h"

// Must come after all headers that specialize FromJniType() / ToJniType().
#include "components/android_autofill/browser/test_support/jni_headers/AutofillProviderTestHelper_jni.h"

namespace autofill {

namespace {
AutofillManager* GetAutofillManager(content::WebContents* web_contents,
                                    content::RenderFrameHost* rfh) {
  // Avoid using ContentAutofillDriver::GetForRenderFrameHost(), it will create
  // a new ContentAutofillDriver.
  if (ContentAutofillDriverFactory* factory =
          ContentAutofillDriverFactory::FromWebContents(web_contents)) {
    if (ContentAutofillDriver* driver = test_api(*factory).GetDriver(rfh)) {
      return &driver->GetAutofillManager();
    }
  }
  return nullptr;
}

AutofillManager* ToMainFrameAutofillManager(
    const base::android::JavaParamRef<jobject>& jweb_contents) {
  content::WebContents* web_contents =
      content::WebContents::FromJavaWebContents(jweb_contents);
  CHECK(web_contents);
  AutofillManager* autofill_manager =
      GetAutofillManager(web_contents, web_contents->GetPrimaryMainFrame());
  CHECK(autofill_manager);
  return autofill_manager;
}

}  // namespace

static void JNI_AutofillProviderTestHelper_DisableCrowdsourcingForTesting(
    JNIEnv* env_md_ctx_st) {
  AutofillProvider::set_is_crowdsourcing_manager_disabled_for_testing();
}

static jboolean
JNI_AutofillProviderTestHelper_SimulateMainFrameAutofillServerResponseForTesting(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& jweb_contents,
    const base::android::JavaParamRef<jobjectArray>& jfield_ids,
    const base::android::JavaParamRef<jintArray>& jfield_types) {
  std::vector<std::u16string> field_ids;
  base::android::AppendJavaStringArrayToStringVector(env, jfield_ids,
                                                     &field_ids);
  std::vector<int> raw_field_types;
  base::android::JavaIntArrayToIntVector(env, jfield_types, &raw_field_types);

  AutofillManager* autofill_manager = ToMainFrameAutofillManager(jweb_contents);
  const std::map<FormGlobalId, std::unique_ptr<FormStructure>>&
      form_structures = autofill_manager->form_structures();
  CHECK(!form_structures.empty());

  // Make API response with suggestions.
  AutofillQueryResponse response;
  AutofillQueryResponse::FormSuggestion* form_suggestion;

  form_suggestion = response.add_form_suggestions();
  size_t found_fields_count = 0;
  std::vector<FormSignature> signatures;
  for (auto& j : form_structures) {
    FormData formData = j.second->ToFormData();
    for (size_t i = 0; i < field_ids.size(); ++i) {
      for (auto form_field_data : formData.fields()) {
        if (form_field_data.id_attribute() == field_ids[i]) {
          autofill::test::AddFieldPredictionToForm(
              form_field_data,
              static_cast<autofill::FieldType>(raw_field_types[i]),
              form_suggestion);
          found_fields_count++;
          break;
        }
      }
    }
    if (found_fields_count > 0) {
      signatures = autofill::test::GetEncodedSignatures(*(j.second));
      break;
    }
  }
  CHECK(found_fields_count == field_ids.size());

  std::string response_string;
  CHECK(response.SerializeToString(&response_string));
  test_api(*autofill_manager)
      .OnLoadedServerPredictions(base::Base64Encode(response_string),
                                 signatures);
  return true;
}

static jboolean
JNI_AutofillProviderTestHelper_SimulateMainFramePredictionsAutofillServerResponseForTesting(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& jweb_contents,
    const base::android::JavaParamRef<jobjectArray>& jfield_ids,
    const base::android::JavaParamRef<jobjectArray>& jfield_types) {
  std::vector<std::u16string> field_ids;
  base::android::AppendJavaStringArrayToStringVector(env, jfield_ids,
                                                     &field_ids);
  std::vector<std::vector<int>> raw_field_types;
  base::android::JavaArrayOfIntArrayToIntVector(env, jfield_types,
                                                &raw_field_types);

  AutofillManager* autofill_manager = ToMainFrameAutofillManager(jweb_contents);
  const std::map<FormGlobalId, std::unique_ptr<FormStructure>>&
      form_structures = autofill_manager->form_structures();
  CHECK(!form_structures.empty());

  // Make API response with suggestions.
  AutofillQueryResponse response;
  AutofillQueryResponse::FormSuggestion* form_suggestion;

  form_suggestion = response.add_form_suggestions();
  size_t found_fields_count = 0;
  std::vector<FormSignature> signatures;
  for (auto& j : form_structures) {
    FormData formData = j.second->ToFormData();
    for (size_t i = 0; i < field_ids.size(); ++i) {
      for (auto form_field_data : formData.fields()) {
        if (form_field_data.id_attribute() == field_ids[i]) {
          std::vector<FieldType> field_types;
          field_types.reserve(raw_field_types[i].size());
          base::ranges::transform(
              raw_field_types[i], std::back_inserter(field_types),
              [](int type) -> FieldType { return FieldType(type); });
          autofill::test::AddFieldPredictionsToForm(
              form_field_data, field_types, form_suggestion);
          found_fields_count++;
          break;
        }
      }
    }
    if (found_fields_count > 0) {
      signatures = autofill::test::GetEncodedSignatures(*(j.second));
      CHECK(found_fields_count == field_ids.size());
    }
  }

  std::string response_string;
  CHECK(response.SerializeToString(&response_string));
  test_api(*autofill_manager)
      .OnLoadedServerPredictions(base::Base64Encode(response_string),
                                 signatures);
  return true;
}

}  // namespace autofill