am 6d25c81e: Merge "Protection against bookmarks with url=null in the database"

Merge commit '6d25c81ef7ddfc6cbc36094388b2de987dd77dae' into gingerbread-plus-aosp

* commit '6d25c81ef7ddfc6cbc36094388b2de987dd77dae':
  Protection against bookmarks with url=null in the database
diff --git a/Android.mk b/Android.mk
index 6e20ab8..e015dda 100644
--- a/Android.mk
+++ b/Android.mk
@@ -12,6 +12,8 @@
 
 LOCAL_PACKAGE_NAME := Browser
 
+LOCAL_EMMA_COVERAGE_FILTER := *,-com.android.common.*
+
 include $(BUILD_PACKAGE)
 
 # additionally, build tests in sub-folders in a separate .apk
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 7e98019..dc8f599 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -30,6 +30,7 @@
     <uses-permission android:name="android.permission.SET_WALLPAPER" />
     <uses-permission android:name="android.permission.WAKE_LOCK"/>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
     <uses-permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"/>
     <uses-permission android:name="com.android.browser.permission.WRITE_HISTORY_BOOKMARKS"/>
     <uses-permission android:name="android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS" />
@@ -199,7 +200,6 @@
         <receiver android:name=".OpenDownloadReceiver">
             <intent-filter>
                 <action android:name="android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED"/>
-                <action android:name="android.intent.action.DELETE"/>
                 <data android:scheme="content" android:mimeType="vnd.android.cursor.item/download"/>
             </intent-filter>
         </receiver>
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..f98d845 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..dacb5c3 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/drawable-hdpi/ic_menu_add_bookmark.png b/res/drawable-hdpi/ic_menu_add_bookmark.png
index 28beaaa..c54eb7e 100644
--- a/res/drawable-hdpi/ic_menu_add_bookmark.png
+++ b/res/drawable-hdpi/ic_menu_add_bookmark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu_bookmarks.png b/res/drawable-hdpi/ic_menu_bookmarks.png
index 3644acf..fd63499 100755
--- a/res/drawable-hdpi/ic_menu_bookmarks.png
+++ b/res/drawable-hdpi/ic_menu_bookmarks.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu_list.png b/res/drawable-hdpi/ic_menu_list.png
index cf95f2f..2b921b3 100644
--- a/res/drawable-hdpi/ic_menu_list.png
+++ b/res/drawable-hdpi/ic_menu_list.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu_new_window.png b/res/drawable-hdpi/ic_menu_new_window.png
index fa544fc..36aee01 100644
--- a/res/drawable-hdpi/ic_menu_new_window.png
+++ b/res/drawable-hdpi/ic_menu_new_window.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu_thumbnail.png b/res/drawable-hdpi/ic_menu_thumbnail.png
index bfc99aa..705b02b 100644
--- a/res/drawable-hdpi/ic_menu_thumbnail.png
+++ b/res/drawable-hdpi/ic_menu_thumbnail.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu_windows.png b/res/drawable-hdpi/ic_menu_windows.png
index 0a27b95..0e80009 100644
--- a/res/drawable-hdpi/ic_menu_windows.png
+++ b/res/drawable-hdpi/ic_menu_windows.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_add_bookmark.png b/res/drawable-mdpi/ic_menu_add_bookmark.png
index 3e38bb9..ce451b3 100644
--- a/res/drawable-mdpi/ic_menu_add_bookmark.png
+++ b/res/drawable-mdpi/ic_menu_add_bookmark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_bookmarks.png b/res/drawable-mdpi/ic_menu_bookmarks.png
old mode 100755
new mode 100644
index 1ac78b6..c6a3cdb
--- a/res/drawable-mdpi/ic_menu_bookmarks.png
+++ b/res/drawable-mdpi/ic_menu_bookmarks.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_list.png b/res/drawable-mdpi/ic_menu_list.png
index b2d35cc..36bf8d6 100644
--- a/res/drawable-mdpi/ic_menu_list.png
+++ b/res/drawable-mdpi/ic_menu_list.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_new_window.png b/res/drawable-mdpi/ic_menu_new_window.png
index 7fb9948..4fdea6c 100644
--- a/res/drawable-mdpi/ic_menu_new_window.png
+++ b/res/drawable-mdpi/ic_menu_new_window.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_thumbnail.png b/res/drawable-mdpi/ic_menu_thumbnail.png
index 74a87e2..be4ed5e 100644
--- a/res/drawable-mdpi/ic_menu_thumbnail.png
+++ b/res/drawable-mdpi/ic_menu_thumbnail.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_windows.png b/res/drawable-mdpi/ic_menu_windows.png
index cdc4d83..c33de2b 100644
--- a/res/drawable-mdpi/ic_menu_windows.png
+++ b/res/drawable-mdpi/ic_menu_windows.png
Binary files differ
diff --git a/res/layout/browser_download_item.xml b/res/layout/browser_download_item.xml
deleted file mode 100644
index 52f49c1..0000000
--- a/res/layout/browser_download_item.xml
+++ /dev/null
@@ -1,91 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** assets/res/any/layout/browser_bookmark_item.xml
-**
-** Copyright 2006, 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.
-*/
--->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:paddingRight="?android:attr/scrollbarSize"
-    >
-
-    <ImageView android:id="@+id/download_icon"
-        android:layout_width="@android:dimen/app_icon_size"
-        android:layout_height="@android:dimen/app_icon_size"
-        android:layout_alignParentTop="true"
-        android:layout_alignParentLeft="true"
-        android:scaleType="fitCenter"
-        />
-
-    <TextView android:id="@+id/download_title"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:maxLines="1"
-        android:layout_alignParentTop="true"
-        android:layout_toRightOf="@id/download_icon"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-    />
-    <TextView android:id="@+id/domain"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_toRightOf="@id/download_icon"
-        android:layout_below="@id/download_title"
-        android:maxLines="1"
-        android:textAppearance="?android:attr/textAppearanceSmall"
-    />
-
-    <TextView android:id="@+id/complete_date"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:maxLines="1"
-        android:textAppearance="?android:attr/textAppearanceSmall"
-        android:layout_below="@id/domain"
-        android:layout_alignParentRight="true"
-        android:visibility="gone"
-    />
-
-    <TextView android:id="@+id/complete_text"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_below="@id/domain"
-        android:layout_toRightOf="@id/download_icon"
-        android:layout_toLeftOf="@id/complete_date"
-        android:textAppearance="?android:attr/textAppearanceSmall"
-        android:visibility="gone"
-    />
-
-    <ProgressBar android:id="@+id/download_progress"
-        style="?android:attr/progressBarStyleHorizontal"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_below="@id/download_icon"
-        android:layout_alignParentLeft="true"
-        android:layout_alignParentRight="true"
-        android:max="100"
-    />
-    <TextView android:id="@+id/progress_text"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:maxLines="1"
-        android:textAppearance="?android:attr/textAppearanceSmall"
-        android:layout_centerHorizontal="true"
-        android:layout_below="@id/download_progress"
-    />
-</RelativeLayout>
-
diff --git a/res/layout/browser_downloads_page.xml b/res/layout/browser_downloads_page.xml
deleted file mode 100644
index 5cdf30c..0000000
--- a/res/layout/browser_downloads_page.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** assets/res/any/layout/browser_bookmarks_page.xml
-**
-** Copyright 2006, 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.
-*/
--->
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
-    <ExpandableListView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent"/>
-    <ViewStub android:id="@+id/empty" android:layout="@layout/no_downloads" android:layout_width="match_parent" android:layout_height="match_parent"/>
-</merge>
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/no_downloads.xml b/res/layout/no_downloads.xml
deleted file mode 100644
index 6918eab..0000000
--- a/res/layout/no_downloads.xml
+++ /dev/null
@@ -1,25 +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.
--->
-
-<TextView xmlns:android="http://schemas.android.com/apk/res/android" 
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:text="@string/no_downloads"
-    android:background="@color/black"
-    android:textColor="@color/white"
-    android:gravity="center"
-    android:textStyle="bold"
-    />
diff --git a/res/values-cs-rCZ/donottranslate-search_engines.xml b/res/values-cs-rCZ/donottranslate-search_engines.xml
new file mode 100644
index 0000000..5aea8c8
--- /dev/null
+++ b/res/values-cs-rCZ/donottranslate-search_engines.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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>seznam</item>
+    <item>bing_cs_CZ</item>
+    <item>centrum_cz</item>
+    <item>atlas_cz</item>
+  </string-array>
+</resources>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 50f9949..8dacc6c 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -136,6 +136,8 @@
   </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"Otevírat nová okna za aktuálním oknem"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"Nastavit domovskou stránku"</string>
+    <string name="pref_content_search_engine" msgid="1620101310821644144">"Nastavit vyhledávač"</string>
+    <string name="pref_content_search_engine_summary" msgid="5162667665858487316">"Výběr vyhledávače"</string>
     <string name="pref_use_current" msgid="1493179933653044553">"Použít aktuální stránku"</string>
     <string name="pref_content_autofit" msgid="8260474534053660809">"Automaticky přizpůsobit"</string>
     <string name="pref_content_autofit_summary" msgid="4587831659894879986">"Přizpůsobit velikost webových stránek obrazovce"</string>
@@ -243,10 +245,14 @@
     <string name="download_file_error_dlg_title" msgid="2693630283595384874">"Nedostatek místa"</string>
     <string name="download_file_error_dlg_msg" msgid="5156405410324072471">"Soubor <xliff:g id="FILENAME">%s</xliff:g> nelze stáhnout."\n"Uvolněte paměť telefonu a akci opakujte."</string>
     <string name="download_failed_generic_dlg_title" msgid="6106781095337833391">"Stažení se nezdařilo."</string>
-    <string name="download_no_sdcard_dlg_title" msgid="605904452159416792">"Žádná karta SD"</string>
-    <string name="download_no_sdcard_dlg_msg" msgid="2616399456116301518">"Na kartu SD je třeba stáhnout soubor <xliff:g id="FILENAME">%s</xliff:g>."</string>
-    <string name="download_sdcard_busy_dlg_title" msgid="6877712666046917741">"Karta SD není dostupná"</string>
-    <string name="download_sdcard_busy_dlg_msg" msgid="3473883538192835204">"Karta SD je zaneprázdněna. Chcete-li povolit stahování, vyberte v oznámení možnost Vypnout úložiště USB."</string>
+    <!-- outdated translation 605904452159416792 -->     <string name="download_no_sdcard_dlg_title" product="nosdcard" msgid="5349772560166195586">"Žádná karta SD"</string>
+    <string name="download_no_sdcard_dlg_title" product="default" msgid="605904452159416792">"Žádná karta SD"</string>
+    <!-- outdated translation 2616399456116301518 -->     <string name="download_no_sdcard_dlg_msg" product="nosdcard" msgid="9049052105269200675">"Na kartu SD je třeba stáhnout soubor <xliff:g id="FILENAME">%s</xliff:g>."</string>
+    <string name="download_no_sdcard_dlg_msg" product="default" msgid="2616399456116301518">"Na kartu SD je třeba stáhnout soubor <xliff:g id="FILENAME">%s</xliff:g>."</string>
+    <!-- outdated translation 6877712666046917741 -->     <string name="download_sdcard_busy_dlg_title" product="nosdcard" msgid="4151068942919670243">"Karta SD není dostupná"</string>
+    <string name="download_sdcard_busy_dlg_title" product="default" msgid="6877712666046917741">"Karta SD není dostupná"</string>
+    <!-- outdated translation 3473883538192835204 -->     <string name="download_sdcard_busy_dlg_msg" product="nosdcard" msgid="7297514580933657663">"Karta SD je zaneprázdněna. Chcete-li povolit stahování, vyberte v oznámení možnost Vypnout úložiště USB."</string>
+    <string name="download_sdcard_busy_dlg_msg" product="default" msgid="3473883538192835204">"Karta SD je zaneprázdněna. Chcete-li povolit stahování, vyberte v oznámení možnost Vypnout úložiště USB."</string>
     <string name="download_no_application_title" msgid="1286056729168874295">"Soubor nelze otevřít"</string>
     <string name="retry" msgid="1835923075542266721">"Zkusit znovu"</string>
     <string name="no_downloads" msgid="3947445710685021498">"Historie stahování je prázdná."</string>
diff --git a/res/values-da-rDK/donottranslate-search_engines.xml b/res/values-da-rDK/donottranslate-search_engines.xml
new file mode 100644
index 0000000..73360b1
--- /dev/null
+++ b/res/values-da-rDK/donottranslate-search_engines.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>bing_da_DK</item>
+    <item>yahoo_dk</item>
+  </string-array>
+</resources>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 3d667ed..7ac2f6a 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -136,6 +136,8 @@
   </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"Åbn nye vinduer bag det aktive"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"Angiv startside"</string>
+    <string name="pref_content_search_engine" msgid="1620101310821644144">"Angiv søgemaskine"</string>
+    <string name="pref_content_search_engine_summary" msgid="5162667665858487316">"Vælg en søgemaskine"</string>
     <string name="pref_use_current" msgid="1493179933653044553">"Brug aktuel side"</string>
     <string name="pref_content_autofit" msgid="8260474534053660809">"Tilpas sider automatisk"</string>
     <string name="pref_content_autofit_summary" msgid="4587831659894879986">"Tilpas websider, så de passer til skærmen"</string>
@@ -243,10 +245,14 @@
     <string name="download_file_error_dlg_title" msgid="2693630283595384874">"Der er ikke mere plads"</string>
     <string name="download_file_error_dlg_msg" msgid="5156405410324072471">"<xliff:g id="FILENAME">%s</xliff:g> kunne ikke downloades."\n"Frigør noget plads på din telefon, og prøv igen."</string>
     <string name="download_failed_generic_dlg_title" msgid="6106781095337833391">"Download mislykkedes"</string>
-    <string name="download_no_sdcard_dlg_title" msgid="605904452159416792">"Der er intet SD-kort"</string>
-    <string name="download_no_sdcard_dlg_msg" msgid="2616399456116301518">"Et SD-kort er påkrævet for at downloade <xliff:g id="FILENAME">%s</xliff:g>."</string>
-    <string name="download_sdcard_busy_dlg_title" msgid="6877712666046917741">"SD-kortet er ikke tilgængeligt"</string>
-    <string name="download_sdcard_busy_dlg_msg" msgid="3473883538192835204">"SD-kortet er optaget. Vælg \"Slå USB-lagring fra\" i meddelelsen for at tillade downloads."</string>
+    <!-- outdated translation 605904452159416792 -->     <string name="download_no_sdcard_dlg_title" product="nosdcard" msgid="5349772560166195586">"Der er intet SD-kort"</string>
+    <string name="download_no_sdcard_dlg_title" product="default" msgid="605904452159416792">"Der er intet SD-kort"</string>
+    <!-- outdated translation 2616399456116301518 -->     <string name="download_no_sdcard_dlg_msg" product="nosdcard" msgid="9049052105269200675">"Et SD-kort er påkrævet for at downloade <xliff:g id="FILENAME">%s</xliff:g>."</string>
+    <string name="download_no_sdcard_dlg_msg" product="default" msgid="2616399456116301518">"Et SD-kort er påkrævet for at downloade <xliff:g id="FILENAME">%s</xliff:g>."</string>
+    <!-- outdated translation 6877712666046917741 -->     <string name="download_sdcard_busy_dlg_title" product="nosdcard" msgid="4151068942919670243">"SD-kortet er ikke tilgængeligt"</string>
+    <string name="download_sdcard_busy_dlg_title" product="default" msgid="6877712666046917741">"SD-kortet er ikke tilgængeligt"</string>
+    <!-- outdated translation 3473883538192835204 -->     <string name="download_sdcard_busy_dlg_msg" product="nosdcard" msgid="7297514580933657663">"SD-kortet er optaget. Vælg \"Slå USB-lagring fra\" i meddelelsen for at tillade downloads."</string>
+    <string name="download_sdcard_busy_dlg_msg" product="default" msgid="3473883538192835204">"SD-kortet er optaget. Vælg \"Slå USB-lagring fra\" i meddelelsen for at tillade downloads."</string>
     <string name="download_no_application_title" msgid="1286056729168874295">"Kan ikke åbne filen"</string>
     <string name="retry" msgid="1835923075542266721">"Prøv igen"</string>
     <string name="no_downloads" msgid="3947445710685021498">"Downloadoversigten er tom."</string>
diff --git a/res/values-de-rAT/donottranslate-search_engines.xml b/res/values-de-rAT/donottranslate-search_engines.xml
new file mode 100644
index 0000000..708d7ed
--- /dev/null
+++ b/res/values-de-rAT/donottranslate-search_engines.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>yahoo_at</item>
+    <item>bing_de_AT</item>
+  </string-array>
+</resources>
diff --git a/res/values-de-rCH/donottranslate-search_engines.xml b/res/values-de-rCH/donottranslate-search_engines.xml
new file mode 100644
index 0000000..4e2360e
--- /dev/null
+++ b/res/values-de-rCH/donottranslate-search_engines.xml
@@ -0,0 +1,32 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>yahoo_ch</item>
+    <item>bing_de_CH</item>
+    <item>bing_fr_CH</item>
+    <item>search_de_CH</item>
+    <item>search_fr_CH</item>
+  </string-array>
+</resources>
diff --git a/res/values-de-rDE/donottranslate-search_engines.xml b/res/values-de-rDE/donottranslate-search_engines.xml
new file mode 100644
index 0000000..5fdde69
--- /dev/null
+++ b/res/values-de-rDE/donottranslate-search_engines.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>ask_de</item>
+    <item>bing_de_DE</item>
+    <item>yahoo_de</item>
+  </string-array>
+</resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 7efb620..4b6d1ef 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -38,7 +38,7 @@
     <item quantity="few" msgid="5544267486978946555">"<xliff:g id="NUMBER">%d</xliff:g> Treffer"</item>
     <item quantity="other" msgid="6616125067364315405">"<xliff:g id="NUMBER">%d</xliff:g> Treffer"</item>
   </plurals>
-    <string name="title_bar_loading" msgid="7438217780834640678">"Ladevorgang läuft..."</string>
+    <string name="title_bar_loading" msgid="7438217780834640678">"Wird geladen..."</string>
     <string name="page_info" msgid="4048529256302257195">"Seiteninfo"</string>
     <string name="page_info_view" msgid="5303490449842635158">"Seiteninfo anzeigen"</string>
     <string name="page_info_address" msgid="2222306609532903254">"Adresse:"</string>
@@ -112,7 +112,7 @@
     <string name="contextmenu_copylink" msgid="5153657160294534270">"Link-URL kopieren"</string>
     <string name="contextmenu_download_image" msgid="4243829645180686912">"Bild speichern"</string>
     <string name="contextmenu_view_image" msgid="3870625602053600905">"Bild anzeigen"</string>
-    <string name="contextmenu_set_wallpaper" msgid="3691902960115350686">"Als Hintergrundbild festlegen"</string>
+    <string name="contextmenu_set_wallpaper" msgid="3691902960115350686">"Als Hintergrund festlegen"</string>
     <string name="contextmenu_dial_dot" msgid="5856550683415933806">"Wählen..."</string>
     <string name="contextmenu_add_contact" msgid="3183511922223645716">"Kontakt hinzufügen"</string>
     <string name="contextmenu_send_mail" msgid="1014513374828775660">"E-Mail senden"</string>
@@ -136,6 +136,8 @@
   </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"Neues Fenster hinter dem aktuellen Fenster öffnen"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"Startseite festlegen"</string>
+    <string name="pref_content_search_engine" msgid="1620101310821644144">"Suchmaschine festlegen"</string>
+    <string name="pref_content_search_engine_summary" msgid="5162667665858487316">"Suchmaschine auswählen"</string>
     <string name="pref_use_current" msgid="1493179933653044553">"Aktuelle Seite verwenden"</string>
     <string name="pref_content_autofit" msgid="8260474534053660809">"Autom. Anpassung"</string>
     <string name="pref_content_autofit_summary" msgid="4587831659894879986">"Webseiten an den Bildschirm anpassen"</string>
@@ -243,10 +245,14 @@
     <string name="download_file_error_dlg_title" msgid="2693630283595384874">"Kein freier Speicher vorhanden"</string>
     <string name="download_file_error_dlg_msg" msgid="5156405410324072471">"<xliff:g id="FILENAME">%s</xliff:g> konnte nicht heruntergeladen werden."\n"Bereinigen Sie den Speicher Ihres Telefons und versuchen Sie es erneut."</string>
     <string name="download_failed_generic_dlg_title" msgid="6106781095337833391">"Download war nicht erfolgreich"</string>
-    <string name="download_no_sdcard_dlg_title" msgid="605904452159416792">"Keine SD-Karte"</string>
-    <string name="download_no_sdcard_dlg_msg" msgid="2616399456116301518">"Zum Download von <xliff:g id="FILENAME">%s</xliff:g> ist eine SD-Karte erforderlich."</string>
-    <string name="download_sdcard_busy_dlg_title" msgid="6877712666046917741">"SD-Karte nicht verfügbar"</string>
-    <string name="download_sdcard_busy_dlg_msg" msgid="3473883538192835204">"Die SD-Karte wird benutzt. Wählen Sie in der Benachrichtigung \"USB-Speicher deaktivieren\" aus, um Downloads zuzulassen."</string>
+    <!-- outdated translation 605904452159416792 -->     <string name="download_no_sdcard_dlg_title" product="nosdcard" msgid="5349772560166195586">"Keine SD-Karte"</string>
+    <string name="download_no_sdcard_dlg_title" product="default" msgid="605904452159416792">"Keine SD-Karte"</string>
+    <!-- outdated translation 2616399456116301518 -->     <string name="download_no_sdcard_dlg_msg" product="nosdcard" msgid="9049052105269200675">"Zum Download von <xliff:g id="FILENAME">%s</xliff:g> ist eine SD-Karte erforderlich."</string>
+    <string name="download_no_sdcard_dlg_msg" product="default" msgid="2616399456116301518">"Zum Download von <xliff:g id="FILENAME">%s</xliff:g> ist eine SD-Karte erforderlich."</string>
+    <!-- outdated translation 6877712666046917741 -->     <string name="download_sdcard_busy_dlg_title" product="nosdcard" msgid="4151068942919670243">"SD-Karte nicht verfügbar"</string>
+    <string name="download_sdcard_busy_dlg_title" product="default" msgid="6877712666046917741">"SD-Karte nicht verfügbar"</string>
+    <!-- outdated translation 3473883538192835204 -->     <string name="download_sdcard_busy_dlg_msg" product="nosdcard" msgid="7297514580933657663">"Die SD-Karte wird benutzt. Wählen Sie in der Benachrichtigung \"USB-Speicher deaktivieren\" aus, um Downloads zuzulassen."</string>
+    <string name="download_sdcard_busy_dlg_msg" product="default" msgid="3473883538192835204">"Die SD-Karte wird benutzt. Wählen Sie in der Benachrichtigung \"USB-Speicher deaktivieren\" aus, um Downloads zuzulassen."</string>
     <string name="download_no_application_title" msgid="1286056729168874295">"Datei kann nicht geöffnet werden."</string>
     <string name="retry" msgid="1835923075542266721">"Wiederholen"</string>
     <string name="no_downloads" msgid="3947445710685021498">"Downloadverlauf ist leer."</string>
@@ -289,5 +295,5 @@
     <string name="website_settings_clear_all_dialog_message" msgid="6150502090601476333">"Alle Websitedaten und Standortberechtigungen werden gelöscht."</string>
     <string name="website_settings_clear_all_dialog_ok_button" msgid="6401582240627669431">"Alle Daten löschen"</string>
     <string name="website_settings_clear_all_dialog_cancel_button" msgid="1896757051856611674">"Abbrechen"</string>
-    <string name="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Hintergrundbild wird eingestellt..."</string>
+    <string name="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Hintergrund wird eingestellt..."</string>
 </resources>
diff --git a/res/values-el-rGR/donottranslate-search_engines.xml b/res/values-el-rGR/donottranslate-search_engines.xml
new file mode 100644
index 0000000..8185cf3
--- /dev/null
+++ b/res/values-el-rGR/donottranslate-search_engines.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>yahoo</item>
+    <item>in</item>
+    <item>bing_el_GR</item>
+  </string-array>
+</resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 7da0027..224fbf0 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -136,6 +136,8 @@
   </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"Άνοιγμα νέων παραθύρων πίσω από το τρέχον"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"Ορισμός ως αρχική σελίδα"</string>
+    <string name="pref_content_search_engine" msgid="1620101310821644144">"Ορισμός μηχανής αναζήτησης"</string>
+    <string name="pref_content_search_engine_summary" msgid="5162667665858487316">"Επιλέξτε μηχανή αναζήτησης"</string>
     <string name="pref_use_current" msgid="1493179933653044553">"Χρήση τρέχουσας σελίδας"</string>
     <string name="pref_content_autofit" msgid="8260474534053660809">"Αυτόματη προσαρμογή σελίδων"</string>
     <string name="pref_content_autofit_summary" msgid="4587831659894879986">"Μορφοποίηση ιστοσελίδων για την προσαρμογή τους στο μέγεθος της οθόνης"</string>
@@ -243,10 +245,14 @@
     <string name="download_file_error_dlg_title" msgid="2693630283595384874">"Εξαντλήθηκε ο χώρος"</string>
     <string name="download_file_error_dlg_msg" msgid="5156405410324072471">"Δεν ήταν δυνατή η λήψη του <xliff:g id="FILENAME">%s</xliff:g>."\n"Απελευθερώστε λίγο χώρο στο τηλέφωνό σας και δοκιμάστε ξανά."</string>
     <string name="download_failed_generic_dlg_title" msgid="6106781095337833391">"Ανεπιτυχής λήψη"</string>
-    <string name="download_no_sdcard_dlg_title" msgid="605904452159416792">"Δεν υπάρχει κάρτα SD"</string>
-    <string name="download_no_sdcard_dlg_msg" msgid="2616399456116301518">"Για τη λήψη του <xliff:g id="FILENAME">%s</xliff:g> απαιτείται κάρτα SD."</string>
-    <string name="download_sdcard_busy_dlg_title" msgid="6877712666046917741">"Η κάρτα SD δεν είναι διαθέσιμη"</string>
-    <string name="download_sdcard_busy_dlg_msg" msgid="3473883538192835204">"Η κάρτα SD είναι απασχολημένη. Για να επιτρέψετε τις λήψεις, στην ειδοποίηση επιλέξτε \"Απενεργοποίηση χώρου αποθήκευσης USB\"."</string>
+    <!-- outdated translation 605904452159416792 -->     <string name="download_no_sdcard_dlg_title" product="nosdcard" msgid="5349772560166195586">"Δεν υπάρχει κάρτα SD"</string>
+    <string name="download_no_sdcard_dlg_title" product="default" msgid="605904452159416792">"Δεν υπάρχει κάρτα SD"</string>
+    <!-- outdated translation 2616399456116301518 -->     <string name="download_no_sdcard_dlg_msg" product="nosdcard" msgid="9049052105269200675">"Για τη λήψη του <xliff:g id="FILENAME">%s</xliff:g> απαιτείται κάρτα SD."</string>
+    <string name="download_no_sdcard_dlg_msg" product="default" msgid="2616399456116301518">"Για τη λήψη του <xliff:g id="FILENAME">%s</xliff:g> απαιτείται κάρτα SD."</string>
+    <!-- outdated translation 6877712666046917741 -->     <string name="download_sdcard_busy_dlg_title" product="nosdcard" msgid="4151068942919670243">"Η κάρτα SD δεν είναι διαθέσιμη"</string>
+    <string name="download_sdcard_busy_dlg_title" product="default" msgid="6877712666046917741">"Η κάρτα SD δεν είναι διαθέσιμη"</string>
+    <!-- outdated translation 3473883538192835204 -->     <string name="download_sdcard_busy_dlg_msg" product="nosdcard" msgid="7297514580933657663">"Η κάρτα SD είναι απασχολημένη. Για να επιτρέψετε τις λήψεις, στην ειδοποίηση επιλέξτε \"Απενεργοποίηση χώρου αποθήκευσης USB\"."</string>
+    <string name="download_sdcard_busy_dlg_msg" product="default" msgid="3473883538192835204">"Η κάρτα SD είναι απασχολημένη. Για να επιτρέψετε τις λήψεις, στην ειδοποίηση επιλέξτε \"Απενεργοποίηση χώρου αποθήκευσης USB\"."</string>
     <string name="download_no_application_title" msgid="1286056729168874295">"Δεν είναι δυνατό το άνοιγμα του αρχείου"</string>
     <string name="retry" msgid="1835923075542266721">"Επανάληψη"</string>
     <string name="no_downloads" msgid="3947445710685021498">"Το ιστορικό λήψεων του προγράμματος περιήγησης είναι κενό."</string>
