OLD | NEW |
| (Empty) |
1 // Copyright 2014 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. | |
4 | |
5 #include "chrome/browser/devtools/device/android_device_manager.h" | |
6 #include "chrome/browser/devtools/device/devtools_android_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" | |
11 | |
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"; | |
17 | |
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"; | |
20 | |
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"; | |
35 | |
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"; | |
44 | |
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"; | |
51 | |
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"; | |
57 | |
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" | |
64 "}"; | |
65 | |
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" | |
72 "}"; | |
73 | |
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" | |
80 "}"; | |
81 | |
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" | |
92 "} ]"; | |
93 | |
94 char kSampleChromeBetaPages[] = "[]"; | |
95 | |
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" | |
111 "}, {\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" | |
125 "}]"; | |
126 | |
127 class MockDeviceImpl : public AndroidDeviceManager::Device { | |
128 public: | |
129 MockDeviceImpl(const std::string& serial, int index, | |
130 bool connected, const char* device_model) | |
131 : Device(serial, connected), | |
132 device_model_(device_model) | |
133 {} | |
134 | |
135 virtual void RunCommand(const std::string& command, | |
136 const CommandCallback& callback) OVERRIDE { | |
137 const char* response; | |
138 | |
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; | |
149 } else { | |
150 NOTREACHED(); | |
151 return; | |
152 } | |
153 | |
154 base::MessageLoop::current()->PostTask( FROM_HERE, | |
155 base::Bind(&MockDeviceImpl::RunCommandCallback, | |
156 this, callback, 0, response)); | |
157 } | |
158 | |
159 void RunCommandCallback(const CommandCallback& callback, int result, | |
160 const std::string& response) { | |
161 callback.Run(result, response); | |
162 } | |
163 | |
164 virtual void OpenSocket(const std::string& name, | |
165 const SocketCallback& callback) OVERRIDE { | |
166 NOTREACHED(); | |
167 } | |
168 | |
169 virtual void HttpQuery(const std::string& la_name, | |
170 const std::string& request, | |
171 const CommandCallback& callback) OVERRIDE { | |
172 const char* response; | |
173 | |
174 if (la_name == "chrome_devtools_remote") { | |
175 if (request == kVersionRequest) { | |
176 response = kSampleChromeVersion; | |
177 } else if (request == kPageListRequest) { | |
178 response = kSampleChromePages; | |
179 } else { | |
180 NOTREACHED(); | |
181 return; | |
182 } | |
183 } else if (la_name == "chrome_devtools_remote_1002") { | |
184 if (request == kVersionRequest) { | |
185 response = kSampleChromeBetaVersion; | |
186 } else if (request == kPageListRequest) { | |
187 response = kSampleChromeBetaPages; | |
188 } else { | |
189 NOTREACHED(); | |
190 return; | |
191 } | |
192 } else if (la_name.find("noprocess_devtools_remote") == 0) { | |
193 if (request == kVersionRequest) { | |
194 response = "{}"; | |
195 } else if (request == kPageListRequest) { | |
196 response = "[]"; | |
197 } else { | |
198 NOTREACHED(); | |
199 return; | |
200 } | |
201 } else if (la_name == "webview_devtools_remote_2425") { | |
202 if (request == kVersionRequest) { | |
203 response = kSampleWebViewVersion; | |
204 } else if (request == kPageListRequest) { | |
205 response = kSampleWebViewPages; | |
206 } else { | |
207 NOTREACHED(); | |
208 return; | |
209 } | |
210 } else { | |
211 NOTREACHED(); | |
212 return; | |
213 } | |
214 | |
215 base::MessageLoop::current()->PostTask( FROM_HERE, | |
216 base::Bind(&MockDeviceImpl::RunCommandCallback, | |
217 this, callback, 0, response)); | |
218 } | |
219 | |
220 virtual void HttpUpgrade(const std::string& la_name, | |
221 const std::string& request, | |
222 const SocketCallback& callback) { | |
223 NOTREACHED(); | |
224 } | |
225 | |
226 virtual void HttpQueryCallback(const CommandCallback& next, int code, | |
227 const std::string& result) { | |
228 NOTREACHED(); | |
229 } | |
230 | |
231 private: | |
232 virtual ~MockDeviceImpl() | |
233 {} | |
234 | |
235 const char* device_model_; | |
236 }; | |
237 | |
238 class MockDeviceProvider : public AndroidDeviceManager::DeviceProvider { | |
239 virtual ~MockDeviceProvider() | |
240 {} | |
241 | |
242 virtual void QueryDevices(const QueryDevicesCallback& callback) OVERRIDE { | |
243 AndroidDeviceManager::Devices 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); | |
247 } | |
248 }; | |
249 | |
250 // static | |
251 scoped_refptr<AndroidDeviceManager::DeviceProvider> | |
252 AndroidDeviceManager::GetMockDeviceProviderForTest() { | |
253 return new MockDeviceProvider(); | |
254 } | |
255 | |
256 static scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> | |
257 FindBrowserByDisplayName(DevToolsAndroidBridge::RemoteBrowsers browsers, | |
258 const std::string& name) { | |
259 for (DevToolsAndroidBridge::RemoteBrowsers::iterator it = browsers.begin(); | |
260 it != browsers.end(); ++it) | |
261 if ((*it)->display_name() == name) | |
262 return *it; | |
263 return NULL; | |
264 } | |
265 | |
266 class DevToolsAdbBridgeTest : public InProcessBrowserTest, | |
267 public DevToolsAndroidBridge::DeviceListListener { | |
268 typedef DevToolsAndroidBridge::RemoteDevices::const_iterator rdci; | |
269 typedef DevToolsAndroidBridge::RemoteBrowsers::const_iterator rbci; | |
270 public: | |
271 virtual void DeviceListChanged( | |
272 const DevToolsAndroidBridge::RemoteDevices& devices) OVERRIDE { | |
273 devices_ = devices; | |
274 runner_->Quit(); | |
275 } | |
276 | |
277 void CheckDevices() { | |
278 ASSERT_EQ(2U, devices_.size()); | |
279 | |
280 scoped_refptr<DevToolsAndroidBridge::RemoteDevice> connected = | |
281 devices_[0]->is_connected() ? devices_[0] : devices_[1]; | |
282 | |
283 scoped_refptr<DevToolsAndroidBridge::RemoteDevice> not_connected = | |
284 devices_[0]->is_connected() ? devices_[1] : devices_[0]; | |
285 | |
286 ASSERT_TRUE(connected->is_connected()); | |
287 ASSERT_FALSE(not_connected->is_connected()); | |
288 | |
289 ASSERT_EQ(720, connected->screen_size().width()); | |
290 ASSERT_EQ(1184, connected->screen_size().height()); | |
291 | |
292 ASSERT_EQ("FirstDevice", connected->serial()); | |
293 ASSERT_EQ("Nexus 6", connected->model()); | |
294 | |
295 ASSERT_EQ("SecondDevice", not_connected->serial()); | |
296 ASSERT_EQ("Offline", not_connected->model()); | |
297 | |
298 const DevToolsAndroidBridge::RemoteBrowsers& browsers = | |
299 connected->browsers(); | |
300 ASSERT_EQ(4U, browsers.size()); | |
301 | |
302 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> chrome = | |
303 FindBrowserByDisplayName(browsers, "Chrome"); | |
304 ASSERT_TRUE(chrome); | |
305 | |
306 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> chrome_beta = | |
307 FindBrowserByDisplayName(browsers, "Chrome Beta"); | |
308 ASSERT_TRUE(chrome_beta); | |
309 | |
310 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> chromium = | |
311 FindBrowserByDisplayName(browsers, "Chromium"); | |
312 ASSERT_FALSE(chromium); | |
313 | |
314 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> webview = | |
315 FindBrowserByDisplayName(browsers, "WebView in com.sample.feed"); | |
316 ASSERT_TRUE(webview); | |
317 | |
318 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> noprocess = | |
319 FindBrowserByDisplayName(browsers, "Noprocess"); | |
320 ASSERT_TRUE(noprocess); | |
321 | |
322 ASSERT_EQ("32.0.1679.0", chrome->version()); | |
323 ASSERT_EQ("31.0.1599.0", chrome_beta->version()); | |
324 ASSERT_EQ("4.0", webview->version()); | |
325 | |
326 std::vector<DevToolsTargetImpl*> chrome_pages = | |
327 chrome->CreatePageTargets(); | |
328 std::vector<DevToolsTargetImpl*> chrome_beta_pages = | |
329 chrome_beta->CreatePageTargets(); | |
330 std::vector<DevToolsTargetImpl*> webview_pages = | |
331 webview->CreatePageTargets(); | |
332 | |
333 ASSERT_EQ(1U, chrome_pages.size()); | |
334 ASSERT_EQ(0U, chrome_beta_pages.size()); | |
335 ASSERT_EQ(2U, webview_pages.size()); | |
336 | |
337 // Check that we have non-empty description for webview pages. | |
338 ASSERT_EQ(0U, chrome_pages[0]->GetDescription().size()); | |
339 ASSERT_NE(0U, webview_pages[0]->GetDescription().size()); | |
340 ASSERT_NE(0U, webview_pages[1]->GetDescription().size()); | |
341 | |
342 ASSERT_EQ(GURL("http://www.chromium.org/"), chrome_pages[0]->GetUrl()); | |
343 ASSERT_EQ("The Chromium Projects", chrome_pages[0]->GetTitle()); | |
344 | |
345 STLDeleteElements(&chrome_pages); | |
346 STLDeleteElements(&webview_pages); | |
347 } | |
348 | |
349 void init() { | |
350 runner_ = new content::MessageLoopRunner; | |
351 } | |
352 | |
353 protected: | |
354 scoped_refptr<content::MessageLoopRunner> runner_; | |
355 DevToolsAndroidBridge::RemoteDevices devices_; | |
356 }; | |
357 | |
358 IN_PROC_BROWSER_TEST_F(DevToolsAdbBridgeTest, DiscoverAndroidBrowsers) { | |
359 init(); | |
360 | |
361 scoped_refptr<DevToolsAndroidBridge> android_bridge = | |
362 DevToolsAndroidBridge::Factory::GetForProfile(browser()->profile()); | |
363 | |
364 AndroidDeviceManager::DeviceProviders providers; | |
365 providers.push_back(AndroidDeviceManager::GetMockDeviceProviderForTest()); | |
366 | |
367 android_bridge->set_device_providers_for_test(providers); | |
368 | |
369 if (!android_bridge) { | |
370 FAIL() << "Failed to get DevToolsAndroidBridge."; | |
371 } | |
372 | |
373 android_bridge->AddDeviceListListener(this); | |
374 | |
375 runner_->Run(); | |
376 | |
377 CheckDevices(); | |
378 } | |
OLD | NEW |