root/chrome/browser/signin/profile_oauth2_token_service_request.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. owner_task_runner_
  2. Start
  3. Stop
  4. request
  5. StopOnUIThread
  6. StartOnUIThread
  7. OnGetTokenSuccess
  8. OnGetTokenFailure
  9. InformOwnerOnGetTokenSuccess
  10. InformOwnerOnGetTokenFailure
  11. CreateAndStart
  12. core_
  13. GetAccountId

// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/signin/profile_oauth2_token_service_request.h"

#include "base/bind.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "components/signin/core/browser/profile_oauth2_token_service.h"
#include "components/signin/core/browser/signin_manager.h"
#include "content/public/browser/browser_thread.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "google_apis/gaia/oauth2_access_token_consumer.h"

class ProfileOAuth2TokenServiceRequest::Core
    : public base::RefCountedThreadSafe<ProfileOAuth2TokenServiceRequest::Core>,
      public OAuth2TokenService::Consumer {
 public:
  // Note the thread where an instance of Core is constructed is referred to as
  // the "owner thread" here. This will be the thread of |owner_task_runner_|.
  Core(Profile* profile,
       ProfileOAuth2TokenServiceRequest* owner);
  // Starts fetching an OAuth2 access token for |account_id| and |scopes|. It
  // should be called on the owner thread.
  void Start(
      const std::string& account_id,
      const OAuth2TokenService::ScopeSet& scopes);
  // Stops the OAuth2 access token fetching. It should be called on the owner
  // thread.
  void Stop();

  OAuth2TokenService::Request* request();

  // OAuth2TokenService::Consumer. It should be called on the UI thread.
  virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
                                 const std::string& access_token,
                                 const base::Time& expiration_time) OVERRIDE;
  virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request,
                                 const GoogleServiceAuthError& error) OVERRIDE;

 private:
  friend class
      base::RefCountedThreadSafe<ProfileOAuth2TokenServiceRequest::Core>;

  // Note this can be destructed on the owner thread or on the UI thread,
  // depending on the reference count.
  virtual ~Core();

  // Starts an OAuth2TokenService::Request on the UI thread.
  void StartOnUIThread(
      const std::string& account_id,
      const OAuth2TokenService::ScopeSet& scopes);
  // Stops the OAuth2TokenService::Request on the UI thread.
  void StopOnUIThread();

  // Method posted to the owner thread to call back |owner_|. Note when this
  // posted task is actually running on the owner thread, it is possible that
  // |owner_| has been reset NULL.
  void InformOwnerOnGetTokenSuccess(std::string access_token,
                                    base::Time expiration_time);
  void InformOwnerOnGetTokenFailure(GoogleServiceAuthError error);

  // The profile with which this instance was initialized.
  Profile* const profile_;

  // The object to call back when fetching completes. |owner_| should be
  // called back only on the owner thread.
  ProfileOAuth2TokenServiceRequest* owner_;
  // Task runner on which |owner_| should be called back.
  scoped_refptr<base::SingleThreadTaskRunner> owner_task_runner_;

  // OAuth2TokenService request for fetching OAuth2 access token; it should be
  // created, reset and accessed only on the UI thread.
  scoped_ptr<OAuth2TokenService::Request> request_;

  DISALLOW_COPY_AND_ASSIGN(Core);
};

ProfileOAuth2TokenServiceRequest::Core::Core(
    Profile* profile,
    ProfileOAuth2TokenServiceRequest* owner)
    : OAuth2TokenService::Consumer("oauth2_token_service"),
      profile_(profile),
      owner_(owner),
      owner_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
  DCHECK(profile);
  DCHECK(owner);
}

ProfileOAuth2TokenServiceRequest::Core::~Core() {
}

void ProfileOAuth2TokenServiceRequest::Core::Start(
    const std::string& account_id,
    const OAuth2TokenService::ScopeSet& scopes) {
  DCHECK(owner_task_runner_->BelongsToCurrentThread());

  if (content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
    StartOnUIThread(account_id, scopes);
  } else {
    content::BrowserThread::PostTask(
        content::BrowserThread::UI,
        FROM_HERE,
        base::Bind(&ProfileOAuth2TokenServiceRequest::Core::StartOnUIThread,
                   this, account_id, scopes));
  }
}

