1414
1515#include " app_check/src/desktop/app_check_desktop.h"
1616
17+ #include < ctime>
18+ #include < string>
19+
1720#include " app_check/src/common/common.h"
1821
1922namespace firebase {
@@ -22,13 +25,16 @@ namespace internal {
2225
2326static AppCheckProviderFactory* g_provider_factory = nullptr ;
2427
25- AppCheckInternal::AppCheckInternal (App* app) : app_(app) {
28+ AppCheckInternal::AppCheckInternal (App* app)
29+ : app_(app), cached_token_(), cached_provider_() {
2630 future_manager ().AllocFutureApi (this , kAppCheckFnCount );
2731}
2832
2933AppCheckInternal::~AppCheckInternal () {
3034 future_manager ().ReleaseFutureApi (this );
3135 app_ = nullptr ;
36+ // Clear the cached token by setting the expiration
37+ cached_token_.expire_time_millis = 0 ;
3238}
3339
3440::firebase::App* AppCheckInternal::app () const { return app_; }
@@ -37,6 +43,29 @@ ReferenceCountedFutureImpl* AppCheckInternal::future() {
3743 return future_manager ().GetFutureApi (this );
3844}
3945
46+ bool AppCheckInternal::HasValidCacheToken () const {
47+ // Get the current time, in milliseconds
48+ int64_t current_time = std::time (nullptr ) * 1000 ;
49+ // TODO(amaurice): Add some additional time to the check
50+ return cached_token_.expire_time_millis > current_time;
51+ }
52+
53+ void AppCheckInternal::UpdateCachedToken (AppCheckToken token) {
54+ cached_token_ = token;
55+ // Call the token listeners
56+ for (AppCheckListener* listener : token_listeners_) {
57+ listener->OnAppCheckTokenChanged (token);
58+ }
59+ }
60+
61+ AppCheckProvider* AppCheckInternal::GetProvider () {
62+ if (!cached_provider_ && g_provider_factory && app_) {
63+ cached_provider_ = g_provider_factory->CreateProvider (app_);
64+ }
65+ return cached_provider_;
66+ }
67+
68+ // static
4069void AppCheckInternal::SetAppCheckProviderFactory (
4170 AppCheckProviderFactory* factory) {
4271 g_provider_factory = factory;
@@ -47,8 +76,30 @@ void AppCheckInternal::SetTokenAutoRefreshEnabled(
4776
4877Future<AppCheckToken> AppCheckInternal::GetAppCheckToken (bool force_refresh) {
4978 auto handle = future ()->SafeAlloc <AppCheckToken>(kAppCheckFnGetAppCheckToken );
50- AppCheckToken token;
51- future ()->CompleteWithResult (handle, 0 , token);
79+ if (!force_refresh && HasValidCacheToken ()) {
80+ // If the cached token is valid, and not told to refresh, return the cache
81+ future ()->CompleteWithResult (handle, 0 , cached_token_);
82+ } else {
83+ // Get a new token, and pass the result into the future.
84+ AppCheckProvider* provider = GetProvider ();
85+ if (provider != nullptr ) {
86+ auto token_callback{
87+ [this , handle](firebase::app_check::AppCheckToken token,
88+ int error_code, const std::string& error_message) {
89+ if (error_code == firebase::app_check::kAppCheckErrorNone ) {
90+ UpdateCachedToken (token);
91+ future ()->CompleteWithResult (handle, 0 , token);
92+ } else {
93+ future ()->Complete (handle, error_code, error_message.c_str ());
94+ }
95+ }};
96+ provider->GetToken (token_callback);
97+ } else {
98+ future ()->Complete (
99+ handle, firebase::app_check::kAppCheckErrorInvalidConfiguration ,
100+ " No AppCheckProvider installed." );
101+ }
102+ }
52103 return MakeFuture (future (), handle);
53104}
54105
@@ -57,9 +108,23 @@ Future<AppCheckToken> AppCheckInternal::GetAppCheckTokenLastResult() {
57108 future ()->LastResult (kAppCheckFnGetAppCheckToken ));
58109}
59110
60- void AppCheckInternal::AddAppCheckListener (AppCheckListener* listener) {}
111+ void AppCheckInternal::AddAppCheckListener (AppCheckListener* listener) {
112+ if (listener) {
113+ token_listeners_.push_back (listener);
61114
62- void AppCheckInternal::RemoveAppCheckListener (AppCheckListener* listener) {}
115+ // Following the Android pattern, if there is a cached token, call the
116+ // listener. Note that the iOS implementation does not do this.
117+ if (HasValidCacheToken ()) {
118+ listener->OnAppCheckTokenChanged (cached_token_);
119+ }
120+ }
121+ }
122+
123+ void AppCheckInternal::RemoveAppCheckListener (AppCheckListener* listener) {
124+ if (listener) {
125+ token_listeners_.remove (listener);
126+ }
127+ }
63128
64129} // namespace internal
65130} // namespace app_check
0 commit comments