Home | History | Annotate | Download | only in bluetooth_low_energy
      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 "base/memory/scoped_ptr.h"
      6 #include "chrome/browser/extensions/extension_apitest.h"
      7 #include "device/bluetooth/test/mock_bluetooth_adapter.h"
      8 #include "device/bluetooth/test/mock_bluetooth_device.h"
      9 #include "device/bluetooth/test/mock_bluetooth_gatt_characteristic.h"
     10 #include "device/bluetooth/test/mock_bluetooth_gatt_connection.h"
     11 #include "device/bluetooth/test/mock_bluetooth_gatt_descriptor.h"
     12 #include "device/bluetooth/test/mock_bluetooth_gatt_notify_session.h"
     13 #include "device/bluetooth/test/mock_bluetooth_gatt_service.h"
     14 #include "extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_api.h"
     15 #include "extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.h"
     16 #include "extensions/common/test_util.h"
     17 #include "extensions/test/extension_test_message_listener.h"
     18 #include "extensions/test/result_catcher.h"
     19 #include "testing/gmock/include/gmock/gmock.h"
     20 
     21 using device::BluetoothUUID;
     22 using device::BluetoothAdapter;
     23 using device::BluetoothDevice;
     24 using device::BluetoothGattCharacteristic;
     25 using device::BluetoothGattConnection;
     26 using device::BluetoothGattDescriptor;
     27 using device::BluetoothGattService;
     28 using device::BluetoothGattNotifySession;
     29 using device::MockBluetoothAdapter;
     30 using device::MockBluetoothDevice;
     31 using device::MockBluetoothGattCharacteristic;
     32 using device::MockBluetoothGattConnection;
     33 using device::MockBluetoothGattDescriptor;
     34 using device::MockBluetoothGattService;
     35 using device::MockBluetoothGattNotifySession;
     36 using extensions::BluetoothLowEnergyEventRouter;
     37 using extensions::ResultCatcher;
     38 using testing::Invoke;
     39 using testing::Return;
     40 using testing::ReturnRef;
     41 using testing::ReturnRefOfCopy;
     42 using testing::SaveArg;
     43 using testing::_;
     44 
     45 namespace {
     46 
     47 // Test service constants.
     48 const char kTestLeDeviceAddress0[] = "11:22:33:44:55:66";
     49 const char kTestLeDeviceName0[] = "Test LE Device 0";
     50 
     51 const char kTestLeDeviceAddress1[] = "77:88:99:AA:BB:CC";
     52 const char kTestLeDeviceName1[] = "Test LE Device 1";
     53 
     54 const char kTestServiceId0[] = "service_id0";
     55 const char kTestServiceUuid0[] = "1234";
     56 
     57 const char kTestServiceId1[] = "service_id1";
     58 const char kTestServiceUuid1[] = "5678";
     59 
     60 // Test characteristic constants.
     61 const char kTestCharacteristicId0[] = "char_id0";
     62 const char kTestCharacteristicUuid0[] = "1211";
     63 const BluetoothGattCharacteristic::Properties kTestCharacteristicProperties0 =
     64     BluetoothGattCharacteristic::kPropertyBroadcast |
     65     BluetoothGattCharacteristic::kPropertyRead |
     66     BluetoothGattCharacteristic::kPropertyWriteWithoutResponse |
     67     BluetoothGattCharacteristic::kPropertyIndicate;
     68 const uint8 kTestCharacteristicDefaultValue0[] = {0x01, 0x02, 0x03, 0x04, 0x05};
     69 
     70 const char kTestCharacteristicId1[] = "char_id1";
     71 const char kTestCharacteristicUuid1[] = "1212";
     72 const BluetoothGattCharacteristic::Properties kTestCharacteristicProperties1 =
     73     BluetoothGattCharacteristic::kPropertyRead |
     74     BluetoothGattCharacteristic::kPropertyWrite |
     75     BluetoothGattCharacteristic::kPropertyNotify;
     76 const uint8 kTestCharacteristicDefaultValue1[] = {0x06, 0x07, 0x08};
     77 
     78 const char kTestCharacteristicId2[] = "char_id2";
     79 const char kTestCharacteristicUuid2[] = "1213";
     80 const BluetoothGattCharacteristic::Properties kTestCharacteristicProperties2 =
     81     BluetoothGattCharacteristic::kPropertyNone;
     82 
     83 // Test descriptor constants.
     84 const char kTestDescriptorId0[] = "desc_id0";
     85 const char kTestDescriptorUuid0[] = "1221";
     86 const uint8 kTestDescriptorDefaultValue0[] = {0x01, 0x02, 0x03};
     87 
     88 const char kTestDescriptorId1[] = "desc_id1";
     89 const char kTestDescriptorUuid1[] = "1222";
     90 const uint8 kTestDescriptorDefaultValue1[] = {0x04, 0x05};
     91 
     92 class BluetoothLowEnergyApiTest : public ExtensionApiTest {
     93  public:
     94   BluetoothLowEnergyApiTest() {}
     95 
     96   virtual ~BluetoothLowEnergyApiTest() {}
     97 
     98   virtual void SetUpOnMainThread() OVERRIDE {
     99     ExtensionApiTest::SetUpOnMainThread();
    100     empty_extension_ = extensions::test_util::CreateEmptyExtension();
    101     SetUpMocks();
    102   }
    103 
    104   virtual void TearDownOnMainThread() OVERRIDE {
    105     EXPECT_CALL(*mock_adapter_, RemoveObserver(_));
    106   }
    107 
    108   void SetUpMocks() {
    109     mock_adapter_ = new testing::StrictMock<MockBluetoothAdapter>();
    110     EXPECT_CALL(*mock_adapter_, GetDevices())
    111         .WillOnce(Return(BluetoothAdapter::ConstDeviceList()));
    112 
    113     event_router()->SetAdapterForTesting(mock_adapter_);
    114 
    115     device0_.reset(
    116         new testing::NiceMock<MockBluetoothDevice>(mock_adapter_,
    117                                                    0,
    118                                                    kTestLeDeviceName0,
    119                                                    kTestLeDeviceAddress0,
    120                                                    false /* paired */,
    121                                                    true /* connected */));
    122 
    123     device1_.reset(
    124         new testing::NiceMock<MockBluetoothDevice>(mock_adapter_,
    125                                                    0,
    126                                                    kTestLeDeviceName1,
    127                                                    kTestLeDeviceAddress1,
    128                                                    false /* paired */,
    129                                                    false /* connected */));
    130 
    131     service0_.reset(new testing::NiceMock<MockBluetoothGattService>(
    132         device0_.get(),
    133         kTestServiceId0,
    134         BluetoothUUID(kTestServiceUuid0),
    135         true /* is_primary */,
    136         false /* is_local */));
    137 
    138     service1_.reset(new testing::NiceMock<MockBluetoothGattService>(
    139         device0_.get(),
    140         kTestServiceId1,
    141         BluetoothUUID(kTestServiceUuid1),
    142         false /* is_primary */,
    143         false /* is_local */));
    144 
    145     // Assign characteristics some random properties and permissions. They don't
    146     // need to reflect what the characteristic is actually capable of, since
    147     // the JS API just passes values through from
    148     // device::BluetoothGattCharacteristic.
    149     std::vector<uint8> default_value;
    150     chrc0_.reset(new testing::NiceMock<MockBluetoothGattCharacteristic>(
    151         service0_.get(),
    152         kTestCharacteristicId0,
    153         BluetoothUUID(kTestCharacteristicUuid0),
    154         false /* is_local */,
    155         kTestCharacteristicProperties0,
    156         BluetoothGattCharacteristic::kPermissionNone));
    157     default_value.assign(kTestCharacteristicDefaultValue0,
    158                          (kTestCharacteristicDefaultValue0 +
    159                           sizeof(kTestCharacteristicDefaultValue0)));
    160     ON_CALL(*chrc0_, GetValue()).WillByDefault(ReturnRefOfCopy(default_value));
    161 
    162     chrc1_.reset(new testing::NiceMock<MockBluetoothGattCharacteristic>(
    163         service0_.get(),
    164         kTestCharacteristicId1,
    165         BluetoothUUID(kTestCharacteristicUuid1),
    166         false /* is_local */,
    167         kTestCharacteristicProperties1,
    168         BluetoothGattCharacteristic::kPermissionNone));
    169     default_value.assign(kTestCharacteristicDefaultValue1,
    170                          (kTestCharacteristicDefaultValue1 +
    171                           sizeof(kTestCharacteristicDefaultValue1)));
    172     ON_CALL(*chrc1_, GetValue()).WillByDefault(ReturnRefOfCopy(default_value));
    173 
    174     chrc2_.reset(new testing::NiceMock<MockBluetoothGattCharacteristic>(
    175         service1_.get(),
    176         kTestCharacteristicId2,
    177         BluetoothUUID(kTestCharacteristicUuid2),
    178         false /* is_local */,
    179         kTestCharacteristicProperties2,
    180         BluetoothGattCharacteristic::kPermissionNone));
    181 
    182     desc0_.reset(new testing::NiceMock<MockBluetoothGattDescriptor>(
    183         chrc0_.get(),
    184         kTestDescriptorId0,
    185         BluetoothUUID(kTestDescriptorUuid0),
    186         false /* is_local */,
    187         BluetoothGattCharacteristic::kPermissionNone));
    188     default_value.assign(
    189         kTestDescriptorDefaultValue0,
    190         (kTestDescriptorDefaultValue0 + sizeof(kTestDescriptorDefaultValue0)));
    191     ON_CALL(*desc0_, GetValue()).WillByDefault(ReturnRefOfCopy(default_value));
    192 
    193     desc1_.reset(new testing::NiceMock<MockBluetoothGattDescriptor>(
    194         chrc0_.get(),
    195         kTestDescriptorId1,
    196         BluetoothUUID(kTestDescriptorUuid1),
    197         false /* is_local */,
    198         BluetoothGattCharacteristic::kPermissionNone));
    199     default_value.assign(
    200         kTestDescriptorDefaultValue1,
    201         (kTestDescriptorDefaultValue1 + sizeof(kTestDescriptorDefaultValue1)));
    202     ON_CALL(*desc1_, GetValue()).WillByDefault(ReturnRefOfCopy(default_value));
    203   }
    204 
    205  protected:
    206   BluetoothLowEnergyEventRouter* event_router() {
    207     return extensions::BluetoothLowEnergyAPI::Get(browser()->profile())
    208         ->event_router();
    209   }
    210 
    211   testing::StrictMock<MockBluetoothAdapter>* mock_adapter_;
    212   scoped_ptr<testing::NiceMock<MockBluetoothDevice> > device0_;
    213   scoped_ptr<testing::NiceMock<MockBluetoothDevice> > device1_;
    214   scoped_ptr<testing::NiceMock<MockBluetoothGattService> > service0_;
    215   scoped_ptr<testing::NiceMock<MockBluetoothGattService> > service1_;
    216   scoped_ptr<testing::NiceMock<MockBluetoothGattCharacteristic> > chrc0_;
    217   scoped_ptr<testing::NiceMock<MockBluetoothGattCharacteristic> > chrc1_;
    218   scoped_ptr<testing::NiceMock<MockBluetoothGattCharacteristic> > chrc2_;
    219   scoped_ptr<testing::NiceMock<MockBluetoothGattDescriptor> > desc0_;
    220   scoped_ptr<testing::NiceMock<MockBluetoothGattDescriptor> > desc1_;
    221 
    222  private:
    223   scoped_refptr<extensions::Extension> empty_extension_;
    224 };
    225 
    226 ACTION_TEMPLATE(InvokeCallbackArgument,
    227                 HAS_1_TEMPLATE_PARAMS(int, k),
    228                 AND_0_VALUE_PARAMS()) {
    229   ::std::tr1::get<k>(args).Run();
    230 }
    231 
    232 ACTION_TEMPLATE(InvokeCallbackArgument,
    233                 HAS_1_TEMPLATE_PARAMS(int, k),
    234                 AND_1_VALUE_PARAMS(p0)) {
    235   ::std::tr1::get<k>(args).Run(p0);
    236 }
    237 
    238 ACTION_TEMPLATE(InvokeCallbackWithScopedPtrArg,
    239                 HAS_2_TEMPLATE_PARAMS(int, k, typename, T),
    240                 AND_1_VALUE_PARAMS(p0)) {
    241   ::std::tr1::get<k>(args).Run(scoped_ptr<T>(p0));
    242 }
    243 
    244 BluetoothGattConnection* CreateGattConnection(
    245     const std::string& device_address,
    246     bool expect_disconnect) {
    247   testing::NiceMock<MockBluetoothGattConnection>* conn =
    248       new testing::NiceMock<MockBluetoothGattConnection>(device_address);
    249 
    250   if (expect_disconnect) {
    251     EXPECT_CALL(*conn, Disconnect(_))
    252         .Times(1)
    253         .WillOnce(InvokeCallbackArgument<0>());
    254   } else {
    255     EXPECT_CALL(*conn, Disconnect(_)).Times(0);
    256   }
    257 
    258   return conn;
    259 }
    260 
    261 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetServices) {
    262   ResultCatcher catcher;
    263   catcher.RestrictToBrowserContext(browser()->profile());
    264 
    265   std::vector<BluetoothGattService*> services;
    266   services.push_back(service0_.get());
    267   services.push_back(service1_.get());
    268 
    269   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    270       .Times(3)
    271       .WillOnce(Return(static_cast<BluetoothDevice*>(NULL)))
    272       .WillRepeatedly(Return(device0_.get()));
    273 
    274   EXPECT_CALL(*device0_, GetGattServices())
    275       .Times(2)
    276       .WillOnce(Return(std::vector<BluetoothGattService*>()))
    277       .WillOnce(Return(services));
    278 
    279   // Load and wait for setup.
    280   ExtensionTestMessageListener listener("ready", true);
    281   ASSERT_TRUE(LoadExtension(
    282       test_data_dir_.AppendASCII("bluetooth_low_energy/get_services")));
    283   EXPECT_TRUE(listener.WaitUntilSatisfied());
    284 
    285   listener.Reply("go");
    286 
    287   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    288 }
    289 
    290 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetService) {
    291   ResultCatcher catcher;
    292   catcher.RestrictToBrowserContext(browser()->profile());
    293 
    294   event_router()->GattServiceAdded(
    295       mock_adapter_, device0_.get(), service0_.get());
    296 
    297   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    298       .Times(3)
    299       .WillOnce(Return(static_cast<BluetoothDevice*>(NULL)))
    300       .WillRepeatedly(Return(device0_.get()));
    301 
    302   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    303       .Times(2)
    304       .WillOnce(Return(static_cast<BluetoothGattService*>(NULL)))
    305       .WillOnce(Return(service0_.get()));
    306 
    307   // Load and wait for setup.
    308   ExtensionTestMessageListener listener("ready", true);
    309   ASSERT_TRUE(LoadExtension(
    310       test_data_dir_.AppendASCII("bluetooth_low_energy/get_service")));
    311   EXPECT_TRUE(listener.WaitUntilSatisfied());
    312 
    313   listener.Reply("go");
    314 
    315   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    316 
    317   event_router()->GattServiceRemoved(
    318       mock_adapter_, device0_.get(), service0_.get());
    319 }
    320 
    321 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, ServiceEvents) {
    322   ResultCatcher catcher;
    323   catcher.RestrictToBrowserContext(browser()->profile());
    324 
    325   // Load the extension and let it set up.
    326   ExtensionTestMessageListener listener("ready", true);
    327   ASSERT_TRUE(LoadExtension(
    328       test_data_dir_.AppendASCII("bluetooth_low_energy/service_events")));
    329 
    330   // These will create the identifier mappings.
    331   event_router()->GattServiceAdded(
    332       mock_adapter_, device0_.get(), service0_.get());
    333   event_router()->GattServiceAdded(
    334       mock_adapter_, device0_.get(), service1_.get());
    335 
    336   // These will send the onServiceAdded event to apps.
    337   event_router()->GattDiscoveryCompleteForService(mock_adapter_,
    338                                                   service0_.get());
    339   event_router()->GattDiscoveryCompleteForService(mock_adapter_,
    340                                                   service1_.get());
    341 
    342   // This will send the onServiceChanged event to apps.
    343   event_router()->GattServiceChanged(mock_adapter_, service1_.get());
    344 
    345   // This will send the  onServiceRemoved event to apps.
    346   event_router()->GattServiceRemoved(
    347       mock_adapter_, device0_.get(), service0_.get());
    348 
    349   EXPECT_TRUE(listener.WaitUntilSatisfied());
    350   listener.Reply("go");
    351 
    352   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    353   event_router()->GattServiceRemoved(
    354       mock_adapter_, device0_.get(), service1_.get());
    355 }
    356 
    357 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetRemovedService) {
    358   ResultCatcher catcher;
    359   catcher.RestrictToBrowserContext(browser()->profile());
    360 
    361   // Load the extension and let it set up.
    362   ASSERT_TRUE(LoadExtension(
    363       test_data_dir_.AppendASCII("bluetooth_low_energy/get_removed_service")));
    364 
    365   // 1. getService success.
    366   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    367       .Times(1)
    368       .WillOnce(Return(device0_.get()));
    369   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    370       .Times(1)
    371       .WillOnce(Return(service0_.get()));
    372 
    373   event_router()->GattServiceAdded(
    374       mock_adapter_, device0_.get(), service0_.get());
    375   event_router()->GattDiscoveryCompleteForService(mock_adapter_,
    376                                                   service0_.get());
    377 
    378   ExtensionTestMessageListener get_service_success_listener("getServiceSuccess",
    379                                                             true);
    380   EXPECT_TRUE(get_service_success_listener.WaitUntilSatisfied());
    381   testing::Mock::VerifyAndClearExpectations(mock_adapter_);
    382   testing::Mock::VerifyAndClearExpectations(device0_.get());
    383 
    384   // 2. getService fail.
    385   EXPECT_CALL(*mock_adapter_, GetDevice(_)).Times(0);
    386   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0)).Times(0);
    387 
    388   event_router()->GattServiceRemoved(
    389       mock_adapter_, device0_.get(), service0_.get());
    390 
    391   ExtensionTestMessageListener get_service_fail_listener("getServiceFail",
    392                                                          true);
    393   EXPECT_TRUE(get_service_fail_listener.WaitUntilSatisfied());
    394   testing::Mock::VerifyAndClearExpectations(mock_adapter_);
    395   testing::Mock::VerifyAndClearExpectations(device0_.get());
    396 
    397   get_service_fail_listener.Reply("go");
    398 
    399   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    400 }
    401 
    402 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetIncludedServices) {
    403   ResultCatcher catcher;
    404   catcher.RestrictToBrowserContext(browser()->profile());
    405 
    406   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
    407       "bluetooth_low_energy/get_included_services")));
    408 
    409   // Wait for initial call to end with failure as there is no mapping.
    410   ExtensionTestMessageListener listener("ready", true);
    411   EXPECT_TRUE(listener.WaitUntilSatisfied());
    412 
    413   // Set up for the rest of the calls before replying. Included services can be
    414   // returned even if there is no instance ID mapping for them yet, so no need
    415   // to call GattServiceAdded for |service1_| here.
    416   event_router()->GattServiceAdded(
    417       mock_adapter_, device0_.get(), service0_.get());
    418 
    419   std::vector<BluetoothGattService*> includes;
    420   includes.push_back(service1_.get());
    421   EXPECT_CALL(*mock_adapter_, GetDevice(kTestLeDeviceAddress0))
    422       .Times(2)
    423       .WillRepeatedly(Return(device0_.get()));
    424   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    425       .Times(2)
    426       .WillRepeatedly(Return(service0_.get()));
    427   EXPECT_CALL(*service0_, GetIncludedServices())
    428       .Times(2)
    429       .WillOnce(Return(std::vector<BluetoothGattService*>()))
    430       .WillOnce(Return(includes));
    431 
    432   listener.Reply("go");
    433   listener.Reset();
    434 
    435   EXPECT_TRUE(listener.WaitUntilSatisfied());
    436 
    437   listener.Reply("go");
    438 
    439   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    440   event_router()->GattServiceRemoved(
    441       mock_adapter_, device0_.get(), service0_.get());
    442 }
    443 
    444 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetCharacteristics) {
    445   ResultCatcher catcher;
    446   catcher.RestrictToBrowserContext(browser()->profile());
    447 
    448   std::vector<BluetoothGattCharacteristic*> characteristics;
    449   characteristics.push_back(chrc0_.get());
    450   characteristics.push_back(chrc1_.get());
    451 
    452   event_router()->GattServiceAdded(
    453       mock_adapter_, device0_.get(), service0_.get());
    454 
    455   EXPECT_CALL(*mock_adapter_, GetDevice(_)).Times(3).WillRepeatedly(
    456       Return(device0_.get()));
    457   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    458       .Times(3)
    459       .WillOnce(Return(static_cast<BluetoothGattService*>(NULL)))
    460       .WillRepeatedly(Return(service0_.get()));
    461   EXPECT_CALL(*service0_, GetCharacteristics())
    462       .Times(2)
    463       .WillOnce(Return(std::vector<BluetoothGattCharacteristic*>()))
    464       .WillOnce(Return(characteristics));
    465 
    466   ExtensionTestMessageListener listener("ready", true);
    467   ASSERT_TRUE(LoadExtension(
    468       test_data_dir_.AppendASCII("bluetooth_low_energy/get_characteristics")));
    469   EXPECT_TRUE(listener.WaitUntilSatisfied());
    470 
    471   listener.Reply("go");
    472 
    473   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    474   event_router()->GattServiceRemoved(
    475       mock_adapter_, device0_.get(), service0_.get());
    476 }
    477 
    478 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetCharacteristic) {
    479   ResultCatcher catcher;
    480   catcher.RestrictToBrowserContext(browser()->profile());
    481 
    482   event_router()->GattServiceAdded(
    483       mock_adapter_, device0_.get(), service0_.get());
    484   event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
    485 
    486   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    487       .Times(4)
    488       .WillOnce(Return(static_cast<BluetoothDevice*>(NULL)))
    489       .WillRepeatedly(Return(device0_.get()));
    490 
    491   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    492       .Times(3)
    493       .WillOnce(Return(static_cast<BluetoothGattService*>(NULL)))
    494       .WillRepeatedly(Return(service0_.get()));
    495 
    496   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
    497       .Times(2)
    498       .WillOnce(Return(static_cast<BluetoothGattCharacteristic*>(NULL)))
    499       .WillOnce(Return(chrc0_.get()));
    500 
    501   // Load the extension and wait for first test.
    502   ExtensionTestMessageListener listener("ready", true);
    503   ASSERT_TRUE(LoadExtension(
    504       test_data_dir_.AppendASCII("bluetooth_low_energy/get_characteristic")));
    505   EXPECT_TRUE(listener.WaitUntilSatisfied());
    506 
    507   listener.Reply("go");
    508 
    509   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    510 
    511   event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
    512   event_router()->GattServiceRemoved(
    513       mock_adapter_, device0_.get(), service0_.get());
    514 }
    515 
    516 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, CharacteristicProperties) {
    517   ResultCatcher catcher;
    518   catcher.RestrictToBrowserContext(browser()->profile());
    519 
    520   event_router()->GattServiceAdded(
    521       mock_adapter_, device0_.get(), service0_.get());
    522   event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
    523 
    524   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    525       .Times(12)
    526       .WillRepeatedly(Return(device0_.get()));
    527   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    528       .Times(12)
    529       .WillRepeatedly(Return(service0_.get()));
    530   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
    531       .Times(12)
    532       .WillRepeatedly(Return(chrc0_.get()));
    533   EXPECT_CALL(*chrc0_, GetProperties())
    534       .Times(12)
    535       .WillOnce(Return(BluetoothGattCharacteristic::kPropertyNone))
    536       .WillOnce(Return(BluetoothGattCharacteristic::kPropertyBroadcast))
    537       .WillOnce(Return(BluetoothGattCharacteristic::kPropertyRead))
    538       .WillOnce(
    539            Return(BluetoothGattCharacteristic::kPropertyWriteWithoutResponse))
    540       .WillOnce(Return(BluetoothGattCharacteristic::kPropertyWrite))
    541       .WillOnce(Return(BluetoothGattCharacteristic::kPropertyNotify))
    542       .WillOnce(Return(BluetoothGattCharacteristic::kPropertyIndicate))
    543       .WillOnce(Return(
    544           BluetoothGattCharacteristic::kPropertyAuthenticatedSignedWrites))
    545       .WillOnce(
    546            Return(BluetoothGattCharacteristic::kPropertyExtendedProperties))
    547       .WillOnce(Return(BluetoothGattCharacteristic::kPropertyReliableWrite))
    548       .WillOnce(
    549            Return(BluetoothGattCharacteristic::kPropertyWritableAuxiliaries))
    550       .WillOnce(Return(
    551           BluetoothGattCharacteristic::kPropertyBroadcast |
    552           BluetoothGattCharacteristic::kPropertyRead |
    553           BluetoothGattCharacteristic::kPropertyWriteWithoutResponse |
    554           BluetoothGattCharacteristic::kPropertyWrite |
    555           BluetoothGattCharacteristic::kPropertyNotify |
    556           BluetoothGattCharacteristic::kPropertyIndicate |
    557           BluetoothGattCharacteristic::kPropertyAuthenticatedSignedWrites |
    558           BluetoothGattCharacteristic::kPropertyExtendedProperties |
    559           BluetoothGattCharacteristic::kPropertyReliableWrite |
    560           BluetoothGattCharacteristic::kPropertyWritableAuxiliaries));
    561 
    562   ExtensionTestMessageListener listener("ready", true);
    563   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
    564       "bluetooth_low_energy/characteristic_properties")));
    565   EXPECT_TRUE(listener.WaitUntilSatisfied());
    566 
    567   listener.Reply("go");
    568 
    569   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    570 
    571   event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
    572   event_router()->GattServiceRemoved(
    573       mock_adapter_, device0_.get(), service0_.get());
    574 }
    575 
    576 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetRemovedCharacteristic) {
    577   ResultCatcher catcher;
    578   catcher.RestrictToBrowserContext(browser()->profile());
    579 
    580   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    581       .Times(1)
    582       .WillOnce(Return(device0_.get()));
    583   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    584       .Times(1)
    585       .WillOnce(Return(service0_.get()));
    586   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
    587       .Times(1)
    588       .WillOnce(Return(chrc0_.get()));
    589 
    590   event_router()->GattServiceAdded(
    591       mock_adapter_, device0_.get(), service0_.get());
    592   event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
    593 
    594   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
    595       "bluetooth_low_energy/get_removed_characteristic")));
    596 
    597   ExtensionTestMessageListener listener("ready", true);
    598   EXPECT_TRUE(listener.WaitUntilSatisfied());
    599   testing::Mock::VerifyAndClearExpectations(mock_adapter_);
    600   testing::Mock::VerifyAndClearExpectations(device0_.get());
    601   testing::Mock::VerifyAndClearExpectations(service0_.get());
    602 
    603   EXPECT_CALL(*mock_adapter_, GetDevice(_)).Times(0);
    604   EXPECT_CALL(*device0_, GetGattService(_)).Times(0);
    605   EXPECT_CALL(*service0_, GetCharacteristic(_)).Times(0);
    606 
    607   event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
    608 
    609   listener.Reply("go");
    610   listener.Reset();
    611   EXPECT_TRUE(listener.WaitUntilSatisfied());
    612 
    613   listener.Reply("go");
    614 
    615   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    616   event_router()->GattServiceRemoved(
    617       mock_adapter_, device0_.get(), service0_.get());
    618 }
    619 
    620 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, CharacteristicValueChanged) {
    621   ResultCatcher catcher;
    622   catcher.RestrictToBrowserContext(browser()->profile());
    623 
    624   // Cause events to be sent to the extension.
    625   event_router()->GattServiceAdded(
    626       mock_adapter_, device0_.get(), service0_.get());
    627   event_router()->GattServiceAdded(
    628       mock_adapter_, device0_.get(), service1_.get());
    629   event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
    630   event_router()->GattCharacteristicAdded(mock_adapter_, chrc2_.get());
    631 
    632   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    633       .Times(2)
    634       .WillRepeatedly(Return(device0_.get()));
    635   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    636       .Times(1)
    637       .WillOnce(Return(service0_.get()));
    638   EXPECT_CALL(*device0_, GetGattService(kTestServiceId1))
    639       .Times(1)
    640       .WillOnce(Return(service1_.get()));
    641   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
    642       .Times(1)
    643       .WillOnce(Return(chrc0_.get()));
    644   EXPECT_CALL(*service1_, GetCharacteristic(kTestCharacteristicId2))
    645       .Times(1)
    646       .WillOnce(Return(chrc2_.get()));
    647 
    648   BluetoothGattNotifySession* session0 =
    649       new testing::NiceMock<MockBluetoothGattNotifySession>(
    650           kTestCharacteristicId0);
    651   BluetoothGattNotifySession* session1 =
    652       new testing::NiceMock<MockBluetoothGattNotifySession>(
    653           kTestCharacteristicId2);
    654 
    655   EXPECT_CALL(*chrc0_, StartNotifySession(_, _))
    656       .Times(1)
    657       .WillOnce(
    658           InvokeCallbackWithScopedPtrArg<0, BluetoothGattNotifySession>(
    659               session0));
    660   EXPECT_CALL(*chrc2_, StartNotifySession(_, _))
    661       .Times(1)
    662       .WillOnce(
    663           InvokeCallbackWithScopedPtrArg<0, BluetoothGattNotifySession>(
    664               session1));
    665 
    666   ExtensionTestMessageListener listener("ready", true);
    667   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
    668       "bluetooth_low_energy/characteristic_value_changed")));
    669 
    670   EXPECT_TRUE(listener.WaitUntilSatisfied());
    671 
    672   std::vector<uint8> value;
    673   event_router()->GattCharacteristicValueChanged(
    674       mock_adapter_, chrc0_.get(), value);
    675   event_router()->GattCharacteristicValueChanged(
    676       mock_adapter_, chrc2_.get(), value);
    677 
    678   listener.Reply("go");
    679 
    680   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    681   event_router()->GattCharacteristicRemoved(mock_adapter_, chrc2_.get());
    682   event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
    683   event_router()->GattServiceRemoved(
    684       mock_adapter_, device0_.get(), service1_.get());
    685   event_router()->GattServiceRemoved(
    686       mock_adapter_, device0_.get(), service0_.get());
    687 }
    688 
    689 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, ReadCharacteristicValue) {
    690   ResultCatcher catcher;
    691   catcher.RestrictToBrowserContext(browser()->profile());
    692 
    693   event_router()->GattServiceAdded(
    694       mock_adapter_, device0_.get(), service0_.get());
    695   event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
    696 
    697   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    698       .Times(3)
    699       .WillRepeatedly(Return(device0_.get()));
    700 
    701   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    702       .Times(3)
    703       .WillRepeatedly(Return(service0_.get()));
    704 
    705   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
    706       .Times(3)
    707       .WillRepeatedly(Return(chrc0_.get()));
    708 
    709   std::vector<uint8> value;
    710   EXPECT_CALL(*chrc0_, ReadRemoteCharacteristic(_, _))
    711       .Times(2)
    712       .WillOnce(InvokeCallbackArgument<1>())
    713       .WillOnce(InvokeCallbackArgument<0>(value));
    714 
    715   ExtensionTestMessageListener listener("ready", true);
    716   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
    717       "bluetooth_low_energy/read_characteristic_value")));
    718   EXPECT_TRUE(listener.WaitUntilSatisfied());
    719 
    720   listener.Reply("go");
    721 
    722   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    723 
    724   event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
    725   event_router()->GattServiceRemoved(
    726       mock_adapter_, device0_.get(), service0_.get());
    727 }
    728 
    729 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, WriteCharacteristicValue) {
    730   ResultCatcher catcher;
    731   catcher.RestrictToBrowserContext(browser()->profile());
    732 
    733   event_router()->GattServiceAdded(
    734       mock_adapter_, device0_.get(), service0_.get());
    735   event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
    736 
    737   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    738       .Times(3)
    739       .WillRepeatedly(Return(device0_.get()));
    740 
    741   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    742       .Times(3)
    743       .WillRepeatedly(Return(service0_.get()));
    744 
    745   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
    746       .Times(3)
    747       .WillRepeatedly(Return(chrc0_.get()));
    748 
    749   std::vector<uint8> write_value;
    750   EXPECT_CALL(*chrc0_, WriteRemoteCharacteristic(_, _, _))
    751       .Times(2)
    752       .WillOnce(InvokeCallbackArgument<2>())
    753       .WillOnce(DoAll(SaveArg<0>(&write_value), InvokeCallbackArgument<1>()));
    754 
    755   EXPECT_CALL(*chrc0_, GetValue()).Times(1).WillOnce(ReturnRef(write_value));
    756 
    757   ExtensionTestMessageListener listener("ready", true);
    758   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
    759       "bluetooth_low_energy/write_characteristic_value")));
    760   EXPECT_TRUE(listener.WaitUntilSatisfied());
    761 
    762   listener.Reply("go");
    763 
    764   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    765 
    766   event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
    767   event_router()->GattServiceRemoved(
    768       mock_adapter_, device0_.get(), service0_.get());
    769 }
    770 
    771 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetDescriptors) {
    772   ResultCatcher catcher;
    773   catcher.RestrictToBrowserContext(browser()->profile());
    774 
    775   std::vector<BluetoothGattDescriptor*> descriptors;
    776   descriptors.push_back(desc0_.get());
    777   descriptors.push_back(desc1_.get());
    778 
    779   event_router()->GattServiceAdded(
    780       mock_adapter_, device0_.get(), service0_.get());
    781   event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
    782 
    783   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    784       .Times(3)
    785       .WillRepeatedly(Return(device0_.get()));
    786   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    787       .Times(3)
    788       .WillRepeatedly(Return(service0_.get()));
    789   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
    790       .Times(3)
    791       .WillOnce(Return(static_cast<BluetoothGattCharacteristic*>(NULL)))
    792       .WillRepeatedly(Return(chrc0_.get()));
    793   EXPECT_CALL(*chrc0_, GetDescriptors())
    794       .Times(2)
    795       .WillOnce(Return(std::vector<BluetoothGattDescriptor*>()))
    796       .WillOnce(Return(descriptors));
    797 
    798   ExtensionTestMessageListener listener("ready", true);
    799   ASSERT_TRUE(LoadExtension(
    800       test_data_dir_.AppendASCII("bluetooth_low_energy/get_descriptors")));
    801   EXPECT_TRUE(listener.WaitUntilSatisfied());
    802 
    803   listener.Reply("go");
    804 
    805   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    806 
    807   event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
    808   event_router()->GattServiceRemoved(
    809       mock_adapter_, device0_.get(), service0_.get());
    810 }
    811 
    812 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetDescriptor) {
    813   ResultCatcher catcher;
    814   catcher.RestrictToBrowserContext(browser()->profile());
    815 
    816   event_router()->GattServiceAdded(
    817       mock_adapter_, device0_.get(), service0_.get());
    818   event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
    819   event_router()->GattDescriptorAdded(mock_adapter_, desc0_.get());
    820 
    821   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    822       .Times(5)
    823       .WillOnce(Return(static_cast<BluetoothDevice*>(NULL)))
    824       .WillRepeatedly(Return(device0_.get()));
    825 
    826   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    827       .Times(4)
    828       .WillOnce(Return(static_cast<BluetoothGattService*>(NULL)))
    829       .WillRepeatedly(Return(service0_.get()));
    830 
    831   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
    832       .Times(3)
    833       .WillOnce(Return(static_cast<BluetoothGattCharacteristic*>(NULL)))
    834       .WillRepeatedly(Return(chrc0_.get()));
    835 
    836   EXPECT_CALL(*chrc0_, GetDescriptor(kTestDescriptorId0))
    837       .Times(2)
    838       .WillOnce(Return(static_cast<BluetoothGattDescriptor*>(NULL)))
    839       .WillOnce(Return(desc0_.get()));
    840 
    841   // Load the extension and wait for first test.
    842   ExtensionTestMessageListener listener("ready", true);
    843   ASSERT_TRUE(LoadExtension(
    844       test_data_dir_.AppendASCII("bluetooth_low_energy/get_descriptor")));
    845   EXPECT_TRUE(listener.WaitUntilSatisfied());
    846 
    847   listener.Reply("go");
    848 
    849   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    850 
    851   event_router()->GattDescriptorRemoved(mock_adapter_, desc0_.get());
    852   event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
    853   event_router()->GattServiceRemoved(
    854       mock_adapter_, device0_.get(), service0_.get());
    855 }
    856 
    857 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetRemovedDescriptor) {
    858   ResultCatcher catcher;
    859   catcher.RestrictToBrowserContext(browser()->profile());
    860 
    861   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    862       .Times(1)
    863       .WillOnce(Return(device0_.get()));
    864   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    865       .Times(1)
    866       .WillOnce(Return(service0_.get()));
    867   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
    868       .Times(1)
    869       .WillOnce(Return(chrc0_.get()));
    870   EXPECT_CALL(*chrc0_, GetDescriptor(kTestDescriptorId0))
    871       .Times(1)
    872       .WillOnce(Return(desc0_.get()));
    873 
    874   event_router()->GattServiceAdded(
    875       mock_adapter_, device0_.get(), service0_.get());
    876   event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
    877   event_router()->GattDescriptorAdded(mock_adapter_, desc0_.get());
    878 
    879   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
    880       "bluetooth_low_energy/get_removed_descriptor")));
    881 
    882   ExtensionTestMessageListener listener("ready", true);
    883   EXPECT_TRUE(listener.WaitUntilSatisfied());
    884   testing::Mock::VerifyAndClearExpectations(mock_adapter_);
    885   testing::Mock::VerifyAndClearExpectations(device0_.get());
    886   testing::Mock::VerifyAndClearExpectations(service0_.get());
    887   testing::Mock::VerifyAndClearExpectations(chrc0_.get());
    888 
    889   EXPECT_CALL(*mock_adapter_, GetDevice(_)).Times(0);
    890   EXPECT_CALL(*device0_, GetGattService(_)).Times(0);
    891   EXPECT_CALL(*service0_, GetCharacteristic(_)).Times(0);
    892   EXPECT_CALL(*chrc0_, GetDescriptor(_)).Times(0);
    893 
    894   event_router()->GattDescriptorRemoved(mock_adapter_, desc0_.get());
    895 
    896   listener.Reply("go");
    897   listener.Reset();
    898   EXPECT_TRUE(listener.WaitUntilSatisfied());
    899 
    900   listener.Reply("go");
    901 
    902   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    903   event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
    904   event_router()->GattServiceRemoved(
    905       mock_adapter_, device0_.get(), service0_.get());
    906 }
    907 
    908 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, DescriptorValueChanged) {
    909   ResultCatcher catcher;
    910   catcher.RestrictToBrowserContext(browser()->profile());
    911 
    912   event_router()->GattServiceAdded(
    913       mock_adapter_, device0_.get(), service0_.get());
    914   event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
    915   event_router()->GattDescriptorAdded(mock_adapter_, desc0_.get());
    916   event_router()->GattDescriptorAdded(mock_adapter_, desc1_.get());
    917 
    918   // Load the extension and let it set up.
    919   ExtensionTestMessageListener listener("ready", true);
    920   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
    921       "bluetooth_low_energy/descriptor_value_changed")));
    922 
    923   // Cause events to be sent to the extension.
    924   std::vector<uint8> value;
    925   event_router()->GattDescriptorValueChanged(
    926       mock_adapter_, desc0_.get(), value);
    927   event_router()->GattDescriptorValueChanged(
    928       mock_adapter_, desc1_.get(), value);
    929 
    930   EXPECT_TRUE(listener.WaitUntilSatisfied());
    931   listener.Reply("go");
    932 
    933   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    934   event_router()->GattDescriptorRemoved(mock_adapter_, desc1_.get());
    935   event_router()->GattDescriptorRemoved(mock_adapter_, desc0_.get());
    936   event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
    937   event_router()->GattServiceRemoved(
    938       mock_adapter_, device0_.get(), service0_.get());
    939 }
    940 
    941 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, ReadDescriptorValue) {
    942   ResultCatcher catcher;
    943   catcher.RestrictToBrowserContext(browser()->profile());
    944 
    945   event_router()->GattServiceAdded(
    946       mock_adapter_, device0_.get(), service0_.get());
    947   event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
    948   event_router()->GattDescriptorAdded(mock_adapter_, desc0_.get());
    949 
    950   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    951       .Times(3)
    952       .WillRepeatedly(Return(device0_.get()));
    953 
    954   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    955       .Times(3)
    956       .WillRepeatedly(Return(service0_.get()));
    957 
    958   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
    959       .Times(3)
    960       .WillRepeatedly(Return(chrc0_.get()));
    961 
    962   EXPECT_CALL(*chrc0_, GetDescriptor(kTestDescriptorId0))
    963       .Times(3)
    964       .WillRepeatedly(Return(desc0_.get()));
    965 
    966   std::vector<uint8> value;
    967   EXPECT_CALL(*desc0_, ReadRemoteDescriptor(_, _))
    968       .Times(2)
    969       .WillOnce(InvokeCallbackArgument<1>())
    970       .WillOnce(InvokeCallbackArgument<0>(value));
    971 
    972   ExtensionTestMessageListener listener("ready", true);
    973   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
    974       "bluetooth_low_energy/read_descriptor_value")));
    975   EXPECT_TRUE(listener.WaitUntilSatisfied());
    976 
    977   listener.Reply("go");
    978 
    979   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    980 
    981   event_router()->GattDescriptorRemoved(mock_adapter_, desc0_.get());
    982   event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
    983   event_router()->GattServiceRemoved(
    984       mock_adapter_, device0_.get(), service0_.get());
    985 }
    986 
    987 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, WriteDescriptorValue) {
    988   ResultCatcher catcher;
    989   catcher.RestrictToBrowserContext(browser()->profile());
    990 
    991   event_router()->GattServiceAdded(
    992       mock_adapter_, device0_.get(), service0_.get());
    993   event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
    994   event_router()->GattDescriptorAdded(mock_adapter_, desc0_.get());
    995 
    996   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    997       .Times(3)
    998       .WillRepeatedly(Return(device0_.get()));
    999 
   1000   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
   1001       .Times(3)
   1002       .WillRepeatedly(Return(service0_.get()));
   1003 
   1004   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
   1005       .Times(3)
   1006       .WillRepeatedly(Return(chrc0_.get()));
   1007 
   1008   EXPECT_CALL(*chrc0_, GetDescriptor(kTestDescriptorId0))
   1009       .Times(3)
   1010       .WillRepeatedly(Return(desc0_.get()));
   1011 
   1012   std::vector<uint8> write_value;
   1013   EXPECT_CALL(*desc0_, WriteRemoteDescriptor(_, _, _))
   1014       .Times(2)
   1015       .WillOnce(InvokeCallbackArgument<2>())
   1016       .WillOnce(DoAll(SaveArg<0>(&write_value), InvokeCallbackArgument<1>()));
   1017 
   1018   EXPECT_CALL(*desc0_, GetValue()).Times(1).WillOnce(ReturnRef(write_value));
   1019 
   1020   ExtensionTestMessageListener listener("ready", true);
   1021   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
   1022       "bluetooth_low_energy/write_descriptor_value")));
   1023   EXPECT_TRUE(listener.WaitUntilSatisfied());
   1024 
   1025   listener.Reply("go");
   1026 
   1027   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
   1028 
   1029   event_router()->GattDescriptorRemoved(mock_adapter_, desc0_.get());
   1030   event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
   1031   event_router()->GattServiceRemoved(
   1032       mock_adapter_, device0_.get(), service0_.get());
   1033 }
   1034 
   1035 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, PermissionDenied) {
   1036   ResultCatcher catcher;
   1037   catcher.RestrictToBrowserContext(browser()->profile());
   1038 
   1039   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
   1040       "bluetooth_low_energy/permission_denied")));
   1041   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
   1042 }
   1043 
   1044 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, UuidPermissionMethods) {
   1045   ResultCatcher catcher;
   1046   catcher.RestrictToBrowserContext(browser()->profile());
   1047 
   1048   event_router()->GattServiceAdded(
   1049       mock_adapter_, device0_.get(), service0_.get());
   1050   event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
   1051   event_router()->GattDescriptorAdded(mock_adapter_, desc0_.get());
   1052 
   1053   std::vector<BluetoothGattService*> services;
   1054   services.push_back(service0_.get());
   1055 
   1056   EXPECT_CALL(*mock_adapter_, GetDevice(_))
   1057       .WillRepeatedly(Return(device0_.get()));
   1058   EXPECT_CALL(*device0_, GetGattServices()).WillOnce(Return(services));
   1059   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
   1060       .WillRepeatedly(Return(service0_.get()));
   1061   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
   1062       .WillRepeatedly(Return(chrc0_.get()));
   1063   EXPECT_CALL(*chrc0_, GetDescriptor(kTestDescriptorId0))
   1064       .WillRepeatedly(Return(desc0_.get()));
   1065 
   1066   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
   1067       "bluetooth_low_energy/uuid_permission_methods")));
   1068   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
   1069 
   1070   event_router()->GattDescriptorRemoved(mock_adapter_, desc0_.get());
   1071   event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
   1072   event_router()->GattServiceRemoved(
   1073       mock_adapter_, device0_.get(), service0_.get());
   1074 }
   1075 
   1076 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, UuidPermissionEvents) {
   1077   ResultCatcher catcher;
   1078   catcher.RestrictToBrowserContext(browser()->profile());
   1079 
   1080   ExtensionTestMessageListener listener("ready", true);
   1081   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
   1082       "bluetooth_low_energy/uuid_permission_events")));
   1083 
   1084   // Cause events to be sent to the extension.
   1085   event_router()->GattServiceAdded(
   1086       mock_adapter_, device0_.get(), service0_.get());
   1087   event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
   1088   event_router()->GattDescriptorAdded(mock_adapter_, desc0_.get());
   1089 
   1090   std::vector<uint8> value;
   1091   event_router()->GattCharacteristicValueChanged(
   1092       mock_adapter_, chrc0_.get(), value);
   1093   event_router()->GattDescriptorValueChanged(
   1094       mock_adapter_, desc0_.get(), value);
   1095   event_router()->GattServiceChanged(mock_adapter_, service0_.get());
   1096 
   1097   EXPECT_TRUE(listener.WaitUntilSatisfied());
   1098   listener.Reply("go");
   1099   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
   1100 
   1101   event_router()->GattDescriptorRemoved(mock_adapter_, desc0_.get());
   1102   event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
   1103   event_router()->GattServiceRemoved(
   1104       mock_adapter_, device0_.get(), service0_.get());
   1105 }
   1106 
   1107 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GattConnection) {
   1108   ResultCatcher catcher;
   1109   catcher.RestrictToBrowserContext(browser()->profile());
   1110 
   1111   EXPECT_CALL(*mock_adapter_, GetDevice(_))
   1112       .WillRepeatedly(Return(static_cast<BluetoothDevice*>(NULL)));
   1113   EXPECT_CALL(*mock_adapter_, GetDevice(kTestLeDeviceAddress0))
   1114       .WillRepeatedly(Return(device0_.get()));
   1115   EXPECT_CALL(*mock_adapter_, GetDevice(kTestLeDeviceAddress1))
   1116       .WillRepeatedly(Return(device1_.get()));
   1117   EXPECT_CALL(*device0_, CreateGattConnection(_, _))
   1118       .Times(3)
   1119       .WillOnce(InvokeCallbackArgument<1>(BluetoothDevice::ERROR_FAILED))
   1120       .WillOnce(InvokeCallbackWithScopedPtrArg<0, BluetoothGattConnection>(
   1121           CreateGattConnection(kTestLeDeviceAddress0,
   1122                                true /* expect_disconnect */)))
   1123       .WillOnce(InvokeCallbackWithScopedPtrArg<0, BluetoothGattConnection>(
   1124           CreateGattConnection(kTestLeDeviceAddress0,
   1125                                false /* expect_disconnect */)));
   1126   EXPECT_CALL(*device1_, CreateGattConnection(_, _))
   1127       .Times(1)
   1128       .WillOnce(InvokeCallbackWithScopedPtrArg<0, BluetoothGattConnection>(
   1129           CreateGattConnection(kTestLeDeviceAddress1,
   1130                                true /* expect_disconnect */)));
   1131 
   1132   ASSERT_TRUE(LoadExtension(
   1133       test_data_dir_.AppendASCII("bluetooth_low_energy/gatt_connection")));
   1134   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
   1135 }
   1136 
   1137 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, ReconnectAfterDisconnected) {
   1138   ResultCatcher catcher;
   1139   catcher.RestrictToBrowserContext(browser()->profile());
   1140 
   1141   EXPECT_CALL(*mock_adapter_, GetDevice(kTestLeDeviceAddress0))
   1142       .WillRepeatedly(Return(device0_.get()));
   1143 
   1144   MockBluetoothGattConnection* first_conn =
   1145       static_cast<MockBluetoothGattConnection*>(CreateGattConnection(
   1146           kTestLeDeviceAddress0, false /* expect_disconnect */));
   1147   EXPECT_CALL(*first_conn, IsConnected())
   1148       .Times(2)
   1149       .WillOnce(Return(true))
   1150       .WillOnce(Return(false));
   1151 
   1152   EXPECT_CALL(*device0_, CreateGattConnection(_, _))
   1153       .Times(2)
   1154       .WillOnce(InvokeCallbackWithScopedPtrArg<0, BluetoothGattConnection>(
   1155           first_conn))
   1156       .WillOnce(InvokeCallbackWithScopedPtrArg<0, BluetoothGattConnection>(
   1157           CreateGattConnection(kTestLeDeviceAddress0,
   1158                                false /* expect_disconnect */)));
   1159 
   1160   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
   1161       "bluetooth_low_energy/reconnect_after_disconnected")));
   1162   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
   1163 }
   1164 
   1165 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, ConnectInProgress) {
   1166   ResultCatcher catcher;
   1167   catcher.RestrictToBrowserContext(browser()->profile());
   1168 
   1169   EXPECT_CALL(*mock_adapter_, GetDevice(kTestLeDeviceAddress0))
   1170       .WillRepeatedly(Return(device0_.get()));
   1171 
   1172   BluetoothDevice::GattConnectionCallback connect_callback;
   1173   base::Closure disconnect_callback;
   1174 
   1175   testing::NiceMock<MockBluetoothGattConnection>* conn =
   1176       new testing::NiceMock<MockBluetoothGattConnection>(
   1177           kTestLeDeviceAddress0);
   1178   scoped_ptr<BluetoothGattConnection> conn_ptr(conn);
   1179   EXPECT_CALL(*conn, Disconnect(_))
   1180       .Times(1)
   1181       .WillOnce(SaveArg<0>(&disconnect_callback));
   1182 
   1183   EXPECT_CALL(*device0_, CreateGattConnection(_, _))
   1184       .Times(1)
   1185       .WillOnce(SaveArg<0>(&connect_callback));
   1186 
   1187   ExtensionTestMessageListener listener("ready", true);
   1188   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
   1189       "bluetooth_low_energy/connect_in_progress")));
   1190 
   1191   listener.WaitUntilSatisfied();
   1192   connect_callback.Run(conn_ptr.Pass());
   1193 
   1194   listener.Reset();
   1195   listener.WaitUntilSatisfied();
   1196   disconnect_callback.Run();
   1197 
   1198   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
   1199 }
   1200 
   1201 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, StartStopNotifications) {
   1202   ResultCatcher catcher;
   1203   catcher.RestrictToBrowserContext(browser()->profile());
   1204 
   1205   event_router()->GattServiceAdded(
   1206       mock_adapter_, device0_.get(), service0_.get());
   1207   event_router()->GattServiceAdded(
   1208       mock_adapter_, device0_.get(), service1_.get());
   1209   event_router()->GattCharacteristicAdded(mock_adapter_, chrc0_.get());
   1210   event_router()->GattCharacteristicAdded(mock_adapter_, chrc1_.get());
   1211   event_router()->GattCharacteristicAdded(mock_adapter_, chrc2_.get());
   1212 
   1213   EXPECT_CALL(*mock_adapter_, GetDevice(_))
   1214       .WillRepeatedly(Return(device0_.get()));
   1215   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
   1216       .WillRepeatedly(Return(service0_.get()));
   1217   EXPECT_CALL(*device0_, GetGattService(kTestServiceId1))
   1218       .WillRepeatedly(Return(service1_.get()));
   1219   EXPECT_CALL(*service1_, GetCharacteristic(kTestCharacteristicId2))
   1220       .Times(1)
   1221       .WillOnce(Return(chrc2_.get()));
   1222   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
   1223       .Times(2)
   1224       .WillRepeatedly(Return(chrc0_.get()));
   1225   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId1))
   1226       .Times(1)
   1227       .WillOnce(Return(chrc1_.get()));
   1228 
   1229   BluetoothGattNotifySession* session0 =
   1230       new testing::NiceMock<MockBluetoothGattNotifySession>(
   1231           kTestCharacteristicId0);
   1232   MockBluetoothGattNotifySession* session1 =
   1233       new testing::NiceMock<MockBluetoothGattNotifySession>(
   1234           kTestCharacteristicId1);
   1235 
   1236   EXPECT_CALL(*session1, Stop(_))
   1237       .Times(1)
   1238       .WillOnce(InvokeCallbackArgument<0>());
   1239 
   1240   EXPECT_CALL(*chrc0_, StartNotifySession(_, _))
   1241       .Times(2)
   1242       .WillOnce(InvokeCallbackArgument<1>())
   1243       .WillOnce(
   1244           InvokeCallbackWithScopedPtrArg<0, BluetoothGattNotifySession>(
   1245               session0));
   1246   EXPECT_CALL(*chrc1_, StartNotifySession(_, _))
   1247       .Times(1)
   1248       .WillOnce(
   1249           InvokeCallbackWithScopedPtrArg<0, BluetoothGattNotifySession>(
   1250               session1));
   1251 
   1252   ExtensionTestMessageListener listener("ready", true);
   1253   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
   1254       "bluetooth_low_energy/start_stop_notifications")));
   1255 
   1256   EXPECT_TRUE(listener.WaitUntilSatisfied());
   1257 
   1258   std::vector<uint8> value;
   1259   event_router()->GattCharacteristicValueChanged(
   1260       mock_adapter_, chrc0_.get(), value);
   1261   event_router()->GattCharacteristicValueChanged(
   1262       mock_adapter_, chrc1_.get(), value);
   1263   event_router()->GattCharacteristicValueChanged(
   1264       mock_adapter_, chrc2_.get(), value);
   1265 
   1266   listener.Reply("go");
   1267 
   1268   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
   1269   event_router()->GattCharacteristicRemoved(mock_adapter_, chrc2_.get());
   1270   event_router()->GattCharacteristicRemoved(mock_adapter_, chrc1_.get());
   1271   event_router()->GattCharacteristicRemoved(mock_adapter_, chrc0_.get());
   1272   event_router()->GattServiceRemoved(
   1273       mock_adapter_, device0_.get(), service1_.get());
   1274   event_router()->GattServiceRemoved(
   1275       mock_adapter_, device0_.get(), service0_.get());
   1276 }
   1277 
   1278 }  // namespace
   1279