am 9c1d7d01: (-s ours) Import revised translations. DO NOT MERGE
Merge commit '9c1d7d017787b73bf4737465fbaf07a07c0f545e' into eclair-mr2
* commit '9c1d7d017787b73bf4737465fbaf07a07c0f545e':
Import revised translations. DO NOT MERGE
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 3d970ab..938dc27 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -150,10 +150,6 @@
android:configChanges="orientation|keyboardHidden">
</activity>
- <activity android:name="BrowserPluginList" android:label=""
- android:configChanges="orientation|keyboardHidden">
- </activity>
-
<activity android:name="WebsiteSettingsActivity" android:label=""
android:configChanges="orientation|keyboardHidden">
</activity>
@@ -183,13 +179,6 @@
<!-- Makes .BrowserActivity the search target for any activity in Browser -->
<meta-data android:name="android.app.default_searchable" android:value=".BrowserActivity" />
- <activity android:name="android.webkit.PluginActivity">
- <intent-filter>
- <action android:name="android.intent.webkit.PLUGIN" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </activity>
-
</application>
</manifest>
diff --git a/res/layout/title_bar.xml b/res/layout/title_bar.xml
index 1ea33fc..780c00a 100644
--- a/res/layout/title_bar.xml
+++ b/res/layout/title_bar.xml
@@ -29,6 +29,7 @@
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="fill_parent"
android:layout_height="5dip"
+ android:layout_marginLeft="1dip"
android:max="100"
/>
diff --git a/res/layout/website_settings_row.xml b/res/layout/website_settings_row.xml
index 4901ff1..d916978 100644
--- a/res/layout/website_settings_row.xml
+++ b/res/layout/website_settings_row.xml
@@ -18,15 +18,16 @@
android:drawingCacheQuality="auto"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
- android:gravity="center"
+ android:gravity="center_vertical"
android:padding="0dip">
<ImageView android:id="@+id/icon"
- android:layout_width="32dip"
- android:layout_height="32dip"
- android:layout_alignParentTop="true"
- android:layout_alignParentLeft="true"
- android:layout_alignParentBottom="true"
+ android:layout_width="20dip"
+ android:layout_height="20dip"
+ android:layout_marginLeft="18dip"
+ android:layout_marginRight="18dip"
+ android:layout_centerVertical="true"
+ android:background="@drawable/fav_icn_background"
android:padding="2dip" />
<LinearLayout android:id="@+id/features"
@@ -49,27 +50,37 @@
android:layout_height="32dip"
android:padding="2dip" />
+ <ImageView android:id="@+id/feature_icon"
+ android:layout_width="32dip"
+ android:layout_height="32dip"
+ android:padding="2dip"
+ android:layout_centerVertical="true"
+ android:layout_alignParentRight="true"
+ android:visibility="gone" />
</LinearLayout>
- <TextView android:id="@+id/title"
+ <LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
+ android:layout_toRightOf="@id/icon"
+ android:layout_toLeftOf="@id/features"
+ android:layout_centerVertical="true"
android:layout_alignWithParentIfMissing="true"
- android:layout_toRightOf="@id/icon"
- android:layout_toLeftOf="@id/features"
- android:layout_marginLeft="6dip"
- android:layout_marginTop="6dip"
- android:textAppearance="?android:attr/textAppearanceLarge"/>
+ android:orientation="vertical">
- <TextView android:id="@+id/subtitle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toRightOf="@id/icon"
- android:layout_toLeftOf="@id/features"
- android:layout_below="@id/title"
- android:layout_alignLeft="@id/title"
- android:layout_marginBottom="2dip"
- android:textAppearance="?android:attr/textAppearanceSmall"/>
+ <TextView android:id="@+id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:maxLines="2"
+ android:ellipsize="end" />
+ <TextView android:id="@+id/subtitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:visibility="gone"
+ android:singleLine="true"
+ android:ellipsize="end" />
+ </LinearLayout>
</RelativeLayout>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 11e4938..8dfbf90 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -16,10 +16,12 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="1935869255545976415">"Prohlížeč"</string>
+ <!-- no translation found for choose_upload (3649366287575002063) -->
+ <skip />
<string name="new_tab" msgid="4505722538297295141">"Nové okno"</string>
<string name="active_tabs" msgid="3050623868203544623">"Okna"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Záložky"</string>
- <string name="tab_most_visited" msgid="1077402532455000703">"Nejnavštěvovanější"</string>
+ <string name="tab_most_visited" msgid="1077402532455000703">"Často navštěvované"</string>
<string name="tab_history" msgid="1979267558744613746">"Historie"</string>
<string name="added_to_bookmarks" msgid="1020224130695956728">"Přidáno k záložkám"</string>
<string name="removed_from_bookmarks" msgid="6063705902028438800">"Odstraněno ze záložek"</string>
@@ -74,7 +76,7 @@
<string name="create_shortcut_bookmark" msgid="9202323987633899835">"Přidat odkaz na plochu"</string>
<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>
+ <string name="remove_from_bookmarks" msgid="4374080666576982775">"Odebrat ze záložek"</string>
<string name="remove_history_item" msgid="5021424935726728618">"Odstranit z historie"</string>
<string name="set_as_homepage" msgid="4752937379414905560">"Nastavit jako domovskou stránku"</string>
<string name="bookmark_saved" msgid="2766434679871317557">"Uloženo do záložek."</string>
@@ -84,10 +86,12 @@
<string name="bookmark_needs_url" msgid="7809876865972755158">"Záložka musí mít umístění."</string>
<string name="empty_bookmark" msgid="7008697085928540511">"Nelze vytvořit prázdnou záložku."</string>
<string name="bookmark_url_not_valid" msgid="6719785633980202419">"Adresa URL není platná."</string>
+ <!-- no translation found for bookmark_cannot_save_url (791722768778386941) -->
+ <skip />
<string name="delete_bookmark" msgid="2422989994934201992">"Smazat"</string>
<string name="bookmark_page" msgid="6845189305130307274">"Přidat poslední zobrazenou stránku do záložek"</string>
<string name="switch_to_thumbnails" msgid="5493351529609043151">"Zobrazit jako miniatury"</string>
- <string name="switch_to_list" msgid="8900531247982121055">"Zrušit přístup k poloze"</string>
+ <string name="switch_to_list" msgid="8900531247982121055">"Zobrazit jako seznam"</string>
<string name="current_page" msgid="7510129573681663135">"od "</string>
<string name="delete_bookmark_warning" msgid="758043186202032205">"Záložka <xliff:g id="BOOKMARK">%s</xliff:g> bude smazána."</string>
<string name="open_in_new_window" msgid="6596775546468054510">"Otevřít v novém okně"</string>
@@ -133,10 +137,10 @@
<string name="pref_content_block_popups" msgid="7808433807197256726">"Blokovat vyskakovací okna"</string>
<string name="pref_content_javascript" msgid="4570972030299516843">"Povolit JavaScript"</string>
<string name="pref_content_open_in_background" msgid="824123779725118663">"Otevřít na pozadí"</string>
- <string name="pref_content_plugins" msgid="7231944644794301582">"Povolit pluginy"</string>
+ <string name="pref_content_plugins" msgid="7231944644794301582">"Aktivovat pluginy"</string>
<string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"Otevírat nová okna za aktuálním oknem"</string>
<string name="pref_content_homepage" msgid="6082437160778559806">"Nastavit domovskou stránku"</string>
- <string name="pref_content_autofit" msgid="8260474534053660809">"Automaticky přizpůsobit"</string>
+ <string name="pref_content_autofit" msgid="8260474534053660809">"Automaticky přizpůsobit stránky"</string>
<string name="pref_content_autofit_summary" msgid="4587831659894879986">"Přizpůsobit velikost webových stránek obrazovce"</string>
<string name="pref_content_landscape_only" msgid="2022546812766219672">"Zobrazení pouze na šířku"</string>
<string name="pref_content_landscape_only_summary" msgid="1008238895535428855">"Zobrazit stránky pouze s displejem otočeným na šířku"</string>
@@ -144,12 +148,12 @@
<string name="pref_privacy_clear_cache" msgid="3380316479925886998">"Vymazat mezipaměť"</string>
<string name="pref_privacy_clear_cache_summary" msgid="2216463577207991454">"Vymazat všechen obsah a databáze uložené do místní mezipaměti"</string>
<string name="pref_privacy_clear_cache_dlg" msgid="5541011591300753881">"Obsah a databáze uložené v místní mezipaměti budou vymazány."</string>
- <string name="pref_privacy_clear_cookies" msgid="3095583579133780331">"Vymazat soubory cookie"</string>
+ <string name="pref_privacy_clear_cookies" msgid="3095583579133780331">"Vymazat všechny soubory cookie"</string>
<string name="pref_privacy_clear_cookies_summary" msgid="6962742063990677520">"Vymazat všechny soubory cookie prohlížeče"</string>
<string name="pref_privacy_clear_cookies_dlg" msgid="552855688091432682">"Všechny soubory cookie budou vymazány."</string>
<string name="pref_privacy_clear_history" msgid="8723795508825198477">"Vymazat historii"</string>
- <string name="pref_privacy_clear_history_summary" msgid="6868501330708940734">"Vymazat historii navigace v prohlížeči"</string>
- <string name="pref_privacy_clear_history_dlg" msgid="544903007914753853">"Historie navigace v prohlížeči bude vymazána."</string>
+ <string name="pref_privacy_clear_history_summary" msgid="6868501330708940734">"Vymazat historii stránek prohlížeče"</string>
+ <string name="pref_privacy_clear_history_dlg" msgid="544903007914753853">"Historie stránek prohlížeče bude vymazána."</string>
<string name="pref_privacy_clear_form_data" msgid="4232668196344383987">"Vymazat data formulářů"</string>
<string name="pref_privacy_clear_form_data_summary" msgid="1790390894719517167">"Vymazat všechna uložená data formulářů"</string>
<string name="pref_privacy_clear_form_data_dlg" msgid="4443621086781197928">"Všechna uložená data formulářů budou vymazána."</string>
@@ -157,14 +161,14 @@
<string name="pref_privacy_clear_passwords_summary" msgid="8856782718942903335">"Vymazat všechna uložená hesla"</string>
<string name="pref_privacy_clear_passwords_dlg" msgid="2083869328824248255">"Všechna uložená hesla budou vymazána."</string>
<string name="pref_privacy_enable_geolocation" msgid="1395040170290765686">"Povolit polohu"</string>
- <string name="pref_privacy_enable_geolocation_summary" msgid="8437020934664306205">"Povolit webovým stránkám žádat o přístup k informacím o vaší poloze"</string>
- <string name="pref_privacy_clear_geolocation_access" msgid="6649680770030042980">"Zrušit přístup k poloze"</string>
- <string name="pref_privacy_clear_geolocation_access_summary" msgid="7750143359497314679">"Zrušit všem webovým stránkám přístup k poloze"</string>
- <string name="pref_privacy_clear_geolocation_access_dlg" msgid="7327063124488827244">"Zrušit všem webovým stránkám přístup k poloze"</string>
+ <string name="pref_privacy_enable_geolocation_summary" msgid="8437020934664306205">"Povolit webovým stránkám požádat o přístup k informacím o vaší poloze"</string>
+ <string name="pref_privacy_clear_geolocation_access" msgid="6649680770030042980">"Zrušit přístup k informacím o poloze"</string>
+ <string name="pref_privacy_clear_geolocation_access_summary" msgid="7750143359497314679">"Zrušit přístup k informacím o poloze pro všechny webové stránky"</string>
+ <string name="pref_privacy_clear_geolocation_access_dlg" msgid="7327063124488827244">"Zrušit přístup k informacím o poloze pro všechny webové stránky"</string>
<string name="pref_security_title" msgid="5763978646932160021">"Nastavení zabezpečení"</string>
<string name="pref_security_remember_passwords" msgid="6492957683454529549">"Zapamatovat hesla"</string>
<string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"Ukládat uživatelská jména a hesla pro webové stránky"</string>
- <string name="pref_security_save_form_data" msgid="1213669802810198893">"Zapamatovat data formulářů"</string>
+ <string name="pref_security_save_form_data" msgid="1213669802810198893">"Zapamatovat data formuláře"</string>
<string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"Zapamatovat si data zadaná do formulářů pro další použití"</string>
<string name="pref_security_show_security_warning" msgid="8901135676266754559">"Zobrazit upozornění zabezpečení"</string>
<string name="pref_security_show_security_warning_summary" msgid="8968906112720511704">"Zobrazit upozornění, pokud dojde k problému se zabezpečením webu"</string>
@@ -186,10 +190,10 @@
<item msgid="3840999588443167001">"Blízko"</item>
</string-array>
<string name="pref_default_zoom_dialogtitle" msgid="6095974367125109021">"Výchozí přiblížení"</string>
- <string name="pref_content_load_page" msgid="2219810141690955452">"Otevírat stránky v náhledu"</string>
- <string name="pref_content_load_page_summary" msgid="8792093504054149369">"Zobrazit náhled nově otevřených stránek"</string>
+ <string name="pref_content_load_page" msgid="2219810141690955452">"Při otevírání stránek zobrazit přehled"</string>
+ <string name="pref_content_load_page_summary" msgid="8792093504054149369">"Zobrazit přehled nově otevřených stránek"</string>
<string name="pref_extras_title" msgid="3091250467679722382">"Upřesnit nastavení"</string>
- <string name="pref_extras_website_settings" msgid="67866640052455549">"Zrušit přístup k poloze"</string>
+ <string name="pref_extras_website_settings" msgid="67866640052455549">"Nastavení webových stránek"</string>
<string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Zobrazit pokročilá nastavení pro jednotlivé webové stránky"</string>
<string name="pref_extras_reset_default" msgid="8904000515846202110">"Obnovit výchozí"</string>
<string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Vymazat všechna data prohlížeče a obnovit všechna nastavení na výchozí hodnoty"</string>
@@ -213,13 +217,13 @@
<string name="browserFrameFormResubmitLabel" msgid="2685923472682180360">"Potvrdit"</string>
<string name="browserFrameFormResubmitMessage" msgid="2752182215695632138">"Stránka, kterou se pokoušíte zobrazit, obsahuje data, která již byla odeslána (POSTDATA). Pokud data odešlete znovu, jakákoli akce vykonaná pomocí formuláře na stránce bude provedena znovu (např. hledání či nákup online)."</string>
<string name="loadSuspendedTitle" msgid="675991625288706944">"Žádné připojení k síti"</string>
- <string name="loadSuspended" msgid="3133656588880851273">"Prohlížeč nemůže tuto stránku načíst, protože není k dispozici připojení k internetu."</string>
+ <string name="loadSuspended" msgid="3133656588880851273">"Prohlížeč nemůže tuto stránku načíst, protože není k dispozici připojení k Internetu."</string>
<string name="clear_history" msgid="5998307092715979619">"Vymazat historii"</string>
<string name="browser_history" msgid="1038987118290272525">"Nedávno navštívené stránky"</string>
<string name="empty_history" msgid="8738772352308207274">"Historie prohlížeče je prázdná."</string>
<string name="add_new_bookmark" msgid="8086367791400349049">"Přidat záložku..."</string>
<string name="add_bookmark_short" msgid="3783984330998103735">"Přidat"</string>
- <string name="search_hint" msgid="4647356319916631820">"Zrušit přístup k poloze"</string>
+ <string name="search_hint" msgid="4647356319916631820">"Vyhledejte nebo zadejte adresu URL"</string>
<string name="search_button_text" msgid="5235226933877634410">"Přejít"</string>
<string name="search_settings_description" msgid="1422401062529014107">"Záložky a webová historie"</string>
<string name="attention" msgid="3473639060042811244">"Upozornění"</string>
@@ -264,25 +268,29 @@
<string name="download_precondition_failed" msgid="8327584102874295580">"Stahování bylo přerušeno a nelze v něm pokračovat."</string>
<string name="activity_instrumentation_test_runner" msgid="8215091309334005029">"Testovací verze prohlížeče"</string>
<string name="search_the_web" msgid="6046130189241962337">"Vyhledat na webu"</string>
- <string name="webstorage_outofspace_notification_title" msgid="1160474608059771788">"Zrušit přístup k poloze"</string>
+ <string name="webstorage_outofspace_notification_title" msgid="1160474608059771788">"Paměť prohlížeče je plná"</string>
<string name="webstorage_outofspace_notification_text" msgid="7341075135051829692">"Kliknutím uvolníte místo."</string>
- <string name="webstorage_clear_data_title" msgid="689484577124333977">"Zrušit přístup k poloze"</string>
- <string name="webstorage_clear_data_summary" msgid="3523128713743907805">"Zrušit přístup k poloze"</string>
+ <string name="webstorage_clear_data_title" msgid="689484577124333977">"Vymazat uložená data"</string>
+ <string name="webstorage_clear_data_summary" msgid="3523128713743907805">"Odebrat všechny databáze přidružené k těmto webovým stránkám"</string>
<string name="webstorage_clear_data_dialog_title" msgid="345457466368974706">"Vymazat uložená data"</string>
- <string name="webstorage_clear_data_dialog_message" msgid="6678281256970470125">"Zrušit přístup k poloze"</string>
+ <string name="webstorage_clear_data_dialog_message" msgid="6678281256970470125">"Všechna data uložená těmito webovými stránkami budou smazána"</string>
<string name="webstorage_clear_data_dialog_ok_button" msgid="2516563534211898636">"Vymazat vše"</string>
<string name="webstorage_clear_data_dialog_cancel_button" msgid="2028867751958942762">"Zrušit"</string>
- <string name="webstorage_origin_summary_mb_stored" msgid="1985885826292236210">"Zrušit přístup k poloze"</string>
+ <string name="webstorage_origin_summary_mb_stored" msgid="1985885826292236210">"MB uloženo ve vašem telefonu"</string>
<string name="loading_video" msgid="4887871585216091096">"Načítání videa"</string>
<string name="geolocation_permissions_prompt_message" msgid="356796102004052471">"Web <xliff:g id="WEBSITE_ORIGIN">%s</xliff:g> požaduje informace o vaší poloze"</string>
<string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Sdílet polohu"</string>
<string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Odmítnout"</string>
<string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Zapamatovat předvolbu"</string>
- <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Zrušit přístup k poloze"</string>
+ <!-- no translation found for geolocation_permissions_prompt_toast_allowed (987286072035125498) -->
+ <skip />
+ <!-- no translation found for geolocation_permissions_prompt_toast_disallowed (7695100950212692515) -->
+ <skip />
+ <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Zrušit přístup k informacím o poloze"</string>
<string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Tyto stránky mohou aktuálně získat přístup k informacím o vaší poloze"</string>
- <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Zrušit přístup k poloze"</string>
- <string name="geolocation_settings_page_dialog_title" msgid="1549842043381347668">"Zrušit přístup k poloze"</string>
- <string name="geolocation_settings_page_dialog_message" msgid="7586671987576403993">"Přístup těchto webových stránek k poloze bude zrušen"</string>
+ <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Tyto stránky nemohou aktuálně získat přístup k informacím o vaší poloze"</string>
+ <string name="geolocation_settings_page_dialog_title" msgid="1549842043381347668">"Zrušit přístup k informacím o poloze"</string>
+ <string name="geolocation_settings_page_dialog_message" msgid="7586671987576403993">"Přístup těchto webových stránek k informacím o poloze bude zrušen"</string>
<string name="geolocation_settings_page_dialog_ok_button" msgid="4789434178048077287">"Zrušit přístup"</string>
<string name="geolocation_settings_page_dialog_cancel_button" msgid="7941036504673409747">"Zrušit"</string>
<string name="website_settings_clear_all" msgid="8739804325997655980">"Vymazat vše"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index a5dde55..4e670ca 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -16,6 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="1935869255545976415">"Browser"</string>
+ <!-- no translation found for choose_upload (3649366287575002063) -->
+ <skip />
<string name="new_tab" msgid="4505722538297295141">"Nyt vindue"</string>
<string name="active_tabs" msgid="3050623868203544623">"Vinduer"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Bogmærker"</string>
@@ -44,7 +46,7 @@
<string name="ssl_continue" msgid="8031515015829358457">"Fortsæt"</string>
<string name="security_warning" msgid="6607795404322797541">"Sikkerhedsadvarsel"</string>
<string name="view_certificate" msgid="1472768887529093862">"Vis certifikat"</string>
- <string name="ssl_untrusted" msgid="5369967226521102194">"Dette certifikat stammer ikke fra en troværdig kilde."</string>
+ <string name="ssl_untrusted" msgid="5369967226521102194">"Dette certifikat stammer ikke fra en troværdig autoritet."</string>
<string name="ssl_mismatch" msgid="558688832420069896">"Navnet på dette websted stemmer ikke overens med navnet på certifikatet."</string>
<string name="ssl_expired" msgid="5739349389499575559">"Dette certifikat er udløbet."</string>
<string name="ssl_not_yet_valid" msgid="2893167846212645846">"Dette certifikat er ikke gyldigt endnu."</string>
@@ -58,8 +60,8 @@
<string name="validity_period" msgid="57988851973181309">"Gyldighed:"</string>
<string name="issued_on" msgid="2082890654801808368">"Udstedt den:"</string>
<string name="expires_on" msgid="8061200430557020704">"Udløber den:"</string>
- <string name="retrieving_creds_dlg_msg" msgid="9207671133094039879">"Henter loginoplysninger ..."</string>
- <string name="stopping" msgid="4839698519340302982">"Stopper ..."</string>
+ <string name="retrieving_creds_dlg_msg" msgid="9207671133094039879">"Henter logindetaljer ..."</string>
+ <string name="stopping" msgid="4839698519340302982">"Standser ..."</string>
<string name="stop" msgid="5687251076030630074">"Stop"</string>
<string name="reload" msgid="8585220783228408062">"Opdater"</string>
<string name="back" msgid="8414603107175713668">"Tilbage"</string>
@@ -76,16 +78,18 @@
<string name="remove_bookmark" msgid="8407495852801410891">"Slet bogmærke"</string>
<string name="remove_from_bookmarks" msgid="4374080666576982775">"Fjern fra bogmærker"</string>
<string name="remove_history_item" msgid="5021424935726728618">"Fjern fra oversigt"</string>
- <string name="set_as_homepage" msgid="4752937379414905560">"Angiv som startside"</string>
+ <string name="set_as_homepage" msgid="4752937379414905560">"Indstil som startside"</string>
<string name="bookmark_saved" msgid="2766434679871317557">"Gemt i bogmærker."</string>
<string name="bookmark_not_saved" msgid="700600955089376724">"Bogmærket kunne ikke gemmes."</string>
<string name="homepage_set" msgid="8768087280310966395">"Startsiden er indstillet."</string>
- <string name="bookmark_needs_title" msgid="6245900436119218187">"Bogmærket skal have et navn."</string>
- <string name="bookmark_needs_url" msgid="7809876865972755158">"Bogmærket skal have en placering."</string>
+ <string name="bookmark_needs_title" msgid="6245900436119218187">"Bogmærke skal have et navn."</string>
+ <string name="bookmark_needs_url" msgid="7809876865972755158">"Bogmærke skal have en placering."</string>
<string name="empty_bookmark" msgid="7008697085928540511">"Der kan ikke oprettes et tomt bogmærke."</string>
- <string name="bookmark_url_not_valid" msgid="6719785633980202419">"Webadressen er ikke gyldig."</string>
+ <string name="bookmark_url_not_valid" msgid="6719785633980202419">"Webadresse er ikke gyldig."</string>
+ <!-- no translation found for bookmark_cannot_save_url (791722768778386941) -->
+ <skip />
<string name="delete_bookmark" msgid="2422989994934201992">"Slet"</string>
- <string name="bookmark_page" msgid="6845189305130307274">"Opret bogmærke for sidst viste side"</string>
+ <string name="bookmark_page" msgid="6845189305130307274">"Tilføj bogmærke ved sidst viste side"</string>
<string name="switch_to_thumbnails" msgid="5493351529609043151">"Miniaturevisning"</string>
<string name="switch_to_list" msgid="8900531247982121055">"Listevisning"</string>
<string name="current_page" msgid="7510129573681663135">"fra "</string>
@@ -97,11 +101,11 @@
<string name="select_dot" msgid="6299170761900561967">"Vælg tekst"</string>
<string name="view_tabs" msgid="1119097492003550564">"Vinduesoversigt"</string>
<string name="view_tabs_condensed" msgid="5803955493821945369">"Vinduer"</string>
- <string name="tab_picker_title" msgid="864478399057782913">"Aktuelle vinduer"</string>
+ <string name="tab_picker_title" msgid="864478399057782913">"Nuværende vinduer"</string>
<string name="tab_picker_view_tab" msgid="2984342364915347656">"Vis"</string>
<string name="tab_picker_new_tab" msgid="3080280018986866528">"Nyt vindue"</string>
<string name="tab_picker_remove_tab" msgid="630087809802479397">"Luk"</string>
- <string name="tab_picker_bookmark" msgid="1084409404198995477">"Opret et bogmærke"</string>
+ <string name="tab_picker_bookmark" msgid="1084409404198995477">"Tilføj et bogmærke"</string>
<string name="tab_picker_send_url" msgid="9102803487525950021">"Del link"</string>
<string name="bookmarks" msgid="1961279134885867815">"Bogmærker"</string>
<string name="shortcut_bookmark" msgid="3974876480401135895">"Bogmærke"</string>
@@ -111,7 +115,7 @@
<string name="share_page" msgid="593756995297268343">"Del side"</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>
+ <string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"Tilføj et bogmærke ved linket"</string>
<string name="contextmenu_savelink" msgid="5508554930832538184">"Gem link"</string>
<string name="contextmenu_sharelink" msgid="5392275392280130331">"Del link"</string>
<string name="contextmenu_copy" msgid="398860586635404030">"Kopier"</string>
@@ -134,13 +138,13 @@
<string name="pref_content_javascript" msgid="4570972030299516843">"Aktiver Javascript"</string>
<string name="pref_content_open_in_background" msgid="824123779725118663">"Åbn i baggrunden"</string>
<string name="pref_content_plugins" msgid="7231944644794301582">"Aktiver plugins"</string>
- <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"Åbn nye vinduer bag det aktive"</string>
- <string name="pref_content_homepage" msgid="6082437160778559806">"Angiv startside"</string>
- <string name="pref_content_autofit" msgid="8260474534053660809">"Tilpas sider automatisk"</string>
- <string name="pref_content_autofit_summary" msgid="4587831659894879986">"Tilpas websider, så de passer til skærmen"</string>
+ <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"Åbn nye vinduer bag det aktuelle"</string>
+ <string name="pref_content_homepage" msgid="6082437160778559806">"Indstil startside"</string>
+ <string name="pref_content_autofit" msgid="8260474534053660809">"Aut. tilpassede sider"</string>
+ <string name="pref_content_autofit_summary" msgid="4587831659894879986">"Formater websider, så de passer til skærmen"</string>
<string name="pref_content_landscape_only" msgid="2022546812766219672">"Kun liggende visning"</string>
- <string name="pref_content_landscape_only_summary" msgid="1008238895535428855">"Vis kun sider i den brede liggende retning"</string>
- <string name="pref_privacy_title" msgid="1052470980370846151">"Indstillinger for fortrolighed"</string>
+ <string name="pref_content_landscape_only_summary" msgid="1008238895535428855">"Vis kun sider i den bredere liggende retning"</string>
+ <string name="pref_privacy_title" msgid="1052470980370846151">"Fortrolighedsindstillinger"</string>
<string name="pref_privacy_clear_cache" msgid="3380316479925886998">"Ryd cache"</string>
<string name="pref_privacy_clear_cache_summary" msgid="2216463577207991454">"Ryd lokalt cachelagret indhold og databaser"</string>
<string name="pref_privacy_clear_cache_dlg" msgid="5541011591300753881">"Lokalt cachelagret indhold og databaser slettes."</string>
@@ -157,7 +161,7 @@
<string name="pref_privacy_clear_passwords_summary" msgid="8856782718942903335">"Ryd alle gemte adgangskoder"</string>
<string name="pref_privacy_clear_passwords_dlg" msgid="2083869328824248255">"Alle gemte adgangskoder slettes."</string>
<string name="pref_privacy_enable_geolocation" msgid="1395040170290765686">"Aktiver placering"</string>
- <string name="pref_privacy_enable_geolocation_summary" msgid="8437020934664306205">"Tillad, at websteder anmoder om adgang til din placering"</string>
+ <string name="pref_privacy_enable_geolocation_summary" msgid="8437020934664306205">"Tillad websteder at anmode om adgang til din placering"</string>
<string name="pref_privacy_clear_geolocation_access" msgid="6649680770030042980">"Ryd placeringsadgang"</string>
<string name="pref_privacy_clear_geolocation_access_summary" msgid="7750143359497314679">"Ryd placeringsadgang for alle websteder"</string>
<string name="pref_privacy_clear_geolocation_access_dlg" msgid="7327063124488827244">"Ryd placeringsadgang for alle websteder"</string>
@@ -167,9 +171,9 @@
<string name="pref_security_save_form_data" msgid="1213669802810198893">"Husk formulardata"</string>
<string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"Husk data, jeg indtaster i formularer, til senere brug"</string>
<string name="pref_security_show_security_warning" msgid="8901135676266754559">"Vis sikkerhedsadvarsler"</string>
- <string name="pref_security_show_security_warning_summary" msgid="8968906112720511704">"Vis en advarsel, hvis der er problemer med sikkerheden på et websted"</string>
+ <string name="pref_security_show_security_warning_summary" msgid="8968906112720511704">"Vis advarsler, hvis der er et problem med et websteds sikkerhed"</string>
<string name="pref_security_accept_cookies" msgid="3201367661925047989">"Accepter cookies"</string>
- <string name="pref_security_accept_cookies_summary" msgid="1465118934875026920">"Tillad, at websteder gemmer og læser \"cookie\"-data"</string>
+ <string name="pref_security_accept_cookies_summary" msgid="1465118934875026920">"Tillad websteder at gemme og læse \"cookie\"-data"</string>
<string name="pref_text_size" msgid="3827031324346612208">"Tekststørrelse"</string>
<string-array name="pref_text_size_choices">
<item msgid="4952686548944739548">"Lillebitte"</item>
@@ -182,14 +186,14 @@
<string name="pref_default_zoom" msgid="8076142259097187395">"Standardzoom"</string>
<string-array name="pref_default_zoom_choices">
<item msgid="549583171195154919">"Langt væk"</item>
- <item msgid="5619034257768161024">"Normal"</item>
+ <item msgid="5619034257768161024">"Mellemlangt"</item>
<item msgid="3840999588443167001">"Luk"</item>
</string-array>
<string name="pref_default_zoom_dialogtitle" msgid="6095974367125109021">"Standardzoom"</string>
<string name="pref_content_load_page" msgid="2219810141690955452">"Åbn sider i oversigt"</string>
<string name="pref_content_load_page_summary" msgid="8792093504054149369">"Vis oversigt over sider, som er åbnet for nylig"</string>
<string name="pref_extras_title" msgid="3091250467679722382">"Avancerede indstillinger"</string>
- <string name="pref_extras_website_settings" msgid="67866640052455549">"Indstillinger for websteder"</string>
+ <string name="pref_extras_website_settings" msgid="67866640052455549">"Webstedsindstillinger"</string>
<string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Vis avancerede indstillinger for individuelle websteder"</string>
<string name="pref_extras_reset_default" msgid="8904000515846202110">"Nulstil til standard"</string>
<string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Ryd alle browserdata, og nulstil alle indstillinger til standard"</string>
@@ -216,8 +220,8 @@
<string name="loadSuspended" msgid="3133656588880851273">"Browseren kan ikke indlæse denne side, fordi der ikke er nogen internetforbindelse."</string>
<string name="clear_history" msgid="5998307092715979619">"Ryd oversigt"</string>
<string name="browser_history" msgid="1038987118290272525">"Seneste besøgte sider"</string>
- <string name="empty_history" msgid="8738772352308207274">"Browseroversigten er tom."</string>
- <string name="add_new_bookmark" msgid="8086367791400349049">"Opret bogmærke ..."</string>
+ <string name="empty_history" msgid="8738772352308207274">"Browseroversigt er tom."</string>
+ <string name="add_new_bookmark" msgid="8086367791400349049">"Tilføj bogmærke ..."</string>
<string name="add_bookmark_short" msgid="3783984330998103735">"Tilføj"</string>
<string name="search_hint" msgid="4647356319916631820">"Søg efter eller indtast en webadresse"</string>
<string name="search_button_text" msgid="5235226933877634410">"Gå"</string>
@@ -226,14 +230,14 @@
<string name="popup_window_attempt" msgid="2673111696288657989">"Dette websted forsøger at åbne et pop op-vindue."</string>
<string name="allow" msgid="1157313689171991335">"Tillad"</string>
<string name="block" msgid="9172175889884707800">"Bloker"</string>
- <string name="too_many_windows_dialog_title" msgid="5175503564948906442">"Der kan ikke åbnes flere vinduer"</string>
- <string name="too_many_windows_dialog_message" msgid="1398571800233959583">"Der kan ikke åbnes et nyt vindue, fordi du allerede har åbnet det maksimale antal."</string>
+ <string name="too_many_windows_dialog_title" msgid="5175503564948906442">"Grænsen for vinduet er nået"</string>
+ <string name="too_many_windows_dialog_message" msgid="1398571800233959583">"Der kunne ikke åbnes et nyt vindue, fordi du allerede har åbnet det maksimale antal."</string>
<string name="too_many_subwindows_dialog_title" msgid="3805453941587725944">"Pop op er allerede åben"</string>
<string name="too_many_subwindows_dialog_message" msgid="5827289829907966657">"Der kunne ikke åbnes et nyt pop op-vindue, da der kun kan være ét åbent ad gangen."</string>
<string name="download_title" msgid="2122874021047565594">"Downloadoversigt"</string>
<string name="download_unknown_filename" msgid="4013465542563652175">"<Ukendt>"</string>
<string name="download_menu_open" msgid="4888327480367757513">"Åbn"</string>
- <string name="download_menu_clear" msgid="6264454531553418124">"Fjern fra listen"</string>
+ <string name="download_menu_clear" msgid="6264454531553418124">"Ryd fra listen"</string>
<string name="download_menu_cancel" msgid="2545333007601851574">"Annuller download"</string>
<string name="download_menu_cancel_all" msgid="2136550823151999166">"Annuller alle downloads"</string>
<string name="download_menu_clear_all" msgid="7423737413377703862">"Ryd liste"</string>
@@ -245,24 +249,24 @@
<string name="download_file_error_dlg_msg" msgid="5156405410324072471">"<xliff:g id="FILENAME">%s</xliff:g> kunne ikke downloades."\n"Frigør noget plads på din telefon, og prøv igen."</string>
<string name="download_failed_generic_dlg_title" msgid="6106781095337833391">"Download mislykkedes"</string>
<string name="download_no_sdcard_dlg_title" msgid="605904452159416792">"Der er intet SD-kort"</string>
- <string name="download_no_sdcard_dlg_msg" msgid="2616399456116301518">"Du skal bruge et SD-kort for at downloade <xliff:g id="FILENAME">%s</xliff:g>."</string>
- <string name="download_sdcard_busy_dlg_title" msgid="6877712666046917741">"SD-kortet er ikke tilgængeligt"</string>
+ <string name="download_no_sdcard_dlg_msg" msgid="2616399456116301518">"Et SD-kort er påkrævet for at downloade <xliff:g id="FILENAME">%s</xliff:g>."</string>
+ <string name="download_sdcard_busy_dlg_title" msgid="6877712666046917741">"SD-kort er ikke tilgængeligt"</string>
<string name="download_sdcard_busy_dlg_msg" msgid="3473883538192835204">"SD-kortet er optaget. Vælg \"Slå USB-lagring fra\" i meddelelsen for at tillade downloads."</string>
<string name="download_no_application" msgid="5054596425887523234">"Der blev ikke fundet et program, der kan åbne denne fil."</string>
<string name="retry" msgid="1835923075542266721">"Prøv igen"</string>
- <string name="no_downloads" msgid="3947445710685021498">"Downloadoversigten er tom."</string>
+ <string name="no_downloads" msgid="3947445710685021498">"Downloadoversigt er tom."</string>
<string name="download_error" msgid="413496839831257187">"Download mislykkedes."</string>
- <string name="download_success" msgid="2279041638155595203">"Download af <xliff:g id="FILE">%s</xliff:g> er afsluttet."</string>
+ <string name="download_success" msgid="2279041638155595203">"<xliff:g id="FILE">%s</xliff:g> Download afsluttet."</string>
<string name="download_running" msgid="2622942231322015059">"Downloader ..."</string>
<string name="download_pending" msgid="2599683668575349559">"Starter download ..."</string>
<string name="download_pending_network" msgid="6548714525679461053">"Venter på dataforbindelse ..."</string>
<string name="download_running_paused" msgid="6418029352085656495">"Venter på dataforbindelse ..."</string>
- <string name="download_canceled" msgid="6057083743144492515">"Download er annulleret."</string>
+ <string name="download_canceled" msgid="6057083743144492515">"Download annulleret."</string>
<string name="download_not_acceptable" msgid="313769696131563652">"Der kan ikke downloades. Indholdet understøttes ikke på denne telefon."</string>
<string name="download_file_error" msgid="1206648050615176113">"Download kan ikke afsluttes. Der er ikke nok plads."</string>
- <string name="download_length_required" msgid="9038605488460437406">"Der kan ikke downloades. Størrelsen på elementet kan ikke fastsættes."</string>
+ <string name="download_length_required" msgid="9038605488460437406">"Der kan ikke downloades. Størrelsen på elementet kan ikke afgøres."</string>
<string name="download_precondition_failed" msgid="8327584102874295580">"Download blev afbrudt. Den kan ikke genoptages."</string>
- <string name="activity_instrumentation_test_runner" msgid="8215091309334005029">"Testkørsel af browser"</string>
+ <string name="activity_instrumentation_test_runner" msgid="8215091309334005029">"Browsertestkørsel"</string>
<string name="search_the_web" msgid="6046130189241962337">"Søg på nettet"</string>
<string name="webstorage_outofspace_notification_title" msgid="1160474608059771788">"Browserlageret er fuldt"</string>
<string name="webstorage_outofspace_notification_text" msgid="7341075135051829692">"Klik her for at frigøre plads."</string>
@@ -278,15 +282,19 @@
<string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Del placering"</string>
<string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Afvis"</string>
<string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Husk indstilling"</string>
+ <!-- no translation found for geolocation_permissions_prompt_toast_allowed (987286072035125498) -->
+ <skip />
+ <!-- no translation found for geolocation_permissions_prompt_toast_disallowed (7695100950212692515) -->
+ <skip />
<string name="geolocation_settings_page_title" msgid="1745477985097536528">"Ryd placeringsadgang"</string>
- <string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Dette websted har i øjeblikket adgang til din placering"</string>
- <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Dette websted har i øjeblikket ikke adgang til din placering"</string>
+ <string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Dette websted kan i øjeblikket få adgang til din placering"</string>
+ <string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Dette websted har i øjeblikket adgang til din placering"</string>
<string name="geolocation_settings_page_dialog_title" msgid="1549842043381347668">"Ryd placeringsadgang"</string>
<string name="geolocation_settings_page_dialog_message" msgid="7586671987576403993">"Placeringsadgang ryddes for dette websted"</string>
<string name="geolocation_settings_page_dialog_ok_button" msgid="4789434178048077287">"Ryd adgang"</string>
<string name="geolocation_settings_page_dialog_cancel_button" msgid="7941036504673409747">"Annuller"</string>
<string name="website_settings_clear_all" msgid="8739804325997655980">"Ryd alle"</string>
- <string name="website_settings_clear_all_dialog_title" msgid="7791826325122461718">"Vil du rydde alle indstillinger for websteder?"</string>
+ <string name="website_settings_clear_all_dialog_title" msgid="7791826325122461718">"Vil du rydde alle webstedsindstillinger?"</string>
<string name="website_settings_clear_all_dialog_message" msgid="6150502090601476333">"Alle webstedsdata og placeringstilladelser slettes."</string>
<string name="website_settings_clear_all_dialog_ok_button" msgid="6401582240627669431">"Slet alle data"</string>
<string name="website_settings_clear_all_dialog_cancel_button" msgid="1896757051856611674">"Annuller"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index a865197..8435f77 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -16,6 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="1935869255545976415">"Browser"</string>
+ <!-- no translation found for choose_upload (3649366287575002063) -->
+ <skip />
<string name="new_tab" msgid="4505722538297295141">"Neues Fenster"</string>
<string name="active_tabs" msgid="3050623868203544623">"Fenster"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Lesezeichen"</string>
@@ -63,7 +65,7 @@
<string name="stop" msgid="5687251076030630074">"Anhalten"</string>
<string name="reload" msgid="8585220783228408062">"Aktualisieren"</string>
<string name="back" msgid="8414603107175713668">"Zurück"</string>
- <string name="forward" msgid="4288210890526641577">"Vorwärts"</string>
+ <string name="forward" msgid="4288210890526641577">"Weiter"</string>
<string name="save" msgid="5922311934992468496">"OK"</string>
<string name="do_not_save" msgid="6777633870113477714">"Abbrechen"</string>
<string name="location" msgid="969988560160364559">"Ort"</string>
@@ -71,7 +73,7 @@
<string name="http" msgid="2163722670597250102">"http://"</string>
<string name="save_to_bookmarks" msgid="588165100024086565">"Lesezeichen hinzufügen"</string>
<string name="edit_bookmark" msgid="5024089053490231905">"Lesezeichen bearbeiten"</string>
- <string name="create_shortcut_bookmark" msgid="9202323987633899835">"Verknüpfung auf dem Startbildschirm erstellen"</string>
+ <string name="create_shortcut_bookmark" msgid="9202323987633899835">"Shortcut zur Startseite hinzufügen"</string>
<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>
@@ -84,6 +86,8 @@
<string name="bookmark_needs_url" msgid="7809876865972755158">"Das Lesezeichen muss über einen Speicherort verfügen."</string>
<string name="empty_bookmark" msgid="7008697085928540511">"Sie können kein leeres Lesezeichen erstellen."</string>
<string name="bookmark_url_not_valid" msgid="6719785633980202419">"URL ist nicht gültig."</string>
+ <!-- no translation found for bookmark_cannot_save_url (791722768778386941) -->
+ <skip />
<string name="delete_bookmark" msgid="2422989994934201992">"Löschen"</string>
<string name="bookmark_page" msgid="6845189305130307274">"Lesezeichen für zuletzt besuchte Seite"</string>
<string name="switch_to_thumbnails" msgid="5493351529609043151">"Miniaturansicht"</string>
@@ -111,7 +115,7 @@
<string name="share_page" msgid="593756995297268343">"Seitenlink weiterleiten"</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>
+ <string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"Lesezeichen-Link"</string>
<string name="contextmenu_savelink" msgid="5508554930832538184">"Link speichern"</string>
<string name="contextmenu_sharelink" msgid="5392275392280130331">"Link weiterleiten"</string>
<string name="contextmenu_copy" msgid="398860586635404030">"Kopieren"</string>
@@ -133,7 +137,7 @@
<string name="pref_content_block_popups" msgid="7808433807197256726">"Popupfenster blockieren"</string>
<string name="pref_content_javascript" msgid="4570972030299516843">"JavaScript aktivieren"</string>
<string name="pref_content_open_in_background" msgid="824123779725118663">"Im Hintergrund öffnen"</string>
- <string name="pref_content_plugins" msgid="7231944644794301582">"Plug-ins aktivieren"</string>
+ <string name="pref_content_plugins" msgid="7231944644794301582">"Plug-Ins aktivieren"</string>
<string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"Neues Fenster hinter dem aktuellen Fenster öffnen"</string>
<string name="pref_content_homepage" msgid="6082437160778559806">"Startseite festlegen"</string>
<string name="pref_content_autofit" msgid="8260474534053660809">"Seiten autom. anpassen"</string>
@@ -163,7 +167,7 @@
<string name="pref_privacy_clear_geolocation_access_dlg" msgid="7327063124488827244">"Standortzugriff für alle Websites löschen"</string>
<string name="pref_security_title" msgid="5763978646932160021">"Sicherheitseinstellungen"</string>
<string name="pref_security_remember_passwords" msgid="6492957683454529549">"Passwörter merken"</string>
- <string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"Nutzernamen und Passwörter für Websites speichern"</string>
+ <string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"Benutzernamen und Passwörter für Websites speichern"</string>
<string name="pref_security_save_form_data" msgid="1213669802810198893">"Formulardaten merken"</string>
<string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"Daten in Formularen zur späteren Verwendung merken"</string>
<string name="pref_security_show_security_warning" msgid="8901135676266754559">"Sicherheitswarnungen"</string>
@@ -183,16 +187,16 @@
<string-array name="pref_default_zoom_choices">
<item msgid="549583171195154919">"Entfernt"</item>
<item msgid="5619034257768161024">"Mittel"</item>
- <item msgid="3840999588443167001">"Nah"</item>
+ <item msgid="3840999588443167001">"Schließen"</item>
</string-array>
<string name="pref_default_zoom_dialogtitle" msgid="6095974367125109021">"Standard-Zoom"</string>
<string name="pref_content_load_page" msgid="2219810141690955452">"Seiten in der Übersicht öffnen"</string>
- <string name="pref_content_load_page_summary" msgid="8792093504054149369">"Neue Seiten in der Übersicht anzeigen"</string>
+ <string name="pref_content_load_page_summary" msgid="8792093504054149369">"Übersicht über kürzlich geöffnete Seiten anzeigen"</string>
<string name="pref_extras_title" msgid="3091250467679722382">"Erweiterte Einstellungen"</string>
<string name="pref_extras_website_settings" msgid="67866640052455549">"Websiteeinstellungen"</string>
<string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Erweiterte Einstellungen für einzelne Websites anzeigen"</string>
<string name="pref_extras_reset_default" msgid="8904000515846202110">"Auf Standard zurücksetzen"</string>
- <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Alle Browserdaten löschen und Einstellungen zurücksetzen"</string>
+ <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Alle Browserdaten löschen und Einstellungen auf Standard zurücksetzen"</string>
<string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"Alle Browserdaten werden gelöscht. Alle Einstellungen werden auf die Standardeinstellung zurückgesetzt."</string>
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Auf Standardeinstellung zurücksetzen"</string>
<string name="pref_development_title" msgid="3263854204533056480">"Debuggen"</string>
@@ -278,6 +282,10 @@
<string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Standort freigeben"</string>
<string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Ablehnen"</string>
<string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Voreinstellung speichern"</string>
+ <!-- no translation found for geolocation_permissions_prompt_toast_allowed (987286072035125498) -->
+ <skip />
+ <!-- no translation found for geolocation_permissions_prompt_toast_disallowed (7695100950212692515) -->
+ <skip />
<string name="geolocation_settings_page_title" msgid="1745477985097536528">"Standortzugriff löschen"</string>
<string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Diese Website hat derzeit Zugriff auf Ihren Standort."</string>
<string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Diese Website hat derzeit keinen Zugriff auf Ihren Standort."</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 9273ec2..fff5203 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -16,6 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="1935869255545976415">"Internet"</string>
+ <!-- no translation found for choose_upload (3649366287575002063) -->
+ <skip />
<string name="new_tab" msgid="4505722538297295141">"Νέο παράθυρο"</string>
<string name="active_tabs" msgid="3050623868203544623">"Παράθυρα"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Σελιδοδείκτες"</string>
@@ -84,6 +86,8 @@
<string name="bookmark_needs_url" msgid="7809876865972755158">"Ο σελιδοδείκτης πρέπει να έχει μια τοποθεσία."</string>
<string name="empty_bookmark" msgid="7008697085928540511">"Δεν είναι δυνατή η δημιουργία κενού σελιδοδείκτη."</string>
<string name="bookmark_url_not_valid" msgid="6719785633980202419">"Μη έγκυρη διεύθυνση URL."</string>
+ <!-- no translation found for bookmark_cannot_save_url (791722768778386941) -->
+ <skip />
<string name="delete_bookmark" msgid="2422989994934201992">"Διαγραφή"</string>
<string name="bookmark_page" msgid="6845189305130307274">"Προσθήκη της τελευταίας σελίδας που προβλήθηκε στους σελιδοδείκτες"</string>
<string name="switch_to_thumbnails" msgid="5493351529609043151">"Προβολή μικρογραφίας"</string>
@@ -143,7 +147,7 @@
<string name="pref_privacy_title" msgid="1052470980370846151">"Ρυθμίσεις απορρήτου"</string>
<string name="pref_privacy_clear_cache" msgid="3380316479925886998">"Εκκαθάριση προσωρινής μνήμης"</string>
<string name="pref_privacy_clear_cache_summary" msgid="2216463577207991454">"Εκκαθάριση τοπικά αποθηκευμένου στη μνήμη cache περιεχομένου και βάσεων δεδομένων"</string>
- <string name="pref_privacy_clear_cache_dlg" msgid="5541011591300753881">"Περιεχόμενο και βάσεις δεδομένων που έχουν αποθηκευτεί στην τοπική προσωρινή μνήμη θα διαγραφούν."</string>
+ <string name="pref_privacy_clear_cache_dlg" msgid="5541011591300753881">"Περιεχόμενο και βάσεις δεδομένων που έχουν αποθηκευτεί στην τοπική προσωρινή μνήμη θα διαγραφού ."</string>
<string name="pref_privacy_clear_cookies" msgid="3095583579133780331">"Εκκαθάριση όλων των δεδομένων cookie"</string>
<string name="pref_privacy_clear_cookies_summary" msgid="6962742063990677520">"Εκκαθάριση όλων των cookie του προγράμματος περιήγησης"</string>
<string name="pref_privacy_clear_cookies_dlg" msgid="552855688091432682">"Όλα τα cookie θα διαγραφούν."</string>
@@ -183,7 +187,7 @@
<string-array name="pref_default_zoom_choices">
<item msgid="549583171195154919">"Μακριά"</item>
<item msgid="5619034257768161024">"Μέτριο"</item>
- <item msgid="3840999588443167001">"Κοντά"</item>
+ <item msgid="3840999588443167001">"Κλείσιμο"</item>
</string-array>
<string name="pref_default_zoom_dialogtitle" msgid="6095974367125109021">"Προεπιλεγμένο ζουμ"</string>
<string name="pref_content_load_page" msgid="2219810141690955452">"Άνοιγμα σελίδων στην επισκόπιση"</string>
@@ -278,6 +282,10 @@
<string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Κοινή χρήση τοποθεσίας"</string>
<string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Απόρριψη"</string>
<string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Διατήρηση προτίμησης"</string>
+ <!-- no translation found for geolocation_permissions_prompt_toast_allowed (987286072035125498) -->
+ <skip />
+ <!-- no translation found for geolocation_permissions_prompt_toast_disallowed (7695100950212692515) -->
+ <skip />
<string name="geolocation_settings_page_title" msgid="1745477985097536528">"Εκκαθάριση πρόσβασης τοποθεσίας"</string>
<string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Αυτήν τη στιγμή, αυτός ο ιστότοπος έχει πρόσβαση στην τοποθεσία σας"</string>
<string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Δεν είναι δυνατή η πρόσβαση στην τοποθεσία σας από αυτόν τον ιστότοπο"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 1b1f6e2..72b3c69 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -16,6 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="1935869255545976415">"Navegador"</string>
+ <!-- no translation found for choose_upload (3649366287575002063) -->
+ <skip />
<string name="new_tab" msgid="4505722538297295141">"Ventana nueva"</string>
<string name="active_tabs" msgid="3050623868203544623">"Windows"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Marcadores"</string>
@@ -84,6 +86,8 @@
<string name="bookmark_needs_url" msgid="7809876865972755158">"El marcador debe tener una ubicación."</string>
<string name="empty_bookmark" msgid="7008697085928540511">"No es posible crear un marcador vacío."</string>
<string name="bookmark_url_not_valid" msgid="6719785633980202419">"La URL no es válida."</string>
+ <!-- no translation found for bookmark_cannot_save_url (791722768778386941) -->
+ <skip />
<string name="delete_bookmark" msgid="2422989994934201992">"Eliminar"</string>
<string name="bookmark_page" msgid="6845189305130307274">"Última página vista del marcador"</string>
<string name="switch_to_thumbnails" msgid="5493351529609043151">"Vista en miniatura"</string>
@@ -278,6 +282,10 @@
<string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Compartir ubicación"</string>
<string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Rechazar"</string>
<string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Recordar la preferencia"</string>
+ <!-- no translation found for geolocation_permissions_prompt_toast_allowed (987286072035125498) -->
+ <skip />
+ <!-- no translation found for geolocation_permissions_prompt_toast_disallowed (7695100950212692515) -->
+ <skip />
<string name="geolocation_settings_page_title" msgid="1745477985097536528">"Borrar acceso a la ubicación"</string>
<string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Este sitio puede acceder a tu ubicación actualmente"</string>
<string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Este sitio no puede acceder a tu ubicación actualmente"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index a3cdf33..5626e63 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -16,6 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="1935869255545976415">"Navegador"</string>
+ <!-- no translation found for choose_upload (3649366287575002063) -->
+ <skip />
<string name="new_tab" msgid="4505722538297295141">"Nueva ventana"</string>
<string name="active_tabs" msgid="3050623868203544623">"Ventanas"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Marcadores"</string>
@@ -76,7 +78,7 @@
<string name="remove_bookmark" msgid="8407495852801410891">"Eliminar marcador"</string>
<string name="remove_from_bookmarks" msgid="4374080666576982775">"Eliminar de marcadores"</string>
<string name="remove_history_item" msgid="5021424935726728618">"Elliminar del historial"</string>
- <string name="set_as_homepage" msgid="4752937379414905560">"Establecer como página de inicio"</string>
+ <string name="set_as_homepage" msgid="4752937379414905560">"Establecer como página principal"</string>
<string name="bookmark_saved" msgid="2766434679871317557">"Guardar en marcadores"</string>
<string name="bookmark_not_saved" msgid="700600955089376724">"No se ha podido guardar el marcador."</string>
<string name="homepage_set" msgid="8768087280310966395">"Página principal establecida"</string>
@@ -84,6 +86,8 @@
<string name="bookmark_needs_url" msgid="7809876865972755158">"El marcador debe tener una ubicación."</string>
<string name="empty_bookmark" msgid="7008697085928540511">"No se puede crear un marcador vacío."</string>
<string name="bookmark_url_not_valid" msgid="6719785633980202419">"La URL no es válida."</string>
+ <!-- no translation found for bookmark_cannot_save_url (791722768778386941) -->
+ <skip />
<string name="delete_bookmark" msgid="2422989994934201992">"Suprimir"</string>
<string name="bookmark_page" msgid="6845189305130307274">"Marcar como última página vista"</string>
<string name="switch_to_thumbnails" msgid="5493351529609043151">"Vista de miniaturas"</string>
@@ -101,10 +105,10 @@
<string name="tab_picker_view_tab" msgid="2984342364915347656">"Ver"</string>
<string name="tab_picker_new_tab" msgid="3080280018986866528">"Nueva ventana"</string>
<string name="tab_picker_remove_tab" msgid="630087809802479397">"Cerrar"</string>
- <string name="tab_picker_bookmark" msgid="1084409404198995477">"Marcador"</string>
+ <string name="tab_picker_bookmark" msgid="1084409404198995477">"Marcar"</string>
<string name="tab_picker_send_url" msgid="9102803487525950021">"Compartir enlace"</string>
<string name="bookmarks" msgid="1961279134885867815">"Marcadores"</string>
- <string name="shortcut_bookmark" msgid="3974876480401135895">"Marcador"</string>
+ <string name="shortcut_bookmark" msgid="3974876480401135895">"Marcar"</string>
<string name="history" msgid="2451240511251410032">"Historial"</string>
<string name="menu_view_download" msgid="2124570321712995120">"Descargas"</string>
<string name="copy_page_url" msgid="7635062169011319208">"Copiar URL de página"</string>
@@ -130,12 +134,12 @@
<string name="pref_content_title" msgid="722227111894838633">"Configuración de contenido de la página"</string>
<string name="pref_content_load_images" msgid="2125616852957377561">"Cargar imágenes"</string>
<string name="pref_content_load_images_summary" msgid="5055874125248398584">"Mostrar imágenes en páginas web"</string>
- <string name="pref_content_block_popups" msgid="7808433807197256726">"Bloquear ventanas emergentes"</string>
+ <string name="pref_content_block_popups" msgid="7808433807197256726">"Bloquear ventanas emer."</string>
<string name="pref_content_javascript" msgid="4570972030299516843">"Habilitar JavaScript"</string>
<string name="pref_content_open_in_background" msgid="824123779725118663">"Abrir en segundo plano"</string>
<string name="pref_content_plugins" msgid="7231944644794301582">"Habilitar complementos"</string>
<string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"Abrir nuevas ventanas detrás de la actual"</string>
- <string name="pref_content_homepage" msgid="6082437160778559806">"Página de inicio"</string>
+ <string name="pref_content_homepage" msgid="6082437160778559806">"Establecer página principal"</string>
<string name="pref_content_autofit" msgid="8260474534053660809">"Ajustar páginas automát."</string>
<string name="pref_content_autofit_summary" msgid="4587831659894879986">"Configurar las páginas web para ajustarlas a la pantalla"</string>
<string name="pref_content_landscape_only" msgid="2022546812766219672">"Vista solo horizontal"</string>
@@ -144,15 +148,15 @@
<string name="pref_privacy_clear_cache" msgid="3380316479925886998">"Borrar caché"</string>
<string name="pref_privacy_clear_cache_summary" msgid="2216463577207991454">"Borrar bases de datos y contenido de la memoria caché local"</string>
<string name="pref_privacy_clear_cache_dlg" msgid="5541011591300753881">"Las bases de datos y el contenido se eliminarán de la memoria caché local."</string>
- <string name="pref_privacy_clear_cookies" msgid="3095583579133780331">"Borrar datos de cookies"</string>
+ <string name="pref_privacy_clear_cookies" msgid="3095583579133780331">"Borrar los datos de cookies"</string>
<string name="pref_privacy_clear_cookies_summary" msgid="6962742063990677520">"Borrar todas las cookies del navegador"</string>
<string name="pref_privacy_clear_cookies_dlg" msgid="552855688091432682">"Se eliminarán todas las cookies."</string>
<string name="pref_privacy_clear_history" msgid="8723795508825198477">"Borrar historial"</string>
<string name="pref_privacy_clear_history_summary" msgid="6868501330708940734">"Borrar el historial de exploración del navegador"</string>
<string name="pref_privacy_clear_history_dlg" msgid="544903007914753853">"Se eliminará el historial de exploración del navegador."</string>
<string name="pref_privacy_clear_form_data" msgid="4232668196344383987">"Borrar datos de formulario"</string>
- <string name="pref_privacy_clear_form_data_summary" msgid="1790390894719517167">"Borrar todos los datos de formulario guardados"</string>
- <string name="pref_privacy_clear_form_data_dlg" msgid="4443621086781197928">"Se eliminarán todos los datos de formulario guardados."</string>
+ <string name="pref_privacy_clear_form_data_summary" msgid="1790390894719517167">"Borrar todos los datos guardados del formulario"</string>
+ <string name="pref_privacy_clear_form_data_dlg" msgid="4443621086781197928">"Se eliminarán todos los datos guardados del formulario."</string>
<string name="pref_privacy_clear_passwords" msgid="4750234112289277480">"Borrar contraseñas"</string>
<string name="pref_privacy_clear_passwords_summary" msgid="8856782718942903335">"Borrar todas las contraseñas guardadas"</string>
<string name="pref_privacy_clear_passwords_dlg" msgid="2083869328824248255">"Se eliminarán todas las contraseñas guardadas."</string>
@@ -191,7 +195,7 @@
<string name="pref_extras_title" msgid="3091250467679722382">"Configuración avanzada"</string>
<string name="pref_extras_website_settings" msgid="67866640052455549">"Configuración del sitio web"</string>
<string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Ver configuración avanzada de sitios web individuales"</string>
- <string name="pref_extras_reset_default" msgid="8904000515846202110">"Restablecer valores predeterminados"</string>
+ <string name="pref_extras_reset_default" msgid="8904000515846202110">"Restablecer valores pred."</string>
<string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Borrar todos los datos del navegador y restablecer la configuración predeterminada"</string>
<string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"Se eliminarán todos los datos del navegador y se restablecerá la configuración predeterminada."</string>
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Restablecer valores predeterminados"</string>
@@ -213,7 +217,7 @@
<string name="browserFrameFormResubmitLabel" msgid="2685923472682180360">"OK"</string>
<string name="browserFrameFormResubmitMessage" msgid="2752182215695632138">"La página que intentas ver contiene datos que ya se han enviado (\"POSTDATA\"). Si reenvías los datos, se repetirá cualquier acción realizada por el formulario de la página (como las búsquedas o las compras online)."</string>
<string name="loadSuspendedTitle" msgid="675991625288706944">"Sin conexión de red"</string>
- <string name="loadSuspended" msgid="3133656588880851273">"El navegador no puede cargar esta página porque no hay conexión a Internet."</string>
+ <string name="loadSuspended" msgid="3133656588880851273">"El navegador no puede cargar esta página porque no existe conexión a Internet."</string>
<string name="clear_history" msgid="5998307092715979619">"Borrar historial"</string>
<string name="browser_history" msgid="1038987118290272525">"Páginas visitadas recientemente"</string>
<string name="empty_history" msgid="8738772352308207274">"El historial del navegador está vacío."</string>
@@ -229,7 +233,7 @@
<string name="too_many_windows_dialog_title" msgid="5175503564948906442">"Límite de ventanas alcanzado"</string>
<string name="too_many_windows_dialog_message" msgid="1398571800233959583">"No se ha podido abrir una ventana nueva porque ya se ha abierto el número máximo de ventanas admitido."</string>
<string name="too_many_subwindows_dialog_title" msgid="3805453941587725944">"Ventana emergente ya abierta"</string>
- <string name="too_many_subwindows_dialog_message" msgid="5827289829907966657">"No se ha podido abrir una nueva ventana emergente porque no se puede abrir más de una ventana emergente a la vez."</string>
+ <string name="too_many_subwindows_dialog_message" msgid="5827289829907966657">"No se ha podido abrir una nueva ventana emergente, porque no se puede abrir más de una ventana emergente a la vez."</string>
<string name="download_title" msgid="2122874021047565594">"Historial de descargas"</string>
<string name="download_unknown_filename" msgid="4013465542563652175">"<Desconocido>"</string>
<string name="download_menu_open" msgid="4888327480367757513">"Abrir"</string>
@@ -258,9 +262,9 @@
<string name="download_pending_network" msgid="6548714525679461053">"Esperando conexión de datos…"</string>
<string name="download_running_paused" msgid="6418029352085656495">"Esperando conexión de datos…"</string>
<string name="download_canceled" msgid="6057083743144492515">"Descarga cancelada"</string>
- <string name="download_not_acceptable" msgid="313769696131563652">"No se puede realizar la descarga porque el teléfono no admite el contenido que se quiere descargar."</string>
+ <string name="download_not_acceptable" msgid="313769696131563652">"No se puede realizar la descarga, porque el teléfono no admite el contenido que se quiere descargar."</string>
<string name="download_file_error" msgid="1206648050615176113">"No se puede completar la descarga porque no hay suficiente espacio."</string>
- <string name="download_length_required" msgid="9038605488460437406">"No se puede realizar la descarga porque no es posible determinar el tamaño del elemento."</string>
+ <string name="download_length_required" msgid="9038605488460437406">"No se puede realizar la descarga, porque no es posible determinar el tamaño del elemento."</string>
<string name="download_precondition_failed" msgid="8327584102874295580">"La descarga se ha interrumpido y no se puede reanudar."</string>
<string name="activity_instrumentation_test_runner" msgid="8215091309334005029">"Realizador de pruebas del navegador"</string>
<string name="search_the_web" msgid="6046130189241962337">"Buscar en la Web"</string>
@@ -278,6 +282,10 @@
<string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Compartir ubicación"</string>
<string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Rechazar"</string>
<string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Recordar preferencia"</string>
+ <!-- no translation found for geolocation_permissions_prompt_toast_allowed (987286072035125498) -->
+ <skip />
+ <!-- no translation found for geolocation_permissions_prompt_toast_disallowed (7695100950212692515) -->
+ <skip />
<string name="geolocation_settings_page_title" msgid="1745477985097536528">"Permitir acceso a la ubicación"</string>
<string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Este sitio puede acceder actualmente a tu ubicación."</string>
<string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Este sitio no puede acceder actualmente a tu ubicación."</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index aad7dc9..8d7cdca 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -16,6 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="1935869255545976415">"Navigateur"</string>
+ <!-- no translation found for choose_upload (3649366287575002063) -->
+ <skip />
<string name="new_tab" msgid="4505722538297295141">"Nouvelle fenêtre"</string>
<string name="active_tabs" msgid="3050623868203544623">"Fenêtres"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Favoris"</string>
@@ -84,13 +86,15 @@
<string name="bookmark_needs_url" msgid="7809876865972755158">"Le favori doit disposer d\'un emplacement."</string>
<string name="empty_bookmark" msgid="7008697085928540511">"Impossible de créer un favori vide."</string>
<string name="bookmark_url_not_valid" msgid="6719785633980202419">"L\'URL est incorrecte."</string>
+ <!-- no translation found for bookmark_cannot_save_url (791722768778386941) -->
+ <skip />
<string name="delete_bookmark" msgid="2422989994934201992">"Supprimer"</string>
<string name="bookmark_page" msgid="6845189305130307274">"Ajouter la dernière page consultée"</string>
<string name="switch_to_thumbnails" msgid="5493351529609043151">"Miniatures"</string>
<string name="switch_to_list" msgid="8900531247982121055">"Liste"</string>
<string name="current_page" msgid="7510129573681663135">"de "</string>
<string name="delete_bookmark_warning" msgid="758043186202032205">"Le favori \"<xliff:g id="BOOKMARK">%s</xliff:g>\" sera supprimé."</string>
- <string name="open_in_new_window" msgid="6596775546468054510">"Nouv. fenêtre"</string>
+ <string name="open_in_new_window" msgid="6596775546468054510">"Nouvelle fenêtre"</string>
<string name="new_window" msgid="8117889615360211551">"Nouvelle fenêtre"</string>
<string name="goto_dot" msgid="3895839050522602723">"Recherche"</string>
<string name="find_dot" msgid="6259312434696611957">"Rechercher sur la page"</string>
@@ -135,11 +139,11 @@
<string name="pref_content_open_in_background" msgid="824123779725118663">"Ouvrir en arrière-plan"</string>
<string name="pref_content_plugins" msgid="7231944644794301582">"Activer les plug-ins"</string>
<string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"Ouvrir les nouvelles fenêtres derrière la fenêtre actuelle"</string>
- <string name="pref_content_homepage" msgid="6082437160778559806">"Page d\'accueil"</string>
+ <string name="pref_content_homepage" msgid="6082437160778559806">"Configurer la page d\'accueil"</string>
<string name="pref_content_autofit" msgid="8260474534053660809">"Redimensionner"</string>
<string name="pref_content_autofit_summary" msgid="4587831659894879986">"Configurer les pages Web pour qu\'elles s\'ajustent à l\'écran"</string>
- <string name="pref_content_landscape_only" msgid="2022546812766219672">"Mode Paysage"</string>
- <string name="pref_content_landscape_only_summary" msgid="1008238895535428855">"Tjrs afficher les pages dans le sens de la largeur (orientation paysage)"</string>
+ <string name="pref_content_landscape_only" msgid="2022546812766219672">"Affichage en mode Paysage uniquement"</string>
+ <string name="pref_content_landscape_only_summary" msgid="1008238895535428855">"Toujours afficher les pages dans le sens de la largeur, en orientation paysage"</string>
<string name="pref_privacy_title" msgid="1052470980370846151">"Paramètres de confidentialité"</string>
<string name="pref_privacy_clear_cache" msgid="3380316479925886998">"Effacer le cache"</string>
<string name="pref_privacy_clear_cache_summary" msgid="2216463577207991454">"Supprimer les bases de données et le contenu mis localement en cache"</string>
@@ -153,7 +157,7 @@
<string name="pref_privacy_clear_form_data" msgid="4232668196344383987">"Eff. données formulaires"</string>
<string name="pref_privacy_clear_form_data_summary" msgid="1790390894719517167">"Effacer toutes les données de formulaire enregistrées"</string>
<string name="pref_privacy_clear_form_data_dlg" msgid="4443621086781197928">"Toutes les données de formulaire enregistrées seront supprimées."</string>
- <string name="pref_privacy_clear_passwords" msgid="4750234112289277480">"Eff. les mots de passe"</string>
+ <string name="pref_privacy_clear_passwords" msgid="4750234112289277480">"Effacer les mots de passe"</string>
<string name="pref_privacy_clear_passwords_summary" msgid="8856782718942903335">"Effacer tous les mots de passe enregistrés"</string>
<string name="pref_privacy_clear_passwords_dlg" msgid="2083869328824248255">"Tous les mots de passe enregistrés seront effacés."</string>
<string name="pref_privacy_enable_geolocation" msgid="1395040170290765686">"Activer la localisation"</string>
@@ -164,7 +168,7 @@
<string name="pref_security_title" msgid="5763978646932160021">"Paramètres de sécurité"</string>
<string name="pref_security_remember_passwords" msgid="6492957683454529549">"Mém. mots de passe"</string>
<string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"Enregistrer les noms d\'utilisateur et les mots de passe pour les sites Web"</string>
- <string name="pref_security_save_form_data" msgid="1213669802810198893">"Données de formulaires"</string>
+ <string name="pref_security_save_form_data" msgid="1213669802810198893">"Mém. données formulaire"</string>
<string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"Mémoriser les données saisies dans les formulaires pour les réutiliser"</string>
<string name="pref_security_show_security_warning" msgid="8901135676266754559">"Avertiss. de sécurité"</string>
<string name="pref_security_show_security_warning_summary" msgid="8968906112720511704">"Afficher un avertissement en cas de problème de sécurité d\'un site"</string>
@@ -186,13 +190,13 @@
<item msgid="3840999588443167001">"Proche"</item>
</string-array>
<string name="pref_default_zoom_dialogtitle" msgid="6095974367125109021">"Zoom par défaut"</string>
- <string name="pref_content_load_page" msgid="2219810141690955452">"Vue d\'ensemble des pages"</string>
+ <string name="pref_content_load_page" msgid="2219810141690955452">"Ouvrir les pages avec une vue d\'ensemble"</string>
<string name="pref_content_load_page_summary" msgid="8792093504054149369">"Afficher une vue d\'ensemble des pages qui viennent d\'être ouvertes"</string>
<string name="pref_extras_title" msgid="3091250467679722382">"Paramètres avancés"</string>
<string name="pref_extras_website_settings" msgid="67866640052455549">"Paramètres du site Web"</string>
<string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Afficher les paramètres avancés de sites Web individuels"</string>
- <string name="pref_extras_reset_default" msgid="8904000515846202110">"Rét. valeurs par défaut"</string>
- <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Effacer les données du navigateur et rétablir les paramètres par défaut"</string>
+ <string name="pref_extras_reset_default" msgid="8904000515846202110">"Rétablir valeurs par défaut"</string>
+ <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Effacer toutes les données du navigateur et rétablir les paramètres par défaut"</string>
<string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"Toutes les données du navigateur seront supprimées et les paramètres par défaut rétablis."</string>
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Rétablir les valeurs par défaut"</string>
<string name="pref_development_title" msgid="3263854204533056480">"Débogage"</string>
@@ -219,7 +223,7 @@
<string name="empty_history" msgid="8738772352308207274">"L\'historique du navigateur est vide."</string>
<string name="add_new_bookmark" msgid="8086367791400349049">"Ajouter aux favoris..."</string>
<string name="add_bookmark_short" msgid="3783984330998103735">"Ajouter"</string>
- <string name="search_hint" msgid="4647356319916631820">"Rech. ou entrer l\'URL"</string>
+ <string name="search_hint" msgid="4647356319916631820">"Rechercher ou entrer l\'URL"</string>
<string name="search_button_text" msgid="5235226933877634410">"Aller"</string>
<string name="search_settings_description" msgid="1422401062529014107">"Favoris et historique Web"</string>
<string name="attention" msgid="3473639060042811244">"Attention"</string>
@@ -278,7 +282,11 @@
<string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Partager ma position"</string>
<string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Refuser"</string>
<string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Mémoriser les préférences"</string>
- <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Accès données localis."</string>
+ <!-- no translation found for geolocation_permissions_prompt_toast_allowed (987286072035125498) -->
+ <skip />
+ <!-- no translation found for geolocation_permissions_prompt_toast_disallowed (7695100950212692515) -->
+ <skip />
+ <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Supprimer l\'accès aux données de localisation"</string>
<string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Ce site a actuellement accès à vos données de localisation."</string>
<string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Ce site n\'a actuellement pas accès à vos données de localisation."</string>
<string name="geolocation_settings_page_dialog_title" msgid="1549842043381347668">"Supprimer l\'accès aux données de localisation"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 91a53ce..af5c739 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -16,6 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="1935869255545976415">"Browser"</string>
+ <!-- no translation found for choose_upload (3649366287575002063) -->
+ <skip />
<string name="new_tab" msgid="4505722538297295141">"Nuova finestra"</string>
<string name="active_tabs" msgid="3050623868203544623">"Finestre"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Segnalibri"</string>
@@ -84,6 +86,8 @@
<string name="bookmark_needs_url" msgid="7809876865972755158">"Inserisci un URL per il segnalibro."</string>
<string name="empty_bookmark" msgid="7008697085928540511">"Impossibile creare un segnalibro vuoto."</string>
<string name="bookmark_url_not_valid" msgid="6719785633980202419">"URL non valido."</string>
+ <!-- no translation found for bookmark_cannot_save_url (791722768778386941) -->
+ <skip />
<string name="delete_bookmark" msgid="2422989994934201992">"Elimina"</string>
<string name="bookmark_page" msgid="6845189305130307274">"Aggiungi ultima pagina visualizzata ai segnalibri"</string>
<string name="switch_to_thumbnails" msgid="5493351529609043151">"Visualizzazione miniatura"</string>
@@ -138,13 +142,13 @@
<string name="pref_content_homepage" msgid="6082437160778559806">"Imposta home page"</string>
<string name="pref_content_autofit" msgid="8260474534053660809">"Adatta autom. pagine"</string>
<string name="pref_content_autofit_summary" msgid="4587831659894879986">"Adatta le pagine web allo schermo"</string>
- <string name="pref_content_landscape_only" msgid="2022546812766219672">"Visual. solo orizzontale"</string>
+ <string name="pref_content_landscape_only" msgid="2022546812766219672">"Visualizzazione solo orizzontale"</string>
<string name="pref_content_landscape_only_summary" msgid="1008238895535428855">"Visualizza le pagine solo con l\'orientamento dello schermo orizzontale più largo"</string>
<string name="pref_privacy_title" msgid="1052470980370846151">"Impostazioni privacy"</string>
<string name="pref_privacy_clear_cache" msgid="3380316479925886998">"Cancella cache"</string>
<string name="pref_privacy_clear_cache_summary" msgid="2216463577207991454">"Cancella i contenuti e i database memorizzati localmente nella cache"</string>
<string name="pref_privacy_clear_cache_dlg" msgid="5541011591300753881">"I contenuti e i database memorizzati localmente nella cache verranno eliminati."</string>
- <string name="pref_privacy_clear_cookies" msgid="3095583579133780331">"Canc. tutti i dati dei cookie"</string>
+ <string name="pref_privacy_clear_cookies" msgid="3095583579133780331">"Cancella tutti i dati dei cookie"</string>
<string name="pref_privacy_clear_cookies_summary" msgid="6962742063990677520">"Cancella tutti i cookie del browser"</string>
<string name="pref_privacy_clear_cookies_dlg" msgid="552855688091432682">"Verranno eliminati tutti i cookie."</string>
<string name="pref_privacy_clear_history" msgid="8723795508825198477">"Cancella cronologia"</string>
@@ -158,7 +162,7 @@
<string name="pref_privacy_clear_passwords_dlg" msgid="2083869328824248255">"Tutte le password salvate verranno eliminate."</string>
<string name="pref_privacy_enable_geolocation" msgid="1395040170290765686">"Attiva posizione"</string>
<string name="pref_privacy_enable_geolocation_summary" msgid="8437020934664306205">"Consenti ai siti di richiedere l\'accesso alla tua posizione"</string>
- <string name="pref_privacy_clear_geolocation_access" msgid="6649680770030042980">"Cancella accesso a posiz."</string>
+ <string name="pref_privacy_clear_geolocation_access" msgid="6649680770030042980">"Cancella accesso a posizione"</string>
<string name="pref_privacy_clear_geolocation_access_summary" msgid="7750143359497314679">"Cancella l\'accesso alla posizione per tutti i siti web"</string>
<string name="pref_privacy_clear_geolocation_access_dlg" msgid="7327063124488827244">"Cancella l\'accesso alla posizione per tutti i siti web"</string>
<string name="pref_security_title" msgid="5763978646932160021">"Impostazioni di protezione"</string>
@@ -186,15 +190,15 @@
<item msgid="3840999588443167001">"Chiudi"</item>
</string-array>
<string name="pref_default_zoom_dialogtitle" msgid="6095974367125109021">"Zoom predefinito"</string>
- <string name="pref_content_load_page" msgid="2219810141690955452">"Apri pag. in panoramica"</string>
+ <string name="pref_content_load_page" msgid="2219810141690955452">"Apri pagine in panoramica"</string>
<string name="pref_content_load_page_summary" msgid="8792093504054149369">"Visualizza la panoramica delle pagine appena aperte"</string>
<string name="pref_extras_title" msgid="3091250467679722382">"Impostazioni avanzate"</string>
<string name="pref_extras_website_settings" msgid="67866640052455549">"Impostazioni siti web"</string>
<string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Visualizza le impostazioni avanzate dei singoli siti web"</string>
- <string name="pref_extras_reset_default" msgid="8904000515846202110">"Ripristina valori predef."</string>
- <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Cancella tutti i dati del browser e ripristina tutte le imp. predef."</string>
+ <string name="pref_extras_reset_default" msgid="8904000515846202110">"Ripristina valori predefiniti"</string>
+ <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Cancella tutti i dati del browser e ripristina tutte le impostazioni predefinite"</string>
<string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"Verranno eliminati tutti i dati del browser e verranno ripristinate le impostazioni predefinite."</string>
- <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Ripristina valori predef."</string>
+ <string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Ripristina valori predefiniti"</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">
@@ -278,10 +282,14 @@
<string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Condividi posizione"</string>
<string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Rifiuta"</string>
<string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Ricorda la preferenza"</string>
- <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Cancella accesso a posiz."</string>
+ <!-- no translation found for geolocation_permissions_prompt_toast_allowed (987286072035125498) -->
+ <skip />
+ <!-- no translation found for geolocation_permissions_prompt_toast_disallowed (7695100950212692515) -->
+ <skip />
+ <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Cancella accesso a posizione"</string>
<string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Al momento questo sito può accedere alla tua posizione"</string>
<string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Al momento questo sito non può accedere alla tua posizione"</string>
- <string name="geolocation_settings_page_dialog_title" msgid="1549842043381347668">"Cancella accesso a posiz."</string>
+ <string name="geolocation_settings_page_dialog_title" msgid="1549842043381347668">"Cancella accesso a posizione"</string>
<string name="geolocation_settings_page_dialog_message" msgid="7586671987576403993">"L\'accesso alla posizione per questo sito web verrà cancellato"</string>
<string name="geolocation_settings_page_dialog_ok_button" msgid="4789434178048077287">"Cancella accesso"</string>
<string name="geolocation_settings_page_dialog_cancel_button" msgid="7941036504673409747">"Annulla"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 4cd44af..87b637b 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -16,6 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="1935869255545976415">"ブラウザ"</string>
+ <!-- no translation found for choose_upload (3649366287575002063) -->
+ <skip />
<string name="new_tab" msgid="4505722538297295141">"新しいウィンドウ"</string>
<string name="active_tabs" msgid="3050623868203544623">"ウィンドウ"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"ブックマーク"</string>
@@ -84,6 +86,8 @@
<string name="bookmark_needs_url" msgid="7809876865972755158">"場所を指定してください。"</string>
<string name="empty_bookmark" msgid="7008697085928540511">"空のブックマークは作成できません。"</string>
<string name="bookmark_url_not_valid" msgid="6719785633980202419">"無効なURLです。"</string>
+ <!-- no translation found for bookmark_cannot_save_url (791722768778386941) -->
+ <skip />
<string name="delete_bookmark" msgid="2422989994934201992">"削除"</string>
<string name="bookmark_page" msgid="6845189305130307274">"最後に表示したページをブックマークする"</string>
<string name="switch_to_thumbnails" msgid="5493351529609043151">"サムネイル表示"</string>
@@ -129,7 +133,7 @@
<string name="menu_preferences" msgid="6709237687234102240">"設定"</string>
<string name="pref_content_title" msgid="722227111894838633">"ページコンテンツ設定"</string>
<string name="pref_content_load_images" msgid="2125616852957377561">"画像の読み込み"</string>
- <string name="pref_content_load_images_summary" msgid="5055874125248398584">"ウェブページに画像を表示する"</string>
+ <string name="pref_content_load_images_summary" msgid="5055874125248398584">"ウェブページに画像を表示"</string>
<string name="pref_content_block_popups" msgid="7808433807197256726">"ポップアップウィンドウをブロック"</string>
<string name="pref_content_javascript" msgid="4570972030299516843">"JavaScriptを有効にする"</string>
<string name="pref_content_open_in_background" msgid="824123779725118663">"バックグラウンドで開く"</string>
@@ -137,33 +141,33 @@
<string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"現在のウィンドウの後ろに新しいウィンドウを開く"</string>
<string name="pref_content_homepage" msgid="6082437160778559806">"ホームページ設定"</string>
<string name="pref_content_autofit" msgid="8260474534053660809">"ページの自動調整"</string>
- <string name="pref_content_autofit_summary" msgid="4587831659894879986">"画面に合わせてウェブページをフォーマットする"</string>
+ <string name="pref_content_autofit_summary" msgid="4587831659894879986">"画面に合わせてウェブページをフォーマット"</string>
<string name="pref_content_landscape_only" msgid="2022546812766219672">"常に横向きに表示"</string>
- <string name="pref_content_landscape_only_summary" msgid="1008238895535428855">"ページを常に横向きに表示する"</string>
+ <string name="pref_content_landscape_only_summary" msgid="1008238895535428855">"ページを常に横向きに表示"</string>
<string name="pref_privacy_title" msgid="1052470980370846151">"プライバシー設定"</string>
<string name="pref_privacy_clear_cache" msgid="3380316479925886998">"キャッシュを消去"</string>
- <string name="pref_privacy_clear_cache_summary" msgid="2216463577207991454">"ローカルにキャッシュしたコンテンツとデータベースを消去する"</string>
+ <string name="pref_privacy_clear_cache_summary" msgid="2216463577207991454">"ローカルにキャッシュしたコンテンツとデータベースを消去"</string>
<string name="pref_privacy_clear_cache_dlg" msgid="5541011591300753881">"ローカルにキャッシュしたコンテンツとデータベースを削除します。"</string>
<string name="pref_privacy_clear_cookies" msgid="3095583579133780331">"Cookieをすべて消去"</string>
- <string name="pref_privacy_clear_cookies_summary" msgid="6962742063990677520">"すべてのブラウザCookieを消去する"</string>
+ <string name="pref_privacy_clear_cookies_summary" msgid="6962742063990677520">"すべてのブラウザCookieを消去"</string>
<string name="pref_privacy_clear_cookies_dlg" msgid="552855688091432682">"すべてのCookieを削除します。"</string>
<string name="pref_privacy_clear_history" msgid="8723795508825198477">"履歴消去"</string>
- <string name="pref_privacy_clear_history_summary" msgid="6868501330708940734">"ブラウザの閲覧履歴を消去する"</string>
+ <string name="pref_privacy_clear_history_summary" msgid="6868501330708940734">"ブラウザの閲覧履歴を消去します"</string>
<string name="pref_privacy_clear_history_dlg" msgid="544903007914753853">"ブラウザの閲覧履歴を削除します。"</string>
<string name="pref_privacy_clear_form_data" msgid="4232668196344383987">"フォームデータを消去"</string>
- <string name="pref_privacy_clear_form_data_summary" msgid="1790390894719517167">"保存されているフォームデータをすべて消去する"</string>
+ <string name="pref_privacy_clear_form_data_summary" msgid="1790390894719517167">"保存されているフォームデータをすべて消去します"</string>
<string name="pref_privacy_clear_form_data_dlg" msgid="4443621086781197928">"保存されているすべてのフォームデータが削除されます。"</string>
<string name="pref_privacy_clear_passwords" msgid="4750234112289277480">"パスワードを消去"</string>
- <string name="pref_privacy_clear_passwords_summary" msgid="8856782718942903335">"保存されているすべてのパスワードを消去する"</string>
+ <string name="pref_privacy_clear_passwords_summary" msgid="8856782718942903335">"保存されているすべてのパスワードを消去"</string>
<string name="pref_privacy_clear_passwords_dlg" msgid="2083869328824248255">"保存されているすべてのパスワードを削除します。"</string>
<string name="pref_privacy_enable_geolocation" msgid="1395040170290765686">"位置情報を有効にする"</string>
<string name="pref_privacy_enable_geolocation_summary" msgid="8437020934664306205">"サイトに現在地情報へのアクセスを許可する"</string>
<string name="pref_privacy_clear_geolocation_access" msgid="6649680770030042980">"位置情報アクセスをクリア"</string>
- <string name="pref_privacy_clear_geolocation_access_summary" msgid="7750143359497314679">"すべてのウェブサイトの位置情報アクセスをクリアする"</string>
+ <string name="pref_privacy_clear_geolocation_access_summary" msgid="7750143359497314679">"すべてのウェブサイトの位置情報アクセスをクリア"</string>
<string name="pref_privacy_clear_geolocation_access_dlg" msgid="7327063124488827244">"すべてのウェブサイトの位置情報アクセスをクリア"</string>
<string name="pref_security_title" msgid="5763978646932160021">"セキュリティ設定"</string>
<string name="pref_security_remember_passwords" msgid="6492957683454529549">"パスワードを保存"</string>
- <string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"ウェブサイトのユーザー名とパスワードを保存する"</string>
+ <string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"ウェブサイトのユーザー名とパスワードを保存"</string>
<string name="pref_security_save_form_data" msgid="1213669802810198893">"フォームデータを保存"</string>
<string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"フォームに入力したデータを保存して後で呼び出せるようにする"</string>
<string name="pref_security_show_security_warning" msgid="8901135676266754559">"セキュリティ警告"</string>
@@ -181,16 +185,16 @@
<string name="pref_text_size_dialogtitle" msgid="3625388833512647865">"文字サイズ"</string>
<string name="pref_default_zoom" msgid="8076142259097187395">"デフォルトの倍率"</string>
<string-array name="pref_default_zoom_choices">
- <item msgid="549583171195154919">"低"</item>
- <item msgid="5619034257768161024">"中"</item>
- <item msgid="3840999588443167001">"高"</item>
+ <item msgid="549583171195154919">"低い"</item>
+ <item msgid="5619034257768161024">"中間"</item>
+ <item msgid="3840999588443167001">"高い"</item>
</string-array>
<string name="pref_default_zoom_dialogtitle" msgid="6095974367125109021">"デフォルトの倍率"</string>
<string name="pref_content_load_page" msgid="2219810141690955452">"ページを全体表示で開く"</string>
<string name="pref_content_load_page_summary" msgid="8792093504054149369">"新しく開いたページを全体表示する"</string>
<string name="pref_extras_title" msgid="3091250467679722382">"詳細設定"</string>
<string name="pref_extras_website_settings" msgid="67866640052455549">"ウェブサイト設定"</string>
- <string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"個々のウェブサイトの詳細設定を表示する"</string>
+ <string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"個々のウェブサイトの詳細設定を表示"</string>
<string name="pref_extras_reset_default" msgid="8904000515846202110">"初期設定にリセット"</string>
<string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"ブラウザデータをすべて消去して出荷時の初期設定に戻す"</string>
<string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"すべてのブラウザデータを削除して設定をデフォルト値に戻します。"</string>
@@ -278,6 +282,10 @@
<string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"位置情報を共有"</string>
<string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"拒否"</string>
<string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"設定を保存"</string>
+ <!-- no translation found for geolocation_permissions_prompt_toast_allowed (987286072035125498) -->
+ <skip />
+ <!-- no translation found for geolocation_permissions_prompt_toast_disallowed (7695100950212692515) -->
+ <skip />
<string name="geolocation_settings_page_title" msgid="1745477985097536528">"位置情報アクセスをクリア"</string>
<string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"このサイトは現在地情報にアクセスできます"</string>
<string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"このサイトは現在地情報にアクセスできません"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 4682712..8082dab 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -15,11 +15,13 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="application_name" msgid="1935869255545976415">"인터넷"</string>
+ <string name="application_name" msgid="1935869255545976415">"브라우저"</string>
+ <!-- no translation found for choose_upload (3649366287575002063) -->
+ <skip />
<string name="new_tab" msgid="4505722538297295141">"새 창"</string>
<string name="active_tabs" msgid="3050623868203544623">"창"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"북마크"</string>
- <string name="tab_most_visited" msgid="1077402532455000703">"자주 방문한 페이지"</string>
+ <string name="tab_most_visited" msgid="1077402532455000703">"최다 방문 웹사이트"</string>
<string name="tab_history" msgid="1979267558744613746">"기록"</string>
<string name="added_to_bookmarks" msgid="1020224130695956728">"북마크에 추가되었습니다."</string>
<string name="removed_from_bookmarks" msgid="6063705902028438800">"북마크에서 삭제됨"</string>
@@ -69,7 +71,7 @@
<string name="location" msgid="969988560160364559">"위치"</string>
<string name="name" msgid="5990326151488445481">"이름"</string>
<string name="http" msgid="2163722670597250102">"http://"</string>
- <string name="save_to_bookmarks" msgid="588165100024086565">"북마크에 추가"</string>
+ <string name="save_to_bookmarks" msgid="588165100024086565">"북마크 추가"</string>
<string name="edit_bookmark" msgid="5024089053490231905">"북마크 수정"</string>
<string name="create_shortcut_bookmark" msgid="9202323987633899835">"홈에 바로가기 추가"</string>
<string name="open_bookmark" msgid="8473581305759935790">"열기"</string>
@@ -84,6 +86,8 @@
<string name="bookmark_needs_url" msgid="7809876865972755158">"북마크의 위치를 입력해야 합니다."</string>
<string name="empty_bookmark" msgid="7008697085928540511">"빈 북마크를 만들 수 없습니다."</string>
<string name="bookmark_url_not_valid" msgid="6719785633980202419">"URL이 유효하지 않습니다."</string>
+ <!-- no translation found for bookmark_cannot_save_url (791722768778386941) -->
+ <skip />
<string name="delete_bookmark" msgid="2422989994934201992">"삭제"</string>
<string name="bookmark_page" msgid="6845189305130307274">"마지막으로 본 페이지를 북마크 설정"</string>
<string name="switch_to_thumbnails" msgid="5493351529609043151">"미리보기 이미지 보기"</string>
@@ -153,8 +157,8 @@
<string name="pref_privacy_clear_form_data" msgid="4232668196344383987">"양식 데이터 지우기"</string>
<string name="pref_privacy_clear_form_data_summary" msgid="1790390894719517167">"저장된 양식 데이터 모두 지우기"</string>
<string name="pref_privacy_clear_form_data_dlg" msgid="4443621086781197928">"저장된 양식 데이터가 모두 삭제됩니다."</string>
- <string name="pref_privacy_clear_passwords" msgid="4750234112289277480">"비밀번호 삭제"</string>
- <string name="pref_privacy_clear_passwords_summary" msgid="8856782718942903335">"저장된 모든 비밀번호 삭제"</string>
+ <string name="pref_privacy_clear_passwords" msgid="4750234112289277480">"비밀번호 지우기"</string>
+ <string name="pref_privacy_clear_passwords_summary" msgid="8856782718942903335">"저장된 모든 비밀번호 지우기"</string>
<string name="pref_privacy_clear_passwords_dlg" msgid="2083869328824248255">"저장된 비밀번호가 모두 삭제됩니다."</string>
<string name="pref_privacy_enable_geolocation" msgid="1395040170290765686">"위치 정보 사용"</string>
<string name="pref_privacy_enable_geolocation_summary" msgid="8437020934664306205">"사이트의 위치 정보 액세스 요청 허용"</string>
@@ -162,7 +166,7 @@
<string name="pref_privacy_clear_geolocation_access_summary" msgid="7750143359497314679">"모든 웹사이트의 위치 정보 액세스 삭제"</string>
<string name="pref_privacy_clear_geolocation_access_dlg" msgid="7327063124488827244">"모든 웹사이트의 위치 정보 액세스 삭제"</string>
<string name="pref_security_title" msgid="5763978646932160021">"보안 설정"</string>
- <string name="pref_security_remember_passwords" msgid="6492957683454529549">"비밀번호 저장"</string>
+ <string name="pref_security_remember_passwords" msgid="6492957683454529549">"비밀번호 기억"</string>
<string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"웹사이트에 대해 사용자 이름 및 비밀번호 저장"</string>
<string name="pref_security_save_form_data" msgid="1213669802810198893">"양식 데이터 기억"</string>
<string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"나중에 사용할 수 있도록 양식에 입력한 데이터 기억"</string>
@@ -278,6 +282,10 @@
<string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"위치 공유"</string>
<string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"거부"</string>
<string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"환경설정 저장"</string>
+ <!-- no translation found for geolocation_permissions_prompt_toast_allowed (987286072035125498) -->
+ <skip />
+ <!-- no translation found for geolocation_permissions_prompt_toast_disallowed (7695100950212692515) -->
+ <skip />
<string name="geolocation_settings_page_title" msgid="1745477985097536528">"위치 정보 액세스 삭제"</string>
<string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"사이트에서 사용자의 위치에 현재 액세스할 수 있음"</string>
<string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"사이트에서 사용자의 위치에 현재 액세스할 수 없음"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 1b4fcb9..ff392c2 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -16,6 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="1935869255545976415">"Nettleser"</string>
+ <!-- no translation found for choose_upload (3649366287575002063) -->
+ <skip />
<string name="new_tab" msgid="4505722538297295141">"Ny fane"</string>
<string name="active_tabs" msgid="3050623868203544623">"Vinduer"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Bokmerker"</string>
@@ -84,6 +86,8 @@
<string name="bookmark_needs_url" msgid="7809876865972755158">"Bokmerket må ha en adresse."</string>
<string name="empty_bookmark" msgid="7008697085928540511">"Kan ikke opprette tomt bokmerke."</string>
<string name="bookmark_url_not_valid" msgid="6719785633980202419">"Ugyldig nettadresse"</string>
+ <!-- no translation found for bookmark_cannot_save_url (791722768778386941) -->
+ <skip />
<string name="delete_bookmark" msgid="2422989994934201992">"Slett"</string>
<string name="bookmark_page" msgid="6845189305130307274">"Bokmerk sist viste side"</string>
<string name="switch_to_thumbnails" msgid="5493351529609043151">"Miniatyrbildevisning"</string>
@@ -278,6 +282,10 @@
<string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Del"</string>
<string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Ikke del"</string>
<string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Husk"</string>
+ <!-- no translation found for geolocation_permissions_prompt_toast_allowed (987286072035125498) -->
+ <skip />
+ <!-- no translation found for geolocation_permissions_prompt_toast_disallowed (7695100950212692515) -->
+ <skip />
<string name="geolocation_settings_page_title" msgid="1745477985097536528">"Deaktiver posisjonstilgang"</string>
<string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Dette nettstedet har for tiden tilgang til posisjonen din"</string>
<string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Dette nettstedet har for tiden ikke tilgang til posisjonen din"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 341ebbd..6d8e79e 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -16,6 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="1935869255545976415">"Browser"</string>
+ <!-- no translation found for choose_upload (3649366287575002063) -->
+ <skip />
<string name="new_tab" msgid="4505722538297295141">"Nieuw venster"</string>
<string name="active_tabs" msgid="3050623868203544623">"Vensters"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Bladwijzers"</string>
@@ -78,12 +80,15 @@
<string name="remove_history_item" msgid="5021424935726728618">"Uit geschiedenis verwijderen"</string>
<string name="set_as_homepage" msgid="4752937379414905560">"Instellen als startpagina"</string>
<string name="bookmark_saved" msgid="2766434679871317557">"Opgeslagen in bladwijzers."</string>
- <string name="bookmark_not_saved" msgid="700600955089376724">"Kan bladwijzer niet opslaan."</string>
+ <!-- no translation found for bookmark_not_saved (700600955089376724) -->
+ <skip />
<string name="homepage_set" msgid="8768087280310966395">"De startpagina is ingesteld."</string>
<string name="bookmark_needs_title" msgid="6245900436119218187">"Bladwijzer moet een naam hebben."</string>
<string name="bookmark_needs_url" msgid="7809876865972755158">"Bladwijzers moeten een locatie hebben."</string>
<string name="empty_bookmark" msgid="7008697085928540511">"Kan geen lege bladwijzer maken."</string>
<string name="bookmark_url_not_valid" msgid="6719785633980202419">"URL is ongeldig."</string>
+ <!-- no translation found for bookmark_cannot_save_url (791722768778386941) -->
+ <skip />
<string name="delete_bookmark" msgid="2422989994934201992">"Verwijderen"</string>
<string name="bookmark_page" msgid="6845189305130307274">"Bladwijzer voor laatst weergegeven pagina"</string>
<string name="switch_to_thumbnails" msgid="5493351529609043151">"Miniatuurweergave"</string>
@@ -115,7 +120,7 @@
<string name="contextmenu_savelink" msgid="5508554930832538184">"Link opslaan"</string>
<string name="contextmenu_sharelink" msgid="5392275392280130331">"Link delen"</string>
<string name="contextmenu_copy" msgid="398860586635404030">"Kopiëren"</string>
- <string name="contextmenu_copylink" msgid="5153657160294534270">"Link-URL kopiëren"</string>
+ <string name="contextmenu_copylink" msgid="5153657160294534270">"URL van koppeling kopiëren"</string>
<string name="contextmenu_download_image" msgid="4243829645180686912">"Afbeelding opslaan"</string>
<string name="contextmenu_view_image" msgid="3870625602053600905">"Afbeelding weergeven"</string>
<string name="contextmenu_dial_dot" msgid="5856550683415933806">"Bellen..."</string>
@@ -278,6 +283,10 @@
<string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Locatie delen"</string>
<string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Weigeren"</string>
<string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Voorkeur onthouden"</string>
+ <!-- no translation found for geolocation_permissions_prompt_toast_allowed (987286072035125498) -->
+ <skip />
+ <!-- no translation found for geolocation_permissions_prompt_toast_disallowed (7695100950212692515) -->
+ <skip />
<string name="geolocation_settings_page_title" msgid="1745477985097536528">"Locatietoegang ongedaan maken"</string>
<string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Deze site heeft momenteel toegang tot uw locatie"</string>
<string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Deze site heeft momenteel geen toegang tot uw locatie"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 8af5b8c..32cab16 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -16,6 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="1935869255545976415">"Internet"</string>
+ <!-- no translation found for choose_upload (3649366287575002063) -->
+ <skip />
<string name="new_tab" msgid="4505722538297295141">"Nowe okno"</string>
<string name="active_tabs" msgid="3050623868203544623">"Okna"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Zakładki"</string>
@@ -84,6 +86,8 @@
<string name="bookmark_needs_url" msgid="7809876865972755158">"Zakładka musi zawierać adres."</string>
<string name="empty_bookmark" msgid="7008697085928540511">"Nie można utworzyć pustej zakładki."</string>
<string name="bookmark_url_not_valid" msgid="6719785633980202419">"Adres URL jest nieprawidłowy."</string>
+ <!-- no translation found for bookmark_cannot_save_url (791722768778386941) -->
+ <skip />
<string name="delete_bookmark" msgid="2422989994934201992">"Usuń"</string>
<string name="bookmark_page" msgid="6845189305130307274">"Dodaj do zakładek ostatnio wyświetlaną stronę"</string>
<string name="switch_to_thumbnails" msgid="5493351529609043151">"Widok miniatur"</string>
@@ -138,7 +142,7 @@
<string name="pref_content_homepage" msgid="6082437160778559806">"Ustaw stronę główną"</string>
<string name="pref_content_autofit" msgid="8260474534053660809">"Autodopasowanie stron"</string>
<string name="pref_content_autofit_summary" msgid="4587831659894879986">"Formatuj strony internetowe w celu dopasowania do ekranu"</string>
- <string name="pref_content_landscape_only" msgid="2022546812766219672">"Zawsze w orientacji poziomej"</string>
+ <string name="pref_content_landscape_only" msgid="2022546812766219672">"Wyświetlanie tylko w orientacji poziomej"</string>
<string name="pref_content_landscape_only_summary" msgid="1008238895535428855">"Wyświetlaj strony tylko w szerszej, poziomej orientacji ekranu"</string>
<string name="pref_privacy_title" msgid="1052470980370846151">"Ustawienia prywatności"</string>
<string name="pref_privacy_clear_cache" msgid="3380316479925886998">"Wyczyść pamięć podręczną"</string>
@@ -158,9 +162,9 @@
<string name="pref_privacy_clear_passwords_dlg" msgid="2083869328824248255">"Wszystkie zapisane hasła zostaną usunięte."</string>
<string name="pref_privacy_enable_geolocation" msgid="1395040170290765686">"Włącz obsługę lokalizacji"</string>
<string name="pref_privacy_enable_geolocation_summary" msgid="8437020934664306205">"Zezwalaj witrynom na żądanie dostępu do informacji o lokalizacji"</string>
- <string name="pref_privacy_clear_geolocation_access" msgid="6649680770030042980">"Wyczyść dostęp do informacji o lokalizacji"</string>
+ <string name="pref_privacy_clear_geolocation_access" msgid="6649680770030042980">"Udziel dostępu do informacji o lokalizacji"</string>
<string name="pref_privacy_clear_geolocation_access_summary" msgid="7750143359497314679">"Usuń dostęp wszystkich witryn do informacji o lokalizacji"</string>
- <string name="pref_privacy_clear_geolocation_access_dlg" msgid="7327063124488827244">"Wyczyść ustawienia dostępu witryn do informacji o lokalizacji"</string>
+ <string name="pref_privacy_clear_geolocation_access_dlg" msgid="7327063124488827244">"Usuń dostęp wszystkich witryn do informacji o lokalizacji"</string>
<string name="pref_security_title" msgid="5763978646932160021">"Ustawienia zabezpieczeń"</string>
<string name="pref_security_remember_passwords" msgid="6492957683454529549">"Pamiętaj hasła"</string>
<string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"Zapisz nazwy użytkowników i hasła używane w witrynach"</string>
@@ -278,10 +282,14 @@
<string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Udostępnij informacje o lokalizacji"</string>
<string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Odrzuć"</string>
<string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Zapamiętaj ustawienie"</string>
- <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Wyczyść dostęp do informacji o lokalizacji"</string>
+ <!-- no translation found for geolocation_permissions_prompt_toast_allowed (987286072035125498) -->
+ <skip />
+ <!-- no translation found for geolocation_permissions_prompt_toast_disallowed (7695100950212692515) -->
+ <skip />
+ <string name="geolocation_settings_page_title" msgid="1745477985097536528">"Udziel dostępu do informacji o lokalizacji"</string>
<string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Ta witryna ma obecnie dostęp do informacji o Twojej lokalizacji"</string>
<string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Ta witryna nie ma obecnie dostępu do informacji o Twojej lokalizacji"</string>
- <string name="geolocation_settings_page_dialog_title" msgid="1549842043381347668">"Wyczyść dostęp do informacji o lokalizacji"</string>
+ <string name="geolocation_settings_page_dialog_title" msgid="1549842043381347668">"Udziel dostępu do informacji o lokalizacji"</string>
<string name="geolocation_settings_page_dialog_message" msgid="7586671987576403993">"Dostęp tej witryny do informacji o lokalizacji zostanie usunięty"</string>
<string name="geolocation_settings_page_dialog_ok_button" msgid="4789434178048077287">"Usuń dostęp"</string>
<string name="geolocation_settings_page_dialog_cancel_button" msgid="7941036504673409747">"Anuluj"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index aa0fcd6..883b75f 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -16,6 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="1935869255545976415">"Browser"</string>
+ <!-- no translation found for choose_upload (3649366287575002063) -->
+ <skip />
<string name="new_tab" msgid="4505722538297295141">"Nova janela"</string>
<string name="active_tabs" msgid="3050623868203544623">"Janelas"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Marcadores"</string>
@@ -84,6 +86,8 @@
<string name="bookmark_needs_url" msgid="7809876865972755158">"O marcador tem de ter uma localização."</string>
<string name="empty_bookmark" msgid="7008697085928540511">"Não é possível criar um marcador vazio."</string>
<string name="bookmark_url_not_valid" msgid="6719785633980202419">"O URL não é válido."</string>
+ <!-- no translation found for bookmark_cannot_save_url (791722768778386941) -->
+ <skip />
<string name="delete_bookmark" msgid="2422989994934201992">"Eliminar"</string>
<string name="bookmark_page" msgid="6845189305130307274">"Adicionar aos marcadores a última página visualizada"</string>
<string name="switch_to_thumbnails" msgid="5493351529609043151">"Vista de miniatura"</string>
@@ -139,7 +143,7 @@
<string name="pref_content_autofit" msgid="8260474534053660809">"Ajuste auto de páginas"</string>
<string name="pref_content_autofit_summary" msgid="4587831659894879986">"Formatar páginas Web para se ajustarem ao ecrã"</string>
<string name="pref_content_landscape_only" msgid="2022546812766219672">"Apresentação apenas na horizontal"</string>
- <string name="pref_content_landscape_only_summary" msgid="1008238895535428855">"Mostrar páginas só na orientação horizontal do ecrã (mais larga)"</string>
+ <string name="pref_content_landscape_only_summary" msgid="1008238895535428855">"Apresentar páginas apenas na orientação horizontal do ecrã (mais larga)"</string>
<string name="pref_privacy_title" msgid="1052470980370846151">"Definições de privacidade"</string>
<string name="pref_privacy_clear_cache" msgid="3380316479925886998">"Limpar cache"</string>
<string name="pref_privacy_clear_cache_summary" msgid="2216463577207991454">"Limpar bases de dados e conteúdos colocados em cache localmente"</string>
@@ -278,6 +282,10 @@
<string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Partilhar localização"</string>
<string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Recusar"</string>
<string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Memorizar preferência"</string>
+ <!-- no translation found for geolocation_permissions_prompt_toast_allowed (987286072035125498) -->
+ <skip />
+ <!-- no translation found for geolocation_permissions_prompt_toast_disallowed (7695100950212692515) -->
+ <skip />
<string name="geolocation_settings_page_title" msgid="1745477985097536528">"Limpar acesso à localização"</string>
<string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Actualmente este site pode aceder à sua localização"</string>
<string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Actualmente este site não pode aceder à sua localização"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 1b0ca0a..7d73805 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -16,6 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="1935869255545976415">"Navegador"</string>
+ <!-- no translation found for choose_upload (3649366287575002063) -->
+ <skip />
<string name="new_tab" msgid="4505722538297295141">"Nova janela"</string>
<string name="active_tabs" msgid="3050623868203544623">"Janelas"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Favoritos"</string>
@@ -63,7 +65,7 @@
<string name="stop" msgid="5687251076030630074">"Parar"</string>
<string name="reload" msgid="8585220783228408062">"Atualizar"</string>
<string name="back" msgid="8414603107175713668">"Voltar"</string>
- <string name="forward" msgid="4288210890526641577">"Avançar"</string>
+ <string name="forward" msgid="4288210890526641577">"Encaminhar"</string>
<string name="save" msgid="5922311934992468496">"OK"</string>
<string name="do_not_save" msgid="6777633870113477714">"Cancelar"</string>
<string name="location" msgid="969988560160364559">"Local"</string>
@@ -84,6 +86,8 @@
<string name="bookmark_needs_url" msgid="7809876865972755158">"O favorito precisa ter um local."</string>
<string name="empty_bookmark" msgid="7008697085928540511">"Não é possível criar um favorito vazio."</string>
<string name="bookmark_url_not_valid" msgid="6719785633980202419">"O URL não é válido."</string>
+ <!-- no translation found for bookmark_cannot_save_url (791722768778386941) -->
+ <skip />
<string name="delete_bookmark" msgid="2422989994934201992">"Excluir"</string>
<string name="bookmark_page" msgid="6845189305130307274">"Adicionar última página visualizada aos favoritos"</string>
<string name="switch_to_thumbnails" msgid="5493351529609043151">"Visualização em miniatura"</string>
@@ -94,7 +98,7 @@
<string name="new_window" msgid="8117889615360211551">"Nova janela"</string>
<string name="goto_dot" msgid="3895839050522602723">"Ir"</string>
<string name="find_dot" msgid="6259312434696611957">"Localizar na página"</string>
- <string name="select_dot" msgid="6299170761900561967">"Selecionar texto"</string>
+ <string name="select_dot" msgid="6299170761900561967">"Selecione o texto"</string>
<string name="view_tabs" msgid="1119097492003550564">"Visão geral da janela"</string>
<string name="view_tabs_condensed" msgid="5803955493821945369">"Janelas"</string>
<string name="tab_picker_title" msgid="864478399057782913">"Janelas atuais"</string>
@@ -138,7 +142,7 @@
<string name="pref_content_homepage" msgid="6082437160778559806">"Definir a página inicial"</string>
<string name="pref_content_autofit" msgid="8260474534053660809">"Ajustar automaticamente"</string>
<string name="pref_content_autofit_summary" msgid="4587831659894879986">"Formatar páginas da web para se ajustarem à tela"</string>
- <string name="pref_content_landscape_only" msgid="2022546812766219672">"Apenas modo paisagem"</string>
+ <string name="pref_content_landscape_only" msgid="2022546812766219672">"Exibição apenas em modo paisagem"</string>
<string name="pref_content_landscape_only_summary" msgid="1008238895535428855">"Exibir páginas apenas na orientação mais larga, com a tela no modo paisagem"</string>
<string name="pref_privacy_title" msgid="1052470980370846151">"Configurações de privacidade"</string>
<string name="pref_privacy_clear_cache" msgid="3380316479925886998">"Limpar cache"</string>
@@ -158,7 +162,7 @@
<string name="pref_privacy_clear_passwords_dlg" msgid="2083869328824248255">"Todas as senhas salvas serão excluídas."</string>
<string name="pref_privacy_enable_geolocation" msgid="1395040170290765686">"Ativar localização"</string>
<string name="pref_privacy_enable_geolocation_summary" msgid="8437020934664306205">"Permitir que os sites solicitem acesso à sua localização"</string>
- <string name="pref_privacy_clear_geolocation_access" msgid="6649680770030042980">"Limpar acesso ao local"</string>
+ <string name="pref_privacy_clear_geolocation_access" msgid="6649680770030042980">"Limpar acesso à localização"</string>
<string name="pref_privacy_clear_geolocation_access_summary" msgid="7750143359497314679">"Limpar acesso à localização para todos os sites"</string>
<string name="pref_privacy_clear_geolocation_access_dlg" msgid="7327063124488827244">"Limpar acesso à localização para todos os sites"</string>
<string name="pref_security_title" msgid="5763978646932160021">"Configurações de segurança"</string>
@@ -186,8 +190,8 @@
<item msgid="3840999588443167001">"Perto"</item>
</string-array>
<string name="pref_default_zoom_dialogtitle" msgid="6095974367125109021">"Zoom padrão"</string>
- <string name="pref_content_load_page" msgid="2219810141690955452">"Abrir em visão geral"</string>
- <string name="pref_content_load_page_summary" msgid="8792093504054149369">"Exibir visão geral de páginas que acabaram de ser abertas"</string>
+ <string name="pref_content_load_page" msgid="2219810141690955452">"Abrir páginas na visão geral"</string>
+ <string name="pref_content_load_page_summary" msgid="8792093504054149369">"Exibir visão geral das páginas abertas recentemente"</string>
<string name="pref_extras_title" msgid="3091250467679722382">"Configurações avançadas"</string>
<string name="pref_extras_website_settings" msgid="67866640052455549">"Configurações do site"</string>
<string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Visualizar configurações avançadas para sites individuais"</string>
@@ -230,7 +234,7 @@
<string name="too_many_windows_dialog_message" msgid="1398571800233959583">"Não foi possível abrir uma nova janela porque você já abriu o número máximo."</string>
<string name="too_many_subwindows_dialog_title" msgid="3805453941587725944">"Pop-up já aberta"</string>
<string name="too_many_subwindows_dialog_message" msgid="5827289829907966657">"Não foi possível abrir uma nova janela pop-up porque apenas uma pode ser aberta por vez."</string>
- <string name="download_title" msgid="2122874021047565594">"Histórico de downloads"</string>
+ <string name="download_title" msgid="2122874021047565594">"Fazer download do histórico"</string>
<string name="download_unknown_filename" msgid="4013465542563652175">"<Desconhecido>"</string>
<string name="download_menu_open" msgid="4888327480367757513">"Abrir"</string>
<string name="download_menu_clear" msgid="6264454531553418124">"Limpar da lista"</string>
@@ -278,6 +282,10 @@
<string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Compartilhar local"</string>
<string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Recusar"</string>
<string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Lembrar preferências"</string>
+ <!-- no translation found for geolocation_permissions_prompt_toast_allowed (987286072035125498) -->
+ <skip />
+ <!-- no translation found for geolocation_permissions_prompt_toast_disallowed (7695100950212692515) -->
+ <skip />
<string name="geolocation_settings_page_title" msgid="1745477985097536528">"Limpar acesso à localização"</string>
<string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Este site pode acessar a sua localização no momento"</string>
<string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Este site não pode acessar a sua localização no momento"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 4af4b4c..84e5d67 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -16,6 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="1935869255545976415">"Браузер"</string>
+ <!-- no translation found for choose_upload (3649366287575002063) -->
+ <skip />
<string name="new_tab" msgid="4505722538297295141">"Новое окно"</string>
<string name="active_tabs" msgid="3050623868203544623">"Окна"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Закладки"</string>
@@ -66,7 +68,7 @@
<string name="forward" msgid="4288210890526641577">"Переслать"</string>
<string name="save" msgid="5922311934992468496">"ОК"</string>
<string name="do_not_save" msgid="6777633870113477714">"Отмена"</string>
- <string name="location" msgid="969988560160364559">"URL-адрес"</string>
+ <string name="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>
@@ -84,11 +86,13 @@
<string name="bookmark_needs_url" msgid="7809876865972755158">"Необходимо указать место закладки."</string>
<string name="empty_bookmark" msgid="7008697085928540511">"Невозможно создать пустую закладку."</string>
<string name="bookmark_url_not_valid" msgid="6719785633980202419">"URL недействителен."</string>
+ <!-- no translation found for bookmark_cannot_save_url (791722768778386941) -->
+ <skip />
<string name="delete_bookmark" msgid="2422989994934201992">"Удалить"</string>
<string name="bookmark_page" msgid="6845189305130307274">"Добавить в закладки последнюю просмотренную страницу"</string>
- <string name="switch_to_thumbnails" msgid="5493351529609043151">"Уменьшенные изображения"</string>
+ <string name="switch_to_thumbnails" msgid="5493351529609043151">"Уменьшенное изображение"</string>
<string name="switch_to_list" msgid="8900531247982121055">"В виде списка"</string>
- <string name="current_page" msgid="7510129573681663135">"на "</string>
+ <string name="current_page" msgid="7510129573681663135">"из "</string>
<string name="delete_bookmark_warning" msgid="758043186202032205">"Закладка \"<xliff:g id="BOOKMARK">%s</xliff:g>\" будет удалена."</string>
<string name="open_in_new_window" msgid="6596775546468054510">"Открыть в новом окне"</string>
<string name="new_window" msgid="8117889615360211551">"Новое окно"</string>
@@ -192,7 +196,7 @@
<string name="pref_extras_website_settings" msgid="67866640052455549">"Настройки веб-сайта"</string>
<string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Просмотреть дополнительные настройки для отдельных сайтов"</string>
<string name="pref_extras_reset_default" msgid="8904000515846202110">"Восстановить настройки по умолчанию"</string>
- <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Очистить все данные браузера и включить настройки по умолчанию"</string>
+ <string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Очистить все данные браузера и восстановить все настройки по умолчанию"</string>
<string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"Все данные браузера будут удалены, настройки по умолчанию будут восстановлены."</string>
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Восстановить настройки по умолчанию"</string>
<string name="pref_development_title" msgid="3263854204533056480">"Отладка"</string>
@@ -221,7 +225,7 @@
<string name="add_bookmark_short" msgid="3783984330998103735">"Добавить"</string>
<string name="search_hint" msgid="4647356319916631820">"Введите условия поиска или URL-адрес"</string>
<string name="search_button_text" msgid="5235226933877634410">"Поиск"</string>
- <string name="search_settings_description" msgid="1422401062529014107">"Закладки и история поиска"</string>
+ <string name="search_settings_description" msgid="1422401062529014107">"Закладки и просмотренные страницы"</string>
<string name="attention" msgid="3473639060042811244">"Внимание"</string>
<string name="popup_window_attempt" msgid="2673111696288657989">"Этот сайт пытается открыть всплывающее окно."</string>
<string name="allow" msgid="1157313689171991335">"Разрешить"</string>
@@ -278,6 +282,10 @@
<string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Сообщить местоположение"</string>
<string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Отклонить"</string>
<string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Запомнить настройки"</string>
+ <!-- no translation found for geolocation_permissions_prompt_toast_allowed (987286072035125498) -->
+ <skip />
+ <!-- no translation found for geolocation_permissions_prompt_toast_disallowed (7695100950212692515) -->
+ <skip />
<string name="geolocation_settings_page_title" msgid="1745477985097536528">"Удалить данные доступа к местоположению"</string>
<string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Этот сайт сейчас имеет доступ к вашему местоположению"</string>
<string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Этот сайт в настоящее время не имеет доступа к вашему местоположению"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index f1cb487..4f967ba 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -15,7 +15,9 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="application_name" msgid="1935869255545976415">"Webbläs."</string>
+ <string name="application_name" msgid="1935869255545976415">"Webbläsare"</string>
+ <!-- no translation found for choose_upload (3649366287575002063) -->
+ <skip />
<string name="new_tab" msgid="4505722538297295141">"Nytt fönster"</string>
<string name="active_tabs" msgid="3050623868203544623">"Fönster"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Bokmärken"</string>
@@ -63,7 +65,7 @@
<string name="stop" msgid="5687251076030630074">"Stoppa"</string>
<string name="reload" msgid="8585220783228408062">"Uppdatera"</string>
<string name="back" msgid="8414603107175713668">"Tillbaka"</string>
- <string name="forward" msgid="4288210890526641577">"Framåt"</string>
+ <string name="forward" msgid="4288210890526641577">"Vidarebefordra"</string>
<string name="save" msgid="5922311934992468496">"OK"</string>
<string name="do_not_save" msgid="6777633870113477714">"Avbryt"</string>
<string name="location" msgid="969988560160364559">"Plats"</string>
@@ -84,6 +86,8 @@
<string name="bookmark_needs_url" msgid="7809876865972755158">"Du måste ange en plats för bokmärket."</string>
<string name="empty_bookmark" msgid="7008697085928540511">"Det går inte att skapa tomma bokmärken."</string>
<string name="bookmark_url_not_valid" msgid="6719785633980202419">"Webbadressen är ogiltig."</string>
+ <!-- no translation found for bookmark_cannot_save_url (791722768778386941) -->
+ <skip />
<string name="delete_bookmark" msgid="2422989994934201992">"Ta bort"</string>
<string name="bookmark_page" msgid="6845189305130307274">"Skapa bokmärke för den senast visade sidan"</string>
<string name="switch_to_thumbnails" msgid="5493351529609043151">"Miniatyrvy"</string>
@@ -186,12 +190,12 @@
<item msgid="3840999588443167001">"Nära"</item>
</string-array>
<string name="pref_default_zoom_dialogtitle" msgid="6095974367125109021">"Standardinställning för zoom"</string>
- <string name="pref_content_load_page" msgid="2219810141690955452">"Öppna sidor i översikt"</string>
+ <string name="pref_content_load_page" msgid="2219810141690955452">"Öppna sidan i översikt"</string>
<string name="pref_content_load_page_summary" msgid="8792093504054149369">"Visa översikt över nyligen öppnade sidor"</string>
<string name="pref_extras_title" msgid="3091250467679722382">"Avancerade inställningar"</string>
<string name="pref_extras_website_settings" msgid="67866640052455549">"Webbplatsinställningar"</string>
<string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"Visa avancerade inställningar för enskilda webbplatser"</string>
- <string name="pref_extras_reset_default" msgid="8904000515846202110">"Återställ standardinställningarna"</string>
+ <string name="pref_extras_reset_default" msgid="8904000515846202110">"Återställ standardinställn."</string>
<string name="pref_extras_reset_default_summary" msgid="7984680562706914966">"Ta bort alla data i webbläsaren och återställ standardinställningarna"</string>
<string name="pref_extras_reset_default_dlg" msgid="6894807766578874830">"Alla data i webbläsaren tas bort och standardinställningarna återställs."</string>
<string name="pref_extras_reset_default_dlg_title" msgid="2250334970728938936">"Återställ standardinställn."</string>
@@ -278,6 +282,10 @@
<string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Dela plats"</string>
<string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Avvisa"</string>
<string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Kom ihåg mina inställningar"</string>
+ <!-- no translation found for geolocation_permissions_prompt_toast_allowed (987286072035125498) -->
+ <skip />
+ <!-- no translation found for geolocation_permissions_prompt_toast_disallowed (7695100950212692515) -->
+ <skip />
<string name="geolocation_settings_page_title" msgid="1745477985097536528">"Ta bort platsåtkomst"</string>
<string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Den här webbplatsen har för närvarande åtkomst till din plats"</string>
<string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Den här webbplatsen har för närvarande inte åtkomst till din plats"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index e318a53..0fddc70 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -16,6 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="1935869255545976415">"Tarayıcı"</string>
+ <!-- no translation found for choose_upload (3649366287575002063) -->
+ <skip />
<string name="new_tab" msgid="4505722538297295141">"Yeni pencere"</string>
<string name="active_tabs" msgid="3050623868203544623">"Pencereler"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"Favoriler"</string>
@@ -84,6 +86,8 @@
<string name="bookmark_needs_url" msgid="7809876865972755158">"Favorinin bir konumu olmalıdır."</string>
<string name="empty_bookmark" msgid="7008697085928540511">"Boş favori oluşturulamaz."</string>
<string name="bookmark_url_not_valid" msgid="6719785633980202419">"URL geçerli değil."</string>
+ <!-- no translation found for bookmark_cannot_save_url (791722768778386941) -->
+ <skip />
<string name="delete_bookmark" msgid="2422989994934201992">"Sil"</string>
<string name="bookmark_page" msgid="6845189305130307274">"Son görüntülenen sayfayı favori olarak işaretle"</string>
<string name="switch_to_thumbnails" msgid="5493351529609043151">"Küçük resim görünümü"</string>
@@ -94,7 +98,7 @@
<string name="new_window" msgid="8117889615360211551">"Yeni pencere"</string>
<string name="goto_dot" msgid="3895839050522602723">"Git"</string>
<string name="find_dot" msgid="6259312434696611957">"Sayfada bul"</string>
- <string name="select_dot" msgid="6299170761900561967">"Metin seç"</string>
+ <string name="select_dot" msgid="6299170761900561967">"Metni seç"</string>
<string name="view_tabs" msgid="1119097492003550564">"Pencereye genel bakış"</string>
<string name="view_tabs_condensed" msgid="5803955493821945369">"Pencereler"</string>
<string name="tab_picker_title" msgid="864478399057782913">"Geçerli pencereler"</string>
@@ -278,6 +282,10 @@
<string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"Konumu paylaş"</string>
<string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"Reddet"</string>
<string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"Tercihi anımsa"</string>
+ <!-- no translation found for geolocation_permissions_prompt_toast_allowed (987286072035125498) -->
+ <skip />
+ <!-- no translation found for geolocation_permissions_prompt_toast_disallowed (7695100950212692515) -->
+ <skip />
<string name="geolocation_settings_page_title" msgid="1745477985097536528">"Konum erişimini temizle"</string>
<string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"Bu site şu anda konumunuza erişebilir"</string>
<string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"Bu site şu anda konumunuza erişemiyor"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index fa152b2..93d8ccc 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -16,6 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="1935869255545976415">"浏览器"</string>
+ <!-- no translation found for choose_upload (3649366287575002063) -->
+ <skip />
<string name="new_tab" msgid="4505722538297295141">"新窗口"</string>
<string name="active_tabs" msgid="3050623868203544623">"窗口"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"书签"</string>
@@ -84,6 +86,8 @@
<string name="bookmark_needs_url" msgid="7809876865972755158">"书签必须具有位置。"</string>
<string name="empty_bookmark" msgid="7008697085928540511">"无法创建空书签。"</string>
<string name="bookmark_url_not_valid" msgid="6719785633980202419">"网址无效。"</string>
+ <!-- no translation found for bookmark_cannot_save_url (791722768778386941) -->
+ <skip />
<string name="delete_bookmark" msgid="2422989994934201992">"删除"</string>
<string name="bookmark_page" msgid="6845189305130307274">"将上次查看过的网页加为书签"</string>
<string name="switch_to_thumbnails" msgid="5493351529609043151">"缩略图视图"</string>
@@ -92,9 +96,9 @@
<string name="delete_bookmark_warning" msgid="758043186202032205">"将会删除书签“<xliff:g id="BOOKMARK">%s</xliff:g>”。"</string>
<string name="open_in_new_window" msgid="6596775546468054510">"在新窗口中打开"</string>
<string name="new_window" msgid="8117889615360211551">"新窗口"</string>
- <string name="goto_dot" msgid="3895839050522602723">"转至"</string>
+ <string name="goto_dot" msgid="3895839050522602723">"输入网址"</string>
<string name="find_dot" msgid="6259312434696611957">"在网页上查找"</string>
- <string name="select_dot" msgid="6299170761900561967">"选择文本"</string>
+ <string name="select_dot" msgid="6299170761900561967">"选择文字"</string>
<string name="view_tabs" msgid="1119097492003550564">"窗口概述"</string>
<string name="view_tabs_condensed" msgid="5803955493821945369">"窗口"</string>
<string name="tab_picker_title" msgid="864478399057782913">"当前窗口"</string>
@@ -111,7 +115,7 @@
<string name="share_page" msgid="593756995297268343">"分享网页"</string>
<string name="contextmenu_openlink" msgid="7237961252214188935">"打开"</string>
<string name="contextmenu_openlink_newwindow" msgid="992765050093960353">"在新窗口中打开"</string>
- <string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"将链接加入书签"</string>
+ <string name="contextmenu_bookmark_thislink" msgid="8095373680616870021">"书签链接"</string>
<string name="contextmenu_savelink" msgid="5508554930832538184">"保存链接"</string>
<string name="contextmenu_sharelink" msgid="5392275392280130331">"分享链接"</string>
<string name="contextmenu_copy" msgid="398860586635404030">"复制"</string>
@@ -129,7 +133,7 @@
<string name="menu_preferences" msgid="6709237687234102240">"设置"</string>
<string name="pref_content_title" msgid="722227111894838633">"网页内容设置"</string>
<string name="pref_content_load_images" msgid="2125616852957377561">"载入图片"</string>
- <string name="pref_content_load_images_summary" msgid="5055874125248398584">"显示网页上的图片"</string>
+ <string name="pref_content_load_images_summary" msgid="5055874125248398584">"在网页上显示图片"</string>
<string name="pref_content_block_popups" msgid="7808433807197256726">"阻止弹出式窗口"</string>
<string name="pref_content_javascript" msgid="4570972030299516843">"启用 JavaScript"</string>
<string name="pref_content_open_in_background" msgid="824123779725118663">"在后方打开"</string>
@@ -137,9 +141,9 @@
<string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"在当前窗口后方打开新窗口"</string>
<string name="pref_content_homepage" msgid="6082437160778559806">"设置主页"</string>
<string name="pref_content_autofit" msgid="8260474534053660809">"自动调整页面"</string>
- <string name="pref_content_autofit_summary" msgid="4587831659894879986">"调整网页版面以适合屏幕大小"</string>
+ <string name="pref_content_autofit_summary" msgid="4587831659894879986">"调整网页格式以适合屏幕大小"</string>
<string name="pref_content_landscape_only" msgid="2022546812766219672">"仅以横向模式显示"</string>
- <string name="pref_content_landscape_only_summary" msgid="1008238895535428855">"仅以横向宽屏模式显示网页"</string>
+ <string name="pref_content_landscape_only_summary" msgid="1008238895535428855">"仅限以横向宽屏模式显示网页"</string>
<string name="pref_privacy_title" msgid="1052470980370846151">"隐私权设置"</string>
<string name="pref_privacy_clear_cache" msgid="3380316479925886998">"清除缓存"</string>
<string name="pref_privacy_clear_cache_summary" msgid="2216463577207991454">"清除存储在本地缓存中的内容和数据库"</string>
@@ -159,8 +163,8 @@
<string name="pref_privacy_enable_geolocation" msgid="1395040170290765686">"启用位置信息功能"</string>
<string name="pref_privacy_enable_geolocation_summary" msgid="8437020934664306205">"允许网站访问您的位置信息"</string>
<string name="pref_privacy_clear_geolocation_access" msgid="6649680770030042980">"取消位置信息访问权限"</string>
- <string name="pref_privacy_clear_geolocation_access_summary" msgid="7750143359497314679">"取消所有网站访问位置信息的权限"</string>
- <string name="pref_privacy_clear_geolocation_access_dlg" msgid="7327063124488827244">"取消所有网站访问位置信息的权限"</string>
+ <string name="pref_privacy_clear_geolocation_access_summary" msgid="7750143359497314679">"取消所有网站的位置信息访问权限"</string>
+ <string name="pref_privacy_clear_geolocation_access_dlg" msgid="7327063124488827244">"取消所有网站的位置信息访问权限"</string>
<string name="pref_security_title" msgid="5763978646932160021">"安全设置"</string>
<string name="pref_security_remember_passwords" msgid="6492957683454529549">"记住密码"</string>
<string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"保存网站的用户名和密码"</string>
@@ -186,7 +190,7 @@
<item msgid="3840999588443167001">"近"</item>
</string-array>
<string name="pref_default_zoom_dialogtitle" msgid="6095974367125109021">"默认缩放设置"</string>
- <string name="pref_content_load_page" msgid="2219810141690955452">"以概览模式打开网页"</string>
+ <string name="pref_content_load_page" msgid="2219810141690955452">"打开概览中的网页"</string>
<string name="pref_content_load_page_summary" msgid="8792093504054149369">"显示新打开网页的概览"</string>
<string name="pref_extras_title" msgid="3091250467679722382">"高级设置"</string>
<string name="pref_extras_website_settings" msgid="67866640052455549">"网站设置"</string>
@@ -238,7 +242,7 @@
<string name="download_menu_cancel_all" msgid="2136550823151999166">"取消所有下载"</string>
<string name="download_menu_clear_all" msgid="7423737413377703862">"清除列表"</string>
<string name="download_clear_dlg_title" msgid="7961996329529777390">"清除"</string>
- <string name="download_clear_dlg_msg" msgid="8056013815679757669">"所有下载项都会从列表中清除并从浏览器缓存中删除。"</string>
+ <string name="download_clear_dlg_msg" msgid="8056013815679757669">"所有项都会从列表中清除并会从浏览器缓存中删除。"</string>
<string name="download_cancel_dlg_title" msgid="8909108500262799748">"取消下载"</string>
<string name="download_cancel_dlg_msg" msgid="6285389170052357797">"所有 <xliff:g id="DOWNLOAD_COUNT">%d</xliff:g> 项下载都会取消并从下载历史记录中清除。"</string>
<string name="download_file_error_dlg_title" msgid="2693630283595384874">"空间不足"</string>
@@ -278,6 +282,10 @@
<string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"共享位置信息"</string>
<string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"拒绝"</string>
<string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"记住偏好设置"</string>
+ <!-- no translation found for geolocation_permissions_prompt_toast_allowed (987286072035125498) -->
+ <skip />
+ <!-- no translation found for geolocation_permissions_prompt_toast_disallowed (7695100950212692515) -->
+ <skip />
<string name="geolocation_settings_page_title" msgid="1745477985097536528">"取消位置信息访问权限"</string>
<string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"此网站目前可访问您的位置信息"</string>
<string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"此网站目前不能访问您的位置信息"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index d1e230a..004854e 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -16,8 +16,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="1935869255545976415">"瀏覽器"</string>
+ <!-- no translation found for choose_upload (3649366287575002063) -->
+ <skip />
<string name="new_tab" msgid="4505722538297295141">"新視窗"</string>
- <string name="active_tabs" msgid="3050623868203544623">"視窗"</string>
+ <string name="active_tabs" msgid="3050623868203544623">"Windows"</string>
<string name="tab_bookmarks" msgid="2305793036003473653">"書籤"</string>
<string name="tab_most_visited" msgid="1077402532455000703">"常用網頁"</string>
<string name="tab_history" msgid="1979267558744613746">"記錄"</string>
@@ -33,8 +35,8 @@
<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>
+ <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>
@@ -58,7 +60,7 @@
<string name="validity_period" msgid="57988851973181309">"合法性:"</string>
<string name="issued_on" msgid="2082890654801808368">"發給:"</string>
<string name="expires_on" msgid="8061200430557020704">"有效日期:"</string>
- <string name="retrieving_creds_dlg_msg" msgid="9207671133094039879">"擷取登入資訊…"</string>
+ <string name="retrieving_creds_dlg_msg" msgid="9207671133094039879">"取回登入資訊…"</string>
<string name="stopping" msgid="4839698519340302982">"停止中…"</string>
<string name="stop" msgid="5687251076030630074">"停止"</string>
<string name="reload" msgid="8585220783228408062">"重新整理"</string>
@@ -67,7 +69,7 @@
<string name="save" msgid="5922311934992468496">"確定"</string>
<string name="do_not_save" msgid="6777633870113477714">"取消"</string>
<string name="location" msgid="969988560160364559">"位置"</string>
- <string name="name" msgid="5990326151488445481">"名稱"</string>
+ <string name="name" msgid="5990326151488445481">"名字"</string>
<string name="http" msgid="2163722670597250102">"http://"</string>
<string name="save_to_bookmarks" msgid="588165100024086565">"新增書籤"</string>
<string name="edit_bookmark" msgid="5024089053490231905">"編輯書籤"</string>
@@ -79,11 +81,13 @@
<string name="set_as_homepage" msgid="4752937379414905560">"設為首頁"</string>
<string name="bookmark_saved" msgid="2766434679871317557">"已儲存至書籤。"</string>
<string name="bookmark_not_saved" msgid="700600955089376724">"無法儲存書籤。"</string>
- <string name="homepage_set" msgid="8768087280310966395">"已設定為首頁。"</string>
+ <string name="homepage_set" msgid="8768087280310966395">"已設定首頁。"</string>
<string name="bookmark_needs_title" msgid="6245900436119218187">"請輸入書籤名稱。"</string>
<string name="bookmark_needs_url" msgid="7809876865972755158">"請選取書籤位置。"</string>
<string name="empty_bookmark" msgid="7008697085928540511">"無法建立空白書籤。"</string>
<string name="bookmark_url_not_valid" msgid="6719785633980202419">"網址無效。"</string>
+ <!-- no translation found for bookmark_cannot_save_url (791722768778386941) -->
+ <skip />
<string name="delete_bookmark" msgid="2422989994934201992">"刪除"</string>
<string name="bookmark_page" msgid="6845189305130307274">"將最後瀏覽的網頁加入書籤"</string>
<string name="switch_to_thumbnails" msgid="5493351529609043151">"縮圖檢視"</string>
@@ -134,7 +138,7 @@
<string name="pref_content_javascript" msgid="4570972030299516843">"啟用 JavaScript"</string>
<string name="pref_content_open_in_background" msgid="824123779725118663">"在背景中開啟"</string>
<string name="pref_content_plugins" msgid="7231944644794301582">"啟用外掛程式"</string>
- <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"在目前視窗的後面開啟新視窗"</string>
+ <string name="pref_content_open_in_background_summary" msgid="1737664075721181678">"在目前視窗的背景開啟新視窗"</string>
<string name="pref_content_homepage" msgid="6082437160778559806">"設定首頁"</string>
<string name="pref_content_autofit" msgid="8260474534053660809">"自動調整頁面"</string>
<string name="pref_content_autofit_summary" msgid="4587831659894879986">"配合螢幕大小調整網頁版面"</string>
@@ -144,15 +148,15 @@
<string name="pref_privacy_clear_cache" msgid="3380316479925886998">"清除快取"</string>
<string name="pref_privacy_clear_cache_summary" msgid="2216463577207991454">"清除本機快取內容與資料庫"</string>
<string name="pref_privacy_clear_cache_dlg" msgid="5541011591300753881">"即將刪除本機快取內容與資料庫。"</string>
- <string name="pref_privacy_clear_cookies" msgid="3095583579133780331">"清除所有 Cookie"</string>
- <string name="pref_privacy_clear_cookies_summary" msgid="6962742063990677520">"清除瀏覽器中所有 Cookie"</string>
+ <string name="pref_privacy_clear_cookies" msgid="3095583579133780331">"清除所有 cookie"</string>
+ <string name="pref_privacy_clear_cookies_summary" msgid="6962742063990677520">"要清除所有瀏覽器 Cookies 嗎?"</string>
<string name="pref_privacy_clear_cookies_dlg" msgid="552855688091432682">"即將刪除所有 Cookie。"</string>
<string name="pref_privacy_clear_history" msgid="8723795508825198477">"清除記錄"</string>
<string name="pref_privacy_clear_history_summary" msgid="6868501330708940734">"清除瀏覽記錄"</string>
<string name="pref_privacy_clear_history_dlg" msgid="544903007914753853">"即將刪除瀏覽器的瀏覽記錄。"</string>
<string name="pref_privacy_clear_form_data" msgid="4232668196344383987">"清除表單資料"</string>
- <string name="pref_privacy_clear_form_data_summary" msgid="1790390894719517167">"清除所有表單資料"</string>
- <string name="pref_privacy_clear_form_data_dlg" msgid="4443621086781197928">"即將刪除所有已儲存的表單資料。"</string>
+ <string name="pref_privacy_clear_form_data_summary" msgid="1790390894719517167">"清除所有表單"</string>
+ <string name="pref_privacy_clear_form_data_dlg" msgid="4443621086781197928">"即將刪除所有已儲存表單資料。"</string>
<string name="pref_privacy_clear_passwords" msgid="4750234112289277480">"清除密碼"</string>
<string name="pref_privacy_clear_passwords_summary" msgid="8856782718942903335">"清除所有已儲存密碼"</string>
<string name="pref_privacy_clear_passwords_dlg" msgid="2083869328824248255">"即將刪除所有儲存的密碼"</string>
@@ -163,13 +167,13 @@
<string name="pref_privacy_clear_geolocation_access_dlg" msgid="7327063124488827244">"清除所有網站的位置資訊存取權"</string>
<string name="pref_security_title" msgid="5763978646932160021">"安全性設定"</string>
<string name="pref_security_remember_passwords" msgid="6492957683454529549">"記住密碼"</string>
- <string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"儲存您的使用者名稱和密碼"</string>
+ <string name="pref_security_remember_passwords_summary" msgid="256388703356349137">"儲存網站的使用者名稱和密碼"</string>
<string name="pref_security_save_form_data" msgid="1213669802810198893">"儲存表單資料"</string>
<string name="pref_security_save_form_data_summary" msgid="4994074685153708026">"儲存輸入的表單資料"</string>
<string name="pref_security_show_security_warning" msgid="8901135676266754559">"顯示安全性警告"</string>
<string name="pref_security_show_security_warning_summary" msgid="8968906112720511704">"當網站安全性有問題時,顯示警告訊息"</string>
- <string name="pref_security_accept_cookies" msgid="3201367661925047989">"接受 Cookie"</string>
- <string name="pref_security_accept_cookies_summary" msgid="1465118934875026920">"允許網站存取 Cookie"</string>
+ <string name="pref_security_accept_cookies" msgid="3201367661925047989">"接受 cookie"</string>
+ <string name="pref_security_accept_cookies_summary" msgid="1465118934875026920">"允許網站存取 cookie"</string>
<string name="pref_text_size" msgid="3827031324346612208">"文字大小"</string>
<string-array name="pref_text_size_choices">
<item msgid="4952686548944739548">"最小"</item>
@@ -187,7 +191,7 @@
</string-array>
<string name="pref_default_zoom_dialogtitle" msgid="6095974367125109021">"預設縮放"</string>
<string name="pref_content_load_page" msgid="2219810141690955452">"以總覽模式開啟網頁"</string>
- <string name="pref_content_load_page_summary" msgid="8792093504054149369">"顯示新開啟網頁的總覽畫面"</string>
+ <string name="pref_content_load_page_summary" msgid="8792093504054149369">"顯示新開啟網頁的綜覽畫面"</string>
<string name="pref_extras_title" msgid="3091250467679722382">"進階設定"</string>
<string name="pref_extras_website_settings" msgid="67866640052455549">"網站設定"</string>
<string name="pref_extras_website_settings_summary" msgid="3917568895776162240">"查看個別網站的進階設定"</string>
@@ -278,6 +282,10 @@
<string name="geolocation_permissions_prompt_share" msgid="9084486342048347976">"分享位置資訊"</string>
<string name="geolocation_permissions_prompt_dont_share" msgid="6303025160237860300">"拒絕"</string>
<string name="geolocation_permissions_prompt_remember" msgid="3118526300707348308">"記住偏好設定"</string>
+ <!-- no translation found for geolocation_permissions_prompt_toast_allowed (987286072035125498) -->
+ <skip />
+ <!-- no translation found for geolocation_permissions_prompt_toast_disallowed (7695100950212692515) -->
+ <skip />
<string name="geolocation_settings_page_title" msgid="1745477985097536528">"清除位置資訊存取權"</string>
<string name="geolocation_settings_page_summary_allowed" msgid="9180251524290811398">"此網站目前可以存取您的位置資訊"</string>
<string name="geolocation_settings_page_summary_not_allowed" msgid="4589649082203102544">"此網站目前無法存取您的位置資訊"</string>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 3bb6ffd..cff8609 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -17,7 +17,8 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- The name of the application. -->
<string name="application_name">Browser</string>
-
+ <!-- Displayed with a file picker to choose a file to upload -->
+ <string name="choose_upload">Choose file for upload</string>
<!-- Name of menu item of a new tab. Also used in the title bar when displaying a new tab -->
<string name="new_tab">New window</string>
<!-- Name of menu item which brings up a list of the currently active tabs -->
@@ -170,6 +171,8 @@
<string name="empty_bookmark">"Cannot create empty bookmark."</string>
<!-- Error that appears in the title of Bookmark dialog when user selects OK with invalid URL -->
<string name="bookmark_url_not_valid">URL is not valid.</string>
+ <!-- Error that appears in the Bookmark dialog when user selects OK with a URL of a type we cannot bookmark -->
+ <string name="bookmark_cannot_save_url">This URL cannot be bookmarked.</string>
<!-- Title of a confirmation dialog when the user deletes a bookmark-->
<string name="delete_bookmark">Delete</string>
<!-- Menu item in the page that displays all bookmarks. It brings up a
@@ -313,6 +316,8 @@
<string name="pref_content_open_in_background_summary">Open new windows behind the current one</string>
<!-- Settings label -->
<string name="pref_content_homepage">Set home page</string>
+ <!-- Settings button label -->
+ <string name="pref_use_current">Use current page</string>
<!-- Settings label -->
<string name="pref_content_autofit">Auto-fit pages</string>
<!-- Settings summary -->
@@ -426,7 +431,7 @@
<!-- Settings label -->
<string name="pref_extras_website_settings">Website settings</string>
<!-- Settings summary -->
- <string name="pref_extras_website_settings_summary">View advanced settings for individual websites</string>
+ <string name="pref_extras_website_settings_summary">Advanced settings for individual websites</string>
<!-- Settings label -->
<string name="pref_extras_reset_default">Reset to default</string>
<!-- Settings summary -->
@@ -673,7 +678,7 @@
<item>eBay</item>
<item>http://www.ebay.com/</item>
<item>CNN</item>
- <item>http://www.cnn.com/index.html</item>
+ <item>http://www.cnn.com/</item>
<item>NY Times</item>
<item>http://www.nytimes.com/</item>
<item>ESPN</item>
@@ -740,6 +745,9 @@
<string name="geolocation_permissions_prompt_share">Share location</string>
<string name="geolocation_permissions_prompt_dont_share">Decline</string>
<string name="geolocation_permissions_prompt_remember">Remember preference</string>
+ <!-- Permissions prompt toast -->
+ <string name="geolocation_permissions_prompt_toast_allowed">This site can access your location. Change this in Settings -> Website settings</string>
+ <string name="geolocation_permissions_prompt_toast_disallowed">This site cannot access your location. Change this in Settings -> Website settings</string>
<!-- Settings page, Advanced Settings -> Website settings -> <origin> -->
<string name="geolocation_settings_page_title">Clear location access</string>
<string name="geolocation_settings_page_summary_allowed">This site can currently access your location</string>
diff --git a/res/xml/browser_preferences.xml b/res/xml/browser_preferences.xml
index 1845e20..04c0ebe 100644
--- a/res/xml/browser_preferences.xml
+++ b/res/xml/browser_preferences.xml
@@ -93,8 +93,7 @@
android:key="homepage"
android:title="@string/pref_content_homepage"
android:hint="@string/http"
- android:inputType="textUri"
- android:singleLine="true" />
+ android:inputType="textUri|textMultiLine" />
</PreferenceCategory>
diff --git a/src/com/android/browser/ActiveTabsPage.java b/src/com/android/browser/ActiveTabsPage.java
index 90c417a..72f291c 100644
--- a/src/com/android/browser/ActiveTabsPage.java
+++ b/src/com/android/browser/ActiveTabsPage.java
@@ -49,7 +49,7 @@
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
- if (mControl.getTabCount() < TabControl.MAX_TABS) {
+ if (mControl.canCreateNewTab()) {
position--;
}
boolean needToAttach = false;
@@ -92,7 +92,7 @@
private class TabsListAdapter extends BaseAdapter {
public int getCount() {
int count = mControl.getTabCount();
- if (count < TabControl.MAX_TABS) {
+ if (mControl.canCreateNewTab()) {
count++;
}
return count;
@@ -107,7 +107,7 @@
return 2;
}
public int getItemViewType(int position) {
- if (mControl.getTabCount() < TabControl.MAX_TABS) {
+ if (mControl.canCreateNewTab()) {
position--;
}
// Do not recycle the "add new tab" item.
@@ -115,7 +115,7 @@
}
public View getView(int position, View convertView, ViewGroup parent) {
final int tabCount = mControl.getTabCount();
- if (tabCount < TabControl.MAX_TABS) {
+ if (mControl.canCreateNewTab()) {
position--;
}
@@ -131,8 +131,8 @@
ImageView favicon =
(ImageView) convertView.findViewById(R.id.favicon);
View close = convertView.findViewById(R.id.close);
- TabControl.Tab tab = mControl.getTab(position);
- mControl.populatePickerData(tab);
+ Tab tab = mControl.getTab(position);
+ tab.populatePickerData();
title.setText(tab.getTitle());
url.setText(tab.getUrl());
Bitmap icon = tab.getFavicon();
diff --git a/src/com/android/browser/AddBookmarkPage.java b/src/com/android/browser/AddBookmarkPage.java
index 81123ba..a9c7217 100644
--- a/src/com/android/browser/AddBookmarkPage.java
+++ b/src/com/android/browser/AddBookmarkPage.java
@@ -178,23 +178,33 @@
}
return false;
}
- String url = unfilteredUrl;
+ String url = unfilteredUrl.trim();
try {
- URI uriObj = new URI(url);
- String scheme = uriObj.getScheme();
- if (!("about".equals(scheme) || "data".equals(scheme)
- || "javascript".equals(scheme)
- || "file".equals(scheme) || "content".equals(scheme))) {
- WebAddress address;
- try {
- address = new WebAddress(unfilteredUrl);
- } catch (ParseException e) {
- throw new URISyntaxException("", "");
+ // We allow bookmarks with a javascript: scheme, but these will in most cases
+ // fail URI parsing, so don't try it if that's the kind of bookmark we have.
+
+ if (!url.toLowerCase().startsWith("javascript:")) {
+ URI uriObj = new URI(url);
+ String scheme = uriObj.getScheme();
+ if (!Bookmarks.urlHasAcceptableScheme(url)) {
+ // If the scheme was non-null, let the user know that we
+ // can't save their bookmark. If it was null, we'll assume
+ // they meant http when we parse it in the WebAddress class.
+ if (scheme != null) {
+ mAddress.setError(r.getText(R.string.bookmark_cannot_save_url));
+ return false;
+ }
+ WebAddress address;
+ try {
+ address = new WebAddress(unfilteredUrl);
+ } catch (ParseException e) {
+ throw new URISyntaxException("", "");
+ }
+ if (address.mHost.length() == 0) {
+ throw new URISyntaxException("", "");
+ }
+ url = address.toString();
}
- if (address.mHost.length() == 0) {
- throw new URISyntaxException("", "");
- }
- url = address.toString();
}
} catch (URISyntaxException e) {
mAddress.setError(r.getText(R.string.bookmark_url_not_valid));
diff --git a/src/com/android/browser/BookmarkItem.java b/src/com/android/browser/BookmarkItem.java
index a70dd4f..fbb362e 100644
--- a/src/com/android/browser/BookmarkItem.java
+++ b/src/com/android/browser/BookmarkItem.java
@@ -33,6 +33,7 @@
protected TextView mUrlText;
protected ImageView mImageView;
protected String mUrl;
+ protected String mTitle;
/**
* Instantiate a bookmark item, including a default favicon.
@@ -65,7 +66,7 @@
* Return the name assigned to this bookmark item.
*/
/* package */ String getName() {
- return mTextView.getText().toString();
+ return mTitle;
}
/**
@@ -99,6 +100,16 @@
* @param name The new name for the bookmark item.
*/
/* package */ void setName(String name) {
+ if (name == null) {
+ return;
+ }
+
+ mTitle = name;
+
+ if (name.length() > BrowserSettings.MAX_TEXTVIEW_LEN) {
+ name = name.substring(0, BrowserSettings.MAX_TEXTVIEW_LEN);
+ }
+
mTextView.setText(name);
}
@@ -107,7 +118,16 @@
* @param url The new url for the bookmark item.
*/
/* package */ void setUrl(String url) {
- mUrlText.setText(url);
+ if (url == null) {
+ return;
+ }
+
mUrl = url;
+
+ if (url.length() > BrowserSettings.MAX_TEXTVIEW_LEN) {
+ url = url.substring(0, BrowserSettings.MAX_TEXTVIEW_LEN);
+ }
+
+ mUrlText.setText(url);
}
}
diff --git a/src/com/android/browser/Bookmarks.java b/src/com/android/browser/Bookmarks.java
index c8aaee7..8d98f89 100644
--- a/src/com/android/browser/Bookmarks.java
+++ b/src/com/android/browser/Bookmarks.java
@@ -41,6 +41,18 @@
private static String[] SELECTION_ARGS;
+ // We only want the user to be able to bookmark content that
+ // the browser can handle directly.
+ private static final String acceptableBookmarkSchemes[] = {
+ "http:",
+ "https:",
+ "about:",
+ "data:",
+ "javascript:",
+ "file:",
+ "content:"
+ };
+
/**
* Add a bookmark to the database.
* @param context Context of the calling Activity. This is used to make
@@ -214,4 +226,17 @@
bm.compress(Bitmap.CompressFormat.PNG, 100, os);
return os.toByteArray();
}
+
+ /* package */ static boolean urlHasAcceptableScheme(String url) {
+ if (url == null) {
+ return false;
+ }
+
+ for (int i = 0; i < acceptableBookmarkSchemes.length; i++) {
+ if (url.startsWith(acceptableBookmarkSchemes[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/src/com/android/browser/BrowserActivity.java b/src/com/android/browser/BrowserActivity.java
index 9030cf7..d39d897 100644
--- a/src/com/android/browser/BrowserActivity.java
+++ b/src/com/android/browser/BrowserActivity.java
@@ -16,9 +16,6 @@
package com.android.browser;
-import com.google.android.googleapps.IGoogleLoginService;
-import com.google.android.googlelogin.GoogleLoginServiceConstants;
-
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
@@ -34,33 +31,23 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
-import android.content.DialogInterface.OnCancelListener;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
-import android.graphics.DrawFilter;
-import android.graphics.Paint;
-import android.graphics.PaintFlagsDrawFilter;
import android.graphics.Picture;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
-import android.hardware.SensorListener;
-import android.hardware.SensorManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.WebAddress;
-import android.net.http.EventHandler;
import android.net.http.SslCertificate;
import android.net.http.SslError;
import android.os.AsyncTask;
@@ -83,7 +70,6 @@
import android.text.IClipboard;
import android.text.TextUtils;
import android.text.format.DateFormat;
-import android.text.util.Regex;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ContextMenu;
@@ -99,41 +85,31 @@
import android.view.WindowManager;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.MenuItem.OnMenuItemClickListener;
-import android.view.animation.AlphaAnimation;
-import android.view.animation.Animation;
-import android.view.animation.AnimationSet;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.ScaleAnimation;
-import android.view.animation.TranslateAnimation;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.DownloadListener;
-import android.webkit.GeolocationPermissions;
import android.webkit.HttpAuthHandler;
import android.webkit.PluginManager;
import android.webkit.SslErrorHandler;
import android.webkit.URLUtil;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
-import android.webkit.WebChromeClient.CustomViewCallback;
import android.webkit.WebHistoryItem;
import android.webkit.WebIconDatabase;
-import android.webkit.WebStorage;
import android.webkit.WebView;
-import android.webkit.WebViewClient;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
-import java.io.BufferedOutputStream;
+import com.android.common.Patterns;
+
+import com.google.android.googleapps.IGoogleLoginService;
+import com.google.android.googlelogin.GoogleLoginServiceConstants;
+
import java.io.ByteArrayOutputStream;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
@@ -141,14 +117,9 @@
import java.net.URLEncoder;
import java.text.ParseException;
import java.util.Date;
-import java.util.Enumeration;
import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
public class BrowserActivity extends Activity
implements View.OnCreateContextMenuListener,
@@ -164,8 +135,6 @@
private IGoogleLoginService mGls = null;
private ServiceConnection mGlsConnection = null;
- private SensorManager mSensorManager = null;
-
// These are single-character shortcuts for searching popular sources.
private static final int SHORTCUT_INVALID = 0;
private static final int SHORTCUT_GOOGLE_SEARCH = 1;
@@ -173,23 +142,6 @@
private static final int SHORTCUT_DICTIONARY_SEARCH = 3;
private static final int SHORTCUT_GOOGLE_MOBILE_LOCAL_SEARCH = 4;
- /* Whitelisted webpages
- private static HashSet<String> sWhiteList;
-
- static {
- sWhiteList = new HashSet<String>();
- sWhiteList.add("cnn.com/");
- sWhiteList.add("espn.go.com/");
- sWhiteList.add("nytimes.com/");
- sWhiteList.add("engadget.com/");
- sWhiteList.add("yahoo.com/");
- sWhiteList.add("msn.com/");
- sWhiteList.add("amazon.com/");
- sWhiteList.add("consumerist.com/");
- sWhiteList.add("google.com/m/news");
- }
- */
-
private void setupHomePage() {
final Runnable getAccount = new Runnable() {
public void run() {
@@ -295,7 +247,8 @@
*/
private FrameLayout mBrowserFrameLayout;
- @Override public void onCreate(Bundle icicle) {
+ @Override
+ public void onCreate(Bundle icicle) {
if (LOGV_ENABLED) {
Log.v(LOGTAG, this + " onStart");
}
@@ -314,16 +267,6 @@
return;
}
- //
- // start MASF proxy service
- //
- //Intent proxyServiceIntent = new Intent();
- //proxyServiceIntent.setComponent
- // (new ComponentName(
- // "com.android.masfproxyservice",
- // "com.android.masfproxyservice.MasfProxyService"));
- //startService(proxyServiceIntent, null);
-
mSecLockIcon = Resources.getSystem().getDrawable(
android.R.drawable.ic_secure);
mMixLockIcon = Resources.getSystem().getDrawable(
@@ -341,6 +284,7 @@
.findViewById(R.id.fullscreen_custom_content);
frameLayout.addView(mBrowserFrameLayout, COVER_SCREEN_PARAMS);
mTitleBar = new TitleBar(this);
+ mFakeTitleBar = new TitleBar(this);
// Create the tab control and our initial tab
mTabControl = new TabControl(this);
@@ -435,7 +379,7 @@
// the tab will be close when exit.
UrlData urlData = getUrlDataFromIntent(intent);
- final TabControl.Tab t = mTabControl.createNewTab(
+ final Tab t = mTabControl.createNewTab(
Intent.ACTION_VIEW.equals(intent.getAction()) &&
intent.getData() != null,
intent.getStringExtra(Browser.EXTRA_APPLICATION_ID), urlData.mUrl);
@@ -485,7 +429,7 @@
@Override
protected void onNewIntent(Intent intent) {
- TabControl.Tab current = mTabControl.getCurrentTab();
+ Tab current = mTabControl.getCurrentTab();
// When a tab is closed on exit, the current tab index is set to -1.
// Reset before proceed as Browser requires the current tab to be set.
if (current == null) {
@@ -528,7 +472,7 @@
if (Intent.ACTION_VIEW.equals(action)
&& !getPackageName().equals(appId)
&& (flags & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
- TabControl.Tab appTab = mTabControl.getTabFromId(appId);
+ Tab appTab = mTabControl.getTabFromId(appId);
if (appTab != null) {
Log.i(LOGTAG, "Reusing tab for " + appId);
// Dismiss the subwindow if applicable.
@@ -575,8 +519,21 @@
}
}
} else {
- if ("about:debug".equals(urlData.mUrl)) {
- mSettings.toggleDebugSettings();
+ if (!urlData.isEmpty()
+ && urlData.mUrl.startsWith("about:debug")) {
+ if ("about:debug.dom".equals(urlData.mUrl)) {
+ current.getWebView().dumpDomTree(false);
+ } else if ("about:debug.dom.file".equals(urlData.mUrl)) {
+ current.getWebView().dumpDomTree(true);
+ } else if ("about:debug.render".equals(urlData.mUrl)) {
+ current.getWebView().dumpRenderTree(false);
+ } else if ("about:debug.render.file".equals(urlData.mUrl)) {
+ current.getWebView().dumpRenderTree(true);
+ } else if ("about:debug.display".equals(urlData.mUrl)) {
+ current.getWebView().dumpDisplayTree();
+ } else {
+ mSettings.toggleDebugSettings();
+ }
return;
}
// Get rid of the subwindow if it exists
@@ -637,7 +594,7 @@
// URLs and site specific search shortcuts are handled by the regular flow of control, so
// return early.
- if (Regex.WEB_URL_PATTERN.matcher(url).matches()
+ if (Patterns.WEB_URL.matcher(url).matches()
|| ACCEPTED_URI_SCHEMA.matcher(url).matches()
|| parseUrlShortcut(url) != SHORTCUT_INVALID) {
return false;
@@ -687,11 +644,7 @@
url = intent.getStringExtra(SearchManager.QUERY);
if (url != null) {
mLastEnteredUrl = url;
- // Don't add Urls, just search terms.
- // Urls will get added when the page is loaded.
- if (!Regex.WEB_URL_PATTERN.matcher(url).matches()) {
- Browser.updateVisitedHistory(mResolver, url, false);
- }
+ Browser.updateVisitedHistory(mResolver, url, false);
// In general, we shouldn't modify URL from Intent.
// But currently, we get the user-typed URL from search box as well.
url = fixUrl(url);
@@ -744,100 +697,8 @@
return inUrl;
}
- /**
- * Looking for the pattern like this
- *
- * *
- * * *
- * *** * *******
- * * *
- * * *
- * *
- */
- private final SensorListener mSensorListener = new SensorListener() {
- private long mLastGestureTime;
- private float[] mPrev = new float[3];
- private float[] mPrevDiff = new float[3];
- private float[] mDiff = new float[3];
- private float[] mRevertDiff = new float[3];
-
- public void onSensorChanged(int sensor, float[] values) {
- boolean show = false;
- float[] diff = new float[3];
-
- for (int i = 0; i < 3; i++) {
- diff[i] = values[i] - mPrev[i];
- if (Math.abs(diff[i]) > 1) {
- show = true;
- }
- if ((diff[i] > 1.0 && mDiff[i] < 0.2)
- || (diff[i] < -1.0 && mDiff[i] > -0.2)) {
- // start track when there is a big move, or revert
- mRevertDiff[i] = mDiff[i];
- mDiff[i] = 0;
- } else if (diff[i] > -0.2 && diff[i] < 0.2) {
- // reset when it is flat
- mDiff[i] = mRevertDiff[i] = 0;
- }
- mDiff[i] += diff[i];
- mPrevDiff[i] = diff[i];
- mPrev[i] = values[i];
- }
-
- if (false) {
- // only shows if we think the delta is big enough, in an attempt
- // to detect "serious" moves left/right or up/down
- Log.d("BrowserSensorHack", "sensorChanged " + sensor + " ("
- + values[0] + ", " + values[1] + ", " + values[2] + ")"
- + " diff(" + diff[0] + " " + diff[1] + " " + diff[2]
- + ")");
- Log.d("BrowserSensorHack", " mDiff(" + mDiff[0] + " "
- + mDiff[1] + " " + mDiff[2] + ")" + " mRevertDiff("
- + mRevertDiff[0] + " " + mRevertDiff[1] + " "
- + mRevertDiff[2] + ")");
- }
-
- long now = android.os.SystemClock.uptimeMillis();
- if (now - mLastGestureTime > 1000) {
- mLastGestureTime = 0;
-
- float y = mDiff[1];
- float z = mDiff[2];
- float ay = Math.abs(y);
- float az = Math.abs(z);
- float ry = mRevertDiff[1];
- float rz = mRevertDiff[2];
- float ary = Math.abs(ry);
- float arz = Math.abs(rz);
- boolean gestY = ay > 2.5f && ary > 1.0f && ay > ary;
- boolean gestZ = az > 3.5f && arz > 1.0f && az > arz;
-
- if ((gestY || gestZ) && !(gestY && gestZ)) {
- WebView view = mTabControl.getCurrentWebView();
-
- if (view != null) {
- if (gestZ) {
- if (z < 0) {
- view.zoomOut();
- } else {
- view.zoomIn();
- }
- } else {
- view.flingScroll(0, Math.round(y * 100));
- }
- }
- mLastGestureTime = now;
- }
- }
- }
-
- public void onAccuracyChanged(int sensor, int accuracy) {
- // TODO Auto-generated method stub
-
- }
- };
-
- @Override protected void onResume() {
+ @Override
+ protected void onResume() {
super.onResume();
if (LOGV_ENABLED) {
Log.v(LOGTAG, "BrowserActivity.onResume: this=" + this);
@@ -867,24 +728,12 @@
registerReceiver(mNetworkStateIntentReceiver,
mNetworkStateChangedFilter);
WebView.enablePlatformNotifications();
-
- if (mSettings.doFlick()) {
- if (mSensorManager == null) {
- mSensorManager = (SensorManager) getSystemService(
- Context.SENSOR_SERVICE);
- }
- mSensorManager.registerListener(mSensorListener,
- SensorManager.SENSOR_ACCELEROMETER,
- SensorManager.SENSOR_DELAY_FASTEST);
- } else {
- mSensorManager = null;
- }
}
/**
* Since the actual title bar is embedded in the WebView, and removing it
- * would change its appearance, create a temporary title bar to go at
- * the top of the screen while the menu is open.
+ * would change its appearance, use a different TitleBar to show overlayed
+ * at the top of the screen, when the menu is open or the page is loading.
*/
private TitleBar mFakeTitleBar;
@@ -987,7 +836,7 @@
private void showFakeTitleBar() {
final View decor = getWindow().peekDecorView();
- if (mFakeTitleBar == null && mActiveTabsPage == null
+ if (mFakeTitleBar.getParent() == null && mActiveTabsPage == null
&& !mActivityInPause && decor != null
&& decor.getWindowToken() != null) {
Rect visRect = new Rect();
@@ -997,12 +846,6 @@
}
return;
}
- final WebView webView = getTopWindow();
- mFakeTitleBar = new TitleBar(this);
- mFakeTitleBar.setTitleAndUrl(null, webView.getUrl());
- mFakeTitleBar.setProgress(webView.getProgress());
- mFakeTitleBar.setFavicon(webView.getFavicon());
- updateLockIconToLatest();
WindowManager manager
= (WindowManager) getSystemService(Context.WINDOW_SERVICE);
@@ -1050,8 +893,9 @@
showFakeTitleBar();
}
}
+
private void hideFakeTitleBar() {
- if (mFakeTitleBar == null) return;
+ if (mFakeTitleBar.getParent() == null) return;
WindowManager.LayoutParams params = (WindowManager.LayoutParams)
mFakeTitleBarHolder.getLayoutParams();
WebView mainView = mTabControl.getCurrentWebView();
@@ -1066,7 +910,6 @@
manager.updateViewLayout(mFakeTitleBarHolder, params);
mFakeTitleBarHolder.removeView(mFakeTitleBar);
manager.removeView(mFakeTitleBarHolder);
- mFakeTitleBar = null;
}
/**
@@ -1081,12 +924,21 @@
openContextMenu(mTitleBar);
}
+ @Override
+ public void onContextMenuClosed(Menu menu) {
+ super.onContextMenuClosed(menu);
+ if (mInLoad) {
+ showFakeTitleBar();
+ }
+ }
+
/**
* onSaveInstanceState(Bundle map)
* onSaveInstanceState is called right before onStop(). The map contains
* the saved state.
*/
- @Override protected void onSaveInstanceState(Bundle outState) {
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
if (LOGV_ENABLED) {
Log.v(LOGTAG, "BrowserActivity.onSaveInstanceState: this=" + this);
}
@@ -1100,7 +952,8 @@
mTabControl.saveState(outState);
}
- @Override protected void onPause() {
+ @Override
+ protected void onPause() {
super.onPause();
if (mActivityInPause) {
@@ -1135,22 +988,27 @@
// unregister network state listener
unregisterReceiver(mNetworkStateIntentReceiver);
WebView.disablePlatformNotifications();
-
- if (mSensorManager != null) {
- mSensorManager.unregisterListener(mSensorListener);
- }
}
- @Override protected void onDestroy() {
+ @Override
+ protected void onDestroy() {
if (LOGV_ENABLED) {
Log.v(LOGTAG, "BrowserActivity.onDestroy: this=" + this);
}
super.onDestroy();
+ if (mUploadMessage != null) {
+ mUploadMessage.onReceiveValue(null);
+ mUploadMessage = null;
+ }
+
if (mTabControl == null) return;
+ // Remove the fake title bar if it is there
+ hideFakeTitleBar();
+
// Remove the current tab and sub window
- TabControl.Tab t = mTabControl.getCurrentTab();
+ Tab t = mTabControl.getCurrentTab();
if (t != null) {
dismissSubWindow(t);
removeTabFromContentView(t);
@@ -1163,16 +1021,6 @@
mGlsConnection = null;
}
- //
- // stop MASF proxy service
- //
- //Intent proxyServiceIntent = new Intent();
- //proxyServiceIntent.setComponent
- // (new ComponentName(
- // "com.android.masfproxyservice",
- // "com.android.masfproxyservice.MasfProxyService"));
- //stopService(proxyServiceIntent);
-
unregisterReceiver(mPackageInstallationReceiver);
}
@@ -1213,21 +1061,20 @@
showHttpAuthentication(mHttpAuthHandler, null, null, title,
name, password, focusId);
}
- if (mFindDialog != null && mFindDialog.isShowing()) {
- mFindDialog.onConfigurationChanged(newConfig);
- }
}
- @Override public void onLowMemory() {
+ @Override
+ public void onLowMemory() {
super.onLowMemory();
mTabControl.freeMemory();
}
private boolean resumeWebViewTimers() {
- if ((!mActivityInPause && !mPageStarted) ||
- (mActivityInPause && mPageStarted)) {
+ Tab tab = mTabControl.getCurrentTab();
+ boolean inLoad = tab.inLoad();
+ if ((!mActivityInPause && !inLoad) || (mActivityInPause && inLoad)) {
CookieSyncManager.getInstance().startSync();
- WebView w = mTabControl.getCurrentWebView();
+ WebView w = tab.getWebView();
if (w != null) {
w.resumeTimers();
}
@@ -1238,7 +1085,9 @@
}
private boolean pauseWebViewTimers() {
- if (mActivityInPause && !mPageStarted) {
+ Tab tab = mTabControl.getCurrentTab();
+ boolean inLoad = tab.inLoad();
+ if (mActivityInPause && !inLoad) {
CookieSyncManager.getInstance().stopSync();
WebView w = mTabControl.getCurrentWebView();
if (w != null) {
@@ -1327,6 +1176,10 @@
return mTabControl.getCurrentTopWebView();
}
+ TabControl getTabControl() {
+ return mTabControl;
+ }
+
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
@@ -1438,8 +1291,8 @@
* the current one, return false.
*/
/* package */ boolean switchToTab(int index) {
- TabControl.Tab tab = mTabControl.getTab(index);
- TabControl.Tab currentTab = mTabControl.getCurrentTab();
+ Tab tab = mTabControl.getTab(index);
+ Tab currentTab = mTabControl.getCurrentTab();
if (tab == null || tab == currentTab) {
return false;
}
@@ -1455,20 +1308,20 @@
return true;
}
- /* package */ TabControl.Tab openTabToHomePage() {
+ /* package */ Tab openTabToHomePage() {
return openTabAndShow(mSettings.getHomePage(), false, null);
}
/* package */ void closeCurrentWindow() {
- final TabControl.Tab current = mTabControl.getCurrentTab();
+ final Tab current = mTabControl.getCurrentTab();
if (mTabControl.getTabCount() == 1) {
// This is the last tab. Open a new one, with the home
// page and close the current one.
- TabControl.Tab newTab = openTabToHomePage();
+ openTabToHomePage();
closeTab(current);
return;
}
- final TabControl.Tab parent = current.getParentTab();
+ final Tab parent = current.getParentTab();
int indexToShow = -1;
if (parent != null) {
indexToShow = mTabControl.getTabIndex(parent);
@@ -1581,7 +1434,7 @@
break;
case R.id.homepage_menu_id:
- TabControl.Tab current = mTabControl.getCurrentTab();
+ Tab current = mTabControl.getCurrentTab();
if (current != null) {
dismissSubWindow(current);
current.getWebView().loadUrl(mSettings.getHomePage());
@@ -1591,6 +1444,8 @@
case R.id.preferences_menu_id:
Intent intent = new Intent(this,
BrowserPreferencesPage.class);
+ intent.putExtra(BrowserPreferencesPage.CURRENT_PAGE,
+ getTopWindow().getUrl());
startActivityForResult(intent, PREFERENCES_PAGE);
break;
@@ -1647,7 +1502,7 @@
int menuid = item.getItemId();
for (int id = 0; id < WINDOW_SHORTCUT_ID_ARRAY.length; id++) {
if (WINDOW_SHORTCUT_ID_ARRAY[id] == menuid) {
- TabControl.Tab desiredTab = mTabControl.getTab(id);
+ Tab desiredTab = mTabControl.getTab(id);
if (desiredTab != null &&
desiredTab != mTabControl.getCurrentTab()) {
switchToTab(id);
@@ -1672,8 +1527,8 @@
mMenuState = R.id.MAIN_MENU;
}
- @Override public boolean onPrepareOptionsMenu(Menu menu)
- {
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
// This happens when the user begins to hold down the menu key, so
// allow them to chord to get a shortcut.
mCanChord = true;
@@ -1714,7 +1569,7 @@
.setEnabled(canGoForward);
menu.findItem(R.id.new_tab_menu_id).setEnabled(
- mTabControl.getTabCount() < TabControl.MAX_TABS);
+ mTabControl.canCreateNewTab());
// decide whether to show the share link option
PackageManager pm = getPackageManager();
@@ -1818,7 +1673,9 @@
menu.setHeaderView(titleView);
// decide whether to show the open link in new tab option
menu.findItem(R.id.open_newtab_context_menu_id).setVisible(
- mTabControl.getTabCount() < TabControl.MAX_TABS);
+ mTabControl.canCreateNewTab());
+ menu.findItem(R.id.bookmark_context_menu_id).setVisible(
+ Bookmarks.urlHasAcceptableScheme(extra));
PackageManager pm = getPackageManager();
Intent send = new Intent(Intent.ACTION_SEND);
send.setType("text/plain");
@@ -1842,17 +1699,18 @@
Log.w(LOGTAG, "We should not get here.");
break;
}
+ hideFakeTitleBar();
}
// Attach the given tab to the content view.
// this should only be called for the current tab.
- private void attachTabToContentView(TabControl.Tab t) {
+ private void attachTabToContentView(Tab t) {
// Attach the container that contains the main WebView and any other UI
// associated with the tab.
t.attachTabToContentView(mContentView);
if (mShouldShowErrorConsole) {
- ErrorConsoleView errorConsole = mTabControl.getCurrentErrorConsole(true);
+ ErrorConsoleView errorConsole = t.getErrorConsole(true);
if (errorConsole.numberOfErrors() == 0) {
errorConsole.showConsole(ErrorConsoleView.SHOW_NONE);
} else {
@@ -1864,14 +1722,6 @@
ViewGroup.LayoutParams.WRAP_CONTENT));
}
- setLockIconType(t.getLockIconType());
- setPrevLockType(t.getPrevLockIconType());
-
- // this is to match the code in removeTabFromContentView()
- if (!mPageStarted && t.getTopWindow().getProgress() < 100) {
- mPageStarted = true;
- }
-
WebView view = t.getWebView();
view.setEmbeddedTitleBar(mTitleBar);
// Request focus on the top window.
@@ -1879,70 +1729,51 @@
}
// Attach a sub window to the main WebView of the given tab.
- private void attachSubWindow(TabControl.Tab t) {
+ void attachSubWindow(Tab t) {
t.attachSubWindow(mContentView);
getTopWindow().requestFocus();
}
// Remove the given tab from the content view.
- private void removeTabFromContentView(TabControl.Tab t) {
+ private void removeTabFromContentView(Tab t) {
// Remove the container that contains the main WebView.
t.removeTabFromContentView(mContentView);
- if (mTabControl.getCurrentErrorConsole(false) != null) {
- mErrorConsoleContainer.removeView(mTabControl.getCurrentErrorConsole(false));
+ ErrorConsoleView errorConsole = t.getErrorConsole(false);
+ if (errorConsole != null) {
+ mErrorConsoleContainer.removeView(errorConsole);
}
WebView view = t.getWebView();
if (view != null) {
view.setEmbeddedTitleBar(null);
}
-
- // unlike attachTabToContentView(), removeTabFromContentView() can be
- // called for the non-current tab. Need to add the check.
- if (t == mTabControl.getCurrentTab()) {
- t.setLockIconType(getLockIconType());
- t.setPrevLockIconType(getPrevLockType());
-
- // this is not a perfect solution. But currently there is one
- // WebViewClient for all the WebView. if user switches from an
- // in-load window to an already loaded window, mPageStarted will not
- // be set to false. If user leaves the Browser, pauseWebViewTimers()
- // won't do anything and leaves the timer running even Browser is in
- // the background.
- if (mPageStarted) {
- mPageStarted = false;
- }
- }
}
// Remove the sub window if it exists. Also called by TabControl when the
// user clicks the 'X' to dismiss a sub window.
- /* package */ void dismissSubWindow(TabControl.Tab t) {
+ /* package */ void dismissSubWindow(Tab t) {
t.removeSubWindow(mContentView);
- // Tell the TabControl to dismiss the subwindow. This will destroy
- // the WebView.
- mTabControl.dismissSubWindow(t);
+ // dismiss the subwindow. This will destroy the WebView.
+ t.dismissSubWindow();
getTopWindow().requestFocus();
}
// A wrapper function of {@link #openTabAndShow(UrlData, boolean, String)}
// that accepts url as string.
- private TabControl.Tab openTabAndShow(String url, boolean closeOnExit,
- String appId) {
+ private Tab openTabAndShow(String url, boolean closeOnExit, String appId) {
return openTabAndShow(new UrlData(url), closeOnExit, appId);
}
// This method does a ton of stuff. It will attempt to create a new tab
// if we haven't reached MAX_TABS. Otherwise it uses the current tab. If
// url isn't null, it will load the given url.
- /* package */ TabControl.Tab openTabAndShow(UrlData urlData,
- boolean closeOnExit, String appId) {
- final boolean newTab = mTabControl.getTabCount() != TabControl.MAX_TABS;
- final TabControl.Tab currentTab = mTabControl.getCurrentTab();
- if (newTab) {
- final TabControl.Tab tab = mTabControl.createNewTab(
- closeOnExit, appId, urlData.mUrl);
+ /* package */Tab openTabAndShow(UrlData urlData, boolean closeOnExit,
+ String appId) {
+ final Tab currentTab = mTabControl.getCurrentTab();
+ if (mTabControl.canCreateNewTab()) {
+ final Tab tab = mTabControl.createNewTab(closeOnExit, appId,
+ urlData.mUrl);
WebView webview = tab.getWebView();
// If the last tab was removed from the active tabs page, currentTab
// will be null.
@@ -1968,9 +1799,9 @@
return currentTab;
}
- private TabControl.Tab openTab(String url) {
+ private Tab openTab(String url) {
if (mSettings.openInBackground()) {
- TabControl.Tab t = mTabControl.createNewTab();
+ Tab t = mTabControl.createNewTab();
if (t != null) {
WebView view = t.getWebView();
view.loadUrl(url);
@@ -2027,7 +1858,8 @@
* call resetTitleAndRevertLockIcon.
*/
/* package */ void resetTitleAndRevertLockIcon() {
- revertLockIcon();
+ mTabControl.getCurrentTab().revertLockIcon();
+ updateLockIconToLatest();
resetTitleIconAndProgress();
}
@@ -2041,7 +1873,7 @@
}
resetTitleAndIcon(current);
int progress = current.getProgress();
- mWebChromeClient.onProgressChanged(current, progress);
+ current.getWebChromeClient().onProgressChanged(current, progress);
}
// Reset the title and the icon based on the given item.
@@ -2061,14 +1893,12 @@
* @param url The URL of the site being loaded.
* @param title The title of the site being loaded.
*/
- private void setUrlTitle(String url, String title) {
+ void setUrlTitle(String url, String title) {
mUrl = url;
mTitle = title;
mTitleBar.setTitleAndUrl(title, url);
- if (mFakeTitleBar != null) {
- mFakeTitleBar.setTitleAndUrl(title, url);
- }
+ mFakeTitleBar.setTitleAndUrl(title, url);
}
/**
@@ -2109,43 +1939,16 @@
}
// Set the favicon in the title bar.
- private void setFavicon(Bitmap icon) {
+ void setFavicon(Bitmap icon) {
mTitleBar.setFavicon(icon);
- if (mFakeTitleBar != null) {
- mFakeTitleBar.setFavicon(icon);
- }
- }
-
- /**
- * Saves the current lock-icon state before resetting
- * the lock icon. If we have an error, we may need to
- * roll back to the previous state.
- */
- private void saveLockIcon() {
- mPrevLockType = mLockIconType;
- }
-
- /**
- * Reverts the lock-icon state to the last saved state,
- * for example, if we had an error, and need to cancel
- * the load.
- */
- private void revertLockIcon() {
- mLockIconType = mPrevLockType;
-
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "BrowserActivity.revertLockIcon:" +
- " revert lock icon to " + mLockIconType);
- }
-
- updateLockIconToLatest();
+ mFakeTitleBar.setFavicon(icon);
}
/**
* Close the tab, remove its associated title bar, and adjust mTabControl's
* current tab to a valid value.
*/
- /* package */ void closeTab(TabControl.Tab t) {
+ /* package */ void closeTab(Tab t) {
int currentIndex = mTabControl.getCurrentIndex();
int removeIndex = mTabControl.getTabIndex(t);
mTabControl.removeTab(t);
@@ -2157,7 +1960,7 @@
}
private void goBackOnePageOrQuit() {
- TabControl.Tab current = mTabControl.getCurrentTab();
+ Tab current = mTabControl.getCurrentTab();
if (current == null) {
/*
* Instead of finishing the activity, simply push this to the back
@@ -2175,17 +1978,17 @@
} else {
// Check to see if we are closing a window that was created by
// another window. If so, we switch back to that window.
- TabControl.Tab parent = current.getParentTab();
+ Tab parent = current.getParentTab();
if (parent != null) {
switchToTab(mTabControl.getTabIndex(parent));
// Now we close the other tab
closeTab(current);
} else {
if (current.closeOnExit()) {
- // force mPageStarted to be false as we are going to either
- // finish the activity or remove the tab. This will ensure
- // pauseWebView() taking action.
- mPageStarted = false;
+ // force the tab's inLoad() to be false as we are going to
+ // either finish the activity or remove the tab. This will
+ // ensure pauseWebViewTimers() taking action.
+ mTabControl.getCurrentTab().clearInLoad();
if (mTabControl.getTabCount() == 1) {
finish();
return;
@@ -2218,17 +2021,24 @@
}
}
+ boolean isMenuDown() {
+ return mMenuIsDown;
+ }
+
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
+ // Even if MENU is already held down, we need to call to super to open
+ // the IME on long press.
+ if (KeyEvent.KEYCODE_MENU == keyCode) {
+ mMenuIsDown = true;
+ return super.onKeyDown(keyCode, event);
+ }
// The default key mode is DEFAULT_KEYS_SEARCH_LOCAL. As the MENU is
// still down, we don't want to trigger the search. Pretend to consume
// the key and do nothing.
if (mMenuIsDown) return true;
switch(keyCode) {
- case KeyEvent.KEYCODE_MENU:
- mMenuIsDown = true;
- break;
case KeyEvent.KEYCODE_SPACE:
// WebView/WebTextView handle the keys in the KeyDown. As
// the Activity's shortcut keys are only handled when WebView
@@ -2263,7 +2073,8 @@
if (event.isTracking() && !event.isCanceled()) {
if (mCustomView != null) {
// if a custom view is showing, hide it
- mWebChromeClient.onHideCustomView();
+ mTabControl.getCurrentWebView().getWebChromeClient()
+ .onHideCustomView();
} else if (mActiveTabsPage != null) {
// if tab page is showing, hide it
removeActiveTabPage(true);
@@ -2291,7 +2102,12 @@
resetTitleAndRevertLockIcon();
WebView w = getTopWindow();
w.stopLoading();
- mWebViewClient.onPageFinished(w, w.getUrl());
+ // FIXME: before refactor, it is using mWebViewClient. So I keep the
+ // same logic here. But for subwindow case, should we call into the main
+ // WebView's onPageFinished as we never call its onPageStarted and if
+ // the page finishes itself, we don't call onPageFinished.
+ mTabControl.getCurrentWebView().getWebViewClient().onPageFinished(w,
+ w.getUrl());
cancelStopToast();
mStopToast = Toast
@@ -2299,6 +2115,10 @@
mStopToast.show();
}
+ boolean didUserStopLoading() {
+ return mDidStopLoad;
+ }
+
private void cancelStopToast() {
if (mStopToast != null) {
mStopToast.cancel();
@@ -2306,9 +2126,16 @@
}
}
- // called by a non-UI thread to post the message
- public void postMessage(int what, int arg1, int arg2, Object obj) {
- mHandler.sendMessage(mHandler.obtainMessage(what, arg1, arg2, obj));
+ // called by a UI or non-UI thread to post the message
+ public void postMessage(int what, int arg1, int arg2, Object obj,
+ long delayMillis) {
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(what, arg1, arg2,
+ obj), delayMillis);
+ }
+
+ // called by a UI or non-UI thread to remove the message
+ void removeMessages(int what, Object object) {
+ mHandler.removeMessages(what, object);
}
// public message ids
@@ -2320,7 +2147,7 @@
private static final int CANCEL_CREDS_REQUEST = 103;
private static final int RELEASE_WAKELOCK = 107;
- private static final int UPDATE_BOOKMARK_THUMBNAIL = 108;
+ static final int UPDATE_BOOKMARK_THUMBNAIL = 108;
// Private handler for handling javascript and saving passwords
private Handler mHandler = new Handler() {
@@ -2330,6 +2157,7 @@
case FOCUS_NODE_HREF:
{
String url = (String) msg.getData().get("url");
+ String title = (String) msg.getData().get("title");
if (url == null || url.length() == 0) {
break;
}
@@ -2345,9 +2173,8 @@
loadURL(getTopWindow(), url);
break;
case R.id.open_newtab_context_menu_id:
- final TabControl.Tab parent = mTabControl
- .getCurrentTab();
- final TabControl.Tab newTab = openTab(url);
+ final Tab parent = mTabControl.getCurrentTab();
+ final Tab newTab = openTab(url);
if (newTab != parent) {
parent.addChildTab(newTab);
}
@@ -2356,6 +2183,7 @@
Intent intent = new Intent(BrowserActivity.this,
AddBookmarkPage.class);
intent.putExtra("url", url);
+ intent.putExtra("title", title);
startActivity(intent);
break;
case R.id.share_link_context_menu_id:
@@ -2388,6 +2216,10 @@
case RELEASE_WAKELOCK:
if (mWakeLock.isHeld()) {
mWakeLock.release();
+ // if we reach here, Browser should be still in the
+ // background loading after WAKELOCK_TIMEOUT (5-min).
+ // To avoid burning the battery, stop loading.
+ mTabControl.stopAllLoading();
}
break;
@@ -2482,17 +2314,36 @@
// May need to tweak these values to determine what is the
// best scale factor
int thumbnailWidth = thumbnail.getWidth();
+ int thumbnailHeight = thumbnail.getHeight();
+ float scaleFactorX = 1.0f;
+ float scaleFactorY = 1.0f;
if (thumbnailWidth > 0) {
- float scaleFactor = (float) getDesiredThumbnailWidth(this) /
+ scaleFactorX = (float) getDesiredThumbnailWidth(this) /
(float)thumbnailWidth;
- canvas.scale(scaleFactor, scaleFactor);
+ } else {
+ return null;
}
+
+ if (view.getWidth() > view.getHeight() &&
+ thumbnailHeight < view.getHeight() && thumbnailHeight > 0) {
+ // If the device is in landscape and the page is shorter
+ // than the height of the view, stretch the thumbnail to fill the
+ // space.
+ scaleFactorY = (float) getDesiredThumbnailHeight(this) /
+ (float)thumbnailHeight;
+ } else {
+ // In the portrait case, this looks nice.
+ scaleFactorY = scaleFactorX;
+ }
+
+ canvas.scale(scaleFactorX, scaleFactorY);
+
thumbnail.draw(canvas);
return bm;
}
// -------------------------------------------------------------------------
- // WebViewClient implementation.
+ // Helper function for WebViewClient.
//-------------------------------------------------------------------------
// Use in overrideUrlLoading
@@ -2501,1022 +2352,309 @@
/* package */ final static String SCHEME_WTAI_SD = "wtai://wp/sd;";
/* package */ final static String SCHEME_WTAI_AP = "wtai://wp/ap;";
- /* package */ WebViewClient getWebViewClient() {
- return mWebViewClient;
- }
+ void onPageStarted(WebView view, String url, Bitmap favicon) {
+ // when BrowserActivity just starts, onPageStarted may be called before
+ // onResume as it is triggered from onCreate. Call resumeWebViewTimers
+ // to start the timer. As we won't switch tabs while an activity is in
+ // pause state, we can ensure calling resume and pause in pair.
+ if (mActivityInPause) resumeWebViewTimers();
- private void updateIcon(WebView view, Bitmap icon) {
- if (icon != null) {
- BrowserBookmarksAdapter.updateBookmarkFavicon(mResolver,
- view.getOriginalUrl(), view.getUrl(), icon);
- }
- setFavicon(icon);
- }
+ resetLockIcon(url);
+ setUrlTitle(url, null);
+ setFavicon(favicon);
+ // Keep this initial progress in sync with initialProgressValue (* 100)
+ // in ProgressTracker.cpp
+ // Show some progress so that the user knows the page is beginning to
+ // load
+ onProgressChanged(view, 10);
+ mDidStopLoad = false;
+ if (!mIsNetworkUp) createAndShowNetworkDialog();
- private void updateIcon(String url, Bitmap icon) {
- if (icon != null) {
- BrowserBookmarksAdapter.updateBookmarkFavicon(mResolver,
- null, url, icon);
- }
- setFavicon(icon);
- }
-
- private final WebViewClient mWebViewClient = new WebViewClient() {
- @Override
- public void onPageStarted(WebView view, String url, Bitmap favicon) {
- resetLockIcon(url);
- setUrlTitle(url, null);
-
- // We've started to load a new page. If there was a pending message
- // to save a screenshot then we will now take the new page and
- // save an incorrect screenshot. Therefore, remove any pending
- // thumbnail messages from the queue.
- mHandler.removeMessages(UPDATE_BOOKMARK_THUMBNAIL);
-
- // If we start a touch icon load and then load a new page, we don't
- // want to cancel the current touch icon loader. But, we do want to
- // create a new one when the touch icon url is known.
- if (mTouchIconLoader != null) {
- mTouchIconLoader.mActivity = null;
- mTouchIconLoader = null;
- }
-
- ErrorConsoleView errorConsole = mTabControl.getCurrentErrorConsole(false);
- if (errorConsole != null) {
- errorConsole.clearErrorMessages();
- if (mShouldShowErrorConsole) {
- errorConsole.showConsole(ErrorConsoleView.SHOW_NONE);
- }
- }
-
- // Call updateIcon instead of setFavicon so the bookmark
- // database can be updated.
- updateIcon(url, favicon);
-
- if (mSettings.isTracing()) {
- String host;
- try {
- WebAddress uri = new WebAddress(url);
- host = uri.mHost;
- } catch (android.net.ParseException ex) {
- host = "browser";
- }
- host = host.replace('.', '_');
- host += ".trace";
- mInTrace = true;
- Debug.startMethodTracing(host, 20 * 1024 * 1024);
- }
-
- // Performance probe
- if (false) {
- mStart = SystemClock.uptimeMillis();
- mProcessStart = Process.getElapsedCpuTime();
- long[] sysCpu = new long[7];
- if (Process.readProcFile("/proc/stat", SYSTEM_CPU_FORMAT, null,
- sysCpu, null)) {
- mUserStart = sysCpu[0] + sysCpu[1];
- mSystemStart = sysCpu[2];
- mIdleStart = sysCpu[3];
- mIrqStart = sysCpu[4] + sysCpu[5] + sysCpu[6];
- }
- mUiStart = SystemClock.currentThreadTimeMillis();
- }
-
- if (!mPageStarted) {
- mPageStarted = true;
- // if onResume() has been called, resumeWebViewTimers() does
- // nothing.
- resumeWebViewTimers();
- }
-
- // reset sync timer to avoid sync starts during loading a page
- CookieSyncManager.getInstance().resetSync();
-
- mInLoad = true;
- mDidStopLoad = false;
- showFakeTitleBar();
- updateInLoadMenuItems();
- if (!mIsNetworkUp) {
- createAndShowNetworkDialog();
- if (view != null) {
- view.setNetworkAvailable(false);
- }
- }
- }
-
- @Override
- public void onPageFinished(WebView view, String url) {
- // Reset the title and icon in case we stopped a provisional
- // load.
- resetTitleAndIcon(view);
-
- if (!mDidStopLoad) {
- // Only update the bookmark screenshot if the user did not
- // cancel the load early.
- Message updateScreenshot = Message.obtain(mHandler, UPDATE_BOOKMARK_THUMBNAIL, view);
- mHandler.sendMessageDelayed(updateScreenshot, 500);
- }
-
- // Update the lock icon image only once we are done loading
- updateLockIconToLatest();
-
- // Performance probe
- if (false) {
- long[] sysCpu = new long[7];
- if (Process.readProcFile("/proc/stat", SYSTEM_CPU_FORMAT, null,
- sysCpu, null)) {
- String uiInfo = "UI thread used "
- + (SystemClock.currentThreadTimeMillis() - mUiStart)
- + " ms";
- if (LOGD_ENABLED) {
- Log.d(LOGTAG, uiInfo);
- }
- //The string that gets written to the log
- String performanceString = "It took total "
- + (SystemClock.uptimeMillis() - mStart)
- + " ms clock time to load the page."
- + "\nbrowser process used "
- + (Process.getElapsedCpuTime() - mProcessStart)
- + " ms, user processes used "
- + (sysCpu[0] + sysCpu[1] - mUserStart) * 10
- + " ms, kernel used "
- + (sysCpu[2] - mSystemStart) * 10
- + " ms, idle took " + (sysCpu[3] - mIdleStart) * 10
- + " ms and irq took "
- + (sysCpu[4] + sysCpu[5] + sysCpu[6] - mIrqStart)
- * 10 + " ms, " + uiInfo;
- if (LOGD_ENABLED) {
- Log.d(LOGTAG, performanceString + "\nWebpage: " + url);
- }
- if (url != null) {
- // strip the url to maintain consistency
- String newUrl = new String(url);
- if (newUrl.startsWith("http://www.")) {
- newUrl = newUrl.substring(11);
- } else if (newUrl.startsWith("http://")) {
- newUrl = newUrl.substring(7);
- } else if (newUrl.startsWith("https://www.")) {
- newUrl = newUrl.substring(12);
- } else if (newUrl.startsWith("https://")) {
- newUrl = newUrl.substring(8);
- }
- if (LOGD_ENABLED) {
- Log.d(LOGTAG, newUrl + " loaded");
- }
- /*
- if (sWhiteList.contains(newUrl)) {
- // The string that gets pushed to the statistcs
- // service
- performanceString = performanceString
- + "\nWebpage: "
- + newUrl
- + "\nCarrier: "
- + android.os.SystemProperties
- .get("gsm.sim.operator.alpha");
- if (mWebView != null
- && mWebView.getContext() != null
- && mWebView.getContext().getSystemService(
- Context.CONNECTIVITY_SERVICE) != null) {
- ConnectivityManager cManager =
- (ConnectivityManager) mWebView
- .getContext().getSystemService(
- Context.CONNECTIVITY_SERVICE);
- NetworkInfo nInfo = cManager
- .getActiveNetworkInfo();
- if (nInfo != null) {
- performanceString = performanceString
- + "\nNetwork Type: "
- + nInfo.getType().toString();
- }
- }
- Checkin.logEvent(mResolver,
- Checkin.Events.Tag.WEBPAGE_LOAD,
- performanceString);
- Log.w(LOGTAG, "pushed to the statistics service");
- }
- */
- }
- }
- }
-
- if (mInTrace) {
- mInTrace = false;
- Debug.stopMethodTracing();
- }
-
- if (mPageStarted) {
- mPageStarted = false;
- // pauseWebViewTimers() will do nothing and return false if
- // onPause() is not called yet.
- if (pauseWebViewTimers()) {
- if (mWakeLock.isHeld()) {
- mHandler.removeMessages(RELEASE_WAKELOCK);
- mWakeLock.release();
- }
- }
- }
- }
-
- // return true if want to hijack the url to let another app to handle it
- @Override
- public boolean shouldOverrideUrlLoading(WebView view, String url) {
- if (url.startsWith(SCHEME_WTAI)) {
- // wtai://wp/mc;number
- // number=string(phone-number)
- if (url.startsWith(SCHEME_WTAI_MC)) {
- Intent intent = new Intent(Intent.ACTION_VIEW,
- Uri.parse(WebView.SCHEME_TEL +
- url.substring(SCHEME_WTAI_MC.length())));
- startActivity(intent);
- return true;
- }
- // wtai://wp/sd;dtmf
- // dtmf=string(dialstring)
- if (url.startsWith(SCHEME_WTAI_SD)) {
- // TODO
- // only send when there is active voice connection
- return false;
- }
- // wtai://wp/ap;number;name
- // number=string(phone-number)
- // name=string
- if (url.startsWith(SCHEME_WTAI_AP)) {
- // TODO
- return false;
- }
- }
-
- // The "about:" schemes are internal to the browser; don't
- // want these to be dispatched to other apps.
- if (url.startsWith("about:")) {
- return false;
- }
-
- Intent intent;
-
- // perform generic parsing of the URI to turn it into an Intent.
+ if (mSettings.isTracing()) {
+ String host;
try {
- intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
- } catch (URISyntaxException ex) {
- Log.w("Browser", "Bad URI " + url + ": " + ex.getMessage());
- return false;
+ WebAddress uri = new WebAddress(url);
+ host = uri.mHost;
+ } catch (android.net.ParseException ex) {
+ host = "browser";
}
+ host = host.replace('.', '_');
+ host += ".trace";
+ mInTrace = true;
+ Debug.startMethodTracing(host, 20 * 1024 * 1024);
+ }
- // check whether the intent can be resolved. If not, we will see
- // whether we can download it from the Market.
- if (getPackageManager().resolveActivity(intent, 0) == null) {
- String packagename = intent.getPackage();
- if (packagename != null) {
- intent = new Intent(Intent.ACTION_VIEW, Uri
- .parse("market://search?q=pname:" + packagename));
- intent.addCategory(Intent.CATEGORY_BROWSABLE);
- startActivity(intent);
- return true;
- } else {
- return false;
+ // Performance probe
+ if (false) {
+ mStart = SystemClock.uptimeMillis();
+ mProcessStart = Process.getElapsedCpuTime();
+ long[] sysCpu = new long[7];
+ if (Process.readProcFile("/proc/stat", SYSTEM_CPU_FORMAT, null,
+ sysCpu, null)) {
+ mUserStart = sysCpu[0] + sysCpu[1];
+ mSystemStart = sysCpu[2];
+ mIdleStart = sysCpu[3];
+ mIrqStart = sysCpu[4] + sysCpu[5] + sysCpu[6];
+ }
+ mUiStart = SystemClock.currentThreadTimeMillis();
+ }
+ }
+
+ void onPageFinished(WebView view, String url) {
+ // Reset the title and icon in case we stopped a provisional load.
+ resetTitleAndIcon(view);
+ // Update the lock icon image only once we are done loading
+ updateLockIconToLatest();
+ // pause the WebView timer and release the wake lock if it is finished
+ // while BrowserActivity is in pause state.
+ if (mActivityInPause && pauseWebViewTimers()) {
+ if (mWakeLock.isHeld()) {
+ mHandler.removeMessages(RELEASE_WAKELOCK);
+ mWakeLock.release();
+ }
+ }
+
+ // Performance probe
+ if (false) {
+ long[] sysCpu = new long[7];
+ if (Process.readProcFile("/proc/stat", SYSTEM_CPU_FORMAT, null,
+ sysCpu, null)) {
+ String uiInfo = "UI thread used "
+ + (SystemClock.currentThreadTimeMillis() - mUiStart)
+ + " ms";
+ if (LOGD_ENABLED) {
+ Log.d(LOGTAG, uiInfo);
+ }
+ //The string that gets written to the log
+ String performanceString = "It took total "
+ + (SystemClock.uptimeMillis() - mStart)
+ + " ms clock time to load the page."
+ + "\nbrowser process used "
+ + (Process.getElapsedCpuTime() - mProcessStart)
+ + " ms, user processes used "
+ + (sysCpu[0] + sysCpu[1] - mUserStart) * 10
+ + " ms, kernel used "
+ + (sysCpu[2] - mSystemStart) * 10
+ + " ms, idle took " + (sysCpu[3] - mIdleStart) * 10
+ + " ms and irq took "
+ + (sysCpu[4] + sysCpu[5] + sysCpu[6] - mIrqStart)
+ * 10 + " ms, " + uiInfo;
+ if (LOGD_ENABLED) {
+ Log.d(LOGTAG, performanceString + "\nWebpage: " + url);
+ }
+ if (url != null) {
+ // strip the url to maintain consistency
+ String newUrl = new String(url);
+ if (newUrl.startsWith("http://www.")) {
+ newUrl = newUrl.substring(11);
+ } else if (newUrl.startsWith("http://")) {
+ newUrl = newUrl.substring(7);
+ } else if (newUrl.startsWith("https://www.")) {
+ newUrl = newUrl.substring(12);
+ } else if (newUrl.startsWith("https://")) {
+ newUrl = newUrl.substring(8);
+ }
+ if (LOGD_ENABLED) {
+ Log.d(LOGTAG, newUrl + " loaded");
+ }
}
}
+ }
- // sanitize the Intent, ensuring web pages can not bypass browser
- // security (only access to BROWSABLE activities).
- intent.addCategory(Intent.CATEGORY_BROWSABLE);
- intent.setComponent(null);
- try {
- if (startActivityIfNeeded(intent, -1)) {
- return true;
- }
- } catch (ActivityNotFoundException ex) {
- // ignore the error. If no application can handle the URL,
- // eg about:blank, assume the browser can handle it.
- }
+ if (mInTrace) {
+ mInTrace = false;
+ Debug.stopMethodTracing();
+ }
+ }
- if (mMenuIsDown) {
- openTab(url);
- closeOptionsMenu();
+ boolean shouldOverrideUrlLoading(WebView view, String url) {
+ if (url.startsWith(SCHEME_WTAI)) {
+ // wtai://wp/mc;number
+ // number=string(phone-number)
+ if (url.startsWith(SCHEME_WTAI_MC)) {
+ Intent intent = new Intent(Intent.ACTION_VIEW,
+ Uri.parse(WebView.SCHEME_TEL +
+ url.substring(SCHEME_WTAI_MC.length())));
+ startActivity(intent);
return true;
}
+ // wtai://wp/sd;dtmf
+ // dtmf=string(dialstring)
+ if (url.startsWith(SCHEME_WTAI_SD)) {
+ // TODO: only send when there is active voice connection
+ return false;
+ }
+ // wtai://wp/ap;number;name
+ // number=string(phone-number)
+ // name=string
+ if (url.startsWith(SCHEME_WTAI_AP)) {
+ // TODO
+ return false;
+ }
+ }
+ // The "about:" schemes are internal to the browser; don't want these to
+ // be dispatched to other apps.
+ if (url.startsWith("about:")) {
return false;
}
- /**
- * Updates the lock icon. This method is called when we discover another
- * resource to be loaded for this page (for example, javascript). While
- * we update the icon type, we do not update the lock icon itself until
- * we are done loading, it is slightly more secure this way.
- */
- @Override
- public void onLoadResource(WebView view, String url) {
- if (url != null && url.length() > 0) {
- // It is only if the page claims to be secure
- // that we may have to update the lock:
- if (mLockIconType == LOCK_ICON_SECURE) {
- // If NOT a 'safe' url, change the lock to mixed content!
- if (!(URLUtil.isHttpsUrl(url) || URLUtil.isDataUrl(url) || URLUtil.isAboutUrl(url))) {
- mLockIconType = LOCK_ICON_MIXED;
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "BrowserActivity.updateLockIcon:" +
- " updated lock icon to " + mLockIconType + " due to " + url);
- }
- }
- }
- }
+ Intent intent;
+ // perform generic parsing of the URI to turn it into an Intent.
+ try {
+ intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
+ } catch (URISyntaxException ex) {
+ Log.w("Browser", "Bad URI " + url + ": " + ex.getMessage());
+ return false;
}
- /**
- * Show the dialog, asking the user if they would like to continue after
- * an excessive number of HTTP redirects.
- */
- @Override
- public void onTooManyRedirects(WebView view, final Message cancelMsg,
- final Message continueMsg) {
- new AlertDialog.Builder(BrowserActivity.this)
- .setTitle(R.string.browserFrameRedirect)
- .setMessage(R.string.browserFrame307Post)
- .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- continueMsg.sendToTarget();
- }})
- .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- cancelMsg.sendToTarget();
- }})
- .setOnCancelListener(new OnCancelListener() {
- public void onCancel(DialogInterface dialog) {
- cancelMsg.sendToTarget();
- }})
- .show();
- }
-
- // Container class for the next error dialog that needs to be
- // displayed.
- class ErrorDialog {
- public final int mTitle;
- public final String mDescription;
- public final int mError;
- ErrorDialog(int title, String desc, int error) {
- mTitle = title;
- mDescription = desc;
- mError = error;
- }
- };
-
- private void processNextError() {
- if (mQueuedErrors == null) {
- return;
- }
- // The first one is currently displayed so just remove it.
- mQueuedErrors.removeFirst();
- if (mQueuedErrors.size() == 0) {
- mQueuedErrors = null;
- return;
- }
- showError(mQueuedErrors.getFirst());
- }
-
- private DialogInterface.OnDismissListener mDialogListener =
- new DialogInterface.OnDismissListener() {
- public void onDismiss(DialogInterface d) {
- processNextError();
- }
- };
- private LinkedList<ErrorDialog> mQueuedErrors;
-
- private void queueError(int err, String desc) {
- if (mQueuedErrors == null) {
- mQueuedErrors = new LinkedList<ErrorDialog>();
- }
- for (ErrorDialog d : mQueuedErrors) {
- if (d.mError == err) {
- // Already saw a similar error, ignore the new one.
- return;
- }
- }
- ErrorDialog errDialog = new ErrorDialog(
- err == WebViewClient.ERROR_FILE_NOT_FOUND ?
- R.string.browserFrameFileErrorLabel :
- R.string.browserFrameNetworkErrorLabel,
- desc, err);
- mQueuedErrors.addLast(errDialog);
-
- // Show the dialog now if the queue was empty.
- if (mQueuedErrors.size() == 1) {
- showError(errDialog);
- }
- }
-
- private void showError(ErrorDialog errDialog) {
- AlertDialog d = new AlertDialog.Builder(BrowserActivity.this)
- .setTitle(errDialog.mTitle)
- .setMessage(errDialog.mDescription)
- .setPositiveButton(R.string.ok, null)
- .create();
- d.setOnDismissListener(mDialogListener);
- d.show();
- }
-
- /**
- * Show a dialog informing the user of the network error reported by
- * WebCore.
- */
- @Override
- public void onReceivedError(WebView view, int errorCode,
- String description, String failingUrl) {
- if (errorCode != WebViewClient.ERROR_HOST_LOOKUP &&
- errorCode != WebViewClient.ERROR_CONNECT &&
- errorCode != WebViewClient.ERROR_BAD_URL &&
- errorCode != WebViewClient.ERROR_UNSUPPORTED_SCHEME &&
- errorCode != WebViewClient.ERROR_FILE) {
- queueError(errorCode, description);
- }
- Log.e(LOGTAG, "onReceivedError " + errorCode + " " + failingUrl
- + " " + description);
-
- // We need to reset the title after an error.
- resetTitleAndRevertLockIcon();
- }
-
- /**
- * Check with the user if it is ok to resend POST data as the page they
- * are trying to navigate to is the result of a POST.
- */
- @Override
- public void onFormResubmission(WebView view, final Message dontResend,
- final Message resend) {
- new AlertDialog.Builder(BrowserActivity.this)
- .setTitle(R.string.browserFrameFormResubmitLabel)
- .setMessage(R.string.browserFrameFormResubmitMessage)
- .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- resend.sendToTarget();
- }})
- .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- dontResend.sendToTarget();
- }})
- .setOnCancelListener(new OnCancelListener() {
- public void onCancel(DialogInterface dialog) {
- dontResend.sendToTarget();
- }})
- .show();
- }
-
- /**
- * Insert the url into the visited history database.
- * @param url The url to be inserted.
- * @param isReload True if this url is being reloaded.
- * FIXME: Not sure what to do when reloading the page.
- */
- @Override
- public void doUpdateVisitedHistory(WebView view, String url,
- boolean isReload) {
- if (url.regionMatches(true, 0, "about:", 0, 6)) {
- return;
- }
- // remove "client" before updating it to the history so that it wont
- // show up in the auto-complete list.
- int index = url.indexOf("client=ms-");
- if (index > 0 && url.contains(".google.")) {
- int end = url.indexOf('&', index);
- if (end > 0) {
- url = url.substring(0, index)
- .concat(url.substring(end + 1));
- } else {
- // the url.charAt(index-1) should be either '?' or '&'
- url = url.substring(0, index-1);
- }
- }
- Browser.updateVisitedHistory(mResolver, url, true);
- WebIconDatabase.getInstance().retainIconForPageUrl(url);
- }
-
- /**
- * Displays SSL error(s) dialog to the user.
- */
- @Override
- public void onReceivedSslError(
- final WebView view, final SslErrorHandler handler, final SslError error) {
-
- if (mSettings.showSecurityWarnings()) {
- final LayoutInflater factory =
- LayoutInflater.from(BrowserActivity.this);
- final View warningsView =
- factory.inflate(R.layout.ssl_warnings, null);
- final LinearLayout placeholder =
- (LinearLayout)warningsView.findViewById(R.id.placeholder);
-
- if (error.hasError(SslError.SSL_UNTRUSTED)) {
- LinearLayout ll = (LinearLayout)factory
- .inflate(R.layout.ssl_warning, null);
- ((TextView)ll.findViewById(R.id.warning))
- .setText(R.string.ssl_untrusted);
- placeholder.addView(ll);
- }
-
- if (error.hasError(SslError.SSL_IDMISMATCH)) {
- LinearLayout ll = (LinearLayout)factory
- .inflate(R.layout.ssl_warning, null);
- ((TextView)ll.findViewById(R.id.warning))
- .setText(R.string.ssl_mismatch);
- placeholder.addView(ll);
- }
-
- if (error.hasError(SslError.SSL_EXPIRED)) {
- LinearLayout ll = (LinearLayout)factory
- .inflate(R.layout.ssl_warning, null);
- ((TextView)ll.findViewById(R.id.warning))
- .setText(R.string.ssl_expired);
- placeholder.addView(ll);
- }
-
- if (error.hasError(SslError.SSL_NOTYETVALID)) {
- LinearLayout ll = (LinearLayout)factory
- .inflate(R.layout.ssl_warning, null);
- ((TextView)ll.findViewById(R.id.warning))
- .setText(R.string.ssl_not_yet_valid);
- placeholder.addView(ll);
- }
-
- new AlertDialog.Builder(BrowserActivity.this)
- .setTitle(R.string.security_warning)
- .setIcon(android.R.drawable.ic_dialog_alert)
- .setView(warningsView)
- .setPositiveButton(R.string.ssl_continue,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
- handler.proceed();
- }
- })
- .setNeutralButton(R.string.view_certificate,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
- showSSLCertificateOnError(view, handler, error);
- }
- })
- .setNegativeButton(R.string.cancel,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
- handler.cancel();
- BrowserActivity.this.resetTitleAndRevertLockIcon();
- }
- })
- .setOnCancelListener(
- new DialogInterface.OnCancelListener() {
- public void onCancel(DialogInterface dialog) {
- handler.cancel();
- BrowserActivity.this.resetTitleAndRevertLockIcon();
- }
- })
- .show();
- } else {
- handler.proceed();
- }
- }
-
- /**
- * Handles an HTTP authentication request.
- *
- * @param handler The authentication handler
- * @param host The host
- * @param realm The realm
- */
- @Override
- public void onReceivedHttpAuthRequest(WebView view,
- final HttpAuthHandler handler, final String host, final String realm) {
- String username = null;
- String password = null;
-
- boolean reuseHttpAuthUsernamePassword =
- handler.useHttpAuthUsernamePassword();
-
- if (reuseHttpAuthUsernamePassword &&
- (mTabControl.getCurrentWebView() != null)) {
- String[] credentials =
- mTabControl.getCurrentWebView()
- .getHttpAuthUsernamePassword(host, realm);
- if (credentials != null && credentials.length == 2) {
- username = credentials[0];
- password = credentials[1];
- }
- }
-
- if (username != null && password != null) {
- handler.proceed(username, password);
- } else {
- showHttpAuthentication(handler, host, realm, null, null, null, 0);
- }
- }
-
- @Override
- public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) {
- if (mMenuIsDown) {
- // only check shortcut key when MENU is held
- return getWindow().isShortcutKey(event.getKeyCode(), event);
+ // check whether the intent can be resolved. If not, we will see
+ // whether we can download it from the Market.
+ if (getPackageManager().resolveActivity(intent, 0) == null) {
+ String packagename = intent.getPackage();
+ if (packagename != null) {
+ intent = new Intent(Intent.ACTION_VIEW, Uri
+ .parse("market://search?q=pname:" + packagename));
+ intent.addCategory(Intent.CATEGORY_BROWSABLE);
+ startActivity(intent);
+ return true;
} else {
return false;
}
}
- @Override
- public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
- if (view != mTabControl.getCurrentTopWebView()) {
- return;
- }
- if (event.isDown()) {
- BrowserActivity.this.onKeyDown(event.getKeyCode(), event);
- } else {
- BrowserActivity.this.onKeyUp(event.getKeyCode(), event);
- }
- }
- };
-
- //--------------------------------------------------------------------------
- // WebChromeClient implementation
- //--------------------------------------------------------------------------
-
- /* package */ WebChromeClient getWebChromeClient() {
- return mWebChromeClient;
- }
-
- private final WebChromeClient mWebChromeClient = new WebChromeClient() {
- // Helper method to create a new tab or sub window.
- private void createWindow(final boolean dialog, final Message msg) {
- if (dialog) {
- mTabControl.createSubWindow();
- final TabControl.Tab t = mTabControl.getCurrentTab();
- attachSubWindow(t);
- WebView.WebViewTransport transport =
- (WebView.WebViewTransport) msg.obj;
- transport.setWebView(t.getSubWebView());
- msg.sendToTarget();
- } else {
- final TabControl.Tab parent = mTabControl.getCurrentTab();
- final TabControl.Tab newTab
- = openTabAndShow(EMPTY_URL_DATA, false, null);
- if (newTab != parent) {
- parent.addChildTab(newTab);
- }
- WebView.WebViewTransport transport =
- (WebView.WebViewTransport) msg.obj;
- transport.setWebView(mTabControl.getCurrentWebView());
- msg.sendToTarget();
- }
- }
-
- @Override
- public boolean onCreateWindow(WebView view, final boolean dialog,
- final boolean userGesture, final Message resultMsg) {
- // Short-circuit if we can't create any more tabs or sub windows.
- if (dialog && mTabControl.getCurrentSubWindow() != null) {
- new AlertDialog.Builder(BrowserActivity.this)
- .setTitle(R.string.too_many_subwindows_dialog_title)
- .setIcon(android.R.drawable.ic_dialog_alert)
- .setMessage(R.string.too_many_subwindows_dialog_message)
- .setPositiveButton(R.string.ok, null)
- .show();
- return false;
- } else if (mTabControl.getTabCount() >= TabControl.MAX_TABS) {
- new AlertDialog.Builder(BrowserActivity.this)
- .setTitle(R.string.too_many_windows_dialog_title)
- .setIcon(android.R.drawable.ic_dialog_alert)
- .setMessage(R.string.too_many_windows_dialog_message)
- .setPositiveButton(R.string.ok, null)
- .show();
- return false;
- }
-
- // Short-circuit if this was a user gesture.
- if (userGesture) {
- createWindow(dialog, resultMsg);
+ // sanitize the Intent, ensuring web pages can not bypass browser
+ // security (only access to BROWSABLE activities).
+ intent.addCategory(Intent.CATEGORY_BROWSABLE);
+ intent.setComponent(null);
+ try {
+ if (startActivityIfNeeded(intent, -1)) {
return true;
}
+ } catch (ActivityNotFoundException ex) {
+ // ignore the error. If no application can handle the URL,
+ // eg about:blank, assume the browser can handle it.
+ }
- // Allow the popup and create the appropriate window.
- final AlertDialog.OnClickListener allowListener =
- new AlertDialog.OnClickListener() {
- public void onClick(DialogInterface d,
- int which) {
- createWindow(dialog, resultMsg);
- }
- };
-
- // Block the popup by returning a null WebView.
- final AlertDialog.OnClickListener blockListener =
- new AlertDialog.OnClickListener() {
- public void onClick(DialogInterface d, int which) {
- resultMsg.sendToTarget();
- }
- };
-
- // Build a confirmation dialog to display to the user.
- final AlertDialog d =
- new AlertDialog.Builder(BrowserActivity.this)
- .setTitle(R.string.attention)
- .setIcon(android.R.drawable.ic_dialog_alert)
- .setMessage(R.string.popup_window_attempt)
- .setPositiveButton(R.string.allow, allowListener)
- .setNegativeButton(R.string.block, blockListener)
- .setCancelable(false)
- .create();
-
- // Show the confirmation dialog.
- d.show();
+ if (mMenuIsDown) {
+ openTab(url);
+ closeOptionsMenu();
return true;
}
+ return false;
+ }
- @Override
- public void onCloseWindow(WebView window) {
- final TabControl.Tab current = mTabControl.getCurrentTab();
- final TabControl.Tab parent = current.getParentTab();
- if (parent != null) {
- // JavaScript can only close popup window.
- switchToTab(mTabControl.getTabIndex(parent));
- // Now we need to close the window
- closeTab(current);
- }
- }
+ // -------------------------------------------------------------------------
+ // Helper function for WebChromeClient
+ // -------------------------------------------------------------------------
- @Override
- public void onProgressChanged(WebView view, int newProgress) {
- mTitleBar.setProgress(newProgress);
- if (mFakeTitleBar != null) {
- mFakeTitleBar.setProgress(newProgress);
- }
+ void onProgressChanged(WebView view, int newProgress) {
+ mTitleBar.setProgress(newProgress);
+ mFakeTitleBar.setProgress(newProgress);
- if (newProgress == 100) {
- // onProgressChanged() may continue to be called after the main
- // frame has finished loading, as any remaining sub frames
- // continue to load. We'll only get called once though with
- // newProgress as 100 when everything is loaded.
- // (onPageFinished is called once when the main frame completes
- // loading regardless of the state of any sub frames so calls
- // to onProgressChanges may continue after onPageFinished has
- // executed)
-
- // sync cookies and cache promptly here.
- CookieSyncManager.getInstance().sync();
- if (mInLoad) {
- mInLoad = false;
- updateInLoadMenuItems();
- // If the options menu is open, leave the title bar
- if (!mOptionsMenuOpen || !mIconView) {
- hideFakeTitleBar();
- }
- }
- } else if (!mInLoad) {
- // onPageFinished may have already been called but a subframe
- // is still loading and updating the progress. Reset mInLoad
- // and update the menu items.
- mInLoad = true;
+ if (newProgress == 100) {
+ // onProgressChanged() may continue to be called after the main
+ // frame has finished loading, as any remaining sub frames continue
+ // to load. We'll only get called once though with newProgress as
+ // 100 when everything is loaded. (onPageFinished is called once
+ // when the main frame completes loading regardless of the state of
+ // any sub frames so calls to onProgressChanges may continue after
+ // onPageFinished has executed)
+ if (mInLoad) {
+ mInLoad = false;
updateInLoadMenuItems();
- if (!mOptionsMenuOpen || mIconView) {
- // This page has begun to load, so show the title bar
- showFakeTitleBar();
+ // If the options menu is open, leave the title bar
+ if (!mOptionsMenuOpen || !mIconView) {
+ hideFakeTitleBar();
}
}
- }
-
- @Override
- public void onReceivedTitle(WebView view, String title) {
- String url = view.getUrl();
-
- // here, if url is null, we want to reset the title
- setUrlTitle(url, title);
-
- if (url == null ||
- url.length() >= SQLiteDatabase.SQLITE_MAX_LIKE_PATTERN_LENGTH) {
- return;
- }
- // See if we can find the current url in our history database and
- // add the new title to it.
- if (url.startsWith("http://www.")) {
- url = url.substring(11);
- } else if (url.startsWith("http://")) {
- url = url.substring(4);
- }
- try {
- url = "%" + url;
- String [] selArgs = new String[] { url };
-
- String where = Browser.BookmarkColumns.URL + " LIKE ? AND "
- + Browser.BookmarkColumns.BOOKMARK + " = 0";
- Cursor c = mResolver.query(Browser.BOOKMARKS_URI,
- Browser.HISTORY_PROJECTION, where, selArgs, null);
- if (c.moveToFirst()) {
- // Current implementation of database only has one entry per
- // url.
- ContentValues map = new ContentValues();
- map.put(Browser.BookmarkColumns.TITLE, title);
- mResolver.update(Browser.BOOKMARKS_URI, map,
- "_id = " + c.getInt(0), null);
- }
- c.close();
- } catch (IllegalStateException e) {
- Log.e(LOGTAG, "BrowserActivity onReceived title", e);
- } catch (SQLiteException ex) {
- Log.e(LOGTAG, "onReceivedTitle() caught SQLiteException: ", ex);
+ } else if (!mInLoad) {
+ // onPageFinished may have already been called but a subframe is
+ // still loading and updating the progress. Reset mInLoad and update
+ // the menu items.
+ mInLoad = true;
+ updateInLoadMenuItems();
+ if (!mOptionsMenuOpen || mIconView) {
+ // This page has begun to load, so show the title bar
+ showFakeTitleBar();
}
}
+ }
- @Override
- public void onReceivedIcon(WebView view, Bitmap icon) {
- updateIcon(view, icon);
+ void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) {
+ if (mCustomView != null)
+ return;
+
+ // Add the custom view to its container.
+ mCustomViewContainer.addView(view, COVER_SCREEN_GRAVITY_CENTER);
+ mCustomView = view;
+ mCustomViewCallback = callback;
+ // Save the menu state and set it to empty while the custom
+ // view is showing.
+ mOldMenuState = mMenuState;
+ mMenuState = EMPTY_MENU;
+ // Hide the content view.
+ mContentView.setVisibility(View.GONE);
+ // Finally show the custom view container.
+ setStatusBarVisibility(false);
+ mCustomViewContainer.setVisibility(View.VISIBLE);
+ mCustomViewContainer.bringToFront();
+ }
+
+ void onHideCustomView() {
+ if (mCustomView == null)
+ return;
+
+ // Hide the custom view.
+ mCustomView.setVisibility(View.GONE);
+ // Remove the custom view from its container.
+ mCustomViewContainer.removeView(mCustomView);
+ mCustomView = null;
+ // Reset the old menu state.
+ mMenuState = mOldMenuState;
+ mOldMenuState = EMPTY_MENU;
+ mCustomViewContainer.setVisibility(View.GONE);
+ mCustomViewCallback.onCustomViewHidden();
+ // Show the content view.
+ setStatusBarVisibility(true);
+ mContentView.setVisibility(View.VISIBLE);
+ }
+
+ Bitmap getDefaultVideoPoster() {
+ if (mDefaultVideoPoster == null) {
+ mDefaultVideoPoster = BitmapFactory.decodeResource(
+ getResources(), R.drawable.default_video_poster);
}
+ return mDefaultVideoPoster;
+ }
- @Override
- public void onReceivedTouchIconUrl(WebView view, String url,
- boolean precomposed) {
- final ContentResolver cr = getContentResolver();
- final Cursor c =
- BrowserBookmarksAdapter.queryBookmarksForUrl(cr,
- view.getOriginalUrl(), view.getUrl(), true);
- if (c != null) {
- if (c.getCount() > 0) {
- // Let precomposed icons take precedence over non-composed
- // icons.
- if (precomposed && mTouchIconLoader != null) {
- mTouchIconLoader.cancel(false);
- mTouchIconLoader = null;
- }
- // Have only one async task at a time.
- if (mTouchIconLoader == null) {
- mTouchIconLoader = new DownloadTouchIcon(
- BrowserActivity.this, cr, c, view);
- mTouchIconLoader.execute(url);
- }
- } else {
- c.close();
- }
- }
+ View getVideoLoadingProgressView() {
+ if (mVideoProgressView == null) {
+ LayoutInflater inflater = LayoutInflater.from(BrowserActivity.this);
+ mVideoProgressView = inflater.inflate(
+ R.layout.video_loading_progress, null);
}
+ return mVideoProgressView;
+ }
- @Override
- public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) {
- if (mCustomView != null)
- return;
+ /*
+ * The Object used to inform the WebView of the file to upload.
+ */
+ private ValueCallback<Uri> mUploadMessage;
- // Add the custom view to its container.
- mCustomViewContainer.addView(view, COVER_SCREEN_GRAVITY_CENTER);
- mCustomView = view;
- mCustomViewCallback = callback;
- // Save the menu state and set it to empty while the custom
- // view is showing.
- mOldMenuState = mMenuState;
- mMenuState = EMPTY_MENU;
- // Hide the content view.
- mContentView.setVisibility(View.GONE);
- // Finally show the custom view container.
- mCustomViewContainer.setVisibility(View.VISIBLE);
- mCustomViewContainer.bringToFront();
- }
+ void openFileChooser(ValueCallback<Uri> uploadMsg) {
+ if (mUploadMessage != null) return;
+ mUploadMessage = uploadMsg;
+ Intent i = new Intent(Intent.ACTION_GET_CONTENT);
+ i.addCategory(Intent.CATEGORY_OPENABLE);
+ i.setType("*/*");
+ BrowserActivity.this.startActivityForResult(Intent.createChooser(i,
+ getString(R.string.choose_upload)), FILE_SELECTED);
+ }
- @Override
- public void onHideCustomView() {
- if (mCustomView == null)
- return;
-
- // Hide the custom view.
- mCustomView.setVisibility(View.GONE);
- // Remove the custom view from its container.
- mCustomViewContainer.removeView(mCustomView);
- mCustomView = null;
- // Reset the old menu state.
- mMenuState = mOldMenuState;
- mOldMenuState = EMPTY_MENU;
- mCustomViewContainer.setVisibility(View.GONE);
- mCustomViewCallback.onCustomViewHidden();
- // Show the content view.
- mContentView.setVisibility(View.VISIBLE);
- }
-
- /**
- * The origin has exceeded its database quota.
- * @param url the URL that exceeded the quota
- * @param databaseIdentifier the identifier of the database on
- * which the transaction that caused the quota overflow was run
- * @param currentQuota the current quota for the origin.
- * @param estimatedSize the estimated size of the database.
- * @param totalUsedQuota is the sum of all origins' quota.
- * @param quotaUpdater The callback to run when a decision to allow or
- * deny quota has been made. Don't forget to call this!
- */
- @Override
- public void onExceededDatabaseQuota(String url,
- String databaseIdentifier, long currentQuota, long estimatedSize,
- long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) {
- mSettings.getWebStorageSizeManager().onExceededDatabaseQuota(
- url, databaseIdentifier, currentQuota, estimatedSize,
- totalUsedQuota, quotaUpdater);
- }
-
- /**
- * The Application Cache has exceeded its max size.
- * @param spaceNeeded is the amount of disk space that would be needed
- * in order for the last appcache operation to succeed.
- * @param totalUsedQuota is the sum of all origins' quota.
- * @param quotaUpdater A callback to inform the WebCore thread that a new
- * app cache size is available. This callback must always be executed at
- * some point to ensure that the sleeping WebCore thread is woken up.
- */
- @Override
- public void onReachedMaxAppCacheSize(long spaceNeeded,
- long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) {
- mSettings.getWebStorageSizeManager().onReachedMaxAppCacheSize(
- spaceNeeded, totalUsedQuota, quotaUpdater);
- }
-
- /**
- * Instructs the browser to show a prompt to ask the user to set the
- * Geolocation permission state for the specified origin.
- * @param origin The origin for which Geolocation permissions are
- * requested.
- * @param callback The callback to call once the user has set the
- * Geolocation permission state.
- */
- @Override
- public void onGeolocationPermissionsShowPrompt(String origin,
- GeolocationPermissions.Callback callback) {
- mTabControl.getCurrentTab().getGeolocationPermissionsPrompt().show(
- origin, callback);
- }
-
- /**
- * Instructs the browser to hide the Geolocation permissions prompt.
- */
- @Override
- public void onGeolocationPermissionsHidePrompt() {
- mTabControl.getCurrentTab().getGeolocationPermissionsPrompt().hide();
- }
-
- /* Adds a JavaScript error message to the system log and if the JS
- * console is enabled in the about:debug options, to that console
- * also.
- * @param message The error message to report.
- * @param lineNumber The line number of the error.
- * @param sourceID The name of the source file that caused the error.
- */
- @Override
- public void onConsoleMessage(String message, int lineNumber, String sourceID) {
- ErrorConsoleView errorConsole = mTabControl.getCurrentErrorConsole(true);
- errorConsole.addErrorMessage(message, sourceID, lineNumber);
- if (mShouldShowErrorConsole &&
- errorConsole.getShowState() != ErrorConsoleView.SHOW_MAXIMIZED) {
- errorConsole.showConsole(ErrorConsoleView.SHOW_MINIMIZED);
- }
- Log.w(LOGTAG, "Console: " + message + " " + sourceID + ":" + lineNumber);
- }
-
- /**
- * Ask the browser for an icon to represent a <video> element.
- * This icon will be used if the Web page did not specify a poster attribute.
- *
- * @return Bitmap The icon or null if no such icon is available.
- * @hide pending API Council approval
- */
- @Override
- public Bitmap getDefaultVideoPoster() {
- if (mDefaultVideoPoster == null) {
- mDefaultVideoPoster = BitmapFactory.decodeResource(
- getResources(), R.drawable.default_video_poster);
- }
- return mDefaultVideoPoster;
- }
-
- /**
- * Ask the host application for a custom progress view to show while
- * a <video> is loading.
- *
- * @return View The progress view.
- * @hide pending API Council approval
- */
- @Override
- public View getVideoLoadingProgressView() {
- if (mVideoProgressView == null) {
- LayoutInflater inflater = LayoutInflater.from(BrowserActivity.this);
- mVideoProgressView = inflater.inflate(R.layout.video_loading_progress, null);
- }
- return mVideoProgressView;
- }
-
- /**
- * Deliver a list of already-visited URLs
- * @hide pending API Council approval
- */
- @Override
- public void getVisitedHistory(final ValueCallback<String[]> callback) {
- AsyncTask<Void, Void, String[]> task = new AsyncTask<Void, Void, String[]>() {
- public String[] doInBackground(Void... unused) {
- return Browser.getVisitedHistory(getContentResolver());
- }
-
- public void onPostExecute(String[] result) {
- callback.onReceiveValue(result);
-
- };
- };
- task.execute();
- };
- };
+ // -------------------------------------------------------------------------
+ // Implement functions for DownloadListener
+ // -------------------------------------------------------------------------
/**
* Notify the host application a download should be done, or that
@@ -3670,47 +2808,23 @@
}
+ // -------------------------------------------------------------------------
+
/**
* Resets the lock icon. This method is called when we start a new load and
* know the url to be loaded.
*/
private void resetLockIcon(String url) {
// Save the lock-icon state (we revert to it if the load gets cancelled)
- saveLockIcon();
-
- mLockIconType = LOCK_ICON_UNSECURE;
- if (URLUtil.isHttpsUrl(url)) {
- mLockIconType = LOCK_ICON_SECURE;
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "BrowserActivity.resetLockIcon:" +
- " reset lock icon to " + mLockIconType);
- }
- }
-
+ mTabControl.getCurrentTab().resetLockIcon(url);
updateLockIconImage(LOCK_ICON_UNSECURE);
}
- /* package */ void setLockIconType(int type) {
- mLockIconType = type;
- }
-
- /* package */ int getLockIconType() {
- return mLockIconType;
- }
-
- /* package */ void setPrevLockType(int type) {
- mPrevLockType = type;
- }
-
- /* package */ int getPrevLockType() {
- return mPrevLockType;
- }
-
/**
* Update the lock icon to correspond to our latest state.
*/
- /* package */ void updateLockIconToLatest() {
- updateLockIconImage(mLockIconType);
+ private void updateLockIconToLatest() {
+ updateLockIconImage(mTabControl.getCurrentTab().getLockIconType());
}
/**
@@ -3724,9 +2838,7 @@
d = mMixLockIcon;
}
mTitleBar.setLock(d);
- if (mFakeTitleBar != null) {
- mFakeTitleBar.setLock(d);
- }
+ mFakeTitleBar.setLock(d);
}
/**
@@ -3737,7 +2849,7 @@
* not. This is important, since we need to know whether to return to
* the parent dialog or simply dismiss.
*/
- private void showPageInfo(final TabControl.Tab tab,
+ private void showPageInfo(final Tab tab,
final boolean fromShowSSLCertificateOnError) {
final LayoutInflater factory = LayoutInflater
.from(this);
@@ -3855,7 +2967,7 @@
* (accessible from the Page-Info dialog).
* @param tab The tab to show certificate for.
*/
- private void showSSLCertificate(final TabControl.Tab tab) {
+ private void showSSLCertificate(final Tab tab) {
final View certificateView =
inflateCertificateView(tab.getWebView().getCertificate());
if (certificateView == null) {
@@ -3907,7 +3019,7 @@
* connection that resulted in an SSL error or proceeding per user request.
* @param error The SSL error object.
*/
- private void showSSLCertificateOnError(
+ void showSSLCertificateOnError(
final WebView view, final SslErrorHandler handler, final SslError error) {
final View certificateView =
@@ -3966,8 +3078,8 @@
mSSLCertificateOnErrorHandler = null;
mSSLCertificateOnErrorError = null;
- mWebViewClient.onReceivedSslError(
- view, handler, error);
+ view.getWebViewClient().onReceivedSslError(
+ view, handler, error);
}
})
.setNeutralButton(R.string.page_info_view,
@@ -3992,8 +3104,8 @@
mSSLCertificateOnErrorHandler = null;
mSSLCertificateOnErrorError = null;
- mWebViewClient.onReceivedSslError(
- view, handler, error);
+ view.getWebViewClient().onReceivedSslError(
+ view, handler, error);
}
})
.show();
@@ -4084,7 +3196,7 @@
/**
* Displays an http-authentication dialog.
*/
- private void showHttpAuthentication(final HttpAuthHandler handler,
+ void showHttpAuthentication(final HttpAuthHandler handler,
final String host, final String realm, final String title,
final String name, final String password, int focusId) {
LayoutInflater factory = LayoutInflater.from(this);
@@ -4205,6 +3317,10 @@
}
}
+ boolean isNetworkUp() {
+ return mIsNetworkUp;
+ }
+
// This method shows the network dialog alerting the user that the net is
// down. It will only show the dialog if mAlertDialog is null.
private void createAndShowNetworkDialog() {
@@ -4220,6 +3336,8 @@
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {
+ if (getTopWindow() == null) return;
+
switch (requestCode) {
case COMBO_PAGE:
if (resultCode == RESULT_OK && intent != null) {
@@ -4228,7 +3346,7 @@
if (extras != null && extras.getBoolean("new_window", false)) {
openTab(data);
} else {
- final TabControl.Tab currentTab =
+ final Tab currentTab =
mTabControl.getCurrentTab();
dismissSubWindow(currentTab);
if (data != null && data.length() != 0) {
@@ -4237,6 +3355,14 @@
}
}
break;
+ // Choose a file from the file picker.
+ case FILE_SELECTED:
+ if (null == mUploadMessage) break;
+ Uri result = intent == null || resultCode != RESULT_OK ? null
+ : intent.getData();
+ mUploadMessage.onReceiveValue(result);
+ mUploadMessage = null;
+ break;
default:
break;
}
@@ -4252,7 +3378,7 @@
Intent intent = new Intent(this,
BrowserDownloadPage.class);
intent.setData(downloadRecord);
- startActivityForResult(intent, this.DOWNLOAD_PAGE);
+ startActivityForResult(intent, BrowserActivity.DOWNLOAD_PAGE);
}
@@ -4289,8 +3415,7 @@
intent.putExtra("url", url);
intent.putExtra("thumbnail", thumbnail);
// Disable opening in a new window if we have maxed out the windows
- intent.putExtra("disable_new_window", mTabControl.getTabCount()
- >= TabControl.MAX_TABS);
+ intent.putExtra("disable_new_window", !mTabControl.canCreateNewTab());
intent.putExtra("touch_icon_url", current.getTouchIconUrl());
if (startWithHistory) {
intent.putExtra(CombinedBookmarkHistoryActivity.STARTING_TAB,
@@ -4304,7 +3429,7 @@
// In case the user enters nothing.
if (url != null && url.length() != 0 && view != null) {
url = smartUrlFilter(url);
- if (!mWebViewClient.shouldOverrideUrlLoading(view, url)) {
+ if (!view.getWebViewClient().shouldOverrideUrlLoading(view, url)) {
view.loadUrl(url);
}
}
@@ -4317,16 +3442,6 @@
return null;
}
-
- // get window count
-
- int getWindowCount(){
- if(mTabControl != null){
- return mTabControl.getTabCount();
- }
- return 0;
- }
-
protected static final Pattern ACCEPTED_URI_SCHEMA = Pattern.compile(
"(?i)" + // switch on case insensitive matching
"(" + // begin group for schema
@@ -4383,7 +3498,7 @@
}
}
} else {
- if (Regex.WEB_URL_PATTERN.matcher(inUrl).matches()) {
+ if (Patterns.WEB_URL.matcher(inUrl).matches()) {
return URLUtil.guessUrl(inUrl);
}
}
@@ -4400,7 +3515,8 @@
mShouldShowErrorConsole = flag;
- ErrorConsoleView errorConsole = mTabControl.getCurrentErrorConsole(true);
+ ErrorConsoleView errorConsole = mTabControl.getCurrentTab()
+ .getErrorConsole(true);
if (flag) {
// Setting the show state of the console will cause it's the layout to be inflated.
@@ -4420,13 +3536,19 @@
}
+ boolean shouldShowErrorConsole() {
+ return mShouldShowErrorConsole;
+ }
+
+ private void setStatusBarVisibility(boolean visible) {
+ int flag = visible ? 0 : WindowManager.LayoutParams.FLAG_FULLSCREEN;
+ getWindow().setFlags(flag, WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ }
+
final static int LOCK_ICON_UNSECURE = 0;
final static int LOCK_ICON_SECURE = 1;
final static int LOCK_ICON_MIXED = 2;
- private int mLockIconType = LOCK_ICON_UNSECURE;
- private int mPrevLockType = LOCK_ICON_UNSECURE;
-
private BrowserSettings mSettings;
private TabControl mTabControl;
private ContentResolver mResolver;
@@ -4452,7 +3574,6 @@
private boolean mIsNetworkUp;
private boolean mDidStopLoad;
- private boolean mPageStarted;
private boolean mActivityInPause = true;
private boolean mMenuIsDown;
@@ -4498,7 +3619,7 @@
// As PageInfo has different style for landscape / portrait, we have
// to re-open it when configuration changed
private AlertDialog mPageInfoDialog;
- private TabControl.Tab mPageInfoView;
+ private Tab mPageInfoView;
// If the Page-Info dialog is launched from the SSL-certificate-on-error
// dialog, we should not just dismiss it, but should get back to the
// SSL-certificate-on-error dialog. This flag is used to store this state
@@ -4514,7 +3635,7 @@
// as SSLCertificate has different style for landscape / portrait, we
// have to re-open it when configuration changed
private AlertDialog mSSLCertificateDialog;
- private TabControl.Tab mSSLCertificateView;
+ private Tab mSSLCertificateView;
// as HttpAuthentication has different style for landscape / portrait, we
// have to re-open it when configuration changed
@@ -4579,13 +3700,11 @@
private BroadcastReceiver mPackageInstallationReceiver;
- // AsyncTask for downloading touch icons
- /* package */ DownloadTouchIcon mTouchIconLoader;
-
// activity requestCode
final static int COMBO_PAGE = 1;
final static int DOWNLOAD_PAGE = 2;
final static int PREFERENCES_PAGE = 3;
+ final static int FILE_SELECTED = 4;
// the default <video> poster
private Bitmap mDefaultVideoPoster;
diff --git a/src/com/android/browser/BrowserBookmarksAdapter.java b/src/com/android/browser/BrowserBookmarksAdapter.java
index dd56d2f..d1fdf07 100644
--- a/src/com/android/browser/BrowserBookmarksAdapter.java
+++ b/src/com/android/browser/BrowserBookmarksAdapter.java
@@ -540,15 +540,8 @@
private void bind(BookmarkItem b, int position) {
mCursor.moveToPosition(position- mExtraOffset);
- String title = mCursor.getString(Browser.HISTORY_PROJECTION_TITLE_INDEX);
- if (title.length() > BrowserSettings.MAX_TEXTVIEW_LEN) {
- title = title.substring(0, BrowserSettings.MAX_TEXTVIEW_LEN);
- }
- b.setName(title);
+ b.setName(mCursor.getString(Browser.HISTORY_PROJECTION_TITLE_INDEX));
String url = mCursor.getString(Browser.HISTORY_PROJECTION_URL_INDEX);
- if (url.length() > BrowserSettings.MAX_TEXTVIEW_LEN) {
- url = url.substring(0, BrowserSettings.MAX_TEXTVIEW_LEN);
- }
b.setUrl(url);
byte[] data = mCursor.getBlob(Browser.HISTORY_PROJECTION_FAVICON_INDEX);
if (data != null) {
diff --git a/src/com/android/browser/BrowserBookmarksPage.java b/src/com/android/browser/BrowserBookmarksPage.java
index 6ab011b..25e364b 100644
--- a/src/com/android/browser/BrowserBookmarksPage.java
+++ b/src/com/android/browser/BrowserBookmarksPage.java
@@ -64,7 +64,7 @@
private BookmarkViewMode mViewMode = BookmarkViewMode.NONE;
private GridView mGridPage;
- private View mVerticalList;
+ private ListView mVerticalList;
private BrowserBookmarksAdapter mBookmarksAdapter;
private static final int BOOKMARKS_SAVE = 1;
private boolean mDisableNewWindow;
@@ -240,12 +240,7 @@
if (mCreateShortcut) {
setTitle(R.string.browser_bookmarks_page_bookmarks_text);
}
- mBookmarksAdapter = new BrowserBookmarksAdapter(this,
- getIntent().getStringExtra("url"),
- getIntent().getStringExtra("title"),
- (Bitmap) getIntent().getParcelableExtra("thumbnail"),
- mCreateShortcut,
- mMostVisited);
+ mHandler.obtainMessage(CREATE_ADAPTER).sendToTarget();
setContentView(R.layout.empty_history);
mEmptyView = findViewById(R.id.empty_view);
@@ -270,12 +265,12 @@
* Set the ContentView to be either the grid of thumbnails or the vertical
* list.
*/
- private void switchViewMode(BookmarkViewMode gridMode) {
- if (mViewMode == gridMode) {
+ private void switchViewMode(BookmarkViewMode viewMode) {
+ if (mViewMode == viewMode) {
return;
}
- mViewMode = gridMode;
+ mViewMode = viewMode;
// Update the preferences to make the new view mode sticky.
Editor ed = getPreferences(MODE_PRIVATE).edit();
@@ -286,11 +281,15 @@
}
ed.commit();
- mBookmarksAdapter.switchViewMode(gridMode);
+ if (mBookmarksAdapter != null) {
+ mBookmarksAdapter.switchViewMode(viewMode);
+ }
if (mViewMode == BookmarkViewMode.GRID) {
if (mGridPage == null) {
mGridPage = new GridView(this);
- mGridPage.setAdapter(mBookmarksAdapter);
+ if (mBookmarksAdapter != null) {
+ mGridPage.setAdapter(mBookmarksAdapter);
+ }
mGridPage.setOnItemClickListener(mListener);
mGridPage.setNumColumns(GridView.AUTO_FIT);
mGridPage.setColumnWidth(
@@ -321,7 +320,9 @@
} else {
if (null == mVerticalList) {
ListView listView = new ListView(this);
- listView.setAdapter(mBookmarksAdapter);
+ if (mBookmarksAdapter != null) {
+ listView.setAdapter(mBookmarksAdapter);
+ }
listView.setDrawSelectorOnTop(false);
listView.setVerticalScrollBarEnabled(true);
listView.setOnItemClickListener(mListener);
@@ -349,11 +350,31 @@
ViewGroup.LayoutParams.FILL_PARENT);
private static final int SAVE_CURRENT_PAGE = 1000;
+ private static final int CREATE_ADAPTER = 1001;
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
- if (msg.what == SAVE_CURRENT_PAGE) {
- saveCurrentPage();
+ switch (msg.what) {
+ case SAVE_CURRENT_PAGE:
+ saveCurrentPage();
+ break;
+ case CREATE_ADAPTER:
+ Intent intent = getIntent();
+ mBookmarksAdapter = new BrowserBookmarksAdapter(
+ BrowserBookmarksPage.this,
+ intent.getStringExtra("url"),
+ intent.getStringExtra("title"),
+ (Bitmap) intent.getParcelableExtra("thumbnail"),
+ mCreateShortcut,
+ mMostVisited);
+ mBookmarksAdapter.switchViewMode(mViewMode);
+ if (mGridPage != null) {
+ mGridPage.setAdapter(mBookmarksAdapter);
+ }
+ if (mVerticalList != null) {
+ mVerticalList.setAdapter(mBookmarksAdapter);
+ }
+ break;
}
}
};
@@ -439,9 +460,10 @@
p.setStyle(Paint.Style.FILL_AND_STROKE);
p.setColor(Color.WHITE);
+ float density = getResources().getDisplayMetrics().density;
// Create a rectangle that is slightly wider than the favicon
- final float iconSize = 16; // 16x16 favicon
- final float padding = 2; // white padding around icon
+ final float iconSize = 16 * density; // 16x16 favicon
+ final float padding = 2; // white padding around icon
final float rectSize = iconSize + 2 * padding;
final float y = icon.getHeight() - rectSize;
RectF r = new RectF(0, y, rectSize, y + rectSize);
@@ -489,7 +511,7 @@
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
boolean result = super.onPrepareOptionsMenu(menu);
- if (mCreateShortcut || mMostVisited
+ if (mCreateShortcut || mMostVisited || mBookmarksAdapter == null
|| mBookmarksAdapter.getCount() == 0) {
// No need to show the menu if there are no items.
return result;
@@ -604,25 +626,29 @@
* Return a hashmap representing the currently highlighted row.
*/
public Bundle getRow(int position) {
- return mBookmarksAdapter.getRow(position);
+ return mBookmarksAdapter == null ? null
+ : mBookmarksAdapter.getRow(position);
}
/**
* Return the url of the currently highlighted row.
*/
public String getUrl(int position) {
- return mBookmarksAdapter.getUrl(position);
+ return mBookmarksAdapter == null ? null
+ : mBookmarksAdapter.getUrl(position);
}
/**
* Return the favicon of the currently highlighted row.
*/
public Bitmap getFavicon(int position) {
- return mBookmarksAdapter.getFavicon(position);
+ return mBookmarksAdapter == null ? null
+ : mBookmarksAdapter.getFavicon(position);
}
private Bitmap getTouchIcon(int position) {
- return mBookmarksAdapter.getTouchIcon(position);
+ return mBookmarksAdapter == null ? null
+ : mBookmarksAdapter.getTouchIcon(position);
}
private void copy(CharSequence text) {
@@ -637,13 +663,15 @@
}
public String getBookmarkTitle(int position) {
- return mBookmarksAdapter.getTitle(position);
+ return mBookmarksAdapter == null ? null
+ : mBookmarksAdapter.getTitle(position);
}
/**
* Delete the currently highlighted row.
*/
public void deleteBookmark(int position) {
+ if (mBookmarksAdapter == null) return;
mBookmarksAdapter.deleteRow(position);
}
diff --git a/src/com/android/browser/BrowserHistoryPage.java b/src/com/android/browser/BrowserHistoryPage.java
index bdd109b..2eab181 100644
--- a/src/com/android/browser/BrowserHistoryPage.java
+++ b/src/com/android/browser/BrowserHistoryPage.java
@@ -418,6 +418,8 @@
} else {
item = (HistoryItem) convertView;
}
+ // Bail early if the Cursor is closed.
+ if (mCursor.isClosed()) return item;
int index = childPosition;
for (int i = 0; i < groupPosition; i++) {
index += mItemMap[i];
@@ -515,7 +517,7 @@
}
public boolean isEmpty() {
- return mCursor.getCount() == 0;
+ return mCursor.isClosed() || mCursor.getCount() == 0;
}
}
}
diff --git a/src/com/android/browser/BrowserHomepagePreference.java b/src/com/android/browser/BrowserHomepagePreference.java
index be96db3..ec603d3 100644
--- a/src/com/android/browser/BrowserHomepagePreference.java
+++ b/src/com/android/browser/BrowserHomepagePreference.java
@@ -18,10 +18,20 @@
import android.app.AlertDialog;
import android.content.Context;
+import android.os.Bundle;
import android.preference.EditTextPreference;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
import android.util.AttributeSet;
public class BrowserHomepagePreference extends EditTextPreference {
+ private String mCurrentPage;
public BrowserHomepagePreference(Context context, AttributeSet attrs,
int defStyle) {
@@ -37,6 +47,27 @@
}
@Override
+ protected void onAddEditTextToDialogView(View dialogView,
+ EditText editText) {
+ super.onAddEditTextToDialogView(dialogView, editText);
+ // Now the EditText has a parent. Add a button to set to the current
+ // page.
+ ViewGroup parent = (ViewGroup) editText.getParent();
+ Button button = new Button(getContext());
+ button.setText(R.string.pref_use_current);
+ button.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ getEditText().setText(mCurrentPage);
+ }
+ });
+ if (parent instanceof LinearLayout) {
+ ((LinearLayout) parent).setGravity(Gravity.CENTER_HORIZONTAL);
+ }
+ parent.addView(button, ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+ }
+
+ @Override
protected void onDialogClosed(boolean positiveResult) {
if (positiveResult) {
String url = getEditText().getText().toString();
@@ -60,4 +91,26 @@
}
super.onDialogClosed(positiveResult);
}
+
+ /**
+ * Set the current page of the browser.
+ * @param currentPage This String will replace the text in the EditText
+ * when the user clicks the "Use current page" button.
+ */
+ /* package */ void setCurrentPage(String currentPage) {
+ mCurrentPage = currentPage;
+ }
+
+ @Override
+ protected void showDialog(Bundle state) {
+ super.showDialog(state);
+ // The dialog has its width set to wrap_content. Change it to
+ // fill_parent so there is more room to type in a url.
+ Window window = getDialog().getWindow();
+ View decorView = window.getDecorView();
+ WindowManager.LayoutParams params
+ = (WindowManager.LayoutParams) decorView.getLayoutParams();
+ params.width = ViewGroup.LayoutParams.FILL_PARENT;
+ window.getWindowManager().updateViewLayout(decorView, params);
+ }
}
diff --git a/src/com/android/browser/BrowserPreferencesPage.java b/src/com/android/browser/BrowserPreferencesPage.java
index 1370722..b636f98 100644
--- a/src/com/android/browser/BrowserPreferencesPage.java
+++ b/src/com/android/browser/BrowserPreferencesPage.java
@@ -39,6 +39,7 @@
implements Preference.OnPreferenceChangeListener {
private String LOGTAG = "BrowserPreferencesPage";
+ /* package */ static final String CURRENT_PAGE = "currentPage";
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -51,6 +52,8 @@
e.setOnPreferenceChangeListener(this);
e.setSummary(getPreferenceScreen().getSharedPreferences()
.getString(BrowserSettings.PREF_HOMEPAGE, null));
+ ((BrowserHomepagePreference) e).setCurrentPage(
+ getIntent().getStringExtra(CURRENT_PAGE));
e = findPreference(BrowserSettings.PREF_EXTRAS_RESET_DEFAULTS);
e.setOnPreferenceChangeListener(this);
diff --git a/src/com/android/browser/BrowserProvider.java b/src/com/android/browser/BrowserProvider.java
index 8e0929b..6755268 100644
--- a/src/com/android/browser/BrowserProvider.java
+++ b/src/com/android/browser/BrowserProvider.java
@@ -16,9 +16,8 @@
package com.android.browser;
-import com.google.android.providers.GoogleSettings.Partner;
-
import android.app.SearchManager;
+import android.app.SearchableInfo;
import android.backup.BackupManager;
import android.content.ComponentName;
import android.content.ContentProvider;
@@ -44,12 +43,14 @@
import android.provider.Browser;
import android.provider.Settings;
import android.provider.Browser.BookmarkColumns;
-import android.server.search.SearchableInfo;
import android.text.TextUtils;
-import android.text.util.Regex;
import android.util.Log;
import android.util.TypedValue;
+import com.android.common.Patterns;
+
+import com.google.android.providers.GoogleSettings.Partner;
+
import java.io.File;
import java.io.FilenameFilter;
import java.util.Date;
@@ -72,11 +73,11 @@
"bookmarks", "searches"
};
private static final String[] SUGGEST_PROJECTION = new String[] {
- "_id", "url", "title", "bookmark"
+ "_id", "url", "title", "bookmark", "user_entered"
};
private static final String SUGGEST_SELECTION =
- "url LIKE ? OR url LIKE ? OR url LIKE ? OR url LIKE ?"
- + " OR title LIKE ?";
+ "(url LIKE ? OR url LIKE ? OR url LIKE ? OR url LIKE ?"
+ + " OR title LIKE ?) AND (bookmark = 1 OR user_entered = 1)";
private String[] SUGGEST_ARGS = new String[5];
// shared suggestion array index, make sure to match COLUMNS
@@ -157,7 +158,8 @@
// 19 -> 20 Added thumbnail
// 20 -> 21 Added touch_icon
// 21 -> 22 Remove "clientid"
- private static final int DATABASE_VERSION = 22;
+ // 22 -> 23 Added user_entered
+ private static final int DATABASE_VERSION = 23;
// Regular expression which matches http://, followed by some stuff, followed by
// optionally a trailing slash, all matched as separate groups.
@@ -231,7 +233,8 @@
"bookmark INTEGER," +
"favicon BLOB DEFAULT NULL," +
"thumbnail BLOB DEFAULT NULL," +
- "touch_icon BLOB DEFAULT NULL" +
+ "touch_icon BLOB DEFAULT NULL," +
+ "user_entered INTEGER" +
");");
final CharSequence[] bookmarks = mContext.getResources()
@@ -271,6 +274,9 @@
if (oldVersion < 22) {
db.execSQL("DELETE FROM bookmarks WHERE (bookmark = 0 AND url LIKE \"%.google.%client=ms-%\")");
removeGears();
+ }
+ if (oldVersion < 23) {
+ db.execSQL("ALTER TABLE bookmarks ADD COLUMN user_entered INTEGER;");
} else {
db.execSQL("DROP TABLE IF EXISTS bookmarks");
db.execSQL("DROP TABLE IF EXISTS searches");
@@ -749,7 +755,7 @@
ORDER_BY, MAX_SUGGESTION_LONG_ENTRIES_STRING);
if (match == URI_MATCH_BOOKMARKS_SUGGEST
- || Regex.WEB_URL_PATTERN.matcher(selectionArgs[0]).matches()) {
+ || Patterns.WEB_URL.matcher(selectionArgs[0]).matches()) {
return new MySuggestionCursor(c, null, "");
} else {
// get Google suggest if there is still space in the list
diff --git a/src/com/android/browser/BrowserSettings.java b/src/com/android/browser/BrowserSettings.java
index 9c5af34..941b28b 100644
--- a/src/com/android/browser/BrowserSettings.java
+++ b/src/com/android/browser/BrowserSettings.java
@@ -19,6 +19,7 @@
import com.google.android.providers.GoogleSettings.Partner;
+import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ActivityInfo;
@@ -106,9 +107,6 @@
// The setting can be then toggled from the settings menu.
private boolean showConsole = true;
- // Browser only settings
- private boolean doFlick = false;
-
// Private preconfigured values
private static int minimumFontSize = 8;
private static int minimumLogicalFontSize = 8;
@@ -118,6 +116,7 @@
WebSettings.TextSize.NORMAL;
private static WebSettings.ZoomDensity zoomDensity =
WebSettings.ZoomDensity.MEDIUM;
+ private static int pageCacheCapacity;
// Preference keys that are used outside this class
public final static String PREF_CLEAR_CACHE = "privacy_clear_cache";
@@ -204,6 +203,7 @@
s.setSaveFormData(b.saveFormData);
s.setSavePassword(b.rememberPasswords);
s.setLoadWithOverviewMode(b.loadsPageInOverviewMode);
+ s.setPageCacheCapacity(pageCacheCapacity);
// WebView inside Browser doesn't want initial focus to be set.
s.setNeedInitialFocus(false);
@@ -256,6 +256,17 @@
homeUrl = getFactoryResetHomeUrl(ctx);
+ // the cost of one cached page is ~3M (measured using nytimes.com). For
+ // low end devices, we only cache one page. For high end devices, we try
+ // to cache more pages, currently choose 5.
+ ActivityManager am = (ActivityManager) ctx
+ .getSystemService(Context.ACTIVITY_SERVICE);
+ if (am.getMemoryClass() > 16) {
+ pageCacheCapacity = 5;
+ } else {
+ pageCacheCapacity = 1;
+ }
+
// Load the defaults from the xml
// This call is TOO SLOW, need to manually keep the defaults
// in sync
@@ -336,7 +347,6 @@
tracing = p.getBoolean("enable_tracing", tracing);
lightTouch = p.getBoolean("enable_light_touch", lightTouch);
navDump = p.getBoolean("enable_nav_dump", navDump);
- doFlick = p.getBoolean("enable_flick", doFlick);
userAgent = Integer.parseInt(p.getString("user_agent", "0"));
}
// JS flags is loaded from DB even if showDebugSettings is false,
@@ -422,10 +432,6 @@
return navDump;
}
- public boolean doFlick() {
- return doFlick;
- }
-
public boolean showDebugSettings() {
return showDebugSettings;
}
diff --git a/src/com/android/browser/DownloadTouchIcon.java b/src/com/android/browser/DownloadTouchIcon.java
index 07d2d3a..99f1930 100644
--- a/src/com/android/browser/DownloadTouchIcon.java
+++ b/src/com/android/browser/DownloadTouchIcon.java
@@ -36,17 +36,16 @@
import java.io.IOException;
import java.io.InputStream;
-class DownloadTouchIcon extends AsyncTask<String, Void, Bitmap> {
+class DownloadTouchIcon extends AsyncTask<String, Void, Void> {
private final ContentResolver mContentResolver;
private final Cursor mCursor;
private final String mOriginalUrl;
private final String mUrl;
private final String mUserAgent;
- /* package */ BrowserActivity mActivity;
+ /* package */ Tab mTab;
- public DownloadTouchIcon(BrowserActivity activity, ContentResolver cr,
- Cursor c, WebView view) {
- mActivity = activity;
+ public DownloadTouchIcon(Tab tab, ContentResolver cr, Cursor c, WebView view) {
+ mTab = tab;
mContentResolver = cr;
mCursor = c;
// Store these in case they change.
@@ -56,7 +55,7 @@
}
public DownloadTouchIcon(ContentResolver cr, Cursor c, String url) {
- mActivity = null;
+ mTab = null;
mContentResolver = cr;
mCursor = c;
mOriginalUrl = null;
@@ -65,7 +64,7 @@
}
@Override
- public Bitmap doInBackground(String... values) {
+ public Void doInBackground(String... values) {
String url = values[0];
AndroidHttpClient client = AndroidHttpClient.newInstance(
@@ -85,7 +84,7 @@
if (content != null) {
Bitmap icon = BitmapFactory.decodeStream(
content, null, null);
- return icon;
+ storeIcon(icon);
}
}
}
@@ -106,12 +105,11 @@
}
}
- @Override
- public void onPostExecute(Bitmap icon) {
+ private void storeIcon(Bitmap icon) {
// Do this first in case the download failed.
- if (mActivity != null) {
+ if (mTab != null) {
// Remove the touch icon loader from the BrowserActivity.
- mActivity.mTouchIconLoader = null;
+ mTab.mTouchIconLoader = null;
}
if (icon == null || mCursor == null || isCancelled()) {
diff --git a/src/com/android/browser/FindDialog.java b/src/com/android/browser/FindDialog.java
index df212d0..9379103 100644
--- a/src/com/android/browser/FindDialog.java
+++ b/src/com/android/browser/FindDialog.java
@@ -18,7 +18,6 @@
import android.app.Dialog;
import android.content.Context;
-import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -97,13 +96,6 @@
setCanceledOnTouchOutside(true);
}
- /* package */ void onConfigurationChanged(Configuration newConfig) {
- // FIXME: Would like to call mWebView.findAll again, so that the
- // matches would refresh, but the new picture has not yet been
- // created, so it is too soon.
- mEditText.getText().clear();
- }
-
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
diff --git a/src/com/android/browser/GeolocationPermissionsPrompt.java b/src/com/android/browser/GeolocationPermissionsPrompt.java
index a21bc3e..982aa89 100755
--- a/src/com/android/browser/GeolocationPermissionsPrompt.java
+++ b/src/com/android/browser/GeolocationPermissionsPrompt.java
@@ -20,6 +20,7 @@
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.util.AttributeSet;
+import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.webkit.WebView;
@@ -28,6 +29,7 @@
import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.TextView;
+import android.widget.Toast;
public class GeolocationPermissionsPrompt extends LinearLayout {
private LinearLayout mInner;
@@ -97,8 +99,19 @@
* Handles a click on one the buttons by invoking the callback.
*/
private void handleButtonClick(boolean allow) {
- boolean remember = mRemember.isChecked();
showDialog(false);
+
+ boolean remember = mRemember.isChecked();
+ if (remember) {
+ Toast toast = Toast.makeText(
+ getContext(),
+ allow ? R.string.geolocation_permissions_prompt_toast_allowed :
+ R.string.geolocation_permissions_prompt_toast_disallowed,
+ Toast.LENGTH_LONG);
+ toast.setGravity(Gravity.BOTTOM, 0, 0);
+ toast.show();
+ }
+
mCallback.invoke(mOrigin, allow, remember);
}
diff --git a/src/com/android/browser/Tab.java b/src/com/android/browser/Tab.java
new file mode 100644
index 0000000..54dc76d
--- /dev/null
+++ b/src/com/android/browser/Tab.java
@@ -0,0 +1,1570 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.browser;
+
+import java.io.File;
+import java.util.LinkedList;
+import java.util.Vector;
+
+import android.app.AlertDialog;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnCancelListener;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteException;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.net.http.SslError;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Message;
+import android.provider.Browser;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.View.OnClickListener;
+import android.webkit.CookieSyncManager;
+import android.webkit.GeolocationPermissions;
+import android.webkit.HttpAuthHandler;
+import android.webkit.SslErrorHandler;
+import android.webkit.URLUtil;
+import android.webkit.ValueCallback;
+import android.webkit.WebBackForwardList;
+import android.webkit.WebChromeClient;
+import android.webkit.WebHistoryItem;
+import android.webkit.WebIconDatabase;
+import android.webkit.WebStorage;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.FrameLayout;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+/**
+ * Class for maintaining Tabs with a main WebView and a subwindow.
+ */
+class Tab {
+ // Log Tag
+ private static final String LOGTAG = "Tab";
+ // The Geolocation permissions prompt
+ private GeolocationPermissionsPrompt mGeolocationPermissionsPrompt;
+ // Main WebView wrapper
+ private View mContainer;
+ // Main WebView
+ private WebView mMainView;
+ // Subwindow container
+ private View mSubViewContainer;
+ // Subwindow WebView
+ private WebView mSubView;
+ // Saved bundle for when we are running low on memory. It contains the
+ // information needed to restore the WebView if the user goes back to the
+ // tab.
+ private Bundle mSavedState;
+ // Data used when displaying the tab in the picker.
+ private PickerData mPickerData;
+ // Parent Tab. This is the Tab that created this Tab, or null if the Tab was
+ // created by the UI
+ private Tab mParentTab;
+ // Tab that constructed by this Tab. This is used when this Tab is
+ // destroyed, it clears all mParentTab values in the children.
+ private Vector<Tab> mChildTabs;
+ // If true, the tab will be removed when back out of the first page.
+ private boolean mCloseOnExit;
+ // If true, the tab is in the foreground of the current activity.
+ private boolean mInForeground;
+ // If true, the tab is in loading state.
+ private boolean mInLoad;
+ // Application identifier used to find tabs that another application wants
+ // to reuse.
+ private String mAppId;
+ // Keep the original url around to avoid killing the old WebView if the url
+ // has not changed.
+ private String mOriginalUrl;
+ // Error console for the tab
+ private ErrorConsoleView mErrorConsole;
+ // the lock icon type and previous lock icon type for the tab
+ private int mLockIconType;
+ private int mPrevLockIconType;
+ // Inflation service for making subwindows.
+ private final LayoutInflater mInflateService;
+ // The BrowserActivity which owners the Tab
+ private final BrowserActivity mActivity;
+
+ // AsyncTask for downloading touch icons
+ DownloadTouchIcon mTouchIconLoader;
+
+ // Extra saved information for displaying the tab in the picker.
+ private static class PickerData {
+ String mUrl;
+ String mTitle;
+ Bitmap mFavicon;
+ }
+
+ // Used for saving and restoring each Tab
+ static final String WEBVIEW = "webview";
+ static final String NUMTABS = "numTabs";
+ static final String CURRTAB = "currentTab";
+ static final String CURRURL = "currentUrl";
+ static final String CURRTITLE = "currentTitle";
+ static final String CURRPICTURE = "currentPicture";
+ static final String CLOSEONEXIT = "closeonexit";
+ static final String PARENTTAB = "parentTab";
+ static final String APPID = "appid";
+ static final String ORIGINALURL = "originalUrl";
+
+ // -------------------------------------------------------------------------
+
+ // Container class for the next error dialog that needs to be displayed
+ private class ErrorDialog {
+ public final int mTitle;
+ public final String mDescription;
+ public final int mError;
+ ErrorDialog(int title, String desc, int error) {
+ mTitle = title;
+ mDescription = desc;
+ mError = error;
+ }
+ };
+
+ private void processNextError() {
+ if (mQueuedErrors == null) {
+ return;
+ }
+ // The first one is currently displayed so just remove it.
+ mQueuedErrors.removeFirst();
+ if (mQueuedErrors.size() == 0) {
+ mQueuedErrors = null;
+ return;
+ }
+ showError(mQueuedErrors.getFirst());
+ }
+
+ private DialogInterface.OnDismissListener mDialogListener =
+ new DialogInterface.OnDismissListener() {
+ public void onDismiss(DialogInterface d) {
+ processNextError();
+ }
+ };
+ private LinkedList<ErrorDialog> mQueuedErrors;
+
+ private void queueError(int err, String desc) {
+ if (mQueuedErrors == null) {
+ mQueuedErrors = new LinkedList<ErrorDialog>();
+ }
+ for (ErrorDialog d : mQueuedErrors) {
+ if (d.mError == err) {
+ // Already saw a similar error, ignore the new one.
+ return;
+ }
+ }
+ ErrorDialog errDialog = new ErrorDialog(
+ err == WebViewClient.ERROR_FILE_NOT_FOUND ?
+ R.string.browserFrameFileErrorLabel :
+ R.string.browserFrameNetworkErrorLabel,
+ desc, err);
+ mQueuedErrors.addLast(errDialog);
+
+ // Show the dialog now if the queue was empty and it is in foreground
+ if (mQueuedErrors.size() == 1 && mInForeground) {
+ showError(errDialog);
+ }
+ }
+
+ private void showError(ErrorDialog errDialog) {
+ if (mInForeground) {
+ AlertDialog d = new AlertDialog.Builder(mActivity)
+ .setTitle(errDialog.mTitle)
+ .setMessage(errDialog.mDescription)
+ .setPositiveButton(R.string.ok, null)
+ .create();
+ d.setOnDismissListener(mDialogListener);
+ d.show();
+ }
+ }
+
+ // -------------------------------------------------------------------------
+ // WebViewClient implementation for the main WebView
+ // -------------------------------------------------------------------------
+
+ private final WebViewClient mWebViewClient = new WebViewClient() {
+ @Override
+ public void onPageStarted(WebView view, String url, Bitmap favicon) {
+ mInLoad = true;
+
+ // We've started to load a new page. If there was a pending message
+ // to save a screenshot then we will now take the new page and save
+ // an incorrect screenshot. Therefore, remove any pending thumbnail
+ // messages from the queue.
+ mActivity.removeMessages(BrowserActivity.UPDATE_BOOKMARK_THUMBNAIL,
+ view);
+
+ // If we start a touch icon load and then load a new page, we don't
+ // want to cancel the current touch icon loader. But, we do want to
+ // create a new one when the touch icon url is known.
+ if (mTouchIconLoader != null) {
+ mTouchIconLoader.mTab = null;
+ mTouchIconLoader = null;
+ }
+
+ // reset the error console
+ if (mErrorConsole != null) {
+ mErrorConsole.clearErrorMessages();
+ if (mActivity.shouldShowErrorConsole()) {
+ mErrorConsole.showConsole(ErrorConsoleView.SHOW_NONE);
+ }
+ }
+
+ // update the bookmark database for favicon
+ if (favicon != null) {
+ BrowserBookmarksAdapter.updateBookmarkFavicon(mActivity
+ .getContentResolver(), view.getOriginalUrl(), view
+ .getUrl(), favicon);
+ }
+
+ // reset sync timer to avoid sync starts during loading a page
+ CookieSyncManager.getInstance().resetSync();
+
+ if (!mActivity.isNetworkUp()) {
+ view.setNetworkAvailable(false);
+ }
+
+ // finally update the UI in the activity if it is in the foreground
+ if (mInForeground) {
+ mActivity.onPageStarted(view, url, favicon);
+ }
+ }
+
+ @Override
+ public void onPageFinished(WebView view, String url) {
+ mInLoad = false;
+
+ if (mInForeground && !mActivity.didUserStopLoading()
+ || !mInForeground) {
+ // Only update the bookmark screenshot if the user did not
+ // cancel the load early.
+ mActivity.postMessage(
+ BrowserActivity.UPDATE_BOOKMARK_THUMBNAIL, 0, 0, view,
+ 500);
+ }
+
+ // finally update the UI in the activity if it is in the foreground
+ if (mInForeground) {
+ mActivity.onPageFinished(view, url);
+ }
+ }
+
+ // return true if want to hijack the url to let another app to handle it
+ @Override
+ public boolean shouldOverrideUrlLoading(WebView view, String url) {
+ if (mInForeground) {
+ return mActivity.shouldOverrideUrlLoading(view, url);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Updates the lock icon. This method is called when we discover another
+ * resource to be loaded for this page (for example, javascript). While
+ * we update the icon type, we do not update the lock icon itself until
+ * we are done loading, it is slightly more secure this way.
+ */
+ @Override
+ public void onLoadResource(WebView view, String url) {
+ if (url != null && url.length() > 0) {
+ // It is only if the page claims to be secure that we may have
+ // to update the lock:
+ if (mLockIconType == BrowserActivity.LOCK_ICON_SECURE) {
+ // If NOT a 'safe' url, change the lock to mixed content!
+ if (!(URLUtil.isHttpsUrl(url) || URLUtil.isDataUrl(url)
+ || URLUtil.isAboutUrl(url))) {
+ mLockIconType = BrowserActivity.LOCK_ICON_MIXED;
+ }
+ }
+ }
+ }
+
+ /**
+ * Show the dialog if it is in the foreground, asking the user if they
+ * would like to continue after an excessive number of HTTP redirects.
+ * Cancel if it is in the background.
+ */
+ @Override
+ public void onTooManyRedirects(WebView view, final Message cancelMsg,
+ final Message continueMsg) {
+ if (!mInForeground) {
+ cancelMsg.sendToTarget();
+ return;
+ }
+ new AlertDialog.Builder(mActivity).setTitle(
+ R.string.browserFrameRedirect).setMessage(
+ R.string.browserFrame307Post).setPositiveButton(
+ R.string.ok, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ continueMsg.sendToTarget();
+ }
+ }).setNegativeButton(R.string.cancel,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ cancelMsg.sendToTarget();
+ }
+ }).setOnCancelListener(new OnCancelListener() {
+ public void onCancel(DialogInterface dialog) {
+ cancelMsg.sendToTarget();
+ }
+ }).show();
+ }
+
+ /**
+ * Show a dialog informing the user of the network error reported by
+ * WebCore if it is in the foreground.
+ */
+ @Override
+ public void onReceivedError(WebView view, int errorCode,
+ String description, String failingUrl) {
+ if (errorCode != WebViewClient.ERROR_HOST_LOOKUP &&
+ errorCode != WebViewClient.ERROR_CONNECT &&
+ errorCode != WebViewClient.ERROR_BAD_URL &&
+ errorCode != WebViewClient.ERROR_UNSUPPORTED_SCHEME &&
+ errorCode != WebViewClient.ERROR_FILE) {
+ queueError(errorCode, description);
+ }
+ Log.e(LOGTAG, "onReceivedError " + errorCode + " " + failingUrl
+ + " " + description);
+
+ // We need to reset the title after an error if it is in foreground.
+ if (mInForeground) {
+ mActivity.resetTitleAndRevertLockIcon();
+ }
+ }
+
+ /**
+ * Check with the user if it is ok to resend POST data as the page they
+ * are trying to navigate to is the result of a POST.
+ */
+ @Override
+ public void onFormResubmission(WebView view, final Message dontResend,
+ final Message resend) {
+ if (!mInForeground) {
+ dontResend.sendToTarget();
+ return;
+ }
+ new AlertDialog.Builder(mActivity).setTitle(
+ R.string.browserFrameFormResubmitLabel).setMessage(
+ R.string.browserFrameFormResubmitMessage)
+ .setPositiveButton(R.string.ok,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog,
+ int which) {
+ resend.sendToTarget();
+ }
+ }).setNegativeButton(R.string.cancel,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog,
+ int which) {
+ dontResend.sendToTarget();
+ }
+ }).setOnCancelListener(new OnCancelListener() {
+ public void onCancel(DialogInterface dialog) {
+ dontResend.sendToTarget();
+ }
+ }).show();
+ }
+
+ /**
+ * Insert the url into the visited history database.
+ * @param url The url to be inserted.
+ * @param isReload True if this url is being reloaded.
+ * FIXME: Not sure what to do when reloading the page.
+ */
+ @Override
+ public void doUpdateVisitedHistory(WebView view, String url,
+ boolean isReload) {
+ if (url.regionMatches(true, 0, "about:", 0, 6)) {
+ return;
+ }
+ // remove "client" before updating it to the history so that it wont
+ // show up in the auto-complete list.
+ int index = url.indexOf("client=ms-");
+ if (index > 0 && url.contains(".google.")) {
+ int end = url.indexOf('&', index);
+ if (end > 0) {
+ url = url.substring(0, index)
+ .concat(url.substring(end + 1));
+ } else {
+ // the url.charAt(index-1) should be either '?' or '&'
+ url = url.substring(0, index-1);
+ }
+ }
+ Browser.updateVisitedHistory(mActivity.getContentResolver(), url,
+ true);
+ WebIconDatabase.getInstance().retainIconForPageUrl(url);
+ }
+
+ /**
+ * Displays SSL error(s) dialog to the user.
+ */
+ @Override
+ public void onReceivedSslError(final WebView view,
+ final SslErrorHandler handler, final SslError error) {
+ if (!mInForeground) {
+ handler.cancel();
+ return;
+ }
+ if (BrowserSettings.getInstance().showSecurityWarnings()) {
+ final LayoutInflater factory =
+ LayoutInflater.from(mActivity);
+ final View warningsView =
+ factory.inflate(R.layout.ssl_warnings, null);
+ final LinearLayout placeholder =
+ (LinearLayout)warningsView.findViewById(R.id.placeholder);
+
+ if (error.hasError(SslError.SSL_UNTRUSTED)) {
+ LinearLayout ll = (LinearLayout)factory
+ .inflate(R.layout.ssl_warning, null);
+ ((TextView)ll.findViewById(R.id.warning))
+ .setText(R.string.ssl_untrusted);
+ placeholder.addView(ll);
+ }
+
+ if (error.hasError(SslError.SSL_IDMISMATCH)) {
+ LinearLayout ll = (LinearLayout)factory
+ .inflate(R.layout.ssl_warning, null);
+ ((TextView)ll.findViewById(R.id.warning))
+ .setText(R.string.ssl_mismatch);
+ placeholder.addView(ll);
+ }
+
+ if (error.hasError(SslError.SSL_EXPIRED)) {
+ LinearLayout ll = (LinearLayout)factory
+ .inflate(R.layout.ssl_warning, null);
+ ((TextView)ll.findViewById(R.id.warning))
+ .setText(R.string.ssl_expired);
+ placeholder.addView(ll);
+ }
+
+ if (error.hasError(SslError.SSL_NOTYETVALID)) {
+ LinearLayout ll = (LinearLayout)factory
+ .inflate(R.layout.ssl_warning, null);
+ ((TextView)ll.findViewById(R.id.warning))
+ .setText(R.string.ssl_not_yet_valid);
+ placeholder.addView(ll);
+ }
+
+ new AlertDialog.Builder(mActivity).setTitle(
+ R.string.security_warning).setIcon(
+ android.R.drawable.ic_dialog_alert).setView(
+ warningsView).setPositiveButton(R.string.ssl_continue,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog,
+ int whichButton) {
+ handler.proceed();
+ }
+ }).setNeutralButton(R.string.view_certificate,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog,
+ int whichButton) {
+ mActivity.showSSLCertificateOnError(view,
+ handler, error);
+ }
+ }).setNegativeButton(R.string.cancel,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog,
+ int whichButton) {
+ handler.cancel();
+ mActivity.resetTitleAndRevertLockIcon();
+ }
+ }).setOnCancelListener(
+ new DialogInterface.OnCancelListener() {
+ public void onCancel(DialogInterface dialog) {
+ handler.cancel();
+ mActivity.resetTitleAndRevertLockIcon();
+ }
+ }).show();
+ } else {
+ handler.proceed();
+ }
+ }
+
+ /**
+ * Handles an HTTP authentication request.
+ *
+ * @param handler The authentication handler
+ * @param host The host
+ * @param realm The realm
+ */
+ @Override
+ public void onReceivedHttpAuthRequest(WebView view,
+ final HttpAuthHandler handler, final String host,
+ final String realm) {
+ String username = null;
+ String password = null;
+
+ boolean reuseHttpAuthUsernamePassword = handler
+ .useHttpAuthUsernamePassword();
+
+ if (reuseHttpAuthUsernamePassword && mMainView != null) {
+ String[] credentials = mMainView.getHttpAuthUsernamePassword(
+ host, realm);
+ if (credentials != null && credentials.length == 2) {
+ username = credentials[0];
+ password = credentials[1];
+ }
+ }
+
+ if (username != null && password != null) {
+ handler.proceed(username, password);
+ } else {
+ if (mInForeground) {
+ mActivity.showHttpAuthentication(handler, host, realm,
+ null, null, null, 0);
+ } else {
+ handler.cancel();
+ }
+ }
+ }
+
+ @Override
+ public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) {
+ if (!mInForeground) {
+ return false;
+ }
+ if (mActivity.isMenuDown()) {
+ // only check shortcut key when MENU is held
+ return mActivity.getWindow().isShortcutKey(event.getKeyCode(),
+ event);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
+ if (!mInForeground) {
+ return;
+ }
+ if (event.isDown()) {
+ mActivity.onKeyDown(event.getKeyCode(), event);
+ } else {
+ mActivity.onKeyUp(event.getKeyCode(), event);
+ }
+ }
+ };
+
+ // -------------------------------------------------------------------------
+ // WebChromeClient implementation for the main WebView
+ // -------------------------------------------------------------------------
+
+ private final WebChromeClient mWebChromeClient = new WebChromeClient() {
+ // Helper method to create a new tab or sub window.
+ private void createWindow(final boolean dialog, final Message msg) {
+ WebView.WebViewTransport transport =
+ (WebView.WebViewTransport) msg.obj;
+ if (dialog) {
+ createSubWindow();
+ mActivity.attachSubWindow(Tab.this);
+ transport.setWebView(mSubView);
+ } else {
+ final Tab newTab = mActivity.openTabAndShow(
+ BrowserActivity.EMPTY_URL_DATA, false, null);
+ if (newTab != Tab.this) {
+ Tab.this.addChildTab(newTab);
+ }
+ transport.setWebView(newTab.getWebView());
+ }
+ msg.sendToTarget();
+ }
+
+ @Override
+ public boolean onCreateWindow(WebView view, final boolean dialog,
+ final boolean userGesture, final Message resultMsg) {
+ // only allow new window or sub window for the foreground case
+ if (!mInForeground) {
+ return false;
+ }
+ // Short-circuit if we can't create any more tabs or sub windows.
+ if (dialog && mSubView != null) {
+ new AlertDialog.Builder(mActivity)
+ .setTitle(R.string.too_many_subwindows_dialog_title)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(R.string.too_many_subwindows_dialog_message)
+ .setPositiveButton(R.string.ok, null)
+ .show();
+ return false;
+ } else if (!mActivity.getTabControl().canCreateNewTab()) {
+ new AlertDialog.Builder(mActivity)
+ .setTitle(R.string.too_many_windows_dialog_title)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(R.string.too_many_windows_dialog_message)
+ .setPositiveButton(R.string.ok, null)
+ .show();
+ return false;
+ }
+
+ // Short-circuit if this was a user gesture.
+ if (userGesture) {
+ createWindow(dialog, resultMsg);
+ return true;
+ }
+
+ // Allow the popup and create the appropriate window.
+ final AlertDialog.OnClickListener allowListener =
+ new AlertDialog.OnClickListener() {
+ public void onClick(DialogInterface d,
+ int which) {
+ createWindow(dialog, resultMsg);
+ }
+ };
+
+ // Block the popup by returning a null WebView.
+ final AlertDialog.OnClickListener blockListener =
+ new AlertDialog.OnClickListener() {
+ public void onClick(DialogInterface d, int which) {
+ resultMsg.sendToTarget();
+ }
+ };
+
+ // Build a confirmation dialog to display to the user.
+ final AlertDialog d =
+ new AlertDialog.Builder(mActivity)
+ .setTitle(R.string.attention)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(R.string.popup_window_attempt)
+ .setPositiveButton(R.string.allow, allowListener)
+ .setNegativeButton(R.string.block, blockListener)
+ .setCancelable(false)
+ .create();
+
+ // Show the confirmation dialog.
+ d.show();
+ return true;
+ }
+
+ @Override
+ public void onRequestFocus(WebView view) {
+ if (!mInForeground) {
+ mActivity.switchToTab(mActivity.getTabControl().getTabIndex(
+ Tab.this));
+ }
+ }
+
+ @Override
+ public void onCloseWindow(WebView window) {
+ if (mParentTab != null) {
+ // JavaScript can only close popup window.
+ if (mInForeground) {
+ mActivity.switchToTab(mActivity.getTabControl()
+ .getTabIndex(mParentTab));
+ }
+ mActivity.closeTab(Tab.this);
+ }
+ }
+
+ @Override
+ public void onProgressChanged(WebView view, int newProgress) {
+ if (newProgress == 100) {
+ // sync cookies and cache promptly here.
+ CookieSyncManager.getInstance().sync();
+ }
+ if (mInForeground) {
+ mActivity.onProgressChanged(view, newProgress);
+ }
+ }
+
+ @Override
+ public void onReceivedTitle(WebView view, String title) {
+ String url = view.getUrl();
+ if (mInForeground) {
+ // here, if url is null, we want to reset the title
+ mActivity.setUrlTitle(url, title);
+ }
+ if (url == null ||
+ url.length() >= SQLiteDatabase.SQLITE_MAX_LIKE_PATTERN_LENGTH) {
+ return;
+ }
+ // See if we can find the current url in our history database and
+ // add the new title to it.
+ if (url.startsWith("http://www.")) {
+ url = url.substring(11);
+ } else if (url.startsWith("http://")) {
+ url = url.substring(4);
+ }
+ try {
+ final ContentResolver cr = mActivity.getContentResolver();
+ url = "%" + url;
+ String [] selArgs = new String[] { url };
+ String where = Browser.BookmarkColumns.URL + " LIKE ? AND "
+ + Browser.BookmarkColumns.BOOKMARK + " = 0";
+ Cursor c = cr.query(Browser.BOOKMARKS_URI,
+ Browser.HISTORY_PROJECTION, where, selArgs, null);
+ if (c.moveToFirst()) {
+ // Current implementation of database only has one entry per
+ // url.
+ ContentValues map = new ContentValues();
+ map.put(Browser.BookmarkColumns.TITLE, title);
+ cr.update(Browser.BOOKMARKS_URI, map, "_id = "
+ + c.getInt(0), null);
+ }
+ c.close();
+ } catch (IllegalStateException e) {
+ Log.e(LOGTAG, "Tab onReceived title", e);
+ } catch (SQLiteException ex) {
+ Log.e(LOGTAG, "onReceivedTitle() caught SQLiteException: ", ex);
+ }
+ }
+
+ @Override
+ public void onReceivedIcon(WebView view, Bitmap icon) {
+ if (icon != null) {
+ BrowserBookmarksAdapter.updateBookmarkFavicon(mActivity
+ .getContentResolver(), view.getOriginalUrl(), view
+ .getUrl(), icon);
+ }
+ if (mInForeground) {
+ mActivity.setFavicon(icon);
+ }
+ }
+
+ @Override
+ public void onReceivedTouchIconUrl(WebView view, String url,
+ boolean precomposed) {
+ final ContentResolver cr = mActivity.getContentResolver();
+ final Cursor c = BrowserBookmarksAdapter.queryBookmarksForUrl(cr,
+ view.getOriginalUrl(), view.getUrl(), true);
+ if (c != null) {
+ if (c.getCount() > 0) {
+ // Let precomposed icons take precedence over non-composed
+ // icons.
+ if (precomposed && mTouchIconLoader != null) {
+ mTouchIconLoader.cancel(false);
+ mTouchIconLoader = null;
+ }
+ // Have only one async task at a time.
+ if (mTouchIconLoader == null) {
+ mTouchIconLoader = new DownloadTouchIcon(Tab.this, cr,
+ c, view);
+ mTouchIconLoader.execute(url);
+ }
+ } else {
+ c.close();
+ }
+ }
+ }
+
+ @Override
+ public void onShowCustomView(View view,
+ WebChromeClient.CustomViewCallback callback) {
+ if (mInForeground) mActivity.onShowCustomView(view, callback);
+ }
+
+ @Override
+ public void onHideCustomView() {
+ if (mInForeground) mActivity.onHideCustomView();
+ }
+
+ /**
+ * The origin has exceeded its database quota.
+ * @param url the URL that exceeded the quota
+ * @param databaseIdentifier the identifier of the database on which the
+ * transaction that caused the quota overflow was run
+ * @param currentQuota the current quota for the origin.
+ * @param estimatedSize the estimated size of the database.
+ * @param totalUsedQuota is the sum of all origins' quota.
+ * @param quotaUpdater The callback to run when a decision to allow or
+ * deny quota has been made. Don't forget to call this!
+ */
+ @Override
+ public void onExceededDatabaseQuota(String url,
+ String databaseIdentifier, long currentQuota, long estimatedSize,
+ long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) {
+ BrowserSettings.getInstance().getWebStorageSizeManager()
+ .onExceededDatabaseQuota(url, databaseIdentifier,
+ currentQuota, estimatedSize, totalUsedQuota,
+ quotaUpdater);
+ }
+
+ /**
+ * The Application Cache has exceeded its max size.
+ * @param spaceNeeded is the amount of disk space that would be needed
+ * in order for the last appcache operation to succeed.
+ * @param totalUsedQuota is the sum of all origins' quota.
+ * @param quotaUpdater A callback to inform the WebCore thread that a
+ * new app cache size is available. This callback must always
+ * be executed at some point to ensure that the sleeping
+ * WebCore thread is woken up.
+ */
+ @Override
+ public void onReachedMaxAppCacheSize(long spaceNeeded,
+ long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) {
+ BrowserSettings.getInstance().getWebStorageSizeManager()
+ .onReachedMaxAppCacheSize(spaceNeeded, totalUsedQuota,
+ quotaUpdater);
+ }
+
+ /**
+ * Instructs the browser to show a prompt to ask the user to set the
+ * Geolocation permission state for the specified origin.
+ * @param origin The origin for which Geolocation permissions are
+ * requested.
+ * @param callback The callback to call once the user has set the
+ * Geolocation permission state.
+ */
+ @Override
+ public void onGeolocationPermissionsShowPrompt(String origin,
+ GeolocationPermissions.Callback callback) {
+ if (mInForeground) {
+ mGeolocationPermissionsPrompt.show(origin, callback);
+ }
+ }
+
+ /**
+ * Instructs the browser to hide the Geolocation permissions prompt.
+ */
+ @Override
+ public void onGeolocationPermissionsHidePrompt() {
+ if (mInForeground) {
+ mGeolocationPermissionsPrompt.hide();
+ }
+ }
+
+ /* Adds a JavaScript error message to the system log and if the JS
+ * console is enabled in the about:debug options, to that console
+ * also.
+ * @param message The error message to report.
+ * @param lineNumber The line number of the error.
+ * @param sourceID The name of the source file that caused the error.
+ */
+ @Override
+ public void onConsoleMessage(String message, int lineNumber,
+ String sourceID) {
+ if (mInForeground) {
+ // call getErrorConsole(true) so it will create one if needed
+ ErrorConsoleView errorConsole = getErrorConsole(true);
+ errorConsole.addErrorMessage(message, sourceID, lineNumber);
+ if (mActivity.shouldShowErrorConsole()
+ && errorConsole.getShowState() != ErrorConsoleView.SHOW_MAXIMIZED) {
+ errorConsole.showConsole(ErrorConsoleView.SHOW_MINIMIZED);
+ }
+ }
+ Log.w(LOGTAG, "Console: " + message + " " + sourceID + ":"
+ + lineNumber);
+ }
+
+ /**
+ * Ask the browser for an icon to represent a <video> element.
+ * This icon will be used if the Web page did not specify a poster attribute.
+ * @return Bitmap The icon or null if no such icon is available.
+ */
+ @Override
+ public Bitmap getDefaultVideoPoster() {
+ if (mInForeground) {
+ return mActivity.getDefaultVideoPoster();
+ }
+ return null;
+ }
+
+ /**
+ * Ask the host application for a custom progress view to show while
+ * a <video> is loading.
+ * @return View The progress view.
+ */
+ @Override
+ public View getVideoLoadingProgressView() {
+ if (mInForeground) {
+ return mActivity.getVideoLoadingProgressView();
+ }
+ return null;
+ }
+
+ @Override
+ public void openFileChooser(ValueCallback<Uri> uploadMsg) {
+ if (mInForeground) {
+ mActivity.openFileChooser(uploadMsg);
+ } else {
+ uploadMsg.onReceiveValue(null);
+ }
+ }
+
+ /**
+ * Deliver a list of already-visited URLs
+ */
+ @Override
+ public void getVisitedHistory(final ValueCallback<String[]> callback) {
+ AsyncTask<Void, Void, String[]> task = new AsyncTask<Void, Void, String[]>() {
+ public String[] doInBackground(Void... unused) {
+ return Browser.getVisitedHistory(mActivity
+ .getContentResolver());
+ }
+ public void onPostExecute(String[] result) {
+ callback.onReceiveValue(result);
+ };
+ };
+ task.execute();
+ };
+ };
+
+ // -------------------------------------------------------------------------
+ // WebViewClient implementation for the sub window
+ // -------------------------------------------------------------------------
+
+ // Subclass of WebViewClient used in subwindows to notify the main
+ // WebViewClient of certain WebView activities.
+ private static class SubWindowClient extends WebViewClient {
+ // The main WebViewClient.
+ private final WebViewClient mClient;
+
+ SubWindowClient(WebViewClient client) {
+ mClient = client;
+ }
+ @Override
+ public void doUpdateVisitedHistory(WebView view, String url,
+ boolean isReload) {
+ mClient.doUpdateVisitedHistory(view, url, isReload);
+ }
+ @Override
+ public boolean shouldOverrideUrlLoading(WebView view, String url) {
+ return mClient.shouldOverrideUrlLoading(view, url);
+ }
+ @Override
+ public void onReceivedSslError(WebView view, SslErrorHandler handler,
+ SslError error) {
+ mClient.onReceivedSslError(view, handler, error);
+ }
+ @Override
+ public void onReceivedHttpAuthRequest(WebView view,
+ HttpAuthHandler handler, String host, String realm) {
+ mClient.onReceivedHttpAuthRequest(view, handler, host, realm);
+ }
+ @Override
+ public void onFormResubmission(WebView view, Message dontResend,
+ Message resend) {
+ mClient.onFormResubmission(view, dontResend, resend);
+ }
+ @Override
+ public void onReceivedError(WebView view, int errorCode,
+ String description, String failingUrl) {
+ mClient.onReceivedError(view, errorCode, description, failingUrl);
+ }
+ @Override
+ public boolean shouldOverrideKeyEvent(WebView view,
+ android.view.KeyEvent event) {
+ return mClient.shouldOverrideKeyEvent(view, event);
+ }
+ @Override
+ public void onUnhandledKeyEvent(WebView view,
+ android.view.KeyEvent event) {
+ mClient.onUnhandledKeyEvent(view, event);
+ }
+ }
+
+ // -------------------------------------------------------------------------
+ // WebChromeClient implementation for the sub window
+ // -------------------------------------------------------------------------
+
+ private class SubWindowChromeClient extends WebChromeClient {
+ // The main WebChromeClient.
+ private final WebChromeClient mClient;
+
+ SubWindowChromeClient(WebChromeClient client) {
+ mClient = client;
+ }
+ @Override
+ public void onProgressChanged(WebView view, int newProgress) {
+ mClient.onProgressChanged(view, newProgress);
+ }
+ @Override
+ public boolean onCreateWindow(WebView view, boolean dialog,
+ boolean userGesture, android.os.Message resultMsg) {
+ return mClient.onCreateWindow(view, dialog, userGesture, resultMsg);
+ }
+ @Override
+ public void onCloseWindow(WebView window) {
+ if (window != mSubView) {
+ Log.e(LOGTAG, "Can't close the window");
+ }
+ mActivity.dismissSubWindow(Tab.this);
+ }
+ }
+
+ // -------------------------------------------------------------------------
+
+ // Construct a new tab
+ Tab(BrowserActivity activity, WebView w, boolean closeOnExit, String appId,
+ String url) {
+ mActivity = activity;
+ mCloseOnExit = closeOnExit;
+ mAppId = appId;
+ mOriginalUrl = url;
+ mLockIconType = BrowserActivity.LOCK_ICON_UNSECURE;
+ mPrevLockIconType = BrowserActivity.LOCK_ICON_UNSECURE;
+ mInLoad = false;
+ mInForeground = false;
+
+ mInflateService = LayoutInflater.from(activity);
+
+ // The tab consists of a container view, which contains the main
+ // WebView, as well as any other UI elements associated with the tab.
+ mContainer = mInflateService.inflate(R.layout.tab, null);
+
+ mGeolocationPermissionsPrompt =
+ (GeolocationPermissionsPrompt) mContainer.findViewById(
+ R.id.geolocation_permissions_prompt);
+
+ setWebView(w);
+ }
+
+ /**
+ * Sets the WebView for this tab, correctly removing the old WebView from
+ * the container view.
+ */
+ void setWebView(WebView w) {
+ if (mMainView == w) {
+ return;
+ }
+ // If the WebView is changing, the page will be reloaded, so any ongoing
+ // Geolocation permission requests are void.
+ mGeolocationPermissionsPrompt.hide();
+
+ // Just remove the old one.
+ FrameLayout wrapper =
+ (FrameLayout) mContainer.findViewById(R.id.webview_wrapper);
+ wrapper.removeView(mMainView);
+
+ // set the new one
+ mMainView = w;
+ // attached the WebViewClient and WebChromeClient
+ if (mMainView != null) {
+ mMainView.setWebViewClient(mWebViewClient);
+ mMainView.setWebChromeClient(mWebChromeClient);
+ }
+ }
+
+ /**
+ * Destroy the tab's main WebView and subWindow if any
+ */
+ void destroy() {
+ if (mMainView != null) {
+ dismissSubWindow();
+ BrowserSettings.getInstance().deleteObserver(mMainView.getSettings());
+ // save the WebView to call destroy() after detach it from the tab
+ WebView webView = mMainView;
+ setWebView(null);
+ webView.destroy();
+ }
+ }
+
+ /**
+ * Remove the tab from the parent
+ */
+ void removeFromTree() {
+ // detach the children
+ if (mChildTabs != null) {
+ for(Tab t : mChildTabs) {
+ t.setParentTab(null);
+ }
+ }
+ // remove itself from the parent list
+ if (mParentTab != null) {
+ mParentTab.mChildTabs.remove(this);
+ }
+ }
+
+ /**
+ * Create a new subwindow unless a subwindow already exists.
+ * @return True if a new subwindow was created. False if one already exists.
+ */
+ boolean createSubWindow() {
+ if (mSubView == null) {
+ mSubViewContainer = mInflateService.inflate(
+ R.layout.browser_subwindow, null);
+ mSubView = (WebView) mSubViewContainer.findViewById(R.id.webview);
+ // use trackball directly
+ mSubView.setMapTrackballToArrowKeys(false);
+ mSubView.setWebViewClient(new SubWindowClient(mWebViewClient));
+ mSubView.setWebChromeClient(new SubWindowChromeClient(
+ mWebChromeClient));
+ mSubView.setDownloadListener(mActivity);
+ mSubView.setOnCreateContextMenuListener(mActivity);
+ final BrowserSettings s = BrowserSettings.getInstance();
+ s.addObserver(mSubView.getSettings()).update(s, null);
+ final ImageButton cancel = (ImageButton) mSubViewContainer
+ .findViewById(R.id.subwindow_close);
+ cancel.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ mSubView.getWebChromeClient().onCloseWindow(mSubView);
+ }
+ });
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Dismiss the subWindow for the tab.
+ */
+ void dismissSubWindow() {
+ if (mSubView != null) {
+ BrowserSettings.getInstance().deleteObserver(
+ mSubView.getSettings());
+ mSubView.destroy();
+ mSubView = null;
+ mSubViewContainer = null;
+ }
+ }
+
+ /**
+ * Attach the sub window to the content view.
+ */
+ void attachSubWindow(ViewGroup content) {
+ if (mSubView != null) {
+ content.addView(mSubViewContainer,
+ BrowserActivity.COVER_SCREEN_PARAMS);
+ }
+ }
+
+ /**
+ * Remove the sub window from the content view.
+ */
+ void removeSubWindow(ViewGroup content) {
+ if (mSubView != null) {
+ content.removeView(mSubViewContainer);
+ }
+ }
+
+ /**
+ * This method attaches both the WebView and any sub window to the
+ * given content view.
+ */
+ void attachTabToContentView(ViewGroup content) {
+ if (mMainView == null) {
+ return;
+ }
+
+ // Attach the WebView to the container and then attach the
+ // container to the content view.
+ FrameLayout wrapper =
+ (FrameLayout) mContainer.findViewById(R.id.webview_wrapper);
+ wrapper.addView(mMainView);
+ content.addView(mContainer, BrowserActivity.COVER_SCREEN_PARAMS);
+ attachSubWindow(content);
+ }
+
+ /**
+ * Remove the WebView and any sub window from the given content view.
+ */
+ void removeTabFromContentView(ViewGroup content) {
+ if (mMainView == null) {
+ return;
+ }
+
+ // Remove the container from the content and then remove the
+ // WebView from the container. This will trigger a focus change
+ // needed by WebView.
+ FrameLayout wrapper =
+ (FrameLayout) mContainer.findViewById(R.id.webview_wrapper);
+ wrapper.removeView(mMainView);
+ content.removeView(mContainer);
+ removeSubWindow(content);
+ }
+
+ /**
+ * Set the parent tab of this tab.
+ */
+ void setParentTab(Tab parent) {
+ mParentTab = parent;
+ // This tab may have been freed due to low memory. If that is the case,
+ // the parent tab index is already saved. If we are changing that index
+ // (most likely due to removing the parent tab) we must update the
+ // parent tab index in the saved Bundle.
+ if (mSavedState != null) {
+ if (parent == null) {
+ mSavedState.remove(PARENTTAB);
+ } else {
+ mSavedState.putInt(PARENTTAB, mActivity.getTabControl()
+ .getTabIndex(parent));
+ }
+ }
+ }
+
+ /**
+ * When a Tab is created through the content of another Tab, then we
+ * associate the Tabs.
+ * @param child the Tab that was created from this Tab
+ */
+ void addChildTab(Tab child) {
+ if (mChildTabs == null) {
+ mChildTabs = new Vector<Tab>();
+ }
+ mChildTabs.add(child);
+ child.setParentTab(this);
+ }
+
+ Vector<Tab> getChildTabs() {
+ return mChildTabs;
+ }
+
+ void resume() {
+ if (mMainView != null) {
+ mMainView.onResume();
+ if (mSubView != null) {
+ mSubView.onResume();
+ }
+ }
+ }
+
+ void pause() {
+ if (mMainView != null) {
+ mMainView.onPause();
+ if (mSubView != null) {
+ mSubView.onPause();
+ }
+ }
+ }
+
+ void putInForeground() {
+ mInForeground = true;
+ resume();
+ mMainView.setOnCreateContextMenuListener(mActivity);
+ if (mSubView != null) {
+ mSubView.setOnCreateContextMenuListener(mActivity);
+ }
+ // Show the pending error dialog if the queue is not empty
+ if (mQueuedErrors != null && mQueuedErrors.size() > 0) {
+ showError(mQueuedErrors.getFirst());
+ }
+ }
+
+ void putInBackground() {
+ mInForeground = false;
+ pause();
+ mMainView.setOnCreateContextMenuListener(null);
+ if (mSubView != null) {
+ mSubView.setOnCreateContextMenuListener(null);
+ }
+ }
+
+ /**
+ * Return the top window of this tab; either the subwindow if it is not
+ * null or the main window.
+ * @return The top window of this tab.
+ */
+ WebView getTopWindow() {
+ if (mSubView != null) {
+ return mSubView;
+ }
+ return mMainView;
+ }
+
+ /**
+ * Return the main window of this tab. Note: if a tab is freed in the
+ * background, this can return null. It is only guaranteed to be
+ * non-null for the current tab.
+ * @return The main WebView of this tab.
+ */
+ WebView getWebView() {
+ return mMainView;
+ }
+
+ /**
+ * Return the subwindow of this tab or null if there is no subwindow.
+ * @return The subwindow of this tab or null.
+ */
+ WebView getSubWebView() {
+ return mSubView;
+ }
+
+ /**
+ * @return The geolocation permissions prompt for this tab.
+ */
+ GeolocationPermissionsPrompt getGeolocationPermissionsPrompt() {
+ return mGeolocationPermissionsPrompt;
+ }
+
+ /**
+ * @return The application id string
+ */
+ String getAppId() {
+ return mAppId;
+ }
+
+ /**
+ * Set the application id string
+ * @param id
+ */
+ void setAppId(String id) {
+ mAppId = id;
+ }
+
+ /**
+ * @return The original url associated with this Tab
+ */
+ String getOriginalUrl() {
+ return mOriginalUrl;
+ }
+
+ /**
+ * Set the original url associated with this tab
+ */
+ void setOriginalUrl(String url) {
+ mOriginalUrl = url;
+ }
+
+ /**
+ * Get the url of this tab. Valid after calling populatePickerData, but
+ * before calling wipePickerData, or if the webview has been destroyed.
+ * @return The WebView's url or null.
+ */
+ String getUrl() {
+ if (mPickerData != null) {
+ return mPickerData.mUrl;
+ }
+ return null;
+ }
+
+ /**
+ * Get the title of this tab. Valid after calling populatePickerData, but
+ * before calling wipePickerData, or if the webview has been destroyed. If
+ * the url has no title, use the url instead.
+ * @return The WebView's title (or url) or null.
+ */
+ String getTitle() {
+ if (mPickerData != null) {
+ return mPickerData.mTitle;
+ }
+ return null;
+ }
+
+ /**
+ * Get the favicon of this tab. Valid after calling populatePickerData, but
+ * before calling wipePickerData, or if the webview has been destroyed.
+ * @return The WebView's favicon or null.
+ */
+ Bitmap getFavicon() {
+ if (mPickerData != null) {
+ return mPickerData.mFavicon;
+ }
+ return null;
+ }
+
+ /**
+ * Return the tab's error console. Creates the console if createIfNEcessary
+ * is true and we haven't already created the console.
+ * @param createIfNecessary Flag to indicate if the console should be
+ * created if it has not been already.
+ * @return The tab's error console, or null if one has not been created and
+ * createIfNecessary is false.
+ */
+ ErrorConsoleView getErrorConsole(boolean createIfNecessary) {
+ if (createIfNecessary && mErrorConsole == null) {
+ mErrorConsole = new ErrorConsoleView(mActivity);
+ mErrorConsole.setWebView(mMainView);
+ }
+ return mErrorConsole;
+ }
+
+ /**
+ * If this Tab was created through another Tab, then this method returns
+ * that Tab.
+ * @return the Tab parent or null
+ */
+ public Tab getParentTab() {
+ return mParentTab;
+ }
+
+ /**
+ * Return whether this tab should be closed when it is backing out of the
+ * first page.
+ * @return TRUE if this tab should be closed when exit.
+ */
+ boolean closeOnExit() {
+ return mCloseOnExit;
+ }
+
+ /**
+ * Saves the current lock-icon state before resetting the lock icon. If we
+ * have an error, we may need to roll back to the previous state.
+ */
+ void resetLockIcon(String url) {
+ mPrevLockIconType = mLockIconType;
+ mLockIconType = BrowserActivity.LOCK_ICON_UNSECURE;
+ if (URLUtil.isHttpsUrl(url)) {
+ mLockIconType = BrowserActivity.LOCK_ICON_SECURE;
+ }
+ }
+
+ /**
+ * Reverts the lock-icon state to the last saved state, for example, if we
+ * had an error, and need to cancel the load.
+ */
+ void revertLockIcon() {
+ mLockIconType = mPrevLockIconType;
+ }
+
+ /**
+ * @return The tab's lock icon type.
+ */
+ int getLockIconType() {
+ return mLockIconType;
+ }
+
+ /**
+ * @return TRUE if onPageStarted is called while onPageFinished is not
+ * called yet.
+ */
+ boolean inLoad() {
+ return mInLoad;
+ }
+
+ // force mInLoad to be false. This should only be called before closing the
+ // tab to ensure BrowserActivity's pauseWebViewTimers() is called correctly.
+ void clearInLoad() {
+ mInLoad = false;
+ }
+
+ void populatePickerData() {
+ if (mMainView == null) {
+ populatePickerDataFromSavedState();
+ return;
+ }
+
+ // FIXME: The only place we cared about subwindow was for
+ // bookmarking (i.e. not when saving state). Was this deliberate?
+ final WebBackForwardList list = mMainView.copyBackForwardList();
+ final WebHistoryItem item = list != null ? list.getCurrentItem() : null;
+ populatePickerData(item);
+ }
+
+ // Populate the picker data using the given history item and the current top
+ // WebView.
+ private void populatePickerData(WebHistoryItem item) {
+ mPickerData = new PickerData();
+ if (item != null) {
+ mPickerData.mUrl = item.getUrl();
+ mPickerData.mTitle = item.getTitle();
+ mPickerData.mFavicon = item.getFavicon();
+ if (mPickerData.mTitle == null) {
+ mPickerData.mTitle = mPickerData.mUrl;
+ }
+ }
+ }
+
+ // Create the PickerData and populate it using the saved state of the tab.
+ void populatePickerDataFromSavedState() {
+ if (mSavedState == null) {
+ return;
+ }
+ mPickerData = new PickerData();
+ mPickerData.mUrl = mSavedState.getString(CURRURL);
+ mPickerData.mTitle = mSavedState.getString(CURRTITLE);
+ }
+
+ void clearPickerData() {
+ mPickerData = null;
+ }
+
+ /**
+ * Get the saved state bundle.
+ * @return
+ */
+ Bundle getSavedState() {
+ return mSavedState;
+ }
+
+ /**
+ * Set the saved state.
+ */
+ void setSavedState(Bundle state) {
+ mSavedState = state;
+ }
+
+ /**
+ * @return TRUE if succeed in saving the state.
+ */
+ boolean saveState() {
+ // If the WebView is null it means we ran low on memory and we already
+ // stored the saved state in mSavedState.
+ if (mMainView == null) {
+ return mSavedState != null;
+ }
+
+ mSavedState = new Bundle();
+ final WebBackForwardList list = mMainView.saveState(mSavedState);
+ if (list != null) {
+ final File f = new File(mActivity.getTabControl().getThumbnailDir(),
+ mMainView.hashCode() + "_pic.save");
+ if (mMainView.savePicture(mSavedState, f)) {
+ mSavedState.putString(CURRPICTURE, f.getPath());
+ }
+ }
+
+ // Store some extra info for displaying the tab in the picker.
+ final WebHistoryItem item = list != null ? list.getCurrentItem() : null;
+ populatePickerData(item);
+
+ if (mPickerData.mUrl != null) {
+ mSavedState.putString(CURRURL, mPickerData.mUrl);
+ }
+ if (mPickerData.mTitle != null) {
+ mSavedState.putString(CURRTITLE, mPickerData.mTitle);
+ }
+ mSavedState.putBoolean(CLOSEONEXIT, mCloseOnExit);
+ if (mAppId != null) {
+ mSavedState.putString(APPID, mAppId);
+ }
+ if (mOriginalUrl != null) {
+ mSavedState.putString(ORIGINALURL, mOriginalUrl);
+ }
+ // Remember the parent tab so the relationship can be restored.
+ if (mParentTab != null) {
+ mSavedState.putInt(PARENTTAB, mActivity.getTabControl().getTabIndex(
+ mParentTab));
+ }
+ return true;
+ }
+
+ /*
+ * Restore the state of the tab.
+ */
+ boolean restoreState(Bundle b) {
+ if (b == null) {
+ return false;
+ }
+ // Restore the internal state even if the WebView fails to restore.
+ // This will maintain the app id, original url and close-on-exit values.
+ mSavedState = null;
+ mPickerData = null;
+ mCloseOnExit = b.getBoolean(CLOSEONEXIT);
+ mAppId = b.getString(APPID);
+ mOriginalUrl = b.getString(ORIGINALURL);
+
+ final WebBackForwardList list = mMainView.restoreState(b);
+ if (list == null) {
+ return false;
+ }
+ if (b.containsKey(CURRPICTURE)) {
+ final File f = new File(b.getString(CURRPICTURE));
+ mMainView.restorePicture(b, f);
+ f.delete();
+ }
+ return true;
+ }
+}
diff --git a/src/com/android/browser/TabControl.java b/src/com/android/browser/TabControl.java
index 2f15a9c..8373182 100644
--- a/src/com/android/browser/TabControl.java
+++ b/src/com/android/browser/TabControl.java
@@ -16,33 +16,13 @@
package com.android.browser;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Picture;
-import android.net.http.SslError;
import android.os.Bundle;
-import android.os.Message;
import android.util.Log;
-import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
-import android.view.View.OnClickListener;
-import android.webkit.HttpAuthHandler;
-import android.webkit.JsPromptResult;
-import android.webkit.JsResult;
-import android.webkit.SslErrorHandler;
import android.webkit.WebBackForwardList;
-import android.webkit.WebChromeClient;
-import android.webkit.WebHistoryItem;
import android.webkit.WebView;
-import android.webkit.WebViewClient;
-import android.widget.FrameLayout;
-import android.widget.ImageButton;
-import android.widget.LinearLayout;
import java.io.File;
-import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Vector;
@@ -50,13 +30,7 @@
// Log Tag
private static final String LOGTAG = "TabControl";
// Maximum number of tabs.
- static final int MAX_TABS = 8;
- // Static instance of an empty callback.
- private static final WebViewClient mEmptyClient =
- new WebViewClient();
- // Instance of BackgroundChromeClient for background tabs.
- private final BackgroundChromeClient mBackgroundChromeClient =
- new BackgroundChromeClient();
+ private static final int MAX_TABS = 8;
// Private array of WebViews that are used as tabs.
private ArrayList<Tab> mTabs = new ArrayList<Tab>(MAX_TABS);
// Queue of most recently viewed tabs.
@@ -66,393 +40,6 @@
// A private instance of BrowserActivity to interface with when adding and
// switching between tabs.
private final BrowserActivity mActivity;
- // Inflation service for making subwindows.
- private final LayoutInflater mInflateService;
- // Subclass of WebViewClient used in subwindows to notify the main
- // WebViewClient of certain WebView activities.
- private static class SubWindowClient extends WebViewClient {
- // The main WebViewClient.
- private final WebViewClient mClient;
-
- SubWindowClient(WebViewClient client) {
- mClient = client;
- }
- @Override
- public void doUpdateVisitedHistory(WebView view, String url,
- boolean isReload) {
- mClient.doUpdateVisitedHistory(view, url, isReload);
- }
- @Override
- public boolean shouldOverrideUrlLoading(WebView view, String url) {
- return mClient.shouldOverrideUrlLoading(view, url);
- }
- @Override
- public void onReceivedSslError(WebView view, SslErrorHandler handler,
- SslError error) {
- mClient.onReceivedSslError(view, handler, error);
- }
- @Override
- public void onReceivedHttpAuthRequest(WebView view,
- HttpAuthHandler handler, String host, String realm) {
- mClient.onReceivedHttpAuthRequest(view, handler, host, realm);
- }
- @Override
- public void onFormResubmission(WebView view, Message dontResend,
- Message resend) {
- mClient.onFormResubmission(view, dontResend, resend);
- }
- @Override
- public void onReceivedError(WebView view, int errorCode,
- String description, String failingUrl) {
- mClient.onReceivedError(view, errorCode, description, failingUrl);
- }
- @Override
- public boolean shouldOverrideKeyEvent(WebView view,
- android.view.KeyEvent event) {
- return mClient.shouldOverrideKeyEvent(view, event);
- }
- @Override
- public void onUnhandledKeyEvent(WebView view,
- android.view.KeyEvent event) {
- mClient.onUnhandledKeyEvent(view, event);
- }
- }
- // Subclass of WebChromeClient to display javascript dialogs.
- private class SubWindowChromeClient extends WebChromeClient {
- // This subwindow's tab.
- private final Tab mTab;
- // The main WebChromeClient.
- private final WebChromeClient mClient;
-
- SubWindowChromeClient(Tab t, WebChromeClient client) {
- mTab = t;
- mClient = client;
- }
- @Override
- public void onProgressChanged(WebView view, int newProgress) {
- mClient.onProgressChanged(view, newProgress);
- }
- @Override
- public boolean onCreateWindow(WebView view, boolean dialog,
- boolean userGesture, android.os.Message resultMsg) {
- return mClient.onCreateWindow(view, dialog, userGesture, resultMsg);
- }
- @Override
- public void onCloseWindow(WebView window) {
- if (Browser.DEBUG && window != mTab.mSubView) {
- throw new AssertionError("Can't close the window");
- }
- mActivity.dismissSubWindow(mTab);
- }
- }
- // Background WebChromeClient for focusing tabs
- private class BackgroundChromeClient extends WebChromeClient {
- @Override
- public void onRequestFocus(WebView view) {
- Tab t = getTabFromView(view);
- if (t != getCurrentTab()) {
- mActivity.switchToTab(getTabIndex(t));
- }
- }
- }
-
- // Extra saved information for displaying the tab in the picker.
- public static class PickerData {
- String mUrl;
- String mTitle;
- Bitmap mFavicon;
- float mScale;
- int mScrollX;
- int mScrollY;
- }
-
- /**
- * Private class for maintaining Tabs with a main WebView and a subwindow.
- */
- public class Tab {
- // The Geolocation permissions prompt
- private GeolocationPermissionsPrompt mGeolocationPermissionsPrompt;
- private View mContainer;
- // Main WebView
- private WebView mMainView;
- // Subwindow WebView
- private WebView mSubView;
- // Subwindow container
- private View mSubViewContainer;
- // Subwindow callback
- private SubWindowClient mSubViewClient;
- // Subwindow chrome callback
- private SubWindowChromeClient mSubViewChromeClient;
- // Saved bundle for when we are running low on memory. It contains the
- // information needed to restore the WebView if the user goes back to
- // the tab.
- private Bundle mSavedState;
- // Data used when displaying the tab in the picker.
- private PickerData mPickerData;
-
- // Parent Tab. This is the Tab that created this Tab, or null
- // if the Tab was created by the UI
- private Tab mParentTab;
- // Tab that constructed by this Tab. This is used when this
- // Tab is destroyed, it clears all mParentTab values in the
- // children.
- private Vector<Tab> mChildTabs;
-
- private Boolean mCloseOnExit;
- // Application identifier used to find tabs that another application
- // wants to reuse.
- private String mAppId;
- // Keep the original url around to avoid killing the old WebView if the
- // url has not changed.
- private String mOriginalUrl;
-
- private ErrorConsoleView mErrorConsole;
- // the lock icon type and previous lock icon type for the tab
- private int mSavedLockIconType;
- private int mSavedPrevLockIconType;
-
- // Construct a new tab
- private Tab(WebView w, boolean closeOnExit, String appId, String url, Context context) {
- mCloseOnExit = closeOnExit;
- mAppId = appId;
- mOriginalUrl = url;
- mSavedLockIconType = BrowserActivity.LOCK_ICON_UNSECURE;
- mSavedPrevLockIconType = BrowserActivity.LOCK_ICON_UNSECURE;
-
- // The tab consists of a container view, which contains the main
- // WebView, as well as any other UI elements associated with the tab.
- LayoutInflater factory = LayoutInflater.from(context);
- mContainer = factory.inflate(R.layout.tab, null);
-
- mGeolocationPermissionsPrompt =
- (GeolocationPermissionsPrompt) mContainer.findViewById(
- R.id.geolocation_permissions_prompt);
-
- setWebView(w);
- }
-
- /**
- * Sets the WebView for this tab, correctly removing the old WebView
- * from the container view.
- */
- public void setWebView(WebView w) {
- if (mMainView == w) {
- return;
- }
- // If the WebView is changing, the page will be reloaded, so any ongoing Geolocation
- // permission requests are void.
- mGeolocationPermissionsPrompt.hide();
-
- // Just remove the old one.
- FrameLayout wrapper =
- (FrameLayout) mContainer.findViewById(R.id.webview_wrapper);
- wrapper.removeView(mMainView);
- mMainView = w;
- }
-
- /**
- * This method attaches both the WebView and any sub window to the
- * given content view.
- */
- public void attachTabToContentView(ViewGroup content) {
- if (mMainView == null) {
- return;
- }
-
- // Attach the WebView to the container and then attach the
- // container to the content view.
- FrameLayout wrapper =
- (FrameLayout) mContainer.findViewById(R.id.webview_wrapper);
- wrapper.addView(mMainView);
- content.addView(mContainer, BrowserActivity.COVER_SCREEN_PARAMS);
- attachSubWindow(content);
- }
-
- /**
- * Remove the WebView and any sub window from the given content view.
- */
- public void removeTabFromContentView(ViewGroup content) {
- if (mMainView == null) {
- return;
- }
-
- // Remove the container from the content and then remove the
- // WebView from the container. This will trigger a focus change
- // needed by WebView.
- FrameLayout wrapper =
- (FrameLayout) mContainer.findViewById(R.id.webview_wrapper);
- wrapper.removeView(mMainView);
- content.removeView(mContainer);
- removeSubWindow(content);
- }
-
- /**
- * Attach the sub window to the content view.
- */
- public void attachSubWindow(ViewGroup content) {
- if (mSubView != null) {
- content.addView(mSubViewContainer,
- BrowserActivity.COVER_SCREEN_PARAMS);
- }
- }
-
- /**
- * Remove the sub window from the content view.
- */
- public void removeSubWindow(ViewGroup content) {
- if (mSubView != null) {
- content.removeView(mSubViewContainer);
- }
- }
-
- /**
- * Return the top window of this tab; either the subwindow if it is not
- * null or the main window.
- * @return The top window of this tab.
- */
- public WebView getTopWindow() {
- if (mSubView != null) {
- return mSubView;
- }
- return mMainView;
- }
-
- /**
- * Return the main window of this tab. Note: if a tab is freed in the
- * background, this can return null. It is only guaranteed to be
- * non-null for the current tab.
- * @return The main WebView of this tab.
- */
- public WebView getWebView() {
- return mMainView;
- }
-
- /**
- * @return The geolocation permissions prompt for this tab.
- */
- public GeolocationPermissionsPrompt getGeolocationPermissionsPrompt() {
- return mGeolocationPermissionsPrompt;
- }
-
- /**
- * Return the subwindow of this tab or null if there is no subwindow.
- * @return The subwindow of this tab or null.
- */
- public WebView getSubWebView() {
- return mSubView;
- }
-
- /**
- * Get the url of this tab. Valid after calling populatePickerData, but
- * before calling wipePickerData, or if the webview has been destroyed.
- *
- * @return The WebView's url or null.
- */
- public String getUrl() {
- if (mPickerData != null) {
- return mPickerData.mUrl;
- }
- return null;
- }
-
- /**
- * Get the title of this tab. Valid after calling populatePickerData,
- * but before calling wipePickerData, or if the webview has been
- * destroyed. If the url has no title, use the url instead.
- *
- * @return The WebView's title (or url) or null.
- */
- public String getTitle() {
- if (mPickerData != null) {
- return mPickerData.mTitle;
- }
- return null;
- }
-
- public Bitmap getFavicon() {
- if (mPickerData != null) {
- return mPickerData.mFavicon;
- }
- return null;
- }
-
- private void setParentTab(Tab parent) {
- mParentTab = parent;
- // This tab may have been freed due to low memory. If that is the
- // case, the parent tab index is already saved. If we are changing
- // that index (most likely due to removing the parent tab) we must
- // update the parent tab index in the saved Bundle.
- if (mSavedState != null) {
- if (parent == null) {
- mSavedState.remove(PARENTTAB);
- } else {
- mSavedState.putInt(PARENTTAB, getTabIndex(parent));
- }
- }
- }
-
- /**
- * When a Tab is created through the content of another Tab, then
- * we associate the Tabs.
- * @param child the Tab that was created from this Tab
- */
- public void addChildTab(Tab child) {
- if (mChildTabs == null) {
- mChildTabs = new Vector<Tab>();
- }
- mChildTabs.add(child);
- child.setParentTab(this);
- }
-
- private void removeFromTree() {
- // detach the children
- if (mChildTabs != null) {
- for(Tab t : mChildTabs) {
- t.setParentTab(null);
- }
- }
-
- // Find myself in my parent list
- if (mParentTab != null) {
- mParentTab.mChildTabs.remove(this);
- }
- }
-
- /**
- * If this Tab was created through another Tab, then this method
- * returns that Tab.
- * @return the Tab parent or null
- */
- public Tab getParentTab() {
- return mParentTab;
- }
-
- /**
- * Return whether this tab should be closed when it is backing out of
- * the first page.
- * @return TRUE if this tab should be closed when exit.
- */
- public boolean closeOnExit() {
- return mCloseOnExit;
- }
-
- void setLockIconType(int type) {
- mSavedLockIconType = type;
- }
-
- int getLockIconType() {
- return mSavedLockIconType;
- }
-
- void setPrevLockIconType(int type) {
- mSavedPrevLockIconType = type;
- }
-
- int getPrevLockIconType() {
- return mSavedPrevLockIconType;
- }
- };
-
// Directory to store thumbnails for each WebView.
private final File mThumbnailDir;
@@ -464,9 +51,6 @@
*/
TabControl(BrowserActivity activity) {
mActivity = activity;
- mInflateService =
- ((LayoutInflater) activity.getSystemService(
- Context.LAYOUT_INFLATER_SERVICE));
mThumbnailDir = activity.getDir("thumbnails", 0);
}
@@ -488,29 +72,7 @@
if (t == null) {
return null;
}
- return t.mMainView;
- }
-
- /**
- * Return the current tab's error console. Creates the console if createIfNEcessary
- * is true and we haven't already created the console.
- * @param createIfNecessary Flag to indicate if the console should be created if it has
- * not been already.
- * @return The current tab's error console, or null if one has not been created and
- * createIfNecessary is false.
- */
- ErrorConsoleView getCurrentErrorConsole(boolean createIfNecessary) {
- Tab t = getTab(mCurrentTab);
- if (t == null) {
- return null;
- }
-
- if (createIfNecessary && t.mErrorConsole == null) {
- t.mErrorConsole = new ErrorConsoleView(mActivity);
- t.mErrorConsole.setWebView(t.mMainView);
- }
-
- return t.mErrorConsole;
+ return t.getWebView();
}
/**
@@ -523,7 +85,7 @@
if (t == null) {
return null;
}
- return t.mSubView != null ? t.mSubView : t.mMainView;
+ return t.getTopWindow();
}
/**
@@ -535,7 +97,7 @@
if (t == null) {
return null;
}
- return t.mSubView;
+ return t.getSubWebView();
}
/**
@@ -578,6 +140,10 @@
return mTabs.indexOf(tab);
}
+ boolean canCreateNewTab() {
+ return MAX_TABS != mTabs.size();
+ }
+
/**
* Create a new tab.
* @return The newly createTab or null if we have reached the maximum
@@ -592,10 +158,10 @@
final WebView w = createNewWebView();
// Create a new tab and add it to the tab list
- Tab t = new Tab(w, closeOnExit, appId, url, mActivity);
+ Tab t = new Tab(mActivity, w, closeOnExit, appId, url);
mTabs.add(t);
// Initially put the tab in the background.
- putTabInBackground(t);
+ t.putInBackground();
return t;
}
@@ -616,86 +182,51 @@
if (t == null) {
return false;
}
+
// Only remove the tab if it is the current one.
if (getCurrentTab() == t) {
- putTabInBackground(t);
+ t.putInBackground();
+ mCurrentTab = -1;
}
- // Only destroy the WebView if it still exists.
- if (t.mMainView != null) {
- // Take down the sub window.
- dismissSubWindow(t);
- // Remove the WebView's settings from the BrowserSettings list of
- // observers.
- BrowserSettings.getInstance().deleteObserver(
- t.mMainView.getSettings());
- WebView w = t.mMainView;
- t.setWebView(null);
- // Destroy the main view
- w.destroy();
- }
+ // destroy the tab
+ t.destroy();
// clear it's references to parent and children
t.removeFromTree();
-
// Remove it from our list of tabs.
mTabs.remove(t);
// The tab indices have shifted, update all the saved state so we point
// to the correct index.
for (Tab tab : mTabs) {
- if (tab.mChildTabs != null) {
- for (Tab child : tab.mChildTabs) {
+ Vector<Tab> children = tab.getChildTabs();
+ if (children != null) {
+ for (Tab child : children) {
child.setParentTab(tab);
}
}
}
-
// This tab may have been pushed in to the background and then closed.
// If the saved state contains a picture file, delete the file.
- if (t.mSavedState != null) {
- if (t.mSavedState.containsKey(CURRPICTURE)) {
- new File(t.mSavedState.getString(CURRPICTURE)).delete();
+ Bundle savedState = t.getSavedState();
+ if (savedState != null) {
+ if (savedState.containsKey(Tab.CURRPICTURE)) {
+ new File(savedState.getString(Tab.CURRPICTURE)).delete();
}
}
// Remove it from the queue of viewed tabs.
mTabQueue.remove(t);
- mCurrentTab = -1;
return true;
}
/**
- * Clear the back/forward list for all the current tabs.
- */
- void clearHistory() {
- int size = getTabCount();
- for (int i = 0; i < size; i++) {
- Tab t = mTabs.get(i);
- // TODO: if a tab is freed due to low memory, its history is not
- // cleared here.
- if (t.mMainView != null) {
- t.mMainView.clearHistory();
- }
- if (t.mSubView != null) {
- t.mSubView.clearHistory();
- }
- }
- }
-
- /**
* Destroy all the tabs and subwindows
*/
void destroy() {
- BrowserSettings s = BrowserSettings.getInstance();
for (Tab t : mTabs) {
- if (t.mMainView != null) {
- dismissSubWindow(t);
- s.deleteObserver(t.mMainView.getSettings());
- WebView w = t.mMainView;
- t.setWebView(null);
- w.destroy();
- }
+ t.destroy();
}
mTabs.clear();
mTabQueue.clear();
@@ -709,17 +240,6 @@
return mTabs.size();
}
- // Used for saving and restoring each Tab
- private static final String WEBVIEW = "webview";
- private static final String NUMTABS = "numTabs";
- private static final String CURRTAB = "currentTab";
- private static final String CURRURL = "currentUrl";
- private static final String CURRTITLE = "currentTitle";
- private static final String CURRPICTURE = "currentPicture";
- private static final String CLOSEONEXIT = "closeonexit";
- private static final String PARENTTAB = "parentTab";
- private static final String APPID = "appid";
- private static final String ORIGINALURL = "originalUrl";
/**
* Save the state of all the Tabs.
@@ -727,13 +247,13 @@
*/
void saveState(Bundle outState) {
final int numTabs = getTabCount();
- outState.putInt(NUMTABS, numTabs);
+ outState.putInt(Tab.NUMTABS, numTabs);
final int index = getCurrentIndex();
- outState.putInt(CURRTAB, (index >= 0 && index < numTabs) ? index : 0);
+ outState.putInt(Tab.CURRTAB, (index >= 0 && index < numTabs) ? index : 0);
for (int i = 0; i < numTabs; i++) {
final Tab t = getTab(i);
- if (saveState(t)) {
- outState.putBundle(WEBVIEW + i, t.mSavedState);
+ if (t.saveState()) {
+ outState.putBundle(Tab.WEBVIEW + i, t.getSavedState());
}
}
}
@@ -746,33 +266,34 @@
*/
boolean restoreState(Bundle inState) {
final int numTabs = (inState == null)
- ? -1 : inState.getInt(NUMTABS, -1);
+ ? -1 : inState.getInt(Tab.NUMTABS, -1);
if (numTabs == -1) {
return false;
} else {
- final int currentTab = inState.getInt(CURRTAB, -1);
+ final int currentTab = inState.getInt(Tab.CURRTAB, -1);
for (int i = 0; i < numTabs; i++) {
if (i == currentTab) {
Tab t = createNewTab();
// Me must set the current tab before restoring the state
// so that all the client classes are set.
setCurrentTab(t);
- if (!restoreState(inState.getBundle(WEBVIEW + i), t)) {
+ if (!t.restoreState(inState.getBundle(Tab.WEBVIEW + i))) {
Log.w(LOGTAG, "Fail in restoreState, load home page.");
- t.mMainView.loadUrl(BrowserSettings.getInstance()
+ t.getWebView().loadUrl(BrowserSettings.getInstance()
.getHomePage());
}
} else {
// Create a new tab and don't restore the state yet, add it
// to the tab list
- Tab t = new Tab(null, false, null, null, mActivity);
- t.mSavedState = inState.getBundle(WEBVIEW + i);
- if (t.mSavedState != null) {
- populatePickerDataFromSavedState(t);
+ Tab t = new Tab(mActivity, null, false, null, null);
+ Bundle state = inState.getBundle(Tab.WEBVIEW + i);
+ if (state != null) {
+ t.setSavedState(state);
+ t.populatePickerDataFromSavedState();
// Need to maintain the app id and original url so we
// can possibly reuse this tab.
- t.mAppId = t.mSavedState.getString(APPID);
- t.mOriginalUrl = t.mSavedState.getString(ORIGINALURL);
+ t.setAppId(state.getString(Tab.APPID));
+ t.setOriginalUrl(state.getString(Tab.ORIGINALURL));
}
mTabs.add(t);
mTabQueue.add(t);
@@ -781,10 +302,10 @@
// Rebuild the tree of tabs. Do this after all tabs have been
// created/restored so that the parent tab exists.
for (int i = 0; i < numTabs; i++) {
- final Bundle b = inState.getBundle(WEBVIEW + i);
+ final Bundle b = inState.getBundle(Tab.WEBVIEW + i);
final Tab t = getTab(i);
if (b != null && t != null) {
- final int parentIndex = b.getInt(PARENTTAB, -1);
+ final int parentIndex = b.getInt(Tab.PARENTTAB, -1);
if (parentIndex != -1) {
final Tab parent = getTab(parentIndex);
if (parent != null) {
@@ -808,9 +329,10 @@
Tab t = getLeastUsedTab(getCurrentTab());
if (t != null) {
Log.w(LOGTAG, "Free a tab in the browser");
- freeTab(t);
- // force a gc
- System.gc();
+ // store the WebView's state.
+ t.saveState();
+ // destroy the tab
+ t.destroy();
return;
}
@@ -820,8 +342,6 @@
if (view != null) {
view.freeMemory();
}
- // force a gc
- System.gc();
}
private Tab getLeastUsedTab(Tab current) {
@@ -831,7 +351,7 @@
return null;
}
- // Rip through the queue starting at the beginning and teardown the
+ // Rip through the queue starting at the beginning and tear down the
// next available tab.
Tab t = null;
int i = 0;
@@ -842,69 +362,18 @@
do {
t = mTabQueue.get(i++);
} while (i < queueSize
- && ((t != null && t.mMainView == null)
- || t == current.mParentTab));
+ && ((t != null && t.getWebView() == null)
+ || t == current.getParentTab()));
// Don't do anything if the last remaining tab is the current one or if
// the last tab has been freed already.
- if (t == current || t.mMainView == null) {
+ if (t == current || t.getWebView() == null) {
return null;
}
return t;
}
- private void freeTab(Tab t) {
- // Store the WebView's state.
- saveState(t);
-
- // Tear down the tab.
- dismissSubWindow(t);
- // Remove the WebView's settings from the BrowserSettings list of
- // observers.
- BrowserSettings.getInstance().deleteObserver(t.mMainView.getSettings());
- WebView w = t.mMainView;
- t.setWebView(null);
- w.destroy();
- }
-
- /**
- * Create a new subwindow unless a subwindow already exists.
- * @return True if a new subwindow was created. False if one already exists.
- */
- void createSubWindow() {
- Tab t = getTab(mCurrentTab);
- if (t != null && t.mSubView == null) {
- final View v = mInflateService.inflate(R.layout.browser_subwindow, null);
- final WebView w = (WebView) v.findViewById(R.id.webview);
- w.setMapTrackballToArrowKeys(false); // use trackball directly
- final SubWindowClient subClient =
- new SubWindowClient(mActivity.getWebViewClient());
- final SubWindowChromeClient subChromeClient =
- new SubWindowChromeClient(t,
- mActivity.getWebChromeClient());
- w.setWebViewClient(subClient);
- w.setWebChromeClient(subChromeClient);
- w.setDownloadListener(mActivity);
- w.setOnCreateContextMenuListener(mActivity);
- final BrowserSettings s = BrowserSettings.getInstance();
- s.addObserver(w.getSettings()).update(s, null);
- t.mSubView = w;
- t.mSubViewClient = subClient;
- t.mSubViewChromeClient = subChromeClient;
- // FIXME: I really hate having to know the name of the view
- // containing the webview.
- t.mSubViewContainer = v.findViewById(R.id.subwindow_container);
- final ImageButton cancel =
- (ImageButton) v.findViewById(R.id.subwindow_close);
- cancel.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- subChromeClient.onCloseWindow(w);
- }
- });
- }
- }
-
/**
* Show the tab that contains the given WebView.
* @param view The WebView used to find the tab.
@@ -913,7 +382,7 @@
final int size = getTabCount();
for (int i = 0; i < size; i++) {
final Tab t = getTab(i);
- if (t.mSubView == view || t.mMainView == view) {
+ if (t.getSubWebView() == view || t.getWebView() == view) {
return t;
}
}
@@ -931,22 +400,42 @@
final int size = getTabCount();
for (int i = 0; i < size; i++) {
final Tab t = getTab(i);
- if (id.equals(t.mAppId)) {
+ if (id.equals(t.getAppId())) {
return t;
}
}
return null;
}
+ /**
+ * Stop loading in all opened WebView including subWindows.
+ */
+ void stopAllLoading() {
+ final int size = getTabCount();
+ for (int i = 0; i < size; i++) {
+ final Tab t = getTab(i);
+ final WebView webview = t.getWebView();
+ if (webview != null) {
+ webview.stopLoading();
+ }
+ final WebView subview = t.getSubWebView();
+ if (subview != null) {
+ webview.stopLoading();
+ }
+ }
+ }
+
// This method checks if a non-app tab (one created within the browser)
// matches the given url.
private boolean tabMatchesUrl(Tab t, String url) {
- if (t.mAppId != null) {
+ if (t.getAppId() != null) {
return false;
- } else if (t.mMainView == null) {
+ }
+ WebView webview = t.getWebView();
+ if (webview == null) {
return false;
- } else if (url.equals(t.mMainView.getUrl()) ||
- url.equals(t.mMainView.getOriginalUrl())) {
+ } else if (url.equals(webview.getUrl())
+ || url.equals(webview.getOriginalUrl())) {
return true;
}
return false;
@@ -982,9 +471,9 @@
* was deleted.
*/
boolean recreateWebView(Tab t, String url) {
- final WebView w = t.mMainView;
+ final WebView w = t.getWebView();
if (w != null) {
- if (url != null && url.equals(t.mOriginalUrl)) {
+ if (url != null && url.equals(t.getOriginalUrl())) {
// The original url matches the current url. Just go back to the
// first history item so we can load it faster than if we
// rebuilt the WebView.
@@ -995,11 +484,7 @@
return false;
}
}
- // Remove the settings object from the global settings and destroy
- // the WebView.
- BrowserSettings.getInstance().deleteObserver(
- t.mMainView.getSettings());
- t.mMainView.destroy();
+ t.destroy();
}
// Create a new WebView. If this tab is the current tab, we need to put
// back all the clients so force it to be the current tab.
@@ -1007,12 +492,11 @@
if (getCurrentTab() == t) {
setCurrentTab(t, true);
}
- // Clear the saved state except for the app id and close-on-exit
- // values.
- t.mSavedState = null;
- t.mPickerData = null;
+ // Clear the saved state and picker data
+ t.setSavedState(null);
+ t.clearPickerData();
// Save the new url in order to avoid deleting the WebView.
- t.mOriginalUrl = url;
+ t.setOriginalUrl(url);
return true;
}
@@ -1027,6 +511,11 @@
w.setMapTrackballToArrowKeys(false); // use trackball directly
// Enable the built-in zoom
w.getSettings().setBuiltInZoomControls(true);
+ // Attach DownloadManager so that downloads can start in an active or
+ // a non-active window. This can happen when going to a site that does
+ // a redirect after a period of time. The user could have switched to
+ // another tab while waiting for the download to start.
+ w.setDownloadListener(mActivity);
// Add this WebView to the settings observer list and update the
// settings
final BrowserSettings s = BrowserSettings.getInstance();
@@ -1043,48 +532,20 @@
return setCurrentTab(newTab, false);
}
- /*package*/ void pauseCurrentTab() {
+ void pauseCurrentTab() {
Tab t = getCurrentTab();
if (t != null) {
- t.mMainView.onPause();
- if (t.mSubView != null) {
- t.mSubView.onPause();
- }
+ t.pause();
}
}
- /*package*/ void resumeCurrentTab() {
+ void resumeCurrentTab() {
Tab t = getCurrentTab();
if (t != null) {
- t.mMainView.onResume();
- if (t.mSubView != null) {
- t.mSubView.onResume();
- }
+ t.resume();
}
}
- private void putViewInForeground(WebView v, WebViewClient vc,
- WebChromeClient cc) {
- v.setWebViewClient(vc);
- v.setWebChromeClient(cc);
- v.setOnCreateContextMenuListener(mActivity);
- v.setDownloadListener(mActivity);
- v.onResume();
- }
-
- private void putViewInBackground(WebView v) {
- // Set an empty callback so that default actions are not triggered.
- v.setWebViewClient(mEmptyClient);
- v.setWebChromeClient(mBackgroundChromeClient);
- v.setOnCreateContextMenuListener(null);
- // Leave the DownloadManager attached so that downloads can start in
- // a non-active window. This can happen when going to a site that does
- // a redirect after a period of time. The user could have switched to
- // another tab while waiting for the download to start.
- v.setDownloadListener(mActivity);
- v.onPause();
- }
-
/**
* If force is true, this method skips the check for newTab == current.
*/
@@ -1094,10 +555,9 @@
return true;
}
if (current != null) {
- // Remove the current WebView and the container of the subwindow
- putTabInBackground(current);
+ current.putInBackground();
+ mCurrentTab = -1;
}
-
if (newTab == null) {
return false;
}
@@ -1109,214 +569,22 @@
}
mTabQueue.add(newTab);
- WebView mainView;
-
// Display the new current tab
mCurrentTab = mTabs.indexOf(newTab);
- mainView = newTab.mMainView;
+ WebView mainView = newTab.getWebView();
boolean needRestore = (mainView == null);
if (needRestore) {
// Same work as in createNewTab() except don't do new Tab()
mainView = createNewWebView();
newTab.setWebView(mainView);
}
- putViewInForeground(mainView, mActivity.getWebViewClient(),
- mActivity.getWebChromeClient());
- // Add the subwindow if it exists
- if (newTab.mSubViewContainer != null) {
- putViewInForeground(newTab.mSubView, newTab.mSubViewClient,
- newTab.mSubViewChromeClient);
- }
+ newTab.putInForeground();
if (needRestore) {
// Have to finish setCurrentTab work before calling restoreState
- if (!restoreState(newTab.mSavedState, newTab)) {
+ if (!newTab.restoreState(newTab.getSavedState())) {
mainView.loadUrl(BrowserSettings.getInstance().getHomePage());
}
}
return true;
}
-
- /*
- * Put the tab in the background using all the empty/background clients.
- */
- private void putTabInBackground(Tab t) {
- putViewInBackground(t.mMainView);
- if (t.mSubView != null) {
- putViewInBackground(t.mSubView);
- }
- }
-
- /*
- * Dismiss the subwindow for the given tab.
- */
- void dismissSubWindow(Tab t) {
- if (t != null && t.mSubView != null) {
- BrowserSettings.getInstance().deleteObserver(
- t.mSubView.getSettings());
- t.mSubView.destroy();
- t.mSubView = null;
- t.mSubViewContainer = null;
- }
- }
-
- /**
- * Ensure that Tab t has data to display in the tab picker.
- * @param t Tab to populate.
- */
- /* package */ void populatePickerData(Tab t) {
- if (t == null) {
- return;
- }
-
- // mMainView == null indicates that the tab has been freed.
- if (t.mMainView == null) {
- populatePickerDataFromSavedState(t);
- return;
- }
-
- // FIXME: The only place we cared about subwindow was for
- // bookmarking (i.e. not when saving state). Was this deliberate?
- final WebBackForwardList list = t.mMainView.copyBackForwardList();
- final WebHistoryItem item =
- list != null ? list.getCurrentItem() : null;
- populatePickerData(t, item);
- }
-
- // Create the PickerData and populate it using the saved state of the tab.
- private void populatePickerDataFromSavedState(Tab t) {
- if (t.mSavedState == null) {
- return;
- }
-
- final PickerData data = new PickerData();
- final Bundle state = t.mSavedState;
- data.mUrl = state.getString(CURRURL);
- data.mTitle = state.getString(CURRTITLE);
- // XXX: These keys are from WebView.savePicture so if they change, this
- // will break.
- data.mScale = state.getFloat("scale", 1.0f);
- data.mScrollX = state.getInt("scrollX", 0);
- data.mScrollY = state.getInt("scrollY", 0);
-
- // Set the tab's picker data.
- t.mPickerData = data;
- }
-
- // Populate the picker data using the given history item and the current
- // top WebView.
- private void populatePickerData(Tab t, WebHistoryItem item) {
- final PickerData data = new PickerData();
- if (item != null) {
- data.mUrl = item.getUrl();
- data.mTitle = item.getTitle();
- data.mFavicon = item.getFavicon();
- if (data.mTitle == null) {
- data.mTitle = data.mUrl;
- }
- }
- // We want to display the top window in the tab picker but use the url
- // and title of the main window.
- final WebView w = t.getTopWindow();
- data.mScale = w.getScale();
- data.mScrollX = w.getScrollX();
- data.mScrollY = w.getScrollY();
-
- t.mPickerData = data;
- }
-
- /**
- * Clean up the data for all tabs.
- */
- /* package */ void wipeAllPickerData() {
- int size = getTabCount();
- for (int i = 0; i < size; i++) {
- final Tab t = getTab(i);
- if (t != null && t.mSavedState == null) {
- t.mPickerData = null;
- }
- }
- }
-
- /*
- * Save the state for an individual tab.
- */
- private boolean saveState(Tab t) {
- if (t != null) {
- final WebView w = t.mMainView;
- // If the WebView is null it means we ran low on memory and we
- // already stored the saved state in mSavedState.
- if (w == null) {
- return true;
- }
- final Bundle b = new Bundle();
- final WebBackForwardList list = w.saveState(b);
- if (list != null) {
- final File f = new File(mThumbnailDir, w.hashCode()
- + "_pic.save");
- if (w.savePicture(b, f)) {
- b.putString(CURRPICTURE, f.getPath());
- }
- }
-
- // Store some extra info for displaying the tab in the picker.
- final WebHistoryItem item =
- list != null ? list.getCurrentItem() : null;
- populatePickerData(t, item);
-
- // XXX: WebView.savePicture stores the scale and scroll positions
- // in the bundle so we don't have to do it here.
- final PickerData data = t.mPickerData;
- if (data.mUrl != null) {
- b.putString(CURRURL, data.mUrl);
- }
- if (data.mTitle != null) {
- b.putString(CURRTITLE, data.mTitle);
- }
- b.putBoolean(CLOSEONEXIT, t.mCloseOnExit);
- if (t.mAppId != null) {
- b.putString(APPID, t.mAppId);
- }
- if (t.mOriginalUrl != null) {
- b.putString(ORIGINALURL, t.mOriginalUrl);
- }
-
- // Remember the parent tab so the relationship can be restored.
- if (t.mParentTab != null) {
- b.putInt(PARENTTAB, getTabIndex(t.mParentTab));
- }
-
- // Remember the saved state.
- t.mSavedState = b;
- return true;
- }
- return false;
- }
-
- /*
- * Restore the state of the tab.
- */
- private boolean restoreState(Bundle b, Tab t) {
- if (b == null) {
- return false;
- }
- // Restore the internal state even if the WebView fails to restore.
- // This will maintain the app id, original url and close-on-exit values.
- t.mSavedState = null;
- t.mPickerData = null;
- t.mCloseOnExit = b.getBoolean(CLOSEONEXIT);
- t.mAppId = b.getString(APPID);
- t.mOriginalUrl = b.getString(ORIGINALURL);
-
- final WebView w = t.mMainView;
- final WebBackForwardList list = w.restoreState(b);
- if (list == null) {
- return false;
- }
- if (b.containsKey(CURRPICTURE)) {
- final File f = new File(b.getString(CURRPICTURE));
- w.restorePicture(b, f);
- f.delete();
- }
- return true;
- }
}
diff --git a/src/com/android/browser/WebsiteSettingsActivity.java b/src/com/android/browser/WebsiteSettingsActivity.java
index 047867a..430286f 100644
--- a/src/com/android/browser/WebsiteSettingsActivity.java
+++ b/src/com/android/browser/WebsiteSettingsActivity.java
@@ -88,6 +88,10 @@
mFeatures |= (1 << feature);
}
+ public void removeFeature(int feature) {
+ mFeatures &= ~(1 << feature);
+ }
+
public boolean hasFeature(int feature) {
return (mFeatures & (1 << feature)) != 0;
}
@@ -168,7 +172,7 @@
mResource = rsc;
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mDefaultIcon = BitmapFactory.decodeResource(getResources(),
- R.drawable.ic_launcher_shortcut_browser_bookmark);
+ R.drawable.app_web_browser_sm);
mUsageEmptyIcon = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_list_data_off);
mUsageLowIcon = BitmapFactory.decodeResource(getResources(),
@@ -280,7 +284,16 @@
Iterator<Site> sitesIter = matchingSites.iterator();
while (sitesIter.hasNext()) {
Site site = sitesIter.next();
- site.setTitle(title);
+ // We should only set the title if the bookmark is for the root
+ // (i.e. www.google.com), as website settings act on the origin
+ // as a whole rather than a single page under that origin. If the
+ // user has bookmarked a page under the root but *not* the root,
+ // then we risk displaying the title of that page which may or
+ // may not have any relevance to the origin.
+ if (url.equals(site.getOrigin()) ||
+ (new String(site.getOrigin()+"/")).equals(url)) {
+ site.setTitle(title);
+ }
if (bmp != null) {
site.setIcon(bmp);
}
@@ -323,7 +336,7 @@
// We display the size in MB, to 1dp, rounding up to the next 0.1MB.
// bytes should always be greater than zero.
if (bytes <= 0) {
- Log.e(LOGTAG, "sizeValueToString called with non-positive value");
+ Log.e(LOGTAG, "sizeValueToString called with non-positive value: " + bytes);
return "0";
}
float megabytes = (float) bytes / (1024.0F * 1024.0F);
@@ -354,8 +367,6 @@
*/
public void setIconForUsage(ImageView usageIcon, long usageInBytes) {
float usageInMegabytes = (float) usageInBytes / (1024.0F * 1024.0F);
- usageIcon.setVisibility(View.VISIBLE);
-
// We set the correct icon:
// 0 < empty < 0.1MB
// 0.1MB < low < 5MB
@@ -373,9 +384,10 @@
View view;
final TextView title;
final TextView subtitle;
- ImageView icon;
+ final ImageView icon;
final ImageView usageIcon;
final ImageView locationIcon;
+ final ImageView featureIcon;
if (convertView == null) {
view = mInflater.inflate(mResource, parent, false);
@@ -386,6 +398,7 @@
title = (TextView) view.findViewById(R.id.title);
subtitle = (TextView) view.findViewById(R.id.subtitle);
icon = (ImageView) view.findViewById(R.id.icon);
+ featureIcon = (ImageView) view.findViewById(R.id.feature_icon);
usageIcon = (ImageView) view.findViewById(R.id.usage_icon);
locationIcon = (ImageView) view.findViewById(R.id.location_icon);
usageIcon.setVisibility(View.GONE);
@@ -396,10 +409,22 @@
Site site = getItem(position);
title.setText(site.getPrettyTitle());
- subtitle.setText(site.getPrettyOrigin());
+ String subtitleText = site.getPrettyOrigin();
+ if (subtitleText != null) {
+ title.setMaxLines(1);
+ title.setSingleLine(true);
+ subtitle.setVisibility(View.VISIBLE);
+ subtitle.setText(subtitleText);
+ } else {
+ subtitle.setVisibility(View.GONE);
+ title.setMaxLines(2);
+ title.setSingleLine(false);
+ }
+
icon.setVisibility(View.VISIBLE);
usageIcon.setVisibility(View.INVISIBLE);
locationIcon.setVisibility(View.INVISIBLE);
+ featureIcon.setVisibility(View.GONE);
Bitmap bmp = site.getIcon();
if (bmp == null) {
bmp = mDefaultIcon;
@@ -415,6 +440,7 @@
public void onReceiveValue(Long value) {
if (value != null) {
setIconForUsage(usageIcon, value.longValue());
+ usageIcon.setVisibility(View.VISIBLE);
}
}
});
@@ -435,8 +461,11 @@
});
}
} else {
- setTitle(mCurrentSite.getPrettyTitle());
icon.setVisibility(View.GONE);
+ locationIcon.setVisibility(View.GONE);
+ usageIcon.setVisibility(View.GONE);
+ featureIcon.setVisibility(View.VISIBLE);
+ setTitle(mCurrentSite.getPrettyTitle());
String origin = mCurrentSite.getOrigin();
switch (mCurrentSite.getFeatureByIndex(position)) {
case Site.FEATURE_WEB_STORAGE:
@@ -446,6 +475,8 @@
String usage = sizeValueToString(value.longValue()) + " " + sMBStored;
title.setText(R.string.webstorage_clear_data_title);
subtitle.setText(usage);
+ subtitle.setVisibility(View.VISIBLE);
+ setIconForUsage(featureIcon, value.longValue());
}
}
});
@@ -457,9 +488,12 @@
if (allowed != null) {
if (allowed.booleanValue()) {
subtitle.setText(R.string.geolocation_settings_page_summary_allowed);
+ featureIcon.setImageBitmap(mLocationAllowedIcon);
} else {
subtitle.setText(R.string.geolocation_settings_page_summary_not_allowed);
+ featureIcon.setImageBitmap(mLocationDisallowedIcon);
}
+ subtitle.setVisibility(View.VISIBLE);
}
}
});
@@ -484,8 +518,14 @@
new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dlg, int which) {
WebStorage.getInstance().deleteOrigin(mCurrentSite.getOrigin());
- mCurrentSite = null;
+ // If this site has no more features, then go back to the
+ // origins list.
+ mCurrentSite.removeFeature(Site.FEATURE_WEB_STORAGE);
+ if (mCurrentSite.getFeatureCount() == 0) {
+ mCurrentSite = null;
+ }
askForOrigins();
+ notifyDataSetChanged();
}})
.setNegativeButton(R.string.webstorage_clear_data_dialog_cancel_button, null)
.setIcon(android.R.drawable.ic_dialog_alert)
@@ -499,8 +539,12 @@
new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dlg, int which) {
GeolocationPermissions.getInstance().clear(mCurrentSite.getOrigin());
- mCurrentSite = null;
+ mCurrentSite.removeFeature(Site.FEATURE_GEOLOCATION);
+ if (mCurrentSite.getFeatureCount() == 0) {
+ mCurrentSite = null;
+ }
askForOrigins();
+ notifyDataSetChanged();
}})
.setNegativeButton(R.string.geolocation_settings_page_dialog_cancel_button, null)
.setIcon(android.R.drawable.ic_dialog_alert)
@@ -512,6 +556,10 @@
notifyDataSetChanged();
}
}
+
+ public Site currentSite() {
+ return mCurrentSite;
+ }
}
/**
@@ -548,8 +596,9 @@
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
- // If we aren't listing any sites hide the clear all button (and hence the menu).
- return mAdapter.getCount() > 0;
+ // If we are not on the sites list (rather on the page for a specific site) or
+ // we aren't listing any sites hide the clear all button (and hence the menu).
+ return mAdapter.currentSite() == null && mAdapter.getCount() > 0;
}
@Override