| 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 <set> | 
| 8 #include <vector> | 9 #include <vector> | 
| 9 | 10 | 
| 10 #include "base/base64.h" | 11 #include "base/base64.h" | 
| 11 #include "base/bind.h" | 12 #include "base/bind.h" | 
| 12 #include "base/command_line.h" | 13 #include "base/command_line.h" | 
| 13 #include "base/compiler_specific.h" | 14 #include "base/compiler_specific.h" | 
| 14 #include "base/json/json_reader.h" | 15 #include "base/json/json_reader.h" | 
| 15 #include "base/lazy_instance.h" | 16 #include "base/lazy_instance.h" | 
| 16 #include "base/memory/singleton.h" | 17 #include "base/memory/singleton.h" | 
| 17 #include "base/message_loop/message_loop.h" | 18 #include "base/message_loop/message_loop.h" | 
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 289   } | 290   } | 
| 290 | 291 | 
| 291   return new DevToolsAndroidBridge( | 292   return new DevToolsAndroidBridge( | 
| 292       profile, signin_manager, token_service); | 293       profile, signin_manager, token_service); | 
| 293 } | 294 } | 
| 294 | 295 | 
| 295 // AgentHostDelegate ---------------------------------------------------------- | 296 // AgentHostDelegate ---------------------------------------------------------- | 
| 296 | 297 | 
| 297 class DevToolsAndroidBridge::AgentHostDelegate | 298 class DevToolsAndroidBridge::AgentHostDelegate | 
| 298     : public content::DevToolsExternalAgentProxyDelegate, | 299     : public content::DevToolsExternalAgentProxyDelegate, | 
| 299       public AndroidDeviceManager::AndroidWebSocket::Delegate { | 300       public AndroidDeviceManager::AndroidWebSocket::Delegate, | 
|  | 301       public DevToolsAndroidBridge::DeviceListListener { | 
| 300  public: | 302  public: | 
| 301   static scoped_refptr<content::DevToolsAgentHost> GetOrCreateAgentHost( | 303   static scoped_refptr<content::DevToolsAgentHost> GetOrCreateAgentHost( | 
| 302       DevToolsAndroidBridge* bridge, | 304       DevToolsAndroidBridge* bridge, | 
| 303       const std::string& id, | 305       const std::string& id, | 
| 304       const BrowserId& browser_id, | 306       const BrowserId& browser_id, | 
| 305       const std::string& debug_url); | 307       const std::string& debug_url); | 
| 306 | 308 | 
| 307  private: | 309  private: | 
| 308   AgentHostDelegate( | 310   AgentHostDelegate( | 
| 309       DevToolsAndroidBridge* bridge, | 311       DevToolsAndroidBridge* bridge, | 
| 310       const std::string& id, | 312       const std::string& id, | 
| 311       const BrowserId& browser_id, | 313       const BrowserId& browser_id, | 
| 312       const std::string& debug_url); | 314       const std::string& debug_url); | 
| 313   ~AgentHostDelegate() override; | 315   ~AgentHostDelegate() override; | 
| 314   void Attach(content::DevToolsExternalAgentProxy* proxy) override; | 316   void Attach(content::DevToolsExternalAgentProxy* proxy) override; | 
| 315   void Detach() override; | 317   void Detach() override; | 
| 316   void SendMessageToBackend(const std::string& message) override; | 318   void SendMessageToBackend(const std::string& message) override; | 
|  | 319   void OpenWorkerInspector(content::BrowserContext* context, | 
|  | 320                            const std::string& id) override; | 
| 317   void OnSocketOpened() override; | 321   void OnSocketOpened() override; | 
| 318   void OnFrameRead(const std::string& message) override; | 322   void OnFrameRead(const std::string& message) override; | 
| 319   void OnSocketClosed() override; | 323   void OnSocketClosed() override; | 
| 320 | 324 | 
|  | 325   // DevToolsAndroidBridge::Listener overrides. | 
|  | 326   void DeviceListChanged( | 
|  | 327       const DevToolsAndroidBridge::RemoteDevices& devices) override; | 
|  | 328 | 
| 321   std::string id_; | 329   std::string id_; | 
| 322   base::WeakPtr<DevToolsAndroidBridge> bridge_; | 330   base::WeakPtr<DevToolsAndroidBridge> bridge_; | 
| 323   BrowserId browser_id_; | 331   BrowserId browser_id_; | 
| 324   std::string debug_url_; | 332   std::string debug_url_; | 
| 325   bool socket_opened_; | 333   bool socket_opened_; | 
| 326   std::vector<std::string> pending_messages_; | 334   std::vector<std::string> pending_messages_; | 
| 327   scoped_refptr<AndroidDeviceManager::Device> device_; | 335   scoped_refptr<AndroidDeviceManager::Device> device_; | 
| 328   scoped_ptr<AndroidDeviceManager::AndroidWebSocket> web_socket_; | 336   scoped_ptr<AndroidDeviceManager::AndroidWebSocket> web_socket_; | 
| 329   content::DevToolsAgentHost* agent_host_; | 337   content::DevToolsAgentHost* agent_host_; | 
| 330   content::DevToolsExternalAgentProxy* proxy_; | 338   content::DevToolsExternalAgentProxy* proxy_; | 
|  | 339   content::BrowserContext* context_; | 
|  | 340   std::set<std::string> pending_workers_; | 
|  | 341   base::WeakPtrFactory<DevToolsAndroidBridge::AgentHostDelegate> weak_factory_; | 
|  | 342 | 
| 331   DISALLOW_COPY_AND_ASSIGN(AgentHostDelegate); | 343   DISALLOW_COPY_AND_ASSIGN(AgentHostDelegate); | 
| 332 }; | 344 }; | 
| 333 | 345 | 
| 334 // static | 346 // static | 
| 335 scoped_refptr<content::DevToolsAgentHost> | 347 scoped_refptr<content::DevToolsAgentHost> | 
| 336 DevToolsAndroidBridge::AgentHostDelegate::GetOrCreateAgentHost( | 348 DevToolsAndroidBridge::AgentHostDelegate::GetOrCreateAgentHost( | 
| 337     DevToolsAndroidBridge* bridge, | 349     DevToolsAndroidBridge* bridge, | 
| 338     const std::string& id, | 350     const std::string& id, | 
| 339     const BrowserId& browser_id, | 351     const BrowserId& browser_id, | 
| 340     const std::string& debug_url) { | 352     const std::string& debug_url) { | 
| 341   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 353   DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| 342   AgentHostDelegates::iterator it = bridge->host_delegates_.find(id); | 354   AgentHostDelegates::iterator it = bridge->host_delegates_.find(id); | 
| 343   if (it != bridge->host_delegates_.end()) | 355   if (it != bridge->host_delegates_.end()) { | 
|  | 356     it->second->debug_url_ = debug_url; | 
| 344     return it->second->agent_host_; | 357     return it->second->agent_host_; | 
|  | 358   } | 
| 345 | 359 | 
| 346   AgentHostDelegate* delegate = | 360   AgentHostDelegate* delegate = | 
| 347       new AgentHostDelegate(bridge, id, browser_id, debug_url); | 361       new AgentHostDelegate(bridge, id, browser_id, debug_url); | 
| 348   scoped_refptr<content::DevToolsAgentHost> result = | 362   scoped_refptr<content::DevToolsAgentHost> result = | 
| 349       content::DevToolsAgentHost::Create(delegate); | 363       content::DevToolsAgentHost::Create(delegate); | 
| 350   delegate->agent_host_ = result.get(); | 364   delegate->agent_host_ = result.get(); | 
| 351   return result; | 365   return result; | 
| 352 } | 366 } | 
| 353 | 367 | 
| 354 DevToolsAndroidBridge::AgentHostDelegate::AgentHostDelegate( | 368 DevToolsAndroidBridge::AgentHostDelegate::AgentHostDelegate( | 
| 355     DevToolsAndroidBridge* bridge, | 369     DevToolsAndroidBridge* bridge, | 
| 356     const std::string& id, | 370     const std::string& id, | 
| 357     const BrowserId& browser_id, | 371     const BrowserId& browser_id, | 
| 358     const std::string& debug_url) | 372     const std::string& debug_url) | 
| 359     : id_(id), | 373     : id_(id), | 
| 360       bridge_(bridge->AsWeakPtr()), | 374       bridge_(bridge->AsWeakPtr()), | 
| 361       browser_id_(browser_id), | 375       browser_id_(browser_id), | 
| 362       debug_url_(debug_url), | 376       debug_url_(debug_url), | 
| 363       socket_opened_(false), | 377       socket_opened_(false), | 
| 364       agent_host_(NULL), | 378       agent_host_(NULL), | 
| 365       proxy_(NULL) { | 379       proxy_(NULL), | 
|  | 380       context_(NULL), | 
|  | 381       weak_factory_(this) { | 
| 366   bridge_->host_delegates_[id] = this; | 382   bridge_->host_delegates_[id] = this; | 
| 367 } | 383 } | 
| 368 | 384 | 
| 369 DevToolsAndroidBridge::AgentHostDelegate::~AgentHostDelegate() { | 385 DevToolsAndroidBridge::AgentHostDelegate::~AgentHostDelegate() { | 
| 370   if (bridge_) | 386   if (bridge_) { | 
|  | 387     if (pending_workers_.size()) { | 
|  | 388       bridge_->RemoveDeviceListListener(this); | 
|  | 389     } | 
| 371     bridge_->host_delegates_.erase(id_); | 390     bridge_->host_delegates_.erase(id_); | 
|  | 391   } | 
| 372 } | 392 } | 
| 373 | 393 | 
| 374 void DevToolsAndroidBridge::AgentHostDelegate::Attach( | 394 void DevToolsAndroidBridge::AgentHostDelegate::Attach( | 
| 375     content::DevToolsExternalAgentProxy* proxy) { | 395     content::DevToolsExternalAgentProxy* proxy) { | 
| 376   proxy_ = proxy; | 396   proxy_ = proxy; | 
| 377   content::RecordAction(browser_id_.second.find(kWebViewSocketPrefix) == 0 ? | 397   content::RecordAction(browser_id_.second.find(kWebViewSocketPrefix) == 0 ? | 
| 378       base::UserMetricsAction("DevTools_InspectAndroidWebView") : | 398       base::UserMetricsAction("DevTools_InspectAndroidWebView") : | 
| 379       base::UserMetricsAction("DevTools_InspectAndroidPage")); | 399       base::UserMetricsAction("DevTools_InspectAndroidPage")); | 
| 380 | 400 | 
| 381   // Retain the device so it's not released until AgentHost is detached. | 401   // Retain the device so it's not released until AgentHost is detached. | 
| 382   if (bridge_) | 402   if (bridge_) | 
| 383     device_ = bridge_->FindDevice(browser_id_.first); | 403     device_ = bridge_->FindDevice(browser_id_.first); | 
| 384   if (!device_.get()) | 404   if (!device_.get()) | 
| 385     return; | 405     return; | 
| 386 |  | 
| 387   web_socket_.reset( | 406   web_socket_.reset( | 
| 388       device_->CreateWebSocket(browser_id_.second, debug_url_, this)); | 407       device_->CreateWebSocket(browser_id_.second, debug_url_, this)); | 
| 389 } | 408 } | 
| 390 | 409 | 
| 391 void DevToolsAndroidBridge::AgentHostDelegate::Detach() { | 410 void DevToolsAndroidBridge::AgentHostDelegate::Detach() { | 
| 392   web_socket_.reset(); | 411   web_socket_.reset(); | 
| 393   device_ = nullptr; | 412   device_ = nullptr; | 
| 394 } | 413 } | 
| 395 | 414 | 
| 396 void DevToolsAndroidBridge::AgentHostDelegate::SendMessageToBackend( | 415 void DevToolsAndroidBridge::AgentHostDelegate::SendMessageToBackend( | 
| 397     const std::string& message) { | 416     const std::string& message) { | 
| 398   if (socket_opened_) | 417   if (socket_opened_) | 
| 399     web_socket_->SendFrame(message); | 418     web_socket_->SendFrame(message); | 
| 400   else | 419   else | 
| 401     pending_messages_.push_back(message); | 420     pending_messages_.push_back(message); | 
| 402 } | 421 } | 
| 403 | 422 | 
|  | 423 void DevToolsAndroidBridge::AgentHostDelegate::OpenWorkerInspector( | 
|  | 424     content::BrowserContext* context, | 
|  | 425     const std::string& id) { | 
|  | 426   if (!bridge_) | 
|  | 427     return; | 
|  | 428   const std::string full_id = | 
|  | 429       base::StringPrintf("%s:%s:%s", browser_id_.first.c_str(), | 
|  | 430                          browser_id_.second.c_str(), id.c_str()); | 
|  | 431   if (pending_workers_.size()) { | 
|  | 432     pending_workers_.insert(full_id); | 
|  | 433   } else { | 
|  | 434     pending_workers_.insert(full_id); | 
|  | 435     context_ = context; | 
|  | 436     bridge_->AddDeviceListListener(this); | 
|  | 437   } | 
|  | 438 } | 
|  | 439 | 
|  | 440 static std::string GetStringProperty(const base::DictionaryValue& value, | 
|  | 441                                      const std::string& name) { | 
|  | 442   std::string result; | 
|  | 443   value.GetString(name, &result); | 
|  | 444   return result; | 
|  | 445 } | 
|  | 446 | 
|  | 447 static std::string BuildUniqueTargetId( | 
|  | 448     const DevToolsAndroidBridge::BrowserId& browser_id, | 
|  | 449     const base::DictionaryValue& value) { | 
|  | 450   return base::StringPrintf("%s:%s:%s", browser_id.first.c_str(), | 
|  | 451                             browser_id.second.c_str(), | 
|  | 452                             GetStringProperty(value, "id").c_str()); | 
|  | 453 } | 
|  | 454 | 
|  | 455 static std::string GetDebugURL(const base::DictionaryValue& value) { | 
|  | 456   std::string debug_url = GetStringProperty(value, "webSocketDebuggerUrl"); | 
|  | 457 | 
|  | 458   if (debug_url.find("ws://") == 0) | 
|  | 459     debug_url = debug_url.substr(5); | 
|  | 460   else | 
|  | 461     debug_url = std::string(); | 
|  | 462   return debug_url; | 
|  | 463 } | 
|  | 464 | 
|  | 465 void DevToolsAndroidBridge::AgentHostDelegate::DeviceListChanged( | 
|  | 466     const DevToolsAndroidBridge::RemoteDevices& devices) { | 
|  | 467   if (!bridge_) { | 
|  | 468     pending_workers_.clear(); | 
|  | 469     return; | 
|  | 470   } | 
|  | 471   for (const auto& device : devices) { | 
|  | 472     for (const auto& browser : device->browsers()) { | 
|  | 473       for (const auto& page : browser->pages()) { | 
|  | 474         scoped_ptr<DevToolsTargetImpl> target(bridge_->CreatePageTarget(page)); | 
|  | 475         if (pending_workers_.count(target->GetId())) { | 
|  | 476           if (GetDebugURL(*page->dict_).length()) { | 
|  | 477             target->Inspect(Profile::FromBrowserContext(context_)); | 
|  | 478           } | 
|  | 479         } | 
|  | 480       } | 
|  | 481     } | 
|  | 482   } | 
|  | 483   pending_workers_.clear(); | 
|  | 484   if (bridge_) | 
|  | 485     bridge_->RemoveDeviceListListener(this); | 
|  | 486 } | 
|  | 487 | 
| 404 void DevToolsAndroidBridge::AgentHostDelegate::OnSocketOpened() { | 488 void DevToolsAndroidBridge::AgentHostDelegate::OnSocketOpened() { | 
| 405   socket_opened_ = true; | 489   socket_opened_ = true; | 
| 406   for (std::vector<std::string>::iterator it = pending_messages_.begin(); | 490   for (std::vector<std::string>::iterator it = pending_messages_.begin(); | 
| 407        it != pending_messages_.end(); ++it) { | 491        it != pending_messages_.end(); ++it) { | 
| 408     SendMessageToBackend(*it); | 492     SendMessageToBackend(*it); | 
| 409   } | 493   } | 
| 410   pending_messages_.clear(); | 494   pending_messages_.clear(); | 
| 411 } | 495 } | 
| 412 | 496 | 
| 413 void DevToolsAndroidBridge::AgentHostDelegate::OnFrameRead( | 497 void DevToolsAndroidBridge::AgentHostDelegate::OnFrameRead( | 
| (...skipping 28 matching lines...) Expand all  Loading... | 
| 442   base::WeakPtr<DevToolsAndroidBridge> bridge_; | 526   base::WeakPtr<DevToolsAndroidBridge> bridge_; | 
| 443   BrowserId browser_id_; | 527   BrowserId browser_id_; | 
| 444   std::string debug_url_; | 528   std::string debug_url_; | 
| 445   std::string frontend_url_; | 529   std::string frontend_url_; | 
| 446   std::string remote_id_; | 530   std::string remote_id_; | 
| 447   std::string remote_type_; | 531   std::string remote_type_; | 
| 448   std::string local_id_; | 532   std::string local_id_; | 
| 449   DISALLOW_COPY_AND_ASSIGN(RemotePageTarget); | 533   DISALLOW_COPY_AND_ASSIGN(RemotePageTarget); | 
| 450 }; | 534 }; | 
| 451 | 535 | 
| 452 static std::string GetStringProperty(const base::DictionaryValue& value, |  | 
| 453                                      const std::string& name) { |  | 
| 454   std::string result; |  | 
| 455   value.GetString(name, &result); |  | 
| 456   return result; |  | 
| 457 } |  | 
| 458 |  | 
| 459 static std::string BuildUniqueTargetId( |  | 
| 460     const DevToolsAndroidBridge::BrowserId& browser_id, |  | 
| 461     const base::DictionaryValue& value) { |  | 
| 462   return base::StringPrintf("%s:%s:%s", browser_id.first.c_str(), |  | 
| 463       browser_id.second.c_str(), GetStringProperty(value, "id").c_str()); |  | 
| 464 } |  | 
| 465 |  | 
| 466 static std::string GetFrontendURL(const base::DictionaryValue& value) { | 536 static std::string GetFrontendURL(const base::DictionaryValue& value) { | 
| 467   std::string frontend_url = GetStringProperty(value, "devtoolsFrontendUrl"); | 537   std::string frontend_url = GetStringProperty(value, "devtoolsFrontendUrl"); | 
| 468   size_t ws_param = frontend_url.find("?ws"); | 538   size_t ws_param = frontend_url.find("?ws"); | 
| 469   if (ws_param != std::string::npos) | 539   if (ws_param != std::string::npos) | 
| 470     frontend_url = frontend_url.substr(0, ws_param); | 540     frontend_url = frontend_url.substr(0, ws_param); | 
| 471   if (frontend_url.find("http:") == 0) | 541   if (frontend_url.find("http:") == 0) | 
| 472     frontend_url = "https:" + frontend_url.substr(5); | 542     frontend_url = "https:" + frontend_url.substr(5); | 
| 473   return frontend_url; | 543   return frontend_url; | 
| 474 } | 544 } | 
| 475 | 545 | 
| 476 static std::string GetDebugURL(const base::DictionaryValue& value) { |  | 
| 477   std::string debug_url = GetStringProperty(value, "webSocketDebuggerUrl"); |  | 
| 478 |  | 
| 479   if (debug_url.find("ws://") == 0) |  | 
| 480     debug_url = debug_url.substr(5); |  | 
| 481   else |  | 
| 482     debug_url = std::string(); |  | 
| 483   return debug_url; |  | 
| 484 } |  | 
| 485 | 546 | 
| 486 DevToolsAndroidBridge::RemotePageTarget::RemotePageTarget( | 547 DevToolsAndroidBridge::RemotePageTarget::RemotePageTarget( | 
| 487     DevToolsAndroidBridge* bridge, | 548     DevToolsAndroidBridge* bridge, | 
| 488     const BrowserId& browser_id, | 549     const BrowserId& browser_id, | 
| 489     const base::DictionaryValue& value) | 550     const base::DictionaryValue& value) | 
| 490     : DevToolsTargetImpl(AgentHostDelegate::GetOrCreateAgentHost( | 551     : DevToolsTargetImpl(AgentHostDelegate::GetOrCreateAgentHost( | 
| 491                              bridge, | 552                              bridge, | 
| 492                              BuildUniqueTargetId(browser_id, value), | 553                              BuildUniqueTargetId(browser_id, value), | 
| 493                              browser_id, | 554                              browser_id, | 
| 494                              GetDebugURL(value))), | 555                              GetDebugURL(value))), | 
| (...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 927     device_providers.push_back( | 988     device_providers.push_back( | 
| 928         new WebRTCDeviceProvider(profile_, signin_manager_, token_service_)); | 989         new WebRTCDeviceProvider(profile_, signin_manager_, token_service_)); | 
| 929   } | 990   } | 
| 930 | 991 | 
| 931   device_manager_->SetDeviceProviders(device_providers); | 992   device_manager_->SetDeviceProviders(device_providers); | 
| 932   if (NeedsDeviceListPolling()) { | 993   if (NeedsDeviceListPolling()) { | 
| 933     StopDeviceListPolling(); | 994     StopDeviceListPolling(); | 
| 934     StartDeviceListPolling(); | 995     StartDeviceListPolling(); | 
| 935   } | 996   } | 
| 936 } | 997 } | 
| OLD | NEW | 
|---|