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

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: disable a test for real and remove a wrong assertion 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..1a01f5e7d6c8845452f20de873729ba67eb24af2
--- /dev/null
+++ b/android_webview/java/src/org/chromium/android_webview/PostMessageSender.java
@@ -0,0 +1,150 @@
+// 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;
+
+/**
+ * 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 {
+
+ /*
+ * Posts a message to the destination frame for real. The unique message port
+ * id of any transferred port should be known at this time.
+ */
+ void postMessageToWeb(String frameName, String message, String sourceOrigin,
+ String targetOrigin, int[] sentPortIds);
+ };
+
+ // 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 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. There are already queued messages
+ // 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 (mMessageQueue.size() > 0 || !senderIsReady()) {
+ return true;
+ }
+ if (anySentPortIsPending(sentPorts)) {
+ 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,
+ 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);
+ }
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698