blob: 90fd071362b913a035be0f204506ee7aab2f6f28 [file] [log] [blame]
// Copyright 2017 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/feature_engagement/internal/android/tracker_impl_android.h"
#include <memory>
#include <utility>
#include <vector>
#include "base/android/callback_android.h"
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/bind.h"
#include "base/feature_list.h"
#include "base/memory/ptr_util.h"
#include "components/feature_engagement/public/feature_list.h"
#include "components/feature_engagement/public/tracker.h"
#include "jni/TrackerImpl_jni.h"
namespace feature_engagement {
namespace {
const char kTrackerImplAndroidKey[] = "tracker_impl_android";
// Create mapping from feature name to base::Feature.
TrackerImplAndroid::FeatureMap CreateMapFromNameToFeature(
FeatureVector features) {
TrackerImplAndroid::FeatureMap feature_map;
for (auto it = features.begin(); it != features.end(); ++it) {
feature_map[(*it)->name] = *it;
}
return feature_map;
}
TrackerImplAndroid* FromTrackerImpl(Tracker* feature_engagement) {
TrackerImpl* impl = static_cast<TrackerImpl*>(feature_engagement);
TrackerImplAndroid* impl_android = static_cast<TrackerImplAndroid*>(
impl->GetUserData(kTrackerImplAndroidKey));
if (!impl_android) {
impl_android = new TrackerImplAndroid(impl, GetAllFeatures());
impl->SetUserData(kTrackerImplAndroidKey, base::WrapUnique(impl_android));
}
return impl_android;
}
} // namespace
// static
TrackerImplAndroid* TrackerImplAndroid::FromJavaObject(
JNIEnv* env,
const base::android::JavaRef<jobject>& jobj) {
return reinterpret_cast<TrackerImplAndroid*>(
Java_TrackerImpl_getNativePtr(env, jobj));
}
// This function is declared in //components/feature_engagement/public/tracker.h
// and should be linked in to any binary using Tracker::GetJavaObject.
// static
base::android::ScopedJavaLocalRef<jobject> Tracker::GetJavaObject(
Tracker* feature_engagement) {
return FromTrackerImpl(feature_engagement)->GetJavaObject();
}
TrackerImplAndroid::TrackerImplAndroid(TrackerImpl* tracker_impl,
FeatureVector features)
: features_(CreateMapFromNameToFeature(features)),
tracker_impl_(tracker_impl) {
JNIEnv* env = base::android::AttachCurrentThread();
java_obj_.Reset(
env,
Java_TrackerImpl_create(env, reinterpret_cast<intptr_t>(this)).obj());
}
TrackerImplAndroid::~TrackerImplAndroid() {
Java_TrackerImpl_clearNativePtr(base::android::AttachCurrentThread(),
java_obj_);
}
base::android::ScopedJavaLocalRef<jobject> TrackerImplAndroid::GetJavaObject() {
return base::android::ScopedJavaLocalRef<jobject>(java_obj_);
}
void TrackerImplAndroid::NotifyEvent(
JNIEnv* env,
const base::android::JavaRef<jobject>& jobj,
const base::android::JavaParamRef<jstring>& jevent) {
std::string event = ConvertJavaStringToUTF8(env, jevent);
tracker_impl_->NotifyEvent(event);
}
bool TrackerImplAndroid::ShouldTriggerHelpUI(
JNIEnv* env,
const base::android::JavaRef<jobject>& jobj,
const base::android::JavaParamRef<jstring>& jfeature) {
std::string feature = ConvertJavaStringToUTF8(env, jfeature);
DCHECK(features_.find(feature) != features_.end());
return tracker_impl_->ShouldTriggerHelpUI(*features_[feature]);
}
bool TrackerImplAndroid::WouldTriggerHelpUI(
JNIEnv* env,
const base::android::JavaRef<jobject>& jobj,
const base::android::JavaParamRef<jstring>& jfeature) {
std::string feature = ConvertJavaStringToUTF8(env, jfeature);
DCHECK(features_.find(feature) != features_.end());
return tracker_impl_->WouldTriggerHelpUI(*features_[feature]);
}
jint TrackerImplAndroid::GetTriggerState(
JNIEnv* env,
const base::android::JavaRef<jobject>& jobj,
const base::android::JavaParamRef<jstring>& jfeature) {
std::string feature = ConvertJavaStringToUTF8(env, jfeature);
DCHECK(features_.find(feature) != features_.end());
return static_cast<int>(tracker_impl_->GetTriggerState(*features_[feature]));
}
void TrackerImplAndroid::Dismissed(
JNIEnv* env,
const base::android::JavaRef<jobject>& jobj,
const base::android::JavaParamRef<jstring>& jfeature) {
std::string feature = ConvertJavaStringToUTF8(env, jfeature);
DCHECK(features_.find(feature) != features_.end());
tracker_impl_->Dismissed(*features_[feature]);
}
base::android::ScopedJavaLocalRef<jobject>
TrackerImplAndroid::AcquireDisplayLock(
JNIEnv* env,
const base::android::JavaRef<jobject>& jobj) {
std::unique_ptr<DisplayLockHandle> lock_handle =
tracker_impl_->AcquireDisplayLock();
if (!lock_handle)
return nullptr;
auto lock_handle_android =
std::make_unique<DisplayLockHandleAndroid>(std::move(lock_handle));
// Intentionally release ownership to Java.
// Callers are required to invoke DisplayLockHandleAndroid#release().
return lock_handle_android.release()->GetJavaObject();
}
bool TrackerImplAndroid::IsInitialized(
JNIEnv* env,
const base::android::JavaRef<jobject>& jobj) {
return tracker_impl_->IsInitialized();
}
void TrackerImplAndroid::AddOnInitializedCallback(
JNIEnv* env,
const base::android::JavaRef<jobject>& jobj,
const base::android::JavaParamRef<jobject>& j_callback_obj) {
// Disambiguate RunCallbackAndroid to get the reference to the bool version.
void (*runBoolCallback)(const base::android::JavaRef<jobject>&, bool) =
&base::android::RunCallbackAndroid;
tracker_impl_->AddOnInitializedCallback(base::BindOnce(
runBoolCallback,
base::android::ScopedJavaGlobalRef<jobject>(j_callback_obj)));
}
DisplayLockHandleAndroid::DisplayLockHandleAndroid(
std::unique_ptr<DisplayLockHandle> display_lock_handle)
: display_lock_handle_(std::move(display_lock_handle)) {
java_obj_.Reset(
base::android::AttachCurrentThread(),
Java_DisplayLockHandleAndroid_create(base::android::AttachCurrentThread(),
reinterpret_cast<intptr_t>(this))
.obj());
}
DisplayLockHandleAndroid::~DisplayLockHandleAndroid() {
Java_DisplayLockHandleAndroid_clearNativePtr(
base::android::AttachCurrentThread(), java_obj_);
}
base::android::ScopedJavaLocalRef<jobject>
DisplayLockHandleAndroid::GetJavaObject() {
return base::android::ScopedJavaLocalRef<jobject>(java_obj_);
}
void DisplayLockHandleAndroid::Release(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& jobj) {
delete this;
}
} // namespace feature_engagement