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 |