// Copyright 2014 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 "components/invalidation/invalidation_service_android.h" #include "base/android/jni_android.h" #include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/callback.h" #include "components/invalidation/object_id_invalidation_map.h" #include "google/cacheinvalidation/types.pb.h" #include "jni/InvalidationService_jni.h" using base::android::ConvertJavaStringToUTF8; using base::android::ConvertUTF8ToJavaString; namespace invalidation { InvalidationServiceAndroid::InvalidationServiceAndroid(jobject context) : invalidator_state_(syncer::INVALIDATIONS_ENABLED), logger_() { DCHECK(CalledOnValidThread()); JNIEnv* env = base::android::AttachCurrentThread(); base::android::ScopedJavaLocalRef local_java_ref = Java_InvalidationService_create(env, context, reinterpret_cast(this)); java_ref_.Reset(env, local_java_ref.obj()); } InvalidationServiceAndroid::~InvalidationServiceAndroid() { } void InvalidationServiceAndroid::RegisterInvalidationHandler( syncer::InvalidationHandler* handler) { DCHECK(CalledOnValidThread()); invalidator_registrar_.RegisterHandler(handler); logger_.OnRegistration(handler->GetOwnerName()); } void InvalidationServiceAndroid::UpdateRegisteredInvalidationIds( syncer::InvalidationHandler* handler, const syncer::ObjectIdSet& ids) { DCHECK(CalledOnValidThread()); JNIEnv* env = base::android::AttachCurrentThread(); DCHECK(env); invalidator_registrar_.UpdateRegisteredIds(handler, ids); const syncer::ObjectIdSet& registered_ids = invalidator_registrar_.GetAllRegisteredIds(); // To call the corresponding method on the Java invalidation service, split // the object ids into object source and object name arrays. std::vector sources; std::vector names; syncer::ObjectIdSet::const_iterator id; for (id = registered_ids.begin(); id != registered_ids.end(); ++id) { sources.push_back(id->source()); names.push_back(id->name()); } Java_InvalidationService_setRegisteredObjectIds( env, java_ref_.obj(), base::android::ToJavaIntArray(env, sources).obj(), base::android::ToJavaArrayOfStrings(env, names).obj()); logger_.OnUpdateIds(invalidator_registrar_.GetSanitizedHandlersIdsMap()); } void InvalidationServiceAndroid::UnregisterInvalidationHandler( syncer::InvalidationHandler* handler) { DCHECK(CalledOnValidThread()); invalidator_registrar_.UnregisterHandler(handler); logger_.OnUnregistration(handler->GetOwnerName()); } syncer::InvalidatorState InvalidationServiceAndroid::GetInvalidatorState() const { DCHECK(CalledOnValidThread()); return invalidator_state_; } std::string InvalidationServiceAndroid::GetInvalidatorClientId() const { DCHECK(CalledOnValidThread()); JNIEnv* env = base::android::AttachCurrentThread(); DCHECK(env); // Ask the Java code to for the invalidator ID it's currently using. base::android::ScopedJavaLocalRef<_jbyteArray*> id_bytes_java = Java_InvalidationService_getInvalidatorClientId(env, java_ref_.obj()); // Convert it into a more convenient format for C++. std::vector id_bytes; base::android::JavaByteArrayToByteVector(env, id_bytes_java.obj(), &id_bytes); std::string id(id_bytes.begin(), id_bytes.end()); return id; } InvalidationLogger* InvalidationServiceAndroid::GetInvalidationLogger() { return &logger_; } void InvalidationServiceAndroid::RequestDetailedStatus( base::Callback return_callback) const { } IdentityProvider* InvalidationServiceAndroid::GetIdentityProvider() { return NULL; } void InvalidationServiceAndroid::TriggerStateChangeForTest( syncer::InvalidatorState state) { DCHECK(CalledOnValidThread()); invalidator_state_ = state; invalidator_registrar_.UpdateInvalidatorState(invalidator_state_); } void InvalidationServiceAndroid::RequestSync(JNIEnv* env, jobject obj, jint object_source, jstring java_object_id, jlong version, jstring java_state) { invalidation::ObjectId object_id(object_source, ConvertJavaStringToUTF8(env, java_object_id)); syncer::ObjectIdInvalidationMap object_ids_with_states; if (version == ipc::invalidation::Constants::UNKNOWN) { object_ids_with_states.Insert( syncer::Invalidation::InitUnknownVersion(object_id)); } else { ObjectIdVersionMap::iterator it = max_invalidation_versions_.find(object_id); if ((it != max_invalidation_versions_.end()) && (version <= it->second)) { DVLOG(1) << "Dropping redundant invalidation with version " << version; return; } max_invalidation_versions_[object_id] = version; object_ids_with_states.Insert( syncer::Invalidation::Init(object_id, version, ConvertJavaStringToUTF8(env, java_state))); } DispatchInvalidations(object_ids_with_states); } void InvalidationServiceAndroid::RequestSyncForAllTypes(JNIEnv* env, jobject obj) { syncer::ObjectIdInvalidationMap object_ids_with_states; DispatchInvalidations(object_ids_with_states); } void InvalidationServiceAndroid::DispatchInvalidations( syncer::ObjectIdInvalidationMap& object_invalidation_map) { // An empty map implies that we should invalidate all. const syncer::ObjectIdInvalidationMap& effective_invalidation_map = object_invalidation_map.Empty() ? syncer::ObjectIdInvalidationMap::InvalidateAll( invalidator_registrar_.GetAllRegisteredIds()) : object_invalidation_map; invalidator_registrar_.DispatchInvalidationsToHandlers( effective_invalidation_map); logger_.OnInvalidation(effective_invalidation_map); } // static bool InvalidationServiceAndroid::RegisterJni(JNIEnv* env) { return RegisterNativesImpl(env); } } // namespace invalidation