blob: ec2f56e2f50d7334421efe372b16b81bb84ee622 [file] [log] [blame]
// Copyright 2016 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 "chromecast/browser/android/cast_content_window_android.h"
#include <memory>
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/logging.h"
#include "chromecast/browser/jni_headers/CastContentWindowAndroid_jni.h"
#include "content/public/browser/web_contents.h"
#include "ui/events/keycodes/keyboard_code_conversion_android.h"
namespace chromecast {
using base::android::ConvertUTF8ToJavaString;
namespace {
base::android::ScopedJavaLocalRef<jobject> CreateJavaWindow(
jlong native_window,
bool enable_touch_input,
bool is_remote_control_mode,
bool turn_on_screen,
bool keep_screen_on,
const std::string& session_id) {
JNIEnv* env = base::android::AttachCurrentThread();
return Java_CastContentWindowAndroid_create(
env, native_window, enable_touch_input, is_remote_control_mode,
turn_on_screen, keep_screen_on, ConvertUTF8ToJavaString(env, session_id));
}
constexpr char kContextInteractionId[] = "interactionId";
constexpr char kContextConversationId[] = "conversationId";
constexpr char kGestureConsumedCallbackClassName[] =
"org/chromium/chromecast/shell/"
"CastWebContentsComponent$GestureHandledCallback";
// Wraps the JNI gesture consumption handled callback for invocation from C++.
class GestureConsumedCallbackWrapper {
public:
GestureConsumedCallbackWrapper(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& callback)
: env_(env), callback_(callback) {
class_ = base::android::ScopedJavaGlobalRef<jclass>(
base::android::GetClass(env_, kGestureConsumedCallbackClassName));
callback_method_id_ =
base::android::MethodID::Get<base::android::MethodID::TYPE_INSTANCE>(
env_, class_.obj(), "invoke",
"(Z" // boolean handled
")V");
}
GestureConsumedCallbackWrapper& operator=(
const GestureConsumedCallbackWrapper&) = delete;
GestureConsumedCallbackWrapper(const GestureConsumedCallbackWrapper&) =
delete;
void Invoke(bool handled) {
jboolean handled_value(handled);
env_->CallVoidMethod(callback_.obj(), callback_method_id_, handled_value);
}
private:
JNIEnv* env_;
const base::android::ScopedJavaGlobalRef<jobject> callback_;
base::android::ScopedJavaGlobalRef<jclass> class_;
jmethodID callback_method_id_;
};
} // namespace
CastContentWindowAndroid::CastContentWindowAndroid(
base::WeakPtr<Delegate> delegate,
mojom::CastWebViewParamsPtr params)
: CastContentWindow(delegate, std::move(params)),
web_contents_attached_(false),
java_window_(CreateJavaWindow(reinterpret_cast<jlong>(this),
params_->enable_touch_input,
params_->is_remote_control_mode,
params_->turn_on_screen,
params_->keep_screen_on,
params_->session_id)) {}
CastContentWindowAndroid::~CastContentWindowAndroid() {
JNIEnv* env = base::android::AttachCurrentThread();
Java_CastContentWindowAndroid_onNativeDestroyed(env, java_window_);
}
void CastContentWindowAndroid::CreateWindow(
mojom::ZOrder /* z_order */,
VisibilityPriority visibility_priority) {
if (web_contents_attached_) {
RequestVisibility(visibility_priority);
return;
}
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jobject> java_web_contents =
cast_web_contents()->web_contents()->GetJavaWebContents();
Java_CastContentWindowAndroid_createWindowForWebContents(
env, java_window_, java_web_contents,
ConvertUTF8ToJavaString(env, params_->activity_id),
static_cast<int>(visibility_priority));
web_contents_attached_ = true;
cast_web_contents()->web_contents()->Focus();
}
void CastContentWindowAndroid::GrantScreenAccess() {
JNIEnv* env = base::android::AttachCurrentThread();
Java_CastContentWindowAndroid_grantScreenAccess(env, java_window_);
}
void CastContentWindowAndroid::RevokeScreenAccess() {
JNIEnv* env = base::android::AttachCurrentThread();
Java_CastContentWindowAndroid_revokeScreenAccess(env, java_window_);
}
void CastContentWindowAndroid::EnableTouchInput(bool enabled) {
JNIEnv* env = base::android::AttachCurrentThread();
Java_CastContentWindowAndroid_enableTouchInput(
env, java_window_, static_cast<jboolean>(enabled));
}
void CastContentWindowAndroid::OnActivityStopped(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& jcaller) {
if (delegate_) {
delegate_->OnWindowDestroyed();
}
}
void CastContentWindowAndroid::RequestVisibility(
VisibilityPriority visibility_priority) {
JNIEnv* env = base::android::AttachCurrentThread();
Java_CastContentWindowAndroid_requestVisibilityPriority(
env, java_window_, static_cast<int>(visibility_priority));
}
void CastContentWindowAndroid::SetActivityContext(
base::Value activity_context) {}
void CastContentWindowAndroid::SetHostContext(base::Value host_context) {
auto* found_interaction_id = host_context.FindKey(kContextInteractionId);
auto* found_conversation_id = host_context.FindKey(kContextConversationId);
if (found_interaction_id && found_conversation_id) {
int interaction_id = found_interaction_id->GetInt();
std::string& conversation_id = found_conversation_id->GetString();
JNIEnv* env = base::android::AttachCurrentThread();
Java_CastContentWindowAndroid_setHostContext(
env, java_window_, static_cast<int>(interaction_id),
ConvertUTF8ToJavaString(env, conversation_id));
} else {
LOG(ERROR) << "Interaction ID or Conversation ID is not found";
}
}
void CastContentWindowAndroid::NotifyVisibilityChange(
VisibilityType visibility_type) {
if (delegate_) {
delegate_->OnVisibilityChange(visibility_type);
}
for (auto& observer : observer_list_) {
observer.OnVisibilityChange(visibility_type);
}
}
void CastContentWindowAndroid::RequestMoveOut() {
JNIEnv* env = base::android::AttachCurrentThread();
Java_CastContentWindowAndroid_requestMoveOut(env, java_window_);
}
void CastContentWindowAndroid::ConsumeGesture(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& jcaller,
int gesture_type,
const base::android::JavaParamRef<jobject>& callback) {
auto wrapper =
std::make_unique<GestureConsumedCallbackWrapper>(env, callback);
if (gesture_router()) {
gesture_router()->ConsumeGesture(
static_cast<GestureType>(gesture_type),
base::BindOnce(&GestureConsumedCallbackWrapper::Invoke,
std::move(wrapper)));
return;
}
wrapper->Invoke(false);
}
void CastContentWindowAndroid::OnVisibilityChange(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& jcaller,
int visibility_type) {
NotifyVisibilityChange(static_cast<VisibilityType>(visibility_type));
}
} // namespace chromecast