Home | History | Annotate | Download | only in signin
      1 // Copyright 2013 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/signin/android_profile_oauth2_token_service.h"
      6 
      7 #include "base/android/jni_android.h"
      8 #include "base/android/jni_string.h"
      9 #include "base/bind.h"
     10 #include "base/logging.h"
     11 #include "chrome/browser/signin/signin_manager.h"
     12 #include "chrome/browser/signin/signin_manager_factory.h"
     13 #include "chrome/browser/sync/profile_sync_service_android.h"
     14 #include "content/public/browser/browser_thread.h"
     15 #include "jni/AndroidProfileOAuth2TokenServiceHelper_jni.h"
     16 
     17 using base::android::AttachCurrentThread;
     18 using base::android::CheckException;
     19 using base::android::ConvertJavaStringToUTF8;
     20 using base::android::ConvertUTF8ToJavaString;
     21 using base::android::ScopedJavaLocalRef;
     22 using content::BrowserThread;
     23 
     24 namespace {
     25 
     26 std::string CombineScopes(const OAuth2TokenService::ScopeSet& scopes) {
     27   // The Android AccountManager supports multiple scopes separated by a space:
     28   // https://code.google.com/p/google-api-java-client/wiki/OAuth2#Android
     29   std::string scope;
     30   for (OAuth2TokenService::ScopeSet::const_iterator it = scopes.begin();
     31        it != scopes.end(); ++it) {
     32     if (!scope.empty())
     33       scope += " ";
     34     scope += *it;
     35   }
     36   return scope;
     37 }
     38 
     39 }  // namespace
     40 
     41 AndroidProfileOAuth2TokenService::AndroidProfileOAuth2TokenService() {
     42 }
     43 
     44 AndroidProfileOAuth2TokenService::~AndroidProfileOAuth2TokenService() {
     45 }
     46 
     47 scoped_ptr<OAuth2TokenService::Request>
     48     AndroidProfileOAuth2TokenService::StartRequest(
     49         const OAuth2TokenService::ScopeSet& scopes,
     50         OAuth2TokenService::Consumer* consumer) {
     51   const std::string& sync_username =
     52       SigninManagerFactory::GetForProfile(profile())->
     53           GetAuthenticatedUsername();
     54   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
     55   DCHECK(!sync_username.empty());
     56   return StartRequestForUsername(sync_username, scopes, consumer);
     57 }
     58 
     59 scoped_ptr<OAuth2TokenService::Request>
     60     AndroidProfileOAuth2TokenService::StartRequestForUsername(
     61         const std::string& username,
     62         const OAuth2TokenService::ScopeSet& scopes,
     63         OAuth2TokenService::Consumer* consumer) {
     64   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
     65 
     66   scoped_ptr<RequestImpl> request(new RequestImpl(consumer));
     67   FetchOAuth2Token(
     68       username,
     69       CombineScopes(scopes),
     70       base::Bind(&RequestImpl::InformConsumer, request->AsWeakPtr()));
     71   return request.PassAs<Request>();
     72 }
     73 
     74 bool AndroidProfileOAuth2TokenService::RefreshTokenIsAvailable() {
     75   SigninManagerBase* signin_manager =
     76       SigninManagerFactory::GetForProfile(profile());
     77   return !signin_manager->GetAuthenticatedUsername().empty();
     78 }
     79 
     80 void AndroidProfileOAuth2TokenService::InvalidateToken(
     81     const ScopeSet& scopes,
     82     const std::string& invalid_token) {
     83   OAuth2TokenService::InvalidateToken(scopes, invalid_token);
     84 
     85   JNIEnv* env = AttachCurrentThread();
     86   ScopedJavaLocalRef<jstring> j_invalid_token =
     87       ConvertUTF8ToJavaString(env, invalid_token);
     88   Java_AndroidProfileOAuth2TokenServiceHelper_invalidateOAuth2AuthToken(
     89       env, base::android::GetApplicationContext(),
     90       j_invalid_token.obj());
     91 }
     92 
     93 void AndroidProfileOAuth2TokenService::FetchOAuth2Token(
     94     const std::string& username,
     95     const std::string& scope,
     96     const FetchOAuth2TokenCallback& callback) {
     97   JNIEnv* env = AttachCurrentThread();
     98   ScopedJavaLocalRef<jstring> j_username =
     99       ConvertUTF8ToJavaString(env, username);
    100   ScopedJavaLocalRef<jstring> j_scope =
    101       ConvertUTF8ToJavaString(env, scope);
    102 
    103   // Allocate a copy of the callback on the heap, because the callback
    104   // needs to be passed through JNI as an int.
    105   // It will be passed back to OAuth2TokenFetched(), where it will be freed.
    106   scoped_ptr<FetchOAuth2TokenCallback> heap_callback(
    107       new FetchOAuth2TokenCallback(callback));
    108 
    109   // Call into Java to get a new token.
    110   Java_AndroidProfileOAuth2TokenServiceHelper_getOAuth2AuthToken(
    111       env, base::android::GetApplicationContext(),
    112       j_username.obj(),
    113       j_scope.obj(),
    114       reinterpret_cast<int>(heap_callback.release()));
    115 }
    116 
    117 // Called from Java when fetching of an OAuth2 token is finished. The
    118 // |authToken| param is only valid when |result| is true.
    119 void OAuth2TokenFetched(JNIEnv* env, jclass clazz,
    120     jstring authToken,
    121     jboolean result,
    122     jint nativeCallback) {
    123   std::string token = ConvertJavaStringToUTF8(env, authToken);
    124   scoped_ptr<AndroidProfileOAuth2TokenService::FetchOAuth2TokenCallback>
    125       heap_callback(
    126           reinterpret_cast<
    127               AndroidProfileOAuth2TokenService::FetchOAuth2TokenCallback*>(
    128                   nativeCallback));
    129   // Android does not provide enough information to know if the credentials are
    130   // wrong, so assume any error is transient by using CONNECTION_FAILED.
    131   GoogleServiceAuthError err(result ?
    132                              GoogleServiceAuthError::NONE :
    133                              GoogleServiceAuthError::CONNECTION_FAILED);
    134   heap_callback->Run(err, token, base::Time());
    135 }
    136 
    137 // static
    138 bool AndroidProfileOAuth2TokenService::Register(JNIEnv* env) {
    139   return RegisterNativesImpl(env);
    140 }
    141