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

Unified Diff: android_webview/java/src/org/chromium/android_webview/MessagePort.java

Issue 986553004: Hold messages in message port service when a message port is (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 9 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 side-by-side diff with in-line comments
Download patch
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);
}

Powered by Google App Engine
This is Rietveld 408576698