Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chromeos / network / network_connection_handler_unittest.cc
1 // Copyright (c) 2012 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/network/network_connection_handler.h"
6
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/file_util.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/run_loop.h"
13 #include "base/strings/stringprintf.h"
14 #include "chromeos/cert_loader.h"
15 #include "chromeos/dbus/dbus_thread_manager.h"
16 #include "chromeos/dbus/shill_manager_client.h"
17 #include "chromeos/dbus/shill_service_client.h"
18 #include "chromeos/network/network_configuration_handler.h"
19 #include "chromeos/network/network_state_handler.h"
20 #include "chromeos/network/onc/onc_utils.h"
21 #include "chromeos/tpm_token_loader.h"
22 #include "crypto/nss_util.h"
23 #include "crypto/nss_util_internal.h"
24 #include "net/base/net_errors.h"
25 #include "net/base/test_data_directory.h"
26 #include "net/cert/nss_cert_database_chromeos.h"
27 #include "net/cert/x509_certificate.h"
28 #include "net/test/cert_test_util.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "third_party/cros_system_api/dbus/service_constants.h"
31
32 namespace {
33
34 const char* kSuccessResult = "success";
35
36 void ConfigureCallback(const dbus::ObjectPath& result) {
37 }
38
39 void ConfigureErrorCallback(const std::string& error_name,
40                             const std::string& error_message) {
41 }
42
43 }  // namespace
44
45 namespace chromeos {
46
47 class NetworkConnectionHandlerTest : public testing::Test {
48  public:
49   NetworkConnectionHandlerTest() : user_("userhash") {
50   }
51   virtual ~NetworkConnectionHandlerTest() {
52   }
53
54   virtual void SetUp() OVERRIDE {
55     ASSERT_TRUE(user_.constructed_successfully());
56     user_.FinishInit();
57
58     test_nssdb_.reset(new net::NSSCertDatabaseChromeOS(
59         crypto::GetPublicSlotForChromeOSUser(user_.username_hash()),
60         crypto::GetPrivateSlotForChromeOSUser(
61             user_.username_hash(),
62             base::Callback<void(crypto::ScopedPK11Slot)>())));
63     test_nssdb_->SetSlowTaskRunnerForTest(message_loop_.message_loop_proxy());
64
65     TPMTokenLoader::InitializeForTest();
66
67     CertLoader::Initialize();
68     CertLoader* cert_loader = CertLoader::Get();
69     cert_loader->force_hardware_backed_for_test();
70
71     // Initialize DBusThreadManager with a stub implementation.
72     DBusThreadManager::InitializeWithStub();
73     base::RunLoop().RunUntilIdle();
74     DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface()
75         ->ClearServices();
76     base::RunLoop().RunUntilIdle();
77     LoginState::Initialize();
78     network_state_handler_.reset(NetworkStateHandler::InitializeForTest());
79     network_configuration_handler_.reset(
80         NetworkConfigurationHandler::InitializeForTest(
81             network_state_handler_.get()));
82
83     network_connection_handler_.reset(new NetworkConnectionHandler);
84     network_connection_handler_->Init(network_state_handler_.get(),
85                                       network_configuration_handler_.get());
86   }
87
88   virtual void TearDown() OVERRIDE {
89     network_connection_handler_.reset();
90     network_configuration_handler_.reset();
91     network_state_handler_.reset();
92     CertLoader::Shutdown();
93     TPMTokenLoader::Shutdown();
94     LoginState::Shutdown();
95     DBusThreadManager::Shutdown();
96   }
97
98  protected:
99   bool Configure(const std::string& json_string) {
100     scoped_ptr<base::DictionaryValue> json_dict =
101         onc::ReadDictionaryFromJson(json_string);
102     if (!json_dict) {
103       LOG(ERROR) << "Error parsing json: " << json_string;
104       return false;
105     }
106     DBusThreadManager::Get()->GetShillManagerClient()->ConfigureService(
107         *json_dict,
108         base::Bind(&ConfigureCallback),
109         base::Bind(&ConfigureErrorCallback));
110     base::RunLoop().RunUntilIdle();
111     return true;
112   }
113
114   void Connect(const std::string& service_path) {
115     const bool check_error_state = true;
116     network_connection_handler_->ConnectToNetwork(
117         service_path,
118         base::Bind(&NetworkConnectionHandlerTest::SuccessCallback,
119                    base::Unretained(this)),
120         base::Bind(&NetworkConnectionHandlerTest::ErrorCallback,
121                    base::Unretained(this)),
122         check_error_state);
123     base::RunLoop().RunUntilIdle();
124   }
125
126   void Disconnect(const std::string& service_path) {
127     network_connection_handler_->DisconnectNetwork(
128         service_path,
129         base::Bind(&NetworkConnectionHandlerTest::SuccessCallback,
130                    base::Unretained(this)),
131         base::Bind(&NetworkConnectionHandlerTest::ErrorCallback,
132                    base::Unretained(this)));
133     base::RunLoop().RunUntilIdle();
134   }
135
136   void SuccessCallback() {
137     result_ = kSuccessResult;
138   }
139
140   void ErrorCallback(const std::string& error_name,
141                      scoped_ptr<base::DictionaryValue> error_data) {
142     result_ = error_name;
143   }
144
145   std::string GetResultAndReset() {
146     std::string result;
147     result.swap(result_);
148     return result;
149   }
150
151   std::string GetServiceStringProperty(const std::string& service_path,
152                                        const std::string& key) {
153     std::string result;
154     const base::DictionaryValue* properties =
155         DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface()->
156         GetServiceProperties(service_path);
157     if (properties)
158       properties->GetStringWithoutPathExpansion(key, &result);
159     return result;
160   }
161
162   void StartCertLoader() {
163     CertLoader::Get()->StartWithNSSDB(test_nssdb_.get());
164     base::RunLoop().RunUntilIdle();
165   }
166
167   void ImportClientCertAndKey(const std::string& pkcs12_file,
168                               net::NSSCertDatabase* nssdb,
169                               net::CertificateList* loaded_certs) {
170     std::string pkcs12_data;
171     base::FilePath pkcs12_path =
172         net::GetTestCertsDirectory().Append(pkcs12_file);
173     ASSERT_TRUE(base::ReadFileToString(pkcs12_path, &pkcs12_data));
174
175     scoped_refptr<net::CryptoModule> module(
176         net::CryptoModule::CreateFromHandle(nssdb->GetPrivateSlot().get()));
177     ASSERT_EQ(
178         net::OK,
179         nssdb->ImportFromPKCS12(module, pkcs12_data, base::string16(), false,
180                                 loaded_certs));
181     ASSERT_EQ(1U, loaded_certs->size());
182   }
183
184   scoped_ptr<NetworkStateHandler> network_state_handler_;
185   scoped_ptr<NetworkConfigurationHandler> network_configuration_handler_;
186   scoped_ptr<NetworkConnectionHandler> network_connection_handler_;
187   crypto::ScopedTestNSSChromeOSUser user_;
188   scoped_ptr<net::NSSCertDatabaseChromeOS> test_nssdb_;
189   base::MessageLoopForUI message_loop_;
190   std::string result_;
191
192  private:
193   DISALLOW_COPY_AND_ASSIGN(NetworkConnectionHandlerTest);
194 };
195
196 namespace {
197
198 const char* kConfigConnectable =
199     "{ \"GUID\": \"wifi0\", \"Type\": \"wifi\", \"State\": \"idle\", "
200     "  \"Connectable\": true }";
201 const char* kConfigConnected =
202     "{ \"GUID\": \"wifi1\", \"Type\": \"wifi\", \"State\": \"online\" }";
203 const char* kConfigConnecting =
204     "{ \"GUID\": \"wifi2\", \"Type\": \"wifi\", \"State\": \"association\" }";
205 const char* kConfigRequiresPassphrase =
206     "{ \"GUID\": \"wifi3\", \"Type\": \"wifi\", "
207     "  \"PassphraseRequired\": true }";
208 const char* kConfigRequiresActivation =
209     "{ \"GUID\": \"cellular1\", \"Type\": \"cellular\","
210     "  \"Cellular.ActivationState\": \"not-activated\" }";
211
212 }  // namespace
213
214 TEST_F(NetworkConnectionHandlerTest, NetworkConnectionHandlerConnectSuccess) {
215   EXPECT_TRUE(Configure(kConfigConnectable));
216   Connect("wifi0");
217   EXPECT_EQ(kSuccessResult, GetResultAndReset());
218   EXPECT_EQ(shill::kStateOnline,
219             GetServiceStringProperty("wifi0", shill::kStateProperty));
220 }
221
222 // Handles basic failure cases.
223 TEST_F(NetworkConnectionHandlerTest, NetworkConnectionHandlerConnectFailure) {
224   Connect("no-network");
225   EXPECT_EQ(NetworkConnectionHandler::kErrorConfigureFailed,
226             GetResultAndReset());
227
228   EXPECT_TRUE(Configure(kConfigConnected));
229   Connect("wifi1");
230   EXPECT_EQ(NetworkConnectionHandler::kErrorConnected, GetResultAndReset());
231
232   EXPECT_TRUE(Configure(kConfigConnecting));
233   Connect("wifi2");
234   EXPECT_EQ(NetworkConnectionHandler::kErrorConnecting, GetResultAndReset());
235
236   EXPECT_TRUE(Configure(kConfigRequiresPassphrase));
237   Connect("wifi3");
238   EXPECT_EQ(NetworkConnectionHandler::kErrorPassphraseRequired,
239             GetResultAndReset());
240
241   EXPECT_TRUE(Configure(kConfigRequiresActivation));
242   Connect("cellular1");
243   EXPECT_EQ(NetworkConnectionHandler::kErrorActivationRequired,
244             GetResultAndReset());
245 }
246
247 namespace {
248
249 const char* kConfigRequiresCertificateTemplate =
250     "{ \"GUID\": \"wifi4\", \"Type\": \"wifi\", \"Connectable\": false,"
251     "  \"Security\": \"802_1x\","
252     "  \"UIData\": \"{"
253     "    \\\"certificate_type\\\": \\\"pattern\\\","
254     "    \\\"certificate_pattern\\\": {"
255     "      \\\"Subject\\\": {\\\"CommonName\\\": \\\"%s\\\" }"
256     "   } }\" }";
257
258 }  // namespace
259
260 // Handle certificates.
261 TEST_F(NetworkConnectionHandlerTest, ConnectCertificateMissing) {
262   StartCertLoader();
263
264   EXPECT_TRUE(Configure(
265       base::StringPrintf(kConfigRequiresCertificateTemplate, "unknown")));
266   Connect("wifi4");
267   EXPECT_EQ(NetworkConnectionHandler::kErrorCertificateRequired,
268             GetResultAndReset());
269 }
270
271 TEST_F(NetworkConnectionHandlerTest, ConnectWithCertificateSuccess) {
272   StartCertLoader();
273
274   net::CertificateList certs;
275   ImportClientCertAndKey("websocket_client_cert.p12",
276                          test_nssdb_.get(),
277                          &certs);
278
279   EXPECT_TRUE(Configure(
280       base::StringPrintf(kConfigRequiresCertificateTemplate,
281                          certs[0]->subject().common_name.c_str())));
282
283   Connect("wifi4");
284   EXPECT_EQ(kSuccessResult, GetResultAndReset());
285 }
286
287 TEST_F(NetworkConnectionHandlerTest,
288        ConnectWithCertificateRequestedBeforeCertsAreLoaded) {
289   net::CertificateList certs;
290   ImportClientCertAndKey("websocket_client_cert.p12",
291                          test_nssdb_.get(),
292                          &certs);
293
294   EXPECT_TRUE(Configure(
295       base::StringPrintf(kConfigRequiresCertificateTemplate,
296                          certs[0]->subject().common_name.c_str())));
297
298   Connect("wifi4");
299
300   // Connect request came before the cert loader loaded certificates, so the
301   // connect request should have been throttled until the certificates are
302   // loaded.
303   EXPECT_EQ("", GetResultAndReset());
304
305   StartCertLoader();
306
307   // |StartCertLoader| should have triggered certificate loading.
308   // When the certificates got loaded, the connection request should have
309   // proceeded and eventually succeeded.
310   EXPECT_EQ(kSuccessResult, GetResultAndReset());
311 }
312
313 TEST_F(NetworkConnectionHandlerTest,
314        NetworkConnectionHandlerDisconnectSuccess) {
315   EXPECT_TRUE(Configure(kConfigConnected));
316   Disconnect("wifi1");
317   EXPECT_EQ(kSuccessResult, GetResultAndReset());
318 }
319
320 TEST_F(NetworkConnectionHandlerTest,
321        NetworkConnectionHandlerDisconnectFailure) {
322   Connect("no-network");
323   EXPECT_EQ(NetworkConnectionHandler::kErrorConfigureFailed,
324             GetResultAndReset());
325
326   EXPECT_TRUE(Configure(kConfigConnectable));
327   Disconnect("wifi0");
328   EXPECT_EQ(NetworkConnectionHandler::kErrorNotConnected, GetResultAndReset());
329 }
330
331 }  // namespace chromeos