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

#include "chrome/browser/autofill/android/personal_data_manager_android.h"

#include <stddef.h>
#include <algorithm>
#include <memory>
#include <utility>

#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/command_line.h"
#include "base/format_macros.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "chrome/browser/android/preferences/prefs.h"
#include "chrome/browser/android/resource_mapper.h"
#include "chrome/browser/autofill/address_normalizer_factory.h"
#include "chrome/browser/autofill/personal_data_manager_factory.h"
#include "chrome/browser/autofill/validation_rules_storage_factory.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/pref_names.h"
#include "components/autofill/content/browser/content_autofill_driver.h"
#include "components/autofill/content/browser/content_autofill_driver_factory.h"
#include "components/autofill/core/browser/address_i18n.h"
#include "components/autofill/core/browser/address_normalizer.h"
#include "components/autofill/core/browser/autofill_country.h"
#include "components/autofill/core/browser/autofill_data_util.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/country_names.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/payments/full_card_request.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/validation.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/web_contents.h"
#include "jni/PersonalDataManager_jni.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "third_party/libaddressinput/chromium/chrome_metadata_source.h"
#include "third_party/libaddressinput/chromium/chrome_storage_impl.h"
#include "ui/base/l10n/l10n_util.h"

namespace autofill {
namespace {

using ::base::android::ConvertJavaStringToUTF8;
using ::base::android::ConvertUTF16ToJavaString;
using ::base::android::ConvertUTF8ToJavaString;
using ::base::android::JavaParamRef;
using ::base::android::JavaRef;
using ::base::android::ScopedJavaGlobalRef;
using ::base::android::ScopedJavaLocalRef;

Profile* GetProfile() {
  return ProfileManager::GetActiveUserProfile()->GetOriginalProfile();
}

PrefService* GetPrefs() {
  return GetProfile()->GetPrefs();
}

ScopedJavaLocalRef<jobject> JNI_PersonalDataManager_CreateJavaProfileFromNative(
    JNIEnv* env,
    const AutofillProfile& profile) {
  return Java_AutofillProfile_create(
      env, ConvertUTF8ToJavaString(env, profile.guid()),
      ConvertUTF8ToJavaString(env, profile.origin()),
      profile.record_type() == AutofillProfile::LOCAL_PROFILE,
      ConvertUTF16ToJavaString(
          env, profile.GetInfo(AutofillType(NAME_FULL),
                               g_browser_process->GetApplicationLocale())),
      ConvertUTF16ToJavaString(env, profile.GetRawInfo(COMPANY_NAME)),
      ConvertUTF16ToJavaString(env,
                               profile.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS)),
      ConvertUTF16ToJavaString(env, profile.GetRawInfo(ADDRESS_HOME_STATE)),
      ConvertUTF16ToJavaString(env, profile.GetRawInfo(ADDRESS_HOME_CITY)),
      ConvertUTF16ToJavaString(
          env, profile.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY)),
      ConvertUTF16ToJavaString(env, profile.GetRawInfo(ADDRESS_HOME_ZIP)),
      ConvertUTF16ToJavaString(env,
                               profile.GetRawInfo(ADDRESS_HOME_SORTING_CODE)),
      ConvertUTF16ToJavaString(env, profile.GetRawInfo(ADDRESS_HOME_COUNTRY)),
      ConvertUTF16ToJavaString(env,
                               profile.GetRawInfo(PHONE_HOME_WHOLE_NUMBER)),
      ConvertUTF16ToJavaString(env, profile.GetRawInfo(EMAIL_ADDRESS)),
      ConvertUTF8ToJavaString(env, profile.language_code()));
}

void MaybeSetRawInfo(AutofillProfile* profile,
                     autofill::ServerFieldType type,
                     const base::android::JavaRef<jstring>& jstr) {
  if (!jstr.is_null())
    profile->SetRawInfo(type, ConvertJavaStringToUTF16(jstr));
}

ScopedJavaLocalRef<jobject>
JNI_PersonalDataManager_CreateJavaCreditCardFromNative(JNIEnv* env,
                                                       const CreditCard& card) {
  const data_util::PaymentRequestData& payment_request_data =
      data_util::GetPaymentRequestData(card.network());
  return Java_CreditCard_create(
      env, ConvertUTF8ToJavaString(env, card.guid()),
      ConvertUTF8ToJavaString(env, card.origin()),
      card.record_type() == CreditCard::LOCAL_CARD,
      card.record_type() == CreditCard::FULL_SERVER_CARD,
      ConvertUTF16ToJavaString(env, card.GetRawInfo(CREDIT_CARD_NAME_FULL)),
      ConvertUTF16ToJavaString(env, card.GetRawInfo(CREDIT_CARD_NUMBER)),
      ConvertUTF16ToJavaString(env, card.NetworkAndLastFourDigits()),
      ConvertUTF16ToJavaString(env, card.GetRawInfo(CREDIT_CARD_EXP_MONTH)),
      ConvertUTF16ToJavaString(env,
                               card.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR)),
      ConvertUTF8ToJavaString(env,
                              payment_request_data.basic_card_issuer_network),
      ResourceMapper::MapFromChromiumId(payment_request_data.icon_resource_id),
      card.card_type(), ConvertUTF8ToJavaString(env, card.billing_address_id()),
      ConvertUTF8ToJavaString(env, card.server_id()));
}

