| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 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 | 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/service.h" | 5 #include "src/service.h" |
| 6 | 6 |
| 7 #include <glog/logging.h> | 7 #include <glog/logging.h> |
| 8 | 8 |
| 9 #include "src/data_plan_provider.h" |
| 9 #include "src/device.h" | 10 #include "src/device.h" |
| 11 #include "src/policy.h" |
| 12 #include "src/service_manager.h" |
| 10 | 13 |
| 11 namespace cashew { | 14 namespace cashew { |
| 12 | 15 |
| 13 // Flimflam Service D-Bus identifiers | 16 // Flimflam Service D-Bus identifiers |
| 14 static const char* kFlimflamServiceName = "org.chromium.flimflam"; | 17 static const char *kFlimflamServiceName = "org.chromium.flimflam"; |
| 15 | 18 |
| 16 // Flimflam Service property names | 19 // Flimflam Service property names |
| 17 static const char *kFlimflamServiceDeviceProperty = "Device"; | 20 static const char *kFlimflamServiceDeviceProperty = "Device"; |
| 18 static const char *kFlimflamServiceStateProperty = "State"; | 21 static const char *kFlimflamServiceStateProperty = "State"; |
| 19 static const char* kFlimflamServiceTypeProperty = "Type"; | 22 static const char *kFlimflamServiceTypeProperty = "Type"; |
| 23 static const char *kFlimflamServiceUsageUrlProperty = "Cellular.UsageUrl"; |
| 20 | 24 |
| 21 // Flimflam Service on-the-wire State values | 25 // Flimflam Service on-the-wire State values |
| 22 static const char* kFlimflamServiceStateIdle = "idle"; | 26 static const char *kFlimflamServiceStateIdle = "idle"; |
| 23 static const char* kFlimflamServiceStateCarrier = "carrier"; | 27 static const char *kFlimflamServiceStateCarrier = "carrier"; |
| 24 static const char* kFlimflamServiceStateAssociation = "association"; | 28 static const char *kFlimflamServiceStateAssociation = "association"; |
| 25 static const char* kFlimflamServiceStateConfiguration = "configuration"; | 29 static const char *kFlimflamServiceStateConfiguration = "configuration"; |
| 26 static const char* kFlimflamServiceStateReady = "ready"; | 30 static const char *kFlimflamServiceStateReady = "ready"; |
| 27 static const char* kFlimflamServiceStateDisconnect = "disconnect"; | 31 static const char *kFlimflamServiceStateDisconnect = "disconnect"; |
| 28 static const char* kFlimflamServiceStateFailure = "failure"; | 32 static const char *kFlimflamServiceStateFailure = "failure"; |
| 29 static const char* kFlimflamServiceStateActivationFailure = | 33 static const char *kFlimflamServiceStateActivationFailure = |
| 30 "activation-failure"; | 34 "activation-failure"; |
| 31 | 35 |
| 32 // Flimflam Service on-the-wire Type values | 36 // Flimflam Service on-the-wire Type values |
| 33 static const char* kFlimflamServiceTypeEthernet = "ethernet"; | 37 static const char *kFlimflamServiceTypeEthernet = "ethernet"; |
| 34 static const char* kFlimflamServiceTypeWifi = "wifi"; | 38 static const char *kFlimflamServiceTypeWifi = "wifi"; |
| 35 static const char* kFlimflamServiceTypeWimax = "wimax"; | 39 static const char *kFlimflamServiceTypeWimax = "wimax"; |
| 36 static const char* kFlimflamServiceTypeBluetooth = "bluetooth"; | 40 static const char *kFlimflamServiceTypeBluetooth = "bluetooth"; |
| 37 static const char* kFlimflamServiceTypeCellular = "cellular"; | 41 static const char *kFlimflamServiceTypeCellular = "cellular"; |
| 38 | 42 |
| 39 Service::Service(DBus::Connection& connection, // NOLINT | 43 // Chromium OS Usage API property names |
| 44 static const char *kCrosUsageVersionProperty = "version"; |
| 45 static const char *kCrosUsageStatusProperty = "status"; |
| 46 static const char *kCrosUsageRestrictedProperty = "restricted"; |
| 47 static const char *kCrosUsagePlansProperty = "plans"; |
| 48 |
| 49 // Chromium OS Usage API version values |
| 50 static const int kCrosUsageVersionMinSupported = 1; |
| 51 static const int kCrosUsageVersionMaxSupported = 1; |
| 52 |
| 53 // Chromium OS Usage API status values |
| 54 static const char *kCrosUsageStatusOk = "OK"; |
| 55 static const char *kCrosUsageStatusError = "ERROR"; |
| 56 |
| 57 Service::Service(ServiceManager * const parent, |
| 58 DBus::Connection& connection, // NOLINT |
| 40 const DBus::Path& path) | 59 const DBus::Path& path) |
| 41 : DBus::ObjectProxy(connection, path, kFlimflamServiceName), | 60 : DBus::ObjectProxy(connection, path, kFlimflamServiceName), |
| 42 connection_(connection), path_(path), state_(kStateUnknown), | 61 parent_(CHECK_NOTNULL(parent)), connection_(connection), path_(path), |
| 43 type_(kTypeUnknown), device_(NULL) { | 62 state_(kStateUnknown), type_(kTypeUnknown), device_(NULL), |
| 63 provider_(NULL), request_in_progress_(false), |
| 64 update_timeout_source_(NULL), policy_(NULL) { |
| 44 // init our state with a GetProperties() call to our Flimflam service path | 65 // init our state with a GetProperties() call to our Flimflam service path |
| 45 // we'll update this state by monitoring PropertyChanged signals | 66 // we'll update this state by monitoring PropertyChanged signals |
| 46 GetServiceProperties(); | 67 GetServiceProperties(); |
| 47 | |
| 48 // init our data plans list with a hardcoded plan | |
| 49 // TODO(vlaviano): implement backend and return real data | |
| 50 AddHardcodedDataPlan(); | |
| 51 } | 68 } |
| 52 | 69 |
| 53 Service::~Service() { | 70 Service::~Service() { |
| 54 DeleteDataPlans(); | 71 DeleteCarrierState(); |
| 72 DeleteDataPlans(&data_plans_); |
| 55 if (device_ != NULL) { | 73 if (device_ != NULL) { |
| 56 DLOG(INFO) << path_ << ": deleting device " << device_->GetPath(); | 74 DLOG(INFO) << path_ << ": deleting device " << device_->GetPath(); |
| 57 delete device_; | 75 delete device_; |
| 58 device_ = NULL; | 76 device_ = NULL; |
| 59 } | 77 } |
| 60 } | 78 } |
| 61 | 79 |
| 62 const DBus::Path& Service::GetPath() const { | 80 const DBus::Path& Service::GetPath() const { |
| 63 return path_; | 81 return path_; |
| 64 } | 82 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 90 | 108 |
| 91 void Service::PropertyChanged(const std::string& property_name, | 109 void Service::PropertyChanged(const std::string& property_name, |
| 92 const DBus::Variant& new_value) { | 110 const DBus::Variant& new_value) { |
| 93 DLOG(INFO) << path_ << ": PropertyChanged: property_name = " << property_name; | 111 DLOG(INFO) << path_ << ": PropertyChanged: property_name = " << property_name; |
| 94 if (property_name.compare(kFlimflamServiceDeviceProperty) == 0) { | 112 if (property_name.compare(kFlimflamServiceDeviceProperty) == 0) { |
| 95 OnDeviceUpdate(new_value.reader().get_path()); | 113 OnDeviceUpdate(new_value.reader().get_path()); |
| 96 } else if (property_name.compare(kFlimflamServiceStateProperty) == 0) { | 114 } else if (property_name.compare(kFlimflamServiceStateProperty) == 0) { |
| 97 OnStateUpdate(new_value.reader().get_string()); | 115 OnStateUpdate(new_value.reader().get_string()); |
| 98 } else if (property_name.compare(kFlimflamServiceTypeProperty) == 0) { | 116 } else if (property_name.compare(kFlimflamServiceTypeProperty) == 0) { |
| 99 OnTypeUpdate(new_value.reader().get_string()); | 117 OnTypeUpdate(new_value.reader().get_string()); |
| 118 } else if (property_name.compare(kFlimflamServiceUsageUrlProperty) == 0) { |
| 119 OnUsageUrlUpdate(new_value.reader().get_string()); |
| 100 } else { | 120 } else { |
| 101 // we don't care about this property | 121 // we don't care about this property |
| 102 } | 122 } |
| 103 } | 123 } |
| 104 | 124 |
| 125 // Device methods |
| 126 |
| 127 void Service::OnCarrierUpdate(const std::string& carrier) { |
| 128 DLOG(INFO) << path_ << ": OnCarrierUpdate: carrier = " << carrier; |
| 129 // NOTE: device_ can be NULL here because we may still be in Device ctor |
| 130 DCHECK(device_ == NULL || carrier.compare(device_->GetCarrier()) == 0); |
| 131 |
| 132 // get rid of state associated with old carrier |
| 133 if (provider_ != NULL) { |
| 134 DCHECK(carrier.compare(provider_->GetCarrier())); |
| 135 } |
| 136 DeleteCarrierState(); |
| 137 |
| 138 // if we don't have new carrier info, we can't do anything now |
| 139 if (carrier.compare(Device::kCarrierUnknown) == 0) { |
| 140 return; |
| 141 } |
| 142 |
| 143 // create state for new carrier |
| 144 DLOG(INFO) << path_ << ": OnCarrierUpdate: creating data plan provider"; |
| 145 provider_ = new(std::nothrow) DataPlanProvider(carrier); |
| 146 if (provider_ == NULL) { |
| 147 LOG(ERROR) << path_ |
| 148 << ": OnCarrierUpdate: could not create data plan provider"; |
| 149 return; |
| 150 } |
| 151 provider_->SetDelegate(this); |
| 152 DLOG(INFO) << path_ << ": OnCarrierUpdate: getting policy for " << carrier; |
| 153 policy_ = Policy::GetPolicy(carrier); |
| 154 if (policy_ == NULL) { |
| 155 LOG(ERROR) << path_ << ": OnCarrierUpdate: could not get policy for " |
| 156 << carrier; |
| 157 DeleteCarrierState(); |
| 158 return; |
| 159 } |
| 160 |
| 161 // if we already have usage url, set new provider in motion |
| 162 if (!usage_url_.empty()) { |
| 163 provider_->SetUsageUrl(usage_url_); |
| 164 RequestUsageUpdate(); |
| 165 CreateUpdateTimer(); |
| 166 } else { |
| 167 // we'll do this later in OnUsageUrlUpdate |
| 168 } |
| 169 } |
| 170 |
| 171 // DataPlanProviderDelegate methods |
| 172 |
| 173 void Service::OnRequestComplete(const DataPlanProvider *provider, |
| 174 bool successful, |
| 175 const Value *parsed_usage_update) { |
| 176 DCHECK(provider != NULL); |
| 177 DCHECK(!successful || parsed_usage_update != NULL); |
| 178 if (provider != provider_) { |
| 179 DLOG(WARNING) << path_ << ": OnRequestComplete: wrong provider"; |
| 180 return; |
| 181 } |
| 182 DCHECK(request_in_progress_); |
| 183 DCHECK(policy_ != NULL); |
| 184 DLOG(INFO) << path_ << ": OnRequestComplete: result = " << successful; |
| 185 request_in_progress_ = false; |
| 186 if (!successful) { |
| 187 LOG(WARNING) << path_ << ": OnRequestComplete: request failed"; |
| 188 return; |
| 189 } |
| 190 |
| 191 // interpret and validate parsed usage update |
| 192 if (!parsed_usage_update->IsType(Value::TYPE_DICTIONARY)) { |
| 193 LOG(WARNING) << path_ |
| 194 << ": OnRequestComplete: root value is not a dictionary"; |
| 195 return; |
| 196 } |
| 197 const DictionaryValue *root = |
| 198 static_cast<const DictionaryValue*>(parsed_usage_update); |
| 199 |
| 200 int version; |
| 201 if (!root->GetInteger(kCrosUsageVersionProperty, &version)) { |
| 202 LOG(WARNING) << path_ << ": OnRequestComplete: no version property"; |
| 203 return; |
| 204 } |
| 205 DLOG(INFO) << path_ << ": OnRequestComplete: version = " << version; |
| 206 if (version < kCrosUsageVersionMinSupported || |
| 207 version > kCrosUsageVersionMaxSupported) { |
| 208 LOG(WARNING) << path_ << ": OnRequestComplete: version " << version |
| 209 << " not in supported range of [" << kCrosUsageVersionMinSupported |
| 210 << ", " << kCrosUsageVersionMaxSupported << "]"; |
| 211 return; |
| 212 } |
| 213 |
| 214 std::string status; |
| 215 if (!root->GetString(kCrosUsageStatusProperty, &status)) { |
| 216 LOG(WARNING) << path_ << ": OnRequestComplete: no status property"; |
| 217 return; |
| 218 } |
| 219 DLOG(INFO) << path_ << ": OnRequestComplete: status = " << status; |
| 220 if (status != kCrosUsageStatusOk && status != kCrosUsageStatusError) { |
| 221 LOG(WARNING) << path_ << ": OnRequestComplete: invalid status: " << status; |
| 222 return; |
| 223 } |
| 224 if (status == kCrosUsageStatusError) { |
| 225 LOG(WARNING) << path_ << ": OnRequestComplete: status: " << status; |
| 226 return; |
| 227 } |
| 228 |
| 229 bool restricted = false; |
| 230 if (root->GetBoolean(kCrosUsageRestrictedProperty, &restricted)) { |
| 231 DLOG(INFO) << path_ << ": OnRequestComplete: restricted = " << restricted; |
| 232 } else { |
| 233 DLOG(INFO) << path_ << ": OnRequestComplete: no restricted property"; |
| 234 // restricted property is optional |
| 235 } |
| 236 |
| 237 ListValue *plans = NULL; // list to which this points is owned by dictionary |
| 238 if (!root->GetList(kCrosUsagePlansProperty, &plans)) { |
| 239 LOG(WARNING) << path_ << ": OnRequestComplete: no plans property"; |
| 240 return; |
| 241 } |
| 242 DCHECK(plans != NULL); |
| 243 size_t plans_size = plans->GetSize(); |
| 244 DLOG(INFO) << path_ << ": OnRequestComplete: plans list has size " |
| 245 << plans_size; |
| 246 |
| 247 // walk plans list and convert each into a DataPlan object |
| 248 DataPlanList new_plans; |
| 249 for (size_t i = 0; i < plans_size; ++i) { |
| 250 DictionaryValue *plan_dict = NULL; |
| 251 if (!plans->GetDictionary(i, &plan_dict)) { |
| 252 LOG(WARNING) << path_ |
| 253 << ": OnRequestComplete: could not get plan[" << i << "]"; |
| 254 continue; |
| 255 } |
| 256 DCHECK(plan_dict != NULL); |
| 257 DataPlan *plan = DataPlan::FromDictionaryValue(plan_dict); |
| 258 if (plan == NULL) { |
| 259 LOG(WARNING) << path_ |
| 260 << ": OnRequestComplete: could not convert plan[" << i << "]"; |
| 261 continue; |
| 262 } |
| 263 DLOG(INFO) << path_ << ": OnRequestComplete: converted plan[" << i << "]"; |
| 264 new_plans.push_back(plan); |
| 265 } |
| 266 |
| 267 // store new info, causing it to be used for subsequent updates to clients |
| 268 DataPlanList old_plans = data_plans_; |
| 269 data_plans_ = new_plans; |
| 270 LOG(INFO) << path_ << ": OnRequestComplete: updated data plans"; |
| 271 |
| 272 // consult policy to determine if we should send an unsolicited update |
| 273 if (policy_->ShouldEmitDataPlansUpdate(old_plans, new_plans)) { |
| 274 DLOG(INFO) << path_ << ": OnRequestComplete: sending update"; |
| 275 parent_->EmitDataPlansUpdate(*this); |
| 276 } else { |
| 277 DLOG(INFO) << path_ << ": OnRequestComplete: not sending update"; |
| 278 } |
| 279 |
| 280 DLOG(INFO) << path_ << ": OnRequestComplete: deleting old data plans"; |
| 281 DeleteDataPlans(&old_plans); |
| 282 } |
| 283 |
| 105 // Private methods | 284 // Private methods |
| 106 | 285 |
| 107 Service::State Service::StateFromString(const std::string& state) const { | 286 Service::State Service::StateFromString(const std::string& state) const { |
| 108 if (state.compare(kFlimflamServiceStateIdle) == 0) { | 287 if (state.compare(kFlimflamServiceStateIdle) == 0) { |
| 109 return kStateIdle; | 288 return kStateIdle; |
| 110 } | 289 } |
| 111 if (state.compare(kFlimflamServiceStateCarrier) == 0) { | 290 if (state.compare(kFlimflamServiceStateCarrier) == 0) { |
| 112 return kStateCarrier; | 291 return kStateCarrier; |
| 113 } | 292 } |
| 114 if (state.compare(kFlimflamServiceStateAssociation) == 0) { | 293 if (state.compare(kFlimflamServiceStateAssociation) == 0) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 delete device_; | 341 delete device_; |
| 163 device_ = NULL; | 342 device_ = NULL; |
| 164 } | 343 } |
| 165 | 344 |
| 166 // if there's an existing device with matching path: all is well | 345 // if there's an existing device with matching path: all is well |
| 167 if (device_ != NULL) { | 346 if (device_ != NULL) { |
| 168 return; | 347 return; |
| 169 } | 348 } |
| 170 | 349 |
| 171 // if there's no existing device: make one | 350 // if there's no existing device: make one |
| 172 device_ = new(std::nothrow) Device(connection_, device_path); | 351 device_ = new(std::nothrow) Device(this, connection_, device_path); |
| 173 if (device_ == NULL) { | 352 if (device_ == NULL) { |
| 174 LOG(ERROR) << path_ << ": OnDeviceUpdate: couldn't create device for " | 353 LOG(ERROR) << path_ << ": OnDeviceUpdate: couldn't create device for " |
| 175 << device_path; | 354 << device_path; |
| 176 return; | 355 return; |
| 177 } | 356 } |
| 178 DLOG(INFO) << path_ << ": OnDeviceUpdate: created device for " | 357 DLOG(INFO) << path_ << ": OnDeviceUpdate: created device for " |
| 179 << device_path; | 358 << device_path; |
| 180 } | 359 } |
| 181 | 360 |
| 182 void Service::OnStateUpdate(const std::string& state) { | 361 void Service::OnStateUpdate(const std::string& state) { |
| 183 DLOG(INFO) << path_ << ": OnStateUpdate: state = " << state; | 362 DLOG(INFO) << path_ << ": OnStateUpdate: state = " << state; |
| 184 state_ = StateFromString(state); | 363 state_ = StateFromString(state); |
| 185 // TODO(vlaviano): react to state changes | 364 // TODO(vlaviano): react to state changes |
| 186 // note that ready does not necessarily mean that we're the default route | 365 // note that ready does not necessarily mean that we're the default route |
| 187 } | 366 } |
| 188 | 367 |
| 189 void Service::OnTypeUpdate(const std::string& type) { | 368 void Service::OnTypeUpdate(const std::string& type) { |
| 190 DLOG(INFO) << path_ << ": OnTypeUpdate: type = " << type; | 369 DLOG(INFO) << path_ << ": OnTypeUpdate: type = " << type; |
| 191 type_ = TypeFromString(type); | 370 type_ = TypeFromString(type); |
| 192 if (type_ != kTypeCellular) { | 371 if (type_ != kTypeCellular) { |
| 193 LOG(WARNING) << path_ << ": OnTypeUpdate: type is not cellular!"; | 372 LOG(WARNING) << path_ << ": OnTypeUpdate: type is not cellular!"; |
| 194 } | 373 } |
| 195 } | 374 } |
| 196 | 375 |
| 376 void Service::OnUsageUrlUpdate(const std::string& usage_url) { |
| 377 DLOG(INFO) << path_ << ": OnUsageUrlUpdate: url = " << usage_url; |
| 378 if (usage_url.compare(usage_url_) == 0) { |
| 379 return; |
| 380 } |
| 381 usage_url_ = usage_url; |
| 382 if (provider_ != NULL) { |
| 383 DCHECK(usage_url.compare(provider_->GetUsageUrl())); |
| 384 DestroyUpdateTimer(); |
| 385 CancelPendingRequests(); |
| 386 provider_->SetUsageUrl(usage_url); |
| 387 RequestUsageUpdate(); |
| 388 CreateUpdateTimer(); |
| 389 } |
| 390 } |
| 391 |
| 197 void Service::GetServiceProperties() { | 392 void Service::GetServiceProperties() { |
| 198 DLOG(INFO) << path_ << ": GetServiceProperties"; | 393 DLOG(INFO) << path_ << ": GetServiceProperties"; |
| 199 PropertyMap properties; | 394 PropertyMap properties; |
| 200 // dbus-c++ throws exceptions | 395 // dbus-c++ throws exceptions |
| 201 // invoke the "Existing Non-conformant Code" clause of the style guide and | 396 // invoke the "Existing Non-conformant Code" clause of the style guide and |
| 202 // isolate the rest of the system from this | 397 // isolate the rest of the system from this |
| 203 try { | 398 try { |
| 204 // TODO(vlaviano): make this call asynchronous | 399 // TODO(vlaviano): make this call asynchronous |
| 205 properties = GetProperties(); | 400 properties = GetProperties(); |
| 206 } catch (DBus::Error& error) { // NOLINT | 401 } catch (DBus::Error& error) { // NOLINT |
| (...skipping 26 matching lines...) Expand all Loading... |
| 233 } else { | 428 } else { |
| 234 DLOG(WARNING) << path_ << ": GetServiceProperties: no State property"; | 429 DLOG(WARNING) << path_ << ": GetServiceProperties: no State property"; |
| 235 } | 430 } |
| 236 it = properties.find(kFlimflamServiceTypeProperty); | 431 it = properties.find(kFlimflamServiceTypeProperty); |
| 237 if (it != properties.end()) { | 432 if (it != properties.end()) { |
| 238 const DBus::Variant& value = static_cast<DBus::Variant>(it->second); | 433 const DBus::Variant& value = static_cast<DBus::Variant>(it->second); |
| 239 OnTypeUpdate(value.reader().get_string()); | 434 OnTypeUpdate(value.reader().get_string()); |
| 240 } else { | 435 } else { |
| 241 DLOG(WARNING) << path_ << ": GetServiceProperties: no Type property"; | 436 DLOG(WARNING) << path_ << ": GetServiceProperties: no Type property"; |
| 242 } | 437 } |
| 438 // don't expect to find Cellular.* properties if we're not a cellular service |
| 439 if (type_ != kTypeCellular) { |
| 440 return; |
| 441 } |
| 442 it = properties.find(kFlimflamServiceUsageUrlProperty); |
| 443 if (it != properties.end()) { |
| 444 const DBus::Variant& value = static_cast<DBus::Variant>(it->second); |
| 445 OnUsageUrlUpdate(value.reader().get_string()); |
| 446 } else { |
| 447 DLOG(WARNING) << path_ |
| 448 << ": GetServiceProperties: no Cellular.UsageUrl property"; |
| 449 } |
| 243 } | 450 } |
| 244 | 451 |
| 245 void Service::DeleteDataPlans() { | 452 void Service::DeleteDataPlans(DataPlanList *data_plans) { |
| 246 while (!data_plans_.empty()) { | 453 DCHECK(data_plans != NULL); |
| 247 DataPlan *plan = *data_plans_.begin(); | 454 while (!data_plans->empty()) { |
| 455 DataPlan *plan = *data_plans->begin(); |
| 248 DCHECK(plan != NULL); | 456 DCHECK(plan != NULL); |
| 249 DLOG(INFO) << path_ << ": DeleteDataPlans: deleting plan: " | 457 DLOG(INFO) << path_ << ": DeleteDataPlans: deleting plan: " |
| 250 << plan->GetName(); | 458 << plan->GetName(); |
| 251 delete plan; | 459 delete plan; |
| 252 data_plans_.erase(data_plans_.begin()); | 460 data_plans->erase(data_plans->begin()); |
| 253 } | 461 } |
| 254 } | 462 } |
| 255 | 463 |
| 256 void Service::AddHardcodedDataPlan() { | 464 void Service::AddHardcodedDataPlan() { |
| 257 const std::string name = "Chromium OS Test Plan"; | 465 const std::string name = "Chromium OS Test Plan"; |
| 258 DataPlan::Type type = DataPlan::kTypeMeteredPaid; | 466 DataPlan::Type type = DataPlan::kTypeMeteredPaid; |
| 259 base::Time update_time = base::Time::Now(); | 467 base::Time update_time = base::Time::Now(); |
| 260 base::TimeDelta twelve_hours = base::TimeDelta::FromHours(12); | 468 base::TimeDelta twelve_hours = base::TimeDelta::FromHours(12); |
| 261 base::Time start_time = base::Time::Now() - twelve_hours; | 469 base::Time start_time = base::Time::Now() - twelve_hours; |
| 262 base::Time end_time = base::Time::Now() + twelve_hours; | 470 base::Time end_time = base::Time::Now() + twelve_hours; |
| 263 Bytes data_bytes_max = 100*1024*1024; // 100 MB | 471 Bytes data_bytes_max = 100*1024*1024; // 100 MB |
| 264 Bytes data_bytes_used = 30*1024*1024; // 30 MB | 472 Bytes data_bytes_used = 30*1024*1024; // 30 MB |
| 265 | 473 |
| 266 DataPlan *plan = new(std::nothrow) DataPlan(name, type, update_time, | 474 DataPlan *plan = new(std::nothrow) DataPlan(name, type, update_time, |
| 267 start_time, end_time, | 475 start_time, end_time, |
| 268 data_bytes_max, data_bytes_used); | 476 data_bytes_max, data_bytes_used); |
| 269 if (plan == NULL) { | 477 if (plan == NULL) { |
| 270 LOG(ERROR) << path_ << ": AddHardcodedDataPlan: could not create plan"; | 478 LOG(ERROR) << path_ << ": AddHardcodedDataPlan: could not create plan"; |
| 271 return; | 479 return; |
| 272 } | 480 } |
| 273 | 481 |
| 274 data_plans_.push_back(plan); | 482 data_plans_.push_back(plan); |
| 275 } | 483 } |
| 276 | 484 |
| 485 void Service::RequestUsageUpdate() { |
| 486 DCHECK(provider_ != NULL); |
| 487 DCHECK(!usage_url_.empty()); |
| 488 DCHECK(device_ == NULL || |
| 489 device_->GetCarrier().compare(Device::kCarrierUnknown)); |
| 490 |
| 491 if (request_in_progress_) { |
| 492 return; |
| 493 } |
| 494 |
| 495 // TODO(vlaviano): apply policy to determine if current connectivity state |
| 496 // allows this request (e.g., if we can only make API requests over the |
| 497 // cellular service itself, is this service the default route?) |
| 498 |
| 499 if (!provider_->RequestUsageUpdate()) { |
| 500 DLOG(WARNING) << path_ << ": RequestUsageUpdate: request failed"; |
| 501 } else { |
| 502 DLOG(INFO) << path_ << ": RequestUsageUpdate: request succeeded"; |
| 503 request_in_progress_ = true; |
| 504 } |
| 505 } |
| 506 |
| 507 void Service::CancelPendingRequests() { |
| 508 if (provider_ != NULL && request_in_progress_) { |
| 509 provider_->CancelPendingRequests(); |
| 510 request_in_progress_ = false; |
| 511 } |
| 512 } |
| 513 |
| 514 gboolean Service::UpdateTimeoutCallback() { |
| 515 DLOG(INFO) << path_ << ": UpdateTimeoutCallback"; |
| 516 RequestUsageUpdate(); |
| 517 return TRUE; |
| 518 } |
| 519 |
| 520 // static |
| 521 gboolean Service::StaticUpdateTimeoutCallback(gpointer data) { |
| 522 CHECK_NOTNULL(data); |
| 523 return reinterpret_cast<Service*>(data)->UpdateTimeoutCallback(); |
| 524 } |
| 525 |
| 526 bool Service::CreateUpdateTimer() { |
| 527 DCHECK(provider_ != NULL); |
| 528 DCHECK(policy_ != NULL); |
| 529 guint idle_seconds = policy_->GetUpdateTimerIdleSecs(data_plans_); |
| 530 DLOG(INFO) << path_ << ": CreateUpdateTimer: idle_seconds = " << idle_seconds; |
| 531 if (update_timeout_source_ != NULL) { |
| 532 DLOG(WARNING) << path_ << ": CreateUpdateTimer: timer already running"; |
| 533 return false; |
| 534 } |
| 535 update_timeout_source_ = g_timeout_source_new_seconds(idle_seconds); |
| 536 if (update_timeout_source_ == NULL) { |
| 537 DLOG(WARNING) << path_ |
| 538 << ": CreateUpdateTimer: could not create timeout source"; |
| 539 return false; |
| 540 } |
| 541 g_source_set_callback(update_timeout_source_, StaticUpdateTimeoutCallback, |
| 542 this, NULL); |
| 543 g_source_attach(update_timeout_source_, NULL); |
| 544 return true; |
| 545 } |
| 546 |
| 547 void Service::DestroyUpdateTimer() { |
| 548 DLOG(INFO) << path_ << ": DestroyUpdateTimer"; |
| 549 if (update_timeout_source_ != NULL) { |
| 550 g_source_destroy(update_timeout_source_); |
| 551 update_timeout_source_ = NULL; |
| 552 } |
| 553 } |
| 554 |
| 555 void Service::DeleteCarrierState() { |
| 556 DLOG(INFO) << path_ << ": DeleteCarrierState"; |
| 557 if (policy_ != NULL) { |
| 558 DLOG(INFO) << path_ << ": DeleteCarrierState: deleting policy"; |
| 559 delete policy_; |
| 560 policy_ = NULL; |
| 561 } |
| 562 DestroyUpdateTimer(); |
| 563 CancelPendingRequests(); |
| 564 if (provider_ != NULL) { |
| 565 DLOG(INFO) << path_ << ": DeleteCarrierState: deleting data plan provider"; |
| 566 delete provider_; |
| 567 provider_ = NULL; |
| 568 } |
| 569 } |
| 570 |
| 277 } // namespace cashew | 571 } // namespace cashew |
| OLD | NEW |