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"
124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/profiles/profile_android.h"
134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/sync/profile_sync_service_android.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "google_apis/gaia/oauth2_access_token_fetcher.h"
174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "jni/OAuth2TokenService_jni.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochusing base::android::AttachCurrentThread;
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
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Callback from FetchOAuth2TokenWithUsername().
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Arguments:
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// - the error, or NONE if the token fetch was successful.
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// - the OAuth2 access token.
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// - the expiry time of the token (may be null, indicating that the expiry
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//   time is unknown.
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitypedef base::Callback<void(
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const GoogleServiceAuthError&, const std::string&, const base::Time&)>
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        FetchOAuth2TokenCallback;
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass AndroidAccessTokenFetcher : public OAuth2AccessTokenFetcher {
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public:
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  AndroidAccessTokenFetcher(OAuth2AccessTokenConsumer* consumer,
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            const std::string& account_id);
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual ~AndroidAccessTokenFetcher();
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Overrides from OAuth2AccessTokenFetcher:
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void Start(const std::string& client_id,
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     const std::string& client_secret,
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     const std::vector<std::string>& scopes) OVERRIDE;
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void CancelRequest() OVERRIDE;
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Handles an access token response.
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void OnAccessTokenResponse(const GoogleServiceAuthError& error,
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             const std::string& access_token,
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             const base::Time& expiration_time);
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private:
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string CombineScopes(const std::vector<std::string>& scopes);
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::WeakPtrFactory<AndroidAccessTokenFetcher> weak_factory_;
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string account_id_;
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool request_was_cancelled_;
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DISALLOW_COPY_AND_ASSIGN(AndroidAccessTokenFetcher);
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciAndroidAccessTokenFetcher::AndroidAccessTokenFetcher(
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    OAuth2AccessTokenConsumer* consumer,
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::string& account_id)
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    : OAuth2AccessTokenFetcher(consumer),
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      weak_factory_(this),
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      account_id_(account_id),
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      request_was_cancelled_(false) {
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciAndroidAccessTokenFetcher::~AndroidAccessTokenFetcher() {}
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AndroidAccessTokenFetcher::Start(const std::string& client_id,
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                      const std::string& client_secret,
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                      const std::vector<std::string>& scopes) {
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  JNIEnv* env = AttachCurrentThread();
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string scope = CombineScopes(scopes);
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ScopedJavaLocalRef<jstring> j_username =
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ConvertUTF8ToJavaString(env, account_id_);
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ScopedJavaLocalRef<jstring> j_scope =
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ConvertUTF8ToJavaString(env, scope);
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<FetchOAuth2TokenCallback> heap_callback(
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new FetchOAuth2TokenCallback(
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          base::Bind(&AndroidAccessTokenFetcher::OnAccessTokenResponse,
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     weak_factory_.GetWeakPtr())));
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Call into Java to get a new token.
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Java_OAuth2TokenService_getOAuth2AuthToken(
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      env, base::android::GetApplicationContext(),
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      j_username.obj(),
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      j_scope.obj(),
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      reinterpret_cast<intptr_t>(heap_callback.release()));
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AndroidAccessTokenFetcher::CancelRequest() {
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  request_was_cancelled_ = true;
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AndroidAccessTokenFetcher::OnAccessTokenResponse(
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const GoogleServiceAuthError& error,
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::string& access_token,
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const base::Time& expiration_time) {
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (request_was_cancelled_) {
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Ignore the callback if the request was cancelled.
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (error.state() == GoogleServiceAuthError::NONE) {
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    FireOnGetTokenSuccess(access_token, expiration_time);
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else {
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    FireOnGetTokenFailure(error);
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistd::string AndroidAccessTokenFetcher::CombineScopes(
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::vector<std::string>& scopes) {
1197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // The Android AccountManager supports multiple scopes separated by a space:
1207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // https://code.google.com/p/google-api-java-client/wiki/OAuth2#Android
1217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string scope;
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (std::vector<std::string>::const_iterator it = scopes.begin();
1237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch       it != scopes.end(); ++it) {
1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (!scope.empty())
1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      scope += " ";
1267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    scope += *it;
1277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return scope;
1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}  // namespace
1327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool AndroidProfileOAuth2TokenService::is_testing_profile_ = false;
134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
135ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochAndroidProfileOAuth2TokenService::AndroidProfileOAuth2TokenService() {
136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  VLOG(1) << "AndroidProfileOAuth2TokenService::ctor";
1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  JNIEnv* env = AttachCurrentThread();
1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::android::ScopedJavaLocalRef<jobject> local_java_ref =
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      Java_OAuth2TokenService_create(env, reinterpret_cast<intptr_t>(this));
1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  java_ref_.Reset(env, local_java_ref.obj());
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)AndroidProfileOAuth2TokenService::~AndroidProfileOAuth2TokenService() {}
1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// static
1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)jobject AndroidProfileOAuth2TokenService::GetForProfile(
1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    JNIEnv* env, jclass clazz, jobject j_profile_android) {
1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile_android);
1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  AndroidProfileOAuth2TokenService* service =
150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ProfileOAuth2TokenServiceFactory::GetPlatformSpecificForProfile(profile);
1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return service->java_ref_.obj();
1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static jobject GetForProfile(JNIEnv* env,
1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             jclass clazz,
1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             jobject j_profile_android) {
1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return AndroidProfileOAuth2TokenService::GetForProfile(
1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      env, clazz, j_profile_android);
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void AndroidProfileOAuth2TokenService::Initialize(SigninClient* client) {
162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  VLOG(1) << "AndroidProfileOAuth2TokenService::Initialize";
163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ProfileOAuth2TokenService::Initialize(client);
164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!is_testing_profile_) {
166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    Java_OAuth2TokenService_validateAccounts(
167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        AttachCurrentThread(), java_ref_.obj(),
168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        base::android::GetApplicationContext(), JNI_TRUE);
169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
17268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool AndroidProfileOAuth2TokenService::RefreshTokenIsAvailable(
173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const std::string& account_id) const {
17468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  JNIEnv* env = AttachCurrentThread();
17568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ScopedJavaLocalRef<jstring> j_account_id =
17668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ConvertUTF8ToJavaString(env, account_id);
17768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  jboolean refresh_token_is_available =
1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      Java_OAuth2TokenService_hasOAuth2RefreshToken(
17968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          env, base::android::GetApplicationContext(),
18068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          j_account_id.obj());
181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return refresh_token_is_available == JNI_TRUE;
1827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AndroidProfileOAuth2TokenService::UpdateAuthError(
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::string& account_id,
1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const GoogleServiceAuthError& error) {
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // TODO(rogerta): do we need to update anything, or does the system handle it?
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
19068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)std::vector<std::string> AndroidProfileOAuth2TokenService::GetAccounts() {
19168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<std::string> accounts;
1927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  JNIEnv* env = AttachCurrentThread();
19368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ScopedJavaLocalRef<jobjectArray> j_accounts =
1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      Java_OAuth2TokenService_getAccounts(
19568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          env, base::android::GetApplicationContext());
19668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // TODO(fgorski): We may decide to filter out some of the accounts.
19768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  base::android::AppendJavaStringArrayToStringVector(env,
19868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                                     j_accounts.obj(),
19968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                                     &accounts);
20068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return accounts;
2017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
2027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustd::vector<std::string> AndroidProfileOAuth2TokenService::GetSystemAccounts() {
2045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  std::vector<std::string> accounts;
2055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  JNIEnv* env = AttachCurrentThread();
2065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ScopedJavaLocalRef<jobjectArray> j_accounts =
2075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      Java_OAuth2TokenService_getSystemAccounts(
2085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          env, base::android::GetApplicationContext());
2095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::android::AppendJavaStringArrayToStringVector(env,
2105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                     j_accounts.obj(),
2115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                     &accounts);
2125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return accounts;
2135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
2145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)OAuth2AccessTokenFetcher*
216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AndroidProfileOAuth2TokenService::CreateAccessTokenFetcher(
217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const std::string& account_id,
218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    net::URLRequestContextGetter* getter,
219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    OAuth2AccessTokenConsumer* consumer) {
2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(!account_id.empty());
2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return new AndroidAccessTokenFetcher(consumer, account_id);
222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
22468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void AndroidProfileOAuth2TokenService::InvalidateOAuth2Token(
22568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& account_id,
22668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& client_id,
22768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const ScopeSet& scopes,
22868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& access_token) {
22968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  OAuth2TokenService::InvalidateOAuth2Token(account_id,
23068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                            client_id,
23168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                            scopes,
23268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                            access_token);
23368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
23468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  JNIEnv* env = AttachCurrentThread();
23568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ScopedJavaLocalRef<jstring> j_access_token =
23668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ConvertUTF8ToJavaString(env, access_token);
2374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Java_OAuth2TokenService_invalidateOAuth2AuthToken(
23868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      env, base::android::GetApplicationContext(),
23968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      j_access_token.obj());
24068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
24168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid AndroidProfileOAuth2TokenService::ValidateAccounts(
2435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    JNIEnv* env,
2445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    jobject obj,
245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    jstring j_current_acc,
246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    jboolean j_force_notifications) {
247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  VLOG(1) << "AndroidProfileOAuth2TokenService::ValidateAccounts from java";
2484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  std::string signed_in_account = ConvertJavaStringToUTF8(env, j_current_acc);
249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ValidateAccounts(signed_in_account, j_force_notifications != JNI_FALSE);
250a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
2514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
252a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void AndroidProfileOAuth2TokenService::ValidateAccounts(
253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const std::string& signed_in_account,
254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    bool force_notifications) {
2555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  std::vector<std::string> prev_ids = GetAccounts();
2565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  std::vector<std::string> curr_ids = GetSystemAccounts();
257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::vector<std::string> refreshed_ids;
258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::vector<std::string> revoked_ids;
2595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  VLOG(1) << "AndroidProfileOAuth2TokenService::ValidateAccounts:"
261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          << " sigined_in_account=" << signed_in_account
262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          << " prev_ids=" << prev_ids.size()
263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          << " curr_ids=" << curr_ids.size()
264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          << " force=" << (force_notifications ? "true" : "false");
265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!ValidateAccounts(signed_in_account, prev_ids, curr_ids, refreshed_ids,
267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        revoked_ids, force_notifications)) {
2685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    curr_ids.clear();
2695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
2704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
271116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ScopedBacthChange batch(this);
272116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
2735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  JNIEnv* env = AttachCurrentThread();
2745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ScopedJavaLocalRef<jobjectArray> java_accounts(
2755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      base::android::ToJavaArrayOfStrings(env, curr_ids));
2765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  Java_OAuth2TokenService_saveStoredAccounts(
2775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      env, base::android::GetApplicationContext(), java_accounts.obj());
278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (std::vector<std::string>::iterator it = refreshed_ids.begin();
280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       it != refreshed_ids.end(); it++) {
281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    FireRefreshTokenAvailable(*it);
282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (std::vector<std::string>::iterator it = revoked_ids.begin();
285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       it != revoked_ids.end(); it++) {
286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    FireRefreshTokenRevoked(*it);
287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
2885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
2895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool AndroidProfileOAuth2TokenService::ValidateAccounts(
2915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const std::string& signed_in_account,
2925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const std::vector<std::string>& prev_account_ids,
293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::vector<std::string>& curr_account_ids,
294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    std::vector<std::string>& refreshed_ids,
295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    std::vector<std::string>& revoked_ids,
296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    bool force_notifications) {
2975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (std::find(curr_account_ids.begin(),
2985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                curr_account_ids.end(),
2995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                signed_in_account) != curr_account_ids.end()) {
3005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // Test to see if an account is removed from the Android AccountManager.
3015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // If so, invoke FireRefreshTokenRevoked to notify the reconcilor.
3025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    for (std::vector<std::string>::const_iterator it = prev_account_ids.begin();
3035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu         it != prev_account_ids.end(); it++) {
3045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (*it == signed_in_account)
3055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        continue;
3065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (std::find(curr_account_ids.begin(),
3085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                    curr_account_ids.end(),
3095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                    *it) == curr_account_ids.end()) {
310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        VLOG(1) << "AndroidProfileOAuth2TokenService::ValidateAccounts:"
311f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                << "revoked=" << *it;
312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        revoked_ids.push_back(*it);
3135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      }
3145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
315a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (force_notifications ||
317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        std::find(prev_account_ids.begin(), prev_account_ids.end(),
318f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  signed_in_account) == prev_account_ids.end()) {
319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // Always fire the primary signed in account first.
320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      VLOG(1) << "AndroidProfileOAuth2TokenService::ValidateAccounts:"
321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)              << "refreshed=" << signed_in_account;
322f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      refreshed_ids.push_back(signed_in_account);
323f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
324a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    for (std::vector<std::string>::const_iterator it = curr_account_ids.begin();
3265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu         it != curr_account_ids.end(); it++) {
327a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if (*it != signed_in_account) {
328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (force_notifications ||
329f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            std::find(prev_account_ids.begin(),
330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                      prev_account_ids.end(),
331f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                      *it) == prev_account_ids.end()) {
332f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          VLOG(1) << "AndroidProfileOAuth2TokenService::ValidateAccounts:"
333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  << "refreshed=" << *it;
334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          refreshed_ids.push_back(*it);
335f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        }
336a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      }
337a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
3385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return true;
3394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  } else {
3404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Currently signed in account does not any longer exist among accounts on
3415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // system together with all other accounts.
342f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (std::find(prev_account_ids.begin(), prev_account_ids.end(),
343f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  signed_in_account) != prev_account_ids.end()) {
344f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      VLOG(1) << "AndroidProfileOAuth2TokenService::ValidateAccounts:"
345f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)              << "revoked=" << signed_in_account;
346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      revoked_ids.push_back(signed_in_account);
3475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
3485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    for (std::vector<std::string>::const_iterator it = prev_account_ids.begin();
3495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu         it != prev_account_ids.end(); it++) {
3505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (*it == signed_in_account)
3515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        continue;
352f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      VLOG(1) << "AndroidProfileOAuth2TokenService::ValidateAccounts:"
353f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)              << "revoked=" << *it;
354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      revoked_ids.push_back(*it);
3555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
3565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return false;
3574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void AndroidProfileOAuth2TokenService::FireRefreshTokenAvailableFromJava(
3614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    JNIEnv* env,
3624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    jobject obj,
3634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const jstring account_name) {
3644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  std::string account_id = ConvertJavaStringToUTF8(env, account_name);
3654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  AndroidProfileOAuth2TokenService::FireRefreshTokenAvailable(account_id);
3664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void AndroidProfileOAuth2TokenService::FireRefreshTokenAvailable(
3694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const std::string& account_id) {
370f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  VLOG(1) << "AndroidProfileOAuth2TokenService::FireRefreshTokenAvailable id="
371f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          << account_id;
372f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
3734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Notify native observers.
3744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  OAuth2TokenService::FireRefreshTokenAvailable(account_id);
3754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Notify Java observers.
3764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  JNIEnv* env = AttachCurrentThread();
3774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ScopedJavaLocalRef<jstring> account_name =
3784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      ConvertUTF8ToJavaString(env, account_id);
3794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Java_OAuth2TokenService_notifyRefreshTokenAvailable(
3804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      env, java_ref_.obj(), account_name.obj());
3814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void AndroidProfileOAuth2TokenService::FireRefreshTokenRevokedFromJava(
3844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    JNIEnv* env,
3854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    jobject obj,
3864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const jstring account_name) {
3874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  std::string account_id = ConvertJavaStringToUTF8(env, account_name);
3884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  AndroidProfileOAuth2TokenService::FireRefreshTokenRevoked(account_id);
3894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void AndroidProfileOAuth2TokenService::FireRefreshTokenRevoked(
3924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const std::string& account_id) {
393f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  VLOG(1) << "AndroidProfileOAuth2TokenService::FireRefreshTokenRevoked id="
394f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          << account_id;
395f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
3964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Notify native observers.
3974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  OAuth2TokenService::FireRefreshTokenRevoked(account_id);
3984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Notify Java observers.
3994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  JNIEnv* env = AttachCurrentThread();
4004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ScopedJavaLocalRef<jstring> account_name =
4014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      ConvertUTF8ToJavaString(env, account_id);
4024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Java_OAuth2TokenService_notifyRefreshTokenRevoked(
4034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      env, java_ref_.obj(), account_name.obj());
4044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
4054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void AndroidProfileOAuth2TokenService::FireRefreshTokensLoadedFromJava(
4074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    JNIEnv* env,
4084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    jobject obj) {
4094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  AndroidProfileOAuth2TokenService::FireRefreshTokensLoaded();
4104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
4114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void AndroidProfileOAuth2TokenService::FireRefreshTokensLoaded() {
413f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  VLOG(1) << "AndroidProfileOAuth2TokenService::FireRefreshTokensLoaded";
4144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Notify native observers.
4154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  OAuth2TokenService::FireRefreshTokensLoaded();
4164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Notify Java observers.
4174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  JNIEnv* env = AttachCurrentThread();
4184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Java_OAuth2TokenService_notifyRefreshTokensLoaded(
4194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      env, java_ref_.obj());
4204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
4214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid AndroidProfileOAuth2TokenService::RevokeAllCredentials() {
423f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  VLOG(1) << "AndroidProfileOAuth2TokenService::RevokeAllCredentials";
424116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ScopedBacthChange batch(this);
4255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  std::vector<std::string> accounts = GetAccounts();
4265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (std::vector<std::string>::iterator it = accounts.begin();
4275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu       it != accounts.end(); it++) {
4285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    FireRefreshTokenRevoked(*it);
4295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
4305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Clear everything on the Java side as well.
4325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<std::string> empty;
4335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  JNIEnv* env = AttachCurrentThread();
4345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ScopedJavaLocalRef<jobjectArray> java_accounts(
4355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::android::ToJavaArrayOfStrings(env, empty));
4365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Java_OAuth2TokenService_saveStoredAccounts(
4375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      env, base::android::GetApplicationContext(), java_accounts.obj());
4385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
4395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Called from Java when fetching of an OAuth2 token is finished. The
4417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// |authToken| param is only valid when |result| is true.
4421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid OAuth2TokenFetched(
4431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    JNIEnv* env,
4441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    jclass clazz,
4457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    jstring authToken,
4467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    jboolean result,
447f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    jlong nativeCallback) {
4487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::string token = ConvertJavaStringToUTF8(env, authToken);
4493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<FetchOAuth2TokenCallback> heap_callback(
4503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      reinterpret_cast<FetchOAuth2TokenCallback*>(nativeCallback));
4514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Android does not provide enough information to know if the credentials are
4524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // wrong, so assume any error is transient by using CONNECTION_FAILED.
4537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  GoogleServiceAuthError err(result ?
4547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                             GoogleServiceAuthError::NONE :
4554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             GoogleServiceAuthError::CONNECTION_FAILED);
4567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  heap_callback->Run(err, token, base::Time());
4577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
4587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// static
4607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool AndroidProfileOAuth2TokenService::Register(JNIEnv* env) {
4617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return RegisterNativesImpl(env);
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
463