// Self-deleting requester of full card details, including full PAN and the CVC
// number.
class FullCardRequester : public payments::FullCardRequest::ResultDelegate,
                          public base::SupportsWeakPtr<FullCardRequester> {
 public:
  FullCardRequester() {}

  // Takes ownership of |card|.
  void GetFullCard(JNIEnv* env,
                   const base::android::JavaParamRef<jobject>& jweb_contents,
                   const base::android::JavaParamRef<jobject>& jdelegate,
                   std::unique_ptr<CreditCard> card) {
    card_ = std::move(card);
    jdelegate_.Reset(env, jdelegate);

    if (!card_) {
      OnFullCardRequestFailed();
      return;
    }

    content::WebContents* contents =
        content::WebContents::FromJavaWebContents(jweb_contents);
    if (!contents) {
      OnFullCardRequestFailed();
      return;
    }

    ContentAutofillDriverFactory* factory =
        ContentAutofillDriverFactory::FromWebContents(contents);
    if (!factory) {
      OnFullCardRequestFailed();
      return;
    }

    ContentAutofillDriver* driver =
        factory->DriverForFrame(contents->GetMainFrame());
    if (!driver) {
      OnFullCardRequestFailed();
      return;
    }

    driver->autofill_manager()->GetOrCreateFullCardRequest()->GetFullCard(
        *card_, AutofillClient::UNMASK_FOR_PAYMENT_REQUEST, AsWeakPtr(),
        driver->autofill_manager()->GetAsFullCardRequestUIDelegate());
  }

 private:
  ~FullCardRequester() override {}

  // payments::FullCardRequest::ResultDelegate:
  void OnFullCardRequestSucceeded(
      const payments::FullCardRequest& /* full_card_request */,
      const CreditCard& card,
      const base::string16& cvc) override {
    JNIEnv* env = base::android::AttachCurrentThread();
    Java_FullCardRequestDelegate_onFullCardDetails(
        env, jdelegate_,
        JNI_PersonalDataManager_CreateJavaCreditCardFromNative(env, card),
        base::android::ConvertUTF16ToJavaString(env, cvc));
    delete this;
  }

  // payments::FullCardRequest::ResultDelegate:
  void OnFullCardRequestFailed() override {
    JNIEnv* env = base::android::AttachCurrentThread();
    Java_FullCardRequestDelegate_onFullCardError(env, jdelegate_);
    delete this;
  }

  std::unique_ptr<CreditCard> card_;
  ScopedJavaGlobalRef<jobject> jdelegate_;

  DISALLOW_COPY_AND_ASSIGN(FullCardRequester);
};

void OnSubKeysReceived(ScopedJavaGlobalRef<jobject> jdelegate,
                       const std::vector<std::string>& subkeys_codes,
                       const std::vector<std::string>& subkeys_names) {
  JNIEnv* env = base::android::AttachCurrentThread();
  Java_GetSubKeysRequestDelegate_onSubKeysReceived(
      env, jdelegate, base::android::ToJavaArrayOfStrings(env, subkeys_codes),
      base::android::ToJavaArrayOfStrings(env, subkeys_names));
}

void OnAddressNormalized(ScopedJavaGlobalRef<jobject> jdelegate,
                         bool success,
                         const AutofillProfile& profile) {
  JNIEnv* env = base::android::AttachCurrentThread();
  if (success) {
    Java_NormalizedAddressRequestDelegate_onAddressNormalized(
        env, jdelegate,
        JNI_PersonalDataManager_CreateJavaProfileFromNative(env, profile));
  } else {
    Java_NormalizedAddressRequestDelegate_onCouldNotNormalize(
        env, jdelegate,
        JNI_PersonalDataManager_CreateJavaProfileFromNative(env, profile));
  }
}

}  // namespace

PersonalDataManagerAndroid::PersonalDataManagerAndroid(JNIEnv* env, jobject obj)
    : weak_java_obj_(env, obj),
      personal_data_manager_(PersonalDataManagerFactory::GetForProfile(
          ProfileManager::GetActiveUserProfile())),
      subkey_requester_(std::make_unique<ChromeMetadataSource>(
                            I18N_ADDRESS_VALIDATION_DATA_URL,
                            g_browser_process->system_network_context_manager()
                                ->GetSharedURLLoaderFactory()),
                        ValidationRulesStorageFactory::CreateStorage()) {
  personal_data_manager_->AddObserver(this);
}

PersonalDataManagerAndroid::~PersonalDataManagerAndroid() {
  personal_data_manager_->RemoveObserver(this);
}

