| 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/data_plan.h" | 5 #include "src/data_plan.h" |
| 6 | 6 |
| 7 #include <time.h> |
| 8 |
| 7 #include <glog/logging.h> | 9 #include <glog/logging.h> |
| 8 | 10 |
| 9 namespace cashew { | 11 namespace cashew { |
| 10 | 12 |
| 11 // libcros CellularDataPlan property names | 13 // libcros CellularDataPlan property names |
| 12 static const char* kCellularDataPlanName = "CellularPlanName"; | 14 // (what we send to libcros) |
| 13 static const char* kCellularDataPlanType = "CellularPlanType"; | 15 static const char *kCellularDataPlanName = "CellularPlanName"; |
| 14 static const char* kCellularDataPlanUpdateTime = "CellularPlanUpdateTime"; | 16 static const char *kCellularDataPlanType = "CellularPlanType"; |
| 15 static const char* kCellularDataPlanStartTime = "CellularPlanStart"; | 17 static const char *kCellularDataPlanUpdateTime = "CellularPlanUpdateTime"; |
| 16 static const char* kCellularDataPlanEndTime = "CellularPlanEnd"; | 18 static const char *kCellularDataPlanStartTime = "CellularPlanStart"; |
| 17 static const char* kCellularDataPlanDataBytesMax = "CellularPlanDataBytes"; | 19 static const char *kCellularDataPlanEndTime = "CellularPlanEnd"; |
| 18 static const char* kCellularDataPlanDataBytesUsed = "CellularDataBytesUsed"; | 20 static const char *kCellularDataPlanDataBytesMax = "CellularPlanDataBytes"; |
| 21 static const char *kCellularDataPlanDataBytesUsed = "CellularDataBytesUsed"; |
| 19 | 22 |
| 20 // libcros CellularDataPlan type values | 23 // libcros CellularDataPlan type values |
| 21 static const char* kCellularDataPlanTypeUnlimited = "UNLIMITED"; | 24 static const char *kCellularDataPlanTypeUnlimited = "UNLIMITED"; |
| 22 static const char* kCellularDataPlanTypeMeteredFree = "METERED_BASE"; | 25 static const char *kCellularDataPlanTypeMeteredFree = "METERED_BASE"; |
| 23 static const char* kCellularDataPlanTypeMeteredPaid = "METERED_PAID"; | 26 static const char *kCellularDataPlanTypeMeteredPaid = "METERED_PAID"; |
| 27 |
| 28 // Chromium OS Usage API Data Plan property names |
| 29 // (what we receive from carrier usage API) |
| 30 static const char *kCrosUsageDataPlanLastUpdateProperty = "lastUpdate"; |
| 31 static const char *kCrosUsageDataPlanNameProperty = "planName"; |
| 32 static const char *kCrosUsageDataPlanTypeProperty = "planType"; |
| 33 static const char *kCrosUsageDataPlanMaxBytesProperty = "maxBytes"; |
| 34 static const char *kCrosUsageDataPlanUsedBytesProperty = "usedBytes"; |
| 35 static const char *kCrosUsageDataPlanEndTimeProperty = "expirationTime"; |
| 36 static const char *kCrosUsageDataPlanStartTimeProperty = "startTime"; |
| 37 |
| 38 // Chromium OS Usage API Data Plan type values |
| 39 static const char *kCrosUsageDataPlanTypeUnlimited = "UNLIMITED"; |
| 40 static const char *kCrosUsageDataPlanTypeMeteredFree = "METERED_FREE"; |
| 41 static const char *kCrosUsageDataPlanTypeMeteredPaid = "METERED_PAID"; |
| 24 | 42 |
| 25 DataPlan::DataPlan(const std::string& name, DataPlan::Type type, | 43 DataPlan::DataPlan(const std::string& name, DataPlan::Type type, |
| 26 base::Time update_time, base::Time start_time, | 44 base::Time update_time, base::Time start_time, |
| 27 base::Time end_time, Bytes data_bytes_max, | 45 base::Time end_time, Bytes data_bytes_max, |
| 28 Bytes data_bytes_used) | 46 Bytes data_bytes_used) |
| 29 : name_(name), type_(type), update_time_(update_time), | 47 : name_(name), type_(type), update_time_(update_time), |
| 30 start_time_(start_time), end_time_(end_time), | 48 start_time_(start_time), end_time_(end_time), |
| 31 data_bytes_max_(data_bytes_max), data_bytes_used_(data_bytes_used) { | 49 data_bytes_max_(data_bytes_max), data_bytes_used_(data_bytes_used) { |
| 32 } | 50 } |
| 33 | 51 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 59 } | 77 } |
| 60 | 78 |
| 61 Bytes DataPlan::GetDataBytesUsed() const { | 79 Bytes DataPlan::GetDataBytesUsed() const { |
| 62 return data_bytes_used_; | 80 return data_bytes_used_; |
| 63 } | 81 } |
| 64 | 82 |
| 65 DBusDataPlan DataPlan::ToDBusFormat() const { | 83 DBusDataPlan DataPlan::ToDBusFormat() const { |
| 66 DBusDataPlan plan; | 84 DBusDataPlan plan; |
| 67 // Indexing into map w/ nonexistent key causes empty DBus::Variant to be | 85 // Indexing into map w/ nonexistent key causes empty DBus::Variant to be |
| 68 // created and inserted. We then fill in the desired value via its writer | 86 // created and inserted. We then fill in the desired value via its writer |
| 69 // DBus::MessageIterator. | 87 // DBus::MessageIter. |
| 70 plan[kCellularDataPlanName].writer().append_string(name_.c_str()); | 88 plan[kCellularDataPlanName].writer().append_string(name_.c_str()); |
| 71 plan[kCellularDataPlanType].writer().append_string(TypeToString(type_)); | 89 plan[kCellularDataPlanType].writer().append_string( |
| 90 TypeToLibcrosString(type_)); |
| 72 plan[kCellularDataPlanUpdateTime].writer().append_int64( | 91 plan[kCellularDataPlanUpdateTime].writer().append_int64( |
| 73 update_time_.ToInternalValue()); | 92 update_time_.ToInternalValue()); |
| 74 plan[kCellularDataPlanStartTime].writer().append_int64( | 93 plan[kCellularDataPlanStartTime].writer().append_int64( |
| 75 start_time_.ToInternalValue()); | 94 start_time_.ToInternalValue()); |
| 76 plan[kCellularDataPlanEndTime].writer().append_int64( | 95 plan[kCellularDataPlanEndTime].writer().append_int64( |
| 77 end_time_.ToInternalValue()); | 96 end_time_.ToInternalValue()); |
| 78 // omit max bytes field for unlimited plans | 97 // omit max bytes field for unlimited plans |
| 79 // can libcros/Chrome deal? if not, can set this to int64 max. | 98 // can libcros/Chrome deal? if not, can set this to int64 max. |
| 80 if (type_ != kTypeUnlimited) { | 99 if (type_ != kTypeUnlimited) { |
| 81 plan[kCellularDataPlanDataBytesMax].writer().append_int64(data_bytes_max_); | 100 plan[kCellularDataPlanDataBytesMax].writer().append_int64(data_bytes_max_); |
| 82 } | 101 } |
| 83 plan[kCellularDataPlanDataBytesUsed].writer().append_int64(data_bytes_used_); | 102 plan[kCellularDataPlanDataBytesUsed].writer().append_int64(data_bytes_used_); |
| 84 return plan; | 103 return plan; |
| 85 } | 104 } |
| 86 | 105 |
| 106 // static |
| 107 DataPlan* DataPlan::FromDictionaryValue(const DictionaryValue *value) { |
| 108 DCHECK(value != NULL); |
| 109 std::string last_update_iso8601; |
| 110 if (!value->GetString(kCrosUsageDataPlanLastUpdateProperty, |
| 111 &last_update_iso8601)) { |
| 112 LOG(WARNING) << "FromDictionaryValue: no last update property"; |
| 113 return NULL; |
| 114 } |
| 115 DLOG(INFO) << "FromDictionaryValue: last update = " << last_update_iso8601; |
| 116 base::Time last_update; |
| 117 if (!TimeFromISO8601UTC(last_update_iso8601, &last_update)) { |
| 118 LOG(WARNING) << "FromDictionaryValue: could not convert last update time"; |
| 119 return NULL; |
| 120 } |
| 121 |
| 122 std::string plan_name; |
| 123 if (!value->GetString(kCrosUsageDataPlanNameProperty, &plan_name)) { |
| 124 LOG(WARNING) << "FromDictionaryValue: no plan name property"; |
| 125 return NULL; |
| 126 } |
| 127 DLOG(INFO) << "FromDictionaryValue: plan name = " << plan_name; |
| 128 |
| 129 std::string plan_type_string; |
| 130 if (!value->GetString(kCrosUsageDataPlanTypeProperty, &plan_type_string)) { |
| 131 LOG(WARNING) << "FromDictionaryValue: no plan type property"; |
| 132 return NULL; |
| 133 } |
| 134 DLOG(INFO) << "FromDictionaryValue: plan type string = " << plan_type_string; |
| 135 Type plan_type; |
| 136 if (!CrosUsageStringToType(plan_type_string, &plan_type)) { |
| 137 LOG(WARNING) << "FromDictionaryValue: invalid plan type string: " |
| 138 << plan_type_string; |
| 139 return NULL; |
| 140 } |
| 141 DLOG(INFO) << "FromDictionaryValue: converted plan type string to type " |
| 142 << plan_type; |
| 143 |
| 144 int max_bytes = 0; |
| 145 // we only expect max bytes for metered plans |
| 146 if (plan_type != kTypeUnlimited) { |
| 147 if (!value->GetInteger(kCrosUsageDataPlanMaxBytesProperty, &max_bytes)) { |
| 148 LOG(WARNING) << "FromDictionaryValue: no max bytes property"; |
| 149 return NULL; |
| 150 } |
| 151 if (max_bytes < 0) { |
| 152 LOG(WARNING) << "FromDictionaryValue: max bytes is negative"; |
| 153 return NULL; |
| 154 } |
| 155 DLOG(INFO) << "FromDictionaryValue: max bytes = " << max_bytes; |
| 156 } |
| 157 |
| 158 int used_bytes = 0; |
| 159 if (!value->GetInteger(kCrosUsageDataPlanUsedBytesProperty, &used_bytes)) { |
| 160 LOG(WARNING) << "FromDictionaryValue: no used bytes property"; |
| 161 return NULL; |
| 162 } |
| 163 if (used_bytes < 0) { |
| 164 LOG(WARNING) << "FromDictionaryValue: used bytes is negative"; |
| 165 return NULL; |
| 166 } |
| 167 DLOG(INFO) << "FromDictionaryValue: used bytes = " << used_bytes; |
| 168 |
| 169 std::string start_time_iso8601; |
| 170 if (!value->GetString(kCrosUsageDataPlanStartTimeProperty, |
| 171 &start_time_iso8601)) { |
| 172 LOG(WARNING) << "FromDictionaryValue: no start time property"; |
| 173 return NULL; |
| 174 } |
| 175 DLOG(INFO) << "FromDictionaryValue: start time = " << start_time_iso8601; |
| 176 base::Time start_time; |
| 177 if (!TimeFromISO8601UTC(start_time_iso8601, &start_time)) { |
| 178 LOG(WARNING) << "FromDictionaryValue: could not convert start time"; |
| 179 return NULL; |
| 180 } |
| 181 |
| 182 std::string end_time_iso8601; |
| 183 if (!value->GetString(kCrosUsageDataPlanEndTimeProperty, |
| 184 &end_time_iso8601)) { |
| 185 LOG(WARNING) << "FromDictionaryValue: no end time property"; |
| 186 return NULL; |
| 187 } |
| 188 DLOG(INFO) << "FromDictionaryValue: end time = " << end_time_iso8601; |
| 189 base::Time end_time; |
| 190 if (!TimeFromISO8601UTC(end_time_iso8601, &end_time)) { |
| 191 LOG(WARNING) << "FromDictionaryValue: could not convert end time"; |
| 192 return NULL; |
| 193 } |
| 194 |
| 195 if (start_time > end_time) { |
| 196 LOG(WARNING) << "FromDictionaryValue: start time > end time"; |
| 197 return NULL; |
| 198 } |
| 199 |
| 200 return new(std::nothrow) DataPlan(plan_name, plan_type, last_update, |
| 201 start_time, end_time, max_bytes, |
| 202 used_bytes); |
| 203 } |
| 204 |
| 205 // static |
| 206 bool DataPlan::TimeFromISO8601UTC(const std::string& time_8601_utc, |
| 207 base::Time *time_out) { |
| 208 DCHECK(time_out != NULL); |
| 209 static const char *kISO8601UTCTimeFormat = "%Y-%m-%dT%H:%M:%SZ"; |
| 210 struct tm tm; |
| 211 if (strptime(time_8601_utc.c_str(), kISO8601UTCTimeFormat, &tm) == NULL) { |
| 212 DLOG(WARNING) << "TimeFromISO8601UTC: strptime failed for time string: " |
| 213 << time_8601_utc; |
| 214 return false; |
| 215 } |
| 216 time_t tt; |
| 217 // NOTE: timegm interprets its input as being in UTC. |
| 218 if ((tt = timegm(&tm)) == -1) { |
| 219 DLOG(WARNING) << "TimeFromISO8601UTC: timegm failed"; |
| 220 return false; |
| 221 } |
| 222 *time_out = base::Time::FromTimeT(tt); |
| 223 return true; |
| 224 } |
| 225 |
| 87 // private methods | 226 // private methods |
| 88 | 227 |
| 89 const char* DataPlan::TypeToString(DataPlan::Type type) const { | 228 const char* DataPlan::TypeToLibcrosString(DataPlan::Type type) const { |
| 90 switch (type) { | 229 switch (type) { |
| 91 case kTypeUnlimited: | 230 case kTypeUnlimited: |
| 92 return kCellularDataPlanTypeUnlimited; | 231 return kCellularDataPlanTypeUnlimited; |
| 93 case kTypeMeteredFree: | 232 case kTypeMeteredFree: |
| 94 return kCellularDataPlanTypeMeteredFree; | 233 return kCellularDataPlanTypeMeteredFree; |
| 95 case kTypeMeteredPaid: | 234 case kTypeMeteredPaid: |
| 96 return kCellularDataPlanTypeMeteredPaid; | 235 return kCellularDataPlanTypeMeteredPaid; |
| 97 default: | 236 default: |
| 98 DCHECK(false); | 237 DCHECK(false); |
| 99 } | 238 } |
| 100 } | 239 } |
| 101 | 240 |
| 241 // static |
| 242 bool DataPlan::CrosUsageStringToType(const std::string& type_string, |
| 243 DataPlan::Type *type_out) { |
| 244 CHECK_NOTNULL(type_out); |
| 245 if (type_string == kCrosUsageDataPlanTypeUnlimited) { |
| 246 *type_out = kTypeUnlimited; |
| 247 } else if (type_string == kCrosUsageDataPlanTypeMeteredFree) { |
| 248 *type_out = kTypeMeteredFree; |
| 249 } else if (type_string == kCrosUsageDataPlanTypeMeteredPaid) { |
| 250 *type_out = kTypeMeteredPaid; |
| 251 } else { |
| 252 return false; |
| 253 } |
| 254 return true; |
| 255 } |
| 256 |
| 102 } // namespace cashew | 257 } // namespace cashew |
| OLD | NEW |