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 "extensions/browser/api/networking_private/networking_private_chromeos.h"
8 #include "base/bind_helpers.h"
9 #include "base/callback.h"
10 #include "chromeos/dbus/dbus_thread_manager.h"
11 #include "chromeos/dbus/shill_manager_client.h"
12 #include "chromeos/login/login_state.h"
13 #include "chromeos/network/device_state.h"
14 #include "chromeos/network/managed_network_configuration_handler.h"
15 #include "chromeos/network/network_activation_handler.h"
16 #include "chromeos/network/network_connection_handler.h"
17 #include "chromeos/network/network_device_handler.h"
18 #include "chromeos/network/network_event_log.h"
19 #include "chromeos/network/network_state.h"
20 #include "chromeos/network/network_state_handler.h"
21 #include "chromeos/network/network_util.h"
22 #include "chromeos/network/onc/onc_signature.h"
23 #include "chromeos/network/onc/onc_translator.h"
24 #include "chromeos/network/onc/onc_utils.h"
25 #include "chromeos/network/portal_detector/network_portal_detector.h"
26 #include "components/onc/onc_constants.h"
27 #include "content/public/browser/browser_context.h"
28 #include "extensions/browser/api/networking_private/networking_private_api.h"
29 #include "extensions/browser/extensions_browser_client.h"
30 #include "third_party/cros_system_api/dbus/service_constants.h"
32 using chromeos::DeviceState
;
33 using chromeos::NetworkHandler
;
34 using chromeos::NetworkStateHandler
;
35 using chromeos::NetworkTypePattern
;
36 using chromeos::ShillManagerClient
;
37 using extensions::NetworkingPrivateDelegate
;
39 namespace private_api
= extensions::api::networking_private
;
43 chromeos::NetworkStateHandler
* GetStateHandler() {
44 return NetworkHandler::Get()->network_state_handler();
47 chromeos::ManagedNetworkConfigurationHandler
* GetManagedConfigurationHandler() {
48 return NetworkHandler::Get()->managed_network_configuration_handler();
51 bool GetServicePathFromGuid(const std::string
& guid
,
52 std::string
* service_path
,
54 const chromeos::NetworkState
* network
=
55 GetStateHandler()->GetNetworkStateFromGuid(guid
);
57 *error
= extensions::networking_private::kErrorInvalidNetworkGuid
;
60 *service_path
= network
->path();
64 bool GetUserIdHash(content::BrowserContext
* browser_context
,
65 std::string
* user_hash
,
67 std::string context_user_hash
=
68 extensions::ExtensionsBrowserClient::Get()->GetUserIdHashFromContext(
71 // Currently Chrome OS only configures networks for the primary user.
72 // Configuration attempts from other browser contexts should fail.
73 if (context_user_hash
!= chromeos::LoginState::Get()->primary_user_hash()) {
74 // Disallow class requiring a user id hash from a non-primary user context
75 // to avoid complexities with the policy code.
76 LOG(ERROR
) << "networkingPrivate API call from non primary user: "
78 *error
= "Error.NonPrimaryUser";
81 *user_hash
= context_user_hash
;
85 void AppendDeviceState(
86 const std::string
& type
,
87 const DeviceState
* device
,
88 NetworkingPrivateDelegate::DeviceStateList
* device_state_list
) {
89 DCHECK(!type
.empty());
90 NetworkTypePattern pattern
=
91 chromeos::onc::NetworkTypePatternFromOncType(type
);
92 NetworkStateHandler::TechnologyState technology_state
=
93 GetStateHandler()->GetTechnologyState(pattern
);
94 private_api::DeviceStateType state
= private_api::DEVICE_STATE_TYPE_NONE
;
95 switch (technology_state
) {
96 case NetworkStateHandler::TECHNOLOGY_UNAVAILABLE
:
99 // If we have a DeviceState entry but the technology is not available,
100 // assume the technology is not initialized.
101 state
= private_api::DEVICE_STATE_TYPE_UNINITIALIZED
;
103 case NetworkStateHandler::TECHNOLOGY_AVAILABLE
:
104 state
= private_api::DEVICE_STATE_TYPE_DISABLED
;
106 case NetworkStateHandler::TECHNOLOGY_UNINITIALIZED
:
107 state
= private_api::DEVICE_STATE_TYPE_UNINITIALIZED
;
109 case NetworkStateHandler::TECHNOLOGY_ENABLING
:
110 state
= private_api::DEVICE_STATE_TYPE_ENABLING
;
112 case NetworkStateHandler::TECHNOLOGY_ENABLED
:
113 state
= private_api::DEVICE_STATE_TYPE_ENABLED
;
116 DCHECK_NE(private_api::DEVICE_STATE_TYPE_NONE
, state
);
117 scoped_ptr
<private_api::DeviceStateProperties
> properties(
118 new private_api::DeviceStateProperties
);
119 properties
->type
= private_api::ParseNetworkType(type
);
120 properties
->state
= state
;
121 if (device
&& state
== private_api::DEVICE_STATE_TYPE_ENABLED
)
122 properties
->scanning
.reset(new bool(device
->scanning()));
123 device_state_list
->push_back(properties
.Pass());
126 void NetworkHandlerDictionaryCallback(
127 const NetworkingPrivateDelegate::DictionaryCallback
& callback
,
128 const std::string
& service_path
,
129 const base::DictionaryValue
& dictionary
) {
130 scoped_ptr
<base::DictionaryValue
> dictionary_copy(dictionary
.DeepCopy());
131 callback
.Run(dictionary_copy
.Pass());
134 void NetworkHandlerFailureCallback(
135 const NetworkingPrivateDelegate::FailureCallback
& callback
,
136 const std::string
& error_name
,
137 scoped_ptr
<base::DictionaryValue
> error_data
) {
138 callback
.Run(error_name
);
141 void RequirePinSuccess(
142 const std::string
& device_path
,
143 const std::string
& current_pin
,
144 const std::string
& new_pin
,
145 const extensions::NetworkingPrivateChromeOS::VoidCallback
& success_callback
,
146 const extensions::NetworkingPrivateChromeOS::FailureCallback
&
148 // After RequirePin succeeds, call ChangePIN iff a different new_pin is
150 if (new_pin
.empty() || new_pin
== current_pin
) {
151 success_callback
.Run();
154 NetworkHandler::Get()->network_device_handler()->ChangePin(
155 device_path
, current_pin
, new_pin
, success_callback
,
156 base::Bind(&NetworkHandlerFailureCallback
, failure_callback
));
161 ////////////////////////////////////////////////////////////////////////////////
163 namespace extensions
{
165 NetworkingPrivateChromeOS::NetworkingPrivateChromeOS(
166 content::BrowserContext
* browser_context
,
167 scoped_ptr
<VerifyDelegate
> verify_delegate
)
168 : NetworkingPrivateDelegate(verify_delegate
.Pass()),
169 browser_context_(browser_context
),
170 weak_ptr_factory_(this) {}
172 NetworkingPrivateChromeOS::~NetworkingPrivateChromeOS() {
175 void NetworkingPrivateChromeOS::GetProperties(
176 const std::string
& guid
,
177 const DictionaryCallback
& success_callback
,
178 const FailureCallback
& failure_callback
) {
179 std::string service_path
, error
;
180 if (!GetServicePathFromGuid(guid
, &service_path
, &error
)) {
181 failure_callback
.Run(error
);
185 GetManagedConfigurationHandler()->GetProperties(
187 base::Bind(&NetworkHandlerDictionaryCallback
, success_callback
),
188 base::Bind(&NetworkHandlerFailureCallback
, failure_callback
));
191 void NetworkingPrivateChromeOS::GetManagedProperties(
192 const std::string
& guid
,
193 const DictionaryCallback
& success_callback
,
194 const FailureCallback
& failure_callback
) {
195 std::string service_path
, error
;
196 if (!GetServicePathFromGuid(guid
, &service_path
, &error
)) {
197 failure_callback
.Run(error
);
201 std::string user_id_hash
;
202 if (!GetUserIdHash(browser_context_
, &user_id_hash
, &error
)) {
203 failure_callback
.Run(error
);
207 GetManagedConfigurationHandler()->GetManagedProperties(
208 user_id_hash
, service_path
,
209 base::Bind(&NetworkHandlerDictionaryCallback
, success_callback
),
210 base::Bind(&NetworkHandlerFailureCallback
, failure_callback
));
213 void NetworkingPrivateChromeOS::GetState(
214 const std::string
& guid
,
215 const DictionaryCallback
& success_callback
,
216 const FailureCallback
& failure_callback
) {
217 std::string service_path
, error
;
218 if (!GetServicePathFromGuid(guid
, &service_path
, &error
)) {
219 failure_callback
.Run(error
);
223 const chromeos::NetworkState
* network_state
=
224 GetStateHandler()->GetNetworkStateFromServicePath(
225 service_path
, false /* configured_only */);
226 if (!network_state
) {
227 failure_callback
.Run(networking_private::kErrorNetworkUnavailable
);
231 scoped_ptr
<base::DictionaryValue
> network_properties
=
232 chromeos::network_util::TranslateNetworkStateToONC(network_state
);
234 success_callback
.Run(network_properties
.Pass());
237 void NetworkingPrivateChromeOS::SetProperties(
238 const std::string
& guid
,
239 scoped_ptr
<base::DictionaryValue
> properties
,
240 const VoidCallback
& success_callback
,
241 const FailureCallback
& failure_callback
) {
242 std::string service_path
, error
;
243 if (!GetServicePathFromGuid(guid
, &service_path
, &error
)) {
244 failure_callback
.Run(error
);
248 GetManagedConfigurationHandler()->SetProperties(
249 service_path
, *properties
, success_callback
,
250 base::Bind(&NetworkHandlerFailureCallback
, failure_callback
));
253 void NetworkingPrivateChromeOS::CreateNetwork(
255 scoped_ptr
<base::DictionaryValue
> properties
,
256 const StringCallback
& success_callback
,
257 const FailureCallback
& failure_callback
) {
258 std::string user_id_hash
, error
;
259 // Do not allow configuring a non-shared network from a non-primary user.
260 if (!shared
&& !GetUserIdHash(browser_context_
, &user_id_hash
, &error
)) {
261 failure_callback
.Run(error
);
265 GetManagedConfigurationHandler()->CreateConfiguration(
266 user_id_hash
, *properties
, success_callback
,
267 base::Bind(&NetworkHandlerFailureCallback
, failure_callback
));
270 void NetworkingPrivateChromeOS::ForgetNetwork(
271 const std::string
& guid
,
272 const VoidCallback
& success_callback
,
273 const FailureCallback
& failure_callback
) {
274 std::string service_path
, error
;
275 if (!GetServicePathFromGuid(guid
, &service_path
, &error
)) {
276 failure_callback
.Run(error
);
280 GetManagedConfigurationHandler()->RemoveConfiguration(
281 service_path
, success_callback
,
282 base::Bind(&NetworkHandlerFailureCallback
, failure_callback
));
285 void NetworkingPrivateChromeOS::GetNetworks(
286 const std::string
& network_type
,
287 bool configured_only
,
290 const NetworkListCallback
& success_callback
,
291 const FailureCallback
& failure_callback
) {
292 NetworkTypePattern pattern
=
293 chromeos::onc::NetworkTypePatternFromOncType(network_type
);
294 scoped_ptr
<base::ListValue
> network_properties_list
=
295 chromeos::network_util::TranslateNetworkListToONC(
296 pattern
, configured_only
, visible_only
, limit
);
297 success_callback
.Run(network_properties_list
.Pass());
300 void NetworkingPrivateChromeOS::StartConnect(
301 const std::string
& guid
,
302 const VoidCallback
& success_callback
,
303 const FailureCallback
& failure_callback
) {
304 std::string service_path
, error
;
305 if (!GetServicePathFromGuid(guid
, &service_path
, &error
)) {
306 failure_callback
.Run(error
);
310 const bool check_error_state
= false;
311 NetworkHandler::Get()->network_connection_handler()->ConnectToNetwork(
312 service_path
, success_callback
,
313 base::Bind(&NetworkingPrivateChromeOS::ConnectFailureCallback
,
314 weak_ptr_factory_
.GetWeakPtr(), guid
, success_callback
,
319 void NetworkingPrivateChromeOS::ConnectFailureCallback(
320 const std::string
& guid
,
321 const VoidCallback
& success_callback
,
322 const FailureCallback
& failure_callback
,
323 const std::string
& error_name
,
324 scoped_ptr
<base::DictionaryValue
> error_data
) {
325 // TODO(stevenjb): Temporary workaround to show the configuration UI.
326 // Eventually the caller (e.g. Settings) should handle any failures and
327 // show its own configuration UI. crbug.com/380937.
328 if (ui_delegate()->HandleConnectFailed(guid
, error_name
)) {
329 success_callback
.Run();
332 failure_callback
.Run(error_name
);
335 void NetworkingPrivateChromeOS::StartDisconnect(
336 const std::string
& guid
,
337 const VoidCallback
& success_callback
,
338 const FailureCallback
& failure_callback
) {
339 std::string service_path
, error
;
340 if (!GetServicePathFromGuid(guid
, &service_path
, &error
)) {
341 failure_callback
.Run(error
);
345 NetworkHandler::Get()->network_connection_handler()->DisconnectNetwork(
346 service_path
, success_callback
,
347 base::Bind(&NetworkHandlerFailureCallback
, failure_callback
));
350 void NetworkingPrivateChromeOS::StartActivate(
351 const std::string
& guid
,
352 const std::string
& specified_carrier
,
353 const VoidCallback
& success_callback
,
354 const FailureCallback
& failure_callback
) {
355 const chromeos::NetworkState
* network
=
356 GetStateHandler()->GetNetworkStateFromGuid(guid
);
358 failure_callback
.Run(
359 extensions::networking_private::kErrorInvalidNetworkGuid
);
363 std::string
carrier(specified_carrier
);
364 if (carrier
.empty()) {
365 const chromeos::DeviceState
* device
=
366 GetStateHandler()->GetDeviceState(network
->device_path());
368 carrier
= device
->carrier();
370 if (carrier
!= shill::kCarrierSprint
) {
371 // Only Sprint is directly activated. For other carriers, show the
372 // account details page.
374 ui_delegate()->ShowAccountDetails(guid
);
375 success_callback
.Run();
379 if (!network
->RequiresActivation()) {
380 // If no activation is required, show the account details page.
382 ui_delegate()->ShowAccountDetails(guid
);
383 success_callback
.Run();
387 NetworkHandler::Get()->network_activation_handler()->Activate(
388 network
->path(), carrier
, success_callback
,
389 base::Bind(&NetworkHandlerFailureCallback
, failure_callback
));
392 void NetworkingPrivateChromeOS::SetWifiTDLSEnabledState(
393 const std::string
& ip_or_mac_address
,
395 const StringCallback
& success_callback
,
396 const FailureCallback
& failure_callback
) {
397 NetworkHandler::Get()->network_device_handler()->SetWifiTDLSEnabled(
398 ip_or_mac_address
, enabled
, success_callback
,
399 base::Bind(&NetworkHandlerFailureCallback
, failure_callback
));
402 void NetworkingPrivateChromeOS::GetWifiTDLSStatus(
403 const std::string
& ip_or_mac_address
,
404 const StringCallback
& success_callback
,
405 const FailureCallback
& failure_callback
) {
406 NetworkHandler::Get()->network_device_handler()->GetWifiTDLSStatus(
407 ip_or_mac_address
, success_callback
,
408 base::Bind(&NetworkHandlerFailureCallback
, failure_callback
));
411 void NetworkingPrivateChromeOS::GetCaptivePortalStatus(
412 const std::string
& guid
,
413 const StringCallback
& success_callback
,
414 const FailureCallback
& failure_callback
) {
415 if (!chromeos::NetworkPortalDetector::IsInitialized()) {
416 failure_callback
.Run(networking_private::kErrorNotReady
);
420 chromeos::NetworkPortalDetector::CaptivePortalState state
=
421 chromeos::NetworkPortalDetector::Get()->GetCaptivePortalState(guid
);
422 success_callback
.Run(
423 chromeos::NetworkPortalDetector::CaptivePortalStatusString(state
.status
));
426 void NetworkingPrivateChromeOS::UnlockCellularSim(
427 const std::string
& guid
,
428 const std::string
& pin
,
429 const std::string
& puk
,
430 const VoidCallback
& success_callback
,
431 const FailureCallback
& failure_callback
) {
432 const chromeos::NetworkState
* network_state
=
433 GetStateHandler()->GetNetworkStateFromGuid(guid
);
434 if (!network_state
) {
435 failure_callback
.Run(networking_private::kErrorNetworkUnavailable
);
438 const chromeos::DeviceState
* device_state
=
439 GetStateHandler()->GetDeviceState(network_state
->device_path());
441 failure_callback
.Run(networking_private::kErrorNetworkUnavailable
);
444 std::string lock_type
= device_state
->sim_lock_type();
445 if (lock_type
.empty()) {
446 // Sim is already unlocked.
447 failure_callback
.Run(networking_private::kErrorInvalidNetworkOperation
);
451 // Unblock or unlock the SIM.
452 if (lock_type
== shill::kSIMLockPuk
) {
453 NetworkHandler::Get()->network_device_handler()->UnblockPin(
454 device_state
->path(), puk
, pin
, success_callback
,
455 base::Bind(&NetworkHandlerFailureCallback
, failure_callback
));
457 NetworkHandler::Get()->network_device_handler()->EnterPin(
458 device_state
->path(), pin
, success_callback
,
459 base::Bind(&NetworkHandlerFailureCallback
, failure_callback
));
463 void NetworkingPrivateChromeOS::SetCellularSimState(
464 const std::string
& guid
,
466 const std::string
& current_pin
,
467 const std::string
& new_pin
,
468 const VoidCallback
& success_callback
,
469 const FailureCallback
& failure_callback
) {
470 const chromeos::NetworkState
* network_state
=
471 GetStateHandler()->GetNetworkStateFromGuid(guid
);
472 if (!network_state
) {
473 failure_callback
.Run(networking_private::kErrorNetworkUnavailable
);
476 const chromeos::DeviceState
* device_state
=
477 GetStateHandler()->GetDeviceState(network_state
->device_path());
479 failure_callback
.Run(networking_private::kErrorNetworkUnavailable
);
482 if (!device_state
->sim_lock_type().empty()) {
483 // The SIM needs to be unlocked before the state can be changed.
484 failure_callback
.Run(networking_private::kErrorSimLocked
);
488 // Only set a new pin if require_pin is true.
489 std::string set_new_pin
= require_pin
? new_pin
: "";
490 NetworkHandler::Get()->network_device_handler()->RequirePin(
491 device_state
->path(), require_pin
, current_pin
,
492 base::Bind(&RequirePinSuccess
, device_state
->path(), current_pin
,
493 set_new_pin
, success_callback
, failure_callback
),
494 base::Bind(&NetworkHandlerFailureCallback
, failure_callback
));
497 scoped_ptr
<base::ListValue
>
498 NetworkingPrivateChromeOS::GetEnabledNetworkTypes() {
499 chromeos::NetworkStateHandler
* state_handler
= GetStateHandler();
501 scoped_ptr
<base::ListValue
> network_list(new base::ListValue
);
503 if (state_handler
->IsTechnologyEnabled(NetworkTypePattern::Ethernet()))
504 network_list
->AppendString(::onc::network_type::kEthernet
);
505 if (state_handler
->IsTechnologyEnabled(NetworkTypePattern::WiFi()))
506 network_list
->AppendString(::onc::network_type::kWiFi
);
507 if (state_handler
->IsTechnologyEnabled(NetworkTypePattern::Wimax()))
508 network_list
->AppendString(::onc::network_type::kWimax
);
509 if (state_handler
->IsTechnologyEnabled(NetworkTypePattern::Cellular()))
510 network_list
->AppendString(::onc::network_type::kCellular
);
512 return network_list
.Pass();
515 scoped_ptr
<NetworkingPrivateDelegate::DeviceStateList
>
516 NetworkingPrivateChromeOS::GetDeviceStateList() {
517 std::set
<std::string
> technologies_found
;
518 NetworkStateHandler::DeviceStateList devices
;
519 NetworkHandler::Get()->network_state_handler()->GetDeviceList(&devices
);
521 scoped_ptr
<DeviceStateList
> device_state_list(new DeviceStateList
);
522 for (const DeviceState
* device
: devices
) {
523 std::string onc_type
=
524 chromeos::network_util::TranslateShillTypeToONC(device
->type());
525 AppendDeviceState(onc_type
, device
, device_state_list
.get());
526 technologies_found
.insert(onc_type
);
529 // For any technologies that we do not have a DeviceState entry for, append
530 // an entry if the technolog is available.
531 const char* technology_types
[] = {::onc::network_type::kEthernet
,
532 ::onc::network_type::kWiFi
,
533 ::onc::network_type::kWimax
,
534 ::onc::network_type::kCellular
};
535 for (const char* technology
: technology_types
) {
536 if (ContainsValue(technologies_found
, technology
))
538 AppendDeviceState(technology
, nullptr /* device */,
539 device_state_list
.get());
541 return device_state_list
.Pass();
544 bool NetworkingPrivateChromeOS::EnableNetworkType(const std::string
& type
) {
545 NetworkTypePattern pattern
=
546 chromeos::onc::NetworkTypePatternFromOncType(type
);
548 GetStateHandler()->SetTechnologyEnabled(
549 pattern
, true, chromeos::network_handler::ErrorCallback());
554 bool NetworkingPrivateChromeOS::DisableNetworkType(const std::string
& type
) {
555 NetworkTypePattern pattern
=
556 chromeos::onc::NetworkTypePatternFromOncType(type
);
558 GetStateHandler()->SetTechnologyEnabled(
559 pattern
, false, chromeos::network_handler::ErrorCallback());
564 bool NetworkingPrivateChromeOS::RequestScan() {
565 GetStateHandler()->RequestScan();
569 } // namespace extensions