Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium 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 "google_apis/gcm/engine/gservices_settings.h" | 5 #include "google_apis/gcm/engine/gservices_settings.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/sha1.h" | |
| 8 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
| 9 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
| 10 | 11 |
| 11 namespace { | 12 namespace { |
| 12 // The expected time in seconds between periodic checkins. | 13 // The expected time in seconds between periodic checkins. |
| 13 const char kCheckinIntervalKey[] = "checkin_interval"; | 14 const char kCheckinIntervalKey[] = "checkin_interval"; |
| 14 // The override URL to the checkin server. | 15 // The override URL to the checkin server. |
| 15 const char kCheckinURLKey[] = "checkin_url"; | 16 const char kCheckinURLKey[] = "checkin_url"; |
| 16 // The MCS machine name to connect to. | 17 // The MCS machine name to connect to. |
| 17 const char kMCSHostnameKey[] = "gcm_hostname"; | 18 const char kMCSHostnameKey[] = "gcm_hostname"; |
| 18 // The MCS port to connect to. | 19 // The MCS port to connect to. |
| 19 const char kMCSSecurePortKey[] = "gcm_secure_port"; | 20 const char kMCSSecurePortKey[] = "gcm_secure_port"; |
| 20 // The URL to get MCS registration IDs. | 21 // The URL to get MCS registration IDs. |
| 21 const char kRegistrationURLKey[] = "gcm_registration_url"; | 22 const char kRegistrationURLKey[] = "gcm_registration_url"; |
| 22 | 23 |
| 23 const int64 kDefaultCheckinInterval = 2 * 24 * 60 * 60; // seconds = 2 days. | 24 const int64 kDefaultCheckinInterval = 2 * 24 * 60 * 60; // seconds = 2 days. |
| 24 const int64 kMinimumCheckinInterval = 12 * 60 * 60; // seconds = 12 hours. | 25 const int64 kMinimumCheckinInterval = 12 * 60 * 60; // seconds = 12 hours. |
| 25 const char kDefaultCheckinURL[] = "https://android.clients.google.com/checkin"; | 26 const char kDefaultCheckinURL[] = "https://android.clients.google.com/checkin"; |
| 26 const char kDefaultMCSHostname[] = "mtalk.google.com"; | 27 const char kDefaultMCSHostname[] = "mtalk.google.com"; |
| 27 const int kDefaultMCSMainSecurePort = 5228; | 28 const int kDefaultMCSMainSecurePort = 5228; |
| 28 const int kDefaultMCSFallbackSecurePort = 443; | 29 const int kDefaultMCSFallbackSecurePort = 443; |
| 29 const char kDefaultRegistrationURL[] = | 30 const char kDefaultRegistrationURL[] = |
| 30 "https://android.clients.google.com/c2dm/register3"; | 31 "https://android.clients.google.com/c2dm/register3"; |
| 32 const char kDeleteSettingPrefix[] = "delete_"; | |
| 33 const char kDigestVersionPrefix[] = "1-"; | |
| 31 const char kMCSEnpointTemplate[] = "https://%s:%d"; | 34 const char kMCSEnpointTemplate[] = "https://%s:%d"; |
| 32 | 35 |
| 33 std::string MakeMCSEndpoint(const std::string& mcs_hostname, int port) { | 36 std::string MakeMCSEndpoint(const std::string& mcs_hostname, int port) { |
| 34 return base::StringPrintf(kMCSEnpointTemplate, mcs_hostname.c_str(), port); | 37 return base::StringPrintf(kMCSEnpointTemplate, mcs_hostname.c_str(), port); |
| 35 } | 38 } |
| 36 | 39 |
| 40 GURL DefaultMainMCSEndpoint() { | |
| 41 return GURL(MakeMCSEndpoint(kDefaultMCSHostname, kDefaultMCSMainSecurePort)); | |
| 42 } | |
| 43 | |
| 44 GURL DefaultFallbackMCSEndpoint() { | |
| 45 return GURL( | |
| 46 MakeMCSEndpoint(kDefaultMCSHostname, kDefaultMCSFallbackSecurePort)); | |
| 47 } | |
| 48 | |
| 49 bool VerifyCheckinInterval( | |
| 50 const gcm::GServicesSettings::SettingsMap& settings) { | |
| 51 gcm::GServicesSettings::SettingsMap::const_iterator iter = | |
| 52 settings.find(kCheckinIntervalKey); | |
| 53 if (iter == settings.end()) { | |
| 54 LOG(ERROR) << "Setting not found: " << kCheckinIntervalKey; | |
| 55 return false; | |
| 56 } | |
| 57 int64 checkin_interval = kMinimumCheckinInterval; | |
| 58 if (!base::StringToInt64(iter->second, &checkin_interval)) { | |
| 59 LOG(ERROR) << "Failed to parse checkin interval: " << iter->second; | |
| 60 return false; | |
| 61 } | |
| 62 if (checkin_interval == std::numeric_limits<int64>::max()) { | |
| 63 LOG(ERROR) << "Checkin interval is too big: " << checkin_interval; | |
| 64 return false; | |
| 65 } | |
| 66 if (checkin_interval < kMinimumCheckinInterval) { | |
| 67 // This is emited as an error, but is not mean to fail verification. | |
|
jianli
2014/05/14 20:13:22
nit: meant
fgorski
2014/05/14 20:44:34
Done.
| |
| 68 LOG(ERROR) << "Checkin interval: " << checkin_interval | |
| 69 << " is less than allowed minimum: " << kMinimumCheckinInterval; | |
| 70 } | |
| 71 | |
| 72 return true; | |
| 73 } | |
| 74 | |
| 75 bool VerifyMCSEndpoint(const gcm::GServicesSettings::SettingsMap& settings) { | |
| 76 gcm::GServicesSettings::SettingsMap::const_iterator iter = | |
| 77 settings.find(kMCSHostnameKey); | |
| 78 std::string mcs_hostname; | |
| 79 if (iter == settings.end()) { | |
| 80 LOG(ERROR) << "Setting not found: " << kMCSHostnameKey; | |
| 81 return false; | |
| 82 } | |
| 83 mcs_hostname = iter->second; | |
| 84 if (iter->second.empty()) { | |
| 85 LOG(ERROR) << "Empty MCS hostname provided."; | |
| 86 return false; | |
| 87 } | |
| 88 | |
| 89 int mcs_secure_port = -1; | |
| 90 iter = settings.find(kMCSSecurePortKey); | |
| 91 if (iter == settings.end()) { | |
| 92 LOG(ERROR) << "Setting not found: " << kMCSSecurePortKey; | |
| 93 return false; | |
| 94 } | |
| 95 if (!base::StringToInt(iter->second, &mcs_secure_port)) { | |
| 96 LOG(ERROR) << "Failed to parse MCS secure port: " << iter->second; | |
| 97 return false; | |
| 98 } | |
| 99 if (mcs_secure_port < 0 || 65535 < mcs_secure_port) { | |
| 100 LOG(ERROR) << "Incorrect port value: " << mcs_secure_port; | |
| 101 return false; | |
| 102 } | |
| 103 | |
| 104 GURL mcs_main_endpoint(MakeMCSEndpoint(mcs_hostname, mcs_secure_port)); | |
| 105 if (!mcs_main_endpoint.is_valid()) { | |
| 106 LOG(ERROR) << "Invalid main MCS endpoint: " | |
| 107 << mcs_main_endpoint.possibly_invalid_spec(); | |
| 108 return false; | |
| 109 } | |
| 110 GURL mcs_fallback_endpoint( | |
| 111 MakeMCSEndpoint(mcs_hostname, kDefaultMCSFallbackSecurePort)); | |
| 112 if (!mcs_fallback_endpoint.is_valid()) { | |
| 113 LOG(ERROR) << "Invalid fallback MCS endpoint: " | |
| 114 << mcs_fallback_endpoint.possibly_invalid_spec(); | |
| 115 return false; | |
| 116 } | |
| 117 | |
| 118 return true; | |
| 119 } | |
| 120 | |
| 121 bool VerifyCheckinURL(const gcm::GServicesSettings::SettingsMap& settings) { | |
| 122 gcm::GServicesSettings::SettingsMap::const_iterator iter = | |
| 123 settings.find(kCheckinURLKey); | |
| 124 if (iter == settings.end()) { | |
| 125 LOG(ERROR) << "Setting not found: " << kCheckinURLKey; | |
| 126 return false; | |
| 127 } | |
| 128 GURL checkin_url(iter->second); | |
| 129 if (!checkin_url.is_valid()) { | |
| 130 LOG(ERROR) << "Invalid checkin URL provided: " | |
| 131 << checkin_url.possibly_invalid_spec(); | |
|
jianli
2014/05/14 20:13:22
nit: print iter->second
fgorski
2014/05/14 20:44:34
Done.
| |
| 132 return false; | |
| 133 } | |
| 134 | |
| 135 return true; | |
| 136 } | |
| 137 | |
| 138 bool VerifyRegistrationURL( | |
| 139 const gcm::GServicesSettings::SettingsMap& settings) { | |
| 140 gcm::GServicesSettings::SettingsMap::const_iterator iter = | |
| 141 settings.find(kRegistrationURLKey); | |
| 142 if (iter == settings.end()) { | |
| 143 LOG(ERROR) << "Setting not found: " << kRegistrationURLKey; | |
| 144 return false; | |
| 145 } | |
| 146 GURL registration_url(iter->second); | |
| 147 if (!registration_url.is_valid()) { | |
| 148 LOG(ERROR) << "Invalid registration URL provided: " | |
| 149 << registration_url.possibly_invalid_spec(); | |
|
jianli
2014/05/14 20:13:22
ditto
fgorski
2014/05/14 20:44:34
Done.
| |
| 150 return false; | |
| 151 } | |
| 152 | |
| 153 return true; | |
| 154 } | |
| 155 | |
| 156 bool VerifySettings(const gcm::GServicesSettings::SettingsMap& settings) { | |
| 157 return VerifyCheckinInterval(settings) && VerifyMCSEndpoint(settings) && | |
| 158 VerifyCheckinURL(settings) && VerifyRegistrationURL(settings); | |
| 159 } | |
| 160 | |
| 161 bool VerifyDigest(const gcm::GServicesSettings::SettingsMap& settings, | |
| 162 const std::string& expected_digest) { | |
| 163 std::string calculated_digest = | |
| 164 gcm::GServicesSettings::CalculateDigest(settings); | |
| 165 if (calculated_digest != expected_digest) { | |
| 166 LOG(ERROR) << "Calculated digest does not match the original digest."; | |
| 167 LOG(ERROR) << "Expected G-Services settings digest: " << expected_digest; | |
| 168 LOG(ERROR) << "Calculated G-services settings digest: " | |
| 169 << calculated_digest; | |
| 170 return false; | |
| 171 } | |
| 172 | |
| 173 return true; | |
| 174 } | |
| 175 | |
| 37 } // namespace | 176 } // namespace |
| 38 | 177 |
| 39 namespace gcm { | 178 namespace gcm { |
| 40 | 179 |
| 41 // static | 180 // static |
| 42 const base::TimeDelta GServicesSettings::MinimumCheckinInterval() { | 181 const base::TimeDelta GServicesSettings::MinimumCheckinInterval() { |
| 43 return base::TimeDelta::FromSeconds(kMinimumCheckinInterval); | 182 return base::TimeDelta::FromSeconds(kMinimumCheckinInterval); |
| 44 } | 183 } |
| 45 | 184 |
| 46 // static | 185 // static |
| 47 const GURL GServicesSettings::DefaultCheckinURL() { | 186 const GURL GServicesSettings::DefaultCheckinURL() { |
| 48 return GURL(kDefaultCheckinURL); | 187 return GURL(kDefaultCheckinURL); |
| 49 } | 188 } |
| 50 | 189 |
| 51 GServicesSettings::GServicesSettings() | 190 // static |
| 52 : checkin_interval_(base::TimeDelta::FromSeconds(kDefaultCheckinInterval)), | 191 std::string GServicesSettings::CalculateDigest(const SettingsMap& settings) { |
| 53 checkin_url_(kDefaultCheckinURL), | 192 unsigned char hash[base::kSHA1Length]; |
| 54 mcs_main_endpoint_(MakeMCSEndpoint(kDefaultMCSHostname, | 193 std::string data; |
| 55 kDefaultMCSMainSecurePort)), | 194 for (SettingsMap::const_iterator iter = settings.begin(); |
| 56 mcs_fallback_endpoint_(MakeMCSEndpoint(kDefaultMCSHostname, | 195 iter != settings.end(); |
| 57 kDefaultMCSFallbackSecurePort)), | 196 ++iter) { |
| 58 registration_url_(kDefaultRegistrationURL), | 197 data += iter->first; |
| 59 weak_ptr_factory_(this) { | 198 data += '\0'; |
| 60 } | 199 data += iter->second; |
| 61 | 200 data += '\0'; |
| 62 GServicesSettings::~GServicesSettings() {} | 201 } |
| 202 base::SHA1HashBytes( | |
| 203 reinterpret_cast<const unsigned char*>(&data[0]), data.size(), hash); | |
| 204 return kDigestVersionPrefix + base::HexEncode(hash, base::kSHA1Length); | |
| 205 } | |
| 206 | |
| 207 GServicesSettings::GServicesSettings() : weak_ptr_factory_(this) { | |
| 208 settings_[kCheckinIntervalKey] = base::Int64ToString(kDefaultCheckinInterval); | |
| 209 settings_[kCheckinURLKey] = kDefaultCheckinURL; | |
| 210 settings_[kMCSHostnameKey] = kDefaultMCSHostname; | |
| 211 settings_[kMCSSecurePortKey] = base::IntToString(kDefaultMCSMainSecurePort); | |
| 212 settings_[kRegistrationURLKey] = kDefaultRegistrationURL; | |
| 213 digest_ = CalculateDigest(settings_); | |
| 214 } | |
| 215 | |
| 216 GServicesSettings::~GServicesSettings() { | |
| 217 } | |
| 63 | 218 |
| 64 bool GServicesSettings::UpdateFromCheckinResponse( | 219 bool GServicesSettings::UpdateFromCheckinResponse( |
| 65 const checkin_proto::AndroidCheckinResponse& checkin_response) { | 220 const checkin_proto::AndroidCheckinResponse& checkin_response) { |
| 66 if (!checkin_response.has_digest() || | 221 if (!checkin_response.has_settings_diff()) { |
| 67 checkin_response.digest() == digest_) { | 222 LOG(ERROR) << "Field settings_diff not set in response."; |
| 68 // There are no changes as digest is the same or no settings provided. | 223 return false; |
| 69 return false; | 224 } |
| 70 } | 225 |
| 71 | 226 if (!checkin_response.has_digest()) { |
| 72 std::map<std::string, std::string> settings; | 227 LOG(ERROR) << "Field digest not set in response."; |
| 228 return false; | |
| 229 } | |
| 230 | |
| 231 if (digest_ == checkin_response.digest()) | |
| 232 return false; | |
| 233 | |
| 234 bool settings_diff = checkin_response.settings_diff(); | |
| 235 SettingsMap new_settings; | |
| 236 // Only reuse the existing settings, if we are given a settings difference. | |
| 237 if (settings_diff) | |
| 238 new_settings = get_settings_map(); | |
| 239 | |
| 73 for (int i = 0; i < checkin_response.setting_size(); ++i) { | 240 for (int i = 0; i < checkin_response.setting_size(); ++i) { |
| 74 std::string name = checkin_response.setting(i).name(); | 241 std::string name = checkin_response.setting(i).name(); |
| 75 std::string value = checkin_response.setting(i).value(); | 242 if (name.empty()) |
| 76 settings[name] = value; | 243 return false; |
| 77 } | 244 |
| 78 | 245 if (settings_diff && name.find(kDeleteSettingPrefix) == 0) { |
| 79 // Only update the settings in store and digest, if the settings actually | 246 std::string setting_to_delete = |
| 80 // passed the verificaiton in update settings. | 247 name.substr(arraysize(kDeleteSettingPrefix)); |
| 81 if (UpdateSettings(settings)) { | 248 new_settings.erase(setting_to_delete); |
| 82 digest_ = checkin_response.digest(); | 249 } else { |
| 83 return true; | 250 new_settings[name] = checkin_response.setting(i).value(); |
| 84 } | 251 } |
| 85 | 252 } |
| 86 return false; | 253 |
| 254 if (!VerifySettings(new_settings)) | |
| 255 return false; | |
| 256 | |
| 257 std::string digest = CalculateDigest(new_settings); | |
| 258 if (digest != checkin_response.digest()) { | |
| 259 LOG(ERROR) << "G-services settings digest mismatch. " | |
| 260 << "Checkin response contains: " << checkin_response.digest() | |
| 261 << ". Calculated digest is: " << digest; | |
| 262 return false; | |
| 263 } | |
| 264 | |
| 265 settings_.swap(new_settings); | |
| 266 digest_ = digest; | |
| 267 return true; | |
| 87 } | 268 } |
| 88 | 269 |
| 89 void GServicesSettings::UpdateFromLoadResult( | 270 void GServicesSettings::UpdateFromLoadResult( |
| 90 const GCMStore::LoadResult& load_result) { | 271 const GCMStore::LoadResult& load_result) { |
| 91 if (UpdateSettings(load_result.gservices_settings)) | 272 // No need to try to update settings when load_result is empty. |
| 273 if (load_result.gservices_settings.empty()) | |
| 274 return; | |
| 275 if (VerifySettings(load_result.gservices_settings) && | |
| 276 VerifyDigest(load_result.gservices_settings, | |
| 277 load_result.gservices_digest)) { | |
| 278 settings_ = load_result.gservices_settings; | |
| 92 digest_ = load_result.gservices_digest; | 279 digest_ = load_result.gservices_digest; |
| 93 } | 280 } |
| 94 | 281 } |
| 95 std::map<std::string, std::string> GServicesSettings::GetSettingsMap() const { | 282 |
| 96 std::map<std::string, std::string> settings; | 283 base::TimeDelta GServicesSettings::GetCheckinInterval() const { |
| 97 settings[kCheckinIntervalKey] = | 284 int64 checkin_interval = kMinimumCheckinInterval; |
| 98 base::Int64ToString(checkin_interval_.InSeconds()); | 285 SettingsMap::const_iterator iter = settings_.find(kCheckinIntervalKey); |
| 99 settings[kCheckinURLKey] = checkin_url_.spec(); | 286 if (iter == settings_.end() || |
| 100 settings[kMCSHostnameKey] = mcs_main_endpoint_.host(); | 287 !base::StringToInt64(iter->second, &checkin_interval)) { |
| 101 settings[kMCSSecurePortKey] = mcs_main_endpoint_.port(); | 288 checkin_interval = kDefaultCheckinInterval; |
| 102 settings[kRegistrationURLKey] = registration_url_.spec(); | 289 } |
| 103 return settings; | 290 |
| 104 } | 291 if (checkin_interval < kMinimumCheckinInterval) |
| 105 | 292 checkin_interval = kMinimumCheckinInterval; |
| 106 bool GServicesSettings::UpdateSettings( | 293 |
| 107 const std::map<std::string, std::string>& settings) { | 294 return base::TimeDelta::FromSeconds(checkin_interval); |
| 108 int64 new_checkin_interval = kMinimumCheckinInterval; | 295 } |
| 109 std::map<std::string, std::string>::const_iterator iter = | 296 |
| 110 settings.find(kCheckinIntervalKey); | 297 GURL GServicesSettings::GetCheckinURL() const { |
| 111 if (iter == settings.end()) { | 298 SettingsMap::const_iterator iter = settings_.find(kCheckinURLKey); |
| 112 LOG(ERROR) << "Setting not found: " << kCheckinIntervalKey; | 299 if (iter == settings_.end() || iter->second.empty()) |
| 113 return false; | 300 return GURL(kDefaultCheckinURL); |
| 114 } | 301 return GURL(iter->second); |
| 115 if (!base::StringToInt64(iter->second, &new_checkin_interval)) { | 302 } |
| 116 LOG(ERROR) << "Failed to parse checkin interval: " << iter->second; | 303 |
| 117 return false; | 304 GURL GServicesSettings::GetMCSMainEndpoint() const { |
| 118 } | 305 SettingsMap::const_iterator iter = settings_.find(kMCSHostnameKey); |
| 119 if (new_checkin_interval < kMinimumCheckinInterval) { | 306 if (iter == settings_.end() || iter->second.empty()) |
| 120 LOG(ERROR) << "Checkin interval: " << new_checkin_interval | 307 return DefaultMainMCSEndpoint(); |
| 121 << " is less than allowed minimum: " << kMinimumCheckinInterval; | 308 |
| 122 new_checkin_interval = kMinimumCheckinInterval; | 309 std::string mcs_hostname = iter->second; |
| 123 } | 310 |
| 124 if (new_checkin_interval == std::numeric_limits<int64>::max()) { | 311 iter = settings_.find(kMCSSecurePortKey); |
| 125 LOG(ERROR) << "Checkin interval is too big: " << new_checkin_interval; | 312 int mcs_secure_port = kDefaultMCSMainSecurePort; |
| 126 return false; | 313 if (iter == settings_.end() || iter->second.empty() || |
| 127 } | 314 !base::StringToInt(iter->second, &mcs_secure_port)) |
| 128 | 315 return DefaultMainMCSEndpoint(); |
| 129 std::string new_mcs_hostname; | 316 |
| 130 iter = settings.find(kMCSHostnameKey); | 317 GURL mcs_endpoint(MakeMCSEndpoint(mcs_hostname, mcs_secure_port)); |
| 131 if (iter == settings.end()) { | 318 |
| 132 LOG(ERROR) << "Setting not found: " << kMCSHostnameKey; | 319 if (!mcs_endpoint.is_valid()) |
| 133 return false; | 320 return DefaultMainMCSEndpoint(); |
| 134 } | 321 |
| 135 new_mcs_hostname = iter->second; | 322 return mcs_endpoint; |
| 136 if (new_mcs_hostname.empty()) { | 323 } |
| 137 LOG(ERROR) << "Empty MCS hostname provided."; | 324 |
| 138 return false; | 325 GURL GServicesSettings::GetMCSFallbackEndpoint() const { |
| 139 } | 326 SettingsMap::const_iterator iter = settings_.find(kMCSHostnameKey); |
| 140 | 327 if (iter == settings_.end() || iter->second.empty()) |
| 141 int new_mcs_secure_port = -1; | 328 return DefaultFallbackMCSEndpoint(); |
| 142 iter = settings.find(kMCSSecurePortKey); | 329 |
| 143 if (iter == settings.end()) { | 330 GURL mcs_endpoint( |
| 144 LOG(ERROR) << "Setting not found: " << kMCSSecurePortKey; | 331 MakeMCSEndpoint(iter->second, kDefaultMCSFallbackSecurePort)); |
| 145 return false; | 332 |
| 146 } | 333 if (!mcs_endpoint.is_valid()) |
| 147 if (!base::StringToInt(iter->second, &new_mcs_secure_port)) { | 334 return DefaultFallbackMCSEndpoint(); |
| 148 LOG(ERROR) << "Failed to parse MCS secure port: " << iter->second; | 335 |
| 149 return false; | 336 return mcs_endpoint; |
| 150 } | 337 } |
| 151 if (new_mcs_secure_port < 0 || 65535 < new_mcs_secure_port) { | 338 |
| 152 LOG(ERROR) << "Incorrect port value: " << new_mcs_secure_port; | 339 GURL GServicesSettings::GetRegistrationURL() const { |
| 153 return false; | 340 SettingsMap::const_iterator iter = settings_.find(kRegistrationURLKey); |
| 154 } | 341 if (iter == settings_.end() || iter->second.empty()) |
| 155 | 342 return GURL(kDefaultRegistrationURL); |
| 156 GURL new_mcs_main_endpoint = | 343 return GURL(iter->second); |
| 157 GURL(MakeMCSEndpoint(new_mcs_hostname, new_mcs_secure_port)); | |
| 158 GURL new_mcs_fallback_endpoint = | |
| 159 GURL(MakeMCSEndpoint(new_mcs_hostname, kDefaultMCSFallbackSecurePort)); | |
| 160 if (!new_mcs_main_endpoint.is_valid() || | |
| 161 !new_mcs_fallback_endpoint.is_valid()) | |
| 162 return false; | |
| 163 | |
| 164 GURL new_checkin_url; | |
| 165 iter = settings.find(kCheckinURLKey); | |
| 166 if (iter == settings.end()) { | |
| 167 LOG(ERROR) << "Setting not found: " << kCheckinURLKey; | |
| 168 return false; | |
| 169 } | |
| 170 new_checkin_url = GURL(iter->second); | |
| 171 if (!new_checkin_url.is_valid()) { | |
| 172 LOG(ERROR) << "Invalid checkin URL provided: " | |
| 173 << new_checkin_url.possibly_invalid_spec(); | |
| 174 return false; | |
| 175 } | |
| 176 | |
| 177 GURL new_registration_url; | |
| 178 iter = settings.find(kRegistrationURLKey); | |
| 179 if (iter == settings.end()) { | |
| 180 LOG(ERROR) << "Setting not found: " << kRegistrationURLKey; | |
| 181 return false; | |
| 182 } | |
| 183 new_registration_url = GURL(iter->second); | |
| 184 if (!new_registration_url.is_valid()) { | |
| 185 LOG(ERROR) << "Invalid registration URL provided: " | |
| 186 << new_registration_url.possibly_invalid_spec(); | |
| 187 return false; | |
| 188 } | |
| 189 | |
| 190 // We only update the settings once all of them are correct. | |
| 191 checkin_interval_ = base::TimeDelta::FromSeconds(new_checkin_interval); | |
| 192 mcs_main_endpoint_ = new_mcs_main_endpoint; | |
| 193 mcs_fallback_endpoint_ = new_mcs_fallback_endpoint; | |
| 194 checkin_url_ = new_checkin_url; | |
| 195 registration_url_ = new_registration_url; | |
| 196 return true; | |
| 197 } | 344 } |
| 198 | 345 |
| 199 } // namespace gcm | 346 } // namespace gcm |
| OLD | NEW |