1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "android_webview/native/aw_message_port_service_impl.h"
7 #include "android_webview/browser/aw_browser_context.h"
8 #include "android_webview/browser/aw_message_port_message_filter.h"
9 #include "android_webview/native/aw_contents.h"
10 #include "base/android/jni_array.h"
11 #include "base/android/jni_string.h"
12 #include "base/bind.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/browser/message_port_provider.h"
15 #include "jni/AwMessagePortService_jni.h"
17 namespace android_webview
{
19 using base::android::AttachCurrentThread
;
20 using base::android::ConvertJavaStringToUTF16
;
21 using base::android::ConvertUTF16ToJavaString
;
22 using base::android::ScopedJavaGlobalRef
;
23 using base::android::ScopedJavaLocalRef
;
24 using base::android::ToJavaIntArray
;
25 using content::BrowserThread
;
26 using content::MessagePortProvider
;
29 AwMessagePortServiceImpl
* AwMessagePortServiceImpl::GetInstance() {
30 return static_cast<AwMessagePortServiceImpl
*>(
31 AwBrowserContext::GetDefault()->GetMessagePortService());
34 AwMessagePortServiceImpl::AwMessagePortServiceImpl() {
37 AwMessagePortServiceImpl::~AwMessagePortServiceImpl() {
38 JNIEnv
* env
= AttachCurrentThread();
39 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
42 Java_AwMessagePortService_unregisterNativeAwMessagePortService(env
,
46 void AwMessagePortServiceImpl::Init(JNIEnv
* env
, jobject obj
) {
47 java_ref_
= JavaObjectWeakGlobalRef(env
, obj
);
50 void AwMessagePortServiceImpl::CreateMessageChannel(
53 scoped_refptr
<AwMessagePortMessageFilter
> filter
) {
54 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
56 ScopedJavaGlobalRef
<jobject
>* j_callback
= new ScopedJavaGlobalRef
<jobject
>();
57 j_callback
->Reset(env
, callback
);
59 int* portId1
= new int;
60 int* portId2
= new int;
61 BrowserThread::PostTaskAndReply(
64 base::Bind(&AwMessagePortServiceImpl::CreateMessageChannelOnIOThread
,
65 base::Unretained(this),
69 base::Bind(&AwMessagePortServiceImpl::OnMessageChannelCreated
,
70 base::Unretained(this),
71 base::Owned(j_callback
),
73 base::Owned(portId2
)));
76 void AwMessagePortServiceImpl::OnConvertedWebToAppMessage(
78 const base::ListValue
& message
,
79 const std::vector
<int>& sent_message_port_ids
) {
80 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
81 JNIEnv
* env
= AttachCurrentThread();
82 ScopedJavaLocalRef
<jobject
> jobj
= java_ref_
.get(env
);
86 if (message
.GetSize() != 1) {
92 if (!message
.GetString(0, &value
)) {
93 LOG(WARNING
) << "Converting post message to a string failed for port "
97 ScopedJavaLocalRef
<jstring
> jmsg
= ConvertUTF16ToJavaString(env
, value
);
98 ScopedJavaLocalRef
<jintArray
> jports
=
99 ToJavaIntArray(env
, sent_message_port_ids
);
100 Java_AwMessagePortService_onPostMessage(env
,
107 void AwMessagePortServiceImpl::OnMessagePortMessageFilterClosing(
108 AwMessagePortMessageFilter
* filter
) {
109 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
110 for (MessagePorts::iterator iter
= ports_
.begin();
111 iter
!= ports_
.end(); iter
++) {
112 if (iter
->second
== filter
) {
118 void AwMessagePortServiceImpl::PostAppToWebMessage(JNIEnv
* env
, jobject obj
,
119 int sender_id
, jstring message
, jintArray sent_ports
) {
120 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
121 base::string16
* j_message
= new base::string16
;
122 ConvertJavaStringToUTF16(env
, message
, j_message
);
123 std::vector
<int>* j_sent_ports
= new std::vector
<int>;
124 if (sent_ports
!= nullptr)
125 base::android::JavaIntArrayToIntVector(env
, sent_ports
, j_sent_ports
);
127 BrowserThread::PostTask(
130 base::Bind(&AwMessagePortServiceImpl::PostAppToWebMessageOnIOThread
,
131 base::Unretained(this),
133 base::Owned(j_message
),
134 base::Owned(j_sent_ports
)));
137 void AwMessagePortServiceImpl::RemoveSentPorts(
138 const std::vector
<int>& sent_ports
) {
139 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
140 // Remove the filters that are associated with the transferred ports
141 for (const auto& iter
: sent_ports
)
145 void AwMessagePortServiceImpl::PostAppToWebMessageOnIOThread(
147 base::string16
* message
,
148 std::vector
<int>* sent_ports
) {
149 RemoveSentPorts(*sent_ports
);
150 ports_
[sender_id
]->SendAppToWebMessage(sender_id
, *message
, *sent_ports
);
154 void AwMessagePortServiceImpl::CreateMessageChannelOnIOThread(
155 scoped_refptr
<AwMessagePortMessageFilter
> filter
,
158 MessagePortProvider::CreateMessageChannel(filter
.get(), portId1
, portId2
);
159 AddPort(*portId1
, filter
.get());
160 AddPort(*portId2
, filter
.get());
163 void AwMessagePortServiceImpl::OnMessageChannelCreated(
164 ScopedJavaGlobalRef
<jobject
>* callback
,
167 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
168 JNIEnv
* env
= AttachCurrentThread();
169 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
172 Java_AwMessagePortService_onMessageChannelCreated(env
, obj
.obj(), *port1
,
173 *port2
, callback
->obj());
176 void AwMessagePortServiceImpl::AddPort(int message_port_id
,
177 AwMessagePortMessageFilter
* filter
) {
178 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
179 if (ports_
.count(message_port_id
)) {
183 ports_
[message_port_id
] = filter
;
186 bool RegisterAwMessagePortService(JNIEnv
* env
) {
187 return RegisterNativesImpl(env
);
191 jlong
InitAwMessagePortService(JNIEnv
* env
, jobject obj
) {
192 AwMessagePortServiceImpl
* service
= AwMessagePortServiceImpl::GetInstance();
193 service
->Init(env
, obj
);
194 return reinterpret_cast<intptr_t>(service
);
197 } // namespace android_webview