am 459bc29d: am 98b938b1: Actually remove the subwindow.

Merge commit '459bc29d145e754d93c79d30314cd1d162b3cc61'

* commit '459bc29d145e754d93c79d30314cd1d162b3cc61':
  Actually remove the subwindow.
diff --git a/res/anim/find_dialog_enter.xml b/res/anim/dialog_enter.xml
similarity index 82%
rename from res/anim/find_dialog_enter.xml
rename to res/anim/dialog_enter.xml
index 5e597a4..6fbcb9e 100644
--- a/res/anim/find_dialog_enter.xml
+++ b/res/anim/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/dialog_exit.xml
similarity index 82%
rename from res/anim/find_dialog_exit.xml
rename to res/anim/dialog_exit.xml
index 854abd0..9845849 100644
--- a/res/anim/find_dialog_exit.xml
+++ b/res/anim/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/drawable-hdpi/ic_btn_copy.png b/res/drawable-hdpi/ic_btn_copy.png
new file mode 100644
index 0000000..04fda7f
--- /dev/null
+++ b/res/drawable-hdpi/ic_btn_copy.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_btn_find.png b/res/drawable-hdpi/ic_btn_find.png
new file mode 100755
index 0000000..20e1fbc
--- /dev/null
+++ b/res/drawable-hdpi/ic_btn_find.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_btn_select_all.png b/res/drawable-hdpi/ic_btn_select_all.png
new file mode 100644
index 0000000..839915b
--- /dev/null
+++ b/res/drawable-hdpi/ic_btn_select_all.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_btn_share.png b/res/drawable-hdpi/ic_btn_share.png
new file mode 100644
index 0000000..44db9b1
--- /dev/null
+++ b/res/drawable-hdpi/ic_btn_share.png
Binary files differ
diff --git a/res/anim/find_dialog_enter.xml b/res/drawable/browserbarbutton.xml
similarity index 62%
copy from res/anim/find_dialog_enter.xml
copy to res/drawable/browserbarbutton.xml
index 5e597a4..35a6f48 100644
--- a/res/anim/find_dialog_enter.xml
+++ b/res/drawable/browserbarbutton.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
+<!-- Copyright (C) 2010 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.
@@ -14,8 +14,8 @@
      limitations under the License.
 -->
 
-<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" />
-</set>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true"
+            android:drawable="@drawable/button_selected" />
+    <item android:state_pressed="false" android:drawable="@drawable/clear" />
+</selector>
diff --git a/res/drawable/button_selected.png b/res/drawable/button_selected.png
new file mode 100644
index 0000000..4fd1aa3
--- /dev/null
+++ b/res/drawable/button_selected.png
Binary files differ
diff --git a/res/anim/find_dialog_enter.xml b/res/drawable/clear.xml
similarity index 62%
copy from res/anim/find_dialog_enter.xml
copy to res/drawable/clear.xml
index 5e597a4..5973f5c 100644
--- a/res/anim/find_dialog_enter.xml
+++ b/res/drawable/clear.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
+<!-- Copyright (C) 2010 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.
@@ -14,8 +14,10 @@
      limitations under the License.
 -->
 
-<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" />
-</set>
+<!-- Used by browserbarbutton to show a clear background for the non pressed
+        state -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="#00000000"/>
+    <padding android:left="9dp" android:top="9dp"
+        android:right="9dp" android:bottom="9dp" />
+</shape>
diff --git a/res/drawable/ic_arrow_left.png b/res/drawable/ic_arrow_left.png
new file mode 100644
index 0000000..58fd2ca
--- /dev/null
+++ b/res/drawable/ic_arrow_left.png
Binary files differ
diff --git a/res/drawable/ic_arrow_right.png b/res/drawable/ic_arrow_right.png
new file mode 100644
index 0000000..aaf3fde
--- /dev/null
+++ b/res/drawable/ic_arrow_right.png
Binary files differ
diff --git a/res/drawable/ic_menu.png b/res/drawable/ic_menu.png
new file mode 100644
index 0000000..520b2c3
--- /dev/null
+++ b/res/drawable/ic_menu.png
Binary files differ
diff --git a/res/drawable/ic_pages.png b/res/drawable/ic_pages.png
new file mode 100644
index 0000000..fba4651
--- /dev/null
+++ b/res/drawable/ic_pages.png
Binary files differ
diff --git a/res/drawable/ic_reload.png b/res/drawable/ic_reload.png
new file mode 100644
index 0000000..ec0c238
--- /dev/null
+++ b/res/drawable/ic_reload.png
Binary files differ
diff --git a/res/drawable/ic_star.png b/res/drawable/ic_star.png
new file mode 100644
index 0000000..20a40de
--- /dev/null
+++ b/res/drawable/ic_star.png
Binary files differ
diff --git a/res/drawable/ic_stop.png b/res/drawable/ic_stop.png
new file mode 100644
index 0000000..7ee56e9
--- /dev/null
+++ b/res/drawable/ic_stop.png
Binary files differ
diff --git a/res/drawable/progress.xml b/res/drawable/progress.xml
new file mode 100644
index 0000000..dd7c375
--- /dev/null
+++ b/res/drawable/progress.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:id="@android:id/background">
+        <shape>
+            <solid android:color="#ffffffff"/>
+        </shape>
+    </item>
+    <item android:id="@android:id/progress">
+        <clip>
+            <shape>
+                <solid android:color="#ff94b73f"/>
+            </shape>
+        </clip>
+    </item>
+
+</layer-list>
diff --git a/res/anim/find_dialog_enter.xml b/res/drawable/textfield_stroke.xml
similarity index 62%
copy from res/anim/find_dialog_enter.xml
copy to res/drawable/textfield_stroke.xml
index 5e597a4..4d4c74e 100644
--- a/res/anim/find_dialog_enter.xml
+++ b/res/drawable/textfield_stroke.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
+<!-- Copyright (C) 2010 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.
@@ -14,8 +14,9 @@
      limitations under the License.
 -->
 
-<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" />
-</set>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="#ffffffff"/>
+    <stroke android:width="3dp" android:color="#ff94b73f"/>
+    <padding android:left="9dp" android:top="9dp"
+        android:right="9dp" android:bottom="9dp" />
+</shape>
diff --git a/res/layout/bookmark_thumbnail.xml b/res/layout/bookmark_thumbnail.xml
index 1f017d0..363e632 100644
--- a/res/layout/bookmark_thumbnail.xml
+++ b/res/layout/bookmark_thumbnail.xml
@@ -35,7 +35,7 @@
     <LinearLayout android:id="@+id/holder"
         android:layout_height="match_parent"
         android:layout_width="match_parent"
-        android:orientation="horizontal"
+        android:orientation="vertical"
         android:background="#99000000"
         android:gravity="center"
         android:layout_alignBottom="@+id/thumb"
