Index: blimp/client/core/session/identity_source.cc |
diff --git a/blimp/client/core/session/identity_source.cc b/blimp/client/core/session/identity_source.cc |
index 48b96f4154863c698a969c928957f3fbc16b9537..fba87f01d0bff9e6d393eb59a35483143af85be8 100644 |
--- a/blimp/client/core/session/identity_source.cc |
+++ b/blimp/client/core/session/identity_source.cc |
@@ -4,7 +4,9 @@ |
#include "blimp/client/core/session/identity_source.h" |
+#include "base/command_line.h" |
#include "base/memory/ptr_util.h" |
+#include "blimp/client/core/blimp_client_switches.h" |
namespace blimp { |
namespace client { |
@@ -13,6 +15,9 @@ namespace { |
// OAuth2 token scope. |
const char kOAuth2TokenScope[] = |
"https://www.googleapis.com/auth/userinfo.email"; |
+ |
+// Max retry times when OAuth2 token request is canceled. |
+const int kTokenRequestCancelMaxRetry = 3; |
} // namespace |
IdentitySource::IdentitySource(BlimpClientContextDelegate* delegate, |
@@ -20,6 +25,7 @@ IdentitySource::IdentitySource(BlimpClientContextDelegate* delegate, |
: OAuth2TokenService::Consumer("blimp_client"), |
token_callback_(callback), |
is_fetching_token_(false), |
+ retry_times_(0), |
delegate_(delegate) { |
DCHECK(delegate_); |
@@ -39,9 +45,16 @@ void IdentitySource::Connect() { |
return; |
} |
- const std::string& account_id = identity_provider_->GetActiveAccountId(); |
+ // Pass empty token to assignment source if we have command line switches. |
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kEngineIP)) { |
+ if (token_callback_) { |
+ token_callback_.Run(std::string()); |
+ } |
+ return; |
+ } |
- // User must sign in first. |
+ // User must sign in first to get an OAuth2 token. |
+ const std::string& account_id = identity_provider_->GetActiveAccountId(); |
if (account_id.empty()) { |
delegate_->OnAuthenticationError( |
BlimpClientContextDelegate::AuthError::NOT_SIGNED_IN); |
@@ -53,12 +66,25 @@ void IdentitySource::Connect() { |
FetchAuthToken(); |
} |
+// Add sign in state observer. |
+void IdentitySource::AddObserver(IdentityProvider::Observer* observer) { |
+ DCHECK(identity_provider_); |
+ identity_provider_->AddObserver(observer); |
+} |
+ |
+// Remove sign in state observer. |
+void IdentitySource::RemoveObserver(IdentityProvider::Observer* observer) { |
+ DCHECK(identity_provider_); |
+ identity_provider_->RemoveObserver(observer); |
+} |
+ |
void IdentitySource::OnGetTokenSuccess( |
const OAuth2TokenService::Request* request, |
const std::string& access_token, |
const base::Time& expiration_time) { |
token_request_.reset(); |
is_fetching_token_ = false; |
+ retry_times_ = 0; |
if (token_callback_) { |
token_callback_.Run(access_token); |
@@ -70,8 +96,26 @@ void IdentitySource::OnGetTokenFailure( |
const OAuth2TokenService::Request* request, |
const GoogleServiceAuthError& error) { |
token_request_.reset(); |
- is_fetching_token_ = false; |
+ // Retry the request. |
+ // The embedder can invalidate the refresh token at any time, this happens |
+ // during application start up or when user switches account. |
+ // OnGetTokenFailure will be called and the error code is REQUEST_CANCELED. |
+ if (error.state() == GoogleServiceAuthError::State::REQUEST_CANCELED && |
+ retry_times_ < kTokenRequestCancelMaxRetry) { |
+ retry_times_++; |
+ VLOG(1) << "Retrying to get OAuth2 token due to request cancellation. " |
+ "retry time = " |
+ << retry_times_; |
+ FetchAuthToken(); |
+ return; |
+ } |
+ |
+ // If request failure was not caused by cancellation, or reached max retry |
+ // times on request cancellation, propagate the error to embedder. |
+ is_fetching_token_ = false; |
+ retry_times_ = 0; |
+ VLOG(1) << "OAuth2 token error: " << error.state(); |
DCHECK(delegate_); |
delegate_->OnAuthenticationError( |
BlimpClientContextDelegate::AuthError::OAUTH_TOKEN_FAIL); |