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/android_device_manager.h" | 5 #include "chrome/browser/devtools/device/android_device_manager.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
| 9 #include "base/location.h" |
9 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
10 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
11 #include "base/strings/stringprintf.h" | 12 #include "base/strings/stringprintf.h" |
| 13 #include "base/thread_task_runner_handle.h" |
12 #include "net/base/io_buffer.h" | 14 #include "net/base/io_buffer.h" |
13 #include "net/base/net_errors.h" | 15 #include "net/base/net_errors.h" |
14 #include "net/socket/stream_socket.h" | 16 #include "net/socket/stream_socket.h" |
15 | 17 |
16 using content::BrowserThread; | 18 using content::BrowserThread; |
17 | 19 |
18 namespace { | 20 namespace { |
19 | 21 |
20 const char kDevToolsAdbBridgeThreadName[] = "Chrome_DevToolsADBThread"; | 22 const char kDevToolsAdbBridgeThreadName[] = "Chrome_DevToolsADBThread"; |
21 | 23 |
22 const int kBufferSize = 16 * 1024; | 24 const int kBufferSize = 16 * 1024; |
23 | 25 |
24 static const char kModelOffline[] = "Offline"; | 26 static const char kModelOffline[] = "Offline"; |
25 | 27 |
26 static const char kHttpGetRequest[] = "GET %s HTTP/1.1\r\n\r\n"; | 28 static const char kHttpGetRequest[] = "GET %s HTTP/1.1\r\n\r\n"; |
27 | 29 |
28 static const char kWebSocketUpgradeRequest[] = "GET %s HTTP/1.1\r\n" | 30 static const char kWebSocketUpgradeRequest[] = "GET %s HTTP/1.1\r\n" |
29 "Upgrade: WebSocket\r\n" | 31 "Upgrade: WebSocket\r\n" |
30 "Connection: Upgrade\r\n" | 32 "Connection: Upgrade\r\n" |
31 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" | 33 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" |
32 "Sec-WebSocket-Version: 13\r\n" | 34 "Sec-WebSocket-Version: 13\r\n" |
33 "%s" | 35 "%s" |
34 "\r\n"; | 36 "\r\n"; |
35 | 37 |
36 static void PostDeviceInfoCallback( | 38 static void PostDeviceInfoCallback( |
37 scoped_refptr<base::MessageLoopProxy> response_message_loop, | 39 scoped_refptr<base::SingleThreadTaskRunner> response_task_runner, |
38 const AndroidDeviceManager::DeviceInfoCallback& callback, | 40 const AndroidDeviceManager::DeviceInfoCallback& callback, |
39 const AndroidDeviceManager::DeviceInfo& device_info) { | 41 const AndroidDeviceManager::DeviceInfo& device_info) { |
40 response_message_loop->PostTask(FROM_HERE, base::Bind(callback, device_info)); | 42 response_task_runner->PostTask(FROM_HERE, base::Bind(callback, device_info)); |
41 } | 43 } |
42 | 44 |
43 static void PostCommandCallback( | 45 static void PostCommandCallback( |
44 scoped_refptr<base::MessageLoopProxy> response_message_loop, | 46 scoped_refptr<base::SingleThreadTaskRunner> response_task_runner, |
45 const AndroidDeviceManager::CommandCallback& callback, | 47 const AndroidDeviceManager::CommandCallback& callback, |
46 int result, | 48 int result, |
47 const std::string& response) { | 49 const std::string& response) { |
48 response_message_loop->PostTask(FROM_HERE, | 50 response_task_runner->PostTask(FROM_HERE, |
49 base::Bind(callback, result, response)); | 51 base::Bind(callback, result, response)); |
50 } | 52 } |
51 | 53 |
52 static void PostHttpUpgradeCallback( | 54 static void PostHttpUpgradeCallback( |
53 scoped_refptr<base::MessageLoopProxy> response_message_loop, | 55 scoped_refptr<base::SingleThreadTaskRunner> response_task_runner, |
54 const AndroidDeviceManager::HttpUpgradeCallback& callback, | 56 const AndroidDeviceManager::HttpUpgradeCallback& callback, |
55 int result, | 57 int result, |
56 const std::string& extensions, | 58 const std::string& extensions, |
57 const std::string& body_head, | 59 const std::string& body_head, |
58 scoped_ptr<net::StreamSocket> socket) { | 60 scoped_ptr<net::StreamSocket> socket) { |
59 response_message_loop->PostTask( | 61 response_task_runner->PostTask( |
60 FROM_HERE, | 62 FROM_HERE, base::Bind(callback, result, extensions, body_head, |
61 base::Bind(callback, result, extensions, body_head, | 63 base::Passed(&socket))); |
62 base::Passed(&socket))); | |
63 } | 64 } |
64 | 65 |
65 class HttpRequest { | 66 class HttpRequest { |
66 public: | 67 public: |
67 typedef AndroidDeviceManager::CommandCallback CommandCallback; | 68 typedef AndroidDeviceManager::CommandCallback CommandCallback; |
68 typedef AndroidDeviceManager::HttpUpgradeCallback HttpUpgradeCallback; | 69 typedef AndroidDeviceManager::HttpUpgradeCallback HttpUpgradeCallback; |
69 | 70 |
70 static void CommandRequest(const std::string& request, | 71 static void CommandRequest(const std::string& request, |
71 const CommandCallback& callback, | 72 const CommandCallback& callback, |
72 int result, | 73 int result, |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 | 261 |
261 class DevicesRequest : public base::RefCountedThreadSafe<DevicesRequest> { | 262 class DevicesRequest : public base::RefCountedThreadSafe<DevicesRequest> { |
262 public: | 263 public: |
263 typedef AndroidDeviceManager::DeviceInfo DeviceInfo; | 264 typedef AndroidDeviceManager::DeviceInfo DeviceInfo; |
264 typedef AndroidDeviceManager::DeviceProvider DeviceProvider; | 265 typedef AndroidDeviceManager::DeviceProvider DeviceProvider; |
265 typedef AndroidDeviceManager::DeviceProviders DeviceProviders; | 266 typedef AndroidDeviceManager::DeviceProviders DeviceProviders; |
266 typedef AndroidDeviceManager::DeviceDescriptors DeviceDescriptors; | 267 typedef AndroidDeviceManager::DeviceDescriptors DeviceDescriptors; |
267 typedef base::Callback<void(scoped_ptr<DeviceDescriptors>)> | 268 typedef base::Callback<void(scoped_ptr<DeviceDescriptors>)> |
268 DescriptorsCallback; | 269 DescriptorsCallback; |
269 | 270 |
270 static void Start(scoped_refptr<base::MessageLoopProxy> device_message_loop, | 271 static void Start( |
271 const DeviceProviders& providers, | 272 scoped_refptr<base::SingleThreadTaskRunner> device_task_runner, |
272 const DescriptorsCallback& callback) { | 273 const DeviceProviders& providers, |
| 274 const DescriptorsCallback& callback) { |
273 // Don't keep counted reference on calling thread; | 275 // Don't keep counted reference on calling thread; |
274 DevicesRequest* request = new DevicesRequest(callback); | 276 DevicesRequest* request = new DevicesRequest(callback); |
275 // Avoid destruction while sending requests | 277 // Avoid destruction while sending requests |
276 request->AddRef(); | 278 request->AddRef(); |
277 for (DeviceProviders::const_iterator it = providers.begin(); | 279 for (DeviceProviders::const_iterator it = providers.begin(); |
278 it != providers.end(); ++it) { | 280 it != providers.end(); ++it) { |
279 device_message_loop->PostTask( | 281 device_task_runner->PostTask( |
280 FROM_HERE, | 282 FROM_HERE, base::Bind(&DeviceProvider::QueryDevices, *it, |
281 base::Bind( | 283 base::Bind(&DevicesRequest::ProcessSerials, |
282 &DeviceProvider::QueryDevices, | 284 request, *it))); |
283 *it, | |
284 base::Bind(&DevicesRequest::ProcessSerials, request, *it))); | |
285 } | 285 } |
286 device_message_loop->ReleaseSoon(FROM_HERE, request); | 286 device_task_runner->ReleaseSoon(FROM_HERE, request); |
287 } | 287 } |
288 | 288 |
289 private: | 289 private: |
290 explicit DevicesRequest(const DescriptorsCallback& callback) | 290 explicit DevicesRequest(const DescriptorsCallback& callback) |
291 : response_message_loop_(base::MessageLoopProxy::current()), | 291 : response_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
292 callback_(callback), | 292 callback_(callback), |
293 descriptors_(new DeviceDescriptors()) { | 293 descriptors_(new DeviceDescriptors()) {} |
294 } | |
295 | 294 |
296 friend class base::RefCountedThreadSafe<DevicesRequest>; | 295 friend class base::RefCountedThreadSafe<DevicesRequest>; |
297 ~DevicesRequest() { | 296 ~DevicesRequest() { |
298 response_message_loop_->PostTask(FROM_HERE, | 297 response_task_runner_->PostTask( |
299 base::Bind(callback_, base::Passed(&descriptors_))); | 298 FROM_HERE, base::Bind(callback_, base::Passed(&descriptors_))); |
300 } | 299 } |
301 | 300 |
302 typedef std::vector<std::string> Serials; | 301 typedef std::vector<std::string> Serials; |
303 | 302 |
304 void ProcessSerials(scoped_refptr<DeviceProvider> provider, | 303 void ProcessSerials(scoped_refptr<DeviceProvider> provider, |
305 const Serials& serials) { | 304 const Serials& serials) { |
306 for (Serials::const_iterator it = serials.begin(); it != serials.end(); | 305 for (Serials::const_iterator it = serials.begin(); it != serials.end(); |
307 ++it) { | 306 ++it) { |
308 descriptors_->resize(descriptors_->size() + 1); | 307 descriptors_->resize(descriptors_->size() + 1); |
309 descriptors_->back().provider = provider; | 308 descriptors_->back().provider = provider; |
310 descriptors_->back().serial = *it; | 309 descriptors_->back().serial = *it; |
311 } | 310 } |
312 } | 311 } |
313 | 312 |
314 scoped_refptr<base::MessageLoopProxy> response_message_loop_; | 313 scoped_refptr<base::SingleThreadTaskRunner> response_task_runner_; |
315 DescriptorsCallback callback_; | 314 DescriptorsCallback callback_; |
316 scoped_ptr<DeviceDescriptors> descriptors_; | 315 scoped_ptr<DeviceDescriptors> descriptors_; |
317 }; | 316 }; |
318 | 317 |
319 void ReleaseDeviceAndProvider( | 318 void ReleaseDeviceAndProvider( |
320 AndroidDeviceManager::DeviceProvider* provider, | 319 AndroidDeviceManager::DeviceProvider* provider, |
321 const std::string& serial) { | 320 const std::string& serial) { |
322 provider->ReleaseDevice(serial); | 321 provider->ReleaseDevice(serial); |
323 provider->Release(); | 322 provider->Release(); |
324 } | 323 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
377 } | 376 } |
378 | 377 |
379 AndroidDeviceManager::DeviceProvider::DeviceProvider() { | 378 AndroidDeviceManager::DeviceProvider::DeviceProvider() { |
380 } | 379 } |
381 | 380 |
382 AndroidDeviceManager::DeviceProvider::~DeviceProvider() { | 381 AndroidDeviceManager::DeviceProvider::~DeviceProvider() { |
383 } | 382 } |
384 | 383 |
385 void AndroidDeviceManager::Device::QueryDeviceInfo( | 384 void AndroidDeviceManager::Device::QueryDeviceInfo( |
386 const DeviceInfoCallback& callback) { | 385 const DeviceInfoCallback& callback) { |
387 message_loop_proxy_->PostTask( | 386 task_runner_->PostTask( |
388 FROM_HERE, | 387 FROM_HERE, |
389 base::Bind(&DeviceProvider::QueryDeviceInfo, | 388 base::Bind(&DeviceProvider::QueryDeviceInfo, provider_, serial_, |
390 provider_, | |
391 serial_, | |
392 base::Bind(&PostDeviceInfoCallback, | 389 base::Bind(&PostDeviceInfoCallback, |
393 base::MessageLoopProxy::current(), | 390 base::ThreadTaskRunnerHandle::Get(), callback))); |
394 callback))); | |
395 } | 391 } |
396 | 392 |
397 void AndroidDeviceManager::Device::OpenSocket(const std::string& socket_name, | 393 void AndroidDeviceManager::Device::OpenSocket(const std::string& socket_name, |
398 const SocketCallback& callback) { | 394 const SocketCallback& callback) { |
399 message_loop_proxy_->PostTask( | 395 task_runner_->PostTask( |
400 FROM_HERE, | 396 FROM_HERE, base::Bind(&DeviceProvider::OpenSocket, provider_, serial_, |
401 base::Bind(&DeviceProvider::OpenSocket, | 397 socket_name, callback)); |
402 provider_, | |
403 serial_, | |
404 socket_name, | |
405 callback)); | |
406 } | 398 } |
407 | 399 |
408 void AndroidDeviceManager::Device::SendJsonRequest( | 400 void AndroidDeviceManager::Device::SendJsonRequest( |
409 const std::string& socket_name, | 401 const std::string& socket_name, |
410 const std::string& request, | 402 const std::string& request, |
411 const CommandCallback& callback) { | 403 const CommandCallback& callback) { |
412 message_loop_proxy_->PostTask( | 404 task_runner_->PostTask( |
413 FROM_HERE, | 405 FROM_HERE, |
414 base::Bind(&DeviceProvider::SendJsonRequest, | 406 base::Bind(&DeviceProvider::SendJsonRequest, provider_, serial_, |
415 provider_, | 407 socket_name, request, |
416 serial_, | |
417 socket_name, | |
418 request, | |
419 base::Bind(&PostCommandCallback, | 408 base::Bind(&PostCommandCallback, |
420 base::MessageLoopProxy::current(), | 409 base::ThreadTaskRunnerHandle::Get(), callback))); |
421 callback))); | |
422 } | 410 } |
423 | 411 |
424 void AndroidDeviceManager::Device::HttpUpgrade( | 412 void AndroidDeviceManager::Device::HttpUpgrade( |
425 const std::string& socket_name, | 413 const std::string& socket_name, |
426 const std::string& url, | 414 const std::string& url, |
427 const std::string& extensions, | 415 const std::string& extensions, |
428 const HttpUpgradeCallback& callback) { | 416 const HttpUpgradeCallback& callback) { |
429 message_loop_proxy_->PostTask( | 417 task_runner_->PostTask( |
430 FROM_HERE, | 418 FROM_HERE, |
431 base::Bind(&DeviceProvider::HttpUpgrade, | 419 base::Bind(&DeviceProvider::HttpUpgrade, provider_, serial_, socket_name, |
432 provider_, | 420 url, extensions, |
433 serial_, | |
434 socket_name, | |
435 url, | |
436 extensions, | |
437 base::Bind(&PostHttpUpgradeCallback, | 421 base::Bind(&PostHttpUpgradeCallback, |
438 base::MessageLoopProxy::current(), | 422 base::ThreadTaskRunnerHandle::Get(), callback))); |
439 callback))); | |
440 } | 423 } |
441 | 424 |
442 AndroidDeviceManager::Device::Device( | 425 AndroidDeviceManager::Device::Device( |
443 scoped_refptr<base::MessageLoopProxy> device_message_loop, | 426 scoped_refptr<base::SingleThreadTaskRunner> device_task_runner, |
444 scoped_refptr<DeviceProvider> provider, | 427 scoped_refptr<DeviceProvider> provider, |
445 const std::string& serial) | 428 const std::string& serial) |
446 : message_loop_proxy_(device_message_loop), | 429 : task_runner_(device_task_runner), |
447 provider_(provider), | 430 provider_(provider), |
448 serial_(serial), | 431 serial_(serial), |
449 weak_factory_(this) { | 432 weak_factory_(this) { |
450 } | 433 } |
451 | 434 |
452 AndroidDeviceManager::Device::~Device() { | 435 AndroidDeviceManager::Device::~Device() { |
453 std::set<AndroidWebSocket*> sockets_copy(sockets_); | 436 std::set<AndroidWebSocket*> sockets_copy(sockets_); |
454 for (AndroidWebSocket* socket : sockets_copy) | 437 for (AndroidWebSocket* socket : sockets_copy) |
455 socket->OnSocketClosed(); | 438 socket->OnSocketClosed(); |
456 | 439 |
457 provider_->AddRef(); | 440 provider_->AddRef(); |
458 DeviceProvider* raw_ptr = provider_.get(); | 441 DeviceProvider* raw_ptr = provider_.get(); |
459 provider_ = NULL; | 442 provider_ = NULL; |
460 message_loop_proxy_->PostTask( | 443 task_runner_->PostTask(FROM_HERE, |
461 FROM_HERE, | 444 base::Bind(&ReleaseDeviceAndProvider, |
462 base::Bind(&ReleaseDeviceAndProvider, | 445 base::Unretained(raw_ptr), serial_)); |
463 base::Unretained(raw_ptr), | |
464 serial_)); | |
465 } | 446 } |
466 | 447 |
467 AndroidDeviceManager::HandlerThread* | 448 AndroidDeviceManager::HandlerThread* |
468 AndroidDeviceManager::HandlerThread::instance_ = NULL; | 449 AndroidDeviceManager::HandlerThread::instance_ = NULL; |
469 | 450 |
470 // static | 451 // static |
471 scoped_refptr<AndroidDeviceManager::HandlerThread> | 452 scoped_refptr<AndroidDeviceManager::HandlerThread> |
472 AndroidDeviceManager::HandlerThread::GetInstance() { | 453 AndroidDeviceManager::HandlerThread::GetInstance() { |
473 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 454 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
474 if (!instance_) | 455 if (!instance_) |
475 new HandlerThread(); | 456 new HandlerThread(); |
476 return instance_; | 457 return instance_; |
477 } | 458 } |
478 | 459 |
479 AndroidDeviceManager::HandlerThread::HandlerThread() { | 460 AndroidDeviceManager::HandlerThread::HandlerThread() { |
480 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 461 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
481 instance_ = this; | 462 instance_ = this; |
482 thread_ = new base::Thread(kDevToolsAdbBridgeThreadName); | 463 thread_ = new base::Thread(kDevToolsAdbBridgeThreadName); |
483 base::Thread::Options options; | 464 base::Thread::Options options; |
484 options.message_loop_type = base::MessageLoop::TYPE_IO; | 465 options.message_loop_type = base::MessageLoop::TYPE_IO; |
485 if (!thread_->StartWithOptions(options)) { | 466 if (!thread_->StartWithOptions(options)) { |
486 delete thread_; | 467 delete thread_; |
487 thread_ = NULL; | 468 thread_ = NULL; |
488 } | 469 } |
489 } | 470 } |
490 | 471 |
491 scoped_refptr<base::MessageLoopProxy> | 472 scoped_refptr<base::SingleThreadTaskRunner> |
492 AndroidDeviceManager::HandlerThread::message_loop() { | 473 AndroidDeviceManager::HandlerThread::message_loop() { |
493 return thread_ ? thread_->message_loop_proxy() : NULL; | 474 return thread_ ? thread_->task_runner() : NULL; |
494 } | 475 } |
495 | 476 |
496 // static | 477 // static |
497 void AndroidDeviceManager::HandlerThread::StopThread( | 478 void AndroidDeviceManager::HandlerThread::StopThread( |
498 base::Thread* thread) { | 479 base::Thread* thread) { |
499 thread->Stop(); | 480 thread->Stop(); |
500 } | 481 } |
501 | 482 |
502 AndroidDeviceManager::HandlerThread::~HandlerThread() { | 483 AndroidDeviceManager::HandlerThread::~HandlerThread() { |
503 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 484 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
(...skipping 17 matching lines...) Expand all Loading... |
521 it != providers_.end(); ++it) { | 502 it != providers_.end(); ++it) { |
522 (*it)->AddRef(); | 503 (*it)->AddRef(); |
523 DeviceProvider* raw_ptr = it->get(); | 504 DeviceProvider* raw_ptr = it->get(); |
524 *it = NULL; | 505 *it = NULL; |
525 handler_thread_->message_loop()->ReleaseSoon(FROM_HERE, raw_ptr); | 506 handler_thread_->message_loop()->ReleaseSoon(FROM_HERE, raw_ptr); |
526 } | 507 } |
527 providers_ = providers; | 508 providers_ = providers; |
528 } | 509 } |
529 | 510 |
530 void AndroidDeviceManager::QueryDevices(const DevicesCallback& callback) { | 511 void AndroidDeviceManager::QueryDevices(const DevicesCallback& callback) { |
531 DevicesRequest::Start(handler_thread_->message_loop(), | 512 DevicesRequest::Start(handler_thread_->message_loop(), providers_, |
532 providers_, | |
533 base::Bind(&AndroidDeviceManager::UpdateDevices, | 513 base::Bind(&AndroidDeviceManager::UpdateDevices, |
534 weak_factory_.GetWeakPtr(), | 514 weak_factory_.GetWeakPtr(), callback)); |
535 callback)); | |
536 } | 515 } |
537 | 516 |
538 AndroidDeviceManager::AndroidDeviceManager() | 517 AndroidDeviceManager::AndroidDeviceManager() |
539 : handler_thread_(HandlerThread::GetInstance()), | 518 : handler_thread_(HandlerThread::GetInstance()), |
540 weak_factory_(this) { | 519 weak_factory_(this) { |
541 } | 520 } |
542 | 521 |
543 AndroidDeviceManager::~AndroidDeviceManager() { | 522 AndroidDeviceManager::~AndroidDeviceManager() { |
544 SetDeviceProviders(DeviceProviders()); | 523 SetDeviceProviders(DeviceProviders()); |
545 } | 524 } |
546 | 525 |
547 void AndroidDeviceManager::UpdateDevices( | 526 void AndroidDeviceManager::UpdateDevices( |
548 const DevicesCallback& callback, | 527 const DevicesCallback& callback, |
549 scoped_ptr<DeviceDescriptors> descriptors) { | 528 scoped_ptr<DeviceDescriptors> descriptors) { |
550 Devices response; | 529 Devices response; |
551 DeviceWeakMap new_devices; | 530 DeviceWeakMap new_devices; |
552 for (DeviceDescriptors::const_iterator it = descriptors->begin(); | 531 for (DeviceDescriptors::const_iterator it = descriptors->begin(); |
553 it != descriptors->end(); | 532 it != descriptors->end(); |
554 ++it) { | 533 ++it) { |
555 DeviceWeakMap::iterator found = devices_.find(it->serial); | 534 DeviceWeakMap::iterator found = devices_.find(it->serial); |
556 scoped_refptr<Device> device; | 535 scoped_refptr<Device> device; |
557 if (found == devices_.end() || !found->second || | 536 if (found == devices_.end() || !found->second || |
558 found->second->provider_.get() != it->provider.get()) { | 537 found->second->provider_.get() != it->provider.get()) { |
559 device = new Device(handler_thread_->message_loop(), | 538 device = |
560 it->provider, it->serial); | 539 new Device(handler_thread_->message_loop(), it->provider, it->serial); |
561 } else { | 540 } else { |
562 device = found->second.get(); | 541 device = found->second.get(); |
563 } | 542 } |
564 response.push_back(device); | 543 response.push_back(device); |
565 new_devices[it->serial] = device->weak_factory_.GetWeakPtr(); | 544 new_devices[it->serial] = device->weak_factory_.GetWeakPtr(); |
566 } | 545 } |
567 devices_.swap(new_devices); | 546 devices_.swap(new_devices); |
568 callback.Run(response); | 547 callback.Run(response); |
569 } | 548 } |
OLD | NEW |