am c3169def: am 6002de42: am 6248bff9: Merge "Remove an incorrect javadoc comment." into froyo
Merge commit 'c3169defa19a824f69b455b5e672931680a194b9'
* commit 'c3169defa19a824f69b455b5e672931680a194b9':
Remove an incorrect javadoc comment.
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 36e2820..14ffe75 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -39,6 +39,7 @@
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 +50,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 +94,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 +154,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 +164,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 +195,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 +204,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 +217,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/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_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/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_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_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_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/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%
rename from res/menu/bookmarks.xml
rename 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..8e1881e 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_selected="true"
+ android:drawable="@drawable/tab_selected_bg" />
+ <item
+ android:state_selected="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..e3e4a9d
--- /dev/null
+++ b/res/layout/bookmarks.xml
@@ -0,0 +1,59 @@
+<?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_history"
+ 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..f15caf2 100644
--- a/res/layout/browser_add_bookmark.xml
+++ b/res/layout/browser_add_bookmark.xml
@@ -80,7 +80,6 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="#c6c3c6"
android:minHeight="54dip"
android:orientation="horizontal"
android:paddingTop="4dip"
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/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/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..b803881
--- /dev/null
+++ b/res/layout/url_bar.xml
@@ -0,0 +1,150 @@
+<?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" />
+ <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
+ 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" >
+ <ImageButton
+ android:id="@+id/star"
+ android:src="@drawable/ic_favorite_on_normal"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ style="@style/HoloButton"
+ android:background="@drawable/browserbarbutton" />
+ <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/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" />
+ </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" />
+ <ImageButton
+ android:id="@+id/go"
+ android:src="@drawable/ic_go_dark"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical"
+ style="@style/HoloButton"
+ android:background="@drawable/browserbarbutton" />
+ </LinearLayout>
+ </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/layout/url_dropdown_item.xml b/res/layout/url_dropdown_item.xml
new file mode 100644
index 0000000..5e8f84c
--- /dev/null
+++ b/res/layout/url_dropdown_item.xml
@@ -0,0 +1,68 @@
+<?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">
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/icon1"
+ android:scaleType="center"
+ style="@style/HoloButton" />
+ <TwoLineListItem
+ android:paddingTop="16dip"
+ android:paddingBottom="16dip"
+ android:layout_width="0dip"
+ android:layout_weight="1"
+ android:layout_height="wrap_content"
+ android:mode="twoLine">
+ <TextView
+ android:id="@android:id/text1"
+ style="?android:attr/dropDownItemStyle"
+ android:textAppearance="?android:attr/textAppearanceLargeInverse"
+ 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" />
+ </TwoLineListItem>
+ <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"
+ />
+</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..6b119e1 100644
--- a/res/menu/browser.xml
+++ b/res/menu/browser.xml
@@ -23,7 +23,7 @@
<item android:id="@+id/bookmarks_menu_id"
android:title="@string/bookmarks"
android:alphabeticShortcut="b"
- android:icon="@drawable/ic_menu_bookmarks"
+ android:icon="@drawable/ic_bookmarks_history_normal"
/>
<item android:id="@+id/active_tabs_menu_id"
android:title="@string/active_tabs"
@@ -34,29 +34,34 @@
<item android:id="@+id/forward_menu_id"
android:title="@string/forward"
android:alphabeticShortcut="k"
- android:icon="@*android:drawable/ic_menu_forward" />
+ android:icon="@drawable/ic_forward_normal" />
<item android:id="@+id/add_bookmark_menu_id"
android:title="@string/save_to_bookmarks"
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="@drawable/ic_menu_findonpage_normal"
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_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:title="@string/menu_save_webarchive"
+ android:icon="@drawable/ic_menu_archive_normal" />
<!-- followings are debug only -->
<item android:id="@+id/dump_nav_menu_id"
android:title="@string/dump_nav"
@@ -91,26 +96,20 @@
<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 -->
<item android:id="@+id/stop_menu_id"
android:title="@string/stop"
- android:icon="@*android:drawable/ic_menu_stop"
+ android:icon="@drawable/ic_stop_normal"
android:visible="false" />
<item android:id="@+id/reload_menu_id"
android:title="@string/reload"
- android:icon="@*android:drawable/ic_menu_refresh"
+ android:icon="@drawable/ic_refresh_normal"
android:visible="false" />
</menu>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 50f9949..f058ded 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -19,6 +19,8 @@
<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>
+ <!-- no translation found for new_incognito_tab (5821404839654751753) -->
+ <skip />
<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 +34,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>
@@ -70,9 +66,11 @@
<string name="location" msgid="969988560160364559">"Místo"</string>
<string name="name" msgid="5990326151488445481">"Jméno"</string>
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Přidat záložku"</string>
+ <!-- no translation found for save_to_bookmarks (8225229701567988479) -->
+ <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 +91,8 @@
<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>
+ <!-- no translation found for incognito_tab (5419458065370134289) -->
+ <skip />
<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 +102,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>
@@ -198,15 +200,7 @@
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Obnovit výchozí"</string>
<string name="pref_development_title" msgid="3263854204533056480">"Ladit"</string>
<string name="pref_default_text_encoding" msgid="5742965543955558478">"Kódování textu"</string>
- <string-array name="pref_default_text_encoding_choices">
- <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
- <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
- <item msgid="6122474363777211732">"Čínština (GBK)"</item>
- <item msgid="373372275931607040">"Čínština (Big5)"</item>
- <item msgid="891615911084608570">"Japonština (ISO-2022-JP)"</item>
- <item msgid="5589150448475151241">"Japonština (SHIFT_JIS)"</item>
- <item msgid="7356792686950371843">"Japonština (EUC-JP)"</item>
- </string-array>
+ <!-- no translation found for pref_default_text_encoding_choices:7 (2193955365569270096) -->
<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>
<string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Problém se souborem"</string>
@@ -290,4 +284,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>
+ <!-- no translation found for defaultBookmarksUpButton (2303951020715704735) -->
+ <skip />
+ <!-- no translation found for rlz_access_point (7165847807377650632) -->
+ <skip />
</resources>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 3d667ed..5d445ce 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -19,6 +19,8 @@
<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>
+ <!-- no translation found for new_incognito_tab (5821404839654751753) -->
+ <skip />
<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 +34,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>
@@ -70,9 +66,11 @@
<string name="location" msgid="969988560160364559">"Placering"</string>
<string name="name" msgid="5990326151488445481">"Navn"</string>
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Tilføj bogmærke"</string>
+ <!-- no translation found for save_to_bookmarks (8225229701567988479) -->
+ <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 +91,8 @@
<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>
+ <!-- no translation found for incognito_tab (5419458065370134289) -->
+ <skip />
<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 +102,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>
@@ -198,15 +200,7 @@
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Nulstil til standard"</string>
<string name="pref_development_title" msgid="3263854204533056480">"Fejlretning"</string>
<string name="pref_default_text_encoding" msgid="5742965543955558478">"Tekstkodning"</string>
- <string-array name="pref_default_text_encoding_choices">
- <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
- <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
- <item msgid="6122474363777211732">"Kinesisk (GBK)"</item>
- <item msgid="373372275931607040">"Kinesisk (Big5)"</item>
- <item msgid="891615911084608570">"Japansk (ISO-2022-JP)"</item>
- <item msgid="5589150448475151241">"Japansk (SHIFT_JIS)"</item>
- <item msgid="7356792686950371843">"Japansk (EUC-JP)"</item>
- </string-array>
+ <!-- no translation found for pref_default_text_encoding_choices:7 (2193955365569270096) -->
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Tekstkodning"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Dataforbindelsesproblem"</string>
<string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Der er et problem med filen"</string>
@@ -290,4 +284,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>
+ <!-- no translation found for defaultBookmarksUpButton (2303951020715704735) -->
+ <skip />
+ <!-- no translation found for rlz_access_point (7165847807377650632) -->
+ <skip />
</resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index e9df9f4..d8b3af1 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -19,6 +19,8 @@
<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>
+ <!-- no translation found for new_incognito_tab (5821404839654751753) -->
+ <skip />
<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 +34,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>
@@ -70,9 +66,11 @@
<string name="location" msgid="969988560160364559">"URL"</string>
<string name="name" msgid="5990326151488445481">"Name"</string>
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Lesezeichen hinzufügen"</string>
+ <!-- no translation found for save_to_bookmarks (8225229701567988479) -->
+ <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 +91,8 @@
<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>
+ <!-- no translation found for incognito_tab (5419458065370134289) -->
+ <skip />
<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 +102,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>
@@ -198,15 +200,7 @@
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Auf Standardeinstellung zurücksetzen"</string>
<string name="pref_development_title" msgid="3263854204533056480">"Debuggen"</string>
<string name="pref_default_text_encoding" msgid="5742965543955558478">"Textcodierung"</string>
- <string-array name="pref_default_text_encoding_choices">
- <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
- <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
- <item msgid="6122474363777211732">"Chinesisch (GBK)"</item>
- <item msgid="373372275931607040">"Chinesisch (Big5)"</item>
- <item msgid="891615911084608570">"Japanisch (ISO-2022-JP)"</item>
- <item msgid="5589150448475151241">"Japanisch (SHIFT_JIS)"</item>
- <item msgid="7356792686950371843">"Japanisch (EUC-JP)"</item>
- </string-array>
+ <!-- no translation found for pref_default_text_encoding_choices:7 (2193955365569270096) -->
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Textcodierung"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Datenverbindungsproblem"</string>
<string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Problem mit Datei"</string>
@@ -290,4 +284,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>
+ <!-- no translation found for defaultBookmarksUpButton (2303951020715704735) -->
+ <skip />
+ <!-- no translation found for rlz_access_point (7165847807377650632) -->
+ <skip />
</resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 7da0027..e894486 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -19,6 +19,8 @@
<string name="application_name" msgid="1935869255545976415">"Internet"</string>
<string name="choose_upload" msgid="3649366287575002063">"Επιλογή αρχείου για μεταφόρτωση"</string>
<string name="new_tab" msgid="4505722538297295141">"Νέο παράθυρο"</string>
+ <!-- no translation found for new_incognito_tab (5821404839654751753) -->
+ <skip />
<string name="active_tabs" msgid="3050623868203544623">"Παράθυρα"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Σελιδοδείκτες"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"Οι πιο δημοφιλείς"</string>
@@ -32,12 +34,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>
@@ -70,9 +66,11 @@
<string name="location" msgid="969988560160364559">"Τοποθεσία"</string>
<string name="name" msgid="5990326151488445481">"Όνομα"</string>
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Προσθήκη σελιδοδείκτη"</string>
+ <!-- no translation found for save_to_bookmarks (8225229701567988479) -->
+ <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 +91,8 @@
<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>
+ <!-- no translation found for incognito_tab (5419458065370134289) -->
+ <skip />
<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 +102,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>
@@ -198,15 +200,7 @@
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Επαναφορά προεπιλογών"</string>
<string name="pref_development_title" msgid="3263854204533056480">"Εντοπισμός σφαλμάτων"</string>
<string name="pref_default_text_encoding" msgid="5742965543955558478">"Κωδικοποίηση κειμένου"</string>
- <string-array name="pref_default_text_encoding_choices">
- <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
- <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
- <item msgid="6122474363777211732">"Κινεζικά (GBK)"</item>
- <item msgid="373372275931607040">"Κινεζικά (Big5)"</item>
- <item msgid="891615911084608570">"Ιαπωνικά (ISO-2022-JP)"</item>
- <item msgid="5589150448475151241">"Ιαπωνικά (SHIFT_JIS)"</item>
- <item msgid="7356792686950371843">"Ιαπωνικά (EUC-JP)"</item>
- </string-array>
+ <!-- no translation found for pref_default_text_encoding_choices:7 (2193955365569270096) -->
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Κωδικοποίηση κειμένου"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Πρόβλημα σύνδεσης δεδομένων"</string>
<string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Υπάρχει πρόβλημα με το αρχείο"</string>
@@ -290,4 +284,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>
+ <!-- no translation found for defaultBookmarksUpButton (2303951020715704735) -->
+ <skip />
+ <!-- no translation found for rlz_access_point (7165847807377650632) -->
+ <skip />
</resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 02b06b1..99fbca3 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -19,6 +19,8 @@
<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>
+ <!-- no translation found for new_incognito_tab (5821404839654751753) -->
+ <skip />
<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>
@@ -32,12 +34,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>
@@ -70,9 +66,11 @@
<string name="location" msgid="969988560160364559">"Ubicación"</string>
<string name="name" msgid="5990326151488445481">"Nombre"</string>
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Agregar marcador"</string>
+ <!-- no translation found for save_to_bookmarks (8225229701567988479) -->
+ <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 +91,8 @@
<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>
+ <!-- no translation found for incognito_tab (5419458065370134289) -->
+ <skip />
<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 +102,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>
@@ -198,15 +200,7 @@
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Restabl. a valores predet."</string>
<string name="pref_development_title" msgid="3263854204533056480">"Depurar"</string>
<string name="pref_default_text_encoding" msgid="5742965543955558478">"Codificación de texto"</string>
- <string-array name="pref_default_text_encoding_choices">
- <item msgid="7275223955790513818">"Latino-1 (ISO-8859-1)"</item>
- <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
- <item msgid="6122474363777211732">"Chino (GBK)"</item>
- <item msgid="373372275931607040">"Chino (Big5)"</item>
- <item msgid="891615911084608570">"Japonés (ISO-2022-JP)"</item>
- <item msgid="5589150448475151241">"Japonés (SHIFT_JIS)"</item>
- <item msgid="7356792686950371843">"Japonés (EUC-JP)"</item>
- </string-array>
+ <!-- no translation found for pref_default_text_encoding_choices:7 (2193955365569270096) -->
<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>
<string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Problema con el archivo"</string>
@@ -290,4 +284,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>
+ <!-- no translation found for defaultBookmarksUpButton (2303951020715704735) -->
+ <skip />
+ <!-- no translation found for rlz_access_point (7165847807377650632) -->
+ <skip />
</resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index e900c61..2964942 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -19,6 +19,8 @@
<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>
+ <!-- no translation found for new_incognito_tab (5821404839654751753) -->
+ <skip />
<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 +34,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>
@@ -70,9 +66,11 @@
<string name="location" msgid="969988560160364559">"Ubicación"</string>
<string name="name" msgid="5990326151488445481">"Nombre"</string>
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Añadir marcador"</string>
+ <!-- no translation found for save_to_bookmarks (8225229701567988479) -->
+ <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 +91,8 @@
<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>
+ <!-- no translation found for incognito_tab (5419458065370134289) -->
+ <skip />
<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 +102,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>
@@ -198,15 +200,7 @@
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Restablecer valores predeterminados"</string>
<string name="pref_development_title" msgid="3263854204533056480">"Depurar"</string>
<string name="pref_default_text_encoding" msgid="5742965543955558478">"Codificación de texto"</string>
- <string-array name="pref_default_text_encoding_choices">
- <item msgid="7275223955790513818">"Latín-1 (ISO-8859-1)"</item>
- <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
- <item msgid="6122474363777211732">"Chino (GBK)"</item>
- <item msgid="373372275931607040">"Chino (Big5)"</item>
- <item msgid="891615911084608570">"Japonés (ISO-2022-JP)"</item>
- <item msgid="5589150448475151241">"Japonés (SHIFT_JIS)"</item>
- <item msgid="7356792686950371843">"Japonés (EUC-JP)"</item>
- </string-array>
+ <!-- no translation found for pref_default_text_encoding_choices:7 (2193955365569270096) -->
<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>
<string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Problema con archivo"</string>
@@ -290,4 +284,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>
+ <!-- no translation found for defaultBookmarksUpButton (2303951020715704735) -->
+ <skip />
+ <!-- no translation found for rlz_access_point (7165847807377650632) -->
+ <skip />
</resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index acd1230..d0fa0be 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -19,6 +19,8 @@
<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>
+ <!-- no translation found for new_incognito_tab (5821404839654751753) -->
+ <skip />
<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 +34,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>
@@ -70,9 +66,11 @@
<string name="location" msgid="969988560160364559">"Emplacement"</string>
<string name="name" msgid="5990326151488445481">"Nom"</string>
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Ajouter un favori"</string>
+ <!-- no translation found for save_to_bookmarks (8225229701567988479) -->
+ <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 +91,8 @@
<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>
+ <!-- no translation found for incognito_tab (5419458065370134289) -->
+ <skip />
<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 +102,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>
@@ -198,15 +200,7 @@
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Rétablir les valeurs par défaut"</string>
<string name="pref_development_title" msgid="3263854204533056480">"Débogage"</string>
<string name="pref_default_text_encoding" msgid="5742965543955558478">"Codage du texte"</string>
- <string-array name="pref_default_text_encoding_choices">
- <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
- <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
- <item msgid="6122474363777211732">"Chinois (GBK)"</item>
- <item msgid="373372275931607040">"Chinois (Big5)"</item>
- <item msgid="891615911084608570">"Japonais (ISO-2022-JP)"</item>
- <item msgid="5589150448475151241">"Japonais (SHIFT_JIS)"</item>
- <item msgid="7356792686950371843">"Japonais (EUC-JP)"</item>
- </string-array>
+ <!-- no translation found for pref_default_text_encoding_choices:7 (2193955365569270096) -->
<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>
<string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Problème de fichier"</string>
@@ -290,4 +284,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>
+ <!-- no translation found for defaultBookmarksUpButton (2303951020715704735) -->
+ <skip />
+ <!-- no translation found for rlz_access_point (7165847807377650632) -->
+ <skip />
</resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index f8fa172..e3d6ae8 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -19,6 +19,8 @@
<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>
+ <!-- no translation found for new_incognito_tab (5821404839654751753) -->
+ <skip />
<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 +34,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>
@@ -70,9 +66,11 @@
<string name="location" msgid="969988560160364559">"URL"</string>
<string name="name" msgid="5990326151488445481">"Nome"</string>
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Aggiungi segnalibro"</string>
+ <!-- no translation found for save_to_bookmarks (8225229701567988479) -->
+ <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 +91,8 @@
<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>
+ <!-- no translation found for incognito_tab (5419458065370134289) -->
+ <skip />
<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 +102,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>
@@ -198,15 +200,7 @@
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Ripristina valori predef."</string>
<string name="pref_development_title" msgid="3263854204533056480">"Debug"</string>
<string name="pref_default_text_encoding" msgid="5742965543955558478">"Codifica testo"</string>
- <string-array name="pref_default_text_encoding_choices">
- <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
- <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
- <item msgid="6122474363777211732">"Cinese (GBK)"</item>
- <item msgid="373372275931607040">"Cinese (Big5)"</item>
- <item msgid="891615911084608570">"Giapponese (ISO-2022-JP)"</item>
- <item msgid="5589150448475151241">"Giapponese (SHIFT_JIS)"</item>
- <item msgid="7356792686950371843">"Giapponese (EUC-JP)"</item>
- </string-array>
+ <!-- no translation found for pref_default_text_encoding_choices:7 (2193955365569270096) -->
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Codifica testo"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Problema di connettività dati"</string>
<string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Problemi con il file"</string>
@@ -290,4 +284,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>
+ <!-- no translation found for defaultBookmarksUpButton (2303951020715704735) -->
+ <skip />
+ <!-- no translation found for rlz_access_point (7165847807377650632) -->
+ <skip />
</resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index b5bf052..1f6984f 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -19,6 +19,8 @@
<string name="application_name" msgid="1935869255545976415">"ブラウザ"</string>
<string name="choose_upload" msgid="3649366287575002063">"アップロードするファイルを選択"</string>
<string name="new_tab" msgid="4505722538297295141">"新しいウィンドウ"</string>
+ <!-- no translation found for new_incognito_tab (5821404839654751753) -->
+ <skip />
<string name="active_tabs" msgid="3050623868203544623">"ウィンドウ"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"ブックマーク"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"よく使用"</string>
@@ -32,12 +34,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>
@@ -70,9 +66,11 @@
<string name="location" msgid="969988560160364559">"場所"</string>
<string name="name" msgid="5990326151488445481">"名前"</string>
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"ブックマークを追加"</string>
+ <!-- no translation found for save_to_bookmarks (8225229701567988479) -->
+ <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 +91,8 @@
<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>
+ <!-- no translation found for incognito_tab (5419458065370134289) -->
+ <skip />
<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 +102,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>
@@ -198,15 +200,7 @@
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"初期設定にリセット"</string>
<string name="pref_development_title" msgid="3263854204533056480">"デバッグ"</string>
<string name="pref_default_text_encoding" msgid="5742965543955558478">"テキストエンコード"</string>
- <string-array name="pref_default_text_encoding_choices">
- <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
- <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
- <item msgid="6122474363777211732">"中国語(GBK)"</item>
- <item msgid="373372275931607040">"中国語(Big5)"</item>
- <item msgid="891615911084608570">"日本語(ISO-2022-JP)"</item>
- <item msgid="5589150448475151241">"日本語(SHIFT_JIS)"</item>
- <item msgid="7356792686950371843">"日本語(EUC-JP)"</item>
- </string-array>
+ <!-- no translation found for pref_default_text_encoding_choices:7 (2193955365569270096) -->
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"テキストエンコード"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"データアクセスエラー"</string>
<string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"ファイルに問題があります"</string>
@@ -290,4 +284,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>
+ <!-- no translation found for defaultBookmarksUpButton (2303951020715704735) -->
+ <skip />
+ <!-- no translation found for rlz_access_point (7165847807377650632) -->
+ <skip />
</resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index bc15b43..0554a5c 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -19,6 +19,8 @@
<string name="application_name" msgid="1935869255545976415">"인터넷"</string>
<string name="choose_upload" msgid="3649366287575002063">"업로드할 파일 선택"</string>
<string name="new_tab" msgid="4505722538297295141">"새 창"</string>
+ <!-- no translation found for new_incognito_tab (5821404839654751753) -->
+ <skip />
<string name="active_tabs" msgid="3050623868203544623">"창"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"북마크"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"자주 방문한 페이지"</string>
@@ -32,12 +34,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>
@@ -70,9 +66,11 @@
<string name="location" msgid="969988560160364559">"URL"</string>
<string name="name" msgid="5990326151488445481">"이름"</string>
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"북마크에 추가"</string>
+ <!-- no translation found for save_to_bookmarks (8225229701567988479) -->
+ <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 +91,8 @@
<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>
+ <!-- no translation found for incognito_tab (5419458065370134289) -->
+ <skip />
<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 +102,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>
@@ -198,15 +200,7 @@
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"기본값으로 재설정"</string>
<string name="pref_development_title" msgid="3263854204533056480">"디버그"</string>
<string name="pref_default_text_encoding" msgid="5742965543955558478">"텍스트 인코딩"</string>
- <string-array name="pref_default_text_encoding_choices">
- <item msgid="7275223955790513818">"라틴어-1(ISO-8859-1)"</item>
- <item msgid="2456597866837587140">"유니코드(UTF-8)"</item>
- <item msgid="6122474363777211732">"중국어(GBK)"</item>
- <item msgid="373372275931607040">"중국어(Big5)"</item>
- <item msgid="891615911084608570">"일본어(ISO-2022-JP)"</item>
- <item msgid="5589150448475151241">"일본어(SHIFT_JIS)"</item>
- <item msgid="7356792686950371843">"일본어(EUC-JP)"</item>
- </string-array>
+ <!-- no translation found for pref_default_text_encoding_choices:7 (2193955365569270096) -->
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"텍스트 인코딩"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"데이터 연결에 문제 발생"</string>
<string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"파일 문제 발생"</string>
@@ -290,4 +284,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>
+ <!-- no translation found for defaultBookmarksUpButton (2303951020715704735) -->
+ <skip />
+ <!-- no translation found for rlz_access_point (7165847807377650632) -->
+ <skip />
</resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index f1341cf..8388b58 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -19,6 +19,8 @@
<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>
+ <!-- no translation found for new_incognito_tab (5821404839654751753) -->
+ <skip />
<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 +34,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>
@@ -70,9 +66,11 @@
<string name="location" msgid="969988560160364559">"Adresse"</string>
<string name="name" msgid="5990326151488445481">"Navn"</string>
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Legg til bokmerke"</string>
+ <!-- no translation found for save_to_bookmarks (8225229701567988479) -->
+ <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 +91,8 @@
<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>
+ <!-- no translation found for incognito_tab (5419458065370134289) -->
+ <skip />
<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 +102,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>
@@ -198,15 +200,7 @@
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Tilbakestill til standard"</string>
<string name="pref_development_title" msgid="3263854204533056480">"Avlusing"</string>
<string name="pref_default_text_encoding" msgid="5742965543955558478">"Tekstkoding"</string>
- <string-array name="pref_default_text_encoding_choices">
- <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
- <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
- <item msgid="6122474363777211732">"Kinesisk (GBK)"</item>
- <item msgid="373372275931607040">"Kinesisk (Big5)"</item>
- <item msgid="891615911084608570">"Japansk (ISO-2022-JP)"</item>
- <item msgid="5589150448475151241">"Japansk (SHIFT_JIS)"</item>
- <item msgid="7356792686950371843">"Japansk (EUC-JP)"</item>
- </string-array>
+ <!-- no translation found for pref_default_text_encoding_choices:7 (2193955365569270096) -->
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Tekstkoding"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Datatilkoblingsproblem"</string>
<string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Problem med fil"</string>
@@ -290,4 +284,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>
+ <!-- no translation found for defaultBookmarksUpButton (2303951020715704735) -->
+ <skip />
+ <!-- no translation found for rlz_access_point (7165847807377650632) -->
+ <skip />
</resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 5a2eb1b..913fac3 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -19,6 +19,8 @@
<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>
+ <!-- no translation found for new_incognito_tab (5821404839654751753) -->
+ <skip />
<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 +34,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>
@@ -70,9 +66,11 @@
<string name="location" msgid="969988560160364559">"Locatie"</string>
<string name="name" msgid="5990326151488445481">"Naam"</string>
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Bladwijzer toevoegen"</string>
+ <!-- no translation found for save_to_bookmarks (8225229701567988479) -->
+ <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 +91,8 @@
<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>
+ <!-- no translation found for incognito_tab (5419458065370134289) -->
+ <skip />
<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 +102,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>
@@ -198,15 +200,7 @@
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Standaardinstellingen"</string>
<string name="pref_development_title" msgid="3263854204533056480">"Foutopsporing"</string>
<string name="pref_default_text_encoding" msgid="5742965543955558478">"Tekstcodering"</string>
- <string-array name="pref_default_text_encoding_choices">
- <item msgid="7275223955790513818">"Latijns-1 (ISO-8859-1)"</item>
- <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
- <item msgid="6122474363777211732">"Chinees (GBK)"</item>
- <item msgid="373372275931607040">"Chinees (Big5)"</item>
- <item msgid="891615911084608570">"Japans (ISO-2022-JP)"</item>
- <item msgid="5589150448475151241">"Japans (SHIFT_JIS)"</item>
- <item msgid="7356792686950371843">"Japans (EUC-JP)"</item>
- </string-array>
+ <!-- no translation found for pref_default_text_encoding_choices:7 (2193955365569270096) -->
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Tekstcodering"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Probleem met gegevensverbinding"</string>
<string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Probleem met bestand"</string>
@@ -290,4 +284,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>
+ <!-- no translation found for defaultBookmarksUpButton (2303951020715704735) -->
+ <skip />
+ <!-- no translation found for rlz_access_point (7165847807377650632) -->
+ <skip />
</resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index a4ccc11..d16b40e 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -19,6 +19,8 @@
<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>
+ <!-- no translation found for new_incognito_tab (5821404839654751753) -->
+ <skip />
<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 +34,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>
@@ -70,9 +66,11 @@
<string name="location" msgid="969988560160364559">"Adres"</string>
<string name="name" msgid="5990326151488445481">"Nazwa"</string>
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Dodaj zakładkę"</string>
+ <!-- no translation found for save_to_bookmarks (8225229701567988479) -->
+ <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 +91,8 @@
<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>
+ <!-- no translation found for incognito_tab (5419458065370134289) -->
+ <skip />
<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 +102,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>
@@ -198,15 +200,7 @@
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Przywróć wartości domyślne"</string>
<string name="pref_development_title" msgid="3263854204533056480">"Debugowanie"</string>
<string name="pref_default_text_encoding" msgid="5742965543955558478">"Kodowanie tekstu"</string>
- <string-array name="pref_default_text_encoding_choices">
- <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
- <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
- <item msgid="6122474363777211732">"chiński (GBK)"</item>
- <item msgid="373372275931607040">"chiński (Big5)"</item>
- <item msgid="891615911084608570">"japoński (ISO-2022-JP)"</item>
- <item msgid="5589150448475151241">"japoński (SHIFT_JIS)"</item>
- <item msgid="7356792686950371843">"japoński (EUC-JP)"</item>
- </string-array>
+ <!-- no translation found for pref_default_text_encoding_choices:7 (2193955365569270096) -->
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Kodowanie tekstu"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Problem z łącznością danych"</string>
<string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Problem z plikiem"</string>
@@ -290,4 +284,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>
+ <!-- no translation found for defaultBookmarksUpButton (2303951020715704735) -->
+ <skip />
+ <!-- no translation found for rlz_access_point (7165847807377650632) -->
+ <skip />
</resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index dd3bc92..2e80596 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -19,6 +19,8 @@
<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>
+ <!-- no translation found for new_incognito_tab (5821404839654751753) -->
+ <skip />
<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 +34,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>
@@ -70,9 +66,11 @@
<string name="location" msgid="969988560160364559">"Local"</string>
<string name="name" msgid="5990326151488445481">"Nome"</string>
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Adicionar marcador"</string>
+ <!-- no translation found for save_to_bookmarks (8225229701567988479) -->
+ <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 +91,8 @@
<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>
+ <!-- no translation found for incognito_tab (5419458065370134289) -->
+ <skip />
<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 +102,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>
@@ -198,15 +200,7 @@
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Repor as predefinições"</string>
<string name="pref_development_title" msgid="3263854204533056480">"Depuração"</string>
<string name="pref_default_text_encoding" msgid="5742965543955558478">"Codificação do texto"</string>
- <string-array name="pref_default_text_encoding_choices">
- <item msgid="7275223955790513818">"Latim-1 (ISO-8859-1)"</item>
- <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
- <item msgid="6122474363777211732">"Chinês (GBK)"</item>
- <item msgid="373372275931607040">"Chinês (Big5)"</item>
- <item msgid="891615911084608570">"Japonês (ISO-2022-JP)"</item>
- <item msgid="5589150448475151241">"Japonês (SHIFT_JIS)"</item>
- <item msgid="7356792686950371843">"Japonês (EUC-JP)"</item>
- </string-array>
+ <!-- no translation found for pref_default_text_encoding_choices:7 (2193955365569270096) -->
<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>
<string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Problemas com o ficheiro"</string>
@@ -290,4 +284,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>
+ <!-- no translation found for defaultBookmarksUpButton (2303951020715704735) -->
+ <skip />
+ <!-- no translation found for rlz_access_point (7165847807377650632) -->
+ <skip />
</resources>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index fde123d..5b875a4 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -19,6 +19,8 @@
<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>
+ <!-- no translation found for new_incognito_tab (5821404839654751753) -->
+ <skip />
<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 +34,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>
@@ -70,9 +66,11 @@
<string name="location" msgid="969988560160364559">"Local"</string>
<string name="name" msgid="5990326151488445481">"Nome"</string>
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Adicionar favorito"</string>
+ <!-- no translation found for save_to_bookmarks (8225229701567988479) -->
+ <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 +91,8 @@
<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>
+ <!-- no translation found for incognito_tab (5419458065370134289) -->
+ <skip />
<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 +102,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>
@@ -198,15 +200,7 @@
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Redefinir para o padrão"</string>
<string name="pref_development_title" msgid="3263854204533056480">"Depurar"</string>
<string name="pref_default_text_encoding" msgid="5742965543955558478">"Codificação de texto"</string>
- <string-array name="pref_default_text_encoding_choices">
- <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
- <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
- <item msgid="6122474363777211732">"Chinês (GBK)"</item>
- <item msgid="373372275931607040">"Chinês (Big5)"</item>
- <item msgid="891615911084608570">"Japonês (ISO-2022-JP)"</item>
- <item msgid="5589150448475151241">"Japonês (SHIFT_JIS)"</item>
- <item msgid="7356792686950371843">"Japonês (EUC-JP)"</item>
- </string-array>
+ <!-- no translation found for pref_default_text_encoding_choices:7 (2193955365569270096) -->
<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>
<string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Problema com o arquivo"</string>
@@ -290,4 +284,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>
+ <!-- no translation found for defaultBookmarksUpButton (2303951020715704735) -->
+ <skip />
+ <!-- no translation found for rlz_access_point (7165847807377650632) -->
+ <skip />
</resources>
diff --git a/res/values-rm/strings.xml b/res/values-rm/strings.xml
new file mode 100644
index 0000000..4ff0bfb
--- /dev/null
+++ b/res/values-rm/strings.xml
@@ -0,0 +1,296 @@
+<?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>
+ <string name="location" msgid="969988560160364559">"Adressa"</string>
+ <string name="name" msgid="5990326151488445481">"Num"</string>
+ <string name="http" msgid="2163722670597250102">"http://"</string>
+ <!-- no translation found for save_to_bookmarks (8225229701567988479) -->
+ <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>
+ <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>
+ <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 rlz_access_point (7165847807377650632) -->
+ <skip />
+</resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 6e19b2e..66c51f1 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -19,6 +19,8 @@
<string name="application_name" msgid="1935869255545976415">"Браузер"</string>
<string name="choose_upload" msgid="3649366287575002063">"Выберите файл для загрузки"</string>
<string name="new_tab" msgid="4505722538297295141">"Новое окно"</string>
+ <!-- no translation found for new_incognito_tab (5821404839654751753) -->
+ <skip />
<string name="active_tabs" msgid="3050623868203544623">"Окна"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Закладки"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"Часто посещаемые"</string>
@@ -32,12 +34,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>
@@ -70,9 +66,11 @@
<string name="location" msgid="969988560160364559">"URL-адрес"</string>
<string name="name" msgid="5990326151488445481">"Имя"</string>
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Добавить закладку"</string>
+ <!-- no translation found for save_to_bookmarks (8225229701567988479) -->
+ <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 +91,8 @@
<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>
+ <!-- no translation found for incognito_tab (5419458065370134289) -->
+ <skip />
<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 +102,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>
@@ -198,15 +200,7 @@
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Сброс настроек"</string>
<string name="pref_development_title" msgid="3263854204533056480">"Выполнить отладку"</string>
<string name="pref_default_text_encoding" msgid="5742965543955558478">"Кодировка текста"</string>
- <string-array name="pref_default_text_encoding_choices">
- <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
- <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
- <item msgid="6122474363777211732">"Китайская (GBK)"</item>
- <item msgid="373372275931607040">"Китайская (Big5)"</item>
- <item msgid="891615911084608570">"Японская (ISO-2022-JP)"</item>
- <item msgid="5589150448475151241">"Японская (SHIFT_JIS)"</item>
- <item msgid="7356792686950371843">"Японская (EUC-JP)"</item>
- </string-array>
+ <!-- no translation found for pref_default_text_encoding_choices:7 (2193955365569270096) -->
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Кодировка текста"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Проблема с подключением"</string>
<string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Проблема с файлом"</string>
@@ -290,4 +284,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>
+ <!-- no translation found for defaultBookmarksUpButton (2303951020715704735) -->
+ <skip />
+ <!-- no translation found for rlz_access_point (7165847807377650632) -->
+ <skip />
</resources>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index bbb698c..0172c51 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -19,6 +19,8 @@
<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>
+ <!-- no translation found for new_incognito_tab (5821404839654751753) -->
+ <skip />
<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 +34,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>
@@ -70,9 +66,11 @@
<string name="location" msgid="969988560160364559">"Plats"</string>
<string name="name" msgid="5990326151488445481">"Namn"</string>
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Lägg till bokmärke"</string>
+ <!-- no translation found for save_to_bookmarks (8225229701567988479) -->
+ <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>
@@ -93,7 +91,8 @@
<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>
+ <!-- no translation found for incognito_tab (5419458065370134289) -->
+ <skip />
<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 +102,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>
@@ -198,15 +200,7 @@
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Återställ standardinställn."</string>
<string name="pref_development_title" msgid="3263854204533056480">"Felsökning"</string>
<string name="pref_default_text_encoding" msgid="5742965543955558478">"Textkodning"</string>
- <string-array name="pref_default_text_encoding_choices">
- <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
- <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
- <item msgid="6122474363777211732">"Kinesisk (GBK)"</item>
- <item msgid="373372275931607040">"Kinesisk (Big5)"</item>
- <item msgid="891615911084608570">"Japansk (ISO-2022-JP)"</item>
- <item msgid="5589150448475151241">"Japansk (SHIFT_JIS)"</item>
- <item msgid="7356792686950371843">"Japansk (EUC-JP)"</item>
- </string-array>
+ <!-- no translation found for pref_default_text_encoding_choices:7 (2193955365569270096) -->
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Textkodning"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Problem med dataanslutning"</string>
<string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Problem med filen"</string>
@@ -290,4 +284,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>
+ <!-- no translation found for defaultBookmarksUpButton (2303951020715704735) -->
+ <skip />
+ <!-- no translation found for rlz_access_point (7165847807377650632) -->
+ <skip />
</resources>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 8f0826c..8e74daa 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -19,6 +19,8 @@
<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>
+ <!-- no translation found for new_incognito_tab (5821404839654751753) -->
+ <skip />
<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 +34,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>
@@ -70,9 +66,11 @@
<string name="location" msgid="969988560160364559">"Konum"</string>
<string name="name" msgid="5990326151488445481">"Ad"</string>
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"Favori ekle"</string>
+ <!-- no translation found for save_to_bookmarks (8225229701567988479) -->
+ <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 +91,8 @@
<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>
+ <!-- no translation found for incognito_tab (5419458065370134289) -->
+ <skip />
<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 +102,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>
@@ -198,15 +200,7 @@
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Varsayılana sıfırla"</string>
<string name="pref_development_title" msgid="3263854204533056480">"Hata Ayıklama"</string>
<string name="pref_default_text_encoding" msgid="5742965543955558478">"Metin kodlama"</string>
- <string-array name="pref_default_text_encoding_choices">
- <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
- <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
- <item msgid="6122474363777211732">"Çince (GBK)"</item>
- <item msgid="373372275931607040">"Çince (Big5)"</item>
- <item msgid="891615911084608570">"Japonca (ISO-2022-JP)"</item>
- <item msgid="5589150448475151241">"Japonca (SHIFT_JIS)"</item>
- <item msgid="7356792686950371843">"Japonca (EUC-JP)"</item>
- </string-array>
+ <!-- no translation found for pref_default_text_encoding_choices:7 (2193955365569270096) -->
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"Metin kodlama"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"Veri bağlantısı sorunu"</string>
<string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"Sorunlu dosya"</string>
@@ -290,4 +284,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>
+ <!-- no translation found for defaultBookmarksUpButton (2303951020715704735) -->
+ <skip />
+ <!-- no translation found for rlz_access_point (7165847807377650632) -->
+ <skip />
</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..0f17da3
--- /dev/null
+++ b/res/values-xlarge/styles.xml
@@ -0,0 +1,71 @@
+<?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:actionDropDownStyle">@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:displayOptions">hideHome</item>
+ </style>
+ <style name="ActionButton">
+ <item name="android:height">12dip</item>
+ <item name="android:background">@drawable/browserbarbutton</item>
+ </style>
+ <style name="ActionDropdown">
+ <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 a315f10..42b4ea4 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -19,6 +19,8 @@
<string name="application_name" msgid="1935869255545976415">"浏览器"</string>
<string name="choose_upload" msgid="3649366287575002063">"选择要上传的文件"</string>
<string name="new_tab" msgid="4505722538297295141">"新窗口"</string>
+ <!-- no translation found for new_incognito_tab (5821404839654751753) -->
+ <skip />
<string name="active_tabs" msgid="3050623868203544623">"窗口"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"书签"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"访问最多"</string>
@@ -32,12 +34,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>
@@ -70,9 +66,11 @@
<string name="location" msgid="969988560160364559">"地点"</string>
<string name="name" msgid="5990326151488445481">"姓名"</string>
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"添加书签"</string>
+ <!-- no translation found for save_to_bookmarks (8225229701567988479) -->
+ <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 +91,8 @@
<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>
+ <!-- no translation found for incognito_tab (5419458065370134289) -->
+ <skip />
<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 +102,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>
@@ -198,15 +200,7 @@
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"重置为默认设置"</string>
<string name="pref_development_title" msgid="3263854204533056480">"调试"</string>
<string name="pref_default_text_encoding" msgid="5742965543955558478">"文字编码"</string>
- <string-array name="pref_default_text_encoding_choices">
- <item msgid="7275223955790513818">"拉丁语-1 (ISO-8859-1)"</item>
- <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
- <item msgid="6122474363777211732">"中文 (GBK)"</item>
- <item msgid="373372275931607040">"中文 (Big5)"</item>
- <item msgid="891615911084608570">"日语 (ISO-2022-JP)"</item>
- <item msgid="5589150448475151241">"日语 (SHIFT_JIS)"</item>
- <item msgid="7356792686950371843">"日语 (EUC-JP)"</item>
- </string-array>
+ <!-- no translation found for pref_default_text_encoding_choices:7 (2193955365569270096) -->
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"文字编码"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"数据连接性问题"</string>
<string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"文件有问题"</string>
@@ -290,4 +284,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>
+ <!-- no translation found for defaultBookmarksUpButton (2303951020715704735) -->
+ <skip />
+ <!-- no translation found for rlz_access_point (7165847807377650632) -->
+ <skip />
</resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 33f3feb..c4585d0 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -19,6 +19,8 @@
<string name="application_name" msgid="1935869255545976415">"瀏覽器"</string>
<string name="choose_upload" msgid="3649366287575002063">"選擇要上載的檔案"</string>
<string name="new_tab" msgid="4505722538297295141">"新視窗"</string>
+ <!-- no translation found for new_incognito_tab (5821404839654751753) -->
+ <skip />
<string name="active_tabs" msgid="3050623868203544623">"視窗"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"書籤"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"常用網頁"</string>
@@ -32,12 +34,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>
@@ -70,9 +66,11 @@
<string name="location" msgid="969988560160364559">"位置"</string>
<string name="name" msgid="5990326151488445481">"名稱"</string>
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"新增書籤"</string>
+ <!-- no translation found for save_to_bookmarks (8225229701567988479) -->
+ <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 +91,8 @@
<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>
+ <!-- no translation found for incognito_tab (5419458065370134289) -->
+ <skip />
<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 +102,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>
@@ -198,15 +200,7 @@
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"還原至初始設定"</string>
<string name="pref_development_title" msgid="3263854204533056480">"偵錯"</string>
<string name="pref_default_text_encoding" msgid="5742965543955558478">"文字編碼"</string>
- <string-array name="pref_default_text_encoding_choices">
- <item msgid="7275223955790513818">"Latin-1 (ISO-8859-1)"</item>
- <item msgid="2456597866837587140">"Unicode (UTF-8)"</item>
- <item msgid="6122474363777211732">"中文 (GBK)"</item>
- <item msgid="373372275931607040">"中文 (Big5)"</item>
- <item msgid="891615911084608570">"日文 (ISO-2022-JP)"</item>
- <item msgid="5589150448475151241">"日文 (SHIFT_JIS)"</item>
- <item msgid="7356792686950371843">"日文 (EUC-JP)"</item>
- </string-array>
+ <!-- no translation found for pref_default_text_encoding_choices:7 (2193955365569270096) -->
<string name="pref_default_text_encoding_dialogtitle" msgid="5508255018084978547">"文字編碼"</string>
<string name="browserFrameNetworkErrorLabel" msgid="126892350904924893">"資料連線問題"</string>
<string name="browserFrameFileErrorLabel" msgid="8063691502792670367">"檔案有問題"</string>
@@ -290,4 +284,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>
+ <!-- no translation found for defaultBookmarksUpButton (2303951020715704735) -->
+ <skip />
+ <!-- no translation found for rlz_access_point (7165847807377650632) -->
+ <skip />
</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/strings.xml b/res/values/strings.xml
index acf8d3d..d6d3609 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>
@@ -138,12 +127,13 @@
<string name="name">Name</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, also displayed as
+ the title of the dialog used for adding a bookmark -->
+ <string name="save_to_bookmarks">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 +184,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 +206,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>
@@ -483,6 +478,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 -->
@@ -496,6 +493,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
@@ -748,4 +746,11 @@
<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 -->
+ <string name="defaultBookmarksUpButton">Bookmarks</string>
+
+ <!-- Access point for RLZ tracking. -->
+ <string name="rlz_access_point">Y1</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/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/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..f287e8e 100644
--- a/src/com/android/browser/AddBookmarkPage.java
+++ b/src/com/android/browser/AddBookmarkPage.java
@@ -51,6 +51,7 @@
private String mTouchIconUrl;
private Bitmap mThumbnail;
private String mOriginalUrl;
+ private boolean mIsUrlEditable = true;
// Message IDs
private static final int SAVE_BOOKMARK = 100;
@@ -74,13 +75,24 @@
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
requestWindowFeature(Window.FEATURE_LEFT_ICON);
- setContentView(R.layout.browser_add_bookmark);
+
+ mMap = getIntent().getExtras();
+ if (mMap != null) {
+ mIsUrlEditable = mMap.getBoolean("url_editable", true);
+ }
+
+ if (mIsUrlEditable) {
+ setContentView(R.layout.browser_add_bookmark);
+ } else {
+ setContentView(R.layout.browser_add_bookmark_const_url);
+ }
+
setTitle(R.string.save_to_bookmarks);
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) {
@@ -96,8 +108,11 @@
mTitle = (EditText) findViewById(R.id.title);
mTitle.setText(title);
- mAddress = (EditText) findViewById(R.id.address);
- mAddress.setText(url);
+
+ if (mIsUrlEditable) {
+ mAddress = (EditText) findViewById(R.id.address);
+ mAddress.setText(url);
+ }
View.OnClickListener accept = mSaveBookmark;
mButton = (TextView) findViewById(R.id.OK);
@@ -135,7 +150,7 @@
final ContentResolver cr = getContentResolver();
Bookmarks.addBookmark(null, cr, url, title, thumbnail, true);
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 +188,14 @@
createHandler();
String title = mTitle.getText().toString().trim();
- String unfilteredUrl =
- BrowserActivity.fixUrl(mAddress.getText().toString());
+ String unfilteredUrl;
+ if (mIsUrlEditable) {
+ unfilteredUrl =
+ BrowserActivity.fixUrl(mAddress.getText().toString());
+ } else {
+ unfilteredUrl = mOriginalUrl;
+ }
+
boolean emptyTitle = title.length() == 0;
boolean emptyUrl = unfilteredUrl.trim().length() == 0;
Resources r = getResources();
@@ -183,9 +204,15 @@
mTitle.setError(r.getText(R.string.bookmark_needs_title));
}
if (emptyUrl) {
- mAddress.setError(r.getText(R.string.bookmark_needs_url));
+ if (mIsUrlEditable) {
+ mAddress.setError(r.getText(R.string.bookmark_needs_url));
+ } else {
+ Toast.makeText(AddBookmarkPage.this, R.string.bookmark_needs_url,
+ Toast.LENGTH_LONG).show();
+ }
}
return false;
+
}
String url = unfilteredUrl.trim();
try {
@@ -200,7 +227,12 @@
// can't save their bookmark. If it was null, we'll assume
// they meant http when we parse it in the WebAddress class.
if (scheme != null) {
- mAddress.setError(r.getText(R.string.bookmark_cannot_save_url));
+ if (mIsUrlEditable) {
+ mAddress.setError(r.getText(R.string.bookmark_cannot_save_url));
+ } else {
+ Toast.makeText(AddBookmarkPage.this, R.string.bookmark_cannot_save_url,
+ Toast.LENGTH_LONG).show();
+ }
return false;
}
WebAddress address;
@@ -216,7 +248,12 @@
}
}
} catch (URISyntaxException e) {
- mAddress.setError(r.getText(R.string.bookmark_url_not_valid));
+ if (mIsUrlEditable) {
+ mAddress.setError(r.getText(R.string.bookmark_url_not_valid));
+ } else {
+ Toast.makeText(AddBookmarkPage.this, R.string.bookmark_url_not_valid,
+ Toast.LENGTH_LONG).show();
+ }
return false;
}
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..3ead203 100644
--- a/src/com/android/browser/Bookmarks.java
+++ b/src/com/android/browser/Bookmarks.java
@@ -23,13 +23,13 @@
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
-import android.provider.Browser;
+import android.os.AsyncTask;
+import android.provider.BrowserContract;
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.
@@ -61,72 +61,18 @@
* This will usually be <code>true</code> except when bookmarks are
* added by a settings restore agent.
*/
- /* package */ static void addBookmark(Context context,
- ContentResolver cr, String url, String name,
- Bitmap thumbnail, boolean retainIcon) {
+ /* package */ static void addBookmark(Context context, ContentResolver cr, String url,
+ String name, Bitmap thumbnail, boolean retainIcon) {
// Want to append to the beginning of the list
- long creationTime = new Date().getTime();
- ContentValues map = new ContentValues();
+ ContentValues values = new ContentValues();
Cursor cursor = null;
try {
- cursor = Browser.getVisitedLike(cr, url);
- if (cursor.moveToFirst() && cursor.getInt(
- Browser.HISTORY_PROJECTION_BOOKMARK_INDEX) == 0) {
- // This means we have been to this site but not bookmarked
- // it, so convert the history item to a bookmark
- map.put(Browser.BookmarkColumns.CREATED, creationTime);
- map.put(Browser.BookmarkColumns.TITLE, name);
- map.put(Browser.BookmarkColumns.BOOKMARK, 1);
- map.put(Browser.BookmarkColumns.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);
- }
- }
+ 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));
+ cr.insert(BrowserContract.Bookmarks.CONTENT_URI, values);
} catch (IllegalStateException e) {
Log.e(LOGTAG, "addBookmark", e);
} finally {
@@ -155,40 +101,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 +151,91 @@
}
return false;
}
+
+ static final String QUERY_BOOKMARKS_WHERE =
+ BrowserContract.Bookmarks.IS_FOLDER + " == 0 AND (" +
+ BrowserContract.Bookmarks.URL + " == ? OR " +
+ BrowserContract.Bookmarks.URL + " == ? OR " +
+ BrowserContract.Bookmarks.URL + " LIKE ? || '%' OR " +
+ BrowserContract.Bookmarks.URL + " LIKE ? || '%')";
+
+ /* package */ static Cursor queryBookmarksForUrl(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 = Bookmarks.removeQuery(originalUrl);
+ String urlNoQuery = Bookmarks.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[] { BrowserContract.Bookmarks._ID };
+ return cr.query(BrowserContract.Bookmarks.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 updateBookmarkFavicon(final ContentResolver cr,
+ final String originalUrl, final String url, final Bitmap favicon) {
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... unused) {
+ final Cursor c =
+ Bookmarks.queryBookmarksForUrl(cr, originalUrl, url);
+ 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(BrowserContract.Bookmarks.FAVICON,
+ os.toByteArray());
+ do {
+ cr.update(ContentUris.withAppendedId(
+ BrowserContract.Bookmarks.CONTENT_URI, c.getLong(0)),
+ values, null, null);
+ } while (c.moveToNext());
+ }
+ c.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..9d5e3ed
--- /dev/null
+++ b/src/com/android/browser/BookmarksLoader.java
@@ -0,0 +1,48 @@
+/*
+ * 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.provider.BrowserContract.Bookmarks;
+
+public class BookmarksLoader extends CursorLoader {
+ public static final String ARG_ROOT_FOLDER = "root";
+
+ 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 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
+ };
+
+ public BookmarksLoader(Context context, int rootFolder) {
+ super(context, Bookmarks.CONTENT_URI_DEFAULT_FOLDER, PROJECTION, null, null, null);
+ }
+}
diff --git a/src/com/android/browser/BrowserActivity.java b/src/com/android/browser/BrowserActivity.java
index e98ab43..e1e1e18 100644
--- a/src/com/android/browser/BrowserActivity.java
+++ b/src/com/android/browser/BrowserActivity.java
@@ -16,12 +16,20 @@
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.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;
@@ -32,19 +40,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;
@@ -60,38 +65,38 @@
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.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;
@@ -102,41 +107,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".
@@ -172,6 +166,11 @@
*/
private FrameLayout mBrowserFrameLayout;
+ private boolean mXLargeScreenSize;
+
+ private Boolean mIsProviderPresent = null;
+ private Uri mRlzUri = null;
+
@Override
public void onCreate(Bundle icicle) {
if (LOGV_ENABLED) {
@@ -187,7 +186,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();
@@ -203,6 +206,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)
@@ -214,13 +224,25 @@
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();
+ actionBar.setBackgroundDrawable(getResources().
+ getDrawable(R.drawable.tabbar_bg));
+ 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();
@@ -263,59 +285,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(
@@ -323,6 +305,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.
@@ -337,7 +321,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();
@@ -354,6 +339,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());
@@ -373,8 +362,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
@@ -382,6 +369,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.
@@ -621,13 +612,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;
@@ -674,12 +668,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;
@@ -699,16 +698,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) {
@@ -772,7 +769,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
@@ -828,9 +825,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) {
@@ -838,28 +834,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);
+ }
}
}
@@ -876,21 +875,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);
}
/**
@@ -931,6 +943,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
@@ -992,8 +1007,6 @@
mTabControl.destroy();
WebIconDatabase.getInstance().close();
- unregisterReceiver(mPackageInstallationReceiver);
-
// Stop watching the default geolocation permissions
mSystemAllowGeolocationOrigins.stop();
mSystemAllowGeolocationOrigins = null;
@@ -1122,12 +1135,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
@@ -1154,7 +1169,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:
@@ -1278,6 +1292,7 @@
*/
/* package */ void removeActiveTabPage(boolean needToAttach) {
mContentView.removeView(mActiveTabsPage);
+ mTitleBar.setVisibility(View.VISIBLE);
mActiveTabsPage = null;
mMenuState = R.id.MAIN_MENU;
if (needToAttach) {
@@ -1286,24 +1301,22 @@
getTopWindow().requestFocus();
}
- private WebView showDialog(WebDialog dialog) {
- // Need to do something special for Tablet
- Tab tab = mTabControl.getCurrentTab();
- if (tab.getSubWebView() == null) {
- // If the find or select is being performed on the main webview,
- // remove the embedded title bar.
- WebView mainView = tab.getWebView();
- if (mainView != null) {
- mainView.setEmbeddedTitleBar(null);
- }
- }
+ @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.
@@ -1325,17 +1338,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();
@@ -1343,14 +1361,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:
@@ -1395,11 +1406,33 @@
break;
case R.id.find_menu_id:
- showFindDialog();
+ getTopWindow().showFindDialog(null);
break;
- case R.id.select_text_id:
- showSelectDialog();
+ 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;
+ 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 {
+ Toast.makeText(BrowserActivity.this, R.string.webarchive_failed,
+ Toast.LENGTH_SHORT).show();
+ }
break;
case R.id.page_info_menu_id:
@@ -1407,7 +1440,7 @@
break;
case R.id.classic_history_menu_id:
- bookmarksOrHistoryPicker(true);
+ bookmarksOrHistoryPicker(true, false);
break;
case R.id.title_bar_share_page_url:
@@ -1420,7 +1453,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:
@@ -1476,60 +1510,57 @@
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)));
+ i.putExtra("url_editable", false);
+ 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) {
@@ -1569,11 +1600,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();
@@ -1601,7 +1634,7 @@
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
- if (v instanceof TitleBar) {
+ if (v instanceof TitleBarBase) {
return;
}
WebView webview = (WebView) v;
@@ -1628,7 +1661,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,
@@ -1685,8 +1718,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();
@@ -1746,6 +1794,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.
@@ -1793,7 +1844,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.
@@ -1819,8 +1870,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();
@@ -1832,6 +1883,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;
@@ -1892,6 +1957,7 @@
return true;
}
+ @Override
public void run() {
Drawable oldWallpaper = BrowserActivity.this.getWallpaper();
try {
@@ -1935,14 +2001,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);
}
/**
@@ -2055,6 +2115,11 @@
}
mTabControl.setCurrentTab(mTabControl.getTab(currentIndex));
resetTitleIconAndProgress();
+ updateLockIconToLatest();
+
+ if (!mTabControl.hasAnyOpenIncognitoTabs()) {
+ WebView.cleanupPrivateBrowsingFiles(this);
+ }
}
/* package */ void goBackOnePageOrQuit() {
@@ -2153,7 +2218,7 @@
return true;
} else if (mCustomView == null && mActiveTabsPage == null
&& event.isLongPress()) {
- bookmarksOrHistoryPicker(true);
+ bookmarksOrHistoryPicker(true, false);
return true;
}
break;
@@ -2246,11 +2311,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");
@@ -2269,13 +2342,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);
@@ -2284,41 +2350,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);
@@ -2355,6 +2388,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;
}
}
};
@@ -2395,7 +2436,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;
}
@@ -2409,19 +2451,19 @@
protected Void doInBackground(Void... unused) {
Cursor c = null;
try {
- c = BrowserBookmarksAdapter.queryBookmarksForUrl(
- cr, originalUrl, url, true);
+ c = Bookmarks.queryBookmarksForUrl(
+ cr, originalUrl, url);
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,
+ values.put(BrowserContract.Bookmarks.THUMBNAIL,
os.toByteArray());
do {
cr.update(ContentUris.withAppendedId(
- Browser.BOOKMARKS_URI, c.getInt(0)),
+ BrowserContract.Bookmarks.CONTENT_URI, c.getLong(0)),
values, null, null);
} while (c.moveToNext());
}
@@ -2437,47 +2479,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
@@ -2486,8 +2512,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;
}
@@ -2497,8 +2522,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;
@@ -2539,7 +2563,7 @@
onProgressChanged(view, INITIAL_PROGRESS);
mDidStopLoad = false;
if (!mIsNetworkUp) createAndShowNetworkDialog();
- closeDialogs();
+ endActionMode();
if (mSettings.isTracing()) {
String host;
try {
@@ -2637,7 +2661,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)
@@ -2646,6 +2688,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
@@ -2669,6 +2716,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 {
@@ -2687,6 +2757,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;
@@ -2699,6 +2774,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) {
@@ -2707,18 +2787,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) {
@@ -2820,15 +2960,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);
}
// -------------------------------------------------------------------------
@@ -3015,7 +3278,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());
+ }
}
/**
@@ -3519,16 +3785,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
@@ -3545,8 +3828,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;
@@ -3567,12 +3867,78 @@
}
+ /* 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;
@@ -3581,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.
@@ -3603,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.
@@ -3778,54 +4183,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;
@@ -3846,8 +4203,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;
@@ -3961,7 +4316,8 @@
private Toast mStopToast;
- private TitleBar mTitleBar;
+ private TitleBarBase mTitleBar;
+ private TabBar mTabBar;
private LinearLayout mErrorConsoleContainer = null;
private boolean mShouldShowErrorConsole = false;
@@ -3977,8 +4333,6 @@
private IntentFilter mNetworkStateChangedFilter;
private BroadcastReceiver mNetworkStateIntentReceiver;
- private BroadcastReceiver mPackageInstallationReceiver;
-
private SystemAllowGeolocationOrigins mSystemAllowGeolocationOrigins;
// activity requestCode
@@ -3992,14 +4346,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/BrowserBookmarksAdapter.java b/src/com/android/browser/BrowserBookmarksAdapter.java
index 241b33b..6efb554 100644
--- a/src/com/android/browser/BrowserBookmarksAdapter.java
+++ b/src/com/android/browser/BrowserBookmarksAdapter.java
@@ -16,567 +16,42 @@
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;
-
- 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";
- } 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;
+ 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);
}
-
- /**
- * 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);
+
+ @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;
+ byte[] data = cursor.getBlob(BookmarksLoader.COLUMN_INDEX_THUMBNAIL);
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;
- }
- }
- if (position < 0) {
- return;
+ thumbnail = BitmapFactory.decodeByteArray(data, 0, data.length);
}
- 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;
+ if (thumbnail == null) {
+ thumb.setImageResource(R.drawable.browser_thumbnail);
} 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();
+ thumb.setImageBitmap(thumbnail);
}
}
}
diff --git a/src/com/android/browser/BrowserBookmarksPage.java b/src/com/android/browser/BrowserBookmarksPage.java
index dd01009..91785d5 100644
--- a/src/com/android/browser/BrowserBookmarksPage.java
+++ b/src/com/android/browser/BrowserBookmarksPage.java
@@ -18,73 +18,122 @@
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.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
+import android.content.Loader;
+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.provider.BrowserContract;
+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.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+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 {
- 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 String EXTRA_SHORTCUT = "create_shortcut";
+ static final String EXTRA_DISABLE_WINDOW = "disable_new_window";
+
+ 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: {
+ int rootFolder = 0;
+ if (args != null) {
+ args.getInt(BookmarksLoader.ARG_ROOT_FOLDER, 0);
+ }
+ return new BookmarksLoader(getActivity(), rootFolder);
+ }
+ }
+ throw new UnsupportedOperationException("Unknown loader id " + id);
+ }
+
+ @Override
+ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+ // Set the visibility of the empty vs. content views
+ if (data == null || data.getCount() == 0) {
+ mEmptyView.setVisibility(View.VISIBLE);
+ mContentView.setVisibility(View.GONE);
+ } else {
+ mEmptyView.setVisibility(View.GONE);
+ mContentView.setVisibility(View.VISIBLE);
+ }
+
+ // Fill in the "up" button if needed
+ BookmarksLoader bl = (BookmarksLoader) loader;
+ boolean rootFolder =
+ (BrowserContract.Bookmarks.CONTENT_URI_DEFAULT_FOLDER.equals(bl.getUri()));
+ if (rootFolder) {
+ mUpButton.setText(R.string.defaultBookmarksUpButton);
+ mUpButton.setEnabled(false);
+ } else {
+ mUpButton.setText(mFolderStack.peek().first);
+ mUpButton.setEnabled(true);
+ }
+
+ // Give the new data to the adapter
+ mAdapter.changeCursor(data);
+ }
+
+ @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 +147,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 +154,224 @@
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;
+
+ 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(mAdapter, mContextHeader, info.position);
+
+ menu.setHeaderView(mContextHeader);
+ }
+
+ private void populateBookmarkItem(BrowserBookmarksAdapter adapter, BookmarkItem item,
+ int position) {
+ Cursor cursor = (Cursor) mAdapter.getItem(position);
+ 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) {
+ 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);
+
+ mAdapter = new BrowserBookmarksAdapter(getActivity());
+ mGrid.setAdapter(mAdapter);
+
+ // Start the loader for the bookmark data
+ getLoaderManager().initLoader(LOADER_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;
+ }
+ if (mCreateShortcut) {
+ Intent intent = createShortcutIntent(position);
+ // the activity handles the intent in startActivityFromFragment
+ startActivity(intent);
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());
+ Cursor cursor = (Cursor) mAdapter.getItem(position);
+ boolean isFolder = cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0;
+ if (!isFolder) {
+ mCallbacks.onUrlSelected(getUrl(position), false);
} else {
- ed.putInt(PREF_BOOKMARK_VIEW_MODE, mViewMode.ordinal());
- }
- 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);
- }
+ String title;
+ if (mFolderStack.size() != 0) {
+ title = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE);
+ } else {
+ // TODO localize
+ title = "Bookmarks";
}
- addContentView(mGridPage, FULL_SCREEN_PARAMS);
- if (mVerticalList != null) {
- ViewGroup parent = (ViewGroup) mVerticalList.getParent();
- if (parent != null) {
- parent.removeView(mVerticalList);
- }
- }
- } 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;
- }
- 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);
-
- 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;
- }
- }
- };
-
- 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();
- }
- }
- };
-
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));
+ 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 +379,104 @@
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.
+ * 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;
+ 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);
+ }
+ updateView();
+ }
+
+ 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();
+ 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.getText(R.string.delete_bookmark_warning).toString().replace(
+ "%s", cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE)))
.setPositiveButton(R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
- deleteBookmark(deletePos);
+ deleteBookmark(position);
}
})
.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);
+ ClipboardManager cm = (ClipboardManager) getActivity().getSystemService(
+ Context.CLIPBOARD_SERVICE);
+ cm.setPrimaryClip(ClipData.newRawUri(null, null, Uri.parse(text.toString())));
}
/**
* Delete the currently highlighted row.
*/
public void deleteBookmark(int position) {
- if (mBookmarksAdapter == null) return;
- mBookmarksAdapter.deleteRow(position);
+ Cursor cursor = (Cursor) mAdapter.getItem(position);
+ String url = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL);
+ String title = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE);
+ Bookmarks.removeFromBookmarks(null, getActivity().getContentResolver(), url, title);
+ updateView();
}
- @Override
- public void onBackPressed() {
- setResultToParent(RESULT_CANCELED, null);
- mCanceled = true;
- super.onBackPressed();
+ private void updateView() {
+ BookmarksLoader loader =
+ (BookmarksLoader) (Loader)(getLoaderManager().getLoader(LOADER_BOOKMARKS));
+ loader.forceLoad();
}
- // 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);
- }
- }
}
diff --git a/src/com/android/browser/BrowserDownloadAdapter.java b/src/com/android/browser/BrowserDownloadAdapter.java
index 0f8f721..6f498b6 100644
--- a/src/com/android/browser/BrowserDownloadAdapter.java
+++ b/src/com/android/browser/BrowserDownloadAdapter.java
@@ -56,7 +56,8 @@
private int mDateColumnId;
public BrowserDownloadAdapter(Context context, Cursor c, int index) {
- super(context, c, index);
+ super(context, index);
+ changeCursor(c);
mTitleColumnId = c.getColumnIndexOrThrow(Downloads.Impl.COLUMN_TITLE);
mDescColumnId = c.getColumnIndexOrThrow(Downloads.Impl.COLUMN_DESCRIPTION);
mStatusColumnId = c.getColumnIndexOrThrow(Downloads.Impl.COLUMN_STATUS);
diff --git a/src/com/android/browser/BrowserDownloadPage.java b/src/com/android/browser/BrowserDownloadPage.java
index 18faf8b..a897f99 100644
--- a/src/com/android/browser/BrowserDownloadPage.java
+++ b/src/com/android/browser/BrowserDownloadPage.java
@@ -18,13 +18,10 @@
import android.app.AlertDialog;
import android.app.ExpandableListActivity;
-import android.content.ActivityNotFoundException;
+import android.content.ContentUris;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.Intent;
-import android.content.ContentUris;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
@@ -34,17 +31,13 @@
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
-import android.view.LayoutInflater;
import android.view.Menu;
-import android.view.MenuItem;
import android.view.MenuInflater;
+import android.view.MenuItem;
import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.AdapterView;
import android.widget.ExpandableListView;
import java.io.File;
-import java.util.List;
/**
* View showing the user's current browser downloads
@@ -63,6 +56,7 @@
// Only meaningful while a ContentObserver is registered. The ContextMenu
// will be reopened on this View.
private View mSelectedView;
+ private Handler mHandler;
private final static String LOGTAG = "BrowserDownloadPage";
@Override
@@ -85,7 +79,7 @@
Downloads.Impl._DATA,
Downloads.Impl.COLUMN_MIME_TYPE},
null, Downloads.Impl.COLUMN_LAST_MODIFICATION + " DESC");
-
+ mHandler = new Handler();
// only attach everything to the listbox if we can access
// the download database. Otherwise, just show it empty
if (mDownloadCursor != null) {
@@ -241,8 +235,8 @@
*/
private class ChangeObserver extends ContentObserver {
private final Uri mTrack;
- public ChangeObserver(Uri track) {
- super(new Handler());
+ public ChangeObserver(Uri track, Handler handler) {
+ super(handler);
mTrack = track;
}
@@ -313,7 +307,7 @@
getContentResolver().unregisterContentObserver(
mContentObserver);
}
- mContentObserver = new ChangeObserver(track);
+ mContentObserver = new ChangeObserver(track, mHandler);
mSelectedView = v;
getContentResolver().registerContentObserver(track, false,
mContentObserver);
diff --git a/src/com/android/browser/BrowserHistoryPage.java b/src/com/android/browser/BrowserHistoryPage.java
index 23080f8..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/BrowserProvider.java b/src/com/android/browser/BrowserProvider.java
index a7da246..1320e83 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,58 +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
- && mSettings.getShowSearchSuggestions()
- && 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;
@@ -840,29 +845,63 @@
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
+ && mSettings.getShowSearchSuggestions()
+ && 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);
@@ -1068,4 +1107,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 58b66ee..e748174 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;
@@ -116,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 =
@@ -168,6 +169,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.
@@ -231,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);
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..1442683 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,21 @@
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.webkit.WebView;
+
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -45,10 +47,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 +68,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.queryBookmarksForUrl(mContentResolver,
+ mOriginalUrl, mUrl);
+ }
- AndroidHttpClient client = AndroidHttpClient.newInstance(
- mUserAgent);
+ boolean inBookmarksDatabase = mCursor != null && mCursor.getCount() > 0;
+
+ String url = values[0];
+
+ if (inBookmarksDatabase || mMessage != null) {
+ AndroidHttpClient client = AndroidHttpClient.newInstance(mUserAgent);
HttpHost httpHost = Proxy.getPreferredHttpHost(mActivity, url);
if (httpHost != null) {
ConnRouteParams.setDefaultProxy(client.getParams(), httpHost);
@@ -89,7 +123,6 @@
try {
HttpResponse response = client.execute(request);
-
if (response.getStatusLine().getStatusCode() == 200) {
HttpEntity entity = response.getEntity();
if (entity != null) {
@@ -97,7 +130,12 @@
if (content != null) {
Bitmap icon = BitmapFactory.decodeStream(
content, null, null);
- storeIcon(icon);
+ if (inBookmarksDatabase) {
+ storeIcon(icon);
+ } else if (mMessage != null) {
+ Bundle b = mMessage.getData();
+ b.putParcelable("touchIcon", icon);
+ }
}
}
}
@@ -109,9 +147,15 @@
client.close();
}
}
+
if (mCursor != null) {
mCursor.close();
}
+
+ if (mMessage != null) {
+ mMessage.sendToTarget();
+ }
+
return null;
}
@@ -136,13 +180,13 @@
final ByteArrayOutputStream os = new ByteArrayOutputStream();
icon.compress(Bitmap.CompressFormat.PNG, 100, os);
ContentValues values = new ContentValues();
- values.put(Browser.BookmarkColumns.TOUCH_ICON,
+ values.put(BrowserContract.Bookmarks.TOUCH_ICON,
os.toByteArray());
if (mCursor.moveToFirst()) {
do {
mContentResolver.update(ContentUris.withAppendedId(
- Browser.BOOKMARKS_URI, mCursor.getInt(0)),
+ BrowserContract.Bookmarks.CONTENT_URI, mCursor.getLong(0)),
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/PageProgressView.java b/src/com/android/browser/PageProgressView.java
new file mode 100644
index 0000000..183566a
--- /dev/null
+++ b/src/com/android/browser/PageProgressView.java
@@ -0,0 +1,94 @@
+
+/*
+ * 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.util.AttributeSet;
+import android.widget.ImageView;
+
+/**
+ *
+ */
+public class PageProgressView extends ImageView {
+
+ private int mProgress;
+ private int mMaxProgress;
+ private Rect mBounds;
+
+ /**
+ * @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) {
+ mMaxProgress = 10000;
+ mBounds = new Rect(0,0,0,0);
+ mProgress = 0;
+ }
+
+ @Override
+ public void onLayout(boolean f, int l, int t, int r, int b) {
+ mBounds.left = 0;
+ mBounds.right = (r - l) * mProgress / mMaxProgress;
+ mBounds.top = 0;
+ mBounds.bottom = b-t;
+ }
+
+ void setMaxProgress(int max) {
+ mMaxProgress = max;
+ }
+
+ void setProgress(int progress) {
+ mProgress = progress;
+ mBounds.right = getWidth()*mProgress/mMaxProgress;
+ invalidate();
+ }
+
+ @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/Tab.java b/src/com/android/browser/Tab.java
index 7019c8a..54f3088 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.updateBookmarkFavicon(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.updateBookmarkFavicon(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..cf0f27c
--- /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 setSelected(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.setSelected(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..d7435d7 100644
--- a/src/com/android/browser/TabControl.java
+++ b/src/com/android/browser/TabControl.java
@@ -29,6 +29,7 @@
import java.io.File;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.Vector;
class TabControl {
@@ -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,7 @@
TabControl(BrowserActivity activity) {
mActivity = activity;
mThumbnailDir = activity.getDir("thumbnails", 0);
+ mDisplayZoomControls = true;
}
File getThumbnailDir() {
@@ -68,6 +72,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 +144,7 @@
int getCurrentIndex() {
return mCurrentTab;
}
-
+
/**
* Given a Tab, find it's index
* @param Tab to find
@@ -150,32 +162,49 @@
}
/**
+ * 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;
+ }
+
+ /**
* Create a new tab.
* @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) {
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 +260,9 @@
// Remove it from the queue of viewed tabs.
mTabQueue.remove(t);
+ if (mTabChangeListener != null) {
+ mTabChangeListener.onRemoveTab(t);
+ }
return true;
}
@@ -277,29 +309,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 +370,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 +590,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 +692,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..b411416
--- /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.setSelected(false);
+ }
+ mSelected = position;
+ v = getSelectedTab();
+ if (v != null) {
+ v.setSelected(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.setSelected(false);
+ }
+
+ void addTab(View tab, int pos) {
+ mContentView.addView(tab, pos);
+ tab.setSelected(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..3408108
--- /dev/null
+++ b/src/com/android/browser/TitleBarXLarge.java
@@ -0,0 +1,222 @@
+/*
+ * 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.util.Log;
+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 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);
+ 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);
+ mUrlFocused.setUrlInputListener(this);
+ mUrlUnfocused.setOnFocusChangeListener(this);
+ }
+
+ public void onFocusChange(View v, boolean hasFocus) {
+ if (hasFocus) {
+ swapUrlContainer(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) {
+ onAction(mUrlFocused.getText().toString());
+ }
+ }
+
+ 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);
+ swapUrlContainer(false);
+ setDisplayTitle(text);
+ }
+
+ @Override
+ public void onDismiss() {
+ mBrowserActivity.getTabControl().getCurrentTopWebView().requestFocus();
+ mBrowserActivity.hideFakeTitleBar();
+ setDisplayTitle(mBrowserActivity.getTabControl().getCurrentWebView().getUrl());
+ swapUrlContainer(false);
+ }
+
+ @Override
+ public void onEdit(String text) {
+ setDisplayTitle(text);
+ if (text != null) {
+ mUrlFocused.setSelection(text.length());
+ }
+ }
+
+ 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.setVisibility(View.GONE);
+ mInLoad = false;
+ mStopButton.setImageDrawable(mReloadDrawable);
+ } else {
+ if (!mInLoad) {
+ mProgressView.setVisibility(View.VISIBLE);
+ mInLoad = true;
+ mStopButton.setImageDrawable(mStopDrawable);
+ }
+ mProgressView.setProgress(newProgress*10000/PROGRESS_MAX);
+ }
+ }
+
+ @Override
+ /* package */ void setDisplayTitle(String title) {
+ mUrlFocused.setText(title);
+ 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..96a5980
--- /dev/null
+++ b/src/com/android/browser/UrlInputView.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.browser;
+
+import android.app.SearchManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.Cursor;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.text.Editable;
+import android.text.SpannableStringBuilder;
+import android.text.TextWatcher;
+import android.text.style.BackgroundColorSpan;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.ActionMode;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnFocusChangeListener;
+import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.AutoCompleteTextView;
+import android.widget.CursorAdapter;
+import android.widget.Filterable;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
+
+/**
+ * url/search input view
+ * handling suggestions
+ */
+public class UrlInputView extends AutoCompleteTextView
+ implements OnFocusChangeListener, OnClickListener, OnEditorActionListener {
+
+ private UrlInputListener mListener;
+ private InputMethodManager mInputManager;
+ private SuggestionsAdapter mAdapter;
+
+ private OnFocusChangeListener mWrappedFocusListener;
+
+ 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(mContext,
+ BrowserProvider.getBookmarksSuggestions(cr, null));
+ setAdapter(mAdapter);
+ setSelectAllOnFocus(false);
+ }
+
+ @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);
+ }
+ }
+
+ @Override
+ public void onClick(View view) {
+ if (view instanceof ImageButton) {
+ // user pressed edit search button
+ String text = mAdapter.getViewString((View)view.getParent());
+ mListener.onEdit(text);
+ } else {
+ // user selected dropdown item
+ String url = mAdapter.getViewString(view);
+ finishInput(url);
+ }
+ }
+
+ 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);
+ }
+ }
+
+ @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);
+ }
+
+ /**
+ * adapter used by suggestion dropdown
+ */
+ class SuggestionsAdapter extends CursorAdapter implements Filterable {
+
+ private Cursor mLastCursor;
+ private ContentResolver mContent;
+ private int mIndexText1;
+ private int mIndexText2;
+ private int mIndexIcon;
+
+ public SuggestionsAdapter(Context context, Cursor c) {
+ super(context, c);
+ mContent = context.getContentResolver();
+ mIndexText1 = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1);
+ mIndexText2 = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2_URL);
+ mIndexIcon = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1);
+ }
+
+ public String getViewString(View view) {
+ TextView tv2 = (TextView) view.findViewById(android.R.id.text2);
+ if (tv2.getText().length() > 0) {
+ return tv2.getText().toString();
+ } else {
+ TextView tv1 = (TextView) view.findViewById(android.R.id.text1);
+ return tv1.getText().toString();
+ }
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ final LayoutInflater inflater = LayoutInflater.from(context);
+ final View view = inflater.inflate(
+ R.layout.url_dropdown_item, parent, false);
+ bindView(view, context, cursor);
+ return view;
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ 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 ic2 = view.findViewById(R.id.icon2);
+ tv1.setText(cursor.getString(mIndexText1));
+ String url = cursor.getString(mIndexText2);
+ tv2.setText((url != null) ? url : "");
+ ic2.setOnClickListener(UrlInputView.this);
+ // assume an id
+ try {
+ int id = Integer.parseInt(cursor.getString(mIndexIcon));
+ Drawable d = context.getResources().getDrawable(id);
+ ic1.setImageDrawable(d);
+ ic2.setVisibility((id == R.drawable.ic_search_category_suggest)? View.VISIBLE : View.GONE);
+ } catch (NumberFormatException nfx) {
+ }
+ view.setOnClickListener(UrlInputView.this);
+ }
+
+ @Override
+ public String convertToString(Cursor cursor) {
+ return cursor.getString(mIndexText1);
+ }
+
+ @Override
+ public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
+ if (getFilterQueryProvider() != null) {
+ return getFilterQueryProvider().runQuery(constraint);
+ }
+ mLastCursor = BrowserProvider.getBookmarksSuggestions(mContent,
+ (constraint != null) ? constraint.toString() : null);
+ return mLastCursor;
+ }
+
+ }
+
+}
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/provider/BrowserProvider2.java b/src/com/android/browser/provider/BrowserProvider2.java
new file mode 100644
index 0000000..28eed79
--- /dev/null
+++ b/src/com/android/browser/provider/BrowserProvider2.java
@@ -0,0 +1,780 @@
+/*
+ * 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.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.SyncStateContract;
+import android.provider.BrowserContract.Bookmarks;
+import android.provider.BrowserContract.ChromeSyncColumns;
+import android.provider.BrowserContract.History;
+import android.provider.BrowserContract.Searches;
+import android.provider.BrowserContract.SyncState;
+import android.provider.ContactsContract.RawContacts;
+import android.text.TextUtils;
+
+import java.util.HashMap;
+
+public class BrowserProvider2 extends SQLiteContentProvider {
+
+ static final Uri LEGACY_BROWSER_AUTHORITY_URI = Uri.parse("browser");
+
+ static final String TABLE_BOOKMARKS = "bookmarks";
+ static final String TABLE_HISTORY = "history";
+ static final String TABLE_SEARCHES = "searches";
+ static final String TABLE_SYNC_STATE = "syncstate";
+
+ static final String DEFAULT_SORT_HISTORY = History.DATE_LAST_VISITED + " 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 long FIXED_ID_CHROME_ROOT = 1;
+ static final long FIXED_ID_BOOKMARKS = 2;
+ static final long FIXED_ID_BOOKMARKS_BAR = 3;
+ static final long FIXED_ID_OTHER_BOOKMARKS = 4;
+
+ 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> 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 UriMatcher matcher = URI_MATCHER;
+ matcher.addURI(BrowserContract.AUTHORITY, "bookmarks", BOOKMARKS);
+ matcher.addURI(BrowserContract.AUTHORITY, "bookmarks/#", BOOKMARKS_ID);
+ matcher.addURI(BrowserContract.AUTHORITY, "bookmarks/folder", BOOKMARKS_FOLDER);
+ matcher.addURI(BrowserContract.AUTHORITY, "bookmarks/folder/#", BOOKMARKS_FOLDER_ID);
+ matcher.addURI(BrowserContract.AUTHORITY, "history", HISTORY);
+ matcher.addURI(BrowserContract.AUTHORITY, "history/#", HISTORY_ID);
+ matcher.addURI(BrowserContract.AUTHORITY, "searches", SEARCHES);
+ matcher.addURI(BrowserContract.AUTHORITY, "searches/#", SEARCHES_ID);
+ matcher.addURI(BrowserContract.AUTHORITY, "syncstate", SYNCSTATE);
+ matcher.addURI(BrowserContract.AUTHORITY, "syncstate/#", SYNCSTATE_ID);
+
+ // Bookmarks
+ HashMap<String, String> 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);
+
+ // 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, Bookmarks.TITLE);
+ map.put(History.URL, Bookmarks.URL);
+ map.put(History.FAVICON, Bookmarks.FAVICON);
+ map.put(History.THUMBNAIL, Bookmarks.THUMBNAIL);
+ map.put(History.TOUCH_ICON, Bookmarks.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);
+ }
+
+ 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 = 16;
+ 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.FAVICON + " BLOB," +
+ Bookmarks.THUMBNAIL + " BLOB," +
+ Bookmarks.TOUCH_ICON + " BLOB," +
+ Bookmarks.IS_FOLDER + " INTEGER NOT NULL DEFAULT 0," +
+ Bookmarks.PARENT + " INTEGER NOT NULL DEFAULT 0," +
+ 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.FAVICON + " BLOB," +
+ History.THUMBNAIL + " BLOB," +
+ History.TOUCH_ICON + " BLOB," +
+ 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_SEARCHES + " (" +
+ Searches._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
+ Searches.SEARCH + " TEXT," +
+ Searches.DATE + " LONG" +
+ ");");
+
+ 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);
+ 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
+
+ // Chrome sync root folder
+ values.put(Bookmarks._ID, FIXED_ID_CHROME_ROOT);
+ values.put(ChromeSyncColumns.SERVER_UNIQUE, ChromeSyncColumns.FOLDER_NAME_ROOT);
+ values.put(Bookmarks.TITLE, "Google Chrome");
+ values.put(Bookmarks.PARENT, 0);
+ values.put(Bookmarks.POSITION, 0);
+ values.put(Bookmarks.IS_FOLDER, true);
+ values.put(Bookmarks.DIRTY, true);
+ db.insertOrThrow(TABLE_BOOKMARKS, null, values);
+
+ // Bookmarks folder
+ values.put(Bookmarks._ID, FIXED_ID_BOOKMARKS);
+ values.put(ChromeSyncColumns.SERVER_UNIQUE, ChromeSyncColumns.FOLDER_NAME_BOOKMARKS);
+ values.put(Bookmarks.TITLE, "Bookmarks");
+ values.put(Bookmarks.PARENT, FIXED_ID_CHROME_ROOT);
+ values.put(Bookmarks.POSITION, 0);
+ values.put(Bookmarks.IS_FOLDER, true);
+ values.put(Bookmarks.DIRTY, true);
+ db.insertOrThrow(TABLE_BOOKMARKS, null, values);
+
+ // Bookmarks Bar folder
+ values.clear();
+ values.put(Bookmarks._ID, FIXED_ID_BOOKMARKS_BAR);
+ values.put(ChromeSyncColumns.SERVER_UNIQUE,
+ ChromeSyncColumns.FOLDER_NAME_BOOKMARKS_BAR);
+ values.put(Bookmarks.TITLE, "Bookmarks Bar");
+ values.put(Bookmarks.PARENT, FIXED_ID_BOOKMARKS);
+ values.put(Bookmarks.POSITION, 0);
+ values.put(Bookmarks.IS_FOLDER, true);
+ values.put(Bookmarks.DIRTY, true);
+ db.insertOrThrow(TABLE_BOOKMARKS, null, values);
+
+ // Other Bookmarks folder
+ values.clear();
+ values.put(Bookmarks._ID, FIXED_ID_OTHER_BOOKMARKS);
+ values.put(ChromeSyncColumns.SERVER_UNIQUE,
+ ChromeSyncColumns.FOLDER_NAME_OTHER_BOOKMARKS);
+ values.put(Bookmarks.TITLE, "Other Bookmarks");
+ values.put(Bookmarks.PARENT, FIXED_ID_BOOKMARKS);
+ values.put(Bookmarks.POSITION, 1000);
+ values.put(Bookmarks.IS_FOLDER, true);
+ values.put(Bookmarks.DIRTY, true);
+ db.insertOrThrow(TABLE_BOOKMARKS, null, values);
+
+ addDefaultBookmarks(db, FIXED_ID_BOOKMARKS_BAR);
+
+ // TODO remove this testing code
+ db.execSQL("INSERT INTO bookmarks (" +
+ Bookmarks.TITLE + ", " +
+ Bookmarks.URL + ", " +
+ Bookmarks.IS_FOLDER + "," +
+ Bookmarks.PARENT + "," +
+ Bookmarks.POSITION +
+ ") VALUES (" +
+ "'Google Reader', " +
+ "'http://reader.google.com', " +
+ "0," +
+ Long.toString(FIXED_ID_OTHER_BOOKMARKS) + "," +
+ 0 +
+ ");");
+ }
+
+ private void addDefaultBookmarks(SQLiteDatabase db, long parentId) {
+ final CharSequence[] bookmarks = getContext().getResources().getTextArray(
+ R.array.bookmarks);
+ int size = bookmarks.length;
+ try {
+ 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 +
+ ") VALUES (" +
+ "'" + bookmarks[i] + "', " +
+ "'" + bookmarkDestination + "', " +
+ "0," +
+ Long.toString(parentId) + "," +
+ Integer.toString(i) +
+ ");");
+ }
+ } 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_BROWSER_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();
+ switch (match) {
+ 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(
+ TABLE_BOOKMARKS + "." + Bookmarks._ID + "=?", selection);
+ 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(
+ TABLE_BOOKMARKS + "." + Bookmarks.PARENT + "=?", selection);
+ selectionArgs = DatabaseUtils.appendSelectionArgs(selectionArgs,
+ new String[] { Long.toString(ContentUris.parseId(uri)) });
+ }
+
+ if (TextUtils.isEmpty(sortOrder)) {
+ sortOrder = DEFAULT_BOOKMARKS_SORT_ORDER;
+ }
+
+ qb.setProjectionMap(BOOKMARKS_PROJECTION_MAP);
+ qb.setTables(TABLE_BOOKMARKS);
+ 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");
+ }
+
+ qb.setTables(TABLE_BOOKMARKS);
+ qb.setProjectionMap(BOOKMARKS_PROJECTION_MAP);
+ String bookmarksBarQuery = qb.buildQuery(projection,
+ Bookmarks.PARENT + "=? AND " + Bookmarks.IS_DELETED + "=0",
+ null, null, null, null, null);
+
+ qb.setProjectionMap(OTHER_BOOKMARKS_PROJECTION_MAP);
+ String otherBookmarksQuery = qb.buildQuery(projection,
+ Bookmarks._ID + "=?",
+ null, null, null, null, null);
+
+ String query = qb.buildUnionQuery(
+ new String[] { bookmarksBarQuery, otherBookmarksQuery },
+ DEFAULT_BOOKMARKS_SORT_ORDER, null);
+
+ return db.rawQuery(query, new String[] {
+ Long.toString(FIXED_ID_BOOKMARKS_BAR),
+ Long.toString(FIXED_ID_OTHER_BOOKMARKS)});
+ }
+
+ case HISTORY_ID: {
+ selection = DatabaseUtils.concatenateWhere(
+ TABLE_HISTORY + "._id=?", selection);
+ 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);
+ 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);
+ }
+
+ default: {
+ throw new UnsupportedOperationException("Unknown URL " + uri.toString());
+ }
+ }
+
+ Cursor cursor = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder);
+ 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 adapater
+ 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
+ if (!values.containsKey(Bookmarks.PARENT)) {
+ values.put(Bookmarks.PARENT, FIXED_ID_BOOKMARKS_BAR);
+ }
+
+ // 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));
+ }
+
+ id = db.insertOrThrow(TABLE_BOOKMARKS, Bookmarks.DIRTY, values);
+ break;
+ }
+
+ case HISTORY: {
+ id = db.insertOrThrow(TABLE_HISTORY, History.VISITS, values);
+ break;
+ }
+
+ case SEARCHES: {
+ id = insertSearchesInTransaction(db, values);
+ break;
+ }
+
+ case SYNCSTATE: {
+ id = mSyncHelper.insert(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();
+ }
+ }
+
+ @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 db.update(TABLE_HISTORY, 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);
+ }
+ }
+ throw new UnsupportedOperationException("Unknown update URI " + uri);
+ }
+
+ /**
+ * Does a query to find the matching bookmarks and updates each one with the provided values.
+ */
+ private 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 },
+ selection, selectionArgs, null);
+ try {
+ String[] args = new String[1];
+ // Mark the bookmark dirty if the caller isn't a sync adapter
+ if (!callerIsSyncAdapter) {
+ values = new ContentValues(values);
+ values.put(Bookmarks.DATE_MODIFIED, System.currentTimeMillis());
+ values.put(Bookmarks.DIRTY, 1);
+ }
+ 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);
+ }
+ } finally {
+ if (cursor != null) cursor.close();
+ }
+ return count;
+ }
+
+ private 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;
+ }
+ }
+}
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..f58cec1
--- /dev/null
+++ b/src/com/android/browser/widget/BookmarkStackWidgetService.java
@@ -0,0 +1,221 @@
+/*
+ * 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-renderer. */
+ 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 EXTRA_ID = "_id";
+ private static final String EXTRA_URL = "_url";
+
+ 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 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 () {
+
+ @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);
+ views.setOnClickPendingIntent(R.id.stack_item,
+ getOpenUrlPendingIntent(res.mUrl));
+
+ // 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() {
+ 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() {
+ }
+ };
+
+ private PendingIntent getOpenUrlPendingIntent(String url) {
+ Intent vi = new Intent(Intent.ACTION_VIEW);
+ vi.setData(Uri.parse(url));
+ return PendingIntent.getActivity(this, 0, vi, PendingIntent.FLAG_CANCEL_CURRENT);
+ }
+
+
+ // 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);
}
}