// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/messages/android/message_wrapper.h"
#include <string>
#include "base/android/jni_string.h"
#include "base/logging.h"
#include "content/public/browser/web_contents.h"
#include "ui/gfx/android/java_bitmap.h"
// Must come after all headers that specialize FromJniType() / ToJniType().
#include "components/messages/android/jni_headers/MessageWrapper_jni.h"
namespace messages {
MessageWrapper::MessageWrapper(MessageIdentifier message_identifier)
: MessageWrapper(message_identifier,
base::NullCallback(),
base::NullCallback()) {}
MessageWrapper::MessageWrapper(MessageIdentifier message_identifier,
base::OnceClosure action_callback,
DismissCallback dismiss_callback)
: action_callback_(std::move(action_callback)),
dismiss_callback_(std::move(dismiss_callback)),
message_enqueued_(false) {
JNIEnv* env = base::android::AttachCurrentThread();
java_message_wrapper_ =
Java_MessageWrapper_create(env, reinterpret_cast<int64_t>(this),
static_cast<int>(message_identifier));
}
MessageWrapper::~MessageWrapper() {
CHECK(!message_enqueued_);
}
std::u16string MessageWrapper::GetTitle() {
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jstring> jtitle =
Java_MessageWrapper_getTitle(env, java_message_wrapper_);
return jtitle.is_null() ? std::u16string()
: base::android::ConvertJavaStringToUTF16(jtitle);
}
void MessageWrapper::SetTitle(const std::u16string& title) {
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jstring> jtitle =
base::android::ConvertUTF16ToJavaString(env, title);
Java_MessageWrapper_setTitle(env, java_message_wrapper_, jtitle);
}
std::u16string MessageWrapper::GetDescription() {
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jstring> jdescription =
Java_MessageWrapper_getDescription(env, java_message_wrapper_);
return jdescription.is_null()
? std::u16string()
: base::android::ConvertJavaStringToUTF16(jdescription);
}
void MessageWrapper::SetDescription(const std::u16string& description) {
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jstring> jdescription =
base::android::ConvertUTF16ToJavaString(env, description);
Java_MessageWrapper_setDescription(env, java_message_wrapper_, jdescription);
}
int MessageWrapper::GetDescriptionMaxLines() {
JNIEnv* env = base::android::AttachCurrentThread();
return Java_MessageWrapper_getDescriptionMaxLines(env, java_message_wrapper_);
}
void MessageWrapper::SetDescriptionMaxLines(int max_lines) {
JNIEnv* env = base::android::AttachCurrentThread();
Java_MessageWrapper_setDescriptionMaxLines(env, java_message_wrapper_,
max_lines);
}
std::u16string MessageWrapper::GetPrimaryButtonText() {
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jstring> jprimary_button_text =
Java_MessageWrapper_getPrimaryButtonText(env, java_message_wrapper_);
return jprimary_button_text.is_null()
? std::u16string()
: base::android::ConvertJavaStringToUTF16(jprimary_button_text);
}
void MessageWrapper::SetPrimaryButtonText(
const std::u16string& primary_button_text) {
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jstring> jprimary_button_text =
base::android::ConvertUTF16ToJavaString(env, primary_button_text);
Java_MessageWrapper_setPrimaryButtonText(env, java_message_wrapper_,
jprimary_button_text);
}
int MessageWrapper::GetPrimaryButtonTextMaxLines() {
JNIEnv* env = base::android::AttachCurrentThread();
return Java_MessageWrapper_getPrimaryButtonTextMaxLines(
env, java_message_wrapper_);
}
void MessageWrapper::SetPrimaryButtonTextMaxLines(int max_lines) {
JNIEnv* env = base::android::AttachCurrentThread();
Java_MessageWrapper_setPrimaryButtonTextMaxLines(env, java_message_wrapper_,
max_lines);
}
std::u16string MessageWrapper::GetSecondaryButtonMenuText() {
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jstring> jsecondary_button_menu_text =
Java_MessageWrapper_getSecondaryButtonMenuText(env,
java_message_wrapper_);
return jsecondary_button_menu_text.is_null()
? std::u16string()
: base::android::ConvertJavaStringToUTF16(
jsecondary_button_menu_text);
}
void MessageWrapper::SetSecondaryButtonMenuText(
const std::u16string& secondary_button_menu_text) {
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jstring> jsecondary_button_menu_text =
base::android::ConvertUTF16ToJavaString(env, secondary_button_menu_text);
Java_MessageWrapper_setSecondaryButtonMenuText(env, java_message_wrapper_,
jsecondary_button_menu_text);
}
void MessageWrapper::SetSecondaryMenuMaxSize(SecondaryMenuMaxSize max_size) {
secondary_menu_max_size_ = max_size;
}
void MessageWrapper::AddSecondaryMenuItem(int item_id,
int resource_id,
const std::u16string& item_text) {
DCHECK(!secondary_menu_item_selected_callback_.is_null());
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jstring> jitem_text =
base::android::ConvertUTF16ToJavaString(env, item_text);
Java_MessageWrapper_addSecondaryMenuItem(env, java_message_wrapper_, item_id,
resource_id, jitem_text);
}
void MessageWrapper::AddSecondaryMenuItem(
int item_id,
int resource_id,
const std::u16string& item_text,
const std::u16string& item_description) {
DCHECK(secondary_menu_item_selected_callback_);
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jstring> jitem_text =
base::android::ConvertUTF16ToJavaString(env, item_text);
base::android::ScopedJavaLocalRef<jstring> jitem_desc =
base::android::ConvertUTF16ToJavaString(env, item_description);
Java_MessageWrapper_addSecondaryMenuItem(env, java_message_wrapper_, item_id,
resource_id, jitem_text, jitem_desc);
}
void MessageWrapper::ClearSecondaryMenuItems() {
JNIEnv* env = base::android::AttachCurrentThread();
Java_MessageWrapper_clearSecondaryMenuItems(env, java_message_wrapper_);
}
void MessageWrapper::AddSecondaryMenuItemDivider() {
JNIEnv* env = base::android::AttachCurrentThread();
Java_MessageWrapper_addSecondaryMenuItemDivider(env, java_message_wrapper_);
}
int MessageWrapper::GetIconResourceId() {
JNIEnv* env = base::android::AttachCurrentThread();
return Java_MessageWrapper_getIconResourceId(env, java_message_wrapper_);
}
void MessageWrapper::SetIconResourceId(int resource_id) {
JNIEnv* env = base::android::AttachCurrentThread();
Java_MessageWrapper_setIconResourceId(env, java_message_wrapper_,
resource_id);
}
bool MessageWrapper::IsValidIcon() {
JNIEnv* env = base::android::AttachCurrentThread();
return Java_MessageWrapper_isValidIcon(env, java_message_wrapper_);
}
void MessageWrapper::SetIcon(const SkBitmap& icon) {
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jobject> java_bitmap =
gfx::ConvertToJavaBitmap(icon);
Java_MessageWrapper_setIcon(env, java_message_wrapper_, java_bitmap);
}
void MessageWrapper::EnableLargeIcon(bool enabled) {
JNIEnv* env = base::android::AttachCurrentThread();
Java_MessageWrapper_setLargeIcon(env, java_message_wrapper_, enabled);
}
void MessageWrapper::SetIconRoundedCornerRadius(int radius) {
JNIEnv* env = base::android::AttachCurrentThread();
Java_MessageWrapper_setIconRoundedCornerRadius(env, java_message_wrapper_,
radius);
}
void MessageWrapper::DisableIconTint() {
JNIEnv* env = base::android::AttachCurrentThread();
Java_MessageWrapper_disableIconTint(env, java_message_wrapper_);
}
int MessageWrapper::GetSecondaryIconResourceId() {
JNIEnv* env = base::android::AttachCurrentThread();
return Java_MessageWrapper_getSecondaryIconResourceId(env,
java_message_wrapper_);
}
void MessageWrapper::SetSecondaryIconResourceId(int resource_id) {
JNIEnv* env = base::android::AttachCurrentThread();
Java_MessageWrapper_setSecondaryIconResourceId(env, java_message_wrapper_,
resource_id);
}
void MessageWrapper::SetSecondaryActionCallback(
base::RepeatingClosure callback) {
secondary_action_callback_ = std::move(callback);
}
void MessageWrapper::SetSecondaryMenuItemSelectedCallback(
base::RepeatingCallback<void(int)> callback) {
secondary_menu_item_selected_callback_ = std::move(callback);
}
void MessageWrapper::SetDuration(long customDuration) {
JNIEnv* env = base::android::AttachCurrentThread();
Java_MessageWrapper_setDuration(env, java_message_wrapper_, customDuration);
}
void MessageWrapper::SetActionClick(base::OnceClosure callback) {
action_callback_ = std::move(callback);
}
void MessageWrapper::SetDismissCallback(DismissCallback callback) {
dismiss_callback_ = std::move(callback);
}
void MessageWrapper::HandleActionClick(JNIEnv* env) {
if (!action_callback_.is_null())
std::move(action_callback_).Run();
}
void MessageWrapper::HandleSecondaryActionClick(JNIEnv* env) {
if (!secondary_action_callback_.is_null())
secondary_action_callback_.Run();
}
void MessageWrapper::HandleSecondaryMenuItemSelected(JNIEnv* env, int item_id) {
if (!secondary_menu_item_selected_callback_.is_null())
secondary_menu_item_selected_callback_.Run(item_id);
}
void MessageWrapper::HandleDismissCallback(JNIEnv* env, int dismiss_reason) {
// Make sure message dismissed callback is called exactly once.
message_enqueued_ = false;
Java_MessageWrapper_clearNativePtr(env, java_message_wrapper_);
if (!dismiss_callback_.is_null())
std::move(dismiss_callback_)
.Run(static_cast<DismissReason>(dismiss_reason));
// Dismiss callback typically deletes the instance of MessageWrapper,
// invalidating |this| pointer. Don't call any methods after dismiss_callback_
// is invoked.
}
const base::android::JavaRef<jobject>& MessageWrapper::GetJavaMessageWrapper()
const {
return java_message_wrapper_;
}
void MessageWrapper::SetMessageEnqueued(
const base::android::JavaRef<jobject>& java_window_android) {
message_enqueued_ = true;
java_window_android_ = java_window_android;
JNIEnv* env = base::android::AttachCurrentThread();
Java_MessageWrapper_initializeSecondaryMenu(
env, java_message_wrapper_, java_window_android_,
static_cast<int>(secondary_menu_max_size_));
}
const SkBitmap MessageWrapper::GetIconBitmap() {
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jobject> bitmap =
Java_MessageWrapper_getIconBitmap(env, java_message_wrapper_);
gfx::JavaBitmap java_bitmap_lock(bitmap);
return gfx::CreateSkBitmapFromJavaBitmap(java_bitmap_lock);
}
} // namespace messages