|
14 | 14 |
|
15 | 15 | #include "auth/src/desktop/auth_desktop.h" |
16 | 16 |
|
| 17 | +#include <algorithm> |
17 | 18 | #include <cassert> |
18 | 19 | #include <cstdint> |
19 | 20 | #include <cstring> |
@@ -92,6 +93,19 @@ void* CreatePlatformAuth(App* const app) { |
92 | 93 | AuthImpl* const auth = new AuthImpl(); |
93 | 94 | auth->api_key = app->options().api_key(); |
94 | 95 | auth->app_name = app->name(); |
| 96 | + |
| 97 | + // Check environment variables for emulator if set. |
| 98 | + if (std::getenv("USE_AUTH_EMULATOR") != nullptr) { |
| 99 | + auth->assigned_emulator_url.append(kEmulatorLocalHost); |
| 100 | + auth->assigned_emulator_url.append(":"); |
| 101 | + if (std::getenv("AUTH_EMULATOR_PORT") == nullptr) { |
| 102 | + auth->assigned_emulator_url.append(kEmulatorPort); |
| 103 | + } else { |
| 104 | + auth->assigned_emulator_url.append(std::getenv("AUTH_EMULATOR_PORT")); |
| 105 | + } |
| 106 | + LogInfo("Using Auth Emulator: %s", auth->assigned_emulator_url.c_str()); |
| 107 | + } |
| 108 | + |
95 | 109 | return auth; |
96 | 110 | } |
97 | 111 |
|
@@ -576,6 +590,7 @@ void Auth::UseEmulator(std::string host, uint32_t port) { |
576 | 590 | auth_impl->assigned_emulator_url.append(host); |
577 | 591 | auth_impl->assigned_emulator_url.append(":"); |
578 | 592 | auth_impl->assigned_emulator_url.append(std::to_string(port)); |
| 593 | + LogInfo("Using Auth Emulator: %s", auth_impl->assigned_emulator_url.c_str()); |
579 | 594 | } |
580 | 595 |
|
581 | 596 | void InitializeTokenRefresher(AuthData* auth_data) { |
@@ -667,6 +682,8 @@ void IdTokenRefreshThread::Initialize(AuthData* auth_data) { |
667 | 682 | thread_ = firebase::Thread( |
668 | 683 | [](IdTokenRefreshThread* refresh_thread) { |
669 | 684 | Auth* auth = refresh_thread->auth; |
| 685 | + ExponentialBackoff backoff; |
| 686 | + |
670 | 687 | while (!refresh_thread->is_shutting_down()) { |
671 | 688 | // Note: Make sure to always make future_impl.mutex the innermost |
672 | 689 | // lock, to prevent deadlocks! |
@@ -700,8 +717,19 @@ void IdTokenRefreshThread::Initialize(AuthData* auth_data) { |
700 | 717 | // is completed. |
701 | 718 | future_sem.Wait(); |
702 | 719 |
|
703 | | - // (We don't actually care about the results of the token request. |
704 | | - // The token listener will handle that.) |
| 720 | + if (future.error() != 0) { |
| 721 | + // Token refresh failed (e.g. network outage). Wait with |
| 722 | + // exponential backoff to prevent tight retry loops and avoid |
| 723 | + // overloading backend servers upon reconnect. Matches Android |
| 724 | + // DefaultTokenRefresher (30s initial, doubling up to 16m max). |
| 725 | + if (!refresh_thread->is_shutting_down()) { |
| 726 | + refresh_thread->wakeup_sem_.TimedWait(backoff.NextDelayMs()); |
| 727 | + } |
| 728 | + continue; |
| 729 | + } else { |
| 730 | + // Refresh succeeded! Reset backoff to minimum interval. |
| 731 | + backoff.Reset(); |
| 732 | + } |
705 | 733 | } else { |
706 | 734 | auth->auth_data_->future_impl.mutex().Release(); |
707 | 735 | refresh_thread->ref_count_mutex_.Release(); |
|
0 commit comments