blob: 81d83b85dd04e9ef2d31a016686756ba7a13bb5d [file] [log] [blame]
// 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/sync/profile_sync_service_android.h"
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/bind.h"
#include "base/i18n/time_formatting.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/sync/sync_ui_util.h"
#include "chrome/common/channel_info.h"
#include "chrome/grit/generated_resources.h"
#include "components/browser_sync/browser/profile_sync_service.h"
#include "components/prefs/pref_service.h"
#include "components/signin/core/browser/signin_manager.h"
#include "components/sync_driver/about_sync_util.h"
#include "components/sync_driver/pref_names.h"
#include "components/sync_driver/sync_prefs.h"
#include "content/public/browser/browser_thread.h"
#include "google/cacheinvalidation/types.pb.h"
#include "google_apis/gaia/gaia_constants.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "grit/components_strings.h"
#include "jni/ProfileSyncService_jni.h"
#include "sync/internal_api/public/network_resources.h"
#include "sync/internal_api/public/read_transaction.h"
#include "ui/base/l10n/l10n_util.h"
using base::android::AttachCurrentThread;
using base::android::CheckException;
using base::android::ConvertJavaStringToUTF8;
using base::android::ConvertUTF8ToJavaString;
using base::android::ScopedJavaLocalRef;
using content::BrowserThread;
namespace {
// Native callback for the JNI GetAllNodes method. When
// ProfileSyncService::GetAllNodes completes, this method is called and the
// results are sent to the Java callback.
void NativeGetAllNodesCallback(
const base::android::ScopedJavaGlobalRef<jobject>& callback,
std::unique_ptr<base::ListValue> result) {
JNIEnv* env = base::android::AttachCurrentThread();
std::string json_string;
if (!result.get() || !base::JSONWriter::Write(*result, &json_string)) {
DVLOG(1) << "Writing as JSON failed. Passing empty string to Java code.";
json_string = std::string();
}
ScopedJavaLocalRef<jstring> java_json_string =
ConvertUTF8ToJavaString(env, json_string);
Java_ProfileSyncService_onGetAllNodesResult(env,
callback.obj(),
java_json_string.obj());
}
ScopedJavaLocalRef<jintArray> ModelTypeSetToJavaIntArray(
JNIEnv* env,
syncer::ModelTypeSet types) {
std::vector<int> type_vector;
for (syncer::ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) {
type_vector.push_back(it.Get());
}
return base::android::ToJavaIntArray(env, type_vector);
}
} // namespace
ProfileSyncServiceAndroid::ProfileSyncServiceAndroid(JNIEnv* env, jobject obj)
: profile_(NULL),
sync_service_(NULL),
weak_java_profile_sync_service_(env, obj) {
if (g_browser_process == NULL ||
g_browser_process->profile_manager() == NULL) {
NOTREACHED() << "Browser process or profile manager not initialized";
return;
}
profile_ = ProfileManager::GetActiveUserProfile();
if (profile_ == NULL) {
NOTREACHED() << "Sync Init: Profile not found.";
return;
}
sync_prefs_.reset(new sync_driver::SyncPrefs(profile_->GetPrefs()));
sync_service_ =
ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile_);
}
bool ProfileSyncServiceAndroid::Init() {
if (sync_service_) {
sync_service_->AddObserver(this);
sync_service_->SetPlatformSyncAllowedProvider(
base::Bind(&ProfileSyncServiceAndroid::IsSyncAllowedByAndroid,
base::Unretained(this)));
return true;
} else {
return false;
}
}
ProfileSyncServiceAndroid::~ProfileSyncServiceAndroid() {
if (sync_service_) {
sync_service_->RemoveObserver(this);
sync_service_->SetPlatformSyncAllowedProvider(
ProfileSyncService::PlatformSyncAllowedProvider());
}
}
void ProfileSyncServiceAndroid::OnStateChanged() {
// Notify the java world that our sync state has changed.
JNIEnv* env = AttachCurrentThread();
Java_ProfileSyncService_syncStateChanged(
env, weak_java_profile_sync_service_.get(env).obj());
}
bool ProfileSyncServiceAndroid::IsSyncAllowedByAndroid() const {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
JNIEnv* env = AttachCurrentThread();
return Java_ProfileSyncService_isMasterSyncEnabled(
env, weak_java_profile_sync_service_.get(env).obj());
}
// Pure ProfileSyncService calls.
jboolean ProfileSyncServiceAndroid::IsSyncRequested(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return sync_service_->IsSyncRequested();
}
void ProfileSyncServiceAndroid::RequestStart(JNIEnv* env,
const JavaParamRef<jobject>&) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
sync_service_->RequestStart();
}
void ProfileSyncServiceAndroid::RequestStop(JNIEnv* env,
const JavaParamRef<jobject>&) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
sync_service_->RequestStop(ProfileSyncService::KEEP_DATA);
}
void ProfileSyncServiceAndroid::SignOutSync(JNIEnv* env,
const JavaParamRef<jobject>&) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(profile_);
sync_service_->RequestStop(ProfileSyncService::CLEAR_DATA);
}
jboolean ProfileSyncServiceAndroid::IsSyncActive(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return sync_service_->IsSyncActive();
}
jboolean ProfileSyncServiceAndroid::IsBackendInitialized(
JNIEnv* env,
const JavaParamRef<jobject>&) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return sync_service_->IsBackendInitialized();
}
void ProfileSyncServiceAndroid::SetSetupInProgress(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
jboolean in_progress) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
sync_service_->SetSetupInProgress(in_progress);
}
jboolean ProfileSyncServiceAndroid::IsFirstSetupComplete(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return sync_service_->IsFirstSetupComplete();
}
void ProfileSyncServiceAndroid::SetFirstSetupComplete(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
sync_service_->SetFirstSetupComplete();
}
ScopedJavaLocalRef<jintArray> ProfileSyncServiceAndroid::GetActiveDataTypes(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
syncer::ModelTypeSet types = sync_service_->GetActiveDataTypes();
return ModelTypeSetToJavaIntArray(env, types);
}
ScopedJavaLocalRef<jintArray> ProfileSyncServiceAndroid::GetPreferredDataTypes(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
syncer::ModelTypeSet types = sync_service_->GetPreferredDataTypes();
return ModelTypeSetToJavaIntArray(env, types);
}
void ProfileSyncServiceAndroid::SetPreferredDataTypes(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
jboolean sync_everything,
const JavaParamRef<jintArray>& model_type_array) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
std::vector<int> types_vector;
base::android::JavaIntArrayToIntVector(env, model_type_array, &types_vector);
syncer::ModelTypeSet types;
for (size_t i = 0; i < types_vector.size(); i++) {
types.Put(static_cast<syncer::ModelType>(types_vector[i]));
}
sync_service_->OnUserChoseDatatypes(sync_everything, types);
}
jboolean ProfileSyncServiceAndroid::IsCryptographerReady(
JNIEnv* env,
const JavaParamRef<jobject>&) {
syncer::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare());
return sync_service_->IsCryptographerReady(&trans);
}
jboolean ProfileSyncServiceAndroid::IsEncryptEverythingAllowed(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return sync_service_->IsEncryptEverythingAllowed();
}
jboolean ProfileSyncServiceAndroid::IsEncryptEverythingEnabled(
JNIEnv* env,
const JavaParamRef<jobject>&) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return sync_service_->IsEncryptEverythingEnabled();
}
void ProfileSyncServiceAndroid::EnableEncryptEverything(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
sync_service_->EnableEncryptEverything();
}
jboolean ProfileSyncServiceAndroid::IsPassphraseRequiredForDecryption(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return sync_service_->IsPassphraseRequiredForDecryption();
}
jboolean ProfileSyncServiceAndroid::IsUsingSecondaryPassphrase(
JNIEnv* env,
const JavaParamRef<jobject>&) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return sync_service_->IsUsingSecondaryPassphrase();
}
ScopedJavaLocalRef<jbyteArray>
ProfileSyncServiceAndroid::GetCustomPassphraseKey(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
std::string key = sync_service_->GetCustomPassphraseKey();
return base::android::ToJavaByteArray(
env, reinterpret_cast<const uint8_t*>(key.data()), key.size());
}
jint ProfileSyncServiceAndroid::GetPassphraseType(
JNIEnv* env,
const JavaParamRef<jobject>&) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return sync_service_->GetPassphraseType();
}
void ProfileSyncServiceAndroid::SetEncryptionPassphrase(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jstring>& passphrase) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
std::string key = ConvertJavaStringToUTF8(env, passphrase);
sync_service_->SetEncryptionPassphrase(key, ProfileSyncService::EXPLICIT);
}
jboolean ProfileSyncServiceAndroid::SetDecryptionPassphrase(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jstring>& passphrase) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
std::string key = ConvertJavaStringToUTF8(env, passphrase);
return sync_service_->SetDecryptionPassphrase(key);
}
jboolean ProfileSyncServiceAndroid::HasExplicitPassphraseTime(
JNIEnv* env,
const JavaParamRef<jobject>&) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::Time passphrase_time = sync_service_->GetExplicitPassphraseTime();
return !passphrase_time.is_null();
}
jlong ProfileSyncServiceAndroid::GetExplicitPassphraseTime(
JNIEnv* env,
const JavaParamRef<jobject>&) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::Time passphrase_time = sync_service_->GetExplicitPassphraseTime();
return passphrase_time.ToJavaTime();
}
void ProfileSyncServiceAndroid::FlushDirectory(JNIEnv* env,
const JavaParamRef<jobject>&) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
sync_service_->FlushDirectory();
}
ScopedJavaLocalRef<jstring> ProfileSyncServiceAndroid::QuerySyncStatusSummary(
JNIEnv* env,
const JavaParamRef<jobject>&) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(profile_);
std::string status(sync_service_->QuerySyncStatusSummaryString());
return ConvertUTF8ToJavaString(env, status);
}
void ProfileSyncServiceAndroid::GetAllNodes(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jobject>& callback) {
base::android::ScopedJavaGlobalRef<jobject> java_callback;
java_callback.Reset(env, callback);
base::Callback<void(std::unique_ptr<base::ListValue>)> native_callback =
base::Bind(&NativeGetAllNodesCallback, java_callback);
sync_service_->GetAllNodes(native_callback);
}
jint ProfileSyncServiceAndroid::GetAuthError(JNIEnv* env,
const JavaParamRef<jobject>&) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return sync_service_->GetAuthError().state();
}
jboolean ProfileSyncServiceAndroid::HasUnrecoverableError(
JNIEnv* env,
const JavaParamRef<jobject>&) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return sync_service_->HasUnrecoverableError();
}
// Pure SyncPrefs calls.
jboolean ProfileSyncServiceAndroid::IsPassphrasePrompted(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
return sync_prefs_->IsPassphrasePrompted();
}
void ProfileSyncServiceAndroid::SetPassphrasePrompted(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
jboolean prompted) {
sync_prefs_->SetPassphrasePrompted(prompted);
}
void ProfileSyncServiceAndroid::SetSyncSessionsId(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
const JavaParamRef<jstring>& tag) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(profile_);
std::string machine_tag = ConvertJavaStringToUTF8(env, tag);
sync_prefs_->SetSyncSessionsGUID(machine_tag);
}
jboolean ProfileSyncServiceAndroid::HasKeepEverythingSynced(
JNIEnv* env,
const JavaParamRef<jobject>&) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return sync_prefs_->HasKeepEverythingSynced();
}
// UI string getters.
ScopedJavaLocalRef<jstring>
ProfileSyncServiceAndroid::GetSyncEnterGooglePassphraseBodyWithDateText(
JNIEnv* env,
const JavaParamRef<jobject>&) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::Time passphrase_time = sync_service_->GetExplicitPassphraseTime();
base::string16 passphrase_time_str =
base::TimeFormatShortDate(passphrase_time);
return base::android::ConvertUTF16ToJavaString(env,
l10n_util::GetStringFUTF16(
IDS_SYNC_ENTER_GOOGLE_PASSPHRASE_BODY_WITH_DATE,
passphrase_time_str));
}
ScopedJavaLocalRef<jstring>
ProfileSyncServiceAndroid::GetSyncEnterCustomPassphraseBodyWithDateText(
JNIEnv* env,
const JavaParamRef<jobject>&) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::Time passphrase_time = sync_service_->GetExplicitPassphraseTime();
base::string16 passphrase_time_str =
base::TimeFormatShortDate(passphrase_time);
return base::android::ConvertUTF16ToJavaString(env,
l10n_util::GetStringFUTF16(IDS_SYNC_ENTER_PASSPHRASE_BODY_WITH_DATE,
passphrase_time_str));
}
ScopedJavaLocalRef<jstring>
ProfileSyncServiceAndroid::GetCurrentSignedInAccountText(
JNIEnv* env,
const JavaParamRef<jobject>&) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
const std::string& sync_username =
SigninManagerFactory::GetForProfile(profile_)
->GetAuthenticatedAccountInfo()
.email;
return base::android::ConvertUTF16ToJavaString(env,
l10n_util::GetStringFUTF16(
IDS_SYNC_ACCOUNT_SYNCING_TO_USER,
base::ASCIIToUTF16(sync_username)));
}
ScopedJavaLocalRef<jstring>
ProfileSyncServiceAndroid::GetSyncEnterCustomPassphraseBodyText(
JNIEnv* env,
const JavaParamRef<jobject>&) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return ConvertUTF8ToJavaString(
env, l10n_util::GetStringUTF8(IDS_SYNC_ENTER_PASSPHRASE_BODY));
}
// Functionality only available for testing purposes.
ScopedJavaLocalRef<jstring> ProfileSyncServiceAndroid::GetAboutInfoForTest(
JNIEnv* env,
const JavaParamRef<jobject>&) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
std::unique_ptr<base::DictionaryValue> about_info =
sync_driver::sync_ui_util::ConstructAboutInformation(
sync_service_, sync_service_->signin(), chrome::GetChannel());
std::string about_info_json;
base::JSONWriter::Write(*about_info, &about_info_json);
return ConvertUTF8ToJavaString(env, about_info_json);
}
jlong ProfileSyncServiceAndroid::GetLastSyncedTimeForTest(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
// Use profile preferences here instead of SyncPrefs to avoid an extra
// conversion, since SyncPrefs::GetLastSyncedTime() converts the stored value
// to to base::Time.
return static_cast<jlong>(
profile_->GetPrefs()->GetInt64(sync_driver::prefs::kSyncLastSyncedTime));
}
void ProfileSyncServiceAndroid::OverrideNetworkResourcesForTest(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
jlong network_resources) {
syncer::NetworkResources* resources =
reinterpret_cast<syncer::NetworkResources*>(network_resources);
sync_service_->OverrideNetworkResourcesForTest(
base::WrapUnique<syncer::NetworkResources>(resources));
}
// static
ProfileSyncServiceAndroid*
ProfileSyncServiceAndroid::GetProfileSyncServiceAndroid() {
return reinterpret_cast<ProfileSyncServiceAndroid*>(
Java_ProfileSyncService_getProfileSyncServiceAndroid(
AttachCurrentThread()));
}
// static
bool ProfileSyncServiceAndroid::Register(JNIEnv* env) {
return RegisterNativesImpl(env);
}
static jlong Init(JNIEnv* env, const JavaParamRef<jobject>& obj) {
ProfileSyncServiceAndroid* profile_sync_service_android =
new ProfileSyncServiceAndroid(env, obj);
if (profile_sync_service_android->Init()) {
return reinterpret_cast<intptr_t>(profile_sync_service_android);
} else {
delete profile_sync_service_android;
return 0;
}
}