diff --git a/res/layout/browser_select.xml b/res/layout/browser_select.xml
new file mode 100644
index 0000000..b30be8d
--- /dev/null
+++ b/res/layout/browser_select.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/selectControls"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingTop="5dip"
+    android:paddingLeft="4dip"
+    android:paddingRight="4dip"
+    android:paddingBottom="1dip"
+    android:background="@android:drawable/bottom_bar">
+    <ImageButton
+        android:src="@drawable/ic_btn_copy"
+        android:id="@+id/copy"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        />
+
+    <ImageButton
+        android:src="@drawable/ic_btn_share"
+        android:id="@+id/share"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        />
+
+    <ImageButton
+        android:src="@drawable/ic_btn_select_all"
+        android:id="@+id/select_all"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        />
+
+    <ImageButton
+        android:src="@drawable/ic_btn_find"
+        android:id="@+id/find"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        />
+
+    <LinearLayout
+        android:layout_height="fill_parent"
+        android:layout_width="fill_parent"
+        android:layout_weight="1"
+        />
+
+    <ImageButton
+        android:src="@drawable/ic_btn_close_panel"
+        android:id="@+id/done"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        />
+</LinearLayout>
+
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/layout/custom_screen.xml b/res/layout/custom_screen.xml
index 90dc324..525f30c 100644
--- a/res/layout/custom_screen.xml
+++ b/res/layout/custom_screen.xml
@@ -22,6 +22,7 @@
         android:layout_height="match_parent"
     />
     <LinearLayout android:orientation="vertical"
+        android:id="@+id/vertical_layout"
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
diff --git a/res/layout/title_bar_xlarge.xml b/res/layout/title_bar_xlarge.xml
new file mode 100644
index 0000000..3070b8b
--- /dev/null
+++ b/res/layout/title_bar_xlarge.xml
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+   Copyright 2010, 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:background="#ffdddddd" >
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        android:paddingLeft="6dip"
+        android:paddingRight="6dip"
+        >
+        <ImageButton android:id="@+id/back"
+            android:src="@drawable/ic_arrow_left"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_marginRight="6dip"
+            android:background="@drawable/browserbarbutton"
+            />
+        <ImageButton android:id="@+id/forward"
+            android:src="@drawable/ic_arrow_right"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_marginRight="6dip"
+            android:background="@drawable/browserbarbutton"
+            />
+        <ImageButton android:id="@+id/star"
+            android:src="@drawable/ic_star"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_marginRight="6dip"
+            android:background="@drawable/browserbarbutton"
+            />
+
+        <LinearLayout android:id="@+id/title_bg"
+            android:background="@drawable/textfield_stroke"
+            android:layout_width="0dip"
+            android:layout_weight="1.0"
+            android:layout_height="wrap_content"
+            android:layout_marginRight="6dip"
+            android:gravity="center_vertical"
+            android:orientation="horizontal"
+            >
+                <ImageView android:id="@+id/favicon"
+                    android:layout_width="20dip"
+                    android:layout_height="20dip"
+                    android:layout_marginLeft="3dip"
+                    />
+                <ImageView android:id="@+id/lock"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="6dip"
+                    android:visibility="gone"
+                    />
+                <TextView
+                    android:id="@+id/title"
+                    android:layout_height="wrap_content"
+                    android:layout_width="0dip"
+                    android:layout_weight="1.0"
+                    android:layout_marginLeft="3dip"
+                    android:textAppearance="?android:attr/textAppearanceMedium"
+                    android:textColor="@color/black"
+                    android:gravity="center_vertical"
+                    android:singleLine="true"
+                    android:ellipsize="end"
+                />
+        </LinearLayout>
+        <ImageButton android:id="@+id/stop"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_marginRight="6dip"
+            android:src="@drawable/ic_stop"
+            android:background="@drawable/browserbarbutton"
+        />
+        <ImageButton android:id="@+id/menu"
+            android:src="@drawable/ic_menu"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_marginRight="6dip"
+            android:background="@drawable/browserbarbutton"
+            />
+        <ImageButton
+            android:id="@+id/all_btn"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:scaleType="center"
+            android:background="@drawable/browserbarbutton"
+            android:src="@drawable/ic_pages"
+        />
+    </LinearLayout>
+
+    <!-- Should show translucent over the webpage -->
+    <ProgressBar android:id="@+id/progress_horizontal"
+        style="?android:attr/progressBarStyleHorizontal"
+        android:layout_width="match_parent"
+        android:layout_height="14dip"
+        android:max="100"
+        />
+
+</LinearLayout>
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..e752711 100644
--- a/src/com/android/browser/BrowserActivity.java
+++ b/src/com/android/browser/BrowserActivity.java
@@ -87,6 +87,7 @@
 import android.view.WindowManager;
 import android.view.ContextMenu.ContextMenuInfo;
 import android.view.MenuItem.OnMenuItemClickListener;
+import android.view.accessibility.AccessibilityManager;
 import android.webkit.CookieManager;
 import android.webkit.CookieSyncManager;
 import android.webkit.DownloadListener;
@@ -171,6 +172,8 @@
      */
     private FrameLayout mBrowserFrameLayout;
 
+    private boolean mXLargeScreenSize;
+
     @Override
     public void onCreate(Bundle icicle) {
         if (LOGV_ENABLED) {
@@ -186,7 +189,11 @@
             BitmapFactory.setDefaultConfig(Bitmap.Config.ARGB_8888);
         }
 
-        setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
+        if (AccessibilityManager.getInstance(this).isEnabled()) {
+            setDefaultKeyMode(DEFAULT_KEYS_DISABLE);
+        } else {
+            setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
+        }
 
         mResolver = getContentResolver();
 
@@ -213,10 +220,24 @@
         mCustomViewContainer = (FrameLayout) mBrowserFrameLayout
                 .findViewById(R.id.fullscreen_custom_content);
         frameLayout.addView(mBrowserFrameLayout, COVER_SCREEN_PARAMS);
-        mTitleBar = new TitleBar(this);
-        // mTitleBar will be always shown in the fully loaded mode
-        mTitleBar.setProgress(100);
-        mFakeTitleBar = new TitleBar(this);
+        mXLargeScreenSize = (getResources().getConfiguration().screenLayout
+                & Configuration.SCREENLAYOUT_SIZE_MASK)
+                == Configuration.SCREENLAYOUT_SIZE_XLARGE;
+        if (mXLargeScreenSize) {
+            mTitleBar = new TitleBarXLarge(this);
+            LinearLayout layout = (LinearLayout) mBrowserFrameLayout.
+                    findViewById(R.id.vertical_layout);
+            layout.addView(mTitleBar, 0, new LinearLayout.LayoutParams(
+                    ViewGroup.LayoutParams.MATCH_PARENT,
+                    ViewGroup.LayoutParams.WRAP_CONTENT));
+        } else {
+            mTitleBar = new TitleBar(this);
+            // mTitleBar will be always be shown in the fully loaded mode on
+            // phone
+            mTitleBar.setProgress(100);
+            // Fake title bar is not needed in xlarge layout
+            mFakeTitleBar = new TitleBar(this);
+        }
 
         // Create the tab control and our initial tab
         mTabControl = new TabControl(this);
@@ -305,9 +326,7 @@
                     }
                     if (permissionOk) {
                         PluginManager.getInstance(BrowserActivity.this)
-                                .refreshPlugins(
-                                        Intent.ACTION_PACKAGE_ADDED
-                                                .equals(action));
+                                .refreshPlugins(true);
                     }
                 }
             }
