Chromium Code Reviews| 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/devtools_android_bridge.h" | 5 #include "chrome/browser/devtools/device/devtools_android_bridge.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/base64.h" | 10 #include "base/base64.h" |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
| 13 #include "base/json/json_reader.h" | 13 #include "base/json/json_reader.h" |
| 14 #include "base/lazy_instance.h" | 14 #include "base/lazy_instance.h" |
| 15 #include "base/message_loop/message_loop.h" | 15 #include "base/message_loop/message_loop.h" |
| 16 #include "base/prefs/pref_service.h" | 16 #include "base/prefs/pref_service.h" |
| 17 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
| 18 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 19 #include "base/strings/stringprintf.h" | 19 #include "base/strings/stringprintf.h" |
| 20 #include "base/strings/utf_string_conversions.h" | 20 #include "base/strings/utf_string_conversions.h" |
| 21 #include "base/threading/thread.h" | 21 #include "base/threading/thread.h" |
| 22 #include "base/values.h" | 22 #include "base/values.h" |
| 23 #include "chrome/browser/devtools/browser_list_tabcontents_provider.h" | 23 #include "chrome/browser/devtools/browser_list_tabcontents_provider.h" |
| 24 #include "chrome/browser/devtools/device/adb/adb_device_info_query.h" | |
| 24 #include "chrome/browser/devtools/device/adb/adb_device_provider.h" | 25 #include "chrome/browser/devtools/device/adb/adb_device_provider.h" |
| 25 #include "chrome/browser/devtools/device/self_device_provider.h" | 26 #include "chrome/browser/devtools/device/self_device_provider.h" |
| 26 #include "chrome/browser/devtools/device/usb/usb_device_provider.h" | 27 #include "chrome/browser/devtools/device/usb/usb_device_provider.h" |
| 27 #include "chrome/browser/devtools/devtools_protocol.h" | 28 #include "chrome/browser/devtools/devtools_protocol.h" |
| 28 #include "chrome/browser/devtools/devtools_target_impl.h" | 29 #include "chrome/browser/devtools/devtools_target_impl.h" |
| 29 #include "chrome/browser/devtools/devtools_window.h" | 30 #include "chrome/browser/devtools/devtools_window.h" |
| 30 #include "chrome/browser/profiles/profile.h" | 31 #include "chrome/browser/profiles/profile.h" |
| 31 #include "chrome/common/pref_names.h" | 32 #include "chrome/common/pref_names.h" |
| 32 #include "components/keyed_service/content/browser_context_dependency_manager.h" | 33 #include "components/keyed_service/content/browser_context_dependency_manager.h" |
| 33 #include "content/public/browser/devtools_agent_host.h" | 34 #include "content/public/browser/devtools_agent_host.h" |
| 34 #include "content/public/browser/devtools_external_agent_proxy.h" | 35 #include "content/public/browser/devtools_external_agent_proxy.h" |
| 35 #include "content/public/browser/devtools_external_agent_proxy_delegate.h" | 36 #include "content/public/browser/devtools_external_agent_proxy_delegate.h" |
| 36 #include "content/public/browser/user_metrics.h" | 37 #include "content/public/browser/user_metrics.h" |
| 37 #include "net/base/escape.h" | 38 #include "net/base/escape.h" |
| 38 | 39 |
| 39 using content::BrowserThread; | 40 using content::BrowserThread; |
| 40 | 41 |
| 41 namespace { | 42 namespace { |
| 42 | 43 |
| 43 const char kDeviceModelCommand[] = "shell:getprop ro.product.model"; | 44 const char kModelOffline[] = "Offline"; |
| 44 const char kInstalledChromePackagesCommand[] = "shell:pm list packages"; | |
| 45 const char kOpenedUnixSocketsCommand[] = "shell:cat /proc/net/unix"; | |
| 46 const char kListProcessesCommand[] = "shell:ps"; | |
| 47 const char kDumpsysCommand[] = "shell:dumpsys window policy"; | |
| 48 const char kDumpsysScreenSizePrefix[] = "mStable="; | |
| 49 | |
| 50 const char kUnknownModel[] = "Offline"; | |
| 51 | 45 |
| 52 const char kPageListRequest[] = "GET /json HTTP/1.1\r\n\r\n"; | 46 const char kPageListRequest[] = "GET /json HTTP/1.1\r\n\r\n"; |
| 53 const char kVersionRequest[] = "GET /json/version HTTP/1.1\r\n\r\n"; | 47 const char kVersionRequest[] = "GET /json/version HTTP/1.1\r\n\r\n"; |
| 54 const char kClosePageRequest[] = "GET /json/close/%s HTTP/1.1\r\n\r\n"; | 48 const char kClosePageRequest[] = "GET /json/close/%s HTTP/1.1\r\n\r\n"; |
| 55 const char kNewPageRequest[] = "GET /json/new HTTP/1.1\r\n\r\n"; | 49 const char kNewPageRequest[] = "GET /json/new HTTP/1.1\r\n\r\n"; |
| 56 const char kNewPageRequestWithURL[] = "GET /json/new?%s HTTP/1.1\r\n\r\n"; | 50 const char kNewPageRequestWithURL[] = "GET /json/new?%s HTTP/1.1\r\n\r\n"; |
| 57 const char kActivatePageRequest[] = | 51 const char kActivatePageRequest[] = |
| 58 "GET /json/activate/%s HTTP/1.1\r\n\r\n"; | 52 "GET /json/activate/%s HTTP/1.1\r\n\r\n"; |
| 59 const int kAdbPollingIntervalMs = 1000; | 53 const int kAdbPollingIntervalMs = 1000; |
| 60 | 54 |
| 61 const char kUrlParam[] = "url"; | 55 const char kUrlParam[] = "url"; |
| 62 const char kPageReloadCommand[] = "Page.reload"; | 56 const char kPageReloadCommand[] = "Page.reload"; |
| 63 const char kPageNavigateCommand[] = "Page.navigate"; | 57 const char kPageNavigateCommand[] = "Page.navigate"; |
| 64 | 58 |
| 65 // The format used for constructing DevTools server socket names. | |
| 66 const char kDevToolsChannelNameFormat[] = "%s_devtools_remote"; | |
| 67 | |
| 68 const char kChromeDefaultName[] = "Chrome"; | |
| 69 const char kChromeDefaultSocket[] = "chrome_devtools_remote"; | |
| 70 const int kMinVersionNewWithURL = 32; | 59 const int kMinVersionNewWithURL = 32; |
| 71 const int kNewPageNavigateDelayMs = 500; | 60 const int kNewPageNavigateDelayMs = 500; |
| 72 | 61 |
| 73 const char kWebViewSocketPrefix[] = "webview_devtools_remote"; | |
| 74 const char kWebViewNameTemplate[] = "WebView in %s"; | |
| 75 | |
| 76 struct BrowserDescriptor { | |
| 77 const char* package; | |
| 78 const char* socket; | |
| 79 const char* display_name; | |
| 80 }; | |
| 81 | |
| 82 const BrowserDescriptor kBrowserDescriptors[] = { | |
| 83 { | |
| 84 "com.android.chrome", | |
| 85 kChromeDefaultSocket, | |
| 86 kChromeDefaultName | |
| 87 }, | |
| 88 { | |
| 89 "com.chrome.beta", | |
| 90 kChromeDefaultSocket, | |
| 91 "Chrome Beta" | |
| 92 }, | |
| 93 { | |
| 94 "com.google.android.apps.chrome_dev", | |
| 95 kChromeDefaultSocket, | |
| 96 "Chrome Dev" | |
| 97 }, | |
| 98 { | |
| 99 "com.chrome.canary", | |
| 100 kChromeDefaultSocket, | |
| 101 "Chrome Canary" | |
| 102 }, | |
| 103 { | |
| 104 "com.google.android.apps.chrome", | |
| 105 kChromeDefaultSocket, | |
| 106 "Chromium" | |
| 107 }, | |
| 108 { | |
| 109 "org.chromium.content_shell_apk", | |
| 110 "content_shell_devtools_remote", | |
| 111 "Content Shell" | |
| 112 }, | |
| 113 { | |
| 114 "org.chromium.chrome.shell", | |
| 115 "chrome_shell_devtools_remote", | |
| 116 "Chrome Shell" | |
| 117 }, | |
| 118 { | |
| 119 "org.chromium.android_webview.shell", | |
| 120 "webview_devtools_remote", | |
| 121 "WebView Test Shell" | |
| 122 } | |
| 123 }; | |
| 124 | |
| 125 const BrowserDescriptor* FindBrowserDescriptor(const std::string& package) { | |
| 126 int count = sizeof(kBrowserDescriptors) / sizeof(kBrowserDescriptors[0]); | |
| 127 for (int i = 0; i < count; i++) | |
| 128 if (kBrowserDescriptors[i].package == package) | |
| 129 return &kBrowserDescriptors[i]; | |
| 130 return NULL; | |
| 131 } | |
| 132 | |
| 133 typedef std::map<std::string, const BrowserDescriptor*> DescriptorMap; | |
| 134 | |
| 135 static DescriptorMap FindInstalledBrowserPackages( | |
| 136 const std::string& response) { | |
| 137 // Parse 'pm list packages' output which on Android looks like this: | |
| 138 // | |
| 139 // package:com.android.chrome | |
| 140 // package:com.chrome.beta | |
| 141 // package:com.example.app | |
| 142 // | |
| 143 DescriptorMap package_to_descriptor; | |
| 144 const std::string package_prefix = "package:"; | |
| 145 std::vector<std::string> entries; | |
| 146 Tokenize(response, "'\r\n", &entries); | |
| 147 for (size_t i = 0; i < entries.size(); ++i) { | |
| 148 if (entries[i].find(package_prefix) != 0) | |
| 149 continue; | |
| 150 std::string package = entries[i].substr(package_prefix.size()); | |
| 151 const BrowserDescriptor* descriptor = FindBrowserDescriptor(package); | |
| 152 if (!descriptor) | |
| 153 continue; | |
| 154 package_to_descriptor[descriptor->package] = descriptor; | |
| 155 } | |
| 156 return package_to_descriptor; | |
| 157 } | |
| 158 | |
| 159 typedef std::map<std::string, std::string> StringMap; | |
| 160 | |
| 161 static void MapProcessesToPackages(const std::string& response, | |
| 162 StringMap& pid_to_package, | |
| 163 StringMap& package_to_pid) { | |
| 164 // Parse 'ps' output which on Android looks like this: | |
| 165 // | |
| 166 // USER PID PPID VSIZE RSS WCHAN PC ? NAME | |
| 167 // | |
| 168 std::vector<std::string> entries; | |
| 169 Tokenize(response, "\n", &entries); | |
| 170 for (size_t i = 1; i < entries.size(); ++i) { | |
| 171 std::vector<std::string> fields; | |
| 172 Tokenize(entries[i], " \r", &fields); | |
| 173 if (fields.size() < 9) | |
| 174 continue; | |
| 175 std::string pid = fields[1]; | |
| 176 std::string package = fields[8]; | |
| 177 pid_to_package[pid] = package; | |
| 178 package_to_pid[package] = pid; | |
| 179 } | |
| 180 } | |
| 181 | |
| 182 typedef std::map<std::string, | |
| 183 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> > | |
| 184 BrowserMap; | |
| 185 | |
| 186 static StringMap MapSocketsToProcesses(const std::string& response, | |
| 187 const std::string& channel_pattern) { | |
| 188 // Parse 'cat /proc/net/unix' output which on Android looks like this: | |
| 189 // | |
| 190 // Num RefCount Protocol Flags Type St Inode Path | |
| 191 // 00000000: 00000002 00000000 00010000 0001 01 331813 /dev/socket/zygote | |
| 192 // 00000000: 00000002 00000000 00010000 0001 01 358606 @xxx_devtools_remote | |
| 193 // 00000000: 00000002 00000000 00010000 0001 01 347300 @yyy_devtools_remote | |
| 194 // | |
| 195 // We need to find records with paths starting from '@' (abstract socket) | |
| 196 // and containing the channel pattern ("_devtools_remote"). | |
| 197 StringMap socket_to_pid; | |
| 198 std::vector<std::string> entries; | |
| 199 Tokenize(response, "\n", &entries); | |
| 200 for (size_t i = 1; i < entries.size(); ++i) { | |
| 201 std::vector<std::string> fields; | |
| 202 Tokenize(entries[i], " \r", &fields); | |
| 203 if (fields.size() < 8) | |
| 204 continue; | |
| 205 if (fields[3] != "00010000" || fields[5] != "01") | |
| 206 continue; | |
| 207 std::string path_field = fields[7]; | |
| 208 if (path_field.size() < 1 || path_field[0] != '@') | |
| 209 continue; | |
| 210 size_t socket_name_pos = path_field.find(channel_pattern); | |
| 211 if (socket_name_pos == std::string::npos) | |
| 212 continue; | |
| 213 | |
| 214 std::string socket = path_field.substr(1); | |
| 215 | |
| 216 std::string pid; | |
| 217 size_t socket_name_end = socket_name_pos + channel_pattern.size(); | |
| 218 if (socket_name_end < path_field.size() && | |
| 219 path_field[socket_name_end] == '_') { | |
| 220 pid = path_field.substr(socket_name_end + 1); | |
| 221 } | |
| 222 socket_to_pid[socket] = pid; | |
| 223 } | |
| 224 return socket_to_pid; | |
| 225 } | |
| 226 | |
| 227 // DiscoveryRequest ----------------------------------------------------- | 62 // DiscoveryRequest ----------------------------------------------------- |
| 228 | 63 |
| 229 class DiscoveryRequest : public base::RefCountedThreadSafe< | 64 class DiscoveryRequest : public base::RefCountedThreadSafe< |
| 230 DiscoveryRequest, | 65 DiscoveryRequest, |
| 231 BrowserThread::DeleteOnUIThread> { | 66 BrowserThread::DeleteOnUIThread> { |
| 232 public: | 67 public: |
| 233 typedef base::Callback<void(DevToolsAndroidBridge::RemoteDevices*)> Callback; | 68 typedef base::Callback<void(DevToolsAndroidBridge::RemoteDevices*)> Callback; |
| 234 | 69 |
| 235 DiscoveryRequest( | 70 DiscoveryRequest( |
| 236 scoped_refptr<DevToolsAndroidBridge> android_bridge, | 71 scoped_refptr<DevToolsAndroidBridge> android_bridge, |
| 237 AndroidDeviceManager* device_manager, | 72 AndroidDeviceManager* device_manager, |
| 238 base::MessageLoop* device_message_loop, | 73 base::MessageLoop* device_message_loop, |
| 239 const AndroidDeviceManager::DeviceProviders& device_providers, | 74 const AndroidDeviceManager::DeviceProviders& device_providers, |
| 240 const Callback& callback); | 75 const Callback& callback); |
| 241 | 76 |
| 242 private: | 77 private: |
| 243 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; | 78 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; |
| 244 friend class base::DeleteHelper<DiscoveryRequest>; | 79 friend class base::DeleteHelper<DiscoveryRequest>; |
| 245 | 80 |
| 246 virtual ~DiscoveryRequest(); | 81 virtual ~DiscoveryRequest(); |
| 247 | 82 |
| 248 void ReceivedSerials(const std::vector<std::string>& serials); | 83 void ReceivedSerials(const std::vector<std::string>& serials); |
| 249 void ProcessSerials(); | 84 void ProcessSerials(); |
| 250 void ReceivedModel(int result, const std::string& response); | 85 void ReceivedDeviceInfo(const AndroidDeviceManager::DeviceInfo& device_info); |
| 251 void ReceivedDumpsys(int result, const std::string& response); | |
| 252 void ReceivedPackages(int result, const std::string& response); | |
| 253 void ReceivedProcesses( | |
| 254 const std::string& packages_response, | |
| 255 int result, | |
| 256 const std::string& processes_response); | |
| 257 void ReceivedSockets( | |
| 258 const std::string& packages_response, | |
| 259 const std::string& processes_response, | |
| 260 int result, | |
| 261 const std::string& sockets_response); | |
| 262 void ProcessSockets(); | 86 void ProcessSockets(); |
| 263 void ReceivedVersion(int result, const std::string& response); | 87 void ReceivedVersion(int result, const std::string& response); |
| 264 void ReceivedPages(int result, const std::string& response); | 88 void ReceivedPages(int result, const std::string& response); |
| 265 | 89 |
| 266 std::string current_serial() const { return serials_.back(); } | 90 std::string current_serial() const { return serials_.back(); } |
| 267 | 91 |
| 268 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> current_browser() const { | 92 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> current_browser() const { |
| 269 return browsers_.back(); | 93 return browsers_.back(); |
| 270 } | 94 } |
| 271 | 95 |
| 272 void NextBrowser(); | 96 void NextBrowser(); |
| 273 void NextDevice(); | 97 void NextDevice(); |
| 274 | 98 |
| 275 void Respond(); | 99 void Respond(); |
| 276 | 100 |
| 277 void CreateBrowsers(const std::string& packages_response, | |
| 278 const std::string& processes_response, | |
| 279 const std::string& sockets_response); | |
| 280 | |
| 281 void ParseDumpsysResponse(const std::string& response); | |
| 282 void ParseScreenSize(const std::string& str); | |
| 283 | |
| 284 scoped_refptr<DevToolsAndroidBridge> android_bridge_; | 101 scoped_refptr<DevToolsAndroidBridge> android_bridge_; |
| 285 AndroidDeviceManager* device_manager_; | 102 AndroidDeviceManager* device_manager_; |
| 286 base::MessageLoop* device_message_loop_; | 103 base::MessageLoop* device_message_loop_; |
| 287 Callback callback_; | 104 Callback callback_; |
| 288 std::vector<std::string> serials_; | 105 std::vector<std::string> serials_; |
| 289 DevToolsAndroidBridge::RemoteBrowsers browsers_; | 106 DevToolsAndroidBridge::RemoteBrowsers browsers_; |
| 290 scoped_ptr<DevToolsAndroidBridge::RemoteDevices> remote_devices_; | 107 scoped_ptr<DevToolsAndroidBridge::RemoteDevices> remote_devices_; |
| 291 }; | 108 }; |
| 292 | 109 |
| 293 DiscoveryRequest::DiscoveryRequest( | 110 DiscoveryRequest::DiscoveryRequest( |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 324 void DiscoveryRequest::ProcessSerials() { | 141 void DiscoveryRequest::ProcessSerials() { |
| 325 DCHECK_EQ(device_message_loop_, base::MessageLoop::current()); | 142 DCHECK_EQ(device_message_loop_, base::MessageLoop::current()); |
| 326 if (serials_.size() == 0) { | 143 if (serials_.size() == 0) { |
| 327 BrowserThread::PostTask( | 144 BrowserThread::PostTask( |
| 328 BrowserThread::UI, FROM_HERE, | 145 BrowserThread::UI, FROM_HERE, |
| 329 base::Bind(&DiscoveryRequest::Respond, this)); | 146 base::Bind(&DiscoveryRequest::Respond, this)); |
| 330 return; | 147 return; |
| 331 } | 148 } |
| 332 | 149 |
| 333 if (device_manager_->IsConnected(current_serial())) { | 150 if (device_manager_->IsConnected(current_serial())) { |
| 334 device_manager_->RunCommand(current_serial(), kDeviceModelCommand, | 151 device_manager_->QueryDeviceInfo(current_serial(), |
| 335 base::Bind(&DiscoveryRequest::ReceivedModel, this)); | 152 base::Bind(&DiscoveryRequest::ReceivedDeviceInfo, this)); |
| 336 } else { | 153 } else { |
| 154 AndroidDeviceManager::DeviceInfo offline_info; | |
| 155 offline_info.model = kModelOffline; | |
| 337 remote_devices_->push_back(new DevToolsAndroidBridge::RemoteDevice( | 156 remote_devices_->push_back(new DevToolsAndroidBridge::RemoteDevice( |
| 338 android_bridge_, current_serial(), kUnknownModel, false)); | 157 android_bridge_, current_serial(), offline_info, false)); |
| 339 NextDevice(); | 158 NextDevice(); |
| 340 } | 159 } |
| 341 } | 160 } |
| 342 | 161 |
| 343 void DiscoveryRequest::ReceivedModel(int result, const std::string& response) { | 162 void DiscoveryRequest::ReceivedDeviceInfo( |
| 344 DCHECK_EQ(device_message_loop_, base::MessageLoop::current()); | 163 const AndroidDeviceManager::DeviceInfo& device_info) { |
| 345 if (result < 0) { | |
| 346 NextDevice(); | |
| 347 return; | |
| 348 } | |
| 349 remote_devices_->push_back(new DevToolsAndroidBridge::RemoteDevice( | 164 remote_devices_->push_back(new DevToolsAndroidBridge::RemoteDevice( |
| 350 android_bridge_, current_serial(), response, true)); | 165 android_bridge_, current_serial(), device_info, true)); |
| 351 device_manager_->RunCommand(current_serial(), kDumpsysCommand, | 166 browsers_ = remote_devices_->back()->browsers(); |
| 352 base::Bind(&DiscoveryRequest::ReceivedDumpsys, this)); | |
| 353 } | |
| 354 | |
| 355 void DiscoveryRequest::ReceivedDumpsys(int result, | |
| 356 const std::string& response) { | |
| 357 DCHECK_EQ(device_message_loop_, base::MessageLoop::current()); | |
| 358 if (result >= 0) | |
| 359 ParseDumpsysResponse(response); | |
| 360 | |
| 361 device_manager_->RunCommand( | |
| 362 current_serial(), | |
| 363 kInstalledChromePackagesCommand, | |
| 364 base::Bind(&DiscoveryRequest::ReceivedPackages, this)); | |
| 365 } | |
| 366 | |
| 367 void DiscoveryRequest::ReceivedPackages(int result, | |
| 368 const std::string& packages_response) { | |
| 369 DCHECK_EQ(device_message_loop_, base::MessageLoop::current()); | |
| 370 if (result < 0) { | |
| 371 NextDevice(); | |
| 372 return; | |
| 373 } | |
| 374 device_manager_->RunCommand( | |
| 375 current_serial(), | |
| 376 kListProcessesCommand, | |
| 377 base::Bind( | |
| 378 &DiscoveryRequest::ReceivedProcesses, this, packages_response)); | |
| 379 } | |
| 380 | |
| 381 void DiscoveryRequest::ReceivedProcesses( | |
| 382 const std::string& packages_response, | |
| 383 int result, | |
| 384 const std::string& processes_response) { | |
| 385 DCHECK_EQ(device_message_loop_, base::MessageLoop::current()); | |
| 386 if (result < 0) { | |
| 387 NextDevice(); | |
| 388 return; | |
| 389 } | |
| 390 device_manager_->RunCommand( | |
| 391 current_serial(), | |
| 392 kOpenedUnixSocketsCommand, | |
| 393 base::Bind(&DiscoveryRequest::ReceivedSockets, | |
| 394 this, | |
| 395 packages_response, | |
| 396 processes_response)); | |
| 397 } | |
| 398 | |
| 399 void DiscoveryRequest::ReceivedSockets( | |
| 400 const std::string& packages_response, | |
| 401 const std::string& processes_response, | |
| 402 int result, | |
| 403 const std::string& sockets_response) { | |
| 404 DCHECK_EQ(device_message_loop_, base::MessageLoop::current()); | |
| 405 if (result >= 0) | |
| 406 CreateBrowsers(packages_response, processes_response, sockets_response); | |
| 407 ProcessSockets(); | 167 ProcessSockets(); |
| 408 } | 168 } |
| 409 | 169 |
| 410 void DiscoveryRequest::ProcessSockets() { | 170 void DiscoveryRequest::ProcessSockets() { |
| 411 DCHECK_EQ(device_message_loop_, base::MessageLoop::current()); | 171 DCHECK_EQ(device_message_loop_, base::MessageLoop::current()); |
| 412 if (browsers_.size() == 0) { | 172 if (browsers_.size() == 0) { |
| 413 NextDevice(); | 173 NextDevice(); |
| 414 return; | 174 return; |
| 415 } | 175 } |
| 416 | 176 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 437 if (dict->GetString("Browser", &browser)) { | 197 if (dict->GetString("Browser", &browser)) { |
| 438 std::vector<std::string> parts; | 198 std::vector<std::string> parts; |
| 439 Tokenize(browser, "/", &parts); | 199 Tokenize(browser, "/", &parts); |
| 440 if (parts.size() == 2) | 200 if (parts.size() == 2) |
| 441 current_browser()->set_version(parts[1]); | 201 current_browser()->set_version(parts[1]); |
| 442 else | 202 else |
| 443 current_browser()->set_version(browser); | 203 current_browser()->set_version(browser); |
| 444 } | 204 } |
| 445 std::string package; | 205 std::string package; |
| 446 if (dict->GetString("Android-Package", &package)) { | 206 if (dict->GetString("Android-Package", &package)) { |
| 447 const BrowserDescriptor* descriptor = FindBrowserDescriptor(package); | 207 std::string display_name = |
| 448 if (descriptor) | 208 AdbDeviceInfoQuery::FindDisplayNameByPackage(package); |
|
pfeldman
2014/05/13 12:44:58
This is confusing. Why do you need to convert pack
Vladislav Kaznacheev
2014/05/15 13:56:34
Newer versions of Chrome on Android report their p
| |
| 449 current_browser()->set_display_name(descriptor->display_name); | 209 if (!display_name.empty()) |
| 210 current_browser()->set_display_name(display_name); | |
| 450 } | 211 } |
| 451 } | 212 } |
| 452 | 213 |
| 453 device_manager_->HttpQuery( | 214 device_manager_->HttpQuery( |
| 454 current_serial(), | 215 current_serial(), |
| 455 current_browser()->socket(), | 216 current_browser()->socket(), |
| 456 kPageListRequest, | 217 kPageListRequest, |
| 457 base::Bind(&DiscoveryRequest::ReceivedPages, this)); | 218 base::Bind(&DiscoveryRequest::ReceivedPages, this)); |
| 458 } | 219 } |
| 459 | 220 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 476 | 237 |
| 477 void DiscoveryRequest::NextDevice() { | 238 void DiscoveryRequest::NextDevice() { |
| 478 serials_.pop_back(); | 239 serials_.pop_back(); |
| 479 ProcessSerials(); | 240 ProcessSerials(); |
| 480 } | 241 } |
| 481 | 242 |
| 482 void DiscoveryRequest::Respond() { | 243 void DiscoveryRequest::Respond() { |
| 483 callback_.Run(remote_devices_.release()); | 244 callback_.Run(remote_devices_.release()); |
| 484 } | 245 } |
| 485 | 246 |
| 486 void DiscoveryRequest::CreateBrowsers( | |
| 487 const std::string& packages_response, | |
| 488 const std::string& processes_response, | |
| 489 const std::string& sockets_response) { | |
| 490 DescriptorMap package_to_descriptor = | |
| 491 FindInstalledBrowserPackages(packages_response); | |
| 492 | |
| 493 StringMap pid_to_package; | |
| 494 StringMap package_to_pid; | |
| 495 MapProcessesToPackages(processes_response, pid_to_package, package_to_pid); | |
| 496 | |
| 497 const std::string channel_pattern = | |
| 498 base::StringPrintf(kDevToolsChannelNameFormat, ""); | |
| 499 | |
| 500 StringMap socket_to_pid = MapSocketsToProcesses(sockets_response, | |
| 501 channel_pattern); | |
| 502 | |
| 503 scoped_refptr<DevToolsAndroidBridge::RemoteDevice> remote_device = | |
| 504 remote_devices_->back(); | |
| 505 | |
| 506 // Create RemoteBrowser instances. | |
| 507 BrowserMap package_to_running_browser; | |
| 508 BrowserMap socket_to_unnamed_browser; | |
| 509 for (StringMap::iterator it = socket_to_pid.begin(); | |
| 510 it != socket_to_pid.end(); ++it) { | |
| 511 std::string socket = it->first; | |
| 512 std::string pid = it->second; | |
| 513 | |
| 514 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser = | |
| 515 new DevToolsAndroidBridge::RemoteBrowser( | |
| 516 android_bridge_, current_serial(), socket); | |
| 517 | |
| 518 StringMap::iterator pit = pid_to_package.find(pid); | |
| 519 if (pit != pid_to_package.end()) { | |
| 520 std::string package = pit->second; | |
| 521 package_to_running_browser[package] = browser; | |
| 522 const BrowserDescriptor* descriptor = FindBrowserDescriptor(package); | |
| 523 if (descriptor) { | |
| 524 browser->set_display_name(descriptor->display_name); | |
| 525 } else if (socket.find(kWebViewSocketPrefix) == 0) { | |
| 526 browser->set_display_name( | |
| 527 base::StringPrintf(kWebViewNameTemplate, package.c_str())); | |
| 528 } else { | |
| 529 browser->set_display_name(package); | |
| 530 } | |
| 531 } else { | |
| 532 // Set fallback display name. | |
| 533 std::string name = socket.substr(0, socket.find(channel_pattern)); | |
| 534 name[0] = base::ToUpperASCII(name[0]); | |
| 535 browser->set_display_name(name); | |
| 536 | |
| 537 socket_to_unnamed_browser[socket] = browser; | |
| 538 } | |
| 539 remote_device->AddBrowser(browser); | |
| 540 } | |
| 541 | |
| 542 browsers_ = remote_device->browsers(); | |
| 543 | |
| 544 // Find installed packages not mapped to browsers. | |
| 545 typedef std::multimap<std::string, const BrowserDescriptor*> | |
| 546 DescriptorMultimap; | |
| 547 DescriptorMultimap socket_to_descriptor; | |
| 548 for (DescriptorMap::iterator it = package_to_descriptor.begin(); | |
| 549 it != package_to_descriptor.end(); ++it) { | |
| 550 std::string package = it->first; | |
| 551 const BrowserDescriptor* descriptor = it->second; | |
| 552 | |
| 553 if (package_to_running_browser.find(package) != | |
| 554 package_to_running_browser.end()) | |
| 555 continue; // This package is already mapped to a browser. | |
| 556 | |
| 557 if (package_to_pid.find(package) != package_to_pid.end()) { | |
| 558 // This package is running but not mapped to a browser. | |
| 559 socket_to_descriptor.insert( | |
| 560 DescriptorMultimap::value_type(descriptor->socket, descriptor)); | |
| 561 continue; | |
| 562 } | |
| 563 } | |
| 564 | |
| 565 // Try naming remaining unnamed browsers. | |
| 566 for (DescriptorMultimap::iterator it = socket_to_descriptor.begin(); | |
| 567 it != socket_to_descriptor.end(); ++it) { | |
| 568 std::string socket = it->first; | |
| 569 const BrowserDescriptor* descriptor = it->second; | |
| 570 | |
| 571 if (socket_to_descriptor.count(socket) != 1) | |
| 572 continue; // No definitive match. | |
| 573 | |
| 574 BrowserMap::iterator bit = socket_to_unnamed_browser.find(socket); | |
| 575 if (bit != socket_to_unnamed_browser.end()) | |
| 576 bit->second->set_display_name(descriptor->display_name); | |
| 577 } | |
| 578 } | |
| 579 | |
| 580 void DiscoveryRequest::ParseDumpsysResponse(const std::string& response) { | |
| 581 std::vector<std::string> lines; | |
| 582 Tokenize(response, "\r", &lines); | |
| 583 for (size_t i = 0; i < lines.size(); ++i) { | |
| 584 std::string line = lines[i]; | |
| 585 size_t pos = line.find(kDumpsysScreenSizePrefix); | |
| 586 if (pos != std::string::npos) { | |
| 587 ParseScreenSize( | |
| 588 line.substr(pos + std::string(kDumpsysScreenSizePrefix).size())); | |
| 589 break; | |
| 590 } | |
| 591 } | |
| 592 } | |
| 593 | |
| 594 void DiscoveryRequest::ParseScreenSize(const std::string& str) { | |
| 595 std::vector<std::string> pairs; | |
| 596 Tokenize(str, "-", &pairs); | |
| 597 if (pairs.size() != 2) | |
| 598 return; | |
| 599 | |
| 600 int width; | |
| 601 int height; | |
| 602 std::vector<std::string> numbers; | |
| 603 Tokenize(pairs[1].substr(1, pairs[1].size() - 2), ",", &numbers); | |
| 604 if (numbers.size() != 2 || | |
| 605 !base::StringToInt(numbers[0], &width) || | |
| 606 !base::StringToInt(numbers[1], &height)) | |
| 607 return; | |
| 608 | |
| 609 remote_devices_->back()->set_screen_size(gfx::Size(width, height)); | |
| 610 } | |
| 611 | |
| 612 | |
| 613 // ProtocolCommand ------------------------------------------------------------ | 247 // ProtocolCommand ------------------------------------------------------------ |
| 614 | 248 |
| 615 class ProtocolCommand | 249 class ProtocolCommand |
| 616 : public DevToolsAndroidBridge::AndroidWebSocket::Delegate { | 250 : public DevToolsAndroidBridge::AndroidWebSocket::Delegate { |
| 617 public: | 251 public: |
| 618 ProtocolCommand( | 252 ProtocolCommand( |
| 619 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser, | 253 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser, |
| 620 const std::string& debug_url, | 254 const std::string& debug_url, |
| 621 const std::string& command, | 255 const std::string& command, |
| 622 const base::Closure callback); | 256 const base::Closure callback); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 755 return delegate->proxy_->GetAgentHost(); | 389 return delegate->proxy_->GetAgentHost(); |
| 756 } | 390 } |
| 757 | 391 |
| 758 AgentHostDelegate::AgentHostDelegate( | 392 AgentHostDelegate::AgentHostDelegate( |
| 759 const std::string& id, | 393 const std::string& id, |
| 760 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser, | 394 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser, |
| 761 const std::string& debug_url) | 395 const std::string& debug_url) |
| 762 : id_(id), | 396 : id_(id), |
| 763 socket_opened_(false), | 397 socket_opened_(false), |
| 764 detached_(false), | 398 detached_(false), |
| 765 is_web_view_(browser->socket().find(kWebViewSocketPrefix) == 0), | 399 is_web_view_(browser->IsWebView()), |
| 766 web_socket_(browser->CreateWebSocket(debug_url, this)), | 400 web_socket_(browser->CreateWebSocket(debug_url, this)), |
| 767 proxy_(content::DevToolsExternalAgentProxy::Create(this)) { | 401 proxy_(content::DevToolsExternalAgentProxy::Create(this)) { |
| 768 g_host_delegates.Get()[id] = this; | 402 g_host_delegates.Get()[id] = this; |
| 769 } | 403 } |
| 770 | 404 |
| 771 AgentHostDelegate::~AgentHostDelegate() { | 405 AgentHostDelegate::~AgentHostDelegate() { |
| 772 g_host_delegates.Get().erase(id_); | 406 g_host_delegates.Get().erase(id_); |
| 773 } | 407 } |
| 774 | 408 |
| 775 void AgentHostDelegate::Attach() { | 409 void AgentHostDelegate::Attach() { |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 944 params.SetString(kUrlParam, url); | 578 params.SetString(kUrlParam, url); |
| 945 browser_->SendProtocolCommand(debug_url_, kPageNavigateCommand, ¶ms, | 579 browser_->SendProtocolCommand(debug_url_, kPageNavigateCommand, ¶ms, |
| 946 callback); | 580 callback); |
| 947 } | 581 } |
| 948 | 582 |
| 949 // DevToolsAndroidBridge::RemoteBrowser --------------------------------------- | 583 // DevToolsAndroidBridge::RemoteBrowser --------------------------------------- |
| 950 | 584 |
| 951 DevToolsAndroidBridge::RemoteBrowser::RemoteBrowser( | 585 DevToolsAndroidBridge::RemoteBrowser::RemoteBrowser( |
| 952 scoped_refptr<DevToolsAndroidBridge> android_bridge, | 586 scoped_refptr<DevToolsAndroidBridge> android_bridge, |
| 953 const std::string& serial, | 587 const std::string& serial, |
| 954 const std::string& socket) | 588 const AndroidDeviceManager::BrowserInfo& browser_info) |
| 955 : android_bridge_(android_bridge), | 589 : android_bridge_(android_bridge), |
| 956 serial_(serial), | 590 serial_(serial), |
| 957 socket_(socket), | 591 socket_(browser_info.socket), |
| 592 display_name_(browser_info.display_name), | |
| 593 type_(browser_info.type), | |
| 958 page_descriptors_(new base::ListValue()) { | 594 page_descriptors_(new base::ListValue()) { |
| 959 } | 595 } |
| 960 | 596 |
| 961 bool DevToolsAndroidBridge::RemoteBrowser::IsChrome() const { | 597 bool DevToolsAndroidBridge::RemoteBrowser::IsChrome() const { |
| 962 return socket_.find(kChromeDefaultSocket) == 0; | 598 return type_ == AndroidDeviceManager::BrowserInfo::kTypeChrome; |
| 599 } | |
| 600 | |
| 601 bool DevToolsAndroidBridge::RemoteBrowser::IsWebView() const { | |
| 602 return type_ == AndroidDeviceManager::BrowserInfo::kTypeWebView; | |
| 963 } | 603 } |
| 964 | 604 |
| 965 DevToolsAndroidBridge::RemoteBrowser::ParsedVersion | 605 DevToolsAndroidBridge::RemoteBrowser::ParsedVersion |
| 966 DevToolsAndroidBridge::RemoteBrowser::GetParsedVersion() const { | 606 DevToolsAndroidBridge::RemoteBrowser::GetParsedVersion() const { |
| 967 ParsedVersion result; | 607 ParsedVersion result; |
| 968 std::vector<std::string> parts; | 608 std::vector<std::string> parts; |
| 969 Tokenize(version_, ".", &parts); | 609 Tokenize(version_, ".", &parts); |
| 970 for (size_t i = 0; i != parts.size(); ++i) { | 610 for (size_t i = 0; i != parts.size(); ++i) { |
| 971 int value = 0; | 611 int value = 0; |
| 972 base::StringToInt(parts[i], &value); | 612 base::StringToInt(parts[i], &value); |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1112 | 752 |
| 1113 DevToolsAndroidBridge::RemoteBrowser::~RemoteBrowser() { | 753 DevToolsAndroidBridge::RemoteBrowser::~RemoteBrowser() { |
| 1114 } | 754 } |
| 1115 | 755 |
| 1116 | 756 |
| 1117 // DevToolsAndroidBridge::RemoteDevice ---------------------------------------- | 757 // DevToolsAndroidBridge::RemoteDevice ---------------------------------------- |
| 1118 | 758 |
| 1119 DevToolsAndroidBridge::RemoteDevice::RemoteDevice( | 759 DevToolsAndroidBridge::RemoteDevice::RemoteDevice( |
| 1120 scoped_refptr<DevToolsAndroidBridge> android_bridge, | 760 scoped_refptr<DevToolsAndroidBridge> android_bridge, |
| 1121 const std::string& serial, | 761 const std::string& serial, |
| 1122 const std::string& model, | 762 const AndroidDeviceManager::DeviceInfo& device_info, |
| 1123 bool connected) | 763 bool connected) |
| 1124 : android_bridge_(android_bridge), | 764 : android_bridge_(android_bridge), |
| 1125 serial_(serial), | 765 serial_(serial), |
| 1126 model_(model), | 766 model_(device_info.model), |
| 1127 connected_(connected) { | 767 connected_(connected), |
| 1128 } | 768 screen_size_(device_info.screen_size) { |
| 1129 | 769 for (std::vector<AndroidDeviceManager::BrowserInfo>::const_iterator it = |
| 1130 void DevToolsAndroidBridge::RemoteDevice::AddBrowser( | 770 device_info.browser_info.begin(); |
| 1131 scoped_refptr<RemoteBrowser> browser) { | 771 it != device_info.browser_info.end(); |
| 1132 browsers_.push_back(browser); | 772 ++it) { |
| 773 browsers_.push_back(new DevToolsAndroidBridge::RemoteBrowser( | |
| 774 android_bridge_, serial_, *it)); | |
| 775 } | |
| 1133 } | 776 } |
| 1134 | 777 |
| 1135 void DevToolsAndroidBridge::RemoteDevice::OpenSocket( | 778 void DevToolsAndroidBridge::RemoteDevice::OpenSocket( |
| 1136 const std::string& socket_name, | 779 const std::string& socket_name, |
| 1137 const AndroidDeviceManager::SocketCallback& callback) { | 780 const AndroidDeviceManager::SocketCallback& callback) { |
| 1138 android_bridge_->device_message_loop()->PostTask(FROM_HERE, | 781 android_bridge_->device_message_loop()->PostTask(FROM_HERE, |
| 1139 base::Bind(&AndroidDeviceManager::OpenSocket, | 782 base::Bind(&AndroidDeviceManager::OpenSocket, |
| 1140 android_bridge_->device_manager(), | 783 android_bridge_->device_manager(), |
| 1141 serial_, | 784 serial_, |
| 1142 socket_name, | 785 socket_name, |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1350 PrefService* service = profile_->GetPrefs(); | 993 PrefService* service = profile_->GetPrefs(); |
| 1351 const PrefService::Preference* pref = | 994 const PrefService::Preference* pref = |
| 1352 service->FindPreference(prefs::kDevToolsDiscoverUsbDevicesEnabled); | 995 service->FindPreference(prefs::kDevToolsDiscoverUsbDevicesEnabled); |
| 1353 const base::Value* pref_value = pref->GetValue(); | 996 const base::Value* pref_value = pref->GetValue(); |
| 1354 | 997 |
| 1355 bool enabled; | 998 bool enabled; |
| 1356 if (pref_value->GetAsBoolean(&enabled) && enabled) { | 999 if (pref_value->GetAsBoolean(&enabled) && enabled) { |
| 1357 device_providers_.push_back(new UsbDeviceProvider(profile_)); | 1000 device_providers_.push_back(new UsbDeviceProvider(profile_)); |
| 1358 } | 1001 } |
| 1359 } | 1002 } |
| OLD | NEW |