blob: dcf2eb24b376412d744a07ab57e5b589aabb55ae [file] [log] [blame]
Gilad Arnold55f39b72014-01-28 12:51:45 -08001// Copyright (c) 2014 The Chromium OS 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
Alex Deymo63784a52014-05-28 10:46:14 -07005#include "update_engine/update_manager/real_shill_provider.h"
Gilad Arnold55f39b72014-01-28 12:51:45 -08006
Gilad Arnold5ef9c482014-03-03 13:51:02 -08007#include <string>
8
9#include <base/logging.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070010#include <base/strings/stringprintf.h>
Gilad Arnold5ef9c482014-03-03 13:51:02 -080011#include <chromeos/dbus/service_constants.h>
12
Alex Deymo30534502015-07-20 15:06:33 -070013using org::chromium::flimflam::ManagerProxyInterface;
14using org::chromium::flimflam::ServiceProxyInterface;
Gilad Arnold5ef9c482014-03-03 13:51:02 -080015using std::string;
16
Alex Deymo63784a52014-05-28 10:46:14 -070017namespace chromeos_update_manager {
Gilad Arnold55f39b72014-01-28 12:51:45 -080018
Alex Deymo30534502015-07-20 15:06:33 -070019ConnectionType RealShillProvider::ParseConnectionType(const string& type_str) {
20 if (type_str == shill::kTypeEthernet) {
Gilad Arnoldef120fa2014-04-09 12:52:10 -070021 return ConnectionType::kEthernet;
Alex Deymo30534502015-07-20 15:06:33 -070022 } else if (type_str == shill::kTypeWifi) {
Gilad Arnoldef120fa2014-04-09 12:52:10 -070023 return ConnectionType::kWifi;
Alex Deymo30534502015-07-20 15:06:33 -070024 } else if (type_str == shill::kTypeWimax) {
Gilad Arnoldef120fa2014-04-09 12:52:10 -070025 return ConnectionType::kWimax;
Alex Deymo30534502015-07-20 15:06:33 -070026 } else if (type_str == shill::kTypeBluetooth) {
Gilad Arnoldef120fa2014-04-09 12:52:10 -070027 return ConnectionType::kBluetooth;
Alex Deymo30534502015-07-20 15:06:33 -070028 } else if (type_str == shill::kTypeCellular) {
Gilad Arnoldef120fa2014-04-09 12:52:10 -070029 return ConnectionType::kCellular;
Alex Deymo30534502015-07-20 15:06:33 -070030 }
Gilad Arnoldef120fa2014-04-09 12:52:10 -070031 return ConnectionType::kUnknown;
32}
33
34ConnectionTethering RealShillProvider::ParseConnectionTethering(
Alex Deymo30534502015-07-20 15:06:33 -070035 const string& tethering_str) {
36 if (tethering_str == shill::kTetheringNotDetectedState) {
Gilad Arnoldef120fa2014-04-09 12:52:10 -070037 return ConnectionTethering::kNotDetected;
Alex Deymo30534502015-07-20 15:06:33 -070038 } else if (tethering_str == shill::kTetheringSuspectedState) {
Gilad Arnoldef120fa2014-04-09 12:52:10 -070039 return ConnectionTethering::kSuspected;
Alex Deymo30534502015-07-20 15:06:33 -070040 } else if (tethering_str == shill::kTetheringConfirmedState) {
Gilad Arnoldef120fa2014-04-09 12:52:10 -070041 return ConnectionTethering::kConfirmed;
Alex Deymo30534502015-07-20 15:06:33 -070042 }
Gilad Arnoldef120fa2014-04-09 12:52:10 -070043 return ConnectionTethering::kUnknown;
44}
45
Alex Deymo42c30c32014-04-24 18:41:18 -070046bool RealShillProvider::Init() {
Alex Deymo30534502015-07-20 15:06:33 -070047 ManagerProxyInterface* manager_proxy = shill_proxy_->GetManagerProxy();
48 if (!manager_proxy)
Gilad Arnold5ef9c482014-03-03 13:51:02 -080049 return false;
Gilad Arnold55f39b72014-01-28 12:51:45 -080050
Gilad Arnoldbeb39e92014-03-11 11:34:50 -070051 // Subscribe to the manager's PropertyChanged signal.
Alex Deymo30534502015-07-20 15:06:33 -070052 manager_proxy->RegisterPropertyChangedSignalHandler(
53 base::Bind(&RealShillProvider::OnManagerPropertyChanged,
54 base::Unretained(this)),
55 base::Bind(&RealShillProvider::OnSignalConnected,
56 base::Unretained(this)));
Gilad Arnold5ef9c482014-03-03 13:51:02 -080057
Gilad Arnoldef120fa2014-04-09 12:52:10 -070058 // Attempt to read initial connection status. Even if this fails because shill
59 // is not responding (e.g. it is down) we'll be notified via "PropertyChanged"
60 // signal as soon as it comes up, so this is not a critical step.
Alex Deymo30534502015-07-20 15:06:33 -070061 chromeos::VariantDictionary properties;
62 chromeos::ErrorPtr error;
63 if (!manager_proxy->GetProperties(&properties, &error))
64 return true;
65
66 const auto& prop_default_service =
67 properties.find(shill::kDefaultServiceProperty);
68 if (prop_default_service != properties.end()) {
69 OnManagerPropertyChanged(prop_default_service->first,
70 prop_default_service->second);
Gilad Arnold5ef9c482014-03-03 13:51:02 -080071 }
72
Gilad Arnoldef120fa2014-04-09 12:52:10 -070073 return true;
Gilad Arnold5ef9c482014-03-03 13:51:02 -080074}
75
Alex Deymo30534502015-07-20 15:06:33 -070076void RealShillProvider::OnManagerPropertyChanged(const string& name,
77 const chromeos::Any& value) {
78 if (name == shill::kDefaultServiceProperty)
79 ProcessDefaultService(value.TryGet<dbus::ObjectPath>().value());
Gilad Arnold5ef9c482014-03-03 13:51:02 -080080}
81
Alex Deymo30534502015-07-20 15:06:33 -070082void RealShillProvider::OnSignalConnected(const string& interface_name,
83 const string& signal_name,
84 bool successful) {
85 if (!successful) {
86 LOG(ERROR) << "Couldn't connect to the signal " << interface_name << "."
87 << signal_name;
Gilad Arnold5ef9c482014-03-03 13:51:02 -080088 }
Gilad Arnold5ef9c482014-03-03 13:51:02 -080089}
90
Alex Deymo30534502015-07-20 15:06:33 -070091bool RealShillProvider::ProcessDefaultService(
92 const string& default_service_path) {
93 // We assume that if the service path didn't change, then the connection
94 // type and the tethering status of it also didn't change.
95 if (default_service_path_ == default_service_path)
Gilad Arnoldef120fa2014-04-09 12:52:10 -070096 return true;
97
Gilad Arnoldd3df25f2014-04-22 08:39:48 -070098 // Update the connection status.
Alex Deymo30534502015-07-20 15:06:33 -070099 default_service_path_ = default_service_path;
Gilad Arnoldd3df25f2014-04-22 08:39:48 -0700100 bool is_connected = (default_service_path_ != "/");
101 var_is_connected_.SetValue(is_connected);
102 var_conn_last_changed_.SetValue(clock_->GetWallclockTime());
Gilad Arnoldef120fa2014-04-09 12:52:10 -0700103
Alex Deymo30534502015-07-20 15:06:33 -0700104 if (!is_connected) {
Gilad Arnoldd3df25f2014-04-22 08:39:48 -0700105 var_conn_type_.UnsetValue();
106 var_conn_tethering_.UnsetValue();
Alex Deymo30534502015-07-20 15:06:33 -0700107 return true;
108 }
109
110 // We create and dispose the ServiceProxyInterface on every request.
111 std::unique_ptr<ServiceProxyInterface> service =
112 shill_proxy_->GetServiceForPath(default_service_path_);
113
114 // Get the connection properties synchronously.
115 chromeos::VariantDictionary properties;
116 chromeos::ErrorPtr error;
117 if (!service->GetProperties(&properties, &error)) {
118 var_conn_type_.UnsetValue();
119 var_conn_tethering_.UnsetValue();
120 return false;
121 }
122
123 // Get the connection tethering mode.
124 const auto& prop_tethering = properties.find(shill::kTetheringProperty);
125 if (prop_tethering == properties.end()) {
126 // Remove the value if not present on the service. This most likely means an
127 // error in shill and the policy will handle it, but we will print a log
128 // message as well for accessing an unused variable.
129 var_conn_tethering_.UnsetValue();
130 LOG(ERROR) << "Could not find connection type (" << default_service_path_
131 << ")";
132 } else {
133 // If the property doesn't contain a string value, the empty string will
134 // become kUnknown.
135 var_conn_tethering_.SetValue(
136 ParseConnectionTethering(prop_tethering->second.TryGet<string>()));
137 }
138
139 // Get the connection type.
140 const auto& prop_type = properties.find(shill::kTypeProperty);
141 if (prop_type == properties.end()) {
142 var_conn_type_.UnsetValue();
143 LOG(ERROR) << "Could not find connection tethering mode ("
144 << default_service_path_ << ")";
145 } else {
146 string type_str = prop_type->second.TryGet<string>();
147 if (type_str == shill::kTypeVPN) {
148 const auto& prop_physical =
149 properties.find(shill::kPhysicalTechnologyProperty);
150 if (prop_physical == properties.end()) {
151 LOG(ERROR) << "No PhysicalTechnology property found for a VPN"
152 << " connection (service: " << default_service_path
153 << "). Using default kUnknown value.";
154 var_conn_type_.SetValue(ConnectionType::kUnknown);
155 } else {
156 var_conn_type_.SetValue(
157 ParseConnectionType(prop_physical->second.TryGet<string>()));
158 }
159 } else {
160 var_conn_type_.SetValue(ParseConnectionType(type_str));
161 }
Gilad Arnoldef120fa2014-04-09 12:52:10 -0700162 }
Gilad Arnolddf3dd242014-04-09 07:15:51 -0700163
Gilad Arnoldbeb39e92014-03-11 11:34:50 -0700164 return true;
165}
166
Alex Deymo63784a52014-05-28 10:46:14 -0700167} // namespace chromeos_update_manager