|
16 | 16 |
|
17 | 17 | #include <assert.h> |
18 | 18 |
|
| 19 | +#include <algorithm> |
| 20 | + |
19 | 21 | #include "app/instance_id/iid_data_generated.h" |
20 | 22 | #include "app/rest/transport_curl.h" |
21 | 23 | #include "app/rest/transport_interface.h" |
@@ -104,10 +106,35 @@ static const char kTokenResetError[] = "RST"; |
104 | 106 | // Wildcard scope used to delete all tokens and the ID in a server registration. |
105 | 107 | static const char kWildcardTokenScope[] = "*"; |
106 | 108 |
|
| 109 | +// Minimum retry time (in seconds) when a fetch token request fails. |
| 110 | +static const uint64_t kMinimumFetchTokenDelaySec = 30; |
| 111 | +// Maximum retry time (in seconds) when a fetch token request fails. |
| 112 | +static const uint64_t kMaximumFetchTokenDelaySec = |
| 113 | + 8 * firebase::internal::kMinutesPerHour * |
| 114 | + firebase::internal::kSecondsPerMinute; |
| 115 | + |
107 | 116 | std::map<App*, InstanceIdDesktopImpl*> |
108 | 117 | InstanceIdDesktopImpl::instance_id_by_app_; // NOLINT |
109 | 118 | Mutex InstanceIdDesktopImpl::instance_id_by_app_mutex_; // NOLINT |
110 | 119 |
|
| 120 | +void InstanceIdDesktopImpl::FetchServerTokenCallback::Run() { |
| 121 | + bool retry; |
| 122 | + bool fetched_token = iid_->FetchServerToken(scope_.c_str(), &retry); |
| 123 | + if (fetched_token) { |
| 124 | + iid_->ref_future()->CompleteWithResult( |
| 125 | + future_handle_, kErrorNone, "", iid_->FindCachedToken(scope_.c_str())); |
| 126 | + } else if (retry) { |
| 127 | + // Retry with an expodential backoff. |
| 128 | + retry_delay_time_ = |
| 129 | + std::min(std::max(retry_delay_time_ * 2, kMinimumFetchTokenDelaySec), |
| 130 | + kMaximumFetchTokenDelaySec); |
| 131 | + iid_->scheduler_.Schedule(this, retry_delay_time_); |
| 132 | + } else { |
| 133 | + iid_->ref_future()->Complete(future_handle_, kErrorUnknownError, |
| 134 | + "FetchToken failed"); |
| 135 | + } |
| 136 | +} |
| 137 | + |
111 | 138 | InstanceIdDesktopImpl::InstanceIdDesktopImpl(App* app) |
112 | 139 | : storage_semaphore_(0), |
113 | 140 | app_(app), |
@@ -267,22 +294,7 @@ Future<std::string> InstanceIdDesktopImpl::GetToken(const char* scope) { |
267 | 294 | ref_future()->Complete(handle, kErrorShutdown, |
268 | 295 | "Failed due to App shutdown in progress"); |
269 | 296 | } else { |
270 | | - std::string scope_str(scope); |
271 | | - auto callback = NewCallback( |
272 | | - [](InstanceIdDesktopImpl* _this, std::string _scope_str, |
273 | | - SafeFutureHandle<std::string> _handle) { |
274 | | - if (_this->FetchServerToken(_scope_str.c_str())) { |
275 | | - _this->ref_future()->CompleteWithResult( |
276 | | - _handle, kErrorNone, "", |
277 | | - _this->FindCachedToken(_scope_str.c_str())); |
278 | | - } else { |
279 | | - _this->ref_future()->Complete(_handle, kErrorUnknownError, |
280 | | - "FetchToken failed"); |
281 | | - } |
282 | | - }, |
283 | | - this, scope_str, handle); |
284 | | - |
285 | | - scheduler_.Schedule(callback); |
| 297 | + scheduler_.Schedule(new FetchServerTokenCallback(this, scope, handle)); |
286 | 298 | } |
287 | 299 |
|
288 | 300 | return MakeFuture(ref_future(), handle); |
@@ -666,7 +678,8 @@ void InstanceIdDesktopImpl::ServerTokenOperation( |
666 | 678 | network_operation_complete_.Wait(); |
667 | 679 | } |
668 | 680 |
|
669 | | -bool InstanceIdDesktopImpl::FetchServerToken(const char* scope) { |
| 681 | +bool InstanceIdDesktopImpl::FetchServerToken(const char* scope, bool* retry) { |
| 682 | + *retry = false; |
670 | 683 | if (terminating_ || !InitialOrRefreshCheckin()) return false; |
671 | 684 |
|
672 | 685 | // If we already have a token, don't refresh. |
@@ -707,9 +720,9 @@ bool InstanceIdDesktopImpl::FetchServerToken(const char* scope) { |
707 | 720 | std::string error_component = |
708 | 721 | error.substr(component_start, component_end - component_start); |
709 | 722 | if (error_component == kPhoneRegistrationError) { |
710 | | - // TODO(smiles): Retry with expodential backoff. |
711 | 723 | network_operation_.reset(nullptr); |
712 | | - return true; |
| 724 | + *retry = true; |
| 725 | + return false; |
713 | 726 | } else if (error_component == kTokenResetError) { |
714 | 727 | // Server requests that the token is reset. |
715 | 728 | DeleteServerToken(nullptr, true); |
|
0 commit comments