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 "chrome/browser/sync/profile_sync_auth_provider.h"
8 #include "base/location.h"
9 #include "base/message_loop/message_loop_proxy.h"
10 #include "base/single_thread_task_runner.h"
11 #include "components/signin/core/browser/profile_oauth2_token_service.h"
12 #include "google_apis/gaia/gaia_constants.h"
14 // This is thin proxy class for forwarding calls between sync and UI threads.
15 // The main purpose is to hide the fact that ProfileSyncAuthProvider and
16 // SyncThreadProxy have independent lifetimes. If ProfileSyncAuthProvider is
17 // destroyed first calls to RequestAccessToken will never complete. This is fine
18 // since sync thread is not blocked and is in the process of shutdown anyway.
19 class ProfileSyncAuthProvider::SyncThreadProxy
20 : public syncer::SyncAuthProvider
,
21 public base::NonThreadSafe
{
24 base::WeakPtr
<ProfileSyncAuthProvider
> provider_impl
,
25 scoped_refptr
<base::SingleThreadTaskRunner
> provider_task_runner
);
27 // syncer::SyncAuthProvider implementation.
28 virtual void RequestAccessToken(
29 const RequestTokenCallback
& callback
) override
;
30 virtual void InvalidateAccessToken(const std::string
& token
) override
;
33 base::WeakPtr
<ProfileSyncAuthProvider
> provider_impl_
;
34 scoped_refptr
<base::SingleThreadTaskRunner
> provider_task_runner_
;
36 DISALLOW_COPY_AND_ASSIGN(SyncThreadProxy
);
39 ProfileSyncAuthProvider::SyncThreadProxy::SyncThreadProxy(
40 base::WeakPtr
<ProfileSyncAuthProvider
> provider_impl
,
41 scoped_refptr
<base::SingleThreadTaskRunner
> provider_task_runner
)
42 : provider_impl_(provider_impl
),
43 provider_task_runner_(provider_task_runner
) {
44 // SyncThreadProxy is created on UI thread but used on sync thread.
45 // Detach NonThreadSafe from UI thread so that it can reattach to sync thread
46 // on first invocation.
50 void ProfileSyncAuthProvider::SyncThreadProxy::RequestAccessToken(
51 const RequestTokenCallback
& callback
) {
52 DCHECK(CalledOnValidThread());
53 provider_task_runner_
->PostTask(
55 base::Bind(&ProfileSyncAuthProvider::RequestAccessToken
,
58 base::MessageLoopProxy::current()));
61 void ProfileSyncAuthProvider::SyncThreadProxy::InvalidateAccessToken(
62 const std::string
& token
) {
63 DCHECK(CalledOnValidThread());
64 provider_task_runner_
->PostTask(
66 base::Bind(&ProfileSyncAuthProvider::InvalidateAccessToken
,
71 ProfileSyncAuthProvider::ProfileSyncAuthProvider(
72 ProfileOAuth2TokenService
* token_service
,
73 const std::string
& account_id
,
74 const std::string
& scope
)
75 : OAuth2TokenService::Consumer("sync_auth_provider"),
76 token_service_(token_service
),
77 account_id_(account_id
),
79 oauth2_scope_
.insert(scope
);
82 ProfileSyncAuthProvider::~ProfileSyncAuthProvider() {
83 DCHECK(CalledOnValidThread());
86 void ProfileSyncAuthProvider::RequestAccessToken(
87 const syncer::SyncAuthProvider::RequestTokenCallback
& callback
,
88 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner
) {
89 DCHECK(CalledOnValidThread());
90 if (access_token_request_
!= NULL
) {
91 // If there is already pending request report it as cancelled.
92 GoogleServiceAuthError
error(GoogleServiceAuthError::REQUEST_CANCELED
);
93 RespondToTokenRequest(error
, std::string());
95 request_token_callback_
= callback
;
96 callback_task_runner_
= task_runner
;
97 access_token_request_
=
98 token_service_
->StartRequest(account_id_
, oauth2_scope_
, this);
101 void ProfileSyncAuthProvider::OnGetTokenSuccess(
102 const OAuth2TokenService::Request
* request
,
103 const std::string
& access_token
,
104 const base::Time
& expiration_time
) {
105 DCHECK_EQ(access_token_request_
, request
);
106 RespondToTokenRequest(GoogleServiceAuthError::AuthErrorNone(), access_token
);
109 void ProfileSyncAuthProvider::OnGetTokenFailure(
110 const OAuth2TokenService::Request
* request
,
111 const GoogleServiceAuthError
& error
) {
112 DCHECK_EQ(access_token_request_
, request
);
113 RespondToTokenRequest(error
, std::string());
116 void ProfileSyncAuthProvider::RespondToTokenRequest(
117 const GoogleServiceAuthError
& error
,
118 const std::string
& token
) {
119 DCHECK(CalledOnValidThread());
120 callback_task_runner_
->PostTask(
121 FROM_HERE
, base::Bind(request_token_callback_
, error
, token
));
122 access_token_request_
.reset();
123 request_token_callback_
.Reset();
124 callback_task_runner_
= NULL
;
127 void ProfileSyncAuthProvider::InvalidateAccessToken(const std::string
& token
) {
128 DCHECK(CalledOnValidThread());
129 token_service_
->InvalidateToken(account_id_
, oauth2_scope_
, token
);
132 scoped_ptr
<syncer::SyncAuthProvider
>
133 ProfileSyncAuthProvider::CreateProviderForSyncThread() {
134 DCHECK(CalledOnValidThread());
135 scoped_ptr
<syncer::SyncAuthProvider
> auth_provider(new SyncThreadProxy(
136 weak_factory_
.GetWeakPtr(), base::MessageLoopProxy::current()));
137 return auth_provider
.Pass();