| 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 "components/gcm_driver/gcm_client_impl.h" | 5 #include "components/gcm_driver/gcm_client_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| 11 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
| 12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram_macros.h" |
| 13 #include "base/sequenced_task_runner.h" | 13 #include "base/sequenced_task_runner.h" |
| 14 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
| 15 #include "base/strings/string_number_conversions.h" | 15 #include "base/strings/string_number_conversions.h" |
| 16 #include "base/strings/stringprintf.h" | 16 #include "base/strings/stringprintf.h" |
| 17 #include "base/time/default_clock.h" | 17 #include "base/time/default_clock.h" |
| 18 #include "base/timer/timer.h" | 18 #include "base/timer/timer.h" |
| 19 #include "components/gcm_driver/gcm_account_mapper.h" | 19 #include "components/gcm_driver/gcm_account_mapper.h" |
| 20 #include "components/gcm_driver/gcm_backoff_policy.h" | 20 #include "components/gcm_driver/gcm_backoff_policy.h" |
| 21 #include "google_apis/gcm/base/encryptor.h" | 21 #include "google_apis/gcm/base/encryptor.h" |
| 22 #include "google_apis/gcm/base/mcs_message.h" | 22 #include "google_apis/gcm/base/mcs_message.h" |
| (...skipping 28 matching lines...) Expand all Loading... |
| 51 TTL_LESS_THAN_OR_EQUAL_TO_ONE_DAY, | 51 TTL_LESS_THAN_OR_EQUAL_TO_ONE_DAY, |
| 52 TTL_LESS_THAN_OR_EQUAL_TO_ONE_WEEK, | 52 TTL_LESS_THAN_OR_EQUAL_TO_ONE_WEEK, |
| 53 TTL_MORE_THAN_ONE_WEEK, | 53 TTL_MORE_THAN_ONE_WEEK, |
| 54 TTL_MAXIMUM, | 54 TTL_MAXIMUM, |
| 55 // NOTE: always keep this entry at the end. Add new TTL category only | 55 // NOTE: always keep this entry at the end. Add new TTL category only |
| 56 // immediately above this line. Make sure to update the corresponding | 56 // immediately above this line. Make sure to update the corresponding |
| 57 // histogram enum accordingly. | 57 // histogram enum accordingly. |
| 58 TTL_CATEGORY_COUNT | 58 TTL_CATEGORY_COUNT |
| 59 }; | 59 }; |
| 60 | 60 |
| 61 enum ResetStoreError { |
| 62 DESTROYING_STORE_FAILED, |
| 63 INFINITE_STORE_RESET, |
| 64 // NOTE: always keep this entry at the end. Add new value only immediately |
| 65 // above this line. Make sure to update the corresponding histogram enum |
| 66 // accordingly. |
| 67 RESET_STORE_ERROR_COUNT |
| 68 }; |
| 69 |
| 61 const int kMaxRegistrationRetries = 5; | 70 const int kMaxRegistrationRetries = 5; |
| 62 const char kMessageTypeDataMessage[] = "gcm"; | 71 const char kMessageTypeDataMessage[] = "gcm"; |
| 63 const char kMessageTypeDeletedMessagesKey[] = "deleted_messages"; | 72 const char kMessageTypeDeletedMessagesKey[] = "deleted_messages"; |
| 64 const char kMessageTypeKey[] = "message_type"; | 73 const char kMessageTypeKey[] = "message_type"; |
| 65 const char kMessageTypeSendErrorKey[] = "send_error"; | 74 const char kMessageTypeSendErrorKey[] = "send_error"; |
| 66 const char kSendErrorMessageIdKey[] = "google.message_id"; | 75 const char kSendErrorMessageIdKey[] = "google.message_id"; |
| 67 const char kSendMessageFromValue[] = "gcm@chrome.com"; | 76 const char kSendMessageFromValue[] = "gcm@chrome.com"; |
| 68 const int64 kDefaultUserSerialNumber = 0LL; | 77 const int64 kDefaultUserSerialNumber = 0LL; |
| 69 | 78 |
| 70 GCMClient::Result ToGCMClientResult(MCSClient::MessageSendStatus status) { | 79 GCMClient::Result ToGCMClientResult(MCSClient::MessageSendStatus status) { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 else if (message.time_to_live <= 24 * 60 * 60) | 181 else if (message.time_to_live <= 24 * 60 * 60) |
| 173 ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_DAY; | 182 ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_DAY; |
| 174 else | 183 else |
| 175 ttl_category = TTL_MAXIMUM; | 184 ttl_category = TTL_MAXIMUM; |
| 176 | 185 |
| 177 UMA_HISTOGRAM_ENUMERATION("GCM.OutgoingMessageTTL", | 186 UMA_HISTOGRAM_ENUMERATION("GCM.OutgoingMessageTTL", |
| 178 ttl_category, | 187 ttl_category, |
| 179 TTL_CATEGORY_COUNT); | 188 TTL_CATEGORY_COUNT); |
| 180 } | 189 } |
| 181 | 190 |
| 191 void RecordResetStoreErrorToUMA(ResetStoreError error) { |
| 192 UMA_HISTOGRAM_ENUMERATION("GCM.ResetStore", error, RESET_STORE_ERROR_COUNT); |
| 193 } |
| 194 |
| 182 } // namespace | 195 } // namespace |
| 183 | 196 |
| 184 GCMInternalsBuilder::GCMInternalsBuilder() {} | 197 GCMInternalsBuilder::GCMInternalsBuilder() {} |
| 185 GCMInternalsBuilder::~GCMInternalsBuilder() {} | 198 GCMInternalsBuilder::~GCMInternalsBuilder() {} |
| 186 | 199 |
| 187 scoped_ptr<base::Clock> GCMInternalsBuilder::BuildClock() { | 200 scoped_ptr<base::Clock> GCMInternalsBuilder::BuildClock() { |
| 188 return make_scoped_ptr<base::Clock>(new base::DefaultClock()); | 201 return make_scoped_ptr<base::Clock>(new base::DefaultClock()); |
| 189 } | 202 } |
| 190 | 203 |
| 191 scoped_ptr<MCSClient> GCMInternalsBuilder::BuildMCSClient( | 204 scoped_ptr<MCSClient> GCMInternalsBuilder::BuildMCSClient( |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 account_tokens.clear(); | 251 account_tokens.clear(); |
| 239 last_checkin_accounts.clear(); | 252 last_checkin_accounts.clear(); |
| 240 } | 253 } |
| 241 | 254 |
| 242 GCMClientImpl::GCMClientImpl(scoped_ptr<GCMInternalsBuilder> internals_builder) | 255 GCMClientImpl::GCMClientImpl(scoped_ptr<GCMInternalsBuilder> internals_builder) |
| 243 : internals_builder_(internals_builder.Pass()), | 256 : internals_builder_(internals_builder.Pass()), |
| 244 state_(UNINITIALIZED), | 257 state_(UNINITIALIZED), |
| 245 delegate_(NULL), | 258 delegate_(NULL), |
| 246 start_mode_(DELAYED_START), | 259 start_mode_(DELAYED_START), |
| 247 clock_(internals_builder_->BuildClock()), | 260 clock_(internals_builder_->BuildClock()), |
| 261 gcm_store_reset_(false), |
| 248 url_request_context_getter_(NULL), | 262 url_request_context_getter_(NULL), |
| 249 pending_registration_requests_deleter_(&pending_registration_requests_), | 263 pending_registration_requests_deleter_(&pending_registration_requests_), |
| 250 pending_unregistration_requests_deleter_( | 264 pending_unregistration_requests_deleter_( |
| 251 &pending_unregistration_requests_), | 265 &pending_unregistration_requests_), |
| 252 periodic_checkin_ptr_factory_(this), | 266 periodic_checkin_ptr_factory_(this), |
| 253 weak_ptr_factory_(this) { | 267 weak_ptr_factory_(this) { |
| 254 } | 268 } |
| 255 | 269 |
| 256 GCMClientImpl::~GCMClientImpl() { | 270 GCMClientImpl::~GCMClientImpl() { |
| 257 } | 271 } |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 // Once the loading is completed, the check-in will be initiated. | 323 // Once the loading is completed, the check-in will be initiated. |
| 310 gcm_store_->Load(base::Bind(&GCMClientImpl::OnLoadCompleted, | 324 gcm_store_->Load(base::Bind(&GCMClientImpl::OnLoadCompleted, |
| 311 weak_ptr_factory_.GetWeakPtr())); | 325 weak_ptr_factory_.GetWeakPtr())); |
| 312 state_ = LOADING; | 326 state_ = LOADING; |
| 313 } | 327 } |
| 314 | 328 |
| 315 void GCMClientImpl::OnLoadCompleted(scoped_ptr<GCMStore::LoadResult> result) { | 329 void GCMClientImpl::OnLoadCompleted(scoped_ptr<GCMStore::LoadResult> result) { |
| 316 DCHECK_EQ(LOADING, state_); | 330 DCHECK_EQ(LOADING, state_); |
| 317 | 331 |
| 318 if (!result->success) { | 332 if (!result->success) { |
| 319 ResetState(); | 333 ResetStore(); |
| 320 return; | 334 return; |
| 321 } | 335 } |
| 336 gcm_store_reset_ = false; |
| 322 | 337 |
| 323 registrations_ = result->registrations; | 338 registrations_ = result->registrations; |
| 324 device_checkin_info_.android_id = result->device_android_id; | 339 device_checkin_info_.android_id = result->device_android_id; |
| 325 device_checkin_info_.secret = result->device_security_token; | 340 device_checkin_info_.secret = result->device_security_token; |
| 326 device_checkin_info_.last_checkin_accounts = result->last_checkin_accounts; | 341 device_checkin_info_.last_checkin_accounts = result->last_checkin_accounts; |
| 327 // A case where there were previously no accounts reported with checkin is | 342 // A case where there were previously no accounts reported with checkin is |
| 328 // considered to be the same as when the list of accounts is empty. It enables | 343 // considered to be the same as when the list of accounts is empty. It enables |
| 329 // scheduling a periodic checkin for devices with no signed in users | 344 // scheduling a periodic checkin for devices with no signed in users |
| 330 // immediately after restart, while keeping |accounts_set == false| delays the | 345 // immediately after restart, while keeping |accounts_set == false| delays the |
| 331 // checkin until the list of accounts is set explicitly. | 346 // checkin until the list of accounts is set explicitly. |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 419 delegate_->OnGCMReady(account_mappings, last_token_fetch_time); | 434 delegate_->OnGCMReady(account_mappings, last_token_fetch_time); |
| 420 } | 435 } |
| 421 | 436 |
| 422 void GCMClientImpl::StartMCSLogin() { | 437 void GCMClientImpl::StartMCSLogin() { |
| 423 DCHECK_EQ(READY, state_); | 438 DCHECK_EQ(READY, state_); |
| 424 DCHECK(device_checkin_info_.IsValid()); | 439 DCHECK(device_checkin_info_.IsValid()); |
| 425 mcs_client_->Login(device_checkin_info_.android_id, | 440 mcs_client_->Login(device_checkin_info_.android_id, |
| 426 device_checkin_info_.secret); | 441 device_checkin_info_.secret); |
| 427 } | 442 } |
| 428 | 443 |
| 429 void GCMClientImpl::ResetState() { | 444 void GCMClientImpl::ResetStore() { |
| 430 state_ = UNINITIALIZED; | 445 DCHECK_EQ(LOADING, state_); |
| 431 // TODO(fgorski): reset all of the necessart objects and start over. | 446 |
| 447 // If already being reset, don't do it again. We want to prevent from |
| 448 // resetting and loading from the store again and again. |
| 449 if (gcm_store_reset_) { |
| 450 RecordResetStoreErrorToUMA(INFINITE_STORE_RESET); |
| 451 state_ = UNINITIALIZED; |
| 452 return; |
| 453 } |
| 454 gcm_store_reset_ = true; |
| 455 |
| 456 // Destroy the GCM store to start over. |
| 457 gcm_store_->Destroy(base::Bind(&GCMClientImpl::ResetStoreCallback, |
| 458 weak_ptr_factory_.GetWeakPtr())); |
| 432 } | 459 } |
| 433 | 460 |
| 434 void GCMClientImpl::SetAccountTokens( | 461 void GCMClientImpl::SetAccountTokens( |
| 435 const std::vector<AccountTokenInfo>& account_tokens) { | 462 const std::vector<AccountTokenInfo>& account_tokens) { |
| 436 device_checkin_info_.account_tokens.clear(); | 463 device_checkin_info_.account_tokens.clear(); |
| 437 for (std::vector<AccountTokenInfo>::const_iterator iter = | 464 for (std::vector<AccountTokenInfo>::const_iterator iter = |
| 438 account_tokens.begin(); | 465 account_tokens.begin(); |
| 439 iter != account_tokens.end(); | 466 iter != account_tokens.end(); |
| 440 ++iter) { | 467 ++iter) { |
| 441 device_checkin_info_.account_tokens[iter->email] = iter->access_token; | 468 device_checkin_info_.account_tokens[iter->email] = iter->access_token; |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 620 | 647 |
| 621 void GCMClientImpl::DefaultStoreCallback(bool success) { | 648 void GCMClientImpl::DefaultStoreCallback(bool success) { |
| 622 DCHECK(success); | 649 DCHECK(success); |
| 623 } | 650 } |
| 624 | 651 |
| 625 void GCMClientImpl::IgnoreWriteResultCallback(bool success) { | 652 void GCMClientImpl::IgnoreWriteResultCallback(bool success) { |
| 626 // TODO(fgorski): Ignoring the write result for now to make sure | 653 // TODO(fgorski): Ignoring the write result for now to make sure |
| 627 // sync_intergration_tests are not broken. | 654 // sync_intergration_tests are not broken. |
| 628 } | 655 } |
| 629 | 656 |
| 657 void GCMClientImpl::ResetStoreCallback(bool success) { |
| 658 if (!success) { |
| 659 LOG(ERROR) << "Failed to reset GCM store"; |
| 660 RecordResetStoreErrorToUMA(DESTROYING_STORE_FAILED); |
| 661 state_ = UNINITIALIZED; |
| 662 return; |
| 663 } |
| 664 |
| 665 state_ = INITIALIZED; |
| 666 Start(start_mode_); |
| 667 } |
| 668 |
| 630 void GCMClientImpl::Stop() { | 669 void GCMClientImpl::Stop() { |
| 631 // TODO(fgorski): Perhaps we should make a distinction between a Stop and a | 670 // TODO(fgorski): Perhaps we should make a distinction between a Stop and a |
| 632 // Shutdown. | 671 // Shutdown. |
| 633 DVLOG(1) << "Stopping the GCM Client"; | 672 DVLOG(1) << "Stopping the GCM Client"; |
| 634 weak_ptr_factory_.InvalidateWeakPtrs(); | 673 weak_ptr_factory_.InvalidateWeakPtrs(); |
| 635 periodic_checkin_ptr_factory_.InvalidateWeakPtrs(); | 674 periodic_checkin_ptr_factory_.InvalidateWeakPtrs(); |
| 636 device_checkin_info_.Reset(); | 675 device_checkin_info_.Reset(); |
| 637 connection_factory_.reset(); | 676 connection_factory_.reset(); |
| 638 delegate_->OnDisconnected(); | 677 delegate_->OnDisconnected(); |
| 639 mcs_client_.reset(); | 678 mcs_client_.reset(); |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1020 bool GCMClientImpl::HasStandaloneRegisteredApp() const { | 1059 bool GCMClientImpl::HasStandaloneRegisteredApp() const { |
| 1021 if (registrations_.empty()) | 1060 if (registrations_.empty()) |
| 1022 return false; | 1061 return false; |
| 1023 // Note that account mapper is not counted as a standalone app since it is | 1062 // Note that account mapper is not counted as a standalone app since it is |
| 1024 // automatically started when other app uses GCM. | 1063 // automatically started when other app uses GCM. |
| 1025 return registrations_.size() > 1 || | 1064 return registrations_.size() > 1 || |
| 1026 !registrations_.count(kGCMAccountMapperAppId); | 1065 !registrations_.count(kGCMAccountMapperAppId); |
| 1027 } | 1066 } |
| 1028 | 1067 |
| 1029 } // namespace gcm | 1068 } // namespace gcm |
| OLD | NEW |