DevTools: cut host and port from webSocketDebuggerUrl in addition to ws:// prefix
[chromium-blink-merge.git] / chrome / browser / devtools / device / usb / android_usb_browsertest.cc
blob7f73ba65dcff86f711d4668b7a54639e254458a0
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
3 // found in the LICENSE file.
5 #include <algorithm>
7 #include "base/containers/scoped_ptr_hash_map.h"
8 #include "base/location.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "chrome/browser/devtools/device/adb/mock_adb_server.h"
13 #include "chrome/browser/devtools/device/devtools_android_bridge.h"
14 #include "chrome/browser/devtools/device/usb/android_usb_device.h"
15 #include "chrome/browser/devtools/device/usb/usb_device_provider.h"
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/test/base/in_process_browser_test.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/test/test_utils.h"
20 #include "device/usb/usb_descriptors.h"
21 #include "device/usb/usb_device.h"
22 #include "device/usb/usb_device_handle.h"
23 #include "device/usb/usb_service.h"
24 #include "testing/gtest/include/gtest/gtest.h"
26 using content::BrowserThread;
27 using device::UsbConfigDescriptor;
28 using device::UsbDevice;
29 using device::UsbDeviceHandle;
30 using device::UsbEndpointDescriptor;
31 using device::UsbEndpointDirection;
32 using device::UsbInterfaceDescriptor;
33 using device::UsbService;
34 using device::UsbSynchronizationType;
35 using device::UsbTransferType;
36 using device::UsbUsageType;
38 namespace {
40 struct NoConfigTraits {
41 static const int kClass = 0xff;
42 static const int kSubclass = 0x42;
43 static const int kProtocol = 0x1;
44 static const bool kBreaks = false;
45 static const bool kConfigured = false;
48 struct AndroidTraits {
49 static const int kClass = 0xff;
50 static const int kSubclass = 0x42;
51 static const int kProtocol = 0x1;
52 static const bool kBreaks = false;
53 static const bool kConfigured = true;
56 struct NonAndroidTraits {
57 static const int kClass = 0xf0;
58 static const int kSubclass = 0x42;
59 static const int kProtocol = 0x2;
60 static const bool kBreaks = false;
61 static const bool kConfigured = true;
64 struct BreakingAndroidTraits {
65 static const int kClass = 0xff;
66 static const int kSubclass = 0x42;
67 static const int kProtocol = 0x1;
68 static const bool kBreaks = true;
69 static const bool kConfigured = true;
72 const uint32 kMaxPayload = 4096;
73 const uint32 kVersion = 0x01000000;
75 const char kDeviceManufacturer[] = "Test Manufacturer";
76 const char kDeviceModel[] = "Nexus 6";
77 const char kDeviceSerial[] = "01498B321301A00A";
79 template <class T>
80 class MockUsbDevice;
82 class MockLocalSocket : public MockAndroidConnection::Delegate {
83 public:
84 using Callback = base::Callback<void(int command,
85 const std::string& message)>;
87 MockLocalSocket(const Callback& callback,
88 const std::string& serial,
89 const std::string& command)
90 : callback_(callback),
91 connection_(new MockAndroidConnection(this, serial, command)) {
94 void Receive(const std::string& data) {
95 connection_->Receive(data);
98 private:
99 void SendSuccess(const std::string& message) override {
100 if (!message.empty())
101 callback_.Run(AdbMessage::kCommandWRTE, message);
104 void SendRaw(const std::string& message) override {
105 callback_.Run(AdbMessage::kCommandWRTE, message);
108 void Close() override {
109 callback_.Run(AdbMessage::kCommandCLSE, std::string());
112 Callback callback_;
113 scoped_ptr<MockAndroidConnection> connection_;
116 template <class T>
117 class MockUsbDeviceHandle : public UsbDeviceHandle {
118 public:
119 explicit MockUsbDeviceHandle(MockUsbDevice<T>* device)
120 : device_(device),
121 remaining_body_length_(0),
122 last_local_socket_(0),
123 broken_(false) {
126 scoped_refptr<UsbDevice> GetDevice() const override {
127 return device_;
130 void Close() override { device_ = nullptr; }
132 void SetConfiguration(int configuration_value,
133 const ResultCallback& callback) override {
134 NOTIMPLEMENTED();
137 void ClaimInterface(int interface_number,
138 const ResultCallback& callback) override {
139 bool success = false;
140 if (device_->claimed_interfaces_.find(interface_number) ==
141 device_->claimed_interfaces_.end()) {
142 device_->claimed_interfaces_.insert(interface_number);
143 success = true;
146 base::ThreadTaskRunnerHandle::Get()->PostTask(
147 FROM_HERE, base::Bind(callback, success));
150 bool ReleaseInterface(int interface_number) override {
151 if (device_->claimed_interfaces_.find(interface_number) ==
152 device_->claimed_interfaces_.end())
153 return false;
155 device_->claimed_interfaces_.erase(interface_number);
156 return true;
159 void SetInterfaceAlternateSetting(int interface_number,
160 int alternate_setting,
161 const ResultCallback& callback) override {
162 NOTIMPLEMENTED();
165 void ResetDevice(const ResultCallback& callback) override {
166 NOTIMPLEMENTED();
169 // Async IO. Can be called on any thread.
170 void ControlTransfer(UsbEndpointDirection direction,
171 TransferRequestType request_type,
172 TransferRecipient recipient,
173 uint8 request,
174 uint16 value,
175 uint16 index,
176 scoped_refptr<net::IOBuffer> buffer,
177 size_t length,
178 unsigned int timeout,
179 const TransferCallback& callback) override {}
181 void BulkTransfer(UsbEndpointDirection direction,
182 uint8 endpoint,
183 scoped_refptr<net::IOBuffer> buffer,
184 size_t length,
185 unsigned int timeout,
186 const TransferCallback& callback) override {
187 if (direction == device::USB_DIRECTION_OUTBOUND) {
188 if (remaining_body_length_ == 0) {
189 std::vector<uint32> header(6);
190 memcpy(&header[0], buffer->data(), length);
191 current_message_.reset(
192 new AdbMessage(header[0], header[1], header[2], std::string()));
193 remaining_body_length_ = header[3];
194 uint32 magic = header[5];
195 if ((current_message_->command ^ 0xffffffff) != magic) {
196 DCHECK(false) << "Header checksum error";
197 return;
199 } else {
200 DCHECK(current_message_.get());
201 current_message_->body += std::string(buffer->data(), length);
202 remaining_body_length_ -= length;
205 if (remaining_body_length_ == 0) {
206 ProcessIncoming();
209 device::UsbTransferStatus status =
210 broken_ ? device::USB_TRANSFER_ERROR : device::USB_TRANSFER_COMPLETED;
211 base::ThreadTaskRunnerHandle::Get()->PostTask(
212 FROM_HERE, base::Bind(callback, status, nullptr, 0));
213 ProcessQueries();
214 } else if (direction == device::USB_DIRECTION_INBOUND) {
215 queries_.push(Query(callback, buffer, length));
216 ProcessQueries();
220 template <class D>
221 void append(D data) {
222 std::copy(reinterpret_cast<char*>(&data),
223 (reinterpret_cast<char*>(&data)) + sizeof(D),
224 std::back_inserter(output_buffer_));
227 // Copied from AndroidUsbDevice::Checksum
228 uint32 Checksum(const std::string& data) {
229 unsigned char* x = (unsigned char*)data.data();
230 int count = data.length();
231 uint32 sum = 0;
232 while (count-- > 0)
233 sum += *x++;
234 return sum;
237 void ProcessIncoming() {
238 DCHECK(current_message_.get());
239 switch (current_message_->command) {
240 case AdbMessage::kCommandCNXN: {
241 WriteResponse(kVersion,
242 kMaxPayload,
243 AdbMessage::kCommandCNXN,
244 "device::ro.product.name=SampleProduct;ro.product.model="
245 "SampleModel;ro.product.device=SampleDevice;");
246 break;
248 case AdbMessage::kCommandCLSE: {
249 WriteResponse(0,
250 current_message_->arg0,
251 AdbMessage::kCommandCLSE,
252 std::string());
253 local_sockets_.erase(current_message_->arg0);
254 break;
256 case AdbMessage::kCommandWRTE: {
257 if (T::kBreaks) {
258 broken_ = true;
259 return;
261 auto it = local_sockets_.find(current_message_->arg0);
262 if (it == local_sockets_.end())
263 return;
265 DCHECK(current_message_->arg1 != 0);
266 WriteResponse(current_message_->arg1,
267 current_message_->arg0,
268 AdbMessage::kCommandOKAY,
269 std::string());
270 it->second->Receive(current_message_->body);
271 break;
273 case AdbMessage::kCommandOPEN: {
274 DCHECK(current_message_->arg1 == 0);
275 DCHECK(current_message_->arg0 != 0);
276 std::string response;
277 WriteResponse(++last_local_socket_,
278 current_message_->arg0,
279 AdbMessage::kCommandOKAY,
280 std::string());
281 local_sockets_.set(
282 current_message_->arg0,
283 make_scoped_ptr(new MockLocalSocket(
284 base::Bind(&MockUsbDeviceHandle::WriteResponse,
285 base::Unretained(this),
286 last_local_socket_,
287 current_message_->arg0),
288 kDeviceSerial,
289 current_message_->body.substr(
290 0, current_message_->body.size() - 1))));
291 return;
293 default: {
294 return;
297 ProcessQueries();
300 void WriteResponse(int arg0, int arg1, int command, const std::string& body) {
301 append(command);
302 append(arg0);
303 append(arg1);
304 bool add_zero = !body.empty() && (command != AdbMessage::kCommandWRTE);
305 append(static_cast<uint32>(body.size() + (add_zero ? 1 : 0)));
306 append(Checksum(body));
307 append(command ^ 0xffffffff);
308 std::copy(body.begin(), body.end(), std::back_inserter(output_buffer_));
309 if (add_zero) {
310 output_buffer_.push_back(0);
312 ProcessQueries();
315 void ProcessQueries() {
316 if (!queries_.size())
317 return;
318 Query query = queries_.front();
319 if (broken_) {
320 base::ThreadTaskRunnerHandle::Get()->PostTask(
321 FROM_HERE,
322 base::Bind(query.callback, device::USB_TRANSFER_ERROR, nullptr, 0));
325 if (query.size > output_buffer_.size())
326 return;
328 queries_.pop();
329 std::copy(output_buffer_.begin(),
330 output_buffer_.begin() + query.size,
331 query.buffer->data());
332 output_buffer_.erase(output_buffer_.begin(),
333 output_buffer_.begin() + query.size);
334 base::ThreadTaskRunnerHandle::Get()->PostTask(
335 FROM_HERE, base::Bind(query.callback, device::USB_TRANSFER_COMPLETED,
336 query.buffer, query.size));
339 void InterruptTransfer(UsbEndpointDirection direction,
340 uint8 endpoint,
341 scoped_refptr<net::IOBuffer> buffer,
342 size_t length,
343 unsigned int timeout,
344 const TransferCallback& callback) override {}
346 void IsochronousTransfer(UsbEndpointDirection direction,
347 uint8 endpoint,
348 scoped_refptr<net::IOBuffer> buffer,
349 size_t length,
350 unsigned int packets,
351 unsigned int packet_length,
352 unsigned int timeout,
353 const TransferCallback& callback) override {}
355 protected:
356 virtual ~MockUsbDeviceHandle() {}
358 struct Query {
359 TransferCallback callback;
360 scoped_refptr<net::IOBuffer> buffer;
361 size_t size;
363 Query(TransferCallback callback,
364 scoped_refptr<net::IOBuffer> buffer,
365 int size)
366 : callback(callback), buffer(buffer), size(size) {}
369 scoped_refptr<MockUsbDevice<T> > device_;
370 uint32 remaining_body_length_;
371 scoped_ptr<AdbMessage> current_message_;
372 std::vector<char> output_buffer_;
373 std::queue<Query> queries_;
374 base::ScopedPtrHashMap<int, scoped_ptr<MockLocalSocket>> local_sockets_;
375 int last_local_socket_;
376 bool broken_;
379 template <class T>
380 class MockUsbDevice : public UsbDevice {
381 public:
382 MockUsbDevice()
383 : UsbDevice(0,
385 base::UTF8ToUTF16(kDeviceManufacturer),
386 base::UTF8ToUTF16(kDeviceModel),
387 base::UTF8ToUTF16(kDeviceSerial)) {
388 UsbEndpointDescriptor bulk_in;
389 bulk_in.address = 0x81;
390 bulk_in.direction = device::USB_DIRECTION_INBOUND;
391 bulk_in.maximum_packet_size = 512;
392 bulk_in.transfer_type = device::USB_TRANSFER_BULK;
394 UsbEndpointDescriptor bulk_out;
395 bulk_out.address = 0x01;
396 bulk_out.direction = device::USB_DIRECTION_OUTBOUND;
397 bulk_out.maximum_packet_size = 512;
398 bulk_out.transfer_type = device::USB_TRANSFER_BULK;
400 UsbInterfaceDescriptor interface_desc;
401 interface_desc.interface_number = 0;
402 interface_desc.alternate_setting = 0;
403 interface_desc.interface_class = T::kClass;
404 interface_desc.interface_subclass = T::kSubclass;
405 interface_desc.interface_protocol = T::kProtocol;
406 interface_desc.endpoints.push_back(bulk_in);
407 interface_desc.endpoints.push_back(bulk_out);
409 config_desc_.interfaces.push_back(interface_desc);
412 void Open(const OpenCallback& callback) override {
413 base::ThreadTaskRunnerHandle::Get()->PostTask(
414 FROM_HERE, base::Bind(callback, make_scoped_refptr(
415 new MockUsbDeviceHandle<T>(this))));
418 const UsbConfigDescriptor* GetConfiguration() override {
419 return T::kConfigured ? &config_desc_ : nullptr;
422 bool Close(scoped_refptr<UsbDeviceHandle> handle) override {
423 return true;
426 std::set<int> claimed_interfaces_;
428 protected:
429 virtual ~MockUsbDevice() {}
431 private:
432 UsbConfigDescriptor config_desc_;
435 class MockUsbService : public UsbService {
436 public:
437 MockUsbService() {
438 devices_.push_back(new MockUsbDevice<AndroidTraits>());
441 scoped_refptr<UsbDevice> GetDevice(const std::string& guid) override {
442 NOTIMPLEMENTED();
443 return nullptr;
446 void GetDevices(const GetDevicesCallback& callback) override {
447 callback.Run(devices_);
450 std::vector<scoped_refptr<UsbDevice> > devices_;
453 class MockBreakingUsbService : public MockUsbService {
454 public:
455 MockBreakingUsbService() {
456 devices_.clear();
457 devices_.push_back(new MockUsbDevice<BreakingAndroidTraits>());
461 class MockNoConfigUsbService : public MockUsbService {
462 public:
463 MockNoConfigUsbService() {
464 devices_.push_back(new MockUsbDevice<NoConfigTraits>());
468 class MockUsbServiceForCheckingTraits : public MockUsbService {
469 public:
470 MockUsbServiceForCheckingTraits() : step_(0) {}
472 void GetDevices(const GetDevicesCallback& callback) override {
473 std::vector<scoped_refptr<UsbDevice>> devices;
474 // This switch should be kept in sync with
475 // AndroidUsbBrowserTest::DeviceCountChanged.
476 switch (step_) {
477 case 0:
478 // No devices.
479 break;
480 case 1:
481 // Android device.
482 devices.push_back(new MockUsbDevice<AndroidTraits>());
483 break;
484 case 2:
485 // Android and non-android device.
486 devices.push_back(new MockUsbDevice<AndroidTraits>());
487 devices.push_back(new MockUsbDevice<NonAndroidTraits>());
488 break;
489 case 3:
490 // Non-android device.
491 devices.push_back(new MockUsbDevice<NonAndroidTraits>());
492 break;
494 step_++;
495 callback.Run(devices);
498 private:
499 int step_;
502 class DevToolsAndroidBridgeWarmUp
503 : public DevToolsAndroidBridge::DeviceCountListener {
504 public:
505 DevToolsAndroidBridgeWarmUp(base::Closure closure,
506 DevToolsAndroidBridge* adb_bridge)
507 : closure_(closure), adb_bridge_(adb_bridge) {}
509 void DeviceCountChanged(int count) override {
510 adb_bridge_->RemoveDeviceCountListener(this);
511 closure_.Run();
514 base::Closure closure_;
515 DevToolsAndroidBridge* adb_bridge_;
518 class AndroidUsbDiscoveryTest : public InProcessBrowserTest {
519 protected:
520 AndroidUsbDiscoveryTest()
521 : scheduler_invoked_(0) {
523 void SetUpOnMainThread() override {
524 mock_usb_service_.reset(CreateMockService());
526 adb_bridge_ =
527 DevToolsAndroidBridge::Factory::GetForProfile(browser()->profile());
528 DCHECK(adb_bridge_);
529 adb_bridge_->set_task_scheduler_for_test(base::Bind(
530 &AndroidUsbDiscoveryTest::ScheduleDeviceCountRequest, this));
532 scoped_refptr<UsbDeviceProvider> provider =
533 new UsbDeviceProvider(browser()->profile());
535 AndroidDeviceManager::DeviceProviders providers;
536 providers.push_back(provider);
537 adb_bridge_->set_device_providers_for_test(providers);
538 runner_ = new content::MessageLoopRunner;
541 void ScheduleDeviceCountRequest(const base::Closure& request) {
542 DCHECK_CURRENTLY_ON(BrowserThread::UI);
543 scheduler_invoked_++;
544 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, request);
547 virtual MockUsbService* CreateMockService() { return new MockUsbService(); }
549 scoped_refptr<content::MessageLoopRunner> runner_;
550 scoped_ptr<MockUsbService> mock_usb_service_;
551 DevToolsAndroidBridge* adb_bridge_;
552 int scheduler_invoked_;
555 class AndroidUsbCountTest : public AndroidUsbDiscoveryTest {
556 protected:
557 void SetUpOnMainThread() override {
558 AndroidUsbDiscoveryTest::SetUpOnMainThread();
559 DevToolsAndroidBridgeWarmUp warmup(runner_->QuitClosure(), adb_bridge_);
560 adb_bridge_->AddDeviceCountListener(&warmup);
561 runner_->Run();
562 runner_ = new content::MessageLoopRunner;
566 class AndroidUsbTraitsTest : public AndroidUsbDiscoveryTest {
567 protected:
568 MockUsbService* CreateMockService() override {
569 return new MockUsbServiceForCheckingTraits();
573 class AndroidBreakingUsbTest : public AndroidUsbDiscoveryTest {
574 protected:
575 MockUsbService* CreateMockService() override {
576 return new MockBreakingUsbService();
580 class AndroidNoConfigUsbTest : public AndroidUsbDiscoveryTest {
581 protected:
582 MockUsbService* CreateMockService() override {
583 return new MockNoConfigUsbService();
587 class MockListListener : public DevToolsAndroidBridge::DeviceListListener {
588 public:
589 MockListListener(DevToolsAndroidBridge* adb_bridge,
590 const base::Closure& callback)
591 : adb_bridge_(adb_bridge),
592 callback_(callback) {
595 void DeviceListChanged(
596 const DevToolsAndroidBridge::RemoteDevices& devices) override {
597 if (devices.size() > 0) {
598 for (const auto& device : devices) {
599 if (device->is_connected()) {
600 ASSERT_EQ(kDeviceModel, device->model());
601 ASSERT_EQ(kDeviceSerial, device->serial());
602 adb_bridge_->RemoveDeviceListListener(this);
603 callback_.Run();
604 break;
610 DevToolsAndroidBridge* adb_bridge_;
611 base::Closure callback_;
614 class MockCountListener : public DevToolsAndroidBridge::DeviceCountListener {
615 public:
616 explicit MockCountListener(DevToolsAndroidBridge* adb_bridge)
617 : adb_bridge_(adb_bridge), invoked_(0) {}
619 void DeviceCountChanged(int count) override {
620 ++invoked_;
621 adb_bridge_->RemoveDeviceCountListener(this);
622 Shutdown();
625 void Shutdown() { base::MessageLoop::current()->Quit(); }
627 DevToolsAndroidBridge* adb_bridge_;
628 int invoked_;
631 class MockCountListenerWithReAdd : public MockCountListener {
632 public:
633 explicit MockCountListenerWithReAdd(
634 DevToolsAndroidBridge* adb_bridge)
635 : MockCountListener(adb_bridge),
636 readd_count_(2) {
639 void DeviceCountChanged(int count) override {
640 ++invoked_;
641 adb_bridge_->RemoveDeviceCountListener(this);
642 if (readd_count_ > 0) {
643 readd_count_--;
644 adb_bridge_->AddDeviceCountListener(this);
645 adb_bridge_->RemoveDeviceCountListener(this);
646 adb_bridge_->AddDeviceCountListener(this);
647 } else {
648 Shutdown();
652 int readd_count_;
655 class MockCountListenerWithReAddWhileQueued : public MockCountListener {
656 public:
657 MockCountListenerWithReAddWhileQueued(
658 DevToolsAndroidBridge* adb_bridge)
659 : MockCountListener(adb_bridge),
660 readded_(false) {
663 void DeviceCountChanged(int count) override {
664 ++invoked_;
665 if (!readded_) {
666 readded_ = true;
667 base::ThreadTaskRunnerHandle::Get()->PostTask(
668 FROM_HERE, base::Bind(&MockCountListenerWithReAddWhileQueued::ReAdd,
669 base::Unretained(this)));
670 } else {
671 adb_bridge_->RemoveDeviceCountListener(this);
672 Shutdown();
676 void ReAdd() {
677 adb_bridge_->RemoveDeviceCountListener(this);
678 adb_bridge_->AddDeviceCountListener(this);
681 bool readded_;
684 class MockCountListenerForCheckingTraits : public MockCountListener {
685 public:
686 MockCountListenerForCheckingTraits(
687 DevToolsAndroidBridge* adb_bridge)
688 : MockCountListener(adb_bridge),
689 step_(0) {
691 void DeviceCountChanged(int count) override {
692 switch (step_) {
693 case 0:
694 // Check for 0 devices when no devices present.
695 EXPECT_EQ(0, count);
696 break;
697 case 1:
698 // Check for 1 device when only android device present.
699 EXPECT_EQ(1, count);
700 break;
701 case 2:
702 // Check for 1 device when android and non-android devices present.
703 EXPECT_EQ(1, count);
704 break;
705 case 3:
706 // Check for 0 devices when only non-android devices present.
707 EXPECT_EQ(0, count);
708 adb_bridge_->RemoveDeviceCountListener(this);
709 Shutdown();
710 break;
711 default:
712 EXPECT_TRUE(false) << "Unknown step " << step_;
714 step_++;
717 int step_;
720 } // namespace
722 IN_PROC_BROWSER_TEST_F(AndroidUsbDiscoveryTest, TestDeviceDiscovery) {
723 MockListListener listener(adb_bridge_, runner_->QuitClosure());
724 adb_bridge_->AddDeviceListListener(&listener);
725 runner_->Run();
728 IN_PROC_BROWSER_TEST_F(AndroidBreakingUsbTest, TestDeviceBreaking) {
729 MockListListener listener(adb_bridge_, runner_->QuitClosure());
730 adb_bridge_->AddDeviceListListener(&listener);
731 runner_->Run();
734 IN_PROC_BROWSER_TEST_F(AndroidNoConfigUsbTest, TestDeviceNoConfig) {
735 MockListListener listener(adb_bridge_, runner_->QuitClosure());
736 adb_bridge_->AddDeviceListListener(&listener);
737 runner_->Run();
740 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest,
741 TestNoMultipleCallsRemoveInCallback) {
742 MockCountListener listener(adb_bridge_);
743 adb_bridge_->AddDeviceCountListener(&listener);
744 runner_->Run();
745 EXPECT_EQ(1, listener.invoked_);
746 EXPECT_EQ(listener.invoked_ - 1, scheduler_invoked_);
747 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
750 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest,
751 TestNoMultipleCallsRemoveAddInCallback) {
752 MockCountListenerWithReAdd listener(adb_bridge_);
753 adb_bridge_->AddDeviceCountListener(&listener);
754 runner_->Run();
755 EXPECT_EQ(3, listener.invoked_);
756 EXPECT_EQ(listener.invoked_ - 1, scheduler_invoked_);
757 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
760 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest,
761 TestNoMultipleCallsRemoveAddOnStart) {
762 MockCountListener listener(adb_bridge_);
763 adb_bridge_->AddDeviceCountListener(&listener);
764 adb_bridge_->RemoveDeviceCountListener(&listener);
765 adb_bridge_->AddDeviceCountListener(&listener);
766 runner_->Run();
767 EXPECT_EQ(1, listener.invoked_);
768 EXPECT_EQ(listener.invoked_ - 1, scheduler_invoked_);
769 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
772 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest,
773 TestNoMultipleCallsRemoveAddWhileQueued) {
774 MockCountListenerWithReAddWhileQueued listener(adb_bridge_);
775 adb_bridge_->AddDeviceCountListener(&listener);
776 runner_->Run();
777 EXPECT_EQ(2, listener.invoked_);
778 EXPECT_EQ(listener.invoked_ - 1, scheduler_invoked_);
779 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
782 IN_PROC_BROWSER_TEST_F(AndroidUsbTraitsTest, TestDeviceCounting) {
783 MockCountListenerForCheckingTraits listener(adb_bridge_);
784 adb_bridge_->AddDeviceCountListener(&listener);
785 runner_->Run();