// static
void PersonalDataManagerAndroid::PopulateNativeCreditCardFromJava(
    const JavaRef<jobject>& jcard,
    JNIEnv* env,
    CreditCard* card) {
  card->set_origin(
      ConvertJavaStringToUTF8(Java_CreditCard_getOrigin(env, jcard)));
  card->SetRawInfo(
      CREDIT_CARD_NAME_FULL,
      ConvertJavaStringToUTF16(Java_CreditCard_getName(env, jcard)));
  card->SetRawInfo(
      CREDIT_CARD_NUMBER,
      ConvertJavaStringToUTF16(Java_CreditCard_getNumber(env, jcard)));
  card->SetRawInfo(
      CREDIT_CARD_EXP_MONTH,
      ConvertJavaStringToUTF16(Java_CreditCard_getMonth(env, jcard)));
  card->SetRawInfo(
      CREDIT_CARD_EXP_4_DIGIT_YEAR,
      ConvertJavaStringToUTF16(Java_CreditCard_getYear(env, jcard)));
  card->set_billing_address_id(
      ConvertJavaStringToUTF8(Java_CreditCard_getBillingAddressId(env, jcard)));
  card->set_server_id(
      ConvertJavaStringToUTF8(Java_CreditCard_getServerId(env, jcard)));

  jint card_type = Java_CreditCard_getCardType(env, jcard);
  DCHECK_GE(CreditCard::CARD_TYPE_PREPAID, card_type);
  DCHECK_LE(CreditCard::CARD_TYPE_UNKNOWN, card_type);
  card->set_card_type(static_cast<CreditCard::CardType>(card_type));

  // Only set the guid if it is an existing card (java guid not empty).
  // Otherwise, keep the generated one.
  std::string guid =
      ConvertJavaStringToUTF8(Java_CreditCard_getGUID(env, jcard));
  if (!guid.empty())
    card->set_guid(guid);

  if (Java_CreditCard_getIsLocal(env, jcard)) {
    card->set_record_type(CreditCard::LOCAL_CARD);
  } else {
    if (Java_CreditCard_getIsCached(env, jcard)) {
      card->set_record_type(CreditCard::FULL_SERVER_CARD);
    } else {
      card->set_record_type(CreditCard::MASKED_SERVER_CARD);
      card->SetNetworkForMaskedCard(
          data_util::GetIssuerNetworkForBasicCardIssuerNetwork(
              ConvertJavaStringToUTF8(
                  env, Java_CreditCard_getBasicCardIssuerNetwork(env, jcard))));
    }
  }
}

// static
void PersonalDataManagerAndroid::PopulateNativeProfileFromJava(
    const JavaParamRef<jobject>& jprofile,
    JNIEnv* env,
    AutofillProfile* profile) {
  // Only set the guid if it is an existing profile (java guid not empty).
  // Otherwise, keep the generated one.
  std::string guid =
      ConvertJavaStringToUTF8(Java_AutofillProfile_getGUID(env, jprofile));
  if (!guid.empty())
    profile->set_guid(guid);

  profile->set_origin(
      ConvertJavaStringToUTF8(Java_AutofillProfile_getOrigin(env, jprofile)));
  profile->SetInfo(
      AutofillType(NAME_FULL),
      ConvertJavaStringToUTF16(Java_AutofillProfile_getFullName(env, jprofile)),
      g_browser_process->GetApplicationLocale());
  MaybeSetRawInfo(profile, autofill::COMPANY_NAME,
                  Java_AutofillProfile_getCompanyName(env, jprofile));
  MaybeSetRawInfo(profile, autofill::ADDRESS_HOME_STREET_ADDRESS,
                  Java_AutofillProfile_getStreetAddress(env, jprofile));
  MaybeSetRawInfo(profile, autofill::ADDRESS_HOME_STATE,
                  Java_AutofillProfile_getRegion(env, jprofile));
  MaybeSetRawInfo(profile, autofill::ADDRESS_HOME_CITY,
                  Java_AutofillProfile_getLocality(env, jprofile));
  MaybeSetRawInfo(profile, autofill::ADDRESS_HOME_DEPENDENT_LOCALITY,
                  Java_AutofillProfile_getDependentLocality(env, jprofile));
  MaybeSetRawInfo(profile, autofill::ADDRESS_HOME_ZIP,
                  Java_AutofillProfile_getPostalCode(env, jprofile));
  MaybeSetRawInfo(profile, autofill::ADDRESS_HOME_SORTING_CODE,
                  Java_AutofillProfile_getSortingCode(env, jprofile));
  ScopedJavaLocalRef<jstring> country_code =
      Java_AutofillProfile_getCountryCode(env, jprofile);
  if (!country_code.is_null()) {
    profile->SetInfo(AutofillType(ADDRESS_HOME_COUNTRY),
                     ConvertJavaStringToUTF16(country_code),
                     g_browser_process->GetApplicationLocale());
  }
  MaybeSetRawInfo(profile, autofill::PHONE_HOME_WHOLE_NUMBER,
                  Java_AutofillProfile_getPhoneNumber(env, jprofile));
  MaybeSetRawInfo(profile, autofill::EMAIL_ADDRESS,
                  Java_AutofillProfile_getEmailAddress(env, jprofile));
  profile->set_language_code(ConvertJavaStringToUTF8(
      Java_AutofillProfile_getLanguageCode(env, jprofile)));
}

