Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(919)

Side by Side Diff: chrome/browser/devtools/device/devtools_device_discovery.cc

Issue 2431483003: [DevTools] Split device discovery off DevToolsAnrdoidBridge. (Closed)
Patch Set: the bug with invalid weak pointer Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/devtools/device/devtools_device_discovery.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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_device_discovery.h"
6 6
7 #include <stddef.h>
8 #include <algorithm>
9 #include <map>
10 #include <set>
11 #include <utility>
12 #include <vector>
13
14 #include "base/base64.h"
15 #include "base/bind.h" 7 #include "base/bind.h"
16 #include "base/command_line.h"
17 #include "base/compiler_specific.h"
18 #include "base/json/json_reader.h" 8 #include "base/json/json_reader.h"
19 #include "base/lazy_instance.h"
20 #include "base/macros.h"
21 #include "base/memory/ptr_util.h" 9 #include "base/memory/ptr_util.h"
22 #include "base/memory/singleton.h"
23 #include "base/message_loop/message_loop.h"
24 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_number_conversions.h"
25 #include "base/strings/string_split.h" 11 #include "base/strings/string_split.h"
26 #include "base/strings/string_util.h" 12 #include "base/strings/string_util.h"
27 #include "base/strings/stringprintf.h" 13 #include "base/strings/stringprintf.h"
28 #include "base/strings/utf_string_conversions.h" 14 #include "base/strings/utf_string_conversions.h"
29 #include "base/threading/thread.h"
30 #include "base/values.h" 15 #include "base/values.h"
31 #include "chrome/browser/devtools/device/adb/adb_device_provider.h"
32 #include "chrome/browser/devtools/device/port_forwarding_controller.h"
33 #include "chrome/browser/devtools/device/tcp_device_provider.h"
34 #include "chrome/browser/devtools/device/usb/usb_device_provider.h"
35 #include "chrome/browser/devtools/devtools_protocol.h" 16 #include "chrome/browser/devtools/devtools_protocol.h"
36 #include "chrome/browser/devtools/devtools_window.h" 17 #include "chrome/browser/devtools/devtools_window.h"
37 #include "chrome/browser/devtools/remote_debugging_server.h"
38 #include "chrome/browser/profiles/profile.h"
39 #include "chrome/common/chrome_switches.h"
40 #include "chrome/common/features.h"
41 #include "chrome/common/pref_names.h"
42 #include "components/keyed_service/content/browser_context_dependency_manager.h"
43 #include "components/prefs/pref_service.h"
44 #include "components/signin/core/browser/profile_oauth2_token_service.h"
45 #include "components/signin/core/browser/signin_manager.h"
46 #include "content/public/browser/devtools_agent_host.h" 18 #include "content/public/browser/devtools_agent_host.h"
47 #include "content/public/browser/devtools_external_agent_proxy.h" 19 #include "content/public/browser/devtools_external_agent_proxy.h"
48 #include "content/public/browser/devtools_external_agent_proxy_delegate.h" 20 #include "content/public/browser/devtools_external_agent_proxy_delegate.h"
49 #include "content/public/browser/user_metrics.h" 21 #include "content/public/browser/user_metrics.h"
50 #include "net/base/escape.h" 22 #include "net/base/escape.h"
51 #include "net/base/host_port_pair.h"
52 #include "net/base/net_errors.h"
53
54 #if BUILDFLAG(ENABLE_SERVICE_DISCOVERY)
55 #include "chrome/browser/devtools/device/cast_device_provider.h"
56 #endif
57 23
58 using content::BrowserThread; 24 using content::BrowserThread;
59 using content::DevToolsAgentHost; 25 using content::DevToolsAgentHost;
26 using RemoteBrowser = DevToolsDeviceDiscovery::RemoteBrowser;
27 using RemoteDevice = DevToolsDeviceDiscovery::RemoteDevice;
28 using RemotePage = DevToolsDeviceDiscovery::RemotePage;
60 29
61 namespace { 30 namespace {
62 31
63 const char kPageListRequest[] = "/json"; 32 const char kPageListRequest[] = "/json";
64 const char kVersionRequest[] = "/json/version"; 33 const char kVersionRequest[] = "/json/version";
65 const char kClosePageRequest[] = "/json/close/%s"; 34 const char kClosePageRequest[] = "/json/close/%s";
66 const char kNewPageRequestWithURL[] = "/json/new?%s";
67 const char kActivatePageRequest[] = "/json/activate/%s"; 35 const char kActivatePageRequest[] = "/json/activate/%s";
68 const char kBrowserTargetSocket[] = "/devtools/browser"; 36 const char kBrowserTargetSocket[] = "/devtools/browser";
69 const int kAdbPollingIntervalMs = 1000; 37 const int kPollingIntervalMs = 1000;
70 38
71 const char kPageReloadCommand[] = "Page.reload"; 39 const char kPageReloadCommand[] = "Page.reload";
72 40
73 const char kWebViewSocketPrefix[] = "webview_devtools_remote"; 41 const char kWebViewSocketPrefix[] = "webview_devtools_remote";
74 42
75 const char kChromeDiscoveryURL[] = "localhost:9222";
76 const char kNodeDiscoveryURL[] = "localhost:9229";
77
78 bool BrowserIdFromString(const std::string& browser_id_str,
79 std::string* serial,
80 std::string* browser_id) {
81 size_t colon_pos = browser_id_str.find(':');
82 if (colon_pos == std::string::npos)
83 return false;
84 *serial = browser_id_str.substr(0, colon_pos);
85 *browser_id = browser_id_str.substr(colon_pos + 1);
86 return true;
87 }
88
89 static void NoOp(int, const std::string&) {} 43 static void NoOp(int, const std::string&) {}
90 44
91 } // namespace 45 static void ScheduleTaskDefault(const base::Closure& task) {
92 46 BrowserThread::PostDelayedTask(
93 // DiscoveryRequest ----------------------------------------------------- 47 BrowserThread::UI,
94 48 FROM_HERE,
95 class DevToolsAndroidBridge::DiscoveryRequest 49 task,
96 : public base::RefCountedThreadSafe<DiscoveryRequest, 50 base::TimeDelta::FromMilliseconds(kPollingIntervalMs));
97 BrowserThread::DeleteOnUIThread> {
98 public:
99 DiscoveryRequest(AndroidDeviceManager* device_manager,
100 const DeviceListCallback& callback);
101 private:
102 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
103 friend class base::DeleteHelper<DiscoveryRequest>;
104 virtual ~DiscoveryRequest();
105
106 void ReceivedDevices(const AndroidDeviceManager::Devices& devices);
107 void ReceivedDeviceInfo(scoped_refptr<AndroidDeviceManager::Device> device,
108 const AndroidDeviceManager::DeviceInfo& device_info);
109 void ReceivedVersion(scoped_refptr<RemoteBrowser>,
110 int result,
111 const std::string& response);
112 void ReceivedPages(scoped_refptr<AndroidDeviceManager::Device> device,
113 scoped_refptr<RemoteBrowser>,
114 int result,
115 const std::string& response);
116
117 DeviceListCallback callback_;
118 CompleteDevices complete_devices_;
119 };
120
121 DevToolsAndroidBridge::DiscoveryRequest::DiscoveryRequest(
122 AndroidDeviceManager* device_manager,
123 const DeviceListCallback& callback)
124 : callback_(callback) {
125 DCHECK_CURRENTLY_ON(BrowserThread::UI);
126 device_manager->QueryDevices(
127 base::Bind(&DiscoveryRequest::ReceivedDevices, this));
128 }
129
130 DevToolsAndroidBridge::DiscoveryRequest::~DiscoveryRequest() {
131 DCHECK_CURRENTLY_ON(BrowserThread::UI);
132 callback_.Run(complete_devices_);
133 }
134
135 void DevToolsAndroidBridge::DiscoveryRequest::ReceivedDevices(
136 const AndroidDeviceManager::Devices& devices) {
137 DCHECK_CURRENTLY_ON(BrowserThread::UI);
138 for (const auto& device : devices) {
139 device->QueryDeviceInfo(
140 base::Bind(&DiscoveryRequest::ReceivedDeviceInfo, this, device));
141 }
142 }
143
144 void DevToolsAndroidBridge::DiscoveryRequest::ReceivedDeviceInfo(
145 scoped_refptr<AndroidDeviceManager::Device> device,
146 const AndroidDeviceManager::DeviceInfo& device_info) {
147 DCHECK_CURRENTLY_ON(BrowserThread::UI);
148 scoped_refptr<RemoteDevice> remote_device =
149 new RemoteDevice(device->serial(), device_info);
150 complete_devices_.push_back(std::make_pair(device, remote_device));
151 for (RemoteBrowsers::iterator it = remote_device->browsers().begin();
152 it != remote_device->browsers().end(); ++it) {
153 device->SendJsonRequest(
154 (*it)->socket(),
155 kVersionRequest,
156 base::Bind(&DiscoveryRequest::ReceivedVersion, this, *it));
157 device->SendJsonRequest(
158 (*it)->socket(),
159 kPageListRequest,
160 base::Bind(&DiscoveryRequest::ReceivedPages, this, device, *it));
161 }
162 }
163
164 void DevToolsAndroidBridge::DiscoveryRequest::ReceivedVersion(
165 scoped_refptr<RemoteBrowser> browser,
166 int result,
167 const std::string& response) {
168 DCHECK_CURRENTLY_ON(BrowserThread::UI);
169 if (result < 0)
170 return;
171 // Parse version, append to package name if available,
172 std::unique_ptr<base::Value> value = base::JSONReader::Read(response);
173 base::DictionaryValue* dict;
174 if (value && value->GetAsDictionary(&dict)) {
175 std::string browser_name;
176 if (dict->GetString("Browser", &browser_name)) {
177 std::vector<std::string> parts = base::SplitString(
178 browser_name, "/", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
179 if (parts.size() == 2)
180 browser->version_ = parts[1];
181 else
182 browser->version_ = browser_name;
183 }
184 std::string package;
185 if (dict->GetString("Android-Package", &package)) {
186 browser->display_name_ =
187 AndroidDeviceManager::GetBrowserName(browser->socket(), package);
188 }
189 }
190 }
191
192 void DevToolsAndroidBridge::DiscoveryRequest::ReceivedPages(
193 scoped_refptr<AndroidDeviceManager::Device> device,
194 scoped_refptr<RemoteBrowser> browser,
195 int result,
196 const std::string& response) {
197 DCHECK_CURRENTLY_ON(BrowserThread::UI);
198 if (result < 0)
199 return;
200 std::unique_ptr<base::Value> value = base::JSONReader::Read(response);
201 base::ListValue* list_value;
202 if (value && value->GetAsList(&list_value)) {
203 for (const auto& page_value : *list_value) {
204 base::DictionaryValue* dict;
205 if (page_value->GetAsDictionary(&dict))
206 browser->pages_.push_back(
207 new RemotePage(device, browser->browser_id_, *dict));
208 }
209 }
210 } 51 }
211 52
212 // ProtocolCommand ------------------------------------------------------------ 53 // ProtocolCommand ------------------------------------------------------------
213 54
214 namespace {
215
216 class ProtocolCommand 55 class ProtocolCommand
217 : public AndroidDeviceManager::AndroidWebSocket::Delegate { 56 : public AndroidDeviceManager::AndroidWebSocket::Delegate {
218 public: 57 public:
219 ProtocolCommand( 58 ProtocolCommand(
220 scoped_refptr<AndroidDeviceManager::Device> device, 59 scoped_refptr<AndroidDeviceManager::Device> device,
221 const std::string& socket, 60 const std::string& socket,
222 const std::string& target_path, 61 const std::string& target_path,
223 const std::string& command, 62 const std::string& command,
224 const base::Closure callback); 63 const base::Closure callback);
225 64
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 96
258 void ProtocolCommand::OnSocketClosed() { 97 void ProtocolCommand::OnSocketClosed() {
259 delete this; 98 delete this;
260 } 99 }
261 100
262 ProtocolCommand::~ProtocolCommand() { 101 ProtocolCommand::~ProtocolCommand() {
263 if (!callback_.is_null()) 102 if (!callback_.is_null())
264 callback_.Run(); 103 callback_.Run();
265 } 104 }
266 105
267 } // namespace
268
269 // static
270 DevToolsAndroidBridge::Factory* DevToolsAndroidBridge::Factory::GetInstance() {
271 return base::Singleton<DevToolsAndroidBridge::Factory>::get();
272 }
273
274 // static
275 DevToolsAndroidBridge* DevToolsAndroidBridge::Factory::GetForProfile(
276 Profile* profile) {
277 return static_cast<DevToolsAndroidBridge*>(GetInstance()->
278 GetServiceForBrowserContext(profile->GetOriginalProfile(), true));
279 }
280
281 DevToolsAndroidBridge::Factory::Factory()
282 : BrowserContextKeyedServiceFactory(
283 "DevToolsAndroidBridge",
284 BrowserContextDependencyManager::GetInstance()) {
285 }
286
287 DevToolsAndroidBridge::Factory::~Factory() {}
288
289 KeyedService* DevToolsAndroidBridge::Factory::BuildServiceInstanceFor(
290 content::BrowserContext* context) const {
291 Profile* profile = Profile::FromBrowserContext(context);
292
293 return new DevToolsAndroidBridge(profile);
294 }
295
296 // AgentHostDelegate ---------------------------------------------------------- 106 // AgentHostDelegate ----------------------------------------------------------
297 107
298 class DevToolsAndroidBridge::AgentHostDelegate 108 class AgentHostDelegate
299 : public content::DevToolsExternalAgentProxyDelegate, 109 : public content::DevToolsExternalAgentProxyDelegate,
300 public AndroidDeviceManager::AndroidWebSocket::Delegate { 110 public AndroidDeviceManager::AndroidWebSocket::Delegate {
301 public: 111 public:
302 static scoped_refptr<content::DevToolsAgentHost> GetOrCreateAgentHost( 112 static scoped_refptr<content::DevToolsAgentHost> GetOrCreateAgentHost(
303 scoped_refptr<AndroidDeviceManager::Device> device, 113 scoped_refptr<AndroidDeviceManager::Device> device,
304 const std::string& browser_id, 114 const std::string& browser_id,
305 const std::string& local_id, 115 const std::string& local_id,
306 const std::string& target_path, 116 const std::string& target_path,
307 const std::string& type, 117 const std::string& type,
308 base::DictionaryValue* value); 118 base::DictionaryValue* value);
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 pos = 5; 202 pos = 5;
393 target_path = target_path.substr(pos); 203 target_path = target_path.substr(pos);
394 } else { 204 } else {
395 target_path = std::string(); 205 target_path = std::string();
396 } 206 }
397 return target_path; 207 return target_path;
398 } 208 }
399 209
400 // static 210 // static
401 scoped_refptr<content::DevToolsAgentHost> 211 scoped_refptr<content::DevToolsAgentHost>
402 DevToolsAndroidBridge::AgentHostDelegate::GetOrCreateAgentHost( 212 AgentHostDelegate::GetOrCreateAgentHost(
403 scoped_refptr<AndroidDeviceManager::Device> device, 213 scoped_refptr<AndroidDeviceManager::Device> device,
404 const std::string& browser_id, 214 const std::string& browser_id,
405 const std::string& local_id, 215 const std::string& local_id,
406 const std::string& target_path, 216 const std::string& target_path,
407 const std::string& type, 217 const std::string& type,
408 base::DictionaryValue* value) { 218 base::DictionaryValue* value) {
409 DCHECK_CURRENTLY_ON(BrowserThread::UI); 219 DCHECK_CURRENTLY_ON(BrowserThread::UI);
410 scoped_refptr<DevToolsAgentHost> result = 220 scoped_refptr<DevToolsAgentHost> result =
411 DevToolsAgentHost::GetForId(local_id); 221 DevToolsAgentHost::GetForId(local_id);
412 if (result) 222 if (result)
413 return result; 223 return result;
414 224
415 AgentHostDelegate* delegate = new AgentHostDelegate( 225 AgentHostDelegate* delegate = new AgentHostDelegate(
416 device, browser_id, local_id, target_path, type, value); 226 device, browser_id, local_id, target_path, type, value);
417 result = content::DevToolsAgentHost::Forward( 227 result = content::DevToolsAgentHost::Forward(
418 local_id, base::WrapUnique(delegate)); 228 local_id, base::WrapUnique(delegate));
419 delegate->agent_host_ = result.get(); 229 delegate->agent_host_ = result.get();
420 return result; 230 return result;
421 } 231 }
422 232
423 DevToolsAndroidBridge::AgentHostDelegate::AgentHostDelegate( 233 AgentHostDelegate::AgentHostDelegate(
424 scoped_refptr<AndroidDeviceManager::Device> device, 234 scoped_refptr<AndroidDeviceManager::Device> device,
425 const std::string& browser_id, 235 const std::string& browser_id,
426 const std::string& local_id, 236 const std::string& local_id,
427 const std::string& target_path, 237 const std::string& target_path,
428 const std::string& type, 238 const std::string& type,
429 base::DictionaryValue* value) 239 base::DictionaryValue* value)
430 : device_(device), 240 : device_(device),
431 browser_id_(browser_id), 241 browser_id_(browser_id),
432 local_id_(local_id), 242 local_id_(local_id),
433 target_path_(target_path), 243 target_path_(target_path),
434 remote_type_(type), 244 remote_type_(type),
435 remote_id_(value ? GetStringProperty(value, "id") : ""), 245 remote_id_(value ? GetStringProperty(value, "id") : ""),
436 frontend_url_(value ? GetFrontendURLFromValue(value) : ""), 246 frontend_url_(value ? GetFrontendURLFromValue(value) : ""),
437 title_(value ? base::UTF16ToUTF8(net::UnescapeForHTML(base::UTF8ToUTF16( 247 title_(value ? base::UTF16ToUTF8(net::UnescapeForHTML(base::UTF8ToUTF16(
438 GetStringProperty(value, "title")))) : ""), 248 GetStringProperty(value, "title")))) : ""),
439 description_(value ? GetStringProperty(value, "description") : ""), 249 description_(value ? GetStringProperty(value, "description") : ""),
440 url_(GURL(value ? GetStringProperty(value, "url") : "")), 250 url_(GURL(value ? GetStringProperty(value, "url") : "")),
441 favicon_url_(GURL(value ? GetStringProperty(value, "faviconUrl") : "")), 251 favicon_url_(GURL(value ? GetStringProperty(value, "faviconUrl") : "")),
442 socket_opened_(false), 252 socket_opened_(false),
443 agent_host_(nullptr), 253 agent_host_(nullptr),
444 proxy_(nullptr) { 254 proxy_(nullptr) {
445 } 255 }
446 256
447 DevToolsAndroidBridge::AgentHostDelegate::~AgentHostDelegate() { 257 AgentHostDelegate::~AgentHostDelegate() {
448 } 258 }
449 259
450 void DevToolsAndroidBridge::AgentHostDelegate::Attach( 260 void AgentHostDelegate::Attach(content::DevToolsExternalAgentProxy* proxy) {
451 content::DevToolsExternalAgentProxy* proxy) {
452 proxy_ = proxy; 261 proxy_ = proxy;
453 content::RecordAction( 262 content::RecordAction(
454 base::StartsWith(browser_id_, kWebViewSocketPrefix, 263 base::StartsWith(browser_id_, kWebViewSocketPrefix,
455 base::CompareCase::SENSITIVE) 264 base::CompareCase::SENSITIVE)
456 ? base::UserMetricsAction("DevTools_InspectAndroidWebView") 265 ? base::UserMetricsAction("DevTools_InspectAndroidWebView")
457 : base::UserMetricsAction("DevTools_InspectAndroidPage")); 266 : base::UserMetricsAction("DevTools_InspectAndroidPage"));
458 web_socket_.reset( 267 web_socket_.reset(
459 device_->CreateWebSocket(browser_id_, target_path_, this)); 268 device_->CreateWebSocket(browser_id_, target_path_, this));
460 } 269 }
461 270
462 void DevToolsAndroidBridge::AgentHostDelegate::Detach() { 271 void AgentHostDelegate::Detach() {
463 web_socket_.reset(); 272 web_socket_.reset();
464 proxy_ = nullptr; 273 proxy_ = nullptr;
465 } 274 }
466 275
467 std::string DevToolsAndroidBridge::AgentHostDelegate::GetType() { 276 std::string AgentHostDelegate::GetType() {
468 return remote_type_; 277 return remote_type_;
469 } 278 }
470 279
471 std::string DevToolsAndroidBridge::AgentHostDelegate::GetTitle() { 280 std::string AgentHostDelegate::GetTitle() {
472 return title_; 281 return title_;
473 } 282 }
474 283
475 std::string DevToolsAndroidBridge::AgentHostDelegate::GetDescription() { 284 std::string AgentHostDelegate::GetDescription() {
476 return description_; 285 return description_;
477 } 286 }
478 287
479 GURL DevToolsAndroidBridge::AgentHostDelegate::GetURL() { 288 GURL AgentHostDelegate::GetURL() {
480 return url_; 289 return url_;
481 } 290 }
482 291
483 GURL DevToolsAndroidBridge::AgentHostDelegate::GetFaviconURL() { 292 GURL AgentHostDelegate::GetFaviconURL() {
484 return favicon_url_; 293 return favicon_url_;
485 } 294 }
486 295
487 std::string DevToolsAndroidBridge::AgentHostDelegate::GetFrontendURL() { 296 std::string AgentHostDelegate::GetFrontendURL() {
488 return frontend_url_; 297 return frontend_url_;
489 } 298 }
490 299
491 bool DevToolsAndroidBridge::AgentHostDelegate::Activate() { 300 bool AgentHostDelegate::Activate() {
492 std::string request = base::StringPrintf(kActivatePageRequest, 301 std::string request = base::StringPrintf(kActivatePageRequest,
493 remote_id_.c_str()); 302 remote_id_.c_str());
494 device_->SendJsonRequest(browser_id_, request, base::Bind(&NoOp)); 303 device_->SendJsonRequest(browser_id_, request, base::Bind(&NoOp));
495 return true; 304 return true;
496 } 305 }
497 306
498 void DevToolsAndroidBridge::AgentHostDelegate::Reload() { 307 void AgentHostDelegate::Reload() {
499 SendProtocolCommand(target_path_, kPageReloadCommand, nullptr, 308 SendProtocolCommand(target_path_, kPageReloadCommand, nullptr,
500 base::Closure()); 309 base::Closure());
501 } 310 }
502 311
503 bool DevToolsAndroidBridge::AgentHostDelegate::Close() { 312 bool AgentHostDelegate::Close() {
504 std::string request = base::StringPrintf(kClosePageRequest, 313 std::string request = base::StringPrintf(kClosePageRequest,
505 remote_id_.c_str()); 314 remote_id_.c_str());
506 device_->SendJsonRequest(browser_id_, request, base::Bind(&NoOp)); 315 device_->SendJsonRequest(browser_id_, request, base::Bind(&NoOp));
507 return true; 316 return true;
508 } 317 }
509 318
510 void DevToolsAndroidBridge::AgentHostDelegate::SendMessageToBackend( 319 void AgentHostDelegate::SendMessageToBackend(const std::string& message) {
511 const std::string& message) {
512 // We could have detached due to physical connection being closed. 320 // We could have detached due to physical connection being closed.
513 if (!proxy_) 321 if (!proxy_)
514 return; 322 return;
515 if (socket_opened_) 323 if (socket_opened_)
516 web_socket_->SendFrame(message); 324 web_socket_->SendFrame(message);
517 else 325 else
518 pending_messages_.push_back(message); 326 pending_messages_.push_back(message);
519 } 327 }
520 328
521 void DevToolsAndroidBridge::AgentHostDelegate::OnSocketOpened() { 329 void AgentHostDelegate::OnSocketOpened() {
522 socket_opened_ = true; 330 socket_opened_ = true;
523 for (std::vector<std::string>::iterator it = pending_messages_.begin(); 331 for (std::vector<std::string>::iterator it = pending_messages_.begin();
524 it != pending_messages_.end(); ++it) { 332 it != pending_messages_.end(); ++it) {
525 SendMessageToBackend(*it); 333 SendMessageToBackend(*it);
526 } 334 }
527 pending_messages_.clear(); 335 pending_messages_.clear();
528 } 336 }
529 337
530 void DevToolsAndroidBridge::AgentHostDelegate::OnFrameRead( 338 void AgentHostDelegate::OnFrameRead(const std::string& message) {
531 const std::string& message) {
532 if (proxy_) 339 if (proxy_)
533 proxy_->DispatchOnClientHost(message); 340 proxy_->DispatchOnClientHost(message);
534 } 341 }
535 342
536 void DevToolsAndroidBridge::AgentHostDelegate::OnSocketClosed() { 343 void AgentHostDelegate::OnSocketClosed() {
537 if (proxy_) { 344 if (proxy_) {
538 std::string message = "{ \"method\": \"Inspector.detached\", " 345 std::string message = "{ \"method\": \"Inspector.detached\", "
539 "\"params\": { \"reason\": \"Connection lost.\"} }"; 346 "\"params\": { \"reason\": \"Connection lost.\"} }";
540 proxy_->DispatchOnClientHost(message); 347 proxy_->DispatchOnClientHost(message);
541 Detach(); 348 Detach();
542 } 349 }
543 } 350 }
544 351
545 void DevToolsAndroidBridge::AgentHostDelegate::SendProtocolCommand( 352 void AgentHostDelegate::SendProtocolCommand(
546 const std::string& target_path, 353 const std::string& target_path,
547 const std::string& method, 354 const std::string& method,
548 std::unique_ptr<base::DictionaryValue> params, 355 std::unique_ptr<base::DictionaryValue> params,
549 const base::Closure callback) { 356 const base::Closure callback) {
550 DCHECK_CURRENTLY_ON(BrowserThread::UI); 357 DCHECK_CURRENTLY_ON(BrowserThread::UI);
551 if (target_path.empty()) 358 if (target_path.empty())
552 return; 359 return;
553 new ProtocolCommand( 360 new ProtocolCommand(
554 device_, browser_id_, target_path, 361 device_, browser_id_, target_path,
555 DevToolsProtocol::SerializeCommand(1, method, std::move(params)), 362 DevToolsProtocol::SerializeCommand(1, method, std::move(params)),
556 callback); 363 callback);
557 } 364 }
558 365
559 // DevToolsAndroidBridge::RemotePage ------------------------------------------ 366 } // namespace
560 367
561 DevToolsAndroidBridge::RemotePage::RemotePage( 368 // DevToolsDeviceDiscovery::DiscoveryRequest ----------------------------------
369
370 class DevToolsDeviceDiscovery::DiscoveryRequest
371 : public base::RefCountedThreadSafe<DiscoveryRequest,
372 BrowserThread::DeleteOnUIThread> {
373 public:
374 DiscoveryRequest(AndroidDeviceManager* device_manager,
375 const DevToolsDeviceDiscovery::DeviceListCallback& callback);
376 private:
377 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
378 friend class base::DeleteHelper<DiscoveryRequest>;
379 virtual ~DiscoveryRequest();
380
381 void ReceivedDevices(const AndroidDeviceManager::Devices& devices);
382 void ReceivedDeviceInfo(scoped_refptr<AndroidDeviceManager::Device> device,
383 const AndroidDeviceManager::DeviceInfo& device_info);
384 void ReceivedVersion(scoped_refptr<RemoteBrowser>,
385 int result,
386 const std::string& response);
387 void ReceivedPages(scoped_refptr<AndroidDeviceManager::Device> device,
388 scoped_refptr<RemoteBrowser>,
389 int result,
390 const std::string& response);
391
392 DevToolsDeviceDiscovery::DeviceListCallback callback_;
393 DevToolsDeviceDiscovery::CompleteDevices complete_devices_;
394 };
395
396 DevToolsDeviceDiscovery::DiscoveryRequest::DiscoveryRequest(
397 AndroidDeviceManager* device_manager,
398 const DevToolsDeviceDiscovery::DeviceListCallback& callback)
399 : callback_(callback) {
400 DCHECK_CURRENTLY_ON(BrowserThread::UI);
401 device_manager->QueryDevices(
402 base::Bind(&DiscoveryRequest::ReceivedDevices, this));
403 }
404
405 DevToolsDeviceDiscovery::DiscoveryRequest::~DiscoveryRequest() {
406 DCHECK_CURRENTLY_ON(BrowserThread::UI);
407 callback_.Run(complete_devices_);
408 }
409
410 void DevToolsDeviceDiscovery::DiscoveryRequest::ReceivedDevices(
411 const AndroidDeviceManager::Devices& devices) {
412 DCHECK_CURRENTLY_ON(BrowserThread::UI);
413 for (const auto& device : devices) {
414 device->QueryDeviceInfo(
415 base::Bind(&DiscoveryRequest::ReceivedDeviceInfo, this, device));
416 }
417 }
418
419 void DevToolsDeviceDiscovery::DiscoveryRequest::ReceivedDeviceInfo(
420 scoped_refptr<AndroidDeviceManager::Device> device,
421 const AndroidDeviceManager::DeviceInfo& device_info) {
422 DCHECK_CURRENTLY_ON(BrowserThread::UI);
423 scoped_refptr<RemoteDevice> remote_device =
424 new RemoteDevice(device->serial(), device_info);
425 complete_devices_.push_back(std::make_pair(device, remote_device));
426 for (RemoteBrowsers::iterator it = remote_device->browsers().begin();
427 it != remote_device->browsers().end(); ++it) {
428 device->SendJsonRequest(
429 (*it)->socket(),
430 kVersionRequest,
431 base::Bind(&DiscoveryRequest::ReceivedVersion, this, *it));
432 device->SendJsonRequest(
433 (*it)->socket(),
434 kPageListRequest,
435 base::Bind(&DiscoveryRequest::ReceivedPages, this, device, *it));
436 }
437 }
438
439 void DevToolsDeviceDiscovery::DiscoveryRequest::ReceivedVersion(
440 scoped_refptr<RemoteBrowser> browser,
441 int result,
442 const std::string& response) {
443 DCHECK_CURRENTLY_ON(BrowserThread::UI);
444 if (result < 0)
445 return;
446 // Parse version, append to package name if available,
447 std::unique_ptr<base::Value> value = base::JSONReader::Read(response);
448 base::DictionaryValue* dict;
449 if (value && value->GetAsDictionary(&dict)) {
450 std::string browser_name;
451 if (dict->GetString("Browser", &browser_name)) {
452 std::vector<std::string> parts = base::SplitString(
453 browser_name, "/", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
454 if (parts.size() == 2)
455 browser->version_ = parts[1];
456 else
457 browser->version_ = browser_name;
458 }
459 std::string package;
460 if (dict->GetString("Android-Package", &package)) {
461 browser->display_name_ =
462 AndroidDeviceManager::GetBrowserName(browser->socket(), package);
463 }
464 }
465 }
466
467 void DevToolsDeviceDiscovery::DiscoveryRequest::ReceivedPages(
468 scoped_refptr<AndroidDeviceManager::Device> device,
469 scoped_refptr<RemoteBrowser> browser,
470 int result,
471 const std::string& response) {
472 DCHECK_CURRENTLY_ON(BrowserThread::UI);
473 if (result < 0)
474 return;
475 std::unique_ptr<base::Value> value = base::JSONReader::Read(response);
476 base::ListValue* list_value;
477 if (value && value->GetAsList(&list_value)) {
478 for (const auto& page_value : *list_value) {
479 base::DictionaryValue* dict;
480 if (page_value->GetAsDictionary(&dict))
481 browser->pages_.push_back(
482 new RemotePage(device, browser->browser_id_, *dict));
483 }
484 }
485 }
486
487 // DevToolsDeviceDiscovery::RemotePage ----------------------------------------
488
489 DevToolsDeviceDiscovery::RemotePage::RemotePage(
562 scoped_refptr<AndroidDeviceManager::Device> device, 490 scoped_refptr<AndroidDeviceManager::Device> device,
563 const std::string& browser_id, 491 const std::string& browser_id,
564 const base::DictionaryValue& dict) 492 const base::DictionaryValue& dict)
565 : device_(device), 493 : device_(device),
566 browser_id_(browser_id), 494 browser_id_(browser_id),
567 dict_(dict.DeepCopy()) { 495 dict_(dict.DeepCopy()) {
568 } 496 }
569 497
570 DevToolsAndroidBridge::RemotePage::~RemotePage() { 498 DevToolsDeviceDiscovery::RemotePage::~RemotePage() {
571 } 499 }
572 500
573 scoped_refptr<content::DevToolsAgentHost> 501 scoped_refptr<content::DevToolsAgentHost>
574 DevToolsAndroidBridge::RemotePage::CreateTarget() { 502 DevToolsDeviceDiscovery::RemotePage::CreateTarget() {
575 std::string local_id = BuildUniqueTargetId(device_->serial(), 503 std::string local_id = BuildUniqueTargetId(device_->serial(),
576 browser_id_, 504 browser_id_,
577 dict_.get()); 505 dict_.get());
578 std::string target_path = GetTargetPath(dict_.get()); 506 std::string target_path = GetTargetPath(dict_.get());
579 std::string type = GetStringProperty(dict_.get(), "type"); 507 std::string type = GetStringProperty(dict_.get(), "type");
580 508
581 return AgentHostDelegate::GetOrCreateAgentHost( 509 return AgentHostDelegate::GetOrCreateAgentHost(
582 device_, browser_id_, local_id, target_path, type, dict_.get()); 510 device_, browser_id_, local_id, target_path, type, dict_.get());
583 } 511 }
584 512
585 // DevToolsAndroidBridge::RemoteBrowser --------------------------------------- 513 // DevToolsDeviceDiscovery::RemoteBrowser -------------------------------------
586 514
587 DevToolsAndroidBridge::RemoteBrowser::RemoteBrowser( 515 DevToolsDeviceDiscovery::RemoteBrowser::RemoteBrowser(
588 const std::string& serial, 516 const std::string& serial,
589 const AndroidDeviceManager::BrowserInfo& browser_info) 517 const AndroidDeviceManager::BrowserInfo& browser_info)
590 : serial_(serial), 518 : serial_(serial),
591 browser_id_(browser_info.socket_name), 519 browser_id_(browser_info.socket_name),
592 display_name_(browser_info.display_name), 520 display_name_(browser_info.display_name),
593 user_(browser_info.user), 521 user_(browser_info.user),
594 type_(browser_info.type) { 522 type_(browser_info.type) {
595 } 523 }
596 524
597 bool DevToolsAndroidBridge::RemoteBrowser::IsChrome() { 525 bool DevToolsDeviceDiscovery::RemoteBrowser::IsChrome() {
598 return type_ == AndroidDeviceManager::BrowserInfo::kTypeChrome; 526 return type_ == AndroidDeviceManager::BrowserInfo::kTypeChrome;
599 } 527 }
600 528
601 std::string DevToolsAndroidBridge::RemoteBrowser::GetId() { 529 std::string DevToolsDeviceDiscovery::RemoteBrowser::GetId() {
602 return serial() + ":" + socket(); 530 return serial() + ":" + socket();
603 } 531 }
604 532
605 DevToolsAndroidBridge::RemoteBrowser::ParsedVersion 533 DevToolsDeviceDiscovery::RemoteBrowser::ParsedVersion
606 DevToolsAndroidBridge::RemoteBrowser::GetParsedVersion() { 534 DevToolsDeviceDiscovery::RemoteBrowser::GetParsedVersion() {
607 ParsedVersion result; 535 ParsedVersion result;
608 for (const base::StringPiece& part : 536 for (const base::StringPiece& part :
609 base::SplitStringPiece( 537 base::SplitStringPiece(
610 version_, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) { 538 version_, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
611 int value = 0; 539 int value = 0;
612 base::StringToInt(part, &value); 540 base::StringToInt(part, &value);
613 result.push_back(value); 541 result.push_back(value);
614 } 542 }
615 return result; 543 return result;
616 } 544 }
617 545
618 scoped_refptr<content::DevToolsAgentHost> 546 DevToolsDeviceDiscovery::RemoteBrowser::~RemoteBrowser() {
619 DevToolsAndroidBridge::GetBrowserAgentHost(
620 scoped_refptr<RemoteBrowser> browser) {
621 DeviceMap::iterator it = device_map_.find(browser->serial());
622 if (it == device_map_.end())
623 return nullptr;
624
625 return AgentHostDelegate::GetOrCreateAgentHost(
626 it->second,
627 browser->browser_id_,
628 "adb:" + browser->serial() + ":" + browser->socket(),
629 kBrowserTargetSocket, DevToolsAgentHost::kTypeBrowser, nullptr);
630 } 547 }
631 548
632 void DevToolsAndroidBridge::SendJsonRequest( 549 // DevToolsDeviceDiscovery::RemoteDevice --------------------------------------
633 const std::string& browser_id_str,
634 const std::string& url,
635 const JsonRequestCallback& callback) {
636 std::string serial;
637 std::string browser_id;
638 if (!BrowserIdFromString(browser_id_str, &serial, &browser_id)) {
639 callback.Run(net::ERR_FAILED, std::string());
640 return;
641 }
642 DeviceMap::iterator it = device_map_.find(serial);
643 if (it == device_map_.end()) {
644 callback.Run(net::ERR_FAILED, std::string());
645 return;
646 }
647 it->second->SendJsonRequest(browser_id, url, callback);
648 }
649 550
650 void DevToolsAndroidBridge::OpenRemotePage(scoped_refptr<RemoteBrowser> browser, 551 DevToolsDeviceDiscovery::RemoteDevice::RemoteDevice(
651 const std::string& input_url) {
652 DCHECK_CURRENTLY_ON(BrowserThread::UI);
653 GURL gurl(input_url);
654 if (!gurl.is_valid()) {
655 gurl = GURL("http://" + input_url);
656 if (!gurl.is_valid())
657 return;
658 }
659 std::string url = gurl.spec();
660 RemoteBrowser::ParsedVersion parsed_version = browser->GetParsedVersion();
661
662 std::string query = net::EscapeQueryParamValue(url, false /* use_plus */);
663 std::string request =
664 base::StringPrintf(kNewPageRequestWithURL, query.c_str());
665 SendJsonRequest(browser->GetId(), request, base::Bind(&NoOp));
666 }
667
668 DevToolsAndroidBridge::RemoteBrowser::~RemoteBrowser() {
669 }
670
671 // DevToolsAndroidBridge::RemoteDevice ----------------------------------------
672
673 DevToolsAndroidBridge::RemoteDevice::RemoteDevice(
674 const std::string& serial, 552 const std::string& serial,
675 const AndroidDeviceManager::DeviceInfo& device_info) 553 const AndroidDeviceManager::DeviceInfo& device_info)
676 : serial_(serial), 554 : serial_(serial),
677 model_(device_info.model), 555 model_(device_info.model),
678 connected_(device_info.connected), 556 connected_(device_info.connected),
679 screen_size_(device_info.screen_size) { 557 screen_size_(device_info.screen_size) {
680 for (std::vector<AndroidDeviceManager::BrowserInfo>::const_iterator it = 558 for (std::vector<AndroidDeviceManager::BrowserInfo>::const_iterator it =
681 device_info.browser_info.begin(); 559 device_info.browser_info.begin();
682 it != device_info.browser_info.end(); 560 it != device_info.browser_info.end();
683 ++it) { 561 ++it) {
684 browsers_.push_back(new RemoteBrowser(serial, *it)); 562 browsers_.push_back(new RemoteBrowser(serial, *it));
685 } 563 }
686 } 564 }
687 565
688 DevToolsAndroidBridge::RemoteDevice::~RemoteDevice() { 566 DevToolsDeviceDiscovery::RemoteDevice::~RemoteDevice() {
689 } 567 }
690 568
691 // DevToolsAndroidBridge ------------------------------------------------------ 569 // DevToolsDeviceDiscovery ----------------------------------------------------
692 570
693 // static 571 DevToolsDeviceDiscovery::DevToolsDeviceDiscovery(
694 void DevToolsAndroidBridge::QueryCompleteDevices(
695 AndroidDeviceManager* device_manager, 572 AndroidDeviceManager* device_manager,
696 const DeviceListCallback& callback) { 573 const DeviceListCallback& callback)
697 new DiscoveryRequest(device_manager, callback); 574 : device_manager_(device_manager),
575 callback_(callback),
576 task_scheduler_(base::Bind(&ScheduleTaskDefault)),
577 weak_factory_(this) {
578 DCHECK_CURRENTLY_ON(BrowserThread::UI);
579 RequestDeviceList();
698 } 580 }
699 581
700 DevToolsAndroidBridge::DevToolsAndroidBridge( 582 DevToolsDeviceDiscovery::~DevToolsDeviceDiscovery() {
701 Profile* profile)
702 : profile_(profile),
703 device_manager_(AndroidDeviceManager::Create()),
704 task_scheduler_(base::Bind(&DevToolsAndroidBridge::ScheduleTaskDefault)),
705 port_forwarding_controller_(new PortForwardingController(profile)),
706 weak_factory_(this) {
707 DCHECK_CURRENTLY_ON(BrowserThread::UI); 583 DCHECK_CURRENTLY_ON(BrowserThread::UI);
708 pref_change_registrar_.Init(profile_->GetPrefs());
709 pref_change_registrar_.Add(prefs::kDevToolsDiscoverUsbDevicesEnabled,
710 base::Bind(&DevToolsAndroidBridge::CreateDeviceProviders,
711 base::Unretained(this)));
712 pref_change_registrar_.Add(prefs::kDevToolsTCPDiscoveryConfig,
713 base::Bind(&DevToolsAndroidBridge::CreateDeviceProviders,
714 base::Unretained(this)));
715 pref_change_registrar_.Add(prefs::kDevToolsDiscoverTCPTargetsEnabled,
716 base::Bind(&DevToolsAndroidBridge::CreateDeviceProviders,
717 base::Unretained(this)));
718 base::ListValue* target_discovery = new base::ListValue();
719 target_discovery->AppendString(kChromeDiscoveryURL);
720 target_discovery->AppendString(kNodeDiscoveryURL);
721 profile->GetPrefs()->SetDefaultPrefValue(
722 prefs::kDevToolsTCPDiscoveryConfig, target_discovery);
723 CreateDeviceProviders();
724 } 584 }
725 585
726 void DevToolsAndroidBridge::AddDeviceListListener( 586 void DevToolsDeviceDiscovery::SetScheduler(
727 DeviceListListener* listener) { 587 base::Callback<void(const base::Closure&)> scheduler) {
728 DCHECK_CURRENTLY_ON(BrowserThread::UI); 588 DCHECK_CURRENTLY_ON(BrowserThread::UI);
729 bool polling_was_off = !NeedsDeviceListPolling(); 589 task_scheduler_ = scheduler;
730 device_list_listeners_.push_back(listener);
731 if (polling_was_off)
732 StartDeviceListPolling();
733 }
734
735 void DevToolsAndroidBridge::RemoveDeviceListListener(
736 DeviceListListener* listener) {
737 DCHECK_CURRENTLY_ON(BrowserThread::UI);
738 DeviceListListeners::iterator it = std::find(
739 device_list_listeners_.begin(), device_list_listeners_.end(), listener);
740 DCHECK(it != device_list_listeners_.end());
741 device_list_listeners_.erase(it);
742 if (!NeedsDeviceListPolling())
743 StopDeviceListPolling();
744 }
745
746 void DevToolsAndroidBridge::AddDeviceCountListener(
747 DeviceCountListener* listener) {
748 device_count_listeners_.push_back(listener);
749 if (device_count_listeners_.size() == 1)
750 StartDeviceCountPolling();
751 }
752
753 void DevToolsAndroidBridge::RemoveDeviceCountListener(
754 DeviceCountListener* listener) {
755 DCHECK_CURRENTLY_ON(BrowserThread::UI);
756 DeviceCountListeners::iterator it = std::find(
757 device_count_listeners_.begin(), device_count_listeners_.end(), listener);
758 DCHECK(it != device_count_listeners_.end());
759 device_count_listeners_.erase(it);
760 if (device_count_listeners_.empty())
761 StopDeviceCountPolling();
762 }
763
764 void DevToolsAndroidBridge::AddPortForwardingListener(
765 PortForwardingListener* listener) {
766 bool polling_was_off = !NeedsDeviceListPolling();
767 port_forwarding_listeners_.push_back(listener);
768 if (polling_was_off)
769 StartDeviceListPolling();
770 }
771
772 void DevToolsAndroidBridge::RemovePortForwardingListener(
773 PortForwardingListener* listener) {
774 PortForwardingListeners::iterator it = std::find(
775 port_forwarding_listeners_.begin(),
776 port_forwarding_listeners_.end(),
777 listener);
778 DCHECK(it != port_forwarding_listeners_.end());
779 port_forwarding_listeners_.erase(it);
780 if (!NeedsDeviceListPolling())
781 StopDeviceListPolling();
782 }
783
784 DevToolsAndroidBridge::~DevToolsAndroidBridge() {
785 DCHECK_CURRENTLY_ON(BrowserThread::UI);
786 DCHECK(device_list_listeners_.empty());
787 DCHECK(device_count_listeners_.empty());
788 DCHECK(port_forwarding_listeners_.empty());
789 }
790
791 void DevToolsAndroidBridge::StartDeviceListPolling() {
792 device_list_callback_.Reset(
793 base::Bind(&DevToolsAndroidBridge::ReceivedDeviceList, AsWeakPtr()));
794 RequestDeviceList(device_list_callback_.callback());
795 }
796
797 void DevToolsAndroidBridge::StopDeviceListPolling() {
798 device_list_callback_.Cancel();
799 device_map_.clear();
800 port_forwarding_controller_->CloseAllConnections();
801 }
802
803 bool DevToolsAndroidBridge::NeedsDeviceListPolling() {
804 return !device_list_listeners_.empty() || !port_forwarding_listeners_.empty();
805 }
806
807 void DevToolsAndroidBridge::RequestDeviceList(
808 const DeviceListCallback& callback) {
809 DCHECK_CURRENTLY_ON(BrowserThread::UI);
810
811 if (!NeedsDeviceListPolling() ||
812 !callback.Equals(device_list_callback_.callback()))
813 return;
814
815 new DiscoveryRequest(device_manager_.get(), callback);
816 }
817
818 void DevToolsAndroidBridge::ReceivedDeviceList(
819 const CompleteDevices& complete_devices) {
820 DCHECK_CURRENTLY_ON(BrowserThread::UI);
821
822 device_map_.clear();
823 RemoteDevices remote_devices;
824 for (const auto& pair : complete_devices) {
825 device_map_[pair.first->serial()] = pair.first;
826 remote_devices.push_back(pair.second);
827 }
828
829 DeviceListListeners copy(device_list_listeners_);
830 for (DeviceListListeners::iterator it = copy.begin(); it != copy.end(); ++it)
831 (*it)->DeviceListChanged(remote_devices);
832
833 ForwardingStatus status =
834 port_forwarding_controller_->DeviceListChanged(complete_devices);
835 PortForwardingListeners forwarding_listeners(port_forwarding_listeners_);
836 for (PortForwardingListeners::iterator it = forwarding_listeners.begin();
837 it != forwarding_listeners.end(); ++it) {
838 (*it)->PortStatusChanged(status);
839 }
840
841 if (!NeedsDeviceListPolling())
842 return;
843
844 task_scheduler_.Run(
845 base::Bind(&DevToolsAndroidBridge::RequestDeviceList,
846 AsWeakPtr(), device_list_callback_.callback()));
847 }
848
849 void DevToolsAndroidBridge::StartDeviceCountPolling() {
850 device_count_callback_.Reset(
851 base::Bind(&DevToolsAndroidBridge::ReceivedDeviceCount, AsWeakPtr()));
852 RequestDeviceCount(device_count_callback_.callback());
853 }
854
855 void DevToolsAndroidBridge::StopDeviceCountPolling() {
856 device_count_callback_.Cancel();
857 }
858
859 void DevToolsAndroidBridge::RequestDeviceCount(
860 const base::Callback<void(int)>& callback) {
861 DCHECK_CURRENTLY_ON(BrowserThread::UI);
862
863 if (device_count_listeners_.empty() ||
864 !callback.Equals(device_count_callback_.callback()))
865 return;
866
867 UsbDeviceProvider::CountDevices(callback);
868 }
869
870 void DevToolsAndroidBridge::ReceivedDeviceCount(int count) {
871 DCHECK_CURRENTLY_ON(BrowserThread::UI);
872
873 DeviceCountListeners copy(device_count_listeners_);
874 for (DeviceCountListeners::iterator it = copy.begin(); it != copy.end(); ++it)
875 (*it)->DeviceCountChanged(count);
876
877 if (device_count_listeners_.empty())
878 return;
879
880 task_scheduler_.Run(
881 base::Bind(&DevToolsAndroidBridge::RequestDeviceCount,
882 AsWeakPtr(), device_count_callback_.callback()));
883 } 590 }
884 591
885 // static 592 // static
886 void DevToolsAndroidBridge::ScheduleTaskDefault(const base::Closure& task) { 593 scoped_refptr<content::DevToolsAgentHost>
887 BrowserThread::PostDelayedTask( 594 DevToolsDeviceDiscovery::CreateBrowserAgentHost(
888 BrowserThread::UI, 595 scoped_refptr<AndroidDeviceManager::Device> device,
889 FROM_HERE, 596 scoped_refptr<RemoteBrowser> browser) {
890 task, 597 return AgentHostDelegate::GetOrCreateAgentHost(
891 base::TimeDelta::FromMilliseconds(kAdbPollingIntervalMs)); 598 device,
599 browser->browser_id_,
600 "adb:" + browser->serial() + ":" + browser->socket(),
601 kBrowserTargetSocket, DevToolsAgentHost::kTypeBrowser, nullptr);
892 } 602 }
893 603
894 static std::set<net::HostPortPair> ParseTargetDiscoveryPreferenceValue( 604 void DevToolsDeviceDiscovery::RequestDeviceList() {
895 const base::ListValue* preferenceValue) { 605 DCHECK_CURRENTLY_ON(BrowserThread::UI);
896 std::set<net::HostPortPair> targets; 606 new DiscoveryRequest(
897 if (!preferenceValue || preferenceValue->empty()) 607 device_manager_,
898 return targets; 608 base::Bind(&DevToolsDeviceDiscovery::ReceivedDeviceList,
899 std::string address; 609 weak_factory_.GetWeakPtr()));
900 for (size_t i = 0; i < preferenceValue->GetSize(); i++) {
901 if (!preferenceValue->GetString(i, &address))
902 continue;
903 net::HostPortPair target = net::HostPortPair::FromString(address);
904 if (target.IsEmpty()) {
905 LOG(WARNING) << "Invalid target: " << address;
906 continue;
907 }
908 targets.insert(target);
909 }
910 return targets;
911 } 610 }
912 611
913 static scoped_refptr<TCPDeviceProvider> CreateTCPDeviceProvider( 612 void DevToolsDeviceDiscovery::ReceivedDeviceList(
914 const base::ListValue* targetDiscoveryConfig) { 613 const CompleteDevices& complete_devices) {
915 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); 614 DCHECK_CURRENTLY_ON(BrowserThread::UI);
916 std::set<net::HostPortPair> targets = 615 task_scheduler_.Run(base::Bind(&DevToolsDeviceDiscovery::RequestDeviceList,
917 ParseTargetDiscoveryPreferenceValue(targetDiscoveryConfig); 616 weak_factory_.GetWeakPtr()));
918 if (targets.empty() && 617 // |callback_| should be run last as it may destroy |this|.
919 !command_line->HasSwitch(switches::kRemoteDebuggingTargets)) 618 callback_.Run(complete_devices);
920 return nullptr;
921 std::string value =
922 command_line->GetSwitchValueASCII(switches::kRemoteDebuggingTargets);
923 std::vector<std::string> addresses = base::SplitString(
924 value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
925 for (const std::string& address : addresses) {
926 net::HostPortPair target = net::HostPortPair::FromString(address);
927 if (target.IsEmpty()) {
928 LOG(WARNING) << "Invalid target: " << address;
929 continue;
930 }
931 targets.insert(target);
932 }
933 if (targets.empty())
934 return nullptr;
935 return new TCPDeviceProvider(targets);
936 } 619 }
937 620
938 void DevToolsAndroidBridge::CreateDeviceProviders() { 621 namespace {
939 AndroidDeviceManager::DeviceProviders device_providers;
940 PrefService* service = profile_->GetPrefs();
941 const base::ListValue* targets =
942 service->GetBoolean(prefs::kDevToolsDiscoverTCPTargetsEnabled)
943 ? service->GetList(prefs::kDevToolsTCPDiscoveryConfig)
944 : nullptr;
945 scoped_refptr<TCPDeviceProvider> provider = CreateTCPDeviceProvider(targets);
946 if (tcp_provider_callback_)
947 tcp_provider_callback_.Run(provider);
948 622
949 if (provider) 623 class OnceWrapper {
950 device_providers.push_back(provider); 624 public:
951 625 OnceWrapper(AndroidDeviceManager* device_manager,
952 #if BUILDFLAG(ENABLE_SERVICE_DISCOVERY) 626 const DevToolsDeviceDiscovery::DeviceListCallback& callback)
953 device_providers.push_back(new CastDeviceProvider()); 627 : callback_(callback) {
954 #endif 628 discovery_.reset(new DevToolsDeviceDiscovery(device_manager,
955 629 base::Bind(&OnceWrapper::Callback, base::Unretained(this))));
956 device_providers.push_back(new AdbDeviceProvider()); 630 discovery_->SetScheduler(base::Bind(&OnceWrapper::NoOp));
957
958 const PrefService::Preference* pref =
959 service->FindPreference(prefs::kDevToolsDiscoverUsbDevicesEnabled);
960 const base::Value* pref_value = pref->GetValue();
961
962 bool enabled;
963 if (pref_value->GetAsBoolean(&enabled) && enabled) {
964 device_providers.push_back(new UsbDeviceProvider(profile_));
965 } 631 }
966 632
967 device_manager_->SetDeviceProviders(device_providers); 633 private:
968 if (NeedsDeviceListPolling()) { 634 static void NoOp(const base::Closure&) {}
969 StopDeviceListPolling(); 635
970 StartDeviceListPolling(); 636 void Callback(const DevToolsDeviceDiscovery::CompleteDevices& devices) {
637 callback_.Run(devices);
638 delete this;
971 } 639 }
640
641 std::unique_ptr<DevToolsDeviceDiscovery> discovery_;
642 const DevToolsDeviceDiscovery::DeviceListCallback callback_;
643 };
644
645 } // namespace
646
647 // static
648 void DevToolsDeviceDiscovery::DiscoverOnce(
649 AndroidDeviceManager* device_manager,
650 const DeviceListCallback& callback) {
651 new OnceWrapper(device_manager, callback);
972 } 652 }
973
974 void DevToolsAndroidBridge::set_tcp_provider_callback_for_test(
975 TCPProviderCallback callback) {
976 tcp_provider_callback_ = callback;
977 CreateDeviceProviders();
978 }
OLDNEW
« no previous file with comments | « chrome/browser/devtools/device/devtools_device_discovery.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698