@@ -697,17 +716,21 @@
     }
     /* package */ void showVoiceTitleBar(String title) {
         mTitleBar.setInVoiceMode(true);
-        mFakeTitleBar.setInVoiceMode(true);
-
         mTitleBar.setDisplayTitle(title);
-        mFakeTitleBar.setDisplayTitle(title);
+
+        if (!mXLargeScreenSize) {
+            mFakeTitleBar.setInVoiceMode(true);
+            mFakeTitleBar.setDisplayTitle(title);
+        }
     }
     /* package */ void revertVoiceTitleBar() {
         mTitleBar.setInVoiceMode(false);
-        mFakeTitleBar.setInVoiceMode(false);
-
         mTitleBar.setDisplayTitle(mUrl);
-        mFakeTitleBar.setDisplayTitle(mUrl);
+
+        if (!mXLargeScreenSize) {
+            mFakeTitleBar.setInVoiceMode(false);
+            mFakeTitleBar.setDisplayTitle(mUrl);
+        }
     }
     /* package */ static String fixUrl(String inUrl) {
         // FIXME: Converting the url to lower case
@@ -827,6 +850,7 @@
     }
 
     private void showFakeTitleBar() {
+        if (mXLargeScreenSize) return;
         if (mFakeTitleBar.getParent() == null && mActiveTabsPage == null
                 && !mActivityInPause) {
             WebView mainView = mTabControl.getCurrentWebView();
@@ -834,6 +858,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 (dialogIsUp()) {
+                // Do not show the fake title bar, which would cover up the
+                // find or select dialog.
+                return;
+            }
 
             WindowManager manager
                     = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
@@ -868,7 +899,7 @@
     }
 
     private void hideFakeTitleBar() {
-        if (mFakeTitleBar.getParent() == null) return;
+        if (mXLargeScreenSize || mFakeTitleBar.getParent() == null) return;
         WindowManager.LayoutParams params = (WindowManager.LayoutParams)
                 mFakeTitleBar.getLayoutParams();
         WebView mainView = mTabControl.getCurrentWebView();
@@ -1145,7 +1176,6 @@
                 break;
             // -- Browser context menu
             case R.id.open_context_menu_id:
-            case R.id.open_newtab_context_menu_id:
             case R.id.bookmark_context_menu_id:
             case R.id.save_link_context_menu_id:
             case R.id.share_link_context_menu_id:
@@ -1263,6 +1293,7 @@
      */
     /* package */ void removeActiveTabPage(boolean needToAttach) {
         mContentView.removeView(mActiveTabsPage);
+        mTitleBar.setVisibility(View.VISIBLE);
         mActiveTabsPage = null;
         mMenuState = R.id.MAIN_MENU;
         if (needToAttach) {
@@ -1271,6 +1302,22 @@
         getTopWindow().requestFocus();
     }
 
+    private WebView showDialog(WebDialog dialog) {
+        // Need to do something special for Tablet
+        Tab tab = mTabControl.getCurrentTab();
+        if (tab.getSubWebView() == null) {
+            // If the find or select is being performed on the main webview,
+            // remove the embedded title bar.
+            WebView mainView = tab.getWebView();
+            if (mainView != null) {
+                mainView.setEmbeddedTitleBar(null);
+            }
+        }
+        hideFakeTitleBar();
+        mMenuState = EMPTY_MENU;
+        return tab.showDialog(dialog);
+    }
+
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         if (!mCanChord) {
@@ -1305,6 +1352,7 @@
             case R.id.active_tabs_menu_id:
                 mActiveTabsPage = new ActiveTabsPage(this, mTabControl);
                 removeTabFromContentView(mTabControl.getCurrentTab());
+                mTitleBar.setVisibility(View.GONE);
                 hideFakeTitleBar();
                 mContentView.addView(mActiveTabsPage, COVER_SCREEN_PARAMS);
                 mActiveTabsPage.requestFocus();
@@ -1312,14 +1360,7 @@
                 break;
 
             case R.id.add_bookmark_menu_id:
-                Intent i = new Intent(BrowserActivity.this,
-                        AddBookmarkPage.class);
-                WebView w = getTopWindow();
-                i.putExtra("url", w.getUrl());
-                i.putExtra("title", w.getTitle());
-                i.putExtra("touch_icon_url", w.getTouchIconUrl());
-                i.putExtra("thumbnail", createScreenshot(w));
-                startActivity(i);
+                bookmarkCurrentPage();
                 break;
 
             case R.id.stop_reload_menu_id:
@@ -1364,18 +1405,13 @@
                 break;
 
             case R.id.find_menu_id:
-                if (null == mFindDialog) {
-                    mFindDialog = new FindDialog(this);
-                }
-                mFindDialog.setWebView(getTopWindow());
-                mFindDialog.show();
-                getTopWindow().setFindIsUp(true);
-                mMenuState = EMPTY_MENU;
+                showFindDialog();
                 break;
 
             case R.id.select_text_id:
-                getTopWindow().emulateShiftHeld();
+                showSelectDialog();
                 break;
+
             case R.id.page_info_menu_id:
                 showPageInfo(mTabControl.getCurrentTab(), false);
                 break;
@@ -1450,8 +1486,72 @@
         return true;
     }
 
-    public void closeFind() {
+    /* package */ void bookmarkCurrentPage() {
+        Intent i = new Intent(BrowserActivity.this,
+                AddBookmarkPage.class);
+        WebView w = getTopWindow();
+        i.putExtra("url", w.getUrl());
+        i.putExtra("title", w.getTitle());
+        i.putExtra("touch_icon_url", w.getTouchIconUrl());
+        i.putExtra("thumbnail", createScreenshot(w));
+        startActivity(i);
+    }
+
+    private boolean dialogIsUp() {
+        return null != mFindDialog && mFindDialog.isVisible() ||
+            null != mSelectDialog && mSelectDialog.isVisible();
+    }
+
+    private boolean closeDialog(WebDialog dialog) {
+        if (null == dialog || !dialog.isVisible()) return false;
+        Tab currentTab = mTabControl.getCurrentTab();
+        currentTab.closeDialog(dialog);
+        dialog.dismiss();
+        return true;
+    }
+
+    /*
+     * Remove the find dialog or select dialog.
+     */
+    public void closeDialogs() {
+        if (!(closeDialog(mFindDialog) || closeDialog(mSelectDialog))) return;
+        if (!mXLargeScreenSize) {
+            // If the Find was being performed in the main WebView, replace the
+            // embedded title bar.
+            Tab currentTab = mTabControl.getCurrentTab();
+            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 or select dialog.  Now that the dialog has been removed,
+            // show the fake title bar once again.
+            showFakeTitleBar();
+        }
+    }
+
+    public void showFindDialog() {
+        if (null == mFindDialog) {
+            mFindDialog = new FindDialog(this);
+        }
+        showDialog(mFindDialog).setFindIsUp(true);
+    }
+
+    public void setFindDialogText(String text) {
+        mFindDialog.setText(text);
+    }
+
+    public void showSelectDialog() {
+        if (null == mSelectDialog) {
+            mSelectDialog = new SelectDialog(this);
+        }
+        showDialog(mSelectDialog).setUpSelect();
+        mSelectDialog.hideSoftInput();
     }
 
     @Override
@@ -1524,7 +1624,7 @@
     @Override
     public void onCreateContextMenu(ContextMenu menu, View v,
             ContextMenuInfo menuInfo) {
-        if (v instanceof TitleBar) {
+        if (v instanceof TitleBarBase) {
             return;
         }
         WebView webview = (WebView) v;
@@ -1551,7 +1651,7 @@
         inflater.inflate(R.menu.browsercontext, menu);
 
         // Show the correct menu group
-        String extra = result.getExtra();
+        final String extra = result.getExtra();
         menu.setGroupVisible(R.id.PHONE_MENU,
                 type == WebView.HitTestResult.PHONE_TYPE);
         menu.setGroupVisible(R.id.EMAIL_MENU,
@@ -1608,8 +1708,23 @@
                 titleView.setText(extra);
                 menu.setHeaderView(titleView);
                 // decide whether to show the open link in new tab option
-                menu.findItem(R.id.open_newtab_context_menu_id).setVisible(
-                        mTabControl.canCreateNewTab());
+                boolean showNewTab = mTabControl.canCreateNewTab();
+                MenuItem newTabItem
+                        = menu.findItem(R.id.open_newtab_context_menu_id);
+                newTabItem.setVisible(showNewTab);
+                if (showNewTab) {
+                    newTabItem.setOnMenuItemClickListener(
+                            new MenuItem.OnMenuItemClickListener() {
+                                public boolean onMenuItemClick(MenuItem item) {
+                                    final Tab parent = mTabControl.getCurrentTab();
+                                    final Tab newTab = openTab(extra);
+                                    if (newTab != parent) {
+                                        parent.addChildTab(newTab);
+                                    }
+                                    return true;
+                                }
+                            });
+                }
                 menu.findItem(R.id.bookmark_context_menu_id).setVisible(
                         Bookmarks.urlHasAcceptableScheme(extra));
                 PackageManager pm = getPackageManager();
@@ -1660,8 +1775,10 @@
                                                   ViewGroup.LayoutParams.WRAP_CONTENT));
         }
 
-        WebView view = t.getWebView();
-        view.setEmbeddedTitleBar(mTitleBar);
+        if (!mXLargeScreenSize){
+            WebView view = t.getWebView();
+            view.setEmbeddedTitleBar(mTitleBar);
+        }
         if (t.isInVoiceSearchMode()) {
             showVoiceTitleBar(t.getVoiceDisplayTitle());
         } else {
@@ -1687,9 +1804,11 @@
             mErrorConsoleContainer.removeView(errorConsole);
         }
 
-        WebView view = t.getWebView();
-        if (view != null) {
-            view.setEmbeddedTitleBar(null);
+        if (!mXLargeScreenSize) {
+            WebView view = t.getWebView();
+            if (view != null) {
+                view.setEmbeddedTitleBar(null);
+            }
         }
     }
 
@@ -1919,7 +2038,9 @@
         // If we are in voice search mode, the title has already been set.
         if (mTabControl.getCurrentTab().isInVoiceSearchMode()) return;
         mTitleBar.setDisplayTitle(url);
-        mFakeTitleBar.setDisplayTitle(url);
+        if (!mXLargeScreenSize) {
+            mFakeTitleBar.setDisplayTitle(url);
+        }
     }
 
     /**
@@ -1962,7 +2083,9 @@
     // Set the favicon in the title bar.
     void setFavicon(Bitmap icon) {
         mTitleBar.setFavicon(icon);
-        mFakeTitleBar.setFavicon(icon);
+        if (!mXLargeScreenSize) {
+            mFakeTitleBar.setFavicon(icon);
+        }
     }
 
     /**
@@ -2192,13 +2315,6 @@
                         case R.id.view_image_context_menu_id:
                             loadUrlFromContext(getTopWindow(), url);
                             break;
-                        case R.id.open_newtab_context_menu_id:
-                            final Tab parent = mTabControl.getCurrentTab();
-                            final Tab newTab = openTab(url);
-                            if (newTab != parent) {
-                                parent.addChildTab(newTab);
-                            }
-                            break;
                         case R.id.bookmark_context_menu_id:
                             Intent intent = new Intent(BrowserActivity.this,
                                     AddBookmarkPage.class);
@@ -2207,41 +2323,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 +2545,7 @@
         onProgressChanged(view, INITIAL_PROGRESS);
         mDidStopLoad = false;
         if (!mIsNetworkUp) createAndShowNetworkDialog();
-
+        closeDialogs();
         if (mSettings.isTracing()) {
             String host;
             try {
@@ -2642,7 +2725,14 @@
     // -------------------------------------------------------------------------
 
     void onProgressChanged(WebView view, int newProgress) {
-        mFakeTitleBar.setProgress(newProgress);
+        if (mXLargeScreenSize) {
+            mTitleBar.setProgress(newProgress);
+        } else {
+            // On the phone, the fake title bar will always cover up the
+            // regular title bar (or the regular one is offscreen), so only the
+            // fake title bar needs to change its progress
+            mFakeTitleBar.setProgress(newProgress);
+        }
 
         if (newProgress == 100) {
             // onProgressChanged() may continue to be called after the main
@@ -2743,15 +2833,85 @@
      * The Object used to inform the WebView of the file to upload.
      */
     private ValueCallback<Uri> mUploadMessage;
+    private String mCameraFilePath;
 
-    void openFileChooser(ValueCallback<Uri> uploadMsg) {
+    void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
+
+        final String imageMimeType = "image/*";
+        final String imageSourceKey = "source";
+        final String imageSourceValueCamera = "camera";
+        final String imageSourceValueGallery = "gallery";
+
+        // image source can be 'gallery' or 'camera'.
+        String imageSource = "";
+
+        // We add the camera intent if there was no accept type (or '*/*') or 'image/*'.
+        boolean addCameraIntent = true;
+
         if (mUploadMessage != null) return;
         mUploadMessage = uploadMsg;
+
+        // Parse the accept type.
+        String params[] = acceptType.split(";");
+        String mimeType = params[0];
+
+        for (String p : params) {
+            String[] keyValue = p.split("=");
+            if (keyValue.length == 2) {
+                // Process key=value parameters.
+                if (imageSourceKey.equals(keyValue[0])) {
+                    imageSource = keyValue[1];
+                }
+            }
+        }
+
+        // This intent will display the standard OPENABLE file picker.
         Intent i = new Intent(Intent.ACTION_GET_CONTENT);
         i.addCategory(Intent.CATEGORY_OPENABLE);
-        i.setType("*/*");
-        BrowserActivity.this.startActivityForResult(Intent.createChooser(i,
-                getString(R.string.choose_upload)), FILE_SELECTED);
+
+        // Create an intent to add to the standard file picker that will
+        // capture an image from the camera. We'll combine this intent with
+        // the standard OPENABLE picker unless the web developer specifically
+        // requested the camera or gallery be opened by passing a parameter
+        // in the accept type.
+        Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
+        File externalDataDir = Environment.getExternalStoragePublicDirectory(
+                Environment.DIRECTORY_DCIM);
+        File cameraDataDir = new File(externalDataDir.getAbsolutePath() +
+                File.separator + "browser-photos");
+        cameraDataDir.mkdirs();
+        mCameraFilePath = cameraDataDir.getAbsolutePath() + File.separator +
+                System.currentTimeMillis() + ".jpg";
+        cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(mCameraFilePath)));
+
+        if (mimeType.equals(imageMimeType)) {
+            i.setType(imageMimeType);
+            if (imageSource.equals(imageSourceValueCamera)) {
+                // Specified 'image/*' and requested the camera, so go ahead and launch the camera
+                // directly.
+                BrowserActivity.this.startActivityForResult(cameraIntent, FILE_SELECTED);
+                return;
+            } else if (imageSource.equals(imageSourceValueGallery)) {
+                // Specified gallery as the source, so don't want to consider the camera.
+                addCameraIntent = false;
+            }
+        } else {
+            i.setType("*/*");
+        }
+
+        // Combine the chooser and the extra choices (like camera)
+        Intent chooser = new Intent(Intent.ACTION_CHOOSER);
+        chooser.putExtra(Intent.EXTRA_INTENT, i);
+
+        if (addCameraIntent) {
+            // Add the camera Intent
+            Intent[] choices = new Intent[1];
+            choices[0] = cameraIntent;
+            chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, choices);
+        }
+
+        chooser.putExtra(Intent.EXTRA_TITLE, getString(R.string.choose_upload));
+        BrowserActivity.this.startActivityForResult(chooser, FILE_SELECTED);
     }
 
     // -------------------------------------------------------------------------
