OLD | NEW |
| (Empty) |
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 <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/chrome_notification_types.h" | |
12 #include "chrome/browser/extensions/api/bluetooth/bluetooth_api.h" | |
13 #include "chrome/browser/extensions/api/bluetooth/bluetooth_event_router.h" | |
14 #include "chrome/browser/extensions/extension_system_factory.h" | |
15 #include "chrome/browser/extensions/test_extension_system.h" | |
16 #include "chrome/common/extensions/api/bluetooth.h" | |
17 #include "chrome/test/base/testing_browser_process.h" | |
18 #include "chrome/test/base/testing_profile.h" | |
19 #include "chrome/test/base/testing_profile_manager.h" | |
20 #include "content/public/browser/notification_service.h" | |
21 #include "content/public/test/test_browser_thread_bundle.h" | |
22 #include "device/bluetooth/test/mock_bluetooth_adapter.h" | |
23 #include "device/bluetooth/test/mock_bluetooth_device.h" | |
24 #include "device/bluetooth/test/mock_bluetooth_profile.h" | |
25 #include "device/bluetooth/test/mock_bluetooth_socket.h" | |
26 #include "extensions/browser/event_router.h" | |
27 #include "extensions/common/extension_builder.h" | |
28 #include "testing/gmock/include/gmock/gmock.h" | |
29 #include "testing/gtest/include/gtest/gtest.h" | |
30 | |
31 namespace { | |
32 | |
33 const char kTestExtensionId[] = "test extension id"; | |
34 const device::BluetoothUUID kAudioProfileUuid("1234"); | |
35 | |
36 static KeyedService* ApiResourceManagerTestFactory( | |
37 content::BrowserContext* context) { | |
38 content::BrowserThread::ID id; | |
39 CHECK(content::BrowserThread::GetCurrentThreadIdentifier(&id)); | |
40 return extensions::ApiResourceManager< | |
41 extensions::BluetoothApiSocket>::CreateApiResourceManagerForTest(context, | |
42 id); | |
43 } | |
44 | |
45 static KeyedService* BluetoothAPITestFactory(content::BrowserContext* context) { | |
46 content::BrowserThread::ID id; | |
47 CHECK(content::BrowserThread::GetCurrentThreadIdentifier(&id)); | |
48 return new extensions::BluetoothAPI(context); | |
49 } | |
50 | |
51 class FakeEventRouter : public extensions::EventRouter { | |
52 public: | |
53 explicit FakeEventRouter(Profile* profile) : EventRouter(profile, NULL) {} | |
54 | |
55 virtual void DispatchEventToExtension(const std::string& extension_id, | |
56 scoped_ptr<extensions::Event> event) | |
57 OVERRIDE { | |
58 extension_id_ = extension_id; | |
59 event_ = event.Pass(); | |
60 } | |
61 | |
62 std::string extension_id() const { return extension_id_; } | |
63 | |
64 const extensions::Event* event() const { return event_.get(); } | |
65 | |
66 private: | |
67 std::string extension_id_; | |
68 scoped_ptr<extensions::Event> event_; | |
69 | |
70 DISALLOW_COPY_AND_ASSIGN(FakeEventRouter); | |
71 }; | |
72 | |
73 class FakeExtensionSystem : public extensions::TestExtensionSystem { | |
74 public: | |
75 explicit FakeExtensionSystem(Profile* profile) | |
76 : extensions::TestExtensionSystem(profile) {} | |
77 | |
78 virtual extensions::EventRouter* event_router() OVERRIDE { | |
79 if (!fake_event_router_) | |
80 fake_event_router_.reset(new FakeEventRouter(profile_)); | |
81 return fake_event_router_.get(); | |
82 } | |
83 | |
84 private: | |
85 scoped_ptr<FakeEventRouter> fake_event_router_; | |
86 | |
87 DISALLOW_COPY_AND_ASSIGN(FakeExtensionSystem); | |
88 }; | |
89 | |
90 KeyedService* BuildFakeExtensionSystem(content::BrowserContext* profile) { | |
91 return new FakeExtensionSystem(static_cast<Profile*>(profile)); | |
92 } | |
93 | |
94 } // namespace | |
95 | |
96 namespace extensions { | |
97 | |
98 namespace bluetooth = api::bluetooth; | |
99 | |
100 class ExtensionBluetoothApiTest : public testing::Test { | |
101 public: | |
102 ExtensionBluetoothApiTest() | |
103 : profile_manager_(TestingBrowserProcess::GetGlobal()), | |
104 mock_adapter_(new testing::StrictMock<device::MockBluetoothAdapter>()), | |
105 test_profile_(NULL) {} | |
106 | |
107 virtual void SetUp() OVERRIDE { | |
108 testing::Test::SetUp(); | |
109 ASSERT_TRUE(profile_manager_.SetUp()); | |
110 test_profile_ = profile_manager_.CreateTestingProfile("test"); | |
111 ExtensionSystemFactory::GetInstance()->SetTestingFactoryAndUse( | |
112 test_profile_, &BuildFakeExtensionSystem); | |
113 ApiResourceManager<BluetoothApiSocket>::GetFactoryInstance() | |
114 ->SetTestingFactoryAndUse(test_profile_, ApiResourceManagerTestFactory); | |
115 BluetoothAPI::GetFactoryInstance()->SetTestingFactoryAndUse( | |
116 test_profile_, BluetoothAPITestFactory); | |
117 BluetoothAPI::Get(test_profile_)->event_router()->SetAdapterForTest( | |
118 mock_adapter_); | |
119 } | |
120 | |
121 virtual void TearDown() OVERRIDE { | |
122 // Some profile-dependent services rely on UI thread to clean up. We make | |
123 // sure they are properly cleaned up by running the UI message loop until | |
124 // idle. | |
125 test_profile_ = NULL; | |
126 profile_manager_.DeleteTestingProfile("test"); | |
127 base::RunLoop run_loop; | |
128 run_loop.RunUntilIdle(); | |
129 } | |
130 | |
131 protected: | |
132 content::TestBrowserThreadBundle thread_bundle_; | |
133 TestingProfileManager profile_manager_; | |
134 scoped_refptr<testing::StrictMock<device::MockBluetoothAdapter> > | |
135 mock_adapter_; | |
136 testing::NiceMock<device::MockBluetoothProfile> mock_audio_profile_; | |
137 testing::NiceMock<device::MockBluetoothProfile> mock_health_profile_; | |
138 // Profiles are weak pointers, owned by |profile_manager_|. | |
139 TestingProfile* test_profile_; | |
140 }; | |
141 | |
142 TEST_F(ExtensionBluetoothApiTest, DispatchConnectionEvent) { | |
143 testing::NiceMock<device::MockBluetoothDevice> mock_device( | |
144 mock_adapter_.get(), 0, "device name", "device address", true, false); | |
145 EXPECT_CALL(*mock_adapter_, GetDevice(mock_device.GetAddress())) | |
146 .WillOnce(testing::Return(&mock_device)); | |
147 scoped_refptr<testing::NiceMock<device::MockBluetoothSocket> > mock_socket( | |
148 new testing::NiceMock<device::MockBluetoothSocket>()); | |
149 | |
150 BluetoothAPI::Get(test_profile_)->event_router()->AddProfile( | |
151 kAudioProfileUuid, kTestExtensionId, &mock_audio_profile_); | |
152 | |
153 BluetoothAPI::Get(test_profile_)->DispatchConnectionEvent( | |
154 kTestExtensionId, kAudioProfileUuid, &mock_device, mock_socket); | |
155 // Connection events are dispatched using a couple of PostTask to the UI | |
156 // thread. Waiting until idle ensures the event is dispatched to the | |
157 // receiver(s). | |
158 base::RunLoop().RunUntilIdle(); | |
159 | |
160 FakeEventRouter* fake_event_router = | |
161 static_cast<FakeEventRouter*>(EventRouter::Get(test_profile_)); | |
162 | |
163 ASSERT_TRUE(fake_event_router->event()); | |
164 EXPECT_STREQ(kTestExtensionId, fake_event_router->extension_id().c_str()); | |
165 EXPECT_STREQ(bluetooth::OnConnection::kEventName, | |
166 fake_event_router->event()->event_name.c_str()); | |
167 | |
168 base::ListValue* event_args = fake_event_router->event()->event_args.get(); | |
169 base::DictionaryValue* socket_value = NULL; | |
170 ASSERT_TRUE(event_args->GetDictionary(0, &socket_value)); | |
171 int socket_id; | |
172 ASSERT_TRUE(socket_value->GetInteger("id", &socket_id)); | |
173 | |
174 ASSERT_TRUE(BluetoothAPI::Get(test_profile_)->socket_data()->Get( | |
175 kTestExtensionId, socket_id)); | |
176 | |
177 std::string uuid; | |
178 ASSERT_TRUE(socket_value->GetString("uuid", &uuid)); | |
179 EXPECT_STREQ(kAudioProfileUuid.canonical_value().c_str(), uuid.c_str()); | |
180 | |
181 EXPECT_CALL(*mock_adapter_, RemoveObserver(testing::_)).Times(1); | |
182 BluetoothAPI::Get(test_profile_)->socket_data()->Remove(kTestExtensionId, | |
183 socket_id); | |
184 } | |
185 | |
186 TEST_F(ExtensionBluetoothApiTest, DoNotDispatchConnectionEvent) { | |
187 testing::NiceMock<device::MockBluetoothDevice> mock_device( | |
188 mock_adapter_.get(), 0, "device name", "device address", true, false); | |
189 scoped_refptr<testing::NiceMock<device::MockBluetoothSocket> > mock_socket( | |
190 new testing::NiceMock<device::MockBluetoothSocket>()); | |
191 | |
192 // Connection event won't be dispatched for non-registered profiles. | |
193 BluetoothAPI::Get(test_profile_)->DispatchConnectionEvent( | |
194 kTestExtensionId, kAudioProfileUuid, &mock_device, mock_socket); | |
195 // Connection events are dispatched using a couple of PostTask to the UI | |
196 // thread. Waiting until idle ensures the event is dispatched to the | |
197 // receiver(s). | |
198 base::RunLoop().RunUntilIdle(); | |
199 | |
200 FakeEventRouter* fake_event_router = | |
201 static_cast<FakeEventRouter*>(EventRouter::Get(test_profile_)); | |
202 EXPECT_TRUE(fake_event_router->event() == NULL); | |
203 | |
204 EXPECT_CALL(*mock_adapter_, RemoveObserver(testing::_)).Times(1); | |
205 } | |
206 | |
207 } // namespace extensions | |
OLD | NEW |