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