blob: fa2587c233d81034b40f6f7d6ec19670193290df [file] [log] [blame]
// Copyright 2020 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.
// This file contains the native implementation of MessagePortDescriptor.java,
// which wraps blink::MessagePortDescriptor from
// /third_party/blink/public/common/messaging/message_port_descriptor.h.
#include "third_party/blink/public/common/messaging/message_port_descriptor.h"
#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/scoped_java_ref.h"
#include "base/stl_util.h"
#include "base/unguessable_token.h"
#include "content/public/android/content_jni_headers/AppWebMessagePortDescriptor_jni.h"
#include "mojo/public/cpp/system/message_pipe.h"
using base::android::JavaRef;
using base::android::ScopedJavaLocalRef;
namespace {
mojo::ScopedMessagePipeHandle WrapNativeHandle(jint native_handle) {
MojoHandle raw_handle = static_cast<MojoHandle>(native_handle);
DCHECK_NE(MOJO_HANDLE_INVALID, raw_handle);
return mojo::ScopedMessagePipeHandle(mojo::MessagePipeHandle(raw_handle));
}
} // namespace
JNI_EXPORT ScopedJavaLocalRef<jlongArray>
JNI_AppWebMessagePortDescriptor_CreatePair(JNIEnv* env) {
// Ownership is passed to the Java code. These are cleaned up when
// CloseAndDestroy is called.
blink::MessagePortDescriptor* port0 = new blink::MessagePortDescriptor();
blink::MessagePortDescriptor* port1 = new blink::MessagePortDescriptor();
blink::MessagePortDescriptorPair pipe;
*port0 = pipe.TakePort0();
*port1 = pipe.TakePort1();
uint64_t pointers[2] = {reinterpret_cast<uint64_t>(port0),
reinterpret_cast<uint64_t>(port1)};
return base::android::ToJavaLongArray(
env, reinterpret_cast<const int64_t*>(pointers), base::size(pointers));
}
JNI_EXPORT jlong JNI_AppWebMessagePortDescriptor_Create(JNIEnv* env,
jint native_handle,
jlong id_low,
jlong id_high,
jlong sequence_number) {
base::UnguessableToken id = base::UnguessableToken::Deserialize(
static_cast<uint64_t>(id_high), static_cast<uint64_t>(id_low));
// Ownership is passed to the Java code. This is cleaned up when
// CloseAndDestroy is called.
blink::MessagePortDescriptor* port = new blink::MessagePortDescriptor();
port->InitializeFromSerializedValues(WrapNativeHandle(native_handle), id,
sequence_number);
return reinterpret_cast<jlong>(port);
}
JNI_EXPORT jint JNI_AppWebMessagePortDescriptor_TakeHandleToEntangle(
JNIEnv* env,
jlong native_message_port_decriptor) {
blink::MessagePortDescriptor* message_port_descriptor =
reinterpret_cast<blink::MessagePortDescriptor*>(
native_message_port_decriptor);
DCHECK(message_port_descriptor->IsValid());
DCHECK(!message_port_descriptor->IsEntangled());
// Ownership of the underlying native handle is passed to Java. It is returned
// before tear-down via "giveDisentangledHandle", or marked as having been
// closed via "onConnectionError".
mojo::ScopedMessagePipeHandle handle =
message_port_descriptor->TakeHandleToEntangleWithEmbedder();
return static_cast<jint>(handle.release().value());
}
JNI_EXPORT void JNI_AppWebMessagePortDescriptor_GiveDisentangledHandle(
JNIEnv* env,
jlong native_message_port_decriptor,
jint native_handle) {
blink::MessagePortDescriptor* message_port_descriptor =
reinterpret_cast<blink::MessagePortDescriptor*>(
native_message_port_decriptor);
DCHECK(message_port_descriptor->IsValid());
DCHECK(message_port_descriptor->IsEntangled());
message_port_descriptor->GiveDisentangledHandle(
WrapNativeHandle(native_handle));
}
JNI_EXPORT void JNI_AppWebMessagePortDescriptor_OnConnectionError(
JNIEnv* env,
jlong native_message_port_decriptor) {
blink::MessagePortDescriptor* message_port_descriptor =
reinterpret_cast<blink::MessagePortDescriptor*>(
native_message_port_decriptor);
DCHECK(message_port_descriptor->IsValid());
DCHECK(message_port_descriptor->IsEntangled());
// Return an empty message pipe.
// TODO(chrisha): Once MessagePortDescriptor vends Connectors directly,
// this should use a dedicated member function much like the Java counterpart.
message_port_descriptor->GiveDisentangledHandle(
mojo::ScopedMessagePipeHandle());
}
JNI_EXPORT ScopedJavaLocalRef<jlongArray>
JNI_AppWebMessagePortDescriptor_PassSerialized(
JNIEnv* env,
jlong native_message_port_decriptor) {
blink::MessagePortDescriptor* message_port_descriptor =
reinterpret_cast<blink::MessagePortDescriptor*>(
native_message_port_decriptor);
DCHECK(message_port_descriptor->IsValid());
DCHECK(!message_port_descriptor->IsEntangled());
// Tear down and free the native object.
mojo::ScopedMessagePipeHandle handle =
message_port_descriptor->TakeHandleForSerialization();
base::UnguessableToken id = message_port_descriptor->TakeIdForSerialization();
uint64_t sequence_number =
message_port_descriptor->TakeSequenceNumberForSerialization();
delete message_port_descriptor;
// Serialize its contents and pass to the Java implementation.
uint64_t serialized[4] = {handle.release().value(),
id.GetLowForSerialization(),
id.GetHighForSerialization(), sequence_number};
return base::android::ToJavaLongArray(
env, reinterpret_cast<const int64_t*>(serialized),
base::size(serialized));
}
JNI_EXPORT void JNI_AppWebMessagePortDescriptor_CloseAndDestroy(
JNIEnv* env,
jlong native_message_port_decriptor) {
blink::MessagePortDescriptor* message_port_descriptor =
reinterpret_cast<blink::MessagePortDescriptor*>(
native_message_port_decriptor);
DCHECK(message_port_descriptor->IsValid());
DCHECK(!message_port_descriptor->IsEntangled());
message_port_descriptor->Reset();
delete message_port_descriptor;
}
JNI_EXPORT void JNI_AppWebMessagePortDescriptor_DisentangleCloseAndDestroy(
JNIEnv* env,
jlong native_message_port_descriptor) {
DCHECK_NE(0u, native_message_port_descriptor);
blink::MessagePortDescriptor* message_port_descriptor =
reinterpret_cast<blink::MessagePortDescriptor*>(
native_message_port_descriptor);
// The descriptor should be valid.
DCHECK(message_port_descriptor->IsValid());
// If the descriptor is entangled, then disentangle it with a dummy handle.
// This is because the handle has actually been closed down directly by the
// Java code.
if (message_port_descriptor->IsEntangled()) {
message_port_descriptor->GiveDisentangledHandle(
mojo::ScopedMessagePipeHandle());
}
// Reset it and finally delete the object.
message_port_descriptor->Reset();
delete message_port_descriptor;
}