jboolean PersonalDataManagerAndroid::IsDataLoaded(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& unused_obj) const {
  return personal_data_manager_->IsDataLoaded();
}

ScopedJavaLocalRef<jobjectArray>
PersonalDataManagerAndroid::GetProfileGUIDsForSettings(
    JNIEnv* env,
    const JavaParamRef<jobject>& unused_obj) {
  return GetProfileGUIDs(env, personal_data_manager_->GetProfiles());
}

ScopedJavaLocalRef<jobjectArray>
PersonalDataManagerAndroid::GetProfileGUIDsToSuggest(
    JNIEnv* env,
    const JavaParamRef<jobject>& unused_obj) {
  return GetProfileGUIDs(env, personal_data_manager_->GetProfilesToSuggest());
}

ScopedJavaLocalRef<jobject> PersonalDataManagerAndroid::GetProfileByGUID(
    JNIEnv* env,
    const JavaParamRef<jobject>& unused_obj,
    const JavaParamRef<jstring>& jguid) {
  AutofillProfile* profile = personal_data_manager_->GetProfileByGUID(
      ConvertJavaStringToUTF8(env, jguid));
  if (!profile)
    return ScopedJavaLocalRef<jobject>();

  return JNI_PersonalDataManager_CreateJavaProfileFromNative(env, *profile);
}

ScopedJavaLocalRef<jstring> PersonalDataManagerAndroid::SetProfile(
    JNIEnv* env,
    const JavaParamRef<jobject>& unused_obj,
    const JavaParamRef<jobject>& jprofile) {
  std::string guid = ConvertJavaStringToUTF8(
      env, Java_AutofillProfile_getGUID(env, jprofile).obj());

  AutofillProfile profile;
  PopulateNativeProfileFromJava(jprofile, env, &profile);

  if (guid.empty()) {
    personal_data_manager_->AddProfile(profile);
  } else {
    profile.set_guid(guid);
    personal_data_manager_->UpdateProfile(profile);
  }

  return ConvertUTF8ToJavaString(env, profile.guid());
}

ScopedJavaLocalRef<jstring> PersonalDataManagerAndroid::SetProfileToLocal(
    JNIEnv* env,
    const JavaParamRef<jobject>& unused_obj,
    const JavaParamRef<jobject>& jprofile) {
  AutofillProfile profile;
  PopulateNativeProfileFromJava(jprofile, env, &profile);

  AutofillProfile* target_profile =
      personal_data_manager_->GetProfileByGUID(ConvertJavaStringToUTF8(
          env, Java_AutofillProfile_getGUID(env, jprofile).obj()));

  if (target_profile != nullptr &&
      target_profile->record_type() == AutofillProfile::LOCAL_PROFILE) {
    profile.set_guid(target_profile->guid());
    personal_data_manager_->UpdateProfile(profile);
  } else {
    personal_data_manager_->AddProfile(profile);
  }

  return ConvertUTF8ToJavaString(env, profile.guid());
}

ScopedJavaLocalRef<jobjectArray>
PersonalDataManagerAndroid::GetProfileLabelsForSettings(
    JNIEnv* env,
    const JavaParamRef<jobject>& unused_obj) {
  return GetProfileLabels(env, false /* address_only */,
                          false /* include_name_in_label */,
                          true /* include_organization_in_label */,
                          true /* include_country_in_label */,
                          personal_data_manager_->GetProfiles());
}

ScopedJavaLocalRef<jobjectArray>
PersonalDataManagerAndroid::GetProfileLabelsToSuggest(
    JNIEnv* env,
    const JavaParamRef<jobject>& unused_obj,
    jboolean include_name_in_label,
    jboolean include_organization_in_label,
    jboolean include_country_in_label) {
  return GetProfileLabels(env, true /* address_only */, include_name_in_label,
                          include_organization_in_label,
                          include_country_in_label,
                          personal_data_manager_->GetProfilesToSuggest());
}

base::android::ScopedJavaLocalRef<jstring>
PersonalDataManagerAndroid::GetShippingAddressLabelWithCountryForPaymentRequest(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& unused_obj,
    const base::android::JavaParamRef<jobject>& jprofile) {
  return GetShippingAddressLabelForPaymentRequest(
      env, jprofile, true /* include_country_in_label */);
}

base::android::ScopedJavaLocalRef<jstring> PersonalDataManagerAndroid::
    GetShippingAddressLabelWithoutCountryForPaymentRequest(
        JNIEnv* env,
        const base::android::JavaParamRef<jobject>& unused_obj,
        const base::android::JavaParamRef<jobject>& jprofile) {
  return GetShippingAddressLabelForPaymentRequest(
      env, jprofile, false /* include_country_in_label */);
}