@@ -2952,7 +3112,9 @@
             d = mMixLockIcon;
         }
         mTitleBar.setLock(d);
-        mFakeTitleBar.setLock(d);
+        if (!mXLargeScreenSize) {
+            mFakeTitleBar.setLock(d);
+        }
     }
 
     /**
@@ -3468,8 +3630,26 @@
                 if (null == mUploadMessage) break;
                 Uri result = intent == null || resultCode != RESULT_OK ? null
                         : intent.getData();
+
+                // As we ask the camera to save the result of the user taking
+                // a picture, the camera application does not return anything other
+                // than RESULT_OK. So we need to check whether the file we expected
+                // was written to disk in the in the case that we
+                // did not get an intent returned but did get a RESULT_OK. If it was,
+                // we assume that this result has came back from the camera.
+                if (result == null && intent == null && resultCode == RESULT_OK) {
+                    File cameraFile = new File(mCameraFilePath);
+                    if (cameraFile.exists()) {
+                        result = Uri.fromFile(cameraFile);
+                        // Broadcast to the media scanner that we have a new photo
+                        // so it will be added into the gallery for the user.
+                        sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, result));
+                    }
+                }
+
                 mUploadMessage.onReceiveValue(result);
                 mUploadMessage = null;
+                mCameraFilePath = null;
                 break;
             default:
                 break;
@@ -3770,6 +3950,7 @@
     private Menu mMenu;
 
     private FindDialog mFindDialog;
+    private SelectDialog mSelectDialog;
     // Used to prevent chording to result in firing two shortcuts immediately
     // one after another.  Fixes bug 1211714.
     boolean mCanChord;
@@ -3883,7 +4064,7 @@
 
     private Toast mStopToast;
 
-    private TitleBar mTitleBar;
+    private TitleBarBase mTitleBar;
 
     private LinearLayout mErrorConsoleContainer = null;
     private boolean mShouldShowErrorConsole = false;
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/BrowserProvider.java b/src/com/android/browser/BrowserProvider.java
index bf1f9d5..1eec52b 100644
--- a/src/com/android/browser/BrowserProvider.java
+++ b/src/com/android/browser/BrowserProvider.java
@@ -465,7 +465,7 @@
         public MySuggestionCursor(Cursor hc, Cursor sc, String string) {
             mHistoryCursor = hc;
             mSuggestCursor = sc;
-            mHistoryCount = hc.getCount();
+            mHistoryCount = hc != null ? hc.getCount() : 0;
             mSuggestionCount = sc != null ? sc.getCount() : 0;
             if (mSuggestionCount > (MAX_SUGGESTION_LONG_ENTRIES - mHistoryCount)) {
                 mSuggestionCount = MAX_SUGGESTION_LONG_ENTRIES - mHistoryCount;
@@ -846,8 +846,7 @@
             String suggestSelection;
             String [] myArgs;
             if (selectionArgs[0] == null || selectionArgs[0].equals("")) {
-                suggestSelection = null;
-                myArgs = null;
+                return new MySuggestionCursor(null, null, "");
             } else {
                 String like = selectionArgs[0] + "%";
                 if (selectionArgs[0].startsWith("http")
diff --git a/src/com/android/browser/BrowserSettings.java b/src/com/android/browser/BrowserSettings.java
index 3d5ca03..91b7765 100644
--- a/src/com/android/browser/BrowserSettings.java
+++ b/src/com/android/browser/BrowserSettings.java
@@ -207,6 +207,9 @@
             s.setNeedInitialFocus(false);
             // Browser supports multiple windows
             s.setSupportMultipleWindows(true);
+            // enable smooth transition for better performance during panning or
+            // zooming
+            s.setEnableSmoothTransition(true);
 
             // HTML5 API flags
             s.setAppCacheEnabled(b.appCacheEnabled);
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..9d0ac4b 100644
--- a/src/com/android/browser/FindDialog.java
+++ b/src/com/android/browser/FindDialog.java
@@ -16,27 +16,25 @@
 
 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 {
-    private WebView         mWebView;
+/* package */ class FindDialog extends WebDialog implements TextWatcher {
     private TextView        mMatches;
-    private BrowserActivity mBrowserActivity;
     
     // Views with which the user can interact.
     private EditText        mEditText;
@@ -44,39 +42,30 @@
     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();
         }
     };
 
