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

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

Issue 920873003: Return created channels synchronously (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 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 side-by-side diff with in-line comments
Download patch
Index: android_webview/java/src/org/chromium/android_webview/PostMessageSender.java
diff --git a/android_webview/java/src/org/chromium/android_webview/PostMessageSender.java b/android_webview/java/src/org/chromium/android_webview/PostMessageSender.java
new file mode 100644
index 0000000000000000000000000000000000000000..1159c1bb6e3a2c86ad72a5397ee4d97350c58d5a
--- /dev/null
+++ b/android_webview/java/src/org/chromium/android_webview/PostMessageSender.java
@@ -0,0 +1,149 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.android_webview;
+
+import java.util.ArrayDeque;
hush (inactive) 2015/02/13 03:25:08 please add a new line after this.
sgurun-gerrit only 2015/02/13 05:11:59 Done.
+/**
+ * Sanity checks and sends post messages to web. Queues messages if necessary.
+ */
+public class PostMessageSender implements AwMessagePortService.MessageChannelObserver {
+
+ /**
+ * The interface for message handler.
+ */
+ public static interface PostMessageSenderDelegate {
+ void postMessageToWeb(String frameName, String message, String sourceOrigin,
+ String targetOrigin, int[] sentPorts);
+ };
+
+ // A struct to store Message parameters that are sent from App to Web.
+ private static class PostMessageParams {
+ public String frameName;
+ public String message;
+ public String sourceOrigin;
+ public String targetOrigin;
+ public MessagePort[] sentPorts;
+
+ public PostMessageParams(String frameName, String message, String sourceOrigin,
+ String targetOrigin, MessagePort[] sentPorts) {
+ this.frameName = frameName;
+ this.message = message;
+ this.sourceOrigin = sourceOrigin;
+ this.targetOrigin = targetOrigin;
+ this.sentPorts = sentPorts;
+ }
+ }
+
+ private PostMessageSenderDelegate mDelegate;
+ private AwMessagePortService mService;
+
+ // If a message that is sent from android webview to web has a pending port (a port that
+ // is not internally created yet), this message, and any following messages will be
+ // queued until the transferred port becomes ready. This is necessary to prevent any
+ // reordering.
+ private boolean mShouldQueue = false;
+ private ArrayDeque<PostMessageParams> mMessageQueue = new ArrayDeque<PostMessageParams>();
+
+ public PostMessageSender(PostMessageSenderDelegate delegate, AwMessagePortService service) {
+ mDelegate = delegate;
+ mService = service;
+ }
+
+ // Return true if any sent port is pending.
+ private boolean anySentPortIsPending(MessagePort[] sentPorts) {
+ if (sentPorts != null) {
+ for (MessagePort port : sentPorts) {
+ if (!port.isReady()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ // By default the sender is always ready.
+ protected boolean senderIsReady() {
+ return true;
+ }
+
+ // A message to a frame is queued if:
+ // 1. Sender is not ready to post. When posting messages to frames, sender is always
+ // ready. However, when posting messages using message channels, sender may be in
+ // a pending state.
+ // 2. The mShouldQueue mode is already on. Having mShouldQueue mode true means
+ // there is a already a message with a pending port in queue.
+ // 3. The message includes a port that is not ready yet.
+ private boolean shouldQueueMessage(MessagePort[] sentPorts) {
+ // if messages to frames are already in queue mode, simply queue it, no need to
+ // check ports.
+ if (mShouldQueue || !senderIsReady()) {
+ return true;
+ }
+ if (anySentPortIsPending(sentPorts)) {
+ mShouldQueue = true;
hush (inactive) 2015/02/13 03:25:08 I feel it is weird that a method that looks like i
sgurun-gerrit only 2015/02/13 05:11:59 this is a private method so I did not worry too mu
+ return true;
+ }
+ return false;
+ }
+
+ private void postMessageToWeb(String frameName, String message, String sourceOrigin,
+ String targetOrigin, MessagePort[] sentPorts) {
+ int[] portIds = null;
+ if (sentPorts != null) {
+ portIds = new int[sentPorts.length];
+ for (int i = 0; i < sentPorts.length; i++) {
+ portIds[i] = sentPorts[i].portId();
+ }
+ mService.removeSentPorts(portIds);
+ }
+ mDelegate.postMessageToWeb(frameName, message, sourceOrigin, targetOrigin, portIds);
+ }
+
+ /*
+ * Sanity checks the message and queues it if necessary. Posts the message to delegate
+ * when message can be sent.
+ */
+ public void postMessage(String frameName, String message, String sourceOrigin,
hush (inactive) 2015/02/13 03:25:08 name it postMessageIfPossible?
sgurun-gerrit only 2015/02/13 05:11:59 I think the name is compatible with HTML5 MessageP
+ String targetOrigin, MessagePort[] sentPorts) throws IllegalStateException {
+ // Sanity check all the ports that are being transferred.
+ if (sentPorts != null) {
+ for (MessagePort p : sentPorts) {
+ if (p.isClosed() || p.isTransferred()) {
+ throw new IllegalStateException("Port cannot be transferred");
+ }
+ p.setTransferred();
+ }
+ }
+ if (shouldQueueMessage(sentPorts)) {
+ mMessageQueue.add(new PostMessageParams(frameName, message, sourceOrigin,
+ targetOrigin, sentPorts));
+ } else {
+ postMessageToWeb(frameName, message, sourceOrigin, targetOrigin, sentPorts);
+ }
+ }
+
+ /*
+ * Starts posting any messages that are queued.
+ */
+ public void onMessageChannelCreated() {
+ PostMessageParams msg;
+
+ if (!senderIsReady()) {
+ return;
+ }
+
+ while ((msg = mMessageQueue.peek()) != null) {
+ // If there are still pending ports, message cannot be posted.
+ if (anySentPortIsPending(msg.sentPorts)) {
+ return;
+ }
+ mMessageQueue.remove();
+ postMessageToWeb(msg.frameName, msg.message, msg.sourceOrigin, msg.targetOrigin,
+ msg.sentPorts);
+ }
+ // No more messages in the queue.
+ mShouldQueue = false;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698