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.
5 #include "chrome/browser/sync/profile_sync_service_android.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_array.h"
9 #include "base/android/jni_string.h"
10 #include "base/bind.h"
11 #include "base/i18n/time_formatting.h"
12 #include "base/json/json_writer.h"
13 #include "base/logging.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/metrics/field_trial.h"
16 #include "base/prefs/pref_service.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/time/time.h"
19 #include "chrome/browser/browser_process.h"
20 #include "chrome/browser/profiles/profile_manager.h"
21 #include "chrome/browser/signin/signin_manager_factory.h"
22 #include "chrome/browser/sync/profile_sync_service.h"
23 #include "chrome/browser/sync/profile_sync_service_factory.h"
24 #include "chrome/browser/sync/sync_ui_util.h"
25 #include "chrome/common/channel_info.h"
26 #include "chrome/grit/generated_resources.h"
27 #include "components/signin/core/browser/signin_manager.h"
28 #include "components/sync_driver/about_sync_util.h"
29 #include "components/sync_driver/pref_names.h"
30 #include "components/sync_driver/sync_prefs.h"
31 #include "content/public/browser/browser_thread.h"
32 #include "google/cacheinvalidation/types.pb.h"
33 #include "google_apis/gaia/gaia_constants.h"
34 #include "google_apis/gaia/google_service_auth_error.h"
35 #include "jni/ProfileSyncService_jni.h"
36 #include "sync/internal_api/public/network_resources.h"
37 #include "sync/internal_api/public/read_transaction.h"
38 #include "ui/base/l10n/l10n_util.h"
40 using base::android::AttachCurrentThread
;
41 using base::android::CheckException
;
42 using base::android::ConvertJavaStringToUTF8
;
43 using base::android::ConvertUTF8ToJavaString
;
44 using base::android::ScopedJavaLocalRef
;
45 using content::BrowserThread
;
49 // Native callback for the JNI GetAllNodes method. When
50 // ProfileSyncService::GetAllNodes completes, this method is called and the
51 // results are sent to the Java callback.
52 void NativeGetAllNodesCallback(
53 const base::android::ScopedJavaGlobalRef
<jobject
>& callback
,
54 scoped_ptr
<base::ListValue
> result
) {
55 JNIEnv
* env
= base::android::AttachCurrentThread();
56 std::string json_string
;
57 if (!result
.get() || !base::JSONWriter::Write(*result
, &json_string
)) {
58 DVLOG(1) << "Writing as JSON failed. Passing empty string to Java code.";
59 json_string
= std::string();
62 ScopedJavaLocalRef
<jstring
> java_json_string
=
63 ConvertUTF8ToJavaString(env
, json_string
);
64 Java_ProfileSyncService_onGetAllNodesResult(env
,
66 java_json_string
.obj());
71 ProfileSyncServiceAndroid::ProfileSyncServiceAndroid(JNIEnv
* env
, jobject obj
)
74 weak_java_profile_sync_service_(env
, obj
) {
75 if (g_browser_process
== NULL
||
76 g_browser_process
->profile_manager() == NULL
) {
77 NOTREACHED() << "Browser process or profile manager not initialized";
81 profile_
= ProfileManager::GetActiveUserProfile();
82 if (profile_
== NULL
) {
83 NOTREACHED() << "Sync Init: Profile not found.";
87 sync_prefs_
.reset(new sync_driver::SyncPrefs(profile_
->GetPrefs()));
90 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile_
);
91 DCHECK(sync_service_
);
94 void ProfileSyncServiceAndroid::Init() {
95 sync_service_
->AddObserver(this);
98 void ProfileSyncServiceAndroid::RemoveObserver() {
99 if (sync_service_
->HasObserver(this)) {
100 sync_service_
->RemoveObserver(this);
104 ProfileSyncServiceAndroid::~ProfileSyncServiceAndroid() {
108 void ProfileSyncServiceAndroid::OnStateChanged() {
109 // Notify the java world that our sync state has changed.
110 JNIEnv
* env
= AttachCurrentThread();
111 Java_ProfileSyncService_syncStateChanged(
112 env
, weak_java_profile_sync_service_
.get(env
).obj());
115 jboolean
ProfileSyncServiceAndroid::IsPassphrasePrompted(JNIEnv
* env
,
117 const std::string group_name
=
118 base::FieldTrialList::FindFullName("LimitSyncPassphrasePrompt");
119 if (group_name
!= "Enabled")
121 return sync_prefs_
->IsPassphrasePrompted();
124 void ProfileSyncServiceAndroid::SetPassphrasePrompted(JNIEnv
* env
,
127 sync_prefs_
->SetPassphrasePrompted(prompted
);
130 void ProfileSyncServiceAndroid::RequestStart(JNIEnv
* env
, jobject
) {
131 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
132 sync_service_
->RequestStart();
135 void ProfileSyncServiceAndroid::RequestStop(JNIEnv
* env
, jobject
) {
136 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
137 sync_service_
->RequestStop(ProfileSyncService::KEEP_DATA
);
140 void ProfileSyncServiceAndroid::SignOutSync(JNIEnv
* env
, jobject
) {
141 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
143 sync_service_
->RequestStop(ProfileSyncService::CLEAR_DATA
);
146 void ProfileSyncServiceAndroid::FlushDirectory(JNIEnv
* env
, jobject
) {
147 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
148 sync_service_
->FlushDirectory();
151 ScopedJavaLocalRef
<jstring
> ProfileSyncServiceAndroid::QuerySyncStatusSummary(
152 JNIEnv
* env
, jobject
) {
153 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
155 std::string
status(sync_service_
->QuerySyncStatusSummaryString());
156 return ConvertUTF8ToJavaString(env
, status
);
159 void ProfileSyncServiceAndroid::GetAllNodes(JNIEnv
* env
,
162 base::android::ScopedJavaGlobalRef
<jobject
> java_callback
;
163 java_callback
.Reset(env
, callback
);
165 base::Callback
<void(scoped_ptr
<base::ListValue
>)> native_callback
=
166 base::Bind(&NativeGetAllNodesCallback
, java_callback
);
167 sync_service_
->GetAllNodes(native_callback
);
170 void ProfileSyncServiceAndroid::SetSyncSessionsId(
171 JNIEnv
* env
, jobject obj
, jstring tag
) {
172 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
174 std::string machine_tag
= ConvertJavaStringToUTF8(env
, tag
);
175 sync_prefs_
->SetSyncSessionsGUID(machine_tag
);
178 jint
ProfileSyncServiceAndroid::GetAuthError(JNIEnv
* env
, jobject
) {
179 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
180 return sync_service_
->GetAuthError().state();
183 jboolean
ProfileSyncServiceAndroid::IsEncryptEverythingEnabled(
184 JNIEnv
* env
, jobject
) {
185 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
186 return sync_service_
->IsEncryptEverythingEnabled();
189 jboolean
ProfileSyncServiceAndroid::IsBackendInitialized(JNIEnv
* env
, jobject
) {
190 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
191 return sync_service_
->IsBackendInitialized();
194 jboolean
ProfileSyncServiceAndroid::IsFirstSetupInProgress(
195 JNIEnv
* env
, jobject
) {
196 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
197 return sync_service_
->IsFirstSetupInProgress();
200 jboolean
ProfileSyncServiceAndroid::IsEncryptEverythingAllowed(
201 JNIEnv
* env
, jobject obj
) {
202 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
203 return sync_service_
->IsEncryptEverythingAllowed();
206 jboolean
ProfileSyncServiceAndroid::IsPassphraseRequired(JNIEnv
* env
, jobject
) {
207 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
208 return sync_service_
->IsPassphraseRequired();
211 jboolean
ProfileSyncServiceAndroid::IsPassphraseRequiredForDecryption(
212 JNIEnv
* env
, jobject obj
) {
213 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
214 return sync_service_
->IsPassphraseRequiredForDecryption();
217 jboolean
ProfileSyncServiceAndroid::IsUsingSecondaryPassphrase(
218 JNIEnv
* env
, jobject
) {
219 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
220 return sync_service_
->IsUsingSecondaryPassphrase();
223 jboolean
ProfileSyncServiceAndroid::SetDecryptionPassphrase(
224 JNIEnv
* env
, jobject obj
, jstring passphrase
) {
225 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
226 std::string key
= ConvertJavaStringToUTF8(env
, passphrase
);
227 return sync_service_
->SetDecryptionPassphrase(key
);
230 void ProfileSyncServiceAndroid::SetEncryptionPassphrase(
231 JNIEnv
* env
, jobject obj
, jstring passphrase
) {
232 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
233 std::string key
= ConvertJavaStringToUTF8(env
, passphrase
);
234 sync_service_
->SetEncryptionPassphrase(key
, ProfileSyncService::EXPLICIT
);
237 jboolean
ProfileSyncServiceAndroid::IsCryptographerReady(JNIEnv
* env
, jobject
) {
238 syncer::ReadTransaction
trans(FROM_HERE
, sync_service_
->GetUserShare());
239 return sync_service_
->IsCryptographerReady(&trans
);
242 jint
ProfileSyncServiceAndroid::GetPassphraseType(JNIEnv
* env
, jobject
) {
243 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
244 return sync_service_
->GetPassphraseType();
247 jboolean
ProfileSyncServiceAndroid::HasExplicitPassphraseTime(
248 JNIEnv
* env
, jobject
) {
249 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
250 base::Time passphrase_time
= sync_service_
->GetExplicitPassphraseTime();
251 return !passphrase_time
.is_null();
254 jlong
ProfileSyncServiceAndroid::GetExplicitPassphraseTime(
255 JNIEnv
* env
, jobject
) {
256 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
257 base::Time passphrase_time
= sync_service_
->GetExplicitPassphraseTime();
258 return passphrase_time
.ToJavaTime();
261 ScopedJavaLocalRef
<jstring
>
262 ProfileSyncServiceAndroid::GetSyncEnterGooglePassphraseBodyWithDateText(
263 JNIEnv
* env
, jobject
) {
264 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
265 base::Time passphrase_time
= sync_service_
->GetExplicitPassphraseTime();
266 base::string16 passphrase_time_str
=
267 base::TimeFormatShortDate(passphrase_time
);
268 return base::android::ConvertUTF16ToJavaString(env
,
269 l10n_util::GetStringFUTF16(
270 IDS_SYNC_ENTER_GOOGLE_PASSPHRASE_BODY_WITH_DATE
,
271 passphrase_time_str
));
274 ScopedJavaLocalRef
<jstring
>
275 ProfileSyncServiceAndroid::GetSyncEnterCustomPassphraseBodyWithDateText(
276 JNIEnv
* env
, jobject
) {
277 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
278 base::Time passphrase_time
= sync_service_
->GetExplicitPassphraseTime();
279 base::string16 passphrase_time_str
=
280 base::TimeFormatShortDate(passphrase_time
);
281 return base::android::ConvertUTF16ToJavaString(env
,
282 l10n_util::GetStringFUTF16(IDS_SYNC_ENTER_PASSPHRASE_BODY_WITH_DATE
,
283 passphrase_time_str
));
286 ScopedJavaLocalRef
<jstring
>
287 ProfileSyncServiceAndroid::GetCurrentSignedInAccountText(
288 JNIEnv
* env
, jobject
) {
289 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
290 const std::string
& sync_username
=
291 SigninManagerFactory::GetForProfile(profile_
)
292 ->GetAuthenticatedAccountInfo()
294 return base::android::ConvertUTF16ToJavaString(env
,
295 l10n_util::GetStringFUTF16(
296 IDS_SYNC_ACCOUNT_SYNCING_TO_USER
,
297 base::ASCIIToUTF16(sync_username
)));
300 ScopedJavaLocalRef
<jstring
>
301 ProfileSyncServiceAndroid::GetSyncEnterCustomPassphraseBodyText(
302 JNIEnv
* env
, jobject
) {
303 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
304 return ConvertUTF8ToJavaString(
305 env
, l10n_util::GetStringUTF8(IDS_SYNC_ENTER_PASSPHRASE_BODY
));
308 jboolean
ProfileSyncServiceAndroid::IsSyncKeystoreMigrationDone(
309 JNIEnv
* env
, jobject
) {
310 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
311 syncer::SyncStatus status
;
312 bool is_status_valid
= sync_service_
->QueryDetailedSyncStatus(&status
);
313 return is_status_valid
&& !status
.keystore_migration_time
.is_null();
316 ScopedJavaLocalRef
<jintArray
> ProfileSyncServiceAndroid::GetActiveDataTypes(
317 JNIEnv
* env
, jobject obj
) {
318 syncer::ModelTypeSet types
= sync_service_
->GetActiveDataTypes();
319 types
.PutAll(syncer::ControlTypes());
320 return ModelTypeSetToJavaIntArray(env
, types
);
323 ScopedJavaLocalRef
<jintArray
> ProfileSyncServiceAndroid::GetPreferredDataTypes(
324 JNIEnv
* env
, jobject obj
) {
325 syncer::ModelTypeSet types
= sync_service_
->GetPreferredDataTypes();
326 types
.PutAll(syncer::ControlTypes());
327 return ModelTypeSetToJavaIntArray(env
, types
);
330 void ProfileSyncServiceAndroid::SetPreferredDataTypes(
331 JNIEnv
* env
, jobject obj
,
332 jboolean sync_everything
,
333 jintArray model_type_array
) {
334 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
335 std::vector
<int> types_vector
;
336 base::android::JavaIntArrayToIntVector(env
, model_type_array
, &types_vector
);
337 syncer::ModelTypeSet types
;
338 for (size_t i
= 0; i
< types_vector
.size(); i
++) {
339 types
.Put(static_cast<syncer::ModelType
>(types_vector
[i
]));
341 types
.RetainAll(syncer::UserSelectableTypes());
342 sync_service_
->OnUserChoseDatatypes(sync_everything
, types
);
345 void ProfileSyncServiceAndroid::SetSetupInProgress(
346 JNIEnv
* env
, jobject obj
, jboolean in_progress
) {
347 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
348 sync_service_
->SetSetupInProgress(in_progress
);
351 void ProfileSyncServiceAndroid::SetSyncSetupCompleted(
352 JNIEnv
* env
, jobject obj
) {
353 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
354 sync_service_
->SetSyncSetupCompleted();
357 jboolean
ProfileSyncServiceAndroid::HasSyncSetupCompleted(
358 JNIEnv
* env
, jobject obj
) {
359 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
360 return sync_service_
->HasSyncSetupCompleted();
363 jboolean
ProfileSyncServiceAndroid::IsSyncRequested(
364 JNIEnv
* env
, jobject obj
) {
365 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
366 return sync_service_
->IsSyncRequested();
369 jboolean
ProfileSyncServiceAndroid::IsSyncActive(JNIEnv
* env
, jobject obj
) {
370 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
371 return sync_service_
->IsSyncActive();
374 void ProfileSyncServiceAndroid::EnableEncryptEverything(
375 JNIEnv
* env
, jobject obj
) {
376 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
377 sync_service_
->EnableEncryptEverything();
380 jboolean
ProfileSyncServiceAndroid::HasKeepEverythingSynced(
381 JNIEnv
* env
, jobject
) {
382 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
383 return sync_prefs_
->HasKeepEverythingSynced();
386 jboolean
ProfileSyncServiceAndroid::HasUnrecoverableError(
387 JNIEnv
* env
, jobject
) {
388 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
389 return sync_service_
->HasUnrecoverableError();
392 ScopedJavaLocalRef
<jstring
> ProfileSyncServiceAndroid::GetAboutInfoForTest(
393 JNIEnv
* env
, jobject
) {
394 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
396 scoped_ptr
<base::DictionaryValue
> about_info
=
397 sync_ui_util::ConstructAboutInformation(sync_service_
,
398 sync_service_
->signin(),
399 chrome::GetChannel());
400 std::string about_info_json
;
401 base::JSONWriter::Write(*about_info
, &about_info_json
);
403 return ConvertUTF8ToJavaString(env
, about_info_json
);
406 jlong
ProfileSyncServiceAndroid::GetLastSyncedTimeForTest(
407 JNIEnv
* env
, jobject obj
) {
408 // Use profile preferences here instead of SyncPrefs to avoid an extra
409 // conversion, since SyncPrefs::GetLastSyncedTime() converts the stored value
411 return static_cast<jlong
>(
412 profile_
->GetPrefs()->GetInt64(sync_driver::prefs::kSyncLastSyncedTime
));
415 void ProfileSyncServiceAndroid::OverrideNetworkResourcesForTest(
418 jlong network_resources
) {
419 syncer::NetworkResources
* resources
=
420 reinterpret_cast<syncer::NetworkResources
*>(network_resources
);
421 sync_service_
->OverrideNetworkResourcesForTest(
422 make_scoped_ptr
<syncer::NetworkResources
>(resources
));
426 ScopedJavaLocalRef
<jintArray
>
427 ProfileSyncServiceAndroid::ModelTypeSetToJavaIntArray(
429 syncer::ModelTypeSet types
) {
430 std::vector
<int> type_vector
;
431 for (syncer::ModelTypeSet::Iterator it
= types
.First(); it
.Good(); it
.Inc()) {
432 type_vector
.push_back(it
.Get());
434 return base::android::ToJavaIntArray(env
, type_vector
);
438 ProfileSyncServiceAndroid
*
439 ProfileSyncServiceAndroid::GetProfileSyncServiceAndroid() {
440 return reinterpret_cast<ProfileSyncServiceAndroid
*>(
441 Java_ProfileSyncService_getProfileSyncServiceAndroid(
442 AttachCurrentThread()));
445 static jlong
Init(JNIEnv
* env
, const JavaParamRef
<jobject
>& obj
) {
446 ProfileSyncServiceAndroid
* profile_sync_service_android
=
447 new ProfileSyncServiceAndroid(env
, obj
);
448 profile_sync_service_android
->Init();
449 return reinterpret_cast<intptr_t>(profile_sync_service_android
);
453 bool ProfileSyncServiceAndroid::Register(JNIEnv
* env
) {
454 return RegisterNativesImpl(env
);