Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / chrome / browser / signin / android_profile_oauth2_token_service.cc
blobc88af816fcb1c90875f3e27db6152019529869fc
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/signin/android_profile_oauth2_token_service.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_array.h"
9 #include "base/android/jni_string.h"
10 #include "base/bind.h"
11 #include "base/logging.h"
12 #include "chrome/browser/profiles/profile_android.h"
13 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
14 #include "chrome/browser/sync/profile_sync_service_android.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "jni/OAuth2TokenService_jni.h"
18 using base::android::AttachCurrentThread;
19 using base::android::ConvertJavaStringToUTF8;
20 using base::android::ConvertUTF8ToJavaString;
21 using base::android::ScopedJavaLocalRef;
22 using content::BrowserThread;
24 namespace {
26 std::string CombineScopes(const OAuth2TokenService::ScopeSet& scopes) {
27 // The Android AccountManager supports multiple scopes separated by a space:
28 // https://code.google.com/p/google-api-java-client/wiki/OAuth2#Android
29 std::string scope;
30 for (OAuth2TokenService::ScopeSet::const_iterator it = scopes.begin();
31 it != scopes.end(); ++it) {
32 if (!scope.empty())
33 scope += " ";
34 scope += *it;
36 return scope;
39 // Callback from FetchOAuth2TokenWithUsername().
40 // Arguments:
41 // - the error, or NONE if the token fetch was successful.
42 // - the OAuth2 access token.
43 // - the expiry time of the token (may be null, indicating that the expiry
44 // time is unknown.
45 typedef base::Callback<void(
46 const GoogleServiceAuthError&, const std::string&, const base::Time&)>
47 FetchOAuth2TokenCallback;
49 } // namespace
51 AndroidProfileOAuth2TokenService::AndroidProfileOAuth2TokenService() {
52 JNIEnv* env = AttachCurrentThread();
53 base::android::ScopedJavaLocalRef<jobject> local_java_ref =
54 Java_OAuth2TokenService_create(env, reinterpret_cast<intptr_t>(this));
55 java_ref_.Reset(env, local_java_ref.obj());
58 AndroidProfileOAuth2TokenService::~AndroidProfileOAuth2TokenService() {}
60 // static
61 jobject AndroidProfileOAuth2TokenService::GetForProfile(
62 JNIEnv* env, jclass clazz, jobject j_profile_android) {
63 Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile_android);
64 AndroidProfileOAuth2TokenService* service =
65 ProfileOAuth2TokenServiceFactory::GetPlatformSpecificForProfile(profile);
66 return service->java_ref_.obj();
69 static jobject GetForProfile(JNIEnv* env,
70 jclass clazz,
71 jobject j_profile_android) {
72 return AndroidProfileOAuth2TokenService::GetForProfile(
73 env, clazz, j_profile_android);
76 bool AndroidProfileOAuth2TokenService::RefreshTokenIsAvailable(
77 const std::string& account_id) const {
78 JNIEnv* env = AttachCurrentThread();
79 ScopedJavaLocalRef<jstring> j_account_id =
80 ConvertUTF8ToJavaString(env, account_id);
81 jboolean refresh_token_is_available =
82 Java_OAuth2TokenService_hasOAuth2RefreshToken(
83 env, base::android::GetApplicationContext(),
84 j_account_id.obj());
85 return refresh_token_is_available != JNI_FALSE;
88 std::vector<std::string> AndroidProfileOAuth2TokenService::GetAccounts() {
89 std::vector<std::string> accounts;
90 JNIEnv* env = AttachCurrentThread();
91 ScopedJavaLocalRef<jobjectArray> j_accounts =
92 Java_OAuth2TokenService_getAccounts(
93 env, base::android::GetApplicationContext());
94 // TODO(fgorski): We may decide to filter out some of the accounts.
95 base::android::AppendJavaStringArrayToStringVector(env,
96 j_accounts.obj(),
97 &accounts);
98 return accounts;
101 std::vector<std::string> AndroidProfileOAuth2TokenService::GetSystemAccounts() {
102 std::vector<std::string> accounts;
103 JNIEnv* env = AttachCurrentThread();
104 ScopedJavaLocalRef<jobjectArray> j_accounts =
105 Java_OAuth2TokenService_getSystemAccounts(
106 env, base::android::GetApplicationContext());
107 base::android::AppendJavaStringArrayToStringVector(env,
108 j_accounts.obj(),
109 &accounts);
110 return accounts;
113 void AndroidProfileOAuth2TokenService::FetchOAuth2Token(
114 RequestImpl* request,
115 const std::string& account_id,
116 net::URLRequestContextGetter* getter,
117 const std::string& client_id,
118 const std::string& client_secret,
119 const OAuth2TokenService::ScopeSet& scopes) {
120 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
121 DCHECK(!account_id.empty());
123 JNIEnv* env = AttachCurrentThread();
124 std::string scope = CombineScopes(scopes);
125 ScopedJavaLocalRef<jstring> j_username =
126 ConvertUTF8ToJavaString(env, account_id);
127 ScopedJavaLocalRef<jstring> j_scope =
128 ConvertUTF8ToJavaString(env, scope);
130 // Allocate a copy of the request WeakPtr on the heap, because the object
131 // needs to be passed through JNI as an int.
132 // It will be passed back to OAuth2TokenFetched(), where it will be freed.
133 scoped_ptr<FetchOAuth2TokenCallback> heap_callback(
134 new FetchOAuth2TokenCallback(base::Bind(&RequestImpl::InformConsumer,
135 request->AsWeakPtr())));
137 // Call into Java to get a new token.
138 Java_OAuth2TokenService_getOAuth2AuthToken(
139 env, base::android::GetApplicationContext(),
140 j_username.obj(),
141 j_scope.obj(),
142 reinterpret_cast<intptr_t>(heap_callback.release()));
145 OAuth2AccessTokenFetcher*
146 AndroidProfileOAuth2TokenService::CreateAccessTokenFetcher(
147 const std::string& account_id,
148 net::URLRequestContextGetter* getter,
149 OAuth2AccessTokenConsumer* consumer) {
150 NOTREACHED();
151 return NULL;
154 void AndroidProfileOAuth2TokenService::InvalidateOAuth2Token(
155 const std::string& account_id,
156 const std::string& client_id,
157 const ScopeSet& scopes,
158 const std::string& access_token) {
159 OAuth2TokenService::InvalidateOAuth2Token(account_id,
160 client_id,
161 scopes,
162 access_token);
164 JNIEnv* env = AttachCurrentThread();
165 ScopedJavaLocalRef<jstring> j_access_token =
166 ConvertUTF8ToJavaString(env, access_token);
167 Java_OAuth2TokenService_invalidateOAuth2AuthToken(
168 env, base::android::GetApplicationContext(),
169 j_access_token.obj());
172 void AndroidProfileOAuth2TokenService::ValidateAccounts(
173 JNIEnv* env,
174 jobject obj,
175 jstring j_current_acc) {
176 std::string signed_in_account = ConvertJavaStringToUTF8(env, j_current_acc);
177 ValidateAccounts(signed_in_account);
180 void AndroidProfileOAuth2TokenService::ValidateAccounts(
181 const std::string& signed_in_account) {
182 std::vector<std::string> prev_ids = GetAccounts();
183 std::vector<std::string> curr_ids = GetSystemAccounts();
185 if (!ValidateAccounts(signed_in_account, prev_ids, curr_ids)) {
186 curr_ids.clear();
189 JNIEnv* env = AttachCurrentThread();
190 ScopedJavaLocalRef<jobjectArray> java_accounts(
191 base::android::ToJavaArrayOfStrings(env, curr_ids));
192 Java_OAuth2TokenService_saveStoredAccounts(
193 env, base::android::GetApplicationContext(), java_accounts.obj());
196 bool AndroidProfileOAuth2TokenService::ValidateAccounts(
197 const std::string& signed_in_account,
198 const std::vector<std::string>& prev_account_ids,
199 const std::vector<std::string>& curr_account_ids) {
200 if (std::find(curr_account_ids.begin(),
201 curr_account_ids.end(),
202 signed_in_account) != curr_account_ids.end()) {
203 // Test to see if an account is removed from the Android AccountManager.
204 // If so, invoke FireRefreshTokenRevoked to notify the reconcilor.
205 for (std::vector<std::string>::const_iterator it = prev_account_ids.begin();
206 it != prev_account_ids.end(); it++) {
207 if (*it == signed_in_account)
208 continue;
210 if (std::find(curr_account_ids.begin(),
211 curr_account_ids.end(),
212 *it) == curr_account_ids.end()) {
213 FireRefreshTokenRevoked(*it);
217 // Always fire the primary signed in account first.
218 FireRefreshTokenAvailable(signed_in_account);
220 for (std::vector<std::string>::const_iterator it = curr_account_ids.begin();
221 it != curr_account_ids.end(); it++) {
222 if (*it != signed_in_account) {
223 FireRefreshTokenAvailable(*it);
226 return true;
227 } else {
228 // Currently signed in account does not any longer exist among accounts on
229 // system together with all other accounts.
230 if (!signed_in_account.empty()) {
231 FireRefreshTokenRevoked(signed_in_account);
233 for (std::vector<std::string>::const_iterator it = prev_account_ids.begin();
234 it != prev_account_ids.end(); it++) {
235 if (*it == signed_in_account)
236 continue;
237 FireRefreshTokenRevoked(*it);
239 return false;
243 void AndroidProfileOAuth2TokenService::FireRefreshTokenAvailableFromJava(
244 JNIEnv* env,
245 jobject obj,
246 const jstring account_name) {
247 std::string account_id = ConvertJavaStringToUTF8(env, account_name);
248 AndroidProfileOAuth2TokenService::FireRefreshTokenAvailable(account_id);
251 void AndroidProfileOAuth2TokenService::FireRefreshTokenAvailable(
252 const std::string& account_id) {
253 // Notify native observers.
254 OAuth2TokenService::FireRefreshTokenAvailable(account_id);
255 // Notify Java observers.
256 JNIEnv* env = AttachCurrentThread();
257 ScopedJavaLocalRef<jstring> account_name =
258 ConvertUTF8ToJavaString(env, account_id);
259 Java_OAuth2TokenService_notifyRefreshTokenAvailable(
260 env, java_ref_.obj(), account_name.obj());
263 void AndroidProfileOAuth2TokenService::FireRefreshTokenRevokedFromJava(
264 JNIEnv* env,
265 jobject obj,
266 const jstring account_name) {
267 std::string account_id = ConvertJavaStringToUTF8(env, account_name);
268 AndroidProfileOAuth2TokenService::FireRefreshTokenRevoked(account_id);
271 void AndroidProfileOAuth2TokenService::FireRefreshTokenRevoked(
272 const std::string& account_id) {
273 // Notify native observers.
274 OAuth2TokenService::FireRefreshTokenRevoked(account_id);
275 // Notify Java observers.
276 JNIEnv* env = AttachCurrentThread();
277 ScopedJavaLocalRef<jstring> account_name =
278 ConvertUTF8ToJavaString(env, account_id);
279 Java_OAuth2TokenService_notifyRefreshTokenRevoked(
280 env, java_ref_.obj(), account_name.obj());
283 void AndroidProfileOAuth2TokenService::FireRefreshTokensLoadedFromJava(
284 JNIEnv* env,
285 jobject obj) {
286 AndroidProfileOAuth2TokenService::FireRefreshTokensLoaded();
289 void AndroidProfileOAuth2TokenService::FireRefreshTokensLoaded() {
290 // Notify native observers.
291 OAuth2TokenService::FireRefreshTokensLoaded();
292 // Notify Java observers.
293 JNIEnv* env = AttachCurrentThread();
294 Java_OAuth2TokenService_notifyRefreshTokensLoaded(
295 env, java_ref_.obj());
298 void AndroidProfileOAuth2TokenService::RevokeAllCredentials() {
299 std::vector<std::string> accounts = GetAccounts();
300 for (std::vector<std::string>::iterator it = accounts.begin();
301 it != accounts.end(); it++) {
302 FireRefreshTokenRevoked(*it);
306 // Called from Java when fetching of an OAuth2 token is finished. The
307 // |authToken| param is only valid when |result| is true.
308 void OAuth2TokenFetched(JNIEnv* env, jclass clazz,
309 jstring authToken,
310 jboolean result,
311 jlong nativeCallback) {
312 std::string token = ConvertJavaStringToUTF8(env, authToken);
313 scoped_ptr<FetchOAuth2TokenCallback> heap_callback(
314 reinterpret_cast<FetchOAuth2TokenCallback*>(nativeCallback));
315 // Android does not provide enough information to know if the credentials are
316 // wrong, so assume any error is transient by using CONNECTION_FAILED.
317 GoogleServiceAuthError err(result ?
318 GoogleServiceAuthError::NONE :
319 GoogleServiceAuthError::CONNECTION_FAILED);
320 heap_callback->Run(err, token, base::Time());
323 // static
324 bool AndroidProfileOAuth2TokenService::Register(JNIEnv* env) {
325 return RegisterNativesImpl(env);