Overhaul handling tab data updates

 Bug: 2127502, 3191165
 Pushed some state tracking to the tab for URL, title, favicon,
 and lock status. This allowed me to remove many duplicate methods
 of updating that data, preventing the UI from getting out of sync
 with the web view.

Change-Id: I995caa98068ad03ca37710207b5ab57bb9d801ab
diff --git a/src/com/android/browser/ActiveTabsPage.java b/src/com/android/browser/ActiveTabsPage.java
index fb5ed3b..664fd68 100644
--- a/src/com/android/browser/ActiveTabsPage.java
+++ b/src/com/android/browser/ActiveTabsPage.java
@@ -170,7 +170,6 @@
                             + (tab.getSavedState() == null ? "null" : "non-null")
                             + " saved state ");
                 }
-                tab.populatePickerData();
                 if (tab.getTitle() == null || tab.getTitle().length() == 0) {
                     Log.w(LOGTAG, "Tab " + position + " has no title. "
                             + "Check above in the Logs to see whether it has a "
diff --git a/src/com/android/browser/BaseUi.java b/src/com/android/browser/BaseUi.java
index 1e9038d..7e0c5da 100644
--- a/src/com/android/browser/BaseUi.java
+++ b/src/com/android/browser/BaseUi.java
@@ -16,6 +16,8 @@
 
 package com.android.browser;
 
+import com.android.browser.Tab.LockIcon;
+
 import android.app.Activity;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -178,15 +180,12 @@
         return false;
     }
 
-    // WebView callbacks
-
+    // Tab callbacks
     @Override
-    public void onPageStarted(Tab tab, String url, Bitmap favicon) {
-        if (tab.inForeground()) {
-            resetLockIcon(tab, url);
-            setUrlTitle(tab, url, null);
-            setFavicon(tab, favicon);
-        }
+    public void onTabDataChanged(Tab tab) {
+        setUrlTitle(tab);
+        setFavicon(tab);
+        updateLockIconToLatest(tab);
     }
 
     @Override
@@ -195,16 +194,6 @@
     }
 
     @Override
-    public void onPageFinished(Tab tab, String url) {
-        if (tab.inForeground()) {
-            // Reset the title and icon in case we stopped a provisional load.
-            resetTitleAndIcon(tab);
-            // Update the lock icon image only once we are done loading
-            updateLockIconToLatest(tab);
-        }
-    }
-
-    @Override
     public void onPageStopped(Tab tab) {
         cancelStopToast();
         if (tab.inForeground()) {
@@ -231,6 +220,8 @@
         mActiveTab = tab;
         attachTabToContentView(tab);
         setShouldShowErrorConsole(tab, mUiController.shouldShowErrorConsole());
+        onTabDataChanged(tab);
+        onProgressChanged(tab);
     }
 
     Tab getActiveTab() {
@@ -424,7 +415,7 @@
     @Override
     public void revertVoiceTitleBar(Tab tab) {
         getEmbeddedTitleBar().setInVoiceMode(false);
-        String url = tab.getCurrentUrl();
+        String url = tab.getUrl();
         getEmbeddedTitleBar().setDisplayTitle(url);
         getFakeTitleBar().setInVoiceMode(false);
         getFakeTitleBar().setDisplayTitle(url);
@@ -524,81 +515,32 @@
 
     // -------------------------------------------------------------------------
 
-    @Override
-    public void resetTitleAndRevertLockIcon(Tab tab) {
-        tab.revertLockIcon();
-        updateLockIconToLatest(tab);
-        resetTitleIconAndProgress(tab);
-    }
-
-    /**
-     * Resets the lock icon. This method is called when we start a new load and
-     * know the url to be loaded.
-     */
-    private void resetLockIcon(Tab tab, String url) {
-        // Save the lock-icon state (we revert to it if the load gets cancelled)
-        tab.resetLockIcon(url);
-        updateLockIconImage(Tab.LOCK_ICON_UNSECURE);
-    }
-
     /**
      * Update the lock icon to correspond to our latest state.
      */
     protected void updateLockIconToLatest(Tab t) {
-        if (t != null) {
+        if (t != null && t.inForeground()) {
             updateLockIconImage(t.getLockIconType());
         }
     }
 
     /**
-     * Reset the title, favicon, and progress.
-     */
-    protected void resetTitleIconAndProgress(Tab tab) {
-        WebView current = tab.getWebView();
-        if (current == null) {
-            return;
-        }
-        resetTitleAndIcon(tab, current);
-        int progress = current.getProgress();
-        current.getWebChromeClient().onProgressChanged(current, progress);
-    }
-
-    @Override
-    public void resetTitleAndIcon(Tab tab) {
-        WebView current = tab.getWebView();
-        if (current != null) {
-            resetTitleAndIcon(tab, current);
-        }
-    }
-
-    // Reset the title and the icon based on the given item.
-    private void resetTitleAndIcon(Tab tab, WebView view) {
-        WebHistoryItem item = view.copyBackForwardList().getCurrentItem();
-        if (item != null) {
-            setUrlTitle(tab, item.getUrl(), item.getTitle());
-            setFavicon(tab, item.getFavicon());
-        } else {
-            setUrlTitle(tab, null, mActivity.getString(R.string.new_tab));
-            setFavicon(tab, null);
-        }
-    }
-
-    /**
      * Updates the lock-icon image in the title-bar.
      */
-    private void updateLockIconImage(int lockIconType) {
+    private void updateLockIconImage(LockIcon lockIconType) {
         Drawable d = null;
-        if (lockIconType == Tab.LOCK_ICON_SECURE) {
+        if (lockIconType == LockIcon.LOCK_ICON_SECURE) {
             d = mSecLockIcon;
-        } else if (lockIconType == Tab.LOCK_ICON_MIXED) {
+        } else if (lockIconType == LockIcon.LOCK_ICON_MIXED) {
             d = mMixLockIcon;
         }
         getEmbeddedTitleBar().setLock(d);
         getFakeTitleBar().setLock(d);
     }
 
-    @Override
-    public void setUrlTitle(Tab tab, String url, String title) {
+    protected void setUrlTitle(Tab tab) {
+        String url = tab.getUrl();
+        String title = tab.getTitle();
         if (TextUtils.isEmpty(title)) {
             title = url;
         }
@@ -610,10 +552,12 @@
     }
 
     // Set the favicon in the title bar.
-    @Override
-    public void setFavicon(Tab tab, Bitmap icon) {
-        getEmbeddedTitleBar().setFavicon(icon);
-        getFakeTitleBar().setFavicon(icon);
+    protected void setFavicon(Tab tab) {
+        if (tab.inForeground()) {
+            Bitmap icon = tab.getFavicon();
+            getEmbeddedTitleBar().setFavicon(icon);
+            getFakeTitleBar().setFavicon(icon);
+        }
     }
 
     @Override
diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java
index 487c69c..ab6578a 100644
--- a/src/com/android/browser/Controller.java
+++ b/src/com/android/browser/Controller.java
@@ -522,7 +522,6 @@
 
     private void shareCurrentPage(Tab tab) {
         if (tab != null) {
-            tab.populatePickerData();
             sharePage(mActivity, tab.getTitle(),
                     tab.getUrl(), tab.getFavicon(),
                     createScreenshot(tab.getWebView(),
@@ -722,15 +721,8 @@
     public void stopLoading() {
         mLoadStopped = true;
         Tab tab = mTabControl.getCurrentTab();
-        resetTitleAndRevertLockIcon(tab);
         WebView w = getCurrentTopWebView();
         w.stopLoading();
-        // FIXME: before refactor, it is using mWebViewClient. So I keep the
-        // same logic here. But for subwindow case, should we call into the main
-        // WebView's onPageFinished as we never call its onPageStarted and if
-        // the page finishes itself, we don't call onPageFinished.
-        mTabControl.getCurrentWebView().getWebViewClient().onPageFinished(w,
-                w.getUrl());
         mUi.onPageStopped(tab);
     }
 
@@ -770,7 +762,7 @@
         }
         endActionMode();
 
-        mUi.onPageStarted(tab, url, favicon);
+        mUi.onTabDataChanged(tab);
 
         // update the bookmark database for favicon
         maybeUpdateFavicon(tab, null, url, favicon);
@@ -786,7 +778,7 @@
 
     @Override
     public void onPageFinished(Tab tab, String url) {
-        mUi.onPageFinished(tab, url);
+        mUi.onTabDataChanged(tab);
         if (!tab.isPrivateBrowsingEnabled()) {
             if (tab.inForeground() && !didUserStopLoading()
                     || !tab.inForeground()) {
@@ -814,7 +806,8 @@
     }
 
     @Override
-    public void onProgressChanged(Tab tab, int newProgress) {
+    public void onProgressChanged(Tab tab) {
+        int newProgress = tab.getLoadProgress();
 
         if (newProgress == 100) {
             CookieSyncManager.getInstance().sync();
@@ -838,13 +831,18 @@
                 updateInLoadMenuItems(mCachedMenu);
             }
         }
-        mUi.onProgressChanged(tab, newProgress);
+        mUi.onProgressChanged(tab);
+    }
+
+    @Override
+    public void onUpdatedLockIcon(Tab tab) {
+        mUi.onTabDataChanged(tab);
     }
 
     @Override
     public void onReceivedTitle(Tab tab, final String title) {
-        final String pageUrl = tab.getWebView().getUrl();
-        setUrlTitle(tab, pageUrl, title);
+        mUi.onTabDataChanged(tab);
+        final String pageUrl = tab.getUrl();
         if (pageUrl == null || pageUrl.length()
                 >= SQLiteDatabase.SQLITE_MAX_LIKE_PATTERN_LENGTH) {
             return;
@@ -857,7 +855,7 @@
 
     @Override
     public void onFavicon(Tab tab, WebView view, Bitmap icon) {
-        mUi.setFavicon(tab, icon);
+        mUi.onTabDataChanged(tab);
         maybeUpdateFavicon(tab, view.getOriginalUrl(), view.getUrl(), icon);
     }
 
@@ -2016,24 +2014,17 @@
         // content view first.
         mUi.detachTab(appTab);
         // Recreate the main WebView after destroying the old one.
-        // If the WebView has the same original url and is on that
-        // page, it can be reused.
-        boolean needsLoad =
-                mTabControl.recreateWebView(appTab, urlData);
+        mTabControl.recreateWebView(appTab);
         // TODO: analyze why the remove and add are necessary
         mUi.attachTab(appTab);
         if (mTabControl.getCurrentTab() != appTab) {
             switchToTab(mTabControl.getTabIndex(appTab));
-            if (needsLoad) {
-                loadUrlDataIn(appTab, urlData);
-            }
+            loadUrlDataIn(appTab, urlData);
         } else {
             // If the tab was the current tab, we have to attach
             // it to the view system again.
             setActiveTab(appTab);
-            if (needsLoad) {
-                loadUrlDataIn(appTab, urlData);
-            }
+            loadUrlDataIn(appTab, urlData);
         }
     }
 
@@ -2233,33 +2224,15 @@
         data.loadIn(t);
     }
 
-    /**
-     * Resets the browser title-view to whatever it must be
-     * (for example, if we had a loading error)
-     * When we have a new page, we call resetTitle, when we
-     * have to reset the titlebar to whatever it used to be
-     * (for example, if the user chose to stop loading), we
-     * call resetTitleAndRevertLockIcon.
-     */
-    public void resetTitleAndRevertLockIcon(Tab tab) {
-        mUi.resetTitleAndRevertLockIcon(tab);
-    }
-
-    void resetTitleAndIcon(Tab tab) {
-        mUi.resetTitleAndIcon(tab);
-    }
-
-    /**
-     * Sets a title composed of the URL and the title string.
-     * @param url The URL of the site being loaded.
-     * @param title The title of the site being loaded.
-     */
-    void setUrlTitle(Tab tab, String url, String title) {
-        tab.setCurrentUrl(url);
-        tab.setCurrentTitle(title);
-        // If we are in voice search mode, the title has already been set.
-        if (tab.isInVoiceSearchMode()) return;
-        mUi.setUrlTitle(tab, url, title);
+    @Override
+    public void onUserCanceledSsl(Tab tab) {
+        WebView web = tab.getWebView();
+        // TODO: Figure out the "right" behavior
+        if (web.canGoBack()) {
+            web.goBack();
+        } else {
+            web.loadUrl(mSettings.getHomePage());
+        }
     }
 
     void goBackOnePageOrQuit() {
diff --git a/src/com/android/browser/IntentHandler.java b/src/com/android/browser/IntentHandler.java
index bd5595f..e5abb11 100644
--- a/src/com/android/browser/IntentHandler.java
+++ b/src/com/android/browser/IntentHandler.java
@@ -75,7 +75,6 @@
                 return;
             }
             mController.setActiveTab(current);
-            mController.resetTitleAndIcon(current);
         }
         final String action = intent.getAction();
         final int flags = intent.getFlags();
diff --git a/src/com/android/browser/PageDialogsHandler.java b/src/com/android/browser/PageDialogsHandler.java
index 6843a10..2dbddf3 100644
--- a/src/com/android/browser/PageDialogsHandler.java
+++ b/src/com/android/browser/PageDialogsHandler.java
@@ -97,7 +97,7 @@
         mHttpAuthenticationDialog.setCancelListener(new HttpAuthenticationDialog.CancelListener() {
             public void onCancel() {
                 handler.cancel();
-                mController.resetTitleAndRevertLockIcon(tab);
+                mController.onUpdatedLockIcon(tab);
                 mHttpAuthenticationDialog = null;
             }
         });
@@ -138,20 +138,8 @@
 
         final WebView view = tab.getWebView();
 
-        String url = null;
-        String title = null;
-
-        if (view == null) {
-            url = tab.getUrl();
-            title = tab.getTitle();
-        } else if (view == mController.getCurrentWebView()) {
-             // Use the cached title and url if this is the current WebView
-            url = tab.getCurrentUrl();
-            title = tab.getCurrentTitle();
-        } else {
-            url = view.getUrl();
-            title = view.getTitle();
-        }
+        String url = tab.getUrl();
+        String title = tab.getTitle();
 
         if (url == null) {
             url = "";
diff --git a/src/com/android/browser/PhoneUi.java b/src/com/android/browser/PhoneUi.java
index e35e624..99fc4a0 100644
--- a/src/com/android/browser/PhoneUi.java
+++ b/src/com/android/browser/PhoneUi.java
@@ -103,8 +103,9 @@
     }
 
     @Override
-    public void onProgressChanged(Tab tab, int progress) {
+    public void onProgressChanged(Tab tab) {
         if (tab.inForeground()) {
+            int progress = tab.getLoadProgress();
             mFakeTitleBar.setProgress(progress);
             if (progress == 100) {
                 if (!mOptionsMenuOpen || !mExtendedMenuOpen) {
@@ -134,8 +135,6 @@
         } else {
             revertVoiceTitleBar(tab);
         }
-        resetTitleIconAndProgress(tab);
-        updateLockIconToLatest(tab);
         tab.getTopWindow().requestFocus();
     }
 
diff --git a/src/com/android/browser/Tab.java b/src/com/android/browser/Tab.java
index 0ba59f4..491c260 100644
--- a/src/com/android/browser/Tab.java
+++ b/src/com/android/browser/Tab.java
@@ -22,12 +22,14 @@
 import android.app.AlertDialog;
 import android.app.SearchManager;
 import android.content.ContentResolver;
+import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnCancelListener;
 import android.content.Intent;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteException;
 import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.net.Uri;
 import android.net.http.SslError;
 import android.os.AsyncTask;
@@ -55,7 +57,6 @@
 import android.webkit.WebStorage;
 import android.webkit.WebView;
 import android.webkit.WebViewClient;
-import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 import android.widget.Toast;
@@ -79,9 +80,11 @@
     // of the browser.
     private static final String CONSOLE_LOGTAG = "browser";
 
-    final static int LOCK_ICON_UNSECURE = 0;
-    final static int LOCK_ICON_SECURE   = 1;
-    final static int LOCK_ICON_MIXED    = 2;
+    public enum LockIcon {
+        LOCK_ICON_UNSECURE,
+        LOCK_ICON_SECURE,
+        LOCK_ICON_MIXED,
+    }
 
     Activity mActivity;
     private WebViewController mWebViewController;
@@ -100,8 +103,6 @@
     // information needed to restore the WebView if the user goes back to the
     // tab.
     private Bundle mSavedState;
-    // Data used when displaying the tab in the picker.
-    private PickerData mPickerData;
     // Parent Tab. This is the Tab that created this Tab, or null if the Tab was
     // created by the UI
     private Tab mParentTab;
@@ -115,6 +116,8 @@
     // If true, the tab is in page loading state (after onPageStarted,
     // before onPageFinsihed)
     private boolean mInPageLoad;
+    // The last reported progress of the current page
+    private int mPageLoadProgress;
     // The time the load started, used to find load page time
     private long mLoadStartTime;
     // Application identifier used to find tabs that another application wants
@@ -122,16 +125,8 @@
     private String mAppId;
     // Keep the original url around to avoid killing the old WebView if the url
     // has not changed.
-    private String mOriginalUrl;
-    // Hold on to the currently loaded url
-    private String mCurrentUrl;
-    //The currently loaded title
-    private String mCurrentTitle;
     // Error console for the tab
     private ErrorConsoleView mErrorConsole;
-    // the lock icon type and previous lock icon type for the tab
-    private int mLockIconType;
-    private int mPrevLockIconType;
     // The listener that gets invoked when a download is started from the
     // mMainView
     private final DownloadListener mDownloadListener;
@@ -141,13 +136,53 @@
     // AsyncTask for downloading touch icons
     DownloadTouchIcon mTouchIconLoader;
 
-    // Extra saved information for displaying the tab in the picker.
-    private static class PickerData {
-        String  mUrl;
-        String  mTitle;
-        Bitmap  mFavicon;
+    // All the state needed for a page
+    private static class PageState {
+        String mUrl;
+        String mTitle;
+        LockIcon mLockIcon;
+        Bitmap mFavicon;
+
+        PageState(Context c, boolean incognito) {
+            if (incognito) {
+                mUrl = "browser:incognito";
+                mTitle = c.getString(R.string.new_incognito_tab);
+                mFavicon = BitmapFactory.decodeResource(
+                        c.getResources(), R.drawable.fav_incognito);
+            } else {
+                mUrl = "";
+                mTitle = c.getString(R.string.new_tab);
+                mFavicon = BitmapFactory.decodeResource(
+                        c.getResources(), R.drawable.app_web_browser_sm);
+            }
+            mLockIcon = LockIcon.LOCK_ICON_UNSECURE;
+        }
+
+        PageState(Context c, boolean incognito, String url, Bitmap favicon) {
+            mUrl = url;
+            mTitle = null;
+            if (URLUtil.isHttpsUrl(url)) {
+                mLockIcon = LockIcon.LOCK_ICON_SECURE;
+            } else {
+                mLockIcon = LockIcon.LOCK_ICON_UNSECURE;
+            }
+            if (favicon != null) {
+                mFavicon = favicon;
+            } else {
+                if (incognito) {
+                    mFavicon = BitmapFactory.decodeResource(
+                            c.getResources(), R.drawable.fav_incognito);
+                } else {
+                    mFavicon = BitmapFactory.decodeResource(
+                            c.getResources(), R.drawable.app_web_browser_sm);
+                }
+            }
+        }
     }
 
+    // The current/loading page's state
+    private PageState mCurrentState;
+
     // Whether or not the currently shown page is a bookmarked site.  Will be
     // out of date when loading a new page until the mBookmarkAsyncTask returns.
     private boolean mIsBookmarkedSite;
@@ -157,6 +192,9 @@
     public boolean isBookmarkedSite() { return mIsBookmarkedSite; }
 
     // Used for saving and restoring each Tab
+    // TODO: Figure out who uses what and where
+    //       Some of these aren't use in this class, and some are only used in
+    //       restoring state but not saving it - FIX THIS
     static final String WEBVIEW = "webview";
     static final String NUMTABS = "numTabs";
     static final String CURRTAB = "currentTab";
@@ -472,6 +510,9 @@
         @Override
         public void onPageStarted(WebView view, String url, Bitmap favicon) {
             mInPageLoad = true;
+            mPageLoadProgress = 0;
+            mCurrentState = new PageState(mActivity,
+                    view.isPrivateBrowsingEnabled(), url, favicon);
             mLoadStartTime = SystemClock.uptimeMillis();
             if (mVoiceSearchData != null
                     && !url.equals(mVoiceSearchData.mLastVoiceSearchUrl)) {
@@ -513,7 +554,15 @@
                         url, SystemClock.uptimeMillis() - mLoadStartTime);
             }
             mInPageLoad = false;
-
+            // Sync state (in case of stop/timeout)
+            mCurrentState.mUrl = view.getUrl();
+            mCurrentState.mTitle = view.getTitle();
+            mCurrentState.mFavicon = view.getFavicon();
+            if (!URLUtil.isHttpsUrl(mCurrentState.mUrl)) {
+                // In case we stop when loading an HTTPS page from an HTTP page
+                // but before a provisional load occurred
+                mCurrentState.mLockIcon = LockIcon.LOCK_ICON_UNSECURE;
+            }
             mWebViewController.onPageFinished(Tab.this, url);
         }
 
@@ -551,11 +600,11 @@
             if (url != null && url.length() > 0) {
                 // It is only if the page claims to be secure that we may have
                 // to update the lock:
-                if (mLockIconType == LOCK_ICON_SECURE) {
+                if (mCurrentState.mLockIcon == LockIcon.LOCK_ICON_SECURE) {
                     // If NOT a 'safe' url, change the lock to mixed content!
                     if (!(URLUtil.isHttpsUrl(url) || URLUtil.isDataUrl(url)
                             || URLUtil.isAboutUrl(url))) {
-                        mLockIconType = LOCK_ICON_MIXED;
+                        mCurrentState.mLockIcon = LockIcon.LOCK_ICON_MIXED;
                     }
                 }
             }
@@ -581,11 +630,6 @@
                 Log.e(LOGTAG, "onReceivedError " + errorCode + " " + failingUrl
                         + " " + description);
             }
-
-            // We need to reset the title after an error if it is in foreground.
-            if (mInForeground) {
-                mWebViewController.resetTitleAndRevertLockIcon(Tab.this);
-            }
         }
 
         /**
@@ -661,6 +705,7 @@
                 final SslErrorHandler handler, final SslError error) {
             if (!mInForeground) {
                 handler.cancel();
+                setLockIconType(LockIcon.LOCK_ICON_UNSECURE);
                 return;
             }
             if (BrowserSettings.getInstance().showSecurityWarnings()) {
@@ -723,14 +768,14 @@
                         new DialogInterface.OnClickListener() {
                             public void onClick(DialogInterface dialog,
                                     int whichButton) {
-                                handler.cancel();
-                                mWebViewController.resetTitleAndRevertLockIcon(Tab.this);
+                                dialog.cancel();
                             }
                         }).setOnCancelListener(
                         new DialogInterface.OnCancelListener() {
                             public void onCancel(DialogInterface dialog) {
                                 handler.cancel();
-                                mWebViewController.resetTitleAndRevertLockIcon(Tab.this);
+                                setLockIconType(LockIcon.LOCK_ICON_UNSECURE);
+                                mWebViewController.onUserCanceledSsl(Tab.this);
                             }
                         }).show();
             } else {
@@ -881,16 +926,19 @@
 
         @Override
         public void onProgressChanged(WebView view, int newProgress) {
-            mWebViewController.onProgressChanged(Tab.this, newProgress);
+            mPageLoadProgress = newProgress;
+            mWebViewController.onProgressChanged(Tab.this);
         }
 
         @Override
         public void onReceivedTitle(WebView view, final String title) {
+            mCurrentState.mTitle = title;
             mWebViewController.onReceivedTitle(Tab.this, title);
         }
 
         @Override
         public void onReceivedIcon(WebView view, Bitmap icon) {
+            mCurrentState.mFavicon = icon;
             mWebViewController.onFavicon(Tab.this, view, icon);
         }
 
@@ -1212,9 +1260,7 @@
         mActivity = mWebViewController.getActivity();
         mCloseOnExit = closeOnExit;
         mAppId = appId;
-        mOriginalUrl = url;
-        mLockIconType = LOCK_ICON_UNSECURE;
-        mPrevLockIconType = LOCK_ICON_UNSECURE;
+        mCurrentState = new PageState(mActivity, w.isPrivateBrowsingEnabled());
         mInPageLoad = false;
         mInForeground = false;
 
@@ -1528,77 +1574,25 @@
         mAppId = id;
     }
 
-    /**
-     * @return The original url associated with this Tab
-     */
-    String getOriginalUrl() {
-        return mOriginalUrl;
-    }
-
-    /**
-     * Set the original url associated with this tab
-     */
-    void setOriginalUrl(String url) {
-        mOriginalUrl = url;
-    }
-
-    /**
-     * set the title for the tab
-     */
-    void setCurrentTitle(String title) {
-        mCurrentTitle = title;
-    }
-
-    /**
-     * set url for this tab
-     * @param url
-     */
-    void setCurrentUrl(String url) {
-        mCurrentUrl = url;
-    }
-
-    String getCurrentTitle() {
-        return mCurrentTitle;
-    }
-
-    String getCurrentUrl() {
-        return mCurrentUrl;
-    }
-    /**
-     * Get the url of this tab. Valid after calling populatePickerData, but
-     * before calling wipePickerData, or if the webview has been destroyed.
-     * @return The WebView's url or null.
-     */
     String getUrl() {
-        if (mPickerData != null) {
-            return mPickerData.mUrl;
-        }
-        return null;
+        return mCurrentState.mUrl;
     }
 
     /**
-     * Get the title of this tab. Valid after calling populatePickerData, but
-     * before calling wipePickerData, or if the webview has been destroyed. If
-     * the url has no title, use the url instead.
-     * @return The WebView's title (or url) or null.
+     * Get the title of this tab.
      */
     String getTitle() {
-        if (mPickerData != null) {
-            return mPickerData.mTitle;
+        if (mCurrentState.mTitle == null && mInPageLoad) {
+            return mActivity.getString(R.string.title_bar_loading);
         }
-        return null;
+        return mCurrentState.mTitle;
     }
 
     /**
-     * Get the favicon of this tab. Valid after calling populatePickerData, but
-     * before calling wipePickerData, or if the webview has been destroyed.
-     * @return The WebView's favicon or null.
+     * Get the favicon of this tab.
      */
     Bitmap getFavicon() {
-        if (mPickerData != null) {
-            return mPickerData.mFavicon;
-        }
-        return null;
+        return mCurrentState.mFavicon;
     }
 
 
@@ -1636,31 +1630,23 @@
         return mCloseOnExit;
     }
 
-    /**
-     * Saves the current lock-icon state before resetting the lock icon. If we
-     * have an error, we may need to roll back to the previous state.
-     */
-    void resetLockIcon(String url) {
-        mPrevLockIconType = mLockIconType;
-        mLockIconType = LOCK_ICON_UNSECURE;
-        if (URLUtil.isHttpsUrl(url)) {
-            mLockIconType = LOCK_ICON_SECURE;
-        }
-    }
-
-    /**
-     * Reverts the lock-icon state to the last saved state, for example, if we
-     * had an error, and need to cancel the load.
-     */
-    void revertLockIcon() {
-        mLockIconType = mPrevLockIconType;
+    private void setLockIconType(LockIcon icon) {
+        mCurrentState.mLockIcon = icon;
+        mWebViewController.onUpdatedLockIcon(this);
     }
 
     /**
      * @return The tab's lock icon type.
      */
-    int getLockIconType() {
-        return mLockIconType;
+    LockIcon getLockIconType() {
+        return mCurrentState.mLockIcon;
+    }
+
+    int getLoadProgress() {
+        if (mInPageLoad) {
+            return mPageLoadProgress;
+        }
+        return 100;
     }
 
     /**
@@ -1677,55 +1663,9 @@
         mInPageLoad = false;
     }
 
-    void populatePickerData() {
-        if (mMainView == null) {
-            populatePickerDataFromSavedState();
-            return;
-        }
-
-        // FIXME: The only place we cared about subwindow was for
-        // bookmarking (i.e. not when saving state). Was this deliberate?
-        final WebBackForwardList list = mMainView.copyBackForwardList();
-        if (list == null) {
-            Log.w(LOGTAG, "populatePickerData called and WebBackForwardList is null");
-        }
-        final WebHistoryItem item = list != null ? list.getCurrentItem() : null;
-        populatePickerData(item);
-    }
-
-    // Populate the picker data using the given history item and the current top
-    // WebView.
-    private void populatePickerData(WebHistoryItem item) {
-        mPickerData = new PickerData();
-        if (item == null) {
-            Log.w(LOGTAG, "populatePickerData called with a null WebHistoryItem");
-        } else {
-            mPickerData.mUrl = item.getUrl();
-            mPickerData.mTitle = item.getTitle();
-            mPickerData.mFavicon = item.getFavicon();
-            if (mPickerData.mTitle == null) {
-                mPickerData.mTitle = mPickerData.mUrl;
-            }
-        }
-    }
-
-    // Create the PickerData and populate it using the saved state of the tab.
-    void populatePickerDataFromSavedState() {
-        if (mSavedState == null) {
-            return;
-        }
-        mPickerData = new PickerData();
-        mPickerData.mUrl = mSavedState.getString(CURRURL);
-        mPickerData.mTitle = mSavedState.getString(CURRTITLE);
-    }
-
-    void clearPickerData() {
-        mPickerData = null;
-    }
-
     /**
-     * Get the saved state bundle.
-     * @return
+     * Get the cached saved state bundle.
+     * @return cached state bundle
      */
     Bundle getSavedState() {
         return mSavedState;
@@ -1753,21 +1693,13 @@
 
         // Store some extra info for displaying the tab in the picker.
         final WebHistoryItem item = list != null ? list.getCurrentItem() : null;
-        populatePickerData(item);
 
-        if (mPickerData.mUrl != null) {
-            mSavedState.putString(CURRURL, mPickerData.mUrl);
-        }
-        if (mPickerData.mTitle != null) {
-            mSavedState.putString(CURRTITLE, mPickerData.mTitle);
-        }
+        mSavedState.putString(CURRURL, mCurrentState.mUrl);
+        mSavedState.putString(CURRTITLE, mCurrentState.mTitle);
         mSavedState.putBoolean(CLOSEONEXIT, mCloseOnExit);
         if (mAppId != null) {
             mSavedState.putString(APPID, mAppId);
         }
-        if (mOriginalUrl != null) {
-            mSavedState.putString(ORIGINALURL, mOriginalUrl);
-        }
         // Remember the parent tab so the relationship can be restored.
         if (mParentTab != null) {
             mSavedState.putInt(PARENTTAB, mWebViewController.getTabControl().getTabIndex(
@@ -1786,10 +1718,8 @@
         // Restore the internal state even if the WebView fails to restore.
         // This will maintain the app id, original url and close-on-exit values.
         mSavedState = null;
-        mPickerData = null;
         mCloseOnExit = b.getBoolean(CLOSEONEXIT);
         mAppId = b.getString(APPID);
-        mOriginalUrl = b.getString(ORIGINALURL);
 
         final WebBackForwardList list = mMainView.restoreState(b);
         if (list == null) {
@@ -1848,5 +1778,4 @@
         };
         mBookmarkAsyncTask.execute();
     }
-
 }
diff --git a/src/com/android/browser/TabBar.java b/src/com/android/browser/TabBar.java
index ea734a6..88209fe 100644
--- a/src/com/android/browser/TabBar.java
+++ b/src/com/android/browser/TabBar.java
@@ -73,10 +73,8 @@
 
     private boolean mUserRequestedUrlbar;
     private int mVisibleTitleHeight;
-    private boolean mHasReceivedTitle;
 
     private Drawable mGenericFavicon;
-    private String mLoadingText;
 
     private Drawable mActiveDrawable;
     private Drawable mInactiveDrawable;
@@ -111,7 +109,6 @@
         mNewTab = (ImageButton) findViewById(R.id.newtab);
         mNewTab.setOnClickListener(this);
         mGenericFavicon = res.getDrawable(R.drawable.app_web_browser_sm);
-        mLoadingText = res.getString(R.string.title_bar_loading);
         setChildrenDrawingOrderEnabled(true);
 
         // TODO: Change enabled states based on whether you can go
@@ -346,19 +343,16 @@
 
         private void updateFromData() {
             mTabData.mTabView = this;
-            if (mTabData.mUrl != null) {
-                setDisplayTitle(mTabData.mUrl);
+            Tab tab = mTabData.mTab;
+            String displayTitle = tab.getTitle();
+            if (displayTitle == null) {
+                displayTitle = tab.getUrl();
             }
-            if (mTabData.mTitle != null) {
-                setDisplayTitle(mTabData.mTitle);
-            }
+            setDisplayTitle(displayTitle);
             setProgress(mTabData.mProgress);
             if (mTabData.mIcon != null) {
                 setFavicon(mTabData.mIcon);
             }
-            if (mTabData.mLock != null) {
-                setLock(mTabData.mLock);
-            }
             if (mTabData.mTab != null) {
                 mIncognito.setVisibility(
                         mTabData.mTab.isPrivateBrowsingEnabled() ?
@@ -463,21 +457,13 @@
         TabView mTabView;
         int mProgress;
         Drawable mIcon;
-        Drawable mLock;
-        String mTitle;
-        String mUrl;
 
         TabViewData(Tab tab) {
             mTab = tab;
-            WebView web = tab.getWebView();
-            if (web != null) {
-                setUrlAndTitle(web.getUrl(), web.getTitle());
-            }
+            setUrlAndTitle(mTab.getUrl(), mTab.getTitle());
         }
 
         void setUrlAndTitle(String url, String title) {
-            mUrl = url;
-            mTitle = title;
             if (mTabView != null) {
                 if (title != null) {
                     mTabView.setDisplayTitle(title);
@@ -562,31 +548,12 @@
     }
 
     public void onUrlAndTitle(Tab tab, String url, String title) {
-        mHasReceivedTitle = true;
         TabViewData tvd = mTabMap.get(tab);
         if (tvd != null) {
             tvd.setUrlAndTitle(url, title);
         }
     }
 
-    public void onPageFinished(Tab tab) {
-        if (!mHasReceivedTitle) {
-            TabViewData tvd = mTabMap.get(tab);
-            if (tvd != null) {
-                tvd.setUrlAndTitle(tvd.mUrl, null);
-            }
-        }
-    }
-
-    public void onPageStarted(Tab tab, String url, Bitmap favicon) {
-        mHasReceivedTitle = false;
-        TabViewData tvd = mTabMap.get(tab);
-        if (tvd != null) {
-            tvd.setFavicon(favicon);
-            tvd.setUrlAndTitle(url, mLoadingText);
-        }
-    }
-
     private boolean isLoading() {
         TabViewData tvd = mTabMap.get(mTabControl.getCurrentTab());
         if ((tvd != null) && (tvd.mTabView != null)) {
diff --git a/src/com/android/browser/TabControl.java b/src/com/android/browser/TabControl.java
index 9e669ce..050ad94 100644
--- a/src/com/android/browser/TabControl.java
+++ b/src/com/android/browser/TabControl.java
@@ -350,11 +350,9 @@
                     Tab t = new Tab(mController, null, false, null, null);
                     if (state != null) {
                         t.setSavedState(state);
-                        t.populatePickerDataFromSavedState();
                         // Need to maintain the app id and original url so we
                         // can possibly reuse this tab.
                         t.setAppId(state.getString(Tab.APPID));
-                        t.setOriginalUrl(state.getString(Tab.ORIGINALURL));
                     }
                     mTabs.add(t);
                     // added the tab to the front as they are not current
@@ -537,28 +535,11 @@
     }
 
     /**
-     * Recreate the main WebView of the given tab. Returns true if the WebView
-     * requires a load, whether it was due to the fact that it was deleted, or
-     * it is because it was a voice search.
+     * Recreate the main WebView of the given tab.
      */
-    boolean recreateWebView(Tab t, UrlData urlData) {
-        final String url = urlData.mUrl;
+    void recreateWebView(Tab t) {
         final WebView w = t.getWebView();
         if (w != null) {
-            if (url != null && url.equals(t.getOriginalUrl())
-                    // Treat a voice intent as though it is a different URL,
-                    // since it most likely is.
-                    && urlData.mVoiceIntent == null) {
-                // The original url matches the current url. Just go back to the
-                // first history item so we can load it faster than if we
-                // rebuilt the WebView.
-                final WebBackForwardList list = w.copyBackForwardList();
-                if (list != null) {
-                    w.goBackOrForward(-list.getCurrentIndex());
-                    w.clearHistory(); // maintains the current page.
-                    return false;
-                }
-            }
             t.destroy();
         }
         // Create a new WebView. If this tab is the current tab, we need to put
@@ -569,10 +550,6 @@
         }
         // Clear the saved state and picker data
         t.setSavedState(null);
-        t.clearPickerData();
-        // Save the new url in order to avoid deleting the WebView.
-        t.setOriginalUrl(url);
-        return true;
     }
 
     /**
diff --git a/src/com/android/browser/UI.java b/src/com/android/browser/UI.java
index 9f03344..e2f76f1 100644
--- a/src/com/android/browser/UI.java
+++ b/src/com/android/browser/UI.java
@@ -64,23 +64,11 @@
 
     public void removeSubWindow(View subContainer);
 
-    // TODO: consolidate
-    public void setUrlTitle(Tab tab, String url, String title);
-
-    // TODO: consolidate
-    public void setFavicon(Tab tab, Bitmap icon);
-
-    public void resetTitleAndRevertLockIcon(Tab tab);
-
-    public void resetTitleAndIcon(Tab tab);
-
-    public void onPageStarted(Tab tab, String url, Bitmap favicon);
-
-    public void onPageFinished(Tab tab, String url);
+    public void onTabDataChanged(Tab tab);
 
     public void onPageStopped(Tab tab);
 
-    public void onProgressChanged(Tab tab, int progress);
+    public void onProgressChanged(Tab tab);
 
     public void showActiveTabsPage();
 
diff --git a/src/com/android/browser/WebViewController.java b/src/com/android/browser/WebViewController.java
index 64e97de..a187af0 100644
--- a/src/com/android/browser/WebViewController.java
+++ b/src/com/android/browser/WebViewController.java
@@ -50,7 +50,7 @@
 
     void onPageFinished(Tab tab, String url);
 
-    void onProgressChanged(Tab tab, int newProgress);
+    void onProgressChanged(Tab tab);
 
     void onReceivedTitle(Tab tab, final String title);
 
@@ -83,13 +83,15 @@
     void showSslCertificateOnError(WebView view, SslErrorHandler handler,
             SslError error);
 
+    void onUserCanceledSsl(Tab tab);
+
     void activateVoiceSearchMode(String title);
 
     void revertVoiceSearchMode(Tab tab);
 
     boolean shouldShowErrorConsole();
 
-    void resetTitleAndRevertLockIcon(Tab tab);
+    void onUpdatedLockIcon(Tab tab);
 
     void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType);
 
diff --git a/src/com/android/browser/XLargeUi.java b/src/com/android/browser/XLargeUi.java
index 11642af..dcba39b 100644
--- a/src/com/android/browser/XLargeUi.java
+++ b/src/com/android/browser/XLargeUi.java
@@ -145,12 +145,6 @@
     // WebView callbacks
 
     @Override
-    public void onPageStarted(Tab tab, String url, Bitmap favicon) {
-        super.onPageStarted(tab, url, favicon);
-        mTabBar.onPageStarted(tab, url, favicon);
-    }
-
-    @Override
     public void bookmarkedStatusHasChanged(Tab tab) {
         if (tab.inForeground()) {
             boolean isBookmark = tab.isBookmarkedSite();
@@ -160,16 +154,8 @@
     }
 
     @Override
-    public void onPageFinished(Tab tab, String url) {
-        mTabBar.onPageFinished(tab);
-        super.onPageFinished(tab, url);
-        if (mUseQuickControls) {
-            mFakeTitleBar.setShowProgressOnly(false);
-        }
-    }
-
-    @Override
-    public void onProgressChanged(Tab tab, int progress) {
+    public void onProgressChanged(Tab tab) {
+        int progress = tab.getLoadProgress();
         mTabBar.onProgress(tab, progress);
         if (tab.inForeground()) {
             mFakeTitleBar.setProgress(progress);
@@ -229,7 +215,6 @@
         } else {
             revertVoiceTitleBar(tab);
         }
-        resetTitleIconAndProgress(tab);
         updateLockIconToLatest(tab);
         tab.getTopWindow().requestFocus();
     }
@@ -331,16 +316,16 @@
     }
 
     @Override
-    public void setUrlTitle(Tab tab, String url, String title) {
-        super.setUrlTitle(tab, url, title);
-        mTabBar.onUrlAndTitle(tab, url, title);
+    public void setUrlTitle(Tab tab) {
+        super.setUrlTitle(tab);
+        mTabBar.onUrlAndTitle(tab, tab.getUrl(), tab.getTitle());
     }
 
     // Set the favicon in the title bar.
     @Override
-    public void setFavicon(Tab tab, Bitmap icon) {
-        super.setFavicon(tab, icon);
-        mTabBar.onFavicon(tab, icon);
+    public void setFavicon(Tab tab) {
+        super.setFavicon(tab);
+        mTabBar.onFavicon(tab, tab.getFavicon());
     }
 
     @Override
@@ -358,7 +343,7 @@
     @Override
     public void revertVoiceTitleBar(Tab tab) {
         mTitleBar.setInVoiceMode(false, null);
-        String url = tab.getCurrentUrl();
+        String url = tab.getUrl();
         mTitleBar.setDisplayTitle(url);
         mFakeTitleBar.setInVoiceMode(false, null);
         mFakeTitleBar.setDisplayTitle(url);