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#ifndef CHROMEOS_NETWORK_NETWORK_CONNECTION_HANDLER_H_
6#define CHROMEOS_NETWORK_NETWORK_CONNECTION_HANDLER_H_
7
8#include <set>
9#include <string>
10
11#include "base/basictypes.h"
12#include "base/callback.h"
13#include "base/memory/weak_ptr.h"
14#include "base/time/time.h"
15#include "base/values.h"
16#include "chromeos/cert_loader.h"
17#include "chromeos/chromeos_export.h"
18#include "chromeos/dbus/dbus_method_call_status.h"
19#include "chromeos/login/login_state.h"
20#include "chromeos/network/network_handler.h"
21#include "chromeos/network/network_handler_callbacks.h"
22#include "chromeos/network/network_policy_observer.h"
23#include "chromeos/network/network_state_handler_observer.h"
24
25namespace chromeos {
26
27class NetworkState;
28
29// The NetworkConnectionHandler class is used to manage network connection
30// requests. This is the only class that should make Shill Connect calls.
31// It handles the following steps:
32// 1. Determine whether or not sufficient information (e.g. passphrase) is
33//    known to be available to connect to the network.
34// 2. Request additional information (e.g. user data which contains certificate
35//    information) and determine whether sufficient information is available.
36// 3. Possibly configure the network certificate info (tpm slot and pkcs11 id).
37// 4. Send the connect request.
38// 5. Wait for the network state to change to a non connecting state.
39// 6. Invoke the appropriate callback (always) on success or failure.
40//
41// NetworkConnectionHandler depends on NetworkStateHandler for immediately
42// available State information, and NetworkConfigurationHandler for any
43// configuration calls.
44
45class CHROMEOS_EXPORT NetworkConnectionHandler
46    : public LoginState::Observer,
47      public CertLoader::Observer,
48      public NetworkStateHandlerObserver,
49      public NetworkPolicyObserver,
50      public base::SupportsWeakPtr<NetworkConnectionHandler> {
51 public:
52  // Constants for |error_name| from |error_callback| for Connect.
53
54  //  No network matching |service_path| is found (hidden networks must be
55  //  configured before connecting).
56  static const char kErrorNotFound[];
57
58  // Already connected to the network.
59  static const char kErrorConnected[];
60
61  // Already connecting to the network.
62  static const char kErrorConnecting[];
63
64  // The passphrase is missing or invalid.
65  static const char kErrorPassphraseRequired[];
66
67  static const char kErrorActivationRequired[];
68
69  // The network requires a cert and none exists.
70  static const char kErrorCertificateRequired[];
71
72  // The network had an authentication error, indicating that additional or
73  // different authentication information is required.
74  static const char kErrorAuthenticationRequired[];
75
76  // Additional configuration is required.
77  static const char kErrorConfigurationRequired[];
78
79  // Configuration failed during the configure stage of the connect flow.
80  static const char kErrorConfigureFailed[];
81
82  // For Disconnect or Activate, an unexpected DBus or Shill error occurred.
83  static const char kErrorShillError[];
84
85  // A new network connect request canceled this one.
86  static const char kErrorConnectCanceled[];
87
88  // Constants for |error_name| from |error_callback| for Disconnect.
89  static const char kErrorNotConnected[];
90
91  // Certificate load timed out.
92  static const char kErrorCertLoadTimeout[];
93
94  virtual ~NetworkConnectionHandler();
95
96  // ConnectToNetwork() will start an asynchronous connection attempt.
97  // On success, |success_callback| will be called.
98  // On failure, |error_callback| will be called with |error_name| one of the
99  //   constants defined above, or shill::kErrorConnectFailed or
100  //   shill::kErrorBadPassphrase if the Shill Error property (from a
101  //   previous connect attempt) was set to one of those.
102  // |error_message| will contain an additional error string for debugging.
103  // If |check_error_state| is true, the current state of the network is
104  //  checked for errors, otherwise current state is ignored (e.g. for recently
105  //  configured networks or repeat attempts).
106  void ConnectToNetwork(const std::string& service_path,
107                        const base::Closure& success_callback,
108                        const network_handler::ErrorCallback& error_callback,
109                        bool check_error_state);
110
111  // DisconnectNetwork() will send a Disconnect request to Shill.
112  // On success, |success_callback| will be called.
113  // On failure, |error_callback| will be called with |error_name| one of:
114  //  kErrorNotFound if no network matching |service_path| is found.
115  //  kErrorNotConnected if not connected to the network.
116  //  kErrorShillError if a DBus or Shill error occurred.
117  // |error_message| will contain and additional error string for debugging.
118  void DisconnectNetwork(const std::string& service_path,
119                         const base::Closure& success_callback,
120                         const network_handler::ErrorCallback& error_callback);
121
122  // Returns true if ConnectToNetwork has been called with |service_path| and
123  // has not completed (i.e. success or error callback has been called).
124  bool HasConnectingNetwork(const std::string& service_path);
125
126  // Returns true if there are any pending connect requests.
127  bool HasPendingConnectRequest();
128
129  // NetworkStateHandlerObserver
130  virtual void NetworkListChanged() OVERRIDE;
131  virtual void NetworkPropertiesUpdated(const NetworkState* network) OVERRIDE;
132
133  // LoginState::Observer
134  virtual void LoggedInStateChanged() OVERRIDE;
135
136  // CertLoader::Observer
137  virtual void OnCertificatesLoaded(const net::CertificateList& cert_list,
138                                    bool initial_load) OVERRIDE;
139
140  // NetworkPolicyObserver
141  virtual void PolicyChanged(const std::string& userhash) OVERRIDE;
142
143 private:
144  friend class NetworkHandler;
145  friend class NetworkConnectionHandlerTest;
146
147  struct ConnectRequest;
148
149  NetworkConnectionHandler();
150
151  void Init(NetworkStateHandler* network_state_handler,
152            NetworkConfigurationHandler* network_configuration_handler,
153            ManagedNetworkConfigurationHandler*
154                managed_network_configuration_handler);
155
156  ConnectRequest* GetPendingRequest(const std::string& service_path);
157
158  // Callback from Shill.Service.GetProperties. Parses |properties| to verify
159  // whether or not the network appears to be configured. If configured,
160  // attempts a connection, otherwise invokes error_callback from
161  // pending_requests_[service_path]. |check_error_state| is passed from
162  // ConnectToNetwork(), see comment for info.
163  void VerifyConfiguredAndConnect(bool check_error_state,
164                                  const std::string& service_path,
165                                  const base::DictionaryValue& properties);
166
167  // Queues a connect request until certificates have loaded.
168  void QueueConnectRequest(const std::string& service_path);
169
170  // Checks to see if certificates have loaded and if not, cancels any queued
171  // connect request and notifies the user.
172  void CheckCertificatesLoaded();
173
174  // Handles connecting to a queued network after certificates are loaded or
175  // handle cert load timeout.
176  void ConnectToQueuedNetwork();
177
178  // Calls Shill.Manager.Connect asynchronously.
179  void CallShillConnect(const std::string& service_path);
180
181  // Handles failure from ConfigurationHandler calls.
182  void HandleConfigurationFailure(
183      const std::string& service_path,
184      const std::string& error_name,
185      scoped_ptr<base::DictionaryValue> error_data);
186
187  // Handles success or failure from Shill.Service.Connect.
188  void HandleShillConnectSuccess(const std::string& service_path);
189  void HandleShillConnectFailure(const std::string& service_path,
190                                 const std::string& error_name,
191                                 const std::string& error_message);
192
193  void CheckPendingRequest(const std::string service_path);
194  void CheckAllPendingRequests();
195
196  void ErrorCallbackForPendingRequest(const std::string& service_path,
197                                      const std::string& error_name);
198
199  // Calls Shill.Manager.Disconnect asynchronously.
200  void CallShillDisconnect(
201      const std::string& service_path,
202      const base::Closure& success_callback,
203      const network_handler::ErrorCallback& error_callback);
204
205  // Handle success from Shill.Service.Disconnect.
206  void HandleShillDisconnectSuccess(const std::string& service_path,
207                                    const base::Closure& success_callback);
208
209  // If the policy to prevent unmanaged & shared networks to autoconnect is
210  // enabled, then disconnect all such networks except wired networks. Does
211  // nothing on consecutive calls.
212  // This is enforced once after a user logs in 1) to allow mananged networks to
213  // autoconnect and 2) to prevent a previous user from foisting a network on
214  // the new user. Therefore, this function is called on startup, at login and
215  // when the device policy is changed.
216  void DisconnectIfPolicyRequires();
217
218  // Requests a connect to the 'best' available network once after login and
219  // after any disconnect required by policy is executed (see
220  // DisconnectIfPolicyRequires()). To include networks with client
221  // certificates, no request is sent until certificates are loaded. Therefore,
222  // this function is called on the initial certificate load and by
223  // DisconnectIfPolicyRequires().
224  void ConnectToBestNetworkAfterLogin();
225
226  // Local references to the associated handler instances.
227  CertLoader* cert_loader_;
228  NetworkStateHandler* network_state_handler_;
229  NetworkConfigurationHandler* configuration_handler_;
230  ManagedNetworkConfigurationHandler* managed_configuration_handler_;
231
232  // Map of pending connect requests, used to prevent repeated attempts while
233  // waiting for Shill and to trigger callbacks on eventual success or failure.
234  std::map<std::string, ConnectRequest> pending_requests_;
235  scoped_ptr<ConnectRequest> queued_connect_;
236
237  // Track certificate loading state.
238  bool logged_in_;
239  bool certificates_loaded_;
240  base::TimeTicks logged_in_time_;
241
242  // Whether the autoconnect policy was applied already, see
243  // DisconnectIfPolicyRequires().
244  bool applied_autoconnect_policy_;
245
246  // Whether the handler already requested a 'ConnectToBestNetwork' after login,
247  // see ConnectToBestNetworkAfterLogin().
248  bool requested_connect_to_best_network_;
249
250  DISALLOW_COPY_AND_ASSIGN(NetworkConnectionHandler);
251};
252
253}  // namespace chromeos
254
255#endif  // CHROMEOS_NETWORK_NETWORK_CONNECTION_HANDLER_H_
256