base::android::ScopedJavaLocalRef<jstring>
PersonalDataManagerAndroid::GetBillingAddressLabelForPaymentRequest(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& unused_obj,
    const base::android::JavaParamRef<jobject>& jprofile) {
  // The company name and country are not included in the billing address label.
  static constexpr ServerFieldType kLabelFields[] = {
      NAME_FULL,          ADDRESS_HOME_LINE1,
      ADDRESS_HOME_LINE2, ADDRESS_HOME_DEPENDENT_LOCALITY,
      ADDRESS_HOME_CITY,  ADDRESS_HOME_STATE,
      ADDRESS_HOME_ZIP,   ADDRESS_HOME_SORTING_CODE,
  };

  AutofillProfile profile;
  PopulateNativeProfileFromJava(jprofile, env, &profile);

  return ConvertUTF16ToJavaString(
      env, profile.ConstructInferredLabel(
               kLabelFields, arraysize(kLabelFields), arraysize(kLabelFields),
               g_browser_process->GetApplicationLocale()));
}

base::android::ScopedJavaLocalRef<jobjectArray>
PersonalDataManagerAndroid::GetCreditCardGUIDsForSettings(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& unused_obj) {
  return GetCreditCardGUIDs(env, personal_data_manager_->GetCreditCards());
}

base::android::ScopedJavaLocalRef<jobjectArray>
PersonalDataManagerAndroid::GetCreditCardGUIDsToSuggest(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& unused_obj,
    bool include_server_cards) {
  return GetCreditCardGUIDs(
      env,
      personal_data_manager_->GetCreditCardsToSuggest(include_server_cards));
}

ScopedJavaLocalRef<jobject> PersonalDataManagerAndroid::GetCreditCardByGUID(
    JNIEnv* env,
    const JavaParamRef<jobject>& unused_obj,
    const JavaParamRef<jstring>& jguid) {
  CreditCard* card = personal_data_manager_->GetCreditCardByGUID(
      ConvertJavaStringToUTF8(env, jguid));
  if (!card)
    return ScopedJavaLocalRef<jobject>();

  return JNI_PersonalDataManager_CreateJavaCreditCardFromNative(env, *card);
}

ScopedJavaLocalRef<jobject> PersonalDataManagerAndroid::GetCreditCardForNumber(
    JNIEnv* env,
    const JavaParamRef<jobject>& unused_obj,
    const JavaParamRef<jstring>& jcard_number) {
  // A local card with empty GUID.
  CreditCard card("", "");
  card.SetNumber(ConvertJavaStringToUTF16(env, jcard_number));
  return JNI_PersonalDataManager_CreateJavaCreditCardFromNative(env, card);
}

ScopedJavaLocalRef<jstring> PersonalDataManagerAndroid::SetCreditCard(
    JNIEnv* env,
    const JavaParamRef<jobject>& unused_obj,
    const JavaParamRef<jobject>& jcard) {
  std::string guid =
      ConvertJavaStringToUTF8(env, Java_CreditCard_getGUID(env, jcard).obj());

  CreditCard card;
  PopulateNativeCreditCardFromJava(jcard, env, &card);

  if (guid.empty()) {
    personal_data_manager_->AddCreditCard(card);
  } else {
    card.set_guid(guid);
    personal_data_manager_->UpdateCreditCard(card);
  }
  return ConvertUTF8ToJavaString(env, card.guid());
}

void PersonalDataManagerAndroid::UpdateServerCardBillingAddress(
    JNIEnv* env,
    const JavaParamRef<jobject>& unused_obj,
    const JavaParamRef<jobject>& jcard) {
  CreditCard card;
  PopulateNativeCreditCardFromJava(jcard, env, &card);

  personal_data_manager_->UpdateServerCardMetadata(card);
}

ScopedJavaLocalRef<jstring>
PersonalDataManagerAndroid::GetBasicCardIssuerNetwork(
    JNIEnv* env,
    const JavaParamRef<jobject>& unused_obj,
    const JavaParamRef<jstring>& jcard_number,
    const jboolean jempty_if_invalid) {
  base::string16 card_number = ConvertJavaStringToUTF16(env, jcard_number);

  if (static_cast<bool>(jempty_if_invalid) &&
      !IsValidCreditCardNumber(card_number)) {
    return ConvertUTF8ToJavaString(env, "");
  }
  return ConvertUTF8ToJavaString(
      env,
      data_util::GetPaymentRequestData(CreditCard::GetCardNetwork(card_number))
          .basic_card_issuer_network);
}

void PersonalDataManagerAndroid::AddServerCreditCardForTest(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& unused_obj,
    const base::android::JavaParamRef<jobject>& jcard) {
  std::unique_ptr<CreditCard> card = std::make_unique<CreditCard>();
  PopulateNativeCreditCardFromJava(jcard, env, card.get());
  card->set_record_type(CreditCard::MASKED_SERVER_CARD);
  personal_data_manager_->AddServerCreditCardForTest(std::move(card));
  personal_data_manager_->NotifyPersonalDataChangedForTest();
}

