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

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

Issue 2375133002: Move MessagePort implementation from android_webview to content (Closed)
Patch Set: rsesek nits and git cl format Created 4 years, 2 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/AwMessagePort.java
diff --git a/android_webview/java/src/org/chromium/android_webview/AwMessagePort.java b/android_webview/java/src/org/chromium/android_webview/AwMessagePort.java
deleted file mode 100644
index 97e4d4951c2c0a7ff41abf09e657fc7a216a71c1..0000000000000000000000000000000000000000
--- a/android_webview/java/src/org/chromium/android_webview/AwMessagePort.java
+++ /dev/null
@@ -1,272 +0,0 @@
-// 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 android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-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 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.
- *
- * 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 transferred port cannot be closed by the application,
- * since the ownership is also transferred during the transfer. Closing a transferred port will
- * throw an exception.
- *
- * 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.
- *
- * 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])
- *
- * 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 AwMessagePort implements PostMessageSender.PostMessageSenderDelegate {
-
- /**
- * The message callback for receiving messages. Called on UI thread or if
- * provided, on the handler that is provided.
- */
- public abstract static class MessageCallback {
- public abstract void onMessage(String message, AwMessagePort[] sentPorts);
- }
-
- private static final String TAG = "MessagePort";
- private static final int PENDING = -1;
-
- // the what value for POST_MESSAGE
- private static final int POST_MESSAGE = 1;
-
- private static class PostMessageFromWeb {
- public AwMessagePort port;
- public String message;
- public AwMessagePort[] sentPorts;
-
- public PostMessageFromWeb(AwMessagePort port, String message, AwMessagePort[] sentPorts) {
- this.port = port;
- this.message = message;
- this.sentPorts = sentPorts;
- }
- }
-
- // Implements the handler to handle messageport messages received from web.
- // These messages are received on IO thread and normally handled in main
- // thread however, alternatively application can pass a handler to execute them.
- private static class MessageHandler extends Handler {
- public MessageHandler(Looper looper) {
- super(looper);
- }
- @Override
- public void handleMessage(Message msg) {
- if (msg.what == POST_MESSAGE) {
- PostMessageFromWeb m = (PostMessageFromWeb) msg.obj;
- m.port.onMessage(m.message, m.sentPorts);
- return;
- }
- throw new IllegalStateException("undefined message");
- }
- }
- // The default message handler
- private static final MessageHandler sDefaultHandler =
- new MessageHandler(Looper.getMainLooper());
-
- private int mPortId = PENDING;
- private MessageCallback mMessageCallback;
- private AwMessagePortService mMessagePortService;
- private boolean mClosed;
- private boolean mTransferred;
- private boolean mStarted;
- private boolean mReleasedMessages;
- private PostMessageSender mPostMessageSender;
- private MessageHandler mHandler;
- private final Object mLock = new Object();
-
- public AwMessagePort(AwMessagePortService messagePortService) {
- mMessagePortService = messagePortService;
- mPostMessageSender = new PostMessageSender(this, mMessagePortService);
- mMessagePortService.addObserver(mPostMessageSender);
- }
-
- public boolean isReady() {
- return mPortId != PENDING;
- }
-
- public int portId() {
- return mPortId;
- }
-
- public void setPortId(int id) {
- mPortId = id;
- releaseMessages();
- }
-
- public void close() {
- if (mTransferred) {
- throw new IllegalStateException("Port is already transferred");
- }
- synchronized (mLock) {
- if (mClosed) return;
- mClosed = true;
- }
- // If the port is already ready, and no messages are waiting in the
- // queue to be transferred, onPostMessageQueueEmpty() callback is not
- // received (it is received only after messages are purged). In this
- // case do the cleanup here.
- if (isReady() && mPostMessageSender.isMessageQueueEmpty()) {
- cleanup();
- }
- }
-
- public boolean isClosed() {
- return mClosed;
- }
-
- public boolean isTransferred() {
- return mTransferred;
- }
-
- public void setTransferred() {
- mTransferred = true;
- }
-
- public boolean isStarted() {
- return mStarted;
- }
-
- // Only called on UI thread
- public void setMessageCallback(MessageCallback messageCallback, Handler handler) {
- mStarted = true;
- synchronized (mLock) {
- mMessageCallback = messageCallback;
- if (handler != null) {
- mHandler = new MessageHandler(handler.getLooper());
- }
- }
- releaseMessages();
- }
-
- // Only called on IO thread.
- public void onReceivedMessage(String message, AwMessagePort[] sentPorts) {
- synchronized (mLock) {
- PostMessageFromWeb m = new PostMessageFromWeb(this, message, sentPorts);
- Handler handler = mHandler != null ? mHandler : sDefaultHandler;
- Message msg = handler.obtainMessage(POST_MESSAGE, m);
- handler.sendMessage(msg);
- }
- }
-
- private void releaseMessages() {
- if (mReleasedMessages || !isReady() || mMessageCallback == null) {
- return;
- }
- mReleasedMessages = true;
- mMessagePortService.releaseMessages(mPortId);
- }
-
- // This method may be called on a different thread than UI thread.
- public void onMessage(String message, AwMessagePort[] ports) {
- synchronized (mLock) {
- if (isClosed()) {
- Log.w(TAG, "Port [" + mPortId + "] received message in closed state");
- return;
- }
- if (mMessageCallback == null) {
- Log.w(TAG, "No handler set for port [" + mPortId + "], dropping message "
- + message);
- return;
- }
- mMessageCallback.onMessage(message, ports);
- }
- }
-
- public void postMessage(String message, AwMessagePort[] sentPorts)
- throws IllegalStateException {
- if (isClosed() || isTransferred()) {
- throw new IllegalStateException("Port is already closed or transferred");
- }
- if (sentPorts != null) {
- for (AwMessagePort port : sentPorts) {
- if (port.equals(this)) {
- throw new IllegalStateException("Source port cannot be transferred");
- }
- }
- }
- mStarted = true;
- mPostMessageSender.postMessage(null, message, null, sentPorts);
- }
-
- // Implements PostMessageSender.PostMessageSenderDelegate interface method.
- @Override
- public boolean isPostMessageSenderReady() {
- return isReady();
- }
-
- // Implements PostMessageSender.PostMessageSenderDelegate interface method.
- @Override
- public void onPostMessageQueueEmpty() {
- if (isClosed()) {
- cleanup();
- }
- }
-
- // Implements PostMessageSender.PostMessageSenderDelegate interface method.
- @Override
- public void postMessageToWeb(String frameName, String message, String targetOrigin,
- int[] sentPortIds) {
- mMessagePortService.postMessage(mPortId, message, sentPortIds);
- }
-
- private void cleanup() {
- mMessagePortService.removeObserver(mPostMessageSender);
- mPostMessageSender = null;
- mMessagePortService.closePort(mPortId);
- }
-}

Powered by Google App Engine
This is Rietveld 408576698