| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2010 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 |
| 5 #include "src/service_manager.h" |
| 6 |
| 7 #include <glog/logging.h> |
| 8 |
| 9 #include "src/service.h" |
| 10 |
| 11 namespace cashew { |
| 12 |
| 13 // Flimflam D-Bus indentifiers |
| 14 static const char* kFlimflamManagerName = "org.chromium.flimflam"; |
| 15 static const char* kFlimflamManagerPath = "/"; |
| 16 |
| 17 // Flimflam property names |
| 18 static const char* kServicesProperty = "Services"; |
| 19 |
| 20 // Flimflam service types |
| 21 static const char* kTypeCellular = "cellular"; |
| 22 |
| 23 ServiceManager::ServiceManager(DBus::Connection& connection) // NOLINT |
| 24 : DBus::ObjectProxy(connection, kFlimflamManagerPath, |
| 25 kFlimflamManagerName), |
| 26 connection_(connection) { |
| 27 // init our state with a GetProperties() call to Flimflam |
| 28 // we'll update this state by monitoring PropertyChanged signals |
| 29 GetFlimflamServices(); |
| 30 } |
| 31 |
| 32 ServiceManager::~ServiceManager() { |
| 33 DeleteServices(&services_); |
| 34 } |
| 35 |
| 36 const Service* ServiceManager::GetService(const std::string& service_path) |
| 37 const { |
| 38 ServiceMap::const_iterator it = services_.find(service_path); |
| 39 if (it == services_.end()) { |
| 40 return NULL; |
| 41 } |
| 42 DCHECK(it->second != NULL); |
| 43 return static_cast<const Service *>(it->second); |
| 44 } |
| 45 |
| 46 // Flimflam Manager D-Bus Proxy methods |
| 47 |
| 48 void ServiceManager::PropertyChanged(const std::string& property_name, |
| 49 const DBus::Variant& new_value) { |
| 50 DLOG(INFO) << "PropertyChanged: property_name = " << property_name; |
| 51 |
| 52 // we only care about Services changes |
| 53 if (property_name.compare(kServicesProperty)) { |
| 54 return; |
| 55 } |
| 56 |
| 57 // interpret new_value as a vector of service paths |
| 58 ServicePathList paths; |
| 59 DBus::MessageIter reader = new_value.reader(); |
| 60 reader >> paths; |
| 61 |
| 62 OnServicesUpdate(paths); |
| 63 } |
| 64 |
| 65 void ServiceManager::StateChanged(const std::string& new_state) { |
| 66 DLOG(INFO) << "StateChanged: new_state = " << new_state; |
| 67 // TODO(vlaviano): switch on state and call private onFlimflamOffline(), |
| 68 // onFlimflamOnline() hooks. If we care. |
| 69 } |
| 70 |
| 71 // Private methods |
| 72 |
| 73 void ServiceManager::DeleteServices(ServiceMap *service_map) { |
| 74 DCHECK(service_map != NULL); |
| 75 while (!service_map->empty()) { |
| 76 const std::string& path = |
| 77 static_cast<std::string>(service_map->begin()->first); |
| 78 DLOG(INFO) << "DeleteServices: deleting service: " << path; |
| 79 Service *service = static_cast<Service *>(service_map->begin()->second); |
| 80 delete service; |
| 81 service_map->erase(service_map->begin()); |
| 82 } |
| 83 } |
| 84 |
| 85 void ServiceManager::GetFlimflamServices() { |
| 86 DLOG(INFO) << "GetFlimflamServices"; |
| 87 PropertyMap properties; |
| 88 // dbus-c++ throws exceptions |
| 89 // invoke the "Existing Non-conformant Code" clause of the style guide and |
| 90 // isolate the rest of the system from this |
| 91 try { |
| 92 // TODO(vlaviano): make this call asynchronous |
| 93 properties = GetProperties(); |
| 94 } catch (DBus::Error& error) { // NOLINT |
| 95 LOG(WARNING) << "GetFlimflamServices: GetProperties() -> Exception: " |
| 96 << error.name() << ": " << error.message(); |
| 97 // TODO(vlaviano): schedule another attempt later |
| 98 return; |
| 99 } catch (...) { // NOLINT |
| 100 LOG(WARNING) << "GetFlimflamServices: GetProperties() -> Exception"; |
| 101 // TODO(vlaviano): schedule another attempt later |
| 102 return; |
| 103 } |
| 104 |
| 105 // grab Services property from result |
| 106 PropertyMap::const_iterator it = properties.find(kServicesProperty); |
| 107 if (it == properties.end()) { |
| 108 DLOG(WARNING) << "GetFlimflamServices: no Services property"; |
| 109 return; |
| 110 } |
| 111 DBus::Variant value = static_cast<DBus::Variant>(it->second); |
| 112 |
| 113 // interpret value as vector of service paths |
| 114 ServicePathList paths; |
| 115 DBus::MessageIter reader = value.reader(); |
| 116 reader >> paths; |
| 117 |
| 118 OnServicesUpdate(paths); |
| 119 } |
| 120 |
| 121 void ServiceManager::OnServicesUpdate(const ServicePathList& paths) { |
| 122 // Remember old set of services. This is the baseline from which we will |
| 123 // determine what has changed. |
| 124 ServiceMap old_services = services_; |
| 125 services_.clear(); |
| 126 |
| 127 // Flimflam service types are embedded in their path names, so we can use |
| 128 // the pattern "/cellular_" to decide which paths are cellular services. |
| 129 static const std::string cellular_pattern = std::string("/") + kTypeCellular |
| 130 + "_"; |
| 131 |
| 132 // Walk paths in this update and see if they're new to us |
| 133 DLOG(INFO) << "OnServicesUpdate: " << paths.size() << " service paths"; |
| 134 ServicePathList::const_iterator it; |
| 135 for (it = paths.begin(); it != paths.end(); ++it) { |
| 136 const DBus::Path& path = *it; |
| 137 |
| 138 // We only care about cellular services |
| 139 if (path.find(cellular_pattern) == std::string::npos) { |
| 140 continue; |
| 141 } |
| 142 |
| 143 ServiceMap::iterator old_it = old_services.find(path); |
| 144 if (old_it != old_services.end()) { |
| 145 // service is old: move it from old_services to services_ |
| 146 Service *service = static_cast<Service *>(old_it->second); |
| 147 DCHECK(service != NULL); |
| 148 old_services.erase(old_it); |
| 149 services_[path] = service; |
| 150 } else { |
| 151 // service is new: create a Service obj for it and add it to services_ |
| 152 OnNewService(path); |
| 153 } |
| 154 } |
| 155 |
| 156 // services left in old_services failed to appear in the update: delete them |
| 157 DeleteServices(&old_services); |
| 158 } |
| 159 |
| 160 void ServiceManager::OnNewService(const DBus::Path& path) { |
| 161 DLOG(INFO) << "OnNewService: " << path; |
| 162 DCHECK(GetService(path) == NULL); |
| 163 Service *service = new(std::nothrow) Service(connection_, path); |
| 164 if (service == NULL) { |
| 165 LOG(ERROR) << "OnNewService: couldn't create service for " << path; |
| 166 return; |
| 167 } |
| 168 services_[path] = service; |
| 169 } |
| 170 |
| 171 } // namespace cashew |
| OLD | NEW |