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