Roll BoringSSL.
[chromium-blink-merge.git] / google_apis / gaia / oauth2_token_service_request.cc
blob0c737ad5ce4a0739455f0d3750dd4f126a17b6d0
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "google_apis/gaia/oauth2_token_service_request.h"
7 #include "base/bind.h"
8 #include "base/memory/ref_counted.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "google_apis/gaia/google_service_auth_error.h"
13 #include "google_apis/gaia/oauth2_access_token_consumer.h"
15 OAuth2TokenServiceRequest::TokenServiceProvider::TokenServiceProvider() {
18 OAuth2TokenServiceRequest::TokenServiceProvider::~TokenServiceProvider() {
21 // Core serves as the base class for OAuth2TokenService operations. Each
22 // operation should be modeled as a derived type.
24 // Core is used like this:
26 // 1. Constructed on owner thread.
28 // 2. Start() is called on owner thread, which calls StartOnTokenServiceThread()
29 // on token service thread.
31 // 3. Request is executed.
33 // 4. Stop() is called on owner thread, which calls StopOnTokenServiceThread()
34 // on token service thread.
36 // 5. Core is destroyed on owner thread.
37 class OAuth2TokenServiceRequest::Core
38 : public base::NonThreadSafe,
39 public base::RefCountedThreadSafe<OAuth2TokenServiceRequest::Core> {
40 public:
41 // Note the thread where an instance of Core is constructed is referred to as
42 // the "owner thread" here.
43 Core(OAuth2TokenServiceRequest* owner,
44 const scoped_refptr<TokenServiceProvider>& provider);
46 // Starts the core. Must be called on the owner thread.
47 void Start();
49 // Stops the core. Must be called on the owner thread.
50 void Stop();
52 // Returns true if this object has been stopped. Must be called on the owner
53 // thread.
54 bool IsStopped() const;
56 protected:
57 // Core must be destroyed on the owner thread. If data members must be
58 // cleaned up or destroyed on the token service thread, do so in the
59 // StopOnTokenServiceThread method.
60 virtual ~Core();
62 // Called on the token service thread.
63 virtual void StartOnTokenServiceThread() = 0;
65 // Called on the token service thread.
66 virtual void StopOnTokenServiceThread() = 0;
68 base::SingleThreadTaskRunner* token_service_task_runner();
69 OAuth2TokenService* token_service();
70 OAuth2TokenServiceRequest* owner();
72 private:
73 friend class base::RefCountedThreadSafe<OAuth2TokenServiceRequest::Core>;
75 void DoNothing();
77 scoped_refptr<base::SingleThreadTaskRunner> token_service_task_runner_;
78 OAuth2TokenServiceRequest* owner_;
80 // Clear on owner thread. OAuth2TokenServiceRequest promises to clear its
81 // last reference to TokenServiceProvider on the owner thread so the caller
82 // can ensure it is destroyed on the owner thread if desired.
83 scoped_refptr<TokenServiceProvider> provider_;
85 DISALLOW_COPY_AND_ASSIGN(Core);
88 OAuth2TokenServiceRequest::Core::Core(
89 OAuth2TokenServiceRequest* owner,
90 const scoped_refptr<TokenServiceProvider>& provider)
91 : owner_(owner), provider_(provider) {
92 DCHECK(owner_);
93 DCHECK(provider_);
94 token_service_task_runner_ = provider_->GetTokenServiceTaskRunner();
95 DCHECK(token_service_task_runner_);
98 OAuth2TokenServiceRequest::Core::~Core() {
101 void OAuth2TokenServiceRequest::Core::Start() {
102 DCHECK(CalledOnValidThread());
103 token_service_task_runner_->PostTask(
104 FROM_HERE,
105 base::Bind(&OAuth2TokenServiceRequest::Core::StartOnTokenServiceThread,
106 this));
109 void OAuth2TokenServiceRequest::Core::Stop() {
110 DCHECK(CalledOnValidThread());
111 DCHECK(!IsStopped());
113 // Detaches |owner_| from this instance so |owner_| will be called back only
114 // if |Stop()| has never been called.
115 owner_ = NULL;
117 // We are stopping and will likely be destroyed soon. Use a reply closure
118 // (DoNothing) to retain "this" and ensure we are destroyed in the owner
119 // thread, not the task runner thread. PostTaskAndReply guarantees that the
120 // reply closure will execute after StopOnTokenServiceThread has completed.
121 token_service_task_runner_->PostTaskAndReply(
122 FROM_HERE,
123 base::Bind(&OAuth2TokenServiceRequest::Core::StopOnTokenServiceThread,
124 this),
125 base::Bind(&OAuth2TokenServiceRequest::Core::DoNothing, this));
128 bool OAuth2TokenServiceRequest::Core::IsStopped() const {
129 DCHECK(CalledOnValidThread());
130 return owner_ == NULL;
133 base::SingleThreadTaskRunner*
134 OAuth2TokenServiceRequest::Core::token_service_task_runner() {
135 return token_service_task_runner_;
138 OAuth2TokenService* OAuth2TokenServiceRequest::Core::token_service() {
139 DCHECK(token_service_task_runner_->BelongsToCurrentThread());
140 return provider_->GetTokenService();
143 OAuth2TokenServiceRequest* OAuth2TokenServiceRequest::Core::owner() {
144 DCHECK(CalledOnValidThread());
145 return owner_;
148 void OAuth2TokenServiceRequest::Core::DoNothing() {
149 DCHECK(CalledOnValidThread());
152 namespace {
154 // An implementation of Core for getting an access token.
155 class RequestCore : public OAuth2TokenServiceRequest::Core,
156 public OAuth2TokenService::Consumer {
157 public:
158 RequestCore(OAuth2TokenServiceRequest* owner,
159 const scoped_refptr<
160 OAuth2TokenServiceRequest::TokenServiceProvider>& provider,
161 OAuth2TokenService::Consumer* consumer,
162 const std::string& account_id,
163 const OAuth2TokenService::ScopeSet& scopes);
165 // OAuth2TokenService::Consumer. Must be called on the token service thread.
166 virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
167 const std::string& access_token,
168 const base::Time& expiration_time) OVERRIDE;
169 virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request,
170 const GoogleServiceAuthError& error) OVERRIDE;
172 private:
173 friend class base::RefCountedThreadSafe<RequestCore>;
175 // Must be destroyed on the owner thread.
176 virtual ~RequestCore();
178 // Core implementation.
179 virtual void StartOnTokenServiceThread() OVERRIDE;
180 virtual void StopOnTokenServiceThread() OVERRIDE;
182 void InformOwnerOnGetTokenSuccess(std::string access_token,
183 base::Time expiration_time);
184 void InformOwnerOnGetTokenFailure(GoogleServiceAuthError error);
186 scoped_refptr<base::SingleThreadTaskRunner> owner_task_runner_;
187 OAuth2TokenService::Consumer* const consumer_;
188 std::string account_id_;
189 OAuth2TokenService::ScopeSet scopes_;
191 // OAuth2TokenService request for fetching OAuth2 access token; it should be
192 // created, reset and accessed only on the token service thread.
193 scoped_ptr<OAuth2TokenService::Request> request_;
195 DISALLOW_COPY_AND_ASSIGN(RequestCore);
198 RequestCore::RequestCore(
199 OAuth2TokenServiceRequest* owner,
200 const scoped_refptr<OAuth2TokenServiceRequest::TokenServiceProvider>&
201 provider,
202 OAuth2TokenService::Consumer* consumer,
203 const std::string& account_id,
204 const OAuth2TokenService::ScopeSet& scopes)
205 : OAuth2TokenServiceRequest::Core(owner, provider),
206 OAuth2TokenService::Consumer("oauth2_token_service"),
207 owner_task_runner_(base::ThreadTaskRunnerHandle::Get()),
208 consumer_(consumer),
209 account_id_(account_id),
210 scopes_(scopes) {
211 DCHECK(consumer_);
212 DCHECK(!account_id_.empty());
213 DCHECK(!scopes_.empty());
216 RequestCore::~RequestCore() {
219 void RequestCore::StartOnTokenServiceThread() {
220 DCHECK(token_service_task_runner()->BelongsToCurrentThread());
221 request_ = token_service()->StartRequest(account_id_, scopes_, this).Pass();
224 void RequestCore::StopOnTokenServiceThread() {
225 DCHECK(token_service_task_runner()->BelongsToCurrentThread());
226 request_.reset();
229 void RequestCore::OnGetTokenSuccess(const OAuth2TokenService::Request* request,
230 const std::string& access_token,
231 const base::Time& expiration_time) {
232 DCHECK(token_service_task_runner()->BelongsToCurrentThread());
233 DCHECK_EQ(request_.get(), request);
234 owner_task_runner_->PostTask(
235 FROM_HERE,
236 base::Bind(&RequestCore::InformOwnerOnGetTokenSuccess,
237 this,
238 access_token,
239 expiration_time));
240 request_.reset();
243 void RequestCore::OnGetTokenFailure(const OAuth2TokenService::Request* request,
244 const GoogleServiceAuthError& error) {
245 DCHECK(token_service_task_runner()->BelongsToCurrentThread());
246 DCHECK_EQ(request_.get(), request);
247 owner_task_runner_->PostTask(
248 FROM_HERE,
249 base::Bind(&RequestCore::InformOwnerOnGetTokenFailure, this, error));
250 request_.reset();
253 void RequestCore::InformOwnerOnGetTokenSuccess(std::string access_token,
254 base::Time expiration_time) {
255 DCHECK(CalledOnValidThread());
256 if (!IsStopped()) {
257 consumer_->OnGetTokenSuccess(owner(), access_token, expiration_time);
261 void RequestCore::InformOwnerOnGetTokenFailure(GoogleServiceAuthError error) {
262 DCHECK(CalledOnValidThread());
263 if (!IsStopped()) {
264 consumer_->OnGetTokenFailure(owner(), error);
268 // An implementation of Core for invalidating an access token.
269 class InvalidateCore : public OAuth2TokenServiceRequest::Core {
270 public:
271 InvalidateCore(OAuth2TokenServiceRequest* owner,
272 const scoped_refptr<
273 OAuth2TokenServiceRequest::TokenServiceProvider>& provider,
274 const std::string& access_token,
275 const std::string& account_id,
276 const OAuth2TokenService::ScopeSet& scopes);
278 private:
279 friend class base::RefCountedThreadSafe<InvalidateCore>;
281 // Must be destroyed on the owner thread.
282 virtual ~InvalidateCore();
284 // Core implementation.
285 virtual void StartOnTokenServiceThread() OVERRIDE;
286 virtual void StopOnTokenServiceThread() OVERRIDE;
288 std::string access_token_;
289 std::string account_id_;
290 OAuth2TokenService::ScopeSet scopes_;
292 DISALLOW_COPY_AND_ASSIGN(InvalidateCore);
295 InvalidateCore::InvalidateCore(
296 OAuth2TokenServiceRequest* owner,
297 const scoped_refptr<OAuth2TokenServiceRequest::TokenServiceProvider>&
298 provider,
299 const std::string& access_token,
300 const std::string& account_id,
301 const OAuth2TokenService::ScopeSet& scopes)
302 : OAuth2TokenServiceRequest::Core(owner, provider),
303 access_token_(access_token),
304 account_id_(account_id),
305 scopes_(scopes) {
306 DCHECK(!access_token_.empty());
307 DCHECK(!account_id_.empty());
308 DCHECK(!scopes.empty());
311 InvalidateCore::~InvalidateCore() {
314 void InvalidateCore::StartOnTokenServiceThread() {
315 DCHECK(token_service_task_runner()->BelongsToCurrentThread());
316 token_service()->InvalidateToken(account_id_, scopes_, access_token_);
319 void InvalidateCore::StopOnTokenServiceThread() {
320 DCHECK(token_service_task_runner()->BelongsToCurrentThread());
321 // Nothing to do.
324 } // namespace
326 // static
327 scoped_ptr<OAuth2TokenServiceRequest> OAuth2TokenServiceRequest::CreateAndStart(
328 const scoped_refptr<TokenServiceProvider>& provider,
329 const std::string& account_id,
330 const OAuth2TokenService::ScopeSet& scopes,
331 OAuth2TokenService::Consumer* consumer) {
332 scoped_ptr<OAuth2TokenServiceRequest> request(
333 new OAuth2TokenServiceRequest(account_id));
334 scoped_refptr<Core> core(
335 new RequestCore(request.get(), provider, consumer, account_id, scopes));
336 request->StartWithCore(core);
337 return request.Pass();
340 // static
341 void OAuth2TokenServiceRequest::InvalidateToken(
342 const scoped_refptr<TokenServiceProvider>& provider,
343 const std::string& account_id,
344 const OAuth2TokenService::ScopeSet& scopes,
345 const std::string& access_token) {
346 scoped_ptr<OAuth2TokenServiceRequest> request(
347 new OAuth2TokenServiceRequest(account_id));
348 scoped_refptr<Core> core(new InvalidateCore(
349 request.get(), provider, access_token, account_id, scopes));
350 request->StartWithCore(core);
353 OAuth2TokenServiceRequest::~OAuth2TokenServiceRequest() {
354 core_->Stop();
357 std::string OAuth2TokenServiceRequest::GetAccountId() const {
358 return account_id_;
361 OAuth2TokenServiceRequest::OAuth2TokenServiceRequest(
362 const std::string& account_id)
363 : account_id_(account_id) {
364 DCHECK(!account_id_.empty());
367 void OAuth2TokenServiceRequest::StartWithCore(const scoped_refptr<Core>& core) {
368 DCHECK(core);
369 core_ = core;
370 core_->Start();