Chromium Code Reviews| 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..97e300a9a67e88be926b9ad2ffd0e93dd1ca5d53 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]) |
|
hush (inactive)
2015/03/06 22:32:37
indent to the left by 1
sgurun-gerrit only
2015/03/06 22:51:34
Done.
|
| + * |
| + * 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); |
| } |