| 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 fc41de39bc4d64bca0121ede55c500c37af18269..b7394d1a5f38d86fb399f25d89b8db8eb698d11e 100644
|
| --- a/android_webview/java/src/org/chromium/android_webview/MessagePort.java
|
| +++ b/android_webview/java/src/org/chromium/android_webview/MessagePort.java
|
| @@ -38,7 +38,36 @@ import android.util.Log;
|
| * 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.
|
| + * Restrictions:
|
| + * The HTML5 message protocol is very flexible in transferring ports. However, this
|
| + * sometimes leads to surprising behavior. For example, in current version of chrome (m41)
|
| + * the code below
|
| + * 1. var c1 = new MessageChannel();
|
| + * 2. var c2 = new MessageChannel();
|
| + * 3. c1.port2.onmessage= function(e) { console.log("1"); }
|
| + * 4. c2.port2.onmessage = function(e) {
|
| + * 5. e.ports[0].onmessage = function(f) {
|
| + * 6. console.log("3");
|
| + * 7. }
|
| + * 8. }
|
| + * 9. c1.port1.postMessage("test");
|
| + * 10. c2.port1.postMessage("test2",[c1.port2])
|
| + *
|
| + * prints 1 or 3 depending on whether or not line 10 is included in code. Further if
|
| + * it gets executed with a timeout, depending on timeout value, the printout value
|
| + * changes.
|
| + *
|
| + * To prevent such problems, Android webview implementation limits the transfer of ports
|
| + * as below:
|
| + * Webview puts a port to a "started" state if:
|
| + * 1. The port is ever used to post a message, or
|
| + * 2. The port was ever registered a handler to receive a message.
|
| + * A started port cannot be transferred.
|
| + *
|
| + * This restriction should not impact postmessage functionality in a big way,
|
| + * because an app can still create as many channels as it wants to and use it for
|
| + * transferring data. As a return, it simplifies implementation and prevents hard
|
| + * to debug, racy corner cases while receiving/sending data.
|
| */
|
| public class MessagePort implements PostMessageSender.PostMessageSenderDelegate {
|
|
|
| @@ -91,6 +120,8 @@ public class MessagePort implements PostMessageSender.PostMessageSenderDelegate
|
| private AwMessagePortService mMessagePortService;
|
| private boolean mClosed;
|
| private boolean mTransferred;
|
| + private boolean mStarted;
|
| + private boolean mReleasedMessages;
|
| private PostMessageSender mPostMessageSender;
|
| private MessageHandler mHandler;
|
| private Object mLock = new Object();
|
| @@ -111,6 +142,7 @@ public class MessagePort implements PostMessageSender.PostMessageSenderDelegate
|
|
|
| public void setPortId(int id) {
|
| mPortId = id;
|
| + releaseMessages();
|
| }
|
|
|
| public void close() {
|
| @@ -142,16 +174,23 @@ public class MessagePort implements PostMessageSender.PostMessageSenderDelegate
|
| mTransferred = true;
|
| }
|
|
|
| + public boolean isStarted() {
|
| + return mStarted;
|
| + }
|
| +
|
| + // Only called on UI thread
|
| public void setWebEventHandler(WebEventHandler webEventHandler, Handler handler) {
|
| + mStarted = true;
|
| synchronized (mLock) {
|
| mWebEventHandler = webEventHandler;
|
| if (handler != null) {
|
| mHandler = new MessageHandler(handler.getLooper());
|
| }
|
| }
|
| + releaseMessages();
|
| }
|
|
|
| - // Called on IO thread.
|
| + // Only called on IO thread.
|
| public void onReceivedMessage(String message) {
|
| synchronized (mLock) {
|
| PostMessageFromWeb m = new PostMessageFromWeb(this, message);
|
| @@ -161,6 +200,14 @@ public class MessagePort implements PostMessageSender.PostMessageSenderDelegate
|
| }
|
| }
|
|
|
| + private void releaseMessages() {
|
| + if (mReleasedMessages || !isReady() || mWebEventHandler == null) {
|
| + return;
|
| + }
|
| + mReleasedMessages = true;
|
| + mMessagePortService.releaseMessages(mPortId);
|
| + }
|
| +
|
| // This method may be called on a different thread than UI thread.
|
| public void onMessage(String message) {
|
| synchronized (mLock) {
|
| @@ -188,6 +235,7 @@ public class MessagePort implements PostMessageSender.PostMessageSenderDelegate
|
| }
|
| }
|
| }
|
| + mStarted = true;
|
| mPostMessageSender.postMessage(null, message, null, msgPorts);
|
| }
|
|
|
|
|