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
<jobjectArray
>* j_ports
=
57 new ScopedJavaGlobalRef
<jobjectArray
>();
58 j_ports
->Reset(env
, ports
);
60 int* portId1
= new int;
61 int* portId2
= new int;
62 BrowserThread::PostTaskAndReply(
65 base::Bind(&AwMessagePortServiceImpl::CreateMessageChannelOnIOThread
,
66 base::Unretained(this),
70 base::Bind(&AwMessagePortServiceImpl::OnMessageChannelCreated
,
71 base::Unretained(this),
74 base::Owned(portId2
)));
77 void AwMessagePortServiceImpl::OnConvertedWebToAppMessage(
79 const base::ListValue
& message
,
80 const std::vector
<int>& sent_message_port_ids
) {
81 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
82 JNIEnv
* env
= AttachCurrentThread();
83 ScopedJavaLocalRef
<jobject
> jobj
= java_ref_
.get(env
);
88 if (!message
.GetString(0, &value
)) {
89 LOG(WARNING
) << "Converting post message to a string failed for port "
94 if (message
.GetSize() != 1) {
99 ScopedJavaLocalRef
<jstring
> jmsg
= ConvertUTF16ToJavaString(env
, value
);
100 ScopedJavaLocalRef
<jintArray
> jports
=
101 ToJavaIntArray(env
, sent_message_port_ids
);
102 Java_AwMessagePortService_onReceivedMessage(env
,
109 void AwMessagePortServiceImpl::OnMessagePortMessageFilterClosing(
110 AwMessagePortMessageFilter
* filter
) {
111 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
112 for (MessagePorts::iterator iter
= ports_
.begin();
113 iter
!= ports_
.end(); iter
++) {
114 if (iter
->second
== filter
) {
120 void AwMessagePortServiceImpl::PostAppToWebMessage(JNIEnv
* env
, jobject obj
,
121 int sender_id
, jstring message
, jintArray sent_ports
) {
122 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
123 base::string16
* j_message
= new base::string16
;
124 ConvertJavaStringToUTF16(env
, message
, j_message
);
125 std::vector
<int>* j_sent_ports
= new std::vector
<int>;
126 if (sent_ports
!= nullptr)
127 base::android::JavaIntArrayToIntVector(env
, sent_ports
, j_sent_ports
);
129 BrowserThread::PostTask(
132 base::Bind(&AwMessagePortServiceImpl::PostAppToWebMessageOnIOThread
,
133 base::Unretained(this),
135 base::Owned(j_message
),
136 base::Owned(j_sent_ports
)));
139 // The message port service cannot immediately close the port, because
140 // it is possible that messages are still queued in the renderer process
141 // waiting for a conversion. Instead, it sends a special message with
142 // a flag which indicates that this message port should be closed.
143 void AwMessagePortServiceImpl::ClosePort(JNIEnv
* env
, jobject obj
,
144 int message_port_id
) {
145 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
146 BrowserThread::PostTask(
149 base::Bind(&AwMessagePortServiceImpl::PostClosePortMessage
,
150 base::Unretained(this),
154 void AwMessagePortServiceImpl::ReleaseMessages(JNIEnv
* env
, jobject obj
,
155 int message_port_id
) {
156 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
157 BrowserThread::PostTask(
160 base::Bind(&MessagePortProvider::ReleaseMessages
, message_port_id
));
163 void AwMessagePortServiceImpl::RemoveSentPorts(
164 const std::vector
<int>& sent_ports
) {
165 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
166 // Remove the filters that are associated with the transferred ports
167 for (const auto& iter
: sent_ports
)
171 void AwMessagePortServiceImpl::PostAppToWebMessageOnIOThread(
173 base::string16
* message
,
174 std::vector
<int>* sent_ports
) {
175 RemoveSentPorts(*sent_ports
);
176 ports_
[sender_id
]->SendAppToWebMessage(sender_id
, *message
, *sent_ports
);
179 void AwMessagePortServiceImpl::PostClosePortMessage(int message_port_id
) {
180 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
181 ports_
[message_port_id
]->SendClosePortMessage(message_port_id
);
184 void AwMessagePortServiceImpl::CleanupPort(int message_port_id
) {
185 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
186 ports_
.erase(message_port_id
);
189 void AwMessagePortServiceImpl::CreateMessageChannelOnIOThread(
190 scoped_refptr
<AwMessagePortMessageFilter
> filter
,
193 MessagePortProvider::CreateMessageChannel(filter
.get(), portId1
, portId2
);
194 MessagePortProvider::HoldMessages(*portId1
);
195 MessagePortProvider::HoldMessages(*portId2
);
196 AddPort(*portId1
, filter
.get());
197 AddPort(*portId2
, filter
.get());
200 void AwMessagePortServiceImpl::OnMessageChannelCreated(
201 ScopedJavaGlobalRef
<jobjectArray
>* ports
,
204 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
205 JNIEnv
* env
= AttachCurrentThread();
206 ScopedJavaLocalRef
<jobject
> obj
= java_ref_
.get(env
);
209 Java_AwMessagePortService_onMessageChannelCreated(env
, obj
.obj(), *port1
,
210 *port2
, ports
->obj());
213 void AwMessagePortServiceImpl::AddPort(int message_port_id
,
214 AwMessagePortMessageFilter
* filter
) {
215 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
216 if (ports_
.count(message_port_id
)) {
220 ports_
[message_port_id
] = filter
;
223 bool RegisterAwMessagePortService(JNIEnv
* env
) {
224 return RegisterNativesImpl(env
);
228 jlong
InitAwMessagePortService(JNIEnv
* env
, jobject obj
) {
229 AwMessagePortServiceImpl
* service
= AwMessagePortServiceImpl::GetInstance();
230 service
->Init(env
, obj
);
231 return reinterpret_cast<intptr_t>(service
);
234 } // namespace android_webview