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 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
773 base::Bind(&DevToolsAndroidBridge::CreateDeviceProviders, | 772 base::Bind(&DevToolsAndroidBridge::CreateDeviceProviders, |
774 base::Unretained(this))); | 773 base::Unretained(this))); |
775 CreateDeviceProviders(); | 774 CreateDeviceProviders(); |
776 } | 775 } |
777 | 776 |
778 void DevToolsAndroidBridge::AddDeviceListListener( | 777 void DevToolsAndroidBridge::AddDeviceListListener( |
779 DeviceListListener* listener) { | 778 DeviceListListener* listener) { |
780 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 779 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
781 device_list_listeners_.push_back(listener); | 780 device_list_listeners_.push_back(listener); |
782 if (device_list_listeners_.size() == 1) | 781 if (device_list_listeners_.size() == 1) |
783 RequestDeviceList(); | 782 StartDeviceListPolling(); |
784 } | 783 } |
785 | 784 |
786 void DevToolsAndroidBridge::RemoveDeviceListListener( | 785 void DevToolsAndroidBridge::RemoveDeviceListListener( |
787 DeviceListListener* listener) { | 786 DeviceListListener* listener) { |
788 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 787 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
789 DeviceListListeners::iterator it = std::find( | 788 DeviceListListeners::iterator it = std::find( |
790 device_list_listeners_.begin(), device_list_listeners_.end(), listener); | 789 device_list_listeners_.begin(), device_list_listeners_.end(), listener); |
791 DCHECK(it != device_list_listeners_.end()); | 790 DCHECK(it != device_list_listeners_.end()); |
792 device_list_listeners_.erase(it); | 791 device_list_listeners_.erase(it); |
793 if (device_list_listeners_.empty()) | 792 if (device_list_listeners_.empty()) |
794 devices_.clear(); | 793 StopDeviceListPolling(); |
795 } | 794 } |
796 | 795 |
797 void DevToolsAndroidBridge::AddDeviceCountListener( | 796 void DevToolsAndroidBridge::AddDeviceCountListener( |
798 DeviceCountListener* listener) { | 797 DeviceCountListener* listener) { |
799 device_count_listeners_.push_back(listener); | 798 device_count_listeners_.push_back(listener); |
800 if (device_count_listeners_.size() == 1) | 799 if (device_count_listeners_.size() == 1) { |
801 RequestDeviceCount(); | 800 device_count_callback_.Reset( |
801 base::Bind(&DevToolsAndroidBridge::ReceivedDeviceCount, this)); | |
802 RequestDeviceCount(device_count_callback_.callback()); | |
Vladislav Kaznacheev
2014/06/02 18:09:43
I do not see the reason not to extract the 3 lines
vkuzkokov
2014/06/03 09:20:50
Done.
| |
803 } | |
802 } | 804 } |
803 | 805 |
804 void DevToolsAndroidBridge::RemoveDeviceCountListener( | 806 void DevToolsAndroidBridge::RemoveDeviceCountListener( |
805 DeviceCountListener* listener) { | 807 DeviceCountListener* listener) { |
806 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 808 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
807 DeviceCountListeners::iterator it = std::find( | 809 DeviceCountListeners::iterator it = std::find( |
808 device_count_listeners_.begin(), device_count_listeners_.end(), listener); | 810 device_count_listeners_.begin(), device_count_listeners_.end(), listener); |
809 DCHECK(it != device_count_listeners_.end()); | 811 DCHECK(it != device_count_listeners_.end()); |
810 device_count_listeners_.erase(it); | 812 device_count_listeners_.erase(it); |
813 if (device_count_listeners_.empty()) | |
814 device_count_callback_.Cancel(); | |
Vladislav Kaznacheev
2014/06/02 18:09:43
Although it is just a single line, it would look c
vkuzkokov
2014/06/03 09:20:50
Done.
| |
811 } | 815 } |
812 | 816 |
813 // static | 817 // static |
814 bool DevToolsAndroidBridge::HasDevToolsWindow(const std::string& agent_id) { | 818 bool DevToolsAndroidBridge::HasDevToolsWindow(const std::string& agent_id) { |
815 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 819 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
816 return g_host_delegates.Get().find(agent_id) != g_host_delegates.Get().end(); | 820 return g_host_delegates.Get().find(agent_id) != g_host_delegates.Get().end(); |
817 } | 821 } |
818 | 822 |
819 DevToolsAndroidBridge::~DevToolsAndroidBridge() { | 823 DevToolsAndroidBridge::~DevToolsAndroidBridge() { |
820 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 824 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
821 DCHECK(device_list_listeners_.empty()); | 825 DCHECK(device_list_listeners_.empty()); |
822 DCHECK(device_count_listeners_.empty()); | 826 DCHECK(device_count_listeners_.empty()); |
823 } | 827 } |
824 | 828 |
825 void DevToolsAndroidBridge::RequestDeviceList() { | 829 void DevToolsAndroidBridge::StartDeviceListPolling() { |
830 device_list_callback_.Reset( | |
831 base::Bind(&DevToolsAndroidBridge::ReceivedDeviceList, this)); | |
832 RequestDeviceList(device_list_callback_.callback()); | |
833 } | |
834 | |
835 void DevToolsAndroidBridge::StopDeviceListPolling() { | |
836 device_list_callback_.Cancel(); | |
837 devices_.clear(); | |
838 } | |
839 | |
840 void DevToolsAndroidBridge::RequestDeviceList( | |
841 const base::Callback<void(const RemoteDevices&)>& callback) { | |
826 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 842 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
827 | 843 |
844 if (device_list_listeners_.empty() || | |
845 !callback.Equals(device_list_callback_.callback())) | |
846 return; | |
847 | |
848 new DiscoveryRequest(device_manager_.get(), callback); | |
849 } | |
850 | |
851 void DevToolsAndroidBridge::ReceivedDeviceList(const RemoteDevices& devices) { | |
852 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
853 | |
854 DeviceListListeners copy(device_list_listeners_); | |
855 for (DeviceListListeners::iterator it = copy.begin(); it != copy.end(); ++it) | |
856 (*it)->DeviceListChanged(devices); | |
857 | |
828 if (device_list_listeners_.empty()) | 858 if (device_list_listeners_.empty()) |
829 return; | 859 return; |
830 | 860 |
831 new DiscoveryRequest( | 861 devices_ = devices; |
832 device_manager_.get(), | |
833 base::Bind(&DevToolsAndroidBridge::ReceivedDeviceList, this)); | |
834 } | |
835 | |
836 void DevToolsAndroidBridge::ReceivedDeviceList( | |
837 scoped_ptr<RemoteDevices> devices) { | |
838 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
839 | |
840 if (device_list_listeners_.empty()) | |
841 return; | |
842 | |
843 devices_ = *devices; | |
844 | |
845 DeviceListListeners copy(device_list_listeners_); | |
846 for (DeviceListListeners::iterator it = copy.begin(); it != copy.end(); ++it) | |
847 (*it)->DeviceListChanged(*devices.get()); | |
848 | 862 |
849 BrowserThread::PostDelayedTask( | 863 BrowserThread::PostDelayedTask( |
850 BrowserThread::UI, | 864 BrowserThread::UI, |
851 FROM_HERE, | 865 FROM_HERE, |
852 base::Bind(&DevToolsAndroidBridge::RequestDeviceList, this), | 866 base::Bind(&DevToolsAndroidBridge::RequestDeviceList, |
867 this, device_list_callback_.callback()), | |
853 base::TimeDelta::FromMilliseconds(kAdbPollingIntervalMs)); | 868 base::TimeDelta::FromMilliseconds(kAdbPollingIntervalMs)); |
854 } | 869 } |
855 | 870 |
856 void DevToolsAndroidBridge::RequestDeviceCount() { | 871 void DevToolsAndroidBridge::RequestDeviceCount( |
872 const base::Callback<void(int)>& callback) { | |
857 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 873 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
858 | 874 |
859 if (device_count_listeners_.empty()) | 875 if (device_count_listeners_.empty() || |
876 !callback.Equals(device_count_callback_.callback())) | |
860 return; | 877 return; |
861 | 878 |
862 UsbDeviceProvider::CountDevices( | 879 UsbDeviceProvider::CountDevices(callback); |
863 base::Bind(&DevToolsAndroidBridge::ReceivedDeviceCount, this)); | |
864 } | 880 } |
865 | 881 |
866 void DevToolsAndroidBridge::ReceivedDeviceCount(int count) { | 882 void DevToolsAndroidBridge::ReceivedDeviceCount(int count) { |
867 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 883 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
868 | 884 |
869 if (device_count_listeners_.empty()) | |
870 return; | |
871 | |
872 DeviceCountListeners copy(device_count_listeners_); | 885 DeviceCountListeners copy(device_count_listeners_); |
873 for (DeviceCountListeners::iterator it = copy.begin(); it != copy.end(); ++it) | 886 for (DeviceCountListeners::iterator it = copy.begin(); it != copy.end(); ++it) |
874 (*it)->DeviceCountChanged(count); | 887 (*it)->DeviceCountChanged(count); |
875 | 888 |
876 BrowserThread::PostDelayedTask( | 889 if (device_count_listeners_.empty()) |
877 BrowserThread::UI, | 890 return; |
878 FROM_HERE, | 891 |
879 base::Bind(&DevToolsAndroidBridge::RequestDeviceCount, this), | 892 ScheduleDeviceCountRequest( |
880 base::TimeDelta::FromMilliseconds(kAdbPollingIntervalMs)); | 893 base::Bind(&DevToolsAndroidBridge::RequestDeviceCount, |
894 this, device_count_callback_.callback())); | |
895 } | |
896 | |
897 void DevToolsAndroidBridge::ScheduleDeviceCountRequest( | |
898 const base::Closure& callback) { | |
899 if (!device_count_scheduler_for_test_.is_null()) { | |
Vladislav Kaznacheev
2014/06/02 18:09:43
I have an idea:
1. Call this member |task_schedule
vkuzkokov
2014/06/03 09:20:50
Done.
| |
900 device_count_scheduler_for_test_.Run(callback); | |
901 } else { | |
902 BrowserThread::PostDelayedTask( | |
903 BrowserThread::UI, | |
904 FROM_HERE, | |
905 callback, | |
906 base::TimeDelta::FromMilliseconds(kAdbPollingIntervalMs)); | |
907 } | |
881 } | 908 } |
882 | 909 |
883 void DevToolsAndroidBridge::CreateDeviceProviders() { | 910 void DevToolsAndroidBridge::CreateDeviceProviders() { |
884 AndroidDeviceManager::DeviceProviders device_providers; | 911 AndroidDeviceManager::DeviceProviders device_providers; |
885 #if defined(DEBUG_DEVTOOLS) | 912 #if defined(DEBUG_DEVTOOLS) |
886 BrowserListTabContentsProvider::EnableTethering(); | 913 BrowserListTabContentsProvider::EnableTethering(); |
887 // We cannot rely on command line switch here as we might want to connect | 914 // 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. | 915 // to another instance of Chrome. Using hard-coded port number instead. |
889 const int kDefaultDebuggingPort = 9222; | 916 const int kDefaultDebuggingPort = 9222; |
890 device_providers.push_back(new SelfAsDeviceProvider(kDefaultDebuggingPort)); | 917 device_providers.push_back(new SelfAsDeviceProvider(kDefaultDebuggingPort)); |
891 #endif | 918 #endif |
892 device_providers.push_back(new AdbDeviceProvider()); | 919 device_providers.push_back(new AdbDeviceProvider()); |
893 | 920 |
894 PrefService* service = profile_->GetPrefs(); | 921 PrefService* service = profile_->GetPrefs(); |
895 const PrefService::Preference* pref = | 922 const PrefService::Preference* pref = |
896 service->FindPreference(prefs::kDevToolsDiscoverUsbDevicesEnabled); | 923 service->FindPreference(prefs::kDevToolsDiscoverUsbDevicesEnabled); |
897 const base::Value* pref_value = pref->GetValue(); | 924 const base::Value* pref_value = pref->GetValue(); |
898 | 925 |
899 bool enabled; | 926 bool enabled; |
900 if (pref_value->GetAsBoolean(&enabled) && enabled) { | 927 if (pref_value->GetAsBoolean(&enabled) && enabled) { |
901 device_providers.push_back(new UsbDeviceProvider(profile_)); | 928 device_providers.push_back(new UsbDeviceProvider(profile_)); |
902 } | 929 } |
903 device_manager_->SetDeviceProviders(device_providers); | 930 device_manager_->SetDeviceProviders(device_providers); |
931 if (!device_list_listeners_.empty()) { | |
932 StopDeviceListPolling(); | |
933 StartDeviceListPolling(); | |
934 } | |
904 } | 935 } |
OLD | NEW |