| 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 |