Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(270)

Side by Side Diff: src/device.cc

Issue 6395007: cashew: gmock integration (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/cashew.git@master
Patch Set: Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/device.h ('k') | src/device_impl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 1 // Copyright (c) 2010, 2011 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/device.h" 5 #include "src/device.h"
6 6
7 #include <glog/logging.h> 7 #include <glog/logging.h>
8 8
9 #include "src/byte_counter.h" 9 #include "src/device_impl.h"
10 #include "src/service.h"
11 10
12 namespace cashew { 11 namespace cashew {
13 12
14 // Flimflam Device D-Bus identifiers
15 static const char *kFlimflamDeviceName = "org.chromium.flimflam";
16
17 // Flimflam Device property names
18 static const char *kFlimflamDeviceCarrierProperty = "Cellular.Carrier";
19 static const char *kFlimflamDeviceInterfaceProperty = "Interface";
20 static const char *kFlimflamDeviceTypeProperty = "Type";
21
22 // Flimflam Device on-the-wire Type values
23 static const char *kFlimflamDeviceTypeEthernet = "ethernet";
24 static const char *kFlimflamDeviceTypeWifi = "wifi";
25 static const char *kFlimflamDeviceTypeWimax = "wimax";
26 static const char *kFlimflamDeviceTypeBluetooth = "bluetooth";
27 static const char *kFlimflamDeviceTypeGPS = "gps";
28 static const char *kFlimflamDeviceTypeCellular = "cellular";
29 // TODO(vlaviano): what does vendor look like?
30 static const char *kFlimflamDeviceTypeVendor = "";
31
32 // GetDeviceProperties retry interval
33 static const guint kSecondsPerMinute = 60;
34 static const guint kGetDevicePropertiesIntervalSeconds = 1 * kSecondsPerMinute;
35
36 Device::Device(Service * const parent, DBus::Connection& connection, // NOLINT
37 const DBus::Path& path)
38 : DBus::ObjectProxy(connection, path, kFlimflamDeviceName),
39 parent_(CHECK_NOTNULL(parent)), path_(path), type_(kTypeUnknown),
40 get_properties_source_id_(0), retrying_get_properties_(false),
41 byte_counter_(NULL), byte_counter_running_(false) {
42 // schedule a GetProperties() call to our Flimflam service path to init state
43 // we'll keep trying periodically until we succeed
44 // we'll subsequently update this state by monitoring PropertyChanged signals
45 get_properties_source_id_ =
46 g_idle_add(StaticGetDevicePropertiesCallback, this);
47 if (get_properties_source_id_ == 0) {
48 LOG(ERROR) << path_ << ": ctor: g_idle_add failed";
49 }
50 property_changed_handler_.delegate(this);
51 }
52
53 Device::~Device() {
54 StopByteCounter();
55 if (get_properties_source_id_ != 0 &&
56 !g_source_remove(get_properties_source_id_)) {
57 DLOG(WARNING) << path_ << ": dtor: g_source_remove failed";
58 }
59 }
60
61 const DBus::Path& Device::GetPath() const {
62 return path_;
63 }
64
65 Device::Type Device::GetType() const {
66 return type_;
67 }
68
69 const std::string& Device::GetCarrier() const {
70 return carrier_;
71 }
72
73 const std::string& Device::GetInterface() const {
74 return interface_;
75 }
76
77 // Flimflam Device D-Bus Proxy methods
78
79 void Device::PropertyChanged(const std::string& property_name,
80 const DBus::Variant& new_value) {
81 DLOG(INFO) << path_ << ": PropertyChanged: property_name = " << property_name;
82 // Queue a tuple representing this signal for later processing from the glib
83 // main loop. We do this to avoid libdbus-c++ deadlocks that can occur when
84 // sending a dbus message from within a dbus callback like this one.
85 PropertyChangedSignal signal(property_name, new_value);
86 property_changed_handler_.EnqueueSignal(signal);
87 }
88
89 // PropertyChangedDelegate methods
90
91 void Device::OnPropertyChanged(const PropertyChangedHandler *handler,
92 const std::string& property_name,
93 const DBus::Variant& new_value) {
94 DCHECK(handler == &property_changed_handler_);
95 DLOG(INFO) << path_ << ": OnPropertyChanged: property_name = "
96 << property_name;
97 if (property_name == kFlimflamDeviceCarrierProperty) {
98 OnCarrierUpdate(new_value.reader().get_string());
99 } else if (property_name == kFlimflamDeviceInterfaceProperty) {
100 OnInterfaceUpdate(new_value.reader().get_string());
101 } else if (property_name == kFlimflamDeviceTypeProperty) {
102 OnTypeUpdate(new_value.reader().get_string());
103 } else {
104 // we don't care about this property
105 }
106 }
107
108 // Service methods
109
110 bool Device::StartByteCounter() {
111 if (byte_counter_running_) {
112 DLOG(WARNING) << path_ << ": StartByteCounter: counter already running";
113 return false;
114 }
115 byte_counter_running_ = true;
116 if (interface_.empty()) {
117 // if we don't yet know our interface name, we report success but hold off
118 // creating a byte counter object; we'll do so later in OnInterfaceUpdate
119 DLOG(INFO) << path_
120 << ": StartByteCounter: no interface name, delaying counter creation";
121 return true;
122 }
123 if (!CreateByteCounter()) {
124 DLOG(WARNING) << path_
125 << ": StartByteCounter: couldn't create byte counter for " << interface_;
126 byte_counter_running_ = false;
127 return false;
128 }
129 DLOG(INFO) << path_ << ": StartByteCounter: created byte counter for "
130 << interface_;
131 return true;
132 }
133
134 void Device::StopByteCounter() {
135 if (byte_counter_running_) {
136 DeleteByteCounter();
137 byte_counter_running_ = false;
138 }
139 DCHECK(byte_counter_ == NULL);
140 }
141
142 bool Device::ByteCounterRunning() const {
143 return byte_counter_running_;
144 }
145
146 // glib integration interface
147
148 guint Device::GetGetPropertiesSourceId() const {
149 return get_properties_source_id_;
150 }
151
152 void Device::SetGetPropertiesSourceId(guint source_id) {
153 get_properties_source_id_ = source_id;
154 }
155
156 bool Device::RetryingGetProperties() const {
157 return retrying_get_properties_;
158 }
159
160 void Device::OnRetryingGetProperties(bool retrying) {
161 retrying_get_properties_ = retrying;
162 }
163
164 // ByteCounterDelegate methods
165
166 void Device::OnByteCounterUpdate(const ByteCounter *counter, uint64 rx_bytes,
167 uint64 tx_bytes) {
168 DCHECK(byte_counter_running_);
169 DCHECK(byte_counter_ != NULL);
170 DCHECK(counter == byte_counter_);
171 DLOG(INFO) << path_ << ": OnByteCounterUpdate: rx_bytes = " << rx_bytes
172 << ", tx_bytes = " << tx_bytes;
173 parent_->OnByteCounterUpdate(rx_bytes, tx_bytes);
174 }
175
176 // Private methods
177
178 Device::Type Device::TypeFromString(const std::string& type) const {
179 if (type == kFlimflamDeviceTypeEthernet) {
180 return kTypeEthernet;
181 }
182 if (type == kFlimflamDeviceTypeWifi) {
183 return kTypeWifi;
184 }
185 if (type == kFlimflamDeviceTypeWimax) {
186 return kTypeWimax;
187 }
188 if (type == kFlimflamDeviceTypeBluetooth) {
189 return kTypeBluetooth;
190 }
191 if (type == kFlimflamDeviceTypeGPS) {
192 return kTypeGPS;
193 }
194 if (type == kFlimflamDeviceTypeCellular) {
195 return kTypeCellular;
196 }
197 if (type == kFlimflamDeviceTypeVendor) {
198 return kTypeVendor;
199 }
200 return kTypeUnknown;
201 }
202
203 void Device::OnCarrierUpdate(const std::string& carrier) {
204 DLOG(INFO) << path_ << ": OnCarrierUpdate: carrier = " << carrier;
205 // only propagate this to parent Service if there's been a change
206 // we expect to see only one such change (from "Unknown")
207 if (carrier_ == carrier) {
208 return;
209 }
210 if (!carrier_.empty()) {
211 LOG(WARNING) << path_ << ": OnCarrierUpdate: carrier change from "
212 << carrier_ << " to " << carrier << "!";
213 }
214 carrier_ = carrier;
215 parent_->OnCarrierUpdate(carrier);
216 }
217
218 void Device::OnInterfaceUpdate(const std::string& interface) {
219 DLOG(INFO) << path_ << ": OnInterfaceUpdate: interface = " << interface;
220 if (interface_ == interface) {
221 return;
222 }
223 if (!interface_.empty()) {
224 LOG(WARNING) << path_ << ": OnInterfaceUpdate: interface change from "
225 << interface_ << " to " << interface << "!";
226 }
227 const std::string old_interface = interface_;
228 interface_ = interface;
229 if (!byte_counter_running_) {
230 return;
231 }
232 // get rid of byte counter for old interface
233 StopByteCounter();
234 // if we don't have new interface info, we can't make a new byte counter yet
235 if (interface_.empty()) {
236 return;
237 }
238 // create byte counter for new interface
239 // TODO(vlaviano): creating new counter on interface change may confuse our
240 // parent service.
241 if (!StartByteCounter()) {
242 LOG(ERROR) << path_
243 << ": OnInterfaceUpdate: could not create byte counter for "
244 << interface_;
245 return;
246 }
247 }
248
249 void Device::OnTypeUpdate(const std::string& type) {
250 DLOG(INFO) << path_ << ": OnTypeUpdate: type = " << type;
251 type_ = TypeFromString(type);
252 if (type_ != kTypeCellular) {
253 LOG(WARNING) << path_ << ": OnTypeUpdate: type is not cellular!";
254 }
255 }
256
257 // static 13 // static
258 gboolean Device::StaticGetDevicePropertiesCallback(gpointer data) { 14 Device* Device::NewDevice(Service * const parent,
259 Device *device = reinterpret_cast<Device*>(data); 15 DBus::Connection& connection, // NOLINT
260 CHECK_NOTNULL(device); 16 const DBus::Path& path) {
261 DCHECK_NE(device->GetGetPropertiesSourceId(), 0); 17 DCHECK(parent != NULL);
262 if (!device->GetDeviceProperties()) { 18 return new(std::nothrow) DeviceImpl(parent, connection, path);
263 // call failed, so try again later
264 DLOG(WARNING) << device->GetPath()
265 << ": StaticGetDevicePropertiesCallback: "
266 << "GetDeviceProperties failed, will retry in "
267 << kGetDevicePropertiesIntervalSeconds << " secs";
268 // if we've arrived here from our first g_idle_add call, set up a timer
269 if (!device->RetryingGetProperties()) {
270 guint source_id =
271 g_timeout_add_seconds(kGetDevicePropertiesIntervalSeconds,
272 StaticGetDevicePropertiesCallback, device);
273 device->SetGetPropertiesSourceId(source_id);
274 if (source_id == 0) {
275 LOG(ERROR) << device->GetPath()
276 << ": StaticGetDevicePropertiesCallback: "
277 << "g_timeout_add_seconds failed";
278 return FALSE; // get rid of old glib source and give up
279 }
280 device->OnRetryingGetProperties(true);
281 // get rid of our old glib source, but our new timer will call us
282 return FALSE;
283 }
284 // otherwise, our timer is already set up
285 // return TRUE to indicate that we want to be called again later
286 return TRUE;
287 }
288 device->SetGetPropertiesSourceId(0);
289 device->OnRetryingGetProperties(false);
290 return FALSE; // we succeeded, so don't repeat
291 }
292
293 bool Device::GetDeviceProperties() {
294 DLOG(INFO) << path_ << ": GetDeviceProperties";
295 PropertyMap properties;
296 // dbus-c++ throws exceptions
297 // invoke the "Existing Non-conformant Code" clause of the style guide and
298 // isolate the rest of the system from this
299 try {
300 // TODO(vlaviano): make this call asynchronous
301 properties = GetProperties();
302 } catch (DBus::Error& error) { // NOLINT
303 LOG(WARNING) << path_
304 << ": GetDeviceProperties: GetProperties() -> Exception: "
305 << error.name() << ": " << error.message();
306 return false;
307 } catch (...) { // NOLINT
308 LOG(WARNING) << path_
309 << ": GetDeviceProperties: GetProperties() -> Exception";
310 return false;
311 }
312 DLOG(INFO) << "Received " << properties.size() << " properties";
313
314 // grab the properties in which we're interested
315 PropertyMap::const_iterator it;
316 it = properties.find(kFlimflamDeviceInterfaceProperty);
317 if (it != properties.end()) {
318 const DBus::Variant& value = static_cast<DBus::Variant>(it->second);
319 OnInterfaceUpdate(value.reader().get_string());
320 } else {
321 DLOG(WARNING) << path_ << ": GetDeviceProperties: no Interface property";
322 }
323 it = properties.find(kFlimflamDeviceTypeProperty);
324 if (it != properties.end()) {
325 const DBus::Variant& value = static_cast<DBus::Variant>(it->second);
326 OnTypeUpdate(value.reader().get_string());
327 } else {
328 DLOG(WARNING) << path_ << ": GetDeviceProperties: no Type property";
329 }
330 // don't expect to find Cellular.* properties if we're not a cellular device
331 if (type_ != kTypeCellular) {
332 return true;
333 }
334 it = properties.find(kFlimflamDeviceCarrierProperty);
335 if (it != properties.end()) {
336 const DBus::Variant& value = static_cast<DBus::Variant>(it->second);
337 OnCarrierUpdate(value.reader().get_string());
338 } else {
339 DLOG(WARNING) << path_
340 << ": GetDeviceProperties: no Cellular.Carrier property";
341 }
342 return true;
343 }
344
345 bool Device::CreateByteCounter() {
346 if (byte_counter_ != NULL) {
347 DLOG(WARNING) << path_ << ": CreateByteCounter: counter already exists";
348 return false;
349 }
350 if (interface_.empty()) {
351 DLOG(WARNING) << path_ << ": CreateByteCounter: interface name unknown";
352 return false;
353 }
354 byte_counter_ = ByteCounter::NewByteCounter(interface_);
355 if (byte_counter_ == NULL) {
356 LOG(ERROR) << path_
357 << ": CreateByteCounter: could not create byte counter for "
358 << interface_;
359 return false;
360 }
361 byte_counter_->SetDelegate(this);
362 return true;
363 }
364
365 void Device::DeleteByteCounter() {
366 DLOG(INFO) << path_ << ": DeleteByteCounter";
367 if (byte_counter_ != NULL) {
368 delete byte_counter_;
369 byte_counter_ = NULL;
370 }
371 } 19 }
372 20
373 } // namespace cashew 21 } // namespace cashew
OLDNEW
« no previous file with comments | « src/device.h ('k') | src/device_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698