| Index: content/browser/android/app_web_message_port.cc
|
| diff --git a/content/browser/android/app_web_message_port.cc b/content/browser/android/app_web_message_port.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..56d538079d469fe6c87fabf289ef95dd8f06e29a
|
| --- /dev/null
|
| +++ b/content/browser/android/app_web_message_port.cc
|
| @@ -0,0 +1,163 @@
|
| +// Copyright 2017 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 "content/browser/android/app_web_message_port.h"
|
| +
|
| +#include "base/android/jni_android.h"
|
| +#include "base/android/jni_string.h"
|
| +#include "base/bind.h"
|
| +#include "content/browser/android/string_message_codec.h"
|
| +#include "jni/AppWebMessagePort_jni.h"
|
| +
|
| +namespace content {
|
| +
|
| +// static
|
| +void AppWebMessagePort::CreateAndBindToJavaObject(
|
| + JNIEnv* env,
|
| + mojo::ScopedMessagePipeHandle handle,
|
| + const base::android::JavaRef<jobject>& jobject) {
|
| + AppWebMessagePort* instance =
|
| + new AppWebMessagePort(env, std::move(handle), jobject);
|
| + Java_AppWebMessagePort_setNativeAppWebMessagePort(
|
| + env, jobject, reinterpret_cast<jlong>(instance));
|
| +}
|
| +
|
| +// static
|
| +std::vector<MessagePort> AppWebMessagePort::UnwrapJavaArray(
|
| + JNIEnv* env,
|
| + const base::android::JavaRef<jobjectArray>& jports) {
|
| + std::vector<MessagePort> ports;
|
| + if (!jports.is_null()) {
|
| + jsize num_ports = env->GetArrayLength(jports.obj());
|
| + for (jsize i = 0; i < num_ports; ++i) {
|
| + base::android::ScopedJavaLocalRef<jobject> jport(
|
| + env, env->GetObjectArrayElement(jports.obj(), i));
|
| + jlong native_port =
|
| + Java_AppWebMessagePort_releaseNativePortForTransfer(env, jport);
|
| + // Uninitialized ports should be trapper earlier at the Java layer.
|
| + DCHECK(native_port != -1);
|
| + AppWebMessagePort* instance =
|
| + reinterpret_cast<AppWebMessagePort*>(native_port);
|
| + ports.push_back(instance->port_);
|
| + }
|
| + }
|
| + return ports;
|
| +}
|
| +
|
| +void AppWebMessagePort::CloseMessagePort(
|
| + JNIEnv* env,
|
| + const base::android::JavaParamRef<jobject>& jcaller) {
|
| + // Explicitly reset the port here to ensure that OnMessagesAvailable has
|
| + // finished before we destroy this.
|
| + port_ = MessagePort();
|
| +
|
| + delete this;
|
| +}
|
| +
|
| +void AppWebMessagePort::PostMessage(
|
| + JNIEnv* env,
|
| + const base::android::JavaParamRef<jobject>& jcaller,
|
| + const base::android::JavaParamRef<jstring>& jmessage,
|
| + const base::android::JavaParamRef<jobjectArray>& jports) {
|
| + port_.PostMessage(
|
| + EncodeStringMessage(base::android::ConvertJavaStringToUTF16(jmessage)),
|
| + UnwrapJavaArray(env, jports));
|
| +}
|
| +
|
| +void AppWebMessagePort::DispatchReceivedMessages(
|
| + JNIEnv* env,
|
| + const base::android::JavaParamRef<jobject>& jcaller) {
|
| + jmethodID app_web_message_port_constructor =
|
| + base::android::MethodID::Get<base::android::MethodID::TYPE_INSTANCE>(
|
| + env, AppWebMessagePort_clazz(env), "<init>", "()V");
|
| +
|
| + // Consume all of the available messages.
|
| + // TODO(darin): Consider breaking this up across multiple PostTask calls.
|
| + for (;;) {
|
| + base::string16 encoded_message;
|
| + std::vector<MessagePort> ports;
|
| + if (!port_.GetMessage(&encoded_message, &ports))
|
| + return;
|
| +
|
| + base::string16 message;
|
| + if (!DecodeStringMessage(encoded_message, &message))
|
| + return;
|
| +
|
| + base::android::ScopedJavaLocalRef<jstring> jmessage =
|
| + base::android::ConvertUTF16ToJavaString(env, message);
|
| +
|
| + base::android::ScopedJavaLocalRef<jobjectArray> jports;
|
| + if (ports.size() > 0) {
|
| + jports = base::android::ScopedJavaLocalRef<jobjectArray>(
|
| + env,
|
| + env->NewObjectArray(ports.size(),
|
| + AppWebMessagePort_clazz(env),
|
| + nullptr));
|
| +
|
| + // Instantiate the Java and C++ wrappers for the transferred ports.
|
| + for (size_t i = 0; i < ports.size(); ++i) {
|
| + base::android::ScopedJavaLocalRef<jobject> jport(
|
| + env,
|
| + env->NewObject(AppWebMessagePort_clazz(env),
|
| + app_web_message_port_constructor));
|
| + CreateAndBindToJavaObject(env, ports[i].ReleaseHandle(), jport);
|
| +
|
| + env->SetObjectArrayElement(jports.obj(), i, jport.obj());
|
| + }
|
| + }
|
| +
|
| + Java_AppWebMessagePort_onReceivedMessage(
|
| + env, java_ref_.get(env), jmessage, jports);
|
| + }
|
| +}
|
| +
|
| +void AppWebMessagePort::StartReceivingMessages(
|
| + JNIEnv* env,
|
| + const base::android::JavaParamRef<jobject>& jcaller) {
|
| + port_.SetCallback(
|
| + base::Bind(&AppWebMessagePort::OnMessagesAvailable,
|
| + base::Unretained(this)));
|
| +}
|
| +
|
| +AppWebMessagePort::AppWebMessagePort(
|
| + JNIEnv* env,
|
| + mojo::ScopedMessagePipeHandle handle,
|
| + const base::android::JavaRef<jobject>& jobject)
|
| + : port_(std::move(handle)),
|
| + java_ref_(env, jobject) {
|
| +}
|
| +
|
| +AppWebMessagePort::~AppWebMessagePort() {
|
| +}
|
| +
|
| +void AppWebMessagePort::OnMessagesAvailable() {
|
| + // Called on the IO thread.
|
| + JNIEnv* env = base::android::AttachCurrentThread();
|
| + Java_AppWebMessagePort_onMessagesAvailable(env, java_ref_.get(env));
|
| +}
|
| +
|
| +bool RegisterAppWebMessagePort(JNIEnv* env) {
|
| + return RegisterNativesImpl(env);
|
| +}
|
| +
|
| +void InitializeAppWebMessagePortPair(
|
| + JNIEnv* env,
|
| + const base::android::JavaParamRef<jclass>& jcaller,
|
| + const base::android::JavaParamRef<jobjectArray>& ports) {
|
| + DCHECK_EQ(2, env->GetArrayLength(ports.obj()));
|
| +
|
| + mojo::MessagePipe pipe;
|
| +
|
| + base::android::ScopedJavaLocalRef<jobject> jport0(
|
| + env, env->GetObjectArrayElement(ports.obj(), 0));
|
| + AppWebMessagePort::CreateAndBindToJavaObject(
|
| + env, std::move(pipe.handle0), jport0);
|
| +
|
| + base::android::ScopedJavaLocalRef<jobject> jport1(
|
| + env, env->GetObjectArrayElement(ports.obj(), 1));
|
| + AppWebMessagePort::CreateAndBindToJavaObject(
|
| + env, std::move(pipe.handle1), jport1);
|
| +}
|
| +
|
| +} // namespace content
|
|
|