am 6946bc38: am f7bd7ee8: Import revised translations
diff --git a/res/anim/find_dialog_enter.xml b/res/anim/find_dialog_enter.xml
index 5e597a4..6fbcb9e 100644
--- a/res/anim/find_dialog_enter.xml
+++ b/res/anim/find_dialog_enter.xml
@@ -16,6 +16,6 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@android:anim/decelerate_interpolator">
-	<translate android:fromYDelta="25%" android:toYDelta="0" android:duration="75"/>
-	<alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="75" />
+    <translate android:fromYDelta="-25%" android:toYDelta="0" android:duration="75"/>
+    <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="75" />
 </set>
diff --git a/res/anim/find_dialog_exit.xml b/res/anim/find_dialog_exit.xml
index 854abd0..9845849 100644
--- a/res/anim/find_dialog_exit.xml
+++ b/res/anim/find_dialog_exit.xml
@@ -16,7 +16,7 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@android:anim/accelerate_interpolator">
-	<translate android:fromYDelta="0" android:toYDelta="50%" android:duration="50"/>
-	<alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="50" />
+    <translate android:fromYDelta="0" android:toYDelta="-50%" android:duration="50"/>
+    <alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="50" />
 </set>
 
diff --git a/res/layout/browser_subwindow.xml b/res/layout/browser_subwindow.xml
index 76d72d5..adf3284 100644
--- a/res/layout/browser_subwindow.xml
+++ b/res/layout/browser_subwindow.xml
@@ -23,6 +23,7 @@
         android:layout_height="match_parent"
         android:padding="10dip" >
         <LinearLayout
+            android:id="@+id/inner_container"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:orientation="vertical"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 18a2144..a30a399 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -50,17 +50,16 @@
     <!-- Label for a confirm button.  Used in multiple contexts. -->
     <string name="ok">OK</string>
 
-    <!-- Displayed on the Find dialog to display the number of matches
-         found in the current page. -->
+    <!-- Displayed on the Find dialog when there are no matches -->
+    <string name="no_matches">No matches</string>
+
+    <!-- Displayed on the Find dialog to display the index of the highlighted
+         match and total number of matches found in the current page. -->
     <plurals name="matches_found">
-        <!-- Case of no matches -->
-        <item quantity="zero">No matches</item>
         <!-- Case of one match -->
         <item quantity="one">1 match</item>
-        <!-- Case of "few" (two) matches -->
-        <item quantity="few"><xliff:g id="number" example="2">%d</xliff:g> matches</item>
-        <!-- Case of several matches -->
-        <item quantity="other"><xliff:g id="number" example="137">%d</xliff:g> matches</item>
+        <!-- Case of multiple total matches -->
+        <item quantity="other"><xliff:g id="index" example="2">%d</xliff:g> of <xliff:g id="total" example="137">%d</xliff:g></item>
     </plurals>
 
     <!-- Displayed on the title bar while the page is loading -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 4779aa1..2e8510a 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -30,11 +30,6 @@
         <item name="android:windowContentOverlay">@null</item>
     </style>
 
-    <style name="FindDialog">
-        <item name="android:windowEnterAnimation">@anim/find_dialog_enter</item>
-        <item name="android:windowExitAnimation">@anim/find_dialog_exit</item>
-    </style>
-
     <style name="TitleBar">
         <item name="android:windowEnterAnimation">@anim/title_bar_enter</item>
         <item name="android:windowExitAnimation">@anim/title_bar_exit</item>