diff --git a/res/values-en-rAU/donottranslate-search_engines.xml b/res/values-en-rAU/donottranslate-search_engines.xml
new file mode 100644
index 0000000..08765ac
--- /dev/null
+++ b/res/values-en-rAU/donottranslate-search_engines.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>bing_en_AU</item>
+    <item>yahoo_au</item>
+  </string-array>
+</resources>
diff --git a/res/values-en-rGB/donottranslate-search_engines.xml b/res/values-en-rGB/donottranslate-search_engines.xml
new file mode 100644
index 0000000..b2ee93c
--- /dev/null
+++ b/res/values-en-rGB/donottranslate-search_engines.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>ask_uk</item>
+    <item>yahoo_uk</item>
+    <item>bing_en_GB</item>
+  </string-array>
+</resources>
diff --git a/res/values-en-rIE/donottranslate-search_engines.xml b/res/values-en-rIE/donottranslate-search_engines.xml
new file mode 100644
index 0000000..25f3f29
--- /dev/null
+++ b/res/values-en-rIE/donottranslate-search_engines.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>yahoo_uk</item>
+    <item>bing_en_IE</item>
+  </string-array>
+</resources>
diff --git a/res/values-en-rNZ/donottranslate-search_engines.xml b/res/values-en-rNZ/donottranslate-search_engines.xml
new file mode 100644
index 0000000..2044c37
--- /dev/null
+++ b/res/values-en-rNZ/donottranslate-search_engines.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>yahoo_nz</item>
+    <item>bing_en_NZ</item>
+  </string-array>
+</resources>
diff --git a/res/values-en-rSG/donottranslate-search_engines.xml b/res/values-en-rSG/donottranslate-search_engines.xml
new file mode 100644
index 0000000..74d6939
--- /dev/null
+++ b/res/values-en-rSG/donottranslate-search_engines.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>yahoo_sg</item>
+    <item>bing_en_SG</item>
+    <item>rednano</item>
+  </string-array>
+</resources>
diff --git a/res/values-en-rZA/donottranslate-search_engines.xml b/res/values-en-rZA/donottranslate-search_engines.xml
new file mode 100644
index 0000000..bab95c4
--- /dev/null
+++ b/res/values-en-rZA/donottranslate-search_engines.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>yahoo</item>
+    <item>bing_en_ZA</item>
+  </string-array>
+</resources>
diff --git a/res/values-es-rES/donottranslate-search_engines.xml b/res/values-es-rES/donottranslate-search_engines.xml
new file mode 100644
index 0000000..053d786
--- /dev/null
+++ b/res/values-es-rES/donottranslate-search_engines.xml
@@ -0,0 +1,32 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>ask_es</item>
+    <item>bing_es_ES</item>
+    <item>yahoo_es</item>
+    <item>terra_es</item>
+    <item>hispavista</item>
+  </string-array>
+</resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index d69b315..9285406 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -136,6 +136,8 @@
   </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"Abrir ventanas nuevas detrás de la actual"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"Definir página de inicio"</string>
+    <string name="pref_content_search_engine" msgid="1620101310821644144">"Establecer el motor de búsqueda"</string>
+    <string name="pref_content_search_engine_summary" msgid="5162667665858487316">"Seleccionar un motor de búsqueda"</string>
     <string name="pref_use_current" msgid="1493179933653044553">"Utilizar la página actual"</string>
     <string name="pref_content_autofit" msgid="8260474534053660809">"Ajuste automát. de pág."</string>
     <string name="pref_content_autofit_summary" msgid="4587831659894879986">"Formatea las páginas web para que se ajusten a la pantalla"</string>
@@ -243,10 +245,14 @@
     <string name="download_file_error_dlg_title" msgid="2693630283595384874">"Sin espacio"</string>
     <string name="download_file_error_dlg_msg" msgid="5156405410324072471">"<xliff:g id="FILENAME">%s</xliff:g> no se pudo cargar."\n"Libera espacio en tu teléfono y vuelve a intentarlo."</string>
     <string name="download_failed_generic_dlg_title" msgid="6106781095337833391">"La descarga no se ha realizado correctamente"</string>
-    <string name="download_no_sdcard_dlg_title" msgid="605904452159416792">"No hay tarjeta SD"</string>
-    <string name="download_no_sdcard_dlg_msg" msgid="2616399456116301518">"Es necesario tener una tarjeta SD para descargar <xliff:g id="FILENAME">%s</xliff:g>."</string>
-    <string name="download_sdcard_busy_dlg_title" msgid="6877712666046917741">"Tarjeta SD no disponible"</string>
-    <string name="download_sdcard_busy_dlg_msg" msgid="3473883538192835204">"La tarjeta SD está llena. Para permitir descargas, selecciona \"Desactivar almacenamiento USB\" en la notificación."</string>
+    <!-- outdated translation 605904452159416792 -->     <string name="download_no_sdcard_dlg_title" product="nosdcard" msgid="5349772560166195586">"No hay tarjeta SD"</string>
+    <string name="download_no_sdcard_dlg_title" product="default" msgid="605904452159416792">"No hay tarjeta SD"</string>
+    <!-- outdated translation 2616399456116301518 -->     <string name="download_no_sdcard_dlg_msg" product="nosdcard" msgid="9049052105269200675">"Es necesario tener una tarjeta SD para descargar <xliff:g id="FILENAME">%s</xliff:g>."</string>
+    <string name="download_no_sdcard_dlg_msg" product="default" msgid="2616399456116301518">"Es necesario tener una tarjeta SD para descargar <xliff:g id="FILENAME">%s</xliff:g>."</string>
+    <!-- outdated translation 6877712666046917741 -->     <string name="download_sdcard_busy_dlg_title" product="nosdcard" msgid="4151068942919670243">"Tarjeta SD no disponible"</string>
+    <string name="download_sdcard_busy_dlg_title" product="default" msgid="6877712666046917741">"Tarjeta SD no disponible"</string>
+    <!-- outdated translation 3473883538192835204 -->     <string name="download_sdcard_busy_dlg_msg" product="nosdcard" msgid="7297514580933657663">"La tarjeta SD está llena. Para permitir descargas, selecciona \"Desactivar almacenamiento USB\" en la notificación."</string>
+    <string name="download_sdcard_busy_dlg_msg" product="default" msgid="3473883538192835204">"La tarjeta SD está llena. Para permitir descargas, selecciona \"Desactivar almacenamiento USB\" en la notificación."</string>
     <string name="download_no_application_title" msgid="1286056729168874295">"No se puede abrir el archivo."</string>
     <string name="retry" msgid="1835923075542266721">"Intentar nuevamente"</string>
     <string name="no_downloads" msgid="3947445710685021498">"El historial de descarga está vacío."</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index e900c61..71903b4 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -136,6 +136,8 @@
   </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"Abrir nuevas ventanas detrás de la actual"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"Escritorio"</string>
+    <string name="pref_content_search_engine" msgid="1620101310821644144">"Establecer motor de búsqueda"</string>
+    <string name="pref_content_search_engine_summary" msgid="5162667665858487316">"Seleccionar un motor de búsqueda"</string>
     <string name="pref_use_current" msgid="1493179933653044553">"Utilizar página actual"</string>
     <string name="pref_content_autofit" msgid="8260474534053660809">"Ajustar páginas automát."</string>
     <string name="pref_content_autofit_summary" msgid="4587831659894879986">"Configurar las páginas web para ajustarlas a la pantalla"</string>
@@ -243,10 +245,14 @@
     <string name="download_file_error_dlg_title" msgid="2693630283595384874">"Sin espacio"</string>
     <string name="download_file_error_dlg_msg" msgid="5156405410324072471">"No se ha podido descargar el archivo <xliff:g id="FILENAME">%s</xliff:g>."\n"Libera espacio en el teléfono e inténtalo de nuevo."</string>
     <string name="download_failed_generic_dlg_title" msgid="6106781095337833391">"Descarga incorrecta"</string>
-    <string name="download_no_sdcard_dlg_title" msgid="605904452159416792">"Falta la tarjeta SD"</string>
-    <string name="download_no_sdcard_dlg_msg" msgid="2616399456116301518">"Para descargar <xliff:g id="FILENAME">%s</xliff:g> se necesita una tarjeta SD."</string>
-    <string name="download_sdcard_busy_dlg_title" msgid="6877712666046917741">"Tarjeta SD no disponible"</string>
-    <string name="download_sdcard_busy_dlg_msg" msgid="3473883538192835204">"La tarjeta SD está ocupada. Para permitir descargas, selecciona \"Desactivar almacenamiento USB\" en la notificación."</string>
+    <!-- outdated translation 605904452159416792 -->     <string name="download_no_sdcard_dlg_title" product="nosdcard" msgid="5349772560166195586">"Falta la tarjeta SD"</string>
+    <string name="download_no_sdcard_dlg_title" product="default" msgid="605904452159416792">"Falta la tarjeta SD"</string>
+    <!-- outdated translation 2616399456116301518 -->     <string name="download_no_sdcard_dlg_msg" product="nosdcard" msgid="9049052105269200675">"Para descargar <xliff:g id="FILENAME">%s</xliff:g> se necesita una tarjeta SD."</string>
+    <string name="download_no_sdcard_dlg_msg" product="default" msgid="2616399456116301518">"Para descargar <xliff:g id="FILENAME">%s</xliff:g> se necesita una tarjeta SD."</string>
+    <!-- outdated translation 6877712666046917741 -->     <string name="download_sdcard_busy_dlg_title" product="nosdcard" msgid="4151068942919670243">"Tarjeta SD no disponible"</string>
+    <string name="download_sdcard_busy_dlg_title" product="default" msgid="6877712666046917741">"Tarjeta SD no disponible"</string>
+    <!-- outdated translation 3473883538192835204 -->     <string name="download_sdcard_busy_dlg_msg" product="nosdcard" msgid="7297514580933657663">"La tarjeta SD está ocupada. Para permitir descargas, selecciona \"Desactivar almacenamiento USB\" en la notificación."</string>
+    <string name="download_sdcard_busy_dlg_msg" product="default" msgid="3473883538192835204">"La tarjeta SD está ocupada. Para permitir descargas, selecciona \"Desactivar almacenamiento USB\" en la notificación."</string>
     <string name="download_no_application_title" msgid="1286056729168874295">"No se puede abrir el archivo"</string>
     <string name="retry" msgid="1835923075542266721">"Reintentar"</string>
     <string name="no_downloads" msgid="3947445710685021498">"El historial de descargas está vacío."</string>
diff --git a/res/values-fr-rBE/donottranslate-search_engines.xml b/res/values-fr-rBE/donottranslate-search_engines.xml
new file mode 100644
index 0000000..d743fc0
--- /dev/null
+++ b/res/values-fr-rBE/donottranslate-search_engines.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>bing_nl_BE</item>
+    <item>yahoo</item>
+    <item>bing_fr_BE</item>
+  </string-array>
+</resources>
diff --git a/res/values-fr-rFR/donottranslate-search_engines.xml b/res/values-fr-rFR/donottranslate-search_engines.xml
new file mode 100644
index 0000000..4a75e4c
--- /dev/null
+++ b/res/values-fr-rFR/donottranslate-search_engines.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>yahoo_fr</item>
+    <item>bing_fr_FR</item>
+  </string-array>
+</resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index acd1230..f0d4ea9 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -136,6 +136,8 @@
   </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"Ouvrir les nouvelles fenêtres derrière la fenêtre actuelle"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"Page d\'accueil"</string>
+    <string name="pref_content_search_engine" msgid="1620101310821644144">"Définir le moteur de recherche"</string>
+    <string name="pref_content_search_engine_summary" msgid="5162667665858487316">"Sélectionnez un moteur de recherche."</string>
     <string name="pref_use_current" msgid="1493179933653044553">"Utiliser la page actuelle"</string>
     <string name="pref_content_autofit" msgid="8260474534053660809">"Redimensionner"</string>
     <string name="pref_content_autofit_summary" msgid="4587831659894879986">"Configurer les pages Web pour qu\'elles s\'ajustent à l\'écran"</string>
@@ -243,10 +245,14 @@
     <string name="download_file_error_dlg_title" msgid="2693630283595384874">"Espace insuffisant"</string>
     <string name="download_file_error_dlg_msg" msgid="5156405410324072471">"Impossible d\'afficher <xliff:g id="FILENAME">%s</xliff:g>"\n". Libérez de l\'espace sur votre téléphone, puis réessayez."</string>
     <string name="download_failed_generic_dlg_title" msgid="6106781095337833391">"Échec de téléchargement"</string>
-    <string name="download_no_sdcard_dlg_title" msgid="605904452159416792">"Aucune carte SD"</string>
-    <string name="download_no_sdcard_dlg_msg" msgid="2616399456116301518">"Le téléchargement de <xliff:g id="FILENAME">%s</xliff:g> requiert une carte SD."</string>
-    <string name="download_sdcard_busy_dlg_title" msgid="6877712666046917741">"Carte SD non disponible"</string>
-    <string name="download_sdcard_busy_dlg_msg" msgid="3473883538192835204">"La carte SD est occupée. Pour autoriser les téléchargements, sélectionnez l\'option \"Désactiver le stockage USB\" dans la notification."</string>
+    <!-- outdated translation 605904452159416792 -->     <string name="download_no_sdcard_dlg_title" product="nosdcard" msgid="5349772560166195586">"Aucune carte SD"</string>
+    <string name="download_no_sdcard_dlg_title" product="default" msgid="605904452159416792">"Aucune carte SD"</string>
+    <!-- outdated translation 2616399456116301518 -->     <string name="download_no_sdcard_dlg_msg" product="nosdcard" msgid="9049052105269200675">"Le téléchargement de <xliff:g id="FILENAME">%s</xliff:g> requiert une carte SD."</string>
+    <string name="download_no_sdcard_dlg_msg" product="default" msgid="2616399456116301518">"Le téléchargement de <xliff:g id="FILENAME">%s</xliff:g> requiert une carte SD."</string>
+    <!-- outdated translation 6877712666046917741 -->     <string name="download_sdcard_busy_dlg_title" product="nosdcard" msgid="4151068942919670243">"Carte SD non disponible"</string>
+    <string name="download_sdcard_busy_dlg_title" product="default" msgid="6877712666046917741">"Carte SD non disponible"</string>
+    <!-- outdated translation 3473883538192835204 -->     <string name="download_sdcard_busy_dlg_msg" product="nosdcard" msgid="7297514580933657663">"La carte SD est occupée. Pour autoriser les téléchargements, sélectionnez l\'option \"Désactiver le stockage USB\" dans la notification."</string>
+    <string name="download_sdcard_busy_dlg_msg" product="default" msgid="3473883538192835204">"La carte SD est occupée. Pour autoriser les téléchargements, sélectionnez l\'option \"Désactiver le stockage USB\" dans la notification."</string>
     <string name="download_no_application_title" msgid="1286056729168874295">"Fichier impossible à ouvrir"</string>
     <string name="retry" msgid="1835923075542266721">"Réessayer"</string>
     <string name="no_downloads" msgid="3947445710685021498">"L\'historique de téléchargement est vide."</string>
@@ -254,8 +260,8 @@
     <string name="download_success" msgid="2279041638155595203">"<xliff:g id="FILE">%s</xliff:g>Téléchargement terminé."</string>
     <string name="download_running" msgid="2622942231322015059">"Téléchargement..."</string>
     <string name="download_pending" msgid="2599683668575349559">"Début du téléchargement..."</string>
-    <string name="download_pending_network" msgid="6548714525679461053">"En attente d\'une connexion de données..."</string>
-    <string name="download_running_paused" msgid="6418029352085656495">"En attente d\'une connexion de données..."</string>
+    <string name="download_pending_network" msgid="6548714525679461053">"En attente de connexion de données..."</string>
+    <string name="download_running_paused" msgid="6418029352085656495">"En attente de connexion de données..."</string>
     <string name="download_canceled" msgid="6057083743144492515">"Téléchargement annulé"</string>
     <string name="download_not_acceptable" msgid="313769696131563652">"Impossible d\'effectuer le téléchargement. Le contenu n\'est pas pris en charge sur ce téléphone."</string>
     <string name="download_file_error" msgid="1206648050615176113">"Téléchargement interrompu. Espace insuffisant."</string>
diff --git a/res/values-it-rIT/donottranslate-search_engines.xml b/res/values-it-rIT/donottranslate-search_engines.xml
new file mode 100644
index 0000000..c2be0d4
--- /dev/null
+++ b/res/values-it-rIT/donottranslate-search_engines.xml
@@ -0,0 +1,32 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>ask_it</item>
+    <item>virgilio</item>
+    <item>bing_it_IT</item>
+    <item>yahoo_it</item>
+    <item>libero</item>
+  </string-array>
+</resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index f8fa172..69bcd0a 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -136,6 +136,8 @@
   </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"Apri le nuove finestre dietro la finestra corrente"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"Imposta home page"</string>
+    <string name="pref_content_search_engine" msgid="1620101310821644144">"Imposta motore di ricerca"</string>
+    <string name="pref_content_search_engine_summary" msgid="5162667665858487316">"Seleziona un motore di ricerca"</string>
     <string name="pref_use_current" msgid="1493179933653044553">"Utilizza pagina corrente"</string>
     <string name="pref_content_autofit" msgid="8260474534053660809">"Adatta autom. pagine"</string>
     <string name="pref_content_autofit_summary" msgid="4587831659894879986">"Adatta le pagine web allo schermo"</string>
@@ -243,10 +245,14 @@
     <string name="download_file_error_dlg_title" msgid="2693630283595384874">"Spazio esaurito"</string>
     <string name="download_file_error_dlg_msg" msgid="5156405410324072471">"Impossibile visualizzare <xliff:g id="FILENAME">%s</xliff:g>"\n". Libera spazio sul telefono e riprova."</string>
     <string name="download_failed_generic_dlg_title" msgid="6106781095337833391">"Download non riuscito"</string>
-    <string name="download_no_sdcard_dlg_title" msgid="605904452159416792">"Nessuna scheda SD"</string>
-    <string name="download_no_sdcard_dlg_msg" msgid="2616399456116301518">"Per scaricare <xliff:g id="FILENAME">%s</xliff:g> occorre una scheda SD."</string>
-    <string name="download_sdcard_busy_dlg_title" msgid="6877712666046917741">"Scheda SD non disponibile"</string>
-    <string name="download_sdcard_busy_dlg_msg" msgid="3473883538192835204">"La scheda SD è piena. Per consentire i download, seleziona \"Disattiva archivio USB\" nella notifica."</string>
+    <!-- outdated translation 605904452159416792 -->     <string name="download_no_sdcard_dlg_title" product="nosdcard" msgid="5349772560166195586">"Nessuna scheda SD"</string>
+    <string name="download_no_sdcard_dlg_title" product="default" msgid="605904452159416792">"Nessuna scheda SD"</string>
+    <!-- outdated translation 2616399456116301518 -->     <string name="download_no_sdcard_dlg_msg" product="nosdcard" msgid="9049052105269200675">"Per scaricare <xliff:g id="FILENAME">%s</xliff:g> occorre una scheda SD."</string>
+    <string name="download_no_sdcard_dlg_msg" product="default" msgid="2616399456116301518">"Per scaricare <xliff:g id="FILENAME">%s</xliff:g> occorre una scheda SD."</string>
+    <!-- outdated translation 6877712666046917741 -->     <string name="download_sdcard_busy_dlg_title" product="nosdcard" msgid="4151068942919670243">"Scheda SD non disponibile"</string>
+    <string name="download_sdcard_busy_dlg_title" product="default" msgid="6877712666046917741">"Scheda SD non disponibile"</string>
+    <!-- outdated translation 3473883538192835204 -->     <string name="download_sdcard_busy_dlg_msg" product="nosdcard" msgid="7297514580933657663">"La scheda SD è piena. Per consentire i download, seleziona \"Disattiva archivio USB\" nella notifica."</string>
+    <string name="download_sdcard_busy_dlg_msg" product="default" msgid="3473883538192835204">"La scheda SD è piena. Per consentire i download, seleziona \"Disattiva archivio USB\" nella notifica."</string>
     <string name="download_no_application_title" msgid="1286056729168874295">"Impossibile aprire il file"</string>
     <string name="retry" msgid="1835923075542266721">"Riprova"</string>
     <string name="no_downloads" msgid="3947445710685021498">"La cronologia download è vuota."</string>
diff --git a/res/values-ja-rJP/donottranslate-search_engines.xml b/res/values-ja-rJP/donottranslate-search_engines.xml
new file mode 100644
index 0000000..03c23f4
--- /dev/null
+++ b/res/values-ja-rJP/donottranslate-search_engines.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>yahoo_jp</item>
+    <item>bing_ja_JP</item>
+    <item>goo</item>
+  </string-array>
+</resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index b5bf052..e91c6e7 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -136,6 +136,8 @@
   </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"現在のウィンドウの後ろに新しいウィンドウを開く"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"ホームページ設定"</string>
+    <string name="pref_content_search_engine" msgid="1620101310821644144">"検索エンジンの設定"</string>
+    <string name="pref_content_search_engine_summary" msgid="5162667665858487316">"検索エンジンを選択します"</string>
     <string name="pref_use_current" msgid="1493179933653044553">"現在のページを使用"</string>
     <string name="pref_content_autofit" msgid="8260474534053660809">"ページの自動調整"</string>
     <string name="pref_content_autofit_summary" msgid="4587831659894879986">"画面に合わせてウェブページをフォーマットする"</string>
@@ -243,10 +245,14 @@
     <string name="download_file_error_dlg_title" msgid="2693630283595384874">"容量不足です"</string>
     <string name="download_file_error_dlg_msg" msgid="5156405410324072471">"<xliff:g id="FILENAME">%s</xliff:g>をダウンロードできませんでした。"\n"端末の空き領域を増やしてからやり直してください。"</string>
     <string name="download_failed_generic_dlg_title" msgid="6106781095337833391">"ダウンロードに失敗しました"</string>
-    <string name="download_no_sdcard_dlg_title" msgid="605904452159416792">"SDカードがありません"</string>
-    <string name="download_no_sdcard_dlg_msg" msgid="2616399456116301518">"<xliff:g id="FILENAME">%s</xliff:g>をダウンロードするにはSDカードが必要です。"</string>
-    <string name="download_sdcard_busy_dlg_title" msgid="6877712666046917741">"SDカードは利用できません"</string>
-    <string name="download_sdcard_busy_dlg_msg" msgid="3473883538192835204">"SDカードは使用中です。[USBストレージをOFFにする]を選択してからダウンロードしてください。"</string>
+    <!-- outdated translation 605904452159416792 -->     <string name="download_no_sdcard_dlg_title" product="nosdcard" msgid="5349772560166195586">"SDカードがありません"</string>
+    <string name="download_no_sdcard_dlg_title" product="default" msgid="605904452159416792">"SDカードがありません"</string>
+    <!-- outdated translation 2616399456116301518 -->     <string name="download_no_sdcard_dlg_msg" product="nosdcard" msgid="9049052105269200675">"<xliff:g id="FILENAME">%s</xliff:g>をダウンロードするにはSDカードが必要です。"</string>
+    <string name="download_no_sdcard_dlg_msg" product="default" msgid="2616399456116301518">"<xliff:g id="FILENAME">%s</xliff:g>をダウンロードするにはSDカードが必要です。"</string>
+    <!-- outdated translation 6877712666046917741 -->     <string name="download_sdcard_busy_dlg_title" product="nosdcard" msgid="4151068942919670243">"SDカードは利用できません"</string>
+    <string name="download_sdcard_busy_dlg_title" product="default" msgid="6877712666046917741">"SDカードは利用できません"</string>
+    <!-- outdated translation 3473883538192835204 -->     <string name="download_sdcard_busy_dlg_msg" product="nosdcard" msgid="7297514580933657663">"SDカードは使用中です。[USBストレージをOFFにする]を選択してからダウンロードしてください。"</string>
+    <string name="download_sdcard_busy_dlg_msg" product="default" msgid="3473883538192835204">"SDカードは使用中です。[USBストレージをOFFにする]を選択してからダウンロードしてください。"</string>
     <string name="download_no_application_title" msgid="1286056729168874295">"ファイルを開けません"</string>
     <string name="retry" msgid="1835923075542266721">"やり直す"</string>
     <string name="no_downloads" msgid="3947445710685021498">"ダウンロード履歴はありません。"</string>
diff --git a/res/values-ko-rKR/donottranslate-search_engines.xml b/res/values-ko-rKR/donottranslate-search_engines.xml
new file mode 100644
index 0000000..4f24631
--- /dev/null
+++ b/res/values-ko-rKR/donottranslate-search_engines.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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>naver</item>
+    <item>daum</item>
+    <item>yahoo_kr</item>
+    <item>nate</item>
+  </string-array>
+</resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index bc15b43..d7c8273 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -136,6 +136,8 @@
   </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"현재 창 뒤에 새 창 열기"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"홈페이지 설정"</string>
+    <string name="pref_content_search_engine" msgid="1620101310821644144">"검색 엔진 설정"</string>
+    <string name="pref_content_search_engine_summary" msgid="5162667665858487316">"검색 엔진 선택"</string>
     <string name="pref_use_current" msgid="1493179933653044553">"현재 페이지 사용"</string>
     <string name="pref_content_autofit" msgid="8260474534053660809">"페이지 자동 맞춤"</string>
     <string name="pref_content_autofit_summary" msgid="4587831659894879986">"화면에 맞게 웹페이지 형식 지정"</string>
@@ -243,10 +245,14 @@
     <string name="download_file_error_dlg_title" msgid="2693630283595384874">"여유 공간이 없음"</string>
     <string name="download_file_error_dlg_msg" msgid="5156405410324072471">"<xliff:g id="FILENAME">%s</xliff:g>을(를) 다운로드할 수 없습니다."\n"휴대전화에서 여유 공간을 늘린 후에 다시 시도하세요."</string>
     <string name="download_failed_generic_dlg_title" msgid="6106781095337833391">"다운로드 실패"</string>
-    <string name="download_no_sdcard_dlg_title" msgid="605904452159416792">"SD 카드 없음"</string>
-    <string name="download_no_sdcard_dlg_msg" msgid="2616399456116301518">"<xliff:g id="FILENAME">%s</xliff:g>을(를) 다운로드하려면 SD 카드가 필요합니다."</string>
-    <string name="download_sdcard_busy_dlg_title" msgid="6877712666046917741">"SD 카드를 사용할 수 없음"</string>
-    <string name="download_sdcard_busy_dlg_msg" msgid="3473883538192835204">"SD 카드가 사용 중입니다. 다운로드를 허용하려면 알림에서 \'USB 저장소 끄기\'를 선택하세요."</string>
+    <!-- outdated translation 605904452159416792 -->     <string name="download_no_sdcard_dlg_title" product="nosdcard" msgid="5349772560166195586">"SD 카드 없음"</string>
+    <string name="download_no_sdcard_dlg_title" product="default" msgid="605904452159416792">"SD 카드 없음"</string>
+    <!-- outdated translation 2616399456116301518 -->     <string name="download_no_sdcard_dlg_msg" product="nosdcard" msgid="9049052105269200675">"<xliff:g id="FILENAME">%s</xliff:g>을(를) 다운로드하려면 SD 카드가 필요합니다."</string>
+    <string name="download_no_sdcard_dlg_msg" product="default" msgid="2616399456116301518">"<xliff:g id="FILENAME">%s</xliff:g>을(를) 다운로드하려면 SD 카드가 필요합니다."</string>
+    <!-- outdated translation 6877712666046917741 -->     <string name="download_sdcard_busy_dlg_title" product="nosdcard" msgid="4151068942919670243">"SD 카드를 사용할 수 없음"</string>
+    <string name="download_sdcard_busy_dlg_title" product="default" msgid="6877712666046917741">"SD 카드를 사용할 수 없음"</string>
+    <!-- outdated translation 3473883538192835204 -->     <string name="download_sdcard_busy_dlg_msg" product="nosdcard" msgid="7297514580933657663">"SD 카드가 사용 중입니다. 다운로드를 허용하려면 알림에서 \'USB 저장소 끄기\'를 선택하세요."</string>
+    <string name="download_sdcard_busy_dlg_msg" product="default" msgid="3473883538192835204">"SD 카드가 사용 중입니다. 다운로드를 허용하려면 알림에서 \'USB 저장소 끄기\'를 선택하세요."</string>
     <string name="download_no_application_title" msgid="1286056729168874295">"파일을 열 수 없음"</string>
     <string name="retry" msgid="1835923075542266721">"다시 시도"</string>
     <string name="no_downloads" msgid="3947445710685021498">"다운로드 기록이 비어 있습니다."</string>
diff --git a/res/values-nb-rNO/donottranslate-search_engines.xml b/res/values-nb-rNO/donottranslate-search_engines.xml
new file mode 100644
index 0000000..418f6d2
--- /dev/null
+++ b/res/values-nb-rNO/donottranslate-search_engines.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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>bing_nb_NO</item>
+    <item>abcsok</item>
+    <item>yahoo_no</item>
+    <item>kvasir</item>
+  </string-array>
+</resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index f1341cf..d123c39 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -136,6 +136,8 @@
   </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"Nye vinduer åpnes bak det gjeldende"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"Angi startside"</string>
+    <string name="pref_content_search_engine" msgid="1620101310821644144">"Angi søkemotor"</string>
+    <string name="pref_content_search_engine_summary" msgid="5162667665858487316">"Velg en søkemotor"</string>
     <string name="pref_use_current" msgid="1493179933653044553">"Bruk nåværende side"</string>
     <string name="pref_content_autofit" msgid="8260474534053660809">"Tilpass sider automatisk"</string>
     <string name="pref_content_autofit_summary" msgid="4587831659894879986">"Tilpass nettsteder til skjermen"</string>
@@ -243,10 +245,14 @@
     <string name="download_file_error_dlg_title" msgid="2693630283595384874">"Tom for plass"</string>
     <string name="download_file_error_dlg_msg" msgid="5156405410324072471">"Kan ikke laste ned <xliff:g id="FILENAME">%s</xliff:g>."\n"Frigjør plass på telefonen og prøv på nytt."</string>
     <string name="download_failed_generic_dlg_title" msgid="6106781095337833391">"Nedlasting mislykket"</string>
