Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync / profile_sync_service_android.cc
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/sync/profile_sync_service_android.h"
6
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/chrome_notification_types.h"
19 #include "chrome/browser/profiles/profile_manager.h"
20 #include "chrome/browser/signin/signin_manager.h"
21 #include "chrome/browser/signin/signin_manager_factory.h"
22 #include "chrome/browser/sync/about_sync_util.h"
23 #include "chrome/browser/sync/profile_sync_service.h"
24 #include "chrome/browser/sync/profile_sync_service_factory.h"
25 #include "chrome/browser/sync/sync_prefs.h"
26 #include "chrome/browser/sync/sync_ui_util.h"
27 #include "chrome/common/pref_names.h"
28 #include "content/public/browser/browser_thread.h"
29 #include "content/public/browser/notification_service.h"
30 #include "content/public/browser/notification_source.h"
31 #include "google/cacheinvalidation/types.pb.h"
32 #include "google_apis/gaia/gaia_constants.h"
33 #include "google_apis/gaia/google_service_auth_error.h"
34 #include "grit/generated_resources.h"
35 #include "jni/ProfileSyncService_jni.h"
36 #include "sync/internal_api/public/read_transaction.h"
37 #include "sync/notifier/object_id_invalidation_map.h"
38 #include "ui/base/l10n/l10n_util.h"
39
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;
46
47 namespace {
48
49 enum {
50 #define DEFINE_MODEL_TYPE_SELECTION(name,value)  name = value,
51 #include "chrome/browser/sync/profile_sync_service_model_type_selection_android.h"
52 #undef DEFINE_MODEL_TYPE_SELECTION
53 };
54
55 }  // namespace
56
57 ProfileSyncServiceAndroid::ProfileSyncServiceAndroid(JNIEnv* env, jobject obj)
58     : profile_(NULL),
59       sync_service_(NULL),
60       weak_java_profile_sync_service_(env, obj) {
61   if (g_browser_process == NULL ||
62       g_browser_process->profile_manager() == NULL) {
63     NOTREACHED() << "Browser process or profile manager not initialized";
64     return;
65   }
66
67   profile_ = ProfileManager::GetActiveUserProfile();
68   if (profile_ == NULL) {
69     NOTREACHED() << "Sync Init: Profile not found.";
70     return;
71   }
72
73   sync_prefs_.reset(new browser_sync::SyncPrefs(profile_->GetPrefs()));
74
75   sync_service_ =
76       ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile_);
77   DCHECK(sync_service_);
78 }
79
80 void ProfileSyncServiceAndroid::Init() {
81   sync_service_->AddObserver(this);
82 }
83
84 void ProfileSyncServiceAndroid::RemoveObserver() {
85   if (sync_service_->HasObserver(this)) {
86     sync_service_->RemoveObserver(this);
87   }
88 }
89
90 ProfileSyncServiceAndroid::~ProfileSyncServiceAndroid() {
91   RemoveObserver();
92 }
93
94 void ProfileSyncServiceAndroid::SendNudgeNotification(
95     int object_source,
96     const std::string& str_object_id,
97     int64 version,
98     const std::string& state) {
99   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
100
101   // TODO(nileshagrawal): Merge this with ChromeInvalidationClient::Invalidate.
102   // Construct the ModelTypeStateMap and send it over with the notification.
103   invalidation::ObjectId object_id(
104       object_source,
105       str_object_id);
106   syncer::ObjectIdInvalidationMap object_ids_with_states;
107   if (version == ipc::invalidation::Constants::UNKNOWN) {
108     object_ids_with_states.Insert(
109         syncer::Invalidation::InitUnknownVersion(object_id));
110   } else {
111     ObjectIdVersionMap::iterator it =
112         max_invalidation_versions_.find(object_id);
113     if ((it != max_invalidation_versions_.end()) &&
114         (version <= it->second)) {
115       DVLOG(1) << "Dropping redundant invalidation with version " << version;
116       return;
117     }
118     max_invalidation_versions_[object_id] = version;
119     object_ids_with_states.Insert(
120         syncer::Invalidation::Init(object_id, version, state));
121   }
122
123   content::NotificationService::current()->Notify(
124       chrome::NOTIFICATION_SYNC_REFRESH_REMOTE,
125       content::Source<Profile>(profile_),
126       content::Details<const syncer::ObjectIdInvalidationMap>(
127           &object_ids_with_states));
128 }
129
130 void ProfileSyncServiceAndroid::OnStateChanged() {
131   // Notify the java world that our sync state has changed.
132   JNIEnv* env = AttachCurrentThread();
133   Java_ProfileSyncService_syncStateChanged(
134       env, weak_java_profile_sync_service_.get(env).obj());
135 }
136
137 void ProfileSyncServiceAndroid::EnableSync(JNIEnv* env, jobject) {
138   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
139   // Don't need to do anything if we're already enabled.
140   if (sync_prefs_->IsStartSuppressed())
141     sync_service_->UnsuppressAndStart();
142   else
143     DVLOG(2) << "Ignoring call to EnableSync() because sync is already enabled";
144 }
145
146 void ProfileSyncServiceAndroid::DisableSync(JNIEnv* env, jobject) {
147   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
148   // Don't need to do anything if we're already disabled.
149   if (!sync_prefs_->IsStartSuppressed()) {
150     sync_service_->StopAndSuppress();
151   } else {
152     DVLOG(2)
153         << "Ignoring call to DisableSync() because sync is already disabled";
154   }
155 }
156
157 void ProfileSyncServiceAndroid::SignInSync(JNIEnv* env, jobject) {
158   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
159   // Just return if sync already has everything it needs to start up (sync
160   // should start up automatically as long as it has credentials). This can
161   // happen normally if (for example) the user closes and reopens the sync
162   // settings window quickly during initial startup.
163   if (sync_service_->IsSyncEnabledAndLoggedIn() &&
164       sync_service_->IsOAuthRefreshTokenAvailable() &&
165       sync_service_->HasSyncSetupCompleted()) {
166     return;
167   }
168
169   // Enable sync (if we don't have credentials yet, this will enable sync but
170   // will not start it up - sync will start once credentials arrive).
171   sync_service_->UnsuppressAndStart();
172 }
173
174 void ProfileSyncServiceAndroid::SignOutSync(JNIEnv* env, jobject) {
175   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
176   DCHECK(profile_);
177   sync_service_->DisableForUser();
178
179   // Need to clear suppress start flag manually
180   sync_prefs_->SetStartSuppressed(false);
181 }
182
183 ScopedJavaLocalRef<jstring> ProfileSyncServiceAndroid::QuerySyncStatusSummary(
184     JNIEnv* env, jobject) {
185   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
186   DCHECK(profile_);
187   std::string status(sync_service_->QuerySyncStatusSummaryString());
188   return ConvertUTF8ToJavaString(env, status);
189 }
190
191 jboolean ProfileSyncServiceAndroid::SetSyncSessionsId(
192     JNIEnv* env, jobject obj, jstring tag) {
193   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
194   DCHECK(profile_);
195   std::string machine_tag = ConvertJavaStringToUTF8(env, tag);
196   sync_prefs_->SetSyncSessionsGUID(machine_tag);
197   return true;
198 }
199
200 jint ProfileSyncServiceAndroid::GetAuthError(JNIEnv* env, jobject) {
201   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
202   return sync_service_->GetAuthError().state();
203 }
204
205 jboolean ProfileSyncServiceAndroid::IsEncryptEverythingEnabled(
206     JNIEnv* env, jobject) {
207   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
208   return sync_service_->EncryptEverythingEnabled();
209 }
210
211 jboolean ProfileSyncServiceAndroid::IsSyncInitialized(JNIEnv* env, jobject) {
212   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
213   return sync_service_->sync_initialized();
214 }
215
216 jboolean ProfileSyncServiceAndroid::IsFirstSetupInProgress(
217     JNIEnv* env, jobject) {
218   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
219   return sync_service_->FirstSetupInProgress();
220 }
221
222 jboolean ProfileSyncServiceAndroid::IsPassphraseRequired(JNIEnv* env, jobject) {
223   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
224   return sync_service_->IsPassphraseRequired();
225 }
226
227 jboolean ProfileSyncServiceAndroid::IsPassphraseRequiredForDecryption(
228     JNIEnv* env, jobject obj) {
229   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
230   // In case of CUSTOM_PASSPHRASE we always sync passwords. Prompt the user for
231   // a passphrase if cryptographer has any pending keys.
232   if (sync_service_->GetPassphraseType() == syncer::CUSTOM_PASSPHRASE) {
233     return !IsCryptographerReady(env, obj);
234   }
235   if (sync_service_->IsPassphraseRequiredForDecryption()) {
236     // Passwords datatype should never prompt for a passphrase, except when
237     // user is using a custom passphrase. Do not prompt for a passphrase if
238     // passwords are the only encrypted datatype. This prevents a temporary
239     // notification for passphrase  when PSS has not completed configuring
240     // DataTypeManager, after configuration password datatype shall be disabled.
241     const syncer::ModelTypeSet encrypted_types =
242         sync_service_->GetEncryptedDataTypes();
243     return !encrypted_types.Equals(syncer::ModelTypeSet(syncer::PASSWORDS));
244   }
245   return false;
246 }
247
248 jboolean ProfileSyncServiceAndroid::IsPassphraseRequiredForExternalType(
249     JNIEnv* env, jobject) {
250   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
251   return
252       sync_service_->passphrase_required_reason() == syncer::REASON_DECRYPTION;
253 }
254
255 jboolean ProfileSyncServiceAndroid::IsUsingSecondaryPassphrase(
256     JNIEnv* env, jobject) {
257   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
258   return sync_service_->IsUsingSecondaryPassphrase();
259 }
260
261 jboolean ProfileSyncServiceAndroid::SetDecryptionPassphrase(
262     JNIEnv* env, jobject obj, jstring passphrase) {
263   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
264   std::string key = ConvertJavaStringToUTF8(env, passphrase);
265   return sync_service_->SetDecryptionPassphrase(key);
266 }
267
268 void ProfileSyncServiceAndroid::SetEncryptionPassphrase(
269     JNIEnv* env, jobject obj, jstring passphrase, jboolean is_gaia) {
270   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
271   std::string key = ConvertJavaStringToUTF8(env, passphrase);
272   sync_service_->SetEncryptionPassphrase(
273       key,
274       is_gaia ? ProfileSyncService::IMPLICIT : ProfileSyncService::EXPLICIT);
275 }
276
277 jboolean ProfileSyncServiceAndroid::IsCryptographerReady(JNIEnv* env, jobject) {
278   syncer::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare());
279   return sync_service_->IsCryptographerReady(&trans);
280 }
281
282 jint ProfileSyncServiceAndroid::GetPassphraseType(JNIEnv* env, jobject) {
283   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
284   return sync_service_->GetPassphraseType();
285 }
286
287 jboolean ProfileSyncServiceAndroid::HasExplicitPassphraseTime(
288     JNIEnv* env, jobject) {
289   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
290   base::Time passphrase_time = sync_service_->GetExplicitPassphraseTime();
291   return !passphrase_time.is_null();
292 }
293
294 ScopedJavaLocalRef<jstring>
295     ProfileSyncServiceAndroid::GetSyncEnterGooglePassphraseBodyWithDateText(
296         JNIEnv* env, jobject) {
297   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
298   base::Time passphrase_time = sync_service_->GetExplicitPassphraseTime();
299   base::string16 passphrase_time_str =
300       base::TimeFormatShortDate(passphrase_time);
301   return base::android::ConvertUTF16ToJavaString(env,
302       l10n_util::GetStringFUTF16(
303         IDS_SYNC_ENTER_GOOGLE_PASSPHRASE_BODY_WITH_DATE,
304         passphrase_time_str));
305 }
306
307 ScopedJavaLocalRef<jstring>
308     ProfileSyncServiceAndroid::GetSyncEnterCustomPassphraseBodyWithDateText(
309         JNIEnv* env, jobject) {
310   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
311   base::Time passphrase_time = sync_service_->GetExplicitPassphraseTime();
312   base::string16 passphrase_time_str =
313       base::TimeFormatShortDate(passphrase_time);
314   return base::android::ConvertUTF16ToJavaString(env,
315       l10n_util::GetStringFUTF16(IDS_SYNC_ENTER_PASSPHRASE_BODY_WITH_DATE,
316         passphrase_time_str));
317 }
318
319 ScopedJavaLocalRef<jstring>
320     ProfileSyncServiceAndroid::GetCurrentSignedInAccountText(
321         JNIEnv* env, jobject) {
322   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
323   const std::string& sync_username =
324       SigninManagerFactory::GetForProfile(profile_)->GetAuthenticatedUsername();
325   return base::android::ConvertUTF16ToJavaString(env,
326       l10n_util::GetStringFUTF16(
327           IDS_SYNC_ACCOUNT_SYNCING_TO_USER,
328           base::ASCIIToUTF16(sync_username)));
329 }
330
331 ScopedJavaLocalRef<jstring>
332     ProfileSyncServiceAndroid::GetSyncEnterCustomPassphraseBodyText(
333         JNIEnv* env, jobject) {
334   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
335   return ConvertUTF8ToJavaString(
336       env, l10n_util::GetStringUTF8(IDS_SYNC_ENTER_PASSPHRASE_BODY));
337 }
338
339 jboolean ProfileSyncServiceAndroid::IsSyncKeystoreMigrationDone(
340       JNIEnv* env, jobject) {
341   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
342   syncer::SyncStatus status;
343   bool is_status_valid = sync_service_->QueryDetailedSyncStatus(&status);
344   return is_status_valid && !status.keystore_migration_time.is_null();
345 }
346
347 jlong ProfileSyncServiceAndroid::GetEnabledDataTypes(JNIEnv* env,
348                                                      jobject obj) {
349   jlong model_type_selection = 0;
350   syncer::ModelTypeSet types = sync_service_->GetActiveDataTypes();
351   types.PutAll(syncer::ControlTypes());
352   if (types.Has(syncer::BOOKMARKS)) {
353     model_type_selection |= BOOKMARK;
354   }
355   if (types.Has(syncer::AUTOFILL)) {
356     model_type_selection |= AUTOFILL;
357   }
358   if (types.Has(syncer::AUTOFILL_PROFILE)) {
359     model_type_selection |= AUTOFILL_PROFILE;
360   }
361   if (types.Has(syncer::PASSWORDS)) {
362     model_type_selection |= PASSWORD;
363   }
364   if (types.Has(syncer::TYPED_URLS)) {
365     model_type_selection |= TYPED_URL;
366   }
367   if (types.Has(syncer::SESSIONS)) {
368     model_type_selection |= SESSION;
369   }
370   if (types.Has(syncer::HISTORY_DELETE_DIRECTIVES)) {
371     model_type_selection |= HISTORY_DELETE_DIRECTIVE;
372   }
373   if (types.Has(syncer::PROXY_TABS)) {
374     model_type_selection |= PROXY_TABS;
375   }
376   if (types.Has(syncer::FAVICON_IMAGES)) {
377     model_type_selection |= FAVICON_IMAGE;
378   }
379   if (types.Has(syncer::FAVICON_TRACKING)) {
380     model_type_selection |= FAVICON_TRACKING;
381   }
382   if (types.Has(syncer::DEVICE_INFO)) {
383     model_type_selection |= DEVICE_INFO;
384   }
385   if (types.Has(syncer::NIGORI)) {
386     model_type_selection |= NIGORI;
387   }
388   if (types.Has(syncer::EXPERIMENTS)) {
389     model_type_selection |= EXPERIMENTS;
390   }
391   return model_type_selection;
392 }
393
394 void ProfileSyncServiceAndroid::SetPreferredDataTypes(
395     JNIEnv* env, jobject obj,
396     jboolean sync_everything,
397     jlong model_type_selection) {
398   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
399   syncer::ModelTypeSet types;
400   // Note: only user selectable types should be included here.
401   if (model_type_selection & AUTOFILL)
402     types.Put(syncer::AUTOFILL);
403   if (model_type_selection & BOOKMARK)
404     types.Put(syncer::BOOKMARKS);
405   if (model_type_selection & PASSWORD)
406     types.Put(syncer::PASSWORDS);
407   if (model_type_selection & PROXY_TABS)
408     types.Put(syncer::PROXY_TABS);
409   if (model_type_selection & TYPED_URL)
410     types.Put(syncer::TYPED_URLS);
411   DCHECK(syncer::UserSelectableTypes().HasAll(types));
412   sync_service_->OnUserChoseDatatypes(sync_everything, types);
413 }
414
415 void ProfileSyncServiceAndroid::SetSetupInProgress(
416     JNIEnv* env, jobject obj, jboolean in_progress) {
417   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
418   sync_service_->SetSetupInProgress(in_progress);
419 }
420
421 void ProfileSyncServiceAndroid::SetSyncSetupCompleted(
422     JNIEnv* env, jobject obj) {
423   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
424   sync_service_->SetSyncSetupCompleted();
425 }
426
427 jboolean ProfileSyncServiceAndroid::HasSyncSetupCompleted(
428     JNIEnv* env, jobject obj) {
429   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
430   return sync_service_->HasSyncSetupCompleted();
431 }
432
433 jboolean ProfileSyncServiceAndroid::IsStartSuppressed(
434     JNIEnv* env, jobject obj) {
435   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
436   return sync_prefs_->IsStartSuppressed();
437 }
438
439 void ProfileSyncServiceAndroid::EnableEncryptEverything(
440     JNIEnv* env, jobject obj) {
441   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
442   sync_service_->EnableEncryptEverything();
443 }
444
445 jboolean ProfileSyncServiceAndroid::HasKeepEverythingSynced(
446     JNIEnv* env, jobject) {
447   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
448   return sync_prefs_->HasKeepEverythingSynced();
449 }
450
451 jboolean ProfileSyncServiceAndroid::HasUnrecoverableError(
452     JNIEnv* env, jobject) {
453   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
454   return sync_service_->HasUnrecoverableError();
455 }
456
457 ScopedJavaLocalRef<jstring> ProfileSyncServiceAndroid::GetAboutInfoForTest(
458     JNIEnv* env, jobject) {
459   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
460
461   scoped_ptr<base::DictionaryValue> about_info =
462       sync_ui_util::ConstructAboutInformation(sync_service_);
463   std::string about_info_json;
464   base::JSONWriter::Write(about_info.get(), &about_info_json);
465
466   return ConvertUTF8ToJavaString(env, about_info_json);
467 }
468
469 jlong ProfileSyncServiceAndroid::GetLastSyncedTimeForTest(
470     JNIEnv* env, jobject obj) {
471   // Use profile preferences here instead of SyncPrefs to avoid an extra
472   // conversion, since SyncPrefs::GetLastSyncedTime() converts the stored value
473   // to to base::Time.
474   return static_cast<jlong>(
475       profile_->GetPrefs()->GetInt64(prefs::kSyncLastSyncedTime));
476 }
477
478 void ProfileSyncServiceAndroid::NudgeSyncer(JNIEnv* env,
479                                             jobject obj,
480                                             jint objectSource,
481                                             jstring objectId,
482                                             jlong version,
483                                             jstring state) {
484   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
485   SendNudgeNotification(objectSource, ConvertJavaStringToUTF8(env, objectId),
486                         version, ConvertJavaStringToUTF8(env, state));
487 }
488
489 void ProfileSyncServiceAndroid::NudgeSyncerForAllTypes(JNIEnv* env,
490                                                        jobject obj) {
491   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
492   syncer::ObjectIdInvalidationMap object_ids_with_states;
493   content::NotificationService::current()->Notify(
494         chrome::NOTIFICATION_SYNC_REFRESH_REMOTE,
495         content::Source<Profile>(profile_),
496         content::Details<const syncer::ObjectIdInvalidationMap>(
497             &object_ids_with_states));
498 }
499
500 // static
501 ProfileSyncServiceAndroid*
502     ProfileSyncServiceAndroid::GetProfileSyncServiceAndroid() {
503   return reinterpret_cast<ProfileSyncServiceAndroid*>(
504           Java_ProfileSyncService_getProfileSyncServiceAndroid(
505       AttachCurrentThread(), base::android::GetApplicationContext()));
506 }
507
508 static jlong Init(JNIEnv* env, jobject obj) {
509   ProfileSyncServiceAndroid* profile_sync_service_android =
510       new ProfileSyncServiceAndroid(env, obj);
511   profile_sync_service_android->Init();
512   return reinterpret_cast<intptr_t>(profile_sync_service_android);
513 }
514
515 // static
516 bool ProfileSyncServiceAndroid::Register(JNIEnv* env) {
517   return RegisterNativesImpl(env);
518 }