diff --git a/res/values/themes.xml b/res/values/themes.xml
deleted file mode 100644
index bb922dd..0000000
--- a/res/values/themes.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<resources>
-    <style name="FindDialogTheme"> 
-        <item name="android:windowFrame">@null</item>
-        <item name="android:windowIsFloating">true</item>
-        <item name="android:windowIsTranslucent">true</item>
-        <item name="android:windowNoTitle">true</item>
-        <item name="android:background">@null</item>
-        <item name="android:windowBackground">@null</item>
-        <item name="android:windowAnimationStyle">@style/FindDialog</item>
-        <item name="android:backgroundDimEnabled">false</item>
-    </style>
-</resources>
diff --git a/src/com/android/browser/ActiveTabsPage.java b/src/com/android/browser/ActiveTabsPage.java
index 2de7787..52828b3 100644
--- a/src/com/android/browser/ActiveTabsPage.java
+++ b/src/com/android/browser/ActiveTabsPage.java
@@ -20,6 +20,7 @@
 import android.graphics.Bitmap;
 import android.os.Handler;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -32,6 +33,7 @@
 import android.widget.TextView;
 
 public class ActiveTabsPage extends LinearLayout {
+    private static final String LOGTAG = "TabPicker";
     private final BrowserActivity   mBrowserActivity;
     private final LayoutInflater    mFactory;
     private final TabControl        mControl;
@@ -152,7 +154,19 @@
                         (ImageView) convertView.findViewById(R.id.favicon);
                 View close = convertView.findViewById(R.id.close);
                 Tab tab = mControl.getTab(position);
+                if (tab.getWebView() == null) {
+                    // This means that populatePickerData will have to use the
+                    // saved state.
+                    Log.w(LOGTAG, "Tab " + position + " has a null WebView and "
+                            + (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 "
+                            + "null WebView or null WebHistoryItem");
+                }
                 title.setText(tab.getTitle());
                 url.setText(tab.getUrl());
                 Bitmap icon = tab.getFavicon();
diff --git a/src/com/android/browser/BrowserActivity.java b/src/com/android/browser/BrowserActivity.java
index 5e55789..bee06b5 100644
--- a/src/com/android/browser/BrowserActivity.java
+++ b/src/com/android/browser/BrowserActivity.java
@@ -834,6 +834,13 @@
             if (mainView == null) {
                 return;
             }
+            // Do not need to check for null, since the current tab will have
+            // at least a main WebView, or we would have returned above.
+            if (getTopWindow().getFindIsUp()) {
+                // Do not show the fake title bar, which would cover up the
+                // FindDialog.
+                return;
+            }
 
             WindowManager manager
                     = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
@@ -1367,9 +1374,18 @@
                 if (null == mFindDialog) {
                     mFindDialog = new FindDialog(this);
                 }
-                mFindDialog.setWebView(getTopWindow());
-                mFindDialog.show();
-                getTopWindow().setFindIsUp(true);
+                // Need to do something special for Tablet
+                Tab tab = mTabControl.getCurrentTab();
+                if (tab.getSubWebView() == null) {
+                    // If the Find is being performed on the main webview,
+                    // remove the embedded title bar.
+                    WebView mainView = tab.getWebView();
+                    if (mainView != null) {
+                        mainView.setEmbeddedTitleBar(null);
+                    }
+                }
+                hideFakeTitleBar();
+                tab.showFind(mFindDialog);
                 mMenuState = EMPTY_MENU;
                 break;
 
@@ -1450,8 +1466,30 @@
         return true;
     }
 
+    /*
+     * Remove the FindDialog.
+     */
     public void closeFind() {
+        Tab currentTab = mTabControl.getCurrentTab();
+        if (mFindDialog != null) {
+            currentTab.closeFind(mFindDialog);
+            mFindDialog.dismiss();
+        }
+        // If the Find was being performed in the main WebView, replace the
+        // embedded title bar.
+        if (currentTab.getSubWebView() == null) {
+            WebView mainView = currentTab.getWebView();
+            if (mainView != null) {
+                mainView.setEmbeddedTitleBar(mTitleBar);
+            }
+        }
         mMenuState = R.id.MAIN_MENU;
+        if (mInLoad) {
+            // The title bar was hidden, because otherwise it would cover up the
+            // find dialog.  Now that the dialog has been removed, show the fake
+            // title bar once again.
+            showFakeTitleBar();
+        }
     }
 
     @Override
@@ -2207,41 +2245,8 @@
                             startActivity(intent);
                             break;
                         case R.id.share_link_context_menu_id:
-                            // See if this site has been visited before
-                            StringBuilder sb = new StringBuilder(
-                                    Browser.BookmarkColumns.URL + " = ");
-                            DatabaseUtils.appendEscapedSQLString(sb, url);
-                            Cursor c = mResolver.query(Browser.BOOKMARKS_URI,
-                                    Browser.HISTORY_PROJECTION,
-                                    sb.toString(),
-                                    null,
+                            sharePage(BrowserActivity.this, title, url, null,
                                     null);
-                            if (c.moveToFirst()) {
-                                // The site has been visited before, so grab the
-                                // info from the database.
-                                Bitmap favicon = null;
-                                Bitmap thumbnail = null;
-                                String linkTitle = c.getString(Browser.
-                                        HISTORY_PROJECTION_TITLE_INDEX);
-                                byte[] data = c.getBlob(Browser.
-                                        HISTORY_PROJECTION_FAVICON_INDEX);
-                                if (data != null) {
-                                    favicon = BitmapFactory.decodeByteArray(
-                                            data, 0, data.length);
-                                }
-                                data = c.getBlob(Browser.
-                                        HISTORY_PROJECTION_THUMBNAIL_INDEX);
-                                if (data != null) {
-                                    thumbnail = BitmapFactory.decodeByteArray(
-                                            data, 0, data.length);
-                                }
-                                sharePage(BrowserActivity.this,
-                                        linkTitle, url, favicon, thumbnail);
-                            } else {
-                                Browser.sendString(BrowserActivity.this, url,
-                                        getString(
-                                        R.string.choosertitle_sharevia));
-                            }
                             break;
                         case R.id.copy_link_context_menu_id:
                             copy(url);
@@ -2462,7 +2467,9 @@
         onProgressChanged(view, INITIAL_PROGRESS);
         mDidStopLoad = false;
         if (!mIsNetworkUp) createAndShowNetworkDialog();
-
+        if (view.getFindIsUp()) {
+            closeFind();
+        }
         if (mSettings.isTracing()) {
             String host;
             try {
diff --git a/src/com/android/browser/BrowserDownloadAdapter.java b/src/com/android/browser/BrowserDownloadAdapter.java
index 0f8f721..f22c9fe 100644
--- a/src/com/android/browser/BrowserDownloadAdapter.java
+++ b/src/com/android/browser/BrowserDownloadAdapter.java
@@ -26,6 +26,7 @@
 import android.drm.mobile1.DrmRawContent;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.os.Handler;
 import android.provider.Downloads;
 import android.text.format.Formatter;
 import android.view.LayoutInflater;
@@ -55,8 +56,9 @@
     private int mMimetypeColumnId;
     private int mDateColumnId;
 
-    public BrowserDownloadAdapter(Context context, Cursor c, int index) {
-        super(context, c, index);
+    public BrowserDownloadAdapter(Context context, Cursor c, int index,
+            Handler handler) {
+        super(context, c, index, handler);
         mTitleColumnId = c.getColumnIndexOrThrow(Downloads.Impl.COLUMN_TITLE);
         mDescColumnId = c.getColumnIndexOrThrow(Downloads.Impl.COLUMN_DESCRIPTION);
         mStatusColumnId = c.getColumnIndexOrThrow(Downloads.Impl.COLUMN_STATUS);
diff --git a/src/com/android/browser/BrowserDownloadPage.java b/src/com/android/browser/BrowserDownloadPage.java
index 18faf8b..bbf1191 100644
--- a/src/com/android/browser/BrowserDownloadPage.java
+++ b/src/com/android/browser/BrowserDownloadPage.java
@@ -63,6 +63,7 @@
     // Only meaningful while a ContentObserver is registered.  The ContextMenu
     // will be reopened on this View.
     private View                    mSelectedView;
+    private Handler                 mHandler;
 
     private final static String LOGTAG = "BrowserDownloadPage";
     @Override 
@@ -85,7 +86,7 @@
                 Downloads.Impl._DATA,
                 Downloads.Impl.COLUMN_MIME_TYPE},
                 null, Downloads.Impl.COLUMN_LAST_MODIFICATION + " DESC");
-        
+        mHandler = new Handler();
         // only attach everything to the listbox if we can access
         // the download database. Otherwise, just show it empty
         if (mDownloadCursor != null) {
@@ -99,7 +100,7 @@
             // Create a list "controller" for the data
             mDownloadAdapter = new BrowserDownloadAdapter(this, 
                     mDownloadCursor, mDownloadCursor.getColumnIndexOrThrow(
-                    Downloads.Impl.COLUMN_LAST_MODIFICATION));
+                    Downloads.Impl.COLUMN_LAST_MODIFICATION), mHandler);
 
             setListAdapter(mDownloadAdapter);
             mListView.setOnCreateContextMenuListener(this);
@@ -241,8 +242,8 @@
      */
     private class ChangeObserver extends ContentObserver {
         private final Uri mTrack;
-        public ChangeObserver(Uri track) {
-            super(new Handler());
+        public ChangeObserver(Uri track, Handler handler) {
+            super(handler);
             mTrack = track;
         }
 
@@ -313,7 +314,7 @@
                     getContentResolver().unregisterContentObserver(
                             mContentObserver);
                 }
-                mContentObserver = new ChangeObserver(track);
+                mContentObserver = new ChangeObserver(track, mHandler);
                 mSelectedView = v;
                 getContentResolver().registerContentObserver(track, false,
                         mContentObserver);
diff --git a/src/com/android/browser/BrowserHistoryPage.java b/src/com/android/browser/BrowserHistoryPage.java
index 23080f8..0281087 100644
--- a/src/com/android/browser/BrowserHistoryPage.java
+++ b/src/com/android/browser/BrowserHistoryPage.java
@@ -25,7 +25,10 @@
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
+import android.os.AsyncTask;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
 import android.os.ServiceManager;
 import android.provider.Browser;
 import android.text.IClipboard;
@@ -92,47 +95,75 @@
         }
     }
 
+    private static final int ADAPTER_CREATED = 1000;
+    private Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case ADAPTER_CREATED:
+                    mAdapter = (HistoryAdapter) msg.obj;
+                    setListAdapter(mAdapter);
+                    final ExpandableListView list = getExpandableListView();
+                    // Add an empty view late, so it does not claim an empty
+                    // history before the adapter is present
+                    View v = new ViewStub(BrowserHistoryPage.this,
+                            R.layout.empty_history);
+                    addContentView(v, new LayoutParams(
+                            LayoutParams.MATCH_PARENT,
+                            LayoutParams.MATCH_PARENT));
+                    list.setEmptyView(v);
+                    list.setOnCreateContextMenuListener(
+                            BrowserHistoryPage.this);
+                    // Do not post the runnable if there is nothing in the list.
+                    if (list.getExpandableListAdapter().getGroupCount() > 0) {
+                        list.post(new Runnable() {
+                            public void run() {
+                                // In case the history gets cleared before this
+                                // event happens
+                                if (list.getExpandableListAdapter()
+                                        .getGroupCount() > 0) {
+                                    list.expandGroup(0);
+                                }
+                            }
+                        });
+                    }
+                    break;
+            }
+        }
+    };
+
     @Override
     protected void onCreate(Bundle icicle) {
         super.onCreate(icicle);
         setTitle(R.string.browser_history);
 
-        final String whereClause = Browser.BookmarkColumns.VISITS + " > 0"
-                // In AddBookmarkPage, where we save new bookmarks, we add
-                // three visits to newly created bookmarks, so that
-                // bookmarks that have not been visited will show up in the
-                // most visited, and higher in the goto search box.
-                // However, this puts the site in the history, unless we
-                // ignore sites with a DATE of 0, which the next line does.
-                + " AND " + Browser.BookmarkColumns.DATE + " > 0";
-        final String orderBy = Browser.BookmarkColumns.DATE + " DESC";
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... unused) {
+                final String whereClause = Browser.BookmarkColumns.VISITS
+                        + " > 0"
+                        // In AddBookmarkPage, where we save new bookmarks, we
+                        // add three visits to newly created bookmarks, so that
+                        // bookmarks that have not been visited will show up in
+                        // the most visited, and higher in the goto search box.
+                        // However, this puts the site in the history, unless
+                        // we ignore sites with a DATE of 0, which the next
+                        // line does.
+                        + " AND " + Browser.BookmarkColumns.DATE + " > 0";
+                final String orderBy = Browser.BookmarkColumns.DATE + " DESC";
 
-        Cursor cursor = managedQuery(
-                Browser.BOOKMARKS_URI,
-                Browser.HISTORY_PROJECTION,
-                whereClause, null, orderBy);
+                Cursor cursor = managedQuery(
+                        Browser.BOOKMARKS_URI,
+                        Browser.HISTORY_PROJECTION,
+                        whereClause, null, orderBy);
 
-        mAdapter = new HistoryAdapter(this, cursor,
-                Browser.HISTORY_PROJECTION_DATE_INDEX);
-        setListAdapter(mAdapter);
-        final ExpandableListView list = getExpandableListView();
-        list.setOnCreateContextMenuListener(this);
-        View v = new ViewStub(this, R.layout.empty_history);
-        addContentView(v, new LayoutParams(LayoutParams.MATCH_PARENT,
-                LayoutParams.MATCH_PARENT));
-        list.setEmptyView(v);
-        // Do not post the runnable if there is nothing in the list.
-        if (list.getExpandableListAdapter().getGroupCount() > 0) {
-            list.post(new Runnable() {
-                public void run() {
-                    // In case the history gets cleared before this event
-                    // happens.
-                    if (list.getExpandableListAdapter().getGroupCount() > 0) {
-                        list.expandGroup(0);
-                    }
-                }
-            });
-        }
+                HistoryAdapter adapter = new HistoryAdapter(
+                        BrowserHistoryPage.this, cursor,
+                        Browser.HISTORY_PROJECTION_DATE_INDEX, mHandler);
+                mHandler.obtainMessage(ADAPTER_CREATED, adapter).sendToTarget();
+                return null;
+            }
+        }.execute();
         mDisableNewWindow = getIntent().getBooleanExtra("disable_new_window",
                 false);
 
