android_profile_oauth2_token_service.cc revision ca12bfac764ba476d6cd062bf1dde12cc64c3f40
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"
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/android/jni_string.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h"
107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/logging.h"
117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/signin/signin_manager.h"
127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/signin/signin_manager_factory.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/sync/profile_sync_service_android.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "jni/AndroidProfileOAuth2TokenServiceHelper_jni.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing base::android::AttachCurrentThread;
187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing base::android::CheckException;
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
397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}  // namespace
407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
41ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochAndroidProfileOAuth2TokenService::AndroidProfileOAuth2TokenService() {
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)AndroidProfileOAuth2TokenService::~AndroidProfileOAuth2TokenService() {
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)scoped_ptr<OAuth2TokenService::Request>
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    AndroidProfileOAuth2TokenService::StartRequest(
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        const OAuth2TokenService::ScopeSet& scopes,
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        OAuth2TokenService::Consumer* consumer) {
517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string& sync_username =
527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      SigninManagerFactory::GetForProfile(profile())->
537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          GetAuthenticatedUsername();
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(!sync_username.empty());
567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return StartRequestForUsername(sync_username, scopes, consumer);
577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochscoped_ptr<OAuth2TokenService::Request>
607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    AndroidProfileOAuth2TokenService::StartRequestForUsername(
617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        const std::string& username,
627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        const OAuth2TokenService::ScopeSet& scopes,
637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        OAuth2TokenService::Consumer* consumer) {
647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<RequestImpl> request(new RequestImpl(consumer));
677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  FetchOAuth2Token(
687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      username,
697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CombineScopes(scopes),
707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      base::Bind(&RequestImpl::InformConsumer, request->AsWeakPtr()));
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return request.PassAs<Request>();
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool AndroidProfileOAuth2TokenService::RefreshTokenIsAvailable() {
757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  SigninManagerBase* signin_manager =
767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      SigninManagerFactory::GetForProfile(profile());
777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return !signin_manager->GetAuthenticatedUsername().empty();
787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AndroidProfileOAuth2TokenService::InvalidateToken(
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ScopeSet& scopes,
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& invalid_token) {
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  OAuth2TokenService::InvalidateToken(scopes, invalid_token);
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  JNIEnv* env = AttachCurrentThread();
867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedJavaLocalRef<jstring> j_invalid_token =
877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      ConvertUTF8ToJavaString(env, invalid_token);
887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Java_AndroidProfileOAuth2TokenServiceHelper_invalidateOAuth2AuthToken(
897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      env, base::android::GetApplicationContext(),
907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      j_invalid_token.obj());
917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid AndroidProfileOAuth2TokenService::FetchOAuth2Token(
947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const std::string& username,
957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const std::string& scope,
967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const FetchOAuth2TokenCallback& callback) {
977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  JNIEnv* env = AttachCurrentThread();
987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedJavaLocalRef<jstring> j_username =
997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      ConvertUTF8ToJavaString(env, username);
1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedJavaLocalRef<jstring> j_scope =
1017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      ConvertUTF8ToJavaString(env, scope);
1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Allocate a copy of the callback on the heap, because the callback
1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // needs to be passed through JNI as an int.
1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // It will be passed back to OAuth2TokenFetched(), where it will be freed.
1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_ptr<FetchOAuth2TokenCallback> heap_callback(
1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      new FetchOAuth2TokenCallback(callback));
1087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Call into Java to get a new token.
1107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Java_AndroidProfileOAuth2TokenServiceHelper_getOAuth2AuthToken(
1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      env, base::android::GetApplicationContext(),
1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      j_username.obj(),
1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      j_scope.obj(),
1147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      reinterpret_cast<int>(heap_callback.release()));
1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Called from Java when fetching of an OAuth2 token is finished. The
1187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// |authToken| param is only valid when |result| is true.
1197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid OAuth2TokenFetched(JNIEnv* env, jclass clazz,
1207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    jstring authToken,
1217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    jboolean result,
1227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    jint nativeCallback) {
1237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string token = ConvertJavaStringToUTF8(env, authToken);
1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_ptr<AndroidProfileOAuth2TokenService::FetchOAuth2TokenCallback>
1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      heap_callback(
1267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          reinterpret_cast<
1277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              AndroidProfileOAuth2TokenService::FetchOAuth2TokenCallback*>(
1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                  nativeCallback));
1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  GoogleServiceAuthError err(result ?
1307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                             GoogleServiceAuthError::NONE :
1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                             GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
1327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  heap_callback->Run(err, token, base::Time());
1337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// static
1367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool AndroidProfileOAuth2TokenService::Register(JNIEnv* env) {
1377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return RegisterNativesImpl(env);
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
139