GoogleAccountLogin.java revision d43e75adea6f394730828cbf830438e2bddaed4b
1539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott/* 2539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * Copyright (C) 2010 The Android Open Source Project 3539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * 4539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * Licensed under the Apache License, Version 2.0 (the "License"); 5539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * you may not use this file except in compliance with the License. 6539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * You may obtain a copy of the License at 7539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * 8539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * http://www.apache.org/licenses/LICENSE-2.0 9539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * 10539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * Unless required by applicable law or agreed to in writing, software 11539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * distributed under the License is distributed on an "AS IS" BASIS, 12539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * See the License for the specific language governing permissions and 14539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott * limitations under the License. 15539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott */ 16539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 17539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottpackage com.android.browser; 18539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 19539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport org.apache.http.Header; 20539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport org.apache.http.HeaderIterator; 21539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport org.apache.http.HttpEntity; 22539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport org.apache.http.HttpResponse; 23539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport org.apache.http.HttpStatus; 24539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport org.apache.http.client.methods.HttpPost; 25539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport org.apache.http.util.EntityUtils; 26539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 27539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.accounts.Account; 28539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.accounts.AccountManager; 29539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.accounts.AccountManagerCallback; 30539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.accounts.AccountManagerFuture; 31539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.app.Activity; 32cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scottimport android.app.ProgressDialog; 33539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.content.Context; 34539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.content.DialogInterface; 35539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.content.DialogInterface.OnCancelListener; 36cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scottimport android.content.SharedPreferences.Editor; 37539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.net.http.AndroidHttpClient; 38539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.net.Uri; 39539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.os.Bundle; 40cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scottimport android.os.Handler; 41cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scottimport android.preference.PreferenceManager; 42a4af6dce2ebe6c4979524461047fcc0eb76fce84Patrick Scottimport android.util.Log; 43ef18de60e02b4b2a7227d9e9751487cc74baec36Patrick Scottimport android.webkit.CookieSyncManager; 44539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.webkit.WebView; 45539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.webkit.WebViewClient; 46539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 4797efb1e650b356d3fc81ff531544383362759d77Patrick Scottimport java.util.StringTokenizer; 48539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 497d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scottpublic class GoogleAccountLogin implements Runnable, 50539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott AccountManagerCallback<Bundle>, OnCancelListener { 51539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 52a4af6dce2ebe6c4979524461047fcc0eb76fce84Patrick Scott private static final String LOGTAG = "BrowserLogin"; 53a4af6dce2ebe6c4979524461047fcc0eb76fce84Patrick Scott 54539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // Url for issuing the uber token. 55539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private Uri ISSUE_AUTH_TOKEN_URL = Uri.parse( 56539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott "https://www.google.com/accounts/IssueAuthToken?service=gaia&Session=false"); 57539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // Url for signing into a particular service. 58a4af6dce2ebe6c4979524461047fcc0eb76fce84Patrick Scott private static final Uri TOKEN_AUTH_URL = Uri.parse( 59539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott "https://www.google.com/accounts/TokenAuth"); 60539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // Google account type 61a4af6dce2ebe6c4979524461047fcc0eb76fce84Patrick Scott private static final String GOOGLE = "com.google"; 62cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott // Last auto login time 63cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott private static final String PREF_AUTOLOGIN_TIME = "last_autologin_time"; 64cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott // A week in milliseconds (7*24*60*60*1000) 65cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott private static final long WEEK_IN_MILLIS = 604800000L; 66539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 67539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private final Activity mActivity; 68539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private final Account mAccount; 69539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private final WebView mWebView; 70cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott // Does not matter if this is initialized in a non-ui thread. 71cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott // Dialog.dismiss() will post to the right handler. 72cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott private final Handler mHandler = new Handler(); 73539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private Runnable mRunnable; 74cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott private ProgressDialog mProgressDialog; 75539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 76539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // SID and LSID retrieval process. 77539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private String mSid; 78539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private String mLsid; 79539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private int mState; // {NONE(0), SID(1), LSID(2)} 807d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott private boolean mTokensInvalidated; 81539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 82d43e75adea6f394730828cbf830438e2bddaed4bPatrick Scott private GoogleAccountLogin(Activity activity, Account account, 83cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott Runnable runnable) { 84539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mActivity = activity; 85d43e75adea6f394730828cbf830438e2bddaed4bPatrick Scott mAccount = account; 86539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mWebView = new WebView(mActivity); 87cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott mRunnable = runnable; 88cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott 89ef18de60e02b4b2a7227d9e9751487cc74baec36Patrick Scott // XXX: Doing pre-login causes onResume to skip calling 90ef18de60e02b4b2a7227d9e9751487cc74baec36Patrick Scott // resumeWebViewTimers. So to avoid problems with timers not running, we 91ef18de60e02b4b2a7227d9e9751487cc74baec36Patrick Scott // duplicate the work here using the off-screen WebView. 92ef18de60e02b4b2a7227d9e9751487cc74baec36Patrick Scott CookieSyncManager.getInstance().startSync(); 93ef18de60e02b4b2a7227d9e9751487cc74baec36Patrick Scott mWebView.resumeTimers(); 94ef18de60e02b4b2a7227d9e9751487cc74baec36Patrick Scott 95539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mWebView.setWebViewClient(new WebViewClient() { 96539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott @Override 97539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott public boolean shouldOverrideUrlLoading(WebView view, String url) { 98539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott return false; 99539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 100539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott @Override 101539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott public void onPageFinished(WebView view, String url) { 102cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott saveLoginTime(); 103539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott done(); 104539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 105539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott }); 106539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 107539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 108cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott private void saveLoginTime() { 109cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott Editor ed = PreferenceManager. 110cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott getDefaultSharedPreferences(mActivity).edit(); 111cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott ed.putLong(PREF_AUTOLOGIN_TIME, System.currentTimeMillis()); 112cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott ed.apply(); 113cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott } 114cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott 1157d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott // Runnable 116539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott @Override 117539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott public void run() { 118539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott String url = ISSUE_AUTH_TOKEN_URL.buildUpon() 119539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott .appendQueryParameter("SID", mSid) 120539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott .appendQueryParameter("LSID", mLsid) 121539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott .build().toString(); 122081caaa34ab5af0694087c3203e39be25797455aPatrick Scott // Check mRunnable to see if the request has been canceled. Otherwise 123081caaa34ab5af0694087c3203e39be25797455aPatrick Scott // we might access a destroyed WebView. 124081caaa34ab5af0694087c3203e39be25797455aPatrick Scott String ua = null; 125081caaa34ab5af0694087c3203e39be25797455aPatrick Scott synchronized (this) { 126081caaa34ab5af0694087c3203e39be25797455aPatrick Scott if (mRunnable == null) { 127081caaa34ab5af0694087c3203e39be25797455aPatrick Scott return; 128081caaa34ab5af0694087c3203e39be25797455aPatrick Scott } 129081caaa34ab5af0694087c3203e39be25797455aPatrick Scott ua = mWebView.getSettings().getUserAgentString(); 130081caaa34ab5af0694087c3203e39be25797455aPatrick Scott } 131539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // Intentionally not using Proxy. 132081caaa34ab5af0694087c3203e39be25797455aPatrick Scott AndroidHttpClient client = AndroidHttpClient.newInstance(ua); 133539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott HttpPost request = new HttpPost(url); 134539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 135539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott String result = null; 136539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott try { 137539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott HttpResponse response = client.execute(request); 1387d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott int status = response.getStatusLine().getStatusCode(); 1397d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott if (status != HttpStatus.SC_OK) { 140a4af6dce2ebe6c4979524461047fcc0eb76fce84Patrick Scott Log.d(LOGTAG, "LOGIN_FAIL: Bad status from auth url " 1417d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott + status + ": " 142a4af6dce2ebe6c4979524461047fcc0eb76fce84Patrick Scott + response.getStatusLine().getReasonPhrase()); 1437d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott // Invalidate the tokens once just in case the 403 was for other 1447d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott // reasons. 1457d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott if (status == HttpStatus.SC_FORBIDDEN && !mTokensInvalidated) { 1467d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott Log.d(LOGTAG, "LOGIN_FAIL: Invalidating tokens..."); 1477d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott // Need to regenerate the auth tokens and try again. 1487d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott invalidateTokens(); 1497d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott // XXX: Do not touch any more member variables from this 1507d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott // thread as a second thread will handle the next login 1517d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott // attempt. 1527d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott return; 1537d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott } 154539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott done(); 155539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott return; 156539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 157539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott HttpEntity entity = response.getEntity(); 158539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott if (entity == null) { 159a4af6dce2ebe6c4979524461047fcc0eb76fce84Patrick Scott Log.d(LOGTAG, "LOGIN_FAIL: Null entity in response"); 160539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott done(); 161539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott return; 162539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 163539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott result = EntityUtils.toString(entity, "UTF-8"); 164539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } catch (Exception e) { 165a4af6dce2ebe6c4979524461047fcc0eb76fce84Patrick Scott Log.d(LOGTAG, "LOGIN_FAIL: Exception acquiring uber token " + e); 166539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott request.abort(); 167539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott done(); 168539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott return; 169539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } finally { 170539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott client.close(); 171539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 172539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott final String newUrl = TOKEN_AUTH_URL.buildUpon() 173539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott .appendQueryParameter("source", "android-browser") 174539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott .appendQueryParameter("auth", result) 175539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott .appendQueryParameter("continue", 176539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott BrowserSettings.getFactoryResetHomeUrl(mActivity)) 177539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott .build().toString(); 178539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mActivity.runOnUiThread(new Runnable() { 179539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott @Override public void run() { 180081caaa34ab5af0694087c3203e39be25797455aPatrick Scott // Check mRunnable in case the request has been canceled. This 181081caaa34ab5af0694087c3203e39be25797455aPatrick Scott // is most likely not necessary as run() is the only non-UI 182081caaa34ab5af0694087c3203e39be25797455aPatrick Scott // thread that calls done() but I am paranoid. 183081caaa34ab5af0694087c3203e39be25797455aPatrick Scott synchronized (GoogleAccountLogin.this) { 184081caaa34ab5af0694087c3203e39be25797455aPatrick Scott if (mRunnable == null) { 185081caaa34ab5af0694087c3203e39be25797455aPatrick Scott return; 186081caaa34ab5af0694087c3203e39be25797455aPatrick Scott } 187081caaa34ab5af0694087c3203e39be25797455aPatrick Scott mWebView.loadUrl(newUrl); 188081caaa34ab5af0694087c3203e39be25797455aPatrick Scott } 189539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 190539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott }); 191539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 192539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 1937d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott private void invalidateTokens() { 1947d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott AccountManager am = AccountManager.get(mActivity); 1957d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott am.invalidateAuthToken(GOOGLE, mSid); 1967d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott am.invalidateAuthToken(GOOGLE, mLsid); 1977d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott mTokensInvalidated = true; 1987d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott mState = 1; // SID 1997d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott am.getAuthToken(mAccount, "SID", null, mActivity, this, null); 2007d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott } 2017d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott 202539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // AccountManager callbacks. 203539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott @Override 204539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott public void run(AccountManagerFuture<Bundle> value) { 205539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott try { 206539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott String id = value.getResult().getString( 207539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott AccountManager.KEY_AUTHTOKEN); 208539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott switch (mState) { 209539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott default: 210539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott case 0: 211539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott throw new IllegalStateException( 212539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott "Impossible to get into this state"); 213539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott case 1: 214539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mSid = id; 215539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mState = 2; // LSID 216539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott AccountManager.get(mActivity).getAuthToken( 217539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mAccount, "LSID", null, mActivity, this, null); 218539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott break; 219539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott case 2: 220539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mLsid = id; 2217d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott new Thread(this).start(); 222539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott break; 223539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 224539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } catch (Exception e) { 225a4af6dce2ebe6c4979524461047fcc0eb76fce84Patrick Scott Log.d(LOGTAG, "LOGIN_FAIL: Exception in state " + mState + " " + e); 226539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // For all exceptions load the original signin page. 227539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // TODO: toast login failed? 228539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott done(); 229539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 230539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 231539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 232cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott // Start the login process if auto-login is enabled and the user is not 233cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott // already logged in. 234cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott public static void startLoginIfNeeded(Activity activity, 235d43e75adea6f394730828cbf830438e2bddaed4bPatrick Scott Runnable runnable) { 236d43e75adea6f394730828cbf830438e2bddaed4bPatrick Scott // Already logged in? 237d43e75adea6f394730828cbf830438e2bddaed4bPatrick Scott if (isLoggedIn(activity)) { 238cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott runnable.run(); 239cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott return; 240cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott } 241cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott 242cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott // No account found? 243d43e75adea6f394730828cbf830438e2bddaed4bPatrick Scott Account[] accounts = getAccounts(activity); 244d43e75adea6f394730828cbf830438e2bddaed4bPatrick Scott if (accounts == null || accounts.length == 0) { 245cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott runnable.run(); 246cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott return; 247cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott } 248cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott 249cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott GoogleAccountLogin login = 250d43e75adea6f394730828cbf830438e2bddaed4bPatrick Scott new GoogleAccountLogin(activity, accounts[0], runnable); 251cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott login.startLogin(); 252cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott } 253cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott 254cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott private void startLogin() { 255cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott mProgressDialog = ProgressDialog.show(mActivity, 256cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott mActivity.getString(R.string.pref_autologin_title), 257cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott mActivity.getString(R.string.pref_autologin_progress, 258cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott mAccount.name), 259cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott true /* indeterminate */, 260cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott true /* cancelable */, 261cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott this); 262539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mState = 1; // SID 263539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott AccountManager.get(mActivity).getAuthToken( 264539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mAccount, "SID", null, mActivity, this, null); 265539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 266539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 267d43e75adea6f394730828cbf830438e2bddaed4bPatrick Scott private static Account[] getAccounts(Context ctx) { 268539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott return AccountManager.get(ctx).getAccountsByType(GOOGLE); 269539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 270539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 271d43e75adea6f394730828cbf830438e2bddaed4bPatrick Scott // Checks if we already did pre-login. 272d43e75adea6f394730828cbf830438e2bddaed4bPatrick Scott private static boolean isLoggedIn(Context ctx) { 273cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott // See if we last logged in less than a week ago. 274cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott long lastLogin = PreferenceManager. 275cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott getDefaultSharedPreferences(ctx). 276cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott getLong(PREF_AUTOLOGIN_TIME, -1); 277cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott if (lastLogin == -1) { 278cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott return false; 279cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott } 280d43e75adea6f394730828cbf830438e2bddaed4bPatrick Scott return true; 28197efb1e650b356d3fc81ff531544383362759d77Patrick Scott } 28297efb1e650b356d3fc81ff531544383362759d77Patrick Scott 283539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // Used to indicate that the Browser should continue loading the main page. 284539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // This can happen on success, error, or timeout. 285539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private synchronized void done() { 286539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott if (mRunnable != null) { 287a4af6dce2ebe6c4979524461047fcc0eb76fce84Patrick Scott Log.d(LOGTAG, "Finished login attempt for " + mAccount.name); 288539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mActivity.runOnUiThread(mRunnable); 289cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott 290cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott // Post a delayed message to dismiss the dialog in order to avoid a 291cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott // flash of the progress dialog. 292cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott mHandler.postDelayed(new Runnable() { 293cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott @Override public void run() { 294cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott mProgressDialog.dismiss(); 295cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott } 296065a7ee11d226f755d217bee100c585f803a2e0aPatrick Scott }, 2000); 297cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott 298539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mRunnable = null; 299539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mWebView.destroy(); 300539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 301539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 302539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 303539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // Called by the progress dialog on startup. 304539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott public void onCancel(DialogInterface unused) { 305539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott done(); 306539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 307539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott} 308