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