summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorphoglund <phoglund@chromium.org>2014-09-24 00:32:58 -0700
committerCommit bot <commit-bot@chromium.org>2014-09-24 07:33:14 +0000
commitcf0900dae461d90af8ed7604da098690d7c744c3 (patch)
tree49f818e6b5144cc417c5fc989118879e34786c37
parent15044609893faf9b2c2a533aa9a136f288ea20a1 (diff)
downloadchromium_src-cf0900dae461d90af8ed7604da098690d7c744c3.zip
chromium_src-cf0900dae461d90af8ed7604da098690d7c744c3.tar.gz
chromium_src-cf0900dae461d90af8ed7604da098690d7c744c3.tar.bz2
Revert of DevTools socket tunnel. (patchset #11 id:300001 of https://codereview.chromium.org/517233002/)
Reason for revert: Fails to compile on Android: https://build.chromium.org/p/chromium.linux/builders/Android%20Arm64%20Builder%20(dbg)/builds/2163 devtools_bridge/android/javatests/src/org/chromium/components/devtools_bridge/SocketTunnelServerTest.java:291: cannot find symbol symbol: method sleep() sleep(); ^ Original issue's description: > Implementation of DevTools socket tunneling service for remote debugging. > > Test APK in addition to instrumentation tests contains launching activity and foreground service what let duplicate ChromeShell debug socket to a differently named socket. If a device with running ChromeShell and DevToolsBridgeTest's service connect to a Desktop chrome (with USB debugging enabled) then chrome://inspect#devices will show 2 ChromeChell items. Both are debuggable (https://codereview.chromium.org/521573002/ should be applied to Desktop chrome to make the process less surprising). It's suitable for manual tests. > > This CL doesn't care of a few known issues: > 1. Data channel buffer overflow. Data channel automatically closed in this case. > 2. Uncontrolled number of pending sockets. DevTools throttles opening sockets and and keeps sockets that exceeds a threshold hanging. > 3. Uncontrolled number of threads (it's actually not a problem if #2 solved, thanks to DevTools throttling). > > To keep this CL reasonably simple this issues will be addressed later. > > TEST=org.chromium.components.devtools_bridge.SocketTunnelServerTest, see description fro manual testing. > BUG=383418 > > Committed: https://crrev.com/15044609893faf9b2c2a533aa9a136f288ea20a1 > Cr-Commit-Position: refs/heads/master@{#296360} TBR=mnaganov@chromium.org,tedchoc@chromium.org,erikwright@chromium.org,serya@chromium.org NOTREECHECKS=true NOTRY=true BUG=383418 Review URL: https://codereview.chromium.org/597063002 Cr-Commit-Position: refs/heads/master@{#296361}
-rw-r--r--build/all.gyp1
-rw-r--r--build/android/pylib/gtest/gtest_config.py1
-rw-r--r--chrome/android/shell/java/AndroidManifest.xml5
-rw-r--r--chrome/android/shell/java/src/org/chromium/chrome/shell/ChromeShellActivity.java3
-rw-r--r--components/OWNERS3
-rw-r--r--components/devtools_bridge.gyp42
-rw-r--r--components/devtools_bridge/OWNERS2
-rw-r--r--components/devtools_bridge/README2
-rw-r--r--components/devtools_bridge/android/java/src/org/chromium/components/devtools_bridge/AbstractDataChannel.java77
-rw-r--r--components/devtools_bridge/android/java/src/org/chromium/components/devtools_bridge/SocketTunnelBase.java396
-rw-r--r--components/devtools_bridge/android/java/src/org/chromium/components/devtools_bridge/SocketTunnelServer.java135
-rw-r--r--components/devtools_bridge/android/javatests/AndroidManifest.xml36
-rw-r--r--components/devtools_bridge/android/javatests/src/org/chromium/components/devtools_bridge/LocalTunnelBridgeTest.java111
-rw-r--r--components/devtools_bridge/android/javatests/src/org/chromium/components/devtools_bridge/SocketTunnelServerTest.java308
-rw-r--r--components/devtools_bridge/android/javatests/src/org/chromium/components/devtools_bridge/tests/DebugActivity.java71
-rw-r--r--components/devtools_bridge/android/javatests/src/org/chromium/components/devtools_bridge/tests/DebugService.java111
-rw-r--r--components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/DataChannelMock.java135
-rw-r--r--components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/DataPipe.java79
-rw-r--r--components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/LocalTunnelBridge.java190
-rw-r--r--components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/PacketDecoder.java67
-rw-r--r--components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/SignalingThreadMock.java162
-rw-r--r--components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/SocketTunnelClient.java303
-rw-r--r--components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/TestUtils.java134
23 files changed, 1 insertions, 2373 deletions
diff --git a/build/all.gyp b/build/all.gyp
index 4cafea2..7f6d6c4 100644
--- a/build/all.gyp
+++ b/build/all.gyp
@@ -800,7 +800,6 @@
'../chrome/chrome.gyp:chrome_shell_uiautomator_tests',
'../chrome/chrome.gyp:unit_tests_apk',
'../components/components_tests.gyp:components_unittests_apk',
- '../components/devtools_bridge.gyp:devtools_bridge_tests_apk',
'../content/content_shell_and_tests.gyp:content_browsertests_apk',
'../content/content_shell_and_tests.gyp:content_gl_tests_apk',
'../content/content_shell_and_tests.gyp:content_unittests_apk',
diff --git a/build/android/pylib/gtest/gtest_config.py b/build/android/pylib/gtest/gtest_config.py
index aeca27e..65d7fc0 100644
--- a/build/android/pylib/gtest/gtest_config.py
+++ b/build/android/pylib/gtest/gtest_config.py
@@ -8,7 +8,6 @@
EXPERIMENTAL_TEST_SUITES = [
'content_gl_tests',
'heap_profiler_unittests',
- 'devtools_bridge_tests',
]
# Do not modify this list without approval of an android owner.
diff --git a/chrome/android/shell/java/AndroidManifest.xml b/chrome/android/shell/java/AndroidManifest.xml
index 442b5b5..84ca1957 100644
--- a/chrome/android/shell/java/AndroidManifest.xml
+++ b/chrome/android/shell/java/AndroidManifest.xml
@@ -32,11 +32,6 @@
<uses-permission android:name="org.chromium.chrome.shell.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
- <permission android:name="org.chromium.chrome.shell.permission.DEBUG"
- android:label="Debug web pages in Chrome Shell"
- android:permissionGroup="android.permission-group.DEVELOPMENT_TOOLS"
- android:protectionLevel="signature" />
-
<application android:name="org.chromium.chrome.shell.ChromeShellApplication"
android:icon="@mipmap/app_icon"
android:label="Chrome Shell">
diff --git a/chrome/android/shell/java/src/org/chromium/chrome/shell/ChromeShellActivity.java b/chrome/android/shell/java/src/org/chromium/chrome/shell/ChromeShellActivity.java
index 62bbbad..5f34230 100644
--- a/chrome/android/shell/java/src/org/chromium/chrome/shell/ChromeShellActivity.java
+++ b/chrome/android/shell/java/src/org/chromium/chrome/shell/ChromeShellActivity.java
@@ -167,8 +167,7 @@ public class ChromeShellActivity extends Activity implements AppMenuPropertiesDe
mToolbar.setMenuHandler(mAppMenuHandler);
mDevToolsServer = new DevToolsServer("chrome_shell");
- mDevToolsServer.setRemoteDebuggingEnabled(
- true, DevToolsServer.Security.ALLOW_DEBUG_PERMISSION);
+ mDevToolsServer.setRemoteDebuggingEnabled(true);
mPrintingController = PrintingControllerFactory.create(this);
diff --git a/components/OWNERS b/components/OWNERS
index ee83a1f..afc7389 100644
--- a/components/OWNERS
+++ b/components/OWNERS
@@ -31,9 +31,6 @@ per-file data_reduction_proxy*=bengr@chromium.org
per-file data_reduction_proxy*=marq@chromium.org
per-file data_reduction_proxy*=bolian@chromium.org
-per-file devtools_bridge.gyp=mnaganov@chromium.org
-per-file devtools_bridge.gyp=serya@chromium.org
-
per-file dom_distiller*=bengr@chromium.org
per-file dom_distiller*=cjhopman@chromium.org
per-file dom_distiller*=nyquist@chromium.org
diff --git a/components/devtools_bridge.gyp b/components/devtools_bridge.gyp
deleted file mode 100644
index 9df9527..0000000
--- a/components/devtools_bridge.gyp
+++ /dev/null
@@ -1,42 +0,0 @@
-# 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.
-
-{
- 'targets': [
- {
- 'target_name': 'devtools_bridge_javalib',
- 'type': 'none',
- 'variables': {
- 'java_in_dir': 'devtools_bridge/android/java',
- },
- 'includes': [ '../build/java.gypi' ],
- },
- {
- 'target_name': 'devtools_bridge_testutils',
- 'type': 'none',
- 'variables': {
- 'java_in_dir': 'devtools_bridge/test/android/javatests',
- },
- 'includes': [ '../build/java.gypi' ],
- 'dependencies': [
- 'devtools_bridge_javalib',
- ],
- },
- {
- 'target_name': 'devtools_bridge_tests_apk',
- 'type': 'none',
- 'dependencies': [
- 'devtools_bridge_javalib',
- 'devtools_bridge_testutils',
- ],
- 'variables': {
- 'apk_name': 'DevToolsBridgeTest',
- 'test_suite_name': 'devtools_bridge_tests',
- 'java_in_dir': 'devtools_bridge/android/javatests',
- 'is_test_apk': 1,
- },
- 'includes': [ '../build/java_apk.gypi' ],
- },
- ],
-}
diff --git a/components/devtools_bridge/OWNERS b/components/devtools_bridge/OWNERS
deleted file mode 100644
index 1b209e2..0000000
--- a/components/devtools_bridge/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-mnaganov@chromium.org
-serya@chromium.org
diff --git a/components/devtools_bridge/README b/components/devtools_bridge/README
deleted file mode 100644
index 40077c9..0000000
--- a/components/devtools_bridge/README
+++ /dev/null
@@ -1,2 +0,0 @@
-The devtools_bridge component contains code for tunneling DevTools connection
-over P2P data channel for remote debugging android devices.
diff --git a/components/devtools_bridge/android/java/src/org/chromium/components/devtools_bridge/AbstractDataChannel.java b/components/devtools_bridge/android/java/src/org/chromium/components/devtools_bridge/AbstractDataChannel.java
deleted file mode 100644
index e92c6db..0000000
--- a/components/devtools_bridge/android/java/src/org/chromium/components/devtools_bridge/AbstractDataChannel.java
+++ /dev/null
@@ -1,77 +0,0 @@
-// 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 java.nio.ByteBuffer;
-
-/**
- * Limited view on org.webrtc.DataChannel. Abstraction layer helps with:
- * 1. Mocking in tests. There is no need to emulate full set of features of the DataChannel.
- * 2. Allows both native and Java API implementation for WebRTC data channel.
- * 3. Hides unused features.
- * Only SCTP data channels supported.
- * Data channel is thread safe (except the dispose method).
- */
-public abstract class AbstractDataChannel {
- /**
- * Observer's callbacks are called on WebRTC signaling thread (or it's equivalent in tests).
- */
- public interface Observer {
- void onStateChange(State state);
-
- /**
- * TEXT and BINARY messages should be handled equally. Size of the message is
- * |message|.remaining(). |message| may reference to a native buffer on stack so
- * the reference to the buffer must not outlive the invocation.
- */
- void onMessage(ByteBuffer message);
- }
-
- /**
- * Type is only significant for JavaScript-based counterpart. TEXT messages will
- * be observed as strings, BINARY as ByteArray's.
- */
- public enum MessageType {
- TEXT, BINARY
- }
-
- /**
- * State of the data channel.
- * Only 2 states of channel are important here: OPEN and everything else.
- */
- public enum State {
- OPEN, CLOSED
- }
-
- /**
- * Registers an observer.
- */
- public abstract void registerObserver(Observer observer);
-
- /**
- * Unregisters the previously registered observer.
- * Observer unregistration synchronized with signaling thread. If some data modified
- * in observer callbacks without additional synchronization it's safe to access
- * this data on the current thread after calling this method.
- */
- public abstract void unregisterObserver();
-
- /**
- * Sending message to the data channel.
- * Message size is |message|.remaining().
- */
- public abstract void send(ByteBuffer message, MessageType type);
-
- /**
- * Closing data channel. Both channels in the pair will change state to CLOSED.
- */
- public abstract void close();
-
- /**
- * Releases native objects (if any). Closes data channel. No other methods are allowed after it
- * (in multithread scenario needs synchronization with access to the data channel).
- */
- public abstract void dispose();
-}
diff --git a/components/devtools_bridge/android/java/src/org/chromium/components/devtools_bridge/SocketTunnelBase.java b/components/devtools_bridge/android/java/src/org/chromium/components/devtools_bridge/SocketTunnelBase.java
deleted file mode 100644
index 7c1439a5..0000000
--- a/components/devtools_bridge/android/java/src/org/chromium/components/devtools_bridge/SocketTunnelBase.java
+++ /dev/null
@@ -1,396 +0,0 @@
-// 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.net.LocalSocket;
-import android.net.LocalSocketAddress;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-/**
- * Base class for client and server that tunnels DevToolsServer's UNIX socket
- * over WebRTC data channel.
- *
- * Server runs on a android device with Chromium (or alike). Client runs where socket
- * needed to be accesses (it could be the same device if socket names are different; this
- * configuration useful for testing).
- *
- * Client listens LocalServerSocket and each time it receives connection it forwards
- * CLIENT_OPEN packet to the server with newly assigned connection id. On receiving this packet
- * server tries to connect to DevToolsServer socket. If succeeded it sends back SERVER_OPEN_ACK
- * with the same connection id. If failed it sends SERVER_CLOSE.
- *
- * When input stream on client shuts down it sends CLIENT_CLOSE. The same with SERVER_CLOSE
- * on the server side (only if SERVER_OPEN_ACK had sent). Between CLIENT_OPEN and CLIENT_CLOSE
- * any amount of data packets may be transferred (the same for SERVER_OPEN_ACK/SERVER_CLOSE
- * on the server side).
- *
- * Since all communication is reliable and ordered it's safe for client to assume that
- * if CLIENT_CLOSE has sent and SERVER_CLOSE has received with the same connection ID this
- * ID is safe to be reused.
- */
-public abstract class SocketTunnelBase {
- // Data channel is threadsafe but access to the reference needs synchromization.
- private final ReadWriteLock mDataChanneliReferenceLock = new ReentrantReadWriteLock();
- private volatile AbstractDataChannel mDataChannel;
-
- // Packet structure encapsulated in buildControlPacket, buildDataPacket and PacketDecoderBase.
- // Structure of control packet:
- // 1-st byte: CONTROL_CONNECTION_ID.
- // 2-d byte: op code.
- // 3-d byte: connection id.
- //
- // Structure of data packet:
- // 1-st byte: connection id.
- // 2..n: data.
-
- private static final int CONTROL_PACKET_SIZE = 3;
-
- // Client to server control packets.
- protected static final byte CLIENT_OPEN = (byte) 0;
- protected static final byte CLIENT_CLOSE = (byte) 1;
-
- // Server to client control packets.
- protected static final byte SERVER_OPEN_ACK = (byte) 0;
- protected static final byte SERVER_CLOSE = (byte) 1;
-
- // Must not exceed WebRTC limit. Exceeding it closes
- // data channel automatically. TODO(serya): WebRTC limit supposed to be removed.
- static final int READING_BUFFER_SIZE = 4 * 1024;
-
- private static final int CONTROL_CONNECTION_ID = 0;
-
- // DevTools supports up to ~10 connections at the time. A few extra IDs usefull for
- // delays in closing acknowledgement.
- protected static final int MIN_CONNECTION_ID = 1;
- protected static final int MAX_CONNECTION_ID = 64;
-
- // Signaling thread isn't accessible via API. Assumes that first caller
- // checkCalledOnSignalingThread is called on it indeed. It also works well for tests.
- private final AtomicReference<Thread> mSignalingThread = new AtomicReference<Thread>();
-
- // For writing in socket without blocking signaling thread.
- private final ExecutorService mWritingThread = Executors.newSingleThreadExecutor();
-
- public boolean isBound() {
- final Lock lock = mDataChanneliReferenceLock.readLock();
- lock.lock();
- try {
- return mDataChannel != null;
- } finally {
- lock.unlock();
- }
- }
-
- /**
- * Binds the tunnel to the data channel. Tunnel starts its activity when data channel
- * open.
- */
- public void bind(AbstractDataChannel dataChannel) {
- // Observer registrution must not be done in constructor.
- final Lock lock = mDataChanneliReferenceLock.writeLock();
- lock.lock();
- try {
- mDataChannel = dataChannel;
- } finally {
- lock.unlock();
- }
- dataChannel.registerObserver(new DataChannelObserver());
- }
-
- /**
- * Stops all tunnel activity and returns the prevously bound data channel.
- * It's safe to dispose the data channel after it.
- */
- public AbstractDataChannel unbind() {
- final Lock lock = mDataChanneliReferenceLock.writeLock();
- lock.lock();
- final AbstractDataChannel dataChannel;
- try {
- dataChannel = mDataChannel;
- mDataChannel = null;
- } finally {
- lock.unlock();
- }
- dataChannel.unregisterObserver();
- mSignalingThread.set(null);
- mWritingThread.shutdownNow();
- return dataChannel;
- }
-
- protected void checkCalledOnSignalingThread() {
- if (!mSignalingThread.compareAndSet(null, Thread.currentThread())) {
- if (mSignalingThread.get() != Thread.currentThread()) {
- throw new RuntimeException("Must be called on signaling thread");
- }
- }
- }
-
- protected static void checkConnectionId(int connectionId) throws ProtocolError {
- if (connectionId < MIN_CONNECTION_ID || connectionId > MAX_CONNECTION_ID) {
- throw new ProtocolError("Invalid connection id: " + Integer.toString(connectionId));
- }
- }
-
- protected void onProtocolError(ProtocolError e) {
- checkCalledOnSignalingThread();
-
- // When integrity of data channel is broken then best way to survive is to close it.
- final Lock lock = mDataChanneliReferenceLock.readLock();
- lock.lock();
- try {
- mDataChannel.close();
- } finally {
- lock.unlock();
- }
- }
-
- protected abstract void onReceivedDataPacket(int connectionId, byte[] data)
- throws ProtocolError;
- protected abstract void onReceivedControlPacket(int connectionId, byte opCode)
- throws ProtocolError;
- protected void onSocketException(IOException e, int connectionId) {}
- protected void onDataChannelOpened() {}
- protected void onDataChannelClosed() {}
-
- static ByteBuffer buildControlPacket(int connectionId, byte opCode) {
- ByteBuffer packet = ByteBuffer.allocateDirect(CONTROL_PACKET_SIZE);
- packet.put((byte) CONTROL_CONNECTION_ID);
- packet.put(opCode);
- packet.put((byte) connectionId);
- return packet;
- }
-
- static ByteBuffer buildDataPacket(int connectionId, byte[] buffer, int count) {
- ByteBuffer packet = ByteBuffer.allocateDirect(count + 1);
- packet.put((byte) connectionId);
- packet.put(buffer, 0, count);
- return packet;
- }
-
- protected void sendToDataChannel(ByteBuffer packet) {
- packet.limit(packet.position());
- packet.position(0);
- final Lock lock = mDataChanneliReferenceLock.readLock();
- lock.lock();
- try {
- if (mDataChannel != null) {
- mDataChannel.send(packet, AbstractDataChannel.MessageType.BINARY);
- }
- } finally {
- lock.unlock();
- }
- }
-
- /**
- * Packet decoding exposed for tests.
- */
- abstract static class PacketDecoderBase {
- protected void decodePacket(ByteBuffer packet) throws ProtocolError {
- if (packet.remaining() == 0) {
- throw new ProtocolError("Empty packet");
- }
-
- int connectionId = packet.get();
- if (connectionId != CONTROL_CONNECTION_ID) {
- checkConnectionId(connectionId);
- byte[] data = new byte[packet.remaining()];
- packet.get(data);
- onReceivedDataPacket(connectionId, data);
- } else {
- if (packet.remaining() != CONTROL_PACKET_SIZE - 1) {
- throw new ProtocolError("Invalid control packet size");
- }
-
- byte opCode = packet.get();
- connectionId = packet.get();
- checkConnectionId(connectionId);
- onReceivedControlPacket(connectionId, opCode);
- }
- }
-
- protected abstract void onReceivedDataPacket(int connectionId, byte[] data)
- throws ProtocolError;
- protected abstract void onReceivedControlPacket(int connectionId, byte opcode)
- throws ProtocolError;
- }
-
- private final class DataChannelObserver
- extends PacketDecoderBase implements AbstractDataChannel.Observer {
- @Override
- public void onStateChange(AbstractDataChannel.State state) {
- checkCalledOnSignalingThread();
-
- if (state == AbstractDataChannel.State.OPEN) {
- onDataChannelOpened();
- } else {
- onDataChannelClosed();
- }
- }
-
- @Override
- public void onMessage(ByteBuffer message) {
- checkCalledOnSignalingThread();
-
- try {
- decodePacket(message);
- } catch (ProtocolError e) {
- onProtocolError(e);
- }
- }
-
- @Override
- protected void onReceivedDataPacket(int connectionId, byte[] data) throws ProtocolError {
- checkCalledOnSignalingThread();
-
- SocketTunnelBase.this.onReceivedDataPacket(connectionId, data);
- }
-
- @Override
- protected void onReceivedControlPacket(int connectionId, byte opCode) throws ProtocolError {
- checkCalledOnSignalingThread();
-
- SocketTunnelBase.this.onReceivedControlPacket(connectionId, opCode);
- }
- }
-
- /**
- * Any problem happened while handling incoming message that breaks state integrity.
- */
- static class ProtocolError extends Exception {
- public ProtocolError(String description) {
- super(description);
- }
- }
-
- /**
- * Base utility class for client and server connections.
- */
- protected abstract class ConnectionBase {
- protected final int mId;
- protected final LocalSocket mSocket;
- private final AtomicInteger mOpenedStreams = new AtomicInteger(2); // input and output.
- private volatile boolean mConnected;
- private byte[] mBuffer;
-
- private ConnectionBase(int id, LocalSocket socket, boolean preconnected) {
- mId = id;
- mSocket = socket;
- mConnected = preconnected;
- }
-
- protected ConnectionBase(int id, LocalSocket socket) {
- this(id, socket, true);
- }
-
- protected ConnectionBase(int id) {
- this(id, new LocalSocket(), false);
- }
-
- protected boolean connect(LocalSocketAddress address) {
- assert !mConnected;
- try {
- mSocket.connect(address);
- mConnected = true;
- return true;
- } catch (IOException e) {
- onSocketException(e, mId);
- return false;
- }
- }
-
- protected void runReadingLoop() {
- mBuffer = new byte[READING_BUFFER_SIZE];
- try {
- boolean open;
- do {
- open = pump();
- } while (open);
- } catch (IOException e) {
- onSocketException(e, mId);
- } finally {
- mBuffer = null;
- }
- }
-
- private boolean pump() throws IOException {
- int count = mSocket.getInputStream().read(mBuffer);
- if (count <= 0)
- return false;
- sendToDataChannel(buildDataPacket(mId, mBuffer, count));
- return true;
- }
-
- protected void writeData(byte[] data) {
- // Called on writing thread.
- try {
- mSocket.getOutputStream().write(data);
- } catch (IOException e) {
- onSocketException(e, mId);
- }
- }
-
- public void onReceivedDataPacket(final byte[] data) {
- mWritingThread.execute(new Runnable() {
- @Override
- public void run() {
- writeData(data);
- }
- });
- }
-
- public void terminate() {
- close();
- }
-
- protected void shutdownOutput() {
- // Shutdown output on writing thread to make sure all pending writes finished.
- mWritingThread.execute(new Runnable() {
- @Override
- public void run() {
- shutdownOutputOnWritingThread();
- }
- });
- }
-
- private void shutdownOutputOnWritingThread() {
- try {
- if (mConnected) mSocket.shutdownOutput();
- } catch (IOException e) {
- onSocketException(e, mId);
- }
- releaseStream();
- }
-
- protected void shutdownInput() {
- try {
- if (mConnected) mSocket.shutdownInput();
- } catch (IOException e) {
- onSocketException(e, mId);
- }
- releaseStream();
- }
-
- private void releaseStream() {
- if (mOpenedStreams.decrementAndGet() == 0) close();
- }
-
- protected void close() {
- try {
- mSocket.close();
- } catch (IOException e) {
- onSocketException(e, mId);
- }
- }
- }
-}
diff --git a/components/devtools_bridge/android/java/src/org/chromium/components/devtools_bridge/SocketTunnelServer.java b/components/devtools_bridge/android/java/src/org/chromium/components/devtools_bridge/SocketTunnelServer.java
deleted file mode 100644
index 7ef0c95..0000000
--- a/components/devtools_bridge/android/java/src/org/chromium/components/devtools_bridge/SocketTunnelServer.java
+++ /dev/null
@@ -1,135 +0,0 @@
-// 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.net.LocalSocketAddress;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-/**
- * Tunnels DevTools UNIX socket over AbstractDataChannel.
- */
-public class SocketTunnelServer extends SocketTunnelBase {
- private final LocalSocketAddress mAddress;
-
- private final ExecutorService mReadingThreadPool = Executors.newCachedThreadPool();
-
- // Connections with opened client to server stream. If bound to data channel must be accessed
- // on signaling thread.
- private final Map<Integer, Connection> mClientConnections =
- new HashMap<Integer, Connection>();
-
- // Connections with opened server to client stream. Values are added
- // on signaling thread and removed on reading thread.
- private final ConcurrentMap<Integer, Connection> mServerConnections =
- new ConcurrentHashMap<Integer, Connection>();
-
- public SocketTunnelServer(String socketName) {
- mAddress = new LocalSocketAddress(socketName);
- }
-
- @Override
- public AbstractDataChannel unbind() {
- AbstractDataChannel dataChannel = super.unbind();
-
- mReadingThreadPool.shutdownNow();
-
- // Safe to access mClientConnections here once AbstractDataChannel.Observer detached.
- for (Connection connection : mClientConnections.values()) {
- connection.terminate();
- }
- mClientConnections.clear();
- return dataChannel;
- }
-
- public boolean hasConnections() {
- return mClientConnections.size() + mServerConnections.size() > 0;
- }
-
- @Override
- protected void onReceivedDataPacket(int connectionId, byte[] data) throws ProtocolError {
- checkCalledOnSignalingThread();
-
- if (!mClientConnections.containsKey(connectionId)) {
- throw new ProtocolError("Unknows conection id");
- }
-
- mClientConnections.get(connectionId).onReceivedDataPacket(data);
- }
-
- @Override
- protected void onReceivedControlPacket(int connectionId, byte opCode) throws ProtocolError {
- checkCalledOnSignalingThread();
-
- switch (opCode) {
- case CLIENT_OPEN:
- onClientOpen(connectionId);
- break;
-
- case CLIENT_CLOSE:
- onClientClose(connectionId);
- break;
-
- default:
- throw new ProtocolError("Invalid opCode");
- }
- }
-
- private void onClientOpen(int connectionId) throws ProtocolError {
- checkCalledOnSignalingThread();
-
- if (mClientConnections.containsKey(connectionId) ||
- mServerConnections.containsKey(connectionId)) {
- throw new ProtocolError("Conection id already used");
- }
-
- Connection connection = new Connection(connectionId);
- mClientConnections.put(connectionId, connection);
- mServerConnections.put(connectionId, connection);
-
- mReadingThreadPool.execute(connection);
- }
-
- private void onClientClose(int connectionId) throws ProtocolError {
- checkCalledOnSignalingThread();
-
- if (!mClientConnections.containsKey(connectionId)) {
- throw new ProtocolError("Unknows connection id");
- }
-
- Connection connection = mClientConnections.get(connectionId);
-
- connection.closedByClient();
- mClientConnections.remove(connectionId);
- }
-
- private final class Connection extends ConnectionBase implements Runnable {
- public Connection(int id) {
- super(id);
- }
-
- public void closedByClient() {
- shutdownOutput();
- }
-
- @Override
- public void run() {
- assert mServerConnections.containsKey(mId);
-
- if (connect(mAddress)) {
- sendToDataChannel(buildControlPacket(mId, SERVER_OPEN_ACK));
- runReadingLoop();
- }
- mServerConnections.remove(mId);
- shutdownInput();
- sendToDataChannel(buildControlPacket(mId, SERVER_CLOSE));
- }
- }
-}
diff --git a/components/devtools_bridge/android/javatests/AndroidManifest.xml b/components/devtools_bridge/android/javatests/AndroidManifest.xml
deleted file mode 100644
index 2478af1..0000000
--- a/components/devtools_bridge/android/javatests/AndroidManifest.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
- <!-- 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 name must be unique so suffix with "tests" so package loader
- doesn't ignore this. -->
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="org.chromium.components.devtools_bridge.tests">
- <application>
- <uses-library android:name="android.test.runner" />
- <service
- android:name=".DebugService" >
- </service>
- <activity
- android:name=".DebugActivity"
- android:label="DevToolsBridge tests" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
- <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="20" />
- <instrumentation android:name="android.test.InstrumentationTestRunner"
- android:targetPackage="org.chromium.components.devtools_bridge.tests"
- android:label="Tests for org.chromium.components.devtools_bridge"/>
-
- <uses-permission android:name="android.permission.RUN_INSTRUMENTATION" />
- <uses-permission android:name="android.permission.INJECT_EVENTS" />
-
- <!-- For manual testing with Chrome Shell -->
- <uses-permission android:name="org.chromium.chrome.shell.permission.DEBUG" />
-
- <!-- For manual testing with Clankium -->
- <uses-permission android:name="com.google.android.apps.chrome.permission.DEBUG" />
-</manifest>
diff --git a/components/devtools_bridge/android/javatests/src/org/chromium/components/devtools_bridge/LocalTunnelBridgeTest.java b/components/devtools_bridge/android/javatests/src/org/chromium/components/devtools_bridge/LocalTunnelBridgeTest.java
deleted file mode 100644
index 6810c28..0000000
--- a/components/devtools_bridge/android/javatests/src/org/chromium/components/devtools_bridge/LocalTunnelBridgeTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-// 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.net.LocalServerSocket;
-import android.net.LocalSocket;
-import android.test.InstrumentationTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.Assert;
-
-import java.io.IOException;
-import java.util.concurrent.Future;
-
-/**
- * Tests for {@link SocketTunnelBridge}
- */
-public class LocalTunnelBridgeTest extends InstrumentationTestCase {
- private static final String REQUEST = "Request";
- private static final String RESPONSE = "Response";
-
- private static final String SERVER_SOCKET_NAME =
- "org.chromium.components.devtools_bridge.LocalTunnelBridgeTest.SERVER_SOCKET";
- private static final String CLIENT_SOCKET_NAME =
- "org.chromium.components.devtools_bridge.LocalTunnelBridgeTest.CLIENT_SOCKET";
-
- private LocalTunnelBridge mBridge;
- private LocalServerSocket mServerSocket;
-
- @Override
- public void setUp() throws Exception {
- super.setUp();
- mServerSocket = new LocalServerSocket(SERVER_SOCKET_NAME);
- }
-
- private void startBridge() throws IOException {
- startBridge(SERVER_SOCKET_NAME);
- }
-
- private void startBridge(String serverSocketName) throws IOException {
- Assert.assertNull(mBridge);
- mBridge = new LocalTunnelBridge(serverSocketName, CLIENT_SOCKET_NAME);
- mBridge.start();
- }
-
- @Override
- public void tearDown() throws Exception {
- super.tearDown();
- if (mBridge != null) {
- mBridge.dispose();
- mBridge = null;
- }
- mServerSocket.close();
- }
-
- @SmallTest
- public void testStartStop() throws Exception {
- startBridge();
- mBridge.stop();
- }
-
- @SmallTest
- public void testRequestResponse() throws Exception {
- startBridge();
-
- Future<String> response = TestUtils.asyncRequest(CLIENT_SOCKET_NAME, REQUEST);
-
- LocalSocket socket = mServerSocket.accept();
- String request = TestUtils.readAll(socket);
- TestUtils.writeAndShutdown(socket, RESPONSE);
-
- Assert.assertEquals(REQUEST, request);
-
- Assert.assertEquals(RESPONSE, response.get());
- socket.close();
-
- mBridge.stop();
- }
-
- @SmallTest
- public void testRequestFailure1() throws Exception {
- startBridge();
-
- Future<String> response = TestUtils.asyncRequest(CLIENT_SOCKET_NAME, REQUEST);
- LocalSocket socket = mServerSocket.accept();
- int firstByte = socket.getInputStream().read();
-
- Assert.assertEquals((int) REQUEST.charAt(0), firstByte);
-
- socket.close();
-
- Assert.assertEquals("", response.get());
-
- mBridge.waitAllConnectionsClosed();
- mBridge.stop();
- }
-
- @SmallTest
- public void testRequestFailure2() throws Exception {
- startBridge("jdwp-control"); // Android system socket will reject connection.
-
- Future<String> response = TestUtils.asyncRequest(CLIENT_SOCKET_NAME, REQUEST);
-
- Assert.assertEquals("", response.get());
-
- mBridge.waitAllConnectionsClosed();
- mBridge.stop();
- }
-}
diff --git a/components/devtools_bridge/android/javatests/src/org/chromium/components/devtools_bridge/SocketTunnelServerTest.java b/components/devtools_bridge/android/javatests/src/org/chromium/components/devtools_bridge/SocketTunnelServerTest.java
deleted file mode 100644
index e6e58eb..0000000
--- a/components/devtools_bridge/android/javatests/src/org/chromium/components/devtools_bridge/SocketTunnelServerTest.java
+++ /dev/null
@@ -1,308 +0,0 @@
-// 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.net.LocalServerSocket;
-import android.net.LocalSocket;
-import android.test.InstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.Assert;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-
-/**
- * Tests for {@link SocketTunnelServer}
- */
-public class SocketTunnelServerTest extends InstrumentationTestCase {
- private static final int CONNECTION_ID = 30;
- private static final String SOCKET_NAME = "ksdjhflksjhdflk";
-
- private DataChannelMock mDataChannelMock;
- private SocketTunnelServer mServer;
- private LocalServerSocket mSocket;
-
- @Override
- public void setUp() throws Exception {
- super.setUp();
- mSocket = new LocalServerSocket(SOCKET_NAME);
- }
-
- @Override
- public void tearDown() throws Exception {
- mSocket.close();
- if (mServer != null) destroyServer();
- super.tearDown();
- }
-
- private void createServer() {
- createServer(new DataChannelMock());
- }
-
- private void createServer(DataChannelMock dataChannel) {
- mDataChannelMock = dataChannel;
- mServer = new SocketTunnelServer(SOCKET_NAME);
- mServer.bind(mDataChannelMock);
- }
-
- private void destroyServer() {
- mServer.unbind().dispose();
- mServer = null;
- }
-
- @SmallTest
- public void testOpenDataChannel() {
- createServer();
- mDataChannelMock.open();
- }
-
- @SmallTest
- public void testDecodeControlPacket() {
- createServer();
- ByteBuffer packet = buildControlPacket(CONNECTION_ID, SocketTunnelBase.SERVER_OPEN_ACK);
-
- PacketDecoder decoder = PacketDecoder.decode(packet);
- Assert.assertTrue(decoder.isControlPacket());
- Assert.assertEquals(CONNECTION_ID, decoder.connectionId());
- Assert.assertEquals(SocketTunnelBase.SERVER_OPEN_ACK, decoder.opCode());
- }
-
- @SmallTest
- public void testConnectToSocket() throws IOException {
- createServer();
- LocalSocket socket = connectToSocket(1);
- Assert.assertTrue(mServer.hasConnections());
- socket.close();
- }
-
- private LocalSocket connectToSocket(int connectionId) throws IOException {
- mDataChannelMock.notifyMessage(
- buildControlPacket(connectionId, SocketTunnelBase.CLIENT_OPEN));
- return mSocket.accept();
- }
-
- private void sendClose(int connectionId) {
- mDataChannelMock.notifyMessage(
- buildControlPacket(connectionId, SocketTunnelBase.CLIENT_CLOSE));
- }
-
- private ByteBuffer buildControlPacket(int connectionId, byte opCode) {
- ByteBuffer packet = SocketTunnelBase.buildControlPacket(connectionId, opCode);
- packet.limit(packet.position());
- packet.position(0);
- Assert.assertTrue(packet.remaining() > 0);
- return packet;
- }
-
- private ByteBuffer buildDataPacket(int connectionId, byte[] data) {
- ByteBuffer packet = SocketTunnelBase.buildDataPacket(connectionId, data, data.length);
- packet.limit(packet.position());
- packet.position(0);
- Assert.assertTrue(packet.remaining() > 0);
- return packet;
- }
-
- @SmallTest
- public void testReceiveOpenAcknowledgement() throws IOException, InterruptedException {
- createServer();
- LocalSocket socket = connectToSocket(CONNECTION_ID);
-
- receiveOpenAck(CONNECTION_ID);
-
- socket.close();
- }
-
- private PacketDecoder receiveControlPacket(int connectionId) throws InterruptedException {
- PacketDecoder decoder = PacketDecoder.decode(mDataChannelMock.receive());
- Assert.assertTrue(decoder.isControlPacket());
- Assert.assertEquals(connectionId, decoder.connectionId());
- return decoder;
- }
-
- private void receiveOpenAck(int connectionId) throws InterruptedException {
- PacketDecoder decoder = receiveControlPacket(connectionId);
- Assert.assertEquals(SocketTunnelBase.SERVER_OPEN_ACK, decoder.opCode());
- }
-
- private void receiveClose(int connectionId) throws InterruptedException {
- PacketDecoder decoder = receiveControlPacket(connectionId);
- Assert.assertEquals(SocketTunnelBase.SERVER_CLOSE, decoder.opCode());
- }
-
- @SmallTest
- public void testClosingSocket() throws IOException, InterruptedException {
- createServer();
- LocalSocket socket = connectToSocket(CONNECTION_ID);
- receiveOpenAck(CONNECTION_ID);
-
- socket.shutdownOutput();
-
- PacketDecoder decoder = PacketDecoder.decode(mDataChannelMock.receive());
-
- Assert.assertTrue(decoder.isControlPacket());
- Assert.assertEquals(SocketTunnelBase.SERVER_CLOSE, decoder.opCode());
- Assert.assertEquals(CONNECTION_ID, decoder.connectionId());
-
- socket.close();
- }
-
- @SmallTest
- public void testReadData() throws IOException, InterruptedException {
- createServer();
- LocalSocket socket = connectToSocket(CONNECTION_ID);
- receiveOpenAck(CONNECTION_ID);
-
- byte[] sample = "Sample".getBytes();
-
- socket.getOutputStream().write(sample);
- socket.getOutputStream().flush();
- socket.shutdownOutput();
-
- ByteBuffer result = receiveData(CONNECTION_ID, sample.length);
- Assert.assertEquals(ByteBuffer.wrap(sample), result);
- }
-
- private ByteBuffer receiveData(int connectionId, int length) throws InterruptedException {
- ByteBuffer result = ByteBuffer.allocate(length);
-
- while (true) {
- PacketDecoder decoder = PacketDecoder.decode(mDataChannelMock.receive());
- if (decoder.isDataPacket()) {
- Assert.assertEquals(connectionId, decoder.connectionId());
- result.put(decoder.data());
- } else if (decoder.isControlPacket()) {
- Assert.assertEquals(SocketTunnelBase.SERVER_CLOSE, decoder.opCode());
- Assert.assertEquals(connectionId, decoder.connectionId());
- break;
- }
- }
- result.limit(result.position());
- result.position(0);
- return result;
- }
-
- private int sum(int[] values) {
- int result = 0;
- for (int v : values)
- result += v;
- return result;
- }
-
- private static final int[] CHUNK_SIZES =
- new int[] { 0, 1, 5, 100, 1000, SocketTunnelBase.READING_BUFFER_SIZE * 2 };
-
- @SmallTest
- public void testReadLongDataChunk() throws IOException, InterruptedException {
- createServer();
- LocalSocket socket = connectToSocket(CONNECTION_ID);
- receiveOpenAck(CONNECTION_ID);
-
- byte[] buffer = new byte[CHUNK_SIZES[CHUNK_SIZES.length - 1]];
- ByteBuffer sentData = ByteBuffer.allocate(sum(CHUNK_SIZES));
- OutputStream stream = socket.getOutputStream();
- byte next = 0;
- int prevSize = 0;
- for (int size : CHUNK_SIZES) {
- while (prevSize < size)
- buffer[prevSize++] = next++;
-
- stream.write(buffer, 0, size);
- sentData.put(buffer, 0, size);
- }
-
- socket.shutdownOutput();
-
- sentData.limit(sentData.position());
- sentData.position(0);
- ByteBuffer readData = receiveData(CONNECTION_ID, sentData.limit());
-
- Assert.assertEquals(sentData, readData);
- }
-
- @SmallTest
- public void testReuseConnectionId() throws IOException, InterruptedException {
- createServer();
- LocalSocket socket = connectToSocket(CONNECTION_ID);
- receiveOpenAck(CONNECTION_ID);
-
- socket.shutdownOutput();
- socket.close();
- receiveClose(CONNECTION_ID);
- sendClose(CONNECTION_ID);
-
- // Open connection with the same ID
- socket = connectToSocket(CONNECTION_ID);
- receiveOpenAck(CONNECTION_ID);
- }
-
- private static final byte[] SAMPLE = "Sample".getBytes();
-
- @SmallTest
- public void testWriteData() throws IOException, InterruptedException {
- createServer();
- LocalSocket socket = connectToSocket(CONNECTION_ID);
- receiveOpenAck(CONNECTION_ID);
-
- mDataChannelMock.notifyMessage(buildDataPacket(CONNECTION_ID, SAMPLE));
-
- byte[] result = new byte[SAMPLE.length];
- int read = 0;
- while (read < SAMPLE.length) {
- int count = socket.getInputStream().read(result, 0, SAMPLE.length - read);
- Assert.assertTrue(count > 0);
- read += count;
- }
-
- Assert.assertEquals(ByteBuffer.wrap(SAMPLE), ByteBuffer.wrap(result));
-
- socket.close();
- }
-
- private enum TestStates {
- INITIAL, SENDING, CLOSING, MAY_FINISH_SENDING, SENT, DONE
- }
-
- @MediumTest
- public void testStopWhileSendingData() throws IOException {
-
- final TestUtils.StateBarrier<TestStates> barrier =
- new TestUtils.StateBarrier<TestStates>(TestStates.INITIAL);
-
- createServer(new DataChannelMock() {
- @Override
- public void send(ByteBuffer message, AbstractDataChannel.MessageType type) {
- barrier.advance(TestStates.INITIAL, TestStates.SENDING);
- barrier.advance(TestStates.MAY_FINISH_SENDING, TestStates.SENT);
- }
- });
-
- LocalSocket socket = connectToSocket(CONNECTION_ID);
- barrier.advance(TestStates.SENDING, TestStates.CLOSING);
- socket.close();
-
- new Thread() {
- @Override
- public void run() {
- sleep();
- barrier.advance(TestStates.CLOSING, TestStates.MAY_FINISH_SENDING);
- }
- }.start();
-
- destroyServer();
-
- barrier.advance(TestStates.SENT, TestStates.DONE);
- }
-
- private void sleep() {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
-}
diff --git a/components/devtools_bridge/android/javatests/src/org/chromium/components/devtools_bridge/tests/DebugActivity.java b/components/devtools_bridge/android/javatests/src/org/chromium/components/devtools_bridge/tests/DebugActivity.java
deleted file mode 100644
index 4e769ec..0000000
--- a/components/devtools_bridge/android/javatests/src/org/chromium/components/devtools_bridge/tests/DebugActivity.java
+++ /dev/null
@@ -1,71 +0,0 @@
-// 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.tests;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.View;
-import android.widget.Button;
-import android.widget.LinearLayout;
-import android.widget.LinearLayout.LayoutParams;
-import android.widget.TextView;
-
-/**
- * Activity for testing devtools bridge.
- */
-public class DebugActivity extends Activity {
- private LinearLayout mLayout;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- mLayout = new LinearLayout(this);
- mLayout.setOrientation(LinearLayout.VERTICAL);
-
- String intro = "To test LocalTunnelBridge manually: \n" +
- "1. Enable USB debugging.\n" +
- "2. Run ChromeShell along with this app.\n" +
- "3. Start the LocalTunnelBridge.\n" +
- "4. Connect the device to a desktop via USB.\n" +
- "5. Open chrome://inspect#devices on desktop Chrome.\n" +
- "6. Observe 2 identical Chrome Shells on the device.";
-
- TextView textView = new TextView(this);
- textView.setText(intro);
- mLayout.addView(textView);
-
- Button startButton = new Button(this);
- startButton.setText("Start LocalTunnelBridge");
- startButton.setOnClickListener(new SendActionOnClickListener(DebugService.START_ACTION));
- mLayout.addView(startButton);
-
- Button stopButton = new Button(this);
- stopButton.setText("Stop");
- stopButton.setOnClickListener(new SendActionOnClickListener(DebugService.STOP_ACTION));
- mLayout.addView(stopButton);
-
- LayoutParams layoutParam = new LayoutParams(LayoutParams.MATCH_PARENT,
- LayoutParams.MATCH_PARENT);
- setContentView(mLayout, layoutParam);
- }
-
- private class SendActionOnClickListener implements View.OnClickListener {
- private final String mAction;
-
- SendActionOnClickListener(String action) {
- mAction = action;
- }
-
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(DebugActivity.this, DebugService.class);
- intent.setAction(mAction);
- startService(intent);
- }
- }
-}
-
diff --git a/components/devtools_bridge/android/javatests/src/org/chromium/components/devtools_bridge/tests/DebugService.java b/components/devtools_bridge/android/javatests/src/org/chromium/components/devtools_bridge/tests/DebugService.java
deleted file mode 100644
index 8d23016..0000000
--- a/components/devtools_bridge/android/javatests/src/org/chromium/components/devtools_bridge/tests/DebugService.java
+++ /dev/null
@@ -1,111 +0,0 @@
-// 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.tests;
-
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.content.Intent;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.Process;
-import android.widget.Toast;
-
-import org.chromium.components.devtools_bridge.LocalTunnelBridge;
-
-import java.io.IOException;
-
-/**
- * Service for testing devtools bridge.
- */
-public class DebugService extends Service {
- private static final String PACKAGE = "org.chromium.components.devtools_bridge.tests";
- public static final String START_ACTION = PACKAGE + ".START_ACTION";
- public static final String STOP_ACTION = PACKAGE + ".STOP_ACTION";
- private static final int NOTIFICATION_ID = 1;
-
- private LocalTunnelBridge mBridge;
-
- private LocalTunnelBridge createBridge() throws IOException {
- String exposingSocketName = "webview_devtools_remote_" + Integer.valueOf(Process.myPid());
- return new LocalTunnelBridge("chrome_shell_devtools_remote", exposingSocketName);
- }
-
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- if (intent == null) return START_NOT_STICKY;
-
- String action = intent.getAction();
- if (START_ACTION.equals(action)) {
- return start();
- } else if (STOP_ACTION.equals(action)) {
- return stop();
- }
- return START_NOT_STICKY;
- }
-
- private int start() {
- if (mBridge != null)
- return START_NOT_STICKY;
-
- try {
- mBridge = createBridge();
- mBridge.start();
- } catch (Exception e) {
- Toast.makeText(this, "Failed to start", Toast.LENGTH_SHORT).show();
- mBridge.dispose();
- mBridge = null;
- return START_NOT_STICKY;
- }
-
- startForeground(NOTIFICATION_ID, makeForegroundServiceNotification());
- Toast.makeText(this, "Service started", Toast.LENGTH_SHORT).show();
- return START_STICKY;
- }
-
- private int stop() {
- if (mBridge == null)
- return START_NOT_STICKY;
-
- mBridge.stop();
- mBridge.dispose();
- mBridge = null;
- stopSelf();
- Toast.makeText(this, "Service stopped", Toast.LENGTH_SHORT).show();
- return START_NOT_STICKY;
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- return new Binder();
- }
-
- private Notification makeForegroundServiceNotification() {
- Intent showInfoIntent = new Intent(this, DebugActivity.class);
- showInfoIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
- PendingIntent showInfoPendingIntent =
- PendingIntent.getActivity(DebugService.this, 0, showInfoIntent, 0);
-
- Intent stopIntent = new Intent(this, DebugService.class);
- stopIntent.setAction(STOP_ACTION);
- PendingIntent stopPendingIntent =
- PendingIntent.getService(DebugService.this, 0, stopIntent, 0);
-
- return new Notification.Builder(this)
- // Mandatory fiends
- .setSmallIcon(android.R.drawable.alert_dark_frame)
- .setContentTitle("DevTools Bridge")
- .setContentText("DevTools socket local test tunnel works")
-
- // Optional
- .setContentIntent(showInfoPendingIntent)
- .addAction(android.R.drawable.ic_delete,
- "Stop", stopPendingIntent)
- .setOngoing(true)
- .setWhen(System.currentTimeMillis())
- .build();
- }
-}
-
diff --git a/components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/DataChannelMock.java b/components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/DataChannelMock.java
deleted file mode 100644
index 9821de1..0000000
--- a/components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/DataChannelMock.java
+++ /dev/null
@@ -1,135 +0,0 @@
-// 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 junit.framework.Assert;
-
-import java.nio.ByteBuffer;
-import java.util.concurrent.LinkedBlockingQueue;
-
-/**
- * Mock of AbstractDataChannel tests. Also base class for DataPipe channels.
- */
-public class DataChannelMock extends AbstractDataChannel {
- private final SignalingThreadMock mSignalingThread;
- private Observer mObserver;
- private boolean mOpen = false;
- private final LinkedBlockingQueue<ByteBuffer> mQueue = new LinkedBlockingQueue<ByteBuffer>();
-
- // |signalingThread| will be disposed in the |dispose| method. If successor needs
- // to control it's lifetime it must override |disposeSignalingThread| and not to invoke super's
- // implementation.
- protected DataChannelMock(SignalingThreadMock signalingThread) {
- mSignalingThread = signalingThread;
- }
-
- public DataChannelMock() {
- this(new SignalingThreadMock());
- }
-
- public void open() {
- onStateChange(AbstractDataChannel.State.OPEN);
- }
-
- @Override
- public void close() {
- onStateChange(AbstractDataChannel.State.CLOSED);
- }
-
- private void onStateChange(final State state) {
- mSignalingThread.invoke(new Runnable() {
- @Override
- public void run() {
- mObserver.onStateChange(state);
- }
- });
- }
-
- // Sends onMessage to the observer.
- public void notifyMessage(ByteBuffer data) {
- final byte[] bytes = toByteArray(data);
- mSignalingThread.invoke(new Runnable() {
- @Override
- public void run() {
- notifyMessageOnSignalingThread(ByteBuffer.wrap(bytes));
- }
- });
- }
-
- protected void notifyMessageOnSignalingThread(ByteBuffer buffer) {
- mObserver.onMessage(buffer);
- }
-
- // Blocks until message received. Removes it from the queue and returns.
- public ByteBuffer receive() {
- try {
- return mQueue.take();
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
-
- @Override
- public void registerObserver(final Observer observer) {
- mSignalingThread.invoke(new Runnable() {
- @Override
- public void run() {
- Assert.assertNull(mObserver);
- mObserver = observer;
- Assert.assertNotNull(mObserver);
- }
- });
- }
-
- @Override
- public void unregisterObserver() {
- mSignalingThread.invoke(new Runnable() {
- @Override
- public void run() {
- Assert.assertNotNull(mObserver);
- mObserver = null;
- }
- });
- }
-
- private byte[] toByteArray(ByteBuffer data) {
- final byte[] result = new byte[data.remaining()];
- data.get(result);
- return result;
- }
-
- @Override
- public void send(ByteBuffer message, MessageType type) {
- final byte[] data = toByteArray(message);
- assert data.length > 0;
- mSignalingThread.post(new Runnable() {
- @Override
- public void run() {
- sendOnSignalingThread(ByteBuffer.wrap(data));
- android.util.Log.d("DataChannelMock", "Packet sent.");
- }
- });
- }
-
- protected void sendOnSignalingThread(ByteBuffer message) {
- boolean success = mQueue.offer(message);
- assert success;
- }
-
- @Override
- public void dispose() {
- mSignalingThread.invoke(new Runnable() {
- @Override
- public void run() {
- Assert.assertNull(mObserver);
- }
- });
- disposeSignalingThread();
- }
-
- protected void disposeSignalingThread() {
- mSignalingThread.dispose();
- }
-}
diff --git a/components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/DataPipe.java b/components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/DataPipe.java
deleted file mode 100644
index c36319a..0000000
--- a/components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/DataPipe.java
+++ /dev/null
@@ -1,79 +0,0 @@
-// 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 java.nio.ByteBuffer;
-
-/**
- * Represents a pair of connected AbstractDataChannel's. Sends to one channel
- * come to another and vice versa.
- */
-public class DataPipe {
- private final SignalingThreadMock mSignalingThread = new SignalingThreadMock();
-
- private final PairedDataChannel mDC0 = new PairedDataChannel();
- private final PairedDataChannel mDC1 = new PairedDataChannel();
-
- public void connect() {
- mDC0.setPair(mDC1);
- mDC1.setPair(mDC0);
- mDC0.open();
- mDC1.open();
- }
-
- public void disconnect() {
- mDC0.setPair(null);
- mDC1.setPair(null);
- mDC0.close();
- mDC1.close();
- }
-
- public AbstractDataChannel dataChannel(int index) {
- switch (index) {
- case 0:
- return mDC0;
- case 1:
- return mDC1;
- default:
- throw new IllegalArgumentException("index");
- }
- }
-
- public void dispose() {
- mDC0.dispose();
- mDC1.dispose();
- mSignalingThread.dispose();
- }
-
- private class PairedDataChannel extends DataChannelMock {
- private PairedDataChannel mPair;
-
- public PairedDataChannel() {
- super(mSignalingThread);
- }
-
- public void setPair(final PairedDataChannel pair) {
- mSignalingThread.invoke(new Runnable() {
- @Override
- public void run() {
- mPair = pair;
- }
- });
- }
-
- @Override
- protected void sendOnSignalingThread(ByteBuffer message) {
- assert message.remaining() > 0;
-
- if (mPair == null) return;
- mPair.notifyMessageOnSignalingThread(message);
- }
-
- @Override
- protected void disposeSignalingThread() {
- // Ignore. Will dispose in DataPipe.dispose.
- }
- }
-}
diff --git a/components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/LocalTunnelBridge.java b/components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/LocalTunnelBridge.java
deleted file mode 100644
index c42909f..0000000
--- a/components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/LocalTunnelBridge.java
+++ /dev/null
@@ -1,190 +0,0 @@
-// 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.Log;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.concurrent.CountDownLatch;
-
-/**
- * It allows testing DevTools socket tunneling on a single device.
- *
- * SocketTunnelClient opens LocalServerSocket named |socketToExpose| and
- * tunnels all incoming connections to |socketToReplicate| using
- * SocketTunnelServer and DataPipe between them. All data passes through
- * WebRTC data channel but doens't leave the device.
- */
-public class LocalTunnelBridge {
- private static final String TAG = "LocalTunnelBridge";
-
- private final DataPipe mPipe;
- private final SocketTunnelServer mServer;
- private final SocketTunnelClient mClient;
- private boolean mLogPackets = false;
-
- private final CountDownLatch mServerDataChannelOpenedFlag = new CountDownLatch(1);
- private final CountDownLatch mServerDataChannelClosedFlag = new CountDownLatch(1);
-
- public LocalTunnelBridge(String socketToReplicate, String socketToExpose) throws IOException {
- mPipe = new DataPipe();
-
- mServer = new SocketTunnelServer(socketToReplicate) {
- @Override
- protected void onProtocolError(ProtocolError e) {
- throw new RuntimeException("Protocol error on server", e);
- }
-
- @Override
- protected void sendToDataChannel(ByteBuffer packet) {
- if (mLogPackets)
- Log.d(TAG, "Sending " + stringifyServerPacket(packet));
- super.sendToDataChannel(packet);
- }
-
- @Override
- protected void onReceivedDataPacket(int connectionId, byte[] data)
- throws ProtocolError {
- if (mLogPackets) {
- Log.d(TAG, "Received client data packet with " +
- Integer.toString(data.length) + " bytes");
- }
- super.onReceivedDataPacket(connectionId, data);
- }
-
- @Override
- protected void onReceivedControlPacket(int connectionId, byte opCode)
- throws ProtocolError {
- if (mLogPackets) {
- Log.d(TAG, "Received client control packet");
- }
- super.onReceivedControlPacket(connectionId, opCode);
- }
-
- @Override
- protected void onSocketException(IOException e, int connectionId) {
- Log.d(TAG, "Server socket exception on " + e +
- " (connection " + Integer.toString(connectionId) + ")");
- super.onSocketException(e, connectionId);
- }
-
- protected void onDataChannelOpened() {
- Log.d(TAG, "Server data channel opened");
- super.onDataChannelOpened();
- mServerDataChannelOpenedFlag.countDown();
- }
-
- protected void onDataChannelClosed() {
- Log.d(TAG, "Client data channel opened");
- super.onDataChannelClosed();
- mServerDataChannelClosedFlag.countDown();
- }
- };
-
- mServer.bind(mPipe.dataChannel(0));
-
- mClient = new SocketTunnelClient(socketToExpose) {
- @Override
- protected void onProtocolError(ProtocolError e) {
- throw new RuntimeException("Protocol error on client" + e);
- }
-
- @Override
- protected void onReceivedDataPacket(int connectionId, byte[] data)
- throws ProtocolError {
- if (mLogPackets) {
- Log.d(TAG, "Received server data packet with "
- + Integer.toString(data.length) + " bytes");
- }
- super.onReceivedDataPacket(connectionId, data);
- }
-
- @Override
- protected void onReceivedControlPacket(int connectionId, byte opCode)
- throws ProtocolError {
- if (mLogPackets) {
- Log.d(TAG, "Received server control packet");
- }
- super.onReceivedControlPacket(connectionId, opCode);
- }
-
- @Override
- protected void sendToDataChannel(ByteBuffer packet) {
- if (mLogPackets) {
- Log.d(TAG, "Sending " + stringifyClientPacket(packet));
- }
- super.sendToDataChannel(packet);
- }
- };
- mClient.bind(mPipe.dataChannel(1));
- }
-
- public void start() {
- mPipe.connect();
- }
-
- public void stop() {
- mPipe.disconnect();
- }
-
- public void dispose() {
- mClient.unbind();
- mServer.unbind();
- mPipe.dispose();
- }
-
- public void waitAllConnectionsClosed() throws InterruptedException {
- while (mServer.hasConnections() || mClient.hasConnections()) {
- Thread.sleep(50);
- }
- }
-
- private String stringifyDataPacket(String type, PacketDecoder decoder) {
- if (!decoder.isDataPacket()) {
- throw new RuntimeException("Invalid packet");
- }
- return type + "_DATA:" + Integer.toString(decoder.data().length);
- }
-
- private String stringifyClientPacket(ByteBuffer packet) {
- PacketDecoder decoder = decode(packet);
- if (!decoder.isControlPacket())
- return stringifyDataPacket("CLIENT", decoder);
- switch (decoder.opCode()) {
- case SocketTunnelBase.CLIENT_OPEN:
- return "CLIENT_OPEN " + Integer.valueOf(decoder.connectionId());
- case SocketTunnelBase.CLIENT_CLOSE:
- return "CLIENT_CLOSE " + Integer.valueOf(decoder.connectionId());
- default:
- throw new RuntimeException("Invalid packet");
- }
- }
-
- private String stringifyServerPacket(ByteBuffer packet) {
- PacketDecoder decoder = decode(packet);
- if (!decoder.isControlPacket())
- return stringifyDataPacket("SERVER", decoder);
- switch (decoder.opCode()) {
- case SocketTunnelBase.SERVER_OPEN_ACK:
- return "SERVER_OPEN_ACK " + Integer.valueOf(decoder.connectionId());
- case SocketTunnelBase.SERVER_CLOSE:
- return "SERVER_CLOSE " + Integer.valueOf(decoder.connectionId());
- default:
- throw new RuntimeException("Invalid packet");
- }
- }
-
- private PacketDecoder decode(ByteBuffer packet) {
- int position = packet.position();
- packet.position(0);
- if (position == 0) {
- throw new RuntimeException("Empty packet");
- }
- PacketDecoder decoder = PacketDecoder.decode(packet);
- packet.position(position);
- return decoder;
- }
-}
diff --git a/components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/PacketDecoder.java b/components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/PacketDecoder.java
deleted file mode 100644
index d8e0dff..0000000
--- a/components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/PacketDecoder.java
+++ /dev/null
@@ -1,67 +0,0 @@
-// 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 java.nio.ByteBuffer;
-
-/**
- * Decodes data packets of SocketTunnelClient and SocketTunnelServer for tests.
- */
-public final class PacketDecoder extends SocketTunnelBase.PacketDecoderBase {
- private boolean mControlPacket = false;
- private boolean mDataPacket;
- private int mOpCode;
- private int mConnectionId;
- private byte[] mData;
-
- protected void onReceivedDataPacket(int connectionId, byte[] data) {
- mDataPacket = true;
- mConnectionId = connectionId;
- mData = data;
- }
-
- @Override
- protected void onReceivedControlPacket(int connectionId, byte opCode) {
- mControlPacket = true;
- mOpCode = opCode;
- mConnectionId = connectionId;
- }
-
- public static PacketDecoder tryDecode(ByteBuffer packet) throws SocketTunnelBase.ProtocolError {
- PacketDecoder decoder = new PacketDecoder();
- decoder.decodePacket(packet);
- return decoder;
- }
-
- public static PacketDecoder decode(ByteBuffer packet) {
- try {
- return tryDecode(packet);
- } catch (SocketTunnelBase.ProtocolError e) {
- throw new RuntimeException(e);
- }
- }
-
- public boolean isControlPacket() {
- return mControlPacket;
- }
-
- public boolean isDataPacket() {
- return mDataPacket;
- }
-
- public int opCode() {
- assert isControlPacket();
- return mOpCode;
- }
-
- public int connectionId() {
- return mConnectionId;
- }
-
- public byte[] data() {
- assert isDataPacket();
- return mData.clone();
- }
-}
diff --git a/components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/SignalingThreadMock.java b/components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/SignalingThreadMock.java
deleted file mode 100644
index 16e0973..0000000
--- a/components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/SignalingThreadMock.java
+++ /dev/null
@@ -1,162 +0,0 @@
-// 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 java.util.concurrent.BlockingQueue;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.LinkedBlockingDeque;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * Convinience class for tests. Like WebRTC threads supports posts
- * and synchromous invokes.
- */
-class SignalingThreadMock {
- // TODO: use scaleTimeout when natives for org.chromium.base get available.
- private static final int EXECUTION_TIME_LIMIT_MS = 5000;
-
- private final AtomicInteger mInvokationCounter = new AtomicInteger(0);
- private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
- private final ScheduledExecutorService mWatchDogExecutor =
- Executors.newSingleThreadScheduledExecutor();
- private ScheduledFuture<?> mWatchDogFuture;
- private final Thread mThread;
- private final BlockingQueue<Runnable> mExecutionQueue = new LinkedBlockingDeque<Runnable>();
-
- public SignalingThreadMock() {
- mThread = new Thread() {
- @Override
- public void run() {
- try {
- runExecutionLoop();
- } catch (InterruptedException e) {
- // Normal finish.
- }
- }
- };
- mThread.start();
- }
-
- private void runExecutionLoop() throws InterruptedException {
- while (true) {
- mExecutionQueue.take().run();
- }
- }
-
- public void invoke(final Runnable runnable) {
- try {
- invoke(new TestUtils.RunnableAdapter(runnable));
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- public <T> T invoke(final Callable<T> callable) throws Exception {
- if (isOnThread()) return callable.call();
-
- try {
- return new InvokeWrapper<T>(callable).invoke();
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- } catch (ExecutionException e) {
- throw (Exception) e.getCause();
- }
- }
-
- public void post(Runnable runnable) {
- boolean success = mExecutionQueue.offer(new PostWrapper(runnable));
- assert success;
- }
-
- public void dispose() {
- mWatchDogExecutor.shutdown();
- mThread.interrupt();
- try {
- mThread.join();
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- }
-
- public boolean isOnThread() {
- return Thread.currentThread() == mThread;
- }
-
- private void onStartedExecution(final int index, final Exception timeoutException) {
- mWatchDogFuture = mWatchDogExecutor.schedule(new Runnable() {
- @Override
- public void run() {
- throw new RuntimeException(
- "Time limit on " + Integer.toString(index) + " invocation",
- timeoutException);
- }
- }, EXECUTION_TIME_LIMIT_MS, TimeUnit.MILLISECONDS);
- }
-
- private void onFinishedExecution() {
- mWatchDogFuture.cancel(false);
- }
-
- private abstract class WrapperBase implements Runnable {
- private final int mIndex;
- private final Exception mTimeoutException;
-
- protected WrapperBase() {
- mIndex = mInvokationCounter.incrementAndGet();
- mTimeoutException = new Exception("Timeout exception");
- }
-
- @Override
- public final void run() {
- onStartedExecution(mIndex, mTimeoutException);
- try {
- runWrapped();
- } finally {
- onFinishedExecution();
- }
- }
-
- protected abstract void runWrapped();
- }
-
- private class InvokeWrapper<T> extends WrapperBase {
- private final Callable<T> mWrapped;
- private final TestUtils.InvokeHelper<T> mHelper = new TestUtils.InvokeHelper<T>();
-
- public InvokeWrapper(Callable<T> wrapped) {
- mWrapped = wrapped;
- }
-
- @Override
- protected void runWrapped() {
- mHelper.runOnTargetThread(mWrapped);
- }
-
- public T invoke() throws Exception {
- boolean success = mExecutionQueue.offer(this);
- assert success;
- return mHelper.takeResult();
- }
- }
-
- private class PostWrapper extends WrapperBase {
- private final Runnable mWrapped;
-
- public PostWrapper(Runnable wrapped) {
- mWrapped = wrapped;
- }
-
- @Override
- protected void runWrapped() {
- mWrapped.run();
- }
- }
-}
diff --git a/components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/SocketTunnelClient.java b/components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/SocketTunnelClient.java
deleted file mode 100644
index 4a83386..0000000
--- a/components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/SocketTunnelClient.java
+++ /dev/null
@@ -1,303 +0,0 @@
-// 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.net.LocalServerSocket;
-import android.net.LocalSocket;
-import android.util.Log;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * Listens LocalServerSocket and tunnels all connections to the SocketTunnelServer.
- */
-public class SocketTunnelClient extends SocketTunnelBase {
- private static final String TAG = "SocketTunnelClient";
-
- private enum State {
- INITIAL, RUNNING, STOPPED
- }
-
- private final AtomicReference<State> mState = new AtomicReference<State>(State.INITIAL);
-
- private final LocalServerSocket mSocket;
- private final ExecutorService mThreadPool = Executors.newCachedThreadPool();
-
- // Connections with opened server to client stream. Always accesses on signaling thread.
- private final Map<Integer, Connection> mServerConnections =
- new HashMap<Integer, Connection>();
-
- // Accepted connections are kept here until server returns SERVER_OPEN_ACK or SERVER_CLOSE.
- // New connections are added in the listening loop, checked and removed on signaling thread.
- // So add/read/remove synchronized through message round trip.
- private final ConcurrentMap<Integer, Connection> mPendingConnections =
- new ConcurrentHashMap<Integer, Connection>();
-
- private final IdRegistry mIdRegistry = new IdRegistry(MIN_CONNECTION_ID, MAX_CONNECTION_ID, 2);
-
- /**
- * This class responsible for generating valid connection IDs. It count usage of connection:
- * one user for client to server stream and one for server to client one. When both are closed
- * it's safe to reuse ID.
- */
- private static final class IdRegistry {
- private final int[] mLocks;
- private final int mMin;
- private final int mMax;
- private final int mMaxLocks;
- private final Object mLock = new Object();
-
- public IdRegistry(int minId, int maxId, int maxLocks) {
- assert minId < maxId;
- assert maxLocks > 0;
-
- mMin = minId;
- mMax = maxId;
- mMaxLocks = maxLocks;
- mLocks = new int[maxId - minId + 1];
- }
-
- public void lock(int id) {
- synchronized (mLock) {
- int index = toIndex(id);
- if (mLocks[index] == 0 || mLocks[index] == mMaxLocks) {
- throw new RuntimeException();
- }
- mLocks[index]++;
- }
- }
-
- public void release(int id) {
- synchronized (mLock) {
- int index = toIndex(id);
- if (mLocks[index] == 0) {
- throw new RuntimeException("Releasing unlocked id " + Integer.toString(id));
- }
- mLocks[index]--;
- }
- }
-
- public boolean isLocked(int id) {
- synchronized (mLock) {
- return mLocks[toIndex(id)] > 0;
- }
- }
-
- public int generate() throws NoIdAvailableException {
- synchronized (mLock) {
- for (int id = mMin; id != mMax; id++) {
- int index = toIndex(id);
- if (mLocks[index] == 0) {
- mLocks[index] = 1;
- return id;
- }
- }
- }
- throw new NoIdAvailableException();
- }
-
- private int toIndex(int id) {
- if (id < mMin || id > mMax) {
- throw new RuntimeException();
- }
- return id - mMin;
- }
- }
-
- private static class NoIdAvailableException extends Exception {}
-
- public SocketTunnelClient(String socketName) throws IOException {
- mSocket = new LocalServerSocket(socketName);
- }
-
- public boolean hasConnections() {
- return mServerConnections.size() + mPendingConnections.size() > 0;
- }
-
- @Override
- public AbstractDataChannel unbind() {
- AbstractDataChannel dataChannel = super.unbind();
- close();
- return dataChannel;
- }
-
- public void close() {
- if (mState.get() != State.STOPPED) closeSocket();
- }
-
- @Override
- protected void onReceivedDataPacket(int connectionId, byte[] data) throws ProtocolError {
- checkCalledOnSignalingThread();
-
- if (!mServerConnections.containsKey(connectionId))
- throw new ProtocolError("Unknows connection id");
-
- mServerConnections.get(connectionId).onReceivedDataPacket(data);
- }
-
- @Override
- protected void onReceivedControlPacket(int connectionId, byte opCode) throws ProtocolError {
- switch (opCode) {
- case SERVER_OPEN_ACK:
- onServerOpenAck(connectionId);
- break;
-
- case SERVER_CLOSE:
- onServerClose(connectionId);
- break;
-
- default:
- throw new ProtocolError("Invalid opCode");
- }
- }
-
- private void onServerOpenAck(int connectionId) throws ProtocolError {
- checkCalledOnSignalingThread();
-
- if (mServerConnections.containsKey(connectionId)) {
- throw new ProtocolError("Connection already acknowledged");
- }
-
- if (!mPendingConnections.containsKey(connectionId)) {
- throw new ProtocolError("Unknow connection id");
- }
-
- // Check/get is safe since it can be only removed on this thread.
- Connection connection = mPendingConnections.get(connectionId);
- mPendingConnections.remove(connectionId);
-
- mServerConnections.put(connectionId, connection);
-
- // Lock for client to server stream.
- mIdRegistry.lock(connectionId);
- mThreadPool.execute(connection);
- }
-
- private void onServerClose(int connectionId) throws ProtocolError {
- checkCalledOnSignalingThread();
-
- if (mServerConnections.containsKey(connectionId)) {
- Connection connection = mServerConnections.get(connectionId);
- mServerConnections.remove(connectionId);
- mIdRegistry.release(connectionId); // Release sever to client stream.
- connection.closedByServer();
- } else if (mPendingConnections.containsKey(connectionId)) {
- Connection connection = mPendingConnections.get(connectionId);
- mPendingConnections.remove(connectionId);
- connection.closedByServer();
- sendToDataChannel(buildControlPacket(connectionId, CLIENT_CLOSE));
- mIdRegistry.release(connectionId); // Release sever to client stream.
- } else {
- throw new ProtocolError("Closing unknown connection");
- }
- }
-
- @Override
- protected void onDataChannelOpened() {
- if (!mState.compareAndSet(State.INITIAL, State.RUNNING)) {
- throw new InvalidStateException();
- }
-
- mThreadPool.execute(new Runnable() {
- @Override
- public void run() {
- runListenLoop();
- }
- });
- }
-
- @Override
- protected void onDataChannelClosed() {
- // All new connections will be rejected.
- if (!mState.compareAndSet(State.RUNNING, State.STOPPED)) {
- throw new InvalidStateException();
- }
-
- for (Connection connection : mServerConnections.values()) {
- connection.terminate();
- }
-
- for (Connection connection : mPendingConnections.values()) {
- connection.terminate();
- }
-
- closeSocket();
-
- mThreadPool.shutdown();
- }
-
- private void closeSocket() {
- try {
- mSocket.close();
- } catch (IOException e) {
- Log.d(TAG, "Failed to close socket: " + e);
- onSocketException(e, -1);
- }
- }
-
- private void runListenLoop() {
- try {
- while (true) {
- LocalSocket socket = mSocket.accept();
- State state = mState.get();
- if (mState.get() == State.RUNNING) {
- // Make sure no socket processed when stopped.
- clientOpenConnection(socket);
- } else {
- socket.close();
- }
- }
- } catch (IOException e) {
- if (mState.get() != State.RUNNING) {
- onSocketException(e, -1);
- }
- // Else exception expected (socket closed).
- }
- }
-
- private void clientOpenConnection(LocalSocket socket) throws IOException {
- try {
- int id = mIdRegistry.generate(); // id generated locked for server to client stream.
- Connection connection = new Connection(id, socket);
- mPendingConnections.put(id, connection);
- sendToDataChannel(buildControlPacket(id, CLIENT_OPEN));
- } catch (NoIdAvailableException e) {
- socket.close();
- }
- }
-
- private final class Connection extends ConnectionBase implements Runnable {
- public Connection(int id, LocalSocket socket) {
- super(id, socket);
- }
-
- public void closedByServer() {
- shutdownOutput();
- }
-
- @Override
- public void run() {
- assert mIdRegistry.isLocked(mId);
-
- runReadingLoop();
-
- shutdownInput();
- sendToDataChannel(buildControlPacket(mId, CLIENT_CLOSE));
- mIdRegistry.release(mId); // Unlock for client to server stream.
- }
- }
-
- /**
- * Method called in inappropriate state.
- */
- public static class InvalidStateException extends RuntimeException {}
-}
diff --git a/components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/TestUtils.java b/components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/TestUtils.java
deleted file mode 100644
index 81f7a44..0000000
--- a/components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/TestUtils.java
+++ /dev/null
@@ -1,134 +0,0 @@
-// 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.net.LocalSocket;
-import android.net.LocalSocketAddress;
-
-import java.io.IOException;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-
-/**
- * Utilities to testing a socket tunnel.
- */
-public class TestUtils {
- private static final String CHARSET = "UTF-8";
-
- // Sends |request| string to UNIX socket socketName on another thread and returns
- // Future<String> for obtainings response.
- public static Future<String> asyncRequest(final String socketName, final String request) {
-
- final ExecutorService executor = Executors.newSingleThreadExecutor();
-
- return executor.submit(new Callable<String>() {
- @Override
- public String call() throws Exception {
- LocalSocket socket = new LocalSocket();
- socket.connect(new LocalSocketAddress(socketName));
- writeAndShutdown(socket, request);
-
- String response = readAll(socket);
- socket.close();
-
- executor.shutdown();
- return response;
- }
- });
- }
-
- public static void writeAndShutdown(LocalSocket socket, String data) throws IOException {
- socket.getOutputStream().write(data.getBytes(CHARSET));
- socket.getOutputStream().flush();
- socket.shutdownOutput();
- }
-
- // Reads all bytes from socket input stream until EOF and converts it to UTF-8 string.
- public static String readAll(LocalSocket socket) throws IOException {
- byte[] buffer = new byte[1000];
- int position = 0;
- while (true) {
- int count = socket.getInputStream().read(buffer, position, buffer.length - position);
- if (count == -1)
- break;
- position += count;
- }
- return new String(buffer, 0, position, CHARSET);
- }
-
- /**
- * Utility class for thread synchronization. Allow to track moving through series of steps.
- */
- public static class StateBarrier<T> {
- private T mState;
- private final Object mLock = new Object();
-
- public StateBarrier(T initialState) {
- mState = initialState;
- }
-
- // Waits until state |from| reached and change state to |to|.
- public void advance(T from, T to) {
- synchronized (mLock) {
- while (mState.equals(from)) {
- try {
- mLock.wait();
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
- mState = to;
- mLock.notifyAll();
- }
- }
- }
-
- /**
- * Helper with runs code on another thread and synchronously take the result.
- */
- public static class InvokeHelper<T> {
- private final CountDownLatch mDone = new CountDownLatch(1);
-
- private T mResult = null;
- private Exception mException = null;
-
- public void runOnTargetThread(Callable<T> callable) {
- try {
- mResult = callable.call();
- } catch (Exception e) {
- mException = e;
- }
- mDone.countDown();
- }
-
- public T takeResult() throws Exception {
- mDone.await();
- if (mException != null)
- throw mException;
- else
- return mResult;
- }
- }
-
- /**
- * Adapts Runnable to Callable<Void>.
- */
- public static class RunnableAdapter implements Callable<Void> {
- private final Runnable mAdaptee;
-
- public RunnableAdapter(Runnable adaptee) {
- mAdaptee = adaptee;
- }
-
- @Override
- public Void call() {
- mAdaptee.run();
- return null;
- }
- }
-}