| // |
| // Copyright (C) 2014 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| |
| #include "update_engine/update_manager/real_shill_provider.h" |
| |
| #include <string> |
| |
| #include <base/logging.h> |
| #include <base/strings/stringprintf.h> |
| #include <brillo/type_name_undecorate.h> |
| #include <shill/dbus-constants.h> |
| #include <shill/dbus-proxies.h> |
| |
| using chromeos_update_engine::connection_utils::ParseConnectionType; |
| using org::chromium::flimflam::ManagerProxyInterface; |
| using org::chromium::flimflam::ServiceProxyInterface; |
| using std::string; |
| |
| namespace chromeos_update_manager { |
| |
| bool RealShillProvider::Init() { |
| ManagerProxyInterface* manager_proxy = shill_proxy_->GetManagerProxy(); |
| if (!manager_proxy) |
| return false; |
| |
| // Subscribe to the manager's PropertyChanged signal. |
| manager_proxy->RegisterPropertyChangedSignalHandler( |
| base::Bind(&RealShillProvider::OnManagerPropertyChanged, |
| base::Unretained(this)), |
| base::Bind(&RealShillProvider::OnSignalConnected, |
| base::Unretained(this))); |
| |
| // Attempt to read initial connection status. Even if this fails because shill |
| // is not responding (e.g. it is down) we'll be notified via "PropertyChanged" |
| // signal as soon as it comes up, so this is not a critical step. |
| brillo::VariantDictionary properties; |
| brillo::ErrorPtr error; |
| if (!manager_proxy->GetProperties(&properties, &error)) |
| return true; |
| |
| const auto& prop_default_service = |
| properties.find(shill::kDefaultServiceProperty); |
| if (prop_default_service != properties.end()) { |
| OnManagerPropertyChanged(prop_default_service->first, |
| prop_default_service->second); |
| } |
| |
| return true; |
| } |
| |
| void RealShillProvider::OnManagerPropertyChanged(const string& name, |
| const brillo::Any& value) { |
| if (name == shill::kDefaultServiceProperty) { |
| dbus::ObjectPath service_path = value.TryGet<dbus::ObjectPath>(); |
| if (!service_path.IsValid()) { |
| LOG(WARNING) << "Got an invalid DefaultService path. The property value " |
| "contains a " |
| << value.GetUndecoratedTypeName() |
| << ", read as the object path: '" << service_path.value() |
| << "'"; |
| } |
| ProcessDefaultService(service_path); |
| } |
| } |
| |
| void RealShillProvider::OnSignalConnected(const string& interface_name, |
| const string& signal_name, |
| bool successful) { |
| if (!successful) { |
| LOG(ERROR) << "Couldn't connect to the signal " << interface_name << "." |
| << signal_name; |
| } |
| } |
| |
| bool RealShillProvider::ProcessDefaultService( |
| const dbus::ObjectPath& default_service_path) { |
| // We assume that if the service path didn't change, then the connection |
| // type and the tethering status of it also didn't change. |
| if (default_service_path_ == default_service_path) |
| return true; |
| |
| // Update the connection status. |
| default_service_path_ = default_service_path; |
| bool is_connected = |
| (default_service_path_.IsValid() && default_service_path_.value() != "/"); |
| var_is_connected_.SetValue(is_connected); |
| var_conn_last_changed_.SetValue(clock_->GetWallclockTime()); |
| |
| if (!is_connected) { |
| var_conn_type_.UnsetValue(); |
| var_conn_tethering_.UnsetValue(); |
| return true; |
| } |
| |
| // We create and dispose the ServiceProxyInterface on every request. |
| std::unique_ptr<ServiceProxyInterface> service = |
| shill_proxy_->GetServiceForPath(default_service_path_); |
| |
| // Get the connection properties synchronously. |
| brillo::VariantDictionary properties; |
| brillo::ErrorPtr error; |
| if (!service->GetProperties(&properties, &error)) { |
| var_conn_type_.UnsetValue(); |
| var_conn_tethering_.UnsetValue(); |
| return false; |
| } |
| |
| // Get the connection tethering mode. |
| const auto& prop_tethering = properties.find(shill::kTetheringProperty); |
| if (prop_tethering == properties.end()) { |
| // Remove the value if not present on the service. This most likely means an |
| // error in shill and the policy will handle it, but we will print a log |
| // message as well for accessing an unused variable. |
| var_conn_tethering_.UnsetValue(); |
| LOG(ERROR) << "Could not find connection type (service: " |
| << default_service_path_.value() << ")"; |
| } else { |
| // If the property doesn't contain a string value, the empty string will |
| // become kUnknown. |
| var_conn_tethering_.SetValue( |
| chromeos_update_engine::connection_utils::ParseConnectionTethering( |
| prop_tethering->second.TryGet<string>())); |
| } |
| |
| // Get the connection type. |
| const auto& prop_type = properties.find(shill::kTypeProperty); |
| if (prop_type == properties.end()) { |
| var_conn_type_.UnsetValue(); |
| LOG(ERROR) << "Could not find connection tethering mode (service: " |
| << default_service_path_.value() << ")"; |
| } else { |
| string type_str = prop_type->second.TryGet<string>(); |
| if (type_str == shill::kTypeVPN) { |
| const auto& prop_physical = |
| properties.find(shill::kPhysicalTechnologyProperty); |
| if (prop_physical == properties.end()) { |
| LOG(ERROR) << "No PhysicalTechnology property found for a VPN" |
| << " connection (service: " << default_service_path_.value() |
| << "). Using default kUnknown value."; |
| var_conn_type_.SetValue( |
| chromeos_update_engine::ConnectionType::kUnknown); |
| } else { |
| var_conn_type_.SetValue( |
| ParseConnectionType(prop_physical->second.TryGet<string>())); |
| } |
| } else { |
| var_conn_type_.SetValue(ParseConnectionType(type_str)); |
| } |
| } |
| |
| return true; |
| } |
| |
| } // namespace chromeos_update_manager |