am bcdaa277: am 7671cb22: Merge "Split strings with SD card references into variations." into gingerbread
Merge commit 'bcdaa277885bb0e751498e68aaae280a232d7cd3'
* commit 'bcdaa277885bb0e751498e68aaae280a232d7cd3':
Split strings with SD card references into variations.
diff --git a/Android.mk b/Android.mk
index e015dda..4cb1edb 100644
--- a/Android.mk
+++ b/Android.mk
@@ -12,6 +12,8 @@
LOCAL_PACKAGE_NAME := Browser
+LOCAL_PROGUARD_FLAGS := -include $(LOCAL_PATH)/proguard.flags
+
LOCAL_EMMA_COVERAGE_FILTER := *,-com.android.common.*
include $(BUILD_PACKAGE)
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index dc8f599..58ce133 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -25,20 +25,23 @@
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<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.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS" />
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
+ <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<uses-permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"/>
<uses-permission android:name="com.android.browser.permission.WRITE_HISTORY_BOOKMARKS"/>
- <uses-permission android:name="android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS" />
+ <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
<application android:name="Browser"
android:label="@string/application_name"
android:icon="@drawable/ic_launcher_browser"
android:backupAgent=".BrowserBackupAgent"
+ android:hardwareAccelerated="false"
android:taskAffinity="android.task.browser" >
<provider android:name="BrowserProvider"
@@ -49,6 +52,14 @@
<path-permission android:path="/bookmarks/search_suggest_query"
android:readPermission="android.permission.GLOBAL_SEARCH" />
</provider>
+ <provider android:name=".provider.BrowserProvider2"
+ android:authorities="com.android.browser"
+ android:multiprocess="true"
+ android:readPermission="com.android.browser.permission.READ_HISTORY_BOOKMARKS"
+ android:writePermission="com.android.browser.permission.WRITE_HISTORY_BOOKMARKS">
+ <path-permission android:path="/bookmarks/search_suggest_query"
+ android:readPermission="android.permission.GLOBAL_SEARCH" />
+ </provider>
<activity android:name="BrowserActivity"
android:label="@string/application_name"
android:launchMode="singleTask"
@@ -85,6 +96,16 @@
<data android:mimeType="application/xhtml+xml"/>
<data android:mimeType="application/vnd.wap.xhtml+xml"/>
</intent-filter>
+ <!-- For viewing saved web archives. -->
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.BROWSABLE" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:scheme="http" />
+ <data android:scheme="https" />
+ <data android:scheme="file" />
+ <data android:mimeType="application/x-webarchive-xml"/>
+ </intent-filter>
<!-- We are also the main entry point of the browser. -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -135,8 +156,8 @@
android:launchMode="singleTop" android:configChanges="orientation|keyboardHidden">
</activity>
- <activity-alias android:name="ShortcutBookmarksPage"
- android:targetActivity="BrowserBookmarksPage"
+ <activity android:name="ShortcutActivity"
+ android:theme="@style/ShortcutTheme"
android:label="@string/shortcut_bookmark"
android:icon="@drawable/ic_launcher_shortcut_browser_bookmark">
@@ -145,7 +166,7 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
- </activity-alias>
+ </activity>
<activity android:name="BrowserDownloadPage" android:label=""
android:configChanges="orientation|keyboardHidden">
@@ -176,7 +197,7 @@
android:resource="@xml/bookmarks_searchable" />
</activity>
- <activity android:name="AddBookmarkPage" android:label="Save bookmark" android:theme="@android:style/Theme.Dialog"
+ <activity android:name="AddBookmarkPage" android:label="Save bookmark" android:theme="@style/Dialog.Holo"
android:configChanges="orientation|keyboardHidden" android:windowSoftInputMode="stateHidden">
<intent-filter>
<action android:name="android.intent.action.INSERT" />
@@ -185,6 +206,10 @@
</intent-filter>
</activity>
+ <activity android:name="SaveToHomescreenDialog" android:label="Save to homescreen" android:theme="@android:style/Theme.Dialog"
+ android:configChanges="orientation|keyboardHidden" android:windowSoftInputMode="stateHidden">
+ </activity>
+
<!--receiver android:name=".widget.BookmarkWidgetProvider" android:label="@string/bookmarks">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
@@ -194,9 +219,32 @@
<service android:name=".widget.BookmarkWidgetService" /-->
+ <receiver
+ android:name=".widget.BookmarkStackWidgetProvider"
+ 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/bookmarkstackwidget" />
+ </receiver>
+ <service
+ android:name=".widget.BookmarkStackWidgetService"
+ android:exported="true" />
+
<!-- Makes .BrowserActivity the search target for any activity in Browser -->
<meta-data android:name="android.app.default_searchable" android:value=".BrowserActivity" />
+ <!-- Application code for RLZ tracking. RLZ assigns non-unique, non-personally identifiable
+ tracking labels to client products; these labels sometimes appear in Google search
+ queries. See http://code.google.com/p/rlz for more info.
+
+ This value signifies to the RLZ client that this application uses RLZ tracking. -->
+ <meta-data android:name="com.google.android.partnersetup.RLZ_ACCESS_POINT"
+ android:value="@string/rlz_access_point" />
+
<receiver android:name=".OpenDownloadReceiver">
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED"/>
diff --git a/CleanSpec.mk b/CleanSpec.mk
index b84e1b6..722b4a4 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -43,6 +43,7 @@
#$(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/*)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Browser_intermediates)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/proguard.flags b/proguard.flags
new file mode 100644
index 0000000..888c238
--- /dev/null
+++ b/proguard.flags
@@ -0,0 +1,2 @@
+# Most of the classes in this package are fragments only referenced from XML
+-keep class com.android.browser.preferences.*
diff --git a/res/anim/dialog_enter.xml b/res/anim/dialog_enter.xml
deleted file mode 100644
index f98d845..0000000
--- a/res/anim/dialog_enter.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:interpolator="@android:anim/decelerate_interpolator">
- <translate android:fromYDelta="25%" android:toYDelta="0" android:duration="75"/>
- <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="75" />
-</set>
diff --git a/res/drawable-hdpi/button_selected.png b/res/drawable-hdpi/button_selected.png
new file mode 100644
index 0000000..752deda
--- /dev/null
+++ b/res/drawable-hdpi/button_selected.png
Binary files differ
diff --git a/res/drawable-hdpi/default_video_poster.png b/res/drawable-hdpi/default_video_poster.png
new file mode 100644
index 0000000..9bbaf9c
--- /dev/null
+++ b/res/drawable-hdpi/default_video_poster.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_arrow_left.png b/res/drawable-hdpi/ic_arrow_left.png
new file mode 100644
index 0000000..bcbe3f6
--- /dev/null
+++ b/res/drawable-hdpi/ic_arrow_left.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_arrow_right.png b/res/drawable-hdpi/ic_arrow_right.png
new file mode 100644
index 0000000..6095533
--- /dev/null
+++ b/res/drawable-hdpi/ic_arrow_right.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_btn_find_next.png b/res/drawable-hdpi/ic_btn_find_next.png
deleted file mode 100644
index b696a6b..0000000
--- a/res/drawable-hdpi/ic_btn_find_next.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_btn_find_prev.png b/res/drawable-hdpi/ic_btn_find_prev.png
deleted file mode 100644
index 5550c5a..0000000
--- a/res/drawable-hdpi/ic_btn_find_prev.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_clear_search.png b/res/drawable-hdpi/ic_clear_search.png
new file mode 100644
index 0000000..e8e67b4
--- /dev/null
+++ b/res/drawable-hdpi/ic_clear_search.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_favorite_off_normal.png b/res/drawable-hdpi/ic_favorite_off_normal.png
new file mode 100644
index 0000000..4741464
--- /dev/null
+++ b/res/drawable-hdpi/ic_favorite_off_normal.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_go_normal_white.png b/res/drawable-hdpi/ic_go_normal_white.png
new file mode 100644
index 0000000..1ae9ed9
--- /dev/null
+++ b/res/drawable-hdpi/ic_go_normal_white.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu.png b/res/drawable-hdpi/ic_menu.png
new file mode 100644
index 0000000..00f784f
--- /dev/null
+++ b/res/drawable-hdpi/ic_menu.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu_downloads.png b/res/drawable-hdpi/ic_menu_downloads.png
new file mode 100644
index 0000000..c85f6a2
--- /dev/null
+++ b/res/drawable-hdpi/ic_menu_downloads.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu_pageinfo.png b/res/drawable-hdpi/ic_menu_pageinfo.png
new file mode 100644
index 0000000..293a021
--- /dev/null
+++ b/res/drawable-hdpi/ic_menu_pageinfo.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu_settings.png b/res/drawable-hdpi/ic_menu_settings.png
new file mode 100644
index 0000000..46be101
--- /dev/null
+++ b/res/drawable-hdpi/ic_menu_settings.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu_share.png b/res/drawable-hdpi/ic_menu_share.png
new file mode 100644
index 0000000..4b69736
--- /dev/null
+++ b/res/drawable-hdpi/ic_menu_share.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_pages.png b/res/drawable-hdpi/ic_pages.png
new file mode 100644
index 0000000..3fc2e46
--- /dev/null
+++ b/res/drawable-hdpi/ic_pages.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_reload.png b/res/drawable-hdpi/ic_reload.png
new file mode 100644
index 0000000..ebad6da
--- /dev/null
+++ b/res/drawable-hdpi/ic_reload.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_star.png b/res/drawable-hdpi/ic_star.png
new file mode 100644
index 0000000..666c670
--- /dev/null
+++ b/res/drawable-hdpi/ic_star.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_stop.png b/res/drawable-hdpi/ic_stop.png
new file mode 100644
index 0000000..0f1337f
--- /dev/null
+++ b/res/drawable-hdpi/ic_stop.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_web_white.png b/res/drawable-hdpi/ic_web_white.png
new file mode 100644
index 0000000..fec99ca
--- /dev/null
+++ b/res/drawable-hdpi/ic_web_white.png
Binary files differ
diff --git a/res/drawable-hdpi/list_divider_vert.9.png b/res/drawable-hdpi/list_divider_vert.9.png
new file mode 100644
index 0000000..d99730a
--- /dev/null
+++ b/res/drawable-hdpi/list_divider_vert.9.png
Binary files differ
diff --git a/res/drawable-hdpi/pattern_carbon_fiber_dark.png b/res/drawable-hdpi/pattern_carbon_fiber_dark.png
new file mode 100644
index 0000000..cc8e0c5
--- /dev/null
+++ b/res/drawable-hdpi/pattern_carbon_fiber_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/progress_stop.png b/res/drawable-hdpi/progress_stop.png
new file mode 100644
index 0000000..aacece2
--- /dev/null
+++ b/res/drawable-hdpi/progress_stop.png
Binary files differ
diff --git a/res/drawable-hdpi/tab_selected_bg.9.png b/res/drawable-hdpi/tab_selected_bg.9.png
new file mode 100644
index 0000000..4e0f740
--- /dev/null
+++ b/res/drawable-hdpi/tab_selected_bg.9.png
Binary files differ
diff --git a/res/drawable-hdpi/tab_unselected_bg.9.png b/res/drawable-hdpi/tab_unselected_bg.9.png
new file mode 100644
index 0000000..9ab7c56
--- /dev/null
+++ b/res/drawable-hdpi/tab_unselected_bg.9.png
Binary files differ
diff --git a/res/drawable-mdpi/bookmark_dialog_bg.9.png b/res/drawable-mdpi/bookmark_dialog_bg.9.png
new file mode 100644
index 0000000..f169daa
--- /dev/null
+++ b/res/drawable-mdpi/bookmark_dialog_bg.9.png
Binary files differ
diff --git a/res/drawable-mdpi/cab_bg.9.png b/res/drawable-mdpi/cab_bg.9.png
new file mode 100644
index 0000000..caf404f
--- /dev/null
+++ b/res/drawable-mdpi/cab_bg.9.png
Binary files differ
diff --git a/res/drawable/default_video_poster.png b/res/drawable-mdpi/default_video_poster.png
similarity index 100%
rename from res/drawable/default_video_poster.png
rename to res/drawable-mdpi/default_video_poster.png
Binary files differ
diff --git a/res/drawable-mdpi/dialog_full.9.png b/res/drawable-mdpi/dialog_full.9.png
new file mode 100644
index 0000000..2c9027b
--- /dev/null
+++ b/res/drawable-mdpi/dialog_full.9.png
Binary files differ
diff --git a/res/drawable-mdpi/empty_bookmark_image.png b/res/drawable-mdpi/empty_bookmark_image.png
new file mode 100644
index 0000000..7e79f35
--- /dev/null
+++ b/res/drawable-mdpi/empty_bookmark_image.png
Binary files differ
diff --git a/res/drawable-mdpi/fav_incognito.png b/res/drawable-mdpi/fav_incognito.png
new file mode 100644
index 0000000..6a120b9
--- /dev/null
+++ b/res/drawable-mdpi/fav_incognito.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_add_string.png b/res/drawable-mdpi/ic_add_string.png
new file mode 100644
index 0000000..e3b95cb
--- /dev/null
+++ b/res/drawable-mdpi/ic_add_string.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_back_normal.png b/res/drawable-mdpi/ic_back_normal.png
new file mode 100644
index 0000000..7e09a94
--- /dev/null
+++ b/res/drawable-mdpi/ic_back_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_bookmarks_history_normal.png b/res/drawable-mdpi/ic_bookmarks_history_normal.png
new file mode 100644
index 0000000..60a7b4a
--- /dev/null
+++ b/res/drawable-mdpi/ic_bookmarks_history_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_btn_copy.png b/res/drawable-mdpi/ic_btn_copy.png
new file mode 100644
index 0000000..04fda7f
--- /dev/null
+++ b/res/drawable-mdpi/ic_btn_copy.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_btn_find.png b/res/drawable-mdpi/ic_btn_find.png
new file mode 100755
index 0000000..20e1fbc
--- /dev/null
+++ b/res/drawable-mdpi/ic_btn_find.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_btn_find_next.png b/res/drawable-mdpi/ic_btn_find_next.png
deleted file mode 100644
index abdc247..0000000
--- a/res/drawable-mdpi/ic_btn_find_next.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_btn_find_prev.png b/res/drawable-mdpi/ic_btn_find_prev.png
deleted file mode 100644
index 4e3da1d..0000000
--- a/res/drawable-mdpi/ic_btn_find_prev.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_btn_select_all.png b/res/drawable-mdpi/ic_btn_select_all.png
new file mode 100644
index 0000000..839915b
--- /dev/null
+++ b/res/drawable-mdpi/ic_btn_select_all.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_btn_share.png b/res/drawable-mdpi/ic_btn_share.png
new file mode 100644
index 0000000..44db9b1
--- /dev/null
+++ b/res/drawable-mdpi/ic_btn_share.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_clear_search.png b/res/drawable-mdpi/ic_clear_search.png
new file mode 100644
index 0000000..e8e67b4
--- /dev/null
+++ b/res/drawable-mdpi/ic_clear_search.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_favorite_off_normal.png b/res/drawable-mdpi/ic_favorite_off_normal.png
new file mode 100644
index 0000000..4741464
--- /dev/null
+++ b/res/drawable-mdpi/ic_favorite_off_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_favorite_on_dark.png b/res/drawable-mdpi/ic_favorite_on_dark.png
new file mode 100644
index 0000000..50563c1
--- /dev/null
+++ b/res/drawable-mdpi/ic_favorite_on_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_favorite_on_normal.png b/res/drawable-mdpi/ic_favorite_on_normal.png
new file mode 100644
index 0000000..bd239e8
--- /dev/null
+++ b/res/drawable-mdpi/ic_favorite_on_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_folder.png b/res/drawable-mdpi/ic_folder.png
new file mode 100644
index 0000000..ee85b28
--- /dev/null
+++ b/res/drawable-mdpi/ic_folder.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_forward_normal.png b/res/drawable-mdpi/ic_forward_normal.png
new file mode 100644
index 0000000..f306403
--- /dev/null
+++ b/res/drawable-mdpi/ic_forward_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_go_dark.png b/res/drawable-mdpi/ic_go_dark.png
new file mode 100644
index 0000000..88c0985
--- /dev/null
+++ b/res/drawable-mdpi/ic_go_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_go_normal_white.png b/res/drawable-mdpi/ic_go_normal_white.png
new file mode 100644
index 0000000..1ae9ed9
--- /dev/null
+++ b/res/drawable-mdpi/ic_go_normal_white.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu.png b/res/drawable-mdpi/ic_menu.png
new file mode 100644
index 0000000..520b2c3
--- /dev/null
+++ b/res/drawable-mdpi/ic_menu.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_archive_normal.png b/res/drawable-mdpi/ic_menu_archive_normal.png
new file mode 100644
index 0000000..40f25a4
--- /dev/null
+++ b/res/drawable-mdpi/ic_menu_archive_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_cab_close.png b/res/drawable-mdpi/ic_menu_cab_close.png
new file mode 100644
index 0000000..3451027
--- /dev/null
+++ b/res/drawable-mdpi/ic_menu_cab_close.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_cab_pencil.png b/res/drawable-mdpi/ic_menu_cab_pencil.png
new file mode 100644
index 0000000..5d6ab57
--- /dev/null
+++ b/res/drawable-mdpi/ic_menu_cab_pencil.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_downloads_normal.png b/res/drawable-mdpi/ic_menu_downloads_normal.png
new file mode 100644
index 0000000..37b6b75
--- /dev/null
+++ b/res/drawable-mdpi/ic_menu_downloads_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_findonpage_normal.png b/res/drawable-mdpi/ic_menu_findonpage_normal.png
new file mode 100644
index 0000000..bea6e44
--- /dev/null
+++ b/res/drawable-mdpi/ic_menu_findonpage_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_incognito_normal.png b/res/drawable-mdpi/ic_menu_incognito_normal.png
new file mode 100644
index 0000000..2e78dc6
--- /dev/null
+++ b/res/drawable-mdpi/ic_menu_incognito_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_new_window.png b/res/drawable-mdpi/ic_menu_new_window.png
index 7fb9948..c767979 100644
--- a/res/drawable-mdpi/ic_menu_new_window.png
+++ b/res/drawable-mdpi/ic_menu_new_window.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_overflow.png b/res/drawable-mdpi/ic_menu_overflow.png
new file mode 100644
index 0000000..e565760
--- /dev/null
+++ b/res/drawable-mdpi/ic_menu_overflow.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_pageinfo_normal.png b/res/drawable-mdpi/ic_menu_pageinfo_normal.png
new file mode 100644
index 0000000..3422e98
--- /dev/null
+++ b/res/drawable-mdpi/ic_menu_pageinfo_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_settings_normal.png b/res/drawable-mdpi/ic_menu_settings_normal.png
new file mode 100644
index 0000000..bd2c30a
--- /dev/null
+++ b/res/drawable-mdpi/ic_menu_settings_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_share_normal.png b/res/drawable-mdpi/ic_menu_share_normal.png
new file mode 100644
index 0000000..4410baa
--- /dev/null
+++ b/res/drawable-mdpi/ic_menu_share_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_pages.png b/res/drawable-mdpi/ic_pages.png
new file mode 100644
index 0000000..fba4651
--- /dev/null
+++ b/res/drawable-mdpi/ic_pages.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_pressed.png b/res/drawable-mdpi/ic_pressed.png
new file mode 100644
index 0000000..fd1c7d9
--- /dev/null
+++ b/res/drawable-mdpi/ic_pressed.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_refresh_normal.png b/res/drawable-mdpi/ic_refresh_normal.png
new file mode 100644
index 0000000..f8ce51d
--- /dev/null
+++ b/res/drawable-mdpi/ic_refresh_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_search_category_bookmark.png b/res/drawable-mdpi/ic_search_category_bookmark.png
old mode 100755
new mode 100644
index d228408..4b3bd2d
--- a/res/drawable-mdpi/ic_search_category_bookmark.png
+++ b/res/drawable-mdpi/ic_search_category_bookmark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_search_category_browser.png b/res/drawable-mdpi/ic_search_category_browser.png
index da8d4e3..d721425 100644
--- a/res/drawable-mdpi/ic_search_category_browser.png
+++ b/res/drawable-mdpi/ic_search_category_browser.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_search_category_history.png b/res/drawable-mdpi/ic_search_category_history.png
old mode 100755
new mode 100644
index 12cd51c..1a3fc98
--- a/res/drawable-mdpi/ic_search_category_history.png
+++ b/res/drawable-mdpi/ic_search_category_history.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_search_category_suggest.png b/res/drawable-mdpi/ic_search_category_suggest.png
old mode 100755
new mode 100644
index a4ed7aa..0216581
--- a/res/drawable-mdpi/ic_search_category_suggest.png
+++ b/res/drawable-mdpi/ic_search_category_suggest.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_search_normal.png b/res/drawable-mdpi/ic_search_normal.png
new file mode 100644
index 0000000..e1fa6d3
--- /dev/null
+++ b/res/drawable-mdpi/ic_search_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_stop_normal.png b/res/drawable-mdpi/ic_stop_normal.png
new file mode 100644
index 0000000..6bd22f9
--- /dev/null
+++ b/res/drawable-mdpi/ic_stop_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_tab_close.png b/res/drawable-mdpi/ic_tab_close.png
new file mode 100644
index 0000000..2f23842
--- /dev/null
+++ b/res/drawable-mdpi/ic_tab_close.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_web_white.png b/res/drawable-mdpi/ic_web_white.png
new file mode 100644
index 0000000..fec99ca
--- /dev/null
+++ b/res/drawable-mdpi/ic_web_white.png
Binary files differ
diff --git a/res/drawable-mdpi/list_divider_vert.9.png b/res/drawable-mdpi/list_divider_vert.9.png
new file mode 100644
index 0000000..d99730a
--- /dev/null
+++ b/res/drawable-mdpi/list_divider_vert.9.png
Binary files differ
diff --git a/res/drawable-mdpi/menu_dropdown.9.png b/res/drawable-mdpi/menu_dropdown.9.png
new file mode 100644
index 0000000..562d55b
--- /dev/null
+++ b/res/drawable-mdpi/menu_dropdown.9.png
Binary files differ
diff --git a/res/drawable/pattern_carbon_fiber_dark.png b/res/drawable-mdpi/pattern_carbon_fiber_dark.png
similarity index 100%
rename from res/drawable/pattern_carbon_fiber_dark.png
rename to res/drawable-mdpi/pattern_carbon_fiber_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/progress.9.png b/res/drawable-mdpi/progress.9.png
new file mode 100644
index 0000000..08de04c
--- /dev/null
+++ b/res/drawable-mdpi/progress.9.png
Binary files differ
diff --git a/res/drawable-mdpi/progress_stop.png b/res/drawable-mdpi/progress_stop.png
new file mode 100644
index 0000000..a85f987
--- /dev/null
+++ b/res/drawable-mdpi/progress_stop.png
Binary files differ
diff --git a/res/drawable-mdpi/tab_selected_bg.9.png b/res/drawable-mdpi/tab_selected_bg.9.png
new file mode 100644
index 0000000..261982e
--- /dev/null
+++ b/res/drawable-mdpi/tab_selected_bg.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tab_unselected_bg.9.png b/res/drawable-mdpi/tab_unselected_bg.9.png
new file mode 100644
index 0000000..5d483e0
--- /dev/null
+++ b/res/drawable-mdpi/tab_unselected_bg.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tabbar_bg.9.png b/res/drawable-mdpi/tabbar_bg.9.png
new file mode 100644
index 0000000..bb9928d
--- /dev/null
+++ b/res/drawable-mdpi/tabbar_bg.9.png
Binary files differ
diff --git a/res/drawable-mdpi/text_field.9.png b/res/drawable-mdpi/text_field.9.png
new file mode 100644
index 0000000..92de7c8
--- /dev/null
+++ b/res/drawable-mdpi/text_field.9.png
Binary files differ
diff --git a/res/drawable-mdpi/text_field_focused.9.png b/res/drawable-mdpi/text_field_focused.9.png
new file mode 100644
index 0000000..6e84bb3
--- /dev/null
+++ b/res/drawable-mdpi/text_field_focused.9.png
Binary files differ
diff --git a/res/drawable-mdpi/text_field_results.9.png b/res/drawable-mdpi/text_field_results.9.png
new file mode 100644
index 0000000..167c42d
--- /dev/null
+++ b/res/drawable-mdpi/text_field_results.9.png
Binary files differ
diff --git a/res/drawable-mdpi/urlbar_bg.9.png b/res/drawable-mdpi/urlbar_bg.9.png
new file mode 100644
index 0000000..18b49e7
--- /dev/null
+++ b/res/drawable-mdpi/urlbar_bg.9.png
Binary files differ
diff --git a/res/menu/bookmarks.xml b/res/drawable/browserbarbutton.xml
similarity index 63%
copy from res/menu/bookmarks.xml
copy to res/drawable/browserbarbutton.xml
index a8781c2..d3eebbe 100644
--- a/res/menu/bookmarks.xml
+++ b/res/drawable/browserbarbutton.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
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.
@@ -14,10 +14,8 @@
limitations under the License.
-->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:id="@+id/new_context_menu_id"
- android:icon="@drawable/ic_menu_add_bookmark"
- android:title="@string/bookmark_page" />
- <item android:id="@+id/switch_mode_menu_id"
- />
-</menu>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true"
+ android:drawable="@drawable/ic_pressed" />
+ <item android:state_pressed="false" android:drawable="@drawable/clear" />
+</selector>
diff --git a/res/drawable/button_bg_selected.xml b/res/drawable/button_bg_selected.xml
new file mode 100644
index 0000000..d0c677b
--- /dev/null
+++ b/res/drawable/button_bg_selected.xml
@@ -0,0 +1,18 @@
+<?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.
+ -->
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid
+ android:color="#ff4d83ba" />
+</shape>
\ No newline at end of file
diff --git a/res/anim/dialog_exit.xml b/res/drawable/clear.xml
similarity index 62%
rename from res/anim/dialog_exit.xml
rename to res/drawable/clear.xml
index dacb5c3..267db10 100644
--- a/res/anim/dialog_exit.xml
+++ b/res/drawable/clear.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
+<!-- Copyright (C) 2010 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,9 +14,10 @@
limitations under the License.
-->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:interpolator="@android:anim/accelerate_interpolator">
- <translate android:fromYDelta="0" android:toYDelta="50%" android:duration="50"/>
- <alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="50" />
-</set>
-
+<!-- Used by browserbarbutton to show a clear background for the non pressed
+ state -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="#00000000"/>
+ <padding android:left="4dp" android:top="4dp"
+ android:right="4dp" android:bottom="4dp" />
+</shape>
diff --git a/res/drawable/ic_menu_incognito.png b/res/drawable/ic_menu_incognito.png
new file mode 100644
index 0000000..d5a7022
--- /dev/null
+++ b/res/drawable/ic_menu_incognito.png
Binary files differ
diff --git a/res/anim/dialog_exit.xml b/res/drawable/tab_background.xml
similarity index 62%
copy from res/anim/dialog_exit.xml
copy to res/drawable/tab_background.xml
index dacb5c3..6fc3ee3 100644
--- a/res/anim/dialog_exit.xml
+++ b/res/drawable/tab_background.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
+<!-- Copyright (C) 2010 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,9 +14,13 @@
limitations under the License.
-->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:interpolator="@android:anim/accelerate_interpolator">
- <translate android:fromYDelta="0" android:toYDelta="50%" android:duration="50"/>
- <alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="50" />
-</set>
-
+<selector
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_activated="true"
+ android:drawable="@drawable/tab_selected_bg" />
+ <item
+ android:state_activated="false"
+ android:drawable="@drawable/tab_unselected_bg">
+ </item>
+</selector>
diff --git a/res/layout/bookmark_thumbnail.xml b/res/layout/bookmark_thumbnail.xml
index 1f017d0..91d8db7 100644
--- a/res/layout/bookmark_thumbnail.xml
+++ b/res/layout/bookmark_thumbnail.xml
@@ -23,39 +23,12 @@
<ImageView android:id="@+id/thumb"
android:src="@drawable/browser_thumbnail"
- android:scaleType="center"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
+ android:scaleType="centerCrop"
+ android:layout_height="@dimen/bookmarkThumbnailHeight"
+ android:layout_width="@dimen/bookmarkThumbnailWidth"
android:layout_gravity="center"
/>
- <!-- FIXME: Want to have a gradient over the thumb -->
-
- <!-- This holds the star for addbookmark -->
- <LinearLayout android:id="@+id/holder"
- android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:orientation="horizontal"
- android:background="#99000000"
- android:gravity="center"
- android:layout_alignBottom="@+id/thumb"
- android:layout_alignTop="@+id/thumb"
- >
- <ImageView
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:src="@drawable/ic_list_bookmark"
- />
- <TextView
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textStyle="bold"
- android:textColor="@color/white"
- android:text="@string/add_bookmark_short"
- />
- </LinearLayout>
-
<TextView android:id="@+id/label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/res/layout/bookmarks.xml b/res/layout/bookmarks.xml
new file mode 100644
index 0000000..d90620c
--- /dev/null
+++ b/res/layout/bookmarks.xml
@@ -0,0 +1,60 @@
+<?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="match_parent"
+ android:layout_height="match_parent"
+>
+
+ <LinearLayout android:id="@android:id/content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ >
+
+ <Button android:id="@+id/up"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/defaultBookmarksUpButton"
+ />
+
+ <GridView android:id="@+id/grid"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+
+ android:horizontalSpacing="8dip"
+ android:verticalSpacing="14dip"
+ android:stretchMode="spacingWidth"
+ android:scrollbarStyle="insideInset"
+ android:listSelector="@android:drawable/gallery_thumb"
+ android:drawSelectorOnTop="true"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ android:numColumns="auto_fit"
+ />
+ </LinearLayout>
+
+ <TextView android:id="@android:id/empty"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:text="@string/empty_bookmarks_folder"
+ android:visibility="gone"
+ />
+
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/bookmarks_history.xml b/res/layout/bookmarks_history.xml
new file mode 100644
index 0000000..c7f57fd
--- /dev/null
+++ b/res/layout/bookmarks_history.xml
@@ -0,0 +1,32 @@
+<?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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+>
+ <ListView android:id="@android:id/list"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:layout_weight="20"
+ />
+
+ <FrameLayout android:id="@+id/fragment"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:layout_weight="80"
+ />
+</LinearLayout>
diff --git a/res/layout/bookmarkstackwidget.xml b/res/layout/bookmarkstackwidget.xml
new file mode 100644
index 0000000..c8c88c4
--- /dev/null
+++ b/res/layout/bookmarkstackwidget.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <StackView
+ android:id="@+id/stackwidget_stack"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:paddingTop="16dip"
+ android:paddingBottom="8dip"
+ android:paddingLeft="8dip"
+ android:paddingRight="8dip"
+ android:background="#00000000"
+ android:cacheColorHint="#00000000"
+ android:autoStart="true" />
+ <ImageView
+ android:id="@+id/logo"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ android:src="@drawable/ic_launcher_shortcut_browser_bookmark" />
+</RelativeLayout>
diff --git a/res/layout/bookmarkstackwidget_item.xml b/res/layout/bookmarkstackwidget_item.xml
new file mode 100644
index 0000000..e7992f7
--- /dev/null
+++ b/res/layout/bookmarkstackwidget_item.xml
@@ -0,0 +1,47 @@
+<?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.
+-->
+
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/stack_item"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:padding="16dip">
+ <ImageView
+ android:id="@+id/thumb"
+ android:src="@drawable/browser_thumbnail"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:scaleType="fitXY"
+ android:layout_centerInParent="true" />
+ <TextView
+ android:id="@+id/label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textStyle="bold"
+ android:textColor="@color/white"
+ android:maxLines="1"
+ android:paddingLeft="2dip"
+ android:paddingRight="2dip"
+ android:paddingTop="0dip"
+ android:paddingBottom="0dip"
+ android:scrollHorizontally="true"
+ android:ellipsize="marquee"
+ android:layout_alignBottom="@id/thumb"
+ android:layout_alignLeft="@id/thumb"
+ android:layout_alignRight="@id/thumb" />
+</RelativeLayout>
diff --git a/res/layout/bookmarkwidget.xml b/res/layout/bookmarkwidget.xml
index 2416e4f..c7c2a90 100644
--- a/res/layout/bookmarkwidget.xml
+++ b/res/layout/bookmarkwidget.xml
@@ -31,7 +31,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dip"
- android:src="@drawable/ic_btn_find_prev" />
+ android:src="@*android:drawable/ic_btn_find_prev" />
<TextView
android:id="@+id/title"
@@ -49,7 +49,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dip"
- android:src="@drawable/ic_btn_find_next" />
+ android:src="@*android:drawable/ic_btn_find_next" />
</LinearLayout>
diff --git a/res/layout/browser_add_bookmark.xml b/res/layout/browser_add_bookmark.xml
index e8a08a4..604bda8 100644
--- a/res/layout/browser_add_bookmark.xml
+++ b/res/layout/browser_add_bookmark.xml
@@ -29,11 +29,10 @@
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"/>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ <RelativeLayout android:id="@+id/default_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:orientation="vertical"
android:paddingTop="5dip"
android:paddingBottom="13dip"
android:paddingLeft="20dip"
@@ -43,6 +42,10 @@
android:id="@+id/titleText"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_marginRight="50dip"
+ android:layout_marginBottom="40dip"
+ android:layout_marginTop="40dip"
android:text="@string/name"
android:gravity="left"
android:textAppearance="?android:attr/textAppearanceMedium" />
@@ -52,8 +55,11 @@
android:layout_height="wrap_content"
android:layout_width="250dip"
android:gravity="fill_horizontal"
+ android:layout_alignBaseline="@+id/titleText"
+ android:layout_toRightOf="@+id/titleText"
android:inputType="textCapSentences"
android:selectAllOnFocus="true"
+ android:ellipsize="end"
android:textAppearance="?android:attr/textAppearanceMedium" />
@@ -64,6 +70,10 @@
android:layout_width="wrap_content"
android:text="@string/location"
android:gravity="left"
+ android:layout_below="@+id/titleText"
+ android:layout_alignLeft="@+id/titleText"
+ android:layout_marginBottom="40dip"
+ android:layout_marginRight="20dip"
android:textAppearance="?android:attr/textAppearanceMedium" />
<EditText
@@ -71,16 +81,85 @@
android:layout_height="wrap_content"
android:layout_width="250dip"
android:hint="@string/http"
+ android:layout_alignBaseline="@+id/addressText"
+ android:layout_alignLeft="@+id/title"
android:gravity="fill_horizontal"
android:inputType="textUri"
android:selectAllOnFocus="true"
+ android:ellipsize="end"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/add_to"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/containing_folder"
+ android:layout_below="@+id/addressText"
+ android:layout_alignLeft="@+id/titleText"
+ android:layout_marginRight="20dip"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/folder"
+ android:layout_height="wrap_content"
+ android:layout_width="250dip"
+ android:layout_alignLeft="@+id/title"
+ android:layout_alignBaseline="@+id/add_to"
+ android:singleLine="true"
+ android:ellipsize="start"
+ android:text="@string/bookmarks"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ </RelativeLayout>
+
+ <LinearLayout android:id="@+id/folder_selector"
+ android:layout_width="500dip"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:visibility="gone"
+ >
+
+ <TextView
+ android:id="@+id/path"
+ android:layout_marginTop="4dip"
+ android:layout_marginLeft="16dip"
+ android:layout_marginRight="16dip"
+ android:layout_marginBottom="4dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="start"
+ android:text="@string/bookmarks"
+ android:textAppearance="?android:attr/textAppearanceLarge" />
+
+ <ListView
+ android:id="@+id/list"
+ android:layout_marginLeft="16dip"
+ android:layout_marginRight="16dip"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ />
+ <EditText
+ android:id="@+id/folder_namer"
+ android:layout_marginLeft="16dip"
+ android:layout_marginRight="16dip"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ />
+ <Button
+ android:id="@+id/add_new_folder"
+ android_marginTop="16dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:text="@string/add_new_folder"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
-
+
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="#c6c3c6"
android:minHeight="54dip"
android:orientation="horizontal"
android:paddingTop="4dip"
@@ -103,4 +182,3 @@
</LinearLayout>
</LinearLayout>
-
diff --git a/res/layout/browser_add_bookmark_const_url.xml b/res/layout/browser_add_bookmark_const_url.xml
new file mode 100644
index 0000000..6a6d78f
--- /dev/null
+++ b/res/layout/browser_add_bookmark_const_url.xml
@@ -0,0 +1,85 @@
+<?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="wrap_content"
+ android:orientation="vertical"
+ >
+
+ <ImageView android:id="@+id/titleDivider"
+ android:layout_width="match_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 xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:paddingTop="5dip"
+ android:paddingBottom="13dip"
+ android:paddingLeft="20dip"
+ android:paddingRight="20dip" >
+
+ <TextView
+ android:id="@+id/titleText"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/name"
+ android:gravity="left"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <EditText
+ android:id="@+id/title"
+ android:layout_height="wrap_content"
+ android:layout_width="250dip"
+ android:gravity="fill_horizontal"
+ android:inputType="textCapSentences"
+ android:selectAllOnFocus="true" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="54dip"
+ android:orientation="horizontal"
+ android:paddingTop="4dip"
+ android:paddingLeft="2dip"
+ android:paddingRight="2dip" >
+ <Button android:id="@+id/OK"
+ android:text="@string/save"
+ android:layout_width="0dip"
+ android:layout_gravity="left"
+ android:layout_weight="1"
+ android:maxLines="2"
+ android:layout_height="wrap_content" />
+ <Button android:id="@+id/cancel"
+ android:text="@string/do_not_save"
+ android:layout_width="0dip"
+ android:layout_gravity="right"
+ android:layout_weight="1"
+ android:maxLines="2"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+
+</LinearLayout>
+
diff --git a/res/layout/browser_find.xml b/res/layout/browser_find.xml
deleted file mode 100644
index e2f0cf6..0000000
--- a/res/layout/browser_find.xml
+++ /dev/null
@@ -1,76 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/findControls"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="5dip"
- android:paddingLeft="4dip"
- android:paddingRight="4dip"
- android:paddingBottom="1dip"
- android:background="@android:drawable/bottom_bar">
- <ImageButton
- android:src="@drawable/ic_btn_find_prev"
- android:id="@+id/previous"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
-
- <ImageButton
- android:src="@drawable/ic_btn_find_next"
- android:id="@+id/next"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
-
- <LinearLayout
- android:layout_height="wrap_content"
- android:layout_width="0dip"
- android:layout_weight="1"
- android:orientation="vertical"
- android:layout_marginRight="6dip"
- >
- <EditText android:id="@+id/edit"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:scrollHorizontally="true"
- android:inputType="text"
- android:hint="@string/find_dot"
- />
- <LinearLayout android:id="@+id/matches_view"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="right"
- android:visibility="invisible"
- >
- <TextView android:id="@+id/matches"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="right"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorSecondaryInverse"
- />
- </LinearLayout>
- </LinearLayout>
- <ImageButton android:id="@+id/done"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_btn_close_panel"
- />
-</LinearLayout>
-
diff --git a/res/layout/browser_select.xml b/res/layout/browser_select.xml
deleted file mode 100644
index b30be8d..0000000
--- a/res/layout/browser_select.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/selectControls"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="5dip"
- android:paddingLeft="4dip"
- android:paddingRight="4dip"
- android:paddingBottom="1dip"
- android:background="@android:drawable/bottom_bar">
- <ImageButton
- android:src="@drawable/ic_btn_copy"
- android:id="@+id/copy"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
-
- <ImageButton
- android:src="@drawable/ic_btn_share"
- android:id="@+id/share"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
-
- <ImageButton
- android:src="@drawable/ic_btn_select_all"
- android:id="@+id/select_all"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
-
- <ImageButton
- android:src="@drawable/ic_btn_find"
- android:id="@+id/find"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
-
- <LinearLayout
- android:layout_height="fill_parent"
- android:layout_width="fill_parent"
- android:layout_weight="1"
- />
-
- <ImageButton
- android:src="@drawable/ic_btn_close_panel"
- android:id="@+id/done"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
-</LinearLayout>
-
diff --git a/res/layout/custom_screen.xml b/res/layout/custom_screen.xml
index 90dc324..525f30c 100644
--- a/res/layout/custom_screen.xml
+++ b/res/layout/custom_screen.xml
@@ -22,6 +22,7 @@
android:layout_height="match_parent"
/>
<LinearLayout android:orientation="vertical"
+ android:id="@+id/vertical_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
diff --git a/res/layout/empty_history.xml b/res/layout/empty_history.xml
deleted file mode 100644
index 4484a16..0000000
--- a/res/layout/empty_history.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.
--->
-
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/empty_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:text="@string/empty_history"
- android:background="@color/black"
- android:textColor="@color/white"
- android:gravity="center"
- android:textStyle="bold"
- />
diff --git a/res/layout/folder_list_item.xml b/res/layout/folder_list_item.xml
new file mode 100644
index 0000000..56c597b
--- /dev/null
+++ b/res/layout/folder_list_item.xml
@@ -0,0 +1,37 @@
+<?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="wrap_content"
+ android:orientation="horizontal">
+ <ImageView
+ android:id="@+id/icon1"
+ style="@style/HoloIcon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:src="@drawable/ic_go_normal_white" />
+ <TextView
+ android:id="@android:id/text1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:gravity="center_vertical"
+ android:paddingLeft="6dip"
+ android:minHeight="?android:attr/listPreferredItemHeight" />
+</LinearLayout>
diff --git a/res/layout/history.xml b/res/layout/history.xml
new file mode 100644
index 0000000..f6e844a
--- /dev/null
+++ b/res/layout/history.xml
@@ -0,0 +1,38 @@
+<?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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+>
+
+ <ExpandableListView android:id="@android:id/list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:drawSelectorOnTop="false"
+ />
+
+ <TextView android:id="@android:id/empty"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:text="@string/empty_history"
+ android:visibility="gone"
+ />
+
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/import_bookmarks_dialog.xml b/res/layout/import_bookmarks_dialog.xml
new file mode 100644
index 0000000..f10f35d
--- /dev/null
+++ b/res/layout/import_bookmarks_dialog.xml
@@ -0,0 +1,47 @@
+<?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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:padding="8dip"
+>
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/import_bookmarks_dialog_description"
+ />
+
+ <LinearLayout android:id="@+id/accountList"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ />
+
+ <Button android:id="@+id/remove"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/import_bookmarks_dialog_remove"
+ android:maxLines="2"
+ />
+
+ <Button android:id="@+id/cancel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@android:string/cancel"
+ />
+</LinearLayout>
\ No newline at end of file
diff --git a/res/menu/bookmarks.xml b/res/layout/import_bookmarks_dialog_button.xml
similarity index 69%
rename from res/menu/bookmarks.xml
rename to res/layout/import_bookmarks_dialog_button.xml
index a8781c2..cf8f628 100644
--- a/res/menu/bookmarks.xml
+++ b/res/layout/import_bookmarks_dialog_button.xml
@@ -14,10 +14,9 @@
limitations under the License.
-->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:id="@+id/new_context_menu_id"
- android:icon="@drawable/ic_menu_add_bookmark"
- android:title="@string/bookmark_page" />
- <item android:id="@+id/switch_mode_menu_id"
- />
-</menu>
+<Button xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/import_bookmarks_dialog_remove"
+ android:maxLines="2"
+/>
diff --git a/res/layout/suggestion_item.xml b/res/layout/suggestion_item.xml
new file mode 100644
index 0000000..fec5ae3
--- /dev/null
+++ b/res/layout/suggestion_item.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/layout/simple_spinner_item.xml
+**
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="56dip"
+ android:orientation="horizontal"
+ android:gravity="center_vertical"
+ android:baselineAligned="false">
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/icon1"
+ android:scaleType="center"
+ style="@style/HoloButton" />
+ <RelativeLayout
+ android:paddingTop="8dip"
+ android:paddingBottom="8dip"
+ android:layout_width="0dip"
+ android:layout_weight="1"
+ android:layout_height="wrap_content" >
+ <TextView
+ android:id="@android:id/text1"
+ style="?android:attr/dropDownItemStyle"
+ android:textAppearance="?android:attr/textAppearanceMediumInverse"
+ android:singleLine="true"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ <TextView
+ android:id="@android:id/text2"
+ style="?android:attr/dropDownItemStyle"
+ android:textAppearance="?android:attr/textAppearanceSmallInverse"
+ android:textColor="#323232"
+ android:singleLine="true"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@android:id/text1"
+ android:layout_alignLeft="@android:id/text1" />
+ </RelativeLayout>
+ <ImageButton
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/icon2"
+ android:scaleType="center"
+ style="@style/HoloButton"
+ android:src="@drawable/ic_add_string"
+ android:background="@drawable/browserbarbutton"
+ />
+ <View
+ android:id="@+id/spacer"
+ android:layout_width="16dip"
+ android:layout_height="match_parent"
+ />
+</LinearLayout>
diff --git a/res/layout/suggestion_two_column.xml b/res/layout/suggestion_two_column.xml
new file mode 100644
index 0000000..fc74140
--- /dev/null
+++ b/res/layout/suggestion_two_column.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/layout/simple_spinner_item.xml
+**
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:gravity="center_vertical"
+ android:baselineAligned="false">
+ <include
+ android:id="@+id/suggest1"
+ layout="@layout/suggestion_item"
+ android:layout_width="0dip"
+ android:layout_weight="1"
+ />
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="56dip"
+ android:background="@drawable/list_divider_vert" />
+ <include
+ android:id="@+id/suggest2"
+ layout="@layout/suggestion_item"
+ android:layout_width="0dip"
+ android:layout_weight="1"
+ />
+</LinearLayout>
diff --git a/res/layout/tab_bar.xml b/res/layout/tab_bar.xml
new file mode 100644
index 0000000..7967307
--- /dev/null
+++ b/res/layout/tab_bar.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ Copyright 2010, The Android Open Source Project Licensed under the
+ Apache License, Version 2.0 (the "License"); you may not use this file
+ except in compliance with the License. You may obtain a copy of the
+ License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
+ applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ CONDITIONS OF ANY KIND, either express or implied. See the License for
+ the specific language governing permissions and limitations under the
+ License.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/tabbarcontent"
+ android:layout_width="match_parent"
+ android:layout_height="48dip"
+ style="@style/ActionBarStyle"
+ android:orientation="horizontal">
+ <com.android.browser.TabScrollView
+ android:id="@+id/tabs"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1.0"
+ android:orientation="horizontal" />
+</LinearLayout>
diff --git a/res/layout/tab_title.xml b/res/layout/tab_title.xml
new file mode 100644
index 0000000..a2da03d
--- /dev/null
+++ b/res/layout/tab_title.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ Copyright 2010, The Android Open Source Project Licensed under the
+ Apache License, Version 2.0 (the "License"); you may not use this file
+ except in compliance with the License. You may obtain a copy of the
+ License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
+ applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ CONDITIONS OF ANY KIND, either express or implied. See the License for
+ the specific language governing permissions and limitations under the
+ License.
+ -->
+<merge
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical"
+ android:orientation="horizontal"
+ android:background="@drawable/tab_background">
+ <ImageView
+ android:id="@+id/incognito"
+ android:layout_width="16dip"
+ android:layout_height="16dip"
+ android:layout_marginLeft="3dip"
+ android:gravity="center_vertical"
+ android:src="@drawable/fav_incognito"
+ android:visibility="gone" />
+ <ImageView
+ android:id="@+id/favicon"
+ android:layout_width="20dip"
+ android:layout_height="20dip"
+ android:layout_marginLeft="16dip" />
+ <ImageView
+ android:id="@+id/lock"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="16dip"
+ android:visibility="gone" />
+ <TextView
+ android:id="@+id/title"
+ android:layout_height="match_parent"
+ android:layout_width="0dip"
+ android:layout_weight="1.0"
+ android:layout_marginLeft="16dip"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="@color/white"
+ android:gravity="center_vertical"
+ android:scrollHorizontally="true"
+ android:fadingEdge="horizontal"
+ android:fadingEdgeLength="24dip"
+ android:lines="1"
+ android:singleLine="true" />
+ <ImageButton
+ android:id="@+id/close"
+ android:background="@drawable/browserbarbutton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="16dip"
+ android:layout_marginRight="16dip"
+ android:src="@drawable/ic_tab_close" />
+</merge>
diff --git a/res/layout/tab_view_add_incognito_tab.xml b/res/layout/tab_view_add_incognito_tab.xml
new file mode 100644
index 0000000..d07b4f5
--- /dev/null
+++ b/res/layout/tab_view_add_incognito_tab.xml
@@ -0,0 +1,39 @@
+<?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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:layout_width="match_parent"
+ android:orientation="horizontal"
+ android:gravity="center_vertical"
+ >
+ <ImageView
+ android:layout_width="40dip"
+ android:layout_height="40dip"
+ android:layout_marginLeft="8dip"
+ android:layout_marginRight="8dip"
+ android:src="@drawable/ic_list_new_window"/>
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:maxLines="1"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:text="@string/new_incognito_tab"
+ />
+</LinearLayout>
diff --git a/res/layout/tabs.xml b/res/layout/tabs.xml
deleted file mode 100644
index c212547..0000000
--- a/res/layout/tabs.xml
+++ /dev/null
@@ -1,37 +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.
--->
-<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@android:id/tabhost"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <LinearLayout
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <TabWidget android:id="@android:id/tabs"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- />
-
- <FrameLayout android:id="@android:id/tabcontent"
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
- />
- </LinearLayout>
-</TabHost>
diff --git a/res/layout/title_bar.xml b/res/layout/title_bar.xml
index 9f0cb51..d6a77e0 100644
--- a/res/layout/title_bar.xml
+++ b/res/layout/title_bar.xml
@@ -90,7 +90,7 @@
android:layout_marginRight="-5dip"
android:scaleType="center"
android:background="@drawable/btn_bookmark"
- android:src="@drawable/ic_btn_bookmarks"
+ android:src="@drawable/ic_list_bookmark"
/>
</LinearLayout>
</LinearLayout>
diff --git a/res/layout/url_bar.xml b/res/layout/url_bar.xml
new file mode 100644
index 0000000..e85ad83
--- /dev/null
+++ b/res/layout/url_bar.xml
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!--
+ Copyright 2010, The Android Open Source Project Licensed under the
+ Apache License, Version 2.0 (the "License"); you may not use this file
+ except in compliance with the License. You may obtain a copy of the
+ License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
+ applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ CONDITIONS OF ANY KIND, either express or implied. See the License for
+ the specific language governing permissions and limitations under the
+ License.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <LinearLayout
+ android:id="@+id/taburlbar"
+ android:layout_width="match_parent"
+ android:layout_height="48dip"
+ android:orientation="horizontal"
+ android:background="@drawable/urlbar_bg">
+ <ImageButton
+ android:id="@+id/back"
+ android:src="@drawable/ic_back_normal"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ style="@style/HoloButton"
+ android:background="@drawable/browserbarbutton" />
+ <ImageButton
+ android:id="@+id/forward"
+ android:src="@drawable/ic_forward_normal"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ style="@style/HoloButton"
+ android:background="@drawable/browserbarbutton" />
+ <ImageView
+ android:id="@+id/stop"
+ android:background="@drawable/browserbarbutton"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ style="@style/HoloButton"
+ android:gravity="center_vertical"
+ android:src="@drawable/ic_stop_normal" />
+ <LinearLayout
+ android:id="@+id/urlbar_unfocused"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:layout_weight="1.0"
+ android:background="@null"
+ android:orientation="horizontal">
+ <ImageView
+ android:id="@+id/browsericon"
+ android:src="@drawable/ic_web_white"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ style="@style/HoloButton" />
+ <ImageView
+ android:id="@+id/lock"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ style="@style/HoloIcon"
+ android:visibility="gone" />
+ <EditText
+ android:id="@+id/url_unfocused"
+ android:layout_width="0dip"
+ android:layout_weight="1.0"
+ android:layout_height="match_parent"
+ android:background="@null"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="#ffc0c0c0"
+ android:hint="@string/search_hint"
+ android:gravity="center_vertical"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:lines="1"
+ android:scrollHorizontally="true"
+ android:inputType="textUri"
+ android:imeOptions="actionGo" />
+ <ImageButton
+ android:id="@+id/star"
+ android:src="@drawable/ic_favorite_off_normal"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ style="@style/HoloButton"
+ android:background="@drawable/browserbarbutton" />
+ </LinearLayout>
+ <LinearLayout
+ android:id="@+id/urlbar_focused"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:layout_weight="1.0"
+ android:orientation="horizontal"
+ android:background="@drawable/text_field_results"
+ android:visibility="gone">
+ <ImageView
+ android:id="@+id/searchicon"
+ android:src="@drawable/ic_search_category_suggest"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ style="@style/HoloButton" />
+ <com.android.browser.UrlInputView
+ android:id="@+id/url_focused"
+ android:layout_width="0dip"
+ android:layout_weight="1.0"
+ android:layout_height="match_parent"
+ android:background="@null"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="@color/black"
+ android:hint="@string/search_hint"
+ android:gravity="center_vertical"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:lines="1"
+ android:scrollHorizontally="true"
+ android:inputType="textUri"
+ android:imeOptions="actionGo" />
+ <ImageView
+ android:id="@+id/clear"
+ android:src="@drawable/ic_clear_search"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ style="@style/HoloButton" />
+ </LinearLayout>
+ <ImageButton
+ android:id="@+id/go"
+ android:src="@drawable/ic_go_normal_white"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:visibility="gone"
+ android:gravity="center_vertical"
+ style="@style/HoloButton"
+ android:background="@drawable/browserbarbutton" />
+ <ImageButton
+ android:id="@+id/search"
+ android:src="@drawable/ic_search_normal"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical"
+ style="@style/HoloButton"
+ android:background="@drawable/browserbarbutton" />
+ <ImageButton
+ android:id="@+id/all_btn"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:scaleType="center"
+ style="@style/HoloButton"
+ android:background="@drawable/browserbarbutton"
+ android:src="@drawable/ic_bookmarks_history_normal" />
+ </LinearLayout>
+ <com.android.browser.PageProgressView
+ android:id="@+id/progress"
+ android:layout_width="match_parent"
+ android:layout_height="22dip"
+ android:background="@null"
+ android:src="@drawable/progress"
+ android:layout_marginTop="-11dip"
+ android:visibility="gone" />
+</LinearLayout>
diff --git a/res/menu-xlarge/browser.xml b/res/menu-xlarge/browser.xml
new file mode 100644
index 0000000..cf29351
--- /dev/null
+++ b/res/menu-xlarge/browser.xml
@@ -0,0 +1,98 @@
+<?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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <group android:id="@+id/MAIN_MENU">
+ <item android:id="@+id/newtab"
+ android:icon="@drawable/ic_menu_new_window"
+ android:title="@string/new_tab"
+ android:showAsAction="always"
+ android:alphabeticShortcut="n" />
+ <item android:id="@+id/incognito_menu_id"
+ android:title="@string/incognito_tab"
+ android:icon="@drawable/ic_menu_incognito_normal" />
+ <item android:id="@+id/find_menu_id"
+ android:title="@*android:string/find_on_page"
+ android:icon="@drawable/ic_menu_findonpage_normal"
+ android:alphabeticShortcut="f" />
+ <item android:id="@+id/share_page_menu_id"
+ android:title="@string/share_page"
+ android:icon="@drawable/ic_menu_share_normal"
+ android:alphabeticShortcut="s" />
+ <item android:id="@+id/page_info_menu_id"
+ android:title="@string/page_info"
+ android:icon="@drawable/ic_menu_pageinfo_normal"
+ android:alphabeticShortcut="g" />
+ <item android:id="@+id/view_downloads_menu_id"
+ android:title="@string/menu_view_download"
+ android:icon="@drawable/ic_menu_downloads_normal"
+ android:alphabeticShortcut="d" />
+ <item android:id="@+id/preferences_menu_id"
+ android:title="@string/menu_preferences"
+ android:icon="@drawable/ic_menu_settings_normal"
+ android:alphabeticShortcut="p" />
+ <item android:id="@+id/save_webarchive_menu_id"
+ android:icon="@drawable/ic_menu_archive_normal"
+ android:title="@string/menu_save_webarchive" />
+ <!-- followings are debug only -->
+ <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"
+ android:alphabeticShortcut=" " />
+ <item android:id="@+id/classic_history_menu_id"
+ android:alphabeticShortcut="h" />
+ <item android:id="@+id/zoom_in_menu_id"
+ android:alphabeticShortcut="i" />
+ <item android:id="@+id/zoom_out_menu_id"
+ android:alphabeticShortcut="o" />
+ <item android:id="@+id/window_one_menu_id"
+ android:alphabeticShortcut="1" />
+ <item android:id="@+id/window_two_menu_id"
+ android:alphabeticShortcut="2" />
+ <item android:id="@+id/window_three_menu_id"
+ android:alphabeticShortcut="3" />
+ <item android:id="@+id/window_four_menu_id"
+ android:alphabeticShortcut="4" />
+ <item android:id="@+id/window_five_menu_id"
+ android:alphabeticShortcut="5" />
+ <item android:id="@+id/window_six_menu_id"
+ android:alphabeticShortcut="6" />
+ <item android:id="@+id/window_seven_menu_id"
+ android:alphabeticShortcut="7" />
+ <item android:id="@+id/window_eight_menu_id"
+ android:alphabeticShortcut="8" />
+ <item android:id="@+id/back_menu_id"
+ android:alphabeticShortcut="j" />
+ <item android:id="@+id/forward_menu_id"
+ android:alphabeticShortcut="k" />
+ <item android:id="@+id/bookmarks_menu_id"
+ android:alphabeticShortcut="b" />
+ <item android:id="@+id/add_bookmark_menu_id"
+ android:alphabeticShortcut="a" />
+ <item android:id="@+id/stop_reload_menu_id"
+ android:alphabeticShortcut="r" />
+ <item android:id="@+id/goto_menu_id"
+ android:alphabeticShortcut="l" />
+ <item android:id="@+id/close_menu_id"
+ android:alphabeticShortcut="w" />
+ </group>
+</menu>
diff --git a/res/menu/bookmarks.xml b/res/menu/bookmark_shortcut.xml
similarity index 63%
copy from res/menu/bookmarks.xml
copy to res/menu/bookmark_shortcut.xml
index a8781c2..67cbddf 100644
--- a/res/menu/bookmarks.xml
+++ b/res/menu/bookmark_shortcut.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
+<!-- Copyright (C) 2010 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,10 +14,12 @@
limitations under the License.
-->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:id="@+id/new_context_menu_id"
- android:icon="@drawable/ic_menu_add_bookmark"
- android:title="@string/bookmark_page" />
- <item android:id="@+id/switch_mode_menu_id"
- />
+<menu
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:id="@+id/add_bookmark_menu_id"
+ android:title="@string/save_to_bookmarks" />
+ <item
+ android:id="@+id/shortcut_to_home_menu_id"
+ android:title="@string/create_shortcut_bookmark" />
</menu>
diff --git a/res/menu/bookmarkscontext.xml b/res/menu/bookmarkscontext.xml
index badbb00..c58d459 100644
--- a/res/menu/bookmarkscontext.xml
+++ b/res/menu/bookmarkscontext.xml
@@ -15,10 +15,6 @@
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <group android:id="@+id/ADD_MENU">
- <item android:id="@+id/new_context_menu_id"
- android:title="@string/save_to_bookmarks"/>
- </group>
<group android:id="@+id/CONTEXT_MENU">
<item android:id="@+id/open_context_menu_id"
android:title="@string/open_bookmark"/>
diff --git a/res/menu/browser.xml b/res/menu/browser.xml
index 4793c21..b5d56c8 100644
--- a/res/menu/browser.xml
+++ b/res/menu/browser.xml
@@ -40,23 +40,28 @@
android:icon="@drawable/ic_menu_add_bookmark"
android:alphabeticShortcut="a" />
<item android:id="@+id/find_menu_id"
- android:title="@string/find_dot"
+ android:title="@*android:string/find_on_page"
+ android:icon="@*android:drawable/ic_menu_find"
android:alphabeticShortcut="f" />
- <item android:id="@+id/select_text_id"
- android:title="@string/select_dot"
- android:alphabeticShortcut="e" />
- <item android:id="@+id/page_info_menu_id"
- android:title="@string/page_info"
- android:alphabeticShortcut="g" />
<item android:id="@+id/share_page_menu_id"
android:title="@string/share_page"
+ android:icon="@drawable/ic_menu_share"
android:alphabeticShortcut="s" />
+ <item android:id="@+id/page_info_menu_id"
+ android:title="@string/page_info"
+ android:icon="@drawable/ic_menu_pageinfo"
+ android:alphabeticShortcut="g" />
<item android:id="@+id/view_downloads_menu_id"
android:title="@string/menu_view_download"
+ android:icon="@drawable/ic_menu_downloads"
android:alphabeticShortcut="d" />
<item android:id="@+id/preferences_menu_id"
android:title="@string/menu_preferences"
+ android:icon="@drawable/ic_menu_settings"
android:alphabeticShortcut="p" />
+ <item android:id="@+id/save_webarchive_menu_id"
+ android:title="@string/menu_save_webarchive"
+ />
<!-- followings are debug only -->
<item android:id="@+id/dump_nav_menu_id"
android:title="@string/dump_nav"
@@ -91,16 +96,10 @@
<item android:id="@+id/window_eight_menu_id"
android:alphabeticShortcut="8" />
<item android:id="@+id/back_menu_id"
- android:title="@string/back"
- android:drawable="@*android:drawable/ic_menu_back"
android:alphabeticShortcut="j" />
<item android:id="@+id/goto_menu_id"
- android:title="@string/goto_dot"
- android:alphabeticShortcut="l"
- android:icon="@android:drawable/ic_menu_search"/>
+ android:alphabeticShortcut="l" />
<item android:id="@+id/close_menu_id"
- android:icon="@drawable/ic_btn_close_panel"
- android:title="@string/tab_picker_remove_tab"
android:alphabeticShortcut="w" />
</group>
<!-- these items are toggled in and out of @+id/stop_reload_menu_id -->
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 82067b5..0920669 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -19,6 +19,7 @@
<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="new_incognito_tab" msgid="5821404839654751753">"Nové anonymní okno"</string>
<string name="active_tabs" msgid="3050623868203544623">"Okna"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Záložky"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"Nejnavštěvovanější"</string>
@@ -32,12 +33,6 @@
<string name="bookmarks_search" msgid="5229596268214362873">"Prohlížeč"</string>
<string name="cancel" msgid="3017274947407233702">"Zrušit"</string>
<string name="ok" msgid="1509280796718850364">"OK"</string>
- <plurals name="matches_found">
- <item quantity="zero" msgid="6242659159545399963">"Žádné shody"</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>
<string name="page_info_view" msgid="5303490449842635158">"Zobrazit informace o stránce"</string>
@@ -67,12 +62,23 @@
<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">"Místo"</string>
- <string name="name" msgid="5990326151488445481">"Jméno"</string>
+ <!-- no translation found for location (3411848697912600125) -->
+ <skip />
+ <!-- no translation found for containing_folder (6771180232953030479) -->
+ <skip />
+ <!-- no translation found for add_new_folder (7027600176450718398) -->
+ <skip />
+ <!-- no translation found for new_folder (7743540149088867917) -->
+ <skip />
+ <!-- no translation found for name (5915607427720935681) -->
+ <skip />
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Přidat záložku"</string>
+ <string name="save_to_bookmarks" msgid="6101482434920313244">"Přidat k záložkám"</string>
+ <!-- no translation found for bookmark_this_page (7530739804320811054) -->
+ <skip />
<string name="edit_bookmark" msgid="5024089053490231905">"Upravit záložku"</string>
- <string name="create_shortcut_bookmark" msgid="9202323987633899835">"Přidat odkaz na plochu"</string>
+ <!-- no translation found for create_shortcut_bookmark (1995095662095484289) -->
+ <skip />
<string name="open_bookmark" msgid="8473581305759935790">"Otevřít"</string>
<string name="remove_bookmark" msgid="8407495852801410891">"Smazat záložku"</string>
<string name="remove_from_bookmarks" msgid="4374080666576982775">"Zrušit přístup k poloze"</string>
@@ -93,7 +99,7 @@
<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="goto_dot" msgid="3895839050522602723">"Přejít"</string>
- <string name="find_dot" msgid="6259312434696611957">"Vyhledat na stránce"</string>
+ <string name="incognito_tab" msgid="5419458065370134289">"Otevřít novou anonymní kartu"</string>
<string name="select_dot" msgid="6299170761900561967">"Vybrat text"</string>
<string name="tab_picker_title" msgid="864478399057782913">"Aktuální okna"</string>
<string name="tab_picker_remove_tab" msgid="630087809802479397">"Zavřít"</string>
@@ -103,6 +109,9 @@
<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="menu_save_webarchive" msgid="3934652434001459581">"Uložit jako webový archiv"</string>
+ <string name="webarchive_saved" msgid="7045250341467345007">"Webový archiv byl uložen."</string>
+ <string name="webarchive_failed" msgid="2880998204746620260">"Uložení webového archivu se nezdařilo."</string>
<string name="contextmenu_openlink" msgid="7237961252214188935">"Otevřít"</string>
<string name="contextmenu_openlink_newwindow" msgid="992765050093960353">"Otevřít v novém okně"</string>
<string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"Přidat odkaz do záložek"</string>
@@ -169,6 +178,10 @@
<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, která zadám do formulářů, pro další použití"</string>
+ <!-- no translation found for pref_autoFill_enabled (5348131327347999291) -->
+ <skip />
+ <!-- no translation found for pref_autoFill_enabled_summary (282122852215557397) -->
+ <skip />
<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>
@@ -208,6 +221,7 @@
<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>
+ <item msgid="2193955365569270096">"Korejština (EUC-KR)"</item>
</string-array>
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Kódování textu"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Problémy s datovým připojením"</string>
@@ -292,4 +306,8 @@
<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="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Nastavení tapety..."</string>
+ <string name="defaultBookmarksUpButton" msgid="2303951020715704735">"Záložky"</string>
+ <!-- no translation found for empty_bookmarks_folder (7843361614634930942) -->
+ <skip />
+ <string name="rlz_access_point" msgid="7165847807377650632">"Y1"</string>
</resources>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 48b7dae..3605c51 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -19,6 +19,7 @@
<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="new_incognito_tab" msgid="5821404839654751753">"Nyt inkognitovindue"</string>
<string name="active_tabs" msgid="3050623868203544623">"Vinduer"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Bogmærker"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"Mest besøgte"</string>
@@ -32,12 +33,6 @@
<string name="bookmarks_search" msgid="5229596268214362873">"Browser"</string>
<string name="cancel" msgid="3017274947407233702">"Annuller"</string>
<string name="ok" msgid="1509280796718850364">"OK"</string>
- <plurals name="matches_found">
- <item quantity="zero" msgid="6242659159545399963">"Der er ingen matches"</item>
- <item quantity="one" msgid="4352019729062956802">"1 match"</item>
- <item quantity="few" msgid="5544267486978946555">"<xliff:g id="NUMBER">%d</xliff:g> matches"</item>
- <item quantity="other" msgid="6616125067364315405">"<xliff:g id="NUMBER">%d</xliff:g> matches"</item>
- </plurals>
<string name="title_bar_loading" msgid="7438217780834640678">"Indlæser ..."</string>
<string name="page_info" msgid="4048529256302257195">"Sideoplysninger"</string>
<string name="page_info_view" msgid="5303490449842635158">"Vis sideoplysninger"</string>
@@ -67,12 +62,23 @@
<string name="forward" msgid="4288210890526641577">"Fremad"</string>
<string name="save" msgid="5922311934992468496">"OK"</string>
<string name="do_not_save" msgid="6777633870113477714">"Annuller"</string>
- <string name="location" msgid="969988560160364559">"Placering"</string>
- <string name="name" msgid="5990326151488445481">"Navn"</string>
+ <!-- no translation found for location (3411848697912600125) -->
+ <skip />
+ <!-- no translation found for containing_folder (6771180232953030479) -->
+ <skip />
+ <!-- no translation found for add_new_folder (7027600176450718398) -->
+ <skip />
+ <!-- no translation found for new_folder (7743540149088867917) -->
+ <skip />
+ <!-- no translation found for name (5915607427720935681) -->
+ <skip />
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Tilføj bogmærke"</string>
+ <string name="save_to_bookmarks" msgid="6101482434920313244">"Føj til bogmærker"</string>
+ <!-- no translation found for bookmark_this_page (7530739804320811054) -->
+ <skip />
<string name="edit_bookmark" msgid="5024089053490231905">"Rediger bogmærke"</string>
- <string name="create_shortcut_bookmark" msgid="9202323987633899835">"Føj genvej til Start"</string>
+ <!-- no translation found for create_shortcut_bookmark (1995095662095484289) -->
+ <skip />
<string name="open_bookmark" msgid="8473581305759935790">"Åbn"</string>
<string name="remove_bookmark" msgid="8407495852801410891">"Slet bogmærke"</string>
<string name="remove_from_bookmarks" msgid="4374080666576982775">"Fjern fra bogmærker"</string>
@@ -93,7 +99,7 @@
<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="goto_dot" msgid="3895839050522602723">"Gå"</string>
- <string name="find_dot" msgid="6259312434696611957">"Find på side"</string>
+ <string name="incognito_tab" msgid="5419458065370134289">"Åbn ny inkognitofane"</string>
<string name="select_dot" msgid="6299170761900561967">"Vælg tekst"</string>
<string name="tab_picker_title" msgid="864478399057782913">"Aktuelle vinduer"</string>
<string name="tab_picker_remove_tab" msgid="630087809802479397">"Luk"</string>
@@ -103,6 +109,9 @@
<string name="menu_view_download" msgid="2124570321712995120">"Downloads"</string>
<string name="copy_page_url" msgid="7635062169011319208">"Kopier sidens webadresse"</string>
<string name="share_page" msgid="593756995297268343">"Del side"</string>
+ <string name="menu_save_webarchive" msgid="3934652434001459581">"Gem som webarkiv"</string>
+ <string name="webarchive_saved" msgid="7045250341467345007">"Webarkivet blev gemt."</string>
+ <string name="webarchive_failed" msgid="2880998204746620260">"Webarkivet blev ikke gemt."</string>
<string name="contextmenu_openlink" msgid="7237961252214188935">"Åbn"</string>
<string name="contextmenu_openlink_newwindow" msgid="992765050093960353">"Åbn i et nyt vindue"</string>
<string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"Opret et bogmærke for linket"</string>
@@ -169,6 +178,10 @@
<string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"Gem brugernavne og adgangskoder til websteder"</string>
<string name="pref_security_save_form_data" msgid="1213669802810198893">"Husk formulardata"</string>
<string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"Husk data, jeg indtaster i formularer, til senere brug"</string>
+ <!-- no translation found for pref_autoFill_enabled (5348131327347999291) -->
+ <skip />
+ <!-- no translation found for pref_autoFill_enabled_summary (282122852215557397) -->
+ <skip />
<string name="pref_security_show_security_warning" msgid="8901135676266754559">"Vis sikkerhedsadvarsler"</string>
<string name="pref_security_show_security_warning_summary" msgid="8968906112720511704">"Vis en advarsel, hvis der er problemer med sikkerheden på et websted"</string>
<string name="pref_security_accept_cookies" msgid="3201367661925047989">"Accepter cookies"</string>
@@ -208,6 +221,7 @@
<item msgid="891615911084608570">"Japansk (ISO-2022-JP)"</item>
<item msgid="5589150448475151241">"Japansk (SHIFT_JIS)"</item>
<item msgid="7356792686950371843">"Japansk (EUC-JP)"</item>
+ <item msgid="2193955365569270096">"Koreansk (EUC-KR)"</item>
</string-array>
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Tekstkodning"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Dataforbindelsesproblem"</string>
@@ -292,4 +306,8 @@
<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="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Indstiller tapet ..."</string>
+ <string name="defaultBookmarksUpButton" msgid="2303951020715704735">"Bogmærker"</string>
+ <!-- no translation found for empty_bookmarks_folder (7843361614634930942) -->
+ <skip />
+ <string name="rlz_access_point" msgid="7165847807377650632">"Y1"</string>
</resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 335357c..8a53c47 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -19,6 +19,7 @@
<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="new_incognito_tab" msgid="5821404839654751753">"Neues Inkognito-Fenster"</string>
<string name="active_tabs" msgid="3050623868203544623">"Fenster"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Lesezeichen"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"Meistbesucht"</string>
@@ -32,12 +33,6 @@
<string name="bookmarks_search" msgid="5229596268214362873">"Browser"</string>
<string name="cancel" msgid="3017274947407233702">"Abbrechen"</string>
<string name="ok" msgid="1509280796718850364">"OK"</string>
- <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> Treffer"</item>
- <item quantity="other" msgid="6616125067364315405">"<xliff:g id="NUMBER">%d</xliff:g> Treffer"</item>
- </plurals>
<string name="title_bar_loading" msgid="7438217780834640678">"Wird geladen..."</string>
<string name="page_info" msgid="4048529256302257195">"Seiteninfo"</string>
<string name="page_info_view" msgid="5303490449842635158">"Seiteninfo anzeigen"</string>
@@ -67,12 +62,23 @@
<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">"URL"</string>
- <string name="name" msgid="5990326151488445481">"Name"</string>
+ <!-- no translation found for location (3411848697912600125) -->
+ <skip />
+ <!-- no translation found for containing_folder (6771180232953030479) -->
+ <skip />
+ <!-- no translation found for add_new_folder (7027600176450718398) -->
+ <skip />
+ <!-- no translation found for new_folder (7743540149088867917) -->
+ <skip />
+ <!-- no translation found for name (5915607427720935681) -->
+ <skip />
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Lesezeichen hinzufügen"</string>
+ <string name="save_to_bookmarks" msgid="6101482434920313244">"Zu Lesezeichen hinzufügen"</string>
+ <!-- no translation found for bookmark_this_page (7530739804320811054) -->
+ <skip />
<string name="edit_bookmark" msgid="5024089053490231905">"Lesezeichen bearbeiten"</string>
- <string name="create_shortcut_bookmark" msgid="9202323987633899835">"Verknüpfung auf dem Startbildschirm erstellen"</string>
+ <!-- no translation found for create_shortcut_bookmark (1995095662095484289) -->
+ <skip />
<string name="open_bookmark" msgid="8473581305759935790">"Öffnen"</string>
<string name="remove_bookmark" msgid="8407495852801410891">"Lesezeichen löschen"</string>
<string name="remove_from_bookmarks" msgid="4374080666576982775">"Aus Lesezeichen entfernen"</string>
@@ -93,7 +99,7 @@
<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="goto_dot" msgid="3895839050522602723">"Los"</string>
- <string name="find_dot" msgid="6259312434696611957">"Auf Seite suchen"</string>
+ <string name="incognito_tab" msgid="5419458065370134289">"Neuen Inkognito-Tab öffnen"</string>
<string name="select_dot" msgid="6299170761900561967">"Text auswählen"</string>
<string name="tab_picker_title" msgid="864478399057782913">"Aktuelle Fenster"</string>
<string name="tab_picker_remove_tab" msgid="630087809802479397">"Schließen"</string>
@@ -103,6 +109,9 @@
<string name="menu_view_download" msgid="2124570321712995120">"Downloads"</string>
<string name="copy_page_url" msgid="7635062169011319208">"Seiten-URL kopieren"</string>
<string name="share_page" msgid="593756995297268343">"Seitenlink weiterleiten"</string>
+ <string name="menu_save_webarchive" msgid="3934652434001459581">"Als Webarchiv speichern"</string>
+ <string name="webarchive_saved" msgid="7045250341467345007">"Webarchiv gespeichert."</string>
+ <string name="webarchive_failed" msgid="2880998204746620260">"Das Webarchiv wurde nicht gespeichert."</string>
<string name="contextmenu_openlink" msgid="7237961252214188935">"Öffnen"</string>
<string name="contextmenu_openlink_newwindow" msgid="992765050093960353">"In neuem Fenster öffnen"</string>
<string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"Link zu Lesezeichen hinzufügen"</string>
@@ -169,6 +178,10 @@
<string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"Nutzernamen und Passwörter für Websites speichern"</string>
<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>
+ <!-- no translation found for pref_autoFill_enabled (5348131327347999291) -->
+ <skip />
+ <!-- no translation found for pref_autoFill_enabled_summary (282122852215557397) -->
+ <skip />
<string name="pref_security_show_security_warning" msgid="8901135676266754559">"Sicherheitswarnungen"</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>
@@ -208,6 +221,7 @@
<item msgid="891615911084608570">"Japanisch (ISO-2022-JP)"</item>
<item msgid="5589150448475151241">"Japanisch (SHIFT_JIS)"</item>
<item msgid="7356792686950371843">"Japanisch (EUC-JP)"</item>
+ <item msgid="2193955365569270096">"Koreanisch (EUC-KR)"</item>
</string-array>
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Textcodierung"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Datenverbindungsproblem"</string>
@@ -292,4 +306,8 @@
<string name="website_settings_clear_all_dialog_ok_button" msgid="6401582240627669431">"Alle Daten löschen"</string>
<string name="website_settings_clear_all_dialog_cancel_button" msgid="1896757051856611674">"Abbrechen"</string>
<string name="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Hintergrund wird eingestellt..."</string>
+ <string name="defaultBookmarksUpButton" msgid="2303951020715704735">"Lesezeichen"</string>
+ <!-- no translation found for empty_bookmarks_folder (7843361614634930942) -->
+ <skip />
+ <string name="rlz_access_point" msgid="7165847807377650632">"Y1"</string>
</resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 170f711..d592d71 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -19,6 +19,7 @@
<string name="application_name" msgid="1935869255545976415">"Internet"</string>
<string name="choose_upload" msgid="3649366287575002063">"Επιλογή αρχείου για μεταφόρτωση"</string>
<string name="new_tab" msgid="4505722538297295141">"Νέο παράθυρο"</string>
+ <string name="new_incognito_tab" msgid="5821404839654751753">"Νέο παράθυρο για ανώνυμη περιήγηση"</string>
<string name="active_tabs" msgid="3050623868203544623">"Παράθυρα"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Σελιδοδείκτες"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"Οι πιο δημοφιλείς"</string>
@@ -32,12 +33,6 @@
<string name="bookmarks_search" msgid="5229596268214362873">"Internet"</string>
<string name="cancel" msgid="3017274947407233702">"Ακύρωση"</string>
<string name="ok" msgid="1509280796718850364">"OK"</string>
- <plurals name="matches_found">
- <item quantity="zero" msgid="6242659159545399963">"Δεν υπάρχουν αποτελέσματα"</item>
- <item quantity="one" msgid="4352019729062956802">"1 αποτέλεσμα"</item>
- <item quantity="few" msgid="5544267486978946555">"<xliff:g id="NUMBER">%d</xliff:g> αποτελέσματα"</item>
- <item quantity="other" msgid="6616125067364315405">"<xliff:g id="NUMBER">%d</xliff:g> αποτελέσματα"</item>
- </plurals>
<string name="title_bar_loading" msgid="7438217780834640678">"Φόρτωση..."</string>
<string name="page_info" msgid="4048529256302257195">"Πληροφορίες σελίδας"</string>
<string name="page_info_view" msgid="5303490449842635158">"Προβολή πληροφοριών σελίδας"</string>
@@ -67,12 +62,23 @@
<string name="forward" msgid="4288210890526641577">"Εμπρός"</string>
<string name="save" msgid="5922311934992468496">"OK"</string>
<string name="do_not_save" msgid="6777633870113477714">"Ακύρωση"</string>
- <string name="location" msgid="969988560160364559">"Τοποθεσία"</string>
- <string name="name" msgid="5990326151488445481">"Όνομα"</string>
+ <!-- no translation found for location (3411848697912600125) -->
+ <skip />
+ <!-- no translation found for containing_folder (6771180232953030479) -->
+ <skip />
+ <!-- no translation found for add_new_folder (7027600176450718398) -->
+ <skip />
+ <!-- no translation found for new_folder (7743540149088867917) -->
+ <skip />
+ <!-- no translation found for name (5915607427720935681) -->
+ <skip />
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Προσθήκη σελιδοδείκτη"</string>
+ <string name="save_to_bookmarks" msgid="6101482434920313244">"Προσθήκη στους σελιδοδείκτες"</string>
+ <!-- no translation found for bookmark_this_page (7530739804320811054) -->
+ <skip />
<string name="edit_bookmark" msgid="5024089053490231905">"Επεξεργασία σελιδοδείκτη"</string>
- <string name="create_shortcut_bookmark" msgid="9202323987633899835">"Προσθήκη συντόμευσης στην αρχική οθόνη"</string>
+ <!-- no translation found for create_shortcut_bookmark (1995095662095484289) -->
+ <skip />
<string name="open_bookmark" msgid="8473581305759935790">"Άνοιγμα"</string>
<string name="remove_bookmark" msgid="8407495852801410891">"Διαγραφή σελιδοδείκτη"</string>
<string name="remove_from_bookmarks" msgid="4374080666576982775">"Κατάργηση από τους σελιδοδείκτες"</string>
@@ -93,7 +99,7 @@
<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="goto_dot" msgid="3895839050522602723">"Μετάβαση"</string>
- <string name="find_dot" msgid="6259312434696611957">"Εύρεση στη σελίδα"</string>
+ <string name="incognito_tab" msgid="5419458065370134289">"Άνοιγμα νέας καρτέλας ανώνυμης περιήγησης"</string>
<string name="select_dot" msgid="6299170761900561967">"Επιλογή κειμένου"</string>
<string name="tab_picker_title" msgid="864478399057782913">"Τρέχοντα παράθυρα"</string>
<string name="tab_picker_remove_tab" msgid="630087809802479397">"Κλείσιμο"</string>
@@ -103,6 +109,9 @@
<string name="menu_view_download" msgid="2124570321712995120">"Λήψεις"</string>
<string name="copy_page_url" msgid="7635062169011319208">"Αντιγραφή διεύθυνσης url της σελίδας"</string>
<string name="share_page" msgid="593756995297268343">"Κοινή χρήση σελίδας"</string>
+ <string name="menu_save_webarchive" msgid="3934652434001459581">"Αποθήκευση ως αρχείου ιστού"</string>
+ <string name="webarchive_saved" msgid="7045250341467345007">"Το αρχείο ιστού αποθηκεύθηκε."</string>
+ <string name="webarchive_failed" msgid="2880998204746620260">"Η αποθήκευση του αρχείου ιστού απέτυχε."</string>
<string name="contextmenu_openlink" msgid="7237961252214188935">"Άνοιγμα"</string>
<string name="contextmenu_openlink_newwindow" msgid="992765050093960353">"Άνοιγμα σε νέο παράθυρο"</string>
<string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"Πρόσθεση συνδέσμου στους σελιδοδείκτες"</string>
@@ -169,6 +178,10 @@
<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>
+ <!-- no translation found for pref_autoFill_enabled (5348131327347999291) -->
+ <skip />
+ <!-- no translation found for pref_autoFill_enabled_summary (282122852215557397) -->
+ <skip />
<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>
@@ -208,6 +221,7 @@
<item msgid="891615911084608570">"Ιαπωνικά (ISO-2022-JP)"</item>
<item msgid="5589150448475151241">"Ιαπωνικά (SHIFT_JIS)"</item>
<item msgid="7356792686950371843">"Ιαπωνικά (EUC-JP)"</item>
+ <item msgid="2193955365569270096">"Κορεατικά (EUC-KR)"</item>
</string-array>
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Κωδικοποίηση κειμένου"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Πρόβλημα σύνδεσης δεδομένων"</string>
@@ -292,4 +306,8 @@
<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="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Ρύθμιση ταπετσαρίας..."</string>
+ <string name="defaultBookmarksUpButton" msgid="2303951020715704735">"Σελιδοδείκτες"</string>
+ <!-- no translation found for empty_bookmarks_folder (7843361614634930942) -->
+ <skip />
+ <string name="rlz_access_point" msgid="7165847807377650632">"Y1"</string>
</resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index fd76fd6..3444c1c 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -19,10 +19,11 @@
<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="new_incognito_tab" msgid="5821404839654751753">"Nueva ventana de incógnito"</string>
<string name="active_tabs" msgid="3050623868203544623">"Windows"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Marcadores"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"Más visitados"</string>
- <string name="tab_history" msgid="1979267558744613746">"Historial"</string>
+ <string name="tab_history" msgid="1979267558744613746">"Historial "</string>
<string name="added_to_bookmarks" msgid="1020224130695956728">"Agregado a marcadores"</string>
<string name="removed_from_bookmarks" msgid="6063705902028438800">"Suprimido de los marcadores"</string>
<string name="sign_in_to" msgid="5939425800148759165">"Iniciar sesión en <xliff:g id="HOSTNAME">%s1</xliff:g> \"<xliff:g id="REALM">%s2</xliff:g>\""</string>
@@ -32,12 +33,6 @@
<string name="bookmarks_search" msgid="5229596268214362873">"Navegador"</string>
<string name="cancel" msgid="3017274947407233702">"Cancelar"</string>
<string name="ok" msgid="1509280796718850364">"Aceptar"</string>
- <plurals name="matches_found">
- <item quantity="zero" msgid="6242659159545399963">"Sin coincidencias"</item>
- <item quantity="one" msgid="4352019729062956802">"1 coincidencia"</item>
- <item quantity="few" msgid="5544267486978946555">"<xliff:g id="NUMBER">%d</xliff:g> coincide"</item>
- <item quantity="other" msgid="6616125067364315405">"<xliff:g id="NUMBER">%d</xliff:g> coincide"</item>
- </plurals>
<string name="title_bar_loading" msgid="7438217780834640678">"Cargando…"</string>
<string name="page_info" msgid="4048529256302257195">"Información de la página"</string>
<string name="page_info_view" msgid="5303490449842635158">"Ver información de la página"</string>
@@ -67,12 +62,23 @@
<string name="forward" msgid="4288210890526641577">"Reenviar"</string>
<string name="save" msgid="5922311934992468496">"Aceptar"</string>
<string name="do_not_save" msgid="6777633870113477714">"Cancelar"</string>
- <string name="location" msgid="969988560160364559">"Ubicación"</string>
- <string name="name" msgid="5990326151488445481">"Nombre"</string>
+ <!-- no translation found for location (3411848697912600125) -->
+ <skip />
+ <!-- no translation found for containing_folder (6771180232953030479) -->
+ <skip />
+ <!-- no translation found for add_new_folder (7027600176450718398) -->
+ <skip />
+ <!-- no translation found for new_folder (7743540149088867917) -->
+ <skip />
+ <!-- no translation found for name (5915607427720935681) -->
+ <skip />
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Agregar marcador"</string>
+ <string name="save_to_bookmarks" msgid="6101482434920313244">"Agregar a Favoritos"</string>
+ <!-- no translation found for bookmark_this_page (7530739804320811054) -->
+ <skip />
<string name="edit_bookmark" msgid="5024089053490231905">"Editar marcador"</string>
- <string name="create_shortcut_bookmark" msgid="9202323987633899835">"Agregar acceso directo a la página de inicio"</string>
+ <!-- no translation found for create_shortcut_bookmark (1995095662095484289) -->
+ <skip />
<string name="open_bookmark" msgid="8473581305759935790">"Abrir"</string>
<string name="remove_bookmark" msgid="8407495852801410891">"Eliminar marcador"</string>
<string name="remove_from_bookmarks" msgid="4374080666576982775">"Eliminar de marcadores"</string>
@@ -93,7 +99,7 @@
<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="goto_dot" msgid="3895839050522602723">"Ir"</string>
- <string name="find_dot" msgid="6259312434696611957">"Buscar en la página"</string>
+ <string name="incognito_tab" msgid="5419458065370134289">"Abrir nueva pestaña de incógnito"</string>
<string name="select_dot" msgid="6299170761900561967">"Seleccionar texto"</string>
<string name="tab_picker_title" msgid="864478399057782913">"Ventana actual"</string>
<string name="tab_picker_remove_tab" msgid="630087809802479397">"Cerrar"</string>
@@ -103,6 +109,9 @@
<string name="menu_view_download" msgid="2124570321712995120">"Descargas"</string>
<string name="copy_page_url" msgid="7635062169011319208">"Copiar la url de la página"</string>
<string name="share_page" msgid="593756995297268343">"Compartir página"</string>
+ <string name="menu_save_webarchive" msgid="3934652434001459581">"Guardar como Archivo web"</string>
+ <string name="webarchive_saved" msgid="7045250341467345007">"Archivo web guardado."</string>
+ <string name="webarchive_failed" msgid="2880998204746620260">"Error al guardar el archivo web."</string>
<string name="contextmenu_openlink" msgid="7237961252214188935">"Abrir"</string>
<string name="contextmenu_openlink_newwindow" msgid="992765050093960353">"Abrir en una ventana nueva"</string>
<string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"Enlace del marcador"</string>
@@ -169,6 +178,10 @@
<string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"Guardar los nombres de usuario y las contraseñas de los sitios web"</string>
<string name="pref_security_save_form_data" msgid="1213669802810198893">"Recordar datos del form."</string>
<string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"Recordar los datos ingresados en los formularios para uso futuro"</string>
+ <!-- no translation found for pref_autoFill_enabled (5348131327347999291) -->
+ <skip />
+ <!-- no translation found for pref_autoFill_enabled_summary (282122852215557397) -->
+ <skip />
<string name="pref_security_show_security_warning" msgid="8901135676266754559">"Mostrar advert. de seguridad"</string>
<string name="pref_security_show_security_warning_summary" msgid="8968906112720511704">"Mostrar una advertencia si hay un problema con la seguridad de un sitio"</string>
<string name="pref_security_accept_cookies" msgid="3201367661925047989">"Aceptar cookies"</string>
@@ -208,6 +221,7 @@
<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>
+ <item msgid="2193955365569270096">"Coreano (EUC-KR)"</item>
</string-array>
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Codificación de texto"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Problema de conectividad de datos"</string>
@@ -228,17 +242,17 @@
<string name="popup_window_attempt" msgid="2673111696288657989">"Este sitio está intentando abrir una ventana emergente."</string>
<string name="allow" msgid="1157313689171991335">"Permitir"</string>
<string name="block" msgid="9172175889884707800">"Bloquear"</string>
- <string name="too_many_windows_dialog_title" msgid="5175503564948906442">"Se alcanzó el límite de la ventana"</string>
+ <string name="too_many_windows_dialog_title" msgid="5175503564948906442">"Se alcanzó el límite de la ventana "</string>
<string name="too_many_windows_dialog_message" msgid="1398571800233959583">"No se ha podido abrir una ventana nueva porque ya has abierto el máximo permitido."</string>
<string name="too_many_subwindows_dialog_title" msgid="3805453941587725944">"Ventana emergente ya abierta"</string>
<string name="too_many_subwindows_dialog_message" msgid="5827289829907966657">"No es posible abrir una ventana emergente nueva porque sólo puede abrirse una por vez."</string>
<string name="download_title" msgid="2122874021047565594">"Historial de descarga"</string>
<string name="download_unknown_filename" msgid="4013465542563652175">"<Desconocido>"</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_clear" msgid="6264454531553418124">"Borrar de la lista\n "</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_cancel_all" msgid="2136550823151999166">"Cancelar todas las descargas\n "</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_delete_file" msgid="5330036497843073249">"El archivo se eliminará"</string>
@@ -292,4 +306,8 @@
<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="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Estableciendo fondo de pantalla..."</string>
+ <string name="defaultBookmarksUpButton" msgid="2303951020715704735">"Marcadores"</string>
+ <!-- no translation found for empty_bookmarks_folder (7843361614634930942) -->
+ <skip />
+ <string name="rlz_access_point" msgid="7165847807377650632">"Y1"</string>
</resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 9bd6e72..b0d9e28 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -19,6 +19,7 @@
<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="new_incognito_tab" msgid="5821404839654751753">"Nueva ventana de incógnito"</string>
<string name="active_tabs" msgid="3050623868203544623">"Ventanas"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Marcadores"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"Más visitados"</string>
@@ -32,12 +33,6 @@
<string name="bookmarks_search" msgid="5229596268214362873">"Navegador"</string>
<string name="cancel" msgid="3017274947407233702">"Cancelar"</string>
<string name="ok" msgid="1509280796718850364">"Aceptar"</string>
- <plurals name="matches_found">
- <item quantity="zero" msgid="6242659159545399963">"No hay coincidencias"</item>
- <item quantity="one" msgid="4352019729062956802">"Una coincidencia"</item>
- <item quantity="few" msgid="5544267486978946555">"<xliff:g id="NUMBER">%d</xliff:g> coincidencias"</item>
- <item quantity="other" msgid="6616125067364315405">"<xliff:g id="NUMBER">%d</xliff:g> coincidencias"</item>
- </plurals>
<string name="title_bar_loading" msgid="7438217780834640678">"Cargando..."</string>
<string name="page_info" msgid="4048529256302257195">"Información de página"</string>
<string name="page_info_view" msgid="5303490449842635158">"Ver información de página"</string>
@@ -67,12 +62,23 @@
<string name="forward" msgid="4288210890526641577">"Siguiente"</string>
<string name="save" msgid="5922311934992468496">"Aceptar"</string>
<string name="do_not_save" msgid="6777633870113477714">"Cancelar"</string>
- <string name="location" msgid="969988560160364559">"Ubicación"</string>
- <string name="name" msgid="5990326151488445481">"Nombre"</string>
+ <!-- no translation found for location (3411848697912600125) -->
+ <skip />
+ <!-- no translation found for containing_folder (6771180232953030479) -->
+ <skip />
+ <!-- no translation found for add_new_folder (7027600176450718398) -->
+ <skip />
+ <!-- no translation found for new_folder (7743540149088867917) -->
+ <skip />
+ <!-- no translation found for name (5915607427720935681) -->
+ <skip />
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Añadir marcador"</string>
+ <string name="save_to_bookmarks" msgid="6101482434920313244">"Añadir a marcadores"</string>
+ <!-- no translation found for bookmark_this_page (7530739804320811054) -->
+ <skip />
<string name="edit_bookmark" msgid="5024089053490231905">"Editar marcador"</string>
- <string name="create_shortcut_bookmark" msgid="9202323987633899835">"Añadir acceso directo al escritorio"</string>
+ <!-- no translation found for create_shortcut_bookmark (1995095662095484289) -->
+ <skip />
<string name="open_bookmark" msgid="8473581305759935790">"Abrir"</string>
<string name="remove_bookmark" msgid="8407495852801410891">"Eliminar marcador"</string>
<string name="remove_from_bookmarks" msgid="4374080666576982775">"Eliminar de marcadores"</string>
@@ -93,7 +99,7 @@
<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="goto_dot" msgid="3895839050522602723">"Ir"</string>
- <string name="find_dot" msgid="6259312434696611957">"Buscar en la página"</string>
+ <string name="incognito_tab" msgid="5419458065370134289">"Abrir nueva pestaña de incógnito"</string>
<string name="select_dot" msgid="6299170761900561967">"Seleccionar texto"</string>
<string name="tab_picker_title" msgid="864478399057782913">"Ventanas actuales"</string>
<string name="tab_picker_remove_tab" msgid="630087809802479397">"Cerrar"</string>
@@ -103,6 +109,9 @@
<string name="menu_view_download" msgid="2124570321712995120">"Descargas"</string>
<string name="copy_page_url" msgid="7635062169011319208">"Copiar URL de página"</string>
<string name="share_page" msgid="593756995297268343">"Compartir página"</string>
+ <string name="menu_save_webarchive" msgid="3934652434001459581">"Guardar como archivo web"</string>
+ <string name="webarchive_saved" msgid="7045250341467345007">"Archivo web guardado"</string>
+ <string name="webarchive_failed" msgid="2880998204746620260">"Error al guardar archivo web"</string>
<string name="contextmenu_openlink" msgid="7237961252214188935">"Abrir"</string>
<string name="contextmenu_openlink_newwindow" msgid="992765050093960353">"Abrir en ventana nueva"</string>
<string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"Marcar enlace"</string>
@@ -169,6 +178,10 @@
<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>
<string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"Recordar datos introducidos en formularios"</string>
+ <!-- no translation found for pref_autoFill_enabled (5348131327347999291) -->
+ <skip />
+ <!-- no translation found for pref_autoFill_enabled_summary (282122852215557397) -->
+ <skip />
<string name="pref_security_show_security_warning" msgid="8901135676266754559">"Mostrar advertencias"</string>
<string name="pref_security_show_security_warning_summary" msgid="8968906112720511704">"Mostrar advertencia si hay algún problema con la seguridad del sitio"</string>
<string name="pref_security_accept_cookies" msgid="3201367661925047989">"Aceptar cookies"</string>
@@ -208,6 +221,7 @@
<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>
+ <item msgid="2193955365569270096">"Coreano (EUC-KR)"</item>
</string-array>
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Codificación de texto"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Problema de conectividad de datos"</string>
@@ -292,4 +306,8 @@
<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="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Estableciendo fondo de pantalla..."</string>
+ <string name="defaultBookmarksUpButton" msgid="2303951020715704735">"Marcadores"</string>
+ <!-- no translation found for empty_bookmarks_folder (7843361614634930942) -->
+ <skip />
+ <string name="rlz_access_point" msgid="7165847807377650632">"Y1"</string>
</resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 2375c11..b78ffc2 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -19,6 +19,7 @@
<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="new_incognito_tab" msgid="5821404839654751753">"Fenêtre de navigation privée"</string>
<string name="active_tabs" msgid="3050623868203544623">"Fenêtres"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Favoris"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"Les + visités"</string>
@@ -32,12 +33,6 @@
<string name="bookmarks_search" msgid="5229596268214362873">"Navigateur"</string>
<string name="cancel" msgid="3017274947407233702">"Annuler"</string>
<string name="ok" msgid="1509280796718850364">"OK"</string>
- <plurals name="matches_found">
- <item quantity="zero" msgid="6242659159545399963">"Aucune correspondance"</item>
- <item quantity="one" msgid="4352019729062956802">"1 correspondance"</item>
- <item quantity="few" msgid="5544267486978946555">"<xliff:g id="NUMBER">%d</xliff:g> correspondances"</item>
- <item quantity="other" msgid="6616125067364315405">"<xliff:g id="NUMBER">%d</xliff:g> correspondances"</item>
- </plurals>
<string name="title_bar_loading" msgid="7438217780834640678">"Chargement…"</string>
<string name="page_info" msgid="4048529256302257195">"Infos sur la page"</string>
<string name="page_info_view" msgid="5303490449842635158">"Afficher les infos sur la page"</string>
@@ -67,12 +62,23 @@
<string name="forward" msgid="4288210890526641577">"Suivant"</string>
<string name="save" msgid="5922311934992468496">"OK"</string>
<string name="do_not_save" msgid="6777633870113477714">"Annuler"</string>
- <string name="location" msgid="969988560160364559">"Emplacement"</string>
- <string name="name" msgid="5990326151488445481">"Nom"</string>
+ <!-- no translation found for location (3411848697912600125) -->
+ <skip />
+ <!-- no translation found for containing_folder (6771180232953030479) -->
+ <skip />
+ <!-- no translation found for add_new_folder (7027600176450718398) -->
+ <skip />
+ <!-- no translation found for new_folder (7743540149088867917) -->
+ <skip />
+ <!-- no translation found for name (5915607427720935681) -->
+ <skip />
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Ajouter un favori"</string>
+ <string name="save_to_bookmarks" msgid="6101482434920313244">"Ajouter aux favoris"</string>
+ <!-- no translation found for bookmark_this_page (7530739804320811054) -->
+ <skip />
<string name="edit_bookmark" msgid="5024089053490231905">"Modifier le favori"</string>
- <string name="create_shortcut_bookmark" msgid="9202323987633899835">"Raccourci (page d\'accueil)"</string>
+ <!-- no translation found for create_shortcut_bookmark (1995095662095484289) -->
+ <skip />
<string name="open_bookmark" msgid="8473581305759935790">"Ouverture"</string>
<string name="remove_bookmark" msgid="8407495852801410891">"Supprimer le favori"</string>
<string name="remove_from_bookmarks" msgid="4374080666576982775">"Supprimer des favoris"</string>
@@ -93,7 +99,7 @@
<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">"Nouvelle fenêtre"</string>
<string name="goto_dot" msgid="3895839050522602723">"OK"</string>
- <string name="find_dot" msgid="6259312434696611957">"Rechercher sur la page"</string>
+ <string name="incognito_tab" msgid="5419458065370134289">"Ouvrir un onglet de navigation privée"</string>
<string name="select_dot" msgid="6299170761900561967">"Sélectionner le texte"</string>
<string name="tab_picker_title" msgid="864478399057782913">"Fenêtres actuelles"</string>
<string name="tab_picker_remove_tab" msgid="630087809802479397">"Fermer"</string>
@@ -103,6 +109,9 @@
<string name="menu_view_download" msgid="2124570321712995120">"Téléchargements"</string>
<string name="copy_page_url" msgid="7635062169011319208">"Copier l\'URL de la page"</string>
<string name="share_page" msgid="593756995297268343">"Partager la page"</string>
+ <string name="menu_save_webarchive" msgid="3934652434001459581">"Enregistrer comme archive Web"</string>
+ <string name="webarchive_saved" msgid="7045250341467345007">"Archive Web enregistrée"</string>
+ <string name="webarchive_failed" msgid="2880998204746620260">"Échec de l\'enregistrement de l\'archive Web"</string>
<string name="contextmenu_openlink" msgid="7237961252214188935">"Ouvrir"</string>
<string name="contextmenu_openlink_newwindow" msgid="992765050093960353">"Nouvelle fenêtre"</string>
<string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"Lien du favori"</string>
@@ -169,6 +178,10 @@
<string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"Enregistrer les noms d\'utilisateur et les mots de passe pour les sites Web"</string>
<string name="pref_security_save_form_data" msgid="1213669802810198893">"Données de formulaires"</string>
<string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"Mémoriser les données saisies dans les formulaires pour les réutiliser"</string>
+ <!-- no translation found for pref_autoFill_enabled (5348131327347999291) -->
+ <skip />
+ <!-- no translation found for pref_autoFill_enabled_summary (282122852215557397) -->
+ <skip />
<string name="pref_security_show_security_warning" msgid="8901135676266754559">"Avertiss. de sécurité"</string>
<string name="pref_security_show_security_warning_summary" msgid="8968906112720511704">"Afficher un avertissement en cas de problème de sécurité d\'un site"</string>
<string name="pref_security_accept_cookies" msgid="3201367661925047989">"Accepter les cookies"</string>
@@ -208,6 +221,7 @@
<item msgid="891615911084608570">"Japonais (ISO-2022-JP)"</item>
<item msgid="5589150448475151241">"Japonais (SHIFT_JIS)"</item>
<item msgid="7356792686950371843">"Japonais (EUC-JP)"</item>
+ <item msgid="2193955365569270096">"Coréen (EUC-KR)"</item>
</string-array>
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Codage du texte"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Problème de connectivité des données"</string>
@@ -292,4 +306,8 @@
<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="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Définition du fond d\'écran..."</string>
+ <string name="defaultBookmarksUpButton" msgid="2303951020715704735">"Favoris"</string>
+ <!-- no translation found for empty_bookmarks_folder (7843361614634930942) -->
+ <skip />
+ <string name="rlz_access_point" msgid="7165847807377650632">"Y1"</string>
</resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index aeed32d..717b20e 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -19,6 +19,7 @@
<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="new_incognito_tab" msgid="5821404839654751753">"Nuova finestra in incognito"</string>
<string name="active_tabs" msgid="3050623868203544623">"Finestre"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Segnalibri"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"I più visitati"</string>
@@ -32,12 +33,6 @@
<string name="bookmarks_search" msgid="5229596268214362873">"Browser"</string>
<string name="cancel" msgid="3017274947407233702">"Annulla"</string>
<string name="ok" msgid="1509280796718850364">"OK"</string>
- <plurals name="matches_found">
- <item quantity="zero" msgid="6242659159545399963">"Nessuna corrispondenza"</item>
- <item quantity="one" msgid="4352019729062956802">"1 corrispondenza"</item>
- <item quantity="few" msgid="5544267486978946555">"<xliff:g id="NUMBER">%d</xliff:g> corrispondenze"</item>
- <item quantity="other" msgid="6616125067364315405">"<xliff:g id="NUMBER">%d</xliff:g> corrispondenze"</item>
- </plurals>
<string name="title_bar_loading" msgid="7438217780834640678">"Caricamento..."</string>
<string name="page_info" msgid="4048529256302257195">"Info pagina"</string>
<string name="page_info_view" msgid="5303490449842635158">"Visualizza info pagina"</string>
@@ -67,12 +62,23 @@
<string name="forward" msgid="4288210890526641577">"Avanti"</string>
<string name="save" msgid="5922311934992468496">"OK"</string>
<string name="do_not_save" msgid="6777633870113477714">"Annulla"</string>
- <string name="location" msgid="969988560160364559">"URL"</string>
- <string name="name" msgid="5990326151488445481">"Nome"</string>
+ <!-- no translation found for location (3411848697912600125) -->
+ <skip />
+ <!-- no translation found for containing_folder (6771180232953030479) -->
+ <skip />
+ <!-- no translation found for add_new_folder (7027600176450718398) -->
+ <skip />
+ <!-- no translation found for new_folder (7743540149088867917) -->
+ <skip />
+ <!-- no translation found for name (5915607427720935681) -->
+ <skip />
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Aggiungi segnalibro"</string>
+ <string name="save_to_bookmarks" msgid="6101482434920313244">"Aggiungi ai segnalibri"</string>
+ <!-- no translation found for bookmark_this_page (7530739804320811054) -->
+ <skip />
<string name="edit_bookmark" msgid="5024089053490231905">"Modifica segnalibro"</string>
- <string name="create_shortcut_bookmark" msgid="9202323987633899835">"Aggiungi scorciatoia su Home"</string>
+ <!-- no translation found for create_shortcut_bookmark (1995095662095484289) -->
+ <skip />
<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>
@@ -93,7 +99,7 @@
<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="goto_dot" msgid="3895839050522602723">"Vai"</string>
- <string name="find_dot" msgid="6259312434696611957">"Trova nella pagina"</string>
+ <string name="incognito_tab" msgid="5419458065370134289">"Apri nuova scheda in incognito"</string>
<string name="select_dot" msgid="6299170761900561967">"Seleziona testo"</string>
<string name="tab_picker_title" msgid="864478399057782913">"Finestre correnti"</string>
<string name="tab_picker_remove_tab" msgid="630087809802479397">"Chiudi"</string>
@@ -103,6 +109,9 @@
<string name="menu_view_download" msgid="2124570321712995120">"Download"</string>
<string name="copy_page_url" msgid="7635062169011319208">"Copia URL della pagina"</string>
<string name="share_page" msgid="593756995297268343">"Condividi pagina"</string>
+ <string name="menu_save_webarchive" msgid="3934652434001459581">"Salva come archivio web"</string>
+ <string name="webarchive_saved" msgid="7045250341467345007">"Archivio web salvato"</string>
+ <string name="webarchive_failed" msgid="2880998204746620260">"Salvataggio archivio web non riuscito."</string>
<string name="contextmenu_openlink" msgid="7237961252214188935">"Apri"</string>
<string name="contextmenu_openlink_newwindow" msgid="992765050093960353">"Apri in nuova finestra"</string>
<string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"Aggiungi link in segnalibri"</string>
@@ -169,6 +178,10 @@
<string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"Salva nomi utente e password per i siti web"</string>
<string name="pref_security_save_form_data" msgid="1213669802810198893">"Memorizza dati moduli"</string>
<string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"Memorizza i dati che digito nei moduli per usi futuri"</string>
+ <!-- no translation found for pref_autoFill_enabled (5348131327347999291) -->
+ <skip />
+ <!-- no translation found for pref_autoFill_enabled_summary (282122852215557397) -->
+ <skip />
<string name="pref_security_show_security_warning" msgid="8901135676266754559">"Mostra avvisi protezione"</string>
<string name="pref_security_show_security_warning_summary" msgid="8968906112720511704">"Mostra un avviso se esiste un problema di sicurezza con un sito"</string>
<string name="pref_security_accept_cookies" msgid="3201367661925047989">"Accetta cookie"</string>
@@ -208,6 +221,7 @@
<item msgid="891615911084608570">"Giapponese (ISO-2022-JP)"</item>
<item msgid="5589150448475151241">"Giapponese (SHIFT_JIS)"</item>
<item msgid="7356792686950371843">"Giapponese (EUC-JP)"</item>
+ <item msgid="2193955365569270096">"Coreano (EUC-KR)"</item>
</string-array>
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Codifica testo"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Problema di connettività dati"</string>
@@ -292,4 +306,8 @@
<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="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Impostazione sfondo in corso..."</string>
+ <string name="defaultBookmarksUpButton" msgid="2303951020715704735">"Segnalibri"</string>
+ <!-- no translation found for empty_bookmarks_folder (7843361614634930942) -->
+ <skip />
+ <string name="rlz_access_point" msgid="7165847807377650632">"Y1"</string>
</resources>
diff --git a/res/values-ja/donottranslate_strings.xml b/res/values-ja/donottranslate_strings.xml
index cbda8f2..026d57a 100644
--- a/res/values-ja/donottranslate_strings.xml
+++ b/res/values-ja/donottranslate_strings.xml
@@ -17,5 +17,5 @@
<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>
+ <string name="pref_default_text_encoding_default" translatable="false">SHIFT_JIS</string>
</resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 85fbbdb..2e7bffb 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -19,6 +19,7 @@
<string name="application_name" msgid="1935869255545976415">"ブラウザ"</string>
<string name="choose_upload" msgid="3649366287575002063">"アップロードするファイルを選択"</string>
<string name="new_tab" msgid="4505722538297295141">"新しいウィンドウ"</string>
+ <string name="new_incognito_tab" msgid="5821404839654751753">"新しいシークレットウインドウ"</string>
<string name="active_tabs" msgid="3050623868203544623">"ウィンドウ"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"ブックマーク"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"よく使用"</string>
@@ -32,12 +33,6 @@
<string name="bookmarks_search" msgid="5229596268214362873">"ブラウザ"</string>
<string name="cancel" msgid="3017274947407233702">"キャンセル"</string>
<string name="ok" msgid="1509280796718850364">"OK"</string>
- <plurals name="matches_found">
- <item quantity="zero" msgid="6242659159545399963">"該当なし"</item>
- <item quantity="one" msgid="4352019729062956802">"1件一致"</item>
- <item quantity="few" msgid="5544267486978946555">"<xliff:g id="NUMBER">%d</xliff:g>件一致"</item>
- <item quantity="other" msgid="6616125067364315405">"<xliff:g id="NUMBER">%d</xliff:g>件一致"</item>
- </plurals>
<string name="title_bar_loading" msgid="7438217780834640678">"読み込み中..."</string>
<string name="page_info" msgid="4048529256302257195">"ページ情報"</string>
<string name="page_info_view" msgid="5303490449842635158">"ページ情報を表示"</string>
@@ -67,12 +62,23 @@
<string name="forward" msgid="4288210890526641577">"進む"</string>
<string name="save" msgid="5922311934992468496">"OK"</string>
<string name="do_not_save" msgid="6777633870113477714">"キャンセル"</string>
- <string name="location" msgid="969988560160364559">"場所"</string>
- <string name="name" msgid="5990326151488445481">"名前"</string>
+ <!-- no translation found for location (3411848697912600125) -->
+ <skip />
+ <!-- no translation found for containing_folder (6771180232953030479) -->
+ <skip />
+ <!-- no translation found for add_new_folder (7027600176450718398) -->
+ <skip />
+ <!-- no translation found for new_folder (7743540149088867917) -->
+ <skip />
+ <!-- no translation found for name (5915607427720935681) -->
+ <skip />
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"ブックマークを追加"</string>
+ <string name="save_to_bookmarks" msgid="6101482434920313244">"ブックマークに追加"</string>
+ <!-- no translation found for bookmark_this_page (7530739804320811054) -->
+ <skip />
<string name="edit_bookmark" msgid="5024089053490231905">"編集"</string>
- <string name="create_shortcut_bookmark" msgid="9202323987633899835">"ショートカットを作成"</string>
+ <!-- no translation found for create_shortcut_bookmark (1995095662095484289) -->
+ <skip />
<string name="open_bookmark" msgid="8473581305759935790">"開く"</string>
<string name="remove_bookmark" msgid="8407495852801410891">"削除"</string>
<string name="remove_from_bookmarks" msgid="4374080666576982775">"ブックマークから削除"</string>
@@ -93,7 +99,7 @@
<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="goto_dot" msgid="3895839050522602723">"移動"</string>
- <string name="find_dot" msgid="6259312434696611957">"ページ内検索"</string>
+ <string name="incognito_tab" msgid="5419458065370134289">"新しいシークレットタブを開く"</string>
<string name="select_dot" msgid="6299170761900561967">"テキストを選択してコピー"</string>
<string name="tab_picker_title" msgid="864478399057782913">"現在のウィンドウ"</string>
<string name="tab_picker_remove_tab" msgid="630087809802479397">"閉じる"</string>
@@ -103,6 +109,9 @@
<string name="menu_view_download" msgid="2124570321712995120">"ダウンロード履歴"</string>
<string name="copy_page_url" msgid="7635062169011319208">"ページのURLをコピー"</string>
<string name="share_page" msgid="593756995297268343">"ページを共有"</string>
+ <string name="menu_save_webarchive" msgid="3934652434001459581">"ウェブアーカイブとして保存"</string>
+ <string name="webarchive_saved" msgid="7045250341467345007">"ウェブアーカイブを保存しました。"</string>
+ <string name="webarchive_failed" msgid="2880998204746620260">"ウェブアーカイブを保存できませんでした。"</string>
<string name="contextmenu_openlink" msgid="7237961252214188935">"開く"</string>
<string name="contextmenu_openlink_newwindow" msgid="992765050093960353">"新しいウィンドウで開く"</string>
<string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"リンクをブックマーク"</string>
@@ -169,6 +178,10 @@
<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>
+ <!-- no translation found for pref_autoFill_enabled (5348131327347999291) -->
+ <skip />
+ <!-- no translation found for pref_autoFill_enabled_summary (282122852215557397) -->
+ <skip />
<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>
@@ -208,6 +221,7 @@
<item msgid="891615911084608570">"日本語(ISO-2022-JP)"</item>
<item msgid="5589150448475151241">"日本語(SHIFT_JIS)"</item>
<item msgid="7356792686950371843">"日本語(EUC-JP)"</item>
+ <item msgid="2193955365569270096">"韓国語(EUC-KR)"</item>
</string-array>
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"テキストエンコード"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"データアクセスエラー"</string>
@@ -292,4 +306,8 @@
<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="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"壁紙を設定中..."</string>
+ <string name="defaultBookmarksUpButton" msgid="2303951020715704735">"ブックマーク"</string>
+ <!-- no translation found for empty_bookmarks_folder (7843361614634930942) -->
+ <skip />
+ <string name="rlz_access_point" msgid="7165847807377650632">"Y1"</string>
</resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 049a243..002d94f 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -19,6 +19,7 @@
<string name="application_name" msgid="1935869255545976415">"인터넷"</string>
<string name="choose_upload" msgid="3649366287575002063">"업로드할 파일 선택"</string>
<string name="new_tab" msgid="4505722538297295141">"새 창"</string>
+ <string name="new_incognito_tab" msgid="5821404839654751753">"새 시크릿 창"</string>
<string name="active_tabs" msgid="3050623868203544623">"창"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"북마크"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"자주 방문한 페이지"</string>
@@ -32,12 +33,6 @@
<string name="bookmarks_search" msgid="5229596268214362873">"브라우저"</string>
<string name="cancel" msgid="3017274947407233702">"취소"</string>
<string name="ok" msgid="1509280796718850364">"확인"</string>
- <plurals name="matches_found">
- <item quantity="zero" msgid="6242659159545399963">"검색결과 없음"</item>
- <item quantity="one" msgid="4352019729062956802">"검색결과 1개"</item>
- <item quantity="few" msgid="5544267486978946555">"검색결과 <xliff:g id="NUMBER">%d</xliff:g>개"</item>
- <item quantity="other" msgid="6616125067364315405">"검색결과 <xliff:g id="NUMBER">%d</xliff:g>개"</item>
- </plurals>
<string name="title_bar_loading" msgid="7438217780834640678">"로드 중..."</string>
<string name="page_info" msgid="4048529256302257195">"페이지 정보"</string>
<string name="page_info_view" msgid="5303490449842635158">"페이지 정보 보기"</string>
@@ -67,12 +62,23 @@
<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>
- <string name="name" msgid="5990326151488445481">"이름"</string>
+ <!-- no translation found for location (3411848697912600125) -->
+ <skip />
+ <!-- no translation found for containing_folder (6771180232953030479) -->
+ <skip />
+ <!-- no translation found for add_new_folder (7027600176450718398) -->
+ <skip />
+ <!-- no translation found for new_folder (7743540149088867917) -->
+ <skip />
+ <!-- no translation found for name (5915607427720935681) -->
+ <skip />
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"북마크에 추가"</string>
+ <string name="save_to_bookmarks" msgid="6101482434920313244">"북마크에 추가"</string>
+ <!-- no translation found for bookmark_this_page (7530739804320811054) -->
+ <skip />
<string name="edit_bookmark" msgid="5024089053490231905">"북마크 수정"</string>
- <string name="create_shortcut_bookmark" msgid="9202323987633899835">"홈에 바로가기 추가"</string>
+ <!-- no translation found for create_shortcut_bookmark (1995095662095484289) -->
+ <skip />
<string name="open_bookmark" msgid="8473581305759935790">"열기"</string>
<string name="remove_bookmark" msgid="8407495852801410891">"북마크 삭제"</string>
<string name="remove_from_bookmarks" msgid="4374080666576982775">"북마크에서 삭제"</string>
@@ -93,7 +99,7 @@
<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="goto_dot" msgid="3895839050522602723">"이동"</string>
- <string name="find_dot" msgid="6259312434696611957">"페이지에서 찾기"</string>
+ <string name="incognito_tab" msgid="5419458065370134289">"새 시크릿 탭 열기"</string>
<string name="select_dot" msgid="6299170761900561967">"텍스트 선택"</string>
<string name="tab_picker_title" msgid="864478399057782913">"현재 창"</string>
<string name="tab_picker_remove_tab" msgid="630087809802479397">"닫기"</string>
@@ -103,6 +109,9 @@
<string name="menu_view_download" msgid="2124570321712995120">"다운로드"</string>
<string name="copy_page_url" msgid="7635062169011319208">"페이지 URL 복사"</string>
<string name="share_page" msgid="593756995297268343">"페이지 공유"</string>
+ <string name="menu_save_webarchive" msgid="3934652434001459581">"웹 아카이브로 저장"</string>
+ <string name="webarchive_saved" msgid="7045250341467345007">"웹 아카이브를 저장했습니다."</string>
+ <string name="webarchive_failed" msgid="2880998204746620260">"웹 아카이브를 저장하지 못했습니다."</string>
<string name="contextmenu_openlink" msgid="7237961252214188935">"열기"</string>
<string name="contextmenu_openlink_newwindow" msgid="992765050093960353">"새 창에서 열기"</string>
<string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"링크를 북마크에 추가"</string>
@@ -169,6 +178,10 @@
<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>
+ <!-- no translation found for pref_autoFill_enabled (5348131327347999291) -->
+ <skip />
+ <!-- no translation found for pref_autoFill_enabled_summary (282122852215557397) -->
+ <skip />
<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">"쿠키 허용"</string>
@@ -208,6 +221,7 @@
<item msgid="891615911084608570">"일본어(ISO-2022-JP)"</item>
<item msgid="5589150448475151241">"일본어(SHIFT_JIS)"</item>
<item msgid="7356792686950371843">"일본어(EUC-JP)"</item>
+ <item msgid="2193955365569270096">"한국어(EUC-KR)"</item>
</string-array>
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"텍스트 인코딩"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"데이터 연결에 문제 발생"</string>
@@ -292,4 +306,8 @@
<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="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"배경화면을 설정하는 중..."</string>
+ <string name="defaultBookmarksUpButton" msgid="2303951020715704735">"북마크"</string>
+ <!-- no translation found for empty_bookmarks_folder (7843361614634930942) -->
+ <skip />
+ <string name="rlz_access_point" msgid="7165847807377650632">"Y1"</string>
</resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index d04f701..2937474 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -19,6 +19,7 @@
<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="new_incognito_tab" msgid="5821404839654751753">"Nytt inkognitovindu"</string>
<string name="active_tabs" msgid="3050623868203544623">"Vinduer"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Bokmerker"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"Mest besøkt"</string>
@@ -32,12 +33,6 @@
<string name="bookmarks_search" msgid="5229596268214362873">"Nettleser"</string>
<string name="cancel" msgid="3017274947407233702">"Avbryt"</string>
<string name="ok" msgid="1509280796718850364">"OK"</string>
- <plurals name="matches_found">
- <item quantity="zero" msgid="6242659159545399963">"Ingen treff"</item>
- <item quantity="one" msgid="4352019729062956802">"Ett treff"</item>
- <item quantity="few" msgid="5544267486978946555">"<xliff:g id="NUMBER">%d</xliff:g> treff"</item>
- <item quantity="other" msgid="6616125067364315405">"<xliff:g id="NUMBER">%d</xliff:g> treff"</item>
- </plurals>
<string name="title_bar_loading" msgid="7438217780834640678">"Laster inn ..."</string>
<string name="page_info" msgid="4048529256302257195">"Sideinfo"</string>
<string name="page_info_view" msgid="5303490449842635158">"Vis sideinformasjon"</string>
@@ -67,12 +62,23 @@
<string name="forward" msgid="4288210890526641577">"Fremover"</string>
<string name="save" msgid="5922311934992468496">"OK"</string>
<string name="do_not_save" msgid="6777633870113477714">"Avbryt"</string>
- <string name="location" msgid="969988560160364559">"Adresse"</string>
- <string name="name" msgid="5990326151488445481">"Navn"</string>
+ <!-- no translation found for location (3411848697912600125) -->
+ <skip />
+ <!-- no translation found for containing_folder (6771180232953030479) -->
+ <skip />
+ <!-- no translation found for add_new_folder (7027600176450718398) -->
+ <skip />
+ <!-- no translation found for new_folder (7743540149088867917) -->
+ <skip />
+ <!-- no translation found for name (5915607427720935681) -->
+ <skip />
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Legg til bokmerke"</string>
+ <string name="save_to_bookmarks" msgid="6101482434920313244">"Legg til i bokmerker"</string>
+ <!-- no translation found for bookmark_this_page (7530739804320811054) -->
+ <skip />
<string name="edit_bookmark" msgid="5024089053490231905">"Rediger bokmerke"</string>
- <string name="create_shortcut_bookmark" msgid="9202323987633899835">"Lag snarvei på skrivebordet"</string>
+ <!-- no translation found for create_shortcut_bookmark (1995095662095484289) -->
+ <skip />
<string name="open_bookmark" msgid="8473581305759935790">"Åpne"</string>
<string name="remove_bookmark" msgid="8407495852801410891">"Slett bokmerke"</string>
<string name="remove_from_bookmarks" msgid="4374080666576982775">"Fjern fra bokmerker"</string>
@@ -93,7 +99,7 @@
<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="goto_dot" msgid="3895839050522602723">"Gå til"</string>
- <string name="find_dot" msgid="6259312434696611957">"Finn på siden"</string>
+ <string name="incognito_tab" msgid="5419458065370134289">"Åpne ny inkognitofane"</string>
<string name="select_dot" msgid="6299170761900561967">"Velg tekst"</string>
<string name="tab_picker_title" msgid="864478399057782913">"Gjeldende vinduer"</string>
<string name="tab_picker_remove_tab" msgid="630087809802479397">"Lukk"</string>
@@ -103,6 +109,9 @@
<string name="menu_view_download" msgid="2124570321712995120">"Nedlastinger"</string>
<string name="copy_page_url" msgid="7635062169011319208">"Kopier nettstedsadresse"</string>
<string name="share_page" msgid="593756995297268343">"Del side"</string>
+ <string name="menu_save_webarchive" msgid="3934652434001459581">"Lagre som nettarkiv"</string>
+ <string name="webarchive_saved" msgid="7045250341467345007">"Nettarkiv lagret."</string>
+ <string name="webarchive_failed" msgid="2880998204746620260">"Kunne ikke lagre nettarkivet."</string>
<string name="contextmenu_openlink" msgid="7237961252214188935">"Åpne"</string>
<string name="contextmenu_openlink_newwindow" msgid="992765050093960353">"Åpne i nytt vindu"</string>
<string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"Bokmerk kobling"</string>
@@ -169,6 +178,10 @@
<string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"Lagre brukernavn og passord for nettsteder"</string>
<string name="pref_security_save_form_data" msgid="1213669802810198893">"Husk skjemadata"</string>
<string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"Husk data skrevet inn i skjemaer til senere"</string>
+ <!-- no translation found for pref_autoFill_enabled (5348131327347999291) -->
+ <skip />
+ <!-- no translation found for pref_autoFill_enabled_summary (282122852215557397) -->
+ <skip />
<string name="pref_security_show_security_warning" msgid="8901135676266754559">"Vis sikkerhetsadvarsler"</string>
<string name="pref_security_show_security_warning_summary" msgid="8968906112720511704">"Vis advarsel hvis det er et problem med sikkerheten på et nettsted"</string>
<string name="pref_security_accept_cookies" msgid="3201367661925047989">"Godta informasjonskapsler"</string>
@@ -208,6 +221,7 @@
<item msgid="891615911084608570">"Japansk (ISO-2022-JP)"</item>
<item msgid="5589150448475151241">"Japansk (SHIFT_JIS)"</item>
<item msgid="7356792686950371843">"Japansk (EUC-JP)"</item>
+ <item msgid="2193955365569270096">"Koreansk (EUC-KR)"</item>
</string-array>
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Tekstkoding"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Datatilkoblingsproblem"</string>
@@ -292,4 +306,8 @@
<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="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Angir bakgrunn ..."</string>
+ <string name="defaultBookmarksUpButton" msgid="2303951020715704735">"Bokmerker"</string>
+ <!-- no translation found for empty_bookmarks_folder (7843361614634930942) -->
+ <skip />
+ <string name="rlz_access_point" msgid="7165847807377650632">"Y1"</string>
</resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index ca922ac..d315a22 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -19,6 +19,7 @@
<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="new_incognito_tab" msgid="5821404839654751753">"Nieuw incognitovenster"</string>
<string name="active_tabs" msgid="3050623868203544623">"Vensters"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Bladwijzers"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"Meest bezocht"</string>
@@ -32,12 +33,6 @@
<string name="bookmarks_search" msgid="5229596268214362873">"Browser"</string>
<string name="cancel" msgid="3017274947407233702">"Annuleren"</string>
<string name="ok" msgid="1509280796718850364">"OK"</string>
- <plurals name="matches_found">
- <item quantity="zero" msgid="6242659159545399963">"Geen overeenkomsten"</item>
- <item quantity="one" msgid="4352019729062956802">"1 overeenkomst"</item>
- <item quantity="few" msgid="5544267486978946555">"<xliff:g id="NUMBER">%d</xliff:g> overeenkomsten"</item>
- <item quantity="other" msgid="6616125067364315405">"<xliff:g id="NUMBER">%d</xliff:g> overeenkomsten"</item>
- </plurals>
<string name="title_bar_loading" msgid="7438217780834640678">"Laden..."</string>
<string name="page_info" msgid="4048529256302257195">"Pagina-informatie"</string>
<string name="page_info_view" msgid="5303490449842635158">"Pagina-informatie weergeven"</string>
@@ -67,12 +62,23 @@
<string name="forward" msgid="4288210890526641577">"Volgende"</string>
<string name="save" msgid="5922311934992468496">"OK"</string>
<string name="do_not_save" msgid="6777633870113477714">"Annuleren"</string>
- <string name="location" msgid="969988560160364559">"Locatie"</string>
- <string name="name" msgid="5990326151488445481">"Naam"</string>
+ <!-- no translation found for location (3411848697912600125) -->
+ <skip />
+ <!-- no translation found for containing_folder (6771180232953030479) -->
+ <skip />
+ <!-- no translation found for add_new_folder (7027600176450718398) -->
+ <skip />
+ <!-- no translation found for new_folder (7743540149088867917) -->
+ <skip />
+ <!-- no translation found for name (5915607427720935681) -->
+ <skip />
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Bladwijzer toevoegen"</string>
+ <string name="save_to_bookmarks" msgid="6101482434920313244">"Toevoegen aan bladwijzers"</string>
+ <!-- no translation found for bookmark_this_page (7530739804320811054) -->
+ <skip />
<string name="edit_bookmark" msgid="5024089053490231905">"Bladwijzer bewerken"</string>
- <string name="create_shortcut_bookmark" msgid="9202323987633899835">"Snelkoppeling naar startpagina toevoegen"</string>
+ <!-- no translation found for create_shortcut_bookmark (1995095662095484289) -->
+ <skip />
<string name="open_bookmark" msgid="8473581305759935790">"Openen"</string>
<string name="remove_bookmark" msgid="8407495852801410891">"Bladwijzer verwijderen"</string>
<string name="remove_from_bookmarks" msgid="4374080666576982775">"Verwijderen uit bladwijzers"</string>
@@ -93,7 +99,7 @@
<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="goto_dot" msgid="3895839050522602723">"Ga"</string>
- <string name="find_dot" msgid="6259312434696611957">"Zoeken op pagina"</string>
+ <string name="incognito_tab" msgid="5419458065370134289">"Nieuw incognitotabblad openen"</string>
<string name="select_dot" msgid="6299170761900561967">"Tekst selecteren"</string>
<string name="tab_picker_title" msgid="864478399057782913">"Huidige vensters"</string>
<string name="tab_picker_remove_tab" msgid="630087809802479397">"Sluiten"</string>
@@ -103,6 +109,9 @@
<string name="menu_view_download" msgid="2124570321712995120">"Downloads"</string>
<string name="copy_page_url" msgid="7635062169011319208">"Pagina-URL kopiëren"</string>
<string name="share_page" msgid="593756995297268343">"Pagina delen"</string>
+ <string name="menu_save_webarchive" msgid="3934652434001459581">"Opslaan als webarchief"</string>
+ <string name="webarchive_saved" msgid="7045250341467345007">"Webarchief opgeslagen."</string>
+ <string name="webarchive_failed" msgid="2880998204746620260">"Opslaan van webarchief is mislukt."</string>
<string name="contextmenu_openlink" msgid="7237961252214188935">"Openen"</string>
<string name="contextmenu_openlink_newwindow" msgid="992765050093960353">"Openen in een nieuw venster"</string>
<string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"Bladwijzer maken van link"</string>
@@ -169,6 +178,10 @@
<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">"Formulierdata onthouden"</string>
<string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"Gegevens die ik typ in formulieren, onthouden voor later gebruik"</string>
+ <!-- no translation found for pref_autoFill_enabled (5348131327347999291) -->
+ <skip />
+ <!-- no translation found for pref_autoFill_enabled_summary (282122852215557397) -->
+ <skip />
<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>
<string name="pref_security_accept_cookies" msgid="3201367661925047989">"Cookies accepteren"</string>
@@ -208,6 +221,7 @@
<item msgid="891615911084608570">"Japans (ISO-2022-JP)"</item>
<item msgid="5589150448475151241">"Japans (SHIFT_JIS)"</item>
<item msgid="7356792686950371843">"Japans (EUC-JP)"</item>
+ <item msgid="2193955365569270096">"Koreaans (EUC-KR)"</item>
</string-array>
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Tekstcodering"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Probleem met gegevensverbinding"</string>
@@ -292,4 +306,8 @@
<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="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Achtergrond instellen..."</string>
+ <string name="defaultBookmarksUpButton" msgid="2303951020715704735">"Bladwijzers"</string>
+ <!-- no translation found for empty_bookmarks_folder (7843361614634930942) -->
+ <skip />
+ <string name="rlz_access_point" msgid="7165847807377650632">"J1"</string>
</resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 2b69fa9..473f907 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -19,6 +19,7 @@
<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="new_incognito_tab" msgid="5821404839654751753">"Nowe okno incognito"</string>
<string name="active_tabs" msgid="3050623868203544623">"Okna"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Zakładki"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"Popularne"</string>
@@ -32,12 +33,6 @@
<string name="bookmarks_search" msgid="5229596268214362873">"Przeglądarka"</string>
<string name="cancel" msgid="3017274947407233702">"Anuluj"</string>
<string name="ok" msgid="1509280796718850364">"OK"</string>
- <plurals name="matches_found">
- <item quantity="zero" msgid="6242659159545399963">"Brak wyników"</item>
- <item quantity="one" msgid="4352019729062956802">"1 wynik"</item>
- <item quantity="few" msgid="5544267486978946555">"Wyników: <xliff:g id="NUMBER">%d</xliff:g>"</item>
- <item quantity="other" msgid="6616125067364315405">"Wyników: <xliff:g id="NUMBER">%d</xliff:g>"</item>
- </plurals>
<string name="title_bar_loading" msgid="7438217780834640678">"Trwa wczytywanie..."</string>
<string name="page_info" msgid="4048529256302257195">"Informacje o stronie"</string>
<string name="page_info_view" msgid="5303490449842635158">"Informacje o stronie"</string>
@@ -67,12 +62,23 @@
<string name="forward" msgid="4288210890526641577">"Dalej"</string>
<string name="save" msgid="5922311934992468496">"OK"</string>
<string name="do_not_save" msgid="6777633870113477714">"Anuluj"</string>
- <string name="location" msgid="969988560160364559">"Adres"</string>
- <string name="name" msgid="5990326151488445481">"Nazwa"</string>
+ <!-- no translation found for location (3411848697912600125) -->
+ <skip />
+ <!-- no translation found for containing_folder (6771180232953030479) -->
+ <skip />
+ <!-- no translation found for add_new_folder (7027600176450718398) -->
+ <skip />
+ <!-- no translation found for new_folder (7743540149088867917) -->
+ <skip />
+ <!-- no translation found for name (5915607427720935681) -->
+ <skip />
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Dodaj zakładkę"</string>
+ <string name="save_to_bookmarks" msgid="6101482434920313244">"Dodaj do Zakładek"</string>
+ <!-- no translation found for bookmark_this_page (7530739804320811054) -->
+ <skip />
<string name="edit_bookmark" msgid="5024089053490231905">"Edytuj zakładkę"</string>
- <string name="create_shortcut_bookmark" msgid="9202323987633899835">"Dodaj skrót do strony głównej"</string>
+ <!-- no translation found for create_shortcut_bookmark (1995095662095484289) -->
+ <skip />
<string name="open_bookmark" msgid="8473581305759935790">"Otwórz"</string>
<string name="remove_bookmark" msgid="8407495852801410891">"Usuń zakładkę"</string>
<string name="remove_from_bookmarks" msgid="4374080666576982775">"Usuń z zakładek"</string>
@@ -93,7 +99,7 @@
<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="goto_dot" msgid="3895839050522602723">"Przejdź"</string>
- <string name="find_dot" msgid="6259312434696611957">"Znajdź na stronie"</string>
+ <string name="incognito_tab" msgid="5419458065370134289">"Otwórz nową kartę incognito"</string>
<string name="select_dot" msgid="6299170761900561967">"Zaznacz tekst"</string>
<string name="tab_picker_title" msgid="864478399057782913">"Bieżące okna"</string>
<string name="tab_picker_remove_tab" msgid="630087809802479397">"Zamknij"</string>
@@ -103,6 +109,9 @@
<string name="menu_view_download" msgid="2124570321712995120">"Pobrane pliki"</string>
<string name="copy_page_url" msgid="7635062169011319208">"Kopiuj adres URL strony"</string>
<string name="share_page" msgid="593756995297268343">"Udostępnij stronę"</string>
+ <string name="menu_save_webarchive" msgid="3934652434001459581">"Zapisz jako archiwum internetowe"</string>
+ <string name="webarchive_saved" msgid="7045250341467345007">"Archiwum internetowe zostało zapisane."</string>
+ <string name="webarchive_failed" msgid="2880998204746620260">"Nie można zapisać archiwum internetowego."</string>
<string name="contextmenu_openlink" msgid="7237961252214188935">"Otwórz"</string>
<string name="contextmenu_openlink_newwindow" msgid="992765050093960353">"Otwórz w nowym oknie"</string>
<string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"Dodaj link do zakładek"</string>
@@ -169,6 +178,10 @@
<string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"Zapisz nazwy użytkowników i hasła używane w witrynach"</string>
<string name="pref_security_save_form_data" msgid="1213669802810198893">"Pamiętaj wpisane dane"</string>
<string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"Zapamiętuj do późniejszego użycia dane, które wpisuję w formularzach"</string>
+ <!-- no translation found for pref_autoFill_enabled (5348131327347999291) -->
+ <skip />
+ <!-- no translation found for pref_autoFill_enabled_summary (282122852215557397) -->
+ <skip />
<string name="pref_security_show_security_warning" msgid="8901135676266754559">"Wyświetlaj ostrzeżenia"</string>
<string name="pref_security_show_security_warning_summary" msgid="8968906112720511704">"Wyświetl ostrzeżenie w razie problemów z zabezpieczeniami strony"</string>
<string name="pref_security_accept_cookies" msgid="3201367661925047989">"Akceptuj pliki cookie"</string>
@@ -208,6 +221,7 @@
<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>
+ <item msgid="2193955365569270096">"koreański (EUC-KR)"</item>
</string-array>
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Kodowanie tekstu"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Problem z łącznością danych"</string>
@@ -292,4 +306,8 @@
<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="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Trwa ustawianie tapety..."</string>
+ <string name="defaultBookmarksUpButton" msgid="2303951020715704735">"Zakładki"</string>
+ <!-- no translation found for empty_bookmarks_folder (7843361614634930942) -->
+ <skip />
+ <string name="rlz_access_point" msgid="7165847807377650632">"Y1"</string>
</resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 55b50fe..ff9ae24 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -19,6 +19,7 @@
<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="new_incognito_tab" msgid="5821404839654751753">"Nova janela de naveg. anónima"</string>
<string name="active_tabs" msgid="3050623868203544623">"Janelas"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Marcadores"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"Os mais visitados"</string>
@@ -32,12 +33,6 @@
<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">
- <item quantity="zero" msgid="6242659159545399963">"Sem correspondência"</item>
- <item quantity="one" msgid="4352019729062956802">"1 correspondência"</item>
- <item quantity="few" msgid="5544267486978946555">"<xliff:g id="NUMBER">%d</xliff:g> correspondências"</item>
- <item quantity="other" msgid="6616125067364315405">"<xliff:g id="NUMBER">%d</xliff:g> correspondências"</item>
- </plurals>
<string name="title_bar_loading" msgid="7438217780834640678">"A carregar..."</string>
<string name="page_info" msgid="4048529256302257195">"Informações da página"</string>
<string name="page_info_view" msgid="5303490449842635158">"Ver informações da página"</string>
@@ -67,12 +62,23 @@
<string name="forward" msgid="4288210890526641577">"Avançar"</string>
<string name="save" msgid="5922311934992468496">"OK"</string>
<string name="do_not_save" msgid="6777633870113477714">"Cancelar"</string>
- <string name="location" msgid="969988560160364559">"Local"</string>
- <string name="name" msgid="5990326151488445481">"Nome"</string>
+ <!-- no translation found for location (3411848697912600125) -->
+ <skip />
+ <!-- no translation found for containing_folder (6771180232953030479) -->
+ <skip />
+ <!-- no translation found for add_new_folder (7027600176450718398) -->
+ <skip />
+ <!-- no translation found for new_folder (7743540149088867917) -->
+ <skip />
+ <!-- no translation found for name (5915607427720935681) -->
+ <skip />
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Adicionar marcador"</string>
+ <string name="save_to_bookmarks" msgid="6101482434920313244">"Adicionar aos marcadores"</string>
+ <!-- no translation found for bookmark_this_page (7530739804320811054) -->
+ <skip />
<string name="edit_bookmark" msgid="5024089053490231905">"Editar marcador"</string>
- <string name="create_shortcut_bookmark" msgid="9202323987633899835">"Adicionar atalho à página inicial"</string>
+ <!-- no translation found for create_shortcut_bookmark (1995095662095484289) -->
+ <skip />
<string name="open_bookmark" msgid="8473581305759935790">"Abrir"</string>
<string name="remove_bookmark" msgid="8407495852801410891">"Eliminar marcador"</string>
<string name="remove_from_bookmarks" msgid="4374080666576982775">"Remover dos marcadores"</string>
@@ -93,7 +99,7 @@
<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="goto_dot" msgid="3895839050522602723">"Ir"</string>
- <string name="find_dot" msgid="6259312434696611957">"Encontrar na página"</string>
+ <string name="incognito_tab" msgid="5419458065370134289">"Abrir novo separador de navegação anónima"</string>
<string name="select_dot" msgid="6299170761900561967">"Seleccionar texto"</string>
<string name="tab_picker_title" msgid="864478399057782913">"Janelas actuais"</string>
<string name="tab_picker_remove_tab" msgid="630087809802479397">"Fechar"</string>
@@ -103,6 +109,9 @@
<string name="menu_view_download" msgid="2124570321712995120">"Transferências"</string>
<string name="copy_page_url" msgid="7635062169011319208">"Copiar URL da página"</string>
<string name="share_page" msgid="593756995297268343">"Partilhar página"</string>
+ <string name="menu_save_webarchive" msgid="3934652434001459581">"Guardar como arquivo Web"</string>
+ <string name="webarchive_saved" msgid="7045250341467345007">"Arquivo Web guardado."</string>
+ <string name="webarchive_failed" msgid="2880998204746620260">"Não foi possível guardar o arquivo Web."</string>
<string name="contextmenu_openlink" msgid="7237961252214188935">"Abrir"</string>
<string name="contextmenu_openlink_newwindow" msgid="992765050093960353">"Abrir numa janela nova"</string>
<string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"Adicionar link aos marcadores"</string>
@@ -169,6 +178,10 @@
<string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"Guardar nomes de utilizador e palavras-passe de Web sites"</string>
<string name="pref_security_save_form_data" msgid="1213669802810198893">"Lembrar dados formulário"</string>
<string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"Lembrar dados introduzidos em formulários para utilização posterior"</string>
+ <!-- no translation found for pref_autoFill_enabled (5348131327347999291) -->
+ <skip />
+ <!-- no translation found for pref_autoFill_enabled_summary (282122852215557397) -->
+ <skip />
<string name="pref_security_show_security_warning" msgid="8901135676266754559">"Mostrar avisos segurança"</string>
<string name="pref_security_show_security_warning_summary" msgid="8968906112720511704">"Mostrar aviso se ocorrer um problema com a segurança de um site"</string>
<string name="pref_security_accept_cookies" msgid="3201367661925047989">"Aceitar cookies"</string>
@@ -208,6 +221,7 @@
<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>
+ <item msgid="2193955365569270096">"Coreano (EUC-KR)"</item>
</string-array>
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Codificação do texto"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Problema de conectividade de dados"</string>
@@ -292,4 +306,8 @@
<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="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"A definir imagem de fundo..."</string>
+ <string name="defaultBookmarksUpButton" msgid="2303951020715704735">"Marcadores"</string>
+ <!-- no translation found for empty_bookmarks_folder (7843361614634930942) -->
+ <skip />
+ <string name="rlz_access_point" msgid="7165847807377650632">"Y1"</string>
</resources>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 337b1c5..3ad1e51 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -19,6 +19,7 @@
<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="new_incognito_tab" msgid="5821404839654751753">"Nova janela anônima"</string>
<string name="active_tabs" msgid="3050623868203544623">"Janelas"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Favoritos"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"Mais visitados"</string>
@@ -32,12 +33,6 @@
<string name="bookmarks_search" msgid="5229596268214362873">"Navegador"</string>
<string name="cancel" msgid="3017274947407233702">"Cancelar"</string>
<string name="ok" msgid="1509280796718850364">"OK"</string>
- <plurals name="matches_found">
- <item quantity="zero" msgid="6242659159545399963">"Sem correspondências"</item>
- <item quantity="one" msgid="4352019729062956802">"1 correspondência"</item>
- <item quantity="few" msgid="5544267486978946555">"<xliff:g id="NUMBER">%d</xliff:g> correspondências"</item>
- <item quantity="other" msgid="6616125067364315405">"<xliff:g id="NUMBER">%d</xliff:g> correspondências"</item>
- </plurals>
<string name="title_bar_loading" msgid="7438217780834640678">"Carregando..."</string>
<string name="page_info" msgid="4048529256302257195">"Informações da página"</string>
<string name="page_info_view" msgid="5303490449842635158">"Visualizar informações da página"</string>
@@ -67,12 +62,23 @@
<string name="forward" msgid="4288210890526641577">"Avançar"</string>
<string name="save" msgid="5922311934992468496">"OK"</string>
<string name="do_not_save" msgid="6777633870113477714">"Cancelar"</string>
- <string name="location" msgid="969988560160364559">"Local"</string>
- <string name="name" msgid="5990326151488445481">"Nome"</string>
+ <!-- no translation found for location (3411848697912600125) -->
+ <skip />
+ <!-- no translation found for containing_folder (6771180232953030479) -->
+ <skip />
+ <!-- no translation found for add_new_folder (7027600176450718398) -->
+ <skip />
+ <!-- no translation found for new_folder (7743540149088867917) -->
+ <skip />
+ <!-- no translation found for name (5915607427720935681) -->
+ <skip />
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Adicionar favorito"</string>
+ <string name="save_to_bookmarks" msgid="6101482434920313244">"Adicionar aos favoritos"</string>
+ <!-- no translation found for bookmark_this_page (7530739804320811054) -->
+ <skip />
<string name="edit_bookmark" msgid="5024089053490231905">"Editar favorito"</string>
- <string name="create_shortcut_bookmark" msgid="9202323987633899835">"Adicionar atalho à Página inicial"</string>
+ <!-- no translation found for create_shortcut_bookmark (1995095662095484289) -->
+ <skip />
<string name="open_bookmark" msgid="8473581305759935790">"Abrir"</string>
<string name="remove_bookmark" msgid="8407495852801410891">"Excluir favorito"</string>
<string name="remove_from_bookmarks" msgid="4374080666576982775">"Remover dos favoritos"</string>
@@ -93,7 +99,7 @@
<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="goto_dot" msgid="3895839050522602723">"Ir"</string>
- <string name="find_dot" msgid="6259312434696611957">"Localizar na página"</string>
+ <string name="incognito_tab" msgid="5419458065370134289">"Abrir nova guia anônima"</string>
<string name="select_dot" msgid="6299170761900561967">"Selecionar texto"</string>
<string name="tab_picker_title" msgid="864478399057782913">"Janelas atuais"</string>
<string name="tab_picker_remove_tab" msgid="630087809802479397">"Fechar"</string>
@@ -103,6 +109,9 @@
<string name="menu_view_download" msgid="2124570321712995120">"Downloads"</string>
<string name="copy_page_url" msgid="7635062169011319208">"Copiar URL da página"</string>
<string name="share_page" msgid="593756995297268343">"Compartilhar página"</string>
+ <string name="menu_save_webarchive" msgid="3934652434001459581">"Salvar como arquivo da web"</string>
+ <string name="webarchive_saved" msgid="7045250341467345007">"Arquivo da web salvo."</string>
+ <string name="webarchive_failed" msgid="2880998204746620260">"Falha ao salvar arquivo da web."</string>
<string name="contextmenu_openlink" msgid="7237961252214188935">"Abrir"</string>
<string name="contextmenu_openlink_newwindow" msgid="992765050093960353">"Abrir em uma nova janela"</string>
<string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"Link do favorito"</string>
@@ -169,6 +178,10 @@
<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 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>
+ <!-- no translation found for pref_autoFill_enabled (5348131327347999291) -->
+ <skip />
+ <!-- no translation found for pref_autoFill_enabled_summary (282122852215557397) -->
+ <skip />
<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>
<string name="pref_security_accept_cookies" msgid="3201367661925047989">"Aceitar cookies"</string>
@@ -208,6 +221,7 @@
<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>
+ <item msgid="2193955365569270096">"Coreano (EUC-KR)"</item>
</string-array>
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Codificação de texto"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Problema de conectividade de dados"</string>
@@ -292,4 +306,8 @@
<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="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Definindo o plano de fundo..."</string>
+ <string name="defaultBookmarksUpButton" msgid="2303951020715704735">"Favoritos"</string>
+ <!-- no translation found for empty_bookmarks_folder (7843361614634930942) -->
+ <skip />
+ <string name="rlz_access_point" msgid="7165847807377650632">"Y1"</string>
</resources>
diff --git a/res/values-rm/strings.xml b/res/values-rm/strings.xml
new file mode 100644
index 0000000..b950a59
--- /dev/null
+++ b/res/values-rm/strings.xml
@@ -0,0 +1,316 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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">"Navigatur"</string>
+ <string name="choose_upload" msgid="3649366287575002063">"Tscherner ina datoteca per importar"</string>
+ <string name="new_tab" msgid="4505722538297295141">"Nova fanestra"</string>
+ <!-- no translation found for new_incognito_tab (5821404839654751753) -->
+ <skip />
+ <string name="active_tabs" msgid="3050623868203544623">"Fanestra"</string>
+ <string name="tab_bookmarks" msgid="2305793036003473653">"Segnapaginas"</string>
+ <string name="tab_most_visited" msgid="1077402532455000703">"Visità il pli savens"</string>
+ <string name="tab_history" msgid="1979267558744613746">"Cronologia"</string>
+ <string name="added_to_bookmarks" msgid="1020224130695956728">"Agiuntà als segnapaginas"</string>
+ <string name="removed_from_bookmarks" msgid="6063705902028438800">"Allontanà dals segnapaginas"</string>
+ <string name="sign_in_to" msgid="5939425800148759165">"S\'annunziar tar <xliff:g id="HOSTNAME">%s1</xliff:g> «<xliff:g id="REALM">%s2</xliff:g>»"</string>
+ <string name="username" msgid="5057566336518215922">"Num"</string>
+ <string name="password" msgid="1177138552305184404">"Pled-clav"</string>
+ <string name="action" msgid="183105774472071343">"S\'annunziar"</string>
+ <string name="bookmarks_search" msgid="5229596268214362873">"Navigatur"</string>
+ <string name="cancel" msgid="3017274947407233702">"Interrumper"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="title_bar_loading" msgid="7438217780834640678">"Chargiar…"</string>
+ <string name="page_info" msgid="4048529256302257195">"Infos davart la pagina"</string>
+ <string name="page_info_view" msgid="5303490449842635158">"Mussar las infurmaziuns da la pagina"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adressa:"</string>
+ <string name="ssl_warnings_header" msgid="79744901983636370">"I ha dà in problem cun il certificat da segirezza per questa pagina."</string>
+ <string name="ssl_continue" msgid="8031515015829358457">"Cuntinuar"</string>
+ <string name="security_warning" msgid="6607795404322797541">"Avertiment da segirezza"</string>
+ <string name="view_certificate" msgid="1472768887529093862">"Mussar il certificat"</string>
+ <string name="ssl_untrusted" msgid="5369967226521102194">"Quest certificat n\'è betg vegnì emess dad in post da certificaziun fidà."</string>
+ <string name="ssl_mismatch" msgid="558688832420069896">"Il num da la website na correspunda betg al num sin il certificat."</string>
+ <string name="ssl_expired" msgid="5739349389499575559">"Quest certificat è scrudà."</string>
+ <string name="ssl_not_yet_valid" msgid="2893167846212645846">"Quest certificat n\'è anc betg valid."</string>
+ <string name="ssl_certificate" msgid="5226747157992111668">"Certificat da segirezza"</string>
+ <string name="ssl_certificate_is_valid" msgid="7096160815933145579">"Quest certificat è valid."</string>
+ <string name="issued_to" msgid="9032338008819841339">"Emess a:"</string>
+ <string name="common_name" msgid="5745530093500062357">"Num general:"</string>
+ <string name="org_name" msgid="8868889052889991293">"Organisaziun:"</string>
+ <string name="org_unit" msgid="4489056376307768196">"Unitad d\'organisaziun:"</string>
+ <string name="issued_by" msgid="6959484326943152487">"Emess da:"</string>
+ <string name="validity_period" msgid="57988851973181309">"Validitad:"</string>
+ <string name="issued_on" msgid="2082890654801808368">"Emess ils:"</string>
+ <string name="expires_on" msgid="8061200430557020704">"Scroda ils:"</string>
+ <string name="stopping" msgid="4839698519340302982">"Fermar…"</string>
+ <string name="stop" msgid="5687251076030630074">"Fermar"</string>
+ <string name="reload" msgid="8585220783228408062">"Actualisar"</string>
+ <string name="back" msgid="8414603107175713668">"Enavos"</string>
+ <string name="forward" msgid="4288210890526641577">"Vinavant"</string>
+ <string name="save" msgid="5922311934992468496">"OK"</string>
+ <string name="do_not_save" msgid="6777633870113477714">"Interrumper"</string>
+ <!-- no translation found for location (3411848697912600125) -->
+ <skip />
+ <!-- no translation found for containing_folder (6771180232953030479) -->
+ <skip />
+ <!-- no translation found for add_new_folder (7027600176450718398) -->
+ <skip />
+ <!-- no translation found for new_folder (7743540149088867917) -->
+ <skip />
+ <!-- no translation found for name (5915607427720935681) -->
+ <skip />
+ <string name="http" msgid="2163722670597250102">"http://"</string>
+ <!-- no translation found for save_to_bookmarks (6101482434920313244) -->
+ <skip />
+ <!-- no translation found for bookmark_this_page (7530739804320811054) -->
+ <skip />
+ <string name="edit_bookmark" msgid="5024089053490231905">"Modifitgar il segnapagina"</string>
+ <!-- no translation found for create_shortcut_bookmark (1995095662095484289) -->
+ <skip />
+ <string name="open_bookmark" msgid="8473581305759935790">"Avrir"</string>
+ <string name="remove_bookmark" msgid="8407495852801410891">"Stizzar il segnapagina"</string>
+ <string name="remove_from_bookmarks" msgid="4374080666576982775">"Stizzar dals segnapaginas"</string>
+ <string name="remove_history_item" msgid="5021424935726728618">"Stizzar da la cronologia"</string>
+ <string name="set_as_homepage" msgid="4752937379414905560">"Definir sco pagina da partenza"</string>
+ <string name="bookmark_saved" msgid="2766434679871317557">"Memorisà en ils segnapaginas."</string>
+ <string name="bookmark_not_saved" msgid="700600955089376724">"Impussibel da memorisar il segnapagina."</string>
+ <string name="homepage_set" msgid="8768087280310966395">"Definì ina pagina da partenza."</string>
+ <string name="bookmark_needs_title" msgid="6245900436119218187">"Il segnapagina sto avair in num."</string>
+ <string name="bookmark_needs_url" msgid="7809876865972755158">"Il segnapagina sto avair in lieu da memorisaziun."</string>
+ <string name="bookmark_url_not_valid" msgid="6719785633980202419">"La URL è nuncorrecta."</string>
+ <string name="bookmark_cannot_save_url" msgid="791722768778386941">"Impussibel d\'agiuntar questa URL a Voss segnapaginas."</string>
+ <string name="delete_bookmark" msgid="2422989994934201992">"Stizzar"</string>
+ <string name="bookmark_page" msgid="6845189305130307274">"Segnapagina per l\'ultima pagina visitada"</string>
+ <string name="switch_to_thumbnails" msgid="5493351529609043151">"Miniaturas"</string>
+ <string name="switch_to_list" msgid="8900531247982121055">"Vista da glista"</string>
+ <string name="current_page" msgid="7510129573681663135">"da "</string>
+ <string name="delete_bookmark_warning" msgid="758043186202032205">"\"Il segnapagina \"\"<xliff:g id="BOOKMARK">%s</xliff:g>\"\" vegn stizzà.\""</string>
+ <string name="open_in_new_window" msgid="6596775546468054510">"Avrir en ina nova fanestra"</string>
+ <string name="goto_dot" msgid="3895839050522602723">"Dai"</string>
+ <!-- no translation found for incognito_tab (5419458065370134289) -->
+ <skip />
+ <string name="select_dot" msgid="6299170761900561967">"Selecziunar text"</string>
+ <string name="tab_picker_title" msgid="864478399057782913">"Fanestras actualas"</string>
+ <string name="tab_picker_remove_tab" msgid="630087809802479397">"Serrar"</string>
+ <string name="bookmarks" msgid="1961279134885867815">"Segnapaginas"</string>
+ <string name="shortcut_bookmark" msgid="3974876480401135895">"Segnapagina"</string>
+ <string name="history" msgid="2451240511251410032">"Cronologia"</string>
+ <string name="menu_view_download" msgid="2124570321712995120">"Telechargiadas"</string>
+ <string name="copy_page_url" msgid="7635062169011319208">"Copiar la URL da la pagina"</string>
+ <string name="share_page" msgid="593756995297268343">"Barattar la pagina"</string>
+ <!-- no translation found for menu_save_webarchive (3934652434001459581) -->
+ <skip />
+ <!-- no translation found for webarchive_saved (7045250341467345007) -->
+ <skip />
+ <!-- no translation found for webarchive_failed (2880998204746620260) -->
+ <skip />
+ <string name="contextmenu_openlink" msgid="7237961252214188935">"Avrir"</string>
+ <string name="contextmenu_openlink_newwindow" msgid="992765050093960353">"Avrir en ina nova fanestra"</string>
+ <string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"Agiuntar la colliaziun als segnapaginas"</string>
+ <string name="contextmenu_savelink" msgid="5508554930832538184">"Memorisar la colliaziun"</string>
+ <string name="contextmenu_sharelink" msgid="5392275392280130331">"Barattar la colliaziun"</string>
+ <string name="contextmenu_copy" msgid="398860586635404030">"Copiar"</string>
+ <string name="contextmenu_copylink" msgid="5153657160294534270">"Copiar la URL da la colliaziun"</string>
+ <string name="contextmenu_download_image" msgid="4243829645180686912">"Memorisar il maletg"</string>
+ <string name="contextmenu_view_image" msgid="3870625602053600905">"Mussar il maletg"</string>
+ <string name="contextmenu_set_wallpaper" msgid="3691902960115350686">"Definir sco fund davos"</string>
+ <string name="contextmenu_dial_dot" msgid="5856550683415933806">"Cumponer..."</string>
+ <string name="contextmenu_add_contact" msgid="3183511922223645716">"Agiuntar in contact"</string>
+ <string name="contextmenu_send_mail" msgid="1014513374828775660">"Trametter in e-mail"</string>
+ <string name="contextmenu_map" msgid="7471390435434034912">"Charta"</string>
+ <string name="choosertitle_sharevia" msgid="4600490613341909086">"Cundivider cun agid da"</string>
+ <string name="clear" msgid="7070043081700011461">"Stizzar"</string>
+ <string name="replace" msgid="4843033491070384047">"Remplazzar"</string>
+ <string name="browser_bookmarks_page_bookmarks_text" msgid="6787605028726162673">"Segnapaginas"</string>
+ <string name="menu_preferences" msgid="6709237687234102240">"Parameters"</string>
+ <string name="pref_content_title" msgid="722227111894838633">"Parameters dal cuntegn da la pagina"</string>
+ <string name="pref_content_load_images" msgid="2125616852957377561">"Chargiar ils maletgs"</string>
+ <string name="pref_content_load_images_summary" msgid="5055874125248398584">"Mussar ils maletgs da las paginas web"</string>
+ <string name="pref_content_block_popups" msgid="7808433807197256726">"Bloccar las fanestras pop-up"</string>
+ <string name="pref_content_javascript" msgid="4570972030299516843">"Activar JavaScript"</string>
+ <string name="pref_content_open_in_background" msgid="824123779725118663">"Avrir davos las culissas"</string>
+ <string name="pref_content_plugins" msgid="7231944644794301582">"Activar ils plug-ins"</string>
+ <string-array name="pref_content_plugins_choices">
+ <item msgid="6745108155096660725">"Adina activ"</item>
+ <item msgid="2484126708670016519">"Sin dumonda"</item>
+ <item msgid="8547442717307793863">"Deactivà"</item>
+ </string-array>
+ <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"Avrir las novas fanestras davos la fanestra actuala"</string>
+ <string name="pref_content_homepage" msgid="6082437160778559806">"Definir la pagina da partenza"</string>
+ <!-- no translation found for pref_content_search_engine (1620101310821644144) -->
+ <skip />
+ <!-- no translation found for pref_content_search_engine_summary (5162667665858487316) -->
+ <skip />
+ <string name="pref_use_current" msgid="1493179933653044553">"Utilisar la pagina actuala"</string>
+ <string name="pref_content_autofit" msgid="8260474534053660809">"Adattar las paginas auto."</string>
+ <string name="pref_content_autofit_summary" msgid="4587831659894879986">"Adattar las paginas web al visur"</string>
+ <string name="pref_content_landscape_only" msgid="2022546812766219672">"Visualisaziun mo en il format orizontal"</string>
+ <string name="pref_content_landscape_only_summary" msgid="1008238895535428855">"Mussar las paginas mo en il format pli lad orizontal"</string>
+ <string name="pref_privacy_title" msgid="1052470980370846151">"Parameters da la protecziun da datas"</string>
+ <string name="pref_privacy_clear_cache" msgid="3380316479925886998">"Stizzar il cache"</string>
+ <string name="pref_privacy_clear_cache_summary" msgid="2216463577207991454">"Stizzar las bancas da datas ed il cuntegn ord il cache local"</string>
+ <string name="pref_privacy_clear_cache_dlg" msgid="5541011591300753881">"Las bancas da datas ed ils cuntegns en il cache local vegnan stizzads."</string>
+ <string name="pref_privacy_clear_cookies" msgid="3095583579133780331">"Stizzar tut ils cookies"</string>
+ <string name="pref_privacy_clear_cookies_summary" msgid="6962742063990677520">"Stizzar tut ils cookies dal navigatur"</string>
+ <string name="pref_privacy_clear_cookies_dlg" msgid="552855688091432682">"Tut ils cookies vegnan stizzads."</string>
+ <string name="pref_privacy_clear_history" msgid="8723795508825198477">"Stizzar la cronologia"</string>
+ <string name="pref_privacy_clear_history_summary" msgid="6868501330708940734">"Stizzar la cronologia dal navigatur"</string>
+ <string name="pref_privacy_clear_history_dlg" msgid="544903007914753853">"La cronologia dal navigatur vegn stizzada."</string>
+ <string name="pref_privacy_clear_form_data" msgid="4232668196344383987">"Stizzar datas da formular"</string>
+ <string name="pref_privacy_clear_form_data_summary" msgid="1790390894719517167">"Stizzar tut las datas da formular memorisadas"</string>
+ <string name="pref_privacy_clear_form_data_dlg" msgid="4443621086781197928">"Tut las datas da formulars memorisadas vegnan stizzadas."</string>
+ <string name="pref_privacy_clear_passwords" msgid="4750234112289277480">"Stizzar ils pleds-clav"</string>
+ <string name="pref_privacy_clear_passwords_summary" msgid="8856782718942903335">"Stizzar tut ils pleds-clav memorisads"</string>
+ <string name="pref_privacy_clear_passwords_dlg" msgid="2083869328824248255">"Tut ils pleds-clav memorisads vegnan stizzads."</string>
+ <string name="pref_privacy_enable_geolocation" msgid="1395040170290765686">"Activar la posiziun"</string>
+ <string name="pref_privacy_enable_geolocation_summary" msgid="8437020934664306205">"Autorisar las websites da dumandar l\'access a Vossa posiziun"</string>
+ <string name="pref_privacy_clear_geolocation_access" msgid="6649680770030042980">"Stizzar l\'access a datas da posiziun"</string>
+ <string name="pref_privacy_clear_geolocation_access_summary" msgid="7750143359497314679">"Stizzar l\'access a datas da posiziun per tut las websites."</string>
+ <string name="pref_privacy_clear_geolocation_access_dlg" msgid="7327063124488827244">"Stizzar l\'access a datas da posiziun per tut las websites"</string>
+ <string name="pref_security_title" msgid="5763978646932160021">"Parameters da segirezza"</string>
+ <string name="pref_security_remember_passwords" msgid="6492957683454529549">"Memorisar ils pleds-clav"</string>
+ <string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"Memorisar ils nums d\'utilisader ed ils pleds-clav per las websites"</string>
+ <string name="pref_security_save_form_data" msgid="1213669802810198893">"Memorisar las datas da formular"</string>
+ <string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"Memorisar las datas endatadas en formulars per reutilisar ellas"</string>
+ <!-- no translation found for pref_autoFill_enabled (5348131327347999291) -->
+ <skip />
+ <!-- no translation found for pref_autoFill_enabled_summary (282122852215557397) -->
+ <skip />
+ <string name="pref_security_show_security_warning" msgid="8901135676266754559">"Avertiments da segirezza"</string>
+ <string name="pref_security_show_security_warning_summary" msgid="8968906112720511704">"Mussar in avertiment en cas da problems da segirezza cun ina website"</string>
+ <string name="pref_security_accept_cookies" msgid="3201367661925047989">"Acceptar cookies"</string>
+ <string name="pref_security_accept_cookies_summary" msgid="1465118934875026920">"Permetter a las websites da memorisar e leger cookies"</string>
+ <string name="pref_text_size" msgid="3827031324346612208">"Grondezza dal text"</string>
+ <string-array name="pref_text_size_choices">
+ <item msgid="4952686548944739548">"Fitg pitschna"</item>
+ <item msgid="1950030433642671460">"Pitschna"</item>
+ <item msgid="4338347520133294584">"Normala"</item>
+ <item msgid="5043128215356351184">"Gronda"</item>
+ <item msgid="7201512237890458902">"Fitg grond"</item>
+ </string-array>
+ <string name="pref_text_size_dialogtitle" msgid="3625388833512647865">"Grondezza dal text"</string>
+ <string name="pref_default_zoom" msgid="8076142259097187395">"Zoom predefinì"</string>
+ <string-array name="pref_default_zoom_choices">
+ <item msgid="549583171195154919">"Lontan"</item>
+ <item msgid="5619034257768161024">"Mesauna"</item>
+ <item msgid="3840999588443167001">"Damanaivel"</item>
+ </string-array>
+ <string name="pref_default_zoom_dialogtitle" msgid="6095974367125109021">"Zoom predefinì"</string>
+ <string name="pref_content_load_page" msgid="2219810141690955452">"Avrir las paginas en la survista"</string>
+ <string name="pref_content_load_page_summary" msgid="8792093504054149369">"Mussar ina survista da las paginas novas"</string>
+ <string name="pref_extras_title" msgid="3091250467679722382">"Parameters avanzads"</string>
+ <string name="pref_extras_website_settings" msgid="67866640052455549">"Parameters per websites"</string>
+ <string name="pref_extras_website_settings_summary" msgid="1656771443223494406">"Parameters avanzads per singulas websites"</string>
+ <string name="pref_extras_reset_default" msgid="8904000515846202110">"Reinizialisar il standard"</string>
+ <string name="pref_extras_reset_default_summary" msgid="4247870778270414501">"Restaurar ils parameters predefinids"</string>
+ <string name="pref_extras_reset_default_dlg" msgid="6640261575874704022">"Ils parameters da standard vegnan restituids."</string>
+ <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Restituir las valurs predefinidas"</string>
+ <string name="pref_development_title" msgid="3263854204533056480">"Debugar"</string>
+ <string name="pref_default_text_encoding" msgid="5742965543955558478">"Codaziun dal text"</string>
+ <!-- no translation found for pref_default_text_encoding_choices:7 (2193955365569270096) -->
+ <string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Codaziun dal text"</string>
+ <string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Problem da connectivitad da datas"</string>
+ <string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Problem da datoteca"</string>
+ <string name="browserFrameFormResubmitLabel" msgid="2685923472682180360">"Confermar"</string>
+ <string name="browserFrameFormResubmitMessage" msgid="2752182215695632138">"La pagina che Vus vulais laschar mussar cuntegna datas ch\'èn gia vegnidas tramessas («POSTDATA»). Sche Vus tramettais danovamain las datas vegn mintga acziun ch\'il formular da la pagina ha exequì repetida (sco per exempel ina tschertga u ina cumpra online)."</string>
+ <string name="loadSuspendedTitle" msgid="675991625288706944">"Nagina connexiun da rait"</string>
+ <string name="loadSuspended" msgid="3133656588880851273">"Impussibel da chargiar questa pagina en il navigatur senza connexiun a l\'internet."</string>
+ <string name="clear_history" msgid="5998307092715979619">"Stizzar la cronologia"</string>
+ <string name="browser_history" msgid="1038987118290272525">"Paginas visitadas dacurt"</string>
+ <string name="empty_history" msgid="8738772352308207274">"La cronologia è vida."</string>
+ <string name="add_new_bookmark" msgid="8086367791400349049">"Agiuntar in segnapagina…"</string>
+ <string name="add_bookmark_short" msgid="3783984330998103735">"Agiuntar"</string>
+ <string name="search_hint" msgid="4647356319916631820">"Tschertgar u endatar ina URL"</string>
+ <string name="search_button_text" msgid="5235226933877634410">"Dai"</string>
+ <string name="search_settings_description" msgid="1422401062529014107">"Segnapaginas e cronologia web"</string>
+ <string name="attention" msgid="3473639060042811244">"Attenziun"</string>
+ <string name="popup_window_attempt" msgid="2673111696288657989">"Questa website emprova dad avrir ina fanestra pop-up."</string>
+ <string name="allow" msgid="1157313689171991335">"Permetter"</string>
+ <string name="block" msgid="9172175889884707800">"Bloccar"</string>
+ <string name="too_many_windows_dialog_title" msgid="5175503564948906442">"Cuntanschì la limita da fanestras"</string>
+ <string name="too_many_windows_dialog_message" msgid="1398571800233959583">"Impussibel dad avrir ina nova fanestra. Il dumber maximal da fanestras avertas è cuntanschì."</string>
+ <string name="too_many_subwindows_dialog_title" msgid="3805453941587725944">"La fanestra pop-up è gia averta"</string>
+ <string name="too_many_subwindows_dialog_message" msgid="5827289829907966657">"Impussibel d\'avrir ina nova fanestra. Ina unica fanestra po esser averta a la giada."</string>
+ <string name="download_title" msgid="2122874021047565594">"Cronologia da telechargiadas"</string>
+ <string name="download_unknown_filename" msgid="4013465542563652175">"<Nunenconuschent>"</string>
+ <string name="download_menu_open" msgid="4888327480367757513">"Avrir"</string>
+ <string name="download_menu_clear" msgid="6264454531553418124">"Stizzar da la glista"</string>
+ <string name="download_menu_delete" msgid="8815502136393894148">"Stizzar"</string>
+ <string name="download_menu_cancel" msgid="2545333007601851574">"Interrumper la telechargiada"</string>
+ <string name="download_menu_cancel_all" msgid="2136550823151999166">"Interrumper tut las telechargiadas"</string>
+ <string name="download_cancel_dlg_title" msgid="8909108500262799748">"Interrumper las telechargiadas"</string>
+ <string name="download_cancel_dlg_msg" msgid="6285389170052357797">"Las <xliff:g id="DOWNLOAD_COUNT">%d</xliff:g> telechargiadas vegnan annulladas e stizzadas da la cronologia da telechargiadas."</string>
+ <string name="download_delete_file" msgid="5330036497843073249">"La datoteca vegn stizzada."</string>
+ <string name="download_file_error_dlg_title" msgid="2693630283595384874">"Capacitad da memorisar nunsuffizienta"</string>
+ <string name="download_file_error_dlg_msg" msgid="5156405410324072471">"Impussibel da telechargiar <xliff:g id="FILENAME">%s</xliff:g>."\n"Rumi la memoria da Voss telefon ed empruvai anc ina giada."</string>
+ <string name="download_failed_generic_dlg_title" msgid="6106781095337833391">"Telechargiada betg reussida"</string>
+ <string name="download_no_sdcard_dlg_title" msgid="605904452159416792">"Nagina carta SD"</string>
+ <string name="download_no_sdcard_dlg_msg" msgid="2616399456116301518">"Per telechargiar <xliff:g id="FILENAME">%s</xliff:g> è necessaria ina carta SD."</string>
+ <string name="download_sdcard_busy_dlg_title" msgid="6877712666046917741">"Carta SD betg disponibla"</string>
+ <string name="download_sdcard_busy_dlg_msg" msgid="3473883538192835204">"La carta SD è occupada. Tscherni «Deactivar la memoria USB» en l\'avis per permetter telechargiadas."</string>
+ <string name="download_no_application_title" msgid="1286056729168874295">"Impussibel dad avrir la datoteca"</string>
+ <string name="retry" msgid="1835923075542266721">"Repeter"</string>
+ <string name="no_downloads" msgid="3947445710685021498">"La cronologia da telechargiadas è vida."</string>
+ <string name="download_error" msgid="413496839831257187">"La telechargiada n\'è betg reussida."</string>
+ <string name="download_success" msgid="2279041638155595203">"Terminà la telechargiada da <xliff:g id="FILE">%s</xliff:g>."</string>
+ <string name="download_running" msgid="2622942231322015059">"Telechargiada en process…"</string>
+ <string name="download_pending" msgid="2599683668575349559">"Cumenzar la telechargiada…"</string>
+ <string name="download_pending_network" msgid="6548714525679461053">"Spetgar ina connexiun da datas…"</string>
+ <string name="download_running_paused" msgid="6418029352085656495">"Spetgar la connexiun da datas…"</string>
+ <string name="download_canceled" msgid="6057083743144492515">"Telechargiada interrutta."</string>
+ <string name="download_not_acceptable" msgid="313769696131563652">"Impussibel da telechargiar. Il cuntegn na vegn betg sustegnì da quest telefon."</string>
+ <string name="download_file_error" msgid="1206648050615176113">"Impussibel da terminar la telechargiada. La capacitad da memorisar è nunsuffizienta."</string>
+ <string name="download_length_required" msgid="9038605488460437406">"Impussibel da cumenzar a telechargiar. La grondezza da l\'element na po betg vegnir distinguida."</string>
+ <string name="download_precondition_failed" msgid="8327584102874295580">"La telechargiada è vegnida interrutta e na po betg vegnir cuntinuada."</string>
+ <!-- no translation found for search_the_web (6046130189241962337) -->
+ <skip />
+ <!-- no translation found for webstorage_outofspace_notification_title (1160474608059771788) -->
+ <skip />
+ <string name="webstorage_outofspace_notification_text" msgid="7341075135051829692">"Cliccai qua per gudagnar capacitad da memorisar."</string>
+ <string name="webstorage_clear_data_title" msgid="689484577124333977">"Stizzar las datas memorisadas"</string>
+ <string name="webstorage_clear_data_dialog_title" msgid="345457466368974706">"Stizzar las datas memorisadas"</string>
+ <string name="webstorage_clear_data_dialog_message" msgid="6678281256970470125">"Tut las datas memorisadas da questa website vegnan stizzadas."</string>
+ <string name="webstorage_clear_data_dialog_ok_button" msgid="2516563534211898636">"Stizzar tut"</string>
+ <string name="webstorage_clear_data_dialog_cancel_button" msgid="2028867751958942762">"Interrumper"</string>
+ <string name="webstorage_origin_summary_mb_stored" msgid="1985885826292236210">"MB memorisads sin Voss telefon"</string>
+ <string name="loading_video" msgid="4887871585216091096">"Chargiar il video"</string>
+ <string name="geolocation_permissions_prompt_message" msgid="356796102004052471">"<xliff:g id="WEBSITE_ORIGIN">%s</xliff:g> vul savair Vossa posiziun geografica."</string>
+ <string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Tradir mia posiziun"</string>
+ <string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Refusar"</string>
+ <string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Memorisar las preferenzas"</string>
+ <string name="geolocation_permissions_prompt_toast_allowed" msgid="987286072035125498">"Questa website ha access a Vossa posiziun. Modifitgai questa opziun en Parameters -> Parameters da la website"</string>
+ <string name="geolocation_permissions_prompt_toast_disallowed" msgid="7695100950212692515">"Questa pagina n\'ha betg access a Vossa posiziun. Midai questa opziun en Parameters -> Parameters da la website"</string>
+ <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Stizzar l\'access a la posiziun"</string>
+ <string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Questa website ha actualmain access a Vossa posiziun"</string>
+ <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Questa website n\'ha per il mument betg access a Vossa posiziun."</string>
+ <string name="geolocation_settings_page_dialog_title" msgid="1549842043381347668">"Stizzar l\'access a datas da posiziun"</string>
+ <string name="geolocation_settings_page_dialog_message" msgid="7586671987576403993">"L\'access da questa website a datas da posiziun vegn stizzà."</string>
+ <string name="geolocation_settings_page_dialog_ok_button" msgid="4789434178048077287">"Stizzar l\'access"</string>
+ <string name="geolocation_settings_page_dialog_cancel_button" msgid="7941036504673409747">"Interrumper"</string>
+ <string name="website_settings_clear_all" msgid="8739804325997655980">"Stizzar tut"</string>
+ <string name="website_settings_clear_all_dialog_title" msgid="7791826325122461718">"Stizzar tut ils parameters da la website?"</string>
+ <string name="website_settings_clear_all_dialog_message" msgid="6150502090601476333">"Tut las datas da la website e las autorisaziuns da posiziun vegnan stizzadas."</string>
+ <string name="website_settings_clear_all_dialog_ok_button" msgid="6401582240627669431">"Stizzar tut las datas"</string>
+ <string name="website_settings_clear_all_dialog_cancel_button" msgid="1896757051856611674">"Interrumper"</string>
+ <string name="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Il maletg dal fund davos vegn endrizzà…"</string>
+ <!-- no translation found for defaultBookmarksUpButton (2303951020715704735) -->
+ <skip />
+ <!-- no translation found for empty_bookmarks_folder (7843361614634930942) -->
+ <skip />
+ <!-- no translation found for rlz_access_point (7165847807377650632) -->
+ <skip />
+</resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 168d03e..a4999ac 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -19,6 +19,7 @@
<string name="application_name" msgid="1935869255545976415">"Браузер"</string>
<string name="choose_upload" msgid="3649366287575002063">"Выберите файл для загрузки"</string>
<string name="new_tab" msgid="4505722538297295141">"Новое окно"</string>
+ <string name="new_incognito_tab" msgid="5821404839654751753">"Новое окно в режиме инкогнито"</string>
<string name="active_tabs" msgid="3050623868203544623">"Окна"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Закладки"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"Часто посещаемые"</string>
@@ -32,12 +33,6 @@
<string name="bookmarks_search" msgid="5229596268214362873">"Браузер"</string>
<string name="cancel" msgid="3017274947407233702">"Отмена"</string>
<string name="ok" msgid="1509280796718850364">"ОК"</string>
- <plurals name="matches_found">
- <item quantity="zero" msgid="6242659159545399963">"Соответствий нет"</item>
- <item quantity="one" msgid="4352019729062956802">"1 соответствие"</item>
- <item quantity="few" msgid="5544267486978946555">"Соответствий: <xliff:g id="NUMBER">%d</xliff:g>"</item>
- <item quantity="other" msgid="6616125067364315405">"Соответствий: <xliff:g id="NUMBER">%d</xliff:g>"</item>
- </plurals>
<string name="title_bar_loading" msgid="7438217780834640678">"Загрузка…"</string>
<string name="page_info" msgid="4048529256302257195">"Информация о странице"</string>
<string name="page_info_view" msgid="5303490449842635158">"Информация о странице"</string>
@@ -67,12 +62,23 @@
<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>
- <string name="name" msgid="5990326151488445481">"Имя"</string>
+ <!-- no translation found for location (3411848697912600125) -->
+ <skip />
+ <!-- no translation found for containing_folder (6771180232953030479) -->
+ <skip />
+ <!-- no translation found for add_new_folder (7027600176450718398) -->
+ <skip />
+ <!-- no translation found for new_folder (7743540149088867917) -->
+ <skip />
+ <!-- no translation found for name (5915607427720935681) -->
+ <skip />
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Добавить закладку"</string>
+ <string name="save_to_bookmarks" msgid="6101482434920313244">"Добавить в Закладки"</string>
+ <!-- no translation found for bookmark_this_page (7530739804320811054) -->
+ <skip />
<string name="edit_bookmark" msgid="5024089053490231905">"Изменить закладку"</string>
- <string name="create_shortcut_bookmark" msgid="9202323987633899835">"Добавить ярлык на главную страницу"</string>
+ <!-- no translation found for create_shortcut_bookmark (1995095662095484289) -->
+ <skip />
<string name="open_bookmark" msgid="8473581305759935790">"Открыть"</string>
<string name="remove_bookmark" msgid="8407495852801410891">"Удалить закладку"</string>
<string name="remove_from_bookmarks" msgid="4374080666576982775">"Удалить из закладок"</string>
@@ -93,7 +99,7 @@
<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="goto_dot" msgid="3895839050522602723">"Поиск"</string>
- <string name="find_dot" msgid="6259312434696611957">"Найти на странице"</string>
+ <string name="incognito_tab" msgid="5419458065370134289">"Открыть новую вкладку в режиме инкогнито"</string>
<string name="select_dot" msgid="6299170761900561967">"Выбрать текст"</string>
<string name="tab_picker_title" msgid="864478399057782913">"Открытые окна"</string>
<string name="tab_picker_remove_tab" msgid="630087809802479397">"Закрыть"</string>
@@ -103,6 +109,9 @@
<string name="menu_view_download" msgid="2124570321712995120">"Загрузки"</string>
<string name="copy_page_url" msgid="7635062169011319208">"Копировать URL страницы"</string>
<string name="share_page" msgid="593756995297268343">"Отправить страницу"</string>
+ <string name="menu_save_webarchive" msgid="3934652434001459581">"Сохранить как веб-архив"</string>
+ <string name="webarchive_saved" msgid="7045250341467345007">"Веб-архив сохранен."</string>
+ <string name="webarchive_failed" msgid="2880998204746620260">"Не удалось сохранить веб-архив."</string>
<string name="contextmenu_openlink" msgid="7237961252214188935">"Открыть"</string>
<string name="contextmenu_openlink_newwindow" msgid="992765050093960353">"Открыть в новом окне"</string>
<string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"Добавить ссылку в закладки"</string>
@@ -169,6 +178,10 @@
<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>
+ <!-- no translation found for pref_autoFill_enabled (5348131327347999291) -->
+ <skip />
+ <!-- no translation found for pref_autoFill_enabled_summary (282122852215557397) -->
+ <skip />
<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>
@@ -208,6 +221,7 @@
<item msgid="891615911084608570">"Японская (ISO-2022-JP)"</item>
<item msgid="5589150448475151241">"Японская (SHIFT_JIS)"</item>
<item msgid="7356792686950371843">"Японская (EUC-JP)"</item>
+ <item msgid="2193955365569270096">"Корейская (EUC-KR)"</item>
</string-array>
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Кодировка текста"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Проблема с подключением"</string>
@@ -292,4 +306,8 @@
<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="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Установка фонового рисунка..."</string>
+ <string name="defaultBookmarksUpButton" msgid="2303951020715704735">"Закладки"</string>
+ <!-- no translation found for empty_bookmarks_folder (7843361614634930942) -->
+ <skip />
+ <string name="rlz_access_point" msgid="7165847807377650632">"Y1"</string>
</resources>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index d140503..af4ea57 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -19,6 +19,7 @@
<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="new_incognito_tab" msgid="5821404839654751753">"Nytt inkognitofönster"</string>
<string name="active_tabs" msgid="3050623868203544623">"Fönster"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Bokmärken"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"Mest besökta"</string>
@@ -32,12 +33,6 @@
<string name="bookmarks_search" msgid="5229596268214362873">"Webbläsare"</string>
<string name="cancel" msgid="3017274947407233702">"Avbryt"</string>
<string name="ok" msgid="1509280796718850364">"OK"</string>
- <plurals name="matches_found">
- <item quantity="zero" msgid="6242659159545399963">"Inga träffar"</item>
- <item quantity="one" msgid="4352019729062956802">"1 träff"</item>
- <item quantity="few" msgid="5544267486978946555">"<xliff:g id="NUMBER">%d</xliff:g> träffar"</item>
- <item quantity="other" msgid="6616125067364315405">"<xliff:g id="NUMBER">%d</xliff:g> träffar"</item>
- </plurals>
<string name="title_bar_loading" msgid="7438217780834640678">"Hämtar…"</string>
<string name="page_info" msgid="4048529256302257195">"Sidinformation"</string>
<string name="page_info_view" msgid="5303490449842635158">"Visa sidinformation"</string>
@@ -67,12 +62,23 @@
<string name="forward" msgid="4288210890526641577">"Framåt"</string>
<string name="save" msgid="5922311934992468496">"OK"</string>
<string name="do_not_save" msgid="6777633870113477714">"Avbryt"</string>
- <string name="location" msgid="969988560160364559">"Plats"</string>
- <string name="name" msgid="5990326151488445481">"Namn"</string>
+ <!-- no translation found for location (3411848697912600125) -->
+ <skip />
+ <!-- no translation found for containing_folder (6771180232953030479) -->
+ <skip />
+ <!-- no translation found for add_new_folder (7027600176450718398) -->
+ <skip />
+ <!-- no translation found for new_folder (7743540149088867917) -->
+ <skip />
+ <!-- no translation found for name (5915607427720935681) -->
+ <skip />
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Lägg till bokmärke"</string>
+ <string name="save_to_bookmarks" msgid="6101482434920313244">"Lägg till i bokmärken"</string>
+ <!-- no translation found for bookmark_this_page (7530739804320811054) -->
+ <skip />
<string name="edit_bookmark" msgid="5024089053490231905">"Redigera bokmärke"</string>
- <string name="create_shortcut_bookmark" msgid="9202323987633899835">"Lägg till genväg till startsidan"</string>
+ <!-- no translation found for create_shortcut_bookmark (1995095662095484289) -->
+ <skip />
<string name="open_bookmark" msgid="8473581305759935790">"Öppna"</string>
<string name="remove_bookmark" msgid="8407495852801410891">"Ta bort bokmärke"</string>
<string name="remove_from_bookmarks" msgid="4374080666576982775">"Ta bort från bokmärken"</string>
@@ -90,10 +96,10 @@
<string name="switch_to_thumbnails" msgid="5493351529609043151">"Miniatyrvy"</string>
<string name="switch_to_list" msgid="8900531247982121055">"Listvy"</string>
<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="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="goto_dot" msgid="3895839050522602723">"Kör"</string>
- <string name="find_dot" msgid="6259312434696611957">"Sök på sidan"</string>
+ <string name="incognito_tab" msgid="5419458065370134289">"Öppna ny inkognitoflik"</string>
<string name="select_dot" msgid="6299170761900561967">"Markera text"</string>
<string name="tab_picker_title" msgid="864478399057782913">"Aktuellt fönster"</string>
<string name="tab_picker_remove_tab" msgid="630087809802479397">"Stäng"</string>
@@ -103,6 +109,9 @@
<string name="menu_view_download" msgid="2124570321712995120">"Hämtningar"</string>
<string name="copy_page_url" msgid="7635062169011319208">"Kopiera sidans webbadress"</string>
<string name="share_page" msgid="593756995297268343">"Dela sida"</string>
+ <string name="menu_save_webarchive" msgid="3934652434001459581">"Spara som webbarkiv"</string>
+ <string name="webarchive_saved" msgid="7045250341467345007">"Webbarkivet har sparats"</string>
+ <string name="webarchive_failed" msgid="2880998204746620260">"Det gick inte att spara webbarkivet."</string>
<string name="contextmenu_openlink" msgid="7237961252214188935">"Öppna"</string>
<string name="contextmenu_openlink_newwindow" msgid="992765050093960353">"Öppna i nytt fönster"</string>
<string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"Skapa ett bokmärke av länken"</string>
@@ -169,6 +178,10 @@
<string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"Spara användarnamn och lösenord för webbplatser"</string>
<string name="pref_security_save_form_data" msgid="1213669802810198893">"Spara formulärdata"</string>
<string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"Kom ihåg data som jag anger i formulär för senare bruk"</string>
+ <!-- no translation found for pref_autoFill_enabled (5348131327347999291) -->
+ <skip />
+ <!-- no translation found for pref_autoFill_enabled_summary (282122852215557397) -->
+ <skip />
<string name="pref_security_show_security_warning" msgid="8901135676266754559">"Visa säkerhetsvarningar"</string>
<string name="pref_security_show_security_warning_summary" msgid="8968906112720511704">"Visa varningar om det uppstår problem med en webbplats säkerhet"</string>
<string name="pref_security_accept_cookies" msgid="3201367661925047989">"Acceptera cookies"</string>
@@ -208,6 +221,7 @@
<item msgid="891615911084608570">"Japansk (ISO-2022-JP)"</item>
<item msgid="5589150448475151241">"Japansk (SHIFT_JIS)"</item>
<item msgid="7356792686950371843">"Japansk (EUC-JP)"</item>
+ <item msgid="2193955365569270096">"koreanska (EUC-KR)"</item>
</string-array>
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Textkodning"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Problem med dataanslutning"</string>
@@ -292,4 +306,8 @@
<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="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Anger bakgrund..."</string>
+ <string name="defaultBookmarksUpButton" msgid="2303951020715704735">"Bokmärken"</string>
+ <!-- no translation found for empty_bookmarks_folder (7843361614634930942) -->
+ <skip />
+ <string name="rlz_access_point" msgid="7165847807377650632">"Y1"</string>
</resources>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index a041aa3..1ac1fe9 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -19,6 +19,7 @@
<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="new_incognito_tab" msgid="5821404839654751753">"Yeni gizli pencere"</string>
<string name="active_tabs" msgid="3050623868203544623">"Pencereler"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Favoriler"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"En çok ziyaret edilenler"</string>
@@ -32,12 +33,6 @@
<string name="bookmarks_search" msgid="5229596268214362873">"Tarayıcı"</string>
<string name="cancel" msgid="3017274947407233702">"İptal"</string>
<string name="ok" msgid="1509280796718850364">"Tamam"</string>
- <plurals name="matches_found">
- <item quantity="zero" msgid="6242659159545399963">"Eşleşme yok"</item>
- <item quantity="one" msgid="4352019729062956802">"1 eşleşme"</item>
- <item quantity="few" msgid="5544267486978946555">"<xliff:g id="NUMBER">%d</xliff:g> eşleşme"</item>
- <item quantity="other" msgid="6616125067364315405">"<xliff:g id="NUMBER">%d</xliff:g> eşleşme"</item>
- </plurals>
<string name="title_bar_loading" msgid="7438217780834640678">"Yükleniyor…"</string>
<string name="page_info" msgid="4048529256302257195">"Sayfa bilgileri"</string>
<string name="page_info_view" msgid="5303490449842635158">"Sayfa bilgilerini görüntüle"</string>
@@ -67,12 +62,23 @@
<string name="forward" msgid="4288210890526641577">"İleri"</string>
<string name="save" msgid="5922311934992468496">"Tamam"</string>
<string name="do_not_save" msgid="6777633870113477714">"İptal"</string>
- <string name="location" msgid="969988560160364559">"Konum"</string>
- <string name="name" msgid="5990326151488445481">"Ad"</string>
+ <!-- no translation found for location (3411848697912600125) -->
+ <skip />
+ <!-- no translation found for containing_folder (6771180232953030479) -->
+ <skip />
+ <!-- no translation found for add_new_folder (7027600176450718398) -->
+ <skip />
+ <!-- no translation found for new_folder (7743540149088867917) -->
+ <skip />
+ <!-- no translation found for name (5915607427720935681) -->
+ <skip />
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Favori ekle"</string>
+ <string name="save_to_bookmarks" msgid="6101482434920313244">"Yer İşaretlerine Ekle"</string>
+ <!-- no translation found for bookmark_this_page (7530739804320811054) -->
+ <skip />
<string name="edit_bookmark" msgid="5024089053490231905">"Favorileri düzenle"</string>
- <string name="create_shortcut_bookmark" msgid="9202323987633899835">"Ana ekrana kısayol ekle"</string>
+ <!-- no translation found for create_shortcut_bookmark (1995095662095484289) -->
+ <skip />
<string name="open_bookmark" msgid="8473581305759935790">"Aç"</string>
<string name="remove_bookmark" msgid="8407495852801410891">"Favoriyi sil"</string>
<string name="remove_from_bookmarks" msgid="4374080666576982775">"Favorilerden kaldır"</string>
@@ -93,7 +99,7 @@
<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="goto_dot" msgid="3895839050522602723">"Git"</string>
- <string name="find_dot" msgid="6259312434696611957">"Sayfada bul"</string>
+ <string name="incognito_tab" msgid="5419458065370134289">"Yeni gizli sekme aç"</string>
<string name="select_dot" msgid="6299170761900561967">"Metin seç"</string>
<string name="tab_picker_title" msgid="864478399057782913">"Geçerli pencereler"</string>
<string name="tab_picker_remove_tab" msgid="630087809802479397">"Kapat"</string>
@@ -103,6 +109,9 @@
<string name="menu_view_download" msgid="2124570321712995120">"İndirme işlemleri"</string>
<string name="copy_page_url" msgid="7635062169011319208">"Sayfa url\'sini kopyala"</string>
<string name="share_page" msgid="593756995297268343">"Sayfayı paylaş"</string>
+ <string name="menu_save_webarchive" msgid="3934652434001459581">"Web Arşivi olarak Kaydet"</string>
+ <string name="webarchive_saved" msgid="7045250341467345007">"Web arşivi kaydedildi."</string>
+ <string name="webarchive_failed" msgid="2880998204746620260">"Web arşivi kaydedilemedi."</string>
<string name="contextmenu_openlink" msgid="7237961252214188935">"Aç"</string>
<string name="contextmenu_openlink_newwindow" msgid="992765050093960353">"Yeni pencerede aç"</string>
<string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"Favori bağlantısı"</string>
@@ -169,6 +178,10 @@
<string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"Web siteleri için kullanıcı adlarını ve şifreleri kaydet"</string>
<string name="pref_security_save_form_data" msgid="1213669802810198893">"Form verilerini hatırla"</string>
<string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"Daha sonra kullanmak üzere formlara yazdığım verileri hatırla"</string>
+ <!-- no translation found for pref_autoFill_enabled (5348131327347999291) -->
+ <skip />
+ <!-- no translation found for pref_autoFill_enabled_summary (282122852215557397) -->
+ <skip />
<string name="pref_security_show_security_warning" msgid="8901135676266754559">"Güvenlik uyarıl. göster"</string>
<string name="pref_security_show_security_warning_summary" msgid="8968906112720511704">"Site güvenliği ile ilgili bir sorun varsa uyarı göster"</string>
<string name="pref_security_accept_cookies" msgid="3201367661925047989">"Çerezleri kabul et"</string>
@@ -208,6 +221,7 @@
<item msgid="891615911084608570">"Japonca (ISO-2022-JP)"</item>
<item msgid="5589150448475151241">"Japonca (SHIFT_JIS)"</item>
<item msgid="7356792686950371843">"Japonca (EUC-JP)"</item>
+ <item msgid="2193955365569270096">"Korece (EUC-KR)"</item>
</string-array>
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Metin kodlama"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Veri bağlantısı sorunu"</string>
@@ -292,4 +306,8 @@
<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="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"Duvar kağıdı ayarlanıyor..."</string>
+ <string name="defaultBookmarksUpButton" msgid="2303951020715704735">"Yer işaretleri"</string>
+ <!-- no translation found for empty_bookmarks_folder (7843361614634930942) -->
+ <skip />
+ <string name="rlz_access_point" msgid="7165847807377650632">"Y1"</string>
</resources>
diff --git a/res/values-xlarge/dimensions.xml b/res/values-xlarge/dimensions.xml
new file mode 100644
index 0000000..602da0e
--- /dev/null
+++ b/res/values-xlarge/dimensions.xml
@@ -0,0 +1,16 @@
+<?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:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <dimen name="bookmarkThumbnailWidth">160dip</dimen>
+ <dimen name="bookmarkThumbnailHeight">180dip</dimen>
+</resources>
\ No newline at end of file
diff --git a/res/values-xlarge/styles.xml b/res/values-xlarge/styles.xml
new file mode 100644
index 0000000..375e3c6
--- /dev/null
+++ b/res/values-xlarge/styles.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ *
+ * Copyright 2006,2007,2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources>
+ <style name="BrowserTheme" parent="@android:Theme.Holo">
+ <item name="android:windowBackground">@color/white</item>
+ <item name="android:colorBackground">#FFFFFFFF</item>
+ <item name="android:windowActionBar">true</item>
+ <item name="android:windowNoTitle">false</item>
+ <item name="android:actionBarStyle">@style/ActionBarStyle</item>
+ <item name="android:windowContentOverlay">@null</item>
+ <item name="android:actionModeBackground">@drawable/cab_bg</item>
+ <item name="android:actionModeCloseDrawable">@drawable/ic_menu_cab_close</item>
+ <item name="android:actionButtonStyle">@style/ActionButton</item>
+ <item name="android:popupMenuStyle">@style/ActionDropdown</item>
+ <item name="android:actionOverflowButtonStyle">@style/Overflow</item>
+ </style>
+ <style name="Dialog.Holo" parent="android:Theme.Holo">
+ <item name="android:windowFrame">@null</item>
+ <item name="android:windowBackground">@drawable/dialog_full</item>
+ <item name="android:windowIsFloating">true</item>
+ <item name="android:windowContentOverlay">@null</item>
+ <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
+ <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
+ <item name="android:colorBackgroundCacheHint">@null</item>
+ </style>
+ <style name="BookmarkTheme" parent="@android:Theme.Panel">
+ <item name="android:windowBackground">@color/black</item>
+ </style>
+ <style name="ShortCutTheme" parent="@android:Theme.Holo">
+ <item name="android:windowContentOverlay">@null</item>
+ </style>
+ <style name="ActionBarStyle">
+ <item name="android:height">48dip</item>
+ <item name="android:padding">0dip</item>
+ <item name="android:background">@drawable/tabbar_bg</item>
+ <item name="android:displayOptions">hideHome</item>
+ </style>
+ <style name="ActionButton">
+ <item name="android:height">12dip</item>
+ <item name="android:background">@drawable/browserbarbutton</item>
+ </style>
+ <style name="ActionDropdown" parent="@android:style/Widget.PopupMenu">
+ <item name="android:background">@drawable/menu_dropdown</item>
+ </style>
+ <style name="Overflow">
+ <item name="android:src">@drawable/ic_menu_overflow</item>
+ <item name="android:paddingLeft">16dip</item>
+ <item name="android:paddingRight">16dip</item>
+ </style>
+ <style name="TitleBar">
+ <item name="android:windowEnterAnimation">@anim/title_bar_enter</item>
+ <item name="android:windowExitAnimation">@anim/title_bar_exit</item>
+ </style>
+</resources>
+
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 82e1ccc..c312ed2 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -19,6 +19,7 @@
<string name="application_name" msgid="1935869255545976415">"浏览器"</string>
<string name="choose_upload" msgid="3649366287575002063">"选择要上传的文件"</string>
<string name="new_tab" msgid="4505722538297295141">"新窗口"</string>
+ <string name="new_incognito_tab" msgid="5821404839654751753">"新隐身窗口"</string>
<string name="active_tabs" msgid="3050623868203544623">"窗口"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"书签"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"访问最多"</string>
@@ -32,12 +33,6 @@
<string name="bookmarks_search" msgid="5229596268214362873">"浏览器"</string>
<string name="cancel" msgid="3017274947407233702">"取消"</string>
<string name="ok" msgid="1509280796718850364">"确定"</string>
- <plurals name="matches_found">
- <item quantity="zero" msgid="6242659159545399963">"没有匹配项"</item>
- <item quantity="one" msgid="4352019729062956802">"1 个匹配项"</item>
- <item quantity="few" msgid="5544267486978946555">"<xliff:g id="NUMBER">%d</xliff:g> 个匹配项"</item>
- <item quantity="other" msgid="6616125067364315405">"<xliff:g id="NUMBER">%d</xliff:g> 个匹配项"</item>
- </plurals>
<string name="title_bar_loading" msgid="7438217780834640678">"正在载入..."</string>
<string name="page_info" msgid="4048529256302257195">"网页信息"</string>
<string name="page_info_view" msgid="5303490449842635158">"查看网页信息"</string>
@@ -67,12 +62,23 @@
<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>
+ <!-- no translation found for location (3411848697912600125) -->
+ <skip />
+ <!-- no translation found for containing_folder (6771180232953030479) -->
+ <skip />
+ <!-- no translation found for add_new_folder (7027600176450718398) -->
+ <skip />
+ <!-- no translation found for new_folder (7743540149088867917) -->
+ <skip />
+ <!-- no translation found for name (5915607427720935681) -->
+ <skip />
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"添加书签"</string>
+ <string name="save_to_bookmarks" msgid="6101482434920313244">"添加到书签"</string>
+ <!-- no translation found for bookmark_this_page (7530739804320811054) -->
+ <skip />
<string name="edit_bookmark" msgid="5024089053490231905">"编辑书签"</string>
- <string name="create_shortcut_bookmark" msgid="9202323987633899835">"向主屏幕添加快捷方式"</string>
+ <!-- no translation found for create_shortcut_bookmark (1995095662095484289) -->
+ <skip />
<string name="open_bookmark" msgid="8473581305759935790">"打开"</string>
<string name="remove_bookmark" msgid="8407495852801410891">"删除书签"</string>
<string name="remove_from_bookmarks" msgid="4374080666576982775">"从书签中删除"</string>
@@ -93,7 +99,7 @@
<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="goto_dot" msgid="3895839050522602723">"转至"</string>
- <string name="find_dot" msgid="6259312434696611957">"页内查找"</string>
+ <string name="incognito_tab" msgid="5419458065370134289">"打开新的隐身标签页"</string>
<string name="select_dot" msgid="6299170761900561967">"选择文本"</string>
<string name="tab_picker_title" msgid="864478399057782913">"当前窗口"</string>
<string name="tab_picker_remove_tab" msgid="630087809802479397">"关闭"</string>
@@ -103,6 +109,9 @@
<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="menu_save_webarchive" msgid="3934652434001459581">"另存为网络存档"</string>
+ <string name="webarchive_saved" msgid="7045250341467345007">"网络存档已保存。"</string>
+ <string name="webarchive_failed" msgid="2880998204746620260">"无法保存网络存档。"</string>
<string name="contextmenu_openlink" msgid="7237961252214188935">"打开"</string>
<string name="contextmenu_openlink_newwindow" msgid="992765050093960353">"在新窗口中打开"</string>
<string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"将链接加入书签"</string>
@@ -169,6 +178,10 @@
<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>
+ <!-- no translation found for pref_autoFill_enabled (5348131327347999291) -->
+ <skip />
+ <!-- no translation found for pref_autoFill_enabled_summary (282122852215557397) -->
+ <skip />
<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>
@@ -208,6 +221,7 @@
<item msgid="891615911084608570">"日语 (ISO-2022-JP)"</item>
<item msgid="5589150448475151241">"日语 (SHIFT_JIS)"</item>
<item msgid="7356792686950371843">"日语 (EUC-JP)"</item>
+ <item msgid="2193955365569270096">"韩语 (EUC-KR)"</item>
</string-array>
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"文字编码"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"数据连接性问题"</string>
@@ -292,4 +306,8 @@
<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="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"正在设置壁纸..."</string>
+ <string name="defaultBookmarksUpButton" msgid="2303951020715704735">"书签"</string>
+ <!-- no translation found for empty_bookmarks_folder (7843361614634930942) -->
+ <skip />
+ <string name="rlz_access_point" msgid="7165847807377650632">"Y1"</string>
</resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index ddf0e17..839ff60 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -19,6 +19,7 @@
<string name="application_name" msgid="1935869255545976415">"瀏覽器"</string>
<string name="choose_upload" msgid="3649366287575002063">"選擇要上載的檔案"</string>
<string name="new_tab" msgid="4505722538297295141">"新視窗"</string>
+ <string name="new_incognito_tab" msgid="5821404839654751753">"新的無痕式視窗"</string>
<string name="active_tabs" msgid="3050623868203544623">"視窗"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"書籤"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"常用網頁"</string>
@@ -32,12 +33,6 @@
<string name="bookmarks_search" msgid="5229596268214362873">"瀏覽器"</string>
<string name="cancel" msgid="3017274947407233702">"取消"</string>
<string name="ok" msgid="1509280796718850364">"確定"</string>
- <plurals name="matches_found">
- <item quantity="zero" msgid="6242659159545399963">"沒有相配項"</item>
- <item quantity="one" msgid="4352019729062956802">"1 個相配項"</item>
- <item quantity="few" msgid="5544267486978946555">"<xliff:g id="NUMBER">%d</xliff:g> 個相符項目"</item>
- <item quantity="other" msgid="6616125067364315405">"<xliff:g id="NUMBER">%d</xliff:g> 個相符項目"</item>
- </plurals>
<string name="title_bar_loading" msgid="7438217780834640678">"載入中..."</string>
<string name="page_info" msgid="4048529256302257195">"頁面資訊"</string>
<string name="page_info_view" msgid="5303490449842635158">"檢視頁面資訊"</string>
@@ -67,12 +62,23 @@
<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>
+ <!-- no translation found for location (3411848697912600125) -->
+ <skip />
+ <!-- no translation found for containing_folder (6771180232953030479) -->
+ <skip />
+ <!-- no translation found for add_new_folder (7027600176450718398) -->
+ <skip />
+ <!-- no translation found for new_folder (7743540149088867917) -->
+ <skip />
+ <!-- no translation found for name (5915607427720935681) -->
+ <skip />
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"新增書籤"</string>
+ <string name="save_to_bookmarks" msgid="6101482434920313244">"加入書籤"</string>
+ <!-- no translation found for bookmark_this_page (7530739804320811054) -->
+ <skip />
<string name="edit_bookmark" msgid="5024089053490231905">"編輯書籤"</string>
- <string name="create_shortcut_bookmark" msgid="9202323987633899835">"新增捷徑至首頁"</string>
+ <!-- no translation found for create_shortcut_bookmark (1995095662095484289) -->
+ <skip />
<string name="open_bookmark" msgid="8473581305759935790">"開啟"</string>
<string name="remove_bookmark" msgid="8407495852801410891">"刪除書籤"</string>
<string name="remove_from_bookmarks" msgid="4374080666576982775">"從書籤中移除"</string>
@@ -93,7 +99,7 @@
<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="goto_dot" msgid="3895839050522602723">"前往"</string>
- <string name="find_dot" msgid="6259312434696611957">"在頁面中尋找"</string>
+ <string name="incognito_tab" msgid="5419458065370134289">"開啟新的無痕式分頁"</string>
<string name="select_dot" msgid="6299170761900561967">"選取文字"</string>
<string name="tab_picker_title" msgid="864478399057782913">"目前視窗"</string>
<string name="tab_picker_remove_tab" msgid="630087809802479397">"關閉"</string>
@@ -103,6 +109,9 @@
<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="menu_save_webarchive" msgid="3934652434001459581">"另存為網頁封存"</string>
+ <string name="webarchive_saved" msgid="7045250341467345007">"已儲存網頁封存。"</string>
+ <string name="webarchive_failed" msgid="2880998204746620260">"無法儲存網頁封存。"</string>
<string name="contextmenu_openlink" msgid="7237961252214188935">"開啟"</string>
<string name="contextmenu_openlink_newwindow" msgid="992765050093960353">"在新視窗開啟"</string>
<string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"將連結加入書籤"</string>
@@ -169,6 +178,10 @@
<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>
+ <!-- no translation found for pref_autoFill_enabled (5348131327347999291) -->
+ <skip />
+ <!-- no translation found for pref_autoFill_enabled_summary (282122852215557397) -->
+ <skip />
<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>
@@ -208,6 +221,7 @@
<item msgid="891615911084608570">"日文 (ISO-2022-JP)"</item>
<item msgid="5589150448475151241">"日文 (SHIFT_JIS)"</item>
<item msgid="7356792686950371843">"日文 (EUC-JP)"</item>
+ <item msgid="2193955365569270096">"韓文 (EUC-KR)"</item>
</string-array>
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"文字編碼"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"資料連線問題"</string>
@@ -292,4 +306,8 @@
<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="progress_dialog_setting_wallpaper" msgid="4871900779338536674">"設定桌布..."</string>
+ <string name="defaultBookmarksUpButton" msgid="2303951020715704735">"書籤"</string>
+ <!-- no translation found for empty_bookmarks_folder (7843361614634930942) -->
+ <skip />
+ <string name="rlz_access_point" msgid="7165847807377650632">"Y1"</string>
</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 68bf253..95105e1 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -32,7 +32,8 @@
<color name="white">#ffffffff</color>
<color name="black">#ff000000</color>
-
+ <color name="tab_title_selected">#ffffffff</color>
+ <color name="tab_title_unselected">#ff808080</color>
<color name="geolocation_permissions_prompt_background">#ffdddddd</color>
</resources>
diff --git a/res/values/dimensions.xml b/res/values/dimensions.xml
new file mode 100644
index 0000000..4d19a9f
--- /dev/null
+++ b/res/values/dimensions.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.
+-->
+<resources
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- The width of a selected tab -->
+ <dimen
+ name="tab_width_selected">300dp</dimen>
+ <!-- The width of an unselected tab -->
+ <dimen
+ name="tab_width_unselected">300dp</dimen>
+
+ <dimen name="bookmarkThumbnailWidth">90dip</dimen>
+ <dimen name="bookmarkThumbnailHeight">80dip</dimen>
+</resources>
\ No newline at end of file
diff --git a/res/values/integers.xml b/res/values/integers.xml
new file mode 100644
index 0000000..9aae216
--- /dev/null
+++ b/res/values/integers.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:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- The number of lines in the suggestions dropdown in landscape -->
+ <integer name="max_suggest_lines_landscape">6</integer>
+ <!-- The number of lines in the suggestions dropdown in portrait -->
+ <integer name="max_suggest_lines_portrait">12</integer>
+ <!-- The maximum number of open tabs -->
+ <integer name="max_tabs">16</integer>
+</resources>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 9c9d30a..54e8f63 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -20,6 +20,9 @@
<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 of a new incognito tab. Also used in the
+ title bar when displaying a new tab [CHAR LIMIT=30] -->
+ <string name="new_incognito_tab">New incognito window</string>
<!-- Name of menu item which brings up a list of the currently active tabs -->
<string name="active_tabs">Windows</string>
<!-- Name of tab containing bookmarks -->
@@ -44,25 +47,11 @@
<string name="action">Sign in</string>
<!-- The name of the bookmarks and history search suggestion source. -->
<string name="bookmarks_search">Browser</string>
-
<!-- Label for a cancel button. It is used for multiple cancel buttons in different contexts -->
<string name="cancel">Cancel</string>
<!-- Label for a confirm button. Used in multiple contexts. -->
<string name="ok">OK</string>
- <!-- Displayed on the Find dialog to display the number of matches
- found in the current page. -->
- <plurals name="matches_found">
- <!-- Case of no matches -->
- <item quantity="zero">No matches</item>
- <!-- Case of one match -->
- <item quantity="one">1 match</item>
- <!-- Case of "few" (two) matches -->
- <item quantity="few"><xliff:g id="number" example="2">%d</xliff:g> matches</item>
- <!-- Case of several matches -->
- <item quantity="other"><xliff:g id="number" example="137">%d</xliff:g> matches</item>
- </plurals>
-
<!-- Displayed on the title bar while the page is loading -->
<string name="title_bar_loading">Loading\u2026</string>
@@ -133,17 +122,26 @@
<!-- Button label to cancel saving a bookmark. -->
<string name="do_not_save">Cancel</string>
<!-- Field label in Bookmark dialog box: refers to URL of the page to bookmark -->
- <string name="location">Location</string>
+ <string name="location">Address</string>
+ <!-- Field label in Bookmark dialog box: refers to the folder in which to save the bookmark -->
+ <string name="containing_folder">Add to</string>
+ <!-- Button text for a button that allows the user to add a new folder. Also used as the title of the add bookmarks dialog on the page
+ that allows choosing the folder to place it in. -->
+ <string name="add_new_folder">Add new folder</string>
+ <!-- Default name for a new folder -->
+ <string name="new_folder">New folder</string>
<!-- Field label in Bookmark dialog box: title that the user wishes to use for the bookmark -->
- <string name="name">Name</string>
+ <string name="name">Label</string>
<!-- Initial value in Location field in Bookmark dialog box -->
<string name="http">http://</string>
- <!-- Menu item that opens a dialog to save a bookmark, initialized with the current page -->
- <string name="save_to_bookmarks">Add bookmark</string>
+ <!-- Menu item that opens a dialog to save a bookmark for the current page -->
+ <string name="save_to_bookmarks">Add to Bookmarks</string>
+ <!-- Title of the dialog to bookmark a page -->
+ <string name="bookmark_this_page">Bookmark this page</string>
<!-- Menu item on the bookmarks page, to edit an existing bookmark -->
<string name="edit_bookmark">Edit bookmark</string>
<!-- Context menu item to create a shortcut to the bookmark on the desktop -->
- <string name="create_shortcut_bookmark">Add shortcut to Home</string>
+ <string name="create_shortcut_bookmark">Add shortcut to home</string>
<!-- Context menu item to open the currently highlighted bookmark -->
<string name="open_bookmark">Open</string>
<!-- Menu item to remove the currently highlighted bookmark-->
@@ -194,9 +192,8 @@
<string name="open_in_new_window">Open in 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
- string and search for it on the page. -->
- <string name="find_dot">Find on page</string>
+ <!-- Menu item that opens up a new incognito tab. -->
+ <string name="incognito_tab">Open new incognito tab</string>
<!-- Menu item to switch to text selection mode for copy and paste. -->
<string name="select_dot">Select text</string>
<!-- Title of current windows screen; appears in title bar -->
@@ -217,6 +214,12 @@
<string name="copy_page_url">Copy page url</string>
<!-- Menu item -->
<string name="share_page">Share page</string>
+ <!-- Menu item for saving a page as a web archive. -->
+ <string name="menu_save_webarchive">Save as Web Archive</string>
+ <!-- Toast informing the user that the page has been saved. -->
+ <string name="webarchive_saved">Web archive saved.</string>
+ <!-- Toast informing the user that saving the page has failed. -->
+ <string name="webarchive_failed">Failed to save web archive.</string>
<!-- Context Menu item open the currently selected link in the current
window.-->
<string name="contextmenu_openlink">Open</string>
@@ -319,6 +322,25 @@
<string name="pref_content_landscape_only">Landscape-only display</string>
<!-- Settings summary -->
<string name="pref_content_landscape_only_summary">Display pages only in the wider, landscape screen orientation</string>
+
+ <!-- Settings screen & section title for "Personal settings". These include things like
+ configuring bookmark syncing to Google servers and form auto fill settings. [CHAR-LIMIT=32] -->
+ <string name="pref_personal_title">Personal settings</string>
+ <!-- Checkbox setting to enable or disable syncing bookmarks and other data with Google Chrome. [CHAR-LIMIT=48] -->
+ <string name="pref_personal_sync_with_chrome">Sync with Google Chrome</string>
+ <!-- Checkbox setting to enable or disable syncing bookmarks and other data with Google Chrome. [CHAR-LIMIT=none] -->
+ <string name="pref_personal_sync_with_chrome_summary">Share bookmarks & other data between Android Browser and Google Chrome</string>
+ <!-- Label indicating which Google account is being used to sync bookmarks between Android and Chrome [CHAR-LIMIT=20] -->
+ <string name="pref_personal_google_account">Google account</string>
+ <!-- Checkbox setting to enable or disable syncing bookmarks with Google Chrome. [CHAR-LIMIT=32] -->
+ <string name="pref_personal_sync_bookmarks">Sync bookmarks</string>
+ <!-- Summary for a checkbox setting to enable or disable syncing bookmarks with Google Chrome. [CHAR-LIMIT=none] -->
+ <string name="pref_personal_sync_bookmarks_summary">Sync bookmarks between Android Browser and Google Chrome</string>
+ <!-- Button to start a sync of bookmarks and other data between the Android Browser and Google Chrome [CHAR-LIMIT=20] -->
+ <string name="pref_personal_start_syncing">Start syncing</string>
+ <!-- Dialog title used when asking the user which Google account they want to use to sync data between Android Browser and Google Chrome [CHAR-LIMIT=20] -->
+ <string name="pref_personal_account_dialog_title">Select Google account to share with</string>
+
<!-- Settings screen, section title -->
<string name="pref_privacy_title">Privacy settings</string>
<!-- Settings label -->
@@ -371,6 +393,10 @@
<string name="pref_security_save_form_data">Remember form data</string>
<!-- Settings summary -->
<string name="pref_security_save_form_data_summary">Remember data I type in forms for later use</string>
+ <!-- Settings label for enabling/disabling the form AutoFill feature -->
+ <string name="pref_autoFill_enabled">AutoFill forms</string>
+ <!-- Settings summary for the form AutoFill feature. -->
+ <string name="pref_autoFill_enabled_summary">Automatically fill out forms where possible</string>
<!-- Settings label -->
<string name="pref_security_show_security_warning">Show security warnings</string>
<!-- Settings summmary -->
@@ -477,6 +503,8 @@
<item>Japanese (ISO-2022-JP)</item>
<item>Japanese (SHIFT_JIS)</item>
<item>Japanese (EUC-JP)</item>
+ <!-- No need to translate a EUC-KR part, and there is no string length limits. -->
+ <item>Korean (EUC-KR)</item>
<!-- TODO: We should add a lot more encodings. -->
</string-array>
<!-- Dialog box title -->
@@ -490,6 +518,7 @@
<item>ISO-2022-JP</item>
<item>SHIFT_JIS</item>
<item>EUC-JP</item>
+ <item>EUC-KR</item>
</string-array>
<string name="pref_default_text_encoding_default" translatable="false">Latin-1</string>
<!-- Title for a dialog displayed when the browser has a data connectivity
@@ -753,4 +782,26 @@
<string name="error_console_eval_text_hint" translatable="false">Evaluate JavaScript</string>
<string name="error_console_eval_button_text" translatable="false">Evaluate</string>
+ <!-- The default state to the "up to parent folder" button in the bookmarks UI. This
+ is displayed when the user is at the highest level and cannot go up [CHAR LIMIT=16] -->
+ <string name="defaultBookmarksUpButton">Bookmarks</string>
+
+ <!-- The string that is displayed when there are no bookmarks to display.
+ This is centered in the middle of the screen [CHAR LIMIT=NONE] -->
+ <string name="empty_bookmarks_folder">There are no bookmarks</string>
+
+ <!-- Access point for RLZ tracking. -->
+ <string name="rlz_access_point">Y1</string>
+
+ <!-- Title for a dialog asking the user what they want to do with their bookmarks when adding a sync account [CHAR-LIMIT=32] -->
+ <string name="import_bookmarks_dialog_title">Sync with Google account</string>
+
+ <!-- Description for a dialog asking the user what they want to do with their bookmarks when adding a sync account [CHAR-LIMIT=none] -->
+ <string name="import_bookmarks_dialog_description">Your Android bookmarks are not associated with a Google account</string>
+
+ <!-- Button allowing users to remove all of their existing bookmarks when setting up syncing with their bookmarks stored in Google Chrome [CHAR-LIMIT=64] -->
+ <string name="import_bookmarks_dialog_remove">Remove your Android bookmarks</string>
+
+ <!-- Button allowing users to import all of their existing bookmarks into an account when setting up syncing with their bookmarks stored in Google Chrome [CHAR-LIMIT=64] -->
+ <string name="import_bookmarks_dialog_import">Add your Android bookmarks to bookmarks for <xliff:g id="Google account" example="account@example.com">%s</xliff:g></string>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 2e8510a..895c1d0 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -1,38 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
-/*
+/*
*
* Copyright 2006,2007,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
+ * 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
+ * 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
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
* limitations under the License.
*/
-->
<resources>
- <style name="BrowserTheme" parent="@android:Theme.Black">
- <item name="android:windowBackground">@color/white</item>
- <item name="android:colorBackground">#FFFFFFFF</item>
+ <style name="BrowserTheme" parent="@android:Theme.Holo">
<item name="android:windowNoTitle">true</item>
<item name="android:windowContentOverlay">@null</item>
</style>
-
+ <style name="ActionBar" parent="@android:style/Widget.ActionBar">
+ <item name="android:background">@color/black</item>
+ </style>
<style name="BookmarkTheme" parent="@android:Theme.Black">
<item name="android:windowNoTitle">true</item>
<item name="android:windowContentOverlay">@null</item>
</style>
-
+ <style name="ShortcutTheme" parent="@android:Theme.Black">
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowContentOverlay">@null</item>
+ </style>
<style name="TitleBar">
<item name="android:windowEnterAnimation">@anim/title_bar_enter</item>
<item name="android:windowExitAnimation">@anim/title_bar_exit</item>
</style>
+ <style name="HoloIcon">
+ <item name="android:paddingLeft">16dip</item>
+ <item name="android:paddingRight">16dip</item>
+ </style>
+ <style name="HoloButton" parent="@style/HoloIcon">
+ <item name="android:background">@drawable/browserbarbutton</item>
+ </style>
+ <style name="TabTitleSelected" parent="@android:style/TextAppearance.Small">
+ <item name="android:textColor">@color/tab_title_selected</item>
+ <item name="android:textStyle">bold</item>
+ </style>
+ <style name="TabTitleUnselected" parent="@android:style/TextAppearance.Small">
+ <item name="android:textColor">@color/tab_title_unselected</item>
+ <item name="android:textStyle">normal</item>
+ </style>
</resources>
diff --git a/res/xml/advanced_preferences.xml b/res/xml/advanced_preferences.xml
new file mode 100644
index 0000000..075232d
--- /dev/null
+++ b/res/xml/advanced_preferences.xml
@@ -0,0 +1,41 @@
+<?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.
+-->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <!-- Entries and values in this list are set dynamically. -->
+ <com.android.browser.search.SearchEnginePreference
+ android:key="search_engine"
+ android:title="@string/pref_content_search_engine"
+ android:defaultValue="google"
+ android:summary="@string/pref_content_search_engine_summary"
+ android:dialogTitle="@string/pref_content_search_engine" />
+
+ <PreferenceScreen
+ android:key="website_settings"
+ android:title="@string/pref_extras_website_settings"
+ android:summary="@string/pref_extras_website_settings_summary" />
+
+ <com.android.browser.BrowserYesNoPreference
+ android:key="reset_default_preferences"
+ android:title="@string/pref_extras_reset_default"
+ android:summary="@string/pref_extras_reset_default_summary"
+ android:dialogMessage="@string/pref_extras_reset_default_dlg"
+ android:dialogTitle="@string/pref_extras_reset_default_dlg_title"
+ android:dialogIcon="@android:drawable/ic_dialog_alert" />
+
+</PreferenceScreen>
diff --git a/res/anim/dialog_exit.xml b/res/xml/bookmarkstackwidget.xml
similarity index 60%
copy from res/anim/dialog_exit.xml
copy to res/xml/bookmarkstackwidget.xml
index dacb5c3..1879923 100644
--- a/res/anim/dialog_exit.xml
+++ b/res/xml/bookmarkstackwidget.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
+<!-- Copyright (C) 2010 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,9 +14,11 @@
limitations under the License.
-->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:interpolator="@android:anim/accelerate_interpolator">
- <translate android:fromYDelta="0" android:toYDelta="50%" android:duration="50"/>
- <alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="50" />
-</set>
-
+<!-- 2x2 Widget displaying the user's bookmarks as thumbnails. -->
+<appwidget-provider
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:minWidth="146dip"
+ android:minHeight="146dip"
+ android:updatePeriodMillis="3600000"
+ android:initialLayout="@layout/bookmarkstackwidget">
+</appwidget-provider>
diff --git a/res/xml/browser_preferences.xml b/res/xml/browser_preferences.xml
index 1da85ec..cc9b18a 100644
--- a/res/xml/browser_preferences.xml
+++ b/res/xml/browser_preferences.xml
@@ -139,6 +139,12 @@
android:title="@string/pref_security_save_form_data"
android:summary="@string/pref_security_save_form_data_summary" />
+ <CheckBoxPreference
+ android:key="autoFill_enabled"
+ android:defaultValue="false"
+ android:title="@string/pref_autoFill_enabled"
+ android:summary="@string/pref_autoFill_enabled_summary" />
+
<com.android.browser.BrowserYesNoPreference
android:key="privacy_clear_form_data"
android:title="@string/pref_privacy_clear_form_data"
diff --git a/res/xml/debug_preferences.xml b/res/xml/debug_preferences.xml
index c1ed1e6..54b2bd5 100644
--- a/res/xml/debug_preferences.xml
+++ b/res/xml/debug_preferences.xml
@@ -16,59 +16,54 @@
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android" >
- <PreferenceCategory
- android:title="@string/pref_development_title"
- android:key="debug_menu" >
- <!-- The javascript console is enabled by default when the user has
- also enabled debug mode by navigating to about:debug. -->
- <CheckBoxPreference
- android:key="javascript_console"
- android:defaultValue="true"
- android:title="@string/pref_development_error_console" />
-
- <CheckBoxPreference
- android:key="small_screen"
- android:defaultValue="false"
- android:title="@string/pref_development_single_column_rendering" />
-
- <CheckBoxPreference
- android:key="wide_viewport"
- android:defaultValue="true"
- android:title="@string/pref_development_viewport" />
+ <!-- The javascript console is enabled by default when the user has
+ also enabled debug mode by navigating to about:debug. -->
+ <CheckBoxPreference
+ android:key="javascript_console"
+ android:defaultValue="true"
+ android:title="@string/pref_development_error_console" />
- <CheckBoxPreference
- android:key="normal_layout"
- android:defaultValue="false"
- android:title="@string/pref_development_normal_rendering" />
-
- <CheckBoxPreference
- android:key="enable_tracing"
- android:defaultValue="false"
- android:title="@string/pref_development_trace" />
+ <CheckBoxPreference
+ android:key="small_screen"
+ android:defaultValue="false"
+ android:title="@string/pref_development_single_column_rendering" />
+
+ <CheckBoxPreference
+ android:key="wide_viewport"
+ android:defaultValue="true"
+ android:title="@string/pref_development_viewport" />
+
+ <CheckBoxPreference
+ android:key="normal_layout"
+ android:defaultValue="false"
+ android:title="@string/pref_development_normal_rendering" />
- <CheckBoxPreference
- android:key="enable_light_touch"
- android:defaultValue="false"
- android:title="Enable light touch" />
+ <CheckBoxPreference
+ android:key="enable_tracing"
+ android:defaultValue="false"
+ android:title="@string/pref_development_trace" />
- <CheckBoxPreference
- android:key="enable_nav_dump"
- android:defaultValue="false"
- android:title="@string/pref_development_nav_dump" />
+ <CheckBoxPreference
+ android:key="enable_light_touch"
+ android:defaultValue="false"
+ android:title="Enable light touch" />
- <EditTextPreference
- android:key="js_engine_flags"
- android:title="@string/js_engine_flags"
- android:singleLine="true" />
+ <CheckBoxPreference
+ android:key="enable_nav_dump"
+ android:defaultValue="false"
+ android:title="@string/pref_development_nav_dump" />
- <ListPreference
- android:key="user_agent"
- android:title="@string/pref_development_uastring"
- android:entries="@array/pref_development_ua_choices"
- android:entryValues="@array/pref_development_ua_values"
- android:defaultValue="0"/>
+ <EditTextPreference
+ android:key="js_engine_flags"
+ android:title="@string/js_engine_flags"
+ android:singleLine="true" />
- </PreferenceCategory>
+ <ListPreference
+ android:key="user_agent"
+ android:title="@string/pref_development_uastring"
+ android:entries="@array/pref_development_ua_choices"
+ android:entryValues="@array/pref_development_ua_values"
+ android:defaultValue="0"/>
</PreferenceScreen>
diff --git a/res/xml/page_content_preferences.xml b/res/xml/page_content_preferences.xml
new file mode 100644
index 0000000..84497dc
--- /dev/null
+++ b/res/xml/page_content_preferences.xml
@@ -0,0 +1,98 @@
+<?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.
+-->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <ListPreference
+ android:key="text_size"
+ android:title="@string/pref_text_size"
+ android:defaultValue="NORMAL"
+ android:entries="@array/pref_text_size_choices"
+ android:entryValues="@array/pref_text_size_values"
+ android:dialogTitle="@string/pref_text_size_dialogtitle" />
+
+ <ListPreference
+ android:key="default_zoom"
+ android:title="@string/pref_default_zoom"
+ android:defaultValue="MEDIUM"
+ android:entries="@array/pref_default_zoom_choices"
+ android:entryValues="@array/pref_default_zoom_values"
+ android:dialogTitle="@string/pref_default_zoom_dialogtitle" />
+
+ <CheckBoxPreference
+ android:key="load_page"
+ android:defaultValue="true"
+ android:title="@string/pref_content_load_page"
+ android:summary="@string/pref_content_load_page_summary" />
+
+ <ListPreference
+ android:key="default_text_encoding"
+ android:title="@string/pref_default_text_encoding"
+ android:defaultValue="@string/pref_default_text_encoding_default"
+ android:entries="@array/pref_default_text_encoding_choices"
+ android:entryValues="@array/pref_default_text_encoding_values"
+ android:dialogTitle="@string/pref_default_text_encoding_dialogtitle" />
+
+ <CheckBoxPreference
+ android:key="block_popup_windows"
+ android:defaultValue="true"
+ android:title="@string/pref_content_block_popups" />
+
+ <CheckBoxPreference
+ android:key="load_images"
+ android:defaultValue="true"
+ android:title="@string/pref_content_load_images"
+ android:summary="@string/pref_content_load_images_summary" />
+
+ <CheckBoxPreference
+ android:key="autofit_pages"
+ android:defaultValue="true"
+ android:title="@string/pref_content_autofit"
+ android:summary="@string/pref_content_autofit_summary" />
+
+ <CheckBoxPreference
+ android:key="landscape_only"
+ android:defaultValue="false"
+ android:title="@string/pref_content_landscape_only"
+ android:summary="@string/pref_content_landscape_only_summary" />
+
+ <CheckBoxPreference
+ android:key="enable_javascript"
+ android:defaultValue="true"
+ android:title="@string/pref_content_javascript" />
+
+ <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"
+ android:defaultValue="false"
+ android:title="@string/pref_content_open_in_background"
+ android:summary="@string/pref_content_open_in_background_summary" />
+
+ <com.android.browser.BrowserHomepagePreference
+ android:key="homepage"
+ android:title="@string/pref_content_homepage"
+ android:hint="@string/http"
+ android:inputType="textUri|textMultiLine" />
+
+</PreferenceScreen>
diff --git a/res/menu/bookmarks.xml b/res/xml/personal_preferences.xml
similarity index 69%
copy from res/menu/bookmarks.xml
copy to res/xml/personal_preferences.xml
index a8781c2..14b057c 100644
--- a/res/menu/bookmarks.xml
+++ b/res/xml/personal_preferences.xml
@@ -4,9 +4,9 @@
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.
@@ -14,10 +14,11 @@
limitations under the License.
-->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:id="@+id/new_context_menu_id"
- android:icon="@drawable/ic_menu_add_bookmark"
- android:title="@string/bookmark_page" />
- <item android:id="@+id/switch_mode_menu_id"
- />
-</menu>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <Preference android:key="sync_with_chrome"
+ android:title="@string/pref_personal_sync_with_chrome"
+ android:summary="@string/pref_personal_sync_with_chrome_summary"
+ />
+
+</PreferenceScreen>
diff --git a/res/xml/preference_headers.xml b/res/xml/preference_headers.xml
new file mode 100644
index 0000000..1a54990
--- /dev/null
+++ b/res/xml/preference_headers.xml
@@ -0,0 +1,38 @@
+<?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.
+-->
+
+<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <header android:fragment="com.android.browser.preferences.PageContentPreferencesFragment"
+ android:title="@string/pref_content_title"
+ />
+
+ <header android:fragment="com.android.browser.preferences.PersonalPreferencesFragment"
+ android:title="@string/pref_personal_title"
+ />
+
+ <header android:fragment="com.android.browser.preferences.PrivacyPreferencesFragment"
+ android:title="@string/pref_privacy_title"
+ />
+
+ <header android:fragment="com.android.browser.preferences.SecurityPreferencesFragment"
+ android:title="@string/pref_security_title"
+ />
+
+ <header android:fragment="com.android.browser.preferences.AdvancedPreferencesFragment"
+ android:title="@string/pref_extras_title"
+ />
+</preference-headers>
diff --git a/res/xml/privacy_preferences.xml b/res/xml/privacy_preferences.xml
new file mode 100644
index 0000000..f8a8d91
--- /dev/null
+++ b/res/xml/privacy_preferences.xml
@@ -0,0 +1,85 @@
+<?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.
+-->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <com.android.browser.BrowserYesNoPreference
+ android:key="privacy_clear_cache"
+ android:title="@string/pref_privacy_clear_cache"
+ android:summary="@string/pref_privacy_clear_cache_summary"
+ android:dialogMessage="@string/pref_privacy_clear_cache_dlg"
+ android:dialogTitle="@string/clear"
+ android:dialogIcon="@android:drawable/ic_dialog_alert" />
+
+ <com.android.browser.BrowserYesNoPreference
+ android:key="privacy_clear_history"
+ android:title="@string/pref_privacy_clear_history"
+ android:summary="@string/pref_privacy_clear_history_summary"
+ android:dialogMessage="@string/pref_privacy_clear_history_dlg"
+ android:dialogTitle="@string/clear"
+ android:dialogIcon="@android:drawable/ic_dialog_alert"/>
+
+ <CheckBoxPreference
+ android:key="accept_cookies"
+ android:defaultValue="true"
+ android:title="@string/pref_security_accept_cookies"
+ android:summary="@string/pref_security_accept_cookies_summary" />
+
+ <com.android.browser.BrowserYesNoPreference
+ android:key="privacy_clear_cookies"
+ android:title="@string/pref_privacy_clear_cookies"
+ android:summary="@string/pref_privacy_clear_cookies_summary"
+ android:dialogMessage="@string/pref_privacy_clear_cookies_dlg"
+ android:dialogTitle="@string/clear"
+ android:dialogIcon="@android:drawable/ic_dialog_alert"/>
+
+ <CheckBoxPreference
+ android:key="save_formdata"
+ android:defaultValue="true"
+ android:title="@string/pref_security_save_form_data"
+ android:summary="@string/pref_security_save_form_data_summary" />
+
+ <CheckBoxPreference
+ android:key="autoFill_enabled"
+ android:defaultValue="false"
+ android:title="@string/pref_autoFill_enabled"
+ android:summary="@string/pref_autoFill_enabled_summary" />
+
+ <com.android.browser.BrowserYesNoPreference
+ android:key="privacy_clear_form_data"
+ android:title="@string/pref_privacy_clear_form_data"
+ android:summary="@string/pref_privacy_clear_form_data_summary"
+ android:dialogMessage="@string/pref_privacy_clear_form_data_dlg"
+ android:dialogTitle="@string/clear"
+ android:dialogIcon="@android:drawable/ic_dialog_alert"/>
+
+ <CheckBoxPreference
+ android:key="enable_geolocation"
+ android:defaultValue="true"
+ android:title="@string/pref_privacy_enable_geolocation"
+ android:summary="@string/pref_privacy_enable_geolocation_summary" />
+
+ <com.android.browser.BrowserYesNoPreference
+ android:key="privacy_clear_geolocation_access"
+ android:dependency="enable_geolocation"
+ android:title="@string/pref_privacy_clear_geolocation_access"
+ android:summary="@string/pref_privacy_clear_geolocation_access_summary"
+ android:dialogMessage="@string/pref_privacy_clear_geolocation_access_dlg"
+ android:dialogTitle="@string/clear"
+ android:dialogIcon="@android:drawable/ic_dialog_alert"/>
+
+</PreferenceScreen>
diff --git a/res/xml/security_preferences.xml b/res/xml/security_preferences.xml
new file mode 100644
index 0000000..8d4464b
--- /dev/null
+++ b/res/xml/security_preferences.xml
@@ -0,0 +1,40 @@
+<?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.
+-->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <CheckBoxPreference
+ android:key="remember_passwords"
+ android:defaultValue="true"
+ android:title="@string/pref_security_remember_passwords"
+ android:summary="@string/pref_security_remember_passwords_summary" />
+
+ <com.android.browser.BrowserYesNoPreference
+ android:key="privacy_clear_passwords"
+ android:title="@string/pref_privacy_clear_passwords"
+ android:summary="@string/pref_privacy_clear_passwords_summary"
+ android:dialogMessage="@string/pref_privacy_clear_passwords_dlg"
+ android:dialogTitle="@string/clear"
+ android:dialogIcon="@android:drawable/ic_dialog_alert"/>
+
+ <CheckBoxPreference
+ android:key="show_security_warnings"
+ android:defaultValue="true"
+ android:title="@string/pref_security_show_security_warning"
+ android:summary="@string/pref_security_show_security_warning_summary" />
+
+</PreferenceScreen>
diff --git a/src/com/android/browser/ActiveTabsPage.java b/src/com/android/browser/ActiveTabsPage.java
index 2de7787..e450a99 100644
--- a/src/com/android/browser/ActiveTabsPage.java
+++ b/src/com/android/browser/ActiveTabsPage.java
@@ -20,6 +20,7 @@
import android.graphics.Bitmap;
import android.os.Handler;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
@@ -32,6 +33,7 @@
import android.widget.TextView;
public class ActiveTabsPage extends LinearLayout {
+ private static final String LOGTAG = "TabPicker";
private final BrowserActivity mBrowserActivity;
private final LayoutInflater mFactory;
private final TabControl mControl;
@@ -51,12 +53,15 @@
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
if (mControl.canCreateNewTab()) {
- position--;
+ position -= 2;
}
boolean needToAttach = false;
- if (position == -1) {
+ if (position == -2) {
// Create a new tab
mBrowserActivity.openTabToHomePage();
+ } else if (position == -1) {
+ // Create a new incognito tab
+ mBrowserActivity.openIncognitoTab();
} else {
// Open the corresponding tab
// If the tab is the current one, switchToTab will
@@ -98,7 +103,7 @@
public int getCount() {
int count = mControl.getTabCount();
if (mControl.canCreateNewTab()) {
- count++;
+ count += 2;
}
// XXX: This is a workaround to be more like a real adapter. Most
// adapters call notifyDataSetChanged() whenever the internal data
@@ -128,23 +133,28 @@
}
public int getItemViewType(int position) {
if (mControl.canCreateNewTab()) {
- position--;
+ position -= 2;
}
// Do not recycle the "add new tab" item.
- return position == -1 ? IGNORE_ITEM_VIEW_TYPE : 1;
+ return position < 0 ? IGNORE_ITEM_VIEW_TYPE : 1;
}
public View getView(int position, View convertView, ViewGroup parent) {
final int tabCount = mControl.getTabCount();
if (mControl.canCreateNewTab()) {
- position--;
+ position -= 2;
}
if (convertView == null) {
- convertView = mFactory.inflate(position == -1 ?
- R.layout.tab_view_add_tab : R.layout.tab_view, null);
+ if (position == -2) {
+ convertView = mFactory.inflate(R.layout.tab_view_add_tab, null);
+ } else if (position == -1) {
+ convertView = mFactory.inflate(R.layout.tab_view_add_incognito_tab, null);
+ } else {
+ convertView = mFactory.inflate(R.layout.tab_view, null);
+ }
}
- if (position != -1) {
+ if (position >= 0) {
TextView title =
(TextView) convertView.findViewById(R.id.title);
TextView url = (TextView) convertView.findViewById(R.id.url);
@@ -152,7 +162,19 @@
(ImageView) convertView.findViewById(R.id.favicon);
View close = convertView.findViewById(R.id.close);
Tab tab = mControl.getTab(position);
+ if (tab.getWebView() == null) {
+ // This means that populatePickerData will have to use the
+ // saved state.
+ Log.w(LOGTAG, "Tab " + position + " has a null WebView and "
+ + (tab.getSavedState() == null ? "null" : "non-null")
+ + " saved state ");
+ }
tab.populatePickerData();
+ if (tab.getTitle() == null || tab.getTitle().length() == 0) {
+ Log.w(LOGTAG, "Tab " + position + " has no title. "
+ + "Check above in the Logs to see whether it has a "
+ + "null WebView or null WebHistoryItem");
+ }
title.setText(tab.getTitle());
url.setText(tab.getUrl());
Bitmap icon = tab.getFavicon();
diff --git a/src/com/android/browser/AddBookmarkPage.java b/src/com/android/browser/AddBookmarkPage.java
index 1104d5e..9070218 100644
--- a/src/com/android/browser/AddBookmarkPage.java
+++ b/src/com/android/browser/AddBookmarkPage.java
@@ -16,32 +16,58 @@
package com.android.browser;
+import com.android.browser.provider.BrowserProvider2;
+
import android.app.Activity;
+import android.app.LoaderManager;
import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.CursorLoader;
import android.content.Intent;
+import android.content.Loader;
+import android.content.SharedPreferences;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.ParseException;
+import android.net.Uri;
import android.net.WebAddress;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
-import android.provider.Browser;
+import android.preference.PreferenceManager;
+import android.provider.BrowserContract;
+import android.text.TextUtils;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
import android.view.Window;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.AdapterView;
+import android.widget.CursorAdapter;
import android.widget.EditText;
+import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.net.URI;
import java.net.URISyntaxException;
-import java.util.Date;
+import java.util.ArrayList;
-public class AddBookmarkPage extends Activity {
+public class AddBookmarkPage extends Activity
+ implements View.OnClickListener, TextView.OnEditorActionListener,
+ AdapterView.OnItemClickListener, LoaderManager.LoaderCallbacks<Cursor> {
private final String LOGTAG = "Bookmarks";
+ // IDs for the CursorLoaders that are used.
+ private final int LOADER_ID_FOLDER_CONTENTS = 0;
+ private final int LOADER_ID_ALL_FOLDERS = 1;
+
private EditText mTitle;
private EditText mAddress;
private TextView mButton;
@@ -51,36 +77,263 @@
private String mTouchIconUrl;
private Bitmap mThumbnail;
private String mOriginalUrl;
+ private TextView mFolder;
+ private View mDefaultView;
+ private View mFolderSelector;
+ private EditText mFolderNamer;
+ private View mAddNewFolder;
+ private long mCurrentFolder = 0;
+ private FolderAdapter mAdapter;
+ private ArrayList<Folder> mPaths;
+ private TextView mPath;
+
+ private static class Folder {
+ String Name;
+ long Id;
+ Folder(String name, long id) {
+ Name = name;
+ Id = id;
+ }
+ }
// Message IDs
private static final int SAVE_BOOKMARK = 100;
private Handler mHandler;
- private View.OnClickListener mSaveBookmark = new View.OnClickListener() {
- public void onClick(View v) {
- if (save()) {
- finish();
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ if (v == mFolderNamer) {
+ if (v.getText().length() > 0) {
+ if (actionId == EditorInfo.IME_NULL) {
+ // Only want to do this once.
+ if (event.getAction() == KeyEvent.ACTION_UP) {
+ String name = v.getText().toString();
+ long id = addFolderToCurrent(name);
+ mFolderNamer.setVisibility(View.GONE);
+ mAddNewFolder.setVisibility(View.VISIBLE);
+ descendInto(name,id);
+ InputMethodManager.getInstance(this)
+ .hideSoftInputFromWindow(
+ mFolderNamer.getWindowToken(), 0);
+ }
+ // Steal the key press for both up and down
+ return true;
+ }
}
}
- };
+ return false;
+ }
- private View.OnClickListener mCancel = new View.OnClickListener() {
- public void onClick(View v) {
- finish();
+ @Override
+ public void onClick(View v) {
+ if (v == mButton) {
+ if (mFolderSelector.getVisibility() == View.VISIBLE) {
+ // We are showing the folder selector.
+ if (mFolderNamer.getVisibility() == View.VISIBLE) {
+ // Editing folder name
+ String name = mFolderNamer.getText().toString();
+ long id = addFolderToCurrent(mFolderNamer.getText().toString());
+ descendInto(name, id);
+ mFolderNamer.setVisibility(View.GONE);
+ mAddNewFolder.setVisibility(View.VISIBLE);
+ } else {
+ // User has selected a folder. Go back to the opening page
+ mFolderSelector.setVisibility(View.GONE);
+ mDefaultView.setVisibility(View.VISIBLE);
+ setTitle(R.string.bookmark_this_page);
+ }
+ } else if (save()) {
+ finish();
+ }
+ } else if (v == mCancelButton) {
+ if (mFolderNamer.getVisibility() == View.VISIBLE) {
+ mFolderNamer.setVisibility(View.GONE);
+ mAddNewFolder.setVisibility(View.VISIBLE);
+ } else {
+ finish();
+ }
+ } else if (v == mFolder) {
+ switchToFolderSelector();
+ } else if (v == mAddNewFolder) {
+ mFolderNamer.setVisibility(View.VISIBLE);
+ mFolderNamer.setText(R.string.new_folder);
+ mFolderNamer.requestFocus();
+ mAddNewFolder.setVisibility(View.GONE);
+ InputMethodManager.getInstance(this).showSoftInput(mFolderNamer,
+ InputMethodManager.SHOW_IMPLICIT);
}
- };
+ }
+
+ private long addFolderToCurrent(String name) {
+ // Add the folder to the database
+ ContentValues values = new ContentValues();
+ values.put(BrowserContract.Bookmarks.TITLE,
+ name);
+ values.put(BrowserContract.Bookmarks.IS_FOLDER, 1);
+ values.put(BrowserContract.Bookmarks.PARENT,
+ mCurrentFolder);
+ Uri uri = getContentResolver().insert(
+ BrowserContract.Bookmarks.CONTENT_URI, values);
+ if (uri != null) {
+ return ContentUris.parseId(uri);
+ } else {
+ return -1;
+ }
+ }
+
+ private void switchToFolderSelector() {
+ mDefaultView.setVisibility(View.GONE);
+ mFolderSelector.setVisibility(View.VISIBLE);
+ setTitle(R.string.containing_folder);
+ }
+
+ private void descendInto(String foldername, long id) {
+ if (id != -1) {
+ mCurrentFolder = id;
+ mPaths.add(new Folder(foldername, id));
+ updatePathString();
+ getLoaderManager().restartLoader(LOADER_ID_FOLDER_CONTENTS, null, this);
+ }
+ }
+
+ @Override
+ public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ String[] projection;
+ switch (id) {
+ case LOADER_ID_ALL_FOLDERS:
+ projection = new String[] {
+ BrowserContract.Bookmarks._ID,
+ BrowserContract.Bookmarks.PARENT,
+ BrowserContract.Bookmarks.TITLE,
+ BrowserContract.Bookmarks.IS_FOLDER
+ };
+ return new CursorLoader(this,
+ BrowserContract.Bookmarks.CONTENT_URI,
+ projection,
+ BrowserContract.Bookmarks.IS_FOLDER + " != 0",
+ null,
+ null);
+ case LOADER_ID_FOLDER_CONTENTS:
+ projection = new String[] {
+ BrowserContract.Bookmarks._ID,
+ BrowserContract.Bookmarks.TITLE,
+ BrowserContract.Bookmarks.IS_FOLDER
+ };
+ return new CursorLoader(this,
+ BrowserContract.Bookmarks.buildFolderUri(
+ mCurrentFolder),
+ projection,
+ BrowserContract.Bookmarks.IS_FOLDER + " != 0",
+ null,
+ null);
+ default:
+ throw new AssertionError("Asking for nonexistant loader!");
+ }
+ }
+
+ @Override
+ public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
+ switch (loader.getId()) {
+ case LOADER_ID_FOLDER_CONTENTS:
+ mAdapter.changeCursor(cursor);
+ break;
+ case LOADER_ID_ALL_FOLDERS:
+ long parent = mCurrentFolder;
+ int idIndex = cursor.getColumnIndexOrThrow(
+ BrowserContract.Bookmarks._ID);
+ int titleIndex = cursor.getColumnIndexOrThrow(
+ BrowserContract.Bookmarks.TITLE);
+ int parentIndex = cursor.getColumnIndexOrThrow(
+ BrowserContract.Bookmarks.PARENT);
+ while ((parent != BrowserProvider2.FIXED_ID_ROOT) &&
+ (parent != 0)) {
+ // First, find the folder corresponding to the current
+ // folder
+ if (!cursor.moveToFirst()) {
+ throw new AssertionError("No folders in the database!");
+ }
+ long folder;
+ do {
+ folder = cursor.getLong(idIndex);
+ } while (folder != parent && cursor.moveToNext());
+ if (cursor.isAfterLast()) {
+ throw new AssertionError("Folder(id=" + parent
+ + ") holding this bookmark does not exist!");
+ }
+ String name = cursor.getString(titleIndex);
+ mPaths.add(1, new Folder(name, parent));
+ parent = cursor.getLong(parentIndex);
+ }
+ getLoaderManager().stopLoader(LOADER_ID_ALL_FOLDERS);
+ updatePathString();
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Update the TextViews in both modes to display the full path of the
+ * current location to insert.
+ */
+ private void updatePathString() {
+ String path = mPaths.get(0).Name;
+ int size = mPaths.size();
+ for (int i = 1; i < size; i++) {
+ path += " / " + mPaths.get(i).Name;
+ }
+ mPath.setText(path);
+ mFolder.setText(path);
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position,
+ long id) {
+ TextView tv = (TextView) view.findViewById(android.R.id.text1);
+ // Switch to the folder that was clicked on.
+ descendInto(tv.getText().toString(), id);
+ }
+
+ /**
+ * Shows a list of names of folders.
+ */
+ private class FolderAdapter extends CursorAdapter {
+ public FolderAdapter(Context context) {
+ super(context, null);
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ ((TextView) view.findViewById(android.R.id.text1)).setText(
+ cursor.getString(cursor.getColumnIndexOrThrow(
+ BrowserContract.Bookmarks.TITLE)));
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ View view = LayoutInflater.from(context).inflate(
+ R.layout.folder_list_item, null);
+ view.setBackgroundDrawable(context.getResources().
+ getDrawable(android.R.drawable.list_selector_background));
+ return view;
+ }
+ }
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
requestWindowFeature(Window.FEATURE_LEFT_ICON);
+
+ mMap = getIntent().getExtras();
+
setContentView(R.layout.browser_add_bookmark);
- setTitle(R.string.save_to_bookmarks);
+
+ setTitle(R.string.bookmark_this_page);
getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, R.drawable.ic_list_bookmark);
-
+
String title = null;
String url = null;
- mMap = getIntent().getExtras();
+
if (mMap != null) {
Bundle b = mMap.getBundle("bookmark");
if (b != null) {
@@ -92,29 +345,125 @@
url = mOriginalUrl = mMap.getString("url");
mTouchIconUrl = mMap.getString("touch_icon_url");
mThumbnail = (Bitmap) mMap.getParcelable("thumbnail");
+ mCurrentFolder = mMap.getLong(BrowserContract.Bookmarks.PARENT, -1);
+ }
+ if (mCurrentFolder == -1) {
+ mCurrentFolder = getBookmarksBarId(this);
}
mTitle = (EditText) findViewById(R.id.title);
mTitle.setText(title);
+
mAddress = (EditText) findViewById(R.id.address);
mAddress.setText(url);
- View.OnClickListener accept = mSaveBookmark;
mButton = (TextView) findViewById(R.id.OK);
- mButton.setOnClickListener(accept);
+ mButton.setOnClickListener(this);
mCancelButton = findViewById(R.id.cancel);
- mCancelButton.setOnClickListener(mCancel);
-
+ mCancelButton.setOnClickListener(this);
+
+ mFolder = (TextView) findViewById(R.id.folder);
+ mFolder.setOnClickListener(this);
+
+ mDefaultView = findViewById(R.id.default_view);
+ mFolderSelector = findViewById(R.id.folder_selector);
+
+ mFolderNamer = (EditText) findViewById(R.id.folder_namer);
+ mFolderNamer.setOnEditorActionListener(this);
+
+ mAddNewFolder = findViewById(R.id.add_new_folder);
+ mAddNewFolder.setOnClickListener(this);
+
+ mPath = (TextView) findViewById(R.id.path);
+ ListView list = (ListView) findViewById(R.id.list);
+
+ mPaths = new ArrayList<Folder>();
+ mPaths.add(0, new Folder(getString(R.string.bookmarks), BrowserProvider2.FIXED_ID_ROOT));
+ mAdapter = new FolderAdapter(this);
+ list.setAdapter(mAdapter);
+ list.setOnItemClickListener(this);
+ LoaderManager manager = getLoaderManager();
+ if (mCurrentFolder != BrowserProvider2.FIXED_ID_ROOT) {
+ // Find all the folders
+ manager.initLoader(LOADER_ID_ALL_FOLDERS, null, this);
+ }
+ manager.initLoader(LOADER_ID_FOLDER_CONTENTS, null, this);
+
+
if (!getWindow().getDecorView().isInTouchMode()) {
mButton.requestFocus();
}
}
+ // FIXME: Use a CursorLoader
+ private long getBookmarksBarId(Context context) {
+ SharedPreferences prefs
+ = PreferenceManager.getDefaultSharedPreferences(context);
+ String accountName =
+ prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_NAME, null);
+ String accountType =
+ prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_TYPE, null);
+ if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) {
+ return BrowserProvider2.FIXED_ID_ROOT;
+ }
+ Cursor cursor = null;
+ try {
+ cursor = context.getContentResolver().query(
+ BrowserContract.Bookmarks.CONTENT_URI,
+ new String[] { BrowserContract.Bookmarks._ID },
+ BrowserContract.ChromeSyncColumns.SERVER_UNIQUE + "=? AND "
+ + BrowserContract.Bookmarks.ACCOUNT_NAME + "=? AND "
+ + BrowserContract.Bookmarks.ACCOUNT_TYPE + "=?",
+ new String[] {
+ BrowserContract.ChromeSyncColumns
+ .FOLDER_NAME_BOOKMARKS_BAR,
+ accountName,
+ accountType },
+ null);
+ if (cursor != null && cursor.moveToFirst()) {
+ return cursor.getLong(0);
+ }
+ } finally {
+ if (cursor != null) cursor.close();
+ }
+ return BrowserProvider2.FIXED_ID_ROOT;
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ if (mFolderSelector.getVisibility() == View.VISIBLE
+ && KeyEvent.KEYCODE_BACK == event.getKeyCode()) {
+ if (KeyEvent.ACTION_UP == event.getAction()) {
+ if (mFolderNamer.getVisibility() == View.VISIBLE) {
+ mFolderNamer.setVisibility(View.GONE);
+ mAddNewFolder.setVisibility(View.VISIBLE);
+ InputMethodManager.getInstance(this).hideSoftInputFromWindow(
+ mFolderNamer.getWindowToken(), 0);
+ } else {
+ int size = mPaths.size();
+ if (1 == size) {
+ // We have reached the top level
+ finish();
+ } else {
+ // Go up a level
+ mPaths.remove(size - 1);
+ mCurrentFolder = mPaths.get(size - 2).Id;
+ updatePathString();
+ getLoaderManager().restartLoader(LOADER_ID_FOLDER_CONTENTS, null, this);
+ }
+ }
+ }
+ return true;
+ }
+ return super.dispatchKeyEvent(event);
+ }
+
/**
* Runnable to save a bookmark, so it can be performed in its own thread.
*/
private class SaveBookmarkRunnable implements Runnable {
+ // FIXME: This should be an async task.
private Message mMessage;
public SaveBookmarkRunnable(Message msg) {
mMessage = msg;
@@ -133,9 +482,10 @@
// Save to the bookmarks DB.
try {
final ContentResolver cr = getContentResolver();
- Bookmarks.addBookmark(null, cr, url, title, thumbnail, true);
+ Bookmarks.addBookmark(AddBookmarkPage.this, false, url,
+ title, thumbnail, true, mCurrentFolder);
if (touchIconUrl != null) {
- new DownloadTouchIcon(cr, url).execute(mTouchIconUrl);
+ new DownloadTouchIcon(AddBookmarkPage.this, cr, url).execute(mTouchIconUrl);
}
mMessage.arg1 = 1;
} catch (IllegalStateException e) {
@@ -173,8 +523,9 @@
createHandler();
String title = mTitle.getText().toString().trim();
- String unfilteredUrl =
- BrowserActivity.fixUrl(mAddress.getText().toString());
+ String unfilteredUrl;
+ unfilteredUrl = BrowserActivity.fixUrl(mAddress.getText().toString());
+
boolean emptyTitle = title.length() == 0;
boolean emptyUrl = unfilteredUrl.trim().length() == 0;
Resources r = getResources();
@@ -186,6 +537,7 @@
mAddress.setError(r.getText(R.string.bookmark_needs_url));
}
return false;
+
}
String url = unfilteredUrl.trim();
try {
@@ -224,6 +576,8 @@
mMap.putString("title", title);
mMap.putString("url", url);
mMap.putBoolean("invalidateThumbnail", !url.equals(mOriginalUrl));
+ // FIXME: This does not work yet
+ mMap.putLong(BrowserContract.Bookmarks.PARENT, mCurrentFolder);
setResult(RESULT_OK, (new Intent()).setAction(
getIntent().toString()).putExtras(mMap));
} else {
diff --git a/src/com/android/browser/BookmarkUtils.java b/src/com/android/browser/BookmarkUtils.java
new file mode 100644
index 0000000..0fdad15
--- /dev/null
+++ b/src/com/android/browser/BookmarkUtils.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.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+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.provider.Browser;
+import android.util.Log;
+
+class BookmarkUtils {
+ private final static String LOGTAG = "BookmarkUtils";
+
+ // 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";
+
+ enum BookmarkIconType {
+ ICON_INSTALLABLE_WEB_APP, // Icon for an installable web app (launches WebAppRuntime).
+ ICON_HOME_SHORTCUT // Icon for a shortcut on the home screen (launches Browser).
+ };
+
+ /**
+ * Creates an icon to be associated with this bookmark. If available, the apple touch icon
+ * will be used, else we draw our own depending on the type of "bookmark" being created.
+ */
+ static Bitmap createIcon(Context context, Bitmap touchIcon, Bitmap favicon,
+ BookmarkIconType type) {
+ int iconDimension = context.getResources().getDimensionPixelSize(
+ android.R.dimen.app_icon_size);
+
+ Bitmap bm = Bitmap.createBitmap(iconDimension, iconDimension, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bm);
+ Rect iconBounds = new Rect(0, 0, bm.getWidth(), bm.getHeight());
+
+ // Use the apple-touch-icon if available
+ if (touchIcon != null) {
+ drawTouchIconToCanvas(touchIcon, canvas, iconBounds);
+ } else {
+ // No touch icon so create our own.
+ // Set the background based on the type of shortcut (either webapp or home shortcut).
+ Bitmap icon = getIconBackground(context, type);
+
+ if (icon != null) {
+ // Now draw the correct icon background into our new bitmap.
+ canvas.drawBitmap(icon, null, iconBounds, null);
+ }
+
+ // If we have a favicon, overlay it in a nice rounded white box on top of the
+ // background.
+ if (favicon != null) {
+ drawFaviconToCanvas(favicon, canvas, iconBounds,
+ context.getResources().getDisplayMetrics().density);
+ }
+ }
+ return bm;
+ }
+
+ /**
+ * Convenience method for creating an intent that will add a shortcut to the home screen.
+ */
+ static Intent createAddToHomeIntent(Context context, String url, String title,
+ Bitmap touchIcon, Bitmap favicon) {
+ Intent i = new Intent(INSTALL_SHORTCUT);
+ Intent shortcutIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+ long urlHash = url.hashCode();
+ long uniqueId = (urlHash << 32) | shortcutIntent.hashCode();
+ shortcutIntent.putExtra(Browser.EXTRA_APPLICATION_ID, Long.toString(uniqueId));
+ i.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
+ i.putExtra(Intent.EXTRA_SHORTCUT_NAME, title);
+ i.putExtra(Intent.EXTRA_SHORTCUT_ICON, createIcon(context, touchIcon, favicon,
+ BookmarkIconType.ICON_HOME_SHORTCUT));
+
+ // Do not allow duplicate items
+ i.putExtra("duplicate", false);
+ return i;
+ }
+
+ private static Bitmap getIconBackground(Context context, BookmarkIconType type) {
+ if (type == BookmarkIconType.ICON_HOME_SHORTCUT) {
+ // Want to create a shortcut icon on the homescreen, so the icon
+ // background is the red bookmark.
+ return BitmapFactory.decodeResource(context.getResources(),
+ R.drawable.ic_launcher_shortcut_browser_bookmark);
+ } else if (type == BookmarkIconType.ICON_INSTALLABLE_WEB_APP) {
+ // Use the web browser icon as the background for the icon for an installable
+ // web app.
+ return BitmapFactory.decodeResource(context.getResources(),
+ R.drawable.ic_launcher_browser);
+ }
+ return null;
+ }
+
+ private static void drawTouchIconToCanvas(Bitmap touchIcon, Canvas canvas, Rect iconBounds) {
+ Rect src = new Rect(0, 0, touchIcon.getWidth(), touchIcon.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, iconBounds, 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(iconBounds);
+ rect.inset(1, 1);
+ path.addRoundRect(rect, 8f, 8f, Path.Direction.CW);
+
+ // Reuse the paint and clear the outside of the rectangle.
+ paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
+ canvas.drawPath(path, paint);
+ }
+
+ private static void drawFaviconToCanvas(Bitmap favicon, Canvas canvas, Rect iconBounds,
+ float density) {
+ // Make a Paint for the white background rectangle and for
+ // filtering the favicon.
+ Paint p = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
+ p.setStyle(Paint.Style.FILL_AND_STROKE);
+ p.setColor(Color.WHITE);
+
+ // Create a rectangle that is slightly wider than the favicon
+ final float iconSize = 16 * density; // 16x16 favicon
+ final float padding = 2 * density; // white padding around icon
+ final float rectSize = iconSize + 2 * padding;
+ 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);
+
+ // Draw the favicon in the same rectangle as the rounded
+ // rectangle but inset by the padding
+ // (results in a 16x16 favicon).
+ r.inset(padding, padding);
+ canvas.drawBitmap(favicon, null, r, p);
+ }
+
+};
diff --git a/src/com/android/browser/Bookmarks.java b/src/com/android/browser/Bookmarks.java
index 5ada9dc..383ae7f 100644
--- a/src/com/android/browser/Bookmarks.java
+++ b/src/com/android/browser/Bookmarks.java
@@ -20,16 +20,20 @@
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
+import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
-import android.provider.Browser;
+import android.os.AsyncTask;
+import android.preference.PreferenceManager;
+import android.provider.BrowserContract;
+import android.provider.BrowserContract.Combined;
+import android.provider.BrowserContract.Images;
import android.util.Log;
import android.webkit.WebIconDatabase;
import android.widget.Toast;
import java.io.ByteArrayOutputStream;
-import java.util.Date;
/**
* This class is purely to have a common place for adding/deleting bookmarks.
@@ -53,89 +57,38 @@
* @param context Context of the calling Activity. This is used to make
* Toast confirming that the bookmark has been added. If the
* caller provides null, the Toast will not be shown.
- * @param cr The ContentResolver being used to add the bookmark to the db.
* @param url URL of the website to be bookmarked.
* @param name Provided name for the bookmark.
* @param thumbnail A thumbnail for the bookmark.
* @param retainIcon Whether to retain the page's icon in the icon database.
* This will usually be <code>true</code> except when bookmarks are
* added by a settings restore agent.
+ * @param parent ID of the parent folder.
*/
- /* package */ static void addBookmark(Context context,
- ContentResolver cr, String url, String name,
- Bitmap thumbnail, boolean retainIcon) {
+ /* package */ static void addBookmark(Context context, boolean showToast, String url,
+ String name, Bitmap thumbnail, boolean retainIcon, long parent) {
// Want to append to the beginning of the list
- long creationTime = new Date().getTime();
- ContentValues map = new ContentValues();
- Cursor cursor = null;
+ ContentValues values = new ContentValues();
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.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);
- 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);
- }
- }
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ String accountType = prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_TYPE, null);
+ String accountName = prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_NAME, null);
+ values.put(BrowserContract.Bookmarks.ACCOUNT_TYPE, accountType);
+ values.put(BrowserContract.Bookmarks.ACCOUNT_NAME, accountName);
+ values.put(BrowserContract.Bookmarks.TITLE, name);
+ values.put(BrowserContract.Bookmarks.URL, url);
+ values.put(BrowserContract.Bookmarks.IS_FOLDER, 0);
+ values.put(BrowserContract.Bookmarks.THUMBNAIL,
+ bitmapToBytes(thumbnail));
+ values.put(BrowserContract.Bookmarks.PARENT, parent);
+ context.getContentResolver().insert(BrowserContract.Bookmarks.CONTENT_URI, values);
} catch (IllegalStateException e) {
Log.e(LOGTAG, "addBookmark", e);
- } finally {
- if (cursor != null) cursor.close();
}
if (retainIcon) {
WebIconDatabase.getInstance().retainIconForPageUrl(url);
}
- if (context != null) {
+ if (showToast) {
Toast.makeText(context, R.string.added_to_bookmarks,
Toast.LENGTH_LONG).show();
}
@@ -155,40 +108,26 @@
ContentResolver cr, String url, String title) {
Cursor cursor = null;
try {
- cursor = cr.query(
- Browser.BOOKMARKS_URI,
- Browser.HISTORY_PROJECTION,
- "url = ? AND title = ?",
+ cursor = cr.query(BrowserContract.Bookmarks.CONTENT_URI,
+ new String[] { BrowserContract.Bookmarks._ID },
+ BrowserContract.Bookmarks.URL + " = ? AND " +
+ BrowserContract.Bookmarks.TITLE + " = ?",
new String[] { url, title },
null);
- boolean first = cursor.moveToFirst();
+
// Should be in the database no matter what
- if (!first) {
+ if (!cursor.moveToFirst()) {
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!");
- }
- }
+ Uri uri = ContentUris.withAppendedId(BrowserContract.Bookmarks.CONTENT_URI,
+ cursor.getLong(0));
+ cr.delete(uri, null, null);
if (context != null) {
- Toast.makeText(context, R.string.removed_from_bookmarks,
- Toast.LENGTH_LONG).show();
+ Toast.makeText(context, R.string.removed_from_bookmarks, Toast.LENGTH_LONG).show();
}
} catch (IllegalStateException e) {
Log.e(LOGTAG, "removeFromBookmarks", e);
@@ -219,4 +158,86 @@
}
return false;
}
+
+ static final String QUERY_BOOKMARKS_WHERE =
+ Combined.URL + " == ? OR " +
+ Combined.URL + " == ? OR " +
+ Combined.URL + " LIKE ? || '%' OR " +
+ Combined.URL + " LIKE ? || '%'";
+
+ /* package */ static Cursor queryCombinedForUrl(ContentResolver cr,
+ String originalUrl, String url) {
+ if (cr == null || url == null) {
+ return null;
+ }
+
+ // If originalUrl is null, just set it to url.
+ if (originalUrl == null) {
+ originalUrl = url;
+ }
+
+ // Look for both the original url and the actual url. This takes in to
+ // account redirects.
+ String originalUrlNoQuery = removeQuery(originalUrl);
+ String urlNoQuery = removeQuery(url);
+ originalUrl = originalUrlNoQuery + '?';
+ url = urlNoQuery + '?';
+
+ // Use NoQuery to search for the base url (i.e. if the url is
+ // http://www.yahoo.com/?rs=1, search for http://www.yahoo.com)
+ // Use url to match the base url with other queries (i.e. if the url is
+ // http://www.google.com/m, search for
+ // http://www.google.com/m?some_query)
+ final String[] selArgs = new String[] { originalUrlNoQuery, urlNoQuery, originalUrl, url };
+ final String[] projection = new String[] { Combined.URL };
+ return cr.query(Combined.CONTENT_URI, projection, QUERY_BOOKMARKS_WHERE, selArgs, null);
+ }
+
+ // Strip the query from the given url.
+ static String removeQuery(String url) {
+ if (url == null) {
+ return null;
+ }
+ int query = url.indexOf('?');
+ String noQuery = url;
+ if (query != -1) {
+ noQuery = url.substring(0, query);
+ }
+ return noQuery;
+ }
+
+ /**
+ * Update the bookmark's favicon. This is a convenience method for updating
+ * a bookmark favicon for the originalUrl and url of the passed in WebView.
+ * @param cr The ContentResolver to use.
+ * @param originalUrl The original url before any redirects.
+ * @param url The current url.
+ * @param favicon The favicon bitmap to write to the db.
+ */
+ /* package */ static void updateFavicon(final ContentResolver cr,
+ final String originalUrl, final String url, final Bitmap favicon) {
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... unused) {
+ Cursor cursor = queryCombinedForUrl(cr, originalUrl, url);
+ try {
+ if (cursor.moveToFirst()) {
+ final ByteArrayOutputStream os = new ByteArrayOutputStream();
+ favicon.compress(Bitmap.CompressFormat.PNG, 100, os);
+
+ ContentValues values = new ContentValues();
+ values.put(Images.FAVICON, os.toByteArray());
+ values.put(Images.URL, cursor.getString(0));
+
+ do {
+ cr.update(Images.CONTENT_URI, values, null, null);
+ } while (cursor.moveToNext());
+ }
+ } finally {
+ if (cursor != null) cursor.close();
+ }
+ return null;
+ }
+ }.execute();
+ }
}
diff --git a/src/com/android/browser/BookmarksLoader.java b/src/com/android/browser/BookmarksLoader.java
new file mode 100644
index 0000000..770ca60
--- /dev/null
+++ b/src/com/android/browser/BookmarksLoader.java
@@ -0,0 +1,72 @@
+/*
+ * 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.CursorLoader;
+import android.net.Uri;
+import android.provider.BrowserContract.Bookmarks;
+import android.text.TextUtils;
+
+public class BookmarksLoader extends CursorLoader {
+ public static final String ARG_ACCOUNT_TYPE = "acct_type";
+ public static final String ARG_ACCOUNT_NAME = "acct_name";
+
+ public static final int COLUMN_INDEX_ID = 0;
+ public static final int COLUMN_INDEX_URL = 1;
+ public static final int COLUMN_INDEX_TITLE = 2;
+ public static final int COLUMN_INDEX_FAVICON = 3;
+ public static final int COLUMN_INDEX_THUMBNAIL = 4;
+ public static final int COLUMN_INDEX_TOUCH_ICON = 5;
+ public static final int COLUMN_INDEX_IS_FOLDER = 6;
+ public static final int COLUMN_INDEX_PARENT = 8;
+
+ public static final String[] PROJECTION = new String[] {
+ Bookmarks._ID, // 0
+ Bookmarks.URL, // 1
+ Bookmarks.TITLE, // 2
+ Bookmarks.FAVICON, // 3
+ Bookmarks.THUMBNAIL, // 4
+ Bookmarks.TOUCH_ICON, // 5
+ Bookmarks.IS_FOLDER, // 6
+ Bookmarks.POSITION, // 7
+ Bookmarks.PARENT, // 8
+ };
+
+ private String mAccountType;
+ private String mAccountName;
+
+ public BookmarksLoader(Context context, String accountType, String accountName) {
+ super(context, addAccount(Bookmarks.CONTENT_URI_DEFAULT_FOLDER, accountType, accountName),
+ PROJECTION, null, null, null);
+ mAccountType = accountType;
+ mAccountName = accountName;
+ }
+
+ @Override
+ public void setUri(Uri uri) {
+ super.setUri(addAccount(uri, mAccountType, mAccountName));
+ }
+
+ private static Uri addAccount(Uri uri, String accountType, String accountName) {
+ if (!TextUtils.isEmpty(accountType) && !TextUtils.isEmpty(accountName)) {
+ return uri.buildUpon().appendQueryParameter(Bookmarks.PARAM_ACCOUNT_TYPE, accountType).
+ appendQueryParameter(Bookmarks.PARAM_ACCOUNT_NAME, accountName).build();
+ }
+ return uri;
+ }
+}
diff --git a/src/com/android/browser/BrowserActivity.java b/src/com/android/browser/BrowserActivity.java
index deb57f3..4ea96bb 100644
--- a/src/com/android/browser/BrowserActivity.java
+++ b/src/com/android/browser/BrowserActivity.java
@@ -16,13 +16,21 @@
package com.android.browser;
+import com.android.browser.ScrollWebView.ScrollListener;
+import com.android.browser.search.SearchEngine;
+import com.android.common.Search;
+import com.android.common.speech.LoggingEvents;
+
+import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
+import android.app.Dialog;
import android.app.DownloadManager;
import android.app.ProgressDialog;
import android.app.SearchManager;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
+import android.content.ClipboardManager;
import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.ContentProviderClient;
@@ -33,19 +41,16 @@
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.Cursor;
-import android.database.DatabaseUtils;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Picture;
import android.graphics.PixelFormat;
-import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
@@ -61,38 +66,39 @@
import android.os.Message;
import android.os.PowerManager;
import android.os.Process;
-import android.os.ServiceManager;
import android.os.SystemClock;
import android.provider.Browser;
+import android.provider.BrowserContract;
import android.provider.ContactsContract;
+import android.provider.BrowserContract.Images;
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.util.AttributeSet;
import android.util.Log;
import android.util.Patterns;
+import android.view.ActionMode;
import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
+import android.view.MenuItem.OnMenuItemClickListener;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.MenuItem.OnMenuItemClickListener;
+import android.view.accessibility.AccessibilityManager;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.DownloadListener;
import android.webkit.HttpAuthHandler;
-import android.webkit.PluginManager;
import android.webkit.SslErrorHandler;
import android.webkit.URLUtil;
import android.webkit.ValueCallback;
@@ -103,41 +109,30 @@
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
+import android.widget.PopupMenu;
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 com.android.browser.search.SearchEngine;
-import com.android.common.Search;
-import com.android.common.speech.LoggingEvents;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
-import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLEncoder;
-import java.text.ParseException;
+import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
-import java.util.List;
import java.util.Map;
-import java.util.Set;
+import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class BrowserActivity extends Activity
- implements View.OnCreateContextMenuListener, DownloadListener {
+ implements View.OnCreateContextMenuListener, DownloadListener,
+ PopupMenu.OnMenuItemClickListener {
/* 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".
@@ -173,6 +168,11 @@
*/
private FrameLayout mBrowserFrameLayout;
+ private boolean mXLargeScreenSize;
+
+ private Boolean mIsProviderPresent = null;
+ private Uri mRlzUri = null;
+
@Override
public void onCreate(Bundle icicle) {
if (LOGV_ENABLED) {
@@ -188,7 +188,11 @@
BitmapFactory.setDefaultConfig(Bitmap.Config.ARGB_8888);
}
- setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
+ if (AccessibilityManager.getInstance(this).isEnabled()) {
+ setDefaultKeyMode(DEFAULT_KEYS_DISABLE);
+ } else {
+ setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
+ }
mResolver = getContentResolver();
@@ -207,6 +211,13 @@
mMixLockIcon = Resources.getSystem().getDrawable(
android.R.drawable.ic_partial_secure);
+ // Create the tab control and our initial tab
+ mTabControl = new TabControl(this);
+
+ mXLargeScreenSize = (getResources().getConfiguration().screenLayout
+ & Configuration.SCREENLAYOUT_SIZE_MASK)
+ == Configuration.SCREENLAYOUT_SIZE_XLARGE;
+
FrameLayout frameLayout = (FrameLayout) getWindow().getDecorView()
.findViewById(com.android.internal.R.id.content);
mBrowserFrameLayout = (FrameLayout) LayoutInflater.from(this)
@@ -218,13 +229,23 @@
mCustomViewContainer = (FrameLayout) mBrowserFrameLayout
.findViewById(R.id.fullscreen_custom_content);
frameLayout.addView(mBrowserFrameLayout, COVER_SCREEN_PARAMS);
- mTitleBar = new TitleBar(this);
- // mTitleBar will be always shown in the fully loaded mode
- mTitleBar.setProgress(100);
- mFakeTitleBar = new TitleBar(this);
- // Create the tab control and our initial tab
- mTabControl = new TabControl(this);
+ if (mXLargeScreenSize) {
+ mTitleBar = new TitleBarXLarge(this);
+ mTitleBar.setProgress(100);
+ mFakeTitleBar = new TitleBarXLarge(this);
+ ActionBar actionBar = getActionBar();
+ mTabBar = new TabBar(this, mTabControl, (TitleBarXLarge) mFakeTitleBar);
+ actionBar.setCustomNavigationMode(mTabBar);
+ // disable built in zoom controls
+ mTabControl.setDisplayZoomControls(false);
+ } else {
+ mTitleBar = new TitleBar(this);
+ // mTitleBar will be always be shown in the fully loaded mode on
+ // phone
+ mTitleBar.setProgress(100);
+ mFakeTitleBar = new TitleBar(this);
+ }
// Open the icon database and retain all the bookmark urls for favicons
retainIconsOnStartup();
@@ -265,59 +286,19 @@
}
};
- IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
- filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
- filter.addDataScheme("package");
- mPackageInstallationReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- final String packageName = intent.getData()
- .getSchemeSpecificPart();
- final boolean replacing = intent.getBooleanExtra(
- Intent.EXTRA_REPLACING, false);
- if (Intent.ACTION_PACKAGE_REMOVED.equals(action) && replacing) {
- // if it is replacing, refreshPlugins() when adding
- return;
- }
+ // Unless the last browser usage was within 24 hours, destroy any
+ // remaining incognito tabs.
- if (sGoogleApps.contains(packageName)) {
- BrowserActivity.this.packageChanged(packageName,
- Intent.ACTION_PACKAGE_ADDED.equals(action));
- }
+ Calendar lastActiveDate = icicle != null ? (Calendar) icicle.getSerializable("lastActiveDate") : null;
+ Calendar today = Calendar.getInstance();
+ Calendar yesterday = Calendar.getInstance();
+ yesterday.add(Calendar.DATE, -1);
- PackageManager pm = BrowserActivity.this.getPackageManager();
- PackageInfo pkgInfo = null;
- try {
- pkgInfo = pm.getPackageInfo(packageName,
- PackageManager.GET_PERMISSIONS);
- } catch (PackageManager.NameNotFoundException e) {
- return;
- }
- if (pkgInfo != null) {
- String permissions[] = pkgInfo.requestedPermissions;
- if (permissions == null) {
- return;
- }
- boolean permissionOk = false;
- for (String permit : permissions) {
- if (PluginManager.PLUGIN_PERMISSION.equals(permit)) {
- permissionOk = true;
- break;
- }
- }
- if (permissionOk) {
- PluginManager.getInstance(BrowserActivity.this)
- .refreshPlugins(
- Intent.ACTION_PACKAGE_ADDED
- .equals(action));
- }
- }
- }
- };
- registerReceiver(mPackageInstallationReceiver, filter);
+ boolean dontRestoreIncognitoTabs = lastActiveDate == null
+ || lastActiveDate.before(yesterday)
+ || lastActiveDate.after(today);
- if (!mTabControl.restoreState(icicle)) {
+ if (!mTabControl.restoreState(icicle, dontRestoreIncognitoTabs)) {
// clear up the thumbnail directory if we can't restore the state as
// none of the files in the directory are referenced any more.
new ClearThumbnails().execute(
@@ -325,6 +306,8 @@
// there is no quit on Android. But if we can't restore the state,
// we can treat it as a new Browser, remove the old session cookies.
CookieManager.getInstance().removeSessionCookie();
+ // remove any incognito files
+ WebView.cleanupPrivateBrowsingFiles(this);
final Intent intent = getIntent();
final Bundle extra = intent.getExtras();
// Create an initial tab.
@@ -339,7 +322,8 @@
intent.getData() != null)
|| RecognizerResultsIntent.ACTION_VOICE_SEARCH_RESULTS
.equals(action),
- intent.getStringExtra(Browser.EXTRA_APPLICATION_ID), urlData.mUrl);
+ intent.getStringExtra(Browser.EXTRA_APPLICATION_ID),
+ urlData.mUrl, false);
mTabControl.setCurrentTab(t);
attachTabToContentView(t);
WebView webView = t.getWebView();
@@ -356,6 +340,10 @@
loadUrlDataIn(t, urlData);
}
} else {
+ if (dontRestoreIncognitoTabs) {
+ WebView.cleanupPrivateBrowsingFiles(this);
+ }
+
// TabControl.restoreState() will create a new tab even if
// restoring the state fails.
attachTabToContentView(mTabControl.getCurrentTab());
@@ -375,8 +363,6 @@
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
@@ -384,6 +370,10 @@
mSystemAllowGeolocationOrigins.start();
}
+ ScrollListener getScrollListener() {
+ return mTabBar;
+ }
+
/**
* Feed the previously stored results strings to the BrowserProvider so that
* the SearchDialog will show them instead of the standard searches.
@@ -623,13 +613,16 @@
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();
+ if (mTabControl == null || !mTabControl.getCurrentWebView().isPrivateBrowsingEnabled()) {
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... unused) {
+ Browser.updateVisitedHistory(cr, newUrl, false);
+ Browser.addSearchUrl(cr, newUrl);
+ return null;
+ }
+ }.execute();
+ }
SearchEngine searchEngine = mSettings.getSearchEngine();
if (searchEngine == null) return false;
@@ -676,12 +669,17 @@
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();
+ if (mTabControl == null
+ || mTabControl.getCurrentWebView() == null
+ || !mTabControl.getCurrentWebView().isPrivateBrowsingEnabled()) {
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ 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;
@@ -701,16 +699,14 @@
}
/* package */ void showVoiceTitleBar(String title) {
mTitleBar.setInVoiceMode(true);
- mFakeTitleBar.setInVoiceMode(true);
-
mTitleBar.setDisplayTitle(title);
+ mFakeTitleBar.setInVoiceMode(true);
mFakeTitleBar.setDisplayTitle(title);
}
/* package */ void revertVoiceTitleBar() {
mTitleBar.setInVoiceMode(false);
- mFakeTitleBar.setInVoiceMode(false);
-
mTitleBar.setDisplayTitle(mUrl);
+ mFakeTitleBar.setInVoiceMode(false);
mFakeTitleBar.setDisplayTitle(mUrl);
}
/* package */ static String fixUrl(String inUrl) {
@@ -774,7 +770,7 @@
* 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;
+ private TitleBarBase mFakeTitleBar;
/**
* Keeps track of whether the options menu is open. This is important in
@@ -830,9 +826,8 @@
return true;
}
- private void showFakeTitleBar() {
- if (mFakeTitleBar.getParent() == null && mActiveTabsPage == null
- && !mActivityInPause) {
+ void showFakeTitleBar() {
+ if (!isFakeTitleBarShowing() && mActiveTabsPage == null && !mActivityInPause) {
WebView mainView = mTabControl.getCurrentWebView();
// if there is no current WebView, don't show the faked title bar;
if (mainView == null) {
@@ -840,28 +835,31 @@
}
// Do not need to check for null, since the current tab will have
// at least a main WebView, or we would have returned above.
- if (dialogIsUp()) {
- // Do not show the fake title bar, which would cover up the
- // find or select dialog.
+ if (isInCustomActionMode()) {
+ // Do not show the fake title bar, while a custom ActionMode
+ // (i.e. find or select) is showing.
return;
}
+ if (mXLargeScreenSize) {
+ mContentView.addView(mFakeTitleBar);
+ mTabBar.onShowTitleBar();
+ } else {
+ WindowManager manager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
- WindowManager manager
- = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
-
- // Add the title bar to the window manager so it can receive touches
- // while the menu is up
- WindowManager.LayoutParams params
- = new WindowManager.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT,
- WindowManager.LayoutParams.TYPE_APPLICATION,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
- PixelFormat.TRANSLUCENT);
- params.gravity = Gravity.TOP;
- boolean atTop = mainView.getScrollY() == 0;
- params.windowAnimations = atTop ? 0 : R.style.TitleBar;
- manager.addView(mFakeTitleBar, params);
+ // Add the title bar to the window manager so it can receive
+ // touches
+ // while the menu is up
+ WindowManager.LayoutParams params =
+ new WindowManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ WindowManager.LayoutParams.TYPE_APPLICATION,
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+ PixelFormat.TRANSLUCENT);
+ params.gravity = Gravity.TOP;
+ boolean atTop = mainView.getScrollY() == 0;
+ params.windowAnimations = atTop ? 0 : R.style.TitleBar;
+ manager.addView(mFakeTitleBar, params);
+ }
}
}
@@ -878,21 +876,34 @@
}
}
- private void hideFakeTitleBar() {
- if (mFakeTitleBar.getParent() == null) return;
- WindowManager.LayoutParams params = (WindowManager.LayoutParams)
- 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
- // fake title bar was displayed. Make sure it has the appropriate
- // animation/lack thereof before removing.
- params.windowAnimations = mainView != null && mainView.getScrollY() == 0
- ? 0 : R.style.TitleBar;
- WindowManager manager
- = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
- manager.updateViewLayout(mFakeTitleBar, params);
- manager.removeView(mFakeTitleBar);
+ void stopScrolling() {
+ ((ScrollWebView) mTabControl.getCurrentWebView()).stopScroll();
+ }
+
+ void hideFakeTitleBar() {
+ if (!isFakeTitleBarShowing()) return;
+ if (mXLargeScreenSize) {
+ mContentView.removeView(mFakeTitleBar);
+ mTabBar.onHideTitleBar();
+ } else {
+ WindowManager.LayoutParams params =
+ (WindowManager.LayoutParams) 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
+ // fake title bar was displayed. Make sure it has the appropriate
+ // animation/lack thereof before removing.
+ params.windowAnimations =
+ mainView != null && mainView.getScrollY() == 0 ? 0 : R.style.TitleBar;
+ WindowManager manager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
+ manager.updateViewLayout(mFakeTitleBar, params);
+ manager.removeView(mFakeTitleBar);
+ }
+ }
+
+ boolean isFakeTitleBarShowing() {
+ return (mFakeTitleBar.getParent() != null);
}
/**
@@ -933,6 +944,9 @@
// Save all the tabs
mTabControl.saveState(outState);
+
+ // Save time so that we know how old incognito tabs (if any) are.
+ outState.putSerializable("lastActiveDate", Calendar.getInstance());
}
@Override
@@ -994,8 +1008,6 @@
mTabControl.destroy();
WebIconDatabase.getInstance().close();
- unregisterReceiver(mPackageInstallationReceiver);
-
// Stop watching the default geolocation permissions
mSystemAllowGeolocationOrigins.stop();
mSystemAllowGeolocationOrigins = null;
@@ -1124,12 +1136,14 @@
if (mMenu == null) {
return;
}
+ MenuItem dest = mMenu.findItem(R.id.stop_reload_menu_id);
MenuItem src = mInLoad ?
mMenu.findItem(R.id.stop_menu_id):
- mMenu.findItem(R.id.reload_menu_id);
- MenuItem dest = mMenu.findItem(R.id.stop_reload_menu_id);
- dest.setIcon(src.getIcon());
- dest.setTitle(src.getTitle());
+ mMenu.findItem(R.id.reload_menu_id);
+ if (src != null) {
+ dest.setIcon(src.getIcon());
+ dest.setTitle(src.getTitle());
+ }
}
@Override
@@ -1156,7 +1170,6 @@
break;
// -- Browser context menu
case R.id.open_context_menu_id:
- case R.id.open_newtab_context_menu_id:
case R.id.bookmark_context_menu_id:
case R.id.save_link_context_menu_id:
case R.id.share_link_context_menu_id:
@@ -1280,6 +1293,7 @@
*/
/* package */ void removeActiveTabPage(boolean needToAttach) {
mContentView.removeView(mActiveTabsPage);
+ mTitleBar.setVisibility(View.VISIBLE);
mActiveTabsPage = null;
mMenuState = R.id.MAIN_MENU;
if (needToAttach) {
@@ -1288,23 +1302,22 @@
getTopWindow().requestFocus();
}
- private WebView showDialog(WebDialog dialog) {
- Tab tab = mTabControl.getCurrentTab();
- if (tab.getSubWebView() == null) {
- // If the find or select is being performed on the main webview,
- // remove the embedded title bar.
- WebView mainView = tab.getWebView();
- if (mainView != null) {
- mainView.setEmbeddedTitleBar(null);
- }
- }
+ @Override
+ public ActionMode onStartActionMode(ActionMode.Callback callback) {
+ mActionMode = super.onStartActionMode(callback);
hideFakeTitleBar();
- mMenuState = EMPTY_MENU;
- return tab.showDialog(dialog);
+ // Would like to change the MENU, but onEndActionMode may not be called
+ return mActionMode;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
+ // check the action bar button before mCanChord check, as the prepare call
+ // doesn't come for action bar buttons
+ if (item.getItemId() == R.id.newtab) {
+ openTabToHomePage();
+ return true;
+ }
if (!mCanChord) {
// The user has already fired a shortcut with this hold down of the
// menu key.
@@ -1326,17 +1339,22 @@
openTabToHomePage();
break;
+ case R.id.incognito_menu_id:
+ openIncognitoTab();
+ break;
+
case R.id.goto_menu_id:
editUrl();
break;
case R.id.bookmarks_menu_id:
- bookmarksOrHistoryPicker(false);
+ bookmarksOrHistoryPicker(false, false);
break;
case R.id.active_tabs_menu_id:
mActiveTabsPage = new ActiveTabsPage(this, mTabControl);
removeTabFromContentView(mTabControl.getCurrentTab());
+ mTitleBar.setVisibility(View.GONE);
hideFakeTitleBar();
mContentView.addView(mActiveTabsPage, COVER_SCREEN_PARAMS);
mActiveTabsPage.requestFocus();
@@ -1344,14 +1362,7 @@
break;
case R.id.add_bookmark_menu_id:
- Intent i = new Intent(BrowserActivity.this,
- AddBookmarkPage.class);
- WebView w = getTopWindow();
- i.putExtra("url", w.getUrl());
- i.putExtra("title", w.getTitle());
- i.putExtra("touch_icon_url", w.getTouchIconUrl());
- i.putExtra("thumbnail", createScreenshot(w));
- startActivity(i);
+ bookmarkCurrentPage();
break;
case R.id.stop_reload_menu_id:
@@ -1396,17 +1407,39 @@
break;
case R.id.find_menu_id:
- showFindDialog();
+ getTopWindow().showFindDialog(null);
break;
- case R.id.select_text_id:
- if (true) {
- Tab currentTab = mTabControl.getCurrentTab();
- if (currentTab != null) {
- currentTab.getWebView().setUpSelect();
+ case R.id.save_webarchive_menu_id:
+ if (LOGD_ENABLED) {
+ Log.d(LOGTAG, "Save as Web Archive");
+ }
+ String state = Environment.getExternalStorageState();
+ if (Environment.MEDIA_MOUNTED.equals(state)) {
+ String directory = Environment.getExternalStoragePublicDirectory(
+ Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + File.separator;
+ File dir = new File(directory);
+ if (!dir.exists() && !dir.mkdirs()) {
+ Log.e(LOGTAG, "Save as Web Archive: mkdirs for " + directory + " failed!");
+ Toast.makeText(BrowserActivity.this, R.string.webarchive_failed,
+ Toast.LENGTH_SHORT).show();
+ break;
}
+ getTopWindow().saveWebArchive(directory, true, new ValueCallback<String>() {
+ @Override
+ public void onReceiveValue(String value) {
+ if (value != null) {
+ Toast.makeText(BrowserActivity.this, R.string.webarchive_saved,
+ Toast.LENGTH_SHORT).show();
+ } else {
+ Toast.makeText(BrowserActivity.this, R.string.webarchive_failed,
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
} else {
- showSelectDialog();
+ Toast.makeText(BrowserActivity.this, R.string.webarchive_failed,
+ Toast.LENGTH_SHORT).show();
}
break;
@@ -1415,7 +1448,7 @@
break;
case R.id.classic_history_menu_id:
- bookmarksOrHistoryPicker(true);
+ bookmarksOrHistoryPicker(true, false);
break;
case R.id.title_bar_share_page_url:
@@ -1428,7 +1461,8 @@
currentTab.populatePickerData();
sharePage(this, currentTab.getTitle(),
currentTab.getUrl(), currentTab.getFavicon(),
- createScreenshot(currentTab.getWebView()));
+ createScreenshot(currentTab.getWebView(), getDesiredThumbnailWidth(this),
+ getDesiredThumbnailHeight(this)));
break;
case R.id.dump_nav_menu_id:
@@ -1484,60 +1518,56 @@
return true;
}
- private boolean dialogIsUp() {
- return null != mFindDialog && mFindDialog.isVisible() ||
- null != mSelectDialog && mSelectDialog.isVisible();
- }
-
- private boolean closeDialog(WebDialog dialog) {
- if (null == dialog || !dialog.isVisible()) return false;
- Tab currentTab = mTabControl.getCurrentTab();
- currentTab.closeDialog(dialog);
- dialog.dismiss();
- return true;
+ /* package */ void bookmarkCurrentPage() {
+ Intent i = new Intent(BrowserActivity.this,
+ AddBookmarkPage.class);
+ WebView w = getTopWindow();
+ i.putExtra("url", w.getUrl());
+ i.putExtra("title", w.getTitle());
+ i.putExtra("touch_icon_url", w.getTouchIconUrl());
+ i.putExtra("thumbnail", createScreenshot(w, getDesiredThumbnailWidth(this),
+ getDesiredThumbnailHeight(this)));
+ startActivity(i);
}
/*
- * Remove the find dialog or select dialog.
+ * True if a custom ActionMode (i.e. find or select) is in use.
*/
- public void closeDialogs() {
- if (!(closeDialog(mFindDialog) || closeDialog(mSelectDialog))) return;
- // If the Find was being performed in the main WebView, replace the
- // embedded title bar.
- Tab currentTab = mTabControl.getCurrentTab();
- if (currentTab.getSubWebView() == null) {
- WebView mainView = currentTab.getWebView();
- if (mainView != null) {
- mainView.setEmbeddedTitleBar(mTitleBar);
- }
+ private boolean isInCustomActionMode() {
+ return mActionMode != null;
+ }
+
+ /*
+ * End the current ActionMode.
+ */
+ void endActionMode() {
+ if (mActionMode != null) {
+ ActionMode mode = mActionMode;
+ onEndActionMode();
+ mode.finish();
}
- mMenuState = R.id.MAIN_MENU;
+ }
+
+ /*
+ * Called by find and select when they are finished. Replace title bars
+ * as necessary.
+ */
+ public void onEndActionMode() {
+ if (!isInCustomActionMode()) return;
if (mInLoad) {
// The title bar was hidden, because otherwise it would cover up the
- // find or select dialog. Now that the dialog has been removed,
+ // find or select dialog. Now that the dialog has been removed,
// show the fake title bar once again.
showFakeTitleBar();
}
+ // Would like to return the menu state to normal, but this does not
+ // necessarily get called.
+ mActionMode = null;
}
- public void showFindDialog() {
- if (null == mFindDialog) {
- mFindDialog = new FindDialog(this);
- }
- showDialog(mFindDialog).setFindIsUp(true);
- }
-
- public void setFindDialogText(String text) {
- mFindDialog.setText(text);
- }
-
- public void showSelectDialog() {
- if (null == mSelectDialog) {
- mSelectDialog = new SelectDialog(this);
- }
- showDialog(mSelectDialog).setUpSelect();
- mSelectDialog.hideSoftInput();
- }
+ // For select and find, we keep track of the ActionMode so that
+ // finish() can be called as desired.
+ private ActionMode mActionMode;
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
@@ -1577,11 +1607,13 @@
final MenuItem home = menu.findItem(R.id.homepage_menu_id);
home.setEnabled(!isHome);
- menu.findItem(R.id.forward_menu_id)
- .setEnabled(canGoForward);
+ final MenuItem forward = menu.findItem(R.id.forward_menu_id);
+ forward.setEnabled(canGoForward);
- menu.findItem(R.id.new_tab_menu_id).setEnabled(
- mTabControl.canCreateNewTab());
+ if (!mXLargeScreenSize) {
+ final MenuItem newtab = menu.findItem(R.id.new_tab_menu_id);
+ newtab.setEnabled(mTabControl.canCreateNewTab());
+ }
// decide whether to show the share link option
PackageManager pm = getPackageManager();
@@ -1609,7 +1641,7 @@
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
- if (v instanceof TitleBar) {
+ if (v instanceof TitleBarBase) {
return;
}
WebView webview = (WebView) v;
@@ -1636,7 +1668,7 @@
inflater.inflate(R.menu.browsercontext, menu);
// Show the correct menu group
- String extra = result.getExtra();
+ final String extra = result.getExtra();
menu.setGroupVisible(R.id.PHONE_MENU,
type == WebView.HitTestResult.PHONE_TYPE);
menu.setGroupVisible(R.id.EMAIL_MENU,
@@ -1693,8 +1725,23 @@
titleView.setText(extra);
menu.setHeaderView(titleView);
// decide whether to show the open link in new tab option
- menu.findItem(R.id.open_newtab_context_menu_id).setVisible(
- mTabControl.canCreateNewTab());
+ boolean showNewTab = mTabControl.canCreateNewTab();
+ MenuItem newTabItem
+ = menu.findItem(R.id.open_newtab_context_menu_id);
+ newTabItem.setVisible(showNewTab);
+ if (showNewTab) {
+ newTabItem.setOnMenuItemClickListener(
+ new MenuItem.OnMenuItemClickListener() {
+ public boolean onMenuItemClick(MenuItem item) {
+ final Tab parent = mTabControl.getCurrentTab();
+ final Tab newTab = openTab(extra, false);
+ if (newTab != parent) {
+ parent.addChildTab(newTab);
+ }
+ return true;
+ }
+ });
+ }
menu.findItem(R.id.bookmark_context_menu_id).setVisible(
Bookmarks.urlHasAcceptableScheme(extra));
PackageManager pm = getPackageManager();
@@ -1754,6 +1801,9 @@
}
// Request focus on the top window.
t.getTopWindow().requestFocus();
+ if (mTabControl.getTabChangeListener() != null) {
+ mTabControl.getTabChangeListener().onCurrentTab(t);
+ }
}
// Attach a sub window to the main WebView of the given tab.
@@ -1801,7 +1851,7 @@
final Tab currentTab = mTabControl.getCurrentTab();
if (mTabControl.canCreateNewTab()) {
final Tab tab = mTabControl.createNewTab(closeOnExit, appId,
- urlData.mUrl);
+ urlData.mUrl, false);
WebView webview = tab.getWebView();
// If the last tab was removed from the active tabs page, currentTab
// will be null.
@@ -1827,8 +1877,8 @@
}
}
- private Tab openTab(String url) {
- if (mSettings.openInBackground()) {
+ private Tab openTab(String url, boolean forceForeground) {
+ if (mSettings.openInBackground() && !forceForeground) {
Tab t = mTabControl.createNewTab();
if (t != null) {
WebView view = t.getWebView();
@@ -1840,6 +1890,20 @@
}
}
+ /* package */ Tab openIncognitoTab() {
+ if (mTabControl.canCreateNewTab()) {
+ Tab currentTab = mTabControl.getCurrentTab();
+ Tab tab = mTabControl.createNewTab(false, null, null, true);
+ if (currentTab != null) {
+ removeTabFromContentView(currentTab);
+ }
+ mTabControl.setCurrentTab(tab);
+ attachTabToContentView(tab);
+ return tab;
+ }
+ return null;
+ }
+
private class Copy implements OnMenuItemClickListener {
private CharSequence mText;
@@ -1900,6 +1964,7 @@
return true;
}
+ @Override
public void run() {
Drawable oldWallpaper = BrowserActivity.this.getWallpaper();
try {
@@ -1943,14 +2008,8 @@
}
private void copy(CharSequence text) {
- try {
- IClipboard clip = IClipboard.Stub.asInterface(ServiceManager.getService("clipboard"));
- if (clip != null) {
- clip.setClipboardText(text);
- }
- } catch (android.os.RemoteException e) {
- Log.e(LOGTAG, "Copy failed", e);
- }
+ ClipboardManager cm = (ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE);
+ cm.setText(text);
}
/**
@@ -2063,6 +2122,11 @@
}
mTabControl.setCurrentTab(mTabControl.getTab(currentIndex));
resetTitleIconAndProgress();
+ updateLockIconToLatest();
+
+ if (!mTabControl.hasAnyOpenIncognitoTabs()) {
+ WebView.cleanupPrivateBrowsingFiles(this);
+ }
}
/* package */ void goBackOnePageOrQuit() {
@@ -2161,7 +2225,7 @@
return true;
} else if (mCustomView == null && mActiveTabsPage == null
&& event.isLongPress()) {
- bookmarksOrHistoryPicker(true);
+ bookmarksOrHistoryPicker(true, false);
return true;
}
break;
@@ -2254,11 +2318,19 @@
static final int UPDATE_BOOKMARK_THUMBNAIL = 108;
+ private static final int TOUCH_ICON_DOWNLOADED = 109;
+
+ private static final int OPEN_BOOKMARKS = 201;
+
// Private handler for handling javascript and saving passwords
private Handler mHandler = new Handler() {
+ @Override
public void handleMessage(Message msg) {
switch (msg.what) {
+ case OPEN_BOOKMARKS:
+ bookmarksOrHistoryPicker(false, false);
+ break;
case FOCUS_NODE_HREF:
{
String url = (String) msg.getData().get("url");
@@ -2277,13 +2349,6 @@
case R.id.view_image_context_menu_id:
loadUrlFromContext(getTopWindow(), url);
break;
- case R.id.open_newtab_context_menu_id:
- final Tab parent = mTabControl.getCurrentTab();
- final Tab newTab = openTab(url);
- if (newTab != parent) {
- parent.addChildTab(newTab);
- }
- break;
case R.id.bookmark_context_menu_id:
Intent intent = new Intent(BrowserActivity.this,
AddBookmarkPage.class);
@@ -2292,41 +2357,8 @@
startActivity(intent);
break;
case R.id.share_link_context_menu_id:
- // See if this site has been visited before
- StringBuilder sb = new StringBuilder(
- Browser.BookmarkColumns.URL + " = ");
- DatabaseUtils.appendEscapedSQLString(sb, url);
- Cursor c = mResolver.query(Browser.BOOKMARKS_URI,
- Browser.HISTORY_PROJECTION,
- sb.toString(),
- null,
+ sharePage(BrowserActivity.this, title, url, null,
null);
- if (c.moveToFirst()) {
- // The site has been visited before, so grab the
- // info from the database.
- Bitmap favicon = null;
- Bitmap thumbnail = null;
- String linkTitle = c.getString(Browser.
- HISTORY_PROJECTION_TITLE_INDEX);
- byte[] data = c.getBlob(Browser.
- HISTORY_PROJECTION_FAVICON_INDEX);
- if (data != null) {
- favicon = BitmapFactory.decodeByteArray(
- data, 0, data.length);
- }
- data = c.getBlob(Browser.
- HISTORY_PROJECTION_THUMBNAIL_INDEX);
- if (data != null) {
- thumbnail = BitmapFactory.decodeByteArray(
- data, 0, data.length);
- }
- sharePage(BrowserActivity.this,
- linkTitle, url, favicon, thumbnail);
- } else {
- Browser.sendString(BrowserActivity.this, url,
- getString(
- R.string.choosertitle_sharevia));
- }
break;
case R.id.copy_link_context_menu_id:
copy(url);
@@ -2363,6 +2395,14 @@
updateScreenshot(view);
}
break;
+
+ case TOUCH_ICON_DOWNLOADED:
+ Bundle b = msg.getData();
+ showSaveToHomescreenDialog(b.getString("url"),
+ b.getString("title"),
+ (Bitmap) b.getParcelable("touchIcon"),
+ (Bitmap) b.getParcelable("favicon"));
+ break;
}
}
};
@@ -2403,7 +2443,8 @@
// draw, but the API for that (WebViewCore.pictureReady()) is not
// currently accessible here.
- final Bitmap bm = createScreenshot(view);
+ final Bitmap bm = createScreenshot(view, getDesiredThumbnailWidth(this),
+ getDesiredThumbnailHeight(this));
if (bm == null) {
return;
}
@@ -2415,29 +2456,25 @@
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... unused) {
- Cursor c = null;
+ Cursor cursor = 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());
- }
+ cursor = Bookmarks.queryCombinedForUrl(cr, originalUrl, url);
+ if (cursor != null && cursor.moveToFirst()) {
+ final ByteArrayOutputStream os = new ByteArrayOutputStream();
+ bm.compress(Bitmap.CompressFormat.PNG, 100, os);
+
+ ContentValues values = new ContentValues();
+ values.put(Images.THUMBNAIL, os.toByteArray());
+ values.put(Images.URL, cursor.getString(0));
+
+ do {
+ cr.update(Images.CONTENT_URI, values, null, null);
+ } while (cursor.moveToNext());
}
} catch (IllegalStateException e) {
// Ignore
} finally {
- if (c != null) c.close();
+ if (cursor != null) cursor.close();
}
return null;
}
@@ -2445,47 +2482,31 @@
}
/**
- * Values for the size of the thumbnail created when taking a screenshot.
- * Lazily initialized. Instead of using these directly, use
- * getDesiredThumbnailWidth() or getDesiredThumbnailHeight().
- */
- private static int THUMBNAIL_WIDTH = 0;
- private static int THUMBNAIL_HEIGHT = 0;
-
- /**
* Return the desired width for thumbnail screenshots, which are stored in
* the database, and used on the bookmarks screen.
* @param context Context for finding out the density of the screen.
- * @return int desired width for thumbnail screenshot.
+ * @return desired width for thumbnail screenshot.
*/
/* package */ static int getDesiredThumbnailWidth(Context context) {
- if (THUMBNAIL_WIDTH == 0) {
- float density = context.getResources().getDisplayMetrics().density;
- THUMBNAIL_WIDTH = (int) (90 * density);
- THUMBNAIL_HEIGHT = (int) (80 * density);
- }
- return THUMBNAIL_WIDTH;
+ return context.getResources().getDimensionPixelOffset(R.dimen.bookmarkThumbnailWidth);
}
/**
* Return the desired height for thumbnail screenshots, which are stored in
* the database, and used on the bookmarks screen.
* @param context Context for finding out the density of the screen.
- * @return int desired height for thumbnail screenshot.
+ * @return desired height for thumbnail screenshot.
*/
/* package */ static int getDesiredThumbnailHeight(Context context) {
- // To ensure that they are both initialized.
- getDesiredThumbnailWidth(context);
- return THUMBNAIL_HEIGHT;
+ return context.getResources().getDimensionPixelOffset(R.dimen.bookmarkThumbnailHeight);
}
- private Bitmap createScreenshot(WebView view) {
+ private Bitmap createScreenshot(WebView view, int width, int height) {
Picture thumbnail = view.capturePicture();
if (thumbnail == null) {
return null;
}
- Bitmap bm = Bitmap.createBitmap(getDesiredThumbnailWidth(this),
- getDesiredThumbnailHeight(this), Bitmap.Config.RGB_565);
+ Bitmap bm = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bm);
// May need to tweak these values to determine what is the
// best scale factor
@@ -2494,8 +2515,7 @@
float scaleFactorX = 1.0f;
float scaleFactorY = 1.0f;
if (thumbnailWidth > 0) {
- scaleFactorX = (float) getDesiredThumbnailWidth(this) /
- (float)thumbnailWidth;
+ scaleFactorX = (float) width / (float)thumbnailWidth;
} else {
return null;
}
@@ -2505,8 +2525,7 @@
// 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;
+ scaleFactorY = (float) height / (float)thumbnailHeight;
} else {
// In the portrait case, this looks nice.
scaleFactorY = scaleFactorX;
@@ -2547,7 +2566,7 @@
onProgressChanged(view, INITIAL_PROGRESS);
mDidStopLoad = false;
if (!mIsNetworkUp) createAndShowNetworkDialog();
- closeDialogs();
+ endActionMode();
if (mSettings.isTracing()) {
String host;
try {
@@ -2645,7 +2664,25 @@
}
}
+ private void closeEmptyChildTab() {
+ Tab current = mTabControl.getCurrentTab();
+ if (current != null
+ && current.getWebView().copyBackForwardList().getSize() == 0) {
+ Tab parent = current.getParentTab();
+ if (parent != null) {
+ switchToTab(mTabControl.getTabIndex(parent));
+ closeTab(current);
+ }
+ }
+ }
+
boolean shouldOverrideUrlLoading(WebView view, String url) {
+ if (view.isPrivateBrowsingEnabled()) {
+ // Don't allow urls to leave the browser app when in private browsing mode
+ loadUrl(view, url);
+ return true;
+ }
+
if (url.startsWith(SCHEME_WTAI)) {
// wtai://wp/mc;number
// number=string(phone-number)
@@ -2654,6 +2691,11 @@
Uri.parse(WebView.SCHEME_TEL +
url.substring(SCHEME_WTAI_MC.length())));
startActivity(intent);
+ // before leaving BrowserActivity, close the empty child tab.
+ // If a new tab is created through JavaScript open to load this
+ // url, we would like to close it as we will load this url in a
+ // different Activity.
+ closeEmptyChildTab();
return true;
}
// wtai://wp/sd;dtmf
@@ -2677,6 +2719,29 @@
return false;
}
+ // If this is a Google search, attempt to add an RLZ string (if one isn't already present).
+ if (rlzProviderPresent()) {
+ Uri siteUri = Uri.parse(url);
+ if (needsRlzString(siteUri)) {
+ String rlz = null;
+ Cursor cur = null;
+ try {
+ cur = getContentResolver().query(getRlzUri(), null, null, null, null);
+ if (cur != null && cur.moveToFirst() && !cur.isNull(0)) {
+ url = siteUri.buildUpon()
+ .appendQueryParameter("rlz", cur.getString(0))
+ .build().toString();
+ }
+ } finally {
+ if (cur != null) {
+ cur.close();
+ }
+ }
+ loadUrl(view, url);
+ return true;
+ }
+ }
+
Intent intent;
// perform generic parsing of the URI to turn it into an Intent.
try {
@@ -2695,6 +2760,11 @@
.parse("market://search?q=pname:" + packagename));
intent.addCategory(Intent.CATEGORY_BROWSABLE);
startActivity(intent);
+ // before leaving BrowserActivity, close the empty child tab.
+ // If a new tab is created through JavaScript open to load this
+ // url, we would like to close it as we will load this url in a
+ // different Activity.
+ closeEmptyChildTab();
return true;
} else {
return false;
@@ -2707,6 +2777,11 @@
intent.setComponent(null);
try {
if (startActivityIfNeeded(intent, -1)) {
+ // before leaving BrowserActivity, close the empty child tab.
+ // If a new tab is created through JavaScript open to load this
+ // url, we would like to close it as we will load this url in a
+ // different Activity.
+ closeEmptyChildTab();
return true;
}
} catch (ActivityNotFoundException ex) {
@@ -2715,18 +2790,78 @@
}
if (mMenuIsDown) {
- openTab(url);
+ openTab(url, false);
closeOptionsMenu();
return true;
}
return false;
}
+ // Determine whether the RLZ provider is present on the system.
+ private boolean rlzProviderPresent() {
+ if (mIsProviderPresent == null) {
+ PackageManager pm = getPackageManager();
+ mIsProviderPresent = pm.resolveContentProvider(BrowserSettings.RLZ_PROVIDER, 0) != null;
+ }
+ return mIsProviderPresent;
+ }
+
+ // Retrieve the RLZ access point string and cache the URI used to retrieve RLZ values.
+ private Uri getRlzUri() {
+ if (mRlzUri == null) {
+ String ap = getResources().getString(R.string.rlz_access_point);
+ mRlzUri = Uri.withAppendedPath(BrowserSettings.RLZ_PROVIDER_URI, ap);
+ }
+ return mRlzUri;
+ }
+
+ // Determine if this URI appears to be for a Google search and does not have an RLZ parameter.
+ // Taken largely from Chrome source, src/chrome/browser/google_url_tracker.cc
+ private static boolean needsRlzString(Uri uri) {
+ String scheme = uri.getScheme();
+ if (("http".equals(scheme) || "https".equals(scheme)) &&
+ (uri.getQueryParameter("q") != null) && (uri.getQueryParameter("rlz") == null)) {
+ String host = uri.getHost();
+ if (host == null) {
+ return false;
+ }
+ String[] hostComponents = host.split("\\.");
+
+ if (hostComponents.length < 2) {
+ return false;
+ }
+ int googleComponent = hostComponents.length - 2;
+ String component = hostComponents[googleComponent];
+ if (!"google".equals(component)) {
+ if (hostComponents.length < 3 ||
+ (!"co".equals(component) && !"com".equals(component))) {
+ return false;
+ }
+ googleComponent = hostComponents.length - 3;
+ if (!"google".equals(hostComponents[googleComponent])) {
+ return false;
+ }
+ }
+
+ // Google corp network handling.
+ if (googleComponent > 0 && "corp".equals(hostComponents[googleComponent - 1])) {
+ return false;
+ }
+
+ return true;
+ }
+ return false;
+ }
+
// -------------------------------------------------------------------------
// Helper function for WebChromeClient
// -------------------------------------------------------------------------
void onProgressChanged(WebView view, int newProgress) {
+
+ // On the phone, the fake title bar will always cover up the
+ // regular title bar (or the regular one is offscreen), so only the
+ // fake title bar needs to change its progress
mFakeTitleBar.setProgress(newProgress);
if (newProgress == 100) {
@@ -2828,15 +2963,138 @@
* The Object used to inform the WebView of the file to upload.
*/
private ValueCallback<Uri> mUploadMessage;
+ private String mCameraFilePath;
- void openFileChooser(ValueCallback<Uri> uploadMsg) {
- if (mUploadMessage != null) return;
+ void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
+
+ final String imageMimeType = "image/*";
+ final String videoMimeType = "video/*";
+ final String audioMimeType = "audio/*";
+ final String mediaSourceKey = "capture";
+ final String mediaSourceValueCamera = "camera";
+ final String mediaSourceValueFileSystem = "filesystem";
+ final String mediaSourceValueCamcorder = "camcorder";
+ final String mediaSourceValueMicrophone = "microphone";
+
+ // media source can be 'filesystem' or 'camera' or 'camcorder' or 'microphone'.
+ String mediaSource = "";
+
+ // We add the camera intent if there was no accept type (or '*/*' or 'image/*').
+ boolean addCameraIntent = true;
+ // We add the camcorder intent if there was no accept type (or '*/*' or 'video/*').
+ boolean addCamcorderIntent = true;
+
+ if (mUploadMessage != null) {
+ // Already a file picker operation in progress.
+ return;
+ }
+
mUploadMessage = uploadMsg;
+
+ // Parse the accept type.
+ String params[] = acceptType.split(";");
+ String mimeType = params[0];
+
+ for (String p : params) {
+ String[] keyValue = p.split("=");
+ if (keyValue.length == 2) {
+ // Process key=value parameters.
+ if (mediaSourceKey.equals(keyValue[0])) {
+ mediaSource = keyValue[1];
+ }
+ }
+ }
+
+ // This intent will display the standard OPENABLE file picker.
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
- i.setType("*/*");
- BrowserActivity.this.startActivityForResult(Intent.createChooser(i,
- getString(R.string.choose_upload)), FILE_SELECTED);
+
+ // Create an intent to add to the standard file picker that will
+ // capture an image from the camera. We'll combine this intent with
+ // the standard OPENABLE picker unless the web developer specifically
+ // requested the camera or gallery be opened by passing a parameter
+ // in the accept type.
+ Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
+ File externalDataDir = Environment.getExternalStoragePublicDirectory(
+ Environment.DIRECTORY_DCIM);
+ File cameraDataDir = new File(externalDataDir.getAbsolutePath() +
+ File.separator + "browser-photos");
+ cameraDataDir.mkdirs();
+ mCameraFilePath = cameraDataDir.getAbsolutePath() + File.separator +
+ System.currentTimeMillis() + ".jpg";
+ cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(mCameraFilePath)));
+
+ Intent camcorderIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
+
+ Intent soundRecIntent = new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
+
+ if (mimeType.equals(imageMimeType)) {
+ i.setType(imageMimeType);
+ addCamcorderIntent = false;
+ if (mediaSource.equals(mediaSourceValueCamera)) {
+ // Specified 'image/*' and requested the camera, so go ahead and launch the camera
+ // directly.
+ BrowserActivity.this.startActivityForResult(cameraIntent, FILE_SELECTED);
+ return;
+ } else if (mediaSource.equals(mediaSourceValueFileSystem)) {
+ // Specified filesytem as the source, so don't want to consider the camera.
+ addCameraIntent = false;
+ }
+ } else if (mimeType.equals(videoMimeType)) {
+ i.setType(videoMimeType);
+ addCameraIntent = false;
+ // The camcorder saves it's own file and returns it to us in the intent, so
+ // we don't need to generate one here.
+ mCameraFilePath = null;
+
+ if (mediaSource.equals(mediaSourceValueCamcorder)) {
+ // Specified 'video/*' and requested the camcorder, so go ahead and launch the
+ // camcorder directly.
+ BrowserActivity.this.startActivityForResult(camcorderIntent, FILE_SELECTED);
+ return;
+ } else if (mediaSource.equals(mediaSourceValueFileSystem)) {
+ // Specified filesystem as the source, so don't want to consider the camcorder.
+ addCamcorderIntent = false;
+ }
+ } else if (mimeType.equals(audioMimeType)) {
+ i.setType(audioMimeType);
+ addCameraIntent = false;
+ addCamcorderIntent = false;
+ if (mediaSource.equals(mediaSourceValueMicrophone)) {
+ // Specified 'audio/*' and requested microphone, so go ahead and launch the sound
+ // recorder.
+ BrowserActivity.this.startActivityForResult(soundRecIntent, FILE_SELECTED);
+ return;
+ }
+ // On a default system, there is no single option to open an audio "gallery". Both the
+ // sound recorder and music browser respond to the OPENABLE/audio/* intent unlike the
+ // image/* and video/* OPENABLE intents where the image / video gallery are the only
+ // respondants (and so the user is not prompted by default).
+ } else {
+ i.setType("*/*");
+ }
+
+ // Combine the chooser and the extra choices (like camera or camcorder)
+ Intent chooser = new Intent(Intent.ACTION_CHOOSER);
+ chooser.putExtra(Intent.EXTRA_INTENT, i);
+
+ Vector<Intent> extraInitialIntents = new Vector<Intent>(0);
+
+ if (addCameraIntent) {
+ extraInitialIntents.add(cameraIntent);
+ }
+
+ if (addCamcorderIntent) {
+ extraInitialIntents.add(camcorderIntent);
+ }
+
+ if (extraInitialIntents.size() > 0) {
+ Intent[] extraIntents = new Intent[extraInitialIntents.size()];
+ chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraInitialIntents.toArray(extraIntents));
+ }
+
+ chooser.putExtra(Intent.EXTRA_TITLE, getString(R.string.choose_upload));
+ BrowserActivity.this.startActivityForResult(chooser, FILE_SELECTED);
}
// -------------------------------------------------------------------------
@@ -3023,7 +3281,10 @@
* Update the lock icon to correspond to our latest state.
*/
private void updateLockIconToLatest() {
- updateLockIconImage(mTabControl.getCurrentTab().getLockIconType());
+ Tab t = mTabControl.getCurrentTab();
+ if (t != null) {
+ updateLockIconImage(t.getLockIconType());
+ }
}
/**
@@ -3527,16 +3788,33 @@
if (resultCode == RESULT_OK && intent != null) {
String data = intent.getAction();
Bundle extras = intent.getExtras();
- if (extras != null && extras.getBoolean("new_window", false)) {
- openTab(data);
+ if (extras != null &&
+ extras.getBoolean(
+ CombinedBookmarkHistoryActivity.EXTRA_OPEN_NEW_WINDOW,
+ false)) {
+ openTab(data, false);
+ } else if ((extras != null) &&
+ extras.getBoolean(CombinedBookmarkHistoryActivity.NEWTAB_MODE)) {
+ openTab(data, true);
} else {
- final Tab currentTab =
- mTabControl.getCurrentTab();
+ final Tab currentTab = mTabControl.getCurrentTab();
dismissSubWindow(currentTab);
if (data != null && data.length() != 0) {
loadUrl(getTopWindow(), data);
}
}
+ } else if (resultCode == RESULT_CANCELED) {
+ if (intent != null) {
+ float evtx = intent.getFloatExtra(CombinedBookmarkHistoryActivity.EVT_X, -1);
+ float evty = intent.getFloatExtra(CombinedBookmarkHistoryActivity.EVT_Y, -1);
+ long now = System.currentTimeMillis();
+ MotionEvent evt = MotionEvent.obtain(now, now,
+ MotionEvent.ACTION_DOWN, evtx, evty, 0);
+ dispatchTouchEvent(evt);
+ MotionEvent up = MotionEvent.obtain(evt);
+ up.setAction(MotionEvent.ACTION_UP);
+ dispatchTouchEvent(up);
+ }
}
// Deliberately fall through to PREFERENCES_PAGE, since the
// same extra may be attached to the COMBO_PAGE
@@ -3553,8 +3831,25 @@
if (null == mUploadMessage) break;
Uri result = intent == null || resultCode != RESULT_OK ? null
: intent.getData();
+
+ // As we ask the camera to save the result of the user taking
+ // a picture, the camera application does not return anything other
+ // than RESULT_OK. So we need to check whether the file we expected
+ // was written to disk in the in the case that we
+ // did not get an intent returned but did get a RESULT_OK. If it was,
+ // we assume that this result has came back from the camera.
+ if (result == null && intent == null && resultCode == RESULT_OK) {
+ File cameraFile = new File(mCameraFilePath);
+ if (cameraFile.exists()) {
+ result = Uri.fromFile(cameraFile);
+ // Broadcast to the media scanner that we have a new photo
+ // so it will be added into the gallery for the user.
+ sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, result));
+ }
+ }
mUploadMessage.onReceiveValue(result);
mUploadMessage = null;
+ mCameraFilePath = null;
break;
default:
break;
@@ -3572,12 +3867,78 @@
startActivity(intent);
}
+ /* package */ void promptAddOrInstallBookmark(View anchor) {
+ PopupMenu popup = new PopupMenu(this, anchor);
+ popup.getMenuInflater().inflate(R.menu.bookmark_shortcut, popup.getMenu());
+ popup.setOnMenuItemClickListener(this);
+ popup.show();
+ }
+
+ /**
+ * popup menu item click listener
+ * @param item
+ */
+ public boolean onMenuItemClick(MenuItem item) {
+ switch(item.getItemId()) {
+ case R.id.add_bookmark_menu_id:
+ bookmarkCurrentPage();
+ return true;
+ case R.id.shortcut_to_home_menu_id:
+ Tab current = mTabControl.getCurrentTab();
+ current.populatePickerData();
+ String touchIconUrl = mTabControl.getCurrentWebView().getTouchIconUrl();
+ if (touchIconUrl != null) {
+ // Download the touch icon for this site then save
+ // it to the
+ // homescreen.
+ Bundle b = new Bundle();
+ b.putString("url", current.getUrl());
+ b.putString("title", current.getTitle());
+ b.putParcelable("favicon", current.getFavicon());
+ Message msg = mHandler.obtainMessage(TOUCH_ICON_DOWNLOADED);
+ msg.setData(b);
+ new DownloadTouchIcon(BrowserActivity.this, msg,
+ mTabControl.getCurrentWebView().getSettings().getUserAgentString())
+ .execute(touchIconUrl);
+ } else {
+ // add to homescreen, can do it immediately as there
+ // is no touch
+ // icon.
+ showSaveToHomescreenDialog(
+ current.getUrl(), current.getTitle(), null, current.getFavicon());
+ }
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /* package */Dialog makeAddOrInstallDialog() {
+ final Tab current = mTabControl.getCurrentTab();
+ Resources resources = getResources();
+ CharSequence[] choices =
+ {resources.getString(R.string.save_to_bookmarks),
+ resources.getString(R.string.create_shortcut_bookmark)};
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.add_new_bookmark);
+ builder.setItems(choices, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int item) {
+ if (item == 0) {
+ bookmarkCurrentPage();
+ } else if (item == 1) {
+ }
+ }
+ });
+ return builder.create();
+ }
+
/**
* Open the Go page.
* @param startWithHistory If true, open starting on the history tab.
* Otherwise, start with the bookmarks tab.
*/
- /* package */ void bookmarksOrHistoryPicker(boolean startWithHistory) {
+ /* package */ void bookmarksOrHistoryPicker(boolean startWithHistory, boolean newTabMode) {
WebView current = mTabControl.getCurrentWebView();
if (current == null) {
return;
@@ -3586,7 +3947,8 @@
CombinedBookmarkHistoryActivity.class);
String title = current.getTitle();
String url = current.getUrl();
- Bitmap thumbnail = createScreenshot(current);
+ Bitmap thumbnail = createScreenshot(current, getDesiredThumbnailWidth(this),
+ getDesiredThumbnailHeight(this));
// Just in case the user opens bookmarks before a page finishes loading
// so the current history item, and therefore the page, is null.
@@ -3608,12 +3970,50 @@
intent.putExtra("disable_new_window", !mTabControl.canCreateNewTab());
intent.putExtra("touch_icon_url", current.getTouchIconUrl());
if (startWithHistory) {
- intent.putExtra(CombinedBookmarkHistoryActivity.STARTING_TAB,
- CombinedBookmarkHistoryActivity.HISTORY_TAB);
+ intent.putExtra(CombinedBookmarkHistoryActivity.STARTING_FRAGMENT,
+ CombinedBookmarkHistoryActivity.FRAGMENT_ID_HISTORY);
}
+ intent.putExtra(CombinedBookmarkHistoryActivity.NEWTAB_MODE, newTabMode);
+ int top = -1;
+ int height = -1;
+ if (mXLargeScreenSize) {
+ showFakeTitleBar();
+ int titleBarHeight = ((TitleBarXLarge)mFakeTitleBar).getHeightWithoutProgress();
+ top = mTabBar.getBottom() + titleBarHeight;
+ height = getTopWindow().getHeight() - titleBarHeight;
+ }
+ intent.putExtra(CombinedBookmarkHistoryActivity.EXTRA_TOP, top);
+ intent.putExtra(CombinedBookmarkHistoryActivity.EXTRA_HEIGHT, height);
startActivityForResult(intent, COMBO_PAGE);
}
+ private void showSaveToHomescreenDialog(String url, String title, Bitmap touchIcon,
+ Bitmap favicon) {
+ Intent intent = new Intent(this, SaveToHomescreenDialog.class);
+
+ // Just in case the user tries to save before a page finishes loading
+ // so the current history item, and therefore the page, is null.
+ if (null == url) {
+ url = mLastEnteredUrl;
+ // This can happen.
+ if (null == url) {
+ url = mSettings.getHomePage();
+ }
+ }
+
+ // In case the web page has not yet received its associated title.
+ if (title == null) {
+ title = url;
+ }
+
+ intent.putExtra("title", title);
+ intent.putExtra("url", url);
+ intent.putExtra("favicon", favicon);
+ intent.putExtra("touchIcon", touchIcon);
+ startActivity(intent);
+ }
+
+
// Called when loading from context menu or LOAD_URL message
private void loadUrlFromContext(WebView view, String url) {
// In case the user enters nothing.
@@ -3787,54 +4187,6 @@
}
}
- 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;
@@ -3855,8 +4207,6 @@
private static final int EMPTY_MENU = -1;
private Menu mMenu;
- private FindDialog mFindDialog;
- private SelectDialog mSelectDialog;
// Used to prevent chording to result in firing two shortcuts immediately
// one after another. Fixes bug 1211714.
boolean mCanChord;
@@ -3970,7 +4320,8 @@
private Toast mStopToast;
- private TitleBar mTitleBar;
+ private TitleBarBase mTitleBar;
+ private TabBar mTabBar;
private LinearLayout mErrorConsoleContainer = null;
private boolean mShouldShowErrorConsole = false;
@@ -3986,8 +4337,6 @@
private IntentFilter mNetworkStateChangedFilter;
private BroadcastReceiver mNetworkStateIntentReceiver;
- private BroadcastReceiver mPackageInstallationReceiver;
-
private SystemAllowGeolocationOrigins mSystemAllowGeolocationOrigins;
// activity requestCode
@@ -4000,14 +4349,6 @@
// 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.
diff --git a/src/com/android/browser/BrowserBackupAgent.java b/src/com/android/browser/BrowserBackupAgent.java
index c968ce5..9c5d65b 100644
--- a/src/com/android/browser/BrowserBackupAgent.java
+++ b/src/com/android/browser/BrowserBackupAgent.java
@@ -166,8 +166,11 @@
if (DEBUG) Log.v(TAG, "Did not see url: " + mark.url);
// Right now we do not reconstruct the db entry in its
// entirety; we just add a new bookmark with the same data
- Bookmarks.addBookmark(null, getContentResolver(),
- mark.url, mark.title, null, false);
+ // FIXME: This file needs to be reworked
+ // anyway For now, add the bookmark at
+ // the root level.
+ Bookmarks.addBookmark(this, false,
+ mark.url, mark.title, null, false, 0);
nUnique++;
} else {
if (DEBUG) Log.v(TAG, "Skipping extant url: " + mark.url);
diff --git a/src/com/android/browser/BrowserBookmarksAdapter.java b/src/com/android/browser/BrowserBookmarksAdapter.java
index 241b33b..a5d51dd 100644
--- a/src/com/android/browser/BrowserBookmarksAdapter.java
+++ b/src/com/android/browser/BrowserBookmarksAdapter.java
@@ -16,567 +16,46 @@
package com.android.browser;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.database.ContentObserver;
+import android.content.Context;
import android.database.Cursor;
-import android.database.DataSetObserver;
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;
-import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
-import android.webkit.WebIconDatabase;
-import android.webkit.WebView;
-import android.widget.BaseAdapter;
import android.widget.ImageView;
+import android.widget.ResourceCursorAdapter;
import android.widget.TextView;
-import java.io.ByteArrayOutputStream;
-
-class BrowserBookmarksAdapter extends BaseAdapter {
-
- private String mCurrentPage;
- private String mCurrentTitle;
- private Bitmap mCurrentThumbnail;
- private Cursor mCursor;
- private int mCount;
- private BrowserBookmarksPage mBookmarksPage;
- private ContentResolver mContentResolver;
- private boolean mDataValid;
- private BookmarkViewMode mViewMode;
- private boolean mMostVisited;
- private boolean mNeedsOffset;
- private int mExtraOffset;
-
+class BrowserBookmarksAdapter extends ResourceCursorAdapter {
/**
* Create a new BrowserBookmarksAdapter.
- * @param b BrowserBookmarksPage that instantiated this.
- * Necessary so it will adjust its focus
- * appropriately after a search.
*/
- public BrowserBookmarksAdapter(BrowserBookmarksPage b, String curPage,
- String curTitle, Bitmap curThumbnail, boolean createShortcut,
- boolean mostVisited) {
- mNeedsOffset = !(createShortcut || mostVisited);
- mMostVisited = mostVisited;
- mExtraOffset = mNeedsOffset ? 1 : 0;
- mBookmarksPage = b;
- mCurrentPage = b.getResources().getString(R.string.current_page)
- + curPage;
- mCurrentTitle = curTitle;
- mCurrentThumbnail = curThumbnail;
- mContentResolver = b.getContentResolver();
- mViewMode = BookmarkViewMode.LIST;
+ public BrowserBookmarksAdapter(Context context) {
+ // Make sure to tell the CursorAdapter to avoid the observer and auto-requery
+ // since the Loader will do that for us.
+ super(context, R.layout.bookmark_thumbnail, null);
+ }
- String whereClause;
- // FIXME: Should have a default sort order that the user selects.
- String orderBy = Browser.BookmarkColumns.VISITS + " DESC";
- if (mostVisited) {
- whereClause = Browser.BookmarkColumns.VISITS + " != 0";
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ ImageView thumb = (ImageView) view.findViewById(R.id.thumb);
+ TextView tv = (TextView) view.findViewById(R.id.label);
+
+ tv.setText(cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE));
+ Bitmap thumbnail = null;
+ if (cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0) {
+ // folder
+ thumb.setImageResource(R.drawable.ic_folder);
} else {
- whereClause = Browser.BookmarkColumns.BOOKMARK + " = 1";
- }
- mCursor = b.managedQuery(Browser.BOOKMARKS_URI,
- Browser.HISTORY_PROJECTION, whereClause, null, orderBy);
- mCursor.registerContentObserver(new ChangeObserver());
- mCursor.registerDataSetObserver(new MyDataSetObserver());
-
- mDataValid = true;
- notifyDataSetChanged();
-
- mCount = mCursor.getCount() + mExtraOffset;
- }
-
- /**
- * Return a hashmap with one row's Title, Url, and favicon.
- * @param position Position in the list.
- * @return Bundle Stores title, url of row position, favicon, and id
- * for the url. Return a blank map if position is out of
- * range.
- */
- public Bundle getRow(int position) {
- Bundle map = new Bundle();
- if (position < mExtraOffset || position >= mCount) {
- return map;
- }
- mCursor.moveToPosition(position- mExtraOffset);
- String url = mCursor.getString(Browser.HISTORY_PROJECTION_URL_INDEX);
- map.putString(Browser.BookmarkColumns.TITLE,
- mCursor.getString(Browser.HISTORY_PROJECTION_TITLE_INDEX));
- map.putString(Browser.BookmarkColumns.URL, url);
- byte[] data = mCursor.getBlob(Browser.HISTORY_PROJECTION_FAVICON_INDEX);
- if (data != null) {
- map.putParcelable(Browser.BookmarkColumns.FAVICON,
- BitmapFactory.decodeByteArray(data, 0, data.length));
- }
- map.putInt("id", mCursor.getInt(Browser.HISTORY_PROJECTION_ID_INDEX));
- return map;
- }
-
- /**
- * Update a row in the database with new information.
- * Requeries the database if the information has changed.
- * @param map Bundle storing id, title and url of new information
- */
- public void updateRow(Bundle map) {
-
- // Find the record
- int id = map.getInt("id");
- int position = -1;
- for (mCursor.moveToFirst(); !mCursor.isAfterLast(); mCursor.moveToNext()) {
- if (mCursor.getInt(Browser.HISTORY_PROJECTION_ID_INDEX) == id) {
- position = mCursor.getPosition();
- break;
+ byte[] data = cursor.getBlob(BookmarksLoader.COLUMN_INDEX_THUMBNAIL);
+ if (data != null) {
+ thumbnail = BitmapFactory.decodeByteArray(data, 0, data.length);
}
- }
- if (position < 0) {
- return;
- }
- mCursor.moveToPosition(position);
- ContentValues values = new ContentValues();
- String title = map.getString(Browser.BookmarkColumns.TITLE);
- if (!title.equals(mCursor
- .getString(Browser.HISTORY_PROJECTION_TITLE_INDEX))) {
- values.put(Browser.BookmarkColumns.TITLE, title);
- }
- String url = map.getString(Browser.BookmarkColumns.URL);
- if (!url.equals(mCursor.
- getString(Browser.HISTORY_PROJECTION_URL_INDEX))) {
- values.put(Browser.BookmarkColumns.URL, url);
- }
-
- if (map.getBoolean("invalidateThumbnail") == true) {
- values.put(Browser.BookmarkColumns.THUMBNAIL, new byte[0]);
- }
- if (values.size() > 0
- && mContentResolver.update(Browser.BOOKMARKS_URI, values,
- "_id = " + id, null) != -1) {
- refreshList();
- }
- }
-
- /**
- * Delete a row from the database. Requeries the database.
- * Does nothing if the provided position is out of range.
- * @param position Position in the list.
- */
- public void deleteRow(int position) {
- if (position < mExtraOffset || position >= getCount()) {
- return;
- }
- mCursor.moveToPosition(position- mExtraOffset);
- String url = mCursor.getString(Browser.HISTORY_PROJECTION_URL_INDEX);
- String title = mCursor.getString(Browser.HISTORY_PROJECTION_TITLE_INDEX);
- Bookmarks.removeFromBookmarks(null, mContentResolver, url, title);
- refreshList();
- }
-
- /**
- * Delete all bookmarks from the db. Requeries the database.
- * All bookmarks with become visited URLs or if never visited
- * are removed
- */
- public void deleteAllRows() {
- StringBuilder deleteIds = null;
- StringBuilder convertIds = null;
-
- for (mCursor.moveToFirst(); !mCursor.isAfterLast(); mCursor.moveToNext()) {
- String url = mCursor.getString(Browser.HISTORY_PROJECTION_URL_INDEX);
- WebIconDatabase.getInstance().releaseIconForPageUrl(url);
- int id = mCursor.getInt(Browser.HISTORY_PROJECTION_ID_INDEX);
- int numVisits = mCursor.getInt(Browser.HISTORY_PROJECTION_VISITS_INDEX);
- if (0 == numVisits) {
- if (deleteIds == null) {
- deleteIds = new StringBuilder();
- deleteIds.append("( ");
- } else {
- deleteIds.append(" OR ( ");
- }
- deleteIds.append(BookmarkColumns._ID);
- deleteIds.append(" = ");
- deleteIds.append(id);
- deleteIds.append(" )");
- } else {
- // It is no longer a bookmark, but it is still a visited site.
- if (convertIds == null) {
- convertIds = new StringBuilder();
- convertIds.append("( ");
- } else {
- convertIds.append(" OR ( ");
- }
- convertIds.append(BookmarkColumns._ID);
- convertIds.append(" = ");
- convertIds.append(id);
- convertIds.append(" )");
- }
- }
-
- if (deleteIds != null) {
- mContentResolver.delete(Browser.BOOKMARKS_URI, deleteIds.toString(),
- null);
- }
- if (convertIds != null) {
- ContentValues values = new ContentValues();
- values.put(Browser.BookmarkColumns.BOOKMARK, 0);
- mContentResolver.update(Browser.BOOKMARKS_URI, values,
- convertIds.toString(), null);
- }
- refreshList();
- }
-
- /**
- * Refresh list to recognize a change in the database.
- */
- public void refreshList() {
- mCursor.requery();
- mCount = mCursor.getCount() + mExtraOffset;
- notifyDataSetChanged();
- }
-
- /**
- * Update the bookmark's favicon. This is a convenience method for updating
- * a bookmark favicon for the originalUrl and url of the passed in WebView.
- * @param cr The ContentResolver to use.
- * @param originalUrl The original url before any redirects.
- * @param url The current url.
- * @param favicon The favicon bitmap to write to the db.
- */
- /* 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;
- }
- }.execute();
- }
-
- /* package */ static Cursor queryBookmarksForUrl(ContentResolver cr,
- String originalUrl, String url, boolean onlyBookmarks) {
- if (cr == null || url == null) {
- return null;
- }
-
- // If originalUrl is null, just set it to url.
- if (originalUrl == null) {
- originalUrl = url;
- }
-
- // Look for both the original url and the actual url. This takes in to
- // account redirects.
- String originalUrlNoQuery = removeQuery(originalUrl);
- String urlNoQuery = removeQuery(url);
- originalUrl = originalUrlNoQuery + '?';
- url = urlNoQuery + '?';
-
- // Use NoQuery to search for the base url (i.e. if the url is
- // http://www.yahoo.com/?rs=1, search for http://www.yahoo.com)
- // Use url to match the base url with other queries (i.e. if the url is
- // http://www.google.com/m, search for
- // http://www.google.com/m?some_query)
- final String[] selArgs = new String[] {
- originalUrlNoQuery, urlNoQuery, originalUrl, url };
- String where = BookmarkColumns.URL + " == ? OR "
- + BookmarkColumns.URL + " == ? OR "
- + BookmarkColumns.URL + " LIKE ? || '%' OR "
- + BookmarkColumns.URL + " LIKE ? || '%'";
- if (onlyBookmarks) {
- where = "(" + where + ") AND " + BookmarkColumns.BOOKMARK + " == 1";
- }
- final String[] projection =
- new String[] { Browser.BookmarkColumns._ID };
- return cr.query(Browser.BOOKMARKS_URI, projection, where, selArgs,
- null);
- }
-
- // Strip the query from the given url.
- private static String removeQuery(String url) {
- if (url == null) {
- return null;
- }
- int query = url.indexOf('?');
- String noQuery = url;
- if (query != -1) {
- noQuery = url.substring(0, query);
- }
- return noQuery;
- }
-
- /**
- * How many items should be displayed in the list.
- * @return Count of items.
- */
- public int getCount() {
- if (mDataValid) {
- return mCount;
- } else {
- return 0;
- }
- }
-
- public boolean areAllItemsEnabled() {
- return true;
- }
-
- public boolean isEnabled(int position) {
- return true;
- }
-
- /**
- * Get the data associated with the specified position in the list.
- * @param position Index of the item whose data we want.
- * @return The data at the specified position.
- */
- public Object getItem(int position) {
- return null;
- }
-
- /**
- * Get the row id associated with the specified position in the list.
- * @param position Index of the item whose row id we want.
- * @return The id of the item at the specified position.
- */
- public long getItemId(int position) {
- return position;
- }
-
- /* package */ void switchViewMode(BookmarkViewMode viewMode) {
- mViewMode = viewMode;
- }
-
- /* package */ void populateBookmarkItem(BookmarkItem b, int position) {
- mCursor.moveToPosition(position - mExtraOffset);
- String url = mCursor.getString(Browser.HISTORY_PROJECTION_URL_INDEX);
- b.setUrl(url);
- b.setName(mCursor.getString(Browser.HISTORY_PROJECTION_TITLE_INDEX));
- byte[] data = mCursor.getBlob(Browser.HISTORY_PROJECTION_FAVICON_INDEX);
- Bitmap bitmap = null;
- if (data == null) {
- bitmap = CombinedBookmarkHistoryActivity.getIconListenerSet()
- .getFavicon(url);
- } else {
- bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
- }
- b.setFavicon(bitmap);
- }
-
- /**
- * Get a View that displays the data at the specified position
- * in the list.
- * @param position Index of the item whose view we want.
- * @return A View corresponding to the data at the specified position.
- */
- public View getView(int position, View convertView, ViewGroup parent) {
- if (!mDataValid) {
- throw new IllegalStateException(
- "this should only be called when the cursor is valid");
- }
- if (position < 0 || position > mCount) {
- throw new AssertionError(
- "BrowserBookmarksAdapter tried to get a view out of range");
- }
- if (mViewMode == BookmarkViewMode.GRID) {
- if (convertView == null || convertView instanceof AddNewBookmark
- || convertView instanceof BookmarkItem) {
- LayoutInflater factory = LayoutInflater.from(mBookmarksPage);
- convertView
- = factory.inflate(R.layout.bookmark_thumbnail, null);
- }
- View holder = convertView.findViewById(R.id.holder);
- ImageView thumb = (ImageView) convertView.findViewById(R.id.thumb);
- TextView tv = (TextView) convertView.findViewById(R.id.label);
-
- if (0 == position && mNeedsOffset) {
- // This is to create a bookmark for the current page.
- holder.setVisibility(View.VISIBLE);
- tv.setText(mCurrentTitle);
-
- if (mCurrentThumbnail != null) {
- thumb.setImageBitmap(mCurrentThumbnail);
- } else {
- thumb.setImageResource(
- R.drawable.browser_thumbnail);
- }
- return convertView;
- }
- holder.setVisibility(View.GONE);
- mCursor.moveToPosition(position - mExtraOffset);
- tv.setText(mCursor.getString(
- Browser.HISTORY_PROJECTION_TITLE_INDEX));
- Bitmap thumbnail = getScreenshot(position);
if (thumbnail == null) {
thumb.setImageResource(R.drawable.browser_thumbnail);
} else {
thumb.setImageBitmap(thumbnail);
}
-
- return convertView;
-
- }
- if (position == 0 && mNeedsOffset) {
- AddNewBookmark b;
- if (convertView instanceof AddNewBookmark) {
- b = (AddNewBookmark) convertView;
- } else {
- b = new AddNewBookmark(mBookmarksPage);
- }
- b.setUrl(mCurrentPage);
- return b;
- }
- if (mMostVisited) {
- if (convertView == null || !(convertView instanceof HistoryItem)) {
- convertView = new HistoryItem(mBookmarksPage);
- }
- } else {
- if (convertView == null || !(convertView instanceof BookmarkItem)) {
- convertView = new BookmarkItem(mBookmarksPage);
- }
- }
- bind((BookmarkItem) convertView, position);
- if (mMostVisited) {
- ((HistoryItem) convertView).setIsBookmark(
- getIsBookmark(position));
- }
- return convertView;
- }
-
- /**
- * Return the title for this item in the list.
- */
- public String getTitle(int position) {
- return getString(Browser.HISTORY_PROJECTION_TITLE_INDEX, position);
- }
-
- /**
- * Return the Url for this item in the list.
- */
- public String getUrl(int position) {
- return getString(Browser.HISTORY_PROJECTION_URL_INDEX, position);
- }
-
- /**
- * 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) {
- return getBitmap(Browser.HISTORY_PROJECTION_FAVICON_INDEX, position);
- }
-
- public Bitmap getTouchIcon(int position) {
- return getBitmap(Browser.HISTORY_PROJECTION_TOUCH_ICON_INDEX, position);
- }
-
- private Bitmap getBitmap(int cursorIndex, int position) {
- if (position < mExtraOffset || position > mCount) {
- return null;
- }
- mCursor.moveToPosition(position - mExtraOffset);
- byte[] data = mCursor.getBlob(cursorIndex);
- if (data == null) {
- return null;
- }
- return BitmapFactory.decodeByteArray(data, 0, data.length);
- }
-
- /**
- * Return whether or not this item represents a bookmarked site.
- */
- public boolean getIsBookmark(int position) {
- if (position < mExtraOffset || position > mCount) {
- return false;
- }
- mCursor.moveToPosition(position - mExtraOffset);
- return (1 == mCursor.getInt(Browser.HISTORY_PROJECTION_BOOKMARK_INDEX));
- }
-
- /**
- * Private helper function to return the title or url.
- */
- private String getString(int cursorIndex, int position) {
- if (position < mExtraOffset || position > mCount) {
- return "";
- }
- mCursor.moveToPosition(position- mExtraOffset);
- return mCursor.getString(cursorIndex);
- }
-
- private void bind(BookmarkItem b, int position) {
- mCursor.moveToPosition(position- mExtraOffset);
-
- b.setName(mCursor.getString(Browser.HISTORY_PROJECTION_TITLE_INDEX));
- String url = mCursor.getString(Browser.HISTORY_PROJECTION_URL_INDEX);
- b.setUrl(url);
- byte[] data = mCursor.getBlob(Browser.HISTORY_PROJECTION_FAVICON_INDEX);
- if (data != null) {
- b.setFavicon(BitmapFactory.decodeByteArray(data, 0, data.length));
- } else {
- b.setFavicon(CombinedBookmarkHistoryActivity.getIconListenerSet()
- .getFavicon(url));
- }
- }
-
- private class ChangeObserver extends ContentObserver {
- public ChangeObserver() {
- super(new Handler(Looper.getMainLooper()));
- }
-
- @Override
- public boolean deliverSelfNotifications() {
- return true;
- }
-
- @Override
- public void onChange(boolean selfChange) {
- refreshList();
- }
- }
-
- private class MyDataSetObserver extends DataSetObserver {
- @Override
- public void onChanged() {
- mDataValid = true;
- notifyDataSetChanged();
- }
-
- @Override
- public void onInvalidated() {
- mDataValid = false;
- notifyDataSetInvalidated();
}
}
}
diff --git a/src/com/android/browser/BrowserBookmarksPage.java b/src/com/android/browser/BrowserBookmarksPage.java
index dd01009..4630d4e 100644
--- a/src/com/android/browser/BrowserBookmarksPage.java
+++ b/src/com/android/browser/BrowserBookmarksPage.java
@@ -18,73 +18,214 @@
import android.app.Activity;
import android.app.AlertDialog;
+import android.app.Fragment;
+import android.app.LoaderManager;
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.CursorLoader;
import android.content.DialogInterface;
import android.content.Intent;
+import android.content.Loader;
import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
+import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-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;
-import android.os.ServiceManager;
-import android.provider.Browser;
-import android.text.IClipboard;
-import android.util.Log;
+import android.preference.PreferenceManager;
+import android.provider.BrowserContract;
+import android.provider.BrowserContract.Accounts;
+import android.text.TextUtils;
+import android.util.Pair;
import android.view.ContextMenu;
-import android.view.Menu;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.LayoutInflater;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
+import android.view.View.OnClickListener;
import android.view.ViewGroup;
-import android.view.ContextMenu.ContextMenuInfo;
import android.webkit.WebIconDatabase.IconListener;
+import android.widget.Adapter;
import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.Button;
import android.widget.GridView;
-import android.widget.ListView;
import android.widget.Toast;
-/*package*/ enum BookmarkViewMode { NONE, GRID, LIST }
+import java.util.Stack;
+
/**
* View showing the user's bookmarks in the browser.
*/
-public class BrowserBookmarksPage extends Activity implements
- View.OnCreateContextMenuListener {
+public class BrowserBookmarksPage extends Fragment implements View.OnCreateContextMenuListener,
+ LoaderManager.LoaderCallbacks<Cursor>, OnItemClickListener, IconListener, OnClickListener,
+ OnItemSelectedListener {
- private BookmarkViewMode mViewMode = BookmarkViewMode.NONE;
- private GridView mGridPage;
- private ListView mVerticalList;
- private BrowserBookmarksAdapter mBookmarksAdapter;
- private static final int BOOKMARKS_SAVE = 1;
- private boolean mDisableNewWindow;
- private BookmarkItem mContextHeader;
- private AddNewBookmark mAddHeader;
- private boolean mCanceled = false;
- 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";
+ static final int BOOKMARKS_SAVE = 1;
+ static final String LOGTAG = "browser";
- 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";
+ static final int LOADER_BOOKMARKS = 1;
+ static final int LOADER_ACCOUNTS_THEN_BOOKMARKS = 2;
+
+ static final String EXTRA_SHORTCUT = "create_shortcut";
+ static final String EXTRA_DISABLE_WINDOW = "disable_new_window";
+
+ static final String ACCOUNT_NAME_UNSYNCED = "Unsynced";
+
+ public static final String PREF_ACCOUNT_TYPE = "acct_type";
+ public static final String PREF_ACCOUNT_NAME = "acct_name";
+
+ static final String DEFAULT_ACCOUNT = "local";
+
+ BookmarksHistoryCallbacks mCallbacks;
+ GridView mGrid;
+ BrowserBookmarksAdapter mAdapter;
+ boolean mDisableNewWindow;
+ BookmarkItem mContextHeader;
+ boolean mCanceled = false;
+ boolean mCreateShortcut;
+ View mEmptyView;
+ View mContentView;
+ Stack<Pair<String, Uri>> mFolderStack = new Stack<Pair<String, Uri>>();
+ Button mUpButton;
+
+ @Override
+ public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ switch (id) {
+ case LOADER_BOOKMARKS: {
+ String accountType = null;
+ String accountName = null;
+ if (args != null) {
+ accountType = args.getString(BookmarksLoader.ARG_ACCOUNT_TYPE);
+ accountName = args.getString(BookmarksLoader.ARG_ACCOUNT_NAME);
+ }
+ return new BookmarksLoader(getActivity(), accountType, accountName);
+ }
+
+ case LOADER_ACCOUNTS_THEN_BOOKMARKS: {
+ return new CursorLoader(getActivity(), Accounts.CONTENT_URI,
+ new String[] { Accounts.ACCOUNT_TYPE, Accounts.ACCOUNT_NAME }, null, null,
+ null);
+ }
+ }
+ throw new UnsupportedOperationException("Unknown loader id " + id);
+ }
+
+ @Override
+ public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
+ switch (loader.getId()) {
+ case LOADER_BOOKMARKS: {
+ // Set the visibility of the empty vs. content views
+ if (cursor == null || cursor.getCount() == 0) {
+ mEmptyView.setVisibility(View.VISIBLE);
+ mGrid.setVisibility(View.GONE);
+ } else {
+ mEmptyView.setVisibility(View.GONE);
+ mGrid.setVisibility(View.VISIBLE);
+ }
+
+ // Fill in the "up" button if needed
+ BookmarksLoader bl = (BookmarksLoader) loader;
+ String path = bl.getUri().getPath();
+ boolean rootFolder =
+ BrowserContract.Bookmarks.CONTENT_URI_DEFAULT_FOLDER.getPath().equals(path);
+ if (rootFolder) {
+ mUpButton.setText(R.string.defaultBookmarksUpButton);
+ mUpButton.setEnabled(false);
+ } else {
+ mUpButton.setText(mFolderStack.peek().first);
+ mUpButton.setEnabled(true);
+ }
+ mUpButton.setVisibility(View.VISIBLE);
+
+ // Give the new data to the adapter
+ mAdapter.changeCursor(cursor);
+
+ break;
+ }
+
+ case LOADER_ACCOUNTS_THEN_BOOKMARKS: {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(
+ getActivity());
+ String storedAccountType = prefs.getString(PREF_ACCOUNT_TYPE, null);
+ String storedAccountName = prefs.getString(PREF_ACCOUNT_NAME, null);
+ String accountType =
+ TextUtils.isEmpty(storedAccountType) ? DEFAULT_ACCOUNT : storedAccountType;
+ String accountName =
+ TextUtils.isEmpty(storedAccountName) ? DEFAULT_ACCOUNT : storedAccountName;
+
+ Bundle args = null;
+ if (cursor == null || !cursor.moveToFirst()) {
+ // No accounts, set the prefs to the default
+ accountType = DEFAULT_ACCOUNT;
+ accountName = DEFAULT_ACCOUNT;
+ } else {
+ int accountPosition = -1;
+
+ if (!DEFAULT_ACCOUNT.equals(accountType) &&
+ !DEFAULT_ACCOUNT.equals(accountName)) {
+ // Check to see if the account in prefs still exists
+ cursor.moveToFirst();
+ do {
+ if (accountType.equals(cursor.getString(0))
+ && accountName.equals(cursor.getString(1))) {
+ accountPosition = cursor.getPosition();
+ break;
+ }
+ } while (cursor.moveToNext());
+ }
+
+ if (accountPosition == -1) {
+ if (!(DEFAULT_ACCOUNT.equals(accountType)
+ && DEFAULT_ACCOUNT.equals(accountName))) {
+ // No account is set in prefs and there is at least one,
+ // so pick the first one as the default
+ cursor.moveToFirst();
+ accountType = cursor.getString(0);
+ accountName = cursor.getString(1);
+ }
+ }
+
+ args = new Bundle();
+ args.putString(BookmarksLoader.ARG_ACCOUNT_TYPE, accountType);
+ args.putString(BookmarksLoader.ARG_ACCOUNT_NAME, accountName);
+ }
+
+ // The stored account name wasn't found, update the stored account with a valid one
+ if (!accountType.equals(storedAccountType)
+ || !accountName.equals(storedAccountName)) {
+ prefs.edit()
+ .putString(PREF_ACCOUNT_TYPE, accountType)
+ .putString(PREF_ACCOUNT_NAME, accountName)
+ .apply();
+ }
+ getLoaderManager().initLoader(LOADER_BOOKMARKS, args, this);
+
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void onClick(View view) {
+ if (view == mUpButton) {
+ Pair<String, Uri> pair = mFolderStack.pop();
+ BookmarksLoader loader =
+ (BookmarksLoader) ((Loader) getLoaderManager().getLoader(LOADER_BOOKMARKS));
+ loader.setUri(pair.second);
+ loader.forceLoad();
+ }
+ }
@Override
public boolean onContextItemSelected(MenuItem item) {
+ final Activity activity = getActivity();
// It is possible that the view has been canceled when we get to
// this point as back has a higher priority
if (mCanceled) {
@@ -98,9 +239,6 @@
}
switch (item.getItemId()) {
- case R.id.new_context_menu_id:
- saveCurrentPage();
- break;
case R.id.open_context_menu_id:
loadUrl(i.position);
break;
@@ -108,533 +246,278 @@
editBookmark(i.position);
break;
case R.id.shortcut_context_menu_id:
- final Intent send = createShortcutIntent(i.position);
- send.setAction(INSTALL_SHORTCUT);
- sendBroadcast(send);
+ activity.sendBroadcast(createShortcutIntent(i.position));
break;
case R.id.delete_context_menu_id:
- if (mMostVisited) {
- Browser.deleteFromHistory(getContentResolver(),
- getUrl(i.position));
- refreshList();
- } else {
- displayRemoveBookmarkDialog(i.position);
- }
+ displayRemoveBookmarkDialog(i.position);
break;
case R.id.new_window_context_menu_id:
openInNewWindow(i.position);
break;
- case R.id.share_link_context_menu_id:
- BrowserActivity.sharePage(BrowserBookmarksPage.this,
- mBookmarksAdapter.getTitle(i.position), getUrl(i.position),
- getFavicon(i.position),
- mBookmarksAdapter.getScreenshot(i.position));
+ case R.id.share_link_context_menu_id: {
+ Cursor cursor = (Cursor) mAdapter.getItem(i.position);
+ BrowserActivity.sharePage(activity,
+ cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE),
+ cursor.getString(BookmarksLoader.COLUMN_INDEX_URL),
+ getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_FAVICON),
+ getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_THUMBNAIL));
break;
+ }
case R.id.copy_url_context_menu_id:
copy(getUrl(i.position));
break;
- case R.id.homepage_context_menu_id:
- BrowserSettings.getInstance().setHomePage(this,
- getUrl(i.position));
- Toast.makeText(this, R.string.homepage_set,
- Toast.LENGTH_LONG).show();
+ case R.id.homepage_context_menu_id: {
+ BrowserSettings.getInstance().setHomePage(activity, getUrl(i.position));
+ Toast.makeText(activity, R.string.homepage_set, Toast.LENGTH_LONG).show();
break;
+ }
// Only for the Most visited page
- case R.id.save_to_bookmarks_menu_id:
- boolean isBookmark;
- String name;
- String url;
- if (mViewMode == BookmarkViewMode.GRID) {
- isBookmark = mBookmarksAdapter.getIsBookmark(i.position);
- name = mBookmarksAdapter.getTitle(i.position);
- url = mBookmarksAdapter.getUrl(i.position);
- } else {
- HistoryItem historyItem = ((HistoryItem) i.targetView);
- isBookmark = historyItem.isBookmark();
- name = historyItem.getName();
- url = historyItem.getUrl();
- }
+ case R.id.save_to_bookmarks_menu_id: {
+ Cursor cursor = (Cursor) mAdapter.getItem(i.position);
+ String name = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE);
+ String url = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL);
// If the site is bookmarked, the item becomes remove from
// bookmarks.
- if (isBookmark) {
- Bookmarks.removeFromBookmarks(this, getContentResolver(), url, name);
- } else {
- Browser.saveBookmark(this, name, url);
- }
+ Bookmarks.removeFromBookmarks(activity, activity.getContentResolver(), url, name);
break;
+ }
default:
return super.onContextItemSelected(item);
}
return true;
}
- @Override
- public void onCreateContextMenu(ContextMenu menu, View v,
- ContextMenuInfo menuInfo) {
- AdapterView.AdapterContextMenuInfo i =
- (AdapterView.AdapterContextMenuInfo) menuInfo;
-
- MenuInflater inflater = getMenuInflater();
- if (mMostVisited) {
- inflater.inflate(R.menu.historycontext, menu);
- } else {
- inflater.inflate(R.menu.bookmarkscontext, menu);
- }
-
- if (0 == i.position && !mMostVisited) {
- menu.setGroupVisible(R.id.CONTEXT_MENU, false);
- if (mAddHeader == null) {
- mAddHeader = new AddNewBookmark(BrowserBookmarksPage.this);
- } else if (mAddHeader.getParent() != null) {
- ((ViewGroup) mAddHeader.getParent()).
- removeView(mAddHeader);
- }
- mAddHeader.setUrl(getIntent().getStringExtra("url"));
- menu.setHeaderView(mAddHeader);
- return;
- }
- if (mMostVisited) {
- if ((mViewMode == BookmarkViewMode.LIST
- && ((HistoryItem) i.targetView).isBookmark())
- || mBookmarksAdapter.getIsBookmark(i.position)) {
- MenuItem item = menu.findItem(
- R.id.save_to_bookmarks_menu_id);
- item.setTitle(R.string.remove_from_bookmarks);
- }
- } else {
- // The historycontext menu has no ADD_MENU group.
- menu.setGroupVisible(R.id.ADD_MENU, false);
- }
- if (mDisableNewWindow) {
- menu.findItem(R.id.new_window_context_menu_id).setVisible(
- false);
- }
- if (mContextHeader == null) {
- mContextHeader = new BookmarkItem(BrowserBookmarksPage.this);
- } else if (mContextHeader.getParent() != null) {
- ((ViewGroup) mContextHeader.getParent()).
- removeView(mContextHeader);
- }
- if (mViewMode == BookmarkViewMode.GRID) {
- mBookmarksAdapter.populateBookmarkItem(mContextHeader,
- i.position);
- } else {
- BookmarkItem b = (BookmarkItem) i.targetView;
- b.copyTo(mContextHeader);
- }
- menu.setHeaderView(mContextHeader);
+ Bitmap getBitmap(Cursor cursor, int columnIndex) {
+ byte[] data = cursor.getBlob(columnIndex);
+ if (data == null) {
+ return null;
}
+ return BitmapFactory.decodeByteArray(data, 0, data.length);
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
+ AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
+ Cursor cursor = (Cursor) mAdapter.getItem(info.position);
+ boolean isFolder
+ = cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0;
+ if (isFolder) return;
+
+ final Activity activity = getActivity();
+ MenuInflater inflater = activity.getMenuInflater();
+ inflater.inflate(R.menu.bookmarkscontext, menu);
+
+ if (mDisableNewWindow) {
+ menu.findItem(R.id.new_window_context_menu_id).setVisible(false);
+ }
+
+ if (mContextHeader == null) {
+ mContextHeader = new BookmarkItem(activity);
+ } else if (mContextHeader.getParent() != null) {
+ ((ViewGroup) mContextHeader.getParent()).removeView(mContextHeader);
+ }
+
+ populateBookmarkItem(cursor, mContextHeader);
+
+ menu.setHeaderView(mContextHeader);
+ }
+
+ private void populateBookmarkItem(Cursor cursor, BookmarkItem item) {
+ String url = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL);
+ item.setUrl(url);
+ item.setName(cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE));
+ Bitmap bitmap = getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_FAVICON);
+ if (bitmap == null) {
+ bitmap = CombinedBookmarkHistoryActivity.getIconListenerSet().getFavicon(url);
+ }
+ item.setFavicon(bitmap);
+ }
/**
* Create a new BrowserBookmarksPage.
*/
@Override
- protected void onCreate(Bundle icicle) {
+ public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- // 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 = intent.getBooleanExtra("disable_new_window",
- false);
- mMostVisited = intent.getBooleanExtra("mostVisited", false);
-
- if (mCreateShortcut) {
- setTitle(R.string.browser_bookmarks_page_bookmarks_text);
- }
-
- setContentView(R.layout.empty_history);
- mEmptyView = findViewById(R.id.empty_view);
- mEmptyView.setVisibility(View.GONE);
-
- SharedPreferences p = getPreferences(MODE_PRIVATE);
-
- // See if the user has set a preference for the view mode of their
- // bookmarks. Otherwise default to grid mode.
- BookmarkViewMode preference = BookmarkViewMode.NONE;
- if (mMostVisited) {
- // For the most visited page, only use list mode.
- preference = BookmarkViewMode.LIST;
- } else {
- preference = BookmarkViewMode.values()[p.getInt(
- 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();
+ Bundle args = getArguments();
+ mCreateShortcut = args == null ? false : args.getBoolean("create_shortcut", false);
+ mDisableNewWindow = args == null ? false : args.getBoolean("disable_new_window", false);
}
@Override
- protected void onDestroy() {
- mHandler.removeCallbacksAndMessages(null);
- super.onDestroy();
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ mCallbacks = (BookmarksHistoryCallbacks) activity;
}
- /**
- * Set the ContentView to be either the grid of thumbnails or the vertical
- * list.
- */
- private void switchViewMode(BookmarkViewMode viewMode) {
- if (mViewMode == viewMode) {
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ Context context = getActivity();
+
+ View root = inflater.inflate(R.layout.bookmarks, container, false);
+ mEmptyView = root.findViewById(android.R.id.empty);
+ mContentView = root.findViewById(android.R.id.content);
+
+ mGrid = (GridView) root.findViewById(R.id.grid);
+ mGrid.setOnItemClickListener(this);
+ mGrid.setColumnWidth(BrowserActivity.getDesiredThumbnailWidth(getActivity()));
+ if (!mCreateShortcut) {
+ mGrid.setOnCreateContextMenuListener(this);
+ }
+
+ mUpButton = (Button) root.findViewById(R.id.up);
+ mUpButton.setEnabled(false);
+ mUpButton.setOnClickListener(this);
+ mUpButton.setVisibility(View.GONE);
+
+ mAdapter = new BrowserBookmarksAdapter(getActivity());
+ mGrid.setAdapter(mAdapter);
+
+ // Start the loaders
+ LoaderManager lm = getLoaderManager();
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ String accountType = prefs.getString(PREF_ACCOUNT_TYPE, DEFAULT_ACCOUNT);
+ String accountName = prefs.getString(PREF_ACCOUNT_NAME, DEFAULT_ACCOUNT);
+ if (!TextUtils.isEmpty(accountType) && !TextUtils.isEmpty(accountName)) {
+ // There is an account set, load up that one
+ Bundle args = null;
+ if (!DEFAULT_ACCOUNT.equals(accountType) && !DEFAULT_ACCOUNT.equals(accountName)) {
+ args = new Bundle();
+ args.putString(BookmarksLoader.ARG_ACCOUNT_TYPE, accountType);
+ args.putString(BookmarksLoader.ARG_ACCOUNT_NAME, accountName);
+ }
+ lm.restartLoader(LOADER_BOOKMARKS, args, this);
+ } else {
+ // No account set, load the account list first
+ lm.restartLoader(LOADER_ACCOUNTS_THEN_BOOKMARKS, null, this);
+ }
+
+ // Add our own listener in case there are favicons that have yet to be loaded.
+ CombinedBookmarkHistoryActivity.getIconListenerSet().addListener(this);
+
+ return root;
+ }
+
+ @Override
+ public void onReceivedIcon(String url, Bitmap icon) {
+ // A new favicon has been loaded, so let anything attached to the adapter know about it
+ // so new icons will be loaded.
+ mAdapter.notifyDataSetChanged();
+ }
+
+ @Override
+ 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
+ if (mCanceled) {
+ android.util.Log.e(LOGTAG, "item clicked when dismissing");
return;
}
- mViewMode = viewMode;
-
- // Update the preferences to make the new view mode sticky.
- Editor ed = getPreferences(MODE_PRIVATE).edit();
- if (mMostVisited) {
- ed.putInt(PREF_MOST_VISITED_VIEW_MODE, mViewMode.ordinal());
- } else {
- ed.putInt(PREF_BOOKMARK_VIEW_MODE, mViewMode.ordinal());
+ if (mCreateShortcut) {
+ Intent intent = createShortcutIntent(position);
+ // the activity handles the intent in startActivityFromFragment
+ startActivity(intent);
+ return;
}
- ed.apply();
- if (mBookmarksAdapter != null) {
- mBookmarksAdapter.switchViewMode(viewMode);
- }
- if (mViewMode == BookmarkViewMode.GRID) {
- if (mGridPage == null) {
- mGridPage = new GridView(this);
- if (mBookmarksAdapter != null) {
- mGridPage.setAdapter(mBookmarksAdapter);
- }
- mGridPage.setOnItemClickListener(mListener);
- mGridPage.setNumColumns(GridView.AUTO_FIT);
- mGridPage.setColumnWidth(
- BrowserActivity.getDesiredThumbnailWidth(this));
- mGridPage.setFocusable(true);
- mGridPage.setFocusableInTouchMode(true);
- mGridPage.setSelector(android.R.drawable.gallery_thumb);
- float density = getResources().getDisplayMetrics().density;
- mGridPage.setVerticalSpacing((int) (14 * density));
- mGridPage.setHorizontalSpacing((int) (8 * density));
- mGridPage.setStretchMode(GridView.STRETCH_SPACING);
- mGridPage.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET);
- mGridPage.setDrawSelectorOnTop(true);
- if (mMostVisited) {
- mGridPage.setEmptyView(mEmptyView);
- }
- if (!mCreateShortcut) {
- mGridPage.setOnCreateContextMenuListener(this);
- }
- }
- addContentView(mGridPage, FULL_SCREEN_PARAMS);
- if (mVerticalList != null) {
- ViewGroup parent = (ViewGroup) mVerticalList.getParent();
- if (parent != null) {
- parent.removeView(mVerticalList);
- }
- }
+ Cursor cursor = (Cursor) mAdapter.getItem(position);
+ boolean isFolder = cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0;
+ if (!isFolder) {
+ mCallbacks.onUrlSelected(getUrl(position), false);
} else {
- if (null == mVerticalList) {
- ListView listView = new ListView(this);
- if (mBookmarksAdapter != null) {
- listView.setAdapter(mBookmarksAdapter);
- }
- listView.setDrawSelectorOnTop(false);
- listView.setVerticalScrollBarEnabled(true);
- listView.setOnItemClickListener(mListener);
- if (mMostVisited) {
- listView.setEmptyView(mEmptyView);
- }
- if (!mCreateShortcut) {
- listView.setOnCreateContextMenuListener(this);
- }
- mVerticalList = listView;
+ String title;
+ if (mFolderStack.size() != 0) {
+ title = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE);
+ } else {
+ // TODO localize
+ title = "Bookmarks";
}
- addContentView(mVerticalList, FULL_SCREEN_PARAMS);
- if (mGridPage != null) {
- ViewGroup parent = (ViewGroup) mGridPage.getParent();
- if (parent != null) {
- parent.removeView(mGridPage);
- }
- }
+ LoaderManager manager = getLoaderManager();
+ BookmarksLoader loader =
+ (BookmarksLoader) ((Loader) manager.getLoader(LOADER_BOOKMARKS));
+ mFolderStack.push(new Pair(title, loader.getUri()));
+ Uri uri = ContentUris.withAppendedId(
+ BrowserContract.Bookmarks.CONTENT_URI_DEFAULT_FOLDER, id);
+ loader.setUri(uri);
+ loader.forceLoad();
}
}
- private static final ViewGroup.LayoutParams FULL_SCREEN_PARAMS
- = new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT);
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ Adapter adapter = parent.getAdapter();
+ String accountType = "com.google";
+ String accountName = adapter.getItem(position).toString();
- 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) {
- 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;
- }
+ Bundle args = null;
+ if (ACCOUNT_NAME_UNSYNCED.equals(accountName)) {
+ accountType = DEFAULT_ACCOUNT;
+ accountName = DEFAULT_ACCOUNT;
+ } else {
+ args = new Bundle();
+ args.putString(BookmarksLoader.ARG_ACCOUNT_TYPE, accountType);
+ args.putString(BookmarksLoader.ARG_ACCOUNT_NAME, accountName);
}
- };
- 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
- if (mCanceled) {
- android.util.Log.e(LOGTAG, "item clicked when dismissing");
- return;
- }
- if (!mCreateShortcut) {
- if (0 == position && !mMostVisited) {
- // XXX: Work-around for a framework issue.
- mHandler.sendEmptyMessage(SAVE_CURRENT_PAGE);
- } else {
- loadUrl(position);
- }
- } else {
- final Intent intent = createShortcutIntent(position);
- setResultToParent(RESULT_OK, intent);
- finish();
- }
- }
- };
+ // Remember the selection for later
+ PreferenceManager.getDefaultSharedPreferences(getActivity()).edit()
+ .putString(PREF_ACCOUNT_TYPE, accountType)
+ .putString(PREF_ACCOUNT_NAME, accountName)
+ .apply();
+
+ getLoaderManager().restartLoader(LOADER_BOOKMARKS, args, this);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ // Do nothing
+ }
private Intent createShortcutIntent(int position) {
- String url = getUrl(position);
- String title = getBookmarkTitle(position);
- Bitmap touchIcon = getTouchIcon(position);
-
- final Intent i = new Intent();
- final Intent shortcutIntent = new Intent(Intent.ACTION_VIEW,
- Uri.parse(url));
- long urlHash = url.hashCode();
- long uniqueId = (urlHash << 32) | shortcutIntent.hashCode();
- shortcutIntent.putExtra(Browser.EXTRA_APPLICATION_ID,
- Long.toString(uniqueId));
- i.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
- 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. 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, bm.getWidth(), bm.getHeight());
- rect.inset(1, 1);
- path.addRoundRect(rect, 8f, 8f, Path.Direction.CW);
-
- // 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, bm);
- } else {
- Bitmap favicon = getFavicon(position);
- if (favicon == null) {
- i.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
- Intent.ShortcutIconResource.fromContext(
- BrowserBookmarksPage.this,
- R.drawable.ic_launcher_shortcut_browser_bookmark));
- } else {
- Bitmap icon = BitmapFactory.decodeResource(getResources(),
- 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);
- Canvas canvas = new Canvas(copy);
-
- // Make a Paint for the white background rectangle and for
- // filtering the favicon.
- Paint p = new Paint(Paint.ANTI_ALIAS_FLAG
- | Paint.FILTER_BITMAP_FLAG);
- 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 * density; // 16x16 favicon
- final float padding = 2 * density; // white padding around icon
- final float rectSize = iconSize + 2 * padding;
-
- 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);
-
- // Draw the favicon in the same rectangle as the rounded
- // rectangle but inset by the padding
- // (results in a 16x16 favicon).
- r.inset(padding, padding);
- canvas.drawBitmap(favicon, null, r, p);
- i.putExtra(Intent.EXTRA_SHORTCUT_ICON, copy);
- }
- }
- // Do not allow duplicate items
- i.putExtra("duplicate", false);
- return i;
- }
-
- private void saveCurrentPage() {
- Intent i = new Intent(BrowserBookmarksPage.this,
- AddBookmarkPage.class);
- i.putExtras(getIntent());
- startActivityForResult(i, BOOKMARKS_SAVE);
+ Cursor cursor = (Cursor) mAdapter.getItem(position);
+ String url = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL);
+ String title = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL);
+ Bitmap touchIcon = getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_TOUCH_ICON);
+ Bitmap favicon = getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_FAVICON);
+ return BookmarkUtils.createAddToHomeIntent(getActivity(), url, title, touchIcon, favicon);
}
private void loadUrl(int position) {
- Intent intent = (new Intent()).setAction(getUrl(position));
- setResultToParent(RESULT_OK, intent);
- finish();
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- boolean result = super.onCreateOptionsMenu(menu);
- if (!mCreateShortcut && !mMostVisited) {
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.bookmarks, menu);
- return true;
- }
- return result;
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- boolean result = super.onPrepareOptionsMenu(menu);
- if (mCreateShortcut || mMostVisited || mBookmarksAdapter == null
- || mBookmarksAdapter.getCount() == 0) {
- // No need to show the menu if there are no items.
- return result;
- }
- MenuItem switchItem = menu.findItem(R.id.switch_mode_menu_id);
- int titleResId;
- int iconResId;
- if (mViewMode == BookmarkViewMode.GRID) {
- titleResId = R.string.switch_to_list;
- iconResId = R.drawable.ic_menu_list;
- } else {
- titleResId = R.string.switch_to_thumbnails;
- iconResId = R.drawable.ic_menu_thumbnail;
- }
- switchItem.setTitle(titleResId);
- switchItem.setIcon(iconResId);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.new_context_menu_id:
- saveCurrentPage();
- break;
-
- case R.id.switch_mode_menu_id:
- if (mViewMode == BookmarkViewMode.GRID) {
- switchViewMode(BookmarkViewMode.LIST);
- } else {
- switchViewMode(BookmarkViewMode.GRID);
- }
- break;
-
- default:
- return super.onOptionsItemSelected(item);
- }
- return true;
+ mCallbacks.onUrlSelected(getUrl(position), false);
}
private void openInNewWindow(int position) {
- Bundle b = new Bundle();
- b.putBoolean("new_window", true);
- setResultToParent(RESULT_OK,
- (new Intent()).setAction(getUrl(position)).putExtras(b));
-
- finish();
+ mCallbacks.onUrlSelected(getUrl(position), true);
}
-
private void editBookmark(int position) {
- Intent intent = new Intent(BrowserBookmarksPage.this,
- AddBookmarkPage.class);
- intent.putExtra("bookmark", getRow(position));
+ Intent intent = new Intent(getActivity(), AddBookmarkPage.class);
+ Cursor cursor = (Cursor) mAdapter.getItem(position);
+ Bundle item = new Bundle();
+ item.putString(BrowserContract.Bookmarks.TITLE,
+ cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE));
+ item.putString(BrowserContract.Bookmarks.URL,
+ cursor.getString(BookmarksLoader.COLUMN_INDEX_URL));
+ byte[] data = cursor.getBlob(BookmarksLoader.COLUMN_INDEX_FAVICON);
+ if (data != null) {
+ item.putParcelable(BrowserContract.Bookmarks.FAVICON,
+ BitmapFactory.decodeByteArray(data, 0, data.length));
+ }
+ item.putInt("id", cursor.getInt(BookmarksLoader.COLUMN_INDEX_ID));
+ item.putLong(BrowserContract.Bookmarks.PARENT,
+ cursor.getLong(BookmarksLoader.COLUMN_INDEX_PARENT));
+ intent.putExtra("bookmark", item);
startActivityForResult(intent, BOOKMARKS_SAVE);
}
@Override
- protected void onActivityResult(int requestCode, int resultCode,
- Intent data) {
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch(requestCode) {
case BOOKMARKS_SAVE:
- if (resultCode == RESULT_OK) {
+ if (resultCode == Activity.RESULT_OK) {
Bundle extras;
if (data != null && (extras = data.getExtras()) != null) {
// If there are extras, then we need to save
@@ -642,118 +525,89 @@
String title = extras.getString("title");
String url = extras.getString("url");
if (title != null && url != null) {
- mBookmarksAdapter.updateRow(extras);
+ updateRow(extras);
}
- } else {
- // extras == null then a new bookmark was added to
- // the database.
- refreshList();
}
}
break;
- default:
- break;
}
}
- private void displayRemoveBookmarkDialog(int position) {
+ /**
+ * Update a row in the database with new information.
+ * @param map Bundle storing id, title and url of new information
+ */
+ public void updateRow(Bundle map) {
+
+ // Find the record
+ int id = map.getInt("id");
+ int position = -1;
+ Cursor cursor = mAdapter.getCursor();
+ for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
+ if (cursor.getInt(BookmarksLoader.COLUMN_INDEX_ID) == id) {
+ position = cursor.getPosition();
+ break;
+ }
+ }
+ if (position < 0) {
+ return;
+ }
+
+ cursor.moveToPosition(position);
+ ContentValues values = new ContentValues();
+ String title = map.getString(BrowserContract.Bookmarks.TITLE);
+ if (!title.equals(cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE))) {
+ values.put(BrowserContract.Bookmarks.TITLE, title);
+ }
+ String url = map.getString(BrowserContract.Bookmarks.URL);
+ if (!url.equals(cursor.getString(BookmarksLoader.COLUMN_INDEX_URL))) {
+ values.put(BrowserContract.Bookmarks.URL, url);
+ }
+
+ if (map.getBoolean("invalidateThumbnail") == true) {
+ values.putNull(BrowserContract.Bookmarks.THUMBNAIL);
+ }
+
+ if (values.size() > 0) {
+ getActivity().getContentResolver().update(
+ ContentUris.withAppendedId(BrowserContract.Bookmarks.CONTENT_URI, id),
+ values, null, null);
+ }
+ }
+
+ private void displayRemoveBookmarkDialog(final int position) {
// Put up a dialog asking if the user really wants to
// delete the bookmark
- final int deletePos = position;
- new AlertDialog.Builder(this)
+ Cursor cursor = (Cursor) mAdapter.getItem(position);
+ Context context = getActivity();
+ final ContentResolver resolver = context.getContentResolver();
+ final Uri uri = ContentUris.withAppendedId(BrowserContract.Bookmarks.CONTENT_URI,
+ cursor.getLong(BookmarksLoader.COLUMN_INDEX_ID));
+
+ new AlertDialog.Builder(context)
.setTitle(R.string.delete_bookmark)
.setIcon(android.R.drawable.ic_dialog_alert)
- .setMessage(getText(R.string.delete_bookmark_warning).toString().replace(
- "%s", getBookmarkTitle(deletePos)))
+ .setMessage(context.getString(R.string.delete_bookmark_warning,
+ cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE)))
.setPositiveButton(R.string.ok,
new DialogInterface.OnClickListener() {
+ @Override
public void onClick(DialogInterface dialog, int whichButton) {
- deleteBookmark(deletePos);
+ resolver.delete(uri, null, null);
}
})
.setNegativeButton(R.string.cancel, null)
.show();
}
- /**
- * 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 == null ? null
- : mBookmarksAdapter.getRow(position);
- }
-
- /**
- * Return the url of the currently highlighted row.
- */
- public String getUrl(int position) {
- return mBookmarksAdapter == null ? null
- : mBookmarksAdapter.getUrl(position);
- }
-
- /**
- * Return the favicon of the currently highlighted row.
- */
- public Bitmap getFavicon(int position) {
- return mBookmarksAdapter == null ? null
- : mBookmarksAdapter.getFavicon(position);
- }
-
- private Bitmap getTouchIcon(int position) {
- return mBookmarksAdapter == null ? null
- : mBookmarksAdapter.getTouchIcon(position);
+ private String getUrl(int position) {
+ Cursor cursor = (Cursor) mAdapter.getItem(position);
+ return cursor.getString(BookmarksLoader.COLUMN_INDEX_URL);
}
private void copy(CharSequence text) {
- try {
- IClipboard clip = IClipboard.Stub.asInterface(ServiceManager.getService("clipboard"));
- if (clip != null) {
- clip.setClipboardText(text);
- }
- } catch (android.os.RemoteException e) {
- Log.e(LOGTAG, "Copy failed", e);
- }
- }
-
- public String getBookmarkTitle(int 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);
- }
-
- @Override
- public void onBackPressed() {
- setResultToParent(RESULT_CANCELED, null);
- mCanceled = true;
- super.onBackPressed();
- }
-
- // 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 parent = getParent();
- if (parent == null) {
- setResult(resultCode, data);
- } else {
- ((CombinedBookmarkHistoryActivity) parent).setResultFromChild(
- resultCode, data);
- }
+ ClipboardManager cm = (ClipboardManager) getActivity().getSystemService(
+ Context.CLIPBOARD_SERVICE);
+ cm.setPrimaryClip(ClipData.newRawUri(null, null, Uri.parse(text.toString())));
}
}
diff --git a/src/com/android/browser/BrowserHistoryPage.java b/src/com/android/browser/BrowserHistoryPage.java
index 23080f8..2295804 100644
--- a/src/com/android/browser/BrowserHistoryPage.java
+++ b/src/com/android/browser/BrowserHistoryPage.java
@@ -17,171 +17,193 @@
package com.android.browser;
import android.app.Activity;
-import android.app.ExpandableListActivity;
+import android.app.Fragment;
+import android.app.LoaderManager.LoaderCallbacks;
+import android.content.ClipboardManager;
import android.content.Context;
+import android.content.CursorLoader;
import android.content.Intent;
+import android.content.Loader;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
-import android.os.ServiceManager;
import android.provider.Browser;
-import android.text.IClipboard;
-import android.util.Log;
+import android.provider.BrowserContract.History;
import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
+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.ContextMenu.ContextMenuInfo;
-import android.view.ViewStub;
import android.webkit.WebIconDatabase.IconListener;
-import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
+import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.Toast;
/**
* Activity for displaying the browser's history, divided into
* days of viewing.
*/
-public class BrowserHistoryPage extends ExpandableListActivity {
- private HistoryAdapter mAdapter;
- private boolean mDisableNewWindow;
- private HistoryItem mContextHeader;
+public class BrowserHistoryPage extends Fragment
+ implements LoaderCallbacks<Cursor>, OnChildClickListener {
- private final static String LOGTAG = "browser";
+ static final int LOADER_HISTORY = 1;
+
+ BookmarksHistoryCallbacks mCallbacks;
+ ExpandableListView mList;
+ View mEmptyView;
+ HistoryAdapter mAdapter;
+ boolean mDisableNewWindow;
+ HistoryItem mContextHeader;
// Implementation of WebIconDatabase.IconListener
- private class IconReceiver implements IconListener {
+ class IconReceiver implements IconListener {
+ @Override
public void onReceivedIcon(String url, Bitmap icon) {
- setListAdapter(mAdapter);
+ mAdapter.notifyDataSetChanged();
}
}
- // Instance of IconReceiver
- private final IconReceiver mIconReceiver = new IconReceiver();
- /**
- * Report back to the calling activity to load a site.
- * @param url Site to load.
- * @param newWindow True if the URL should be loaded in a new window
- */
- 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();
+ // Instance of IconReceiver
+ final IconReceiver mIconReceiver = new IconReceiver();
+
+ static interface HistoryQuery {
+ static final String[] PROJECTION = new String[] {
+ History._ID, // 0
+ History.DATE_LAST_VISITED, // 1
+ History.TITLE, // 2
+ History.URL, // 3
+ History.FAVICON, // 4
+ };
+
+ static final int INDEX_ID = 0;
+ static final int INDEX_DATE_LAST_VISITED = 1;
+ static final int INDEX_TITE = 2;
+ static final int INDEX_URL = 3;
+ static final int INDEX_FAVICON = 4;
}
-
+
private void copy(CharSequence text) {
- try {
- IClipboard clip = IClipboard.Stub.asInterface(ServiceManager.getService("clipboard"));
- if (clip != null) {
- clip.setClipboardText(text);
+ ClipboardManager cm = (ClipboardManager) getActivity().getSystemService(
+ Context.CLIPBOARD_SERVICE);
+ cm.setText(text);
+ }
+
+ @Override
+ public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ switch (id) {
+ case LOADER_HISTORY: {
+ CursorLoader loader = new CursorLoader(getActivity(), History.CONTENT_URI,
+ HistoryQuery.PROJECTION, null, null, null);
+ return loader;
}
- } catch (android.os.RemoteException e) {
- Log.e(LOGTAG, "Copy failed", e);
+
+ default: {
+ throw new IllegalArgumentException();
+ }
}
}
@Override
- protected void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- setTitle(R.string.browser_history);
+ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+ switch (loader.getId()) {
+ case LOADER_HISTORY: {
+ mAdapter.changeCursor(data);
- 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";
+ // Add an empty view late, so it does not claim an empty
+ // history before the adapter is present
+ mList.setEmptyView(mEmptyView);
- Cursor cursor = managedQuery(
- Browser.BOOKMARKS_URI,
- Browser.HISTORY_PROJECTION,
- whereClause, null, orderBy);
-
- mAdapter = new HistoryAdapter(this, cursor,
- Browser.HISTORY_PROJECTION_DATE_INDEX);
- setListAdapter(mAdapter);
- final ExpandableListView list = getExpandableListView();
- list.setOnCreateContextMenuListener(this);
- View v = new ViewStub(this, R.layout.empty_history);
- addContentView(v, new LayoutParams(LayoutParams.MATCH_PARENT,
- LayoutParams.MATCH_PARENT));
- list.setEmptyView(v);
- // Do not post the runnable if there is nothing in the list.
- if (list.getExpandableListAdapter().getGroupCount() > 0) {
- list.post(new Runnable() {
- public void run() {
- // In case the history gets cleared before this event
- // happens.
- if (list.getExpandableListAdapter().getGroupCount() > 0) {
- list.expandGroup(0);
- }
+ // Do not post the runnable if there is nothing in the list.
+ if (mList.getExpandableListAdapter().getGroupCount() > 0) {
+ mList.post(new Runnable() {
+ @Override
+ public void run() {
+ // In case the history gets cleared before this
+ // event happens
+ if (mList.getExpandableListAdapter().getGroupCount() > 0) {
+ mList.expandGroup(0);
+ }
+ }
+ });
}
- });
+ break;
+ }
+
+ default: {
+ throw new IllegalArgumentException();
+ }
}
- mDisableNewWindow = getIntent().getBooleanExtra("disable_new_window",
- false);
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ setHasOptionsMenu(true);
+
+ Bundle args = getArguments();
+ mDisableNewWindow = args.getBoolean("disable_new_window", false);
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ mCallbacks = (BookmarksHistoryCallbacks) activity;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View root = inflater.inflate(R.layout.history, container, false);
+ mList = (ExpandableListView) root.findViewById(android.R.id.list);
+ mList.setOnCreateContextMenuListener(this);
+ mList.setOnChildClickListener(this);
+ mAdapter = new HistoryAdapter(getActivity());
+ mList.setAdapter(mAdapter);
+
+ mEmptyView = root.findViewById(android.R.id.empty);
+
+ // Start the loader
+ getLoaderManager().initLoader(LOADER_HISTORY, null, this);
// Register to receive icons in case they haven't all been loaded.
- CombinedBookmarkHistoryActivity.getIconListenerSet()
- .addListener(mIconReceiver);
+ 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);
+ return root;
}
@Override
- protected void onDestroy() {
+ public void onDestroy() {
super.onDestroy();
- CombinedBookmarkHistoryActivity.getIconListenerSet()
- .removeListener(mIconReceiver);
+ CombinedBookmarkHistoryActivity.getIconListenerSet().removeListener(mIconReceiver);
}
@Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- MenuInflater inflater = getMenuInflater();
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.history, menu);
- return true;
}
@Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- menu.findItem(R.id.clear_history_menu_id).setVisible(Browser.canClearHistory(this.getContentResolver()));
- return true;
+ public void onPrepareOptionsMenu(Menu menu) {
+ menu.findItem(R.id.clear_history_menu_id).setVisible(
+ Browser.canClearHistory(getActivity().getContentResolver()));
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.clear_history_menu_id:
- Browser.clearHistory(getContentResolver());
+ Browser.clearHistory(getActivity().getContentResolver());
// BrowserHistoryPage is always a child of
// CombinedBookmarkHistoryActivity
- ((CombinedBookmarkHistoryActivity) getParent())
- .removeParentChildRelationShips();
- mAdapter.refreshData();
+ mCallbacks.onRemoveParentChildRelationShips();
return true;
default:
@@ -191,24 +213,23 @@
}
@Override
- public void onCreateContextMenu(ContextMenu menu, View v,
- ContextMenuInfo menuInfo) {
- ExpandableListContextMenuInfo i =
- (ExpandableListContextMenuInfo) menuInfo;
+ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
+ ExpandableListContextMenuInfo i = (ExpandableListContextMenuInfo) menuInfo;
// Do not allow a context menu to come up from the group views.
if (!(i.targetView instanceof HistoryItem)) {
return;
}
// Inflate the menu
- MenuInflater inflater = getMenuInflater();
+ Activity parent = getActivity();
+ MenuInflater inflater = parent.getMenuInflater();
inflater.inflate(R.menu.historycontext, menu);
HistoryItem historyItem = (HistoryItem) i.targetView;
// Setup the header
if (mContextHeader == null) {
- mContextHeader = new HistoryItem(this);
+ mContextHeader = new HistoryItem(parent);
} else if (mContextHeader.getParent() != null) {
((ViewGroup) mContextHeader.getParent()).removeView(mContextHeader);
}
@@ -225,7 +246,7 @@
item.setTitle(R.string.remove_from_bookmarks);
}
// decide whether to show the share link option
- PackageManager pm = getPackageManager();
+ PackageManager pm = parent.getPackageManager();
Intent send = new Intent(Intent.ACTION_SEND);
send.setType("text/plain");
ResolveInfo ri = pm.resolveActivity(send, PackageManager.MATCH_DEFAULT_ONLY);
@@ -241,72 +262,63 @@
HistoryItem historyItem = (HistoryItem) i.targetView;
String url = historyItem.getUrl();
String title = historyItem.getName();
+ Activity activity = getActivity();
switch (item.getItemId()) {
case R.id.open_context_menu_id:
- loadUrl(url, false);
+ mCallbacks.onUrlSelected(url, false);
return true;
case R.id.new_window_context_menu_id:
- loadUrl(url, true);
+ mCallbacks.onUrlSelected(url, true);
return true;
case R.id.save_to_bookmarks_menu_id:
if (historyItem.isBookmark()) {
- Bookmarks.removeFromBookmarks(this, getContentResolver(),
+ Bookmarks.removeFromBookmarks(activity, activity.getContentResolver(),
url, title);
} else {
- Browser.saveBookmark(this, title, url);
+ Browser.saveBookmark(activity, title, url);
}
return true;
case R.id.share_link_context_menu_id:
- Browser.sendString(this, url,
- getText(R.string.choosertitle_sharevia).toString());
+ Browser.sendString(activity, url,
+ activity.getText(R.string.choosertitle_sharevia).toString());
return true;
case R.id.copy_url_context_menu_id:
copy(url);
return true;
case R.id.delete_context_menu_id:
- Browser.deleteFromHistory(getContentResolver(), url);
- mAdapter.refreshData();
+ Browser.deleteFromHistory(activity.getContentResolver(), url);
return true;
case R.id.homepage_context_menu_id:
- BrowserSettings.getInstance().setHomePage(this, url);
- Toast.makeText(this, R.string.homepage_set,
- Toast.LENGTH_LONG).show();
+ BrowserSettings.getInstance().setHomePage(activity, url);
+ Toast.makeText(activity, R.string.homepage_set, Toast.LENGTH_LONG).show();
return true;
default:
break;
}
return super.onContextItemSelected(item);
}
-
+
@Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
- if (v instanceof HistoryItem) {
- loadUrl(((HistoryItem) v).getUrl(), false);
+ if (v instanceof BookmarkItem) {
+ mCallbacks.onUrlSelected(((BookmarkItem) v).getUrl(), false);
return true;
}
return false;
}
- // 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) {
- ((CombinedBookmarkHistoryActivity) getParent()).setResultFromChild(
- resultCode, data);
- }
-
private class HistoryAdapter extends DateSortedExpandableListAdapter {
- HistoryAdapter(Context context, Cursor cursor, int index) {
- super(context, cursor, index);
-
+ HistoryAdapter(Context context) {
+ super(context, HistoryQuery.INDEX_DATE_LAST_VISITED);
}
+ @Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
View convertView, ViewGroup parent) {
- HistoryItem item;
- if (null == convertView || !(convertView instanceof HistoryItem)) {
- item = new HistoryItem(BrowserHistoryPage.this);
+ BookmarkItem item;
+ if (null == convertView || !(convertView instanceof BookmarkItem)) {
+ item = new BookmarkItem(getContext());
// Add padding on the left so it will be indented from the
// arrows on the group views.
item.setPadding(item.getPaddingLeft() + 10,
@@ -314,16 +326,18 @@
item.getPaddingRight(),
item.getPaddingBottom());
} else {
- item = (HistoryItem) convertView;
+ item = (BookmarkItem) convertView;
}
+
// Bail early if the Cursor is closed.
if (!moveCursorToChildPosition(groupPosition, childPosition)) {
return item;
}
- item.setName(getString(Browser.HISTORY_PROJECTION_TITLE_INDEX));
- String url = getString(Browser.HISTORY_PROJECTION_URL_INDEX);
+
+ item.setName(getString(HistoryQuery.INDEX_TITE));
+ String url = getString(HistoryQuery.INDEX_URL);
item.setUrl(url);
- byte[] data = getBlob(Browser.HISTORY_PROJECTION_FAVICON_INDEX);
+ byte[] data = getBlob(HistoryQuery.INDEX_FAVICON);
if (data != null) {
item.setFavicon(BitmapFactory.decodeByteArray(data, 0,
data.length));
@@ -331,8 +345,6 @@
item.setFavicon(CombinedBookmarkHistoryActivity
.getIconListenerSet().getFavicon(url));
}
- item.setIsBookmark(1 ==
- getInt(Browser.HISTORY_PROJECTION_BOOKMARK_INDEX));
return item;
}
}
diff --git a/src/com/android/browser/BrowserHomepagePreference.java b/src/com/android/browser/BrowserHomepagePreference.java
index 4f18bd5..057e691 100644
--- a/src/com/android/browser/BrowserHomepagePreference.java
+++ b/src/com/android/browser/BrowserHomepagePreference.java
@@ -97,7 +97,7 @@
* @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) {
+ public void setCurrentPage(String currentPage) {
mCurrentPage = currentPage;
}
diff --git a/src/com/android/browser/BrowserPreferencesPage.java b/src/com/android/browser/BrowserPreferencesPage.java
index 9af66f1..d93e70f 100644
--- a/src/com/android/browser/BrowserPreferencesPage.java
+++ b/src/com/android/browser/BrowserPreferencesPage.java
@@ -16,96 +16,30 @@
package com.android.browser;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.preference.EditTextPreference;
-import android.preference.Preference;
+import com.android.browser.preferences.DebugPreferencesFragment;
+
import android.preference.PreferenceActivity;
-import android.preference.PreferenceScreen;
-import android.webkit.GeolocationPermissions;
-import android.webkit.ValueCallback;
-import android.webkit.WebStorage;
+import android.preference.PreferenceManager;
-import java.util.Map;
-import java.util.Set;
+import java.util.List;
-public class BrowserPreferencesPage extends PreferenceActivity
- implements Preference.OnPreferenceChangeListener {
+public class BrowserPreferencesPage extends PreferenceActivity {
- private String LOGTAG = "BrowserPreferencesPage";
- /* package */ static final String CURRENT_PAGE = "currentPage";
+ public static final String CURRENT_PAGE = "currentPage";
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // Load the XML preferences file
- addPreferencesFromResource(R.xml.browser_preferences);
-
- Preference e = findPreference(BrowserSettings.PREF_HOMEPAGE);
- 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);
-
- e = findPreference(BrowserSettings.PREF_TEXT_SIZE);
- e.setOnPreferenceChangeListener(this);
- e.setSummary(getVisualTextSizeName(
- getPreferenceScreen().getSharedPreferences()
- .getString(BrowserSettings.PREF_TEXT_SIZE, null)) );
-
- e = findPreference(BrowserSettings.PREF_DEFAULT_ZOOM);
- e.setOnPreferenceChangeListener(this);
- e.setSummary(getVisualDefaultZoomName(
- getPreferenceScreen().getSharedPreferences()
- .getString(BrowserSettings.PREF_DEFAULT_ZOOM, null)) );
-
- 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);
- }
-
- PreferenceScreen websiteSettings = (PreferenceScreen)
- findPreference(BrowserSettings.PREF_WEBSITE_SETTINGS);
- Intent intent = new Intent(this, WebsiteSettingsActivity.class);
- websiteSettings.setIntent(intent);
- }
-
- /*
- * We need to set the PreferenceScreen state in onResume(), as the number of
- * origins with active features (WebStorage, Geolocation etc) could have
- * changed after calling the WebsiteSettingsActivity.
+ /**
+ * Populate the activity with the top-level headers.
*/
@Override
- protected void onResume() {
- super.onResume();
- final PreferenceScreen websiteSettings = (PreferenceScreen)
- findPreference(BrowserSettings.PREF_WEBSITE_SETTINGS);
- websiteSettings.setEnabled(false);
- WebStorage.getInstance().getOrigins(new ValueCallback<Map>() {
- public void onReceiveValue(Map webStorageOrigins) {
- if ((webStorageOrigins != null) && !webStorageOrigins.isEmpty()) {
- websiteSettings.setEnabled(true);
- }
- }
- });
- GeolocationPermissions.getInstance().getOrigins(new ValueCallback<Set<String> >() {
- public void onReceiveValue(Set<String> geolocationOrigins) {
- if ((geolocationOrigins != null) && !geolocationOrigins.isEmpty()) {
- websiteSettings.setEnabled(true);
- }
- }
- });
+ public void onBuildHeaders(List<Header> target) {
+ loadHeadersFromResource(R.xml.preference_headers, target);
+
+ if (BrowserSettings.getInstance().showDebugSettings()) {
+ Header debug = new Header();
+ debug.title = getText(R.string.pref_development_title);
+ debug.fragment = DebugPreferencesFragment.class.getName();
+ target.add(debug);
+ }
}
@Override
@@ -115,98 +49,6 @@
// sync the shared preferences back to BrowserSettings
BrowserSettings.getInstance().syncSharedPreferences(
getApplicationContext(),
- getPreferenceScreen().getSharedPreferences());
- }
-
- public boolean onPreferenceChange(Preference pref, Object objValue) {
- if (pref.getKey().equals(BrowserSettings.PREF_EXTRAS_RESET_DEFAULTS)) {
- Boolean value = (Boolean) objValue;
- if (value.booleanValue() == true) {
- finish();
- }
- } else if (pref.getKey().equals(BrowserSettings.PREF_HOMEPAGE)) {
- String value = (String) objValue;
- boolean needUpdate = value.indexOf(' ') != -1;
- if (needUpdate) {
- value = value.trim().replace(" ", "%20");
- }
- if (value.length() != 0 && Uri.parse(value).getScheme() == null) {
- value = "http://" + value;
- needUpdate = true;
- }
- // Set the summary value.
- pref.setSummary(value);
- if (needUpdate) {
- // Update through the EditText control as it has a cached copy
- // of the string and it will handle persisting the value
- ((EditTextPreference) pref).setText(value);
-
- // as we update the value above, we need to return false
- // here so that setText() is not called by EditTextPref
- // with the old value.
- return false;
- } else {
- return true;
- }
- } else if (pref.getKey().equals(BrowserSettings.PREF_TEXT_SIZE)) {
- pref.setSummary(getVisualTextSizeName((String) objValue));
- return true;
- } else if (pref.getKey().equals(BrowserSettings.PREF_DEFAULT_ZOOM)) {
- pref.setSummary(getVisualDefaultZoomName((String) objValue));
- return true;
- } else if (pref.getKey().equals(
- 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;
- }
-
- private CharSequence getVisualTextSizeName(String enumName) {
- CharSequence[] visualNames = getResources().getTextArray(
- R.array.pref_text_size_choices);
- CharSequence[] enumNames = getResources().getTextArray(
- R.array.pref_text_size_values);
-
- // Sanity check
- if (visualNames.length != enumNames.length) {
- return "";
- }
-
- for (int i = 0; i < enumNames.length; i++) {
- if (enumNames[i].equals(enumName)) {
- return visualNames[i];
- }
- }
-
- return "";
- }
-
- private CharSequence getVisualDefaultZoomName(String enumName) {
- CharSequence[] visualNames = getResources().getTextArray(
- R.array.pref_default_zoom_choices);
- CharSequence[] enumNames = getResources().getTextArray(
- R.array.pref_default_zoom_values);
-
- // Sanity check
- if (visualNames.length != enumNames.length) {
- return "";
- }
-
- for (int i = 0; i < enumNames.length; i++) {
- if (enumNames[i].equals(enumName)) {
- return visualNames[i];
- }
- }
-
- return "";
+ PreferenceManager.getDefaultSharedPreferences(this));
}
}
diff --git a/src/com/android/browser/BrowserProvider.java b/src/com/android/browser/BrowserProvider.java
index f8574ed..f371e24 100644
--- a/src/com/android/browser/BrowserProvider.java
+++ b/src/com/android/browser/BrowserProvider.java
@@ -29,8 +29,10 @@
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.UriMatcher;
+import android.content.res.Configuration;
import android.database.AbstractCursor;
import android.database.Cursor;
+import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
@@ -38,6 +40,7 @@
import android.preference.PreferenceManager;
import android.provider.Browser;
import android.provider.Browser.BookmarkColumns;
+import android.provider.Settings;
import android.speech.RecognizerResultsIntent;
import android.text.TextUtils;
import android.util.Log;
@@ -84,6 +87,17 @@
private static final int SUGGEST_COLUMN_QUERY_ID = 8;
private static final int SUGGEST_COLUMN_INTENT_EXTRA_DATA = 9;
+ // how many suggestions will be shown in dropdown
+ // 0..SHORT: filled by browser db
+ private static final int MAX_SUGGEST_SHORT_SMALL = 3;
+ // SHORT..LONG: filled by search suggestions
+ private static final int MAX_SUGGEST_LONG_SMALL = 6;
+
+ // large screen size shows more
+ private static final int MAX_SUGGEST_SHORT_LARGE = 6;
+ private static final int MAX_SUGGEST_LONG_LARGE = 9;
+
+
// shared suggestion columns
private static final String[] COLUMNS = new String[] {
"_id",
@@ -97,10 +111,6 @@
SearchManager.SUGGEST_COLUMN_QUERY,
SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA};
- private static final int MAX_SUGGESTION_SHORT_ENTRIES = 3;
- private static final int MAX_SUGGESTION_LONG_ENTRIES = 6;
- private static final String MAX_SUGGESTION_LONG_ENTRIES_STRING =
- Integer.valueOf(MAX_SUGGESTION_LONG_ENTRIES).toString();
// make sure that these match the index of TABLE_NAMES
private static final int URI_MATCH_BOOKMARKS = 0;
@@ -160,6 +170,9 @@
private BrowserSettings mSettings;
+ private int mMaxSuggestionShortSize;
+ private int mMaxSuggestionLongSize;
+
public BrowserProvider() {
}
@@ -343,6 +356,20 @@
@Override
public boolean onCreate() {
final Context context = getContext();
+ boolean xlargeScreenSize = (context.getResources().getConfiguration().screenLayout
+ & Configuration.SCREENLAYOUT_SIZE_MASK)
+ == Configuration.SCREENLAYOUT_SIZE_XLARGE;
+ boolean isPortrait = (context.getResources().getConfiguration().orientation
+ == Configuration.ORIENTATION_PORTRAIT);
+
+
+ if (xlargeScreenSize && isPortrait) {
+ mMaxSuggestionLongSize = MAX_SUGGEST_LONG_LARGE;
+ mMaxSuggestionShortSize = MAX_SUGGEST_SHORT_LARGE;
+ } else {
+ mMaxSuggestionLongSize = MAX_SUGGEST_LONG_SMALL;
+ mMaxSuggestionShortSize = MAX_SUGGEST_SHORT_SMALL;
+ }
mOpenHelper = new DatabaseHelper(context);
mBackupManager = new BackupManager(context);
// we added "picasa web album" into default bookmarks for version 19.
@@ -409,10 +436,10 @@
public MySuggestionCursor(Cursor hc, Cursor sc, String string) {
mHistoryCursor = hc;
mSuggestCursor = sc;
- mHistoryCount = hc.getCount();
+ mHistoryCount = hc != null ? hc.getCount() : 0;
mSuggestionCount = sc != null ? sc.getCount() : 0;
- if (mSuggestionCount > (MAX_SUGGESTION_LONG_ENTRIES - mHistoryCount)) {
- mSuggestionCount = MAX_SUGGESTION_LONG_ENTRIES - mHistoryCount;
+ if (mSuggestionCount > (mMaxSuggestionLongSize - mHistoryCount)) {
+ mSuggestionCount = mMaxSuggestionLongSize - mHistoryCount;
}
mString = string;
mIncludeWebSearch = string.length() > 0;
@@ -626,6 +653,7 @@
}
// TODO Temporary change, finalize after jq's changes go in
+ @Override
public void deactivate() {
if (mHistoryCursor != null) {
mHistoryCursor.deactivate();
@@ -636,12 +664,14 @@
super.deactivate();
}
+ @Override
public boolean requery() {
return (mHistoryCursor != null ? mHistoryCursor.requery() : false) |
(mSuggestCursor != null ? mSuggestCursor.requery() : false);
}
// TODO Temporary change, finalize after jq's changes go in
+ @Override
public void close() {
super.close();
if (mHistoryCursor != null) {
@@ -706,12 +736,15 @@
public ResultsCursor(ArrayList<String> results) {
mResults = results;
}
+ @Override
public int getCount() { return mResults.size(); }
+ @Override
public String[] getColumnNames() {
return RESULTS_COLUMNS;
}
+ @Override
public String getString(int column) {
switch (column) {
case RESULT_ACTION_ID:
@@ -733,30 +766,39 @@
return null;
}
}
+ @Override
public short getShort(int column) {
throw new UnsupportedOperationException();
}
+ @Override
public int getInt(int column) {
throw new UnsupportedOperationException();
}
+ @Override
public long getLong(int column) {
if ((mPos != -1) && column == 0) {
return mPos; // use row# as the _id
}
throw new UnsupportedOperationException();
}
+ @Override
public float getFloat(int column) {
throw new UnsupportedOperationException();
}
+ @Override
public double getDouble(int column) {
throw new UnsupportedOperationException();
}
+ @Override
public boolean isNull(int column) {
throw new UnsupportedOperationException();
}
}
+ /** Contains custom suggestions results set by the UI */
private ResultsCursor mResultsCursor;
+ /** Locks access to {@link #mResultsCursor} */
+ private Object mResultsCursorLock = new Object();
/**
* Provide a set of results to be returned to query, intended to be used
@@ -764,10 +806,12 @@
* @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);
+ synchronized (mResultsCursorLock) {
+ if (results == null) {
+ mResultsCursor = null;
+ } else {
+ mResultsCursor = new ResultsCursor(results);
+ }
}
}
@@ -779,57 +823,19 @@
if (match == -1) {
throw new IllegalArgumentException("Unknown URL");
}
- if (match == URI_MATCH_SUGGEST && mResultsCursor != null) {
- Cursor results = mResultsCursor;
- mResultsCursor = null;
- return results;
+
+ // If results for the suggestion are already ready just return them directly
+ synchronized (mResultsCursorLock) {
+ 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;
- String [] myArgs;
- if (selectionArgs[0] == null || selectionArgs[0].equals("")) {
- suggestSelection = null;
- myArgs = null;
- } else {
- String like = selectionArgs[0] + "%";
- if (selectionArgs[0].startsWith("http")
- || selectionArgs[0].startsWith("file")) {
- myArgs = new String[1];
- myArgs[0] = like;
- suggestSelection = selection;
- } else {
- SUGGEST_ARGS[0] = "http://" + like;
- SUGGEST_ARGS[1] = "http://www." + like;
- SUGGEST_ARGS[2] = "https://" + like;
- SUGGEST_ARGS[3] = "https://www." + like;
- // To match against titles.
- SUGGEST_ARGS[4] = like;
- myArgs = SUGGEST_ARGS;
- suggestSelection = SUGGEST_SELECTION;
- }
- }
-
- Cursor c = db.query(TABLE_NAMES[URI_MATCH_BOOKMARKS],
- SUGGEST_PROJECTION, suggestSelection, myArgs, null, null,
- ORDER_BY, MAX_SUGGESTION_LONG_ENTRIES_STRING);
-
- if (match == URI_MATCH_BOOKMARKS_SUGGEST
- || Patterns.WEB_URL.matcher(selectionArgs[0]).matches()) {
- return new MySuggestionCursor(c, null, "");
- } else {
- // get search suggestions if there is still space in the list
- if (myArgs != null && myArgs.length > 1
- && c.getCount() < (MAX_SUGGESTION_SHORT_ENTRIES - 1)) {
- SearchEngine searchEngine = mSettings.getSearchEngine();
- if (searchEngine != null && searchEngine.supportsSuggestions()) {
- Cursor sc = searchEngine.getSuggestions(getContext(), selectionArgs[0]);
- return new MySuggestionCursor(c, sc, selectionArgs[0]);
- }
- }
- return new MySuggestionCursor(c, null, selectionArgs[0]);
- }
+ // Handle suggestions
+ return doSuggestQuery(selection, selectionArgs, match == URI_MATCH_BOOKMARKS_SUGGEST);
}
String[] projection = null;
@@ -839,29 +845,62 @@
projection[projectionIn.length] = "_id AS _id";
}
- StringBuilder whereClause = new StringBuilder(256);
+ String whereClause = null;
if (match == URI_MATCH_BOOKMARKS_ID || match == URI_MATCH_SEARCHES_ID) {
- whereClause.append("(_id = ").append(url.getPathSegments().get(1))
- .append(")");
+ whereClause = "_id = " + url.getPathSegments().get(1);
}
- // Tack on the user's selection, if present
- if (selection != null && selection.length() > 0) {
- if (whereClause.length() > 0) {
- whereClause.append(" AND ");
- }
-
- whereClause.append('(');
- whereClause.append(selection);
- whereClause.append(')');
- }
- Cursor c = db.query(TABLE_NAMES[match % 10], projection,
- whereClause.toString(), selectionArgs, null, null, sortOrder,
- null);
+ Cursor c = mOpenHelper.getReadableDatabase().query(TABLE_NAMES[match % 10], projection,
+ DatabaseUtils.concatenateWhere(whereClause, selection), selectionArgs,
+ null, null, sortOrder, null);
c.setNotificationUri(getContext().getContentResolver(), url);
return c;
}
+ private Cursor doSuggestQuery(String selection, String[] selectionArgs, boolean bookmarksOnly) {
+ String suggestSelection;
+ String [] myArgs;
+ if (selectionArgs[0] == null || selectionArgs[0].equals("")) {
+ return new MySuggestionCursor(null, null, "");
+ } else {
+ String like = selectionArgs[0] + "%";
+ if (selectionArgs[0].startsWith("http")
+ || selectionArgs[0].startsWith("file")) {
+ myArgs = new String[1];
+ myArgs[0] = like;
+ suggestSelection = selection;
+ } else {
+ SUGGEST_ARGS[0] = "http://" + like;
+ SUGGEST_ARGS[1] = "http://www." + like;
+ SUGGEST_ARGS[2] = "https://" + like;
+ SUGGEST_ARGS[3] = "https://www." + like;
+ // To match against titles.
+ SUGGEST_ARGS[4] = like;
+ myArgs = SUGGEST_ARGS;
+ suggestSelection = SUGGEST_SELECTION;
+ }
+ }
+
+ Cursor c = mOpenHelper.getReadableDatabase().query(TABLE_NAMES[URI_MATCH_BOOKMARKS],
+ SUGGEST_PROJECTION, suggestSelection, myArgs, null, null,
+ ORDER_BY, Integer.toString(mMaxSuggestionLongSize));
+
+ if (bookmarksOnly || Patterns.WEB_URL.matcher(selectionArgs[0]).matches()) {
+ return new MySuggestionCursor(c, null, "");
+ } else {
+ // get search suggestions if there is still space in the list
+ if (myArgs != null && myArgs.length > 1
+ && c.getCount() < (MAX_SUGGEST_SHORT_SMALL - 1)) {
+ SearchEngine searchEngine = mSettings.getSearchEngine();
+ if (searchEngine != null && searchEngine.supportsSuggestions()) {
+ Cursor sc = searchEngine.getSuggestions(getContext(), selectionArgs[0]);
+ return new MySuggestionCursor(c, sc, selectionArgs[0]);
+ }
+ }
+ return new MySuggestionCursor(c, null, selectionArgs[0]);
+ }
+ }
+
@Override
public String getType(Uri url) {
int match = URI_MATCHER.match(url);
@@ -1067,4 +1106,10 @@
}
}
+ public static Cursor getBookmarksSuggestions(ContentResolver cr, String constraint) {
+ Uri uri = Uri.parse("content://browser/" + SearchManager.SUGGEST_URI_PATH_QUERY);
+ return cr.query(uri, SUGGEST_PROJECTION, SUGGEST_SELECTION,
+ new String[] { constraint }, ORDER_BY);
+ }
+
}
diff --git a/src/com/android/browser/BrowserSettings.java b/src/com/android/browser/BrowserSettings.java
index 3791eb0..8cd001e 100644
--- a/src/com/android/browser/BrowserSettings.java
+++ b/src/com/android/browser/BrowserSettings.java
@@ -28,6 +28,7 @@
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.database.ContentObserver;
+import android.net.Uri;
import android.os.Handler;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
@@ -62,7 +63,7 @@
* To remove an observer:
* s.deleteObserver(webView.getSettings());
*/
-class BrowserSettings extends Observable {
+public class BrowserSettings extends Observable {
// Private variables for settings
// NOTE: these defaults need to be kept in sync with the XML
@@ -76,6 +77,7 @@
private boolean showSecurityWarnings;
private boolean rememberPasswords;
private boolean saveFormData;
+ private boolean autoFillEnabled;
private boolean openInBackground;
private String defaultTextEncodingName;
private String homeUrl = "";
@@ -115,8 +117,8 @@
private boolean showConsole = true;
// Private preconfigured values
- private static int minimumFontSize = 8;
- private static int minimumLogicalFontSize = 8;
+ private static int minimumFontSize = 1;
+ private static int minimumLogicalFontSize = 1;
private static int defaultFontSize = 16;
private static int defaultFixedFontSize = 13;
private static WebSettings.TextSize textSize =
@@ -166,6 +168,10 @@
// a ListView
public final static int MAX_TEXTVIEW_LEN = 80;
+ public static final String RLZ_PROVIDER = "com.google.android.partnersetup.rlzappprovider";
+
+ public static final Uri RLZ_PROVIDER_URI = Uri.parse("content://" + RLZ_PROVIDER + "/");
+
private TabControl mTabControl;
// Single instance of the BrowserSettings for use in the Browser app.
@@ -221,6 +227,7 @@
s.setDefaultZoom(b.zoomDensity);
s.setLightTouchEnabled(b.lightTouch);
s.setSaveFormData(b.saveFormData);
+ s.setAutoFillEnabled(b.autoFillEnabled);
s.setSavePassword(b.rememberPasswords);
s.setLoadWithOverviewMode(b.loadsPageInOverviewMode);
s.setPageCacheCapacity(pageCacheCapacity);
@@ -229,6 +236,9 @@
s.setNeedInitialFocus(false);
// Browser supports multiple windows
s.setSupportMultipleWindows(true);
+ // enable smooth transition for better performance during panning or
+ // zooming
+ s.setEnableSmoothTransition(true);
// HTML5 API flags
s.setAppCacheEnabled(b.appCacheEnabled);
@@ -332,6 +342,7 @@
rememberPasswords);
saveFormData = p.getBoolean("save_formdata",
saveFormData);
+ autoFillEnabled = p.getBoolean("autoFill_enabled", autoFillEnabled);
boolean accept_cookies = p.getBoolean("accept_cookies",
CookieManager.getInstance().acceptCookie());
CookieManager.getInstance().setAcceptCookie(accept_cookies);
@@ -568,45 +579,23 @@
: ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
- private void maybeDisableWebsiteSettings(Context context) {
- PreferenceActivity activity = (PreferenceActivity) context;
- final PreferenceScreen screen = (PreferenceScreen)
- activity.findPreference(BrowserSettings.PREF_WEBSITE_SETTINGS);
- screen.setEnabled(false);
- WebStorage.getInstance().getOrigins(new ValueCallback<Map>() {
- public void onReceiveValue(Map webStorageOrigins) {
- if ((webStorageOrigins != null) && !webStorageOrigins.isEmpty()) {
- screen.setEnabled(true);
- }
- }
- });
-
- GeolocationPermissions.getInstance().getOrigins(new ValueCallback<Set<String> >() {
- public void onReceiveValue(Set<String> geolocationOrigins) {
- if ((geolocationOrigins != null) && !geolocationOrigins.isEmpty()) {
- screen.setEnabled(true);
- }
- }
- });
- }
-
/*package*/ void clearDatabases(Context context) {
WebStorage.getInstance().deleteAllData();
- maybeDisableWebsiteSettings(context);
}
/*package*/ void clearLocationAccess(Context context) {
GeolocationPermissions.getInstance().clearAll();
- maybeDisableWebsiteSettings(context);
}
/*package*/ void resetDefaultPreferences(Context ctx) {
reset();
- SharedPreferences p =
- PreferenceManager.getDefaultSharedPreferences(ctx);
+ SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(ctx);
p.edit().clear().apply();
- PreferenceManager.setDefaultValues(ctx, R.xml.browser_preferences,
- true);
+ PreferenceManager.setDefaultValues(ctx, R.xml.page_content_preferences, true);
+ PreferenceManager.setDefaultValues(ctx, R.xml.personal_preferences, true);
+ PreferenceManager.setDefaultValues(ctx, R.xml.privacy_preferences, true);
+ PreferenceManager.setDefaultValues(ctx, R.xml.security_preferences, true);
+ PreferenceManager.setDefaultValues(ctx, R.xml.advanced_preferences, true);
// reset homeUrl
setHomePage(ctx, getFactoryResetHomeUrl(ctx));
// reset appcache max size
@@ -639,6 +628,7 @@
showSecurityWarnings = true;
rememberPasswords = true;
saveFormData = true;
+ autoFillEnabled = false;
openInBackground = false;
autoFitPage = true;
landscapeOnly = false;
diff --git a/src/com/android/browser/CircularProgressView.java b/src/com/android/browser/CircularProgressView.java
new file mode 100644
index 0000000..48f293a
--- /dev/null
+++ b/src/com/android/browser/CircularProgressView.java
@@ -0,0 +1,140 @@
+
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.browser;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.widget.ImageButton;
+
+/**
+ *
+ */
+public class CircularProgressView extends ImageButton {
+
+ private static final int[] ALPHAS = {
+ 64, 96, 128, 160, 192, 192, 160, 128, 96, 64
+ };
+
+ // 100 ms delay between frames, 10fps
+ private static int ALPHA_REFRESH_DELAY = 100;
+
+ private int mEndAngle;
+ private int mProgress;
+ private Paint mPaint;
+ private int mAlpha;
+ private boolean mAnimated;
+ private RectF mRect;
+ private int mMaxProgress;
+
+ /**
+ * @param context
+ * @param attrs
+ * @param defStyle
+ */
+ public CircularProgressView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init(context);
+ }
+
+ /**
+ * @param context
+ * @param attrs
+ */
+ public CircularProgressView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context);
+ }
+
+ /**
+ * @param context
+ */
+ public CircularProgressView(Context context) {
+ super(context);
+ init(context);
+ }
+
+ private void init(Context ctx) {
+ mEndAngle = 0;
+ mProgress = 0;
+ mMaxProgress = 100;
+ mPaint = new Paint();
+ mPaint.setAntiAlias(true);
+ mPaint.setColor(Color.BLACK);
+ mRect = new RectF();
+ }
+
+ void setMaxProgress(int max) {
+ mMaxProgress = max;
+ }
+
+ private synchronized boolean isAnimated() {
+ return mAnimated;
+ }
+
+ private synchronized void setAnimated(boolean animated) {
+ mAnimated = animated;
+ }
+
+ void setProgress(int progress) {
+ mProgress = progress;
+ mEndAngle = 360 * progress / mMaxProgress;
+ invalidate();
+ if (!isAnimated() && (progress > 0) && (progress < mMaxProgress)) {
+ setAnimated(true);
+ mAlpha = 0;
+ post(new Runnable() {
+ @Override
+ public void run() {
+ if (isAnimated()) {
+ mAlpha = (mAlpha + 1) % ALPHAS.length;
+ mPaint.setAlpha(ALPHAS[mAlpha]);
+ invalidate();
+ postDelayed(this, ALPHA_REFRESH_DELAY);
+ }
+ }
+ });
+ } else if ((progress <= 0) || (progress >= mMaxProgress)) {
+ setAnimated(false);
+ }
+ }
+
+ @Override
+ public void onDraw(Canvas canvas) {
+ int w = getWidth();
+ int h = getHeight();
+ float cx = w * 0.5f;
+ float cy = h * 0.5f;
+ mRect.set(0, 0, w, h);
+ if ((mProgress > 0) && (mProgress < mMaxProgress)) {
+ Path p = new Path();
+ p.moveTo(cx, cy);
+ p.lineTo(cx, 0);
+ p.arcTo(mRect, 270, mEndAngle);
+ p.lineTo(cx, cy);
+ int state = canvas.save();
+ canvas.drawPath(p, mPaint);
+ canvas.restoreToCount(state);
+ }
+ super.onDraw(canvas);
+ }
+
+}
diff --git a/src/com/android/browser/CombinedBookmarkHistoryActivity.java b/src/com/android/browser/CombinedBookmarkHistoryActivity.java
index 194956f..a98408c 100644
--- a/src/com/android/browser/CombinedBookmarkHistoryActivity.java
+++ b/src/com/android/browser/CombinedBookmarkHistoryActivity.java
@@ -17,22 +17,48 @@
package com.android.browser;
import android.app.Activity;
-import android.app.TabActivity;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
import android.content.Intent;
-import android.content.res.Resources;
+import android.database.MatrixCursor;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Browser;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowManager;
import android.webkit.WebIconDatabase;
import android.webkit.WebIconDatabase.IconListener;
-import android.widget.TabHost;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ListView;
+import android.widget.SimpleCursorAdapter;
import java.util.HashMap;
import java.util.Vector;
-public class CombinedBookmarkHistoryActivity extends TabActivity
- implements TabHost.OnTabChangeListener {
+interface BookmarksHistoryCallbacks {
+ public void onUrlSelected(String url, boolean newWindow);
+ public void onRemoveParentChildRelationShips();
+}
+
+public class CombinedBookmarkHistoryActivity extends Activity
+ implements BookmarksHistoryCallbacks, OnItemClickListener {
+ final static String NEWTAB_MODE = "newtab_mode";
+ final static String EXTRA_OPEN_NEW_WINDOW = "new_window";
+ final static String STARTING_FRAGMENT = "fragment";
+ final static String EVT_X = "evt_x";
+ final static String EVT_Y = "evt_y";
+ final static String EXTRA_TOP = "top";
+ final static String EXTRA_HEIGHT = "height";
+
+
+ final static int FRAGMENT_ID_BOOKMARKS = 1;
+ final static int FRAGMENT_ID_HISTORY = 2;
+
/**
* Used to inform BrowserActivity to remove the parent/child relationships
* from all the tabs.
@@ -48,10 +74,15 @@
*/
private int mResultCode;
- /* package */ static String BOOKMARKS_TAB = "bookmark";
- /* package */ static String VISITED_TAB = "visited";
- /* package */ static String HISTORY_TAB = "history";
- /* package */ static String STARTING_TAB = "tab";
+ /**
+ * Flag to inform the browser to force the result to open in a new tab.
+ */
+ private boolean mNewTabMode;
+
+ private int mRequestedTop;
+ private int mRequestedHeight;
+
+ long mCurrentFragment;
static class IconListenerSet implements IconListener {
// Used to store favicons as we get them from the database
@@ -64,6 +95,7 @@
mUrlsToIcons = new HashMap<String, Bitmap>();
mListeners = new Vector<IconListener>();
}
+ @Override
public void onReceivedIcon(String url, Bitmap icon) {
mUrlsToIcons.put(url, icon);
for (IconListener listener : mListeners) {
@@ -77,9 +109,10 @@
mListeners.remove(listener);
}
public Bitmap getFavicon(String url) {
- return (Bitmap) mUrlsToIcons.get(url);
+ return mUrlsToIcons.get(url);
}
}
+
private static IconListenerSet sIconListenerSet;
static IconListenerSet getIconListenerSet() {
if (null == sIconListenerSet) {
@@ -91,80 +124,104 @@
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.tabs);
+ setContentView(R.layout.bookmarks_history);
setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
- getTabHost().setOnTabChangedListener(this);
+ ListView list = (ListView) findViewById(android.R.id.list);
+ list.setOnItemClickListener(this);
+ MatrixCursor cursor = new MatrixCursor(new String[] { "name", "_id" });
+ cursor.newRow().add(getString(R.string.bookmarks)).add(FRAGMENT_ID_BOOKMARKS);
+ cursor.newRow().add(getString(R.string.history)).add(FRAGMENT_ID_HISTORY);
+ list.setAdapter(new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, cursor,
+ new String[] { "name" }, new int[] { android.R.id.text1 }));
+ int startingFragment = FRAGMENT_ID_BOOKMARKS;
Bundle extras = getIntent().getExtras();
-
- Intent bookmarksIntent = new Intent(this, BrowserBookmarksPage.class);
if (extras != null) {
- bookmarksIntent.putExtras(extras);
+ mNewTabMode = extras.getBoolean(NEWTAB_MODE);
+ mRequestedTop = extras.getInt(EXTRA_TOP, -1);
+ mRequestedHeight = extras.getInt(EXTRA_HEIGHT, -1);
+ startingFragment = extras.getInt(STARTING_FRAGMENT, FRAGMENT_ID_BOOKMARKS);
}
- 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 = 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);
- 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);
-
- if (defaultTab != null) {
- getTabHost().setCurrentTab(2);
- }
+ // Start up the default fragment
+ loadFragment(startingFragment);
// 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>() {
+ @Override
public Void doInBackground(Void... v) {
Browser.requestAllIcons(getContentResolver(),
- Browser.BookmarkColumns.FAVICON + " is NULL",
- getIconListenerSet());
+ Browser.BookmarkColumns.FAVICON + " is NULL", getIconListenerSet());
return null;
}
}).execute();
}
- private void createTab(Intent intent, int labelResId, int iconResId,
- String tab) {
- Resources resources = getResources();
- TabHost tabHost = getTabHost();
- tabHost.addTab(tabHost.newTabSpec(tab).setIndicator(
- resources.getText(labelResId), resources.getDrawable(iconResId))
- .setContent(intent));
- }
- // Copied from DialTacts Activity
- /** {@inheritDoc} */
- public void onTabChanged(String tabId) {
- Activity activity = getLocalActivityManager().getActivity(tabId);
- if (activity != null) {
- activity.onWindowFocusChanged(true);
+ @Override
+ public void onAttachedToWindow() {
+ if (mRequestedTop > -1) {
+ WindowManager.LayoutParams lp = getWindow().getAttributes();
+ lp.x = 0;
+ lp.y = mRequestedTop;
+ lp.height = mRequestedHeight;
+ lp.gravity = Gravity.TOP | Gravity.LEFT;
+ getWindow().setAttributes(lp);
}
}
+ @Override
+ public boolean onTouchEvent(MotionEvent evt) {
+ if (((evt.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) && (evt.getY() < 0)) {
+ Intent result = new Intent();
+ result.putExtra(EVT_X, evt.getRawX());
+ result.putExtra(EVT_Y, evt.getRawY());
+ setResultFromChild(Activity.RESULT_CANCELED, result);
+ finish();
+ return true;
+ }
+ return super.onTouchEvent(evt);
+ }
+
+ private void loadFragment(int id) {
+ String fragmentClassName;
+ switch (id) {
+ case FRAGMENT_ID_BOOKMARKS:
+ fragmentClassName = BrowserBookmarksPage.class.getName();
+ break;
+ case FRAGMENT_ID_HISTORY:
+ fragmentClassName = BrowserHistoryPage.class.getName();
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ mCurrentFragment = id;
+
+ FragmentManager fm = getFragmentManager();
+ FragmentTransaction transaction = fm.openTransaction();
+ Fragment frag = Fragment.instantiate(this, fragmentClassName, getIntent().getExtras());
+ transaction.replace(R.id.fragment, frag);
+ transaction.commit();
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ if (id == mCurrentFragment) return;
+ loadFragment((int) id);
+ }
+
/**
* 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() {
+ @Override
+ public void onRemoveParentChildRelationShips() {
mExtraData = BrowserSettings.PREF_CLEAR_HISTORY;
}
@@ -174,7 +231,7 @@
* @param resultCode Uses same codes as Activity.setResult
* @param data Intent returned to onActivityResult.
*/
- /* package */ void setResultFromChild(int resultCode, Intent data) {
+ private void setResultFromChild(int resultCode, Intent data) {
mResultCode = resultCode;
mResultData = data;
}
@@ -186,7 +243,26 @@
if (mResultData == null) mResultData = new Intent();
mResultData.putExtra(Intent.EXTRA_TEXT, mExtraData);
}
+ if (mNewTabMode) {
+ if (mResultData == null) mResultData = new Intent();
+ mResultData.putExtra(NEWTAB_MODE, true);
+ }
setResult(mResultCode, mResultData);
super.finish();
}
+
+ /**
+ * Report back to the calling activity to load a site.
+ * @param url Site to load.
+ * @param newWindow True if the URL should be loaded in a new window
+ */
+ @Override
+ public void onUrlSelected(String url, boolean newWindow) {
+ Intent intent = new Intent().setAction(url);
+ if (newWindow) {
+ intent.putExtra(EXTRA_OPEN_NEW_WINDOW, true);
+ }
+ setResultFromChild(RESULT_OK, intent);
+ finish();
+ }
}
diff --git a/src/com/android/browser/DateSortedExpandableListAdapter.java b/src/com/android/browser/DateSortedExpandableListAdapter.java
index 1d04493..a48efe6 100644
--- a/src/com/android/browser/DateSortedExpandableListAdapter.java
+++ b/src/com/android/browser/DateSortedExpandableListAdapter.java
@@ -17,65 +17,55 @@
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.BaseExpandableListAdapter;
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 {
+public class DateSortedExpandableListAdapter extends BaseExpandableListAdapter {
// 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());
+ boolean mDataValid;
+
+ DataSetObserver mDataSetObserver = new DataSetObserver() {
+ @Override
+ public void onChanged() {
+ mDataValid = true;
+ notifyDataSetChanged();
}
@Override
- public boolean deliverSelfNotifications() {
- return true;
+ public void onInvalidated() {
+ mDataValid = false;
+ notifyDataSetInvalidated();
}
-
- @Override
- public void onChange(boolean selfChange) {
- refreshData();
- }
- }
-
- public DateSortedExpandableListAdapter(Context context, Cursor cursor,
- int dateIndex) {
+ };
+
+ public DateSortedExpandableListAdapter(Context context, 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();
+ mDataValid = false;
+ mIdIndex = -1;
}
/**
@@ -122,6 +112,7 @@
* @return corresponding byte array from the Cursor.
*/
/* package */ byte[] getBlob(int cursorIndex) {
+ if (!mDataValid) return null;
return mCursor.getBlob(cursorIndex);
}
@@ -138,6 +129,7 @@
* @return corresponding integer from the Cursor.
*/
/* package */ int getInt(int cursorIndex) {
+ if (!mDataValid) return 0;
return mCursor.getInt(cursorIndex);
}
@@ -146,6 +138,7 @@
* already been moved to the correct position.
*/
/* package */ long getLong(int cursorIndex) {
+ if (!mDataValid) return 0;
return mCursor.getLong(cursorIndex);
}
@@ -158,6 +151,7 @@
* @return corresponding String from the Cursor.
*/
/* package */ String getString(int cursorIndex) {
+ if (!mDataValid) return null;
return mCursor.getString(cursorIndex);
}
@@ -166,6 +160,7 @@
* @param childId ID of the child view in question.
* @return int Group position of the containing group.
/* package */ int groupFromChildId(long childId) {
+ if (!mDataValid) return -1;
int group = -1;
for (mCursor.moveToFirst(); !mCursor.isAfterLast();
mCursor.moveToNext()) {
@@ -173,11 +168,15 @@
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;
+ if (DateSorter.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++;
+ if (mItemMap[i] != 0) {
+ group++;
+ }
}
break;
}
@@ -193,6 +192,7 @@
* @return The corresponding bin that holds that group.
*/
private int groupPositionToBin(int groupPosition) {
+ if (!mDataValid) return -1;
if (groupPosition < 0 || groupPosition >= DateSorter.DAY_COUNT) {
throw new AssertionError("group position out of range");
}
@@ -241,7 +241,9 @@
*/
/* package */ boolean moveCursorToChildPosition(int groupPosition,
int childPosition) {
- if (mCursor.isClosed()) return false;
+ if (!mDataValid || mCursor.isClosed()) {
+ return false;
+ }
groupPosition = groupPositionToBin(groupPosition);
int index = childPosition;
for (int i = 0; i < groupPosition; i++) {
@@ -250,19 +252,34 @@
return mCursor.moveToPosition(index);
}
- /* package */ void refreshData() {
- if (mCursor.isClosed()) {
+ public void changeCursor(Cursor cursor) {
+ if (cursor == mCursor) {
return;
}
- mCursor.requery();
- buildMap();
- for (DataSetObserver o : mObservers) {
- o.onChanged();
+ if (mCursor != null) {
+ mCursor.unregisterDataSetObserver(mDataSetObserver);
+ mCursor.close();
+ }
+ mCursor = cursor;
+ if (cursor != null) {
+ cursor.registerDataSetObserver(mDataSetObserver);
+ mIdIndex = cursor.getColumnIndexOrThrow("_id");
+ mDataValid = true;
+ buildMap();
+ // notify the observers about the new cursor
+ notifyDataSetChanged();
+ } else {
+ mIdIndex = -1;
+ mDataValid = false;
+ // notify the observers about the lack of a data set
+ notifyDataSetInvalidated();
}
}
+ @Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
+ if (!mDataValid) throw new IllegalStateException("Data is not valid");
TextView item;
if (null == convertView || !(convertView instanceof TextView)) {
LayoutInflater factory = LayoutInflater.from(mContext);
@@ -275,73 +292,87 @@
return item;
}
+ @Override
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
+ if (!mDataValid) throw new IllegalStateException("Data is not valid");
return null;
}
+ @Override
public boolean areAllItemsEnabled() {
return true;
}
+ @Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
+ @Override
public int getGroupCount() {
+ if (!mDataValid) return 0;
return mNumberOfBins;
}
+ @Override
public int getChildrenCount(int groupPosition) {
+ if (!mDataValid) return 0;
return mItemMap[groupPositionToBin(groupPosition)];
}
+ @Override
public Object getGroup(int groupPosition) {
return null;
}
+ @Override
public Object getChild(int groupPosition, int childPosition) {
return null;
}
+ @Override
public long getGroupId(int groupPosition) {
+ if (!mDataValid) return 0;
return groupPosition;
}
+ @Override
public long getChildId(int groupPosition, int childPosition) {
+ if (!mDataValid) return 0;
if (moveCursorToChildPosition(groupPosition, childPosition)) {
return getLong(mIdIndex);
}
return 0;
}
+ @Override
public boolean hasStableIds() {
return true;
}
- public void registerDataSetObserver(DataSetObserver observer) {
- mObservers.add(observer);
- }
-
- public void unregisterDataSetObserver(DataSetObserver observer) {
- mObservers.remove(observer);
- }
-
+ @Override
public void onGroupExpanded(int groupPosition) {
}
+ @Override
public void onGroupCollapsed(int groupPosition) {
}
+ @Override
public long getCombinedChildId(long groupId, long childId) {
+ if (!mDataValid) return 0;
return childId;
}
+ @Override
public long getCombinedGroupId(long groupId) {
+ if (!mDataValid) return 0;
return groupId;
}
+ @Override
public boolean isEmpty() {
- return mCursor.isClosed() || mCursor.getCount() == 0;
+ return !mDataValid || mCursor == null || mCursor.isClosed() || mCursor.getCount() == 0;
}
}
diff --git a/src/com/android/browser/DownloadTouchIcon.java b/src/com/android/browser/DownloadTouchIcon.java
index 14404ff..7bb93dc 100644
--- a/src/com/android/browser/DownloadTouchIcon.java
+++ b/src/com/android/browser/DownloadTouchIcon.java
@@ -16,19 +16,6 @@
package com.android.browser;
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.net.http.AndroidHttpClient;
-import android.net.Proxy;
-import android.os.AsyncTask;
-import android.provider.Browser;
-import android.webkit.WebView;
-
-
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
@@ -36,6 +23,22 @@
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.conn.params.ConnRouteParams;
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.Proxy;
+import android.net.http.AndroidHttpClient;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Message;
+import android.provider.BrowserContract;
+import android.provider.BrowserContract.Images;
+import android.webkit.WebView;
+
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -45,10 +48,17 @@
private Cursor mCursor;
private final String mOriginalUrl;
private final String mUrl;
- private final String mUserAgent;
- private final BrowserActivity mActivity;
+ private final String mUserAgent; // Sites may serve a different icon to different UAs
+ private Message mMessage;
+
+ private final Activity mActivity;
/* package */ Tab mTab;
+ /**
+ * Use this ctor to store the touch icon in the bookmarks database for
+ * the originalUrl so we take account of redirects. Used when the user
+ * bookmarks a page from outside the bookmarks activity.
+ */
public DownloadTouchIcon(Tab tab, BrowserActivity activity, ContentResolver cr, WebView view) {
mTab = tab;
mActivity = activity;
@@ -59,24 +69,49 @@
mUserAgent = view.getSettings().getUserAgentString();
}
- public DownloadTouchIcon(ContentResolver cr, String url) {
+ /**
+ * Use this ctor to download the touch icon and update the bookmarks database
+ * entry for the given url. Used when the user creates a bookmark from
+ * within the bookmarks activity and there haven't been any redirects.
+ * TODO: Would be nice to set the user agent here so that there is no
+ * potential for the three different ctors here to return different icons.
+ */
+ public DownloadTouchIcon(AddBookmarkPage activity, ContentResolver cr, String url) {
mTab = null;
- mActivity = null;
+ mActivity = activity;
mContentResolver = cr;
mOriginalUrl = null;
mUrl = url;
mUserAgent = null;
}
+ /**
+ * Use this ctor to not store the touch icon in a database, rather add it to
+ * the passed Message's data bundle with the key "touchIcon" and then send
+ * the message.
+ */
+ public DownloadTouchIcon(BrowserActivity activity, Message msg, String userAgent) {
+ mMessage = msg;
+ mActivity = activity;
+ mContentResolver = null;
+ mOriginalUrl = null;
+ mUrl = null;
+ mUserAgent = userAgent;
+ }
+
@Override
public Void doInBackground(String... values) {
- mCursor = BrowserBookmarksAdapter.queryBookmarksForUrl(mContentResolver,
- mOriginalUrl, mUrl, true);
- if (mCursor != null && mCursor.getCount() > 0) {
- String url = values[0];
+ if (mContentResolver != null) {
+ mCursor = Bookmarks.queryCombinedForUrl(mContentResolver,
+ mOriginalUrl, mUrl);
+ }
- AndroidHttpClient client = AndroidHttpClient.newInstance(
- mUserAgent);
+ boolean inDatabase = mCursor != null && mCursor.getCount() > 0;
+
+ String url = values[0];
+
+ if (inDatabase || mMessage != null) {
+ AndroidHttpClient client = AndroidHttpClient.newInstance(mUserAgent);
HttpHost httpHost = Proxy.getPreferredHttpHost(mActivity, url);
if (httpHost != null) {
ConnRouteParams.setDefaultProxy(client.getParams(), httpHost);
@@ -89,7 +124,6 @@
try {
HttpResponse response = client.execute(request);
-
if (response.getStatusLine().getStatusCode() == 200) {
HttpEntity entity = response.getEntity();
if (entity != null) {
@@ -97,7 +131,12 @@
if (content != null) {
Bitmap icon = BitmapFactory.decodeStream(
content, null, null);
- storeIcon(icon);
+ if (inDatabase) {
+ storeIcon(icon);
+ } else if (mMessage != null) {
+ Bundle b = mMessage.getData();
+ b.putParcelable("touchIcon", icon);
+ }
}
}
}
@@ -109,9 +148,15 @@
client.close();
}
}
+
if (mCursor != null) {
mCursor.close();
}
+
+ if (mMessage != null) {
+ mMessage.sendToTarget();
+ }
+
return null;
}
@@ -133,17 +178,16 @@
return;
}
- final ByteArrayOutputStream os = new ByteArrayOutputStream();
- icon.compress(Bitmap.CompressFormat.PNG, 100, os);
- ContentValues values = new ContentValues();
- values.put(Browser.BookmarkColumns.TOUCH_ICON,
- os.toByteArray());
-
if (mCursor.moveToFirst()) {
+ final ByteArrayOutputStream os = new ByteArrayOutputStream();
+ icon.compress(Bitmap.CompressFormat.PNG, 100, os);
+
+ ContentValues values = new ContentValues();
+ values.put(Images.TOUCH_ICON, os.toByteArray());
+ values.put(Images.URL, mCursor.getString(0));
+
do {
- mContentResolver.update(ContentUris.withAppendedId(
- Browser.BOOKMARKS_URI, mCursor.getInt(0)),
- values, null, null);
+ mContentResolver.update(Images.CONTENT_URI, values, null, null);
} while (mCursor.moveToNext());
}
}
diff --git a/src/com/android/browser/FindDialog.java b/src/com/android/browser/FindDialog.java
deleted file mode 100644
index 726138e..0000000
--- a/src/com/android/browser/FindDialog.java
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.browser;
-
-import android.content.Context;
-import android.text.Editable;
-import android.text.Selection;
-import android.text.Spannable;
-import android.text.TextWatcher;
-import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.animation.AnimationUtils;
-import android.view.inputmethod.InputMethodManager;
-import android.webkit.WebView;
-import android.widget.EditText;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-/* package */ class FindDialog extends WebDialog implements TextWatcher {
- private TextView mMatches;
-
- // Views with which the user can interact.
- private EditText mEditText;
- private View mNextButton;
- private View mPrevButton;
- private View mMatchesView;
-
- // When the dialog is opened up with old text, enter needs to be pressed
- // (or the text needs to be changed) before WebView.findAll can be called.
- // Once it has been called, enter should move to the next match.
- private boolean mMatchesFound;
- private int mNumberOfMatches;
-
- private View.OnClickListener mFindListener = new View.OnClickListener() {
- public void onClick(View v) {
- findNext();
- }
- };
-
- private View.OnClickListener mFindPreviousListener =
- new View.OnClickListener() {
- public void onClick(View v) {
- if (mWebView == null) {
- throw new AssertionError("No WebView for FindDialog::onClick");
- }
- mWebView.findNext(false);
- updateMatchesString();
- hideSoftInput();
- }
- };
-
- private void disableButtons() {
- mPrevButton.setEnabled(false);
- mNextButton.setEnabled(false);
- mPrevButton.setFocusable(false);
- mNextButton.setFocusable(false);
- }
-
- /* package */ FindDialog(BrowserActivity context) {
- super(context);
-
- LayoutInflater factory = LayoutInflater.from(context);
- factory.inflate(R.layout.browser_find, this);
-
- addCancel();
- mEditText = (EditText) findViewById(R.id.edit);
-
- View button = findViewById(R.id.next);
- button.setOnClickListener(mFindListener);
- mNextButton = button;
-
- button = findViewById(R.id.previous);
- button.setOnClickListener(mFindPreviousListener);
- mPrevButton = button;
-
- mMatches = (TextView) findViewById(R.id.matches);
- mMatchesView = findViewById(R.id.matches_view);
- disableButtons();
-
- }
-
- /**
- * Called by BrowserActivity.closeDialog. Start the animation to hide
- * the dialog, inform the WebView that the dialog is being dismissed,
- * and hide the soft keyboard.
- */
- public void dismiss() {
- super.dismiss();
- mWebView.notifyFindDialogDismissed();
- hideSoftInput();
- }
-
- @Override
- public boolean dispatchKeyEventPreIme(KeyEvent event) {
- if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
- KeyEvent.DispatcherState state = getKeyDispatcherState();
- if (state != null) {
- int action = event.getAction();
- if (KeyEvent.ACTION_DOWN == action
- && event.getRepeatCount() == 0) {
- state.startTracking(event, this);
- return true;
- } else if (KeyEvent.ACTION_UP == action
- && !event.isCanceled() && state.isTracking(event)) {
- mBrowserActivity.closeDialogs();
- return true;
- }
- }
- }
- return super.dispatchKeyEventPreIme(event);
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- int keyCode = event.getKeyCode();
- if (event.getAction() == KeyEvent.ACTION_UP) {
- if (keyCode == KeyEvent.KEYCODE_ENTER
- && mEditText.hasFocus()) {
- if (mMatchesFound) {
- findNext();
- } else {
- findAll();
- // Set the selection to the end.
- Spannable span = (Spannable) mEditText.getText();
- Selection.setSelection(span, span.length());
- }
- return true;
- }
- }
- return super.dispatchKeyEvent(event);
- }
-
- private void findNext() {
- if (mWebView == null) {
- throw new AssertionError("No WebView for FindDialog::findNext");
- }
- mWebView.findNext(true);
- updateMatchesString();
- hideSoftInput();
- }
-
- public void show() {
- super.show();
- // In case the matches view is showing from a previous search
- mMatchesView.setVisibility(View.INVISIBLE);
- mMatchesFound = false;
- // This text is only here to ensure that mMatches has a height.
- mMatches.setText("0");
- mEditText.requestFocus();
- Spannable span = (Spannable) mEditText.getText();
- int length = span.length();
- Selection.setSelection(span, 0, length);
- span.setSpan(this, 0, length, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
- disableButtons();
- InputMethodManager imm = (InputMethodManager)
- mBrowserActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.showSoftInput(mEditText, 0);
- }
-
- // TextWatcher methods
- public void beforeTextChanged(CharSequence s,
- int start,
- int count,
- int after) {
- }
-
- public void onTextChanged(CharSequence s,
- int start,
- int before,
- int count) {
- findAll();
- }
-
- private void findAll() {
- if (mWebView == null) {
- throw new AssertionError(
- "No WebView for FindDialog::findAll");
- }
- CharSequence find = mEditText.getText();
- if (0 == find.length()) {
- disableButtons();
- mWebView.clearMatches();
- mMatchesView.setVisibility(View.INVISIBLE);
- } else {
- mMatchesView.setVisibility(View.VISIBLE);
- int found = mWebView.findAll(find.toString());
- mMatchesFound = true;
- setMatchesFound(found);
- if (found < 2) {
- disableButtons();
- if (found == 0) {
- // Cannot use getQuantityString, which ignores the "zero"
- // quantity.
- // FIXME: is this fix is beyond the scope
- // of adding touch selection to gingerbread?
- // mMatches.setText(mBrowserActivity.getResources().getString(
- // R.string.no_matches));
- }
- } else {
- mPrevButton.setFocusable(true);
- mNextButton.setFocusable(true);
- mPrevButton.setEnabled(true);
- mNextButton.setEnabled(true);
- }
- }
- }
-
- private void setMatchesFound(int found) {
- mNumberOfMatches = found;
- updateMatchesString();
- }
-
- public void setText(String text) {
- mEditText.setText(text);
- findAll();
- }
-
- private void updateMatchesString() {
- // Note: updateMatchesString is only called by methods that have already
- // checked mWebView for null.
- String template = mBrowserActivity.getResources().
- getQuantityString(R.plurals.matches_found, mNumberOfMatches,
- mWebView.findIndex() + 1, mNumberOfMatches);
-
- mMatches.setText(template);
- }
-
- public void afterTextChanged(Editable s) {
- }
-}
diff --git a/src/com/android/browser/HistoryItem.java b/src/com/android/browser/HistoryItem.java
index 72e1b19..a03c29f 100644
--- a/src/com/android/browser/HistoryItem.java
+++ b/src/com/android/browser/HistoryItem.java
@@ -18,12 +18,8 @@
package com.android.browser;
import android.content.Context;
-import android.graphics.Bitmap;
-import android.provider.Browser;
import android.view.View;
import android.widget.CompoundButton;
-import android.widget.ImageView;
-import android.widget.TextView;
/**
* Layout representing a history item in the classic history viewer.
@@ -45,8 +41,9 @@
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if (isChecked) {
- Bookmarks.addBookmark(mContext,
- mContext.getContentResolver(), mUrl, getName(), null, true);
+ // FIXME: For now, add at the root level. Should we
+ // open AddBookmark from here?
+ Bookmarks.addBookmark(mContext, true, mUrl, getName(), null, true, 0);
LogTag.logBookmarkAdded(mUrl, "history");
} else {
Bookmarks.removeFromBookmarks(mContext,
diff --git a/src/com/android/browser/PageProgressView.java b/src/com/android/browser/PageProgressView.java
new file mode 100644
index 0000000..f512cef
--- /dev/null
+++ b/src/com/android/browser/PageProgressView.java
@@ -0,0 +1,117 @@
+
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.browser;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+/**
+ *
+ */
+public class PageProgressView extends ImageView {
+
+ public static final int MAX_PROGRESS = 10000;
+ private static final int MSG_UPDATE = 42;
+ private static final int STEPS = 10;
+ private static final int DELAY = 40;
+
+ private int mCurrentProgress;
+ private int mTargetProgress;
+ private int mIncrement;
+ private Rect mBounds;
+ private Handler mHandler;
+
+ /**
+ * @param context
+ * @param attrs
+ * @param defStyle
+ */
+ public PageProgressView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init(context);
+ }
+
+ /**
+ * @param context
+ * @param attrs
+ */
+ public PageProgressView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context);
+ }
+
+ /**
+ * @param context
+ */
+ public PageProgressView(Context context) {
+ super(context);
+ init(context);
+ }
+
+ private void init(Context ctx) {
+ mBounds = new Rect(0,0,0,0);
+ mCurrentProgress = 0;
+ mTargetProgress = 0;
+ mHandler = new Handler() {
+
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what == MSG_UPDATE) {
+ mCurrentProgress = Math.min(mTargetProgress,
+ mCurrentProgress + mIncrement);
+ mBounds.right = getWidth() * mCurrentProgress / MAX_PROGRESS;
+ invalidate();
+ if (mCurrentProgress < mTargetProgress) {
+ sendMessageDelayed(mHandler.obtainMessage(MSG_UPDATE), DELAY);
+ }
+ }
+ }
+
+ };
+ }
+
+ @Override
+ public void onLayout(boolean f, int l, int t, int r, int b) {
+ mBounds.left = 0;
+ mBounds.right = (r - l) * mCurrentProgress / MAX_PROGRESS;
+ mBounds.top = 0;
+ mBounds.bottom = b-t;
+ }
+
+ void setProgress(int progress) {
+ mCurrentProgress = mTargetProgress;
+ mTargetProgress = progress;
+ mIncrement = (mTargetProgress - mCurrentProgress) / STEPS;
+ mHandler.removeMessages(MSG_UPDATE);
+ mHandler.sendEmptyMessage(MSG_UPDATE);
+ }
+
+ @Override
+ public void onDraw(Canvas canvas) {
+// super.onDraw(canvas);
+ Drawable d = getDrawable();
+ d.setBounds(mBounds);
+ d.draw(canvas);
+ }
+
+}
diff --git a/src/com/android/browser/SaveToHomescreenDialog.java b/src/com/android/browser/SaveToHomescreenDialog.java
new file mode 100644
index 0000000..15f0aea
--- /dev/null
+++ b/src/com/android/browser/SaveToHomescreenDialog.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.app.Activity;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.net.ParseException;
+import android.net.Uri;
+import android.net.WebAddress;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.provider.Browser;
+import android.util.Log;
+import android.view.View;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Date;
+
+public class SaveToHomescreenDialog extends Activity {
+
+ private EditText mTitle;
+ private String mUrl;
+ private Bitmap mFavicon;
+ private Bitmap mTouchIcon;
+
+ private View.OnClickListener mOk = new View.OnClickListener() {
+ public void onClick(View v) {
+ if (save()) {
+ finish();
+ }
+ }
+ };
+
+ private View.OnClickListener mCancel = new View.OnClickListener() {
+ public void onClick(View v) {
+ finish();
+ }
+ };
+
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ requestWindowFeature(Window.FEATURE_LEFT_ICON);
+ setContentView(R.layout.browser_add_bookmark_const_url);
+ setTitle(R.string.create_shortcut_bookmark);
+ getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
+ R.drawable.ic_list_bookmark);
+
+ String title = null;
+ String url = null;
+ Bundle map = getIntent().getExtras();
+ if (map != null) {
+ title = map.getString("title");
+ }
+
+ mUrl = map.getString("url");
+ mFavicon = (Bitmap)map.getParcelable("favicon");
+ mTouchIcon = (Bitmap)map.getParcelable("touchIcon");
+
+ Bitmap icon = BookmarkUtils.createIcon(this, mTouchIcon, mFavicon,
+ BookmarkUtils.BookmarkIconType.ICON_HOME_SHORTCUT);
+ getWindow().setFeatureDrawable(Window.FEATURE_LEFT_ICON, new BitmapDrawable(icon));
+
+ mTitle = (EditText) findViewById(R.id.title);
+ mTitle.setText(title);
+
+ Button okButton = (Button) findViewById(R.id.OK);
+ okButton.setOnClickListener(mOk);
+
+ Button cancelButton = (Button) findViewById(R.id.cancel);
+ cancelButton.setOnClickListener(mCancel);
+
+ if (!getWindow().getDecorView().isInTouchMode()) {
+ okButton.requestFocus();
+ }
+ }
+
+ /**
+ * Parse the data entered in the dialog and send an intent to create an
+ * icon on the homescreen.
+ */
+ private boolean save() {
+ String title = mTitle.getText().toString().trim();
+ String unfilteredUrl = BrowserActivity.fixUrl(mUrl);
+ if (title.length() == 0) {
+ mTitle.setError(getResources().getText(R.string.bookmark_needs_title));
+ return false;
+ }
+
+ String url = unfilteredUrl.trim();
+
+ sendBroadcast(BookmarkUtils.createAddToHomeIntent(this, url, title,
+ mTouchIcon, mFavicon));
+ setResult(RESULT_OK);
+ return true;
+ }
+}
diff --git a/src/com/android/browser/ScrollWebView.java b/src/com/android/browser/ScrollWebView.java
new file mode 100644
index 0000000..97bd2c7
--- /dev/null
+++ b/src/com/android/browser/ScrollWebView.java
@@ -0,0 +1,125 @@
+/*
+ * 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.util.AttributeSet;
+import android.view.View;
+import android.webkit.WebView;
+
+import java.util.Map;
+
+/**
+ * Manage WebView scroll events
+ */
+public class ScrollWebView extends WebView {
+
+ private ScrollListener mScrollListener;
+ private boolean mIsCancelled;
+ private Runnable mScrollRunnable;
+
+ /**
+ * @param context
+ * @param attrs
+ * @param defStyle
+ * @param javascriptInterfaces
+ */
+ public ScrollWebView(Context context, AttributeSet attrs, int defStyle,
+ Map<String, Object> javascriptInterfaces, boolean privateBrowsing) {
+ super(context, attrs, defStyle, javascriptInterfaces, privateBrowsing);
+ }
+
+ /**
+ * @param context
+ * @param attrs
+ * @param defStyle
+ */
+ public ScrollWebView(Context context, AttributeSet attrs, int defStyle,
+ boolean privateBrowsing) {
+ super(context, attrs, defStyle, privateBrowsing);
+ }
+
+ /**
+ * @param context
+ * @param attrs
+ */
+ public ScrollWebView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ /**
+ * @param context
+ */
+ public ScrollWebView(Context context) {
+ super(context);
+ }
+
+ void hideEmbeddedTitleBar() {
+ scrollBy(0, getVisibleTitleHeight());
+ }
+
+ @Override
+ public void setEmbeddedTitleBar(final View title) {
+ super.setEmbeddedTitleBar(title);
+ if (title != null && mScrollListener != null) {
+ // allow the scroll listener to initialize its state
+ post(new Runnable() {
+ @Override
+ public void run() {
+ mScrollListener.onScroll((title.getHeight() == 0 ||
+ getVisibleTitleHeight() > 0));
+ }
+ });
+ }
+ }
+
+ @Override
+ public void stopScroll() {
+ mIsCancelled = true;
+ super.stopScroll();
+ }
+
+ @Override
+ protected void onScrollChanged(int l, final int t, int ol, int ot) {
+ super.onScrollChanged(l, t, ol, ot);
+ if (!mIsCancelled) {
+ post(mScrollRunnable);
+ } else {
+ mIsCancelled = false;
+ }
+ }
+
+ void setScrollListener(ScrollListener l) {
+ mScrollListener = l;
+ if (mScrollListener != null) {
+ mScrollRunnable = new Runnable() {
+ public void run() {
+ if (!mIsCancelled) {
+ mScrollListener.onScroll(getVisibleTitleHeight() > 0);
+ }
+ }
+ };
+ }
+ }
+
+ // callback for scroll events
+
+ interface ScrollListener {
+ public void onScroll(boolean titleVisible);
+ }
+
+}
diff --git a/src/com/android/browser/SelectDialog.java b/src/com/android/browser/SelectDialog.java
deleted file mode 100644
index 461127a..0000000
--- a/src/com/android/browser/SelectDialog.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.browser;
-
-import android.provider.Browser;
-import android.view.LayoutInflater;
-import android.view.View;
-
-/* package */ class SelectDialog extends WebDialog {
- private View mCopyButton;
- private View mSelectAllButton;
- private View mShareButton;
- private View mFindButton;
-
- SelectDialog(BrowserActivity context) {
- super(context);
- LayoutInflater factory = LayoutInflater.from(context);
- factory.inflate(R.layout.browser_select, this);
- addCancel();
-
- mCopyButton = findViewById(R.id.copy);
- mCopyButton.setOnClickListener(mCopyListener);
- mSelectAllButton = findViewById(R.id.select_all);
- mSelectAllButton.setOnClickListener(mSelectAllListener);
- mShareButton = findViewById(R.id.share);
- mShareButton.setOnClickListener(mShareListener);
- mFindButton = findViewById(R.id.find);
- mFindButton.setOnClickListener(mFindListener);
- }
-
- private View.OnClickListener mCopyListener = new View.OnClickListener() {
- public void onClick(View v) {
- mWebView.copySelection();
- mBrowserActivity.closeDialogs();
- }
- };
-
- private View.OnClickListener mSelectAllListener = new View.OnClickListener() {
- public void onClick(View v) {
- mWebView.selectAll();
- }
- };
-
- private View.OnClickListener mShareListener = new View.OnClickListener() {
- public void onClick(View v) {
- String selection = mWebView.getSelection();
- Browser.sendString(mBrowserActivity, selection);
- mBrowserActivity.closeDialogs();
- }
- };
-
- private View.OnClickListener mFindListener = new View.OnClickListener() {
- public void onClick(View v) {
- String selection = mWebView.getSelection();
- mBrowserActivity.closeDialogs();
- mBrowserActivity.showFindDialog();
- mBrowserActivity.setFindDialogText(selection);
- }
- };
-
- /**
- * Called by BrowserActivity.closeDialog. Start the animation to hide
- * the dialog, and inform the WebView that the dialog is being dismissed.
- */
- @Override
- public void dismiss() {
- super.dismiss();
- mWebView.notifySelectDialogDismissed();
- }
-
-}
diff --git a/src/com/android/browser/ShortcutActivity.java b/src/com/android/browser/ShortcutActivity.java
new file mode 100644
index 0000000..7994d0a
--- /dev/null
+++ b/src/com/android/browser/ShortcutActivity.java
@@ -0,0 +1,69 @@
+/*
+ * 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.Activity;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.content.Intent;
+import android.os.Bundle;
+
+public class ShortcutActivity extends Activity
+ implements BookmarksHistoryCallbacks {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
+ FragmentManager fm = getFragmentManager();
+ FragmentTransaction transaction = fm.openTransaction();
+ Bundle extras = new Bundle();
+ extras.putBoolean(BrowserBookmarksPage.EXTRA_SHORTCUT, true);
+ extras.putBoolean(BrowserBookmarksPage.EXTRA_DISABLE_WINDOW, true);
+ Fragment frag = Fragment.instantiate(this, BrowserBookmarksPage.class.getName(), extras);
+ transaction.add(android.R.id.content, frag);
+ transaction.commit();
+ }
+
+ /**
+ * not used for shortcuts
+ */
+ @Override
+ public void onRemoveParentChildRelationShips() {}
+
+ /**
+ * handle fragment startActivity
+ */
+ @Override
+ public void startActivityFromFragment(Fragment f, Intent intent, int requestCode) {
+ setResult(RESULT_OK, intent);
+ finish();
+ }
+
+ @Override
+ public void finish() {
+ super.finish();
+ }
+
+ /**
+ * not used for shortcuts
+ */
+ @Override
+ public void onUrlSelected(String url, boolean newWindow) {}
+
+}
diff --git a/src/com/android/browser/SuggestionsAdapter.java b/src/com/android/browser/SuggestionsAdapter.java
new file mode 100644
index 0000000..7cfd78e
--- /dev/null
+++ b/src/com/android/browser/SuggestionsAdapter.java
@@ -0,0 +1,591 @@
+/*
+ * 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 com.android.browser.search.SearchEngine;
+
+import android.app.SearchManager;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.BrowserContract;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.Filter;
+import android.widget.Filterable;
+import android.widget.ImageView;
+import android.widget.LinearLayout.LayoutParams;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * adapter to wrap multiple cursors for url/search completions
+ */
+public class SuggestionsAdapter extends BaseAdapter implements Filterable, OnClickListener {
+
+ static final int TYPE_SEARCH = 0;
+ static final int TYPE_SUGGEST = 1;
+ static final int TYPE_BOOKMARK = 2;
+ static final int TYPE_SUGGEST_URL = 3;
+ static final int TYPE_HISTORY = 4;
+
+ private static final String[] COMBINED_PROJECTION =
+ {BrowserContract.Combined._ID, BrowserContract.Combined.TITLE,
+ BrowserContract.Combined.URL, BrowserContract.Combined.IS_BOOKMARK};
+
+ private static final String[] SEARCHES_PROJECTION = {BrowserContract.Searches.SEARCH};
+
+ private static final String COMBINED_SELECTION =
+ "(url LIKE ? OR url LIKE ? OR url LIKE ? OR url LIKE ? OR title LIKE ?)";
+
+ // Regular expression which matches http://, followed by some stuff, followed by
+ // optionally a trailing slash, all matched as separate groups.
+ private static final Pattern STRIP_URL_PATTERN = Pattern.compile("^(http://)(.*?)(/$)?");
+
+ Context mContext;
+ Filter mFilter;
+ SuggestionResults mResults;
+ List<CursorSource> mSources;
+ boolean mLandscapeMode;
+ CompletionListener mListener;
+ int mLinesPortrait;
+ int mLinesLandscape;
+
+ interface CompletionListener {
+
+ public void onSearch(String txt);
+
+ public void onSelect(String txt);
+
+ }
+
+ public SuggestionsAdapter(Context ctx, CompletionListener listener) {
+ mContext = ctx;
+ mListener = listener;
+ mLinesPortrait = mContext.getResources().
+ getInteger(R.integer.max_suggest_lines_portrait);
+ mLinesLandscape = mContext.getResources().
+ getInteger(R.integer.max_suggest_lines_landscape);
+ mFilter = new SuggestFilter();
+ addSource(new SuggestCursor());
+ addSource(new SearchesCursor());
+ addSource(new CombinedCursor());
+ }
+
+ public void setLandscapeMode(boolean mode) {
+ mLandscapeMode = mode;
+ }
+
+ public int getLeftCount() {
+ return mResults.getLeftCount();
+ }
+
+ public int getRightCount() {
+ return mResults.getRightCount();
+ }
+
+ public void addSource(CursorSource c) {
+ if (mSources == null) {
+ mSources = new ArrayList<CursorSource>(5);
+ }
+ mSources.add(c);
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (R.id.icon2 == v.getId()) {
+ // replace input field text with suggestion text
+ SuggestItem item = (SuggestItem) ((View) v.getParent()).getTag();
+ mListener.onSearch(item.title);
+ } else {
+ SuggestItem item = (SuggestItem) v.getTag();
+ mListener.onSelect((TextUtils.isEmpty(item.url)? item.title : item.url));
+ }
+ }
+
+ @Override
+ public Filter getFilter() {
+ return mFilter;
+ }
+
+ @Override
+ public int getCount() {
+ return (mResults == null) ? 0 : mResults.getLineCount();
+ }
+
+ @Override
+ public SuggestItem getItem(int position) {
+ if (mResults == null) {
+ return null;
+ }
+ if (mLandscapeMode) {
+ if (position >= mResults.getLineCount()) {
+ // right column
+ position = position - mResults.getLineCount();
+ // index in column
+ if (position >= mResults.getRightCount()) {
+ return null;
+ }
+ return mResults.items.get(position + mResults.getLeftCount());
+ } else {
+ // left column
+ if (position >= mResults.getLeftCount()) {
+ return null;
+ }
+ return mResults.items.get(position);
+ }
+ } else {
+ return mResults.items.get(position);
+ }
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return 0;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ final LayoutInflater inflater = LayoutInflater.from(mContext);
+ if (mLandscapeMode) {
+ View view = inflater.inflate(R.layout.suggestion_two_column, parent, false);
+ SuggestItem item = getItem(position);
+ View iv = view.findViewById(R.id.suggest1);
+ LayoutParams lp = new LayoutParams(iv.getLayoutParams());
+ lp.weight = 0.5f;
+ iv.setLayoutParams(lp);
+ if (item != null) {
+ bindView(iv, item);
+ } else {
+ iv.setVisibility((mResults.getLeftCount() == 0) ? View.GONE :
+ View.INVISIBLE);
+ }
+ item = getItem(position + mResults.getLineCount());
+ iv = view.findViewById(R.id.suggest2);
+ lp = new LayoutParams(iv.getLayoutParams());
+ lp.weight = 0.5f;
+ iv.setLayoutParams(lp);
+ if (item != null) {
+ bindView(iv, item);
+ } else {
+ iv.setVisibility((mResults.getRightCount() == 0) ? View.GONE :
+ View.INVISIBLE);
+ }
+ return view;
+ } else {
+ View view = inflater.inflate(R.layout.suggestion_item, parent, false);
+ bindView(view, getItem(position));
+ return view;
+ }
+ }
+
+ private void bindView(View view, SuggestItem item) {
+ // store item for click handling
+ view.setTag(item);
+ TextView tv1 = (TextView) view.findViewById(android.R.id.text1);
+ TextView tv2 = (TextView) view.findViewById(android.R.id.text2);
+ ImageView ic1 = (ImageView) view.findViewById(R.id.icon1);
+ View spacer = view.findViewById(R.id.spacer);
+ View ic2 = view.findViewById(R.id.icon2);
+ tv1.setText(item.title);
+ tv2.setText(item.url);
+ int id = -1;
+ switch (item.type) {
+ case TYPE_SUGGEST:
+ case TYPE_SEARCH:
+ id = R.drawable.ic_search_category_suggest;
+ break;
+ case TYPE_BOOKMARK:
+ id = R.drawable.ic_search_category_bookmark;
+ break;
+ case TYPE_HISTORY:
+ id = R.drawable.ic_search_category_history;
+ break;
+ case TYPE_SUGGEST_URL:
+ id = R.drawable.ic_search_category_browser;
+ break;
+ default:
+ id = -1;
+ }
+ if (id != -1) {
+ ic1.setImageDrawable(mContext.getResources().getDrawable(id));
+ }
+ ic2.setVisibility(((TYPE_SUGGEST == item.type) || (TYPE_SEARCH == item.type))
+ ? View.VISIBLE : View.GONE);
+ spacer.setVisibility(((TYPE_SUGGEST == item.type) || (TYPE_SEARCH == item.type))
+ ? View.GONE : View.INVISIBLE);
+ view.setOnClickListener(this);
+ ic2.setOnClickListener(this);
+ }
+
+ class SuggestFilter extends Filter {
+
+ int count;
+ SuggestionResults results;
+
+ @Override
+ public CharSequence convertResultToString(Object item) {
+ if (item == null) {
+ return "";
+ }
+ SuggestItem sitem = (SuggestItem) item;
+ if (sitem.title != null) {
+ return sitem.title;
+ } else {
+ return sitem.url;
+ }
+ }
+
+ @Override
+ protected FilterResults performFiltering(CharSequence constraint) {
+ FilterResults res = new FilterResults();
+ if (TextUtils.isEmpty(constraint)) {
+ res.count = 0;
+ res.values = null;
+ return res;
+ }
+ results = new SuggestionResults();
+ count = 0;
+ if (constraint != null) {
+ for (CursorSource sc : mSources) {
+ sc.runQuery(constraint);
+ }
+ mixResults();
+ }
+ res.count = count;
+ res.values = results;
+ return res;
+ }
+
+ void mixResults() {
+ for (int i = 0; i < mSources.size(); i++) {
+ CursorSource s = mSources.get(i);
+ int n = Math.min(s.getCount(), (mLandscapeMode ? mLinesLandscape
+ : mLinesPortrait));
+ boolean more = true;
+ for (int j = 0; j < n; j++) {
+ results.addResult(s.getItem());
+ more = s.moveToNext();
+ }
+ if (s instanceof SuggestCursor) {
+ int k = n;
+ while (more && (k < mLinesPortrait)) {
+ SuggestItem item = s.getItem();
+ if (item.type == TYPE_SUGGEST_URL) {
+ results.addResult(item);
+ break;
+ }
+ more = s.moveToNext();
+ k++;
+
+ }
+ }
+ }
+
+ }
+
+ @Override
+ protected void publishResults(CharSequence constraint, FilterResults fresults) {
+ mResults = (SuggestionResults) fresults.values;
+ notifyDataSetChanged();
+ }
+
+ }
+
+ /**
+ * sorted list of results of a suggestion query
+ *
+ */
+ class SuggestionResults {
+
+ ArrayList<SuggestItem> items;
+ // count per type
+ int[] counts;
+
+ SuggestionResults() {
+ items = new ArrayList<SuggestItem>(24);
+ // n of types:
+ counts = new int[5];
+ }
+
+ int getTypeCount(int type) {
+ return counts[type];
+ }
+
+ void addResult(SuggestItem item) {
+ int ix = 0;
+ while ((ix < items.size()) && (item.type >= items.get(ix).type))
+ ix++;
+ items.add(ix, item);
+ counts[item.type]++;
+ }
+
+ int getLineCount() {
+ if (mLandscapeMode) {
+ return Math.max(getLeftCount(), getRightCount());
+ } else {
+ return getLeftCount() + getRightCount();
+ }
+ }
+
+ int getLeftCount() {
+ return counts[TYPE_SEARCH] + counts[TYPE_SUGGEST];
+ }
+
+ int getRightCount() {
+ return counts[TYPE_BOOKMARK] + counts[TYPE_HISTORY] + counts[TYPE_SUGGEST_URL];
+ }
+
+ public String toString() {
+ if (items == null) return null;
+ if (items.size() == 0) return "[]";
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < items.size(); i++) {
+ SuggestItem item = items.get(i);
+ sb.append(item.type + ": " + item.title);
+ if (i < items.size() - 1) {
+ sb.append(", ");
+ }
+ }
+ return sb.toString();
+ }
+ }
+
+ /**
+ * data object to hold suggestion values
+ */
+ class SuggestItem {
+ String title;
+ String url;
+ int type;
+
+ public SuggestItem(String text, String u, int t) {
+ title = text;
+ url = u;
+ type = t;
+ }
+ }
+
+ abstract class CursorSource {
+
+ Cursor mCursor;
+
+ boolean moveToNext() {
+ return mCursor.moveToNext();
+ }
+
+ public abstract void runQuery(CharSequence constraint);
+
+ public abstract SuggestItem getItem();
+
+ public int getCount() {
+ return (mCursor != null) ? mCursor.getCount() : 0;
+ }
+
+ public void close() {
+ if (mCursor != null) {
+ mCursor.close();
+ }
+ }
+ }
+
+ /**
+ * combined bookmark & history source
+ */
+ class CombinedCursor extends CursorSource {
+
+ @Override
+ public SuggestItem getItem() {
+ if ((mCursor != null) && (!mCursor.isAfterLast())) {
+ String title = mCursor.getString(1);
+ String url = mCursor.getString(2);
+ boolean isBookmark = (mCursor.getInt(3) == 1);
+ return new SuggestItem(getTitle(title, url), getUrl(title, url),
+ isBookmark ? TYPE_BOOKMARK : TYPE_HISTORY);
+ }
+ return null;
+ }
+
+ @Override
+ public void runQuery(CharSequence constraint) {
+ // constraint != null
+ if (mCursor != null) {
+ mCursor.close();
+ }
+ String like = constraint + "%";
+ String[] args = null;
+ String selection = null;
+ if (like.startsWith("http") || like.startsWith("file")) {
+ args = new String[1];
+ args[0] = like;
+ selection = "url LIKE ?";
+ } else {
+ args = new String[5];
+ args[0] = "http://" + like;
+ args[1] = "http://www." + like;
+ args[2] = "https://" + like;
+ args[3] = "https://www." + like;
+ // To match against titles.
+ args[4] = like;
+ selection = COMBINED_SELECTION;
+ }
+ Uri.Builder ub = BrowserContract.Combined.CONTENT_URI.buildUpon();
+ ub.appendQueryParameter(BrowserContract.PARAM_LIMIT,
+ Integer.toString(mLinesPortrait));
+ mCursor =
+ mContext.getContentResolver().query(ub.build(), COMBINED_PROJECTION,
+ selection,
+ (constraint != null) ? args : null,
+ BrowserContract.Combined.VISITS + " DESC, " +
+ BrowserContract.Combined.DATE_LAST_VISITED + " DESC");
+ if (mCursor != null) {
+ mCursor.moveToFirst();
+ }
+ }
+
+ /**
+ * Provides the title (text line 1) for a browser suggestion, which should be the
+ * webpage title. If the webpage title is empty, returns the stripped url instead.
+ *
+ * @return the title string to use
+ */
+ private String getTitle(String title, String url) {
+ if (TextUtils.isEmpty(title) || TextUtils.getTrimmedLength(title) == 0) {
+ title = stripUrl(url);
+ }
+ return title;
+ }
+
+ /**
+ * Provides the subtitle (text line 2) for a browser suggestion, which should be the
+ * webpage url. If the webpage title is empty, then the url should go in the title
+ * instead, and the subtitle should be empty, so this would return null.
+ *
+ * @return the subtitle string to use, or null if none
+ */
+ private String getUrl(String title, String url) {
+ if (TextUtils.isEmpty(title) || TextUtils.getTrimmedLength(title) == 0) {
+ return null;
+ } else {
+ return stripUrl(url);
+ }
+ }
+
+ /**
+ * Strips the provided url of preceding "http://" and any trailing "/". Does not
+ * strip "https://". If the provided string cannot be stripped, the original string
+ * is returned.
+ *
+ * TODO: Put this in TextUtils to be used by other packages doing something similar.
+ *
+ * @param url a url to strip, like "http://www.google.com/"
+ * @return a stripped url like "www.google.com", or the original string if it could
+ * not be stripped
+ */
+ private String stripUrl(String url) {
+ if (url == null) return null;
+ Matcher m = STRIP_URL_PATTERN.matcher(url);
+ if (m.matches() && m.groupCount() == 3) {
+ return m.group(2);
+ } else {
+ return url;
+ }
+ }
+
+ }
+
+ class SearchesCursor extends CursorSource {
+
+ @Override
+ public SuggestItem getItem() {
+ if ((mCursor != null) && (!mCursor.isAfterLast())) {
+ return new SuggestItem(mCursor.getString(0), null, TYPE_SEARCH);
+ }
+ return null;
+ }
+
+ @Override
+ public void runQuery(CharSequence constraint) {
+ // constraint != null
+ if (mCursor != null) {
+ mCursor.close();
+ }
+ String like = constraint + "%";
+ String[] args = new String[] {constraint.toString()};
+ String selection = BrowserContract.Searches.SEARCH + " LIKE ?";
+ Uri.Builder ub = BrowserContract.Searches.CONTENT_URI.buildUpon();
+ ub.appendQueryParameter(BrowserContract.PARAM_LIMIT,
+ Integer.toString(mLinesPortrait));
+ mCursor =
+ mContext.getContentResolver().query(ub.build(), SEARCHES_PROJECTION,
+ selection,
+ args, BrowserContract.Searches.DATE + " DESC");
+ if (mCursor != null) {
+ mCursor.moveToFirst();
+ }
+ }
+
+ }
+
+ class SuggestCursor extends CursorSource {
+
+ @Override
+ public SuggestItem getItem() {
+ if (mCursor != null) {
+ String title = mCursor.getString(
+ mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1));
+ String text2 = mCursor.getString(
+ mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2));
+ String url = mCursor.getString(
+ mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2_URL));
+ String uri = mCursor.getString(
+ mCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_INTENT_DATA));
+ int type = (TextUtils.isEmpty(url)) ? TYPE_SUGGEST : TYPE_SUGGEST_URL;
+ return new SuggestItem(title, url, type);
+ }
+ return null;
+ }
+
+ @Override
+ public void runQuery(CharSequence constraint) {
+ if (mCursor != null) {
+ mCursor.close();
+ }
+ if (!TextUtils.isEmpty(constraint)) {
+ SearchEngine searchEngine = BrowserSettings.getInstance().getSearchEngine();
+ if (searchEngine != null && searchEngine.supportsSuggestions()) {
+ mCursor = searchEngine.getSuggestions(mContext, constraint.toString());
+ if (mCursor != null) {
+ mCursor.moveToFirst();
+ }
+ }
+ } else {
+ mCursor = null;
+ }
+ }
+
+ }
+
+}
diff --git a/src/com/android/browser/Tab.java b/src/com/android/browser/Tab.java
index 7019c8a..dc42428 100644
--- a/src/com/android/browser/Tab.java
+++ b/src/com/android/browser/Tab.java
@@ -16,13 +16,8 @@
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 com.android.browser.TabControl.TabChangeListener;
+import com.android.common.speech.LoggingEvents;
import android.app.AlertDialog;
import android.app.SearchManager;
@@ -42,14 +37,15 @@
import android.os.Message;
import android.os.SystemClock;
import android.provider.Browser;
+import android.provider.BrowserContract.History;
import android.speech.RecognizerResultsIntent;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.View.OnClickListener;
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;
@@ -71,7 +67,12 @@
import android.widget.LinearLayout;
import android.widget.TextView;
-import com.android.common.speech.LoggingEvents;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Vector;
/**
* Class for maintaining Tabs with a main WebView and a subwindow.
@@ -155,6 +156,7 @@
static final String PARENTTAB = "parentTab";
static final String APPID = "appid";
static final String ORIGINALURL = "originalUrl";
+ static final String INCOGNITO = "privateBrowsingEnabled";
// -------------------------------------------------------------------------
@@ -495,7 +497,7 @@
// update the bookmark database for favicon
if (favicon != null) {
- BrowserBookmarksAdapter.updateBookmarkFavicon(mActivity
+ Bookmarks.updateFavicon(mActivity
.getContentResolver(), null, url, favicon);
}
@@ -510,6 +512,9 @@
if (mInForeground) {
mActivity.onPageStarted(view, url, favicon);
}
+ if (getTabChangeListener() != null) {
+ getTabChangeListener().onPageStarted(Tab.this);
+ }
}
@Override
@@ -531,6 +536,9 @@
if (mInForeground) {
mActivity.onPageFinished(view, url);
}
+ if (getTabChangeListener() != null) {
+ getTabChangeListener().onPageFinished(Tab.this);
+ }
}
// return true if want to hijack the url to let another app to handle it
@@ -590,8 +598,12 @@
errorCode != WebViewClient.ERROR_FILE) {
queueError(errorCode, description);
}
- Log.e(LOGTAG, "onReceivedError " + errorCode + " " + failingUrl
- + " " + description);
+
+ // Don't log URLs when in private browsing mode
+ if (!getWebView().isPrivateBrowsingEnabled()) {
+ Log.e(LOGTAG, "onReceivedError " + errorCode + " " + failingUrl
+ + " " + description);
+ }
// We need to reset the title after an error if it is in foreground.
if (mInForeground) {
@@ -661,6 +673,9 @@
@Override
public void doUpdateVisitedHistory(WebView view, String url,
boolean isReload) {
+ // Don't save anything in private browsing mode
+ if (getWebView().isPrivateBrowsingEnabled()) return;
+
if (url.regionMatches(true, 0, "about:", 0, 6)) {
return;
}
@@ -680,6 +695,7 @@
final ContentResolver cr = mActivity.getContentResolver();
final String newUrl = url;
new AsyncTask<Void, Void, Void>() {
+ @Override
protected Void doInBackground(Void... unused) {
Browser.updateVisitedHistory(cr, newUrl, true);
return null;
@@ -956,6 +972,9 @@
if (mInForeground) {
mActivity.onProgressChanged(view, newProgress);
}
+ if (getTabChangeListener() != null) {
+ getTabChangeListener().onProgress(Tab.this, newProgress);
+ }
}
@Override
@@ -965,69 +984,67 @@
// here, if url is null, we want to reset the title
mActivity.setUrlTitle(pageUrl, title);
}
+ TabChangeListener tcl = getTabChangeListener();
+ if (tcl != null) {
+ tcl.onUrlAndTitle(Tab.this, 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);
- }
- // Escape wildcards for LIKE operator.
- url = url.replace("\\", "\\\\").replace("%", "\\%")
- .replace("_", "\\_");
- Cursor c = null;
- try {
- final ContentResolver cr
- = mActivity.getContentResolver();
- url = "%" + url;
- String [] selArgs = new String[] { url };
- String where = Browser.BookmarkColumns.URL
- + " LIKE ? ESCAPE '\\' 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);
+
+ // Update the title in the history database if not in private browsing mode
+ if (!getWebView().isPrivateBrowsingEnabled()) {
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ 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);
}
- } 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();
+ // Escape wildcards for LIKE operator.
+ url = url.replace("\\", "\\\\").replace("%", "\\%")
+ .replace("_", "\\_");
+ Cursor c = null;
+ try {
+ final ContentResolver cr = mActivity.getContentResolver();
+ String selection = History.URL + " LIKE ? ESCAPE '\\'";
+ String [] selectionArgs = new String[] { "%" + url };
+ ContentValues values = new ContentValues();
+ values.put(History.TITLE, title);
+ cr.update(History.CONTENT_URI, values, selection, selectionArgs);
+ } 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;
}
- return null;
- }
- }.execute();
+ }.execute();
+ }
}
@Override
public void onReceivedIcon(WebView view, Bitmap icon) {
if (icon != null) {
- BrowserBookmarksAdapter.updateBookmarkFavicon(mActivity
+ Bookmarks.updateFavicon(mActivity
.getContentResolver(), view.getOriginalUrl(), view
.getUrl(), icon);
}
if (mInForeground) {
mActivity.setFavicon(icon);
}
+ if (getTabChangeListener() != null) {
+ getTabChangeListener().onFavicon(Tab.this, icon);
+ }
}
@Override
@@ -1048,16 +1065,6 @@
}
@Override
- public void onSelectionDone(WebView view) {
- if (mInForeground) mActivity.closeDialogs();
- }
-
- @Override
- public void onSelectionStart(WebView view) {
- if (false && mInForeground) mActivity.showSelectDialog();
- }
-
- @Override
public void onShowCustomView(View view,
WebChromeClient.CustomViewCallback callback) {
if (mInForeground) mActivity.onShowCustomView(view, callback);
@@ -1150,6 +1157,9 @@
}
}
+ // Don't log console messages in private browsing mode
+ if (getWebView().isPrivateBrowsingEnabled()) return true;
+
String message = "Console: " + consoleMessage.message() + " "
+ consoleMessage.sourceId() + ":"
+ consoleMessage.lineNumber();
@@ -1202,9 +1212,9 @@
}
@Override
- public void openFileChooser(ValueCallback<Uri> uploadMsg) {
+ public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
if (mInForeground) {
- mActivity.openFileChooser(uploadMsg);
+ mActivity.openFileChooser(uploadMsg, acceptType);
} else {
uploadMsg.onReceiveValue(null);
}
@@ -1216,10 +1226,12 @@
@Override
public void getVisitedHistory(final ValueCallback<String[]> callback) {
AsyncTask<Void, Void, String[]> task = new AsyncTask<Void, Void, String[]>() {
+ @Override
public String[] doInBackground(Void... unused) {
return Browser.getVisitedHistory(mActivity
.getContentResolver());
}
+ @Override
public void onPostExecute(String[] result) {
callback.onReceiveValue(result);
};
@@ -1248,7 +1260,7 @@
// Unlike the others, do not call mClient's version, which would
// change the progress bar. However, we do want to remove the
// find or select dialog.
- mBrowserActivity.closeDialogs();
+ mBrowserActivity.endActionMode();
}
@Override
public void doUpdateVisitedHistory(WebView view, String url,
@@ -1449,7 +1461,7 @@
*/
boolean createSubWindow() {
if (mSubView == null) {
- mActivity.closeDialogs();
+ mActivity.endActionMode();
mSubViewContainer = mInflateService.inflate(
R.layout.browser_subwindow, null);
mSubView = (WebView) mSubViewContainer.findViewById(R.id.webview);
@@ -1497,7 +1509,7 @@
*/
void dismissSubWindow() {
if (mSubView != null) {
- mActivity.closeDialogs();
+ mActivity.endActionMode();
BrowserSettings.getInstance().deleteObserver(
mSubView.getSettings());
mSubView.destroy();
@@ -1522,7 +1534,7 @@
void removeSubWindow(ViewGroup content) {
if (mSubView != null) {
content.removeView(mSubViewContainer);
- mActivity.closeDialogs();
+ mActivity.endActionMode();
}
}
@@ -1581,7 +1593,7 @@
(FrameLayout) mContainer.findViewById(R.id.webview_wrapper);
wrapper.removeView(mMainView);
content.removeView(mContainer);
- mActivity.closeDialogs();
+ mActivity.endActionMode();
removeSubWindow(content);
}
@@ -1855,6 +1867,9 @@
// FIXME: The only place we cared about subwindow was for
// bookmarking (i.e. not when saving state). Was this deliberate?
final WebBackForwardList list = mMainView.copyBackForwardList();
+ if (list == null) {
+ Log.w(LOGTAG, "populatePickerData called and WebBackForwardList is null");
+ }
final WebHistoryItem item = list != null ? list.getCurrentItem() : null;
populatePickerData(item);
}
@@ -1863,7 +1878,9 @@
// WebView.
private void populatePickerData(WebHistoryItem item) {
mPickerData = new PickerData();
- if (item != null) {
+ if (item == null) {
+ Log.w(LOGTAG, "populatePickerData called with a null WebHistoryItem");
+ } else {
mPickerData.mUrl = item.getUrl();
mPickerData.mTitle = item.getTitle();
mPickerData.mFavicon = item.getFavicon();
@@ -1962,35 +1979,12 @@
return true;
}
- /*
- * Opens the find and select text dialogs. Called by BrowserActivity.
+ /**
+ * always get the TabChangeListener form the tab control
+ * @return the TabControl change listener
*/
- WebView showDialog(WebDialog dialog) {
- LinearLayout container;
- WebView view;
- if (mSubView != null) {
- view = mSubView;
- container = (LinearLayout) mSubViewContainer.findViewById(
- R.id.inner_container);
- } else {
- view = mMainView;
- container = mContainer;
- }
- dialog.show();
- container.addView(dialog, 0, new LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT));
- dialog.setWebView(view);
- return view;
+ private TabChangeListener getTabChangeListener() {
+ return mActivity.getTabControl().getTabChangeListener();
}
- /*
- * Close the find or select dialog. Called by BrowserActivity.closeDialog.
- */
- void closeDialog(WebDialog dialog) {
- // The dialog may be attached to the subwindow. Ensure that the
- // correct parent has it removed.
- LinearLayout parent = (LinearLayout) dialog.getParent();
- if (parent != null) parent.removeView(dialog);
- }
}
diff --git a/src/com/android/browser/TabBar.java b/src/com/android/browser/TabBar.java
new file mode 100644
index 0000000..4c8ab26
--- /dev/null
+++ b/src/com/android/browser/TabBar.java
@@ -0,0 +1,431 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.browser;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+import android.graphics.drawable.PaintDrawable;
+import android.view.ContextMenu;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.MenuInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.webkit.WebView;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.browser.ScrollWebView.ScrollListener;
+import com.android.browser.TabControl.TabChangeListener;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * tabbed title bar for xlarge screen browser
+ */
+public class TabBar extends LinearLayout
+ implements TabChangeListener, ScrollListener, OnClickListener {
+
+ private static final int PROGRESS_MAX = 100;
+
+ private BrowserActivity mBrowserActivity;
+
+ private final int mTabWidthSelected;
+ private final int mTabWidthUnselected;
+
+ private TitleBarXLarge mTitleBar;
+
+ private TabScrollView mTabs;
+ private TabControl mControl;
+
+ private Map<Tab, TabViewData> mTabMap;
+
+ private float mDensityScale;
+ private boolean mUserRequestedUrlbar;
+ private boolean mTitleVisible;
+ private boolean mShowUrlMode;
+
+ public TabBar(BrowserActivity context, TabControl tabcontrol, TitleBarXLarge titlebar) {
+ super(context);
+ Resources res = context.getResources();
+ mTabWidthSelected = (int) res.getDimension(R.dimen.tab_width_selected);
+ mTabWidthUnselected = (int) res.getDimension(R.dimen.tab_width_unselected);
+
+ mTitleBar = titlebar;
+ mTitleBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
+ LayoutParams.WRAP_CONTENT));
+ mDensityScale = context.getResources().getDisplayMetrics().density;
+ mTabMap = new HashMap<Tab, TabViewData>();
+ mBrowserActivity = context;
+ mControl = tabcontrol;
+ Resources resources = context.getResources();
+ LayoutInflater factory = LayoutInflater.from(context);
+ factory.inflate(R.layout.tab_bar, this);
+ mTabs = (TabScrollView) findViewById(R.id.tabs);
+
+ // TODO: Change enabled states based on whether you can go
+ // back/forward. Probably should be done inside onPageStarted.
+
+ // build tabs
+ int tabcount = mControl.getTabCount();
+ for (int i = 0; i < tabcount; i++) {
+ Tab tab = mControl.getTab(i);
+ TabViewData data = buildTab(tab);
+ TabView tv = buildView(data);
+ }
+ mTabs.setSelectedTab(mControl.getCurrentIndex());
+
+ // register the tab change listener
+ mControl.setOnTabChangeListener(this);
+ mUserRequestedUrlbar = false;
+ mTitleVisible = true;
+ }
+
+ public void onClick(View view) {
+ if (mTabs.getSelectedTab() == view) {
+ if (mBrowserActivity.isFakeTitleBarShowing() && !isLoading()) {
+ mBrowserActivity.hideFakeTitleBar();
+ } else {
+ showUrlBar();
+ }
+ // temporarily disabled
+ // mTitleBar.requestUrlInputFocus();
+ } else {
+ TabViewData data = (TabViewData) view.getTag();
+ int ix = mControl.getTabIndex(data.mTab);
+ mTabs.setSelectedTab(ix);
+ mBrowserActivity.switchToTab(ix);
+ }
+ }
+
+ private void showUrlBar() {
+ mBrowserActivity.stopScrolling();
+ mBrowserActivity.showFakeTitleBar();
+ mUserRequestedUrlbar = true;
+ }
+
+ private void setShowUrlMode(boolean showUrl) {
+ mShowUrlMode = showUrl;
+ }
+
+ // callback after fake titlebar is shown
+ void onShowTitleBar() {
+ setShowUrlMode(false);
+ }
+
+ // callback after fake titlebar is hidden
+ void onHideTitleBar() {
+ setShowUrlMode(!mTitleVisible);
+ Tab tab = mControl.getCurrentTab();
+ tab.getWebView().requestFocus();
+ mUserRequestedUrlbar = false;
+ }
+
+ // webview scroll listener
+
+ @Override
+ public void onScroll(boolean titleVisible) {
+ mTitleVisible = titleVisible;
+ if (!mShowUrlMode && !mTitleVisible && !isLoading()) {
+ if (mUserRequestedUrlbar) {
+ mBrowserActivity.hideFakeTitleBar();
+ } else {
+ setShowUrlMode(true);
+ }
+ } else if (mTitleVisible && !isLoading()) {
+ if (mShowUrlMode) {
+ setShowUrlMode(false);
+ }
+ }
+ }
+
+ @Override
+ public void createContextMenu(ContextMenu menu) {
+ MenuInflater inflater = mBrowserActivity.getMenuInflater();
+ inflater.inflate(R.menu.title_context, menu);
+ mBrowserActivity.onCreateContextMenu(menu, this, null);
+ }
+
+ private TabViewData buildTab(Tab tab) {
+ TabViewData data = new TabViewData(tab);
+ mTabMap.put(tab, data);
+ return data;
+ }
+
+ private TabView buildView(final TabViewData data) {
+ TabView tv = new TabView(mBrowserActivity, data);
+ tv.setTag(data);
+ tv.setOnClickListener(this);
+ mTabs.addTab(tv);
+ return tv;
+ }
+
+ /**
+ * View used in the tab bar
+ */
+ class TabView extends LinearLayout implements OnClickListener {
+
+ TabViewData mTabData;
+ View mTabContent;
+ TextView mTitle;
+ View mIncognito;
+ ImageView mIconView;
+ ImageView mLock;
+ ImageView mClose;
+ boolean mSelected;
+ boolean mInLoad;
+
+ /**
+ * @param context
+ */
+ public TabView(Context context, TabViewData tab) {
+ super(context);
+ mTabData = tab;
+ setGravity(Gravity.CENTER_VERTICAL);
+ setOrientation(LinearLayout.HORIZONTAL);
+ setBackgroundResource(R.drawable.tab_background);
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ mTabContent = inflater.inflate(R.layout.tab_title, this, true);
+ mTitle = (TextView) mTabContent.findViewById(R.id.title);
+ mIconView = (ImageView) mTabContent.findViewById(R.id.favicon);
+ mLock = (ImageView) mTabContent.findViewById(R.id.lock);
+ mClose = (ImageView) mTabContent.findViewById(R.id.close);
+ mClose.setOnClickListener(this);
+ mIncognito = mTabContent.findViewById(R.id.incognito);
+ mSelected = false;
+ mInLoad = false;
+ // update the status
+ updateFromData();
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (v == mClose) {
+ closeTab();
+ }
+ }
+
+ private void updateFromData() {
+ mTabData.mTabView = this;
+ if (mTabData.mUrl != null) {
+ setDisplayTitle(mTabData.mUrl);
+ }
+ if (mTabData.mTitle != null) {
+ setDisplayTitle(mTabData.mTitle);
+ }
+ setProgress(mTabData.mProgress);
+ if (mTabData.mIcon != null) {
+ setFavicon(mTabData.mIcon);
+ }
+ if (mTabData.mLock != null) {
+ setLock(mTabData.mLock);
+ }
+ if (mTabData.mTab != null) {
+ mIncognito.setVisibility(
+ mTabData.mTab.getWebView().isPrivateBrowsingEnabled() ?
+ View.VISIBLE : View.GONE);
+ }
+ }
+
+ @Override
+ public void setActivated(boolean selected) {
+ mSelected = selected;
+ mClose.setVisibility(mSelected ? View.VISIBLE : View.GONE);
+ mTitle.setTextAppearance(mBrowserActivity, mSelected ?
+ R.style.TabTitleSelected : R.style.TabTitleUnselected);
+ setHorizontalFadingEdgeEnabled(!mSelected);
+ setFadingEdgeLength(50);
+ super.setActivated(selected);
+ setLayoutParams(new LayoutParams(selected ?
+ mTabWidthSelected : mTabWidthUnselected,
+ LayoutParams.MATCH_PARENT));
+ }
+
+ void setDisplayTitle(String title) {
+ mTitle.setText(title);
+ }
+
+ void setFavicon(Drawable d) {
+ mIconView.setImageDrawable(d);
+ }
+
+ void setLock(Drawable d) {
+ if (null == d) {
+ mLock.setVisibility(View.GONE);
+ } else {
+ mLock.setImageDrawable(d);
+ mLock.setVisibility(View.VISIBLE);
+ }
+ }
+
+ void setTitleCompoundDrawables(Drawable left, Drawable top,
+ Drawable right, Drawable bottom) {
+ mTitle.setCompoundDrawables(left, top, right, bottom);
+ }
+
+ void setProgress(int newProgress) {
+ if (newProgress >= PROGRESS_MAX) {
+ mInLoad = false;
+ } else {
+ if (!mInLoad && getWindowToken() != null) {
+ mInLoad = true;
+ }
+ }
+ }
+
+ private void closeTab() {
+ if (mTabData.mTab == mControl.getCurrentTab()) {
+ mBrowserActivity.closeCurrentWindow();
+ } else {
+ mBrowserActivity.closeTab(mTabData.mTab);
+ }
+ }
+
+ }
+
+ /**
+ * Store tab state within the title bar
+ */
+ class TabViewData {
+
+ Tab mTab;
+ TabView mTabView;
+ int mProgress;
+ Drawable mIcon;
+ Drawable mLock;
+ String mTitle;
+ String mUrl;
+
+ TabViewData(Tab tab) {
+ mTab = tab;
+ }
+
+ void setUrlAndTitle(String url, String title) {
+ mUrl = url;
+ mTitle = title;
+ if (mTabView != null) {
+ if (title != null) {
+ mTabView.setDisplayTitle(title);
+ } else if (url != null) {
+ mTabView.setDisplayTitle(url);
+ }
+ }
+ }
+
+ void setProgress(int newProgress) {
+ mProgress = newProgress;
+ if (mTabView != null) {
+ mTabView.setProgress(mProgress);
+ }
+ }
+
+ void setFavicon(Bitmap icon) {
+ Drawable[] array = new Drawable[3];
+ array[0] = new PaintDrawable(Color.BLACK);
+ array[1] = new PaintDrawable(Color.WHITE);
+ if (icon == null) {
+// array[2] = mGenericFavicon;
+ } else {
+ array[2] = new BitmapDrawable(icon);
+ }
+ LayerDrawable d = new LayerDrawable(array);
+ d.setLayerInset(1, 1, 1, 1, 1);
+ d.setLayerInset(2, 2, 2, 2, 2);
+ mIcon = d;
+ if (mTabView != null) {
+ mTabView.setFavicon(mIcon);
+ }
+ }
+
+ }
+
+ // TabChangeListener implementation
+
+ @Override
+ public void onCurrentTab(Tab tab) {
+ mTabs.setSelectedTab(mControl.getCurrentIndex());
+ TabViewData tvd = mTabMap.get(tab);
+ if (tvd != null) {
+ tvd.setProgress(tvd.mProgress);
+ // update the scroll state
+ WebView webview = tab.getWebView();
+ onScroll(webview.getVisibleTitleHeight() > 0);
+ }
+ }
+
+ @Override
+ public void onFavicon(Tab tab, Bitmap favicon) {
+ TabViewData tvd = mTabMap.get(tab);
+ if (tvd != null) {
+ tvd.setFavicon(favicon);
+ }
+ }
+
+ @Override
+ public void onNewTab(Tab tab) {
+ TabViewData tvd = buildTab(tab);
+ buildView(tvd);
+ }
+
+ @Override
+ public void onProgress(Tab tab, int progress) {
+ TabViewData tvd = mTabMap.get(tab);
+ if (tvd != null) {
+ tvd.setProgress(progress);
+ }
+ }
+
+ @Override
+ public void onRemoveTab(Tab tab) {
+ TabViewData tvd = mTabMap.get(tab);
+ TabView tv = tvd.mTabView;
+ if (tv != null) {
+ mTabs.removeTab(tv);
+ }
+ mTabMap.remove(tab);
+ }
+
+ @Override
+ public void onUrlAndTitle(Tab tab, String url, String title) {
+ TabViewData tvd = mTabMap.get(tab);
+ if (tvd != null) {
+ tvd.setUrlAndTitle(url, title);
+ }
+ }
+
+ @Override
+ public void onPageFinished(Tab tab) {
+ }
+
+ @Override
+ public void onPageStarted(Tab tab) {
+ }
+
+
+ private boolean isLoading() {
+ return mTabMap.get(mControl.getCurrentTab()).mTabView.mInLoad;
+ }
+
+}
diff --git a/src/com/android/browser/TabControl.java b/src/com/android/browser/TabControl.java
index afd4ea8..e417a39 100644
--- a/src/com/android/browser/TabControl.java
+++ b/src/com/android/browser/TabControl.java
@@ -29,17 +29,18 @@
import java.io.File;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.Vector;
class TabControl {
// Log Tag
private static final String LOGTAG = "TabControl";
// Maximum number of tabs.
- private static final int MAX_TABS = 8;
+ private int mMaxTabs;
// Private array of WebViews that are used as tabs.
- private ArrayList<Tab> mTabs = new ArrayList<Tab>(MAX_TABS);
+ private ArrayList<Tab> mTabs;
// Queue of most recently viewed tabs.
- private ArrayList<Tab> mTabQueue = new ArrayList<Tab>(MAX_TABS);
+ private ArrayList<Tab> mTabQueue;
// Current position in mTabs.
private int mCurrentTab = -1;
// A private instance of BrowserActivity to interface with when adding and
@@ -47,6 +48,8 @@
private final BrowserActivity mActivity;
// Directory to store thumbnails for each WebView.
private final File mThumbnailDir;
+ // Use on screen zoom buttons
+ private boolean mDisplayZoomControls;
/**
* Construct a new TabControl object that interfaces with the given
@@ -57,6 +60,10 @@
TabControl(BrowserActivity activity) {
mActivity = activity;
mThumbnailDir = activity.getDir("thumbnails", 0);
+ mDisplayZoomControls = true;
+ mMaxTabs = activity.getResources().getInteger(R.integer.max_tabs);
+ mTabs = new ArrayList<Tab>(mMaxTabs);
+ mTabQueue = new ArrayList<Tab>(mMaxTabs);
}
File getThumbnailDir() {
@@ -68,6 +75,14 @@
}
/**
+ * Set if the webview should use the on screen zoom controls
+ * @param enabled
+ */
+ void setDisplayZoomControls(boolean enabled) {
+ mDisplayZoomControls = enabled;
+ }
+
+ /**
* Return the current tab's main WebView. This will always return the main
* WebView for a given tab and not a subwindow.
* @return The current tab's WebView.
@@ -132,7 +147,7 @@
int getCurrentIndex() {
return mCurrentTab;
}
-
+
/**
* Given a Tab, find it's index
* @param Tab to find
@@ -146,7 +161,20 @@
}
boolean canCreateNewTab() {
- return MAX_TABS != mTabs.size();
+ return mMaxTabs != mTabs.size();
+ }
+
+ /**
+ * Returns true if there are any incognito tabs open.
+ * @return True when any incognito tabs are open, false otherwise.
+ */
+ boolean hasAnyOpenIncognitoTabs() {
+ for (Tab tab : mTabs) {
+ if (tab.getWebView() != null && tab.getWebView().isPrivateBrowsingEnabled()) {
+ return true;
+ }
+ }
+ return false;
}
/**
@@ -154,28 +182,32 @@
* @return The newly createTab or null if we have reached the maximum
* number of open tabs.
*/
- Tab createNewTab(boolean closeOnExit, String appId, String url) {
+ Tab createNewTab(boolean closeOnExit, String appId, String url,
+ boolean privateBrowsing) {
int size = mTabs.size();
// Return false if we have maxed out on tabs
- if (MAX_TABS == size) {
+ if (mMaxTabs == size) {
return null;
}
- final WebView w = createNewWebView();
+ final WebView w = createNewWebView(privateBrowsing);
// Create a new tab and add it to the tab list
Tab t = new Tab(mActivity, w, closeOnExit, appId, url);
mTabs.add(t);
// Initially put the tab in the background.
t.putInBackground();
+ if (mTabChangeListener != null) {
+ mTabChangeListener.onNewTab(t);
+ }
return t;
}
/**
* Create a new tab with default values for closeOnExit(false),
- * appId(null), and url(null).
+ * appId(null), url(null), and privateBrowsing(false).
*/
Tab createNewTab() {
- return createNewTab(false, null, null);
+ return createNewTab(false, null, null, false);
}
/**
@@ -231,6 +263,9 @@
// Remove it from the queue of viewed tabs.
mTabQueue.remove(t);
+ if (mTabChangeListener != null) {
+ mTabChangeListener.onRemoveTab(t);
+ }
return true;
}
@@ -277,29 +312,56 @@
* @return True if there were previous tabs that were restored. False if
* there was no saved state or restoring the state failed.
*/
- boolean restoreState(Bundle inState) {
+ boolean restoreState(Bundle inState, boolean dontRestoreIncognitoTabs) {
final int numTabs = (inState == null)
? -1 : inState.getInt(Tab.NUMTABS, -1);
if (numTabs == -1) {
return false;
} else {
- final int currentTab = inState.getInt(Tab.CURRTAB, -1);
+ final int oldCurrentTab = inState.getInt(Tab.CURRTAB, -1);
+
+ // Determine whether the saved current tab can be restored, and
+ // if not, which tab will take its place.
+ int currentTab = -1;
+ if (!dontRestoreIncognitoTabs
+ || !inState.getBundle(Tab.WEBVIEW + oldCurrentTab).getBoolean(Tab.INCOGNITO)) {
+ currentTab = oldCurrentTab;
+ } else {
+ for (int i = 0; i < numTabs; i++) {
+ if (!inState.getBundle(Tab.WEBVIEW + i).getBoolean(Tab.INCOGNITO)) {
+ currentTab = i;
+ break;
+ }
+ }
+ }
+ if (currentTab < 0) {
+ return false;
+ }
+
+ // Map saved tab indices to new indices, in case any incognito tabs
+ // need to not be restored.
+ HashMap<Integer, Integer> originalTabIndices = new HashMap<Integer, Integer>();
+ originalTabIndices.put(-1, -1);
for (int i = 0; i < numTabs; i++) {
- if (i == currentTab) {
+ Bundle state = inState.getBundle(Tab.WEBVIEW + i);
+
+ if (dontRestoreIncognitoTabs && state != null && state.getBoolean(Tab.INCOGNITO)) {
+ originalTabIndices.put(i, -1);
+ } else 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 (!t.restoreState(inState.getBundle(Tab.WEBVIEW + i))) {
+ if (!t.restoreState(state)) {
Log.w(LOGTAG, "Fail in restoreState, load home page.");
t.getWebView().loadUrl(BrowserSettings.getInstance()
.getHomePage());
}
+ originalTabIndices.put(i, getTabCount() - 1);
} else {
// Create a new tab and don't restore the state yet, add it
// to the tab list
Tab t = new Tab(mActivity, null, false, null, null);
- Bundle state = inState.getBundle(Tab.WEBVIEW + i);
if (state != null) {
t.setSavedState(state);
t.populatePickerDataFromSavedState();
@@ -311,15 +373,17 @@
mTabs.add(t);
// added the tab to the front as they are not current
mTabQueue.add(0, t);
+ originalTabIndices.put(i, getTabCount() - 1);
}
}
+
// 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(Tab.WEBVIEW + i);
final Tab t = getTab(i);
if (b != null && t != null) {
- final int parentIndex = b.getInt(Tab.PARENTTAB, -1);
+ final Integer parentIndex = originalTabIndices.get(b.getInt(Tab.PARENTTAB, -1));
if (parentIndex != -1) {
final Tab parent = getTab(parentIndex);
if (parent != null) {
@@ -529,13 +593,25 @@
* Creates a new WebView and registers it with the global settings.
*/
private WebView createNewWebView() {
+ return createNewWebView(false);
+ }
+
+ /**
+ * Creates a new WebView and registers it with the global settings.
+ * @param privateBrowsing When true, enables private browsing in the new
+ * WebView.
+ */
+ private WebView createNewWebView(boolean privateBrowsing) {
// Create a new WebView
- WebView w = new WebView(mActivity);
+ ScrollWebView w = new ScrollWebView(mActivity, null,
+ com.android.internal.R.attr.webViewStyle, privateBrowsing);
+ w.setScrollListener(mActivity.getScrollListener());
w.setScrollbarFadingEnabled(true);
w.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY);
w.setMapTrackballToArrowKeys(false); // use trackball directly
// Enable the built-in zoom
w.getSettings().setBuiltInZoomControls(true);
+ w.getSettings().setDisplayZoomControls(mDisplayZoomControls);
// Add this WebView to the settings observer list and update the
// settings
final BrowserSettings s = BrowserSettings.getInstance();
@@ -619,4 +695,42 @@
}
return true;
}
+
+ interface TabChangeListener {
+
+ public void onNewTab(Tab tab);
+
+ public void onRemoveTab(Tab tab);
+
+ public void onCurrentTab(Tab tab);
+
+ public void onProgress(Tab tab, int progress);
+
+ public void onUrlAndTitle(Tab tab, String url, String title);
+
+ public void onFavicon(Tab tab, Bitmap favicon);
+
+ public void onPageStarted(Tab tab);
+
+ public void onPageFinished(Tab tab);
+
+ }
+
+ private TabChangeListener mTabChangeListener;
+
+ /**
+ * register the TabChangeListener with the tab control
+ * @param listener
+ */
+ void setOnTabChangeListener(TabChangeListener listener) {
+ mTabChangeListener = listener;
+ }
+
+ /**
+ * get the current TabChangeListener (used by the tabs)
+ */
+ TabChangeListener getTabChangeListener() {
+ return mTabChangeListener;
+ }
+
}
diff --git a/src/com/android/browser/TabScrollView.java b/src/com/android/browser/TabScrollView.java
new file mode 100644
index 0000000..435362d
--- /dev/null
+++ b/src/com/android/browser/TabScrollView.java
@@ -0,0 +1,142 @@
+/*
+ * 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.util.AttributeSet;
+import android.view.View;
+import android.widget.HorizontalScrollView;
+import android.widget.LinearLayout;
+
+/**
+ * custom view for displaying tabs in the tabbed title bar
+ */
+public class TabScrollView extends HorizontalScrollView {
+
+ private Context mContext;
+
+ private LinearLayout mContentView;
+
+ private int mSelected;
+
+ /**
+ * @param context
+ * @param attrs
+ * @param defStyle
+ */
+ public TabScrollView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init(context);
+ }
+
+ /**
+ * @param context
+ * @param attrs
+ */
+ public TabScrollView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context);
+ }
+
+ /**
+ * @param context
+ */
+ public TabScrollView(Context context) {
+ super(context);
+ init(context);
+ }
+
+ private void init(Context ctx) {
+ mContext = ctx;
+ setHorizontalScrollBarEnabled(false);
+ mContentView = new LinearLayout(mContext);
+ mContentView.setOrientation(LinearLayout.HORIZONTAL);
+ mContentView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.MATCH_PARENT));
+ addView(mContentView);
+ mSelected = -1;
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ ensureChildVisible(getSelectedTab());
+ }
+
+ void setSelectedTab(int position) {
+ View v = getSelectedTab();
+ if (v != null) {
+ v.setActivated(false);
+ }
+ mSelected = position;
+ v = getSelectedTab();
+ if (v != null) {
+ v.setActivated(true);
+ }
+ requestLayout();
+ }
+
+ View getSelectedTab() {
+ if ((mSelected >= 0) && (mSelected < mContentView.getChildCount())) {
+ return mContentView.getChildAt(mSelected);
+ } else {
+ return null;
+ }
+ }
+
+ void clearTabs() {
+ mContentView.removeAllViews();
+ }
+
+ void addTab(View tab) {
+ mContentView.addView(tab);
+ tab.setActivated(false);
+ }
+
+ void addTab(View tab, int pos) {
+ mContentView.addView(tab, pos);
+ tab.setActivated(false);
+ }
+
+ void removeTab(View tab) {
+ int ix = mContentView.indexOfChild(tab);
+ if (ix == mSelected) {
+ mSelected = -1;
+ } else if (ix < mSelected) {
+ mSelected--;
+ }
+ mContentView.removeView(tab);
+ }
+
+ void ensureChildVisible(View child) {
+ if (child != null) {
+ int childl = child.getLeft();
+ int childr = childl + child.getWidth();
+ int viewl = getScrollX();
+ int viewr = viewl + getWidth();
+ if (childl < viewl) {
+ // need scrolling to left
+ scrollTo(childl, 0);
+ } else if (childr > viewr) {
+ // need scrolling to right
+ scrollTo(childr - viewr + viewl, 0);
+ }
+ }
+ }
+
+
+}
diff --git a/src/com/android/browser/TitleBar.java b/src/com/android/browser/TitleBar.java
index dc4979b..bbb55ad 100644
--- a/src/com/android/browser/TitleBar.java
+++ b/src/com/android/browser/TitleBar.java
@@ -21,14 +21,8 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Color;
-import android.graphics.Rect;
import android.graphics.drawable.Animatable;
-import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
-import android.graphics.drawable.PaintDrawable;
import android.os.Handler;
import android.os.Message;
import android.speech.RecognizerIntent;
@@ -45,7 +39,6 @@
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.ImageView;
-import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
@@ -55,21 +48,16 @@
* This class represents a title bar for a particular "tab" or "window" in the
* browser.
*/
-public class TitleBar extends LinearLayout {
+public class TitleBar extends TitleBarBase {
private TextView mTitle;
- private Drawable mCloseDrawable;
private ImageView mRtButton;
private Drawable mCircularProgress;
private ProgressBar mHorizontalProgress;
- private ImageView mFavicon;
- private ImageView mLockIcon;
private ImageView mStopButton;
private Drawable mBookmarkDrawable;
private Drawable mVoiceDrawable;
private boolean mInLoad;
private BrowserActivity mBrowserActivity;
- private Drawable mGenericFavicon;
- private int mIconDimension;
private View mTitleBg;
private MyHandler mHandler;
private Intent mVoiceSearchIntent;
@@ -84,7 +72,7 @@
private static int LONG_PRESS = 1;
public TitleBar(BrowserActivity context) {
- super(context, null);
+ super(context);
mHandler = new MyHandler();
LayoutInflater factory = LayoutInflater.from(context);
factory.inflate(R.layout.title_bar, this);
@@ -107,13 +95,11 @@
TypedValue.COMPLEX_UNIT_DIP, 8f, metrics);
mRightMargin = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 6f, metrics);
- mIconDimension = (int) TypedValue.applyDimension(
+ int iconDimension = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 20f, metrics);
- mCircularProgress.setBounds(0, 0, mIconDimension, mIconDimension);
+ mCircularProgress.setBounds(0, 0, iconDimension, iconDimension);
mHorizontalProgress = (ProgressBar) findViewById(
R.id.progress_horizontal);
- mGenericFavicon = context.getResources().getDrawable(
- R.drawable.app_web_browser_sm);
mVoiceSearchIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
mVoiceSearchIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);
@@ -219,7 +205,7 @@
} else if (mInLoad) {
mBrowserActivity.stopLoading();
} else {
- mBrowserActivity.bookmarksOrHistoryPicker(false);
+ mBrowserActivity.promptAddOrInstallBookmark(button);
}
button.setPressed(false);
} else if (mTitleBg.isPressed()) {
@@ -248,25 +234,6 @@
}
/**
- * Set a new Bitmap for the Favicon.
- */
- /* package */ void setFavicon(Bitmap icon) {
- Drawable[] array = new Drawable[3];
- array[0] = new PaintDrawable(Color.BLACK);
- PaintDrawable p = new PaintDrawable(Color.WHITE);
- array[1] = p;
- if (icon == null) {
- array[2] = mGenericFavicon;
- } else {
- array[2] = new BitmapDrawable(icon);
- }
- LayerDrawable d = new LayerDrawable(array);
- d.setLayerInset(1, 1, 1, 1, 1);
- d.setLayerInset(2, 2, 2, 2, 2);
- mFavicon.setImageDrawable(d);
- }
-
- /**
* Change the TitleBar to or from voice mode. If there is no package to
* handle voice search, the TitleBar cannot be set to voice mode.
*/
@@ -302,18 +269,6 @@
}
/**
- * Set the Drawable for the lock icon, or null to hide it.
- */
- /* package */ void setLock(Drawable d) {
- if (null == d) {
- mLockIcon.setVisibility(View.GONE);
- } else {
- mLockIcon.setImageDrawable(d);
- mLockIcon.setVisibility(View.VISIBLE);
- }
- }
-
- /**
* Update the progress, from 0 to 100.
*/
/* package */ void setProgress(int newProgress) {
@@ -374,11 +329,4 @@
}
}
}
-
- /* package */ void setToTabPicker() {
- mTitle.setText(R.string.tab_picker_title);
- setFavicon(null);
- setLock(null);
- mHorizontalProgress.setVisibility(View.GONE);
- }
}
diff --git a/src/com/android/browser/TitleBarBase.java b/src/com/android/browser/TitleBarBase.java
new file mode 100644
index 0000000..7016dc0
--- /dev/null
+++ b/src/com/android/browser/TitleBarBase.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.browser;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+import android.graphics.drawable.PaintDrawable;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+/**
+ * Base class for a title bar used by the browser.
+ */
+public class TitleBarBase extends LinearLayout {
+ // These need to be set by the subclass.
+ protected ImageView mFavicon;
+ protected ImageView mLockIcon;
+
+ protected Drawable mGenericFavicon;
+
+ public TitleBarBase(Context context) {
+ super(context, null);
+ mGenericFavicon = context.getResources().getDrawable(
+ R.drawable.app_web_browser_sm);
+ }
+
+ /* package */ void setProgress(int newProgress) {}
+ /* package */ void setDisplayTitle(String title) {}
+
+ /* package */ void setLock(Drawable d) {
+ assert mLockIcon != null;
+ if (null == d) {
+ mLockIcon.setVisibility(View.GONE);
+ } else {
+ mLockIcon.setImageDrawable(d);
+ mLockIcon.setVisibility(View.VISIBLE);
+ }
+ }
+
+ /* package */ void setFavicon(Bitmap icon) {
+ assert mFavicon != null;
+ Drawable[] array = new Drawable[3];
+ array[0] = new PaintDrawable(Color.BLACK);
+ PaintDrawable p = new PaintDrawable(Color.WHITE);
+ array[1] = p;
+ if (icon == null) {
+ array[2] = mGenericFavicon;
+ } else {
+ array[2] = new BitmapDrawable(icon);
+ }
+ LayerDrawable d = new LayerDrawable(array);
+ d.setLayerInset(1, 1, 1, 1, 1);
+ d.setLayerInset(2, 2, 2, 2, 2);
+ mFavicon.setImageDrawable(d);
+ }
+
+ /* package */ void setInVoiceMode(boolean inVoiceMode) {}
+
+}
diff --git a/src/com/android/browser/TitleBarXLarge.java b/src/com/android/browser/TitleBarXLarge.java
new file mode 100644
index 0000000..b652e15
--- /dev/null
+++ b/src/com/android/browser/TitleBarXLarge.java
@@ -0,0 +1,243 @@
+/*
+ * 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 com.android.browser.UrlInputView.UrlInputListener;
+
+import android.app.SearchManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
+import android.view.ContextMenu;
+import android.view.LayoutInflater;
+import android.view.MenuInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnFocusChangeListener;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+/**
+ * tabbed title bar for xlarge screen browser
+ */
+public class TitleBarXLarge extends TitleBarBase
+ implements UrlInputListener, OnClickListener, OnFocusChangeListener {
+
+ private static final int PROGRESS_MAX = 100;
+
+ private BrowserActivity mBrowserActivity;
+ private Drawable mStopDrawable;
+ private Drawable mReloadDrawable;
+
+
+ private View mContainer;
+ private View mBackButton;
+ private View mForwardButton;
+ private View mStar;
+ private View mSearchButton;
+ private View mFocusContainer;
+ private View mUnfocusContainer;
+ private View mGoButton;
+ private ImageView mStopButton;
+ private View mAllButton;
+ private View mClearButton;
+ private PageProgressView mProgressView;
+ private UrlInputView mUrlFocused;
+ private TextView mUrlUnfocused;
+ private boolean mInLoad;
+
+ public TitleBarXLarge(BrowserActivity context) {
+ super(context);
+ mBrowserActivity = context;
+ Resources resources = context.getResources();
+ mStopDrawable = resources.getDrawable(R.drawable.ic_stop_normal);
+ mReloadDrawable = resources.getDrawable(R.drawable.ic_refresh_normal);
+ rebuildLayout(context, true);
+ }
+
+ private void rebuildLayout(Context context, boolean rebuildData) {
+ LayoutInflater factory = LayoutInflater.from(context);
+ factory.inflate(R.layout.url_bar, this);
+
+ mContainer = findViewById(R.id.taburlbar);
+ mUrlFocused = (UrlInputView) findViewById(R.id.url_focused);
+ mUrlUnfocused = (TextView) findViewById(R.id.url_unfocused);
+ mAllButton = findViewById(R.id.all_btn);
+ // TODO: Change enabled states based on whether you can go
+ // back/forward. Probably should be done inside onPageStarted.
+ mBackButton = findViewById(R.id.back);
+ mForwardButton = findViewById(R.id.forward);
+ mStar = findViewById(R.id.star);
+ mStopButton = (ImageView) findViewById(R.id.stop);
+ mSearchButton = findViewById(R.id.search);
+ mLockIcon = (ImageView) findViewById(R.id.lock);
+ mGoButton = findViewById(R.id.go);
+ mClearButton = findViewById(R.id.clear);
+ mProgressView = (PageProgressView) findViewById(R.id.progress);
+ mFocusContainer = findViewById(R.id.urlbar_focused);
+ mUnfocusContainer = findViewById(R.id.urlbar_unfocused);
+
+ mBackButton.setOnClickListener(this);
+ mForwardButton.setOnClickListener(this);
+ mStar.setOnClickListener(this);
+ mAllButton.setOnClickListener(this);
+ mStopButton.setOnClickListener(this);
+ mSearchButton.setOnClickListener(this);
+ mGoButton.setOnClickListener(this);
+ mClearButton.setOnClickListener(this);
+ mUrlFocused.setUrlInputListener(this);
+ mUrlUnfocused.setOnFocusChangeListener(this);
+ mUrlFocused.setContainer(mFocusContainer);
+ }
+
+ public void onFocusChange(View v, boolean hasFocus) {
+ if (hasFocus) {
+ setUrlMode(true);
+ mUrlFocused.selectAll();
+ mUrlFocused.requestFocus();
+ mUrlFocused.setDropDownWidth(mUnfocusContainer.getWidth());
+ mUrlFocused.setDropDownHorizontalOffset(-mUrlFocused.getLeft());
+ }
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (mBackButton == v) {
+ mBrowserActivity.getTopWindow().goBack();
+ } else if (mForwardButton == v) {
+ mBrowserActivity.getTopWindow().goForward();
+ } else if (mStar == v) {
+ mBrowserActivity.promptAddOrInstallBookmark(mStar);
+ } else if (mAllButton == v) {
+ mBrowserActivity.bookmarksOrHistoryPicker(false, false);
+ } else if (mSearchButton == v) {
+ search();
+ } else if (mStopButton == v) {
+ stopOrRefresh();
+ } else if (mGoButton == v) {
+ if (!TextUtils.isEmpty(mUrlFocused.getText())) {
+ onAction(mUrlFocused.getText().toString());
+ }
+ } else if (mClearButton == v) {
+ mUrlFocused.setText("");
+ }
+ }
+
+ int getHeightWithoutProgress() {
+ return mContainer.getHeight();
+ }
+
+ @Override
+ void setFavicon(Bitmap icon) { }
+
+ // UrlInputListener implementation
+
+ @Override
+ public void onAction(String text) {
+ mBrowserActivity.getTabControl().getCurrentTopWebView().requestFocus();
+ mBrowserActivity.hideFakeTitleBar();
+ Intent i = new Intent();
+ i.setAction(Intent.ACTION_SEARCH);
+ i.putExtra(SearchManager.QUERY, text);
+ mBrowserActivity.onNewIntent(i);
+ setUrlMode(false);
+ setDisplayTitle(text);
+ }
+
+ @Override
+ public void onDismiss() {
+ mBrowserActivity.getTabControl().getCurrentTopWebView().requestFocus();
+ mBrowserActivity.hideFakeTitleBar();
+ setUrlMode(false);
+ setDisplayTitle(mBrowserActivity.getTabControl().getCurrentWebView().getUrl());
+ }
+
+ @Override
+ public void onEdit(String text) {
+ setDisplayTitle(text);
+ if (text != null) {
+ mUrlFocused.setSelection(text.length());
+ }
+ }
+
+ private void setUrlMode(boolean focused) {
+ swapUrlContainer(focused);
+ if (focused) {
+ mSearchButton.setVisibility(View.GONE);
+ mGoButton.setVisibility(View.VISIBLE);
+ } else {
+ mSearchButton.setVisibility(View.VISIBLE);
+ mGoButton.setVisibility(View.GONE);
+ }
+ }
+
+ private void swapUrlContainer(boolean focus) {
+ mUnfocusContainer.setVisibility(focus ? View.GONE : View.VISIBLE);
+ mFocusContainer.setVisibility(focus ? View.VISIBLE : View.GONE);
+ }
+
+ @Override
+ public void createContextMenu(ContextMenu menu) {
+ MenuInflater inflater = mBrowserActivity.getMenuInflater();
+ inflater.inflate(R.menu.title_context, menu);
+ mBrowserActivity.onCreateContextMenu(menu, this, null);
+ }
+
+ private void search() {
+ setDisplayTitle("");
+ mUrlUnfocused.requestFocus();
+ }
+
+ private void stopOrRefresh() {
+ if (mInLoad) {
+ mBrowserActivity.stopLoading();
+ } else {
+ mBrowserActivity.getTopWindow().reload();
+ }
+ }
+
+ /**
+ * Update the progress, from 0 to 100.
+ */
+ @Override
+ void setProgress(int newProgress) {
+ if (newProgress >= PROGRESS_MAX) {
+ mProgressView.setProgress(PageProgressView.MAX_PROGRESS);
+ mProgressView.setVisibility(View.GONE);
+ mInLoad = false;
+ mStopButton.setImageDrawable(mReloadDrawable);
+ } else {
+ if (!mInLoad) {
+ mProgressView.setVisibility(View.VISIBLE);
+ mInLoad = true;
+ mStopButton.setImageDrawable(mStopDrawable);
+ }
+ mProgressView.setProgress(newProgress * PageProgressView.MAX_PROGRESS
+ / PROGRESS_MAX);
+ }
+ }
+
+ @Override
+ /* package */ void setDisplayTitle(String title) {
+ mUrlFocused.setText(title, false);
+ mUrlUnfocused.setText(title);
+ }
+
+}
diff --git a/src/com/android/browser/UrlInputView.java b/src/com/android/browser/UrlInputView.java
new file mode 100644
index 0000000..8662f55
--- /dev/null
+++ b/src/com/android/browser/UrlInputView.java
@@ -0,0 +1,180 @@
+/*
+ * 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 com.android.browser.SuggestionsAdapter.CompletionListener;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.util.AttributeSet;
+import android.view.ActionMode;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.View.OnFocusChangeListener;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.AutoCompleteTextView;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
+
+/**
+ * url/search input view
+ * handling suggestions
+ */
+public class UrlInputView extends AutoCompleteTextView
+ implements OnFocusChangeListener, OnEditorActionListener, CompletionListener {
+
+ private UrlInputListener mListener;
+ private InputMethodManager mInputManager;
+ private SuggestionsAdapter mAdapter;
+ private OnFocusChangeListener mWrappedFocusListener;
+ private View mContainer;
+ private boolean mLandscape;
+
+ public UrlInputView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init(context);
+ }
+
+ public UrlInputView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context);
+ }
+
+ public UrlInputView(Context context) {
+ super(context);
+ init(context);
+ }
+
+ private void init(Context ctx) {
+ mInputManager = (InputMethodManager) ctx.getSystemService(Context.INPUT_METHOD_SERVICE);
+ setOnEditorActionListener(this);
+ super.setOnFocusChangeListener(this);
+ final ContentResolver cr = mContext.getContentResolver();
+ mAdapter = new SuggestionsAdapter(ctx, this);
+ setAdapter(mAdapter);
+ setSelectAllOnFocus(false);
+ onConfigurationChanged(ctx.getResources().getConfiguration());
+ }
+
+ void setContainer(View container) {
+ mContainer = container;
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration config) {
+ mLandscape = (config.orientation &
+ Configuration.ORIENTATION_LANDSCAPE) > 0;
+ if (isPopupShowing() && (getVisibility() == View.VISIBLE)) {
+ dismissDropDown();
+ getFilter().filter(getText());
+ }
+ }
+
+ @Override
+ public void showDropDown() {
+ int width = mContainer.getWidth();
+ if ((mAdapter.getLeftCount() == 0) || (mAdapter.getRightCount() == 0)) {
+ width = width / 2;
+ }
+ setDropDownWidth(width);
+ setDropDownHorizontalOffset(-getLeft());
+ mAdapter.setLandscapeMode(mLandscape);
+ super.showDropDown();
+ }
+
+ @Override
+ public ActionMode startActionMode(ActionMode.Callback callback) {
+ // suppress selection action mode
+ return null;
+ }
+
+ @Override
+ public void setOnFocusChangeListener(OnFocusChangeListener focusListener) {
+ mWrappedFocusListener = focusListener;
+ }
+
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ finishInput(getText().toString());
+ return true;
+ }
+
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ if (hasFocus) {
+ forceIme();
+ } else {
+ finishInput(null);
+ }
+ if (mWrappedFocusListener != null) {
+ mWrappedFocusListener.onFocusChange(v, hasFocus);
+ }
+ }
+
+ public void setUrlInputListener(UrlInputListener listener) {
+ mListener = listener;
+ }
+
+ public void forceIme() {
+ mInputManager.showSoftInput(this, 0);
+ }
+
+ private void finishInput(String url) {
+ this.dismissDropDown();
+ this.setSelection(0,0);
+ mInputManager.hideSoftInputFromWindow(getWindowToken(), 0);
+ if (url == null) {
+ mListener.onDismiss();
+ } else {
+ mListener.onAction(url);
+ }
+ }
+
+ // Completion Listener
+
+ @Override
+ public void onSearch(String search) {
+ mListener.onEdit(search);
+ }
+
+ @Override
+ public void onSelect(String url) {
+ finishInput(url);
+ }
+
+ @Override
+ public boolean onKeyPreIme(int keyCode, KeyEvent evt) {
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ // catch back key in order to do slightly more cleanup than usual
+ finishInput(null);
+ return true;
+ }
+ return super.onKeyPreIme(keyCode, evt);
+ }
+
+ interface UrlInputListener {
+
+ public void onDismiss();
+
+ public void onAction(String text);
+
+ public void onEdit(String text);
+
+ }
+
+}
diff --git a/src/com/android/browser/WebDialog.java b/src/com/android/browser/WebDialog.java
deleted file mode 100644
index 9995e8f..0000000
--- a/src/com/android/browser/WebDialog.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.browser;
-
-import android.content.Context;
-import android.view.View;
-import android.view.animation.AnimationUtils;
-import android.view.inputmethod.InputMethodManager;
-import android.webkit.WebView;
-import android.widget.LinearLayout;
-
-/* package */ class WebDialog extends LinearLayout {
- protected WebView mWebView;
- protected BrowserActivity mBrowserActivity;
- private boolean mIsVisible;
-
- /* package */ WebDialog(BrowserActivity context) {
- super(context);
- mBrowserActivity = context;
- }
-
- /* dialogs that have cancel buttons can optionally share code by including a
- * view with an id of 'done'.
- */
- protected void addCancel() {
- View button = findViewById(R.id.done);
- if (button != null) button.setOnClickListener(mCancelListener);
- }
-
- private View.OnClickListener mCancelListener = new View.OnClickListener() {
- public void onClick(View v) {
- mBrowserActivity.closeDialogs();
- }
- };
-
- protected void dismiss() {
- startAnimation(AnimationUtils.loadAnimation(mBrowserActivity,
- R.anim.dialog_exit));
- mIsVisible = false;
- }
-
- /*
- * Remove the soft keyboard from the screen.
- */
- protected void hideSoftInput() {
- InputMethodManager imm = (InputMethodManager)
- mBrowserActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.hideSoftInputFromWindow(mWebView.getWindowToken(), 0);
- }
-
- protected boolean isVisible() {
- return mIsVisible;
- }
-
- /* package */ void setWebView(WebView webview) {
- mWebView = webview;
- }
-
- protected void show() {
- startAnimation(AnimationUtils.loadAnimation(mBrowserActivity,
- R.anim.dialog_enter));
- mIsVisible = true;
- }
-
-}
diff --git a/src/com/android/browser/preferences/AdvancedPreferencesFragment.java b/src/com/android/browser/preferences/AdvancedPreferencesFragment.java
new file mode 100644
index 0000000..59b6ce1
--- /dev/null
+++ b/src/com/android/browser/preferences/AdvancedPreferencesFragment.java
@@ -0,0 +1,91 @@
+/*
+ * 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.preferences;
+
+import com.android.browser.BrowserSettings;
+import com.android.browser.R;
+import com.android.browser.WebsiteSettingsActivity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceScreen;
+import android.webkit.GeolocationPermissions;
+import android.webkit.ValueCallback;
+import android.webkit.WebStorage;
+
+import java.util.Map;
+import java.util.Set;
+
+public class AdvancedPreferencesFragment extends PreferenceFragment
+ implements Preference.OnPreferenceChangeListener {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Load the XML preferences file
+ addPreferencesFromResource(R.xml.advanced_preferences);
+
+ PreferenceScreen websiteSettings = (PreferenceScreen) findPreference(
+ BrowserSettings.PREF_WEBSITE_SETTINGS);
+ Intent intent = new Intent(getActivity(), WebsiteSettingsActivity.class);
+ websiteSettings.setIntent(intent);
+ }
+
+ /*
+ * We need to set the PreferenceScreen state in onResume(), as the number of
+ * origins with active features (WebStorage, Geolocation etc) could have
+ * changed after calling the WebsiteSettingsActivity.
+ */
+ @Override
+ public void onResume() {
+ super.onResume();
+ final PreferenceScreen websiteSettings = (PreferenceScreen) findPreference(
+ BrowserSettings.PREF_WEBSITE_SETTINGS);
+ websiteSettings.setEnabled(false);
+ WebStorage.getInstance().getOrigins(new ValueCallback<Map>() {
+ @Override
+ public void onReceiveValue(Map webStorageOrigins) {
+ if ((webStorageOrigins != null) && !webStorageOrigins.isEmpty()) {
+ websiteSettings.setEnabled(true);
+ }
+ }
+ });
+ GeolocationPermissions.getInstance().getOrigins(new ValueCallback<Set<String> >() {
+ @Override
+ public void onReceiveValue(Set<String> geolocationOrigins) {
+ if ((geolocationOrigins != null) && !geolocationOrigins.isEmpty()) {
+ websiteSettings.setEnabled(true);
+ }
+ }
+ });
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference pref, Object objValue) {
+ if (pref.getKey().equals(BrowserSettings.PREF_EXTRAS_RESET_DEFAULTS)) {
+ Boolean value = (Boolean) objValue;
+ if (value.booleanValue() == true) {
+ getActivity().finish();
+ return true;
+ }
+ }
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/browser/preferences/DebugPreferencesFragment.java b/src/com/android/browser/preferences/DebugPreferencesFragment.java
new file mode 100644
index 0000000..d643a97
--- /dev/null
+++ b/src/com/android/browser/preferences/DebugPreferencesFragment.java
@@ -0,0 +1,32 @@
+/*
+ * 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.preferences;
+
+import com.android.browser.R;
+
+import android.os.Bundle;
+import android.preference.PreferenceFragment;
+
+public class DebugPreferencesFragment extends PreferenceFragment {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Load the XML preferences file
+ addPreferencesFromResource(R.xml.debug_preferences);
+ }
+}
diff --git a/src/com/android/browser/preferences/PageContentPreferencesFragment.java b/src/com/android/browser/preferences/PageContentPreferencesFragment.java
new file mode 100644
index 0000000..4bb2fab
--- /dev/null
+++ b/src/com/android/browser/preferences/PageContentPreferencesFragment.java
@@ -0,0 +1,143 @@
+/*
+ * 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.preferences;
+
+import com.android.browser.BrowserHomepagePreference;
+import com.android.browser.BrowserPreferencesPage;
+import com.android.browser.BrowserSettings;
+import com.android.browser.R;
+
+import android.content.res.Resources;
+import android.net.Uri;
+import android.os.Bundle;
+import android.preference.EditTextPreference;
+import android.preference.Preference;
+import android.preference.PreferenceFragment;
+
+public class PageContentPreferencesFragment extends PreferenceFragment
+ implements Preference.OnPreferenceChangeListener {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Load the preferences from an XML resource
+ addPreferencesFromResource(R.xml.page_content_preferences);
+
+ Preference e = findPreference(BrowserSettings.PREF_HOMEPAGE);
+ e.setOnPreferenceChangeListener(this);
+ e.setSummary(getPreferenceScreen().getSharedPreferences()
+ .getString(BrowserSettings.PREF_HOMEPAGE, null));
+ ((BrowserHomepagePreference) e).setCurrentPage(
+ getActivity().getIntent().getStringExtra(BrowserPreferencesPage.CURRENT_PAGE));
+
+ e = findPreference(BrowserSettings.PREF_TEXT_SIZE);
+ e.setOnPreferenceChangeListener(this);
+ e.setSummary(getVisualTextSizeName(
+ getPreferenceScreen().getSharedPreferences()
+ .getString(BrowserSettings.PREF_TEXT_SIZE, null)) );
+
+ e = findPreference(BrowserSettings.PREF_DEFAULT_ZOOM);
+ e.setOnPreferenceChangeListener(this);
+ e.setSummary(getVisualDefaultZoomName(
+ getPreferenceScreen().getSharedPreferences()
+ .getString(BrowserSettings.PREF_DEFAULT_ZOOM, null)) );
+
+ e = findPreference(BrowserSettings.PREF_DEFAULT_TEXT_ENCODING);
+ e.setOnPreferenceChangeListener(this);
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference pref, Object objValue) {
+ if (pref.getKey().equals(BrowserSettings.PREF_HOMEPAGE)) {
+ String value = (String) objValue;
+ boolean needUpdate = value.indexOf(' ') != -1;
+ if (needUpdate) {
+ value = value.trim().replace(" ", "%20");
+ }
+ if (value.length() != 0 && Uri.parse(value).getScheme() == null) {
+ value = "http://" + value;
+ needUpdate = true;
+ }
+ // Set the summary value.
+ pref.setSummary(value);
+ if (needUpdate) {
+ // Update through the EditText control as it has a cached copy
+ // of the string and it will handle persisting the value
+ ((EditTextPreference) pref).setText(value);
+
+ // as we update the value above, we need to return false
+ // here so that setText() is not called by EditTextPref
+ // with the old value.
+ return false;
+ } else {
+ return true;
+ }
+ } else if (pref.getKey().equals(BrowserSettings.PREF_TEXT_SIZE)) {
+ pref.setSummary(getVisualTextSizeName((String) objValue));
+ return true;
+ } else if (pref.getKey().equals(BrowserSettings.PREF_DEFAULT_ZOOM)) {
+ pref.setSummary(getVisualDefaultZoomName((String) objValue));
+ return true;
+ } else if (pref.getKey().equals(BrowserSettings.PREF_DEFAULT_TEXT_ENCODING)) {
+ pref.setSummary((String) objValue);
+ return true;
+ }
+
+ return false;
+ }
+
+ private CharSequence getVisualTextSizeName(String enumName) {
+ Resources res = getActivity().getResources();
+ CharSequence[] visualNames = res.getTextArray(R.array.pref_text_size_choices);
+ CharSequence[] enumNames = res.getTextArray(R.array.pref_text_size_values);
+
+ // Sanity check
+ if (visualNames.length != enumNames.length) {
+ return "";
+ }
+
+ int length = enumNames.length;
+ for (int i = 0; i < length; i++) {
+ if (enumNames[i].equals(enumName)) {
+ return visualNames[i];
+ }
+ }
+
+ return "";
+ }
+
+ private CharSequence getVisualDefaultZoomName(String enumName) {
+ Resources res = getActivity().getResources();
+ CharSequence[] visualNames = res.getTextArray(R.array.pref_default_zoom_choices);
+ CharSequence[] enumNames = res.getTextArray(R.array.pref_default_zoom_values);
+
+ // Sanity check
+ if (visualNames.length != enumNames.length) {
+ return "";
+ }
+
+ int length = enumNames.length;
+ for (int i = 0; i < length; i++) {
+ if (enumNames[i].equals(enumName)) {
+ return visualNames[i];
+ }
+ }
+
+ return "";
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/browser/preferences/PersonalPreferencesFragment.java b/src/com/android/browser/preferences/PersonalPreferencesFragment.java
new file mode 100644
index 0000000..12751c5
--- /dev/null
+++ b/src/com/android/browser/preferences/PersonalPreferencesFragment.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.preferences;
+
+import com.android.browser.BrowserBookmarksPage;
+import com.android.browser.R;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.content.ContentProviderOperation;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.OperationApplicationException;
+import android.content.SharedPreferences;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceManager;
+import android.provider.BrowserContract;
+import android.provider.BrowserContract.Bookmarks;
+import android.provider.BrowserContract.ChromeSyncColumns;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.LinearLayout;
+
+import java.util.ArrayList;
+
+public class PersonalPreferencesFragment extends PreferenceFragment
+ implements OnPreferenceClickListener {
+ static final String TAG = "PersonalPreferencesFragment";
+
+ static final String PREF_CHROME_SYNC = "sync_with_chrome";
+
+ Preference mChromeSync;
+ boolean mEnabled;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Load the XML preferences file
+ addPreferencesFromResource(R.xml.personal_preferences);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ // Setup the proper state for the sync with chrome item
+ Context context = getActivity();
+ mChromeSync = findPreference(PREF_CHROME_SYNC);
+ refreshUi(context);
+ }
+
+ void refreshUi(Context context) {
+ AccountManager am = (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE);
+ Account[] accounts = am.getAccountsByType("com.google");
+ if (accounts == null || accounts.length == 0) {
+ // No Google accounts setup, don't offer Chrome sync
+ getPreferenceScreen().removePreference(mChromeSync);
+ } else {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ Bundle args = mChromeSync.getExtras();
+ args.putParcelableArray("accounts", accounts);
+ mEnabled = BrowserContract.Settings.isSyncEnabled(context);
+ if (!mEnabled) {
+ // Google accounts are present, but Chrome sync isn't enabled yet.
+ // Setup a link to the enable wizard
+ mChromeSync.setSummary(R.string.pref_personal_sync_with_chrome_summary);
+ } else {
+ // Chrome sync is enabled, setup a link to account switcher
+ String accountName = prefs.getString(BrowserBookmarksPage.PREF_ACCOUNT_NAME, null);
+ mChromeSync.setSummary(accountName);
+ args.putString("curAccount", accountName);
+ }
+ mChromeSync.setOnPreferenceClickListener(this);
+ }
+ }
+
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ Fragment frag;
+ if (mEnabled) {
+ frag = new AccountChooserDialog();
+ } else {
+ frag = new ImportWizardDialog();
+ }
+ frag.setArguments(preference.getExtras());
+ getFragmentManager().openTransaction()
+ .add(frag, null)
+ .commit();
+ return true;
+ }
+
+ final class AccountChooserDialog extends DialogFragment
+ implements DialogInterface.OnClickListener {
+
+ AlertDialog mDialog;
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ Bundle args = getArguments();
+ Account[] accounts = (Account[]) args.getParcelableArray("accounts");
+ String curAccount = args.getString("curAccount");
+ int length = accounts.length;
+ int curAccountOffset = 0;
+ CharSequence[] accountNames = new CharSequence[length];
+ for (int i = 0; i < length; i++) {
+ String name = accounts[i].name;
+ if (name.equals(curAccount)) {
+ curAccountOffset = i;
+ }
+ accountNames[i] = name;
+ }
+
+ mDialog = new AlertDialog.Builder(getActivity())
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setTitle("Choose account") // STOPSHIP localize
+ .setSingleChoiceItems(accountNames, curAccountOffset, this)
+ .create();
+ return mDialog;
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ String accountName = mDialog.getListView().getAdapter().getItem(which).toString();
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
+ prefs.edit().putString(BrowserBookmarksPage.PREF_ACCOUNT_NAME, accountName).apply();
+ refreshUi(getActivity());
+ dismiss();
+ }
+ }
+
+ final class ImportWizardDialog extends DialogFragment implements OnClickListener {
+ View mRemoveButton;
+ View mCancelButton;
+ String mDefaultAccount;
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ Context context = getActivity();
+ Dialog dialog = new Dialog(context);
+ dialog.setTitle(R.string.import_bookmarks_dialog_title);
+ dialog.setContentView(R.layout.import_bookmarks_dialog);
+ mRemoveButton = dialog.findViewById(R.id.remove);
+ mRemoveButton.setOnClickListener(this);
+ mCancelButton = dialog.findViewById(R.id.cancel);
+ mCancelButton.setOnClickListener(this);
+
+ LayoutInflater inflater = dialog.getLayoutInflater();
+ LinearLayout accountList = (LinearLayout) dialog.findViewById(R.id.accountList);
+ Account[] accounts = (Account[]) getArguments().getParcelableArray("accounts");
+ mDefaultAccount = accounts[0].name;
+ int length = accounts.length;
+ for (int i = 0; i < length; i++) {
+ Button button = (Button) inflater.inflate(R.layout.import_bookmarks_dialog_button,
+ null);
+ button.setText(context.getString(R.string.import_bookmarks_dialog_import,
+ accounts[i].name));
+ button.setTag(accounts[i].name);
+ button.setOnClickListener(this);
+ accountList.addView(button);
+ }
+
+ return dialog;
+ }
+
+ @Override
+ public void onClick(View view) {
+ if (view == mCancelButton) {
+ dismiss();
+ return;
+ }
+
+ ContentResolver resolver = getActivity().getContentResolver();
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
+ String accountName;
+ if (view == mRemoveButton) {
+ // The user chose to remove their old bookmarks, delete them now
+ resolver.delete(Bookmarks.CONTENT_URI,
+ Bookmarks.PARENT + "=1 AND " + Bookmarks.ACCOUNT_NAME + " IS NULL", null);
+ accountName = mDefaultAccount;
+ } else {
+ // The user chose to migrate their old bookmarks to the account they're syncing
+ accountName = view.getTag().toString();
+ migrateBookmarks(resolver, accountName);
+ }
+
+ // Record the fact that we turned on sync
+ BrowserContract.Settings.setSyncEnabled(getActivity(), true);
+ prefs.edit()
+ .putString(BrowserBookmarksPage.PREF_ACCOUNT_TYPE, "com.google")
+ .putString(BrowserBookmarksPage.PREF_ACCOUNT_NAME, accountName)
+ .apply();
+
+ // Enable bookmark sync on all accounts
+ Account[] accounts = (Account[]) getArguments().getParcelableArray("accounts");
+ for (Account account : accounts) {
+ ContentResolver.setIsSyncable(account, BrowserContract.AUTHORITY, 1);
+ }
+
+ refreshUi(getActivity());
+ dismiss();
+ }
+
+ /**
+ * Migrates bookmarks to the given account
+ */
+ void migrateBookmarks(ContentResolver resolver, String accountName) {
+ Cursor cursor = null;
+ try {
+ // Re-parent the bookmarks in the default root folder
+ cursor = resolver.query(Bookmarks.CONTENT_URI, new String[] { Bookmarks._ID },
+ Bookmarks.ACCOUNT_NAME + " =? AND " +
+ ChromeSyncColumns.SERVER_UNIQUE + " =?",
+ new String[] { accountName,
+ ChromeSyncColumns.FOLDER_NAME_BOOKMARKS_BAR },
+ null);
+ ContentValues values = new ContentValues();
+ if (cursor == null || !cursor.moveToFirst()) {
+ // The root folders don't exist for the account, create them now
+ ArrayList<ContentProviderOperation> ops =
+ new ArrayList<ContentProviderOperation>();
+
+ // Chrome sync root folder
+ values.clear();
+ values.put(ChromeSyncColumns.SERVER_UNIQUE, ChromeSyncColumns.FOLDER_NAME_ROOT);
+ values.put(Bookmarks.TITLE, "Google Chrome");
+ values.put(Bookmarks.POSITION, 0);
+ values.put(Bookmarks.IS_FOLDER, true);
+ values.put(Bookmarks.DIRTY, true);
+ ops.add(ContentProviderOperation.newInsert(
+ Bookmarks.CONTENT_URI.buildUpon().appendQueryParameter(
+ BrowserContract.CALLER_IS_SYNCADAPTER, "true").build())
+ .withValues(values)
+ .build());
+
+ // Bookmarks folder
+ values.clear();
+ values.put(ChromeSyncColumns.SERVER_UNIQUE,
+ ChromeSyncColumns.FOLDER_NAME_BOOKMARKS);
+ values.put(Bookmarks.TITLE, "Bookmarks");
+ values.put(Bookmarks.POSITION, 0);
+ values.put(Bookmarks.IS_FOLDER, true);
+ values.put(Bookmarks.DIRTY, true);
+ ops.add(ContentProviderOperation.newInsert(Bookmarks.CONTENT_URI)
+ .withValues(values)
+ .withValueBackReference(Bookmarks.PARENT, 0)
+ .build());
+
+ // Bookmarks Bar folder
+ values.clear();
+ values.put(ChromeSyncColumns.SERVER_UNIQUE,
+ ChromeSyncColumns.FOLDER_NAME_BOOKMARKS_BAR);
+ values.put(Bookmarks.TITLE, "Bookmarks Bar");
+ values.put(Bookmarks.POSITION, 0);
+ values.put(Bookmarks.IS_FOLDER, true);
+ values.put(Bookmarks.DIRTY, true);
+ ops.add(ContentProviderOperation.newInsert(Bookmarks.CONTENT_URI)
+ .withValues(values)
+ .withValueBackReference(Bookmarks.PARENT, 1)
+ .build());
+
+ // Other Bookmarks folder
+ values.clear();
+ values.put(ChromeSyncColumns.SERVER_UNIQUE,
+ ChromeSyncColumns.FOLDER_NAME_OTHER_BOOKMARKS);
+ values.put(Bookmarks.TITLE, "Other Bookmarks");
+ values.put(Bookmarks.POSITION, 1000);
+ values.put(Bookmarks.IS_FOLDER, true);
+ values.put(Bookmarks.DIRTY, true);
+ ops.add(ContentProviderOperation.newInsert(Bookmarks.CONTENT_URI)
+ .withValues(values)
+ .withValueBackReference(Bookmarks.PARENT, 1)
+ .build());
+
+ // Re-parent the existing bookmarks to the newly create bookmarks bar folder
+ ops.add(ContentProviderOperation.newUpdate(Bookmarks.CONTENT_URI)
+ .withValueBackReference(Bookmarks.PARENT, 2)
+ .withSelection(Bookmarks.PARENT + "=?",
+ new String[] { Integer.toString(1) })
+ .build());
+
+ // Mark all non-root folder items as belonging to the new account
+ values.clear();
+ values.put(Bookmarks.ACCOUNT_TYPE, "com.google");
+ values.put(Bookmarks.ACCOUNT_NAME, accountName);
+ ops.add(ContentProviderOperation.newUpdate(Bookmarks.CONTENT_URI)
+ .withValues(values)
+ .withSelection(Bookmarks.ACCOUNT_NAME + " IS NULL AND " +
+ Bookmarks._ID + "<>1", null)
+ .build());
+
+ try {
+ resolver.applyBatch(BrowserContract.AUTHORITY, ops);
+ } catch (RemoteException e) {
+ Log.e(TAG, "failed to create root folder for account " + accountName, e);
+ return;
+ } catch (OperationApplicationException e) {
+ Log.e(TAG, "failed to create root folder for account " + accountName, e);
+ return;
+ }
+ } else {
+ values.put(Bookmarks.PARENT, cursor.getLong(0));
+ resolver.update(Bookmarks.CONTENT_URI, values, Bookmarks.PARENT + "=?",
+ new String[] { Integer.toString(1) });
+
+ // Mark all bookmarks at all levels as part of the new account
+ values.clear();
+ values.put(Bookmarks.ACCOUNT_TYPE, "com.google");
+ values.put(Bookmarks.ACCOUNT_NAME, accountName);
+ resolver.update(Bookmarks.CONTENT_URI, values,
+ Bookmarks.ACCOUNT_NAME + " IS NULL AND " + Bookmarks._ID + "<>1",
+ null);
+ }
+ } finally {
+ if (cursor != null) cursor.close();
+ }
+ }
+ }
+}
diff --git a/src/com/android/browser/preferences/PrivacyPreferencesFragment.java b/src/com/android/browser/preferences/PrivacyPreferencesFragment.java
new file mode 100644
index 0000000..79f2084
--- /dev/null
+++ b/src/com/android/browser/preferences/PrivacyPreferencesFragment.java
@@ -0,0 +1,55 @@
+/*
+ * 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.preferences;
+
+import com.android.browser.BrowserSettings;
+import com.android.browser.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.PreferenceFragment;
+
+public class PrivacyPreferencesFragment extends PreferenceFragment
+ implements Preference.OnPreferenceChangeListener {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Load the preferences from an XML resource
+ addPreferencesFromResource(R.xml.privacy_preferences);
+
+ Preference e = findPreference(BrowserSettings.PREF_CLEAR_HISTORY);
+ e.setOnPreferenceChangeListener(this);
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference pref, Object objValue) {
+ 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
+ getActivity().setResult(Activity.RESULT_OK, (new Intent()).putExtra(Intent.EXTRA_TEXT,
+ pref.getKey()));
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/src/com/android/browser/preferences/SecurityPreferencesFragment.java b/src/com/android/browser/preferences/SecurityPreferencesFragment.java
new file mode 100644
index 0000000..d20a50c
--- /dev/null
+++ b/src/com/android/browser/preferences/SecurityPreferencesFragment.java
@@ -0,0 +1,32 @@
+/*
+ * 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.preferences;
+
+import com.android.browser.R;
+
+import android.os.Bundle;
+import android.preference.PreferenceFragment;
+
+public class SecurityPreferencesFragment extends PreferenceFragment {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Load the XML preferences file
+ addPreferencesFromResource(R.xml.security_preferences);
+ }
+}
diff --git a/src/com/android/browser/provider/BrowserProvider2.java b/src/com/android/browser/provider/BrowserProvider2.java
new file mode 100644
index 0000000..b73927a
--- /dev/null
+++ b/src/com/android/browser/provider/BrowserProvider2.java
@@ -0,0 +1,1117 @@
+/*
+ * Copyright (C) 2010 he 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.provider;
+
+import com.android.browser.R;
+import com.android.internal.content.SyncStateContentProviderHelper;
+
+import android.accounts.Account;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.UriMatcher;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.net.Uri;
+import android.provider.BrowserContract;
+import android.provider.BrowserContract.Accounts;
+import android.provider.BrowserContract.Bookmarks;
+import android.provider.BrowserContract.ChromeSyncColumns;
+import android.provider.BrowserContract.Combined;
+import android.provider.BrowserContract.History;
+import android.provider.BrowserContract.Images;
+import android.provider.BrowserContract.Searches;
+import android.provider.BrowserContract.Settings;
+import android.provider.BrowserContract.SyncState;
+import android.provider.ContactsContract.RawContacts;
+import android.provider.SyncStateContract;
+import android.text.TextUtils;
+
+import java.util.HashMap;
+
+public class BrowserProvider2 extends SQLiteContentProvider {
+
+ static final String LEGACY_AUTHORITY = "browser";
+ static final Uri LEGACY_AUTHORITY_URI = new Uri.Builder().authority(LEGACY_AUTHORITY).build();
+
+ static final String TABLE_BOOKMARKS = "bookmarks";
+ static final String TABLE_HISTORY = "history";
+ static final String TABLE_IMAGES = "images";
+ static final String TABLE_SEARCHES = "searches";
+ static final String TABLE_SYNC_STATE = "syncstate";
+ static final String TABLE_SETTINGS = "settings";
+ static final String VIEW_COMBINED = "combined";
+
+ static final String TABLE_BOOKMARKS_JOIN_IMAGES = "bookmarks LEFT OUTER JOIN images " +
+ "ON bookmarks.url = images." + Images.URL;
+ static final String TABLE_HISTORY_JOIN_IMAGES = "history LEFT OUTER JOIN images " +
+ "ON history.url = images." + Images.URL;
+
+ static final String DEFAULT_SORT_HISTORY = History.DATE_LAST_VISITED + " DESC";
+
+ static final String DEFAULT_SORT_SEARCHES = Searches.DATE + " DESC";
+
+ static final int BOOKMARKS = 1000;
+ static final int BOOKMARKS_ID = 1001;
+ static final int BOOKMARKS_FOLDER = 1002;
+ static final int BOOKMARKS_FOLDER_ID = 1003;
+
+ static final int HISTORY = 2000;
+ static final int HISTORY_ID = 2001;
+
+ static final int SEARCHES = 3000;
+ static final int SEARCHES_ID = 3001;
+
+ static final int SYNCSTATE = 4000;
+ static final int SYNCSTATE_ID = 4001;
+
+ static final int IMAGES = 5000;
+
+ static final int COMBINED = 6000;
+ static final int COMBINED_ID = 6001;
+
+ static final int ACCOUNTS = 7000;
+
+ static final int SETTINGS = 8000;
+
+ public static final long FIXED_ID_ROOT = 1;
+
+ static final String DEFAULT_BOOKMARKS_SORT_ORDER = "position ASC, _id ASC";
+
+ static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
+
+ static final HashMap<String, String> ACCOUNTS_PROJECTION_MAP = new HashMap<String, String>();
+ static final HashMap<String, String> BOOKMARKS_PROJECTION_MAP = new HashMap<String, String>();
+ static final HashMap<String, String> OTHER_BOOKMARKS_PROJECTION_MAP =
+ new HashMap<String, String>();
+ static final HashMap<String, String> HISTORY_PROJECTION_MAP = new HashMap<String, String>();
+ static final HashMap<String, String> SYNC_STATE_PROJECTION_MAP = new HashMap<String, String>();
+ static final HashMap<String, String> IMAGES_PROJECTION_MAP = new HashMap<String, String>();
+ static final HashMap<String, String> COMBINED_PROJECTION_MAP = new HashMap<String, String>();
+ static final HashMap<String, String> SEARCHES_PROJECTION_MAP = new HashMap<String, String>();
+ static final HashMap<String, String> SETTINGS_PROJECTION_MAP = new HashMap<String, String>();
+
+ static {
+ final UriMatcher matcher = URI_MATCHER;
+ final String authority = BrowserContract.AUTHORITY;
+ matcher.addURI(authority, "accounts", ACCOUNTS);
+ matcher.addURI(authority, "bookmarks", BOOKMARKS);
+ matcher.addURI(authority, "bookmarks/#", BOOKMARKS_ID);
+ matcher.addURI(authority, "bookmarks/folder", BOOKMARKS_FOLDER);
+ matcher.addURI(authority, "bookmarks/folder/#", BOOKMARKS_FOLDER_ID);
+ matcher.addURI(authority, "history", HISTORY);
+ matcher.addURI(authority, "history/#", HISTORY_ID);
+ matcher.addURI(authority, "searches", SEARCHES);
+ matcher.addURI(authority, "searches/#", SEARCHES_ID);
+ matcher.addURI(authority, "syncstate", SYNCSTATE);
+ matcher.addURI(authority, "syncstate/#", SYNCSTATE_ID);
+ matcher.addURI(authority, "images", IMAGES);
+ matcher.addURI(authority, "combined", COMBINED);
+ matcher.addURI(authority, "combined/#", COMBINED_ID);
+ matcher.addURI(authority, "settings", SETTINGS);
+
+ // Projection maps
+ HashMap<String, String> map;
+
+ // Accounts
+ map = ACCOUNTS_PROJECTION_MAP;
+ map.put(Accounts.ACCOUNT_TYPE, Accounts.ACCOUNT_TYPE);
+ map.put(Accounts.ACCOUNT_NAME, Accounts.ACCOUNT_NAME);
+
+ // Bookmarks
+ map = BOOKMARKS_PROJECTION_MAP;
+ map.put(Bookmarks._ID, qualifyColumn(TABLE_BOOKMARKS, Bookmarks._ID));
+ map.put(Bookmarks.TITLE, Bookmarks.TITLE);
+ map.put(Bookmarks.URL, Bookmarks.URL);
+ map.put(Bookmarks.FAVICON, Bookmarks.FAVICON);
+ map.put(Bookmarks.THUMBNAIL, Bookmarks.THUMBNAIL);
+ map.put(Bookmarks.TOUCH_ICON, Bookmarks.TOUCH_ICON);
+ map.put(Bookmarks.IS_FOLDER, Bookmarks.IS_FOLDER);
+ map.put(Bookmarks.PARENT, Bookmarks.PARENT);
+ map.put(Bookmarks.POSITION, Bookmarks.POSITION);
+ map.put(Bookmarks.INSERT_AFTER, Bookmarks.INSERT_AFTER);
+ map.put(Bookmarks.IS_DELETED, Bookmarks.IS_DELETED);
+ map.put(Bookmarks.ACCOUNT_NAME, Bookmarks.ACCOUNT_NAME);
+ map.put(Bookmarks.ACCOUNT_TYPE, Bookmarks.ACCOUNT_TYPE);
+ map.put(Bookmarks.SOURCE_ID, Bookmarks.SOURCE_ID);
+ map.put(Bookmarks.VERSION, Bookmarks.VERSION);
+ map.put(Bookmarks.DATE_CREATED, Bookmarks.DATE_CREATED);
+ map.put(Bookmarks.DATE_MODIFIED, Bookmarks.DATE_MODIFIED);
+ map.put(Bookmarks.DIRTY, Bookmarks.DIRTY);
+ map.put(Bookmarks.SYNC1, Bookmarks.SYNC1);
+ map.put(Bookmarks.SYNC2, Bookmarks.SYNC2);
+ map.put(Bookmarks.SYNC3, Bookmarks.SYNC3);
+ map.put(Bookmarks.SYNC4, Bookmarks.SYNC4);
+ map.put(Bookmarks.SYNC5, Bookmarks.SYNC5);
+ map.put(Bookmarks.PARENT_SOURCE_ID, "(SELECT " + Bookmarks.SOURCE_ID +
+ " FROM " + TABLE_BOOKMARKS + " A WHERE " +
+ "A." + Bookmarks._ID + "=" + TABLE_BOOKMARKS + "." + Bookmarks.PARENT +
+ ") AS " + Bookmarks.PARENT_SOURCE_ID);
+ map.put(Bookmarks.INSERT_AFTER_SOURCE_ID, "(SELECT " + Bookmarks.SOURCE_ID +
+ " FROM " + TABLE_BOOKMARKS + " A WHERE " +
+ "A." + Bookmarks._ID + "=" + TABLE_BOOKMARKS + "." + Bookmarks.INSERT_AFTER +
+ ") AS " + Bookmarks.INSERT_AFTER_SOURCE_ID);
+
+ // Other bookmarks
+ OTHER_BOOKMARKS_PROJECTION_MAP.putAll(BOOKMARKS_PROJECTION_MAP);
+ OTHER_BOOKMARKS_PROJECTION_MAP.put(Bookmarks.POSITION,
+ Long.toString(Long.MAX_VALUE) + " AS " + Bookmarks.POSITION);
+
+ // History
+ map = HISTORY_PROJECTION_MAP;
+ map.put(History._ID, qualifyColumn(TABLE_HISTORY, History._ID));
+ map.put(History.TITLE, History.TITLE);
+ map.put(History.URL, History.URL);
+ map.put(History.FAVICON, History.FAVICON);
+ map.put(History.THUMBNAIL, History.THUMBNAIL);
+ map.put(History.TOUCH_ICON, History.TOUCH_ICON);
+ map.put(History.DATE_CREATED, History.DATE_CREATED);
+ map.put(History.DATE_LAST_VISITED, History.DATE_LAST_VISITED);
+ map.put(History.VISITS, History.VISITS);
+ map.put(History.USER_ENTERED, History.USER_ENTERED);
+
+ // Sync state
+ map = SYNC_STATE_PROJECTION_MAP;
+ map.put(SyncState._ID, SyncState._ID);
+ map.put(SyncState.ACCOUNT_NAME, SyncState.ACCOUNT_NAME);
+ map.put(SyncState.ACCOUNT_TYPE, SyncState.ACCOUNT_TYPE);
+ map.put(SyncState.DATA, SyncState.DATA);
+
+ // Images
+ map = IMAGES_PROJECTION_MAP;
+ map.put(Images.URL, Images.URL);
+ map.put(Images.FAVICON, Images.FAVICON);
+ map.put(Images.THUMBNAIL, Images.THUMBNAIL);
+ map.put(Images.TOUCH_ICON, Images.TOUCH_ICON);
+
+ // Combined history half
+ map = COMBINED_PROJECTION_MAP;
+ map.put(Combined._ID, Combined._ID);
+ map.put(Combined.TITLE, Combined.TITLE);
+ map.put(Combined.URL, Combined.URL);
+ map.put(Combined.DATE_CREATED, Combined.DATE_CREATED);
+ map.put(Combined.DATE_LAST_VISITED, Combined.DATE_LAST_VISITED);
+ map.put(Combined.IS_BOOKMARK, Combined.IS_BOOKMARK);
+ map.put(Combined.VISITS, Combined.VISITS);
+ map.put(Combined.FAVICON, Combined.FAVICON);
+ map.put(Combined.THUMBNAIL, Combined.THUMBNAIL);
+ map.put(Combined.TOUCH_ICON, Combined.TOUCH_ICON);
+ map.put(Combined.USER_ENTERED, Combined.USER_ENTERED);
+
+ // Searches
+ map = SEARCHES_PROJECTION_MAP;
+ map.put(Searches._ID, Searches._ID);
+ map.put(Searches.SEARCH, Searches.SEARCH);
+ map.put(Searches.DATE, Searches.DATE);
+
+ // Settings
+ map = SETTINGS_PROJECTION_MAP;
+ map.put(Settings.KEY, Settings.KEY);
+ map.put(Settings.VALUE, Settings.VALUE);
+ }
+
+ static final String bookmarkOrHistoryColumn(String column) {
+ return "CASE WHEN bookmarks." + column + " IS NOT NULL THEN " +
+ "bookmarks." + column + " ELSE history." + column + " END AS " + column;
+ }
+
+ static final String qualifyColumn(String table, String column) {
+ return table + "." + column + " AS " + column;
+ }
+
+ DatabaseHelper mOpenHelper;
+ SyncStateContentProviderHelper mSyncHelper = new SyncStateContentProviderHelper();
+
+ final class DatabaseHelper extends SQLiteOpenHelper {
+ static final String DATABASE_NAME = "browser2.db";
+ static final int DATABASE_VERSION = 25;
+ public DatabaseHelper(Context context) {
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ db.execSQL("CREATE TABLE " + TABLE_BOOKMARKS + "(" +
+ Bookmarks._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
+ Bookmarks.TITLE + " TEXT," +
+ Bookmarks.URL + " TEXT," +
+ Bookmarks.IS_FOLDER + " INTEGER NOT NULL DEFAULT 0," +
+ Bookmarks.PARENT + " INTEGER," +
+ Bookmarks.POSITION + " INTEGER NOT NULL," +
+ Bookmarks.INSERT_AFTER + " INTEGER," +
+ Bookmarks.IS_DELETED + " INTEGER NOT NULL DEFAULT 0," +
+ Bookmarks.ACCOUNT_NAME + " TEXT," +
+ Bookmarks.ACCOUNT_TYPE + " TEXT," +
+ Bookmarks.SOURCE_ID + " TEXT," +
+ Bookmarks.VERSION + " INTEGER NOT NULL DEFAULT 1," +
+ Bookmarks.DATE_CREATED + " INTEGER," +
+ Bookmarks.DATE_MODIFIED + " INTEGER," +
+ Bookmarks.DIRTY + " INTEGER NOT NULL DEFAULT 0," +
+ Bookmarks.SYNC1 + " TEXT," +
+ Bookmarks.SYNC2 + " TEXT," +
+ Bookmarks.SYNC3 + " TEXT," +
+ Bookmarks.SYNC4 + " TEXT," +
+ Bookmarks.SYNC5 + " TEXT" +
+ ");");
+
+ // TODO indices
+
+ createDefaultBookmarks(db);
+
+ db.execSQL("CREATE TABLE " + TABLE_HISTORY + "(" +
+ History._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
+ History.TITLE + " TEXT," +
+ History.URL + " TEXT NOT NULL," +
+ History.DATE_CREATED + " INTEGER," +
+ History.DATE_LAST_VISITED + " INTEGER," +
+ History.VISITS + " INTEGER NOT NULL DEFAULT 0," +
+ History.USER_ENTERED + " INTEGER" +
+ ");");
+
+ db.execSQL("CREATE TABLE " + TABLE_IMAGES + " (" +
+ Images.URL + " TEXT UNIQUE NOT NULL," +
+ Images.FAVICON + " BLOB," +
+ Images.THUMBNAIL + " BLOB," +
+ Images.TOUCH_ICON + " BLOB" +
+ ");");
+ db.execSQL("CREATE INDEX imagesUrlIndex ON " + TABLE_IMAGES +
+ "(" + Images.URL + ")");
+
+ db.execSQL("CREATE TABLE " + TABLE_SEARCHES + " (" +
+ Searches._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
+ Searches.SEARCH + " TEXT," +
+ Searches.DATE + " LONG" +
+ ");");
+
+ db.execSQL("CREATE TABLE " + TABLE_SETTINGS + " (" +
+ Settings.KEY + " TEXT PRIMARY KEY," +
+ Settings.VALUE + " TEXT NOT NULL" +
+ ");");
+
+ db.execSQL("CREATE VIEW " + VIEW_COMBINED + " AS " +
+ "SELECT " +
+ bookmarkOrHistoryColumn(Combined._ID) + ", " +
+ bookmarkOrHistoryColumn(Combined.TITLE) + ", " +
+ qualifyColumn(TABLE_HISTORY, Combined.URL) + ", " +
+ qualifyColumn(TABLE_HISTORY, Combined.DATE_CREATED) + ", " +
+ Combined.DATE_LAST_VISITED + ", " +
+ "CASE WHEN bookmarks._id IS NOT NULL THEN 1 ELSE 0 END AS " + Combined.IS_BOOKMARK + ", " +
+ Combined.VISITS + ", " +
+ Combined.FAVICON + ", " +
+ Combined.THUMBNAIL + ", " +
+ Combined.TOUCH_ICON + ", " +
+ "NULL AS " + Combined.USER_ENTERED + " "+
+ "FROM history LEFT OUTER JOIN bookmarks ON history.url = bookmarks.url LEFT OUTER JOIN images ON history.url = images.url_key " +
+
+ "UNION ALL " +
+
+ "SELECT " +
+ Combined._ID + ", " +
+ Combined.TITLE + ", " +
+ Combined.URL + ", " +
+ Combined.DATE_CREATED + ", " +
+ "NULL AS " + Combined.DATE_LAST_VISITED + ", "+
+ "1 AS " + Combined.IS_BOOKMARK + ", " +
+ "0 AS " + Combined.VISITS + ", "+
+ Combined.FAVICON + ", " +
+ Combined.THUMBNAIL + ", " +
+ Combined.TOUCH_ICON + ", " +
+ "NULL AS " + Combined.USER_ENTERED + " "+
+ "FROM bookmarks LEFT OUTER JOIN images ON bookmarks.url = images.url_key WHERE url NOT IN (SELECT url FROM history)");
+
+ mSyncHelper.createDatabase(db);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ // TODO write upgrade logic
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_BOOKMARKS);
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_HISTORY);
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_SEARCHES);
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_IMAGES);
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_SETTINGS);
+ db.execSQL("DROP VIEW IF EXISTS " + VIEW_COMBINED);
+ mSyncHelper.onAccountsChanged(db, new Account[] {}); // remove all sync info
+ onCreate(db);
+ }
+
+ @Override
+ public void onOpen(SQLiteDatabase db) {
+ mSyncHelper.onDatabaseOpened(db);
+ }
+
+ private void createDefaultBookmarks(SQLiteDatabase db) {
+ ContentValues values = new ContentValues();
+ // TODO figure out how to deal with localization for the defaults
+
+ // Bookmarks folder
+ values.put(Bookmarks._ID, FIXED_ID_ROOT);
+ values.put(ChromeSyncColumns.SERVER_UNIQUE, ChromeSyncColumns.FOLDER_NAME_BOOKMARKS);
+ values.put(Bookmarks.TITLE, "Bookmarks");
+ values.putNull(Bookmarks.PARENT);
+ values.put(Bookmarks.POSITION, 0);
+ values.put(Bookmarks.IS_FOLDER, true);
+ values.put(Bookmarks.DIRTY, true);
+ db.insertOrThrow(TABLE_BOOKMARKS, null, values);
+
+ addDefaultBookmarks(db, FIXED_ID_ROOT);
+ }
+
+ private void addDefaultBookmarks(SQLiteDatabase db, long parentId) {
+ final CharSequence[] bookmarks = getContext().getResources().getTextArray(
+ R.array.bookmarks);
+ int size = bookmarks.length;
+ try {
+ String parent = Long.toString(parentId);
+ String now = Long.toString(System.currentTimeMillis());
+ for (int i = 0; i < size; i = i + 2) {
+ CharSequence bookmarkDestination = replaceSystemPropertyInString(getContext(),
+ bookmarks[i + 1]);
+ db.execSQL("INSERT INTO bookmarks (" +
+ Bookmarks.TITLE + ", " +
+ Bookmarks.URL + ", " +
+ Bookmarks.IS_FOLDER + "," +
+ Bookmarks.PARENT + "," +
+ Bookmarks.POSITION + "," +
+ Bookmarks.DATE_CREATED +
+ ") VALUES (" +
+ "'" + bookmarks[i] + "', " +
+ "'" + bookmarkDestination + "', " +
+ "0," +
+ parent + "," +
+ Integer.toString(i) + "," +
+ now +
+ ");");
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ }
+ }
+
+ // XXX: This is a major hack to remove our dependency on gsf constants and
+ // its content provider. http://b/issue?id=2425179
+ private 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 CharSequence replaceSystemPropertyInString(Context context, CharSequence srcString) {
+ StringBuffer sb = new StringBuffer();
+ int lastCharLoc = 0;
+
+ final String client_id = getClientId(context.getContentResolver());
+
+ for (int i = 0; i < srcString.length(); ++i) {
+ char c = srcString.charAt(i);
+ if (c == '{') {
+ sb.append(srcString.subSequence(lastCharLoc, i));
+ lastCharLoc = i;
+ inner:
+ for (int j = i; j < srcString.length(); ++j) {
+ char k = srcString.charAt(j);
+ if (k == '}') {
+ String propertyKeyValue = srcString.subSequence(i + 1, j).toString();
+ if (propertyKeyValue.equals("CLIENT_ID")) {
+ sb.append(client_id);
+ } else {
+ sb.append("unknown");
+ }
+ lastCharLoc = j + 1;
+ i = j;
+ break inner;
+ }
+ }
+ }
+ }
+ if (srcString.length() - lastCharLoc > 0) {
+ // Put on the tail, if there is one
+ sb.append(srcString.subSequence(lastCharLoc, srcString.length()));
+ }
+ return sb;
+ }
+ }
+
+ @Override
+ public SQLiteOpenHelper getDatabaseHelper(Context context) {
+ synchronized (this) {
+ if (mOpenHelper == null) {
+ mOpenHelper = new DatabaseHelper(context);
+ }
+ return mOpenHelper;
+ }
+ }
+
+ @Override
+ public boolean isCallerSyncAdapter(Uri uri) {
+ return uri.getBooleanQueryParameter(BrowserContract.CALLER_IS_SYNCADAPTER, false);
+ }
+
+ @Override
+ public void notifyChange(boolean callerIsSyncAdapter) {
+ ContentResolver resolver = getContext().getContentResolver();
+ resolver.notifyChange(BrowserContract.AUTHORITY_URI, null, !callerIsSyncAdapter);
+ resolver.notifyChange(LEGACY_AUTHORITY_URI, null, !callerIsSyncAdapter);
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ final int match = URI_MATCHER.match(uri);
+ switch (match) {
+ case BOOKMARKS:
+ return Bookmarks.CONTENT_TYPE;
+ case BOOKMARKS_ID:
+ return Bookmarks.CONTENT_ITEM_TYPE;
+ case HISTORY:
+ return History.CONTENT_TYPE;
+ case HISTORY_ID:
+ return History.CONTENT_ITEM_TYPE;
+ case SEARCHES:
+ return Searches.CONTENT_TYPE;
+ case SEARCHES_ID:
+ return Searches.CONTENT_ITEM_TYPE;
+// case SUGGEST:
+// return SearchManager.SUGGEST_MIME_TYPE;
+ }
+ return null;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ final int match = URI_MATCHER.match(uri);
+ SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
+ String limit = uri.getQueryParameter(BrowserContract.PARAM_LIMIT);
+ switch (match) {
+ case ACCOUNTS: {
+ qb.setTables(TABLE_BOOKMARKS);
+ qb.setProjectionMap(ACCOUNTS_PROJECTION_MAP);
+ qb.setDistinct(true);
+ qb.appendWhere(Bookmarks.ACCOUNT_NAME + " IS NOT NULL");
+ break;
+ }
+
+ case BOOKMARKS_FOLDER_ID:
+ case BOOKMARKS_ID:
+ case BOOKMARKS: {
+ // Only show deleted bookmarks if requested to do so
+ if (!uri.getBooleanQueryParameter(Bookmarks.QUERY_PARAMETER_SHOW_DELETED, false)) {
+ selection = DatabaseUtils.concatenateWhere(
+ Bookmarks.IS_DELETED + "=0", selection);
+ }
+
+ if (match == BOOKMARKS_ID) {
+ // Tack on the ID of the specific bookmark requested
+ selection = DatabaseUtils.concatenateWhere(selection,
+ TABLE_BOOKMARKS + "." + Bookmarks._ID + "=?");
+ selectionArgs = DatabaseUtils.appendSelectionArgs(selectionArgs,
+ new String[] { Long.toString(ContentUris.parseId(uri)) });
+ } else if (match == BOOKMARKS_FOLDER_ID) {
+ // Tack on the ID of the specific folder requested
+ selection = DatabaseUtils.concatenateWhere(selection,
+ TABLE_BOOKMARKS + "." + Bookmarks.PARENT + "=?");
+ selectionArgs = DatabaseUtils.appendSelectionArgs(selectionArgs,
+ new String[] { Long.toString(ContentUris.parseId(uri)) });
+ }
+
+ // Look for account info
+ String accountType = uri.getQueryParameter(Bookmarks.PARAM_ACCOUNT_TYPE);
+ String accountName = uri.getQueryParameter(Bookmarks.PARAM_ACCOUNT_NAME);
+ if (!TextUtils.isEmpty(accountType) && !TextUtils.isEmpty(accountName)) {
+ selection = DatabaseUtils.concatenateWhere(selection,
+ Bookmarks.ACCOUNT_TYPE + "=? AND " + Bookmarks.ACCOUNT_NAME + "=? ");
+ selectionArgs = DatabaseUtils.appendSelectionArgs(selectionArgs,
+ new String[] { accountType, accountName });
+ }
+
+ // Set a default sort order if one isn't specified
+ if (TextUtils.isEmpty(sortOrder)) {
+ sortOrder = DEFAULT_BOOKMARKS_SORT_ORDER;
+ }
+
+ qb.setProjectionMap(BOOKMARKS_PROJECTION_MAP);
+ qb.setTables(TABLE_BOOKMARKS_JOIN_IMAGES);
+ break;
+ }
+
+ case BOOKMARKS_FOLDER: {
+ // Don't allow selections to be applied to the default folder
+ if (!TextUtils.isEmpty(selection) || selectionArgs != null) {
+ throw new UnsupportedOperationException(
+ "selections aren't supported on this URI");
+ }
+
+ // Look for an account
+ boolean useAccount = false;
+ String accountType = uri.getQueryParameter(Bookmarks.PARAM_ACCOUNT_TYPE);
+ String accountName = uri.getQueryParameter(Bookmarks.PARAM_ACCOUNT_NAME);
+ if (!TextUtils.isEmpty(accountType) && !TextUtils.isEmpty(accountName)) {
+ useAccount = true;
+ }
+
+ qb.setTables(TABLE_BOOKMARKS_JOIN_IMAGES);
+ String[] args;
+ String query;
+ if (!useAccount) {
+ qb.setProjectionMap(BOOKMARKS_PROJECTION_MAP);
+ query = qb.buildQuery(projection,
+ Bookmarks.PARENT + "=? AND " + Bookmarks.IS_DELETED + "=0",
+ null, null, null, null, null);
+
+ args = new String[] { Long.toString(FIXED_ID_ROOT) };
+ } else {
+ qb.setProjectionMap(BOOKMARKS_PROJECTION_MAP);
+ String bookmarksBarQuery = qb.buildQuery(projection,
+ Bookmarks.ACCOUNT_TYPE + "=? AND " + Bookmarks.ACCOUNT_NAME + "=? " +
+ "AND parent = " +
+ "(SELECT _id FROM " + TABLE_BOOKMARKS + " WHERE " +
+ ChromeSyncColumns.SERVER_UNIQUE + "=" +
+ "'" + ChromeSyncColumns.FOLDER_NAME_BOOKMARKS_BAR + "' " +
+ "AND account_type = ? AND account_name = ?) " +
+ "AND " + Bookmarks.IS_DELETED + "=0",
+ null, null, null, null, null);
+
+ qb.setProjectionMap(OTHER_BOOKMARKS_PROJECTION_MAP);
+ String otherBookmarksQuery = qb.buildQuery(projection,
+ Bookmarks.ACCOUNT_TYPE + "=? AND " + Bookmarks.ACCOUNT_NAME + "=?" +
+ " AND " + ChromeSyncColumns.SERVER_UNIQUE + "=?",
+ null, null, null, null, null);
+
+ query = qb.buildUnionQuery(
+ new String[] { bookmarksBarQuery, otherBookmarksQuery },
+ DEFAULT_BOOKMARKS_SORT_ORDER, limit);
+
+ args = new String[] {
+ accountType, accountName, accountType, accountName,
+ accountType, accountName, ChromeSyncColumns.FOLDER_NAME_OTHER_BOOKMARKS,
+ };
+ }
+
+ return db.rawQuery(query, args);
+ }
+
+ case HISTORY_ID: {
+ selection = DatabaseUtils.concatenateWhere(selection, TABLE_HISTORY + "._id=?");
+ selectionArgs = DatabaseUtils.appendSelectionArgs(selectionArgs,
+ new String[] { Long.toString(ContentUris.parseId(uri)) });
+ // fall through
+ }
+ case HISTORY: {
+ if (sortOrder == null) {
+ sortOrder = DEFAULT_SORT_HISTORY;
+ }
+ qb.setProjectionMap(HISTORY_PROJECTION_MAP);
+ qb.setTables(TABLE_HISTORY_JOIN_IMAGES);
+ break;
+ }
+
+ case SEARCHES_ID: {
+ selection = DatabaseUtils.concatenateWhere(selection, TABLE_SEARCHES + "._id=?");
+ selectionArgs = DatabaseUtils.appendSelectionArgs(selectionArgs,
+ new String[] { Long.toString(ContentUris.parseId(uri)) });
+ // fall through
+ }
+ case SEARCHES: {
+ if (sortOrder == null) {
+ sortOrder = DEFAULT_SORT_SEARCHES;
+ }
+ qb.setTables(TABLE_SEARCHES);
+ qb.setProjectionMap(SEARCHES_PROJECTION_MAP);
+ break;
+ }
+
+ case SYNCSTATE: {
+ return mSyncHelper.query(db, projection, selection, selectionArgs, sortOrder);
+ }
+
+ case SYNCSTATE_ID: {
+ selection = appendAccountToSelection(uri, selection);
+ String selectionWithId =
+ (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ")
+ + (selection == null ? "" : " AND (" + selection + ")");
+ return mSyncHelper.query(db, projection, selectionWithId, selectionArgs, sortOrder);
+ }
+
+ case IMAGES: {
+ qb.setTables(TABLE_IMAGES);
+ qb.setProjectionMap(IMAGES_PROJECTION_MAP);
+ break;
+ }
+
+ case COMBINED_ID: {
+ selection = DatabaseUtils.concatenateWhere(selection, VIEW_COMBINED + "._id=?");
+ selectionArgs = DatabaseUtils.appendSelectionArgs(selectionArgs,
+ new String[] { Long.toString(ContentUris.parseId(uri)) });
+ // fall through
+ }
+ case COMBINED: {
+ qb.setTables(VIEW_COMBINED);
+ qb.setProjectionMap(COMBINED_PROJECTION_MAP);
+ break;
+ }
+
+ case SETTINGS: {
+ qb.setTables(TABLE_SETTINGS);
+ qb.setProjectionMap(SETTINGS_PROJECTION_MAP);
+ break;
+ }
+
+ default: {
+ throw new UnsupportedOperationException("Unknown URL " + uri.toString());
+ }
+ }
+
+ Cursor cursor = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder,
+ limit);
+ cursor.setNotificationUri(getContext().getContentResolver(), BrowserContract.AUTHORITY_URI);
+ return cursor;
+ }
+
+ @Override
+ public int deleteInTransaction(Uri uri, String selection, String[] selectionArgs,
+ boolean callerIsSyncAdapter) {
+ final int match = URI_MATCHER.match(uri);
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ switch (match) {
+ case BOOKMARKS_ID:
+ case BOOKMARKS: {
+ //TODO cascade deletes down from folders
+ if (!callerIsSyncAdapter) {
+ // If the caller isn't a sync adapter just go through and update all the
+ // bookmarks to have the deleted flag set.
+ ContentValues values = new ContentValues();
+ values.put(Bookmarks.DATE_MODIFIED, System.currentTimeMillis());
+ values.put(Bookmarks.IS_DELETED, 1);
+ return updateInTransaction(uri, values, selection, selectionArgs,
+ callerIsSyncAdapter);
+ } else {
+ // Sync adapters are allowed to actually delete things
+ if (match == BOOKMARKS_ID) {
+ selection = DatabaseUtils.concatenateWhere(selection,
+ TABLE_BOOKMARKS + "._id=?");
+ selectionArgs = DatabaseUtils.appendSelectionArgs(selectionArgs,
+ new String[] { Long.toString(ContentUris.parseId(uri)) });
+ }
+ return db.delete(TABLE_BOOKMARKS, selection, selectionArgs);
+ }
+ }
+
+ case HISTORY_ID: {
+ selection = DatabaseUtils.concatenateWhere(selection, TABLE_HISTORY + "._id=?");
+ selectionArgs = DatabaseUtils.appendSelectionArgs(selectionArgs,
+ new String[] { Long.toString(ContentUris.parseId(uri)) });
+ // fall through
+ }
+ case HISTORY: {
+ return db.delete(TABLE_HISTORY, selection, selectionArgs);
+ }
+
+ case SEARCHES_ID: {
+ selection = DatabaseUtils.concatenateWhere(selection, TABLE_SEARCHES + "._id=?");
+ selectionArgs = DatabaseUtils.appendSelectionArgs(selectionArgs,
+ new String[] { Long.toString(ContentUris.parseId(uri)) });
+ // fall through
+ }
+ case SEARCHES: {
+ return db.delete(TABLE_SEARCHES, selection, selectionArgs);
+ }
+
+ case SYNCSTATE: {
+ return mSyncHelper.delete(db, selection, selectionArgs);
+ }
+ case SYNCSTATE_ID: {
+ String selectionWithId =
+ (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ")
+ + (selection == null ? "" : " AND (" + selection + ")");
+ return mSyncHelper.delete(db, selectionWithId, selectionArgs);
+ }
+ }
+ throw new UnsupportedOperationException("Unknown update URI " + uri);
+ }
+
+ @Override
+ public Uri insertInTransaction(Uri uri, ContentValues values, boolean callerIsSyncAdapter) {
+ final int match = URI_MATCHER.match(uri);
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ long id = -1;
+ switch (match) {
+ case BOOKMARKS: {
+ // Mark rows dirty if they're not coming from a sync adapter
+ if (!callerIsSyncAdapter) {
+ long now = System.currentTimeMillis();
+ values.put(Bookmarks.DATE_CREATED, now);
+ values.put(Bookmarks.DATE_MODIFIED, now);
+ values.put(Bookmarks.DIRTY, 1);
+
+ // If no parent is set default to the "Bookmarks Bar" folder
+ // TODO set the parent based on the account info
+ if (!values.containsKey(Bookmarks.PARENT)) {
+ values.put(Bookmarks.PARENT, FIXED_ID_ROOT);
+ }
+ }
+
+ // If no position is requested put the bookmark at the beginning of the list
+ if (!values.containsKey(Bookmarks.POSITION)) {
+ values.put(Bookmarks.POSITION, Long.toString(Long.MIN_VALUE));
+ }
+
+ // Extract out the image values so they can be inserted into the images table
+ String url = values.getAsString(Bookmarks.URL);
+ ContentValues imageValues = extractImageValues(values, url);
+ Boolean isFolder = values.getAsBoolean(Bookmarks.IS_FOLDER);
+ if ((isFolder == null || !isFolder)
+ && imageValues != null && !TextUtils.isEmpty(url)) {
+ int count = db.update(TABLE_IMAGES, imageValues, Images.URL + "=?",
+ new String[] { url });
+ if (count == 0) {
+ db.insertOrThrow(TABLE_IMAGES, Images.FAVICON, imageValues);
+ }
+ }
+
+ id = db.insertOrThrow(TABLE_BOOKMARKS, Bookmarks.DIRTY, values);
+ break;
+ }
+
+ case HISTORY: {
+ // If no created time is specified set it to now
+ if (!values.containsKey(History.DATE_CREATED)) {
+ values.put(History.DATE_CREATED, System.currentTimeMillis());
+ }
+
+ // Extract out the image values so they can be inserted into the images table
+ ContentValues imageValues = extractImageValues(values,
+ values.getAsString(History.URL));
+ if (imageValues != null) {
+ db.insertOrThrow(TABLE_IMAGES, Images.FAVICON, imageValues);
+ }
+
+ id = db.insertOrThrow(TABLE_HISTORY, History.VISITS, values);
+ break;
+ }
+
+ case SEARCHES: {
+ id = insertSearchesInTransaction(db, values);
+ break;
+ }
+
+ case SYNCSTATE: {
+ id = mSyncHelper.insert(db, values);
+ break;
+ }
+
+ case SETTINGS: {
+ id = 0;
+ insertSettingsInTransaction(db, values);
+ break;
+ }
+
+ default: {
+ throw new UnsupportedOperationException("Unknown insert URI " + uri);
+ }
+ }
+
+ if (id >= 0) {
+ return ContentUris.withAppendedId(uri, id);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Searches are unique, so perform an UPSERT manually since SQLite doesn't support them.
+ */
+ private long insertSearchesInTransaction(SQLiteDatabase db, ContentValues values) {
+ String search = values.getAsString(Searches.SEARCH);
+ if (TextUtils.isEmpty(search)) {
+ throw new IllegalArgumentException("Must include the SEARCH field");
+ }
+ Cursor cursor = null;
+ try {
+ cursor = db.query(TABLE_SEARCHES, new String[] { Searches._ID },
+ Searches.SEARCH + "=?", new String[] { search }, null, null, null);
+ if (cursor.moveToNext()) {
+ long id = cursor.getLong(0);
+ db.update(TABLE_SEARCHES, values, Searches._ID + "=?",
+ new String[] { Long.toString(id) });
+ return id;
+ } else {
+ return db.insertOrThrow(TABLE_SEARCHES, Searches.SEARCH, values);
+ }
+ } finally {
+ if (cursor != null) cursor.close();
+ }
+ }
+
+ /**
+ * Settings are unique, so perform an UPSERT manually since SQLite doesn't support them.
+ */
+ private long insertSettingsInTransaction(SQLiteDatabase db, ContentValues values) {
+ String key = values.getAsString(Settings.KEY);
+ if (TextUtils.isEmpty(key)) {
+ throw new IllegalArgumentException("Must include the KEY field");
+ }
+ String[] keyArray = new String[] { key };
+ Cursor cursor = null;
+ try {
+ cursor = db.query(TABLE_SETTINGS, new String[] { Settings.KEY },
+ Settings.KEY + "=?", keyArray, null, null, null);
+ if (cursor.moveToNext()) {
+ long id = cursor.getLong(0);
+ db.update(TABLE_SETTINGS, values, Settings.KEY + "=?", keyArray);
+ return id;
+ } else {
+ return db.insertOrThrow(TABLE_SETTINGS, Settings.VALUE, values);
+ }
+ } finally {
+ if (cursor != null) cursor.close();
+ }
+ }
+
+ @Override
+ public int updateInTransaction(Uri uri, ContentValues values, String selection,
+ String[] selectionArgs, boolean callerIsSyncAdapter) {
+ final int match = URI_MATCHER.match(uri);
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ switch (match) {
+ case BOOKMARKS_ID: {
+ selection = DatabaseUtils.concatenateWhere(selection,
+ TABLE_BOOKMARKS + "._id=?");
+ selectionArgs = DatabaseUtils.appendSelectionArgs(selectionArgs,
+ new String[] { Long.toString(ContentUris.parseId(uri)) });
+ // fall through
+ }
+ case BOOKMARKS: {
+ return updateBookmarksInTransaction(values, selection, selectionArgs,
+ callerIsSyncAdapter);
+ }
+
+ case HISTORY_ID: {
+ selection = DatabaseUtils.concatenateWhere(selection, TABLE_HISTORY + "._id=?");
+ selectionArgs = DatabaseUtils.appendSelectionArgs(selectionArgs,
+ new String[] { Long.toString(ContentUris.parseId(uri)) });
+ // fall through
+ }
+ case HISTORY: {
+ return updateHistoryInTransaction(values, selection, selectionArgs);
+ }
+
+ case SYNCSTATE: {
+ return mSyncHelper.update(mDb, values,
+ appendAccountToSelection(uri, selection), selectionArgs);
+ }
+
+ case SYNCSTATE_ID: {
+ selection = appendAccountToSelection(uri, selection);
+ String selectionWithId =
+ (SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ")
+ + (selection == null ? "" : " AND (" + selection + ")");
+ return mSyncHelper.update(mDb, values,
+ selectionWithId, selectionArgs);
+ }
+
+ case IMAGES: {
+ String url = values.getAsString(Images.URL);
+ if (TextUtils.isEmpty(url)) {
+ throw new IllegalArgumentException("Images.URL is required");
+ }
+ int count = db.update(TABLE_IMAGES, values, Images.URL + "=?",
+ new String[] { url });
+ if (count == 0) {
+ db.insertOrThrow(TABLE_IMAGES, Images.FAVICON, values);
+ count = 1;
+ }
+ return count;
+ }
+ }
+ throw new UnsupportedOperationException("Unknown update URI " + uri);
+ }
+
+ /**
+ * Does a query to find the matching bookmarks and updates each one with the provided values.
+ */
+ int updateBookmarksInTransaction(ContentValues values, String selection,
+ String[] selectionArgs, boolean callerIsSyncAdapter) {
+ int count = 0;
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ Cursor cursor = query(Bookmarks.CONTENT_URI,
+ new String[] { Bookmarks._ID, Bookmarks.VERSION, Bookmarks.URL },
+ selection, selectionArgs, null);
+ try {
+ String[] args = new String[1];
+ // Mark the bookmark dirty if the caller isn't a sync adapter
+ if (!callerIsSyncAdapter) {
+ values.put(Bookmarks.DATE_MODIFIED, System.currentTimeMillis());
+ values.put(Bookmarks.DIRTY, 1);
+ }
+
+ boolean updatingUrl = values.containsKey(Bookmarks.URL);
+ String url = null;
+ if (updatingUrl) {
+ url = values.getAsString(Bookmarks.URL);
+ }
+ ContentValues imageValues = extractImageValues(values, url);
+
+ while (cursor.moveToNext()) {
+ args[0] = cursor.getString(0);
+ if (!callerIsSyncAdapter) {
+ // increase the local version for non-sync changes
+ values.put(Bookmarks.VERSION, cursor.getLong(1) + 1);
+ }
+ count += db.update(TABLE_BOOKMARKS, values, "_id=?", args);
+
+ // Update the images over in their table
+ if (imageValues != null) {
+ if (!updatingUrl) {
+ url = cursor.getString(2);
+ imageValues.put(Images.URL, url);
+ }
+
+ if (!TextUtils.isEmpty(url)) {
+ args[0] = url;
+ if (db.update(TABLE_IMAGES, imageValues, Images.URL + "=?", args) == 0) {
+ db.insert(TABLE_IMAGES, Images.FAVICON, imageValues);
+ }
+ }
+ }
+ }
+ } finally {
+ if (cursor != null) cursor.close();
+ }
+ return count;
+ }
+
+ /**
+ * Does a query to find the matching bookmarks and updates each one with the provided values.
+ */
+ int updateHistoryInTransaction(ContentValues values, String selection, String[] selectionArgs) {
+ int count = 0;
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ Cursor cursor = query(History.CONTENT_URI,
+ new String[] { History._ID, History.URL },
+ selection, selectionArgs, null);
+ try {
+ String[] args = new String[1];
+
+ boolean updatingUrl = values.containsKey(History.URL);
+ String url = null;
+ if (updatingUrl) {
+ url = values.getAsString(History.URL);
+ }
+ ContentValues imageValues = extractImageValues(values, url);
+
+ while (cursor.moveToNext()) {
+ args[0] = cursor.getString(0);
+ count += db.update(TABLE_HISTORY, values, "_id=?", args);
+
+ // Update the images over in their table
+ if (imageValues != null) {
+ if (!updatingUrl) {
+ url = cursor.getString(1);
+ imageValues.put(Images.URL, url);
+ }
+ args[0] = url;
+ if (db.update(TABLE_IMAGES, imageValues, Images.URL + "=?", args) == 0) {
+ db.insert(TABLE_IMAGES, Images.FAVICON, imageValues);
+ }
+ }
+ }
+ } finally {
+ if (cursor != null) cursor.close();
+ }
+ return count;
+ }
+
+ String appendAccountToSelection(Uri uri, String selection) {
+ final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME);
+ final String accountType = uri.getQueryParameter(RawContacts.ACCOUNT_TYPE);
+
+ final boolean partialUri = TextUtils.isEmpty(accountName) ^ TextUtils.isEmpty(accountType);
+ if (partialUri) {
+ // Throw when either account is incomplete
+ throw new IllegalArgumentException(
+ "Must specify both or neither of ACCOUNT_NAME and ACCOUNT_TYPE for " + uri);
+ }
+
+ // Accounts are valid by only checking one parameter, since we've
+ // already ruled out partial accounts.
+ final boolean validAccount = !TextUtils.isEmpty(accountName);
+ if (validAccount) {
+ StringBuilder selectionSb = new StringBuilder(RawContacts.ACCOUNT_NAME + "="
+ + DatabaseUtils.sqlEscapeString(accountName) + " AND "
+ + RawContacts.ACCOUNT_TYPE + "="
+ + DatabaseUtils.sqlEscapeString(accountType));
+ if (!TextUtils.isEmpty(selection)) {
+ selectionSb.append(" AND (");
+ selectionSb.append(selection);
+ selectionSb.append(')');
+ }
+ return selectionSb.toString();
+ } else {
+ return selection;
+ }
+ }
+
+ ContentValues extractImageValues(ContentValues values, String url) {
+ ContentValues imageValues = null;
+ // favicon
+ if (values.containsKey(Bookmarks.FAVICON)) {
+ imageValues = new ContentValues();
+ imageValues.put(Images.FAVICON, values.getAsByteArray(Bookmarks.FAVICON));
+ values.remove(Bookmarks.FAVICON);
+ }
+
+ // thumbnail
+ if (values.containsKey(Bookmarks.THUMBNAIL)) {
+ if (imageValues == null) {
+ imageValues = new ContentValues();
+ }
+ imageValues.put(Images.THUMBNAIL, values.getAsByteArray(Bookmarks.THUMBNAIL));
+ values.remove(Bookmarks.THUMBNAIL);
+ }
+
+ // touch icon
+ if (values.containsKey(Bookmarks.TOUCH_ICON)) {
+ if (imageValues == null) {
+ imageValues = new ContentValues();
+ }
+ imageValues.put(Images.TOUCH_ICON, values.getAsByteArray(Bookmarks.TOUCH_ICON));
+ values.remove(Bookmarks.TOUCH_ICON);
+ }
+
+ if (imageValues != null) {
+ imageValues.put(Images.URL, url);
+ }
+ return imageValues;
+ }
+}
diff --git a/src/com/android/browser/provider/SQLiteContentProvider.java b/src/com/android/browser/provider/SQLiteContentProvider.java
new file mode 100644
index 0000000..a50894a
--- /dev/null
+++ b/src/com/android/browser/provider/SQLiteContentProvider.java
@@ -0,0 +1,276 @@
+/*
+ * 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.provider;
+
+import android.content.ContentProvider;
+import android.content.ContentProviderOperation;
+import android.content.ContentProviderResult;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.OperationApplicationException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteTransactionListener;
+import android.net.Uri;
+
+import java.util.ArrayList;
+
+/**
+ * General purpose {@link ContentProvider} base class that uses SQLiteDatabase for storage.
+ */
+public abstract class SQLiteContentProvider extends ContentProvider
+ implements SQLiteTransactionListener {
+
+ private static final String TAG = "SQLiteContentProvider";
+
+ private SQLiteOpenHelper mOpenHelper;
+ private volatile boolean mNotifyChange;
+ protected SQLiteDatabase mDb;
+
+ private final ThreadLocal<Boolean> mApplyingBatch = new ThreadLocal<Boolean>();
+ private static final int SLEEP_AFTER_YIELD_DELAY = 4000;
+
+ /**
+ * Maximum number of operations allowed in a batch between yield points.
+ */
+ private static final int MAX_OPERATIONS_PER_YIELD_POINT = 500;
+
+ @Override
+ public boolean onCreate() {
+ Context context = getContext();
+ mOpenHelper = getDatabaseHelper(context);
+ return true;
+ }
+
+ /**
+ * Returns a {@link SQLiteOpenHelper} that can open the database.
+ */
+ public abstract SQLiteOpenHelper getDatabaseHelper(Context context);
+
+ /**
+ * The equivalent of the {@link #insert} method, but invoked within a transaction.
+ */
+ public abstract Uri insertInTransaction(Uri uri, ContentValues values,
+ boolean callerIsSyncAdapter);
+
+ /**
+ * The equivalent of the {@link #update} method, but invoked within a transaction.
+ */
+ public abstract int updateInTransaction(Uri uri, ContentValues values, String selection,
+ String[] selectionArgs, boolean callerIsSyncAdapter);
+
+ /**
+ * The equivalent of the {@link #delete} method, but invoked within a transaction.
+ */
+ public abstract int deleteInTransaction(Uri uri, String selection, String[] selectionArgs,
+ boolean callerIsSyncAdapter);
+
+ /**
+ * Called when the provider needs to notify the system of a change.
+ * @param callerIsSyncAdapter true if the caller that caused the change was a sync adapter.
+ */
+ public abstract void notifyChange(boolean callerIsSyncAdapter);
+
+ public boolean isCallerSyncAdapter(Uri uri) {
+ return false;
+ }
+
+ public SQLiteOpenHelper getDatabaseHelper() {
+ return mOpenHelper;
+ }
+
+ private boolean applyingBatch() {
+ return mApplyingBatch.get() != null && mApplyingBatch.get();
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ Uri result = null;
+ boolean callerIsSyncAdapter = isCallerSyncAdapter(uri);
+ boolean applyingBatch = applyingBatch();
+ if (!applyingBatch) {
+ mDb = mOpenHelper.getWritableDatabase();
+ mDb.beginTransactionWithListener(this);
+ try {
+ result = insertInTransaction(uri, values, callerIsSyncAdapter);
+ if (result != null) {
+ mNotifyChange = true;
+ }
+ mDb.setTransactionSuccessful();
+ } finally {
+ mDb.endTransaction();
+ }
+
+ onEndTransaction(callerIsSyncAdapter);
+ } else {
+ result = insertInTransaction(uri, values, callerIsSyncAdapter);
+ if (result != null) {
+ mNotifyChange = true;
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public int bulkInsert(Uri uri, ContentValues[] values) {
+ int numValues = values.length;
+ boolean callerIsSyncAdapter = isCallerSyncAdapter(uri);
+ mDb = mOpenHelper.getWritableDatabase();
+ mDb.beginTransactionWithListener(this);
+ try {
+ for (int i = 0; i < numValues; i++) {
+ Uri result = insertInTransaction(uri, values[i], callerIsSyncAdapter);
+ if (result != null) {
+ mNotifyChange = true;
+ }
+ mDb.yieldIfContendedSafely();
+ }
+ mDb.setTransactionSuccessful();
+ } finally {
+ mDb.endTransaction();
+ }
+
+ onEndTransaction(callerIsSyncAdapter);
+ return numValues;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ int count = 0;
+ boolean callerIsSyncAdapter = isCallerSyncAdapter(uri);
+ boolean applyingBatch = applyingBatch();
+ if (!applyingBatch) {
+ mDb = mOpenHelper.getWritableDatabase();
+ mDb.beginTransactionWithListener(this);
+ try {
+ count = updateInTransaction(uri, values, selection, selectionArgs,
+ callerIsSyncAdapter);
+ if (count > 0) {
+ mNotifyChange = true;
+ }
+ mDb.setTransactionSuccessful();
+ } finally {
+ mDb.endTransaction();
+ }
+
+ onEndTransaction(callerIsSyncAdapter);
+ } else {
+ count = updateInTransaction(uri, values, selection, selectionArgs, callerIsSyncAdapter);
+ if (count > 0) {
+ mNotifyChange = true;
+ }
+ }
+
+ return count;
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ int count = 0;
+ boolean callerIsSyncAdapter = isCallerSyncAdapter(uri);
+ boolean applyingBatch = applyingBatch();
+ if (!applyingBatch) {
+ mDb = mOpenHelper.getWritableDatabase();
+ mDb.beginTransactionWithListener(this);
+ try {
+ count = deleteInTransaction(uri, selection, selectionArgs, callerIsSyncAdapter);
+ if (count > 0) {
+ mNotifyChange = true;
+ }
+ mDb.setTransactionSuccessful();
+ } finally {
+ mDb.endTransaction();
+ }
+
+ onEndTransaction(callerIsSyncAdapter);
+ } else {
+ count = deleteInTransaction(uri, selection, selectionArgs, callerIsSyncAdapter);
+ if (count > 0) {
+ mNotifyChange = true;
+ }
+ }
+ return count;
+ }
+
+ @Override
+ public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
+ throws OperationApplicationException {
+ int ypCount = 0;
+ int opCount = 0;
+ boolean callerIsSyncAdapter = false;
+ mDb = mOpenHelper.getWritableDatabase();
+ mDb.beginTransactionWithListener(this);
+ try {
+ mApplyingBatch.set(true);
+ final int numOperations = operations.size();
+ final ContentProviderResult[] results = new ContentProviderResult[numOperations];
+ for (int i = 0; i < numOperations; i++) {
+ if (++opCount >= MAX_OPERATIONS_PER_YIELD_POINT) {
+ throw new OperationApplicationException(
+ "Too many content provider operations between yield points. "
+ + "The maximum number of operations per yield point is "
+ + MAX_OPERATIONS_PER_YIELD_POINT, ypCount);
+ }
+ final ContentProviderOperation operation = operations.get(i);
+ if (!callerIsSyncAdapter && isCallerSyncAdapter(operation.getUri())) {
+ callerIsSyncAdapter = true;
+ }
+ if (i > 0 && operation.isYieldAllowed()) {
+ opCount = 0;
+ if (mDb.yieldIfContendedSafely(SLEEP_AFTER_YIELD_DELAY)) {
+ ypCount++;
+ }
+ }
+ results[i] = operation.apply(this, results, i);
+ }
+ mDb.setTransactionSuccessful();
+ return results;
+ } finally {
+ mApplyingBatch.set(false);
+ mDb.endTransaction();
+ onEndTransaction(callerIsSyncAdapter);
+ }
+ }
+
+ @Override
+ public void onBegin() {
+ onBeginTransaction();
+ }
+
+ @Override
+ public void onCommit() {
+ beforeTransactionCommit();
+ }
+
+ @Override
+ public void onRollback() {
+ // not used
+ }
+
+ protected void onBeginTransaction() {
+ }
+
+ protected void beforeTransactionCommit() {
+ }
+
+ protected void onEndTransaction(boolean callerIsSyncAdapter) {
+ if (mNotifyChange) {
+ mNotifyChange = false;
+ notifyChange(callerIsSyncAdapter);
+ }
+ }
+}
diff --git a/src/com/android/browser/search/.DefaultSearchEngine.java.swp b/src/com/android/browser/search/.DefaultSearchEngine.java.swp
new file mode 100644
index 0000000..441153c
--- /dev/null
+++ b/src/com/android/browser/search/.DefaultSearchEngine.java.swp
Binary files differ
diff --git a/src/com/android/browser/widget/BookmarkStackWidgetProvider.java b/src/com/android/browser/widget/BookmarkStackWidgetProvider.java
new file mode 100644
index 0000000..0684c61
--- /dev/null
+++ b/src/com/android/browser/widget/BookmarkStackWidgetProvider.java
@@ -0,0 +1,45 @@
+/*
+ * 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.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProvider;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * Widget that shows a preview of the user's bookmarks.
+ */
+public class BookmarkStackWidgetProvider extends AppWidgetProvider {
+
+ @Override
+ public void onUpdate(Context context, AppWidgetManager mngr, int[] ids) {
+ context.startService(new Intent(BookmarkStackWidgetService.UPDATE, null,
+ context, BookmarkStackWidgetService.class));
+ }
+
+ @Override
+ public void onEnabled(Context context) {
+ context.startService(new Intent(context, BookmarkStackWidgetService.class));
+ }
+
+ @Override
+ public void onDisabled(Context context) {
+ context.stopService(new Intent(context, BookmarkStackWidgetService.class));
+ }
+
+}
diff --git a/src/com/android/browser/widget/BookmarkStackWidgetService.java b/src/com/android/browser/widget/BookmarkStackWidgetService.java
new file mode 100644
index 0000000..83b07df
--- /dev/null
+++ b/src/com/android/browser/widget/BookmarkStackWidgetService.java
@@ -0,0 +1,217 @@
+/*
+ * 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 com.android.browser.R;
+
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetManager;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Message;
+import android.provider.BrowserContract;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.RemoteViews;
+import android.widget.RemoteViewsService;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class BookmarkStackWidgetService extends RemoteViewsService {
+
+ private static final String LOGTAG = "browserwidget";
+
+ /** Force the bookmarks to be re-rendered. */
+ public static final String UPDATE = "com.android.browser.widget.UPDATE";
+
+ /** the adapter intent action */
+ public static final String ADAPTER = "com.android.browser.widget.ADAPTER";
+
+ private static final String[] PROJECTION = new String[] {
+ BrowserContract.Bookmarks._ID,
+ BrowserContract.Bookmarks.TITLE,
+ BrowserContract.Bookmarks.URL,
+ BrowserContract.Bookmarks.THUMBNAIL };
+
+ private static final String WHERE_CLAUSE = BrowserContract.Bookmarks.IS_FOLDER +
+ " == 0";
+
+ // No id specified.
+ private static final int NO_ID = -1;
+
+ private static final int MSG_UPDATE = 0;
+
+ List<RenderResult> mBookmarks;
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_UPDATE:
+ updateWidget();
+ break;
+ default:
+ break;
+ }
+ }
+ };
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ if ((intent == null) || (intent.getAction() != null) && UPDATE.equals(intent.getAction())) {
+ mHandler.sendEmptyMessage(MSG_UPDATE);
+ }
+ return START_STICKY;
+ }
+
+ private void updateWidget() {
+ RemoteViews views = new RemoteViews(getPackageName(),
+ R.layout.bookmarkstackwidget);
+ Intent vi = new Intent(Intent.ACTION_VIEW);
+ vi.addCategory(Intent.CATEGORY_BROWSABLE);
+ views.setPendingIntentTemplate(R.id.stackwidget_stack,
+ PendingIntent.getActivity(BookmarkStackWidgetService.this, 0, vi,
+ PendingIntent.FLAG_CANCEL_CURRENT));
+ Intent adapter = new Intent(BookmarkStackWidgetService.ADAPTER, null,
+ this, BookmarkStackWidgetService.class);
+ views.setRemoteAdapter(R.id.stackwidget_stack, adapter);
+ AppWidgetManager.getInstance(this).updateAppWidget(
+ new ComponentName(this, BookmarkStackWidgetProvider.class),
+ views);
+ }
+
+ @Override
+ public RemoteViewsFactory onGetViewFactory(Intent intent) {
+ return mViewFactory;
+ }
+
+ RemoteViewsService.RemoteViewsFactory mViewFactory = new RemoteViewsFactory () {
+
+ Intent mFillIntent;
+
+ @Override
+ public int getCount() {
+ return mBookmarks.size();
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public RemoteViews getLoadingView() {
+ return null;
+ }
+
+ @Override
+ public RemoteViews getViewAt(int position) {
+ RenderResult res = mBookmarks.get(position);
+ RemoteViews views = new RemoteViews(getPackageName(),
+ R.layout.bookmarkstackwidget_item);
+ mFillIntent.setData(Uri.parse(res.mUrl));
+ views.setOnClickFillInIntent(R.id.stack_item, mFillIntent);
+ // Set the title of the bookmark. Use the url as a backup.
+ String displayTitle = res.mTitle;
+ if (TextUtils.isEmpty(displayTitle)) {
+ displayTitle = res.mUrl;
+ }
+ views.setTextViewText(R.id.label, displayTitle);
+ if (res.mBitmap != null) {
+ views.setImageViewBitmap(R.id.thumb, res.mBitmap);
+ views.setViewVisibility(R.id.label, View.GONE);
+ }
+ return views;
+ }
+
+ @Override
+ public int getViewTypeCount() {
+ return 1;
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return false;
+ }
+
+ @Override
+ public void onCreate() {
+ mFillIntent = new Intent();
+ update();
+ }
+
+ @Override
+ public void onDestroy() {
+ }
+
+ public void update() {
+ mBookmarks = new ArrayList<RenderResult>();
+ // Look up all the bookmarks
+ Cursor c = null;
+ try {
+ c = getContentResolver().query(BrowserContract.Bookmarks.CONTENT_URI,
+ PROJECTION, WHERE_CLAUSE, null, null);
+ if (c != null) {
+ while (c.moveToNext()) {
+ int id = c.getInt(0);
+ String title = c.getString(1);
+ String url = c.getString(2);
+ RenderResult res = new RenderResult(id, title, url);
+ byte[] blob = c.getBlob(3);
+ if (blob != null) {
+ res.mBitmap = BitmapFactory.decodeByteArray(blob, 0, blob.length);
+ }
+ mBookmarks.add(res);
+ }
+ }
+ } catch (IllegalStateException e) {
+ Log.e(LOGTAG, "update bookmark widget", e);
+ } finally {
+ if (c != null) {
+ c.close();
+ }
+ }
+ }
+
+ @Override
+ public void onDataSetChanged() {
+ }
+ };
+
+ // 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;
+ }
+
+ }
+
+}
diff --git a/tests/src/com/android/browser/JNIBindingsTestApp.java b/tests/src/com/android/browser/JNIBindingsTestApp.java
index 4f083f6..4c8802a 100644
--- a/tests/src/com/android/browser/JNIBindingsTestApp.java
+++ b/tests/src/com/android/browser/JNIBindingsTestApp.java
@@ -37,6 +37,9 @@
/**
* Adds a JavaScript interface to the webview and calls functions on it to verify variables
* are passed from JS to Java correctly.
+ * To run this test, execute:
+ * adb shell am instrument -w -e class com.android.browser.JNIBindingsTestApp#testJNIBindings \
+ * com.android.browser.tests/android.test.InstrumentationTestRunner
*/
public class JNIBindingsTestApp extends ActivityInstrumentationTestCase2<BrowserActivity> {
@@ -89,7 +92,7 @@
}
}
};
- mWebView.documentAsText(mHandler.obtainMessage(MSG_WEBKIT_DATA_READY));
+ mWebView.documentAsText(mHandler.obtainMessage(MSG_WEBKIT_DATA_READY, 1, 0));
Looper.loop();
}
}
diff --git a/tests/src/com/android/browser/TestWebChromeClient.java b/tests/src/com/android/browser/TestWebChromeClient.java
index d78eaed..53f8db3 100644
--- a/tests/src/com/android/browser/TestWebChromeClient.java
+++ b/tests/src/com/android/browser/TestWebChromeClient.java
@@ -195,7 +195,7 @@
/** {@inheritDoc} */
@Override
- public void openFileChooser(ValueCallback<Uri> uploadFile) {
- mWrappedClient.openFileChooser(uploadFile);
+ public void openFileChooser(ValueCallback<Uri> uploadFile, String acceptType) {
+ mWrappedClient.openFileChooser(uploadFile, acceptType);
}
}