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/api/bluetooth_low_energy/bluetooth_low_energy_api.h"
      7 #include "chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_event_router.h"
      8 #include "chrome/browser/extensions/extension_apitest.h"
      9 #include "chrome/browser/extensions/extension_function_test_utils.h"
     10 #include "chrome/browser/extensions/extension_test_message_listener.h"
     11 #include "device/bluetooth/test/mock_bluetooth_adapter.h"
     12 #include "device/bluetooth/test/mock_bluetooth_device.h"
     13 #include "device/bluetooth/test/mock_bluetooth_gatt_characteristic.h"
     14 #include "device/bluetooth/test/mock_bluetooth_gatt_connection.h"
     15 #include "device/bluetooth/test/mock_bluetooth_gatt_descriptor.h"
     16 #include "device/bluetooth/test/mock_bluetooth_gatt_notify_session.h"
     17 #include "device/bluetooth/test/mock_bluetooth_gatt_service.h"
     18 #include "testing/gmock/include/gmock/gmock.h"
     19 
     20 using device::BluetoothUUID;
     21 using device::BluetoothAdapter;
     22 using device::BluetoothDevice;
     23 using device::BluetoothGattCharacteristic;
     24 using device::BluetoothGattConnection;
     25 using device::BluetoothGattDescriptor;
     26 using device::BluetoothGattService;
     27 using device::BluetoothGattNotifySession;
     28 using device::MockBluetoothAdapter;
     29 using device::MockBluetoothDevice;
     30 using device::MockBluetoothGattCharacteristic;
     31 using device::MockBluetoothGattConnection;
     32 using device::MockBluetoothGattDescriptor;
     33 using device::MockBluetoothGattService;
     34 using device::MockBluetoothGattNotifySession;
     35 using extensions::BluetoothLowEnergyEventRouter;
     36 using testing::Invoke;
     37 using testing::Return;
     38 using testing::ReturnRef;
     39 using testing::ReturnRefOfCopy;
     40 using testing::SaveArg;
     41 using testing::_;
     42 
     43 namespace utils = extension_function_test_utils;
     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_ = utils::CreateEmptyExtension();
    101     SetUpMocks();
    102   }
    103 
    104   virtual void CleanUpOnMainThread() 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.RestrictToProfile(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.RestrictToProfile(browser()->profile());
    293 
    294   event_router()->DeviceAdded(mock_adapter_, device0_.get());
    295   event_router()->GattServiceAdded(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(device0_.get(), service0_.get());
    318   event_router()->DeviceRemoved(mock_adapter_, device0_.get());
    319 }
    320 
    321 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, ServiceEvents) {
    322   ResultCatcher catcher;
    323   catcher.RestrictToProfile(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   // Cause events to be sent to the extension.
    331   event_router()->DeviceAdded(mock_adapter_, device0_.get());
    332 
    333   event_router()->GattServiceAdded(device0_.get(), service0_.get());
    334   event_router()->GattServiceAdded(device0_.get(), service1_.get());
    335   event_router()->GattServiceChanged(service1_.get());
    336   event_router()->GattServiceRemoved(device0_.get(), service0_.get());
    337 
    338   EXPECT_TRUE(listener.WaitUntilSatisfied());
    339   listener.Reply("go");
    340 
    341   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    342   event_router()->GattServiceRemoved(device0_.get(), service1_.get());
    343   event_router()->DeviceRemoved(mock_adapter_, device0_.get());
    344 }
    345 
    346 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetRemovedService) {
    347   ResultCatcher catcher;
    348   catcher.RestrictToProfile(browser()->profile());
    349 
    350   // Load the extension and let it set up.
    351   ASSERT_TRUE(LoadExtension(
    352       test_data_dir_.AppendASCII("bluetooth_low_energy/get_removed_service")));
    353 
    354   // 1. getService success.
    355   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    356       .Times(1)
    357       .WillOnce(Return(device0_.get()));
    358   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    359       .Times(1)
    360       .WillOnce(Return(service0_.get()));
    361 
    362   event_router()->DeviceAdded(mock_adapter_, device0_.get());
    363   event_router()->GattServiceAdded(device0_.get(), service0_.get());
    364 
    365   ExtensionTestMessageListener get_service_success_listener("getServiceSuccess",
    366                                                             true);
    367   EXPECT_TRUE(get_service_success_listener.WaitUntilSatisfied());
    368   testing::Mock::VerifyAndClearExpectations(mock_adapter_);
    369   testing::Mock::VerifyAndClearExpectations(device0_.get());
    370 
    371   // 2. getService fail.
    372   EXPECT_CALL(*mock_adapter_, GetDevice(_)).Times(0);
    373   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0)).Times(0);
    374 
    375   event_router()->GattServiceRemoved(device0_.get(), service0_.get());
    376 
    377   ExtensionTestMessageListener get_service_fail_listener("getServiceFail",
    378                                                          true);
    379   EXPECT_TRUE(get_service_fail_listener.WaitUntilSatisfied());
    380   testing::Mock::VerifyAndClearExpectations(mock_adapter_);
    381   testing::Mock::VerifyAndClearExpectations(device0_.get());
    382 
    383   get_service_fail_listener.Reply("go");
    384 
    385   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    386   event_router()->DeviceRemoved(mock_adapter_, device0_.get());
    387 }
    388 
    389 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetIncludedServices) {
    390   ResultCatcher catcher;
    391   catcher.RestrictToProfile(browser()->profile());
    392 
    393   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
    394       "bluetooth_low_energy/get_included_services")));
    395 
    396   // Wait for initial call to end with failure as there is no mapping.
    397   ExtensionTestMessageListener listener("ready", true);
    398   EXPECT_TRUE(listener.WaitUntilSatisfied());
    399 
    400   // Set up for the rest of the calls before replying. Included services can be
    401   // returned even if there is no instance ID mapping for them yet, so no need
    402   // to call GattServiceAdded for |service1_| here.
    403   event_router()->DeviceAdded(mock_adapter_, device0_.get());
    404   event_router()->GattServiceAdded(device0_.get(), service0_.get());
    405 
    406   std::vector<BluetoothGattService*> includes;
    407   includes.push_back(service1_.get());
    408   EXPECT_CALL(*mock_adapter_, GetDevice(kTestLeDeviceAddress0))
    409       .Times(2)
    410       .WillRepeatedly(Return(device0_.get()));
    411   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    412       .Times(2)
    413       .WillRepeatedly(Return(service0_.get()));
    414   EXPECT_CALL(*service0_, GetIncludedServices())
    415       .Times(2)
    416       .WillOnce(Return(std::vector<BluetoothGattService*>()))
    417       .WillOnce(Return(includes));
    418 
    419   listener.Reply("go");
    420   listener.Reset();
    421 
    422   EXPECT_TRUE(listener.WaitUntilSatisfied());
    423 
    424   listener.Reply("go");
    425 
    426   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    427   event_router()->GattServiceRemoved(device0_.get(), service0_.get());
    428   event_router()->DeviceRemoved(mock_adapter_, device0_.get());
    429 }
    430 
    431 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetCharacteristics) {
    432   ResultCatcher catcher;
    433   catcher.RestrictToProfile(browser()->profile());
    434 
    435   std::vector<BluetoothGattCharacteristic*> characteristics;
    436   characteristics.push_back(chrc0_.get());
    437   characteristics.push_back(chrc1_.get());
    438 
    439   event_router()->DeviceAdded(mock_adapter_, device0_.get());
    440   event_router()->GattServiceAdded(device0_.get(), service0_.get());
    441 
    442   EXPECT_CALL(*mock_adapter_, GetDevice(_)).Times(3).WillRepeatedly(
    443       Return(device0_.get()));
    444   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    445       .Times(3)
    446       .WillOnce(Return(static_cast<BluetoothGattService*>(NULL)))
    447       .WillRepeatedly(Return(service0_.get()));
    448   EXPECT_CALL(*service0_, GetCharacteristics())
    449       .Times(2)
    450       .WillOnce(Return(std::vector<BluetoothGattCharacteristic*>()))
    451       .WillOnce(Return(characteristics));
    452 
    453   ExtensionTestMessageListener listener("ready", true);
    454   ASSERT_TRUE(LoadExtension(
    455       test_data_dir_.AppendASCII("bluetooth_low_energy/get_characteristics")));
    456   EXPECT_TRUE(listener.WaitUntilSatisfied());
    457 
    458   listener.Reply("go");
    459 
    460   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    461   event_router()->GattServiceRemoved(device0_.get(), service0_.get());
    462   event_router()->DeviceRemoved(mock_adapter_, device0_.get());
    463 }
    464 
    465 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetCharacteristic) {
    466   ResultCatcher catcher;
    467   catcher.RestrictToProfile(browser()->profile());
    468 
    469   event_router()->DeviceAdded(mock_adapter_, device0_.get());
    470   event_router()->GattServiceAdded(device0_.get(), service0_.get());
    471   event_router()->GattCharacteristicAdded(service0_.get(), chrc0_.get());
    472 
    473   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    474       .Times(4)
    475       .WillOnce(Return(static_cast<BluetoothDevice*>(NULL)))
    476       .WillRepeatedly(Return(device0_.get()));
    477 
    478   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    479       .Times(3)
    480       .WillOnce(Return(static_cast<BluetoothGattService*>(NULL)))
    481       .WillRepeatedly(Return(service0_.get()));
    482 
    483   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
    484       .Times(2)
    485       .WillOnce(Return(static_cast<BluetoothGattCharacteristic*>(NULL)))
    486       .WillOnce(Return(chrc0_.get()));
    487 
    488   // Load the extension and wait for first test.
    489   ExtensionTestMessageListener listener("ready", true);
    490   ASSERT_TRUE(LoadExtension(
    491       test_data_dir_.AppendASCII("bluetooth_low_energy/get_characteristic")));
    492   EXPECT_TRUE(listener.WaitUntilSatisfied());
    493 
    494   listener.Reply("go");
    495 
    496   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    497 
    498   event_router()->GattCharacteristicRemoved(service0_.get(), chrc0_.get());
    499   event_router()->GattServiceRemoved(device0_.get(), service0_.get());
    500   event_router()->DeviceRemoved(mock_adapter_, device0_.get());
    501 }
    502 
    503 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, CharacteristicProperties) {
    504   ResultCatcher catcher;
    505   catcher.RestrictToProfile(browser()->profile());
    506 
    507   event_router()->DeviceAdded(mock_adapter_, device0_.get());
    508   event_router()->GattServiceAdded(device0_.get(), service0_.get());
    509   event_router()->GattCharacteristicAdded(service0_.get(), chrc0_.get());
    510 
    511   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    512       .Times(12)
    513       .WillRepeatedly(Return(device0_.get()));
    514   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    515       .Times(12)
    516       .WillRepeatedly(Return(service0_.get()));
    517   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
    518       .Times(12)
    519       .WillRepeatedly(Return(chrc0_.get()));
    520   EXPECT_CALL(*chrc0_, GetProperties())
    521       .Times(12)
    522       .WillOnce(Return(BluetoothGattCharacteristic::kPropertyNone))
    523       .WillOnce(Return(BluetoothGattCharacteristic::kPropertyBroadcast))
    524       .WillOnce(Return(BluetoothGattCharacteristic::kPropertyRead))
    525       .WillOnce(
    526            Return(BluetoothGattCharacteristic::kPropertyWriteWithoutResponse))
    527       .WillOnce(Return(BluetoothGattCharacteristic::kPropertyWrite))
    528       .WillOnce(Return(BluetoothGattCharacteristic::kPropertyNotify))
    529       .WillOnce(Return(BluetoothGattCharacteristic::kPropertyIndicate))
    530       .WillOnce(Return(
    531           BluetoothGattCharacteristic::kPropertyAuthenticatedSignedWrites))
    532       .WillOnce(
    533            Return(BluetoothGattCharacteristic::kPropertyExtendedProperties))
    534       .WillOnce(Return(BluetoothGattCharacteristic::kPropertyReliableWrite))
    535       .WillOnce(
    536            Return(BluetoothGattCharacteristic::kPropertyWritableAuxiliaries))
    537       .WillOnce(Return(
    538           BluetoothGattCharacteristic::kPropertyBroadcast |
    539           BluetoothGattCharacteristic::kPropertyRead |
    540           BluetoothGattCharacteristic::kPropertyWriteWithoutResponse |
    541           BluetoothGattCharacteristic::kPropertyWrite |
    542           BluetoothGattCharacteristic::kPropertyNotify |
    543           BluetoothGattCharacteristic::kPropertyIndicate |
    544           BluetoothGattCharacteristic::kPropertyAuthenticatedSignedWrites |
    545           BluetoothGattCharacteristic::kPropertyExtendedProperties |
    546           BluetoothGattCharacteristic::kPropertyReliableWrite |
    547           BluetoothGattCharacteristic::kPropertyWritableAuxiliaries));
    548 
    549   ExtensionTestMessageListener listener("ready", true);
    550   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
    551       "bluetooth_low_energy/characteristic_properties")));
    552   EXPECT_TRUE(listener.WaitUntilSatisfied());
    553 
    554   listener.Reply("go");
    555 
    556   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    557 
    558   event_router()->GattCharacteristicRemoved(service0_.get(), chrc0_.get());
    559   event_router()->GattServiceRemoved(device0_.get(), service0_.get());
    560   event_router()->DeviceRemoved(mock_adapter_, device0_.get());
    561 }
    562 
    563 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetRemovedCharacteristic) {
    564   ResultCatcher catcher;
    565   catcher.RestrictToProfile(browser()->profile());
    566 
    567   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    568       .Times(1)
    569       .WillOnce(Return(device0_.get()));
    570   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    571       .Times(1)
    572       .WillOnce(Return(service0_.get()));
    573   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
    574       .Times(1)
    575       .WillOnce(Return(chrc0_.get()));
    576 
    577   event_router()->DeviceAdded(mock_adapter_, device0_.get());
    578   event_router()->GattServiceAdded(device0_.get(), service0_.get());
    579   event_router()->GattCharacteristicAdded(service0_.get(), chrc0_.get());
    580 
    581   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
    582       "bluetooth_low_energy/get_removed_characteristic")));
    583 
    584   ExtensionTestMessageListener listener("ready", true);
    585   EXPECT_TRUE(listener.WaitUntilSatisfied());
    586   testing::Mock::VerifyAndClearExpectations(mock_adapter_);
    587   testing::Mock::VerifyAndClearExpectations(device0_.get());
    588   testing::Mock::VerifyAndClearExpectations(service0_.get());
    589 
    590   EXPECT_CALL(*mock_adapter_, GetDevice(_)).Times(0);
    591   EXPECT_CALL(*device0_, GetGattService(_)).Times(0);
    592   EXPECT_CALL(*service0_, GetCharacteristic(_)).Times(0);
    593 
    594   event_router()->GattCharacteristicRemoved(service0_.get(), chrc0_.get());
    595 
    596   listener.Reply("go");
    597   listener.Reset();
    598   EXPECT_TRUE(listener.WaitUntilSatisfied());
    599 
    600   listener.Reply("go");
    601 
    602   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    603   event_router()->GattServiceRemoved(device0_.get(), service0_.get());
    604   event_router()->DeviceRemoved(mock_adapter_, device0_.get());
    605 }
    606 
    607 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, CharacteristicValueChanged) {
    608   ResultCatcher catcher;
    609   catcher.RestrictToProfile(browser()->profile());
    610 
    611   // Cause events to be sent to the extension.
    612   event_router()->DeviceAdded(mock_adapter_, device0_.get());
    613   event_router()->GattServiceAdded(device0_.get(), service0_.get());
    614   event_router()->GattServiceAdded(device0_.get(), service1_.get());
    615   event_router()->GattCharacteristicAdded(service0_.get(), chrc0_.get());
    616   event_router()->GattCharacteristicAdded(service1_.get(), chrc2_.get());
    617 
    618   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    619       .Times(2)
    620       .WillRepeatedly(Return(device0_.get()));
    621   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    622       .Times(1)
    623       .WillOnce(Return(service0_.get()));
    624   EXPECT_CALL(*device0_, GetGattService(kTestServiceId1))
    625       .Times(1)
    626       .WillOnce(Return(service1_.get()));
    627   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
    628       .Times(1)
    629       .WillOnce(Return(chrc0_.get()));
    630   EXPECT_CALL(*service1_, GetCharacteristic(kTestCharacteristicId2))
    631       .Times(1)
    632       .WillOnce(Return(chrc2_.get()));
    633 
    634   BluetoothGattNotifySession* session0 =
    635       new testing::NiceMock<MockBluetoothGattNotifySession>(
    636           kTestCharacteristicId0);
    637   BluetoothGattNotifySession* session1 =
    638       new testing::NiceMock<MockBluetoothGattNotifySession>(
    639           kTestCharacteristicId2);
    640 
    641   EXPECT_CALL(*chrc0_, StartNotifySession(_, _))
    642       .Times(1)
    643       .WillOnce(
    644           InvokeCallbackWithScopedPtrArg<0, BluetoothGattNotifySession>(
    645               session0));
    646   EXPECT_CALL(*chrc2_, StartNotifySession(_, _))
    647       .Times(1)
    648       .WillOnce(
    649           InvokeCallbackWithScopedPtrArg<0, BluetoothGattNotifySession>(
    650               session1));
    651 
    652   ExtensionTestMessageListener listener("ready", true);
    653   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
    654       "bluetooth_low_energy/characteristic_value_changed")));
    655 
    656   EXPECT_TRUE(listener.WaitUntilSatisfied());
    657 
    658   std::vector<uint8> value;
    659   event_router()->GattCharacteristicValueChanged(
    660       service0_.get(), chrc0_.get(), value);
    661   event_router()->GattCharacteristicValueChanged(
    662       service1_.get(), chrc2_.get(), value);
    663 
    664   listener.Reply("go");
    665 
    666   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    667   event_router()->GattCharacteristicRemoved(service1_.get(), chrc2_.get());
    668   event_router()->GattCharacteristicRemoved(service0_.get(), chrc0_.get());
    669   event_router()->GattServiceRemoved(device0_.get(), service1_.get());
    670   event_router()->GattServiceRemoved(device0_.get(), service0_.get());
    671   event_router()->DeviceRemoved(mock_adapter_, device0_.get());
    672 }
    673 
    674 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, ReadCharacteristicValue) {
    675   ResultCatcher catcher;
    676   catcher.RestrictToProfile(browser()->profile());
    677 
    678   event_router()->DeviceAdded(mock_adapter_, device0_.get());
    679   event_router()->GattServiceAdded(device0_.get(), service0_.get());
    680   event_router()->GattCharacteristicAdded(service0_.get(), chrc0_.get());
    681 
    682   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    683       .Times(3)
    684       .WillRepeatedly(Return(device0_.get()));
    685 
    686   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    687       .Times(3)
    688       .WillRepeatedly(Return(service0_.get()));
    689 
    690   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
    691       .Times(3)
    692       .WillRepeatedly(Return(chrc0_.get()));
    693 
    694   std::vector<uint8> value;
    695   EXPECT_CALL(*chrc0_, ReadRemoteCharacteristic(_, _))
    696       .Times(2)
    697       .WillOnce(InvokeCallbackArgument<1>())
    698       .WillOnce(InvokeCallbackArgument<0>(value));
    699 
    700   ExtensionTestMessageListener listener("ready", true);
    701   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
    702       "bluetooth_low_energy/read_characteristic_value")));
    703   EXPECT_TRUE(listener.WaitUntilSatisfied());
    704 
    705   listener.Reply("go");
    706 
    707   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    708 
    709   event_router()->GattCharacteristicRemoved(service0_.get(), chrc0_.get());
    710   event_router()->GattServiceRemoved(device0_.get(), service0_.get());
    711   event_router()->DeviceRemoved(mock_adapter_, device0_.get());
    712 }
    713 
    714 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, WriteCharacteristicValue) {
    715   ResultCatcher catcher;
    716   catcher.RestrictToProfile(browser()->profile());
    717 
    718   event_router()->DeviceAdded(mock_adapter_, device0_.get());
    719   event_router()->GattServiceAdded(device0_.get(), service0_.get());
    720   event_router()->GattCharacteristicAdded(service0_.get(), chrc0_.get());
    721 
    722   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    723       .Times(3)
    724       .WillRepeatedly(Return(device0_.get()));
    725 
    726   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    727       .Times(3)
    728       .WillRepeatedly(Return(service0_.get()));
    729 
    730   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
    731       .Times(3)
    732       .WillRepeatedly(Return(chrc0_.get()));
    733 
    734   std::vector<uint8> write_value;
    735   EXPECT_CALL(*chrc0_, WriteRemoteCharacteristic(_, _, _))
    736       .Times(2)
    737       .WillOnce(InvokeCallbackArgument<2>())
    738       .WillOnce(DoAll(SaveArg<0>(&write_value), InvokeCallbackArgument<1>()));
    739 
    740   EXPECT_CALL(*chrc0_, GetValue()).Times(1).WillOnce(ReturnRef(write_value));
    741 
    742   ExtensionTestMessageListener listener("ready", true);
    743   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
    744       "bluetooth_low_energy/write_characteristic_value")));
    745   EXPECT_TRUE(listener.WaitUntilSatisfied());
    746 
    747   listener.Reply("go");
    748 
    749   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    750 
    751   event_router()->GattCharacteristicRemoved(service0_.get(), chrc0_.get());
    752   event_router()->GattServiceRemoved(device0_.get(), service0_.get());
    753   event_router()->DeviceRemoved(mock_adapter_, device0_.get());
    754 }
    755 
    756 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetDescriptors) {
    757   ResultCatcher catcher;
    758   catcher.RestrictToProfile(browser()->profile());
    759 
    760   std::vector<BluetoothGattDescriptor*> descriptors;
    761   descriptors.push_back(desc0_.get());
    762   descriptors.push_back(desc1_.get());
    763 
    764   event_router()->DeviceAdded(mock_adapter_, device0_.get());
    765   event_router()->GattServiceAdded(device0_.get(), service0_.get());
    766   event_router()->GattCharacteristicAdded(service0_.get(), chrc0_.get());
    767 
    768   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    769       .Times(3)
    770       .WillRepeatedly(Return(device0_.get()));
    771   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    772       .Times(3)
    773       .WillRepeatedly(Return(service0_.get()));
    774   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
    775       .Times(3)
    776       .WillOnce(Return(static_cast<BluetoothGattCharacteristic*>(NULL)))
    777       .WillRepeatedly(Return(chrc0_.get()));
    778   EXPECT_CALL(*chrc0_, GetDescriptors())
    779       .Times(2)
    780       .WillOnce(Return(std::vector<BluetoothGattDescriptor*>()))
    781       .WillOnce(Return(descriptors));
    782 
    783   ExtensionTestMessageListener listener("ready", true);
    784   ASSERT_TRUE(LoadExtension(
    785       test_data_dir_.AppendASCII("bluetooth_low_energy/get_descriptors")));
    786   EXPECT_TRUE(listener.WaitUntilSatisfied());
    787 
    788   listener.Reply("go");
    789 
    790   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    791 
    792   event_router()->GattCharacteristicRemoved(service0_.get(), chrc0_.get());
    793   event_router()->GattServiceRemoved(device0_.get(), service0_.get());
    794   event_router()->DeviceRemoved(mock_adapter_, device0_.get());
    795 }
    796 
    797 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetDescriptor) {
    798   ResultCatcher catcher;
    799   catcher.RestrictToProfile(browser()->profile());
    800 
    801   event_router()->DeviceAdded(mock_adapter_, device0_.get());
    802   event_router()->GattServiceAdded(device0_.get(), service0_.get());
    803   event_router()->GattCharacteristicAdded(service0_.get(), chrc0_.get());
    804   event_router()->GattDescriptorAdded(chrc0_.get(), desc0_.get());
    805 
    806   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    807       .Times(5)
    808       .WillOnce(Return(static_cast<BluetoothDevice*>(NULL)))
    809       .WillRepeatedly(Return(device0_.get()));
    810 
    811   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    812       .Times(4)
    813       .WillOnce(Return(static_cast<BluetoothGattService*>(NULL)))
    814       .WillRepeatedly(Return(service0_.get()));
    815 
    816   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
    817       .Times(3)
    818       .WillOnce(Return(static_cast<BluetoothGattCharacteristic*>(NULL)))
    819       .WillRepeatedly(Return(chrc0_.get()));
    820 
    821   EXPECT_CALL(*chrc0_, GetDescriptor(kTestDescriptorId0))
    822       .Times(2)
    823       .WillOnce(Return(static_cast<BluetoothGattDescriptor*>(NULL)))
    824       .WillOnce(Return(desc0_.get()));
    825 
    826   // Load the extension and wait for first test.
    827   ExtensionTestMessageListener listener("ready", true);
    828   ASSERT_TRUE(LoadExtension(
    829       test_data_dir_.AppendASCII("bluetooth_low_energy/get_descriptor")));
    830   EXPECT_TRUE(listener.WaitUntilSatisfied());
    831 
    832   listener.Reply("go");
    833 
    834   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    835 
    836   event_router()->GattDescriptorRemoved(chrc0_.get(), desc0_.get());
    837   event_router()->GattCharacteristicRemoved(service0_.get(), chrc0_.get());
    838   event_router()->GattServiceRemoved(device0_.get(), service0_.get());
    839   event_router()->DeviceRemoved(mock_adapter_, device0_.get());
    840 }
    841 
    842 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GetRemovedDescriptor) {
    843   ResultCatcher catcher;
    844   catcher.RestrictToProfile(browser()->profile());
    845 
    846   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    847       .Times(1)
    848       .WillOnce(Return(device0_.get()));
    849   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    850       .Times(1)
    851       .WillOnce(Return(service0_.get()));
    852   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
    853       .Times(1)
    854       .WillOnce(Return(chrc0_.get()));
    855   EXPECT_CALL(*chrc0_, GetDescriptor(kTestDescriptorId0))
    856       .Times(1)
    857       .WillOnce(Return(desc0_.get()));
    858 
    859   event_router()->DeviceAdded(mock_adapter_, device0_.get());
    860   event_router()->GattServiceAdded(device0_.get(), service0_.get());
    861   event_router()->GattCharacteristicAdded(service0_.get(), chrc0_.get());
    862   event_router()->GattDescriptorAdded(chrc0_.get(), desc0_.get());
    863 
    864   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
    865       "bluetooth_low_energy/get_removed_descriptor")));
    866 
    867   ExtensionTestMessageListener listener("ready", true);
    868   EXPECT_TRUE(listener.WaitUntilSatisfied());
    869   testing::Mock::VerifyAndClearExpectations(mock_adapter_);
    870   testing::Mock::VerifyAndClearExpectations(device0_.get());
    871   testing::Mock::VerifyAndClearExpectations(service0_.get());
    872   testing::Mock::VerifyAndClearExpectations(chrc0_.get());
    873 
    874   EXPECT_CALL(*mock_adapter_, GetDevice(_)).Times(0);
    875   EXPECT_CALL(*device0_, GetGattService(_)).Times(0);
    876   EXPECT_CALL(*service0_, GetCharacteristic(_)).Times(0);
    877   EXPECT_CALL(*chrc0_, GetDescriptor(_)).Times(0);
    878 
    879   event_router()->GattDescriptorRemoved(chrc0_.get(), desc0_.get());
    880 
    881   listener.Reply("go");
    882   listener.Reset();
    883   EXPECT_TRUE(listener.WaitUntilSatisfied());
    884 
    885   listener.Reply("go");
    886 
    887   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    888   event_router()->GattCharacteristicRemoved(service0_.get(), chrc0_.get());
    889   event_router()->GattServiceRemoved(device0_.get(), service0_.get());
    890   event_router()->DeviceRemoved(mock_adapter_, device0_.get());
    891 }
    892 
    893 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, DescriptorValueChanged) {
    894   ResultCatcher catcher;
    895   catcher.RestrictToProfile(browser()->profile());
    896 
    897   event_router()->DeviceAdded(mock_adapter_, device0_.get());
    898   event_router()->GattServiceAdded(device0_.get(), service0_.get());
    899   event_router()->GattCharacteristicAdded(service0_.get(), chrc0_.get());
    900   event_router()->GattDescriptorAdded(chrc0_.get(), desc0_.get());
    901   event_router()->GattDescriptorAdded(chrc0_.get(), desc1_.get());
    902 
    903   // Load the extension and let it set up.
    904   ExtensionTestMessageListener listener("ready", true);
    905   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
    906       "bluetooth_low_energy/descriptor_value_changed")));
    907 
    908   // Cause events to be sent to the extension.
    909   std::vector<uint8> value;
    910   event_router()->GattDescriptorValueChanged(chrc0_.get(), desc0_.get(), value);
    911   event_router()->GattDescriptorValueChanged(chrc0_.get(), desc1_.get(), value);
    912 
    913   EXPECT_TRUE(listener.WaitUntilSatisfied());
    914   listener.Reply("go");
    915 
    916   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    917   event_router()->GattDescriptorRemoved(chrc0_.get(), desc1_.get());
    918   event_router()->GattDescriptorRemoved(chrc0_.get(), desc0_.get());
    919   event_router()->GattCharacteristicRemoved(service0_.get(), chrc0_.get());
    920   event_router()->GattServiceRemoved(device0_.get(), service0_.get());
    921   event_router()->DeviceRemoved(mock_adapter_, device0_.get());
    922 }
    923 
    924 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, ReadDescriptorValue) {
    925   ResultCatcher catcher;
    926   catcher.RestrictToProfile(browser()->profile());
    927 
    928   event_router()->DeviceAdded(mock_adapter_, device0_.get());
    929   event_router()->GattServiceAdded(device0_.get(), service0_.get());
    930   event_router()->GattCharacteristicAdded(service0_.get(), chrc0_.get());
    931   event_router()->GattDescriptorAdded(chrc0_.get(), desc0_.get());
    932 
    933   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    934       .Times(3)
    935       .WillRepeatedly(Return(device0_.get()));
    936 
    937   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    938       .Times(3)
    939       .WillRepeatedly(Return(service0_.get()));
    940 
    941   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
    942       .Times(3)
    943       .WillRepeatedly(Return(chrc0_.get()));
    944 
    945   EXPECT_CALL(*chrc0_, GetDescriptor(kTestDescriptorId0))
    946       .Times(3)
    947       .WillRepeatedly(Return(desc0_.get()));
    948 
    949   std::vector<uint8> value;
    950   EXPECT_CALL(*desc0_, ReadRemoteDescriptor(_, _))
    951       .Times(2)
    952       .WillOnce(InvokeCallbackArgument<1>())
    953       .WillOnce(InvokeCallbackArgument<0>(value));
    954 
    955   ExtensionTestMessageListener listener("ready", true);
    956   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
    957       "bluetooth_low_energy/read_descriptor_value")));
    958   EXPECT_TRUE(listener.WaitUntilSatisfied());
    959 
    960   listener.Reply("go");
    961 
    962   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    963 
    964   event_router()->GattDescriptorRemoved(chrc0_.get(), desc0_.get());
    965   event_router()->GattCharacteristicRemoved(service0_.get(), chrc0_.get());
    966   event_router()->GattServiceRemoved(device0_.get(), service0_.get());
    967   event_router()->DeviceRemoved(mock_adapter_, device0_.get());
    968 }
    969 
    970 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, WriteDescriptorValue) {
    971   ResultCatcher catcher;
    972   catcher.RestrictToProfile(browser()->profile());
    973 
    974   event_router()->DeviceAdded(mock_adapter_, device0_.get());
    975   event_router()->GattServiceAdded(device0_.get(), service0_.get());
    976   event_router()->GattCharacteristicAdded(service0_.get(), chrc0_.get());
    977   event_router()->GattDescriptorAdded(chrc0_.get(), desc0_.get());
    978 
    979   EXPECT_CALL(*mock_adapter_, GetDevice(_))
    980       .Times(3)
    981       .WillRepeatedly(Return(device0_.get()));
    982 
    983   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
    984       .Times(3)
    985       .WillRepeatedly(Return(service0_.get()));
    986 
    987   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
    988       .Times(3)
    989       .WillRepeatedly(Return(chrc0_.get()));
    990 
    991   EXPECT_CALL(*chrc0_, GetDescriptor(kTestDescriptorId0))
    992       .Times(3)
    993       .WillRepeatedly(Return(desc0_.get()));
    994 
    995   std::vector<uint8> write_value;
    996   EXPECT_CALL(*desc0_, WriteRemoteDescriptor(_, _, _))
    997       .Times(2)
    998       .WillOnce(InvokeCallbackArgument<2>())
    999       .WillOnce(DoAll(SaveArg<0>(&write_value), InvokeCallbackArgument<1>()));
   1000 
   1001   EXPECT_CALL(*desc0_, GetValue()).Times(1).WillOnce(ReturnRef(write_value));
   1002 
   1003   ExtensionTestMessageListener listener("ready", true);
   1004   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
   1005       "bluetooth_low_energy/write_descriptor_value")));
   1006   EXPECT_TRUE(listener.WaitUntilSatisfied());
   1007 
   1008   listener.Reply("go");
   1009 
   1010   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
   1011 
   1012   event_router()->GattDescriptorRemoved(chrc0_.get(), desc0_.get());
   1013   event_router()->GattCharacteristicRemoved(service0_.get(), chrc0_.get());
   1014   event_router()->GattServiceRemoved(device0_.get(), service0_.get());
   1015   event_router()->DeviceRemoved(mock_adapter_, device0_.get());
   1016 }
   1017 
   1018 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, PermissionDenied) {
   1019   ResultCatcher catcher;
   1020   catcher.RestrictToProfile(browser()->profile());
   1021 
   1022   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
   1023       "bluetooth_low_energy/permission_denied")));
   1024   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
   1025 }
   1026 
   1027 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, UuidPermissionMethods) {
   1028   ResultCatcher catcher;
   1029   catcher.RestrictToProfile(browser()->profile());
   1030 
   1031   event_router()->DeviceAdded(mock_adapter_, device0_.get());
   1032   event_router()->GattServiceAdded(device0_.get(), service0_.get());
   1033   event_router()->GattCharacteristicAdded(service0_.get(), chrc0_.get());
   1034   event_router()->GattDescriptorAdded(chrc0_.get(), desc0_.get());
   1035 
   1036   std::vector<BluetoothGattService*> services;
   1037   services.push_back(service0_.get());
   1038 
   1039   EXPECT_CALL(*mock_adapter_, GetDevice(_))
   1040       .WillRepeatedly(Return(device0_.get()));
   1041   EXPECT_CALL(*device0_, GetGattServices()).WillOnce(Return(services));
   1042   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
   1043       .WillRepeatedly(Return(service0_.get()));
   1044   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
   1045       .WillRepeatedly(Return(chrc0_.get()));
   1046   EXPECT_CALL(*chrc0_, GetDescriptor(kTestDescriptorId0))
   1047       .WillRepeatedly(Return(desc0_.get()));
   1048 
   1049   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
   1050       "bluetooth_low_energy/uuid_permission_methods")));
   1051   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
   1052 
   1053   event_router()->GattDescriptorRemoved(chrc0_.get(), desc0_.get());
   1054   event_router()->GattCharacteristicRemoved(service0_.get(), chrc0_.get());
   1055   event_router()->GattServiceRemoved(device0_.get(), service0_.get());
   1056   event_router()->DeviceRemoved(mock_adapter_, device0_.get());
   1057 }
   1058 
   1059 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, UuidPermissionEvents) {
   1060   ResultCatcher catcher;
   1061   catcher.RestrictToProfile(browser()->profile());
   1062 
   1063   ExtensionTestMessageListener listener("ready", true);
   1064   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
   1065       "bluetooth_low_energy/uuid_permission_events")));
   1066 
   1067   // Cause events to be sent to the extension.
   1068   event_router()->DeviceAdded(mock_adapter_, device0_.get());
   1069   event_router()->GattServiceAdded(device0_.get(), service0_.get());
   1070   event_router()->GattCharacteristicAdded(service0_.get(), chrc0_.get());
   1071   event_router()->GattDescriptorAdded(chrc0_.get(), desc0_.get());
   1072 
   1073   std::vector<uint8> value;
   1074   event_router()->GattCharacteristicValueChanged(
   1075       service0_.get(), chrc0_.get(), value);
   1076   event_router()->GattDescriptorValueChanged(chrc0_.get(), desc0_.get(), value);
   1077   event_router()->GattServiceChanged(service0_.get());
   1078 
   1079   EXPECT_TRUE(listener.WaitUntilSatisfied());
   1080   listener.Reply("go");
   1081   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
   1082 
   1083   event_router()->GattDescriptorRemoved(chrc0_.get(), desc0_.get());
   1084   event_router()->GattCharacteristicRemoved(service0_.get(), chrc0_.get());
   1085   event_router()->GattServiceRemoved(device0_.get(), service0_.get());
   1086   event_router()->DeviceRemoved(mock_adapter_, device0_.get());
   1087 }
   1088 
   1089 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, GattConnection) {
   1090   ResultCatcher catcher;
   1091   catcher.RestrictToProfile(browser()->profile());
   1092 
   1093   event_router()->DeviceAdded(mock_adapter_, device0_.get());
   1094   event_router()->DeviceAdded(mock_adapter_, device1_.get());
   1095 
   1096   EXPECT_CALL(*mock_adapter_, GetDevice(_))
   1097       .WillRepeatedly(Return(static_cast<BluetoothDevice*>(NULL)));
   1098   EXPECT_CALL(*mock_adapter_, GetDevice(kTestLeDeviceAddress0))
   1099       .WillRepeatedly(Return(device0_.get()));
   1100   EXPECT_CALL(*mock_adapter_, GetDevice(kTestLeDeviceAddress1))
   1101       .WillRepeatedly(Return(device1_.get()));
   1102   EXPECT_CALL(*device0_, CreateGattConnection(_, _))
   1103       .Times(3)
   1104       .WillOnce(InvokeCallbackArgument<1>(BluetoothDevice::ERROR_FAILED))
   1105       .WillOnce(InvokeCallbackWithScopedPtrArg<0, BluetoothGattConnection>(
   1106           CreateGattConnection(kTestLeDeviceAddress0,
   1107                                true /* expect_disconnect */)))
   1108       .WillOnce(InvokeCallbackWithScopedPtrArg<0, BluetoothGattConnection>(
   1109           CreateGattConnection(kTestLeDeviceAddress0,
   1110                                false /* expect_disconnect */)));
   1111   EXPECT_CALL(*device1_, CreateGattConnection(_, _))
   1112       .Times(1)
   1113       .WillOnce(InvokeCallbackWithScopedPtrArg<0, BluetoothGattConnection>(
   1114           CreateGattConnection(kTestLeDeviceAddress1,
   1115                                true /* expect_disconnect */)));
   1116 
   1117   ASSERT_TRUE(LoadExtension(
   1118       test_data_dir_.AppendASCII("bluetooth_low_energy/gatt_connection")));
   1119   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
   1120 
   1121   event_router()->DeviceRemoved(mock_adapter_, device1_.get());
   1122   event_router()->DeviceRemoved(mock_adapter_, device0_.get());
   1123 }
   1124 
   1125 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, ReconnectAfterDisconnected) {
   1126   ResultCatcher catcher;
   1127   catcher.RestrictToProfile(browser()->profile());
   1128 
   1129   event_router()->DeviceAdded(mock_adapter_, device0_.get());
   1130 
   1131   EXPECT_CALL(*mock_adapter_, GetDevice(kTestLeDeviceAddress0))
   1132       .WillRepeatedly(Return(device0_.get()));
   1133 
   1134   MockBluetoothGattConnection* first_conn =
   1135       static_cast<MockBluetoothGattConnection*>(CreateGattConnection(
   1136           kTestLeDeviceAddress0, false /* expect_disconnect */));
   1137   EXPECT_CALL(*first_conn, IsConnected())
   1138       .Times(2)
   1139       .WillOnce(Return(true))
   1140       .WillOnce(Return(false));
   1141 
   1142   EXPECT_CALL(*device0_, CreateGattConnection(_, _))
   1143       .Times(2)
   1144       .WillOnce(InvokeCallbackWithScopedPtrArg<0, BluetoothGattConnection>(
   1145           first_conn))
   1146       .WillOnce(InvokeCallbackWithScopedPtrArg<0, BluetoothGattConnection>(
   1147           CreateGattConnection(kTestLeDeviceAddress0,
   1148                                false /* expect_disconnect */)));
   1149 
   1150   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
   1151       "bluetooth_low_energy/reconnect_after_disconnected")));
   1152   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
   1153 
   1154   event_router()->DeviceRemoved(mock_adapter_, device0_.get());
   1155 }
   1156 
   1157 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, ConnectInProgress) {
   1158   ResultCatcher catcher;
   1159   catcher.RestrictToProfile(browser()->profile());
   1160 
   1161   event_router()->DeviceAdded(mock_adapter_, device0_.get());
   1162 
   1163   EXPECT_CALL(*mock_adapter_, GetDevice(kTestLeDeviceAddress0))
   1164       .WillRepeatedly(Return(device0_.get()));
   1165 
   1166   BluetoothDevice::GattConnectionCallback connect_callback;
   1167   base::Closure disconnect_callback;
   1168 
   1169   testing::NiceMock<MockBluetoothGattConnection>* conn =
   1170       new testing::NiceMock<MockBluetoothGattConnection>(
   1171           kTestLeDeviceAddress0);
   1172   scoped_ptr<BluetoothGattConnection> conn_ptr(conn);
   1173   EXPECT_CALL(*conn, Disconnect(_))
   1174       .Times(1)
   1175       .WillOnce(SaveArg<0>(&disconnect_callback));
   1176 
   1177   EXPECT_CALL(*device0_, CreateGattConnection(_, _))
   1178       .Times(1)
   1179       .WillOnce(SaveArg<0>(&connect_callback));
   1180 
   1181   ExtensionTestMessageListener listener("ready", true);
   1182   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
   1183       "bluetooth_low_energy/connect_in_progress")));
   1184 
   1185   listener.WaitUntilSatisfied();
   1186   connect_callback.Run(conn_ptr.Pass());
   1187 
   1188   listener.Reset();
   1189   listener.WaitUntilSatisfied();
   1190   disconnect_callback.Run();
   1191 
   1192   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
   1193 
   1194   event_router()->DeviceRemoved(mock_adapter_, device0_.get());
   1195 }
   1196 
   1197 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, StartStopNotifications) {
   1198   ResultCatcher catcher;
   1199   catcher.RestrictToProfile(browser()->profile());
   1200 
   1201   event_router()->DeviceAdded(mock_adapter_, device0_.get());
   1202   event_router()->GattServiceAdded(device0_.get(), service0_.get());
   1203   event_router()->GattServiceAdded(device0_.get(), service1_.get());
   1204   event_router()->GattCharacteristicAdded(service0_.get(), chrc0_.get());
   1205   event_router()->GattCharacteristicAdded(service0_.get(), chrc1_.get());
   1206   event_router()->GattCharacteristicAdded(service1_.get(), chrc2_.get());
   1207 
   1208   EXPECT_CALL(*mock_adapter_, GetDevice(_))
   1209       .WillRepeatedly(Return(device0_.get()));
   1210   EXPECT_CALL(*device0_, GetGattService(kTestServiceId0))
   1211       .WillRepeatedly(Return(service0_.get()));
   1212   EXPECT_CALL(*device0_, GetGattService(kTestServiceId1))
   1213       .WillRepeatedly(Return(service1_.get()));
   1214   EXPECT_CALL(*service1_, GetCharacteristic(kTestCharacteristicId2))
   1215       .Times(1)
   1216       .WillOnce(Return(chrc2_.get()));
   1217   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
   1218       .Times(2)
   1219       .WillRepeatedly(Return(chrc0_.get()));
   1220   EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId1))
   1221       .Times(1)
   1222       .WillOnce(Return(chrc1_.get()));
   1223 
   1224   BluetoothGattNotifySession* session0 =
   1225       new testing::NiceMock<MockBluetoothGattNotifySession>(
   1226           kTestCharacteristicId0);
   1227   MockBluetoothGattNotifySession* session1 =
   1228       new testing::NiceMock<MockBluetoothGattNotifySession>(
   1229           kTestCharacteristicId1);
   1230 
   1231   EXPECT_CALL(*session1, Stop(_))
   1232       .Times(1)
   1233       .WillOnce(InvokeCallbackArgument<0>());
   1234 
   1235   EXPECT_CALL(*chrc0_, StartNotifySession(_, _))
   1236       .Times(2)
   1237       .WillOnce(InvokeCallbackArgument<1>())
   1238       .WillOnce(
   1239           InvokeCallbackWithScopedPtrArg<0, BluetoothGattNotifySession>(
   1240               session0));
   1241   EXPECT_CALL(*chrc1_, StartNotifySession(_, _))
   1242       .Times(1)
   1243       .WillOnce(
   1244           InvokeCallbackWithScopedPtrArg<0, BluetoothGattNotifySession>(
   1245               session1));
   1246 
   1247   ExtensionTestMessageListener listener("ready", true);
   1248   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
   1249       "bluetooth_low_energy/start_stop_notifications")));
   1250 
   1251   EXPECT_TRUE(listener.WaitUntilSatisfied());
   1252 
   1253   std::vector<uint8> value;
   1254   event_router()->GattCharacteristicValueChanged(
   1255       service0_.get(), chrc0_.get(), value);
   1256   event_router()->GattCharacteristicValueChanged(
   1257       service0_.get(), chrc1_.get(), value);
   1258   event_router()->GattCharacteristicValueChanged(
   1259       service1_.get(), chrc2_.get(), value);
   1260 
   1261   listener.Reply("go");
   1262 
   1263   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
   1264   event_router()->GattCharacteristicRemoved(service1_.get(), chrc2_.get());
   1265   event_router()->GattCharacteristicRemoved(service0_.get(), chrc1_.get());
   1266   event_router()->GattCharacteristicRemoved(service0_.get(), chrc0_.get());
   1267   event_router()->GattServiceRemoved(device0_.get(), service1_.get());
   1268   event_router()->GattServiceRemoved(device0_.get(), service0_.get());
   1269   event_router()->DeviceRemoved(mock_adapter_, device0_.get());
   1270 }
   1271 
   1272 }  // namespace
   1273