// 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()); } bool InvalidationServiceAndroid::UpdateRegisteredInvalidationIds( syncer::InvalidationHandler* handler, const syncer::ObjectIdSet& ids) { DCHECK(CalledOnValidThread()); JNIEnv* env = base::android::AttachCurrentThread(); DCHECK(env); if (!invalidator_registrar_.UpdateRegisteredIds(handler, ids)) return false; 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()); return true; } 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::Invalidate(JNIEnv* env, jobject obj, jint object_source, jstring java_object_id, jlong version, jstring java_payload) { syncer::ObjectIdInvalidationMap object_invalidation_map; if (!java_object_id) { syncer::ObjectIdSet sync_ids; if (object_source == 0) { sync_ids = invalidator_registrar_.GetAllRegisteredIds(); } else { for (const auto& id : invalidator_registrar_.GetAllRegisteredIds()) { if (id.source() == object_source) sync_ids.insert(id); } } object_invalidation_map = syncer::ObjectIdInvalidationMap::InvalidateAll(sync_ids); } else { invalidation::ObjectId object_id( object_source, ConvertJavaStringToUTF8(env, java_object_id)); if (version == ipc::invalidation::Constants::UNKNOWN) { object_invalidation_map.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_invalidation_map.Insert(syncer::Invalidation::Init( object_id, version, ConvertJavaStringToUTF8(env, java_payload))); } } invalidator_registrar_.DispatchInvalidationsToHandlers( object_invalidation_map); logger_.OnInvalidation(object_invalidation_map); } // static bool InvalidationServiceAndroid::RegisterJni(JNIEnv* env) { return RegisterNativesImpl(env); } } // namespace invalidation