|
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