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 android.accounts.Account; 20539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.accounts.AccountManager; 21539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.accounts.AccountManagerCallback; 22539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.accounts.AccountManagerFuture; 23539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.app.Activity; 24cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scottimport android.app.ProgressDialog; 25539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.content.Context; 26539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.content.DialogInterface; 27539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.content.DialogInterface.OnCancelListener; 28cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scottimport android.content.SharedPreferences.Editor; 29539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.net.Uri; 30539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.os.Bundle; 31a4af6dce2ebe6c4979524461047fcc0eb76fce84Patrick Scottimport android.util.Log; 32ef18de60e02b4b2a7227d9e9751487cc74baec36Patrick Scottimport android.webkit.CookieSyncManager; 33539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.webkit.WebView; 34539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scottimport android.webkit.WebViewClient; 35539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 363a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamathimport java.io.IOException; 373a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamathimport java.io.InputStream; 383a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamathimport java.net.HttpURLConnection; 393a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamathimport java.net.Proxy; 403a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamathimport java.net.URL; 413a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamathimport java.nio.charset.Charset; 423a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamathimport java.nio.charset.IllegalCharsetNameException; 433a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamathimport java.nio.charset.UnsupportedCharsetException; 443a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamathimport libcore.io.Streams; 453a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamathimport libcore.net.http.ResponseUtils; 46ba287c2673922ac51c4e4258224574411c0117e1John Reck 477d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scottpublic class GoogleAccountLogin implements Runnable, 48539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott AccountManagerCallback<Bundle>, OnCancelListener { 49539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 50a4af6dce2ebe6c4979524461047fcc0eb76fce84Patrick Scott private static final String LOGTAG = "BrowserLogin"; 51a4af6dce2ebe6c4979524461047fcc0eb76fce84Patrick Scott 52539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // Url for issuing the uber token. 53539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private Uri ISSUE_AUTH_TOKEN_URL = Uri.parse( 54539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott "https://www.google.com/accounts/IssueAuthToken?service=gaia&Session=false"); 55539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // Url for signing into a particular service. 56a4af6dce2ebe6c4979524461047fcc0eb76fce84Patrick Scott private static final Uri TOKEN_AUTH_URL = Uri.parse( 57539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott "https://www.google.com/accounts/TokenAuth"); 58539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // Google account type 59a4af6dce2ebe6c4979524461047fcc0eb76fce84Patrick Scott private static final String GOOGLE = "com.google"; 60cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott // Last auto login time 61ba287c2673922ac51c4e4258224574411c0117e1John Reck public static final String PREF_AUTOLOGIN_TIME = "last_autologin_time"; 62539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 63539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private final Activity mActivity; 64539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private final Account mAccount; 65539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private final WebView mWebView; 66539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private Runnable mRunnable; 67cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott private ProgressDialog mProgressDialog; 68539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 69539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // SID and LSID retrieval process. 70539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private String mSid; 71539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private String mLsid; 72539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private int mState; // {NONE(0), SID(1), LSID(2)} 737d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott private boolean mTokensInvalidated; 749bbd9314fee5f284ff254d7063c30d147fe47454Ben Murdoch private String mUserAgent; 75539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 76d43e75adea6f394730828cbf830438e2bddaed4bPatrick Scott private GoogleAccountLogin(Activity activity, Account account, 77cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott Runnable runnable) { 78539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mActivity = activity; 79d43e75adea6f394730828cbf830438e2bddaed4bPatrick Scott mAccount = account; 80539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mWebView = new WebView(mActivity); 81cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott mRunnable = runnable; 829bbd9314fee5f284ff254d7063c30d147fe47454Ben Murdoch mUserAgent = mWebView.getSettings().getUserAgentString(); 83cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott 84ef18de60e02b4b2a7227d9e9751487cc74baec36Patrick Scott // XXX: Doing pre-login causes onResume to skip calling 85ef18de60e02b4b2a7227d9e9751487cc74baec36Patrick Scott // resumeWebViewTimers. So to avoid problems with timers not running, we 86ef18de60e02b4b2a7227d9e9751487cc74baec36Patrick Scott // duplicate the work here using the off-screen WebView. 87ef18de60e02b4b2a7227d9e9751487cc74baec36Patrick Scott CookieSyncManager.getInstance().startSync(); 88e1dbb956d762c3f07033f247c05270a9882a79a7Mathew Inwood WebViewTimersControl.getInstance().onBrowserActivityResume(mWebView); 89ef18de60e02b4b2a7227d9e9751487cc74baec36Patrick Scott 90539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mWebView.setWebViewClient(new WebViewClient() { 91539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott @Override 92539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott public boolean shouldOverrideUrlLoading(WebView view, String url) { 93539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott return false; 94539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 95539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott @Override 96539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott public void onPageFinished(WebView view, String url) { 97539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott done(); 98539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 99539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott }); 100539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 101539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 102cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott private void saveLoginTime() { 103ba287c2673922ac51c4e4258224574411c0117e1John Reck Editor ed = BrowserSettings.getInstance().getPreferences().edit(); 104cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott ed.putLong(PREF_AUTOLOGIN_TIME, System.currentTimeMillis()); 105cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott ed.apply(); 106cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott } 107cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott 1087d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott // Runnable 109539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott @Override 110539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott public void run() { 1113a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamath String urlString = ISSUE_AUTH_TOKEN_URL.buildUpon() 112539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott .appendQueryParameter("SID", mSid) 113539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott .appendQueryParameter("LSID", mLsid) 114539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott .build().toString(); 115539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 1163a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamath HttpURLConnection connection = null; 1173a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamath String authToken = null; 118539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott try { 1193a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamath URL url = new URL(urlString); 1203a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamath // Intentionally not using Proxy. 1213a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamath connection = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY); 1223a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamath connection.setRequestMethod("POST"); 1233a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamath connection.setRequestProperty("User-Agent", mUserAgent); 1243a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamath 1253a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamath int status = connection.getResponseCode(); 1263a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamath if (status != HttpURLConnection.HTTP_OK) { 127a4af6dce2ebe6c4979524461047fcc0eb76fce84Patrick Scott Log.d(LOGTAG, "LOGIN_FAIL: Bad status from auth url " 1283a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamath + status + ": " + connection.getResponseMessage()); 1297d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott // Invalidate the tokens once just in case the 403 was for other 1307d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott // reasons. 1313a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamath if (status == HttpURLConnection.HTTP_FORBIDDEN && !mTokensInvalidated) { 1327d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott Log.d(LOGTAG, "LOGIN_FAIL: Invalidating tokens..."); 1337d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott // Need to regenerate the auth tokens and try again. 1347d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott invalidateTokens(); 1357d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott // XXX: Do not touch any more member variables from this 1367d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott // thread as a second thread will handle the next login 1377d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott // attempt. 1387d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott return; 1397d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott } 140539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott done(); 141539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott return; 142539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 1433a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamath 1443a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamath final Charset responseCharset = ResponseUtils.responseCharset( 1453a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamath connection.getContentType()); 1463a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamath byte[] responseBytes = Streams.readFully(connection.getInputStream()); 1473a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamath authToken = new String(responseBytes, responseCharset); 148539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } catch (Exception e) { 149a4af6dce2ebe6c4979524461047fcc0eb76fce84Patrick Scott Log.d(LOGTAG, "LOGIN_FAIL: Exception acquiring uber token " + e); 150539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott done(); 151539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott return; 152539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } finally { 1533a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamath if (connection != null) { 1543a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamath connection.disconnect(); 1553a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamath } 156539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 1573a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamath 158539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott final String newUrl = TOKEN_AUTH_URL.buildUpon() 159539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott .appendQueryParameter("source", "android-browser") 1603a2cf8007db4f3258b94fdcb74c147220350aa36Narayan Kamath .appendQueryParameter("auth", authToken) 161539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott .appendQueryParameter("continue", 162539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott BrowserSettings.getFactoryResetHomeUrl(mActivity)) 163539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott .build().toString(); 164539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mActivity.runOnUiThread(new Runnable() { 165539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott @Override public void run() { 166081caaa34ab5af0694087c3203e39be25797455aPatrick Scott // Check mRunnable in case the request has been canceled. This 167081caaa34ab5af0694087c3203e39be25797455aPatrick Scott // is most likely not necessary as run() is the only non-UI 168081caaa34ab5af0694087c3203e39be25797455aPatrick Scott // thread that calls done() but I am paranoid. 169081caaa34ab5af0694087c3203e39be25797455aPatrick Scott synchronized (GoogleAccountLogin.this) { 170081caaa34ab5af0694087c3203e39be25797455aPatrick Scott if (mRunnable == null) { 171081caaa34ab5af0694087c3203e39be25797455aPatrick Scott return; 172081caaa34ab5af0694087c3203e39be25797455aPatrick Scott } 173081caaa34ab5af0694087c3203e39be25797455aPatrick Scott mWebView.loadUrl(newUrl); 174081caaa34ab5af0694087c3203e39be25797455aPatrick Scott } 175539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 176539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott }); 177539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 178539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 1797d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott private void invalidateTokens() { 1807d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott AccountManager am = AccountManager.get(mActivity); 1817d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott am.invalidateAuthToken(GOOGLE, mSid); 1827d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott am.invalidateAuthToken(GOOGLE, mLsid); 1837d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott mTokensInvalidated = true; 1847d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott mState = 1; // SID 1857d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott am.getAuthToken(mAccount, "SID", null, mActivity, this, null); 1867d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott } 1877d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott 188539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // AccountManager callbacks. 189539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott @Override 190539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott public void run(AccountManagerFuture<Bundle> value) { 191539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott try { 192539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott String id = value.getResult().getString( 193539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott AccountManager.KEY_AUTHTOKEN); 194539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott switch (mState) { 195539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott default: 196539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott case 0: 197539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott throw new IllegalStateException( 198539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott "Impossible to get into this state"); 199539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott case 1: 200539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mSid = id; 201539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mState = 2; // LSID 202539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott AccountManager.get(mActivity).getAuthToken( 203539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mAccount, "LSID", null, mActivity, this, null); 204539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott break; 205539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott case 2: 206539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mLsid = id; 2077d50a9364107c21e3358e1dbc51a06359a5287fbPatrick Scott new Thread(this).start(); 208539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott break; 209539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 210539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } catch (Exception e) { 211a4af6dce2ebe6c4979524461047fcc0eb76fce84Patrick Scott Log.d(LOGTAG, "LOGIN_FAIL: Exception in state " + mState + " " + e); 212539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // For all exceptions load the original signin page. 213539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // TODO: toast login failed? 214539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott done(); 215539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 216539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 217539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 218cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott // Start the login process if auto-login is enabled and the user is not 219cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott // already logged in. 220cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott public static void startLoginIfNeeded(Activity activity, 221d43e75adea6f394730828cbf830438e2bddaed4bPatrick Scott Runnable runnable) { 222d43e75adea6f394730828cbf830438e2bddaed4bPatrick Scott // Already logged in? 223ba287c2673922ac51c4e4258224574411c0117e1John Reck if (isLoggedIn()) { 224cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott runnable.run(); 225cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott return; 226cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott } 227cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott 228cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott // No account found? 229d43e75adea6f394730828cbf830438e2bddaed4bPatrick Scott Account[] accounts = getAccounts(activity); 230d43e75adea6f394730828cbf830438e2bddaed4bPatrick Scott if (accounts == null || accounts.length == 0) { 231cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott runnable.run(); 232cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott return; 233cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott } 234cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott 235cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott GoogleAccountLogin login = 236d43e75adea6f394730828cbf830438e2bddaed4bPatrick Scott new GoogleAccountLogin(activity, accounts[0], runnable); 237cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott login.startLogin(); 238cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott } 239cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott 240cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott private void startLogin() { 241ba287c2673922ac51c4e4258224574411c0117e1John Reck saveLoginTime(); 242cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott mProgressDialog = ProgressDialog.show(mActivity, 243cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott mActivity.getString(R.string.pref_autologin_title), 244cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott mActivity.getString(R.string.pref_autologin_progress, 245cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott mAccount.name), 246cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott true /* indeterminate */, 247cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott true /* cancelable */, 248cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott this); 249539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mState = 1; // SID 250539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott AccountManager.get(mActivity).getAuthToken( 251539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mAccount, "SID", null, mActivity, this, null); 252539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 253539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 254d43e75adea6f394730828cbf830438e2bddaed4bPatrick Scott private static Account[] getAccounts(Context ctx) { 255539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott return AccountManager.get(ctx).getAccountsByType(GOOGLE); 256539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 257539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 258d43e75adea6f394730828cbf830438e2bddaed4bPatrick Scott // Checks if we already did pre-login. 259ba287c2673922ac51c4e4258224574411c0117e1John Reck private static boolean isLoggedIn() { 260cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott // See if we last logged in less than a week ago. 261ba287c2673922ac51c4e4258224574411c0117e1John Reck long lastLogin = BrowserSettings.getInstance().getPreferences() 262ba287c2673922ac51c4e4258224574411c0117e1John Reck .getLong(PREF_AUTOLOGIN_TIME, -1); 263cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott if (lastLogin == -1) { 264cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott return false; 265cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott } 266d43e75adea6f394730828cbf830438e2bddaed4bPatrick Scott return true; 26797efb1e650b356d3fc81ff531544383362759d77Patrick Scott } 26897efb1e650b356d3fc81ff531544383362759d77Patrick Scott 269539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // Used to indicate that the Browser should continue loading the main page. 270539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // This can happen on success, error, or timeout. 271539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott private synchronized void done() { 272539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott if (mRunnable != null) { 273a4af6dce2ebe6c4979524461047fcc0eb76fce84Patrick Scott Log.d(LOGTAG, "Finished login attempt for " + mAccount.name); 274539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mActivity.runOnUiThread(mRunnable); 275cd135089d54a8c003f7b0a35d88b3230f0a206b5Patrick Scott 276cf1df73719e171915eed887a5f06916158e42f04John Reck try { 277cf1df73719e171915eed887a5f06916158e42f04John Reck mProgressDialog.dismiss(); 278cf1df73719e171915eed887a5f06916158e42f04John Reck } catch (Exception e) { 279cf1df73719e171915eed887a5f06916158e42f04John Reck // TODO: Switch to a managed dialog solution (DialogFragment?) 280cf1df73719e171915eed887a5f06916158e42f04John Reck // Also refactor this class, it doesn't 281cf1df73719e171915eed887a5f06916158e42f04John Reck // play nice with the activity lifecycle, leading to issues 282cf1df73719e171915eed887a5f06916158e42f04John Reck // with the dialog it manages 283cf1df73719e171915eed887a5f06916158e42f04John Reck Log.w(LOGTAG, "Failed to dismiss mProgressDialog: " + e.getMessage()); 284cf1df73719e171915eed887a5f06916158e42f04John Reck } 285539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott mRunnable = null; 286474c927a76d4a6b12e942ba4bde3a7db18a1a332John Reck mActivity.runOnUiThread(new Runnable() { 287474c927a76d4a6b12e942ba4bde3a7db18a1a332John Reck @Override 288474c927a76d4a6b12e942ba4bde3a7db18a1a332John Reck public void run() { 289474c927a76d4a6b12e942ba4bde3a7db18a1a332John Reck mWebView.destroy(); 290474c927a76d4a6b12e942ba4bde3a7db18a1a332John Reck } 291474c927a76d4a6b12e942ba4bde3a7db18a1a332John Reck }); 292539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 293539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 294539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott 295539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott // Called by the progress dialog on startup. 296539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott public void onCancel(DialogInterface unused) { 297539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott done(); 298539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott } 2990fba5d9470f3b98d5aa61ae7392164450baf73deMichael Kolb 300539e2eced0f35144d7841477e5cdc2d8c521e82aPatrick Scott} 301