Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2011 The Chromium 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 "chrome/browser/chromeos/mobile_config.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 | |
| 9 #include "base/file_path.h" | |
| 10 #include "base/file_util.h" | |
| 11 #include "base/json/json_reader.h" | |
| 12 #include "base/logging.h" | |
| 13 #include "base/values.h" | |
| 14 #include "chrome/browser/browser_process.h" | |
| 15 #include "chrome/browser/chromeos/login/wizard_controller.h" | |
| 16 #include "content/browser/browser_thread.h" | |
| 17 | |
| 18 namespace { | |
| 19 | |
| 20 // Config attributes names. | |
| 21 const char kVersionAttr[] = "version"; | |
| 22 const char kAcceptedConfigVersion[] = "1.0"; | |
| 23 const char kDefaultAttr[] = "default"; | |
| 24 | |
| 25 // Carrier config attributes. | |
| 26 const char kCarriersAttr[] = "carriers"; | |
| 27 const char kCarrierIdsAttr[] = "ids"; | |
| 28 const char kCarrierIdAttr[] = "id"; | |
| 29 const char kTopUpURLAttr[] = "top_up_url"; | |
| 30 const char kDealsAttr[] = "deals"; | |
| 31 | |
| 32 // Carrier deal attributes. | |
| 33 const char kDealIdAttr[] = "deal_id"; | |
| 34 const char kDealLocalesAttr[] = "locales"; | |
| 35 | |
| 36 const char kInfoURLAttr[] = "info_url"; | |
| 37 const char kNotificationCountAttr[] = "notification_count"; | |
| 38 const char kDealExpireDateAttr[] = "expire_date"; | |
| 39 const char kLocalizedContentAttr[] = "localized_content"; | |
| 40 const char kNotificationTextAttr[] = "notification_text"; | |
| 41 | |
| 42 // Location of the global carrier config. | |
| 43 const char kGlobalCarrierConfigPath[] = | |
| 44 "/usr/share/chromeos-assets/mobile/carrier_config.json"; | |
| 45 | |
| 46 } // anonymous namespace | |
| 47 | |
| 48 DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::MobileConfig); | |
| 49 | |
| 50 namespace chromeos { | |
| 51 | |
| 52 // MobileConfig::CarrierDeal implementation. ------------------ | |
| 53 | |
| 54 MobileConfig::CarrierDeal::CarrierDeal(DictionaryValue* deal_dict) | |
| 55 : notification_count_(0), | |
| 56 localized_strings_(NULL) { | |
| 57 deal_dict->GetString(kDealIdAttr, &deal_id_); | |
| 58 | |
| 59 // Extract list of deal locales. | |
| 60 ListValue* locale_list = NULL; | |
| 61 if (deal_dict->GetList(kDealLocalesAttr, &locale_list)) { | |
| 62 for (size_t i = 0; i < locale_list->GetSize(); ++i) { | |
| 63 std::string locale; | |
| 64 if (locale_list->GetString(i, &locale)) | |
| 65 locales_.push_back(locale); | |
| 66 } | |
| 67 } | |
| 68 | |
| 69 deal_dict->GetString(kInfoURLAttr, &info_url_); | |
| 70 deal_dict->GetInteger(kNotificationCountAttr, ¬ification_count_); | |
| 71 std::string date_string; | |
| 72 if (deal_dict->GetString(kDealExpireDateAttr, &date_string)) { | |
| 73 if (!base::Time::FromString(date_string.c_str(), &expire_date_)) | |
| 74 LOG(ERROR) << "Error parsing deal_expire_date: " << date_string; | |
| 75 } | |
| 76 deal_dict->GetDictionary(kLocalizedContentAttr, &localized_strings_); | |
| 77 } | |
| 78 | |
| 79 MobileConfig::CarrierDeal::~CarrierDeal() { | |
| 80 } | |
| 81 | |
| 82 std::string MobileConfig::CarrierDeal::GetLocalizedString( | |
| 83 const std::string& locale, const std::string& id) const { | |
| 84 std::string result; | |
| 85 if (localized_strings_) { | |
| 86 DictionaryValue* locale_dict = NULL; | |
| 87 if (localized_strings_->GetDictionary(locale, &locale_dict) && | |
| 88 locale_dict->GetString(id, &result)) { | |
| 89 return result; | |
| 90 } else if (localized_strings_->GetDictionary(kDefaultAttr, &locale_dict) && | |
| 91 locale_dict->GetString(id, &result)) { | |
| 92 return result; | |
| 93 } | |
| 94 } | |
| 95 return result; | |
| 96 } | |
| 97 | |
| 98 // MobileConfig::Carrier implementation. ---------------------- | |
| 99 | |
| 100 MobileConfig::Carrier::Carrier(DictionaryValue* carrier_dict, | |
| 101 const std::string& initial_locale) { | |
| 102 carrier_dict->GetString(kTopUpURLAttr, &top_up_url_); | |
| 103 | |
| 104 // Extract list of external IDs for this carrier. | |
| 105 ListValue* id_list = NULL; | |
| 106 if (carrier_dict->GetList(kCarrierIdsAttr, &id_list)) { | |
| 107 for (size_t i = 0; i < id_list->GetSize(); ++i) { | |
| 108 DictionaryValue* id_dict = NULL; | |
| 109 std::string external_id; | |
| 110 if (id_list->GetDictionary(i, &id_dict) && | |
| 111 id_dict->GetString(kCarrierIdAttr, &external_id)) { | |
| 112 external_ids_.push_back(external_id); | |
| 113 } | |
| 114 } | |
| 115 } | |
| 116 | |
| 117 // Extract list of deals for this carrier. | |
| 118 ListValue* deals_list = NULL; | |
| 119 if (carrier_dict->GetList(kDealsAttr, &deals_list)) { | |
| 120 for (size_t i = 0; i < deals_list->GetSize(); ++i) { | |
| 121 DictionaryValue* deal_dict = NULL; | |
| 122 if (deals_list->GetDictionary(i, &deal_dict)) { | |
| 123 CarrierDeal* deal = new CarrierDeal(deal_dict); | |
|
Dmitry Polukhin
2011/09/05 06:33:11
It looks like, here there is memory leak. |deal| m
Nikita (slow)
2011/09/05 10:13:44
Done.
| |
| 124 // Filter out deals by initial_locale right away. | |
| 125 std::vector<std::string>::const_iterator iter = | |
| 126 std::find(deal->locales().begin(), | |
| 127 deal->locales().end(), | |
| 128 initial_locale); | |
| 129 if (iter != deal->locales().end()) | |
| 130 deals_[deal->deal_id()] = deal; | |
| 131 } | |
| 132 } | |
| 133 } | |
| 134 } | |
| 135 | |
| 136 MobileConfig::Carrier::~Carrier() { | |
| 137 } | |
| 138 | |
| 139 const MobileConfig::CarrierDeal* MobileConfig::Carrier::GetDefaultDeal() const { | |
| 140 // TODO(nkostylev): Use carrier "default_deal_id" attribute. | |
| 141 CarrierDeals::const_iterator iter = deals_.begin(); | |
| 142 if (iter != deals_.end()) | |
| 143 return GetDeal((*iter).first); | |
| 144 else | |
| 145 return NULL; | |
| 146 } | |
| 147 | |
| 148 const MobileConfig::CarrierDeal* MobileConfig::Carrier::GetDeal( | |
| 149 const std::string& deal_id) const { | |
| 150 CarrierDeals::const_iterator iter = deals_.find(deal_id); | |
| 151 if (iter != deals_.end()) { | |
| 152 CarrierDeal* deal = iter->second; | |
| 153 // Make sure that deal is still active, | |
| 154 // i.e. if deal expire date is defined, check it. | |
| 155 if (!deal->expire_date().is_null() && | |
| 156 deal->expire_date() <= base::Time::Now()) { | |
| 157 return NULL; | |
| 158 } | |
| 159 return deal; | |
| 160 } else { | |
| 161 return NULL; | |
| 162 } | |
| 163 } | |
| 164 | |
| 165 // MobileConfig implementation. ------------------------------- | |
| 166 | |
| 167 MobileConfig::MobileConfig() | |
| 168 : initial_locale_(WizardController::GetInitialLocale()) { | |
| 169 LoadConfig(); | |
| 170 } | |
| 171 | |
| 172 MobileConfig::MobileConfig( | |
| 173 const std::string& config, const std::string& initial_locale) | |
| 174 : initial_locale_(initial_locale) { | |
| 175 LoadConfigFromString(config); | |
| 176 } | |
| 177 | |
| 178 MobileConfig::~MobileConfig() {} | |
| 179 | |
| 180 // static | |
| 181 MobileConfig* MobileConfig::GetInstance() { | |
| 182 return Singleton<MobileConfig, | |
| 183 DefaultSingletonTraits<MobileConfig> >::get(); | |
| 184 } | |
| 185 | |
| 186 bool MobileConfig::IsReady() { | |
| 187 return root_.get() != NULL; | |
| 188 } | |
| 189 | |
| 190 void MobileConfig::LoadConfig() { | |
| 191 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | |
| 192 NewRunnableMethod(this, | |
| 193 &MobileConfig::ReadFileInBackground, | |
| 194 FilePath(kGlobalCarrierConfigPath))); | |
| 195 } | |
| 196 | |
| 197 void MobileConfig::ReadFileInBackground(const FilePath& file) { | |
| 198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 199 std::string config; | |
| 200 if (file_util::ReadFileToString(file, &config)) { | |
| 201 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
| 202 NewRunnableMethod( | |
| 203 this, | |
| 204 &MobileConfig::LoadConfigFromString, | |
| 205 config)); | |
| 206 } else { | |
| 207 VLOG(1) << "Failed to load mobile config from: " | |
| 208 << file.value(); | |
| 209 } | |
| 210 } | |
| 211 | |
| 212 const MobileConfig::Carrier* MobileConfig::GetCarrier( | |
| 213 const std::string& carrier_id) const { | |
| 214 CarrierIdMap::const_iterator id_iter = carrier_id_map_.find(carrier_id); | |
| 215 std::string internal_id; | |
| 216 if (id_iter != carrier_id_map_.end()) | |
| 217 internal_id = id_iter->second; | |
| 218 else | |
| 219 return NULL; | |
| 220 Carriers::const_iterator iter = carriers_. find(internal_id); | |
| 221 if (iter != carriers_.end()) | |
| 222 return iter->second; | |
| 223 else | |
| 224 return NULL; | |
| 225 } | |
| 226 | |
| 227 bool MobileConfig::LoadConfigFromString(const std::string& config) { | |
| 228 int error_code = 0; | |
| 229 std::string error; | |
| 230 scoped_ptr<Value> root(base::JSONReader::ReadAndReturnError( | |
| 231 config, true, &error_code, &error)); | |
| 232 if (error_code != base::JSONReader::JSON_NO_ERROR) | |
| 233 LOG(ERROR) << error; | |
| 234 DCHECK(root.get() != NULL); | |
| 235 if (root.get() == NULL) | |
| 236 return false; | |
| 237 DCHECK(root->GetType() == Value::TYPE_DICTIONARY); | |
| 238 if (root->GetType() == Value::TYPE_DICTIONARY) { | |
| 239 root_.reset(static_cast<DictionaryValue*>(root.release())); | |
| 240 std::string result; | |
| 241 if (!root_->GetString(kVersionAttr, &result) || | |
| 242 result != kAcceptedConfigVersion) { | |
| 243 LOG(ERROR) << "Wrong mobile config version"; | |
| 244 root_.reset(NULL); | |
| 245 } | |
| 246 } else { | |
| 247 return false; | |
| 248 } | |
| 249 | |
| 250 // Other parts are optional. | |
| 251 DictionaryValue* carriers = NULL; | |
| 252 if (root_.get() && root_->GetDictionary(kCarriersAttr, &carriers)) { | |
| 253 for (DictionaryValue::key_iterator iter = carriers->begin_keys(); | |
| 254 iter != carriers->end_keys(); ++iter) { | |
| 255 DictionaryValue* carrier_dict = NULL; | |
| 256 if (carriers->GetDictionary(*iter, &carrier_dict)) { | |
| 257 const std::string& internal_id = *iter; | |
| 258 Carrier* carrier = new Carrier(carrier_dict, initial_locale_); | |
|
Dmitry Polukhin
2011/09/05 06:33:11
There is similar memory leak here.
Nikita (slow)
2011/09/05 10:13:44
Done.
| |
| 259 if (!carrier->external_ids().empty()) { | |
| 260 // Map all external IDs to a single internal one. | |
| 261 for (std::vector<std::string>::const_iterator | |
| 262 i = carrier->external_ids().begin(); | |
| 263 i != carrier->external_ids().end(); ++i) { | |
| 264 carrier_id_map_[*i] = internal_id; | |
| 265 } | |
| 266 } else { | |
| 267 // Trivial case - using same ID for external/internal one. | |
| 268 carrier_id_map_[internal_id] = internal_id; | |
| 269 } | |
| 270 carriers_[internal_id] = carrier; | |
| 271 } | |
| 272 } | |
| 273 } | |
| 274 return true; | |
| 275 } | |
| 276 | |
| 277 } // namespace chromeos | |
| OLD | NEW |