Re-login after a week.

Refactor GoogleAccountLogin to handle the progress dialog.  Store the last login
time and login after a week to refresh cookies.

Bug: 3367395
Change-Id: I62a277610af5b642f51cc775f17806c558812d4a
diff --git a/src/com/android/browser/BrowserActivity.java b/src/com/android/browser/BrowserActivity.java
index 527f025..ec09673 100644
--- a/src/com/android/browser/BrowserActivity.java
+++ b/src/com/android/browser/BrowserActivity.java
@@ -19,14 +19,12 @@
 import com.google.common.annotations.VisibleForTesting;
 
 import android.app.Activity;
-import android.app.ProgressDialog;
 import android.content.Intent;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.PixelFormat;
 import android.os.Bundle;
-import android.os.Handler;
 import android.util.Log;
 import android.view.ActionMode;
 import android.view.ContextMenu;
@@ -113,36 +111,12 @@
             icicle = state;
         }
 
-        String account = settings.getAutoLoginAccount(this);
-        if (settings.isAutoLoginEnabled() && account != null &&
-                !GoogleAccountLogin.isLoggedIn()) {
-            GoogleAccountLogin login =
-                    new GoogleAccountLogin(this, account);
-            final ProgressDialog dialog = ProgressDialog.show(this,
-                    getString(R.string.pref_autologin_title),
-                    getString(R.string.pref_autologin_progress, account),
-                    true /* indeterminate */,
-                    true /* cancelable */,
-                    login);
-            final Bundle b = icicle;
-            final Handler handler = new Handler();
-            final Runnable dismiss = new Runnable() {
-                @Override public void run() {
-                    dialog.dismiss();
-                }
-            };
-            final Runnable start = new Runnable() {
-                @Override public void run() {
-                    // Post a delayed dismiss message to avoid a flash of the
-                    // progress dialog.
-                    handler.postDelayed(dismiss, 1000);
-                    mController.start(b, getIntent());
-                }
-            };
-            login.startLogin(start);
-        } else {
-            mController.start(icicle, getIntent());
-        }
+        final Bundle b = icicle;
+        GoogleAccountLogin.startLoginIfNeeded(this, settings, new Runnable() {
+            @Override public void run() {
+                mController.start(b, getIntent());
+            }
+        });
     }
 
     @VisibleForTesting
diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java
index 472201b..a2ddc8c 100644
--- a/src/com/android/browser/Controller.java
+++ b/src/com/android/browser/Controller.java
@@ -2093,8 +2093,8 @@
     // This method does a ton of stuff. It will attempt to create a new tab
     // if we haven't reached MAX_TABS. Otherwise it uses the current tab. If
     // url isn't null, it will load the given url.
