1 // Copyright 2018 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 "chromeos/services/secure_channel/active_connection_manager_impl.h"
6
7 #include <memory>
8
9 #include "base/bind.h"
10 #include "base/containers/flat_map.h"
11 #include "base/macros.h"
12 #include "base/test/gtest_util.h"
13 #include "base/test/task_environment.h"
14 #include "base/unguessable_token.h"
15 #include "chromeos/services/secure_channel/connection_details.h"
16 #include "chromeos/services/secure_channel/fake_active_connection_manager.h"
17 #include "chromeos/services/secure_channel/fake_authenticated_channel.h"
18 #include "chromeos/services/secure_channel/fake_client_connection_parameters.h"
19 #include "chromeos/services/secure_channel/fake_multiplexed_channel.h"
20 #include "chromeos/services/secure_channel/multiplexed_channel_impl.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22
23 namespace chromeos {
24
25 namespace secure_channel {
26
27 namespace {
28
29 class FakeMultiplexedChannelFactory : public MultiplexedChannelImpl::Factory {
30 public:
FakeMultiplexedChannelFactory(MultiplexedChannel::Delegate * expected_delegate)31 explicit FakeMultiplexedChannelFactory(
32 MultiplexedChannel::Delegate* expected_delegate)
33 : expected_delegate_(expected_delegate) {}
34 ~FakeMultiplexedChannelFactory() override = default;
35
36 base::flat_map<ConnectionDetails, FakeMultiplexedChannel*>&
connection_details_to_active_channel_map()37 connection_details_to_active_channel_map() {
38 return connection_details_to_active_channel_map_;
39 }
40
set_next_expected_authenticated_channel(AuthenticatedChannel * authenticated_channel)41 void set_next_expected_authenticated_channel(
42 AuthenticatedChannel* authenticated_channel) {
43 next_expected_authenticated_channel_ = authenticated_channel;
44 }
45
46 // MultiplexedChannelImpl::Factory:
CreateInstance(std::unique_ptr<AuthenticatedChannel> authenticated_channel,MultiplexedChannel::Delegate * delegate,ConnectionDetails connection_details,std::vector<std::unique_ptr<ClientConnectionParameters>> * initial_clients)47 std::unique_ptr<MultiplexedChannel> CreateInstance(
48 std::unique_ptr<AuthenticatedChannel> authenticated_channel,
49 MultiplexedChannel::Delegate* delegate,
50 ConnectionDetails connection_details,
51 std::vector<std::unique_ptr<ClientConnectionParameters>>* initial_clients)
52 override {
53 EXPECT_EQ(expected_delegate_, delegate);
54 EXPECT_EQ(next_expected_authenticated_channel_,
55 authenticated_channel.get());
56 next_expected_authenticated_channel_ = nullptr;
57
58 auto fake_channel = std::make_unique<FakeMultiplexedChannel>(
59 delegate, connection_details,
60 base::BindOnce(&FakeMultiplexedChannelFactory::OnChannelDeleted,
61 base::Unretained(this)));
62
63 for (auto& initial_client : *initial_clients)
64 fake_channel->AddClientToChannel(std::move(initial_client));
65
66 connection_details_to_active_channel_map_[connection_details] =
67 fake_channel.get();
68
69 return fake_channel;
70 }
71
72 private:
OnChannelDeleted(const ConnectionDetails & connection_details)73 void OnChannelDeleted(const ConnectionDetails& connection_details) {
74 size_t num_deleted =
75 connection_details_to_active_channel_map_.erase(connection_details);
76 EXPECT_EQ(1u, num_deleted);
77 }
78
79 const MultiplexedChannel::Delegate* expected_delegate_;
80
81 AuthenticatedChannel* next_expected_authenticated_channel_ = nullptr;
82
83 base::flat_map<ConnectionDetails, FakeMultiplexedChannel*>
84 connection_details_to_active_channel_map_;
85
86 DISALLOW_COPY_AND_ASSIGN(FakeMultiplexedChannelFactory);
87 };
88
ClientListToIdList(const std::vector<std::unique_ptr<ClientConnectionParameters>> & client_list)89 std::vector<base::UnguessableToken> ClientListToIdList(
90 const std::vector<std::unique_ptr<ClientConnectionParameters>>&
91 client_list) {
92 std::vector<base::UnguessableToken> id_list;
93 std::transform(client_list.begin(), client_list.end(),
94 std::back_inserter(id_list),
95 [](auto& client) { return client->id(); });
96 return id_list;
97 }
98
99 } // namespace
100
101 class SecureChannelActiveConnectionManagerImplTest : public testing::Test {
102 protected:
103 SecureChannelActiveConnectionManagerImplTest() = default;
104 ~SecureChannelActiveConnectionManagerImplTest() override = default;
105
106 // testing::Test:
SetUp()107 void SetUp() override {
108 fake_delegate_ = std::make_unique<FakeActiveConnectionManagerDelegate>();
109
110 manager_ =
111 ActiveConnectionManagerImpl::Factory::Create(fake_delegate_.get());
112
113 ActiveConnectionManagerImpl* ptr_as_impl =
114 static_cast<ActiveConnectionManagerImpl*>(manager_.get());
115 fake_multiplexed_channel_factory_ =
116 std::make_unique<FakeMultiplexedChannelFactory>(ptr_as_impl);
117 MultiplexedChannelImpl::Factory::SetFactoryForTesting(
118 fake_multiplexed_channel_factory_.get());
119 }
120
TearDown()121 void TearDown() override {
122 MultiplexedChannelImpl::Factory::SetFactoryForTesting(nullptr);
123 }
124
AddActiveConnectionAndVerifyState(const std::string & device_id,std::vector<std::unique_ptr<ClientConnectionParameters>> initial_clients)125 void AddActiveConnectionAndVerifyState(
126 const std::string& device_id,
127 std::vector<std::unique_ptr<ClientConnectionParameters>>
128 initial_clients) {
129 EXPECT_EQ(ActiveConnectionManager::ConnectionState::kNoConnectionExists,
130 GetConnectionState(device_id));
131
132 std::vector<base::UnguessableToken> initial_client_ids =
133 ClientListToIdList(initial_clients);
134
135 auto fake_authenticated_channel =
136 std::make_unique<FakeAuthenticatedChannel>();
137 fake_multiplexed_channel_factory_->set_next_expected_authenticated_channel(
138 fake_authenticated_channel.get());
139
140 manager_->AddActiveConnection(
141 std::move(fake_authenticated_channel), std::move(initial_clients),
142 ConnectionDetails(device_id, ConnectionMedium::kBluetoothLowEnergy));
143
144 // The connection should be active, and the initial clients should now be
145 // present in the associated channel.
146 EXPECT_EQ(ActiveConnectionManager::ConnectionState::kActiveConnectionExists,
147 GetConnectionState(device_id));
148 EXPECT_EQ(initial_client_ids,
149 ClientListToIdList(
150 GetActiveChannelForDeviceId(device_id)->added_clients()));
151 }
152
AddNewClientAndVerifyState(const std::string & device_id,std::unique_ptr<ClientConnectionParameters> client_connection_parameters)153 void AddNewClientAndVerifyState(const std::string& device_id,
154 std::unique_ptr<ClientConnectionParameters>
155 client_connection_parameters) {
156 EXPECT_EQ(ActiveConnectionManager::ConnectionState::kActiveConnectionExists,
157 GetConnectionState(device_id));
158
159 // Initialize to the IDs before this call.
160 std::vector<base::UnguessableToken> client_ids = ClientListToIdList(
161 GetActiveChannelForDeviceId(device_id)->added_clients());
162
163 // Add in the new ID for this new client.
164 client_ids.push_back(client_connection_parameters->id());
165
166 manager_->AddClientToChannel(
167 std::move(client_connection_parameters),
168 ConnectionDetails(device_id, ConnectionMedium::kBluetoothLowEnergy));
169
170 // The connection should remain active, and the clients list should now have
171 // the new client.
172 EXPECT_EQ(ActiveConnectionManager::ConnectionState::kActiveConnectionExists,
173 GetConnectionState(device_id));
174 EXPECT_EQ(client_ids,
175 ClientListToIdList(
176 GetActiveChannelForDeviceId(device_id)->added_clients()));
177 }
178
GetConnectionState(const std::string device_id)179 ActiveConnectionManager::ConnectionState GetConnectionState(
180 const std::string device_id) {
181 return manager_->GetConnectionState(
182 ConnectionDetails(device_id, ConnectionMedium::kBluetoothLowEnergy));
183 }
184
GetActiveChannelForDeviceId(const std::string & device_id)185 FakeMultiplexedChannel* GetActiveChannelForDeviceId(
186 const std::string& device_id) {
187 ConnectionDetails connection_details(device_id,
188 ConnectionMedium::kBluetoothLowEnergy);
189 if (!base::Contains(fake_multiplexed_channel_factory_
190 ->connection_details_to_active_channel_map(),
191 connection_details)) {
192 return nullptr;
193 }
194
195 return fake_multiplexed_channel_factory_
196 ->connection_details_to_active_channel_map()[connection_details];
197 }
198
GetNumActiveChannels()199 size_t GetNumActiveChannels() {
200 return fake_multiplexed_channel_factory_
201 ->connection_details_to_active_channel_map()
202 .size();
203 }
204
GetNumDisconnections(const std::string & device_id)205 size_t GetNumDisconnections(const std::string& device_id) {
206 ConnectionDetails connection_details(device_id,
207 ConnectionMedium::kBluetoothLowEnergy);
208
209 const auto& map =
210 fake_delegate_->connection_details_to_num_disconnections_map();
211 auto it = map.find(connection_details);
212 EXPECT_NE(it, map.end());
213 return it->second;
214 }
215
active_connection_manager()216 ActiveConnectionManager* active_connection_manager() {
217 return manager_.get();
218 }
219
220 private:
221 base::test::TaskEnvironment task_environment_;
222
223 std::unique_ptr<FakeMultiplexedChannelFactory>
224 fake_multiplexed_channel_factory_;
225 std::unique_ptr<FakeActiveConnectionManagerDelegate> fake_delegate_;
226
227 std::unique_ptr<ActiveConnectionManager> manager_;
228
229 DISALLOW_COPY_AND_ASSIGN(SecureChannelActiveConnectionManagerImplTest);
230 };
231
TEST_F(SecureChannelActiveConnectionManagerImplTest,EdgeCases)232 TEST_F(SecureChannelActiveConnectionManagerImplTest, EdgeCases) {
233 std::vector<std::unique_ptr<ClientConnectionParameters>> client_list;
234 client_list.push_back(
235 std::make_unique<FakeClientConnectionParameters>("feature"));
236
237 AddActiveConnectionAndVerifyState("deviceId", std::move(client_list));
238
239 // Try to add another channel for the same ConnectionDetails; this should
240 // fail, since one already exists.
241 client_list.push_back(
242 std::make_unique<FakeClientConnectionParameters>("feature"));
243 EXPECT_DCHECK_DEATH(active_connection_manager()->AddActiveConnection(
244 std::make_unique<FakeAuthenticatedChannel>(), std::move(client_list),
245 ConnectionDetails("deviceId", ConnectionMedium::kBluetoothLowEnergy)));
246
247 // Move to disconnecting state.
248 GetActiveChannelForDeviceId("deviceId")->SetDisconnecting();
249 EXPECT_EQ(
250 ActiveConnectionManager::ConnectionState::kDisconnectingConnectionExists,
251 GetConnectionState("deviceId"));
252
253 // Try to add another channel; this should still fail while disconnecting.
254 client_list.push_back(
255 std::make_unique<FakeClientConnectionParameters>("feature"));
256 EXPECT_DCHECK_DEATH(active_connection_manager()->AddActiveConnection(
257 std::make_unique<FakeAuthenticatedChannel>(), std::move(client_list),
258 ConnectionDetails("deviceId", ConnectionMedium::kBluetoothLowEnergy)));
259
260 // Try to add an additional client; this should also fail while disconnecting.
261 EXPECT_DCHECK_DEATH(active_connection_manager()->AddClientToChannel(
262 std::make_unique<FakeClientConnectionParameters>("feature"),
263 ConnectionDetails("deviceId", ConnectionMedium::kBluetoothLowEnergy)));
264
265 GetActiveChannelForDeviceId("deviceId")->SetDisconnected();
266 EXPECT_EQ(ActiveConnectionManager::ConnectionState::kNoConnectionExists,
267 GetConnectionState("deviceId"));
268
269 // Try to add an additional client; this should also fail while disconnected.
270 EXPECT_DCHECK_DEATH(active_connection_manager()->AddClientToChannel(
271 std::make_unique<FakeClientConnectionParameters>("feature"),
272 ConnectionDetails("deviceId", ConnectionMedium::kBluetoothLowEnergy)));
273 }
274
TEST_F(SecureChannelActiveConnectionManagerImplTest,SingleChannel_OneClient)275 TEST_F(SecureChannelActiveConnectionManagerImplTest, SingleChannel_OneClient) {
276 std::vector<std::unique_ptr<ClientConnectionParameters>> client_list;
277 client_list.push_back(
278 std::make_unique<FakeClientConnectionParameters>("feature"));
279
280 AddActiveConnectionAndVerifyState("deviceId", std::move(client_list));
281 EXPECT_EQ(1u, GetNumActiveChannels());
282
283 GetActiveChannelForDeviceId("deviceId")->SetDisconnecting();
284 EXPECT_EQ(
285 ActiveConnectionManager::ConnectionState::kDisconnectingConnectionExists,
286 GetConnectionState("deviceId"));
287 EXPECT_EQ(1u, GetNumActiveChannels());
288
289 GetActiveChannelForDeviceId("deviceId")->SetDisconnected();
290 EXPECT_EQ(ActiveConnectionManager::ConnectionState::kNoConnectionExists,
291 GetConnectionState("deviceId"));
292 EXPECT_EQ(0u, GetNumActiveChannels());
293 EXPECT_EQ(1u, GetNumDisconnections("deviceId"));
294 }
295
TEST_F(SecureChannelActiveConnectionManagerImplTest,SingleChannel_MultipleClients)296 TEST_F(SecureChannelActiveConnectionManagerImplTest,
297 SingleChannel_MultipleClients) {
298 std::vector<std::unique_ptr<ClientConnectionParameters>> client_list;
299 client_list.push_back(
300 std::make_unique<FakeClientConnectionParameters>("feature1"));
301 client_list.push_back(
302 std::make_unique<FakeClientConnectionParameters>("feature2"));
303
304 AddActiveConnectionAndVerifyState("deviceId", std::move(client_list));
305 EXPECT_EQ(1u, GetNumActiveChannels());
306
307 AddNewClientAndVerifyState(
308 "deviceId", std::make_unique<FakeClientConnectionParameters>("feature3"));
309 EXPECT_EQ(1u, GetNumActiveChannels());
310
311 GetActiveChannelForDeviceId("deviceId")->SetDisconnecting();
312 EXPECT_EQ(
313 ActiveConnectionManager::ConnectionState::kDisconnectingConnectionExists,
314 GetConnectionState("deviceId"));
315 EXPECT_EQ(1u, GetNumActiveChannels());
316
317 GetActiveChannelForDeviceId("deviceId")->SetDisconnected();
318 EXPECT_EQ(ActiveConnectionManager::ConnectionState::kNoConnectionExists,
319 GetConnectionState("deviceId"));
320 EXPECT_EQ(0u, GetNumActiveChannels());
321 EXPECT_EQ(1u, GetNumDisconnections("deviceId"));
322 }
323
TEST_F(SecureChannelActiveConnectionManagerImplTest,MultipleChannels_MultipleClients)324 TEST_F(SecureChannelActiveConnectionManagerImplTest,
325 MultipleChannels_MultipleClients) {
326 // Add an initial channel with two clients.
327 std::vector<std::unique_ptr<ClientConnectionParameters>> client_list;
328 client_list.push_back(
329 std::make_unique<FakeClientConnectionParameters>("feature1"));
330 client_list.push_back(
331 std::make_unique<FakeClientConnectionParameters>("feature2"));
332
333 AddActiveConnectionAndVerifyState("deviceId1", std::move(client_list));
334 EXPECT_EQ(1u, GetNumActiveChannels());
335
336 // Add another channel with two more clients.
337 client_list.push_back(
338 std::make_unique<FakeClientConnectionParameters>("feature3"));
339 client_list.push_back(
340 std::make_unique<FakeClientConnectionParameters>("feature4"));
341
342 AddActiveConnectionAndVerifyState("deviceId2", std::move(client_list));
343 EXPECT_EQ(2u, GetNumActiveChannels());
344
345 // Add a new client to the first channel.
346 AddNewClientAndVerifyState(
347 "deviceId1",
348 std::make_unique<FakeClientConnectionParameters>("feature5"));
349 EXPECT_EQ(2u, GetNumActiveChannels());
350
351 // Add a new client to the second channel.
352 AddNewClientAndVerifyState(
353 "deviceId2",
354 std::make_unique<FakeClientConnectionParameters>("feature6"));
355 EXPECT_EQ(2u, GetNumActiveChannels());
356
357 // Start disconnecting the first channel.
358 GetActiveChannelForDeviceId("deviceId1")->SetDisconnecting();
359 EXPECT_EQ(
360 ActiveConnectionManager::ConnectionState::kDisconnectingConnectionExists,
361 GetConnectionState("deviceId1"));
362 EXPECT_EQ(2u, GetNumActiveChannels());
363
364 // Disconnect the first channel.
365 GetActiveChannelForDeviceId("deviceId1")->SetDisconnected();
366 EXPECT_EQ(ActiveConnectionManager::ConnectionState::kNoConnectionExists,
367 GetConnectionState("deviceId1"));
368 EXPECT_EQ(1u, GetNumActiveChannels());
369 EXPECT_EQ(1u, GetNumDisconnections("deviceId1"));
370
371 // Now, add another channel for the same device that just disconnected.
372 client_list.push_back(
373 std::make_unique<FakeClientConnectionParameters>("feature7"));
374 client_list.push_back(
375 std::make_unique<FakeClientConnectionParameters>("feature8"));
376
377 AddActiveConnectionAndVerifyState("deviceId1", std::move(client_list));
378 EXPECT_EQ(2u, GetNumActiveChannels());
379
380 // Start disconnecting the second channel.
381 GetActiveChannelForDeviceId("deviceId2")->SetDisconnecting();
382 EXPECT_EQ(
383 ActiveConnectionManager::ConnectionState::kDisconnectingConnectionExists,
384 GetConnectionState("deviceId2"));
385 EXPECT_EQ(2u, GetNumActiveChannels());
386
387 // Disconnect the second channel.
388 GetActiveChannelForDeviceId("deviceId2")->SetDisconnected();
389 EXPECT_EQ(ActiveConnectionManager::ConnectionState::kNoConnectionExists,
390 GetConnectionState("deviceId2"));
391 EXPECT_EQ(1u, GetNumActiveChannels());
392 EXPECT_EQ(1u, GetNumDisconnections("deviceId2"));
393
394 // Start disconnecting the second iteration of the first channel.
395 GetActiveChannelForDeviceId("deviceId1")->SetDisconnecting();
396 EXPECT_EQ(
397 ActiveConnectionManager::ConnectionState::kDisconnectingConnectionExists,
398 GetConnectionState("deviceId1"));
399 EXPECT_EQ(1u, GetNumActiveChannels());
400
401 // Disconnect the second iteration of the first channel.
402 GetActiveChannelForDeviceId("deviceId1")->SetDisconnected();
403 EXPECT_EQ(ActiveConnectionManager::ConnectionState::kNoConnectionExists,
404 GetConnectionState("deviceId1"));
405 EXPECT_EQ(0u, GetNumActiveChannels());
406 EXPECT_EQ(2u, GetNumDisconnections("deviceId1"));
407 }
408
409 } // namespace secure_channel
410
411 } // namespace chromeos
412