-    <string name="download_no_sdcard_dlg_title" msgid="605904452159416792">"Mangler minnekort"</string>
-    <string name="download_no_sdcard_dlg_msg" msgid="2616399456116301518">"Du trenger et minnekort for å laste ned <xliff:g id="FILENAME">%s</xliff:g>."</string>
-    <string name="download_sdcard_busy_dlg_title" msgid="6877712666046917741">"Minnekort utilgjengelig"</string>
-    <string name="download_sdcard_busy_dlg_msg" msgid="3473883538192835204">"Minnekortet er opptatt. For å tillate nedlasting, velg \"Slå av USB-lagring\" i varslingen."</string>
+    <!-- outdated translation 605904452159416792 -->     <string name="download_no_sdcard_dlg_title" product="nosdcard" msgid="5349772560166195586">"Mangler minnekort"</string>
+    <string name="download_no_sdcard_dlg_title" product="default" msgid="605904452159416792">"Mangler minnekort"</string>
+    <!-- outdated translation 2616399456116301518 -->     <string name="download_no_sdcard_dlg_msg" product="nosdcard" msgid="9049052105269200675">"Du trenger et minnekort for å laste ned <xliff:g id="FILENAME">%s</xliff:g>."</string>
+    <string name="download_no_sdcard_dlg_msg" product="default" msgid="2616399456116301518">"Du trenger et minnekort for å laste ned <xliff:g id="FILENAME">%s</xliff:g>."</string>
+    <!-- outdated translation 6877712666046917741 -->     <string name="download_sdcard_busy_dlg_title" product="nosdcard" msgid="4151068942919670243">"Minnekort utilgjengelig"</string>
+    <string name="download_sdcard_busy_dlg_title" product="default" msgid="6877712666046917741">"Minnekort utilgjengelig"</string>
+    <!-- outdated translation 3473883538192835204 -->     <string name="download_sdcard_busy_dlg_msg" product="nosdcard" msgid="7297514580933657663">"Minnekortet er opptatt. For å tillate nedlasting, velg \"Slå av USB-lagring\" i varslingen."</string>
+    <string name="download_sdcard_busy_dlg_msg" product="default" msgid="3473883538192835204">"Minnekortet er opptatt. For å tillate nedlasting, velg \"Slå av USB-lagring\" i varslingen."</string>
     <string name="download_no_application_title" msgid="1286056729168874295">"Får ikke åpnet filen"</string>
     <string name="retry" msgid="1835923075542266721">"Prøv igjen"</string>
     <string name="no_downloads" msgid="3947445710685021498">"Nedlastingsloggen er tom."</string>
diff --git a/res/values-nl-rBE/donottranslate-search_engines.xml b/res/values-nl-rBE/donottranslate-search_engines.xml
new file mode 100644
index 0000000..d743fc0
--- /dev/null
+++ b/res/values-nl-rBE/donottranslate-search_engines.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>bing_nl_BE</item>
+    <item>yahoo</item>
+    <item>bing_fr_BE</item>
+  </string-array>
+</resources>
diff --git a/res/values-nl-rNL/donottranslate-search_engines.xml b/res/values-nl-rNL/donottranslate-search_engines.xml
new file mode 100644
index 0000000..b9c1b40
--- /dev/null
+++ b/res/values-nl-rNL/donottranslate-search_engines.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>bing_nl_NL</item>
+    <item>yahoo_nl</item>
+    <item>ask_nl</item>
+  </string-array>
+</resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 5a2eb1b..dab30c9 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -136,6 +136,8 @@
   </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"Nieuwe vensters openen achter het huidige venster"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"Startpagina instellen"</string>
+    <string name="pref_content_search_engine" msgid="1620101310821644144">"Zoekmachine instellen"</string>
+    <string name="pref_content_search_engine_summary" msgid="5162667665858487316">"Selecteer een zoekmachine"</string>
     <string name="pref_use_current" msgid="1493179933653044553">"Huidige pagina gebruiken"</string>
     <string name="pref_content_autofit" msgid="8260474534053660809">"Pagina\'s passend maken"</string>
     <string name="pref_content_autofit_summary" msgid="4587831659894879986">"Webpagina\'s zo indelen dat deze op het scherm passen"</string>
@@ -243,10 +245,14 @@
     <string name="download_file_error_dlg_title" msgid="2693630283595384874">"Geen ruimte meer"</string>
     <string name="download_file_error_dlg_msg" msgid="5156405410324072471">"<xliff:g id="FILENAME">%s</xliff:g> kan niet worden gedownload."\n"Maak ruimte vrij op uw telefoon en probeer het opnieuw."</string>
     <string name="download_failed_generic_dlg_title" msgid="6106781095337833391">"Downloaden is mislukt."</string>
-    <string name="download_no_sdcard_dlg_title" msgid="605904452159416792">"Geen SD-kaart"</string>
-    <string name="download_no_sdcard_dlg_msg" msgid="2616399456116301518">"Een SD-kaart is vereist om <xliff:g id="FILENAME">%s</xliff:g> te kunnen downloaden."</string>
-    <string name="download_sdcard_busy_dlg_title" msgid="6877712666046917741">"SD-kaart niet beschikbaar"</string>
-    <string name="download_sdcard_busy_dlg_msg" msgid="3473883538192835204">"De SD-kaart wordt gebruikt. Als u downloads wilt toestaan, selecteert u \'USB-opslag uitschakelen\' in de melding."</string>
+    <!-- outdated translation 605904452159416792 -->     <string name="download_no_sdcard_dlg_title" product="nosdcard" msgid="5349772560166195586">"Geen SD-kaart"</string>
+    <string name="download_no_sdcard_dlg_title" product="default" msgid="605904452159416792">"Geen SD-kaart"</string>
+    <!-- outdated translation 2616399456116301518 -->     <string name="download_no_sdcard_dlg_msg" product="nosdcard" msgid="9049052105269200675">"Een SD-kaart is vereist om <xliff:g id="FILENAME">%s</xliff:g> te kunnen downloaden."</string>
+    <string name="download_no_sdcard_dlg_msg" product="default" msgid="2616399456116301518">"Een SD-kaart is vereist om <xliff:g id="FILENAME">%s</xliff:g> te kunnen downloaden."</string>
+    <!-- outdated translation 6877712666046917741 -->     <string name="download_sdcard_busy_dlg_title" product="nosdcard" msgid="4151068942919670243">"SD-kaart niet beschikbaar"</string>
+    <string name="download_sdcard_busy_dlg_title" product="default" msgid="6877712666046917741">"SD-kaart niet beschikbaar"</string>
+    <!-- outdated translation 3473883538192835204 -->     <string name="download_sdcard_busy_dlg_msg" product="nosdcard" msgid="7297514580933657663">"De SD-kaart wordt gebruikt. Als u downloads wilt toestaan, selecteert u \'USB-opslag uitschakelen\' in de melding."</string>
+    <string name="download_sdcard_busy_dlg_msg" product="default" msgid="3473883538192835204">"De SD-kaart wordt gebruikt. Als u downloads wilt toestaan, selecteert u \'USB-opslag uitschakelen\' in de melding."</string>
     <string name="download_no_application_title" msgid="1286056729168874295">"Kan bestand niet openen"</string>
     <string name="retry" msgid="1835923075542266721">"Opnieuw proberen"</string>
     <string name="no_downloads" msgid="3947445710685021498">"Downloadgeschiedenis is leeg."</string>
diff --git a/res/values-pl-rPL/donottranslate-search_engines.xml b/res/values-pl-rPL/donottranslate-search_engines.xml
new file mode 100644
index 0000000..ddc262e
--- /dev/null
+++ b/res/values-pl-rPL/donottranslate-search_engines.xml
@@ -0,0 +1,32 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>bing_pl_PL</item>
+    <item>netsprint</item>
+    <item>yahoo_uk</item>
+    <item>onet</item>
+    <item>wp</item>
+  </string-array>
+</resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index a4ccc11..3090ce0 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -136,6 +136,8 @@
   </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"Otwieraj nowe okna za bieżącym"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"Ustaw stronę główną"</string>
+    <string name="pref_content_search_engine" msgid="1620101310821644144">"Ustaw wyszukiwarkę"</string>
+    <string name="pref_content_search_engine_summary" msgid="5162667665858487316">"Wybierz wyszukiwarkę"</string>
     <string name="pref_use_current" msgid="1493179933653044553">"Użyj bieżącej strony"</string>
     <string name="pref_content_autofit" msgid="8260474534053660809">"Autodopasowanie stron"</string>
     <string name="pref_content_autofit_summary" msgid="4587831659894879986">"Formatuj strony internetowe w celu dopasowania do ekranu"</string>
@@ -243,10 +245,14 @@
     <string name="download_file_error_dlg_title" msgid="2693630283595384874">"Brak miejsca"</string>
     <string name="download_file_error_dlg_msg" msgid="5156405410324072471">"Nie można pobrać pliku <xliff:g id="FILENAME">%s</xliff:g>."\n" Zwolnij trochę miejsca w telefonie i spróbuj ponownie."</string>
     <string name="download_failed_generic_dlg_title" msgid="6106781095337833391">"Pobieranie nie powiodło się"</string>
-    <string name="download_no_sdcard_dlg_title" msgid="605904452159416792">"Brak karty SD"</string>
-    <string name="download_no_sdcard_dlg_msg" msgid="2616399456116301518">"Do pobrania pliku <xliff:g id="FILENAME">%s</xliff:g> potrzebna jest karta SD."</string>
-    <string name="download_sdcard_busy_dlg_title" msgid="6877712666046917741">"Karta SD jest niedostępna"</string>
-    <string name="download_sdcard_busy_dlg_msg" msgid="3473883538192835204">"Karta SD jest zajęta. Aby umożliwić pobieranie, wybierz w powiadomieniu opcję „Wyłącz nośnik USB”."</string>
+    <!-- outdated translation 605904452159416792 -->     <string name="download_no_sdcard_dlg_title" product="nosdcard" msgid="5349772560166195586">"Brak karty SD"</string>
+    <string name="download_no_sdcard_dlg_title" product="default" msgid="605904452159416792">"Brak karty SD"</string>
+    <!-- outdated translation 2616399456116301518 -->     <string name="download_no_sdcard_dlg_msg" product="nosdcard" msgid="9049052105269200675">"Do pobrania pliku <xliff:g id="FILENAME">%s</xliff:g> potrzebna jest karta SD."</string>
+    <string name="download_no_sdcard_dlg_msg" product="default" msgid="2616399456116301518">"Do pobrania pliku <xliff:g id="FILENAME">%s</xliff:g> potrzebna jest karta SD."</string>
+    <!-- outdated translation 6877712666046917741 -->     <string name="download_sdcard_busy_dlg_title" product="nosdcard" msgid="4151068942919670243">"Karta SD jest niedostępna"</string>
+    <string name="download_sdcard_busy_dlg_title" product="default" msgid="6877712666046917741">"Karta SD jest niedostępna"</string>
+    <!-- outdated translation 3473883538192835204 -->     <string name="download_sdcard_busy_dlg_msg" product="nosdcard" msgid="7297514580933657663">"Karta SD jest zajęta. Aby umożliwić pobieranie, wybierz w powiadomieniu opcję „Wyłącz nośnik USB”."</string>
+    <string name="download_sdcard_busy_dlg_msg" product="default" msgid="3473883538192835204">"Karta SD jest zajęta. Aby umożliwić pobieranie, wybierz w powiadomieniu opcję „Wyłącz nośnik USB”."</string>
     <string name="download_no_application_title" msgid="1286056729168874295">"Nie można otworzyć pliku"</string>
     <string name="retry" msgid="1835923075542266721">"Spróbuj ponownie"</string>
     <string name="no_downloads" msgid="3947445710685021498">"Historia pobierania jest pusta."</string>
diff --git a/res/values-pt-rBR/donottranslate-search_engines.xml b/res/values-pt-rBR/donottranslate-search_engines.xml
new file mode 100644
index 0000000..56cda34
--- /dev/null
+++ b/res/values-pt-rBR/donottranslate-search_engines.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>bing_pt_BR</item>
+    <item>yahoo_br</item>
+    <item>uol</item>
+  </string-array>
+</resources>
diff --git a/res/values-pt-rPT/donottranslate-search_engines.xml b/res/values-pt-rPT/donottranslate-search_engines.xml
new file mode 100644
index 0000000..3780d73
--- /dev/null
+++ b/res/values-pt-rPT/donottranslate-search_engines.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>sapo</item>
+    <item>bing_pt_PT</item>
+    <item>yahoo</item>
+  </string-array>
+</resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index dd3bc92..17bdb48 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -136,6 +136,8 @@
   </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"Abrir novas janelas atrás da actual"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"Definir página inicial"</string>
+    <string name="pref_content_search_engine" msgid="1620101310821644144">"Definir motor de pesquisa"</string>
+    <string name="pref_content_search_engine_summary" msgid="5162667665858487316">"Seleccionar um motor de pesquisa"</string>
     <string name="pref_use_current" msgid="1493179933653044553">"Utilizar página actual"</string>
     <string name="pref_content_autofit" msgid="8260474534053660809">"Ajuste auto de páginas"</string>
     <string name="pref_content_autofit_summary" msgid="4587831659894879986">"Formatar páginas Web para se ajustarem ao ecrã"</string>
@@ -243,10 +245,14 @@
     <string name="download_file_error_dlg_title" msgid="2693630283595384874">"Sem espaço"</string>
     <string name="download_file_error_dlg_msg" msgid="5156405410324072471">"Não foi possível transferir <xliff:g id="FILENAME">%s</xliff:g>. "\n"Liberte algum espaço no telefone e tente novamente."</string>
     <string name="download_failed_generic_dlg_title" msgid="6106781095337833391">"Falha na transferência"</string>
-    <string name="download_no_sdcard_dlg_title" msgid="605904452159416792">"Sem cartão SD"</string>
-    <string name="download_no_sdcard_dlg_msg" msgid="2616399456116301518">"É necessário um cartão SD para transferir <xliff:g id="FILENAME">%s</xliff:g>."</string>
-    <string name="download_sdcard_busy_dlg_title" msgid="6877712666046917741">"Cartão SD não disponível"</string>
-    <string name="download_sdcard_busy_dlg_msg" msgid="3473883538192835204">"O cartão SD está ocupado. Para permitir as transferências, seleccione \"Desactivar armazenamento USB\" na notificação."</string>
+    <!-- outdated translation 605904452159416792 -->     <string name="download_no_sdcard_dlg_title" product="nosdcard" msgid="5349772560166195586">"Sem cartão SD"</string>
+    <string name="download_no_sdcard_dlg_title" product="default" msgid="605904452159416792">"Sem cartão SD"</string>
+    <!-- outdated translation 2616399456116301518 -->     <string name="download_no_sdcard_dlg_msg" product="nosdcard" msgid="9049052105269200675">"É necessário um cartão SD para transferir <xliff:g id="FILENAME">%s</xliff:g>."</string>
+    <string name="download_no_sdcard_dlg_msg" product="default" msgid="2616399456116301518">"É necessário um cartão SD para transferir <xliff:g id="FILENAME">%s</xliff:g>."</string>
+    <!-- outdated translation 6877712666046917741 -->     <string name="download_sdcard_busy_dlg_title" product="nosdcard" msgid="4151068942919670243">"Cartão SD não disponível"</string>
+    <string name="download_sdcard_busy_dlg_title" product="default" msgid="6877712666046917741">"Cartão SD não disponível"</string>
+    <!-- outdated translation 3473883538192835204 -->     <string name="download_sdcard_busy_dlg_msg" product="nosdcard" msgid="7297514580933657663">"O cartão SD está ocupado. Para permitir as transferências, seleccione \"Desactivar armazenamento USB\" na notificação."</string>
+    <string name="download_sdcard_busy_dlg_msg" product="default" msgid="3473883538192835204">"O cartão SD está ocupado. Para permitir as transferências, seleccione \"Desactivar armazenamento USB\" na notificação."</string>
     <string name="download_no_application_title" msgid="1286056729168874295">"Não é possível abrir o ficheiro"</string>
     <string name="retry" msgid="1835923075542266721">"Tentar novamente"</string>
     <string name="no_downloads" msgid="3947445710685021498">"O histórico de transferências está vazio."</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index fde123d..0f7e4fd 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -136,6 +136,8 @@
   </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"Abrir novas janelas atrás da janela atual"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"Definir a página inicial"</string>
+    <string name="pref_content_search_engine" msgid="1620101310821644144">"Definir mecanismo de pesquisa"</string>
+    <string name="pref_content_search_engine_summary" msgid="5162667665858487316">"Selecionar um mecanismo de pesquisa"</string>
     <string name="pref_use_current" msgid="1493179933653044553">"Usar a página atual"</string>
     <string name="pref_content_autofit" msgid="8260474534053660809">"Ajustar automaticamente"</string>
     <string name="pref_content_autofit_summary" msgid="4587831659894879986">"Formatar páginas da web para se ajustarem à tela"</string>
@@ -243,10 +245,14 @@
     <string name="download_file_error_dlg_title" msgid="2693630283595384874">"Sem espaço"</string>
     <string name="download_file_error_dlg_msg" msgid="5156405410324072471">"Não foi possível fazer o download do <xliff:g id="FILENAME">%s</xliff:g>."\n"Libere espaço no seu telefone e tente novamente."</string>
     <string name="download_failed_generic_dlg_title" msgid="6106781095337833391">"Falha no download"</string>
-    <string name="download_no_sdcard_dlg_title" msgid="605904452159416792">"Nenhum cartão SD disponível"</string>
-    <string name="download_no_sdcard_dlg_msg" msgid="2616399456116301518">"Um cartão SD é solicitado para fazer download do <xliff:g id="FILENAME">%s</xliff:g>."</string>
-    <string name="download_sdcard_busy_dlg_title" msgid="6877712666046917741">"Cartão SD não disponível"</string>
-    <string name="download_sdcard_busy_dlg_msg" msgid="3473883538192835204">"O cartão SD está ocupado. Para permitir downloads, selecione \"Desativar armazenamento USB\" na notificação."</string>
+    <!-- outdated translation 605904452159416792 -->     <string name="download_no_sdcard_dlg_title" product="nosdcard" msgid="5349772560166195586">"Nenhum cartão SD disponível"</string>
+    <string name="download_no_sdcard_dlg_title" product="default" msgid="605904452159416792">"Nenhum cartão SD disponível"</string>
+    <!-- outdated translation 2616399456116301518 -->     <string name="download_no_sdcard_dlg_msg" product="nosdcard" msgid="9049052105269200675">"Um cartão SD é solicitado para fazer download do <xliff:g id="FILENAME">%s</xliff:g>."</string>
+    <string name="download_no_sdcard_dlg_msg" product="default" msgid="2616399456116301518">"Um cartão SD é solicitado para fazer download do <xliff:g id="FILENAME">%s</xliff:g>."</string>
+    <!-- outdated translation 6877712666046917741 -->     <string name="download_sdcard_busy_dlg_title" product="nosdcard" msgid="4151068942919670243">"Cartão SD não disponível"</string>
+    <string name="download_sdcard_busy_dlg_title" product="default" msgid="6877712666046917741">"Cartão SD não disponível"</string>
+    <!-- outdated translation 3473883538192835204 -->     <string name="download_sdcard_busy_dlg_msg" product="nosdcard" msgid="7297514580933657663">"O cartão SD está ocupado. Para permitir downloads, selecione \"Desativar armazenamento USB\" na notificação."</string>
+    <string name="download_sdcard_busy_dlg_msg" product="default" msgid="3473883538192835204">"O cartão SD está ocupado. Para permitir downloads, selecione \"Desativar armazenamento USB\" na notificação."</string>
     <string name="download_no_application_title" msgid="1286056729168874295">"Não é possível abrir o arquivo."</string>
     <string name="retry" msgid="1835923075542266721">"Tentar novamente"</string>
     <string name="no_downloads" msgid="3947445710685021498">"O histórico de downloads está vazio."</string>
diff --git a/res/values-ru-rRU/donottranslate-search_engines.xml b/res/values-ru-rRU/donottranslate-search_engines.xml
new file mode 100644
index 0000000..80ff214
--- /dev/null
+++ b/res/values-ru-rRU/donottranslate-search_engines.xml
@@ -0,0 +1,32 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>yandex_ru</item>
+    <item>mail_ru</item>
+    <item>tut</item>
+    <item>rambler</item>
+    <item>bing_ru_RU</item>
+  </string-array>
+</resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index b976eeb..f57f1f7 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -62,7 +62,7 @@
     <string name="expires_on" msgid="8061200430557020704">"Дата окончания действия:"</string>
     <string name="stopping" msgid="4839698519340302982">"Остановка..."</string>
     <string name="stop" msgid="5687251076030630074">"Стоп"</string>
-    <string name="reload" msgid="8585220783228408062">"Обновление"</string>
+    <string name="reload" msgid="8585220783228408062">"Обновить"</string>
     <string name="back" msgid="8414603107175713668">"Назад"</string>
     <string name="forward" msgid="4288210890526641577">"Вперед"</string>
     <string name="save" msgid="5922311934992468496">"ОК"</string>
@@ -136,6 +136,8 @@
   </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"Открывать новые окна позади текущего окна"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"Домашняя страница"</string>
+    <string name="pref_content_search_engine" msgid="1620101310821644144">"Поисковая система"</string>
+    <string name="pref_content_search_engine_summary" msgid="5162667665858487316">"Выберите поисковую систему"</string>
     <string name="pref_use_current" msgid="1493179933653044553">"Использовать текущую страницу"</string>
     <string name="pref_content_autofit" msgid="8260474534053660809">"Мобильный вид"</string>
     <string name="pref_content_autofit_summary" msgid="4587831659894879986">"Адаптировать контент к размеру экрана мобильного устройства"</string>
@@ -243,10 +245,14 @@
     <string name="download_file_error_dlg_title" msgid="2693630283595384874">"Недостаточно места"</string>
     <string name="download_file_error_dlg_msg" msgid="5156405410324072471">"Невозможно загрузить <xliff:g id="FILENAME">%s</xliff:g>."\n"Освободите место в памяти телефона и повторите попытку."</string>
     <string name="download_failed_generic_dlg_title" msgid="6106781095337833391">"Ошибка загрузки"</string>
-    <string name="download_no_sdcard_dlg_title" msgid="605904452159416792">"SD-карта отсутствует"</string>
-    <string name="download_no_sdcard_dlg_msg" msgid="2616399456116301518">"Для загрузки <xliff:g id="FILENAME">%s</xliff:g> необходима SD-карта."</string>
-    <string name="download_sdcard_busy_dlg_title" msgid="6877712666046917741">"SD-карта недоступна"</string>
-    <string name="download_sdcard_busy_dlg_msg" msgid="3473883538192835204">"Карта SD занята. Чтобы разрешить загрузки, выберите \"Выключить USB-накопитель\" в уведомлении."</string>
+    <!-- outdated translation 605904452159416792 -->     <string name="download_no_sdcard_dlg_title" product="nosdcard" msgid="5349772560166195586">"SD-карта отсутствует"</string>
+    <string name="download_no_sdcard_dlg_title" product="default" msgid="605904452159416792">"SD-карта отсутствует"</string>
+    <!-- outdated translation 2616399456116301518 -->     <string name="download_no_sdcard_dlg_msg" product="nosdcard" msgid="9049052105269200675">"Для загрузки <xliff:g id="FILENAME">%s</xliff:g> необходима SD-карта."</string>
+    <string name="download_no_sdcard_dlg_msg" product="default" msgid="2616399456116301518">"Для загрузки <xliff:g id="FILENAME">%s</xliff:g> необходима SD-карта."</string>
+    <!-- outdated translation 6877712666046917741 -->     <string name="download_sdcard_busy_dlg_title" product="nosdcard" msgid="4151068942919670243">"SD-карта недоступна"</string>
+    <string name="download_sdcard_busy_dlg_title" product="default" msgid="6877712666046917741">"SD-карта недоступна"</string>
+    <!-- outdated translation 3473883538192835204 -->     <string name="download_sdcard_busy_dlg_msg" product="nosdcard" msgid="7297514580933657663">"Карта SD занята. Чтобы разрешить загрузки, выберите \"Выключить USB-накопитель\" в уведомлении."</string>
+    <string name="download_sdcard_busy_dlg_msg" product="default" msgid="3473883538192835204">"Карта SD занята. Чтобы разрешить загрузки, выберите \"Выключить USB-накопитель\" в уведомлении."</string>
     <string name="download_no_application_title" msgid="1286056729168874295">"Невозможно открыть файл"</string>
     <string name="retry" msgid="1835923075542266721">"Повторить попытку"</string>
     <string name="no_downloads" msgid="3947445710685021498">"История загрузок пуста."</string>
diff --git a/res/values-sv-rSE/donottranslate-search_engines.xml b/res/values-sv-rSE/donottranslate-search_engines.xml
new file mode 100644
index 0000000..f216357
--- /dev/null
+++ b/res/values-sv-rSE/donottranslate-search_engines.xml
@@ -0,0 +1,32 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>bing_sv_SE</item>
+    <item>yahoo_se</item>
+    <item>altavista_se</item>
+    <item>spray</item>
+    <item>eniro_se</item>
+  </string-array>
+</resources>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index b4dafb1..e085938 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -136,6 +136,8 @@
   </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"Öppna nya fönster bakom det aktiva"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"Ange startsida"</string>
+    <string name="pref_content_search_engine" msgid="1620101310821644144">"Ange sökmotor"</string>
+    <string name="pref_content_search_engine_summary" msgid="5162667665858487316">"Välj en sökmotor"</string>
     <string name="pref_use_current" msgid="1493179933653044553">"Använd aktuell sida"</string>
     <string name="pref_content_autofit" msgid="8260474534053660809">"Autoanpassa sidor"</string>
     <string name="pref_content_autofit_summary" msgid="4587831659894879986">"Anpassa webbsidor efter skärmen"</string>
@@ -243,10 +245,14 @@
     <string name="download_file_error_dlg_title" msgid="2693630283595384874">"Slut på ledigt diskutrymme"</string>
     <string name="download_file_error_dlg_msg" msgid="5156405410324072471">"<xliff:g id="FILENAME">%s</xliff:g> gick inte att hämta."\n"Frigör lite utrymme i telefonen och försök igen."</string>
     <string name="download_failed_generic_dlg_title" msgid="6106781095337833391">"Det gick inte att hämta"</string>
-    <string name="download_no_sdcard_dlg_title" msgid="605904452159416792">"Inget SD-kort"</string>
-    <string name="download_no_sdcard_dlg_msg" msgid="2616399456116301518">"Du behöver ett SD-kort för att hämta <xliff:g id="FILENAME">%s</xliff:g>."</string>
-    <string name="download_sdcard_busy_dlg_title" msgid="6877712666046917741">"SD-kortet är inte tillgängligt"</string>
-    <string name="download_sdcard_busy_dlg_msg" msgid="3473883538192835204">"SD-kortet är upptaget. Om du vill tillåta hämtning väljer du Inaktivera USB-lagring i meddelandet."</string>
+    <!-- outdated translation 605904452159416792 -->     <string name="download_no_sdcard_dlg_title" product="nosdcard" msgid="5349772560166195586">"Inget SD-kort"</string>
+    <string name="download_no_sdcard_dlg_title" product="default" msgid="605904452159416792">"Inget SD-kort"</string>
+    <!-- outdated translation 2616399456116301518 -->     <string name="download_no_sdcard_dlg_msg" product="nosdcard" msgid="9049052105269200675">"Du behöver ett SD-kort för att hämta <xliff:g id="FILENAME">%s</xliff:g>."</string>
+    <string name="download_no_sdcard_dlg_msg" product="default" msgid="2616399456116301518">"Du behöver ett SD-kort för att hämta <xliff:g id="FILENAME">%s</xliff:g>."</string>
+    <!-- outdated translation 6877712666046917741 -->     <string name="download_sdcard_busy_dlg_title" product="nosdcard" msgid="4151068942919670243">"SD-kortet är inte tillgängligt"</string>
+    <string name="download_sdcard_busy_dlg_title" product="default" msgid="6877712666046917741">"SD-kortet är inte tillgängligt"</string>
+    <!-- outdated translation 3473883538192835204 -->     <string name="download_sdcard_busy_dlg_msg" product="nosdcard" msgid="7297514580933657663">"SD-kortet är upptaget. Om du vill tillåta hämtning väljer du Inaktivera USB-lagring i meddelandet."</string>
+    <string name="download_sdcard_busy_dlg_msg" product="default" msgid="3473883538192835204">"SD-kortet är upptaget. Om du vill tillåta hämtning väljer du Inaktivera USB-lagring i meddelandet."</string>
     <string name="download_no_application_title" msgid="1286056729168874295">"Det går inte att öppna filen"</string>
     <string name="retry" msgid="1835923075542266721">"Försök igen"</string>
     <string name="no_downloads" msgid="3947445710685021498">"Det finns ingen hämtningshistorik."</string>
