android_profile_oauth2_token_service.cc revision ca12bfac764ba476d6cd062bf1dde12cc64c3f40
1efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris// Copyright 2013 The Chromium Authors. All rights reserved.
2efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris// Use of this source code is governed by a BSD-style license that can be
3efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris// found in the LICENSE file.
4efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris
51acb3f0c936b75afede6795288a745ce7343fa8dChristopher Ferris#include "chrome/browser/signin/android_profile_oauth2_token_service.h"
6efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris
7efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris#include "base/android/jni_android.h"
8efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris#include "base/android/jni_string.h"
9efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris#include "base/bind.h"
10efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris#include "base/logging.h"
11efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris#include "chrome/browser/signin/signin_manager.h"
12efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris#include "chrome/browser/signin/signin_manager_factory.h"
13efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris#include "chrome/browser/sync/profile_sync_service_android.h"
14efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris#include "content/public/browser/browser_thread.h"
15efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris#include "jni/AndroidProfileOAuth2TokenServiceHelper_jni.h"
16efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris
17efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferrisusing base::android::AttachCurrentThread;
18cc6cc088ba4077f5b6cfa3931a1737b03fc0446eChristopher Ferrisusing base::android::CheckException;
19cc6cc088ba4077f5b6cfa3931a1737b03fc0446eChristopher Ferrisusing base::android::ConvertJavaStringToUTF8;
20cc6cc088ba4077f5b6cfa3931a1737b03fc0446eChristopher Ferrisusing base::android::ConvertUTF8ToJavaString;
21efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferrisusing base::android::ScopedJavaLocalRef;
22efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferrisusing content::BrowserThread;
23efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris
24efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferrisnamespace {
25efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris
26efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferrisstd::string CombineScopes(const OAuth2TokenService::ScopeSet& scopes) {
27efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  // The Android AccountManager supports multiple scopes separated by a space:
28efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  // https://code.google.com/p/google-api-java-client/wiki/OAuth2#Android
29efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  std::string scope;
30efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  for (OAuth2TokenService::ScopeSet::const_iterator it = scopes.begin();
31efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris       it != scopes.end(); ++it) {
32efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris    if (!scope.empty())
33efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris      scope += " ";
34efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris    scope += *it;
35efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  }
36efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  return scope;
37efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris}
38efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris
39efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris}  // namespace
40fb2fafb9daf5b9f5119d5550a68ebdc3d0564b06Christopher Ferris
41fb2fafb9daf5b9f5119d5550a68ebdc3d0564b06Christopher FerrisAndroidProfileOAuth2TokenService::AndroidProfileOAuth2TokenService() {
42fb2fafb9daf5b9f5119d5550a68ebdc3d0564b06Christopher Ferris}
43efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris
44fb2fafb9daf5b9f5119d5550a68ebdc3d0564b06Christopher FerrisAndroidProfileOAuth2TokenService::~AndroidProfileOAuth2TokenService() {
45efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris}
46efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris
47efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferrisscoped_ptr<OAuth2TokenService::Request>
48efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris    AndroidProfileOAuth2TokenService::StartRequest(
49efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris        const OAuth2TokenService::ScopeSet& scopes,
50efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris        OAuth2TokenService::Consumer* consumer) {
51efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  const std::string& sync_username =
52efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris      SigninManagerFactory::GetForProfile(profile())->
53efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris          GetAuthenticatedUsername();
54efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
55efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  DCHECK(!sync_username.empty());
56efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  return StartRequestForUsername(sync_username, scopes, consumer);
57efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris}
58efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris
59efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferrisscoped_ptr<OAuth2TokenService::Request>
60efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris    AndroidProfileOAuth2TokenService::StartRequestForUsername(
61efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris        const std::string& username,
62efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris        const OAuth2TokenService::ScopeSet& scopes,
63efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris        OAuth2TokenService::Consumer* consumer) {
64efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
65efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris
66efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  scoped_ptr<RequestImpl> request(new RequestImpl(consumer));
67efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  FetchOAuth2Token(
68fb2fafb9daf5b9f5119d5550a68ebdc3d0564b06Christopher Ferris      username,
69fb2fafb9daf5b9f5119d5550a68ebdc3d0564b06Christopher Ferris      CombineScopes(scopes),
70fb2fafb9daf5b9f5119d5550a68ebdc3d0564b06Christopher Ferris      base::Bind(&RequestImpl::InformConsumer, request->AsWeakPtr()));
71efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  return request.PassAs<Request>();
72fb2fafb9daf5b9f5119d5550a68ebdc3d0564b06Christopher Ferris}
73fb2fafb9daf5b9f5119d5550a68ebdc3d0564b06Christopher Ferris
74fb2fafb9daf5b9f5119d5550a68ebdc3d0564b06Christopher Ferrisbool AndroidProfileOAuth2TokenService::RefreshTokenIsAvailable() {
75fb2fafb9daf5b9f5119d5550a68ebdc3d0564b06Christopher Ferris  SigninManagerBase* signin_manager =
76fb2fafb9daf5b9f5119d5550a68ebdc3d0564b06Christopher Ferris      SigninManagerFactory::GetForProfile(profile());
77fb2fafb9daf5b9f5119d5550a68ebdc3d0564b06Christopher Ferris  return !signin_manager->GetAuthenticatedUsername().empty();
78fb2fafb9daf5b9f5119d5550a68ebdc3d0564b06Christopher Ferris}
79fb2fafb9daf5b9f5119d5550a68ebdc3d0564b06Christopher Ferris
80fb2fafb9daf5b9f5119d5550a68ebdc3d0564b06Christopher Ferrisvoid AndroidProfileOAuth2TokenService::InvalidateToken(
81efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris    const ScopeSet& scopes,
82efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris    const std::string& invalid_token) {
83efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  OAuth2TokenService::InvalidateToken(scopes, invalid_token);
84efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris
85efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  JNIEnv* env = AttachCurrentThread();
86efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  ScopedJavaLocalRef<jstring> j_invalid_token =
87efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris      ConvertUTF8ToJavaString(env, invalid_token);
88efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  Java_AndroidProfileOAuth2TokenServiceHelper_invalidateOAuth2AuthToken(
89efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris      env, base::android::GetApplicationContext(),
90efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris      j_invalid_token.obj());
91efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris}
92efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris
93efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferrisvoid AndroidProfileOAuth2TokenService::FetchOAuth2Token(
94efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris    const std::string& username,
95efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris    const std::string& scope,
96efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris    const FetchOAuth2TokenCallback& callback) {
97efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  JNIEnv* env = AttachCurrentThread();
98efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  ScopedJavaLocalRef<jstring> j_username =
99efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris      ConvertUTF8ToJavaString(env, username);
100efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  ScopedJavaLocalRef<jstring> j_scope =
101efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris      ConvertUTF8ToJavaString(env, scope);
102efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris
103efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  // Allocate a copy of the callback on the heap, because the callback
104efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  // needs to be passed through JNI as an int.
105efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  // It will be passed back to OAuth2TokenFetched(), where it will be freed.
106efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  scoped_ptr<FetchOAuth2TokenCallback> heap_callback(
107efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris      new FetchOAuth2TokenCallback(callback));
108efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris
109efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  // Call into Java to get a new token.
110efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  Java_AndroidProfileOAuth2TokenServiceHelper_getOAuth2AuthToken(
111efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris      env, base::android::GetApplicationContext(),
112efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris      j_username.obj(),
113efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris      j_scope.obj(),
114efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris      reinterpret_cast<int>(heap_callback.release()));
115efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris}
116efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris
117efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris// Called from Java when fetching of an OAuth2 token is finished. The
118efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris// |authToken| param is only valid when |result| is true.
119efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferrisvoid OAuth2TokenFetched(JNIEnv* env, jclass clazz,
120efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris    jstring authToken,
121efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris    jboolean result,
122efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris    jint nativeCallback) {
123efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  std::string token = ConvertJavaStringToUTF8(env, authToken);
124efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  scoped_ptr<AndroidProfileOAuth2TokenService::FetchOAuth2TokenCallback>
125efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris      heap_callback(
126efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris          reinterpret_cast<
127efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris              AndroidProfileOAuth2TokenService::FetchOAuth2TokenCallback*>(
128efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris                  nativeCallback));
129efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  GoogleServiceAuthError err(result ?
130efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris                             GoogleServiceAuthError::NONE :
131efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris                             GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
132efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  heap_callback->Run(err, token, base::Time());
133efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris}
134efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris
135efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris// static
136efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferrisbool AndroidProfileOAuth2TokenService::Register(JNIEnv* env) {
137efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris  return RegisterNativesImpl(env);
138efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris}
139efb75a0b84fed700173700a2e4fee153ba491b32Christopher Ferris