Home | History | Annotate | Download | only in bluetooth
      1 // Copyright (c) 2012 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 <string>
      6 
      7 #include "base/memory/ref_counted.h"
      8 #include "base/memory/scoped_ptr.h"
      9 #include "base/message_loop/message_loop.h"
     10 #include "base/run_loop.h"
     11 #include "chrome/browser/extensions/api/bluetooth/bluetooth_event_router.h"
     12 #include "chrome/browser/extensions/event_names.h"
     13 #include "chrome/browser/extensions/event_router.h"
     14 #include "chrome/browser/extensions/extension_system_factory.h"
     15 #include "chrome/browser/extensions/test_extension_system.h"
     16 #include "chrome/test/base/testing_profile.h"
     17 #include "content/public/test/test_browser_thread.h"
     18 #include "device/bluetooth/test/mock_bluetooth_adapter.h"
     19 #include "device/bluetooth/test/mock_bluetooth_device.h"
     20 #include "device/bluetooth/test/mock_bluetooth_profile.h"
     21 #include "device/bluetooth/test/mock_bluetooth_socket.h"
     22 #include "testing/gmock/include/gmock/gmock.h"
     23 #include "testing/gtest/include/gtest/gtest.h"
     24 
     25 namespace {
     26 
     27 const char kAudioProfileUuid[] = "audio profile uuid";
     28 const char kHealthProfileUuid[] = "health profile uuid";
     29 
     30 class FakeEventRouter : public extensions::EventRouter {
     31  public:
     32   explicit FakeEventRouter(Profile* profile) : EventRouter(profile, NULL) {}
     33 
     34   virtual void DispatchEventToExtension(
     35       const std::string& extension_id,
     36       scoped_ptr<extensions::Event> event) OVERRIDE {
     37     extension_id_ = extension_id;
     38     event_ = event.Pass();
     39   }
     40 
     41   std::string extension_id() const {
     42     return extension_id_;
     43   }
     44 
     45   const extensions::Event* event() const {
     46     return event_.get();
     47   }
     48 
     49  private:
     50   std::string extension_id_;
     51   scoped_ptr<extensions::Event> event_;
     52 
     53   DISALLOW_COPY_AND_ASSIGN(FakeEventRouter);
     54 };
     55 
     56 class FakeExtensionSystem : public extensions::TestExtensionSystem {
     57  public:
     58   explicit FakeExtensionSystem(Profile* profile)
     59       : extensions::TestExtensionSystem(profile) {}
     60 
     61   virtual extensions::EventRouter* event_router() OVERRIDE {
     62     if (!fake_event_router_)
     63       fake_event_router_.reset(new FakeEventRouter(profile_));
     64     return fake_event_router_.get();
     65   }
     66 
     67  private:
     68   scoped_ptr<FakeEventRouter> fake_event_router_;
     69 
     70   DISALLOW_COPY_AND_ASSIGN(FakeExtensionSystem);
     71 };
     72 
     73 BrowserContextKeyedService* BuildFakeExtensionSystem(
     74     content::BrowserContext* profile) {
     75   return new FakeExtensionSystem(static_cast<Profile*>(profile));
     76 }
     77 
     78 }  // namespace
     79 
     80 namespace extensions {
     81 
     82 class ExtensionBluetoothEventRouterTest : public testing::Test {
     83  public:
     84   ExtensionBluetoothEventRouterTest()
     85       : mock_adapter_(new testing::StrictMock<device::MockBluetoothAdapter>()),
     86         test_profile_(new TestingProfile()),
     87         router_(test_profile_.get()),
     88         ui_thread_(content::BrowserThread::UI, &message_loop_) {
     89     router_.SetAdapterForTest(mock_adapter_);
     90   }
     91 
     92   virtual void TearDown() OVERRIDE {
     93     // Some profile-dependent services rely on UI thread to clean up. We make
     94     // sure they are properly cleaned up by running the UI message loop until
     95     // idle.
     96     test_profile_.reset(NULL);
     97     base::RunLoop run_loop;
     98     run_loop.RunUntilIdle();
     99   }
    100 
    101  protected:
    102   testing::StrictMock<device::MockBluetoothAdapter>* mock_adapter_;
    103   testing::NiceMock<device::MockBluetoothProfile> mock_audio_profile_;
    104   testing::NiceMock<device::MockBluetoothProfile> mock_health_profile_;
    105   scoped_ptr<TestingProfile> test_profile_;
    106   ExtensionBluetoothEventRouter router_;
    107   base::MessageLoopForUI message_loop_;
    108   content::TestBrowserThread ui_thread_;
    109 };
    110 
    111 TEST_F(ExtensionBluetoothEventRouterTest, BluetoothEventListener) {
    112   router_.OnListenerAdded();
    113   EXPECT_CALL(*mock_adapter_, RemoveObserver(testing::_)).Times(1);
    114   router_.OnListenerRemoved();
    115 }
    116 
    117 TEST_F(ExtensionBluetoothEventRouterTest, MultipleBluetoothEventListeners) {
    118   router_.OnListenerAdded();
    119   router_.OnListenerAdded();
    120   router_.OnListenerAdded();
    121   router_.OnListenerRemoved();
    122   router_.OnListenerRemoved();
    123   EXPECT_CALL(*mock_adapter_, RemoveObserver(testing::_)).Times(1);
    124   router_.OnListenerRemoved();
    125 }
    126 
    127 TEST_F(ExtensionBluetoothEventRouterTest, Profiles) {
    128   EXPECT_FALSE(router_.HasProfile(kAudioProfileUuid));
    129   EXPECT_FALSE(router_.HasProfile(kHealthProfileUuid));
    130 
    131   router_.AddProfile(kAudioProfileUuid, &mock_audio_profile_);
    132   router_.AddProfile(kHealthProfileUuid, &mock_health_profile_);
    133   EXPECT_TRUE(router_.HasProfile(kAudioProfileUuid));
    134   EXPECT_TRUE(router_.HasProfile(kHealthProfileUuid));
    135 
    136   EXPECT_CALL(mock_audio_profile_, Unregister()).Times(1);
    137   router_.RemoveProfile(kAudioProfileUuid);
    138   EXPECT_FALSE(router_.HasProfile(kAudioProfileUuid));
    139   EXPECT_TRUE(router_.HasProfile(kHealthProfileUuid));
    140 
    141   // Make sure remaining profiles are unregistered in destructor.
    142   EXPECT_CALL(mock_health_profile_, Unregister()).Times(1);
    143   EXPECT_CALL(*mock_adapter_, RemoveObserver(testing::_)).Times(1);
    144 }
    145 
    146 TEST_F(ExtensionBluetoothEventRouterTest, DispatchConnectionEvent) {
    147   router_.AddProfile(kAudioProfileUuid, &mock_audio_profile_);
    148 
    149   FakeExtensionSystem* fake_extension_system =
    150       static_cast<FakeExtensionSystem*>(ExtensionSystemFactory::GetInstance()->
    151           SetTestingFactoryAndUse(test_profile_.get(),
    152                                   &BuildFakeExtensionSystem));
    153 
    154   const char test_extension_id[] = "test extension id";
    155   testing::NiceMock<device::MockBluetoothDevice> mock_device(
    156       mock_adapter_, 0, "device name", "device address", true, false);
    157   scoped_refptr<testing::NiceMock<device::MockBluetoothSocket> > mock_socket(
    158       new testing::NiceMock<device::MockBluetoothSocket>());
    159 
    160   router_.DispatchConnectionEvent(test_extension_id,
    161                                   kAudioProfileUuid,
    162                                   &mock_device,
    163                                   mock_socket);
    164 
    165   FakeEventRouter* fake_event_router =
    166       static_cast<FakeEventRouter*>(fake_extension_system->event_router());
    167 
    168   EXPECT_STREQ(test_extension_id, fake_event_router->extension_id().c_str());
    169   EXPECT_STREQ(event_names::kBluetoothOnConnection,
    170                fake_event_router->event()->event_name.c_str());
    171 
    172   base::ListValue* event_args = fake_event_router->event()->event_args.get();
    173   base::DictionaryValue* socket_value = NULL;
    174   ASSERT_TRUE(event_args->GetDictionary(0, &socket_value));
    175   int socket_id;
    176   ASSERT_TRUE(socket_value->GetInteger("id", &socket_id));
    177   EXPECT_EQ(mock_socket.get(), router_.GetSocket(socket_id).get());
    178 
    179   base::DictionaryValue* profile_value = NULL;
    180   ASSERT_TRUE(socket_value->GetDictionary("profile", &profile_value));
    181   std::string profile_uuid;
    182   ASSERT_TRUE(profile_value->GetString("uuid", &profile_uuid));
    183   EXPECT_STREQ(kAudioProfileUuid, profile_uuid.c_str());
    184 
    185   EXPECT_CALL(*mock_adapter_, RemoveObserver(testing::_)).Times(1);
    186   router_.ReleaseSocket(socket_id);
    187 }
    188 
    189 TEST_F(ExtensionBluetoothEventRouterTest, DoNotDispatchConnectionEvent) {
    190   FakeExtensionSystem* fake_extension_system =
    191       static_cast<FakeExtensionSystem*>(ExtensionSystemFactory::GetInstance()->
    192           SetTestingFactoryAndUse(test_profile_.get(),
    193                                   &BuildFakeExtensionSystem));
    194   testing::NiceMock<device::MockBluetoothDevice> mock_device(
    195       mock_adapter_, 0, "device name", "device address", true, false);
    196   scoped_refptr<testing::NiceMock<device::MockBluetoothSocket> > mock_socket(
    197       new testing::NiceMock<device::MockBluetoothSocket>());
    198 
    199   // Connection event won't be dispatched for non-registered profiles.
    200   router_.DispatchConnectionEvent("test extension id",
    201                                   kAudioProfileUuid,
    202                                   &mock_device,
    203                                   mock_socket);
    204   FakeEventRouter* fake_event_router =
    205       static_cast<FakeEventRouter*>(fake_extension_system->event_router());
    206   EXPECT_TRUE(fake_event_router->event() == NULL);
    207 
    208   EXPECT_CALL(*mock_adapter_, RemoveObserver(testing::_)).Times(1);
    209 }
    210 
    211 }  // namespace extensions
    212