diff --git a/res/values-tr-rTR/donottranslate-search_engines.xml b/res/values-tr-rTR/donottranslate-search_engines.xml
new file mode 100644
index 0000000..06cdb12
--- /dev/null
+++ b/res/values-tr-rTR/donottranslate-search_engines.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>bing_tr_TR</item>
+    <item>yahoo</item>
+    <item>mynet</item>
+  </string-array>
+</resources>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 8f0826c..2b29ac8 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -136,6 +136,8 @@
   </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"Geçerli pencerenin arkasında yeni pencereler aç"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"Ana sayfayı ayarla"</string>
+    <string name="pref_content_search_engine" msgid="1620101310821644144">"Arama motoru ayarlayın"</string>
+    <string name="pref_content_search_engine_summary" msgid="5162667665858487316">"Arama moturu seçin"</string>
     <string name="pref_use_current" msgid="1493179933653044553">"Geçerli sayfayı kullan"</string>
     <string name="pref_content_autofit" msgid="8260474534053660809">"Sayfaları otomatik sığdır"</string>
     <string name="pref_content_autofit_summary" msgid="4587831659894879986">"Web sayfalarını ekrana sığacak şekilde biçimlendir"</string>
@@ -243,10 +245,14 @@
     <string name="download_file_error_dlg_title" msgid="2693630283595384874">"Alan yetersiz"</string>
     <string name="download_file_error_dlg_msg" msgid="5156405410324072471">"<xliff:g id="FILENAME">%s</xliff:g> indirilemedi."\n"Telefonunuzda biraz yer açın ve tekrar deneyin."</string>
     <string name="download_failed_generic_dlg_title" msgid="6106781095337833391">"İndirme işlemi başarısız"</string>
-    <string name="download_no_sdcard_dlg_title" msgid="605904452159416792">"SD kart yok"</string>
-    <string name="download_no_sdcard_dlg_msg" msgid="2616399456116301518">"<xliff:g id="FILENAME">%s</xliff:g> dosyasını indirmek için bir SD kart gerekli."</string>
-    <string name="download_sdcard_busy_dlg_title" msgid="6877712666046917741">"SD kart kullanılamıyor"</string>
-    <string name="download_sdcard_busy_dlg_msg" msgid="3473883538192835204">"SD kart meşgul. İndirme işlemlerine izin vermek için bildirim alanında \"USB\'de depolamayı kapat\"ı seçin."</string>
+    <!-- outdated translation 605904452159416792 -->     <string name="download_no_sdcard_dlg_title" product="nosdcard" msgid="5349772560166195586">"SD kart yok"</string>
+    <string name="download_no_sdcard_dlg_title" product="default" msgid="605904452159416792">"SD kart yok"</string>
+    <!-- outdated translation 2616399456116301518 -->     <string name="download_no_sdcard_dlg_msg" product="nosdcard" msgid="9049052105269200675">"<xliff:g id="FILENAME">%s</xliff:g> dosyasını indirmek için bir SD kart gerekli."</string>
+    <string name="download_no_sdcard_dlg_msg" product="default" msgid="2616399456116301518">"<xliff:g id="FILENAME">%s</xliff:g> dosyasını indirmek için bir SD kart gerekli."</string>
+    <!-- outdated translation 6877712666046917741 -->     <string name="download_sdcard_busy_dlg_title" product="nosdcard" msgid="4151068942919670243">"SD kart kullanılamıyor"</string>
+    <string name="download_sdcard_busy_dlg_title" product="default" msgid="6877712666046917741">"SD kart kullanılamıyor"</string>
+    <!-- outdated translation 3473883538192835204 -->     <string name="download_sdcard_busy_dlg_msg" product="nosdcard" msgid="7297514580933657663">"SD kart meşgul. İndirme işlemlerine izin vermek için bildirim alanında \"USB\'de depolamayı kapat\"ı seçin."</string>
+    <string name="download_sdcard_busy_dlg_msg" product="default" msgid="3473883538192835204">"SD kart meşgul. İndirme işlemlerine izin vermek için bildirim alanında \"USB\'de depolamayı kapat\"ı seçin."</string>
     <string name="download_no_application_title" msgid="1286056729168874295">"Dosya açılamıyor"</string>
     <string name="retry" msgid="1835923075542266721">"Tekrar Dene"</string>
     <string name="no_downloads" msgid="3947445710685021498">"İndirme geçmişi boş."</string>
diff --git a/res/values-zh-rCN/donottranslate-search_engines.xml b/res/values-zh-rCN/donottranslate-search_engines.xml
new file mode 100644
index 0000000..c38055c
--- /dev/null
+++ b/res/values-zh-rCN/donottranslate-search_engines.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>baidu</item>
+    <item>yahoo_cn</item>
+    <item>bing_zh_CN</item>
+  </string-array>
+</resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index a315f10..d218cd3 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -136,6 +136,8 @@
   </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"在当前窗口后方打开新窗口"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"设置主页"</string>
+    <string name="pref_content_search_engine" msgid="1620101310821644144">"设置搜索引擎"</string>
+    <string name="pref_content_search_engine_summary" msgid="5162667665858487316">"选择搜索引擎"</string>
     <string name="pref_use_current" msgid="1493179933653044553">"使用当前页面"</string>
     <string name="pref_content_autofit" msgid="8260474534053660809">"自动调整页面"</string>
     <string name="pref_content_autofit_summary" msgid="4587831659894879986">"调整网页版面以适合屏幕大小"</string>
@@ -243,10 +245,14 @@
     <string name="download_file_error_dlg_title" msgid="2693630283595384874">"没有存储空间"</string>
     <string name="download_file_error_dlg_msg" msgid="5156405410324072471">"无法下载<xliff:g id="FILENAME">%s</xliff:g>。"\n"请释放部分手机空间,然后重试。"</string>
     <string name="download_failed_generic_dlg_title" msgid="6106781095337833391">"下载失败"</string>
-    <string name="download_no_sdcard_dlg_title" msgid="605904452159416792">"无 SD 卡"</string>
-    <string name="download_no_sdcard_dlg_msg" msgid="2616399456116301518">"需要有 SD 卡才能下载<xliff:g id="FILENAME">%s</xliff:g>。"</string>
-    <string name="download_sdcard_busy_dlg_title" msgid="6877712666046917741">"SD 卡不可用"</string>
-    <string name="download_sdcard_busy_dlg_msg" msgid="3473883538192835204">"SD 卡正忙。要允许下载,请在通知中选择“关闭 USB 存储”。"</string>
+    <!-- outdated translation 605904452159416792 -->     <string name="download_no_sdcard_dlg_title" product="nosdcard" msgid="5349772560166195586">"无 SD 卡"</string>
+    <string name="download_no_sdcard_dlg_title" product="default" msgid="605904452159416792">"无 SD 卡"</string>
+    <!-- outdated translation 2616399456116301518 -->     <string name="download_no_sdcard_dlg_msg" product="nosdcard" msgid="9049052105269200675">"需要有 SD 卡才能下载<xliff:g id="FILENAME">%s</xliff:g>。"</string>
+    <string name="download_no_sdcard_dlg_msg" product="default" msgid="2616399456116301518">"需要有 SD 卡才能下载<xliff:g id="FILENAME">%s</xliff:g>。"</string>
+    <!-- outdated translation 6877712666046917741 -->     <string name="download_sdcard_busy_dlg_title" product="nosdcard" msgid="4151068942919670243">"SD 卡不可用"</string>
+    <string name="download_sdcard_busy_dlg_title" product="default" msgid="6877712666046917741">"SD 卡不可用"</string>
+    <!-- outdated translation 3473883538192835204 -->     <string name="download_sdcard_busy_dlg_msg" product="nosdcard" msgid="7297514580933657663">"SD 卡正忙。要允许下载,请在通知中选择“关闭 USB 存储”。"</string>
+    <string name="download_sdcard_busy_dlg_msg" product="default" msgid="3473883538192835204">"SD 卡正忙。要允许下载,请在通知中选择“关闭 USB 存储”。"</string>
     <string name="download_no_application_title" msgid="1286056729168874295">"无法打开文件"</string>
     <string name="retry" msgid="1835923075542266721">"重试"</string>
     <string name="no_downloads" msgid="3947445710685021498">"下载历史记录为空。"</string>
diff --git a/res/values-zh-rHK/donottranslate-search_engines.xml b/res/values-zh-rHK/donottranslate-search_engines.xml
new file mode 100644
index 0000000..eaf35d5
--- /dev/null
+++ b/res/values-zh-rHK/donottranslate-search_engines.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>yahoo_hk</item>
+    <item>bing_zh_HK</item>
+    <item>baidu</item>
+  </string-array>
+</resources>
diff --git a/res/values-zh-rTW/donottranslate-search_engines.xml b/res/values-zh-rTW/donottranslate-search_engines.xml
new file mode 100644
index 0000000..6d02b43
--- /dev/null
+++ b/res/values-zh-rTW/donottranslate-search_engines.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>yahoo_tw</item>
+    <item>bing_zh_TW</item>
+  </string-array>
+</resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 33f3feb..6868075 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -136,6 +136,8 @@
   </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"在目前視窗的後面開啟新視窗"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"設定首頁"</string>
+    <string name="pref_content_search_engine" msgid="1620101310821644144">"設定搜尋引擎"</string>
+    <string name="pref_content_search_engine_summary" msgid="5162667665858487316">"選取搜尋引擎"</string>
     <string name="pref_use_current" msgid="1493179933653044553">"使用目前的網頁"</string>
     <string name="pref_content_autofit" msgid="8260474534053660809">"自動調整頁面"</string>
     <string name="pref_content_autofit_summary" msgid="4587831659894879986">"配合螢幕大小調整網頁版面"</string>
@@ -243,10 +245,14 @@
     <string name="download_file_error_dlg_title" msgid="2693630283595384874">"空間不足"</string>
     <string name="download_file_error_dlg_msg" msgid="5156405410324072471">"無法下載 <xliff:g id="FILENAME">%s</xliff:g>。"\n" 請清除手機上的空間或再試一次。"</string>
     <string name="download_failed_generic_dlg_title" msgid="6106781095337833391">"下載失敗"</string>
-    <string name="download_no_sdcard_dlg_title" msgid="605904452159416792">"沒有 SD 卡"</string>
-    <string name="download_no_sdcard_dlg_msg" msgid="2616399456116301518">"需要 SD 卡下載 <xliff:g id="FILENAME">%s</xliff:g>。"</string>
-    <string name="download_sdcard_busy_dlg_title" msgid="6877712666046917741">"無法使用 SD 卡"</string>
-    <string name="download_sdcard_busy_dlg_msg" msgid="3473883538192835204">"SD 記憶卡忙碌。如要允許下載,請選取通知中的 [停用 USB 儲存裝置]。"</string>
+    <!-- outdated translation 605904452159416792 -->     <string name="download_no_sdcard_dlg_title" product="nosdcard" msgid="5349772560166195586">"沒有 SD 卡"</string>
+    <string name="download_no_sdcard_dlg_title" product="default" msgid="605904452159416792">"沒有 SD 卡"</string>
+    <!-- outdated translation 2616399456116301518 -->     <string name="download_no_sdcard_dlg_msg" product="nosdcard" msgid="9049052105269200675">"需要 SD 卡下載 <xliff:g id="FILENAME">%s</xliff:g>。"</string>
+    <string name="download_no_sdcard_dlg_msg" product="default" msgid="2616399456116301518">"需要 SD 卡下載 <xliff:g id="FILENAME">%s</xliff:g>。"</string>
+    <!-- outdated translation 6877712666046917741 -->     <string name="download_sdcard_busy_dlg_title" product="nosdcard" msgid="4151068942919670243">"無法使用 SD 卡"</string>
+    <string name="download_sdcard_busy_dlg_title" product="default" msgid="6877712666046917741">"無法使用 SD 卡"</string>
+    <!-- outdated translation 3473883538192835204 -->     <string name="download_sdcard_busy_dlg_msg" product="nosdcard" msgid="7297514580933657663">"SD 記憶卡忙碌。如要允許下載,請選取通知中的 [停用 USB 儲存裝置]。"</string>
+    <string name="download_sdcard_busy_dlg_msg" product="default" msgid="3473883538192835204">"SD 記憶卡忙碌。如要允許下載,請選取通知中的 [停用 USB 儲存裝置]。"</string>
     <string name="download_no_application_title" msgid="1286056729168874295">"無法開啟檔案"</string>
     <string name="retry" msgid="1835923075542266721">"重試"</string>
     <string name="no_downloads" msgid="3947445710685021498">"下載記錄是空的。"</string>
diff --git a/res/values/all_search_engines.xml b/res/values/all_search_engines.xml
new file mode 100644
index 0000000..08cf763
--- /dev/null
+++ b/res/values/all_search_engines.xml
@@ -0,0 +1,752 @@
+<?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.
+-->
+
+
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each string-array item below refers to one search engine in a specific locale, and the name of the
+item is referred to by the <engine_X_name> items in the locale specific search_engines.xml file.
+
+Format:
+  - Human readable label
+  - Keyword: empty string if the engine has no keyword. (currently unused)
+  - Favicon URL
+  - Search URL
+  - Encoding
+  - Suggest URL: empty string if this engine has no suggest feature
+
+The parameters enclosed in curly braces come from the OpenSearch specification, see
+http://www.opensearch.org/Specifications/OpenSearch/1.1/Draft_4#OpenSearch_1.1_parameters
+-->
+
+<resources>
+  <string-array name="yahoo_uk" translatable="false">
+    <item>Yahoo! UK &amp; Ireland</item>
+    <item>uk.yahoo.com</item>
+    <item>http://uk.search.yahoo.com/favicon.ico</item>
+    <item>http://uk.search.yahoo.com/search?ei={inputEncoding}&amp;fr=crmas&amp;p={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://uk-sayt.ff.search.yahoo.com/gossip-uk-sayt?output=fxjson&amp;command={searchTerms}</item>
+  </string-array>
+  <string-array name="yahoo_jp" translatable="false">
+    <item>Yahoo! JAPAN</item>
+    <item>yahoo.co.jp</item>
+    <item>http://search.yahoo.co.jp/favicon.ico</item>
+    <item>http://search.yahoo.co.jp/search?ei={inputEncoding}&amp;fr=crmas&amp;p={searchTerms}</item>
+    <item>UTF-8</item>
+    <item></item>
+  </string-array>
+  <string-array name="rambler" translatable="false">
+    <item>Rambler</item>
+    <item>rambler.ru</item>
+    <item>http://www.rambler.ru/favicon.ico</item>
+    <item>http://www.rambler.ru/srch?words={searchTerms}</item>
+    <item>windows-1251</item>
+    <item></item>
+  </string-array>
+  <string-array name="yahoo_br" translatable="false">
+    <item>Yahoo! Brasil</item>
+    <item>br.yahoo.com</item>
+    <item>http://br.search.yahoo.com/favicon.ico</item>
+    <item>http://br.search.yahoo.com/search?ei={inputEncoding}&amp;fr=crmas&amp;p={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://br-sayt.ff.search.yahoo.com/gossip-br-sayt?output=fxjson&amp;command={searchTerms}</item>
+  </string-array>
+  <string-array name="bing_zh_HK" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=zh-HK&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="bing_el_GR" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=el-GR&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="bing_tr_TR" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=tr-TR&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="ask_uk" translatable="false">
+    <item>Ask Jeeves</item>
+    <item>uk.ask.com</item>
+    <item>http://uk.ask.com/favicon.ico</item>
+    <item>http://uk.ask.com/web?q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://ss.uk.ask.com/query?q={searchTerms}&amp;li=ff</item>
+  </string-array>
+  <string-array name="nate" translatable="false">
+    <item>&#xb124;&#xc774;&#xd2b8;&#xb2f7;&#xcef4;</item>
+    <item>nate.com</item>
+    <item>http://nate.search.empas.com/favicon.ico</item>
+    <item>http://nate.search.empas.com/search/all.html?q={searchTerms}</item>
+    <item>EUC-KR</item>
+    <item></item>
+  </string-array>
+  <string-array name="uol" translatable="false">
+    <item>UOL Busca</item>
+    <item>busca.uol.com.br</item>
+    <item>http://busca.uol.com.br/favicon.ico</item>
+    <item>http://busca.uol.com.br/www/index.html?q={searchTerms}</item>
+    <item>ISO-8859-1</item>
+    <item></item>
+  </string-array>
+  <string-array name="baidu" translatable="false">
+    <item>&#x767e;&#x5ea6;</item>
+    <item>baidu.com</item>
+    <item>http://www.baidu.com/favicon.ico</item>
+    <item>http://www.baidu.com/s?wd={searchTerms}</item>
+    <item>GB2312</item>
+    <item></item>
+  </string-array>
+  <string-array name="yahoo_ch" translatable="false">
+    <item>Yahoo! Suche</item>
+    <item>ch.yahoo.com</item>
+    <item>http://ch.search.yahoo.com/favicon.ico</item>
+    <item>http://ch.search.yahoo.com/search?ei={inputEncoding}&amp;fr=crmas&amp;p={searchTerms}</item>
+    <item>UTF-8</item>
+    <item></item>
+  </string-array>
+  <string-array name="bing_nl_BE" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=nl-BE&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="yahoo_cn" translatable="false">
+    <item>&#x4e2d;&#x56fd;&#x96c5;&#x864e;</item>
+    <item>cn.yahoo.com</item>
+    <item>http://search.cn.yahoo.com/favicon.ico</item>
+    <item>http://search.cn.yahoo.com/search?ei={inputEncoding}&amp;fr=crmas&amp;p={searchTerms}</item>
+    <item>GB2312</item>
+    <item></item>
+  </string-array>
+  <string-array name="onet" translatable="false">
+    <item>Onet.pl</item>
+    <item>onet.pl</item>
+    <item>http://szukaj.onet.pl/favicon.ico</item>
+    <item>http://szukaj.onet.pl/query.html?qt={searchTerms}</item>
+    <item>ISO-8859-2</item>
+    <item></item>
+  </string-array>
+  <string-array name="ask_es" translatable="false">
+    <item>Ask.com Espa&#x00f1a;</item>
+    <item>es.ask.com</item>
+    <item>http://es.ask.com/favicon.ico</item>
+    <item>http://es.ask.com/web?q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://ss.es.ask.com/query?q={searchTerms}&amp;li=ff</item>
+  </string-array>
+  <string-array name="bing_cs_CZ" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=cs-CZ&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="altavista_se" translatable="false">
+    <item>AltaVista</item>
+    <item>se.altavista.com</item>
+    <item>http://se.altavista.com/favicon.ico</item>
+    <item>http://se.altavista.com/web/results?q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item></item>
+  </string-array>
+  <string-array name="mail_ru" translatable="false">
+    <item>\@MAIL.RU</item>
+    <item>mail.ru</item>
+    <item>http://img.go.mail.ru/favicon.ico</item>
+    <item>http://go.mail.ru/search?q={searchTerms}</item>
+    <item>windows-1251</item>
+    <item></item>
+  </string-array>
+  <string-array name="hispavista" translatable="false">
+    <item>hispavista</item>
+    <item>hispavista.com</item>
+    <item>http://buscar.hispavista.com/favicon.ico</item>
+    <item>http://buscar.hispavista.com/?cadena={searchTerms}</item>
+    <item>iso-8859-1</item>
+    <item></item>
+  </string-array>
+  <string-array name="bing_zh_CN" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=zh-CN&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="google" translatable="false">
+    <item>Google</item>
+    <item>google.com</item>
+    <item>http://www.google.com/favicon.ico</item>
+    <item>http://www.google.com/m?hl={language}&amp;ie={inputEncoding}&amp;source=android-browser&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://www.google.com/complete/search?hl={language}&amp;json=true&amp;q={searchTerms}</item>
+  </string-array>
+  <string-array name="bing_en_NZ" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=en-NZ&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="bing_fr_BE" translatable="false">
+    <item>Bing</item>
+    <item></item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=fr-BE&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="rednano" translatable="false">
+    <item>Rednano</item>
+    <item>rednano.sg</item>
+    <item>http://rednano.sg/favicon.ico</item>
+    <item>http://rednano.sg/sfe/lwi.action?querystring={searchTerms}</item>
+    <item>UTF-8</item>
+    <item></item>
+  </string-array>
+  <string-array name="goo" translatable="false">
+    <item>goo</item>
+    <item>search.goo.ne.jp</item>
+    <item>http://goo.ne.jp/favicon.ico</item>
+    <item>http://search.goo.ne.jp/web.jsp?MT={searchTerms}&amp;IE={inputEncoding}</item>
+    <item>UTF-8</item>
+    <item></item>
+  </string-array>
+  <string-array name="sapo" translatable="false">
+    <item>SAPO</item>
+    <item>sapo.pt</item>
+    <item>http://imgs.sapo.pt/images/sapo.ico</item>
+    <item>http://pesquisa.sapo.pt/?q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://pesquisa.sapo.pt/livesapo?q={searchTerms}</item>
+  </string-array>
+  <string-array name="bing_it_IT" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=it-IT&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="bing_es_ES" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=es-ES&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="abcsok" translatable="false">
+    <item>ABC S&#x00f8;k</item>
+    <item>abcsok.no</item>
+    <item>http://abcsok.no/favicon.ico</item>
+    <item>http://abcsok.no/index.html?q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item></item>
+  </string-array>
+  <string-array name="yahoo_dk" translatable="false">
+    <item>Yahoo! Danmark</item>
+    <item>dk.yahoo.com</item>
+    <item>http://dk.search.yahoo.com/favicon.ico</item>
+    <item>http://dk.search.yahoo.com/search?ei={inputEncoding}&amp;fr=crmas&amp;p={searchTerms}</item>
+    <item>UTF-8</item>
+    <item></item>
+  </string-array>
+  <string-array name="yahoo_de" translatable="false">
+    <item>Yahoo! Deutschland</item>
+    <item>de.yahoo.com</item>
+    <item>http://de.search.yahoo.com/favicon.ico</item>
+    <item>http://de.search.yahoo.com/search?ei={inputEncoding}&amp;fr=crmas&amp;p={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://de-sayt.ff.search.yahoo.com/gossip-de-sayt?output=fxjson&amp;command={searchTerms}</item>
+  </string-array>
+  <string-array name="bing_de_AT" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=de-AT&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="bing_pl_PL" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=pl-PL&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="tut" translatable="false">
+    <item>TUT.BY</item>
+    <item>tut.by</item>
+    <item>http://www.tut.by/favicon.ico</item>
+    <item>http://search.tut.by/?query={searchTerms}</item>
+    <item>windows-1251</item>
+    <item></item>
+  </string-array>
+  <string-array name="spray" translatable="false">
+    <item>Spray</item>
+    <item>spray.se</item>
+    <item>http://www.eniro.se/favicon.ico</item>
+    <item>http://www.eniro.se/query?ax=spray&amp;search_word={searchTerms}&amp;what=web</item>
+    <item>ISO-8859-1</item>
+    <item></item>
+  </string-array>
+  <string-array name="wp" translatable="false">
+    <item>Wirtualna Polska</item>
+    <item>wp.pl</item>
+    <item>http://szukaj.wp.pl/favicon.ico</item>
+    <item>http://szukaj.wp.pl/szukaj.html?szukaj={searchTerms}</item>
+    <item>ISO-8859-2</item>
+    <item></item>
+  </string-array>
+  <string-array name="yahoo_tw" translatable="false">
+    <item>Yahoo!&#x5947;&#x6469;</item>
+    <item>tw.yahoo.com</item>
+    <item>http://tw.search.yahoo.com/favicon.ico</item>
+    <item>http://tw.search.yahoo.com/search?ei={inputEncoding}&amp;fr=crmas&amp;p={searchTerms}</item>
+    <item>UTF-8</item>
+    <item></item>
+  </string-array>
+  <string-array name="atlas_cz" translatable="false">
+    <item>Atlas</item>
+    <item>atlas.cz</item>
+    <item>http://img.atlas.cz/favicon.ico</item>
+    <item>http://search.atlas.cz/?q={searchTerms}</item>
+    <item>windows-1250</item>
+    <item></item>
+  </string-array>
+  <string-array name="bing_en_GB" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=en-GB&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="yahoo_es" translatable="false">
+    <item>Yahoo! Espa&#x00f1a;</item>
+    <item>es.yahoo.com</item>
+    <item>http://es.search.yahoo.com/favicon.ico</item>
+    <item>http://es.search.yahoo.com/search?ei={inputEncoding}&amp;fr=crmas&amp;p={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://es-sayt.ff.search.yahoo.com/gossip-es-sayt?output=fxjson&amp;command={searchTerms}</item>
+  </string-array>
+  <string-array name="libero" translatable="false">
+    <item>Libero</item>
+    <item>libero.it</item>
+    <item>http://arianna.libero.it/favicon.ico</item>
+    <item>http://arianna.libero.it/search/abin/integrata.cgi?query={searchTerms}</item>
+    <item>ISO-8859-1</item>
+    <item></item>
+  </string-array>
+  <string-array name="bing_sv_SE" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=sv-SE&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="yahoo_nz" translatable="false">
+    <item>Yahoo!Xtra</item>
+    <item>nz.yahoo.com</item>
+    <item>http://nz.search.yahoo.com/favicon.ico</item>
+    <item>http://nz.search.yahoo.com/search?ei={inputEncoding}&amp;fr=crmas&amp;p={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://aue-sayt.ff.search.yahoo.com/gossip-nz-sayt?output=fxjson&amp;command={searchTerms}</item>
+  </string-array>
+  <string-array name="terra_es" translatable="false">
+    <item>Terra</item>
+    <item>terra.es</item>
+    <item>http://buscador.terra.es/favicon.ico</item>
+    <item>http://buscador.terra.es/Default.aspx?query={searchTerms}&amp;source=Search</item>
+    <item>ISO-8859-1</item>
+    <item></item>
+  </string-array>
+  <string-array name="yahoo_nl" translatable="false">
+    <item>Yahoo! Nederland</item>
+    <item>nl.yahoo.com</item>
+    <item>http://nl.search.yahoo.com/favicon.ico</item>
+    <item>http://nl.search.yahoo.com/search?ei={inputEncoding}&amp;fr=crmas&amp;p={searchTerms}</item>
+    <item>UTF-8</item>
+    <item></item>
+  </string-array>
+  <string-array name="yahoo_no" translatable="false">
+    <item>Yahoo! Norge</item>
+    <item>no.yahoo.com</item>
+    <item>http://no.search.yahoo.com/favicon.ico</item>
+    <item>http://no.search.yahoo.com/search?ei={inputEncoding}&amp;fr=crmas&amp;p={searchTerms}</item>
+    <item>UTF-8</item>
+    <item></item>
+  </string-array>
+  <string-array name="daum" translatable="false">
+    <item>Daum</item>
+    <item>daum.net</item>
+    <item>http://search.daum.net/favicon.ico</item>
+    <item>http://search.daum.net/search?q={searchTerms}</item>
+    <item>EUC-KR</item>
+    <item>http://sug.search.daum.net/search_nsuggest?mod=fxjson&amp;q={searchTerms}</item>
+  </string-array>
+  <string-array name="yahoo_fr" translatable="false">
+    <item>Yahoo! France</item>
+    <item>fr.yahoo.com</item>
+    <item>http://fr.search.yahoo.com/favicon.ico</item>
+    <item>http://fr.search.yahoo.com/search?ei={inputEncoding}&amp;fr=crmas&amp;p={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://fr-sayt.ff.search.yahoo.com/gossip-fr-sayt?output=fxjson&amp;command={searchTerms}</item>
+  </string-array>
+  <string-array name="ask_nl" translatable="false">
+    <item>Ask.com Nederland</item>
+    <item>nl.ask.com</item>
+    <item>http://nl.ask.com/favicon.ico</item>
+    <item>http://nl.ask.com/web?q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://ss.nl.ask.com/query?q={searchTerms}&amp;li=ff</item>
+  </string-array>
+  <string-array name="seznam" translatable="false">
+    <item>Seznam</item>
+    <item>seznam.cz</item>
+    <item>http://1.im.cz/szn/img/favicon.ico</item>
+    <item>http://search.seznam.cz/?q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http:///suggest.fulltext.seznam.cz/?dict=fulltext_ff&amp;phrase={searchTerms}&amp;encoding={inputEncoding}&amp;response_encoding=utf-8</item>
+  </string-array>
+  <string-array name="centrum_cz" translatable="false">
+    <item>Centrum.cz</item>
+    <item>centrum.cz</item>
+    <item>http://img.centrum.cz/6/vy2/o/favicon.ico</item>
+    <item>http://search.centrum.cz/index.php?charset={inputEncoding}&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item></item>
+  </string-array>
+  <string-array name="eniro_se" translatable="false">
+    <item>Eniro</item>
+    <item>eniro.se</item>
+    <item>http://eniro.se/favicon.ico</item>
+    <item>http://eniro.se/query?search_word={searchTerms}&amp;what=web_local</item>
+    <item>ISO-8859-1</item>
+    <item></item>
+  </string-array>
+  <string-array name="kvasir" translatable="false">
+    <item>Kvasir</item>
+    <item>kvasir.no</item>
+    <item>http://www.kvasir.no/img/favicon.ico</item>
+    <item>http://www.kvasir.no/nettsok/searchResult.html?searchExpr={searchTerms}</item>
+    <item>ISO-8859-1</item>
+    <item></item>
+  </string-array>
+  <string-array name="yahoo" translatable="false">
+    <item>Yahoo!</item>
+    <item>yahoo.com</item>
+    <item>http://search.yahoo.com/favicon.ico</item>
+    <item>http://search.yahoo.com/search?ei={inputEncoding}&amp;fr=crmas&amp;p={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://ff.search.yahoo.com/gossip?output=fxjson&amp;command={searchTerms}</item>
+  </string-array>
+  <string-array name="bing_en_IE" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=en-IE&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="bing_pt_PT" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=pt-PT&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="bing_de_CH" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=de-CH&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="bing_nl_NL" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=nl-NL&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="bing_fr_CH" translatable="false">
+    <item>Bing</item>
+    <item></item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=fr-CH&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="bing_zh_TW" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=zh-TW&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="bing_ru_RU" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=ru-RU&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="bing_en_AU" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=en-AU&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="bing_da_DK" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=da-DK&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="ask_it" translatable="false">
+    <item>Ask.com Italia</item>
+    <item>it.ask.com</item>
+    <item>http://it.ask.com/favicon.ico</item>
+    <item>http://it.ask.com/web?q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://ss.it.ask.com/query?q={searchTerms}&amp;li=ff</item>
+  </string-array>
+  <string-array name="yandex_ru" translatable="false">
+    <item>&#x042f;&#x043d;&#x0434;&#x0435;&#x043a;&#x0441;</item>
+    <item>yandex.ru</item>
+    <item>http://yandex.ru/favicon.ico</item>
+    <item>http://yandex.ru/yandsearch?text={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://suggest.yandex.net/suggest-ff.cgi?part={searchTerms}</item>
+  </string-array>
+  <string-array name="bing_ja_JP" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=ja-JP&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="yahoo_kr" translatable="false">
+    <item>&#xc57c;&#xd6c4;! &#xcf54;&#xb9ac;&#xc544;</item>
+    <item>kr.yahoo.com</item>
+    <item>http://kr.search.yahoo.com/favicon.ico</item>
+    <item>http://kr.search.yahoo.com/search?ei={inputEncoding}&amp;fr=crmas&amp;p={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://kr.atc.search.yahoo.com/atcx.php?property=main&amp;ot=fxjson&amp;ei=utf8&amp;eo=utf8&amp;command={searchTerms}</item>
+  </string-array>
+  <string-array name="ask_de" translatable="false">
+    <item>Ask.com Deutschland</item>
+    <item>de.ask.com</item>
+    <item>http://de.ask.com/favicon.ico</item>
+    <item>http://de.ask.com/web?q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://ss.de.ask.com/query?q={searchTerms}&amp;li=ff</item>
+  </string-array>
+  <string-array name="yahoo_hk" translatable="false">
+    <item>Yahoo! Hong Kong</item>
+    <item>hk.yahoo.com</item>
+    <item>http://hk.search.yahoo.com/favicon.ico</item>
+    <item>http://hk.search.yahoo.com/search?ei={inputEncoding}&amp;fr=crmas&amp;p={searchTerms}</item>
+    <item>UTF-8</item>
+    <item></item>
+  </string-array>
+  <string-array name="bing_fr_FR" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=fr-FR&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="in" translatable="false">
+    <item>in.gr</item>
+    <item>in.gr</item>
+    <item>http://www.in.gr/favicon.ico</item>
+    <item>http://find.in.gr/?qs={searchTerms}</item>
+    <item>ISO-8859-7</item>
+    <item></item>
+  </string-array>
+  <string-array name="bing_nb_NO" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=nb-NO&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="yahoo_sg" translatable="false">
+    <item>Yahoo! Singapore</item>
+    <item>sg.yahoo.com</item>
+    <item>http://sg.search.yahoo.com/favicon.ico</item>
+    <item>http://sg.search.yahoo.com/search?ei={inputEncoding}&amp;fr=crmas&amp;p={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://sg-sayt.ff.search.yahoo.com/gossip-sg-sayt?output=fxjson&amp;command={searchTerms}</item>
+  </string-array>
+  <string-array name="yahoo_se" translatable="false">
+    <item>Yahoo! Sverige</item>
+    <item>se.yahoo.com</item>
+    <item>http://se.search.yahoo.com/favicon.ico</item>
+    <item>http://se.search.yahoo.com/search?ei={inputEncoding}&amp;fr=crmas&amp;p={searchTerms}</item>
+    <item>UTF-8</item>
+    <item></item>
+  </string-array>
+  <string-array name="bing_de_DE" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=de-DE&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="search_de_CH" translatable="false">
+    <item>search.ch</item>
+    <item>search.ch</item>
+    <item>http://www.search.ch/favicon.ico</item>
+    <item>http://www.search.ch/index.de.html?q={searchTerms}</item>
+    <item>ISO-8859-1</item>
+    <item></item>
+  </string-array>
+  <string-array name="mynet" translatable="false">
+    <item>MYNET</item>
+    <item>mynet.com</item>
+    <item>http://img.mynet.com/mynetfavori.ico</item>
+    <item>http://arama.mynet.com/search.aspx?q={searchTerms}&amp;pg=q</item>
+    <item>windows-1254</item>
+    <item></item>
+  </string-array>
+  <string-array name="search_fr_CH" translatable="false">
+    <item>search.ch</item>
+    <item></item>
+    <item>http://www.search.ch/favicon.ico</item>
+    <item>http://www.search.ch/index.fr.html?q={searchTerms}</item>
+    <item>ISO-8859-1</item>
+    <item></item>
+  </string-array>
+  <string-array name="virgilio" translatable="false">
+    <item>Virgilio</item>
+    <item>virgilio.it</item>
+    <item>http://ricerca.alice.it/favicon.ico</item>
+    <item>http://ricerca.alice.it/ricerca?qs={searchTerms}</item>
+    <item>ISO-8859-1</item>
+    <item></item>
+  </string-array>
+  <string-array name="bing_en_SG" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=en-SG&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="yahoo_it" translatable="false">
+    <item>Yahoo! Italia</item>
+    <item>it.yahoo.com</item>
+    <item>http://it.search.yahoo.com/favicon.ico</item>
+    <item>http://it.search.yahoo.com/search?ei={inputEncoding}&amp;fr=crmas&amp;p={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://it-sayt.ff.search.yahoo.com/gossip-it-sayt?output=fxjson&amp;command={searchTerms}</item>
+  </string-array>
+  <string-array name="yahoo_at" translatable="false">
+    <item>Yahoo! Suche</item>
+    <item>at.yahoo.com</item>
+    <item>http://at.search.yahoo.com/favicon.ico</item>
+    <item>http://at.search.yahoo.com/search?ei={inputEncoding}&amp;fr=crmas&amp;p={searchTerms}</item>
+    <item>UTF-8</item>
+    <item></item>
+  </string-array>
+  <string-array name="yahoo_au" translatable="false">
+    <item>Yahoo!7</item>
+    <item>au.yahoo.com</item>
+    <item>http://au.search.yahoo.com/favicon.ico</item>
+    <item>http://au.search.yahoo.com/search?ei={inputEncoding}&amp;fr=crmas&amp;p={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://aue-sayt.ff.search.yahoo.com/gossip-au-sayt?output=fxjson&amp;command={searchTerms}</item>
+  </string-array>
+  <string-array name="bing_pt_BR" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=pt-BR&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="bing" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+  <string-array name="netsprint" translatable="false">
+    <item>NetSprint</item>
+    <item>netsprint.pl</item>
+    <item>http://netsprint.pl/favicon.ico</item>
+    <item>http://www.netsprint.pl/serwis/search?q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item></item>
+  </string-array>
+  <string-array name="naver" translatable="false">
+    <item>&#xb124;&#xc774;&#xbc84;</item>
+    <item>naver.com</item>
+    <item>http://search.naver.com/favicon.ico</item>
+    <item>http://search.naver.com/search.naver?ie={inputEncoding}&amp;query={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://ac.search.naver.com/autocompl?m=s&amp;ie={inputEncoding}&amp;oe=utf-8&amp;q={searchTerms}</item>
+  </string-array>
+  <string-array name="bing_en_ZA" translatable="false">
+    <item>Bing</item>
+    <item>bing.com</item>
+    <item>http://www.bing.com/s/wlflag.ico</item>
+    <item>http://www.bing.com/search?setmkt=en-ZA&amp;q={searchTerms}</item>
+    <item>UTF-8</item>
+    <item>http://api.bing.com/osjson.aspx?query={searchTerms}&amp;language={language}</item>
+  </string-array>
+</resources>
+
diff --git a/res/values/donottranslate-search_engines.xml b/res/values/donottranslate-search_engines.xml
new file mode 100644
index 0000000..c6ed9ca
--- /dev/null
+++ b/res/values/donottranslate-search_engines.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="search_engines" translatable="false">
+    <item>google</item>
+    <item>yahoo</item>
+    <item>bing</item>
+  </string-array>
+</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 18a2144..9c9d30a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -305,6 +305,10 @@
     <string name="pref_content_open_in_background_summary">Open new windows behind the current one</string>
     <!-- Settings label -->
     <string name="pref_content_homepage">Set home page</string>
