Add more checks to investigate SupervisedUserPrefStore crash at startup.
[chromium-blink-merge.git] / chrome / browser / sync / profile_sync_service_android.cc
bloba8914fc0af7107c2cc72823f046f813ba7ba7450
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_string.h"
9 #include "base/bind.h"
10 #include "base/i18n/time_formatting.h"
11 #include "base/json/json_writer.h"
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/prefs/pref_service.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/time/time.h"
17 #include "chrome/browser/browser_process.h"
18 #include "chrome/browser/profiles/profile_manager.h"
19 #include "chrome/browser/signin/signin_manager_factory.h"
20 #include "chrome/browser/sync/about_sync_util.h"
21 #include "chrome/browser/sync/profile_sync_service.h"
22 #include "chrome/browser/sync/profile_sync_service_factory.h"
23 #include "chrome/browser/sync/sync_ui_util.h"
24 #include "chrome/grit/generated_resources.h"
25 #include "components/signin/core/browser/signin_manager.h"
26 #include "components/sync_driver/pref_names.h"
27 #include "components/sync_driver/sync_prefs.h"
28 #include "content/public/browser/browser_thread.h"
29 #include "google/cacheinvalidation/types.pb.h"
30 #include "google_apis/gaia/gaia_constants.h"
31 #include "google_apis/gaia/google_service_auth_error.h"
32 #include "jni/ProfileSyncService_jni.h"
33 #include "sync/internal_api/public/network_resources.h"
34 #include "sync/internal_api/public/read_transaction.h"
35 #include "ui/base/l10n/l10n_util.h"
37 using base::android::AttachCurrentThread;
38 using base::android::CheckException;
39 using base::android::ConvertJavaStringToUTF8;
40 using base::android::ConvertUTF8ToJavaString;
41 using base::android::ScopedJavaLocalRef;
42 using content::BrowserThread;
44 namespace {
46 // This enum contains the list of sync ModelTypes that Android can register for
47 // invalidations for.
49 // A Java counterpart will be generated for this enum.
50 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.sync
51 enum ModelTypeSelection {
52 AUTOFILL = 1 << 0,
53 BOOKMARK = 1 << 1,
54 PASSWORD = 1 << 2,
55 SESSION = 1 << 3,
56 TYPED_URL = 1 << 4,
57 AUTOFILL_PROFILE = 1 << 5,
58 HISTORY_DELETE_DIRECTIVE = 1 << 6,
59 PROXY_TABS = 1 << 7,
60 FAVICON_IMAGE = 1 << 8,
61 FAVICON_TRACKING = 1 << 9,
62 NIGORI = 1 << 10,
63 DEVICE_INFO = 1 << 11,
64 EXPERIMENTS = 1 << 12,
65 SUPERVISED_USER_SETTING = 1 << 13,
66 SUPERVISED_USER_WHITELIST = 1 << 14,
69 } // namespace
71 ProfileSyncServiceAndroid::ProfileSyncServiceAndroid(JNIEnv* env, jobject obj)
72 : profile_(NULL),
73 sync_service_(NULL),
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";
78 return;
81 profile_ = ProfileManager::GetActiveUserProfile();
82 if (profile_ == NULL) {
83 NOTREACHED() << "Sync Init: Profile not found.";
84 return;
87 sync_prefs_.reset(new sync_driver::SyncPrefs(profile_->GetPrefs()));
89 sync_service_ =
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() {
105 RemoveObserver();
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 void ProfileSyncServiceAndroid::EnableSync(JNIEnv* env, jobject) {
116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
117 // Don't need to do anything if we're already enabled.
118 if (sync_prefs_->IsStartSuppressed())
119 sync_service_->UnsuppressAndStart();
120 else
121 DVLOG(2) << "Ignoring call to EnableSync() because sync is already enabled";
124 void ProfileSyncServiceAndroid::DisableSync(JNIEnv* env, jobject) {
125 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
126 // Don't need to do anything if we're already disabled.
127 if (!sync_prefs_->IsStartSuppressed()) {
128 sync_service_->StopAndSuppress();
129 } else {
130 DVLOG(2)
131 << "Ignoring call to DisableSync() because sync is already disabled";
135 void ProfileSyncServiceAndroid::SignInSync(JNIEnv* env, jobject) {
136 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
137 // Just return if sync already has everything it needs to start up (sync
138 // should start up automatically as long as it has credentials). This can
139 // happen normally if (for example) the user closes and reopens the sync
140 // settings window quickly during initial startup.
141 if (sync_service_->IsSyncEnabledAndLoggedIn() &&
142 sync_service_->IsOAuthRefreshTokenAvailable() &&
143 sync_service_->HasSyncSetupCompleted()) {
144 return;
147 // Enable sync (if we don't have credentials yet, this will enable sync but
148 // will not start it up - sync will start once credentials arrive).
149 sync_service_->UnsuppressAndStart();
152 void ProfileSyncServiceAndroid::SignOutSync(JNIEnv* env, jobject) {
153 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
154 DCHECK(profile_);
155 sync_service_->DisableForUser();
157 // Need to clear suppress start flag manually
158 sync_prefs_->SetStartSuppressed(false);
161 void ProfileSyncServiceAndroid::FlushDirectory(JNIEnv* env, jobject) {
162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
163 sync_service_->FlushDirectory();
166 ScopedJavaLocalRef<jstring> ProfileSyncServiceAndroid::QuerySyncStatusSummary(
167 JNIEnv* env, jobject) {
168 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
169 DCHECK(profile_);
170 std::string status(sync_service_->QuerySyncStatusSummaryString());
171 return ConvertUTF8ToJavaString(env, status);
174 jboolean ProfileSyncServiceAndroid::SetSyncSessionsId(
175 JNIEnv* env, jobject obj, jstring tag) {
176 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
177 DCHECK(profile_);
178 std::string machine_tag = ConvertJavaStringToUTF8(env, tag);
179 sync_prefs_->SetSyncSessionsGUID(machine_tag);
180 return true;
183 jint ProfileSyncServiceAndroid::GetAuthError(JNIEnv* env, jobject) {
184 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
185 return sync_service_->GetAuthError().state();
188 jboolean ProfileSyncServiceAndroid::IsEncryptEverythingEnabled(
189 JNIEnv* env, jobject) {
190 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
191 return sync_service_->EncryptEverythingEnabled();
194 jboolean ProfileSyncServiceAndroid::IsSyncInitialized(JNIEnv* env, jobject) {
195 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
196 return sync_service_->backend_initialized();
199 jboolean ProfileSyncServiceAndroid::IsFirstSetupInProgress(
200 JNIEnv* env, jobject) {
201 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
202 return sync_service_->FirstSetupInProgress();
205 jboolean ProfileSyncServiceAndroid::IsEncryptEverythingAllowed(
206 JNIEnv* env, jobject obj) {
207 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
208 return sync_service_->EncryptEverythingAllowed();
211 jboolean ProfileSyncServiceAndroid::IsPassphraseRequired(JNIEnv* env, jobject) {
212 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
213 return sync_service_->IsPassphraseRequired();
216 jboolean ProfileSyncServiceAndroid::IsPassphraseRequiredForDecryption(
217 JNIEnv* env, jobject obj) {
218 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
219 // In case of CUSTOM_PASSPHRASE we always sync passwords. Prompt the user for
220 // a passphrase if cryptographer has any pending keys.
221 if (sync_service_->GetPassphraseType() == syncer::CUSTOM_PASSPHRASE) {
222 return !IsCryptographerReady(env, obj);
224 if (sync_service_->IsPassphraseRequiredForDecryption()) {
225 // Passwords datatype should never prompt for a passphrase, except when
226 // user is using a custom passphrase. Do not prompt for a passphrase if
227 // passwords are the only encrypted datatype. This prevents a temporary
228 // notification for passphrase when PSS has not completed configuring
229 // DataTypeManager, after configuration password datatype shall be disabled.
230 const syncer::ModelTypeSet encrypted_types =
231 sync_service_->GetEncryptedDataTypes();
232 return !encrypted_types.Equals(syncer::ModelTypeSet(syncer::PASSWORDS));
234 return false;
237 jboolean ProfileSyncServiceAndroid::IsPassphraseRequiredForExternalType(
238 JNIEnv* env, jobject) {
239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
240 return
241 sync_service_->passphrase_required_reason() == syncer::REASON_DECRYPTION;
244 jboolean ProfileSyncServiceAndroid::IsUsingSecondaryPassphrase(
245 JNIEnv* env, jobject) {
246 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
247 return sync_service_->IsUsingSecondaryPassphrase();
250 jboolean ProfileSyncServiceAndroid::SetDecryptionPassphrase(
251 JNIEnv* env, jobject obj, jstring passphrase) {
252 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
253 std::string key = ConvertJavaStringToUTF8(env, passphrase);
254 return sync_service_->SetDecryptionPassphrase(key);
257 void ProfileSyncServiceAndroid::SetEncryptionPassphrase(
258 JNIEnv* env, jobject obj, jstring passphrase, jboolean is_gaia) {
259 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
260 std::string key = ConvertJavaStringToUTF8(env, passphrase);
261 sync_service_->SetEncryptionPassphrase(
262 key,
263 is_gaia ? ProfileSyncService::IMPLICIT : ProfileSyncService::EXPLICIT);
266 jboolean ProfileSyncServiceAndroid::IsCryptographerReady(JNIEnv* env, jobject) {
267 syncer::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare());
268 return sync_service_->IsCryptographerReady(&trans);
271 jint ProfileSyncServiceAndroid::GetPassphraseType(JNIEnv* env, jobject) {
272 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
273 return sync_service_->GetPassphraseType();
276 jboolean ProfileSyncServiceAndroid::HasExplicitPassphraseTime(
277 JNIEnv* env, jobject) {
278 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
279 base::Time passphrase_time = sync_service_->GetExplicitPassphraseTime();
280 return !passphrase_time.is_null();
283 jlong ProfileSyncServiceAndroid::GetExplicitPassphraseTime(
284 JNIEnv* env, jobject) {
285 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
286 base::Time passphrase_time = sync_service_->GetExplicitPassphraseTime();
287 return passphrase_time.ToJavaTime();
290 ScopedJavaLocalRef<jstring>
291 ProfileSyncServiceAndroid::GetSyncEnterGooglePassphraseBodyWithDateText(
292 JNIEnv* env, jobject) {
293 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
294 base::Time passphrase_time = sync_service_->GetExplicitPassphraseTime();
295 base::string16 passphrase_time_str =
296 base::TimeFormatShortDate(passphrase_time);
297 return base::android::ConvertUTF16ToJavaString(env,
298 l10n_util::GetStringFUTF16(
299 IDS_SYNC_ENTER_GOOGLE_PASSPHRASE_BODY_WITH_DATE,
300 passphrase_time_str));
303 ScopedJavaLocalRef<jstring>
304 ProfileSyncServiceAndroid::GetSyncEnterCustomPassphraseBodyWithDateText(
305 JNIEnv* env, jobject) {
306 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
307 base::Time passphrase_time = sync_service_->GetExplicitPassphraseTime();
308 base::string16 passphrase_time_str =
309 base::TimeFormatShortDate(passphrase_time);
310 return base::android::ConvertUTF16ToJavaString(env,
311 l10n_util::GetStringFUTF16(IDS_SYNC_ENTER_PASSPHRASE_BODY_WITH_DATE,
312 passphrase_time_str));
315 ScopedJavaLocalRef<jstring>
316 ProfileSyncServiceAndroid::GetCurrentSignedInAccountText(
317 JNIEnv* env, jobject) {
318 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
319 const std::string& sync_username =
320 SigninManagerFactory::GetForProfile(profile_)->GetAuthenticatedUsername();
321 return base::android::ConvertUTF16ToJavaString(env,
322 l10n_util::GetStringFUTF16(
323 IDS_SYNC_ACCOUNT_SYNCING_TO_USER,
324 base::ASCIIToUTF16(sync_username)));
327 ScopedJavaLocalRef<jstring>
328 ProfileSyncServiceAndroid::GetSyncEnterCustomPassphraseBodyText(
329 JNIEnv* env, jobject) {
330 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
331 return ConvertUTF8ToJavaString(
332 env, l10n_util::GetStringUTF8(IDS_SYNC_ENTER_PASSPHRASE_BODY));
335 jboolean ProfileSyncServiceAndroid::IsSyncKeystoreMigrationDone(
336 JNIEnv* env, jobject) {
337 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
338 syncer::SyncStatus status;
339 bool is_status_valid = sync_service_->QueryDetailedSyncStatus(&status);
340 return is_status_valid && !status.keystore_migration_time.is_null();
343 jlong ProfileSyncServiceAndroid::GetEnabledDataTypes(JNIEnv* env,
344 jobject obj) {
345 syncer::ModelTypeSet types = sync_service_->GetActiveDataTypes();
346 types.PutAll(syncer::ControlTypes());
347 return ModelTypeSetToSelection(types);
350 void ProfileSyncServiceAndroid::SetPreferredDataTypes(
351 JNIEnv* env, jobject obj,
352 jboolean sync_everything,
353 jlong model_type_selection) {
354 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
355 syncer::ModelTypeSet types;
356 // Note: only user selectable types should be included here.
357 if (model_type_selection & AUTOFILL)
358 types.Put(syncer::AUTOFILL);
359 if (model_type_selection & BOOKMARK)
360 types.Put(syncer::BOOKMARKS);
361 if (model_type_selection & PASSWORD)
362 types.Put(syncer::PASSWORDS);
363 if (model_type_selection & PROXY_TABS)
364 types.Put(syncer::PROXY_TABS);
365 if (model_type_selection & TYPED_URL)
366 types.Put(syncer::TYPED_URLS);
367 DCHECK(syncer::UserSelectableTypes().HasAll(types));
368 sync_service_->OnUserChoseDatatypes(sync_everything, types);
371 void ProfileSyncServiceAndroid::SetSetupInProgress(
372 JNIEnv* env, jobject obj, jboolean in_progress) {
373 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
374 sync_service_->SetSetupInProgress(in_progress);
377 void ProfileSyncServiceAndroid::SetSyncSetupCompleted(
378 JNIEnv* env, jobject obj) {
379 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
380 sync_service_->SetSyncSetupCompleted();
383 jboolean ProfileSyncServiceAndroid::HasSyncSetupCompleted(
384 JNIEnv* env, jobject obj) {
385 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
386 return sync_service_->HasSyncSetupCompleted();
389 jboolean ProfileSyncServiceAndroid::IsStartSuppressed(
390 JNIEnv* env, jobject obj) {
391 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
392 return sync_prefs_->IsStartSuppressed();
395 void ProfileSyncServiceAndroid::EnableEncryptEverything(
396 JNIEnv* env, jobject obj) {
397 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
398 sync_service_->EnableEncryptEverything();
401 jboolean ProfileSyncServiceAndroid::HasKeepEverythingSynced(
402 JNIEnv* env, jobject) {
403 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
404 return sync_prefs_->HasKeepEverythingSynced();
407 jboolean ProfileSyncServiceAndroid::HasUnrecoverableError(
408 JNIEnv* env, jobject) {
409 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
410 return sync_service_->HasUnrecoverableError();
413 ScopedJavaLocalRef<jstring> ProfileSyncServiceAndroid::GetAboutInfoForTest(
414 JNIEnv* env, jobject) {
415 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
417 scoped_ptr<base::DictionaryValue> about_info =
418 sync_ui_util::ConstructAboutInformation(sync_service_);
419 std::string about_info_json;
420 base::JSONWriter::Write(about_info.get(), &about_info_json);
422 return ConvertUTF8ToJavaString(env, about_info_json);
425 jlong ProfileSyncServiceAndroid::GetLastSyncedTimeForTest(
426 JNIEnv* env, jobject obj) {
427 // Use profile preferences here instead of SyncPrefs to avoid an extra
428 // conversion, since SyncPrefs::GetLastSyncedTime() converts the stored value
429 // to to base::Time.
430 return static_cast<jlong>(
431 profile_->GetPrefs()->GetInt64(sync_driver::prefs::kSyncLastSyncedTime));
434 void ProfileSyncServiceAndroid::OverrideNetworkResourcesForTest(
435 JNIEnv* env,
436 jobject obj,
437 jlong network_resources) {
438 syncer::NetworkResources* resources =
439 reinterpret_cast<syncer::NetworkResources*>(network_resources);
440 sync_service_->OverrideNetworkResourcesForTest(
441 make_scoped_ptr<syncer::NetworkResources>(resources));
444 // static
445 jlong ProfileSyncServiceAndroid::ModelTypeSetToSelection(
446 syncer::ModelTypeSet types) {
447 jlong model_type_selection = 0;
448 if (types.Has(syncer::BOOKMARKS)) {
449 model_type_selection |= BOOKMARK;
451 if (types.Has(syncer::AUTOFILL)) {
452 model_type_selection |= AUTOFILL;
454 if (types.Has(syncer::AUTOFILL_PROFILE)) {
455 model_type_selection |= AUTOFILL_PROFILE;
457 if (types.Has(syncer::PASSWORDS)) {
458 model_type_selection |= PASSWORD;
460 if (types.Has(syncer::TYPED_URLS)) {
461 model_type_selection |= TYPED_URL;
463 if (types.Has(syncer::SESSIONS)) {
464 model_type_selection |= SESSION;
466 if (types.Has(syncer::HISTORY_DELETE_DIRECTIVES)) {
467 model_type_selection |= HISTORY_DELETE_DIRECTIVE;
469 if (types.Has(syncer::PROXY_TABS)) {
470 model_type_selection |= PROXY_TABS;
472 if (types.Has(syncer::FAVICON_IMAGES)) {
473 model_type_selection |= FAVICON_IMAGE;
475 if (types.Has(syncer::FAVICON_TRACKING)) {
476 model_type_selection |= FAVICON_TRACKING;
478 if (types.Has(syncer::DEVICE_INFO)) {
479 model_type_selection |= DEVICE_INFO;
481 if (types.Has(syncer::NIGORI)) {
482 model_type_selection |= NIGORI;
484 if (types.Has(syncer::EXPERIMENTS)) {
485 model_type_selection |= EXPERIMENTS;
487 if (types.Has(syncer::SUPERVISED_USER_SETTINGS)) {
488 model_type_selection |= SUPERVISED_USER_SETTING;
490 if (types.Has(syncer::SUPERVISED_USER_WHITELISTS)) {
491 model_type_selection |= SUPERVISED_USER_WHITELIST;
493 return model_type_selection;
496 // static
497 std::string ProfileSyncServiceAndroid::ModelTypeSelectionToStringForTest(
498 jlong model_type_selection) {
499 ScopedJavaLocalRef<jstring> string =
500 Java_ProfileSyncService_modelTypeSelectionToStringForTest(
501 AttachCurrentThread(), model_type_selection);
502 return ConvertJavaStringToUTF8(string);
505 // static
506 ProfileSyncServiceAndroid*
507 ProfileSyncServiceAndroid::GetProfileSyncServiceAndroid() {
508 return reinterpret_cast<ProfileSyncServiceAndroid*>(
509 Java_ProfileSyncService_getProfileSyncServiceAndroid(
510 AttachCurrentThread(), base::android::GetApplicationContext()));
513 static jlong Init(JNIEnv* env, jobject obj) {
514 ProfileSyncServiceAndroid* profile_sync_service_android =
515 new ProfileSyncServiceAndroid(env, obj);
516 profile_sync_service_android->Init();
517 return reinterpret_cast<intptr_t>(profile_sync_service_android);
520 // static
521 bool ProfileSyncServiceAndroid::Register(JNIEnv* env) {
522 return RegisterNativesImpl(env);