void PersonalDataManagerAndroid::RemoveByGUID(
    JNIEnv* env,
    const JavaParamRef<jobject>& unused_obj,
    const JavaParamRef<jstring>& jguid) {
  personal_data_manager_->RemoveByGUID(ConvertJavaStringToUTF8(env, jguid));
}

void PersonalDataManagerAndroid::ClearUnmaskedCache(
    JNIEnv* env,
    const JavaParamRef<jobject>& unused_obj,
    const JavaParamRef<jstring>& guid) {
  personal_data_manager_->ResetFullServerCard(
      ConvertJavaStringToUTF8(env, guid));
}

void PersonalDataManagerAndroid::GetFullCardForPaymentRequest(
    JNIEnv* env,
    const JavaParamRef<jobject>& unused_obj,
    const JavaParamRef<jobject>& jweb_contents,
    const JavaParamRef<jobject>& jcard,
    const JavaParamRef<jobject>& jdelegate) {
  std::unique_ptr<CreditCard> card = std::make_unique<CreditCard>();
  PopulateNativeCreditCardFromJava(jcard, env, card.get());
  // Self-deleting object.
  (new FullCardRequester())
      ->GetFullCard(env, jweb_contents, jdelegate, std::move(card));
}

void PersonalDataManagerAndroid::OnPersonalDataChanged() {
  JNIEnv* env = base::android::AttachCurrentThread();
  auto java_obj = weak_java_obj_.get(env);
  if (java_obj.is_null())
    return;

  Java_PersonalDataManager_personalDataChanged(env, java_obj);
}

void PersonalDataManagerAndroid::RecordAndLogProfileUse(
    JNIEnv* env,
    const JavaParamRef<jobject>& unused_obj,
    const JavaParamRef<jstring>& jguid) {
  AutofillProfile* profile = personal_data_manager_->GetProfileByGUID(
      ConvertJavaStringToUTF8(env, jguid));
  if (profile)
    personal_data_manager_->RecordUseOf(*profile);
}

void PersonalDataManagerAndroid::SetProfileUseStatsForTesting(
    JNIEnv* env,
    const JavaParamRef<jobject>& unused_obj,
    const JavaParamRef<jstring>& jguid,
    jint count,
    jint date) {
  DCHECK(count >= 0 && date >= 0);

  AutofillProfile* profile = personal_data_manager_->GetProfileByGUID(
      ConvertJavaStringToUTF8(env, jguid));
  profile->set_use_count(static_cast<size_t>(count));
  profile->set_use_date(base::Time::FromTimeT(date));

  personal_data_manager_->NotifyPersonalDataChangedForTest();
}

jint PersonalDataManagerAndroid::GetProfileUseCountForTesting(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& unused_obj,
    const base::android::JavaParamRef<jstring>& jguid) {
  AutofillProfile* profile = personal_data_manager_->GetProfileByGUID(
      ConvertJavaStringToUTF8(env, jguid));
  return profile->use_count();
}

jlong PersonalDataManagerAndroid::GetProfileUseDateForTesting(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& unused_obj,
    const base::android::JavaParamRef<jstring>& jguid) {
  AutofillProfile* profile = personal_data_manager_->GetProfileByGUID(
      ConvertJavaStringToUTF8(env, jguid));
  return profile->use_date().ToTimeT();
}

void PersonalDataManagerAndroid::RecordAndLogCreditCardUse(
    JNIEnv* env,
    const JavaParamRef<jobject>& unused_obj,
    const JavaParamRef<jstring>& jguid) {
  CreditCard* card = personal_data_manager_->GetCreditCardByGUID(
      ConvertJavaStringToUTF8(env, jguid));
  if (card)
    personal_data_manager_->RecordUseOf(*card);
}

void PersonalDataManagerAndroid::SetCreditCardUseStatsForTesting(
    JNIEnv* env,
    const JavaParamRef<jobject>& unused_obj,
    const JavaParamRef<jstring>& jguid,
    jint count,
    jint date) {
  DCHECK(count >= 0 && date >= 0);

  CreditCard* card = personal_data_manager_->GetCreditCardByGUID(
      ConvertJavaStringToUTF8(env, jguid));
  card->set_use_count(static_cast<size_t>(count));
  card->set_use_date(base::Time::FromTimeT(date));

  personal_data_manager_->NotifyPersonalDataChangedForTest();
}

jint PersonalDataManagerAndroid::GetCreditCardUseCountForTesting(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& unused_obj,
    const base::android::JavaParamRef<jstring>& jguid) {
  CreditCard* card = personal_data_manager_->GetCreditCardByGUID(
      ConvertJavaStringToUTF8(env, jguid));
  return card->use_count();
}

jlong PersonalDataManagerAndroid::GetCreditCardUseDateForTesting(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& unused_obj,
    const base::android::JavaParamRef<jstring>& jguid) {
  CreditCard* card = personal_data_manager_->GetCreditCardByGUID(
      ConvertJavaStringToUTF8(env, jguid));
  return card->use_date().ToTimeT();
}