+    <!-- Settings label -->
+    <string name="pref_content_search_engine">Set search engine</string>
+    <!-- Settings summary -->
+    <string name="pref_content_search_engine_summary">Select a search engine</string>
     <!-- Settings button label -->
     <string name="pref_use_current">Use current page</string>
     <!-- Settings label -->
@@ -450,12 +454,16 @@
         <item>Android</item>
         <item>Desktop</item>
         <item>iPhone</item>
+        <item>iPad</item>
+        <item>Froyo-N1</item>
     </string-array>
     <!-- Do not tranlsate.  Development option -->
     <string-array name="pref_development_ua_values" translatable="false">
         <item>0</item>
         <item>1</item>
         <item>2</item>
+        <item>3</item>
+        <item>4</item>
     </string-array>
     <string name="pref_development_error_console" translatable="false">Show JavaScript Console</string>
     <!-- Settings screen, setting option name -->
@@ -576,17 +584,28 @@
     <string name="download_file_error_dlg_msg"><xliff:g id="filename">%s</xliff:g> could not be downloaded.\nFree up some space on your phone and try again.</string>
     <!-- Title for a dialog informing the user that the download has failed -->
     <string name="download_failed_generic_dlg_title">Download unsuccessful</string>
+    <!-- Dialog title [CHAR LIMIT=25] -->
+    <string name="download_no_sdcard_dlg_title" product="nosdcard">Shared storage unavailable</string>
     <!-- Dialog title -->
-    <string name="download_no_sdcard_dlg_title">No SD card</string>
+    <string name="download_no_sdcard_dlg_title" product="default">No SD card</string>
+    <!-- Dialog message [CHAR LIMIT=NONE] -->
+    <string name="download_no_sdcard_dlg_msg" product="nosdcard">Shared storage is required to download <xliff:g id="filename">%s</xliff:g>.</string>
     <!-- Dialog message -->
-    <string name="download_no_sdcard_dlg_msg">An SD card is required to download <xliff:g id="filename">%s</xliff:g>.</string>
+    <string name="download_no_sdcard_dlg_msg" product="default">An SD card is required to download <xliff:g id="filename">%s</xliff:g>.</string>
+    <!-- Title for a dialog informing the user that the SD card used for
+            external storage is busy so they cannot download anything [CHAR LIMIT=25] -->
+    <string name="download_sdcard_busy_dlg_title" product="nosdcard">Shared storage unavailable</string>
     <!-- Title for a dialog informing the user that the SD card used for
             external storage is busy so they cannot download anything -->
-    <string name="download_sdcard_busy_dlg_title">SD card unavailable</string>
+    <string name="download_sdcard_busy_dlg_title" product="default">SD card unavailable</string>
+    <!-- Message for a dialog informing the user that the SD card used for
+            external storage is busy so they cannot download anything.  Informs
+            the user how to enable SD card storage [CHAR LIMIT=NONE] -->
+    <string name="download_sdcard_busy_dlg_msg" product="nosdcard">The shared storage is busy. To allow downloads, select \"Turn off USB storage\" in the notification.</string>
     <!-- Message for a dialog informing the user that the SD card used for
             external storage is busy so they cannot download anything.  Informs
             the user how to enable SD card storage -->
-    <string name="download_sdcard_busy_dlg_msg">The SD card is busy. To allow downloads, select \"Turn off USB storage\" in the notification.</string>
+    <string name="download_sdcard_busy_dlg_msg" product="default">The SD card is busy. To allow downloads, select \"Turn off USB storage\" in the notification.</string>
 
     <!-- Title for a dialog informing the user that there is no application on
             the phone that can open the file that was downloaded -->
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/res/xml/browser_preferences.xml b/res/xml/browser_preferences.xml
index ee1b306..1da85ec 100644
--- a/res/xml/browser_preferences.xml
+++ b/res/xml/browser_preferences.xml
@@ -192,6 +192,14 @@
     <PreferenceCategory
             android:title="@string/pref_extras_title">
 
+            <!-- Entries and values in this list are set dynamically. -->
+            <com.android.browser.search.SearchEnginePreference
+                    android:key="search_engine"
+                    android:title="@string/pref_content_search_engine"
+                    android:defaultValue="google"
+                    android:summary="@string/pref_content_search_engine_summary"
+                    android:dialogTitle="@string/pref_content_search_engine" />
+
             <PreferenceScreen
                   android:key="website_settings"
                   android:title="@string/pref_extras_website_settings"
diff --git a/src/com/android/browser/BrowserActivity.java b/src/com/android/browser/BrowserActivity.java
index 29e333a..a30bf83 100644
--- a/src/com/android/browser/BrowserActivity.java
+++ b/src/com/android/browser/BrowserActivity.java
@@ -18,6 +18,7 @@
 
 import android.app.Activity;
 import android.app.AlertDialog;
+import android.app.DownloadManager;
 import android.app.ProgressDialog;
 import android.app.SearchManager;
 import android.content.ActivityNotFoundException;
@@ -111,6 +112,7 @@
 import android.accounts.OperationCanceledException;
 import android.accounts.AccountManagerCallback;
 
+import com.android.browser.search.SearchEngine;
 import com.android.common.Search;
 import com.android.common.speech.LoggingEvents;
 
@@ -144,13 +146,6 @@
     private final static boolean LOGV_ENABLED = com.android.browser.Browser.LOGV_ENABLED;
     private final static boolean LOGD_ENABLED = com.android.browser.Browser.LOGD_ENABLED;
 
