OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/devtools/device/adb/adb_device_info_query.h" | 5 #include "chrome/browser/devtools/device/adb/adb_device_info_query.h" |
6 | 6 |
7 #include "base/strings/string_number_conversions.h" | 7 #include "base/strings/string_number_conversions.h" |
8 #include "base/strings/string_util.h" | 8 #include "base/strings/string_util.h" |
9 #include "base/strings/stringprintf.h" | 9 #include "base/strings/stringprintf.h" |
10 | 10 |
11 namespace { | 11 namespace { |
12 | 12 |
13 | 13 |
14 const char kDeviceModelCommand[] = "shell:getprop ro.product.model"; | 14 const char kDeviceModelCommand[] = "shell:getprop ro.product.model"; |
15 const char kInstalledChromePackagesCommand[] = "shell:pm list packages"; | |
16 const char kOpenedUnixSocketsCommand[] = "shell:cat /proc/net/unix"; | 15 const char kOpenedUnixSocketsCommand[] = "shell:cat /proc/net/unix"; |
17 const char kListProcessesCommand[] = "shell:ps"; | 16 const char kListProcessesCommand[] = "shell:ps"; |
18 const char kDumpsysCommand[] = "shell:dumpsys window policy"; | 17 const char kDumpsysCommand[] = "shell:dumpsys window policy"; |
19 const char kDumpsysScreenSizePrefix[] = "mStable="; | 18 const char kDumpsysScreenSizePrefix[] = "mStable="; |
20 | 19 |
21 const char kDevToolsSocketSuffix[] = "_devtools_remote"; | 20 const char kDevToolsSocketSuffix[] = "_devtools_remote"; |
22 | 21 |
23 const char kChromeDefaultName[] = "Chrome"; | 22 const char kChromeDefaultName[] = "Chrome"; |
24 const char kChromeDefaultSocket[] = "chrome_devtools_remote"; | 23 const char kChromeDefaultSocket[] = "chrome_devtools_remote"; |
25 | 24 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 }; | 75 }; |
77 | 76 |
78 const BrowserDescriptor* FindBrowserDescriptor(const std::string& package) { | 77 const BrowserDescriptor* FindBrowserDescriptor(const std::string& package) { |
79 int count = sizeof(kBrowserDescriptors) / sizeof(kBrowserDescriptors[0]); | 78 int count = sizeof(kBrowserDescriptors) / sizeof(kBrowserDescriptors[0]); |
80 for (int i = 0; i < count; i++) | 79 for (int i = 0; i < count; i++) |
81 if (kBrowserDescriptors[i].package == package) | 80 if (kBrowserDescriptors[i].package == package) |
82 return &kBrowserDescriptors[i]; | 81 return &kBrowserDescriptors[i]; |
83 return NULL; | 82 return NULL; |
84 } | 83 } |
85 | 84 |
86 typedef std::map<std::string, const BrowserDescriptor*> DescriptorMap; | |
87 | |
88 static DescriptorMap FindInstalledBrowserPackages(const std::string& response) { | |
89 // Parse 'pm list packages' output which on Android looks like this: | |
90 // | |
91 // package:com.android.chrome | |
92 // package:com.chrome.beta | |
93 // package:com.example.app | |
94 // | |
95 DescriptorMap package_to_descriptor; | |
96 const std::string package_prefix = "package:"; | |
97 std::vector<std::string> entries; | |
98 Tokenize(response, "'\r\n", &entries); | |
99 for (size_t i = 0; i < entries.size(); ++i) { | |
100 if (entries[i].find(package_prefix) != 0) | |
101 continue; | |
102 std::string package = entries[i].substr(package_prefix.size()); | |
103 const BrowserDescriptor* descriptor = FindBrowserDescriptor(package); | |
104 if (!descriptor) | |
105 continue; | |
106 package_to_descriptor[descriptor->package] = descriptor; | |
107 } | |
108 return package_to_descriptor; | |
109 } | |
110 | |
111 typedef std::map<std::string, std::string> StringMap; | 85 typedef std::map<std::string, std::string> StringMap; |
112 | 86 |
113 static void MapProcessesToPackages(const std::string& response, | 87 static void MapProcessesToPackages(const std::string& response, |
114 StringMap& pid_to_package, | 88 StringMap& pid_to_package, |
115 StringMap& package_to_pid) { | 89 StringMap& package_to_pid) { |
116 // Parse 'ps' output which on Android looks like this: | 90 // Parse 'ps' output which on Android looks like this: |
117 // | 91 // |
118 // USER PID PPID VSIZE RSS WCHAN PC ? NAME | 92 // USER PID PPID VSIZE RSS WCHAN PC ? NAME |
119 // | 93 // |
120 std::vector<std::string> entries; | 94 std::vector<std::string> entries; |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 base::Bind(&AdbDeviceInfoQuery::ReceivedDumpsys, base::Unretained(this))); | 214 base::Bind(&AdbDeviceInfoQuery::ReceivedDumpsys, base::Unretained(this))); |
241 } | 215 } |
242 | 216 |
243 void AdbDeviceInfoQuery::ReceivedDumpsys(int result, | 217 void AdbDeviceInfoQuery::ReceivedDumpsys(int result, |
244 const std::string& response) { | 218 const std::string& response) { |
245 DCHECK(CalledOnValidThread()); | 219 DCHECK(CalledOnValidThread()); |
246 if (result >= 0) | 220 if (result >= 0) |
247 ParseDumpsysResponse(response); | 221 ParseDumpsysResponse(response); |
248 | 222 |
249 command_callback_.Run( | 223 command_callback_.Run( |
250 kInstalledChromePackagesCommand, | 224 kListProcessesCommand, |
251 base::Bind(&AdbDeviceInfoQuery::ReceivedPackages, | 225 base::Bind(&AdbDeviceInfoQuery::ReceivedProcesses, |
252 base::Unretained(this))); | 226 base::Unretained(this))); |
253 } | 227 } |
254 | 228 |
255 void AdbDeviceInfoQuery::ParseDumpsysResponse(const std::string& response) { | 229 void AdbDeviceInfoQuery::ParseDumpsysResponse(const std::string& response) { |
256 std::vector<std::string> lines; | 230 std::vector<std::string> lines; |
257 Tokenize(response, "\r", &lines); | 231 Tokenize(response, "\r", &lines); |
258 for (size_t i = 0; i < lines.size(); ++i) { | 232 for (size_t i = 0; i < lines.size(); ++i) { |
259 std::string line = lines[i]; | 233 std::string line = lines[i]; |
260 size_t pos = line.find(kDumpsysScreenSizePrefix); | 234 size_t pos = line.find(kDumpsysScreenSizePrefix); |
261 if (pos != std::string::npos) { | 235 if (pos != std::string::npos) { |
(...skipping 16 matching lines...) Expand all Loading... |
278 Tokenize(pairs[1].substr(1, pairs[1].size() - 2), ",", &numbers); | 252 Tokenize(pairs[1].substr(1, pairs[1].size() - 2), ",", &numbers); |
279 if (numbers.size() != 2 || | 253 if (numbers.size() != 2 || |
280 !base::StringToInt(numbers[0], &width) || | 254 !base::StringToInt(numbers[0], &width) || |
281 !base::StringToInt(numbers[1], &height)) | 255 !base::StringToInt(numbers[1], &height)) |
282 return; | 256 return; |
283 | 257 |
284 device_info_.screen_size = gfx::Size(width, height); | 258 device_info_.screen_size = gfx::Size(width, height); |
285 } | 259 } |
286 | 260 |
287 | 261 |
288 void AdbDeviceInfoQuery::ReceivedPackages( | |
289 int result, | |
290 const std::string& packages_response) { | |
291 DCHECK(CalledOnValidThread()); | |
292 if (result < 0) { | |
293 Respond(); | |
294 return; | |
295 } | |
296 command_callback_.Run( | |
297 kListProcessesCommand, | |
298 base::Bind(&AdbDeviceInfoQuery::ReceivedProcesses, | |
299 base::Unretained(this), packages_response)); | |
300 } | |
301 | |
302 void AdbDeviceInfoQuery::ReceivedProcesses( | 262 void AdbDeviceInfoQuery::ReceivedProcesses( |
303 const std::string& packages_response, | |
304 int result, | 263 int result, |
305 const std::string& processes_response) { | 264 const std::string& processes_response) { |
306 DCHECK(CalledOnValidThread()); | 265 DCHECK(CalledOnValidThread()); |
307 if (result < 0) { | 266 if (result < 0) { |
308 Respond(); | 267 Respond(); |
309 return; | 268 return; |
310 } | 269 } |
311 command_callback_.Run( | 270 command_callback_.Run( |
312 kOpenedUnixSocketsCommand, | 271 kOpenedUnixSocketsCommand, |
313 base::Bind(&AdbDeviceInfoQuery::ReceivedSockets, | 272 base::Bind(&AdbDeviceInfoQuery::ReceivedSockets, |
314 base::Unretained(this), | 273 base::Unretained(this), |
315 packages_response, | |
316 processes_response)); | 274 processes_response)); |
317 } | 275 } |
318 | 276 |
319 void AdbDeviceInfoQuery::ReceivedSockets( | 277 void AdbDeviceInfoQuery::ReceivedSockets( |
320 const std::string& packages_response, | |
321 const std::string& processes_response, | 278 const std::string& processes_response, |
322 int result, | 279 int result, |
323 const std::string& sockets_response) { | 280 const std::string& sockets_response) { |
324 DCHECK(CalledOnValidThread()); | 281 DCHECK(CalledOnValidThread()); |
325 if (result >= 0) | 282 if (result >= 0) |
326 ParseBrowserInfo(packages_response, processes_response, sockets_response); | 283 ParseBrowserInfo(processes_response, sockets_response); |
327 Respond(); | 284 Respond(); |
328 } | 285 } |
329 | 286 |
330 void AdbDeviceInfoQuery::ParseBrowserInfo( | 287 void AdbDeviceInfoQuery::ParseBrowserInfo( |
331 const std::string& packages_response, | |
332 const std::string& processes_response, | 288 const std::string& processes_response, |
333 const std::string& sockets_response) { | 289 const std::string& sockets_response) { |
334 DCHECK(CalledOnValidThread()); | 290 DCHECK(CalledOnValidThread()); |
335 DescriptorMap package_to_descriptor = | |
336 FindInstalledBrowserPackages(packages_response); | |
337 StringMap pid_to_package; | 291 StringMap pid_to_package; |
338 StringMap package_to_pid; | 292 StringMap package_to_pid; |
339 MapProcessesToPackages(processes_response, pid_to_package, package_to_pid); | 293 MapProcessesToPackages(processes_response, pid_to_package, package_to_pid); |
340 | 294 |
341 StringMap socket_to_pid = MapSocketsToProcesses(sockets_response, | 295 StringMap socket_to_pid = MapSocketsToProcesses(sockets_response, |
342 kDevToolsSocketSuffix); | 296 kDevToolsSocketSuffix); |
343 | 297 |
344 std::set<std::string> packages_for_running_browsers; | 298 std::set<std::string> packages_for_running_browsers; |
345 | 299 |
346 typedef std::map<std::string, int> BrowserMap; | 300 typedef std::map<std::string, int> BrowserMap; |
(...skipping 13 matching lines...) Expand all Loading... |
360 socket_to_unnamed_browser_index[socket] = | 314 socket_to_unnamed_browser_index[socket] = |
361 device_info_.browser_info.size(); | 315 device_info_.browser_info.size(); |
362 } | 316 } |
363 | 317 |
364 AndroidDeviceManager::BrowserInfo browser_info; | 318 AndroidDeviceManager::BrowserInfo browser_info; |
365 browser_info.socket_name = socket; | 319 browser_info.socket_name = socket; |
366 browser_info.type = GetBrowserType(socket); | 320 browser_info.type = GetBrowserType(socket); |
367 browser_info.display_name = GetDisplayName(socket, package); | 321 browser_info.display_name = GetDisplayName(socket, package); |
368 device_info_.browser_info.push_back(browser_info); | 322 device_info_.browser_info.push_back(browser_info); |
369 } | 323 } |
370 | |
371 // Find installed packages not mapped to browsers. | |
372 typedef std::multimap<std::string, const BrowserDescriptor*> | |
373 DescriptorMultimap; | |
374 DescriptorMultimap socket_to_descriptor; | |
375 for (DescriptorMap::iterator it = package_to_descriptor.begin(); | |
376 it != package_to_descriptor.end(); ++it) { | |
377 std::string package = it->first; | |
378 const BrowserDescriptor* descriptor = it->second; | |
379 | |
380 if (packages_for_running_browsers.count(package)) | |
381 continue; // This package is already mapped to a browser. | |
382 | |
383 if (package_to_pid.find(package) != package_to_pid.end()) { | |
384 // This package is running but not mapped to a browser. | |
385 socket_to_descriptor.insert( | |
386 DescriptorMultimap::value_type(descriptor->socket, descriptor)); | |
387 continue; | |
388 } | |
389 } | |
390 | |
391 // Try naming remaining unnamed browsers. | |
392 for (DescriptorMultimap::iterator it = socket_to_descriptor.begin(); | |
393 it != socket_to_descriptor.end(); ++it) { | |
394 std::string socket = it->first; | |
395 const BrowserDescriptor* descriptor = it->second; | |
396 | |
397 if (socket_to_descriptor.count(socket) != 1) | |
398 continue; // No definitive match. | |
399 | |
400 BrowserMap::iterator bit = socket_to_unnamed_browser_index.find(socket); | |
401 if (bit != socket_to_unnamed_browser_index.end()) { | |
402 device_info_.browser_info[bit->second].display_name = | |
403 descriptor->display_name; | |
404 } | |
405 } | |
406 } | 324 } |
407 | 325 |
408 void AdbDeviceInfoQuery::Respond() { | 326 void AdbDeviceInfoQuery::Respond() { |
409 DCHECK(CalledOnValidThread()); | 327 DCHECK(CalledOnValidThread()); |
410 callback_.Run(device_info_); | 328 callback_.Run(device_info_); |
411 delete this; | 329 delete this; |
412 } | 330 } |
OLD | NEW |