android_profile_oauth2_token_service.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
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)#include "net/url_request/url_request_context_getter.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing base::android::AttachCurrentThread;
197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing base::android::CheckException;
207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing base::android::ConvertJavaStringToUTF8;
217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing base::android::ConvertUTF8ToJavaString;
227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing base::android::ScopedJavaLocalRef;
237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing content::BrowserThread;
247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace {
267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstd::string CombineScopes(const OAuth2TokenService::ScopeSet& scopes) {
287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // The Android AccountManager supports multiple scopes separated by a space:
297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // https://code.google.com/p/google-api-java-client/wiki/OAuth2#Android
307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string scope;
317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  for (OAuth2TokenService::ScopeSet::const_iterator it = scopes.begin();
327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch       it != scopes.end(); ++it) {
337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (!scope.empty())
347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      scope += " ";
357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    scope += *it;
367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return scope;
387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}  // namespace
417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)AndroidProfileOAuth2TokenService::AndroidProfileOAuth2TokenService(
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    net::URLRequestContextGetter* getter)
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : ProfileOAuth2TokenService(getter) {
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)AndroidProfileOAuth2TokenService::~AndroidProfileOAuth2TokenService() {
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)scoped_ptr<OAuth2TokenService::Request>
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    AndroidProfileOAuth2TokenService::StartRequest(
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        const OAuth2TokenService::ScopeSet& scopes,
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        OAuth2TokenService::Consumer* consumer) {
547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::string& sync_username =
557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      SigninManagerFactory::GetForProfile(profile())->
567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          GetAuthenticatedUsername();
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(!sync_username.empty());
597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return StartRequestForUsername(sync_username, scopes, consumer);
607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochscoped_ptr<OAuth2TokenService::Request>
637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    AndroidProfileOAuth2TokenService::StartRequestForUsername(
647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        const std::string& username,
657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        const OAuth2TokenService::ScopeSet& scopes,
667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        OAuth2TokenService::Consumer* consumer) {
677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<RequestImpl> request(new RequestImpl(consumer));
707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  FetchOAuth2Token(
717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      username,
727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CombineScopes(scopes),
737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      base::Bind(&RequestImpl::InformConsumer, request->AsWeakPtr()));
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return request.PassAs<Request>();
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool AndroidProfileOAuth2TokenService::RefreshTokenIsAvailable() {
787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  SigninManagerBase* signin_manager =
797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      SigninManagerFactory::GetForProfile(profile());
807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return !signin_manager->GetAuthenticatedUsername().empty();
817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AndroidProfileOAuth2TokenService::InvalidateToken(
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ScopeSet& scopes,
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& invalid_token) {
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  OAuth2TokenService::InvalidateToken(scopes, invalid_token);
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  JNIEnv* env = AttachCurrentThread();
897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedJavaLocalRef<jstring> j_invalid_token =
907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      ConvertUTF8ToJavaString(env, invalid_token);
917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Java_AndroidProfileOAuth2TokenServiceHelper_invalidateOAuth2AuthToken(
927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      env, base::android::GetApplicationContext(),
937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      j_invalid_token.obj());
947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid AndroidProfileOAuth2TokenService::FetchOAuth2Token(
977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const std::string& username,
987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const std::string& scope,
997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const FetchOAuth2TokenCallback& callback) {
1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  JNIEnv* env = AttachCurrentThread();
1017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedJavaLocalRef<jstring> j_username =
1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      ConvertUTF8ToJavaString(env, username);
1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ScopedJavaLocalRef<jstring> j_scope =
1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      ConvertUTF8ToJavaString(env, scope);
1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Allocate a copy of the callback on the heap, because the callback
1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // needs to be passed through JNI as an int.
1087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // It will be passed back to OAuth2TokenFetched(), where it will be freed.
1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_ptr<FetchOAuth2TokenCallback> heap_callback(
1107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      new FetchOAuth2TokenCallback(callback));
1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Call into Java to get a new token.
1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Java_AndroidProfileOAuth2TokenServiceHelper_getOAuth2AuthToken(
1147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      env, base::android::GetApplicationContext(),
1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      j_username.obj(),
1167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      j_scope.obj(),
1177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      reinterpret_cast<int>(heap_callback.release()));
1187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Called from Java when fetching of an OAuth2 token is finished. The
1217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// |authToken| param is only valid when |result| is true.
1227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid OAuth2TokenFetched(JNIEnv* env, jclass clazz,
1237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    jstring authToken,
1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    jboolean result,
1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    jint nativeCallback) {
1267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string token = ConvertJavaStringToUTF8(env, authToken);
1277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_ptr<AndroidProfileOAuth2TokenService::FetchOAuth2TokenCallback>
1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      heap_callback(
1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          reinterpret_cast<
1307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              AndroidProfileOAuth2TokenService::FetchOAuth2TokenCallback*>(
1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                  nativeCallback));
1327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  GoogleServiceAuthError err(result ?
1337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                             GoogleServiceAuthError::NONE :
1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                             GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
1357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  heap_callback->Run(err, token, base::Time());
1367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// static
1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool AndroidProfileOAuth2TokenService::Register(JNIEnv* env) {
1407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return RegisterNativesImpl(env);
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
142