-    // These are single-character shortcuts for searching popular sources.
-    private static final int SHORTCUT_INVALID = 0;
-    private static final int SHORTCUT_GOOGLE_SEARCH = 1;
-    private static final int SHORTCUT_WIKIPEDIA_SEARCH = 2;
-    private static final int SHORTCUT_DICTIONARY_SEARCH = 3;
-    private static final int SHORTCUT_GOOGLE_MOBILE_LOCAL_SEARCH = 4;
-
     private static class ClearThumbnails extends AsyncTask<File, Void, Void> {
         @Override
         public Void doInBackground(File... files) {
@@ -190,6 +185,9 @@
 
         mResolver = getContentResolver();
 
+        // Keep a settings instance handy.
+        mSettings = BrowserSettings.getInstance();
+
         // If this was a web search request, pass it on to the default web
         // search provider and finish this activity.
         if (handleWebSearchIntent(getIntent())) {
@@ -224,8 +222,6 @@
         // Open the icon database and retain all the bookmark urls for favicons
         retainIconsOnStartup();
 
-        // Keep a settings instance handy.
-        mSettings = BrowserSettings.getInstance();
         mSettings.setTabControl(mTabControl);
 
         PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
@@ -358,6 +354,15 @@
             attachTabToContentView(mTabControl.getCurrentTab());
         }
 
+        // Delete old thumbnails to save space
+        File dir = mTabControl.getThumbnailDir();
+        if (dir.exists()) {
+            for (String child : dir.list()) {
+                File f = new File(dir, child);
+                f.delete();
+            }
+        }
+
         // Read JavaScript flags if it exists.
         String jsFlags = mSettings.getJsFlags();
         if (jsFlags.trim().length() != 0) {
@@ -548,21 +553,6 @@
         }
     }
 
-    private int parseUrlShortcut(String url) {
-        if (url == null) return SHORTCUT_INVALID;
-
-        // FIXME: quick search, need to be customized by setting
-        if (url.length() > 2 && url.charAt(1) == ' ') {
-            switch (url.charAt(0)) {
-            case 'g': return SHORTCUT_GOOGLE_SEARCH;
-            case 'w': return SHORTCUT_WIKIPEDIA_SEARCH;
-            case 'd': return SHORTCUT_DICTIONARY_SEARCH;
-            case 'l': return SHORTCUT_GOOGLE_MOBILE_LOCAL_SEARCH;
-            }
-        }
-        return SHORTCUT_INVALID;
-    }
-
     /**
      * Launches the default web search activity with the query parameters if the given intent's data
      * are identified as plain search terms and not URLs/shortcuts.
@@ -601,11 +591,10 @@
         // But currently, we get the user-typed URL from search box as well.
         String url = fixUrl(inUrl).trim();
 
-        // URLs and site specific search shortcuts are handled by the regular flow of control, so
+        // URLs are handled by the regular flow of control, so
         // return early.
         if (Patterns.WEB_URL.matcher(url).matches()
-                || ACCEPTED_URI_SCHEMA.matcher(url).matches()
-                || parseUrlShortcut(url) != SHORTCUT_INVALID) {
+                || ACCEPTED_URI_SCHEMA.matcher(url).matches()) {
             return false;
         }
 
@@ -619,23 +608,9 @@
             }
         }.execute();
 
-        Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
-        intent.addCategory(Intent.CATEGORY_DEFAULT);
-        intent.putExtra(SearchManager.QUERY, url);
-        if (appData != null) {
-            intent.putExtra(SearchManager.APP_DATA, appData);
-        }
-        if (extraData != null) {
-            intent.putExtra(SearchManager.EXTRA_DATA_KEY, extraData);
-        }
-        intent.putExtra(Browser.EXTRA_APPLICATION_ID, getPackageName());
-
-        // can't be sure there is an activity for the Intent
-        try {
-            startActivity(intent);
-        } catch (ActivityNotFoundException ex) {
-            return false;
-        }
+        SearchEngine searchEngine = mSettings.getSearchEngine();
+        if (searchEngine == null) return false;
+        searchEngine.startSearch(this, url, appData, extraData);
 
         return true;
     }
@@ -840,6 +815,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);
@@ -1198,6 +1180,12 @@
         if (appSearchData == null) {
             appSearchData = createGoogleSearchSourceBundle(GOOGLE_SEARCH_SOURCE_TYPE);
         }
+
+        SearchEngine searchEngine = mSettings.getSearchEngine();
+        if (searchEngine != null && !searchEngine.supportsVoiceSearch()) {
+            appSearchData.putBoolean(SearchManager.DISABLE_VOICE_SEARCH, true);
+        }
+
         super.startSearch(initialQuery, selectInitialQuery, appSearchData, globalSearch);
     }
 
@@ -1277,6 +1265,21 @@
         getTopWindow().requestFocus();
     }
 
+    private WebView showDialog(WebDialog dialog) {
+        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) {
@@ -1370,18 +1373,20 @@
                 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();
+                if (true) {
+                    Tab currentTab = mTabControl.getCurrentTab();
+                    if (currentTab != null) {
+                        currentTab.getWebView().setUpSelect();
+                    }
+                } else {
+                    showSelectDialog();
+                }
                 break;
+
             case R.id.page_info_menu_id:
                 showPageInfo(mTabControl.getCurrentTab(), false);
                 break;
@@ -1420,7 +1425,7 @@
                 break;
 
             case R.id.view_downloads_menu_id:
-                viewDownloads(null);
+                viewDownloads();
                 break;
 
             case R.id.window_one_menu_id:
@@ -1456,8 +1461,59 @@
         return true;
     }
 
-    public void closeFind() {
+    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 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
@@ -2468,7 +2524,7 @@
         onProgressChanged(view, INITIAL_PROGRESS);
         mDidStopLoad = false;
         if (!mIsNetworkUp) createAndShowNetworkDialog();
-
+        closeDialogs();
         if (mSettings.isTracing()) {
             String host;
             try {
@@ -3488,12 +3544,9 @@
      * menu to see the download window. It shows the download window on top of
      * the current window.
      */
-    private void viewDownloads(Uri downloadRecord) {
-        Intent intent = new Intent(this,
-                BrowserDownloadPage.class);
-        intent.setData(downloadRecord);
-        startActivityForResult(intent, BrowserActivity.DOWNLOAD_PAGE);
-
+    private void viewDownloads() {
+        Intent intent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
+        startActivity(intent);
     }
 
     /**
@@ -3632,31 +3685,15 @@
             }
             return inUrl;
         }
-        if (hasSpace) {
-            // FIXME: Is this the correct place to add to searches?
-            // what if someone else calls this function?
-            int shortcut = parseUrlShortcut(inUrl);
-            if (shortcut != SHORTCUT_INVALID) {
-                Browser.addSearchUrl(mResolver, inUrl);
-                String query = inUrl.substring(2);
-                switch (shortcut) {
-                case SHORTCUT_GOOGLE_SEARCH:
-                    return URLUtil.composeSearchUrl(query, QuickSearch_G, QUERY_PLACE_HOLDER);
-                case SHORTCUT_WIKIPEDIA_SEARCH:
-                    return URLUtil.composeSearchUrl(query, QuickSearch_W, QUERY_PLACE_HOLDER);
-                case SHORTCUT_DICTIONARY_SEARCH:
-                    return URLUtil.composeSearchUrl(query, QuickSearch_D, QUERY_PLACE_HOLDER);
-                case SHORTCUT_GOOGLE_MOBILE_LOCAL_SEARCH:
-                    // FIXME: we need location in this case
-                    return URLUtil.composeSearchUrl(query, QuickSearch_L, QUERY_PLACE_HOLDER);
-                }
-            }
-        } else {
+        if (!hasSpace) {
             if (Patterns.WEB_URL.matcher(inUrl).matches()) {
                 return URLUtil.guessUrl(inUrl);
             }
         }
 
+        // FIXME: Is this the correct place to add to searches?
+        // what if someone else calls this function?
+
         Browser.addSearchUrl(mResolver, inUrl);
         return URLUtil.composeSearchUrl(inUrl, QuickSearch_G, QUERY_PLACE_HOLDER);
     }
@@ -3666,11 +3703,15 @@
             // Nothing to do.
             return;
         }
+        Tab t = mTabControl.getCurrentTab();
+        if (t == null) {
+            // There is no current tab so we cannot toggle the error console
+            return;
+        }
 
         mShouldShowErrorConsole = flag;
 
-        ErrorConsoleView errorConsole = mTabControl.getCurrentTab()
-                .getErrorConsole(true);
+        ErrorConsoleView errorConsole = t.getErrorConsole(true);
 
         if (flag) {
             // Setting the show state of the console will cause it's the layout to be inflated.
@@ -3776,6 +3817,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;
@@ -3860,12 +3902,6 @@
                                             Gravity.CENTER);
     // Google search
     final static String QuickSearch_G = "http://www.google.com/m?q=%s";
-    // Wikipedia search
-    final static String QuickSearch_W = "http://en.wikipedia.org/w/index.php?search=%s&go=Go";
-    // Dictionary search
-    final static String QuickSearch_D = "http://dictionary.reference.com/search?q=%s";
-    // Google Mobile Local search
-    final static String QuickSearch_L = "http://www.google.com/m/search?site=local&q=%s&near=mountain+view";
 
     final static String QUERY_PLACE_HOLDER = "%s";
 
@@ -3911,7 +3947,6 @@
 
     // activity requestCode
     final static int COMBO_PAGE                 = 1;
-    final static int DOWNLOAD_PAGE              = 2;
     final static int PREFERENCES_PAGE           = 3;
     final static int FILE_SELECTED              = 4;
 
diff --git a/src/com/android/browser/BrowserBookmarksPage.java b/src/com/android/browser/BrowserBookmarksPage.java
index 7560c78..dd01009 100644
--- a/src/com/android/browser/BrowserBookmarksPage.java
+++ b/src/com/android/browser/BrowserBookmarksPage.java
@@ -312,7 +312,7 @@
         } else {
             ed.putInt(PREF_BOOKMARK_VIEW_MODE, mViewMode.ordinal());
         }
-        ed.commit();
+        ed.apply();
 
         if (mBookmarksAdapter != null) {
             mBookmarksAdapter.switchViewMode(viewMode);
diff --git a/src/com/android/browser/BrowserDownloadAdapter.java b/src/com/android/browser/BrowserDownloadAdapter.java
deleted file mode 100644
index 0f8f721..0000000
--- a/src/com/android/browser/BrowserDownloadAdapter.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (C) 2007 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.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.drm.mobile1.DrmRawContent;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.provider.Downloads;
-import android.text.format.Formatter;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.ProgressBar;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-
-import java.text.DateFormat;
-import java.util.Date;
-import java.util.List;
-
-/**
- * This class is used to represent the data for the download list box. The only 
- * real work done by this class is to construct a custom view for the line
- * items.
- */
-public class BrowserDownloadAdapter extends DateSortedExpandableListAdapter {
-    
-    private int mTitleColumnId;
-    private int mDescColumnId;
-    private int mStatusColumnId;
-    private int mTotalBytesColumnId;
-    private int mCurrentBytesColumnId;
-    private int mMimetypeColumnId;
-    private int mDateColumnId;
-
-    public BrowserDownloadAdapter(Context context, Cursor c, int index) {
-        super(context, c, index);
-        mTitleColumnId = c.getColumnIndexOrThrow(Downloads.Impl.COLUMN_TITLE);
-        mDescColumnId = c.getColumnIndexOrThrow(Downloads.Impl.COLUMN_DESCRIPTION);
-        mStatusColumnId = c.getColumnIndexOrThrow(Downloads.Impl.COLUMN_STATUS);
-        mTotalBytesColumnId = c.getColumnIndexOrThrow(Downloads.Impl.COLUMN_TOTAL_BYTES);
-        mCurrentBytesColumnId = 
-            c.getColumnIndexOrThrow(Downloads.Impl.COLUMN_CURRENT_BYTES);
-        mMimetypeColumnId = c.getColumnIndexOrThrow(Downloads.Impl.COLUMN_MIME_TYPE);
-        mDateColumnId = c.getColumnIndexOrThrow(Downloads.Impl.COLUMN_LAST_MODIFICATION);
-    }
-
-    @Override
-    public View getChildView(int groupPosition, int childPosition,
-                boolean isLastChild, View convertView, ViewGroup parent) {
-        Context context = getContext();
-        // The layout file uses a RelativeLayout, whereas the GroupViews use
-        // TextView.
-        if (null == convertView || !(convertView instanceof RelativeLayout)) {
-            convertView = LayoutInflater.from(context).inflate(
-                    R.layout.browser_download_item, null);
-        }
-
-        // Bail early if the Cursor is closed.
-        if (!moveCursorToChildPosition(groupPosition, childPosition)) {
-            return convertView;
-        }
-
-        Resources r = context.getResources();
-        
-        // Retrieve the icon for this download
-        String mimeType = getString(mMimetypeColumnId);
-        ImageView iv = (ImageView) convertView.findViewById(R.id.download_icon);
-        if (DrmRawContent.DRM_MIMETYPE_MESSAGE_STRING.equalsIgnoreCase(mimeType)) {
-            iv.setImageResource(R.drawable.ic_launcher_drm_file);
-        } else if (mimeType == null) {
-            iv.setVisibility(View.INVISIBLE);
-        } else {
-            Intent intent = new Intent(Intent.ACTION_VIEW);
-            intent.setDataAndType(Uri.fromParts("file", "", null), mimeType);
-            PackageManager pm = context.getPackageManager();
-            List<ResolveInfo> list = pm.queryIntentActivities(intent,
-                    PackageManager.MATCH_DEFAULT_ONLY);
-            if (list.size() > 0) {
-                Drawable icon = list.get(0).activityInfo.loadIcon(pm);
-                iv.setImageDrawable(icon);
-                iv.setVisibility(View.VISIBLE);
-            } else {
-                iv.setVisibility(View.INVISIBLE);
-            }
-        }
-        
-        TextView tv = (TextView) convertView.findViewById(R.id.download_title);
-        String title = getString(mTitleColumnId);
-        if (title == null) {
-            title = r.getString(R.string.download_unknown_filename);
-        }
-        tv.setText(title);
-        
-        tv = (TextView) convertView.findViewById(R.id.domain);
-        tv.setText(getString(mDescColumnId));
-        
-        long totalBytes = getLong(mTotalBytesColumnId);
-        
-        int status = getInt(mStatusColumnId);
-        if (Downloads.Impl.isStatusCompleted(status)) { // Download stopped
-            View v = convertView.findViewById(R.id.progress_text);
-            v.setVisibility(View.GONE);
-
-            v = convertView.findViewById(R.id.download_progress);
-            v.setVisibility(View.GONE);
-
-            tv = (TextView) convertView.findViewById(R.id.complete_text);
-            tv.setVisibility(View.VISIBLE);
-            if (Downloads.Impl.isStatusError(status)) {
-                tv.setText(getErrorText(status));
-            } else {
-                tv.setText(r.getString(R.string.download_success, 
-                        Formatter.formatFileSize(context, totalBytes)));
-            }
-            
-            long time = getLong(mDateColumnId);
-            Date d = new Date(time);
-            DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
-            tv = (TextView) convertView.findViewById(R.id.complete_date);
-            tv.setVisibility(View.VISIBLE);
-            tv.setText(df.format(d));
-            
-        } else { // Download is still running
-            tv = (TextView) convertView.findViewById(R.id.progress_text);
-            tv.setVisibility(View.VISIBLE);
-
-            View progress = convertView.findViewById(R.id.download_progress);
-            progress.setVisibility(View.VISIBLE);
-            
-            View v = convertView.findViewById(R.id.complete_date);
-            v.setVisibility(View.GONE);
-
-            v = convertView.findViewById(R.id.complete_text);
-            v.setVisibility(View.GONE);
-            
-            if (status == Downloads.Impl.STATUS_PENDING) {
-                tv.setText(r.getText(R.string.download_pending));
-            } else if (status == Downloads.Impl.STATUS_PENDING_PAUSED) {
-                tv.setText(r.getText(R.string.download_pending_network));
-            } else {
-                ProgressBar pb = (ProgressBar) progress;
-
-                StringBuilder sb = new StringBuilder();
-                if (status == Downloads.Impl.STATUS_RUNNING) {
-                    sb.append(r.getText(R.string.download_running));
-                } else {
-                    sb.append(r.getText(R.string.download_running_paused));
-                }
-                if (totalBytes > 0) {
-                    long currentBytes = getLong(mCurrentBytesColumnId);
-                    int progressAmount = (int)(currentBytes * 100 / totalBytes);
-                    sb.append(' ');
-                    sb.append(progressAmount);
-                    sb.append("% (");
-                    sb.append(Formatter.formatFileSize(context, currentBytes));
-                    sb.append("/");
-                    sb.append(Formatter.formatFileSize(context, totalBytes));
-                    sb.append(")");
-                    pb.setIndeterminate(false);
-                    pb.setProgress(progressAmount);
-                } else {
-                    pb.setIndeterminate(true);
-                }
-                tv.setText(sb.toString()); 
-            }
-        }
-        return convertView;
-    }
-    
-    /**
-     * Provide the resource id for the error string.
-     * @param status status of the download item
-     * @return resource id for the error string.
-     */
-    public static int getErrorText(int status) {
-        switch (status) {
-            case Downloads.Impl.STATUS_NOT_ACCEPTABLE:
-                return R.string.download_not_acceptable;
-                
-            case Downloads.Impl.STATUS_LENGTH_REQUIRED:
-                return R.string.download_length_required;
-                
-            case Downloads.Impl.STATUS_PRECONDITION_FAILED:
-                return R.string.download_precondition_failed;
-                
-            case Downloads.Impl.STATUS_CANCELED:
-                return R.string.download_canceled;
-
-            case Downloads.Impl.STATUS_FILE_ERROR:
-                return R.string.download_file_error;
-                
-            case Downloads.Impl.STATUS_BAD_REQUEST:
-            case Downloads.Impl.STATUS_UNKNOWN_ERROR:
-            default:
-                return R.string.download_error;
-        }
-    }
-}
diff --git a/src/com/android/browser/BrowserDownloadPage.java b/src/com/android/browser/BrowserDownloadPage.java
deleted file mode 100644
index 18faf8b..0000000
--- a/src/com/android/browser/BrowserDownloadPage.java
+++ /dev/null
@@ -1,535 +0,0 @@
-/*
- * Copyright (C) 2007 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.app.AlertDialog;
-import android.app.ExpandableListActivity;
-import android.content.ActivityNotFoundException;
-import android.content.ContentValues;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.ContentUris;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.provider.Downloads;
-import android.util.Log;
-import android.view.ContextMenu;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.MenuInflater;
-import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.AdapterView;
-import android.widget.ExpandableListView;
-
-import java.io.File;
-import java.util.List;
-
-/**
- *  View showing the user's current browser downloads
- */
-public class BrowserDownloadPage extends ExpandableListActivity {
-    private ExpandableListView      mListView;
-    private Cursor                  mDownloadCursor;
-    private BrowserDownloadAdapter  mDownloadAdapter;
-    private int                     mStatusColumnId;
-    private int                     mIdColumnId;
-    private int                     mTitleColumnId;
-    private long                    mContextMenuPosition;
-    // Used to update the ContextMenu if an item is being downloaded and the
-    // user opens the ContextMenu.
-    private ContentObserver         mContentObserver;
-    // Only meaningful while a ContentObserver is registered.  The ContextMenu
-    // will be reopened on this View.
-    private View                    mSelectedView;
-
-    private final static String LOGTAG = "BrowserDownloadPage";
-    @Override 
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-        setContentView(R.layout.browser_downloads_page);
-        
-        setTitle(getText(R.string.download_title));
-
-        mListView = (ExpandableListView) findViewById(android.R.id.list);
-        mListView.setEmptyView(findViewById(R.id.empty));
-        mDownloadCursor = managedQuery(Downloads.Impl.CONTENT_URI,
-                new String [] {Downloads.Impl._ID, Downloads.Impl.COLUMN_TITLE,
-                Downloads.Impl.COLUMN_STATUS, Downloads.Impl.COLUMN_TOTAL_BYTES,
-                Downloads.Impl.COLUMN_CURRENT_BYTES,
-                Downloads.Impl.COLUMN_DESCRIPTION,
-                Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE,
-                Downloads.Impl.COLUMN_LAST_MODIFICATION,
-                Downloads.Impl.COLUMN_VISIBILITY,
-                Downloads.Impl._DATA,
-                Downloads.Impl.COLUMN_MIME_TYPE},
-                null, Downloads.Impl.COLUMN_LAST_MODIFICATION + " DESC");
-        
-        // only attach everything to the listbox if we can access
-        // the download database. Otherwise, just show it empty
-        if (mDownloadCursor != null) {
-            mStatusColumnId = 
-                    mDownloadCursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_STATUS);
-            mIdColumnId =
-                    mDownloadCursor.getColumnIndexOrThrow(Downloads.Impl._ID);
-            mTitleColumnId = 
-                    mDownloadCursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_TITLE);
-            
-            // Create a list "controller" for the data
-            mDownloadAdapter = new BrowserDownloadAdapter(this, 
-                    mDownloadCursor, mDownloadCursor.getColumnIndexOrThrow(
-                    Downloads.Impl.COLUMN_LAST_MODIFICATION));
-
-            setListAdapter(mDownloadAdapter);
-            mListView.setOnCreateContextMenuListener(this);
-
-            Intent intent = getIntent();
-            final int groupToShow = intent == null || intent.getData() == null
-                    ? 0 : checkStatus(ContentUris.parseId(intent.getData()));
-            if (mDownloadAdapter.getGroupCount() > groupToShow) {
-                mListView.post(new Runnable() {
-                    public void run() {
-                        if (mDownloadAdapter.getGroupCount() > groupToShow) {
-                            mListView.expandGroup(groupToShow);
-                        }
-                    }
-                });
-            }
-        }
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        if (mDownloadCursor != null) {
-            String where = null;
-            for (mDownloadCursor.moveToFirst(); !mDownloadCursor.isAfterLast();
-                    mDownloadCursor.moveToNext()) {
-                if (!Downloads.Impl.isStatusCompleted(
-                        mDownloadCursor.getInt(mStatusColumnId))) {
-                    // Only want to check files that have completed.
-                    continue;
-                }
-                int filenameColumnId = mDownloadCursor.getColumnIndexOrThrow(
-                        Downloads.Impl._DATA);
-                String filename = mDownloadCursor.getString(filenameColumnId);
-                if (filename != null) {
-                    File file = new File(filename);
-                    if (!file.exists()) {
-                        long id = mDownloadCursor.getLong(mIdColumnId);
-                        if (where == null) {
-                            where = Downloads.Impl._ID + " = '" + id + "'";
-                        } else {
-                            where += " OR " + Downloads.Impl._ID + " = '" + id
-                                    + "'";
-                        }
-                    }
-                }
-            }
-            if (where != null) {
-                getContentResolver().delete(Downloads.Impl.CONTENT_URI, where,
-                        null);
-            }
-        }
-    }
-
-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        if (mDownloadCursor != null) {
-            MenuInflater inflater = getMenuInflater();
-            inflater.inflate(R.menu.downloadhistory, menu);
-        }
-        return true;
-    }
-    
-    @Override
-    public boolean onPrepareOptionsMenu(Menu menu) {
-        boolean showCancel = getCancelableCount() > 0;
-        menu.findItem(R.id.download_menu_cancel_all).setEnabled(showCancel);
-        return super.onPrepareOptionsMenu(menu);
-    }
-    
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        switch (item.getItemId()) {
-            case R.id.download_menu_cancel_all:
-                promptCancelAll();
-                return true;
-        }
-        return false;
-    }
-
-    /**
-     * Remove the file from the list of downloads.
-     * @param id Unique ID of the download to remove.
-     */
-    private void clearFromDownloads(long id) {
-        getContentResolver().delete(ContentUris.withAppendedId(
-                Downloads.Impl.CONTENT_URI, id), null, null);
-    }
-
-    @Override
-    public boolean onContextItemSelected(MenuItem item) {
-        if (!mDownloadAdapter.moveCursorToPackedChildPosition(
-                mContextMenuPosition)) {
-            return false;
-        }
-        switch (item.getItemId()) {
-            case R.id.download_menu_open:
-                hideCompletedDownload();
-                openOrDeleteCurrentDownload(false);
-                return true;
-
-            case R.id.download_menu_delete:
-                new AlertDialog.Builder(this)
-                        .setTitle(R.string.download_delete_file)
-                        .setIcon(android.R.drawable.ic_dialog_alert)
-                        .setMessage(mDownloadCursor.getString(mTitleColumnId))
-                        .setNegativeButton(R.string.cancel, null)
-                        .setPositiveButton(R.string.ok,
-                                new DialogInterface.OnClickListener() {
-                                    public void onClick(DialogInterface dialog,
-                                            int whichButton) {
-                                        openOrDeleteCurrentDownload(true);
-                                    }
-                                })
-                        .show();
-                break;
-
-            case R.id.download_menu_clear:
-            case R.id.download_menu_cancel:
-                clearFromDownloads(mDownloadCursor.getLong(mIdColumnId));
-                return true;
-        }
-        return false;
-    }
-
-    @Override
-    protected void onPause() {
-        super.onPause();
-        if (mContentObserver != null) {
-            getContentResolver().unregisterContentObserver(mContentObserver);
-            // Note that we do not need to undo this in onResume, because the
-            // ContextMenu does not get reinvoked when the Activity resumes.
-        }
-    }
-
-    /*
-     * ContentObserver to update the ContextMenu if it is open when the
-     * corresponding download completes.
-     */
-    private class ChangeObserver extends ContentObserver {
-        private final Uri mTrack;
-        public ChangeObserver(Uri track) {
-            super(new Handler());
-            mTrack = track;
-        }
-
-        @Override
-        public boolean deliverSelfNotifications() {
-            return false;
-        }
-
-        @Override
-        public void onChange(boolean selfChange) {
-            Cursor cursor = null;
-            try {
-                cursor = getContentResolver().query(mTrack,
-                        new String[] { Downloads.Impl.COLUMN_STATUS }, null, null,
-                        null);
-                if (cursor.moveToFirst() && Downloads.Impl.isStatusSuccess(
-                        cursor.getInt(0))) {
-                    // Do this right away, so we get no more updates.
-                    getContentResolver().unregisterContentObserver(
-                            mContentObserver);
-                    // Post a runnable in case this ContentObserver gets notified
-                    // before the one that updates the ListView.
-                    mListView.post(new Runnable() {
-                        public void run() {
-                            // Close the context menu, reopen with up to date data.
-                            closeContextMenu();
-                            openContextMenu(mSelectedView);
-                        }
-                    });
-                }
-            } catch (IllegalStateException e) {
-                Log.e(LOGTAG, "onChange", e);
-            } finally {
-                if (cursor != null) cursor.close();
-            }
-        }
-    }
-
-    @Override
-    public void onCreateContextMenu(ContextMenu menu, View v,
-            ContextMenuInfo menuInfo) {
-        if (mDownloadCursor != null) {
-            ExpandableListView.ExpandableListContextMenuInfo info
-                    = (ExpandableListView.ExpandableListContextMenuInfo) menuInfo;
-            long packedPosition = info.packedPosition;
-            // Only show a context menu for the child views
-            if (!mDownloadAdapter.moveCursorToPackedChildPosition(
-                    packedPosition)) {
-                return;
-            }
-            mContextMenuPosition = packedPosition;
-            menu.setHeaderTitle(mDownloadCursor.getString(mTitleColumnId));
-            
-            MenuInflater inflater = getMenuInflater();
-            int status = mDownloadCursor.getInt(mStatusColumnId);
-            if (Downloads.Impl.isStatusSuccess(status)) {
-                inflater.inflate(R.menu.downloadhistorycontextfinished, menu);
-            } else if (Downloads.Impl.isStatusError(status)) {
-                inflater.inflate(R.menu.downloadhistorycontextfailed, menu);
-            } else {
-                // In this case, the download is in progress.  Set a
-                // ContentObserver so that we can know when it completes,
-                // and if it does, we can then update the context menu
-                Uri track = ContentUris.withAppendedId(
-                        Downloads.Impl.CONTENT_URI,
-                        mDownloadCursor.getLong(mIdColumnId));
-                if (mContentObserver != null) {
-                    getContentResolver().unregisterContentObserver(
-                            mContentObserver);
-                }
-                mContentObserver = new ChangeObserver(track);
-                mSelectedView = v;
-                getContentResolver().registerContentObserver(track, false,
-                        mContentObserver);
-                inflater.inflate(R.menu.downloadhistorycontextrunning, menu);
-            }
-        }
-        super.onCreateContextMenu(menu, v, menuInfo);
-    }
-
-    /**
-     * This function is called to check the status of the download and if it
-     * has an error show an error dialog.
-     * @param id Row id of the download to check
-     * @return Group which contains the download
-     */
-    private int checkStatus(final long id) {
-        int groupToShow = mDownloadAdapter.groupFromChildId(id);
-        if (-1 == groupToShow) return 0;
-        int status = mDownloadCursor.getInt(mStatusColumnId);
-        if (!Downloads.Impl.isStatusError(status)) {
-            return groupToShow;
-        }
-        if (status == Downloads.Impl.STATUS_FILE_ERROR) {
-            String title = mDownloadCursor.getString(mTitleColumnId);
-            if (title == null || title.length() == 0) {
-                title = getString(R.string.download_unknown_filename);
-            }
-            String msg = getString(R.string.download_file_error_dlg_msg, title);
-            new AlertDialog.Builder(this)
-                    .setTitle(R.string.download_file_error_dlg_title)
-                    .setIcon(android.R.drawable.ic_popup_disk_full)
-                    .setMessage(msg)
-                    .setPositiveButton(R.string.ok, null)
-                    .setNegativeButton(R.string.retry,
-                            new DialogInterface.OnClickListener() {
-                                public void onClick(DialogInterface dialog,
-                                        int whichButton) {
-                                    resumeDownload(id);
-                                }
-                            })
-                    .show();
-        } else {
-            new AlertDialog.Builder(this)
-                    .setTitle(R.string.download_failed_generic_dlg_title)
-                    .setIcon(R.drawable.ssl_icon)
-                    .setMessage(BrowserDownloadAdapter.getErrorText(status))
-                    .setPositiveButton(R.string.ok, null)
-                    .show();
-        }
-        return groupToShow;
-    }
-    
-    /**
-     * Resume a given download
-     * @param id Row id of the download to resume
-     */
-    private void resumeDownload(final long id) {
-        // the relevant functionality doesn't exist in the download manager
-    }
-    
-    /**
-     * Return the number of items in the list that can be canceled.
-     * @return count
-     */
-    private int getCancelableCount() {
-        // Count the number of items that will be canceled.
-        int count = 0;
-        if (mDownloadCursor != null) {
-            for (mDownloadCursor.moveToFirst(); !mDownloadCursor.isAfterLast();
-                    mDownloadCursor.moveToNext()) {
-                int status = mDownloadCursor.getInt(mStatusColumnId);
-                if (!Downloads.Impl.isStatusCompleted(status)) {
-                    count++;
-                }
-            }
-        }
-        
-        return count;
-    }
-    
-    /**
-     * Prompt the user if they would like to clear the download history
-     */
-    private void promptCancelAll() {
-        int count = getCancelableCount();
-        
-        // If there is nothing to do, just return
-        if (count == 0) {
-            return;
-        }
-        
-        // Don't show the dialog if there is only one download
-        if (count == 1) {
-            cancelAllDownloads();
-            return;
-        }
-        String msg = 
-            getString(R.string.download_cancel_dlg_msg, count);
-        new AlertDialog.Builder(this)
-                .setTitle(R.string.download_cancel_dlg_title)
-                .setIcon(R.drawable.ssl_icon)
-                .setMessage(msg)
-                .setPositiveButton(R.string.ok, 
-                        new DialogInterface.OnClickListener() {
-                            public void onClick(DialogInterface dialog, 
-                                    int whichButton) {
-                                cancelAllDownloads();
-                            }
-                        })
-                 .setNegativeButton(R.string.cancel, null)
-                 .show();
-    }
-    
-    /**
-     * Cancel all downloads. As canceled downloads are not
-     * listed, we removed them from the db. Removing a download
-     * record, cancels the download.
-     */
-    private void cancelAllDownloads() {
-        if (mDownloadCursor.moveToFirst()) {
-            StringBuilder where = new StringBuilder();
-            boolean firstTime = true;
-            while (!mDownloadCursor.isAfterLast()) {
-                int status = mDownloadCursor.getInt(mStatusColumnId);
-                if (!Downloads.Impl.isStatusCompleted(status)) {
-                    if (firstTime) {
-                        firstTime = false;
-                    } else {
-                        where.append(" OR ");
-                    }
-                    where.append("( ");
-                    where.append(Downloads.Impl._ID);
-                    where.append(" = '");
-                    where.append(mDownloadCursor.getLong(mIdColumnId));
-                    where.append("' )");
-                }
-                mDownloadCursor.moveToNext();
-            }
-            if (!firstTime) {
-                getContentResolver().delete(Downloads.Impl.CONTENT_URI,
-                        where.toString(), null);
-            }
-        }
-    }
-    
-    private int getClearableCount() {
-        int count = 0;
-        if (mDownloadCursor.moveToFirst()) {
-            while (!mDownloadCursor.isAfterLast()) {
-                int status = mDownloadCursor.getInt(mStatusColumnId);
-                if (Downloads.Impl.isStatusCompleted(status)) {
-                    count++;
-                }
-                mDownloadCursor.moveToNext();
-            }
-        }
-        return count;
-    }
-
-    /**
-     * Open or delete content where the download db cursor currently is.  Sends
-     * an Intent to perform the action.
-     * @param delete If true, delete the content.  Otherwise open it.
-     */
-    private void openOrDeleteCurrentDownload(boolean delete) {
-        int packageColumnId = mDownloadCursor.getColumnIndexOrThrow(
-                Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE);
-        String packageName = mDownloadCursor.getString(packageColumnId);
-        Intent intent = new Intent(delete ? Intent.ACTION_DELETE
-                : Downloads.Impl.ACTION_NOTIFICATION_CLICKED);
-        Uri contentUri = ContentUris.withAppendedId(
-                Downloads.Impl.CONTENT_URI,
-                mDownloadCursor.getLong(mIdColumnId));
-        intent.setData(contentUri);
-        intent.setPackage(packageName);
-        sendBroadcast(intent);
-    }
-
-    @Override
-    public boolean onChildClick(ExpandableListView parent, View v,
-            int groupPosition, int childPosition, long id) {
-        // Open the selected item
-        mDownloadAdapter.moveCursorToChildPosition(groupPosition,
-                childPosition);
-        
-        hideCompletedDownload();
-
-        int status = mDownloadCursor.getInt(mStatusColumnId);
-        if (Downloads.Impl.isStatusSuccess(status)) {
-            // Open it if it downloaded successfully
-            openOrDeleteCurrentDownload(false);
-        } else {
-            // Check to see if there is an error.
-            checkStatus(id);
-        }
-        return true;
-    }
-    
-    /**
-     * hides the notification for the download pointed by mDownloadCursor
-     * if the download has completed.
-     */
-    private void hideCompletedDownload() {
-        int status = mDownloadCursor.getInt(mStatusColumnId);
-
-        int visibilityColumn = mDownloadCursor.getColumnIndexOrThrow(
-                Downloads.Impl.COLUMN_VISIBILITY);
-        int visibility = mDownloadCursor.getInt(visibilityColumn);
-
-        if (Downloads.Impl.isStatusCompleted(status) &&
-                visibility == Downloads.Impl.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) {
-            ContentValues values = new ContentValues();
-            values.put(Downloads.Impl.COLUMN_VISIBILITY, Downloads.Impl.VISIBILITY_VISIBLE);
-            getContentResolver().update(
-                    ContentUris.withAppendedId(Downloads.Impl.CONTENT_URI,
-                    mDownloadCursor.getLong(mIdColumnId)), values, null, null);
-        }
-    }
-}
diff --git a/src/com/android/browser/BrowserPreferencesPage.java b/src/com/android/browser/BrowserPreferencesPage.java
index 6426b99..9af66f1 100644
--- a/src/com/android/browser/BrowserPreferencesPage.java
+++ b/src/com/android/browser/BrowserPreferencesPage.java
@@ -16,24 +16,19 @@
 
 package com.android.browser;
 
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.Vector;
-
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
 import android.preference.EditTextPreference;
-import android.preference.ListPreference;
 import android.preference.Preference;
 import android.preference.PreferenceActivity;
 import android.preference.PreferenceScreen;
-import android.util.Log;
 import android.webkit.GeolocationPermissions;
 import android.webkit.ValueCallback;
 import android.webkit.WebStorage;
-import android.webkit.WebView;
+
+import java.util.Map;
+import java.util.Set;
 
 public class BrowserPreferencesPage extends PreferenceActivity
         implements Preference.OnPreferenceChangeListener {
@@ -119,6 +114,7 @@
 
         // sync the shared preferences back to BrowserSettings
         BrowserSettings.getInstance().syncSharedPreferences(
+                getApplicationContext(),
                 getPreferenceScreen().getSharedPreferences());
     }
 
diff --git a/src/com/android/browser/BrowserProvider.java b/src/com/android/browser/BrowserProvider.java
index a6ceb8b..72ec819 100644
--- a/src/com/android/browser/BrowserProvider.java
+++ b/src/com/android/browser/BrowserProvider.java
@@ -16,10 +16,10 @@
 
 package com.android.browser;
 
+import com.android.browser.search.SearchEngine;
+
 import android.app.SearchManager;
-import android.app.SearchableInfo;
 import android.app.backup.BackupManager;
-import android.content.ComponentName;
 import android.content.ContentProvider;
 import android.content.ContentResolver;
 import android.content.ContentUris;
@@ -27,28 +27,21 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
-import android.content.UriMatcher;
 import android.content.SharedPreferences.Editor;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
+import android.content.UriMatcher;
 import android.database.AbstractCursor;
-import android.database.ContentObserver;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteOpenHelper;
 import android.net.Uri;
-import android.os.Handler;
 import android.os.Process;
 import android.preference.PreferenceManager;
 import android.provider.Browser;
-import android.provider.Settings;
 import android.provider.Browser.BookmarkColumns;
 import android.speech.RecognizerResultsIntent;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Patterns;
-import android.util.TypedValue;
-
 
 import java.io.File;
 import java.io.FilenameFilter;
@@ -166,7 +159,7 @@
     // optionally a trailing slash, all matched as separate groups.
     private static final Pattern STRIP_URL_PATTERN = Pattern.compile("^(http://)(.*?)(/$)?");
 
-    private SearchManager mSearchManager;
+    private BrowserSettings mSettings;
 
     public BrowserProvider() {
     }
@@ -385,62 +378,13 @@
                 fixPicasaBookmark();
                 Editor ed = p.edit();
                 ed.putBoolean("fix_picasa", false);
-                ed.commit();
+                ed.apply();
             }
         }
-        mSearchManager = (SearchManager) context.getSystemService(Context.SEARCH_SERVICE);
-        mShowWebSuggestionsSettingChangeObserver
-            = new ShowWebSuggestionsSettingChangeObserver();
-        context.getContentResolver().registerContentObserver(
-                Settings.System.getUriFor(
-                        Settings.System.SHOW_WEB_SUGGESTIONS),
-                true, mShowWebSuggestionsSettingChangeObserver);
-        updateShowWebSuggestions();
+        mSettings = BrowserSettings.getInstance();
         return true;
     }
 
-    /**
-     * This Observer will ensure that if the user changes the system
-     * setting of whether to display web suggestions, we will
-     * change accordingly.
-     */
-    /* package */ class ShowWebSuggestionsSettingChangeObserver
-            extends ContentObserver {
-        public ShowWebSuggestionsSettingChangeObserver() {
-            super(new Handler());
-        }
-
-        @Override
-        public void onChange(boolean selfChange) {
-            updateShowWebSuggestions();
-        }
-    }
-
-    private ShowWebSuggestionsSettingChangeObserver
-            mShowWebSuggestionsSettingChangeObserver;
-
-    // If non-null, then the system is set to show web suggestions,
-    // and this is the SearchableInfo to use to get them.
-    private SearchableInfo mSearchableInfo;
-
-    /**
-     * Check the system settings to see whether web suggestions are
-     * allowed.  If so, store the SearchableInfo to grab suggestions
-     * while the user is typing.
-     */
-    private void updateShowWebSuggestions() {
-        mSearchableInfo = null;
-        Context context = getContext();
-        if (Settings.System.getInt(context.getContentResolver(),
-                Settings.System.SHOW_WEB_SUGGESTIONS,
-                1 /* default on */) == 1) {
-            ComponentName webSearchComponent = mSearchManager.getWebSearchActivity();
-            if (webSearchComponent != null) {
-                mSearchableInfo = mSearchManager.getSearchableInfo(webSearchComponent);
-            }
-        }
-    }
-
     private void fixPicasaBookmark() {
         SQLiteDatabase db = mOpenHelper.getWritableDatabase();
         Cursor cursor = db.rawQuery("SELECT _id FROM bookmarks WHERE " +
@@ -897,12 +841,14 @@
                     || Patterns.WEB_URL.matcher(selectionArgs[0]).matches()) {
                 return new MySuggestionCursor(c, null, "");
             } else {
-                // get Google suggest if there is still space in the list
+                // get search suggestions if there is still space in the list
                 if (myArgs != null && myArgs.length > 1
-                        && mSearchableInfo != null
                         && c.getCount() < (MAX_SUGGESTION_SHORT_ENTRIES - 1)) {
-                    Cursor sc = mSearchManager.getSuggestions(mSearchableInfo, selectionArgs[0]);
-                    return new MySuggestionCursor(c, sc, selectionArgs[0]);
+                    SearchEngine searchEngine = mSettings.getSearchEngine();
+                    if (searchEngine != null && searchEngine.supportsSuggestions()) {
+                        Cursor sc = searchEngine.getSuggestions(getContext(), selectionArgs[0]);
+                        return new MySuggestionCursor(c, sc, selectionArgs[0]);
+                    }
                 }
                 return new MySuggestionCursor(c, null, selectionArgs[0]);
             }
diff --git a/src/com/android/browser/BrowserSettings.java b/src/com/android/browser/BrowserSettings.java
index 3d5ca03..3791eb0 100644
--- a/src/com/android/browser/BrowserSettings.java
+++ b/src/com/android/browser/BrowserSettings.java
@@ -17,14 +17,22 @@
 
 package com.android.browser;
 
+import com.android.browser.search.SearchEngine;
+import com.android.browser.search.SearchEngines;
+
 import android.app.ActivityManager;
+import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.SharedPreferences;
 import android.content.SharedPreferences.Editor;
+import android.database.ContentObserver;
+import android.os.Handler;
 import android.preference.PreferenceActivity;
 import android.preference.PreferenceScreen;
+import android.provider.Settings;
+import android.util.Log;
 import android.webkit.CookieManager;
 import android.webkit.GeolocationPermissions;
 import android.webkit.ValueCallback;
@@ -71,6 +79,7 @@
     private boolean openInBackground;
     private String defaultTextEncodingName;
     private String homeUrl = "";
+    private SearchEngine searchEngine;
     private boolean autoFitPage;
     private boolean landscapeOnly;
     private boolean loadsPageInOverviewMode;
@@ -121,6 +130,7 @@
     public final static String PREF_CLEAR_COOKIES = "privacy_clear_cookies";
     public final static String PREF_CLEAR_HISTORY = "privacy_clear_history";
     public final static String PREF_HOMEPAGE = "homepage";
+    public final static String PREF_SEARCH_ENGINE = "search_engine";
     public final static String PREF_CLEAR_FORM_DATA =
             "privacy_clear_form_data";
     public final static String PREF_CLEAR_PASSWORDS =
@@ -137,12 +147,20 @@
             "privacy_clear_geolocation_access";
 
     private static final String DESKTOP_USERAGENT = "Mozilla/5.0 (Macintosh; " +
-            "U; Intel Mac OS X 10_5_7; en-us) AppleWebKit/530.17 (KHTML, " +
-            "like Gecko) Version/4.0 Safari/530.17";
+            "U; Intel Mac OS X 10_6_3; en-us) AppleWebKit/533.16 (KHTML, " +
+            "like Gecko) Version/5.0 Safari/533.16";
 
     private static final String IPHONE_USERAGENT = "Mozilla/5.0 (iPhone; U; " +
-            "CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 " +
-            "(KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16";
+            "CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 " +
+            "(KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7";
+
+    private static final String IPAD_USERAGENT = "Mozilla/5.0 (iPad; U; " +
+            "CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 " +
+            "(KHTML, like Gecko) Version/4.0.4 Mobile/7B367 Safari/531.21.10";
+
+    private static final String FROYO_USERAGENT = "Mozilla/5.0 (Linux; U; " +
+            "Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 " +
+            "(KHTML, like Gecko) Version/4.0 Mobile Safari/533.1";
 
     // Value to truncate strings when adding them to a TextView within
     // a ListView
@@ -182,6 +200,10 @@
                 s.setUserAgentString(DESKTOP_USERAGENT);
             } else if (b.userAgent == 2) {
                 s.setUserAgentString(IPHONE_USERAGENT);
+            } else if (b.userAgent == 3) {
+                s.setUserAgentString(IPAD_USERAGENT);
+            } else if (b.userAgent == 4) {
+                s.setUserAgentString(FROYO_USERAGENT);
             }
             s.setUseWideViewPort(b.useWideViewPort);
             s.setLoadsImagesAutomatically(b.loadsImagesAutomatically);