-    private View.OnClickListener mFindCancelListener  = 
-            new View.OnClickListener() {
-        public void onClick(View v) {
-            dismiss();
-        }
-    };
-    
-    private View.OnClickListener mFindPreviousListener  = 
+    private View.OnClickListener mFindPreviousListener  =
             new View.OnClickListener() {
         public void onClick(View v) {
             if (mWebView == null) {
                 throw new AssertionError("No WebView for FindDialog::onClick");
             }
             mWebView.findNext(false);
+            updateMatchesString();
             hideSoftInput();
         }
     };
 
-    /*
-     * Remove the soft keyboard from the screen.
-     */
-    private void hideSoftInput() {
-        InputMethodManager imm = (InputMethodManager)
-                mBrowserActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
-        imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
-    }
-
     private void disableButtons() {
         mPrevButton.setEnabled(false);
         mNextButton.setEnabled(false);
@@ -84,28 +73,13 @@
         mNextButton.setFocusable(false);
     }
 
-    /* package */ void setWebView(WebView webview) {
-        mWebView = webview;
-    }
-
     /* package */ FindDialog(BrowserActivity context) {
-        super(context, R.style.FindDialogTheme);
-        mBrowserActivity = context;
-        setCanceledOnTouchOutside(true);
-    }
+        super(context);
 
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
+        LayoutInflater factory = LayoutInflater.from(context);
+        factory.inflate(R.layout.browser_find, this);
 
-        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);
-
+        addCancel();
         mEditText = (EditText) findViewById(R.id.edit);
         
         View button = findViewById(R.id.next);
