1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/devtools/android_device.h"
6 #include "chrome/browser/devtools/devtools_adb_bridge.h"
7 #include "chrome/browser/devtools/devtools_target_impl.h"
8 #include "chrome/browser/ui/browser.h"
9 #include "chrome/test/base/in_process_browser_test.h"
10 #include "content/public/test/test_utils.h"
12 const char kDeviceModelCommand[] = "shell:getprop ro.product.model";
13 const char kOpenedUnixSocketsCommand[] = "shell:cat /proc/net/unix";
14 const char kListProcessesCommand[] = "shell:ps";
15 const char kDumpsysCommand[] = "shell:dumpsys window policy";
17 const char kPageListRequest[] = "GET /json HTTP/1.1\r\n\r\n";
18 const char kVersionRequest[] = "GET /json/version HTTP/1.1\r\n\r\n";
20 const char kSampleOpenedUnixSockets[] =
21 "Num RefCount Protocol Flags Type St Inode Path\n"
22 "00000000: 00000004 00000000"
23 " 00000000 0002 01 3328 /dev/socket/wpa_wlan0\n"
24 "00000000: 00000002 00000000"
25 " 00010000 0001 01 5394 /dev/socket/vold\n"
26 "00000000: 00000002 00000000"
27 " 00010000 0001 01 11810 @webview_devtools_remote_2425\n"
28 "00000000: 00000002 00000000"
29 " 00010000 0001 01 20893 @chrome_devtools_remote\n";
31 const char kSampleListProcesses[] =
32 "USER PID PPID VSIZE RSS WCHAN PC NAME\n"
33 "root 1 0 688 508 ffffffff 00000000 S /init\n"
34 "u0_a75 2425 123 933736 193024 ffffffff 00000000 S com.sample.feed\n"
35 "nfc 741 123 706448 26316 ffffffff 00000000 S com.android.nfc";
37 const char kSampleDumpsysCommand[] =
38 "WINDOW MANAGER POLICY STATE (dumpsys window policy)\r\n"
39 " mSafeMode=false mSystemReady=true mSystemBooted=true\r\n"
40 " mStable=(0,50)-(720,1184)\r\n" // Only mStable parameter is parsed
41 " mForceStatusBar=false mForceStatusBarFromKeyguard=false\r\n";
43 char kSampleChromeVersion[] = "{\n"
44 " \"Browser\": \"Chrome/32.0.1679.0\",\n"
45 " \"Protocol-Version\": \"1.0\",\n"
46 " \"User-Agent\": \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 "
47 "(KHTML, like Gecko) Chrome/32.0.1679.0 Safari/537.36\",\n"
48 " \"WebKit-Version\": \"537.36 (@160162)\"\n"
51 char kSampleWebViewVersion[] = "{\n"
52 " \"Browser\": \"Version/4.0\",\n"
53 " \"Protocol-Version\": \"1.0\",\n"
54 " \"User-Agent\": \"Mozilla/5.0 (Linux; Android 4.3; Build/KRS74B) "
55 "AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Safari/537.36\",\n"
56 " \"WebKit-Version\": \"537.36 (@157588)\"\n"
59 char kSampleChromePages[] = "[ {\n"
60 " \"description\": \"\",\n"
61 " \"devtoolsFrontendUrl\": \"/devtools/devtools.html?"
62 "ws=/devtools/page/755DE5C9-D49F-811D-0693-51B8E15C80D2\",\n"
63 " \"id\": \"755DE5C9-D49F-811D-0693-51B8E15C80D2\",\n"
64 " \"title\": \"The Chromium Projects\",\n"
65 " \"type\": \"page\",\n"
66 " \"url\": \"http://www.chromium.org/\",\n"
67 " \"webSocketDebuggerUrl\": \""
68 "ws:///devtools/page/755DE5C9-D49F-811D-0693-51B8E15C80D2\"\n"
71 char kSampleWebViewPages[] = "[ {\n"
72 " \"description\": \"{\\\"attached\\\":false,\\\"empty\\\":false,"
73 "\\\"height\\\":1173,\\\"screenX\\\":0,\\\"screenY\\\":0,"
74 "\\\"visible\\\":true,\\\"width\\\":800}\",\n"
75 " \"devtoolsFrontendUrl\": \"http://chrome-devtools-frontend.appspot.com/"
76 "serve_rev/@157588/devtools.html?ws="
77 "/devtools/page/3E962D4D-B676-182D-3BE8-FAE7CE224DE7\",\n"
78 " \"faviconUrl\": \"http://chromium.org/favicon.ico\",\n"
79 " \"id\": \"3E962D4D-B676-182D-3BE8-FAE7CE224DE7\",\n"
80 " \"thumbnailUrl\": \"/thumb/3E962D4D-B676-182D-3BE8-FAE7CE224DE7\",\n"
81 " \"title\": \"Blink - The Chromium Projects\",\n"
82 " \"type\": \"page\",\n"
83 " \"url\": \"http://www.chromium.org/blink\",\n"
84 " \"webSocketDebuggerUrl\": \"ws:///devtools/"
85 "page/3E962D4D-B676-182D-3BE8-FAE7CE224DE7\"\n"
87 " \"description\": \"{\\\"attached\\\":true,\\\"empty\\\":true,"
88 "\\\"screenX\\\":0,\\\"screenY\\\":33,\\\"visible\\\":false}\",\n"
89 " \"devtoolsFrontendUrl\": \"http://chrome-devtools-frontend.appspot.com/"
90 "serve_rev/@157588/devtools.html?ws="
91 "/devtools/page/44681551-ADFD-2411-076B-3AB14C1C60E2\",\n"
92 " \"faviconUrl\": \"\",\n"
93 " \"id\": \"44681551-ADFD-2411-076B-3AB14C1C60E2\",\n"
94 " \"thumbnailUrl\": \"/thumb/44681551-ADFD-2411-076B-3AB14C1C60E2\",\n"
95 " \"title\": \"More Activity\",\n"
96 " \"type\": \"page\",\n"
97 " \"url\": \"about:blank\",\n"
98 " \"webSocketDebuggerUrl\": \"ws:///devtools/page/"
99 "44681551-ADFD-2411-076B-3AB14C1C60E2\"\n"
102 class MockDeviceImpl : public AndroidDevice {
104 MockDeviceImpl(const std::string& serial, int index,
105 bool connected, const char* device_model)
106 : AndroidDevice(serial, connected),
107 device_model_(device_model)
110 virtual void RunCommand(const std::string& command,
111 const CommandCallback& callback) OVERRIDE {
112 const char* response;
114 if (command == kDeviceModelCommand) {
115 response = device_model_;
116 } else if (command == kOpenedUnixSocketsCommand) {
117 response = kSampleOpenedUnixSockets;
118 } else if (command == kListProcessesCommand) {
119 response = kSampleListProcesses;
120 } else if (command == kDumpsysCommand) {
121 response = kSampleDumpsysCommand;
127 base::MessageLoop::current()->PostTask( FROM_HERE,
128 base::Bind(&MockDeviceImpl::RunCommandCallback,
129 this, callback, 0, response));
132 void RunCommandCallback(const CommandCallback& callback, int result,
133 const std::string& response) {
134 callback.Run(result, response);
137 virtual void OpenSocket(const std::string& name,
138 const SocketCallback& callback) OVERRIDE {
142 virtual void HttpQuery(const std::string& la_name,
143 const std::string& request,
144 const CommandCallback& callback) OVERRIDE {
145 const char* response;
147 if (la_name == "chrome_devtools_remote") {
148 if (request == kVersionRequest) {
149 response = kSampleChromeVersion;
150 } else if (request == kPageListRequest) {
151 response = kSampleChromePages;
156 } else if (la_name == "webview_devtools_remote_2425") {
157 if (request == kVersionRequest) {
158 response = kSampleWebViewVersion;
159 } else if (request == kPageListRequest) {
160 response = kSampleWebViewPages;
170 base::MessageLoop::current()->PostTask( FROM_HERE,
171 base::Bind(&MockDeviceImpl::RunCommandCallback,
172 this, callback, 0, response));
175 virtual void HttpUpgrade(const std::string& la_name,
176 const std::string& request,
177 const SocketCallback& callback) {
181 virtual void HttpQueryCallback(const CommandCallback& next, int code,
182 const std::string& result) {
187 virtual ~MockDeviceImpl()
190 const char* device_model_;
193 class MockDeviceProvider : public AndroidDeviceProvider {
194 virtual ~MockDeviceProvider()
197 virtual void QueryDevices(const QueryDevicesCallback& callback) OVERRIDE {
198 AndroidDeviceProvider::AndroidDevices devices;
199 devices.push_back(new MockDeviceImpl("FirstDevice", 0, true, "Nexus 6"));
200 devices.push_back(new MockDeviceImpl("SecondDevice", 1, false, "Nexus 8"));
201 callback.Run(devices);
206 class DevToolsAdbBridgeTest : public InProcessBrowserTest,
207 public DevToolsAdbBridge::Listener {
208 typedef DevToolsAdbBridge::RemoteDevices::const_iterator rdci;
209 typedef DevToolsAdbBridge::RemoteBrowsers::const_iterator rbci;
211 virtual void RemoteDevicesChanged(
212 DevToolsAdbBridge::RemoteDevices* devices) OVERRIDE{
213 ASSERT_EQ(2U, devices->size());
215 scoped_refptr<DevToolsAdbBridge::RemoteDevice> connected =
216 (*devices)[0]->IsConnected() ? (*devices)[0] : (*devices)[1];
218 scoped_refptr<DevToolsAdbBridge::RemoteDevice> not_connected =
219 (*devices)[0]->IsConnected() ? (*devices)[1] : (*devices)[0];
221 ASSERT_TRUE(connected->IsConnected());
222 ASSERT_FALSE(not_connected->IsConnected());
224 ASSERT_EQ(720, connected->screen_size().width());
225 ASSERT_EQ(1184, connected->screen_size().height());
227 ASSERT_EQ("FirstDevice", connected->GetSerial());
228 ASSERT_EQ("Nexus 6", connected->GetModel());
230 ASSERT_EQ("SecondDevice", not_connected->GetSerial());
231 ASSERT_EQ("Offline", not_connected->GetModel());
233 const DevToolsAdbBridge::RemoteBrowsers& browsers = connected->browsers();
234 ASSERT_EQ(2U, browsers.size());
236 scoped_refptr<DevToolsAdbBridge::RemoteBrowser> chrome =
237 browsers[0]->product() == "Chrome" ? browsers[0] : browsers[1];
239 scoped_refptr<DevToolsAdbBridge::RemoteBrowser> webview =
240 browsers[0]->product() == "Chrome" ? browsers[1] : browsers[0];
242 ASSERT_EQ("Chrome", chrome->product());
243 ASSERT_EQ("32.0.1679.0", chrome->version());
245 ASSERT_EQ("Webview", webview->product());
246 ASSERT_EQ("4.0", webview->version());
248 // Check that we parse process list properly.
249 ASSERT_EQ("com.sample.feed", webview->package());
251 std::vector<DevToolsTargetImpl*> chrome_pages =
252 chrome->CreatePageTargets();
253 std::vector<DevToolsTargetImpl*> webview_pages =
254 webview->CreatePageTargets();
256 ASSERT_EQ(1U, chrome_pages.size());
257 ASSERT_EQ(2U, webview_pages.size());
259 // Check that we have non-empty description for webview pages.
260 ASSERT_EQ(0U, chrome_pages[0]->GetDescription().size());
261 ASSERT_NE(0U, webview_pages[0]->GetDescription().size());
262 ASSERT_NE(0U, webview_pages[1]->GetDescription().size());
264 ASSERT_EQ(GURL("http://www.chromium.org/"), chrome_pages[0]->GetUrl());
265 ASSERT_EQ("The Chromium Projects", chrome_pages[0]->GetTitle());
267 STLDeleteElements(&chrome_pages);
268 STLDeleteElements(&webview_pages);
274 runner_ = new content::MessageLoopRunner;
278 scoped_refptr<content::MessageLoopRunner> runner_;
281 IN_PROC_BROWSER_TEST_F(DevToolsAdbBridgeTest, Main) {
284 scoped_refptr<DevToolsAdbBridge> adb_bridge =
285 DevToolsAdbBridge::Factory::GetForProfile(browser()->profile());
287 DevToolsAdbBridge::DeviceProviders providers;
288 providers.push_back(new MockDeviceProvider());
290 adb_bridge->set_device_providers(providers);
293 FAIL() << "Failed to get DevToolsAdbBridge.";
296 adb_bridge->AddListener(this);