void ProfileOAuth2TokenServiceRequest::Core::Stop() {
  DCHECK(owner_task_runner_->BelongsToCurrentThread());

  // Detaches |owner_| from this instance so |owner_| will be called back only
  // if |Stop()| has never been called.
  owner_ = NULL;
  if (content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
    StopOnUIThread();
  } else {
    content::BrowserThread::PostTask(
        content::BrowserThread::UI,
        FROM_HERE,
        base::Bind(&ProfileOAuth2TokenServiceRequest::Core::StopOnUIThread,
                   this));
  }
}

OAuth2TokenService::Request* ProfileOAuth2TokenServiceRequest::Core::request() {
  return request_.get();
}

void ProfileOAuth2TokenServiceRequest::Core::StopOnUIThread() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  request_.reset();
}

void ProfileOAuth2TokenServiceRequest::Core::StartOnUIThread(
    const std::string& account_id,
    const OAuth2TokenService::ScopeSet& scopes) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));

  ProfileOAuth2TokenService* service =
      ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
  DCHECK(service);
  SigninManagerBase* signin_manager =
      SigninManagerFactory::GetForProfile(profile_);
  DCHECK(signin_manager);
  std::string account_id_to_use =
      account_id.empty() ? signin_manager->GetAuthenticatedAccountId()
                         : account_id;
  request_.reset(
      service->StartRequest(account_id_to_use, scopes, this).release());
}

void ProfileOAuth2TokenServiceRequest::Core::OnGetTokenSuccess(
    const OAuth2TokenService::Request* request,
    const std::string& access_token,
    const base::Time& expiration_time) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  DCHECK_EQ(request_.get(), request);
  owner_task_runner_->PostTask(FROM_HERE, base::Bind(
      &ProfileOAuth2TokenServiceRequest::Core::InformOwnerOnGetTokenSuccess,
      this,
      access_token,
      expiration_time));
  request_.reset();
}

void ProfileOAuth2TokenServiceRequest::Core::OnGetTokenFailure(
    const OAuth2TokenService::Request* request,
    const GoogleServiceAuthError& error) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  DCHECK_EQ(request_.get(), request);
  owner_task_runner_->PostTask(FROM_HERE, base::Bind(
      &ProfileOAuth2TokenServiceRequest::Core::InformOwnerOnGetTokenFailure,
      this,
      error));
  request_.reset();
}

void ProfileOAuth2TokenServiceRequest::Core::InformOwnerOnGetTokenSuccess(
    std::string access_token,
    base::Time expiration_time) {
  DCHECK(owner_task_runner_->BelongsToCurrentThread());

  if (owner_)
    owner_->consumer_->OnGetTokenSuccess(owner_, access_token, expiration_time);
}

void ProfileOAuth2TokenServiceRequest::Core::InformOwnerOnGetTokenFailure(
    GoogleServiceAuthError error) {
  DCHECK(owner_task_runner_->BelongsToCurrentThread());

  if (owner_)
    owner_->consumer_->OnGetTokenFailure(owner_, error);
}

// static
ProfileOAuth2TokenServiceRequest*
    ProfileOAuth2TokenServiceRequest::CreateAndStart(
        Profile* profile,
        const std::string& account_id,
        const OAuth2TokenService::ScopeSet& scopes,
        OAuth2TokenService::Consumer* consumer) {
  return new ProfileOAuth2TokenServiceRequest(profile, account_id, scopes,
      consumer);
}

ProfileOAuth2TokenServiceRequest::ProfileOAuth2TokenServiceRequest(
    Profile* profile,
    const std::string& account_id,
    const OAuth2TokenService::ScopeSet& scopes,
    OAuth2TokenService::Consumer* consumer)
    : consumer_(consumer),
      core_(new Core(profile, this)) {
  core_->Start(account_id, scopes);
}

ProfileOAuth2TokenServiceRequest::~ProfileOAuth2TokenServiceRequest() {
  DCHECK(CalledOnValidThread());
  core_->Stop();
}

std::string ProfileOAuth2TokenServiceRequest::GetAccountId() const {
  return core_->request()->GetAccountId();
}


/* [<][>][^][v][top][bottom][index][help] */