| 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 | 43 |
| 44 const char kModelOffline[] = "Offline"; | 44 const char kModelOffline[] = "Offline"; |
| 45 | 45 |
| 46 const char kPageListRequest[] = "/json"; | 46 const char kPageListRequest[] = "/json"; |
| 47 const char kVersionRequest[] = "/json/version"; | 47 const char kVersionRequest[] = "/json/version"; |
| 48 const char kClosePageRequest[] = "/json/close/%s"; | 48 const char kClosePageRequest[] = "/json/close/%s"; |
| 49 const char kNewPageRequest[] = "/json/new"; | 49 const char kNewPageRequest[] = "/json/new"; |
| 50 const char kNewPageRequestWithURL[] = "/json/new?%s"; | 50 const char kNewPageRequestWithURL[] = "/json/new?%s"; |
| 51 const char kActivatePageRequest[] = "/json/activate/%s"; | 51 const char kActivatePageRequest[] = "/json/activate/%s"; |
| 52 const char kBrowserTargetSocket[] = "/devtools/browser"; | 52 const char kBrowserTargetSocket[] = "/devtools/browser"; |
| 53 const int kAdbPollingIntervalMs = 1000; | |
| 54 | 53 |
| 55 const char kUrlParam[] = "url"; | 54 const char kUrlParam[] = "url"; |
| 56 const char kPageReloadCommand[] = "Page.reload"; | 55 const char kPageReloadCommand[] = "Page.reload"; |
| 57 const char kPageNavigateCommand[] = "Page.navigate"; | 56 const char kPageNavigateCommand[] = "Page.navigate"; |
| 58 | 57 |
| 59 const int kMinVersionNewWithURL = 32; | 58 const int kMinVersionNewWithURL = 32; |
| 60 const int kNewPageNavigateDelayMs = 500; | 59 const int kNewPageNavigateDelayMs = 500; |
| 61 | 60 |
| 62 // DiscoveryRequest ----------------------------------------------------- | 61 // DiscoveryRequest ----------------------------------------------------- |
| 63 | 62 |
| (...skipping 773 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 837 if (!thread_) | 836 if (!thread_) |
| 838 return; | 837 return; |
| 839 // Shut down thread on FILE thread to join into IO. | 838 // Shut down thread on FILE thread to join into IO. |
| 840 BrowserThread::PostTask( | 839 BrowserThread::PostTask( |
| 841 BrowserThread::FILE, FROM_HERE, | 840 BrowserThread::FILE, FROM_HERE, |
| 842 base::Bind(&HandlerThread::StopThread, thread_)); | 841 base::Bind(&HandlerThread::StopThread, thread_)); |
| 843 } | 842 } |
| 844 | 843 |
| 845 // DevToolsAndroidBridge ------------------------------------------------------ | 844 // DevToolsAndroidBridge ------------------------------------------------------ |
| 846 | 845 |
| 846 const int DevToolsAndroidBridge::kAdbPollingIntervalMs = 1000; |
| 847 |
| 847 DevToolsAndroidBridge::DevToolsAndroidBridge(Profile* profile) | 848 DevToolsAndroidBridge::DevToolsAndroidBridge(Profile* profile) |
| 848 : profile_(profile), | 849 : profile_(profile), |
| 849 handler_thread_(HandlerThread::GetInstance()) { | 850 handler_thread_(HandlerThread::GetInstance()) { |
| 850 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 851 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 851 pref_change_registrar_.Init(profile_->GetPrefs()); | 852 pref_change_registrar_.Init(profile_->GetPrefs()); |
| 852 pref_change_registrar_.Add(prefs::kDevToolsDiscoverUsbDevicesEnabled, | 853 pref_change_registrar_.Add(prefs::kDevToolsDiscoverUsbDevicesEnabled, |
| 853 base::Bind(&DevToolsAndroidBridge::CreateDeviceProviders, | 854 base::Bind(&DevToolsAndroidBridge::CreateDeviceProviders, |
| 854 base::Unretained(this))); | 855 base::Unretained(this))); |
| 855 CreateDeviceProviders(); | 856 CreateDeviceProviders(); |
| 856 base::PostTaskAndReplyWithResult( | 857 base::PostTaskAndReplyWithResult( |
| 857 device_message_loop()->message_loop_proxy(), | 858 device_message_loop()->message_loop_proxy(), |
| 858 FROM_HERE, | 859 FROM_HERE, |
| 859 base::Bind(&AndroidDeviceManager::Create), | 860 base::Bind(&AndroidDeviceManager::Create), |
| 860 base::Bind(&DevToolsAndroidBridge::CreatedDeviceManager, this)); | 861 base::Bind(&DevToolsAndroidBridge::CreatedDeviceManager, this)); |
| 861 } | 862 } |
| 862 | 863 |
| 863 void DevToolsAndroidBridge::AddDeviceListListener( | 864 void DevToolsAndroidBridge::AddDeviceListListener( |
| 864 DeviceListListener* listener) { | 865 DeviceListListener* listener) { |
| 865 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 866 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 866 device_list_listeners_.push_back(listener); | 867 device_list_listeners_.push_back(listener); |
| 867 if (device_list_listeners_.size() == 1 && device_manager_) | 868 if (device_list_listeners_.size() == 1 && device_manager_) |
| 868 RequestDeviceList(); | 869 StartDeviceListPollingLoop(); |
| 869 } | 870 } |
| 870 | 871 |
| 871 void DevToolsAndroidBridge::RemoveDeviceListListener( | 872 void DevToolsAndroidBridge::RemoveDeviceListListener( |
| 872 DeviceListListener* listener) { | 873 DeviceListListener* listener) { |
| 873 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 874 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 874 DeviceListListeners::iterator it = std::find( | 875 DeviceListListeners::iterator it = std::find( |
| 875 device_list_listeners_.begin(), device_list_listeners_.end(), listener); | 876 device_list_listeners_.begin(), device_list_listeners_.end(), listener); |
| 876 DCHECK(it != device_list_listeners_.end()); | 877 DCHECK(it != device_list_listeners_.end()); |
| 877 device_list_listeners_.erase(it); | 878 device_list_listeners_.erase(it); |
| 878 if (device_list_listeners_.empty() && device_manager_) { | 879 if (device_list_listeners_.empty() && device_manager_) { |
| 879 device_message_loop()->PostTask(FROM_HERE, | 880 device_message_loop()->PostTask(FROM_HERE, |
| 880 base::Bind(&AndroidDeviceManager::Stop, device_manager_)); | 881 base::Bind(&AndroidDeviceManager::Stop, device_manager_)); |
| 882 StopDeviceListPollingLoop(); |
| 881 } | 883 } |
| 882 } | 884 } |
| 883 | 885 |
| 884 void DevToolsAndroidBridge::AddDeviceCountListener( | 886 void DevToolsAndroidBridge::AddDeviceCountListener( |
| 885 DeviceCountListener* listener) { | 887 DeviceCountListener* listener) { |
| 886 device_count_listeners_.push_back(listener); | 888 device_count_listeners_.push_back(listener); |
| 887 if (device_count_listeners_.size() == 1 && device_manager_) | 889 if (device_count_listeners_.size() == 1 && device_manager_) |
| 888 RequestDeviceCount(); | 890 StartDeviceCountPollingLoop(); |
| 889 } | 891 } |
| 890 | 892 |
| 891 void DevToolsAndroidBridge::RemoveDeviceCountListener( | 893 void DevToolsAndroidBridge::RemoveDeviceCountListener( |
| 892 DeviceCountListener* listener) { | 894 DeviceCountListener* listener) { |
| 893 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 895 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 894 DeviceCountListeners::iterator it = std::find( | 896 DeviceCountListeners::iterator it = std::find( |
| 895 device_count_listeners_.begin(), device_count_listeners_.end(), listener); | 897 device_count_listeners_.begin(), device_count_listeners_.end(), listener); |
| 896 DCHECK(it != device_count_listeners_.end()); | 898 DCHECK(it != device_count_listeners_.end()); |
| 897 device_count_listeners_.erase(it); | 899 device_count_listeners_.erase(it); |
| 900 if (device_count_listeners_.empty()) |
| 901 StopDeviceCountPollingLoop(); |
| 898 } | 902 } |
| 899 | 903 |
| 900 // static | 904 // static |
| 901 bool DevToolsAndroidBridge::HasDevToolsWindow(const std::string& agent_id) { | 905 bool DevToolsAndroidBridge::HasDevToolsWindow(const std::string& agent_id) { |
| 902 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 906 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 903 return g_host_delegates.Get().find(agent_id) != g_host_delegates.Get().end(); | 907 return g_host_delegates.Get().find(agent_id) != g_host_delegates.Get().end(); |
| 904 } | 908 } |
| 905 | 909 |
| 906 DevToolsAndroidBridge::~DevToolsAndroidBridge() { | 910 DevToolsAndroidBridge::~DevToolsAndroidBridge() { |
| 907 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 911 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 908 DCHECK(device_list_listeners_.empty()); | 912 DCHECK(device_list_listeners_.empty()); |
| 909 DCHECK(device_count_listeners_.empty()); | 913 DCHECK(device_count_listeners_.empty()); |
| 910 if (device_manager_) { | 914 if (device_manager_) { |
| 911 AndroidDeviceManager* raw_ptr = device_manager_.get(); | 915 AndroidDeviceManager* raw_ptr = device_manager_.get(); |
| 912 device_manager_->AddRef(); | 916 device_manager_->AddRef(); |
| 913 device_manager_ = NULL; | 917 device_manager_ = NULL; |
| 914 device_message_loop()->ReleaseSoon(FROM_HERE, raw_ptr); | 918 device_message_loop()->ReleaseSoon(FROM_HERE, raw_ptr); |
| 915 } | 919 } |
| 916 } | 920 } |
| 917 | 921 |
| 922 void DevToolsAndroidBridge::CreatedDeviceManager( |
| 923 scoped_refptr<AndroidDeviceManager> device_manager) { |
| 924 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 925 device_manager_ = device_manager; |
| 926 if (!device_list_listeners_.empty()) |
| 927 StartDeviceListPollingLoop(); |
| 928 if (!device_count_listeners_.empty()) |
| 929 StartDeviceCountPollingLoop(); |
| 930 } |
| 931 |
| 918 void DevToolsAndroidBridge::RequestDeviceList() { | 932 void DevToolsAndroidBridge::RequestDeviceList() { |
| 919 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 933 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 920 DCHECK(device_manager_); | 934 DCHECK(device_manager_); |
| 921 | 935 |
| 922 if (device_list_listeners_.empty()) | 936 if (device_list_listeners_.empty()) |
| 923 return; | 937 return; |
| 924 | 938 |
| 925 new DiscoveryRequest( | 939 new DiscoveryRequest(this, |
| 926 this, | 940 device_manager(), |
| 927 device_manager(), | 941 device_message_loop(), |
| 928 device_message_loop(), | 942 device_providers_, |
| 929 device_providers_, | 943 received_device_list_bound_.callback()); |
| 930 base::Bind(&DevToolsAndroidBridge::ReceivedDeviceList, this)); | |
| 931 } | |
| 932 | |
| 933 void DevToolsAndroidBridge::CreatedDeviceManager( | |
| 934 scoped_refptr<AndroidDeviceManager> device_manager) { | |
| 935 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 936 device_manager_ = device_manager; | |
| 937 if (!device_list_listeners_.empty()) | |
| 938 RequestDeviceList(); | |
| 939 if (!device_count_listeners_.empty()) | |
| 940 RequestDeviceCount(); | |
| 941 } | 944 } |
| 942 | 945 |
| 943 void DevToolsAndroidBridge::ReceivedDeviceList(RemoteDevices* devices_ptr) { | 946 void DevToolsAndroidBridge::ReceivedDeviceList(RemoteDevices* devices_ptr) { |
| 944 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 947 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 945 | 948 |
| 946 scoped_ptr<RemoteDevices> devices(devices_ptr); | 949 scoped_ptr<RemoteDevices> devices(devices_ptr); |
| 947 | 950 |
| 948 if (device_list_listeners_.empty()) | |
| 949 return; | |
| 950 | |
| 951 DeviceListListeners copy(device_list_listeners_); | 951 DeviceListListeners copy(device_list_listeners_); |
| 952 for (DeviceListListeners::iterator it = copy.begin(); it != copy.end(); ++it) | 952 for (DeviceListListeners::iterator it = copy.begin(); it != copy.end(); ++it) |
| 953 (*it)->DeviceListChanged(*devices.get()); | 953 (*it)->DeviceListChanged(*devices.get()); |
| 954 | 954 |
| 955 if (device_list_listeners_.empty()) |
| 956 return; |
| 957 |
| 955 BrowserThread::PostDelayedTask( | 958 BrowserThread::PostDelayedTask( |
| 956 BrowserThread::UI, | 959 BrowserThread::UI, |
| 957 FROM_HERE, | 960 FROM_HERE, |
| 958 base::Bind(&DevToolsAndroidBridge::RequestDeviceList, this), | 961 request_device_list_bound_.callback(), |
| 959 base::TimeDelta::FromMilliseconds(kAdbPollingIntervalMs)); | 962 base::TimeDelta::FromMilliseconds(kAdbPollingIntervalMs)); |
| 960 } | 963 } |
| 961 | 964 |
| 965 void DevToolsAndroidBridge::StartDeviceListPollingLoop() { |
| 966 request_device_list_bound_.Reset( |
| 967 base::Bind(&DevToolsAndroidBridge::RequestDeviceList, this)); |
| 968 received_device_list_bound_.Reset( |
| 969 base::Bind(&DevToolsAndroidBridge::ReceivedDeviceList, this)); |
| 970 RequestDeviceList(); |
| 971 } |
| 972 |
| 973 void DevToolsAndroidBridge::StopDeviceListPollingLoop() { |
| 974 request_device_list_bound_.Cancel(); |
| 975 received_device_list_bound_.Cancel(); |
| 976 } |
| 977 |
| 962 void DevToolsAndroidBridge::RequestDeviceCount() { | 978 void DevToolsAndroidBridge::RequestDeviceCount() { |
| 963 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 979 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 964 DCHECK(device_manager_); | 980 DCHECK(device_manager_); |
| 965 | 981 |
| 966 if (device_count_listeners_.empty()) | 982 if (device_count_listeners_.empty()) |
| 967 return; | 983 return; |
| 968 | 984 |
| 969 UsbDeviceProvider::CountDevices( | 985 UsbDeviceProvider::CountDevices(received_device_count_bound_.callback()); |
| 970 base::Bind(&DevToolsAndroidBridge::ReceivedDeviceCount, this)); | |
| 971 } | 986 } |
| 972 | 987 |
| 973 void DevToolsAndroidBridge::ReceivedDeviceCount(int count) { | 988 void DevToolsAndroidBridge::ReceivedDeviceCount(int count) { |
| 974 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 989 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 975 | 990 |
| 976 if (device_count_listeners_.empty()) | |
| 977 return; | |
| 978 | |
| 979 DeviceCountListeners copy(device_count_listeners_); | 991 DeviceCountListeners copy(device_count_listeners_); |
| 980 for (DeviceCountListeners::iterator it = copy.begin(); it != copy.end(); ++it) | 992 for (DeviceCountListeners::iterator it = copy.begin(); it != copy.end(); ++it) |
| 981 (*it)->DeviceCountChanged(count); | 993 (*it)->DeviceCountChanged(count); |
| 982 | 994 |
| 983 BrowserThread::PostDelayedTask( | 995 if (device_count_listeners_.empty()) |
| 984 BrowserThread::UI, | 996 return; |
| 985 FROM_HERE, | 997 |
| 986 base::Bind(&DevToolsAndroidBridge::RequestDeviceCount, this), | 998 ScheduleDeviceCountRequest(request_device_count_bound_.callback()); |
| 987 base::TimeDelta::FromMilliseconds(kAdbPollingIntervalMs)); | 999 } |
| 1000 |
| 1001 void DevToolsAndroidBridge::ScheduleDeviceCountRequest(base::Closure callback) { |
| 1002 if (!device_count_request_scheduler_for_test_.is_null()) |
| 1003 device_count_request_scheduler_for_test_.Run(callback); |
| 1004 else |
| 1005 BrowserThread::PostDelayedTask( |
| 1006 BrowserThread::UI, |
| 1007 FROM_HERE, |
| 1008 callback, |
| 1009 base::TimeDelta::FromMilliseconds(kAdbPollingIntervalMs)); |
| 1010 } |
| 1011 |
| 1012 void DevToolsAndroidBridge::StartDeviceCountPollingLoop() { |
| 1013 request_device_count_bound_.Reset( |
| 1014 base::Bind(&DevToolsAndroidBridge::RequestDeviceCount, this)); |
| 1015 received_device_count_bound_.Reset( |
| 1016 base::Bind(&DevToolsAndroidBridge::ReceivedDeviceCount, this)); |
| 1017 RequestDeviceCount(); |
| 1018 } |
| 1019 |
| 1020 void DevToolsAndroidBridge::StopDeviceCountPollingLoop() { |
| 1021 request_device_count_bound_.Cancel(); |
| 1022 received_device_count_bound_.Cancel(); |
| 988 } | 1023 } |
| 989 | 1024 |
| 990 void DevToolsAndroidBridge::CreateDeviceProviders() { | 1025 void DevToolsAndroidBridge::CreateDeviceProviders() { |
| 991 device_providers_.clear(); | 1026 device_providers_.clear(); |
| 992 #if defined(DEBUG_DEVTOOLS) | 1027 #if defined(DEBUG_DEVTOOLS) |
| 993 BrowserListTabContentsProvider::EnableTethering(); | 1028 BrowserListTabContentsProvider::EnableTethering(); |
| 994 // We cannot rely on command line switch here as we might want to connect | 1029 // We cannot rely on command line switch here as we might want to connect |
| 995 // to another instance of Chrome. Using hard-coded port number instead. | 1030 // to another instance of Chrome. Using hard-coded port number instead. |
| 996 const int kDefaultDebuggingPort = 9222; | 1031 const int kDefaultDebuggingPort = 9222; |
| 997 device_providers_.push_back(new SelfAsDeviceProvider(kDefaultDebuggingPort)); | 1032 device_providers_.push_back(new SelfAsDeviceProvider(kDefaultDebuggingPort)); |
| 998 #endif | 1033 #endif |
| 999 device_providers_.push_back(new AdbDeviceProvider()); | 1034 device_providers_.push_back(new AdbDeviceProvider()); |
| 1000 | 1035 |
| 1001 PrefService* service = profile_->GetPrefs(); | 1036 PrefService* service = profile_->GetPrefs(); |
| 1002 const PrefService::Preference* pref = | 1037 const PrefService::Preference* pref = |
| 1003 service->FindPreference(prefs::kDevToolsDiscoverUsbDevicesEnabled); | 1038 service->FindPreference(prefs::kDevToolsDiscoverUsbDevicesEnabled); |
| 1004 const base::Value* pref_value = pref->GetValue(); | 1039 const base::Value* pref_value = pref->GetValue(); |
| 1005 | 1040 |
| 1006 bool enabled; | 1041 bool enabled; |
| 1007 if (pref_value->GetAsBoolean(&enabled) && enabled) { | 1042 if (pref_value->GetAsBoolean(&enabled) && enabled) { |
| 1008 device_providers_.push_back(new UsbDeviceProvider(profile_)); | 1043 device_providers_.push_back(new UsbDeviceProvider(profile_)); |
| 1009 } | 1044 } |
| 1010 } | 1045 } |
| OLD | NEW |