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