Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / chromeos / network / auto_connect_handler.cc
blobedb8c6dd94d54b68f082eb49db27f394ede28674
1 // Copyright 2014 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.
5 #include "chromeos/network/auto_connect_handler.h"
8 #include "base/bind.h"
9 #include "base/bind_helpers.h"
10 #include "base/location.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "base/values.h"
14 #include "chromeos/dbus/dbus_thread_manager.h"
15 #include "chromeos/dbus/shill_manager_client.h"
16 #include "chromeos/dbus/shill_service_client.h"
17 #include "chromeos/network/device_state.h"
18 #include "chromeos/network/managed_network_configuration_handler.h"
19 #include "chromeos/network/network_connection_handler.h"
20 #include "chromeos/network/network_event_log.h"
21 #include "chromeos/network/network_state.h"
22 #include "chromeos/network/network_type_pattern.h"
23 #include "dbus/object_path.h"
24 #include "third_party/cros_system_api/dbus/service_constants.h"
26 namespace chromeos {
28 AutoConnectHandler::AutoConnectHandler()
29 : client_cert_resolver_(nullptr),
30 request_best_connection_pending_(false),
31 device_policy_applied_(false),
32 user_policy_applied_(false),
33 client_certs_resolved_(false),
34 applied_autoconnect_policy_(false),
35 connect_to_best_services_after_scan_(false),
36 weak_ptr_factory_(this) {
39 AutoConnectHandler::~AutoConnectHandler() {
40 if (client_cert_resolver_)
41 client_cert_resolver_->RemoveObserver(this);
42 if (LoginState::IsInitialized())
43 LoginState::Get()->RemoveObserver(this);
44 if (network_state_handler_)
45 network_state_handler_->RemoveObserver(this, FROM_HERE);
46 if (managed_configuration_handler_)
47 managed_configuration_handler_->RemoveObserver(this);
50 void AutoConnectHandler::Init(
51 ClientCertResolver* client_cert_resolver,
52 NetworkConnectionHandler* network_connection_handler,
53 NetworkStateHandler* network_state_handler,
54 ManagedNetworkConfigurationHandler* managed_network_configuration_handler) {
55 if (LoginState::IsInitialized())
56 LoginState::Get()->AddObserver(this);
58 client_cert_resolver_ = client_cert_resolver;
59 if (client_cert_resolver_)
60 client_cert_resolver_->AddObserver(this);
62 network_connection_handler_ = network_connection_handler;
63 if (network_connection_handler_)
64 network_connection_handler_->AddObserver(this);
66 network_state_handler_ = network_state_handler;
67 if (network_state_handler_)
68 network_state_handler_->AddObserver(this, FROM_HERE);
70 managed_configuration_handler_ = managed_network_configuration_handler;
71 if (managed_configuration_handler_)
72 managed_configuration_handler_->AddObserver(this);
74 if (LoginState::IsInitialized())
75 LoggedInStateChanged();
78 void AutoConnectHandler::LoggedInStateChanged() {
79 if (!LoginState::Get()->IsUserLoggedIn())
80 return;
82 // Disconnect before connecting, to ensure that we do not disconnect a network
83 // that we just connected.
84 DisconnectIfPolicyRequires();
85 NET_LOG_DEBUG("RequestBestConnection", "User logged in");
86 RequestBestConnection();
89 void AutoConnectHandler::ConnectToNetworkRequested(
90 const std::string& /*service_path*/) {
91 // Stop any pending request to connect to the best newtork.
92 request_best_connection_pending_ = false;
95 void AutoConnectHandler::PoliciesChanged(const std::string& userhash) {
96 // Ignore user policies.
97 if (!userhash.empty())
98 return;
99 DisconnectIfPolicyRequires();
102 void AutoConnectHandler::PoliciesApplied(const std::string& userhash) {
103 if (userhash.empty())
104 device_policy_applied_ = true;
105 else
106 user_policy_applied_ = true;
108 // Request to connect to the best network only if there is at least one
109 // managed network. Otherwise only process existing requests.
110 const ManagedNetworkConfigurationHandler::GuidToPolicyMap* managed_networks =
111 managed_configuration_handler_->GetNetworkConfigsFromPolicy(userhash);
112 DCHECK(managed_networks);
113 if (!managed_networks->empty()) {
114 NET_LOG_DEBUG("RequestBestConnection", "Policy applied");
115 RequestBestConnection();
116 } else {
117 CheckBestConnection();
121 void AutoConnectHandler::ScanCompleted(const DeviceState* device) {
122 if (!connect_to_best_services_after_scan_ ||
123 device->type() != shill::kTypeWifi) {
124 return;
126 connect_to_best_services_after_scan_ = false;
127 // Request ConnectToBestServices after processing any pending DBus calls.
128 base::ThreadTaskRunnerHandle::Get()->PostTask(
129 FROM_HERE, base::Bind(&AutoConnectHandler::CallShillConnectToBestServices,
130 weak_ptr_factory_.GetWeakPtr()));
133 void AutoConnectHandler::ResolveRequestCompleted(
134 bool network_properties_changed) {
135 client_certs_resolved_ = true;
137 // Only request to connect to the best network if network properties were
138 // actually changed. Otherwise only process existing requests.
139 if (network_properties_changed) {
140 NET_LOG_DEBUG("RequestBestConnection",
141 "Client certificate patterns resolved");
142 RequestBestConnection();
143 } else {
144 CheckBestConnection();
148 void AutoConnectHandler::RequestBestConnection() {
149 request_best_connection_pending_ = true;
150 CheckBestConnection();
153 void AutoConnectHandler::CheckBestConnection() {
154 // Return immediately if there is currently no request pending to change to
155 // the best network.
156 if (!request_best_connection_pending_)
157 return;
159 bool policy_application_running =
160 managed_configuration_handler_->IsAnyPolicyApplicationRunning();
161 bool client_cert_resolve_task_running =
162 client_cert_resolver_->IsAnyResolveTaskRunning();
163 VLOG(2) << "device policy applied: " << device_policy_applied_
164 << "\nuser policy applied: " << user_policy_applied_
165 << "\npolicy application running: " << policy_application_running
166 << "\nclient cert patterns resolved: " << client_certs_resolved_
167 << "\nclient cert resolve task running: "
168 << client_cert_resolve_task_running;
169 if (!device_policy_applied_ || policy_application_running ||
170 client_cert_resolve_task_running) {
171 return;
174 if (LoginState::Get()->IsUserLoggedIn()) {
175 // Before changing connection after login, we wait at least for:
176 // - user policy applied at least once
177 // - client certificate patterns resolved
178 if (!user_policy_applied_ || !client_certs_resolved_)
179 return;
182 request_best_connection_pending_ = false;
184 // Trigger a ConnectToBestNetwork request after the next scan completion.
185 // Note: there is an edge case here if a scan is in progress and a hidden
186 // network has been configured since the scan started. crbug.com/433075.
187 if (connect_to_best_services_after_scan_)
188 return;
189 connect_to_best_services_after_scan_ = true;
190 if (!network_state_handler_->GetScanningByType(
191 NetworkTypePattern::Primitive(shill::kTypeWifi))) {
192 network_state_handler_->RequestScan();
196 void AutoConnectHandler::DisconnectIfPolicyRequires() {
197 if (applied_autoconnect_policy_ || !LoginState::Get()->IsUserLoggedIn())
198 return;
200 const base::DictionaryValue* global_network_config =
201 managed_configuration_handler_->GetGlobalConfigFromPolicy(
202 std::string() /* no username hash, device policy */);
204 if (!global_network_config)
205 return; // Device policy is not set, yet.
207 applied_autoconnect_policy_ = true;
209 bool only_policy_autoconnect = false;
210 global_network_config->GetBooleanWithoutPathExpansion(
211 ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect,
212 &only_policy_autoconnect);
214 if (only_policy_autoconnect)
215 DisconnectFromUnmanagedSharedWiFiNetworks();
218 void AutoConnectHandler::DisconnectFromUnmanagedSharedWiFiNetworks() {
219 NET_LOG_DEBUG("DisconnectFromUnmanagedSharedWiFiNetworks", "");
221 NetworkStateHandler::NetworkStateList networks;
222 network_state_handler_->GetVisibleNetworkListByType(
223 NetworkTypePattern::Wireless(), &networks);
224 for (const NetworkState* network : networks) {
225 if (!(network->IsConnectingState() || network->IsConnectedState()))
226 break; // Connected and connecting networks are listed first.
228 if (network->IsPrivate())
229 continue;
231 const bool network_is_policy_managed =
232 !network->profile_path().empty() && !network->guid().empty() &&
233 managed_configuration_handler_->FindPolicyByGuidAndProfile(
234 network->guid(), network->profile_path());
235 if (network_is_policy_managed)
236 continue;
238 NET_LOG_EVENT("Disconnect Forced by Policy", network->path());
239 DBusThreadManager::Get()->GetShillServiceClient()->Disconnect(
240 dbus::ObjectPath(network->path()), base::Bind(&base::DoNothing),
241 base::Bind(&network_handler::ShillErrorCallbackFunction,
242 "AutoConnectHandler.Disconnect failed", network->path(),
243 network_handler::ErrorCallback()));
247 void AutoConnectHandler::CallShillConnectToBestServices() const {
248 NET_LOG_EVENT("ConnectToBestServices", "");
249 DBusThreadManager::Get()->GetShillManagerClient()->ConnectToBestServices(
250 base::Bind(&base::DoNothing),
251 base::Bind(&network_handler::ShillErrorCallbackFunction,
252 "ConnectToBestServices Failed",
253 "", network_handler::ErrorCallback()));
256 } // namespace chromeos