| Index: android_webview/java/src/org/chromium/android_webview/MessagePort.java
|
| diff --git a/android_webview/java/src/org/chromium/android_webview/MessagePort.java b/android_webview/java/src/org/chromium/android_webview/MessagePort.java
|
| index 620cbbbcb95428cd2d00c64a321b0af2b1ecb2d5..fc41de39bc4d64bca0121ede55c500c37af18269 100644
|
| --- a/android_webview/java/src/org/chromium/android_webview/MessagePort.java
|
| +++ b/android_webview/java/src/org/chromium/android_webview/MessagePort.java
|
| @@ -4,6 +4,9 @@
|
|
|
| package org.chromium.android_webview;
|
|
|
| +import android.os.Handler;
|
| +import android.os.Looper;
|
| +import android.os.Message;
|
| import android.util.Log;
|
|
|
| /**
|
| @@ -32,7 +35,10 @@ import android.util.Log;
|
| * since the ownership is also transferred during the transfer. Closing a transferred port will
|
| * throw an exception.
|
| *
|
| - * TODO(sgurun) implement queueing messages while a port is in transfer
|
| + * The fact that messages can be handled on a separate thread means that thread
|
| + * synchronization is important. All methods are called on UI thread except as noted.
|
| + *
|
| + * TODO(sgurun) implement queueing messages while a port is in transfer.
|
| */
|
| public class MessagePort implements PostMessageSender.PostMessageSenderDelegate {
|
|
|
| @@ -41,16 +47,53 @@ public class MessagePort implements PostMessageSender.PostMessageSenderDelegate
|
| */
|
| public abstract static class WebEventHandler {
|
| public abstract void onMessage(String message);
|
| - };
|
| + }
|
|
|
| private static final String TAG = "MessagePort";
|
| private static final int PENDING = -1;
|
| +
|
| + // the what value for POST_MESSAGE
|
| + private static final int POST_MESSAGE = 1;
|
| +
|
| + private static class PostMessageFromWeb {
|
| + public MessagePort port;
|
| + public String message;
|
| +
|
| + public PostMessageFromWeb(MessagePort port, String message) {
|
| + this.port = port;
|
| + this.message = message;
|
| + }
|
| + }
|
| +
|
| + // Implements the handler to handle messageport messages received from web.
|
| + // These messages are received on IO thread and normally handled in main
|
| + // thread however, alternatively application can pass a handler to execute them.
|
| + private static class MessageHandler extends Handler {
|
| + public MessageHandler(Looper looper) {
|
| + super(looper);
|
| + }
|
| + @Override
|
| + public void handleMessage(Message msg) {
|
| + if (msg.what == POST_MESSAGE) {
|
| + PostMessageFromWeb m = (PostMessageFromWeb) msg.obj;
|
| + m.port.onMessage(m.message);
|
| + return;
|
| + }
|
| + throw new IllegalStateException("undefined message");
|
| + }
|
| + }
|
| + // The default message handler
|
| + private static final MessageHandler sDefaultHandler =
|
| + new MessageHandler(Looper.getMainLooper());
|
| +
|
| private int mPortId = PENDING;
|
| private WebEventHandler mWebEventHandler;
|
| private AwMessagePortService mMessagePortService;
|
| private boolean mClosed;
|
| private boolean mTransferred;
|
| private PostMessageSender mPostMessageSender;
|
| + private MessageHandler mHandler;
|
| + private Object mLock = new Object();
|
|
|
| public MessagePort(AwMessagePortService messagePortService) {
|
| mMessagePortService = messagePortService;
|
| @@ -74,8 +117,10 @@ public class MessagePort implements PostMessageSender.PostMessageSenderDelegate
|
| if (mTransferred) {
|
| throw new IllegalStateException("Port is already transferred");
|
| }
|
| - if (mClosed) return;
|
| - mClosed = true;
|
| + synchronized (mLock) {
|
| + if (mClosed) return;
|
| + mClosed = true;
|
| + }
|
| // If the port is already ready, and no messages are waiting in the
|
| // queue to be transferred, onPostMessageQueueEmpty() callback is not
|
| // received (it is received only after messages are purged). In this
|
| @@ -97,20 +142,39 @@ public class MessagePort implements PostMessageSender.PostMessageSenderDelegate
|
| mTransferred = true;
|
| }
|
|
|
| - public void setWebEventHandler(WebEventHandler webEventHandler) {
|
| - mWebEventHandler = webEventHandler;
|
| + public void setWebEventHandler(WebEventHandler webEventHandler, Handler handler) {
|
| + synchronized (mLock) {
|
| + mWebEventHandler = webEventHandler;
|
| + if (handler != null) {
|
| + mHandler = new MessageHandler(handler.getLooper());
|
| + }
|
| + }
|
| }
|
|
|
| - public void onMessage(String message) {
|
| - if (isClosed()) {
|
| - Log.w(TAG, "Port [" + mPortId + "] received message in closed state");
|
| - return;
|
| + // Called on IO thread.
|
| + public void onReceivedMessage(String message) {
|
| + synchronized (mLock) {
|
| + PostMessageFromWeb m = new PostMessageFromWeb(this, message);
|
| + Handler handler = mHandler != null ? mHandler : sDefaultHandler;
|
| + Message msg = handler.obtainMessage(POST_MESSAGE, m);
|
| + handler.sendMessage(msg);
|
| }
|
| - if (mWebEventHandler == null) {
|
| - Log.w(TAG, "No handler set for port [" + mPortId + "], dropping message " + message);
|
| - return;
|
| + }
|
| +
|
| + // This method may be called on a different thread than UI thread.
|
| + public void onMessage(String message) {
|
| + synchronized (mLock) {
|
| + if (isClosed()) {
|
| + Log.w(TAG, "Port [" + mPortId + "] received message in closed state");
|
| + return;
|
| + }
|
| + if (mWebEventHandler == null) {
|
| + Log.w(TAG, "No handler set for port [" + mPortId + "], dropping message "
|
| + + message);
|
| + return;
|
| + }
|
| + mWebEventHandler.onMessage(message);
|
| }
|
| - mWebEventHandler.onMessage(message);
|
| }
|
|
|
| public void postMessage(String message, MessagePort[] msgPorts) throws IllegalStateException {
|
|
|