blob: 3789b73b2d5083b5443722a255e3d0d0c8d2cf62 [file] [log] [blame]
// Copyright 2018 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 "chrome/browser/ui/android/tab_model/tab_model_observer_jni_bridge.h"
#include "chrome/browser/android/tab_android.h"
#include "chrome/browser/ui/android/tab_model/tab_model.h"
#include "chrome/browser/ui/android/tab_model/tab_model_jni_bridge.h"
#include "chrome/browser/ui/android/tab_model/tab_model_observer.h"
#include "jni/TabModelObserverJniBridge_jni.h"
using base::android::AttachCurrentThread;
using base::android::JavaParamRef;
using base::android::JavaRef;
using base::android::ScopedJavaLocalRef;
namespace {
// Gets the size of the provided enum.
int GetTabModelStaticIntField(JNIEnv* env, const char* field_name) {
jclass clazz =
env->FindClass("org/chromium/chrome/browser/tabmodel/TabModel");
jfieldID field_id = env->GetStaticFieldID(clazz, field_name, "I");
jint value = env->GetStaticIntField(clazz, field_id);
return value;
}
void EnsureEnumSizesConsistent(JNIEnv* env) {
DCHECK_EQ(static_cast<int>(TabModel::TabLaunchType::SIZE),
GetTabModelStaticIntField(env, "TabLaunchTypeSize"));
DCHECK_EQ(static_cast<int>(TabModel::TabSelectionType::SIZE),
GetTabModelStaticIntField(env, "TabSelectionTypeSize"));
}
// Converts from a Java TabModel.TabLaunchType to a C++ TabModel::TabLaunchType.
TabModel::TabLaunchType GetTabLaunchType(JNIEnv* env, int type) {
return static_cast<TabModel::TabLaunchType>(type);
}
// Converts from a Java TabModel.TabSelectionType to a C++
// TabModel::TabSelectionType.
TabModel::TabSelectionType GetTabSelectionType(JNIEnv* env, int type) {
return static_cast<TabModel::TabSelectionType>(type);
}
} // namespace
TabModelObserverJniBridge::TabModelObserverJniBridge(
JNIEnv* env,
const JavaRef<jobject>& tab_model) {
// TODO(chrisha): Clean up these enums so that the Java ones are generated
// from them.
// https://chromium.googlesource.com/chromium/src/+/lkcr/docs/android_accessing_cpp_enums_in_java.md
EnsureEnumSizesConsistent(env);
// Create the Java object. This immediately adds it as an observer on the
// corresponding TabModel.
java_object_.Reset(Java_TabModelObserverJniBridge_create(
env, reinterpret_cast<uintptr_t>(this), tab_model));
}
TabModelObserverJniBridge::~TabModelObserverJniBridge() {
JNIEnv* env = AttachCurrentThread();
Java_TabModelObserverJniBridge_detachFromTabModel(env, java_object_);
}
void TabModelObserverJniBridge::DidSelectTab(JNIEnv* env,
const JavaParamRef<jobject>& jobj,
const JavaParamRef<jobject>& jtab,
int jtype,
int last_id) {
TabAndroid* tab = TabAndroid::GetNativeTab(env, jtab);
CHECK(tab);
TabModel::TabSelectionType type = GetTabSelectionType(env, jtype);
for (auto& observer : observers_)
observer.DidSelectTab(tab, type);
}
void TabModelObserverJniBridge::WillCloseTab(JNIEnv* env,
const JavaParamRef<jobject>& jobj,
const JavaParamRef<jobject>& jtab,
bool animate) {
TabAndroid* tab = TabAndroid::GetNativeTab(env, jtab);
CHECK(tab);
for (auto& observer : observers_)
observer.WillCloseTab(tab, animate);
}
void TabModelObserverJniBridge::DidCloseTab(JNIEnv* env,
const JavaParamRef<jobject>& jobj,
int tab_id,
bool incognito) {
for (auto& observer : observers_)
observer.DidCloseTab(tab_id, incognito);
}
void TabModelObserverJniBridge::WillAddTab(JNIEnv* env,
const JavaParamRef<jobject>& jobj,
const JavaParamRef<jobject>& jtab,
int jtype) {
TabAndroid* tab = TabAndroid::GetNativeTab(env, jtab);
CHECK(tab);
TabModel::TabLaunchType type = GetTabLaunchType(env, jtype);
for (auto& observer : observers_)
observer.WillAddTab(tab, type);
}
void TabModelObserverJniBridge::DidAddTab(JNIEnv* env,
const JavaParamRef<jobject>& jobj,
const JavaParamRef<jobject>& jtab,
int jtype) {
TabAndroid* tab = TabAndroid::GetNativeTab(env, jtab);
CHECK(tab);
TabModel::TabLaunchType type = GetTabLaunchType(env, jtype);
for (auto& observer : observers_)
observer.DidAddTab(tab, type);
}
void TabModelObserverJniBridge::DidMoveTab(JNIEnv* env,
const JavaParamRef<jobject>& jobj,
const JavaParamRef<jobject>& jtab,
int new_index,
int cur_index) {
TabAndroid* tab = TabAndroid::GetNativeTab(env, jtab);
CHECK(tab);
for (auto& observer : observers_)
observer.DidMoveTab(tab, new_index, cur_index);
}
void TabModelObserverJniBridge::TabPendingClosure(
JNIEnv* env,
const JavaParamRef<jobject>& jobj,
const JavaParamRef<jobject>& jtab) {
TabAndroid* tab = TabAndroid::GetNativeTab(env, jtab);
CHECK(tab);
for (auto& observer : observers_)
observer.TabPendingClosure(tab);
}
void TabModelObserverJniBridge::TabClosureUndone(
JNIEnv* env,
const JavaParamRef<jobject>& jobj,
const JavaParamRef<jobject>& jtab) {
TabAndroid* tab = TabAndroid::GetNativeTab(env, jtab);
CHECK(tab);
for (auto& observer : observers_)
observer.TabClosureUndone(tab);
}
void TabModelObserverJniBridge::TabClosureCommitted(
JNIEnv* env,
const JavaParamRef<jobject>& jobj,
const JavaParamRef<jobject>& jtab) {
TabAndroid* tab = TabAndroid::GetNativeTab(env, jtab);
CHECK(tab);
for (auto& observer : observers_)
observer.TabClosureCommitted(tab);
}
void TabModelObserverJniBridge::AllTabsPendingClosure(
JNIEnv* env,
const JavaParamRef<jobject>& jobj,
const JavaParamRef<jobjectArray>& jtabs) {
std::vector<TabAndroid*> tabs;
// |jtabs| is actually a Tab[]. Iterate over the array and convert it to
// a vector of TabAndroid*.
jint size = env->GetArrayLength(jtabs.obj());
tabs.reserve(size);
for (jint i = 0; i < size; ++i) {
jobject jtab = env->GetObjectArrayElement(jtabs.obj(), 0);
TabAndroid* tab =
TabAndroid::GetNativeTab(env, JavaParamRef<jobject>(env, jtab));
CHECK(tab);
tabs.push_back(tab);
}
for (auto& observer : observers_)
observer.AllTabsPendingClosure(tabs);
}
void TabModelObserverJniBridge::AllTabsClosureCommitted(
JNIEnv* env,
const JavaParamRef<jobject>& jobj) {
for (auto& observer : observers_)
observer.AllTabsClosureCommitted();
}
void TabModelObserverJniBridge::TabRemoved(JNIEnv* env,
const JavaParamRef<jobject>& jobj,
const JavaParamRef<jobject>& jtab) {
TabAndroid* tab = TabAndroid::GetNativeTab(env, jtab);
CHECK(tab);
for (auto& observer : observers_)
observer.TabRemoved(tab);
}
void TabModelObserverJniBridge::AddObserver(TabModelObserver* observer) {
observers_.AddObserver(observer);
}
void TabModelObserverJniBridge::RemoveObserver(TabModelObserver* observer) {
observers_.RemoveObserver(observer);
}