@@ -234,7 +256,7 @@
      *            stored in this BrowserSettings object. This will update all
      *            observers of this object.
      */
-    public void loadFromDb(Context ctx) {
+    public void loadFromDb(final Context ctx) {
         SharedPreferences p =
                 PreferenceManager.getDefaultSharedPreferences(ctx);
         // Set the default value for the Application Caches path.
@@ -266,17 +288,34 @@
             pageCacheCapacity = 1;
         }
 
-        // Load the defaults from the xml
+    // Load the defaults from the xml
         // This call is TOO SLOW, need to manually keep the defaults
         // in sync
         //PreferenceManager.setDefaultValues(ctx, R.xml.browser_preferences);
-        syncSharedPreferences(p);
+        syncSharedPreferences(ctx, p);
     }
 
-    /* package */ void syncSharedPreferences(SharedPreferences p) {
+    /* package */ void syncSharedPreferences(Context ctx, SharedPreferences p) {
 
         homeUrl =
             p.getString(PREF_HOMEPAGE, homeUrl);
+        String searchEngineName = p.getString(PREF_SEARCH_ENGINE,
+                SearchEngine.GOOGLE);
+        if (searchEngine == null || !searchEngine.getName().equals(searchEngineName)) {
+            if (searchEngine != null) {
+                if (searchEngine.supportsVoiceSearch()) {
+                    // One or more tabs could have been in voice search mode.
+                    // Clear it, since the new SearchEngine may not support
+                    // it, or may handle it differently.
+                    for (int i = 0; i < mTabControl.getTabCount(); i++) {
+                        mTabControl.getTab(i).revertVoiceSearchMode();
+                    }
+                }
+                searchEngine.close();
+            }
+            searchEngine = SearchEngines.get(ctx, searchEngineName);
+        }
+        Log.i(TAG, "Selected search engine: " + searchEngine);
 
         loadsImagesAutomatically = p.getBoolean("load_images",
                 loadsImagesAutomatically);
@@ -369,6 +408,10 @@
         return homeUrl;
     }
 
+    public SearchEngine getSearchEngine() {
+        return searchEngine;
+    }
+
     public String getJsFlags() {
         return jsFlags;
     }
@@ -381,7 +424,7 @@
         Editor ed = PreferenceManager.
                 getDefaultSharedPreferences(context).edit();
         ed.putString(PREF_HOMEPAGE, url);
-        ed.commit();
+        ed.apply();
         homeUrl = url;
     }
 
@@ -561,7 +604,7 @@
         reset();
         SharedPreferences p =
             PreferenceManager.getDefaultSharedPreferences(ctx);
-        p.edit().clear().commit();
+        p.edit().clear().apply();
         PreferenceManager.setDefaultValues(ctx, R.xml.browser_preferences,
                 true);
         // reset homeUrl
diff --git a/src/com/android/browser/FindDialog.java b/src/com/android/browser/FindDialog.java
index 45c8016..726138e 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,18 @@
             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.
+                    // FIXME: is this fix is beyond the scope
+                    // of adding touch selection to gingerbread?
+                    // mMatches.setText(mBrowserActivity.getResources().getString(
+                    //        R.string.no_matches));
                 }
             } else {
                 mPrevButton.setFocusable(true);
@@ -203,8 +223,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/OpenDownloadReceiver.java b/src/com/android/browser/OpenDownloadReceiver.java
index 814aa9c..99e5f41 100644
--- a/src/com/android/browser/OpenDownloadReceiver.java
+++ b/src/com/android/browser/OpenDownloadReceiver.java
@@ -16,23 +16,24 @@
 
 package com.android.browser;
 
+import android.app.DownloadManager;
 import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.database.Cursor;
-import android.database.DatabaseUtils;
 import android.net.Uri;
 import android.provider.Downloads;
-import android.provider.MediaStore;
 import android.widget.Toast;
 
 import java.io.File;
 
 /**
- * This {@link BroadcastReceiver} handles {@link Intent}s to open and delete
- * files downloaded by the Browser.
+ * This {@link BroadcastReceiver} handles clicks to notifications that
+ * downloads from the browser are in progress/complete.  Clicking on an
+ * in-progress or failed download will open the download manager.  Clicking on
+ * a complete, successful download will open the file.
  */
 public class OpenDownloadReceiver extends BroadcastReceiver {
     public void onReceive(Context context, Intent intent) {
@@ -69,44 +70,15 @@
                         }
                     } else {
                         // Open the downloads page
-                        Intent pageView = new Intent(context,
-                                BrowserDownloadPage.class);
-                        pageView.setData(data);
+                        Intent pageView = new Intent(
+                                DownloadManager.ACTION_VIEW_DOWNLOADS);
                         pageView.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                         context.startActivity(pageView);
                     }
-                } else if (Intent.ACTION_DELETE.equals(action)) {
-                    if (deleteFile(cr, filename, mimetype)) {
-                        cr.delete(data, null, null);
-                    }
                 }
             }
         } finally {
             if (cursor != null) cursor.close();
         }
     }
-
-    /**
-     * Remove the file from the SD card
-     * @param cr ContentResolver used to delete the file.
-     * @param filename Name of the file to delete.
-     * @param mimetype Mimetype of the file to delete.
-     * @return boolean True on success, false on failure.
-     */
-    private boolean deleteFile(ContentResolver cr, String filename,
-            String mimetype) {
-        Uri uri;
-        if (mimetype.startsWith("image")) {
-            uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
-        } else if (mimetype.startsWith("audio")) {
-            uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
-        } else if (mimetype.startsWith("video")) {
-            uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
-        } else {
-            uri = null;
-        }
-        return (uri != null && cr.delete(uri, MediaStore.MediaColumns.DATA
-                + " = " + DatabaseUtils.sqlEscapeString(filename), null) > 0)
-                || new File(filename).delete();
-    }
 }
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/SystemAllowGeolocationOrigins.java b/src/com/android/browser/SystemAllowGeolocationOrigins.java
index 3f5a84e..b53611f 100644
--- a/src/com/android/browser/SystemAllowGeolocationOrigins.java
+++ b/src/com/android/browser/SystemAllowGeolocationOrigins.java
@@ -103,7 +103,7 @@
         // Save the new value as the last read value
         preferences.edit()
                 .putString(LAST_READ_ALLOW_GEOLOCATION_ORIGINS, newSetting)
-                .commit();
+                .apply();
 
         Set<String> oldOrigins = parseAllowGeolocationOrigins(lastReadSetting);
         Set<String> newOrigins = parseAllowGeolocationOrigins(newSetting);
diff --git a/src/com/android/browser/Tab.java b/src/com/android/browser/Tab.java
index b31abc2..7019c8a 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
@@ -151,7 +151,6 @@
     static final String CURRTAB = "currentTab";
     static final String CURRURL = "currentUrl";
     static final String CURRTITLE = "currentTitle";
-    static final String CURRPICTURE = "currentPicture";
     static final String CLOSEONEXIT = "closeonexit";
     static final String PARENTTAB = "parentTab";
     static final String APPID = "appid";
@@ -165,14 +164,25 @@
      */
     private VoiceSearchData mVoiceSearchData;
     /**
+     * Remove voice search mode from this tab.
+     */
+    public void revertVoiceSearchMode() {
+        if (mVoiceSearchData != null) {
+            mVoiceSearchData = null;
+            if (mInForeground) {
+                mActivity.revertVoiceTitleBar();
+            }
+        }
+    }
+    /**
      * Return whether the tab is in voice search mode.
      */
     public boolean isInVoiceSearchMode() {
         return mVoiceSearchData != null;
     }
     /**
-     * Return true if the voice search Intent came with a String identifying
-     * that Google provided the Intent.
+     * Return true if the Tab is in voice search mode and the voice search
+     * Intent came with a String identifying that Google provided the Intent.
      */
     public boolean voiceSearchSourceIsGoogle() {
         return mVoiceSearchData != null && mVoiceSearchData.mSourceIsGoogle;
@@ -457,10 +467,7 @@
                     i.putExtra(LoggingEvents.EXTRA_FLUSH, true);
                     mActivity.sendBroadcast(i);
                 }
-                mVoiceSearchData = null;
-                if (mInForeground) {
-                    mActivity.revertVoiceTitleBar();
-                }
+                revertVoiceSearchMode();
             }
 
             // We've started to load a new page. If there was a pending message
@@ -529,6 +536,18 @@
         // return true if want to hijack the url to let another app to handle it
         @Override
         public boolean shouldOverrideUrlLoading(WebView view, String url) {
+            if (voiceSearchSourceIsGoogle()) {
+                // This method is called when the user clicks on a link.
+                // VoiceSearchMode is turned off when the user leaves the
+                // Google results page, so at this point the user must be on
+                // that page.  If the user clicked a link on that page, assume
+                // that the voice search was effective, and broadcast an Intent
+                // so a receiver can take note of that fact.
+                Intent logIntent = new Intent(LoggingEvents.ACTION_LOG_EVENT);
+                logIntent.putExtra(LoggingEvents.EXTRA_EVENT,
+                        LoggingEvents.VoiceSearch.RESULT_CLICKED);
+                mActivity.sendBroadcast(logIntent);
+            }
             if (mInForeground) {
                 return mActivity.shouldOverrideUrlLoading(view, url);
             } else {
@@ -1029,6 +1048,16 @@
         }
 
         @Override
+        public void onSelectionDone(WebView view) {
+            if (mInForeground) mActivity.closeDialogs();
+        }
+
+        @Override
+        public void onSelectionStart(WebView view) {
+            if (false && mInForeground) mActivity.showSelectDialog();
+        }
+
+        @Override
         public void onShowCustomView(View view,
                 WebChromeClient.CustomViewCallback callback) {
             if (mInForeground) mActivity.onShowCustomView(view, callback);
@@ -1208,9 +1237,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 +1338,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 +1449,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 +1458,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
@@ -1433,7 +1473,7 @@
                     if (mSubView.copyBackForwardList().getSize() == 0) {
                         // This subwindow was opened for the sole purpose of
                         // downloading a file. Remove it.
-                        dismissSubWindow();
+                        mActivity.dismissSubWindow(Tab.this);
                     }
                 }
             });
@@ -1457,6 +1497,7 @@
      */
     void dismissSubWindow() {
         if (mSubView != null) {
+            mActivity.closeDialogs();
             BrowserSettings.getInstance().deleteObserver(
                     mSubView.getSettings());
             mSubView.destroy();
@@ -1481,6 +1522,7 @@
     void removeSubWindow(ViewGroup content) {
         if (mSubView != null) {
             content.removeView(mSubViewContainer);
+            mActivity.closeDialogs();
         }
     }
 
@@ -1539,6 +1581,7 @@
                 (FrameLayout) mContainer.findViewById(R.id.webview_wrapper);
         wrapper.removeView(mMainView);
         content.removeView(mContainer);
+        mActivity.closeDialogs();
         removeSubWindow(content);
     }
 
@@ -1871,17 +1914,6 @@
 
         mSavedState = new Bundle();
         final WebBackForwardList list = mMainView.saveState(mSavedState);
-        if (list != null) {
-            final File f = new File(mActivity.getTabControl().getThumbnailDir(),
-                    mMainView.hashCode() + "_pic.save");
-            if (mMainView.savePicture(mSavedState, f)) {
-                mSavedState.putString(CURRPICTURE, f.getPath());
-            } else {
-                // if savePicture returned false, we can't trust the contents,
-                // and it may be large, so we delete it right away
-                f.delete();
-            }
-        }
 
         // Store some extra info for displaying the tab in the picker.
         final WebHistoryItem item = list != null ? list.getCurrentItem() : null;
@@ -1927,11 +1959,38 @@
         if (list == null) {
             return false;
         }
-        if (b.containsKey(CURRPICTURE)) {
-            final File f = new File(b.getString(CURRPICTURE));
-            mMainView.restorePicture(b, f);
-            f.delete();
-        }
         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/TabControl.java b/src/com/android/browser/TabControl.java
index 7cd2ccb..afd4ea8 100644
--- a/src/com/android/browser/TabControl.java
+++ b/src/com/android/browser/TabControl.java
@@ -229,15 +229,6 @@
             }
         }
 
