Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / google_apis / gaia / oauth2_token_service_request.cc
blob3af40c31bee214a8e5dcf64c3e463425aa1fa50a
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/location.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "google_apis/gaia/google_service_auth_error.h"
14 #include "google_apis/gaia/oauth2_access_token_consumer.h"
16 OAuth2TokenServiceRequest::TokenServiceProvider::TokenServiceProvider() {
19 OAuth2TokenServiceRequest::TokenServiceProvider::~TokenServiceProvider() {
22 // Core serves as the base class for OAuth2TokenService operations. Each
23 // operation should be modeled as a derived type.
25 // Core is used like this:
27 // 1. Constructed on owner thread.
29 // 2. Start() is called on owner thread, which calls StartOnTokenServiceThread()
30 // on token service thread.
32 // 3. Request is executed.
34 // 4. Stop() is called on owner thread, which calls StopOnTokenServiceThread()
35 // on token service thread.
37 // 5. Core is destroyed on owner thread.
38 class OAuth2TokenServiceRequest::Core
39 : public base::NonThreadSafe,
40 public base::RefCountedThreadSafe<OAuth2TokenServiceRequest::Core> {
41 public:
42 // Note the thread where an instance of Core is constructed is referred to as
43 // the "owner thread" here.
44 Core(OAuth2TokenServiceRequest* owner,
45 const scoped_refptr<TokenServiceProvider>& provider);
47 // Starts the core. Must be called on the owner thread.
48 void Start();
50 // Stops the core. Must be called on the owner thread.
51 void Stop();
53 // Returns true if this object has been stopped. Must be called on the owner
54 // thread.
55 bool IsStopped() const;
57 protected:
58 // Core must be destroyed on the owner thread. If data members must be
59 // cleaned up or destroyed on the token service thread, do so in the
60 // StopOnTokenServiceThread method.
61 virtual ~Core();
63 // Called on the token service thread.
64 virtual void StartOnTokenServiceThread() = 0;
66 // Called on the token service thread.
67 virtual void StopOnTokenServiceThread() = 0;
69 base::SingleThreadTaskRunner* token_service_task_runner();
70 OAuth2TokenService* token_service();
71 OAuth2TokenServiceRequest* owner();
73 private:
74 friend class base::RefCountedThreadSafe<OAuth2TokenServiceRequest::Core>;
76 void DoNothing();
78 scoped_refptr<base::SingleThreadTaskRunner> token_service_task_runner_;
79 OAuth2TokenServiceRequest* owner_;
81 // Clear on owner thread. OAuth2TokenServiceRequest promises to clear its
82 // last reference to TokenServiceProvider on the owner thread so the caller
83 // can ensure it is destroyed on the owner thread if desired.
84 scoped_refptr<TokenServiceProvider> provider_;
86 DISALLOW_COPY_AND_ASSIGN(Core);
89 OAuth2TokenServiceRequest::Core::Core(
90 OAuth2TokenServiceRequest* owner,
91 const scoped_refptr<TokenServiceProvider>& provider)
92 : owner_(owner), provider_(provider) {
93 DCHECK(owner_);
94 DCHECK(provider_.get());
95 token_service_task_runner_ = provider_->GetTokenServiceTaskRunner();
96 DCHECK(token_service_task_runner_.get());
99 OAuth2TokenServiceRequest::Core::~Core() {
102 void OAuth2TokenServiceRequest::Core::Start() {
103 DCHECK(CalledOnValidThread());
104 token_service_task_runner_->PostTask(
105 FROM_HERE,
106 base::Bind(&OAuth2TokenServiceRequest::Core::StartOnTokenServiceThread,
107 this));
110 void OAuth2TokenServiceRequest::Core::Stop() {
111 DCHECK(CalledOnValidThread());
112 DCHECK(!IsStopped());
114 // Detaches |owner_| from this instance so |owner_| will be called back only
115 // if |Stop()| has never been called.
116 owner_ = NULL;
118 // We are stopping and will likely be destroyed soon. Use a reply closure
119 // (DoNothing) to retain "this" and ensure we are destroyed in the owner
120 // thread, not the task runner thread. PostTaskAndReply guarantees that the
121 // reply closure will execute after StopOnTokenServiceThread has completed.
122 token_service_task_runner_->PostTaskAndReply(
123 FROM_HERE,
124 base::Bind(&OAuth2TokenServiceRequest::Core::StopOnTokenServiceThread,
125 this),
126 base::Bind(&OAuth2TokenServiceRequest::Core::DoNothing, this));
129 bool OAuth2TokenServiceRequest::Core::IsStopped() const {
130 DCHECK(CalledOnValidThread());
131 return owner_ == NULL;
134 base::SingleThreadTaskRunner*
135 OAuth2TokenServiceRequest::Core::token_service_task_runner() {
136 return token_service_task_runner_.get();
139 OAuth2TokenService* OAuth2TokenServiceRequest::Core::token_service() {
140 DCHECK(token_service_task_runner_->BelongsToCurrentThread());
141 return provider_->GetTokenService();
144 OAuth2TokenServiceRequest* OAuth2TokenServiceRequest::Core::owner() {
145 DCHECK(CalledOnValidThread());
146 return owner_;
149 void OAuth2TokenServiceRequest::Core::DoNothing() {
150 DCHECK(CalledOnValidThread());
153 namespace {
155 // An implementation of Core for getting an access token.
156 class RequestCore : public OAuth2TokenServiceRequest::Core,
157 public OAuth2TokenService::Consumer {
158 public:
159 RequestCore(OAuth2TokenServiceRequest* owner,
160 const scoped_refptr<
161 OAuth2TokenServiceRequest::TokenServiceProvider>& provider,
162 OAuth2TokenService::Consumer* consumer,
163 const std::string& account_id,
164 const OAuth2TokenService::ScopeSet& scopes);
166 // OAuth2TokenService::Consumer. Must be called on the token service thread.
167 void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
168 const std::string& access_token,
169 const base::Time& expiration_time) override;
170 void OnGetTokenFailure(const OAuth2TokenService::Request* request,
171 const GoogleServiceAuthError& error) override;
173 private:
174 friend class base::RefCountedThreadSafe<RequestCore>;
176 // Must be destroyed on the owner thread.
177 ~RequestCore() override;
179 // Core implementation.
180 void StartOnTokenServiceThread() override;
181 void StopOnTokenServiceThread() override;
183 void InformOwnerOnGetTokenSuccess(std::string access_token,
184 base::Time expiration_time);
185 void InformOwnerOnGetTokenFailure(GoogleServiceAuthError error);
187 scoped_refptr<base::SingleThreadTaskRunner> owner_task_runner_;
188 OAuth2TokenService::Consumer* const consumer_;
189 std::string account_id_;
190 OAuth2TokenService::ScopeSet scopes_;
192 // OAuth2TokenService request for fetching OAuth2 access token; it should be
193 // created, reset and accessed only on the token service thread.
194 scoped_ptr<OAuth2TokenService::Request> request_;
196 DISALLOW_COPY_AND_ASSIGN(RequestCore);
199 RequestCore::RequestCore(
200 OAuth2TokenServiceRequest* owner,
201 const scoped_refptr<OAuth2TokenServiceRequest::TokenServiceProvider>&
202 provider,
203 OAuth2TokenService::Consumer* consumer,
204 const std::string& account_id,
205 const OAuth2TokenService::ScopeSet& scopes)
206 : OAuth2TokenServiceRequest::Core(owner, provider),
207 OAuth2TokenService::Consumer("oauth2_token_service"),
208 owner_task_runner_(base::ThreadTaskRunnerHandle::Get()),
209 consumer_(consumer),
210 account_id_(account_id),
211 scopes_(scopes) {
212 DCHECK(consumer_);
213 DCHECK(!account_id_.empty());
214 DCHECK(!scopes_.empty());
217 RequestCore::~RequestCore() {
220 void RequestCore::StartOnTokenServiceThread() {
221 DCHECK(token_service_task_runner()->BelongsToCurrentThread());
222 request_ = token_service()->StartRequest(account_id_, scopes_, this).Pass();
225 void RequestCore::StopOnTokenServiceThread() {
226 DCHECK(token_service_task_runner()->BelongsToCurrentThread());
227 request_.reset();
230 void RequestCore::OnGetTokenSuccess(const OAuth2TokenService::Request* request,
231 const std::string& access_token,
232 const base::Time& expiration_time) {
233 DCHECK(token_service_task_runner()->BelongsToCurrentThread());
234 DCHECK_EQ(request_.get(), request);
235 owner_task_runner_->PostTask(
236 FROM_HERE,
237 base::Bind(&RequestCore::InformOwnerOnGetTokenSuccess,
238 this,
239 access_token,
240 expiration_time));
241 request_.reset();
244 void RequestCore::OnGetTokenFailure(const OAuth2TokenService::Request* request,
245 const GoogleServiceAuthError& error) {
246 DCHECK(token_service_task_runner()->BelongsToCurrentThread());
247 DCHECK_EQ(request_.get(), request);
248 owner_task_runner_->PostTask(
249 FROM_HERE,
250 base::Bind(&RequestCore::InformOwnerOnGetTokenFailure, this, error));
251 request_.reset();
254 void RequestCore::InformOwnerOnGetTokenSuccess(std::string access_token,
255 base::Time expiration_time) {
256 DCHECK(CalledOnValidThread());
257 if (!IsStopped()) {
258 consumer_->OnGetTokenSuccess(owner(), access_token, expiration_time);
262 void RequestCore::InformOwnerOnGetTokenFailure(GoogleServiceAuthError error) {
263 DCHECK(CalledOnValidThread());
264 if (!IsStopped()) {
265 consumer_->OnGetTokenFailure(owner(), error);
269 // An implementation of Core for invalidating an access token.
270 class InvalidateCore : public OAuth2TokenServiceRequest::Core {
271 public:
272 InvalidateCore(OAuth2TokenServiceRequest* owner,
273 const scoped_refptr<
274 OAuth2TokenServiceRequest::TokenServiceProvider>& provider,
275 const std::string& access_token,
276 const std::string& account_id,
277 const OAuth2TokenService::ScopeSet& scopes);
279 private:
280 friend class base::RefCountedThreadSafe<InvalidateCore>;
282 // Must be destroyed on the owner thread.
283 ~InvalidateCore() override;
285 // Core implementation.
286 void StartOnTokenServiceThread() override;
287 void StopOnTokenServiceThread() override;
289 std::string access_token_;
290 std::string account_id_;
291 OAuth2TokenService::ScopeSet scopes_;
293 DISALLOW_COPY_AND_ASSIGN(InvalidateCore);
296 InvalidateCore::InvalidateCore(
297 OAuth2TokenServiceRequest* owner,
298 const scoped_refptr<OAuth2TokenServiceRequest::TokenServiceProvider>&
299 provider,
300 const std::string& access_token,
301 const std::string& account_id,
302 const OAuth2TokenService::ScopeSet& scopes)
303 : OAuth2TokenServiceRequest::Core(owner, provider),
304 access_token_(access_token),
305 account_id_(account_id),
306 scopes_(scopes) {
307 DCHECK(!access_token_.empty());
308 DCHECK(!account_id_.empty());
309 DCHECK(!scopes.empty());
312 InvalidateCore::~InvalidateCore() {
315 void InvalidateCore::StartOnTokenServiceThread() {
316 DCHECK(token_service_task_runner()->BelongsToCurrentThread());
317 token_service()->InvalidateAccessToken(account_id_, scopes_, access_token_);
320 void InvalidateCore::StopOnTokenServiceThread() {
321 DCHECK(token_service_task_runner()->BelongsToCurrentThread());
322 // Nothing to do.
325 } // namespace
327 // static
328 scoped_ptr<OAuth2TokenServiceRequest> OAuth2TokenServiceRequest::CreateAndStart(
329 const scoped_refptr<TokenServiceProvider>& provider,
330 const std::string& account_id,
331 const OAuth2TokenService::ScopeSet& scopes,
332 OAuth2TokenService::Consumer* consumer) {
333 scoped_ptr<OAuth2TokenServiceRequest> request(
334 new OAuth2TokenServiceRequest(account_id));
335 scoped_refptr<Core> core(
336 new RequestCore(request.get(), provider, consumer, account_id, scopes));
337 request->StartWithCore(core);
338 return request.Pass();
341 // static
342 void OAuth2TokenServiceRequest::InvalidateToken(
343 const scoped_refptr<TokenServiceProvider>& provider,
344 const std::string& account_id,
345 const OAuth2TokenService::ScopeSet& scopes,
346 const std::string& access_token) {
347 scoped_ptr<OAuth2TokenServiceRequest> request(
348 new OAuth2TokenServiceRequest(account_id));
349 scoped_refptr<Core> core(new InvalidateCore(
350 request.get(), provider, access_token, account_id, scopes));
351 request->StartWithCore(core);
354 OAuth2TokenServiceRequest::~OAuth2TokenServiceRequest() {
355 core_->Stop();
358 std::string OAuth2TokenServiceRequest::GetAccountId() const {
359 return account_id_;
362 OAuth2TokenServiceRequest::OAuth2TokenServiceRequest(
363 const std::string& account_id)
364 : account_id_(account_id) {
365 DCHECK(!account_id_.empty());
368 void OAuth2TokenServiceRequest::StartWithCore(const scoped_refptr<Core>& core) {
369 DCHECK(core.get());
370 core_ = core;
371 core_->Start();