1ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis// Copyright 2013 The Chromium Authors. All rights reserved.
29fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis// Use of this source code is governed by a BSD-style license that can be
39fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis// found in the LICENSE file.
49fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
59fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis#include "chrome/browser/signin/android_profile_oauth2_token_service.h"
69fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
79fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis#include "base/android/jni_android.h"
89fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis#include "base/android/jni_array.h"
99fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis#include "base/android/jni_string.h"
10ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "base/bind.h"
119fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis#include "base/logging.h"
129fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis#include "chrome/browser/profiles/profile_android.h"
139fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
14ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "chrome/browser/sync/profile_sync_service_android.h"
15ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "content/public/browser/browser_thread.h"
169fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis#include "google_apis/gaia/oauth2_access_token_fetcher.h"
17ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek#include "jni/OAuth2TokenService_jni.h"
189fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
19b3d74da3e1620c9a7a378afb5f244e4987e6713eArgyrios Kyrtzidisusing base::android::AttachCurrentThread;
209fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidisusing base::android::ConvertJavaStringToUTF8;
219fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidisusing base::android::ConvertUTF8ToJavaString;
229fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidisusing base::android::ScopedJavaLocalRef;
239fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidisusing content::BrowserThread;
249fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
259fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidisnamespace {
269fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
279fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis// Callback from FetchOAuth2TokenWithUsername().
289fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis// Arguments:
299fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis// - the error, or NONE if the token fetch was successful.
309fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis// - the OAuth2 access token.
319fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis// - the expiry time of the token (may be null, indicating that the expiry
329fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis//   time is unknown.
339fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidistypedef base::Callback<void(
349fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis    const GoogleServiceAuthError&, const std::string&, const base::Time&)>
359fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis        FetchOAuth2TokenCallback;
369fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
37cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenkoclass AndroidAccessTokenFetcher : public OAuth2AccessTokenFetcher {
389fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis public:
399fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  AndroidAccessTokenFetcher(OAuth2AccessTokenConsumer* consumer,
409fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis                            const std::string& account_id);
41cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko  virtual ~AndroidAccessTokenFetcher();
429fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
439fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  // Overrides from OAuth2AccessTokenFetcher:
449fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  virtual void Start(const std::string& client_id,
459fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis                     const std::string& client_secret,
46769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                     const std::vector<std::string>& scopes) OVERRIDE;
47769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  virtual void CancelRequest() OVERRIDE;
48769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
499fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  // Handles an access token response.
509fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  void OnAccessTokenResponse(const GoogleServiceAuthError& error,
519fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis                             const std::string& access_token,
529fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis                             const base::Time& expiration_time);
539fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
549fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis private:
559fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  std::string CombineScopes(const std::vector<std::string>& scopes);
569fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
579fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  base::WeakPtrFactory<AndroidAccessTokenFetcher> weak_factory_;
589fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  std::string account_id_;
599fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  bool request_was_cancelled_;
609fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
619fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  DISALLOW_COPY_AND_ASSIGN(AndroidAccessTokenFetcher);
62769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis};
63769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
64769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios KyrtzidisAndroidAccessTokenFetcher::AndroidAccessTokenFetcher(
65769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    OAuth2AccessTokenConsumer* consumer,
66769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    const std::string& account_id)
679be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek    : OAuth2AccessTokenFetcher(consumer),
689be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek      weak_factory_(this),
699be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek      account_id_(account_id),
709be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek      request_was_cancelled_(false) {
719be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek}
729be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek
739be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted KremenekAndroidAccessTokenFetcher::~AndroidAccessTokenFetcher() {}
749be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek
759be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenekvoid AndroidAccessTokenFetcher::Start(const std::string& client_id,
769be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek                                      const std::string& client_secret,
779be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek                                      const std::vector<std::string>& scopes) {
789be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek  JNIEnv* env = AttachCurrentThread();
799be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek  std::string scope = CombineScopes(scopes);
809be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek  ScopedJavaLocalRef<jstring> j_username =
819be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek      ConvertUTF8ToJavaString(env, account_id_);
829be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek  ScopedJavaLocalRef<jstring> j_scope =
839be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek      ConvertUTF8ToJavaString(env, scope);
849be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek  scoped_ptr<FetchOAuth2TokenCallback> heap_callback(
85769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      new FetchOAuth2TokenCallback(
86769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis          base::Bind(&AndroidAccessTokenFetcher::OnAccessTokenResponse,
87769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                     weak_factory_.GetWeakPtr())));
88769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
89cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko  // Call into Java to get a new token.
90769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  Java_OAuth2TokenService_getOAuth2AuthToken(
91769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      env, base::android::GetApplicationContext(),
92769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      j_username.obj(),
93cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko      j_scope.obj(),
94769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      reinterpret_cast<intptr_t>(heap_callback.release()));
95769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
96769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
97769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid AndroidAccessTokenFetcher::CancelRequest() {
98769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  request_was_cancelled_ = true;
99769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
100769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
101769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid AndroidAccessTokenFetcher::OnAccessTokenResponse(
102769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    const GoogleServiceAuthError& error,
103769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    const std::string& access_token,
104769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    const base::Time& expiration_time) {
105769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  if (request_was_cancelled_) {
106769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    // Ignore the callback if the request was cancelled.
107769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    return;
108cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko  }
109769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  if (error.state() == GoogleServiceAuthError::NONE) {
110769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    FireOnGetTokenSuccess(access_token, expiration_time);
111769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  } else {
112cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko    FireOnGetTokenFailure(error);
113769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  }
114769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
115769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
116769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// static
117769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisstd::string AndroidAccessTokenFetcher::CombineScopes(
118769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    const std::vector<std::string>& scopes) {
119769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  // The Android AccountManager supports multiple scopes separated by a space:
120769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  // https://code.google.com/p/google-api-java-client/wiki/OAuth2#Android
121769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  std::string scope;
122769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  for (std::vector<std::string>::const_iterator it = scopes.begin();
123769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis       it != scopes.end(); ++it) {
124769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    if (!scope.empty())
125de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose      scope += " ";
126769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    scope += *it;
127769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  }
128769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  return scope;
129769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
130769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
131769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}  // namespace
132769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
133769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisbool AndroidProfileOAuth2TokenService::is_testing_profile_ = false;
134769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
135769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios KyrtzidisAndroidProfileOAuth2TokenService::AndroidProfileOAuth2TokenService() {
136769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  VLOG(1) << "AndroidProfileOAuth2TokenService::ctor";
137769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  JNIEnv* env = AttachCurrentThread();
138769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  base::android::ScopedJavaLocalRef<jobject> local_java_ref =
139769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      Java_OAuth2TokenService_create(env, reinterpret_cast<intptr_t>(this));
140de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose  java_ref_.Reset(env, local_java_ref.obj());
141769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
142769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
143769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios KyrtzidisAndroidProfileOAuth2TokenService::~AndroidProfileOAuth2TokenService() {}
144769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
145769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// static
146769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisjobject AndroidProfileOAuth2TokenService::GetForProfile(
147769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    JNIEnv* env, jclass clazz, jobject j_profile_android) {
148769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile_android);
149769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  AndroidProfileOAuth2TokenService* service =
150769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      ProfileOAuth2TokenServiceFactory::GetPlatformSpecificForProfile(profile);
151769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  return service->java_ref_.obj();
152769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
15396479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose
15496479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rosestatic jobject GetForProfile(JNIEnv* env,
15596479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose                             jclass clazz,
15696479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose                             jobject j_profile_android) {
15796479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  return AndroidProfileOAuth2TokenService::GetForProfile(
15896479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose      env, clazz, j_profile_android);
15996479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose}
16096479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose
16196479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rosevoid AndroidProfileOAuth2TokenService::Initialize(SigninClient* client) {
16296479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  VLOG(1) << "AndroidProfileOAuth2TokenService::Initialize";
16396479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  ProfileOAuth2TokenService::Initialize(client);
16496479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose
16596479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  if (!is_testing_profile_) {
16696479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose    Java_OAuth2TokenService_validateAccounts(
16796479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose        AttachCurrentThread(), java_ref_.obj(),
16896479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose        base::android::GetApplicationContext(), JNI_TRUE);
16996479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  }
17096479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose}
17196479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose
17296479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rosebool AndroidProfileOAuth2TokenService::RefreshTokenIsAvailable(
17396479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose    const std::string& account_id) const {
17496479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  JNIEnv* env = AttachCurrentThread();
17596479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  ScopedJavaLocalRef<jstring> j_account_id =
17696479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose      ConvertUTF8ToJavaString(env, account_id);
17796479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  jboolean refresh_token_is_available =
17896479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose      Java_OAuth2TokenService_hasOAuth2RefreshToken(
17996479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose          env, base::android::GetApplicationContext(),
18096479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose          j_account_id.obj());
18196479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  return refresh_token_is_available == JNI_TRUE;
18296479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose}
183769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
184769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid AndroidProfileOAuth2TokenService::UpdateAuthError(
185390909c89c98ab1807e15e033a72e975f866fb23Anna Zaks    const std::string& account_id,
186390909c89c98ab1807e15e033a72e975f866fb23Anna Zaks    const GoogleServiceAuthError& error) {
187769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  // TODO(rogerta): do we need to update anything, or does the system handle it?
188390909c89c98ab1807e15e033a72e975f866fb23Anna Zaks}
189769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
190769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisstd::vector<std::string> AndroidProfileOAuth2TokenService::GetAccounts() {
191769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  std::vector<std::string> accounts;
192769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  JNIEnv* env = AttachCurrentThread();
193769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  ScopedJavaLocalRef<jobjectArray> j_accounts =
194769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      Java_OAuth2TokenService_getAccounts(
195769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis          env, base::android::GetApplicationContext());
1969fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  // TODO(fgorski): We may decide to filter out some of the accounts.
1979fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  base::android::AppendJavaStringArrayToStringVector(env,
1989fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis                                                     j_accounts.obj(),
199312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis                                                     &accounts);
200312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  return accounts;
201390909c89c98ab1807e15e033a72e975f866fb23Anna Zaks}
202390909c89c98ab1807e15e033a72e975f866fb23Anna Zaks
203312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidisstd::vector<std::string> AndroidProfileOAuth2TokenService::GetSystemAccounts() {
204390909c89c98ab1807e15e033a72e975f866fb23Anna Zaks  std::vector<std::string> accounts;
205312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  JNIEnv* env = AttachCurrentThread();
206312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  ScopedJavaLocalRef<jobjectArray> j_accounts =
207312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis      Java_OAuth2TokenService_getSystemAccounts(
208312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis          env, base::android::GetApplicationContext());
209312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  base::android::AppendJavaStringArrayToStringVector(env,
210312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis                                                     j_accounts.obj(),
211312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis                                                     &accounts);
212312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  return accounts;
213312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis}
214312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis
21530726c6baee1417307236e854f1474fdb3cedb98Argyrios KyrtzidisOAuth2AccessTokenFetcher*
21630726c6baee1417307236e854f1474fdb3cedb98Argyrios KyrtzidisAndroidProfileOAuth2TokenService::CreateAccessTokenFetcher(
21730726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis    const std::string& account_id,
21830726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis    net::URLRequestContextGetter* getter,
21930726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis    OAuth2AccessTokenConsumer* consumer) {
22030726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis  DCHECK(!account_id.empty());
22130726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis  return new AndroidAccessTokenFetcher(consumer, account_id);
22230726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis}
22330726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis
22430726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidisvoid AndroidProfileOAuth2TokenService::InvalidateOAuth2Token(
22530726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis    const std::string& account_id,
22630726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis    const std::string& client_id,
22730726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis    const ScopeSet& scopes,
22830726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis    const std::string& access_token) {
22930726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis  OAuth2TokenService::InvalidateOAuth2Token(account_id,
230344c77aac25e5d960aced3f45fbaa09853383f6dAnna Zaks                                            client_id,
231af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis                                            scopes,
232344c77aac25e5d960aced3f45fbaa09853383f6dAnna Zaks                                            access_token);
233344c77aac25e5d960aced3f45fbaa09853383f6dAnna Zaks
234344c77aac25e5d960aced3f45fbaa09853383f6dAnna Zaks  JNIEnv* env = AttachCurrentThread();
235af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis  ScopedJavaLocalRef<jstring> j_access_token =
236af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis      ConvertUTF8ToJavaString(env, access_token);
237af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis  Java_OAuth2TokenService_invalidateOAuth2AuthToken(
238af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis      env, base::android::GetApplicationContext(),
239af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis      j_access_token.obj());
240344c77aac25e5d960aced3f45fbaa09853383f6dAnna Zaks}
241344c77aac25e5d960aced3f45fbaa09853383f6dAnna Zaks
242af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidisvoid AndroidProfileOAuth2TokenService::ValidateAccounts(
243af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis    JNIEnv* env,
244af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis    jobject obj,
245cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis    jstring j_current_acc,
246cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis    jboolean j_force_notifications) {
247f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks  VLOG(1) << "AndroidProfileOAuth2TokenService::ValidateAccounts from java";
248f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks  std::string signed_in_account = ConvertJavaStringToUTF8(env, j_current_acc);
249f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks  ValidateAccounts(signed_in_account, j_force_notifications != JNI_FALSE);
250cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis}
251cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis
252cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidisvoid AndroidProfileOAuth2TokenService::ValidateAccounts(
253cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis    const std::string& signed_in_account,
254cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis    bool force_notifications) {
255cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis  std::vector<std::string> prev_ids = GetAccounts();
256cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis  std::vector<std::string> curr_ids = GetSystemAccounts();
257cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis  std::vector<std::string> refreshed_ids;
258cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis  std::vector<std::string> revoked_ids;
259cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis
260cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis  VLOG(1) << "AndroidProfileOAuth2TokenService::ValidateAccounts:"
261183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis          << " sigined_in_account=" << signed_in_account
262183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis          << " prev_ids=" << prev_ids.size()
26323111dcd66ee242bb5caf1ecab01bd930ee42c4cTed Kremenek          << " curr_ids=" << curr_ids.size()
264183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis          << " force=" << (force_notifications ? "true" : "false");
265183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
266183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  if (!ValidateAccounts(signed_in_account, prev_ids, curr_ids, refreshed_ids,
267183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis                        revoked_ids, force_notifications)) {
268183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    curr_ids.clear();
269183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  }
270183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
271183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  ScopedBacthChange batch(this);
272183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
273183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  JNIEnv* env = AttachCurrentThread();
274183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  ScopedJavaLocalRef<jobjectArray> java_accounts(
275183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis      base::android::ToJavaArrayOfStrings(env, curr_ids));
276183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  Java_OAuth2TokenService_saveStoredAccounts(
277183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis      env, base::android::GetApplicationContext(), java_accounts.obj());
278183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
279183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  for (std::vector<std::string>::iterator it = refreshed_ids.begin();
280183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis       it != refreshed_ids.end(); it++) {
281183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    FireRefreshTokenAvailable(*it);
282183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  }
283183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
284183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  for (std::vector<std::string>::iterator it = revoked_ids.begin();
285183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis       it != revoked_ids.end(); it++) {
286183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    FireRefreshTokenRevoked(*it);
287183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  }
288183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis}
289183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
290183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisbool AndroidProfileOAuth2TokenService::ValidateAccounts(
291183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    const std::string& signed_in_account,
292183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    const std::vector<std::string>& prev_account_ids,
29323111dcd66ee242bb5caf1ecab01bd930ee42c4cTed Kremenek    const std::vector<std::string>& curr_account_ids,
29418c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek    std::vector<std::string>& refreshed_ids,
29523111dcd66ee242bb5caf1ecab01bd930ee42c4cTed Kremenek    std::vector<std::string>& revoked_ids,
296bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks    bool force_notifications) {
297537716ad8dd10f984b6cfe6985afade1185c5e3cJordy Rose  if (std::find(curr_account_ids.begin(),
29866c40400e7d6272b0cd675ada18dd62c1f0362c7Anna Zaks                curr_account_ids.end(),
299740d490593e0de8732a697c9f77b90ddd463863bJordan Rose                signed_in_account) != curr_account_ids.end()) {
30035bdbf40624beba3fc00cb72ab444659939c1a6bTed Kremenek    // Test to see if an account is removed from the Android AccountManager.
30166c40400e7d6272b0cd675ada18dd62c1f0362c7Anna Zaks    // If so, invoke FireRefreshTokenRevoked to notify the reconcilor.
302183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    for (std::vector<std::string>::const_iterator it = prev_account_ids.begin();
303183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis         it != prev_account_ids.end(); it++) {
30418c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek      if (*it == signed_in_account)
30523111dcd66ee242bb5caf1ecab01bd930ee42c4cTed Kremenek        continue;
306183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
307183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis      if (std::find(curr_account_ids.begin(),
308183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis                    curr_account_ids.end(),
309183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis                    *it) == curr_account_ids.end()) {
310183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis        VLOG(1) << "AndroidProfileOAuth2TokenService::ValidateAccounts:"
311183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis                << "revoked=" << *it;
312183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis        revoked_ids.push_back(*it);
313183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis      }
314183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    }
315183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
316183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    if (force_notifications ||
317183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis        std::find(prev_account_ids.begin(), prev_account_ids.end(),
318183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis                  signed_in_account) == prev_account_ids.end()) {
319183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis      // Always fire the primary signed in account first.
320bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks      VLOG(1) << "AndroidProfileOAuth2TokenService::ValidateAccounts:"
321bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks              << "refreshed=" << signed_in_account;
322bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks      refreshed_ids.push_back(signed_in_account);
323da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev    }
324bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks
325bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks    for (std::vector<std::string>::const_iterator it = curr_account_ids.begin();
326233e26acc0ff2a1098f4c813f69286fce840a422Anna Zaks         it != curr_account_ids.end(); it++) {
32741988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks      if (*it != signed_in_account) {
328da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev        if (force_notifications ||
329da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev            std::find(prev_account_ids.begin(),
330da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev                      prev_account_ids.end(),
331da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev                      *it) == prev_account_ids.end()) {
33241988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks          VLOG(1) << "AndroidProfileOAuth2TokenService::ValidateAccounts:"
33341988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks                  << "refreshed=" << *it;
33441988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks          refreshed_ids.push_back(*it);
335da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev        }
336da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev      }
337da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev    }
338da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev    return true;
339da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev  } else {
340b7a747b0c271faeeb8d0f886f0e691eb25f637d9Anton Yartsev    // Currently signed in account does not any longer exist among accounts on
341b7a747b0c271faeeb8d0f886f0e691eb25f637d9Anton Yartsev    // system together with all other accounts.
342b7a747b0c271faeeb8d0f886f0e691eb25f637d9Anton Yartsev    if (std::find(prev_account_ids.begin(), prev_account_ids.end(),
343da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev                  signed_in_account) != prev_account_ids.end()) {
344da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev      VLOG(1) << "AndroidProfileOAuth2TokenService::ValidateAccounts:"
345da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev              << "revoked=" << signed_in_account;
346da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev      revoked_ids.push_back(signed_in_account);
347da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev    }
348da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev    for (std::vector<std::string>::const_iterator it = prev_account_ids.begin();
349da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev         it != prev_account_ids.end(); it++) {
350da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev      if (*it == signed_in_account)
351da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev        continue;
352bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks      VLOG(1) << "AndroidProfileOAuth2TokenService::ValidateAccounts:"
353bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks              << "revoked=" << *it;
354bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks      revoked_ids.push_back(*it);
355bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks    }
356bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks    return false;
357bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks  }
358bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks}
359bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks
360bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaksvoid AndroidProfileOAuth2TokenService::FireRefreshTokenAvailableFromJava(
361bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks    JNIEnv* env,
362bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks    jobject obj,
36341988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks    const jstring account_name) {
36441988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks  std::string account_id = ConvertJavaStringToUTF8(env, account_name);
36541988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks  AndroidProfileOAuth2TokenService::FireRefreshTokenAvailable(account_id);
366da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev}
36741988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks
36841988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaksvoid AndroidProfileOAuth2TokenService::FireRefreshTokenAvailable(
36941988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks    const std::string& account_id) {
37041988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks  VLOG(1) << "AndroidProfileOAuth2TokenService::FireRefreshTokenAvailable id="
371da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev          << account_id;
372da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev
373da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev  // Notify native observers.
374da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev  OAuth2TokenService::FireRefreshTokenAvailable(account_id);
375da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev  // Notify Java observers.
376da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev  JNIEnv* env = AttachCurrentThread();
377da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev  ScopedJavaLocalRef<jstring> account_name =
378da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev      ConvertUTF8ToJavaString(env, account_id);
379da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev  Java_OAuth2TokenService_notifyRefreshTokenAvailable(
380b7a747b0c271faeeb8d0f886f0e691eb25f637d9Anton Yartsev      env, java_ref_.obj(), account_name.obj());
381b7a747b0c271faeeb8d0f886f0e691eb25f637d9Anton Yartsev}
382b7a747b0c271faeeb8d0f886f0e691eb25f637d9Anton Yartsev
383da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsevvoid AndroidProfileOAuth2TokenService::FireRefreshTokenRevokedFromJava(
384da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev    JNIEnv* env,
385da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev    jobject obj,
386da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev    const jstring account_name) {
387da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev  std::string account_id = ConvertJavaStringToUTF8(env, account_name);
388da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev  AndroidProfileOAuth2TokenService::FireRefreshTokenRevoked(account_id);
389da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev}
390da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsev
391da8d37ce42d2db4e1e76ee6f7f38f10f6b0ef0f8Anton Yartsevvoid AndroidProfileOAuth2TokenService::FireRefreshTokenRevoked(
39241988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks    const std::string& account_id) {
39341988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks  VLOG(1) << "AndroidProfileOAuth2TokenService::FireRefreshTokenRevoked id="
39441988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks          << account_id;
39541988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks
39641988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks  // Notify native observers.
39741988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks  OAuth2TokenService::FireRefreshTokenRevoked(account_id);
39841988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks  // Notify Java observers.
39941988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks  JNIEnv* env = AttachCurrentThread();
40041988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks  ScopedJavaLocalRef<jstring> account_name =
40141988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks      ConvertUTF8ToJavaString(env, account_id);
40241988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks  Java_OAuth2TokenService_notifyRefreshTokenRevoked(
40341988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks      env, java_ref_.obj(), account_name.obj());
404deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis}
405deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis
406deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidisvoid AndroidProfileOAuth2TokenService::FireRefreshTokensLoadedFromJava(
407deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis    JNIEnv* env,
408deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis    jobject obj) {
409deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis  AndroidProfileOAuth2TokenService::FireRefreshTokensLoaded();
410deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis}
411deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis
412deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidisvoid AndroidProfileOAuth2TokenService::FireRefreshTokensLoaded() {
413deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis  VLOG(1) << "AndroidProfileOAuth2TokenService::FireRefreshTokensLoaded";
414deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis  // Notify native observers.
415deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis  OAuth2TokenService::FireRefreshTokensLoaded();
416deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis  // Notify Java observers.
417deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis  JNIEnv* env = AttachCurrentThread();
4189fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  Java_OAuth2TokenService_notifyRefreshTokensLoaded(
4199fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis      env, java_ref_.obj());
420e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis}
421e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis
422312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidisvoid AndroidProfileOAuth2TokenService::RevokeAllCredentials() {
423312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  VLOG(1) << "AndroidProfileOAuth2TokenService::RevokeAllCredentials";
42423111dcd66ee242bb5caf1ecab01bd930ee42c4cTed Kremenek  ScopedBacthChange batch(this);
42523111dcd66ee242bb5caf1ecab01bd930ee42c4cTed Kremenek  std::vector<std::string> accounts = GetAccounts();
42618c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek  for (std::vector<std::string>::iterator it = accounts.begin();
42718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek       it != accounts.end(); it++) {
428312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    FireRefreshTokenRevoked(*it);
429312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  }
430312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis
431312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  // Clear everything on the Java side as well.
432312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  std::vector<std::string> empty;
433312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  JNIEnv* env = AttachCurrentThread();
434312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  ScopedJavaLocalRef<jobjectArray> java_accounts(
435312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis      base::android::ToJavaArrayOfStrings(env, empty));
436312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  Java_OAuth2TokenService_saveStoredAccounts(
437312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis      env, base::android::GetApplicationContext(), java_accounts.obj());
438312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis}
439e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis
440e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis// Called from Java when fetching of an OAuth2 token is finished. The
441e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis// |authToken| param is only valid when |result| is true.
442e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidisvoid OAuth2TokenFetched(
443e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    JNIEnv* env,
444e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    jclass clazz,
445e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    jstring authToken,
446e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    jboolean result,
447e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    jlong nativeCallback) {
448e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis  std::string token = ConvertJavaStringToUTF8(env, authToken);
449e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis  scoped_ptr<FetchOAuth2TokenCallback> heap_callback(
450e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis      reinterpret_cast<FetchOAuth2TokenCallback*>(nativeCallback));
451e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis  // Android does not provide enough information to know if the credentials are
452e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis  // wrong, so assume any error is transient by using CONNECTION_FAILED.
453e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis  GoogleServiceAuthError err(result ?
454e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis                             GoogleServiceAuthError::NONE :
455ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek                             GoogleServiceAuthError::CONNECTION_FAILED);
456651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  heap_callback->Run(err, token, base::Time());
457651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
458651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
459ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek// static
460651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesbool AndroidProfileOAuth2TokenService::Register(JNIEnv* env) {
461651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return RegisterNativesImpl(env);
462dbd658e139b3e0bf084f75feaea8d844af9e319fJordy Rose}
463dbd658e139b3e0bf084f75feaea8d844af9e319fJordy Rose