// TODO(crbug.com/629507): Use a mock clock for testing.
jlong PersonalDataManagerAndroid::GetCurrentDateForTesting(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& unused_obj) {
  return base::Time::Now().ToTimeT();
}

void PersonalDataManagerAndroid::LoadRulesForAddressNormalization(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& unused_obj,
    const base::android::JavaParamRef<jstring>& jregion_code) {
  AddressNormalizer* normalizer = AddressNormalizerFactory::GetInstance();
  normalizer->LoadRulesForRegion(ConvertJavaStringToUTF8(env, jregion_code));
}

void PersonalDataManagerAndroid::LoadRulesForSubKeys(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& unused_obj,
    const base::android::JavaParamRef<jstring>& jregion_code) {
  subkey_requester_.LoadRulesForRegion(
      ConvertJavaStringToUTF8(env, jregion_code));
}

void PersonalDataManagerAndroid::StartAddressNormalization(
    JNIEnv* env,
    const JavaParamRef<jobject>& unused_obj,
    const JavaParamRef<jobject>& jprofile,
    jint jtimeout_seconds,
    const JavaParamRef<jobject>& jdelegate) {
  AutofillProfile profile;
  PopulateNativeProfileFromJava(jprofile, env, &profile);

  // Start the normalization.
  AddressNormalizer* normalizer = AddressNormalizerFactory::GetInstance();
  normalizer->NormalizeAddressAsync(
      profile, jtimeout_seconds,
      base::BindOnce(&OnAddressNormalized,
                     ScopedJavaGlobalRef<jobject>(jdelegate)));
}

jboolean PersonalDataManagerAndroid::HasProfiles(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& unused_obj) {
  return !personal_data_manager_->GetProfiles().empty();
}

jboolean PersonalDataManagerAndroid::HasCreditCards(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& unused_obj) {
  return !personal_data_manager_->GetCreditCards().empty();
}

void PersonalDataManagerAndroid::StartRegionSubKeysRequest(
    JNIEnv* env,
    const JavaParamRef<jobject>& unused_obj,
    const JavaParamRef<jstring>& jregion_code,
    jint jtimeout_seconds,
    const JavaParamRef<jobject>& jdelegate) {
  const std::string region_code = ConvertJavaStringToUTF8(env, jregion_code);

  ScopedJavaGlobalRef<jobject> my_jdelegate;
  my_jdelegate.Reset(env, jdelegate);

  SubKeyReceiverCallback cb = base::BindOnce(
      &OnSubKeysReceived, ScopedJavaGlobalRef<jobject>(my_jdelegate));

  std::string language =
      l10n_util::GetLanguage(g_browser_process->GetApplicationLocale());
  subkey_requester_.StartRegionSubKeysRequest(region_code, language,
                                              jtimeout_seconds, std::move(cb));
}

void PersonalDataManagerAndroid::CancelPendingGetSubKeys(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& unused_obj) {
  subkey_requester_.CancelPendingGetSubKeys();
}

void PersonalDataManagerAndroid::SetSyncServiceForTesting(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& unused_obj) {
  personal_data_manager_->SetSyncingForTest(true);
}

ScopedJavaLocalRef<jobjectArray> PersonalDataManagerAndroid::GetProfileGUIDs(
    JNIEnv* env,
    const std::vector<AutofillProfile*>& profiles) {
  std::vector<base::string16> guids;
  for (AutofillProfile* profile : profiles)
    guids.push_back(base::UTF8ToUTF16(profile->guid()));

  return base::android::ToJavaArrayOfStrings(env, guids);
}

ScopedJavaLocalRef<jobjectArray> PersonalDataManagerAndroid::GetCreditCardGUIDs(
    JNIEnv* env,
    const std::vector<CreditCard*>& credit_cards) {
  std::vector<base::string16> guids;
  for (CreditCard* credit_card : credit_cards)
    guids.push_back(base::UTF8ToUTF16(credit_card->guid()));

  return base::android::ToJavaArrayOfStrings(env, guids);
}

ScopedJavaLocalRef<jobjectArray> PersonalDataManagerAndroid::GetProfileLabels(
    JNIEnv* env,
    bool address_only,
    bool include_name_in_label,
    bool include_organization_in_label,
    bool include_country_in_label,
    std::vector<AutofillProfile*> profiles) {
  std::unique_ptr<std::vector<ServerFieldType>> suggested_fields;
  size_t minimal_fields_shown = 2;
  if (address_only) {
    suggested_fields = std::make_unique<std::vector<ServerFieldType>>();
    if (include_name_in_label)
      suggested_fields->push_back(NAME_FULL);
    if (include_organization_in_label)
      suggested_fields->push_back(COMPANY_NAME);
    suggested_fields->push_back(ADDRESS_HOME_LINE1);
    suggested_fields->push_back(ADDRESS_HOME_LINE2);
    suggested_fields->push_back(ADDRESS_HOME_DEPENDENT_LOCALITY);
    suggested_fields->push_back(ADDRESS_HOME_CITY);
    suggested_fields->push_back(ADDRESS_HOME_STATE);
    suggested_fields->push_back(ADDRESS_HOME_ZIP);
    suggested_fields->push_back(ADDRESS_HOME_SORTING_CODE);
    if (include_country_in_label)
      suggested_fields->push_back(ADDRESS_HOME_COUNTRY);
    minimal_fields_shown = suggested_fields->size();
  }

  ServerFieldType excluded_field =
      include_name_in_label ? UNKNOWN_TYPE : NAME_FULL;

  std::vector<base::string16> labels;
  AutofillProfile::CreateInferredLabels(
      profiles, suggested_fields.get(), excluded_field, minimal_fields_shown,
      g_browser_process->GetApplicationLocale(), &labels);

  return base::android::ToJavaArrayOfStrings(env, labels);
}

