Home | History | Annotate | Download | only in sync
      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 }
    139