Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(304)

Side by Side Diff: components/gcm_driver/gcm_client_impl.cc

Issue 910093003: Reset the GCM store to recover from it when it is busted (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address more feedback Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « components/gcm_driver/gcm_client_impl.h ('k') | components/gcm_driver/gcm_client_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698