Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: content/public/android/java/src/org/chromium/content/browser/AppWebMessagePort.java

Issue 2422793002: HTML MessagePort as mojo::MessagePipeHandle (Closed)
Patch Set: Rebase Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.content.browser; 5 package org.chromium.content.browser;
6 6
7 import android.os.Handler; 7 import android.os.Handler;
8 import android.os.Looper; 8 import android.os.Looper;
9 import android.os.Message; 9 import android.os.Message;
10 10
11 import org.chromium.base.Log; 11 import org.chromium.base.Log;
12 import org.chromium.base.annotations.CalledByNative;
13 import org.chromium.base.annotations.JNINamespace;
12 import org.chromium.content_public.browser.MessagePort; 14 import org.chromium.content_public.browser.MessagePort;
13 15
14 import java.util.Arrays; 16 import java.util.Arrays;
15 17
16 /** 18 /**
17 * Represents the MessageChannel MessagePort object. Inspired from 19 * Represents the MessageChannel MessagePort object. Inspired from
18 * http://www.whatwg.org/specs/web-apps/current-work/multipage/web-messaging.htm l#message-channels 20 * http://www.whatwg.org/specs/web-apps/current-work/multipage/web-messaging.htm l#message-channels
19 * 21 *
20 * State management: 22 * State management:
21 * 23 *
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 * A port is put to a "started" state if: 68 * A port is put to a "started" state if:
67 * 1. The port is ever used to post a message, or 69 * 1. The port is ever used to post a message, or
68 * 2. The port was ever registered a handler to receive a message. 70 * 2. The port was ever registered a handler to receive a message.
69 * A started port cannot be transferred. 71 * A started port cannot be transferred.
70 * 72 *
71 * This restriction should not impact postmessage functionality in a big way, 73 * This restriction should not impact postmessage functionality in a big way,
72 * because an app can still create as many channels as it wants to and use it fo r 74 * because an app can still create as many channels as it wants to and use it fo r
73 * transferring data. As a return, it simplifies implementation and prevents har d 75 * transferring data. As a return, it simplifies implementation and prevents har d
74 * to debug, racy corner cases while receiving/sending data. 76 * to debug, racy corner cases while receiving/sending data.
75 */ 77 */
76 public class AppWebMessagePort implements MessagePort, PostMessageSender.PostMes sageSenderDelegate { 78 @JNINamespace("content")
77 private static final String TAG = "MessagePort"; 79 public class AppWebMessagePort implements MessagePort {
78 private static final int PENDING = -1; 80 private static final String TAG = "AppWebMessagePort";
81 private static final long UNINITIALIZED_PORT = -1;
Yusuf 2017/01/26 22:53:54 in all JNI classes 0 in general is used as the uni
79 82
80 // the what value for POST_MESSAGE 83 // The |what| value for handleMessage.
81 private static final int POST_MESSAGE = 1; 84 private static final int MESSAGES_AVAILABLE = 1;
82
83 private static class PostMessageFromWeb {
84 public AppWebMessagePort port;
85 public String message;
86 public AppWebMessagePort[] sentPorts;
87
88 public PostMessageFromWeb(
89 AppWebMessagePort port, String message, AppWebMessagePort[] sent Ports) {
90 this.port = port;
91 this.message = message;
92 this.sentPorts = sentPorts;
93 }
94 }
95 85
96 // Implements the handler to handle messageport messages received from web. 86 // Implements the handler to handle messageport messages received from web.
97 // These messages are received on IO thread and normally handled in main 87 // These messages are received on IO thread and normally handled in main
98 // thread however, alternatively application can pass a handler to execute t hem. 88 // thread however, alternatively application can pass a handler to execute t hem.
99 private static class MessageHandler extends Handler { 89 private static class MessageHandler extends Handler {
100 public MessageHandler(Looper looper) { 90 public MessageHandler(Looper looper) {
101 super(looper); 91 super(looper);
102 } 92 }
103 @Override 93 @Override
104 public void handleMessage(Message msg) { 94 public void handleMessage(Message msg) {
105 if (msg.what == POST_MESSAGE) { 95 if (msg.what == MESSAGES_AVAILABLE) {
106 PostMessageFromWeb m = (PostMessageFromWeb) msg.obj; 96 AppWebMessagePort port = (AppWebMessagePort) msg.obj;
107 m.port.onMessage(m.message, m.sentPorts); 97 port.dispatchReceivedMessages();
108 return; 98 return;
109 } 99 }
110 throw new IllegalStateException("undefined message"); 100 throw new IllegalStateException("undefined message");
111 } 101 }
112 } 102 }
113 // The default message handler 103 // The default message handler
114 private static final MessageHandler sDefaultHandler = 104 private static final MessageHandler sDefaultHandler =
115 new MessageHandler(Looper.getMainLooper()); 105 new MessageHandler(Looper.getMainLooper());
116 106
117 private int mPortId = PENDING; 107 private long mNativeAppWebMessagePort = UNINITIALIZED_PORT;
108
118 private MessageCallback mMessageCallback; 109 private MessageCallback mMessageCallback;
119 private AppWebMessagePortService mMessagePortService;
120 private boolean mClosed; 110 private boolean mClosed;
121 private boolean mTransferred; 111 private boolean mTransferred;
122 private boolean mStarted; 112 private boolean mStarted;
123 private boolean mReleasedMessages;
124 private PostMessageSender mPostMessageSender;
125 private MessageHandler mHandler; 113 private MessageHandler mHandler;
126 private final Object mLock = new Object(); 114 private final Object mLock = new Object();
127 115
128 public AppWebMessagePort(AppWebMessagePortService messagePortService) { 116 public AppWebMessagePort() {
129 mMessagePortService = messagePortService;
130 mPostMessageSender = new PostMessageSender(this, mMessagePortService);
131 mMessagePortService.addObserver(mPostMessageSender);
132 } 117 }
133 118
134 @Override 119 @Override
135 public boolean isReady() { 120 public boolean isReady() {
136 return mPortId != PENDING; 121 return mNativeAppWebMessagePort != UNINITIALIZED_PORT;
137 } 122 }
138 123
139 public int portId() { 124 @CalledByNative
140 return mPortId; 125 private void setNativeAppWebMessagePort(long nativeAppWebMessagePort) {
126 mNativeAppWebMessagePort = nativeAppWebMessagePort;
141 } 127 }
142 128
143 public void setPortId(int id) { 129 @CalledByNative
144 mPortId = id; 130 private long releaseNativePortForTransfer() {
145 releaseMessages(); 131 mTransferred = true;
132 long port = mNativeAppWebMessagePort;
133 mNativeAppWebMessagePort = UNINITIALIZED_PORT;
134 return port;
146 } 135 }
147 136
148 @Override 137 @Override
149 public void close() { 138 public void close() {
150 if (mTransferred) { 139 if (mTransferred) {
151 throw new IllegalStateException("Port is already transferred"); 140 throw new IllegalStateException("Port is already transferred");
152 } 141 }
153 synchronized (mLock) { 142 synchronized (mLock) {
154 if (mClosed) return; 143 if (mClosed) return;
155 mClosed = true; 144 mClosed = true;
156 } 145 }
157 // If the port is already ready, and no messages are waiting in the 146 if (isReady()) {
158 // queue to be transferred, onPostMessageQueueEmpty() callback is not
159 // received (it is received only after messages are purged). In this
160 // case do the cleanup here.
161 if (isReady() && mPostMessageSender.isMessageQueueEmpty()) {
162 cleanup(); 147 cleanup();
163 } 148 }
164 } 149 }
165 150
166 @Override 151 @Override
167 public boolean isClosed() { 152 public boolean isClosed() {
168 return mClosed; 153 synchronized (mLock) {
154 return mClosed;
155 }
169 } 156 }
170 157
171 @Override 158 @Override
172 public boolean isTransferred() { 159 public boolean isTransferred() {
173 return mTransferred; 160 return mTransferred;
174 } 161 }
175 162
176 public void setTransferred() {
177 mTransferred = true;
178 }
179
180 @Override 163 @Override
181 public boolean isStarted() { 164 public boolean isStarted() {
182 return mStarted; 165 return mStarted;
183 } 166 }
184 167
185 // Only called on UI thread 168 // Only called on UI thread
186 @Override 169 @Override
187 public void setMessageCallback(MessageCallback messageCallback, Handler hand ler) { 170 public void setMessageCallback(MessageCallback messageCallback, Handler hand ler) {
188 mStarted = true; 171 mStarted = true;
189 synchronized (mLock) { 172 synchronized (mLock) {
190 mMessageCallback = messageCallback; 173 mMessageCallback = messageCallback;
191 if (handler != null) { 174 if (handler != null) {
192 mHandler = new MessageHandler(handler.getLooper()); 175 mHandler = new MessageHandler(handler.getLooper());
193 } 176 }
194 } 177 }
195 releaseMessages(); 178 nativeStartReceivingMessages(mNativeAppWebMessagePort);
196 } 179 }
197 180
198 // Only called on IO thread. 181 // Called on a background thread.
199 public void onReceivedMessage(String message, AppWebMessagePort[] sentPorts) { 182 @CalledByNative
183 private void onMessagesAvailable() {
200 synchronized (mLock) { 184 synchronized (mLock) {
201 PostMessageFromWeb m = new PostMessageFromWeb(this, message, sentPor ts);
202 Handler handler = mHandler != null ? mHandler : sDefaultHandler; 185 Handler handler = mHandler != null ? mHandler : sDefaultHandler;
203 Message msg = handler.obtainMessage(POST_MESSAGE, m); 186 Message msg = handler.obtainMessage(MESSAGES_AVAILABLE, this);
204 handler.sendMessage(msg); 187 handler.sendMessage(msg);
205 } 188 }
206 } 189 }
207 190
208 private void releaseMessages() {
209 if (mReleasedMessages || !isReady() || mMessageCallback == null) {
210 return;
211 }
212 mReleasedMessages = true;
213 mMessagePortService.releaseMessages(mPortId);
214 }
215
216 // This method may be called on a different thread than UI thread. 191 // This method may be called on a different thread than UI thread.
217 public void onMessage(String message, AppWebMessagePort[] ports) { 192 @CalledByNative
193 private void onReceivedMessage(String message, AppWebMessagePort[] ports) {
218 synchronized (mLock) { 194 synchronized (mLock) {
219 if (isClosed()) { 195 if (isClosed()) {
220 Log.w(TAG, "Port [" + mPortId + "] received message in closed st ate"); 196 Log.w(TAG, "Port [" + mNativeAppWebMessagePort
197 + "] received message in closed state");
221 return; 198 return;
222 } 199 }
223 if (mMessageCallback == null) { 200 if (mMessageCallback == null) {
224 Log.w(TAG, 201 Log.w(TAG, "No handler set for port [" + mNativeAppWebMessagePor t
225 "No handler set for port [" + mPortId + "], dropping mes sage " + message); 202 + "], dropping message " + message);
226 return; 203 return;
227 } 204 }
228 mMessageCallback.onMessage(message, ports); 205 mMessageCallback.onMessage(message, ports);
229 } 206 }
230 } 207 }
231 208
209 public void dispatchReceivedMessages() {
Yusuf 2017/01/26 22:53:54 javadoc
210 nativeDispatchReceivedMessages(mNativeAppWebMessagePort);
211 }
212
232 @Override 213 @Override
233 public void postMessage(String message, MessagePort[] sentPorts) throws Ille galStateException { 214 public void postMessage(String message, MessagePort[] sentPorts) throws Ille galStateException {
234 if (isClosed() || isTransferred()) { 215 if (isClosed() || isTransferred()) {
235 throw new IllegalStateException("Port is already closed or transferr ed"); 216 throw new IllegalStateException("Port is already closed or transferr ed");
236 } 217 }
237 AppWebMessagePort[] ports = null; 218 AppWebMessagePort[] ports = null;
238 if (sentPorts != null) { 219 if (sentPorts != null) {
239 for (MessagePort port : sentPorts) { 220 for (MessagePort port : sentPorts) {
240 if (port.equals(this)) { 221 if (port.equals(this)) {
241 throw new IllegalStateException("Source port cannot be trans ferred"); 222 throw new IllegalStateException("Source port cannot be trans ferred");
242 } 223 }
224 if (port.isClosed() || port.isTransferred()) {
225 throw new IllegalStateException("Port is already closed or t ransferred");
226 }
227 if (port.isStarted()) {
228 throw new IllegalStateException("Port is already started");
229 }
243 } 230 }
244 ports = Arrays.copyOf(sentPorts, sentPorts.length, AppWebMessagePort [].class); 231 ports = Arrays.copyOf(sentPorts, sentPorts.length, AppWebMessagePort [].class);
245 } 232 }
246 mStarted = true; 233 mStarted = true;
247 mPostMessageSender.postMessage(null, message, null, ports); 234 nativePostMessage(mNativeAppWebMessagePort, message, ports);
248 }
249
250 // Implements PostMessageSender.PostMessageSenderDelegate interface method.
251 @Override
252 public boolean isPostMessageSenderReady() {
253 return isReady();
254 }
255
256 // Implements PostMessageSender.PostMessageSenderDelegate interface method.
257 @Override
258 public void onPostMessageQueueEmpty() {
259 if (isClosed()) {
260 cleanup();
261 }
262 }
263
264 // Implements PostMessageSender.PostMessageSenderDelegate interface method.
265 @Override
266 public void postMessageToWeb(
267 String frameName, String message, String targetOrigin, int[] sentPor tIds) {
268 mMessagePortService.postMessage(mPortId, message, sentPortIds);
269 } 235 }
270 236
271 private void cleanup() { 237 private void cleanup() {
272 mMessagePortService.removeObserver(mPostMessageSender); 238 nativeCloseMessagePort(mNativeAppWebMessagePort);
273 mPostMessageSender = null; 239 mNativeAppWebMessagePort = UNINITIALIZED_PORT;
274 mMessagePortService.closePort(mPortId);
275 } 240 }
241
242 private native void nativeCloseMessagePort(long nativeAppWebMessagePort);
243 private native void nativePostMessage(long nativeAppWebMessagePort, String m essage,
244 AppWebMessagePort[] ports);
245 private native void nativeDispatchReceivedMessages(long nativeAppWebMessageP ort);
246 private native void nativeStartReceivingMessages(long nativeAppWebMessagePor t);
276 } 247 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698