Index: components/gcm_driver/gcm_driver.cc |
diff --git a/components/gcm_driver/gcm_driver.cc b/components/gcm_driver/gcm_driver.cc |
index 2e2d4857b03e7d78361f99f60170371cb053b412..db0362408a9a3587aaa769987ee42eb80797715a 100644 |
--- a/components/gcm_driver/gcm_driver.cc |
+++ b/components/gcm_driver/gcm_driver.cc |
@@ -24,7 +24,7 @@ bool GCMDriver::IsAllowedForAllUsers() { |
return group_name == kGCMFieldTrialEnabledGroupName; |
} |
-GCMDriver::GCMDriver() { |
+GCMDriver::GCMDriver() : weak_ptr_factory_(this) { |
} |
GCMDriver::~GCMDriver() { |
@@ -43,8 +43,8 @@ void GCMDriver::Register(const std::string& app_id, |
return; |
} |
- // If previous un/register operation is still in progress, bail out. |
- if (IsAsyncOperationPending(app_id)) { |
+ // If previous register operation is still in progress, bail out. |
+ if (register_callbacks_.find(app_id) != register_callbacks_.end()) { |
callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING); |
return; |
} |
@@ -55,6 +55,28 @@ void GCMDriver::Register(const std::string& app_id, |
register_callbacks_[app_id] = callback; |
+ // If previous unregister operation is still in progress, wait until it |
+ // finishes. We don't want to throw ASYNC_OPERATION_PENDING when the user |
+ // uninstalls an app (ungistering) and then reinstalls the app again |
+ // (registering). |
+ std::map<std::string, UnregisterCallback>::iterator unregister_iter = |
+ unregister_callbacks_.find(app_id); |
+ if (unregister_iter != unregister_callbacks_.end()) { |
+ // Replace the original unregister callback with an intermediate callback |
+ // that will invoke the original unregister callback and trigger the pending |
+ // registration after the unregistration finishes. |
+ // Note that some parameters to RegisterAfterUnregister are specified here |
+ // when the callback is created (base::Bind supports the partial binding |
+ // of parameters). |
+ unregister_iter->second = base::Bind( |
+ &GCMDriver::RegisterAfterUnregister, |
+ weak_ptr_factory_.GetWeakPtr(), |
+ app_id, |
+ normalized_sender_ids, |
+ unregister_iter->second); |
+ return; |
+ } |
+ |
RegisterImpl(app_id, normalized_sender_ids); |
} |
@@ -70,7 +92,8 @@ void GCMDriver::Unregister(const std::string& app_id, |
} |
// If previous un/register operation is still in progress, bail out. |
- if (IsAsyncOperationPending(app_id)) { |
+ if (register_callbacks_.find(app_id) != register_callbacks_.end() || |
+ unregister_callbacks_.find(app_id) != unregister_callbacks_.end()) { |
callback.Run(GCMClient::ASYNC_OPERATION_PENDING); |
return; |
} |
@@ -198,9 +221,17 @@ void GCMDriver::ClearCallbacks() { |
send_callbacks_.clear(); |
} |
-bool GCMDriver::IsAsyncOperationPending(const std::string& app_id) const { |
- return register_callbacks_.find(app_id) != register_callbacks_.end() || |
- unregister_callbacks_.find(app_id) != unregister_callbacks_.end(); |
+void GCMDriver::RegisterAfterUnregister( |
+ const std::string& app_id, |
+ const std::vector<std::string>& normalized_sender_ids, |
+ const UnregisterCallback& unregister_callback, |
+ GCMClient::Result result) { |
+ // Invoke the original unregister callback. |
+ unregister_callback.Run(result); |
+ |
+ // Trigger the pending registration. |
+ DCHECK(register_callbacks_.find(app_id) != register_callbacks_.end()); |
+ RegisterImpl(app_id, normalized_sender_ids); |
} |
} // namespace gcm |