| Index: src/service_manager.cc
|
| diff --git a/src/service_manager.cc b/src/service_manager.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..39f3c6d1d283d77c59bf4dea6823ea26cbe42e7d
|
| --- /dev/null
|
| +++ b/src/service_manager.cc
|
| @@ -0,0 +1,171 @@
|
| +// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "src/service_manager.h"
|
| +
|
| +#include <glog/logging.h>
|
| +
|
| +#include "src/service.h"
|
| +
|
| +namespace cashew {
|
| +
|
| +// Flimflam D-Bus indentifiers
|
| +static const char* kFlimflamManagerName = "org.chromium.flimflam";
|
| +static const char* kFlimflamManagerPath = "/";
|
| +
|
| +// Flimflam property names
|
| +static const char* kServicesProperty = "Services";
|
| +
|
| +// Flimflam service types
|
| +static const char* kTypeCellular = "cellular";
|
| +
|
| +ServiceManager::ServiceManager(DBus::Connection& connection) // NOLINT
|
| + : DBus::ObjectProxy(connection, kFlimflamManagerPath,
|
| + kFlimflamManagerName),
|
| + connection_(connection) {
|
| + // init our state with a GetProperties() call to Flimflam
|
| + // we'll update this state by monitoring PropertyChanged signals
|
| + GetFlimflamServices();
|
| +}
|
| +
|
| +ServiceManager::~ServiceManager() {
|
| + DeleteServices(&services_);
|
| +}
|
| +
|
| +const Service* ServiceManager::GetService(const std::string& service_path)
|
| + const {
|
| + ServiceMap::const_iterator it = services_.find(service_path);
|
| + if (it == services_.end()) {
|
| + return NULL;
|
| + }
|
| + DCHECK(it->second != NULL);
|
| + return static_cast<const Service *>(it->second);
|
| +}
|
| +
|
| +// Flimflam Manager D-Bus Proxy methods
|
| +
|
| +void ServiceManager::PropertyChanged(const std::string& property_name,
|
| + const DBus::Variant& new_value) {
|
| + DLOG(INFO) << "PropertyChanged: property_name = " << property_name;
|
| +
|
| + // we only care about Services changes
|
| + if (property_name.compare(kServicesProperty)) {
|
| + return;
|
| + }
|
| +
|
| + // interpret new_value as a vector of service paths
|
| + ServicePathList paths;
|
| + DBus::MessageIter reader = new_value.reader();
|
| + reader >> paths;
|
| +
|
| + OnServicesUpdate(paths);
|
| +}
|
| +
|
| +void ServiceManager::StateChanged(const std::string& new_state) {
|
| + DLOG(INFO) << "StateChanged: new_state = " << new_state;
|
| + // TODO(vlaviano): switch on state and call private onFlimflamOffline(),
|
| + // onFlimflamOnline() hooks. If we care.
|
| +}
|
| +
|
| +// Private methods
|
| +
|
| +void ServiceManager::DeleteServices(ServiceMap *service_map) {
|
| + DCHECK(service_map != NULL);
|
| + while (!service_map->empty()) {
|
| + const std::string& path =
|
| + static_cast<std::string>(service_map->begin()->first);
|
| + DLOG(INFO) << "DeleteServices: deleting service: " << path;
|
| + Service *service = static_cast<Service *>(service_map->begin()->second);
|
| + delete service;
|
| + service_map->erase(service_map->begin());
|
| + }
|
| +}
|
| +
|
| +void ServiceManager::GetFlimflamServices() {
|
| + DLOG(INFO) << "GetFlimflamServices";
|
| + PropertyMap properties;
|
| + // dbus-c++ throws exceptions
|
| + // invoke the "Existing Non-conformant Code" clause of the style guide and
|
| + // isolate the rest of the system from this
|
| + try {
|
| + // TODO(vlaviano): make this call asynchronous
|
| + properties = GetProperties();
|
| + } catch (DBus::Error& error) { // NOLINT
|
| + LOG(WARNING) << "GetFlimflamServices: GetProperties() -> Exception: "
|
| + << error.name() << ": " << error.message();
|
| + // TODO(vlaviano): schedule another attempt later
|
| + return;
|
| + } catch (...) { // NOLINT
|
| + LOG(WARNING) << "GetFlimflamServices: GetProperties() -> Exception";
|
| + // TODO(vlaviano): schedule another attempt later
|
| + return;
|
| + }
|
| +
|
| + // grab Services property from result
|
| + PropertyMap::const_iterator it = properties.find(kServicesProperty);
|
| + if (it == properties.end()) {
|
| + DLOG(WARNING) << "GetFlimflamServices: no Services property";
|
| + return;
|
| + }
|
| + DBus::Variant value = static_cast<DBus::Variant>(it->second);
|
| +
|
| + // interpret value as vector of service paths
|
| + ServicePathList paths;
|
| + DBus::MessageIter reader = value.reader();
|
| + reader >> paths;
|
| +
|
| + OnServicesUpdate(paths);
|
| +}
|
| +
|
| +void ServiceManager::OnServicesUpdate(const ServicePathList& paths) {
|
| + // Remember old set of services. This is the baseline from which we will
|
| + // determine what has changed.
|
| + ServiceMap old_services = services_;
|
| + services_.clear();
|
| +
|
| + // Flimflam service types are embedded in their path names, so we can use
|
| + // the pattern "/cellular_" to decide which paths are cellular services.
|
| + static const std::string cellular_pattern = std::string("/") + kTypeCellular
|
| + + "_";
|
| +
|
| + // Walk paths in this update and see if they're new to us
|
| + DLOG(INFO) << "OnServicesUpdate: " << paths.size() << " service paths";
|
| + ServicePathList::const_iterator it;
|
| + for (it = paths.begin(); it != paths.end(); ++it) {
|
| + const DBus::Path& path = *it;
|
| +
|
| + // We only care about cellular services
|
| + if (path.find(cellular_pattern) == std::string::npos) {
|
| + continue;
|
| + }
|
| +
|
| + ServiceMap::iterator old_it = old_services.find(path);
|
| + if (old_it != old_services.end()) {
|
| + // service is old: move it from old_services to services_
|
| + Service *service = static_cast<Service *>(old_it->second);
|
| + DCHECK(service != NULL);
|
| + old_services.erase(old_it);
|
| + services_[path] = service;
|
| + } else {
|
| + // service is new: create a Service obj for it and add it to services_
|
| + OnNewService(path);
|
| + }
|
| + }
|
| +
|
| + // services left in old_services failed to appear in the update: delete them
|
| + DeleteServices(&old_services);
|
| +}
|
| +
|
| +void ServiceManager::OnNewService(const DBus::Path& path) {
|
| + DLOG(INFO) << "OnNewService: " << path;
|
| + DCHECK(GetService(path) == NULL);
|
| + Service *service = new(std::nothrow) Service(connection_, path);
|
| + if (service == NULL) {
|
| + LOG(ERROR) << "OnNewService: couldn't create service for " << path;
|
| + return;
|
| + }
|
| + services_[path] = service;
|
| +}
|
| +
|
| +} // namespace cashew
|
|
|