Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync / profile_sync_auth_provider.cc
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.
4
5 #include "chrome/browser/sync/profile_sync_auth_provider.h"
6
7 #include "base/bind.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"
13
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 {
22  public:
23   SyncThreadProxy(
24       base::WeakPtr<ProfileSyncAuthProvider> provider_impl,
25       scoped_refptr<base::SingleThreadTaskRunner> provider_task_runner);
26
27   // syncer::SyncAuthProvider implementation.
28   virtual void RequestAccessToken(
29       const RequestTokenCallback& callback) OVERRIDE;
30   virtual void InvalidateAccessToken(const std::string& token) OVERRIDE;
31
32  private:
33   base::WeakPtr<ProfileSyncAuthProvider> provider_impl_;
34   scoped_refptr<base::SingleThreadTaskRunner> provider_task_runner_;
35
36   DISALLOW_COPY_AND_ASSIGN(SyncThreadProxy);
37 };
38
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.
47   DetachFromThread();
48 }
49
50 void ProfileSyncAuthProvider::SyncThreadProxy::RequestAccessToken(
51     const RequestTokenCallback& callback) {
52   DCHECK(CalledOnValidThread());
53   provider_task_runner_->PostTask(
54       FROM_HERE,
55       base::Bind(&ProfileSyncAuthProvider::RequestAccessToken,
56                  provider_impl_,
57                  callback,
58                  base::MessageLoopProxy::current()));
59 }
60
61 void ProfileSyncAuthProvider::SyncThreadProxy::InvalidateAccessToken(
62     const std::string& token) {
63   DCHECK(CalledOnValidThread());
64   provider_task_runner_->PostTask(
65       FROM_HERE,
66       base::Bind(&ProfileSyncAuthProvider::InvalidateAccessToken,
67                  provider_impl_,
68                  token));
69 }
70
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),
78       weak_factory_(this) {
79   oauth2_scope_.insert(scope);
80 }
81
82 ProfileSyncAuthProvider::~ProfileSyncAuthProvider() {
83   DCHECK(CalledOnValidThread());
84 }
85
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());
94   }
95   request_token_callback_ = callback;
96   callback_task_runner_ = task_runner;
97   access_token_request_ =
98       token_service_->StartRequest(account_id_, oauth2_scope_, this);
99 }
100
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);
107 }
108
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());
114 }
115
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;
125 }
126
127 void ProfileSyncAuthProvider::InvalidateAccessToken(const std::string& token) {
128   DCHECK(CalledOnValidThread());
129   token_service_->InvalidateToken(account_id_, oauth2_scope_, token);
130 }
131
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();
138 }