merge in honeycomb-release history after reset to honeycomb
diff --git a/src/com/android/browser/BrowserActivity.java b/src/com/android/browser/BrowserActivity.java
index ec09673..899a7c2 100644
--- a/src/com/android/browser/BrowserActivity.java
+++ b/src/com/android/browser/BrowserActivity.java
@@ -111,12 +111,7 @@
             icicle = state;
         }
 
-        final Bundle b = icicle;
-        GoogleAccountLogin.startLoginIfNeeded(this, settings, new Runnable() {
-            @Override public void run() {
-                mController.start(b, getIntent());
-            }
-        });
+        mController.start(icicle, getIntent());
     }
 
     @VisibleForTesting
diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java
index 07e1ef9..74a66b1 100644
--- a/src/com/android/browser/Controller.java
+++ b/src/com/android/browser/Controller.java
@@ -251,7 +251,7 @@
         retainIconsOnStartup();
     }
 
-    void start(Bundle icicle, Intent intent) {
+    void start(final Bundle icicle, final Intent intent) {
         // Unless the last browser usage was within 24 hours, destroy any
         // remaining incognito tabs.
 
@@ -261,17 +261,32 @@
         Calendar yesterday = Calendar.getInstance();
         yesterday.add(Calendar.DATE, -1);
 
-        boolean restoreIncognitoTabs = !(lastActiveDate == null
+        final boolean restoreIncognitoTabs = !(lastActiveDate == null
             || lastActiveDate.before(yesterday)
             || lastActiveDate.after(today));
 
-        if (!mTabControl.restoreState(icicle, restoreIncognitoTabs,
-                mUi.needsRestoreAllTabs())) {
-            // there is no quit on Android. But if we can't restore the state,
-            // we can treat it as a new Browser, remove the old session cookies.
-            // This is done async in the CookieManager.
-            CookieManager.getInstance().removeSessionCookie();
+        // Find out if we will restore any state and remember the tab.
+        final int currentTab =
+                mTabControl.canRestoreState(icicle, restoreIncognitoTabs);
 
+        if (currentTab == -1) {
+            // Not able to restore so we go ahead and clear session cookies.  We
+            // must do this before trying to login the user as we don't want to
+            // clear any session cookies set during login.
+            CookieManager.getInstance().removeSessionCookie();
+        }
+
+        GoogleAccountLogin.startLoginIfNeeded(mActivity, mSettings,
+                new Runnable() {
+                    @Override public void run() {
+                        start(icicle, intent, currentTab, restoreIncognitoTabs);
+                    }
+                });
+    }
+
+    private void start(Bundle icicle, Intent intent, int currentTab,
+            boolean restoreIncognitoTabs) {
+        if (currentTab == -1) {
             final Bundle extra = intent.getExtras();
             // Create an initial tab.
             // If the intent is ACTION_VIEW and data is not null, the Browser is
@@ -303,6 +318,8 @@
                 loadUrlDataIn(t, urlData);
             }
         } else {
+            mTabControl.restoreState(icicle, currentTab, restoreIncognitoTabs,
+                    mUi.needsRestoreAllTabs());
             mUi.updateTabs(mTabControl.getTabs());
             // TabControl.restoreState() will create a new tab even if
             // restoring the state fails.
diff --git a/src/com/android/browser/GoogleAccountLogin.java b/src/com/android/browser/GoogleAccountLogin.java
index f019b52..eaf45ea 100644
--- a/src/com/android/browser/GoogleAccountLogin.java
+++ b/src/com/android/browser/GoogleAccountLogin.java
@@ -46,7 +46,7 @@
 
 import java.util.StringTokenizer;
 
-public class GoogleAccountLogin extends Thread implements
+public class GoogleAccountLogin implements Runnable,
         AccountManagerCallback<Bundle>, OnCancelListener {
 
     private static final String LOGTAG = "BrowserLogin";
@@ -77,6 +77,7 @@
     private String mSid;
     private String mLsid;
     private int mState;  // {NONE(0), SID(1), LSID(2)}
+    private boolean mTokensInvalidated;
 
     private GoogleAccountLogin(Activity activity, String name,
             Runnable runnable) {
@@ -105,7 +106,7 @@
         ed.apply();
     }
 
-    // Thread
+    // Runnable
     @Override
     public void run() {
         String url = ISSUE_AUTH_TOKEN_URL.buildUpon()
@@ -128,10 +129,22 @@
         String result = null;
         try {
             HttpResponse response = client.execute(request);
-            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
+            int status = response.getStatusLine().getStatusCode();
+            if (status != HttpStatus.SC_OK) {
                 Log.d(LOGTAG, "LOGIN_FAIL: Bad status from auth url "
-                      + response.getStatusLine().getStatusCode() + ": "
+                      + status + ": "
                       + response.getStatusLine().getReasonPhrase());
+                // Invalidate the tokens once just in case the 403 was for other
+                // reasons.
+                if (status == HttpStatus.SC_FORBIDDEN && !mTokensInvalidated) {
+                    Log.d(LOGTAG, "LOGIN_FAIL: Invalidating tokens...");
+                    // Need to regenerate the auth tokens and try again.
+                    invalidateTokens();
+                    // XXX: Do not touch any more member variables from this
+                    // thread as a second thread will handle the next login
+                    // attempt.
+                    return;
+                }
                 done();
                 return;
             }
@@ -171,6 +184,15 @@
         });
     }
 
+    private void invalidateTokens() {
+        AccountManager am = AccountManager.get(mActivity);
+        am.invalidateAuthToken(GOOGLE, mSid);
+        am.invalidateAuthToken(GOOGLE, mLsid);
+        mTokensInvalidated = true;
+        mState = 1;  // SID
+        am.getAuthToken(mAccount, "SID", null, mActivity, this, null);
+    }
+
     // AccountManager callbacks.
     @Override
     public void run(AccountManagerFuture<Bundle> value) {
@@ -190,7 +212,7 @@
                     break;
                 case 2:
                     mLsid = id;
-                    this.start();
+                    new Thread(this).start();
                     break;
             }
         } catch (Exception e) {
@@ -280,6 +302,11 @@
             return false;
         }
 
+        // This will potentially block the UI thread but we have to have the
+        // most updated cookies.
+        // FIXME: Figure out how to avoid waiting to clear session cookies.
+        CookieManager.getInstance().waitForCookieOperationsToComplete();
+
         // Use /a/ to grab hosted cookies as well as the base set of google.com
         // cookies.
         String cookies = CookieManager.getInstance().getCookie(
diff --git a/src/com/android/browser/TabControl.java b/src/com/android/browser/TabControl.java
index 050ad94..af9928a 100644
--- a/src/com/android/browser/TabControl.java
+++ b/src/com/android/browser/TabControl.java
@@ -287,7 +287,42 @@
     }
 
     /**
+     * Check if the state can be restored.  If the state can be restored, the
+     * current tab index is returned.  This can be passed to restoreState below
+     * in order to restore the correct tab.  Otherwise, -1 is returned and the
+     * state cannot be restored.
+     */
+    int canRestoreState(Bundle inState, boolean restoreIncognitoTabs) {
+        final int numTabs = (inState == null)
+                ? - 1 : inState.getInt(Tab.NUMTABS, -1);
+        if (numTabs == -1) {
+            return -1;
+        }
+        final int oldCurrentTab = inState.getInt(Tab.CURRTAB, -1);
+
+        // Determine whether the saved current tab can be restored, and if not,
+        // which tab will take its place.
+        int currentTab = -1;
+        if (restoreIncognitoTabs ||
+                !inState.getBundle(Tab.WEBVIEW + oldCurrentTab)
+                .getBoolean(Tab.INCOGNITO)) {
+            currentTab = oldCurrentTab;
+        } else {
+            for (int i = 0; i < numTabs; i++) {
+                if (!inState.getBundle(Tab.WEBVIEW + i)
+                        .getBoolean(Tab.INCOGNITO)) {
+                    currentTab = i;
+                    break;
+                }
+            }
+        }
+
+        return currentTab;
+    }
+
+    /**
      * Restore the state of all the tabs.
+     * @param currentTab The tab index to restore.
      * @param inState The saved state of all the tabs.
      * @param restoreIncognitoTabs Restoring private browsing tabs
      * @param restoreAll All webviews get restored, not just the current tab
@@ -295,89 +330,69 @@
      * @return True if there were previous tabs that were restored. False if
      *         there was no saved state or restoring the state failed.
      */
-    boolean restoreState(Bundle inState, boolean restoreIncognitoTabs,
-            boolean restoreAll) {
-        final int numTabs = (inState == null)
-                ? -1 : inState.getInt(Tab.NUMTABS, -1);
-        if (numTabs == -1) {
-            return false;
-        } else {
-            final int oldCurrentTab = inState.getInt(Tab.CURRTAB, -1);
+    void restoreState(Bundle inState, int currentTab,
+            boolean restoreIncognitoTabs, boolean restoreAll) {
+        if (currentTab == -1) {
+            return;
+        }
 
-            // Determine whether the saved current tab can be restored, and
-            // if not, which tab will take its place.
-            int currentTab = -1;
-            if (restoreIncognitoTabs
-                    || !inState.getBundle(Tab.WEBVIEW + oldCurrentTab).getBoolean(Tab.INCOGNITO)) {
-                currentTab = oldCurrentTab;
+        // If currentTab is valid, numTabs must be present.
+        final int numTabs = inState.getInt(Tab.NUMTABS, -1);
+
+        // Map saved tab indices to new indices, in case any incognito tabs
+        // need to not be restored.
+        HashMap<Integer, Integer> originalTabIndices = new HashMap<Integer, Integer>();
+        originalTabIndices.put(-1, -1);
+        for (int i = 0; i < numTabs; i++) {
+            Bundle state = inState.getBundle(Tab.WEBVIEW + i);
+
+            if (!restoreIncognitoTabs && state != null && state.getBoolean(Tab.INCOGNITO)) {
+                originalTabIndices.put(i, -1);
+            } else if (i == currentTab || restoreAll) {
+                Tab t = createNewTab();
+                // Me must set the current tab before restoring the state
+                // so that all the client classes are set.
+                if (i == currentTab) {
+                    setCurrentTab(t);
+                }
+                if (!t.restoreState(state)) {
+                    Log.w(LOGTAG, "Fail in restoreState, load home page.");
+                    t.getWebView().loadUrl(BrowserSettings.getInstance()
+                            .getHomePage());
+                }
+                originalTabIndices.put(i, getTabCount() - 1);
             } else {
-                for (int i = 0; i < numTabs; i++) {
-                    if (!inState.getBundle(Tab.WEBVIEW + i).getBoolean(Tab.INCOGNITO)) {
-                        currentTab = i;
-                        break;
-                    }
+                // Create a new tab and don't restore the state yet, add it
+                // to the tab list
+                Tab t = new Tab(mController, null, false, null, null);
+                if (state != null) {
+                    t.setSavedState(state);
+                    // Need to maintain the app id and original url so we
+                    // can possibly reuse this tab.
+                    t.setAppId(state.getString(Tab.APPID));
                 }
+                mTabs.add(t);
+                // added the tab to the front as they are not current
+                mTabQueue.add(0, t);
+                originalTabIndices.put(i, getTabCount() - 1);
             }
-            if (currentTab < 0) {
-                return false;
-            }
+        }
 
-            // Map saved tab indices to new indices, in case any incognito tabs
-            // need to not be restored.
-            HashMap<Integer, Integer> originalTabIndices = new HashMap<Integer, Integer>();
-            originalTabIndices.put(-1, -1);
-            for (int i = 0; i < numTabs; i++) {
-                Bundle state = inState.getBundle(Tab.WEBVIEW + i);
-
-                if (!restoreIncognitoTabs && state != null && state.getBoolean(Tab.INCOGNITO)) {
-                    originalTabIndices.put(i, -1);
-                } else if (i == currentTab || restoreAll) {
-                    Tab t = createNewTab();
-                    // Me must set the current tab before restoring the state
-                    // so that all the client classes are set.
-                    if (i == currentTab) {
-                        setCurrentTab(t);
-                    }
-                    if (!t.restoreState(state)) {
-                        Log.w(LOGTAG, "Fail in restoreState, load home page.");
-                        t.getWebView().loadUrl(BrowserSettings.getInstance()
-                                .getHomePage());
-                    }
-                    originalTabIndices.put(i, getTabCount() - 1);
-                } else {
-                    // Create a new tab and don't restore the state yet, add it
-                    // to the tab list
-                    Tab t = new Tab(mController, null, false, null, null);
-                    if (state != null) {
-                        t.setSavedState(state);
-                        // Need to maintain the app id and original url so we
-                        // can possibly reuse this tab.
-                        t.setAppId(state.getString(Tab.APPID));
-                    }
-                    mTabs.add(t);
-                    // added the tab to the front as they are not current
-                    mTabQueue.add(0, t);
-                    originalTabIndices.put(i, getTabCount() - 1);
-                }
-            }
-
-            // Rebuild the tree of tabs. Do this after all tabs have been
-            // created/restored so that the parent tab exists.
-            for (int i = 0; i < numTabs; i++) {
-                final Bundle b = inState.getBundle(Tab.WEBVIEW + i);
-                final Tab t = getTab(i);
-                if (b != null && t != null) {
-                    final Integer parentIndex = originalTabIndices.get(b.getInt(Tab.PARENTTAB, -1));
-                    if (parentIndex != -1) {
-                        final Tab parent = getTab(parentIndex);
-                        if (parent != null) {
-                            parent.addChildTab(t);
-                        }
+        // Rebuild the tree of tabs. Do this after all tabs have been
+        // created/restored so that the parent tab exists.
+        for (int i = 0; i < numTabs; i++) {
+            final Bundle b = inState.getBundle(Tab.WEBVIEW + i);
+            final Tab t = getTab(i);
+            if (b != null && t != null) {
+                final Integer parentIndex = originalTabIndices.get(b.getInt(Tab.PARENTTAB, -1));
+                if (parentIndex != -1) {
+                    final Tab parent = getTab(parentIndex);
+                    if (parent != null) {
+                        parent.addChildTab(t);
                     }
                 }
             }
         }
-        return true;
     }
 
     /**