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