15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Copyright 2014 The Chromium Authors. All rights reserved.
25c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Use of this source code is governed by a BSD-style license that can be
35c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// found in the LICENSE file.
45c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/memory/weak_ptr.h"
65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/strings/string_number_conversions.h"
75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/strings/string_util.h"
85c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/strings/stringprintf.h"
95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/threading/non_thread_safe.h"
105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/public/browser/browser_thread.h"
115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/public/test/browser_test.h"
125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/public/test/test_utils.h"
135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "net/base/io_buffer.h"
145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "net/base/ip_endpoint.h"
155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "net/base/net_errors.h"
165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "net/socket/stream_socket.h"
175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "net/socket/tcp_server_socket.h"
185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing content::BrowserThread;
205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace {
225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kHostTransportPrefix[] = "host:transport:";
245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kLocalAbstractPrefix[] = "localabstract:";
255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kOpenedUnixSocketsCommand[] = "shell:cat /proc/net/unix";
275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kDeviceModelCommand[] = "shell:getprop ro.product.model";
285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kDumpsysCommand[] = "shell:dumpsys window policy";
295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kListProcessesCommand[] = "shell:ps";
305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kSerialOnline[] = "01498B321301A00A";
325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kSerialOffline[] = "01498B2B0D01300E";
335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kDeviceModel[] = "Nexus 6";
345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kJsonVersionPath[] = "/json/version";
365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kJsonPath[] = "/json";
375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kJsonListPath[] = "/json/list";
385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kHttpRequestTerminator[] = "\r\n\r\n";
405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kHttpResponse[] =
425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "HTTP/1.1 200 OK\r\n"
435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "Content-Length:%d\r\n"
445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "Content-Type:application/json; charset=UTF-8\r\n\r\n%s";
455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kSampleOpenedUnixSockets[] =
475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "Num       RefCount Protocol Flags    Type St Inode Path\n"
485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "00000000: 00000004 00000000"
495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    " 00000000 0002 01  3328 /dev/socket/wpa_wlan0\n"
505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "00000000: 00000002 00000000"
515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    " 00010000 0001 01  5394 /dev/socket/vold\n"
525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "00000000: 00000002 00000000"
535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    " 00010000 0001 01 11810 @webview_devtools_remote_2425\n"
545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "00000000: 00000002 00000000"
555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    " 00010000 0001 01 20893 @chrome_devtools_remote\n"
565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "00000000: 00000002 00000000"
575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    " 00010000 0001 01 20894 @chrome_devtools_remote_1002\n"
585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "00000000: 00000002 00000000"
595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    " 00010000 0001 01 20895 @noprocess_devtools_remote\n";
605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kSampleListProcesses[] =
625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "USER   PID  PPID VSIZE  RSS    WCHAN    PC         NAME\n"
635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "root   1    0    688    508    ffffffff 00000000 S /init\r\n"
645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "u0_a75 2425 123  933736 193024 ffffffff 00000000 S com.sample.feed\r\n"
655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "nfc    741  123  706448 26316  ffffffff 00000000 S com.android.nfc\r\n"
665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "u0_a76 1001 124  111111 222222 ffffffff 00000000 S com.android.chrome\r\n"
675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "u0_a77 1002 125  111111 222222 ffffffff 00000000 S com.chrome.beta\r\n"
685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "u0_a78 1003 126  111111 222222 ffffffff 00000000 S com.noprocess.app\r\n";
695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst char kSampleDumpsys[] =
715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "WINDOW MANAGER POLICY STATE (dumpsys window policy)\r\n"
725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "    mSafeMode=false mSystemReady=true mSystemBooted=true\r\n"
735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "    mStable=(0,50)-(720,1184)\r\n" // Only mStable parameter is parsed
745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "    mForceStatusBar=false mForceStatusBarFromKeyguard=false\r\n";
755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuchar kSampleChromeVersion[] = "{\n"
775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"Browser\": \"Chrome/32.0.1679.0\",\n"
785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"Protocol-Version\": \"1.0\",\n"
795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"User-Agent\": \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 "
805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "(KHTML, like Gecko) Chrome/32.0.1679.0 Safari/537.36\",\n"
815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"WebKit-Version\": \"537.36 (@160162)\"\n"
825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "}";
835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuchar kSampleChromeBetaVersion[] = "{\n"
855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"Browser\": \"Chrome/31.0.1599.0\",\n"
865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"Protocol-Version\": \"1.0\",\n"
875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"User-Agent\": \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 "
885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "(KHTML, like Gecko) Chrome/32.0.1679.0 Safari/537.36\",\n"
895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"WebKit-Version\": \"537.36 (@160162)\"\n"
905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "}";
915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuchar kSampleWebViewVersion[] = "{\n"
935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"Browser\": \"Version/4.0\",\n"
945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"Protocol-Version\": \"1.0\",\n"
955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"User-Agent\": \"Mozilla/5.0 (Linux; Android 4.3; Build/KRS74B) "
965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Safari/537.36\",\n"
975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"WebKit-Version\": \"537.36 (@157588)\"\n"
985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "}";
995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuchar kSampleChromePages[] = "[ {\n"
1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"description\": \"\",\n"
1025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"devtoolsFrontendUrl\": \"/devtools/devtools.html?"
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "ws=/devtools/page/0\",\n"
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "   \"id\": \"0\",\n"
1055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"title\": \"The Chromium Projects\",\n"
1065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"type\": \"page\",\n"
1075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"url\": \"http://www.chromium.org/\",\n"
1085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"webSocketDebuggerUrl\": \""
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "ws:///devtools/page/0\"\n"
1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "} ]";
1115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccichar kSampleChromeBetaPages[] = "[ {\n"
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "   \"description\": \"\",\n"
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "   \"devtoolsFrontendUrl\": \"/devtools/devtools.html?"
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "ws=/devtools/page/0\",\n"
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "   \"id\": \"0\",\n"
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "   \"title\": \"The Chromium Projects\",\n"
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "   \"type\": \"page\",\n"
1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "   \"url\": \"http://www.chromium.org/\",\n"
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "   \"webSocketDebuggerUrl\": \""
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "ws:///devtools/page/0\"\n"
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    "} ]";
1235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuchar kSampleWebViewPages[] = "[ {\n"
1255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"description\": \"{\\\"attached\\\":false,\\\"empty\\\":false,"
1265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "\\\"height\\\":1173,\\\"screenX\\\":0,\\\"screenY\\\":0,"
1275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "\\\"visible\\\":true,\\\"width\\\":800}\",\n"
1285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"devtoolsFrontendUrl\": \"http://chrome-devtools-frontend.appspot.com/"
1295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "serve_rev/@157588/devtools.html?ws="
1305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "/devtools/page/3E962D4D-B676-182D-3BE8-FAE7CE224DE7\",\n"
1315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"faviconUrl\": \"http://chromium.org/favicon.ico\",\n"
1325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"id\": \"3E962D4D-B676-182D-3BE8-FAE7CE224DE7\",\n"
1335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"thumbnailUrl\": \"/thumb/3E962D4D-B676-182D-3BE8-FAE7CE224DE7\",\n"
1345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"title\": \"Blink - The Chromium Projects\",\n"
1355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"type\": \"page\",\n"
1365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"url\": \"http://www.chromium.org/blink\",\n"
1375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"webSocketDebuggerUrl\": \"ws:///devtools/"
1385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "page/3E962D4D-B676-182D-3BE8-FAE7CE224DE7\"\n"
1395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "}, {\n"
1405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"description\": \"{\\\"attached\\\":true,\\\"empty\\\":true,"
1415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "\\\"screenX\\\":0,\\\"screenY\\\":33,\\\"visible\\\":false}\",\n"
1425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"devtoolsFrontendUrl\": \"http://chrome-devtools-frontend.appspot.com/"
1435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "serve_rev/@157588/devtools.html?ws="
1445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "/devtools/page/44681551-ADFD-2411-076B-3AB14C1C60E2\",\n"
1455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"faviconUrl\": \"\",\n"
1465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"id\": \"44681551-ADFD-2411-076B-3AB14C1C60E2\",\n"
1475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"thumbnailUrl\": \"/thumb/44681551-ADFD-2411-076B-3AB14C1C60E2\",\n"
1485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"title\": \"More Activity\",\n"
1495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"type\": \"page\",\n"
1505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"url\": \"about:blank\",\n"
1515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "   \"webSocketDebuggerUrl\": \"ws:///devtools/page/"
1525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "44681551-ADFD-2411-076B-3AB14C1C60E2\"\n"
1535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    "}]";
1545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustatic const int kBufferSize = 16*1024;
1565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustatic const int kAdbPort = 5037;
1575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustatic const int kAdbMessageHeaderSize = 4;
1595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
16046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class SimpleHttpServer : base::NonThreadSafe {
1615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public:
1625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  class Parser {
1635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu   public:
1645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    virtual int Consume(const char* data, int size) = 0;
1655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    virtual ~Parser() {}
1665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  };
1675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  typedef base::Callback<void(const std::string&)> SendCallback;
16946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  typedef base::Callback<Parser*(const SendCallback&)> ParserFactory;
1705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
17146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  SimpleHttpServer(const ParserFactory& factory, net::IPEndPoint endpoint);
17246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual ~SimpleHttpServer();
1735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private:
17546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  class Connection : base::NonThreadSafe {
17646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)   public:
17746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    Connection(net::StreamSocket* socket, const ParserFactory& factory);
17846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    virtual ~Connection();
17946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
18046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)   private:
18146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    void Send(const std::string& message);
18246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    void ReadData();
18346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    void OnDataRead(int count);
18446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    void WriteData();
18546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    void OnDataWritten(int count);
18646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
18746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_ptr<net::StreamSocket> socket_;
18846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_ptr<Parser> parser_;
18946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_refptr<net::GrowableIOBuffer> input_buffer_;
19046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_refptr<net::GrowableIOBuffer> output_buffer_;
19146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    int bytes_to_write_;
19246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    bool read_closed_;
19303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    base::WeakPtrFactory<Connection> weak_factory_;
19446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
19546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(Connection);
19646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  };
1975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void AcceptConnection();
1995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void OnAccepted(int result);
2005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
20146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ParserFactory factory_;
20246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<net::TCPServerSocket> socket_;
2035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<net::StreamSocket> client_socket_;
20403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  base::WeakPtrFactory<SimpleHttpServer> weak_factory_;
2055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
20646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SimpleHttpServer);
2075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
2085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
20946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)SimpleHttpServer::SimpleHttpServer(const ParserFactory& factory,
21046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                   net::IPEndPoint endpoint)
21146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : factory_(factory),
21203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      socket_(new net::TCPServerSocket(NULL, net::NetLog::Source())),
21303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      weak_factory_(this) {
21446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  socket_->Listen(endpoint, 5);
2155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  AcceptConnection();
2165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
2175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
21846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)SimpleHttpServer::~SimpleHttpServer() {
21946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
2205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
22146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)SimpleHttpServer::Connection::Connection(net::StreamSocket* socket,
22246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                         const ParserFactory& factory)
22346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : socket_(socket),
22446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      parser_(factory.Run(base::Bind(&Connection::Send,
22546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                     base::Unretained(this)))),
22646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      input_buffer_(new net::GrowableIOBuffer()),
22746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      output_buffer_(new net::GrowableIOBuffer()),
22846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      bytes_to_write_(0),
22903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      read_closed_(false),
23003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      weak_factory_(this) {
23146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  input_buffer_->SetCapacity(kBufferSize);
23246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ReadData();
2335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
2345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
23546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)SimpleHttpServer::Connection::~Connection() {
2365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
2375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
23846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void SimpleHttpServer::Connection::Send(const std::string& message) {
2395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK(CalledOnValidThread());
24046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const char* data = message.c_str();
24146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  int size = message.size();
2425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if ((output_buffer_->offset() + bytes_to_write_ + size) >
2445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      output_buffer_->capacity()) {
2455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // If not enough space without relocation
2465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (output_buffer_->capacity() < (bytes_to_write_ + size)) {
2475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // If even buffer is not enough
2485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      int new_size = std::max(output_buffer_->capacity() * 2, size * 2);
2495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      output_buffer_->SetCapacity(new_size);
2505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
2515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    memmove(output_buffer_->StartOfBuffer(),
2525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            output_buffer_->data(),
2535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            bytes_to_write_);
2545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    output_buffer_->set_offset(0);
2555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
2565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  memcpy(output_buffer_->data() + bytes_to_write_, data, size);
2585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bytes_to_write_ += size;
2595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (bytes_to_write_ == size)
2615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // If write loop wasn't yet started, then start it
2625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    WriteData();
2635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
2645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
26546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void SimpleHttpServer::Connection::ReadData() {
2665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK(CalledOnValidThread());
2675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (input_buffer_->RemainingCapacity() == 0)
2695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    input_buffer_->SetCapacity(input_buffer_->capacity() * 2);
2705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
27146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  int read_result = socket_->Read(
2725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      input_buffer_.get(),
2735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      input_buffer_->RemainingCapacity(),
27446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::Bind(&Connection::OnDataRead, base::Unretained(this)));
2755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (read_result != net::ERR_IO_PENDING)
2775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    OnDataRead(read_result);
2785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
2795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
28046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void SimpleHttpServer::Connection::OnDataRead(int count) {
2815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK(CalledOnValidThread());
2825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (count <= 0) {
28346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (bytes_to_write_ == 0)
28446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      delete this;
28546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    else
28646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      read_closed_ = true;
2875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return;
2885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
2895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  input_buffer_->set_offset(input_buffer_->offset() + count);
2905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  int bytes_processed;
2915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  do {
2935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    char* data = input_buffer_->StartOfBuffer();
2945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    int data_size = input_buffer_->offset();
2955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    bytes_processed = parser_->Consume(data, data_size);
2965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (bytes_processed) {
2985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      memmove(data, data + bytes_processed, data_size - bytes_processed);
2995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      input_buffer_->set_offset(data_size - bytes_processed);
3005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
3015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  } while (bytes_processed);
30246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Posting to avoid deep recursion in case of synchronous IO
3035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::MessageLoop::current()->PostTask(
3045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      FROM_HERE,
30503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      base::Bind(&Connection::ReadData, weak_factory_.GetWeakPtr()));
3065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
3075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
30846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void SimpleHttpServer::Connection::WriteData() {
3095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK(CalledOnValidThread());
3105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_GE(output_buffer_->capacity(),
3115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu           output_buffer_->offset() + bytes_to_write_) << "Overflow";
3125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
31346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  int write_result = socket_->Write(
3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      output_buffer_.get(),
3155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      bytes_to_write_,
31646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::Bind(&Connection::OnDataWritten, base::Unretained(this)));
31746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
3185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (write_result != net::ERR_IO_PENDING)
3195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    OnDataWritten(write_result);
3205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
3215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
32246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void SimpleHttpServer::Connection::OnDataWritten(int count) {
3235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK(CalledOnValidThread());
3245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (count < 0) {
32546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    delete this;
3265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return;
3275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
3285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_GT(count, 0);
3295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK_GE(output_buffer_->capacity(),
3305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu           output_buffer_->offset() + bytes_to_write_) << "Overflow";
3315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bytes_to_write_ -= count;
3335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  output_buffer_->set_offset(output_buffer_->offset() + count);
3345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (bytes_to_write_ != 0)
33646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Posting to avoid deep recursion in case of synchronous IO
3375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    base::MessageLoop::current()->PostTask(
3385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        FROM_HERE,
33903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        base::Bind(&Connection::WriteData, weak_factory_.GetWeakPtr()));
34046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  else if (read_closed_)
34146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    delete this;
3425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
3435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
34446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void SimpleHttpServer::AcceptConnection() {
34546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  CHECK(CalledOnValidThread());
34646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
34746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  int accept_result = socket_->Accept(&client_socket_,
34846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::Bind(&SimpleHttpServer::OnAccepted, base::Unretained(this)));
3495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
35046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (accept_result != net::ERR_IO_PENDING)
35146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    base::MessageLoop::current()->PostTask(
35246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        FROM_HERE,
35346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        base::Bind(&SimpleHttpServer::OnAccepted,
35403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                   weak_factory_.GetWeakPtr(),
35546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                   accept_result));
35646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
35746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
35846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void SimpleHttpServer::OnAccepted(int result) {
35946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  CHECK(CalledOnValidThread());
36046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ASSERT_EQ(result, 0);  // Fails if the socket is already in use.
36146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  new Connection(client_socket_.release(), factory_);
36246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  AcceptConnection();
36346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
36446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
36546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class AdbParser : SimpleHttpServer::Parser, base::NonThreadSafe {
3665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public:
36746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  static Parser* Create(const SimpleHttpServer::SendCallback& callback) {
36846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return new AdbParser(callback);
3695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
3705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
37146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  explicit AdbParser(const SimpleHttpServer::SendCallback& callback)
37246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      : callback_(callback) {
37346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
37446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
37546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual ~AdbParser() {
3765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
3775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private:
3795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual int Consume(const char* data, int size) OVERRIDE {
3805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CHECK(CalledOnValidThread());
3815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (!selected_socket_.empty()) {
3825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      std::string message(data, size);
3835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      size_t request_end_pos = message.find(kHttpRequestTerminator);
3845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (request_end_pos != std::string::npos) {
3855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        ProcessHTTPRequest(message.substr(0, request_end_pos));
3865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        return request_end_pos + strlen(kHttpRequestTerminator);
3875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      }
3885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return 0;
3895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
3905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (size >= kAdbMessageHeaderSize) {
3915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      std::string message_header(data, kAdbMessageHeaderSize);
3925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      int message_size;
3935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      EXPECT_TRUE(base::HexStringToInt(message_header, &message_size));
3955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (size >= message_size + kAdbMessageHeaderSize) {
39746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        std::string message_body(data + kAdbMessageHeaderSize, message_size);
3985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        ProcessCommand(message_body);
3995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        return kAdbMessageHeaderSize + message_size;
4005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      }
4015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
4025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return 0;
4035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
4045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void ProcessHTTPRequest(const std::string& request) {
4065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CHECK(CalledOnValidThread());
4075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    std::vector<std::string> tokens;
4085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    Tokenize(request, " ", &tokens);
4095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CHECK_EQ(3U, tokens.size());
4105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CHECK_EQ("GET", tokens[0]);
4115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CHECK_EQ("HTTP/1.1", tokens[2]);
4125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    std::string path(tokens[1]);
4145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (path == kJsonPath)
4155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      path = kJsonListPath;
4165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (selected_socket_ == "chrome_devtools_remote") {
4185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (path == kJsonVersionPath)
4195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        SendHTTPResponse(kSampleChromeVersion);
4205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      else if (path == kJsonListPath)
4215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        SendHTTPResponse(kSampleChromePages);
4225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      else
4235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        NOTREACHED() << "Unknown command " << request;
4245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    } else if (selected_socket_ == "chrome_devtools_remote_1002") {
4255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (path == kJsonVersionPath)
4265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        SendHTTPResponse(kSampleChromeBetaVersion);
4275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      else if (path == kJsonListPath)
4285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        SendHTTPResponse(kSampleChromeBetaPages);
4295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      else
4305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        NOTREACHED() << "Unknown command " << request;
4315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    } else if (selected_socket_.find("noprocess_devtools_remote") == 0) {
4325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (path == kJsonVersionPath)
4335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        SendHTTPResponse("{}");
4345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      else if (path == kJsonListPath)
4355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        SendHTTPResponse("[]");
4365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      else
4375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        NOTREACHED() << "Unknown command " << request;
4385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    } else if (selected_socket_ == "webview_devtools_remote_2425") {
4395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (path == kJsonVersionPath)
4405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        SendHTTPResponse(kSampleWebViewVersion);
4415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      else if (path == kJsonListPath)
4425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        SendHTTPResponse(kSampleWebViewPages);
4435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      else
4445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        NOTREACHED() << "Unknown command " << request;
4455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    } else {
4465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      NOTREACHED() << "Unknown socket " << selected_socket_;
4475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
4485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
4495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void ProcessCommand(const std::string& command) {
4515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CHECK(CalledOnValidThread());
4525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (command == "host:devices") {
4535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      SendResponse(base::StringPrintf("%s\tdevice\n%s\toffline",
4545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                      kSerialOnline,
4555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                      kSerialOffline));
4565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    } else if (command.find(kHostTransportPrefix) == 0) {
4575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      selected_device_ = command.substr(strlen(kHostTransportPrefix));
4585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      SendResponse("");
4595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    } else if (selected_device_ != kSerialOnline) {
46046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      Send("FAIL", "device offline (x)");
4615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    } else if (command == kDeviceModelCommand) {
4625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      SendResponse(kDeviceModel);
4635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    } else if (command == kOpenedUnixSocketsCommand) {
4645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      SendResponse(kSampleOpenedUnixSockets);
4655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    } else if (command == kDumpsysCommand) {
4665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      SendResponse(kSampleDumpsys);
4675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    } else if (command == kListProcessesCommand) {
4685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      SendResponse(kSampleListProcesses);
4695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    } else if (command.find(kLocalAbstractPrefix) == 0) {
4705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      selected_socket_ = command.substr(strlen(kLocalAbstractPrefix));
4715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      SendResponse("");
4725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    } else {
4735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      NOTREACHED() << "Unknown command - " << command;
4745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
4755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
4765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void SendResponse(const std::string& response) {
47846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    Send("OKAY", response);
47946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
48046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
48146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  void Send(const std::string& status, const std::string& response) {
4825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CHECK(CalledOnValidThread());
48346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    CHECK_EQ(4U, status.size());
48446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    std::stringstream response_stream;
48646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    response_stream << status;
4875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    int size = response.size();
4895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (size > 0) {
4905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      static const char kHexChars[] = "0123456789ABCDEF";
4915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      for (int i = 3; i >= 0; i--)
4925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        response_stream << kHexChars[ (size >> 4*i) & 0x0f ];
4935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      response_stream << response;
4945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
49546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    callback_.Run(response_stream.str());
4965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
4975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void SendHTTPResponse(const std::string& body) {
4995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    CHECK(CalledOnValidThread());
5005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    std::string response_data(base::StringPrintf(kHttpResponse,
5015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                 static_cast<int>(body.size()),
5025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                 body.c_str()));
50346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    callback_.Run(response_data);
5045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
5055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  std::string selected_device_;
5075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  std::string selected_socket_;
50846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  SimpleHttpServer::SendCallback callback_;
5095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
5105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
51146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)static SimpleHttpServer* mock_adb_server_ = NULL;
5125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid StartMockAdbServerOnIOThread() {
5145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
5155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK(mock_adb_server_ == NULL);
51646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  net::IPAddressNumber address;
51746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  net::ParseIPLiteralToNumber("127.0.0.1", &address);
51846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  net::IPEndPoint endpoint(address, kAdbPort);
51946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  mock_adb_server_ =
52046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      new SimpleHttpServer(base::Bind(&AdbParser::Create), endpoint);
5215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid StopMockAdbServerOnIOThread() {
5245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
5255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  CHECK(mock_adb_server_ != NULL);
5265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  delete mock_adb_server_;
5275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  mock_adb_server_ = NULL;
5285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} // namespace
5315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid StartMockAdbServer() {
5335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  BrowserThread::PostTaskAndReply(
5345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      BrowserThread::IO,
5355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      FROM_HERE,
5365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      base::Bind(&StartMockAdbServerOnIOThread),
5375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      base::MessageLoop::QuitClosure());
5385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  content::RunMessageLoop();
5395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid StopMockAdbServer() {
5425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  BrowserThread::PostTaskAndReply(
5435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      BrowserThread::IO,
5445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      FROM_HERE,
5455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      base::Bind(&StopMockAdbServerOnIOThread),
5465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      base::MessageLoop::QuitClosure());
5475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  content::RunMessageLoop();
5485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
550