| 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 4025c4507264c56d4fd753c4bd53be8e57955ece..55dd626f23c9a34cef299066658e19891c1bfab7 100644
|
| --- a/android_webview/java/src/org/chromium/android_webview/MessagePort.java
|
| +++ b/android_webview/java/src/org/chromium/android_webview/MessagePort.java
|
| @@ -9,8 +9,32 @@ import android.util.Log;
|
| /**
|
| * Represents the MessageChannel MessagePort object. Inspired from
|
| * http://www.whatwg.org/specs/web-apps/current-work/multipage/web-messaging.html#message-channels
|
| + *
|
| + * State management:
|
| + *
|
| + * Initially a message port will be in a pending state. It will be ready once it is created in
|
| + * content/ (in IO thread) and a message port id is assigned.
|
| + * A pending message port cannnot be transferred, and cannot send or receive messages. However,
|
| + * these details are hidden from the user. If a message port is in the pending state:
|
| + * 1. Any messages posted in this port will be queued until the port is ready
|
| + * 2. Transferring the port using a message channel will cause the message (and any subsequent
|
| + * messages sent) to be queued until the port is ready
|
| + * 3. Transferring the pending port via postMessageToFrame will cause the message (and all
|
| + * subsequent messages posted via postMessageToFrame) to be queued until the port is ready.
|
| + *
|
| + * A message port should be closed by the app when it is not needed any more. This will free
|
| + * any resources used by it. A closed port cannot receive/send messages and cannot be transferred.
|
| + * close() can be called multiple times.
|
| + *
|
| + * A message port can be in transferred state while a transfer is pending or complete. An
|
| + * application cannot use a transferred port to post messages. If a transferred port
|
| + * receives messages, they will be queued. This state is not visible to embedder app.
|
| + *
|
| + * TODO(sgurun) implement queueing messages while a port is in transfer
|
| + * TODO(sgurun) implement freeing resources in content/message_port_service when a port is
|
| + * closed
|
| */
|
| -public class MessagePort {
|
| +public class MessagePort implements PostMessageSender.PostMessageSenderDelegate {
|
|
|
| /**
|
| * The interface for message handler for receiving messages. Called on a background thread.
|
| @@ -19,33 +43,71 @@ public class MessagePort {
|
| void onMessage(String message);
|
| };
|
|
|
| - private static final String TAG = "MessagePort";
|
| + /**
|
| + * A specialized PostMessageSender for message channel message port.
|
| + */
|
| + private static class MessagePortPostMessageSender extends PostMessageSender {
|
|
|
| - private int mPortId;
|
| + private MessagePort mSender;
|
| +
|
| + public MessagePortPostMessageSender(MessagePort sender, AwMessagePortService service) {
|
| + super(sender, service);
|
| + mSender = sender;
|
| + }
|
| + @Override
|
| + protected boolean senderIsReady() {
|
| + return mSender.isReady();
|
| + }
|
| + }
|
| +
|
| + private static final String TAG = "MessagePort";
|
| + private static final int PENDING = -1;
|
| + private int mPortId = PENDING;
|
| private MessageHandler mHandler;
|
| private AwMessagePortService mMessagePortService;
|
| - // A port is put into a closed state when transferred. Such a port can no longer
|
| - // send or receive messages.
|
| private boolean mClosed;
|
| + private boolean mTransferred;
|
| + private MessagePortPostMessageSender mPostMessageSender;
|
|
|
| - public MessagePort(int portId, AwMessagePortService messagePortService) {
|
| - mPortId = portId;
|
| + public MessagePort(AwMessagePortService messagePortService) {
|
| mMessagePortService = messagePortService;
|
| + mPostMessageSender = new MessagePortPostMessageSender(this, mMessagePortService);
|
| + mMessagePortService.addObserver(mPostMessageSender);
|
| + }
|
| +
|
| + public boolean isReady() {
|
| + return mPortId != PENDING;
|
| }
|
|
|
| public int portId() {
|
| return mPortId;
|
| }
|
|
|
| + public void setPortId(int id) {
|
| + mPortId = id;
|
| + }
|
| +
|
| public void close() {
|
| - assert !mClosed;
|
| - mClosed = true;
|
| + if (!mClosed) {
|
| + mClosed = true;
|
| + mMessagePortService.removeObserver(mPostMessageSender);
|
| + // TODO(sgurun) remove the port from AwMessagePortService and write a test
|
| + // to verify it.
|
| + }
|
| }
|
|
|
| public boolean isClosed() {
|
| return mClosed;
|
| }
|
|
|
| + public boolean isTransferred() {
|
| + return mTransferred;
|
| + }
|
| +
|
| + public void setTransferred() {
|
| + mTransferred = true;
|
| + }
|
| +
|
| public void setMessageHandler(MessageHandler handler) {
|
| mHandler = handler;
|
| }
|
| @@ -63,20 +125,22 @@ public class MessagePort {
|
| }
|
|
|
| public void postMessage(String message, MessagePort[] msgPorts) throws IllegalStateException {
|
| - if (isClosed()) {
|
| - throw new IllegalStateException("Messageport is already closed");
|
| + if (isClosed() || isTransferred()) {
|
| + throw new IllegalStateException("Port is already closed or transferred");
|
| }
|
| - int[] portIds = null;
|
| if (msgPorts != null) {
|
| - portIds = new int[msgPorts.length];
|
| - for (int i = 0; i < msgPorts.length; i++) {
|
| - int sentId = msgPorts[i].portId();
|
| - if (sentId == mPortId) {
|
| + for (MessagePort port : msgPorts) {
|
| + if (port.portId() == mPortId) {
|
| throw new IllegalStateException("Source port cannot be transferred");
|
| }
|
| - portIds[i] = sentId;
|
| }
|
| }
|
| - mMessagePortService.postMessage(mPortId, message, portIds);
|
| + mPostMessageSender.postMessage(null, message, null, null, msgPorts);
|
| + }
|
| +
|
| + @Override
|
| + public void postMessageToWeb(String frameName, String message,
|
| + String sourceOrigin, String targetOrigin, int[] sentPortIds) {
|
| + mMessagePortService.postMessage(mPortId, message, sentPortIds);
|
| }
|
| }
|
|
|