Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / devtools / device / usb / android_usb_browsertest.cc
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.
4
5 #include <algorithm>
6
7 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/browser/devtools/device/devtools_android_bridge.h"
9 #include "chrome/browser/devtools/device/usb/android_usb_device.h"
10 #include "chrome/browser/devtools/device/usb/usb_device_provider.h"
11 #include "chrome/browser/ui/browser.h"
12 #include "chrome/test/base/in_process_browser_test.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/test/test_utils.h"
15 #include "device/usb/usb_descriptors.h"
16 #include "device/usb/usb_device.h"
17 #include "device/usb/usb_device_handle.h"
18 #include "device/usb/usb_service.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 using content::BrowserThread;
22 using device::UsbConfigDescriptor;
23 using device::UsbDevice;
24 using device::UsbDeviceHandle;
25 using device::UsbEndpointDescriptor;
26 using device::UsbEndpointDirection;
27 using device::UsbInterfaceDescriptor;
28 using device::UsbService;
29 using device::UsbSynchronizationType;
30 using device::UsbTransferCallback;
31 using device::UsbTransferType;
32 using device::UsbUsageType;
33
34 namespace {
35
36 struct AndroidTraits {
37   static const int kClass = 0xff;
38   static const int kSubclass = 0x42;
39   static const int kProtocol = 0x1;
40 };
41
42 struct NonAndroidTraits {
43   static const int kClass = 0xf0;
44   static const int kSubclass = 0x42;
45   static const int kProtocol = 0x2;
46 };
47
48 const uint32 kMaxPayload = 4096;
49 const uint32 kVersion = 0x01000000;
50
51 const char kOpenedUnixSocketsCommand[] = "shell:cat /proc/net/unix";
52 const char kDeviceModelCommand[] = "shell:getprop ro.product.model";
53 const char kDumpsysCommand[] = "shell:dumpsys window policy";
54 const char kListProcessesCommand[] = "shell:ps";
55 const char kInstalledChromePackagesCommand[] = "shell:pm list packages";
56 const char kDeviceManufacturer[] = "Test Manufacturer";
57 const char kDeviceModel[] = "Nexus 5";
58 const char kDeviceSerial[] = "Sample serial";
59
60 const char kSampleOpenedUnixSockets[] =
61     "Num       RefCount Protocol Flags    Type St Inode Path\n"
62     "00000000: 00000004 00000000"
63     " 00000000 0002 01  3328 /dev/socket/wpa_wlan0\n"
64     "00000000: 00000002 00000000"
65     " 00010000 0001 01  5394 /dev/socket/vold\n";
66
67 const char kSampleListProcesses[] =
68     "USER   PID  PPID VSIZE  RSS    WCHAN    PC         NAME\n"
69     "root   1    0    688    508    ffffffff 00000000 S /init\r\n"
70     "u0_a75 2425 123  933736 193024 ffffffff 00000000 S com.sample.feed\r\n"
71     "nfc    741  123  706448 26316  ffffffff 00000000 S com.android.nfc\r\n"
72     "u0_a76 1001 124  111111 222222 ffffffff 00000000 S com.android.chrome\r\n"
73     "u0_a78 1003 126  111111 222222 ffffffff 00000000 S com.noprocess.app\r\n";
74
75 const char kSampleListPackages[] =
76     "package:com.sample.feed\r\n"
77     "package:com.android.nfc\r\n"
78     "package:com.android.chrome\r\n"
79     "package:com.chrome.beta\r\n"
80     "package:com.google.android.apps.chrome\r\n";
81
82 const char kSampleDumpsys[] =
83     "WINDOW MANAGER POLICY STATE (dumpsys window policy)\r\n"
84     "    mSafeMode=false mSystemReady=true mSystemBooted=true\r\n"
85     "    mStable=(0,50)-(720,1184)\r\n"  // Only mStable parameter is parsed
86     "    mForceStatusBar=false mForceStatusBarFromKeyguard=false\r\n";
87
88 const char* GetMockShellResponse(std::string command) {
89   if (command == kDeviceModelCommand) {
90     return kDeviceModel;
91   } else if (command == kOpenedUnixSocketsCommand) {
92     return kSampleOpenedUnixSockets;
93   } else if (command == kDumpsysCommand) {
94     return kSampleDumpsys;
95   } else if (command == kListProcessesCommand) {
96     return kSampleListProcesses;
97   } else if (command == kInstalledChromePackagesCommand) {
98     return kSampleListPackages;
99   }
100
101   DCHECK(false) << "Should not be reached";
102
103   return "";
104 }
105
106 template <class T>
107 class MockUsbDevice;
108
109 template <class T>
110 class MockUsbDeviceHandle : public UsbDeviceHandle {
111  public:
112   explicit MockUsbDeviceHandle(MockUsbDevice<T>* device)
113       : device_(device),
114         remaining_body_length_(0),
115         next_local_socket_(0) {}
116
117   virtual scoped_refptr<UsbDevice> GetDevice() const OVERRIDE {
118     return device_;
119   }
120
121   virtual void Close() OVERRIDE { device_ = NULL; }
122
123   bool ClaimInterface(int interface_number) {
124     if (device_->claimed_interfaces_.find(interface_number) !=
125         device_->claimed_interfaces_.end())
126       return false;
127
128     device_->claimed_interfaces_.insert(interface_number);
129     return true;
130   }
131
132   bool ReleaseInterface(int interface_number) {
133     if (device_->claimed_interfaces_.find(interface_number) ==
134         device_->claimed_interfaces_.end())
135       return false;
136
137     device_->claimed_interfaces_.erase(interface_number);
138     return true;
139   }
140
141   virtual bool SetInterfaceAlternateSetting(int interface_number,
142                                             int alternate_setting) OVERRIDE {
143     return true;
144   }
145
146   virtual bool ResetDevice() OVERRIDE { return true; }
147   virtual bool GetStringDescriptor(uint8_t string_id, base::string16* content) {
148     return false;
149   }
150
151   // Async IO. Can be called on any thread.
152   virtual void ControlTransfer(UsbEndpointDirection direction,
153                                TransferRequestType request_type,
154                                TransferRecipient recipient,
155                                uint8 request,
156                                uint16 value,
157                                uint16 index,
158                                net::IOBuffer* buffer,
159                                size_t length,
160                                unsigned int timeout,
161                                const UsbTransferCallback& callback) OVERRIDE {}
162
163   virtual void BulkTransfer(UsbEndpointDirection direction,
164                             uint8 endpoint,
165                             net::IOBuffer* buffer,
166                             size_t length,
167                             unsigned int timeout,
168                             const UsbTransferCallback& callback) OVERRIDE {
169     if (direction == device::USB_DIRECTION_OUTBOUND) {
170       if (remaining_body_length_ == 0) {
171         std::vector<uint32> header(6);
172         memcpy(&header[0], buffer->data(), length);
173         current_message_ = new AdbMessage(header[0], header[1], header[2], "");
174         remaining_body_length_ = header[3];
175         uint32 magic = header[5];
176         if ((current_message_->command ^ 0xffffffff) != magic) {
177           DCHECK(false) << "Header checksum error";
178           return;
179         }
180       } else {
181         DCHECK(current_message_.get());
182         current_message_->body += std::string(buffer->data(), length);
183         remaining_body_length_ -= length;
184       }
185
186       if (remaining_body_length_ == 0) {
187         ProcessIncoming();
188       }
189
190       base::MessageLoop::current()->PostTask(
191           FROM_HERE,
192           base::Bind(callback,
193                      device::USB_TRANSFER_COMPLETED,
194                      scoped_refptr<net::IOBuffer>(),
195                      0));
196
197     } else if (direction == device::USB_DIRECTION_INBOUND) {
198       queries_.push(Query(callback, make_scoped_refptr(buffer), length));
199       ProcessQueries();
200     }
201   }
202
203   template <class D>
204   void append(D data) {
205     std::copy(reinterpret_cast<char*>(&data),
206               (reinterpret_cast<char*>(&data)) + sizeof(D),
207               std::back_inserter(output_buffer_));
208   }
209
210   // Copied from AndroidUsbDevice::Checksum
211   uint32 Checksum(const std::string& data) {
212     unsigned char* x = (unsigned char*)data.data();
213     int count = data.length();
214     uint32 sum = 0;
215     while (count-- > 0)
216       sum += *x++;
217     return sum;
218   }
219
220   void ProcessIncoming() {
221     DCHECK(current_message_.get());
222     switch (current_message_->command) {
223       case AdbMessage::kCommandCNXN:
224         WriteResponse(new AdbMessage(AdbMessage::kCommandCNXN,
225                                      kVersion,
226                                      kMaxPayload,
227                                      "device::ro.product.name=SampleProduct;ro."
228                                      "product.model=SampleModel;ro.product."
229                                      "device=SampleDevice;"));
230         break;
231       case AdbMessage::kCommandOPEN:
232         DCHECK(current_message_->arg1 == 0);
233         DCHECK(current_message_->arg0 != 0);
234         if (current_message_->body.find("shell:") != std::string::npos) {
235           WriteResponse(new AdbMessage(AdbMessage::kCommandOKAY,
236                                        ++next_local_socket_,
237                                        current_message_->arg0,
238                                        ""));
239           WriteResponse(
240               new AdbMessage(AdbMessage::kCommandWRTE,
241                              next_local_socket_,
242                              current_message_->arg0,
243                              GetMockShellResponse(current_message_->body.substr(
244                                  0, current_message_->body.size() - 1))));
245           WriteResponse(new AdbMessage(
246               AdbMessage::kCommandCLSE, 0, current_message_->arg0, ""));
247         }
248       default:
249         return;
250     }
251     ProcessQueries();
252   }
253
254   void WriteResponse(scoped_refptr<AdbMessage> response) {
255     append(response->command);
256     append(response->arg0);
257     append(response->arg1);
258     bool add_zero = response->body.length() &&
259                     (response->command != AdbMessage::kCommandWRTE);
260     append(static_cast<uint32>(response->body.length() + (add_zero ? 1 : 0)));
261     append(Checksum(response->body));
262     append(response->command ^ 0xffffffff);
263     std::copy(response->body.begin(),
264               response->body.end(),
265               std::back_inserter(output_buffer_));
266     if (add_zero) {
267       output_buffer_.push_back(0);
268     }
269     ProcessQueries();
270   }
271
272   void ProcessQueries() {
273     if (!queries_.size())
274       return;
275     Query query = queries_.front();
276
277     if (query.size > output_buffer_.size())
278       return;
279
280     queries_.pop();
281     std::copy(output_buffer_.begin(),
282               output_buffer_.begin() + query.size,
283               query.buffer->data());
284     output_buffer_.erase(output_buffer_.begin(),
285                          output_buffer_.begin() + query.size);
286     base::MessageLoop::current()->PostTask(
287         FROM_HERE,
288         base::Bind(query.callback,
289                    device::USB_TRANSFER_COMPLETED,
290                    query.buffer,
291                    query.size));
292   }
293
294   virtual void InterruptTransfer(UsbEndpointDirection direction,
295                                  uint8 endpoint,
296                                  net::IOBuffer* buffer,
297                                  size_t length,
298                                  unsigned int timeout,
299                                  const UsbTransferCallback& callback) OVERRIDE {
300   }
301
302   virtual void IsochronousTransfer(
303       UsbEndpointDirection direction,
304       uint8 endpoint,
305       net::IOBuffer* buffer,
306       size_t length,
307       unsigned int packets,
308       unsigned int packet_length,
309       unsigned int timeout,
310       const UsbTransferCallback& callback) OVERRIDE {}
311
312  protected:
313   virtual ~MockUsbDeviceHandle() {}
314
315   struct Query {
316     UsbTransferCallback callback;
317     scoped_refptr<net::IOBuffer> buffer;
318     size_t size;
319
320     Query(UsbTransferCallback callback,
321           scoped_refptr<net::IOBuffer> buffer,
322           int size)
323         : callback(callback), buffer(buffer), size(size) {};
324   };
325
326   scoped_refptr<MockUsbDevice<T> > device_;
327   uint32 remaining_body_length_;
328   scoped_refptr<AdbMessage> current_message_;
329   std::vector<char> output_buffer_;
330   std::queue<Query> queries_;
331   int next_local_socket_;
332 };
333
334 template <class T>
335 class MockUsbDevice : public UsbDevice {
336  public:
337   MockUsbDevice() : UsbDevice(0, 0, 0) {
338     UsbEndpointDescriptor bulk_in;
339     bulk_in.address = 0x81;
340     bulk_in.direction = device::USB_DIRECTION_INBOUND;
341     bulk_in.maximum_packet_size = 512;
342     bulk_in.transfer_type = device::USB_TRANSFER_BULK;
343
344     UsbEndpointDescriptor bulk_out;
345     bulk_out.address = 0x01;
346     bulk_out.direction = device::USB_DIRECTION_OUTBOUND;
347     bulk_out.maximum_packet_size = 512;
348     bulk_out.transfer_type = device::USB_TRANSFER_BULK;
349
350     UsbInterfaceDescriptor interface_desc;
351     interface_desc.interface_number = 0;
352     interface_desc.alternate_setting = 0;
353     interface_desc.interface_class = T::kClass;
354     interface_desc.interface_subclass = T::kSubclass;
355     interface_desc.interface_protocol = T::kProtocol;
356     interface_desc.endpoints.push_back(bulk_in);
357     interface_desc.endpoints.push_back(bulk_out);
358
359     config_desc_.interfaces.push_back(interface_desc);
360   }
361
362   virtual scoped_refptr<UsbDeviceHandle> Open() OVERRIDE {
363     return new MockUsbDeviceHandle<T>(this);
364   }
365
366   virtual const UsbConfigDescriptor& GetConfiguration() OVERRIDE {
367     return config_desc_;
368   }
369
370   virtual bool GetManufacturer(base::string16* manufacturer) OVERRIDE {
371     *manufacturer = base::UTF8ToUTF16(kDeviceManufacturer);
372     return true;
373   }
374
375   virtual bool GetProduct(base::string16* product) OVERRIDE {
376     *product = base::UTF8ToUTF16(kDeviceModel);
377     return true;
378   }
379
380   virtual bool GetSerialNumber(base::string16* serial) OVERRIDE {
381     *serial = base::UTF8ToUTF16(kDeviceSerial);
382     return true;
383   }
384
385   virtual bool Close(scoped_refptr<UsbDeviceHandle> handle) OVERRIDE {
386     return true;
387   }
388
389 #if defined(OS_CHROMEOS)
390   // On ChromeOS, if an interface of a claimed device is not claimed, the
391   // permission broker can change the owner of the device so that the unclaimed
392   // interfaces can be used. If this argument is missing, permission broker will
393   // not be used and this method fails if the device is claimed.
394   virtual void RequestUsbAccess(
395       int interface_id,
396       const base::Callback<void(bool success)>& callback) OVERRIDE {
397     callback.Run(true);
398   }
399 #endif  // OS_CHROMEOS
400
401   std::set<int> claimed_interfaces_;
402
403  protected:
404   virtual ~MockUsbDevice() {}
405
406  private:
407   UsbConfigDescriptor config_desc_;
408 };
409
410 class MockUsbService : public UsbService {
411  public:
412   MockUsbService() {
413     devices_.push_back(new MockUsbDevice<AndroidTraits>());
414   }
415
416   virtual ~MockUsbService() {}
417
418   virtual scoped_refptr<UsbDevice> GetDeviceById(uint32 unique_id) OVERRIDE {
419     NOTIMPLEMENTED();
420     return NULL;
421   }
422
423   virtual void GetDevices(
424       std::vector<scoped_refptr<UsbDevice> >* devices) OVERRIDE {
425     STLClearObject(devices);
426     std::copy(devices_.begin(), devices_.end(), back_inserter(*devices));
427   }
428
429   std::vector<scoped_refptr<UsbDevice> > devices_;
430 };
431
432 class MockUsbServiceForCheckingTraits : public UsbService {
433  public:
434   MockUsbServiceForCheckingTraits() : step_(0) {}
435
436   virtual ~MockUsbServiceForCheckingTraits() {}
437
438   virtual scoped_refptr<UsbDevice> GetDeviceById(uint32 unique_id) OVERRIDE {
439     NOTIMPLEMENTED();
440     return NULL;
441   }
442
443   virtual void GetDevices(
444       std::vector<scoped_refptr<UsbDevice> >* devices) OVERRIDE {
445     STLClearObject(devices);
446     // This switch should be kept in sync with
447     // AndroidUsbBrowserTest::DeviceCountChanged.
448     switch (step_) {
449       case 0:
450         // No devices.
451         break;
452       case 1:
453         // Android device.
454         devices->push_back(new MockUsbDevice<AndroidTraits>());
455         break;
456       case 2:
457         // Android and non-android device.
458         devices->push_back(new MockUsbDevice<AndroidTraits>());
459         devices->push_back(new MockUsbDevice<NonAndroidTraits>());
460         break;
461       case 3:
462         // Non-android device.
463         devices->push_back(new MockUsbDevice<NonAndroidTraits>());
464         break;
465     }
466     step_++;
467   }
468
469  private:
470   int step_;
471 };
472
473 class DevToolsAndroidBridgeWarmUp
474     : public DevToolsAndroidBridge::DeviceCountListener {
475  public:
476   DevToolsAndroidBridgeWarmUp(base::Closure closure,
477                               scoped_refptr<DevToolsAndroidBridge> adb_bridge)
478       : closure_(closure), adb_bridge_(adb_bridge) {}
479
480   virtual void DeviceCountChanged(int count) OVERRIDE {
481     adb_bridge_->RemoveDeviceCountListener(this);
482     closure_.Run();
483   }
484
485   base::Closure closure_;
486   scoped_refptr<DevToolsAndroidBridge> adb_bridge_;
487 };
488
489 class AndroidUsbDiscoveryTest : public InProcessBrowserTest {
490  protected:
491   AndroidUsbDiscoveryTest()
492       : scheduler_invoked_(0) {
493   }
494   virtual void SetUpOnMainThread() OVERRIDE {
495     scoped_refptr<content::MessageLoopRunner> runner =
496         new content::MessageLoopRunner;
497
498     BrowserThread::PostTaskAndReply(
499         BrowserThread::FILE,
500         FROM_HERE,
501         base::Bind(&AndroidUsbDiscoveryTest::SetUpService, this),
502         runner->QuitClosure());
503     runner->Run();
504
505     adb_bridge_ =
506         DevToolsAndroidBridge::Factory::GetForProfile(browser()->profile());
507     DCHECK(adb_bridge_.get());
508     adb_bridge_->set_task_scheduler_for_test(base::Bind(
509         &AndroidUsbDiscoveryTest::ScheduleDeviceCountRequest, this));
510
511     scoped_refptr<UsbDeviceProvider> provider =
512         new UsbDeviceProvider(browser()->profile());
513
514     AndroidDeviceManager::DeviceProviders providers;
515     providers.push_back(provider);
516     adb_bridge_->set_device_providers_for_test(providers);
517     runner_ = new content::MessageLoopRunner;
518   }
519
520   void ScheduleDeviceCountRequest(const base::Closure& request) {
521     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
522     scheduler_invoked_++;
523     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, request);
524   }
525
526   virtual void SetUpService() {
527     UsbService::SetInstanceForTest(new MockUsbService());
528   }
529
530   virtual void TearDownOnMainThread() OVERRIDE {
531     scoped_refptr<content::MessageLoopRunner> runner =
532         new content::MessageLoopRunner;
533     UsbService* service = NULL;
534     BrowserThread::PostTaskAndReply(
535         BrowserThread::FILE,
536         FROM_HERE,
537         base::Bind(&UsbService::SetInstanceForTest, service),
538         runner->QuitClosure());
539     runner->Run();
540   }
541
542   scoped_refptr<content::MessageLoopRunner> runner_;
543   scoped_refptr<DevToolsAndroidBridge> adb_bridge_;
544   int scheduler_invoked_;
545 };
546
547 class AndroidUsbCountTest : public AndroidUsbDiscoveryTest {
548  protected:
549   virtual void SetUpOnMainThread() OVERRIDE {
550     AndroidUsbDiscoveryTest::SetUpOnMainThread();
551     DevToolsAndroidBridgeWarmUp warmup(runner_->QuitClosure(), adb_bridge_);
552     adb_bridge_->AddDeviceCountListener(&warmup);
553     runner_->Run();
554     runner_ = new content::MessageLoopRunner;
555   }
556 };
557
558 class AndroidUsbTraitsTest : public AndroidUsbDiscoveryTest {
559  protected:
560   virtual void SetUpService() OVERRIDE {
561     UsbService::SetInstanceForTest(new MockUsbServiceForCheckingTraits());
562   }
563 };
564
565 class MockListListener : public DevToolsAndroidBridge::DeviceListListener {
566  public:
567   MockListListener(scoped_refptr<DevToolsAndroidBridge> adb_bridge,
568                    const base::Closure& callback)
569       : adb_bridge_(adb_bridge),
570         callback_(callback) {
571   }
572
573   virtual void DeviceListChanged(
574       const DevToolsAndroidBridge::RemoteDevices& devices) OVERRIDE {
575     if (devices.size() > 0) {
576       if (devices[0]->is_connected()) {
577         ASSERT_EQ(kDeviceModel, devices[0]->model());
578         ASSERT_EQ(kDeviceSerial, devices[0]->serial());
579         adb_bridge_->RemoveDeviceListListener(this);
580         callback_.Run();
581       }
582     }
583   }
584
585   scoped_refptr<DevToolsAndroidBridge> adb_bridge_;
586   base::Closure callback_;
587 };
588
589 class MockCountListener : public DevToolsAndroidBridge::DeviceCountListener {
590  public:
591   explicit MockCountListener(scoped_refptr<DevToolsAndroidBridge> adb_bridge)
592       : adb_bridge_(adb_bridge),
593         reposts_left_(10),
594         invoked_(0) {
595   }
596
597   virtual void DeviceCountChanged(int count) OVERRIDE {
598     ++invoked_;
599     adb_bridge_->RemoveDeviceCountListener(this);
600     Shutdown();
601   }
602
603   void Shutdown() {
604     ShutdownOnUIThread();
605   };
606
607   void ShutdownOnUIThread() {
608     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
609     if (reposts_left_-- == 0) {
610       base::MessageLoop::current()->Quit();
611     } else {
612       BrowserThread::PostTask(
613           BrowserThread::FILE,
614           FROM_HERE,
615           base::Bind(&MockCountListener::ShutdownOnFileThread,
616                      base::Unretained(this)));
617     }
618   }
619
620   void ShutdownOnFileThread() {
621     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
622     BrowserThread::PostTask(BrowserThread::UI,
623                             FROM_HERE,
624                             base::Bind(&MockCountListener::ShutdownOnUIThread,
625                                        base::Unretained(this)));
626   }
627
628   scoped_refptr<DevToolsAndroidBridge> adb_bridge_;
629   int reposts_left_;
630   int invoked_;
631 };
632
633 class MockCountListenerWithReAdd : public MockCountListener {
634  public:
635   explicit MockCountListenerWithReAdd(
636       scoped_refptr<DevToolsAndroidBridge> adb_bridge)
637       : MockCountListener(adb_bridge),
638         readd_count_(2) {
639   }
640
641   virtual void DeviceCountChanged(int count) OVERRIDE {
642     ++invoked_;
643     adb_bridge_->RemoveDeviceCountListener(this);
644     if (readd_count_ > 0) {
645       readd_count_--;
646       adb_bridge_->AddDeviceCountListener(this);
647       adb_bridge_->RemoveDeviceCountListener(this);
648       adb_bridge_->AddDeviceCountListener(this);
649     } else {
650       Shutdown();
651     }
652   }
653
654   int readd_count_;
655 };
656
657 class MockCountListenerWithReAddWhileQueued : public MockCountListener {
658  public:
659   MockCountListenerWithReAddWhileQueued(
660       scoped_refptr<DevToolsAndroidBridge> adb_bridge)
661       : MockCountListener(adb_bridge),
662         readded_(false) {
663   }
664
665   virtual void DeviceCountChanged(int count) OVERRIDE {
666     ++invoked_;
667     if (!readded_) {
668       readded_ = true;
669       base::MessageLoop::current()->PostTask(
670           FROM_HERE,
671           base::Bind(&MockCountListenerWithReAddWhileQueued::ReAdd,
672                      base::Unretained(this)));
673     } else {
674       adb_bridge_->RemoveDeviceCountListener(this);
675       Shutdown();
676     }
677   }
678
679   void ReAdd() {
680     adb_bridge_->RemoveDeviceCountListener(this);
681     adb_bridge_->AddDeviceCountListener(this);
682   }
683
684   bool readded_;
685 };
686
687 class MockCountListenerForCheckingTraits : public MockCountListener {
688  public:
689   MockCountListenerForCheckingTraits(
690       scoped_refptr<DevToolsAndroidBridge> adb_bridge)
691       : MockCountListener(adb_bridge),
692         step_(0) {
693   }
694   virtual void DeviceCountChanged(int count) OVERRIDE {
695     switch (step_) {
696       case 0:
697         // Check for 0 devices when no devices present.
698         EXPECT_EQ(0, count);
699         break;
700       case 1:
701         // Check for 1 device when only android device present.
702         EXPECT_EQ(1, count);
703         break;
704       case 2:
705         // Check for 1 device when android and non-android devices present.
706         EXPECT_EQ(1, count);
707         break;
708       case 3:
709         // Check for 0 devices when only non-android devices present.
710         EXPECT_EQ(0, count);
711         adb_bridge_->RemoveDeviceCountListener(this);
712         Shutdown();
713         break;
714       default:
715         EXPECT_TRUE(false) << "Unknown step " << step_;
716     }
717     step_++;
718   }
719
720   int step_;
721 };
722
723 }  // namespace
724
725 IN_PROC_BROWSER_TEST_F(AndroidUsbDiscoveryTest, TestDeviceDiscovery) {
726   MockListListener listener(adb_bridge_, runner_->QuitClosure());
727   adb_bridge_->AddDeviceListListener(&listener);
728   runner_->Run();
729 }
730
731 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest,
732                        TestNoMultipleCallsRemoveInCallback) {
733   MockCountListener listener(adb_bridge_);
734   adb_bridge_->AddDeviceCountListener(&listener);
735   runner_->Run();
736   EXPECT_EQ(1, listener.invoked_);
737   EXPECT_EQ(listener.invoked_ - 1, scheduler_invoked_);
738 }
739
740 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest,
741                        TestNoMultipleCallsRemoveAddInCallback) {
742   MockCountListenerWithReAdd listener(adb_bridge_);
743   adb_bridge_->AddDeviceCountListener(&listener);
744   runner_->Run();
745   EXPECT_EQ(3, listener.invoked_);
746   EXPECT_EQ(listener.invoked_ - 1, scheduler_invoked_);
747 }
748
749 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest,
750                        TestNoMultipleCallsRemoveAddOnStart) {
751   MockCountListener listener(adb_bridge_);
752   adb_bridge_->AddDeviceCountListener(&listener);
753   adb_bridge_->RemoveDeviceCountListener(&listener);
754   adb_bridge_->AddDeviceCountListener(&listener);
755   runner_->Run();
756   EXPECT_EQ(1, listener.invoked_);
757   EXPECT_EQ(listener.invoked_ - 1, scheduler_invoked_);
758 }
759
760 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest,
761                        TestNoMultipleCallsRemoveAddWhileQueued) {
762   MockCountListenerWithReAddWhileQueued listener(adb_bridge_);
763   adb_bridge_->AddDeviceCountListener(&listener);
764   runner_->Run();
765   EXPECT_EQ(2, listener.invoked_);
766   EXPECT_EQ(listener.invoked_ - 1, scheduler_invoked_);
767 }
768
769 IN_PROC_BROWSER_TEST_F(AndroidUsbTraitsTest, TestDeviceCounting) {
770   MockCountListenerForCheckingTraits listener(adb_bridge_);
771   adb_bridge_->AddDeviceCountListener(&listener);
772   runner_->Run();
773 }