@@ -116,29 +90,59 @@
         button.setOnClickListener(mFindPreviousListener);
         mPrevButton = button;
         
-        button = findViewById(R.id.done);
-        button.setOnClickListener(mFindCancelListener);
-        
         mMatches = (TextView) findViewById(R.id.matches);
         mMatchesView = findViewById(R.id.matches_view);
         disableButtons();
-        theWindow.setSoftInputMode(
-                WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
+
     }
-    
+
+    /**
+     * Called by BrowserActivity.closeDialog.  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();
+        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.closeDialogs();
+                    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 +152,26 @@
             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();
+        InputMethodManager imm = (InputMethodManager)
+                mBrowserActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
+        imm.showSoftInput(mEditText, 0);
     }
     
     // TextWatcher methods
@@ -173,9 +185,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 +200,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 +221,21 @@
     }
 
     private void setMatchesFound(int found) {
+        mNumberOfMatches = found;
+        updateMatchesString();
+    }
+
+    public void setText(String text) {
+        mEditText.setText(text);
+        findAll();
+    }
+
+    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/SelectDialog.java b/src/com/android/browser/SelectDialog.java
new file mode 100644
index 0000000..461127a
--- /dev/null
+++ b/src/com/android/browser/SelectDialog.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+package com.android.browser;
+
+import android.provider.Browser;
+import android.view.LayoutInflater;
+import android.view.View;
+
+/* package */ class SelectDialog extends WebDialog {
+    private View mCopyButton;
+    private View mSelectAllButton;
+    private View mShareButton;
+    private View mFindButton;
+
+    SelectDialog(BrowserActivity context) {
+        super(context);
+        LayoutInflater factory = LayoutInflater.from(context);
+        factory.inflate(R.layout.browser_select, this);
+        addCancel();
+
+        mCopyButton = findViewById(R.id.copy);
+        mCopyButton.setOnClickListener(mCopyListener);
+        mSelectAllButton = findViewById(R.id.select_all);
+        mSelectAllButton.setOnClickListener(mSelectAllListener);
+        mShareButton = findViewById(R.id.share);
+        mShareButton.setOnClickListener(mShareListener);
+        mFindButton = findViewById(R.id.find);
+        mFindButton.setOnClickListener(mFindListener);
+    }
+
+    private View.OnClickListener mCopyListener = new View.OnClickListener() {
+        public void onClick(View v) {
+            mWebView.copySelection();
+            mBrowserActivity.closeDialogs();
+        }
+    };
+
+    private View.OnClickListener mSelectAllListener = new View.OnClickListener() {
+        public void onClick(View v) {
+            mWebView.selectAll();
+        }
+    };
+
+    private View.OnClickListener mShareListener = new View.OnClickListener() {
+        public void onClick(View v) {
+            String selection = mWebView.getSelection();
+            Browser.sendString(mBrowserActivity, selection);
+            mBrowserActivity.closeDialogs();
+        }
+    };
+
+    private View.OnClickListener mFindListener = new View.OnClickListener() {
+        public void onClick(View v) {
+            String selection = mWebView.getSelection();
+            mBrowserActivity.closeDialogs();
+            mBrowserActivity.showFindDialog();
+            mBrowserActivity.setFindDialogText(selection);
+        }
+    };
+
+    /**
+     * Called by BrowserActivity.closeDialog.  Start the animation to hide
+     * the dialog, and inform the WebView that the dialog is being dismissed.
+     */
+    @Override
+    public void dismiss() {
+        super.dismiss();
+        mWebView.notifySelectDialogDismissed();
+    }
+
+}
diff --git a/src/com/android/browser/Tab.java b/src/com/android/browser/Tab.java
index 07310bf..9994945 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
@@ -1029,6 +1029,16 @@
         }
 
         @Override
+        public void onSelectionDone() {
+            if (mInForeground) mActivity.closeDialogs();
+        }
+
+        @Override
+        public void onSelectionStart() {
+            if (mInForeground) mActivity.showSelectDialog();
+        }
+
+        @Override
         public void onShowCustomView(View view,
                 WebChromeClient.CustomViewCallback callback) {
             if (mInForeground) mActivity.onShowCustomView(view, callback);
@@ -1173,9 +1183,9 @@
         }
 
         @Override
