OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "blimp/client/core/session/identity_source.h" | 5 #include "blimp/client/core/session/identity_source.h" |
6 | 6 |
7 #include "base/command_line.h" | |
7 #include "base/memory/ptr_util.h" | 8 #include "base/memory/ptr_util.h" |
9 #include "blimp/client/core/blimp_client_switches.h" | |
8 | 10 |
9 namespace blimp { | 11 namespace blimp { |
10 namespace client { | 12 namespace client { |
11 | 13 |
12 namespace { | 14 namespace { |
13 // OAuth2 token scope. | 15 // OAuth2 token scope. |
14 const char kOAuth2TokenScope[] = | 16 const char kOAuth2TokenScope[] = |
15 "https://www.googleapis.com/auth/userinfo.email"; | 17 "https://www.googleapis.com/auth/userinfo.email"; |
18 | |
19 // Max retry times when OAuth2 token request is canceled. | |
20 const int kTokenRequestCancelMaxRetry = 3; | |
16 } // namespace | 21 } // namespace |
17 | 22 |
18 IdentitySource::IdentitySource(BlimpClientContextDelegate* delegate, | 23 IdentitySource::IdentitySource(BlimpClientContextDelegate* delegate, |
19 const TokenCallback& callback) | 24 const TokenCallback& callback) |
20 : OAuth2TokenService::Consumer("blimp_client"), | 25 : OAuth2TokenService::Consumer("blimp_client"), |
21 token_callback_(callback), | 26 token_callback_(callback), |
22 is_fetching_token_(false), | 27 is_fetching_token_(false), |
28 retry_times_(0), | |
23 delegate_(delegate) { | 29 delegate_(delegate) { |
24 DCHECK(delegate_); | 30 DCHECK(delegate_); |
25 | 31 |
26 // Create identity provider. | 32 // Create identity provider. |
27 identity_provider_ = delegate_->CreateIdentityProvider(); | 33 identity_provider_ = delegate_->CreateIdentityProvider(); |
28 DCHECK(identity_provider_.get()); | 34 DCHECK(identity_provider_.get()); |
29 identity_provider_->AddObserver(this); | 35 identity_provider_->AddObserver(this); |
30 } | 36 } |
31 | 37 |
32 IdentitySource::~IdentitySource() { | 38 IdentitySource::~IdentitySource() { |
33 identity_provider_->RemoveActiveAccountRefreshTokenObserver(this); | 39 identity_provider_->RemoveActiveAccountRefreshTokenObserver(this); |
34 identity_provider_->RemoveObserver(this); | 40 identity_provider_->RemoveObserver(this); |
35 } | 41 } |
36 | 42 |
37 void IdentitySource::Connect() { | 43 void IdentitySource::Connect() { |
38 if (is_fetching_token_) { | 44 if (is_fetching_token_) { |
39 return; | 45 return; |
40 } | 46 } |
41 | 47 |
48 // Pass empty token to assignment source if we have command line switches. | |
49 if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kEngineIP)) { | |
50 if (token_callback_) { | |
51 token_callback_.Run(std::string()); | |
52 } | |
53 return; | |
54 } | |
55 | |
56 // User must sign in first to get an OAuth2 token. | |
42 const std::string& account_id = identity_provider_->GetActiveAccountId(); | 57 const std::string& account_id = identity_provider_->GetActiveAccountId(); |
43 | |
44 // User must sign in first. | |
45 if (account_id.empty()) { | 58 if (account_id.empty()) { |
46 delegate_->OnAuthenticationError( | 59 delegate_->OnAuthenticationError( |
47 BlimpClientContextDelegate::AuthError::NOT_SIGNED_IN); | 60 BlimpClientContextDelegate::AuthError::NOT_SIGNED_IN); |
48 return; | 61 return; |
49 } | 62 } |
50 | 63 |
51 account_id_ = account_id; | 64 account_id_ = account_id; |
52 is_fetching_token_ = true; | 65 is_fetching_token_ = true; |
53 FetchAuthToken(); | 66 FetchAuthToken(); |
54 } | 67 } |
55 | 68 |
69 // Add sign in state observer. | |
70 void IdentitySource::AddObserver(IdentityProvider::Observer* observer) { | |
71 DCHECK(identity_provider_); | |
72 identity_provider_->AddObserver(observer); | |
73 } | |
74 | |
75 // Remove sign in state observer. | |
76 void IdentitySource::RemoveObserver(IdentityProvider::Observer* observer) { | |
77 DCHECK(identity_provider_); | |
78 identity_provider_->RemoveObserver(observer); | |
79 } | |
80 | |
56 void IdentitySource::OnGetTokenSuccess( | 81 void IdentitySource::OnGetTokenSuccess( |
57 const OAuth2TokenService::Request* request, | 82 const OAuth2TokenService::Request* request, |
58 const std::string& access_token, | 83 const std::string& access_token, |
59 const base::Time& expiration_time) { | 84 const base::Time& expiration_time) { |
60 token_request_.reset(); | 85 token_request_.reset(); |
61 is_fetching_token_ = false; | 86 is_fetching_token_ = false; |
87 retry_times_ = 0; | |
62 | 88 |
63 if (token_callback_) { | 89 if (token_callback_) { |
64 token_callback_.Run(access_token); | 90 token_callback_.Run(access_token); |
65 } | 91 } |
66 } | 92 } |
67 | 93 |
68 // Fail to get the token after retries attempts in native layer and Java layer. | 94 // Fail to get the token after retries attempts in native layer and Java layer. |
69 void IdentitySource::OnGetTokenFailure( | 95 void IdentitySource::OnGetTokenFailure( |
70 const OAuth2TokenService::Request* request, | 96 const OAuth2TokenService::Request* request, |
71 const GoogleServiceAuthError& error) { | 97 const GoogleServiceAuthError& error) { |
72 token_request_.reset(); | 98 token_request_.reset(); |
99 | |
100 // The embedder can invalidate the refresh token at any time, this happens | |
101 // during application start up or when user switches account. | |
102 // OnGetTokenFailure will be called and the error code is REQUEST_CANCELED. | |
103 // Retry the request to avoid this to happen. | |
David Trainor- moved to gerrit
2016/08/30 20:46:29
remove "to happen"
xingliu
2016/08/30 22:27:36
Done.
| |
104 if (error.state() == GoogleServiceAuthError::State::REQUEST_CANCELED && | |
105 retry_times_ < kTokenRequestCancelMaxRetry) { | |
106 retry_times_++; | |
107 VLOG(1) << "Retrying to get OAuth2 token due to request cancellation. " | |
108 "retry time = " | |
109 << retry_times_; | |
110 FetchAuthToken(); | |
111 return; | |
112 } | |
113 | |
114 // If request failure was not caused by cancellation, or reached max retry | |
115 // times on request cancellation, propagate the error to embedder. | |
73 is_fetching_token_ = false; | 116 is_fetching_token_ = false; |
74 | 117 retry_times_ = 0; |
118 VLOG(1) << "OAuth2 token error: " << error.state(); | |
75 DCHECK(delegate_); | 119 DCHECK(delegate_); |
76 delegate_->OnAuthenticationError( | 120 delegate_->OnAuthenticationError( |
77 BlimpClientContextDelegate::AuthError::OAUTH_TOKEN_FAIL); | 121 BlimpClientContextDelegate::AuthError::OAUTH_TOKEN_FAIL); |
78 } | 122 } |
79 | 123 |
80 void IdentitySource::OnRefreshTokenAvailable(const std::string& account_id) { | 124 void IdentitySource::OnRefreshTokenAvailable(const std::string& account_id) { |
81 if (account_id != account_id_) { | 125 if (account_id != account_id_) { |
82 return; | 126 return; |
83 } | 127 } |
84 | 128 |
85 identity_provider_->RemoveActiveAccountRefreshTokenObserver(this); | 129 identity_provider_->RemoveActiveAccountRefreshTokenObserver(this); |
86 FetchAuthToken(); | 130 FetchAuthToken(); |
87 } | 131 } |
88 | 132 |
89 void IdentitySource::FetchAuthToken() { | 133 void IdentitySource::FetchAuthToken() { |
90 OAuth2TokenService* token_service = identity_provider_->GetTokenService(); | 134 OAuth2TokenService* token_service = identity_provider_->GetTokenService(); |
91 DCHECK(token_service); | 135 DCHECK(token_service); |
92 | 136 |
93 if (token_service->RefreshTokenIsAvailable(account_id_)) { | 137 if (token_service->RefreshTokenIsAvailable(account_id_)) { |
94 OAuth2TokenService::ScopeSet scopes; | 138 OAuth2TokenService::ScopeSet scopes; |
95 scopes.insert(kOAuth2TokenScope); | 139 scopes.insert(kOAuth2TokenScope); |
96 token_request_ = token_service->StartRequest(account_id_, scopes, this); | 140 token_request_ = token_service->StartRequest(account_id_, scopes, this); |
97 } else { | 141 } else { |
98 identity_provider_->AddActiveAccountRefreshTokenObserver(this); | 142 identity_provider_->AddActiveAccountRefreshTokenObserver(this); |
99 } | 143 } |
100 } | 144 } |
101 | 145 |
102 } // namespace client | 146 } // namespace client |
103 } // namespace blimp | 147 } // namespace blimp |
OLD | NEW |