@@ -153,6 +184,7 @@
 
     @Override
     protected void onDestroy() {
+        mHandler.removeCallbacksAndMessages(null);
         super.onDestroy();
         CombinedBookmarkHistoryActivity.getIconListenerSet()
                 .removeListener(mIconReceiver);
@@ -181,7 +213,7 @@
                 // CombinedBookmarkHistoryActivity
                 ((CombinedBookmarkHistoryActivity) getParent())
                         .removeParentChildRelationShips();
-                mAdapter.refreshData();
+                if (mAdapter != null) mAdapter.refreshData();
                 return true;
                 
             default:
@@ -265,7 +297,7 @@
                 return true;
             case R.id.delete_context_menu_id:
                 Browser.deleteFromHistory(getContentResolver(), url);
-                mAdapter.refreshData();
+                if (mAdapter != null) mAdapter.refreshData();
                 return true;
             case R.id.homepage_context_menu_id:
                 BrowserSettings.getInstance().setHomePage(this, url);
@@ -297,8 +329,9 @@
     }
 
     private class HistoryAdapter extends DateSortedExpandableListAdapter {
-        HistoryAdapter(Context context, Cursor cursor, int index) {
-            super(context, cursor, index);
+        HistoryAdapter(Context context, Cursor cursor, int index,
+                Handler handler) {
+            super(context, cursor, index, handler);
             
         }
 
diff --git a/src/com/android/browser/DateSortedExpandableListAdapter.java b/src/com/android/browser/DateSortedExpandableListAdapter.java
index 1d04493..f8261d8 100644
--- a/src/com/android/browser/DateSortedExpandableListAdapter.java
+++ b/src/com/android/browser/DateSortedExpandableListAdapter.java
@@ -51,8 +51,8 @@
     private Context mContext;
 
     private class ChangeObserver extends ContentObserver {
-        public ChangeObserver() {
-            super(new Handler());
+        public ChangeObserver(Handler handler) {
+            super(handler);
         }
 
         @Override
@@ -67,13 +67,13 @@
     }
 
     public DateSortedExpandableListAdapter(Context context, Cursor cursor,
-            int dateIndex) {
+            int dateIndex, Handler handler) {
         mContext = context;
         mDateSorter = new DateSorter(context);
         mObservers = new Vector<DataSetObserver>();
         mCursor = cursor;
         mIdIndex = cursor.getColumnIndexOrThrow(BaseColumns._ID);
-        cursor.registerContentObserver(new ChangeObserver());
+        cursor.registerContentObserver(new ChangeObserver(handler));
         mDateIndex = dateIndex;
         buildMap();
     }
diff --git a/src/com/android/browser/FindDialog.java b/src/com/android/browser/FindDialog.java
index 45c8016..bcd5bb7 100644
--- a/src/com/android/browser/FindDialog.java
+++ b/src/com/android/browser/FindDialog.java
@@ -16,24 +16,24 @@
 
 package com.android.browser;
 
-import android.app.Dialog;
 import android.content.Context;
-import android.os.Bundle;
 import android.text.Editable;
+import android.text.Selection;
 import android.text.Spannable;
 import android.text.TextWatcher;
 import android.view.Gravity;
 import android.view.KeyEvent;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.Window;
-import android.view.WindowManager;
+import android.view.animation.AnimationUtils;
 import android.view.inputmethod.InputMethodManager;
 import android.webkit.WebView;
 import android.widget.EditText;
+import android.widget.LinearLayout;
 import android.widget.TextView;
 
-/* package */ class FindDialog extends Dialog implements TextWatcher {
+/* package */ class FindDialog extends LinearLayout implements TextWatcher {
     private WebView         mWebView;
     private TextView        mMatches;
     private BrowserActivity mBrowserActivity;
@@ -44,6 +44,11 @@
     private View            mPrevButton;
     private View            mMatchesView;
 
+    // When the dialog is opened up with old text, enter needs to be pressed
+    // (or the text needs to be changed) before WebView.findAll can be called.
+    // Once it has been called, enter should move to the next match.
+    private boolean         mMatchesFound;
+    private int             mNumberOfMatches;
     private View.OnClickListener mFindListener = new View.OnClickListener() {
         public void onClick(View v) {
             findNext();
@@ -53,7 +58,7 @@
     private View.OnClickListener mFindCancelListener  = 
             new View.OnClickListener() {
         public void onClick(View v) {
-            dismiss();
+            mBrowserActivity.closeFind();
         }
     };
     
@@ -64,6 +69,7 @@
                 throw new AssertionError("No WebView for FindDialog::onClick");
             }
             mWebView.findNext(false);
+            updateMatchesString();
             hideSoftInput();
         }
     };
@@ -89,22 +95,11 @@
     }
 
     /* package */ FindDialog(BrowserActivity context) {
-        super(context, R.style.FindDialogTheme);
+        super(context);
         mBrowserActivity = context;
-        setCanceledOnTouchOutside(true);
-    }
 
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        Window theWindow = getWindow();
-        theWindow.setGravity(Gravity.BOTTOM|Gravity.FILL_HORIZONTAL);
-
-        setContentView(R.layout.browser_find);
-
-        theWindow.setLayout(ViewGroup.LayoutParams.MATCH_PARENT,
-                ViewGroup.LayoutParams.WRAP_CONTENT);
+        LayoutInflater factory = LayoutInflater.from(context);
+        factory.inflate(R.layout.browser_find, this);
 
         mEditText = (EditText) findViewById(R.id.edit);
         
@@ -122,23 +117,57 @@
         mMatches = (TextView) findViewById(R.id.matches);
         mMatchesView = findViewById(R.id.matches_view);
         disableButtons();
-        theWindow.setSoftInputMode(
-                WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
+
     }
-    
+
+    /**
+     * Called by BrowserActivity.closeFind.  Start the animation to hide
+     * the dialog, inform the WebView that the dialog is being dismissed,
+     * and hide the soft keyboard.
+     */
     public void dismiss() {
-        super.dismiss();
-        mBrowserActivity.closeFind();
         mWebView.notifyFindDialogDismissed();
+        startAnimation(AnimationUtils.loadAnimation(mBrowserActivity,
+                R.anim.find_dialog_exit));
+        hideSoftInput();
+    }
+
+    @Override
+    public boolean dispatchKeyEventPreIme(KeyEvent event) {
+        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
+            KeyEvent.DispatcherState state = getKeyDispatcherState();
+            if (state != null) {
+                int action = event.getAction();
+                if (KeyEvent.ACTION_DOWN == action
+                        && event.getRepeatCount() == 0) {
+                    state.startTracking(event, this);
+                    return true;
+                } else if (KeyEvent.ACTION_UP == action
+                        && !event.isCanceled() && state.isTracking(event)) {
+                    mBrowserActivity.closeFind();
+                    return true;
+                }
+            }
+        }
+        return super.dispatchKeyEventPreIme(event);
     }
 
     @Override
     public boolean dispatchKeyEvent(KeyEvent event) {
-        if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER
-                && event.getAction() == KeyEvent.ACTION_UP
-                && mEditText.hasFocus()) {
-            findNext();
-            return true;
+        int keyCode = event.getKeyCode();
+        if (event.getAction() == KeyEvent.ACTION_UP) {
+            if (keyCode == KeyEvent.KEYCODE_ENTER
+                    && mEditText.hasFocus()) {
+                if (mMatchesFound) {
+                    findNext();
+                } else {
+                    findAll();
+                    // Set the selection to the end.
+                    Spannable span = (Spannable) mEditText.getText();
+                    Selection.setSelection(span, span.length());
+                }
+                return true;
+            }
         }
         return super.dispatchKeyEvent(event);
     }
@@ -148,18 +177,27 @@
             throw new AssertionError("No WebView for FindDialog::findNext");
         }
         mWebView.findNext(true);
+        updateMatchesString();
         hideSoftInput();
     }
 
     public void show() {
-        super.show();
+        // In case the matches view is showing from a previous search
+        mMatchesView.setVisibility(View.INVISIBLE);
+        mMatchesFound = false;
+        // This text is only here to ensure that mMatches has a height.
+        mMatches.setText("0");
         mEditText.requestFocus();
-        mEditText.setText("");
         Spannable span = (Spannable) mEditText.getText();
-        span.setSpan(this, 0, span.length(), 
-                     Spannable.SPAN_INCLUSIVE_INCLUSIVE);
-        setMatchesFound(0);
+        int length = span.length();
+        Selection.setSelection(span, 0, length);
+        span.setSpan(this, 0, length, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
         disableButtons();
+        startAnimation(AnimationUtils.loadAnimation(mBrowserActivity,
+                R.anim.find_dialog_enter));
+        InputMethodManager imm = (InputMethodManager)
+                mBrowserActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
+        imm.showSoftInput(mEditText, 0);
     }
     
     // TextWatcher methods
@@ -173,9 +211,13 @@
                               int start, 
                               int before, 
                               int count) {
+        findAll();
+    }
+
+    private void findAll() {
         if (mWebView == null) {
             throw new AssertionError(
-                    "No WebView for FindDialog::onTextChanged");
+                    "No WebView for FindDialog::findAll");
         }
         CharSequence find = mEditText.getText();
         if (0 == find.length()) {
@@ -184,14 +226,16 @@
             mMatchesView.setVisibility(View.INVISIBLE);
         } else {
             mMatchesView.setVisibility(View.VISIBLE);
-            mWebView.setFindDialogHeight(
-                getWindow().getDecorView().getHeight());
             int found = mWebView.findAll(find.toString());
+            mMatchesFound = true;
             setMatchesFound(found);
             if (found < 2) {
                 disableButtons();
                 if (found == 0) {
-                    setMatchesFound(0);
+                    // Cannot use getQuantityString, which ignores the "zero"
+                    // quantity.
+                    mMatches.setText(mBrowserActivity.getResources().getString(
+                            R.string.no_matches));
                 }
             } else {
                 mPrevButton.setFocusable(true);
@@ -203,8 +247,16 @@
     }
 
     private void setMatchesFound(int found) {
+        mNumberOfMatches = found;
+        updateMatchesString();
+    }
+
+    private void updateMatchesString() {
+        // Note: updateMatchesString is only called by methods that have already
+        // checked mWebView for null.
         String template = mBrowserActivity.getResources().
-                getQuantityString(R.plurals.matches_found, found, found);
+                getQuantityString(R.plurals.matches_found, mNumberOfMatches,
+                mWebView.findIndex() + 1, mNumberOfMatches);
 
         mMatches.setText(template);
     }
diff --git a/src/com/android/browser/Tab.java b/src/com/android/browser/Tab.java
index 5350a18..b9942c0 100644
--- a/src/com/android/browser/Tab.java
+++ b/src/com/android/browser/Tab.java
@@ -87,7 +87,7 @@
     // The Geolocation permissions prompt
     private GeolocationPermissionsPrompt mGeolocationPermissionsPrompt;
     // Main WebView wrapper
-    private View mContainer;
+    private LinearLayout mContainer;
     // Main WebView
     private WebView mMainView;
     // Subwindow container
@@ -1208,9 +1208,18 @@
     private static class SubWindowClient extends WebViewClient {
         // The main WebViewClient.
         private final WebViewClient mClient;
+        private final BrowserActivity mBrowserActivity;
 
-        SubWindowClient(WebViewClient client) {
+        SubWindowClient(WebViewClient client, BrowserActivity activity) {
             mClient = client;
+            mBrowserActivity = activity;
+        }
+        @Override
+        public void onPageStarted(WebView view, String url, Bitmap favicon) {
+            // Unlike the others, do not call mClient's version, which would
+            // change the progress bar.  However, we do want to remove the
+            // find dialog.
+            if (view.getFindIsUp()) mBrowserActivity.closeFind();
         }
         @Override
         public void doUpdateVisitedHistory(WebView view, String url,
@@ -1300,7 +1309,7 @@
 
         // The tab consists of a container view, which contains the main
         // WebView, as well as any other UI elements associated with the tab.
-        mContainer = mInflateService.inflate(R.layout.tab, null);
+        mContainer = (LinearLayout) mInflateService.inflate(R.layout.tab, null);
 
         mDownloadListener = new DownloadListener() {
             public void onDownloadStart(String url, String userAgent,
@@ -1411,6 +1420,7 @@
      */
     boolean createSubWindow() {
         if (mSubView == null) {
+            if (mMainView.getFindIsUp()) mActivity.closeFind();
             mSubViewContainer = mInflateService.inflate(
                     R.layout.browser_subwindow, null);
             mSubView = (WebView) mSubViewContainer.findViewById(R.id.webview);
@@ -1419,7 +1429,8 @@
             mSubView.setMapTrackballToArrowKeys(false);
             // Enable the built-in zoom
             mSubView.getSettings().setBuiltInZoomControls(true);
-            mSubView.setWebViewClient(new SubWindowClient(mWebViewClient));
+            mSubView.setWebViewClient(new SubWindowClient(mWebViewClient,
+                    mActivity));
             mSubView.setWebChromeClient(new SubWindowChromeClient(
                     mWebChromeClient));
             // Set a different DownloadListener for the mSubView, since it will
@@ -1457,6 +1468,9 @@
      */
     void dismissSubWindow() {
         if (mSubView != null) {
+            if (mSubView.getFindIsUp()) {
+                mActivity.closeFind();
+            }
             BrowserSettings.getInstance().deleteObserver(
                     mSubView.getSettings());
             mSubView.destroy();
@@ -1481,6 +1495,7 @@
     void removeSubWindow(ViewGroup content) {
         if (mSubView != null) {
             content.removeView(mSubViewContainer);
+            if (mSubView.getFindIsUp()) mActivity.closeFind();
         }
     }
 
@@ -1539,6 +1554,7 @@
                 (FrameLayout) mContainer.findViewById(R.id.webview_wrapper);
         wrapper.removeView(mMainView);
         content.removeView(mContainer);
+        if (mMainView.getFindIsUp()) mActivity.closeFind();
         removeSubWindow(content);
     }
 
@@ -1812,6 +1828,9 @@
         // 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);
     }
@@ -1820,7 +1839,9 @@
     // WebView.
     private void populatePickerData(WebHistoryItem item) {
         mPickerData = new PickerData();
-        if (item != null) {
+        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();
@@ -1934,4 +1955,36 @@
         }
         return true;
     }
+
+    /*
+     * Open the find dialog.  Called by BrowserActivity.
+     */
+    void showFind(FindDialog dialog) {
+        LinearLayout container;
+        WebView view;
+        if (mSubView != null) {
+            view = mSubView;
+            container = (LinearLayout) mSubViewContainer.findViewById(
+                    R.id.inner_container);
+        } else {
+            view = mMainView;
+            container = mContainer;
+        }
+        dialog.show();
+        container.addView(dialog, 0, new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT));
+        dialog.setWebView(view);
+        view.setFindIsUp(true);
+    }
+
+    /*
+     * Close the find dialog.  Called by BrowserActivity.closeFind.
+     */
+    void closeFind(FindDialog dialog) {
+        // The dialog may be attached to the subwindow.  Ensure that the
+        // correct parent has it removed.
+        LinearLayout parent = (LinearLayout) dialog.getParent();
+        if (parent != null) parent.removeView(dialog);
+    }
 }
diff --git a/tests/assets/bindings_test.html b/tests/assets/bindings_test.html
index c20ccec..71f3438 100755
--- a/tests/assets/bindings_test.html
+++ b/tests/assets/bindings_test.html
@@ -175,7 +175,7 @@
 function runTests() {
 
   // Assume that if the test isn't done after 10s that we failed.
-  window.setTimeout(function() { JNIBindingsTest.testComplete(); }, 10000);
+  window.setTimeout(function() { JNIBindingsTest.notifyComplete(); }, 10000);
 
   if (testPrimitiveTypes()) {
     appendLog("testPrimitiveTypes passed!");
@@ -231,7 +231,7 @@
     appendLog("testParameterTypeMismatch failed!");
   }
 
-  JNIBindingsTest.testComplete();
+  JNIBindingsTest.notifyComplete();
 }
 </script>
 
diff --git a/tests/src/com/android/browser/JNIBindingsTest.java b/tests/src/com/android/browser/JNIBindingsTest.java
index bfa3ac1..ba3c66a 100644
--- a/tests/src/com/android/browser/JNIBindingsTest.java
+++ b/tests/src/com/android/browser/JNIBindingsTest.java
@@ -20,6 +20,7 @@
 import android.util.Log;
 
 import java.util.Arrays;
+
 import junit.framework.AssertionFailedError;
 
 public class JNIBindingsTest extends AndroidTestCase {
@@ -34,9 +35,9 @@
         mTestApp = testApp;
     }
 
-    public void testComplete() {
+    public void notifyComplete() {
         Log.v(LOGTAG, "Completing the test.");
-        mTestApp.testComplete();
+        mTestApp.notifyComplete();
     }
 
     public void printAssertionFailed(AssertionFailedError e) {
@@ -232,7 +233,7 @@
             assertEquals(expectedIntParam, intParam);
             assertEquals(expectedDoubleParam, doubleParam);
             assertEquals(expectedBooleanParam, booleanParam);
-            assertEquals(expectedCharParam, charParam);;
+            assertEquals(expectedCharParam, charParam);
 
             // EMULATE_JSC_BINDINGS  JSC passes "undefined" for undefined types.
             assertEquals(expectedUndefinedParam, undefinedParam);
diff --git a/tests/src/com/android/browser/JNIBindingsTestApp.java b/tests/src/com/android/browser/JNIBindingsTestApp.java
index e01aca2..4f083f6 100644
--- a/tests/src/com/android/browser/JNIBindingsTestApp.java
+++ b/tests/src/com/android/browser/JNIBindingsTestApp.java
@@ -18,7 +18,6 @@
 
 import android.app.Instrumentation;
 import android.net.http.SslError;
-import android.os.Environment;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -29,6 +28,12 @@
 import android.webkit.SslErrorHandler;
 import android.webkit.WebView;
 
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
 /**
  * Adds a JavaScript interface to the webview and calls functions on it to verify variables
  * are passed from JS to Java correctly.
@@ -37,6 +42,8 @@
 
     private final static String TAG = "JNIBindingsTest";
 
+    private static final String SDCARD_BINDINGS_TEST_HTML = "/sdcard/bindings_test.html";
+
     private static final int MSG_WEBKIT_DATA_READY = 101;
 
     private BrowserActivity mActivity = null;
@@ -67,9 +74,11 @@
             mWebView = webView;
         }
 
+        @Override
         public void run() {
             Looper.prepare();
             mHandler = new Handler() {
+                @Override
                 public void handleMessage(Message msg) {
                     switch (msg.what) {
                         case MSG_WEBKIT_DATA_READY: {
@@ -102,6 +111,32 @@
         mInst = getInstrumentation();
         mInst.waitForIdleSync();
 
+        extractAsset();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        removeAsset();
+        super.tearDown();
+    }
+
+    protected void extractAsset() throws IOException {
+        InputStream in = getInstrumentation().getContext().getAssets().open("bindings_test.html");
+        OutputStream out = new FileOutputStream(SDCARD_BINDINGS_TEST_HTML);
+
+        byte[] buf = new byte[2048];
+        int len;
+
+        while ((len = in.read(buf)) >= 0 ) {
+            out.write(buf, 0, len);
+        }
+        out.close();
+        in.close();
+    }
+
+    protected void removeAsset(){
+        File fileToDelete = new File(SDCARD_BINDINGS_TEST_HTML);
+        fileToDelete.delete();
     }
 
     /**
@@ -183,7 +218,7 @@
         });
     }
 
-    public synchronized void testComplete() {
+    public synchronized void notifyComplete() {
         mTestDone = true;
         notify();
     }
@@ -193,7 +228,7 @@
 
         Tab tab = mActivity.getTabControl().getCurrentTab();
         WebView webView = tab.getWebView();
-        webView.loadUrl("file:///sdcard/bindings_test.html");
+        webView.loadUrl("file://" + SDCARD_BINDINGS_TEST_HTML);
         synchronized(this) {
             while(!mTestDone) {
                 try {