1 // Copyright 2015 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 <stddef.h>
6 #include <stdint.h>
7
8 #include "base/bind.h"
9 #include "base/bind_helpers.h"
10 #include "base/memory/ptr_util.h"
11 #include "base/stl_util.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "chrome/browser/chromeos/profiles/profile_helper.h"
14 #include "chrome/browser/extensions/extension_apitest.h"
15 #include "chrome/browser/extensions/extension_service.h"
16 #include "chromeos/dbus/shill/fake_shill_third_party_vpn_driver_client.h"
17 #include "chromeos/dbus/shill/shill_clients.h"
18 #include "chromeos/dbus/shill/shill_profile_client.h"
19 #include "chromeos/dbus/shill/shill_service_client.h"
20 #include "chromeos/network/network_configuration_handler.h"
21 #include "chromeos/network/network_profile_handler.h"
22 #include "content/public/browser/browser_context.h"
23 #include "content/public/test/test_utils.h"
24 #include "extensions/browser/api/vpn_provider/vpn_provider_api.h"
25 #include "extensions/browser/api/vpn_provider/vpn_service.h"
26 #include "extensions/browser/api/vpn_provider/vpn_service_factory.h"
27 #include "extensions/browser/api_test_utils.h"
28 #include "extensions/common/extension.h"
29 #include "extensions/test/result_catcher.h"
30 #include "testing/gmock/include/gmock/gmock.h"
31 #include "third_party/cros_system_api/dbus/service_constants.h"
32
33 using testing::_;
34 using testing::Invoke;
35
36 namespace chromeos {
37
38 namespace {
39
40 namespace api_vpn = extensions::api::vpn_provider;
41
42 const char kNetworkProfilePath[] = "/network/test";
43 const char kTestConfig[] = "testconfig";
44 const char* kParameterValues[] = {"10.10.10.10",
45 "24",
46 "63.145.213.129/32 63.145.212.0/24",
47 "0.0.0.0/0 63.145.212.128/25",
48 "8.8.8.8",
49 "1600",
50 "10.10.10.255",
51 "foo:bar"};
52 const char* kParameterKeys[] = {shill::kAddressParameterThirdPartyVpn,
53 shill::kSubnetPrefixParameterThirdPartyVpn,
54 shill::kExclusionListParameterThirdPartyVpn,
55 shill::kInclusionListParameterThirdPartyVpn,
56 shill::kDnsServersParameterThirdPartyVpn,
57 shill::kMtuParameterThirdPartyVpn,
58 shill::kBroadcastAddressParameterThirdPartyVpn,
59 shill::kDomainSearchParameterThirdPartyVpn};
60
DoNothingFailureCallback(const std::string & error_name,std::unique_ptr<base::DictionaryValue> error_data)61 void DoNothingFailureCallback(
62 const std::string& error_name,
63 std::unique_ptr<base::DictionaryValue> error_data) {
64 EXPECT_EQ(true, false);
65 }
66
DoNothingSuccessCallback(const std::string & service_path,const std::string & guid)67 void DoNothingSuccessCallback(const std::string& service_path,
68 const std::string& guid) {}
69
70 } // namespace
71
72 // Records the number of calls and their parameters. Always replies successfully
73 // to calls.
74 class TestShillThirdPartyVpnDriverClient
75 : public FakeShillThirdPartyVpnDriverClient {
76 public:
SetParameters(const std::string & object_path_value,const base::DictionaryValue & parameters,StringCallback callback,ErrorCallback error_callback)77 void SetParameters(const std::string& object_path_value,
78 const base::DictionaryValue& parameters,
79 StringCallback callback,
80 ErrorCallback error_callback) override {
81 set_parameters_counter_++;
82 parameters_ = parameters.DeepCopy();
83 FakeShillThirdPartyVpnDriverClient::SetParameters(
84 object_path_value, parameters, std::move(callback),
85 std::move(error_callback));
86 }
87
UpdateConnectionState(const std::string & object_path_value,const uint32_t connection_state,base::OnceClosure callback,ErrorCallback error_callback)88 void UpdateConnectionState(const std::string& object_path_value,
89 const uint32_t connection_state,
90 base::OnceClosure callback,
91 ErrorCallback error_callback) override {
92 update_connection_state_counter_++;
93 connection_state_ = connection_state;
94 FakeShillThirdPartyVpnDriverClient::UpdateConnectionState(
95 object_path_value, connection_state, std::move(callback),
96 std::move(error_callback));
97 }
98
SendPacket(const std::string & object_path_value,const std::vector<char> & ip_packet,base::OnceClosure callback,ErrorCallback error_callback)99 void SendPacket(const std::string& object_path_value,
100 const std::vector<char>& ip_packet,
101 base::OnceClosure callback,
102 ErrorCallback error_callback) override {
103 send_packet_counter_++;
104 ip_packet_ = ip_packet;
105 FakeShillThirdPartyVpnDriverClient::SendPacket(object_path_value, ip_packet,
106 std::move(callback),
107 std::move(error_callback));
108 }
109
110 int set_parameters_counter_ = 0;
111 base::DictionaryValue* parameters_ = nullptr;
112 int update_connection_state_counter_ = 0;
113 uint32_t connection_state_;
114 int send_packet_counter_ = 0;
115 std::vector<char> ip_packet_;
116 };
117
118 class VpnProviderApiTest : public extensions::ExtensionApiTest {
119 public:
VpnProviderApiTest()120 VpnProviderApiTest() {}
~VpnProviderApiTest()121 ~VpnProviderApiTest() override {}
122
SetUpInProcessBrowserTestFixture()123 void SetUpInProcessBrowserTestFixture() override {
124 extensions::ExtensionApiTest::SetUpInProcessBrowserTestFixture();
125 // Destroy the existing client and create a test specific fake client. It
126 // will be destroyed in ChromeBrowserMain.
127 test_client_ = new TestShillThirdPartyVpnDriverClient();
128 }
129
AddNetworkProfileForUser()130 void AddNetworkProfileForUser() {
131 ShillProfileClient::Get()->GetTestInterface()->AddProfile(
132 kNetworkProfilePath,
133 chromeos::ProfileHelper::GetUserIdHashFromProfile(profile()));
134 content::RunAllPendingInMessageLoop();
135 }
136
LoadVpnExtension()137 void LoadVpnExtension() {
138 extension_ = LoadExtension(test_data_dir_.AppendASCII("vpn_provider"));
139 extension_id_ = extension_->id();
140 service_ = VpnServiceFactory::GetForBrowserContext(profile());
141 content::RunAllPendingInMessageLoop();
142 }
143
RunExtensionTest(const std::string & test_name)144 bool RunExtensionTest(const std::string& test_name) {
145 GURL url = extension_->GetResourceURL("basic.html?#" + test_name);
146 return RunExtensionSubtest("vpn_provider", url.spec());
147 }
148
GetKey(const std::string & config_name)149 std::string GetKey(const std::string& config_name) {
150 return service_->GetKey(extension_id_, config_name);
151 }
152
DoesConfigExist(const std::string & config_name)153 bool DoesConfigExist(const std::string& config_name) {
154 return service_->VerifyConfigExistsForTesting(extension_id_, config_name);
155 }
156
IsConfigConnected()157 bool IsConfigConnected() {
158 return service_->VerifyConfigIsConnectedForTesting(extension_id_);
159 }
160
GetSingleServicePath()161 std::string GetSingleServicePath() {
162 std::string service_path = service_->GetSingleServicepathForTesting();
163 EXPECT_FALSE(service_path.empty());
164 return service_path;
165 }
166
CreateConfigForTest(const std::string & name)167 bool CreateConfigForTest(const std::string& name) {
168 scoped_refptr<extensions::VpnProviderCreateConfigFunction> create(
169 new extensions::VpnProviderCreateConfigFunction());
170
171 create->set_extension(GetSingleLoadedExtension());
172 return extensions::api_test_utils::RunFunction(
173 create.get(), "[\"" + name + "\"]", profile());
174 }
175
DestroyConfigForTest(const std::string & name)176 bool DestroyConfigForTest(const std::string& name) {
177 scoped_refptr<extensions::VpnProviderDestroyConfigFunction> destroy(
178 new extensions::VpnProviderDestroyConfigFunction());
179
180 destroy->set_extension(GetSingleLoadedExtension());
181 return extensions::api_test_utils::RunFunction(
182 destroy.get(), "[\"" + name + "\"]", profile());
183 }
184
TriggerInternalRemove()185 void TriggerInternalRemove() {
186 NetworkHandler::Get()->network_configuration_handler()->RemoveConfiguration(
187 GetSingleServicePath(), base::DoNothing(),
188 base::Bind(DoNothingFailureCallback));
189 }
190
191 protected:
192 TestShillThirdPartyVpnDriverClient* test_client_ = nullptr; // Unowned
193 VpnService* service_ = nullptr;
194 std::string extension_id_;
195 std::string service_path_;
196 const extensions::Extension* extension_ = nullptr;
197 };
198
IN_PROC_BROWSER_TEST_F(VpnProviderApiTest,ComboSuite)199 IN_PROC_BROWSER_TEST_F(VpnProviderApiTest, ComboSuite) {
200 LoadVpnExtension();
201 AddNetworkProfileForUser();
202 EXPECT_TRUE(RunExtensionTest("comboSuite"));
203 }
204
IN_PROC_BROWSER_TEST_F(VpnProviderApiTest,CreateConfigWithoutNetworkProfile)205 IN_PROC_BROWSER_TEST_F(VpnProviderApiTest, CreateConfigWithoutNetworkProfile) {
206 LoadVpnExtension();
207 EXPECT_TRUE(RunExtensionTest("createConfigWithoutNetworkProfile"));
208 }
209
IN_PROC_BROWSER_TEST_F(VpnProviderApiTest,CreateConfig)210 IN_PROC_BROWSER_TEST_F(VpnProviderApiTest, CreateConfig) {
211 LoadVpnExtension();
212 AddNetworkProfileForUser();
213 EXPECT_TRUE(RunExtensionTest("createConfigSuccess"));
214 EXPECT_TRUE(DoesConfigExist(kTestConfig));
215 const std::string service_path = GetSingleServicePath();
216 std::string profile_path;
217 base::DictionaryValue properties;
218 EXPECT_TRUE(ShillProfileClient::Get()->GetTestInterface()->GetService(
219 service_path, &profile_path, &properties));
220 }
221
IN_PROC_BROWSER_TEST_F(VpnProviderApiTest,DestroyConfig)222 IN_PROC_BROWSER_TEST_F(VpnProviderApiTest, DestroyConfig) {
223 LoadVpnExtension();
224 AddNetworkProfileForUser();
225 EXPECT_TRUE(CreateConfigForTest(kTestConfig));
226 EXPECT_TRUE(DoesConfigExist(kTestConfig));
227 const std::string service_path = GetSingleServicePath();
228 std::string profile_path;
229 base::DictionaryValue properties;
230 EXPECT_TRUE(ShillProfileClient::Get()->GetTestInterface()->GetService(
231 service_path, &profile_path, &properties));
232
233 EXPECT_TRUE(RunExtensionTest("destroyConfigSuccess"));
234 EXPECT_FALSE(DoesConfigExist(kTestConfig));
235 EXPECT_FALSE(ShillProfileClient::Get()->GetTestInterface()->GetService(
236 service_path, &profile_path, &properties));
237 }
238
IN_PROC_BROWSER_TEST_F(VpnProviderApiTest,DestroyConnectedConfig)239 IN_PROC_BROWSER_TEST_F(VpnProviderApiTest, DestroyConnectedConfig) {
240 LoadVpnExtension();
241 AddNetworkProfileForUser();
242
243 EXPECT_TRUE(CreateConfigForTest(kTestConfig));
244 EXPECT_TRUE(DoesConfigExist(kTestConfig));
245 const std::string service_path = GetSingleServicePath();
246 std::string profile_path;
247 base::DictionaryValue properties;
248 EXPECT_TRUE(ShillProfileClient::Get()->GetTestInterface()->GetService(
249 service_path, &profile_path, &properties));
250 EXPECT_FALSE(IsConfigConnected());
251
252 const std::string object_path = shill::kObjectPathBase + GetKey(kTestConfig);
253 test_client_->OnPlatformMessage(object_path,
254 api_vpn::PLATFORM_MESSAGE_CONNECTED);
255 EXPECT_TRUE(IsConfigConnected());
256
257 EXPECT_TRUE(RunExtensionTest("destroyConnectedConfigSetup"));
258
259 EXPECT_TRUE(DestroyConfigForTest(kTestConfig));
260 EXPECT_FALSE(DoesConfigExist(kTestConfig));
261 EXPECT_FALSE(ShillProfileClient::Get()->GetTestInterface()->GetService(
262 service_path, &profile_path, &properties));
263
264 extensions::ResultCatcher catcher;
265 ASSERT_TRUE(catcher.GetNextResult());
266 }
267
IN_PROC_BROWSER_TEST_F(VpnProviderApiTest,VpnSuccess)268 IN_PROC_BROWSER_TEST_F(VpnProviderApiTest, VpnSuccess) {
269 LoadVpnExtension();
270 AddNetworkProfileForUser();
271 EXPECT_TRUE(RunExtensionTest("createConfigConnectAndDisconnect"));
272 EXPECT_TRUE(DoesConfigExist(kTestConfig));
273 const std::string service_path = GetSingleServicePath();
274 std::string profile_path;
275 base::DictionaryValue properties;
276 EXPECT_TRUE(ShillProfileClient::Get()->GetTestInterface()->GetService(
277 service_path, &profile_path, &properties));
278 EXPECT_FALSE(IsConfigConnected());
279
280 const std::string object_path = shill::kObjectPathBase + GetKey(kTestConfig);
281
282 extensions::ResultCatcher catcher;
283 EXPECT_EQ(0, test_client_->set_parameters_counter_);
284 EXPECT_EQ(0, test_client_->update_connection_state_counter_);
285 EXPECT_EQ(0, test_client_->send_packet_counter_);
286 test_client_->OnPlatformMessage(object_path,
287 api_vpn::PLATFORM_MESSAGE_CONNECTED);
288 EXPECT_TRUE(IsConfigConnected());
289 ASSERT_TRUE(catcher.GetNextResult());
290 EXPECT_EQ(1, test_client_->set_parameters_counter_);
291 EXPECT_EQ(1, test_client_->update_connection_state_counter_);
292 EXPECT_EQ(1, test_client_->send_packet_counter_);
293 EXPECT_EQ(api_vpn::VPN_CONNECTION_STATE_CONNECTED,
294 test_client_->update_connection_state_counter_);
295 for (size_t i = 0; i < base::size(kParameterValues); ++i) {
296 std::string value;
297 EXPECT_TRUE(
298 test_client_->parameters_->GetString(kParameterKeys[i], &value));
299 EXPECT_EQ(kParameterValues[i], value);
300 }
301 const char kPacket[] = "feebdaed";
302 std::vector<char> packet(&kPacket[0], &kPacket[8]);
303 EXPECT_EQ(packet, test_client_->ip_packet_);
304
305 packet.assign(test_client_->ip_packet_.rbegin(),
306 test_client_->ip_packet_.rend());
307 test_client_->OnPacketReceived(object_path, packet);
308 ASSERT_TRUE(catcher.GetNextResult());
309
310 test_client_->OnPlatformMessage(object_path,
311 api_vpn::PLATFORM_MESSAGE_DISCONNECTED);
312 ASSERT_TRUE(catcher.GetNextResult());
313 EXPECT_FALSE(IsConfigConnected());
314 }
315
IN_PROC_BROWSER_TEST_F(VpnProviderApiTest,ConfigInternalRemove)316 IN_PROC_BROWSER_TEST_F(VpnProviderApiTest, ConfigInternalRemove) {
317 LoadVpnExtension();
318 AddNetworkProfileForUser();
319 EXPECT_TRUE(RunExtensionTest("configInternalRemove"));
320 EXPECT_TRUE(DoesConfigExist(kTestConfig));
321
322 extensions::ResultCatcher catcher;
323 TriggerInternalRemove();
324 ASSERT_TRUE(catcher.GetNextResult());
325 EXPECT_FALSE(DoesConfigExist(kTestConfig));
326 }
327
IN_PROC_BROWSER_TEST_F(VpnProviderApiTest,CheckEvents)328 IN_PROC_BROWSER_TEST_F(VpnProviderApiTest, CheckEvents) {
329 LoadVpnExtension();
330 AddNetworkProfileForUser();
331 EXPECT_TRUE(RunExtensionTest("expectEvents"));
332 EXPECT_TRUE(DoesConfigExist(kTestConfig));
333
334 extensions::ResultCatcher catcher;
335 service_->SendPlatformError(extension_id_, kTestConfig, "error_message");
336 service_->SendShowAddDialogToExtension(extension_id_);
337 service_->SendShowConfigureDialogToExtension(extension_id_, kTestConfig);
338 EXPECT_TRUE(catcher.GetNextResult());
339 }
340
IN_PROC_BROWSER_TEST_F(VpnProviderApiTest,ConfigPersistence)341 IN_PROC_BROWSER_TEST_F(VpnProviderApiTest, ConfigPersistence) {
342 LoadVpnExtension();
343 AddNetworkProfileForUser();
344 EXPECT_FALSE(DoesConfigExist(kTestConfig));
345
346 base::DictionaryValue properties;
347 properties.SetKey(shill::kTypeProperty, base::Value(shill::kTypeVPN));
348 properties.SetKey(shill::kNameProperty, base::Value(kTestConfig));
349 properties.SetKey(shill::kProviderHostProperty, base::Value(extension_id_));
350 properties.SetKey(shill::kObjectPathSuffixProperty,
351 base::Value(GetKey(kTestConfig)));
352 properties.SetKey(shill::kProviderTypeProperty,
353 base::Value(shill::kProviderThirdPartyVpn));
354 properties.SetKey(shill::kProfileProperty, base::Value(kNetworkProfilePath));
355 NetworkHandler::Get()
356 ->network_configuration_handler()
357 ->CreateShillConfiguration(properties,
358 base::Bind(DoNothingSuccessCallback),
359 base::Bind(DoNothingFailureCallback));
360 content::RunAllPendingInMessageLoop();
361 EXPECT_TRUE(DoesConfigExist(kTestConfig));
362 }
363
IN_PROC_BROWSER_TEST_F(VpnProviderApiTest,CreateUninstall)364 IN_PROC_BROWSER_TEST_F(VpnProviderApiTest, CreateUninstall) {
365 LoadVpnExtension();
366 AddNetworkProfileForUser();
367 EXPECT_TRUE(RunExtensionTest("createConfigSuccess"));
368 EXPECT_TRUE(DoesConfigExist(kTestConfig));
369
370 const std::string service_path = GetSingleServicePath();
371 std::string profile_path;
372 base::DictionaryValue properties;
373 EXPECT_TRUE(ShillProfileClient::Get()->GetTestInterface()->GetService(
374 service_path, &profile_path, &properties));
375
376 UninstallExtension(extension_id_);
377 content::RunAllPendingInMessageLoop();
378 EXPECT_FALSE(DoesConfigExist(kTestConfig));
379 EXPECT_FALSE(ShillProfileClient::Get()->GetTestInterface()->GetService(
380 service_path, &profile_path, &properties));
381 }
382
IN_PROC_BROWSER_TEST_F(VpnProviderApiTest,CreateDisable)383 IN_PROC_BROWSER_TEST_F(VpnProviderApiTest, CreateDisable) {
384 LoadVpnExtension();
385 AddNetworkProfileForUser();
386 EXPECT_TRUE(RunExtensionTest("createConfigSuccess"));
387 EXPECT_TRUE(DoesConfigExist(kTestConfig));
388
389 const std::string service_path = GetSingleServicePath();
390 std::string profile_path;
391 base::DictionaryValue properties;
392 EXPECT_TRUE(ShillProfileClient::Get()->GetTestInterface()->GetService(
393 service_path, &profile_path, &properties));
394
395 extensions::ExtensionService* extension_service =
396 extensions::ExtensionSystem::Get(profile())->extension_service();
397 extension_service->DisableExtension(
398 extension_id_, extensions::disable_reason::DISABLE_USER_ACTION);
399 content::RunAllPendingInMessageLoop();
400 EXPECT_FALSE(DoesConfigExist(kTestConfig));
401 EXPECT_FALSE(ShillProfileClient::Get()->GetTestInterface()->GetService(
402 service_path, &profile_path, &properties));
403 }
404
IN_PROC_BROWSER_TEST_F(VpnProviderApiTest,CreateBlacklist)405 IN_PROC_BROWSER_TEST_F(VpnProviderApiTest, CreateBlacklist) {
406 LoadVpnExtension();
407 AddNetworkProfileForUser();
408 EXPECT_TRUE(RunExtensionTest("createConfigSuccess"));
409 EXPECT_TRUE(DoesConfigExist(kTestConfig));
410
411 const std::string service_path = GetSingleServicePath();
412 std::string profile_path;
413 base::DictionaryValue properties;
414 EXPECT_TRUE(ShillProfileClient::Get()->GetTestInterface()->GetService(
415 service_path, &profile_path, &properties));
416
417 extensions::ExtensionService* extension_service =
418 extensions::ExtensionSystem::Get(profile())->extension_service();
419 extension_service->BlacklistExtensionForTest(extension_id_);
420 content::RunAllPendingInMessageLoop();
421 EXPECT_FALSE(DoesConfigExist(kTestConfig));
422 EXPECT_FALSE(ShillProfileClient::Get()->GetTestInterface()->GetService(
423 service_path, &profile_path, &properties));
424 }
425
426 } // namespace chromeos
427