author | Eugene Ostroukhov <eugeneo@symbian.org> |
Wed, 28 Jul 2010 09:27:51 -0700 | |
changeset 455 | 5da55957c779 |
parent 276 | f2f4a1259de8 |
permissions | -rw-r--r-- |
2 | 1 |
// Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 |
// Use of this source code is governed by a BSD-style license that can be |
|
3 |
// found in the LICENSE file. |
|
4 |
||
5 |
package org.chromium.sdk.internal.transport; |
|
6 |
||
7 |
import java.io.IOException; |
|
8 |
import java.io.Writer; |
|
9 |
import java.util.concurrent.Callable; |
|
10 |
import java.util.concurrent.ExecutionException; |
|
11 |
import java.util.concurrent.Future; |
|
12 |
import java.util.concurrent.FutureTask; |
|
13 |
||
52
f577ea64429e
Migrated to unmodified Chromium Development Tools version
Eugene Ostroukhov <eugeneo@symbian.org>
parents:
2
diff
changeset
|
14 |
import org.chromium.sdk.LineReader; |
276
f2f4a1259de8
Bug 2065 - Pull updated Chrome Developer Tools into the workspace
Eugene Ostroukhov <eugeneo@symbian.org>
parents:
56
diff
changeset
|
15 |
import org.chromium.sdk.internal.JavascriptVmImpl; |
2 | 16 |
import org.chromium.sdk.internal.transport.Message.MalformedMessageException; |
17 |
||
18 |
/** |
|
19 |
* Handshaker handles "handshake" part of communication. It may write and read whatever it needs |
|
20 |
* before regular message-based communication has started. |
|
21 |
*/ |
|
22 |
public interface Handshaker { |
|
23 |
/** |
|
24 |
* Performs handshake. This method is blocking. After it has successfully finished, input/output |
|
25 |
* should be ready for normal message-based communication. In case method fails with IOException, |
|
26 |
* input and output are returned in undefined state. |
|
27 |
* @throws IOException if handshake process failed physically (input or output has unexpectedly |
|
28 |
* closed) or logically (if unexpected message came from remote). |
|
29 |
*/ |
|
52
f577ea64429e
Migrated to unmodified Chromium Development Tools version
Eugene Ostroukhov <eugeneo@symbian.org>
parents:
2
diff
changeset
|
30 |
void perform(LineReader input, Writer output) throws IOException; |
2 | 31 |
|
32 |
/** |
|
33 |
* Implementation of handshake from Google Chrome Developer Tools Protocol. Used when we |
|
34 |
* connect to browser. |
|
35 |
*/ |
|
36 |
Handshaker CHROMIUM = new Handshaker() { |
|
52
f577ea64429e
Migrated to unmodified Chromium Development Tools version
Eugene Ostroukhov <eugeneo@symbian.org>
parents:
2
diff
changeset
|
37 |
public void perform(LineReader input, Writer output) throws IOException { |
2 | 38 |
output.write(OUTGOING_MESSAGE); |
39 |
output.flush(); |
|
40 |
||
41 |
// TODO(prybin): expose this as a parameter or get rid of this option if we don't need it. |
|
42 |
final boolean ignoreUnexpectedResponses = false; |
|
43 |
||
44 |
while (true) { |
|
45 |
if (Thread.interrupted()) { |
|
46 |
throw new IOException("Interrupted"); |
|
47 |
} |
|
48 |
String line = input.readLine(); |
|
49 |
if (line == null) { |
|
50 |
throw new IOException("Connection closed"); |
|
51 |
} |
|
52 |
if (INCOMING_TEXT.equals(line)) { |
|
53 |
break; |
|
54 |
} |
|
55 |
if (!ignoreUnexpectedResponses) { |
|
56 |
throw new IOException("Unexpected handshake: " + line); |
|
57 |
} |
|
58 |
} |
|
59 |
} |
|
60 |
||
61 |
/** |
|
62 |
* A handshake string to be sent by a browser on the connection start, |
|
63 |
* specified by the protocol design doc (without trailing cr/lf). |
|
64 |
*/ |
|
65 |
private static final String INCOMING_TEXT = "ChromeDevToolsHandshake"; |
|
66 |
||
67 |
/** |
|
68 |
* A handshake string that we send to a browser on the connection start, |
|
69 |
* specified by the protocol design doc (including trailing cr/lf). |
|
70 |
*/ |
|
71 |
private static final String OUTGOING_MESSAGE = "ChromeDevToolsHandshake\r\n"; |
|
72 |
}; |
|
73 |
||
74 |
/** |
|
75 |
* Stateful handshaker implementation for Standalone V8 protocol. |
|
76 |
*/ |
|
77 |
class StandaloneV8 implements Handshaker { |
|
78 |
public interface RemoteInfo { |
|
79 |
String getProtocolVersion(); |
|
80 |
String getV8VmVersion(); |
|
81 |
String getEmbeddingHostName(); |
|
82 |
} |
|
83 |
||
84 |
public Future<RemoteInfo> getRemoteInfo() { |
|
85 |
return runnableFuture; |
|
86 |
} |
|
87 |
||
56
22f918ed49f7
Java5 is now supported
Eugene Ostroukhov <eostroukhov@gmail.com>
parents:
52
diff
changeset
|
88 |
private final FutureTask<RemoteInfo> runnableFuture = |
2 | 89 |
new FutureTask<RemoteInfo>(new HandshakeTaks()); |
90 |
||
52
f577ea64429e
Migrated to unmodified Chromium Development Tools version
Eugene Ostroukhov <eugeneo@symbian.org>
parents:
2
diff
changeset
|
91 |
private LineReader input = null; |
2 | 92 |
|
52
f577ea64429e
Migrated to unmodified Chromium Development Tools version
Eugene Ostroukhov <eugeneo@symbian.org>
parents:
2
diff
changeset
|
93 |
public void perform(LineReader input, Writer output) throws IOException { |
2 | 94 |
this.input = input; |
95 |
runnableFuture.run(); |
|
96 |
||
97 |
// Check for possible exceptions |
|
98 |
try { |
|
99 |
runnableFuture.get(); |
|
100 |
} catch (InterruptedException e) { |
|
101 |
throw new RuntimeException(e); |
|
102 |
} catch (ExecutionException e) { |
|
276
f2f4a1259de8
Bug 2065 - Pull updated Chrome Developer Tools into the workspace
Eugene Ostroukhov <eugeneo@symbian.org>
parents:
56
diff
changeset
|
103 |
throw JavascriptVmImpl.newIOException("Failed to perform handshake", e); |
2 | 104 |
} |
105 |
||
106 |
} |
|
107 |
||
108 |
class HandshakeTaks implements Callable<RemoteInfo> { |
|
109 |
public RemoteInfo call() throws IOException { |
|
110 |
final Message message; |
|
111 |
try { |
|
112 |
message = Message.fromBufferedReader(input); |
|
113 |
} catch (MalformedMessageException e) { |
|
276
f2f4a1259de8
Bug 2065 - Pull updated Chrome Developer Tools into the workspace
Eugene Ostroukhov <eugeneo@symbian.org>
parents:
56
diff
changeset
|
114 |
throw JavascriptVmImpl.newIOException("Unrecognized handshake message from remote", e); |
2 | 115 |
} |
116 |
if (message == null) { |
|
117 |
throw new IOException("End of stream"); |
|
118 |
} |
|
119 |
final String protocolVersion = message.getHeader("Protocol-Version", null); |
|
120 |
if (protocolVersion == null) { |
|
121 |
throw new IOException("Absent protocol version"); |
|
122 |
} |
|
123 |
final String vmVersion = message.getHeader("V8-Version", null); |
|
124 |
if (vmVersion == null) { |
|
125 |
throw new IOException("Absent V8 VM version"); |
|
126 |
} |
|
127 |
RemoteInfo remoteInfo = new RemoteInfo() { |
|
128 |
public String getProtocolVersion() { |
|
129 |
return protocolVersion; |
|
130 |
} |
|
131 |
public String getV8VmVersion() { |
|
132 |
return vmVersion; |
|
133 |
} |
|
134 |
public String getEmbeddingHostName() { |
|
135 |
return message.getHeader("Embedding-Host", null); |
|
136 |
} |
|
137 |
}; |
|
138 |
return remoteInfo; |
|
139 |
} |
|
140 |
} |
|
141 |
} |
|
142 |
} |