base::android::ScopedJavaLocalRef<jstring>
PersonalDataManagerAndroid::GetShippingAddressLabelForPaymentRequest(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& jprofile,
    bool include_country_in_label) {
  // The full name is not included in the label for shipping address. It is
  // added separately instead.
  static constexpr ServerFieldType kLabelFields[] = {
      COMPANY_NAME,         ADDRESS_HOME_LINE1,
      ADDRESS_HOME_LINE2,   ADDRESS_HOME_DEPENDENT_LOCALITY,
      ADDRESS_HOME_CITY,    ADDRESS_HOME_STATE,
      ADDRESS_HOME_ZIP,     ADDRESS_HOME_SORTING_CODE,
      ADDRESS_HOME_COUNTRY,
  };
  size_t kLabelFields_size = arraysize(kLabelFields);
  if (!include_country_in_label)
    --kLabelFields_size;

  AutofillProfile profile;
  PopulateNativeProfileFromJava(jprofile, env, &profile);

  return ConvertUTF16ToJavaString(
      env, profile.ConstructInferredLabel(
               kLabelFields, kLabelFields_size, kLabelFields_size,
               g_browser_process->GetApplicationLocale()));
}

// Returns whether the specified feature is enabled.
static jboolean JNI_PersonalDataManager_GetPref(
    JNIEnv* env,
    const jint j_pref_index) {
  return GetPrefs()->GetBoolean(
      PersonalDataManagerAndroid::GetPrefNameExposedToJava(j_pref_index));
}

// Enables or disables the specified feature for profiles.
static void JNI_PersonalDataManager_SetPref(JNIEnv* env,
                                            const jint j_pref_index,
                                            const jboolean j_enable) {
  return GetPrefs()->SetBoolean(
      PersonalDataManagerAndroid::GetPrefNameExposedToJava(j_pref_index),
      j_enable);
}

// Returns whether the Autofill feature is managed.
static jboolean JNI_PersonalDataManager_IsAutofillManaged(JNIEnv* env) {
  return prefs::IsAutofillManaged(GetPrefs());
}

// Returns whether the Autofill feature for profiles is managed.
static jboolean JNI_PersonalDataManager_IsAutofillProfileManaged(JNIEnv* env) {
  return prefs::IsProfileAutofillManaged(GetPrefs());
}

// Returns whether the Autofill feature for credit cards is managed.
static jboolean JNI_PersonalDataManager_IsAutofillCreditCardManaged(
    JNIEnv* env) {
  return prefs::IsCreditCardAutofillManaged(GetPrefs());
}

// Returns whether the Payments integration feature is enabled.
static jboolean JNI_PersonalDataManager_IsPaymentsIntegrationEnabled(
    JNIEnv* env) {
  return prefs::IsPaymentsIntegrationEnabled(GetPrefs());
}

// Enables or disables the Payments integration feature.
static void JNI_PersonalDataManager_SetPaymentsIntegrationEnabled(
    JNIEnv* env,
    jboolean enable) {
  prefs::SetPaymentsIntegrationEnabled(GetPrefs(), enable);
}

// Returns an ISO 3166-1-alpha-2 country code for a |jcountry_name| using
// the application locale, or an empty string.
static ScopedJavaLocalRef<jstring> JNI_PersonalDataManager_ToCountryCode(
    JNIEnv* env,
    const JavaParamRef<jstring>& jcountry_name) {
  return ConvertUTF8ToJavaString(
      env, CountryNames::GetInstance()->GetCountryCode(
               base::android::ConvertJavaStringToUTF16(env, jcountry_name)));
}

static jlong JNI_PersonalDataManager_Init(JNIEnv* env,
                                          const JavaParamRef<jobject>& obj) {
  PersonalDataManagerAndroid* personal_data_manager_android =
      new PersonalDataManagerAndroid(env, obj);
  return reinterpret_cast<intptr_t>(personal_data_manager_android);
}

const char* PersonalDataManagerAndroid::GetPrefNameExposedToJava(
    int pref_index) {
  DCHECK_GE(pref_index, 0);
  DCHECK_LT(pref_index, Pref::PREF_NUM_PREFS);
  return kPrefsExposedToJava[pref_index];
}

}  // namespace autofill
