1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/autofill/android/personal_data_manager_android.h"
6
7#include "base/android/jni_array.h"
8#include "base/android/jni_string.h"
9#include "base/format_macros.h"
10#include "base/prefs/pref_service.h"
11#include "base/strings/stringprintf.h"
12#include "base/strings/utf_string_conversions.h"
13#include "chrome/browser/autofill/personal_data_manager_factory.h"
14#include "chrome/browser/browser_process.h"
15#include "chrome/browser/profiles/profile_manager.h"
16#include "chrome/common/pref_names.h"
17#include "components/autofill/core/browser/autofill_country.h"
18#include "components/autofill/core/browser/autofill_type.h"
19#include "components/autofill/core/browser/field_types.h"
20#include "components/autofill/core/browser/personal_data_manager.h"
21#include "jni/PersonalDataManager_jni.h"
22
23using base::android::ConvertJavaStringToUTF8;
24using base::android::ConvertUTF16ToJavaString;
25using base::android::ConvertUTF8ToJavaString;
26using base::android::ScopedJavaLocalRef;
27
28namespace autofill {
29namespace {
30
31PrefService* GetPrefs() {
32  return
33      ProfileManager::GetActiveUserProfile()->GetOriginalProfile()->GetPrefs();
34}
35
36ScopedJavaLocalRef<jobject> CreateJavaProfileFromNative(
37    JNIEnv* env,
38    const AutofillProfile& profile) {
39  return Java_AutofillProfile_create(
40      env,
41      ConvertUTF8ToJavaString(env, profile.guid()).obj(),
42      ConvertUTF8ToJavaString(env, profile.origin()).obj(),
43      ConvertUTF16ToJavaString(env, profile.GetRawInfo(NAME_FULL)).obj(),
44      ConvertUTF16ToJavaString(env, profile.GetRawInfo(COMPANY_NAME)).obj(),
45      ConvertUTF16ToJavaString(
46          env, profile.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS)).obj(),
47      ConvertUTF16ToJavaString(env, profile.GetRawInfo(ADDRESS_HOME_STATE))
48          .obj(),
49      ConvertUTF16ToJavaString(env, profile.GetRawInfo(ADDRESS_HOME_CITY))
50          .obj(),
51      ConvertUTF16ToJavaString(
52          env, profile.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY)).obj(),
53      ConvertUTF16ToJavaString(env, profile.GetRawInfo(ADDRESS_HOME_ZIP)).obj(),
54      ConvertUTF16ToJavaString(
55          env, profile.GetRawInfo(ADDRESS_HOME_SORTING_CODE)).obj(),
56      ConvertUTF16ToJavaString(env, profile.GetRawInfo(ADDRESS_HOME_COUNTRY))
57          .obj(),
58      ConvertUTF16ToJavaString(env, profile.GetRawInfo(PHONE_HOME_WHOLE_NUMBER))
59          .obj(),
60      ConvertUTF16ToJavaString(env, profile.GetRawInfo(EMAIL_ADDRESS)).obj(),
61      ConvertUTF8ToJavaString(env, profile.language_code()).obj());
62}
63
64void PopulateNativeProfileFromJava(
65    const jobject& jprofile,
66    JNIEnv* env,
67    AutofillProfile* profile) {
68  profile->set_origin(
69      ConvertJavaStringToUTF8(
70          Java_AutofillProfile_getOrigin(env, jprofile)));
71  profile->SetInfo(
72      AutofillType(NAME_FULL),
73      ConvertJavaStringToUTF16(
74          Java_AutofillProfile_getFullName(env, jprofile)),
75      g_browser_process->GetApplicationLocale());
76  profile->SetInfo(
77      AutofillType(COMPANY_NAME),
78      ConvertJavaStringToUTF16(
79          Java_AutofillProfile_getCompanyName(env, jprofile)),
80      g_browser_process->GetApplicationLocale());
81  profile->SetInfo(
82      AutofillType(ADDRESS_HOME_STREET_ADDRESS),
83      ConvertJavaStringToUTF16(
84          Java_AutofillProfile_getStreetAddress(env, jprofile)),
85      g_browser_process->GetApplicationLocale());
86  profile->SetInfo(
87      AutofillType(ADDRESS_HOME_STATE),
88      ConvertJavaStringToUTF16(
89          Java_AutofillProfile_getRegion(env, jprofile)),
90      g_browser_process->GetApplicationLocale());
91  profile->SetInfo(
92      AutofillType(ADDRESS_HOME_CITY),
93      ConvertJavaStringToUTF16(
94          Java_AutofillProfile_getLocality(env, jprofile)),
95      g_browser_process->GetApplicationLocale());
96  profile->SetInfo(
97      AutofillType(ADDRESS_HOME_DEPENDENT_LOCALITY),
98      ConvertJavaStringToUTF16(
99          Java_AutofillProfile_getDependentLocality(env, jprofile)),
100      g_browser_process->GetApplicationLocale());
101  profile->SetInfo(
102      AutofillType(ADDRESS_HOME_ZIP),
103      ConvertJavaStringToUTF16(
104          Java_AutofillProfile_getPostalCode(env, jprofile)),
105      g_browser_process->GetApplicationLocale());
106  profile->SetInfo(
107      AutofillType(ADDRESS_HOME_SORTING_CODE),
108      ConvertJavaStringToUTF16(
109          Java_AutofillProfile_getSortingCode(env, jprofile)),
110      g_browser_process->GetApplicationLocale());
111  profile->SetInfo(AutofillType(ADDRESS_HOME_COUNTRY),
112                   ConvertJavaStringToUTF16(
113                       Java_AutofillProfile_getCountryCode(env, jprofile)),
114                   g_browser_process->GetApplicationLocale());
115  profile->SetInfo(
116      AutofillType(PHONE_HOME_WHOLE_NUMBER),
117      ConvertJavaStringToUTF16(
118          Java_AutofillProfile_getPhoneNumber(env, jprofile)),
119      g_browser_process->GetApplicationLocale());
120  profile->SetInfo(
121      AutofillType(EMAIL_ADDRESS),
122      ConvertJavaStringToUTF16(
123          Java_AutofillProfile_getEmailAddress(env, jprofile)),
124      g_browser_process->GetApplicationLocale());
125  profile->set_language_code(
126      ConvertJavaStringToUTF8(
127          Java_AutofillProfile_getLanguageCode(env, jprofile)));
128}
129
130ScopedJavaLocalRef<jobject> CreateJavaCreditCardFromNative(
131    JNIEnv* env,
132    const CreditCard& card) {
133  return Java_CreditCard_create(
134      env,
135      ConvertUTF8ToJavaString(env, card.guid()).obj(),
136      ConvertUTF8ToJavaString(env, card.origin()).obj(),
137      ConvertUTF16ToJavaString(env, card.GetRawInfo(CREDIT_CARD_NAME)).obj(),
138      ConvertUTF16ToJavaString(env, card.GetRawInfo(CREDIT_CARD_NUMBER)).obj(),
139      ConvertUTF16ToJavaString(env, card.ObfuscatedNumber()).obj(),
140      ConvertUTF16ToJavaString(
141          env,
142          card.GetRawInfo(CREDIT_CARD_EXP_MONTH)).obj(),
143      ConvertUTF16ToJavaString(
144          env,
145          card.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR)).obj());
146}
147
148void PopulateNativeCreditCardFromJava(
149    const jobject& jcard,
150    JNIEnv* env,
151    CreditCard* card) {
152  card->set_origin(
153      ConvertJavaStringToUTF8(Java_CreditCard_getOrigin(env, jcard)));
154  card->SetRawInfo(
155      CREDIT_CARD_NAME,
156      ConvertJavaStringToUTF16(Java_CreditCard_getName(env, jcard)));
157  card->SetRawInfo(
158      CREDIT_CARD_NUMBER,
159      ConvertJavaStringToUTF16(Java_CreditCard_getNumber(env, jcard)));
160  card->SetRawInfo(
161      CREDIT_CARD_EXP_MONTH,
162      ConvertJavaStringToUTF16(Java_CreditCard_getMonth(env, jcard)));
163  card->SetRawInfo(
164      CREDIT_CARD_EXP_4_DIGIT_YEAR,
165      ConvertJavaStringToUTF16(Java_CreditCard_getYear(env, jcard)));
166}
167
168}  // namespace
169
170PersonalDataManagerAndroid::PersonalDataManagerAndroid(JNIEnv* env,
171                                                       jobject obj)
172    : weak_java_obj_(env, obj),
173      personal_data_manager_(PersonalDataManagerFactory::GetForProfile(
174          ProfileManager::GetActiveUserProfile())) {
175  personal_data_manager_->AddObserver(this);
176}
177
178PersonalDataManagerAndroid::~PersonalDataManagerAndroid() {
179  personal_data_manager_->RemoveObserver(this);
180}
181
182jint PersonalDataManagerAndroid::GetProfileCount(JNIEnv* unused_env,
183                                                 jobject unused_obj) {
184  return personal_data_manager_->GetProfiles().size();
185}
186
187ScopedJavaLocalRef<jobject> PersonalDataManagerAndroid::GetProfileByIndex(
188    JNIEnv* env,
189    jobject unused_obj,
190    jint index) {
191  const std::vector<AutofillProfile*>& profiles =
192      personal_data_manager_->GetProfiles();
193  size_t index_size_t = static_cast<size_t>(index);
194  DCHECK_LT(index_size_t, profiles.size());
195  return CreateJavaProfileFromNative(env, *profiles[index_size_t]);
196}
197
198ScopedJavaLocalRef<jobject> PersonalDataManagerAndroid::GetProfileByGUID(
199    JNIEnv* env,
200    jobject unused_obj,
201    jstring jguid) {
202  AutofillProfile* profile = personal_data_manager_->GetProfileByGUID(
203      ConvertJavaStringToUTF8(env, jguid));
204  if (!profile)
205    return ScopedJavaLocalRef<jobject>();
206
207  return CreateJavaProfileFromNative(env, *profile);
208}
209
210ScopedJavaLocalRef<jstring> PersonalDataManagerAndroid::SetProfile(
211    JNIEnv* env,
212    jobject unused_obj,
213    jobject jprofile) {
214  std::string guid = ConvertJavaStringToUTF8(
215      env,
216      Java_AutofillProfile_getGUID(env, jprofile).obj());
217
218  AutofillProfile profile;
219  PopulateNativeProfileFromJava(jprofile, env, &profile);
220
221  if (guid.empty()) {
222    personal_data_manager_->AddProfile(profile);
223  } else {
224    profile.set_guid(guid);
225    personal_data_manager_->UpdateProfile(profile);
226  }
227
228  return ConvertUTF8ToJavaString(env, profile.guid());
229}
230
231jint PersonalDataManagerAndroid::GetCreditCardCount(JNIEnv* unused_env,
232                                                    jobject unused_obj) {
233  return personal_data_manager_->GetCreditCards().size();
234}
235
236ScopedJavaLocalRef<jobject> PersonalDataManagerAndroid::GetCreditCardByIndex(
237    JNIEnv* env,
238    jobject unused_obj,
239    jint index) {
240  const std::vector<CreditCard*>& credit_cards =
241      personal_data_manager_->GetCreditCards();
242  size_t index_size_t = static_cast<size_t>(index);
243  DCHECK_LT(index_size_t, credit_cards.size());
244  return CreateJavaCreditCardFromNative(env, *credit_cards[index_size_t]);
245}
246
247ScopedJavaLocalRef<jobject> PersonalDataManagerAndroid::GetCreditCardByGUID(
248    JNIEnv* env,
249    jobject unused_obj,
250    jstring jguid) {
251  CreditCard* card = personal_data_manager_->GetCreditCardByGUID(
252          ConvertJavaStringToUTF8(env, jguid));
253  if (!card)
254    return ScopedJavaLocalRef<jobject>();
255
256  return CreateJavaCreditCardFromNative(env, *card);
257}
258
259ScopedJavaLocalRef<jstring> PersonalDataManagerAndroid::SetCreditCard(
260    JNIEnv* env,
261    jobject unused_obj,
262    jobject jcard) {
263  std::string guid = ConvertJavaStringToUTF8(
264       env,
265       Java_CreditCard_getGUID(env, jcard).obj());
266
267  CreditCard card;
268  PopulateNativeCreditCardFromJava(jcard, env, &card);
269
270  if (guid.empty()) {
271    personal_data_manager_->AddCreditCard(card);
272  } else {
273    card.set_guid(guid);
274    personal_data_manager_->UpdateCreditCard(card);
275  }
276  return ConvertUTF8ToJavaString(env, card.guid());
277}
278
279ScopedJavaLocalRef<jobjectArray> PersonalDataManagerAndroid::GetProfileLabels(
280    JNIEnv* env,
281    jobject unused_obj) {
282  std::vector<base::string16> labels;
283  AutofillProfile::CreateInferredLabels(
284      personal_data_manager_->GetProfiles(),
285      NULL,
286      NAME_FULL,
287      2,
288      g_browser_process->GetApplicationLocale(),
289      &labels);
290
291  return base::android::ToJavaArrayOfStrings(env, labels);
292}
293
294void PersonalDataManagerAndroid::RemoveByGUID(JNIEnv* env,
295                                              jobject unused_obj,
296                                              jstring jguid) {
297  personal_data_manager_->RemoveByGUID(ConvertJavaStringToUTF8(env, jguid));
298}
299
300void PersonalDataManagerAndroid::OnPersonalDataChanged() {
301  JNIEnv* env = base::android::AttachCurrentThread();
302  if (weak_java_obj_.get(env).is_null())
303    return;
304
305  Java_PersonalDataManager_personalDataChanged(env,
306                                               weak_java_obj_.get(env).obj());
307}
308
309// static
310bool PersonalDataManagerAndroid::Register(JNIEnv* env) {
311  return RegisterNativesImpl(env);
312}
313
314// Returns whether the Autofill feature is enabled.
315static jboolean IsAutofillEnabled(JNIEnv* env, jclass clazz) {
316  return GetPrefs()->GetBoolean(autofill::prefs::kAutofillEnabled);
317}
318
319// Enables or disables the Autofill feature.
320static void SetAutofillEnabled(JNIEnv* env, jclass clazz, jboolean enable) {
321  GetPrefs()->SetBoolean(autofill::prefs::kAutofillEnabled, enable);
322}
323
324// Returns whether Autofill feature is managed.
325static jboolean IsAutofillManaged(JNIEnv* env, jclass clazz) {
326  return GetPrefs()->IsManagedPreference(autofill::prefs::kAutofillEnabled);
327}
328
329// Returns an ISO 3166-1-alpha-2 country code for a |jcountry_name| using
330// the application locale, or an empty string.
331static jstring ToCountryCode(JNIEnv* env, jclass clazz, jstring jcountry_name) {
332  return ConvertUTF8ToJavaString(
333      env,
334      AutofillCountry::GetCountryCode(
335          base::android::ConvertJavaStringToUTF16(env, jcountry_name),
336          g_browser_process->GetApplicationLocale())).Release();
337}
338
339static jlong Init(JNIEnv* env, jobject obj) {
340  PersonalDataManagerAndroid* personal_data_manager_android =
341      new PersonalDataManagerAndroid(env, obj);
342  return reinterpret_cast<intptr_t>(personal_data_manager_android);
343}
344
345}  // namespace autofill
346