Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(275)

Side by Side Diff: blimp/client/app/android/java/src/org/chromium/blimp/auth/TokenSourceImpl.java

Issue 2493333002: Move Java Blimp shell code to app subpackage (Closed)
Patch Set: Merge branch 'refs/heads/master' into blimp-shell-integration Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.blimp.auth;
6
7 import android.accounts.Account;
8 import android.accounts.AccountManager;
9 import android.content.Context;
10 import android.content.Intent;
11 import android.content.SharedPreferences;
12 import android.os.AsyncTask;
13
14 import com.google.android.gms.auth.GoogleAuthException;
15 import com.google.android.gms.auth.GoogleAuthUtil;
16 import com.google.android.gms.auth.GooglePlayServicesAvailabilityException;
17 import com.google.android.gms.auth.UserRecoverableNotifiedException;
18 import com.google.android.gms.common.ConnectionResult;
19
20 import org.chromium.base.ContextUtils;
21 import org.chromium.base.Log;
22 import org.chromium.base.ThreadUtils;
23 import org.chromium.blimp.R;
24
25 import java.io.IOException;
26 import java.util.concurrent.atomic.AtomicBoolean;
27
28 /**
29 * An implementation of TokenSource that handles querying {@link GoogleAuthUtil} for a valid
30 * authentication token for a particular user account. The user account will be saved as an
31 * application preference once set. See {@link TokenSource} for information on how callers know
32 * whether or not an account is set and how they set one.
33 */
34 public class TokenSourceImpl implements TokenSource {
35 private static final String ACCOUNT_NAME_PREF = "BlimpAccount";
36 // Prefix with oauth2: to make sure we get back an oauth2 token.
37 private static final String ACCOUNT_OAUTH2_SCOPE =
38 "oauth2:https://www.googleapis.com/auth/userinfo.email";
39 private static final String ACCOUNT_TYPE = "com.google";
40 private static final String TAG = "BlimpTokenSource";
41
42 private final Context mAppContext;
43
44 private TokenSource.Callback mCallback;
45 private AsyncTask<String, Void, String> mTokenQueryTask;
46
47 /**
48 * Creates a {@link TokenSourceImpl} that will load and save account informa tion from the
49 * application {@link Context} given by {@code context}.
50 * @param context
51 */
52 public TokenSourceImpl(Context context) {
53 mAppContext = context.getApplicationContext();
54 }
55
56 // TokenSource implementation.
57 @Override
58 public void destroy() {
59 ThreadUtils.assertOnUiThread();
60
61 if (isRetrievingToken()) {
62 mTokenQueryTask.cancel(true);
63 }
64 }
65
66 @Override
67 public void setCallback(TokenSource.Callback callback) {
68 ThreadUtils.assertOnUiThread();
69
70 mCallback = callback;
71 }
72
73 @Override
74 public void getToken() {
75 ThreadUtils.assertOnUiThread();
76
77 if (isRetrievingToken()) {
78 mTokenQueryTask.cancel(true);
79 mTokenQueryTask = null;
80 }
81
82 if (mCallback == null) return;
83
84 // Find the current account tracked by settings.
85 SharedPreferences preferences = ContextUtils.getAppSharedPreferences();
86 String accountName = preferences.getString(ACCOUNT_NAME_PREF, null);
87
88 if (accountName == null || !doesAccountExist(accountName)) {
89 // Remove any old preference value in case the account is invalid.
90 preferences.edit().remove(ACCOUNT_NAME_PREF).apply();
91
92 // Trigger account selection.
93 mCallback.onNeedsAccountToBeSelected(getAccountChooserIntent());
94 return;
95 }
96
97 mTokenQueryTask = new TokenQueryTask();
98 mTokenQueryTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, accoun tName);
99 }
100
101 @Override
102 public boolean isRetrievingToken() {
103 ThreadUtils.assertOnUiThread();
104
105 return mTokenQueryTask != null && mTokenQueryTask.getStatus() == AsyncTa sk.Status.RUNNING;
106 }
107
108 @Override
109 public int tokenIsInvalid(String token) {
110 ThreadUtils.assertOnUiThread();
111
112 // TODO(dtrainor): Handle failure cases for tokenIsInvalid.
113 try {
114 GoogleAuthUtil.clearToken(mAppContext, token);
115 } catch (GooglePlayServicesAvailabilityException ex) {
116 return ex.getConnectionStatusCode();
117 } catch (GoogleAuthException ex) {
118 Log.e(TAG, "Authentication exception during token query.");
119 return ConnectionResult.SIGN_IN_FAILED;
120 } catch (IOException ex) {
121 Log.e(TAG, "IOException during token query.");
122 return ConnectionResult.SIGN_IN_FAILED;
123 }
124 return ConnectionResult.SUCCESS;
125 }
126
127 @Override
128 public void onAccountSelected(Intent data) {
129 ThreadUtils.assertOnUiThread();
130
131 String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME );
132 SharedPreferences preferences = ContextUtils.getAppSharedPreferences();
133 preferences.edit().putString(ACCOUNT_NAME_PREF, accountName).apply();
134 }
135
136 @SuppressWarnings("deprecation")
137 private Intent getAccountChooserIntent() {
138 // TODO(dtrainor): Change this to com.google.android.gms.common.AccountP icker.
139 return AccountManager.newChooseAccountIntent(null, null, new String[] {A CCOUNT_TYPE}, false,
140 mAppContext.getString(R.string.signin_chooser_description), null , null, null);
141 }
142
143 private boolean doesAccountExist(String accountName) {
144 Account[] accounts = AccountManager.get(mAppContext).getAccountsByType(A CCOUNT_TYPE);
145 for (Account account : accounts) {
146 if (account.name.equals(accountName)) return true;
147 }
148
149 return false;
150 }
151
152 private class TokenQueryTask extends AsyncTask<String, Void, String> {
153 private final AtomicBoolean mIsRecoverable = new AtomicBoolean();
154
155 @Override
156 protected String doInBackground(String... params) {
157 try {
158 return GoogleAuthUtil.getTokenWithNotification(
159 mAppContext, params[0], ACCOUNT_OAUTH2_SCOPE, null);
160 } catch (UserRecoverableNotifiedException ex) {
161 // TODO(dtrainor): Does it make sense for this to be true if we can't recover until
162 // the user performs some action?
163 mIsRecoverable.set(true);
164 } catch (IOException ex) {
165 mIsRecoverable.set(true);
166 } catch (GoogleAuthException ex) {
167 mIsRecoverable.set(false);
168 }
169 return null;
170 }
171
172 @Override
173 protected void onPostExecute(String token) {
174 if (mCallback == null || isCancelled()) return;
175
176 if (token == null) {
177 mCallback.onTokenUnavailable(mIsRecoverable.get());
178 } else {
179 mCallback.onTokenReceived(token);
180 }
181 if (mTokenQueryTask == TokenQueryTask.this) mTokenQueryTask = null;
182 }
183 }
184 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698