-        public void openFileChooser(ValueCallback<Uri> uploadMsg) {
+        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
             if (mInForeground) {
-                mActivity.openFileChooser(uploadMsg);
+                mActivity.openFileChooser(uploadMsg, acceptType);
             } else {
                 uploadMsg.onReceiveValue(null);
             }
@@ -1208,9 +1218,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 or select dialog.
+            mBrowserActivity.closeDialogs();
         }
         @Override
         public void doUpdateVisitedHistory(WebView view, String url,
@@ -1300,7 +1319,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 +1430,7 @@
      */
     boolean createSubWindow() {
         if (mSubView == null) {
+            mActivity.closeDialogs();
             mSubViewContainer = mInflateService.inflate(
                     R.layout.browser_subwindow, null);
             mSubView = (WebView) mSubViewContainer.findViewById(R.id.webview);
@@ -1419,7 +1439,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 +1478,7 @@
      */
     void dismissSubWindow() {
         if (mSubView != null) {
+            mActivity.closeDialogs();
             BrowserSettings.getInstance().deleteObserver(
                     mSubView.getSettings());
             mSubView.destroy();
@@ -1481,6 +1503,7 @@
     void removeSubWindow(ViewGroup content) {
         if (mSubView != null) {
             content.removeView(mSubViewContainer);
+            mActivity.closeDialogs();
         }
     }
 
@@ -1539,6 +1562,7 @@
                 (FrameLayout) mContainer.findViewById(R.id.webview_wrapper);
         wrapper.removeView(mMainView);
         content.removeView(mContainer);
+        mActivity.closeDialogs();
         removeSubWindow(content);
     }
 
@@ -1812,6 +1836,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 +1847,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 +1963,36 @@
         }
         return true;
     }
+
+    /*
+     * Opens the find and select text dialogs.  Called by BrowserActivity.
+     */
+    WebView showDialog(WebDialog 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);
+        return view;
+    }
+
+    /*
+     * Close the find or select dialog. Called by BrowserActivity.closeDialog.
+     */
+    void closeDialog(WebDialog 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/src/com/android/browser/TitleBar.java b/src/com/android/browser/TitleBar.java
index dc4979b..4e76334 100644
--- a/src/com/android/browser/TitleBar.java
+++ b/src/com/android/browser/TitleBar.java
@@ -21,14 +21,8 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Color;
-import android.graphics.Rect;
 import android.graphics.drawable.Animatable;
-import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
-import android.graphics.drawable.PaintDrawable;
 import android.os.Handler;
 import android.os.Message;
 import android.speech.RecognizerIntent;
@@ -45,7 +39,6 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.widget.ImageView;
-import android.widget.LinearLayout;
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
@@ -55,21 +48,16 @@
  * This class represents a title bar for a particular "tab" or "window" in the
  * browser.
  */
-public class TitleBar extends LinearLayout {
+public class TitleBar extends TitleBarBase {
     private TextView        mTitle;
-    private Drawable        mCloseDrawable;
     private ImageView       mRtButton;
     private Drawable        mCircularProgress;
     private ProgressBar     mHorizontalProgress;
-    private ImageView       mFavicon;
-    private ImageView       mLockIcon;
     private ImageView       mStopButton;
     private Drawable        mBookmarkDrawable;
     private Drawable        mVoiceDrawable;
     private boolean         mInLoad;
     private BrowserActivity mBrowserActivity;
-    private Drawable        mGenericFavicon;
-    private int             mIconDimension;
     private View            mTitleBg;
     private MyHandler       mHandler;
     private Intent          mVoiceSearchIntent;
@@ -84,7 +72,7 @@
     private static int LONG_PRESS = 1;
 
     public TitleBar(BrowserActivity context) {
-        super(context, null);
+        super(context);
         mHandler = new MyHandler();
         LayoutInflater factory = LayoutInflater.from(context);
         factory.inflate(R.layout.title_bar, this);
@@ -107,13 +95,11 @@
                 TypedValue.COMPLEX_UNIT_DIP, 8f, metrics);
         mRightMargin = (int) TypedValue.applyDimension(
                 TypedValue.COMPLEX_UNIT_DIP, 6f, metrics);
-        mIconDimension = (int) TypedValue.applyDimension(
+        int iconDimension = (int) TypedValue.applyDimension(
                 TypedValue.COMPLEX_UNIT_DIP, 20f, metrics);
-        mCircularProgress.setBounds(0, 0, mIconDimension, mIconDimension);
+        mCircularProgress.setBounds(0, 0, iconDimension, iconDimension);
         mHorizontalProgress = (ProgressBar) findViewById(
                 R.id.progress_horizontal);
-        mGenericFavicon = context.getResources().getDrawable(
-                R.drawable.app_web_browser_sm);
         mVoiceSearchIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
         mVoiceSearchIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
                 RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);
@@ -248,25 +234,6 @@
     }
 
     /**
-     * Set a new Bitmap for the Favicon.
-     */
-    /* package */ void setFavicon(Bitmap icon) {
-        Drawable[] array = new Drawable[3];
-        array[0] = new PaintDrawable(Color.BLACK);
-        PaintDrawable p = new PaintDrawable(Color.WHITE);
-        array[1] = p;
-        if (icon == null) {
-            array[2] = mGenericFavicon;
-        } else {
-            array[2] = new BitmapDrawable(icon);
-        }
-        LayerDrawable d = new LayerDrawable(array);
-        d.setLayerInset(1, 1, 1, 1, 1);
-        d.setLayerInset(2, 2, 2, 2, 2);
-        mFavicon.setImageDrawable(d);
-    }
-
-    /**
      * Change the TitleBar to or from voice mode.  If there is no package to
      * handle voice search, the TitleBar cannot be set to voice mode.
      */
@@ -302,18 +269,6 @@
     }
 
     /**
-     * Set the Drawable for the lock icon, or null to hide it.
-     */
-    /* package */ void setLock(Drawable d) {
-        if (null == d) {
-            mLockIcon.setVisibility(View.GONE);
-        } else {
-            mLockIcon.setImageDrawable(d);
-            mLockIcon.setVisibility(View.VISIBLE);
-        }
-    }
-
-    /**
      * Update the progress, from 0 to 100.
      */
     /* package */ void setProgress(int newProgress) {
@@ -374,11 +329,4 @@
             }
         }
     }
-
-    /* package */ void setToTabPicker() {
-        mTitle.setText(R.string.tab_picker_title);
-        setFavicon(null);
-        setLock(null);
-        mHorizontalProgress.setVisibility(View.GONE);
-    }
 }
