android_profile_oauth2_token_service.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/signin/android_profile_oauth2_token_service.h" 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/android/jni_android.h" 868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/android/jni_array.h" 97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/android/jni_string.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h" 117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/logging.h" 127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/signin/signin_manager.h" 137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/signin/signin_manager_factory.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/sync/profile_sync_service_android.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "jni/AndroidProfileOAuth2TokenServiceHelper_jni.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing base::android::AttachCurrentThread; 197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing base::android::ConvertJavaStringToUTF8; 207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing base::android::ConvertUTF8ToJavaString; 217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing base::android::ScopedJavaLocalRef; 227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing content::BrowserThread; 237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace { 257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstd::string CombineScopes(const OAuth2TokenService::ScopeSet& scopes) { 277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // The Android AccountManager supports multiple scopes separated by a space: 287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // https://code.google.com/p/google-api-java-client/wiki/OAuth2#Android 297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::string scope; 307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for (OAuth2TokenService::ScopeSet::const_iterator it = scopes.begin(); 317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch it != scopes.end(); ++it) { 327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!scope.empty()) 337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch scope += " "; 347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch scope += *it; 357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return scope; 377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Callback from FetchOAuth2TokenWithUsername(). 403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Arguments: 413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// - the error, or NONE if the token fetch was successful. 423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// - the OAuth2 access token. 433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// - the expiry time of the token (may be null, indicating that the expiry 443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// time is unknown. 453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)typedef base::Callback<void( 463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const GoogleServiceAuthError&, const std::string&, const base::Time&)> 473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) FetchOAuth2TokenCallback; 483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} // namespace 507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 51ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochAndroidProfileOAuth2TokenService::AndroidProfileOAuth2TokenService() { 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)AndroidProfileOAuth2TokenService::~AndroidProfileOAuth2TokenService() { 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool AndroidProfileOAuth2TokenService::RefreshTokenIsAvailable( 5868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string& account_id) { 5968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) JNIEnv* env = AttachCurrentThread(); 6068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ScopedJavaLocalRef<jstring> j_account_id = 6168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ConvertUTF8ToJavaString(env, account_id); 6268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) jboolean refresh_token_is_available = 6368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Java_AndroidProfileOAuth2TokenServiceHelper_hasOAuth2RefreshToken( 6468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) env, base::android::GetApplicationContext(), 6568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) j_account_id.obj()); 6668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return refresh_token_is_available != JNI_FALSE; 677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)std::vector<std::string> AndroidProfileOAuth2TokenService::GetAccounts() { 7068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::vector<std::string> accounts; 717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch JNIEnv* env = AttachCurrentThread(); 7268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ScopedJavaLocalRef<jobjectArray> j_accounts = 7368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Java_AndroidProfileOAuth2TokenServiceHelper_getAccounts( 7468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) env, base::android::GetApplicationContext()); 7568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // TODO(fgorski): We may decide to filter out some of the accounts. 7668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::android::AppendJavaStringArrayToStringVector(env, 7768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) j_accounts.obj(), 7868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) &accounts); 7968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return accounts; 807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid AndroidProfileOAuth2TokenService::FetchOAuth2Token( 833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RequestImpl* request, 8468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string& account_id, 853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) net::URLRequestContextGetter* getter, 863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& client_id, 873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& client_secret, 883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const OAuth2TokenService::ScopeSet& scopes) { 893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 9068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) DCHECK(!account_id.empty()); 913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch JNIEnv* env = AttachCurrentThread(); 933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::string scope = CombineScopes(scopes); 947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ScopedJavaLocalRef<jstring> j_username = 9568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ConvertUTF8ToJavaString(env, account_id); 967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ScopedJavaLocalRef<jstring> j_scope = 977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ConvertUTF8ToJavaString(env, scope); 987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Allocate a copy of the request WeakPtr on the heap, because the object 1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // needs to be passed through JNI as an int. 1017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // It will be passed back to OAuth2TokenFetched(), where it will be freed. 1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch scoped_ptr<FetchOAuth2TokenCallback> heap_callback( 1033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) new FetchOAuth2TokenCallback(base::Bind(&RequestImpl::InformConsumer, 1043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) request->AsWeakPtr()))); 1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Call into Java to get a new token. 1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Java_AndroidProfileOAuth2TokenServiceHelper_getOAuth2AuthToken( 1087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch env, base::android::GetApplicationContext(), 1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch j_username.obj(), 1107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch j_scope.obj(), 1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch reinterpret_cast<int>(heap_callback.release())); 1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 11468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void AndroidProfileOAuth2TokenService::InvalidateOAuth2Token( 11568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string& account_id, 11668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string& client_id, 11768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const ScopeSet& scopes, 11868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string& access_token) { 11968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) OAuth2TokenService::InvalidateOAuth2Token(account_id, 12068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) client_id, 12168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) scopes, 12268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) access_token); 12368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 12468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) JNIEnv* env = AttachCurrentThread(); 12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ScopedJavaLocalRef<jstring> j_access_token = 12668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ConvertUTF8ToJavaString(env, access_token); 12768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Java_AndroidProfileOAuth2TokenServiceHelper_invalidateOAuth2AuthToken( 12868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) env, base::android::GetApplicationContext(), 12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) j_access_token.obj()); 13068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 13168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 1327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Called from Java when fetching of an OAuth2 token is finished. The 1337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// |authToken| param is only valid when |result| is true. 1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid OAuth2TokenFetched(JNIEnv* env, jclass clazz, 1357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch jstring authToken, 1367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch jboolean result, 1377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch jint nativeCallback) { 1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::string token = ConvertJavaStringToUTF8(env, authToken); 1393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<FetchOAuth2TokenCallback> heap_callback( 1403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) reinterpret_cast<FetchOAuth2TokenCallback*>(nativeCallback)); 1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch GoogleServiceAuthError err(result ? 1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch GoogleServiceAuthError::NONE : 1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); 1447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch heap_callback->Run(err, token, base::Time()); 1457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// static 1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool AndroidProfileOAuth2TokenService::Register(JNIEnv* env) { 1497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return RegisterNativesImpl(env); 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 151