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 kListPackagesCommand
[] = "shell:pm list packages";
16 const char kDumpsysCommand
[] = "shell:dumpsys window policy";
18 const char kPageListRequest
[] = "GET /json HTTP/1.1\r\n\r\n";
19 const char kVersionRequest
[] = "GET /json/version HTTP/1.1\r\n\r\n";
21 const char kSampleOpenedUnixSockets
[] =
22 "Num RefCount Protocol Flags Type St Inode Path\n"
23 "00000000: 00000004 00000000"
24 " 00000000 0002 01 3328 /dev/socket/wpa_wlan0\n"
25 "00000000: 00000002 00000000"
26 " 00010000 0001 01 5394 /dev/socket/vold\n"
27 "00000000: 00000002 00000000"
28 " 00010000 0001 01 11810 @webview_devtools_remote_2425\n"
29 "00000000: 00000002 00000000"
30 " 00010000 0001 01 20893 @chrome_devtools_remote\n"
31 "00000000: 00000002 00000000"
32 " 00010000 0001 01 20894 @chrome_devtools_remote_1002\n"
33 "00000000: 00000002 00000000"
34 " 00010000 0001 01 20895 @noprocess_devtools_remote\n";
36 const char kSampleListProcesses
[] =
37 "USER PID PPID VSIZE RSS WCHAN PC NAME\n"
38 "root 1 0 688 508 ffffffff 00000000 S /init\r\n"
39 "u0_a75 2425 123 933736 193024 ffffffff 00000000 S com.sample.feed\r\n"
40 "nfc 741 123 706448 26316 ffffffff 00000000 S com.android.nfc\r\n"
41 "u0_a76 1001 124 111111 222222 ffffffff 00000000 S com.android.chrome\r\n"
42 "u0_a77 1002 125 111111 222222 ffffffff 00000000 S com.chrome.beta\r\n"
43 "u0_a78 1003 126 111111 222222 ffffffff 00000000 S com.noprocess.app\r\n";
45 const char kSampleListPackages
[] =
46 "package:com.sample.feed\r\n"
47 "package:com.android.nfc\r\n"
48 "package:com.android.chrome\r\n"
49 "package:com.chrome.beta\r\n"
50 "package:com.google.android.apps.chrome\r\n";
52 const char kSampleDumpsysCommand
[] =
53 "WINDOW MANAGER POLICY STATE (dumpsys window policy)\r\n"
54 " mSafeMode=false mSystemReady=true mSystemBooted=true\r\n"
55 " mStable=(0,50)-(720,1184)\r\n" // Only mStable parameter is parsed
56 " mForceStatusBar=false mForceStatusBarFromKeyguard=false\r\n";
58 char kSampleChromeVersion
[] = "{\n"
59 " \"Browser\": \"Chrome/32.0.1679.0\",\n"
60 " \"Protocol-Version\": \"1.0\",\n"
61 " \"User-Agent\": \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 "
62 "(KHTML, like Gecko) Chrome/32.0.1679.0 Safari/537.36\",\n"
63 " \"WebKit-Version\": \"537.36 (@160162)\"\n"
66 char kSampleChromeBetaVersion
[] = "{\n"
67 " \"Browser\": \"Chrome/31.0.1599.0\",\n"
68 " \"Protocol-Version\": \"1.0\",\n"
69 " \"User-Agent\": \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 "
70 "(KHTML, like Gecko) Chrome/32.0.1679.0 Safari/537.36\",\n"
71 " \"WebKit-Version\": \"537.36 (@160162)\"\n"
74 char kSampleWebViewVersion
[] = "{\n"
75 " \"Browser\": \"Version/4.0\",\n"
76 " \"Protocol-Version\": \"1.0\",\n"
77 " \"User-Agent\": \"Mozilla/5.0 (Linux; Android 4.3; Build/KRS74B) "
78 "AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Safari/537.36\",\n"
79 " \"WebKit-Version\": \"537.36 (@157588)\"\n"
82 char kSampleChromePages
[] = "[ {\n"
83 " \"description\": \"\",\n"
84 " \"devtoolsFrontendUrl\": \"/devtools/devtools.html?"
85 "ws=/devtools/page/755DE5C9-D49F-811D-0693-51B8E15C80D2\",\n"
86 " \"id\": \"755DE5C9-D49F-811D-0693-51B8E15C80D2\",\n"
87 " \"title\": \"The Chromium Projects\",\n"
88 " \"type\": \"page\",\n"
89 " \"url\": \"http://www.chromium.org/\",\n"
90 " \"webSocketDebuggerUrl\": \""
91 "ws:///devtools/page/755DE5C9-D49F-811D-0693-51B8E15C80D2\"\n"
94 char kSampleChromeBetaPages
[] = "[]";
96 char kSampleWebViewPages
[] = "[ {\n"
97 " \"description\": \"{\\\"attached\\\":false,\\\"empty\\\":false,"
98 "\\\"height\\\":1173,\\\"screenX\\\":0,\\\"screenY\\\":0,"
99 "\\\"visible\\\":true,\\\"width\\\":800}\",\n"
100 " \"devtoolsFrontendUrl\": \"http://chrome-devtools-frontend.appspot.com/"
101 "serve_rev/@157588/devtools.html?ws="
102 "/devtools/page/3E962D4D-B676-182D-3BE8-FAE7CE224DE7\",\n"
103 " \"faviconUrl\": \"http://chromium.org/favicon.ico\",\n"
104 " \"id\": \"3E962D4D-B676-182D-3BE8-FAE7CE224DE7\",\n"
105 " \"thumbnailUrl\": \"/thumb/3E962D4D-B676-182D-3BE8-FAE7CE224DE7\",\n"
106 " \"title\": \"Blink - The Chromium Projects\",\n"
107 " \"type\": \"page\",\n"
108 " \"url\": \"http://www.chromium.org/blink\",\n"
109 " \"webSocketDebuggerUrl\": \"ws:///devtools/"
110 "page/3E962D4D-B676-182D-3BE8-FAE7CE224DE7\"\n"
112 " \"description\": \"{\\\"attached\\\":true,\\\"empty\\\":true,"
113 "\\\"screenX\\\":0,\\\"screenY\\\":33,\\\"visible\\\":false}\",\n"
114 " \"devtoolsFrontendUrl\": \"http://chrome-devtools-frontend.appspot.com/"
115 "serve_rev/@157588/devtools.html?ws="
116 "/devtools/page/44681551-ADFD-2411-076B-3AB14C1C60E2\",\n"
117 " \"faviconUrl\": \"\",\n"
118 " \"id\": \"44681551-ADFD-2411-076B-3AB14C1C60E2\",\n"
119 " \"thumbnailUrl\": \"/thumb/44681551-ADFD-2411-076B-3AB14C1C60E2\",\n"
120 " \"title\": \"More Activity\",\n"
121 " \"type\": \"page\",\n"
122 " \"url\": \"about:blank\",\n"
123 " \"webSocketDebuggerUrl\": \"ws:///devtools/page/"
124 "44681551-ADFD-2411-076B-3AB14C1C60E2\"\n"
127 class MockDeviceImpl
: public AndroidDevice
{
129 MockDeviceImpl(const std::string
& serial
, int index
,
130 bool connected
, const char* device_model
)
131 : AndroidDevice(serial
, connected
),
132 device_model_(device_model
)
135 virtual void RunCommand(const std::string
& command
,
136 const CommandCallback
& callback
) OVERRIDE
{
137 const char* response
;
139 if (command
== kDeviceModelCommand
) {
140 response
= device_model_
;
141 } else if (command
== kOpenedUnixSocketsCommand
) {
142 response
= kSampleOpenedUnixSockets
;
143 } else if (command
== kListProcessesCommand
) {
144 response
= kSampleListProcesses
;
145 } else if (command
== kListPackagesCommand
) {
146 response
= kSampleListPackages
;
147 } else if (command
== kDumpsysCommand
) {
148 response
= kSampleDumpsysCommand
;
154 base::MessageLoop::current()->PostTask( FROM_HERE
,
155 base::Bind(&MockDeviceImpl::RunCommandCallback
,
156 this, callback
, 0, response
));
159 void RunCommandCallback(const CommandCallback
& callback
, int result
,
160 const std::string
& response
) {
161 callback
.Run(result
, response
);
164 virtual void OpenSocket(const std::string
& name
,
165 const SocketCallback
& callback
) OVERRIDE
{
169 virtual void HttpQuery(const std::string
& la_name
,
170 const std::string
& request
,
171 const CommandCallback
& callback
) OVERRIDE
{
172 const char* response
;
174 if (la_name
== "chrome_devtools_remote") {
175 if (request
== kVersionRequest
) {
176 response
= kSampleChromeVersion
;
177 } else if (request
== kPageListRequest
) {
178 response
= kSampleChromePages
;
183 } else if (la_name
== "chrome_devtools_remote_1002") {
184 if (request
== kVersionRequest
) {
185 response
= kSampleChromeBetaVersion
;
186 } else if (request
== kPageListRequest
) {
187 response
= kSampleChromeBetaPages
;
192 } else if (la_name
.find("noprocess_devtools_remote") == 0) {
193 if (request
== kVersionRequest
) {
195 } else if (request
== kPageListRequest
) {
201 } else if (la_name
== "webview_devtools_remote_2425") {
202 if (request
== kVersionRequest
) {
203 response
= kSampleWebViewVersion
;
204 } else if (request
== kPageListRequest
) {
205 response
= kSampleWebViewPages
;
215 base::MessageLoop::current()->PostTask( FROM_HERE
,
216 base::Bind(&MockDeviceImpl::RunCommandCallback
,
217 this, callback
, 0, response
));
220 virtual void HttpUpgrade(const std::string
& la_name
,
221 const std::string
& request
,
222 const SocketCallback
& callback
) {
226 virtual void HttpQueryCallback(const CommandCallback
& next
, int code
,
227 const std::string
& result
) {
232 virtual ~MockDeviceImpl()
235 const char* device_model_
;
238 class MockDeviceProvider
: public AndroidDeviceProvider
{
239 virtual ~MockDeviceProvider()
242 virtual void QueryDevices(const QueryDevicesCallback
& callback
) OVERRIDE
{
243 AndroidDeviceProvider::AndroidDevices devices
;
244 devices
.push_back(new MockDeviceImpl("FirstDevice", 0, true, "Nexus 6"));
245 devices
.push_back(new MockDeviceImpl("SecondDevice", 1, false, "Nexus 8"));
246 callback
.Run(devices
);
250 static scoped_refptr
<DevToolsAdbBridge::RemoteBrowser
>
251 FindBrowserByDisplayName(DevToolsAdbBridge::RemoteBrowsers browsers
,
252 const std::string
& name
) {
253 for (DevToolsAdbBridge::RemoteBrowsers::iterator it
= browsers
.begin();
254 it
!= browsers
.end(); ++it
)
255 if ((*it
)->display_name() == name
)
260 class DevToolsAdbBridgeTest
: public InProcessBrowserTest
,
261 public DevToolsAdbBridge::Listener
{
262 typedef DevToolsAdbBridge::RemoteDevices::const_iterator rdci
;
263 typedef DevToolsAdbBridge::RemoteBrowsers::const_iterator rbci
;
265 virtual void RemoteDevicesChanged(
266 DevToolsAdbBridge::RemoteDevices
* devices
) OVERRIDE
{
271 void CheckDevices() {
272 ASSERT_EQ(2U, devices_
.size());
274 scoped_refptr
<DevToolsAdbBridge::RemoteDevice
> connected
=
275 devices_
[0]->IsConnected() ? devices_
[0] : devices_
[1];
277 scoped_refptr
<DevToolsAdbBridge::RemoteDevice
> not_connected
=
278 devices_
[0]->IsConnected() ? devices_
[1] : devices_
[0];
280 ASSERT_TRUE(connected
->IsConnected());
281 ASSERT_FALSE(not_connected
->IsConnected());
283 ASSERT_EQ(720, connected
->screen_size().width());
284 ASSERT_EQ(1184, connected
->screen_size().height());
286 ASSERT_EQ("FirstDevice", connected
->GetSerial());
287 ASSERT_EQ("Nexus 6", connected
->GetModel());
289 ASSERT_EQ("SecondDevice", not_connected
->GetSerial());
290 ASSERT_EQ("Offline", not_connected
->GetModel());
292 const DevToolsAdbBridge::RemoteBrowsers
& browsers
= connected
->browsers();
293 ASSERT_EQ(4U, browsers
.size());
295 scoped_refptr
<DevToolsAdbBridge::RemoteBrowser
> chrome
=
296 FindBrowserByDisplayName(browsers
, "Chrome");
299 scoped_refptr
<DevToolsAdbBridge::RemoteBrowser
> chrome_beta
=
300 FindBrowserByDisplayName(browsers
, "Chrome Beta");
301 ASSERT_TRUE(chrome_beta
);
303 scoped_refptr
<DevToolsAdbBridge::RemoteBrowser
> chromium
=
304 FindBrowserByDisplayName(browsers
, "Chromium");
305 ASSERT_FALSE(chromium
);
307 scoped_refptr
<DevToolsAdbBridge::RemoteBrowser
> webview
=
308 FindBrowserByDisplayName(browsers
, "WebView in com.sample.feed");
309 ASSERT_TRUE(webview
);
311 scoped_refptr
<DevToolsAdbBridge::RemoteBrowser
> noprocess
=
312 FindBrowserByDisplayName(browsers
, "Noprocess");
313 ASSERT_TRUE(noprocess
);
315 ASSERT_EQ("32.0.1679.0", chrome
->version());
316 ASSERT_EQ("31.0.1599.0", chrome_beta
->version());
317 ASSERT_EQ("4.0", webview
->version());
319 std::vector
<DevToolsTargetImpl
*> chrome_pages
=
320 chrome
->CreatePageTargets();
321 std::vector
<DevToolsTargetImpl
*> chrome_beta_pages
=
322 chrome_beta
->CreatePageTargets();
323 std::vector
<DevToolsTargetImpl
*> webview_pages
=
324 webview
->CreatePageTargets();
326 ASSERT_EQ(1U, chrome_pages
.size());
327 ASSERT_EQ(0U, chrome_beta_pages
.size());
328 ASSERT_EQ(2U, webview_pages
.size());
330 // Check that we have non-empty description for webview pages.
331 ASSERT_EQ(0U, chrome_pages
[0]->GetDescription().size());
332 ASSERT_NE(0U, webview_pages
[0]->GetDescription().size());
333 ASSERT_NE(0U, webview_pages
[1]->GetDescription().size());
335 ASSERT_EQ(GURL("http://www.chromium.org/"), chrome_pages
[0]->GetUrl());
336 ASSERT_EQ("The Chromium Projects", chrome_pages
[0]->GetTitle());
338 STLDeleteElements(&chrome_pages
);
339 STLDeleteElements(&webview_pages
);
343 runner_
= new content::MessageLoopRunner
;
347 scoped_refptr
<content::MessageLoopRunner
> runner_
;
348 DevToolsAdbBridge::RemoteDevices devices_
;
351 IN_PROC_BROWSER_TEST_F(DevToolsAdbBridgeTest
, DiscoverAndroidBrowsers
) {
354 scoped_refptr
<DevToolsAdbBridge
> adb_bridge
=
355 DevToolsAdbBridge::Factory::GetForProfile(browser()->profile());
357 DevToolsAdbBridge::DeviceProviders providers
;
358 providers
.push_back(new MockDeviceProvider());
360 adb_bridge
->set_device_providers(providers
);
363 FAIL() << "Failed to get DevToolsAdbBridge.";
366 adb_bridge
->AddListener(this);