-        // This tab may have been pushed in to the background and then closed.
-        // If the saved state contains a picture file, delete the file.
-        Bundle savedState = t.getSavedState();
-        if (savedState != null) {
-            if (savedState.containsKey(Tab.CURRPICTURE)) {
-                new File(savedState.getString(Tab.CURRPICTURE)).delete();
-            }
-        }
-
         // Remove it from the queue of viewed tabs.
         mTabQueue.remove(t);
         return true;
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/src/com/android/browser/search/DefaultSearchEngine.java b/src/com/android/browser/search/DefaultSearchEngine.java
new file mode 100644
index 0000000..f282b0b
--- /dev/null
+++ b/src/com/android/browser/search/DefaultSearchEngine.java
@@ -0,0 +1,123 @@
+/*
+ * 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.search;
+
+import android.app.SearchManager;
+import android.app.SearchableInfo;
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.provider.Browser;
+import android.text.TextUtils;
+import android.util.Log;
+
+public class DefaultSearchEngine implements SearchEngine {
+
+    private static final String TAG = "DefaultSearchEngine";
+
+    private final SearchableInfo mSearchable;
+
+    private final CharSequence mLabel;
+
+    private DefaultSearchEngine(Context context, SearchableInfo searchable) {
+        mSearchable = searchable;
+        mLabel = loadLabel(context, mSearchable.getSearchActivity());
+    }
+
+    public static DefaultSearchEngine create(Context context) {
+        SearchManager searchManager =
+                (SearchManager) context.getSystemService(Context.SEARCH_SERVICE);
+        ComponentName name = searchManager.getWebSearchActivity();
+        if (name == null) return null;
+        SearchableInfo searchable = searchManager.getSearchableInfo(name);
+        if (searchable == null) return null;
+        return new DefaultSearchEngine(context, searchable);
+    }
+
+    private CharSequence loadLabel(Context context, ComponentName activityName) {
+        PackageManager pm = context.getPackageManager();
+        try {
+            ActivityInfo ai = pm.getActivityInfo(activityName, 0);
+            return ai.loadLabel(pm);
+        } catch (PackageManager.NameNotFoundException ex) {
+            Log.e(TAG, "Web search activity not found: " + activityName);
+            return null;
+        }
+    }
+
+    public String getName() {
+        String packageName = mSearchable.getSearchActivity().getPackageName();
+        // Use "google" as name to avoid showing Google twice (app + OpenSearch)
+        if ("com.google.android.googlequicksearchbox".equals(packageName)) {
+            return SearchEngine.GOOGLE;
+        } else if ("com.android.quicksearchbox".equals(packageName)) {
+            return SearchEngine.GOOGLE;
+        } else {
+            return packageName;
+        }
+    }
+
+    public CharSequence getLabel() {
+        return mLabel;
+    }
+
+    public void startSearch(Context context, String query, Bundle appData, String extraData) {
+        try {
+            Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
+            intent.setComponent(mSearchable.getSearchActivity());
+            intent.addCategory(Intent.CATEGORY_DEFAULT);
+            intent.putExtra(SearchManager.QUERY, query);
+            if (appData != null) {
+                intent.putExtra(SearchManager.APP_DATA, appData);
+            }
+            if (extraData != null) {
+                intent.putExtra(SearchManager.EXTRA_DATA_KEY, extraData);
+            }
+            intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
+            context.startActivity(intent);
+        } catch (ActivityNotFoundException ex) {
+            Log.e(TAG, "Web search activity not found: " + mSearchable.getSearchActivity());
+        }
+    }
+
+    public Cursor getSuggestions(Context context, String query) {
+        SearchManager searchManager =
+                (SearchManager) context.getSystemService(Context.SEARCH_SERVICE);
+        return searchManager.getSuggestions(mSearchable, query);
+    }
+
+    public boolean supportsSuggestions() {
+        return !TextUtils.isEmpty(mSearchable.getSuggestAuthority());
+    }
+
+    public void close() {
+    }
+
+    public boolean supportsVoiceSearch() {
+        return getName().equals(SearchEngine.GOOGLE);
+    }
+
+    @Override
+    public String toString() {
+        return "ActivitySearchEngine{" + mSearchable + "}";
+    }
+
+}
diff --git a/src/com/android/browser/search/OpenSearchSearchEngine.java b/src/com/android/browser/search/OpenSearchSearchEngine.java
new file mode 100644
index 0000000..a19e50d
--- /dev/null
+++ b/src/com/android/browser/search/OpenSearchSearchEngine.java
@@ -0,0 +1,298 @@
+/*
+ * 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.search;
+
+import com.android.browser.R;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.params.HttpParams;
+import org.apache.http.util.EntityUtils;
+import org.json.JSONArray;
+import org.json.JSONException;
+
+import android.app.SearchManager;
+import android.content.Context;
+import android.content.Intent;
+import android.database.AbstractCursor;
+import android.database.Cursor;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.Uri;
+import android.net.http.AndroidHttpClient;
+import android.os.Bundle;
+import android.provider.Browser;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.io.IOException;
+
+/**
+ * Provides search suggestions, if any, for a given web search provider.
+ */
+public class OpenSearchSearchEngine implements SearchEngine {
+
+    private static final String TAG = "OpenSearchSearchEngine";
+
+    private static final String USER_AGENT = "Android/1.0";
+    private static final int HTTP_TIMEOUT_MS = 1000;
+
+    // TODO: this should be defined somewhere
+    private static final String HTTP_TIMEOUT = "http.connection-manager.timeout";
+
+    // Indices of the columns in the below arrays.
+    private static final int COLUMN_INDEX_ID = 0;
+    private static final int COLUMN_INDEX_QUERY = 1;
+    private static final int COLUMN_INDEX_ICON = 2;
+    private static final int COLUMN_INDEX_TEXT_1 = 3;
+    private static final int COLUMN_INDEX_TEXT_2 = 4;
+
+    // The suggestion columns used. If you are adding a new entry to these arrays make sure to
+    // update the list of indices declared above.
+    private static final String[] COLUMNS = new String[] {
+        "_id",
+        SearchManager.SUGGEST_COLUMN_QUERY,
+        SearchManager.SUGGEST_COLUMN_ICON_1,
+        SearchManager.SUGGEST_COLUMN_TEXT_1,
+        SearchManager.SUGGEST_COLUMN_TEXT_2,
+    };
+
+    private static final String[] COLUMNS_WITHOUT_DESCRIPTION = new String[] {
+        "_id",
+        SearchManager.SUGGEST_COLUMN_QUERY,
+        SearchManager.SUGGEST_COLUMN_ICON_1,
+        SearchManager.SUGGEST_COLUMN_TEXT_1,
+    };
+
+    private final SearchEngineInfo mSearchEngineInfo;
+
+    private final AndroidHttpClient mHttpClient;
+
+    public OpenSearchSearchEngine(Context context, SearchEngineInfo searchEngineInfo) {
+        mSearchEngineInfo = searchEngineInfo;
+        mHttpClient = AndroidHttpClient.newInstance(USER_AGENT);
+        HttpParams params = mHttpClient.getParams();
+        params.setLongParameter(HTTP_TIMEOUT, HTTP_TIMEOUT_MS);
+    }
+
+    public String getName() {
+        return mSearchEngineInfo.getName();
+    }
+
+    public CharSequence getLabel() {
+        return mSearchEngineInfo.getLabel();
+    }
+
+    public void startSearch(Context context, String query, Bundle appData, String extraData) {
+        String uri = mSearchEngineInfo.getSearchUriForQuery(query);
+        if (uri == null) {
+            Log.e(TAG, "Unable to get search URI for " + mSearchEngineInfo);
+        } else {
+            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
+            // Make sure the intent goes to the Browser itself
+            intent.setPackage(context.getPackageName());
+            intent.addCategory(Intent.CATEGORY_DEFAULT);
+            intent.putExtra(SearchManager.QUERY, query);
+            if (appData != null) {
+                intent.putExtra(SearchManager.APP_DATA, appData);
+            }
+            if (extraData != null) {
+                intent.putExtra(SearchManager.EXTRA_DATA_KEY, extraData);
+            }
+            intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
+            context.startActivity(intent);
+        }
+    }
+
+    /**
+     * Queries for a given search term and returns a cursor containing
+     * suggestions ordered by best match.
+     */
+    public Cursor getSuggestions(Context context, String query) {
+        if (TextUtils.isEmpty(query)) {
+            return null;
+        }
+        if (!isNetworkConnected(context)) {
+            Log.i(TAG, "Not connected to network.");
+            return null;
+        }
+
+        String suggestUri = mSearchEngineInfo.getSuggestUriForQuery(query);
+        if (TextUtils.isEmpty(suggestUri)) {
+            // No suggest URI available for this engine
+            return null;
+        }
+
+        try {
+            String content = readUrl(suggestUri);
+            if (content == null) return null;
+            /* The data format is a JSON array with items being regular strings or JSON arrays
+             * themselves. We are interested in the second and third elements, both of which
+             * should be JSON arrays. The second element/array contains the suggestions and the
+             * third element contains the descriptions. Some search engines don't support
+             * suggestion descriptions so the third element is optional.
+             */
+            JSONArray results = new JSONArray(content);
+            JSONArray suggestions = results.getJSONArray(1);
+            JSONArray descriptions = null;
+            if (results.length() > 2) {
+                descriptions = results.getJSONArray(2);
+                // Some search engines given an empty array "[]" for descriptions instead of
+                // not including it in the response.
+                if (descriptions.length() == 0) {
+                    descriptions = null;
+                }
+            }
+            return new SuggestionsCursor(suggestions, descriptions);
+        } catch (JSONException e) {
+            Log.w(TAG, "Error", e);
+        }
+        return null;
+    }
+
+    /**
+     * Executes a GET request and returns the response content.
+     *
+     * @param url Request URI.
+     * @return The response content. This is the empty string if the response
+     *         contained no content.
+     */
+    public String readUrl(String url) {
+        try {
+            HttpGet method = new HttpGet(url);
+            HttpResponse response = mHttpClient.execute(method);
+            if (response.getStatusLine().getStatusCode() == 200) {
+                return EntityUtils.toString(response.getEntity());
+            } else {
+                Log.i(TAG, "Suggestion request failed");
+                return null;
+            }
+        } catch (IOException e) {
+            Log.w(TAG, "Error", e);
+            return null;
+        }
+    }
+
+    public boolean supportsSuggestions() {
+        return mSearchEngineInfo.supportsSuggestions();
+    }
+
+    public void close() {
+        mHttpClient.close();
+    }
+
+    public boolean supportsVoiceSearch() {
+        return getName().equals(SearchEngine.GOOGLE);
+    }
+
+    private boolean isNetworkConnected(Context context) {
+        NetworkInfo networkInfo = getActiveNetworkInfo(context);
+        return networkInfo != null && networkInfo.isConnected();
+    }
+
+    private NetworkInfo getActiveNetworkInfo(Context context) {
+        ConnectivityManager connectivity =
+                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+        if (connectivity == null) {
+            return null;
+        }
+        return connectivity.getActiveNetworkInfo();
+    }
+
+    private static class SuggestionsCursor extends AbstractCursor {
+
+        private final JSONArray mSuggestions;
+
+        private final JSONArray mDescriptions;
+
+        public SuggestionsCursor(JSONArray suggestions, JSONArray descriptions) {
+            mSuggestions = suggestions;
+            mDescriptions = descriptions;
+        }
+
+        @Override
+        public int getCount() {
+            return mSuggestions.length();
+        }
+
+        @Override
+        public String[] getColumnNames() {
+            return (mDescriptions != null ? COLUMNS : COLUMNS_WITHOUT_DESCRIPTION);
+        }
+
+        @Override
+        public String getString(int column) {
+            if (mPos != -1) {
+                if ((column == COLUMN_INDEX_QUERY) || (column == COLUMN_INDEX_TEXT_1)) {
+                    try {
+                        return mSuggestions.getString(mPos);
+                    } catch (JSONException e) {
+                        Log.w(TAG, "Error", e);
+                    }
+                } else if (column == COLUMN_INDEX_TEXT_2) {
+                    try {
+                        return mDescriptions.getString(mPos);
+                    } catch (JSONException e) {
+                        Log.w(TAG, "Error", e);
+                    }
+                } else if (column == COLUMN_INDEX_ICON) {
+                    return String.valueOf(R.drawable.magnifying_glass);
+                }
+            }
+            return null;
+        }
+
+        @Override
+        public double getDouble(int column) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public float getFloat(int column) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public int getInt(int column) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public long getLong(int column) {
+            if (column == COLUMN_INDEX_ID) {
+                return mPos;        // use row# as the _Id
+            }
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public short getShort(int column) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean isNull(int column) {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "OpenSearchSearchEngine{" + mSearchEngineInfo + "}";
+    }
+
+}
diff --git a/src/com/android/browser/search/SearchEngine.java b/src/com/android/browser/search/SearchEngine.java
new file mode 100644
index 0000000..b7e1859
--- /dev/null
+++ b/src/com/android/browser/search/SearchEngine.java
@@ -0,0 +1,64 @@
+/*
+ * 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.search;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.os.Bundle;
+
+/**
+ * Interface for search engines.
+ */
+public interface SearchEngine {
+
+    // Used if the search engine is Google
+    static final String GOOGLE = "google";
+
+    /**
+     * Gets the unique name of this search engine.
+     */
+    public String getName();
+
+    /**
+     * Gets the human-readable name of this search engine.
+     */
+    public CharSequence getLabel();
+
+    /**
+     * Starts a search.
+     */
+    public void startSearch(Context context, String query, Bundle appData, String extraData);
+
+    /**
+     * Gets search suggestions.
+     */
+    public Cursor getSuggestions(Context context, String query);
+
+    /**
+     * Checks whether this search engine supports search suggestions.
+     */
+    public boolean supportsSuggestions();
+
+    /**
+     * Closes this search engine.
+     */
+    public void close();
+
+    /**
+     * Checks whether this search engine supports voice search.
+     */
+    public boolean supportsVoiceSearch();
+}
diff --git a/src/com/android/browser/search/SearchEngineInfo.java b/src/com/android/browser/search/SearchEngineInfo.java
new file mode 100644
index 0000000..6f0b1d5
--- /dev/null
+++ b/src/com/android/browser/search/SearchEngineInfo.java
@@ -0,0 +1,169 @@
+/*
+ * 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.search;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.net.URLEncoder;
+import java.util.Arrays;
+import java.util.Locale;
+
+/**
+ * Loads and holds data for a given web search engine.
+ */
+public class SearchEngineInfo {
+
+    private static String TAG = "SearchEngineInfo";
+
+    // The fields of a search engine data array, defined in the same order as they appear in the
+    // all_search_engines.xml file.
+    // If you are adding/removing to this list, remember to update NUM_FIELDS below.
+    private static final int FIELD_LABEL = 0;
+    private static final int FIELD_KEYWORD = 1;
+    private static final int FIELD_FAVICON_URI = 2;
+    private static final int FIELD_SEARCH_URI = 3;
+    private static final int FIELD_ENCODING = 4;
+    private static final int FIELD_SUGGEST_URI = 5;
+    private static final int NUM_FIELDS = 6;
+
+    // The OpenSearch URI template parameters that we support.
+    private static final String PARAMETER_LANGUAGE = "{language}";
+    private static final String PARAMETER_SEARCH_TERMS = "{searchTerms}";
+    private static final String PARAMETER_INPUT_ENCODING = "{inputEncoding}";
+
+    private final String mName;
+
+    // The array of strings defining this search engine. The array values are in the same order as
+    // the above enumeration definition.
+    private final String[] mSearchEngineData;
+
+    /**
+     * @throws IllegalArgumentException If the name does not refer to a valid search engine
+     */
+    public SearchEngineInfo(Context context, String name) throws IllegalArgumentException {
+        mName = name;
+
+        Resources res = context.getResources();
+        int id_data = res.getIdentifier(name, "array", context.getPackageName());
+        mSearchEngineData = res.getStringArray(id_data);
+
+        if (mSearchEngineData == null) {
+            throw new IllegalArgumentException("No data found for " + name);
+        }
+        if (mSearchEngineData.length != NUM_FIELDS) {
+                throw new IllegalArgumentException(
+                        name + " has invalid number of fields - " + mSearchEngineData.length);
+        }
+        if (TextUtils.isEmpty(mSearchEngineData[FIELD_SEARCH_URI])) {
+            throw new IllegalArgumentException(name + " has an empty search URI");
+        }
+
+        // Add the current language/country information to the URIs.
+        Locale locale = context.getResources().getConfiguration().locale;
+        StringBuilder language = new StringBuilder(locale.getLanguage());
+        if (!TextUtils.isEmpty(locale.getCountry())) {
+            language.append('-');
+            language.append(locale.getCountry());
+        }
+
+        String language_str = language.toString();
+        mSearchEngineData[FIELD_SEARCH_URI] =
+                mSearchEngineData[FIELD_SEARCH_URI].replace(PARAMETER_LANGUAGE, language_str);
+        mSearchEngineData[FIELD_SUGGEST_URI] =
+                mSearchEngineData[FIELD_SUGGEST_URI].replace(PARAMETER_LANGUAGE, language_str);
+
+        // Default to UTF-8 if not specified.
+        String enc = mSearchEngineData[FIELD_ENCODING];
+        if (TextUtils.isEmpty(enc)) {
+            enc = "UTF-8";
+            mSearchEngineData[FIELD_ENCODING] = enc;
+        }
+
+        // Add the input encoding method to the URI.
+        mSearchEngineData[FIELD_SEARCH_URI] =
+                mSearchEngineData[FIELD_SEARCH_URI].replace(PARAMETER_INPUT_ENCODING, enc);
+        mSearchEngineData[FIELD_SUGGEST_URI] =
+                mSearchEngineData[FIELD_SUGGEST_URI].replace(PARAMETER_INPUT_ENCODING, enc);
+    }
+
+    public String getName() {
+        return mName;
+    }
+
+    public String getLabel() {
+        return mSearchEngineData[FIELD_LABEL];
+    }
+
+    /**
+     * Returns the URI for launching a web search with the given query (or null if there was no
+     * data available for this search engine).
+     */
+    public String getSearchUriForQuery(String query) {
+        return getFormattedUri(searchUri(), query);
+    }
+
+    /**
+     * Returns the URI for retrieving web search suggestions for the given query (or null if there
+     * was no data available for this search engine).
+     */
+    public String getSuggestUriForQuery(String query) {
+        return getFormattedUri(suggestUri(), query);
+    }
+
+    public boolean supportsSuggestions() {
+        return !TextUtils.isEmpty(suggestUri());
+    }
+
+    public String faviconUri() {
+        return mSearchEngineData[FIELD_FAVICON_URI];
+    }
+
+    private String suggestUri() {
+        return mSearchEngineData[FIELD_SUGGEST_URI];
+    }
+
+    private String searchUri() {
+        return mSearchEngineData[FIELD_SEARCH_URI];
+    }
+
+    /**
+     * Formats a launchable uri out of the template uri by replacing the template parameters with
+     * actual values.
+     */
+    private String getFormattedUri(String templateUri, String query) {
+        if (TextUtils.isEmpty(templateUri)) {
+            return null;
+        }
+
+        // Encode the query terms in the requested encoding (and fallback to UTF-8 if not).
+        String enc = mSearchEngineData[FIELD_ENCODING];
+        try {
+            return templateUri.replace(PARAMETER_SEARCH_TERMS, URLEncoder.encode(query, enc));
+        } catch (java.io.UnsupportedEncodingException e) {
+            Log.e(TAG, "Exception occured when encoding query " + query + " to " + enc);
+            return null;
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "SearchEngineInfo{" + Arrays.toString(mSearchEngineData) + "}";
+    }
+
+}
diff --git a/src/com/android/browser/search/SearchEnginePreference.java b/src/com/android/browser/search/SearchEnginePreference.java
new file mode 100644
index 0000000..18ce495
--- /dev/null
+++ b/src/com/android/browser/search/SearchEnginePreference.java
@@ -0,0 +1,62 @@
+/*
+ * 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.search;
+
+import com.android.browser.R;
+
+import android.app.SearchManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.preference.ListPreference;
+import android.util.AttributeSet;
+import android.util.Log;
+
+import java.util.ArrayList;
+
+class SearchEnginePreference extends ListPreference {
+
+    private static final String TAG = "SearchEnginePreference";
+
+    public SearchEnginePreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        ArrayList<CharSequence> entryValues = new ArrayList<CharSequence>();
+        ArrayList<CharSequence> entries = new ArrayList<CharSequence>();
+
+        SearchEngine defaultSearchEngine = SearchEngines.getDefaultSearchEngine(context);
+        String defaultSearchEngineName = null;
+        if (defaultSearchEngine != null) {
+            defaultSearchEngineName = defaultSearchEngine.getName();
+            entryValues.add(defaultSearchEngineName);
+            entries.add(defaultSearchEngine.getLabel());
+        }
+        for (SearchEngineInfo searchEngineInfo : SearchEngines.getSearchEngineInfos(context)) {
+            String name = searchEngineInfo.getName();
+            // Skip entry with same name as default provider
+            if (!name.equals(defaultSearchEngineName)) {
+                entryValues.add(name);
+                entries.add(searchEngineInfo.getLabel());
+            }
+        }
+
+        setEntryValues(entryValues.toArray(new CharSequence[entryValues.size()]));
+        setEntries(entries.toArray(new CharSequence[entries.size()]));
+    }
+
+}
diff --git a/src/com/android/browser/search/SearchEngines.java b/src/com/android/browser/search/SearchEngines.java
new file mode 100644
index 0000000..62690e7
--- /dev/null
+++ b/src/com/android/browser/search/SearchEngines.java
@@ -0,0 +1,73 @@
+/*
+ * 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.search;
+
+import com.android.browser.R;
+
+import android.app.SearchManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SearchEngines {
+
+    private static final String TAG = "SearchEngines";
+
+    public static SearchEngine getDefaultSearchEngine(Context context) {
+        return DefaultSearchEngine.create(context);
+    }
+
+    public static List<SearchEngineInfo> getSearchEngineInfos(Context context) {
+        ArrayList<SearchEngineInfo> searchEngineInfos = new ArrayList<SearchEngineInfo>();
+        Resources res = context.getResources();
+        String[] searchEngines = res.getStringArray(R.array.search_engines);
+        for (int i = 0; i < searchEngines.length; i++) {
+            String name = searchEngines[i];
+            SearchEngineInfo info = new SearchEngineInfo(context, name);
+            searchEngineInfos.add(info);
+        }
+        return searchEngineInfos;
+    }
+
+    public static SearchEngine get(Context context, String name) {
+        // TODO: cache
+        SearchEngine defaultSearchEngine = getDefaultSearchEngine(context);
+        if (TextUtils.isEmpty(name)
+                || (defaultSearchEngine != null && name.equals(defaultSearchEngine.getName()))) {
+            return defaultSearchEngine;
+        }
+        SearchEngineInfo searchEngineInfo = getSearchEngineInfo(context, name);
+        if (searchEngineInfo == null) return defaultSearchEngine;
+        return new OpenSearchSearchEngine(context, searchEngineInfo);
+    }
+
+    private static SearchEngineInfo getSearchEngineInfo(Context context, String name) {
+        try {
+            return new SearchEngineInfo(context, name);
+        } catch (IllegalArgumentException exception) {
+            Log.e(TAG, "Cannot load search engine " + name, exception);
+            return null;
+        }
+    }
+
+}
diff --git a/tests/assets/bindings_test.html b/tests/assets/bindings_test.html
index c20ccec..71f3438 100755
--- a/tests/assets/bindings_test.html
+++ b/tests/assets/bindings_test.html
@@ -175,7 +175,7 @@
 function runTests() {
 
   // Assume that if the test isn't done after 10s that we failed.
-  window.setTimeout(function() { JNIBindingsTest.testComplete(); }, 10000);
+  window.setTimeout(function() { JNIBindingsTest.notifyComplete(); }, 10000);
 
   if (testPrimitiveTypes()) {
     appendLog("testPrimitiveTypes passed!");
@@ -231,7 +231,7 @@
     appendLog("testParameterTypeMismatch failed!");
   }
 
-  JNIBindingsTest.testComplete();
+  JNIBindingsTest.notifyComplete();
 }
 </script>
 
diff --git a/tests/src/com/android/browser/JNIBindingsTest.java b/tests/src/com/android/browser/JNIBindingsTest.java
index bfa3ac1..ba3c66a 100644
--- a/tests/src/com/android/browser/JNIBindingsTest.java
+++ b/tests/src/com/android/browser/JNIBindingsTest.java
@@ -20,6 +20,7 @@
 import android.util.Log;
 
 import java.util.Arrays;
+
 import junit.framework.AssertionFailedError;
 
 public class JNIBindingsTest extends AndroidTestCase {
@@ -34,9 +35,9 @@
         mTestApp = testApp;
     }
 
-    public void testComplete() {
+    public void notifyComplete() {
         Log.v(LOGTAG, "Completing the test.");
-        mTestApp.testComplete();
+        mTestApp.notifyComplete();
     }
 
     public void printAssertionFailed(AssertionFailedError e) {
@@ -232,7 +233,7 @@
             assertEquals(expectedIntParam, intParam);
             assertEquals(expectedDoubleParam, doubleParam);
             assertEquals(expectedBooleanParam, booleanParam);
-            assertEquals(expectedCharParam, charParam);;
+            assertEquals(expectedCharParam, charParam);
 
             // EMULATE_JSC_BINDINGS  JSC passes "undefined" for undefined types.
             assertEquals(expectedUndefinedParam, undefinedParam);
diff --git a/tests/src/com/android/browser/JNIBindingsTestApp.java b/tests/src/com/android/browser/JNIBindingsTestApp.java
index e01aca2..4f083f6 100644
--- a/tests/src/com/android/browser/JNIBindingsTestApp.java
+++ b/tests/src/com/android/browser/JNIBindingsTestApp.java
@@ -18,7 +18,6 @@
 
 import android.app.Instrumentation;
 import android.net.http.SslError;
-import android.os.Environment;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -29,6 +28,12 @@
 import android.webkit.SslErrorHandler;
 import android.webkit.WebView;
 
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
 /**
  * Adds a JavaScript interface to the webview and calls functions on it to verify variables
  * are passed from JS to Java correctly.
@@ -37,6 +42,8 @@
 
     private final static String TAG = "JNIBindingsTest";
 
+    private static final String SDCARD_BINDINGS_TEST_HTML = "/sdcard/bindings_test.html";
+
     private static final int MSG_WEBKIT_DATA_READY = 101;
 
     private BrowserActivity mActivity = null;
@@ -67,9 +74,11 @@
             mWebView = webView;
         }
 
+        @Override
         public void run() {
             Looper.prepare();
             mHandler = new Handler() {
+                @Override
                 public void handleMessage(Message msg) {
                     switch (msg.what) {
                         case MSG_WEBKIT_DATA_READY: {
@@ -102,6 +111,32 @@
         mInst = getInstrumentation();
         mInst.waitForIdleSync();
 
+        extractAsset();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        removeAsset();
+        super.tearDown();
+    }
+
+    protected void extractAsset() throws IOException {
+        InputStream in = getInstrumentation().getContext().getAssets().open("bindings_test.html");
+        OutputStream out = new FileOutputStream(SDCARD_BINDINGS_TEST_HTML);
+
+        byte[] buf = new byte[2048];
+        int len;
+
+        while ((len = in.read(buf)) >= 0 ) {
+            out.write(buf, 0, len);
+        }
+        out.close();
+        in.close();
+    }
+
+    protected void removeAsset(){
+        File fileToDelete = new File(SDCARD_BINDINGS_TEST_HTML);
+        fileToDelete.delete();
     }
 
     /**
@@ -183,7 +218,7 @@
         });
     }
 
-    public synchronized void testComplete() {
+    public synchronized void notifyComplete() {
         mTestDone = true;
         notify();
     }
@@ -193,7 +228,7 @@
 
         Tab tab = mActivity.getTabControl().getCurrentTab();
         WebView webView = tab.getWebView();
-        webView.loadUrl("file:///sdcard/bindings_test.html");
+        webView.loadUrl("file://" + SDCARD_BINDINGS_TEST_HTML);
         synchronized(this) {
             while(!mTestDone) {
                 try {
diff --git a/tests/src/com/android/browser/PopularUrlsTest.java b/tests/src/com/android/browser/PopularUrlsTest.java
index d3806a0..98a0e9f 100644
--- a/tests/src/com/android/browser/PopularUrlsTest.java
+++ b/tests/src/com/android/browser/PopularUrlsTest.java
@@ -16,19 +16,6 @@
 
 package com.android.browser;
 
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
 import android.app.Instrumentation;
 import android.content.Intent;
 import android.net.Uri;
@@ -42,6 +29,19 @@
 import android.webkit.SslErrorHandler;
 import android.webkit.WebView;
 
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 /**
  *
  * Iterates over a list of URLs from a file and outputs the time to load each.
@@ -63,6 +63,7 @@
     private Instrumentation mInst = null;
     private CountDownLatch mLatch = new CountDownLatch(1);
     private RunStatus mStatus;
+    private boolean pageLoadFinishCalled, pageProgressFull;
 
     public PopularUrlsTest() {
         super(BrowserActivity.class);
@@ -72,6 +73,8 @@
     protected void setUp() throws Exception {
         super.setUp();
 
+        Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse("about:blank"));
+        setActivityIntent(i);
         mActivity = getActivity();
         mInst = getInstrumentation();
         mInst.waitForIdleSync();
@@ -122,14 +125,18 @@
 
         webView.setWebChromeClient(new TestWebChromeClient(webView.getWebChromeClient()) {
 
-            /**
-             * Reset the latch whenever page progress reaches 100%.
-             */
             @Override
             public void onProgressChanged(WebView view, int newProgress) {
                 super.onProgressChanged(view, newProgress);
                 if (newProgress >= 100) {
-                    resetLatch();
+                    if (!pageProgressFull) {
+                        // void duplicate calls
+                        pageProgressFull  = true;
+                        if (pageLoadFinishCalled) {
+                            //reset latch and move forward only if both indicators are true
+                            resetLatch();
+                        }
+                    }
                 }
             }
 
@@ -206,20 +213,38 @@
                     String host, String realm) {
                 handler.proceed("user", "passwd");
             }
+
+            /* (non-Javadoc)
+             * @see com.android.browser.TestWebViewClient#onPageFinished(android.webkit.WebView, java.lang.String)
+             */
+            @Override
+            public void onPageFinished(WebView view, String url) {
+                if (!pageLoadFinishCalled) {
+                    pageLoadFinishCalled = true;
+                    if (pageProgressFull) {
+                        //reset latch and move forward only if both indicators are true
+                        resetLatch();
+                    }
+                }
+            }
+
         });
     }
 
     void resetLatch() {
-        CountDownLatch temp = mLatch;
-        mLatch = new CountDownLatch(1);
-        if (temp != null) {
-            // Notify existing latch that it's done.
-            while (temp.getCount() > 0) {
-                temp.countDown();
-            }
+        if (mLatch.getCount() != 1) {
+            Log.w(TAG, "Expecting latch to be 1, but it's not!");
+        } else {
+            mLatch.countDown();
         }
     }
 
+    void resetForNewPage() {
+        mLatch = new CountDownLatch(1);
+        pageLoadFinishCalled = false;
+        pageProgressFull = false;
+    }
+
     void waitForLoad() throws InterruptedException {
         boolean timedout = !mLatch.await(PAGE_LOAD_TIMEOUT, TimeUnit.MILLISECONDS);
         if (timedout) {
@@ -249,16 +274,26 @@
             mFile = new File(file);
             FileReader input = null;
             BufferedReader reader = null;
+            isRecovery = false;
+            iteration = 0;
+            page = 0;
             try {
                 input = new FileReader(mFile);
                 isRecovery = true;
                 reader = new BufferedReader(input);
-                iteration = Integer.parseInt(reader.readLine());
-                page = Integer.parseInt(reader.readLine());
+                String line = reader.readLine();
+                if (line == null)
+                    return;
+                iteration = Integer.parseInt(line);
+                line = reader.readLine();
+                if (line == null)
+                    return;
+                page = Integer.parseInt(line);
             } catch (FileNotFoundException ex) {
-                isRecovery = false;
-                iteration = 0;
-                page = 0;
+                return;
+            } catch (NumberFormatException nfe) {
+                Log.wtf(TAG, "unexpected data in status file, will start from begining");
+                return;
             } finally {
                 try {
                     if (reader != null) {
@@ -282,7 +317,6 @@
 
         public void write() throws IOException {
             FileWriter output = null;
-            OutputStreamWriter writer = null;
             if (mFile.exists()) {
                 mFile.delete();
             }
@@ -292,14 +326,8 @@
                 output.write(page + newLine);
                 output.write(url + newLine);
             } finally {
-                try {
-                    if (writer != null) {
-                        writer.close();
-                    }
-                } finally {
-                    if (output != null) {
-                        output.close();
-                    }
+                if (output != null) {
+                    output.close();
                 }
             }
         }
@@ -369,21 +397,23 @@
 
         if (mStatus.getIsRecovery()) {
             Log.e(TAG, "Recovering after crash: " + iterator.next());
+            mStatus.incrementPage();
         }
 
         while (mStatus.getIteration() < loopCount) {
+            if (clearCache) {
+                webView.clearCache(true);
+            }
             while(iterator.hasNext()) {
                 page = iterator.next();
                 mStatus.setUrl(page);
                 mStatus.write();
                 Log.i(TAG, "start: " + page);
                 Uri uri = Uri.parse(page);
-                if (clearCache) {
-                    webView.clearCache(true);
-                }
                 final Intent intent = new Intent(Intent.ACTION_VIEW, uri);
 
                 long startTime = System.currentTimeMillis();
+                resetForNewPage();
                 mInst.runOnMainSync(new Runnable() {
 
                     public void run() {
@@ -423,6 +453,9 @@
                     bufferedReader.close();
                 }
             }
+        } catch (FileNotFoundException fnfe) {
+            Log.e(TAG, fnfe.getMessage(), fnfe);
+            fail("Test environment not setup correctly");
         } finally {
             if (writer != null) {
                 writer.close();
@@ -436,6 +469,9 @@
         BufferedReader bufferedReader = getInputStream();
         try {
             loopUrls(bufferedReader, null, true, STABILITY_LOOPCOUNT);
+        } catch (FileNotFoundException fnfe) {
+            Log.e(TAG, fnfe.getMessage(), fnfe);
+            fail("Test environment not setup correctly");
         } finally {
             if (bufferedReader != null) {
                 bufferedReader.close();
diff --git a/tools/all_search_engines.template.xml b/tools/all_search_engines.template.xml
new file mode 100644
index 0000000..a8d0c89
--- /dev/null
+++ b/tools/all_search_engines.template.xml
@@ -0,0 +1,40 @@
+<?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.
+-->
+
+
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
+
+Each string-array item below refers to one search engine in a specific locale, and the name of the
+item is referred to by the <engine_X_name> items in the locale specific search_engines.xml file.
+
+Format:
+  - Human readable label
+  - Keyword: empty string if the engine has no keyword. (currently unused)
+  - Favicon URL
+  - Search URL
+  - Encoding
+  - Suggest URL: empty string if this engine has no suggest feature
+
+The parameters enclosed in curly braces come from the OpenSearch specification, see
+http://www.opensearch.org/Specifications/OpenSearch/1.1/Draft_4#OpenSearch_1.1_parameters
+-->
+
+<resources>
+</resources>
+
diff --git a/tools/get_search_engines.py b/tools/get_search_engines.py
new file mode 100755
index 0000000..cd73423
--- /dev/null
+++ b/tools/get_search_engines.py
@@ -0,0 +1,268 @@
+#!/usr/bin/python2.4
+#
+# 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.
+#
+"""
+Creates the list of search engines
+
+The created list is placed in the res/values-<locale> directory. Also updates
+res/values/all_search_engines.xml if required with new data.
+
+Usage: get_search_engines.py
+
+Copyright (C) 2010 The Android Open Source Project
+"""
+
+import os
+import re
+import sys
+import urllib
+from xml.dom import minidom
+
+# Locales to generate search engine lists for
+locales = ["cs-CZ", "da-DK", "de-AT", "de-CH", "de-DE", "el-GR", "en-AU",
+    "en-GB", "en-IE", "en-NZ", "en-SG", "en-ZA", "es-ES", "fr-BE", "fr-FR",
+    "it-IT", "ja-JP", "ko-KR", "nb-NO", "nl-BE", "nl-NL", "pl-PL", "pt-PT",
+    "pt-BR", "ru-RU", "sv-SE", "tr-TR", "zh-CN", "zh-HK", "zh-MO", "zh-TW"]
+
+google_data = ["google", "Google", "google.com",
+  "http://www.google.com/favicon.ico",
+  "http://www.google.com/m?hl={language}&amp;ie={inputEncoding}&amp;source=android-browser&amp;q={searchTerms}",
+  "UTF-8",
+  "http://www.google.com/complete/search?hl={language}&amp;json=true&amp;q={searchTerms}"]
+
+class SearchEngineManager(object):
+  """Manages list of search engines and creates locale specific lists.
+
+  The main method useful for the caller is generateListForLocale(), which
+  creates a locale specific search_engines.xml file suitable for use by the
+  Android WebSearchProvider implementation.
+  """
+
+  def __init__(self):
+    """Inits SearchEngineManager with relevant search engine data.
+
+    The search engine data is downloaded from the Chrome source repository.
+    """
+    self.chrome_data = urllib.urlopen(
+        'http://src.chromium.org/viewvc/chrome/trunk/src/chrome/'
+        'browser/search_engines/template_url_prepopulate_data.cc').read()
+    if self.chrome_data.lower().find('repository not found') != -1:
+      print 'Unable to get Chrome source data for search engine list.\nExiting.'
+      sys.exit(2)
+
+    self.resdir = os.path.normpath(os.path.join(sys.path[0], '../res'))
+
+    self.all_engines = set()
+
+  def getXmlString(self, str):
+    """Returns an XML-safe string for the given string.
+
+    Given a string from the search engine data structure, convert it to a
+    string suitable to write to our XML data file by stripping away NULLs,
+    unwanted quotes, wide-string declarations (L"") and replacing C-style
+    unicode characters with XML equivalents.
+    """
+    str = str.strip()
+    if str.upper() == 'NULL':
+      return ''
+
+    if str.startswith('L"'):
+      str = str[2:]
+    if str.startswith('@') or str.startswith('?'):
+      str = '\\' + str
+
+    str = str.strip('"')
+    str = str.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
+    str = str.replace('"', '&quot;').replace('\'', '&apos;')
+    str = re.sub(r'\\x([a-fA-F0-9]+)', r'&#x\1;', str)
+
+    return str
+
+  def getEngineData(self, name):
+    """Returns an array of strings describing the specified search engine.
+
+    The returned strings are in the same order as in the Chrome source data file
+    except that the internal name of the search engine is inserted at the
+    beginning of the list.
+    """
+
+    if name == "google":
+      return google_data
+
+    # Find the first occurance of this search engine name in the form
+    # " <name> =" in the chrome data file.
+    re_exp = '\s' + name + '\s*='
+    search_obj = re.search(re_exp, self.chrome_data)
+    if not search_obj:
+      print ('Unable to find data for search engine ' + name +
+             '. Please check the chrome data file for format changes.')
+      return None
+
+    # Extract the struct declaration between the curly braces.
+    start_pos = self.chrome_data.find('{', search_obj.start()) + 1;
+    end_pos = self.chrome_data.find('};', start_pos);
+    engine_data_str = self.chrome_data[start_pos:end_pos]
+
+    # Remove c++ style '//' comments at the ends of each line
+    engine_data_lines = engine_data_str.split('\n')
+    engine_data_str = ""
+    for line in engine_data_lines:
+        start_pos = line.find(' // ')
+        if start_pos != -1:
+            line = line[:start_pos]
+        engine_data_str = engine_data_str + line + '\n'
+
+    # Join multiple line strings into a single string.
+    engine_data_str = re.sub('\"\s+\"', '', engine_data_str)
+    engine_data_str = re.sub('\"\s+L\"', '', engine_data_str)
+    engine_data_str = engine_data_str.replace('"L"', '')
+
+    engine_data = engine_data_str.split(',')
+    for i in range(len(engine_data)):
+      engine_data[i] = self.getXmlString(engine_data[i])
+
+    # If the last element was an empty string (due to an extra comma at the
+    # end), ignore it.
+    if not engine_data[len(engine_data) - 1]:
+      engine_data.pop()
+
+    engine_data.insert(0, name)
+
+    return engine_data
+
+  def getSearchEnginesForCountry(self, country):
+    """Returns the list of search engine names for the given country.
+
+    The data comes from the Chrome data file.
+    """
+    # The Chrome data file has an array defined with the name 'engines_XX'
+    # where XX = country.
+    pos = self.chrome_data.find('engines_' + country)
+    if pos == -1:
+      print ('Unable to find search engine data for country ' + country + '.')
+      return
+
+    # Extract the text between the curly braces for this array declaration
+    engines_start = self.chrome_data.find('{', pos) + 1;
+    engines_end = self.chrome_data.find('}', engines_start);
+    engines_str = self.chrome_data[engines_start:engines_end]
+
+    # Remove embedded /**/ style comments, white spaces, address-of operators
+    # and the trailing comma if any.
+    engines_str = re.sub('\/\*.+\*\/', '', engines_str)
+    engines_str = re.sub('\s+', '', engines_str)
+    engines_str = engines_str.replace('&','')
+    engines_str = engines_str.rstrip(',')
+
+    # Split the array into it's elements
+    engines = engines_str.split(',')
+
+    return engines
+
+  def writeAllEngines(self):
+    """Writes all search engines to the all_search_engines.xml file.
+    """
+
+    all_search_engines_path = os.path.join(self.resdir, 'values/all_search_engines.xml')
+
+    text = []
+
+    for engine_name in self.all_engines:
+      engine_data = self.getEngineData(engine_name)
+      text.append('  <string-array name="%s" translatable="false">\n' % (engine_data[0]))
+      for i in range(1, 7):
+        text.append('    <item>%s</item>\n' % (engine_data[i]))
+      text.append('  </string-array>\n')
+      print engine_data[1] + " added to all_search_engines.xml"
+
+    self.generateXmlFromTemplate(os.path.join(sys.path[0], 'all_search_engines.template.xml'),
+        all_search_engines_path, text)
+
+  def generateDefaultList(self):
+    self.writeEngineList(os.path.join(self.resdir, 'values'), "default")
+
+  def generateListForLocale(self, locale):
+    """Creates a new locale specific search_engines.xml file.
+
+    The new file contains search engines specific to that country. If required
+    this function updates all_search_engines.xml file with any new search
+    engine data necessary.
+    """
+    separator_pos = locale.find('-')
+    if separator_pos == -1:
+      print ('Locale must be of format <language>-<country>. For e.g.'
+             ' "es-US" or "en-GB"')
+      return
+
+    language = locale[0:separator_pos]
+    country = locale[separator_pos + 1:].upper()
+    dir_path = os.path.join(self.resdir, 'values-' + language + '-r' + country)
+
+    self.writeEngineList(dir_path, country)
+
+  def writeEngineList(self, dir_path, country):
+    if os.path.exists(dir_path) and not os.path.isdir(dir_path):
+      print "File exists in output directory path " + dir_path + ". Please remove it and try again."
+      return
+
+    engines = self.getSearchEnginesForCountry(country)
+    if not engines:
+      return
+    for engine in engines:
+      self.all_engines.add(engine)
+
+    # Create the locale specific search_engines.xml file. Each
+    # search_engines.xml file has a hardcoded list of 7 items. If there are less
+    # than 7 search engines for this country, the remaining items are marked as
+    # enabled=false.
+    text = []
+    text.append('  <string-array name="search_engines" translatable="false">\n');
+    for engine in engines:
+      engine_data = self.getEngineData(engine)
+      name = engine_data[0]
+      text.append('    <item>%s</item>\n' % (name))
+    text.append('  </string-array>\n');
+
+    self.generateXmlFromTemplate(os.path.join(sys.path[0], 'search_engines.template.xml'),
+        os.path.join(dir_path, 'search_engines.xml'),
+        text)
+
+  def generateXmlFromTemplate(self, template_path, out_path, text):
+    # Load the template file and insert the new contents before the last line.
+    template_text = open(template_path).read()
+    pos = template_text.rfind('\n', 0, -2) + 1
+    contents = template_text[0:pos] + ''.join(text) + template_text[pos:]
+
+    # Make sure what we have created is valid XML :) No need to check for errors
+    # as the script will terminate with an exception if the XML was malformed.
+    engines_dom = minidom.parseString(contents)
+
+    dir_path = os.path.dirname(out_path)
+    if not os.path.exists(dir_path):
+      os.makedirs(dir_path)
+      print 'Created directory ' + dir_path
+    file = open(out_path, 'w')
+    file.write(contents)
+    file.close()
+    print 'Wrote ' + out_path
+
+if __name__ == "__main__":
+  manager = SearchEngineManager()
+  manager.generateDefaultList()
+  for locale in locales:
+    manager.generateListForLocale(locale)
+  manager.writeAllEngines()
+
diff --git a/res/anim/find_dialog_enter.xml b/tools/search_engines.template.xml
old mode 100644
new mode 100755
similarity index 62%
copy from res/anim/find_dialog_enter.xml
copy to tools/search_engines.template.xml
index 5e597a4..553d333
--- a/res/anim/find_dialog_enter.xml
+++ b/tools/search_engines.template.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.
@@ -13,9 +13,12 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
+<!--
+****
+**** THIS FILE WAS GENERATED BY tools/get_search_engines.py
+****
 
-<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>
+Each value in the string-array is the name of a value in all_search_engines.xml
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+</resources>