| 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 <stddef.h> | 7 #include <stddef.h> |
| 8 #include <algorithm> | 8 #include <algorithm> |
| 9 #include <map> | 9 #include <map> |
| 10 #include <set> | 10 #include <set> |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 | 53 |
| 54 #if BUILDFLAG(ENABLE_SERVICE_DISCOVERY) | 54 #if BUILDFLAG(ENABLE_SERVICE_DISCOVERY) |
| 55 #include "chrome/browser/devtools/device/cast_device_provider.h" | 55 #include "chrome/browser/devtools/device/cast_device_provider.h" |
| 56 #endif | 56 #endif |
| 57 | 57 |
| 58 using content::BrowserThread; | 58 using content::BrowserThread; |
| 59 using content::DevToolsAgentHost; | 59 using content::DevToolsAgentHost; |
| 60 | 60 |
| 61 namespace { | 61 namespace { |
| 62 | 62 |
| 63 const char kPageListRequest[] = "/json"; | |
| 64 const char kVersionRequest[] = "/json/version"; | |
| 65 const char kClosePageRequest[] = "/json/close/%s"; | |
| 66 const char kNewPageRequestWithURL[] = "/json/new?%s"; | 63 const char kNewPageRequestWithURL[] = "/json/new?%s"; |
| 67 const char kActivatePageRequest[] = "/json/activate/%s"; | |
| 68 const char kBrowserTargetSocket[] = "/devtools/browser"; | |
| 69 const int kAdbPollingIntervalMs = 1000; | |
| 70 | |
| 71 const char kPageReloadCommand[] = "Page.reload"; | |
| 72 | |
| 73 const char kWebViewSocketPrefix[] = "webview_devtools_remote"; | |
| 74 | |
| 75 const char kChromeDiscoveryURL[] = "localhost:9222"; | 64 const char kChromeDiscoveryURL[] = "localhost:9222"; |
| 76 const char kNodeDiscoveryURL[] = "localhost:9229"; | 65 const char kNodeDiscoveryURL[] = "localhost:9229"; |
| 77 | 66 |
| 78 bool BrowserIdFromString(const std::string& browser_id_str, | 67 bool BrowserIdFromString(const std::string& browser_id_str, |
| 79 std::string* serial, | 68 std::string* serial, |
| 80 std::string* browser_id) { | 69 std::string* browser_id) { |
| 81 size_t colon_pos = browser_id_str.find(':'); | 70 size_t colon_pos = browser_id_str.find(':'); |
| 82 if (colon_pos == std::string::npos) | 71 if (colon_pos == std::string::npos) |
| 83 return false; | 72 return false; |
| 84 *serial = browser_id_str.substr(0, colon_pos); | 73 *serial = browser_id_str.substr(0, colon_pos); |
| 85 *browser_id = browser_id_str.substr(colon_pos + 1); | 74 *browser_id = browser_id_str.substr(colon_pos + 1); |
| 86 return true; | 75 return true; |
| 87 } | 76 } |
| 88 | 77 |
| 89 static void NoOp(int, const std::string&) {} | 78 static void NoOp(int, const std::string&) {} |
| 90 | 79 |
| 91 } // namespace | 80 } // namespace |
| 92 | 81 |
| 93 // DiscoveryRequest ----------------------------------------------------- | |
| 94 | |
| 95 class DevToolsAndroidBridge::DiscoveryRequest | |
| 96 : public base::RefCountedThreadSafe<DiscoveryRequest, | |
| 97 BrowserThread::DeleteOnUIThread> { | |
| 98 public: | |
| 99 DiscoveryRequest(AndroidDeviceManager* device_manager, | |
| 100 const DeviceListCallback& callback); | |
| 101 private: | |
| 102 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; | |
| 103 friend class base::DeleteHelper<DiscoveryRequest>; | |
| 104 virtual ~DiscoveryRequest(); | |
| 105 | |
| 106 void ReceivedDevices(const AndroidDeviceManager::Devices& devices); | |
| 107 void ReceivedDeviceInfo(scoped_refptr<AndroidDeviceManager::Device> device, | |
| 108 const AndroidDeviceManager::DeviceInfo& device_info); | |
| 109 void ReceivedVersion(scoped_refptr<RemoteBrowser>, | |
| 110 int result, | |
| 111 const std::string& response); | |
| 112 void ReceivedPages(scoped_refptr<AndroidDeviceManager::Device> device, | |
| 113 scoped_refptr<RemoteBrowser>, | |
| 114 int result, | |
| 115 const std::string& response); | |
| 116 | |
| 117 DeviceListCallback callback_; | |
| 118 CompleteDevices complete_devices_; | |
| 119 }; | |
| 120 | |
| 121 DevToolsAndroidBridge::DiscoveryRequest::DiscoveryRequest( | |
| 122 AndroidDeviceManager* device_manager, | |
| 123 const DeviceListCallback& callback) | |
| 124 : callback_(callback) { | |
| 125 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 126 device_manager->QueryDevices( | |
| 127 base::Bind(&DiscoveryRequest::ReceivedDevices, this)); | |
| 128 } | |
| 129 | |
| 130 DevToolsAndroidBridge::DiscoveryRequest::~DiscoveryRequest() { | |
| 131 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 132 callback_.Run(complete_devices_); | |
| 133 } | |
| 134 | |
| 135 void DevToolsAndroidBridge::DiscoveryRequest::ReceivedDevices( | |
| 136 const AndroidDeviceManager::Devices& devices) { | |
| 137 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 138 for (const auto& device : devices) { | |
| 139 device->QueryDeviceInfo( | |
| 140 base::Bind(&DiscoveryRequest::ReceivedDeviceInfo, this, device)); | |
| 141 } | |
| 142 } | |
| 143 | |
| 144 void DevToolsAndroidBridge::DiscoveryRequest::ReceivedDeviceInfo( | |
| 145 scoped_refptr<AndroidDeviceManager::Device> device, | |
| 146 const AndroidDeviceManager::DeviceInfo& device_info) { | |
| 147 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 148 scoped_refptr<RemoteDevice> remote_device = | |
| 149 new RemoteDevice(device->serial(), device_info); | |
| 150 complete_devices_.push_back(std::make_pair(device, remote_device)); | |
| 151 for (RemoteBrowsers::iterator it = remote_device->browsers().begin(); | |
| 152 it != remote_device->browsers().end(); ++it) { | |
| 153 device->SendJsonRequest( | |
| 154 (*it)->socket(), | |
| 155 kVersionRequest, | |
| 156 base::Bind(&DiscoveryRequest::ReceivedVersion, this, *it)); | |
| 157 device->SendJsonRequest( | |
| 158 (*it)->socket(), | |
| 159 kPageListRequest, | |
| 160 base::Bind(&DiscoveryRequest::ReceivedPages, this, device, *it)); | |
| 161 } | |
| 162 } | |
| 163 | |
| 164 void DevToolsAndroidBridge::DiscoveryRequest::ReceivedVersion( | |
| 165 scoped_refptr<RemoteBrowser> browser, | |
| 166 int result, | |
| 167 const std::string& response) { | |
| 168 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 169 if (result < 0) | |
| 170 return; | |
| 171 // Parse version, append to package name if available, | |
| 172 std::unique_ptr<base::Value> value = base::JSONReader::Read(response); | |
| 173 base::DictionaryValue* dict; | |
| 174 if (value && value->GetAsDictionary(&dict)) { | |
| 175 std::string browser_name; | |
| 176 if (dict->GetString("Browser", &browser_name)) { | |
| 177 std::vector<std::string> parts = base::SplitString( | |
| 178 browser_name, "/", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); | |
| 179 if (parts.size() == 2) | |
| 180 browser->version_ = parts[1]; | |
| 181 else | |
| 182 browser->version_ = browser_name; | |
| 183 } | |
| 184 std::string package; | |
| 185 if (dict->GetString("Android-Package", &package)) { | |
| 186 browser->display_name_ = | |
| 187 AndroidDeviceManager::GetBrowserName(browser->socket(), package); | |
| 188 } | |
| 189 } | |
| 190 } | |
| 191 | |
| 192 void DevToolsAndroidBridge::DiscoveryRequest::ReceivedPages( | |
| 193 scoped_refptr<AndroidDeviceManager::Device> device, | |
| 194 scoped_refptr<RemoteBrowser> browser, | |
| 195 int result, | |
| 196 const std::string& response) { | |
| 197 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 198 if (result < 0) | |
| 199 return; | |
| 200 std::unique_ptr<base::Value> value = base::JSONReader::Read(response); | |
| 201 base::ListValue* list_value; | |
| 202 if (value && value->GetAsList(&list_value)) { | |
| 203 for (const auto& page_value : *list_value) { | |
| 204 base::DictionaryValue* dict; | |
| 205 if (page_value->GetAsDictionary(&dict)) | |
| 206 browser->pages_.push_back( | |
| 207 new RemotePage(device, browser->browser_id_, *dict)); | |
| 208 } | |
| 209 } | |
| 210 } | |
| 211 | |
| 212 // ProtocolCommand ------------------------------------------------------------ | |
| 213 | |
| 214 namespace { | |
| 215 | |
| 216 class ProtocolCommand | |
| 217 : public AndroidDeviceManager::AndroidWebSocket::Delegate { | |
| 218 public: | |
| 219 ProtocolCommand( | |
| 220 scoped_refptr<AndroidDeviceManager::Device> device, | |
| 221 const std::string& socket, | |
| 222 const std::string& target_path, | |
| 223 const std::string& command, | |
| 224 const base::Closure callback); | |
| 225 | |
| 226 private: | |
| 227 void OnSocketOpened() override; | |
| 228 void OnFrameRead(const std::string& message) override; | |
| 229 void OnSocketClosed() override; | |
| 230 ~ProtocolCommand() override; | |
| 231 | |
| 232 const std::string command_; | |
| 233 const base::Closure callback_; | |
| 234 std::unique_ptr<AndroidDeviceManager::AndroidWebSocket> web_socket_; | |
| 235 | |
| 236 DISALLOW_COPY_AND_ASSIGN(ProtocolCommand); | |
| 237 }; | |
| 238 | |
| 239 ProtocolCommand::ProtocolCommand( | |
| 240 scoped_refptr<AndroidDeviceManager::Device> device, | |
| 241 const std::string& socket, | |
| 242 const std::string& target_path, | |
| 243 const std::string& command, | |
| 244 const base::Closure callback) | |
| 245 : command_(command), | |
| 246 callback_(callback), | |
| 247 web_socket_(device->CreateWebSocket(socket, target_path, this)) { | |
| 248 } | |
| 249 | |
| 250 void ProtocolCommand::OnSocketOpened() { | |
| 251 web_socket_->SendFrame(command_); | |
| 252 } | |
| 253 | |
| 254 void ProtocolCommand::OnFrameRead(const std::string& message) { | |
| 255 delete this; | |
| 256 } | |
| 257 | |
| 258 void ProtocolCommand::OnSocketClosed() { | |
| 259 delete this; | |
| 260 } | |
| 261 | |
| 262 ProtocolCommand::~ProtocolCommand() { | |
| 263 if (!callback_.is_null()) | |
| 264 callback_.Run(); | |
| 265 } | |
| 266 | |
| 267 } // namespace | |
| 268 | |
| 269 // static | 82 // static |
| 270 DevToolsAndroidBridge::Factory* DevToolsAndroidBridge::Factory::GetInstance() { | 83 DevToolsAndroidBridge::Factory* DevToolsAndroidBridge::Factory::GetInstance() { |
| 271 return base::Singleton<DevToolsAndroidBridge::Factory>::get(); | 84 return base::Singleton<DevToolsAndroidBridge::Factory>::get(); |
| 272 } | 85 } |
| 273 | 86 |
| 274 // static | 87 // static |
| 275 DevToolsAndroidBridge* DevToolsAndroidBridge::Factory::GetForProfile( | 88 DevToolsAndroidBridge* DevToolsAndroidBridge::Factory::GetForProfile( |
| 276 Profile* profile) { | 89 Profile* profile) { |
| 277 return static_cast<DevToolsAndroidBridge*>(GetInstance()-> | 90 return static_cast<DevToolsAndroidBridge*>(GetInstance()-> |
| 278 GetServiceForBrowserContext(profile->GetOriginalProfile(), true)); | 91 GetServiceForBrowserContext(profile->GetOriginalProfile(), true)); |
| 279 } | 92 } |
| 280 | 93 |
| 281 DevToolsAndroidBridge::Factory::Factory() | 94 DevToolsAndroidBridge::Factory::Factory() |
| 282 : BrowserContextKeyedServiceFactory( | 95 : BrowserContextKeyedServiceFactory( |
| 283 "DevToolsAndroidBridge", | 96 "DevToolsAndroidBridge", |
| 284 BrowserContextDependencyManager::GetInstance()) { | 97 BrowserContextDependencyManager::GetInstance()) { |
| 285 } | 98 } |
| 286 | 99 |
| 287 DevToolsAndroidBridge::Factory::~Factory() {} | 100 DevToolsAndroidBridge::Factory::~Factory() {} |
| 288 | 101 |
| 289 KeyedService* DevToolsAndroidBridge::Factory::BuildServiceInstanceFor( | 102 KeyedService* DevToolsAndroidBridge::Factory::BuildServiceInstanceFor( |
| 290 content::BrowserContext* context) const { | 103 content::BrowserContext* context) const { |
| 291 Profile* profile = Profile::FromBrowserContext(context); | 104 Profile* profile = Profile::FromBrowserContext(context); |
| 292 | 105 |
| 293 return new DevToolsAndroidBridge(profile); | 106 return new DevToolsAndroidBridge(profile); |
| 294 } | 107 } |
| 295 | 108 |
| 296 // AgentHostDelegate ---------------------------------------------------------- | |
| 297 | |
| 298 class DevToolsAndroidBridge::AgentHostDelegate | |
| 299 : public content::DevToolsExternalAgentProxyDelegate, | |
| 300 public AndroidDeviceManager::AndroidWebSocket::Delegate { | |
| 301 public: | |
| 302 static scoped_refptr<content::DevToolsAgentHost> GetOrCreateAgentHost( | |
| 303 scoped_refptr<AndroidDeviceManager::Device> device, | |
| 304 const std::string& browser_id, | |
| 305 const std::string& local_id, | |
| 306 const std::string& target_path, | |
| 307 const std::string& type, | |
| 308 base::DictionaryValue* value); | |
| 309 ~AgentHostDelegate() override; | |
| 310 | |
| 311 private: | |
| 312 AgentHostDelegate( | |
| 313 scoped_refptr<AndroidDeviceManager::Device> device, | |
| 314 const std::string& browser_id, | |
| 315 const std::string& local_id, | |
| 316 const std::string& target_path, | |
| 317 const std::string& type, | |
| 318 base::DictionaryValue* value); | |
| 319 // DevToolsExternalAgentProxyDelegate overrides. | |
| 320 void Attach(content::DevToolsExternalAgentProxy* proxy) override; | |
| 321 void Detach() override; | |
| 322 std::string GetType() override; | |
| 323 std::string GetTitle() override; | |
| 324 std::string GetDescription() override; | |
| 325 GURL GetURL() override; | |
| 326 GURL GetFaviconURL() override; | |
| 327 std::string GetFrontendURL() override; | |
| 328 bool Activate() override; | |
| 329 void Reload() override; | |
| 330 bool Close() override; | |
| 331 void SendMessageToBackend(const std::string& message) override; | |
| 332 | |
| 333 void OnSocketOpened() override; | |
| 334 void OnFrameRead(const std::string& message) override; | |
| 335 void OnSocketClosed() override; | |
| 336 | |
| 337 void SendProtocolCommand(const std::string& target_path, | |
| 338 const std::string& method, | |
| 339 std::unique_ptr<base::DictionaryValue> params, | |
| 340 const base::Closure callback); | |
| 341 | |
| 342 scoped_refptr<AndroidDeviceManager::Device> device_; | |
| 343 std::string browser_id_; | |
| 344 std::string local_id_; | |
| 345 std::string target_path_; | |
| 346 std::string remote_type_; | |
| 347 std::string remote_id_; | |
| 348 std::string frontend_url_; | |
| 349 std::string title_; | |
| 350 std::string description_; | |
| 351 GURL url_; | |
| 352 GURL favicon_url_; | |
| 353 bool socket_opened_; | |
| 354 std::vector<std::string> pending_messages_; | |
| 355 std::unique_ptr<AndroidDeviceManager::AndroidWebSocket> web_socket_; | |
| 356 content::DevToolsAgentHost* agent_host_; | |
| 357 content::DevToolsExternalAgentProxy* proxy_; | |
| 358 DISALLOW_COPY_AND_ASSIGN(AgentHostDelegate); | |
| 359 }; | |
| 360 | |
| 361 static std::string GetStringProperty(base::DictionaryValue* value, | |
| 362 const std::string& name) { | |
| 363 std::string result; | |
| 364 value->GetString(name, &result); | |
| 365 return result; | |
| 366 } | |
| 367 | |
| 368 static std::string BuildUniqueTargetId( | |
| 369 const std::string& serial, | |
| 370 const std::string& browser_id, | |
| 371 base::DictionaryValue* value) { | |
| 372 return base::StringPrintf("%s:%s:%s", serial.c_str(), | |
| 373 browser_id.c_str(), GetStringProperty(value, "id").c_str()); | |
| 374 } | |
| 375 | |
| 376 static std::string GetFrontendURLFromValue(base::DictionaryValue* value) { | |
| 377 std::string frontend_url = GetStringProperty(value, "devtoolsFrontendUrl"); | |
| 378 size_t ws_param = frontend_url.find("?ws"); | |
| 379 if (ws_param != std::string::npos) | |
| 380 frontend_url = frontend_url.substr(0, ws_param); | |
| 381 if (base::StartsWith(frontend_url, "http:", base::CompareCase::SENSITIVE)) | |
| 382 frontend_url = "https:" + frontend_url.substr(5); | |
| 383 return frontend_url; | |
| 384 } | |
| 385 | |
| 386 static std::string GetTargetPath(base::DictionaryValue* value) { | |
| 387 std::string target_path = GetStringProperty(value, "webSocketDebuggerUrl"); | |
| 388 | |
| 389 if (base::StartsWith(target_path, "ws://", base::CompareCase::SENSITIVE)) { | |
| 390 size_t pos = target_path.find("/", 5); | |
| 391 if (pos == std::string::npos) | |
| 392 pos = 5; | |
| 393 target_path = target_path.substr(pos); | |
| 394 } else { | |
| 395 target_path = std::string(); | |
| 396 } | |
| 397 return target_path; | |
| 398 } | |
| 399 | |
| 400 // static | |
| 401 scoped_refptr<content::DevToolsAgentHost> | |
| 402 DevToolsAndroidBridge::AgentHostDelegate::GetOrCreateAgentHost( | |
| 403 scoped_refptr<AndroidDeviceManager::Device> device, | |
| 404 const std::string& browser_id, | |
| 405 const std::string& local_id, | |
| 406 const std::string& target_path, | |
| 407 const std::string& type, | |
| 408 base::DictionaryValue* value) { | |
| 409 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 410 scoped_refptr<DevToolsAgentHost> result = | |
| 411 DevToolsAgentHost::GetForId(local_id); | |
| 412 if (result) | |
| 413 return result; | |
| 414 | |
| 415 AgentHostDelegate* delegate = new AgentHostDelegate( | |
| 416 device, browser_id, local_id, target_path, type, value); | |
| 417 result = content::DevToolsAgentHost::Forward( | |
| 418 local_id, base::WrapUnique(delegate)); | |
| 419 delegate->agent_host_ = result.get(); | |
| 420 return result; | |
| 421 } | |
| 422 | |
| 423 DevToolsAndroidBridge::AgentHostDelegate::AgentHostDelegate( | |
| 424 scoped_refptr<AndroidDeviceManager::Device> device, | |
| 425 const std::string& browser_id, | |
| 426 const std::string& local_id, | |
| 427 const std::string& target_path, | |
| 428 const std::string& type, | |
| 429 base::DictionaryValue* value) | |
| 430 : device_(device), | |
| 431 browser_id_(browser_id), | |
| 432 local_id_(local_id), | |
| 433 target_path_(target_path), | |
| 434 remote_type_(type), | |
| 435 remote_id_(value ? GetStringProperty(value, "id") : ""), | |
| 436 frontend_url_(value ? GetFrontendURLFromValue(value) : ""), | |
| 437 title_(value ? base::UTF16ToUTF8(net::UnescapeForHTML(base::UTF8ToUTF16( | |
| 438 GetStringProperty(value, "title")))) : ""), | |
| 439 description_(value ? GetStringProperty(value, "description") : ""), | |
| 440 url_(GURL(value ? GetStringProperty(value, "url") : "")), | |
| 441 favicon_url_(GURL(value ? GetStringProperty(value, "faviconUrl") : "")), | |
| 442 socket_opened_(false), | |
| 443 agent_host_(nullptr), | |
| 444 proxy_(nullptr) { | |
| 445 } | |
| 446 | |
| 447 DevToolsAndroidBridge::AgentHostDelegate::~AgentHostDelegate() { | |
| 448 } | |
| 449 | |
| 450 void DevToolsAndroidBridge::AgentHostDelegate::Attach( | |
| 451 content::DevToolsExternalAgentProxy* proxy) { | |
| 452 proxy_ = proxy; | |
| 453 content::RecordAction( | |
| 454 base::StartsWith(browser_id_, kWebViewSocketPrefix, | |
| 455 base::CompareCase::SENSITIVE) | |
| 456 ? base::UserMetricsAction("DevTools_InspectAndroidWebView") | |
| 457 : base::UserMetricsAction("DevTools_InspectAndroidPage")); | |
| 458 web_socket_.reset( | |
| 459 device_->CreateWebSocket(browser_id_, target_path_, this)); | |
| 460 } | |
| 461 | |
| 462 void DevToolsAndroidBridge::AgentHostDelegate::Detach() { | |
| 463 web_socket_.reset(); | |
| 464 proxy_ = nullptr; | |
| 465 } | |
| 466 | |
| 467 std::string DevToolsAndroidBridge::AgentHostDelegate::GetType() { | |
| 468 return remote_type_; | |
| 469 } | |
| 470 | |
| 471 std::string DevToolsAndroidBridge::AgentHostDelegate::GetTitle() { | |
| 472 return title_; | |
| 473 } | |
| 474 | |
| 475 std::string DevToolsAndroidBridge::AgentHostDelegate::GetDescription() { | |
| 476 return description_; | |
| 477 } | |
| 478 | |
| 479 GURL DevToolsAndroidBridge::AgentHostDelegate::GetURL() { | |
| 480 return url_; | |
| 481 } | |
| 482 | |
| 483 GURL DevToolsAndroidBridge::AgentHostDelegate::GetFaviconURL() { | |
| 484 return favicon_url_; | |
| 485 } | |
| 486 | |
| 487 std::string DevToolsAndroidBridge::AgentHostDelegate::GetFrontendURL() { | |
| 488 return frontend_url_; | |
| 489 } | |
| 490 | |
| 491 bool DevToolsAndroidBridge::AgentHostDelegate::Activate() { | |
| 492 std::string request = base::StringPrintf(kActivatePageRequest, | |
| 493 remote_id_.c_str()); | |
| 494 device_->SendJsonRequest(browser_id_, request, base::Bind(&NoOp)); | |
| 495 return true; | |
| 496 } | |
| 497 | |
| 498 void DevToolsAndroidBridge::AgentHostDelegate::Reload() { | |
| 499 SendProtocolCommand(target_path_, kPageReloadCommand, nullptr, | |
| 500 base::Closure()); | |
| 501 } | |
| 502 | |
| 503 bool DevToolsAndroidBridge::AgentHostDelegate::Close() { | |
| 504 std::string request = base::StringPrintf(kClosePageRequest, | |
| 505 remote_id_.c_str()); | |
| 506 device_->SendJsonRequest(browser_id_, request, base::Bind(&NoOp)); | |
| 507 return true; | |
| 508 } | |
| 509 | |
| 510 void DevToolsAndroidBridge::AgentHostDelegate::SendMessageToBackend( | |
| 511 const std::string& message) { | |
| 512 // We could have detached due to physical connection being closed. | |
| 513 if (!proxy_) | |
| 514 return; | |
| 515 if (socket_opened_) | |
| 516 web_socket_->SendFrame(message); | |
| 517 else | |
| 518 pending_messages_.push_back(message); | |
| 519 } | |
| 520 | |
| 521 void DevToolsAndroidBridge::AgentHostDelegate::OnSocketOpened() { | |
| 522 socket_opened_ = true; | |
| 523 for (std::vector<std::string>::iterator it = pending_messages_.begin(); | |
| 524 it != pending_messages_.end(); ++it) { | |
| 525 SendMessageToBackend(*it); | |
| 526 } | |
| 527 pending_messages_.clear(); | |
| 528 } | |
| 529 | |
| 530 void DevToolsAndroidBridge::AgentHostDelegate::OnFrameRead( | |
| 531 const std::string& message) { | |
| 532 if (proxy_) | |
| 533 proxy_->DispatchOnClientHost(message); | |
| 534 } | |
| 535 | |
| 536 void DevToolsAndroidBridge::AgentHostDelegate::OnSocketClosed() { | |
| 537 if (proxy_) { | |
| 538 std::string message = "{ \"method\": \"Inspector.detached\", " | |
| 539 "\"params\": { \"reason\": \"Connection lost.\"} }"; | |
| 540 proxy_->DispatchOnClientHost(message); | |
| 541 Detach(); | |
| 542 } | |
| 543 } | |
| 544 | |
| 545 void DevToolsAndroidBridge::AgentHostDelegate::SendProtocolCommand( | |
| 546 const std::string& target_path, | |
| 547 const std::string& method, | |
| 548 std::unique_ptr<base::DictionaryValue> params, | |
| 549 const base::Closure callback) { | |
| 550 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 551 if (target_path.empty()) | |
| 552 return; | |
| 553 new ProtocolCommand( | |
| 554 device_, browser_id_, target_path, | |
| 555 DevToolsProtocol::SerializeCommand(1, method, std::move(params)), | |
| 556 callback); | |
| 557 } | |
| 558 | |
| 559 // DevToolsAndroidBridge::RemotePage ------------------------------------------ | |
| 560 | |
| 561 DevToolsAndroidBridge::RemotePage::RemotePage( | |
| 562 scoped_refptr<AndroidDeviceManager::Device> device, | |
| 563 const std::string& browser_id, | |
| 564 const base::DictionaryValue& dict) | |
| 565 : device_(device), | |
| 566 browser_id_(browser_id), | |
| 567 dict_(dict.DeepCopy()) { | |
| 568 } | |
| 569 | |
| 570 DevToolsAndroidBridge::RemotePage::~RemotePage() { | |
| 571 } | |
| 572 | |
| 573 scoped_refptr<content::DevToolsAgentHost> | |
| 574 DevToolsAndroidBridge::RemotePage::CreateTarget() { | |
| 575 std::string local_id = BuildUniqueTargetId(device_->serial(), | |
| 576 browser_id_, | |
| 577 dict_.get()); | |
| 578 std::string target_path = GetTargetPath(dict_.get()); | |
| 579 std::string type = GetStringProperty(dict_.get(), "type"); | |
| 580 | |
| 581 return AgentHostDelegate::GetOrCreateAgentHost( | |
| 582 device_, browser_id_, local_id, target_path, type, dict_.get()); | |
| 583 } | |
| 584 | |
| 585 // DevToolsAndroidBridge::RemoteBrowser --------------------------------------- | |
| 586 | |
| 587 DevToolsAndroidBridge::RemoteBrowser::RemoteBrowser( | |
| 588 const std::string& serial, | |
| 589 const AndroidDeviceManager::BrowserInfo& browser_info) | |
| 590 : serial_(serial), | |
| 591 browser_id_(browser_info.socket_name), | |
| 592 display_name_(browser_info.display_name), | |
| 593 user_(browser_info.user), | |
| 594 type_(browser_info.type) { | |
| 595 } | |
| 596 | |
| 597 bool DevToolsAndroidBridge::RemoteBrowser::IsChrome() { | |
| 598 return type_ == AndroidDeviceManager::BrowserInfo::kTypeChrome; | |
| 599 } | |
| 600 | |
| 601 std::string DevToolsAndroidBridge::RemoteBrowser::GetId() { | |
| 602 return serial() + ":" + socket(); | |
| 603 } | |
| 604 | |
| 605 DevToolsAndroidBridge::RemoteBrowser::ParsedVersion | |
| 606 DevToolsAndroidBridge::RemoteBrowser::GetParsedVersion() { | |
| 607 ParsedVersion result; | |
| 608 for (const base::StringPiece& part : | |
| 609 base::SplitStringPiece( | |
| 610 version_, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) { | |
| 611 int value = 0; | |
| 612 base::StringToInt(part, &value); | |
| 613 result.push_back(value); | |
| 614 } | |
| 615 return result; | |
| 616 } | |
| 617 | |
| 618 scoped_refptr<content::DevToolsAgentHost> | 109 scoped_refptr<content::DevToolsAgentHost> |
| 619 DevToolsAndroidBridge::GetBrowserAgentHost( | 110 DevToolsAndroidBridge::GetBrowserAgentHost( |
| 620 scoped_refptr<RemoteBrowser> browser) { | 111 scoped_refptr<RemoteBrowser> browser) { |
| 621 DeviceMap::iterator it = device_map_.find(browser->serial()); | 112 DeviceMap::iterator it = device_map_.find(browser->serial()); |
| 622 if (it == device_map_.end()) | 113 if (it == device_map_.end()) |
| 623 return nullptr; | 114 return nullptr; |
| 624 | 115 |
| 625 return AgentHostDelegate::GetOrCreateAgentHost( | 116 return DevToolsDeviceDiscovery::CreateBrowserAgentHost(it->second, browser); |
| 626 it->second, | |
| 627 browser->browser_id_, | |
| 628 "adb:" + browser->serial() + ":" + browser->socket(), | |
| 629 kBrowserTargetSocket, DevToolsAgentHost::kTypeBrowser, nullptr); | |
| 630 } | 117 } |
| 631 | 118 |
| 632 void DevToolsAndroidBridge::SendJsonRequest( | 119 void DevToolsAndroidBridge::SendJsonRequest( |
| 633 const std::string& browser_id_str, | 120 const std::string& browser_id_str, |
| 634 const std::string& url, | 121 const std::string& url, |
| 635 const JsonRequestCallback& callback) { | 122 const JsonRequestCallback& callback) { |
| 636 std::string serial; | 123 std::string serial; |
| 637 std::string browser_id; | 124 std::string browser_id; |
| 638 if (!BrowserIdFromString(browser_id_str, &serial, &browser_id)) { | 125 if (!BrowserIdFromString(browser_id_str, &serial, &browser_id)) { |
| 639 callback.Run(net::ERR_FAILED, std::string()); | 126 callback.Run(net::ERR_FAILED, std::string()); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 658 } | 145 } |
| 659 std::string url = gurl.spec(); | 146 std::string url = gurl.spec(); |
| 660 RemoteBrowser::ParsedVersion parsed_version = browser->GetParsedVersion(); | 147 RemoteBrowser::ParsedVersion parsed_version = browser->GetParsedVersion(); |
| 661 | 148 |
| 662 std::string query = net::EscapeQueryParamValue(url, false /* use_plus */); | 149 std::string query = net::EscapeQueryParamValue(url, false /* use_plus */); |
| 663 std::string request = | 150 std::string request = |
| 664 base::StringPrintf(kNewPageRequestWithURL, query.c_str()); | 151 base::StringPrintf(kNewPageRequestWithURL, query.c_str()); |
| 665 SendJsonRequest(browser->GetId(), request, base::Bind(&NoOp)); | 152 SendJsonRequest(browser->GetId(), request, base::Bind(&NoOp)); |
| 666 } | 153 } |
| 667 | 154 |
| 668 DevToolsAndroidBridge::RemoteBrowser::~RemoteBrowser() { | |
| 669 } | |
| 670 | |
| 671 // DevToolsAndroidBridge::RemoteDevice ---------------------------------------- | |
| 672 | |
| 673 DevToolsAndroidBridge::RemoteDevice::RemoteDevice( | |
| 674 const std::string& serial, | |
| 675 const AndroidDeviceManager::DeviceInfo& device_info) | |
| 676 : serial_(serial), | |
| 677 model_(device_info.model), | |
| 678 connected_(device_info.connected), | |
| 679 screen_size_(device_info.screen_size) { | |
| 680 for (std::vector<AndroidDeviceManager::BrowserInfo>::const_iterator it = | |
| 681 device_info.browser_info.begin(); | |
| 682 it != device_info.browser_info.end(); | |
| 683 ++it) { | |
| 684 browsers_.push_back(new RemoteBrowser(serial, *it)); | |
| 685 } | |
| 686 } | |
| 687 | |
| 688 DevToolsAndroidBridge::RemoteDevice::~RemoteDevice() { | |
| 689 } | |
| 690 | |
| 691 // DevToolsAndroidBridge ------------------------------------------------------ | |
| 692 | |
| 693 // static | |
| 694 void DevToolsAndroidBridge::QueryCompleteDevices( | |
| 695 AndroidDeviceManager* device_manager, | |
| 696 const DeviceListCallback& callback) { | |
| 697 new DiscoveryRequest(device_manager, callback); | |
| 698 } | |
| 699 | |
| 700 DevToolsAndroidBridge::DevToolsAndroidBridge( | 155 DevToolsAndroidBridge::DevToolsAndroidBridge( |
| 701 Profile* profile) | 156 Profile* profile) |
| 702 : profile_(profile), | 157 : profile_(profile), |
| 703 device_manager_(AndroidDeviceManager::Create()), | 158 device_manager_(AndroidDeviceManager::Create()), |
| 704 task_scheduler_(base::Bind(&DevToolsAndroidBridge::ScheduleTaskDefault)), | |
| 705 port_forwarding_controller_(new PortForwardingController(profile)), | 159 port_forwarding_controller_(new PortForwardingController(profile)), |
| 706 weak_factory_(this) { | 160 weak_factory_(this) { |
| 707 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 161 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 708 pref_change_registrar_.Init(profile_->GetPrefs()); | 162 pref_change_registrar_.Init(profile_->GetPrefs()); |
| 709 pref_change_registrar_.Add(prefs::kDevToolsDiscoverUsbDevicesEnabled, | 163 pref_change_registrar_.Add(prefs::kDevToolsDiscoverUsbDevicesEnabled, |
| 710 base::Bind(&DevToolsAndroidBridge::CreateDeviceProviders, | 164 base::Bind(&DevToolsAndroidBridge::CreateDeviceProviders, |
| 711 base::Unretained(this))); | 165 base::Unretained(this))); |
| 712 pref_change_registrar_.Add(prefs::kDevToolsTCPDiscoveryConfig, | 166 pref_change_registrar_.Add(prefs::kDevToolsTCPDiscoveryConfig, |
| 713 base::Bind(&DevToolsAndroidBridge::CreateDeviceProviders, | 167 base::Bind(&DevToolsAndroidBridge::CreateDeviceProviders, |
| 714 base::Unretained(this))); | 168 base::Unretained(this))); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 782 } | 236 } |
| 783 | 237 |
| 784 DevToolsAndroidBridge::~DevToolsAndroidBridge() { | 238 DevToolsAndroidBridge::~DevToolsAndroidBridge() { |
| 785 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 239 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 786 DCHECK(device_list_listeners_.empty()); | 240 DCHECK(device_list_listeners_.empty()); |
| 787 DCHECK(device_count_listeners_.empty()); | 241 DCHECK(device_count_listeners_.empty()); |
| 788 DCHECK(port_forwarding_listeners_.empty()); | 242 DCHECK(port_forwarding_listeners_.empty()); |
| 789 } | 243 } |
| 790 | 244 |
| 791 void DevToolsAndroidBridge::StartDeviceListPolling() { | 245 void DevToolsAndroidBridge::StartDeviceListPolling() { |
| 792 device_list_callback_.Reset( | 246 device_discovery_.reset(new DevToolsDeviceDiscovery(device_manager_.get(), |
| 793 base::Bind(&DevToolsAndroidBridge::ReceivedDeviceList, AsWeakPtr())); | 247 base::Bind(&DevToolsAndroidBridge::ReceivedDeviceList, |
| 794 RequestDeviceList(device_list_callback_.callback()); | 248 base::Unretained(this)))); |
| 249 if (!task_scheduler_.is_null()) |
| 250 device_discovery_->SetScheduler(task_scheduler_); |
| 795 } | 251 } |
| 796 | 252 |
| 797 void DevToolsAndroidBridge::StopDeviceListPolling() { | 253 void DevToolsAndroidBridge::StopDeviceListPolling() { |
| 798 device_list_callback_.Cancel(); | 254 device_discovery_.reset(); |
| 799 device_map_.clear(); | 255 device_map_.clear(); |
| 800 port_forwarding_controller_->CloseAllConnections(); | 256 port_forwarding_controller_->CloseAllConnections(); |
| 801 } | 257 } |
| 802 | 258 |
| 803 bool DevToolsAndroidBridge::NeedsDeviceListPolling() { | 259 bool DevToolsAndroidBridge::NeedsDeviceListPolling() { |
| 804 return !device_list_listeners_.empty() || !port_forwarding_listeners_.empty(); | 260 return !device_list_listeners_.empty() || !port_forwarding_listeners_.empty(); |
| 805 } | 261 } |
| 806 | 262 |
| 807 void DevToolsAndroidBridge::RequestDeviceList( | |
| 808 const DeviceListCallback& callback) { | |
| 809 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 810 | |
| 811 if (!NeedsDeviceListPolling() || | |
| 812 !callback.Equals(device_list_callback_.callback())) | |
| 813 return; | |
| 814 | |
| 815 new DiscoveryRequest(device_manager_.get(), callback); | |
| 816 } | |
| 817 | |
| 818 void DevToolsAndroidBridge::ReceivedDeviceList( | 263 void DevToolsAndroidBridge::ReceivedDeviceList( |
| 819 const CompleteDevices& complete_devices) { | 264 const CompleteDevices& complete_devices) { |
| 820 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 265 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 821 | 266 |
| 822 device_map_.clear(); | 267 device_map_.clear(); |
| 823 RemoteDevices remote_devices; | 268 RemoteDevices remote_devices; |
| 824 for (const auto& pair : complete_devices) { | 269 for (const auto& pair : complete_devices) { |
| 825 device_map_[pair.first->serial()] = pair.first; | 270 device_map_[pair.first->serial()] = pair.first; |
| 826 remote_devices.push_back(pair.second); | 271 remote_devices.push_back(pair.second); |
| 827 } | 272 } |
| 828 | 273 |
| 829 DeviceListListeners copy(device_list_listeners_); | 274 DeviceListListeners copy(device_list_listeners_); |
| 830 for (DeviceListListeners::iterator it = copy.begin(); it != copy.end(); ++it) | 275 for (DeviceListListeners::iterator it = copy.begin(); it != copy.end(); ++it) |
| 831 (*it)->DeviceListChanged(remote_devices); | 276 (*it)->DeviceListChanged(remote_devices); |
| 832 | 277 |
| 833 ForwardingStatus status = | 278 ForwardingStatus status = |
| 834 port_forwarding_controller_->DeviceListChanged(complete_devices); | 279 port_forwarding_controller_->DeviceListChanged(complete_devices); |
| 835 PortForwardingListeners forwarding_listeners(port_forwarding_listeners_); | 280 PortForwardingListeners forwarding_listeners(port_forwarding_listeners_); |
| 836 for (PortForwardingListeners::iterator it = forwarding_listeners.begin(); | 281 for (PortForwardingListeners::iterator it = forwarding_listeners.begin(); |
| 837 it != forwarding_listeners.end(); ++it) { | 282 it != forwarding_listeners.end(); ++it) { |
| 838 (*it)->PortStatusChanged(status); | 283 (*it)->PortStatusChanged(status); |
| 839 } | 284 } |
| 840 | |
| 841 if (!NeedsDeviceListPolling()) | |
| 842 return; | |
| 843 | |
| 844 task_scheduler_.Run( | |
| 845 base::Bind(&DevToolsAndroidBridge::RequestDeviceList, | |
| 846 AsWeakPtr(), device_list_callback_.callback())); | |
| 847 } | 285 } |
| 848 | 286 |
| 849 void DevToolsAndroidBridge::StartDeviceCountPolling() { | 287 void DevToolsAndroidBridge::StartDeviceCountPolling() { |
| 850 device_count_callback_.Reset( | 288 device_count_callback_.Reset( |
| 851 base::Bind(&DevToolsAndroidBridge::ReceivedDeviceCount, AsWeakPtr())); | 289 base::Bind(&DevToolsAndroidBridge::ReceivedDeviceCount, AsWeakPtr())); |
| 852 RequestDeviceCount(device_count_callback_.callback()); | 290 RequestDeviceCount(device_count_callback_.callback()); |
| 853 } | 291 } |
| 854 | 292 |
| 855 void DevToolsAndroidBridge::StopDeviceCountPolling() { | 293 void DevToolsAndroidBridge::StopDeviceCountPolling() { |
| 856 device_count_callback_.Cancel(); | 294 device_count_callback_.Cancel(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 875 (*it)->DeviceCountChanged(count); | 313 (*it)->DeviceCountChanged(count); |
| 876 | 314 |
| 877 if (device_count_listeners_.empty()) | 315 if (device_count_listeners_.empty()) |
| 878 return; | 316 return; |
| 879 | 317 |
| 880 task_scheduler_.Run( | 318 task_scheduler_.Run( |
| 881 base::Bind(&DevToolsAndroidBridge::RequestDeviceCount, | 319 base::Bind(&DevToolsAndroidBridge::RequestDeviceCount, |
| 882 AsWeakPtr(), device_count_callback_.callback())); | 320 AsWeakPtr(), device_count_callback_.callback())); |
| 883 } | 321 } |
| 884 | 322 |
| 885 // static | |
| 886 void DevToolsAndroidBridge::ScheduleTaskDefault(const base::Closure& task) { | |
| 887 BrowserThread::PostDelayedTask( | |
| 888 BrowserThread::UI, | |
| 889 FROM_HERE, | |
| 890 task, | |
| 891 base::TimeDelta::FromMilliseconds(kAdbPollingIntervalMs)); | |
| 892 } | |
| 893 | |
| 894 static std::set<net::HostPortPair> ParseTargetDiscoveryPreferenceValue( | 323 static std::set<net::HostPortPair> ParseTargetDiscoveryPreferenceValue( |
| 895 const base::ListValue* preferenceValue) { | 324 const base::ListValue* preferenceValue) { |
| 896 std::set<net::HostPortPair> targets; | 325 std::set<net::HostPortPair> targets; |
| 897 if (!preferenceValue || preferenceValue->empty()) | 326 if (!preferenceValue || preferenceValue->empty()) |
| 898 return targets; | 327 return targets; |
| 899 std::string address; | 328 std::string address; |
| 900 for (size_t i = 0; i < preferenceValue->GetSize(); i++) { | 329 for (size_t i = 0; i < preferenceValue->GetSize(); i++) { |
| 901 if (!preferenceValue->GetString(i, &address)) | 330 if (!preferenceValue->GetString(i, &address)) |
| 902 continue; | 331 continue; |
| 903 net::HostPortPair target = net::HostPortPair::FromString(address); | 332 net::HostPortPair target = net::HostPortPair::FromString(address); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 969 StopDeviceListPolling(); | 398 StopDeviceListPolling(); |
| 970 StartDeviceListPolling(); | 399 StartDeviceListPolling(); |
| 971 } | 400 } |
| 972 } | 401 } |
| 973 | 402 |
| 974 void DevToolsAndroidBridge::set_tcp_provider_callback_for_test( | 403 void DevToolsAndroidBridge::set_tcp_provider_callback_for_test( |
| 975 TCPProviderCallback callback) { | 404 TCPProviderCallback callback) { |
| 976 tcp_provider_callback_ = callback; | 405 tcp_provider_callback_ = callback; |
| 977 CreateDeviceProviders(); | 406 CreateDeviceProviders(); |
| 978 } | 407 } |
| OLD | NEW |