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/chrome_devtools_manager_delegate.h" | 5 #include "chrome/browser/devtools/chrome_devtools_manager_delegate.h" |
6 | 6 |
7 #include "base/memory/ptr_util.h" | 7 #include "base/memory/ptr_util.h" |
8 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
9 #include "build/build_config.h" | 9 #include "build/build_config.h" |
10 #include "chrome/browser/devtools/device/android_device_manager.h" | 10 #include "chrome/browser/devtools/device/android_device_manager.h" |
11 #include "chrome/browser/devtools/device/tcp_device_provider.h" | 11 #include "chrome/browser/devtools/device/tcp_device_provider.h" |
12 #include "chrome/browser/devtools/devtools_network_protocol_handler.h" | 12 #include "chrome/browser/devtools/devtools_network_protocol_handler.h" |
13 #include "chrome/browser/devtools/devtools_protocol_constants.h" | 13 #include "chrome/browser/devtools/devtools_protocol_constants.h" |
14 #include "chrome/browser/devtools/devtools_window.h" | 14 #include "chrome/browser/devtools/devtools_window.h" |
15 #include "chrome/browser/extensions/extension_tab_util.h" | 15 #include "chrome/browser/extensions/extension_tab_util.h" |
16 #include "chrome/browser/profiles/profile.h" | 16 #include "chrome/browser/profiles/profile.h" |
17 #include "chrome/browser/profiles/profile_manager.h" | 17 #include "chrome/browser/profiles/profile_manager.h" |
18 #include "chrome/browser/ui/browser_navigator.h" | 18 #include "chrome/browser/ui/browser_navigator.h" |
19 #include "chrome/browser/ui/browser_navigator_params.h" | 19 #include "chrome/browser/ui/browser_navigator_params.h" |
20 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" | 20 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" |
21 #include "chrome/grit/browser_resources.h" | 21 #include "chrome/grit/browser_resources.h" |
22 #include "components/guest_view/browser/guest_view_base.h" | 22 #include "components/guest_view/browser/guest_view_base.h" |
23 #include "content/public/browser/devtools_agent_host.h" | 23 #include "content/public/browser/devtools_agent_host.h" |
24 #include "content/public/browser/render_frame_host.h" | 24 #include "content/public/browser/render_frame_host.h" |
25 #include "content/public/browser/web_contents.h" | 25 #include "content/public/browser/web_contents.h" |
26 #include "extensions/browser/extension_host.h" | 26 #include "extensions/browser/extension_host.h" |
27 #include "extensions/browser/extension_registry.h" | 27 #include "extensions/browser/extension_registry.h" |
28 #include "extensions/browser/process_manager.h" | 28 #include "extensions/browser/process_manager.h" |
29 #include "net/base/host_port_pair.h" | |
30 #include "ui/base/resource/resource_bundle.h" | 29 #include "ui/base/resource/resource_bundle.h" |
31 | 30 |
32 using content::DevToolsAgentHost; | 31 using content::DevToolsAgentHost; |
33 | 32 |
34 char ChromeDevToolsManagerDelegate::kTypeApp[] = "app"; | 33 char ChromeDevToolsManagerDelegate::kTypeApp[] = "app"; |
35 char ChromeDevToolsManagerDelegate::kTypeBackgroundPage[] = "background_page"; | 34 char ChromeDevToolsManagerDelegate::kTypeBackgroundPage[] = "background_page"; |
36 char ChromeDevToolsManagerDelegate::kTypeWebView[] = "webview"; | 35 char ChromeDevToolsManagerDelegate::kTypeWebView[] = "webview"; |
37 | 36 |
38 char kLocationsParam[] = "locations"; | 37 char kLocationsParam[] = "locations"; |
39 char kHostParam[] = "host"; | 38 char kHostParam[] = "host"; |
40 char kPortParam[] = "port"; | 39 char kPortParam[] = "port"; |
41 | 40 |
| 41 class ChromeDevToolsManagerDelegate::HostData { |
| 42 public: |
| 43 HostData() {} |
| 44 ~HostData() {} |
| 45 |
| 46 RemoteLocations& remote_locations() { return remote_locations_; } |
| 47 |
| 48 void set_remote_locations(RemoteLocations& locations) { |
| 49 remote_locations_.swap(locations); |
| 50 } |
| 51 |
| 52 private: |
| 53 RemoteLocations remote_locations_; |
| 54 }; |
| 55 |
42 ChromeDevToolsManagerDelegate::ChromeDevToolsManagerDelegate() | 56 ChromeDevToolsManagerDelegate::ChromeDevToolsManagerDelegate() |
43 : network_protocol_handler_(new DevToolsNetworkProtocolHandler()), | 57 : network_protocol_handler_(new DevToolsNetworkProtocolHandler()) { |
44 remote_locations_requester_(nullptr) { | |
45 content::DevToolsAgentHost::AddObserver(this); | 58 content::DevToolsAgentHost::AddObserver(this); |
46 } | 59 } |
47 | 60 |
48 ChromeDevToolsManagerDelegate::~ChromeDevToolsManagerDelegate() { | 61 ChromeDevToolsManagerDelegate::~ChromeDevToolsManagerDelegate() { |
49 content::DevToolsAgentHost::RemoveObserver(this); | 62 content::DevToolsAgentHost::RemoveObserver(this); |
50 } | 63 } |
51 | 64 |
52 void ChromeDevToolsManagerDelegate::Inspect( | 65 void ChromeDevToolsManagerDelegate::Inspect( |
53 content::DevToolsAgentHost* agent_host) { | 66 content::DevToolsAgentHost* agent_host) { |
54 DevToolsWindow::OpenDevToolsWindow(agent_host, nullptr); | 67 DevToolsWindow::OpenDevToolsWindow(agent_host, nullptr); |
55 } | 68 } |
56 | 69 |
57 void ChromeDevToolsManagerDelegate::DevicesAvailable( | |
58 const DevToolsDeviceDiscovery::CompleteDevices& devices) { | |
59 DevToolsAgentHost::List remote_targets; | |
60 for (const auto& complete : devices) { | |
61 for (const auto& browser : complete.second->browsers()) { | |
62 for (const auto& page : browser->pages()) | |
63 remote_targets.push_back(page->CreateTarget()); | |
64 } | |
65 } | |
66 remote_agent_hosts_.swap(remote_targets); | |
67 } | |
68 | |
69 base::DictionaryValue* ChromeDevToolsManagerDelegate::HandleCommand( | 70 base::DictionaryValue* ChromeDevToolsManagerDelegate::HandleCommand( |
70 DevToolsAgentHost* agent_host, | 71 DevToolsAgentHost* agent_host, |
71 base::DictionaryValue* command_dict) { | 72 base::DictionaryValue* command_dict) { |
72 | 73 |
73 int id = 0; | 74 int id = 0; |
74 std::string method; | 75 std::string method; |
75 base::DictionaryValue* params = nullptr; | 76 base::DictionaryValue* params = nullptr; |
76 if (!DevToolsProtocol::ParseCommand(command_dict, &id, &method, ¶ms)) | 77 if (!DevToolsProtocol::ParseCommand(command_dict, &id, &method, ¶ms)) |
77 return nullptr; | 78 return nullptr; |
78 | 79 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 } | 163 } |
163 | 164 |
164 std::string ChromeDevToolsManagerDelegate::GetFrontendResource( | 165 std::string ChromeDevToolsManagerDelegate::GetFrontendResource( |
165 const std::string& path) { | 166 const std::string& path) { |
166 return content::DevToolsFrontendHost::GetFrontendResource(path).as_string(); | 167 return content::DevToolsFrontendHost::GetFrontendResource(path).as_string(); |
167 } | 168 } |
168 | 169 |
169 void ChromeDevToolsManagerDelegate::DevToolsAgentHostAttached( | 170 void ChromeDevToolsManagerDelegate::DevToolsAgentHostAttached( |
170 content::DevToolsAgentHost* agent_host) { | 171 content::DevToolsAgentHost* agent_host) { |
171 network_protocol_handler_->DevToolsAgentStateChanged(agent_host, true); | 172 network_protocol_handler_->DevToolsAgentStateChanged(agent_host, true); |
| 173 |
| 174 DCHECK(host_data_.find(agent_host) == host_data_.end()); |
| 175 host_data_[agent_host].reset(new ChromeDevToolsManagerDelegate::HostData()); |
172 } | 176 } |
173 | 177 |
174 void ChromeDevToolsManagerDelegate::DevToolsAgentHostDetached( | 178 void ChromeDevToolsManagerDelegate::DevToolsAgentHostDetached( |
175 content::DevToolsAgentHost* agent_host) { | 179 content::DevToolsAgentHost* agent_host) { |
176 if (agent_host == remote_locations_requester_) { | 180 network_protocol_handler_->DevToolsAgentStateChanged(agent_host, false); |
177 remote_locations_requester_ = nullptr; | 181 // This class is created lazily, so it may not know about some attached hosts. |
| 182 if (host_data_.find(agent_host) != host_data_.end()) { |
| 183 host_data_.erase(agent_host); |
| 184 UpdateDeviceDiscovery(); |
| 185 } |
| 186 } |
| 187 |
| 188 void ChromeDevToolsManagerDelegate::DevicesAvailable( |
| 189 const DevToolsDeviceDiscovery::CompleteDevices& devices) { |
| 190 DevToolsAgentHost::List remote_targets; |
| 191 for (const auto& complete : devices) { |
| 192 for (const auto& browser : complete.second->browsers()) { |
| 193 for (const auto& page : browser->pages()) |
| 194 remote_targets.push_back(page->CreateTarget()); |
| 195 } |
| 196 } |
| 197 remote_agent_hosts_.swap(remote_targets); |
| 198 } |
| 199 |
| 200 void ChromeDevToolsManagerDelegate::UpdateDeviceDiscovery() { |
| 201 RemoteLocations remote_locations; |
| 202 for (const auto& pair : host_data_) { |
| 203 RemoteLocations& locations = pair.second->remote_locations(); |
| 204 remote_locations.insert(locations.begin(), locations.end()); |
| 205 } |
| 206 |
| 207 bool equals = remote_locations.size() == remote_locations_.size(); |
| 208 if (equals) { |
| 209 RemoteLocations::iterator it1 = remote_locations.begin(); |
| 210 RemoteLocations::iterator it2 = remote_locations_.begin(); |
| 211 while (it1 != remote_locations.end()) { |
| 212 DCHECK(it2 != remote_locations_.end()); |
| 213 if (!(*it1).Equals(*it2)) |
| 214 equals = false; |
| 215 ++it1; |
| 216 ++it2; |
| 217 } |
| 218 DCHECK(it2 == remote_locations_.end()); |
| 219 } |
| 220 |
| 221 if (equals) |
| 222 return; |
| 223 |
| 224 if (remote_locations.empty()) { |
178 device_discovery_.reset(); | 225 device_discovery_.reset(); |
179 remote_agent_hosts_.clear(); | 226 remote_agent_hosts_.clear(); |
| 227 } else { |
| 228 if (!device_manager_) |
| 229 device_manager_ = AndroidDeviceManager::Create(); |
| 230 |
| 231 AndroidDeviceManager::DeviceProviders providers; |
| 232 providers.push_back(new TCPDeviceProvider(remote_locations)); |
| 233 device_manager_->SetDeviceProviders(providers); |
| 234 |
| 235 device_discovery_.reset(new DevToolsDeviceDiscovery(device_manager_.get(), |
| 236 base::Bind(&ChromeDevToolsManagerDelegate::DevicesAvailable, |
| 237 base::Unretained(this)))); |
180 } | 238 } |
181 network_protocol_handler_->DevToolsAgentStateChanged(agent_host, false); | 239 remote_locations_.swap(remote_locations); |
182 } | 240 } |
183 | 241 |
184 std::unique_ptr<base::DictionaryValue> | 242 std::unique_ptr<base::DictionaryValue> |
185 ChromeDevToolsManagerDelegate::SetRemoteLocations( | 243 ChromeDevToolsManagerDelegate::SetRemoteLocations( |
186 content::DevToolsAgentHost* agent_host, | 244 content::DevToolsAgentHost* agent_host, |
187 int command_id, | 245 int command_id, |
188 base::DictionaryValue* params) { | 246 base::DictionaryValue* params) { |
189 if (remote_locations_requester_) { | 247 if (host_data_.find(agent_host) == host_data_.end()) { |
190 return DevToolsProtocol::CreateInvalidParamsResponse( | 248 return DevToolsProtocol::CreateInvalidParamsResponse( |
191 command_id, | 249 command_id, "Cannot find agent host"); |
192 "Remote locations are already in use by another client."); | |
193 } | 250 } |
194 | 251 |
195 remote_locations_requester_ = agent_host; | |
196 std::set<net::HostPortPair> tcp_locations; | 252 std::set<net::HostPortPair> tcp_locations; |
197 base::ListValue* locations; | 253 base::ListValue* locations; |
198 if (!params->GetList(kLocationsParam, &locations)) | 254 if (!params->GetList(kLocationsParam, &locations)) |
199 return DevToolsProtocol::CreateInvalidParamsResponse(command_id, | 255 return DevToolsProtocol::CreateInvalidParamsResponse(command_id, |
200 kLocationsParam); | 256 kLocationsParam); |
201 for (const auto& item : *locations) { | 257 for (const auto& item : *locations) { |
202 if (!item->IsType(base::Value::Type::DICTIONARY)) { | 258 if (!item->IsType(base::Value::Type::DICTIONARY)) { |
203 return DevToolsProtocol::CreateInvalidParamsResponse(command_id, | 259 return DevToolsProtocol::CreateInvalidParamsResponse(command_id, |
204 kLocationsParam); | 260 kLocationsParam); |
205 } | 261 } |
206 base::DictionaryValue* dictionary = | 262 base::DictionaryValue* dictionary = |
207 static_cast<base::DictionaryValue*>(item.get()); | 263 static_cast<base::DictionaryValue*>(item.get()); |
208 std::string host; | 264 std::string host; |
209 if (!dictionary->GetStringWithoutPathExpansion(kHostParam, &host)) { | 265 if (!dictionary->GetStringWithoutPathExpansion(kHostParam, &host)) { |
210 return DevToolsProtocol::CreateInvalidParamsResponse(command_id, | 266 return DevToolsProtocol::CreateInvalidParamsResponse(command_id, |
211 kLocationsParam); | 267 kLocationsParam); |
212 } | 268 } |
213 int port = 0; | 269 int port = 0; |
214 if (!dictionary->GetIntegerWithoutPathExpansion(kPortParam, &port)) { | 270 if (!dictionary->GetIntegerWithoutPathExpansion(kPortParam, &port)) { |
215 return DevToolsProtocol::CreateInvalidParamsResponse(command_id, | 271 return DevToolsProtocol::CreateInvalidParamsResponse(command_id, |
216 kLocationsParam); | 272 kLocationsParam); |
217 } | 273 } |
218 tcp_locations.insert(net::HostPortPair(host, port)); | 274 tcp_locations.insert(net::HostPortPair(host, port)); |
219 } | 275 } |
220 | 276 |
221 if (tcp_locations.empty()) { | 277 host_data_[agent_host]->set_remote_locations(tcp_locations); |
222 device_discovery_.reset(); | 278 UpdateDeviceDiscovery(); |
223 remote_agent_hosts_.clear(); | |
224 } else { | |
225 if (!device_manager_) | |
226 device_manager_ = AndroidDeviceManager::Create(); | |
227 | |
228 AndroidDeviceManager::DeviceProviders providers; | |
229 providers.push_back(new TCPDeviceProvider(tcp_locations)); | |
230 device_manager_->SetDeviceProviders(providers); | |
231 | |
232 device_discovery_.reset(new DevToolsDeviceDiscovery(device_manager_.get(), | |
233 base::Bind(&ChromeDevToolsManagerDelegate::DevicesAvailable, | |
234 base::Unretained(this)))); | |
235 } | |
236 | 279 |
237 std::unique_ptr<base::DictionaryValue> result( | 280 std::unique_ptr<base::DictionaryValue> result( |
238 base::MakeUnique<base::DictionaryValue>()); | 281 base::MakeUnique<base::DictionaryValue>()); |
239 return DevToolsProtocol::CreateSuccessResponse(command_id, std::move(result)); | 282 return DevToolsProtocol::CreateSuccessResponse(command_id, std::move(result)); |
240 } | 283 } |
OLD | NEW |