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