android_profile_oauth2_token_service.cc revision 3551c9c881056c480085172ff9840cab31610854
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 17using base::android::AttachCurrentThread; 18using base::android::CheckException; 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 57scoped_ptr<OAuth2TokenService::Request> 58 AndroidProfileOAuth2TokenService::StartRequestForUsername( 59 const std::string& username, 60 const OAuth2TokenService::ScopeSet& scopes, 61 OAuth2TokenService::Consumer* consumer) { 62 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 63 64 scoped_ptr<RequestImpl> request(new RequestImpl(consumer)); 65 FetchOAuth2TokenWithUsername(request.get(), username, scopes); 66 return request.PassAs<Request>(); 67} 68 69bool AndroidProfileOAuth2TokenService::RefreshTokenIsAvailable() { 70 SigninManagerBase* signin_manager = 71 SigninManagerFactory::GetForProfile(profile()); 72 return !signin_manager->GetAuthenticatedUsername().empty(); 73} 74 75void AndroidProfileOAuth2TokenService::InvalidateToken( 76 const ScopeSet& scopes, 77 const std::string& invalid_token) { 78 OAuth2TokenService::InvalidateToken(scopes, invalid_token); 79 80 JNIEnv* env = AttachCurrentThread(); 81 ScopedJavaLocalRef<jstring> j_invalid_token = 82 ConvertUTF8ToJavaString(env, invalid_token); 83 Java_AndroidProfileOAuth2TokenServiceHelper_invalidateOAuth2AuthToken( 84 env, base::android::GetApplicationContext(), 85 j_invalid_token.obj()); 86} 87 88void AndroidProfileOAuth2TokenService::FetchOAuth2Token( 89 RequestImpl* request, 90 net::URLRequestContextGetter* getter, 91 const std::string& client_id, 92 const std::string& client_secret, 93 const OAuth2TokenService::ScopeSet& scopes) { 94 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 95 std::string username = SigninManagerFactory::GetForProfile(profile())-> 96 GetAuthenticatedUsername(); 97 DCHECK(!username.empty()); 98 // Just ignore client_id, getter, etc since we don't use them on Android. 99 FetchOAuth2TokenWithUsername(request, username, scopes); 100} 101 102void AndroidProfileOAuth2TokenService::FetchOAuth2TokenWithUsername( 103 RequestImpl* request, 104 const std::string& username, 105 const OAuth2TokenService::ScopeSet& scopes) { 106 JNIEnv* env = AttachCurrentThread(); 107 std::string scope = CombineScopes(scopes); 108 ScopedJavaLocalRef<jstring> j_username = 109 ConvertUTF8ToJavaString(env, username); 110 ScopedJavaLocalRef<jstring> j_scope = 111 ConvertUTF8ToJavaString(env, scope); 112 113 // Allocate a copy of the request WeakPtr on the heap, because the object 114 // needs to be passed through JNI as an int. 115 // It will be passed back to OAuth2TokenFetched(), where it will be freed. 116 scoped_ptr<FetchOAuth2TokenCallback> heap_callback( 117 new FetchOAuth2TokenCallback(base::Bind(&RequestImpl::InformConsumer, 118 request->AsWeakPtr()))); 119 120 // Call into Java to get a new token. 121 Java_AndroidProfileOAuth2TokenServiceHelper_getOAuth2AuthToken( 122 env, base::android::GetApplicationContext(), 123 j_username.obj(), 124 j_scope.obj(), 125 reinterpret_cast<int>(heap_callback.release())); 126} 127 128// Called from Java when fetching of an OAuth2 token is finished. The 129// |authToken| param is only valid when |result| is true. 130void OAuth2TokenFetched(JNIEnv* env, jclass clazz, 131 jstring authToken, 132 jboolean result, 133 jint nativeCallback) { 134 std::string token = ConvertJavaStringToUTF8(env, authToken); 135 scoped_ptr<FetchOAuth2TokenCallback> heap_callback( 136 reinterpret_cast<FetchOAuth2TokenCallback*>(nativeCallback)); 137 GoogleServiceAuthError err(result ? 138 GoogleServiceAuthError::NONE : 139 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); 140 heap_callback->Run(err, token, base::Time()); 141} 142 143// static 144bool AndroidProfileOAuth2TokenService::Register(JNIEnv* env) { 145 return RegisterNativesImpl(env); 146} 147