android_profile_oauth2_token_service.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
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_array.h" 9#include "base/android/jni_string.h" 10#include "base/bind.h" 11#include "base/logging.h" 12#include "chrome/browser/signin/signin_manager.h" 13#include "chrome/browser/signin/signin_manager_factory.h" 14#include "chrome/browser/sync/profile_sync_service_android.h" 15#include "content/public/browser/browser_thread.h" 16#include "jni/AndroidProfileOAuth2TokenServiceHelper_jni.h" 17 18using base::android::AttachCurrentThread; 19using base::android::ConvertJavaStringToUTF8; 20using base::android::ConvertUTF8ToJavaString; 21using base::android::ScopedJavaLocalRef; 22using content::BrowserThread; 23 24namespace { 25 26std::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// Callback from FetchOAuth2TokenWithUsername(). 40// Arguments: 41// - the error, or NONE if the token fetch was successful. 42// - the OAuth2 access token. 43// - the expiry time of the token (may be null, indicating that the expiry 44// time is unknown. 45typedef base::Callback<void( 46 const GoogleServiceAuthError&, const std::string&, const base::Time&)> 47 FetchOAuth2TokenCallback; 48 49} // namespace 50 51AndroidProfileOAuth2TokenService::AndroidProfileOAuth2TokenService() { 52} 53 54AndroidProfileOAuth2TokenService::~AndroidProfileOAuth2TokenService() { 55} 56 57bool AndroidProfileOAuth2TokenService::RefreshTokenIsAvailable( 58 const std::string& account_id) { 59 JNIEnv* env = AttachCurrentThread(); 60 ScopedJavaLocalRef<jstring> j_account_id = 61 ConvertUTF8ToJavaString(env, account_id); 62 jboolean refresh_token_is_available = 63 Java_AndroidProfileOAuth2TokenServiceHelper_hasOAuth2RefreshToken( 64 env, base::android::GetApplicationContext(), 65 j_account_id.obj()); 66 return refresh_token_is_available != JNI_FALSE; 67} 68 69std::vector<std::string> AndroidProfileOAuth2TokenService::GetAccounts() { 70 std::vector<std::string> accounts; 71 JNIEnv* env = AttachCurrentThread(); 72 ScopedJavaLocalRef<jobjectArray> j_accounts = 73 Java_AndroidProfileOAuth2TokenServiceHelper_getAccounts( 74 env, base::android::GetApplicationContext()); 75 // TODO(fgorski): We may decide to filter out some of the accounts. 76 base::android::AppendJavaStringArrayToStringVector(env, 77 j_accounts.obj(), 78 &accounts); 79 return accounts; 80} 81 82void AndroidProfileOAuth2TokenService::FetchOAuth2Token( 83 RequestImpl* request, 84 const std::string& account_id, 85 net::URLRequestContextGetter* getter, 86 const std::string& client_id, 87 const std::string& client_secret, 88 const OAuth2TokenService::ScopeSet& scopes) { 89 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 90 DCHECK(!account_id.empty()); 91 92 JNIEnv* env = AttachCurrentThread(); 93 std::string scope = CombineScopes(scopes); 94 ScopedJavaLocalRef<jstring> j_username = 95 ConvertUTF8ToJavaString(env, account_id); 96 ScopedJavaLocalRef<jstring> j_scope = 97 ConvertUTF8ToJavaString(env, scope); 98 99 // Allocate a copy of the request WeakPtr on the heap, because the object 100 // needs to be passed through JNI as an int. 101 // It will be passed back to OAuth2TokenFetched(), where it will be freed. 102 scoped_ptr<FetchOAuth2TokenCallback> heap_callback( 103 new FetchOAuth2TokenCallback(base::Bind(&RequestImpl::InformConsumer, 104 request->AsWeakPtr()))); 105 106 // Call into Java to get a new token. 107 Java_AndroidProfileOAuth2TokenServiceHelper_getOAuth2AuthToken( 108 env, base::android::GetApplicationContext(), 109 j_username.obj(), 110 j_scope.obj(), 111 reinterpret_cast<int>(heap_callback.release())); 112} 113 114void AndroidProfileOAuth2TokenService::InvalidateOAuth2Token( 115 const std::string& account_id, 116 const std::string& client_id, 117 const ScopeSet& scopes, 118 const std::string& access_token) { 119 OAuth2TokenService::InvalidateOAuth2Token(account_id, 120 client_id, 121 scopes, 122 access_token); 123 124 JNIEnv* env = AttachCurrentThread(); 125 ScopedJavaLocalRef<jstring> j_access_token = 126 ConvertUTF8ToJavaString(env, access_token); 127 Java_AndroidProfileOAuth2TokenServiceHelper_invalidateOAuth2AuthToken( 128 env, base::android::GetApplicationContext(), 129 j_access_token.obj()); 130} 131 132// Called from Java when fetching of an OAuth2 token is finished. The 133// |authToken| param is only valid when |result| is true. 134void OAuth2TokenFetched(JNIEnv* env, jclass clazz, 135 jstring authToken, 136 jboolean result, 137 jint nativeCallback) { 138 std::string token = ConvertJavaStringToUTF8(env, authToken); 139 scoped_ptr<FetchOAuth2TokenCallback> heap_callback( 140 reinterpret_cast<FetchOAuth2TokenCallback*>(nativeCallback)); 141 GoogleServiceAuthError err(result ? 142 GoogleServiceAuthError::NONE : 143 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); 144 heap_callback->Run(err, token, base::Time()); 145} 146 147// static 148bool AndroidProfileOAuth2TokenService::Register(JNIEnv* env) { 149 return RegisterNativesImpl(env); 150} 151