-    public Tab openTabAndShow(Tab parent, UrlData urlData, boolean closeOnExit,
-            String appId) {
+    public Tab openTabAndShow(Tab parent, final UrlData urlData,
+            boolean closeOnExit, String appId) {
         final Tab currentTab = mTabControl.getCurrentTab();
         if (mTabControl.canCreateNewTab()) {
             final Tab tab = mTabControl.createNewTab(closeOnExit, appId,
@@ -2105,9 +2105,17 @@
             // animation behavior.
             addTab(tab);
             setActiveTab(tab);
-            if (!urlData.isEmpty()) {
-                loadUrlDataIn(tab, urlData);
-            }
+
+            // Callback to load the url data.
+            final Runnable load = new Runnable() {
+                @Override public void run() {
+                    if (!urlData.isEmpty()) {
+                        loadUrlDataIn(tab, urlData);
+                    }
+                }
+            };
+
+            GoogleAccountLogin.startLoginIfNeeded(mActivity, mSettings, load);
             return tab;
         } else {
             // Get rid of the subwindow if it exists
diff --git a/src/com/android/browser/GoogleAccountLogin.java b/src/com/android/browser/GoogleAccountLogin.java
index 910c1bc..6bec8dc 100644
--- a/src/com/android/browser/GoogleAccountLogin.java
+++ b/src/com/android/browser/GoogleAccountLogin.java
@@ -29,12 +29,16 @@
 import android.accounts.AccountManagerCallback;
 import android.accounts.AccountManagerFuture;
 import android.app.Activity;
+import android.app.ProgressDialog;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnCancelListener;
+import android.content.SharedPreferences.Editor;
 import android.net.http.AndroidHttpClient;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Handler;
+import android.preference.PreferenceManager;
 import android.util.Log;
 import android.webkit.CookieManager;
 import android.webkit.WebView;
@@ -55,21 +59,32 @@
             "https://www.google.com/accounts/TokenAuth");
     // Google account type
     private static final String GOOGLE = "com.google";
+    // Last auto login time
+    private static final String PREF_AUTOLOGIN_TIME = "last_autologin_time";
+    // A week in milliseconds (7*24*60*60*1000)
+    private static final long WEEK_IN_MILLIS = 604800000L;
 
     private final Activity mActivity;
     private final Account mAccount;
     private final WebView mWebView;
+    // Does not matter if this is initialized in a non-ui thread.
+    // Dialog.dismiss() will post to the right handler.
+    private final Handler mHandler = new Handler();
     private Runnable mRunnable;
+    private ProgressDialog mProgressDialog;
 
     // SID and LSID retrieval process.
     private String mSid;
     private String mLsid;
     private int mState;  // {NONE(0), SID(1), LSID(2)}
 
-    GoogleAccountLogin(Activity activity, String name) {
+    private GoogleAccountLogin(Activity activity, String name,
+            Runnable runnable) {
         mActivity = activity;
         mAccount = new Account(name, GOOGLE);
         mWebView = new WebView(mActivity);
+        mRunnable = runnable;
+
         mWebView.setWebViewClient(new WebViewClient() {
             @Override
             public boolean shouldOverrideUrlLoading(WebView view, String url) {
@@ -77,11 +92,19 @@
             }
             @Override
             public void onPageFinished(WebView view, String url) {
+                saveLoginTime();
                 done();
             }
         });
     }
 
+    private void saveLoginTime() {
+        Editor ed = PreferenceManager.
+                getDefaultSharedPreferences(mActivity).edit();
+        ed.putLong(PREF_AUTOLOGIN_TIME, System.currentTimeMillis());
+        ed.apply();
+    }
+
     // Thread
     @Override
     public void run() {
@@ -178,8 +201,42 @@
         }
     }
 
-    public void startLogin(Runnable runnable) {
-        mRunnable = runnable;
+    // Start the login process if auto-login is enabled and the user is not
+    // already logged in.
+    public static void startLoginIfNeeded(Activity activity,
+            BrowserSettings settings, Runnable runnable) {
+        // Auto login not enabled?
+        if (!settings.isAutoLoginEnabled()) {
+            runnable.run();
+            return;
+        }
+
+        // No account found?
+        String account = settings.getAutoLoginAccount(activity);
+        if (account == null) {
+            runnable.run();
+            return;
+        }
+
+        // Already logged in?
+        if (isLoggedIn(activity)) {
+            runnable.run();
+            return;
+        }
+
+        GoogleAccountLogin login =
+                new GoogleAccountLogin(activity, account, runnable);
+        login.startLogin();
+    }
+
+    private void startLogin() {
+        mProgressDialog = ProgressDialog.show(mActivity,
+                mActivity.getString(R.string.pref_autologin_title),
+                mActivity.getString(R.string.pref_autologin_progress,
+                                    mAccount.name),
+                true /* indeterminate */,
+                true /* cancelable */,
+                this);
         mState = 1;  // SID
         AccountManager.get(mActivity).getAuthToken(
                 mAccount, "SID", null, mActivity, this, null);
@@ -209,7 +266,20 @@
     }
 
     // Checks for the presence of the SID cookie on google.com.
-    public static boolean isLoggedIn() {
+    public static boolean isLoggedIn(Context ctx) {
+        // See if we last logged in less than a week ago.
+        long lastLogin = PreferenceManager.
+                getDefaultSharedPreferences(ctx).
+                getLong(PREF_AUTOLOGIN_TIME, -1);
+        if (lastLogin == -1) {
+            return false;
+        }
+        long diff = System.currentTimeMillis() - lastLogin;
+        if (diff > WEEK_IN_MILLIS) {
+            Log.d(LOGTAG, "Forcing login after " + diff + "ms");
+            return false;
+        }
+
         String cookies = CookieManager.getInstance().getCookie(
                 "http://www.google.com");
         if (cookies != null) {
@@ -230,6 +300,15 @@
         if (mRunnable != null) {
             Log.d(LOGTAG, "Finished login attempt for " + mAccount.name);
             mActivity.runOnUiThread(mRunnable);
+
+            // Post a delayed message to dismiss the dialog in order to avoid a
+            // flash of the progress dialog.
+            mHandler.postDelayed(new Runnable() {
+                @Override public void run() {
+                    mProgressDialog.dismiss();
+                }
+            }, 1000);
+
             mRunnable = null;
             mWebView.destroy();
         }