merge from open-source master

Change-Id: Iaaf00603ec92506775c28cc6a4cc587d3a02939a
diff --git a/Android.mk b/Android.mk
index 33cd6ab..6e20ab8 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,11 +1,14 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := user
+LOCAL_MODULE_TAGS := optional
 
-LOCAL_STATIC_JAVA_LIBRARIES := google-framework
+LOCAL_STATIC_JAVA_LIBRARIES := \
+        android-common
 
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_SRC_FILES := \
+        $(call all-java-files-under, src) \
+        src/com/android/browser/EventLogTags.logtags
 
 LOCAL_PACKAGE_NAME := Browser
 
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 3d970ab..7e98019 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -18,8 +18,8 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.browser">
 
-    <uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH" />
-    <uses-permission android:name="android.permission.USE_CREDENTIALS" />
+    <original-package android:name="com.android.browser" />
+
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
     <uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER"/>
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
@@ -27,11 +27,12 @@
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
     <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
     <uses-permission android:name="android.permission.INTERNET" />
+    <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="com.android.browser.permission.READ_HISTORY_BOOKMARKS"/>
     <uses-permission android:name="com.android.browser.permission.WRITE_HISTORY_BOOKMARKS"/>
-    <uses-permission android:name="android.permission.BACKUP_DATA" />
+    <uses-permission android:name="android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS" />
 
     <application   android:name="Browser"
                    android:label="@string/application_name"
@@ -52,7 +53,12 @@
                   android:launchMode="singleTask"
                   android:alwaysRetainTaskState="true"
                   android:configChanges="orientation|keyboardHidden"
-                  android:theme="@style/BrowserTheme" >
+                  android:theme="@style/BrowserTheme"
+                  android:windowSoftInputMode="adjustResize" >
+            <intent-filter>
+                <action android:name="android.speech.action.VOICE_SEARCH_RESULTS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
             <!-- For these schemes were not particular MIME type has been
                  supplied, we are a good candidate. -->
             <intent-filter>
@@ -113,18 +119,20 @@
                     android:resource="@xml/searchable" />
         </activity>
 
-        <activity android:name="CombinedBookmarkHistoryActivity" android:label=""
+        <activity android:name="CombinedBookmarkHistoryActivity" android:label="@string/bookmarks"
+                  android:excludeFromRecents="true"
                   android:launchMode="singleTop" android:configChanges="orientation|keyboardHidden"
                   android:theme="@style/BookmarkTheme" >
             <meta-data android:name="android.app.default_searchable"
                     android:value=".BrowserActivity" />
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+            </intent-filter>
         </activity>
 
         <activity android:name="BrowserBookmarksPage" android:label="@string/bookmarks"
                   android:launchMode="singleTop" android:configChanges="orientation|keyboardHidden">
         </activity>
-        <activity android:name="MostVisitedActivity" android:label=""
-                android:launchMode="singleTop" android:configChanges="orientation|keyboardHidden"/>
 
         <activity-alias android:name="ShortcutBookmarksPage"
             android:targetActivity="BrowserBookmarksPage"
@@ -150,10 +158,6 @@
                   android:configChanges="orientation|keyboardHidden">
         </activity>
 
-        <activity android:name="BrowserPluginList" android:label=""
-                  android:configChanges="orientation|keyboardHidden">
-        </activity>
-
         <activity android:name="WebsiteSettingsActivity" android:label=""
                   android:configChanges="orientation|keyboardHidden">
         </activity>
@@ -180,16 +184,25 @@
             </intent-filter>
         </activity>
 
+        <!--receiver android:name=".widget.BookmarkWidgetProvider" android:label="@string/bookmarks">
+            <intent-filter>
+                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+            </intent-filter>
+            <meta-data android:name="android.appwidget.provider" android:resource="@xml/bookmarkwidget"/>
+        </receiver>
+
+        <service android:name=".widget.BookmarkWidgetService" /-->
+
         <!-- Makes .BrowserActivity the search target for any activity in Browser -->
         <meta-data android:name="android.app.default_searchable" android:value=".BrowserActivity" />
 
-        <activity android:name="android.webkit.PluginActivity">
+        <receiver android:name=".OpenDownloadReceiver">
             <intent-filter>
-                <action android:name="android.intent.webkit.PLUGIN" />
-                <category android:name="android.intent.category.DEFAULT" />
+                <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>
-        </activity>
-
+        </receiver>
     </application>
 
 </manifest>
diff --git a/CleanSpec.mk b/CleanSpec.mk
new file mode 100644
index 0000000..b84e1b6
--- /dev/null
+++ b/CleanSpec.mk
@@ -0,0 +1,49 @@
+# 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.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list.  These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list.  E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
diff --git a/res/drawable-hdpi/appwidget_bg.9.png b/res/drawable-hdpi/appwidget_bg.9.png
new file mode 100644
index 0000000..3b29eae
--- /dev/null
+++ b/res/drawable-hdpi/appwidget_bg.9.png
Binary files differ
diff --git a/res/drawable-hdpi/arcs.png b/res/drawable-hdpi/arcs.png
new file mode 100644
index 0000000..9555a9f
--- /dev/null
+++ b/res/drawable-hdpi/arcs.png
Binary files differ
diff --git a/res/drawable-hdpi/bookmark_shadow.9.png b/res/drawable-hdpi/bookmark_shadow.9.png
deleted file mode 100755
index 570a802..0000000
--- a/res/drawable-hdpi/bookmark_shadow.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_btn_bookmark_browsertab.png b/res/drawable-hdpi/ic_btn_bookmark_browsertab.png
deleted file mode 100755
index b633696..0000000
--- a/res/drawable-hdpi/ic_btn_bookmark_browsertab.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_close_tab.png b/res/drawable-hdpi/ic_close_tab.png
deleted file mode 100755
index ae86d2f..0000000
--- a/res/drawable-hdpi/ic_close_tab.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_dialog_bookmark.png b/res/drawable-hdpi/ic_dialog_bookmark.png
deleted file mode 100644
index 0ec7756..0000000
--- a/res/drawable-hdpi/ic_dialog_bookmark.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_dialog_menu_generic.png b/res/drawable-hdpi/ic_dialog_menu_generic.png
deleted file mode 100644
index f9527b6..0000000
--- a/res/drawable-hdpi/ic_dialog_menu_generic.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_launcher_shortcut_browser_bookmark.png b/res/drawable-hdpi/ic_launcher_shortcut_browser_bookmark.png
index f861650..7b2c680 100644
--- a/res/drawable-hdpi/ic_launcher_shortcut_browser_bookmark.png
+++ b/res/drawable-hdpi/ic_launcher_shortcut_browser_bookmark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_launcher_shortcut_browser_bookmark_icon.png b/res/drawable-hdpi/ic_launcher_shortcut_browser_bookmark_icon.png
new file mode 100644
index 0000000..57fc915
--- /dev/null
+++ b/res/drawable-hdpi/ic_launcher_shortcut_browser_bookmark_icon.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu_bookmark.png b/res/drawable-hdpi/ic_menu_bookmark.png
deleted file mode 100644
index 16e7339..0000000
--- a/res/drawable-hdpi/ic_menu_bookmark.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/magnifying_glass.png b/res/drawable-hdpi/magnifying_glass.png
new file mode 100755
index 0000000..27c4a04
--- /dev/null
+++ b/res/drawable-hdpi/magnifying_glass.png
Binary files differ
diff --git a/res/drawable-hdpi/search_plate_browser.9.png b/res/drawable-hdpi/search_plate_browser.9.png
index f078259..cf0567b 100644
--- a/res/drawable-hdpi/search_plate_browser.9.png
+++ b/res/drawable-hdpi/search_plate_browser.9.png
Binary files differ
diff --git a/res/drawable-hdpi/textfield_voice_search.9.png b/res/drawable-hdpi/textfield_voice_search.9.png
new file mode 100644
index 0000000..5d3f281
--- /dev/null
+++ b/res/drawable-hdpi/textfield_voice_search.9.png
Binary files differ
diff --git a/res/drawable-mdpi/appwidget_bg.9.png b/res/drawable-mdpi/appwidget_bg.9.png
new file mode 100644
index 0000000..afe41b6
--- /dev/null
+++ b/res/drawable-mdpi/appwidget_bg.9.png
Binary files differ
diff --git a/res/drawable-mdpi/arcs.png b/res/drawable-mdpi/arcs.png
new file mode 100644
index 0000000..5e0d949
--- /dev/null
+++ b/res/drawable-mdpi/arcs.png
Binary files differ
diff --git a/res/drawable-mdpi/bookmark_shadow.9.png b/res/drawable-mdpi/bookmark_shadow.9.png
deleted file mode 100644
index 3c706be..0000000
--- a/res/drawable-mdpi/bookmark_shadow.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_btn_bookmark_browsertab.png b/res/drawable-mdpi/ic_btn_bookmark_browsertab.png
deleted file mode 100644
index 1c52124..0000000
--- a/res/drawable-mdpi/ic_btn_bookmark_browsertab.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_close_tab.png b/res/drawable-mdpi/ic_close_tab.png
deleted file mode 100644
index 44a789e..0000000
--- a/res/drawable-mdpi/ic_close_tab.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_dialog_menu_generic.png b/res/drawable-mdpi/ic_dialog_menu_generic.png
deleted file mode 100755
index de07bda..0000000
--- a/res/drawable-mdpi/ic_dialog_menu_generic.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher_browser.png b/res/drawable-mdpi/ic_launcher_browser.png
index 47c79d1..f9d6172 100755
--- a/res/drawable-mdpi/ic_launcher_browser.png
+++ b/res/drawable-mdpi/ic_launcher_browser.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher_shortcut_browser_bookmark.png b/res/drawable-mdpi/ic_launcher_shortcut_browser_bookmark.png
index e144727..aa05683 100644
--- a/res/drawable-mdpi/ic_launcher_shortcut_browser_bookmark.png
+++ b/res/drawable-mdpi/ic_launcher_shortcut_browser_bookmark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher_shortcut_browser_bookmark_icon.png b/res/drawable-mdpi/ic_launcher_shortcut_browser_bookmark_icon.png
new file mode 100644
index 0000000..ba82911
--- /dev/null
+++ b/res/drawable-mdpi/ic_launcher_shortcut_browser_bookmark_icon.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_bookmark.png b/res/drawable-mdpi/ic_menu_bookmark.png
deleted file mode 100644
index 40c6950..0000000
--- a/res/drawable-mdpi/ic_menu_bookmark.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_dialog_bookmark.png b/res/drawable-mdpi/magnifying_glass.png
old mode 100644
new mode 100755
similarity index 68%
rename from res/drawable-mdpi/ic_dialog_bookmark.png
rename to res/drawable-mdpi/magnifying_glass.png
index 6a83a16..20e1fbc
--- a/res/drawable-mdpi/ic_dialog_bookmark.png
+++ b/res/drawable-mdpi/magnifying_glass.png
Binary files differ
diff --git a/res/drawable-mdpi/search_plate_browser.9.png b/res/drawable-mdpi/search_plate_browser.9.png
index 0436dcf..2370d9c 100644
--- a/res/drawable-mdpi/search_plate_browser.9.png
+++ b/res/drawable-mdpi/search_plate_browser.9.png
Binary files differ
diff --git a/res/drawable-mdpi/textfield_voice_search.9.png b/res/drawable-mdpi/textfield_voice_search.9.png
new file mode 100644
index 0000000..e7baba0
--- /dev/null
+++ b/res/drawable-mdpi/textfield_voice_search.9.png
Binary files differ
diff --git a/res/drawable/stop_background.xml b/res/drawable/stop_background.xml
new file mode 100644
index 0000000..a9a4dd4
--- /dev/null
+++ b/res/drawable/stop_background.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+
+<!-- Custom background for the stop button which mimics btn_search_dialog
+        but draws in a pressed state even if it is in an unfocused window -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:state_pressed="true"
+        android:drawable="@*android:drawable/btn_search_dialog_pressed" />
+    <item android:state_pressed="false"
+         android:drawable="@*android:drawable/btn_search_dialog_default" />
+</selector>
diff --git a/res/drawable/title_loading.xml b/res/drawable/title_loading.xml
new file mode 100644
index 0000000..7f145d3
--- /dev/null
+++ b/res/drawable/title_loading.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.
+-->
+
+<!-- Custom layout file which mimics the textfield_search look, but draws the
+        pressed state even without window focus -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:state_pressed="true"
+        android:drawable="@*android:drawable/textfield_search_pressed" />
+
+    <item android:state_enabled="true" android:state_focused="true"
+        android:drawable="@*android:drawable/textfield_search_selected" />
+
+    <item android:drawable="@*android:drawable/textfield_search_default" />
+
+</selector>
+
diff --git a/res/drawable/title_text.xml b/res/drawable/title_text.xml
index 6a214d9..b435e4d 100644
--- a/res/drawable/title_text.xml
+++ b/res/drawable/title_text.xml
@@ -18,7 +18,7 @@
         pressed state even without window focus -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_pressed="true"
-            android:drawable="@*android:drawable/textfield_pressed" />
+            android:drawable="@*android:drawable/textfield_search_empty_pressed" />
     <item android:state_pressed="false"
-            android:drawable="@*android:drawable/textfield_default" />
+            android:drawable="@*android:drawable/textfield_search_empty_default" />
 </selector>
diff --git a/res/drawable/button_line.xml b/res/drawable/title_voice.xml
similarity index 60%
rename from res/drawable/button_line.xml
rename to res/drawable/title_voice.xml
index 67869d0..e96eb94 100644
--- a/res/drawable/button_line.xml
+++ b/res/drawable/title_voice.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 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,15 +13,10 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-    <item>
-        <shape android:width="2dip">
-            <solid android:color="#ff000000"/>
-        </shape>
-    </item>
-    <item android:left="1dip" android:width="1dip">
-        <shape>
-            <solid android:color="#ffffffff"/>
-        </shape>
-    </item>
-</layer-list>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true"
+            android:drawable="@*android:drawable/textfield_search_empty_pressed" />
+    <item android:state_pressed="false"
+            android:drawable="@drawable/textfield_voice_search" />
+</selector>
diff --git a/res/layout-land/http_authentication.xml b/res/layout-land/http_authentication.xml
index b2f012d..c008ceb 100644
--- a/res/layout-land/http_authentication.xml
+++ b/res/layout-land/http_authentication.xml
@@ -15,13 +15,13 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
+    android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:gravity="center_horizontal"
     android:orientation="vertical">
 
     <TableLayout
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginTop="12dip"
         android:gravity="center_horizontal" >
diff --git a/res/layout-land/page_info.xml b/res/layout-land/page_info.xml
index 63d18ca..f4397a5 100644
--- a/res/layout-land/page_info.xml
+++ b/res/layout-land/page_info.xml
@@ -16,12 +16,12 @@
 
 <ScrollView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
+    android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical" >
 
     <LinearLayout
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="vertical" >
     
@@ -40,7 +40,7 @@
 
         <!-- Address: -->
         <TableLayout
-            android:layout_width="fill_parent"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:shrinkColumns="1"
             android:orientation="vertical">
diff --git a/res/layout-land/ssl_certificate.xml b/res/layout-land/ssl_certificate.xml
index d6036c1..44c5904 100644
--- a/res/layout-land/ssl_certificate.xml
+++ b/res/layout-land/ssl_certificate.xml
@@ -16,11 +16,11 @@
 
 <ScrollView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
+    android:layout_width="match_parent"
     android:layout_height="wrap_content" >
 
     <LinearLayout
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="vertical" >
 
@@ -28,7 +28,7 @@
         <LinearLayout 
             android:id="@+id/placeholder"
             android:layout_height="wrap_content"
-            android:layout_width="fill_parent"
+            android:layout_width="match_parent"
             android:layout_marginTop="12dip"
             android:orientation="vertical" />
 
@@ -36,7 +36,7 @@
         <ImageView 
             android:id="@+id/title_separator"
             android:src="@android:drawable/divider_horizontal_dark"
-            android:layout_width="fill_parent"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:scaleType="fitXY"
             android:layout_weight="1"
@@ -46,7 +46,7 @@
             android:layout_marginBottom="12dip" />
 
         <TableLayout
-            android:layout_width="fill_parent"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:shrinkColumns="1"
             android:orientation="vertical">
diff --git a/res/layout/active_tabs.xml b/res/layout/active_tabs.xml
index d25f154..8b5fe9e 100644
--- a/res/layout/active_tabs.xml
+++ b/res/layout/active_tabs.xml
@@ -15,20 +15,20 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_height="fill_parent"
-    android:layout_width="fill_parent"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent"
     android:orientation="vertical"
     android:background="@color/black"
     >
     <RelativeLayout
         style="?android:attr/windowTitleBackgroundStyle"
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="?android:attr/windowTitleSize"
         >
         <TextView android:id="@android:id/title"
             style="?android:attr/windowTitleStyle"
-            android:layout_width="fill_parent"
-            android:layout_height="fill_parent"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
             android:background="@null"
             android:fadingEdge="horizontal"
             android:gravity="center_vertical"
@@ -36,7 +36,7 @@
             />
     </RelativeLayout>
     <ListView android:id="@+id/list"
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="0dip"
         android:layout_weight="1"
         android:cacheColorHint="@color/black"
diff --git a/res/layout/add_new_bookmark.xml b/res/layout/add_new_bookmark.xml
index 1880e20..d11a68a 100644
--- a/res/layout/add_new_bookmark.xml
+++ b/res/layout/add_new_bookmark.xml
@@ -15,7 +15,7 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
-        android:layout_width="fill_parent" 
+        android:layout_width="match_parent" 
         android:layout_height="wrap_content"
         android:minHeight="?android:attr/listPreferredItemHeight"
         android:orientation="horizontal"
@@ -35,7 +35,7 @@
             android:scaleType="fitCenter"
             />
     <LinearLayout
-            android:layout_width="fill_parent"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical"
             >
diff --git a/res/layout/bookmark_thumbnail.xml b/res/layout/bookmark_thumbnail.xml
index 8dc5564..1f017d0 100644
--- a/res/layout/bookmark_thumbnail.xml
+++ b/res/layout/bookmark_thumbnail.xml
@@ -15,8 +15,8 @@
 -->
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
     android:orientation="vertical"
     android:padding="0dip"
     >
@@ -33,8 +33,8 @@
 
     <!-- This holds the star for addbookmark -->
     <LinearLayout android:id="@+id/holder"
-        android:layout_height="fill_parent"
-        android:layout_width="fill_parent"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
         android:orientation="horizontal"
         android:background="#99000000"
         android:gravity="center"
@@ -57,7 +57,7 @@
     </LinearLayout>
 
     <TextView android:id="@+id/label"
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_gravity="bottom"
         android:textAppearance="?android:attr/textAppearanceSmall"
diff --git a/res/layout/bookmarkwidget.xml b/res/layout/bookmarkwidget.xml
new file mode 100644
index 0000000..2416e4f
--- /dev/null
+++ b/res/layout/bookmarkwidget.xml
@@ -0,0 +1,79 @@
+<?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:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:padding="8dip"
+    android:orientation="vertical"
+    android:background="@drawable/appwidget_bg" >
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal" >
+
+        <ImageView
+            android:id="@+id/previous"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:padding="10dip"
+            android:src="@drawable/ic_btn_find_prev" />
+
+        <TextView
+            android:id="@+id/title"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center"
+            android:layout_gravity="center"
+            android:text="@string/title_bar_loading"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textColor="?android:attr/textColorPrimary" />
+
+        <ImageView
+            android:id="@+id/next"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:padding="10dip"
+            android:src="@drawable/ic_btn_find_next" />
+
+    </LinearLayout>
+
+    <ImageView
+        android:id="@+id/image"
+        android:visibility="gone"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:scaleType="fitXY"
+        android:padding="5dip"
+        android:gravity="center" />
+
+    <RelativeLayout
+        android:id="@+id/progress"
+        android:visibility="visible"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center" >
+
+        <ProgressBar
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:indeterminateOnly="true" />
+
+    </RelativeLayout>
+
+</LinearLayout>
diff --git a/res/layout/browser_add_bookmark.xml b/res/layout/browser_add_bookmark.xml
index 9fb2b46..e8a08a4 100644
--- a/res/layout/browser_add_bookmark.xml
+++ b/res/layout/browser_add_bookmark.xml
@@ -15,13 +15,13 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
+    android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical"
     >
 
     <ImageView android:id="@+id/titleDivider"
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="1dip"
         android:scaleType="fitXY"
         android:gravity="fill_horizontal"
@@ -30,7 +30,7 @@
         android:layout_marginRight="10dip"/>
 
     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_weight="1"
         android:orientation="vertical"
@@ -78,7 +78,7 @@
     </LinearLayout>
         
     <LinearLayout 
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:background="#c6c3c6"
         android:minHeight="54dip"
diff --git a/res/layout/browser_bookmarks_page.xml b/res/layout/browser_bookmarks_page.xml
deleted file mode 100644
index 3fb0308..0000000
--- a/res/layout/browser_bookmarks_page.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
-        android:orientation="vertical" 
-        android:layout_width="fill_parent" 
-        android:layout_height="fill_parent"
-        >
-    <ListView android:id="@+id/list" 
-            android:layout_width="fill_parent" 
-            android:layout_height="0dip" 
-            android:layout_weight="1"
-            />
-</LinearLayout>
diff --git a/res/layout/browser_download_item.xml b/res/layout/browser_download_item.xml
index c26aab9..52f49c1 100644
--- a/res/layout/browser_download_item.xml
+++ b/res/layout/browser_download_item.xml
@@ -20,8 +20,10 @@
 -->
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
-    android:layout_height="wrap_content">
+    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"
@@ -70,7 +72,7 @@
 
     <ProgressBar android:id="@+id/download_progress"
         style="?android:attr/progressBarStyleHorizontal"
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_below="@id/download_icon"
         android:layout_alignParentLeft="true"
diff --git a/res/layout/browser_downloads_page.xml b/res/layout/browser_downloads_page.xml
index 1d4d4e6..5cdf30c 100644
--- a/res/layout/browser_downloads_page.xml
+++ b/res/layout/browser_downloads_page.xml
@@ -19,13 +19,6 @@
 */
 -->
 <merge xmlns:android="http://schemas.android.com/apk/res/android">
-    <ListView 
-        android:id="@+id/list"
-        android:layout_width="fill_parent"
-        android:layout_height="fill_parent"/>
-    <ViewStub 
-        android:id="@+id/empty"
-        android:layout="@layout/no_downloads"
-        android:layout_width="fill_parent"
-        android:layout_height="fill_parent"/>
+    <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_find.xml b/res/layout/browser_find.xml
index 7a77152..e2f0cf6 100644
--- a/res/layout/browser_find.xml
+++ b/res/layout/browser_find.xml
@@ -16,7 +16,7 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/findControls"
-    android:layout_width="fill_parent"
+    android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:paddingTop="5dip"
     android:paddingLeft="4dip"
@@ -45,7 +45,7 @@
         android:layout_marginRight="6dip"
         >
         <EditText android:id="@+id/edit"
-            android:layout_width="fill_parent"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:scrollHorizontally="true"
             android:inputType="text"
diff --git a/res/layout/browser_subwindow.xml b/res/layout/browser_subwindow.xml
index 0eb9e72..76d72d5 100644
--- a/res/layout/browser_subwindow.xml
+++ b/res/layout/browser_subwindow.xml
@@ -16,27 +16,27 @@
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/subwindow_container"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent" >
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" >
     <FrameLayout
-        android:layout_width="fill_parent"
-        android:layout_height="fill_parent"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
         android:padding="10dip" >
         <LinearLayout
-            android:layout_width="fill_parent"
-            android:layout_height="fill_parent"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
             android:orientation="vertical"
             android:background="@android:drawable/dialog_frame" >
             <WebView android:id="@+id/webview"
-                android:layout_width="fill_parent"
-                android:layout_height="fill_parent"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
                 android:fadeScrollbars="true"
                 android:scrollbarStyle="outsideOverlay"
                 android:layout_weight="1" />
         </LinearLayout>
     </FrameLayout>
     <LinearLayout
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="vertical"
         android:layout_gravity="right"
diff --git a/res/layout/custom_screen.xml b/res/layout/custom_screen.xml
index 8bc03fb..90dc324 100644
--- a/res/layout/custom_screen.xml
+++ b/res/layout/custom_screen.xml
@@ -18,21 +18,21 @@
     <FrameLayout android:id="@+id/fullscreen_custom_content"
         android:visibility="gone"
         android:background="@color/black"
-        android:layout_width="fill_parent"
-        android:layout_height="fill_parent"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
     />
     <LinearLayout android:orientation="vertical"
-        android:layout_width="fill_parent"
-        android:layout_height="fill_parent">
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
 
         <LinearLayout android:id="@+id/error_console"
-            android:layout_width="fill_parent"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
         />
 
         <FrameLayout android:id="@+id/main_content"
-            android:layout_width="fill_parent"
-            android:layout_height="fill_parent"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
         />
     </LinearLayout>
 </FrameLayout>
diff --git a/res/layout/empty_history.xml b/res/layout/empty_history.xml
index 8fd3c01..4484a16 100644
--- a/res/layout/empty_history.xml
+++ b/res/layout/empty_history.xml
@@ -16,8 +16,8 @@
 
 <TextView xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/empty_view"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
     android:text="@string/empty_history"
     android:background="@color/black"
     android:textColor="@color/white"
diff --git a/res/layout/error_console.xml b/res/layout/error_console.xml
index 0fffcde..e239622 100644
--- a/res/layout/error_console.xml
+++ b/res/layout/error_console.xml
@@ -17,14 +17,14 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/error_console_view_group_id"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
     android:orientation="vertical"
     android:background="#000000">
 
     <TextView android:id="@+id/error_console_header_id"
         android:text="@string/error_console_header_text_minimized"
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:paddingTop="2dip"
         android:paddingBottom="2dip"
@@ -35,7 +35,7 @@
 
     <view class="com.android.browser.ErrorConsoleView$ErrorConsoleListView"
         android:id="@+id/error_console_list_id"
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="200dip"
         android:visibility="gone"
         android:layout_weight="1"
@@ -44,7 +44,7 @@
 
     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@+id/error_console_eval_view_group_id"
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:visibility="gone">
 
diff --git a/res/layout/geolocation_permissions_prompt.xml b/res/layout/geolocation_permissions_prompt.xml
index 357da00..babde3a 100755
--- a/res/layout/geolocation_permissions_prompt.xml
+++ b/res/layout/geolocation_permissions_prompt.xml
@@ -16,15 +16,16 @@
      This is the layout for the Geolocation permissions prompt.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.browser.GeolocationPermissionsPrompt
+    xmlns:android="http://schemas.android.com/apk/res/android"
     android:fitsSystemWindows="true"
-    android:layout_width="fill_parent"
+    android:layout_width="match_parent"
     android:layout_height="wrap_content">
 
     <!-- Use an inner element as we can't show a hidden outermost element -->
     <LinearLayout android:id="@+id/inner"
         android:orientation="vertical"
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:background="@color/black"
         android:paddingTop="1px"
@@ -33,21 +34,21 @@
         <!-- White line -->
         <View
             android:orientation="vertical"
-            android:layout_width="fill_parent"
+            android:layout_width="match_parent"
             android:layout_height="1px"
             android:background="@color/white" />
 
         <!-- Container for content -->
         <LinearLayout
             android:orientation="vertical"
-            android:layout_width="fill_parent"
-            android:layout_height="fill_parent"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
             android:background="@color/geolocation_permissions_prompt_background"
             android:padding="6dip">
 
             <!-- 'google.com wants to know your location' -->
             <TextView android:id="@+id/message"
-                android:layout_width="fill_parent"
+                android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:textSize="14dip"
                 android:textColor="@color/black" />
@@ -55,7 +56,7 @@
             <!-- Checkbox -->
             <LinearLayout
                 android:orientation="horizontal"
-                android:layout_width="fill_parent"
+                android:layout_width="match_parent"
                 android:layout_height="wrap_content">
                 <CheckBox android:id="@+id/remember"
                     android:layout_width="wrap_content"
@@ -71,7 +72,7 @@
 
             <!-- Buttons -->
             <LinearLayout
-                android:layout_width="fill_parent"
+                android:layout_width="match_parent"
                 android:layout_height="wrap_content">
                 <Button android:id="@+id/share_button"
                     android:text="@string/geolocation_permissions_prompt_share"
@@ -87,4 +88,4 @@
 
         </LinearLayout>
     </LinearLayout>
-</LinearLayout>
+</com.android.browser.GeolocationPermissionsPrompt>
diff --git a/res/layout/history_header.xml b/res/layout/history_header.xml
index a390c37..e03b009 100644
--- a/res/layout/history_header.xml
+++ b/res/layout/history_header.xml
@@ -15,7 +15,7 @@
 -->
 
 <TextView xmlns:android="http://schemas.android.com/apk/res/android" 
-        android:layout_width="fill_parent" 
+        android:layout_width="match_parent" 
         android:layout_height="wrap_content"
         android:minHeight="?android:attr/listPreferredItemHeight"
         android:textAppearance="?android:attr/textAppearanceMedium"
diff --git a/res/layout/history_item.xml b/res/layout/history_item.xml
index 50903a4..4522a75 100644
--- a/res/layout/history_item.xml
+++ b/res/layout/history_item.xml
@@ -15,7 +15,7 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
-        android:layout_width="fill_parent" 
+        android:layout_width="match_parent" 
         android:layout_height="wrap_content"
         android:minHeight="?android:attr/listPreferredItemHeight"
         android:orientation="horizontal"
diff --git a/res/layout/http_authentication.xml b/res/layout/http_authentication.xml
index 01cd3af..cc785c9 100644
--- a/res/layout/http_authentication.xml
+++ b/res/layout/http_authentication.xml
@@ -15,7 +15,7 @@
 -->
 
 <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
+    android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:gravity="center_horizontal"
     android:orientation="vertical">
diff --git a/res/layout/no_downloads.xml b/res/layout/no_downloads.xml
index 1c1e1cd..6918eab 100644
--- a/res/layout/no_downloads.xml
+++ b/res/layout/no_downloads.xml
@@ -15,8 +15,8 @@
 -->
 
 <TextView xmlns:android="http://schemas.android.com/apk/res/android" 
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
     android:text="@string/no_downloads"
     android:background="@color/black"
     android:textColor="@color/white"
diff --git a/res/layout/page_info.xml b/res/layout/page_info.xml
index ee45082..275fcf4 100644
--- a/res/layout/page_info.xml
+++ b/res/layout/page_info.xml
@@ -16,12 +16,12 @@
 
 <ScrollView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
+    android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical" >
 
     <LinearLayout
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="vertical" >
     
@@ -40,7 +40,7 @@
     
         <!-- Address: -->
         <TableLayout
-            android:layout_width="fill_parent"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical">
         
diff --git a/res/layout/permission_dialog.xml b/res/layout/permission_dialog.xml
deleted file mode 100644
index ff24eaf..0000000
--- a/res/layout/permission_dialog.xml
+++ /dev/null
@@ -1,158 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright 2009, 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:drawingCacheQuality="auto"
-  android:layout_width="fill_parent"
-  android:layout_height="wrap_content"
-  android:orientation="vertical"
-  android:padding="0dip">
-
-  <LinearLayout
-    android:layout_width="fill_parent"
-    android:layout_height="wrap_content"
-    android:orientation="horizontal"
-    android:padding="10dip">
-
-    <ImageView
-      android:id="@+id/icon"
-      android:paddingRight="10dip"
-      android:layout_width="wrap_content"
-      android:layout_height="wrap_content"
-      android:layout_centerHorizontal="true"/>
-
-    <TextView
-      android:id="@+id/dialog_title"
-      android:layout_width="wrap_content"
-      android:layout_height="wrap_content"
-      android:layout_centerVertical="true"
-      android:gravity="center_vertical"
-      android:visibility="gone"
-      android:textSize="16dip"
-      android:textStyle="bold"
-      android:textColor="@color/white"/>
-
-  </LinearLayout>
-
-  <LinearLayout
-    android:layout_width="fill_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical">
-
-    <ImageView android:id="@+id/titleDivider"
-        android:layout_width="fill_parent"
-        android:layout_height="1dip"
-        android:scaleType="fitXY"
-        android:gravity="fill_horizontal"
-        android:src="@drawable/dialog_divider_horizontal_light"
-        android:layout_marginLeft="10dip"
-        android:layout_marginRight="10dip"/>
-
-  </LinearLayout>
-
-  <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
-    android:layout_height="wrap_content"
-    android:paddingBottom="10dip"
-    android:layout_weight="1">
-
-    <LinearLayout
-      android:orientation="vertical"
-      android:layout_width="fill_parent"
-      android:paddingTop="10dip"
-      android:paddingLeft="10dip"
-      android:paddingRight="10dip"
-      android:layout_height="wrap_content">
-
-      <TextView
-        android:id="@+id/origin"
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        android:visibility="gone"
-        android:textStyle="bold"
-        android:gravity="left"
-        android:textSize="16dip"
-        android:textColor="@color/white"/>
-
-      <TextView
-        android:id="@+id/dialog_message"
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        android:paddingLeft="4dip"
-        android:paddingTop="10dip"
-        android:gravity="left"
-        android:textSize="16dip"
-        android:textColor="@color/white"/>
-
-    </LinearLayout>
-
-  </ScrollView>
-
-  <LinearLayout
-    android:layout_width="fill_parent"
-    android:background="@color/gray"
-    android:layout_height="wrap_content"
-    android:paddingTop="4dip"
-    android:paddingLeft="0dip"
-    android:paddingRight="0dip">
-
-    <LinearLayout android:id="@+id/leftSpacer"
-       android:layout_weight="0.25"
-       android:layout_width="0dip"
-       android:layout_height="wrap_content"
-       android:orientation="horizontal"
-       android:visibility="gone"/>
-
-    <Button
-      android:id="@+id/button_allow"
-      android:layout_width="96dip"
-      android:layout_height="48dip"
-      android:layout_gravity="left"
-      android:layout_weight="1"
-      android:maxLines="2"
-      android:textSize="13dip"/>
-
-    <Button
-      android:id="@+id/button_alwaysdeny"
-      android:layout_width="96dip"
-      android:layout_height="48dip"
-      android:layout_gravity="left"
-      android:layout_weight="1"
-      android:maxLines="2"
-      android:textSize="13dip"/>
-
-    <Button
-      android:id="@+id/button_deny"
-      android:layout_width="96dip"
-      android:layout_height="48dip"
-      android:layout_gravity="right"
-      android:layout_weight="1"
-      android:maxLines="2"
-      android:textSize="13dip"/>
-
-    <LinearLayout android:id="@+id/rightSpacer"
-      android:layout_width="0dip"
-      android:layout_weight="0.25"
-      android:layout_height="wrap_content"
-      android:orientation="horizontal"
-      android:visibility="gone" />
-
-  </LinearLayout>
-
-</LinearLayout>
diff --git a/res/layout/ssl_certificate.xml b/res/layout/ssl_certificate.xml
index 9f9bbf1..a137d66 100644
--- a/res/layout/ssl_certificate.xml
+++ b/res/layout/ssl_certificate.xml
@@ -16,11 +16,11 @@
 
 <ScrollView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
+    android:layout_width="match_parent"
     android:layout_height="wrap_content" >
 
     <LinearLayout 
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="vertical" >
 
@@ -28,7 +28,7 @@
         <LinearLayout 
             android:id="@+id/placeholder"
             android:layout_height="wrap_content"
-            android:layout_width="fill_parent"
+            android:layout_width="match_parent"
             android:layout_marginTop="12dip"
             android:orientation="vertical" />
 
@@ -36,7 +36,7 @@
         <ImageView
             android:id="@+id/title_separator"
             android:src="@android:drawable/divider_horizontal_dark"
-            android:layout_width="fill_parent"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:scaleType="fitXY"
             android:layout_weight="1"
@@ -46,7 +46,7 @@
             android:layout_marginBottom="12dip" />
 
         <TableLayout
-            android:layout_width="fill_parent"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical">
 
diff --git a/res/layout/ssl_success.xml b/res/layout/ssl_success.xml
index dad654a..e819f23 100644
--- a/res/layout/ssl_success.xml
+++ b/res/layout/ssl_success.xml
@@ -15,7 +15,7 @@
 -->
 
 <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="horizontal" >
     
diff --git a/res/layout/ssl_warning.xml b/res/layout/ssl_warning.xml
index 8bc406a..285c189 100644
--- a/res/layout/ssl_warning.xml
+++ b/res/layout/ssl_warning.xml
@@ -15,7 +15,7 @@
 -->
 
 <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:shrinkColumns="1"
         android:orientation="horizontal" >
diff --git a/res/layout/ssl_warnings.xml b/res/layout/ssl_warnings.xml
index 5a02d97..7e43256 100644
--- a/res/layout/ssl_warnings.xml
+++ b/res/layout/ssl_warnings.xml
@@ -16,12 +16,12 @@
 
 <ScrollView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
+    android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical">
 
     <LinearLayout
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="vertical">
 
@@ -29,7 +29,7 @@
         <TextView
             android:id="@+id/warnings_header"
             android:layout_height="wrap_content"
-            android:layout_width="fill_parent"
+            android:layout_width="match_parent"
             android:textSize="18sp"
             android:textColor="@color/ssl_text_label"
             android:gravity="left"
@@ -42,7 +42,7 @@
         <LinearLayout
             android:id="@+id/placeholder"
             android:layout_height="wrap_content"
-            android:layout_width="fill_parent"
+            android:layout_width="match_parent"
             android:layout_marginTop="12dip"
             android:orientation="vertical" />
 
diff --git a/res/layout/tab.xml b/res/layout/tab.xml
index e6ec970..69baf56 100755
--- a/res/layout/tab.xml
+++ b/res/layout/tab.xml
@@ -22,19 +22,19 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
     android:fitsSystemWindows="true"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent">
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
 
     <!-- Wrapper layout for the WebView, which must be in a FrameLayout. -->
     <FrameLayout android:id="@+id/webview_wrapper"
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="0dip"
         android:layout_weight="1" />
 
     <!-- Geolocation permissions prompt -->
-    <com.android.browser.GeolocationPermissionsPrompt
-        android:id="@+id/geolocation_permissions_prompt"
-        android:layout_width="fill_parent"
+    <ViewStub android:id="@+id/geolocation_permissions_prompt"
+        android:layout="@layout/geolocation_permissions_prompt"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content" />
 
 </LinearLayout>
diff --git a/res/layout/tab_view.xml b/res/layout/tab_view.xml
index a5302f4..885f4cf 100644
--- a/res/layout/tab_view.xml
+++ b/res/layout/tab_view.xml
@@ -17,7 +17,7 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_height="wrap_content"
     android:minHeight="?android:attr/listPreferredItemHeight"
-    android:layout_width="fill_parent"
+    android:layout_width="match_parent"
     android:orientation="horizontal"
     android:gravity="center_vertical"
     >
@@ -37,7 +37,7 @@
         android:orientation="vertical"
         >
         <TextView android:id="@+id/title"
-            android:layout_width="fill_parent"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:maxLines="1"
@@ -45,7 +45,7 @@
             android:ellipsize="end"
             />
         <TextView android:id="@+id/url"
-            android:layout_width="fill_parent"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:maxLines="1"
@@ -56,14 +56,14 @@
     <View android:id="@+id/divider"
         android:background="#ff313431"
         android:layout_width="1dip"
-        android:layout_height="fill_parent"
+        android:layout_height="match_parent"
         android:layout_marginLeft="8dip"
         android:layout_marginTop="5dip"
         android:layout_marginBottom="5dip"
         />
     <view class="com.android.browser.ActiveTabsPage$CloseHolder" android:id="@+id/close"
         android:layout_width="wrap_content"
-        android:layout_height="fill_parent"
+        android:layout_height="match_parent"
         android:paddingLeft="18dip"
         android:paddingRight="18dip"
         android:background="@drawable/close_background"
diff --git a/res/layout/tab_view_add_tab.xml b/res/layout/tab_view_add_tab.xml
index 0752a84..f69865e 100644
--- a/res/layout/tab_view_add_tab.xml
+++ b/res/layout/tab_view_add_tab.xml
@@ -17,7 +17,7 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_height="wrap_content"
     android:minHeight="?android:attr/listPreferredItemHeight"
-    android:layout_width="fill_parent"
+    android:layout_width="match_parent"
     android:orientation="horizontal"
     android:gravity="center_vertical"
     >
@@ -28,7 +28,7 @@
         android:layout_marginRight="8dip"
         android:src="@drawable/ic_list_new_window"/>
     <TextView
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:maxLines="1"
diff --git a/res/layout/tabitem.xml b/res/layout/tabitem.xml
deleted file mode 100644
index 9c82972..0000000
--- a/res/layout/tabitem.xml
+++ /dev/null
@@ -1,53 +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.
--->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
-    android:orientation="vertical"
-    android:padding="4dip"
-    android:background="@color/white">
-
-    <com.android.browser.FakeWebView android:id="@+id/icon"
-        android:background="@color/black"
-        android:layout_width="fill_parent"
-        android:layout_height="fill_parent" />
-
-    <TextView android:id="@+id/label"
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        android:layout_gravity="bottom"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textColor="@color/white"
-        android:maxLines="1"
-        android:paddingTop="3dip"
-        android:paddingBottom="3dip"
-        android:paddingLeft="2dip"
-        android:paddingRight="2dip"
-        android:scrollHorizontally="true"
-        android:background="#CC000000"/>
-
-    <ImageView android:id="@+id/close"
-        android:focusable="false"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="bottom|right"
-        android:paddingTop="14dip"
-        android:paddingBottom="12dip"
-        android:paddingLeft="12dip"
-        android:paddingRight="12dip"
-        android:src="@android:drawable/btn_dialog" />
-
-</FrameLayout>
diff --git a/res/layout/tabs.xml b/res/layout/tabs.xml
index 759e0c7..c212547 100644
--- a/res/layout/tabs.xml
+++ b/res/layout/tabs.xml
@@ -15,21 +15,21 @@
 -->
 <TabHost xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@android:id/tabhost"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent">
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
 
     <LinearLayout
         android:orientation="vertical"
-        android:layout_width="fill_parent"
-        android:layout_height="fill_parent">
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
 
         <TabWidget android:id="@android:id/tabs"
-            android:layout_width="fill_parent"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
         />
 
         <FrameLayout android:id="@android:id/tabcontent"
-            android:layout_width="fill_parent"
+            android:layout_width="match_parent"
             android:layout_height="0dip"
             android:layout_weight="1"
         />
diff --git a/res/layout/title_bar.xml b/res/layout/title_bar.xml
index 1ea33fc..9f0cb51 100644
--- a/res/layout/title_bar.xml
+++ b/res/layout/title_bar.xml
@@ -16,7 +16,7 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
+    android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical"
     android:paddingLeft="8dip"
@@ -27,13 +27,14 @@
 
     <ProgressBar android:id="@+id/progress_horizontal"
         style="?android:attr/progressBarStyleHorizontal"
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="5dip"
+        android:layout_marginLeft="1dip"
         android:max="100"
         />
 
     <LinearLayout
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="horizontal"
         >
@@ -43,6 +44,7 @@
             android:layout_width="0dip"
             android:layout_weight="1.0"
             android:layout_height="wrap_content"
+            android:layout_marginBottom="4dip"
             android:gravity="center_vertical"
             android:orientation="horizontal"
             >
@@ -62,8 +64,7 @@
                     android:layout_height="wrap_content"
                     android:layout_width="0dip"
                     android:layout_weight="1.0"
-                    android:paddingLeft="8dip"
-                    android:paddingRight="6dip"
+                    android:layout_marginLeft="3dip"
                     android:textAppearance="?android:attr/textAppearanceMedium"
                     android:textColor="@color/black"
                     android:gravity="center_vertical"
@@ -71,13 +72,23 @@
                     android:ellipsize="end"
                 />
         </LinearLayout>
+        <ImageView android:id="@+id/stop"
+            android:background="@drawable/stop_background"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_marginBottom="4dip"
+            android:src="@drawable/ic_btn_stop_v2"
+            android:visibility="gone"
+        />
         <ImageView
             android:id="@+id/rt_btn"
             android:layout_width="wrap_content"
-            android:layout_height="fill_parent"
-            android:layout_marginLeft="6dip"
+            android:layout_height="match_parent"
+            android:layout_marginLeft="-2dip"
+            android:layout_marginTop="-6.5dip"
+            android:layout_marginBottom="-2dip"
+            android:layout_marginRight="-5dip"
             android:scaleType="center"
-            android:layout_marginBottom="4dip"
             android:background="@drawable/btn_bookmark"
             android:src="@drawable/ic_btn_bookmarks"
         />
diff --git a/res/layout/title_bar_bg.xml b/res/layout/title_bar_bg.xml
deleted file mode 100644
index 3e19c5c..0000000
--- a/res/layout/title_bar_bg.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-   Copyright 2009, The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_height="wrap_content"
-    android:layout_width="wrap_content"
-    android:orientation="vertical"
-    >
-        <view class="com.android.browser.BrowserActivity$Shadow"
-            android:id="@+id/shadow"
-            android:layout_height="5dip"
-            android:layout_width="fill_parent"
-            android:background="@*android:drawable/title_bar_shadow"
-            />
-</LinearLayout>
diff --git a/res/layout/website_settings_row.xml b/res/layout/website_settings_row.xml
index 4901ff1..6308035 100644
--- a/res/layout/website_settings_row.xml
+++ b/res/layout/website_settings_row.xml
@@ -16,17 +16,18 @@
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:drawingCacheQuality="auto"
-  android:layout_width="fill_parent"
+  android:layout_width="match_parent"
   android:layout_height="?android:attr/listPreferredItemHeight"
-  android:gravity="center"
+  android:gravity="center_vertical"
   android:padding="0dip">
 
   <ImageView android:id="@+id/icon"
-    android:layout_width="32dip"
-    android:layout_height="32dip"
-    android:layout_alignParentTop="true"
-    android:layout_alignParentLeft="true"
-    android:layout_alignParentBottom="true"
+    android:layout_width="20dip"
+    android:layout_height="20dip"
+    android:layout_marginLeft="18dip"
+    android:layout_marginRight="18dip"
+    android:layout_centerVertical="true"
+    android:background="@drawable/fav_icn_background"
     android:padding="2dip" />
 
   <LinearLayout android:id="@+id/features"
@@ -49,27 +50,37 @@
       android:layout_height="32dip"
       android:padding="2dip" />
 
+    <ImageView android:id="@+id/feature_icon"
+      android:layout_width="32dip"
+      android:layout_height="32dip"
+      android:padding="2dip"
+      android:layout_centerVertical="true"
+      android:layout_alignParentRight="true"
+      android:visibility="gone" />
   </LinearLayout>
 
-  <TextView android:id="@+id/title"
+  <LinearLayout
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
-    android:layout_alignParentTop="true"
+    android:layout_toRightOf="@id/icon"
+    android:layout_toLeftOf="@id/features"
+    android:layout_centerVertical="true"
     android:layout_alignWithParentIfMissing="true"
-    android:layout_toRightOf="@id/icon"
-    android:layout_toLeftOf="@id/features"
-    android:layout_marginLeft="6dip"
-    android:layout_marginTop="6dip"
-    android:textAppearance="?android:attr/textAppearanceLarge"/>
+    android:orientation="vertical">
 
-  <TextView android:id="@+id/subtitle"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:layout_toRightOf="@id/icon"
-    android:layout_toLeftOf="@id/features"
-    android:layout_below="@id/title"
-    android:layout_alignLeft="@id/title"
-    android:layout_marginBottom="2dip"
-    android:textAppearance="?android:attr/textAppearanceSmall"/>
+    <TextView android:id="@+id/title"
+      android:layout_width="wrap_content"
+      android:layout_height="wrap_content"
+      android:textAppearance="?android:attr/textAppearanceMedium"
+      android:maxLines="2"
+      android:ellipsize="end" />
 
+    <TextView android:id="@+id/subtitle"
+      android:layout_width="wrap_content"
+      android:layout_height="wrap_content"
+      android:textAppearance="?android:attr/textAppearanceSmall"
+      android:visibility="gone"
+      android:singleLine="true"
+      android:ellipsize="end" />
+  </LinearLayout>
 </RelativeLayout>
diff --git a/res/menu/browser.xml b/res/menu/browser.xml
index 2752c3a..4793c21 100644
--- a/res/menu/browser.xml
+++ b/res/menu/browser.xml
@@ -61,6 +61,9 @@
         <item android:id="@+id/dump_nav_menu_id"
             android:title="@string/dump_nav"
             android:visible="false" />
+        <item android:id="@+id/dump_counters_menu_id"
+            android:title="@string/dump_counters"
+            android:visible="false" />
     </group>
     <group android:id="@+id/MAIN_SHORTCUT_MENU" android:visible="false">
         <item android:id="@+id/homepage_menu_id"
diff --git a/res/menu/browsercontext.xml b/res/menu/browsercontext.xml
index 8b2678e..70cf8d4 100644
--- a/res/menu/browsercontext.xml
+++ b/res/menu/browsercontext.xml
@@ -54,6 +54,8 @@
             android:title="@string/contextmenu_download_image"/>
         <item android:id="@+id/view_image_context_menu_id"
             android:title="@string/contextmenu_view_image"/>
+        <item android:id="@+id/set_wallpaper_context_menu_id"
+            android:title="@string/contextmenu_set_wallpaper"/>
     </group>
 </menu>
  
diff --git a/res/menu/downloadhistory.xml b/res/menu/downloadhistory.xml
index ee3b751..195b0db 100644
--- a/res/menu/downloadhistory.xml
+++ b/res/menu/downloadhistory.xml
@@ -16,9 +16,6 @@
 
 <menu xmlns:android="http://schemas.android.com/apk/res/android">
 
-    <item android:id="@+id/download_menu_clear_all"
-        android:title="@string/download_menu_clear_all" 
-        android:icon="@*android:drawable/ic_menu_clear_playlist" />
     <item android:id="@+id/download_menu_cancel_all"
         android:title="@string/download_menu_cancel_all" 
         android:icon="@android:drawable/ic_menu_close_clear_cancel" />
diff --git a/res/menu/downloadhistorycontextfinished.xml b/res/menu/downloadhistorycontextfinished.xml
index 2714b5b..8d1fdd0 100644
--- a/res/menu/downloadhistorycontextfinished.xml
+++ b/res/menu/downloadhistorycontextfinished.xml
@@ -18,7 +18,7 @@
 
     <item android:id="@+id/download_menu_open"
         android:title="@string/download_menu_open" />
-    <item android:id="@+id/download_menu_clear"
-        android:title="@string/download_menu_clear" />
+    <item android:id="@+id/download_menu_delete"
+        android:title="@string/download_menu_delete" />
 
 </menu>
diff --git a/res/menu/tabscontext.xml b/res/menu/tabscontext.xml
deleted file mode 100644
index e89720e..0000000
--- a/res/menu/tabscontext.xml
+++ /dev/null
@@ -1,26 +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.
--->
-
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@+id/view_tab_menu_id"
-        android:title="@string/tab_picker_view_tab"/>
-    <item android:id="@+id/remove_tab_menu_id"
-        android:title="@string/tab_picker_remove_tab"/>
-    <item android:id="@+id/bookmark_tab_menu_id"
-        android:title="@string/tab_picker_bookmark"/>
-    <item android:id="@+id/properties_tab_menu_id"
-        android:title="@string/page_info"/>    
-</menu>
diff --git a/res/values-cs/arrays.xml b/res/values-cs/arrays.xml
deleted file mode 100644
index 84ef7b7..0000000
--- a/res/values-cs/arrays.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="webstorage_quota_entries">
-    <item msgid="5433313236875537673">"Není povolena žádná kvóta"</item>
-    <item msgid="7374272188672967690">"5 MB"</item>
-    <item msgid="8699352701856136738">"10 MB"</item>
-    <item msgid="2018822431469084862">"30 MB"</item>
-    <item msgid="5383642976774534074">"100 MB"</item>
-  </string-array>
-  <string-array name="webstorage_quota_entries_values">
-    <item msgid="7620410313725236055">"0"</item>
-    <item msgid="4302688814760304206">"5"</item>
-    <item msgid="7291990205847586165">"10"</item>
-    <item msgid="916913372287112423">"30"</item>
-    <item msgid="3437188301324229987">"100"</item>
-  </string-array>
-</resources>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 11e4938..50f9949 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -1,21 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--  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.
--->
+ -->
+
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="1935869255545976415">"Prohlížeč"</string>
+    <string name="choose_upload" msgid="3649366287575002063">"Zvolit soubor, který chcete nahrát."</string>
     <string name="new_tab" msgid="4505722538297295141">"Nové okno"</string>
     <string name="active_tabs" msgid="3050623868203544623">"Okna"</string>
     <string name="tab_bookmarks" msgid="2305793036003473653">"Záložky"</string>
@@ -24,7 +26,7 @@
     <string name="added_to_bookmarks" msgid="1020224130695956728">"Přidáno k záložkám"</string>
     <string name="removed_from_bookmarks" msgid="6063705902028438800">"Odstraněno ze záložek"</string>
     <string name="sign_in_to" msgid="5939425800148759165">"Přihlásit se: <xliff:g id="HOSTNAME">%s1</xliff:g> <xliff:g id="REALM">%s2</xliff:g>"</string>
-    <string name="username" msgid="5057566336518215922">"Název"</string>
+    <string name="username" msgid="5057566336518215922">"Jméno"</string>
     <string name="password" msgid="1177138552305184404">"Heslo"</string>
     <string name="action" msgid="183105774472071343">"Přihlásit se"</string>
     <string name="bookmarks_search" msgid="5229596268214362873">"Prohlížeč"</string>
@@ -32,9 +34,9 @@
     <string name="ok" msgid="1509280796718850364">"OK"</string>
   <plurals name="matches_found">
     <item quantity="zero" msgid="6242659159545399963">"Žádné shody"</item>
-    <item quantity="one" msgid="4352019729062956802">"1 shoda"</item>
-    <item quantity="few" msgid="5544267486978946555">"Počet shod: <xliff:g id="NUMBER">%d</xliff:g>"</item>
-    <item quantity="other" msgid="6616125067364315405">"Počet shod: <xliff:g id="NUMBER">%d</xliff:g>"</item>
+    <item quantity="one" msgid="4352019729062956802">"Shoda"</item>
+    <item quantity="few" msgid="5544267486978946555">"<xliff:g id="NUMBER">%d</xliff:g> shod"</item>
+    <item quantity="other" msgid="6616125067364315405">"<xliff:g id="NUMBER">%d</xliff:g> shod"</item>
   </plurals>
     <string name="title_bar_loading" msgid="7438217780834640678">"Načítání..."</string>
     <string name="page_info" msgid="4048529256302257195">"Informace o stránce"</string>
@@ -58,16 +60,15 @@
     <string name="validity_period" msgid="57988851973181309">"Platnost:"</string>
     <string name="issued_on" msgid="2082890654801808368">"Datum vydání:"</string>
     <string name="expires_on" msgid="8061200430557020704">"Platnost vyprší:"</string>
-    <string name="retrieving_creds_dlg_msg" msgid="9207671133094039879">"Načítání podrobností pro přihlášení..."</string>
     <string name="stopping" msgid="4839698519340302982">"Zastavuji..."</string>
     <string name="stop" msgid="5687251076030630074">"Zastavit"</string>
-    <string name="reload" msgid="8585220783228408062">"Obnovit"</string>
+    <string name="reload" msgid="8585220783228408062">"Aktualizovat"</string>
     <string name="back" msgid="8414603107175713668">"Zpět"</string>
     <string name="forward" msgid="4288210890526641577">"Předat dál"</string>
     <string name="save" msgid="5922311934992468496">"OK"</string>
     <string name="do_not_save" msgid="6777633870113477714">"Zrušit"</string>
-    <string name="location" msgid="969988560160364559">"Umístění"</string>
-    <string name="name" msgid="5990326151488445481">"Název"</string>
+    <string name="location" msgid="969988560160364559">"Místo"</string>
+    <string name="name" msgid="5990326151488445481">"Jméno"</string>
     <string name="http" msgid="2163722670597250102">"http://"</string>
     <string name="save_to_bookmarks" msgid="588165100024086565">"Přidat záložku"</string>
     <string name="edit_bookmark" msgid="5024089053490231905">"Upravit záložku"</string>
@@ -82,8 +83,8 @@
     <string name="homepage_set" msgid="8768087280310966395">"Domovská stránka byla nastavena."</string>
     <string name="bookmark_needs_title" msgid="6245900436119218187">"Záložka musí mít název."</string>
     <string name="bookmark_needs_url" msgid="7809876865972755158">"Záložka musí mít umístění."</string>
-    <string name="empty_bookmark" msgid="7008697085928540511">"Nelze vytvořit prázdnou záložku."</string>
     <string name="bookmark_url_not_valid" msgid="6719785633980202419">"Adresa URL není platná."</string>
+    <string name="bookmark_cannot_save_url" msgid="791722768778386941">"Tuto adresu URL nelze přidat do záložek."</string>
     <string name="delete_bookmark" msgid="2422989994934201992">"Smazat"</string>
     <string name="bookmark_page" msgid="6845189305130307274">"Přidat poslední zobrazenou stránku do záložek"</string>
     <string name="switch_to_thumbnails" msgid="5493351529609043151">"Zobrazit jako miniatury"</string>
@@ -91,22 +92,15 @@
     <string name="current_page" msgid="7510129573681663135">"od "</string>
     <string name="delete_bookmark_warning" msgid="758043186202032205">"Záložka <xliff:g id="BOOKMARK">%s</xliff:g> bude smazána."</string>
     <string name="open_in_new_window" msgid="6596775546468054510">"Otevřít v novém okně"</string>
-    <string name="new_window" msgid="8117889615360211551">"Nové okno"</string>
     <string name="goto_dot" msgid="3895839050522602723">"Přejít"</string>
     <string name="find_dot" msgid="6259312434696611957">"Vyhledat na stránce"</string>
     <string name="select_dot" msgid="6299170761900561967">"Vybrat text"</string>
-    <string name="view_tabs" msgid="1119097492003550564">"Přehled okna"</string>
-    <string name="view_tabs_condensed" msgid="5803955493821945369">"Okna"</string>
     <string name="tab_picker_title" msgid="864478399057782913">"Aktuální okna"</string>
-    <string name="tab_picker_view_tab" msgid="2984342364915347656">"Zobrazit"</string>
-    <string name="tab_picker_new_tab" msgid="3080280018986866528">"Nové okno"</string>
     <string name="tab_picker_remove_tab" msgid="630087809802479397">"Zavřít"</string>
-    <string name="tab_picker_bookmark" msgid="1084409404198995477">"Přidat do záložek"</string>
-    <string name="tab_picker_send_url" msgid="9102803487525950021">"Sdílet odkaz"</string>
     <string name="bookmarks" msgid="1961279134885867815">"Záložky"</string>
     <string name="shortcut_bookmark" msgid="3974876480401135895">"Přidat do záložek"</string>
     <string name="history" msgid="2451240511251410032">"Historie"</string>
-    <string name="menu_view_download" msgid="2124570321712995120">"Stahování"</string>
+    <string name="menu_view_download" msgid="2124570321712995120">"Stažené"</string>
     <string name="copy_page_url" msgid="7635062169011319208">"Kopírovat adresu URL stránky"</string>
     <string name="share_page" msgid="593756995297268343">"Sdílet stránku"</string>
     <string name="contextmenu_openlink" msgid="7237961252214188935">"Otevřít"</string>
@@ -115,9 +109,10 @@
     <string name="contextmenu_savelink" msgid="5508554930832538184">"Uložit odkaz"</string>
     <string name="contextmenu_sharelink" msgid="5392275392280130331">"Sdílet odkaz"</string>
     <string name="contextmenu_copy" msgid="398860586635404030">"Kopírovat"</string>
-    <string name="contextmenu_copylink" msgid="5153657160294534270">"Kopírovat URL odkazu"</string>
+    <string name="contextmenu_copylink" msgid="5153657160294534270">"Kopírovat adresu URL odkazu"</string>
     <string name="contextmenu_download_image" msgid="4243829645180686912">"Uložit obrázek"</string>
     <string name="contextmenu_view_image" msgid="3870625602053600905">"Zobrazit obrázek"</string>
+    <string name="contextmenu_set_wallpaper" msgid="3691902960115350686">"Nastavit jako tapetu"</string>
     <string name="contextmenu_dial_dot" msgid="5856550683415933806">"Volat..."</string>
     <string name="contextmenu_add_contact" msgid="3183511922223645716">"Přidat kontakt"</string>
     <string name="contextmenu_send_mail" msgid="1014513374828775660">"Odeslat e-mail"</string>
@@ -128,14 +123,20 @@
     <string name="browser_bookmarks_page_bookmarks_text" msgid="6787605028726162673">"Záložky"</string>
     <string name="menu_preferences" msgid="6709237687234102240">"Nastavení"</string>
     <string name="pref_content_title" msgid="722227111894838633">"Nastavení obsahu stránky"</string>
-    <string name="pref_content_load_images" msgid="2125616852957377561">"Načítat obrázky"</string>
+    <string name="pref_content_load_images" msgid="2125616852957377561">"Načíst obrázky"</string>
     <string name="pref_content_load_images_summary" msgid="5055874125248398584">"Zobrazovat na webových stránkách obrázky"</string>
     <string name="pref_content_block_popups" msgid="7808433807197256726">"Blokovat vyskakovací okna"</string>
     <string name="pref_content_javascript" msgid="4570972030299516843">"Povolit JavaScript"</string>
     <string name="pref_content_open_in_background" msgid="824123779725118663">"Otevřít na pozadí"</string>
     <string name="pref_content_plugins" msgid="7231944644794301582">"Povolit pluginy"</string>
+  <string-array name="pref_content_plugins_choices">
+    <item msgid="6745108155096660725">"Vždy zapnuto"</item>
+    <item msgid="2484126708670016519">"Na požádání"</item>
+    <item msgid="8547442717307793863">"Vypnuto"</item>
+  </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_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>
     <string name="pref_content_landscape_only" msgid="2022546812766219672">"Zobrazení pouze na šířku"</string>
@@ -165,7 +166,7 @@
     <string name="pref_security_remember_passwords" msgid="6492957683454529549">"Zapamatovat hesla"</string>
     <string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"Ukládat uživatelská jména a hesla pro webové stránky"</string>
     <string name="pref_security_save_form_data" msgid="1213669802810198893">"Zapamatovat data formulářů"</string>
-    <string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"Zapamatovat si data zadaná do formulářů pro další použití"</string>
+    <string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"Zapamatovat si data, která zadám do formulářů, pro další použití"</string>
     <string name="pref_security_show_security_warning" msgid="8901135676266754559">"Zobrazit upozornění zabezpečení"</string>
     <string name="pref_security_show_security_warning_summary" msgid="8968906112720511704">"Zobrazit upozornění, pokud dojde k problému se zabezpečením webu"</string>
     <string name="pref_security_accept_cookies" msgid="3201367661925047989">"Přijímat soubory cookie"</string>
@@ -190,24 +191,23 @@
     <string name="pref_content_load_page_summary" msgid="8792093504054149369">"Zobrazit náhled nově otevřených stránek"</string>
     <string name="pref_extras_title" msgid="3091250467679722382">"Upřesnit nastavení"</string>
     <string name="pref_extras_website_settings" msgid="67866640052455549">"Zrušit přístup k poloze"</string>
-    <string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Zobrazit pokročilá nastavení pro jednotlivé webové stránky"</string>
+    <string name="pref_extras_website_settings_summary" msgid="1656771443223494406">"Pokročilá nastavení pro jednotlivé webové stránky"</string>
     <string name="pref_extras_reset_default" msgid="8904000515846202110">"Obnovit výchozí"</string>
-    <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Vymazat všechna data prohlížeče a obnovit všechna nastavení na výchozí hodnoty"</string>
-    <string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"Budou vymazána všechna data prohlížeče a obnoveny výchozí hodnoty nastavení."</string>
+    <string name="pref_extras_reset_default_summary" msgid="4247870778270414501">"Obnovit výchozí nastavení"</string>
+    <string name="pref_extras_reset_default_dlg" msgid="6640261575874704022">"Budou obnoveny výchozí hodnoty nastavení."</string>
     <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Obnovit výchozí"</string>
     <string name="pref_development_title" msgid="3263854204533056480">"Ladit"</string>
     <string name="pref_default_text_encoding" msgid="5742965543955558478">"Kódování textu"</string>
   <string-array name="pref_default_text_encoding_choices">
     <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
     <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
-    <item msgid="7143715548814380950">"Japonština (ISO-2022-JP)"</item>
-    <item msgid="5111312120564516587">"Japonština (SHIFT_JIS)"</item>
-    <item msgid="6545734186479713946">"Japonština (EUC-JP)"</item>
+    <item msgid="6122474363777211732">"Čínština (GBK)"</item>
+    <item msgid="373372275931607040">"Čínština (Big5)"</item>
+    <item msgid="891615911084608570">"Japonština (ISO-2022-JP)"</item>
+    <item msgid="5589150448475151241">"Japonština (SHIFT_JIS)"</item>
+    <item msgid="7356792686950371843">"Japonština (EUC-JP)"</item>
   </string-array>
     <string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Kódování textu"</string>
-    <string name="pref_default_text_encoding_default" msgid="5272126711231936722">"Latin-1"</string>
-    <string name="browserFrameRedirect" msgid="7049675479777828343">"Přesměrování"</string>
-    <string name="browserFrame307Post" msgid="1429094844669510768">"Probíhá přesměrování webové stránky. Chcete data zadaná do formuláře znovu odeslat do nového umístění?"</string>
     <string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Problémy s datovým připojením"</string>
     <string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Problém se souborem"</string>
     <string name="browserFrameFormResubmitLabel" msgid="2685923472682180360">"Potvrdit"</string>
@@ -234,21 +234,20 @@
     <string name="download_unknown_filename" msgid="4013465542563652175">"&lt;Neznámé&gt;"</string>
     <string name="download_menu_open" msgid="4888327480367757513">"Otevřít"</string>
     <string name="download_menu_clear" msgid="6264454531553418124">"Vymazat ze seznamu"</string>
+    <string name="download_menu_delete" msgid="8815502136393894148">"Smazat"</string>
     <string name="download_menu_cancel" msgid="2545333007601851574">"Zrušit stahování"</string>
     <string name="download_menu_cancel_all" msgid="2136550823151999166">"Zrušit stahování všech souborů"</string>
-    <string name="download_menu_clear_all" msgid="7423737413377703862">"Vymazat seznam"</string>
-    <string name="download_clear_dlg_title" msgid="7961996329529777390">"Vymazat"</string>
-    <string name="download_clear_dlg_msg" msgid="8056013815679757669">"Všechny položky v seznamu budou vymazány a odstraněny z mezipaměti prohlížeče."</string>
     <string name="download_cancel_dlg_title" msgid="8909108500262799748">"Zrušit stahování"</string>
     <string name="download_cancel_dlg_msg" msgid="6285389170052357797">"Stahování všech souborů (<xliff:g id="DOWNLOAD_COUNT">%d</xliff:g>) bude zrušeno a soubory budou vymazány z historie stahování."</string>
+    <string name="download_delete_file" msgid="5330036497843073249">"Soubor bude smazán"</string>
     <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">"Stahování bylo neúspěšné"</string>
-    <string name="download_no_sdcard_dlg_title" msgid="605904452159416792">"Žádná karta SD není dostupná."</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>
-    <string name="download_no_application" msgid="5054596425887523234">"Nebyla nalezena žádná aplikace, ve které lze tento soubor otevřít."</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>
     <string name="download_error" msgid="413496839831257187">"Stahování bylo neúspěšné."</string>
@@ -262,12 +261,10 @@
     <string name="download_file_error" msgid="1206648050615176113">"Stahování nelze dokončit. Není dostatek místa."</string>
     <string name="download_length_required" msgid="9038605488460437406">"Nelze stáhnout. Velikost položky nelze určit."</string>
     <string name="download_precondition_failed" msgid="8327584102874295580">"Stahování bylo přerušeno a nelze v něm pokračovat."</string>
-    <string name="activity_instrumentation_test_runner" msgid="8215091309334005029">"Testovací verze prohlížeče"</string>
     <string name="search_the_web" msgid="6046130189241962337">"Vyhledat na webu"</string>
     <string name="webstorage_outofspace_notification_title" msgid="1160474608059771788">"Zrušit přístup k poloze"</string>
     <string name="webstorage_outofspace_notification_text" msgid="7341075135051829692">"Kliknutím uvolníte místo."</string>
     <string name="webstorage_clear_data_title" msgid="689484577124333977">"Zrušit přístup k poloze"</string>
-    <string name="webstorage_clear_data_summary" msgid="3523128713743907805">"Zrušit přístup k poloze"</string>
     <string name="webstorage_clear_data_dialog_title" msgid="345457466368974706">"Vymazat uložená data"</string>
     <string name="webstorage_clear_data_dialog_message" msgid="6678281256970470125">"Zrušit přístup k poloze"</string>
     <string name="webstorage_clear_data_dialog_ok_button" msgid="2516563534211898636">"Vymazat vše"</string>
@@ -278,6 +275,8 @@
     <string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Sdílet polohu"</string>
     <string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Odmítnout"</string>
     <string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Zapamatovat předvolbu"</string>
+    <string name="geolocation_permissions_prompt_toast_allowed" msgid="987286072035125498">"Tyto stránky mohou přistupovat k vaší aktuální poloze. Toto nastavení můžete změnit zde: Nastavení -&gt; Nastavení webových stránek."</string>
+    <string name="geolocation_permissions_prompt_toast_disallowed" msgid="7695100950212692515">"Tyto stránky nemohou přistupovat k vaší aktuální poloze. Toto nastavení můžete změnit zde: Nastavení -&gt; Nastavení webových stránek."</string>
     <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Zrušit přístup k poloze"</string>
     <string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Tyto stránky mohou aktuálně získat přístup k informacím o vaší poloze"</string>
     <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Zrušit přístup k poloze"</string>
@@ -290,5 +289,5 @@
     <string name="website_settings_clear_all_dialog_message" msgid="6150502090601476333">"Všechna data webových stránek a oprávnění přistupovat k informacím o poloze budou vymazána."</string>
     <string name="website_settings_clear_all_dialog_ok_button" msgid="6401582240627669431">"Vymazat všechna data"</string>
     <string name="website_settings_clear_all_dialog_cancel_button" msgid="1896757051856611674">"Zrušit"</string>
-    <string name="zoom_overview_button_text" msgid="4146579940085488881">"Přehled"</string>
+    <string name="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Nastavení tapety..."</string>
 </resources>
diff --git a/res/values-da/arrays.xml b/res/values-da/arrays.xml
deleted file mode 100644
index 2048215..0000000
--- a/res/values-da/arrays.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="webstorage_quota_entries">
-    <item msgid="5433313236875537673">"Der er ingen tilladt kvote"</item>
-    <item msgid="7374272188672967690">"5 Mb"</item>
-    <item msgid="8699352701856136738">"10 Mb"</item>
-    <item msgid="2018822431469084862">"30 Mb"</item>
-    <item msgid="5383642976774534074">"100 Mb"</item>
-  </string-array>
-  <string-array name="webstorage_quota_entries_values">
-    <item msgid="7620410313725236055">"0"</item>
-    <item msgid="4302688814760304206">"5"</item>
-    <item msgid="7291990205847586165">"10"</item>
-    <item msgid="916913372287112423">"30"</item>
-    <item msgid="3437188301324229987">"100"</item>
-  </string-array>
-</resources>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index a5dde55..3d667ed 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -1,21 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--  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.
--->
+ -->
+
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="1935869255545976415">"Browser"</string>
+    <string name="choose_upload" msgid="3649366287575002063">"Vælg fil til upload"</string>
     <string name="new_tab" msgid="4505722538297295141">"Nyt vindue"</string>
     <string name="active_tabs" msgid="3050623868203544623">"Vinduer"</string>
     <string name="tab_bookmarks" msgid="2305793036003473653">"Bogmærker"</string>
@@ -58,7 +60,6 @@
     <string name="validity_period" msgid="57988851973181309">"Gyldighed:"</string>
     <string name="issued_on" msgid="2082890654801808368">"Udstedt den:"</string>
     <string name="expires_on" msgid="8061200430557020704">"Udløber den:"</string>
-    <string name="retrieving_creds_dlg_msg" msgid="9207671133094039879">"Henter loginoplysninger ..."</string>
     <string name="stopping" msgid="4839698519340302982">"Stopper ..."</string>
     <string name="stop" msgid="5687251076030630074">"Stop"</string>
     <string name="reload" msgid="8585220783228408062">"Opdater"</string>
@@ -82,8 +83,8 @@
     <string name="homepage_set" msgid="8768087280310966395">"Startsiden er indstillet."</string>
     <string name="bookmark_needs_title" msgid="6245900436119218187">"Bogmærket skal have et navn."</string>
     <string name="bookmark_needs_url" msgid="7809876865972755158">"Bogmærket skal have en placering."</string>
-    <string name="empty_bookmark" msgid="7008697085928540511">"Der kan ikke oprettes et tomt bogmærke."</string>
     <string name="bookmark_url_not_valid" msgid="6719785633980202419">"Webadressen er ikke gyldig."</string>
+    <string name="bookmark_cannot_save_url" msgid="791722768778386941">"Denne webadresse kan ikke tilføjes som bogmærke."</string>
     <string name="delete_bookmark" msgid="2422989994934201992">"Slet"</string>
     <string name="bookmark_page" msgid="6845189305130307274">"Opret bogmærke for sidst viste side"</string>
     <string name="switch_to_thumbnails" msgid="5493351529609043151">"Miniaturevisning"</string>
@@ -91,20 +92,13 @@
     <string name="current_page" msgid="7510129573681663135">"fra "</string>
     <string name="delete_bookmark_warning" msgid="758043186202032205">"Bogmærket \"<xliff:g id="BOOKMARK">%s</xliff:g>\" slettes."</string>
     <string name="open_in_new_window" msgid="6596775546468054510">"Åbn i et nyt vindue"</string>
-    <string name="new_window" msgid="8117889615360211551">"Nyt vindue"</string>
     <string name="goto_dot" msgid="3895839050522602723">"Gå"</string>
     <string name="find_dot" msgid="6259312434696611957">"Find på side"</string>
     <string name="select_dot" msgid="6299170761900561967">"Vælg tekst"</string>
-    <string name="view_tabs" msgid="1119097492003550564">"Vinduesoversigt"</string>
-    <string name="view_tabs_condensed" msgid="5803955493821945369">"Vinduer"</string>
     <string name="tab_picker_title" msgid="864478399057782913">"Aktuelle vinduer"</string>
-    <string name="tab_picker_view_tab" msgid="2984342364915347656">"Vis"</string>
-    <string name="tab_picker_new_tab" msgid="3080280018986866528">"Nyt vindue"</string>
     <string name="tab_picker_remove_tab" msgid="630087809802479397">"Luk"</string>
-    <string name="tab_picker_bookmark" msgid="1084409404198995477">"Opret et bogmærke"</string>
-    <string name="tab_picker_send_url" msgid="9102803487525950021">"Del link"</string>
     <string name="bookmarks" msgid="1961279134885867815">"Bogmærker"</string>
-    <string name="shortcut_bookmark" msgid="3974876480401135895">"Bogmærke"</string>
+    <string name="shortcut_bookmark" msgid="3974876480401135895">"Opret et bogmærke"</string>
     <string name="history" msgid="2451240511251410032">"Oversigt"</string>
     <string name="menu_view_download" msgid="2124570321712995120">"Downloads"</string>
     <string name="copy_page_url" msgid="7635062169011319208">"Kopier sidens webadresse"</string>
@@ -118,6 +112,7 @@
     <string name="contextmenu_copylink" msgid="5153657160294534270">"Kopier linkets webadresse"</string>
     <string name="contextmenu_download_image" msgid="4243829645180686912">"Gem billede"</string>
     <string name="contextmenu_view_image" msgid="3870625602053600905">"Vis billede"</string>
+    <string name="contextmenu_set_wallpaper" msgid="3691902960115350686">"Anvend som baggrund"</string>
     <string name="contextmenu_dial_dot" msgid="5856550683415933806">"Ring til ..."</string>
     <string name="contextmenu_add_contact" msgid="3183511922223645716">"Tilføj kontakt"</string>
     <string name="contextmenu_send_mail" msgid="1014513374828775660">"Send e-mail"</string>
@@ -134,8 +129,14 @@
     <string name="pref_content_javascript" msgid="4570972030299516843">"Aktiver Javascript"</string>
     <string name="pref_content_open_in_background" msgid="824123779725118663">"Åbn i baggrunden"</string>
     <string name="pref_content_plugins" msgid="7231944644794301582">"Aktiver plugins"</string>
+  <string-array name="pref_content_plugins_choices">
+    <item msgid="6745108155096660725">"Altid slået til"</item>
+    <item msgid="2484126708670016519">"Påkrævet"</item>
+    <item msgid="8547442717307793863">"Fra"</item>
+  </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_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>
     <string name="pref_content_landscape_only" msgid="2022546812766219672">"Kun liggende visning"</string>
@@ -190,24 +191,23 @@
     <string name="pref_content_load_page_summary" msgid="8792093504054149369">"Vis oversigt over sider, som er åbnet for nylig"</string>
     <string name="pref_extras_title" msgid="3091250467679722382">"Avancerede indstillinger"</string>
     <string name="pref_extras_website_settings" msgid="67866640052455549">"Indstillinger for websteder"</string>
-    <string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Vis avancerede indstillinger for individuelle websteder"</string>
+    <string name="pref_extras_website_settings_summary" msgid="1656771443223494406">"Avancerede indstillinger for individuelle websteder"</string>
     <string name="pref_extras_reset_default" msgid="8904000515846202110">"Nulstil til standard"</string>
-    <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Ryd alle browserdata, og nulstil alle indstillinger til standard"</string>
-    <string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"Alle browserdata slettes, og indstillingerne nulstilles til standardværdier."</string>
+    <string name="pref_extras_reset_default_summary" msgid="4247870778270414501">"Gendan standardindstillinger"</string>
+    <string name="pref_extras_reset_default_dlg" msgid="6640261575874704022">"Indstillingerne vil blive gendannet til standardværdierne."</string>
     <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Nulstil til standard"</string>
     <string name="pref_development_title" msgid="3263854204533056480">"Fejlretning"</string>
     <string name="pref_default_text_encoding" msgid="5742965543955558478">"Tekstkodning"</string>
   <string-array name="pref_default_text_encoding_choices">
     <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
     <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
-    <item msgid="7143715548814380950">"Japansk (ISO-2022-JP)"</item>
-    <item msgid="5111312120564516587">"Japansk (SHIFT_JIS)"</item>
-    <item msgid="6545734186479713946">"Japansk (EUC-JP)"</item>
+    <item msgid="6122474363777211732">"Kinesisk (GBK)"</item>
+    <item msgid="373372275931607040">"Kinesisk (Big5)"</item>
+    <item msgid="891615911084608570">"Japansk (ISO-2022-JP)"</item>
+    <item msgid="5589150448475151241">"Japansk (SHIFT_JIS)"</item>
+    <item msgid="7356792686950371843">"Japansk (EUC-JP)"</item>
   </string-array>
     <string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Tekstkodning"</string>
-    <string name="pref_default_text_encoding_default" msgid="5272126711231936722">"Latin-1"</string>
-    <string name="browserFrameRedirect" msgid="7049675479777828343">"Omdiriger"</string>
-    <string name="browserFrame307Post" msgid="1429094844669510768">"Dette websted omdirigeres. Send dine indtastede formulardata til den nye placering?"</string>
     <string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Dataforbindelsesproblem"</string>
     <string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Der er et problem med filen"</string>
     <string name="browserFrameFormResubmitLabel" msgid="2685923472682180360">"Bekræft"</string>
@@ -234,25 +234,24 @@
     <string name="download_unknown_filename" msgid="4013465542563652175">"&lt;Ukendt&gt;"</string>
     <string name="download_menu_open" msgid="4888327480367757513">"Åbn"</string>
     <string name="download_menu_clear" msgid="6264454531553418124">"Fjern fra listen"</string>
+    <string name="download_menu_delete" msgid="8815502136393894148">"Slet"</string>
     <string name="download_menu_cancel" msgid="2545333007601851574">"Annuller download"</string>
     <string name="download_menu_cancel_all" msgid="2136550823151999166">"Annuller alle downloads"</string>
-    <string name="download_menu_clear_all" msgid="7423737413377703862">"Ryd liste"</string>
-    <string name="download_clear_dlg_title" msgid="7961996329529777390">"Ryd"</string>
-    <string name="download_clear_dlg_msg" msgid="8056013815679757669">"Alle elementer ryddes fra listen og fjernes fra browserens cache."</string>
     <string name="download_cancel_dlg_title" msgid="8909108500262799748">"Annuller downloads"</string>
     <string name="download_cancel_dlg_msg" msgid="6285389170052357797">"Alle <xliff:g id="DOWNLOAD_COUNT">%d</xliff:g> downloads annulleres og ryddes fra downloadoversigten."</string>
+    <string name="download_delete_file" msgid="5330036497843073249">"Filen slettes"</string>
     <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">"Du skal bruge et SD-kort for at downloade <xliff:g id="FILENAME">%s</xliff:g>."</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>
-    <string name="download_no_application" msgid="5054596425887523234">"Der blev ikke fundet et program, der kan åbne denne fil."</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>
     <string name="download_error" msgid="413496839831257187">"Download mislykkedes."</string>
-    <string name="download_success" msgid="2279041638155595203">"Download af <xliff:g id="FILE">%s</xliff:g> er afsluttet."</string>
+    <string name="download_success" msgid="2279041638155595203">"<xliff:g id="FILE">%s</xliff:g> Download afsluttet."</string>
     <string name="download_running" msgid="2622942231322015059">"Downloader ..."</string>
     <string name="download_pending" msgid="2599683668575349559">"Starter download ..."</string>
     <string name="download_pending_network" msgid="6548714525679461053">"Venter på dataforbindelse ..."</string>
@@ -262,12 +261,10 @@
     <string name="download_file_error" msgid="1206648050615176113">"Download kan ikke afsluttes. Der er ikke nok plads."</string>
     <string name="download_length_required" msgid="9038605488460437406">"Der kan ikke downloades. Størrelsen på elementet kan ikke fastsættes."</string>
     <string name="download_precondition_failed" msgid="8327584102874295580">"Download blev afbrudt. Den kan ikke genoptages."</string>
-    <string name="activity_instrumentation_test_runner" msgid="8215091309334005029">"Testkørsel af browser"</string>
     <string name="search_the_web" msgid="6046130189241962337">"Søg på nettet"</string>
     <string name="webstorage_outofspace_notification_title" msgid="1160474608059771788">"Browserlageret er fuldt"</string>
     <string name="webstorage_outofspace_notification_text" msgid="7341075135051829692">"Klik her for at frigøre plads."</string>
     <string name="webstorage_clear_data_title" msgid="689484577124333977">"Ryd lagrede data"</string>
-    <string name="webstorage_clear_data_summary" msgid="3523128713743907805">"Fjern alle databaser, der er tilknyttet dette websted"</string>
     <string name="webstorage_clear_data_dialog_title" msgid="345457466368974706">"Ryd lagrede data"</string>
     <string name="webstorage_clear_data_dialog_message" msgid="6678281256970470125">"Alle data, der er lagret af dette websted, slettes"</string>
     <string name="webstorage_clear_data_dialog_ok_button" msgid="2516563534211898636">"Ryd alle"</string>
@@ -278,6 +275,8 @@
     <string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Del placering"</string>
     <string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Afvis"</string>
     <string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Husk indstilling"</string>
+    <string name="geolocation_permissions_prompt_toast_allowed" msgid="987286072035125498">"Dette websted har adgang til din placering. Skift denne indstilling i: Indstillinger -&gt; Webstedsindstillinger"</string>
+    <string name="geolocation_permissions_prompt_toast_disallowed" msgid="7695100950212692515">"Dette websted kan ikke få adgang til din placering. Skift denne indstilling i Indstillinger -&gt; Webstedsindstillinger"</string>
     <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Ryd placeringsadgang"</string>
     <string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Dette websted har i øjeblikket adgang til din placering"</string>
     <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Dette websted har i øjeblikket ikke adgang til din placering"</string>
@@ -290,5 +289,5 @@
     <string name="website_settings_clear_all_dialog_message" msgid="6150502090601476333">"Alle webstedsdata og placeringstilladelser slettes."</string>
     <string name="website_settings_clear_all_dialog_ok_button" msgid="6401582240627669431">"Slet alle data"</string>
     <string name="website_settings_clear_all_dialog_cancel_button" msgid="1896757051856611674">"Annuller"</string>
-    <string name="zoom_overview_button_text" msgid="4146579940085488881">"Oversigt"</string>
+    <string name="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Indstiller tapet ..."</string>
 </resources>
diff --git a/res/values-de/arrays.xml b/res/values-de/arrays.xml
deleted file mode 100644
index bfee20d..0000000
--- a/res/values-de/arrays.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="webstorage_quota_entries">
-    <item msgid="5433313236875537673">"Kein Kontingent erlaubt"</item>
-    <item msgid="7374272188672967690">"5 MB"</item>
-    <item msgid="8699352701856136738">"10 MB"</item>
-    <item msgid="2018822431469084862">"30 MB"</item>
-    <item msgid="5383642976774534074">"100 MB"</item>
-  </string-array>
-  <string-array name="webstorage_quota_entries_values">
-    <item msgid="7620410313725236055">"0"</item>
-    <item msgid="4302688814760304206">"5"</item>
-    <item msgid="7291990205847586165">"10"</item>
-    <item msgid="916913372287112423">"30"</item>
-    <item msgid="3437188301324229987">"100"</item>
-  </string-array>
-</resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index a865197..6d26905 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -1,21 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--  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.
--->
+ -->
+
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="1935869255545976415">"Browser"</string>
+    <string name="choose_upload" msgid="3649366287575002063">"Datei zum Hochladen auswählen"</string>
     <string name="new_tab" msgid="4505722538297295141">"Neues Fenster"</string>
     <string name="active_tabs" msgid="3050623868203544623">"Fenster"</string>
     <string name="tab_bookmarks" msgid="2305793036003473653">"Lesezeichen"</string>
@@ -33,8 +35,8 @@
   <plurals name="matches_found">
     <item quantity="zero" msgid="6242659159545399963">"Keine Übereinstimmungen"</item>
     <item quantity="one" msgid="4352019729062956802">"1 Übereinstimmung"</item>
-    <item quantity="few" msgid="5544267486978946555">"<xliff:g id="NUMBER">%d</xliff:g> Übereinstimmungen"</item>
-    <item quantity="other" msgid="6616125067364315405">"<xliff:g id="NUMBER">%d</xliff:g> Übereinstimmungen"</item>
+    <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="page_info" msgid="4048529256302257195">"Seiten-Info"</string>
@@ -58,7 +60,6 @@
     <string name="validity_period" msgid="57988851973181309">"Gültigkeit:"</string>
     <string name="issued_on" msgid="2082890654801808368">"Ausgegeben am:"</string>
     <string name="expires_on" msgid="8061200430557020704">"Läuft ab am:"</string>
-    <string name="retrieving_creds_dlg_msg" msgid="9207671133094039879">"Anmeldedetails werden abgerufen…"</string>
     <string name="stopping" msgid="4839698519340302982">"Wird angehalten..."</string>
     <string name="stop" msgid="5687251076030630074">"Anhalten"</string>
     <string name="reload" msgid="8585220783228408062">"Aktualisieren"</string>
@@ -66,7 +67,7 @@
     <string name="forward" msgid="4288210890526641577">"Vorwärts"</string>
     <string name="save" msgid="5922311934992468496">"OK"</string>
     <string name="do_not_save" msgid="6777633870113477714">"Abbrechen"</string>
-    <string name="location" msgid="969988560160364559">"Ort"</string>
+    <string name="location" msgid="969988560160364559">"URL"</string>
     <string name="name" msgid="5990326151488445481">"Name"</string>
     <string name="http" msgid="2163722670597250102">"http://"</string>
     <string name="save_to_bookmarks" msgid="588165100024086565">"Lesezeichen hinzufügen"</string>
@@ -82,8 +83,8 @@
     <string name="homepage_set" msgid="8768087280310966395">"Startseite festgelegt."</string>
     <string name="bookmark_needs_title" msgid="6245900436119218187">"Das Lesezeichen muss über einen Namen verfügen."</string>
     <string name="bookmark_needs_url" msgid="7809876865972755158">"Das Lesezeichen muss über einen Speicherort verfügen."</string>
-    <string name="empty_bookmark" msgid="7008697085928540511">"Sie können kein leeres Lesezeichen erstellen."</string>
     <string name="bookmark_url_not_valid" msgid="6719785633980202419">"URL ist nicht gültig."</string>
+    <string name="bookmark_cannot_save_url" msgid="791722768778386941">"Diese URL kann nicht als Lesezeichen gespeichert werden."</string>
     <string name="delete_bookmark" msgid="2422989994934201992">"Löschen"</string>
     <string name="bookmark_page" msgid="6845189305130307274">"Lesezeichen für zuletzt besuchte Seite"</string>
     <string name="switch_to_thumbnails" msgid="5493351529609043151">"Miniaturansicht"</string>
@@ -91,18 +92,11 @@
     <string name="current_page" msgid="7510129573681663135">"von "</string>
     <string name="delete_bookmark_warning" msgid="758043186202032205">"Lesezeichen \"<xliff:g id="BOOKMARK">%s</xliff:g>\" wird gelöscht."</string>
     <string name="open_in_new_window" msgid="6596775546468054510">"In neuem Fenster öffnen"</string>
-    <string name="new_window" msgid="8117889615360211551">"Neues Fenster"</string>
     <string name="goto_dot" msgid="3895839050522602723">"Los"</string>
     <string name="find_dot" msgid="6259312434696611957">"Auf Seite suchen"</string>
     <string name="select_dot" msgid="6299170761900561967">"Text auswählen"</string>
-    <string name="view_tabs" msgid="1119097492003550564">"Fensterübersicht"</string>
-    <string name="view_tabs_condensed" msgid="5803955493821945369">"Fenster"</string>
     <string name="tab_picker_title" msgid="864478399057782913">"Aktuelle Fenster"</string>
-    <string name="tab_picker_view_tab" msgid="2984342364915347656">"Anzeigen"</string>
-    <string name="tab_picker_new_tab" msgid="3080280018986866528">"Neues Fenster"</string>
     <string name="tab_picker_remove_tab" msgid="630087809802479397">"Schließen"</string>
-    <string name="tab_picker_bookmark" msgid="1084409404198995477">"Lesezeichen"</string>
-    <string name="tab_picker_send_url" msgid="9102803487525950021">"Link weiterleiten"</string>
     <string name="bookmarks" msgid="1961279134885867815">"Lesezeichen"</string>
     <string name="shortcut_bookmark" msgid="3974876480401135895">"Lesezeichen"</string>
     <string name="history" msgid="2451240511251410032">"Verlauf"</string>
@@ -118,6 +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_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>
@@ -130,13 +125,19 @@
     <string name="pref_content_title" msgid="722227111894838633">"Einstellungen für Seiteninhalt"</string>
     <string name="pref_content_load_images" msgid="2125616852957377561">"Bilder laden"</string>
     <string name="pref_content_load_images_summary" msgid="5055874125248398584">"Bilder auf Webseiten anzeigen"</string>
-    <string name="pref_content_block_popups" msgid="7808433807197256726">"Popupfenster blockieren"</string>
+    <string name="pref_content_block_popups" msgid="7808433807197256726">"Pop-ups blockieren"</string>
     <string name="pref_content_javascript" msgid="4570972030299516843">"JavaScript aktivieren"</string>
     <string name="pref_content_open_in_background" msgid="824123779725118663">"Im Hintergrund öffnen"</string>
     <string name="pref_content_plugins" msgid="7231944644794301582">"Plug-ins aktivieren"</string>
+  <string-array name="pref_content_plugins_choices">
+    <item msgid="6745108155096660725">"Immer an"</item>
+    <item msgid="2484126708670016519">"Nach Bedarf"</item>
+    <item msgid="8547442717307793863">"Aus"</item>
+  </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_autofit" msgid="8260474534053660809">"Seiten autom. anpassen"</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>
     <string name="pref_content_landscape_only" msgid="2022546812766219672">"Anzeige nur im Querformat"</string>
     <string name="pref_content_landscape_only_summary" msgid="1008238895535428855">"Seiten nur im breiteren Querformat anzeigen"</string>
@@ -144,7 +145,7 @@
     <string name="pref_privacy_clear_cache" msgid="3380316479925886998">"Cache löschen"</string>
     <string name="pref_privacy_clear_cache_summary" msgid="2216463577207991454">"Content und Datenbanken aus dem lokalen Cache löschen"</string>
     <string name="pref_privacy_clear_cache_dlg" msgid="5541011591300753881">"Content und Datenbanken werden aus dem lokalen Cache gelöscht."</string>
-    <string name="pref_privacy_clear_cookies" msgid="3095583579133780331">"Alle Cookiedaten löschen"</string>
+    <string name="pref_privacy_clear_cookies" msgid="3095583579133780331">"Cookie-Daten löschen"</string>
     <string name="pref_privacy_clear_cookies_summary" msgid="6962742063990677520">"Alle Browser-Cookies löschen"</string>
     <string name="pref_privacy_clear_cookies_dlg" msgid="552855688091432682">"Alle Cookies werden gelöscht."</string>
     <string name="pref_privacy_clear_history" msgid="8723795508825198477">"Verlauf löschen"</string>
@@ -157,7 +158,7 @@
     <string name="pref_privacy_clear_passwords_summary" msgid="8856782718942903335">"Alle gespeicherten Passwörter löschen"</string>
     <string name="pref_privacy_clear_passwords_dlg" msgid="2083869328824248255">"Alle gespeicherten Passwörter werden gelöscht."</string>
     <string name="pref_privacy_enable_geolocation" msgid="1395040170290765686">"Standort aktivieren"</string>
-    <string name="pref_privacy_enable_geolocation_summary" msgid="8437020934664306205">"Zugriff auf Ihren Standort für Websites ermöglichen"</string>
+    <string name="pref_privacy_enable_geolocation_summary" msgid="8437020934664306205">"Standortzugriff für Websites zulassen"</string>
     <string name="pref_privacy_clear_geolocation_access" msgid="6649680770030042980">"Standortzugriff löschen"</string>
     <string name="pref_privacy_clear_geolocation_access_summary" msgid="7750143359497314679">"Standortzugriff für alle Websites löschen"</string>
     <string name="pref_privacy_clear_geolocation_access_dlg" msgid="7327063124488827244">"Standortzugriff für alle Websites löschen"</string>
@@ -167,9 +168,9 @@
     <string name="pref_security_save_form_data" msgid="1213669802810198893">"Formulardaten merken"</string>
     <string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"Daten in Formularen zur späteren Verwendung merken"</string>
     <string name="pref_security_show_security_warning" msgid="8901135676266754559">"Sicherheitswarnungen"</string>
-    <string name="pref_security_show_security_warning_summary" msgid="8968906112720511704">"Bei Problemen mit der Sicherheit der Website Warnung anzeigen"</string>
+    <string name="pref_security_show_security_warning_summary" msgid="8968906112720511704">"Warnung anzeigen, wenn bei einer Website Sicherheitsprobleme auftreten"</string>
     <string name="pref_security_accept_cookies" msgid="3201367661925047989">"Cookies akzeptieren"</string>
-    <string name="pref_security_accept_cookies_summary" msgid="1465118934875026920">"Speichern und Lesen von \"Cookie\"-Daten zulassen"</string>
+    <string name="pref_security_accept_cookies_summary" msgid="1465118934875026920">"Speichern und Lesen von Cookie-Daten zulassen"</string>
     <string name="pref_text_size" msgid="3827031324346612208">"Textgröße"</string>
   <string-array name="pref_text_size_choices">
     <item msgid="4952686548944739548">"Sehr klein"</item>
@@ -186,28 +187,27 @@
     <item msgid="3840999588443167001">"Nah"</item>
   </string-array>
     <string name="pref_default_zoom_dialogtitle" msgid="6095974367125109021">"Standard-Zoom"</string>
-    <string name="pref_content_load_page" msgid="2219810141690955452">"Seiten in der Übersicht öffnen"</string>
+    <string name="pref_content_load_page" msgid="2219810141690955452">"Seitenübersicht"</string>
     <string name="pref_content_load_page_summary" msgid="8792093504054149369">"Neue Seiten in der Übersicht anzeigen"</string>
     <string name="pref_extras_title" msgid="3091250467679722382">"Erweiterte Einstellungen"</string>
-    <string name="pref_extras_website_settings" msgid="67866640052455549">"Websiteeinstellungen"</string>
-    <string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Erweiterte Einstellungen für einzelne Websites anzeigen"</string>
-    <string name="pref_extras_reset_default" msgid="8904000515846202110">"Auf Standard zurücksetzen"</string>
-    <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Alle Browserdaten löschen und Einstellungen zurücksetzen"</string>
-    <string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"Alle Browserdaten werden gelöscht. Alle Einstellungen werden auf die Standardeinstellung zurückgesetzt."</string>
+    <string name="pref_extras_website_settings" msgid="67866640052455549">"Website-Einstellungen"</string>
+    <string name="pref_extras_website_settings_summary" msgid="1656771443223494406">"Erweiterte Einstellungen für einzelne Websites"</string>
+    <string name="pref_extras_reset_default" msgid="8904000515846202110">"Zurück auf Standard"</string>
+    <string name="pref_extras_reset_default_summary" msgid="4247870778270414501">"Standardeinstellungen wiederherstellen"</string>
+    <string name="pref_extras_reset_default_dlg" msgid="6640261575874704022">"Die Einstellungen werden auf die Standardeinstellung zurückgesetzt."</string>
     <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Auf Standardeinstellung zurücksetzen"</string>
     <string name="pref_development_title" msgid="3263854204533056480">"Debuggen"</string>
     <string name="pref_default_text_encoding" msgid="5742965543955558478">"Textcodierung"</string>
   <string-array name="pref_default_text_encoding_choices">
     <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
     <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
-    <item msgid="7143715548814380950">"Japanisch (ISO-2022-JP)"</item>
-    <item msgid="5111312120564516587">"Japanisch (SHIFT_JIS)"</item>
-    <item msgid="6545734186479713946">"Japanisch (EUC-JP)"</item>
+    <item msgid="6122474363777211732">"Chinesisch (GBK)"</item>
+    <item msgid="373372275931607040">"Chinesisch (Big5)"</item>
+    <item msgid="891615911084608570">"Japanisch (ISO-2022-JP)"</item>
+    <item msgid="5589150448475151241">"Japanisch (SHIFT_JIS)"</item>
+    <item msgid="7356792686950371843">"Japanisch (EUC-JP)"</item>
   </string-array>
     <string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Textcodierung"</string>
-    <string name="pref_default_text_encoding_default" msgid="5272126711231936722">"Latin-1"</string>
-    <string name="browserFrameRedirect" msgid="7049675479777828343">"Redirect"</string>
-    <string name="browserFrame307Post" msgid="1429094844669510768">"Diese Webseite wird umgeleitet. Sollen Ihre eingegebenen Formulardaten an den neuen Standort gesendet werden?"</string>
     <string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Datenverbindungsproblem"</string>
     <string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Problem mit Datei"</string>
     <string name="browserFrameFormResubmitLabel" msgid="2685923472682180360">"Bestätigen"</string>
@@ -219,7 +219,7 @@
     <string name="empty_history" msgid="8738772352308207274">"Browserverlauf ist leer."</string>
     <string name="add_new_bookmark" msgid="8086367791400349049">"Lesezeichen hinzufügen..."</string>
     <string name="add_bookmark_short" msgid="3783984330998103735">"Hinzufügen"</string>
-    <string name="search_hint" msgid="4647356319916631820">"URL suchen oder eingeben"</string>
+    <string name="search_hint" msgid="4647356319916631820">"Suchen oder URL eingeben"</string>
     <string name="search_button_text" msgid="5235226933877634410">"Los"</string>
     <string name="search_settings_description" msgid="1422401062529014107">"Lesezeichen und Webprotokoll"</string>
     <string name="attention" msgid="3473639060042811244">"Achtung"</string>
@@ -234,21 +234,20 @@
     <string name="download_unknown_filename" msgid="4013465542563652175">"&lt;Unbekannt&gt;"</string>
     <string name="download_menu_open" msgid="4888327480367757513">"Öffnen"</string>
     <string name="download_menu_clear" msgid="6264454531553418124">"Aus Liste löschen"</string>
+    <string name="download_menu_delete" msgid="8815502136393894148">"Löschen"</string>
     <string name="download_menu_cancel" msgid="2545333007601851574">"Download abbrechen"</string>
     <string name="download_menu_cancel_all" msgid="2136550823151999166">"Alle Downloads abbrechen"</string>
-    <string name="download_menu_clear_all" msgid="7423737413377703862">"Liste löschen"</string>
-    <string name="download_clear_dlg_title" msgid="7961996329529777390">"Löschen"</string>
-    <string name="download_clear_dlg_msg" msgid="8056013815679757669">"Alle Elemente werden aus der Liste gelöscht und aus dem Browser-Cache entfernt."</string>
     <string name="download_cancel_dlg_title" msgid="8909108500262799748">"Downloads abbrechen"</string>
     <string name="download_cancel_dlg_msg" msgid="6285389170052357797">"Alle <xliff:g id="DOWNLOAD_COUNT">%d</xliff:g> Downloads werden abgebrochen und aus dem Downloadverlauf gelöscht."</string>
+    <string name="download_delete_file" msgid="5330036497843073249">"Datei wird gelöscht."</string>
     <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 ist ausgelastet. Wählen Sie in der Benachrichtigung \"USB-Speicher deaktivieren\" aus, um Downloads zuzulassen."</string>
-    <string name="download_no_application" msgid="5054596425887523234">"Es kann keine Anwendung gefunden werden, um diese Datei zu öffnen."</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>
+    <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>
     <string name="download_error" msgid="413496839831257187">"Download war nicht erfolgreich."</string>
@@ -262,12 +261,10 @@
     <string name="download_file_error" msgid="1206648050615176113">"Download kann nicht beendet werden, da nicht genügend Speicherplatz vorhanden ist."</string>
     <string name="download_length_required" msgid="9038605488460437406">"Download kann nicht gestartet werden, da die Größe des Elements nicht bestimmt werden kann."</string>
     <string name="download_precondition_failed" msgid="8327584102874295580">"Download wurde unterbrochen und kann nicht fortgesetzt werden."</string>
-    <string name="activity_instrumentation_test_runner" msgid="8215091309334005029">"Browser Test Runner"</string>
     <string name="search_the_web" msgid="6046130189241962337">"Web durchsuchen"</string>
     <string name="webstorage_outofspace_notification_title" msgid="1160474608059771788">"Browserspeicher voll"</string>
     <string name="webstorage_outofspace_notification_text" msgid="7341075135051829692">"Klicken Sie, um Speicherplatz freizugeben."</string>
     <string name="webstorage_clear_data_title" msgid="689484577124333977">"Gespeicherte Daten löschen"</string>
-    <string name="webstorage_clear_data_summary" msgid="3523128713743907805">"Alle mit dieser Website verknüpften Datenbanken entfernen"</string>
     <string name="webstorage_clear_data_dialog_title" msgid="345457466368974706">"Gespeicherte Daten löschen"</string>
     <string name="webstorage_clear_data_dialog_message" msgid="6678281256970470125">"Alle von dieser Website gespeicherten Daten werden gelöscht."</string>
     <string name="webstorage_clear_data_dialog_ok_button" msgid="2516563534211898636">"Alles löschen"</string>
@@ -278,6 +275,8 @@
     <string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Standort freigeben"</string>
     <string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Ablehnen"</string>
     <string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Voreinstellung speichern"</string>
+    <string name="geolocation_permissions_prompt_toast_allowed" msgid="987286072035125498">"Diese Website hat Zugriff auf Ihren Standort. Ändern Sie diese Einstellung unter Einstellungen -&gt; Website-Einstellungen."</string>
+    <string name="geolocation_permissions_prompt_toast_disallowed" msgid="7695100950212692515">"Diese Website hat keinen Zugriff auf Ihren Standort. Ändern Sie diese Einstellung unter Einstellungen -&gt; Website-Einstellungen."</string>
     <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Standortzugriff löschen"</string>
     <string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Diese Website hat derzeit Zugriff auf Ihren Standort."</string>
     <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Diese Website hat derzeit keinen Zugriff auf Ihren Standort."</string>
@@ -290,5 +289,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="zoom_overview_button_text" msgid="4146579940085488881">"Übersicht"</string>
+    <string name="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Hintergrundbild wird eingestellt..."</string>
 </resources>
diff --git a/res/values-el/arrays.xml b/res/values-el/arrays.xml
deleted file mode 100644
index c1c25c5..0000000
--- a/res/values-el/arrays.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="webstorage_quota_entries">
-    <item msgid="5433313236875537673">"Δεν επιτρέπονται όρια"</item>
-    <item msgid="7374272188672967690">"5 MB"</item>
-    <item msgid="8699352701856136738">"10 MB"</item>
-    <item msgid="2018822431469084862">"30 MB"</item>
-    <item msgid="5383642976774534074">"100 MB"</item>
-  </string-array>
-  <string-array name="webstorage_quota_entries_values">
-    <item msgid="7620410313725236055">"0"</item>
-    <item msgid="4302688814760304206">"5"</item>
-    <item msgid="7291990205847586165">"10"</item>
-    <item msgid="916913372287112423">"30"</item>
-    <item msgid="3437188301324229987">"100"</item>
-  </string-array>
-</resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 9273ec2..7da0027 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -1,21 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--  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.
--->
+ -->
+
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="1935869255545976415">"Internet"</string>
+    <string name="choose_upload" msgid="3649366287575002063">"Επιλογή αρχείου για μεταφόρτωση"</string>
     <string name="new_tab" msgid="4505722538297295141">"Νέο παράθυρο"</string>
     <string name="active_tabs" msgid="3050623868203544623">"Παράθυρα"</string>
     <string name="tab_bookmarks" msgid="2305793036003473653">"Σελιδοδείκτες"</string>
@@ -58,7 +60,6 @@
     <string name="validity_period" msgid="57988851973181309">"Ισχύς:"</string>
     <string name="issued_on" msgid="2082890654801808368">"Εκδόθηκε στις:"</string>
     <string name="expires_on" msgid="8061200430557020704">"Λήγει:"</string>
-    <string name="retrieving_creds_dlg_msg" msgid="9207671133094039879">"Ανάκτηση λεπτομερειών σύνδεσης..."</string>
     <string name="stopping" msgid="4839698519340302982">"Διακοπή..."</string>
     <string name="stop" msgid="5687251076030630074">"Διακοπή"</string>
     <string name="reload" msgid="8585220783228408062">"Ανανέωση"</string>
@@ -82,8 +83,8 @@
     <string name="homepage_set" msgid="8768087280310966395">"Ορισμός αρχικής σελίδας."</string>
     <string name="bookmark_needs_title" msgid="6245900436119218187">"Ο σελιδοδείκτης πρέπει να έχει ένα όνομα."</string>
     <string name="bookmark_needs_url" msgid="7809876865972755158">"Ο σελιδοδείκτης πρέπει να έχει μια τοποθεσία."</string>
-    <string name="empty_bookmark" msgid="7008697085928540511">"Δεν είναι δυνατή η δημιουργία κενού σελιδοδείκτη."</string>
     <string name="bookmark_url_not_valid" msgid="6719785633980202419">"Μη έγκυρη διεύθυνση URL."</string>
+    <string name="bookmark_cannot_save_url" msgid="791722768778386941">"Η διεύθυνση URL δεν ήταν δυνατό να προστεθεί στους σελιδοδείκτες."</string>
     <string name="delete_bookmark" msgid="2422989994934201992">"Διαγραφή"</string>
     <string name="bookmark_page" msgid="6845189305130307274">"Προσθήκη της τελευταίας σελίδας που προβλήθηκε στους σελιδοδείκτες"</string>
     <string name="switch_to_thumbnails" msgid="5493351529609043151">"Προβολή μικρογραφίας"</string>
@@ -91,18 +92,11 @@
     <string name="current_page" msgid="7510129573681663135">"από "</string>
     <string name="delete_bookmark_warning" msgid="758043186202032205">"Ο σελιδοδείκτης \"<xliff:g id="BOOKMARK">%s</xliff:g>\" θα διαγραφεί."</string>
     <string name="open_in_new_window" msgid="6596775546468054510">"Άνοιγμα σε νέο παράθυρο"</string>
-    <string name="new_window" msgid="8117889615360211551">"Νέο παράθυρο"</string>
     <string name="goto_dot" msgid="3895839050522602723">"Μετάβαση"</string>
     <string name="find_dot" msgid="6259312434696611957">"Εύρεση στη σελίδα"</string>
     <string name="select_dot" msgid="6299170761900561967">"Επιλογή κειμένου"</string>
-    <string name="view_tabs" msgid="1119097492003550564">"Προεπισκόπηση παραθύρου"</string>
-    <string name="view_tabs_condensed" msgid="5803955493821945369">"Παράθυρα"</string>
     <string name="tab_picker_title" msgid="864478399057782913">"Τρέχοντα παράθυρα"</string>
-    <string name="tab_picker_view_tab" msgid="2984342364915347656">"Προβολή"</string>
-    <string name="tab_picker_new_tab" msgid="3080280018986866528">"Νέο παράθυρο"</string>
     <string name="tab_picker_remove_tab" msgid="630087809802479397">"Κλείσιμο"</string>
-    <string name="tab_picker_bookmark" msgid="1084409404198995477">"Σελιδοδείκτης"</string>
-    <string name="tab_picker_send_url" msgid="9102803487525950021">"Κοινή χρήση συνδέσμου"</string>
     <string name="bookmarks" msgid="1961279134885867815">"Σελιδοδείκτες"</string>
     <string name="shortcut_bookmark" msgid="3974876480401135895">"Σελιδοδείκτης"</string>
     <string name="history" msgid="2451240511251410032">"Ιστορικό"</string>
@@ -118,6 +112,7 @@
     <string name="contextmenu_copylink" msgid="5153657160294534270">"Αντιγραφή συνδέσμου διεύθυνσης URL"</string>
     <string name="contextmenu_download_image" msgid="4243829645180686912">"Αποθήκευση εικόνας"</string>
     <string name="contextmenu_view_image" msgid="3870625602053600905">"Προβολή εικόνας"</string>
+    <string name="contextmenu_set_wallpaper" msgid="3691902960115350686">"Ορισμός ως ταπετσαρία"</string>
     <string name="contextmenu_dial_dot" msgid="5856550683415933806">"Κλήση..."</string>
     <string name="contextmenu_add_contact" msgid="3183511922223645716">"Προσθήκη επαφής"</string>
     <string name="contextmenu_send_mail" msgid="1014513374828775660">"Αποστολή μηνύματος ηλεκτρονικού ταχυδρομείου"</string>
@@ -134,8 +129,14 @@
     <string name="pref_content_javascript" msgid="4570972030299516843">"Ενεργοποίηση JavaScript"</string>
     <string name="pref_content_open_in_background" msgid="824123779725118663">"Άνοιγμα στο παρασκήνιο"</string>
     <string name="pref_content_plugins" msgid="7231944644794301582">"Ενεργοποίηση πρόσθετων"</string>
+  <string-array name="pref_content_plugins_choices">
+    <item msgid="6745108155096660725">"Πάντα ενεργοποιημένο"</item>
+    <item msgid="2484126708670016519">"Κατά απαίτηση"</item>
+    <item msgid="8547442717307793863">"Απενεργοποιημένο"</item>
+  </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"Άνοιγμα νέων παραθύρων πίσω από το τρέχον"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"Ορισμός ως αρχική σελίδα"</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>
     <string name="pref_content_landscape_only" msgid="2022546812766219672">"Προβολή μόνο σε τοπίο"</string>
@@ -190,24 +191,23 @@
     <string name="pref_content_load_page_summary" msgid="8792093504054149369">"Εμφάνιση επισκόπισης σελίδων που ανοίξατε πρόσφατα"</string>
     <string name="pref_extras_title" msgid="3091250467679722382">"Σύνθετες ρυθμίσεις"</string>
     <string name="pref_extras_website_settings" msgid="67866640052455549">"Ρυθμίσεις ιστότοπου"</string>
-    <string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Προβολή σύνθετων ρυθμίσεων για μεμονωμένους ιστότοπους"</string>
+    <string name="pref_extras_website_settings_summary" msgid="1656771443223494406">"Σύνθετες ρυθμίσεις για μεμονωμένους ιστότοπους"</string>
     <string name="pref_extras_reset_default" msgid="8904000515846202110">"Επαναφορά προεπιλογών"</string>
-    <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Εκκαθ.όλων των δεδ.του προγρ.περιήγ.και επαναφ.όλων των ρυθμ.στις προεπ.ρυθμ."</string>
-    <string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"Θα γίνει διαγραφή όλων των δεδομένων του προγράμματος περιήγησης και επαναφορά των ρυθμίσεων στις προεπιλεγμένες τιμές."</string>
+    <string name="pref_extras_reset_default_summary" msgid="4247870778270414501">"Επαναφορά προεπιλεγμένων ρυθμίσεων"</string>
+    <string name="pref_extras_reset_default_dlg" msgid="6640261575874704022">"Θα γίνει επαναφορά των ρυθμίσεων στις προεπιλεγμένες τιμές."</string>
     <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Επαναφορά προεπιλογών"</string>
     <string name="pref_development_title" msgid="3263854204533056480">"Εντοπισμός σφαλμάτων"</string>
     <string name="pref_default_text_encoding" msgid="5742965543955558478">"Κωδικοποίηση κειμένου"</string>
   <string-array name="pref_default_text_encoding_choices">
     <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
     <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
-    <item msgid="7143715548814380950">"Ιαπωνικά (ISO-2022-JP)"</item>
-    <item msgid="5111312120564516587">"Ιαπωνικά (SHIFT_JIS)"</item>
-    <item msgid="6545734186479713946">"Ιαπωνικά (EUC-JP)"</item>
+    <item msgid="6122474363777211732">"Κινεζικά (GBK)"</item>
+    <item msgid="373372275931607040">"Κινεζικά (Big5)"</item>
+    <item msgid="891615911084608570">"Ιαπωνικά (ISO-2022-JP)"</item>
+    <item msgid="5589150448475151241">"Ιαπωνικά (SHIFT_JIS)"</item>
+    <item msgid="7356792686950371843">"Ιαπωνικά (EUC-JP)"</item>
   </string-array>
     <string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Κωδικοποίηση κειμένου"</string>
-    <string name="pref_default_text_encoding_default" msgid="5272126711231936722">"Latin-1"</string>
-    <string name="browserFrameRedirect" msgid="7049675479777828343">"Ανακατεύθυνση"</string>
-    <string name="browserFrame307Post" msgid="1429094844669510768">"Γίνεται ανακατεύθυνση αυτής της ιστοσελίδας. Να αποσταλούν ξανά τα δεδομένα φόρμας που έχετε εισάγει, στην νέα τοποθεσία;"</string>
     <string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Πρόβλημα σύνδεσης δεδομένων"</string>
     <string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Υπάρχει πρόβλημα με το αρχείο"</string>
     <string name="browserFrameFormResubmitLabel" msgid="2685923472682180360">"Επιβεβαίωση"</string>
@@ -234,13 +234,12 @@
     <string name="download_unknown_filename" msgid="4013465542563652175">"&lt;Άγνωστο&gt;"</string>
     <string name="download_menu_open" msgid="4888327480367757513">"Άνοιγμα"</string>
     <string name="download_menu_clear" msgid="6264454531553418124">"Εκκαθάριση από τη λίστα"</string>
+    <string name="download_menu_delete" msgid="8815502136393894148">"Διαγραφή"</string>
     <string name="download_menu_cancel" msgid="2545333007601851574">"Ακύρωση λήψης"</string>
     <string name="download_menu_cancel_all" msgid="2136550823151999166">"Ακύρωση όλων των λήψεων"</string>
-    <string name="download_menu_clear_all" msgid="7423737413377703862">"Εκκαθάριση λίστας"</string>
-    <string name="download_clear_dlg_title" msgid="7961996329529777390">"Εκκαθάριση"</string>
-    <string name="download_clear_dlg_msg" msgid="8056013815679757669">"Θα γίνει εκκαθάριση όλων των στοιχείων από τη λίστα και κατάργηση από την προσωρινή μνήμη του προγράμματος περιήγησης."</string>
     <string name="download_cancel_dlg_title" msgid="8909108500262799748">"Ακύρωση λήψεων"</string>
     <string name="download_cancel_dlg_msg" msgid="6285389170052357797">"Οι <xliff:g id="DOWNLOAD_COUNT">%d</xliff:g> λήψεις θα ακυρωθούν και θα γίνει εκκαθάρισή τους από το ιστορικό λήψεων."</string>
+    <string name="download_delete_file" msgid="5330036497843073249">"Το αρχείο θα διαγραφεί"</string>
     <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>
@@ -248,7 +247,7 @@
     <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>
-    <string name="download_no_application" msgid="5054596425887523234">"Δεν βρέθηκε εφαρμογή για το άνοιγμα αυτού του αρχείου."</string>
+    <string name="download_no_application_title" msgid="1286056729168874295">"Δεν είναι δυνατό το άνοιγμα του αρχείου"</string>
     <string name="retry" msgid="1835923075542266721">"Επανάληψη"</string>
     <string name="no_downloads" msgid="3947445710685021498">"Το ιστορικό λήψεων του προγράμματος περιήγησης είναι κενό."</string>
     <string name="download_error" msgid="413496839831257187">"Ανεπιτυχής λήψη."</string>
@@ -262,12 +261,10 @@
     <string name="download_file_error" msgid="1206648050615176113">"Δεν είναι δυνατή η ολοκλήρωση της λήψης. Δεν υπάρχει αρκετός διαθέσιμος χώρος."</string>
     <string name="download_length_required" msgid="9038605488460437406">"Δεν είναι δυνατή η λήψη. Δεν είναι δυνατός ο προσδιορισμός του μεγέθους του στοιχείου."</string>
     <string name="download_precondition_failed" msgid="8327584102874295580">"Η λήψη διακόπηκε. Δεν είναι δυνατή η συνέχισή της."</string>
-    <string name="activity_instrumentation_test_runner" msgid="8215091309334005029">"Πρόγραμμα εκτέλεσης δοκιμών προγράμματος περιήγησης"</string>
     <string name="search_the_web" msgid="6046130189241962337">"Αναζήτηση στον ιστό"</string>
     <string name="webstorage_outofspace_notification_title" msgid="1160474608059771788">"Χώρος αποθήκευσης προγράμματος περιήγησης πλήρης"</string>
     <string name="webstorage_outofspace_notification_text" msgid="7341075135051829692">"Κάντε κλικ για να αποδεσμεύσετε χώρο."</string>
     <string name="webstorage_clear_data_title" msgid="689484577124333977">"Εκκαθάριση αποθηκευμένων δεδομένων"</string>
-    <string name="webstorage_clear_data_summary" msgid="3523128713743907805">"Κατάργηση όλων των βάσεων δεδομένων που σχετίζονται με αυτόν τον ιστότοπο"</string>
     <string name="webstorage_clear_data_dialog_title" msgid="345457466368974706">"Εκκαθάριση αποθηκευμένων δεδομένων"</string>
     <string name="webstorage_clear_data_dialog_message" msgid="6678281256970470125">"Όλα τα δεδομένα που αποθηκεύτηκαν από αυτόν τον ιστότοπο θα διαγραφούν"</string>
     <string name="webstorage_clear_data_dialog_ok_button" msgid="2516563534211898636">"Εκκαθάριση όλων"</string>
@@ -278,6 +275,8 @@
     <string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Κοινή χρήση τοποθεσίας"</string>
     <string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Απόρριψη"</string>
     <string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Διατήρηση προτίμησης"</string>
+    <string name="geolocation_permissions_prompt_toast_allowed" msgid="987286072035125498">"Αυτός ο ιστότοπος μπορεί να αποκτήσει πρόσβαση στην τοποθεσία σας. Αλλάξτε αυτήν τη ρύθμιση στο μενού: Ρυθμίσεις και ρυθμίσεις ιστότοπου"</string>
+    <string name="geolocation_permissions_prompt_toast_disallowed" msgid="7695100950212692515">"Αυτός ο ιστότοπος δεν μπορεί να αποκτήσει πρόσβαση στην τοποθεσία σας. Αλλάξτε αυτήν τη ρύθμιση στο μενού: Ρυθμίσεις και ρυθμίσεις ιστότοπου"</string>
     <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Εκκαθάριση πρόσβασης τοποθεσίας"</string>
     <string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Αυτήν τη στιγμή, αυτός ο ιστότοπος έχει πρόσβαση στην τοποθεσία σας"</string>
     <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Δεν είναι δυνατή η πρόσβαση στην τοποθεσία σας από αυτόν τον ιστότοπο"</string>
@@ -290,5 +289,5 @@
     <string name="website_settings_clear_all_dialog_message" msgid="6150502090601476333">"Θα γίνει διαγραφή όλων των δεδομένων ιστοτόπων και αδειών τοποθεσιών."</string>
     <string name="website_settings_clear_all_dialog_ok_button" msgid="6401582240627669431">"Διαγραφή όλων των δεδομένων"</string>
     <string name="website_settings_clear_all_dialog_cancel_button" msgid="1896757051856611674">"Ακύρωση"</string>
-    <string name="zoom_overview_button_text" msgid="4146579940085488881">"Επισκόπηση"</string>
+    <string name="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Ρύθμιση ταπετσαρίας..."</string>
 </resources>
diff --git a/res/values-es-rUS/arrays.xml b/res/values-es-rUS/arrays.xml
deleted file mode 100644
index a622228..0000000
--- a/res/values-es-rUS/arrays.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="webstorage_quota_entries">
-    <item msgid="5433313236875537673">"Cuota no permitida"</item>
-    <item msgid="7374272188672967690">"5 MB"</item>
-    <item msgid="8699352701856136738">"10 MB"</item>
-    <item msgid="2018822431469084862">"30 MB"</item>
-    <item msgid="5383642976774534074">"100 MB"</item>
-  </string-array>
-  <string-array name="webstorage_quota_entries_values">
-    <item msgid="7620410313725236055">"0"</item>
-    <item msgid="4302688814760304206">"5"</item>
-    <item msgid="7291990205847586165">"10"</item>
-    <item msgid="916913372287112423">"30"</item>
-    <item msgid="3437188301324229987">"100"</item>
-  </string-array>
-</resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 1b1f6e2..d69b315 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -1,21 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--  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.
--->
+ -->
+
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="1935869255545976415">"Navegador"</string>
+    <string name="choose_upload" msgid="3649366287575002063">"Elegir el archivo para cargar"</string>
     <string name="new_tab" msgid="4505722538297295141">"Ventana nueva"</string>
     <string name="active_tabs" msgid="3050623868203544623">"Windows"</string>
     <string name="tab_bookmarks" msgid="2305793036003473653">"Marcadores"</string>
@@ -58,7 +60,6 @@
     <string name="validity_period" msgid="57988851973181309">"Validez:"</string>
     <string name="issued_on" msgid="2082890654801808368">"Enviado el:"</string>
     <string name="expires_on" msgid="8061200430557020704">"Expira el:"</string>
-    <string name="retrieving_creds_dlg_msg" msgid="9207671133094039879">"Recuperando detalles de inicio de sesión..."</string>
     <string name="stopping" msgid="4839698519340302982">"Deteniendo..."</string>
     <string name="stop" msgid="5687251076030630074">"Detener"</string>
     <string name="reload" msgid="8585220783228408062">"Actualizar"</string>
@@ -82,8 +83,8 @@
     <string name="homepage_set" msgid="8768087280310966395">"Configuración de página principal."</string>
     <string name="bookmark_needs_title" msgid="6245900436119218187">"El marcador debe tener un nombre."</string>
     <string name="bookmark_needs_url" msgid="7809876865972755158">"El marcador debe tener una ubicación."</string>
-    <string name="empty_bookmark" msgid="7008697085928540511">"No es posible crear un marcador vacío."</string>
     <string name="bookmark_url_not_valid" msgid="6719785633980202419">"La URL no es válida."</string>
+    <string name="bookmark_cannot_save_url" msgid="791722768778386941">"No se puede agregar esta URL a los marcadores."</string>
     <string name="delete_bookmark" msgid="2422989994934201992">"Eliminar"</string>
     <string name="bookmark_page" msgid="6845189305130307274">"Última página vista del marcador"</string>
     <string name="switch_to_thumbnails" msgid="5493351529609043151">"Vista en miniatura"</string>
@@ -91,18 +92,11 @@
     <string name="current_page" msgid="7510129573681663135">"de "</string>
     <string name="delete_bookmark_warning" msgid="758043186202032205">"El marcador \"<xliff:g id="BOOKMARK">%s</xliff:g>\" se eliminará."</string>
     <string name="open_in_new_window" msgid="6596775546468054510">"Abrir en una ventana nueva"</string>
-    <string name="new_window" msgid="8117889615360211551">"Ventana nueva"</string>
     <string name="goto_dot" msgid="3895839050522602723">"Ir"</string>
     <string name="find_dot" msgid="6259312434696611957">"Buscar en la página"</string>
     <string name="select_dot" msgid="6299170761900561967">"Seleccionar texto"</string>
-    <string name="view_tabs" msgid="1119097492003550564">"Descripción general de la ventana"</string>
-    <string name="view_tabs_condensed" msgid="5803955493821945369">"Windows"</string>
     <string name="tab_picker_title" msgid="864478399057782913">"Ventana actual"</string>
-    <string name="tab_picker_view_tab" msgid="2984342364915347656">"Ver"</string>
-    <string name="tab_picker_new_tab" msgid="3080280018986866528">"Ventana nueva"</string>
     <string name="tab_picker_remove_tab" msgid="630087809802479397">"Cerrar"</string>
-    <string name="tab_picker_bookmark" msgid="1084409404198995477">"Marcador"</string>
-    <string name="tab_picker_send_url" msgid="9102803487525950021">"Compartir enlace"</string>
     <string name="bookmarks" msgid="1961279134885867815">"Marcadores"</string>
     <string name="shortcut_bookmark" msgid="3974876480401135895">"Marcador"</string>
     <string name="history" msgid="2451240511251410032">"Historial"</string>
@@ -113,20 +107,21 @@
     <string name="contextmenu_openlink_newwindow" msgid="992765050093960353">"Abrir en una ventana nueva"</string>
     <string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"Enlace del marcador"</string>
     <string name="contextmenu_savelink" msgid="5508554930832538184">"Guardar enlace"</string>
-    <string name="contextmenu_sharelink" msgid="5392275392280130331">"Compartir enlace"</string>
+    <string name="contextmenu_sharelink" msgid="5392275392280130331">"Compartir vínculo"</string>
     <string name="contextmenu_copy" msgid="398860586635404030">"Copiar"</string>
     <string name="contextmenu_copylink" msgid="5153657160294534270">"Copiar URL de vínculo"</string>
     <string name="contextmenu_download_image" msgid="4243829645180686912">"Guardar imagen"</string>
     <string name="contextmenu_view_image" msgid="3870625602053600905">"Ver imagen"</string>
-    <string name="contextmenu_dial_dot" msgid="5856550683415933806">"Discar..."</string>
+    <string name="contextmenu_set_wallpaper" msgid="3691902960115350686">"Establecer como fondo de pantalla"</string>
+    <string name="contextmenu_dial_dot" msgid="5856550683415933806">"Marcar…"</string>
     <string name="contextmenu_add_contact" msgid="3183511922223645716">"Agregar contacto"</string>
     <string name="contextmenu_send_mail" msgid="1014513374828775660">"Enviar correo electrónico"</string>
     <string name="contextmenu_map" msgid="7471390435434034912">"Situar en el mapa"</string>
     <string name="choosertitle_sharevia" msgid="4600490613341909086">"Compartir mediante"</string>
     <string name="clear" msgid="7070043081700011461">"Borrar"</string>
-    <string name="replace" msgid="4843033491070384047">"Reemplazar"</string>
+    <string name="replace" msgid="4843033491070384047">"Sustituir"</string>
     <string name="browser_bookmarks_page_bookmarks_text" msgid="6787605028726162673">"Marcadores"</string>
-    <string name="menu_preferences" msgid="6709237687234102240">"Configurac."</string>
+    <string name="menu_preferences" msgid="6709237687234102240">"Config."</string>
     <string name="pref_content_title" msgid="722227111894838633">"Configuración del contenido de la página"</string>
     <string name="pref_content_load_images" msgid="2125616852957377561">"Cargar imágenes"</string>
     <string name="pref_content_load_images_summary" msgid="5055874125248398584">"Visualizar imágenes en páginas web"</string>
@@ -134,14 +129,20 @@
     <string name="pref_content_javascript" msgid="4570972030299516843">"Habilitar JavaScript"</string>
     <string name="pref_content_open_in_background" msgid="824123779725118663">"Abrir en modo subord."</string>
     <string name="pref_content_plugins" msgid="7231944644794301582">"Activar complementos"</string>
+  <string-array name="pref_content_plugins_choices">
+    <item msgid="6745108155096660725">"Siempre en"</item>
+    <item msgid="2484126708670016519">"A pedido"</item>
+    <item msgid="8547442717307793863">"Apagado"</item>
+  </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_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>
     <string name="pref_content_landscape_only" msgid="2022546812766219672">"Visualización horizontal solamente"</string>
     <string name="pref_content_landscape_only_summary" msgid="1008238895535428855">"Mostrar páginas sólo en la orientación de pantalla horizontal más ancha"</string>
     <string name="pref_privacy_title" msgid="1052470980370846151">"Configuración de privacidad"</string>
-    <string name="pref_privacy_clear_cache" msgid="3380316479925886998">"Borrar caché"</string>
+    <string name="pref_privacy_clear_cache" msgid="3380316479925886998">"Borrar memoria caché"</string>
     <string name="pref_privacy_clear_cache_summary" msgid="2216463577207991454">"Borrar el contenido y las bases de datos de la memoria caché local"</string>
     <string name="pref_privacy_clear_cache_dlg" msgid="5541011591300753881">"Se suprimirá el contenido y las bases de datos de la memoria caché local."</string>
     <string name="pref_privacy_clear_cookies" msgid="3095583579133780331">"Borrar datos de cookies"</string>
@@ -182,7 +183,7 @@
     <string name="pref_default_zoom" msgid="8076142259097187395">"Predeterminar zoom"</string>
   <string-array name="pref_default_zoom_choices">
     <item msgid="549583171195154919">"Lejos"</item>
-    <item msgid="5619034257768161024">"Mediano"</item>
+    <item msgid="5619034257768161024">"Medio"</item>
     <item msgid="3840999588443167001">"Cerrar"</item>
   </string-array>
     <string name="pref_default_zoom_dialogtitle" msgid="6095974367125109021">"Predeterminar zoom"</string>
@@ -190,24 +191,23 @@
     <string name="pref_content_load_page_summary" msgid="8792093504054149369">"Mostrar la descripción general de las páginas nuevas abiertas"</string>
     <string name="pref_extras_title" msgid="3091250467679722382">"Configuración avanzada"</string>
     <string name="pref_extras_website_settings" msgid="67866640052455549">"Configuración del sitio web"</string>
-    <string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Ver configuración avanzada para sitios web individuales"</string>
+    <string name="pref_extras_website_settings_summary" msgid="1656771443223494406">"Configuración avanzada para sitios web individuales"</string>
     <string name="pref_extras_reset_default" msgid="8904000515846202110">"Restabl. a valores predet."</string>
-    <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Borrar todos los datos del navegador y restablecer la configuración a los valores predeterminados"</string>
-    <string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"Se suprimirán todos los datos del navegador y la configuración volverá a los valores predeterminados."</string>
-    <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Restablecer a los valores predeterminados"</string>
+    <string name="pref_extras_reset_default_summary" msgid="4247870778270414501">"Restaurar configuración predeterminada"</string>
+    <string name="pref_extras_reset_default_dlg" msgid="6640261575874704022">"La configuración volverá a los valores predeterminados."</string>
+    <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Restabl. a valores predet."</string>
     <string name="pref_development_title" msgid="3263854204533056480">"Depurar"</string>
     <string name="pref_default_text_encoding" msgid="5742965543955558478">"Codificación de texto"</string>
   <string-array name="pref_default_text_encoding_choices">
     <item msgid="7275223955790513818">"Latino-1 (ISO-8859-1)"</item>
     <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
-    <item msgid="7143715548814380950">"Japonés (ISO-2022-JP)"</item>
-    <item msgid="5111312120564516587">"Japonés (SHIFT_JIS)"</item>
-    <item msgid="6545734186479713946">"Japonés (EUC-JP)"</item>
+    <item msgid="6122474363777211732">"Chino (GBK)"</item>
+    <item msgid="373372275931607040">"Chino (Big5)"</item>
+    <item msgid="891615911084608570">"Japonés (ISO-2022-JP)"</item>
+    <item msgid="5589150448475151241">"Japonés (SHIFT_JIS)"</item>
+    <item msgid="7356792686950371843">"Japonés (EUC-JP)"</item>
   </string-array>
     <string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Codificación de texto"</string>
-    <string name="pref_default_text_encoding_default" msgid="5272126711231936722">"Latino-1"</string>
-    <string name="browserFrameRedirect" msgid="7049675479777828343">"Redireccionamiento"</string>
-    <string name="browserFrame307Post" msgid="1429094844669510768">"Esta página web está siendo redireccionada. ¿Deseas reenviar los datos que ingresaste en tu formulario a la ubicación nueva?"</string>
     <string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Problema de conectividad de datos"</string>
     <string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Problema con el archivo"</string>
     <string name="browserFrameFormResubmitLabel" msgid="2685923472682180360">"Confirmar"</string>
@@ -217,7 +217,7 @@
     <string name="clear_history" msgid="5998307092715979619">"Borrar historial"</string>
     <string name="browser_history" msgid="1038987118290272525">"Páginas visitadas recientemente"</string>
     <string name="empty_history" msgid="8738772352308207274">"El historial del navegador está vacío."</string>
-    <string name="add_new_bookmark" msgid="8086367791400349049">"Agregar marcador..."</string>
+    <string name="add_new_bookmark" msgid="8086367791400349049">"Agregar marcador…"</string>
     <string name="add_bookmark_short" msgid="3783984330998103735">"Agregar"</string>
     <string name="search_hint" msgid="4647356319916631820">"Buscar o escribir URL"</string>
     <string name="search_button_text" msgid="5235226933877634410">"Ir"</string>
@@ -234,27 +234,26 @@
     <string name="download_unknown_filename" msgid="4013465542563652175">"&lt;Desconocido&gt;"</string>
     <string name="download_menu_open" msgid="4888327480367757513">"Abrir"</string>
     <string name="download_menu_clear" msgid="6264454531553418124">"Borrar de la lista"</string>
+    <string name="download_menu_delete" msgid="8815502136393894148">"Eliminar"</string>
     <string name="download_menu_cancel" msgid="2545333007601851574">"Cancelar descarga"</string>
     <string name="download_menu_cancel_all" msgid="2136550823151999166">"Cancelar todas las descargas"</string>
-    <string name="download_menu_clear_all" msgid="7423737413377703862">"Borrar lista"</string>
-    <string name="download_clear_dlg_title" msgid="7961996329529777390">"Borrar"</string>
-    <string name="download_clear_dlg_msg" msgid="8056013815679757669">"Todos los elementos se borrarán de la lista y se suprimirán del caché del navegador."</string>
     <string name="download_cancel_dlg_title" msgid="8909108500262799748">"Cancelar descargas"</string>
     <string name="download_cancel_dlg_msg" msgid="6285389170052357797">"Las <xliff:g id="DOWNLOAD_COUNT">%d</xliff:g> descargas se cancelarán y se borrarán del historial de descarga."</string>
-    <string name="download_file_error_dlg_title" msgid="2693630283595384874">"No hay espacio suficiente"</string>
+    <string name="download_delete_file" msgid="5330036497843073249">"El archivo se eliminará"</string>
+    <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">"Descarga incorrecta"</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>
-    <string name="download_no_application" msgid="5054596425887523234">"No se encuentra una aplicación para abrir este archivo."</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>
     <string name="download_error" msgid="413496839831257187">"Descarga incorrecta."</string>
     <string name="download_success" msgid="2279041638155595203">"<xliff:g id="FILE">%s</xliff:g> Descarga completa."</string>
-    <string name="download_running" msgid="2622942231322015059">"Descargando..."</string>
-    <string name="download_pending" msgid="2599683668575349559">"Iniciando la descarga..."</string>
+    <string name="download_running" msgid="2622942231322015059">"Descargando…"</string>
+    <string name="download_pending" msgid="2599683668575349559">"Iniciando descarga..."</string>
     <string name="download_pending_network" msgid="6548714525679461053">"Esperando la conexión de datos..."</string>
     <string name="download_running_paused" msgid="6418029352085656495">"Esperando la conexión de datos..."</string>
     <string name="download_canceled" msgid="6057083743144492515">"Descarga cancelada."</string>
@@ -262,12 +261,10 @@
     <string name="download_file_error" msgid="1206648050615176113">"No es posible terminar la descarga. No hay espacio suficiente."</string>
     <string name="download_length_required" msgid="9038605488460437406">"No es posible realizar la descarga. No puede determinarse el tamaño del elemento."</string>
     <string name="download_precondition_failed" msgid="8327584102874295580">"Descarga interrumpida. No se puede retomar."</string>
-    <string name="activity_instrumentation_test_runner" msgid="8215091309334005029">"Ejecutor de pruebas del navegador"</string>
     <string name="search_the_web" msgid="6046130189241962337">"Buscar en Internet"</string>
     <string name="webstorage_outofspace_notification_title" msgid="1160474608059771788">"Almacenamiento del navegador lleno"</string>
     <string name="webstorage_outofspace_notification_text" msgid="7341075135051829692">"Hacer clic para liberar espacio"</string>
     <string name="webstorage_clear_data_title" msgid="689484577124333977">"Borrar datos almacenados"</string>
-    <string name="webstorage_clear_data_summary" msgid="3523128713743907805">"Eliminar todas las bases de datos asociadas con este sitio web"</string>
     <string name="webstorage_clear_data_dialog_title" msgid="345457466368974706">"Borrar datos almacenados"</string>
     <string name="webstorage_clear_data_dialog_message" msgid="6678281256970470125">"Todos los datos almacenados por este sitio web serán suprimidos"</string>
     <string name="webstorage_clear_data_dialog_ok_button" msgid="2516563534211898636">"Eliminar todos"</string>
@@ -278,6 +275,8 @@
     <string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Compartir ubicación"</string>
     <string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Rechazar"</string>
     <string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Recordar la preferencia"</string>
+    <string name="geolocation_permissions_prompt_toast_allowed" msgid="987286072035125498">"Este sitio puede acceder a tu ubicación. Cambia esta configuración en: Configuración -&gt; Configuración de sitios web."</string>
+    <string name="geolocation_permissions_prompt_toast_disallowed" msgid="7695100950212692515">"Este sitio no puede acceder a tu ubicación. Cambia esta configuración en: Configuración -&gt; Configuración de sitios web."</string>
     <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Borrar acceso a la ubicación"</string>
     <string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Este sitio puede acceder a tu ubicación actualmente"</string>
     <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Este sitio no puede acceder a tu ubicación actualmente"</string>
@@ -288,7 +287,7 @@
     <string name="website_settings_clear_all" msgid="8739804325997655980">"Eliminar todos"</string>
     <string name="website_settings_clear_all_dialog_title" msgid="7791826325122461718">"¿Deseas eliminar toda la configuración del sitio web?"</string>
     <string name="website_settings_clear_all_dialog_message" msgid="6150502090601476333">"Se suprimirán todos los datos del sitio web y los permisos de ubicación."</string>
-    <string name="website_settings_clear_all_dialog_ok_button" msgid="6401582240627669431">"Suprimir todos los datos"</string>
+    <string name="website_settings_clear_all_dialog_ok_button" msgid="6401582240627669431">"Eliminar todos los datos"</string>
     <string name="website_settings_clear_all_dialog_cancel_button" msgid="1896757051856611674">"Cancelar"</string>
-    <string name="zoom_overview_button_text" msgid="4146579940085488881">"Descripción general"</string>
+    <string name="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Estableciendo fondo de pantalla..."</string>
 </resources>
diff --git a/res/values-es/arrays.xml b/res/values-es/arrays.xml
deleted file mode 100644
index 074f300..0000000
--- a/res/values-es/arrays.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="webstorage_quota_entries">
-    <item msgid="5433313236875537673">"Ninguna cuota permitida"</item>
-    <item msgid="7374272188672967690">"5 MB"</item>
-    <item msgid="8699352701856136738">"10 MB"</item>
-    <item msgid="2018822431469084862">"30 MB"</item>
-    <item msgid="5383642976774534074">"100 MB"</item>
-  </string-array>
-  <string-array name="webstorage_quota_entries_values">
-    <item msgid="7620410313725236055">"0"</item>
-    <item msgid="4302688814760304206">"5"</item>
-    <item msgid="7291990205847586165">"10"</item>
-    <item msgid="916913372287112423">"30"</item>
-    <item msgid="3437188301324229987">"100"</item>
-  </string-array>
-</resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index a3cdf33..83baade 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -1,21 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--  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.
--->
+ -->
+
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="1935869255545976415">"Navegador"</string>
+    <string name="choose_upload" msgid="3649366287575002063">"Seleccionar archivo para subir"</string>
     <string name="new_tab" msgid="4505722538297295141">"Nueva ventana"</string>
     <string name="active_tabs" msgid="3050623868203544623">"Ventanas"</string>
     <string name="tab_bookmarks" msgid="2305793036003473653">"Marcadores"</string>
@@ -58,11 +60,10 @@
     <string name="validity_period" msgid="57988851973181309">"Validez:"</string>
     <string name="issued_on" msgid="2082890654801808368">"Fecha de emisión:"</string>
     <string name="expires_on" msgid="8061200430557020704">"Fecha de caducidad:"</string>
-    <string name="retrieving_creds_dlg_msg" msgid="9207671133094039879">"Recuperando detalles de acceso..."</string>
     <string name="stopping" msgid="4839698519340302982">"Deteniendo..."</string>
     <string name="stop" msgid="5687251076030630074">"Detener"</string>
     <string name="reload" msgid="8585220783228408062">"Actualizar"</string>
-    <string name="back" msgid="8414603107175713668">"Anterior"</string>
+    <string name="back" msgid="8414603107175713668">"Atrás"</string>
     <string name="forward" msgid="4288210890526641577">"Siguiente"</string>
     <string name="save" msgid="5922311934992468496">"Aceptar"</string>
     <string name="do_not_save" msgid="6777633870113477714">"Cancelar"</string>
@@ -76,33 +77,26 @@
     <string name="remove_bookmark" msgid="8407495852801410891">"Eliminar marcador"</string>
     <string name="remove_from_bookmarks" msgid="4374080666576982775">"Eliminar de marcadores"</string>
     <string name="remove_history_item" msgid="5021424935726728618">"Elliminar del historial"</string>
-    <string name="set_as_homepage" msgid="4752937379414905560">"Establecer como página de inicio"</string>
+    <string name="set_as_homepage" msgid="4752937379414905560">"Establecer como página principal"</string>
     <string name="bookmark_saved" msgid="2766434679871317557">"Guardar en marcadores"</string>
     <string name="bookmark_not_saved" msgid="700600955089376724">"No se ha podido guardar el marcador."</string>
     <string name="homepage_set" msgid="8768087280310966395">"Página principal establecida"</string>
     <string name="bookmark_needs_title" msgid="6245900436119218187">"El marcador debe tener un nombre."</string>
     <string name="bookmark_needs_url" msgid="7809876865972755158">"El marcador debe tener una ubicación."</string>
-    <string name="empty_bookmark" msgid="7008697085928540511">"No se puede crear un marcador vacío."</string>
     <string name="bookmark_url_not_valid" msgid="6719785633980202419">"La URL no es válida."</string>
-    <string name="delete_bookmark" msgid="2422989994934201992">"Suprimir"</string>
+    <string name="bookmark_cannot_save_url" msgid="791722768778386941">"Esta URL no se puede añadir a marcadores."</string>
+    <string name="delete_bookmark" msgid="2422989994934201992">"Eliminar"</string>
     <string name="bookmark_page" msgid="6845189305130307274">"Marcar como última página vista"</string>
     <string name="switch_to_thumbnails" msgid="5493351529609043151">"Vista de miniaturas"</string>
     <string name="switch_to_list" msgid="8900531247982121055">"Vista de lista"</string>
     <string name="current_page" msgid="7510129573681663135">"de "</string>
     <string name="delete_bookmark_warning" msgid="758043186202032205">"Se eliminará el marcador \"<xliff:g id="BOOKMARK">%s</xliff:g>\"."</string>
     <string name="open_in_new_window" msgid="6596775546468054510">"Abrir en ventana nueva"</string>
-    <string name="new_window" msgid="8117889615360211551">"Nueva ventana"</string>
     <string name="goto_dot" msgid="3895839050522602723">"Ir"</string>
     <string name="find_dot" msgid="6259312434696611957">"Buscar en la página"</string>
     <string name="select_dot" msgid="6299170761900561967">"Seleccionar texto"</string>
-    <string name="view_tabs" msgid="1119097492003550564">"Visión general de ventanas"</string>
-    <string name="view_tabs_condensed" msgid="5803955493821945369">"Ventanas"</string>
     <string name="tab_picker_title" msgid="864478399057782913">"Ventanas actuales"</string>
-    <string name="tab_picker_view_tab" msgid="2984342364915347656">"Ver"</string>
-    <string name="tab_picker_new_tab" msgid="3080280018986866528">"Nueva ventana"</string>
     <string name="tab_picker_remove_tab" msgid="630087809802479397">"Cerrar"</string>
-    <string name="tab_picker_bookmark" msgid="1084409404198995477">"Marcador"</string>
-    <string name="tab_picker_send_url" msgid="9102803487525950021">"Compartir enlace"</string>
     <string name="bookmarks" msgid="1961279134885867815">"Marcadores"</string>
     <string name="shortcut_bookmark" msgid="3974876480401135895">"Marcador"</string>
     <string name="history" msgid="2451240511251410032">"Historial"</string>
@@ -118,6 +112,7 @@
     <string name="contextmenu_copylink" msgid="5153657160294534270">"Copiar URL de enlace"</string>
     <string name="contextmenu_download_image" msgid="4243829645180686912">"Guardar imagen"</string>
     <string name="contextmenu_view_image" msgid="3870625602053600905">"Ver imagen"</string>
+    <string name="contextmenu_set_wallpaper" msgid="3691902960115350686">"Establecer como fondo de pantalla"</string>
     <string name="contextmenu_dial_dot" msgid="5856550683415933806">"Llamar…"</string>
     <string name="contextmenu_add_contact" msgid="3183511922223645716">"Añadir contacto"</string>
     <string name="contextmenu_send_mail" msgid="1014513374828775660">"Enviar mensaje de correo electrónico"</string>
@@ -127,20 +122,26 @@
     <string name="replace" msgid="4843033491070384047">"Sustituir"</string>
     <string name="browser_bookmarks_page_bookmarks_text" msgid="6787605028726162673">"Marcadores"</string>
     <string name="menu_preferences" msgid="6709237687234102240">"Ajustes"</string>
-    <string name="pref_content_title" msgid="722227111894838633">"Configuración de contenido de la página"</string>
+    <string name="pref_content_title" msgid="722227111894838633">"Ajustes de contenido de la página"</string>
     <string name="pref_content_load_images" msgid="2125616852957377561">"Cargar imágenes"</string>
     <string name="pref_content_load_images_summary" msgid="5055874125248398584">"Mostrar imágenes en páginas web"</string>
-    <string name="pref_content_block_popups" msgid="7808433807197256726">"Bloquear ventanas emergentes"</string>
+    <string name="pref_content_block_popups" msgid="7808433807197256726">"Bloquear pop-ups"</string>
     <string name="pref_content_javascript" msgid="4570972030299516843">"Habilitar JavaScript"</string>
     <string name="pref_content_open_in_background" msgid="824123779725118663">"Abrir en segundo plano"</string>
     <string name="pref_content_plugins" msgid="7231944644794301582">"Habilitar complementos"</string>
+  <string-array name="pref_content_plugins_choices">
+    <item msgid="6745108155096660725">"Siempre activado"</item>
+    <item msgid="2484126708670016519">"A petición"</item>
+    <item msgid="8547442717307793863">"Desactivado"</item>
+  </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">"Página de inicio"</string>
+    <string name="pref_content_homepage" msgid="6082437160778559806">"Página principal"</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>
     <string name="pref_content_landscape_only" msgid="2022546812766219672">"Vista solo horizontal"</string>
     <string name="pref_content_landscape_only_summary" msgid="1008238895535428855">"Mostrar solo las páginas con la orientación de pantalla horizontal"</string>
-    <string name="pref_privacy_title" msgid="1052470980370846151">"Configuración de privacidad"</string>
+    <string name="pref_privacy_title" msgid="1052470980370846151">"Ajustes de privacidad"</string>
     <string name="pref_privacy_clear_cache" msgid="3380316479925886998">"Borrar caché"</string>
     <string name="pref_privacy_clear_cache_summary" msgid="2216463577207991454">"Borrar bases de datos y contenido de la memoria caché local"</string>
     <string name="pref_privacy_clear_cache_dlg" msgid="5541011591300753881">"Las bases de datos y el contenido se eliminarán de la memoria caché local."</string>
@@ -150,7 +151,7 @@
     <string name="pref_privacy_clear_history" msgid="8723795508825198477">"Borrar historial"</string>
     <string name="pref_privacy_clear_history_summary" msgid="6868501330708940734">"Borrar el historial de exploración del navegador"</string>
     <string name="pref_privacy_clear_history_dlg" msgid="544903007914753853">"Se eliminará el historial de exploración del navegador."</string>
-    <string name="pref_privacy_clear_form_data" msgid="4232668196344383987">"Borrar datos de formulario"</string>
+    <string name="pref_privacy_clear_form_data" msgid="4232668196344383987">"Borrar datos formulario"</string>
     <string name="pref_privacy_clear_form_data_summary" msgid="1790390894719517167">"Borrar todos los datos de formulario guardados"</string>
     <string name="pref_privacy_clear_form_data_dlg" msgid="4443621086781197928">"Se eliminarán todos los datos de formulario guardados."</string>
     <string name="pref_privacy_clear_passwords" msgid="4750234112289277480">"Borrar contraseñas"</string>
@@ -161,7 +162,7 @@
     <string name="pref_privacy_clear_geolocation_access" msgid="6649680770030042980">"Permitir acceso a la ubicación"</string>
     <string name="pref_privacy_clear_geolocation_access_summary" msgid="7750143359497314679">"Permitir que todos los sitios web accedan a la ubicación"</string>
     <string name="pref_privacy_clear_geolocation_access_dlg" msgid="7327063124488827244">"Permitir que todos los sitios web accedan a la ubicación"</string>
-    <string name="pref_security_title" msgid="5763978646932160021">"Configuración de seguridad"</string>
+    <string name="pref_security_title" msgid="5763978646932160021">"Ajustes de seguridad"</string>
     <string name="pref_security_remember_passwords" msgid="6492957683454529549">"Recordar contraseñas"</string>
     <string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"Guardar nombres de usuario y contraseñas de sitios web"</string>
     <string name="pref_security_save_form_data" msgid="1213669802810198893">"Recordar formularios"</string>
@@ -186,28 +187,27 @@
     <item msgid="3840999588443167001">"Cerca"</item>
   </string-array>
     <string name="pref_default_zoom_dialogtitle" msgid="6095974367125109021">"Zoom predeterminado"</string>
-    <string name="pref_content_load_page" msgid="2219810141690955452">"Abrir páginas en visión general"</string>
+    <string name="pref_content_load_page" msgid="2219810141690955452">"Abrir en visión general"</string>
     <string name="pref_content_load_page_summary" msgid="8792093504054149369">"Mostrar información general de las páginas abiertas recientemente"</string>
-    <string name="pref_extras_title" msgid="3091250467679722382">"Configuración avanzada"</string>
-    <string name="pref_extras_website_settings" msgid="67866640052455549">"Configuración del sitio web"</string>
-    <string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Ver configuración avanzada de sitios web individuales"</string>
+    <string name="pref_extras_title" msgid="3091250467679722382">"Ajustes avanzados"</string>
+    <string name="pref_extras_website_settings" msgid="67866640052455549">"Ajustes del sitio web"</string>
+    <string name="pref_extras_website_settings_summary" msgid="1656771443223494406">"Ajustes avanzados de sitios web individuales"</string>
     <string name="pref_extras_reset_default" msgid="8904000515846202110">"Restablecer valores predeterminados"</string>
-    <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Borrar todos los datos del navegador y restablecer la configuración predeterminada"</string>
-    <string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"Se eliminarán todos los datos del navegador y se restablecerá la configuración predeterminada."</string>
+    <string name="pref_extras_reset_default_summary" msgid="4247870778270414501">"Restaurar ajustes predeterminados"</string>
+    <string name="pref_extras_reset_default_dlg" msgid="6640261575874704022">"Se restablecerán los ajustes predeterminados."</string>
     <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Restablecer valores predeterminados"</string>
     <string name="pref_development_title" msgid="3263854204533056480">"Depurar"</string>
     <string name="pref_default_text_encoding" msgid="5742965543955558478">"Codificación de texto"</string>
   <string-array name="pref_default_text_encoding_choices">
     <item msgid="7275223955790513818">"Latín-1 (ISO-8859-1)"</item>
     <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
-    <item msgid="7143715548814380950">"Japonés (ISO-2022-JP)"</item>
-    <item msgid="5111312120564516587">"Japonés (SHIFT_JIS)"</item>
-    <item msgid="6545734186479713946">"Japonés (EUC-JP)"</item>
+    <item msgid="6122474363777211732">"Chino (GBK)"</item>
+    <item msgid="373372275931607040">"Chino (Big5)"</item>
+    <item msgid="891615911084608570">"Japonés (ISO-2022-JP)"</item>
+    <item msgid="5589150448475151241">"Japonés (SHIFT_JIS)"</item>
+    <item msgid="7356792686950371843">"Japonés (EUC-JP)"</item>
   </string-array>
     <string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Codificación de texto"</string>
-    <string name="pref_default_text_encoding_default" msgid="5272126711231936722">"Latín-1"</string>
-    <string name="browserFrameRedirect" msgid="7049675479777828343">"Redireccionamiento"</string>
-    <string name="browserFrame307Post" msgid="1429094844669510768">"Esta página web se ha redirigido a otra ubicación. ¿Quieres enviar los datos del formulario cumplimentado a la nueva ubicación?"</string>
     <string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Problema de conectividad de datos"</string>
     <string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Problema con archivo"</string>
     <string name="browserFrameFormResubmitLabel" msgid="2685923472682180360">"OK"</string>
@@ -234,13 +234,12 @@
     <string name="download_unknown_filename" msgid="4013465542563652175">"&lt;Desconocido&gt;"</string>
     <string name="download_menu_open" msgid="4888327480367757513">"Abrir"</string>
     <string name="download_menu_clear" msgid="6264454531553418124">"Borrar de la lista"</string>
+    <string name="download_menu_delete" msgid="8815502136393894148">"Eliminar"</string>
     <string name="download_menu_cancel" msgid="2545333007601851574">"Cancelar descarga"</string>
     <string name="download_menu_cancel_all" msgid="2136550823151999166">"Cancelar todas las descargas"</string>
-    <string name="download_menu_clear_all" msgid="7423737413377703862">"Borrar lista"</string>
-    <string name="download_clear_dlg_title" msgid="7961996329529777390">"Borrar"</string>
-    <string name="download_clear_dlg_msg" msgid="8056013815679757669">"Todos los elementos se borrarán de la lista y se eliminarán de la caché del navegador."</string>
     <string name="download_cancel_dlg_title" msgid="8909108500262799748">"Cancelar descargas"</string>
     <string name="download_cancel_dlg_msg" msgid="6285389170052357797">"Las <xliff:g id="DOWNLOAD_COUNT">%d</xliff:g> descargas se cancelarán y se borrarán del historial de descargas."</string>
+    <string name="download_delete_file" msgid="5330036497843073249">"El archivo se eliminará"</string>
     <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>
@@ -248,7 +247,7 @@
     <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>
-    <string name="download_no_application" msgid="5054596425887523234">"No se ha encontrado ninguna aplicación que permita abrir este archivo."</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>
     <string name="download_error" msgid="413496839831257187">"Descarga incorrecta"</string>
@@ -262,12 +261,10 @@
     <string name="download_file_error" msgid="1206648050615176113">"No se puede completar la descarga porque no hay suficiente espacio."</string>
     <string name="download_length_required" msgid="9038605488460437406">"No se puede realizar la descarga porque no es posible determinar el tamaño del elemento."</string>
     <string name="download_precondition_failed" msgid="8327584102874295580">"La descarga se ha interrumpido y no se puede reanudar."</string>
-    <string name="activity_instrumentation_test_runner" msgid="8215091309334005029">"Realizador de pruebas del navegador"</string>
     <string name="search_the_web" msgid="6046130189241962337">"Buscar en la Web"</string>
     <string name="webstorage_outofspace_notification_title" msgid="1160474608059771788">"Espacio de almacenamiento del navegador agotado"</string>
     <string name="webstorage_outofspace_notification_text" msgid="7341075135051829692">"Haz clic aquí para liberar espacio."</string>
     <string name="webstorage_clear_data_title" msgid="689484577124333977">"Borrar datos almacenados"</string>
-    <string name="webstorage_clear_data_summary" msgid="3523128713743907805">"Eliminar todas las bases de datos asociadas a este sitio web"</string>
     <string name="webstorage_clear_data_dialog_title" msgid="345457466368974706">"Borrar datos almacenados"</string>
     <string name="webstorage_clear_data_dialog_message" msgid="6678281256970470125">"Todos los datos almacenados por este sitio web se eliminarán."</string>
     <string name="webstorage_clear_data_dialog_ok_button" msgid="2516563534211898636">"Borrar todo"</string>
@@ -278,17 +275,19 @@
     <string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Compartir ubicación"</string>
     <string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Rechazar"</string>
     <string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Recordar preferencia"</string>
+    <string name="geolocation_permissions_prompt_toast_allowed" msgid="987286072035125498">"Este sitio puede acceder a tu ubicación. Para modificar esta opción, accede a \"Ajustes -&gt; Ajustes del sitio web\"."</string>
+    <string name="geolocation_permissions_prompt_toast_disallowed" msgid="7695100950212692515">"Este sitio no puede acceder a tu ubicación. Para modificar esta opción, accede a \"Ajustes -&gt; Ajustes del sitio web\"."</string>
     <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Permitir acceso a la ubicación"</string>
     <string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Este sitio puede acceder actualmente a tu ubicación."</string>
     <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Este sitio no puede acceder actualmente a tu ubicación."</string>
-    <string name="geolocation_settings_page_dialog_title" msgid="1549842043381347668">"Permitir acceso a la ubicación"</string>
+    <string name="geolocation_settings_page_dialog_title" msgid="1549842043381347668">"Permitir acceso ubicación"</string>
     <string name="geolocation_settings_page_dialog_message" msgid="7586671987576403993">"Se permitirá que este sitio web acceda a tu ubicación."</string>
     <string name="geolocation_settings_page_dialog_ok_button" msgid="4789434178048077287">"Permitir acceso"</string>
     <string name="geolocation_settings_page_dialog_cancel_button" msgid="7941036504673409747">"Cancelar"</string>
     <string name="website_settings_clear_all" msgid="8739804325997655980">"Borrar todo"</string>
-    <string name="website_settings_clear_all_dialog_title" msgid="7791826325122461718">"¿Quieres borrar toda la configuración del sitio web?"</string>
+    <string name="website_settings_clear_all_dialog_title" msgid="7791826325122461718">"¿Quieres borrar todos los ajustes del sitio web?"</string>
     <string name="website_settings_clear_all_dialog_message" msgid="6150502090601476333">"Se eliminarán todos los permisos de ubicación y los datos del sitio web."</string>
     <string name="website_settings_clear_all_dialog_ok_button" msgid="6401582240627669431">"Eliminar todos los datos"</string>
     <string name="website_settings_clear_all_dialog_cancel_button" msgid="1896757051856611674">"Cancelar"</string>
-    <string name="zoom_overview_button_text" msgid="4146579940085488881">"Información general"</string>
+    <string name="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Estableciendo fondo de pantalla..."</string>
 </resources>
diff --git a/res/values-fr/arrays.xml b/res/values-fr/arrays.xml
deleted file mode 100644
index f0ea8e8..0000000
--- a/res/values-fr/arrays.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="webstorage_quota_entries">
-    <item msgid="5433313236875537673">"Aucun quota autorisé"</item>
-    <item msgid="7374272188672967690">"5 Mo"</item>
-    <item msgid="8699352701856136738">"10 Mo"</item>
-    <item msgid="2018822431469084862">"30 Mo"</item>
-    <item msgid="5383642976774534074">"100 Mo"</item>
-  </string-array>
-  <string-array name="webstorage_quota_entries_values">
-    <item msgid="7620410313725236055">"0"</item>
-    <item msgid="4302688814760304206">"5"</item>
-    <item msgid="7291990205847586165">"10"</item>
-    <item msgid="916913372287112423">"30"</item>
-    <item msgid="3437188301324229987">"100"</item>
-  </string-array>
-</resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index aad7dc9..33e4005 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -1,21 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--  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.
--->
+ -->
+
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="1935869255545976415">"Navigateur"</string>
+    <string name="choose_upload" msgid="3649366287575002063">"Choisir le fichier à importer"</string>
     <string name="new_tab" msgid="4505722538297295141">"Nouvelle fenêtre"</string>
     <string name="active_tabs" msgid="3050623868203544623">"Fenêtres"</string>
     <string name="tab_bookmarks" msgid="2305793036003473653">"Favoris"</string>
@@ -58,11 +60,10 @@
     <string name="validity_period" msgid="57988851973181309">"Validité :"</string>
     <string name="issued_on" msgid="2082890654801808368">"Émis le :"</string>
     <string name="expires_on" msgid="8061200430557020704">"Expire le :"</string>
-    <string name="retrieving_creds_dlg_msg" msgid="9207671133094039879">"Récupération des données de connexion..."</string>
     <string name="stopping" msgid="4839698519340302982">"Arrêt..."</string>
     <string name="stop" msgid="5687251076030630074">"Interrompre"</string>
     <string name="reload" msgid="8585220783228408062">"Actualiser"</string>
-    <string name="back" msgid="8414603107175713668">"Précédent"</string>
+    <string name="back" msgid="8414603107175713668">"Retour"</string>
     <string name="forward" msgid="4288210890526641577">"Suivant"</string>
     <string name="save" msgid="5922311934992468496">"OK"</string>
     <string name="do_not_save" msgid="6777633870113477714">"Annuler"</string>
@@ -82,8 +83,8 @@
     <string name="homepage_set" msgid="8768087280310966395">"La page d\'accueil a été définie."</string>
     <string name="bookmark_needs_title" msgid="6245900436119218187">"Vous devez attribuer un nom à votre favori."</string>
     <string name="bookmark_needs_url" msgid="7809876865972755158">"Le favori doit disposer d\'un emplacement."</string>
-    <string name="empty_bookmark" msgid="7008697085928540511">"Impossible de créer un favori vide."</string>
     <string name="bookmark_url_not_valid" msgid="6719785633980202419">"L\'URL est incorrecte."</string>
+    <string name="bookmark_cannot_save_url" msgid="791722768778386941">"Impossible d\'ajouter cette URL à vos favoris."</string>
     <string name="delete_bookmark" msgid="2422989994934201992">"Supprimer"</string>
     <string name="bookmark_page" msgid="6845189305130307274">"Ajouter la dernière page consultée"</string>
     <string name="switch_to_thumbnails" msgid="5493351529609043151">"Miniatures"</string>
@@ -91,18 +92,11 @@
     <string name="current_page" msgid="7510129573681663135">"de "</string>
     <string name="delete_bookmark_warning" msgid="758043186202032205">"Le favori \"<xliff:g id="BOOKMARK">%s</xliff:g>\" sera supprimé."</string>
     <string name="open_in_new_window" msgid="6596775546468054510">"Nouv. fenêtre"</string>
-    <string name="new_window" msgid="8117889615360211551">"Nouvelle fenêtre"</string>
     <string name="goto_dot" msgid="3895839050522602723">"Recherche"</string>
     <string name="find_dot" msgid="6259312434696611957">"Rechercher sur la page"</string>
     <string name="select_dot" msgid="6299170761900561967">"Sélectionner le texte"</string>
-    <string name="view_tabs" msgid="1119097492003550564">"Vue d\'ensemble des fenêtres"</string>
-    <string name="view_tabs_condensed" msgid="5803955493821945369">"Fenêtres"</string>
     <string name="tab_picker_title" msgid="864478399057782913">"Fenêtres actuelles"</string>
-    <string name="tab_picker_view_tab" msgid="2984342364915347656">"Afficher"</string>
-    <string name="tab_picker_new_tab" msgid="3080280018986866528">"Nouv. fenêtre"</string>
     <string name="tab_picker_remove_tab" msgid="630087809802479397">"Fermer"</string>
-    <string name="tab_picker_bookmark" msgid="1084409404198995477">"Favori"</string>
-    <string name="tab_picker_send_url" msgid="9102803487525950021">"Partager le lien"</string>
     <string name="bookmarks" msgid="1961279134885867815">"Favoris"</string>
     <string name="shortcut_bookmark" msgid="3974876480401135895">"Favori"</string>
     <string name="history" msgid="2451240511251410032">"Historique"</string>
@@ -118,6 +112,7 @@
     <string name="contextmenu_copylink" msgid="5153657160294534270">"Copier l\'URL du lien"</string>
     <string name="contextmenu_download_image" msgid="4243829645180686912">"Enregistrer l\'image"</string>
     <string name="contextmenu_view_image" msgid="3870625602053600905">"Afficher l\'image"</string>
+    <string name="contextmenu_set_wallpaper" msgid="3691902960115350686">"Définir comme fond d\'écran"</string>
     <string name="contextmenu_dial_dot" msgid="5856550683415933806">"Composer..."</string>
     <string name="contextmenu_add_contact" msgid="3183511922223645716">"Ajouter un contact"</string>
     <string name="contextmenu_send_mail" msgid="1014513374828775660">"Envoyer un e-mail"</string>
@@ -134,8 +129,14 @@
     <string name="pref_content_javascript" msgid="4570972030299516843">"Activer JavaScript"</string>
     <string name="pref_content_open_in_background" msgid="824123779725118663">"Ouvrir en arrière-plan"</string>
     <string name="pref_content_plugins" msgid="7231944644794301582">"Activer les plug-ins"</string>
+  <string-array name="pref_content_plugins_choices">
+    <item msgid="6745108155096660725">"Toujours activé"</item>
+    <item msgid="2484126708670016519">"À la demande"</item>
+    <item msgid="8547442717307793863">"Désactivé"</item>
+  </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_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>
     <string name="pref_content_landscape_only" msgid="2022546812766219672">"Mode Paysage"</string>
@@ -190,24 +191,23 @@
     <string name="pref_content_load_page_summary" msgid="8792093504054149369">"Afficher une vue d\'ensemble des pages qui viennent d\'être ouvertes"</string>
     <string name="pref_extras_title" msgid="3091250467679722382">"Paramètres avancés"</string>
     <string name="pref_extras_website_settings" msgid="67866640052455549">"Paramètres du site Web"</string>
-    <string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Afficher les paramètres avancés de sites Web individuels"</string>
+    <string name="pref_extras_website_settings_summary" msgid="1656771443223494406">"Paramètres avancés de sites Web individuels"</string>
     <string name="pref_extras_reset_default" msgid="8904000515846202110">"Rét. valeurs par défaut"</string>
-    <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Effacer les données du navigateur et rétablir les paramètres par défaut"</string>
-    <string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"Toutes les données du navigateur seront supprimées et les paramètres par défaut rétablis."</string>
+    <string name="pref_extras_reset_default_summary" msgid="4247870778270414501">"Rétablir les paramètres par défaut"</string>
+    <string name="pref_extras_reset_default_dlg" msgid="6640261575874704022">"Les paramètres par défaut seront rétablis."</string>
     <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Rétablir les valeurs par défaut"</string>
     <string name="pref_development_title" msgid="3263854204533056480">"Débogage"</string>
     <string name="pref_default_text_encoding" msgid="5742965543955558478">"Codage du texte"</string>
   <string-array name="pref_default_text_encoding_choices">
     <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
     <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
-    <item msgid="7143715548814380950">"Japonais (ISO-2022-JP)"</item>
-    <item msgid="5111312120564516587">"Japonais (SHIFT_JIS)"</item>
-    <item msgid="6545734186479713946">"Japonais (EUC-JP)"</item>
+    <item msgid="6122474363777211732">"Chinois (GBK)"</item>
+    <item msgid="373372275931607040">"Chinois (Big5)"</item>
+    <item msgid="891615911084608570">"Japonais (ISO-2022-JP)"</item>
+    <item msgid="5589150448475151241">"Japonais (SHIFT_JIS)"</item>
+    <item msgid="7356792686950371843">"Japonais (EUC-JP)"</item>
   </string-array>
     <string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Codage du texte"</string>
-    <string name="pref_default_text_encoding_default" msgid="5272126711231936722">"Latin-1"</string>
-    <string name="browserFrameRedirect" msgid="7049675479777828343">"Rediriger"</string>
-    <string name="browserFrame307Post" msgid="1429094844669510768">"Cette page Web est en cours de redirection. Voulez-vous renvoyer les données de formulaire saisies vers le nouvel emplacement ?"</string>
     <string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Problème de connectivité des données"</string>
     <string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Problème de fichier"</string>
     <string name="browserFrameFormResubmitLabel" msgid="2685923472682180360">"Confirmer"</string>
@@ -222,7 +222,7 @@
     <string name="search_hint" msgid="4647356319916631820">"Rech. ou entrer l\'URL"</string>
     <string name="search_button_text" msgid="5235226933877634410">"Aller"</string>
     <string name="search_settings_description" msgid="1422401062529014107">"Favoris et historique Web"</string>
-    <string name="attention" msgid="3473639060042811244">"Attention"</string>
+    <string name="attention" msgid="3473639060042811244">"Avertissement"</string>
     <string name="popup_window_attempt" msgid="2673111696288657989">"Le site tente d\'ouvrir une fenêtre contextuelle."</string>
     <string name="allow" msgid="1157313689171991335">"Autoriser"</string>
     <string name="block" msgid="9172175889884707800">"Bloquer"</string>
@@ -234,25 +234,24 @@
     <string name="download_unknown_filename" msgid="4013465542563652175">"&lt;Inconnu&gt;"</string>
     <string name="download_menu_open" msgid="4888327480367757513">"Ouvrir"</string>
     <string name="download_menu_clear" msgid="6264454531553418124">"Effacer de la liste"</string>
+    <string name="download_menu_delete" msgid="8815502136393894148">"Supprimer"</string>
     <string name="download_menu_cancel" msgid="2545333007601851574">"Annuler le téléchargement"</string>
     <string name="download_menu_cancel_all" msgid="2136550823151999166">"Annuler tous les téléchargements"</string>
-    <string name="download_menu_clear_all" msgid="7423737413377703862">"Effacer la liste"</string>
-    <string name="download_clear_dlg_title" msgid="7961996329529777390">"Effacer"</string>
-    <string name="download_clear_dlg_msg" msgid="8056013815679757669">"Tous les éléments seront effacés de la liste et supprimés du cache du navigateur."</string>
     <string name="download_cancel_dlg_title" msgid="8909108500262799748">"Annuler les téléchargements"</string>
     <string name="download_cancel_dlg_msg" msgid="6285389170052357797">"Les <xliff:g id="DOWNLOAD_COUNT">%d</xliff:g> téléchargements seront annulés et effacés de l\'historique des téléchargements."</string>
+    <string name="download_delete_file" msgid="5330036497843073249">"Suppression du fichier"</string>
     <string name="download_file_error_dlg_title" msgid="2693630283595384874">"Espace insuffisant"</string>
-    <string name="download_file_error_dlg_msg" msgid="5156405410324072471">"Impossible de télécharger <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_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>
-    <string name="download_no_application" msgid="5054596425887523234">"Impossible de trouver une application permettant d\'ouvrir ce fichier."</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>
     <string name="download_error" msgid="413496839831257187">"Échec du téléchargement"</string>
-    <string name="download_success" msgid="2279041638155595203">"Téléchargement de <xliff:g id="FILE">%s</xliff:g> terminé."</string>
+    <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>
@@ -262,12 +261,10 @@
     <string name="download_file_error" msgid="1206648050615176113">"Téléchargement interrompu. Espace insuffisant."</string>
     <string name="download_length_required" msgid="9038605488460437406">"Téléchargement impossible. La taille de l\'élément n\'a pas pu être déterminée."</string>
     <string name="download_precondition_failed" msgid="8327584102874295580">"Téléchargement interrompu. Impossible de reprendre le téléchargement."</string>
-    <string name="activity_instrumentation_test_runner" msgid="8215091309334005029">"Testeur de navigateur"</string>
     <string name="search_the_web" msgid="6046130189241962337">"Rechercher sur le Web"</string>
     <string name="webstorage_outofspace_notification_title" msgid="1160474608059771788">"Espace de stockage du navigateur saturé"</string>
     <string name="webstorage_outofspace_notification_text" msgid="7341075135051829692">"Cliquez ici pour libérer de l\'espace."</string>
     <string name="webstorage_clear_data_title" msgid="689484577124333977">"Effacer les données stockées"</string>
-    <string name="webstorage_clear_data_summary" msgid="3523128713743907805">"Supprimer toutes les bases de données associées à ce site Web"</string>
     <string name="webstorage_clear_data_dialog_title" msgid="345457466368974706">"Effacer les données stockées"</string>
     <string name="webstorage_clear_data_dialog_message" msgid="6678281256970470125">"Toutes les données stockées par le site Web vont être supprimées."</string>
     <string name="webstorage_clear_data_dialog_ok_button" msgid="2516563534211898636">"Tout effacer"</string>
@@ -278,6 +275,8 @@
     <string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Partager ma position"</string>
     <string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Refuser"</string>
     <string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Mémoriser les préférences"</string>
+    <string name="geolocation_permissions_prompt_toast_allowed" msgid="987286072035125498">"Ce site peut afficher votre position. Modifiez cette option dans Paramètres -&gt; Paramètres du site Web."</string>
+    <string name="geolocation_permissions_prompt_toast_disallowed" msgid="7695100950212692515">"Ce site ne peut afficher votre position. Modifiez cette option dans Paramètres -&gt; Paramètres du site Web."</string>
     <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Accès données localis."</string>
     <string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Ce site a actuellement accès à vos données de localisation."</string>
     <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Ce site n\'a actuellement pas accès à vos données de localisation."</string>
@@ -290,5 +289,5 @@
     <string name="website_settings_clear_all_dialog_message" msgid="6150502090601476333">"Toutes les données du site Web et les autorisations de localisation seront supprimées."</string>
     <string name="website_settings_clear_all_dialog_ok_button" msgid="6401582240627669431">"Supprimer toutes les données"</string>
     <string name="website_settings_clear_all_dialog_cancel_button" msgid="1896757051856611674">"Annuler"</string>
-    <string name="zoom_overview_button_text" msgid="4146579940085488881">"Présentation"</string>
+    <string name="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Définition du fond d\'écran..."</string>
 </resources>
diff --git a/res/values-it/arrays.xml b/res/values-it/arrays.xml
deleted file mode 100644
index 5245c81..0000000
--- a/res/values-it/arrays.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="webstorage_quota_entries">
-    <item msgid="5433313236875537673">"Nessuna quota consentita"</item>
-    <item msgid="7374272188672967690">"5 MB"</item>
-    <item msgid="8699352701856136738">"10 MB"</item>
-    <item msgid="2018822431469084862">"30 MB"</item>
-    <item msgid="5383642976774534074">"100 MB"</item>
-  </string-array>
-  <string-array name="webstorage_quota_entries_values">
-    <item msgid="7620410313725236055">"0"</item>
-    <item msgid="4302688814760304206">"5"</item>
-    <item msgid="7291990205847586165">"10"</item>
-    <item msgid="916913372287112423">"30"</item>
-    <item msgid="3437188301324229987">"100"</item>
-  </string-array>
-</resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 91a53ce..f8fa172 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -1,21 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--  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.
--->
+ -->
+
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="1935869255545976415">"Browser"</string>
+    <string name="choose_upload" msgid="3649366287575002063">"Scegli il file per il caricamento"</string>
     <string name="new_tab" msgid="4505722538297295141">"Nuova finestra"</string>
     <string name="active_tabs" msgid="3050623868203544623">"Finestre"</string>
     <string name="tab_bookmarks" msgid="2305793036003473653">"Segnalibri"</string>
@@ -58,7 +60,6 @@
     <string name="validity_period" msgid="57988851973181309">"Validità:"</string>
     <string name="issued_on" msgid="2082890654801808368">"Rilasciato il:"</string>
     <string name="expires_on" msgid="8061200430557020704">"Scade il:"</string>
-    <string name="retrieving_creds_dlg_msg" msgid="9207671133094039879">"Recupero dettagli di accesso..."</string>
     <string name="stopping" msgid="4839698519340302982">"Interruzione..."</string>
     <string name="stop" msgid="5687251076030630074">"Interrompi"</string>
     <string name="reload" msgid="8585220783228408062">"Aggiorna"</string>
@@ -71,7 +72,7 @@
     <string name="http" msgid="2163722670597250102">"http://"</string>
     <string name="save_to_bookmarks" msgid="588165100024086565">"Aggiungi segnalibro"</string>
     <string name="edit_bookmark" msgid="5024089053490231905">"Modifica segnalibro"</string>
-    <string name="create_shortcut_bookmark" msgid="9202323987633899835">"Aggiungi scorciatoia Home"</string>
+    <string name="create_shortcut_bookmark" msgid="9202323987633899835">"Aggiungi scorciatoia su Home"</string>
     <string name="open_bookmark" msgid="8473581305759935790">"Apri"</string>
     <string name="remove_bookmark" msgid="8407495852801410891">"Elimina segnalibro"</string>
     <string name="remove_from_bookmarks" msgid="4374080666576982775">"Rimuovi dai segnalibri"</string>
@@ -82,8 +83,8 @@
     <string name="homepage_set" msgid="8768087280310966395">"Home page impostata."</string>
     <string name="bookmark_needs_title" msgid="6245900436119218187">"Inserisci un nome per il segnalibro."</string>
     <string name="bookmark_needs_url" msgid="7809876865972755158">"Inserisci un URL per il segnalibro."</string>
-    <string name="empty_bookmark" msgid="7008697085928540511">"Impossibile creare un segnalibro vuoto."</string>
     <string name="bookmark_url_not_valid" msgid="6719785633980202419">"URL non valido."</string>
+    <string name="bookmark_cannot_save_url" msgid="791722768778386941">"L\'URL non può essere aggiunto ai segnalibri."</string>
     <string name="delete_bookmark" msgid="2422989994934201992">"Elimina"</string>
     <string name="bookmark_page" msgid="6845189305130307274">"Aggiungi ultima pagina visualizzata ai segnalibri"</string>
     <string name="switch_to_thumbnails" msgid="5493351529609043151">"Visualizzazione miniatura"</string>
@@ -91,18 +92,11 @@
     <string name="current_page" msgid="7510129573681663135">"da "</string>
     <string name="delete_bookmark_warning" msgid="758043186202032205">"Il segnalibro \"<xliff:g id="BOOKMARK">%s</xliff:g>\" verrà eliminato."</string>
     <string name="open_in_new_window" msgid="6596775546468054510">"Apri in nuova finestra"</string>
-    <string name="new_window" msgid="8117889615360211551">"Nuova finestra"</string>
     <string name="goto_dot" msgid="3895839050522602723">"Vai"</string>
     <string name="find_dot" msgid="6259312434696611957">"Trova nella pagina"</string>
     <string name="select_dot" msgid="6299170761900561967">"Seleziona testo"</string>
-    <string name="view_tabs" msgid="1119097492003550564">"Anteprima finestre"</string>
-    <string name="view_tabs_condensed" msgid="5803955493821945369">"Finestre"</string>
     <string name="tab_picker_title" msgid="864478399057782913">"Finestre correnti"</string>
-    <string name="tab_picker_view_tab" msgid="2984342364915347656">"Visualizza"</string>
-    <string name="tab_picker_new_tab" msgid="3080280018986866528">"Nuova finestra"</string>
     <string name="tab_picker_remove_tab" msgid="630087809802479397">"Chiudi"</string>
-    <string name="tab_picker_bookmark" msgid="1084409404198995477">"Segnalibro"</string>
-    <string name="tab_picker_send_url" msgid="9102803487525950021">"Condividi link"</string>
     <string name="bookmarks" msgid="1961279134885867815">"Segnalibri"</string>
     <string name="shortcut_bookmark" msgid="3974876480401135895">"Segnalibro"</string>
     <string name="history" msgid="2451240511251410032">"Cronologia"</string>
@@ -118,6 +112,7 @@
     <string name="contextmenu_copylink" msgid="5153657160294534270">"Copia URL link"</string>
     <string name="contextmenu_download_image" msgid="4243829645180686912">"Salva immagine"</string>
     <string name="contextmenu_view_image" msgid="3870625602053600905">"Visualizza immagine"</string>
+    <string name="contextmenu_set_wallpaper" msgid="3691902960115350686">"Imposta come sfondo"</string>
     <string name="contextmenu_dial_dot" msgid="5856550683415933806">"Componi..."</string>
     <string name="contextmenu_add_contact" msgid="3183511922223645716">"Aggiungi contatto"</string>
     <string name="contextmenu_send_mail" msgid="1014513374828775660">"Invia email"</string>
@@ -134,8 +129,14 @@
     <string name="pref_content_javascript" msgid="4570972030299516843">"Attiva JavaScript"</string>
     <string name="pref_content_open_in_background" msgid="824123779725118663">"Apri in secondo piano"</string>
     <string name="pref_content_plugins" msgid="7231944644794301582">"Attiva plug-in"</string>
+  <string-array name="pref_content_plugins_choices">
+    <item msgid="6745108155096660725">"Sempre attivo"</item>
+    <item msgid="2484126708670016519">"Su richiesta"</item>
+    <item msgid="8547442717307793863">"Non attivo"</item>
+  </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_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>
     <string name="pref_content_landscape_only" msgid="2022546812766219672">"Visual. solo orizzontale"</string>
@@ -190,24 +191,23 @@
     <string name="pref_content_load_page_summary" msgid="8792093504054149369">"Visualizza la panoramica delle pagine appena aperte"</string>
     <string name="pref_extras_title" msgid="3091250467679722382">"Impostazioni avanzate"</string>
     <string name="pref_extras_website_settings" msgid="67866640052455549">"Impostazioni siti web"</string>
-    <string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Visualizza le impostazioni avanzate dei singoli siti web"</string>
+    <string name="pref_extras_website_settings_summary" msgid="1656771443223494406">"Impostazioni avanzate dei singoli siti web"</string>
     <string name="pref_extras_reset_default" msgid="8904000515846202110">"Ripristina valori predef."</string>
-    <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Cancella tutti i dati del browser e ripristina tutte le imp. predef."</string>
-    <string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"Verranno eliminati tutti i dati del browser e verranno ripristinate le impostazioni predefinite."</string>
+    <string name="pref_extras_reset_default_summary" msgid="4247870778270414501">"Ripristina impostazioni predefinite"</string>
+    <string name="pref_extras_reset_default_dlg" msgid="6640261575874704022">"Verranno ripristinate le impostazioni predefinite."</string>
     <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Ripristina valori predef."</string>
     <string name="pref_development_title" msgid="3263854204533056480">"Debug"</string>
     <string name="pref_default_text_encoding" msgid="5742965543955558478">"Codifica testo"</string>
   <string-array name="pref_default_text_encoding_choices">
     <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
     <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
-    <item msgid="7143715548814380950">"Giapponese (ISO-2022-JP)"</item>
-    <item msgid="5111312120564516587">"Giapponese (SHIFT_JIS)"</item>
-    <item msgid="6545734186479713946">"Giapponese (EUC-JP)"</item>
+    <item msgid="6122474363777211732">"Cinese (GBK)"</item>
+    <item msgid="373372275931607040">"Cinese (Big5)"</item>
+    <item msgid="891615911084608570">"Giapponese (ISO-2022-JP)"</item>
+    <item msgid="5589150448475151241">"Giapponese (SHIFT_JIS)"</item>
+    <item msgid="7356792686950371843">"Giapponese (EUC-JP)"</item>
   </string-array>
     <string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Codifica testo"</string>
-    <string name="pref_default_text_encoding_default" msgid="5272126711231936722">"Latin-1"</string>
-    <string name="browserFrameRedirect" msgid="7049675479777828343">"Reindirizza"</string>
-    <string name="browserFrame307Post" msgid="1429094844669510768">"La pagina web è in fase di reindirizzamento. Inviare di nuovo i dati del modulo alla nuova posizione?"</string>
     <string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Problema di connettività dati"</string>
     <string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Problemi con il file"</string>
     <string name="browserFrameFormResubmitLabel" msgid="2685923472682180360">"Conferma"</string>
@@ -234,25 +234,24 @@
     <string name="download_unknown_filename" msgid="4013465542563652175">"&lt;Sconosciuto&gt;"</string>
     <string name="download_menu_open" msgid="4888327480367757513">"Apri"</string>
     <string name="download_menu_clear" msgid="6264454531553418124">"Cancella da elenco"</string>
+    <string name="download_menu_delete" msgid="8815502136393894148">"Elimina"</string>
     <string name="download_menu_cancel" msgid="2545333007601851574">"Cancella download"</string>
     <string name="download_menu_cancel_all" msgid="2136550823151999166">"Annulla tutti i download"</string>
-    <string name="download_menu_clear_all" msgid="7423737413377703862">"Cancella elenco"</string>
-    <string name="download_clear_dlg_title" msgid="7961996329529777390">"Cancella"</string>
-    <string name="download_clear_dlg_msg" msgid="8056013815679757669">"Tutti gli elementi verranno cancellati dall\'elenco e rimossi dalla cache del browser."</string>
     <string name="download_cancel_dlg_title" msgid="8909108500262799748">"Annulla download"</string>
     <string name="download_cancel_dlg_msg" msgid="6285389170052357797">"Tutti i <xliff:g id="DOWNLOAD_COUNT">%d</xliff:g> download verranno cancellati dalla cronologia download."</string>
+    <string name="download_delete_file" msgid="5330036497843073249">"Il file verrà eliminato"</string>
     <string name="download_file_error_dlg_title" msgid="2693630283595384874">"Spazio esaurito"</string>
-    <string name="download_file_error_dlg_msg" msgid="5156405410324072471">"Impossibile scaricare <xliff:g id="FILENAME">%s</xliff:g>."\n"Liberare spazio sul telefono e riprovare."</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>
-    <string name="download_no_application" msgid="5054596425887523234">"Impossibile trovare un\'applicazione in cui aprire questo file."</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>
     <string name="download_error" msgid="413496839831257187">"Download non riuscito."</string>
-    <string name="download_success" msgid="2279041638155595203">"Download di <xliff:g id="FILE">%s</xliff:g> completo."</string>
+    <string name="download_success" msgid="2279041638155595203">"<xliff:g id="FILE">%s</xliff:g> Download completato."</string>
     <string name="download_running" msgid="2622942231322015059">"Download..."</string>
     <string name="download_pending" msgid="2599683668575349559">"Avvio download..."</string>
     <string name="download_pending_network" msgid="6548714525679461053">"In attesa di connessione dati..."</string>
@@ -262,12 +261,10 @@
     <string name="download_file_error" msgid="1206648050615176113">"Impossibile terminare il download. Spazio insufficiente."</string>
     <string name="download_length_required" msgid="9038605488460437406">"Impossibile effettuare il download. Impossibile determinare le dimensioni dell\'elemento."</string>
     <string name="download_precondition_failed" msgid="8327584102874295580">"Download interrotto. Impossibile ripristinarlo."</string>
-    <string name="activity_instrumentation_test_runner" msgid="8215091309334005029">"Browser Test Runner"</string>
     <string name="search_the_web" msgid="6046130189241962337">"Cerca nel Web"</string>
     <string name="webstorage_outofspace_notification_title" msgid="1160474608059771788">"Memoria del browser piena"</string>
     <string name="webstorage_outofspace_notification_text" msgid="7341075135051829692">"Fai clic per liberare spazio."</string>
     <string name="webstorage_clear_data_title" msgid="689484577124333977">"Cancella dati archiviati"</string>
-    <string name="webstorage_clear_data_summary" msgid="3523128713743907805">"Rimuovi tutti i database associati al sito web"</string>
     <string name="webstorage_clear_data_dialog_title" msgid="345457466368974706">"Cancella dati archiviati"</string>
     <string name="webstorage_clear_data_dialog_message" msgid="6678281256970470125">"Tutti i dati archiviati da questo sito web verranno eliminati"</string>
     <string name="webstorage_clear_data_dialog_ok_button" msgid="2516563534211898636">"Clear all"</string>
@@ -278,6 +275,8 @@
     <string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Condividi posizione"</string>
     <string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Rifiuta"</string>
     <string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Ricorda la preferenza"</string>
+    <string name="geolocation_permissions_prompt_toast_allowed" msgid="987286072035125498">"Questo sito può accedere alla tua posizione. Modifica questa impostazione in: Impostazioni -&gt; Impostazioni siti web"</string>
+    <string name="geolocation_permissions_prompt_toast_disallowed" msgid="7695100950212692515">"Questo sito non può accedere alla tua posizione. Modifica questa impostazione in: Impostazioni -&gt; Impostazioni siti web"</string>
     <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Cancella accesso a posiz."</string>
     <string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Al momento questo sito può accedere alla tua posizione"</string>
     <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Al momento questo sito non può accedere alla tua posizione"</string>
@@ -290,5 +289,5 @@
     <string name="website_settings_clear_all_dialog_message" msgid="6150502090601476333">"Tutti i dati dei siti web e le autorizzazioni relative alla posizione verranno eliminati."</string>
     <string name="website_settings_clear_all_dialog_ok_button" msgid="6401582240627669431">"Elimina tutti i dati"</string>
     <string name="website_settings_clear_all_dialog_cancel_button" msgid="1896757051856611674">"Annulla"</string>
-    <string name="zoom_overview_button_text" msgid="4146579940085488881">"Panoramica"</string>
+    <string name="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Impostazione sfondo in corso..."</string>
 </resources>
diff --git a/res/values-ja/arrays.xml b/res/values-ja/arrays.xml
deleted file mode 100644
index c244e64..0000000
--- a/res/values-ja/arrays.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="webstorage_quota_entries">
-    <item msgid="5433313236875537673">"割り当てられません"</item>
-    <item msgid="7374272188672967690">"5MB"</item>
-    <item msgid="8699352701856136738">"10MB"</item>
-    <item msgid="2018822431469084862">"30MB"</item>
-    <item msgid="5383642976774534074">"100MB"</item>
-  </string-array>
-  <string-array name="webstorage_quota_entries_values">
-    <item msgid="7620410313725236055">"0"</item>
-    <item msgid="4302688814760304206">"5"</item>
-    <item msgid="7291990205847586165">"10"</item>
-    <item msgid="916913372287112423">"30"</item>
-    <item msgid="3437188301324229987">"100"</item>
-  </string-array>
-</resources>
diff --git a/res/values-ja/donottranslate_strings.xml b/res/values-ja/donottranslate_strings.xml
new file mode 100644
index 0000000..cbda8f2
--- /dev/null
+++ b/res/values-ja/donottranslate_strings.xml
@@ -0,0 +1,21 @@
+<?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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <string name="pref_default_text_encoding_default">SHIFT_JIS</string>
+</resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 4cd44af..b5bf052 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -1,21 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--  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.
--->
+ -->
+
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="1935869255545976415">"ブラウザ"</string>
+    <string name="choose_upload" msgid="3649366287575002063">"アップロードするファイルを選択"</string>
     <string name="new_tab" msgid="4505722538297295141">"新しいウィンドウ"</string>
     <string name="active_tabs" msgid="3050623868203544623">"ウィンドウ"</string>
     <string name="tab_bookmarks" msgid="2305793036003473653">"ブックマーク"</string>
@@ -58,7 +60,6 @@
     <string name="validity_period" msgid="57988851973181309">"有効期間:"</string>
     <string name="issued_on" msgid="2082890654801808368">"発行:"</string>
     <string name="expires_on" msgid="8061200430557020704">"有効期限:"</string>
-    <string name="retrieving_creds_dlg_msg" msgid="9207671133094039879">"ログイン詳細を取得中..."</string>
     <string name="stopping" msgid="4839698519340302982">"停止中..."</string>
     <string name="stop" msgid="5687251076030630074">"停止"</string>
     <string name="reload" msgid="8585220783228408062">"再読み込み"</string>
@@ -82,8 +83,8 @@
     <string name="homepage_set" msgid="8768087280310966395">"ホームページを設定しました。"</string>
     <string name="bookmark_needs_title" msgid="6245900436119218187">"名前を指定してください。"</string>
     <string name="bookmark_needs_url" msgid="7809876865972755158">"場所を指定してください。"</string>
-    <string name="empty_bookmark" msgid="7008697085928540511">"空のブックマークは作成できません。"</string>
     <string name="bookmark_url_not_valid" msgid="6719785633980202419">"無効なURLです。"</string>
+    <string name="bookmark_cannot_save_url" msgid="791722768778386941">"このURLはブックマークに追加できません。"</string>
     <string name="delete_bookmark" msgid="2422989994934201992">"削除"</string>
     <string name="bookmark_page" msgid="6845189305130307274">"最後に表示したページをブックマークする"</string>
     <string name="switch_to_thumbnails" msgid="5493351529609043151">"サムネイル表示"</string>
@@ -91,18 +92,11 @@
     <string name="current_page" msgid="7510129573681663135">"URL "</string>
     <string name="delete_bookmark_warning" msgid="758043186202032205">"ブックマーク「<xliff:g id="BOOKMARK">%s</xliff:g>」を削除します。"</string>
     <string name="open_in_new_window" msgid="6596775546468054510">"新しいウィンドウで開く"</string>
-    <string name="new_window" msgid="8117889615360211551">"新規ウィンドウ"</string>
     <string name="goto_dot" msgid="3895839050522602723">"移動"</string>
     <string name="find_dot" msgid="6259312434696611957">"ページ内検索"</string>
     <string name="select_dot" msgid="6299170761900561967">"テキストを選択してコピー"</string>
-    <string name="view_tabs" msgid="1119097492003550564">"ウィンドウリスト"</string>
-    <string name="view_tabs_condensed" msgid="5803955493821945369">"ウィンドウ"</string>
     <string name="tab_picker_title" msgid="864478399057782913">"現在のウィンドウ"</string>
-    <string name="tab_picker_view_tab" msgid="2984342364915347656">"表示"</string>
-    <string name="tab_picker_new_tab" msgid="3080280018986866528">"新規ウィンドウ"</string>
     <string name="tab_picker_remove_tab" msgid="630087809802479397">"閉じる"</string>
-    <string name="tab_picker_bookmark" msgid="1084409404198995477">"ブックマーク"</string>
-    <string name="tab_picker_send_url" msgid="9102803487525950021">"リンクを共有"</string>
     <string name="bookmarks" msgid="1961279134885867815">"ブックマーク"</string>
     <string name="shortcut_bookmark" msgid="3974876480401135895">"ブックマーク"</string>
     <string name="history" msgid="2451240511251410032">"履歴"</string>
@@ -118,6 +112,7 @@
     <string name="contextmenu_copylink" msgid="5153657160294534270">"URLをコピー"</string>
     <string name="contextmenu_download_image" msgid="4243829645180686912">"画像を保存"</string>
     <string name="contextmenu_view_image" msgid="3870625602053600905">"画像を表示"</string>
+    <string name="contextmenu_set_wallpaper" msgid="3691902960115350686">"壁紙として設定"</string>
     <string name="contextmenu_dial_dot" msgid="5856550683415933806">"発信..."</string>
     <string name="contextmenu_add_contact" msgid="3183511922223645716">"連絡先を追加"</string>
     <string name="contextmenu_send_mail" msgid="1014513374828775660">"メールを送信"</string>
@@ -134,8 +129,14 @@
     <string name="pref_content_javascript" msgid="4570972030299516843">"JavaScriptを有効にする"</string>
     <string name="pref_content_open_in_background" msgid="824123779725118663">"バックグラウンドで開く"</string>
     <string name="pref_content_plugins" msgid="7231944644794301582">"プラグインを有効にする"</string>
+  <string-array name="pref_content_plugins_choices">
+    <item msgid="6745108155096660725">"常にON"</item>
+    <item msgid="2484126708670016519">"オンデマンド"</item>
+    <item msgid="8547442717307793863">"OFF"</item>
+  </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"現在のウィンドウの後ろに新しいウィンドウを開く"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"ホームページ設定"</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>
     <string name="pref_content_landscape_only" msgid="2022546812766219672">"常に横向きに表示"</string>
@@ -190,24 +191,23 @@
     <string name="pref_content_load_page_summary" msgid="8792093504054149369">"新しく開いたページを全体表示する"</string>
     <string name="pref_extras_title" msgid="3091250467679722382">"詳細設定"</string>
     <string name="pref_extras_website_settings" msgid="67866640052455549">"ウェブサイト設定"</string>
-    <string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"個々のウェブサイトの詳細設定を表示する"</string>
+    <string name="pref_extras_website_settings_summary" msgid="1656771443223494406">"個々のウェブサイトの詳細設定"</string>
     <string name="pref_extras_reset_default" msgid="8904000515846202110">"初期設定にリセット"</string>
-    <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"ブラウザデータをすべて消去して出荷時の初期設定に戻す"</string>
-    <string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"すべてのブラウザデータを削除して設定をデフォルト値に戻します。"</string>
+    <string name="pref_extras_reset_default_summary" msgid="4247870778270414501">"初期設定に戻す"</string>
+    <string name="pref_extras_reset_default_dlg" msgid="6640261575874704022">"設定を初期値に戻します。"</string>
     <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"初期設定にリセット"</string>
     <string name="pref_development_title" msgid="3263854204533056480">"デバッグ"</string>
     <string name="pref_default_text_encoding" msgid="5742965543955558478">"テキストエンコード"</string>
   <string-array name="pref_default_text_encoding_choices">
     <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
     <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
-    <item msgid="7143715548814380950">"日本語 (ISO-2022-JP)"</item>
-    <item msgid="5111312120564516587">"日本語 (Shift_JIS)"</item>
-    <item msgid="6545734186479713946">"日本語 (EUC-JP)"</item>
+    <item msgid="6122474363777211732">"中国語(GBK)"</item>
+    <item msgid="373372275931607040">"中国語(Big5)"</item>
+    <item msgid="891615911084608570">"日本語(ISO-2022-JP)"</item>
+    <item msgid="5589150448475151241">"日本語(SHIFT_JIS)"</item>
+    <item msgid="7356792686950371843">"日本語(EUC-JP)"</item>
   </string-array>
     <string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"テキストエンコード"</string>
-    <string name="pref_default_text_encoding_default" msgid="5272126711231936722">"SHIFT_JIS"</string>
-    <string name="browserFrameRedirect" msgid="7049675479777828343">"リダイレクト"</string>
-    <string name="browserFrame307Post" msgid="1429094844669510768">"このウェブページはリダイレクトされます。入力したフォームデータをリダイレクト先に送信しますか?"</string>
     <string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"データアクセスエラー"</string>
     <string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"ファイルに問題があります"</string>
     <string name="browserFrameFormResubmitLabel" msgid="2685923472682180360">"確認"</string>
@@ -234,13 +234,12 @@
     <string name="download_unknown_filename" msgid="4013465542563652175">"&lt;不明&gt;"</string>
     <string name="download_menu_open" msgid="4888327480367757513">"開く"</string>
     <string name="download_menu_clear" msgid="6264454531553418124">"リストから消去"</string>
+    <string name="download_menu_delete" msgid="8815502136393894148">"削除"</string>
     <string name="download_menu_cancel" msgid="2545333007601851574">"ダウンロードをキャンセル"</string>
     <string name="download_menu_cancel_all" msgid="2136550823151999166">"全ダウンロードをキャンセル"</string>
-    <string name="download_menu_clear_all" msgid="7423737413377703862">"リストを消去"</string>
-    <string name="download_clear_dlg_title" msgid="7961996329529777390">"消去"</string>
-    <string name="download_clear_dlg_msg" msgid="8056013815679757669">"リストの項目をすべて消去し、ブラウザのキャッシュから削除します。"</string>
     <string name="download_cancel_dlg_title" msgid="8909108500262799748">"ダウンロードをキャンセル"</string>
     <string name="download_cancel_dlg_msg" msgid="6285389170052357797">"全<xliff:g id="DOWNLOAD_COUNT">%d</xliff:g>件のダウンロードをキャンセルし、ダウンロード履歴から消去します。"</string>
+    <string name="download_delete_file" msgid="5330036497843073249">"ファイルを削除します"</string>
     <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>
@@ -248,7 +247,7 @@
     <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>
-    <string name="download_no_application" msgid="5054596425887523234">"このファイルを開くアプリケーションがありません。"</string>
+    <string name="download_no_application_title" msgid="1286056729168874295">"ファイルを開けません"</string>
     <string name="retry" msgid="1835923075542266721">"やり直す"</string>
     <string name="no_downloads" msgid="3947445710685021498">"ダウンロード履歴はありません。"</string>
     <string name="download_error" msgid="413496839831257187">"ダウンロードできませんでした。"</string>
@@ -262,12 +261,10 @@
     <string name="download_file_error" msgid="1206648050615176113">"空き容量が不足しているため、ダウンロードを完了できません。"</string>
     <string name="download_length_required" msgid="9038605488460437406">"項目のサイズを特定できないため、ダウンロードできません。"</string>
     <string name="download_precondition_failed" msgid="8327584102874295580">"ダウンロードが中断されました。再開できません。"</string>
-    <string name="activity_instrumentation_test_runner" msgid="8215091309334005029">"Browser Test Runner"</string>
     <string name="search_the_web" msgid="6046130189241962337">"ウェブを検索します"</string>
     <string name="webstorage_outofspace_notification_title" msgid="1160474608059771788">"ブラウザのメモリがいっぱいです"</string>
     <string name="webstorage_outofspace_notification_text" msgid="7341075135051829692">"クリックして空き領域を増やします。"</string>
     <string name="webstorage_clear_data_title" msgid="689484577124333977">"保存したデータを消去"</string>
-    <string name="webstorage_clear_data_summary" msgid="3523128713743907805">"このウェブサイトに関連付けたデータベースをすべて削除"</string>
     <string name="webstorage_clear_data_dialog_title" msgid="345457466368974706">"保存したデータを消去"</string>
     <string name="webstorage_clear_data_dialog_message" msgid="6678281256970470125">"このウェブサイトに保存されたデータをすべて削除します"</string>
     <string name="webstorage_clear_data_dialog_ok_button" msgid="2516563534211898636">"すべて消去"</string>
@@ -278,6 +275,8 @@
     <string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"位置情報を共有"</string>
     <string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"拒否"</string>
     <string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"設定を保存"</string>
+    <string name="geolocation_permissions_prompt_toast_allowed" msgid="987286072035125498">"このサイトは現在地情報にアクセスできます。設定変更: [設定]-&gt;[ウェブサイト設定]"</string>
+    <string name="geolocation_permissions_prompt_toast_disallowed" msgid="7695100950212692515">"このサイトは現在地情報にアクセスできません。設定変更: [設定]-&gt;[ウェブサイト設定]"</string>
     <string name="geolocation_settings_page_title" msgid="1745477985097536528">"位置情報アクセスをクリア"</string>
     <string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"このサイトは現在地情報にアクセスできます"</string>
     <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"このサイトは現在地情報にアクセスできません"</string>
@@ -290,5 +289,5 @@
     <string name="website_settings_clear_all_dialog_message" msgid="6150502090601476333">"すべてのウェブサイトデータと位置情報の許可が削除されます。"</string>
     <string name="website_settings_clear_all_dialog_ok_button" msgid="6401582240627669431">"すべてのデータを削除"</string>
     <string name="website_settings_clear_all_dialog_cancel_button" msgid="1896757051856611674">"キャンセル"</string>
-    <string name="zoom_overview_button_text" msgid="4146579940085488881">"全体表示"</string>
+    <string name="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"壁紙を設定中..."</string>
 </resources>
diff --git a/res/values-ko/arrays.xml b/res/values-ko/arrays.xml
deleted file mode 100644
index 7d27cd1..0000000
--- a/res/values-ko/arrays.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="webstorage_quota_entries">
-    <item msgid="5433313236875537673">"할당된 저장용량이 없습니다."</item>
-    <item msgid="7374272188672967690">"5MB"</item>
-    <item msgid="8699352701856136738">"10MB"</item>
-    <item msgid="2018822431469084862">"30MB"</item>
-    <item msgid="5383642976774534074">"100MB"</item>
-  </string-array>
-  <string-array name="webstorage_quota_entries_values">
-    <item msgid="7620410313725236055">"0"</item>
-    <item msgid="4302688814760304206">"5"</item>
-    <item msgid="7291990205847586165">"10"</item>
-    <item msgid="916913372287112423">"30"</item>
-    <item msgid="3437188301324229987">"100"</item>
-  </string-array>
-</resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 4682712..82cafbc 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -1,21 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--  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.
--->
+ -->
+
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="1935869255545976415">"인터넷"</string>
+    <string name="choose_upload" msgid="3649366287575002063">"업로드할 파일 선택"</string>
     <string name="new_tab" msgid="4505722538297295141">"새 창"</string>
     <string name="active_tabs" msgid="3050623868203544623">"창"</string>
     <string name="tab_bookmarks" msgid="2305793036003473653">"북마크"</string>
@@ -58,15 +60,14 @@
     <string name="validity_period" msgid="57988851973181309">"유효성:"</string>
     <string name="issued_on" msgid="2082890654801808368">"발급 날짜:"</string>
     <string name="expires_on" msgid="8061200430557020704">"만료 날짜:"</string>
-    <string name="retrieving_creds_dlg_msg" msgid="9207671133094039879">"로그인 세부정보를 가져오는 중..."</string>
     <string name="stopping" msgid="4839698519340302982">"중지하는 중..."</string>
     <string name="stop" msgid="5687251076030630074">"중지"</string>
     <string name="reload" msgid="8585220783228408062">"새로고침"</string>
     <string name="back" msgid="8414603107175713668">"뒤로"</string>
-    <string name="forward" msgid="4288210890526641577">"앞으로"</string>
+    <string name="forward" msgid="4288210890526641577">"전달"</string>
     <string name="save" msgid="5922311934992468496">"확인"</string>
     <string name="do_not_save" msgid="6777633870113477714">"취소"</string>
-    <string name="location" msgid="969988560160364559">"위치"</string>
+    <string name="location" msgid="969988560160364559">"국가"</string>
     <string name="name" msgid="5990326151488445481">"이름"</string>
     <string name="http" msgid="2163722670597250102">"http://"</string>
     <string name="save_to_bookmarks" msgid="588165100024086565">"북마크에 추가"</string>
@@ -82,8 +83,8 @@
     <string name="homepage_set" msgid="8768087280310966395">"홈페이지가 설정되었습니다."</string>
     <string name="bookmark_needs_title" msgid="6245900436119218187">"북마크의 이름을 입력해야 합니다."</string>
     <string name="bookmark_needs_url" msgid="7809876865972755158">"북마크의 위치를 입력해야 합니다."</string>
-    <string name="empty_bookmark" msgid="7008697085928540511">"빈 북마크를 만들 수 없습니다."</string>
     <string name="bookmark_url_not_valid" msgid="6719785633980202419">"URL이 유효하지 않습니다."</string>
+    <string name="bookmark_cannot_save_url" msgid="791722768778386941">"URL을 북마크에 추가할 수 없습니다."</string>
     <string name="delete_bookmark" msgid="2422989994934201992">"삭제"</string>
     <string name="bookmark_page" msgid="6845189305130307274">"마지막으로 본 페이지를 북마크 설정"</string>
     <string name="switch_to_thumbnails" msgid="5493351529609043151">"미리보기 이미지 보기"</string>
@@ -91,18 +92,11 @@
     <string name="current_page" msgid="7510129573681663135">"북마크할 페이지 "</string>
     <string name="delete_bookmark_warning" msgid="758043186202032205">"\'<xliff:g id="BOOKMARK">%s</xliff:g>\' 북마크가 삭제됩니다."</string>
     <string name="open_in_new_window" msgid="6596775546468054510">"새 창에서 열기"</string>
-    <string name="new_window" msgid="8117889615360211551">"새 창"</string>
-    <string name="goto_dot" msgid="3895839050522602723">"실행"</string>
+    <string name="goto_dot" msgid="3895839050522602723">"이동"</string>
     <string name="find_dot" msgid="6259312434696611957">"페이지에서 찾기"</string>
     <string name="select_dot" msgid="6299170761900561967">"텍스트 선택"</string>
-    <string name="view_tabs" msgid="1119097492003550564">"창 전체보기"</string>
-    <string name="view_tabs_condensed" msgid="5803955493821945369">"창"</string>
     <string name="tab_picker_title" msgid="864478399057782913">"현재 창"</string>
-    <string name="tab_picker_view_tab" msgid="2984342364915347656">"보기"</string>
-    <string name="tab_picker_new_tab" msgid="3080280018986866528">"새 창"</string>
     <string name="tab_picker_remove_tab" msgid="630087809802479397">"닫기"</string>
-    <string name="tab_picker_bookmark" msgid="1084409404198995477">"북마크"</string>
-    <string name="tab_picker_send_url" msgid="9102803487525950021">"링크 공유"</string>
     <string name="bookmarks" msgid="1961279134885867815">"북마크"</string>
     <string name="shortcut_bookmark" msgid="3974876480401135895">"북마크"</string>
     <string name="history" msgid="2451240511251410032">"기록"</string>
@@ -118,7 +112,8 @@
     <string name="contextmenu_copylink" msgid="5153657160294534270">"링크 URL 복사"</string>
     <string name="contextmenu_download_image" msgid="4243829645180686912">"이미지 저장"</string>
     <string name="contextmenu_view_image" msgid="3870625602053600905">"이미지 보기"</string>
-    <string name="contextmenu_dial_dot" msgid="5856550683415933806">"전화 걸기..."</string>
+    <string name="contextmenu_set_wallpaper" msgid="3691902960115350686">"배경화면으로 설정"</string>
+    <string name="contextmenu_dial_dot" msgid="5856550683415933806">"전화걸기…"</string>
     <string name="contextmenu_add_contact" msgid="3183511922223645716">"연락처 추가"</string>
     <string name="contextmenu_send_mail" msgid="1014513374828775660">"이메일 보내기"</string>
     <string name="contextmenu_map" msgid="7471390435434034912">"지도"</string>
@@ -134,8 +129,14 @@
     <string name="pref_content_javascript" msgid="4570972030299516843">"자바스크립트 사용"</string>
     <string name="pref_content_open_in_background" msgid="824123779725118663">"백그라운드에서 열기"</string>
     <string name="pref_content_plugins" msgid="7231944644794301582">"플러그인 사용"</string>
+  <string-array name="pref_content_plugins_choices">
+    <item msgid="6745108155096660725">"항상 사용"</item>
+    <item msgid="2484126708670016519">"요청 시"</item>
+    <item msgid="8547442717307793863">"사용 안함"</item>
+  </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"현재 창 뒤에 새 창 열기"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"홈페이지 설정"</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>
     <string name="pref_content_landscape_only" msgid="2022546812766219672">"가로 표시 전용"</string>
@@ -181,33 +182,32 @@
     <string name="pref_text_size_dialogtitle" msgid="3625388833512647865">"텍스트 크기"</string>
     <string name="pref_default_zoom" msgid="8076142259097187395">"기본 확대/축소"</string>
   <string-array name="pref_default_zoom_choices">
-    <item msgid="549583171195154919">"멀리"</item>
+    <item msgid="549583171195154919">"축소"</item>
     <item msgid="5619034257768161024">"보통"</item>
-    <item msgid="3840999588443167001">"닫기"</item>
+    <item msgid="3840999588443167001">"확대"</item>
   </string-array>
     <string name="pref_default_zoom_dialogtitle" msgid="6095974367125109021">"기본 확대/축소"</string>
-    <string name="pref_content_load_page" msgid="2219810141690955452">"개요에서 페이지 열기"</string>
-    <string name="pref_content_load_page_summary" msgid="8792093504054149369">"새로 연 페이지의 개요 표시"</string>
+    <string name="pref_content_load_page" msgid="2219810141690955452">"페이지 전체보기"</string>
+    <string name="pref_content_load_page_summary" msgid="8792093504054149369">"새 창을 열 때 페이지 전체 표시"</string>
     <string name="pref_extras_title" msgid="3091250467679722382">"고급 설정"</string>
     <string name="pref_extras_website_settings" msgid="67866640052455549">"웹사이트 설정"</string>
-    <string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"개별 웹사이트의 고급 설정 보기"</string>
+    <string name="pref_extras_website_settings_summary" msgid="1656771443223494406">"개별 웹사이트의 고급 설정"</string>
     <string name="pref_extras_reset_default" msgid="8904000515846202110">"기본값으로 재설정"</string>
-    <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"모든 브라우저 데이터를 지우고 모든 설정을 기본값으로 재설정"</string>
-    <string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"모든 브라우저 데이터가 삭제되고 설정이 기본값으로 돌아갑니다."</string>
+    <string name="pref_extras_reset_default_summary" msgid="4247870778270414501">"기본 설정값 복원"</string>
+    <string name="pref_extras_reset_default_dlg" msgid="6640261575874704022">"설정이 기본값으로 되돌아갑니다."</string>
     <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"기본값으로 재설정"</string>
     <string name="pref_development_title" msgid="3263854204533056480">"디버그"</string>
     <string name="pref_default_text_encoding" msgid="5742965543955558478">"텍스트 인코딩"</string>
   <string-array name="pref_default_text_encoding_choices">
     <item msgid="7275223955790513818">"라틴어-1(ISO-8859-1)"</item>
     <item msgid="2456597866837587140">"유니코드(UTF-8)"</item>
-    <item msgid="7143715548814380950">"일본어(ISO-2022-JP)"</item>
-    <item msgid="5111312120564516587">"일본어(SHIFT_JIS)"</item>
-    <item msgid="6545734186479713946">"일본어(EUC-JP)"</item>
+    <item msgid="6122474363777211732">"중국어(GBK)"</item>
+    <item msgid="373372275931607040">"중국어(Big5)"</item>
+    <item msgid="891615911084608570">"일본어(ISO-2022-JP)"</item>
+    <item msgid="5589150448475151241">"일본어(SHIFT_JIS)"</item>
+    <item msgid="7356792686950371843">"일본어(EUC-JP)"</item>
   </string-array>
     <string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"텍스트 인코딩"</string>
-    <string name="pref_default_text_encoding_default" msgid="5272126711231936722">"라틴어-1"</string>
-    <string name="browserFrameRedirect" msgid="7049675479777828343">"리디렉션"</string>
-    <string name="browserFrame307Post" msgid="1429094844669510768">"웹페이지가 리디렉션됩니다. 입력한 양식 데이터를 새 위치로 다시 보내시겠습니까?"</string>
     <string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"데이터 연결에 문제 발생"</string>
     <string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"파일 문제 발생"</string>
     <string name="browserFrameFormResubmitLabel" msgid="2685923472682180360">"확인"</string>
@@ -217,7 +217,7 @@
     <string name="clear_history" msgid="5998307092715979619">"기록 지우기"</string>
     <string name="browser_history" msgid="1038987118290272525">"최근 방문한 페이지"</string>
     <string name="empty_history" msgid="8738772352308207274">"브라우저 기록이 비어 있습니다."</string>
-    <string name="add_new_bookmark" msgid="8086367791400349049">"북마크에 추가..."</string>
+    <string name="add_new_bookmark" msgid="8086367791400349049">"북마크에 추가…"</string>
     <string name="add_bookmark_short" msgid="3783984330998103735">"추가"</string>
     <string name="search_hint" msgid="4647356319916631820">"URL을 검색하거나 입력"</string>
     <string name="search_button_text" msgid="5235226933877634410">"이동"</string>
@@ -234,13 +234,12 @@
     <string name="download_unknown_filename" msgid="4013465542563652175">"&lt;알 수 없음&gt;"</string>
     <string name="download_menu_open" msgid="4888327480367757513">"열기"</string>
     <string name="download_menu_clear" msgid="6264454531553418124">"목록에서 지우기"</string>
+    <string name="download_menu_delete" msgid="8815502136393894148">"삭제"</string>
     <string name="download_menu_cancel" msgid="2545333007601851574">"다운로드 취소"</string>
     <string name="download_menu_cancel_all" msgid="2136550823151999166">"모든 다운로드 취소"</string>
-    <string name="download_menu_clear_all" msgid="7423737413377703862">"목록 지우기"</string>
-    <string name="download_clear_dlg_title" msgid="7961996329529777390">"지우기"</string>
-    <string name="download_clear_dlg_msg" msgid="8056013815679757669">"목록에서 모든 항목이 지워지고 브라우저 캐시에서 삭제됩니다."</string>
     <string name="download_cancel_dlg_title" msgid="8909108500262799748">"다운로드 취소"</string>
     <string name="download_cancel_dlg_msg" msgid="6285389170052357797">"<xliff:g id="DOWNLOAD_COUNT">%d</xliff:g>개의 다운로드가 모두 취소되고 다운로드 기록에서 지워집니다."</string>
+    <string name="download_delete_file" msgid="5330036497843073249">"파일이 삭제됩니다."</string>
     <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>
@@ -248,7 +247,7 @@
     <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>
-    <string name="download_no_application" msgid="5054596425887523234">"이 파일을 열 수 있는 응용프로그램을 찾을 수 없습니다."</string>
+    <string name="download_no_application_title" msgid="1286056729168874295">"파일을 열 수 없음"</string>
     <string name="retry" msgid="1835923075542266721">"다시 시도"</string>
     <string name="no_downloads" msgid="3947445710685021498">"다운로드 기록이 비어 있습니다."</string>
     <string name="download_error" msgid="413496839831257187">"다운로드에 실패했습니다."</string>
@@ -256,18 +255,16 @@
     <string name="download_running" msgid="2622942231322015059">"다운로드 중..."</string>
     <string name="download_pending" msgid="2599683668575349559">"다운로드 시작 중..."</string>
     <string name="download_pending_network" msgid="6548714525679461053">"데이터 연결 대기 중..."</string>
-    <string name="download_running_paused" msgid="6418029352085656495">"데이터 연결을 기다리는 중..."</string>
+    <string name="download_running_paused" msgid="6418029352085656495">"데이터 연결 대기 중..."</string>
     <string name="download_canceled" msgid="6057083743144492515">"다운로드가 취소되었습니다."</string>
     <string name="download_not_acceptable" msgid="313769696131563652">"휴대전화에서 지원하지 않는 콘텐츠이므로 다운로드할 수 없습니다."</string>
     <string name="download_file_error" msgid="1206648050615176113">"저장 용량이 부족하여 다운로드를 완료할 수 없습니다."</string>
     <string name="download_length_required" msgid="9038605488460437406">"항목의 크기를 확인할 수 없으므로 다운로드할 수 없습니다."</string>
     <string name="download_precondition_failed" msgid="8327584102874295580">"다운로드가 중단되었으며 다시 시작할 수 없습니다."</string>
-    <string name="activity_instrumentation_test_runner" msgid="8215091309334005029">"브라우저 테스트 실행기"</string>
     <string name="search_the_web" msgid="6046130189241962337">"웹 검색"</string>
     <string name="webstorage_outofspace_notification_title" msgid="1160474608059771788">"브라우저 저장용량 가득 참"</string>
     <string name="webstorage_outofspace_notification_text" msgid="7341075135051829692">"여유 공간을 확보하려면 클릭하세요."</string>
     <string name="webstorage_clear_data_title" msgid="689484577124333977">"저장된 데이터 삭제"</string>
-    <string name="webstorage_clear_data_summary" msgid="3523128713743907805">"웹사이트에 연결된 모든 데이터베이스 삭제"</string>
     <string name="webstorage_clear_data_dialog_title" msgid="345457466368974706">"저장된 데이터 삭제"</string>
     <string name="webstorage_clear_data_dialog_message" msgid="6678281256970470125">"웹사이트에서 저장한 모든 데이터가 삭제됩니다."</string>
     <string name="webstorage_clear_data_dialog_ok_button" msgid="2516563534211898636">"모두 지우기"</string>
@@ -278,6 +275,8 @@
     <string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"위치 공유"</string>
     <string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"거부"</string>
     <string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"환경설정 저장"</string>
+    <string name="geolocation_permissions_prompt_toast_allowed" msgid="987286072035125498">"사이트에서 현재 위치에 액세스할 수 있습니다. 설정 -&gt; 웹사이트 설정에서 설정을 변경하세요."</string>
+    <string name="geolocation_permissions_prompt_toast_disallowed" msgid="7695100950212692515">"사이트에서 현재 위치에 액세스할 수 없습니다. 설정 -&gt; 웹사이트 설정에서 설정을 변경하세요."</string>
     <string name="geolocation_settings_page_title" msgid="1745477985097536528">"위치 정보 액세스 삭제"</string>
     <string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"사이트에서 사용자의 위치에 현재 액세스할 수 있음"</string>
     <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"사이트에서 사용자의 위치에 현재 액세스할 수 없음"</string>
@@ -290,5 +289,5 @@
     <string name="website_settings_clear_all_dialog_message" msgid="6150502090601476333">"모든 웹사이트 데이터와 위치 권한이 삭제됩니다."</string>
     <string name="website_settings_clear_all_dialog_ok_button" msgid="6401582240627669431">"모든 데이터 삭제"</string>
     <string name="website_settings_clear_all_dialog_cancel_button" msgid="1896757051856611674">"취소"</string>
-    <string name="zoom_overview_button_text" msgid="4146579940085488881">"전체보기"</string>
+    <string name="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"배경화면을 설정하는 중..."</string>
 </resources>
diff --git a/res/values-nb/arrays.xml b/res/values-nb/arrays.xml
deleted file mode 100644
index cbaf8c2..0000000
--- a/res/values-nb/arrays.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="webstorage_quota_entries">
-    <item msgid="5433313236875537673">"Ingen kvote tillatt"</item>
-    <item msgid="7374272188672967690">"5 MB"</item>
-    <item msgid="8699352701856136738">"10 MB"</item>
-    <item msgid="2018822431469084862">"30 MB"</item>
-    <item msgid="5383642976774534074">"100 MB"</item>
-  </string-array>
-  <string-array name="webstorage_quota_entries_values">
-    <item msgid="7620410313725236055">"0"</item>
-    <item msgid="4302688814760304206">"5"</item>
-    <item msgid="7291990205847586165">"10"</item>
-    <item msgid="916913372287112423">"30"</item>
-    <item msgid="3437188301324229987">"100"</item>
-  </string-array>
-</resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 1b4fcb9..f1341cf 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -1,21 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--  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.
--->
+ -->
+
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="1935869255545976415">"Nettleser"</string>
+    <string name="choose_upload" msgid="3649366287575002063">"Velg fil for opplasting"</string>
     <string name="new_tab" msgid="4505722538297295141">"Ny fane"</string>
     <string name="active_tabs" msgid="3050623868203544623">"Vinduer"</string>
     <string name="tab_bookmarks" msgid="2305793036003473653">"Bokmerker"</string>
@@ -58,7 +60,6 @@
     <string name="validity_period" msgid="57988851973181309">"Gyldighet:"</string>
     <string name="issued_on" msgid="2082890654801808368">"Utstedt:"</string>
     <string name="expires_on" msgid="8061200430557020704">"Utløper den:"</string>
-    <string name="retrieving_creds_dlg_msg" msgid="9207671133094039879">"Henter påloggingsinformasjon…"</string>
     <string name="stopping" msgid="4839698519340302982">"Avbryter…"</string>
     <string name="stop" msgid="5687251076030630074">"Avbryt"</string>
     <string name="reload" msgid="8585220783228408062">"Oppdater"</string>
@@ -82,8 +83,8 @@
     <string name="homepage_set" msgid="8768087280310966395">"Startside angitt"</string>
     <string name="bookmark_needs_title" msgid="6245900436119218187">"Bokmerket må ha et navn."</string>
     <string name="bookmark_needs_url" msgid="7809876865972755158">"Bokmerket må ha en adresse."</string>
-    <string name="empty_bookmark" msgid="7008697085928540511">"Kan ikke opprette tomt bokmerke."</string>
     <string name="bookmark_url_not_valid" msgid="6719785633980202419">"Ugyldig nettadresse"</string>
+    <string name="bookmark_cannot_save_url" msgid="791722768778386941">"Kan ikke legge til et bokmerke for denne nettadressen."</string>
     <string name="delete_bookmark" msgid="2422989994934201992">"Slett"</string>
     <string name="bookmark_page" msgid="6845189305130307274">"Bokmerk sist viste side"</string>
     <string name="switch_to_thumbnails" msgid="5493351529609043151">"Miniatyrbildevisning"</string>
@@ -91,18 +92,11 @@
     <string name="current_page" msgid="7510129573681663135">"fra "</string>
     <string name="delete_bookmark_warning" msgid="758043186202032205">"Bokmerket \"<xliff:g id="BOOKMARK">%s</xliff:g>\" vil bli slettet."</string>
     <string name="open_in_new_window" msgid="6596775546468054510">"Åpne i nytt vindu"</string>
-    <string name="new_window" msgid="8117889615360211551">"Nytt vindu"</string>
     <string name="goto_dot" msgid="3895839050522602723">"Gå til"</string>
     <string name="find_dot" msgid="6259312434696611957">"Finn på siden"</string>
     <string name="select_dot" msgid="6299170761900561967">"Velg tekst"</string>
-    <string name="view_tabs" msgid="1119097492003550564">"Vindusoversikt"</string>
-    <string name="view_tabs_condensed" msgid="5803955493821945369">"Vinduer"</string>
     <string name="tab_picker_title" msgid="864478399057782913">"Gjeldende vinduer"</string>
-    <string name="tab_picker_view_tab" msgid="2984342364915347656">"Vis"</string>
-    <string name="tab_picker_new_tab" msgid="3080280018986866528">"Nytt vindu"</string>
     <string name="tab_picker_remove_tab" msgid="630087809802479397">"Lukk"</string>
-    <string name="tab_picker_bookmark" msgid="1084409404198995477">"Legg til bokmerke"</string>
-    <string name="tab_picker_send_url" msgid="9102803487525950021">"Del kobling"</string>
     <string name="bookmarks" msgid="1961279134885867815">"Bokmerker"</string>
     <string name="shortcut_bookmark" msgid="3974876480401135895">"Bokmerk"</string>
     <string name="history" msgid="2451240511251410032">"Logg"</string>
@@ -118,6 +112,7 @@
     <string name="contextmenu_copylink" msgid="5153657160294534270">"Kopier koblingsadresse"</string>
     <string name="contextmenu_download_image" msgid="4243829645180686912">"Lagre bilde"</string>
     <string name="contextmenu_view_image" msgid="3870625602053600905">"Vis bilde"</string>
+    <string name="contextmenu_set_wallpaper" msgid="3691902960115350686">"Bruk som bakgrunn"</string>
     <string name="contextmenu_dial_dot" msgid="5856550683415933806">"Ring…"</string>
     <string name="contextmenu_add_contact" msgid="3183511922223645716">"Legg til kontakt"</string>
     <string name="contextmenu_send_mail" msgid="1014513374828775660">"Send e-post"</string>
@@ -134,8 +129,14 @@
     <string name="pref_content_javascript" msgid="4570972030299516843">"Aktiver JavaScript"</string>
     <string name="pref_content_open_in_background" msgid="824123779725118663">"Åpne i bakgrunnen"</string>
     <string name="pref_content_plugins" msgid="7231944644794301582">"Aktiver utvidelser"</string>
+  <string-array name="pref_content_plugins_choices">
+    <item msgid="6745108155096660725">"Alltid på"</item>
+    <item msgid="2484126708670016519">"Behovsbasert"</item>
+    <item msgid="8547442717307793863">"Av"</item>
+  </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_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>
     <string name="pref_content_landscape_only" msgid="2022546812766219672">"Bare liggende visning"</string>
@@ -190,24 +191,23 @@
     <string name="pref_content_load_page_summary" msgid="8792093504054149369">"Vis oversikt over siden"</string>
     <string name="pref_extras_title" msgid="3091250467679722382">"Avanserte innstillinger"</string>
     <string name="pref_extras_website_settings" msgid="67866640052455549">"Nettstedsinnstillinger"</string>
-    <string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Vis avanserte innstillinger for individuelle nettsteder"</string>
+    <string name="pref_extras_website_settings_summary" msgid="1656771443223494406">"Avanserte innstillinger for individuelle nettsteder"</string>
     <string name="pref_extras_reset_default" msgid="8904000515846202110">"Tilbakestill til standard"</string>
-    <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Fjern alle data fra nettleseren og tilbakestill alle innstillinger til standard"</string>
-    <string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"Alle data vil bli fjernet og innstillinger vil bli tilbakestilt til standardverdier."</string>
+    <string name="pref_extras_reset_default_summary" msgid="4247870778270414501">"Gjenoppretter til standardinnstillinger"</string>
+    <string name="pref_extras_reset_default_dlg" msgid="6640261575874704022">"Tilbakestiller innstillingene til standardverdier."</string>
     <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Tilbakestill til standard"</string>
     <string name="pref_development_title" msgid="3263854204533056480">"Avlusing"</string>
     <string name="pref_default_text_encoding" msgid="5742965543955558478">"Tekstkoding"</string>
   <string-array name="pref_default_text_encoding_choices">
     <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
     <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
-    <item msgid="7143715548814380950">"Japansk (ISO-2022-JP)"</item>
-    <item msgid="5111312120564516587">"Japansk (SHIFT_JIS)"</item>
-    <item msgid="6545734186479713946">"Japansk (EUC-JP)"</item>
+    <item msgid="6122474363777211732">"Kinesisk (GBK)"</item>
+    <item msgid="373372275931607040">"Kinesisk (Big5)"</item>
+    <item msgid="891615911084608570">"Japansk (ISO-2022-JP)"</item>
+    <item msgid="5589150448475151241">"Japansk (SHIFT_JIS)"</item>
+    <item msgid="7356792686950371843">"Japansk (EUC-JP)"</item>
   </string-array>
     <string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Tekstkoding"</string>
-    <string name="pref_default_text_encoding_default" msgid="5272126711231936722">"Latin-1"</string>
-    <string name="browserFrameRedirect" msgid="7049675479777828343">"Videresending"</string>
-    <string name="browserFrame307Post" msgid="1429094844669510768">"Dette nettstedet blir viderekoblet. Send skjemadataene på nytt til det nye nettstedet?"</string>
     <string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Datatilkoblingsproblem"</string>
     <string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Problem med fil"</string>
     <string name="browserFrameFormResubmitLabel" msgid="2685923472682180360">"Bekreft"</string>
@@ -234,13 +234,12 @@
     <string name="download_unknown_filename" msgid="4013465542563652175">"&lt;Ukjent&gt;"</string>
     <string name="download_menu_open" msgid="4888327480367757513">"Åpne"</string>
     <string name="download_menu_clear" msgid="6264454531553418124">"Fjern fra listen"</string>
+    <string name="download_menu_delete" msgid="8815502136393894148">"Slett"</string>
     <string name="download_menu_cancel" msgid="2545333007601851574">"Avbryt nedlasting"</string>
     <string name="download_menu_cancel_all" msgid="2136550823151999166">"Avbryt alle nedlastinger"</string>
-    <string name="download_menu_clear_all" msgid="7423737413377703862">"Tøm listen"</string>
-    <string name="download_clear_dlg_title" msgid="7961996329529777390">"Tøm"</string>
-    <string name="download_clear_dlg_msg" msgid="8056013815679757669">"Alle poster vil bli fjernet fra listen og nettleserens hurtiglager."</string>
     <string name="download_cancel_dlg_title" msgid="8909108500262799748">"Avbryt nedlastinger"</string>
     <string name="download_cancel_dlg_msg" msgid="6285389170052357797">"Alle <xliff:g id="DOWNLOAD_COUNT">%d</xliff:g> nedlastinger vil bli avbrutt og fjernet fra nedlastingsloggen."</string>
+    <string name="download_delete_file" msgid="5330036497843073249">"Filen slettes"</string>
     <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>
@@ -248,7 +247,7 @@
     <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>
-    <string name="download_no_application" msgid="5054596425887523234">"Finner ikke program som kan åpne denne filen."</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>
     <string name="download_error" msgid="413496839831257187">"Nedlasting mislykket."</string>
@@ -262,12 +261,10 @@
     <string name="download_file_error" msgid="1206648050615176113">"Kan ikke fullføre nedlastingen. Det er ikke nok plass."</string>
     <string name="download_length_required" msgid="9038605488460437406">"Kan ikke laste ned. Kan ikke fastsette størrelsen på filen."</string>
     <string name="download_precondition_failed" msgid="8327584102874295580">"Nedlasting avbrutt. Den kan ikke gjenopptas."</string>
-    <string name="activity_instrumentation_test_runner" msgid="8215091309334005029">"Browser Test Runner"</string>
     <string name="search_the_web" msgid="6046130189241962337">"Søk på nettet"</string>
     <string name="webstorage_outofspace_notification_title" msgid="1160474608059771788">"Nettleserlageret er fullt"</string>
     <string name="webstorage_outofspace_notification_text" msgid="7341075135051829692">"Klikk for å frigjøre plass."</string>
     <string name="webstorage_clear_data_title" msgid="689484577124333977">"Fjern lagrede data"</string>
-    <string name="webstorage_clear_data_summary" msgid="3523128713743907805">"Fjern alle databaser tilknyttet dette nettstedet"</string>
     <string name="webstorage_clear_data_dialog_title" msgid="345457466368974706">"Fjern lagrede data"</string>
     <string name="webstorage_clear_data_dialog_message" msgid="6678281256970470125">"Alle data som er lagret av dette nettstedet, vil bli slettet"</string>
     <string name="webstorage_clear_data_dialog_ok_button" msgid="2516563534211898636">"Fjern alle"</string>
@@ -278,6 +275,8 @@
     <string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Del"</string>
     <string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Ikke del"</string>
     <string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Husk"</string>
+    <string name="geolocation_permissions_prompt_toast_allowed" msgid="987286072035125498">"Nettstedet har tilgang til din posisjon. Endre dette i Innstillinger &gt; Nettstedinnstillinger"</string>
+    <string name="geolocation_permissions_prompt_toast_disallowed" msgid="7695100950212692515">"Nettstedet har ikke tilgang til din posisjon. Endre dette i Innstillinger &gt; Nettstedinnstillinger"</string>
     <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Deaktiver posisjonstilgang"</string>
     <string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Dette nettstedet har for tiden tilgang til posisjonen din"</string>
     <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Dette nettstedet har for tiden ikke tilgang til posisjonen din"</string>
@@ -290,5 +289,5 @@
     <string name="website_settings_clear_all_dialog_message" msgid="6150502090601476333">"Alle data fra nettsteder og plasseringstillatelser vil bli slettet."</string>
     <string name="website_settings_clear_all_dialog_ok_button" msgid="6401582240627669431">"Slett alle data"</string>
     <string name="website_settings_clear_all_dialog_cancel_button" msgid="1896757051856611674">"Avbryt"</string>
-    <string name="zoom_overview_button_text" msgid="4146579940085488881">"Oversikt"</string>
+    <string name="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Angir bakgrunn ..."</string>
 </resources>
diff --git a/res/values-nl/arrays.xml b/res/values-nl/arrays.xml
deleted file mode 100644
index 5872a9a..0000000
--- a/res/values-nl/arrays.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="webstorage_quota_entries">
-    <item msgid="5433313236875537673">"Geen maximum toegestaan"</item>
-    <item msgid="7374272188672967690">"5 MB"</item>
-    <item msgid="8699352701856136738">"10 MB"</item>
-    <item msgid="2018822431469084862">"30 MB"</item>
-    <item msgid="5383642976774534074">"100 MB"</item>
-  </string-array>
-  <string-array name="webstorage_quota_entries_values">
-    <item msgid="7620410313725236055">"0"</item>
-    <item msgid="4302688814760304206">"5"</item>
-    <item msgid="7291990205847586165">"10"</item>
-    <item msgid="916913372287112423">"30"</item>
-    <item msgid="3437188301324229987">"100"</item>
-  </string-array>
-</resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 341ebbd..733c33f 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -1,21 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--  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.
--->
+ -->
+
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="1935869255545976415">"Browser"</string>
+    <string name="choose_upload" msgid="3649366287575002063">"Bestand selecteren voor uploaden"</string>
     <string name="new_tab" msgid="4505722538297295141">"Nieuw venster"</string>
     <string name="active_tabs" msgid="3050623868203544623">"Vensters"</string>
     <string name="tab_bookmarks" msgid="2305793036003473653">"Bladwijzers"</string>
@@ -42,7 +44,7 @@
     <string name="page_info_address" msgid="2222306609532903254">"Adres:"</string>
     <string name="ssl_warnings_header" msgid="79744901983636370">"Er zijn problemen met het beveiligingscertificaat van deze site."</string>
     <string name="ssl_continue" msgid="8031515015829358457">"Doorgaan"</string>
-    <string name="security_warning" msgid="6607795404322797541">"Beveiligingswaarschuwing"</string>
+    <string name="security_warning" msgid="6607795404322797541">"Beveiligingsmelding"</string>
     <string name="view_certificate" msgid="1472768887529093862">"Certificaat weergeven"</string>
     <string name="ssl_untrusted" msgid="5369967226521102194">"Dit is geen certificaat van een vertrouwde autoriteit."</string>
     <string name="ssl_mismatch" msgid="558688832420069896">"De naam van deze site komt niet overeen met de naam op het certificaat."</string>
@@ -58,7 +60,6 @@
     <string name="validity_period" msgid="57988851973181309">"Geldigheid:"</string>
     <string name="issued_on" msgid="2082890654801808368">"Uitgegeven op:"</string>
     <string name="expires_on" msgid="8061200430557020704">"Verloopt op:"</string>
-    <string name="retrieving_creds_dlg_msg" msgid="9207671133094039879">"Aanmeldingsgegevens ophalen..."</string>
     <string name="stopping" msgid="4839698519340302982">"Stoppen..."</string>
     <string name="stop" msgid="5687251076030630074">"Stoppen"</string>
     <string name="reload" msgid="8585220783228408062">"Vernieuwen"</string>
@@ -82,8 +83,8 @@
     <string name="homepage_set" msgid="8768087280310966395">"De startpagina is ingesteld."</string>
     <string name="bookmark_needs_title" msgid="6245900436119218187">"Bladwijzer moet een naam hebben."</string>
     <string name="bookmark_needs_url" msgid="7809876865972755158">"Bladwijzers moeten een locatie hebben."</string>
-    <string name="empty_bookmark" msgid="7008697085928540511">"Kan geen lege bladwijzer maken."</string>
     <string name="bookmark_url_not_valid" msgid="6719785633980202419">"URL is ongeldig."</string>
+    <string name="bookmark_cannot_save_url" msgid="791722768778386941">"U kunt geen bladwijzer instellen voor deze URL."</string>
     <string name="delete_bookmark" msgid="2422989994934201992">"Verwijderen"</string>
     <string name="bookmark_page" msgid="6845189305130307274">"Bladwijzer voor laatst weergegeven pagina"</string>
     <string name="switch_to_thumbnails" msgid="5493351529609043151">"Miniatuurweergave"</string>
@@ -91,18 +92,11 @@
     <string name="current_page" msgid="7510129573681663135">"van "</string>
     <string name="delete_bookmark_warning" msgid="758043186202032205">"Bladwijzer \'<xliff:g id="BOOKMARK">%s</xliff:g>\' wordt verwijderd."</string>
     <string name="open_in_new_window" msgid="6596775546468054510">"Openen in een nieuw venster"</string>
-    <string name="new_window" msgid="8117889615360211551">"Nieuw venster"</string>
     <string name="goto_dot" msgid="3895839050522602723">"Ga"</string>
     <string name="find_dot" msgid="6259312434696611957">"Zoeken op pagina"</string>
     <string name="select_dot" msgid="6299170761900561967">"Tekst selecteren"</string>
-    <string name="view_tabs" msgid="1119097492003550564">"Vensteroverzicht"</string>
-    <string name="view_tabs_condensed" msgid="5803955493821945369">"Vensters"</string>
     <string name="tab_picker_title" msgid="864478399057782913">"Huidige vensters"</string>
-    <string name="tab_picker_view_tab" msgid="2984342364915347656">"Weergeven"</string>
-    <string name="tab_picker_new_tab" msgid="3080280018986866528">"Nieuw venster"</string>
     <string name="tab_picker_remove_tab" msgid="630087809802479397">"Sluiten"</string>
-    <string name="tab_picker_bookmark" msgid="1084409404198995477">"Bladwijzer"</string>
-    <string name="tab_picker_send_url" msgid="9102803487525950021">"Link delen"</string>
     <string name="bookmarks" msgid="1961279134885867815">"Bladwijzers"</string>
     <string name="shortcut_bookmark" msgid="3974876480401135895">"Bladwijzer"</string>
     <string name="history" msgid="2451240511251410032">"Geschiedenis"</string>
@@ -118,6 +112,7 @@
     <string name="contextmenu_copylink" msgid="5153657160294534270">"Link-URL kopiëren"</string>
     <string name="contextmenu_download_image" msgid="4243829645180686912">"Afbeelding opslaan"</string>
     <string name="contextmenu_view_image" msgid="3870625602053600905">"Afbeelding weergeven"</string>
+    <string name="contextmenu_set_wallpaper" msgid="3691902960115350686">"Instellen als achtergrond"</string>
     <string name="contextmenu_dial_dot" msgid="5856550683415933806">"Bellen..."</string>
     <string name="contextmenu_add_contact" msgid="3183511922223645716">"Contact toevoegen"</string>
     <string name="contextmenu_send_mail" msgid="1014513374828775660">"E-mail verzenden"</string>
@@ -130,15 +125,21 @@
     <string name="pref_content_title" msgid="722227111894838633">"Instellingen voor pagina-inhoud"</string>
     <string name="pref_content_load_images" msgid="2125616852957377561">"Afbeeldingen laden"</string>
     <string name="pref_content_load_images_summary" msgid="5055874125248398584">"Afbeeldingen op webpagina\'s weergeven"</string>
-    <string name="pref_content_block_popups" msgid="7808433807197256726">"Pop-upvensters blokkeren"</string>
+    <string name="pref_content_block_popups" msgid="7808433807197256726">"Pop-ups blokkeren"</string>
     <string name="pref_content_javascript" msgid="4570972030299516843">"JavaScript inschakelen"</string>
     <string name="pref_content_open_in_background" msgid="824123779725118663">"Openen op de achtergrond"</string>
-    <string name="pref_content_plugins" msgid="7231944644794301582">"Invoegtoepassingen inschakelen"</string>
+    <string name="pref_content_plugins" msgid="7231944644794301582">"Plug-ins inschakelen"</string>
+  <string-array name="pref_content_plugins_choices">
+    <item msgid="6745108155096660725">"Altijd aan"</item>
+    <item msgid="2484126708670016519">"Op aanvraag"</item>
+    <item msgid="8547442717307793863">"Uit"</item>
+  </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_autofit" msgid="8260474534053660809">"Pagina\'s automatisch laten passen"</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>
-    <string name="pref_content_landscape_only" msgid="2022546812766219672">"Alleen liggende weergave"</string>
+    <string name="pref_content_landscape_only" msgid="2022546812766219672">"Altijd liggende weergave"</string>
     <string name="pref_content_landscape_only_summary" msgid="1008238895535428855">"Pagina\'s alleen liggend weergeven"</string>
     <string name="pref_privacy_title" msgid="1052470980370846151">"Privacyinstellingen"</string>
     <string name="pref_privacy_clear_cache" msgid="3380316479925886998">"Cache wissen"</string>
@@ -150,7 +151,7 @@
     <string name="pref_privacy_clear_history" msgid="8723795508825198477">"Geschiedenis wissen"</string>
     <string name="pref_privacy_clear_history_summary" msgid="6868501330708940734">"Navigatiegeschiedenis van de browser wissen"</string>
     <string name="pref_privacy_clear_history_dlg" msgid="544903007914753853">"De navigatiegeschiedenis van de browser wordt gewist."</string>
-    <string name="pref_privacy_clear_form_data" msgid="4232668196344383987">"Formuliergegevens wissen"</string>
+    <string name="pref_privacy_clear_form_data" msgid="4232668196344383987">"Formulierdata wissen"</string>
     <string name="pref_privacy_clear_form_data_summary" msgid="1790390894719517167">"Alle opgeslagen formuliergegevens wissen"</string>
     <string name="pref_privacy_clear_form_data_dlg" msgid="4443621086781197928">"Alle opgeslagen formuliergegevens worden gewist."</string>
     <string name="pref_privacy_clear_passwords" msgid="4750234112289277480">"Wachtwoorden wissen"</string>
@@ -164,7 +165,7 @@
     <string name="pref_security_title" msgid="5763978646932160021">"Beveiligingsinstellingen"</string>
     <string name="pref_security_remember_passwords" msgid="6492957683454529549">"Wachtwoorden onthouden"</string>
     <string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"Gebruikersnamen en wachtwoorden voor websites opslaan"</string>
-    <string name="pref_security_save_form_data" msgid="1213669802810198893">"Gegevens op formulier onthouden"</string>
+    <string name="pref_security_save_form_data" msgid="1213669802810198893">"Formulierdata onthouden"</string>
     <string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"Gegevens die ik typ in formulieren, onthouden voor later gebruik"</string>
     <string name="pref_security_show_security_warning" msgid="8901135676266754559">"Beveiligingswaarschuwingen weergeven"</string>
     <string name="pref_security_show_security_warning_summary" msgid="8968906112720511704">"Waarschuwen als er een beveiligingsprobleem is met een site"</string>
@@ -186,28 +187,27 @@
     <item msgid="3840999588443167001">"Dichtbij"</item>
   </string-array>
     <string name="pref_default_zoom_dialogtitle" msgid="6095974367125109021">"Standaardzoom"</string>
-    <string name="pref_content_load_page" msgid="2219810141690955452">"Pagina\'s openen in overzicht"</string>
+    <string name="pref_content_load_page" msgid="2219810141690955452">"Paginaoverzicht"</string>
     <string name="pref_content_load_page_summary" msgid="8792093504054149369">"Overzicht weergeven van pas geopende pagina\'s"</string>
     <string name="pref_extras_title" msgid="3091250467679722382">"Geavanceerde instellingen"</string>
     <string name="pref_extras_website_settings" msgid="67866640052455549">"Website-instellingen"</string>
-    <string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Geavanceerde instellingen weergeven voor afzonderlijke websites"</string>
-    <string name="pref_extras_reset_default" msgid="8904000515846202110">"Standaardinstellingen herstellen"</string>
-    <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Alle browsergegevens wissen en alle standaardinstellingen herstellen"</string>
-    <string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"Alle browsergegevens worden gewist en de standaardinstellingen worden hersteld."</string>
-    <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Standaardinstellingen herstellen"</string>
+    <string name="pref_extras_website_settings_summary" msgid="1656771443223494406">"Geavanceerde instellingen voor afzonderlijke websites"</string>
+    <string name="pref_extras_reset_default" msgid="8904000515846202110">"Standaardinstellingen"</string>
+    <string name="pref_extras_reset_default_summary" msgid="4247870778270414501">"Standaardinstellingen terugzetten"</string>
+    <string name="pref_extras_reset_default_dlg" msgid="6640261575874704022">"De instellingen worden teruggezet op de standaardwaarden."</string>
+    <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Standaardinstellingen"</string>
     <string name="pref_development_title" msgid="3263854204533056480">"Foutopsporing"</string>
     <string name="pref_default_text_encoding" msgid="5742965543955558478">"Tekstcodering"</string>
   <string-array name="pref_default_text_encoding_choices">
     <item msgid="7275223955790513818">"Latijns-1 (ISO-8859-1)"</item>
     <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
-    <item msgid="7143715548814380950">"Japans (ISO-2022-JP)"</item>
-    <item msgid="5111312120564516587">"Japans (SHIFT_JIS)"</item>
-    <item msgid="6545734186479713946">"Japans (EUC-JP)"</item>
+    <item msgid="6122474363777211732">"Chinees (GBK)"</item>
+    <item msgid="373372275931607040">"Chinees (Big5)"</item>
+    <item msgid="891615911084608570">"Japans (ISO-2022-JP)"</item>
+    <item msgid="5589150448475151241">"Japans (SHIFT_JIS)"</item>
+    <item msgid="7356792686950371843">"Japans (EUC-JP)"</item>
   </string-array>
     <string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Tekstcodering"</string>
-    <string name="pref_default_text_encoding_default" msgid="5272126711231936722">"Latijns-1"</string>
-    <string name="browserFrameRedirect" msgid="7049675479777828343">"Omleiden"</string>
-    <string name="browserFrame307Post" msgid="1429094844669510768">"Deze webpagina wordt omgeleid. Wilt u de ingevulde formuliergegevens doorsturen naar de nieuwe locatie?"</string>
     <string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Probleem met gegevensverbinding"</string>
     <string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Probleem met bestand"</string>
     <string name="browserFrameFormResubmitLabel" msgid="2685923472682180360">"Bevestigen"</string>
@@ -234,13 +234,12 @@
     <string name="download_unknown_filename" msgid="4013465542563652175">"&lt;Onbekend&gt;"</string>
     <string name="download_menu_open" msgid="4888327480367757513">"Openen"</string>
     <string name="download_menu_clear" msgid="6264454531553418124">"Wissen uit lijst"</string>
+    <string name="download_menu_delete" msgid="8815502136393894148">"Verwijderen"</string>
     <string name="download_menu_cancel" msgid="2545333007601851574">"Download annuleren"</string>
     <string name="download_menu_cancel_all" msgid="2136550823151999166">"Alle downloads annuleren"</string>
-    <string name="download_menu_clear_all" msgid="7423737413377703862">"Lijst wissen"</string>
-    <string name="download_clear_dlg_title" msgid="7961996329529777390">"Wissen"</string>
-    <string name="download_clear_dlg_msg" msgid="8056013815679757669">"Alle items worden uit de lijst en uit de browsercache verwijderd."</string>
     <string name="download_cancel_dlg_title" msgid="8909108500262799748">"Downloads annuleren"</string>
     <string name="download_cancel_dlg_msg" msgid="6285389170052357797">"Alle <xliff:g id="DOWNLOAD_COUNT">%d</xliff:g> downloads worden geannuleerd en gewist uit de downloadgeschiedenis."</string>
+    <string name="download_delete_file" msgid="5330036497843073249">"Bestand wordt verwijderd"</string>
     <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>
@@ -248,7 +247,7 @@
     <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>
-    <string name="download_no_application" msgid="5054596425887523234">"Geen toepassing gevonden om dit bestand te openen"</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>
     <string name="download_error" msgid="413496839831257187">"Downloaden is mislukt."</string>
@@ -262,12 +261,10 @@
     <string name="download_file_error" msgid="1206648050615176113">"Kan download niet voltooien. Er is niet genoeg ruimte."</string>
     <string name="download_length_required" msgid="9038605488460437406">"Kan niet downloaden. De grootte van het item kan niet worden vastgesteld."</string>
     <string name="download_precondition_failed" msgid="8327584102874295580">"Download is onderbroken. Deze kan niet worden voortgezet."</string>
-    <string name="activity_instrumentation_test_runner" msgid="8215091309334005029">"Browser Test Runner"</string>
     <string name="search_the_web" msgid="6046130189241962337">"Zoeken op internet"</string>
     <string name="webstorage_outofspace_notification_title" msgid="1160474608059771788">"Browseropslag is vol"</string>
     <string name="webstorage_outofspace_notification_text" msgid="7341075135051829692">"Klik hier om ruimte vrij te maken."</string>
     <string name="webstorage_clear_data_title" msgid="689484577124333977">"Opgeslagen gegevens wissen"</string>
-    <string name="webstorage_clear_data_summary" msgid="3523128713743907805">"Alle databases verwijderen die aan deze website zijn gekoppeld"</string>
     <string name="webstorage_clear_data_dialog_title" msgid="345457466368974706">"Opgeslagen gegevens wissen"</string>
     <string name="webstorage_clear_data_dialog_message" msgid="6678281256970470125">"Alle gegevens die door deze website worden opgeslagen, worden verwijderd"</string>
     <string name="webstorage_clear_data_dialog_ok_button" msgid="2516563534211898636">"Alles wissen"</string>
@@ -278,7 +275,9 @@
     <string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Locatie delen"</string>
     <string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Weigeren"</string>
     <string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Voorkeur onthouden"</string>
-    <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Locatietoegang ongedaan maken"</string>
+    <string name="geolocation_permissions_prompt_toast_allowed" msgid="987286072035125498">"Deze site heeft toegang tot uw locatie. Wijzig dit in \'Instellingen\' -&gt; \'Website-instellingen\'"</string>
+    <string name="geolocation_permissions_prompt_toast_disallowed" msgid="7695100950212692515">"Deze site heeft geen toegang tot uw locatie. Wijzig dit in \'Instellingen\' -&gt; \'Website-instellingen\'"</string>
+    <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Locatietoegang blokk."</string>
     <string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Deze site heeft momenteel toegang tot uw locatie"</string>
     <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Deze site heeft momenteel geen toegang tot uw locatie"</string>
     <string name="geolocation_settings_page_dialog_title" msgid="1549842043381347668">"Locatietoegang ongedaan maken"</string>
@@ -290,5 +289,5 @@
     <string name="website_settings_clear_all_dialog_message" msgid="6150502090601476333">"Alle websitegegevens en locatiemachtigingen worden gewist."</string>
     <string name="website_settings_clear_all_dialog_ok_button" msgid="6401582240627669431">"Alle gegevens wissen"</string>
     <string name="website_settings_clear_all_dialog_cancel_button" msgid="1896757051856611674">"Annuleren"</string>
-    <string name="zoom_overview_button_text" msgid="4146579940085488881">"Overzicht"</string>
+    <string name="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Achtergrond instellen..."</string>
 </resources>
diff --git a/res/values-pl/arrays.xml b/res/values-pl/arrays.xml
deleted file mode 100644
index 2bf9627..0000000
--- a/res/values-pl/arrays.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="webstorage_quota_entries">
-    <item msgid="5433313236875537673">"Brak dozwolonego przydziału"</item>
-    <item msgid="7374272188672967690">"5 MB"</item>
-    <item msgid="8699352701856136738">"10 MB"</item>
-    <item msgid="2018822431469084862">"30 MB"</item>
-    <item msgid="5383642976774534074">"100 MB"</item>
-  </string-array>
-  <string-array name="webstorage_quota_entries_values">
-    <item msgid="7620410313725236055">"0"</item>
-    <item msgid="4302688814760304206">"5"</item>
-    <item msgid="7291990205847586165">"10"</item>
-    <item msgid="916913372287112423">"30"</item>
-    <item msgid="3437188301324229987">"100"</item>
-  </string-array>
-</resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 8af5b8c..a4ccc11 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -1,21 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--  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.
--->
+ -->
+
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="1935869255545976415">"Internet"</string>
+    <string name="choose_upload" msgid="3649366287575002063">"Wybierz plik do przesłania"</string>
     <string name="new_tab" msgid="4505722538297295141">"Nowe okno"</string>
     <string name="active_tabs" msgid="3050623868203544623">"Okna"</string>
     <string name="tab_bookmarks" msgid="2305793036003473653">"Zakładki"</string>
@@ -58,7 +60,6 @@
     <string name="validity_period" msgid="57988851973181309">"Poprawność:"</string>
     <string name="issued_on" msgid="2082890654801808368">"Data wystawienia:"</string>
     <string name="expires_on" msgid="8061200430557020704">"Wygasa:"</string>
-    <string name="retrieving_creds_dlg_msg" msgid="9207671133094039879">"Pobieranie szczegółów logowania…"</string>
     <string name="stopping" msgid="4839698519340302982">"Trwa zatrzymywanie…"</string>
     <string name="stop" msgid="5687251076030630074">"Zatrzymaj"</string>
     <string name="reload" msgid="8585220783228408062">"Odśwież"</string>
@@ -82,8 +83,8 @@
     <string name="homepage_set" msgid="8768087280310966395">"Strona główna została ustawiona."</string>
     <string name="bookmark_needs_title" msgid="6245900436119218187">"Zakładka musi mieć nazwę."</string>
     <string name="bookmark_needs_url" msgid="7809876865972755158">"Zakładka musi zawierać adres."</string>
-    <string name="empty_bookmark" msgid="7008697085928540511">"Nie można utworzyć pustej zakładki."</string>
     <string name="bookmark_url_not_valid" msgid="6719785633980202419">"Adres URL jest nieprawidłowy."</string>
+    <string name="bookmark_cannot_save_url" msgid="791722768778386941">"Nie można dodać tego adresu URL do zakładek."</string>
     <string name="delete_bookmark" msgid="2422989994934201992">"Usuń"</string>
     <string name="bookmark_page" msgid="6845189305130307274">"Dodaj do zakładek ostatnio wyświetlaną stronę"</string>
     <string name="switch_to_thumbnails" msgid="5493351529609043151">"Widok miniatur"</string>
@@ -91,20 +92,13 @@
     <string name="current_page" msgid="7510129573681663135">"z "</string>
     <string name="delete_bookmark_warning" msgid="758043186202032205">"Zakładka „<xliff:g id="BOOKMARK">%s</xliff:g>” zostanie usunięta."</string>
     <string name="open_in_new_window" msgid="6596775546468054510">"Otwórz w nowym oknie"</string>
-    <string name="new_window" msgid="8117889615360211551">"Nowe okno"</string>
     <string name="goto_dot" msgid="3895839050522602723">"Przejdź"</string>
     <string name="find_dot" msgid="6259312434696611957">"Znajdź na stronie"</string>
     <string name="select_dot" msgid="6299170761900561967">"Zaznacz tekst"</string>
-    <string name="view_tabs" msgid="1119097492003550564">"Przegląd okien"</string>
-    <string name="view_tabs_condensed" msgid="5803955493821945369">"Okna"</string>
     <string name="tab_picker_title" msgid="864478399057782913">"Bieżące okna"</string>
-    <string name="tab_picker_view_tab" msgid="2984342364915347656">"Wyświetl"</string>
-    <string name="tab_picker_new_tab" msgid="3080280018986866528">"Nowe okno"</string>
     <string name="tab_picker_remove_tab" msgid="630087809802479397">"Zamknij"</string>
-    <string name="tab_picker_bookmark" msgid="1084409404198995477">"Utwórz zakładkę"</string>
-    <string name="tab_picker_send_url" msgid="9102803487525950021">"Prześlij link"</string>
     <string name="bookmarks" msgid="1961279134885867815">"Zakładki"</string>
-    <string name="shortcut_bookmark" msgid="3974876480401135895">"Utwórz zakładkę"</string>
+    <string name="shortcut_bookmark" msgid="3974876480401135895">"Zakładka"</string>
     <string name="history" msgid="2451240511251410032">"Historia"</string>
     <string name="menu_view_download" msgid="2124570321712995120">"Pobrane pliki"</string>
     <string name="copy_page_url" msgid="7635062169011319208">"Kopiuj adres URL strony"</string>
@@ -118,33 +112,40 @@
     <string name="contextmenu_copylink" msgid="5153657160294534270">"Kopiuj adres URL linku"</string>
     <string name="contextmenu_download_image" msgid="4243829645180686912">"Zapisz obraz"</string>
     <string name="contextmenu_view_image" msgid="3870625602053600905">"Wyświetl obraz"</string>
+    <string name="contextmenu_set_wallpaper" msgid="3691902960115350686">"Ustaw jako tapetę"</string>
     <string name="contextmenu_dial_dot" msgid="5856550683415933806">"Wybierz numer…"</string>
     <string name="contextmenu_add_contact" msgid="3183511922223645716">"Dodaj kontakt"</string>
     <string name="contextmenu_send_mail" msgid="1014513374828775660">"Wyślij e-mail"</string>
     <string name="contextmenu_map" msgid="7471390435434034912">"Mapa"</string>
-    <string name="choosertitle_sharevia" msgid="4600490613341909086">"Udostępnij za pośrednictwem"</string>
+    <string name="choosertitle_sharevia" msgid="4600490613341909086">"Udostępnij przez"</string>
     <string name="clear" msgid="7070043081700011461">"Wyczyść"</string>
     <string name="replace" msgid="4843033491070384047">"Zastąp adres"</string>
     <string name="browser_bookmarks_page_bookmarks_text" msgid="6787605028726162673">"Zakładki"</string>
     <string name="menu_preferences" msgid="6709237687234102240">"Ustawienia"</string>
     <string name="pref_content_title" msgid="722227111894838633">"Ustawienia zawartości stron"</string>
     <string name="pref_content_load_images" msgid="2125616852957377561">"Wczytuj obrazy"</string>
-    <string name="pref_content_load_images_summary" msgid="5055874125248398584">"Wyświetlaj grafiki na stronach internetowych"</string>
+    <string name="pref_content_load_images_summary" msgid="5055874125248398584">"Wyświetlaj obrazy na stronach internetowych"</string>
     <string name="pref_content_block_popups" msgid="7808433807197256726">"Blokuj wyskakujące okna"</string>
     <string name="pref_content_javascript" msgid="4570972030299516843">"Włącz skrypty JavaScript"</string>
-    <string name="pref_content_open_in_background" msgid="824123779725118663">"Otwórz w tle"</string>
-    <string name="pref_content_plugins" msgid="7231944644794301582">"Włącz wtyczki"</string>
+    <string name="pref_content_open_in_background" msgid="824123779725118663">"Otwieraj w tle"</string>
+    <string name="pref_content_plugins" msgid="7231944644794301582">"Obsługa wtyczek"</string>
+  <string-array name="pref_content_plugins_choices">
+    <item msgid="6745108155096660725">"Zawsze włączona"</item>
+    <item msgid="2484126708670016519">"Na żądanie"</item>
+    <item msgid="8547442717307793863">"Wyłączona"</item>
+  </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_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>
-    <string name="pref_content_landscape_only" msgid="2022546812766219672">"Zawsze w orientacji poziomej"</string>
+    <string name="pref_content_landscape_only" msgid="2022546812766219672">"Zawsze w poziomie"</string>
     <string name="pref_content_landscape_only_summary" msgid="1008238895535428855">"Wyświetlaj strony tylko w szerszej, poziomej orientacji ekranu"</string>
     <string name="pref_privacy_title" msgid="1052470980370846151">"Ustawienia prywatności"</string>
     <string name="pref_privacy_clear_cache" msgid="3380316479925886998">"Wyczyść pamięć podręczną"</string>
     <string name="pref_privacy_clear_cache_summary" msgid="2216463577207991454">"Wyczyść zawartość lokalnej pamięci podręcznej i baz danych"</string>
     <string name="pref_privacy_clear_cache_dlg" msgid="5541011591300753881">"Zawartość lokalnej pamięci podręcznej i baz danych zostanie usunięta."</string>
-    <string name="pref_privacy_clear_cookies" msgid="3095583579133780331">"Wyczyść wszystkie pliki cookie"</string>
+    <string name="pref_privacy_clear_cookies" msgid="3095583579133780331">"Wyczyść pliki cookie"</string>
     <string name="pref_privacy_clear_cookies_summary" msgid="6962742063990677520">"Wyczyść wszystkie pliki cookie przeglądarki"</string>
     <string name="pref_privacy_clear_cookies_dlg" msgid="552855688091432682">"Wszystkie pliki cookie zostaną usunięte."</string>
     <string name="pref_privacy_clear_history" msgid="8723795508825198477">"Wyczyść historię"</string>
@@ -159,7 +160,7 @@
     <string name="pref_privacy_enable_geolocation" msgid="1395040170290765686">"Włącz obsługę lokalizacji"</string>
     <string name="pref_privacy_enable_geolocation_summary" msgid="8437020934664306205">"Zezwalaj witrynom na żądanie dostępu do informacji o lokalizacji"</string>
     <string name="pref_privacy_clear_geolocation_access" msgid="6649680770030042980">"Wyczyść dostęp do informacji o lokalizacji"</string>
-    <string name="pref_privacy_clear_geolocation_access_summary" msgid="7750143359497314679">"Usuń dostęp wszystkich witryn do informacji o lokalizacji"</string>
+    <string name="pref_privacy_clear_geolocation_access_summary" msgid="7750143359497314679">"Usuń ustawienia dostępu do informacji o lokalizacji dla witryn"</string>
     <string name="pref_privacy_clear_geolocation_access_dlg" msgid="7327063124488827244">"Wyczyść ustawienia dostępu witryn do informacji o lokalizacji"</string>
     <string name="pref_security_title" msgid="5763978646932160021">"Ustawienia zabezpieczeń"</string>
     <string name="pref_security_remember_passwords" msgid="6492957683454529549">"Pamiętaj hasła"</string>
@@ -189,25 +190,24 @@
     <string name="pref_content_load_page" msgid="2219810141690955452">"Otwieraj strony w widoku ogólnym"</string>
     <string name="pref_content_load_page_summary" msgid="8792093504054149369">"Pokaż przegląd nowo otwartych stron"</string>
     <string name="pref_extras_title" msgid="3091250467679722382">"Ustawienia zaawansowane"</string>
-    <string name="pref_extras_website_settings" msgid="67866640052455549">"Ustawienia witryny"</string>
-    <string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Wyświetl ustawienia zaawansowane dla poszczególnych witryn"</string>
+    <string name="pref_extras_website_settings" msgid="67866640052455549">"Ustawienia witryn"</string>
+    <string name="pref_extras_website_settings_summary" msgid="1656771443223494406">"Ustawienia zaawansowane dla poszczególnych witryn"</string>
     <string name="pref_extras_reset_default" msgid="8904000515846202110">"Przywróć wartości domyślne"</string>
-    <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Wyczyść wszystkie dane przeglądarki i przywróć wszystkie ustawienia domyślne"</string>
-    <string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"Wszystkie dane przeglądarki zostaną usunięte i zostaną przywrócone wartości domyślne ustawień."</string>
+    <string name="pref_extras_reset_default_summary" msgid="4247870778270414501">"Przywróć ustawienia domyślne"</string>
+    <string name="pref_extras_reset_default_dlg" msgid="6640261575874704022">"Zostaną przywrócone wartości domyślne ustawień."</string>
     <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Przywróć wartości domyślne"</string>
     <string name="pref_development_title" msgid="3263854204533056480">"Debugowanie"</string>
     <string name="pref_default_text_encoding" msgid="5742965543955558478">"Kodowanie tekstu"</string>
   <string-array name="pref_default_text_encoding_choices">
     <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
     <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
-    <item msgid="7143715548814380950">"Japoński (ISO-2022-JP)"</item>
-    <item msgid="5111312120564516587">"Japoński (SHIFT_JIS)"</item>
-    <item msgid="6545734186479713946">"Japoński (EUC-JP)"</item>
+    <item msgid="6122474363777211732">"chiński (GBK)"</item>
+    <item msgid="373372275931607040">"chiński (Big5)"</item>
+    <item msgid="891615911084608570">"japoński (ISO-2022-JP)"</item>
+    <item msgid="5589150448475151241">"japoński (SHIFT_JIS)"</item>
+    <item msgid="7356792686950371843">"japoński (EUC-JP)"</item>
   </string-array>
     <string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Kodowanie tekstu"</string>
-    <string name="pref_default_text_encoding_default" msgid="5272126711231936722">"Latin-1"</string>
-    <string name="browserFrameRedirect" msgid="7049675479777828343">"Przekieruj"</string>
-    <string name="browserFrame307Post" msgid="1429094844669510768">"Trwa przekierowywanie tej strony internetowej. Czy ponownie wysłać wpisane dane formularza do nowej lokalizacji?"</string>
     <string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Problem z łącznością danych"</string>
     <string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Problem z plikiem"</string>
     <string name="browserFrameFormResubmitLabel" msgid="2685923472682180360">"Potwierdzenie"</string>
@@ -219,7 +219,7 @@
     <string name="empty_history" msgid="8738772352308207274">"Historia przeglądarki jest pusta."</string>
     <string name="add_new_bookmark" msgid="8086367791400349049">"Dodaj do zakładek..."</string>
     <string name="add_bookmark_short" msgid="3783984330998103735">"Dodaj"</string>
-    <string name="search_hint" msgid="4647356319916631820">"Wyszukaj lub wpisz adres URL"</string>
+    <string name="search_hint" msgid="4647356319916631820">"Wyszukaj lub wpisz URL"</string>
     <string name="search_button_text" msgid="5235226933877634410">"Otwórz"</string>
     <string name="search_settings_description" msgid="1422401062529014107">"Zakładki i historia przeglądanych zasobów sieciowych"</string>
     <string name="attention" msgid="3473639060042811244">"Uwaga"</string>
@@ -234,13 +234,12 @@
     <string name="download_unknown_filename" msgid="4013465542563652175">"&lt;Nieznane&gt;"</string>
     <string name="download_menu_open" msgid="4888327480367757513">"Otwórz"</string>
     <string name="download_menu_clear" msgid="6264454531553418124">"Usuń z listy"</string>
+    <string name="download_menu_delete" msgid="8815502136393894148">"Usuń"</string>
     <string name="download_menu_cancel" msgid="2545333007601851574">"Anuluj pobieranie"</string>
     <string name="download_menu_cancel_all" msgid="2136550823151999166">"Anuluj pobieranie wszystkich plików"</string>
-    <string name="download_menu_clear_all" msgid="7423737413377703862">"Wyczyść listę"</string>
-    <string name="download_clear_dlg_title" msgid="7961996329529777390">"Wyczyść"</string>
-    <string name="download_clear_dlg_msg" msgid="8056013815679757669">"Wszystkie pozycje zostaną usunięte z listy i z pamięci podręcznej przeglądarki."</string>
     <string name="download_cancel_dlg_title" msgid="8909108500262799748">"Anuluj wszystkie pobierania"</string>
     <string name="download_cancel_dlg_msg" msgid="6285389170052357797">"Wszystkie pobierane pliki (<xliff:g id="DOWNLOAD_COUNT">%d</xliff:g>) zostaną anulowane i usunięte z historii pobierania."</string>
+    <string name="download_delete_file" msgid="5330036497843073249">"Plik zostanie usunięty"</string>
     <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>
@@ -248,7 +247,7 @@
     <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>
-    <string name="download_no_application" msgid="5054596425887523234">"Nie można znaleźć pliku do otwarcia tego programu."</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>
     <string name="download_error" msgid="413496839831257187">"Pobieranie nie powiodło się."</string>
@@ -262,12 +261,10 @@
     <string name="download_file_error" msgid="1206648050615176113">"Nie można ukończyć pobierania. Za mało miejsca."</string>
     <string name="download_length_required" msgid="9038605488460437406">"Pobieranie niemożliwe. Nie można ustalić rozmiaru elementu."</string>
     <string name="download_precondition_failed" msgid="8327584102874295580">"Pobieranie zostało przerwane. Nie można go wznowić."</string>
-    <string name="activity_instrumentation_test_runner" msgid="8215091309334005029">"Uruchamianie testów przeglądarki"</string>
     <string name="search_the_web" msgid="6046130189241962337">"Szukaj w internecie"</string>
     <string name="webstorage_outofspace_notification_title" msgid="1160474608059771788">"Pamięć przeglądarki jest pełna"</string>
     <string name="webstorage_outofspace_notification_text" msgid="7341075135051829692">"Kliknij, aby zwolnić miejsce."</string>
     <string name="webstorage_clear_data_title" msgid="689484577124333977">"Wyczyść zapisane dane"</string>
-    <string name="webstorage_clear_data_summary" msgid="3523128713743907805">"Usuń wszystkie bazy danych powiązane z tą witryną"</string>
     <string name="webstorage_clear_data_dialog_title" msgid="345457466368974706">"Wyczyść zapisane dane"</string>
     <string name="webstorage_clear_data_dialog_message" msgid="6678281256970470125">"Wszystkie dane zapisane przez tę witrynę zostaną usunięte"</string>
     <string name="webstorage_clear_data_dialog_ok_button" msgid="2516563534211898636">"Wyczyść wszystko"</string>
@@ -278,6 +275,8 @@
     <string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Udostępnij informacje o lokalizacji"</string>
     <string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Odrzuć"</string>
     <string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Zapamiętaj ustawienie"</string>
+    <string name="geolocation_permissions_prompt_toast_allowed" msgid="987286072035125498">"Ta witryna może uzyskać dostęp do informacji o Twojej lokalizacji. Zmień to ustawienie w menu Ustawienia -&gt; Ustawienia witryn."</string>
+    <string name="geolocation_permissions_prompt_toast_disallowed" msgid="7695100950212692515">"Ta witryna nie może uzyskać dostępu do informacji o Twojej lokalizacji. Zmień to ustawienie w menu Ustawienia -&gt; Ustawienia witryn."</string>
     <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Wyczyść dostęp do informacji o lokalizacji"</string>
     <string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Ta witryna ma obecnie dostęp do informacji o Twojej lokalizacji"</string>
     <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Ta witryna nie ma obecnie dostępu do informacji o Twojej lokalizacji"</string>
@@ -290,5 +289,5 @@
     <string name="website_settings_clear_all_dialog_message" msgid="6150502090601476333">"Wszystkie dane witryn i uprawnienia do lokalizacji zostaną usunięte."</string>
     <string name="website_settings_clear_all_dialog_ok_button" msgid="6401582240627669431">"Usuń wszystkie dane"</string>
     <string name="website_settings_clear_all_dialog_cancel_button" msgid="1896757051856611674">"Anuluj"</string>
-    <string name="zoom_overview_button_text" msgid="4146579940085488881">"Widok ogólny"</string>
+    <string name="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Trwa ustawianie tapety..."</string>
 </resources>
diff --git a/res/values-pt-rPT/arrays.xml b/res/values-pt-rPT/arrays.xml
deleted file mode 100644
index 7f3d759..0000000
--- a/res/values-pt-rPT/arrays.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="webstorage_quota_entries">
-    <item msgid="5433313236875537673">"Nenhuma quota permitida"</item>
-    <item msgid="7374272188672967690">"5 MB"</item>
-    <item msgid="8699352701856136738">"10 MB"</item>
-    <item msgid="2018822431469084862">"30 MB"</item>
-    <item msgid="5383642976774534074">"100 MB"</item>
-  </string-array>
-  <string-array name="webstorage_quota_entries_values">
-    <item msgid="7620410313725236055">"0"</item>
-    <item msgid="4302688814760304206">"5"</item>
-    <item msgid="7291990205847586165">"10"</item>
-    <item msgid="916913372287112423">"30"</item>
-    <item msgid="3437188301324229987">"100"</item>
-  </string-array>
-</resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index aa0fcd6..dd3bc92 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -1,21 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--  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.
--->
+ -->
+
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="application_name" msgid="1935869255545976415">"Browser"</string>
+    <string name="application_name" msgid="1935869255545976415">"Navegad."</string>
+    <string name="choose_upload" msgid="3649366287575002063">"Escolher ficheiro a carregar"</string>
     <string name="new_tab" msgid="4505722538297295141">"Nova janela"</string>
     <string name="active_tabs" msgid="3050623868203544623">"Janelas"</string>
     <string name="tab_bookmarks" msgid="2305793036003473653">"Marcadores"</string>
@@ -27,7 +29,7 @@
     <string name="username" msgid="5057566336518215922">"Nome"</string>
     <string name="password" msgid="1177138552305184404">"Palavra-passe"</string>
     <string name="action" msgid="183105774472071343">"Iniciar sessão"</string>
-    <string name="bookmarks_search" msgid="5229596268214362873">"Browser"</string>
+    <string name="bookmarks_search" msgid="5229596268214362873">"Navegad."</string>
     <string name="cancel" msgid="3017274947407233702">"Cancelar"</string>
     <string name="ok" msgid="1509280796718850364">"OK"</string>
   <plurals name="matches_found">
@@ -58,7 +60,6 @@
     <string name="validity_period" msgid="57988851973181309">"Validade:"</string>
     <string name="issued_on" msgid="2082890654801808368">"Emitido em:"</string>
     <string name="expires_on" msgid="8061200430557020704">"Expira em:"</string>
-    <string name="retrieving_creds_dlg_msg" msgid="9207671133094039879">"A obter detalhes de início de sessão..."</string>
     <string name="stopping" msgid="4839698519340302982">"A interromper..."</string>
     <string name="stop" msgid="5687251076030630074">"Parar"</string>
     <string name="reload" msgid="8585220783228408062">"Actualizar"</string>
@@ -82,8 +83,8 @@
     <string name="homepage_set" msgid="8768087280310966395">"Página inicial definida."</string>
     <string name="bookmark_needs_title" msgid="6245900436119218187">"Os marcadores têm de ter um nome."</string>
     <string name="bookmark_needs_url" msgid="7809876865972755158">"O marcador tem de ter uma localização."</string>
-    <string name="empty_bookmark" msgid="7008697085928540511">"Não é possível criar um marcador vazio."</string>
     <string name="bookmark_url_not_valid" msgid="6719785633980202419">"O URL não é válido."</string>
+    <string name="bookmark_cannot_save_url" msgid="791722768778386941">"Este URL não pode ser adicionado aos marcadores."</string>
     <string name="delete_bookmark" msgid="2422989994934201992">"Eliminar"</string>
     <string name="bookmark_page" msgid="6845189305130307274">"Adicionar aos marcadores a última página visualizada"</string>
     <string name="switch_to_thumbnails" msgid="5493351529609043151">"Vista de miniatura"</string>
@@ -91,18 +92,11 @@
     <string name="current_page" msgid="7510129573681663135">"de "</string>
     <string name="delete_bookmark_warning" msgid="758043186202032205">"O marcador \"<xliff:g id="BOOKMARK">%s</xliff:g>\" será eliminado."</string>
     <string name="open_in_new_window" msgid="6596775546468054510">"Abrir numa janela nova"</string>
-    <string name="new_window" msgid="8117889615360211551">"Nova janela"</string>
     <string name="goto_dot" msgid="3895839050522602723">"Ir"</string>
     <string name="find_dot" msgid="6259312434696611957">"Encontrar na página"</string>
     <string name="select_dot" msgid="6299170761900561967">"Seleccionar texto"</string>
-    <string name="view_tabs" msgid="1119097492003550564">"Visão geral das janelas"</string>
-    <string name="view_tabs_condensed" msgid="5803955493821945369">"Janelas"</string>
     <string name="tab_picker_title" msgid="864478399057782913">"Janelas actuais"</string>
-    <string name="tab_picker_view_tab" msgid="2984342364915347656">"Ver"</string>
-    <string name="tab_picker_new_tab" msgid="3080280018986866528">"Nova janela"</string>
     <string name="tab_picker_remove_tab" msgid="630087809802479397">"Fechar"</string>
-    <string name="tab_picker_bookmark" msgid="1084409404198995477">"Adicionar aos marcadores"</string>
-    <string name="tab_picker_send_url" msgid="9102803487525950021">"Partilhar link"</string>
     <string name="bookmarks" msgid="1961279134885867815">"Marcadores"</string>
     <string name="shortcut_bookmark" msgid="3974876480401135895">"Marcador"</string>
     <string name="history" msgid="2451240511251410032">"Histórico"</string>
@@ -118,6 +112,7 @@
     <string name="contextmenu_copylink" msgid="5153657160294534270">"Copiar URL do link"</string>
     <string name="contextmenu_download_image" msgid="4243829645180686912">"Guardar imagem"</string>
     <string name="contextmenu_view_image" msgid="3870625602053600905">"Ver imagem"</string>
+    <string name="contextmenu_set_wallpaper" msgid="3691902960115350686">"Definir como imagem de fundo"</string>
     <string name="contextmenu_dial_dot" msgid="5856550683415933806">"Marcar..."</string>
     <string name="contextmenu_add_contact" msgid="3183511922223645716">"Adicionar contacto"</string>
     <string name="contextmenu_send_mail" msgid="1014513374828775660">"Enviar e-mail"</string>
@@ -134,8 +129,14 @@
     <string name="pref_content_javascript" msgid="4570972030299516843">"Activar JavaScript"</string>
     <string name="pref_content_open_in_background" msgid="824123779725118663">"Abrir em segundo plano"</string>
     <string name="pref_content_plugins" msgid="7231944644794301582">"Activar plug-ins"</string>
+  <string-array name="pref_content_plugins_choices">
+    <item msgid="6745108155096660725">"Sempre ligado"</item>
+    <item msgid="2484126708670016519">"A pedido"</item>
+    <item msgid="8547442717307793863">"Desligado"</item>
+  </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_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>
     <string name="pref_content_landscape_only" msgid="2022546812766219672">"Apresentação apenas na horizontal"</string>
@@ -190,24 +191,23 @@
     <string name="pref_content_load_page_summary" msgid="8792093504054149369">"Mostrar descrição geral de páginas abertas recentemente"</string>
     <string name="pref_extras_title" msgid="3091250467679722382">"Definições avançadas"</string>
     <string name="pref_extras_website_settings" msgid="67866640052455549">"Definições de Web site"</string>
-    <string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Ver definições avançadas para Web sites individuais"</string>
+    <string name="pref_extras_website_settings_summary" msgid="1656771443223494406">"Definições avançadas para Web sites individuais"</string>
     <string name="pref_extras_reset_default" msgid="8904000515846202110">"Repor as predefinições"</string>
-    <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Limpar todos os dados do browser e repor todas as predefinições"</string>
-    <string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"Todos os dados do browser serão eliminados e as definições assumirão os valores predefinidos."</string>
+    <string name="pref_extras_reset_default_summary" msgid="4247870778270414501">"Restaurar predefinições"</string>
+    <string name="pref_extras_reset_default_dlg" msgid="6640261575874704022">"As definições assumirão os valores predefinidos."</string>
     <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Repor as predefinições"</string>
     <string name="pref_development_title" msgid="3263854204533056480">"Depuração"</string>
     <string name="pref_default_text_encoding" msgid="5742965543955558478">"Codificação do texto"</string>
   <string-array name="pref_default_text_encoding_choices">
     <item msgid="7275223955790513818">"Latim-1 (ISO-8859-1)"</item>
     <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
-    <item msgid="7143715548814380950">"Japonês (ISO-2022-JP)"</item>
-    <item msgid="5111312120564516587">"Japonês (SHIFT_JIS)"</item>
-    <item msgid="6545734186479713946">"Japonês (EUC-JP)"</item>
+    <item msgid="6122474363777211732">"Chinês (GBK)"</item>
+    <item msgid="373372275931607040">"Chinês (Big5)"</item>
+    <item msgid="891615911084608570">"Japonês (ISO-2022-JP)"</item>
+    <item msgid="5589150448475151241">"Japonês (SHIFT_JIS)"</item>
+    <item msgid="7356792686950371843">"Japonês (EUC-JP)"</item>
   </string-array>
     <string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Codificação do texto"</string>
-    <string name="pref_default_text_encoding_default" msgid="5272126711231936722">"Latim-1"</string>
-    <string name="browserFrameRedirect" msgid="7049675479777828343">"Redireccionar"</string>
-    <string name="browserFrame307Post" msgid="1429094844669510768">"Esta página Web está a ser redireccionada. Pretende reenviar os dados de formulário introduzidos para a nova localização?"</string>
     <string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Problema de conectividade de dados"</string>
     <string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Problemas com o ficheiro"</string>
     <string name="browserFrameFormResubmitLabel" msgid="2685923472682180360">"Confirmar"</string>
@@ -234,13 +234,12 @@
     <string name="download_unknown_filename" msgid="4013465542563652175">"&lt;Desconhecido&gt;"</string>
     <string name="download_menu_open" msgid="4888327480367757513">"Abrir"</string>
     <string name="download_menu_clear" msgid="6264454531553418124">"Limpar da lista"</string>
+    <string name="download_menu_delete" msgid="8815502136393894148">"Eliminar"</string>
     <string name="download_menu_cancel" msgid="2545333007601851574">"Cancelar transferência"</string>
     <string name="download_menu_cancel_all" msgid="2136550823151999166">"Cancelar todas as transferências"</string>
-    <string name="download_menu_clear_all" msgid="7423737413377703862">"Limpar lista"</string>
-    <string name="download_clear_dlg_title" msgid="7961996329529777390">"Limpar"</string>
-    <string name="download_clear_dlg_msg" msgid="8056013815679757669">"Todos os itens serão limpos da lista e removidos da cache do browser."</string>
     <string name="download_cancel_dlg_title" msgid="8909108500262799748">"Cancelar transferências"</string>
     <string name="download_cancel_dlg_msg" msgid="6285389170052357797">"As <xliff:g id="DOWNLOAD_COUNT">%d</xliff:g> transferências serão canceladas e limpas do histórico de transferências."</string>
+    <string name="download_delete_file" msgid="5330036497843073249">"O ficheiro será eliminado"</string>
     <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>
@@ -248,7 +247,7 @@
     <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>
-    <string name="download_no_application" msgid="5054596425887523234">"Nenhuma aplicação encontrada para abrir este ficheiro."</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>
     <string name="download_error" msgid="413496839831257187">"Falha na transferência."</string>
@@ -262,12 +261,10 @@
     <string name="download_file_error" msgid="1206648050615176113">"Não é possível concluir a transferência. Não existe espaço suficiente."</string>
     <string name="download_length_required" msgid="9038605488460437406">"Não é possível transferir porque o tamanho do item é indeterminado."</string>
     <string name="download_precondition_failed" msgid="8327584102874295580">"A transferência foi interrompida e não pode ser retomada."</string>
-    <string name="activity_instrumentation_test_runner" msgid="8215091309334005029">"Teste de browser"</string>
     <string name="search_the_web" msgid="6046130189241962337">"Pesquisar na Web"</string>
     <string name="webstorage_outofspace_notification_title" msgid="1160474608059771788">"Espaço de armazenamento do browser cheio"</string>
     <string name="webstorage_outofspace_notification_text" msgid="7341075135051829692">"Clique para libertar espaço."</string>
     <string name="webstorage_clear_data_title" msgid="689484577124333977">"Limpar dados armazenados"</string>
-    <string name="webstorage_clear_data_summary" msgid="3523128713743907805">"Remover todas as bases de dados associadas a este Web site"</string>
     <string name="webstorage_clear_data_dialog_title" msgid="345457466368974706">"Limpar dados armazenados"</string>
     <string name="webstorage_clear_data_dialog_message" msgid="6678281256970470125">"Todos os dados armazenados por este Web site serão limpos"</string>
     <string name="webstorage_clear_data_dialog_ok_button" msgid="2516563534211898636">"Limpar tudo"</string>
@@ -278,6 +275,8 @@
     <string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Partilhar localização"</string>
     <string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Recusar"</string>
     <string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Memorizar preferência"</string>
+    <string name="geolocation_permissions_prompt_toast_allowed" msgid="987286072035125498">"Este site tem acesso à sua localização. Altere esta definição em Definições -&gt; Definições do Web site"</string>
+    <string name="geolocation_permissions_prompt_toast_disallowed" msgid="7695100950212692515">"Este site não tem acesso à sua localização. Altere esta definição em Definições -&gt; Definições do Web site"</string>
     <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Limpar acesso à localização"</string>
     <string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Actualmente este site pode aceder à sua localização"</string>
     <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Actualmente este site não pode aceder à sua localização"</string>
@@ -290,5 +289,5 @@
     <string name="website_settings_clear_all_dialog_message" msgid="6150502090601476333">"Todos os dados do Web site e permissões de localização serão eliminados."</string>
     <string name="website_settings_clear_all_dialog_ok_button" msgid="6401582240627669431">"Eliminar todos os dados"</string>
     <string name="website_settings_clear_all_dialog_cancel_button" msgid="1896757051856611674">"Cancelar"</string>
-    <string name="zoom_overview_button_text" msgid="4146579940085488881">"Visão geral"</string>
+    <string name="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"A definir imagem de fundo..."</string>
 </resources>
diff --git a/res/values-pt/arrays.xml b/res/values-pt/arrays.xml
deleted file mode 100644
index 7f3d759..0000000
--- a/res/values-pt/arrays.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="webstorage_quota_entries">
-    <item msgid="5433313236875537673">"Nenhuma quota permitida"</item>
-    <item msgid="7374272188672967690">"5 MB"</item>
-    <item msgid="8699352701856136738">"10 MB"</item>
-    <item msgid="2018822431469084862">"30 MB"</item>
-    <item msgid="5383642976774534074">"100 MB"</item>
-  </string-array>
-  <string-array name="webstorage_quota_entries_values">
-    <item msgid="7620410313725236055">"0"</item>
-    <item msgid="4302688814760304206">"5"</item>
-    <item msgid="7291990205847586165">"10"</item>
-    <item msgid="916913372287112423">"30"</item>
-    <item msgid="3437188301324229987">"100"</item>
-  </string-array>
-</resources>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 1b0ca0a..2e9f8a8 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -1,21 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--  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.
--->
+ -->
+
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="1935869255545976415">"Navegador"</string>
+    <string name="choose_upload" msgid="3649366287575002063">"Escolha o arquivo para envio"</string>
     <string name="new_tab" msgid="4505722538297295141">"Nova janela"</string>
     <string name="active_tabs" msgid="3050623868203544623">"Janelas"</string>
     <string name="tab_bookmarks" msgid="2305793036003473653">"Favoritos"</string>
@@ -58,7 +60,6 @@
     <string name="validity_period" msgid="57988851973181309">"Validade:"</string>
     <string name="issued_on" msgid="2082890654801808368">"Emitido em:"</string>
     <string name="expires_on" msgid="8061200430557020704">"Expira em:"</string>
-    <string name="retrieving_creds_dlg_msg" msgid="9207671133094039879">"Recuperando detalhes do login…"</string>
     <string name="stopping" msgid="4839698519340302982">"Parando…"</string>
     <string name="stop" msgid="5687251076030630074">"Parar"</string>
     <string name="reload" msgid="8585220783228408062">"Atualizar"</string>
@@ -82,8 +83,8 @@
     <string name="homepage_set" msgid="8768087280310966395">"Página inicial definida."</string>
     <string name="bookmark_needs_title" msgid="6245900436119218187">"O favorito precisa ter um nome."</string>
     <string name="bookmark_needs_url" msgid="7809876865972755158">"O favorito precisa ter um local."</string>
-    <string name="empty_bookmark" msgid="7008697085928540511">"Não é possível criar um favorito vazio."</string>
     <string name="bookmark_url_not_valid" msgid="6719785633980202419">"O URL não é válido."</string>
+    <string name="bookmark_cannot_save_url" msgid="791722768778386941">"Este URL não pode ser adicionado como favorito."</string>
     <string name="delete_bookmark" msgid="2422989994934201992">"Excluir"</string>
     <string name="bookmark_page" msgid="6845189305130307274">"Adicionar última página visualizada aos favoritos"</string>
     <string name="switch_to_thumbnails" msgid="5493351529609043151">"Visualização em miniatura"</string>
@@ -91,18 +92,11 @@
     <string name="current_page" msgid="7510129573681663135">"de "</string>
     <string name="delete_bookmark_warning" msgid="758043186202032205">"O favorito \"<xliff:g id="BOOKMARK">%s</xliff:g>\" será excluído."</string>
     <string name="open_in_new_window" msgid="6596775546468054510">"Abrir em uma nova janela"</string>
-    <string name="new_window" msgid="8117889615360211551">"Nova janela"</string>
     <string name="goto_dot" msgid="3895839050522602723">"Ir"</string>
     <string name="find_dot" msgid="6259312434696611957">"Localizar na página"</string>
     <string name="select_dot" msgid="6299170761900561967">"Selecionar texto"</string>
-    <string name="view_tabs" msgid="1119097492003550564">"Visão geral da janela"</string>
-    <string name="view_tabs_condensed" msgid="5803955493821945369">"Janelas"</string>
     <string name="tab_picker_title" msgid="864478399057782913">"Janelas atuais"</string>
-    <string name="tab_picker_view_tab" msgid="2984342364915347656">"Exibir"</string>
-    <string name="tab_picker_new_tab" msgid="3080280018986866528">"Nova janela"</string>
     <string name="tab_picker_remove_tab" msgid="630087809802479397">"Fechar"</string>
-    <string name="tab_picker_bookmark" msgid="1084409404198995477">"Favorito"</string>
-    <string name="tab_picker_send_url" msgid="9102803487525950021">"Compartilhar link"</string>
     <string name="bookmarks" msgid="1961279134885867815">"Favoritos"</string>
     <string name="shortcut_bookmark" msgid="3974876480401135895">"Favorito"</string>
     <string name="history" msgid="2451240511251410032">"Histórico"</string>
@@ -118,7 +112,8 @@
     <string name="contextmenu_copylink" msgid="5153657160294534270">"Copiar URL do link"</string>
     <string name="contextmenu_download_image" msgid="4243829645180686912">"Salvar imagem"</string>
     <string name="contextmenu_view_image" msgid="3870625602053600905">"Visualizar imagem"</string>
-    <string name="contextmenu_dial_dot" msgid="5856550683415933806">"Discar..."</string>
+    <string name="contextmenu_set_wallpaper" msgid="3691902960115350686">"Definir como plano de fundo"</string>
+    <string name="contextmenu_dial_dot" msgid="5856550683415933806">"Discar…"</string>
     <string name="contextmenu_add_contact" msgid="3183511922223645716">"Adicionar contato"</string>
     <string name="contextmenu_send_mail" msgid="1014513374828775660">"Enviar e-mail"</string>
     <string name="contextmenu_map" msgid="7471390435434034912">"Mapa"</string>
@@ -134,8 +129,14 @@
     <string name="pref_content_javascript" msgid="4570972030299516843">"Ativar JavaScript"</string>
     <string name="pref_content_open_in_background" msgid="824123779725118663">"Abrir em segundo plano"</string>
     <string name="pref_content_plugins" msgid="7231944644794301582">"Ativar plug-ins"</string>
+  <string-array name="pref_content_plugins_choices">
+    <item msgid="6745108155096660725">"Sempre ativado"</item>
+    <item msgid="2484126708670016519">"Sob demanda"</item>
+    <item msgid="8547442717307793863">"Desativado"</item>
+  </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_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>
     <string name="pref_content_landscape_only" msgid="2022546812766219672">"Apenas modo paisagem"</string>
@@ -164,7 +165,7 @@
     <string name="pref_security_title" msgid="5763978646932160021">"Configurações de segurança"</string>
     <string name="pref_security_remember_passwords" msgid="6492957683454529549">"Lembrar senhas"</string>
     <string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"Salvar nomes de usuário e senhas para sites"</string>
-    <string name="pref_security_save_form_data" msgid="1213669802810198893">"Lembrar dados formulário"</string>
+    <string name="pref_security_save_form_data" msgid="1213669802810198893">"Lembrar dados de form."</string>
     <string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"Lembrar os dados que digitei nos formulários para uso posterior."</string>
     <string name="pref_security_show_security_warning" msgid="8901135676266754559">"Avisos de segurança"</string>
     <string name="pref_security_show_security_warning_summary" msgid="8968906112720511704">"Mostrar aviso se houver um problema com a segurança de um site."</string>
@@ -190,24 +191,23 @@
     <string name="pref_content_load_page_summary" msgid="8792093504054149369">"Exibir visão geral de páginas que acabaram de ser abertas"</string>
     <string name="pref_extras_title" msgid="3091250467679722382">"Configurações avançadas"</string>
     <string name="pref_extras_website_settings" msgid="67866640052455549">"Configurações do site"</string>
-    <string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Visualizar configurações avançadas para sites individuais"</string>
+    <string name="pref_extras_website_settings_summary" msgid="1656771443223494406">"Configurações avançadas para sites individuais."</string>
     <string name="pref_extras_reset_default" msgid="8904000515846202110">"Redefinir para o padrão"</string>
-    <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Limpar dados do navegador e redefinir as configurações para o padrão"</string>
-    <string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"Todos os dados do navegador serão excluídos e as configurações voltarão para os valores padrão."</string>
+    <string name="pref_extras_reset_default_summary" msgid="4247870778270414501">"Restaurar as configurações padrão"</string>
+    <string name="pref_extras_reset_default_dlg" msgid="6640261575874704022">"As configurações voltarão para os valores padrão."</string>
     <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Redefinir para o padrão"</string>
     <string name="pref_development_title" msgid="3263854204533056480">"Depurar"</string>
     <string name="pref_default_text_encoding" msgid="5742965543955558478">"Codificação de texto"</string>
   <string-array name="pref_default_text_encoding_choices">
     <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
     <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
-    <item msgid="7143715548814380950">"Japonês (ISO-2022-JP)"</item>
-    <item msgid="5111312120564516587">"Japonês (SHIFT_JIS)"</item>
-    <item msgid="6545734186479713946">"Japonês (EUC-JP)"</item>
+    <item msgid="6122474363777211732">"Chinês (GBK)"</item>
+    <item msgid="373372275931607040">"Chinês (Big5)"</item>
+    <item msgid="891615911084608570">"Japonês (ISO-2022-JP)"</item>
+    <item msgid="5589150448475151241">"Japonês (SHIFT_JIS)"</item>
+    <item msgid="7356792686950371843">"Japonês (EUC-JP)"</item>
   </string-array>
     <string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Codificação de texto"</string>
-    <string name="pref_default_text_encoding_default" msgid="5272126711231936722">"Latin-1"</string>
-    <string name="browserFrameRedirect" msgid="7049675479777828343">"Redirecionar"</string>
-    <string name="browserFrame307Post" msgid="1429094844669510768">"Esta página da web está sendo redirecionada. Reenviar os seus dados de formulário digitados para o novo local?"</string>
     <string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Problema de conectividade de dados"</string>
     <string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Problema com o arquivo"</string>
     <string name="browserFrameFormResubmitLabel" msgid="2685923472682180360">"Confirmar"</string>
@@ -234,13 +234,12 @@
     <string name="download_unknown_filename" msgid="4013465542563652175">"&lt;Desconhecido&gt;"</string>
     <string name="download_menu_open" msgid="4888327480367757513">"Abrir"</string>
     <string name="download_menu_clear" msgid="6264454531553418124">"Limpar da lista"</string>
+    <string name="download_menu_delete" msgid="8815502136393894148">"Excluir"</string>
     <string name="download_menu_cancel" msgid="2545333007601851574">"Cancelar download"</string>
     <string name="download_menu_cancel_all" msgid="2136550823151999166">"Cancelar todos os downloads"</string>
-    <string name="download_menu_clear_all" msgid="7423737413377703862">"Limpar lista"</string>
-    <string name="download_clear_dlg_title" msgid="7961996329529777390">"Limpar"</string>
-    <string name="download_clear_dlg_msg" msgid="8056013815679757669">"Todos os itens serão limpos da lista e removidos do cache do navegador."</string>
     <string name="download_cancel_dlg_title" msgid="8909108500262799748">"Cancelar downloads"</string>
     <string name="download_cancel_dlg_msg" msgid="6285389170052357797">"Todos os <xliff:g id="DOWNLOAD_COUNT">%d</xliff:g> downloads serão cancelados e limpos do histórico de downloads."</string>
+    <string name="download_delete_file" msgid="5330036497843073249">"O arquivo será excluído."</string>
     <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>
@@ -248,7 +247,7 @@
     <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>
-    <string name="download_no_application" msgid="5054596425887523234">"Não é possível encontrar um aplicativo para abrir este arquivo."</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>
     <string name="download_error" msgid="413496839831257187">"Falha no download."</string>
@@ -262,12 +261,10 @@
     <string name="download_file_error" msgid="1206648050615176113">"Não é possível concluir o download. Não há espaço suficiente."</string>
     <string name="download_length_required" msgid="9038605488460437406">"Não é possível fazer o download. O tamanho do item não pode ser determinado."</string>
     <string name="download_precondition_failed" msgid="8327584102874295580">"Download interrompido. Não é possível retomar."</string>
-    <string name="activity_instrumentation_test_runner" msgid="8215091309334005029">"Executador de teste do navegador"</string>
     <string name="search_the_web" msgid="6046130189241962337">"Pesquisar na web"</string>
     <string name="webstorage_outofspace_notification_title" msgid="1160474608059771788">"Armazenamento do navegador cheio"</string>
     <string name="webstorage_outofspace_notification_text" msgid="7341075135051829692">"Clique para liberar espaço."</string>
     <string name="webstorage_clear_data_title" msgid="689484577124333977">"Limpar dados armazenados"</string>
-    <string name="webstorage_clear_data_summary" msgid="3523128713743907805">"Remover todos os bancos de dados associados a esse site"</string>
     <string name="webstorage_clear_data_dialog_title" msgid="345457466368974706">"Limpar dados armazenados"</string>
     <string name="webstorage_clear_data_dialog_message" msgid="6678281256970470125">"Todos os dados armazenados por este site serão excluídos"</string>
     <string name="webstorage_clear_data_dialog_ok_button" msgid="2516563534211898636">"Limpar tudo"</string>
@@ -278,6 +275,8 @@
     <string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Compartilhar local"</string>
     <string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Recusar"</string>
     <string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Lembrar preferências"</string>
+    <string name="geolocation_permissions_prompt_toast_allowed" msgid="987286072035125498">"Este site pode acessar o seu local. Altere esta configuração em Configurações -&gt; Configurações do site."</string>
+    <string name="geolocation_permissions_prompt_toast_disallowed" msgid="7695100950212692515">"Este site não pode acessar o seu local. Altere esta configuração em Configurações -&gt; Configurações do site."</string>
     <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Limpar acesso à localização"</string>
     <string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Este site pode acessar a sua localização no momento"</string>
     <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Este site não pode acessar a sua localização no momento"</string>
@@ -290,5 +289,5 @@
     <string name="website_settings_clear_all_dialog_message" msgid="6150502090601476333">"Todos os dados do site e permissões de local serão excluídos."</string>
     <string name="website_settings_clear_all_dialog_ok_button" msgid="6401582240627669431">"Excluir todos os dados"</string>
     <string name="website_settings_clear_all_dialog_cancel_button" msgid="1896757051856611674">"Cancelar"</string>
-    <string name="zoom_overview_button_text" msgid="4146579940085488881">"Visão geral"</string>
+    <string name="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Definindo o plano de fundo..."</string>
 </resources>
diff --git a/res/values-ru/arrays.xml b/res/values-ru/arrays.xml
deleted file mode 100644
index b3a5146..0000000
--- a/res/values-ru/arrays.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="webstorage_quota_entries">
-    <item msgid="5433313236875537673">"Квота не назначена"</item>
-    <item msgid="7374272188672967690">"5 МБ"</item>
-    <item msgid="8699352701856136738">"10 МБ"</item>
-    <item msgid="2018822431469084862">"30 МБ"</item>
-    <item msgid="5383642976774534074">"100 МБ"</item>
-  </string-array>
-  <string-array name="webstorage_quota_entries_values">
-    <item msgid="7620410313725236055">"0"</item>
-    <item msgid="4302688814760304206">"5"</item>
-    <item msgid="7291990205847586165">"10"</item>
-    <item msgid="916913372287112423">"30"</item>
-    <item msgid="3437188301324229987">"100"</item>
-  </string-array>
-</resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 4af4b4c..b976eeb 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -1,21 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--  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.
--->
+ -->
+
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="1935869255545976415">"Браузер"</string>
+    <string name="choose_upload" msgid="3649366287575002063">"Выберите файл для загрузки"</string>
     <string name="new_tab" msgid="4505722538297295141">"Новое окно"</string>
     <string name="active_tabs" msgid="3050623868203544623">"Окна"</string>
     <string name="tab_bookmarks" msgid="2305793036003473653">"Закладки"</string>
@@ -38,7 +40,7 @@
   </plurals>
     <string name="title_bar_loading" msgid="7438217780834640678">"Загрузка…"</string>
     <string name="page_info" msgid="4048529256302257195">"Информация о странице"</string>
-    <string name="page_info_view" msgid="5303490449842635158">"Просмотр информации о странице"</string>
+    <string name="page_info_view" msgid="5303490449842635158">"Информация о странице"</string>
     <string name="page_info_address" msgid="2222306609532903254">"Адрес:"</string>
     <string name="ssl_warnings_header" msgid="79744901983636370">"У этого сайта проблемы с сертификатом безопасности."</string>
     <string name="ssl_continue" msgid="8031515015829358457">"Продолжить"</string>
@@ -58,12 +60,11 @@
     <string name="validity_period" msgid="57988851973181309">"Срок действия:"</string>
     <string name="issued_on" msgid="2082890654801808368">"Дата издания:"</string>
     <string name="expires_on" msgid="8061200430557020704">"Дата окончания действия:"</string>
-    <string name="retrieving_creds_dlg_msg" msgid="9207671133094039879">"Получение регистрационной информации..."</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="forward" msgid="4288210890526641577">"Вперед"</string>
     <string name="save" msgid="5922311934992468496">"ОК"</string>
     <string name="do_not_save" msgid="6777633870113477714">"Отмена"</string>
     <string name="location" msgid="969988560160364559">"URL-адрес"</string>
@@ -82,8 +83,8 @@
     <string name="homepage_set" msgid="8768087280310966395">"Главная страница установлена."</string>
     <string name="bookmark_needs_title" msgid="6245900436119218187">"Необходимо указать имя закладки."</string>
     <string name="bookmark_needs_url" msgid="7809876865972755158">"Необходимо указать место закладки."</string>
-    <string name="empty_bookmark" msgid="7008697085928540511">"Невозможно создать пустую закладку."</string>
     <string name="bookmark_url_not_valid" msgid="6719785633980202419">"URL недействителен."</string>
+    <string name="bookmark_cannot_save_url" msgid="791722768778386941">"Невозможно добавить этот URL в закладки"</string>
     <string name="delete_bookmark" msgid="2422989994934201992">"Удалить"</string>
     <string name="bookmark_page" msgid="6845189305130307274">"Добавить в закладки последнюю просмотренную страницу"</string>
     <string name="switch_to_thumbnails" msgid="5493351529609043151">"Уменьшенные изображения"</string>
@@ -91,18 +92,11 @@
     <string name="current_page" msgid="7510129573681663135">"на "</string>
     <string name="delete_bookmark_warning" msgid="758043186202032205">"Закладка \"<xliff:g id="BOOKMARK">%s</xliff:g>\" будет удалена."</string>
     <string name="open_in_new_window" msgid="6596775546468054510">"Открыть в новом окне"</string>
-    <string name="new_window" msgid="8117889615360211551">"Новое окно"</string>
     <string name="goto_dot" msgid="3895839050522602723">"Поиск"</string>
     <string name="find_dot" msgid="6259312434696611957">"Найти на странице"</string>
     <string name="select_dot" msgid="6299170761900561967">"Выбрать текст"</string>
-    <string name="view_tabs" msgid="1119097492003550564">"Обзор окон"</string>
-    <string name="view_tabs_condensed" msgid="5803955493821945369">"Окна"</string>
     <string name="tab_picker_title" msgid="864478399057782913">"Открытые окна"</string>
-    <string name="tab_picker_view_tab" msgid="2984342364915347656">"Просмотр"</string>
-    <string name="tab_picker_new_tab" msgid="3080280018986866528">"Новое окно"</string>
     <string name="tab_picker_remove_tab" msgid="630087809802479397">"Закрыть"</string>
-    <string name="tab_picker_bookmark" msgid="1084409404198995477">"Добавить в закладки"</string>
-    <string name="tab_picker_send_url" msgid="9102803487525950021">"Отправить ссылку"</string>
     <string name="bookmarks" msgid="1961279134885867815">"Закладки"</string>
     <string name="shortcut_bookmark" msgid="3974876480401135895">"Добавить в закладки"</string>
     <string name="history" msgid="2451240511251410032">"История"</string>
@@ -118,6 +112,7 @@
     <string name="contextmenu_copylink" msgid="5153657160294534270">"Копировать URL ссылки"</string>
     <string name="contextmenu_download_image" msgid="4243829645180686912">"Сохранить изображение"</string>
     <string name="contextmenu_view_image" msgid="3870625602053600905">"Просмотр изображения"</string>
+    <string name="contextmenu_set_wallpaper" msgid="3691902960115350686">"Установить как фоновый рисунок"</string>
     <string name="contextmenu_dial_dot" msgid="5856550683415933806">"Набор номера..."</string>
     <string name="contextmenu_add_contact" msgid="3183511922223645716">"Добавить контакт"</string>
     <string name="contextmenu_send_mail" msgid="1014513374828775660">"Отправить сообщение по электронной почте"</string>
@@ -127,37 +122,43 @@
     <string name="replace" msgid="4843033491070384047">"Заменить"</string>
     <string name="browser_bookmarks_page_bookmarks_text" msgid="6787605028726162673">"Закладки"</string>
     <string name="menu_preferences" msgid="6709237687234102240">"Настройки"</string>
-    <string name="pref_content_title" msgid="722227111894838633">"Настройки содержания страницы"</string>
-    <string name="pref_content_load_images" msgid="2125616852957377561">"Загружать картинки"</string>
-    <string name="pref_content_load_images_summary" msgid="5055874125248398584">"Показывать картинки на веб-страницах"</string>
-    <string name="pref_content_block_popups" msgid="7808433807197256726">"Блокировать всплывающие окна"</string>
-    <string name="pref_content_javascript" msgid="4570972030299516843">"Включить JavaScript"</string>
+    <string name="pref_content_title" msgid="722227111894838633">"Настройки отображения"</string>
+    <string name="pref_content_load_images" msgid="2125616852957377561">"Загружать графику"</string>
+    <string name="pref_content_load_images_summary" msgid="5055874125248398584">"Показывать изображения на веб-страницах"</string>
+    <string name="pref_content_block_popups" msgid="7808433807197256726">"Блокир. всплыв. окна"</string>
+    <string name="pref_content_javascript" msgid="4570972030299516843">"Разрешить JavaScript"</string>
     <string name="pref_content_open_in_background" msgid="824123779725118663">"Открывать в фоновом режиме"</string>
-    <string name="pref_content_plugins" msgid="7231944644794301582">"Включить плагины"</string>
+    <string name="pref_content_plugins" msgid="7231944644794301582">"Разрешить плагины"</string>
+  <string-array name="pref_content_plugins_choices">
+    <item msgid="6745108155096660725">"Всегда вкл."</item>
+    <item msgid="2484126708670016519">"По требованию"</item>
+    <item msgid="8547442717307793863">"Выкл."</item>
+  </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_autofit" msgid="8260474534053660809">"Подгонять страницы"</string>
-    <string name="pref_content_autofit_summary" msgid="4587831659894879986">"Подгонять веб-страницы под размер экрана"</string>
-    <string name="pref_content_landscape_only" msgid="2022546812766219672">"Только альбомный вид"</string>
-    <string name="pref_content_landscape_only_summary" msgid="1008238895535428855">"Показывать страницы только в альбомной ориентации"</string>
+    <string name="pref_content_homepage" msgid="6082437160778559806">"Домашняя страница"</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>
+    <string name="pref_content_landscape_only" msgid="2022546812766219672">"Только горизонтально"</string>
+    <string name="pref_content_landscape_only_summary" msgid="1008238895535428855">"Показывать страницы только в горизонтальной ориентации"</string>
     <string name="pref_privacy_title" msgid="1052470980370846151">"Настройки конфиденциальности"</string>
     <string name="pref_privacy_clear_cache" msgid="3380316479925886998">"Очистить кэш"</string>
-    <string name="pref_privacy_clear_cache_summary" msgid="2216463577207991454">"Очистить содержание и базы данных, сохраненные локально"</string>
-    <string name="pref_privacy_clear_cache_dlg" msgid="5541011591300753881">"Содержание и базы данных, сохраненные локально, будут удалены."</string>
-    <string name="pref_privacy_clear_cookies" msgid="3095583579133780331">"Очистить все данные cookie"</string>
+    <string name="pref_privacy_clear_cache_summary" msgid="2216463577207991454">"Удалить контент и данные, сохраненные браузером"</string>
+    <string name="pref_privacy_clear_cache_dlg" msgid="5541011591300753881">"Контент и данные, сохраненные браузером, будут удалены."</string>
+    <string name="pref_privacy_clear_cookies" msgid="3095583579133780331">"Удалить cookie"</string>
     <string name="pref_privacy_clear_cookies_summary" msgid="6962742063990677520">"Удалить все файлы cookie браузера"</string>
     <string name="pref_privacy_clear_cookies_dlg" msgid="552855688091432682">"Все файлы cookie будут удалены."</string>
     <string name="pref_privacy_clear_history" msgid="8723795508825198477">"Очистить историю"</string>
-    <string name="pref_privacy_clear_history_summary" msgid="6868501330708940734">"Очистить историю браузера"</string>
+    <string name="pref_privacy_clear_history_summary" msgid="6868501330708940734">"Очистить список посещенных в Интернете страниц"</string>
     <string name="pref_privacy_clear_history_dlg" msgid="544903007914753853">"История браузера будет очищена."</string>
     <string name="pref_privacy_clear_form_data" msgid="4232668196344383987">"Очистить данные формы"</string>
-    <string name="pref_privacy_clear_form_data_summary" msgid="1790390894719517167">"Очистить все данные сохраненных форм"</string>
+    <string name="pref_privacy_clear_form_data_summary" msgid="1790390894719517167">"Очистить все сохраненные данные форм"</string>
     <string name="pref_privacy_clear_form_data_dlg" msgid="4443621086781197928">"Все данные сохраненных форм будут удалены."</string>
     <string name="pref_privacy_clear_passwords" msgid="4750234112289277480">"Очистить пароли"</string>
     <string name="pref_privacy_clear_passwords_summary" msgid="8856782718942903335">"Удалить все сохраненные пароли"</string>
     <string name="pref_privacy_clear_passwords_dlg" msgid="2083869328824248255">"Все сохраненные пароли будут удалены."</string>
     <string name="pref_privacy_enable_geolocation" msgid="1395040170290765686">"Включить местоположение"</string>
-    <string name="pref_privacy_enable_geolocation_summary" msgid="8437020934664306205">"Разрешить сайтам запрашивать данные доступа к местоположению"</string>
+    <string name="pref_privacy_enable_geolocation_summary" msgid="8437020934664306205">"Разрешить сайтам запрашивать доступ к данным о местоположении"</string>
     <string name="pref_privacy_clear_geolocation_access" msgid="6649680770030042980">"Удалить данные доступа к местоположению"</string>
     <string name="pref_privacy_clear_geolocation_access_summary" msgid="7750143359497314679">"Удалить данные доступа к местоположению для всех сайтов"</string>
     <string name="pref_privacy_clear_geolocation_access_dlg" msgid="7327063124488827244">"Удалить данные доступа к местоположению для всех сайтов"</string>
@@ -165,9 +166,9 @@
     <string name="pref_security_remember_passwords" msgid="6492957683454529549">"Сохранять пароли"</string>
     <string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"Сохранять имена пользователей и пароли веб-сайтов"</string>
     <string name="pref_security_save_form_data" msgid="1213669802810198893">"Сохранять данные форм"</string>
-    <string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"Запоминать введенные данные для дальнейшего использования"</string>
-    <string name="pref_security_show_security_warning" msgid="8901135676266754559">"Показывать предупреждения безопасности"</string>
-    <string name="pref_security_show_security_warning_summary" msgid="8968906112720511704">"Сообщать о найденных проблемах с безопасностью сайта"</string>
+    <string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"Запоминать введенные в формы данные для дальнейшего использования"</string>
+    <string name="pref_security_show_security_warning" msgid="8901135676266754559">"Предупреждать об опасности"</string>
+    <string name="pref_security_show_security_warning_summary" msgid="8968906112720511704">"Предупреждать при обнаружении на сайтах угроз для безопасности"</string>
     <string name="pref_security_accept_cookies" msgid="3201367661925047989">"Разрешить cookie"</string>
     <string name="pref_security_accept_cookies_summary" msgid="1465118934875026920">"Разрешить сайтам сохранять и читать файлы cookie"</string>
     <string name="pref_text_size" msgid="3827031324346612208">"Размер текста"</string>
@@ -181,36 +182,35 @@
     <string name="pref_text_size_dialogtitle" msgid="3625388833512647865">"Размер текста"</string>
     <string name="pref_default_zoom" msgid="8076142259097187395">"Масштаб по умолчанию"</string>
   <string-array name="pref_default_zoom_choices">
-    <item msgid="549583171195154919">"Мелко"</item>
-    <item msgid="5619034257768161024">"Нормально"</item>
-    <item msgid="3840999588443167001">"Крупно"</item>
+    <item msgid="549583171195154919">"Мелкий"</item>
+    <item msgid="5619034257768161024">"Средний"</item>
+    <item msgid="3840999588443167001">"Крупный"</item>
   </string-array>
     <string name="pref_default_zoom_dialogtitle" msgid="6095974367125109021">"Масштаб по умолчанию"</string>
-    <string name="pref_content_load_page" msgid="2219810141690955452">"Открывать страницы в обзоре окон"</string>
-    <string name="pref_content_load_page_summary" msgid="8792093504054149369">"Показывать обзор новых открытых страниц"</string>
+    <string name="pref_content_load_page" msgid="2219810141690955452">"Обзор страниц"</string>
+    <string name="pref_content_load_page_summary" msgid="8792093504054149369">"Открывать страницы в мелком маштабе для ознакомления"</string>
     <string name="pref_extras_title" msgid="3091250467679722382">"Расширенные настройки"</string>
     <string name="pref_extras_website_settings" msgid="67866640052455549">"Настройки веб-сайта"</string>
-    <string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Просмотреть дополнительные настройки для отдельных сайтов"</string>
-    <string name="pref_extras_reset_default" msgid="8904000515846202110">"Восстановить настройки по умолчанию"</string>
-    <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Очистить все данные браузера и включить настройки по умолчанию"</string>
-    <string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"Все данные браузера будут удалены, настройки по умолчанию будут восстановлены."</string>
-    <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Восстановить настройки по умолчанию"</string>
-    <string name="pref_development_title" msgid="3263854204533056480">"Отладка"</string>
+    <string name="pref_extras_website_settings_summary" msgid="1656771443223494406">"Дополнительные настройки для отдельных сайтов"</string>
+    <string name="pref_extras_reset_default" msgid="8904000515846202110">"Сброс настроек"</string>
+    <string name="pref_extras_reset_default_summary" msgid="4247870778270414501">"Восстановить значения по умолчанию"</string>
+    <string name="pref_extras_reset_default_dlg" msgid="6640261575874704022">"Будут восстановлены значения по умолчанию."</string>
+    <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Сброс настроек"</string>
+    <string name="pref_development_title" msgid="3263854204533056480">"Выполнить отладку"</string>
     <string name="pref_default_text_encoding" msgid="5742965543955558478">"Кодировка текста"</string>
   <string-array name="pref_default_text_encoding_choices">
     <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
     <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
-    <item msgid="7143715548814380950">"Японская (ISO-2022-JP)"</item>
-    <item msgid="5111312120564516587">"Японская (SHIFT_JIS)"</item>
-    <item msgid="6545734186479713946">"Японская (EUC-JP)"</item>
+    <item msgid="6122474363777211732">"Китайская (GBK)"</item>
+    <item msgid="373372275931607040">"Китайская (Big5)"</item>
+    <item msgid="891615911084608570">"Японская (ISO-2022-JP)"</item>
+    <item msgid="5589150448475151241">"Японская (SHIFT_JIS)"</item>
+    <item msgid="7356792686950371843">"Японская (EUC-JP)"</item>
   </string-array>
     <string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Кодировка текста"</string>
-    <string name="pref_default_text_encoding_default" msgid="5272126711231936722">"Latin-1"</string>
-    <string name="browserFrameRedirect" msgid="7049675479777828343">"Перенаправление"</string>
-    <string name="browserFrame307Post" msgid="1429094844669510768">"Вы перенаправлены с этой страницы. Отправить ваши данные формы в новое место?"</string>
     <string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Проблема с подключением"</string>
     <string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Проблема с файлом"</string>
-    <string name="browserFrameFormResubmitLabel" msgid="2685923472682180360">"Подтверждение"</string>
+    <string name="browserFrameFormResubmitLabel" msgid="2685923472682180360">"Подтвердить"</string>
     <string name="browserFrameFormResubmitMessage" msgid="2752182215695632138">"Страница, которую вы пытаетесь просмотреть, содержит уже отправленные данные (POSTDATA). Если отправить их еще раз, произойдет повтор всех действий, которые форма выполнила на странице (например поиск или покупка через Интернет)."</string>
     <string name="loadSuspendedTitle" msgid="675991625288706944">"Сетевое подключение отсутствует"</string>
     <string name="loadSuspended" msgid="3133656588880851273">"Браузер не может загрузить эту страницу, так как отсутствует подключение к Интернету."</string>
@@ -222,7 +222,7 @@
     <string name="search_hint" msgid="4647356319916631820">"Введите условия поиска или URL-адрес"</string>
     <string name="search_button_text" msgid="5235226933877634410">"Поиск"</string>
     <string name="search_settings_description" msgid="1422401062529014107">"Закладки и история поиска"</string>
-    <string name="attention" msgid="3473639060042811244">"Внимание"</string>
+    <string name="attention" msgid="3473639060042811244">"Внимание!"</string>
     <string name="popup_window_attempt" msgid="2673111696288657989">"Этот сайт пытается открыть всплывающее окно."</string>
     <string name="allow" msgid="1157313689171991335">"Разрешить"</string>
     <string name="block" msgid="9172175889884707800">"Заблокировать"</string>
@@ -234,13 +234,12 @@
     <string name="download_unknown_filename" msgid="4013465542563652175">"&lt;неизвестно&gt;"</string>
     <string name="download_menu_open" msgid="4888327480367757513">"Открыть"</string>
     <string name="download_menu_clear" msgid="6264454531553418124">"Удалить из списка"</string>
+    <string name="download_menu_delete" msgid="8815502136393894148">"Удалить"</string>
     <string name="download_menu_cancel" msgid="2545333007601851574">"Отменить загрузку"</string>
     <string name="download_menu_cancel_all" msgid="2136550823151999166">"Отменить все загрузки"</string>
-    <string name="download_menu_clear_all" msgid="7423737413377703862">"Очистить список"</string>
-    <string name="download_clear_dlg_title" msgid="7961996329529777390">"Очистить"</string>
-    <string name="download_clear_dlg_msg" msgid="8056013815679757669">"Будут удалены все данные из списка и кэша браузера."</string>
     <string name="download_cancel_dlg_title" msgid="8909108500262799748">"Отменить загрузки"</string>
     <string name="download_cancel_dlg_msg" msgid="6285389170052357797">"Все загрузки (<xliff:g id="DOWNLOAD_COUNT">%d</xliff:g>) будут отменены и удалены из истории загрузок."</string>
+    <string name="download_delete_file" msgid="5330036497843073249">"Файл будет удален"</string>
     <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>
@@ -248,7 +247,7 @@
     <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>
-    <string name="download_no_application" msgid="5054596425887523234">"Приложение для открытия этого файла не найдено."</string>
+    <string name="download_no_application_title" msgid="1286056729168874295">"Невозможно открыть файл"</string>
     <string name="retry" msgid="1835923075542266721">"Повторить попытку"</string>
     <string name="no_downloads" msgid="3947445710685021498">"История загрузок пуста."</string>
     <string name="download_error" msgid="413496839831257187">"Ошибка загрузки."</string>
@@ -262,12 +261,10 @@
     <string name="download_file_error" msgid="1206648050615176113">"Невозможно завершить загрузку. Недостаточно места."</string>
     <string name="download_length_required" msgid="9038605488460437406">"Загрузка невозможна. Размер файла не определен."</string>
     <string name="download_precondition_failed" msgid="8327584102874295580">"Загрузка прервана и не может быть возобновлена."</string>
-    <string name="activity_instrumentation_test_runner" msgid="8215091309334005029">"Тестирование браузера"</string>
     <string name="search_the_web" msgid="6046130189241962337">"Поиск в Интернете"</string>
     <string name="webstorage_outofspace_notification_title" msgid="1160474608059771788">"Память браузера переполнена"</string>
     <string name="webstorage_outofspace_notification_text" msgid="7341075135051829692">"Нажмите, чтобы освободить место."</string>
     <string name="webstorage_clear_data_title" msgid="689484577124333977">"Удалить сохраненные данные"</string>
-    <string name="webstorage_clear_data_summary" msgid="3523128713743907805">"Удалить все базы данных, связанные с этим сайтом"</string>
     <string name="webstorage_clear_data_dialog_title" msgid="345457466368974706">"Удалить сохраненные данные"</string>
     <string name="webstorage_clear_data_dialog_message" msgid="6678281256970470125">"Все данные, сохраненные этим веб-сайтом, будут удалены"</string>
     <string name="webstorage_clear_data_dialog_ok_button" msgid="2516563534211898636">"Удалить все"</string>
@@ -278,6 +275,8 @@
     <string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Сообщить местоположение"</string>
     <string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Отклонить"</string>
     <string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Запомнить настройки"</string>
+    <string name="geolocation_permissions_prompt_toast_allowed" msgid="987286072035125498">"У этого сайта есть доступ к данным о вашем местоположении. Для изменения параметров доступа выберите Настройки -&gt; Настройки веб-сайта"</string>
+    <string name="geolocation_permissions_prompt_toast_disallowed" msgid="7695100950212692515">"У этого сайта нет доступа к данным о вашем местоположении. Для изменения параметров доступа выберите Настройки -&gt; Настройки веб-сайта"</string>
     <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Удалить данные доступа к местоположению"</string>
     <string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Этот сайт сейчас имеет доступ к вашему местоположению"</string>
     <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Этот сайт в настоящее время не имеет доступа к вашему местоположению"</string>
@@ -290,5 +289,5 @@
     <string name="website_settings_clear_all_dialog_message" msgid="6150502090601476333">"Все данные сайтов и разрешения относительно местоположения будут удалены."</string>
     <string name="website_settings_clear_all_dialog_ok_button" msgid="6401582240627669431">"Удалить все данные"</string>
     <string name="website_settings_clear_all_dialog_cancel_button" msgid="1896757051856611674">"Отмена"</string>
-    <string name="zoom_overview_button_text" msgid="4146579940085488881">"Обзор"</string>
+    <string name="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Установка фонового рисунка..."</string>
 </resources>
diff --git a/res/values-sv/arrays.xml b/res/values-sv/arrays.xml
deleted file mode 100644
index 0f5814d..0000000
--- a/res/values-sv/arrays.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="webstorage_quota_entries">
-    <item msgid="5433313236875537673">"Ingen kvot tillåts"</item>
-    <item msgid="7374272188672967690">"5 MB"</item>
-    <item msgid="8699352701856136738">"10 MB"</item>
-    <item msgid="2018822431469084862">"30 MB"</item>
-    <item msgid="5383642976774534074">"100 MB"</item>
-  </string-array>
-  <string-array name="webstorage_quota_entries_values">
-    <item msgid="7620410313725236055">"0"</item>
-    <item msgid="4302688814760304206">"5"</item>
-    <item msgid="7291990205847586165">"10"</item>
-    <item msgid="916913372287112423">"30"</item>
-    <item msgid="3437188301324229987">"100"</item>
-  </string-array>
-</resources>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index f1cb487..b4dafb1 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -1,21 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--  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.
--->
+ -->
+
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="1935869255545976415">"Webbläs."</string>
+    <string name="choose_upload" msgid="3649366287575002063">"Välj filen som du vill överföra"</string>
     <string name="new_tab" msgid="4505722538297295141">"Nytt fönster"</string>
     <string name="active_tabs" msgid="3050623868203544623">"Fönster"</string>
     <string name="tab_bookmarks" msgid="2305793036003473653">"Bokmärken"</string>
@@ -58,7 +60,6 @@
     <string name="validity_period" msgid="57988851973181309">"Giltighet:"</string>
     <string name="issued_on" msgid="2082890654801808368">"Utfärdat den:"</string>
     <string name="expires_on" msgid="8061200430557020704">"Upphör att gälla:"</string>
-    <string name="retrieving_creds_dlg_msg" msgid="9207671133094039879">"Hämtar inloggningsuppgifter…"</string>
     <string name="stopping" msgid="4839698519340302982">"Avbryter…"</string>
     <string name="stop" msgid="5687251076030630074">"Stoppa"</string>
     <string name="reload" msgid="8585220783228408062">"Uppdatera"</string>
@@ -82,8 +83,8 @@
     <string name="homepage_set" msgid="8768087280310966395">"Startsida har angetts."</string>
     <string name="bookmark_needs_title" msgid="6245900436119218187">"Du måste ange ett namn på bokmärket."</string>
     <string name="bookmark_needs_url" msgid="7809876865972755158">"Du måste ange en plats för bokmärket."</string>
-    <string name="empty_bookmark" msgid="7008697085928540511">"Det går inte att skapa tomma bokmärken."</string>
     <string name="bookmark_url_not_valid" msgid="6719785633980202419">"Webbadressen är ogiltig."</string>
+    <string name="bookmark_cannot_save_url" msgid="791722768778386941">"Det går inte att spara webbadressen som ett bokmärke"</string>
     <string name="delete_bookmark" msgid="2422989994934201992">"Ta bort"</string>
     <string name="bookmark_page" msgid="6845189305130307274">"Skapa bokmärke för den senast visade sidan"</string>
     <string name="switch_to_thumbnails" msgid="5493351529609043151">"Miniatyrvy"</string>
@@ -91,18 +92,11 @@
     <string name="current_page" msgid="7510129573681663135">"från "</string>
     <string name="delete_bookmark_warning" msgid="758043186202032205">"Bokmärket <xliff:g id="BOOKMARK">%s</xliff:g> tas bort."</string>
     <string name="open_in_new_window" msgid="6596775546468054510">"Öppna i nytt fönster"</string>
-    <string name="new_window" msgid="8117889615360211551">"Nytt fönster"</string>
     <string name="goto_dot" msgid="3895839050522602723">"Kör"</string>
     <string name="find_dot" msgid="6259312434696611957">"Sök på sidan"</string>
     <string name="select_dot" msgid="6299170761900561967">"Markera text"</string>
-    <string name="view_tabs" msgid="1119097492003550564">"Översikt över fönster"</string>
-    <string name="view_tabs_condensed" msgid="5803955493821945369">"Fönster"</string>
     <string name="tab_picker_title" msgid="864478399057782913">"Aktuellt fönster"</string>
-    <string name="tab_picker_view_tab" msgid="2984342364915347656">"Visa"</string>
-    <string name="tab_picker_new_tab" msgid="3080280018986866528">"Nytt fönster"</string>
     <string name="tab_picker_remove_tab" msgid="630087809802479397">"Stäng"</string>
-    <string name="tab_picker_bookmark" msgid="1084409404198995477">"Bokmärke"</string>
-    <string name="tab_picker_send_url" msgid="9102803487525950021">"Dela länk"</string>
     <string name="bookmarks" msgid="1961279134885867815">"Bokmärken"</string>
     <string name="shortcut_bookmark" msgid="3974876480401135895">"Bokmärke"</string>
     <string name="history" msgid="2451240511251410032">"Historik"</string>
@@ -118,6 +112,7 @@
     <string name="contextmenu_copylink" msgid="5153657160294534270">"Kopiera länkens webbadress"</string>
     <string name="contextmenu_download_image" msgid="4243829645180686912">"Spara bild"</string>
     <string name="contextmenu_view_image" msgid="3870625602053600905">"Visa bild"</string>
+    <string name="contextmenu_set_wallpaper" msgid="3691902960115350686">"Använd som bakgrund"</string>
     <string name="contextmenu_dial_dot" msgid="5856550683415933806">"Ring..."</string>
     <string name="contextmenu_add_contact" msgid="3183511922223645716">"Lägg till kontakt"</string>
     <string name="contextmenu_send_mail" msgid="1014513374828775660">"Skicka e-post"</string>
@@ -134,8 +129,14 @@
     <string name="pref_content_javascript" msgid="4570972030299516843">"Aktivera JavaScript"</string>
     <string name="pref_content_open_in_background" msgid="824123779725118663">"Öppen i bakgrunden"</string>
     <string name="pref_content_plugins" msgid="7231944644794301582">"Aktivera plugin-program"</string>
+  <string-array name="pref_content_plugins_choices">
+    <item msgid="6745108155096660725">"Alltid på"</item>
+    <item msgid="2484126708670016519">"På begäran"</item>
+    <item msgid="8547442717307793863">"Av"</item>
+  </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_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>
     <string name="pref_content_landscape_only" msgid="2022546812766219672">"Endast liggande"</string>
@@ -190,24 +191,23 @@
     <string name="pref_content_load_page_summary" msgid="8792093504054149369">"Visa översikt över nyligen öppnade sidor"</string>
     <string name="pref_extras_title" msgid="3091250467679722382">"Avancerade inställningar"</string>
     <string name="pref_extras_website_settings" msgid="67866640052455549">"Webbplatsinställningar"</string>
-    <string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Visa avancerade inställningar för enskilda webbplatser"</string>
+    <string name="pref_extras_website_settings_summary" msgid="1656771443223494406">"Avancerade inställningar för enskilda webbplatser"</string>
     <string name="pref_extras_reset_default" msgid="8904000515846202110">"Återställ standardinställningarna"</string>
-    <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Ta bort alla data i webbläsaren och återställ standardinställningarna"</string>
-    <string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"Alla data i webbläsaren tas bort och standardinställningarna återställs."</string>
+    <string name="pref_extras_reset_default_summary" msgid="4247870778270414501">"Återställ standardinställningar"</string>
+    <string name="pref_extras_reset_default_dlg" msgid="6640261575874704022">"Standardvärdena för inställningarna återställs."</string>
     <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Återställ standardinställn."</string>
     <string name="pref_development_title" msgid="3263854204533056480">"Felsökning"</string>
     <string name="pref_default_text_encoding" msgid="5742965543955558478">"Textkodning"</string>
   <string-array name="pref_default_text_encoding_choices">
     <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
     <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
-    <item msgid="7143715548814380950">"Japansk (ISO-2022-JP)"</item>
-    <item msgid="5111312120564516587">"Japansk (SHIFT_JIS)"</item>
-    <item msgid="6545734186479713946">"Japansk (EUC-JP)"</item>
+    <item msgid="6122474363777211732">"Kinesisk (GBK)"</item>
+    <item msgid="373372275931607040">"Kinesisk (Big5)"</item>
+    <item msgid="891615911084608570">"Japansk (ISO-2022-JP)"</item>
+    <item msgid="5589150448475151241">"Japansk (SHIFT_JIS)"</item>
+    <item msgid="7356792686950371843">"Japansk (EUC-JP)"</item>
   </string-array>
     <string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Textkodning"</string>
-    <string name="pref_default_text_encoding_default" msgid="5272126711231936722">"Latin-1"</string>
-    <string name="browserFrameRedirect" msgid="7049675479777828343">"Omdirigera"</string>
-    <string name="browserFrame307Post" msgid="1429094844669510768">"Den här webbsidan omdirigeras. Vill du skicka uppgifterna i formuläret till den nya platsen?"</string>
     <string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Problem med dataanslutning"</string>
     <string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Problem med filen"</string>
     <string name="browserFrameFormResubmitLabel" msgid="2685923472682180360">"Bekräfta"</string>
@@ -234,13 +234,12 @@
     <string name="download_unknown_filename" msgid="4013465542563652175">"&lt;Okänd&gt;"</string>
     <string name="download_menu_open" msgid="4888327480367757513">"Öppna"</string>
     <string name="download_menu_clear" msgid="6264454531553418124">"Ta bort från listan"</string>
+    <string name="download_menu_delete" msgid="8815502136393894148">"Ta bort"</string>
     <string name="download_menu_cancel" msgid="2545333007601851574">"Avbryt hämtning"</string>
     <string name="download_menu_cancel_all" msgid="2136550823151999166">"Avbryt alla hämtningar"</string>
-    <string name="download_menu_clear_all" msgid="7423737413377703862">"Rensa listan"</string>
-    <string name="download_clear_dlg_title" msgid="7961996329529777390">"Rensa"</string>
-    <string name="download_clear_dlg_msg" msgid="8056013815679757669">"Alla objekt tas bort från listan och från webbläsarens cacheminne."</string>
     <string name="download_cancel_dlg_title" msgid="8909108500262799748">"Avbryt hämtningar"</string>
     <string name="download_cancel_dlg_msg" msgid="6285389170052357797">"Alla <xliff:g id="DOWNLOAD_COUNT">%d</xliff:g> hämtningar avbryts och tas bort från hämtningshistoriken."</string>
+    <string name="download_delete_file" msgid="5330036497843073249">"Filen kommer att tas bort"</string>
     <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>
@@ -248,7 +247,7 @@
     <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>
-    <string name="download_no_application" msgid="5054596425887523234">"Vi hittade inget program som kunde öppna filen."</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>
     <string name="download_error" msgid="413496839831257187">"Det gick inte att hämta."</string>
@@ -262,12 +261,10 @@
     <string name="download_file_error" msgid="1206648050615176113">"Det går inte att hämta. Det finns inte tillräckligt med utrymme."</string>
     <string name="download_length_required" msgid="9038605488460437406">"Det går inte att hämta eftersom objektets storlek inte kan avläsas."</string>
     <string name="download_precondition_failed" msgid="8327584102874295580">"Hämtningen avbröts. Den kan inte återupptas."</string>
-    <string name="activity_instrumentation_test_runner" msgid="8215091309334005029">"Testprogram för webbläsaren"</string>
     <string name="search_the_web" msgid="6046130189241962337">"Sök på webben"</string>
     <string name="webstorage_outofspace_notification_title" msgid="1160474608059771788">"Webbläsarens lagringsutrymme är fullt"</string>
     <string name="webstorage_outofspace_notification_text" msgid="7341075135051829692">"Klicka om du vill frigöra utrymme."</string>
     <string name="webstorage_clear_data_title" msgid="689484577124333977">"Ta bort sparade data"</string>
-    <string name="webstorage_clear_data_summary" msgid="3523128713743907805">"Ta bort alla databaser som är kopplade till den här webbplatsen"</string>
     <string name="webstorage_clear_data_dialog_title" msgid="345457466368974706">"Ta bort sparade data"</string>
     <string name="webstorage_clear_data_dialog_message" msgid="6678281256970470125">"Alla data som sparats på webbplatsen tas bort"</string>
     <string name="webstorage_clear_data_dialog_ok_button" msgid="2516563534211898636">"Ta bort alla"</string>
@@ -278,6 +275,8 @@
     <string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Dela plats"</string>
     <string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Avvisa"</string>
     <string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Kom ihåg mina inställningar"</string>
+    <string name="geolocation_permissions_prompt_toast_allowed" msgid="987286072035125498">"Webbplatsen har åtkomst till din plats. Ändra detta under Inställningar -&gt; Webbplatsinställningar"</string>
+    <string name="geolocation_permissions_prompt_toast_disallowed" msgid="7695100950212692515">"Webbplatsen har inte åtkomst till din plats. Ändra detta under Inställningar -&gt; Webbplatsinställningar"</string>
     <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Ta bort platsåtkomst"</string>
     <string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Den här webbplatsen har för närvarande åtkomst till din plats"</string>
     <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Den här webbplatsen har för närvarande inte åtkomst till din plats"</string>
@@ -290,5 +289,5 @@
     <string name="website_settings_clear_all_dialog_message" msgid="6150502090601476333">"Alla webbplatsdata och alla platsbehörigheter kommer att tas bort."</string>
     <string name="website_settings_clear_all_dialog_ok_button" msgid="6401582240627669431">"Ta bort alla data"</string>
     <string name="website_settings_clear_all_dialog_cancel_button" msgid="1896757051856611674">"Avbryt"</string>
-    <string name="zoom_overview_button_text" msgid="4146579940085488881">"Översikt"</string>
+    <string name="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Anger bakgrund..."</string>
 </resources>
diff --git a/res/values-tr/arrays.xml b/res/values-tr/arrays.xml
deleted file mode 100644
index bac7d19..0000000
--- a/res/values-tr/arrays.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="webstorage_quota_entries">
-    <item msgid="5433313236875537673">"İzin verilen kota yok"</item>
-    <item msgid="7374272188672967690">"5 MB"</item>
-    <item msgid="8699352701856136738">"10 MB"</item>
-    <item msgid="2018822431469084862">"30 MB"</item>
-    <item msgid="5383642976774534074">"100 MB"</item>
-  </string-array>
-  <string-array name="webstorage_quota_entries_values">
-    <item msgid="7620410313725236055">"0"</item>
-    <item msgid="4302688814760304206">"5"</item>
-    <item msgid="7291990205847586165">"10"</item>
-    <item msgid="916913372287112423">"30"</item>
-    <item msgid="3437188301324229987">"100"</item>
-  </string-array>
-</resources>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index e318a53..8f0826c 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -1,21 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--  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.
--->
+ -->
+
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="1935869255545976415">"Tarayıcı"</string>
+    <string name="choose_upload" msgid="3649366287575002063">"Yükleme için dosya seçin"</string>
     <string name="new_tab" msgid="4505722538297295141">"Yeni pencere"</string>
     <string name="active_tabs" msgid="3050623868203544623">"Pencereler"</string>
     <string name="tab_bookmarks" msgid="2305793036003473653">"Favoriler"</string>
@@ -26,7 +28,7 @@
     <string name="sign_in_to" msgid="5939425800148759165">"<xliff:g id="HOSTNAME">%s1</xliff:g> \"<xliff:g id="REALM">%s2</xliff:g>\" oturumu aç"</string>
     <string name="username" msgid="5057566336518215922">"Ad"</string>
     <string name="password" msgid="1177138552305184404">"Şifre"</string>
-    <string name="action" msgid="183105774472071343">"Oturum aç"</string>
+    <string name="action" msgid="183105774472071343">"Oturum açın"</string>
     <string name="bookmarks_search" msgid="5229596268214362873">"Tarayıcı"</string>
     <string name="cancel" msgid="3017274947407233702">"İptal"</string>
     <string name="ok" msgid="1509280796718850364">"Tamam"</string>
@@ -58,7 +60,6 @@
     <string name="validity_period" msgid="57988851973181309">"Geçerlilik:"</string>
     <string name="issued_on" msgid="2082890654801808368">"Yayınlanma tarihi:"</string>
     <string name="expires_on" msgid="8061200430557020704">"Sona erme tarihi:"</string>
-    <string name="retrieving_creds_dlg_msg" msgid="9207671133094039879">"Oturum açma bilgileri alınıyor..."</string>
     <string name="stopping" msgid="4839698519340302982">"Durduruluyor..."</string>
     <string name="stop" msgid="5687251076030630074">"Durdur"</string>
     <string name="reload" msgid="8585220783228408062">"Yenile"</string>
@@ -82,8 +83,8 @@
     <string name="homepage_set" msgid="8768087280310966395">"Ana sayfa ayarlandı."</string>
     <string name="bookmark_needs_title" msgid="6245900436119218187">"Favorinin bir adı olmalıdır."</string>
     <string name="bookmark_needs_url" msgid="7809876865972755158">"Favorinin bir konumu olmalıdır."</string>
-    <string name="empty_bookmark" msgid="7008697085928540511">"Boş favori oluşturulamaz."</string>
     <string name="bookmark_url_not_valid" msgid="6719785633980202419">"URL geçerli değil."</string>
+    <string name="bookmark_cannot_save_url" msgid="791722768778386941">"Bu URL yer işareti olarak eklenemez."</string>
     <string name="delete_bookmark" msgid="2422989994934201992">"Sil"</string>
     <string name="bookmark_page" msgid="6845189305130307274">"Son görüntülenen sayfayı favori olarak işaretle"</string>
     <string name="switch_to_thumbnails" msgid="5493351529609043151">"Küçük resim görünümü"</string>
@@ -91,18 +92,11 @@
     <string name="current_page" msgid="7510129573681663135">"kaynak: "</string>
     <string name="delete_bookmark_warning" msgid="758043186202032205">"Favori \"<xliff:g id="BOOKMARK">%s</xliff:g>\" silinecek."</string>
     <string name="open_in_new_window" msgid="6596775546468054510">"Yeni pencerede aç"</string>
-    <string name="new_window" msgid="8117889615360211551">"Yeni pencere"</string>
     <string name="goto_dot" msgid="3895839050522602723">"Git"</string>
     <string name="find_dot" msgid="6259312434696611957">"Sayfada bul"</string>
     <string name="select_dot" msgid="6299170761900561967">"Metin seç"</string>
-    <string name="view_tabs" msgid="1119097492003550564">"Pencereye genel bakış"</string>
-    <string name="view_tabs_condensed" msgid="5803955493821945369">"Pencereler"</string>
     <string name="tab_picker_title" msgid="864478399057782913">"Geçerli pencereler"</string>
-    <string name="tab_picker_view_tab" msgid="2984342364915347656">"Görüntüle"</string>
-    <string name="tab_picker_new_tab" msgid="3080280018986866528">"Yeni pencere"</string>
     <string name="tab_picker_remove_tab" msgid="630087809802479397">"Kapat"</string>
-    <string name="tab_picker_bookmark" msgid="1084409404198995477">"Favori"</string>
-    <string name="tab_picker_send_url" msgid="9102803487525950021">"Bağlantıyı paylaş"</string>
     <string name="bookmarks" msgid="1961279134885867815">"Favoriler"</string>
     <string name="shortcut_bookmark" msgid="3974876480401135895">"Favori"</string>
     <string name="history" msgid="2451240511251410032">"Geçmiş"</string>
@@ -118,6 +112,7 @@
     <string name="contextmenu_copylink" msgid="5153657160294534270">"Bağlantı URL\'sini kopyala"</string>
     <string name="contextmenu_download_image" msgid="4243829645180686912">"Görseli kaydet"</string>
     <string name="contextmenu_view_image" msgid="3870625602053600905">"Görseli görüntüle"</string>
+    <string name="contextmenu_set_wallpaper" msgid="3691902960115350686">"Duvar kağıdı olarak ayarla"</string>
     <string name="contextmenu_dial_dot" msgid="5856550683415933806">"Ara..."</string>
     <string name="contextmenu_add_contact" msgid="3183511922223645716">"Kişi ekle"</string>
     <string name="contextmenu_send_mail" msgid="1014513374828775660">"E-posta gönder"</string>
@@ -134,8 +129,14 @@
     <string name="pref_content_javascript" msgid="4570972030299516843">"JavaScript\'i etkinleştir"</string>
     <string name="pref_content_open_in_background" msgid="824123779725118663">"Arka planda aç"</string>
     <string name="pref_content_plugins" msgid="7231944644794301582">"Eklentileri etkinleştir"</string>
+  <string-array name="pref_content_plugins_choices">
+    <item msgid="6745108155096660725">"Her zaman açık"</item>
+    <item msgid="2484126708670016519">"İsteğe bağlı"</item>
+    <item msgid="8547442717307793863">"Kapalı"</item>
+  </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_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>
     <string name="pref_content_landscape_only" msgid="2022546812766219672">"Yalnızca yatay görüntü"</string>
@@ -190,24 +191,23 @@
     <string name="pref_content_load_page_summary" msgid="8792093504054149369">"Yeni açılan sayfaların genel görünümünü göster"</string>
     <string name="pref_extras_title" msgid="3091250467679722382">"Gelişmiş ayarlar"</string>
     <string name="pref_extras_website_settings" msgid="67866640052455549">"Web sitesi ayarları"</string>
-    <string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Her web sitesi için gelişmiş ayarları görüntüle"</string>
+    <string name="pref_extras_website_settings_summary" msgid="1656771443223494406">"Her web sitesi için ayrı düzenlenebilen gelişmiş ayarlar"</string>
     <string name="pref_extras_reset_default" msgid="8904000515846202110">"Varsayılana sıfırla"</string>
-    <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Tüm tarayıcı verilerini temizle ve tüm ayarları varsayılana sıfırla"</string>
-    <string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"Tüm tarayıcı verileri silinecek ve ayarlar varsayılan değerlere geri döndürülecek."</string>
+    <string name="pref_extras_reset_default_summary" msgid="4247870778270414501">"Varsayılan ayarları geri yükle"</string>
+    <string name="pref_extras_reset_default_dlg" msgid="6640261575874704022">"Ayarlar, varsayılan değerlere döndürülecek."</string>
     <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Varsayılana sıfırla"</string>
     <string name="pref_development_title" msgid="3263854204533056480">"Hata Ayıklama"</string>
     <string name="pref_default_text_encoding" msgid="5742965543955558478">"Metin kodlama"</string>
   <string-array name="pref_default_text_encoding_choices">
     <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
     <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
-    <item msgid="7143715548814380950">"Japonca (ISO-2022-JP)"</item>
-    <item msgid="5111312120564516587">"Japonca (SHIFT_JIS)"</item>
-    <item msgid="6545734186479713946">"Japonca (EUC-JP)"</item>
+    <item msgid="6122474363777211732">"Çince (GBK)"</item>
+    <item msgid="373372275931607040">"Çince (Big5)"</item>
+    <item msgid="891615911084608570">"Japonca (ISO-2022-JP)"</item>
+    <item msgid="5589150448475151241">"Japonca (SHIFT_JIS)"</item>
+    <item msgid="7356792686950371843">"Japonca (EUC-JP)"</item>
   </string-array>
     <string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Metin kodlama"</string>
-    <string name="pref_default_text_encoding_default" msgid="5272126711231936722">"Latin-1"</string>
-    <string name="browserFrameRedirect" msgid="7049675479777828343">"Yeniden yönlendir"</string>
-    <string name="browserFrame307Post" msgid="1429094844669510768">"Bu web sayfası yeniden yönlendiriliyor. Yazılı form verileriniz yeni konuma tekrar gönderilsin mi?"</string>
     <string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Veri bağlantısı sorunu"</string>
     <string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Sorunlu dosya"</string>
     <string name="browserFrameFormResubmitLabel" msgid="2685923472682180360">"Doğrula"</string>
@@ -234,13 +234,12 @@
     <string name="download_unknown_filename" msgid="4013465542563652175">"&lt;Bilinmiyor&gt;"</string>
     <string name="download_menu_open" msgid="4888327480367757513">"Aç"</string>
     <string name="download_menu_clear" msgid="6264454531553418124">"Listeden temizle"</string>
+    <string name="download_menu_delete" msgid="8815502136393894148">"Sil"</string>
     <string name="download_menu_cancel" msgid="2545333007601851574">"İndirme işlemini iptal et"</string>
     <string name="download_menu_cancel_all" msgid="2136550823151999166">"Tüm indirme işlemlerini iptal et"</string>
-    <string name="download_menu_clear_all" msgid="7423737413377703862">"Listeyi temizle"</string>
-    <string name="download_clear_dlg_title" msgid="7961996329529777390">"Temizle"</string>
-    <string name="download_clear_dlg_msg" msgid="8056013815679757669">"Tüm öğeler listeden silinecek ve tarayıcı önbelleğinden kaldırılacak."</string>
     <string name="download_cancel_dlg_title" msgid="8909108500262799748">"İndirme işlemlerini iptal et"</string>
     <string name="download_cancel_dlg_msg" msgid="6285389170052357797">"<xliff:g id="DOWNLOAD_COUNT">%d</xliff:g> indirme işleminin tümü iptal edilecek ve indirme geçmişinden temizlenecek."</string>
+    <string name="download_delete_file" msgid="5330036497843073249">"Dosya silinecek"</string>
     <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>
@@ -248,26 +247,24 @@
     <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>
-    <string name="download_no_application" msgid="5054596425887523234">"Bu dosyayı açmak için hiçbir uygulama bulunamadı."</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>
     <string name="download_error" msgid="413496839831257187">"İndirme işlemi başarısız."</string>
     <string name="download_success" msgid="2279041638155595203">"<xliff:g id="FILE">%s</xliff:g> İndirme işlemi tamamlandı."</string>
-    <string name="download_running" msgid="2622942231322015059">"İndiriliyor..."</string>
-    <string name="download_pending" msgid="2599683668575349559">"İndirme işlemi başlatılıyor..."</string>
-    <string name="download_pending_network" msgid="6548714525679461053">"Veri bağlantısı bekleniyor..."</string>
-    <string name="download_running_paused" msgid="6418029352085656495">"Veri bağlantısı bekleniyor..."</string>
+    <string name="download_running" msgid="2622942231322015059">"İndiriliyor…"</string>
+    <string name="download_pending" msgid="2599683668575349559">"İndirme işlemi başlatılıyor…"</string>
+    <string name="download_pending_network" msgid="6548714525679461053">"Veri bağlantısı için bekleniyor…"</string>
+    <string name="download_running_paused" msgid="6418029352085656495">"Veri bağlantısı için bekleniyor…"</string>
     <string name="download_canceled" msgid="6057083743144492515">"İndirme işlemi iptal edildi."</string>
     <string name="download_not_acceptable" msgid="313769696131563652">"İndirilemiyor. Söz konusu içerik bu telefonda desteklenmiyor."</string>
     <string name="download_file_error" msgid="1206648050615176113">"İndirme işlemi tamamlanamıyor. Yeterli alan yok."</string>
     <string name="download_length_required" msgid="9038605488460437406">"İndirilemiyor. Öğenin boyutu belirlenemiyor."</string>
     <string name="download_precondition_failed" msgid="8327584102874295580">"İndirme işlemi kesintiye uğradı. Sürdürülemez."</string>
-    <string name="activity_instrumentation_test_runner" msgid="8215091309334005029">"Tarayıcı Test Aracı"</string>
     <string name="search_the_web" msgid="6046130189241962337">"Web\'de ara"</string>
     <string name="webstorage_outofspace_notification_title" msgid="1160474608059771788">"Tarayıcı deposu dolu"</string>
     <string name="webstorage_outofspace_notification_text" msgid="7341075135051829692">"Alan açmak için tıklayın."</string>
     <string name="webstorage_clear_data_title" msgid="689484577124333977">"Depolanmış verileri temizle"</string>
-    <string name="webstorage_clear_data_summary" msgid="3523128713743907805">"Bu web sitesi ile ilişkilendirilmiş tüm veritabanlarını kaldır"</string>
     <string name="webstorage_clear_data_dialog_title" msgid="345457466368974706">"Depolanmış verileri temizle"</string>
     <string name="webstorage_clear_data_dialog_message" msgid="6678281256970470125">"Bu web sitesi tarafından depolanmış tüm veriler silinecek"</string>
     <string name="webstorage_clear_data_dialog_ok_button" msgid="2516563534211898636">"Tümünü temizle"</string>
@@ -278,6 +275,8 @@
     <string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Konumu paylaş"</string>
     <string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Reddet"</string>
     <string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Tercihi anımsa"</string>
+    <string name="geolocation_permissions_prompt_toast_allowed" msgid="987286072035125498">"Bu site konum bilginize erişebilir. Bunu, Ayarlar -&gt; Web sitesi ayarlarından değiştirin"</string>
+    <string name="geolocation_permissions_prompt_toast_disallowed" msgid="7695100950212692515">"Bu site konum bilginize erişemiyor. Bunu, Ayarlar -&gt; Web sitesi ayarlarından değiştirin"</string>
     <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Konum erişimini temizle"</string>
     <string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Bu site şu anda konumunuza erişebilir"</string>
     <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Bu site şu anda konumunuza erişemiyor"</string>
@@ -290,5 +289,5 @@
     <string name="website_settings_clear_all_dialog_message" msgid="6150502090601476333">"Web sitesi verilerinin ve konum izinlerinin tümü silinecek."</string>
     <string name="website_settings_clear_all_dialog_ok_button" msgid="6401582240627669431">"Tüm verileri sil"</string>
     <string name="website_settings_clear_all_dialog_cancel_button" msgid="1896757051856611674">"İptal"</string>
-    <string name="zoom_overview_button_text" msgid="4146579940085488881">"Genel Bakış"</string>
+    <string name="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Duvar kağıdı ayarlanıyor..."</string>
 </resources>
diff --git a/res/values-zh-rCN/arrays.xml b/res/values-zh-rCN/arrays.xml
deleted file mode 100644
index cf00e8f..0000000
--- a/res/values-zh-rCN/arrays.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="webstorage_quota_entries">
-    <item msgid="5433313236875537673">"不允许设置配额"</item>
-    <item msgid="7374272188672967690">"5 MB"</item>
-    <item msgid="8699352701856136738">"10 MB"</item>
-    <item msgid="2018822431469084862">"30 MB"</item>
-    <item msgid="5383642976774534074">"100 MB"</item>
-  </string-array>
-  <string-array name="webstorage_quota_entries_values">
-    <item msgid="7620410313725236055">"0"</item>
-    <item msgid="4302688814760304206">"5"</item>
-    <item msgid="7291990205847586165">"10"</item>
-    <item msgid="916913372287112423">"30"</item>
-    <item msgid="3437188301324229987">"100"</item>
-  </string-array>
-</resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index fa152b2..22fefa2 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -1,21 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--  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.
--->
+ -->
+
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="1935869255545976415">"浏览器"</string>
+    <string name="choose_upload" msgid="3649366287575002063">"选择要上传的文件"</string>
     <string name="new_tab" msgid="4505722538297295141">"新窗口"</string>
     <string name="active_tabs" msgid="3050623868203544623">"窗口"</string>
     <string name="tab_bookmarks" msgid="2305793036003473653">"书签"</string>
@@ -24,7 +26,7 @@
     <string name="added_to_bookmarks" msgid="1020224130695956728">"已添加到书签"</string>
     <string name="removed_from_bookmarks" msgid="6063705902028438800">"从书签中删除"</string>
     <string name="sign_in_to" msgid="5939425800148759165">"登录 <xliff:g id="HOSTNAME">%s1</xliff:g>“<xliff:g id="REALM">%s2</xliff:g>”"</string>
-    <string name="username" msgid="5057566336518215922">"名称"</string>
+    <string name="username" msgid="5057566336518215922">"姓名"</string>
     <string name="password" msgid="1177138552305184404">"密码"</string>
     <string name="action" msgid="183105774472071343">"登录"</string>
     <string name="bookmarks_search" msgid="5229596268214362873">"浏览器"</string>
@@ -39,7 +41,7 @@
     <string name="title_bar_loading" msgid="7438217780834640678">"正在载入..."</string>
     <string name="page_info" msgid="4048529256302257195">"网页信息"</string>
     <string name="page_info_view" msgid="5303490449842635158">"查看网页信息"</string>
-    <string name="page_info_address" msgid="2222306609532903254">"地址:"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"地址:"</string>
     <string name="ssl_warnings_header" msgid="79744901983636370">"该网站的安全证书有问题。"</string>
     <string name="ssl_continue" msgid="8031515015829358457">"继续"</string>
     <string name="security_warning" msgid="6607795404322797541">"安全警告"</string>
@@ -52,22 +54,21 @@
     <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"该证书有效。"</string>
     <string name="issued_to" msgid="9032338008819841339">"颁发给:"</string>
     <string name="common_name" msgid="5745530093500062357">"常用名称:"</string>
-    <string name="org_name" msgid="8868889052889991293">"组织:"</string>
+    <string name="org_name" msgid="8868889052889991293">"组织:"</string>
     <string name="org_unit" msgid="4489056376307768196">"组织单位:"</string>
     <string name="issued_by" msgid="6959484326943152487">"颁发者:"</string>
     <string name="validity_period" msgid="57988851973181309">"有效期:"</string>
     <string name="issued_on" msgid="2082890654801808368">"颁发时间:"</string>
     <string name="expires_on" msgid="8061200430557020704">"有效期至:"</string>
-    <string name="retrieving_creds_dlg_msg" msgid="9207671133094039879">"正在检索登录详细信息..."</string>
     <string name="stopping" msgid="4839698519340302982">"正在停止..."</string>
     <string name="stop" msgid="5687251076030630074">"停止"</string>
     <string name="reload" msgid="8585220783228408062">"刷新"</string>
     <string name="back" msgid="8414603107175713668">"返回"</string>
-    <string name="forward" msgid="4288210890526641577">"前进"</string>
+    <string name="forward" msgid="4288210890526641577">"转发"</string>
     <string name="save" msgid="5922311934992468496">"确定"</string>
     <string name="do_not_save" msgid="6777633870113477714">"取消"</string>
-    <string name="location" msgid="969988560160364559">"位置"</string>
-    <string name="name" msgid="5990326151488445481">"名称"</string>
+    <string name="location" msgid="969988560160364559">"地点"</string>
+    <string name="name" msgid="5990326151488445481">"姓名"</string>
     <string name="http" msgid="2163722670597250102">"http://"</string>
     <string name="save_to_bookmarks" msgid="588165100024086565">"添加书签"</string>
     <string name="edit_bookmark" msgid="5024089053490231905">"编辑书签"</string>
@@ -82,8 +83,8 @@
     <string name="homepage_set" msgid="8768087280310966395">"主页已设置。"</string>
     <string name="bookmark_needs_title" msgid="6245900436119218187">"书签必须具有名称。"</string>
     <string name="bookmark_needs_url" msgid="7809876865972755158">"书签必须具有位置。"</string>
-    <string name="empty_bookmark" msgid="7008697085928540511">"无法创建空书签。"</string>
     <string name="bookmark_url_not_valid" msgid="6719785633980202419">"网址无效。"</string>
+    <string name="bookmark_cannot_save_url" msgid="791722768778386941">"无法将此网址添加到书签。"</string>
     <string name="delete_bookmark" msgid="2422989994934201992">"删除"</string>
     <string name="bookmark_page" msgid="6845189305130307274">"将上次查看过的网页加为书签"</string>
     <string name="switch_to_thumbnails" msgid="5493351529609043151">"缩略图视图"</string>
@@ -91,22 +92,15 @@
     <string name="current_page" msgid="7510129573681663135">"来源 "</string>
     <string name="delete_bookmark_warning" msgid="758043186202032205">"将会删除书签“<xliff:g id="BOOKMARK">%s</xliff:g>”。"</string>
     <string name="open_in_new_window" msgid="6596775546468054510">"在新窗口中打开"</string>
-    <string name="new_window" msgid="8117889615360211551">"新窗口"</string>
     <string name="goto_dot" msgid="3895839050522602723">"转至"</string>
-    <string name="find_dot" msgid="6259312434696611957">"在网页上查找"</string>
+    <string name="find_dot" msgid="6259312434696611957">"页内查找"</string>
     <string name="select_dot" msgid="6299170761900561967">"选择文本"</string>
-    <string name="view_tabs" msgid="1119097492003550564">"窗口概述"</string>
-    <string name="view_tabs_condensed" msgid="5803955493821945369">"窗口"</string>
     <string name="tab_picker_title" msgid="864478399057782913">"当前窗口"</string>
-    <string name="tab_picker_view_tab" msgid="2984342364915347656">"查看"</string>
-    <string name="tab_picker_new_tab" msgid="3080280018986866528">"新窗口"</string>
     <string name="tab_picker_remove_tab" msgid="630087809802479397">"关闭"</string>
-    <string name="tab_picker_bookmark" msgid="1084409404198995477">"书签"</string>
-    <string name="tab_picker_send_url" msgid="9102803487525950021">"分享链接"</string>
     <string name="bookmarks" msgid="1961279134885867815">"书签"</string>
     <string name="shortcut_bookmark" msgid="3974876480401135895">"书签"</string>
     <string name="history" msgid="2451240511251410032">"历史记录"</string>
-    <string name="menu_view_download" msgid="2124570321712995120">"下载"</string>
+    <string name="menu_view_download" msgid="2124570321712995120">"下载内容"</string>
     <string name="copy_page_url" msgid="7635062169011319208">"复制网页网址"</string>
     <string name="share_page" msgid="593756995297268343">"分享网页"</string>
     <string name="contextmenu_openlink" msgid="7237961252214188935">"打开"</string>
@@ -118,7 +112,8 @@
     <string name="contextmenu_copylink" msgid="5153657160294534270">"复制链接网址"</string>
     <string name="contextmenu_download_image" msgid="4243829645180686912">"保存图片"</string>
     <string name="contextmenu_view_image" msgid="3870625602053600905">"查看图片"</string>
-    <string name="contextmenu_dial_dot" msgid="5856550683415933806">"拔号..."</string>
+    <string name="contextmenu_set_wallpaper" msgid="3691902960115350686">"设置为壁纸"</string>
+    <string name="contextmenu_dial_dot" msgid="5856550683415933806">"拨打…"</string>
     <string name="contextmenu_add_contact" msgid="3183511922223645716">"添加联系人"</string>
     <string name="contextmenu_send_mail" msgid="1014513374828775660">"发送电子邮件"</string>
     <string name="contextmenu_map" msgid="7471390435434034912">"地图"</string>
@@ -134,8 +129,14 @@
     <string name="pref_content_javascript" msgid="4570972030299516843">"启用 JavaScript"</string>
     <string name="pref_content_open_in_background" msgid="824123779725118663">"在后方打开"</string>
     <string name="pref_content_plugins" msgid="7231944644794301582">"启用插件"</string>
+  <string-array name="pref_content_plugins_choices">
+    <item msgid="6745108155096660725">"始终打开"</item>
+    <item msgid="2484126708670016519">"在需要时打开"</item>
+    <item msgid="8547442717307793863">"关"</item>
+  </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"在当前窗口后方打开新窗口"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"设置主页"</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>
     <string name="pref_content_landscape_only" msgid="2022546812766219672">"仅以横向模式显示"</string>
@@ -190,24 +191,23 @@
     <string name="pref_content_load_page_summary" msgid="8792093504054149369">"显示新打开网页的概览"</string>
     <string name="pref_extras_title" msgid="3091250467679722382">"高级设置"</string>
     <string name="pref_extras_website_settings" msgid="67866640052455549">"网站设置"</string>
-    <string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"查看各网站的高级设置"</string>
+    <string name="pref_extras_website_settings_summary" msgid="1656771443223494406">"各网站的高级设置"</string>
     <string name="pref_extras_reset_default" msgid="8904000515846202110">"重置为默认设置"</string>
-    <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"清除所有浏览器数据并恢复所有默认设置"</string>
-    <string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"此操作将会刪除所有浏览器数据并将设置恢复为默认值。"</string>
+    <string name="pref_extras_reset_default_summary" msgid="4247870778270414501">"还原默认设置"</string>
+    <string name="pref_extras_reset_default_dlg" msgid="6640261575874704022">"设置将恢复为默认值。"</string>
     <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"重置为默认设置"</string>
     <string name="pref_development_title" msgid="3263854204533056480">"调试"</string>
     <string name="pref_default_text_encoding" msgid="5742965543955558478">"文字编码"</string>
   <string-array name="pref_default_text_encoding_choices">
     <item msgid="7275223955790513818">"拉丁语-1 (ISO-8859-1)"</item>
     <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
-    <item msgid="7143715548814380950">"日文 (ISO-2022-JP)"</item>
-    <item msgid="5111312120564516587">"日文 (SHIFT_JIS)"</item>
-    <item msgid="6545734186479713946">"日文 (EUC-JP)"</item>
+    <item msgid="6122474363777211732">"中文 (GBK)"</item>
+    <item msgid="373372275931607040">"中文 (Big5)"</item>
+    <item msgid="891615911084608570">"日语 (ISO-2022-JP)"</item>
+    <item msgid="5589150448475151241">"日语 (SHIFT_JIS)"</item>
+    <item msgid="7356792686950371843">"日语 (EUC-JP)"</item>
   </string-array>
     <string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"文字编码"</string>
-    <string name="pref_default_text_encoding_default" msgid="5272126711231936722">"Latin-1"</string>
-    <string name="browserFrameRedirect" msgid="7049675479777828343">"重定向"</string>
-    <string name="browserFrame307Post" msgid="1429094844669510768">"该网页正在进行重定向。是否要将您键入的表单数据重新发送到新位置?"</string>
     <string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"数据连接性问题"</string>
     <string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"文件有问题"</string>
     <string name="browserFrameFormResubmitLabel" msgid="2685923472682180360">"确认"</string>
@@ -217,10 +217,10 @@
     <string name="clear_history" msgid="5998307092715979619">"清除历史记录"</string>
     <string name="browser_history" msgid="1038987118290272525">"最近访问过的网页"</string>
     <string name="empty_history" msgid="8738772352308207274">"浏览器历史记录为空。"</string>
-    <string name="add_new_bookmark" msgid="8086367791400349049">"添加书签..."</string>
+    <string name="add_new_bookmark" msgid="8086367791400349049">"添加书签…"</string>
     <string name="add_bookmark_short" msgid="3783984330998103735">"添加"</string>
     <string name="search_hint" msgid="4647356319916631820">"搜索或键入网址"</string>
-    <string name="search_button_text" msgid="5235226933877634410">"转至"</string>
+    <string name="search_button_text" msgid="5235226933877634410">"开始"</string>
     <string name="search_settings_description" msgid="1422401062529014107">"书签和网络历史记录"</string>
     <string name="attention" msgid="3473639060042811244">"注意"</string>
     <string name="popup_window_attempt" msgid="2673111696288657989">"该网站试图打开一个弹出式窗口。"</string>
@@ -234,21 +234,20 @@
     <string name="download_unknown_filename" msgid="4013465542563652175">"&lt;未知&gt;"</string>
     <string name="download_menu_open" msgid="4888327480367757513">"打开"</string>
     <string name="download_menu_clear" msgid="6264454531553418124">"从列表中清除"</string>
+    <string name="download_menu_delete" msgid="8815502136393894148">"删除"</string>
     <string name="download_menu_cancel" msgid="2545333007601851574">"取消下载"</string>
     <string name="download_menu_cancel_all" msgid="2136550823151999166">"取消所有下载"</string>
-    <string name="download_menu_clear_all" msgid="7423737413377703862">"清除列表"</string>
-    <string name="download_clear_dlg_title" msgid="7961996329529777390">"清除"</string>
-    <string name="download_clear_dlg_msg" msgid="8056013815679757669">"所有下载项都会从列表中清除并从浏览器缓存中删除。"</string>
     <string name="download_cancel_dlg_title" msgid="8909108500262799748">"取消下载"</string>
     <string name="download_cancel_dlg_msg" msgid="6285389170052357797">"所有 <xliff:g id="DOWNLOAD_COUNT">%d</xliff:g> 项下载都会取消并从下载历史记录中清除。"</string>
-    <string name="download_file_error_dlg_title" msgid="2693630283595384874">"空间不足"</string>
+    <string name="download_delete_file" msgid="5330036497843073249">"文件将被删除"</string>
+    <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_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>
-    <string name="download_no_application" msgid="5054596425887523234">"无法找到可打开此文件的应用程序。"</string>
+    <string name="download_no_application_title" msgid="1286056729168874295">"无法打开文件"</string>
     <string name="retry" msgid="1835923075542266721">"重试"</string>
     <string name="no_downloads" msgid="3947445710685021498">"下载历史记录为空。"</string>
     <string name="download_error" msgid="413496839831257187">"下载不成功。"</string>
@@ -262,12 +261,10 @@
     <string name="download_file_error" msgid="1206648050615176113">"无法完成下载,存储空间不足。"</string>
     <string name="download_length_required" msgid="9038605488460437406">"无法下载,因为无法确定该下载项的大小。"</string>
     <string name="download_precondition_failed" msgid="8327584102874295580">"下载中断,无法重新开始。"</string>
-    <string name="activity_instrumentation_test_runner" msgid="8215091309334005029">"浏览器测试运行程序"</string>
     <string name="search_the_web" msgid="6046130189241962337">"搜索网页"</string>
     <string name="webstorage_outofspace_notification_title" msgid="1160474608059771788">"浏览器存储空间已满"</string>
     <string name="webstorage_outofspace_notification_text" msgid="7341075135051829692">"点击可释放空间。"</string>
     <string name="webstorage_clear_data_title" msgid="689484577124333977">"清除存储的数据"</string>
-    <string name="webstorage_clear_data_summary" msgid="3523128713743907805">"删除所有与此网站相关联的数据库"</string>
     <string name="webstorage_clear_data_dialog_title" msgid="345457466368974706">"清除存储的数据"</string>
     <string name="webstorage_clear_data_dialog_message" msgid="6678281256970470125">"此时将删除由此网站存储的所有数据"</string>
     <string name="webstorage_clear_data_dialog_ok_button" msgid="2516563534211898636">"全部清除"</string>
@@ -278,6 +275,8 @@
     <string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"共享位置信息"</string>
     <string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"拒绝"</string>
     <string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"记住偏好设置"</string>
+    <string name="geolocation_permissions_prompt_toast_allowed" msgid="987286072035125498">"此网站可以访问您所在的地点。请在“设置”-&gt;“网站设置”中进行相应更改"</string>
+    <string name="geolocation_permissions_prompt_toast_disallowed" msgid="7695100950212692515">"此网站无法访问您所在的地点。请在“设置”-&gt;“网站设置”中进行相应更改"</string>
     <string name="geolocation_settings_page_title" msgid="1745477985097536528">"取消位置信息访问权限"</string>
     <string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"此网站目前可访问您的位置信息"</string>
     <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"此网站目前不能访问您的位置信息"</string>
@@ -290,5 +289,5 @@
     <string name="website_settings_clear_all_dialog_message" msgid="6150502090601476333">"此操作将会删除所有网站数据和位置权限。"</string>
     <string name="website_settings_clear_all_dialog_ok_button" msgid="6401582240627669431">"删除所有数据"</string>
     <string name="website_settings_clear_all_dialog_cancel_button" msgid="1896757051856611674">"取消"</string>
-    <string name="zoom_overview_button_text" msgid="4146579940085488881">"概览"</string>
+    <string name="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"正在设置壁纸..."</string>
 </resources>
diff --git a/res/values-zh-rTW/arrays.xml b/res/values-zh-rTW/arrays.xml
deleted file mode 100644
index 60e6ec9..0000000
--- a/res/values-zh-rTW/arrays.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string-array name="webstorage_quota_entries">
-    <item msgid="5433313236875537673">"未獲得任何配額"</item>
-    <item msgid="7374272188672967690">"5 MB"</item>
-    <item msgid="8699352701856136738">"10 MB"</item>
-    <item msgid="2018822431469084862">"30 MB"</item>
-    <item msgid="5383642976774534074">"100 MB"</item>
-  </string-array>
-  <string-array name="webstorage_quota_entries_values">
-    <item msgid="7620410313725236055">"0"</item>
-    <item msgid="4302688814760304206">"5"</item>
-    <item msgid="7291990205847586165">"10"</item>
-    <item msgid="916913372287112423">"30"</item>
-    <item msgid="3437188301324229987">"100"</item>
-  </string-array>
-</resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index d1e230a..33f3feb 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -1,21 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--  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.
--->
+ -->
+
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="1935869255545976415">"瀏覽器"</string>
+    <string name="choose_upload" msgid="3649366287575002063">"選擇要上載的檔案"</string>
     <string name="new_tab" msgid="4505722538297295141">"新視窗"</string>
     <string name="active_tabs" msgid="3050623868203544623">"視窗"</string>
     <string name="tab_bookmarks" msgid="2305793036003473653">"書籤"</string>
@@ -58,7 +60,6 @@
     <string name="validity_period" msgid="57988851973181309">"合法性:"</string>
     <string name="issued_on" msgid="2082890654801808368">"發給:"</string>
     <string name="expires_on" msgid="8061200430557020704">"有效日期:"</string>
-    <string name="retrieving_creds_dlg_msg" msgid="9207671133094039879">"擷取登入資訊…"</string>
     <string name="stopping" msgid="4839698519340302982">"停止中…"</string>
     <string name="stop" msgid="5687251076030630074">"停止"</string>
     <string name="reload" msgid="8585220783228408062">"重新整理"</string>
@@ -82,8 +83,8 @@
     <string name="homepage_set" msgid="8768087280310966395">"已設定為首頁。"</string>
     <string name="bookmark_needs_title" msgid="6245900436119218187">"請輸入書籤名稱。"</string>
     <string name="bookmark_needs_url" msgid="7809876865972755158">"請選取書籤位置。"</string>
-    <string name="empty_bookmark" msgid="7008697085928540511">"無法建立空白書籤。"</string>
     <string name="bookmark_url_not_valid" msgid="6719785633980202419">"網址無效。"</string>
+    <string name="bookmark_cannot_save_url" msgid="791722768778386941">"無法將此網址加入書籤。"</string>
     <string name="delete_bookmark" msgid="2422989994934201992">"刪除"</string>
     <string name="bookmark_page" msgid="6845189305130307274">"將最後瀏覽的網頁加入書籤"</string>
     <string name="switch_to_thumbnails" msgid="5493351529609043151">"縮圖檢視"</string>
@@ -91,18 +92,11 @@
     <string name="current_page" msgid="7510129573681663135">"來源 "</string>
     <string name="delete_bookmark_warning" msgid="758043186202032205">"刪除「<xliff:g id="BOOKMARK">%s</xliff:g>」書籤?"</string>
     <string name="open_in_new_window" msgid="6596775546468054510">"在新視窗開啟"</string>
-    <string name="new_window" msgid="8117889615360211551">"新視窗"</string>
     <string name="goto_dot" msgid="3895839050522602723">"前往"</string>
     <string name="find_dot" msgid="6259312434696611957">"在頁面中尋找"</string>
     <string name="select_dot" msgid="6299170761900561967">"選取文字"</string>
-    <string name="view_tabs" msgid="1119097492003550564">"視窗總覽"</string>
-    <string name="view_tabs_condensed" msgid="5803955493821945369">"視窗"</string>
     <string name="tab_picker_title" msgid="864478399057782913">"目前視窗"</string>
-    <string name="tab_picker_view_tab" msgid="2984342364915347656">"檢視"</string>
-    <string name="tab_picker_new_tab" msgid="3080280018986866528">"新視窗"</string>
     <string name="tab_picker_remove_tab" msgid="630087809802479397">"關閉"</string>
-    <string name="tab_picker_bookmark" msgid="1084409404198995477">"加入書籤"</string>
-    <string name="tab_picker_send_url" msgid="9102803487525950021">"分享連結"</string>
     <string name="bookmarks" msgid="1961279134885867815">"書籤"</string>
     <string name="shortcut_bookmark" msgid="3974876480401135895">"書籤"</string>
     <string name="history" msgid="2451240511251410032">"記錄"</string>
@@ -118,6 +112,7 @@
     <string name="contextmenu_copylink" msgid="5153657160294534270">"複製連結網址"</string>
     <string name="contextmenu_download_image" msgid="4243829645180686912">"儲存圖片"</string>
     <string name="contextmenu_view_image" msgid="3870625602053600905">"檢視圖片"</string>
+    <string name="contextmenu_set_wallpaper" msgid="3691902960115350686">"設為桌布"</string>
     <string name="contextmenu_dial_dot" msgid="5856550683415933806">"撥打…"</string>
     <string name="contextmenu_add_contact" msgid="3183511922223645716">"新增聯絡人"</string>
     <string name="contextmenu_send_mail" msgid="1014513374828775660">"傳送電子郵件"</string>
@@ -134,8 +129,14 @@
     <string name="pref_content_javascript" msgid="4570972030299516843">"啟用 JavaScript"</string>
     <string name="pref_content_open_in_background" msgid="824123779725118663">"在背景中開啟"</string>
     <string name="pref_content_plugins" msgid="7231944644794301582">"啟用外掛程式"</string>
+  <string-array name="pref_content_plugins_choices">
+    <item msgid="6745108155096660725">"永遠開啟"</item>
+    <item msgid="2484126708670016519">"隨選"</item>
+    <item msgid="8547442717307793863">"關閉"</item>
+  </string-array>
     <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"在目前視窗的後面開啟新視窗"</string>
     <string name="pref_content_homepage" msgid="6082437160778559806">"設定首頁"</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>
     <string name="pref_content_landscape_only" msgid="2022546812766219672">"僅以水平模式顯示"</string>
@@ -190,24 +191,23 @@
     <string name="pref_content_load_page_summary" msgid="8792093504054149369">"顯示新開啟網頁的總覽畫面"</string>
     <string name="pref_extras_title" msgid="3091250467679722382">"進階設定"</string>
     <string name="pref_extras_website_settings" msgid="67866640052455549">"網站設定"</string>
-    <string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"查看個別網站的進階設定"</string>
+    <string name="pref_extras_website_settings_summary" msgid="1656771443223494406">"個別網站的進階設定"</string>
     <string name="pref_extras_reset_default" msgid="8904000515846202110">"還原至初始設定"</string>
-    <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"清除瀏覽器所有資料,並還原至初始設定"</string>
-    <string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"即將刪除所有瀏覽器資料,並將設定還原為預設值。"</string>
+    <string name="pref_extras_reset_default_summary" msgid="4247870778270414501">"還原預設設定"</string>
+    <string name="pref_extras_reset_default_dlg" msgid="6640261575874704022">"設定會還原為預設值。"</string>
     <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"還原至初始設定"</string>
     <string name="pref_development_title" msgid="3263854204533056480">"偵錯"</string>
     <string name="pref_default_text_encoding" msgid="5742965543955558478">"文字編碼"</string>
   <string-array name="pref_default_text_encoding_choices">
     <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
     <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
-    <item msgid="7143715548814380950">"Japanese (ISO-2022-JP)"</item>
-    <item msgid="5111312120564516587">"Japanese (SHIFT_JIS)"</item>
-    <item msgid="6545734186479713946">"Japanese (EUC-JP)"</item>
+    <item msgid="6122474363777211732">"中文 (GBK)"</item>
+    <item msgid="373372275931607040">"中文 (Big5)"</item>
+    <item msgid="891615911084608570">"日文 (ISO-2022-JP)"</item>
+    <item msgid="5589150448475151241">"日文 (SHIFT_JIS)"</item>
+    <item msgid="7356792686950371843">"日文 (EUC-JP)"</item>
   </string-array>
     <string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"文字編碼"</string>
-    <string name="pref_default_text_encoding_default" msgid="5272126711231936722">"Latin-1"</string>
-    <string name="browserFrameRedirect" msgid="7049675479777828343">"轉址"</string>
-    <string name="browserFrame307Post" msgid="1429094844669510768">"系統正將您重新導向至新的網頁,要將已輸入的表單資料重新傳送至新的網頁嗎?"</string>
     <string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"資料連線問題"</string>
     <string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"檔案有問題"</string>
     <string name="browserFrameFormResubmitLabel" msgid="2685923472682180360">"確認"</string>
@@ -231,16 +231,15 @@
     <string name="too_many_subwindows_dialog_title" msgid="3805453941587725944">"已開啟快顯視窗"</string>
     <string name="too_many_subwindows_dialog_message" msgid="5827289829907966657">"無法開啟新的快顯視窗,同時只能有一個快顯視窗存在。"</string>
     <string name="download_title" msgid="2122874021047565594">"下載記錄"</string>
-    <string name="download_unknown_filename" msgid="4013465542563652175">"&lt;未知&gt;"</string>
+    <string name="download_unknown_filename" msgid="4013465542563652175">"&lt;不明&gt;"</string>
     <string name="download_menu_open" msgid="4888327480367757513">"開啟"</string>
     <string name="download_menu_clear" msgid="6264454531553418124">"清除表單列表"</string>
+    <string name="download_menu_delete" msgid="8815502136393894148">"刪除"</string>
     <string name="download_menu_cancel" msgid="2545333007601851574">"取消下載"</string>
     <string name="download_menu_cancel_all" msgid="2136550823151999166">"取消所有下載"</string>
-    <string name="download_menu_clear_all" msgid="7423737413377703862">"清除清單"</string>
-    <string name="download_clear_dlg_title" msgid="7961996329529777390">"清除"</string>
-    <string name="download_clear_dlg_msg" msgid="8056013815679757669">"所有清單中的項目會被清除,並從快取中移除。"</string>
     <string name="download_cancel_dlg_title" msgid="8909108500262799748">"取消下載"</string>
     <string name="download_cancel_dlg_msg" msgid="6285389170052357797">"所有 (<xliff:g id="DOWNLOAD_COUNT">%d</xliff:g>) 下載會取消並從下載記錄中清除。"</string>
+    <string name="download_delete_file" msgid="5330036497843073249">"即將刪除檔案"</string>
     <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>
@@ -248,7 +247,7 @@
     <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>
-    <string name="download_no_application" msgid="5054596425887523234">"找不到可以開啟這個檔案的應用程式。"</string>
+    <string name="download_no_application_title" msgid="1286056729168874295">"無法開啟檔案"</string>
     <string name="retry" msgid="1835923075542266721">"重試"</string>
     <string name="no_downloads" msgid="3947445710685021498">"下載記錄是空的。"</string>
     <string name="download_error" msgid="413496839831257187">"下載失敗"</string>
@@ -262,12 +261,10 @@
     <string name="download_file_error" msgid="1206648050615176113">"無法完成下載。儲存空間不足。"</string>
     <string name="download_length_required" msgid="9038605488460437406">"無法下載。物件大小無法估計。"</string>
     <string name="download_precondition_failed" msgid="8327584102874295580">"下載中斷。無法續傳。"</string>
-    <string name="activity_instrumentation_test_runner" msgid="8215091309334005029">"Browser Test Runner"</string>
     <string name="search_the_web" msgid="6046130189241962337">"搜尋網頁"</string>
     <string name="webstorage_outofspace_notification_title" msgid="1160474608059771788">"瀏覽器儲存空間已滿"</string>
     <string name="webstorage_outofspace_notification_text" msgid="7341075135051829692">"按一下可釋出儲存空間。"</string>
     <string name="webstorage_clear_data_title" msgid="689484577124333977">"清除儲存的資料"</string>
-    <string name="webstorage_clear_data_summary" msgid="3523128713743907805">"移除所有與此網站關聯的資料庫"</string>
     <string name="webstorage_clear_data_dialog_title" msgid="345457466368974706">"清除儲存的資料"</string>
     <string name="webstorage_clear_data_dialog_message" msgid="6678281256970470125">"即將刪除此網站儲存的所有資料"</string>
     <string name="webstorage_clear_data_dialog_ok_button" msgid="2516563534211898636">"全部清除"</string>
@@ -278,6 +275,8 @@
     <string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"分享位置資訊"</string>
     <string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"拒絕"</string>
     <string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"記住偏好設定"</string>
+    <string name="geolocation_permissions_prompt_toast_allowed" msgid="987286072035125498">"此網站可以存取您的位置資訊;您可以前往 [設定] -&gt; [網站設定] 變更此設定"</string>
+    <string name="geolocation_permissions_prompt_toast_disallowed" msgid="7695100950212692515">"此網站無法存取您的位置資訊;您可以前往 [設定] -&gt; [網站設定] 變更此設定"</string>
     <string name="geolocation_settings_page_title" msgid="1745477985097536528">"清除位置資訊存取權"</string>
     <string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"此網站目前可以存取您的位置資訊"</string>
     <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"此網站目前無法存取您的位置資訊"</string>
@@ -290,5 +289,5 @@
     <string name="website_settings_clear_all_dialog_message" msgid="6150502090601476333">"即將刪除所有網站資料和位置存取權限。"</string>
     <string name="website_settings_clear_all_dialog_ok_button" msgid="6401582240627669431">"刪除所有資料"</string>
     <string name="website_settings_clear_all_dialog_cancel_button" msgid="1896757051856611674">"取消"</string>
-    <string name="zoom_overview_button_text" msgid="4146579940085488881">"總覽"</string>
+    <string name="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"設定桌布..."</string>
 </resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 72f1355..68bf253 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -31,9 +31,8 @@
     
     <color name="white">#ffffffff</color>
     <color name="black">#ff000000</color>
-    <color name="gray">#ffbbbbbb</color>
-    <color name="dark_gray">#ff777777</color>
+    
+    
 
     <color name="geolocation_permissions_prompt_background">#ffdddddd</color>
 </resources>
-
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 3bb6ffd..18a2144 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -13,11 +13,11 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- The name of the application. -->
     <string name="application_name">Browser</string>
-
+    <!-- Displayed with a file picker to choose a file to upload -->
+    <string name="choose_upload">Choose file for upload</string>
     <!-- Name of menu item of a new tab.  Also used in the title bar when displaying a new tab -->
     <string name="new_tab">New window</string>
     <!-- Name of menu item which brings up a list of the currently active tabs -->
@@ -118,8 +118,6 @@
     <!-- Label for an information field on an SSL Certificate Dialog -->
     <string name="expires_on">Expires on:</string>
 
-    <!-- Dialog that is shown while we are retrieving the login creds from the system -->
-    <string name="retrieving_creds_dlg_msg">Retrieving sign-in details\u2026</string>
     <!-- Toast informing the user that loading has stopped for the current page. -->
     <string name="stopping">Stopping\u2026</string>
     <!-- Menu item to stop the current page from loading. -->
@@ -166,10 +164,10 @@
     <string name="bookmark_needs_title">"Bookmark must have a name."</string>
         <!-- Error that appears in the title of Bookmark dialog when user selects OK with empty Location field -->
     <string name="bookmark_needs_url">"Bookmark must have a location."</string>
-        <!-- Error that appears in the title of Bookmark dialog when user selects OK with empty Name & Location fields -->
-    <string name="empty_bookmark">"Cannot create empty bookmark."</string>
         <!-- Error that appears in the title of Bookmark dialog when user selects OK with invalid URL -->
     <string name="bookmark_url_not_valid">URL is not valid.</string>
+        <!-- Error that appears in the Bookmark dialog when user selects OK with a URL of a type we cannot bookmark -->
+    <string name="bookmark_cannot_save_url">This URL cannot be bookmarked.</string>
         <!-- Title of a confirmation dialog when the user deletes a bookmark-->
     <string name="delete_bookmark">Delete</string>
     <!-- Menu item in the page that displays all bookmarks. It brings up a
@@ -194,9 +192,6 @@
     <string name="delete_bookmark_warning">Bookmark \"<xliff:g id="bookmark">%s</xliff:g>\" will be deleted.</string>
     <!-- Context Menu item to open the selected link in a new window -->
     <string name="open_in_new_window">Open in new window</string>
-    <!-- Appears in Current windows screen as label on blank + window; user 
-            selects this window to open a new browser window -->
-    <string name="new_window">New window</string>
     <!-- Menu item to open a dialog which allows the user to enter a url or do search-->
     <string name="goto_dot">Go</string>
     <!-- Menu item that opens up a dialog which allows the user to provide a
@@ -204,27 +199,10 @@
     <string name="find_dot">Find on page</string>
     <!-- Menu item to switch to text selection mode for copy and paste. -->
     <string name="select_dot">Select text</string>
-    <!-- Menu item which opens a screen which shows all the currently open
-            windows, and also allows them to create a new one. -->
-    <string name="view_tabs">Window overview</string>
-    <!-- Menu item which opens a screen which shows all the currently open
-            windows, and also allows them to create a new one. This is a shorter
-            alternate version of "view_tabs"-->
-    <string name="view_tabs_condensed">Windows</string>
     <!-- Title of current windows screen; appears in title bar -->
     <string name="tab_picker_title">Current windows</string>
-    <!-- Context Menu item to view the selected window on the window picker
-            screen -->
-    <string name="tab_picker_view_tab">View</string>
-    <!-- Menu item on the window picker screen to open a new window -->
-    <string name="tab_picker_new_tab">New window</string>
     <!-- Context Menu item to close the currently selected window -->
     <string name="tab_picker_remove_tab">Close</string>
-    <!-- Context Menu item to bookmark the currently selected window -->
-    <string name="tab_picker_bookmark">Bookmark</string>
-    <!-- Context Menu item from the bookmarks page to share the selected
-            bookmark  -->
-    <string name="tab_picker_send_url">Share link</string>
     <!-- Menu item to open the bookmarks page. This is a shorter version that
             is displayed with an icon -->
     <string name="bookmarks">Bookmarks</string>
@@ -263,6 +241,9 @@
     <string name="contextmenu_download_image">Save image</string>
     <!-- Context Menu item to view the image by itself in the browser -->
     <string name="contextmenu_view_image">View image</string>
+    <!-- Context Menu item to set the image as the home screen wallpaper -->
+    <string name="contextmenu_set_wallpaper">Set as wallpaper</string>
+
     <!-- Context Menu item to open the dialer app with the selected phone number
             -->
     <string name="contextmenu_dial_dot">Dial\u2026</string>
@@ -309,10 +290,23 @@
     <string name="pref_content_open_in_background">Open in background</string>
     <!-- Settings label -->
     <string name="pref_content_plugins">Enable plug-ins</string>
+    <!-- Plugin options -->
+    <string-array name="pref_content_plugins_choices">
+        <item>Always on</item>
+        <item>On demand</item>
+        <item>Off</item>
+    </string-array>
+    <string-array name="pref_content_plugins_values" translatable="false">
+        <item>ON</item>
+        <item>ON_DEMAND</item>
+        <item>OFF</item>
+    </string-array>
     <!-- Settings summary -->
     <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 button label -->
+    <string name="pref_use_current">Use current page</string>
     <!-- Settings label -->
     <string name="pref_content_autofit">Auto-fit pages</string>
     <!-- Settings summary -->
@@ -426,13 +420,13 @@
     <!-- Settings label -->
     <string name="pref_extras_website_settings">Website settings</string>
     <!-- Settings summary -->
-    <string name="pref_extras_website_settings_summary">View advanced settings for individual websites</string>
+    <string name="pref_extras_website_settings_summary">Advanced settings for individual websites</string>
     <!-- Settings label -->
     <string name="pref_extras_reset_default">Reset to default</string>
     <!-- Settings summary -->
-    <string name="pref_extras_reset_default_summary">Clear all browser data and reset all settings to default</string>
+    <string name="pref_extras_reset_default_summary">Restore default settings</string>
     <!-- Confirmation dialog message -->
-    <string name="pref_extras_reset_default_dlg">All browser data will be deleted and settings will revert to default values.</string>
+    <string name="pref_extras_reset_default_dlg">Settings will revert to default values.</string>
     <!-- Confirmation dialog title -->
     <string name="pref_extras_reset_default_dlg_title">Reset to default</string>
     <!-- Title for a group of settings -->
@@ -470,6 +464,8 @@
     <string-array name="pref_default_text_encoding_choices">
         <item>Latin-1 (ISO-8859-1)</item>
         <item>Unicode (UTF-8)</item>
+        <item>Chinese (GBK)</item>
+        <item>Chinese (Big5)</item>
         <item>Japanese (ISO-2022-JP)</item>
         <item>Japanese (SHIFT_JIS)</item>
         <item>Japanese (EUC-JP)</item>
@@ -481,15 +477,13 @@
     <string-array name="pref_default_text_encoding_values" translatable="false">
         <item>Latin-1</item>
         <item>UTF-8</item>
+        <item>GBK</item>
+        <item>Big5</item>
         <item>ISO-2022-JP</item>
         <item>SHIFT_JIS</item>
         <item>EUC-JP</item>
     </string-array>
-    <string name="pref_default_text_encoding_default">Latin-1</string>
-    <!-- Dialog box title -->
-    <string name="browserFrameRedirect">Redirect</string>
-    <!-- Dialog box message -->
-    <string name="browserFrame307Post">This web page is being redirected. Resend your typed form data to the new location?</string>
+    <string name="pref_default_text_encoding_default" translatable="false">Latin-1</string>
     <!-- Title for a dialog displayed when the browser has a data connectivity
             problem -->
     <string name="browserFrameNetworkErrorLabel">Data connectivity problem</string>
@@ -565,19 +559,17 @@
     <!-- Context menu item on Download history screen -->
     <string name="download_menu_clear">Clear from list</string>
     <!-- Context menu item in Download history screen -->
+    <string name="download_menu_delete">Delete</string>
+    <!-- Context menu item in Download history screen -->
     <string name="download_menu_cancel">Cancel download</string>
     <!-- Menu item -->
     <string name="download_menu_cancel_all">Cancel all downloads</string>
-    <!-- Menu item -->
-    <string name="download_menu_clear_all">Clear list</string>
-    <!-- Confirmation dialog title -->
-    <string name="download_clear_dlg_title">Clear</string>
-    <!-- Confirmation dialog message -->
-    <string name="download_clear_dlg_msg">All items will be cleared from the list and removed from the browser cache.</string>
     <!-- Confirmation dialog title -->
     <string name="download_cancel_dlg_title">Cancel downloads</string>
     <!-- Confirmation dialog message -->
     <string name="download_cancel_dlg_msg">All <xliff:g id="download_count">%d</xliff:g> downloads will be canceled and cleared from the download history.</string>
+    <!-- Confirmation dialog title -->
+    <string name="download_delete_file">File will be deleted</string>
     <!-- Dialog title -->
     <string name="download_file_error_dlg_title">Out of space</string>
     <!-- Dialog message -->
@@ -595,10 +587,10 @@
             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>
- 
-    <!-- Message for a dialog informing the user that there is no application on
-            the phone that can open the file that was downloaded  -->
-    <string name="download_no_application">No application can be found to open this file.</string>
+
+    <!-- Title for a dialog informing the user that there is no application on
+            the phone that can open the file that was downloaded -->
+    <string name="download_no_application_title">Cannot open file</string>
     <!-- Label for a button to re-attempt downloading a file -->
     <string name="retry">Retry</string>
     <!-- Appears in Download history screen if there is no history -->
@@ -642,11 +634,10 @@
             interrupted and cannot be resumed -->
     <string name="download_precondition_failed">Download interrupted. It cannot be resumed.</string>
 
-    <string name="activity_instrumentation_test_runner">Browser Test Runner</string>
-    <!-- Do not translate.  Testing only -->
-    <string name="activity_instrumentation_functional_test_runner" translatable="false">Browser Functional Test Runner</string>
     <!-- Do not translate.  Testing only -->
     <string name="dump_nav" translatable="false">Dump navigation cache</string>
+    <!-- Do not translate.  Testing only -->
+    <string name="dump_counters" translatable="false">Dump V8 counters</string>
 
     <!-- The default homepage. If it starts with "http://www.google" and the
             user signs up the device with a Google sites account, the site's
@@ -673,7 +664,7 @@
         <item>eBay</item>
         <item>http://www.ebay.com/</item>
         <item>CNN</item>
-        <item>http://www.cnn.com/index.html</item>
+        <item>http://www.cnn.com/</item>
         <item>NY Times</item>
         <item>http://www.nytimes.com/</item>
         <item>ESPN</item>
@@ -689,41 +680,17 @@
     <!-- Bookmark name for Picasa website -->
     <string name="picasa" translatable="false">Picasa</string>
 
-    <!-- Note that this is the standard search url.  It uses the current locale for language -->
-    <!-- (%1$s) and country (%2$s) and shouldn't need to be replaced by locale or mcc selected -->
-    <!-- resources. -->
-    <!-- Any changes to this (especially in terms of adding/removing the MCC-specific flavors) -->
-    <!-- should be mirrored by changes in apps/GoogleSearch. -->
-    <!-- Do not translate.  This string is an internal URI, not seen in the UI. -->
-    <string name="google_search_base" translatable="false">
-        http://www.google.com/m?hl=%1$s&amp;gl=%2$s&amp;</string>
-    
     <!-- The description of the suggestion that lets the user search the web for the query currently
          in the text field. -->
     <string name="search_the_web">Search the web</string>
 
-    <!-- FIXME: the next four strings(read/write history permissions) should be removed.
-         At the moment actually removing them requires manually deleting all of the
-         existing translations. -->
-    <!-- Do not translate -->
-    <string name="permlab_readHistoryBookmarks">read Browser\'s history and bookmarks</string>
-    <!-- Do not translate -->
-    <string name="permdesc_readHistoryBookmarks">Allows the application to read all
-        the URLs that the Browser has visited, and all of the Browser\'s bookmarks.</string>
-    <!-- Do not translate -->
-    <string name="permlab_writeHistoryBookmarks">write Browser\'s history and bookmarks</string>
-    <!-- Do not translate -->
-    <string name="permdesc_writeHistoryBookmarks">Allows an application to modify the
-        Browser\'s history or bookmarks stored on your phone. Malicious applications 
-        can use this to erase or modify your Browser\'s data.</string>
-
     <!-- HTML5 dialogs -->
     <!-- Used as a status bar notification when the browser is running out of space trying to allocate or increase the database quota for an HTML5 databae or application cache. -->
     <string name="webstorage_outofspace_notification_title">Browser storage full</string>
     <string name="webstorage_outofspace_notification_text">Click to free up space.</string>
     <!-- Used in the Browser Settings -->
     <string name="webstorage_clear_data_title">Clear stored data</string>
-    <string name="webstorage_clear_data_summary">Remove all databases associated with this website</string>
+    
     <!-- Confirmation dialog when the user ask to clear all data for an origin -->
     <string name="webstorage_clear_data_dialog_title">Clear stored data</string>
     <string name="webstorage_clear_data_dialog_message">All data stored by this website will be deleted</string>
@@ -740,6 +707,9 @@
     <string name="geolocation_permissions_prompt_share">Share location</string>
     <string name="geolocation_permissions_prompt_dont_share">Decline</string>
     <string name="geolocation_permissions_prompt_remember">Remember preference</string>
+    <!-- Permissions prompt toast -->
+    <string name="geolocation_permissions_prompt_toast_allowed">This site can access your location. Change this in Settings -&gt; Website settings</string>
+    <string name="geolocation_permissions_prompt_toast_disallowed">This site cannot access your location. Change this in Settings -&gt; Website settings</string>
     <!-- Settings page, Advanced Settings -> Website settings -> <origin> -->
     <string name="geolocation_settings_page_title">Clear location access</string>
     <string name="geolocation_settings_page_summary_allowed">This site can currently access your location</string>
@@ -756,10 +726,8 @@
     <string name="website_settings_clear_all_dialog_ok_button">Delete all data</string>
     <string name="website_settings_clear_all_dialog_cancel_button">Cancel</string>
 
-
-    <!-- Zoom-related strings --><skip />
-    <!-- Caption for a button that is shown when the zoom widget is showing.  The button's action will switch to the zoom overview mode. -->
-    <string name="zoom_overview_button_text">Overview</string>
+    <!-- Text in the progress dialog when we are setting an image as the home screen wallpaper. -->
+    <string name="progress_dialog_setting_wallpaper">Setting wallpaper...</string>
 
     <string name="error_console_header_text_minimized" translatable="false">Show JavaScript console</string>
     <string name="error_console_header_text_maximized" translatable="false">JavaScript console</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index fa29a2a..4779aa1 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -23,7 +23,6 @@
         <item name="android:colorBackground">#FFFFFFFF</item>
         <item name="android:windowNoTitle">true</item>
         <item name="android:windowContentOverlay">@null</item>
-        <item name="android:autoCompleteTextViewStyle">@style/AutoCompleteTextView</item>
     </style>
 
     <style name="BookmarkTheme" parent="@android:Theme.Black">
@@ -31,17 +30,6 @@
         <item name="android:windowContentOverlay">@null</item>
     </style>
 
-    <style name="AutoCompleteTextView">
-        <item name="android:focusable">true</item>
-        <item name="android:focusableInTouchMode">true</item>
-        <item name="android:clickable">true</item>
-        <item name="android:completionHintView">@android:layout/simple_dropdown_item_1line</item>
-        <item name="android:textAppearance">?android:attr/textAppearanceLargeInverse</item>
-        <item name="android:completionThreshold">2</item>
-        <item name="android:dropDownSelector">@android:drawable/list_selector_background</item>
-        <item name="android:popupBackground">@android:drawable/spinner_dropdown_background</item>
-    </style>
-
     <style name="FindDialog">
         <item name="android:windowEnterAnimation">@anim/find_dialog_enter</item>
         <item name="android:windowExitAnimation">@anim/find_dialog_exit</item>
diff --git a/res/xml/bookmarkwidget.xml b/res/xml/bookmarkwidget.xml
new file mode 100644
index 0000000..adbe5f2
--- /dev/null
+++ b/res/xml/bookmarkwidget.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+
+<!-- 4x4 Widget displaying the user's bookmarks as thumbnails. -->
+<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
+    android:minWidth="294dip"
+    android:minHeight="294dip"
+    android:updatePeriodMillis="3600000"
+    android:initialLayout="@layout/bookmarkwidget"
+    >
+</appwidget-provider>
diff --git a/res/xml/browser_preferences.xml b/res/xml/browser_preferences.xml
index 1845e20..ee1b306 100644
--- a/res/xml/browser_preferences.xml
+++ b/res/xml/browser_preferences.xml
@@ -78,10 +78,13 @@
                 android:defaultValue="true"
                 android:title="@string/pref_content_javascript" />     
 
-        <CheckBoxPreference
-                android:key="enable_plugins"
-                android:defaultValue="true"
-                android:title="@string/pref_content_plugins" />
+        <ListPreference
+                android:key="plugin_state"
+                android:title="@string/pref_content_plugins"
+                android:defaultValue="ON"
+                android:entries="@array/pref_content_plugins_choices"
+                android:entryValues="@array/pref_content_plugins_values"
+                android:dialogTitle="@string/pref_content_plugins" />
 
         <CheckBoxPreference
                 android:key="open_in_background"
@@ -93,8 +96,7 @@
                 android:key="homepage" 
                 android:title="@string/pref_content_homepage"
                 android:hint="@string/http"
-                android:inputType="textUri"
-                android:singleLine="true" />
+                android:inputType="textUri|textMultiLine" />
 
     </PreferenceCategory>
 
diff --git a/src/com/android/browser/ActiveTabsPage.java b/src/com/android/browser/ActiveTabsPage.java
index 90c417a..2de7787 100644
--- a/src/com/android/browser/ActiveTabsPage.java
+++ b/src/com/android/browser/ActiveTabsPage.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.graphics.Bitmap;
+import android.os.Handler;
 import android.util.AttributeSet;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
@@ -49,7 +50,7 @@
         mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                 public void onItemClick(AdapterView<?> parent, View view,
                         int position, long id) {
-                    if (mControl.getTabCount() < TabControl.MAX_TABS) {
+                    if (mControl.canCreateNewTab()) {
                         position--;
                     }
                     boolean needToAttach = false;
@@ -90,11 +91,30 @@
     }
 
     private class TabsListAdapter extends BaseAdapter {
+        private boolean mNotified = true;
+        private int mReturnedCount;
+        private Handler mHandler = new Handler();
+
         public int getCount() {
             int count = mControl.getTabCount();
-            if (count < TabControl.MAX_TABS) {
+            if (mControl.canCreateNewTab()) {
                 count++;
             }
+            // XXX: This is a workaround to be more like a real adapter. Most
+            // adapters call notifyDataSetChanged() whenever the internal data
+            // has changed. Since TabControl is our internal data, we don't
+            // know when that changes.
+            //
+            // Keep track of the last count we returned and whether we called
+            // notifyDataSetChanged(). If we did not initiate a data set
+            // change, and the count is different, send the notify and return
+            // the old count.
+            if (!mNotified && count != mReturnedCount) {
+                notifyChange();
+                return mReturnedCount;
+            }
+            mReturnedCount = count;
+            mNotified = false;
             return count;
         }
         public Object getItem(int position) {
@@ -107,7 +127,7 @@
             return 2;
         }
         public int getItemViewType(int position) {
-            if (mControl.getTabCount() < TabControl.MAX_TABS) {
+            if (mControl.canCreateNewTab()) {
                 position--;
             }
             // Do not recycle the "add new tab" item.
@@ -115,7 +135,7 @@
         }
         public View getView(int position, View convertView, ViewGroup parent) {
             final int tabCount = mControl.getTabCount();
-            if (tabCount < TabControl.MAX_TABS) {
+            if (mControl.canCreateNewTab()) {
                 position--;
             }
 
@@ -131,8 +151,8 @@
                 ImageView favicon =
                         (ImageView) convertView.findViewById(R.id.favicon);
                 View close = convertView.findViewById(R.id.close);
-                TabControl.Tab tab = mControl.getTab(position);
-                mControl.populatePickerData(tab);
+                Tab tab = mControl.getTab(position);
+                tab.populatePickerData();
                 title.setText(tab.getTitle());
                 url.setText(tab.getUrl());
                 Bitmap icon = tab.getFavicon();
@@ -150,12 +170,22 @@
                                 mBrowserActivity.openTabToHomePage();
                                 mBrowserActivity.removeActiveTabPage(false);
                             } else {
-                                mListView.setAdapter(mAdapter);
+                                mNotified = true;
+                                notifyDataSetChanged();
                             }
                         }
                 });
             }
             return convertView;
         }
+
+        void notifyChange() {
+            mHandler.post(new Runnable() {
+                public void run() {
+                    mNotified = true;
+                    notifyDataSetChanged();
+                }
+            });
+        }
     }
 }
diff --git a/src/com/android/browser/AddBookmarkPage.java b/src/com/android/browser/AddBookmarkPage.java
index 81123ba..1104d5e 100644
--- a/src/com/android/browser/AddBookmarkPage.java
+++ b/src/com/android/browser/AddBookmarkPage.java
@@ -111,6 +111,40 @@
         }
     }
 
+    /**
+     * Runnable to save a bookmark, so it can be performed in its own thread.
+     */
+    private class SaveBookmarkRunnable implements Runnable {
+        private Message mMessage;
+        public SaveBookmarkRunnable(Message msg) {
+            mMessage = msg;
+        }
+        public void run() {
+            // Unbundle bookmark data.
+            Bundle bundle = mMessage.getData();
+            String title = bundle.getString("title");
+            String url = bundle.getString("url");
+            boolean invalidateThumbnail = bundle.getBoolean(
+                    "invalidateThumbnail");
+            Bitmap thumbnail = invalidateThumbnail ? null
+                    : (Bitmap) bundle.getParcelable("thumbnail");
+            String touchIconUrl = bundle.getString("touchIconUrl");
+
+            // Save to the bookmarks DB.
+            try {
+                final ContentResolver cr = getContentResolver();
+                Bookmarks.addBookmark(null, cr, url, title, thumbnail, true);
+                if (touchIconUrl != null) {
+                    new DownloadTouchIcon(cr, url).execute(mTouchIconUrl);
+                }
+                mMessage.arg1 = 1;
+            } catch (IllegalStateException e) {
+                mMessage.arg1 = 0;
+            }
+            mMessage.sendToTarget();
+        }
+    }
+
     private void createHandler() {
         if (mHandler == null) {
             mHandler = new Handler() {
@@ -118,17 +152,7 @@
                 public void handleMessage(Message msg) {
                     switch (msg.what) {
                         case SAVE_BOOKMARK:
-                            // Unbundle bookmark data.
-                            Bundle bundle = msg.getData();
-                            String title = bundle.getString("title");
-                            String url = bundle.getString("url");
-                            boolean invalidateThumbnail = bundle.getBoolean("invalidateThumbnail");
-                            Bitmap thumbnail = invalidateThumbnail
-                                    ? null : (Bitmap) bundle.getParcelable("thumbnail");
-                            String touchIconUrl = bundle.getString("touchIconUrl");
-
-                            // Save to the bookmarks DB.
-                            if (updateBookmarksDB(title, url, thumbnail, touchIconUrl)) {
+                            if (1 == msg.arg1) {
                                 Toast.makeText(AddBookmarkPage.this, R.string.bookmark_saved,
                                         Toast.LENGTH_LONG).show();
                             } else {
@@ -142,21 +166,6 @@
         }
     }
 
-    private boolean updateBookmarksDB(String title, String url, Bitmap thumbnail, String touchIconUrl) {
-        try {
-            final ContentResolver cr = getContentResolver();
-            Bookmarks.addBookmark(null, cr, url, title, thumbnail, true);
-            if (touchIconUrl != null) {
-                final Cursor c =
-                        BrowserBookmarksAdapter.queryBookmarksForUrl(cr, null, url, true);
-                new DownloadTouchIcon(cr, c, url).execute(mTouchIconUrl);
-            }
-        } catch (IllegalStateException e) {
-            return false;
-        }
-        return true;
-    }
-
     /**
      * Parse the data entered in the dialog and post a message to update the bookmarks database.
      */
@@ -178,23 +187,33 @@
             }
             return false;
         }
-        String url = unfilteredUrl;
+        String url = unfilteredUrl.trim();
         try {
-            URI uriObj = new URI(url);
-            String scheme = uriObj.getScheme();
-            if (!("about".equals(scheme) || "data".equals(scheme)
-                    || "javascript".equals(scheme)
-                    || "file".equals(scheme) || "content".equals(scheme))) {
-                WebAddress address;
-                try {
-                    address = new WebAddress(unfilteredUrl);
-                } catch (ParseException e) {
-                    throw new URISyntaxException("", "");
+            // We allow bookmarks with a javascript: scheme, but these will in most cases
+            // fail URI parsing, so don't try it if that's the kind of bookmark we have.
+
+            if (!url.toLowerCase().startsWith("javascript:")) {
+                URI uriObj = new URI(url);
+                String scheme = uriObj.getScheme();
+                if (!Bookmarks.urlHasAcceptableScheme(url)) {
+                    // If the scheme was non-null, let the user know that we
+                    // can't save their bookmark. If it was null, we'll assume
+                    // they meant http when we parse it in the WebAddress class.
+                    if (scheme != null) {
+                        mAddress.setError(r.getText(R.string.bookmark_cannot_save_url));
+                        return false;
+                    }
+                    WebAddress address;
+                    try {
+                        address = new WebAddress(unfilteredUrl);
+                    } catch (ParseException e) {
+                        throw new URISyntaxException("", "");
+                    }
+                    if (address.mHost.length() == 0) {
+                        throw new URISyntaxException("", "");
+                    }
+                    url = address.toString();
                 }
-                if (address.mHost.length() == 0) {
-                    throw new URISyntaxException("", "");
-                }
-                url = address.toString();
             }
         } catch (URISyntaxException e) {
             mAddress.setError(r.getText(R.string.bookmark_url_not_valid));
@@ -217,8 +236,11 @@
             bundle.putString("touchIconUrl", mTouchIconUrl);
             Message msg = Message.obtain(mHandler, SAVE_BOOKMARK);
             msg.setData(bundle);
-            mHandler.sendMessage(msg);
+            // Start a new thread so as to not slow down the UI
+            Thread t = new Thread(new SaveBookmarkRunnable(msg));
+            t.start();
             setResult(RESULT_OK);
+            LogTag.logBookmarkAdded(url, "bookmarkview");
         }
         return true;
     }
diff --git a/src/com/android/browser/BookmarkItem.java b/src/com/android/browser/BookmarkItem.java
index a70dd4f..fbb362e 100644
--- a/src/com/android/browser/BookmarkItem.java
+++ b/src/com/android/browser/BookmarkItem.java
@@ -33,6 +33,7 @@
     protected TextView    mUrlText;
     protected ImageView   mImageView;
     protected String      mUrl;
+    protected String      mTitle;
 
     /**
      *  Instantiate a bookmark item, including a default favicon.
@@ -65,7 +66,7 @@
      * Return the name assigned to this bookmark item.
      */
     /* package */ String getName() {
-        return mTextView.getText().toString();
+        return mTitle;
     }
 
     /**
@@ -99,6 +100,16 @@
      *  @param name The new name for the bookmark item.
      */
     /* package */ void setName(String name) {
+        if (name == null) {
+            return;
+        }
+
+        mTitle = name;
+
+        if (name.length() > BrowserSettings.MAX_TEXTVIEW_LEN) {
+            name = name.substring(0, BrowserSettings.MAX_TEXTVIEW_LEN);
+        }
+
         mTextView.setText(name);
     }
     
@@ -107,7 +118,16 @@
      *  @param url  The new url for the bookmark item.
      */
     /* package */ void setUrl(String url) {
-        mUrlText.setText(url);
+        if (url == null) {
+            return;
+        }
+
         mUrl = url;
+
+        if (url.length() > BrowserSettings.MAX_TEXTVIEW_LEN) {
+            url = url.substring(0, BrowserSettings.MAX_TEXTVIEW_LEN);
+        }
+
+        mUrlText.setText(url);
     }
 }
diff --git a/src/com/android/browser/Bookmarks.java b/src/com/android/browser/Bookmarks.java
index c8aaee7..5ada9dc 100644
--- a/src/com/android/browser/Bookmarks.java
+++ b/src/com/android/browser/Bookmarks.java
@@ -35,12 +35,19 @@
  *  This class is purely to have a common place for adding/deleting bookmarks.
  */
 /* package */ class Bookmarks {
-    private static final String     WHERE_CLAUSE
-            = "url = ? OR url = ? OR url = ? OR url = ?";
-    private static final String     WHERE_CLAUSE_SECURE = "url = ? OR url = ?";
+    // We only want the user to be able to bookmark content that
+    // the browser can handle directly.
+    private static final String acceptableBookmarkSchemes[] = {
+            "http:",
+            "https:",
+            "about:",
+            "data:",
+            "javascript:",
+            "file:",
+            "content:"
+    };
 
-    private static String[]         SELECTION_ARGS;
-
+    private final static String LOGTAG = "Bookmarks";
     /**
      *  Add a bookmark to the database.
      *  @param context Context of the calling Activity.  This is used to make
@@ -59,97 +66,75 @@
             Bitmap thumbnail, boolean retainIcon) {
         // Want to append to the beginning of the list
         long creationTime = new Date().getTime();
-        // First we check to see if the user has already visited this
-        // site.  They may have bookmarked it in a different way from
-        // how it's stored in the database, so allow different combos
-        // to map to the same url.
-        boolean secure = false;
-        String compareString = url;
-        if (compareString.startsWith("http://")) {
-            compareString = compareString.substring(7);
-        } else if (compareString.startsWith("https://")) {
-            compareString = compareString.substring(8);
-            secure = true;
-        }
-        if (compareString.startsWith("www.")) {
-            compareString = compareString.substring(4);
-        }
-        if (secure) {
-            SELECTION_ARGS = new String[2];
-            SELECTION_ARGS[0] = "https://" + compareString;
-            SELECTION_ARGS[1] = "https://www." + compareString;
-        } else {
-            SELECTION_ARGS = new String[4];
-            SELECTION_ARGS[0] = compareString;
-            SELECTION_ARGS[1] = "www." + compareString;
-            SELECTION_ARGS[2] = "http://" + compareString;
-            SELECTION_ARGS[3] = "http://" + SELECTION_ARGS[1];
-        }
-        Cursor cursor = cr.query(Browser.BOOKMARKS_URI,
-                Browser.HISTORY_PROJECTION,
-                secure ? WHERE_CLAUSE_SECURE : WHERE_CLAUSE,
-                SELECTION_ARGS,
-                null);
         ContentValues map = new ContentValues();
-        if (cursor.moveToFirst() && cursor.getInt(
-                Browser.HISTORY_PROJECTION_BOOKMARK_INDEX) == 0) {
-            // This means we have been to this site but not bookmarked
-            // it, so convert the history item to a bookmark
-            map.put(Browser.BookmarkColumns.CREATED, creationTime);
-            map.put(Browser.BookmarkColumns.TITLE, name);
-            map.put(Browser.BookmarkColumns.BOOKMARK, 1);
-            map.put(Browser.BookmarkColumns.THUMBNAIL, bitmapToBytes(thumbnail));
-            cr.update(Browser.BOOKMARKS_URI, map,
-                    "_id = " + cursor.getInt(0), null);
-        } else {
-            int count = cursor.getCount();
-            boolean matchedTitle = false;
-            for (int i = 0; i < count; i++) {
-                // One or more bookmarks already exist for this site.
-                // Check the names of each
-                cursor.moveToPosition(i);
-                if (cursor.getString(Browser.HISTORY_PROJECTION_TITLE_INDEX)
-                        .equals(name)) {
-                    // The old bookmark has the same name.
-                    // Update its creation time.
-                    map.put(Browser.BookmarkColumns.CREATED,
-                            creationTime);
-                    cr.update(Browser.BOOKMARKS_URI, map,
-                            "_id = " + cursor.getInt(0), null);
-                    matchedTitle = true;
-                    break;
-                }
-            }
-            if (!matchedTitle) {
-                // Adding a bookmark for a site the user has visited,
-                // or a new bookmark (with a different name) for a site
-                // the user has visited
-                map.put(Browser.BookmarkColumns.TITLE, name);
-                map.put(Browser.BookmarkColumns.URL, url);
+        Cursor cursor = null;
+        try {
+            cursor = Browser.getVisitedLike(cr, url);
+            if (cursor.moveToFirst() && cursor.getInt(
+                    Browser.HISTORY_PROJECTION_BOOKMARK_INDEX) == 0) {
+                // This means we have been to this site but not bookmarked
+                // it, so convert the history item to a bookmark
                 map.put(Browser.BookmarkColumns.CREATED, creationTime);
+                map.put(Browser.BookmarkColumns.TITLE, name);
                 map.put(Browser.BookmarkColumns.BOOKMARK, 1);
-                map.put(Browser.BookmarkColumns.DATE, 0);
-                map.put(Browser.BookmarkColumns.THUMBNAIL, bitmapToBytes(thumbnail));
-                int visits = 0;
-                if (count > 0) {
-                    // The user has already bookmarked, and possibly
-                    // visited this site.  However, they are creating
-                    // a new bookmark with the same url but a different
-                    // name.  The new bookmark should have the same
-                    // number of visits as the already created bookmark.
-                    visits = cursor.getInt(
-                            Browser.HISTORY_PROJECTION_VISITS_INDEX);
+                map.put(Browser.BookmarkColumns.THUMBNAIL,
+                        bitmapToBytes(thumbnail));
+                cr.update(Browser.BOOKMARKS_URI, map,
+                        "_id = " + cursor.getInt(0), null);
+            } else {
+                int count = cursor.getCount();
+                boolean matchedTitle = false;
+                for (int i = 0; i < count; i++) {
+                    // One or more bookmarks already exist for this site.
+                    // Check the names of each
+                    cursor.moveToPosition(i);
+                    if (cursor.getString(Browser.HISTORY_PROJECTION_TITLE_INDEX)
+                            .equals(name)) {
+                        // The old bookmark has the same name.
+                        // Update its creation time.
+                        map.put(Browser.BookmarkColumns.CREATED,
+                                creationTime);
+                        cr.update(Browser.BOOKMARKS_URI, map,
+                                "_id = " + cursor.getInt(0), null);
+                        matchedTitle = true;
+                        break;
+                    }
                 }
-                // Bookmark starts with 3 extra visits so that it will
-                // bubble up in the most visited and goto search box
-                map.put(Browser.BookmarkColumns.VISITS, visits + 3);
-                cr.insert(Browser.BOOKMARKS_URI, map);
+                if (!matchedTitle) {
+                    // Adding a bookmark for a site the user has visited,
+                    // or a new bookmark (with a different name) for a site
+                    // the user has visited
+                    map.put(Browser.BookmarkColumns.TITLE, name);
+                    map.put(Browser.BookmarkColumns.URL, url);
+                    map.put(Browser.BookmarkColumns.CREATED, creationTime);
+                    map.put(Browser.BookmarkColumns.BOOKMARK, 1);
+                    map.put(Browser.BookmarkColumns.DATE, 0);
+                    map.put(Browser.BookmarkColumns.THUMBNAIL,
+                            bitmapToBytes(thumbnail));
+                    int visits = 0;
+                    if (count > 0) {
+                        // The user has already bookmarked, and possibly
+                        // visited this site.  However, they are creating
+                        // a new bookmark with the same url but a different
+                        // name.  The new bookmark should have the same
+                        // number of visits as the already created bookmark.
+                        visits = cursor.getInt(
+                                Browser.HISTORY_PROJECTION_VISITS_INDEX);
+                    }
+                    // Bookmark starts with 3 extra visits so that it will
+                    // bubble up in the most visited and goto search box
+                    map.put(Browser.BookmarkColumns.VISITS, visits + 3);
+                    cr.insert(Browser.BOOKMARKS_URI, map);
+                }
             }
+        } catch (IllegalStateException e) {
+            Log.e(LOGTAG, "addBookmark", e);
+        } finally {
+            if (cursor != null) cursor.close();
         }
         if (retainIcon) {
             WebIconDatabase.getInstance().retainIconForPageUrl(url);
         }
-        cursor.deactivate();
         if (context != null) {
             Toast.makeText(context, R.string.added_to_bookmarks,
                     Toast.LENGTH_LONG).show();
@@ -168,41 +153,48 @@
      */
     /* package */ static void removeFromBookmarks(Context context,
             ContentResolver cr, String url, String title) {
-        Cursor cursor = cr.query(
-                Browser.BOOKMARKS_URI,
-                Browser.HISTORY_PROJECTION,
-                "url = ? AND title = ?",
-                new String[] { url, title },
-                null);
-        boolean first = cursor.moveToFirst();
-        // Should be in the database no matter what
-        if (!first) {
-            throw new AssertionError("URL is not in the database! " + url + " " + title);
-        }
-        // Remove from bookmarks
-        WebIconDatabase.getInstance().releaseIconForPageUrl(url);
-        Uri uri = ContentUris.withAppendedId(Browser.BOOKMARKS_URI,
-                cursor.getInt(Browser.HISTORY_PROJECTION_ID_INDEX));
-        int numVisits = cursor.getInt(
-                Browser.HISTORY_PROJECTION_VISITS_INDEX);
-        if (0 == numVisits) {
-            cr.delete(uri, null, null);
-        } else {
-            // It is no longer a bookmark, but it is still a visited
-            // site.
-            ContentValues values = new ContentValues();
-            values.put(Browser.BookmarkColumns.BOOKMARK, 0);
-            try {
-                cr.update(uri, values, null, null);
-            } catch (IllegalStateException e) {
-                Log.e("removeFromBookmarks", "no database!");
+        Cursor cursor = null;
+        try {
+            cursor = cr.query(
+                    Browser.BOOKMARKS_URI,
+                    Browser.HISTORY_PROJECTION,
+                    "url = ? AND title = ?",
+                    new String[] { url, title },
+                    null);
+            boolean first = cursor.moveToFirst();
+            // Should be in the database no matter what
+            if (!first) {
+                throw new AssertionError("URL is not in the database! " + url
+                        + " " + title);
             }
+            // Remove from bookmarks
+            WebIconDatabase.getInstance().releaseIconForPageUrl(url);
+            Uri uri = ContentUris.withAppendedId(Browser.BOOKMARKS_URI,
+                    cursor.getInt(Browser.HISTORY_PROJECTION_ID_INDEX));
+            int numVisits = cursor.getInt(
+                    Browser.HISTORY_PROJECTION_VISITS_INDEX);
+            if (0 == numVisits) {
+                cr.delete(uri, null, null);
+            } else {
+                // It is no longer a bookmark, but it is still a visited
+                // site.
+                ContentValues values = new ContentValues();
+                values.put(Browser.BookmarkColumns.BOOKMARK, 0);
+                try {
+                    cr.update(uri, values, null, null);
+                } catch (IllegalStateException e) {
+                    Log.e("removeFromBookmarks", "no database!");
+                }
+            }
+            if (context != null) {
+                Toast.makeText(context, R.string.removed_from_bookmarks,
+                        Toast.LENGTH_LONG).show();
+            }
+        } catch (IllegalStateException e) {
+            Log.e(LOGTAG, "removeFromBookmarks", e);
+        } finally {
+            if (cursor != null) cursor.close();
         }
-        if (context != null) {
-            Toast.makeText(context, R.string.removed_from_bookmarks,
-                    Toast.LENGTH_LONG).show();
-        }
-        cursor.deactivate();
     }
 
     private static byte[] bitmapToBytes(Bitmap bm) {
@@ -214,4 +206,17 @@
         bm.compress(Bitmap.CompressFormat.PNG, 100, os);
         return os.toByteArray();
     }
+
+    /* package */ static boolean urlHasAcceptableScheme(String url) {
+        if (url == null) {
+            return false;
+        }
+
+        for (int i = 0; i < acceptableBookmarkSchemes.length; i++) {
+            if (url.startsWith(acceptableBookmarkSchemes[i])) {
+                return true;
+            }
+        }
+        return false;
+    }
 }
diff --git a/src/com/android/browser/Browser.java b/src/com/android/browser/Browser.java
index 524f789..7822ec8 100644
--- a/src/com/android/browser/Browser.java
+++ b/src/com/android/browser/Browser.java
@@ -57,6 +57,7 @@
         CookieSyncManager.createInstance(this);
         // remove all expired cookies
         CookieManager.getInstance().removeExpiredCookie();
+        BrowserSettings.getInstance().loadFromDb(this);
     }
 
     static Intent createBrowserViewIntent() {
diff --git a/src/com/android/browser/BrowserActivity.java b/src/com/android/browser/BrowserActivity.java
index a754900..5e55789 100644
--- a/src/com/android/browser/BrowserActivity.java
+++ b/src/com/android/browser/BrowserActivity.java
@@ -16,9 +16,6 @@
 
 package com.android.browser;
 
-import com.google.android.googleapps.IGoogleLoginService;
-import com.google.android.googlelogin.GoogleLoginServiceConstants;
-
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.ProgressDialog;
@@ -26,6 +23,8 @@
 import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
+import android.content.ContentProvider;
+import android.content.ContentProviderClient;
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
@@ -33,34 +32,24 @@
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.ServiceConnection;
-import android.content.DialogInterface.OnCancelListener;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.content.res.AssetManager;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteException;
+import android.database.DatabaseUtils;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
-import android.graphics.DrawFilter;
-import android.graphics.Paint;
-import android.graphics.PaintFlagsDrawFilter;
 import android.graphics.Picture;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import android.hardware.SensorListener;
-import android.hardware.SensorManager;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.net.Uri;
 import android.net.WebAddress;
-import android.net.http.EventHandler;
 import android.net.http.SslCertificate;
 import android.net.http.SslError;
 import android.os.AsyncTask;
@@ -68,11 +57,9 @@
 import android.os.Debug;
 import android.os.Environment;
 import android.os.Handler;
-import android.os.IBinder;
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.Process;
-import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.provider.Browser;
@@ -80,12 +67,13 @@
 import android.provider.ContactsContract.Intents.Insert;
 import android.provider.Downloads;
 import android.provider.MediaStore;
+import android.speech.RecognizerResultsIntent;
 import android.text.IClipboard;
 import android.text.TextUtils;
 import android.text.format.DateFormat;
-import android.text.util.Regex;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.Patterns;
 import android.view.ContextMenu;
 import android.view.Gravity;
 import android.view.KeyEvent;
@@ -99,39 +87,35 @@
 import android.view.WindowManager;
 import android.view.ContextMenu.ContextMenuInfo;
 import android.view.MenuItem.OnMenuItemClickListener;
-import android.view.animation.AlphaAnimation;
-import android.view.animation.Animation;
-import android.view.animation.AnimationSet;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.ScaleAnimation;
-import android.view.animation.TranslateAnimation;
 import android.webkit.CookieManager;
 import android.webkit.CookieSyncManager;
 import android.webkit.DownloadListener;
-import android.webkit.GeolocationPermissions;
 import android.webkit.HttpAuthHandler;
 import android.webkit.PluginManager;
 import android.webkit.SslErrorHandler;
 import android.webkit.URLUtil;
 import android.webkit.ValueCallback;
 import android.webkit.WebChromeClient;
-import android.webkit.WebChromeClient.CustomViewCallback;
 import android.webkit.WebHistoryItem;
 import android.webkit.WebIconDatabase;
-import android.webkit.WebStorage;
 import android.webkit.WebView;
-import android.webkit.WebViewClient;
 import android.widget.EditText;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 import android.widget.Toast;
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AccountManagerFuture;
+import android.accounts.AuthenticatorException;
+import android.accounts.OperationCanceledException;
+import android.accounts.AccountManagerCallback;
 
-import java.io.BufferedOutputStream;
+import com.android.common.Search;
+import com.android.common.speech.LoggingEvents;
+
 import java.io.ByteArrayOutputStream;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.MalformedURLException;
@@ -141,18 +125,17 @@
 import java.net.URLEncoder;
 import java.text.ParseException;
 import java.util.Date;
-import java.util.Enumeration;
 import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.Vector;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
 
 public class BrowserActivity extends Activity
-    implements View.OnCreateContextMenuListener,
-        DownloadListener {
+    implements View.OnCreateContextMenuListener, DownloadListener {
 
     /* Define some aliases to make these debugging flags easier to refer to.
      * This file imports android.provider.Browser, so we can't just refer to "Browser.DEBUG".
@@ -161,11 +144,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;
 
-    private IGoogleLoginService mGls = null;
-    private ServiceConnection mGlsConnection = null;
-
-    private SensorManager mSensorManager = null;
-
     // These are single-character shortcuts for searching popular sources.
     private static final int SHORTCUT_INVALID = 0;
     private static final int SHORTCUT_GOOGLE_SEARCH = 1;
@@ -173,108 +151,6 @@
     private static final int SHORTCUT_DICTIONARY_SEARCH = 3;
     private static final int SHORTCUT_GOOGLE_MOBILE_LOCAL_SEARCH = 4;
 
-    /* Whitelisted webpages
-    private static HashSet<String> sWhiteList;
-
-    static {
-        sWhiteList = new HashSet<String>();
-        sWhiteList.add("cnn.com/");
-        sWhiteList.add("espn.go.com/");
-        sWhiteList.add("nytimes.com/");
-        sWhiteList.add("engadget.com/");
-        sWhiteList.add("yahoo.com/");
-        sWhiteList.add("msn.com/");
-        sWhiteList.add("amazon.com/");
-        sWhiteList.add("consumerist.com/");
-        sWhiteList.add("google.com/m/news");
-    }
-    */
-
-    private void setupHomePage() {
-        final Runnable getAccount = new Runnable() {
-            public void run() {
-                // Lower priority
-                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
-                // get the default home page
-                String homepage = mSettings.getHomePage();
-
-                try {
-                    if (mGls == null) return;
-
-                    if (!homepage.startsWith("http://www.google.")) return;
-                    if (homepage.indexOf('?') == -1) return;
-
-                    String hostedUser = mGls.getAccount(GoogleLoginServiceConstants.PREFER_HOSTED);
-                    String googleUser = mGls.getAccount(GoogleLoginServiceConstants.REQUIRE_GOOGLE);
-
-                    // three cases:
-                    //
-                    //   hostedUser == googleUser
-                    //      The device has only a google account
-                    //
-                    //   hostedUser != googleUser
-                    //      The device has a hosted account and a google account
-                    //
-                    //   hostedUser != null, googleUser == null
-                    //      The device has only a hosted account (so far)
-
-                    // developers might have no accounts at all
-                    if (hostedUser == null) return;
-
-                    if (googleUser == null || !hostedUser.equals(googleUser)) {
-                        String domain = hostedUser.substring(hostedUser.lastIndexOf('@')+1);
-                        homepage = homepage.replace("?", "/a/" + domain + "?");
-                    }
-                } catch (RemoteException ignore) {
-                    // Login service died; carry on
-                } catch (RuntimeException ignore) {
-                    // Login service died; carry on
-                } finally {
-                    finish(homepage);
-                }
-            }
-
-            private void finish(final String homepage) {
-                mHandler.post(new Runnable() {
-                    public void run() {
-                        mSettings.setHomePage(BrowserActivity.this, homepage);
-                        resumeAfterCredentials();
-
-                        // as this is running in a separate thread,
-                        // BrowserActivity's onDestroy() may have been called,
-                        // which also calls unbindService().
-                        if (mGlsConnection != null) {
-                            // we no longer need to keep GLS open
-                            unbindService(mGlsConnection);
-                            mGlsConnection = null;
-                        }
-                    } });
-            } };
-
-        final boolean[] done = { false };
-
-        // Open a connection to the Google Login Service.  The first
-        // time the connection is established, set up the homepage depending on
-        // the account in a background thread.
-        mGlsConnection = new ServiceConnection() {
-            public void onServiceConnected(ComponentName className, IBinder service) {
-                mGls = IGoogleLoginService.Stub.asInterface(service);
-                if (done[0] == false) {
-                    done[0] = true;
-                    Thread account = new Thread(getAccount);
-                    account.setName("GLSAccount");
-                    account.start();
-                }
-            }
-            public void onServiceDisconnected(ComponentName className) {
-                mGls = null;
-            }
-        };
-
-        bindService(GoogleLoginServiceConstants.SERVICE_INTENT,
-                    mGlsConnection, Context.BIND_AUTO_CREATE);
-    }
-
     private static class ClearThumbnails extends AsyncTask<File, Void, Void> {
         @Override
         public Void doInBackground(File... files) {
@@ -295,7 +171,8 @@
      */
     private FrameLayout mBrowserFrameLayout;
 
-    @Override public void onCreate(Bundle icicle) {
+    @Override
+    public void onCreate(Bundle icicle) {
         if (LOGV_ENABLED) {
             Log.v(LOGTAG, this + " onStart");
         }
@@ -303,6 +180,12 @@
         // test the browser in OpenGL
         // requestWindowFeature(Window.FEATURE_OPENGL);
 
+        // enable this to test the browser in 32bit
+        if (false) {
+            getWindow().setFormat(PixelFormat.RGBX_8888);
+            BitmapFactory.setDefaultConfig(Bitmap.Config.ARGB_8888);
+        }
+
         setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
 
         mResolver = getContentResolver();
@@ -314,16 +197,6 @@
             return;
         }
 
-        //
-        // start MASF proxy service
-        //
-        //Intent proxyServiceIntent = new Intent();
-        //proxyServiceIntent.setComponent
-        //    (new ComponentName(
-        //        "com.android.masfproxyservice",
-        //        "com.android.masfproxyservice.MasfProxyService"));
-        //startService(proxyServiceIntent, null);
-
         mSecLockIcon = Resources.getSystem().getDrawable(
                 android.R.drawable.ic_secure);
         mMixLockIcon = Resources.getSystem().getDrawable(
@@ -341,6 +214,9 @@
                 .findViewById(R.id.fullscreen_custom_content);
         frameLayout.addView(mBrowserFrameLayout, COVER_SCREEN_PARAMS);
         mTitleBar = new TitleBar(this);
+        // mTitleBar will be always shown in the fully loaded mode
+        mTitleBar.setProgress(100);
+        mFakeTitleBar = new TitleBar(this);
 
         // Create the tab control and our initial tab
         mTabControl = new TabControl(this);
@@ -351,11 +227,18 @@
         // Keep a settings instance handy.
         mSettings = BrowserSettings.getInstance();
         mSettings.setTabControl(mTabControl);
-        mSettings.loadFromDb(this);
 
         PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Browser");
 
+        // Find out if the network is currently up.
+        ConnectivityManager cm = (ConnectivityManager) getSystemService(
+                Context.CONNECTIVITY_SERVICE);
+        NetworkInfo info = cm.getActiveNetworkInfo();
+        if (info != null) {
+            mIsNetworkUp = info.isAvailable();
+        }
+
         /* enables registration for changes in network status from
            http stack */
         mNetworkStateChangedFilter = new IntentFilter();
@@ -366,9 +249,15 @@
                 public void onReceive(Context context, Intent intent) {
                     if (intent.getAction().equals(
                             ConnectivityManager.CONNECTIVITY_ACTION)) {
-                        boolean noConnectivity = intent.getBooleanExtra(
-                                ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
-                        onNetworkToggle(!noConnectivity);
+
+                        NetworkInfo info = intent.getParcelableExtra(
+                                ConnectivityManager.EXTRA_NETWORK_INFO);
+                        String typeName = info.getTypeName();
+                        String subtypeName = info.getSubtypeName();
+                        sendNetworkType(typeName.toLowerCase(),
+                                (subtypeName != null ? subtypeName.toLowerCase() : ""));
+
+                        onNetworkToggle(info.isAvailable());
                     }
                 }
             };
@@ -388,6 +277,12 @@
                     // if it is replacing, refreshPlugins() when adding
                     return;
                 }
+
+                if (sGoogleApps.contains(packageName)) {
+                    BrowserActivity.this.packageChanged(packageName,
+                            Intent.ACTION_PACKAGE_ADDED.equals(action));
+                }
+
                 PackageManager pm = BrowserActivity.this.getPackageManager();
                 PackageInfo pkgInfo = null;
                 try {
@@ -435,9 +330,12 @@
             // the tab will be close when exit.
             UrlData urlData = getUrlDataFromIntent(intent);
 
-            final TabControl.Tab t = mTabControl.createNewTab(
-                    Intent.ACTION_VIEW.equals(intent.getAction()) &&
-                    intent.getData() != null,
+            String action = intent.getAction();
+            final Tab t = mTabControl.createNewTab(
+                    (Intent.ACTION_VIEW.equals(action) &&
+                    intent.getData() != null)
+                    || RecognizerResultsIntent.ACTION_VOICE_SEARCH_RESULTS
+                    .equals(action),
                     intent.getStringExtra(Browser.EXTRA_APPLICATION_ID), urlData.mUrl);
             mTabControl.setCurrentTab(t);
             attachTabToContentView(t);
@@ -448,27 +346,11 @@
                     webView.setInitialScale(scale);
                 }
             }
-            // If we are not restoring from an icicle, then there is a high
-            // likely hood this is the first run. So, check to see if the
-            // homepage needs to be configured and copy any plugins from our
-            // asset directory to the data partition.
-            if ((extra == null || !extra.getBoolean("testing"))
-                    && !mSettings.isLoginInitialized()) {
-                setupHomePage();
-            }
 
             if (urlData.isEmpty()) {
-                if (mSettings.isLoginInitialized()) {
-                    webView.loadUrl(mSettings.getHomePage());
-                } else {
-                    waitForCredentials();
-                }
+                loadUrl(webView, mSettings.getHomePage());
             } else {
-                if (extra != null) {
-                    urlData.setPostData(extra
-                            .getByteArray(Browser.EXTRA_POST_DATA));
-                }
-                urlData.loadIn(webView);
+                loadUrlDataIn(t, urlData);
             }
         } else {
             // TabControl.restoreState() will create a new tab even if
@@ -481,11 +363,37 @@
         if (jsFlags.trim().length() != 0) {
             mTabControl.getCurrentWebView().setJsFlags(jsFlags);
         }
+        // Work out which packages are installed on the system.
+        getInstalledPackages();
+
+        // Start watching the default geolocation permissions
+        mSystemAllowGeolocationOrigins
+                = new SystemAllowGeolocationOrigins(getApplicationContext());
+        mSystemAllowGeolocationOrigins.start();
+    }
+
+    /**
+     * Feed the previously stored results strings to the BrowserProvider so that
+     * the SearchDialog will show them instead of the standard searches.
+     * @param result String to show on the editable line of the SearchDialog.
+     */
+    /* package */ void showVoiceSearchResults(String result) {
+        ContentProviderClient client = mResolver.acquireContentProviderClient(
+                Browser.BOOKMARKS_URI);
+        ContentProvider prov = client.getLocalContentProvider();
+        BrowserProvider bp = (BrowserProvider) prov;
+        bp.setQueryResults(mTabControl.getCurrentTab().getVoiceSearchResults());
+        client.release();
+
+        Bundle bundle = createGoogleSearchSourceBundle(
+                GOOGLE_SEARCH_SOURCE_SEARCHKEY);
+        bundle.putBoolean(SearchManager.CONTEXT_IS_VOICE, true);
+        startSearch(result, false, bundle, false);
     }
 
     @Override
     protected void onNewIntent(Intent intent) {
-        TabControl.Tab current = mTabControl.getCurrentTab();
+        Tab current = mTabControl.getCurrentTab();
         // When a tab is closed on exit, the current tab index is set to -1.
         // Reset before proceed as Browser requires the current tab to be set.
         if (current == null) {
@@ -506,10 +414,39 @@
             // just resume the browser
             return;
         }
+        // In case the SearchDialog is open.
+        ((SearchManager) getSystemService(Context.SEARCH_SERVICE))
+                .stopSearch();
+        boolean activateVoiceSearch = RecognizerResultsIntent
+                .ACTION_VOICE_SEARCH_RESULTS.equals(action);
         if (Intent.ACTION_VIEW.equals(action)
                 || Intent.ACTION_SEARCH.equals(action)
                 || MediaStore.INTENT_ACTION_MEDIA_SEARCH.equals(action)
-                || Intent.ACTION_WEB_SEARCH.equals(action)) {
+                || Intent.ACTION_WEB_SEARCH.equals(action)
+                || activateVoiceSearch) {
+            if (current.isInVoiceSearchMode()) {
+                String title = current.getVoiceDisplayTitle();
+                if (title != null && title.equals(intent.getStringExtra(
+                        SearchManager.QUERY))) {
+                    // The user submitted the same search as the last voice
+                    // search, so do nothing.
+                    return;
+                }
+                if (Intent.ACTION_SEARCH.equals(action)
+                        && current.voiceSearchSourceIsGoogle()) {
+                    Intent logIntent = new Intent(
+                            LoggingEvents.ACTION_LOG_EVENT);
+                    logIntent.putExtra(LoggingEvents.EXTRA_EVENT,
+                            LoggingEvents.VoiceSearch.QUERY_UPDATED);
+                    logIntent.putExtra(
+                            LoggingEvents.VoiceSearch.EXTRA_QUERY_UPDATED_VALUE,
+                            intent.getDataString());
+                    sendBroadcast(logIntent);
+                    // Note, onPageStarted will revert the voice title bar
+                    // When http://b/issue?id=2379215 is fixed, we should update
+                    // the title bar here.
+                }
+            }
             // If this was a search request (e.g. search query directly typed into the address bar),
             // pass it on to the default web search provider.
             if (handleWebSearchIntent(intent)) {
@@ -520,15 +457,16 @@
             if (urlData.isEmpty()) {
                 urlData = new UrlData(mSettings.getHomePage());
             }
-            urlData.setPostData(intent
-                    .getByteArrayExtra(Browser.EXTRA_POST_DATA));
 
             final String appId = intent
                     .getStringExtra(Browser.EXTRA_APPLICATION_ID);
-            if (Intent.ACTION_VIEW.equals(action)
+            if ((Intent.ACTION_VIEW.equals(action)
+                    // If a voice search has no appId, it means that it came
+                    // from the browser.  In that case, reuse the current tab.
+                    || (activateVoiceSearch && appId != null))
                     && !getPackageName().equals(appId)
                     && (flags & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
-                TabControl.Tab appTab = mTabControl.getTabFromId(appId);
+                Tab appTab = mTabControl.getTabFromId(appId);
                 if (appTab != null) {
                     Log.i(LOGTAG, "Reusing tab for " + appId);
                     // Dismiss the subwindow if applicable.
@@ -540,19 +478,19 @@
                     // If the WebView has the same original url and is on that
                     // page, it can be reused.
                     boolean needsLoad =
-                            mTabControl.recreateWebView(appTab, urlData.mUrl);
+                            mTabControl.recreateWebView(appTab, urlData);
 
                     if (current != appTab) {
                         switchToTab(mTabControl.getTabIndex(appTab));
                         if (needsLoad) {
-                            urlData.loadIn(appTab.getWebView());
+                            loadUrlDataIn(appTab, urlData);
                         }
                     } else {
                         // If the tab was the current tab, we have to attach
                         // it to the view system again.
                         attachTabToContentView(appTab);
                         if (needsLoad) {
-                            urlData.loadIn(appTab.getWebView());
+                            loadUrlDataIn(appTab, urlData);
                         }
                     }
                     return;
@@ -575,13 +513,37 @@
                     }
                 }
             } else {
-                if ("about:debug".equals(urlData.mUrl)) {
-                    mSettings.toggleDebugSettings();
+                if (!urlData.isEmpty()
+                        && urlData.mUrl.startsWith("about:debug")) {
+                    if ("about:debug.dom".equals(urlData.mUrl)) {
+                        current.getWebView().dumpDomTree(false);
+                    } else if ("about:debug.dom.file".equals(urlData.mUrl)) {
+                        current.getWebView().dumpDomTree(true);
+                    } else if ("about:debug.render".equals(urlData.mUrl)) {
+                        current.getWebView().dumpRenderTree(false);
+                    } else if ("about:debug.render.file".equals(urlData.mUrl)) {
+                        current.getWebView().dumpRenderTree(true);
+                    } else if ("about:debug.display".equals(urlData.mUrl)) {
+                        current.getWebView().dumpDisplayTree();
+                    } else if (urlData.mUrl.startsWith("about:debug.drag")) {
+                        int index = urlData.mUrl.codePointAt(16) - '0';
+                        if (index <= 0 || index > 9) {
+                            current.getWebView().setDragTracker(null);
+                        } else {
+                            current.getWebView().setDragTracker(new MeshTracker(index));
+                        }
+                    } else {
+                        mSettings.toggleDebugSettings();
+                    }
                     return;
                 }
                 // Get rid of the subwindow if it exists
                 dismissSubWindow(current);
-                urlData.loadIn(current.getWebView());
+                // If the current Tab is being used as an application tab,
+                // remove the association, since the new Intent means that it is
+                // no longer associated with that application.
+                current.setAppId(null);
+                loadUrlDataIn(current, urlData);
             }
         }
     }
@@ -611,6 +573,10 @@
 
         String url = null;
         final String action = intent.getAction();
+        if (RecognizerResultsIntent.ACTION_VOICE_SEARCH_RESULTS.equals(
+                action)) {
+            return false;
+        }
         if (Intent.ACTION_VIEW.equals(action)) {
             Uri data = intent.getData();
             if (data != null) url = data.toString();
@@ -637,14 +603,21 @@
 
         // URLs and site specific search shortcuts are handled by the regular flow of control, so
         // return early.
-        if (Regex.WEB_URL_PATTERN.matcher(url).matches()
+        if (Patterns.WEB_URL.matcher(url).matches()
                 || ACCEPTED_URI_SCHEMA.matcher(url).matches()
                 || parseUrlShortcut(url) != SHORTCUT_INVALID) {
             return false;
         }
 
-        Browser.updateVisitedHistory(mResolver, url, false);
-        Browser.addSearchUrl(mResolver, url);
+        final ContentResolver cr = mResolver;
+        final String newUrl = url;
+        new AsyncTask<Void, Void, Void>() {
+            protected Void doInBackground(Void... unused) {
+                Browser.updateVisitedHistory(cr, newUrl, false);
+                Browser.addSearchUrl(cr, newUrl);
+                return null;
+            }
+        }.execute();
 
         Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
         intent.addCategory(Intent.CATEGORY_DEFAULT);
@@ -662,7 +635,8 @@
     }
 
     private UrlData getUrlDataFromIntent(Intent intent) {
-        String url = null;
+        String url = "";
+        Map<String, String> headers = null;
         if (intent != null) {
             final String action = intent.getAction();
             if (Intent.ACTION_VIEW.equals(action)) {
@@ -674,12 +648,17 @@
                         url += "?" + mimeType;
                     }
                 }
-                if ("inline:".equals(url)) {
-                    return new InlinedUrlData(
-                            intent.getStringExtra(Browser.EXTRA_INLINE_CONTENT),
-                            intent.getType(),
-                            intent.getStringExtra(Browser.EXTRA_INLINE_ENCODING),
-                            intent.getStringExtra(Browser.EXTRA_INLINE_FAILURL));
+                if (url != null && url.startsWith("http")) {
+                    final Bundle pairs = intent
+                            .getBundleExtra(Browser.EXTRA_HEADERS);
+                    if (pairs != null && !pairs.isEmpty()) {
+                        Iterator<String> iter = pairs.keySet().iterator();
+                        headers = new HashMap<String, String>();
+                        while (iter.hasNext()) {
+                            String key = iter.next();
+                            headers.put(key, pairs.getString(key));
+                        }
+                    }
                 }
             } else if (Intent.ACTION_SEARCH.equals(action)
                     || MediaStore.INTENT_ACTION_MEDIA_SEARCH.equals(action)
@@ -687,21 +666,24 @@
                 url = intent.getStringExtra(SearchManager.QUERY);
                 if (url != null) {
                     mLastEnteredUrl = url;
-                    // Don't add Urls, just search terms.
-                    // Urls will get added when the page is loaded.
-                    if (!Regex.WEB_URL_PATTERN.matcher(url).matches()) {
-                        Browser.updateVisitedHistory(mResolver, url, false);
-                    }
                     // In general, we shouldn't modify URL from Intent.
                     // But currently, we get the user-typed URL from search box as well.
                     url = fixUrl(url);
                     url = smartUrlFilter(url);
+                    final ContentResolver cr = mResolver;
+                    final String newUrl = url;
+                    new AsyncTask<Void, Void, Void>() {
+                        protected Void doInBackground(Void... unused) {
+                            Browser.updateVisitedHistory(cr, newUrl, false);
+                            return null;
+                        }
+                    }.execute();
                     String searchSource = "&source=android-" + GOOGLE_SEARCH_SOURCE_SUGGEST + "&";
                     if (url.contains(searchSource)) {
                         String source = null;
                         final Bundle appData = intent.getBundleExtra(SearchManager.APP_DATA);
                         if (appData != null) {
-                            source = appData.getString(SearchManager.SOURCE);
+                            source = appData.getString(Search.SOURCE);
                         }
                         if (TextUtils.isEmpty(source)) {
                             source = GOOGLE_SEARCH_SOURCE_UNKNOWN;
@@ -711,9 +693,22 @@
                 }
             }
         }
-        return new UrlData(url);
+        return new UrlData(url, headers, intent);
     }
+    /* package */ void showVoiceTitleBar(String title) {
+        mTitleBar.setInVoiceMode(true);
+        mFakeTitleBar.setInVoiceMode(true);
 
+        mTitleBar.setDisplayTitle(title);
+        mFakeTitleBar.setDisplayTitle(title);
+    }
+    /* package */ void revertVoiceTitleBar() {
+        mTitleBar.setInVoiceMode(false);
+        mFakeTitleBar.setInVoiceMode(false);
+
+        mTitleBar.setDisplayTitle(mUrl);
+        mFakeTitleBar.setDisplayTitle(mUrl);
+    }
     /* package */ static String fixUrl(String inUrl) {
         // FIXME: Converting the url to lower case
         // duplicates functionality in smartUrlFilter().
@@ -744,100 +739,8 @@
         return inUrl;
     }
 
-    /**
-     * Looking for the pattern like this
-     *
-     *          *
-     *         * *
-     *      ***   *     *******
-     *             *   *
-     *              * *
-     *               *
-     */
-    private final SensorListener mSensorListener = new SensorListener() {
-        private long mLastGestureTime;
-        private float[] mPrev = new float[3];
-        private float[] mPrevDiff = new float[3];
-        private float[] mDiff = new float[3];
-        private float[] mRevertDiff = new float[3];
-
-        public void onSensorChanged(int sensor, float[] values) {
-            boolean show = false;
-            float[] diff = new float[3];
-
-            for (int i = 0; i < 3; i++) {
-                diff[i] = values[i] - mPrev[i];
-                if (Math.abs(diff[i]) > 1) {
-                    show = true;
-                }
-                if ((diff[i] > 1.0 && mDiff[i] < 0.2)
-                        || (diff[i] < -1.0 && mDiff[i] > -0.2)) {
-                    // start track when there is a big move, or revert
-                    mRevertDiff[i] = mDiff[i];
-                    mDiff[i] = 0;
-                } else if (diff[i] > -0.2 && diff[i] < 0.2) {
-                    // reset when it is flat
-                    mDiff[i] = mRevertDiff[i]  = 0;
-                }
-                mDiff[i] += diff[i];
-                mPrevDiff[i] = diff[i];
-                mPrev[i] = values[i];
-            }
-
-            if (false) {
-                // only shows if we think the delta is big enough, in an attempt
-                // to detect "serious" moves left/right or up/down
-                Log.d("BrowserSensorHack", "sensorChanged " + sensor + " ("
-                        + values[0] + ", " + values[1] + ", " + values[2] + ")"
-                        + " diff(" + diff[0] + " " + diff[1] + " " + diff[2]
-                        + ")");
-                Log.d("BrowserSensorHack", "      mDiff(" + mDiff[0] + " "
-                        + mDiff[1] + " " + mDiff[2] + ")" + " mRevertDiff("
-                        + mRevertDiff[0] + " " + mRevertDiff[1] + " "
-                        + mRevertDiff[2] + ")");
-            }
-
-            long now = android.os.SystemClock.uptimeMillis();
-            if (now - mLastGestureTime > 1000) {
-                mLastGestureTime = 0;
-
-                float y = mDiff[1];
-                float z = mDiff[2];
-                float ay = Math.abs(y);
-                float az = Math.abs(z);
-                float ry = mRevertDiff[1];
-                float rz = mRevertDiff[2];
-                float ary = Math.abs(ry);
-                float arz = Math.abs(rz);
-                boolean gestY = ay > 2.5f && ary > 1.0f && ay > ary;
-                boolean gestZ = az > 3.5f && arz > 1.0f && az > arz;
-
-                if ((gestY || gestZ) && !(gestY && gestZ)) {
-                    WebView view = mTabControl.getCurrentWebView();
-
-                    if (view != null) {
-                        if (gestZ) {
-                            if (z < 0) {
-                                view.zoomOut();
-                            } else {
-                                view.zoomIn();
-                            }
-                        } else {
-                            view.flingScroll(0, Math.round(y * 100));
-                        }
-                    }
-                    mLastGestureTime = now;
-                }
-            }
-        }
-
-        public void onAccuracyChanged(int sensor, int accuracy) {
-            // TODO Auto-generated method stub
-
-        }
-    };
-
-    @Override protected void onResume() {
+    @Override
+    protected void onResume() {
         super.onResume();
         if (LOGV_ENABLED) {
             Log.v(LOGTAG, "BrowserActivity.onResume: this=" + this);
@@ -857,51 +760,19 @@
             mWakeLock.release();
         }
 
-        if (mCredsDlg != null) {
-            if (!mHandler.hasMessages(CANCEL_CREDS_REQUEST)) {
-             // In case credential request never comes back
-                mHandler.sendEmptyMessageDelayed(CANCEL_CREDS_REQUEST, 6000);
-            }
-        }
-
         registerReceiver(mNetworkStateIntentReceiver,
                          mNetworkStateChangedFilter);
         WebView.enablePlatformNotifications();
-
-        if (mSettings.doFlick()) {
-            if (mSensorManager == null) {
-                mSensorManager = (SensorManager) getSystemService(
-                        Context.SENSOR_SERVICE);
-            }
-            mSensorManager.registerListener(mSensorListener,
-                    SensorManager.SENSOR_ACCELEROMETER,
-                    SensorManager.SENSOR_DELAY_FASTEST);
-        } else {
-            mSensorManager = null;
-        }
     }
 
     /**
      * Since the actual title bar is embedded in the WebView, and removing it
-     * would change its appearance, create a temporary title bar to go at
-     * the top of the screen while the menu is open.
+     * would change its appearance, use a different TitleBar to show overlayed
+     * at the top of the screen, when the menu is open or the page is loading.
      */
     private TitleBar mFakeTitleBar;
 
     /**
-     * Holder for the fake title bar.  It will have a foreground shadow, as well
-     * as a white background, so the fake title bar looks like the real one.
-     */
-    private ViewGroup mFakeTitleBarHolder;
-
-    /**
-     * Layout parameters for the fake title bar within mFakeTitleBarHolder
-     */
-    private FrameLayout.LayoutParams mFakeTitleBarParams
-            = new FrameLayout.LayoutParams(
-            ViewGroup.LayoutParams.FILL_PARENT,
-            ViewGroup.LayoutParams.WRAP_CONTENT);
-    /**
      * Keeps track of whether the options menu is open.  This is important in
      * determining whether to show or hide the title bar overlay.
      */
@@ -955,54 +826,14 @@
         return true;
     }
 
-    /**
-     * Special class used exclusively for the shadow drawn underneath the fake
-     * title bar.  The shadow does not need to be drawn if the WebView
-     * underneath is scrolled to the top, because it will draw directly on top
-     * of the embedded shadow.
-     */
-    private static class Shadow extends View {
-        private WebView mWebView;
-
-        public Shadow(Context context, AttributeSet attrs) {
-            super(context, attrs);
-        }
-
-        public void setWebView(WebView view) {
-            mWebView = view;
-        }
-
-        @Override
-        public void draw(Canvas canvas) {
-            // In general onDraw is the method to override, but we care about
-            // whether or not the background gets drawn, which happens in draw()
-            if (mWebView == null || mWebView.getScrollY() > getHeight()) {
-                super.draw(canvas);
-            }
-            // Need to invalidate so that if the scroll position changes, we
-            // still draw as appropriate.
-            invalidate();
-        }
-    }
-
     private void showFakeTitleBar() {
-        final View decor = getWindow().peekDecorView();
-        if (mFakeTitleBar == null && mActiveTabsPage == null
-                && !mActivityInPause && decor != null
-                && decor.getWindowToken() != null) {
-            Rect visRect = new Rect();
-            if (!mBrowserFrameLayout.getGlobalVisibleRect(visRect)) {
-                if (LOGD_ENABLED) {
-                    Log.d(LOGTAG, "showFakeTitleBar visRect failed");
-                }
+        if (mFakeTitleBar.getParent() == null && mActiveTabsPage == null
+                && !mActivityInPause) {
+            WebView mainView = mTabControl.getCurrentWebView();
+            // if there is no current WebView, don't show the faked title bar;
+            if (mainView == null) {
                 return;
             }
-            final WebView webView = getTopWindow();
-            mFakeTitleBar = new TitleBar(this);
-            mFakeTitleBar.setTitleAndUrl(null, webView.getUrl());
-            mFakeTitleBar.setProgress(webView.getProgress());
-            mFakeTitleBar.setFavicon(webView.getFavicon());
-            updateLockIconToLatest();
 
             WindowManager manager
                     = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
@@ -1011,30 +842,15 @@
             // while the menu is up
             WindowManager.LayoutParams params
                     = new WindowManager.LayoutParams(
-                    ViewGroup.LayoutParams.FILL_PARENT,
+                    ViewGroup.LayoutParams.MATCH_PARENT,
                     ViewGroup.LayoutParams.WRAP_CONTENT,
-                    WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL,
+                    WindowManager.LayoutParams.TYPE_APPLICATION,
                     WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                     PixelFormat.TRANSLUCENT);
             params.gravity = Gravity.TOP;
-            WebView mainView = mTabControl.getCurrentWebView();
-            boolean atTop = mainView != null && mainView.getScrollY() == 0;
+            boolean atTop = mainView.getScrollY() == 0;
             params.windowAnimations = atTop ? 0 : R.style.TitleBar;
-            // XXX : Without providing an offset, the fake title bar will be
-            // placed underneath the status bar.  Use the global visible rect
-            // of mBrowserFrameLayout to determine the bottom of the status bar
-            params.y = visRect.top;
-            // Add a holder for the title bar.  It also holds a shadow to show
-            // below the title bar.
-            if (mFakeTitleBarHolder == null) {
-                mFakeTitleBarHolder = (ViewGroup) LayoutInflater.from(this)
-                    .inflate(R.layout.title_bar_bg, null);
-            }
-            Shadow shadow = (Shadow) mFakeTitleBarHolder.findViewById(
-                    R.id.shadow);
-            shadow.setWebView(mainView);
-            mFakeTitleBarHolder.addView(mFakeTitleBar, 0, mFakeTitleBarParams);
-            manager.addView(mFakeTitleBarHolder, params);
+            manager.addView(mFakeTitleBar, params);
         }
     }
 
@@ -1050,10 +866,11 @@
             showFakeTitleBar();
         }
     }
+
     private void hideFakeTitleBar() {
-        if (mFakeTitleBar == null) return;
+        if (mFakeTitleBar.getParent() == null) return;
         WindowManager.LayoutParams params = (WindowManager.LayoutParams)
-                mFakeTitleBarHolder.getLayoutParams();
+                mFakeTitleBar.getLayoutParams();
         WebView mainView = mTabControl.getCurrentWebView();
         // Although we decided whether or not to animate based on the current
         // scroll position, the scroll position may have changed since the
@@ -1063,10 +880,8 @@
                 ? 0 : R.style.TitleBar;
         WindowManager manager
                     = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
-        manager.updateViewLayout(mFakeTitleBarHolder, params);
-        mFakeTitleBarHolder.removeView(mFakeTitleBar);
-        manager.removeView(mFakeTitleBarHolder);
-        mFakeTitleBar = null;
+        manager.updateViewLayout(mFakeTitleBar, params);
+        manager.removeView(mFakeTitleBar);
     }
 
     /**
@@ -1081,12 +896,21 @@
         openContextMenu(mTitleBar);
     }
 
+    @Override
+    public void onContextMenuClosed(Menu menu) {
+        super.onContextMenuClosed(menu);
+        if (mInLoad) {
+            showFakeTitleBar();
+        }
+    }
+
     /**
      *  onSaveInstanceState(Bundle map)
      *  onSaveInstanceState is called right before onStop(). The map contains
      *  the saved state.
      */
-    @Override protected void onSaveInstanceState(Bundle outState) {
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
         if (LOGV_ENABLED) {
             Log.v(LOGTAG, "BrowserActivity.onSaveInstanceState: this=" + this);
         }
@@ -1100,7 +924,8 @@
         mTabControl.saveState(outState);
     }
 
-    @Override protected void onPause() {
+    @Override
+    protected void onPause() {
         super.onPause();
 
         if (mActivityInPause) {
@@ -1116,12 +941,6 @@
                     .obtainMessage(RELEASE_WAKELOCK), WAKELOCK_TIMEOUT);
         }
 
-        // Clear the credentials toast if it is up
-        if (mCredsDlg != null && mCredsDlg.isShowing()) {
-            mCredsDlg.dismiss();
-        }
-        mCredsDlg = null;
-
         // FIXME: This removes the active tabs page and resets the menu to
         // MAIN_MENU.  A better solution might be to do this work in onNewIntent
         // but then we would need to save it in onSaveInstanceState and restore
@@ -1135,22 +954,27 @@
         // unregister network state listener
         unregisterReceiver(mNetworkStateIntentReceiver);
         WebView.disablePlatformNotifications();
-
-        if (mSensorManager != null) {
-            mSensorManager.unregisterListener(mSensorListener);
-        }
     }
 
-    @Override protected void onDestroy() {
+    @Override
+    protected void onDestroy() {
         if (LOGV_ENABLED) {
             Log.v(LOGTAG, "BrowserActivity.onDestroy: this=" + this);
         }
         super.onDestroy();
 
+        if (mUploadMessage != null) {
+            mUploadMessage.onReceiveValue(null);
+            mUploadMessage = null;
+        }
+
         if (mTabControl == null) return;
 
+        // Remove the fake title bar if it is there
+        hideFakeTitleBar();
+
         // Remove the current tab and sub window
-        TabControl.Tab t = mTabControl.getCurrentTab();
+        Tab t = mTabControl.getCurrentTab();
         if (t != null) {
             dismissSubWindow(t);
             removeTabFromContentView(t);
@@ -1158,22 +982,12 @@
         // Destroy all the tabs
         mTabControl.destroy();
         WebIconDatabase.getInstance().close();
-        if (mGlsConnection != null) {
-            unbindService(mGlsConnection);
-            mGlsConnection = null;
-        }
-
-        //
-        // stop MASF proxy service
-        //
-        //Intent proxyServiceIntent = new Intent();
-        //proxyServiceIntent.setComponent
-        //   (new ComponentName(
-        //        "com.android.masfproxyservice",
-        //        "com.android.masfproxyservice.MasfProxyService"));
-        //stopService(proxyServiceIntent);
 
         unregisterReceiver(mPackageInstallationReceiver);
+
+        // Stop watching the default geolocation permissions
+        mSystemAllowGeolocationOrigins.stop();
+        mSystemAllowGeolocationOrigins = null;
     }
 
     @Override
@@ -1185,7 +999,7 @@
             mPageInfoDialog.dismiss();
             showPageInfo(
                 mPageInfoView,
-                mPageInfoFromShowSSLCertificateOnError.booleanValue());
+                mPageInfoFromShowSSLCertificateOnError);
         }
         if (mSSLCertificateDialog != null) {
             mSSLCertificateDialog.dismiss();
@@ -1213,32 +1027,31 @@
             showHttpAuthentication(mHttpAuthHandler, null, null, title,
                     name, password, focusId);
         }
-        if (mFindDialog != null && mFindDialog.isShowing()) {
-            mFindDialog.onConfigurationChanged(newConfig);
-        }
     }
 
-    @Override public void onLowMemory() {
+    @Override
+    public void onLowMemory() {
         super.onLowMemory();
         mTabControl.freeMemory();
     }
 
-    private boolean resumeWebViewTimers() {
-        if ((!mActivityInPause && !mPageStarted) ||
-                (mActivityInPause && mPageStarted)) {
+    private void resumeWebViewTimers() {
+        Tab tab = mTabControl.getCurrentTab();
+        if (tab == null) return; // monkey can trigger this
+        boolean inLoad = tab.inLoad();
+        if ((!mActivityInPause && !inLoad) || (mActivityInPause && inLoad)) {
             CookieSyncManager.getInstance().startSync();
-            WebView w = mTabControl.getCurrentWebView();
+            WebView w = tab.getWebView();
             if (w != null) {
                 w.resumeTimers();
             }
-            return true;
-        } else {
-            return false;
         }
     }
 
     private boolean pauseWebViewTimers() {
-        if (mActivityInPause && !mPageStarted) {
+        Tab tab = mTabControl.getCurrentTab();
+        boolean inLoad = tab.inLoad();
+        if (mActivityInPause && !inLoad) {
             CookieSyncManager.getInstance().stopSync();
             WebView w = mTabControl.getCurrentWebView();
             if (w != null) {
@@ -1250,75 +1063,24 @@
         }
     }
 
-    // FIXME: Do we want to call this when loading google for the first time?
-    /*
-     * This function is called when we are launching for the first time. We
-     * are waiting for the login credentials before loading Google home
-     * pages. This way the user will be logged in straight away.
-     */
-    private void waitForCredentials() {
-        // Show a toast
-        mCredsDlg = new ProgressDialog(this);
-        mCredsDlg.setIndeterminate(true);
-        mCredsDlg.setMessage(getText(R.string.retrieving_creds_dlg_msg));
-        // If the user cancels the operation, then cancel the Google
-        // Credentials request.
-        mCredsDlg.setCancelMessage(mHandler.obtainMessage(CANCEL_CREDS_REQUEST));
-        mCredsDlg.show();
-
-        // We set a timeout for the retrieval of credentials in onResume()
-        // as that is when we have freed up some CPU time to get
-        // the login credentials.
-    }
-
-    /*
-     * If we have received the credentials or we have timed out and we are
-     * showing the credentials dialog, then it is time to move on.
-     */
-    private void resumeAfterCredentials() {
-        if (mCredsDlg == null) {
-            return;
-        }
-
-        // Clear the toast
-        if (mCredsDlg.isShowing()) {
-            mCredsDlg.dismiss();
-        }
-        mCredsDlg = null;
-
-        // Clear any pending timeout
-        mHandler.removeMessages(CANCEL_CREDS_REQUEST);
-
-        // Load the page
-        WebView w = mTabControl.getCurrentWebView();
-        if (w != null) {
-            w.loadUrl(mSettings.getHomePage());
-        }
-
-        // Update the settings, need to do this last as it can take a moment
-        // to persist the settings. In the mean time we could be loading
-        // content.
-        mSettings.setLoginInitialized(this);
-    }
-
     // Open the icon database and retain all the icons for visited sites.
     private void retainIconsOnStartup() {
         final WebIconDatabase db = WebIconDatabase.getInstance();
         db.open(getDir("icons", 0).getPath());
+        Cursor c = null;
         try {
-            Cursor c = Browser.getAllBookmarks(mResolver);
-            if (!c.moveToFirst()) {
-                c.deactivate();
-                return;
+            c = Browser.getAllBookmarks(mResolver);
+            if (c.moveToFirst()) {
+                int urlIndex = c.getColumnIndex(Browser.BookmarkColumns.URL);
+                do {
+                    String url = c.getString(urlIndex);
+                    db.retainIconForPageUrl(url);
+                } while (c.moveToNext());
             }
-            int urlIndex = c.getColumnIndex(Browser.BookmarkColumns.URL);
-            do {
-                String url = c.getString(urlIndex);
-                db.retainIconForPageUrl(url);
-            } while (c.moveToNext());
-            c.deactivate();
         } catch (IllegalStateException e) {
             Log.e(LOGTAG, "retainIconsOnStartup", e);
+        } finally {
+            if (c!= null) c.close();
         }
     }
 
@@ -1327,6 +1089,10 @@
         return mTabControl.getCurrentTopWebView();
     }
 
+    TabControl getTabControl() {
+        return mTabControl;
+    }
+
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         super.onCreateOptionsMenu(menu);
@@ -1361,19 +1127,21 @@
         // options selector, so set mCanChord to true so we can access them.
         mCanChord = true;
         int id = item.getItemId();
+        boolean result = true;
         switch (id) {
             // For the context menu from the title bar
-            case R.id.title_bar_share_page_url:
             case R.id.title_bar_copy_page_url:
-                WebView mainView = mTabControl.getCurrentWebView();
+                Tab currentTab = mTabControl.getCurrentTab();
+                if (null == currentTab) {
+                    result = false;
+                    break;
+                }
+                WebView mainView = currentTab.getWebView();
                 if (null == mainView) {
-                    return false;
+                    result = false;
+                    break;
                 }
-                if (id == R.id.title_bar_share_page_url) {
-                    Browser.sendString(this, mainView.getUrl());
-                } else {
-                    copy(mainView.getUrl());
-                }
+                copy(mainView.getUrl());
                 break;
             // -- Browser context menu
             case R.id.open_context_menu_id:
@@ -1384,7 +1152,8 @@
             case R.id.copy_link_context_menu_id:
                 final WebView webView = getTopWindow();
                 if (null == webView) {
-                    return false;
+                    result = false;
+                    break;
                 }
                 final HashMap hrefMap = new HashMap();
                 hrefMap.put("webview", webView);
@@ -1395,31 +1164,29 @@
 
             default:
                 // For other context menus
-                return onOptionsItemSelected(item);
+                result = onOptionsItemSelected(item);
         }
         mCanChord = false;
-        return true;
+        return result;
     }
 
     private Bundle createGoogleSearchSourceBundle(String source) {
         Bundle bundle = new Bundle();
-        bundle.putString(SearchManager.SOURCE, source);
+        bundle.putString(Search.SOURCE, source);
         return bundle;
     }
 
+    /* package */ void editUrl() {
+        if (mOptionsMenuOpen) closeOptionsMenu();
+        String url = (getTopWindow() == null) ? null : getTopWindow().getUrl();
+        startSearch(mSettings.getHomePage().equals(url) ? null : url, true,
+                null, false);
+    }
+
     /**
      * Overriding this to insert a local information bundle
      */
     @Override
-    public boolean onSearchRequested() {
-        if (mOptionsMenuOpen) closeOptionsMenu();
-        String url = (getTopWindow() == null) ? null : getTopWindow().getUrl();
-        startSearch(mSettings.getHomePage().equals(url) ? null : url, true,
-                createGoogleSearchSourceBundle(GOOGLE_SEARCH_SOURCE_SEARCHKEY), false);
-        return true;
-    }
-
-    @Override
     public void startSearch(String initialQuery, boolean selectInitialQuery,
             Bundle appSearchData, boolean globalSearch) {
         if (appSearchData == null) {
@@ -1438,8 +1205,8 @@
      *                 the current one, return false.
      */
     /* package */ boolean switchToTab(int index) {
-        TabControl.Tab tab = mTabControl.getTab(index);
-        TabControl.Tab currentTab = mTabControl.getCurrentTab();
+        Tab tab = mTabControl.getTab(index);
+        Tab currentTab = mTabControl.getCurrentTab();
         if (tab == null || tab == currentTab) {
             return false;
         }
@@ -1455,12 +1222,12 @@
         return true;
     }
 
-    /* package */ TabControl.Tab openTabToHomePage() {
+    /* package */ Tab openTabToHomePage() {
         return openTabAndShow(mSettings.getHomePage(), false, null);
     }
 
     /* package */ void closeCurrentWindow() {
-        final TabControl.Tab current = mTabControl.getCurrentTab();
+        final Tab current = mTabControl.getCurrentTab();
         if (mTabControl.getTabCount() == 1) {
             // This is the last tab.  Open a new one, with the home
             // page and close the current one.
@@ -1468,7 +1235,7 @@
             closeTab(current);
             return;
         }
-        final TabControl.Tab parent = current.getParentTab();
+        final Tab parent = current.getParentTab();
         int indexToShow = -1;
         if (parent != null) {
             indexToShow = mTabControl.getTabIndex(parent);
@@ -1528,7 +1295,7 @@
                 break;
 
             case R.id.goto_menu_id:
-                onSearchRequested();
+                editUrl();
                 break;
 
             case R.id.bookmarks_menu_id:
@@ -1581,16 +1348,18 @@
                 break;
 
             case R.id.homepage_menu_id:
-                TabControl.Tab current = mTabControl.getCurrentTab();
+                Tab current = mTabControl.getCurrentTab();
                 if (current != null) {
                     dismissSubWindow(current);
-                    current.getWebView().loadUrl(mSettings.getHomePage());
+                    loadUrl(current.getWebView(), mSettings.getHomePage());
                 }
                 break;
 
             case R.id.preferences_menu_id:
                 Intent intent = new Intent(this,
                         BrowserPreferencesPage.class);
+                intent.putExtra(BrowserPreferencesPage.CURRENT_PAGE,
+                        getTopWindow().getUrl());
                 startActivityForResult(intent, PREFERENCES_PAGE);
                 break;
 
@@ -1600,6 +1369,7 @@
                 }
                 mFindDialog.setWebView(getTopWindow());
                 mFindDialog.show();
+                getTopWindow().setFindIsUp(true);
                 mMenuState = EMPTY_MENU;
                 break;
 
@@ -1614,15 +1384,27 @@
                 bookmarksOrHistoryPicker(true);
                 break;
 
+            case R.id.title_bar_share_page_url:
             case R.id.share_page_menu_id:
-                Browser.sendString(this, getTopWindow().getUrl(),
-                        getText(R.string.choosertitle_sharevia).toString());
+                Tab currentTab = mTabControl.getCurrentTab();
+                if (null == currentTab) {
+                    mCanChord = false;
+                    return false;
+                }
+                currentTab.populatePickerData();
+                sharePage(this, currentTab.getTitle(),
+                        currentTab.getUrl(), currentTab.getFavicon(),
+                        createScreenshot(currentTab.getWebView()));
                 break;
 
             case R.id.dump_nav_menu_id:
                 getTopWindow().debugDump();
                 break;
 
+            case R.id.dump_counters_menu_id:
+                getTopWindow().dumpV8Counters();
+                break;
+
             case R.id.zoom_in_menu_id:
                 getTopWindow().zoomIn();
                 break;
@@ -1647,7 +1429,7 @@
                     int menuid = item.getItemId();
                     for (int id = 0; id < WINDOW_SHORTCUT_ID_ARRAY.length; id++) {
                         if (WINDOW_SHORTCUT_ID_ARRAY[id] == menuid) {
-                            TabControl.Tab desiredTab = mTabControl.getTab(id);
+                            Tab desiredTab = mTabControl.getTab(id);
                             if (desiredTab != null &&
                                     desiredTab != mTabControl.getCurrentTab()) {
                                 switchToTab(id);
@@ -1672,8 +1454,8 @@
         mMenuState = R.id.MAIN_MENU;
     }
 
-    @Override public boolean onPrepareOptionsMenu(Menu menu)
-    {
+    @Override
+    public boolean onPrepareOptionsMenu(Menu menu) {
         // This happens when the user begins to hold down the menu key, so
         // allow them to chord to get a shortcut.
         mCanChord = true;
@@ -1714,7 +1496,7 @@
                         .setEnabled(canGoForward);
 
                 menu.findItem(R.id.new_tab_menu_id).setEnabled(
-                        mTabControl.getTabCount() < TabControl.MAX_TABS);
+                        mTabControl.canCreateNewTab());
 
                 // decide whether to show the share link option
                 PackageManager pm = getPackageManager();
@@ -1727,6 +1509,12 @@
                 final MenuItem nav = menu.findItem(R.id.dump_nav_menu_id);
                 nav.setVisible(isNavDump);
                 nav.setEnabled(isNavDump);
+
+                boolean showDebugSettings = mSettings.showDebugSettings();
+                final MenuItem counter = menu.findItem(R.id.dump_counters_menu_id);
+                counter.setVisible(showDebugSettings);
+                counter.setEnabled(showDebugSettings);
+
                 break;
         }
         mCurrentMenuState = mMenuState;
@@ -1736,6 +1524,9 @@
     @Override
     public void onCreateContextMenu(ContextMenu menu, View v,
             ContextMenuInfo menuInfo) {
+        if (v instanceof TitleBar) {
+            return;
+        }
         WebView webview = (WebView) v;
         WebView.HitTestResult result = webview.getHitTestResult();
         if (result == null) {
@@ -1818,7 +1609,9 @@
                 menu.setHeaderView(titleView);
                 // decide whether to show the open link in new tab option
                 menu.findItem(R.id.open_newtab_context_menu_id).setVisible(
-                        mTabControl.getTabCount() < TabControl.MAX_TABS);
+                        mTabControl.canCreateNewTab());
+                menu.findItem(R.id.bookmark_context_menu_id).setVisible(
+                        Bookmarks.urlHasAcceptableScheme(extra));
                 PackageManager pm = getPackageManager();
                 Intent send = new Intent(Intent.ACTION_SEND);
                 send.setType("text/plain");
@@ -1836,23 +1629,26 @@
                         new Intent(Intent.ACTION_VIEW, Uri.parse(extra)));
                 menu.findItem(R.id.download_context_menu_id).
                         setOnMenuItemClickListener(new Download(extra));
+                menu.findItem(R.id.set_wallpaper_context_menu_id).
+                        setOnMenuItemClickListener(new SetAsWallpaper(extra));
                 break;
 
             default:
                 Log.w(LOGTAG, "We should not get here.");
                 break;
         }
+        hideFakeTitleBar();
     }
 
     // Attach the given tab to the content view.
     // this should only be called for the current tab.
-    private void attachTabToContentView(TabControl.Tab t) {
+    private void attachTabToContentView(Tab t) {
         // Attach the container that contains the main WebView and any other UI
         // associated with the tab.
         t.attachTabToContentView(mContentView);
 
         if (mShouldShowErrorConsole) {
-            ErrorConsoleView errorConsole = mTabControl.getCurrentErrorConsole(true);
+            ErrorConsoleView errorConsole = t.getErrorConsole(true);
             if (errorConsole.numberOfErrors() == 0) {
                 errorConsole.showConsole(ErrorConsoleView.SHOW_NONE);
             } else {
@@ -1860,89 +1656,67 @@
             }
 
             mErrorConsoleContainer.addView(errorConsole,
-                    new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
+                    new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                                                   ViewGroup.LayoutParams.WRAP_CONTENT));
         }
 
-        setLockIconType(t.getLockIconType());
-        setPrevLockType(t.getPrevLockIconType());
-
-        // this is to match the code in removeTabFromContentView()
-        if (!mPageStarted && t.getTopWindow().getProgress() < 100) {
-            mPageStarted = true;
-        }
-
         WebView view = t.getWebView();
         view.setEmbeddedTitleBar(mTitleBar);
+        if (t.isInVoiceSearchMode()) {
+            showVoiceTitleBar(t.getVoiceDisplayTitle());
+        } else {
+            revertVoiceTitleBar();
+        }
         // Request focus on the top window.
         t.getTopWindow().requestFocus();
     }
 
     // Attach a sub window to the main WebView of the given tab.
-    private void attachSubWindow(TabControl.Tab t) {
+    void attachSubWindow(Tab t) {
         t.attachSubWindow(mContentView);
         getTopWindow().requestFocus();
     }
 
     // Remove the given tab from the content view.
-    private void removeTabFromContentView(TabControl.Tab t) {
+    private void removeTabFromContentView(Tab t) {
         // Remove the container that contains the main WebView.
         t.removeTabFromContentView(mContentView);
 
-        if (mTabControl.getCurrentErrorConsole(false) != null) {
-            mErrorConsoleContainer.removeView(mTabControl.getCurrentErrorConsole(false));
+        ErrorConsoleView errorConsole = t.getErrorConsole(false);
+        if (errorConsole != null) {
+            mErrorConsoleContainer.removeView(errorConsole);
         }
 
         WebView view = t.getWebView();
         if (view != null) {
             view.setEmbeddedTitleBar(null);
         }
-
-        // unlike attachTabToContentView(), removeTabFromContentView() can be
-        // called for the non-current tab. Need to add the check.
-        if (t == mTabControl.getCurrentTab()) {
-            t.setLockIconType(getLockIconType());
-            t.setPrevLockIconType(getPrevLockType());
-
-            // this is not a perfect solution. But currently there is one
-            // WebViewClient for all the WebView. if user switches from an
-            // in-load window to an already loaded window, mPageStarted will not
-            // be set to false. If user leaves the Browser, pauseWebViewTimers()
-            // won't do anything and leaves the timer running even Browser is in
-            // the background.
-            if (mPageStarted) {
-                mPageStarted = false;
-            }
-        }
     }
 
     // Remove the sub window if it exists. Also called by TabControl when the
     // user clicks the 'X' to dismiss a sub window.
-    /* package */ void dismissSubWindow(TabControl.Tab t) {
+    /* package */ void dismissSubWindow(Tab t) {
         t.removeSubWindow(mContentView);
-        // Tell the TabControl to dismiss the subwindow. This will destroy
-        // the WebView.
-        mTabControl.dismissSubWindow(t);
+        // dismiss the subwindow. This will destroy the WebView.
+        t.dismissSubWindow();
         getTopWindow().requestFocus();
     }
 
     // A wrapper function of {@link #openTabAndShow(UrlData, boolean, String)}
     // that accepts url as string.
-    private TabControl.Tab openTabAndShow(String url, boolean closeOnExit,
-            String appId) {
+    private Tab openTabAndShow(String url, boolean closeOnExit, String appId) {
         return openTabAndShow(new UrlData(url), closeOnExit, appId);
     }
 
     // This method does a ton of stuff. It will attempt to create a new tab
     // if we haven't reached MAX_TABS. Otherwise it uses the current tab. If
     // url isn't null, it will load the given url.
-    /* package */ TabControl.Tab openTabAndShow(UrlData urlData,
-            boolean closeOnExit, String appId) {
-        final boolean newTab = mTabControl.getTabCount() != TabControl.MAX_TABS;
-        final TabControl.Tab currentTab = mTabControl.getCurrentTab();
-        if (newTab) {
-            final TabControl.Tab tab = mTabControl.createNewTab(
-                    closeOnExit, appId, urlData.mUrl);
+    /* package */Tab openTabAndShow(UrlData urlData, boolean closeOnExit,
+            String appId) {
+        final Tab currentTab = mTabControl.getCurrentTab();
+        if (mTabControl.canCreateNewTab()) {
+            final Tab tab = mTabControl.createNewTab(closeOnExit, appId,
+                    urlData.mUrl);
             WebView webview = tab.getWebView();
             // If the last tab was removed from the active tabs page, currentTab
             // will be null.
@@ -1954,7 +1728,7 @@
             mTabControl.setCurrentTab(tab);
             attachTabToContentView(tab);
             if (!urlData.isEmpty()) {
-                urlData.loadIn(webview);
+                loadUrlDataIn(tab, urlData);
             }
             return tab;
         } else {
@@ -1962,18 +1736,18 @@
             dismissSubWindow(currentTab);
             if (!urlData.isEmpty()) {
                 // Load the given url.
-                urlData.loadIn(currentTab.getWebView());
+                loadUrlDataIn(currentTab, urlData);
             }
+            return currentTab;
         }
-        return currentTab;
     }
 
-    private TabControl.Tab openTab(String url) {
+    private Tab openTab(String url) {
         if (mSettings.openInBackground()) {
-            TabControl.Tab t = mTabControl.createNewTab();
+            Tab t = mTabControl.createNewTab();
             if (t != null) {
                 WebView view = t.getWebView();
-                view.loadUrl(url);
+                loadUrl(view, url);
             }
             return t;
         } else {
@@ -2007,6 +1781,82 @@
         }
     }
 
+    private class SetAsWallpaper extends Thread implements
+            OnMenuItemClickListener, DialogInterface.OnCancelListener {
+        private URL mUrl;
+        private ProgressDialog mWallpaperProgress;
+        private boolean mCanceled = false;
+
+        public SetAsWallpaper(String url) {
+            try {
+                mUrl = new URL(url);
+            } catch (MalformedURLException e) {
+                mUrl = null;
+            }
+        }
+
+        public void onCancel(DialogInterface dialog) {
+            mCanceled = true;
+        }
+
+        public boolean onMenuItemClick(MenuItem item) {
+            if (mUrl != null) {
+                // The user may have tried to set a image with a large file size as their
+                // background so it may take a few moments to perform the operation. Display
+                // a progress spinner while it is working.
+                mWallpaperProgress = new ProgressDialog(BrowserActivity.this);
+                mWallpaperProgress.setIndeterminate(true);
+                mWallpaperProgress.setMessage(getText(R.string.progress_dialog_setting_wallpaper));
+                mWallpaperProgress.setCancelable(true);
+                mWallpaperProgress.setOnCancelListener(this);
+                mWallpaperProgress.show();
+                start();
+            }
+            return true;
+        }
+
+        public void run() {
+            Drawable oldWallpaper = BrowserActivity.this.getWallpaper();
+            try {
+                // TODO: This will cause the resource to be downloaded again, when we
+                // should in most cases be able to grab it from the cache. To fix this
+                // we should query WebCore to see if we can access a cached version and
+                // instead open an input stream on that. This pattern could also be used
+                // in the download manager where the same problem exists.
+                InputStream inputstream = mUrl.openStream();
+                if (inputstream != null) {
+                    setWallpaper(inputstream);
+                }
+            } catch (IOException e) {
+                Log.e(LOGTAG, "Unable to set new wallpaper");
+                // Act as though the user canceled the operation so we try to
+                // restore the old wallpaper.
+                mCanceled = true;
+            }
+
+            if (mCanceled) {
+                // Restore the old wallpaper if the user cancelled whilst we were setting
+                // the new wallpaper.
+                int width = oldWallpaper.getIntrinsicWidth();
+                int height = oldWallpaper.getIntrinsicHeight();
+                Bitmap bm = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+                Canvas canvas = new Canvas(bm);
+                oldWallpaper.setBounds(0, 0, width, height);
+                oldWallpaper.draw(canvas);
+                try {
+                    setWallpaper(bm);
+                } catch (IOException e) {
+                    Log.e(LOGTAG, "Unable to restore old wallpaper.");
+                }
+                mCanceled = false;
+            }
+
+            if (mWallpaperProgress.isShowing()) {
+                mWallpaperProgress.dismiss();
+            }
+        }
+    }
+
     private void copy(CharSequence text) {
         try {
             IClipboard clip = IClipboard.Stub.asInterface(ServiceManager.getService("clipboard"));
@@ -2027,7 +1877,8 @@
      * call resetTitleAndRevertLockIcon.
      */
     /* package */ void resetTitleAndRevertLockIcon() {
-        revertLockIcon();
+        mTabControl.getCurrentTab().revertLockIcon();
+        updateLockIconToLatest();
         resetTitleIconAndProgress();
     }
 
@@ -2041,7 +1892,7 @@
         }
         resetTitleAndIcon(current);
         int progress = current.getProgress();
-        mWebChromeClient.onProgressChanged(current, progress);
+        current.getWebChromeClient().onProgressChanged(current, progress);
     }
 
     // Reset the title and the icon based on the given item.
@@ -2061,14 +1912,14 @@
      * @param url The URL of the site being loaded.
      * @param title The title of the site being loaded.
      */
-    private void setUrlTitle(String url, String title) {
+    void setUrlTitle(String url, String title) {
         mUrl = url;
         mTitle = title;
 
-        mTitleBar.setTitleAndUrl(title, url);
-        if (mFakeTitleBar != null) {
-            mFakeTitleBar.setTitleAndUrl(title, url);
-        }
+        // If we are in voice search mode, the title has already been set.
+        if (mTabControl.getCurrentTab().isInVoiceSearchMode()) return;
+        mTitleBar.setDisplayTitle(url);
+        mFakeTitleBar.setDisplayTitle(url);
     }
 
     /**
@@ -2109,43 +1960,16 @@
     }
 
     // Set the favicon in the title bar.
-    private void setFavicon(Bitmap icon) {
+    void setFavicon(Bitmap icon) {
         mTitleBar.setFavicon(icon);
-        if (mFakeTitleBar != null) {
-            mFakeTitleBar.setFavicon(icon);
-        }
-    }
-
-    /**
-     * Saves the current lock-icon state before resetting
-     * the lock icon. If we have an error, we may need to
-     * roll back to the previous state.
-     */
-    private void saveLockIcon() {
-        mPrevLockType = mLockIconType;
-    }
-
-    /**
-     * Reverts the lock-icon state to the last saved state,
-     * for example, if we had an error, and need to cancel
-     * the load.
-     */
-    private void revertLockIcon() {
-        mLockIconType = mPrevLockType;
-
-        if (LOGV_ENABLED) {
-            Log.v(LOGTAG, "BrowserActivity.revertLockIcon:" +
-                  " revert lock icon to " + mLockIconType);
-        }
-
-        updateLockIconToLatest();
+        mFakeTitleBar.setFavicon(icon);
     }
 
     /**
      * Close the tab, remove its associated title bar, and adjust mTabControl's
      * current tab to a valid value.
      */
-    /* package */ void closeTab(TabControl.Tab t) {
+    /* package */ void closeTab(Tab t) {
         int currentIndex = mTabControl.getCurrentIndex();
         int removeIndex = mTabControl.getTabIndex(t);
         mTabControl.removeTab(t);
@@ -2156,8 +1980,8 @@
         resetTitleIconAndProgress();
     }
 
-    private void goBackOnePageOrQuit() {
-        TabControl.Tab current = mTabControl.getCurrentTab();
+    /* package */ void goBackOnePageOrQuit() {
+        Tab current = mTabControl.getCurrentTab();
         if (current == null) {
             /*
              * Instead of finishing the activity, simply push this to the back
@@ -2175,17 +1999,17 @@
         } else {
             // Check to see if we are closing a window that was created by
             // another window. If so, we switch back to that window.
-            TabControl.Tab parent = current.getParentTab();
+            Tab parent = current.getParentTab();
             if (parent != null) {
                 switchToTab(mTabControl.getTabIndex(parent));
                 // Now we close the other tab
                 closeTab(current);
             } else {
                 if (current.closeOnExit()) {
-                    // force mPageStarted to be false as we are going to either
-                    // finish the activity or remove the tab. This will ensure
-                    // pauseWebView() taking action.
-                    mPageStarted = false;
+                    // force the tab's inLoad() to be false as we are going to
+                    // either finish the activity or remove the tab. This will
+                    // ensure pauseWebViewTimers() taking action.
+                    mTabControl.getCurrentTab().clearInLoad();
                     if (mTabControl.getTabCount() == 1) {
                         finish();
                         return;
@@ -2218,17 +2042,24 @@
         }
     }
 
+    boolean isMenuDown() {
+        return mMenuIsDown;
+    }
+
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
+        // Even if MENU is already held down, we need to call to super to open
+        // the IME on long press.
+        if (KeyEvent.KEYCODE_MENU == keyCode) {
+            mMenuIsDown = true;
+            return super.onKeyDown(keyCode, event);
+        }
         // The default key mode is DEFAULT_KEYS_SEARCH_LOCAL. As the MENU is
         // still down, we don't want to trigger the search. Pretend to consume
         // the key and do nothing.
         if (mMenuIsDown) return true;
 
         switch(keyCode) {
-            case KeyEvent.KEYCODE_MENU:
-                mMenuIsDown = true;
-                break;
             case KeyEvent.KEYCODE_SPACE:
                 // WebView/WebTextView handle the keys in the KeyDown. As
                 // the Activity's shortcut keys are only handled when WebView
@@ -2263,7 +2094,8 @@
                 if (event.isTracking() && !event.isCanceled()) {
                     if (mCustomView != null) {
                         // if a custom view is showing, hide it
-                        mWebChromeClient.onHideCustomView();
+                        mTabControl.getCurrentWebView().getWebChromeClient()
+                                .onHideCustomView();
                     } else if (mActiveTabsPage != null) {
                         // if tab page is showing, hide it
                         removeActiveTabPage(true);
@@ -2291,7 +2123,12 @@
         resetTitleAndRevertLockIcon();
         WebView w = getTopWindow();
         w.stopLoading();
-        mWebViewClient.onPageFinished(w, w.getUrl());
+        // FIXME: before refactor, it is using mWebViewClient. So I keep the
+        // same logic here. But for subwindow case, should we call into the main
+        // WebView's onPageFinished as we never call its onPageStarted and if
+        // the page finishes itself, we don't call onPageFinished.
+        mTabControl.getCurrentWebView().getWebViewClient().onPageFinished(w,
+                w.getUrl());
 
         cancelStopToast();
         mStopToast = Toast
@@ -2299,6 +2136,10 @@
         mStopToast.show();
     }
 
+    boolean didUserStopLoading() {
+        return mDidStopLoad;
+    }
+
     private void cancelStopToast() {
         if (mStopToast != null) {
             mStopToast.cancel();
@@ -2306,9 +2147,16 @@
         }
     }
 
-    // called by a non-UI thread to post the message
-    public void postMessage(int what, int arg1, int arg2, Object obj) {
-        mHandler.sendMessage(mHandler.obtainMessage(what, arg1, arg2, obj));
+    // called by a UI or non-UI thread to post the message
+    public void postMessage(int what, int arg1, int arg2, Object obj,
+            long delayMillis) {
+        mHandler.sendMessageDelayed(mHandler.obtainMessage(what, arg1, arg2,
+                obj), delayMillis);
+    }
+
+    // called by a UI or non-UI thread to remove the message
+    void removeMessages(int what, Object object) {
+        mHandler.removeMessages(what, object);
     }
 
     // public message ids
@@ -2317,10 +2165,9 @@
 
     // Message Ids
     private static final int FOCUS_NODE_HREF         = 102;
-    private static final int CANCEL_CREDS_REQUEST    = 103;
     private static final int RELEASE_WAKELOCK        = 107;
 
-    private static final int UPDATE_BOOKMARK_THUMBNAIL = 108;
+    static final int UPDATE_BOOKMARK_THUMBNAIL       = 108;
 
     // Private handler for handling javascript and saving passwords
     private Handler mHandler = new Handler() {
@@ -2330,6 +2177,7 @@
                 case FOCUS_NODE_HREF:
                 {
                     String url = (String) msg.getData().get("url");
+                    String title = (String) msg.getData().get("title");
                     if (url == null || url.length() == 0) {
                         break;
                     }
@@ -2342,12 +2190,11 @@
                     switch (msg.arg1) {
                         case R.id.open_context_menu_id:
                         case R.id.view_image_context_menu_id:
-                            loadURL(getTopWindow(), url);
+                            loadUrlFromContext(getTopWindow(), url);
                             break;
                         case R.id.open_newtab_context_menu_id:
-                            final TabControl.Tab parent = mTabControl
-                                    .getCurrentTab();
-                            final TabControl.Tab newTab = openTab(url);
+                            final Tab parent = mTabControl.getCurrentTab();
+                            final Tab newTab = openTab(url);
                             if (newTab != parent) {
                                 parent.addChildTab(newTab);
                             }
@@ -2356,11 +2203,45 @@
                             Intent intent = new Intent(BrowserActivity.this,
                                     AddBookmarkPage.class);
                             intent.putExtra("url", url);
+                            intent.putExtra("title", title);
                             startActivity(intent);
                             break;
                         case R.id.share_link_context_menu_id:
-                            Browser.sendString(BrowserActivity.this, url,
-                                    getText(R.string.choosertitle_sharevia).toString());
+                            // See if this site has been visited before
+                            StringBuilder sb = new StringBuilder(
+                                    Browser.BookmarkColumns.URL + " = ");
+                            DatabaseUtils.appendEscapedSQLString(sb, url);
+                            Cursor c = mResolver.query(Browser.BOOKMARKS_URI,
+                                    Browser.HISTORY_PROJECTION,
+                                    sb.toString(),
+                                    null,
+                                    null);
+                            if (c.moveToFirst()) {
+                                // The site has been visited before, so grab the
+                                // info from the database.
+                                Bitmap favicon = null;
+                                Bitmap thumbnail = null;
+                                String linkTitle = c.getString(Browser.
+                                        HISTORY_PROJECTION_TITLE_INDEX);
+                                byte[] data = c.getBlob(Browser.
+                                        HISTORY_PROJECTION_FAVICON_INDEX);
+                                if (data != null) {
+                                    favicon = BitmapFactory.decodeByteArray(
+                                            data, 0, data.length);
+                                }
+                                data = c.getBlob(Browser.
+                                        HISTORY_PROJECTION_THUMBNAIL_INDEX);
+                                if (data != null) {
+                                    thumbnail = BitmapFactory.decodeByteArray(
+                                            data, 0, data.length);
+                                }
+                                sharePage(BrowserActivity.this,
+                                        linkTitle, url, favicon, thumbnail);
+                            } else {
+                                Browser.sendString(BrowserActivity.this, url,
+                                        getString(
+                                        R.string.choosertitle_sharevia));
+                            }
                             break;
                         case R.id.copy_link_context_menu_id:
                             copy(url);
@@ -2374,20 +2255,20 @@
                 }
 
                 case LOAD_URL:
-                    loadURL(getTopWindow(), (String) msg.obj);
+                    loadUrlFromContext(getTopWindow(), (String) msg.obj);
                     break;
 
                 case STOP_LOAD:
                     stopLoading();
                     break;
 
-                case CANCEL_CREDS_REQUEST:
-                    resumeAfterCredentials();
-                    break;
-
                 case RELEASE_WAKELOCK:
                     if (mWakeLock.isHeld()) {
                         mWakeLock.release();
+                        // if we reach here, Browser should be still in the
+                        // background loading after WAKELOCK_TIMEOUT (5-min).
+                        // To avoid burning the battery, stop loading.
+                        mTabControl.stopAllLoading();
                     }
                     break;
 
@@ -2401,6 +2282,35 @@
         }
     };
 
+    /**
+     * Share a page, providing the title, url, favicon, and a screenshot.  Uses
+     * an {@link Intent} to launch the Activity chooser.
+     * @param c Context used to launch a new Activity.
+     * @param title Title of the page.  Stored in the Intent with
+     *          {@link Intent#EXTRA_SUBJECT}
+     * @param url URL of the page.  Stored in the Intent with
+     *          {@link Intent#EXTRA_TEXT}
+     * @param favicon Bitmap of the favicon for the page.  Stored in the Intent
+     *          with {@link Browser#EXTRA_SHARE_FAVICON}
+     * @param screenshot Bitmap of a screenshot of the page.  Stored in the
+     *          Intent with {@link Browser#EXTRA_SHARE_SCREENSHOT}
+     */
+    public static final void sharePage(Context c, String title, String url,
+            Bitmap favicon, Bitmap screenshot) {
+        Intent send = new Intent(Intent.ACTION_SEND);
+        send.setType("text/plain");
+        send.putExtra(Intent.EXTRA_TEXT, url);
+        send.putExtra(Intent.EXTRA_SUBJECT, title);
+        send.putExtra(Browser.EXTRA_SHARE_FAVICON, favicon);
+        send.putExtra(Browser.EXTRA_SHARE_SCREENSHOT, screenshot);
+        try {
+            c.startActivity(Intent.createChooser(send, c.getString(
+                    R.string.choosertitle_sharevia)));
+        } catch(android.content.ActivityNotFoundException ex) {
+            // if no app handles it, do nothing
+        }
+    }
+
     private void updateScreenshot(WebView view) {
         // If this is a bookmarked site, add a screenshot to the database.
         // FIXME: When should we update?  Every time?
@@ -2408,32 +2318,45 @@
         // draw, but the API for that (WebViewCore.pictureReady()) is not
         // currently accessible here.
 
-        ContentResolver cr = getContentResolver();
-        final Cursor c = BrowserBookmarksAdapter.queryBookmarksForUrl(
-                cr, view.getOriginalUrl(), view.getUrl(), true);
-        if (c != null) {
-            boolean succeed = c.moveToFirst();
-            ContentValues values = null;
-            while (succeed) {
-                if (values == null) {
-                    final ByteArrayOutputStream os
-                            = new ByteArrayOutputStream();
-                    Bitmap bm = createScreenshot(view);
-                    if (bm == null) {
-                        c.close();
-                        return;
-                    }
-                    bm.compress(Bitmap.CompressFormat.PNG, 100, os);
-                    values = new ContentValues();
-                    values.put(Browser.BookmarkColumns.THUMBNAIL,
-                            os.toByteArray());
-                }
-                cr.update(ContentUris.withAppendedId(Browser.BOOKMARKS_URI,
-                        c.getInt(0)), values, null, null);
-                succeed = c.moveToNext();
-            }
-            c.close();
+        final Bitmap bm = createScreenshot(view);
+        if (bm == null) {
+            return;
         }
+
+        final ContentResolver cr = getContentResolver();
+        final String url = view.getUrl();
+        final String originalUrl = view.getOriginalUrl();
+
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... unused) {
+                Cursor c = null;
+                try {
+                    c = BrowserBookmarksAdapter.queryBookmarksForUrl(
+                            cr, originalUrl, url, true);
+                    if (c != null) {
+                        if (c.moveToFirst()) {
+                            ContentValues values = new ContentValues();
+                            final ByteArrayOutputStream os
+                                    = new ByteArrayOutputStream();
+                            bm.compress(Bitmap.CompressFormat.PNG, 100, os);
+                            values.put(Browser.BookmarkColumns.THUMBNAIL,
+                                    os.toByteArray());
+                            do {
+                                cr.update(ContentUris.withAppendedId(
+                                        Browser.BOOKMARKS_URI, c.getInt(0)),
+                                        values, null, null);
+                            } while (c.moveToNext());
+                        }
+                    }
+                } catch (IllegalStateException e) {
+                    // Ignore
+                } finally {
+                    if (c != null) c.close();
+                }
+                return null;
+            }
+        }.execute();
     }
 
     /**
@@ -2477,22 +2400,41 @@
             return null;
         }
         Bitmap bm = Bitmap.createBitmap(getDesiredThumbnailWidth(this),
-                getDesiredThumbnailHeight(this), Bitmap.Config.ARGB_4444);
+                getDesiredThumbnailHeight(this), Bitmap.Config.RGB_565);
         Canvas canvas = new Canvas(bm);
         // May need to tweak these values to determine what is the
         // best scale factor
         int thumbnailWidth = thumbnail.getWidth();
+        int thumbnailHeight = thumbnail.getHeight();
+        float scaleFactorX = 1.0f;
+        float scaleFactorY = 1.0f;
         if (thumbnailWidth > 0) {
-            float scaleFactor = (float) getDesiredThumbnailWidth(this) /
+            scaleFactorX = (float) getDesiredThumbnailWidth(this) /
                     (float)thumbnailWidth;
-            canvas.scale(scaleFactor, scaleFactor);
+        } else {
+            return null;
         }
+
+        if (view.getWidth() > view.getHeight() &&
+                thumbnailHeight < view.getHeight() && thumbnailHeight > 0) {
+            // If the device is in landscape and the page is shorter
+            // than the height of the view, stretch the thumbnail to fill the
+            // space.
+            scaleFactorY = (float) getDesiredThumbnailHeight(this) /
+                    (float)thumbnailHeight;
+        } else {
+            // In the portrait case, this looks nice.
+            scaleFactorY = scaleFactorX;
+        }
+
+        canvas.scale(scaleFactorX, scaleFactorY);
+
         thumbnail.draw(canvas);
         return bm;
     }
 
     // -------------------------------------------------------------------------
-    // WebViewClient implementation.
+    // Helper function for WebViewClient.
     //-------------------------------------------------------------------------
 
     // Use in overrideUrlLoading
@@ -2501,1022 +2443,320 @@
     /* package */ final static String SCHEME_WTAI_SD = "wtai://wp/sd;";
     /* package */ final static String SCHEME_WTAI_AP = "wtai://wp/ap;";
 
-    /* package */ WebViewClient getWebViewClient() {
-        return mWebViewClient;
-    }
+    // Keep this initial progress in sync with initialProgressValue (* 100)
+    // in ProgressTracker.cpp
+    private final static int INITIAL_PROGRESS = 10;
 
-    private void updateIcon(WebView view, Bitmap icon) {
-        if (icon != null) {
-            BrowserBookmarksAdapter.updateBookmarkFavicon(mResolver,
-                    view.getOriginalUrl(), view.getUrl(), icon);
-        }
-        setFavicon(icon);
-    }
+    void onPageStarted(WebView view, String url, Bitmap favicon) {
+        // when BrowserActivity just starts, onPageStarted may be called before
+        // onResume as it is triggered from onCreate. Call resumeWebViewTimers
+        // to start the timer. As we won't switch tabs while an activity is in
+        // pause state, we can ensure calling resume and pause in pair.
+        if (mActivityInPause) resumeWebViewTimers();
 
-    private void updateIcon(String url, Bitmap icon) {
-        if (icon != null) {
-            BrowserBookmarksAdapter.updateBookmarkFavicon(mResolver,
-                    null, url, icon);
-        }
-        setFavicon(icon);
-    }
+        resetLockIcon(url);
+        setUrlTitle(url, null);
+        setFavicon(favicon);
+        // Show some progress so that the user knows the page is beginning to
+        // load
+        onProgressChanged(view, INITIAL_PROGRESS);
+        mDidStopLoad = false;
+        if (!mIsNetworkUp) createAndShowNetworkDialog();
 
-    private final WebViewClient mWebViewClient = new WebViewClient() {
-        @Override
-        public void onPageStarted(WebView view, String url, Bitmap favicon) {
-            resetLockIcon(url);
-            setUrlTitle(url, null);
-
-            // We've started to load a new page. If there was a pending message
-            // to save a screenshot then we will now take the new page and
-            // save an incorrect screenshot. Therefore, remove any pending
-            // thumbnail messages from the queue.
-            mHandler.removeMessages(UPDATE_BOOKMARK_THUMBNAIL);
-
-            // If we start a touch icon load and then load a new page, we don't
-            // want to cancel the current touch icon loader. But, we do want to
-            // create a new one when the touch icon url is known.
-            if (mTouchIconLoader != null) {
-                mTouchIconLoader.mActivity = null;
-                mTouchIconLoader = null;
-            }
-
-            ErrorConsoleView errorConsole = mTabControl.getCurrentErrorConsole(false);
-            if (errorConsole != null) {
-                errorConsole.clearErrorMessages();
-                if (mShouldShowErrorConsole) {
-                    errorConsole.showConsole(ErrorConsoleView.SHOW_NONE);
-                }
-            }
-
-            // Call updateIcon instead of setFavicon so the bookmark
-            // database can be updated.
-            updateIcon(url, favicon);
-
-            if (mSettings.isTracing()) {
-                String host;
-                try {
-                    WebAddress uri = new WebAddress(url);
-                    host = uri.mHost;
-                } catch (android.net.ParseException ex) {
-                    host = "browser";
-                }
-                host = host.replace('.', '_');
-                host += ".trace";
-                mInTrace = true;
-                Debug.startMethodTracing(host, 20 * 1024 * 1024);
-            }
-
-            // Performance probe
-            if (false) {
-                mStart = SystemClock.uptimeMillis();
-                mProcessStart = Process.getElapsedCpuTime();
-                long[] sysCpu = new long[7];
-                if (Process.readProcFile("/proc/stat", SYSTEM_CPU_FORMAT, null,
-                        sysCpu, null)) {
-                    mUserStart = sysCpu[0] + sysCpu[1];
-                    mSystemStart = sysCpu[2];
-                    mIdleStart = sysCpu[3];
-                    mIrqStart = sysCpu[4] + sysCpu[5] + sysCpu[6];
-                }
-                mUiStart = SystemClock.currentThreadTimeMillis();
-            }
-
-            if (!mPageStarted) {
-                mPageStarted = true;
-                // if onResume() has been called, resumeWebViewTimers() does
-                // nothing.
-                resumeWebViewTimers();
-            }
-
-            // reset sync timer to avoid sync starts during loading a page
-            CookieSyncManager.getInstance().resetSync();
-
-            mInLoad = true;
-            mDidStopLoad = false;
-            showFakeTitleBar();
-            updateInLoadMenuItems();
-            if (!mIsNetworkUp) {
-                createAndShowNetworkDialog();
-                if (view != null) {
-                    view.setNetworkAvailable(false);
-                }
-            }
-        }
-
-        @Override
-        public void onPageFinished(WebView view, String url) {
-            // Reset the title and icon in case we stopped a provisional
-            // load.
-            resetTitleAndIcon(view);
-
-            if (!mDidStopLoad) {
-                // Only update the bookmark screenshot if the user did not
-                // cancel the load early.
-                Message updateScreenshot = Message.obtain(mHandler, UPDATE_BOOKMARK_THUMBNAIL, view);
-                mHandler.sendMessageDelayed(updateScreenshot, 500);
-            }
-
-            // Update the lock icon image only once we are done loading
-            updateLockIconToLatest();
-
-            // Performance probe
-            if (false) {
-                long[] sysCpu = new long[7];
-                if (Process.readProcFile("/proc/stat", SYSTEM_CPU_FORMAT, null,
-                        sysCpu, null)) {
-                    String uiInfo = "UI thread used "
-                            + (SystemClock.currentThreadTimeMillis() - mUiStart)
-                            + " ms";
-                    if (LOGD_ENABLED) {
-                        Log.d(LOGTAG, uiInfo);
-                    }
-                    //The string that gets written to the log
-                    String performanceString = "It took total "
-                            + (SystemClock.uptimeMillis() - mStart)
-                            + " ms clock time to load the page."
-                            + "\nbrowser process used "
-                            + (Process.getElapsedCpuTime() - mProcessStart)
-                            + " ms, user processes used "
-                            + (sysCpu[0] + sysCpu[1] - mUserStart) * 10
-                            + " ms, kernel used "
-                            + (sysCpu[2] - mSystemStart) * 10
-                            + " ms, idle took " + (sysCpu[3] - mIdleStart) * 10
-                            + " ms and irq took "
-                            + (sysCpu[4] + sysCpu[5] + sysCpu[6] - mIrqStart)
-                            * 10 + " ms, " + uiInfo;
-                    if (LOGD_ENABLED) {
-                        Log.d(LOGTAG, performanceString + "\nWebpage: " + url);
-                    }
-                    if (url != null) {
-                        // strip the url to maintain consistency
-                        String newUrl = new String(url);
-                        if (newUrl.startsWith("http://www.")) {
-                            newUrl = newUrl.substring(11);
-                        } else if (newUrl.startsWith("http://")) {
-                            newUrl = newUrl.substring(7);
-                        } else if (newUrl.startsWith("https://www.")) {
-                            newUrl = newUrl.substring(12);
-                        } else if (newUrl.startsWith("https://")) {
-                            newUrl = newUrl.substring(8);
-                        }
-                        if (LOGD_ENABLED) {
-                            Log.d(LOGTAG, newUrl + " loaded");
-                        }
-                        /*
-                        if (sWhiteList.contains(newUrl)) {
-                            // The string that gets pushed to the statistcs
-                            // service
-                            performanceString = performanceString
-                                    + "\nWebpage: "
-                                    + newUrl
-                                    + "\nCarrier: "
-                                    + android.os.SystemProperties
-                                            .get("gsm.sim.operator.alpha");
-                            if (mWebView != null
-                                    && mWebView.getContext() != null
-                                    && mWebView.getContext().getSystemService(
-                                    Context.CONNECTIVITY_SERVICE) != null) {
-                                ConnectivityManager cManager =
-                                        (ConnectivityManager) mWebView
-                                        .getContext().getSystemService(
-                                        Context.CONNECTIVITY_SERVICE);
-                                NetworkInfo nInfo = cManager
-                                        .getActiveNetworkInfo();
-                                if (nInfo != null) {
-                                    performanceString = performanceString
-                                            + "\nNetwork Type: "
-                                            + nInfo.getType().toString();
-                                }
-                            }
-                            Checkin.logEvent(mResolver,
-                                    Checkin.Events.Tag.WEBPAGE_LOAD,
-                                    performanceString);
-                            Log.w(LOGTAG, "pushed to the statistics service");
-                        }
-                        */
-                    }
-                }
-             }
-
-            if (mInTrace) {
-                mInTrace = false;
-                Debug.stopMethodTracing();
-            }
-
-            if (mPageStarted) {
-                mPageStarted = false;
-                // pauseWebViewTimers() will do nothing and return false if
-                // onPause() is not called yet.
-                if (pauseWebViewTimers()) {
-                    if (mWakeLock.isHeld()) {
-                        mHandler.removeMessages(RELEASE_WAKELOCK);
-                        mWakeLock.release();
-                    }
-                }
-            }
-        }
-
-        // return true if want to hijack the url to let another app to handle it
-        @Override
-        public boolean shouldOverrideUrlLoading(WebView view, String url) {
-            if (url.startsWith(SCHEME_WTAI)) {
-                // wtai://wp/mc;number
-                // number=string(phone-number)
-                if (url.startsWith(SCHEME_WTAI_MC)) {
-                    Intent intent = new Intent(Intent.ACTION_VIEW,
-                            Uri.parse(WebView.SCHEME_TEL +
-                            url.substring(SCHEME_WTAI_MC.length())));
-                    startActivity(intent);
-                    return true;
-                }
-                // wtai://wp/sd;dtmf
-                // dtmf=string(dialstring)
-                if (url.startsWith(SCHEME_WTAI_SD)) {
-                    // TODO
-                    // only send when there is active voice connection
-                    return false;
-                }
-                // wtai://wp/ap;number;name
-                // number=string(phone-number)
-                // name=string
-                if (url.startsWith(SCHEME_WTAI_AP)) {
-                    // TODO
-                    return false;
-                }
-            }
-
-            // The "about:" schemes are internal to the browser; don't
-            // want these to be dispatched to other apps.
-            if (url.startsWith("about:")) {
-                return false;
-            }
-
-            Intent intent;
-
-            // perform generic parsing of the URI to turn it into an Intent.
+        if (mSettings.isTracing()) {
+            String host;
             try {
-                intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
-            } catch (URISyntaxException ex) {
-                Log.w("Browser", "Bad URI " + url + ": " + ex.getMessage());
-                return false;
+                WebAddress uri = new WebAddress(url);
+                host = uri.mHost;
+            } catch (android.net.ParseException ex) {
+                host = "browser";
             }
+            host = host.replace('.', '_');
+            host += ".trace";
+            mInTrace = true;
+            Debug.startMethodTracing(host, 20 * 1024 * 1024);
+        }
 
-            // check whether the intent can be resolved. If not, we will see
-            // whether we can download it from the Market.
-            if (getPackageManager().resolveActivity(intent, 0) == null) {
-                String packagename = intent.getPackage();
-                if (packagename != null) {
-                    intent = new Intent(Intent.ACTION_VIEW, Uri
-                            .parse("market://search?q=pname:" + packagename));
-                    intent.addCategory(Intent.CATEGORY_BROWSABLE);
-                    startActivity(intent);
-                    return true;
-                } else {
-                    return false;
+        // Performance probe
+        if (false) {
+            mStart = SystemClock.uptimeMillis();
+            mProcessStart = Process.getElapsedCpuTime();
+            long[] sysCpu = new long[7];
+            if (Process.readProcFile("/proc/stat", SYSTEM_CPU_FORMAT, null,
+                    sysCpu, null)) {
+                mUserStart = sysCpu[0] + sysCpu[1];
+                mSystemStart = sysCpu[2];
+                mIdleStart = sysCpu[3];
+                mIrqStart = sysCpu[4] + sysCpu[5] + sysCpu[6];
+            }
+            mUiStart = SystemClock.currentThreadTimeMillis();
+        }
+    }
+
+    void onPageFinished(WebView view, String url) {
+        // Reset the title and icon in case we stopped a provisional load.
+        resetTitleAndIcon(view);
+        // Update the lock icon image only once we are done loading
+        updateLockIconToLatest();
+        // pause the WebView timer and release the wake lock if it is finished
+        // while BrowserActivity is in pause state.
+        if (mActivityInPause && pauseWebViewTimers()) {
+            if (mWakeLock.isHeld()) {
+                mHandler.removeMessages(RELEASE_WAKELOCK);
+                mWakeLock.release();
+            }
+        }
+
+        // Performance probe
+        if (false) {
+            long[] sysCpu = new long[7];
+            if (Process.readProcFile("/proc/stat", SYSTEM_CPU_FORMAT, null,
+                    sysCpu, null)) {
+                String uiInfo = "UI thread used "
+                        + (SystemClock.currentThreadTimeMillis() - mUiStart)
+                        + " ms";
+                if (LOGD_ENABLED) {
+                    Log.d(LOGTAG, uiInfo);
+                }
+                //The string that gets written to the log
+                String performanceString = "It took total "
+                        + (SystemClock.uptimeMillis() - mStart)
+                        + " ms clock time to load the page."
+                        + "\nbrowser process used "
+                        + (Process.getElapsedCpuTime() - mProcessStart)
+                        + " ms, user processes used "
+                        + (sysCpu[0] + sysCpu[1] - mUserStart) * 10
+                        + " ms, kernel used "
+                        + (sysCpu[2] - mSystemStart) * 10
+                        + " ms, idle took " + (sysCpu[3] - mIdleStart) * 10
+                        + " ms and irq took "
+                        + (sysCpu[4] + sysCpu[5] + sysCpu[6] - mIrqStart)
+                        * 10 + " ms, " + uiInfo;
+                if (LOGD_ENABLED) {
+                    Log.d(LOGTAG, performanceString + "\nWebpage: " + url);
+                }
+                if (url != null) {
+                    // strip the url to maintain consistency
+                    String newUrl = new String(url);
+                    if (newUrl.startsWith("http://www.")) {
+                        newUrl = newUrl.substring(11);
+                    } else if (newUrl.startsWith("http://")) {
+                        newUrl = newUrl.substring(7);
+                    } else if (newUrl.startsWith("https://www.")) {
+                        newUrl = newUrl.substring(12);
+                    } else if (newUrl.startsWith("https://")) {
+                        newUrl = newUrl.substring(8);
+                    }
+                    if (LOGD_ENABLED) {
+                        Log.d(LOGTAG, newUrl + " loaded");
+                    }
                 }
             }
+         }
 
-            // sanitize the Intent, ensuring web pages can not bypass browser
-            // security (only access to BROWSABLE activities).
-            intent.addCategory(Intent.CATEGORY_BROWSABLE);
-            intent.setComponent(null);
-            try {
-                if (startActivityIfNeeded(intent, -1)) {
-                    return true;
-                }
-            } catch (ActivityNotFoundException ex) {
-                // ignore the error. If no application can handle the URL,
-                // eg about:blank, assume the browser can handle it.
-            }
+        if (mInTrace) {
+            mInTrace = false;
+            Debug.stopMethodTracing();
+        }
+    }
 
-            if (mMenuIsDown) {
-                openTab(url);
-                closeOptionsMenu();
+    boolean shouldOverrideUrlLoading(WebView view, String url) {
+        if (url.startsWith(SCHEME_WTAI)) {
+            // wtai://wp/mc;number
+            // number=string(phone-number)
+            if (url.startsWith(SCHEME_WTAI_MC)) {
+                Intent intent = new Intent(Intent.ACTION_VIEW,
+                        Uri.parse(WebView.SCHEME_TEL +
+                        url.substring(SCHEME_WTAI_MC.length())));
+                startActivity(intent);
                 return true;
             }
+            // wtai://wp/sd;dtmf
+            // dtmf=string(dialstring)
+            if (url.startsWith(SCHEME_WTAI_SD)) {
+                // TODO: only send when there is active voice connection
+                return false;
+            }
+            // wtai://wp/ap;number;name
+            // number=string(phone-number)
+            // name=string
+            if (url.startsWith(SCHEME_WTAI_AP)) {
+                // TODO
+                return false;
+            }
+        }
 
+        // The "about:" schemes are internal to the browser; don't want these to
+        // be dispatched to other apps.
+        if (url.startsWith("about:")) {
             return false;
         }
 
-        /**
-         * Updates the lock icon. This method is called when we discover another
-         * resource to be loaded for this page (for example, javascript). While
-         * we update the icon type, we do not update the lock icon itself until
-         * we are done loading, it is slightly more secure this way.
-         */
-        @Override
-        public void onLoadResource(WebView view, String url) {
-            if (url != null && url.length() > 0) {
-                // It is only if the page claims to be secure
-                // that we may have to update the lock:
-                if (mLockIconType == LOCK_ICON_SECURE) {
-                    // If NOT a 'safe' url, change the lock to mixed content!
-                    if (!(URLUtil.isHttpsUrl(url) || URLUtil.isDataUrl(url) || URLUtil.isAboutUrl(url))) {
-                        mLockIconType = LOCK_ICON_MIXED;
-                        if (LOGV_ENABLED) {
-                            Log.v(LOGTAG, "BrowserActivity.updateLockIcon:" +
-                                  " updated lock icon to " + mLockIconType + " due to " + url);
-                        }
-                    }
-                }
-            }
+        Intent intent;
+        // perform generic parsing of the URI to turn it into an Intent.
+        try {
+            intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
+        } catch (URISyntaxException ex) {
+            Log.w("Browser", "Bad URI " + url + ": " + ex.getMessage());
+            return false;
         }
 
-        /**
-         * Show the dialog, asking the user if they would like to continue after
-         * an excessive number of HTTP redirects.
-         */
-        @Override
-        public void onTooManyRedirects(WebView view, final Message cancelMsg,
-                final Message continueMsg) {
-            new AlertDialog.Builder(BrowserActivity.this)
-                .setTitle(R.string.browserFrameRedirect)
-                .setMessage(R.string.browserFrame307Post)
-                .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
-                    public void onClick(DialogInterface dialog, int which) {
-                        continueMsg.sendToTarget();
-                    }})
-                .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
-                    public void onClick(DialogInterface dialog, int which) {
-                        cancelMsg.sendToTarget();
-                    }})
-                .setOnCancelListener(new OnCancelListener() {
-                    public void onCancel(DialogInterface dialog) {
-                        cancelMsg.sendToTarget();
-                    }})
-                .show();
-        }
-
-        // Container class for the next error dialog that needs to be
-        // displayed.
-        class ErrorDialog {
-            public final int mTitle;
-            public final String mDescription;
-            public final int mError;
-            ErrorDialog(int title, String desc, int error) {
-                mTitle = title;
-                mDescription = desc;
-                mError = error;
-            }
-        };
-
-        private void processNextError() {
-            if (mQueuedErrors == null) {
-                return;
-            }
-            // The first one is currently displayed so just remove it.
-            mQueuedErrors.removeFirst();
-            if (mQueuedErrors.size() == 0) {
-                mQueuedErrors = null;
-                return;
-            }
-            showError(mQueuedErrors.getFirst());
-        }
-
-        private DialogInterface.OnDismissListener mDialogListener =
-                new DialogInterface.OnDismissListener() {
-                    public void onDismiss(DialogInterface d) {
-                        processNextError();
-                    }
-                };
-        private LinkedList<ErrorDialog> mQueuedErrors;
-
-        private void queueError(int err, String desc) {
-            if (mQueuedErrors == null) {
-                mQueuedErrors = new LinkedList<ErrorDialog>();
-            }
-            for (ErrorDialog d : mQueuedErrors) {
-                if (d.mError == err) {
-                    // Already saw a similar error, ignore the new one.
-                    return;
-                }
-            }
-            ErrorDialog errDialog = new ErrorDialog(
-                    err == WebViewClient.ERROR_FILE_NOT_FOUND ?
-                    R.string.browserFrameFileErrorLabel :
-                    R.string.browserFrameNetworkErrorLabel,
-                    desc, err);
-            mQueuedErrors.addLast(errDialog);
-
-            // Show the dialog now if the queue was empty.
-            if (mQueuedErrors.size() == 1) {
-                showError(errDialog);
-            }
-        }
-
-        private void showError(ErrorDialog errDialog) {
-            AlertDialog d = new AlertDialog.Builder(BrowserActivity.this)
-                    .setTitle(errDialog.mTitle)
-                    .setMessage(errDialog.mDescription)
-                    .setPositiveButton(R.string.ok, null)
-                    .create();
-            d.setOnDismissListener(mDialogListener);
-            d.show();
-        }
-
-        /**
-         * Show a dialog informing the user of the network error reported by
-         * WebCore.
-         */
-        @Override
-        public void onReceivedError(WebView view, int errorCode,
-                String description, String failingUrl) {
-            if (errorCode != WebViewClient.ERROR_HOST_LOOKUP &&
-                    errorCode != WebViewClient.ERROR_CONNECT &&
-                    errorCode != WebViewClient.ERROR_BAD_URL &&
-                    errorCode != WebViewClient.ERROR_UNSUPPORTED_SCHEME &&
-                    errorCode != WebViewClient.ERROR_FILE) {
-                queueError(errorCode, description);
-            }
-            Log.e(LOGTAG, "onReceivedError " + errorCode + " " + failingUrl
-                    + " " + description);
-
-            // We need to reset the title after an error.
-            resetTitleAndRevertLockIcon();
-        }
-
-        /**
-         * Check with the user if it is ok to resend POST data as the page they
-         * are trying to navigate to is the result of a POST.
-         */
-        @Override
-        public void onFormResubmission(WebView view, final Message dontResend,
-                                       final Message resend) {
-            new AlertDialog.Builder(BrowserActivity.this)
-                .setTitle(R.string.browserFrameFormResubmitLabel)
-                .setMessage(R.string.browserFrameFormResubmitMessage)
-                .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
-                    public void onClick(DialogInterface dialog, int which) {
-                        resend.sendToTarget();
-                    }})
-                .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
-                    public void onClick(DialogInterface dialog, int which) {
-                        dontResend.sendToTarget();
-                    }})
-                .setOnCancelListener(new OnCancelListener() {
-                    public void onCancel(DialogInterface dialog) {
-                        dontResend.sendToTarget();
-                    }})
-                .show();
-        }
-
-        /**
-         * Insert the url into the visited history database.
-         * @param url The url to be inserted.
-         * @param isReload True if this url is being reloaded.
-         * FIXME: Not sure what to do when reloading the page.
-         */
-        @Override
-        public void doUpdateVisitedHistory(WebView view, String url,
-                boolean isReload) {
-            if (url.regionMatches(true, 0, "about:", 0, 6)) {
-                return;
-            }
-            // remove "client" before updating it to the history so that it wont
-            // show up in the auto-complete list.
-            int index = url.indexOf("client=ms-");
-            if (index > 0 && url.contains(".google.")) {
-                int end = url.indexOf('&', index);
-                if (end > 0) {
-                    url = url.substring(0, index)
-                            .concat(url.substring(end + 1));
-                } else {
-                    // the url.charAt(index-1) should be either '?' or '&'
-                    url = url.substring(0, index-1);
-                }
-            }
-            Browser.updateVisitedHistory(mResolver, url, true);
-            WebIconDatabase.getInstance().retainIconForPageUrl(url);
-        }
-
-        /**
-         * Displays SSL error(s) dialog to the user.
-         */
-        @Override
-        public void onReceivedSslError(
-            final WebView view, final SslErrorHandler handler, final SslError error) {
-
-            if (mSettings.showSecurityWarnings()) {
-                final LayoutInflater factory =
-                    LayoutInflater.from(BrowserActivity.this);
-                final View warningsView =
-                    factory.inflate(R.layout.ssl_warnings, null);
-                final LinearLayout placeholder =
-                    (LinearLayout)warningsView.findViewById(R.id.placeholder);
-
-                if (error.hasError(SslError.SSL_UNTRUSTED)) {
-                    LinearLayout ll = (LinearLayout)factory
-                        .inflate(R.layout.ssl_warning, null);
-                    ((TextView)ll.findViewById(R.id.warning))
-                        .setText(R.string.ssl_untrusted);
-                    placeholder.addView(ll);
-                }
-
-                if (error.hasError(SslError.SSL_IDMISMATCH)) {
-                    LinearLayout ll = (LinearLayout)factory
-                        .inflate(R.layout.ssl_warning, null);
-                    ((TextView)ll.findViewById(R.id.warning))
-                        .setText(R.string.ssl_mismatch);
-                    placeholder.addView(ll);
-                }
-
-                if (error.hasError(SslError.SSL_EXPIRED)) {
-                    LinearLayout ll = (LinearLayout)factory
-                        .inflate(R.layout.ssl_warning, null);
-                    ((TextView)ll.findViewById(R.id.warning))
-                        .setText(R.string.ssl_expired);
-                    placeholder.addView(ll);
-                }
-
-                if (error.hasError(SslError.SSL_NOTYETVALID)) {
-                    LinearLayout ll = (LinearLayout)factory
-                        .inflate(R.layout.ssl_warning, null);
-                    ((TextView)ll.findViewById(R.id.warning))
-                        .setText(R.string.ssl_not_yet_valid);
-                    placeholder.addView(ll);
-                }
-
-                new AlertDialog.Builder(BrowserActivity.this)
-                    .setTitle(R.string.security_warning)
-                    .setIcon(android.R.drawable.ic_dialog_alert)
-                    .setView(warningsView)
-                    .setPositiveButton(R.string.ssl_continue,
-                            new DialogInterface.OnClickListener() {
-                                public void onClick(DialogInterface dialog, int whichButton) {
-                                    handler.proceed();
-                                }
-                            })
-                    .setNeutralButton(R.string.view_certificate,
-                            new DialogInterface.OnClickListener() {
-                                public void onClick(DialogInterface dialog, int whichButton) {
-                                    showSSLCertificateOnError(view, handler, error);
-                                }
-                            })
-                    .setNegativeButton(R.string.cancel,
-                            new DialogInterface.OnClickListener() {
-                                public void onClick(DialogInterface dialog, int whichButton) {
-                                    handler.cancel();
-                                    BrowserActivity.this.resetTitleAndRevertLockIcon();
-                                }
-                            })
-                    .setOnCancelListener(
-                            new DialogInterface.OnCancelListener() {
-                                public void onCancel(DialogInterface dialog) {
-                                    handler.cancel();
-                                    BrowserActivity.this.resetTitleAndRevertLockIcon();
-                                }
-                            })
-                    .show();
-            } else {
-                handler.proceed();
-            }
-        }
-
-        /**
-         * Handles an HTTP authentication request.
-         *
-         * @param handler The authentication handler
-         * @param host The host
-         * @param realm The realm
-         */
-        @Override
-        public void onReceivedHttpAuthRequest(WebView view,
-                final HttpAuthHandler handler, final String host, final String realm) {
-            String username = null;
-            String password = null;
-
-            boolean reuseHttpAuthUsernamePassword =
-                handler.useHttpAuthUsernamePassword();
-
-            if (reuseHttpAuthUsernamePassword &&
-                    (mTabControl.getCurrentWebView() != null)) {
-                String[] credentials =
-                        mTabControl.getCurrentWebView()
-                                .getHttpAuthUsernamePassword(host, realm);
-                if (credentials != null && credentials.length == 2) {
-                    username = credentials[0];
-                    password = credentials[1];
-                }
-            }
-
-            if (username != null && password != null) {
-                handler.proceed(username, password);
-            } else {
-                showHttpAuthentication(handler, host, realm, null, null, null, 0);
-            }
-        }
-
-        @Override
-        public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) {
-            if (mMenuIsDown) {
-                // only check shortcut key when MENU is held
-                return getWindow().isShortcutKey(event.getKeyCode(), event);
+        // check whether the intent can be resolved. If not, we will see
+        // whether we can download it from the Market.
+        if (getPackageManager().resolveActivity(intent, 0) == null) {
+            String packagename = intent.getPackage();
+            if (packagename != null) {
+                intent = new Intent(Intent.ACTION_VIEW, Uri
+                        .parse("market://search?q=pname:" + packagename));
+                intent.addCategory(Intent.CATEGORY_BROWSABLE);
+                startActivity(intent);
+                return true;
             } else {
                 return false;
             }
         }
 
-        @Override
-        public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
-            if (view != mTabControl.getCurrentTopWebView()) {
-                return;
-            }
-            if (event.isDown()) {
-                BrowserActivity.this.onKeyDown(event.getKeyCode(), event);
-            } else {
-                BrowserActivity.this.onKeyUp(event.getKeyCode(), event);
-            }
-        }
-    };
-
-    //--------------------------------------------------------------------------
-    // WebChromeClient implementation
-    //--------------------------------------------------------------------------
-
-    /* package */ WebChromeClient getWebChromeClient() {
-        return mWebChromeClient;
-    }
-
-    private final WebChromeClient mWebChromeClient = new WebChromeClient() {
-        // Helper method to create a new tab or sub window.
-        private void createWindow(final boolean dialog, final Message msg) {
-            if (dialog) {
-                mTabControl.createSubWindow();
-                final TabControl.Tab t = mTabControl.getCurrentTab();
-                attachSubWindow(t);
-                WebView.WebViewTransport transport =
-                        (WebView.WebViewTransport) msg.obj;
-                transport.setWebView(t.getSubWebView());
-                msg.sendToTarget();
-            } else {
-                final TabControl.Tab parent = mTabControl.getCurrentTab();
-                final TabControl.Tab newTab
-                        = openTabAndShow(EMPTY_URL_DATA, false, null);
-                if (newTab != parent) {
-                    parent.addChildTab(newTab);
-                }
-                WebView.WebViewTransport transport =
-                        (WebView.WebViewTransport) msg.obj;
-                transport.setWebView(mTabControl.getCurrentWebView());
-                msg.sendToTarget();
-            }
-        }
-
-        @Override
-        public boolean onCreateWindow(WebView view, final boolean dialog,
-                final boolean userGesture, final Message resultMsg) {
-            // Short-circuit if we can't create any more tabs or sub windows.
-            if (dialog && mTabControl.getCurrentSubWindow() != null) {
-                new AlertDialog.Builder(BrowserActivity.this)
-                        .setTitle(R.string.too_many_subwindows_dialog_title)
-                        .setIcon(android.R.drawable.ic_dialog_alert)
-                        .setMessage(R.string.too_many_subwindows_dialog_message)
-                        .setPositiveButton(R.string.ok, null)
-                        .show();
-                return false;
-            } else if (mTabControl.getTabCount() >= TabControl.MAX_TABS) {
-                new AlertDialog.Builder(BrowserActivity.this)
-                        .setTitle(R.string.too_many_windows_dialog_title)
-                        .setIcon(android.R.drawable.ic_dialog_alert)
-                        .setMessage(R.string.too_many_windows_dialog_message)
-                        .setPositiveButton(R.string.ok, null)
-                        .show();
-                return false;
-            }
-
-            // Short-circuit if this was a user gesture.
-            if (userGesture) {
-                createWindow(dialog, resultMsg);
+        // sanitize the Intent, ensuring web pages can not bypass browser
+        // security (only access to BROWSABLE activities).
+        intent.addCategory(Intent.CATEGORY_BROWSABLE);
+        intent.setComponent(null);
+        try {
+            if (startActivityIfNeeded(intent, -1)) {
                 return true;
             }
+        } catch (ActivityNotFoundException ex) {
+            // ignore the error. If no application can handle the URL,
+            // eg about:blank, assume the browser can handle it.
+        }
 
-            // Allow the popup and create the appropriate window.
-            final AlertDialog.OnClickListener allowListener =
-                    new AlertDialog.OnClickListener() {
-                        public void onClick(DialogInterface d,
-                                int which) {
-                            createWindow(dialog, resultMsg);
-                        }
-                    };
-
-            // Block the popup by returning a null WebView.
-            final AlertDialog.OnClickListener blockListener =
-                    new AlertDialog.OnClickListener() {
-                        public void onClick(DialogInterface d, int which) {
-                            resultMsg.sendToTarget();
-                        }
-                    };
-
-            // Build a confirmation dialog to display to the user.
-            final AlertDialog d =
-                    new AlertDialog.Builder(BrowserActivity.this)
-                    .setTitle(R.string.attention)
-                    .setIcon(android.R.drawable.ic_dialog_alert)
-                    .setMessage(R.string.popup_window_attempt)
-                    .setPositiveButton(R.string.allow, allowListener)
-                    .setNegativeButton(R.string.block, blockListener)
-                    .setCancelable(false)
-                    .create();
-
-            // Show the confirmation dialog.
-            d.show();
+        if (mMenuIsDown) {
+            openTab(url);
+            closeOptionsMenu();
             return true;
         }
+        return false;
+    }
 
-        @Override
-        public void onCloseWindow(WebView window) {
-            final TabControl.Tab current = mTabControl.getCurrentTab();
-            final TabControl.Tab parent = current.getParentTab();
-            if (parent != null) {
-                // JavaScript can only close popup window.
-                switchToTab(mTabControl.getTabIndex(parent));
-                // Now we need to close the window
-                closeTab(current);
-            }
-        }
+    // -------------------------------------------------------------------------
+    // Helper function for WebChromeClient
+    // -------------------------------------------------------------------------
 
-        @Override
-        public void onProgressChanged(WebView view, int newProgress) {
-            mTitleBar.setProgress(newProgress);
-            if (mFakeTitleBar != null) {
-                mFakeTitleBar.setProgress(newProgress);
-            }
+    void onProgressChanged(WebView view, int newProgress) {
+        mFakeTitleBar.setProgress(newProgress);
 
-            if (newProgress == 100) {
-                // onProgressChanged() may continue to be called after the main
-                // frame has finished loading, as any remaining sub frames
-                // continue to load. We'll only get called once though with
-                // newProgress as 100 when everything is loaded.
-                // (onPageFinished is called once when the main frame completes
-                // loading regardless of the state of any sub frames so calls
-                // to onProgressChanges may continue after onPageFinished has
-                // executed)
-
-                // sync cookies and cache promptly here.
-                CookieSyncManager.getInstance().sync();
-                if (mInLoad) {
-                    mInLoad = false;
-                    updateInLoadMenuItems();
-                    // If the options menu is open, leave the title bar
-                    if (!mOptionsMenuOpen || !mIconView) {
-                        hideFakeTitleBar();
-                    }
+        if (newProgress == 100) {
+            // onProgressChanged() may continue to be called after the main
+            // frame has finished loading, as any remaining sub frames continue
+            // to load. We'll only get called once though with newProgress as
+            // 100 when everything is loaded. (onPageFinished is called once
+            // when the main frame completes loading regardless of the state of
+            // any sub frames so calls to onProgressChanges may continue after
+            // onPageFinished has executed)
+            if (mInLoad) {
+                mInLoad = false;
+                updateInLoadMenuItems();
+                // If the options menu is open, leave the title bar
+                if (!mOptionsMenuOpen || !mIconView) {
+                    hideFakeTitleBar();
                 }
-            } else if (!mInLoad) {
-                // onPageFinished may have already been called but a subframe
-                // is still loading and updating the progress. Reset mInLoad
-                // and update the menu items.
+            }
+        } else {
+            if (!mInLoad) {
+                // onPageFinished may have already been called but a subframe is
+                // still loading and updating the progress. Reset mInLoad and
+                // update the menu items.
                 mInLoad = true;
                 updateInLoadMenuItems();
-                if (!mOptionsMenuOpen || mIconView) {
-                    // This page has begun to load, so show the title bar
-                    showFakeTitleBar();
-                }
+            }
+            // When the page first begins to load, the Activity may still be
+            // paused, in which case showFakeTitleBar will do nothing.  Call
+            // again as the page continues to load so that it will be shown.
+            // (Calling it will the fake title bar is already showing will also
+            // do nothing.
+            if (!mOptionsMenuOpen || mIconView) {
+                // This page has begun to load, so show the title bar
+                showFakeTitleBar();
             }
         }
+    }
 
-        @Override
-        public void onReceivedTitle(WebView view, String title) {
-            String url = view.getUrl();
-
-            // here, if url is null, we want to reset the title
-            setUrlTitle(url, title);
-
-            if (url == null ||
-                url.length() >= SQLiteDatabase.SQLITE_MAX_LIKE_PATTERN_LENGTH) {
-                return;
-            }
-            // See if we can find the current url in our history database and
-            // add the new title to it.
-            if (url.startsWith("http://www.")) {
-                url = url.substring(11);
-            } else if (url.startsWith("http://")) {
-                url = url.substring(4);
-            }
-            try {
-                url = "%" + url;
-                String [] selArgs = new String[] { url };
-
-                String where = Browser.BookmarkColumns.URL + " LIKE ? AND "
-                        + Browser.BookmarkColumns.BOOKMARK + " = 0";
-                Cursor c = mResolver.query(Browser.BOOKMARKS_URI,
-                    Browser.HISTORY_PROJECTION, where, selArgs, null);
-                if (c.moveToFirst()) {
-                    // Current implementation of database only has one entry per
-                    // url.
-                    ContentValues map = new ContentValues();
-                    map.put(Browser.BookmarkColumns.TITLE, title);
-                    mResolver.update(Browser.BOOKMARKS_URI, map,
-                            "_id = " + c.getInt(0), null);
-                }
-                c.close();
-            } catch (IllegalStateException e) {
-                Log.e(LOGTAG, "BrowserActivity onReceived title", e);
-            } catch (SQLiteException ex) {
-                Log.e(LOGTAG, "onReceivedTitle() caught SQLiteException: ", ex);
-            }
+    void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) {
+        // if a view already exists then immediately terminate the new one
+        if (mCustomView != null) {
+            callback.onCustomViewHidden();
+            return;
         }
 
-        @Override
-        public void onReceivedIcon(WebView view, Bitmap icon) {
-            updateIcon(view, icon);
+        // Add the custom view to its container.
+        mCustomViewContainer.addView(view, COVER_SCREEN_GRAVITY_CENTER);
+        mCustomView = view;
+        mCustomViewCallback = callback;
+        // Save the menu state and set it to empty while the custom
+        // view is showing.
+        mOldMenuState = mMenuState;
+        mMenuState = EMPTY_MENU;
+        // Hide the content view.
+        mContentView.setVisibility(View.GONE);
+        // Finally show the custom view container.
+        setStatusBarVisibility(false);
+        mCustomViewContainer.setVisibility(View.VISIBLE);
+        mCustomViewContainer.bringToFront();
+    }
+
+    void onHideCustomView() {
+        if (mCustomView == null)
+            return;
+
+        // Hide the custom view.
+        mCustomView.setVisibility(View.GONE);
+        // Remove the custom view from its container.
+        mCustomViewContainer.removeView(mCustomView);
+        mCustomView = null;
+        // Reset the old menu state.
+        mMenuState = mOldMenuState;
+        mOldMenuState = EMPTY_MENU;
+        mCustomViewContainer.setVisibility(View.GONE);
+        mCustomViewCallback.onCustomViewHidden();
+        // Show the content view.
+        setStatusBarVisibility(true);
+        mContentView.setVisibility(View.VISIBLE);
+    }
+
+    Bitmap getDefaultVideoPoster() {
+        if (mDefaultVideoPoster == null) {
+            mDefaultVideoPoster = BitmapFactory.decodeResource(
+                    getResources(), R.drawable.default_video_poster);
         }
+        return mDefaultVideoPoster;
+    }
 
-        @Override
-        public void onReceivedTouchIconUrl(WebView view, String url,
-                boolean precomposed) {
-            final ContentResolver cr = getContentResolver();
-            final Cursor c =
-                    BrowserBookmarksAdapter.queryBookmarksForUrl(cr,
-                            view.getOriginalUrl(), view.getUrl(), true);
-            if (c != null) {
-                if (c.getCount() > 0) {
-                    // Let precomposed icons take precedence over non-composed
-                    // icons.
-                    if (precomposed && mTouchIconLoader != null) {
-                        mTouchIconLoader.cancel(false);
-                        mTouchIconLoader = null;
-                    }
-                    // Have only one async task at a time.
-                    if (mTouchIconLoader == null) {
-                        mTouchIconLoader = new DownloadTouchIcon(
-                                BrowserActivity.this, cr, c, view);
-                        mTouchIconLoader.execute(url);
-                    }
-                } else {
-                    c.close();
-                }
-            }
+    View getVideoLoadingProgressView() {
+        if (mVideoProgressView == null) {
+            LayoutInflater inflater = LayoutInflater.from(BrowserActivity.this);
+            mVideoProgressView = inflater.inflate(
+                    R.layout.video_loading_progress, null);
         }
+        return mVideoProgressView;
+    }
 
-        @Override
-        public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) {
-            if (mCustomView != null)
-                return;
+    /*
+     * The Object used to inform the WebView of the file to upload.
+     */
+    private ValueCallback<Uri> mUploadMessage;
 
-            // Add the custom view to its container.
-            mCustomViewContainer.addView(view, COVER_SCREEN_GRAVITY_CENTER);
-            mCustomView = view;
-            mCustomViewCallback = callback;
-            // Save the menu state and set it to empty while the custom
-            // view is showing.
-            mOldMenuState = mMenuState;
-            mMenuState = EMPTY_MENU;
-            // Hide the content view.
-            mContentView.setVisibility(View.GONE);
-            // Finally show the custom view container.
-            mCustomViewContainer.setVisibility(View.VISIBLE);
-            mCustomViewContainer.bringToFront();
-        }
+    void openFileChooser(ValueCallback<Uri> uploadMsg) {
+        if (mUploadMessage != null) return;
+        mUploadMessage = uploadMsg;
+        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
+        i.addCategory(Intent.CATEGORY_OPENABLE);
+        i.setType("*/*");
+        BrowserActivity.this.startActivityForResult(Intent.createChooser(i,
+                getString(R.string.choose_upload)), FILE_SELECTED);
+    }
 
-        @Override
-        public void onHideCustomView() {
-            if (mCustomView == null)
-                return;
-
-            // Hide the custom view.
-            mCustomView.setVisibility(View.GONE);
-            // Remove the custom view from its container.
-            mCustomViewContainer.removeView(mCustomView);
-            mCustomView = null;
-            // Reset the old menu state.
-            mMenuState = mOldMenuState;
-            mOldMenuState = EMPTY_MENU;
-            mCustomViewContainer.setVisibility(View.GONE);
-            mCustomViewCallback.onCustomViewHidden();
-            // Show the content view.
-            mContentView.setVisibility(View.VISIBLE);
-        }
-
-        /**
-         * The origin has exceeded its database quota.
-         * @param url the URL that exceeded the quota
-         * @param databaseIdentifier the identifier of the database on
-         *     which the transaction that caused the quota overflow was run
-         * @param currentQuota the current quota for the origin.
-         * @param estimatedSize the estimated size of the database.
-         * @param totalUsedQuota is the sum of all origins' quota.
-         * @param quotaUpdater The callback to run when a decision to allow or
-         *     deny quota has been made. Don't forget to call this!
-         */
-        @Override
-        public void onExceededDatabaseQuota(String url,
-            String databaseIdentifier, long currentQuota, long estimatedSize,
-            long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) {
-            mSettings.getWebStorageSizeManager().onExceededDatabaseQuota(
-                    url, databaseIdentifier, currentQuota, estimatedSize,
-                    totalUsedQuota, quotaUpdater);
-        }
-
-        /**
-         * The Application Cache has exceeded its max size.
-         * @param spaceNeeded is the amount of disk space that would be needed
-         * in order for the last appcache operation to succeed.
-         * @param totalUsedQuota is the sum of all origins' quota.
-         * @param quotaUpdater A callback to inform the WebCore thread that a new
-         * app cache size is available. This callback must always be executed at
-         * some point to ensure that the sleeping WebCore thread is woken up.
-         */
-        @Override
-        public void onReachedMaxAppCacheSize(long spaceNeeded,
-                long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) {
-            mSettings.getWebStorageSizeManager().onReachedMaxAppCacheSize(
-                    spaceNeeded, totalUsedQuota, quotaUpdater);
-        }
-
-        /**
-         * Instructs the browser to show a prompt to ask the user to set the
-         * Geolocation permission state for the specified origin.
-         * @param origin The origin for which Geolocation permissions are
-         *     requested.
-         * @param callback The callback to call once the user has set the
-         *     Geolocation permission state.
-         */
-        @Override
-        public void onGeolocationPermissionsShowPrompt(String origin,
-                GeolocationPermissions.Callback callback) {
-            mTabControl.getCurrentTab().getGeolocationPermissionsPrompt().show(
-                    origin, callback);
-        }
-
-        /**
-         * Instructs the browser to hide the Geolocation permissions prompt.
-         */
-        @Override
-        public void onGeolocationPermissionsHidePrompt() {
-            mTabControl.getCurrentTab().getGeolocationPermissionsPrompt().hide();
-        }
-
-        /* Adds a JavaScript error message to the system log and if the JS
-         * console is enabled in the about:debug options, to that console
-         * also.
-         * @param message The error message to report.
-         * @param lineNumber The line number of the error.
-         * @param sourceID The name of the source file that caused the error.
-         */
-        @Override
-        public void onConsoleMessage(String message, int lineNumber, String sourceID) {
-            ErrorConsoleView errorConsole = mTabControl.getCurrentErrorConsole(true);
-            errorConsole.addErrorMessage(message, sourceID, lineNumber);
-                if (mShouldShowErrorConsole &&
-                        errorConsole.getShowState() != ErrorConsoleView.SHOW_MAXIMIZED) {
-                    errorConsole.showConsole(ErrorConsoleView.SHOW_MINIMIZED);
-                }
-            Log.w(LOGTAG, "Console: " + message + " " + sourceID + ":" + lineNumber);
-        }
-
-        /**
-         * Ask the browser for an icon to represent a <video> element.
-         * This icon will be used if the Web page did not specify a poster attribute.
-         *
-         * @return Bitmap The icon or null if no such icon is available.
-         * @hide pending API Council approval
-         */
-        @Override
-        public Bitmap getDefaultVideoPoster() {
-            if (mDefaultVideoPoster == null) {
-                mDefaultVideoPoster = BitmapFactory.decodeResource(
-                        getResources(), R.drawable.default_video_poster);
-            }
-            return mDefaultVideoPoster;
-        }
-
-        /**
-         * Ask the host application for a custom progress view to show while
-         * a <video> is loading.
-         *
-         * @return View The progress view.
-         * @hide pending API Council approval
-         */
-        @Override
-        public View getVideoLoadingProgressView() {
-            if (mVideoProgressView == null) {
-                LayoutInflater inflater = LayoutInflater.from(BrowserActivity.this);
-                mVideoProgressView = inflater.inflate(R.layout.video_loading_progress, null);
-            }
-            return mVideoProgressView;
-        }
-
-        /**
-         * Deliver a list of already-visited URLs
-         * @hide pending API Council approval
-         */
-        @Override
-        public void getVisitedHistory(final ValueCallback<String[]> callback) {
-            AsyncTask<Void, Void, String[]> task = new AsyncTask<Void, Void, String[]>() {
-                public String[] doInBackground(Void... unused) {
-                    return Browser.getVisitedHistory(getContentResolver());
-                }
-
-                public void onPostExecute(String[] result) {
-                    callback.onReceiveValue(result);
-
-                };
-            };
-            task.execute();
-        };
-    };
+    // -------------------------------------------------------------------------
+    // Implement functions for DownloadListener
+    // -------------------------------------------------------------------------
 
     /**
      * Notify the host application a download should be done, or that
@@ -3568,6 +2808,36 @@
         onDownloadStartNoStream(url, userAgent, contentDisposition, mimetype, contentLength);
     }
 
+    // This is to work around the fact that java.net.URI throws Exceptions
+    // instead of just encoding URL's properly
+    // Helper method for onDownloadStartNoStream
+    private static String encodePath(String path) {
+        char[] chars = path.toCharArray();
+
+        boolean needed = false;
+        for (char c : chars) {
+            if (c == '[' || c == ']') {
+                needed = true;
+                break;
+            }
+        }
+        if (needed == false) {
+            return path;
+        }
+
+        StringBuilder sb = new StringBuilder("");
+        for (char c : chars) {
+            if (c == '[' || c == ']') {
+                sb.append('%');
+                sb.append(Integer.toHexString(c));
+            } else {
+                sb.append(c);
+            }
+        }
+
+        return sb.toString();
+    }
+
     /**
      * Notify the host application a download should be done, even if there
      * is a streaming viewer available for thise type.
@@ -3607,35 +2877,16 @@
             return;
         }
 
-        // java.net.URI is a lot stricter than KURL so we have to undo
-        // KURL's percent-encoding and redo the encoding using java.net.URI.
-        URI uri = null;
+        // java.net.URI is a lot stricter than KURL so we have to encode some
+        // extra characters. Fix for b 2538060 and b 1634719
+        WebAddress webAddress;
         try {
-            // Undo the percent-encoding that KURL may have done.
-            String newUrl = new String(URLUtil.decode(url.getBytes()));
-            // Parse the url into pieces
-            WebAddress w = new WebAddress(newUrl);
-            String frag = null;
-            String query = null;
-            String path = w.mPath;
-            // Break the path into path, query, and fragment
-            if (path.length() > 0) {
-                // Strip the fragment
-                int idx = path.lastIndexOf('#');
-                if (idx != -1) {
-                    frag = path.substring(idx + 1);
-                    path = path.substring(0, idx);
-                }
-                idx = path.lastIndexOf('?');
-                if (idx != -1) {
-                    query = path.substring(idx + 1);
-                    path = path.substring(0, idx);
-                }
-            }
-            uri = new URI(w.mScheme, w.mAuthInfo, w.mHost, w.mPort, path,
-                    query, frag);
+            webAddress = new WebAddress(url);
+            webAddress.mPath = encodePath(webAddress.mPath);
         } catch (Exception e) {
-            Log.e(LOGTAG, "Could not parse url for download: " + url, e);
+            // This only happens for very bad urls, we want to chatch the
+            // exception here
+            Log.e(LOGTAG, "Exception trying to parse url:" + url);
             return;
         }
 
@@ -3644,19 +2895,20 @@
         String cookies = CookieManager.getInstance().getCookie(url);
 
         ContentValues values = new ContentValues();
-        values.put(Downloads.COLUMN_URI, uri.toString());
-        values.put(Downloads.COLUMN_COOKIE_DATA, cookies);
-        values.put(Downloads.COLUMN_USER_AGENT, userAgent);
-        values.put(Downloads.COLUMN_NOTIFICATION_PACKAGE,
+        values.put(Downloads.Impl.COLUMN_URI, webAddress.toString());
+        values.put(Downloads.Impl.COLUMN_COOKIE_DATA, cookies);
+        values.put(Downloads.Impl.COLUMN_USER_AGENT, userAgent);
+        values.put(Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE,
                 getPackageName());
-        values.put(Downloads.COLUMN_NOTIFICATION_CLASS,
-                BrowserDownloadPage.class.getCanonicalName());
-        values.put(Downloads.COLUMN_VISIBILITY, Downloads.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
-        values.put(Downloads.COLUMN_MIME_TYPE, mimetype);
-        values.put(Downloads.COLUMN_FILE_NAME_HINT, filename);
-        values.put(Downloads.COLUMN_DESCRIPTION, uri.getHost());
+        values.put(Downloads.Impl.COLUMN_NOTIFICATION_CLASS,
+                OpenDownloadReceiver.class.getCanonicalName());
+        values.put(Downloads.Impl.COLUMN_VISIBILITY,
+                Downloads.Impl.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
+        values.put(Downloads.Impl.COLUMN_MIME_TYPE, mimetype);
+        values.put(Downloads.Impl.COLUMN_FILE_NAME_HINT, filename);
+        values.put(Downloads.Impl.COLUMN_DESCRIPTION, webAddress.mHost);
         if (contentLength > 0) {
-            values.put(Downloads.COLUMN_TOTAL_BYTES, contentLength);
+            values.put(Downloads.Impl.COLUMN_TOTAL_BYTES, contentLength);
         }
         if (mimetype == null) {
             // We must have long pressed on a link or image to download it. We
@@ -3664,53 +2916,29 @@
             new FetchUrlMimeType(this).execute(values);
         } else {
             final Uri contentUri =
-                    getContentResolver().insert(Downloads.CONTENT_URI, values);
-            viewDownloads(contentUri);
+                    getContentResolver().insert(Downloads.Impl.CONTENT_URI, values);
         }
-
+        Toast.makeText(this, R.string.download_pending, Toast.LENGTH_SHORT)
+                .show();
     }
 
+    // -------------------------------------------------------------------------
+
     /**
      * Resets the lock icon. This method is called when we start a new load and
      * know the url to be loaded.
      */
     private void resetLockIcon(String url) {
         // Save the lock-icon state (we revert to it if the load gets cancelled)
-        saveLockIcon();
-
-        mLockIconType = LOCK_ICON_UNSECURE;
-        if (URLUtil.isHttpsUrl(url)) {
-            mLockIconType = LOCK_ICON_SECURE;
-            if (LOGV_ENABLED) {
-                Log.v(LOGTAG, "BrowserActivity.resetLockIcon:" +
-                      " reset lock icon to " + mLockIconType);
-            }
-        }
-
+        mTabControl.getCurrentTab().resetLockIcon(url);
         updateLockIconImage(LOCK_ICON_UNSECURE);
     }
 
-    /* package */ void setLockIconType(int type) {
-        mLockIconType = type;
-    }
-
-    /* package */ int getLockIconType() {
-        return mLockIconType;
-    }
-
-    /* package */ void setPrevLockType(int type) {
-        mPrevLockType = type;
-    }
-
-    /* package */ int getPrevLockType() {
-        return mPrevLockType;
-    }
-
     /**
      * Update the lock icon to correspond to our latest state.
      */
-    /* package */ void updateLockIconToLatest() {
-        updateLockIconImage(mLockIconType);
+    private void updateLockIconToLatest() {
+        updateLockIconImage(mTabControl.getCurrentTab().getLockIconType());
     }
 
     /**
@@ -3724,9 +2952,7 @@
             d = mMixLockIcon;
         }
         mTitleBar.setLock(d);
-        if (mFakeTitleBar != null) {
-            mFakeTitleBar.setLock(d);
-        }
+        mFakeTitleBar.setLock(d);
     }
 
     /**
@@ -3737,7 +2963,7 @@
      * not. This is important, since we need to know whether to return to
      * the parent dialog or simply dismiss.
      */
-    private void showPageInfo(final TabControl.Tab tab,
+    private void showPageInfo(final Tab tab,
                               final boolean fromShowSSLCertificateOnError) {
         final LayoutInflater factory = LayoutInflater
                 .from(this);
@@ -3772,7 +2998,7 @@
         ((TextView) pageInfoView.findViewById(R.id.title)).setText(title);
 
         mPageInfoView = tab;
-        mPageInfoFromShowSSLCertificateOnError = Boolean.valueOf(fromShowSSLCertificateOnError);
+        mPageInfoFromShowSSLCertificateOnError = fromShowSSLCertificateOnError;
 
         AlertDialog.Builder alertDialogBuilder =
             new AlertDialog.Builder(this)
@@ -3785,7 +3011,6 @@
                                         int whichButton) {
                         mPageInfoDialog = null;
                         mPageInfoView = null;
-                        mPageInfoFromShowSSLCertificateOnError = null;
 
                         // if we came here from the SSL error dialog
                         if (fromShowSSLCertificateOnError) {
@@ -3802,7 +3027,6 @@
                     public void onCancel(DialogInterface dialog) {
                         mPageInfoDialog = null;
                         mPageInfoView = null;
-                        mPageInfoFromShowSSLCertificateOnError = null;
 
                         // if we came here from the SSL error dialog
                         if (fromShowSSLCertificateOnError) {
@@ -3827,7 +3051,6 @@
                                         int whichButton) {
                         mPageInfoDialog = null;
                         mPageInfoView = null;
-                        mPageInfoFromShowSSLCertificateOnError = null;
 
                         // if we came here from the SSL error dialog
                         if (fromShowSSLCertificateOnError) {
@@ -3855,7 +3078,7 @@
      * (accessible from the Page-Info dialog).
      * @param tab The tab to show certificate for.
      */
-    private void showSSLCertificate(final TabControl.Tab tab) {
+    private void showSSLCertificate(final Tab tab) {
         final View certificateView =
                 inflateCertificateView(tab.getWebView().getCertificate());
         if (certificateView == null) {
@@ -3907,7 +3130,7 @@
      * connection that resulted in an SSL error or proceeding per user request.
      * @param error The SSL error object.
      */
-    private void showSSLCertificateOnError(
+    void showSSLCertificateOnError(
         final WebView view, final SslErrorHandler handler, final SslError error) {
 
         final View certificateView =
@@ -3966,8 +3189,8 @@
                                 mSSLCertificateOnErrorHandler = null;
                                 mSSLCertificateOnErrorError = null;
 
-                                mWebViewClient.onReceivedSslError(
-                                    view, handler, error);
+                                view.getWebViewClient().onReceivedSslError(
+                                                view, handler, error);
                             }
                         })
                  .setNeutralButton(R.string.page_info_view,
@@ -3992,8 +3215,8 @@
                                 mSSLCertificateOnErrorHandler = null;
                                 mSSLCertificateOnErrorError = null;
 
-                                mWebViewClient.onReceivedSslError(
-                                    view, handler, error);
+                                view.getWebViewClient().onReceivedSslError(
+                                                view, handler, error);
                             }
                         })
                 .show();
@@ -4039,14 +3262,14 @@
         }
 
         // issued on:
-        String issuedOn = reformatCertificateDate(
-            certificate.getValidNotBefore());
+        String issuedOn = formatCertificateDate(
+            certificate.getValidNotBeforeDate());
         ((TextView) certificateView.findViewById(R.id.issued_on))
             .setText(issuedOn);
 
         // expires on:
-        String expiresOn = reformatCertificateDate(
-            certificate.getValidNotAfter());
+        String expiresOn = formatCertificateDate(
+            certificate.getValidNotAfterDate());
         ((TextView) certificateView.findViewById(R.id.expires_on))
             .setText(expiresOn);
 
@@ -4054,37 +3277,25 @@
     }
 
     /**
-     * Re-formats the certificate date (Date.toString()) string to
-     * a properly localized date string.
+     * Formats the certificate date to a properly localized date string.
      * @return Properly localized version of the certificate date string and
-     * the original certificate date string if fails to localize.
-     * If the original string is null, returns an empty string "".
+     * the "" if it fails to localize.
      */
-    private String reformatCertificateDate(String certificateDate) {
-      String reformattedDate = null;
-
-      if (certificateDate != null) {
-          Date date = null;
-          try {
-              date = java.text.DateFormat.getInstance().parse(certificateDate);
-          } catch (ParseException e) {
-              date = null;
-          }
-
-          if (date != null) {
-              reformattedDate =
-                  DateFormat.getDateFormat(this).format(date);
-          }
+    private String formatCertificateDate(Date certificateDate) {
+      if (certificateDate == null) {
+          return "";
       }
-
-      return reformattedDate != null ? reformattedDate :
-          (certificateDate != null ? certificateDate : "");
+      String formattedDate = DateFormat.getDateFormat(this).format(certificateDate);
+      if (formattedDate == null) {
+          return "";
+      }
+      return formattedDate;
     }
 
     /**
      * Displays an http-authentication dialog.
      */
-    private void showHttpAuthentication(final HttpAuthHandler handler,
+    void showHttpAuthentication(final HttpAuthHandler handler,
             final String host, final String realm, final String title,
             final String name, final String password, int focusId) {
         LayoutInflater factory = LayoutInflater.from(this);
@@ -4174,7 +3385,7 @@
     public void setHttpAuthUsernamePassword(String host, String realm,
                                             String username,
                                             String password) {
-        WebView w = mTabControl.getCurrentWebView();
+        WebView w = getTopWindow();
         if (w != null) {
             w.setHttpAuthUsernamePassword(host, realm, username, password);
         }
@@ -4205,6 +3416,10 @@
         }
     }
 
+    boolean isNetworkUp() {
+        return mIsNetworkUp;
+    }
+
     // This method shows the network dialog alerting the user that the net is
     // down. It will only show the dialog if mAlertDialog is null.
     private void createAndShowNetworkDialog() {
@@ -4220,6 +3435,8 @@
     @Override
     protected void onActivityResult(int requestCode, int resultCode,
                                     Intent intent) {
+        if (getTopWindow() == null) return;
+
         switch (requestCode) {
             case COMBO_PAGE:
                 if (resultCode == RESULT_OK && intent != null) {
@@ -4228,14 +3445,31 @@
                     if (extras != null && extras.getBoolean("new_window", false)) {
                         openTab(data);
                     } else {
-                        final TabControl.Tab currentTab =
+                        final Tab currentTab =
                                 mTabControl.getCurrentTab();
                         dismissSubWindow(currentTab);
                         if (data != null && data.length() != 0) {
-                            getTopWindow().loadUrl(data);
+                            loadUrl(getTopWindow(), data);
                         }
                     }
                 }
+                // Deliberately fall through to PREFERENCES_PAGE, since the
+                // same extra may be attached to the COMBO_PAGE
+            case PREFERENCES_PAGE:
+                if (resultCode == RESULT_OK && intent != null) {
+                    String action = intent.getStringExtra(Intent.EXTRA_TEXT);
+                    if (BrowserSettings.PREF_CLEAR_HISTORY.equals(action)) {
+                        mTabControl.removeParentChildRelationShips();
+                    }
+                }
+                break;
+            // Choose a file from the file picker.
+            case FILE_SELECTED:
+                if (null == mUploadMessage) break;
+                Uri result = intent == null || resultCode != RESULT_OK ? null
+                        : intent.getData();
+                mUploadMessage.onReceiveValue(result);
+                mUploadMessage = null;
                 break;
             default:
                 break;
@@ -4245,14 +3479,14 @@
 
     /*
      * This method is called as a result of the user selecting the options
-     * menu to see the download window, or when a download changes state. It
-     * shows the download window ontop of the current window.
+     * menu to see the download window. It shows the download window on top of
+     * the current window.
      */
-    /* package */ void viewDownloads(Uri downloadRecord) {
+    private void viewDownloads(Uri downloadRecord) {
         Intent intent = new Intent(this,
                 BrowserDownloadPage.class);
         intent.setData(downloadRecord);
-        startActivityForResult(intent, this.DOWNLOAD_PAGE);
+        startActivityForResult(intent, BrowserActivity.DOWNLOAD_PAGE);
 
     }
 
@@ -4289,8 +3523,7 @@
         intent.putExtra("url", url);
         intent.putExtra("thumbnail", thumbnail);
         // Disable opening in a new window if we have maxed out the windows
-        intent.putExtra("disable_new_window", mTabControl.getTabCount()
-                >= TabControl.MAX_TABS);
+        intent.putExtra("disable_new_window", !mTabControl.canCreateNewTab());
         intent.putExtra("touch_icon_url", current.getTouchIconUrl());
         if (startWithHistory) {
             intent.putExtra(CombinedBookmarkHistoryActivity.STARTING_TAB,
@@ -4300,16 +3533,56 @@
     }
 
     // Called when loading from context menu or LOAD_URL message
-    private void loadURL(WebView view, String url) {
+    private void loadUrlFromContext(WebView view, String url) {
         // In case the user enters nothing.
         if (url != null && url.length() != 0 && view != null) {
             url = smartUrlFilter(url);
-            if (!mWebViewClient.shouldOverrideUrlLoading(view, url)) {
-                view.loadUrl(url);
+            if (!view.getWebViewClient().shouldOverrideUrlLoading(view, url)) {
+                loadUrl(view, url);
             }
         }
     }
 
+    /**
+     * Load the URL into the given WebView and update the title bar
+     * to reflect the new load.  Call this instead of WebView.loadUrl
+     * directly.
+     * @param view The WebView used to load url.
+     * @param url The URL to load.
+     */
+    private void loadUrl(WebView view, String url) {
+        updateTitleBarForNewLoad(view, url);
+        view.loadUrl(url);
+    }
+
+    /**
+     * Load UrlData into a Tab and update the title bar to reflect the new
+     * load.  Call this instead of UrlData.loadIn directly.
+     * @param t The Tab used to load.
+     * @param data The UrlData being loaded.
+     */
+    private void loadUrlDataIn(Tab t, UrlData data) {
+        updateTitleBarForNewLoad(t.getWebView(), data.mUrl);
+        data.loadIn(t);
+    }
+
+    /**
+     * If the WebView is the top window, update the title bar to reflect
+     * loading the new URL.  i.e. set its text, clear the favicon (which
+     * will be set once the page begins loading), and set the progress to
+     * INITIAL_PROGRESS to show that the page has begun to load. Called
+     * by loadUrl and loadUrlDataIn.
+     * @param view The WebView that is starting a load.
+     * @param url The URL that is being loaded.
+     */
+    private void updateTitleBarForNewLoad(WebView view, String url) {
+        if (view == getTopWindow()) {
+            setUrlTitle(url, null);
+            setFavicon(null);
+            onProgressChanged(view, INITIAL_PROGRESS);
+        }
+    }
+
     private String smartUrlFilter(Uri inUri) {
         if (inUri != null) {
             return smartUrlFilter(inUri.toString());
@@ -4317,16 +3590,6 @@
         return null;
     }
 
-
-    // get window count
-
-    int getWindowCount(){
-      if(mTabControl != null){
-        return mTabControl.getTabCount();
-      }
-      return 0;
-    }
-
     protected static final Pattern ACCEPTED_URI_SCHEMA = Pattern.compile(
             "(?i)" + // switch on case insensitive matching
             "(" +    // begin group for schema
@@ -4383,7 +3646,7 @@
                 }
             }
         } else {
-            if (Regex.WEB_URL_PATTERN.matcher(inUrl).matches()) {
+            if (Patterns.WEB_URL.matcher(inUrl).matches()) {
                 return URLUtil.guessUrl(inUrl);
             }
         }
@@ -4400,7 +3663,8 @@
 
         mShouldShowErrorConsole = flag;
 
-        ErrorConsoleView errorConsole = mTabControl.getCurrentErrorConsole(true);
+        ErrorConsoleView errorConsole = mTabControl.getCurrentTab()
+                .getErrorConsole(true);
 
         if (flag) {
             // Setting the show state of the console will cause it's the layout to be inflated.
@@ -4412,7 +3676,7 @@
 
             // Now we can add it to the main view.
             mErrorConsoleContainer.addView(errorConsole,
-                    new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
+                    new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                                                   ViewGroup.LayoutParams.WRAP_CONTENT));
         } else {
             mErrorConsoleContainer.removeView(errorConsole);
@@ -4420,13 +3684,75 @@
 
     }
 
+    boolean shouldShowErrorConsole() {
+        return mShouldShowErrorConsole;
+    }
+
+    private void setStatusBarVisibility(boolean visible) {
+        int flag = visible ? 0 : WindowManager.LayoutParams.FLAG_FULLSCREEN;
+        getWindow().setFlags(flag, WindowManager.LayoutParams.FLAG_FULLSCREEN);
+    }
+
+
+    private void sendNetworkType(String type, String subtype) {
+        WebView w = mTabControl.getCurrentWebView();
+        if (w != null) {
+            w.setNetworkType(type, subtype);
+        }
+    }
+
+    private void packageChanged(String packageName, boolean wasAdded) {
+        WebView w = mTabControl.getCurrentWebView();
+        if (w == null) {
+            return;
+        }
+
+        if (wasAdded) {
+            w.addPackageName(packageName);
+        } else {
+            w.removePackageName(packageName);
+        }
+    }
+
+    private void addPackageNames(Set<String> packageNames) {
+        WebView w = mTabControl.getCurrentWebView();
+        if (w == null) {
+            return;
+        }
+
+        w.addPackageNames(packageNames);
+    }
+
+    private void getInstalledPackages() {
+        AsyncTask<Void, Void, Set<String> > task =
+            new AsyncTask<Void, Void, Set<String> >() {
+            protected Set<String> doInBackground(Void... unused) {
+                Set<String> installedPackages = new HashSet<String>();
+                PackageManager pm = BrowserActivity.this.getPackageManager();
+                if (pm != null) {
+                    List<PackageInfo> packages = pm.getInstalledPackages(0);
+                    for (PackageInfo p : packages) {
+                        if (BrowserActivity.this.sGoogleApps.contains(p.packageName)) {
+                            installedPackages.add(p.packageName);
+                        }
+                    }
+                }
+
+                return installedPackages;
+            }
+
+            // Executes on the UI thread
+            protected void onPostExecute(Set<String> installedPackages) {
+                addPackageNames(installedPackages);
+            }
+        };
+        task.execute();
+    }
+
     final static int LOCK_ICON_UNSECURE = 0;
     final static int LOCK_ICON_SECURE   = 1;
     final static int LOCK_ICON_MIXED    = 2;
 
-    private int mLockIconType = LOCK_ICON_UNSECURE;
-    private int mPrevLockType = LOCK_ICON_UNSECURE;
-
     private BrowserSettings mSettings;
     private TabControl      mTabControl;
     private ContentResolver mResolver;
@@ -4452,8 +3778,7 @@
     private boolean mIsNetworkUp;
     private boolean mDidStopLoad;
 
-    private boolean mPageStarted;
-    private boolean mActivityInPause = true;
+    /* package */ boolean mActivityInPause = true;
 
     private boolean mMenuIsDown;
 
@@ -4486,9 +3811,6 @@
     /* hold a ref so we can auto-cancel if necessary */
     private AlertDialog mAlertDialog;
 
-    // Wait for credentials before loading google.com
-    private ProgressDialog mCredsDlg;
-
     // The up-to-date URL and title (these can be different from those stored
     // in WebView, since it takes some time for the information in WebView to
     // get updated)
@@ -4498,11 +3820,11 @@
     // As PageInfo has different style for landscape / portrait, we have
     // to re-open it when configuration changed
     private AlertDialog mPageInfoDialog;
-    private TabControl.Tab mPageInfoView;
+    private Tab mPageInfoView;
     // If the Page-Info dialog is launched from the SSL-certificate-on-error
     // dialog, we should not just dismiss it, but should get back to the
     // SSL-certificate-on-error dialog. This flag is used to store this state
-    private Boolean mPageInfoFromShowSSLCertificateOnError;
+    private boolean mPageInfoFromShowSSLCertificateOnError;
 
     // as SSLCertificateOnError has different style for landscape / portrait,
     // we have to re-open it when configuration changed
@@ -4514,7 +3836,7 @@
     // as SSLCertificate has different style for landscape / portrait, we
     // have to re-open it when configuration changed
     private AlertDialog mSSLCertificateDialog;
-    private TabControl.Tab mSSLCertificateView;
+    private Tab mSSLCertificateView;
 
     // as HttpAuthentication has different style for landscape / portrait, we
     // have to re-open it when configuration changed
@@ -4523,12 +3845,12 @@
 
     /*package*/ static final FrameLayout.LayoutParams COVER_SCREEN_PARAMS =
                                             new FrameLayout.LayoutParams(
-                                            ViewGroup.LayoutParams.FILL_PARENT,
-                                            ViewGroup.LayoutParams.FILL_PARENT);
+                                            ViewGroup.LayoutParams.MATCH_PARENT,
+                                            ViewGroup.LayoutParams.MATCH_PARENT);
     /*package*/ static final FrameLayout.LayoutParams COVER_SCREEN_GRAVITY_CENTER =
                                             new FrameLayout.LayoutParams(
-                                            ViewGroup.LayoutParams.FILL_PARENT,
-                                            ViewGroup.LayoutParams.FILL_PARENT,
+                                            ViewGroup.LayoutParams.MATCH_PARENT,
+                                            ViewGroup.LayoutParams.MATCH_PARENT,
                                             Gravity.CENTER);
     // Google search
     final static String QuickSearch_G = "http://www.google.com/m?q=%s";
@@ -4579,72 +3901,69 @@
 
     private BroadcastReceiver mPackageInstallationReceiver;
 
-    // AsyncTask for downloading touch icons
-    /* package */ DownloadTouchIcon mTouchIconLoader;
+    private SystemAllowGeolocationOrigins mSystemAllowGeolocationOrigins;
 
     // 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;
 
     // the default <video> poster
     private Bitmap mDefaultVideoPoster;
     // the video progress view
     private View mVideoProgressView;
 
+    // The Google packages we monitor for the navigator.isApplicationInstalled()
+    // API. Add as needed.
+    private static Set<String> sGoogleApps;
+    static {
+        sGoogleApps = new HashSet<String>();
+        sGoogleApps.add("com.google.android.youtube");
+    }
+
     /**
      * A UrlData class to abstract how the content will be set to WebView.
      * This base class uses loadUrl to show the content.
      */
-    private static class UrlData {
-        String mUrl;
-        byte[] mPostData;
+    /* package */ static class UrlData {
+        final String mUrl;
+        final Map<String, String> mHeaders;
+        final Intent mVoiceIntent;
 
         UrlData(String url) {
             this.mUrl = url;
+            this.mHeaders = null;
+            this.mVoiceIntent = null;
         }
 
-        void setPostData(byte[] postData) {
-            mPostData = postData;
+        UrlData(String url, Map<String, String> headers, Intent intent) {
+            this.mUrl = url;
+            this.mHeaders = headers;
+            if (RecognizerResultsIntent.ACTION_VOICE_SEARCH_RESULTS
+                    .equals(intent.getAction())) {
+                this.mVoiceIntent = intent;
+            } else {
+                this.mVoiceIntent = null;
+            }
         }
 
         boolean isEmpty() {
-            return mUrl == null || mUrl.length() == 0;
+            return mVoiceIntent == null && (mUrl == null || mUrl.length() == 0);
         }
 
-        public void loadIn(WebView webView) {
-            if (mPostData != null) {
-                webView.postUrl(mUrl, mPostData);
+        /**
+         * Load this UrlData into the given Tab.  Use loadUrlDataIn to update
+         * the title bar as well.
+         */
+        public void loadIn(Tab t) {
+            if (mVoiceIntent != null) {
+                t.activateVoiceSearchMode(mVoiceIntent);
             } else {
-                webView.loadUrl(mUrl);
+                t.getWebView().loadUrl(mUrl, mHeaders);
             }
         }
     };
 
-    /**
-     * A subclass of UrlData class that can display inlined content using
-     * {@link WebView#loadDataWithBaseURL(String, String, String, String, String)}.
-     */
-    private static class InlinedUrlData extends UrlData {
-        InlinedUrlData(String inlined, String mimeType, String encoding, String failUrl) {
-            super(failUrl);
-            mInlined = inlined;
-            mMimeType = mimeType;
-            mEncoding = encoding;
-        }
-        String mMimeType;
-        String mInlined;
-        String mEncoding;
-        @Override
-        boolean isEmpty() {
-            return mInlined == null || mInlined.length() == 0 || super.isEmpty();
-        }
-
-        @Override
-        public void loadIn(WebView webView) {
-            webView.loadDataWithBaseURL(null, mInlined, mMimeType, mEncoding, mUrl);
-        }
-    }
-
     /* package */ static final UrlData EMPTY_URL_DATA = new UrlData(null);
 }
diff --git a/src/com/android/browser/BrowserBackupAgent.java b/src/com/android/browser/BrowserBackupAgent.java
index 84672b1..c968ce5 100644
--- a/src/com/android/browser/BrowserBackupAgent.java
+++ b/src/com/android/browser/BrowserBackupAgent.java
@@ -18,9 +18,9 @@
 
 import java.io.IOException;
 
-import android.app.BackupAgent;
-import android.backup.BackupDataInput;
-import android.backup.BackupDataOutput;
+import android.app.backup.BackupAgent;
+import android.app.backup.BackupDataInput;
+import android.app.backup.BackupDataOutput;
 import android.database.Cursor;
 import android.os.ParcelFileDescriptor;
 import android.provider.Browser;
diff --git a/src/com/android/browser/BrowserBookmarksAdapter.java b/src/com/android/browser/BrowserBookmarksAdapter.java
index dd56d2f..241b33b 100644
--- a/src/com/android/browser/BrowserBookmarksAdapter.java
+++ b/src/com/android/browser/BrowserBookmarksAdapter.java
@@ -25,8 +25,10 @@
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.net.Uri;
+import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.Looper;
 import android.provider.Browser;
 import android.provider.Browser.BookmarkColumns;
 import android.view.KeyEvent;
@@ -34,7 +36,6 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.webkit.WebIconDatabase;
-import android.webkit.WebIconDatabase.IconListener;
 import android.webkit.WebView;
 import android.widget.BaseAdapter;
 import android.widget.ImageView;
@@ -57,16 +58,6 @@
     private boolean                 mNeedsOffset;
     private int                     mExtraOffset;
 
-    // Implementation of WebIconDatabase.IconListener
-    private class IconReceiver implements IconListener {
-        public void onReceivedIcon(String url, Bitmap icon) {
-            updateBookmarkFavicon(mContentResolver, null, url, icon);
-        }
-    }
-
-    // Instance of IconReceiver
-    private final IconReceiver mIconReceiver = new IconReceiver();
-
     /**
      *  Create a new BrowserBookmarksAdapter.
      *  @param b        BrowserBookmarksPage that instantiated this.
@@ -93,7 +84,7 @@
         if (mostVisited) {
             whereClause = Browser.BookmarkColumns.VISITS + " != 0";
         } else {
-            whereClause = Browser.BookmarkColumns.BOOKMARK + " != 0";
+            whereClause = Browser.BookmarkColumns.BOOKMARK + " = 1";
         }
         mCursor = b.managedQuery(Browser.BOOKMARKS_URI,
                 Browser.HISTORY_PROJECTION, whereClause, null, orderBy);
@@ -104,12 +95,6 @@
         notifyDataSetChanged();
 
         mCount = mCursor.getCount() + mExtraOffset;
-
-        // FIXME: This requires another query of the database after the
-        // managedQuery. Can we optimize this?
-        Browser.requestAllIcons(mContentResolver,
-                Browser.BookmarkColumns.FAVICON + " is NULL AND " +
-                Browser.BookmarkColumns.BOOKMARK + " == 1", mIconReceiver);
     }
     
     /**
@@ -267,26 +252,32 @@
      * @param url The current url.
      * @param favicon The favicon bitmap to write to the db.
      */
-    /* package */ static void updateBookmarkFavicon(ContentResolver cr,
-            String originalUrl, String url, Bitmap favicon) {
-        final Cursor c = queryBookmarksForUrl(cr, originalUrl, url, true);
-        if (c == null) {
-            return;
-        }
-        boolean succeed = c.moveToFirst();
-        ContentValues values = null;
-        while (succeed) {
-            if (values == null) {
-                final ByteArrayOutputStream os = new ByteArrayOutputStream();
-                favicon.compress(Bitmap.CompressFormat.PNG, 100, os);
-                values = new ContentValues();
-                values.put(Browser.BookmarkColumns.FAVICON, os.toByteArray());
+    /* package */ static void updateBookmarkFavicon(final ContentResolver cr,
+            final String originalUrl, final String url, final Bitmap favicon) {
+        new AsyncTask<Void, Void, Void>() {
+            protected Void doInBackground(Void... unused) {
+                final Cursor c =
+                        queryBookmarksForUrl(cr, originalUrl, url, true);
+                if (c == null) {
+                    return null;
+                }
+                if (c.moveToFirst()) {
+                    ContentValues values = new ContentValues();
+                    final ByteArrayOutputStream os =
+                            new ByteArrayOutputStream();
+                    favicon.compress(Bitmap.CompressFormat.PNG, 100, os);
+                    values.put(Browser.BookmarkColumns.FAVICON,
+                            os.toByteArray());
+                    do {
+                        cr.update(ContentUris.withAppendedId(
+                                Browser.BOOKMARKS_URI, c.getInt(0)),
+                                values, null, null);
+                    } while (c.moveToNext());
+                }
+                c.close();
+                return null;
             }
-            cr.update(ContentUris.withAppendedId(Browser.BOOKMARKS_URI, c
-                    .getInt(0)), values, null, null);
-            succeed = c.moveToNext();
-        }
-        c.close();
+        }.execute();
     }
 
     /* package */ static Cursor queryBookmarksForUrl(ContentResolver cr,
@@ -316,8 +307,8 @@
             originalUrlNoQuery, urlNoQuery, originalUrl, url };
         String where = BookmarkColumns.URL + " == ? OR "
                 + BookmarkColumns.URL + " == ? OR "
-                + BookmarkColumns.URL + " GLOB ? || '*' OR "
-                + BookmarkColumns.URL + " GLOB ? || '*'";
+                + BookmarkColumns.URL + " LIKE ? || '%' OR "
+                + BookmarkColumns.URL + " LIKE ? || '%'";
         if (onlyBookmarks) {
             where = "(" + where + ") AND " + BookmarkColumns.BOOKMARK + " == 1";
         }
@@ -441,7 +432,7 @@
             mCursor.moveToPosition(position - mExtraOffset);
             tv.setText(mCursor.getString(
                     Browser.HISTORY_PROJECTION_TITLE_INDEX));
-            Bitmap thumbnail = getBitmap(Browser.HISTORY_PROJECTION_THUMBNAIL_INDEX, position);
+            Bitmap thumbnail = getScreenshot(position);
             if (thumbnail == null) {
                 thumb.setImageResource(R.drawable.browser_thumbnail);
             } else {
@@ -493,6 +484,13 @@
     }
 
     /**
+     * Return the screenshot for this item in the list.
+     */
+    public Bitmap getScreenshot(int position) {
+        return getBitmap(Browser.HISTORY_PROJECTION_THUMBNAIL_INDEX, position);
+    }
+
+    /**
      * Return the favicon for this item in the list.
      */
     public Bitmap getFavicon(int position) {
@@ -540,15 +538,8 @@
     private void bind(BookmarkItem b, int position) {
         mCursor.moveToPosition(position- mExtraOffset);
 
-        String title = mCursor.getString(Browser.HISTORY_PROJECTION_TITLE_INDEX);
-        if (title.length() > BrowserSettings.MAX_TEXTVIEW_LEN) {
-            title = title.substring(0, BrowserSettings.MAX_TEXTVIEW_LEN);
-        }
-        b.setName(title);
+        b.setName(mCursor.getString(Browser.HISTORY_PROJECTION_TITLE_INDEX));
         String url = mCursor.getString(Browser.HISTORY_PROJECTION_URL_INDEX);
-        if (url.length() > BrowserSettings.MAX_TEXTVIEW_LEN) {
-            url = url.substring(0, BrowserSettings.MAX_TEXTVIEW_LEN);
-        }
         b.setUrl(url);
         byte[] data = mCursor.getBlob(Browser.HISTORY_PROJECTION_FAVICON_INDEX);
         if (data != null) {
@@ -561,7 +552,7 @@
 
     private class ChangeObserver extends ContentObserver {
         public ChangeObserver() {
-            super(new Handler());
+            super(new Handler(Looper.getMainLooper()));
         }
 
         @Override
diff --git a/src/com/android/browser/BrowserBookmarksPage.java b/src/com/android/browser/BrowserBookmarksPage.java
index 6ab011b..7560c78 100644
--- a/src/com/android/browser/BrowserBookmarksPage.java
+++ b/src/com/android/browser/BrowserBookmarksPage.java
@@ -30,8 +30,10 @@
 import android.graphics.Path;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
 import android.graphics.RectF;
 import android.net.Uri;
+import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
@@ -40,16 +42,13 @@
 import android.text.IClipboard;
 import android.util.Log;
 import android.view.ContextMenu;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
-import android.view.ViewStub;
 import android.view.ContextMenu.ContextMenuInfo;
+import android.webkit.WebIconDatabase.IconListener;
 import android.widget.AdapterView;
 import android.widget.GridView;
 import android.widget.ListView;
@@ -59,12 +58,12 @@
 /**
  *  View showing the user's bookmarks in the browser.
  */
-public class BrowserBookmarksPage extends Activity implements 
+public class BrowserBookmarksPage extends Activity implements
         View.OnCreateContextMenuListener {
 
     private BookmarkViewMode        mViewMode = BookmarkViewMode.NONE;
     private GridView                mGridPage;
-    private View                    mVerticalList;
+    private ListView                mVerticalList;
     private BrowserBookmarksAdapter mBookmarksAdapter;
     private static final int        BOOKMARKS_SAVE = 1;
     private boolean                 mDisableNewWindow;
@@ -74,11 +73,12 @@
     private boolean                 mCreateShortcut;
     private boolean                 mMostVisited;
     private View                    mEmptyView;
+    private int                     mIconSize;
     // XXX: There is no public string defining this intent so if Home changes
     // the value, we have to update this string.
     private static final String     INSTALL_SHORTCUT =
             "com.android.launcher.action.INSTALL_SHORTCUT";
-    
+
     private final static String LOGTAG = "browser";
     private final static String PREF_BOOKMARK_VIEW_MODE = "pref_bookmark_view_mode";
     private final static String PREF_MOST_VISITED_VIEW_MODE = "pref_most_visited_view_mode";
@@ -86,17 +86,17 @@
     @Override
     public boolean onContextItemSelected(MenuItem item) {
         // It is possible that the view has been canceled when we get to
-        // this point as back has a higher priority 
+        // this point as back has a higher priority
         if (mCanceled) {
             return true;
         }
-        AdapterView.AdapterContextMenuInfo i = 
+        AdapterView.AdapterContextMenuInfo i =
             (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
         // If we have no menu info, we can't tell which item was selected.
         if (i == null) {
             return true;
         }
-        
+
         switch (item.getItemId()) {
         case R.id.new_context_menu_id:
             saveCurrentPage();
@@ -125,8 +125,10 @@
             openInNewWindow(i.position);
             break;
         case R.id.share_link_context_menu_id:
-            Browser.sendString(BrowserBookmarksPage.this, getUrl(i.position),
-                    getText(R.string.choosertitle_sharevia).toString());
+            BrowserActivity.sharePage(BrowserBookmarksPage.this,
+                    mBookmarksAdapter.getTitle(i.position), getUrl(i.position),
+                    getFavicon(i.position),
+                    mBookmarksAdapter.getScreenshot(i.position));
             break;
         case R.id.copy_url_context_menu_id:
             copy(getUrl(i.position));
@@ -169,7 +171,7 @@
     @Override
     public void onCreateContextMenu(ContextMenu menu, View v,
                 ContextMenuInfo menuInfo) {
-            AdapterView.AdapterContextMenuInfo i = 
+            AdapterView.AdapterContextMenuInfo i =
                     (AdapterView.AdapterContextMenuInfo) menuInfo;
 
             MenuInflater inflater = getMenuInflater();
@@ -225,27 +227,26 @@
 
     /**
      *  Create a new BrowserBookmarksPage.
-     */  
+     */
     @Override
     protected void onCreate(Bundle icicle) {
         super.onCreate(icicle);
 
-        if (Intent.ACTION_CREATE_SHORTCUT.equals(getIntent().getAction())) {
+        // Grab the app icon size as a resource.
+        mIconSize = getResources().getDimensionPixelSize(
+                android.R.dimen.app_icon_size);
+
+        Intent intent = getIntent();
+        if (Intent.ACTION_CREATE_SHORTCUT.equals(intent.getAction())) {
             mCreateShortcut = true;
         }
-        mDisableNewWindow = getIntent().getBooleanExtra("disable_new_window",
+        mDisableNewWindow = intent.getBooleanExtra("disable_new_window",
                 false);
-        mMostVisited = getIntent().getBooleanExtra("mostVisited", false);
+        mMostVisited = intent.getBooleanExtra("mostVisited", false);
 
         if (mCreateShortcut) {
             setTitle(R.string.browser_bookmarks_page_bookmarks_text);
         }
-        mBookmarksAdapter = new BrowserBookmarksAdapter(this,
-                        getIntent().getStringExtra("url"),
-                        getIntent().getStringExtra("title"),
-                        (Bitmap) getIntent().getParcelableExtra("thumbnail"),
-                        mCreateShortcut,
-                        mMostVisited);
 
         setContentView(R.layout.empty_history);
         mEmptyView = findViewById(R.id.empty_view);
@@ -264,18 +265,45 @@
                     PREF_BOOKMARK_VIEW_MODE, BookmarkViewMode.GRID.ordinal())];
         }
         switchViewMode(preference);
+
+        final boolean createShortcut = mCreateShortcut;
+        final boolean mostVisited = mMostVisited;
+        final String url = intent.getStringExtra("url");
+        final String title = intent.getStringExtra("title");
+        final Bitmap thumbnail =
+                (Bitmap) intent.getParcelableExtra("thumbnail");
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... unused) {
+                BrowserBookmarksAdapter adapter = new BrowserBookmarksAdapter(
+                        BrowserBookmarksPage.this,
+                        url,
+                        title,
+                        thumbnail,
+                        createShortcut,
+                        mostVisited);
+                mHandler.obtainMessage(ADAPTER_CREATED, adapter).sendToTarget();
+                return null;
+            }
+        }.execute();
+    }
+
+    @Override
+    protected void onDestroy() {
+        mHandler.removeCallbacksAndMessages(null);
+        super.onDestroy();
     }
 
     /**
      *  Set the ContentView to be either the grid of thumbnails or the vertical
      *  list.
      */
-    private void switchViewMode(BookmarkViewMode gridMode) {
-        if (mViewMode == gridMode) {
+    private void switchViewMode(BookmarkViewMode viewMode) {
+        if (mViewMode == viewMode) {
             return;
         }
 
-        mViewMode = gridMode;
+        mViewMode = viewMode;
 
         // Update the preferences to make the new view mode sticky.
         Editor ed = getPreferences(MODE_PRIVATE).edit();
@@ -286,11 +314,15 @@
         }
         ed.commit();
 
-        mBookmarksAdapter.switchViewMode(gridMode);
+        if (mBookmarksAdapter != null) {
+            mBookmarksAdapter.switchViewMode(viewMode);
+        }
         if (mViewMode == BookmarkViewMode.GRID) {
             if (mGridPage == null) {
                 mGridPage = new GridView(this);
-                mGridPage.setAdapter(mBookmarksAdapter);
+                if (mBookmarksAdapter != null) {
+                    mGridPage.setAdapter(mBookmarksAdapter);
+                }
                 mGridPage.setOnItemClickListener(mListener);
                 mGridPage.setNumColumns(GridView.AUTO_FIT);
                 mGridPage.setColumnWidth(
@@ -321,7 +353,9 @@
         } else {
             if (null == mVerticalList) {
                 ListView listView = new ListView(this);
-                listView.setAdapter(mBookmarksAdapter);
+                if (mBookmarksAdapter != null) {
+                    listView.setAdapter(mBookmarksAdapter);
+                }
                 listView.setDrawSelectorOnTop(false);
                 listView.setVerticalScrollBarEnabled(true);
                 listView.setOnItemClickListener(mListener);
@@ -345,15 +379,45 @@
 
     private static final ViewGroup.LayoutParams FULL_SCREEN_PARAMS
             = new ViewGroup.LayoutParams(
-            ViewGroup.LayoutParams.FILL_PARENT,
-            ViewGroup.LayoutParams.FILL_PARENT);
+            ViewGroup.LayoutParams.MATCH_PARENT,
+            ViewGroup.LayoutParams.MATCH_PARENT);
 
     private static final int SAVE_CURRENT_PAGE = 1000;
+    private static final int ADAPTER_CREATED = 1001;
     private final Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
-            if (msg.what == SAVE_CURRENT_PAGE) {
-                saveCurrentPage();
+            switch (msg.what) {
+                case SAVE_CURRENT_PAGE:
+                    saveCurrentPage();
+                    break;
+                case ADAPTER_CREATED:
+                    mBookmarksAdapter = (BrowserBookmarksAdapter) msg.obj;
+                    mBookmarksAdapter.switchViewMode(mViewMode);
+                    if (mGridPage != null) {
+                        mGridPage.setAdapter(mBookmarksAdapter);
+                    }
+                    if (mVerticalList != null) {
+                        mVerticalList.setAdapter(mBookmarksAdapter);
+                    }
+                    // Add our own listener in case there are favicons that
+                    // have yet to be loaded.
+                    if (mMostVisited) {
+                        IconListener listener = new IconListener() {
+                            public void onReceivedIcon(String url,
+                                    Bitmap icon) {
+                                if (mGridPage != null) {
+                                    mGridPage.setAdapter(mBookmarksAdapter);
+                                }
+                                if (mVerticalList != null) {
+                                    mVerticalList.setAdapter(mBookmarksAdapter);
+                                }
+                            }
+                        };
+                        CombinedBookmarkHistoryActivity.getIconListenerSet()
+                                .addListener(listener);
+                    }
+                    break;
             }
         }
     };
@@ -361,7 +425,7 @@
     private AdapterView.OnItemClickListener mListener = new AdapterView.OnItemClickListener() {
         public void onItemClick(AdapterView parent, View v, int position, long id) {
             // It is possible that the view has been canceled when we get to
-            // this point as back has a higher priority 
+            // this point as back has a higher priority
             if (mCanceled) {
                 android.util.Log.e(LOGTAG, "item clicked when dismissing");
                 return;
@@ -397,26 +461,34 @@
         i.putExtra(Intent.EXTRA_SHORTCUT_NAME, title);
         // Use the apple-touch-icon if available
         if (touchIcon != null) {
-            // Make a copy so we can modify the pixels.
-            Bitmap copy = touchIcon.copy(Bitmap.Config.ARGB_8888, true);
-            Canvas canvas = new Canvas(copy);
+            // Make a copy so we can modify the pixels.  We can't use
+            // createScaledBitmap or copy since they will preserve the config
+            // and lose the ability to add alpha.
+            Bitmap bm = Bitmap.createBitmap(mIconSize, mIconSize,
+                    Bitmap.Config.ARGB_8888);
+            Canvas canvas = new Canvas(bm);
+            Rect src = new Rect(0, 0, touchIcon.getWidth(),
+                                touchIcon.getHeight());
+            Rect dest = new Rect(0, 0, bm.getWidth(), bm.getHeight());
+
+            // Paint used for scaling the bitmap and drawing the rounded rect.
+            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+            paint.setFilterBitmap(true);
+            canvas.drawBitmap(touchIcon, src, dest, paint);
 
             // Construct a path from a round rect. This will allow drawing with
             // an inverse fill so we can punch a hole using the round rect.
             Path path = new Path();
             path.setFillType(Path.FillType.INVERSE_WINDING);
-            RectF rect = new RectF(0, 0, touchIcon.getWidth(),
-                    touchIcon.getHeight());
+            RectF rect = new RectF(0, 0, bm.getWidth(), bm.getHeight());
             rect.inset(1, 1);
             path.addRoundRect(rect, 8f, 8f, Path.Direction.CW);
 
-            // Construct a paint that clears the outside of the rectangle and
-            // draw.
-            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+            // Reuse the paint and clear the outside of the rectangle.
             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
             canvas.drawPath(path, paint);
 
-            i.putExtra(Intent.EXTRA_SHORTCUT_ICON, copy);
+            i.putExtra(Intent.EXTRA_SHORTCUT_ICON, bm);
         } else {
             Bitmap favicon = getFavicon(position);
             if (favicon == null) {
@@ -426,7 +498,7 @@
                                 R.drawable.ic_launcher_shortcut_browser_bookmark));
             } else {
                 Bitmap icon = BitmapFactory.decodeResource(getResources(),
-                        R.drawable.ic_launcher_shortcut_browser_bookmark);
+                        R.drawable.ic_launcher_shortcut_browser_bookmark_icon);
 
                 // Make a copy of the regular icon so we can modify the pixels.
                 Bitmap copy = icon.copy(Bitmap.Config.ARGB_8888, true);
@@ -439,12 +511,22 @@
                 p.setStyle(Paint.Style.FILL_AND_STROKE);
                 p.setColor(Color.WHITE);
 
+                final float density =
+                        getResources().getDisplayMetrics().density;
                 // Create a rectangle that is slightly wider than the favicon
-                final float iconSize = 16; // 16x16 favicon
-                final float padding = 2;   // white padding around icon
+                final float iconSize = 16 * density; // 16x16 favicon
+                final float padding = 2 * density; // white padding around icon
                 final float rectSize = iconSize + 2 * padding;
-                final float y = icon.getHeight() - rectSize;
-                RectF r = new RectF(0, y, rectSize, y + rectSize);
+
+                final Rect iconBounds =
+                        new Rect(0, 0, icon.getWidth(), icon.getHeight());
+                final float x = iconBounds.exactCenterX() - (rectSize / 2);
+                // Note: Subtract 2 dip from the y position since the box is
+                // slightly higher than center. Use padding since it is already
+                // 2 * density.
+                final float y = iconBounds.exactCenterY() - (rectSize / 2)
+                        - padding;
+                RectF r = new RectF(x, y, x + rectSize, y + rectSize);
 
                 // Draw a white rounded rectangle behind the favicon
                 canvas.drawRoundRect(r, 2, 2, p);
@@ -489,7 +571,7 @@
     @Override
     public boolean onPrepareOptionsMenu(Menu menu) {
         boolean result = super.onPrepareOptionsMenu(menu);
-        if (mCreateShortcut || mMostVisited
+        if (mCreateShortcut || mMostVisited || mBookmarksAdapter == null
                 || mBookmarksAdapter.getCount() == 0) {
             // No need to show the menu if there are no items.
             return result;
@@ -538,10 +620,10 @@
 
         finish();
     }
-    
+
 
     private void editBookmark(int position) {
-        Intent intent = new Intent(BrowserBookmarksPage.this, 
+        Intent intent = new Intent(BrowserBookmarksPage.this,
             AddBookmarkPage.class);
         intent.putExtra("bookmark", getRow(position));
         startActivityForResult(intent, BOOKMARKS_SAVE);
@@ -573,7 +655,7 @@
                 break;
         }
     }
-    
+
     private void displayRemoveBookmarkDialog(int position) {
         // Put up a dialog asking if the user really wants to
         // delete the bookmark
@@ -583,7 +665,7 @@
                 .setIcon(android.R.drawable.ic_dialog_alert)
                 .setMessage(getText(R.string.delete_bookmark_warning).toString().replace(
                         "%s", getBookmarkTitle(deletePos)))
-                .setPositiveButton(R.string.ok, 
+                .setPositiveButton(R.string.ok,
                         new DialogInterface.OnClickListener() {
                             public void onClick(DialogInterface dialog, int whichButton) {
                                 deleteBookmark(deletePos);
@@ -597,32 +679,37 @@
      *  Refresh the shown list after the database has changed.
      */
     private void refreshList() {
+        if (mBookmarksAdapter == null) return;
         mBookmarksAdapter.refreshList();
     }
-    
+
     /**
      *  Return a hashmap representing the currently highlighted row.
      */
     public Bundle getRow(int position) {
-        return mBookmarksAdapter.getRow(position);
+        return mBookmarksAdapter == null ? null
+                : mBookmarksAdapter.getRow(position);
     }
 
     /**
      *  Return the url of the currently highlighted row.
      */
     public String getUrl(int position) {
-        return mBookmarksAdapter.getUrl(position);
+        return mBookmarksAdapter == null ? null
+                : mBookmarksAdapter.getUrl(position);
     }
 
     /**
      * Return the favicon of the currently highlighted row.
      */
     public Bitmap getFavicon(int position) {
-        return mBookmarksAdapter.getFavicon(position);
+        return mBookmarksAdapter == null ? null
+                : mBookmarksAdapter.getFavicon(position);
     }
 
     private Bitmap getTouchIcon(int position) {
-        return mBookmarksAdapter.getTouchIcon(position);
+        return mBookmarksAdapter == null ? null
+                : mBookmarksAdapter.getTouchIcon(position);
     }
 
     private void copy(CharSequence text) {
@@ -635,15 +722,17 @@
             Log.e(LOGTAG, "Copy failed", e);
         }
     }
-    
+
     public String getBookmarkTitle(int position) {
-        return mBookmarksAdapter.getTitle(position);
+        return mBookmarksAdapter == null ? null
+                : mBookmarksAdapter.getTitle(position);
     }
 
     /**
      *  Delete the currently highlighted row.
      */
     public void deleteBookmark(int position) {
+        if (mBookmarksAdapter == null) return;
         mBookmarksAdapter.deleteRow(position);
     }
 
@@ -654,12 +743,17 @@
         super.onBackPressed();
     }
 
-    // This Activity is generally a sub-Activity of CombinedHistoryActivity. In
-    // that situation, we need to pass our result code up to our parent.
-    // However, if someone calls this Activity directly, then this has no
-    // parent, and it needs to set it on itself.
+    // This Activity is generally a sub-Activity of
+    // CombinedBookmarkHistoryActivity. In that situation, we need to pass our
+    // result code up to our parent. However, if someone calls this Activity
+    // directly, then this has no parent, and it needs to set it on itself.
     private void setResultToParent(int resultCode, Intent data) {
-        Activity a = getParent() == null ? this : getParent();
-        a.setResult(resultCode, data);
+        Activity parent = getParent();
+        if (parent == null) {
+            setResult(resultCode, data);
+        } else {
+            ((CombinedBookmarkHistoryActivity) parent).setResultFromChild(
+                    resultCode, data);
+        }
     }
 }
diff --git a/src/com/android/browser/BrowserDownloadAdapter.java b/src/com/android/browser/BrowserDownloadAdapter.java
index 16cb982..0f8f721 100644
--- a/src/com/android/browser/BrowserDownloadAdapter.java
+++ b/src/com/android/browser/BrowserDownloadAdapter.java
@@ -17,8 +17,6 @@
  
 package com.android.browser;
 
-import android.content.ContentUris;
-import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -30,13 +28,14 @@
 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.ResourceCursorAdapter;
+import android.widget.RelativeLayout;
 import android.widget.TextView;
 
-import java.io.File;
 import java.text.DateFormat;
 import java.util.Date;
 import java.util.List;
@@ -46,9 +45,8 @@
  * real work done by this class is to construct a custom view for the line
  * items.
  */
-public class BrowserDownloadAdapter extends ResourceCursorAdapter {
+public class BrowserDownloadAdapter extends DateSortedExpandableListAdapter {
     
-    private int mFilenameColumnId;
     private int mTitleColumnId;
     private int mDescColumnId;
     private int mStatusColumnId;
@@ -57,26 +55,39 @@
     private int mMimetypeColumnId;
     private int mDateColumnId;
 
-    public BrowserDownloadAdapter(Context context, int layout, Cursor c) {
-        super(context, layout, c);
-        mFilenameColumnId = c.getColumnIndexOrThrow(Downloads._DATA);
-        mTitleColumnId = c.getColumnIndexOrThrow(Downloads.COLUMN_TITLE);
-        mDescColumnId = c.getColumnIndexOrThrow(Downloads.COLUMN_DESCRIPTION);
-        mStatusColumnId = c.getColumnIndexOrThrow(Downloads.COLUMN_STATUS);
-        mTotalBytesColumnId = c.getColumnIndexOrThrow(Downloads.COLUMN_TOTAL_BYTES);
+    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.COLUMN_CURRENT_BYTES);
-        mMimetypeColumnId = c.getColumnIndexOrThrow(Downloads.COLUMN_MIME_TYPE);
-        mDateColumnId = c.getColumnIndexOrThrow(Downloads.COLUMN_LAST_MODIFICATION);
+            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 void bindView(View view, Context context, Cursor cursor) {
+    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 = cursor.getString(mMimetypeColumnId);
-        ImageView iv = (ImageView) view.findViewById(R.id.download_icon);
+        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) {
@@ -96,89 +107,77 @@
             }
         }
         
-        TextView tv = (TextView) view.findViewById(R.id.download_title);
-        String title = cursor.getString(mTitleColumnId);
+        TextView tv = (TextView) convertView.findViewById(R.id.download_title);
+        String title = getString(mTitleColumnId);
         if (title == null) {
-            String fullFilename = cursor.getString(mFilenameColumnId);
-            if (fullFilename == null) {
-                title = r.getString(R.string.download_unknown_filename);
-            } else {
-                // We have a filename, so we can build a title from that
-                title = new File(fullFilename).getName();
-                ContentValues values = new ContentValues();
-                values.put(Downloads.COLUMN_TITLE, title);
-                // assume "_id" is the first column for the cursor 
-                context.getContentResolver().update(
-                        ContentUris.withAppendedId(Downloads.CONTENT_URI,
-                        cursor.getLong(0)), values, null, null);
-            }
+            title = r.getString(R.string.download_unknown_filename);
         }
         tv.setText(title);
         
-        tv = (TextView) view.findViewById(R.id.domain);
-        tv.setText(cursor.getString(mDescColumnId));
+        tv = (TextView) convertView.findViewById(R.id.domain);
+        tv.setText(getString(mDescColumnId));
         
-        long totalBytes = cursor.getLong(mTotalBytesColumnId);
+        long totalBytes = getLong(mTotalBytesColumnId);
         
-        int status = cursor.getInt(mStatusColumnId);
-        if (Downloads.isStatusCompleted(status)) { // Download stopped
-            View v = view.findViewById(R.id.progress_text);
+        int status = getInt(mStatusColumnId);
+        if (Downloads.Impl.isStatusCompleted(status)) { // Download stopped
+            View v = convertView.findViewById(R.id.progress_text);
             v.setVisibility(View.GONE);
 
-            v = view.findViewById(R.id.download_progress);
+            v = convertView.findViewById(R.id.download_progress);
             v.setVisibility(View.GONE);
 
-            tv = (TextView) view.findViewById(R.id.complete_text);
+            tv = (TextView) convertView.findViewById(R.id.complete_text);
             tv.setVisibility(View.VISIBLE);
-            if (Downloads.isStatusError(status)) {
+            if (Downloads.Impl.isStatusError(status)) {
                 tv.setText(getErrorText(status));
             } else {
                 tv.setText(r.getString(R.string.download_success, 
-                        Formatter.formatFileSize(mContext, totalBytes)));
+                        Formatter.formatFileSize(context, totalBytes)));
             }
             
-            long time = cursor.getLong(mDateColumnId);
+            long time = getLong(mDateColumnId);
             Date d = new Date(time);
             DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
-            tv = (TextView) view.findViewById(R.id.complete_date);
+            tv = (TextView) convertView.findViewById(R.id.complete_date);
             tv.setVisibility(View.VISIBLE);
             tv.setText(df.format(d));
             
         } else { // Download is still running
-            tv = (TextView) view.findViewById(R.id.progress_text);
+            tv = (TextView) convertView.findViewById(R.id.progress_text);
             tv.setVisibility(View.VISIBLE);
 
-            View progress = view.findViewById(R.id.download_progress);
+            View progress = convertView.findViewById(R.id.download_progress);
             progress.setVisibility(View.VISIBLE);
             
-            View v = view.findViewById(R.id.complete_date);
+            View v = convertView.findViewById(R.id.complete_date);
             v.setVisibility(View.GONE);
 
-            v = view.findViewById(R.id.complete_text);
+            v = convertView.findViewById(R.id.complete_text);
             v.setVisibility(View.GONE);
             
-            if (status == Downloads.STATUS_PENDING) {
+            if (status == Downloads.Impl.STATUS_PENDING) {
                 tv.setText(r.getText(R.string.download_pending));
-            } else if (status == Downloads.STATUS_PENDING_PAUSED) {
+            } 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.STATUS_RUNNING) {
+                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 = cursor.getLong(mCurrentBytesColumnId); 
+                    long currentBytes = getLong(mCurrentBytesColumnId);
                     int progressAmount = (int)(currentBytes * 100 / totalBytes);
                     sb.append(' ');
                     sb.append(progressAmount);
                     sb.append("% (");
-                    sb.append(Formatter.formatFileSize(mContext, currentBytes));
+                    sb.append(Formatter.formatFileSize(context, currentBytes));
                     sb.append("/");
-                    sb.append(Formatter.formatFileSize(mContext, totalBytes));
+                    sb.append(Formatter.formatFileSize(context, totalBytes));
                     sb.append(")");
                     pb.setIndeterminate(false);
                     pb.setProgress(progressAmount);
@@ -188,7 +187,7 @@
                 tv.setText(sb.toString()); 
             }
         }
-        
+        return convertView;
     }
     
     /**
@@ -198,23 +197,23 @@
      */
     public static int getErrorText(int status) {
         switch (status) {
-            case Downloads.STATUS_NOT_ACCEPTABLE:
+            case Downloads.Impl.STATUS_NOT_ACCEPTABLE:
                 return R.string.download_not_acceptable;
                 
-            case Downloads.STATUS_LENGTH_REQUIRED:
+            case Downloads.Impl.STATUS_LENGTH_REQUIRED:
                 return R.string.download_length_required;
                 
-            case Downloads.STATUS_PRECONDITION_FAILED:
+            case Downloads.Impl.STATUS_PRECONDITION_FAILED:
                 return R.string.download_precondition_failed;
                 
-            case Downloads.STATUS_CANCELED:
+            case Downloads.Impl.STATUS_CANCELED:
                 return R.string.download_canceled;
 
-            case Downloads.STATUS_FILE_ERROR:
+            case Downloads.Impl.STATUS_FILE_ERROR:
                 return R.string.download_file_error;
                 
-            case Downloads.STATUS_BAD_REQUEST:
-            case Downloads.STATUS_UNKNOWN_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
index 22e0e65..18faf8b 100644
--- a/src/com/android/browser/BrowserDownloadPage.java
+++ b/src/com/android/browser/BrowserDownloadPage.java
@@ -16,8 +16,8 @@
 
 package com.android.browser;
 
-import android.app.Activity;
 import android.app.AlertDialog;
+import android.app.ExpandableListActivity;
 import android.content.ActivityNotFoundException;
 import android.content.ContentValues;
 import android.content.DialogInterface;
@@ -25,10 +25,13 @@
 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;
@@ -38,8 +41,7 @@
 import android.view.View;
 import android.view.ViewGroup.LayoutParams;
 import android.widget.AdapterView;
-import android.widget.ListView;
-import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ExpandableListView;
 
 import java.io.File;
 import java.util.List;
@@ -47,17 +49,22 @@
 /**
  *  View showing the user's current browser downloads
  */
-public class BrowserDownloadPage extends Activity 
-        implements View.OnCreateContextMenuListener, OnItemClickListener {
-    
-    private ListView                mListView;
+public class BrowserDownloadPage extends ExpandableListActivity {
+    private ExpandableListView      mListView;
     private Cursor                  mDownloadCursor;
     private BrowserDownloadAdapter  mDownloadAdapter;
     private int                     mStatusColumnId;
     private int                     mIdColumnId;
     private int                     mTitleColumnId;
-    private int                     mContextMenuPosition;
-    
+    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);
@@ -65,47 +72,88 @@
         
         setTitle(getText(R.string.download_title));
 
-        mListView = (ListView) findViewById(R.id.list);
+        mListView = (ExpandableListView) findViewById(android.R.id.list);
         mListView.setEmptyView(findViewById(R.id.empty));
-        
-        mDownloadCursor = managedQuery(Downloads.CONTENT_URI, 
-                new String [] {"_id", Downloads.COLUMN_TITLE, Downloads.COLUMN_STATUS,
-                Downloads.COLUMN_TOTAL_BYTES, Downloads.COLUMN_CURRENT_BYTES, 
-                Downloads._DATA, Downloads.COLUMN_DESCRIPTION, 
-                Downloads.COLUMN_MIME_TYPE, Downloads.COLUMN_LAST_MODIFICATION,
-                Downloads.COLUMN_VISIBILITY}, 
-                null, null);
+        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.COLUMN_STATUS);
+                    mDownloadCursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_STATUS);
             mIdColumnId =
-                    mDownloadCursor.getColumnIndexOrThrow(Downloads._ID);
+                    mDownloadCursor.getColumnIndexOrThrow(Downloads.Impl._ID);
             mTitleColumnId = 
-                    mDownloadCursor.getColumnIndexOrThrow(Downloads.COLUMN_TITLE);
+                    mDownloadCursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_TITLE);
             
             // Create a list "controller" for the data
             mDownloadAdapter = new BrowserDownloadAdapter(this, 
-                    R.layout.browser_download_item, mDownloadCursor);
+                    mDownloadCursor, mDownloadCursor.getColumnIndexOrThrow(
+                    Downloads.Impl.COLUMN_LAST_MODIFICATION));
 
-            mListView.setAdapter(mDownloadAdapter);
-            mListView.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET);
+            setListAdapter(mDownloadAdapter);
             mListView.setOnCreateContextMenuListener(this);
-            mListView.setOnItemClickListener(this);
-            
+
             Intent intent = getIntent();
-            if (intent != null && intent.getData() != null) {
-                int position = checkStatus(
-                        ContentUris.parseId(intent.getData()));
-                if (position >= 0) {
-                    mListView.setSelection(position);
-                }
+            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) {
@@ -119,9 +167,6 @@
     public boolean onPrepareOptionsMenu(Menu menu) {
         boolean showCancel = getCancelableCount() > 0;
         menu.findItem(R.id.download_menu_cancel_all).setEnabled(showCancel);
-        
-        boolean showClear = getClearableCount() > 0;
-        menu.findItem(R.id.download_menu_clear_all).setEnabled(showClear);
         return super.onPrepareOptionsMenu(menu);
     }
     
@@ -131,107 +176,194 @@
             case R.id.download_menu_cancel_all:
                 promptCancelAll();
                 return true;
-                
-            case R.id.download_menu_clear_all:
-                promptClearList();
+        }
+        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
-    public boolean onContextItemSelected(MenuItem item) {
-        mDownloadCursor.moveToPosition(mContextMenuPosition);
-        switch (item.getItemId()) {
-            case R.id.download_menu_open:
-                hideCompletedDownload();
-                openCurrentDownload();
-                return true;
-                
-            case R.id.download_menu_clear:
-            case R.id.download_menu_cancel:
-                getContentResolver().delete(
-                        ContentUris.withAppendedId(Downloads.CONTENT_URI,
-                        mDownloadCursor.getLong(mIdColumnId)), null, null);
-                return true;
+    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.
         }
-        return false;
+    }
+
+    /*
+     * 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) {
-            AdapterView.AdapterContextMenuInfo info = 
-                    (AdapterView.AdapterContextMenuInfo) menuInfo;
-            mDownloadCursor.moveToPosition(info.position);
-            mContextMenuPosition = info.position;
+            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.isStatusSuccess(status)) {
+            if (Downloads.Impl.isStatusSuccess(status)) {
                 inflater.inflate(R.menu.downloadhistorycontextfinished, menu);
-            } else if (Downloads.isStatusError(status)) {
+            } 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 position of item
+     * @return Group which contains the download
      */
-    int checkStatus(final long id) {
-        int position = -1;
-        for (mDownloadCursor.moveToFirst(); !mDownloadCursor.isAfterLast(); 
-                mDownloadCursor.moveToNext()) {
-            if (id == mDownloadCursor.getLong(mIdColumnId)) {
-                position = mDownloadCursor.getPosition();
-                break;
-            }
-            
+    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 (!mDownloadCursor.isAfterLast()) {
-            int status = mDownloadCursor.getInt(mStatusColumnId);
-            if (!Downloads.isStatusError(status)) {
-                return position;
+        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);
             }
-            
-            if (status == Downloads.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();
-            }
+            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 position;
+        return groupToShow;
     }
     
     /**
@@ -243,25 +375,6 @@
     }
     
     /**
-     * Prompt the user if they would like to clear the download history
-     */
-    private void promptClearList() {
-        new AlertDialog.Builder(this)
-               .setTitle(R.string.download_clear_dlg_title)
-               .setIcon(R.drawable.ssl_icon)
-               .setMessage(R.string.download_clear_dlg_msg)
-               .setPositiveButton(R.string.ok, 
-                       new DialogInterface.OnClickListener() {
-                           public void onClick(DialogInterface dialog, 
-                                   int whichButton) {
-                               clearAllDownloads();
-                           }
-                       })
-                .setNegativeButton(R.string.cancel, null)
-                .show();
-    }
-    
-    /**
      * Return the number of items in the list that can be canceled.
      * @return count
      */
@@ -269,10 +382,10 @@
         // Count the number of items that will be canceled.
         int count = 0;
         if (mDownloadCursor != null) {
-            for (mDownloadCursor.moveToFirst(); !mDownloadCursor.isAfterLast(); 
+            for (mDownloadCursor.moveToFirst(); !mDownloadCursor.isAfterLast();
                     mDownloadCursor.moveToNext()) {
                 int status = mDownloadCursor.getInt(mStatusColumnId);
-                if (!Downloads.isStatusCompleted(status)) {
+                if (!Downloads.Impl.isStatusCompleted(status)) {
                     count++;
                 }
             }
@@ -325,14 +438,14 @@
             boolean firstTime = true;
             while (!mDownloadCursor.isAfterLast()) {
                 int status = mDownloadCursor.getInt(mStatusColumnId);
-                if (!Downloads.isStatusCompleted(status)) {
+                if (!Downloads.Impl.isStatusCompleted(status)) {
                     if (firstTime) {
                         firstTime = false;
                     } else {
                         where.append(" OR ");
                     }
                     where.append("( ");
-                    where.append(Downloads._ID);
+                    where.append(Downloads.Impl._ID);
                     where.append(" = '");
                     where.append(mDownloadCursor.getLong(mIdColumnId));
                     where.append("' )");
@@ -340,7 +453,7 @@
                 mDownloadCursor.moveToNext();
             }
             if (!firstTime) {
-                getContentResolver().delete(Downloads.CONTENT_URI,
+                getContentResolver().delete(Downloads.Impl.CONTENT_URI,
                         where.toString(), null);
             }
         }
@@ -351,7 +464,7 @@
         if (mDownloadCursor.moveToFirst()) {
             while (!mDownloadCursor.isAfterLast()) {
                 int status = mDownloadCursor.getInt(mStatusColumnId);
-                if (Downloads.isStatusCompleted(status)) {
+                if (Downloads.Impl.isStatusCompleted(status)) {
                     count++;
                 }
                 mDownloadCursor.moveToNext();
@@ -359,87 +472,44 @@
         }
         return count;
     }
-    
+
     /**
-     * Clear all stopped downloads, ie canceled (though should not be
-     * there), error and success download items.
+     * 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 clearAllDownloads() {
-        if (mDownloadCursor.moveToFirst()) {
-            StringBuilder where = new StringBuilder();
-            boolean firstTime = true;
-            while (!mDownloadCursor.isAfterLast()) {
-                int status = mDownloadCursor.getInt(mStatusColumnId);
-                if (Downloads.isStatusCompleted(status)) {
-                    if (firstTime) {
-                        firstTime = false;
-                    } else {
-                        where.append(" OR ");
-                    }
-                    where.append("( ");
-                    where.append(Downloads._ID);
-                    where.append(" = '");
-                    where.append(mDownloadCursor.getLong(mIdColumnId));
-                    where.append("' )");
-                }
-                mDownloadCursor.moveToNext();
-            }
-            if (!firstTime) {
-                getContentResolver().delete(Downloads.CONTENT_URI,
-                        where.toString(), null);
-            }
-        }
-    }
-    
-    /**
-     * Open the content where the download db cursor currently is
-     */
-    private void openCurrentDownload() {
-        int filenameColumnId = 
-                mDownloadCursor.getColumnIndexOrThrow(Downloads._DATA);
-        String filename = mDownloadCursor.getString(filenameColumnId);
-        int mimetypeColumnId =
-                mDownloadCursor.getColumnIndexOrThrow(Downloads.COLUMN_MIME_TYPE);
-        String mimetype = mDownloadCursor.getString(mimetypeColumnId);
-        Uri path = Uri.parse(filename);
-        // If there is no scheme, then it must be a file
-        if (path.getScheme() == null) {
-            path = Uri.fromFile(new File(filename));
-        }
-        Intent intent = new Intent(Intent.ACTION_VIEW);
-        intent.setDataAndType(path, mimetype);
-        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-        try {
-            startActivity(intent);
-        } catch (ActivityNotFoundException ex) {
-            new AlertDialog.Builder(this)
-                    .setTitle(R.string.download_failed_generic_dlg_title)
-                    .setIcon(R.drawable.ssl_icon)
-                    .setMessage(R.string.download_no_application)
-                    .setPositiveButton(R.string.ok, null)
-                    .show();
-        }
+    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);
     }
 
-    /*
-     * (non-Javadoc)
-     * @see android.widget.AdapterView.OnItemClickListener#onItemClick(android.widget.AdapterView, android.view.View, int, long)
-     */
-    public void onItemClick(AdapterView parent, View view, int position, 
-            long id) {
+    @Override
+    public boolean onChildClick(ExpandableListView parent, View v,
+            int groupPosition, int childPosition, long id) {
         // Open the selected item
-        mDownloadCursor.moveToPosition(position);
+        mDownloadAdapter.moveCursorToChildPosition(groupPosition,
+                childPosition);
         
         hideCompletedDownload();
 
         int status = mDownloadCursor.getInt(mStatusColumnId);
-        if (Downloads.isStatusSuccess(status)) {
+        if (Downloads.Impl.isStatusSuccess(status)) {
             // Open it if it downloaded successfully
-            openCurrentDownload();
+            openOrDeleteCurrentDownload(false);
         } else {
             // Check to see if there is an error.
             checkStatus(id);
         }
+        return true;
     }
     
     /**
@@ -449,15 +519,16 @@
     private void hideCompletedDownload() {
         int status = mDownloadCursor.getInt(mStatusColumnId);
 
-        int visibilityColumn = mDownloadCursor.getColumnIndexOrThrow(Downloads.COLUMN_VISIBILITY);
+        int visibilityColumn = mDownloadCursor.getColumnIndexOrThrow(
+                Downloads.Impl.COLUMN_VISIBILITY);
         int visibility = mDownloadCursor.getInt(visibilityColumn);
 
-        if (Downloads.isStatusCompleted(status) &&
-                visibility == Downloads.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) {
+        if (Downloads.Impl.isStatusCompleted(status) &&
+                visibility == Downloads.Impl.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) {
             ContentValues values = new ContentValues();
-            values.put(Downloads.COLUMN_VISIBILITY, Downloads.VISIBILITY_VISIBLE);
+            values.put(Downloads.Impl.COLUMN_VISIBILITY, Downloads.Impl.VISIBILITY_VISIBLE);
             getContentResolver().update(
-                    ContentUris.withAppendedId(Downloads.CONTENT_URI,
+                    ContentUris.withAppendedId(Downloads.Impl.CONTENT_URI,
                     mDownloadCursor.getLong(mIdColumnId)), values, null, null);
         }
     }
diff --git a/src/com/android/browser/BrowserHistoryPage.java b/src/com/android/browser/BrowserHistoryPage.java
index bdd109b..23080f8 100644
--- a/src/com/android/browser/BrowserHistoryPage.java
+++ b/src/com/android/browser/BrowserHistoryPage.java
@@ -18,23 +18,19 @@
 
 import android.app.Activity;
 import android.app.ExpandableListActivity;
+import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.database.ContentObserver;
 import android.database.Cursor;
-import android.database.DataSetObserver;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.os.Bundle;
-import android.os.Handler;
 import android.os.ServiceManager;
 import android.provider.Browser;
 import android.text.IClipboard;
 import android.util.Log;
 import android.view.ContextMenu;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
@@ -43,25 +39,18 @@
 import android.view.ViewGroup.LayoutParams;
 import android.view.ContextMenu.ContextMenuInfo;
 import android.view.ViewStub;
-import android.webkit.DateSorter;
 import android.webkit.WebIconDatabase.IconListener;
-import android.widget.AdapterView;
 import android.widget.ExpandableListAdapter;
 import android.widget.ExpandableListView;
 import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
-import android.widget.TextView;
 import android.widget.Toast;
 
-import java.util.List;
-import java.util.Vector;
-
 /**
  * Activity for displaying the browser's history, divided into
  * days of viewing.
  */
 public class BrowserHistoryPage extends ExpandableListActivity {
     private HistoryAdapter          mAdapter;
-    private DateSorter              mDateSorter;
     private boolean                 mDisableNewWindow;
     private HistoryItem             mContextHeader;
 
@@ -107,16 +96,30 @@
     protected void onCreate(Bundle icicle) {
         super.onCreate(icicle);
         setTitle(R.string.browser_history);
-        
-        mDateSorter = new DateSorter(this);
 
-        mAdapter = new HistoryAdapter();
+        final String whereClause = Browser.BookmarkColumns.VISITS + " > 0"
+                // In AddBookmarkPage, where we save new bookmarks, we add
+                // three visits to newly created bookmarks, so that
+                // bookmarks that have not been visited will show up in the
+                // most visited, and higher in the goto search box.
+                // However, this puts the site in the history, unless we
+                // ignore sites with a DATE of 0, which the next line does.
+                + " AND " + Browser.BookmarkColumns.DATE + " > 0";
+        final String orderBy = Browser.BookmarkColumns.DATE + " DESC";
+
+        Cursor cursor = managedQuery(
+                Browser.BOOKMARKS_URI,
+                Browser.HISTORY_PROJECTION,
+                whereClause, null, orderBy);
+
+        mAdapter = new HistoryAdapter(this, cursor,
+                Browser.HISTORY_PROJECTION_DATE_INDEX);
         setListAdapter(mAdapter);
         final ExpandableListView list = getExpandableListView();
         list.setOnCreateContextMenuListener(this);
         View v = new ViewStub(this, R.layout.empty_history);
-        addContentView(v, new LayoutParams(LayoutParams.FILL_PARENT,
-                LayoutParams.FILL_PARENT));
+        addContentView(v, new LayoutParams(LayoutParams.MATCH_PARENT,
+                LayoutParams.MATCH_PARENT));
         list.setEmptyView(v);
         // Do not post the runnable if there is nothing in the list.
         if (list.getExpandableListAdapter().getGroupCount() > 0) {
@@ -132,9 +135,17 @@
         }
         mDisableNewWindow = getIntent().getBooleanExtra("disable_new_window",
                 false);
+
+        // Register to receive icons in case they haven't all been loaded.
         CombinedBookmarkHistoryActivity.getIconListenerSet()
                 .addListener(mIconReceiver);
-        
+
+        Activity parent = getParent();
+        if (null == parent
+                || !(parent instanceof CombinedBookmarkHistoryActivity)) {
+            throw new AssertionError("history page can only be viewed as a tab"
+                    + "in CombinedBookmarkHistoryActivity");
+        }
         // initialize the result to canceled, so that if the user just presses
         // back then it will have the correct result
         setResultToParent(RESULT_CANCELED, null);
@@ -165,9 +176,11 @@
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
             case R.id.clear_history_menu_id:
-                // FIXME: Need to clear the tab control in browserActivity 
-                // as well
                 Browser.clearHistory(getContentResolver());
+                // BrowserHistoryPage is always a child of
+                // CombinedBookmarkHistoryActivity
+                ((CombinedBookmarkHistoryActivity) getParent())
+                        .removeParentChildRelationShips();
                 mAdapter.refreshData();
                 return true;
                 
@@ -275,137 +288,22 @@
         return false;
     }
 
-    // This Activity is generally a sub-Activity of CombinedHistoryActivity. In
-    // that situation, we need to pass our result code up to our parent.
-    // However, if someone calls this Activity directly, then this has no
-    // parent, and it needs to set it on itself.
+    // This Activity is always a sub-Activity of
+    // CombinedBookmarkHistoryActivity. Therefore, we need to pass our
+    // result code up to our parent.
     private void setResultToParent(int resultCode, Intent data) {
-        Activity a = getParent() == null ? this : getParent();
-        a.setResult(resultCode, data);
+        ((CombinedBookmarkHistoryActivity) getParent()).setResultFromChild(
+                resultCode, data);
     }
 
-    private class ChangeObserver extends ContentObserver {
-        public ChangeObserver() {
-            super(new Handler());
-        }
-
-        @Override
-        public boolean deliverSelfNotifications() {
-            return true;
-        }
-
-        @Override
-        public void onChange(boolean selfChange) {
-            mAdapter.refreshData();
-        }
-    }
-    
-    private class HistoryAdapter implements ExpandableListAdapter {
-        
-        // Array for each of our bins.  Each entry represents how many items are
-        // in that bin.
-        private int mItemMap[];
-        // This is our GroupCount.  We will have at most DateSorter.DAY_COUNT
-        // bins, less if the user has no items in one or more bins.
-        private int mNumberOfBins;
-        private Vector<DataSetObserver> mObservers;
-        private Cursor mCursor;
-        
-        HistoryAdapter() {
-            mObservers = new Vector<DataSetObserver>();
+    private class HistoryAdapter extends DateSortedExpandableListAdapter {
+        HistoryAdapter(Context context, Cursor cursor, int index) {
+            super(context, cursor, index);
             
-            final String whereClause = Browser.BookmarkColumns.VISITS + " > 0"
-                    // In AddBookmarkPage, where we save new bookmarks, we add
-                    // three visits to newly created bookmarks, so that
-                    // bookmarks that have not been visited will show up in the
-                    // most visited, and higher in the goto search box.
-                    // However, this puts the site in the history, unless we
-                    // ignore sites with a DATE of 0, which the next line does.
-                    + " AND " + Browser.BookmarkColumns.DATE + " > 0";
-            final String orderBy = Browser.BookmarkColumns.DATE + " DESC";
-           
-            mCursor = managedQuery(
-                    Browser.BOOKMARKS_URI,
-                    Browser.HISTORY_PROJECTION,
-                    whereClause, null, orderBy);
-            
-            buildMap();
-            mCursor.registerContentObserver(new ChangeObserver());
-        }
-        
-        void refreshData() {
-            if (mCursor.isClosed()) {
-                return;
-            }
-            mCursor.requery();
-            buildMap();
-            for (DataSetObserver o : mObservers) {
-                o.onChanged();
-            }
-        }
-        
-        private void buildMap() {
-            // The cursor is sorted by date
-            // The ItemMap will store the number of items in each bin.
-            int array[] = new int[DateSorter.DAY_COUNT];
-            // Zero out the array.
-            for (int j = 0; j < DateSorter.DAY_COUNT; j++) {
-                array[j] = 0;
-            }
-            mNumberOfBins = 0;
-            int dateIndex = -1;
-            if (mCursor.moveToFirst() && mCursor.getCount() > 0) {
-                while (!mCursor.isAfterLast()) {
-                    long date = mCursor.getLong(Browser.HISTORY_PROJECTION_DATE_INDEX);
-                    int index = mDateSorter.getIndex(date);
-                    if (index > dateIndex) {
-                        mNumberOfBins++;
-                        if (index == DateSorter.DAY_COUNT - 1) {
-                            // We are already in the last bin, so it will
-                            // include all the remaining items
-                            array[index] = mCursor.getCount()
-                                    - mCursor.getPosition();
-                            break;
-                        }
-                        dateIndex = index;
-                    }
-                    array[dateIndex]++;
-                    mCursor.moveToNext();
-                }
-            }
-            mItemMap = array;
-        }
-
-        // This translates from a group position in the Adapter to a position in
-        // our array.  This is necessary because some positions in the array
-        // have no history items, so we simply do not present those positions
-        // to the Adapter.
-        private int groupPositionToArrayPosition(int groupPosition) {
-            if (groupPosition < 0 || groupPosition >= DateSorter.DAY_COUNT) {
-                throw new AssertionError("group position out of range");
-            }
-            if (DateSorter.DAY_COUNT == mNumberOfBins || 0 == mNumberOfBins) {
-                // In the first case, we have exactly the same number of bins
-                // as our maximum possible, so there is no need to do a
-                // conversion
-                // The second statement is in case this method gets called when
-                // the array is empty, in which case the provided groupPosition
-                // will do fine.
-                return groupPosition;
-            }
-            int arrayPosition = -1;
-            while (groupPosition > -1) {
-                arrayPosition++;
-                if (mItemMap[arrayPosition] != 0) {
-                    groupPosition--;
-                }
-            }
-            return arrayPosition;
         }
 
         public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
                 View convertView, ViewGroup parent) {
-            groupPosition = groupPositionToArrayPosition(groupPosition);
             HistoryItem item;
             if (null == convertView || !(convertView instanceof HistoryItem)) {
                 item = new HistoryItem(BrowserHistoryPage.this);
@@ -418,15 +316,14 @@
             } else {
                 item = (HistoryItem) convertView;
             }
-            int index = childPosition;
-            for (int i = 0; i < groupPosition; i++) {
-                index += mItemMap[i];
+            // Bail early if the Cursor is closed.
+            if (!moveCursorToChildPosition(groupPosition, childPosition)) {
+                return item;
             }
-            mCursor.moveToPosition(index);
-            item.setName(mCursor.getString(Browser.HISTORY_PROJECTION_TITLE_INDEX));
-            String url = mCursor.getString(Browser.HISTORY_PROJECTION_URL_INDEX);
+            item.setName(getString(Browser.HISTORY_PROJECTION_TITLE_INDEX));
+            String url = getString(Browser.HISTORY_PROJECTION_URL_INDEX);
             item.setUrl(url);
-            byte[] data = mCursor.getBlob(Browser.HISTORY_PROJECTION_FAVICON_INDEX);
+            byte[] data = getBlob(Browser.HISTORY_PROJECTION_FAVICON_INDEX);
             if (data != null) {
                 item.setFavicon(BitmapFactory.decodeByteArray(data, 0,
                         data.length));
@@ -435,87 +332,8 @@
                         .getIconListenerSet().getFavicon(url));
             }
             item.setIsBookmark(1 ==
-                    mCursor.getInt(Browser.HISTORY_PROJECTION_BOOKMARK_INDEX));
+                    getInt(Browser.HISTORY_PROJECTION_BOOKMARK_INDEX));
             return item;
         }
-        
-        public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
-            groupPosition = groupPositionToArrayPosition(groupPosition);
-            TextView item;
-            if (null == convertView || !(convertView instanceof TextView)) {
-                LayoutInflater factory = 
-                        LayoutInflater.from(BrowserHistoryPage.this);
-                item = (TextView) 
-                        factory.inflate(R.layout.history_header, null);
-            } else {
-                item = (TextView) convertView;
-            }
-            item.setText(mDateSorter.getLabel(groupPosition));
-            return item;
-        }
-
-        public boolean areAllItemsEnabled() {
-            return true;
-        }
-
-        public boolean isChildSelectable(int groupPosition, int childPosition) {
-            return true;
-        }
-
-        public int getGroupCount() {
-            return mNumberOfBins;
-        }
-
-        public int getChildrenCount(int groupPosition) {
-            return mItemMap[groupPositionToArrayPosition(groupPosition)];
-        }
-
-        public Object getGroup(int groupPosition) {
-            return null;
-        }
-
-        public Object getChild(int groupPosition, int childPosition) {
-            return null;
-        }
-
-        public long getGroupId(int groupPosition) {
-            return groupPosition;
-        }
-
-        public long getChildId(int groupPosition, int childPosition) {
-            return (childPosition << 3) + groupPosition;
-        }
-
-        public boolean hasStableIds() {
-            return true;
-        }
-
-        public void registerDataSetObserver(DataSetObserver observer) {
-            mObservers.add(observer);
-        }
-
-        public void unregisterDataSetObserver(DataSetObserver observer) {
-            mObservers.remove(observer);
-        }
-
-        public void onGroupExpanded(int groupPosition) {
-        
-        }
-
-        public void onGroupCollapsed(int groupPosition) {
-        
-        }
-
-        public long getCombinedChildId(long groupId, long childId) {
-            return childId;
-        }
-
-        public long getCombinedGroupId(long groupId) {
-            return groupId;
-        }
-
-        public boolean isEmpty() {
-            return mCursor.getCount() == 0;
-        }
     }
 }
diff --git a/src/com/android/browser/BrowserHomepagePreference.java b/src/com/android/browser/BrowserHomepagePreference.java
index be96db3..4f18bd5 100644
--- a/src/com/android/browser/BrowserHomepagePreference.java
+++ b/src/com/android/browser/BrowserHomepagePreference.java
@@ -18,10 +18,20 @@
 
 import android.app.AlertDialog;
 import android.content.Context;
+import android.os.Bundle;
 import android.preference.EditTextPreference;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
 import android.util.AttributeSet;
 
 public class BrowserHomepagePreference extends EditTextPreference {
+    private String mCurrentPage;
 
     public BrowserHomepagePreference(Context context, AttributeSet attrs,
             int defStyle) {
@@ -37,6 +47,27 @@
     }
 
     @Override
+    protected void onAddEditTextToDialogView(View dialogView,
+            EditText editText) {
+        super.onAddEditTextToDialogView(dialogView, editText);
+        // Now the EditText has a parent.  Add a button to set to the current
+        // page.
+        ViewGroup parent = (ViewGroup) editText.getParent();
+        Button button = new Button(getContext());
+        button.setText(R.string.pref_use_current);
+        button.setOnClickListener(new View.OnClickListener() {
+            public void onClick(View v) {
+                getEditText().setText(mCurrentPage);
+            }
+        });
+        if (parent instanceof LinearLayout) {
+            ((LinearLayout) parent).setGravity(Gravity.CENTER_HORIZONTAL);
+        }
+        parent.addView(button, ViewGroup.LayoutParams.WRAP_CONTENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT);
+    }
+
+    @Override
     protected void onDialogClosed(boolean positiveResult) {
         if (positiveResult) {
             String url = getEditText().getText().toString();
@@ -60,4 +91,26 @@
         }
         super.onDialogClosed(positiveResult);
     }
+
+    /**
+     * Set the current page of the browser.
+     * @param currentPage This String will replace the text in the EditText
+     *          when the user clicks the "Use current page" button.
+     */
+    /* package */ void setCurrentPage(String currentPage) {
+        mCurrentPage = currentPage;
+    }
+
+    @Override
+    protected void showDialog(Bundle state) {
+        super.showDialog(state);
+        // The dialog has its width set to wrap_content.  Change it to
+        // match_parent so there is more room to type in a url.
+        Window window = getDialog().getWindow();
+        View decorView = window.getDecorView();
+        WindowManager.LayoutParams params
+                = (WindowManager.LayoutParams) decorView.getLayoutParams();
+        params.width = ViewGroup.LayoutParams.MATCH_PARENT;
+        window.getWindowManager().updateViewLayout(decorView, params);
+    }
 }
diff --git a/src/com/android/browser/BrowserPreferencesPage.java b/src/com/android/browser/BrowserPreferencesPage.java
index 1370722..6426b99 100644
--- a/src/com/android/browser/BrowserPreferencesPage.java
+++ b/src/com/android/browser/BrowserPreferencesPage.java
@@ -39,6 +39,7 @@
         implements Preference.OnPreferenceChangeListener {
 
     private String LOGTAG = "BrowserPreferencesPage";
+    /* package */ static final String CURRENT_PAGE = "currentPage";
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -51,6 +52,8 @@
         e.setOnPreferenceChangeListener(this);
         e.setSummary(getPreferenceScreen().getSharedPreferences()
                 .getString(BrowserSettings.PREF_HOMEPAGE, null));
+        ((BrowserHomepagePreference) e).setCurrentPage(
+                getIntent().getStringExtra(CURRENT_PAGE));
         
         e = findPreference(BrowserSettings.PREF_EXTRAS_RESET_DEFAULTS);
         e.setOnPreferenceChangeListener(this);
@@ -70,6 +73,9 @@
         e = findPreference(BrowserSettings.PREF_DEFAULT_TEXT_ENCODING);
         e.setOnPreferenceChangeListener(this);
 
+        e = findPreference(BrowserSettings.PREF_CLEAR_HISTORY);
+        e.setOnPreferenceChangeListener(this);
+
         if (BrowserSettings.getInstance().showDebugSettings()) {
             addPreferencesFromResource(R.xml.debug_preferences);
         }
@@ -156,6 +162,13 @@
                 BrowserSettings.PREF_DEFAULT_TEXT_ENCODING)) {
             pref.setSummary((String) objValue);
             return true;
+        } else if (pref.getKey().equals(BrowserSettings.PREF_CLEAR_HISTORY)
+                && ((Boolean) objValue).booleanValue() == true) {
+            // Need to tell the browser to remove the parent/child relationship
+            // between tabs
+            setResult(RESULT_OK, (new Intent()).putExtra(Intent.EXTRA_TEXT,
+                    pref.getKey()));
+            return true;
         }
         
         return false;
diff --git a/src/com/android/browser/BrowserProvider.java b/src/com/android/browser/BrowserProvider.java
index 8e0929b..bf1f9d5 100644
--- a/src/com/android/browser/BrowserProvider.java
+++ b/src/com/android/browser/BrowserProvider.java
@@ -16,10 +16,9 @@
 
 package com.android.browser;
 
-import com.google.android.providers.GoogleSettings.Partner;
-
 import android.app.SearchManager;
-import android.backup.BackupManager;
+import android.app.SearchableInfo;
+import android.app.backup.BackupManager;
 import android.content.ComponentName;
 import android.content.ContentProvider;
 import android.content.ContentResolver;
@@ -38,20 +37,22 @@
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteOpenHelper;
 import android.net.Uri;
-import android.os.AsyncTask;
 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.server.search.SearchableInfo;
+import android.speech.RecognizerResultsIntent;
 import android.text.TextUtils;
-import android.text.util.Regex;
 import android.util.Log;
+import android.util.Patterns;
 import android.util.TypedValue;
 
+
 import java.io.File;
 import java.io.FilenameFilter;
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -72,11 +73,11 @@
         "bookmarks", "searches"
     };
     private static final String[] SUGGEST_PROJECTION = new String[] {
-            "_id", "url", "title", "bookmark"
+            "_id", "url", "title", "bookmark", "user_entered"
     };
     private static final String SUGGEST_SELECTION =
-            "url LIKE ? OR url LIKE ? OR url LIKE ? OR url LIKE ?"
-                + " OR title LIKE ?";
+            "(url LIKE ? OR url LIKE ? OR url LIKE ? OR url LIKE ?"
+                + " OR title LIKE ?) AND (bookmark = 1 OR user_entered = 1)";
     private String[] SUGGEST_ARGS = new String[5];
 
     // shared suggestion array index, make sure to match COLUMNS
@@ -84,10 +85,10 @@
     private static final int SUGGEST_COLUMN_INTENT_DATA_ID = 2;
     private static final int SUGGEST_COLUMN_TEXT_1_ID = 3;
     private static final int SUGGEST_COLUMN_TEXT_2_ID = 4;
-    private static final int SUGGEST_COLUMN_ICON_1_ID = 5;
-    private static final int SUGGEST_COLUMN_ICON_2_ID = 6;
-    private static final int SUGGEST_COLUMN_QUERY_ID = 7;
-    private static final int SUGGEST_COLUMN_FORMAT = 8;
+    private static final int SUGGEST_COLUMN_TEXT_2_URL_ID = 5;
+    private static final int SUGGEST_COLUMN_ICON_1_ID = 6;
+    private static final int SUGGEST_COLUMN_ICON_2_ID = 7;
+    private static final int SUGGEST_COLUMN_QUERY_ID = 8;
     private static final int SUGGEST_COLUMN_INTENT_EXTRA_DATA = 9;
 
     // shared suggestion columns
@@ -97,10 +98,10 @@
             SearchManager.SUGGEST_COLUMN_INTENT_DATA,
             SearchManager.SUGGEST_COLUMN_TEXT_1,
             SearchManager.SUGGEST_COLUMN_TEXT_2,
+            SearchManager.SUGGEST_COLUMN_TEXT_2_URL,
             SearchManager.SUGGEST_COLUMN_ICON_1,
             SearchManager.SUGGEST_COLUMN_ICON_2,
             SearchManager.SUGGEST_COLUMN_QUERY,
-            SearchManager.SUGGEST_COLUMN_FORMAT,
             SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA};
 
     private static final int MAX_SUGGESTION_SHORT_ENTRIES = 3;
@@ -157,7 +158,8 @@
     // 19 -> 20 Added thumbnail
     // 20 -> 21 Added touch_icon
     // 21 -> 22 Remove "clientid"
-    private static final int DATABASE_VERSION = 22;
+    // 22 -> 23 Added user_entered
+    private static final int DATABASE_VERSION = 23;
 
     // Regular expression which matches http://, followed by some stuff, followed by
     // optionally a trailing slash, all matched as separate groups.
@@ -165,21 +167,35 @@
 
     private SearchManager mSearchManager;
 
-    // The ID of the ColorStateList to be applied to urls of website suggestions, as derived from
-    // the current theme. This is not set until/unless beautifyUrl is called, at which point
-    // this variable caches the color value.
-    private static String mSearchUrlColorId;
-
     public BrowserProvider() {
     }
 
+    // XXX: This is a major hack to remove our dependency on gsf constants and
+    // its content provider. http://b/issue?id=2425179
+    static String getClientId(ContentResolver cr) {
+        String ret = "android-google";
+        Cursor c = null;
+        try {
+            c = cr.query(Uri.parse("content://com.google.settings/partner"),
+                    new String[] { "value" }, "name='client_id'", null, null);
+            if (c != null && c.moveToNext()) {
+                ret = c.getString(0);
+            }
+        } catch (RuntimeException ex) {
+            // fall through to return the default
+        } finally {
+            if (c != null) {
+                c.close();
+            }
+        }
+        return ret;
+    }
 
     private static CharSequence replaceSystemPropertyInString(Context context, CharSequence srcString) {
         StringBuffer sb = new StringBuffer();
         int lastCharLoc = 0;
 
-        final String client_id = Partner.getString(context.getContentResolver(),
-                                                    Partner.CLIENT_ID, "android-google");
+        final String client_id = getClientId(context.getContentResolver());
 
         for (int i = 0; i < srcString.length(); ++i) {
             char c = srcString.charAt(i);
@@ -231,7 +247,8 @@
                     "bookmark INTEGER," +
                     "favicon BLOB DEFAULT NULL," +
                     "thumbnail BLOB DEFAULT NULL," +
-                    "touch_icon BLOB DEFAULT NULL" +
+                    "touch_icon BLOB DEFAULT NULL," +
+                    "user_entered INTEGER" +
                     ");");
 
             final CharSequence[] bookmarks = mContext.getResources()
@@ -271,6 +288,9 @@
             if (oldVersion < 22) {
                 db.execSQL("DELETE FROM bookmarks WHERE (bookmark = 0 AND url LIKE \"%.google.%client=ms-%\")");
                 removeGears();
+            }
+            if (oldVersion < 23) {
+                db.execSQL("ALTER TABLE bookmarks ADD COLUMN user_entered INTEGER;");
             } else {
                 db.execSQL("DROP TABLE IF EXISTS bookmarks");
                 db.execSQL("DROP TABLE IF EXISTS searches");
@@ -279,15 +299,17 @@
         }
 
         private void removeGears() {
-            AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
-                public Void doInBackground(Void... unused) {
+            new Thread() {
+                @Override
+                public void run() {
+                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                     String browserDataDirString = mContext.getApplicationInfo().dataDir;
                     final String appPluginsDirString = "app_plugins";
                     final String gearsPrefix = "gears";
                     File appPluginsDir = new File(browserDataDirString + File.separator
                             + appPluginsDirString);
                     if (!appPluginsDir.exists()) {
-                        return null;
+                        return;
                     }
                     // Delete the Gears plugin files
                     File[] gearsFiles = appPluginsDir.listFiles(new FilenameFilter() {
@@ -306,10 +328,9 @@
                     File gearsDataDir = new File(browserDataDirString + File.separator
                             + gearsPrefix);
                     if (!gearsDataDir.exists()) {
-                        return null;
+                        return;
                     }
                     deleteDirectory(gearsDataDir);
-                    return null;
                 }
 
                 private void deleteDirectory(File currentDir) {
@@ -322,9 +343,7 @@
                     }
                     currentDir.delete();
                 }
-            };
-
-            task.execute();
+            }.start();
         }
     }
 
@@ -393,16 +412,9 @@
         if (Settings.System.getInt(context.getContentResolver(),
                 Settings.System.SHOW_WEB_SUGGESTIONS,
                 1 /* default on */) == 1) {
-            Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
-            intent.addCategory(Intent.CATEGORY_DEFAULT);
-            ResolveInfo info = context.getPackageManager().resolveActivity(
-                    intent, PackageManager.MATCH_DEFAULT_ONLY);
-            if (info != null) {
-                ComponentName googleSearchComponent =
-                        new ComponentName(info.activityInfo.packageName,
-                                info.activityInfo.name);
-                mSearchableInfo = mSearchManager.getSearchableInfo(
-                        googleSearchComponent, false);
+            ComponentName webSearchComponent = mSearchManager.getWebSearchActivity();
+            if (webSearchComponent != null) {
+                mSearchableInfo = mSearchManager.getSearchableInfo(webSearchComponent);
             }
         }
     }
@@ -429,22 +441,24 @@
 
     /*
      * Subclass AbstractCursor so we can combine multiple Cursors and add
-     * "Google Search".
+     * "Search the web".
      * Here are the rules.
      * 1. We only have MAX_SUGGESTION_LONG_ENTRIES in the list plus
-     *      "Google Search";
-     * 2. If bookmark/history entries are less than
-     *      (MAX_SUGGESTION_SHORT_ENTRIES -1), we include Google suggest.
+     *      "Search the web";
+     * 2. If bookmark/history entries has a match, "Search the web" shows up at
+     *      the second place. Otherwise, "Search the web" shows up at the first
+     *      place.
      */
     private class MySuggestionCursor extends AbstractCursor {
         private Cursor  mHistoryCursor;
         private Cursor  mSuggestCursor;
         private int     mHistoryCount;
         private int     mSuggestionCount;
-        private boolean mBeyondCursor;
+        private boolean mIncludeWebSearch;
         private String  mString;
         private int     mSuggestText1Id;
         private int     mSuggestText2Id;
+        private int     mSuggestText2UrlId;
         private int     mSuggestQueryId;
         private int     mSuggestIntentExtraDataId;
 
@@ -457,7 +471,7 @@
                 mSuggestionCount = MAX_SUGGESTION_LONG_ENTRIES - mHistoryCount;
             }
             mString = string;
-            mBeyondCursor = false;
+            mIncludeWebSearch = string.length() > 0;
 
             // Some web suggest providers only give suggestions and have no description string for
             // items. The order of the result columns may be different as well. So retrieve the
@@ -465,6 +479,7 @@
             if (mSuggestCursor == null) {
                 mSuggestText1Id = -1;
                 mSuggestText2Id = -1;
+                mSuggestText2UrlId = -1;
                 mSuggestQueryId = -1;
                 mSuggestIntentExtraDataId = -1;
             } else {
@@ -472,6 +487,8 @@
                                 SearchManager.SUGGEST_COLUMN_TEXT_1);
                 mSuggestText2Id = mSuggestCursor.getColumnIndex(
                                 SearchManager.SUGGEST_COLUMN_TEXT_2);
+                mSuggestText2UrlId = mSuggestCursor.getColumnIndex(
+                        SearchManager.SUGGEST_COLUMN_TEXT_2_URL);
                 mSuggestQueryId = mSuggestCursor.getColumnIndex(
                                 SearchManager.SUGGEST_COLUMN_QUERY);
                 mSuggestIntentExtraDataId = mSuggestCursor.getColumnIndex(
@@ -484,21 +501,30 @@
             if (mHistoryCursor == null) {
                 return false;
             }
+            if (mIncludeWebSearch) {
+                if (mHistoryCount == 0 && newPosition == 0) {
+                    return true;
+                } else if (mHistoryCount > 0) {
+                    if (newPosition == 0) {
+                        mHistoryCursor.moveToPosition(0);
+                        return true;
+                    } else if (newPosition == 1) {
+                        return true;
+                    }
+                }
+                newPosition--;
+            }
             if (mHistoryCount > newPosition) {
                 mHistoryCursor.moveToPosition(newPosition);
-                mBeyondCursor = false;
-            } else if (mHistoryCount + mSuggestionCount > newPosition) {
-                mSuggestCursor.moveToPosition(newPosition - mHistoryCount);
-                mBeyondCursor = false;
             } else {
-                mBeyondCursor = true;
+                mSuggestCursor.moveToPosition(newPosition - mHistoryCount);
             }
             return true;
         }
 
         @Override
         public int getCount() {
-            if (mString.length() > 0) {
+            if (mIncludeWebSearch) {
                 return mHistoryCount + mSuggestionCount + 1;
             } else {
                 return mHistoryCount + mSuggestionCount;
@@ -513,43 +539,69 @@
         @Override
         public String getString(int columnIndex) {
             if ((mPos != -1 && mHistoryCursor != null)) {
+                int type = -1; // 0: web search; 1: history; 2: suggestion
+                if (mIncludeWebSearch) {
+                    if (mHistoryCount == 0 && mPos == 0) {
+                        type = 0;
+                    } else if (mHistoryCount > 0) {
+                        if (mPos == 0) {
+                            type = 1;
+                        } else if (mPos == 1) {
+                            type = 0;
+                        }
+                    }
+                    if (type == -1) type = (mPos - 1) < mHistoryCount ? 1 : 2;
+                } else {
+                    type = mPos < mHistoryCount ? 1 : 2;
+                }
+
                 switch(columnIndex) {
                     case SUGGEST_COLUMN_INTENT_ACTION_ID:
-                        if (mHistoryCount > mPos) {
+                        if (type == 1) {
                             return Intent.ACTION_VIEW;
                         } else {
                             return Intent.ACTION_SEARCH;
                         }
 
                     case SUGGEST_COLUMN_INTENT_DATA_ID:
-                        if (mHistoryCount > mPos) {
+                        if (type == 1) {
                             return mHistoryCursor.getString(1);
                         } else {
                             return null;
                         }
 
                     case SUGGEST_COLUMN_TEXT_1_ID:
-                        if (mHistoryCount > mPos) {
+                        if (type == 0) {
+                            return mString;
+                        } else if (type == 1) {
                             return getHistoryTitle();
-                        } else if (!mBeyondCursor) {
+                        } else {
                             if (mSuggestText1Id == -1) return null;
                             return mSuggestCursor.getString(mSuggestText1Id);
-                        } else {
-                            return mString;
                         }
 
                     case SUGGEST_COLUMN_TEXT_2_ID:
-                        if (mHistoryCount > mPos) {
-                            return getHistorySubtitle();
-                        } else if (!mBeyondCursor) {
+                        if (type == 0) {
+                            return getContext().getString(R.string.search_the_web);
+                        } else if (type == 1) {
+                            return null;  // Use TEXT_2_URL instead
+                        } else {
                             if (mSuggestText2Id == -1) return null;
                             return mSuggestCursor.getString(mSuggestText2Id);
+                        }
+
+                    case SUGGEST_COLUMN_TEXT_2_URL_ID:
+                        if (type == 0) {
+                            return null;
+                        } else if (type == 1) {
+                            return getHistoryUrl();
                         } else {
-                            return getContext().getString(R.string.search_the_web);
+                            if (mSuggestText2UrlId == -1) return null;
+                            return mSuggestCursor.getString(mSuggestText2UrlId);
                         }
 
                     case SUGGEST_COLUMN_ICON_1_ID:
-                        if (mHistoryCount > mPos) {
+                        if (type == 1) {
                             if (mHistoryCursor.getInt(3) == 1) {
                                 return Integer.valueOf(
                                         R.drawable.ic_search_category_bookmark)
@@ -569,30 +621,27 @@
                         return "0";
 
                     case SUGGEST_COLUMN_QUERY_ID:
-                        if (mHistoryCount > mPos) {
+                        if (type == 0) {
+                            return mString;
+                        } else if (type == 1) {
                             // Return the url in the intent query column. This is ignored
                             // within the browser because our searchable is set to
                             // android:searchMode="queryRewriteFromData", but it is used by
                             // global search for query rewriting.
                             return mHistoryCursor.getString(1);
-                        } else if (!mBeyondCursor) {
+                        } else {
                             if (mSuggestQueryId == -1) return null;
                             return mSuggestCursor.getString(mSuggestQueryId);
-                        } else {
-                            return mString;
                         }
 
-                    case SUGGEST_COLUMN_FORMAT:
-                        return "html";
-
                     case SUGGEST_COLUMN_INTENT_EXTRA_DATA:
-                        if (mHistoryCount > mPos) {
+                        if (type == 0) {
                             return null;
-                        } else if (!mBeyondCursor) {
+                        } else if (type == 1) {
+                            return null;
+                        } else {
                             if (mSuggestIntentExtraDataId == -1) return null;
                             return mSuggestCursor.getString(mSuggestIntentExtraDataId);
-                        } else {
-                            return null;
                         }
                 }
             }
@@ -670,7 +719,7 @@
         private String getHistoryTitle() {
             String title = mHistoryCursor.getString(2 /* webpage title */);
             if (TextUtils.isEmpty(title) || TextUtils.getTrimmedLength(title) == 0) {
-                title = beautifyUrl(mHistoryCursor.getString(1 /* url */));
+                title = stripUrl(mHistoryCursor.getString(1 /* url */));
             }
             return title;
         }
@@ -682,29 +731,99 @@
          *
          * @return the subtitle string to use, or null if none
          */
-        private String getHistorySubtitle() {
+        private String getHistoryUrl() {
             String title = mHistoryCursor.getString(2 /* webpage title */);
             if (TextUtils.isEmpty(title) || TextUtils.getTrimmedLength(title) == 0) {
                 return null;
             } else {
-                return beautifyUrl(mHistoryCursor.getString(1 /* url */));
+                return stripUrl(mHistoryCursor.getString(1 /* url */));
             }
         }
 
-        /**
-         * Strips "http://" from the beginning of a url and "/" from the end,
-         * and adds html formatting to make it green.
-         */
-        private String beautifyUrl(String url) {
-            if (mSearchUrlColorId == null) {
-                // Get the color used for this purpose from the current theme.
-                TypedValue colorValue = new TypedValue();
-                getContext().getTheme().resolveAttribute(
-                        com.android.internal.R.attr.textColorSearchUrl, colorValue, true);
-                mSearchUrlColorId = Integer.toString(colorValue.resourceId);
-            }
+    }
 
-            return "<font color=\"@" + mSearchUrlColorId + "\">" + stripUrl(url) + "</font>";
+    private static class ResultsCursor extends AbstractCursor {
+        // Array indices for RESULTS_COLUMNS
+        private static final int RESULT_ACTION_ID = 1;
+        private static final int RESULT_DATA_ID = 2;
+        private static final int RESULT_TEXT_ID = 3;
+        private static final int RESULT_ICON_ID = 4;
+        private static final int RESULT_EXTRA_ID = 5;
+
+        private static final String[] RESULTS_COLUMNS = new String[] {
+                "_id",
+                SearchManager.SUGGEST_COLUMN_INTENT_ACTION,
+                SearchManager.SUGGEST_COLUMN_INTENT_DATA,
+                SearchManager.SUGGEST_COLUMN_TEXT_1,
+                SearchManager.SUGGEST_COLUMN_ICON_1,
+                SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA
+        };
+        private final ArrayList<String> mResults;
+        public ResultsCursor(ArrayList<String> results) {
+            mResults = results;
+        }
+        public int getCount() { return mResults.size(); }
+
+        public String[] getColumnNames() {
+            return RESULTS_COLUMNS;
+        }
+
+        public String getString(int column) {
+            switch (column) {
+                case RESULT_ACTION_ID:
+                    return RecognizerResultsIntent.ACTION_VOICE_SEARCH_RESULTS;
+                case RESULT_TEXT_ID:
+                // The data is used when the phone is in landscape mode.  We
+                // still want to show the result string.
+                case RESULT_DATA_ID:
+                    return mResults.get(mPos);
+                case RESULT_EXTRA_ID:
+                    // The Intent's extra data will store the index into
+                    // mResults so the BrowserActivity will know which result to
+                    // use.
+                    return Integer.toString(mPos);
+                case RESULT_ICON_ID:
+                    return Integer.valueOf(R.drawable.magnifying_glass)
+                            .toString();
+                default:
+                    return null;
+            }
+        }
+        public short getShort(int column) {
+            throw new UnsupportedOperationException();
+        }
+        public int getInt(int column) {
+            throw new UnsupportedOperationException();
+        }
+        public long getLong(int column) {
+            if ((mPos != -1) && column == 0) {
+                return mPos;        // use row# as the _id
+            }
+            throw new UnsupportedOperationException();
+        }
+        public float getFloat(int column) {
+            throw new UnsupportedOperationException();
+        }
+        public double getDouble(int column) {
+            throw new UnsupportedOperationException();
+        }
+        public boolean isNull(int column) {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    private ResultsCursor mResultsCursor;
+
+    /**
+     * Provide a set of results to be returned to query, intended to be used
+     * by the SearchDialog when the BrowserActivity is in voice search mode.
+     * @param results Strings to display in the dropdown from the SearchDialog
+     */
+    /* package */ void setQueryResults(ArrayList<String> results) {
+        if (results == null) {
+            mResultsCursor = null;
+        } else {
+            mResultsCursor = new ResultsCursor(results);
         }
     }
 
@@ -712,12 +831,16 @@
     public Cursor query(Uri url, String[] projectionIn, String selection,
             String[] selectionArgs, String sortOrder)
             throws IllegalStateException {
-        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
-
         int match = URI_MATCHER.match(url);
         if (match == -1) {
             throw new IllegalArgumentException("Unknown URL");
         }
+        if (match == URI_MATCH_SUGGEST && mResultsCursor != null) {
+            Cursor results = mResultsCursor;
+            mResultsCursor = null;
+            return results;
+        }
+        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
 
         if (match == URI_MATCH_SUGGEST || match == URI_MATCH_BOOKMARKS_SUGGEST) {
             String suggestSelection;
@@ -749,7 +872,7 @@
                     ORDER_BY, MAX_SUGGESTION_LONG_ENTRIES_STRING);
 
             if (match == URI_MATCH_BOOKMARKS_SUGGEST
-                    || Regex.WEB_URL_PATTERN.matcher(selectionArgs[0]).matches()) {
+                    || Patterns.WEB_URL.matcher(selectionArgs[0]).matches()) {
                 return new MySuggestionCursor(c, null, "");
             } else {
                 // get Google suggest if there is still space in the list
@@ -925,18 +1048,14 @@
             throw new IllegalArgumentException("Unknown URL");
         }
 
-        String id = null;
-        boolean isBookmarkTable = (match == URI_MATCH_BOOKMARKS_ID);
-        boolean changingBookmarks = false;
-
-        if (isBookmarkTable || match == URI_MATCH_SEARCHES_ID) {
+        if (match == URI_MATCH_BOOKMARKS_ID || match == URI_MATCH_SEARCHES_ID) {
             StringBuilder sb = new StringBuilder();
             if (where != null && where.length() > 0) {
                 sb.append("( ");
                 sb.append(where);
                 sb.append(" ) AND ");
             }
-            id = url.getPathSegments().get(1);
+            String id = url.getPathSegments().get(1);
             sb.append("_id = ");
             sb.append(id);
             where = sb.toString();
@@ -947,23 +1066,23 @@
         // Not all bookmark-table updates should be backed up.  Look to see
         // whether we changed the title, url, or "is a bookmark" state, and
         // request a backup if so.
-        if (isBookmarkTable) {
+        if (match == URI_MATCH_BOOKMARKS_ID || match == URI_MATCH_BOOKMARKS) {
+            boolean changingBookmarks = false;
             // Alterations to the bookmark field inherently change the bookmark
             // set, so we don't need to query the record; we know a priori that
             // we will need to back up this change.
             if (values.containsKey(BookmarkColumns.BOOKMARK)) {
                 changingBookmarks = true;
-            }
-            // changing the title or URL of a bookmark record requires a backup,
-            // but we don't know wether such an update is on a bookmark without
-            // querying the record
-            if (!changingBookmarks &&
-                    (values.containsKey(BookmarkColumns.TITLE)
-                     || values.containsKey(BookmarkColumns.URL))) {
-                // when isBookmarkTable is true, the 'id' var was assigned above
+            } else if ((values.containsKey(BookmarkColumns.TITLE)
+                     || values.containsKey(BookmarkColumns.URL))
+                     && values.containsKey(BookmarkColumns._ID)) {
+                // If a title or URL has been changed, check to see if it is to
+                // a bookmark.  The ID should have been included in the update,
+                // so use it.
                 Cursor cursor = cr.query(Browser.BOOKMARKS_URI,
                         new String[] { BookmarkColumns.BOOKMARK },
-                        "_id = " + id, null, null);
+                        BookmarkColumns._ID + " = "
+                        + values.getAsString(BookmarkColumns._ID), null, null);
                 if (cursor.moveToNext()) {
                     changingBookmarks = (cursor.getInt(0) != 0);
                 }
diff --git a/src/com/android/browser/BrowserSettings.java b/src/com/android/browser/BrowserSettings.java
index c3b6a08..3d5ca03 100644
--- a/src/com/android/browser/BrowserSettings.java
+++ b/src/com/android/browser/BrowserSettings.java
@@ -17,8 +17,7 @@
 
 package com.android.browser;
 
-import com.google.android.providers.GoogleSettings.Partner;
-
+import android.app.ActivityManager;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
@@ -61,27 +60,27 @@
     // NOTE: these defaults need to be kept in sync with the XML
     // until the performance of PreferenceManager.setDefaultValues()
     // is improved.
-    private boolean loadsImagesAutomatically = true;
-    private boolean javaScriptEnabled = true;
-    private boolean pluginsEnabled = true;
-    private boolean javaScriptCanOpenWindowsAutomatically = false;
-    private boolean showSecurityWarnings = true;
-    private boolean rememberPasswords = true;
-    private boolean saveFormData = true;
-    private boolean openInBackground = false;
+    // Note: boolean variables are set inside reset function.
+    private boolean loadsImagesAutomatically;
+    private boolean javaScriptEnabled;
+    private WebSettings.PluginState pluginState;
+    private boolean javaScriptCanOpenWindowsAutomatically;
+    private boolean showSecurityWarnings;
+    private boolean rememberPasswords;
+    private boolean saveFormData;
+    private boolean openInBackground;
     private String defaultTextEncodingName;
     private String homeUrl = "";
-    private boolean loginInitialized = false;
-    private boolean autoFitPage = true;
-    private boolean landscapeOnly = false;
-    private boolean loadsPageInOverviewMode = true;
-    private boolean showDebugSettings = false;
+    private boolean autoFitPage;
+    private boolean landscapeOnly;
+    private boolean loadsPageInOverviewMode;
+    private boolean showDebugSettings;
     // HTML5 API flags
-    private boolean appCacheEnabled = true;
-    private boolean databaseEnabled = true;
-    private boolean domStorageEnabled = true;
-    private boolean geolocationEnabled = true;
-    private boolean workersEnabled = true;  // only affects V8. JSC does not have a similar setting
+    private boolean appCacheEnabled;
+    private boolean databaseEnabled;
+    private boolean domStorageEnabled;
+    private boolean geolocationEnabled;
+    private boolean workersEnabled;  // only affects V8. JSC does not have a similar setting
     // HTML5 API configuration params
     private long appCacheMaxSize = Long.MAX_VALUE;
     private String appCachePath;  // default value set in loadFromDb().
@@ -106,9 +105,6 @@
     // The setting can be then toggled from the settings menu.
     private boolean showConsole = true;
 
-    // Browser only settings
-    private boolean doFlick = false;
-
     // Private preconfigured values
     private static int minimumFontSize = 8;
     private static int minimumLogicalFontSize = 8;
@@ -118,6 +114,7 @@
         WebSettings.TextSize.NORMAL;
     private static WebSettings.ZoomDensity zoomDensity =
         WebSettings.ZoomDensity.MEDIUM;
+    private static int pageCacheCapacity;
 
     // Preference keys that are used outside this class
     public final static String PREF_CLEAR_CACHE = "privacy_clear_cache";
@@ -189,7 +186,7 @@
             s.setUseWideViewPort(b.useWideViewPort);
             s.setLoadsImagesAutomatically(b.loadsImagesAutomatically);
             s.setJavaScriptEnabled(b.javaScriptEnabled);
-            s.setPluginsEnabled(b.pluginsEnabled);
+            s.setPluginState(b.pluginState);
             s.setJavaScriptCanOpenWindowsAutomatically(
                     b.javaScriptCanOpenWindowsAutomatically);
             s.setDefaultTextEncodingName(b.defaultTextEncodingName);
@@ -204,6 +201,7 @@
             s.setSaveFormData(b.saveFormData);
             s.setSavePassword(b.rememberPasswords);
             s.setLoadWithOverviewMode(b.loadsPageInOverviewMode);
+            s.setPageCacheCapacity(pageCacheCapacity);
 
             // WebView inside Browser doesn't want initial focus to be set.
             s.setNeedInitialFocus(false);
@@ -223,9 +221,7 @@
             s.setDatabasePath(b.databasePath);
             s.setGeolocationDatabasePath(b.geolocationDatabasePath);
 
-            // Enable/Disable the error console.
-            b.mTabControl.getBrowserActivity().setShouldShowErrorConsole(
-                    b.showDebugSettings && b.showConsole);
+            b.updateTabControlSettings();
         }
     }
 
@@ -254,7 +250,21 @@
         // Set the default value for the Geolocation database path.
         geolocationDatabasePath = ctx.getDir("geolocation", 0).getPath();
 
-        homeUrl = getFactoryResetHomeUrl(ctx);
+        if (p.getString(PREF_HOMEPAGE, "") == "") {
+            // No home page preferences is set, set it to default.
+            setHomePage(ctx, getFactoryResetHomeUrl(ctx));
+        }
+
+        // the cost of one cached page is ~3M (measured using nytimes.com). For
+        // low end devices, we only cache one page. For high end devices, we try
+        // to cache more pages, currently choose 5.
+        ActivityManager am = (ActivityManager) ctx
+                .getSystemService(Context.ACTIVITY_SERVICE);
+        if (am.getMemoryClass() > 16) {
+            pageCacheCapacity = 5;
+        } else {
+            pageCacheCapacity = 1;
+        }
 
         // Load the defaults from the xml
         // This call is TOO SLOW, need to manually keep the defaults
@@ -272,8 +282,8 @@
                 loadsImagesAutomatically);
         javaScriptEnabled = p.getBoolean("enable_javascript",
                 javaScriptEnabled);
-        pluginsEnabled = p.getBoolean("enable_plugins",
-                pluginsEnabled);
+        pluginState = WebSettings.PluginState.valueOf(
+                p.getString("plugin_state", pluginState.name()));
         javaScriptCanOpenWindowsAutomatically = !p.getBoolean(
             "block_popup_windows",
             !javaScriptCanOpenWindowsAutomatically);
@@ -287,7 +297,6 @@
                 CookieManager.getInstance().acceptCookie());
         CookieManager.getInstance().setAcceptCookie(accept_cookies);
         openInBackground = p.getBoolean("open_in_background", openInBackground);
-        loginInitialized = p.getBoolean("login_initialized", loginInitialized);
         textSize = WebSettings.TextSize.valueOf(
                 p.getString(PREF_TEXT_SIZE, textSize.name()));
         zoomDensity = WebSettings.ZoomDensity.valueOf(
@@ -299,9 +308,6 @@
                 p.getBoolean("landscape_only", landscapeOnly);
         if (landscapeOnlyTemp != landscapeOnly) {
             landscapeOnly = landscapeOnlyTemp;
-            mTabControl.getBrowserActivity().setRequestedOrientation(
-                    landscapeOnly ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
-                    : ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
         }
         useWideViewPort = true; // use wide view port for either setting
         if (autoFitPage) {
@@ -336,7 +342,6 @@
             tracing = p.getBoolean("enable_tracing", tracing);
             lightTouch = p.getBoolean("enable_light_touch", lightTouch);
             navDump = p.getBoolean("enable_nav_dump", navDump);
-            doFlick = p.getBoolean("enable_flick", doFlick);
             userAgent = Integer.parseInt(p.getString("user_agent", "0"));
         }
         // JS flags is loaded from DB even if showDebugSettings is false,
@@ -349,8 +354,6 @@
         // regardless of the setting we read here. This setting is only used after debug
         // is enabled.
         showConsole = p.getBoolean("javascript_console", showConsole);
-        mTabControl.getBrowserActivity().setShouldShowErrorConsole(
-                showDebugSettings && showConsole);
 
         // HTML5 API flags
         appCacheEnabled = p.getBoolean("enable_appcache", appCacheEnabled);
@@ -382,18 +385,6 @@
         homeUrl = url;
     }
 
-    public boolean isLoginInitialized() {
-        return loginInitialized;
-    }
-
-    public void setLoginInitialized(Context context) {
-        loginInitialized = true;
-        Editor ed = PreferenceManager.
-                getDefaultSharedPreferences(context).edit();
-        ed.putBoolean("login_initialized", loginInitialized);
-        ed.commit();
-    }
-
     public WebSettings.TextSize getTextSize() {
         return textSize;
     }
@@ -422,10 +413,6 @@
         return navDump;
     }
 
-    public boolean doFlick() {
-        return doFlick;
-    }
-
     public boolean showDebugSettings() {
         return showDebugSettings;
     }
@@ -482,6 +469,7 @@
      */
     /* package */void setTabControl(TabControl tabControl) {
         mTabControl = tabControl;
+        updateTabControlSettings();
     }
 
     /*
@@ -528,6 +516,15 @@
         db.clearHttpAuthUsernamePassword();
     }
 
+    private void updateTabControlSettings() {
+        // Enable/disable the error console.
+        mTabControl.getBrowserActivity().setShouldShowErrorConsole(
+            showDebugSettings && showConsole);
+        mTabControl.getBrowserActivity().setRequestedOrientation(
+            landscapeOnly ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
+            : ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
+    }
+
     private void maybeDisableWebsiteSettings(Context context) {
         PreferenceActivity activity = (PreferenceActivity) context;
         final PreferenceScreen screen = (PreferenceScreen)
@@ -561,6 +558,7 @@
     }
 
     /*package*/ void resetDefaultPreferences(Context ctx) {
+        reset();
         SharedPreferences p =
             PreferenceManager.getDefaultSharedPreferences(ctx);
         p.edit().clear().commit();
@@ -575,13 +573,39 @@
     private String getFactoryResetHomeUrl(Context context) {
         String url = context.getResources().getString(R.string.homepage_base);
         if (url.indexOf("{CID}") != -1) {
-            url = url.replace("{CID}", Partner.getString(context
-                    .getContentResolver(), Partner.CLIENT_ID, "android-google"));
+            url = url.replace("{CID}",
+                    BrowserProvider.getClientId(context.getContentResolver()));
         }
         return url;
     }
 
     // Private constructor that does nothing.
     private BrowserSettings() {
+        reset();
+    }
+
+    private void reset() {
+        // Private variables for settings
+        // NOTE: these defaults need to be kept in sync with the XML
+        // until the performance of PreferenceManager.setDefaultValues()
+        // is improved.
+        loadsImagesAutomatically = true;
+        javaScriptEnabled = true;
+        pluginState = WebSettings.PluginState.ON;
+        javaScriptCanOpenWindowsAutomatically = false;
+        showSecurityWarnings = true;
+        rememberPasswords = true;
+        saveFormData = true;
+        openInBackground = false;
+        autoFitPage = true;
+        landscapeOnly = false;
+        loadsPageInOverviewMode = true;
+        showDebugSettings = false;
+        // HTML5 API flags
+        appCacheEnabled = true;
+        databaseEnabled = true;
+        domStorageEnabled = true;
+        geolocationEnabled = true;
+        workersEnabled = true;  // only affects V8. JSC does not have a similar setting
     }
 }
diff --git a/src/com/android/browser/CombinedBookmarkHistoryActivity.java b/src/com/android/browser/CombinedBookmarkHistoryActivity.java
index a611d79..194956f 100644
--- a/src/com/android/browser/CombinedBookmarkHistoryActivity.java
+++ b/src/com/android/browser/CombinedBookmarkHistoryActivity.java
@@ -18,22 +18,36 @@
 
 import android.app.Activity;
 import android.app.TabActivity;
-import android.content.ContentResolver;
 import android.content.Intent;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
+import android.os.AsyncTask;
 import android.os.Bundle;
 import android.provider.Browser;
-import android.view.Window;
+import android.webkit.WebIconDatabase;
 import android.webkit.WebIconDatabase.IconListener;
 import android.widget.TabHost;
-import android.widget.TabHost.TabSpec;
 
 import java.util.HashMap;
 import java.util.Vector;
 
 public class CombinedBookmarkHistoryActivity extends TabActivity
         implements TabHost.OnTabChangeListener {
+    /**
+     * Used to inform BrowserActivity to remove the parent/child relationships
+     * from all the tabs.
+     */
+    private String mExtraData;
+    /**
+     * Intent to be passed to calling Activity when finished.  Keep a pointer to
+     * it locally so mExtraData can be added.
+     */
+    private Intent mResultData;
+    /**
+     * Result code to pass back to calling Activity when finished.
+     */
+    private int mResultCode;
+
     /* package */ static String BOOKMARKS_TAB = "bookmark";
     /* package */ static String VISITED_TAB = "visited";
     /* package */ static String HISTORY_TAB = "history";
@@ -85,34 +99,48 @@
 
         Bundle extras = getIntent().getExtras();
 
-        getIconListenerSet();
-        // Do this every time we create a new activity so that we get the
-        // newest icons.
-        Browser.requestAllIcons(getContentResolver(), null, sIconListenerSet);
-
         Intent bookmarksIntent = new Intent(this, BrowserBookmarksPage.class);
-        bookmarksIntent.putExtras(extras);
+        if (extras != null) {
+            bookmarksIntent.putExtras(extras);
+        }
         createTab(bookmarksIntent, R.string.tab_bookmarks,
                 R.drawable.browser_bookmark_tab, BOOKMARKS_TAB);
 
         Intent visitedIntent = new Intent(this, BrowserBookmarksPage.class);
         // Need to copy extras so the bookmarks activity and this one will be
         // different
-        Bundle visitedExtras = new Bundle(extras);
+        Bundle visitedExtras = extras == null ? new Bundle() : new Bundle(extras);
         visitedExtras.putBoolean("mostVisited", true);
         visitedIntent.putExtras(visitedExtras);
         createTab(visitedIntent, R.string.tab_most_visited,
                 R.drawable.browser_visited_tab, VISITED_TAB);
 
         Intent historyIntent = new Intent(this, BrowserHistoryPage.class);
-        historyIntent.putExtras(extras);
+        String defaultTab = null;
+        if (extras != null) {
+            historyIntent.putExtras(extras);
+            defaultTab = extras.getString(STARTING_TAB);
+        }
         createTab(historyIntent, R.string.tab_history,
                 R.drawable.browser_history_tab, HISTORY_TAB);
 
-        String defaultTab = extras.getString(STARTING_TAB);
         if (defaultTab != null) {
             getTabHost().setCurrentTab(2);
         }
+
+        // XXX: Must do this before launching the AsyncTask to avoid a
+        // potential crash if the icon database has not been created.
+        WebIconDatabase.getInstance();
+        // Do this every time we launch the activity in case a new favicon was
+        // added to the webkit db.
+        (new AsyncTask<Void, Void, Void>() {
+            public Void doInBackground(Void... v) {
+                Browser.requestAllIcons(getContentResolver(),
+                    Browser.BookmarkColumns.FAVICON + " is NULL",
+                    getIconListenerSet());
+                return null;
+            }
+        }).execute();
     }
 
     private void createTab(Intent intent, int labelResId, int iconResId,
@@ -132,5 +160,33 @@
         }
     }
 
-    
+    /**
+     * Store extra data in the Intent to return to the calling Activity to tell
+     * it to clear the parent/child relationships from all tabs.
+     */
+    /* package */ void removeParentChildRelationShips() {
+        mExtraData = BrowserSettings.PREF_CLEAR_HISTORY;
+    }
+
+    /**
+     * Custom setResult() method so that the Intent can have extra data attached
+     * if necessary.
+     * @param resultCode Uses same codes as Activity.setResult
+     * @param data Intent returned to onActivityResult.
+     */
+    /* package */ void setResultFromChild(int resultCode, Intent data) {
+        mResultCode = resultCode;
+        mResultData = data;
+    }
+
+    @Override
+    public void finish() {
+        if (mExtraData != null) {
+            mResultCode = RESULT_OK;
+            if (mResultData == null) mResultData = new Intent();
+            mResultData.putExtra(Intent.EXTRA_TEXT, mExtraData);
+        }
+        setResult(mResultCode, mResultData);
+        super.finish();
+    }
 }
diff --git a/src/com/android/browser/DateSortedExpandableListAdapter.java b/src/com/android/browser/DateSortedExpandableListAdapter.java
new file mode 100644
index 0000000..1d04493
--- /dev/null
+++ b/src/com/android/browser/DateSortedExpandableListAdapter.java
@@ -0,0 +1,347 @@
+/*
+ * 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.database.ContentObserver;
+import android.database.Cursor;
+import android.database.DataSetObserver;
+import android.os.Handler;
+import android.provider.BaseColumns;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.webkit.DateSorter;
+import android.widget.ExpandableListAdapter;
+import android.widget.ExpandableListView;
+import android.widget.TextView;
+
+import java.util.Vector;
+
+/**
+ * ExpandableListAdapter which separates data into categories based on date.
+ * Used for History and Downloads.
+ */
+public class DateSortedExpandableListAdapter implements ExpandableListAdapter {
+    // Array for each of our bins.  Each entry represents how many items are
+    // in that bin.
+    private int mItemMap[];
+    // This is our GroupCount.  We will have at most DateSorter.DAY_COUNT
+    // bins, less if the user has no items in one or more bins.
+    private int mNumberOfBins;
+    private Vector<DataSetObserver> mObservers;
+    private Cursor mCursor;
+    private DateSorter mDateSorter;
+    private int mDateIndex;
+    private int mIdIndex;
+    private Context mContext;
+
+    private class ChangeObserver extends ContentObserver {
+        public ChangeObserver() {
+            super(new Handler());
+        }
+
+        @Override
+        public boolean deliverSelfNotifications() {
+            return true;
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            refreshData();
+        }
+    }
+
+    public DateSortedExpandableListAdapter(Context context, Cursor cursor,
+            int dateIndex) {
+        mContext = context;
+        mDateSorter = new DateSorter(context);
+        mObservers = new Vector<DataSetObserver>();
+        mCursor = cursor;
+        mIdIndex = cursor.getColumnIndexOrThrow(BaseColumns._ID);
+        cursor.registerContentObserver(new ChangeObserver());
+        mDateIndex = dateIndex;
+        buildMap();
+    }
+
+    /**
+     * Set up the bins for determining which items belong to which groups.
+     */
+    private void buildMap() {
+        // The cursor is sorted by date
+        // The ItemMap will store the number of items in each bin.
+        int array[] = new int[DateSorter.DAY_COUNT];
+        // Zero out the array.
+        for (int j = 0; j < DateSorter.DAY_COUNT; j++) {
+            array[j] = 0;
+        }
+        mNumberOfBins = 0;
+        int dateIndex = -1;
+        if (mCursor.moveToFirst() && mCursor.getCount() > 0) {
+            while (!mCursor.isAfterLast()) {
+                long date = getLong(mDateIndex);
+                int index = mDateSorter.getIndex(date);
+                if (index > dateIndex) {
+                    mNumberOfBins++;
+                    if (index == DateSorter.DAY_COUNT - 1) {
+                        // We are already in the last bin, so it will
+                        // include all the remaining items
+                        array[index] = mCursor.getCount()
+                                - mCursor.getPosition();
+                        break;
+                    }
+                    dateIndex = index;
+                }
+                array[dateIndex]++;
+                mCursor.moveToNext();
+            }
+        }
+        mItemMap = array;
+    }
+
+    /**
+     * Get the byte array at cursorIndex from the Cursor.  Assumes the Cursor
+     * has already been moved to the correct position.  Along with
+     * {@link #getInt} and {@link #getString}, these are provided so the client
+     * does not need to access the Cursor directly
+     * @param cursorIndex Index to query the Cursor.
+     * @return corresponding byte array from the Cursor.
+     */
+    /* package */ byte[] getBlob(int cursorIndex) {
+        return mCursor.getBlob(cursorIndex);
+    }
+
+    /* package */ Context getContext() {
+        return mContext;
+    }
+
+    /**
+     * Get the integer at cursorIndex from the Cursor.  Assumes the Cursor has
+     * already been moved to the correct position.  Along with
+     * {@link #getBlob} and {@link #getString}, these are provided so the client
+     * does not need to access the Cursor directly
+     * @param cursorIndex Index to query the Cursor.
+     * @return corresponding integer from the Cursor.
+     */
+    /* package */ int getInt(int cursorIndex) {
+        return mCursor.getInt(cursorIndex);
+    }
+
+    /**
+     * Get the long at cursorIndex from the Cursor.  Assumes the Cursor has
+     * already been moved to the correct position.
+     */
+    /* package */ long getLong(int cursorIndex) {
+        return mCursor.getLong(cursorIndex);
+    }
+
+    /**
+     * Get the String at cursorIndex from the Cursor.  Assumes the Cursor has
+     * already been moved to the correct position.  Along with
+     * {@link #getInt} and {@link #getInt}, these are provided so the client
+     * does not need to access the Cursor directly
+     * @param cursorIndex Index to query the Cursor.
+     * @return corresponding String from the Cursor.
+     */
+    /* package */ String getString(int cursorIndex) {
+        return mCursor.getString(cursorIndex);
+    }
+
+    /**
+     * Determine which group an item belongs to.
+     * @param childId ID of the child view in question.
+     * @return int Group position of the containing group.
+    /* package */ int groupFromChildId(long childId) {
+        int group = -1;
+        for (mCursor.moveToFirst(); !mCursor.isAfterLast();
+                mCursor.moveToNext()) {
+            if (getLong(mIdIndex) == childId) {
+                int bin = mDateSorter.getIndex(getLong(mDateIndex));
+                // bin is the same as the group if the number of bins is the
+                // same as DateSorter
+                if (mDateSorter.DAY_COUNT == mNumberOfBins) return bin;
+                // There are some empty bins.  Find the corresponding group.
+                group = 0;
+                for (int i = 0; i < bin; i++) {
+                    if (mItemMap[i] != 0) group++;
+                }
+                break;
+            }
+        }
+        return group;
+    }
+
+    /**
+     * Translates from a group position in the ExpandableList to a bin.  This is
+     * necessary because some groups have no history items, so we do not include
+     * those in the ExpandableList.
+     * @param groupPosition Position in the ExpandableList's set of groups
+     * @return The corresponding bin that holds that group.
+     */
+    private int groupPositionToBin(int groupPosition) {
+        if (groupPosition < 0 || groupPosition >= DateSorter.DAY_COUNT) {
+            throw new AssertionError("group position out of range");
+        }
+        if (DateSorter.DAY_COUNT == mNumberOfBins || 0 == mNumberOfBins) {
+            // In the first case, we have exactly the same number of bins
+            // as our maximum possible, so there is no need to do a
+            // conversion
+            // The second statement is in case this method gets called when
+            // the array is empty, in which case the provided groupPosition
+            // will do fine.
+            return groupPosition;
+        }
+        int arrayPosition = -1;
+        while (groupPosition > -1) {
+            arrayPosition++;
+            if (mItemMap[arrayPosition] != 0) {
+                groupPosition--;
+            }
+        }
+        return arrayPosition;
+    }
+
+    /**
+     * Move the cursor to the position indicated.
+     * @param packedPosition Position in packed position representation.
+     * @return True on success, false otherwise.
+     */
+    boolean moveCursorToPackedChildPosition(long packedPosition) {
+        if (ExpandableListView.getPackedPositionType(packedPosition) !=
+                ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
+            return false;
+        }
+        int groupPosition = ExpandableListView.getPackedPositionGroup(
+                packedPosition);
+        int childPosition = ExpandableListView.getPackedPositionChild(
+                packedPosition);
+        return moveCursorToChildPosition(groupPosition, childPosition);
+    }
+
+    /**
+     * Move the cursor the the position indicated.
+     * @param groupPosition Index of the group containing the desired item.
+     * @param childPosition Index of the item within the specified group.
+     * @return boolean False if the cursor is closed, so the Cursor was not
+     *      moved.  True on success.
+     */
+    /* package */ boolean moveCursorToChildPosition(int groupPosition,
+            int childPosition) {
+        if (mCursor.isClosed()) return false;
+        groupPosition = groupPositionToBin(groupPosition);
+        int index = childPosition;
+        for (int i = 0; i < groupPosition; i++) {
+            index += mItemMap[i];
+        }
+        return mCursor.moveToPosition(index);
+    }
+
+    /* package */ void refreshData() {
+        if (mCursor.isClosed()) {
+            return;
+        }
+        mCursor.requery();
+        buildMap();
+        for (DataSetObserver o : mObservers) {
+            o.onChanged();
+        }
+    }
+
+    public View getGroupView(int groupPosition, boolean isExpanded,
+            View convertView, ViewGroup parent) {
+        TextView item;
+        if (null == convertView || !(convertView instanceof TextView)) {
+            LayoutInflater factory = LayoutInflater.from(mContext);
+            item = (TextView) factory.inflate(R.layout.history_header, null);
+        } else {
+            item = (TextView) convertView;
+        }
+        String label = mDateSorter.getLabel(groupPositionToBin(groupPosition));
+        item.setText(label);
+        return item;
+    }
+
+    public View getChildView(int groupPosition, int childPosition,
+            boolean isLastChild, View convertView, ViewGroup parent) {
+        return null;
+    }
+
+    public boolean areAllItemsEnabled() {
+        return true;
+    }
+
+    public boolean isChildSelectable(int groupPosition, int childPosition) {
+        return true;
+    }
+
+    public int getGroupCount() {
+        return mNumberOfBins;
+    }
+
+    public int getChildrenCount(int groupPosition) {
+        return mItemMap[groupPositionToBin(groupPosition)];
+    }
+
+    public Object getGroup(int groupPosition) {
+        return null;
+    }
+
+    public Object getChild(int groupPosition, int childPosition) {
+        return null;
+    }
+
+    public long getGroupId(int groupPosition) {
+        return groupPosition;
+    }
+
+    public long getChildId(int groupPosition, int childPosition) {
+        if (moveCursorToChildPosition(groupPosition, childPosition)) {
+            return getLong(mIdIndex);
+        }
+        return 0;
+    }
+
+    public boolean hasStableIds() {
+        return true;
+    }
+
+    public void registerDataSetObserver(DataSetObserver observer) {
+        mObservers.add(observer);
+    }
+
+    public void unregisterDataSetObserver(DataSetObserver observer) {
+        mObservers.remove(observer);
+    }
+
+    public void onGroupExpanded(int groupPosition) {
+    }
+
+    public void onGroupCollapsed(int groupPosition) {
+    }
+
+    public long getCombinedChildId(long groupId, long childId) {
+        return childId;
+    }
+
+    public long getCombinedGroupId(long groupId) {
+        return groupId;
+    }
+
+    public boolean isEmpty() {
+        return mCursor.isClosed() || mCursor.getCount() == 0;
+    }
+}
diff --git a/src/com/android/browser/DownloadTouchIcon.java b/src/com/android/browser/DownloadTouchIcon.java
index 07d2d3a..b5369ae 100644
--- a/src/com/android/browser/DownloadTouchIcon.java
+++ b/src/com/android/browser/DownloadTouchIcon.java
@@ -27,6 +27,7 @@
 import android.provider.Browser;
 import android.webkit.WebView;
 
+
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpResponse;
 import org.apache.http.client.methods.HttpGet;
@@ -36,65 +37,69 @@
 import java.io.IOException;
 import java.io.InputStream;
 
-class DownloadTouchIcon extends AsyncTask<String, Void, Bitmap> {
+class DownloadTouchIcon extends AsyncTask<String, Void, Void> {
     private final ContentResolver mContentResolver;
-    private final Cursor mCursor;
+    private Cursor mCursor;
     private final String mOriginalUrl;
     private final String mUrl;
     private final String mUserAgent;
-    /* package */ BrowserActivity mActivity;
+    /* package */ Tab mTab;
 
-    public DownloadTouchIcon(BrowserActivity activity, ContentResolver cr,
-            Cursor c, WebView view) {
-        mActivity = activity;
+    public DownloadTouchIcon(Tab tab, ContentResolver cr, WebView view) {
+        mTab = tab;
         mContentResolver = cr;
-        mCursor = c;
         // Store these in case they change.
         mOriginalUrl = view.getOriginalUrl();
         mUrl = view.getUrl();
         mUserAgent = view.getSettings().getUserAgentString();
     }
 
-    public DownloadTouchIcon(ContentResolver cr, Cursor c, String url) {
-        mActivity = null;
+    public DownloadTouchIcon(ContentResolver cr, String url) {
+        mTab = null;
         mContentResolver = cr;
-        mCursor = c;
         mOriginalUrl = null;
         mUrl = url;
         mUserAgent = null;
     }
 
     @Override
-    public Bitmap doInBackground(String... values) {
-        String url = values[0];
+    public Void doInBackground(String... values) {
+        mCursor = BrowserBookmarksAdapter.queryBookmarksForUrl(mContentResolver,
+                mOriginalUrl, mUrl, true);
+        if (mCursor != null && mCursor.getCount() > 0) {
+            String url = values[0];
 
-        AndroidHttpClient client = AndroidHttpClient.newInstance(
-                mUserAgent);
-        HttpGet request = new HttpGet(url);
+            AndroidHttpClient client = AndroidHttpClient.newInstance(
+                    mUserAgent);
+            HttpGet request = new HttpGet(url);
 
-        // Follow redirects
-        HttpClientParams.setRedirecting(client.getParams(), true);
+            // Follow redirects
+            HttpClientParams.setRedirecting(client.getParams(), true);
 
-        try {
-            HttpResponse response = client.execute(request);
+            try {
+                HttpResponse response = client.execute(request);
 
-            if (response.getStatusLine().getStatusCode() == 200) {
-                HttpEntity entity = response.getEntity();
-                if (entity != null) {
-                    InputStream content = entity.getContent();
-                    if (content != null) {
-                        Bitmap icon = BitmapFactory.decodeStream(
-                                content, null, null);
-                        return icon;
+                if (response.getStatusLine().getStatusCode() == 200) {
+                    HttpEntity entity = response.getEntity();
+                    if (entity != null) {
+                        InputStream content = entity.getContent();
+                        if (content != null) {
+                            Bitmap icon = BitmapFactory.decodeStream(
+                                    content, null, null);
+                            storeIcon(icon);
+                        }
                     }
                 }
+            } catch (IllegalArgumentException ex) {
+                request.abort();
+            } catch (IOException ex) {
+                request.abort();
+            } finally {
+                client.close();
             }
-        } catch (IllegalArgumentException ex) {
-            request.abort();
-        } catch (IOException ex) {
-            request.abort();
-        } finally {
-            client.close();
+        }
+        if (mCursor != null) {
+            mCursor.close();
         }
         return null;
     }
@@ -106,12 +111,11 @@
         }
     }
 
-    @Override
-    public void onPostExecute(Bitmap icon) {
+    private void storeIcon(Bitmap icon) {
         // Do this first in case the download failed.
-        if (mActivity != null) {
+        if (mTab != null) {
             // Remove the touch icon loader from the BrowserActivity.
-            mActivity.mTouchIconLoader = null;
+            mTab.mTouchIconLoader = null;
         }
 
         if (icon == null || mCursor == null || isCancelled()) {
@@ -131,6 +135,5 @@
                         values, null, null);
             } while (mCursor.moveToNext());
         }
-        mCursor.close();
     }
 }
diff --git a/src/com/android/browser/ErrorConsoleView.java b/src/com/android/browser/ErrorConsoleView.java
index 9f1873c..ca5fed4 100644
--- a/src/com/android/browser/ErrorConsoleView.java
+++ b/src/com/android/browser/ErrorConsoleView.java
@@ -18,11 +18,13 @@
 
 import android.content.Context;
 import android.database.DataSetObserver;
+import android.graphics.Color;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.View.OnClickListener;
+import android.webkit.ConsoleMessage;
 import android.webkit.WebView;
 import android.widget.Button;
 import android.widget.EditText;
@@ -55,7 +57,7 @@
     // Before we've been asked to display the console, cache any messages that should
     // be added to the console. Then when we do display the console, add them to the view
     // then.
-    private Vector<ErrorConsoleMessage> mErrorMessageCache;
+    private Vector<ConsoleMessage> mErrorMessageCache;
 
     public ErrorConsoleView(Context context) {
         super(context);
@@ -108,8 +110,8 @@
 
         // Add any cached messages to the list now that we've assembled the view.
         if (mErrorMessageCache != null) {
-            for (ErrorConsoleMessage msg : mErrorMessageCache) {
-                mErrorList.addErrorMessage(msg.getMessage(), msg.getSourceID(), msg.getLineNumber());
+            for (ConsoleMessage msg : mErrorMessageCache) {
+                mErrorList.addErrorMessage(msg);
             }
             mErrorMessageCache.clear();
         }
@@ -120,14 +122,14 @@
     /**
      * Adds a message to the set of messages the console uses.
      */
-    public void addErrorMessage(String msg, String sourceId, int lineNumber) {
+    public void addErrorMessage(ConsoleMessage consoleMessage) {
         if (mSetupComplete) {
-            mErrorList.addErrorMessage(msg, sourceId, lineNumber);
+            mErrorList.addErrorMessage(consoleMessage);
         } else {
             if (mErrorMessageCache == null) {
-                mErrorMessageCache = new Vector<ErrorConsoleMessage>();
+                mErrorMessageCache = new Vector<ConsoleMessage>();
             }
-            mErrorMessageCache.add(new ErrorConsoleMessage(msg, sourceId, lineNumber));
+            mErrorMessageCache.add(consoleMessage);
         }
     }
 
@@ -215,8 +217,8 @@
             setAdapter(mConsoleMessages);
         }
 
-        public void addErrorMessage(String msg, String sourceId, int lineNumber) {
-            mConsoleMessages.add(msg, sourceId, lineNumber);
+        public void addErrorMessage(ConsoleMessage consoleMessage) {
+            mConsoleMessages.add(consoleMessage);
             setSelection(mConsoleMessages.getCount());
         }
 
@@ -231,11 +233,11 @@
         private static class ErrorConsoleMessageList extends android.widget.BaseAdapter
                 implements android.widget.ListAdapter {
 
-            private Vector<ErrorConsoleMessage> mMessages;
+            private Vector<ConsoleMessage> mMessages;
             private LayoutInflater mInflater;
 
             public ErrorConsoleMessageList(Context context) {
-                mMessages = new Vector<ErrorConsoleMessage>();
+                mMessages = new Vector<ConsoleMessage>();
                 mInflater = (LayoutInflater)context.getSystemService(
                         Context.LAYOUT_INFLATER_SERVICE);
             }
@@ -243,8 +245,8 @@
             /**
              * Add a new message to the list and update the View.
              */
-            public void add(String msg, String sourceID, int lineNumber) {
-                mMessages.add(new ErrorConsoleMessage(msg, sourceID, lineNumber));
+            public void add(ConsoleMessage consoleMessage) {
+                mMessages.add(consoleMessage);
                 notifyDataSetChanged();
             }
 
@@ -288,7 +290,7 @@
              */
             public View getView(int position, View convertView, ViewGroup parent) {
                 View view;
-                ErrorConsoleMessage error = mMessages.get(position);
+                ConsoleMessage error = mMessages.get(position);
 
                 if (error == null) {
                     return null;
@@ -302,38 +304,26 @@
 
                 TextView headline = (TextView) view.findViewById(android.R.id.text1);
                 TextView subText = (TextView) view.findViewById(android.R.id.text2);
-                headline.setText(error.getSourceID() + ":" + error.getLineNumber());
-                subText.setText(error.getMessage());
+                headline.setText(error.sourceId() + ":" + error.lineNumber());
+                subText.setText(error.message());
+                switch (error.messageLevel()) {
+                    case ERROR:
+                        subText.setTextColor(Color.RED);
+                        break;
+                    case WARNING:
+                        // Orange
+                        subText.setTextColor(Color.rgb(255,192,0));
+                        break;
+                    case TIP:
+                        subText.setTextColor(Color.BLUE);
+                        break;
+                    default:
+                        subText.setTextColor(Color.LTGRAY);
+                        break;
+                }
                 return view;
             }
 
         }
     }
-
-    /**
-     * This class holds the data for a single error message in the console.
-     */
-    private static class ErrorConsoleMessage {
-        private String mMessage;
-        private String mSourceID;
-        private int mLineNumber;
-
-        public ErrorConsoleMessage(String msg, String sourceID, int lineNumber) {
-            mMessage = msg;
-            mSourceID = sourceID;
-            mLineNumber = lineNumber;
-        }
-
-        public String getMessage() {
-            return mMessage;
-        }
-
-        public String getSourceID() {
-            return mSourceID;
-        }
-
-        public int getLineNumber() {
-            return mLineNumber;
-        }
-    }
 }
diff --git a/src/com/android/browser/EventLogTags.logtags b/src/com/android/browser/EventLogTags.logtags
new file mode 100644
index 0000000..b3834cf
--- /dev/null
+++ b/src/com/android/browser/EventLogTags.logtags
@@ -0,0 +1,15 @@
+# See system/core/logcat/event.logtags for a description of the format of this file.
+
+option java_package com.android.browser
+
+# This event is logged when a user adds a new bookmark. This could just be a boolean,
+# but if lots of users add the same bookmark it could be a default bookmark on the browser.
+# Second parameter is where the bookmark was added from, currently history or bookmarks view.
+70103 browser_bookmark_added (url|3), (where|3)
+
+# This event is logged after a page has finished loading. It is sending back the page url,
+# and how long it took to load the page. Could maybe also tell the kind of connection (2g, 3g, WiFi)?
+70104 browser_page_loaded (url|3), (time|2|3)
+
+# This event is logged when the user navigates to a new page, sending the time spent on the current page.
+70105 browser_timeonpage (url|3), (time|2|3)
diff --git a/src/com/android/browser/FetchUrlMimeType.java b/src/com/android/browser/FetchUrlMimeType.java
index 0081d32..1e4debf 100644
--- a/src/com/android/browser/FetchUrlMimeType.java
+++ b/src/com/android/browser/FetchUrlMimeType.java
@@ -58,7 +58,7 @@
         mValues = values[0];
 
         // Check to make sure we have a URI to download
-        String uri = mValues.getAsString(Downloads.COLUMN_URI);
+        String uri = mValues.getAsString(Downloads.Impl.COLUMN_URI);
         if (uri == null || uri.length() == 0) {
             return null;
         }
@@ -66,15 +66,15 @@
         // User agent is likely to be null, though the AndroidHttpClient
         // seems ok with that.
         AndroidHttpClient client = AndroidHttpClient.newInstance(
-                mValues.getAsString(Downloads.COLUMN_USER_AGENT));
+                mValues.getAsString(Downloads.Impl.COLUMN_USER_AGENT));
         HttpHead request = new HttpHead(uri);
 
-        String cookie = mValues.getAsString(Downloads.COLUMN_COOKIE_DATA);
+        String cookie = mValues.getAsString(Downloads.Impl.COLUMN_COOKIE_DATA);
         if (cookie != null && cookie.length() > 0) {
             request.addHeader("Cookie", cookie);
         }
 
-        String referer = mValues.getAsString(Downloads.COLUMN_REFERER);
+        String referer = mValues.getAsString(Downloads.Impl.COLUMN_REFERER);
         if (referer != null && referer.length() > 0) {
             request.addHeader("Referer", referer);
         }
@@ -110,25 +110,24 @@
    @Override
     public void onPostExecute(String mimeType) {
        if (mimeType != null) {
-           String url = mValues.getAsString(Downloads.COLUMN_URI);
+           String url = mValues.getAsString(Downloads.Impl.COLUMN_URI);
            if (mimeType.equalsIgnoreCase("text/plain") ||
                    mimeType.equalsIgnoreCase("application/octet-stream")) {
                String newMimeType =
                        MimeTypeMap.getSingleton().getMimeTypeFromExtension(
                            MimeTypeMap.getFileExtensionFromUrl(url));
                if (newMimeType != null) {
-                   mValues.put(Downloads.COLUMN_MIME_TYPE, newMimeType);
+                   mValues.put(Downloads.Impl.COLUMN_MIME_TYPE, newMimeType);
                }
            }
            String filename = URLUtil.guessFileName(url,
                    null, mimeType);
-           mValues.put(Downloads.COLUMN_FILE_NAME_HINT, filename);
+           mValues.put(Downloads.Impl.COLUMN_FILE_NAME_HINT, filename);
        }
 
        // Start the download
        final Uri contentUri =
-           mActivity.getContentResolver().insert(Downloads.CONTENT_URI, mValues);
-       mActivity.viewDownloads(contentUri);
+           mActivity.getContentResolver().insert(Downloads.Impl.CONTENT_URI, mValues);
     }
 
 }
diff --git a/src/com/android/browser/FindDialog.java b/src/com/android/browser/FindDialog.java
index df212d0..45c8016 100644
--- a/src/com/android/browser/FindDialog.java
+++ b/src/com/android/browser/FindDialog.java
@@ -18,10 +18,7 @@
 
 import android.app.Dialog;
 import android.content.Context;
-import android.content.res.Configuration;
 import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
 import android.text.Editable;
 import android.text.Spannable;
 import android.text.TextWatcher;
@@ -97,13 +94,6 @@
         setCanceledOnTouchOutside(true);
     }
 
-    /* package */ void onConfigurationChanged(Configuration newConfig) {
-        // FIXME: Would like to call mWebView.findAll again, so that the
-        // matches would refresh, but the new picture has not yet been
-        // created, so it is too soon.
-        mEditText.getText().clear();
-    }
-
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -113,7 +103,7 @@
 
         setContentView(R.layout.browser_find);
 
-        theWindow.setLayout(ViewGroup.LayoutParams.FILL_PARENT,
+        theWindow.setLayout(ViewGroup.LayoutParams.MATCH_PARENT,
                 ViewGroup.LayoutParams.WRAP_CONTENT);
 
         mEditText = (EditText) findViewById(R.id.edit);
@@ -139,7 +129,7 @@
     public void dismiss() {
         super.dismiss();
         mBrowserActivity.closeFind();
-        mWebView.clearMatches();
+        mWebView.notifyFindDialogDismissed();
     }
 
     @Override
diff --git a/src/com/android/browser/GeolocationPermissionsPrompt.java b/src/com/android/browser/GeolocationPermissionsPrompt.java
index a21bc3e..95c5415 100755
--- a/src/com/android/browser/GeolocationPermissionsPrompt.java
+++ b/src/com/android/browser/GeolocationPermissionsPrompt.java
@@ -20,6 +20,7 @@
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.util.AttributeSet;
+import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.webkit.WebView;
@@ -28,6 +29,7 @@
 import android.widget.CheckBox;
 import android.widget.LinearLayout;
 import android.widget.TextView;
+import android.widget.Toast;
 
 public class GeolocationPermissionsPrompt extends LinearLayout {
     private LinearLayout mInner;
@@ -44,15 +46,26 @@
 
     public GeolocationPermissionsPrompt(Context context, AttributeSet attrs) {
         super(context, attrs);
-        LayoutInflater factory = LayoutInflater.from(context);
-        factory.inflate(R.layout.geolocation_permissions_prompt, this);
+    }
 
+    void init() {
         mInner = (LinearLayout) findViewById(R.id.inner);
         mMessage = (TextView) findViewById(R.id.message);
         mShareButton = (Button) findViewById(R.id.share_button);
         mDontShareButton = (Button) findViewById(R.id.dont_share_button);
         mRemember = (CheckBox) findViewById(R.id.remember);
-        setButtonClickListeners();
+
+        final GeolocationPermissionsPrompt me = this;
+        mShareButton.setOnClickListener(new View.OnClickListener() {
+            public void onClick(View v) {
+                me.handleButtonClick(true);
+            }
+        });
+        mDontShareButton.setOnClickListener(new View.OnClickListener() {
+            public void onClick(View v) {
+                me.handleButtonClick(false);
+            }
+        });
     }
 
     /**
@@ -77,28 +90,22 @@
     }
 
     /**
-     * Sets the on click listeners for the buttons.
-     */
-    private void setButtonClickListeners() {
-        final GeolocationPermissionsPrompt me = this;
-        mShareButton.setOnClickListener(new View.OnClickListener() {
-            public void onClick(View v) {
-                me.handleButtonClick(true);
-            }
-        });
-        mDontShareButton.setOnClickListener(new View.OnClickListener() {
-            public void onClick(View v) {
-                me.handleButtonClick(false);
-            }
-        });
-    }
-
-    /**
      * Handles a click on one the buttons by invoking the callback.
      */
     private void handleButtonClick(boolean allow) {
-        boolean remember = mRemember.isChecked();
         showDialog(false);
+
+        boolean remember = mRemember.isChecked();
+        if (remember) {
+            Toast toast = Toast.makeText(
+                    getContext(),
+                    allow ? R.string.geolocation_permissions_prompt_toast_allowed :
+                            R.string.geolocation_permissions_prompt_toast_disallowed,
+                    Toast.LENGTH_LONG);
+            toast.setGravity(Gravity.BOTTOM, 0, 0);
+            toast.show();
+        }
+
         mCallback.invoke(mOrigin, allow, remember);
     }
 
diff --git a/src/com/android/browser/HistoryItem.java b/src/com/android/browser/HistoryItem.java
index 51cb026..72e1b19 100644
--- a/src/com/android/browser/HistoryItem.java
+++ b/src/com/android/browser/HistoryItem.java
@@ -47,6 +47,7 @@
                 if (isChecked) {
                     Bookmarks.addBookmark(mContext,
                             mContext.getContentResolver(), mUrl, getName(), null, true);
+                    LogTag.logBookmarkAdded(mUrl, "history");
                 } else {
                     Bookmarks.removeFromBookmarks(mContext,
                             mContext.getContentResolver(), mUrl, getName());
diff --git a/src/com/android/browser/LogTag.java b/src/com/android/browser/LogTag.java
new file mode 100644
index 0000000..38fea47
--- /dev/null
+++ b/src/com/android/browser/LogTag.java
@@ -0,0 +1,59 @@
+/*
+ * 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.util.EventLog;
+
+public class LogTag {
+
+    /**
+     * Log when the user is adding a new bookmark.
+     *
+     * @param url the url of the new bookmark.
+     * @param where the location from where the bookmark was added
+     */
+    public static void logBookmarkAdded(String url, String where) {
+        EventLog.writeEvent(EventLogTags.BROWSER_BOOKMARK_ADDED, url + "|"
+            + where);
+    }
+
+    /**
+     * Log when a page has finished loading with how much
+     * time the browser used to load the page.
+     *
+     * Note that a redirect will restart the timer, so this time is not
+     * always how long it takes for the user to load a page.
+     *
+     * @param url the url of that page that finished loading.
+     * @param duration the time the browser spent loading the page.
+     */
+    public static void logPageFinishedLoading(String url, long duration) {
+        EventLog.writeEvent(EventLogTags.BROWSER_PAGE_LOADED, url + "|"
+            + duration);
+    }
+
+    /**
+     * log the time the user has spent on a webpage
+     *
+     * @param url the url of the page that is being logged (old page).
+     * @param duration the time spent on the webpage.
+     */
+    public static void logTimeOnPage(String url, long duration) {
+        EventLog.writeEvent(EventLogTags.BROWSER_TIMEONPAGE, url + "|"
+            + duration);
+    }
+}
diff --git a/src/com/android/browser/MeshTracker.java b/src/com/android/browser/MeshTracker.java
index aa7099f..c4b6332 100644
--- a/src/com/android/browser/MeshTracker.java
+++ b/src/com/android/browser/MeshTracker.java
@@ -38,7 +38,7 @@
             mRows = rows;
             mCols = cols;
         }
-        
+
         private void rebuildPatch() {
             mPatch.setCubicBoundary(mCubics, 0, mRows, mCols);
         }
@@ -165,7 +165,7 @@
     public void setBGPaint(Paint paint) {
         mBGPaint = paint;
     }
-    
+
     @Override public void onStartDrag(float x, float y) {
         mMesh = new Mesh(mWhich, 16, 16);
     }
diff --git a/src/com/android/browser/MostVisitedActivity.java b/src/com/android/browser/MostVisitedActivity.java
deleted file mode 100644
index d03c7a3..0000000
--- a/src/com/android/browser/MostVisitedActivity.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (C) 2009 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.Activity;
-import android.app.ListActivity;
-import android.content.Intent;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.database.DataSetObserver;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.os.Bundle;
-import android.os.Handler;
-import android.provider.Browser;
-import android.webkit.WebIconDatabase.IconListener;
-import android.widget.ListAdapter;
-import android.widget.ListView;
-import android.widget.SimpleCursorAdapter;
-import android.widget.TextView;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
-import android.view.ViewStub;
-
-import java.util.Vector;
-
-public class MostVisitedActivity extends ListActivity {
-
-    private MyAdapter   mAdapter;
-
-    // Instance of IconReceiver
-    private final IconReceiver mIconReceiver = new IconReceiver();
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        mAdapter = new MyAdapter();
-        CombinedBookmarkHistoryActivity.getIconListenerSet()
-                .addListener(mIconReceiver);
-        setListAdapter(mAdapter);
-        ListView list = getListView();
-        View v = new ViewStub(this, R.layout.empty_history);
-        addContentView(v, new LayoutParams(LayoutParams.FILL_PARENT,
-                LayoutParams.FILL_PARENT));
-        list.setEmptyView(v);
-    }
-
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-        CombinedBookmarkHistoryActivity.getIconListenerSet()
-               .removeListener(mIconReceiver);
-    }
-
-    private class IconReceiver implements IconListener {
-        public void onReceivedIcon(String url, Bitmap icon) {
-            setListAdapter(mAdapter);
-        }
-    }
-
-    protected void onListItemClick(ListView l, View v, int position, long id) {
-        TextView tv = (TextView) v.findViewById(R.id.url);
-        String url = tv.getText().toString();
-        loadUrl(url, false);
-    }
-
-    private void loadUrl(String url, boolean newWindow) {
-        Intent intent = new Intent().setAction(url);
-        if (newWindow) {
-            Bundle b = new Bundle();
-            b.putBoolean("new_window", true);
-            intent.putExtras(b);
-        }
-        setResultToParent(RESULT_OK, intent);
-        finish();
-    }
-
-    private class MyAdapter implements ListAdapter {
-        private Vector<DataSetObserver> mObservers;
-        private Cursor mCursor;
-        // These correspond with projection below.
-        private static final int mUrlIndex = 0;
-        private static final int mTitleIndex = 1;
-        private static final int mBookmarkIndex = 2;
-        private static final int mFaviconIndex = 3;
-
-        MyAdapter() {
-            mObservers = new Vector<DataSetObserver>();
-            String[] projection = new String[] {
-                    Browser.BookmarkColumns.URL,
-                    Browser.BookmarkColumns.TITLE,
-                    Browser.BookmarkColumns.BOOKMARK,
-                    Browser.BookmarkColumns.FAVICON };
-            String whereClause = Browser.BookmarkColumns.VISITS + " != 0";
-            String orderBy = Browser.BookmarkColumns.VISITS + " DESC";
-            mCursor = managedQuery(Browser.BOOKMARKS_URI, projection,
-                    whereClause, null, orderBy);
-            mCursor.registerContentObserver(new ChangeObserver());
-        }
-
-        private class ChangeObserver extends ContentObserver {
-            public ChangeObserver() {
-                super(new Handler());
-            }
-
-            @Override
-            public boolean deliverSelfNotifications() {
-                return true;
-            }
-
-            @Override
-            public void onChange(boolean selfChange) {
-                MyAdapter.this.refreshData();
-            }
-        }
-
-        void refreshData() {
-            mCursor.requery();
-            for (DataSetObserver o : mObservers) {
-                o.onChanged();
-            }
-        }
-
-        public View getView(int position, View convertView, ViewGroup parent) {
-            HistoryItem item;
-            if (null == convertView) {
-                item = new HistoryItem(MostVisitedActivity.this);
-            } else {
-                item = (HistoryItem) convertView;
-            }
-            mCursor.moveToPosition(position);
-            item.setName(mCursor.getString(mTitleIndex));
-            String url = mCursor.getString(mUrlIndex);
-            item.setUrl(url);
-            byte[] data = mCursor.getBlob(mFaviconIndex);
-            if (data != null) {
-                item.setFavicon(BitmapFactory.decodeByteArray(data, 0,
-                        data.length));
-            } else {
-                item.setFavicon(CombinedBookmarkHistoryActivity
-                        .getIconListenerSet().getFavicon(url));
-            }
-            item.setIsBookmark(1 == mCursor.getInt(mBookmarkIndex));
-            return item;
-        }
-
-        public boolean areAllItemsEnabled() {
-            return true;
-        }
-
-        public boolean isEnabled(int position) {
-            return true;
-        }
-
-        public int getCount() {
-            return mCursor.getCount();
-        }
-
-        public Object getItem(int position) {
-            return null;
-        }
-
-        public long getItemId(int position) {
-            return position;
-        }
-
-        // Always a HistoryItem
-        public int getItemViewType(int position) {
-            return 0;
-        }
-
-        public int getViewTypeCount() {
-            return 1;
-        }
-
-        public boolean hasStableIds() {
-            return true;
-        }
-
-        public void registerDataSetObserver(DataSetObserver observer) {
-            mObservers.add(observer);
-        }
-
-        public void unregisterDataSetObserver(DataSetObserver observer) {
-            mObservers.remove(observer);
-        }
-
-        public boolean isEmpty() {
-            return getCount() == 0;
-        }
-    }
-
-    // This Activity is generally a sub-Activity of CombinedHistoryActivity. In
-    // that situation, we need to pass our result code up to our parent.
-    // However, if someone calls this Activity directly, then this has no
-    // parent, and it needs to set it on itself.
-    private void setResultToParent(int resultCode, Intent data) {
-        Activity a = getParent() == null ? this : getParent();
-        a.setResult(resultCode, data);
-    }
-}
-
diff --git a/src/com/android/browser/OpenDownloadReceiver.java b/src/com/android/browser/OpenDownloadReceiver.java
new file mode 100644
index 0000000..814aa9c
--- /dev/null
+++ b/src/com/android/browser/OpenDownloadReceiver.java
@@ -0,0 +1,112 @@
+/*
+ * 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.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.
+ */
+public class OpenDownloadReceiver extends BroadcastReceiver {
+    public void onReceive(Context context, Intent intent) {
+        ContentResolver cr = context.getContentResolver();
+        Uri data = intent.getData();
+        Cursor cursor = null;
+        try {
+            cursor = cr.query(data,
+                    new String[] { Downloads.Impl._ID, Downloads.Impl._DATA,
+                    Downloads.Impl.COLUMN_MIME_TYPE, Downloads.COLUMN_STATUS },
+                    null, null, null);
+            if (cursor.moveToFirst()) {
+                String filename = cursor.getString(1);
+                String mimetype = cursor.getString(2);
+                String action = intent.getAction();
+                if (Downloads.ACTION_NOTIFICATION_CLICKED.equals(action)) {
+                    int status = cursor.getInt(3);
+                    if (Downloads.isStatusCompleted(status)
+                            && Downloads.isStatusSuccess(status)) {
+                        Intent launchIntent = new Intent(Intent.ACTION_VIEW);
+                        Uri path = Uri.parse(filename);
+                        // If there is no scheme, then it must be a file
+                        if (path.getScheme() == null) {
+                            path = Uri.fromFile(new File(filename));
+                        }
+                        launchIntent.setDataAndType(path, mimetype);
+                        launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                        try {
+                            context.startActivity(launchIntent);
+                        } catch (ActivityNotFoundException ex) {
+                            Toast.makeText(context,
+                                    R.string.download_no_application_title,
+                                    Toast.LENGTH_LONG).show();
+                        }
+                    } else {
+                        // Open the downloads page
+                        Intent pageView = new Intent(context,
+                                BrowserDownloadPage.class);
+                        pageView.setData(data);
+                        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/SystemAllowGeolocationOrigins.java b/src/com/android/browser/SystemAllowGeolocationOrigins.java
new file mode 100644
index 0000000..3f5a84e
--- /dev/null
+++ b/src/com/android/browser/SystemAllowGeolocationOrigins.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.browser;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.preference.PreferenceManager;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.webkit.GeolocationPermissions;
+import android.webkit.ValueCallback;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Manages the interaction between the secure system setting for default geolocation
+ * permissions and the browser.
+ */
+class SystemAllowGeolocationOrigins {
+
+    // Preference key for the value of the system setting last read by the browser
+    private final static String LAST_READ_ALLOW_GEOLOCATION_ORIGINS =
+            "last_read_allow_geolocation_origins";
+
+    // The application context
+    private final Context mContext;
+
+    // The observer used to listen to the system setting.
+    private final SettingObserver mSettingObserver;
+
+    public SystemAllowGeolocationOrigins(Context context) {
+        mContext = context;
+        mSettingObserver = new SettingObserver();
+    }
+
+    /**
+     * Checks whether the setting has changed and installs an observer to listen for
+     * future changes. Must be called on the application main thread.
+     */
+    public void start() {
+        // Register to receive notifications when the system settings change.
+        Uri uri = Settings.Secure.getUriFor(Settings.Secure.ALLOWED_GEOLOCATION_ORIGINS);
+        mContext.getContentResolver().registerContentObserver(uri, false, mSettingObserver);
+
+        // Read and apply the setting if needed.
+        maybeApplySettingAsync();
+    }
+
+    /**
+     * Stops the manager.
+     */
+    public void stop() {
+        mContext.getContentResolver().unregisterContentObserver(mSettingObserver);
+    }
+
+    void maybeApplySettingAsync() {
+        new AsyncTask<Void,Void,Void>() {
+            @Override
+            protected Void doInBackground(Void... params) {
+                maybeApplySetting();
+                return null;
+            }
+        }.execute();
+    }
+
+    /**
+     * Checks to see if the system setting has changed and if so,
+     * updates the Geolocation permissions accordingly.
+     */
+    private void maybeApplySetting() {
+        // Get the new value
+        String newSetting = getSystemSetting();
+
+        // Get the last read value
+        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
+        String lastReadSetting =
+                preferences.getString(LAST_READ_ALLOW_GEOLOCATION_ORIGINS, "");
+
+        // If the new value is the same as the last one we read, we're done.
+        if (TextUtils.equals(lastReadSetting, newSetting)) {
+            return;
+        }
+
+        // Save the new value as the last read value
+        preferences.edit()
+                .putString(LAST_READ_ALLOW_GEOLOCATION_ORIGINS, newSetting)
+                .commit();
+
+        Set<String> oldOrigins = parseAllowGeolocationOrigins(lastReadSetting);
+        Set<String> newOrigins = parseAllowGeolocationOrigins(newSetting);
+        Set<String> addedOrigins = setMinus(newOrigins, oldOrigins);
+        Set<String> removedOrigins = setMinus(oldOrigins, newOrigins);
+
+        // Remove the origins in the last read value
+        removeOrigins(removedOrigins);
+
+        // Add the origins in the new value
+        addOrigins(addedOrigins);
+    }
+
+    /**
+     * Parses the value of the default geolocation permissions setting.
+     *
+     * @param setting A space-separated list of origins.
+     * @return A mutable set of origins.
+     */
+    private static HashSet<String> parseAllowGeolocationOrigins(String setting) {
+        HashSet<String> origins = new HashSet<String>();
+        if (!TextUtils.isEmpty(setting)) {
+            for (String origin : setting.split("\\s+")) {
+                if (!TextUtils.isEmpty(origin)) {
+                    origins.add(origin);
+                }
+            }
+        }
+        return origins;
+    }
+
+    /**
+     * Gets the difference between two sets. Does not modify any of the arguments.
+     *
+     * @return A set containing all elements in {@code x} that are not in {@code y}.
+     */
+    private <A> Set<A> setMinus(Set<A> x, Set<A> y) {
+        HashSet<A> z = new HashSet<A>(x.size());
+        for (A a : x) {
+            if (!y.contains(a)) {
+                z.add(a);
+            }
+        }
+        return z;
+    }
+
+    /**
+     * Gets the current system setting for default allowed geolocation origins.
+     *
+     * @return The default allowed origins. Returns {@code ""} if not set.
+     */
+    private String getSystemSetting() {
+        String value = Settings.Secure.getString(mContext.getContentResolver(),
+                Settings.Secure.ALLOWED_GEOLOCATION_ORIGINS);
+        return value == null ? "" : value;
+    }
+
+    /**
+     * Adds geolocation permissions for the given origins.
+     */
+    private void addOrigins(Set<String> origins) {
+        for (String origin : origins) {
+            GeolocationPermissions.getInstance().allow(origin);
+        }
+    }
+
+    /**
+     * Removes geolocation permissions for the given origins, if they are allowed.
+     * If they are denied or not set, nothing is done.
+     */
+    private void removeOrigins(Set<String> origins) {
+        for (final String origin : origins) {
+            GeolocationPermissions.getInstance().getAllowed(origin, new ValueCallback<Boolean>() {
+                public void onReceiveValue(Boolean value) {
+                    if (value != null && value.booleanValue()) {
+                        GeolocationPermissions.getInstance().clear(origin);
+                    }
+                }
+            });
+        }
+    }
+
+    /**
+     * Listens for changes to the system setting.
+     */
+    private class SettingObserver extends ContentObserver {
+
+        SettingObserver() {
+            super(new Handler());
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            maybeApplySettingAsync();
+        }
+    }
+
+}
diff --git a/src/com/android/browser/Tab.java b/src/com/android/browser/Tab.java
new file mode 100644
index 0000000..2dac050
--- /dev/null
+++ b/src/com/android/browser/Tab.java
@@ -0,0 +1,1934 @@
+/*
+ * Copyright (C) 2009 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 java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Vector;
+
+import android.app.AlertDialog;
+import android.app.SearchManager;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnCancelListener;
+import android.content.Intent;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteException;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.net.http.SslError;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Message;
+import android.os.SystemClock;
+import android.provider.Browser;
+import android.speech.RecognizerResultsIntent;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewStub;
+import android.view.View.OnClickListener;
+import android.webkit.ConsoleMessage;
+import android.webkit.CookieSyncManager;
+import android.webkit.DownloadListener;
+import android.webkit.GeolocationPermissions;
+import android.webkit.HttpAuthHandler;
+import android.webkit.SslErrorHandler;
+import android.webkit.URLUtil;
+import android.webkit.ValueCallback;
+import android.webkit.WebBackForwardList;
+import android.webkit.WebBackForwardListClient;
+import android.webkit.WebChromeClient;
+import android.webkit.WebHistoryItem;
+import android.webkit.WebIconDatabase;
+import android.webkit.WebStorage;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.FrameLayout;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.common.speech.LoggingEvents;
+
+/**
+ * Class for maintaining Tabs with a main WebView and a subwindow.
+ */
+class Tab {
+    // Log Tag
+    private static final String LOGTAG = "Tab";
+    // Special case the logtag for messages for the Console to make it easier to
+    // filter them and match the logtag used for these messages in older versions
+    // of the browser.
+    private static final String CONSOLE_LOGTAG = "browser";
+
+    // The Geolocation permissions prompt
+    private GeolocationPermissionsPrompt mGeolocationPermissionsPrompt;
+    // Main WebView wrapper
+    private View mContainer;
+    // Main WebView
+    private WebView mMainView;
+    // Subwindow container
+    private View mSubViewContainer;
+    // Subwindow WebView
+    private WebView mSubView;
+    // Saved bundle for when we are running low on memory. It contains the
+    // information needed to restore the WebView if the user goes back to the
+    // tab.
+    private Bundle mSavedState;
+    // Data used when displaying the tab in the picker.
+    private PickerData mPickerData;
+    // Parent Tab. This is the Tab that created this Tab, or null if the Tab was
+    // created by the UI
+    private Tab mParentTab;
+    // Tab that constructed by this Tab. This is used when this Tab is
+    // destroyed, it clears all mParentTab values in the children.
+    private Vector<Tab> mChildTabs;
+    // If true, the tab will be removed when back out of the first page.
+    private boolean mCloseOnExit;
+    // If true, the tab is in the foreground of the current activity.
+    private boolean mInForeground;
+    // If true, the tab is in loading state.
+    private boolean mInLoad;
+    // The time the load started, used to find load page time
+    private long mLoadStartTime;
+    // Application identifier used to find tabs that another application wants
+    // to reuse.
+    private String mAppId;
+    // Keep the original url around to avoid killing the old WebView if the url
+    // has not changed.
+    private String mOriginalUrl;
+    // Error console for the tab
+    private ErrorConsoleView mErrorConsole;
+    // the lock icon type and previous lock icon type for the tab
+    private int mLockIconType;
+    private int mPrevLockIconType;
+    // Inflation service for making subwindows.
+    private final LayoutInflater mInflateService;
+    // The BrowserActivity which owners the Tab
+    private final BrowserActivity mActivity;
+    // The listener that gets invoked when a download is started from the
+    // mMainView
+    private final DownloadListener mDownloadListener;
+    // Listener used to know when we move forward or back in the history list.
+    private final WebBackForwardListClient mWebBackForwardListClient;
+
+    // AsyncTask for downloading touch icons
+    DownloadTouchIcon mTouchIconLoader;
+
+    // Extra saved information for displaying the tab in the picker.
+    private static class PickerData {
+        String  mUrl;
+        String  mTitle;
+        Bitmap  mFavicon;
+    }
+
+    // Used for saving and restoring each Tab
+    static final String WEBVIEW = "webview";
+    static final String NUMTABS = "numTabs";
+    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";
+    static final String ORIGINALURL = "originalUrl";
+
+    // -------------------------------------------------------------------------
+
+    /**
+     * Private information regarding the latest voice search.  If the Tab is not
+     * in voice search mode, this will be null.
+     */
+    private VoiceSearchData mVoiceSearchData;
+    /**
+     * 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.
+     */
+    public boolean voiceSearchSourceIsGoogle() {
+        return mVoiceSearchData != null && mVoiceSearchData.mSourceIsGoogle;
+    }
+    /**
+     * Get the title to display for the current voice search page.  If the Tab
+     * is not in voice search mode, return null.
+     */
+    public String getVoiceDisplayTitle() {
+        if (mVoiceSearchData == null) return null;
+        return mVoiceSearchData.mLastVoiceSearchTitle;
+    }
+    /**
+     * Get the latest array of voice search results, to be passed to the
+     * BrowserProvider.  If the Tab is not in voice search mode, return null.
+     */
+    public ArrayList<String> getVoiceSearchResults() {
+        if (mVoiceSearchData == null) return null;
+        return mVoiceSearchData.mVoiceSearchResults;
+    }
+    /**
+     * Activate voice search mode.
+     * @param intent Intent which has the results to use, or an index into the
+     *      results when reusing the old results.
+     */
+    /* package */ void activateVoiceSearchMode(Intent intent) {
+        int index = 0;
+        ArrayList<String> results = intent.getStringArrayListExtra(
+                    RecognizerResultsIntent.EXTRA_VOICE_SEARCH_RESULT_STRINGS);
+        if (results != null) {
+            ArrayList<String> urls = intent.getStringArrayListExtra(
+                        RecognizerResultsIntent.EXTRA_VOICE_SEARCH_RESULT_URLS);
+            ArrayList<String> htmls = intent.getStringArrayListExtra(
+                        RecognizerResultsIntent.EXTRA_VOICE_SEARCH_RESULT_HTML);
+            ArrayList<String> baseUrls = intent.getStringArrayListExtra(
+                        RecognizerResultsIntent
+                        .EXTRA_VOICE_SEARCH_RESULT_HTML_BASE_URLS);
+            // This tab is now entering voice search mode for the first time, or
+            // a new voice search was done.
+            int size = results.size();
+            if (urls == null || size != urls.size()) {
+                throw new AssertionError("improper extras passed in Intent");
+            }
+            if (htmls == null || htmls.size() != size || baseUrls == null ||
+                    (baseUrls.size() != size && baseUrls.size() != 1)) {
+                // If either of these arrays are empty/incorrectly sized, ignore
+                // them.
+                htmls = null;
+                baseUrls = null;
+            }
+            mVoiceSearchData = new VoiceSearchData(results, urls, htmls,
+                    baseUrls);
+            mVoiceSearchData.mHeaders = intent.getParcelableArrayListExtra(
+                    RecognizerResultsIntent
+                    .EXTRA_VOICE_SEARCH_RESULT_HTTP_HEADERS);
+            mVoiceSearchData.mSourceIsGoogle = intent.getBooleanExtra(
+                    VoiceSearchData.SOURCE_IS_GOOGLE, false);
+            mVoiceSearchData.mVoiceSearchIntent = new Intent(intent);
+        }
+        String extraData = intent.getStringExtra(
+                SearchManager.EXTRA_DATA_KEY);
+        if (extraData != null) {
+            index = Integer.parseInt(extraData);
+            if (index >= mVoiceSearchData.mVoiceSearchResults.size()) {
+                throw new AssertionError("index must be less than "
+                        + "size of mVoiceSearchResults");
+            }
+            if (mVoiceSearchData.mSourceIsGoogle) {
+                Intent logIntent = new Intent(
+                        LoggingEvents.ACTION_LOG_EVENT);
+                logIntent.putExtra(LoggingEvents.EXTRA_EVENT,
+                        LoggingEvents.VoiceSearch.N_BEST_CHOOSE);
+                logIntent.putExtra(
+                        LoggingEvents.VoiceSearch.EXTRA_N_BEST_CHOOSE_INDEX,
+                        index);
+                mActivity.sendBroadcast(logIntent);
+            }
+            if (mVoiceSearchData.mVoiceSearchIntent != null) {
+                // Copy the Intent, so that each history item will have its own
+                // Intent, with different (or none) extra data.
+                Intent latest = new Intent(mVoiceSearchData.mVoiceSearchIntent);
+                latest.putExtra(SearchManager.EXTRA_DATA_KEY, extraData);
+                mVoiceSearchData.mVoiceSearchIntent = latest;
+            }
+        }
+        mVoiceSearchData.mLastVoiceSearchTitle
+                = mVoiceSearchData.mVoiceSearchResults.get(index);
+        if (mInForeground) {
+            mActivity.showVoiceTitleBar(mVoiceSearchData.mLastVoiceSearchTitle);
+        }
+        if (mVoiceSearchData.mVoiceSearchHtmls != null) {
+            // When index was found it was already ensured that it was valid
+            String uriString = mVoiceSearchData.mVoiceSearchHtmls.get(index);
+            if (uriString != null) {
+                Uri dataUri = Uri.parse(uriString);
+                if (RecognizerResultsIntent.URI_SCHEME_INLINE.equals(
+                        dataUri.getScheme())) {
+                    // If there is only one base URL, use it.  If there are
+                    // more, there will be one for each index, so use the base
+                    // URL corresponding to the index.
+                    String baseUrl = mVoiceSearchData.mVoiceSearchBaseUrls.get(
+                            mVoiceSearchData.mVoiceSearchBaseUrls.size() > 1 ?
+                            index : 0);
+                    mVoiceSearchData.mLastVoiceSearchUrl = baseUrl;
+                    mMainView.loadDataWithBaseURL(baseUrl,
+                            uriString.substring(RecognizerResultsIntent
+                            .URI_SCHEME_INLINE.length() + 1), "text/html",
+                            "utf-8", baseUrl);
+                    return;
+                }
+            }
+        }
+        mVoiceSearchData.mLastVoiceSearchUrl
+                = mVoiceSearchData.mVoiceSearchUrls.get(index);
+        if (null == mVoiceSearchData.mLastVoiceSearchUrl) {
+            mVoiceSearchData.mLastVoiceSearchUrl = mActivity.smartUrlFilter(
+                    mVoiceSearchData.mLastVoiceSearchTitle);
+        }
+        Map<String, String> headers = null;
+        if (mVoiceSearchData.mHeaders != null) {
+            int bundleIndex = mVoiceSearchData.mHeaders.size() == 1 ? 0
+                    : index;
+            Bundle bundle = mVoiceSearchData.mHeaders.get(bundleIndex);
+            if (bundle != null && !bundle.isEmpty()) {
+                Iterator<String> iter = bundle.keySet().iterator();
+                headers = new HashMap<String, String>();
+                while (iter.hasNext()) {
+                    String key = iter.next();
+                    headers.put(key, bundle.getString(key));
+                }
+            }
+        }
+        mMainView.loadUrl(mVoiceSearchData.mLastVoiceSearchUrl, headers);
+    }
+    /* package */ static class VoiceSearchData {
+        public VoiceSearchData(ArrayList<String> results,
+                ArrayList<String> urls, ArrayList<String> htmls,
+                ArrayList<String> baseUrls) {
+            mVoiceSearchResults = results;
+            mVoiceSearchUrls = urls;
+            mVoiceSearchHtmls = htmls;
+            mVoiceSearchBaseUrls = baseUrls;
+        }
+        /*
+         * ArrayList of suggestions to be displayed when opening the
+         * SearchManager
+         */
+        public ArrayList<String> mVoiceSearchResults;
+        /*
+         * ArrayList of urls, associated with the suggestions in
+         * mVoiceSearchResults.
+         */
+        public ArrayList<String> mVoiceSearchUrls;
+        /*
+         * ArrayList holding content to load for each item in
+         * mVoiceSearchResults.
+         */
+        public ArrayList<String> mVoiceSearchHtmls;
+        /*
+         * ArrayList holding base urls for the items in mVoiceSearchResults.
+         * If non null, this will either have the same size as
+         * mVoiceSearchResults or have a size of 1, in which case all will use
+         * the same base url
+         */
+        public ArrayList<String> mVoiceSearchBaseUrls;
+        /*
+         * The last url provided by voice search.  Used for comparison to see if
+         * we are going to a page by some method besides voice search.
+         */
+        public String mLastVoiceSearchUrl;
+        /**
+         * The last title used for voice search.  Needed to update the title bar
+         * when switching tabs.
+         */
+        public String mLastVoiceSearchTitle;
+        /**
+         * Whether the Intent which turned on voice search mode contained the
+         * String signifying that Google was the source.
+         */
+        public boolean mSourceIsGoogle;
+        /**
+         * List of headers to be passed into the WebView containing location
+         * information
+         */
+        public ArrayList<Bundle> mHeaders;
+        /**
+         * The Intent used to invoke voice search.  Placed on the
+         * WebHistoryItem so that when coming back to a previous voice search
+         * page we can again activate voice search.
+         */
+        public Intent mVoiceSearchIntent;
+        /**
+         * String used to identify Google as the source of voice search.
+         */
+        public static String SOURCE_IS_GOOGLE
+                = "android.speech.extras.SOURCE_IS_GOOGLE";
+    }
+
+    // Container class for the next error dialog that needs to be displayed
+    private class ErrorDialog {
+        public final int mTitle;
+        public final String mDescription;
+        public final int mError;
+        ErrorDialog(int title, String desc, int error) {
+            mTitle = title;
+            mDescription = desc;
+            mError = error;
+        }
+    };
+
+    private void processNextError() {
+        if (mQueuedErrors == null) {
+            return;
+        }
+        // The first one is currently displayed so just remove it.
+        mQueuedErrors.removeFirst();
+        if (mQueuedErrors.size() == 0) {
+            mQueuedErrors = null;
+            return;
+        }
+        showError(mQueuedErrors.getFirst());
+    }
+
+    private DialogInterface.OnDismissListener mDialogListener =
+            new DialogInterface.OnDismissListener() {
+                public void onDismiss(DialogInterface d) {
+                    processNextError();
+                }
+            };
+    private LinkedList<ErrorDialog> mQueuedErrors;
+
+    private void queueError(int err, String desc) {
+        if (mQueuedErrors == null) {
+            mQueuedErrors = new LinkedList<ErrorDialog>();
+        }
+        for (ErrorDialog d : mQueuedErrors) {
+            if (d.mError == err) {
+                // Already saw a similar error, ignore the new one.
+                return;
+            }
+        }
+        ErrorDialog errDialog = new ErrorDialog(
+                err == WebViewClient.ERROR_FILE_NOT_FOUND ?
+                R.string.browserFrameFileErrorLabel :
+                R.string.browserFrameNetworkErrorLabel,
+                desc, err);
+        mQueuedErrors.addLast(errDialog);
+
+        // Show the dialog now if the queue was empty and it is in foreground
+        if (mQueuedErrors.size() == 1 && mInForeground) {
+            showError(errDialog);
+        }
+    }
+
+    private void showError(ErrorDialog errDialog) {
+        if (mInForeground) {
+            AlertDialog d = new AlertDialog.Builder(mActivity)
+                    .setTitle(errDialog.mTitle)
+                    .setMessage(errDialog.mDescription)
+                    .setPositiveButton(R.string.ok, null)
+                    .create();
+            d.setOnDismissListener(mDialogListener);
+            d.show();
+        }
+    }
+
+    // -------------------------------------------------------------------------
+    // WebViewClient implementation for the main WebView
+    // -------------------------------------------------------------------------
+
+    private final WebViewClient mWebViewClient = new WebViewClient() {
+        private Message mDontResend;
+        private Message mResend;
+        @Override
+        public void onPageStarted(WebView view, String url, Bitmap favicon) {
+            mInLoad = true;
+            mLoadStartTime = SystemClock.uptimeMillis();
+            if (mVoiceSearchData != null
+                    && !url.equals(mVoiceSearchData.mLastVoiceSearchUrl)) {
+                if (mVoiceSearchData.mSourceIsGoogle) {
+                    Intent i = new Intent(LoggingEvents.ACTION_LOG_EVENT);
+                    i.putExtra(LoggingEvents.EXTRA_FLUSH, true);
+                    mActivity.sendBroadcast(i);
+                }
+                mVoiceSearchData = null;
+                if (mInForeground) {
+                    mActivity.revertVoiceTitleBar();
+                }
+            }
+
+            // We've started to load a new page. If there was a pending message
+            // to save a screenshot then we will now take the new page and save
+            // an incorrect screenshot. Therefore, remove any pending thumbnail
+            // messages from the queue.
+            mActivity.removeMessages(BrowserActivity.UPDATE_BOOKMARK_THUMBNAIL,
+                    view);
+
+            // If we start a touch icon load and then load a new page, we don't
+            // want to cancel the current touch icon loader. But, we do want to
+            // create a new one when the touch icon url is known.
+            if (mTouchIconLoader != null) {
+                mTouchIconLoader.mTab = null;
+                mTouchIconLoader = null;
+            }
+
+            // reset the error console
+            if (mErrorConsole != null) {
+                mErrorConsole.clearErrorMessages();
+                if (mActivity.shouldShowErrorConsole()) {
+                    mErrorConsole.showConsole(ErrorConsoleView.SHOW_NONE);
+                }
+            }
+
+            // update the bookmark database for favicon
+            if (favicon != null) {
+                BrowserBookmarksAdapter.updateBookmarkFavicon(mActivity
+                        .getContentResolver(), null, url, favicon);
+            }
+
+            // reset sync timer to avoid sync starts during loading a page
+            CookieSyncManager.getInstance().resetSync();
+
+            if (!mActivity.isNetworkUp()) {
+                view.setNetworkAvailable(false);
+            }
+
+            // finally update the UI in the activity if it is in the foreground
+            if (mInForeground) {
+                mActivity.onPageStarted(view, url, favicon);
+            }
+        }
+
+        @Override
+        public void onPageFinished(WebView view, String url) {
+            LogTag.logPageFinishedLoading(
+                    url, SystemClock.uptimeMillis() - mLoadStartTime);
+            mInLoad = false;
+
+            if (mInForeground && !mActivity.didUserStopLoading()
+                    || !mInForeground) {
+                // Only update the bookmark screenshot if the user did not
+                // cancel the load early.
+                mActivity.postMessage(
+                        BrowserActivity.UPDATE_BOOKMARK_THUMBNAIL, 0, 0, view,
+                        500);
+            }
+
+            // finally update the UI in the activity if it is in the foreground
+            if (mInForeground) {
+                mActivity.onPageFinished(view, url);
+            }
+        }
+
+        // return true if want to hijack the url to let another app to handle it
+        @Override
+        public boolean shouldOverrideUrlLoading(WebView view, String url) {
+            if (mInForeground) {
+                return mActivity.shouldOverrideUrlLoading(view, url);
+            } else {
+                return false;
+            }
+        }
+
+        /**
+         * Updates the lock icon. This method is called when we discover another
+         * resource to be loaded for this page (for example, javascript). While
+         * we update the icon type, we do not update the lock icon itself until
+         * we are done loading, it is slightly more secure this way.
+         */
+        @Override
+        public void onLoadResource(WebView view, String url) {
+            if (url != null && url.length() > 0) {
+                // It is only if the page claims to be secure that we may have
+                // to update the lock:
+                if (mLockIconType == BrowserActivity.LOCK_ICON_SECURE) {
+                    // If NOT a 'safe' url, change the lock to mixed content!
+                    if (!(URLUtil.isHttpsUrl(url) || URLUtil.isDataUrl(url)
+                            || URLUtil.isAboutUrl(url))) {
+                        mLockIconType = BrowserActivity.LOCK_ICON_MIXED;
+                    }
+                }
+            }
+        }
+
+        /**
+         * Show a dialog informing the user of the network error reported by
+         * WebCore if it is in the foreground.
+         */
+        @Override
+        public void onReceivedError(WebView view, int errorCode,
+                String description, String failingUrl) {
+            if (errorCode != WebViewClient.ERROR_HOST_LOOKUP &&
+                    errorCode != WebViewClient.ERROR_CONNECT &&
+                    errorCode != WebViewClient.ERROR_BAD_URL &&
+                    errorCode != WebViewClient.ERROR_UNSUPPORTED_SCHEME &&
+                    errorCode != WebViewClient.ERROR_FILE) {
+                queueError(errorCode, description);
+            }
+            Log.e(LOGTAG, "onReceivedError " + errorCode + " " + failingUrl
+                    + " " + description);
+
+            // We need to reset the title after an error if it is in foreground.
+            if (mInForeground) {
+                mActivity.resetTitleAndRevertLockIcon();
+            }
+        }
+
+        /**
+         * Check with the user if it is ok to resend POST data as the page they
+         * are trying to navigate to is the result of a POST.
+         */
+        @Override
+        public void onFormResubmission(WebView view, final Message dontResend,
+                                       final Message resend) {
+            if (!mInForeground) {
+                dontResend.sendToTarget();
+                return;
+            }
+            if (mDontResend != null) {
+                Log.w(LOGTAG, "onFormResubmission should not be called again "
+                        + "while dialog is still up");
+                dontResend.sendToTarget();
+                return;
+            }
+            mDontResend = dontResend;
+            mResend = resend;
+            new AlertDialog.Builder(mActivity).setTitle(
+                    R.string.browserFrameFormResubmitLabel).setMessage(
+                    R.string.browserFrameFormResubmitMessage)
+                    .setPositiveButton(R.string.ok,
+                            new DialogInterface.OnClickListener() {
+                                public void onClick(DialogInterface dialog,
+                                        int which) {
+                                    if (mResend != null) {
+                                        mResend.sendToTarget();
+                                        mResend = null;
+                                        mDontResend = null;
+                                    }
+                                }
+                            }).setNegativeButton(R.string.cancel,
+                            new DialogInterface.OnClickListener() {
+                                public void onClick(DialogInterface dialog,
+                                        int which) {
+                                    if (mDontResend != null) {
+                                        mDontResend.sendToTarget();
+                                        mResend = null;
+                                        mDontResend = null;
+                                    }
+                                }
+                            }).setOnCancelListener(new OnCancelListener() {
+                        public void onCancel(DialogInterface dialog) {
+                            if (mDontResend != null) {
+                                mDontResend.sendToTarget();
+                                mResend = null;
+                                mDontResend = null;
+                            }
+                        }
+                    }).show();
+        }
+
+        /**
+         * Insert the url into the visited history database.
+         * @param url The url to be inserted.
+         * @param isReload True if this url is being reloaded.
+         * FIXME: Not sure what to do when reloading the page.
+         */
+        @Override
+        public void doUpdateVisitedHistory(WebView view, String url,
+                boolean isReload) {
+            if (url.regionMatches(true, 0, "about:", 0, 6)) {
+                return;
+            }
+            // remove "client" before updating it to the history so that it wont
+            // show up in the auto-complete list.
+            int index = url.indexOf("client=ms-");
+            if (index > 0 && url.contains(".google.")) {
+                int end = url.indexOf('&', index);
+                if (end > 0) {
+                    url = url.substring(0, index)
+                            .concat(url.substring(end + 1));
+                } else {
+                    // the url.charAt(index-1) should be either '?' or '&'
+                    url = url.substring(0, index-1);
+                }
+            }
+            final ContentResolver cr = mActivity.getContentResolver();
+            final String newUrl = url;
+            new AsyncTask<Void, Void, Void>() {
+                protected Void doInBackground(Void... unused) {
+                    Browser.updateVisitedHistory(cr, newUrl, true);
+                    return null;
+                }
+            }.execute();
+            WebIconDatabase.getInstance().retainIconForPageUrl(url);
+        }
+
+        /**
+         * Displays SSL error(s) dialog to the user.
+         */
+        @Override
+        public void onReceivedSslError(final WebView view,
+                final SslErrorHandler handler, final SslError error) {
+            if (!mInForeground) {
+                handler.cancel();
+                return;
+            }
+            if (BrowserSettings.getInstance().showSecurityWarnings()) {
+                final LayoutInflater factory =
+                    LayoutInflater.from(mActivity);
+                final View warningsView =
+                    factory.inflate(R.layout.ssl_warnings, null);
+                final LinearLayout placeholder =
+                    (LinearLayout)warningsView.findViewById(R.id.placeholder);
+
+                if (error.hasError(SslError.SSL_UNTRUSTED)) {
+                    LinearLayout ll = (LinearLayout)factory
+                        .inflate(R.layout.ssl_warning, null);
+                    ((TextView)ll.findViewById(R.id.warning))
+                        .setText(R.string.ssl_untrusted);
+                    placeholder.addView(ll);
+                }
+
+                if (error.hasError(SslError.SSL_IDMISMATCH)) {
+                    LinearLayout ll = (LinearLayout)factory
+                        .inflate(R.layout.ssl_warning, null);
+                    ((TextView)ll.findViewById(R.id.warning))
+                        .setText(R.string.ssl_mismatch);
+                    placeholder.addView(ll);
+                }
+
+                if (error.hasError(SslError.SSL_EXPIRED)) {
+                    LinearLayout ll = (LinearLayout)factory
+                        .inflate(R.layout.ssl_warning, null);
+                    ((TextView)ll.findViewById(R.id.warning))
+                        .setText(R.string.ssl_expired);
+                    placeholder.addView(ll);
+                }
+
+                if (error.hasError(SslError.SSL_NOTYETVALID)) {
+                    LinearLayout ll = (LinearLayout)factory
+                        .inflate(R.layout.ssl_warning, null);
+                    ((TextView)ll.findViewById(R.id.warning))
+                        .setText(R.string.ssl_not_yet_valid);
+                    placeholder.addView(ll);
+                }
+
+                new AlertDialog.Builder(mActivity).setTitle(
+                        R.string.security_warning).setIcon(
+                        android.R.drawable.ic_dialog_alert).setView(
+                        warningsView).setPositiveButton(R.string.ssl_continue,
+                        new DialogInterface.OnClickListener() {
+                            public void onClick(DialogInterface dialog,
+                                    int whichButton) {
+                                handler.proceed();
+                            }
+                        }).setNeutralButton(R.string.view_certificate,
+                        new DialogInterface.OnClickListener() {
+                            public void onClick(DialogInterface dialog,
+                                    int whichButton) {
+                                mActivity.showSSLCertificateOnError(view,
+                                        handler, error);
+                            }
+                        }).setNegativeButton(R.string.cancel,
+                        new DialogInterface.OnClickListener() {
+                            public void onClick(DialogInterface dialog,
+                                    int whichButton) {
+                                handler.cancel();
+                                mActivity.resetTitleAndRevertLockIcon();
+                            }
+                        }).setOnCancelListener(
+                        new DialogInterface.OnCancelListener() {
+                            public void onCancel(DialogInterface dialog) {
+                                handler.cancel();
+                                mActivity.resetTitleAndRevertLockIcon();
+                            }
+                        }).show();
+            } else {
+                handler.proceed();
+            }
+        }
+
+        /**
+         * Handles an HTTP authentication request.
+         *
+         * @param handler The authentication handler
+         * @param host The host
+         * @param realm The realm
+         */
+        @Override
+        public void onReceivedHttpAuthRequest(WebView view,
+                final HttpAuthHandler handler, final String host,
+                final String realm) {
+            String username = null;
+            String password = null;
+
+            boolean reuseHttpAuthUsernamePassword = handler
+                    .useHttpAuthUsernamePassword();
+
+            if (reuseHttpAuthUsernamePassword && view != null) {
+                String[] credentials = view.getHttpAuthUsernamePassword(
+                        host, realm);
+                if (credentials != null && credentials.length == 2) {
+                    username = credentials[0];
+                    password = credentials[1];
+                }
+            }
+
+            if (username != null && password != null) {
+                handler.proceed(username, password);
+            } else {
+                if (mInForeground) {
+                    mActivity.showHttpAuthentication(handler, host, realm,
+                            null, null, null, 0);
+                } else {
+                    handler.cancel();
+                }
+            }
+        }
+
+        @Override
+        public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) {
+            if (!mInForeground) {
+                return false;
+            }
+            if (mActivity.isMenuDown()) {
+                // only check shortcut key when MENU is held
+                return mActivity.getWindow().isShortcutKey(event.getKeyCode(),
+                        event);
+            } else {
+                return false;
+            }
+        }
+
+        @Override
+        public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
+            if (!mInForeground || mActivity.mActivityInPause) {
+                return;
+            }
+            if (event.isDown()) {
+                mActivity.onKeyDown(event.getKeyCode(), event);
+            } else {
+                mActivity.onKeyUp(event.getKeyCode(), event);
+            }
+        }
+    };
+
+    // -------------------------------------------------------------------------
+    // WebChromeClient implementation for the main WebView
+    // -------------------------------------------------------------------------
+
+    private final WebChromeClient mWebChromeClient = new WebChromeClient() {
+        // Helper method to create a new tab or sub window.
+        private void createWindow(final boolean dialog, final Message msg) {
+            WebView.WebViewTransport transport =
+                    (WebView.WebViewTransport) msg.obj;
+            if (dialog) {
+                createSubWindow();
+                mActivity.attachSubWindow(Tab.this);
+                transport.setWebView(mSubView);
+            } else {
+                final Tab newTab = mActivity.openTabAndShow(
+                        BrowserActivity.EMPTY_URL_DATA, false, null);
+                if (newTab != Tab.this) {
+                    Tab.this.addChildTab(newTab);
+                }
+                transport.setWebView(newTab.getWebView());
+            }
+            msg.sendToTarget();
+        }
+
+        @Override
+        public boolean onCreateWindow(WebView view, final boolean dialog,
+                final boolean userGesture, final Message resultMsg) {
+            // only allow new window or sub window for the foreground case
+            if (!mInForeground) {
+                return false;
+            }
+            // Short-circuit if we can't create any more tabs or sub windows.
+            if (dialog && mSubView != null) {
+                new AlertDialog.Builder(mActivity)
+                        .setTitle(R.string.too_many_subwindows_dialog_title)
+                        .setIcon(android.R.drawable.ic_dialog_alert)
+                        .setMessage(R.string.too_many_subwindows_dialog_message)
+                        .setPositiveButton(R.string.ok, null)
+                        .show();
+                return false;
+            } else if (!mActivity.getTabControl().canCreateNewTab()) {
+                new AlertDialog.Builder(mActivity)
+                        .setTitle(R.string.too_many_windows_dialog_title)
+                        .setIcon(android.R.drawable.ic_dialog_alert)
+                        .setMessage(R.string.too_many_windows_dialog_message)
+                        .setPositiveButton(R.string.ok, null)
+                        .show();
+                return false;
+            }
+
+            // Short-circuit if this was a user gesture.
+            if (userGesture) {
+                createWindow(dialog, resultMsg);
+                return true;
+            }
+
+            // Allow the popup and create the appropriate window.
+            final AlertDialog.OnClickListener allowListener =
+                    new AlertDialog.OnClickListener() {
+                        public void onClick(DialogInterface d,
+                                int which) {
+                            createWindow(dialog, resultMsg);
+                        }
+                    };
+
+            // Block the popup by returning a null WebView.
+            final AlertDialog.OnClickListener blockListener =
+                    new AlertDialog.OnClickListener() {
+                        public void onClick(DialogInterface d, int which) {
+                            resultMsg.sendToTarget();
+                        }
+                    };
+
+            // Build a confirmation dialog to display to the user.
+            final AlertDialog d =
+                    new AlertDialog.Builder(mActivity)
+                    .setTitle(R.string.attention)
+                    .setIcon(android.R.drawable.ic_dialog_alert)
+                    .setMessage(R.string.popup_window_attempt)
+                    .setPositiveButton(R.string.allow, allowListener)
+                    .setNegativeButton(R.string.block, blockListener)
+                    .setCancelable(false)
+                    .create();
+
+            // Show the confirmation dialog.
+            d.show();
+            return true;
+        }
+
+        @Override
+        public void onRequestFocus(WebView view) {
+            if (!mInForeground) {
+                mActivity.switchToTab(mActivity.getTabControl().getTabIndex(
+                        Tab.this));
+            }
+        }
+
+        @Override
+        public void onCloseWindow(WebView window) {
+            if (mParentTab != null) {
+                // JavaScript can only close popup window.
+                if (mInForeground) {
+                    mActivity.switchToTab(mActivity.getTabControl()
+                            .getTabIndex(mParentTab));
+                }
+                mActivity.closeTab(Tab.this);
+            }
+        }
+
+        @Override
+        public void onProgressChanged(WebView view, int newProgress) {
+            if (newProgress == 100) {
+                // sync cookies and cache promptly here.
+                CookieSyncManager.getInstance().sync();
+            }
+            if (mInForeground) {
+                mActivity.onProgressChanged(view, newProgress);
+            }
+        }
+
+        @Override
+        public void onReceivedTitle(WebView view, final String title) {
+            final String pageUrl = view.getUrl();
+            if (mInForeground) {
+                // here, if url is null, we want to reset the title
+                mActivity.setUrlTitle(pageUrl, title);
+            }
+            if (pageUrl == null || pageUrl.length()
+                    >= SQLiteDatabase.SQLITE_MAX_LIKE_PATTERN_LENGTH) {
+                return;
+            }
+            new AsyncTask<Void, Void, Void>() {
+                protected Void doInBackground(Void... unused) {
+                    // See if we can find the current url in our history
+                    // database and add the new title to it.
+                    String url = pageUrl;
+                    if (url.startsWith("http://www.")) {
+                        url = url.substring(11);
+                    } else if (url.startsWith("http://")) {
+                        url = url.substring(4);
+                    }
+                    Cursor c = null;
+                    try {
+                        final ContentResolver cr
+                                = mActivity.getContentResolver();
+                        url = "%" + url;
+                        String [] selArgs = new String[] { url };
+                        String where = Browser.BookmarkColumns.URL
+                                + " LIKE ? AND "
+                                + Browser.BookmarkColumns.BOOKMARK + " = 0";
+                        c = cr.query(Browser.BOOKMARKS_URI, new String[]
+                                { Browser.BookmarkColumns._ID }, where, selArgs,
+                                null);
+                        if (c.moveToFirst()) {
+                            // Current implementation of database only has one
+                            // entry per url.
+                            ContentValues map = new ContentValues();
+                            map.put(Browser.BookmarkColumns.TITLE, title);
+                            String[] projection = new String[]
+                                    { Integer.valueOf(c.getInt(0)).toString() };
+                            cr.update(Browser.BOOKMARKS_URI, map, "_id = ?",
+                                    projection);
+                        }
+                    } catch (IllegalStateException e) {
+                        Log.e(LOGTAG, "Tab onReceived title", e);
+                    } catch (SQLiteException ex) {
+                        Log.e(LOGTAG,
+                                "onReceivedTitle() caught SQLiteException: ",
+                                ex);
+                    } finally {
+                        if (c != null) c.close();
+                    }
+                    return null;
+                }
+            }.execute();
+        }
+
+        @Override
+        public void onReceivedIcon(WebView view, Bitmap icon) {
+            if (icon != null) {
+                BrowserBookmarksAdapter.updateBookmarkFavicon(mActivity
+                        .getContentResolver(), view.getOriginalUrl(), view
+                        .getUrl(), icon);
+            }
+            if (mInForeground) {
+                mActivity.setFavicon(icon);
+            }
+        }
+
+        @Override
+        public void onReceivedTouchIconUrl(WebView view, String url,
+                boolean precomposed) {
+            final ContentResolver cr = mActivity.getContentResolver();
+            // Let precomposed icons take precedence over non-composed
+            // icons.
+            if (precomposed && mTouchIconLoader != null) {
+                mTouchIconLoader.cancel(false);
+                mTouchIconLoader = null;
+            }
+            // Have only one async task at a time.
+            if (mTouchIconLoader == null) {
+                mTouchIconLoader = new DownloadTouchIcon(Tab.this, cr, view);
+                mTouchIconLoader.execute(url);
+            }
+        }
+
+        @Override
+        public void onShowCustomView(View view,
+                WebChromeClient.CustomViewCallback callback) {
+            if (mInForeground) mActivity.onShowCustomView(view, callback);
+        }
+
+        @Override
+        public void onHideCustomView() {
+            if (mInForeground) mActivity.onHideCustomView();
+        }
+
+        /**
+         * The origin has exceeded its database quota.
+         * @param url the URL that exceeded the quota
+         * @param databaseIdentifier the identifier of the database on which the
+         *            transaction that caused the quota overflow was run
+         * @param currentQuota the current quota for the origin.
+         * @param estimatedSize the estimated size of the database.
+         * @param totalUsedQuota is the sum of all origins' quota.
+         * @param quotaUpdater The callback to run when a decision to allow or
+         *            deny quota has been made. Don't forget to call this!
+         */
+        @Override
+        public void onExceededDatabaseQuota(String url,
+            String databaseIdentifier, long currentQuota, long estimatedSize,
+            long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) {
+            BrowserSettings.getInstance().getWebStorageSizeManager()
+                    .onExceededDatabaseQuota(url, databaseIdentifier,
+                            currentQuota, estimatedSize, totalUsedQuota,
+                            quotaUpdater);
+        }
+
+        /**
+         * The Application Cache has exceeded its max size.
+         * @param spaceNeeded is the amount of disk space that would be needed
+         *            in order for the last appcache operation to succeed.
+         * @param totalUsedQuota is the sum of all origins' quota.
+         * @param quotaUpdater A callback to inform the WebCore thread that a
+         *            new app cache size is available. This callback must always
+         *            be executed at some point to ensure that the sleeping
+         *            WebCore thread is woken up.
+         */
+        @Override
+        public void onReachedMaxAppCacheSize(long spaceNeeded,
+                long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) {
+            BrowserSettings.getInstance().getWebStorageSizeManager()
+                    .onReachedMaxAppCacheSize(spaceNeeded, totalUsedQuota,
+                            quotaUpdater);
+        }
+
+        /**
+         * Instructs the browser to show a prompt to ask the user to set the
+         * Geolocation permission state for the specified origin.
+         * @param origin The origin for which Geolocation permissions are
+         *     requested.
+         * @param callback The callback to call once the user has set the
+         *     Geolocation permission state.
+         */
+        @Override
+        public void onGeolocationPermissionsShowPrompt(String origin,
+                GeolocationPermissions.Callback callback) {
+            if (mInForeground) {
+                getGeolocationPermissionsPrompt().show(origin, callback);
+            }
+        }
+
+        /**
+         * Instructs the browser to hide the Geolocation permissions prompt.
+         */
+        @Override
+        public void onGeolocationPermissionsHidePrompt() {
+            if (mInForeground && mGeolocationPermissionsPrompt != null) {
+                mGeolocationPermissionsPrompt.hide();
+            }
+        }
+
+        /* Adds a JavaScript error message to the system log and if the JS
+         * console is enabled in the about:debug options, to that console
+         * also.
+         * @param consoleMessage the message object.
+         */
+        @Override
+        public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
+            if (mInForeground) {
+                // call getErrorConsole(true) so it will create one if needed
+                ErrorConsoleView errorConsole = getErrorConsole(true);
+                errorConsole.addErrorMessage(consoleMessage);
+                if (mActivity.shouldShowErrorConsole()
+                        && errorConsole.getShowState() != ErrorConsoleView.SHOW_MAXIMIZED) {
+                    errorConsole.showConsole(ErrorConsoleView.SHOW_MINIMIZED);
+                }
+            }
+
+            String message = "Console: " + consoleMessage.message() + " "
+                    + consoleMessage.sourceId() +  ":"
+                    + consoleMessage.lineNumber();
+
+            switch (consoleMessage.messageLevel()) {
+                case TIP:
+                    Log.v(CONSOLE_LOGTAG, message);
+                    break;
+                case LOG:
+                    Log.i(CONSOLE_LOGTAG, message);
+                    break;
+                case WARNING:
+                    Log.w(CONSOLE_LOGTAG, message);
+                    break;
+                case ERROR:
+                    Log.e(CONSOLE_LOGTAG, message);
+                    break;
+                case DEBUG:
+                    Log.d(CONSOLE_LOGTAG, message);
+                    break;
+            }
+
+            return true;
+        }
+
+        /**
+         * Ask the browser for an icon to represent a <video> element.
+         * This icon will be used if the Web page did not specify a poster attribute.
+         * @return Bitmap The icon or null if no such icon is available.
+         */
+        @Override
+        public Bitmap getDefaultVideoPoster() {
+            if (mInForeground) {
+                return mActivity.getDefaultVideoPoster();
+            }
+            return null;
+        }
+
+        /**
+         * Ask the host application for a custom progress view to show while
+         * a <video> is loading.
+         * @return View The progress view.
+         */
+        @Override
+        public View getVideoLoadingProgressView() {
+            if (mInForeground) {
+                return mActivity.getVideoLoadingProgressView();
+            }
+            return null;
+        }
+
+        @Override
+        public void openFileChooser(ValueCallback<Uri> uploadMsg) {
+            if (mInForeground) {
+                mActivity.openFileChooser(uploadMsg);
+            } else {
+                uploadMsg.onReceiveValue(null);
+            }
+        }
+
+        /**
+         * Deliver a list of already-visited URLs
+         */
+        @Override
+        public void getVisitedHistory(final ValueCallback<String[]> callback) {
+            AsyncTask<Void, Void, String[]> task = new AsyncTask<Void, Void, String[]>() {
+                public String[] doInBackground(Void... unused) {
+                    return Browser.getVisitedHistory(mActivity
+                            .getContentResolver());
+                }
+                public void onPostExecute(String[] result) {
+                    callback.onReceiveValue(result);
+                };
+            };
+            task.execute();
+        };
+    };
+
+    // -------------------------------------------------------------------------
+    // WebViewClient implementation for the sub window
+    // -------------------------------------------------------------------------
+
+    // Subclass of WebViewClient used in subwindows to notify the main
+    // WebViewClient of certain WebView activities.
+    private static class SubWindowClient extends WebViewClient {
+        // The main WebViewClient.
+        private final WebViewClient mClient;
+
+        SubWindowClient(WebViewClient client) {
+            mClient = client;
+        }
+        @Override
+        public void doUpdateVisitedHistory(WebView view, String url,
+                boolean isReload) {
+            mClient.doUpdateVisitedHistory(view, url, isReload);
+        }
+        @Override
+        public boolean shouldOverrideUrlLoading(WebView view, String url) {
+            return mClient.shouldOverrideUrlLoading(view, url);
+        }
+        @Override
+        public void onReceivedSslError(WebView view, SslErrorHandler handler,
+                SslError error) {
+            mClient.onReceivedSslError(view, handler, error);
+        }
+        @Override
+        public void onReceivedHttpAuthRequest(WebView view,
+                HttpAuthHandler handler, String host, String realm) {
+            mClient.onReceivedHttpAuthRequest(view, handler, host, realm);
+        }
+        @Override
+        public void onFormResubmission(WebView view, Message dontResend,
+                Message resend) {
+            mClient.onFormResubmission(view, dontResend, resend);
+        }
+        @Override
+        public void onReceivedError(WebView view, int errorCode,
+                String description, String failingUrl) {
+            mClient.onReceivedError(view, errorCode, description, failingUrl);
+        }
+        @Override
+        public boolean shouldOverrideKeyEvent(WebView view,
+                android.view.KeyEvent event) {
+            return mClient.shouldOverrideKeyEvent(view, event);
+        }
+        @Override
+        public void onUnhandledKeyEvent(WebView view,
+                android.view.KeyEvent event) {
+            mClient.onUnhandledKeyEvent(view, event);
+        }
+    }
+
+    // -------------------------------------------------------------------------
+    // WebChromeClient implementation for the sub window
+    // -------------------------------------------------------------------------
+
+    private class SubWindowChromeClient extends WebChromeClient {
+        // The main WebChromeClient.
+        private final WebChromeClient mClient;
+
+        SubWindowChromeClient(WebChromeClient client) {
+            mClient = client;
+        }
+        @Override
+        public void onProgressChanged(WebView view, int newProgress) {
+            mClient.onProgressChanged(view, newProgress);
+        }
+        @Override
+        public boolean onCreateWindow(WebView view, boolean dialog,
+                boolean userGesture, android.os.Message resultMsg) {
+            return mClient.onCreateWindow(view, dialog, userGesture, resultMsg);
+        }
+        @Override
+        public void onCloseWindow(WebView window) {
+            if (window != mSubView) {
+                Log.e(LOGTAG, "Can't close the window");
+            }
+            mActivity.dismissSubWindow(Tab.this);
+        }
+    }
+
+    // -------------------------------------------------------------------------
+
+    // Construct a new tab
+    Tab(BrowserActivity activity, WebView w, boolean closeOnExit, String appId,
+            String url) {
+        mActivity = activity;
+        mCloseOnExit = closeOnExit;
+        mAppId = appId;
+        mOriginalUrl = url;
+        mLockIconType = BrowserActivity.LOCK_ICON_UNSECURE;
+        mPrevLockIconType = BrowserActivity.LOCK_ICON_UNSECURE;
+        mInLoad = false;
+        mInForeground = false;
+
+        mInflateService = LayoutInflater.from(activity);
+
+        // 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);
+
+        mDownloadListener = new DownloadListener() {
+            public void onDownloadStart(String url, String userAgent,
+                    String contentDisposition, String mimetype,
+                    long contentLength) {
+                mActivity.onDownloadStart(url, userAgent, contentDisposition,
+                        mimetype, contentLength);
+                if (mMainView.copyBackForwardList().getSize() == 0) {
+                    // This Tab was opened for the sole purpose of downloading a
+                    // file. Remove it.
+                    if (mActivity.getTabControl().getCurrentWebView()
+                            == mMainView) {
+                        // In this case, the Tab is still on top.
+                        mActivity.goBackOnePageOrQuit();
+                    } else {
+                        // In this case, it is not.
+                        mActivity.closeTab(Tab.this);
+                    }
+                }
+            }
+        };
+        mWebBackForwardListClient = new WebBackForwardListClient() {
+            @Override
+            public void onNewHistoryItem(WebHistoryItem item) {
+                if (isInVoiceSearchMode()) {
+                    item.setCustomData(mVoiceSearchData.mVoiceSearchIntent);
+                }
+            }
+            @Override
+            public void onIndexChanged(WebHistoryItem item, int index) {
+                Object data = item.getCustomData();
+                if (data != null && data instanceof Intent) {
+                    activateVoiceSearchMode((Intent) data);
+                }
+            }
+        };
+
+        setWebView(w);
+    }
+
+    /**
+     * Sets the WebView for this tab, correctly removing the old WebView from
+     * the container view.
+     */
+    void setWebView(WebView w) {
+        if (mMainView == w) {
+            return;
+        }
+        // If the WebView is changing, the page will be reloaded, so any ongoing
+        // Geolocation permission requests are void.
+        if (mGeolocationPermissionsPrompt != null) {
+            mGeolocationPermissionsPrompt.hide();
+        }
+
+        // Just remove the old one.
+        FrameLayout wrapper =
+                (FrameLayout) mContainer.findViewById(R.id.webview_wrapper);
+        wrapper.removeView(mMainView);
+
+        // set the new one
+        mMainView = w;
+        // attach the WebViewClient, WebChromeClient and DownloadListener
+        if (mMainView != null) {
+            mMainView.setWebViewClient(mWebViewClient);
+            mMainView.setWebChromeClient(mWebChromeClient);
+            // Attach DownloadManager so that downloads can start in an active
+            // or a non-active window. This can happen when going to a site that
+            // does a redirect after a period of time. The user could have
+            // switched to another tab while waiting for the download to start.
+            mMainView.setDownloadListener(mDownloadListener);
+            mMainView.setWebBackForwardListClient(mWebBackForwardListClient);
+        }
+    }
+
+    /**
+     * Destroy the tab's main WebView and subWindow if any
+     */
+    void destroy() {
+        if (mMainView != null) {
+            dismissSubWindow();
+            BrowserSettings.getInstance().deleteObserver(mMainView.getSettings());
+            // save the WebView to call destroy() after detach it from the tab
+            WebView webView = mMainView;
+            setWebView(null);
+            webView.destroy();
+        }
+    }
+
+    /**
+     * Remove the tab from the parent
+     */
+    void removeFromTree() {
+        // detach the children
+        if (mChildTabs != null) {
+            for(Tab t : mChildTabs) {
+                t.setParentTab(null);
+            }
+        }
+        // remove itself from the parent list
+        if (mParentTab != null) {
+            mParentTab.mChildTabs.remove(this);
+        }
+    }
+
+    /**
+     * Create a new subwindow unless a subwindow already exists.
+     * @return True if a new subwindow was created. False if one already exists.
+     */
+    boolean createSubWindow() {
+        if (mSubView == null) {
+            mSubViewContainer = mInflateService.inflate(
+                    R.layout.browser_subwindow, null);
+            mSubView = (WebView) mSubViewContainer.findViewById(R.id.webview);
+            mSubView.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY);
+            // use trackball directly
+            mSubView.setMapTrackballToArrowKeys(false);
+            // Enable the built-in zoom
+            mSubView.getSettings().setBuiltInZoomControls(true);
+            mSubView.setWebViewClient(new SubWindowClient(mWebViewClient));
+            mSubView.setWebChromeClient(new SubWindowChromeClient(
+                    mWebChromeClient));
+            // Set a different DownloadListener for the mSubView, since it will
+            // just need to dismiss the mSubView, rather than close the Tab
+            mSubView.setDownloadListener(new DownloadListener() {
+                public void onDownloadStart(String url, String userAgent,
+                        String contentDisposition, String mimetype,
+                        long contentLength) {
+                    mActivity.onDownloadStart(url, userAgent,
+                            contentDisposition, mimetype, contentLength);
+                    if (mSubView.copyBackForwardList().getSize() == 0) {
+                        // This subwindow was opened for the sole purpose of
+                        // downloading a file. Remove it.
+                        dismissSubWindow();
+                    }
+                }
+            });
+            mSubView.setOnCreateContextMenuListener(mActivity);
+            final BrowserSettings s = BrowserSettings.getInstance();
+            s.addObserver(mSubView.getSettings()).update(s, null);
+            final ImageButton cancel = (ImageButton) mSubViewContainer
+                    .findViewById(R.id.subwindow_close);
+            cancel.setOnClickListener(new OnClickListener() {
+                public void onClick(View v) {
+                    mSubView.getWebChromeClient().onCloseWindow(mSubView);
+                }
+            });
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Dismiss the subWindow for the tab.
+     */
+    void dismissSubWindow() {
+        if (mSubView != null) {
+            BrowserSettings.getInstance().deleteObserver(
+                    mSubView.getSettings());
+            mSubView.destroy();
+            mSubView = null;
+            mSubViewContainer = null;
+        }
+    }
+
+    /**
+     * Attach the sub window to the content view.
+     */
+    void attachSubWindow(ViewGroup content) {
+        if (mSubView != null) {
+            content.addView(mSubViewContainer,
+                    BrowserActivity.COVER_SCREEN_PARAMS);
+        }
+    }
+
+    /**
+     * Remove the sub window from the content view.
+     */
+    void removeSubWindow(ViewGroup content) {
+        if (mSubView != null) {
+            content.removeView(mSubViewContainer);
+        }
+    }
+
+    /**
+     * This method attaches both the WebView and any sub window to the
+     * given content view.
+     */
+    void attachTabToContentView(ViewGroup content) {
+        if (mMainView == null) {
+            return;
+        }
+
+        // Attach the WebView to the container and then attach the
+        // container to the content view.
+        FrameLayout wrapper =
+                (FrameLayout) mContainer.findViewById(R.id.webview_wrapper);
+        ViewGroup parent = (ViewGroup) mMainView.getParent();
+        if (parent != wrapper) {
+            if (parent != null) {
+                Log.w(LOGTAG, "mMainView already has a parent in"
+                        + " attachTabToContentView!");
+                parent.removeView(mMainView);
+            }
+            wrapper.addView(mMainView);
+        } else {
+            Log.w(LOGTAG, "mMainView is already attached to wrapper in"
+                    + " attachTabToContentView!");
+        }
+        parent = (ViewGroup) mContainer.getParent();
+        if (parent != content) {
+            if (parent != null) {
+                Log.w(LOGTAG, "mContainer already has a parent in"
+                        + " attachTabToContentView!");
+                parent.removeView(mContainer);
+            }
+            content.addView(mContainer, BrowserActivity.COVER_SCREEN_PARAMS);
+        } else {
+            Log.w(LOGTAG, "mContainer is already attached to content in"
+                    + " attachTabToContentView!");
+        }
+        attachSubWindow(content);
+    }
+
+    /**
+     * Remove the WebView and any sub window from the given content view.
+     */
+    void removeTabFromContentView(ViewGroup content) {
+        if (mMainView == null) {
+            return;
+        }
+
+        // Remove the container from the content and then remove the
+        // WebView from the container. This will trigger a focus change
+        // needed by WebView.
+        FrameLayout wrapper =
+                (FrameLayout) mContainer.findViewById(R.id.webview_wrapper);
+        wrapper.removeView(mMainView);
+        content.removeView(mContainer);
+        removeSubWindow(content);
+    }
+
+    /**
+     * Set the parent tab of this tab.
+     */
+    void setParentTab(Tab parent) {
+        mParentTab = parent;
+        // This tab may have been freed due to low memory. If that is the case,
+        // the parent tab index is already saved. If we are changing that index
+        // (most likely due to removing the parent tab) we must update the
+        // parent tab index in the saved Bundle.
+        if (mSavedState != null) {
+            if (parent == null) {
+                mSavedState.remove(PARENTTAB);
+            } else {
+                mSavedState.putInt(PARENTTAB, mActivity.getTabControl()
+                        .getTabIndex(parent));
+            }
+        }
+    }
+
+    /**
+     * When a Tab is created through the content of another Tab, then we
+     * associate the Tabs.
+     * @param child the Tab that was created from this Tab
+     */
+    void addChildTab(Tab child) {
+        if (mChildTabs == null) {
+            mChildTabs = new Vector<Tab>();
+        }
+        mChildTabs.add(child);
+        child.setParentTab(this);
+    }
+
+    Vector<Tab> getChildTabs() {
+        return mChildTabs;
+    }
+
+    void resume() {
+        if (mMainView != null) {
+            mMainView.onResume();
+            if (mSubView != null) {
+                mSubView.onResume();
+            }
+        }
+    }
+
+    void pause() {
+        if (mMainView != null) {
+            mMainView.onPause();
+            if (mSubView != null) {
+                mSubView.onPause();
+            }
+        }
+    }
+
+    void putInForeground() {
+        mInForeground = true;
+        resume();
+        mMainView.setOnCreateContextMenuListener(mActivity);
+        if (mSubView != null) {
+            mSubView.setOnCreateContextMenuListener(mActivity);
+        }
+        // Show the pending error dialog if the queue is not empty
+        if (mQueuedErrors != null && mQueuedErrors.size() >  0) {
+            showError(mQueuedErrors.getFirst());
+        }
+    }
+
+    void putInBackground() {
+        mInForeground = false;
+        pause();
+        mMainView.setOnCreateContextMenuListener(null);
+        if (mSubView != null) {
+            mSubView.setOnCreateContextMenuListener(null);
+        }
+    }
+
+    /**
+     * Return the top window of this tab; either the subwindow if it is not
+     * null or the main window.
+     * @return The top window of this tab.
+     */
+    WebView getTopWindow() {
+        if (mSubView != null) {
+            return mSubView;
+        }
+        return mMainView;
+    }
+
+    /**
+     * Return the main window of this tab. Note: if a tab is freed in the
+     * background, this can return null. It is only guaranteed to be
+     * non-null for the current tab.
+     * @return The main WebView of this tab.
+     */
+    WebView getWebView() {
+        return mMainView;
+    }
+
+    /**
+     * Return the subwindow of this tab or null if there is no subwindow.
+     * @return The subwindow of this tab or null.
+     */
+    WebView getSubWebView() {
+        return mSubView;
+    }
+
+    /**
+     * @return The geolocation permissions prompt for this tab.
+     */
+    GeolocationPermissionsPrompt getGeolocationPermissionsPrompt() {
+        if (mGeolocationPermissionsPrompt == null) {
+            ViewStub stub = (ViewStub) mContainer
+                    .findViewById(R.id.geolocation_permissions_prompt);
+            mGeolocationPermissionsPrompt = (GeolocationPermissionsPrompt) stub
+                    .inflate();
+            mGeolocationPermissionsPrompt.init();
+        }
+        return mGeolocationPermissionsPrompt;
+    }
+
+    /**
+     * @return The application id string
+     */
+    String getAppId() {
+        return mAppId;
+    }
+
+    /**
+     * Set the application id string
+     * @param id
+     */
+    void setAppId(String id) {
+        mAppId = id;
+    }
+
+    /**
+     * @return The original url associated with this Tab
+     */
+    String getOriginalUrl() {
+        return mOriginalUrl;
+    }
+
+    /**
+     * Set the original url associated with this tab
+     */
+    void setOriginalUrl(String url) {
+        mOriginalUrl = url;
+    }
+
+    /**
+     * Get the url of this tab. Valid after calling populatePickerData, but
+     * before calling wipePickerData, or if the webview has been destroyed.
+     * @return The WebView's url or null.
+     */
+    String getUrl() {
+        if (mPickerData != null) {
+            return mPickerData.mUrl;
+        }
+        return null;
+    }
+
+    /**
+     * Get the title of this tab. Valid after calling populatePickerData, but
+     * before calling wipePickerData, or if the webview has been destroyed. If
+     * the url has no title, use the url instead.
+     * @return The WebView's title (or url) or null.
+     */
+    String getTitle() {
+        if (mPickerData != null) {
+            return mPickerData.mTitle;
+        }
+        return null;
+    }
+
+    /**
+     * Get the favicon of this tab. Valid after calling populatePickerData, but
+     * before calling wipePickerData, or if the webview has been destroyed.
+     * @return The WebView's favicon or null.
+     */
+    Bitmap getFavicon() {
+        if (mPickerData != null) {
+            return mPickerData.mFavicon;
+        }
+        return null;
+    }
+
+    /**
+     * Return the tab's error console. Creates the console if createIfNEcessary
+     * is true and we haven't already created the console.
+     * @param createIfNecessary Flag to indicate if the console should be
+     *            created if it has not been already.
+     * @return The tab's error console, or null if one has not been created and
+     *         createIfNecessary is false.
+     */
+    ErrorConsoleView getErrorConsole(boolean createIfNecessary) {
+        if (createIfNecessary && mErrorConsole == null) {
+            mErrorConsole = new ErrorConsoleView(mActivity);
+            mErrorConsole.setWebView(mMainView);
+        }
+        return mErrorConsole;
+    }
+
+    /**
+     * If this Tab was created through another Tab, then this method returns
+     * that Tab.
+     * @return the Tab parent or null
+     */
+    public Tab getParentTab() {
+        return mParentTab;
+    }
+
+    /**
+     * Return whether this tab should be closed when it is backing out of the
+     * first page.
+     * @return TRUE if this tab should be closed when exit.
+     */
+    boolean closeOnExit() {
+        return mCloseOnExit;
+    }
+
+    /**
+     * Saves the current lock-icon state before resetting the lock icon. If we
+     * have an error, we may need to roll back to the previous state.
+     */
+    void resetLockIcon(String url) {
+        mPrevLockIconType = mLockIconType;
+        mLockIconType = BrowserActivity.LOCK_ICON_UNSECURE;
+        if (URLUtil.isHttpsUrl(url)) {
+            mLockIconType = BrowserActivity.LOCK_ICON_SECURE;
+        }
+    }
+
+    /**
+     * Reverts the lock-icon state to the last saved state, for example, if we
+     * had an error, and need to cancel the load.
+     */
+    void revertLockIcon() {
+        mLockIconType = mPrevLockIconType;
+    }
+
+    /**
+     * @return The tab's lock icon type.
+     */
+    int getLockIconType() {
+        return mLockIconType;
+    }
+
+    /**
+     * @return TRUE if onPageStarted is called while onPageFinished is not
+     *         called yet.
+     */
+    boolean inLoad() {
+        return mInLoad;
+    }
+
+    // force mInLoad to be false. This should only be called before closing the
+    // tab to ensure BrowserActivity's pauseWebViewTimers() is called correctly.
+    void clearInLoad() {
+        mInLoad = false;
+    }
+
+    void populatePickerData() {
+        if (mMainView == null) {
+            populatePickerDataFromSavedState();
+            return;
+        }
+
+        // FIXME: The only place we cared about subwindow was for
+        // bookmarking (i.e. not when saving state). Was this deliberate?
+        final WebBackForwardList list = mMainView.copyBackForwardList();
+        final WebHistoryItem item = list != null ? list.getCurrentItem() : null;
+        populatePickerData(item);
+    }
+
+    // Populate the picker data using the given history item and the current top
+    // WebView.
+    private void populatePickerData(WebHistoryItem item) {
+        mPickerData = new PickerData();
+        if (item != null) {
+            mPickerData.mUrl = item.getUrl();
+            mPickerData.mTitle = item.getTitle();
+            mPickerData.mFavicon = item.getFavicon();
+            if (mPickerData.mTitle == null) {
+                mPickerData.mTitle = mPickerData.mUrl;
+            }
+        }
+    }
+
+    // Create the PickerData and populate it using the saved state of the tab.
+    void populatePickerDataFromSavedState() {
+        if (mSavedState == null) {
+            return;
+        }
+        mPickerData = new PickerData();
+        mPickerData.mUrl = mSavedState.getString(CURRURL);
+        mPickerData.mTitle = mSavedState.getString(CURRTITLE);
+    }
+
+    void clearPickerData() {
+        mPickerData = null;
+    }
+
+    /**
+     * Get the saved state bundle.
+     * @return
+     */
+    Bundle getSavedState() {
+        return mSavedState;
+    }
+
+    /**
+     * Set the saved state.
+     */
+    void setSavedState(Bundle state) {
+        mSavedState = state;
+    }
+
+    /**
+     * @return TRUE if succeed in saving the state.
+     */
+    boolean saveState() {
+        // If the WebView is null it means we ran low on memory and we already
+        // stored the saved state in mSavedState.
+        if (mMainView == null) {
+            return mSavedState != null;
+        }
+
+        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;
+        populatePickerData(item);
+
+        if (mPickerData.mUrl != null) {
+            mSavedState.putString(CURRURL, mPickerData.mUrl);
+        }
+        if (mPickerData.mTitle != null) {
+            mSavedState.putString(CURRTITLE, mPickerData.mTitle);
+        }
+        mSavedState.putBoolean(CLOSEONEXIT, mCloseOnExit);
+        if (mAppId != null) {
+            mSavedState.putString(APPID, mAppId);
+        }
+        if (mOriginalUrl != null) {
+            mSavedState.putString(ORIGINALURL, mOriginalUrl);
+        }
+        // Remember the parent tab so the relationship can be restored.
+        if (mParentTab != null) {
+            mSavedState.putInt(PARENTTAB, mActivity.getTabControl().getTabIndex(
+                    mParentTab));
+        }
+        return true;
+    }
+
+    /*
+     * Restore the state of the tab.
+     */
+    boolean restoreState(Bundle b) {
+        if (b == null) {
+            return false;
+        }
+        // Restore the internal state even if the WebView fails to restore.
+        // This will maintain the app id, original url and close-on-exit values.
+        mSavedState = null;
+        mPickerData = null;
+        mCloseOnExit = b.getBoolean(CLOSEONEXIT);
+        mAppId = b.getString(APPID);
+        mOriginalUrl = b.getString(ORIGINALURL);
+
+        final WebBackForwardList list = mMainView.restoreState(b);
+        if (list == null) {
+            return false;
+        }
+        if (b.containsKey(CURRPICTURE)) {
+            final File f = new File(b.getString(CURRPICTURE));
+            mMainView.restorePicture(b, f);
+            f.delete();
+        }
+        return true;
+    }
+}
diff --git a/src/com/android/browser/TabControl.java b/src/com/android/browser/TabControl.java
index c03fdf4..7cd2ccb 100644
--- a/src/com/android/browser/TabControl.java
+++ b/src/com/android/browser/TabControl.java
@@ -16,37 +16,18 @@
 
 package com.android.browser;
 
-import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.BitmapShader;
 import android.graphics.Paint;
-import android.graphics.Picture;
 import android.graphics.Shader;
-import android.net.http.SslError;
 import android.os.Bundle;
-import android.os.Message;
 import android.util.Log;
-import android.view.Gravity;
-import android.view.LayoutInflater;
 import android.view.View;
-import android.view.ViewGroup;
-import android.view.View.OnClickListener;
-import android.webkit.HttpAuthHandler;
-import android.webkit.JsPromptResult;
-import android.webkit.JsResult;
-import android.webkit.SslErrorHandler;
 import android.webkit.WebBackForwardList;
-import android.webkit.WebChromeClient;
-import android.webkit.WebHistoryItem;
 import android.webkit.WebView;
-import android.webkit.WebViewClient;
-import android.widget.FrameLayout;
-import android.widget.ImageButton;
-import android.widget.LinearLayout;
 
 import java.io.File;
-import java.io.FileInputStream;
 import java.util.ArrayList;
 import java.util.Vector;
 
@@ -54,13 +35,7 @@
     // Log Tag
     private static final String LOGTAG = "TabControl";
     // Maximum number of tabs.
-    static final int MAX_TABS = 8;
-    // Static instance of an empty callback.
-    private static final WebViewClient mEmptyClient =
-            new WebViewClient();
-    // Instance of BackgroundChromeClient for background tabs.
-    private final BackgroundChromeClient mBackgroundChromeClient =
-            new BackgroundChromeClient();
+    private static final int MAX_TABS = 8;
     // Private array of WebViews that are used as tabs.
     private ArrayList<Tab> mTabs = new ArrayList<Tab>(MAX_TABS);
     // Queue of most recently viewed tabs.
@@ -70,393 +45,6 @@
     // A private instance of BrowserActivity to interface with when adding and
     // switching between tabs.
     private final BrowserActivity mActivity;
-    // Inflation service for making subwindows.
-    private final LayoutInflater mInflateService;
-    // Subclass of WebViewClient used in subwindows to notify the main
-    // WebViewClient of certain WebView activities.
-    private static class SubWindowClient extends WebViewClient {
-        // The main WebViewClient.
-        private final WebViewClient mClient;
-
-        SubWindowClient(WebViewClient client) {
-            mClient = client;
-        }
-        @Override
-        public void doUpdateVisitedHistory(WebView view, String url,
-                boolean isReload) {
-            mClient.doUpdateVisitedHistory(view, url, isReload);
-        }
-        @Override
-        public boolean shouldOverrideUrlLoading(WebView view, String url) {
-            return mClient.shouldOverrideUrlLoading(view, url);
-        }
-        @Override
-        public void onReceivedSslError(WebView view, SslErrorHandler handler,
-                SslError error) {
-            mClient.onReceivedSslError(view, handler, error);
-        }
-        @Override
-        public void onReceivedHttpAuthRequest(WebView view,
-                HttpAuthHandler handler, String host, String realm) {
-            mClient.onReceivedHttpAuthRequest(view, handler, host, realm);
-        }
-        @Override
-        public void onFormResubmission(WebView view, Message dontResend,
-                Message resend) {
-            mClient.onFormResubmission(view, dontResend, resend);
-        }
-        @Override
-        public void onReceivedError(WebView view, int errorCode,
-                String description, String failingUrl) {
-            mClient.onReceivedError(view, errorCode, description, failingUrl);
-        }
-        @Override
-        public boolean shouldOverrideKeyEvent(WebView view,
-                android.view.KeyEvent event) {
-            return mClient.shouldOverrideKeyEvent(view, event);
-        }
-        @Override
-        public void onUnhandledKeyEvent(WebView view,
-                android.view.KeyEvent event) {
-            mClient.onUnhandledKeyEvent(view, event);
-        }
-    }
-    // Subclass of WebChromeClient to display javascript dialogs.
-    private class SubWindowChromeClient extends WebChromeClient {
-        // This subwindow's tab.
-        private final Tab mTab;
-        // The main WebChromeClient.
-        private final WebChromeClient mClient;
-
-        SubWindowChromeClient(Tab t, WebChromeClient client) {
-            mTab = t;
-            mClient = client;
-        }
-        @Override
-        public void onProgressChanged(WebView view, int newProgress) {
-            mClient.onProgressChanged(view, newProgress);
-        }
-        @Override
-        public boolean onCreateWindow(WebView view, boolean dialog,
-                boolean userGesture, android.os.Message resultMsg) {
-            return mClient.onCreateWindow(view, dialog, userGesture, resultMsg);
-        }
-        @Override
-        public void onCloseWindow(WebView window) {
-            if (Browser.DEBUG && window != mTab.mSubView) {
-                throw new AssertionError("Can't close the window");
-            }
-            mActivity.dismissSubWindow(mTab);
-        }
-    }
-    // Background WebChromeClient for focusing tabs
-    private class BackgroundChromeClient extends WebChromeClient {
-        @Override
-        public void onRequestFocus(WebView view) {
-            Tab t = getTabFromView(view);
-            if (t != getCurrentTab()) {
-                mActivity.switchToTab(getTabIndex(t));
-            }
-        }
-    }
-
-    // Extra saved information for displaying the tab in the picker.
-    public static class PickerData {
-        String  mUrl;
-        String  mTitle;
-        Bitmap  mFavicon;
-        float   mScale;
-        int     mScrollX;
-        int     mScrollY;
-    }
-
-    /**
-     * Private class for maintaining Tabs with a main WebView and a subwindow.
-     */
-    public class Tab {
-        // The Geolocation permissions prompt
-        private GeolocationPermissionsPrompt mGeolocationPermissionsPrompt;
-        private View mContainer;
-        // Main WebView
-        private WebView mMainView;
-        // Subwindow WebView
-        private WebView mSubView;
-        // Subwindow container
-        private View mSubViewContainer;
-        // Subwindow callback
-        private SubWindowClient mSubViewClient;
-        // Subwindow chrome callback
-        private SubWindowChromeClient mSubViewChromeClient;
-        // Saved bundle for when we are running low on memory. It contains the
-        // information needed to restore the WebView if the user goes back to
-        // the tab.
-        private Bundle mSavedState;
-        // Data used when displaying the tab in the picker.
-        private PickerData mPickerData;
-
-        // Parent Tab. This is the Tab that created this Tab, or null
-        // if the Tab was created by the UI
-        private Tab mParentTab;
-        // Tab that constructed by this Tab. This is used when this
-        // Tab is destroyed, it clears all mParentTab values in the 
-        // children.
-        private Vector<Tab> mChildTabs;
-
-        private Boolean mCloseOnExit;
-        // Application identifier used to find tabs that another application
-        // wants to reuse.
-        private String mAppId;
-        // Keep the original url around to avoid killing the old WebView if the
-        // url has not changed.
-        private String mOriginalUrl;
-
-        private ErrorConsoleView mErrorConsole;
-        // the lock icon type and previous lock icon type for the tab
-        private int mSavedLockIconType;
-        private int mSavedPrevLockIconType;
-
-        // Construct a new tab
-        private Tab(WebView w, boolean closeOnExit, String appId, String url, Context context) {
-            mCloseOnExit = closeOnExit;
-            mAppId = appId;
-            mOriginalUrl = url;
-            mSavedLockIconType = BrowserActivity.LOCK_ICON_UNSECURE;
-            mSavedPrevLockIconType = BrowserActivity.LOCK_ICON_UNSECURE;
-
-            // The tab consists of a container view, which contains the main
-            // WebView, as well as any other UI elements associated with the tab.
-            LayoutInflater factory = LayoutInflater.from(context);
-            mContainer = factory.inflate(R.layout.tab, null);
-
-            mGeolocationPermissionsPrompt =
-                (GeolocationPermissionsPrompt) mContainer.findViewById(
-                    R.id.geolocation_permissions_prompt);
-
-            setWebView(w);
-        }
-
-        /**
-         * Sets the WebView for this tab, correctly removing the old WebView
-         * from the container view.
-         */
-        public void setWebView(WebView w) {
-            if (mMainView == w) {
-                return;
-            }
-            // If the WebView is changing, the page will be reloaded, so any ongoing Geolocation
-            // permission requests are void.
-            mGeolocationPermissionsPrompt.hide();
-
-            // Just remove the old one.
-            FrameLayout wrapper =
-                    (FrameLayout) mContainer.findViewById(R.id.webview_wrapper);
-            wrapper.removeView(mMainView);
-            mMainView = w;
-        }
-
-        /**
-         * This method attaches both the WebView and any sub window to the
-         * given content view.
-         */
-        public void attachTabToContentView(ViewGroup content) {
-            if (mMainView == null) {
-                return;
-            }
-
-            // Attach the WebView to the container and then attach the
-            // container to the content view.
-            FrameLayout wrapper =
-                    (FrameLayout) mContainer.findViewById(R.id.webview_wrapper);
-            wrapper.addView(mMainView);
-            content.addView(mContainer, BrowserActivity.COVER_SCREEN_PARAMS);
-            attachSubWindow(content);
-        }
-
-        /**
-         * Remove the WebView and any sub window from the given content view.
-         */
-        public void removeTabFromContentView(ViewGroup content) {
-            if (mMainView == null) {
-                return;
-            }
-
-            // Remove the container from the content and then remove the
-            // WebView from the container. This will trigger a focus change
-            // needed by WebView.
-            FrameLayout wrapper =
-                    (FrameLayout) mContainer.findViewById(R.id.webview_wrapper);
-            wrapper.removeView(mMainView);
-            content.removeView(mContainer);
-            removeSubWindow(content);
-        }
-
-        /**
-         * Attach the sub window to the content view.
-         */
-        public void attachSubWindow(ViewGroup content) {
-            if (mSubView != null) {
-                content.addView(mSubViewContainer,
-                        BrowserActivity.COVER_SCREEN_PARAMS);
-            }
-        }
-
-        /**
-         * Remove the sub window from the content view.
-         */
-        public void removeSubWindow(ViewGroup content) {
-            if (mSubView != null) {
-                content.removeView(mSubViewContainer);
-            }
-        }
-
-        /**
-         * Return the top window of this tab; either the subwindow if it is not
-         * null or the main window.
-         * @return The top window of this tab.
-         */
-        public WebView getTopWindow() {
-            if (mSubView != null) {
-                return mSubView;
-            }
-            return mMainView;
-        }
-
-        /**
-         * Return the main window of this tab. Note: if a tab is freed in the
-         * background, this can return null. It is only guaranteed to be 
-         * non-null for the current tab.
-         * @return The main WebView of this tab.
-         */
-        public WebView getWebView() {
-            return mMainView;
-        }
-
-        /**
-         * @return The geolocation permissions prompt for this tab.
-         */
-        public GeolocationPermissionsPrompt getGeolocationPermissionsPrompt() {
-            return mGeolocationPermissionsPrompt;
-        }
-
-        /**
-         * Return the subwindow of this tab or null if there is no subwindow.
-         * @return The subwindow of this tab or null.
-         */
-        public WebView getSubWebView() {
-            return mSubView;
-        }
-
-        /**
-         * Get the url of this tab.  Valid after calling populatePickerData, but
-         * before calling wipePickerData, or if the webview has been destroyed.
-         * 
-         * @return The WebView's url or null.
-         */
-        public String getUrl() {
-            if (mPickerData != null) {
-                return mPickerData.mUrl;
-            }
-            return null;
-        }
-
-        /**
-         * Get the title of this tab.  Valid after calling populatePickerData, 
-         * but before calling wipePickerData, or if the webview has been 
-         * destroyed.  If the url has no title, use the url instead.
-         * 
-         * @return The WebView's title (or url) or null.
-         */
-        public String getTitle() {
-            if (mPickerData != null) {
-                return mPickerData.mTitle;
-            }
-            return null;
-        }
-
-        public Bitmap getFavicon() {
-            if (mPickerData != null) {
-                return mPickerData.mFavicon;
-            }
-            return null;
-        }
-
-        private void setParentTab(Tab parent) {
-            mParentTab = parent;
-            // This tab may have been freed due to low memory. If that is the
-            // case, the parent tab index is already saved. If we are changing
-            // that index (most likely due to removing the parent tab) we must
-            // update the parent tab index in the saved Bundle.
-            if (mSavedState != null) {
-                if (parent == null) {
-                    mSavedState.remove(PARENTTAB);
-                } else {
-                    mSavedState.putInt(PARENTTAB, getTabIndex(parent));
-                }
-            }
-        }
-        
-        /**
-         * When a Tab is created through the content of another Tab, then 
-         * we associate the Tabs. 
-         * @param child the Tab that was created from this Tab
-         */
-        public void addChildTab(Tab child) {
-            if (mChildTabs == null) {
-                mChildTabs = new Vector<Tab>();
-            }
-            mChildTabs.add(child);
-            child.setParentTab(this);
-        }
-        
-        private void removeFromTree() {
-            // detach the children
-            if (mChildTabs != null) {
-                for(Tab t : mChildTabs) {
-                    t.setParentTab(null);
-                }
-            }
-            
-            // Find myself in my parent list
-            if (mParentTab != null) {
-                mParentTab.mChildTabs.remove(this);
-            }
-        }
-        
-        /**
-         * If this Tab was created through another Tab, then this method
-         * returns that Tab.
-         * @return the Tab parent or null
-         */
-        public Tab getParentTab() {
-            return mParentTab;
-        }
-
-        /**
-         * Return whether this tab should be closed when it is backing out of
-         * the first page.
-         * @return TRUE if this tab should be closed when exit.
-         */
-        public boolean closeOnExit() {
-            return mCloseOnExit;
-        }
-
-        void setLockIconType(int type) {
-            mSavedLockIconType = type;
-        }
-
-        int getLockIconType() {
-            return mSavedLockIconType;
-        }
-
-        void setPrevLockIconType(int type) {
-            mSavedPrevLockIconType = type;
-        }
-
-        int getPrevLockIconType() {
-            return mSavedPrevLockIconType;
-        }
-    };
-
     // Directory to store thumbnails for each WebView.
     private final File mThumbnailDir;
 
@@ -468,9 +56,6 @@
      */
     TabControl(BrowserActivity activity) {
         mActivity = activity;
-        mInflateService =
-                ((LayoutInflater) activity.getSystemService(
-                        Context.LAYOUT_INFLATER_SERVICE));
         mThumbnailDir = activity.getDir("thumbnails", 0);
     }
 
@@ -492,29 +77,7 @@
         if (t == null) {
             return null;
         }
-        return t.mMainView;
-    }
-
-    /**
-     * Return the current tab's error console. Creates the console if createIfNEcessary
-     * is true and we haven't already created the console.
-     * @param createIfNecessary Flag to indicate if the console should be created if it has
-     *                          not been already.
-     * @return The current tab's error console, or null if one has not been created and
-     *         createIfNecessary is false.
-     */
-    ErrorConsoleView getCurrentErrorConsole(boolean createIfNecessary) {
-        Tab t = getTab(mCurrentTab);
-        if (t == null) {
-            return null;
-        }
-
-        if (createIfNecessary && t.mErrorConsole == null) {
-            t.mErrorConsole = new ErrorConsoleView(mActivity);
-            t.mErrorConsole.setWebView(t.mMainView);
-        }
-
-        return t.mErrorConsole;
+        return t.getWebView();
     }
 
     /**
@@ -527,7 +90,7 @@
         if (t == null) {
             return null;
         }
-        return t.mSubView != null ? t.mSubView : t.mMainView;
+        return t.getTopWindow();
     }
 
     /**
@@ -539,7 +102,7 @@
         if (t == null) {
             return null;
         }
-        return t.mSubView;
+        return t.getSubWebView();
     }
 
     /**
@@ -582,6 +145,10 @@
         return mTabs.indexOf(tab);
     }
 
+    boolean canCreateNewTab() {
+        return MAX_TABS != mTabs.size();
+    }
+
     /**
      * Create a new tab.
      * @return The newly createTab or null if we have reached the maximum
@@ -596,10 +163,10 @@
         final WebView w = createNewWebView();
 
         // Create a new tab and add it to the tab list
-        Tab t = new Tab(w, closeOnExit, appId, url, mActivity);
+        Tab t = new Tab(mActivity, w, closeOnExit, appId, url);
         mTabs.add(t);
         // Initially put the tab in the background.
-        putTabInBackground(t);
+        t.putInBackground();
         return t;
     }
 
@@ -612,6 +179,15 @@
     }
 
     /**
+     * Remove the parent child relationships from all tabs.
+     */
+    void removeParentChildRelationShips() {
+        for (Tab tab : mTabs) {
+            tab.removeFromTree();
+        }
+    }
+
+    /**
      * Remove the tab from the list. If the tab is the current tab shown, the
      * last created tab will be shown.
      * @param t The tab to be removed.
@@ -620,86 +196,59 @@
         if (t == null) {
             return false;
         }
-        // Only remove the tab if it is the current one.
-        if (getCurrentTab() == t) {
-            putTabInBackground(t);
+
+        // Grab the current tab before modifying the list.
+        Tab current = getCurrentTab();
+
+        // Remove t from our list of tabs.
+        mTabs.remove(t);
+
+        // Put the tab in the background only if it is the current one.
+        if (current == t) {
+            t.putInBackground();
+            mCurrentTab = -1;
+        } else {
+            // If a tab that is earlier in the list gets removed, the current
+            // index no longer points to the correct tab.
+            mCurrentTab = getTabIndex(current);
         }
 
-        // Only destroy the WebView if it still exists.
-        if (t.mMainView != null) {
-            // Take down the sub window.
-            dismissSubWindow(t);
-            // Remove the WebView's settings from the BrowserSettings list of
-            // observers.
-            BrowserSettings.getInstance().deleteObserver(
-                    t.mMainView.getSettings());
-            WebView w = t.mMainView;
-            t.setWebView(null);
-            // Destroy the main view
-            w.destroy();
-        }
+        // destroy the tab
+        t.destroy();
         // clear it's references to parent and children
         t.removeFromTree();
-        
-        // Remove it from our list of tabs.
-        mTabs.remove(t);
 
         // The tab indices have shifted, update all the saved state so we point
         // to the correct index.
         for (Tab tab : mTabs) {
-            if (tab.mChildTabs != null) {
-                for (Tab child : tab.mChildTabs) {
+            Vector<Tab> children = tab.getChildTabs();
+            if (children != null) {
+                for (Tab child : children) {
                     child.setParentTab(tab);
                 }
             }
         }
 
-
         // This tab may have been pushed in to the background and then closed.
         // If the saved state contains a picture file, delete the file.
-        if (t.mSavedState != null) {
-            if (t.mSavedState.containsKey(CURRPICTURE)) {
-                new File(t.mSavedState.getString(CURRPICTURE)).delete();
+        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);
-        mCurrentTab = -1;
         return true;
     }
 
     /**
-     * Clear the back/forward list for all the current tabs.
-     */
-    void clearHistory() {
-        int size = getTabCount();
-        for (int i = 0; i < size; i++) {
-            Tab t = mTabs.get(i);
-            // TODO: if a tab is freed due to low memory, its history is not
-            // cleared here.
-            if (t.mMainView != null) {
-                t.mMainView.clearHistory();
-            }
-            if (t.mSubView != null) {
-                t.mSubView.clearHistory();
-            }
-        }
-    }
-
-    /**
      * Destroy all the tabs and subwindows
      */
     void destroy() {
-        BrowserSettings s = BrowserSettings.getInstance();
         for (Tab t : mTabs) {
-            if (t.mMainView != null) {
-                dismissSubWindow(t);
-                s.deleteObserver(t.mMainView.getSettings());
-                WebView w = t.mMainView;
-                t.setWebView(null);
-                w.destroy();
-            }
+            t.destroy();
         }
         mTabs.clear();
         mTabQueue.clear();
@@ -713,17 +262,6 @@
         return mTabs.size();
     }
 
-    // Used for saving and restoring each Tab
-    private static final String WEBVIEW = "webview";
-    private static final String NUMTABS = "numTabs";
-    private static final String CURRTAB = "currentTab";
-    private static final String CURRURL = "currentUrl";
-    private static final String CURRTITLE = "currentTitle";
-    private static final String CURRPICTURE = "currentPicture";
-    private static final String CLOSEONEXIT = "closeonexit";
-    private static final String PARENTTAB = "parentTab";
-    private static final String APPID = "appid";
-    private static final String ORIGINALURL = "originalUrl";
 
     /**
      * Save the state of all the Tabs.
@@ -731,13 +269,13 @@
      */
     void saveState(Bundle outState) {
         final int numTabs = getTabCount();
-        outState.putInt(NUMTABS, numTabs);
+        outState.putInt(Tab.NUMTABS, numTabs);
         final int index = getCurrentIndex();
-        outState.putInt(CURRTAB, (index >= 0 && index < numTabs) ? index : 0);
+        outState.putInt(Tab.CURRTAB, (index >= 0 && index < numTabs) ? index : 0);
         for (int i = 0; i < numTabs; i++) {
             final Tab t = getTab(i);
-            if (saveState(t)) {
-                outState.putBundle(WEBVIEW + i, t.mSavedState);
+            if (t.saveState()) {
+                outState.putBundle(Tab.WEBVIEW + i, t.getSavedState());
             }
         }
     }
@@ -750,45 +288,47 @@
      */
     boolean restoreState(Bundle inState) {
         final int numTabs = (inState == null)
-                ? -1 : inState.getInt(NUMTABS, -1);
+                ? -1 : inState.getInt(Tab.NUMTABS, -1);
         if (numTabs == -1) {
             return false;
         } else {
-            final int currentTab = inState.getInt(CURRTAB, -1);
+            final int currentTab = inState.getInt(Tab.CURRTAB, -1);
             for (int i = 0; i < numTabs; i++) {
                 if (i == currentTab) {
                     Tab t = createNewTab();
                     // Me must set the current tab before restoring the state
                     // so that all the client classes are set.
                     setCurrentTab(t);
-                    if (!restoreState(inState.getBundle(WEBVIEW + i), t)) {
+                    if (!t.restoreState(inState.getBundle(Tab.WEBVIEW + i))) {
                         Log.w(LOGTAG, "Fail in restoreState, load home page.");
-                        t.mMainView.loadUrl(BrowserSettings.getInstance()
+                        t.getWebView().loadUrl(BrowserSettings.getInstance()
                                 .getHomePage());
                     }
                 } else {
                     // Create a new tab and don't restore the state yet, add it
                     // to the tab list
-                    Tab t = new Tab(null, false, null, null, mActivity);
-                    t.mSavedState = inState.getBundle(WEBVIEW + i);
-                    if (t.mSavedState != null) {
-                        populatePickerDataFromSavedState(t);
+                    Tab t = new Tab(mActivity, null, false, null, null);
+                    Bundle state = inState.getBundle(Tab.WEBVIEW + i);
+                    if (state != null) {
+                        t.setSavedState(state);
+                        t.populatePickerDataFromSavedState();
                         // Need to maintain the app id and original url so we
                         // can possibly reuse this tab.
-                        t.mAppId = t.mSavedState.getString(APPID);
-                        t.mOriginalUrl = t.mSavedState.getString(ORIGINALURL);
+                        t.setAppId(state.getString(Tab.APPID));
+                        t.setOriginalUrl(state.getString(Tab.ORIGINALURL));
                     }
                     mTabs.add(t);
-                    mTabQueue.add(t);
+                    // added the tab to the front as they are not current
+                    mTabQueue.add(0, t);
                 }
             }
             // Rebuild the tree of tabs. Do this after all tabs have been
             // created/restored so that the parent tab exists.
             for (int i = 0; i < numTabs; i++) {
-                final Bundle b = inState.getBundle(WEBVIEW + i);
+                final Bundle b = inState.getBundle(Tab.WEBVIEW + i);
                 final Tab t = getTab(i);
                 if (b != null && t != null) {
-                    final int parentIndex = b.getInt(PARENTTAB, -1);
+                    final int parentIndex = b.getInt(Tab.PARENTTAB, -1);
                     if (parentIndex != -1) {
                         final Tab parent = getTab(parentIndex);
                         if (parent != null) {
@@ -802,19 +342,22 @@
     }
 
     /**
-     * Free the memory in this order, 1) free the background tab; 2) free the
+     * Free the memory in this order, 1) free the background tabs; 2) free the
      * WebView cache;
      */
     void freeMemory() {
         if (getTabCount() == 0) return;
 
-        // free the least frequently used background tab
-        Tab t = getLeastUsedTab(getCurrentTab());
-        if (t != null) {
-            Log.w(LOGTAG, "Free a tab in the browser");
-            freeTab(t);
-            // force a gc
-            System.gc();
+        // free the least frequently used background tabs
+        Vector<Tab> tabs = getHalfLeastUsedTabs(getCurrentTab());
+        if (tabs.size() > 0) {
+            Log.w(LOGTAG, "Free " + tabs.size() + " tabs in the browser");
+            for (Tab t : tabs) {
+                // store the WebView's state.
+                t.saveState();
+                // destroy the tab
+                t.destroy();
+            }
             return;
         }
 
@@ -824,89 +367,40 @@
         if (view != null) {
             view.freeMemory();
         }
-        // force a gc
-        System.gc();
     }
 
-    private Tab getLeastUsedTab(Tab current) {
+    private Vector<Tab> getHalfLeastUsedTabs(Tab current) {
+        Vector<Tab> tabsToGo = new Vector<Tab>();
+
         // Don't do anything if we only have 1 tab or if the current tab is
         // null.
         if (getTabCount() == 1 || current == null) {
-            return null;
+            return tabsToGo;
         }
 
-        // Rip through the queue starting at the beginning and teardown the
-        // next available tab.
-        Tab t = null;
-        int i = 0;
-        final int queueSize = mTabQueue.size();
-        if (queueSize == 0) {
-            return null;
-        }
-        do {
-            t = mTabQueue.get(i++);
-        } while (i < queueSize
-                && ((t != null && t.mMainView == null)
-                    || t == current.mParentTab));
-
-        // Don't do anything if the last remaining tab is the current one or if
-        // the last tab has been freed already.
-        if (t == current || t.mMainView == null) {
-            return null;
+        if (mTabQueue.size() == 0) {
+            return tabsToGo;
         }
 
-        return t;
-    }
-
-    private void freeTab(Tab t) {
-        // Store the WebView's state.
-        saveState(t);
-
-        // Tear down the tab.
-        dismissSubWindow(t);
-        // Remove the WebView's settings from the BrowserSettings list of
-        // observers.
-        BrowserSettings.getInstance().deleteObserver(t.mMainView.getSettings());
-        WebView w = t.mMainView;
-        t.setWebView(null);
-        w.destroy();
-    }
-
-    /**
-     * Create a new subwindow unless a subwindow already exists.
-     * @return True if a new subwindow was created. False if one already exists.
-     */
-    void createSubWindow() {
-        Tab t = getTab(mCurrentTab);
-        if (t != null && t.mSubView == null) {
-            final View v = mInflateService.inflate(R.layout.browser_subwindow, null);
-            final WebView w = (WebView) v.findViewById(R.id.webview);
-            w.setMapTrackballToArrowKeys(false); // use trackball directly
-            final SubWindowClient subClient =
-                    new SubWindowClient(mActivity.getWebViewClient());
-            final SubWindowChromeClient subChromeClient =
-                    new SubWindowChromeClient(t,
-                            mActivity.getWebChromeClient());
-            w.setWebViewClient(subClient);
-            w.setWebChromeClient(subChromeClient);
-            w.setDownloadListener(mActivity);
-            w.setOnCreateContextMenuListener(mActivity);
-            final BrowserSettings s = BrowserSettings.getInstance();
-            s.addObserver(w.getSettings()).update(s, null);
-            t.mSubView = w;
-            t.mSubViewClient = subClient;
-            t.mSubViewChromeClient = subChromeClient;
-            // FIXME: I really hate having to know the name of the view
-            // containing the webview.
-            t.mSubViewContainer = v.findViewById(R.id.subwindow_container);
-            final ImageButton cancel =
-                    (ImageButton) v.findViewById(R.id.subwindow_close);
-            cancel.setOnClickListener(new OnClickListener() {
-                    public void onClick(View v) {
-                        subChromeClient.onCloseWindow(w);
-                    }
-                });
+        // Rip through the queue starting at the beginning and tear down half of
+        // available tabs which are not the current tab or the parent of the
+        // current tab.
+        int openTabCount = 0;
+        for (Tab t : mTabQueue) {
+            if (t != null && t.getWebView() != null) {
+                openTabCount++;
+                if (t != current && t != current.getParentTab()) {
+                    tabsToGo.add(t);
+                }
+            }
         }
+
+        openTabCount /= 2;
+        if (tabsToGo.size() > openTabCount) {
+            tabsToGo.setSize(openTabCount);
+        }
+
+        return tabsToGo;
     }
 
     /**
@@ -917,7 +411,7 @@
         final int size = getTabCount();
         for (int i = 0; i < size; i++) {
             final Tab t = getTab(i);
-            if (t.mSubView == view || t.mMainView == view) {
+            if (t.getSubWebView() == view || t.getWebView() == view) {
                 return t;
             }
         }
@@ -935,22 +429,42 @@
         final int size = getTabCount();
         for (int i = 0; i < size; i++) {
             final Tab t = getTab(i);
-            if (id.equals(t.mAppId)) {
+            if (id.equals(t.getAppId())) {
                 return t;
             }
         }
         return null;
     }
 
+    /**
+     * Stop loading in all opened WebView including subWindows.
+     */
+    void stopAllLoading() {
+        final int size = getTabCount();
+        for (int i = 0; i < size; i++) {
+            final Tab t = getTab(i);
+            final WebView webview = t.getWebView();
+            if (webview != null) {
+                webview.stopLoading();
+            }
+            final WebView subview = t.getSubWebView();
+            if (subview != null) {
+                webview.stopLoading();
+            }
+        }
+    }
+
     // This method checks if a non-app tab (one created within the browser)
     // matches the given url.
     private boolean tabMatchesUrl(Tab t, String url) {
-        if (t.mAppId != null) {
+        if (t.getAppId() != null) {
             return false;
-        } else if (t.mMainView == null) {
+        }
+        WebView webview = t.getWebView();
+        if (webview == null) {
             return false;
-        } else if (url.equals(t.mMainView.getUrl()) ||
-                url.equals(t.mMainView.getOriginalUrl())) {
+        } else if (url.equals(webview.getUrl())
+                || url.equals(webview.getOriginalUrl())) {
             return true;
         }
         return false;
@@ -983,12 +497,17 @@
 
     /**
      * Recreate the main WebView of the given tab. Returns true if the WebView
-     * was deleted.
+     * requires a load, whether it was due to the fact that it was deleted, or
+     * it is because it was a voice search.
      */
-    boolean recreateWebView(Tab t, String url) {
-        final WebView w = t.mMainView;
+    boolean recreateWebView(Tab t, BrowserActivity.UrlData urlData) {
+        final String url = urlData.mUrl;
+        final WebView w = t.getWebView();
         if (w != null) {
-            if (url != null && url.equals(t.mOriginalUrl)) {
+            if (url != null && url.equals(t.getOriginalUrl())
+                    // Treat a voice intent as though it is a different URL,
+                    // since it most likely is.
+                    && urlData.mVoiceIntent == null) {
                 // The original url matches the current url. Just go back to the
                 // first history item so we can load it faster than if we
                 // rebuilt the WebView.
@@ -999,11 +518,7 @@
                     return false;
                 }
             }
-            // Remove the settings object from the global settings and destroy
-            // the WebView.
-            BrowserSettings.getInstance().deleteObserver(
-                    t.mMainView.getSettings());
-            t.mMainView.destroy();
+            t.destroy();
         }
         // Create a new WebView. If this tab is the current tab, we need to put
         // back all the clients so force it to be the current tab.
@@ -1011,12 +526,11 @@
         if (getCurrentTab() == t) {
             setCurrentTab(t, true);
         }
-        // Clear the saved state except for the app id and close-on-exit
-        // values.
-        t.mSavedState = null;
-        t.mPickerData = null;
+        // Clear the saved state and picker data
+        t.setSavedState(null);
+        t.clearPickerData();
         // Save the new url in order to avoid deleting the WebView.
-        t.mOriginalUrl = url;
+        t.setOriginalUrl(url);
         return true;
     }
 
@@ -1059,48 +573,20 @@
         return setCurrentTab(newTab, false);
     }
 
-    /*package*/ void pauseCurrentTab() {
+    void pauseCurrentTab() {
         Tab t = getCurrentTab();
         if (t != null) {
-            t.mMainView.onPause();
-            if (t.mSubView != null) {
-                t.mSubView.onPause();
-            }
+            t.pause();
         }
     }
 
-    /*package*/ void resumeCurrentTab() {
+    void resumeCurrentTab() {
         Tab t = getCurrentTab();
         if (t != null) {
-            t.mMainView.onResume();
-            if (t.mSubView != null) {
-                t.mSubView.onResume();
-            }
+            t.resume();
         }
     }
 
-    private void putViewInForeground(WebView v, WebViewClient vc,
-                                     WebChromeClient cc) {
-        v.setWebViewClient(vc);
-        v.setWebChromeClient(cc);
-        v.setOnCreateContextMenuListener(mActivity);
-        v.setDownloadListener(mActivity);
-        v.onResume();
-    }
-
-    private void putViewInBackground(WebView v) {
-        // Set an empty callback so that default actions are not triggered.
-        v.setWebViewClient(mEmptyClient);
-        v.setWebChromeClient(mBackgroundChromeClient);
-        v.setOnCreateContextMenuListener(null);
-        // Leave the DownloadManager attached so that downloads can start in
-        // a non-active window. This can happen when going to a site that does
-        // a redirect after a period of time. The user could have switched to
-        // another tab while waiting for the download to start.
-        v.setDownloadListener(mActivity);
-        v.onPause();
-    }
-
     /**
      * If force is true, this method skips the check for newTab == current.
      */
@@ -1110,10 +596,9 @@
             return true;
         }
         if (current != null) {
-            // Remove the current WebView and the container of the subwindow
-            putTabInBackground(current);
+            current.putInBackground();
+            mCurrentTab = -1;
         }
-
         if (newTab == null) {
             return false;
         }
@@ -1125,214 +610,22 @@
         }
         mTabQueue.add(newTab);
 
-        WebView mainView;
-
         // Display the new current tab
         mCurrentTab = mTabs.indexOf(newTab);
-        mainView = newTab.mMainView;
+        WebView mainView = newTab.getWebView();
         boolean needRestore = (mainView == null);
         if (needRestore) {
             // Same work as in createNewTab() except don't do new Tab()
             mainView = createNewWebView();
             newTab.setWebView(mainView);
         }
-        putViewInForeground(mainView, mActivity.getWebViewClient(),
-                            mActivity.getWebChromeClient());
-        // Add the subwindow if it exists
-        if (newTab.mSubViewContainer != null) {
-            putViewInForeground(newTab.mSubView, newTab.mSubViewClient,
-                                newTab.mSubViewChromeClient);
-        }
+        newTab.putInForeground();
         if (needRestore) {
             // Have to finish setCurrentTab work before calling restoreState
-            if (!restoreState(newTab.mSavedState, newTab)) {
+            if (!newTab.restoreState(newTab.getSavedState())) {
                 mainView.loadUrl(BrowserSettings.getInstance().getHomePage());
             }
         }
         return true;
     }
-
-    /*
-     * Put the tab in the background using all the empty/background clients.
-     */
-    private void putTabInBackground(Tab t) {
-        putViewInBackground(t.mMainView);
-        if (t.mSubView != null) {
-            putViewInBackground(t.mSubView);
-        }
-    }
-
-    /*
-     * Dismiss the subwindow for the given tab.
-     */
-    void dismissSubWindow(Tab t) {
-        if (t != null && t.mSubView != null) {
-            BrowserSettings.getInstance().deleteObserver(
-                    t.mSubView.getSettings());
-            t.mSubView.destroy();
-            t.mSubView = null;
-            t.mSubViewContainer = null;
-        }
-    }
-
-    /**
-     * Ensure that Tab t has data to display in the tab picker.
-     * @param  t   Tab to populate.
-     */
-    /* package */ void populatePickerData(Tab t) {
-        if (t == null) {
-            return;
-        }
-
-        // mMainView == null indicates that the tab has been freed.
-        if (t.mMainView == null) {
-            populatePickerDataFromSavedState(t);
-            return;
-        }
-
-        // FIXME: The only place we cared about subwindow was for 
-        // bookmarking (i.e. not when saving state). Was this deliberate?
-        final WebBackForwardList list = t.mMainView.copyBackForwardList();
-        final WebHistoryItem item =
-                list != null ? list.getCurrentItem() : null;
-        populatePickerData(t, item);
-    }
-
-    // Create the PickerData and populate it using the saved state of the tab.
-    private void populatePickerDataFromSavedState(Tab t) {
-        if (t.mSavedState == null) {
-            return;
-        }
-
-        final PickerData data = new PickerData();
-        final Bundle state = t.mSavedState;
-        data.mUrl = state.getString(CURRURL);
-        data.mTitle = state.getString(CURRTITLE);
-        // XXX: These keys are from WebView.savePicture so if they change, this
-        // will break.
-        data.mScale = state.getFloat("scale", 1.0f);
-        data.mScrollX = state.getInt("scrollX", 0);
-        data.mScrollY = state.getInt("scrollY", 0);
-
-        // Set the tab's picker data.
-        t.mPickerData = data;
-    }
-
-    // Populate the picker data using the given history item and the current
-    // top WebView.
-    private void populatePickerData(Tab t, WebHistoryItem item) {
-        final PickerData data = new PickerData();
-        if (item != null) {
-            data.mUrl = item.getUrl();
-            data.mTitle = item.getTitle();
-            data.mFavicon = item.getFavicon();
-            if (data.mTitle == null) {
-                data.mTitle = data.mUrl;
-            }
-        }
-        // We want to display the top window in the tab picker but use the url
-        // and title of the main window.
-        final WebView w = t.getTopWindow();
-        data.mScale = w.getScale();
-        data.mScrollX = w.getScrollX();
-        data.mScrollY = w.getScrollY();
-
-        t.mPickerData = data;
-    }
-    
-    /**
-     * Clean up the data for all tabs.
-     */
-    /* package */ void wipeAllPickerData() {
-        int size = getTabCount();
-        for (int i = 0; i < size; i++) {
-            final Tab t = getTab(i);
-            if (t != null && t.mSavedState == null) {
-                t.mPickerData = null;
-            }
-        }
-    }
-
-    /*
-     * Save the state for an individual tab.
-     */
-    private boolean saveState(Tab t) {
-        if (t != null) {
-            final WebView w = t.mMainView;
-            // If the WebView is null it means we ran low on memory and we
-            // already stored the saved state in mSavedState.
-            if (w == null) {
-                return true;
-            }
-            final Bundle b = new Bundle();
-            final WebBackForwardList list = w.saveState(b);
-            if (list != null) {
-                final File f = new File(mThumbnailDir, w.hashCode()
-                        + "_pic.save");
-                if (w.savePicture(b, f)) {
-                    b.putString(CURRPICTURE, f.getPath());
-                }
-            }
-
-            // Store some extra info for displaying the tab in the picker.
-            final WebHistoryItem item =
-                    list != null ? list.getCurrentItem() : null;
-            populatePickerData(t, item);
-
-            // XXX: WebView.savePicture stores the scale and scroll positions
-            // in the bundle so we don't have to do it here.
-            final PickerData data = t.mPickerData;
-            if (data.mUrl != null) {
-                b.putString(CURRURL, data.mUrl);
-            }
-            if (data.mTitle != null) {
-                b.putString(CURRTITLE, data.mTitle);
-            }
-            b.putBoolean(CLOSEONEXIT, t.mCloseOnExit);
-            if (t.mAppId != null) {
-                b.putString(APPID, t.mAppId);
-            }
-            if (t.mOriginalUrl != null) {
-                b.putString(ORIGINALURL, t.mOriginalUrl);
-            }
-
-            // Remember the parent tab so the relationship can be restored.
-            if (t.mParentTab != null) {
-                b.putInt(PARENTTAB, getTabIndex(t.mParentTab));
-            }
-
-            // Remember the saved state.
-            t.mSavedState = b;
-            return true;
-        }
-        return false;
-    }
-
-    /*
-     * Restore the state of the tab.
-     */
-    private boolean restoreState(Bundle b, Tab t) {
-        if (b == null) {
-            return false;
-        }
-        // Restore the internal state even if the WebView fails to restore.
-        // This will maintain the app id, original url and close-on-exit values.
-        t.mSavedState = null;
-        t.mPickerData = null;
-        t.mCloseOnExit = b.getBoolean(CLOSEONEXIT);
-        t.mAppId = b.getString(APPID);
-        t.mOriginalUrl = b.getString(ORIGINALURL);
-
-        final WebView w = t.mMainView;
-        final WebBackForwardList list = w.restoreState(b);
-        if (list == null) {
-            return false;
-        }
-        if (b.containsKey(CURRPICTURE)) {
-            final File f = new File(b.getString(CURRPICTURE));
-            w.restorePicture(b, f);
-            f.delete();
-        }
-        return true;
-    }
 }
diff --git a/src/com/android/browser/TitleBar.java b/src/com/android/browser/TitleBar.java
index 23b1ed5..dc4979b 100644
--- a/src/com/android/browser/TitleBar.java
+++ b/src/com/android/browser/TitleBar.java
@@ -17,6 +17,9 @@
 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.graphics.Bitmap;
 import android.graphics.Color;
@@ -28,6 +31,12 @@
 import android.graphics.drawable.PaintDrawable;
 import android.os.Handler;
 import android.os.Message;
+import android.speech.RecognizerIntent;
+import android.text.SpannableString;
+import android.text.Spanned;
+import android.text.TextUtils;
+import android.text.style.ImageSpan;
+import android.util.DisplayMetrics;
 import android.util.TypedValue;
 import android.view.ContextMenu;
 import android.view.LayoutInflater;
@@ -40,6 +49,8 @@
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
+import com.android.common.speech.LoggingEvents;
+
 /**
  * This class represents a title bar for a particular "tab" or "window" in the
  * browser.
@@ -52,14 +63,23 @@
     private ProgressBar     mHorizontalProgress;
     private ImageView       mFavicon;
     private ImageView       mLockIcon;
-    private Drawable        mStopDrawable;
+    private ImageView       mStopButton;
     private Drawable        mBookmarkDrawable;
+    private Drawable        mVoiceDrawable;
     private boolean         mInLoad;
     private BrowserActivity mBrowserActivity;
     private Drawable        mGenericFavicon;
     private int             mIconDimension;
     private View            mTitleBg;
     private MyHandler       mHandler;
+    private Intent          mVoiceSearchIntent;
+    private boolean         mInVoiceMode;
+    private Drawable        mVoiceModeBackground;
+    private Drawable        mNormalBackground;
+    private Drawable        mLoadingBackground;
+    private ImageSpan       mArcsSpan;
+    private int             mLeftMargin;
+    private int             mRightMargin;
 
     private static int LONG_PRESS = 1;
 
@@ -76,19 +96,48 @@
         mTitleBg = findViewById(R.id.title_bg);
         mLockIcon = (ImageView) findViewById(R.id.lock);
         mFavicon = (ImageView) findViewById(R.id.favicon);
+        mStopButton = (ImageView) findViewById(R.id.stop);
 
         mRtButton = (ImageView) findViewById(R.id.rt_btn);
         Resources resources = context.getResources();
         mCircularProgress = (Drawable) resources.getDrawable(
                 com.android.internal.R.drawable.search_spinner);
+        DisplayMetrics metrics = resources.getDisplayMetrics();
+        mLeftMargin = (int) TypedValue.applyDimension(
+                TypedValue.COMPLEX_UNIT_DIP, 8f, metrics);
+        mRightMargin = (int) TypedValue.applyDimension(
+                TypedValue.COMPLEX_UNIT_DIP, 6f, metrics);
         mIconDimension = (int) TypedValue.applyDimension(
-                TypedValue.COMPLEX_UNIT_DIP, 20f,
-                resources.getDisplayMetrics());
+                TypedValue.COMPLEX_UNIT_DIP, 20f, metrics);
         mCircularProgress.setBounds(0, 0, mIconDimension, mIconDimension);
         mHorizontalProgress = (ProgressBar) findViewById(
                 R.id.progress_horizontal);
         mGenericFavicon = context.getResources().getDrawable(
                 R.drawable.app_web_browser_sm);
+        mVoiceSearchIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
+        mVoiceSearchIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
+                RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);
+        // This extra tells voice search not to send the application id in its
+        // results intent - http://b/2546173
+        //
+        // TODO: Make a constant for this extra.
+        mVoiceSearchIntent.putExtra("android.speech.extras.SEND_APPLICATION_ID_EXTRA", false);
+        PackageManager pm = context.getPackageManager();
+        ResolveInfo ri = pm.resolveActivity(mVoiceSearchIntent,
+                PackageManager.MATCH_DEFAULT_ONLY);
+        if (ri == null) {
+            mVoiceSearchIntent = null;
+        } else {
+            mVoiceDrawable = resources.getDrawable(
+                    android.R.drawable.ic_btn_speak_now);
+        }
+        mBookmarkDrawable = mRtButton.getDrawable();
+        mVoiceModeBackground = resources.getDrawable(
+                R.drawable.title_voice);
+        mNormalBackground = mTitleBg.getBackground();
+        mLoadingBackground = resources.getDrawable(R.drawable.title_loading);
+        mArcsSpan = new ImageSpan(context, R.drawable.arcs,
+                ImageSpan.ALIGN_BASELINE);
     }
 
     private class MyHandler extends Handler {
@@ -106,20 +155,22 @@
     };
 
     @Override
-    protected void onCreateContextMenu(ContextMenu menu) {
+    public void createContextMenu(ContextMenu menu) {
         MenuInflater inflater = mBrowserActivity.getMenuInflater();
         inflater.inflate(R.menu.title_context, menu);
+        mBrowserActivity.onCreateContextMenu(menu, this, null);
     }
 
     @Override
     public boolean onTouchEvent(MotionEvent event) {
+        ImageView button = mInLoad ? mStopButton : mRtButton;
         switch (event.getAction()) {
             case MotionEvent.ACTION_DOWN:
                 // Make all touches hit either the textfield or the button,
                 // depending on which side of the right edge of the textfield
                 // they hit.
                 if ((int) event.getX() > mTitleBg.getRight()) {
-                    mRtButton.setPressed(true);
+                    button.setPressed(true);
                 } else {
                     mTitleBg.setPressed(true);
                     mHandler.sendMessageDelayed(mHandler.obtainMessage(
@@ -135,7 +186,7 @@
                     // other is pressed.  Since the user moved off the title
                     // bar, mark both as not pressed.
                     mTitleBg.setPressed(false);
-                    mRtButton.setPressed(false);
+                    button.setPressed(false);
                     mHandler.removeMessages(LONG_PRESS);
                     break;
                 }
@@ -144,26 +195,49 @@
                 if (mTitleBg.isPressed() && x > titleRight + slop) {
                     mTitleBg.setPressed(false);
                     mHandler.removeMessages(LONG_PRESS);
-                } else if (mRtButton.isPressed() && x < titleRight - slop) {
-                    mRtButton.setPressed(false);
+                } else if (button.isPressed() && x < titleRight - slop) {
+                    button.setPressed(false);
                 }
                 break;
             case MotionEvent.ACTION_CANCEL:
-                mRtButton.setPressed(false);
+                button.setPressed(false);
                 mTitleBg.setPressed(false);
                 mHandler.removeMessages(LONG_PRESS);
                 break;
             case MotionEvent.ACTION_UP:
-                if (mRtButton.isPressed()) {
-                    if (mInLoad) {
+                if (button.isPressed()) {
+                    if (mInVoiceMode) {
+                        if (mBrowserActivity.getTabControl().getCurrentTab()
+                                .voiceSearchSourceIsGoogle()) {
+                            Intent i = new Intent(
+                                    LoggingEvents.ACTION_LOG_EVENT);
+                            i.putExtra(LoggingEvents.EXTRA_EVENT,
+                                    LoggingEvents.VoiceSearch.RETRY);
+                            mBrowserActivity.sendBroadcast(i);
+                        }
+                        mBrowserActivity.startActivity(mVoiceSearchIntent);
+                    } else if (mInLoad) {
                         mBrowserActivity.stopLoading();
                     } else {
                         mBrowserActivity.bookmarksOrHistoryPicker(false);
                     }
-                    mRtButton.setPressed(false);
+                    button.setPressed(false);
                 } else if (mTitleBg.isPressed()) {
                     mHandler.removeMessages(LONG_PRESS);
-                    mBrowserActivity.onSearchRequested();
+                    if (mInVoiceMode) {
+                        if (mBrowserActivity.getTabControl().getCurrentTab()
+                                .voiceSearchSourceIsGoogle()) {
+                            Intent i = new Intent(
+                                    LoggingEvents.ACTION_LOG_EVENT);
+                            i.putExtra(LoggingEvents.EXTRA_EVENT,
+                                    LoggingEvents.VoiceSearch.N_BEST_REVEAL);
+                            mBrowserActivity.sendBroadcast(i);
+                        }
+                        mBrowserActivity.showVoiceSearchResults(
+                                mTitle.getText().toString().trim());
+                    } else {
+                        mBrowserActivity.editUrl();
+                    }
                     mTitleBg.setPressed(false);
                 }
                 break;
@@ -174,14 +248,6 @@
     }
 
     /**
-     * Return whether the associated WebView is currently loading.  Needed to
-     * determine whether a click should stop the load or close the tab.
-     */
-    /* package */ boolean isInLoad() {
-        return mInLoad;
-    }
-
-    /**
      * Set a new Bitmap for the Favicon.
      */
     /* package */ void setFavicon(Bitmap icon) {
@@ -201,6 +267,41 @@
     }
 
     /**
+     * Change the TitleBar to or from voice mode.  If there is no package to
+     * handle voice search, the TitleBar cannot be set to voice mode.
+     */
+    /* package */ void setInVoiceMode(boolean inVoiceMode) {
+        if (mInVoiceMode == inVoiceMode) return;
+        mInVoiceMode = inVoiceMode && mVoiceSearchIntent != null;
+        Drawable titleDrawable;
+        if (mInVoiceMode) {
+            mRtButton.setImageDrawable(mVoiceDrawable);
+            titleDrawable = mVoiceModeBackground;
+            mTitle.setEllipsize(null);
+            mRtButton.setVisibility(View.VISIBLE);
+            mStopButton.setVisibility(View.GONE);
+            mTitleBg.setBackgroundDrawable(titleDrawable);
+            mTitleBg.setPadding(mLeftMargin, mTitleBg.getPaddingTop(),
+                    mRightMargin, mTitleBg.getPaddingBottom());
+        } else {
+            if (mInLoad) {
+                titleDrawable = mLoadingBackground;
+                mRtButton.setVisibility(View.GONE);
+                mStopButton.setVisibility(View.VISIBLE);
+            } else {
+                titleDrawable = mNormalBackground;
+                mRtButton.setVisibility(View.VISIBLE);
+                mStopButton.setVisibility(View.GONE);
+                mRtButton.setImageDrawable(mBookmarkDrawable);
+            }
+            mTitle.setEllipsize(TextUtils.TruncateAt.END);
+            mTitleBg.setBackgroundDrawable(titleDrawable);
+            mTitleBg.setPadding(mLeftMargin, 0, mRightMargin, 0);
+        }
+        mTitle.setSingleLine(!mInVoiceMode);
+    }
+
+    /**
      * Set the Drawable for the lock icon, or null to hide it.
      */
     /* package */ void setLock(Drawable d) {
@@ -220,8 +321,12 @@
             mTitle.setCompoundDrawables(null, null, null, null);
             ((Animatable) mCircularProgress).stop();
             mHorizontalProgress.setVisibility(View.INVISIBLE);
-            if (mBookmarkDrawable != null) {
+            if (!mInVoiceMode) {
                 mRtButton.setImageDrawable(mBookmarkDrawable);
+                mRtButton.setVisibility(View.VISIBLE);
+                mStopButton.setVisibility(View.GONE);
+                mTitleBg.setBackgroundDrawable(mNormalBackground);
+                mTitleBg.setPadding(mLeftMargin, 0, mRightMargin, 0);
             }
             mInLoad = false;
         } else {
@@ -235,14 +340,11 @@
                         null);
                 ((Animatable) mCircularProgress).start();
                 mHorizontalProgress.setVisibility(View.VISIBLE);
-                if (mBookmarkDrawable == null) {
-                    mBookmarkDrawable = mRtButton.getDrawable();
-                }
-                if (mStopDrawable == null) {
-                    mRtButton.setImageResource(R.drawable.ic_btn_stop_v2);
-                    mStopDrawable = mRtButton.getDrawable();
-                } else {
-                    mRtButton.setImageDrawable(mStopDrawable);
+                if (!mInVoiceMode) {
+                    mTitleBg.setBackgroundDrawable(mLoadingBackground);
+                    mTitleBg.setPadding(mLeftMargin, 0, mRightMargin, 0);
+                    mRtButton.setVisibility(View.GONE);
+                    mStopButton.setVisibility(View.VISIBLE);
                 }
                 mInLoad = true;
             }
@@ -250,13 +352,26 @@
     }
 
     /**
-     * Update the title and url.
+     * Update the text displayed in the title bar.
+     * @param title String to display.  If null, the loading string will be
+     *      shown.
      */
-    /* package */ void setTitleAndUrl(CharSequence title, CharSequence url) {
-        if (url == null) {
+    /* package */ void setDisplayTitle(String title) {
+        if (title == null) {
             mTitle.setText(R.string.title_bar_loading);
         } else {
-            mTitle.setText(url.toString());
+            if (mInVoiceMode) {
+                // Add two spaces.  The second one will be replaced with an
+                // image, and the first one will put space between it and the
+                // text
+                SpannableString spannable = new SpannableString(title + "  ");
+                int end = spannable.length();
+                spannable.setSpan(mArcsSpan, end - 1, end,
+                        Spanned.SPAN_MARK_POINT);
+                mTitle.setText(spannable);
+            } else {
+                mTitle.setText(title);
+            }
         }
     }
 
diff --git a/src/com/android/browser/WebStorageSizeManager.java b/src/com/android/browser/WebStorageSizeManager.java
index 3afcadc..dcf2f8b 100644
--- a/src/com/android/browser/WebStorageSizeManager.java
+++ b/src/com/android/browser/WebStorageSizeManager.java
@@ -209,6 +209,9 @@
      * @param databaseIdentifier the identifier of the database on
      *     which the transaction that caused the quota overflow was run
      * @param currentQuota the current quota for the origin.
+     * @param estimatedSize the estimated size of a new database, or 0 if
+     *     this has been invoked in response to an existing database
+     *     overflowing its quota.
      * @param totalUsedQuota is the sum of all origins' quota.
      * @param quotaUpdater The callback to run when a decision to allow or
      *     deny quota has been made. Don't forget to call this!
@@ -248,7 +251,8 @@
             }
             return;
         }
-        // We have enough space inside mGlobalLimit.
+
+        // We have some space inside mGlobalLimit.
         long newOriginQuota = currentQuota;
         if (newOriginQuota == 0) {
             // This is a new origin, give it the size it asked for if possible.
@@ -260,19 +264,31 @@
             } else {
                 if (LOGV_ENABLED) {
                     Log.v(LOGTAG,
-                          "onExceededDatabaseQuota: Unable to satisfy" +
-                          " estimatedSize for the new database " +
-                          " (estimatedSize: " + estimatedSize +
-                          ", unused quota: " + totalUnusedQuota);
+                            "onExceededDatabaseQuota: Unable to satisfy" +
+                            " estimatedSize for the new database " +
+                            " (estimatedSize: " + estimatedSize +
+                            ", unused quota: " + totalUnusedQuota);
                 }
                 newOriginQuota = 0;
             }
         } else {
             // This is an origin we have seen before. It wants a quota
-            // increase.
-            newOriginQuota +=
-                Math.min(QUOTA_INCREASE_STEP, totalUnusedQuota);
+            // increase. There are two circumstances: either the origin
+            // is creating a new database or it has overflowed an existing database.
+
+            // Increase the quota. If estimatedSize == 0, then this is a quota overflow
+            // rather than the creation of a new database.
+            long quotaIncrease = estimatedSize == 0 ?
+                    Math.min(QUOTA_INCREASE_STEP, totalUnusedQuota) :
+                    estimatedSize;
+            newOriginQuota += quotaIncrease;
+
+            if (quotaIncrease > totalUnusedQuota) {
+                // We can't fit, so deny quota.
+                newOriginQuota = currentQuota;
+            }
         }
+
         quotaUpdater.updateQuota(newOriginQuota);
 
         if(LOGV_ENABLED) {
diff --git a/src/com/android/browser/WebsiteSettingsActivity.java b/src/com/android/browser/WebsiteSettingsActivity.java
index a5270a4..1e27092 100644
--- a/src/com/android/browser/WebsiteSettingsActivity.java
+++ b/src/com/android/browser/WebsiteSettingsActivity.java
@@ -88,6 +88,10 @@
             mFeatures |= (1 << feature);
         }
 
+        public void removeFeature(int feature) {
+            mFeatures &= ~(1 << feature);
+        }
+
         public boolean hasFeature(int feature) {
             return (mFeatures & (1 << feature)) != 0;
         }
@@ -168,7 +172,7 @@
             mResource = rsc;
             mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
             mDefaultIcon = BitmapFactory.decodeResource(getResources(),
-                    R.drawable.ic_launcher_shortcut_browser_bookmark);
+                    R.drawable.app_web_browser_sm);
             mUsageEmptyIcon = BitmapFactory.decodeResource(getResources(),
                     R.drawable.ic_list_data_off);
             mUsageLowIcon = BitmapFactory.decodeResource(getResources(),
@@ -263,7 +267,7 @@
                     Browser.BookmarkColumns.FAVICON }, "bookmark = 1", null, null);
 
             if (c != null) {
-                if(c.moveToFirst()) {
+                if (c.moveToFirst()) {
                     int urlIndex = c.getColumnIndex(Browser.BookmarkColumns.URL);
                     int titleIndex = c.getColumnIndex(Browser.BookmarkColumns.TITLE);
                     int faviconIndex = c.getColumnIndex(Browser.BookmarkColumns.FAVICON);
@@ -277,11 +281,20 @@
                             if (data != null) {
                                 bmp = BitmapFactory.decodeByteArray(data, 0, data.length);
                             }
-                            Set matchingSites = (Set)hosts.get(host);
+                            Set matchingSites = (Set) hosts.get(host);
                             Iterator<Site> sitesIter = matchingSites.iterator();
                             while (sitesIter.hasNext()) {
                                 Site site = sitesIter.next();
-                                site.setTitle(title);
+                                // We should only set the title if the bookmark is for the root
+                                // (i.e. www.google.com), as website settings act on the origin
+                                // as a whole rather than a single page under that origin. If the
+                                // user has bookmarked a page under the root but *not* the root,
+                                // then we risk displaying the title of that page which may or
+                                // may not have any relevance to the origin.
+                                if (url.equals(site.getOrigin()) ||
+                                        (new String(site.getOrigin()+"/")).equals(url)) {
+                                    site.setTitle(title);
+                                }
                                 if (bmp != null) {
                                     site.setIcon(bmp);
                                 }
@@ -324,7 +337,7 @@
             // We display the size in MB, to 1dp, rounding up to the next 0.1MB.
             // bytes should always be greater than zero.
             if (bytes <= 0) {
-                Log.e(LOGTAG, "sizeValueToString called with non-positive value");
+                Log.e(LOGTAG, "sizeValueToString called with non-positive value: " + bytes);
                 return "0";
             }
             float megabytes = (float) bytes / (1024.0F * 1024.0F);
@@ -355,8 +368,6 @@
          */
         public void setIconForUsage(ImageView usageIcon, long usageInBytes) {
             float usageInMegabytes = (float) usageInBytes / (1024.0F * 1024.0F);
-            usageIcon.setVisibility(View.VISIBLE);
-
             // We set the correct icon:
             // 0 < empty < 0.1MB
             // 0.1MB < low < 5MB
@@ -374,9 +385,10 @@
             View view;
             final TextView title;
             final TextView subtitle;
-            ImageView icon;
+            final ImageView icon;
             final ImageView usageIcon;
             final ImageView locationIcon;
+            final ImageView featureIcon;
 
             if (convertView == null) {
                 view = mInflater.inflate(mResource, parent, false);
@@ -387,6 +399,7 @@
             title = (TextView) view.findViewById(R.id.title);
             subtitle = (TextView) view.findViewById(R.id.subtitle);
             icon = (ImageView) view.findViewById(R.id.icon);
+            featureIcon = (ImageView) view.findViewById(R.id.feature_icon);
             usageIcon = (ImageView) view.findViewById(R.id.usage_icon);
             locationIcon = (ImageView) view.findViewById(R.id.location_icon);
             usageIcon.setVisibility(View.GONE);
@@ -397,10 +410,22 @@
 
                 Site site = getItem(position);
                 title.setText(site.getPrettyTitle());
-                subtitle.setText(site.getPrettyOrigin());
+                String subtitleText = site.getPrettyOrigin();
+                if (subtitleText != null) {
+                    title.setMaxLines(1);
+                    title.setSingleLine(true);
+                    subtitle.setVisibility(View.VISIBLE);
+                    subtitle.setText(subtitleText);
+                } else {
+                    subtitle.setVisibility(View.GONE);
+                    title.setMaxLines(2);
+                    title.setSingleLine(false);
+                }
+
                 icon.setVisibility(View.VISIBLE);
                 usageIcon.setVisibility(View.INVISIBLE);
                 locationIcon.setVisibility(View.INVISIBLE);
+                featureIcon.setVisibility(View.GONE);
                 Bitmap bmp = site.getIcon();
                 if (bmp == null) {
                     bmp = mDefaultIcon;
@@ -416,6 +441,7 @@
                         public void onReceiveValue(Long value) {
                             if (value != null) {
                                 setIconForUsage(usageIcon, value.longValue());
+                                usageIcon.setVisibility(View.VISIBLE);
                             }
                         }
                     });
@@ -436,8 +462,11 @@
                     });
                 }
             } else {
-                setTitle(mCurrentSite.getPrettyTitle());
                 icon.setVisibility(View.GONE);
+                locationIcon.setVisibility(View.GONE);
+                usageIcon.setVisibility(View.GONE);
+                featureIcon.setVisibility(View.VISIBLE);
+                setTitle(mCurrentSite.getPrettyTitle());
                 String origin = mCurrentSite.getOrigin();
                 switch (mCurrentSite.getFeatureByIndex(position)) {
                     case Site.FEATURE_WEB_STORAGE:
@@ -447,6 +476,8 @@
                                     String usage = sizeValueToString(value.longValue()) + " " + sMBStored;
                                     title.setText(R.string.webstorage_clear_data_title);
                                     subtitle.setText(usage);
+                                    subtitle.setVisibility(View.VISIBLE);
+                                    setIconForUsage(featureIcon, value.longValue());
                                 }
                             }
                         });
@@ -458,9 +489,12 @@
                                 if (allowed != null) {
                                     if (allowed.booleanValue()) {
                                         subtitle.setText(R.string.geolocation_settings_page_summary_allowed);
+                                        featureIcon.setImageBitmap(mLocationAllowedIcon);
                                     } else {
                                         subtitle.setText(R.string.geolocation_settings_page_summary_not_allowed);
+                                        featureIcon.setImageBitmap(mLocationDisallowedIcon);
                                     }
+                                    subtitle.setVisibility(View.VISIBLE);
                                 }
                             }
                         });
@@ -485,8 +519,14 @@
                                                new AlertDialog.OnClickListener() {
                                 public void onClick(DialogInterface dlg, int which) {
                                     WebStorage.getInstance().deleteOrigin(mCurrentSite.getOrigin());
-                                    mCurrentSite = null;
+                                    // If this site has no more features, then go back to the
+                                    // origins list.
+                                    mCurrentSite.removeFeature(Site.FEATURE_WEB_STORAGE);
+                                    if (mCurrentSite.getFeatureCount() == 0) {
+                                        mCurrentSite = null;
+                                    }
                                     askForOrigins();
+                                    notifyDataSetChanged();
                                 }})
                             .setNegativeButton(R.string.webstorage_clear_data_dialog_cancel_button, null)
                             .setIcon(android.R.drawable.ic_dialog_alert)
@@ -500,8 +540,12 @@
                                                new AlertDialog.OnClickListener() {
                                 public void onClick(DialogInterface dlg, int which) {
                                     GeolocationPermissions.getInstance().clear(mCurrentSite.getOrigin());
-                                    mCurrentSite = null;
+                                    mCurrentSite.removeFeature(Site.FEATURE_GEOLOCATION);
+                                    if (mCurrentSite.getFeatureCount() == 0) {
+                                        mCurrentSite = null;
+                                    }
                                     askForOrigins();
+                                    notifyDataSetChanged();
                                 }})
                             .setNegativeButton(R.string.geolocation_settings_page_dialog_cancel_button, null)
                             .setIcon(android.R.drawable.ic_dialog_alert)
@@ -513,6 +557,10 @@
                 notifyDataSetChanged();
             }
         }
+
+        public Site currentSite() {
+            return mCurrentSite;
+        }
     }
 
     /**
@@ -549,8 +597,9 @@
 
     @Override
     public boolean onPrepareOptionsMenu(Menu menu) {
-        // If we aren't listing any sites hide the clear all button (and hence the menu).
-        return mAdapter.getCount() > 0;
+        // If we are not on the sites list (rather on the page for a specific site) or
+        // we aren't listing any sites hide the clear all button (and hence the menu).
+        return  mAdapter.currentSite() == null && mAdapter.getCount() > 0;
     }
 
     @Override
diff --git a/src/com/android/browser/widget/BookmarkWidgetProvider.java b/src/com/android/browser/widget/BookmarkWidgetProvider.java
new file mode 100644
index 0000000..62b48c0
--- /dev/null
+++ b/src/com/android/browser/widget/BookmarkWidgetProvider.java
@@ -0,0 +1,49 @@
+/*
+ * 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.widget;
+
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProvider;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+/**
+ * Widget that shows a preview of the user's bookmarks.
+ */
+public class BookmarkWidgetProvider extends AppWidgetProvider {
+
+    static final String TAG = "BookmarkWidgetProvider";
+
+    @Override
+    public void onUpdate(Context context, AppWidgetManager mngr, int[] ids) {
+        context.startService(new Intent(BookmarkWidgetService.UPDATE, null,
+                    context, BookmarkWidgetService.class));
+    }
+
+    @Override
+    public void onEnabled(Context context) {
+        context.startService(new Intent(context, BookmarkWidgetService.class));
+    }
+
+    @Override
+    public void onDisabled(Context context) {
+        context.stopService(new Intent(context, BookmarkWidgetService.class));
+    }
+}
+
diff --git a/src/com/android/browser/widget/BookmarkWidgetService.java b/src/com/android/browser/widget/BookmarkWidgetService.java
new file mode 100644
index 0000000..1fd9163
--- /dev/null
+++ b/src/com/android/browser/widget/BookmarkWidgetService.java
@@ -0,0 +1,385 @@
+/*
+ * 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.widget;
+
+import android.app.PendingIntent;
+import android.app.Service;
+import android.appwidget.AppWidgetManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.ParcelFileDescriptor;
+import android.provider.Browser;
+import android.provider.Browser.BookmarkColumns;
+import android.service.urlrenderer.UrlRenderer;
+import android.service.urlrenderer.UrlRendererService;
+import android.util.Log;
+import android.view.View;
+import android.widget.RemoteViews;
+
+import com.android.browser.R;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public class BookmarkWidgetService extends Service
+        implements UrlRenderer.Callback {
+
+    private static final String TAG = "BookmarkWidgetService";
+
+    /** Force the bookmarks to be re-renderer. */
+    public static final String UPDATE = "com.android.browser.widget.UPDATE";
+
+    /** Change the widget to the next bookmark. */
+    private static final String NEXT = "com.android.browser.widget.NEXT";
+
+    /** Change the widget to the previous bookmark. */
+    private static final String PREV = "com.android.browser.widget.PREV";
+
+    /** Id of the current item displayed in the widget. */
+    private static final String EXTRA_ID =
+            "com.android.browser.widget.extra.ID";
+
+    // XXX: Remove these magic numbers once the dimensions of the widget can be
+    // queried.
+    private static final int WIDTH = 306;
+    private static final int HEIGHT = 386;
+
+    // Limit the number of connection attempts.
+    private static final int MAX_SERVICE_RETRY_COUNT = 5;
+
+    // No id specified.
+    private static final int NO_ID = -1;
+
+    private static final int MSG_UPDATE = 0;
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_UPDATE:
+                    if (mRenderer != null) {
+                        queryCursorAndRender();
+                    } else {
+                        if (++mServiceRetryCount <= MAX_SERVICE_RETRY_COUNT) {
+                            // Service is not connected, try again in a second.
+                            mHandler.sendEmptyMessageDelayed(MSG_UPDATE, 1000);
+                        }
+                    }
+                    break;
+                default:
+                    break;
+            }
+        }
+    };
+
+    private final ServiceConnection mConnection = new ServiceConnection() {
+        public void onServiceConnected(ComponentName className,
+                IBinder service) {
+            mRenderer = new UrlRenderer(service);
+        }
+
+        public void onServiceDisconnected(ComponentName className) {
+            mRenderer = null;
+        }
+    };
+
+    // Id -> information map storing db ids and their result.
+    private final HashMap<Integer, RenderResult> mIdsToResults =
+            new HashMap<Integer, RenderResult>();
+
+    // List of ids in order
+    private final ArrayList<Integer> mIdList = new ArrayList<Integer>();
+
+    // Map of urls to ids for when a url is complete.
+    private final HashMap<String, Integer> mUrlsToIds =
+            new HashMap<String, Integer>();
+
+    // The current id used by the widget during an update.
+    private int mCurrentId = NO_ID;
+    // Class that contacts the service on the phone to render bookmarks.
+    private UrlRenderer mRenderer;
+    // Number of service retries. Stop trying to connect after
+    // MAX_SERVICE_RETRY_COUNT
+    private int mServiceRetryCount;
+
+    @Override
+    public void onCreate() {
+        bindService(new Intent(UrlRendererService.SERVICE_INTERFACE),
+                mConnection, Context.BIND_AUTO_CREATE);
+    }
+
+    @Override
+    public void onDestroy() {
+        unbindService(mConnection);
+    }
+
+    @Override
+    public android.os.IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        final String action = intent.getAction();
+        if (UPDATE.equals(action)) {
+            mHandler.sendEmptyMessage(MSG_UPDATE);
+        } else if (PREV.equals(action) && mIdList.size() > 1) {
+            int prev = getPreviousId(intent);
+            if (prev == NO_ID) {
+                Log.d(TAG, "Could not determine previous id");
+                return START_NOT_STICKY;
+            }
+            RenderResult res = mIdsToResults.get(prev);
+            if (res != null) {
+                updateWidget(res);
+            }
+        } else if (NEXT.equals(action) && mIdList.size() > 1) {
+            int next = getNextId(intent);
+            if (next == NO_ID) {
+                Log.d(TAG, "Could not determine next id");
+                return START_NOT_STICKY;
+            }
+            RenderResult res = mIdsToResults.get(next);
+            if (res != null) {
+                updateWidget(res);
+            }
+        }
+        return START_STICKY;
+    }
+
+    private int getPreviousId(Intent intent) {
+        int listSize = mIdList.size();
+        // If the list contains 1 or fewer entries, return NO_ID so that the
+        // widget does not update.
+        if (listSize <= 1) {
+            return NO_ID;
+        }
+
+        int curr = intent.getIntExtra(EXTRA_ID, NO_ID);
+        if (curr == NO_ID) {
+            return NO_ID;
+        }
+
+        // Check if the current id is the beginning of the list so we can skip
+        // iterating through.
+        if (mIdList.get(0) == curr) {
+            return mIdList.get(listSize - 1);
+        }
+
+        // Search for the current id and remember the previous id.
+        int prev = NO_ID;
+        for (int id : mIdList) {
+            if (id == curr) {
+                break;
+            }
+            prev = id;
+        }
+        return prev;
+    }
+
+    private int getNextId(Intent intent) {
+        int listSize = mIdList.size();
+        // If the list contains 1 or fewer entries, return NO_ID so that the
+        // widget does not update.
+        if (listSize <= 1) {
+            return NO_ID;
+        }
+
+        int curr = intent.getIntExtra(EXTRA_ID, NO_ID);
+        if (curr == NO_ID) {
+            return NO_ID;
+        }
+
+        // Check if the current id is at the end of the list so we can skip
+        // iterating through.
+        if (mIdList.get(listSize - 1) == curr) {
+            return mIdList.get(0);
+        }
+
+        // Iterate through the ids. i is set to the current index + 1.
+        int i = 1;
+        for (int id : mIdList) {
+            if (id == curr) {
+                break;
+            }
+            i++;
+        }
+        return mIdList.get(i);
+    }
+
+    private void updateWidget(RenderResult res) {
+        RemoteViews views = new RemoteViews(getPackageName(),
+                R.layout.bookmarkwidget);
+
+        Intent prev = new Intent(PREV, null, this, BookmarkWidgetService.class);
+        prev.putExtra(EXTRA_ID, res.mId);
+        views.setOnClickPendingIntent(R.id.previous,
+                PendingIntent.getService(this, 0, prev,
+                    PendingIntent.FLAG_CANCEL_CURRENT));
+
+        Intent next = new Intent(NEXT, null, this, BookmarkWidgetService.class);
+        next.putExtra(EXTRA_ID, res.mId);
+        views.setOnClickPendingIntent(R.id.next,
+                PendingIntent.getService(this, 0, next,
+                    PendingIntent.FLAG_CANCEL_CURRENT));
+
+        // Set the title of the bookmark. Use the url as a backup.
+        String displayTitle = res.mTitle;
+        if (displayTitle == null) {
+            displayTitle = res.mUrl;
+        }
+        views.setTextViewText(R.id.title, displayTitle);
+
+        // Set the image or revert to the progress indicator.
+        if (res.mBitmap != null) {
+            views.setImageViewBitmap(R.id.image, res.mBitmap);
+            views.setViewVisibility(R.id.image, View.VISIBLE);
+            views.setViewVisibility(R.id.progress, View.GONE);
+        } else {
+            views.setViewVisibility(R.id.progress, View.VISIBLE);
+            views.setViewVisibility(R.id.image, View.GONE);
+        }
+
+        // Update the current id.
+        mCurrentId = res.mId;
+
+        AppWidgetManager.getInstance(this).updateAppWidget(
+                new ComponentName(this, BookmarkWidgetProvider.class),
+                views);
+    }
+
+    // Default WHERE clause is all bookmarks.
+    private static final String QUERY_WHERE =
+            BookmarkColumns.BOOKMARK + " == 1";
+    private static final String[] PROJECTION = new String[] {
+            BookmarkColumns._ID, BookmarkColumns.TITLE, BookmarkColumns.URL };
+
+    // Class containing the rendering information for a specific bookmark.
+    private static class RenderResult {
+        final int    mId;
+        final String mTitle;
+        final String mUrl;
+        Bitmap       mBitmap;
+
+        RenderResult(int id, String title, String url) {
+            mId = id;
+            mTitle = title;
+            mUrl = url;
+        }
+    }
+
+    private void queryCursorAndRender() {
+        // Clear the ordered list of ids and the map of ids to bitmaps.
+        mIdList.clear();
+        mIdsToResults.clear();
+
+        // Look up all the bookmarks
+        Cursor c = getContentResolver().query(Browser.BOOKMARKS_URI, PROJECTION,
+                QUERY_WHERE, null, null);
+        if (c != null) {
+            if (c.moveToFirst()) {
+                ArrayList<String> urls = new ArrayList<String>(c.getCount());
+                boolean sawCurrentId = false;
+                do {
+                    int id = c.getInt(0);
+                    String title = c.getString(1);
+                    String url = c.getString(2);
+
+                    // Linear list of ids to obtain the previous and next.
+                    mIdList.add(id);
+
+                    // Map the url to its db id for lookup when complete.
+                    mUrlsToIds.put(url, id);
+
+                    // Is this the current id?
+                    if (mCurrentId == id) {
+                        sawCurrentId = true;
+                    }
+
+                    // Store the current information to at least display the
+                    // title.
+                    RenderResult res = new RenderResult(id, title, url);
+                    mIdsToResults.put(id, res);
+
+                    // Add the url to our list to render.
+                    urls.add(url);
+                } while (c.moveToNext());
+
+                // Request a rendering of the urls. XXX: Hard-coded dimensions
+                // until the view's orientation and size can be determined. Or
+                // in the future the image will be a picture that can be
+                // scaled/zoomed arbitrarily.
+                mRenderer.render(urls, WIDTH, HEIGHT, this);
+
+                // Set the current id to the very first id if we did not see
+                // the current id in the list (the bookmark could have been
+                // deleted or this is the first update).
+                if (!sawCurrentId) {
+                    mCurrentId = mIdList.get(0);
+                }
+            }
+            c.close();
+        }
+    }
+
+    // UrlRenderer.Callback implementation
+    public void complete(String url, ParcelFileDescriptor result) {
+        int id = mUrlsToIds.get(url);
+        if (id == NO_ID) {
+            Log.d(TAG, "No matching id found during completion of "
+                    + url);
+            return;
+        }
+
+        RenderResult res = mIdsToResults.get(id);
+        if (res == null) {
+            Log.d(TAG, "No result found during completion of "
+                    + url);
+            return;
+        }
+
+        // Set the result.
+        if (result != null) {
+            InputStream input =
+                    new ParcelFileDescriptor.AutoCloseInputStream(result);
+            Bitmap orig = BitmapFactory.decodeStream(input, null, null);
+            // XXX: Hard-coded scaled bitmap until I can query the image
+            // dimensions.
+            res.mBitmap = Bitmap.createScaledBitmap(orig, WIDTH, HEIGHT, true);
+            try {
+                input.close();
+            } catch (IOException e) {
+                // oh well...
+            }
+        }
+
+        // If we are currently looking at the bookmark that just finished,
+        // update the widget.
+        if (mCurrentId == id) {
+            updateWidget(res);
+        }
+    }
+}
diff --git a/tests/Android.mk b/tests/Android.mk
index f86942d..ce9acbd 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -31,7 +31,4 @@
 
 LOCAL_INSTRUMENTATION_FOR := Browser
 
-LOCAL_SDK_VERSION := current
-
 include $(BUILD_PACKAGE)
-
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index 51715a9..cb1ffc7 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -34,4 +34,9 @@
                      android:targetPackage="com.android.browser"
                      android:label="Tests for Browser."/>
 
+    <instrumentation android:name="com.android.browser.BrowserLaunchPerformance"
+        android:targetPackage="com.android.browser"
+        android:label="Browser Launch Performance">
+    </instrumentation>
+
 </manifest>
diff --git a/tests/assets/bindings_test.html b/tests/assets/bindings_test.html
new file mode 100755
index 0000000..c20ccec
--- /dev/null
+++ b/tests/assets/bindings_test.html
@@ -0,0 +1,241 @@
+<html>
+<head>
+<script type="text/javascript">
+
+function testPrimitiveTypes() {
+  return JNIBindingsTest.testPrimitiveTypes(100, 'c', 123.34567890, 456.789, 1234567, 1234567890, 6000, true);
+}
+
+function testObjectTypes() {
+  return JNIBindingsTest.testObjectTypes("Foo", "", {"foo":"bar"}, {});
+}
+
+function testArray() {
+  return JNIBindingsTest.testArray([1,2,3], ['d', 'o', 'g'], [1.2, 2.3, 3.4], [4.5,5.6,6.7], [1,2,3], [4,5,6], [7,8,9], [true, false]);
+}
+
+function testObjectArray() {
+  return JNIBindingsTest.testObjectArray(['Hello', 'World', '!'], [], [{"foo":"bar"}]);
+}
+
+function testObjectMembers() {
+  var foo = {"bool":true,
+             "byte":101,
+             "char":'d',
+             "double":123.456,
+             "float":456.789,
+             "int":102,
+             "long":103,
+             "short":104,
+             "string":"Hello World",
+             "array": [1,2,3],
+             "objArray":["foo", "bar", "baz"],
+             "object": {"foo":1}
+  };
+  return JNIBindingsTest.testObjectMembers(foo.bool, foo.byte, foo.char, foo.double, foo.float, foo.int, foo.long, foo.short, foo.string, foo.array, foo.objArray, foo.object);
+}
+
+function testJSPrimitivesToStringsInJava() {
+    return JNIBindingsTest.testJSPrimitivesToStringsInJava(123, null, 456.789, true, 'd', undefined);
+}
+
+function testJavaReturnTypes() {
+  var expectedBoolReturn = true;
+  var expectedByteReturn = 1;
+  var expectedCharReturn = 98; // 'b'; Currently bindings in JSC and V8 return chars as their ASCII equivalent.
+  var expectedDoubleReturn = 123.456;
+  var expectedFloatReturn = 456.789;
+  var expectedIntReturn = 123;
+  var expectedLongReturn = 1234;
+  var expectedShortReturn = 12345;
+  var expectedStringReturn = "Hello World!";
+
+  var returned = JNIBindingsTest.returnBool();
+  if (returned != expectedBoolReturn) {
+    appendLog("returnBool() failed: expected "+ expectedBoolReturn +", got " + returned);
+    return false;
+  }
+
+  returned = JNIBindingsTest.returnByte();
+  if (returned != expectedByteReturn) {
+    appendLog("returnByte() failed: expected "+ expectedByteReturn +", got " + returned);
+    return false;
+  }
+
+  returned = JNIBindingsTest.returnChar();
+  if (returned != expectedCharReturn) {
+    appendLog("returnChar() failed: expected "+ expectedCharReturn +", got " + returned);
+    return false;
+  }
+
+  returned = JNIBindingsTest.returnDouble();
+  if (returned != expectedDoubleReturn) {
+    appendLog("returnDouble() failed: expected "+ expectedDoubleReturn +", got " + returned);
+    return false;
+  }
+
+  returned = JNIBindingsTest.returnFloat();
+  if (Math.abs(returned - expectedFloatReturn) > 0.001) {
+    appendLog("returnFloat() failed: expected "+ expectedFloatReturn +", got " + returned);
+    return false;
+  }
+
+  returned = JNIBindingsTest.returnInt();
+  if (returned != expectedIntReturn) {
+    appendLog("returnInt() failed: expected "+ expectedIntReturn +", got " + returned);
+    return false;
+  }
+
+  returned = JNIBindingsTest.returnLong();
+  if (returned != expectedLongReturn) {
+    appendLog("returnLong() failed: expected "+ expectedLongReturn +", got " + returned);
+    return false;
+  }
+
+  returned = JNIBindingsTest.returnShort();
+  if (returned != expectedShortReturn) {
+    appendLog("returnShort() failed: expected "+ expectedShortReturn +", got " + returned);
+    return false;
+  }
+
+  returned = JNIBindingsTest.returnString();
+  if (returned != expectedStringReturn) {
+    appendLog("returnString() failed: expected "+ expectedStringReturn +", got " + returned);
+    return false;
+  }
+
+  returned = JNIBindingsTest.returnObject();
+  if (returned == null) {
+    appendLog("returnObject() failed: expected non-null, got " + returned);
+    return false;
+  } else if (returned.x != 0) {
+    // EMULATE_JSC_BINDINGS
+    // Note: the Java sets the x property to 123. JSC and V8 do not support object
+    // members in the bindings though.
+    appendLog("returnObject() failed: expected 'x' property 0, got " + returned.x)
+    return false;
+  } else if (returned.s != undefined) {
+    // EMULATE_JSC_BINDINGS
+    // Note that the java class returned has s set to Hello World. JSC and V8 do not support
+    // getting properties.
+    appendLog("returnObject() failed: expected 's' property undefined, got " + returned.s);
+    return false;
+  } else if (!returned.aMethod()) {
+    appendLog("returnObject() failed: expected 'aMethod' method to return true, got " + returned.aMethod());
+    return false;
+  } else if (returned.anotherMethod() != "Hello World") {
+    appendLog("returnObject() failed: expected 'anotherMethod' to return 'Hello World' got "+ returned.anotherMethod());
+    return false;
+  }
+
+  returned = JNIBindingsTest.returnArray();
+  if (returned != null) {
+    appendLog("returnArray() failed: expected null, got " + returned);
+    return false;
+  }
+
+  returned = JNIBindingsTest.returnVoid();
+  if (returned != null) {
+    appendLog("returnVoid() failed: expected null, got " + returned);
+    return false;
+  }
+
+  return true;
+}
+
+function getIfaceProperties() {
+  if (JNIBindingsTest.mInt != 0) {
+    // EMULATE_JSC_BINDINGS
+    // Note: the Java sets the mInt property to 123. JSC and V8 do not support object
+    // members in the bindings though.
+    appendLog("getIfaceProperties() failed: expected mInt = 0, got " + JNIBindingsTest.mInt);
+    return false;
+  }
+
+  if (JNIBindingsTest.mString != undefined) {
+    // EMULATE_JSC_BINDINGS
+    // Note that the java class returned has s set to Hello World. JSC and V8 do not support
+    // getting properties.
+    appendLog("getIfaceProperties() failed: expected mString = 'Hello World', got " + JNIBindingsTest.mString);
+    return false;
+  }
+
+  return true;
+}
+
+function testParameterTypeMismatch() {
+  return JNIBindingsTest.testParameterTypeMismatch("dog");
+}
+
+function appendLog(msg) {
+  var log = document.getElementById("status");
+  log.innerHTML += "<br/>" + msg;
+}
+
+function runTests() {
+
+  // Assume that if the test isn't done after 10s that we failed.
+  window.setTimeout(function() { JNIBindingsTest.testComplete(); }, 10000);
+
+  if (testPrimitiveTypes()) {
+    appendLog("testPrimitiveTypes passed!");
+  } else {
+    appendLog("testPrimtiveTypes failed!");
+  }
+
+  if (testObjectTypes()) {
+    appendLog("testObjectTypes passed!");
+  } else {
+    appendLog("testObjectTypes failed!");
+  }
+
+  if (testArray()) {
+    appendLog("testArray passed!");
+  } else {
+    appendLog("testArray failed!");
+  }
+
+  if (testObjectArray()) {
+    appendLog("testObjectArray passed!");
+  } else {
+    appendLog("testObjectArray failed!");
+  }
+
+  if (testObjectMembers()) {
+    appendLog("testObjectMembers passed!");
+  } else {
+    appendLog("<br/>testObjectMembers failed!");
+  }
+
+  if (testJSPrimitivesToStringsInJava()) {
+    appendLog("testJSPrimitivesToStringsInJava passed!");
+  } else {
+    appendLog("testJSPrimitivesToStringsInJava failed!");
+  }
+
+  if (testJavaReturnTypes()) {
+    appendLog("testJavaReturnTypes passed!");
+  } else {
+    appendLog("testJavaReturnTypes failed!");
+  }
+
+  if (getIfaceProperties()) {
+    appendLog("getIfaceProperties passed!");
+  } else {
+    appendLog("getIfaceProperties failed!");
+  }
+
+  if (testParameterTypeMismatch()) {
+    appendLog("testParameterTypeMismatch passed!");
+  } else {
+    appendLog("testParameterTypeMismatch failed!");
+  }
+
+  JNIBindingsTest.testComplete();
+}
+</script>
+
+<body onload="runTests();">
+<p id="status">Running JNI Bindings test...</p>
+</body>
+</html>
diff --git a/tests/src/com/android/browser/BrowserLaunchPerformance.java b/tests/src/com/android/browser/BrowserLaunchPerformance.java
new file mode 100644
index 0000000..c5d4279
--- /dev/null
+++ b/tests/src/com/android/browser/BrowserLaunchPerformance.java
@@ -0,0 +1,26 @@
+package com.android.browser;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.test.LaunchPerformanceBase;
+
+public class BrowserLaunchPerformance extends LaunchPerformanceBase {
+
+    @Override
+    public void onCreate(Bundle arguments) {
+        super.onCreate(arguments);
+
+        mIntent.setClassName(getTargetContext(), "com.android.browser.BrowserActivity");
+        start();
+    }
+
+    /**
+     * Calls LaunchApp and finish.
+     */
+    @Override
+    public void onStart() {
+        super.onStart();
+        LaunchApp();
+        finish(Activity.RESULT_OK, mResults);
+    }
+}
diff --git a/tests/src/com/android/browser/BrowserProviderTests.java b/tests/src/com/android/browser/BrowserProviderTests.java
new file mode 100644
index 0000000..f4bf942
--- /dev/null
+++ b/tests/src/com/android/browser/BrowserProviderTests.java
@@ -0,0 +1,168 @@
+/*
+ * 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.app.SearchManager;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * Unit tests for {@link BrowserProvider}.
+ */
+@MediumTest
+public class BrowserProviderTests extends AndroidTestCase {
+
+    private ArrayList<Uri> mDeleteUris;
+
+    @Override
+    protected void setUp() throws Exception {
+        mDeleteUris = new ArrayList<Uri>();
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        for (Uri uri : mDeleteUris) {
+            deleteUri(uri);
+        }
+        super.tearDown();
+    }
+
+    public void testHasDefaultBookmarks() {
+        Cursor c = getBookmarksSuggest("");
+        try {
+            assertTrue("No default bookmarks", c.getCount() > 0);
+        } finally {
+            c.close();
+        }
+    }
+
+    public void testPartialFirstTitleWord() {
+        assertInsertQuery("http://www.example.com/rasdfe", "nfgjra sdfywe", "nfgj");
+    }
+
+    public void testFullFirstTitleWord() {
+        assertInsertQuery("http://www.example.com/", "nfgjra dfger", "nfgjra");
+    }
+
+    public void testFullFirstTitleWordPartialSecond() {
+        assertInsertQuery("http://www.example.com/", "nfgjra dfger", "nfgjra df");
+    }
+
+    public void testFullTitle() {
+        assertInsertQuery("http://www.example.com/", "nfgjra dfger", "nfgjra dfger");
+    }
+
+// Not implemented in BrowserProvider
+//    public void testFullSecondTitleWord() {
+//        assertInsertQuery("http://www.example.com/rasdfe", "nfgjra sdfywe", "sdfywe");
+//    }
+
+    public void testFullTitleJapanese() {
+        String title = "\u30ae\u30e3\u30e9\u30ea\u30fc\u30fcGoogle\u691c\u7d22";
+        assertInsertQuery("http://www.example.com/sdaga", title, title);
+    }
+
+    public void testPartialTitleJapanese() {
+        String title = "\u30ae\u30e3\u30e9\u30ea\u30fc\u30fcGoogle\u691c\u7d22";
+        String query = "\u30ae\u30e3\u30e9\u30ea\u30fc";
+        assertInsertQuery("http://www.example.com/sdaga", title, query);
+    }
+
+    // Test for http://b/issue?id=2152749
+    public void testSoundmarkTitleJapanese() {
+        String title = "\u30ae\u30e3\u30e9\u30ea\u30fc\u30fcGoogle\u691c\u7d22";
+        String query = "\u30ad\u30e3\u30e9\u30ea\u30fc";
+        assertInsertQuery("http://www.example.com/sdaga", title, query);
+    }
+
+    //
+    // Utilities
+    //
+
+    private void assertInsertQuery(String url, String title, String query) {
+        addBookmark(url, title);
+        assertQueryReturns(url, title, query);
+    }
+
+    private void assertQueryReturns(String url, String title, String query) {
+        Cursor c = getBookmarksSuggest(query);
+        try {
+            assertTrue(title + " not matched by " + query, c.getCount() > 0);
+            assertTrue("More than one result for " + query, c.getCount() == 1);
+            while (c.moveToNext()) {
+                String text1 = getCol(c, SearchManager.SUGGEST_COLUMN_TEXT_1);
+                assertNotNull(text1);
+                assertEquals("Bad title", title, text1);
+                String text2 = getCol(c, SearchManager.SUGGEST_COLUMN_TEXT_2);
+                assertNotNull(text2);
+                String data = getCol(c, SearchManager.SUGGEST_COLUMN_INTENT_DATA);
+                assertNotNull(data);
+                assertEquals("Bad URL", url, data);
+            }
+        } finally {
+            c.close();
+        }
+    }
+
+    private Cursor getBookmarksSuggest(String query) {
+        Uri suggestUri = Uri.parse("content://browser/bookmarks/search_suggest_query");
+        String[] selectionArgs = { query };
+        Cursor c = getContext().getContentResolver().query(suggestUri, null, "url LIKE ?",
+                selectionArgs, null);
+        assertNotNull(c);
+        return c;
+    }
+
+    private void addBookmark(String url, String title) {
+        Uri uri = insertBookmark(url, title);
+        assertNotNull(uri);
+        assertFalse(android.provider.Browser.BOOKMARKS_URI.equals(uri));
+        mDeleteUris.add(uri);
+    }
+
+    private Uri insertBookmark(String url, String title) {
+        ContentValues values = new ContentValues();
+        values.put("title", title);
+        values.put("url", url);
+        values.put("visits", 0);
+        values.put("date", 0);
+        values.put("created", 0);
+        values.put("bookmark", 1);
+        return getContext().getContentResolver().insert(android.provider.Browser.BOOKMARKS_URI,
+                values);
+    }
+
+    private void deleteUri(Uri uri) {
+        int count = getContext().getContentResolver().delete(uri, null, null);
+        assertEquals("Failed to delete " + uri, 1, count);
+    }
+
+    private static String getCol(Cursor c, String name) {
+        int col = c.getColumnIndex(name);
+        String msg = "Column " + name + " not found, columns: "
+                + Arrays.toString(c.getColumnNames());
+        assertTrue(msg, col >= 0);
+        return c.getString(col);
+    }
+}
diff --git a/tests/src/com/android/browser/JNIBindingsTest.java b/tests/src/com/android/browser/JNIBindingsTest.java
new file mode 100644
index 0000000..bfa3ac1
--- /dev/null
+++ b/tests/src/com/android/browser/JNIBindingsTest.java
@@ -0,0 +1,285 @@
+/*
+ * 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.test.AndroidTestCase;
+import android.util.Log;
+
+import java.util.Arrays;
+import junit.framework.AssertionFailedError;
+
+public class JNIBindingsTest extends AndroidTestCase {
+
+    private final static String LOGTAG = "JNIBindingsTest";
+    private JNIBindingsTestApp mTestApp;
+
+    public int mInt = 123;
+    public String mString = "Hello World";
+
+    public JNIBindingsTest(JNIBindingsTestApp testApp) {
+        mTestApp = testApp;
+    }
+
+    public void testComplete() {
+        Log.v(LOGTAG, "Completing the test.");
+        mTestApp.testComplete();
+    }
+
+    public void printAssertionFailed(AssertionFailedError e) {
+        Log.e(LOGTAG, "");
+        Log.e(LOGTAG, "*** ASSERTION FAILED: " + e.getMessage());
+        Log.e(LOGTAG, "*** Stack trace:");
+        StackTraceElement[] trace = e.getStackTrace();
+        for(StackTraceElement elem : trace) {
+            Log.e(LOGTAG, "***\t" + elem.toString());
+        }
+        Log.e(LOGTAG, "");
+    }
+
+    public boolean testPrimitiveTypes(byte byteParam, char charParam, double doubleParam,
+            float floatParam, int intParam, long longParam, short shortParam,
+            boolean booleanParam) {
+        byte expectedByteParam = 100;
+        char expectedCharParam = 'c';
+        double expectedDoubleParam = 123.34567890;
+        float expectedFloatParam = 456.789f;
+        int expectedIntParam = 1234567;
+        long expectedLongParam = 1234567890L;
+        short expectedShortParam = 6000;
+        boolean expectedBooleanParam = true;
+
+        try {
+            assertEquals(expectedByteParam, byteParam);
+
+            // EMULATE_JSC_BINDINGS: JSC does not pass chars correctly
+            // assertEquals(expectedCharParam, charParam);
+
+            assertEquals(expectedDoubleParam, doubleParam);
+            assertEquals(expectedFloatParam, floatParam);
+            assertEquals(expectedIntParam, intParam);
+            assertEquals(expectedLongParam, longParam);
+            assertEquals(expectedShortParam, shortParam);
+            assertEquals(expectedBooleanParam, booleanParam);
+        } catch (AssertionFailedError e) {
+            printAssertionFailed(e);
+           return false;
+        }
+        return true;
+    }
+
+    public boolean testObjectTypes(String stringParam, String emptyString, Object objectParam,
+            Object emptyObject) {
+        String expectedString = "Foo";
+        String expectedEmptyString = "";
+
+        try {
+            assertNotNull(stringParam);
+            assertNotNull(emptyString);
+            assertEquals(expectedString, stringParam);
+            assertEquals(expectedEmptyString, emptyString);
+            assertNull(objectParam);
+            assertNull(emptyObject);
+        } catch (AssertionFailedError e) {
+            printAssertionFailed(e);
+            return false;
+        }
+        return true;
+    }
+
+    public boolean testArray(byte[] byteArray, char[] charArray, double[] doubleArray,
+            float[] floatArray, int[] intArray, long[] longArray, short[] shortArray,
+            boolean[] booleanArray) {
+        byte[] expectedByteArray = { 1,2,3};
+        char[] expectedCharArray = {'d', 'o', 'g'};
+        double[] expectedDoubleArray = {1.2,2.3,3.4};
+        float[] expectedFloatArray = {4.5F,5.6F,6.7F};
+        int[] expectedIntArray = {1,2,3};
+        long[] expectedLongArray = {4L,5L,6L};
+        short[] expectedShortArray = {7,8,9};
+        boolean[] expectedBooleanArray = {true, false};
+
+        try {
+            assertNotNull(byteArray);
+            assertNotNull(charArray);
+            assertNotNull(doubleArray);
+            assertNotNull(floatArray);
+            assertNotNull(intArray);
+            assertNotNull(longArray);
+            assertNotNull(shortArray);
+            assertNotNull(booleanArray);
+            assertEquals(Arrays.toString(expectedByteArray), Arrays.toString(byteArray));
+            assertEquals(Arrays.toString(expectedCharArray), Arrays.toString(charArray));
+            assertEquals(Arrays.toString(expectedDoubleArray), Arrays.toString(doubleArray));
+            assertEquals(Arrays.toString(expectedFloatArray), Arrays.toString(floatArray));
+            assertEquals(Arrays.toString(expectedIntArray), Arrays.toString(intArray));
+            assertEquals(Arrays.toString(expectedLongArray), Arrays.toString(longArray));
+            assertEquals(Arrays.toString(expectedShortArray), Arrays.toString(shortArray));
+            assertEquals(Arrays.toString(expectedBooleanArray), Arrays.toString(booleanArray));
+        } catch (AssertionFailedError e) {
+            printAssertionFailed(e);
+            return false;
+        }
+        return true;
+    }
+
+    public boolean testObjectArray(String[] stringArray, Object[] emptyArray,
+            Object[] objectArray) {
+        String[] expectedStringArray = {"Hello", "World", "!"};
+        String expectedStringArrayClassName = "[Ljava.lang.String;";
+        Object[] expectedObjectArray = {};
+
+        try {
+            assertNotNull(stringArray);
+
+            // EMULATE_JSC_BINDINGS JSC pass null for object arrays that are not strings.
+            // Should be an empty array?
+            assertNull(emptyArray);
+            assertNull(objectArray);
+
+            assertEquals(Arrays.toString(expectedStringArray), Arrays.toString(stringArray));
+            assertEquals(expectedStringArrayClassName, stringArray.getClass().getName());
+
+            // EMULATE_JSC_BINDINGS
+            // assertEquals(Arrays.toString(expectedObjectArray), Arrays.toString(emptyArray));
+            // assertEquals(expectedObjectArrayClassName, emptyArray.getClass().getName());
+            // assertEquals(Arrays.toString(expectedObjectArray), Arrays.toString(objectArray));
+            // assertEquals(expectedStringObjectClassName, objectArray.getClass().getName());
+
+        } catch (AssertionFailedError e) {
+            printAssertionFailed(e);
+            return false;
+        }
+        return true;
+    }
+
+    public boolean testObjectMembers(boolean boolParam, byte byteParam, char charParam,
+            double doubleParam, float floatParam, int intParam, long longParam, short shortParam,
+            String stringParam, int[] intArrayParam, String[] stringArrayParam,
+            Object objectParam) {
+        boolean expectedBoolParam = true;
+        byte expectedByteParam = 101;
+        char expectedCharParam = 'd';
+        double expectedDoubleParam = 123.456;
+        float expectedFloatParam = 456.789F;
+        int expectedIntParam = 102;
+        long expectedLongParam = 103L;
+        short expectedShortParam = 104;
+        String expectedStringParam = "Hello World";
+        int[] expectedIntArray = {1,2,3};
+        String[] expectedStringArrayParam = {"foo", "bar", "baz"};
+        String expectedStringArrayClassName = "[Ljava.lang.String;";
+
+        try {
+            assertEquals(expectedBoolParam, boolParam);
+            assertEquals(expectedByteParam, byteParam);
+
+            // EMULATE_JSC_BINDINGS: JSC does not pass chars correctly. (chars are strings in JS)
+            // assertEquals(expectedCharParam, charParam);
+
+            assertEquals(expectedDoubleParam, doubleParam);
+            assertEquals(expectedFloatParam, floatParam);
+            assertEquals(expectedIntParam, intParam);
+            assertEquals(expectedLongParam, longParam);
+            assertEquals(expectedShortParam, shortParam);
+            assertEquals(expectedStringParam, stringParam);
+            assertEquals(Arrays.toString(expectedIntArray), Arrays.toString(intArrayParam));
+            assertEquals(Arrays.toString(expectedStringArrayParam),
+                    Arrays.toString(stringArrayParam));
+            assertEquals(expectedStringArrayClassName, stringArrayParam.getClass().getName());
+            assertNull(objectParam);
+        } catch (AssertionFailedError e) {
+            printAssertionFailed(e);
+            return false;
+        }
+        return true;
+    }
+
+    public boolean testJSPrimitivesToStringsInJava(String intParam, String nullParam,
+            String doubleParam, String booleanParam, String charParam,
+            String undefinedParam) {
+        String expectedIntParam = "123";
+        String expectedDoubleParam = "456.789";
+        String expectedBooleanParam = "true";
+        String expectedCharParam = "d";
+
+        // EMULATE_JSC_BINDINGS JSC passes "undefined" for undefined types. Should be null?
+        String expectedUndefinedParam = "undefined";
+
+        try {
+            assertNotNull(intParam);
+            assertNull(nullParam);
+            assertNotNull(doubleParam);
+            assertNotNull(booleanParam);
+            assertNotNull(charParam);
+
+            // EMULATE_JSC_BINDINGS JSC passes "undefined" for undefined types.
+            assertNotNull(undefinedParam);
+
+            assertEquals(expectedIntParam, intParam);
+            assertEquals(expectedDoubleParam, doubleParam);
+            assertEquals(expectedBooleanParam, booleanParam);
+            assertEquals(expectedCharParam, charParam);;
+
+            // EMULATE_JSC_BINDINGS  JSC passes "undefined" for undefined types.
+            assertEquals(expectedUndefinedParam, undefinedParam);
+
+        } catch (AssertionFailedError e) {
+            printAssertionFailed(e);
+            return false;
+        }
+        return true;
+    }
+
+    public boolean testParameterTypeMismatch(String[] stringArrayParam) {
+        // The JS test will pass a string, not an array to this test.
+        try {
+            assertNull(stringArrayParam);
+        } catch (AssertionFailedError e) {
+            printAssertionFailed(e);
+            return false;
+        }
+
+        return true;
+    }
+
+    public boolean returnBool() { return true; }
+    public byte returnByte() { return 1; }
+    public char returnChar() { return 'b'; }
+    public double returnDouble() { return 123.456; }
+    public float returnFloat() { return 456.789F; }
+    public int returnInt() { return 123; }
+    public long returnLong() { return 1234L; }
+    public short returnShort() { return 12345; }
+    public String returnString() { return "Hello World!"; }
+
+    public class TestObject {
+        public int x = 123;
+        public String s = "Hello World!";
+
+        public boolean aMethod() { return true; }
+        public String anotherMethod() { return "Hello World"; }
+    }
+
+    public TestObject returnObject() { return new TestObject(); }
+
+    public int[] returnArray() {
+        int[] array = {1,2,3,4,5};
+        return array;
+    }
+
+    public void returnVoid() { }
+}
diff --git a/tests/src/com/android/browser/JNIBindingsTestApp.java b/tests/src/com/android/browser/JNIBindingsTestApp.java
new file mode 100644
index 0000000..e01aca2
--- /dev/null
+++ b/tests/src/com/android/browser/JNIBindingsTestApp.java
@@ -0,0 +1,223 @@
+/*
+ * 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.app.Instrumentation;
+import android.net.http.SslError;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+import android.webkit.JsPromptResult;
+import android.webkit.JsResult;
+import android.webkit.SslErrorHandler;
+import android.webkit.WebView;
+
+/**
+ * Adds a JavaScript interface to the webview and calls functions on it to verify variables
+ * are passed from JS to Java correctly.
+ */
+public class JNIBindingsTestApp extends ActivityInstrumentationTestCase2<BrowserActivity> {
+
+    private final static String TAG = "JNIBindingsTest";
+
+    private static final int MSG_WEBKIT_DATA_READY = 101;
+
+    private BrowserActivity mActivity = null;
+    private Instrumentation mInst = null;
+
+    private boolean mTestDone = false;
+    private String mWebKitResult;
+
+    private String mExpectedWebKitResult = "Running JNI Bindings test...\n" +
+            "testPrimitiveTypes passed!\n" +
+            "testObjectTypes passed!\n" +
+            "testArray passed!\n" +
+            "testObjectArray passed!\n" +
+            "testObjectMembers passed!\n" +
+            "testJSPrimitivesToStringsInJava passed!\n" +
+            "testJavaReturnTypes passed!\n" +
+            "getIfaceProperties passed!\n" +
+            "testParameterTypeMismatch passed!\n";
+
+
+    private class GetWebKitDataThread extends Thread {
+        private JNIBindingsTestApp mTestApp;
+        private WebView mWebView;
+        private Handler mHandler;
+
+        GetWebKitDataThread(JNIBindingsTestApp testApp, WebView webView) {
+            mTestApp = testApp;
+            mWebView = webView;
+        }
+
+        public void run() {
+            Looper.prepare();
+            mHandler = new Handler() {
+                public void handleMessage(Message msg) {
+                    switch (msg.what) {
+                        case MSG_WEBKIT_DATA_READY: {
+                            mTestApp.setWebKitResult((String)msg.obj);
+                            Looper.myLooper().quit();
+                        }
+                        default: super.handleMessage(msg); break;
+                    }
+                }
+            };
+            mWebView.documentAsText(mHandler.obtainMessage(MSG_WEBKIT_DATA_READY));
+            Looper.loop();
+        }
+    }
+
+    public synchronized void setWebKitResult(String result) {
+       mWebKitResult = result;
+       notify();
+    }
+
+    public JNIBindingsTestApp() {
+        super(BrowserActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mInst = getInstrumentation();
+        mInst.waitForIdleSync();
+
+    }
+
+    /**
+     * Gets the browser ready for testing by starting the application
+     * and wrapping the WebView's helper clients.
+     */
+    void setUpBrowser() {
+        Tab tab = mActivity.getTabControl().getCurrentTab();
+        WebView webView = tab.getWebView();
+        webView.addJavascriptInterface(new JNIBindingsTest(this), "JNIBindingsTest");
+
+        webView.setWebChromeClient(new TestWebChromeClient(webView.getWebChromeClient()) {
+
+            /**
+             * Dismisses and logs Javascript alerts.
+             */
+            @Override
+            public boolean onJsAlert(WebView view, String url, String message,
+                    JsResult result) {
+                String logMsg = String.format("JS Alert '%s' received from %s", message, url);
+                Log.w(TAG, logMsg);
+                result.confirm();
+
+                return true;
+            }
+
+            /**
+             * Confirms and logs Javascript alerts.
+             */
+            @Override
+            public boolean onJsConfirm(WebView view, String url, String message,
+                    JsResult result) {
+                String logMsg = String.format("JS Confirmation '%s' received from %s",
+                        message, url);
+                Log.w(TAG, logMsg);
+                result.confirm();
+
+                return true;
+            }
+
+            /**
+             * Confirms and logs Javascript alerts, providing the default value.
+             */
+            @Override
+            public boolean onJsPrompt(WebView view, String url, String message,
+                    String defaultValue, JsPromptResult result) {
+                String logMsg = String.format("JS Prompt '%s' received from %s; " +
+                        "Giving default value '%s'", message, url, defaultValue);
+                Log.w(TAG, logMsg);
+                result.confirm(defaultValue);
+
+                return true;
+            }
+        });
+
+        webView.setWebViewClient(new TestWebViewClient(webView.getWebViewClient()) {
+
+            /**
+             * Bypasses and logs errors.
+             */
+            @Override
+            public void onReceivedError(WebView view, int errorCode,
+                    String description, String failingUrl) {
+                String message = String.format("Error '%s' (%d) loading url: %s",
+                        description, errorCode, failingUrl);
+                Log.w(TAG, message);
+            }
+
+            /**
+             * Ignores and logs SSL errors.
+             */
+            @Override
+            public void onReceivedSslError(WebView view, SslErrorHandler handler,
+                    SslError error) {
+                Log.w(TAG, "SSL error: " + error);
+                handler.proceed();
+            }
+
+        });
+    }
+
+    public synchronized void testComplete() {
+        mTestDone = true;
+        notify();
+    }
+
+    public void testJNIBindings() {
+        setUpBrowser();
+
+        Tab tab = mActivity.getTabControl().getCurrentTab();
+        WebView webView = tab.getWebView();
+        webView.loadUrl("file:///sdcard/bindings_test.html");
+        synchronized(this) {
+            while(!mTestDone) {
+                try {
+                    wait();
+                } catch (InterruptedException e) {}
+            }
+        }
+
+        // Now the tests are complete grab the DOM content and compare to the reference.
+        GetWebKitDataThread getWKData = new GetWebKitDataThread(this, webView);
+        mWebKitResult = null;
+        getWKData.start();
+
+        synchronized(this) {
+            while(mWebKitResult == null) {
+                try {
+                    wait();
+                } catch (InterruptedException e) {}
+            }
+        }
+
+        Log.v(TAG, "WebKit result:");
+        Log.v(TAG, mWebKitResult);
+        assertEquals("Bindings test failed! See logcat for more details!", mExpectedWebKitResult,
+                mWebKitResult);
+    }
+}
diff --git a/tests/src/com/android/browser/PopularUrlsTest.java b/tests/src/com/android/browser/PopularUrlsTest.java
new file mode 100644
index 0000000..d3806a0
--- /dev/null
+++ b/tests/src/com/android/browser/PopularUrlsTest.java
@@ -0,0 +1,445 @@
+/*
+ * 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 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;
+import android.net.http.SslError;
+import android.os.Environment;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+import android.webkit.HttpAuthHandler;
+import android.webkit.JsPromptResult;
+import android.webkit.JsResult;
+import android.webkit.SslErrorHandler;
+import android.webkit.WebView;
+
+/**
+ *
+ * Iterates over a list of URLs from a file and outputs the time to load each.
+ */
+public class PopularUrlsTest extends ActivityInstrumentationTestCase2<BrowserActivity> {
+
+    private final static String TAG = "PopularUrlsTest";
+    private final static String newLine = System.getProperty("line.separator");
+    private final static String sInputFile = "popular_urls.txt";
+    private final static String sOutputFile = "test_output.txt";
+    private final static String sStatusFile = "test_status.txt";
+    private final static File sExternalStorage = Environment.getExternalStorageDirectory();
+
+    private final static int PERF_LOOPCOUNT = 10;
+    private final static int STABILITY_LOOPCOUNT = 1;
+    private final static int PAGE_LOAD_TIMEOUT = 120000; // 2 minutes
+
+    private BrowserActivity mActivity = null;
+    private Instrumentation mInst = null;
+    private CountDownLatch mLatch = new CountDownLatch(1);
+    private RunStatus mStatus;
+
+    public PopularUrlsTest() {
+        super(BrowserActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mActivity = getActivity();
+        mInst = getInstrumentation();
+        mInst.waitForIdleSync();
+
+        mStatus = RunStatus.load();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mStatus != null) {
+            mStatus.cleanUp();
+        }
+
+        super.tearDown();
+    }
+
+    static BufferedReader getInputStream() throws FileNotFoundException {
+        return getInputStream(sInputFile);
+    }
+
+    static BufferedReader getInputStream(String inputFile) throws FileNotFoundException {
+        String path = sExternalStorage + File.separator + inputFile;
+        FileReader fileReader = new FileReader(path);
+        BufferedReader bufferedReader = new BufferedReader(fileReader);
+
+        return bufferedReader;
+    }
+
+    OutputStreamWriter getOutputStream() throws IOException {
+        return getOutputStream(sOutputFile);
+    }
+
+    OutputStreamWriter getOutputStream(String outputFile) throws IOException {
+        String path = sExternalStorage + File.separator + outputFile;
+
+        File file = new File(path);
+
+        return new FileWriter(file, mStatus.getIsRecovery());
+    }
+
+    /**
+     * Gets the browser ready for testing by starting the application
+     * and wrapping the WebView's helper clients.
+     */
+    void setUpBrowser() {
+        Tab tab = mActivity.getTabControl().getCurrentTab();
+        WebView webView = tab.getWebView();
+
+        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();
+                }
+            }
+
+            /**
+             * Dismisses and logs Javascript alerts.
+             */
+            @Override
+            public boolean onJsAlert(WebView view, String url, String message,
+                    JsResult result) {
+                String logMsg = String.format("JS Alert '%s' received from %s", message, url);
+                Log.w(TAG, logMsg);
+                result.confirm();
+
+                return true;
+            }
+
+            /**
+             * Confirms and logs Javascript alerts.
+             */
+            @Override
+            public boolean onJsConfirm(WebView view, String url, String message,
+                    JsResult result) {
+                String logMsg = String.format("JS Confirmation '%s' received from %s",
+                        message, url);
+                Log.w(TAG, logMsg);
+                result.confirm();
+
+                return true;
+            }
+
+            /**
+             * Confirms and logs Javascript alerts, providing the default value.
+             */
+            @Override
+            public boolean onJsPrompt(WebView view, String url, String message,
+                    String defaultValue, JsPromptResult result) {
+                String logMsg = String.format("JS Prompt '%s' received from %s; " +
+                        "Giving default value '%s'", message, url, defaultValue);
+                Log.w(TAG, logMsg);
+                result.confirm(defaultValue);
+
+                return true;
+            }
+        });
+
+        webView.setWebViewClient(new TestWebViewClient(webView.getWebViewClient()) {
+
+            /**
+             * Bypasses and logs errors.
+             */
+            @Override
+            public void onReceivedError(WebView view, int errorCode,
+                    String description, String failingUrl) {
+                String message = String.format("Error '%s' (%d) loading url: %s",
+                        description, errorCode, failingUrl);
+                Log.w(TAG, message);
+            }
+
+            /**
+             * Ignores and logs SSL errors.
+             */
+            @Override
+            public void onReceivedSslError(WebView view, SslErrorHandler handler,
+                    SslError error) {
+                Log.w(TAG, "SSL error: " + error);
+                handler.proceed();
+            }
+
+            /**
+             * Ignores http auth with dummy username and password
+             */
+            @Override
+            public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler,
+                    String host, String realm) {
+                handler.proceed("user", "passwd");
+            }
+        });
+    }
+
+    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();
+            }
+        }
+    }
+
+    void waitForLoad() throws InterruptedException {
+        boolean timedout = !mLatch.await(PAGE_LOAD_TIMEOUT, TimeUnit.MILLISECONDS);
+        if (timedout) {
+            Log.w(TAG, "page timeout. trying to stop.");
+            // try to stop page load
+            mInst.runOnMainSync(new Runnable(){
+                public void run() {
+                    mActivity.getTabControl().getCurrentTab().getWebView().stopLoading();
+                }
+            });
+            // try to wait for count down latch again
+            timedout = !mLatch.await(5000, TimeUnit.MILLISECONDS);
+            if (timedout) {
+                Log.e(TAG, "failed to stop the timedout site in 5s");
+            }
+        }
+    }
+
+    private static class RunStatus {
+        private File mFile;
+        private int iteration;
+        private int page;
+        private String url;
+        private boolean isRecovery;
+
+        private RunStatus(String file) throws IOException {
+            mFile = new File(file);
+            FileReader input = null;
+            BufferedReader reader = null;
+            try {
+                input = new FileReader(mFile);
+                isRecovery = true;
+                reader = new BufferedReader(input);
+                iteration = Integer.parseInt(reader.readLine());
+                page = Integer.parseInt(reader.readLine());
+            } catch (FileNotFoundException ex) {
+                isRecovery = false;
+                iteration = 0;
+                page = 0;
+            } finally {
+                try {
+                    if (reader != null) {
+                        reader.close();
+                    }
+                } finally {
+                    if (input != null) {
+                        input.close();
+                    }
+                }
+            }
+        }
+
+        public static RunStatus load() throws IOException {
+            return load(sStatusFile);
+        }
+
+        public static RunStatus load(String file) throws IOException {
+            return new RunStatus(sExternalStorage + File.separator + file);
+        }
+
+        public void write() throws IOException {
+            FileWriter output = null;
+            OutputStreamWriter writer = null;
+            if (mFile.exists()) {
+                mFile.delete();
+            }
+            try {
+                output = new FileWriter(mFile);
+                output.write(iteration + newLine);
+                output.write(page + newLine);
+                output.write(url + newLine);
+            } finally {
+                try {
+                    if (writer != null) {
+                        writer.close();
+                    }
+                } finally {
+                    if (output != null) {
+                        output.close();
+                    }
+                }
+            }
+        }
+
+        public void cleanUp() {
+            if (mFile.exists()) {
+                mFile.delete();
+            }
+        }
+
+        public void resetPage() {
+            page = 0;
+        }
+
+        public void incrementPage() {
+            ++page;
+        }
+
+        public void incrementIteration() {
+            ++iteration;
+        }
+
+        public int getPage() {
+            return page;
+        }
+
+        public int getIteration() {
+            return iteration;
+        }
+
+        public boolean getIsRecovery() {
+            return isRecovery;
+        }
+
+        public void setUrl(String url) {
+            this.url = url;
+        }
+    }
+
+    /**
+     * Loops over a list of URLs, points the browser to each one, and records the time elapsed.
+     *
+     * @param input the reader from which to get the URLs.
+     * @param writer the writer to which to output the results.
+     * @param clearCache determines whether the cache is cleared before loading each page
+     * @param loopCount the number of times to loop through the list of pages
+     * @throws IOException unable to read from input or write to writer.
+     * @throws InterruptedException the thread was interrupted waiting for the page to load.
+     */
+    void loopUrls(BufferedReader input, OutputStreamWriter writer,
+            boolean clearCache, int loopCount)
+            throws IOException, InterruptedException {
+        Tab tab = mActivity.getTabControl().getCurrentTab();
+        WebView webView = tab.getWebView();
+
+        List<String> pages = new LinkedList<String>();
+
+        String page;
+        while (null != (page = input.readLine())) {
+            pages.add(page);
+        }
+
+        Iterator<String> iterator = pages.iterator();
+        for (int i = 0; i < mStatus.getPage(); ++i) {
+            iterator.next();
+        }
+
+        if (mStatus.getIsRecovery()) {
+            Log.e(TAG, "Recovering after crash: " + iterator.next());
+        }
+
+        while (mStatus.getIteration() < loopCount) {
+            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();
+                mInst.runOnMainSync(new Runnable() {
+
+                    public void run() {
+                        mActivity.onNewIntent(intent);
+                    }
+
+                });
+                waitForLoad();
+                long stopTime = System.currentTimeMillis();
+
+                String url = webView.getUrl();
+                Log.i(TAG, "finish: " + url);
+
+                if (writer != null) {
+                    writer.write(page + "|" + (stopTime - startTime) + newLine);
+                    writer.flush();
+                }
+
+                mStatus.incrementPage();
+            }
+            mStatus.incrementIteration();
+            mStatus.resetPage();
+            iterator = pages.iterator();
+        }
+    }
+
+    public void testLoadPerformance() throws IOException, InterruptedException {
+        setUpBrowser();
+
+        OutputStreamWriter writer = getOutputStream();
+        try {
+            BufferedReader bufferedReader = getInputStream();
+            try {
+                loopUrls(bufferedReader, writer, true, PERF_LOOPCOUNT);
+            } finally {
+                if (bufferedReader != null) {
+                    bufferedReader.close();
+                }
+            }
+        } finally {
+            if (writer != null) {
+                writer.close();
+            }
+        }
+    }
+
+    public void testStability() throws IOException, InterruptedException {
+        setUpBrowser();
+
+        BufferedReader bufferedReader = getInputStream();
+        try {
+            loopUrls(bufferedReader, null, true, STABILITY_LOOPCOUNT);
+        } finally {
+            if (bufferedReader != null) {
+                bufferedReader.close();
+            }
+        }
+    }
+}
diff --git a/tests/src/com/android/browser/TestWebChromeClient.java b/tests/src/com/android/browser/TestWebChromeClient.java
new file mode 100644
index 0000000..d78eaed
--- /dev/null
+++ b/tests/src/com/android/browser/TestWebChromeClient.java
@@ -0,0 +1,201 @@
+/*
+ * 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.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Message;
+import android.view.View;
+import android.webkit.ConsoleMessage;
+import android.webkit.GeolocationPermissions;
+import android.webkit.JsPromptResult;
+import android.webkit.JsResult;
+import android.webkit.ValueCallback;
+import android.webkit.WebChromeClient;
+import android.webkit.WebStorage;
+import android.webkit.WebView;
+
+/**
+ *
+ * WebChromeClient for browser tests.
+ * Wraps around existing client so that specific methods can be overridden if needed.
+ *
+ */
+abstract class TestWebChromeClient extends WebChromeClient {
+
+    private WebChromeClient mWrappedClient;
+
+    protected TestWebChromeClient(WebChromeClient wrappedClient) {
+        mWrappedClient = wrappedClient;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onProgressChanged(WebView view, int newProgress) {
+        mWrappedClient.onProgressChanged(view, newProgress);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onReceivedTitle(WebView view, String title) {
+        mWrappedClient.onReceivedTitle(view, title);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onReceivedIcon(WebView view, Bitmap icon) {
+        mWrappedClient.onReceivedIcon(view, icon);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onReceivedTouchIconUrl(WebView view, String url,
+            boolean precomposed) {
+        mWrappedClient.onReceivedTouchIconUrl(view, url, precomposed);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onShowCustomView(View view, CustomViewCallback callback) {
+        mWrappedClient.onShowCustomView(view, callback);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onHideCustomView() {
+        mWrappedClient.onHideCustomView();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean onCreateWindow(WebView view, boolean dialog,
+            boolean userGesture, Message resultMsg) {
+        return mWrappedClient.onCreateWindow(view, dialog, userGesture, resultMsg);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onRequestFocus(WebView view) {
+        mWrappedClient.onRequestFocus(view);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onCloseWindow(WebView window) {
+        mWrappedClient.onCloseWindow(window);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean onJsAlert(WebView view, String url, String message,
+            JsResult result) {
+        return mWrappedClient.onJsAlert(view, url, message, result);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean onJsConfirm(WebView view, String url, String message,
+            JsResult result) {
+        return mWrappedClient.onJsConfirm(view, url, message, result);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean onJsPrompt(WebView view, String url, String message,
+            String defaultValue, JsPromptResult result) {
+        return mWrappedClient.onJsPrompt(view, url, message, defaultValue, result);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean onJsBeforeUnload(WebView view, String url, String message,
+            JsResult result) {
+        return mWrappedClient.onJsBeforeUnload(view, url, message, result);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onExceededDatabaseQuota(String url, String databaseIdentifier,
+            long currentQuota, long estimatedSize, long totalUsedQuota,
+            WebStorage.QuotaUpdater quotaUpdater) {
+        mWrappedClient.onExceededDatabaseQuota(url, databaseIdentifier, currentQuota,
+                estimatedSize, totalUsedQuota, quotaUpdater);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onReachedMaxAppCacheSize(long spaceNeeded, long totalUsedQuota,
+            WebStorage.QuotaUpdater quotaUpdater) {
+        mWrappedClient.onReachedMaxAppCacheSize(spaceNeeded, totalUsedQuota, quotaUpdater);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onGeolocationPermissionsShowPrompt(String origin,
+            GeolocationPermissions.Callback callback) {
+        mWrappedClient.onGeolocationPermissionsShowPrompt(origin, callback);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void onGeolocationPermissionsHidePrompt() {
+        mWrappedClient.onGeolocationPermissionsHidePrompt();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean onJsTimeout() {
+        return mWrappedClient.onJsTimeout();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    @Deprecated
+    public void onConsoleMessage(String message, int lineNumber, String sourceID) {
+        mWrappedClient.onConsoleMessage(message, lineNumber, sourceID);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
+        return mWrappedClient.onConsoleMessage(consoleMessage);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Bitmap getDefaultVideoPoster() {
+        return mWrappedClient.getDefaultVideoPoster();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public View getVideoLoadingProgressView() {
+        return mWrappedClient.getVideoLoadingProgressView();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void getVisitedHistory(ValueCallback<String[]> callback) {
+        mWrappedClient.getVisitedHistory(callback);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void openFileChooser(ValueCallback<Uri> uploadFile) {
+        mWrappedClient.openFileChooser(uploadFile);
+    }
+}
diff --git a/tests/src/com/android/browser/TestWebViewClient.java b/tests/src/com/android/browser/TestWebViewClient.java
new file mode 100644
index 0000000..7159a7e
--- /dev/null
+++ b/tests/src/com/android/browser/TestWebViewClient.java
@@ -0,0 +1,127 @@
+/*
+ * 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.graphics.Bitmap;
+import android.net.http.SslError;
+import android.os.Message;
+import android.view.KeyEvent;
+import android.webkit.HttpAuthHandler;
+import android.webkit.SslErrorHandler;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+
+/**
+ *
+ *
+ * WebViewClient for browser tests.
+ * Wraps around existing client so that specific methods can be overridden if needed.
+ *
+ */
+abstract class TestWebViewClient extends WebViewClient {
+
+  private WebViewClient mWrappedClient;
+
+  protected TestWebViewClient(WebViewClient wrappedClient) {
+    mWrappedClient = wrappedClient;
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public boolean shouldOverrideUrlLoading(WebView view, String url) {
+      return mWrappedClient.shouldOverrideUrlLoading(view, url);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public void onPageStarted(WebView view, String url, Bitmap favicon) {
+    mWrappedClient.onPageStarted(view, url, favicon);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public void onPageFinished(WebView view, String url) {
+    mWrappedClient.onPageFinished(view, url);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public void onLoadResource(WebView view, String url) {
+    mWrappedClient.onLoadResource(view, url);
+  }
+
+  /** {@inheritDoc} */
+  @Deprecated
+  @Override
+  public void onTooManyRedirects(WebView view, Message cancelMsg,
+          Message continueMsg) {
+      mWrappedClient.onTooManyRedirects(view, cancelMsg, continueMsg);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public void onReceivedError(WebView view, int errorCode,
+          String description, String failingUrl) {
+    mWrappedClient.onReceivedError(view, errorCode, description, failingUrl);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public void onFormResubmission(WebView view, Message dontResend,
+          Message resend) {
+    mWrappedClient.onFormResubmission(view, dontResend, resend);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public void doUpdateVisitedHistory(WebView view, String url,
+          boolean isReload) {
+    mWrappedClient.doUpdateVisitedHistory(view, url, isReload);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public void onReceivedSslError(WebView view, SslErrorHandler handler,
+          SslError error) {
+      mWrappedClient.onReceivedSslError(view, handler, error);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public void onReceivedHttpAuthRequest(WebView view,
+          HttpAuthHandler handler, String host, String realm) {
+      mWrappedClient.onReceivedHttpAuthRequest(view, handler, host, realm);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) {
+      return mWrappedClient.shouldOverrideKeyEvent(view, event);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
+    mWrappedClient.onUnhandledKeyEvent(view, event);
+  }
+
+  /** {@inheritDoc} */
+  @Override
+  public void onScaleChanged(WebView view, float oldScale, float newScale) {
+    mWrappedClient.onScaleChanged(view, oldScale, newScale);
+  }
+}
diff --git a/tests/src/com/android/browser/WebStorageSizeManagerUnitTests.java b/tests/src/com/android/browser/WebStorageSizeManagerUnitTests.java
index b7956d7..354c4da 100644
--- a/tests/src/com/android/browser/WebStorageSizeManagerUnitTests.java
+++ b/tests/src/com/android/browser/WebStorageSizeManagerUnitTests.java
@@ -108,14 +108,14 @@
         totalUsedQuota += origin2Quota;
 
         // Origin 1 runs out of space.
-        manager.onExceededDatabaseQuota("1", "1", origin1Quota, origin1EstimatedSize, totalUsedQuota, mQuotaUpdater);
+        manager.onExceededDatabaseQuota("1", "1", origin1Quota, 0, totalUsedQuota, mQuotaUpdater);
         assertEquals(origin1EstimatedSize + quotaIncrease, mNewQuota);
         totalUsedQuota -= origin1Quota;
         origin1Quota = mNewQuota;
         totalUsedQuota += origin1Quota;
 
         // Origin 2 runs out of space.
-        manager.onExceededDatabaseQuota("2", "2", origin2Quota, origin2EstimatedSize, totalUsedQuota, mQuotaUpdater);
+        manager.onExceededDatabaseQuota("2", "2", origin2Quota, 0, totalUsedQuota, mQuotaUpdater);
         assertEquals(origin2EstimatedSize + quotaIncrease, mNewQuota);
         totalUsedQuota -= origin2Quota;
         origin2Quota = mNewQuota;
@@ -131,14 +131,14 @@
         totalUsedQuota += origin3Quota;
 
         // Origin 1 runs out of space again. It should increase it's quota to take the last 1MB.
-        manager.onExceededDatabaseQuota("1", "1", origin1Quota, origin1EstimatedSize, totalUsedQuota, mQuotaUpdater);
+        manager.onExceededDatabaseQuota("1", "1", origin1Quota, 0, totalUsedQuota, mQuotaUpdater);
         assertEquals(origin1Quota + quotaIncrease, mNewQuota);
         totalUsedQuota -= origin1Quota;
         origin1Quota = mNewQuota;
         totalUsedQuota += origin1Quota;
 
         // Origin 1 runs out of space again. It should inow fail to increase in size.
-        manager.onExceededDatabaseQuota("1", "1", origin1Quota, origin1EstimatedSize, totalUsedQuota, mQuotaUpdater);
+        manager.onExceededDatabaseQuota("1", "1", origin1Quota, 0, totalUsedQuota, mQuotaUpdater);
         assertEquals(origin1Quota, mNewQuota);
 
         // We try adding a new origin. Which will fail.
@@ -228,4 +228,73 @@
         maxSize = WebStorageSizeManager.calculateGlobalLimit(fileSystemSize, freeSpaceSize);
         assertEquals(0, maxSize);
     }
+
+    public void testManyDatabasesOnOneOrigin() {
+        // This test ensures that if an origin creates more than one database, the quota that is
+        // assigned to the origin after the second creation is enough to satisfy all databases
+        // under that origin.
+        // See b/2417477.
+
+        long totalUsedQuota = 0;
+        mDiskInfo.setTotalSizeBytes(bytes(100));
+        mDiskInfo.setFreeSpaceSizeBytes(bytes(100));
+        // This should give us a storage area of 13MB, with 3.25MB for appcache and 9.75MB for
+        // databases.
+        assertEquals(bytes(13), WebStorageSizeManager.calculateGlobalLimit(
+                mDiskInfo.getTotalSizeBytes(), mDiskInfo.getFreeSpaceSizeBytes()));
+
+        // We have an appcache file size of 0 MB.
+        mAppCacheInfo.setAppCacheSizeBytes(0);
+
+        // Create the manager.
+        WebStorageSizeManager manager = new WebStorageSizeManager(null, mDiskInfo, mAppCacheInfo);
+
+        // We add an origin.
+        long originQuota = 0;
+        long database1EstimatedSize = bytes(2);
+        manager.onExceededDatabaseQuota("1", "1", originQuota, database1EstimatedSize,
+                totalUsedQuota, mQuotaUpdater);
+        assertEquals(database1EstimatedSize, mNewQuota);
+        originQuota = mNewQuota;
+        totalUsedQuota = originQuota;
+
+        // Now try to create a new database under the origin, by invoking onExceededDatabaseQuota
+        // again. This time, request more space than the old quota + the quota increase step.
+        long database2EstimatedSize = bytes(3.5);
+        manager.onExceededDatabaseQuota("1", "2", originQuota, database2EstimatedSize,
+                totalUsedQuota, mQuotaUpdater);
+        assertEquals(database1EstimatedSize + database2EstimatedSize, mNewQuota);
+        originQuota = mNewQuota;
+        totalUsedQuota = originQuota;
+
+        // Create another database, but this time use a size that will overflow the space on the
+        // device. It should be denied.
+        long database3EstimatedSize = bytes(50);
+        manager.onExceededDatabaseQuota("1", "3", originQuota, database3EstimatedSize,
+                totalUsedQuota, mQuotaUpdater);
+        assertEquals(originQuota, mNewQuota);
+
+        // Create another database. This time, request less than the old quota.
+        long database4EstimatedSize = bytes(2);
+        manager.onExceededDatabaseQuota("1", "4", originQuota, database4EstimatedSize,
+                totalUsedQuota, mQuotaUpdater);
+        assertEquals(database1EstimatedSize + database2EstimatedSize + database4EstimatedSize,
+                mNewQuota);
+        originQuota = mNewQuota;
+        totalUsedQuota = originQuota;
+
+        // Now have the first database overflow it's quota. We should get 1 more MB.
+        manager.onExceededDatabaseQuota("1", "1", originQuota, 0, totalUsedQuota, mQuotaUpdater);
+        assertEquals(database1EstimatedSize + database2EstimatedSize + database4EstimatedSize +
+                bytes(1), mNewQuota);
+        originQuota = mNewQuota;
+        totalUsedQuota = originQuota;
+
+        // Create a db under the origin that uses a quota less than the usual quota increase step.
+        long database5EstimatedSize = bytes(0.5);
+        manager.onExceededDatabaseQuota("1", "5", originQuota, database5EstimatedSize,
+                totalUsedQuota, mQuotaUpdater);
+        assertEquals(database1EstimatedSize + database2EstimatedSize + database4EstimatedSize +
+                bytes(1) + database5EstimatedSize, mNewQuota);
+    }
 }