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

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: Use std::move more 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_NATIVE_PTR = 0;
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_NATIVE_PTR;
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
Yusuf 2017/02/07 19:12:17 javadoc?
darin (slow to review) 2017/02/08 07:29:27 Done.
128 public AppWebMessagePort(AppWebMessagePortService messagePortService) { 116 public static AppWebMessagePort[] createPair() {
129 mMessagePortService = messagePortService; 117 AppWebMessagePort[] ports =
130 mPostMessageSender = new PostMessageSender(this, mMessagePortService); 118 new AppWebMessagePort[] { new AppWebMessagePort(), new AppWebMessage Port() };
131 mMessagePortService.addObserver(mPostMessageSender); 119 ports[0].nativeInitializeAppWebMessagePortPair(ports);
Yusuf 2017/02/07 19:12:17 We can declare this static on this side as well. S
darin (slow to review) 2017/02/08 07:29:27 Thanks, this worked. I had previously marked the m
120 return ports;
121 }
122
Yusuf 2017/02/07 19:12:17 We don't need this anymore?
darin (slow to review) 2017/02/08 07:29:27 Good catch. Removed.
123 public AppWebMessagePort() {
132 } 124 }
133 125
134 @Override 126 @Override
135 public boolean isReady() { 127 public boolean isReady() {
136 return mPortId != PENDING; 128 return mNativeAppWebMessagePort != UNINITIALIZED_PORT_NATIVE_PTR;
137 } 129 }
138 130
139 public int portId() { 131 @CalledByNative
140 return mPortId; 132 private void setNativeAppWebMessagePort(long nativeAppWebMessagePort) {
133 mNativeAppWebMessagePort = nativeAppWebMessagePort;
141 } 134 }
142 135
143 public void setPortId(int id) { 136 @CalledByNative
144 mPortId = id; 137 private long releaseNativePortForTransfer() {
145 releaseMessages(); 138 mTransferred = true;
139 long port = mNativeAppWebMessagePort;
140 mNativeAppWebMessagePort = UNINITIALIZED_PORT_NATIVE_PTR;
141 return port;
146 } 142 }
147 143
148 @Override 144 @Override
149 public void close() { 145 public void close() {
150 if (mTransferred) { 146 if (mTransferred) {
151 throw new IllegalStateException("Port is already transferred"); 147 throw new IllegalStateException("Port is already transferred");
152 } 148 }
153 synchronized (mLock) { 149 synchronized (mLock) {
154 if (mClosed) return; 150 if (mClosed) return;
155 mClosed = true; 151 mClosed = true;
156 } 152 }
157 // If the port is already ready, and no messages are waiting in the 153 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(); 154 cleanup();
163 } 155 }
164 } 156 }
165 157
166 @Override 158 @Override
167 public boolean isClosed() { 159 public boolean isClosed() {
168 return mClosed; 160 synchronized (mLock) {
161 return mClosed;
162 }
169 } 163 }
170 164
171 @Override 165 @Override
172 public boolean isTransferred() { 166 public boolean isTransferred() {
173 return mTransferred; 167 return mTransferred;
174 } 168 }
175 169
176 public void setTransferred() {
177 mTransferred = true;
178 }
179
180 @Override 170 @Override
181 public boolean isStarted() { 171 public boolean isStarted() {
182 return mStarted; 172 return mStarted;
183 } 173 }
184 174
185 // Only called on UI thread 175 // Only called on UI thread
186 @Override 176 @Override
187 public void setMessageCallback(MessageCallback messageCallback, Handler hand ler) { 177 public void setMessageCallback(MessageCallback messageCallback, Handler hand ler) {
188 mStarted = true; 178 mStarted = true;
189 synchronized (mLock) { 179 synchronized (mLock) {
190 mMessageCallback = messageCallback; 180 mMessageCallback = messageCallback;
191 if (handler != null) { 181 if (handler != null) {
192 mHandler = new MessageHandler(handler.getLooper()); 182 mHandler = new MessageHandler(handler.getLooper());
193 } 183 }
194 } 184 }
195 releaseMessages(); 185 nativeStartReceivingMessages(mNativeAppWebMessagePort);
196 } 186 }
197 187
198 // Only called on IO thread. 188 // Called on a background thread.
199 public void onReceivedMessage(String message, AppWebMessagePort[] sentPorts) { 189 @CalledByNative
190 private void onMessagesAvailable() {
200 synchronized (mLock) { 191 synchronized (mLock) {
201 PostMessageFromWeb m = new PostMessageFromWeb(this, message, sentPor ts);
202 Handler handler = mHandler != null ? mHandler : sDefaultHandler; 192 Handler handler = mHandler != null ? mHandler : sDefaultHandler;
203 Message msg = handler.obtainMessage(POST_MESSAGE, m); 193 Message msg = handler.obtainMessage(MESSAGES_AVAILABLE, this);
204 handler.sendMessage(msg); 194 handler.sendMessage(msg);
205 } 195 }
206 } 196 }
207 197
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. 198 // This method may be called on a different thread than UI thread.
217 public void onMessage(String message, AppWebMessagePort[] ports) { 199 @CalledByNative
200 private void onReceivedMessage(String message, AppWebMessagePort[] ports) {
218 synchronized (mLock) { 201 synchronized (mLock) {
219 if (isClosed()) { 202 if (isClosed()) {
220 Log.w(TAG, "Port [" + mPortId + "] received message in closed st ate"); 203 Log.w(TAG, "Port [" + mNativeAppWebMessagePort
204 + "] received message in closed state");
221 return; 205 return;
222 } 206 }
223 if (mMessageCallback == null) { 207 if (mMessageCallback == null) {
224 Log.w(TAG, 208 Log.w(TAG, "No handler set for port [" + mNativeAppWebMessagePor t
225 "No handler set for port [" + mPortId + "], dropping mes sage " + message); 209 + "], dropping message " + message);
226 return; 210 return;
227 } 211 }
228 mMessageCallback.onMessage(message, ports); 212 mMessageCallback.onMessage(message, ports);
229 } 213 }
230 } 214 }
231 215
216 public void dispatchReceivedMessages() {
Yusuf 2017/02/07 19:12:17 javadoc
darin (slow to review) 2017/02/08 07:29:27 I just changed this method to be private.
217 nativeDispatchReceivedMessages(mNativeAppWebMessagePort);
218 }
219
232 @Override 220 @Override
233 public void postMessage(String message, MessagePort[] sentPorts) throws Ille galStateException { 221 public void postMessage(String message, MessagePort[] sentPorts) throws Ille galStateException {
234 if (isClosed() || isTransferred()) { 222 if (isClosed() || isTransferred()) {
235 throw new IllegalStateException("Port is already closed or transferr ed"); 223 throw new IllegalStateException("Port is already closed or transferr ed");
236 } 224 }
237 AppWebMessagePort[] ports = null; 225 AppWebMessagePort[] ports = null;
238 if (sentPorts != null) { 226 if (sentPorts != null) {
239 for (MessagePort port : sentPorts) { 227 for (MessagePort port : sentPorts) {
240 if (port.equals(this)) { 228 if (port.equals(this)) {
241 throw new IllegalStateException("Source port cannot be trans ferred"); 229 throw new IllegalStateException("Source port cannot be trans ferred");
242 } 230 }
231 if (port.isClosed() || port.isTransferred()) {
232 throw new IllegalStateException("Port is already closed or t ransferred");
233 }
234 if (port.isStarted()) {
235 throw new IllegalStateException("Port is already started");
236 }
243 } 237 }
244 ports = Arrays.copyOf(sentPorts, sentPorts.length, AppWebMessagePort [].class); 238 ports = Arrays.copyOf(sentPorts, sentPorts.length, AppWebMessagePort [].class);
245 } 239 }
246 mStarted = true; 240 mStarted = true;
247 mPostMessageSender.postMessage(null, message, null, ports); 241 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 } 242 }
270 243
271 private void cleanup() { 244 private void cleanup() {
272 mMessagePortService.removeObserver(mPostMessageSender); 245 nativeCloseMessagePort(mNativeAppWebMessagePort);
273 mPostMessageSender = null; 246 mNativeAppWebMessagePort = UNINITIALIZED_PORT_NATIVE_PTR;
274 mMessagePortService.closePort(mPortId);
275 } 247 }
248
249 private native void nativeInitializeAppWebMessagePortPair(AppWebMessagePort[ ] ports);
Yusuf 2017/02/07 19:12:17 you can declare this private static native and the
250
251 private native void nativeCloseMessagePort(long nativeAppWebMessagePort);
252 private native void nativePostMessage(long nativeAppWebMessagePort, String m essage,
253 AppWebMessagePort[] ports);
254 private native void nativeDispatchReceivedMessages(long nativeAppWebMessageP ort);
255 private native void nativeStartReceivingMessages(long nativeAppWebMessagePor t);
276 } 256 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698