chromium/chrome/browser/ui/android/tab_model/tab_model_observer_jni_bridge.cc

// Copyright 2018 The Chromium Authors
// 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 "base/memory/raw_ptr.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"

// Must come after all headers that specialize FromJniType() / ToJniType().
#include "chrome/android/chrome_jni_headers/TabModelObserverJniBridge_jni.h"

using base::android::AttachCurrentThread;
using base::android::JavaObjectArrayReader;
using base::android::JavaParamRef;
using base::android::JavaRef;
using base::android::ScopedJavaLocalRef;

namespace {

// 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) {
  // 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) {
  TabAndroid* tab = TabAndroid::GetNativeTab(env, jtab);
  CHECK(tab);
  for (auto& observer : observers_) {
    observer.WillCloseTab(tab);
  }
}

void TabModelObserverJniBridge::OnFinishingTabClosure(
    JNIEnv* env,
    const JavaParamRef<jobject>& jobj,
    int tab_id,
    bool incognito) {
  for (auto& observer : observers_) {
    observer.OnFinishingTabClosure(tab_id, incognito);
  }
}

void TabModelObserverJniBridge::OnFinishingMultipleTabClosure(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& jobj,
    const base::android::JavaParamRef<jobjectArray>& jtabs,
    bool canRestore) {
  std::vector<raw_ptr<TabAndroid, VectorExperimental>> tabs =
      TabAndroid::GetAllNativeTabs(env,
                                   ScopedJavaLocalRef<jobjectArray>(jtabs));
  for (auto& observer : observers_) {
    observer.OnFinishingMultipleTabClosure(tabs, canRestore);
  }
}

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<raw_ptr<TabAndroid, VectorExperimental>> tabs =
      TabAndroid::GetAllNativeTabs(env,
                                   ScopedJavaLocalRef<jobjectArray>(jtabs));
  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);
}