blob: c909c421ec0fc8c597bf8eceb2a247600839726e [file] [log] [blame]
// 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/impl/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/public/object_id_invalidation_map.h"
#include "google/cacheinvalidation/types.pb.h"
#include "jni/InvalidationService_jni.h"
using base::android::ConvertJavaStringToUTF8;
using base::android::ConvertUTF8ToJavaString;
using base::android::JavaRef;
using base::android::JavaParamRef;
namespace invalidation {
InvalidationServiceAndroid::InvalidationServiceAndroid(
const JavaRef<jobject>& context)
: invalidator_state_(syncer::INVALIDATIONS_ENABLED), logger_() {
DCHECK(CalledOnValidThread());
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jobject> local_java_ref =
Java_InvalidationService_create(env,
context,
reinterpret_cast<intptr_t>(this));
java_ref_.Reset(env, local_java_ref.obj());
logger_.OnStateChange(invalidator_state_);
}
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<int> sources;
std::vector<std::string> 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_, base::android::ToJavaIntArray(env, sources),
base::android::ToJavaArrayOfStrings(env, names));
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_);
// Convert it into a more convenient format for C++.
std::vector<uint8_t> 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<void(const base::DictionaryValue&)> 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,
const JavaParamRef<jobject>& obj,
jint object_source,
const JavaParamRef<jstring>& java_object_id,
jlong version,
const JavaParamRef<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;
std::string payload;
if (!java_payload.is_null())
ConvertJavaStringToUTF8(env, java_payload, &payload);
object_invalidation_map.Insert(
syncer::Invalidation::Init(object_id, version, payload));
}
}
invalidator_registrar_.DispatchInvalidationsToHandlers(
object_invalidation_map);
logger_.OnInvalidation(object_invalidation_map);
}
// static
bool InvalidationServiceAndroid::RegisterJni(JNIEnv* env) {
return RegisterNativesImpl(env);
}
} // namespace invalidation