diff --git a/src/com/android/browser/TitleBarBase.java b/src/com/android/browser/TitleBarBase.java
new file mode 100644
index 0000000..3d234e8
--- /dev/null
+++ b/src/com/android/browser/TitleBarBase.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+package com.android.browser;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+import android.graphics.drawable.PaintDrawable;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+/**
+ * Base class for a title bar used by the browser.
+ */
+public class TitleBarBase extends LinearLayout {
+    // These need to be set by the subclass.
+    protected ImageView mFavicon;
+    protected ImageView mLockIcon;
+
+    private Drawable mGenericFavicon;
+
+    public TitleBarBase(Context context) {
+        super(context, null);
+        mGenericFavicon = context.getResources().getDrawable(
+                R.drawable.app_web_browser_sm);
+    }
+
+    /* package */ void setProgress(int newProgress) {}
+    /* package */ void setDisplayTitle(String title) {}
+
+    /* package */ void setLock(Drawable d) {
+        assert mLockIcon != null;
+        if (null == d) {
+            mLockIcon.setVisibility(View.GONE);
+        } else {
+            mLockIcon.setImageDrawable(d);
+            mLockIcon.setVisibility(View.VISIBLE);
+        }
+    }
+
+    /* package */ void setFavicon(Bitmap icon) {
+        assert mFavicon != null;
+        Drawable[] array = new Drawable[3];
+        array[0] = new PaintDrawable(Color.BLACK);
+        PaintDrawable p = new PaintDrawable(Color.WHITE);
+        array[1] = p;
+        if (icon == null) {
+            array[2] = mGenericFavicon;
+        } else {
+            array[2] = new BitmapDrawable(icon);
+        }
+        LayerDrawable d = new LayerDrawable(array);
+        d.setLayerInset(1, 1, 1, 1, 1);
+        d.setLayerInset(2, 2, 2, 2, 2);
+        mFavicon.setImageDrawable(d);
+    }
+
+    /* package */ void setInVoiceMode(boolean inVoiceMode) {}
+
+}
diff --git a/src/com/android/browser/TitleBarXLarge.java b/src/com/android/browser/TitleBarXLarge.java
new file mode 100644
index 0000000..76f57d0
--- /dev/null
+++ b/src/com/android/browser/TitleBarXLarge.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+package com.android.browser;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.Animatable;
+import android.graphics.drawable.Drawable;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.ContextMenu;
+import android.view.LayoutInflater;
+import android.view.MenuInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import com.android.common.speech.LoggingEvents;
+
+/**
+ * This class represents a title bar for a particular "tab" or "window" in the
+ * browser.
+ */
+public class TitleBarXLarge extends TitleBarBase {
+    private Drawable        mCircularProgress;
+    private ProgressBar     mHorizontalProgress;
+    private Drawable        mStopDrawable;
+    private Drawable        mReloadDrawable;
+    private boolean         mInLoad;
+    private BrowserActivity mBrowserActivity;
+
+    private final View            mBackButton;
+    private final View            mForwardButton;
+    private final View            mStar;
+    private final View            mMenu;
+    private final ImageView       mStopButton;
+    private final TextView        mTitle;
+    private final View            mAllButton;
+
+    public TitleBarXLarge(BrowserActivity context) {
+        super(context);
+        Resources resources = context.getResources();
+        LayoutInflater factory = LayoutInflater.from(context);
+        factory.inflate(R.layout.title_bar_xlarge, this);
+        mBrowserActivity = context;
+
+        mTitle = (TextView) findViewById(R.id.title);
+        mTitle.setCompoundDrawablePadding(5);
+        mTitle.setLongClickable(true);
+
+        mLockIcon = (ImageView) findViewById(R.id.lock);
+        mFavicon = (ImageView) findViewById(R.id.favicon);
+        mStopButton = (ImageView) findViewById(R.id.stop);
+        mStopDrawable = mStopButton.getDrawable();
+        mReloadDrawable = resources.getDrawable(R.drawable.ic_reload);
+
+        mAllButton = (ImageView) findViewById(R.id.all_btn);
+        mCircularProgress = (Drawable) resources.getDrawable(
+                com.android.internal.R.drawable.search_spinner);
+        DisplayMetrics metrics = resources.getDisplayMetrics();
+        int iconDimension = (int) TypedValue.applyDimension(
+                TypedValue.COMPLEX_UNIT_DIP, 20f, metrics);
+        mCircularProgress.setBounds(0, 0, iconDimension, iconDimension);
+        mHorizontalProgress = (ProgressBar) findViewById(
+                R.id.progress_horizontal);
+        mHorizontalProgress.setProgressDrawable(
+                resources.getDrawable(R.drawable.progress));
+
+        // FIXME: Change enabled states based on whether you can go
+        // back/forward.  Probably should be done inside onPageStarted.
+        mBackButton = findViewById(R.id.back);
+        mForwardButton = findViewById(R.id.forward);
+        mStar = findViewById(R.id.star);
+        mMenu = findViewById(R.id.menu);
+        View.OnClickListener listener = new View.OnClickListener() {
+                public void onClick(View v) {
+                    if (mBackButton == v) {
+                        mBrowserActivity.getTopWindow().goBack();
+                    } else if (mForwardButton == v) {
+                        mBrowserActivity.getTopWindow().goForward();
+                    } else if (mStar == v) {
+                        // FIXME: Show a menu with option to bookmark or
+                        // save to home page
+                        mBrowserActivity.bookmarkCurrentPage();
+                    } else if (mMenu == v) {
+                        mBrowserActivity.openOptionsMenu();
+                    } else if (mStopButton == v) {
+                        if (mInLoad) {
+                            mBrowserActivity.stopLoading();
+                        } else {
+                            mBrowserActivity.getTopWindow().reload();
+                        }
+                    } else if (mTitle == v) {
+                        mBrowserActivity.editUrl();
+                    } else if (mAllButton == v) {
+                        // FIXME: Show the new bookmarks/windows view.
+                        mBrowserActivity.bookmarksOrHistoryPicker(false);
+                    }
+                }
+        };
+        mBackButton.setOnClickListener(listener);
+        mForwardButton.setOnClickListener(listener);
+        mStar.setOnClickListener(listener);
+        mStopButton.setOnClickListener(listener);
+        mTitle.setOnClickListener(listener);
+        mAllButton.setOnClickListener(listener);
+        mMenu.setOnClickListener(listener);
+    }
+
+    @Override
+    public void createContextMenu(ContextMenu menu) {
+        MenuInflater inflater = mBrowserActivity.getMenuInflater();
+        inflater.inflate(R.menu.title_context, menu);
+        mBrowserActivity.onCreateContextMenu(menu, this, null);
+    }
+
+    /**
+     * Update the progress, from 0 to 100.
+     */
+    /* package */ void setProgress(int newProgress) {
+        if (newProgress >= mHorizontalProgress.getMax()) {
+            mTitle.setCompoundDrawables(null, null, null, null);
+            ((Animatable) mCircularProgress).stop();
+            mHorizontalProgress.setVisibility(View.GONE);
+            mInLoad = false;
+            mStopButton.setImageDrawable(mReloadDrawable);
+        } else {
+            mHorizontalProgress.setProgress(newProgress);
+            if (!mInLoad && getWindowToken() != null) {
+                // checking the window token lets us be sure that we
+                // are attached to a window before starting the animation,
+                // preventing a potential race condition
+                // (fix for bug http://b/2115736)
+                mTitle.setCompoundDrawables(null, null, mCircularProgress,
+                        null);
+                ((Animatable) mCircularProgress).start();
+                mHorizontalProgress.setVisibility(View.VISIBLE);
+                mInLoad = true;
+                mStopButton.setImageDrawable(mStopDrawable);
+            }
+        }
+    }
+
+    /**
+     * Update the text displayed in the title bar.
+     * @param title String to display.  If null, the loading string will be
+     *      shown.
+     */
+    /* package */ void setDisplayTitle(String title) {
+        if (title == null) {
+            mTitle.setText(R.string.title_bar_loading);
+        } else {
+            mTitle.setText(title);
+        }
+    }
+
+}
diff --git a/src/com/android/browser/WebDialog.java b/src/com/android/browser/WebDialog.java
new file mode 100644
index 0000000..9995e8f
--- /dev/null
+++ b/src/com/android/browser/WebDialog.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+package com.android.browser;
+
+import android.content.Context;
+import android.view.View;
+import android.view.animation.AnimationUtils;
+import android.view.inputmethod.InputMethodManager;
+import android.webkit.WebView;
+import android.widget.LinearLayout;
+
+/* package */ class WebDialog extends LinearLayout {
+    protected WebView         mWebView;
+    protected BrowserActivity mBrowserActivity;
+    private boolean           mIsVisible;
+
+    /* package */ WebDialog(BrowserActivity context) {
+        super(context);
+        mBrowserActivity = context;
+    }
+
+    /* dialogs that have cancel buttons can optionally share code by including a
+     * view with an id of 'done'.
+     */
+    protected void addCancel() {
+        View button = findViewById(R.id.done);
+        if (button != null) button.setOnClickListener(mCancelListener);
+    }
+
+    private View.OnClickListener mCancelListener = new View.OnClickListener() {
+        public void onClick(View v) {
+            mBrowserActivity.closeDialogs();
+        }
+    };
+
+    protected void dismiss() {
+        startAnimation(AnimationUtils.loadAnimation(mBrowserActivity,
+                R.anim.dialog_exit));
+        mIsVisible = false;
+    }
+
+    /*
+     * Remove the soft keyboard from the screen.
+     */
+    protected void hideSoftInput() {
+        InputMethodManager imm = (InputMethodManager)
+                mBrowserActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
+        imm.hideSoftInputFromWindow(mWebView.getWindowToken(), 0);
+    }
+
+    protected boolean isVisible() {
+        return mIsVisible;
+    }
+
+    /* package */ void setWebView(WebView webview) {
+        mWebView = webview;
+    }
+
+    protected void show() {
+        startAnimation(AnimationUtils.loadAnimation(mBrowserActivity,
+            R.anim.dialog_enter));
+        mIsVisible = true;
+    }
+
+}
diff --git a/tests/src/com/android/browser/TestWebChromeClient.java b/tests/src/com/android/browser/TestWebChromeClient.java
index d78eaed..53f8db3 100644
--- a/tests/src/com/android/browser/TestWebChromeClient.java
+++ b/tests/src/com/android/browser/TestWebChromeClient.java
@@ -195,7 +195,7 @@
 
     /** {@inheritDoc} */
     @Override
-    public void openFileChooser(ValueCallback<Uri> uploadFile) {
-        mWrappedClient.openFileChooser(uploadFile);
+    public void openFileChooser(ValueCallback<Uri> uploadFile, String acceptType) {
+        mWrappedClient.openFileChooser(uploadFile, acceptType);
     }
 }