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" |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 | 56 |
57 const int kMinVersionNewWithURL = 32; | 57 const int kMinVersionNewWithURL = 32; |
58 const int kNewPageNavigateDelayMs = 500; | 58 const int kNewPageNavigateDelayMs = 500; |
59 | 59 |
60 // DiscoveryRequest ----------------------------------------------------- | 60 // DiscoveryRequest ----------------------------------------------------- |
61 | 61 |
62 class DiscoveryRequest : public base::RefCountedThreadSafe< | 62 class DiscoveryRequest : public base::RefCountedThreadSafe< |
63 DiscoveryRequest, | 63 DiscoveryRequest, |
64 BrowserThread::DeleteOnUIThread> { | 64 BrowserThread::DeleteOnUIThread> { |
65 public: | 65 public: |
66 typedef base::Callback<void(scoped_ptr<DevToolsAndroidBridge::RemoteDevices>)> | 66 typedef base::Callback<void(const DevToolsAndroidBridge::RemoteDevices&)> |
67 DiscoveryCallback; | 67 DiscoveryCallback; |
68 typedef AndroidDeviceManager::Device Device; | 68 typedef AndroidDeviceManager::Device Device; |
69 typedef AndroidDeviceManager::Devices Devices; | 69 typedef AndroidDeviceManager::Devices Devices; |
70 | 70 |
71 DiscoveryRequest( | 71 DiscoveryRequest( |
72 AndroidDeviceManager* device_manager, | 72 AndroidDeviceManager* device_manager, |
73 const DiscoveryCallback& callback); | 73 const DiscoveryCallback& callback); |
74 | 74 |
75 private: | 75 private: |
76 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; | 76 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; |
(...skipping 15 matching lines...) Expand all Loading... |
92 } | 92 } |
93 | 93 |
94 void NextBrowser(); | 94 void NextBrowser(); |
95 void NextDevice(); | 95 void NextDevice(); |
96 | 96 |
97 void Respond(); | 97 void Respond(); |
98 | 98 |
99 DiscoveryCallback callback_; | 99 DiscoveryCallback callback_; |
100 Devices devices_; | 100 Devices devices_; |
101 DevToolsAndroidBridge::RemoteBrowsers browsers_; | 101 DevToolsAndroidBridge::RemoteBrowsers browsers_; |
102 scoped_ptr<DevToolsAndroidBridge::RemoteDevices> remote_devices_; | 102 DevToolsAndroidBridge::RemoteDevices remote_devices_; |
103 }; | 103 }; |
104 | 104 |
105 DiscoveryRequest::DiscoveryRequest( | 105 DiscoveryRequest::DiscoveryRequest( |
106 AndroidDeviceManager* device_manager, | 106 AndroidDeviceManager* device_manager, |
107 const DiscoveryCallback& callback) | 107 const DiscoveryCallback& callback) |
108 : callback_(callback) { | 108 : callback_(callback) { |
109 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 109 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
110 remote_devices_.reset(new DevToolsAndroidBridge::RemoteDevices()); | |
111 | 110 |
112 device_manager->QueryDevices( | 111 device_manager->QueryDevices( |
113 base::Bind(&DiscoveryRequest::ReceivedDevices, this)); | 112 base::Bind(&DiscoveryRequest::ReceivedDevices, this)); |
114 } | 113 } |
115 | 114 |
116 DiscoveryRequest::~DiscoveryRequest() { | 115 DiscoveryRequest::~DiscoveryRequest() { |
117 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
118 } | 117 } |
119 | 118 |
120 void DiscoveryRequest::ReceivedDevices(const Devices& devices) { | 119 void DiscoveryRequest::ReceivedDevices(const Devices& devices) { |
121 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 120 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
122 devices_ = devices; | 121 devices_ = devices; |
123 ProcessDevices(); | 122 ProcessDevices(); |
124 } | 123 } |
125 | 124 |
126 void DiscoveryRequest::ProcessDevices() { | 125 void DiscoveryRequest::ProcessDevices() { |
127 if (devices_.size() == 0) { | 126 if (devices_.size() == 0) { |
128 Respond(); | 127 Respond(); |
129 return; | 128 return; |
130 } | 129 } |
131 | 130 |
132 current_device()->QueryDeviceInfo( | 131 current_device()->QueryDeviceInfo( |
133 base::Bind(&DiscoveryRequest::ReceivedDeviceInfo, this)); | 132 base::Bind(&DiscoveryRequest::ReceivedDeviceInfo, this)); |
134 } | 133 } |
135 | 134 |
136 void DiscoveryRequest::ReceivedDeviceInfo( | 135 void DiscoveryRequest::ReceivedDeviceInfo( |
137 const AndroidDeviceManager::DeviceInfo& device_info) { | 136 const AndroidDeviceManager::DeviceInfo& device_info) { |
138 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 137 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
139 remote_devices_->push_back( | 138 remote_devices_.push_back( |
140 new DevToolsAndroidBridge::RemoteDevice(current_device(), device_info)); | 139 new DevToolsAndroidBridge::RemoteDevice(current_device(), device_info)); |
141 browsers_ = remote_devices_->back()->browsers(); | 140 browsers_ = remote_devices_.back()->browsers(); |
142 ProcessSockets(); | 141 ProcessSockets(); |
143 } | 142 } |
144 | 143 |
145 void DiscoveryRequest::ProcessSockets() { | 144 void DiscoveryRequest::ProcessSockets() { |
146 if (browsers_.size() == 0) { | 145 if (browsers_.size() == 0) { |
147 NextDevice(); | 146 NextDevice(); |
148 return; | 147 return; |
149 } | 148 } |
150 | 149 |
151 current_device()->SendJsonRequest( | 150 current_device()->SendJsonRequest( |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 browsers_.pop_back(); | 204 browsers_.pop_back(); |
206 ProcessSockets(); | 205 ProcessSockets(); |
207 } | 206 } |
208 | 207 |
209 void DiscoveryRequest::NextDevice() { | 208 void DiscoveryRequest::NextDevice() { |
210 devices_.pop_back(); | 209 devices_.pop_back(); |
211 ProcessDevices(); | 210 ProcessDevices(); |
212 } | 211 } |
213 | 212 |
214 void DiscoveryRequest::Respond() { | 213 void DiscoveryRequest::Respond() { |
215 callback_.Run(remote_devices_.Pass()); | 214 callback_.Run(remote_devices_); |
216 } | 215 } |
217 | 216 |
218 // ProtocolCommand ------------------------------------------------------------ | 217 // ProtocolCommand ------------------------------------------------------------ |
219 | 218 |
220 class ProtocolCommand | 219 class ProtocolCommand |
221 : public DevToolsAndroidBridge::AndroidWebSocket::Delegate { | 220 : public DevToolsAndroidBridge::AndroidWebSocket::Delegate { |
222 public: | 221 public: |
223 ProtocolCommand( | 222 ProtocolCommand( |
224 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser, | 223 scoped_refptr<DevToolsAndroidBridge::RemoteBrowser> browser, |
225 const std::string& debug_url, | 224 const std::string& debug_url, |
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
759 device_->OpenSocket(socket_name, callback); | 758 device_->OpenSocket(socket_name, callback); |
760 } | 759 } |
761 | 760 |
762 DevToolsAndroidBridge::RemoteDevice::~RemoteDevice() { | 761 DevToolsAndroidBridge::RemoteDevice::~RemoteDevice() { |
763 } | 762 } |
764 | 763 |
765 // DevToolsAndroidBridge ------------------------------------------------------ | 764 // DevToolsAndroidBridge ------------------------------------------------------ |
766 | 765 |
767 DevToolsAndroidBridge::DevToolsAndroidBridge(Profile* profile) | 766 DevToolsAndroidBridge::DevToolsAndroidBridge(Profile* profile) |
768 : profile_(profile), | 767 : profile_(profile), |
769 device_manager_(AndroidDeviceManager::Create()) { | 768 device_manager_(AndroidDeviceManager::Create()), |
| 769 task_scheduler_(base::Bind(&DevToolsAndroidBridge::ScheduleTaskDefault)) { |
770 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 770 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
771 pref_change_registrar_.Init(profile_->GetPrefs()); | 771 pref_change_registrar_.Init(profile_->GetPrefs()); |
772 pref_change_registrar_.Add(prefs::kDevToolsDiscoverUsbDevicesEnabled, | 772 pref_change_registrar_.Add(prefs::kDevToolsDiscoverUsbDevicesEnabled, |
773 base::Bind(&DevToolsAndroidBridge::CreateDeviceProviders, | 773 base::Bind(&DevToolsAndroidBridge::CreateDeviceProviders, |
774 base::Unretained(this))); | 774 base::Unretained(this))); |
775 CreateDeviceProviders(); | 775 CreateDeviceProviders(); |
776 } | 776 } |
777 | 777 |
778 void DevToolsAndroidBridge::AddDeviceListListener( | 778 void DevToolsAndroidBridge::AddDeviceListListener( |
779 DeviceListListener* listener) { | 779 DeviceListListener* listener) { |
780 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 780 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
781 device_list_listeners_.push_back(listener); | 781 device_list_listeners_.push_back(listener); |
782 if (device_list_listeners_.size() == 1) | 782 if (device_list_listeners_.size() == 1) |
783 RequestDeviceList(); | 783 StartDeviceListPolling(); |
784 } | 784 } |
785 | 785 |
786 void DevToolsAndroidBridge::RemoveDeviceListListener( | 786 void DevToolsAndroidBridge::RemoveDeviceListListener( |
787 DeviceListListener* listener) { | 787 DeviceListListener* listener) { |
788 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 788 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
789 DeviceListListeners::iterator it = std::find( | 789 DeviceListListeners::iterator it = std::find( |
790 device_list_listeners_.begin(), device_list_listeners_.end(), listener); | 790 device_list_listeners_.begin(), device_list_listeners_.end(), listener); |
791 DCHECK(it != device_list_listeners_.end()); | 791 DCHECK(it != device_list_listeners_.end()); |
792 device_list_listeners_.erase(it); | 792 device_list_listeners_.erase(it); |
793 if (device_list_listeners_.empty()) | 793 if (device_list_listeners_.empty()) |
794 devices_.clear(); | 794 StopDeviceListPolling(); |
795 } | 795 } |
796 | 796 |
797 void DevToolsAndroidBridge::AddDeviceCountListener( | 797 void DevToolsAndroidBridge::AddDeviceCountListener( |
798 DeviceCountListener* listener) { | 798 DeviceCountListener* listener) { |
799 device_count_listeners_.push_back(listener); | 799 device_count_listeners_.push_back(listener); |
800 if (device_count_listeners_.size() == 1) | 800 if (device_count_listeners_.size() == 1) |
801 RequestDeviceCount(); | 801 StartDeviceCountPolling(); |
802 } | 802 } |
803 | 803 |
804 void DevToolsAndroidBridge::RemoveDeviceCountListener( | 804 void DevToolsAndroidBridge::RemoveDeviceCountListener( |
805 DeviceCountListener* listener) { | 805 DeviceCountListener* listener) { |
806 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 806 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
807 DeviceCountListeners::iterator it = std::find( | 807 DeviceCountListeners::iterator it = std::find( |
808 device_count_listeners_.begin(), device_count_listeners_.end(), listener); | 808 device_count_listeners_.begin(), device_count_listeners_.end(), listener); |
809 DCHECK(it != device_count_listeners_.end()); | 809 DCHECK(it != device_count_listeners_.end()); |
810 device_count_listeners_.erase(it); | 810 device_count_listeners_.erase(it); |
| 811 if (device_count_listeners_.empty()) |
| 812 StopDeviceCountPolling(); |
811 } | 813 } |
812 | 814 |
813 // static | 815 // static |
814 bool DevToolsAndroidBridge::HasDevToolsWindow(const std::string& agent_id) { | 816 bool DevToolsAndroidBridge::HasDevToolsWindow(const std::string& agent_id) { |
815 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 817 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
816 return g_host_delegates.Get().find(agent_id) != g_host_delegates.Get().end(); | 818 return g_host_delegates.Get().find(agent_id) != g_host_delegates.Get().end(); |
817 } | 819 } |
818 | 820 |
819 DevToolsAndroidBridge::~DevToolsAndroidBridge() { | 821 DevToolsAndroidBridge::~DevToolsAndroidBridge() { |
820 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 822 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
821 DCHECK(device_list_listeners_.empty()); | 823 DCHECK(device_list_listeners_.empty()); |
822 DCHECK(device_count_listeners_.empty()); | 824 DCHECK(device_count_listeners_.empty()); |
823 } | 825 } |
824 | 826 |
825 void DevToolsAndroidBridge::RequestDeviceList() { | 827 void DevToolsAndroidBridge::StartDeviceListPolling() { |
| 828 device_list_callback_.Reset( |
| 829 base::Bind(&DevToolsAndroidBridge::ReceivedDeviceList, this)); |
| 830 RequestDeviceList(device_list_callback_.callback()); |
| 831 } |
| 832 |
| 833 void DevToolsAndroidBridge::StopDeviceListPolling() { |
| 834 device_list_callback_.Cancel(); |
| 835 devices_.clear(); |
| 836 } |
| 837 |
| 838 void DevToolsAndroidBridge::RequestDeviceList( |
| 839 const base::Callback<void(const RemoteDevices&)>& callback) { |
826 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 840 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
827 | 841 |
| 842 if (device_list_listeners_.empty() || |
| 843 !callback.Equals(device_list_callback_.callback())) |
| 844 return; |
| 845 |
| 846 new DiscoveryRequest(device_manager_.get(), callback); |
| 847 } |
| 848 |
| 849 void DevToolsAndroidBridge::ReceivedDeviceList(const RemoteDevices& devices) { |
| 850 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 851 |
| 852 DeviceListListeners copy(device_list_listeners_); |
| 853 for (DeviceListListeners::iterator it = copy.begin(); it != copy.end(); ++it) |
| 854 (*it)->DeviceListChanged(devices); |
| 855 |
828 if (device_list_listeners_.empty()) | 856 if (device_list_listeners_.empty()) |
829 return; | 857 return; |
830 | 858 |
831 new DiscoveryRequest( | 859 devices_ = devices; |
832 device_manager_.get(), | 860 |
833 base::Bind(&DevToolsAndroidBridge::ReceivedDeviceList, this)); | 861 task_scheduler_.Run( |
| 862 base::Bind(&DevToolsAndroidBridge::RequestDeviceList, |
| 863 this, device_list_callback_.callback())); |
834 } | 864 } |
835 | 865 |
836 void DevToolsAndroidBridge::ReceivedDeviceList( | 866 void DevToolsAndroidBridge::StartDeviceCountPolling() { |
837 scoped_ptr<RemoteDevices> devices) { | 867 device_count_callback_.Reset( |
| 868 base::Bind(&DevToolsAndroidBridge::ReceivedDeviceCount, this)); |
| 869 RequestDeviceCount(device_count_callback_.callback()); |
| 870 } |
| 871 |
| 872 void DevToolsAndroidBridge::StopDeviceCountPolling() { |
| 873 device_count_callback_.Cancel(); |
| 874 } |
| 875 |
| 876 void DevToolsAndroidBridge::RequestDeviceCount( |
| 877 const base::Callback<void(int)>& callback) { |
838 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 878 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
839 | 879 |
840 if (device_list_listeners_.empty()) | 880 if (device_count_listeners_.empty() || |
| 881 !callback.Equals(device_count_callback_.callback())) |
841 return; | 882 return; |
842 | 883 |
843 devices_ = *devices; | 884 UsbDeviceProvider::CountDevices(callback); |
844 | |
845 DeviceListListeners copy(device_list_listeners_); | |
846 for (DeviceListListeners::iterator it = copy.begin(); it != copy.end(); ++it) | |
847 (*it)->DeviceListChanged(*devices.get()); | |
848 | |
849 BrowserThread::PostDelayedTask( | |
850 BrowserThread::UI, | |
851 FROM_HERE, | |
852 base::Bind(&DevToolsAndroidBridge::RequestDeviceList, this), | |
853 base::TimeDelta::FromMilliseconds(kAdbPollingIntervalMs)); | |
854 } | |
855 | |
856 void DevToolsAndroidBridge::RequestDeviceCount() { | |
857 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
858 | |
859 if (device_count_listeners_.empty()) | |
860 return; | |
861 | |
862 UsbDeviceProvider::CountDevices( | |
863 base::Bind(&DevToolsAndroidBridge::ReceivedDeviceCount, this)); | |
864 } | 885 } |
865 | 886 |
866 void DevToolsAndroidBridge::ReceivedDeviceCount(int count) { | 887 void DevToolsAndroidBridge::ReceivedDeviceCount(int count) { |
867 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 888 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
868 | 889 |
869 if (device_count_listeners_.empty()) | |
870 return; | |
871 | |
872 DeviceCountListeners copy(device_count_listeners_); | 890 DeviceCountListeners copy(device_count_listeners_); |
873 for (DeviceCountListeners::iterator it = copy.begin(); it != copy.end(); ++it) | 891 for (DeviceCountListeners::iterator it = copy.begin(); it != copy.end(); ++it) |
874 (*it)->DeviceCountChanged(count); | 892 (*it)->DeviceCountChanged(count); |
875 | 893 |
| 894 if (device_count_listeners_.empty()) |
| 895 return; |
| 896 |
| 897 task_scheduler_.Run( |
| 898 base::Bind(&DevToolsAndroidBridge::RequestDeviceCount, |
| 899 this, device_count_callback_.callback())); |
| 900 } |
| 901 |
| 902 // static |
| 903 void DevToolsAndroidBridge::ScheduleTaskDefault(const base::Closure& task) { |
876 BrowserThread::PostDelayedTask( | 904 BrowserThread::PostDelayedTask( |
877 BrowserThread::UI, | 905 BrowserThread::UI, |
878 FROM_HERE, | 906 FROM_HERE, |
879 base::Bind(&DevToolsAndroidBridge::RequestDeviceCount, this), | 907 task, |
880 base::TimeDelta::FromMilliseconds(kAdbPollingIntervalMs)); | 908 base::TimeDelta::FromMilliseconds(kAdbPollingIntervalMs)); |
881 } | 909 } |
882 | 910 |
883 void DevToolsAndroidBridge::CreateDeviceProviders() { | 911 void DevToolsAndroidBridge::CreateDeviceProviders() { |
884 AndroidDeviceManager::DeviceProviders device_providers; | 912 AndroidDeviceManager::DeviceProviders device_providers; |
885 #if defined(DEBUG_DEVTOOLS) | 913 #if defined(DEBUG_DEVTOOLS) |
886 BrowserListTabContentsProvider::EnableTethering(); | 914 BrowserListTabContentsProvider::EnableTethering(); |
887 // We cannot rely on command line switch here as we might want to connect | 915 // We cannot rely on command line switch here as we might want to connect |
888 // to another instance of Chrome. Using hard-coded port number instead. | 916 // to another instance of Chrome. Using hard-coded port number instead. |
889 const int kDefaultDebuggingPort = 9222; | 917 const int kDefaultDebuggingPort = 9222; |
890 device_providers.push_back(new SelfAsDeviceProvider(kDefaultDebuggingPort)); | 918 device_providers.push_back(new SelfAsDeviceProvider(kDefaultDebuggingPort)); |
891 #endif | 919 #endif |
892 device_providers.push_back(new AdbDeviceProvider()); | 920 device_providers.push_back(new AdbDeviceProvider()); |
893 | 921 |
894 PrefService* service = profile_->GetPrefs(); | 922 PrefService* service = profile_->GetPrefs(); |
895 const PrefService::Preference* pref = | 923 const PrefService::Preference* pref = |
896 service->FindPreference(prefs::kDevToolsDiscoverUsbDevicesEnabled); | 924 service->FindPreference(prefs::kDevToolsDiscoverUsbDevicesEnabled); |
897 const base::Value* pref_value = pref->GetValue(); | 925 const base::Value* pref_value = pref->GetValue(); |
898 | 926 |
899 bool enabled; | 927 bool enabled; |
900 if (pref_value->GetAsBoolean(&enabled) && enabled) { | 928 if (pref_value->GetAsBoolean(&enabled) && enabled) { |
901 device_providers.push_back(new UsbDeviceProvider(profile_)); | 929 device_providers.push_back(new UsbDeviceProvider(profile_)); |
902 } | 930 } |
903 device_manager_->SetDeviceProviders(device_providers); | 931 device_manager_->SetDeviceProviders(device_providers); |
| 932 if (!device_list_listeners_.empty()) { |
| 933 StopDeviceListPolling(); |
| 934 StartDeviceListPolling(); |
| 935 } |
904 } | 936 } |
OLD | NEW |