Index: components/gcm_driver/gcm_client_impl.cc |
diff --git a/components/gcm_driver/gcm_client_impl.cc b/components/gcm_driver/gcm_client_impl.cc |
index 6b1c980f00ff8441153b58afde58881516509f0c..1c9f64fbe447498e27d1ca4a8c47b77a210adb1b 100644 |
--- a/components/gcm_driver/gcm_client_impl.cc |
+++ b/components/gcm_driver/gcm_client_impl.cc |
@@ -9,7 +9,7 @@ |
#include "base/logging.h" |
#include "base/memory/scoped_ptr.h" |
#include "base/message_loop/message_loop.h" |
-#include "base/metrics/histogram.h" |
+#include "base/metrics/histogram_macros.h" |
#include "base/sequenced_task_runner.h" |
#include "base/stl_util.h" |
#include "base/strings/string_number_conversions.h" |
@@ -58,6 +58,15 @@ enum OutgoingMessageTTLCategory { |
TTL_CATEGORY_COUNT |
}; |
+enum ResetStoreError { |
+ DESTROYING_STORE_FAILED, |
+ INFINITE_STORE_RESET, |
+ // NOTE: always keep this entry at the end. Add new value only immediately |
+ // above this line. Make sure to update the corresponding histogram enum |
+ // accordingly. |
+ RESET_STORE_ERROR_COUNT |
+}; |
+ |
const int kMaxRegistrationRetries = 5; |
const char kMessageTypeDataMessage[] = "gcm"; |
const char kMessageTypeDeletedMessagesKey[] = "deleted_messages"; |
@@ -179,6 +188,10 @@ void RecordOutgoingMessageToUMA( |
TTL_CATEGORY_COUNT); |
} |
+void RecordResetStoreErrorToUMA(ResetStoreError error) { |
+ UMA_HISTOGRAM_ENUMERATION("GCM.ResetStore", error, RESET_STORE_ERROR_COUNT); |
+} |
+ |
} // namespace |
GCMInternalsBuilder::GCMInternalsBuilder() {} |
@@ -245,6 +258,7 @@ GCMClientImpl::GCMClientImpl(scoped_ptr<GCMInternalsBuilder> internals_builder) |
delegate_(NULL), |
start_mode_(DELAYED_START), |
clock_(internals_builder_->BuildClock()), |
+ gcm_store_reset_(false), |
url_request_context_getter_(NULL), |
pending_registration_requests_deleter_(&pending_registration_requests_), |
pending_unregistration_requests_deleter_( |
@@ -316,9 +330,10 @@ void GCMClientImpl::OnLoadCompleted(scoped_ptr<GCMStore::LoadResult> result) { |
DCHECK_EQ(LOADING, state_); |
if (!result->success) { |
- ResetState(); |
+ ResetStore(); |
return; |
} |
+ gcm_store_reset_ = false; |
registrations_ = result->registrations; |
device_checkin_info_.android_id = result->device_android_id; |
@@ -426,9 +441,21 @@ void GCMClientImpl::StartMCSLogin() { |
device_checkin_info_.secret); |
} |
-void GCMClientImpl::ResetState() { |
- state_ = UNINITIALIZED; |
- // TODO(fgorski): reset all of the necessart objects and start over. |
+void GCMClientImpl::ResetStore() { |
+ DCHECK_EQ(LOADING, state_); |
+ |
+ // If already being reset, don't do it again. We want to prevent from |
+ // resetting and loading from the store again and again. |
+ if (gcm_store_reset_) { |
+ RecordResetStoreErrorToUMA(INFINITE_STORE_RESET); |
+ state_ = UNINITIALIZED; |
+ return; |
+ } |
+ gcm_store_reset_ = true; |
+ |
+ // Destroy the GCM store to start over. |
+ gcm_store_->Destroy(base::Bind(&GCMClientImpl::ResetStoreCallback, |
+ weak_ptr_factory_.GetWeakPtr())); |
} |
void GCMClientImpl::SetAccountTokens( |
@@ -627,6 +654,18 @@ void GCMClientImpl::IgnoreWriteResultCallback(bool success) { |
// sync_intergration_tests are not broken. |
} |
+void GCMClientImpl::ResetStoreCallback(bool success) { |
+ if (!success) { |
+ LOG(ERROR) << "Failed to reset GCM store"; |
+ RecordResetStoreErrorToUMA(DESTROYING_STORE_FAILED); |
+ state_ = UNINITIALIZED; |
+ return; |
+ } |
+ |
+ state_ = INITIALIZED; |
+ Start(start_mode_); |
+} |
+ |
void GCMClientImpl::Stop() { |
// TODO(fgorski): Perhaps we should make a distinction between a Stop and a |
// Shutdown. |