Index: components/devtools_bridge/android/java/src/org/chromium/components/devtools_bridge/SessionControlMessages.java |
diff --git a/components/devtools_bridge/android/java/src/org/chromium/components/devtools_bridge/SessionControlMessages.java b/components/devtools_bridge/android/java/src/org/chromium/components/devtools_bridge/SessionControlMessages.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..028af60a603faf17b1826dd389d0760de13e809a |
--- /dev/null |
+++ b/components/devtools_bridge/android/java/src/org/chromium/components/devtools_bridge/SessionControlMessages.java |
@@ -0,0 +1,250 @@ |
+// Copyright 2014 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.components.devtools_bridge; |
+ |
+import android.util.JsonReader; |
+import android.util.JsonWriter; |
+ |
+import java.io.ByteArrayInputStream; |
+import java.io.ByteArrayOutputStream; |
+import java.io.IOException; |
+import java.io.InputStreamReader; |
+import java.io.OutputStreamWriter; |
+ |
+/** |
+ * Defines protocol of control channel of SessionBase. Messages are JSON serializable |
+ * and transferred through AbstractDataChannel. |
+ */ |
+public final class SessionControlMessages { |
+ private SessionControlMessages() { |
+ throw new RuntimeException("Class not intended to instantiate"); |
+ } |
+ |
+ /** |
+ * Types of messages that client sends to server. |
+ */ |
+ enum ClientMessageType { |
+ UNKNOWN_REQUEST |
+ } |
+ |
+ /** |
+ * Types of messages that servers sends to client. |
+ */ |
+ enum ServerMessageType { |
+ ICE_EXCHANGE, |
+ UNKNOWN_RESPONSE |
+ } |
+ |
+ /** |
+ * Base class for all messages. |
+ */ |
+ public abstract static class Message<T extends Enum> { |
+ public final T type; |
+ |
+ protected Message(T type) { |
+ this.type = type; |
+ } |
+ |
+ public void write(JsonWriter writer) throws IOException { |
+ writer.name("type"); |
+ writer.value(type.toString()); |
+ } |
+ } |
+ |
+ /** |
+ * Base calss for messages that client sends to server. |
+ */ |
+ public abstract static class ClientMessage extends Message<ClientMessageType> { |
+ protected ClientMessage(ClientMessageType type) { |
+ super(type); |
+ } |
+ } |
+ |
+ /** |
+ * Base class for messages that server sends to client. |
+ */ |
+ public abstract static class ServerMessage extends Message<ServerMessageType> { |
+ protected ServerMessage(ServerMessageType type) { |
+ super(type); |
+ } |
+ } |
+ |
+ /** |
+ * Server sends this message when it has ICE candidates to exchange. Client initiates |
+ * ICE exchange over signaling channel. |
+ */ |
+ public static final class IceExchangeMessage extends ServerMessage { |
+ public IceExchangeMessage() { |
+ super(ServerMessageType.ICE_EXCHANGE); |
+ } |
+ } |
+ |
+ /** |
+ * Server response on unrecognized client message. |
+ */ |
+ public static final class UnknownResponseMessage extends ServerMessage { |
+ public final String rawRequestType; |
+ |
+ public UnknownResponseMessage(String rawRequestType) { |
+ super(ServerMessageType.UNKNOWN_RESPONSE); |
+ this.rawRequestType = rawRequestType; |
+ } |
+ |
+ public void write(JsonWriter writer) throws IOException { |
+ super.write(writer); |
+ writer.name("rawRequestType"); |
+ writer.value(rawRequestType.toString()); |
+ } |
+ } |
+ |
+ /** |
+ * Helper class to represent message of unknown type. Should not be sent. |
+ */ |
+ public static final class UnknownRequestMessage extends ClientMessage { |
+ public final String rawType; |
+ |
+ public UnknownRequestMessage(String rawType) { |
+ super(ClientMessageType.UNKNOWN_REQUEST); |
+ this.rawType = rawType; |
+ } |
+ |
+ @Override |
+ public void write(JsonWriter writer) throws IOException { |
+ throw new RuntimeException("Should not be serialized"); |
+ } |
+ |
+ public UnknownResponseMessage createResponse() { |
+ return new UnknownResponseMessage(rawType); |
+ } |
+ } |
+ |
+ private static <T extends Enum<T>> T getMessageType( |
+ Class<T> enumType, String rawType, T defaultType) throws IOException { |
+ try { |
+ return Enum.valueOf(enumType, rawType); |
+ } catch (IllegalArgumentException e) { |
+ if (defaultType != null) |
+ return defaultType; |
+ throw new IOException("Invalid message type " + rawType); |
+ } |
+ } |
+ |
+ public static void write(JsonWriter writer, Message<?> message) throws IOException { |
+ writer.beginObject(); |
+ message.write(writer); |
+ writer.endObject(); |
+ } |
+ |
+ public static ClientMessage readClientMessage(JsonReader reader) throws IOException { |
+ String rawType = ""; |
+ boolean success = false; |
+ |
+ reader.beginObject(); |
+ while (reader.hasNext()) { |
+ String name = reader.nextName(); |
+ if ("type".equals(name)) { |
+ rawType = reader.nextString(); |
+ } |
+ } |
+ reader.endObject(); |
+ |
+ switch (getMessageType(ClientMessageType.class, |
+ rawType, |
+ ClientMessageType.UNKNOWN_REQUEST)) { |
+ case UNKNOWN_REQUEST: |
+ return new UnknownRequestMessage(rawType); |
+ } |
+ throw new IOException("Invalid message"); |
+ } |
+ |
+ public static ServerMessage readServerMessage(JsonReader reader) throws IOException { |
+ String rawType = ""; |
+ String rawRequestType = null; |
+ |
+ reader.beginObject(); |
+ while (reader.hasNext()) { |
+ String name = reader.nextName(); |
+ if ("type".equals(name)) { |
+ rawType = reader.nextString(); |
+ } else if ("rawRequestType".equals(name)) { |
+ rawRequestType = reader.nextString(); |
+ } |
+ } |
+ reader.endObject(); |
+ |
+ switch (getMessageType(ServerMessageType.class, rawType, null)) { |
+ case ICE_EXCHANGE: |
+ return new IceExchangeMessage(); |
+ case UNKNOWN_RESPONSE: |
+ return new UnknownResponseMessage(rawRequestType); |
+ } |
+ throw new IOException("Invalid message"); |
+ } |
+ |
+ /** |
+ * Base class for client and server message handlers. |
+ */ |
+ public abstract static class MessageHandler { |
+ protected abstract void readMessage(JsonReader reader) throws IOException; |
+ |
+ public boolean readMessage(byte[] bytes) throws InvalidFormatException { |
+ try { |
+ readMessage(new JsonReader(new InputStreamReader(new ByteArrayInputStream(bytes)))); |
+ return true; |
+ } catch (IOException e) { |
+ throw new InvalidFormatException(e); |
+ } |
+ } |
+ } |
+ |
+ /** |
+ * Exception when parsing or handling message. |
+ */ |
+ public static class InvalidFormatException extends IOException { |
+ public InvalidFormatException(IOException e) { |
+ super(e); |
+ } |
+ |
+ public InvalidFormatException(String message) { |
+ super(message); |
+ } |
+ } |
+ |
+ /** |
+ * Base class for handler of server messages (to be created on client). |
+ */ |
+ public abstract static class ServerMessageHandler extends MessageHandler { |
+ @Override |
+ protected void readMessage(JsonReader reader) throws IOException { |
+ onMessage(readServerMessage(reader)); |
+ } |
+ |
+ protected abstract void onMessage(ServerMessage message); |
+ } |
+ |
+ /** |
+ * Base class for handler of client messages (to be created on server). |
+ */ |
+ public abstract static class ClientMessageHandler extends MessageHandler { |
+ @Override |
+ public void readMessage(JsonReader reader) throws IOException { |
+ onMessage(readClientMessage(reader)); |
+ } |
+ |
+ protected abstract void onMessage(ClientMessage message); |
+ } |
+ |
+ public static byte[] toByteArray(Message<?> message) { |
+ ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); |
+ JsonWriter writer = new JsonWriter(new OutputStreamWriter(byteStream)); |
+ try { |
+ write(writer, message); |
+ writer.close(); |
+ return byteStream.toByteArray(); |
+ } catch (IOException e) { |
+ throw new RuntimeException(e); |
+ } |
+ } |
+} |