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