]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/commitdiff
Implement Save as Archive. https://redmine.stoutner.com/issues/188
authorSoren Stoutner <soren@stoutner.com>
Thu, 26 Dec 2019 22:15:21 +0000 (15:15 -0700)
committerSoren Stoutner <soren@stoutner.com>
Thu, 26 Dec 2019 22:15:21 +0000 (15:15 -0700)
31 files changed:
app/src/main/AndroidManifest.xml
app/src/main/assets/de/guide_proxies_dark.html
app/src/main/assets/de/guide_proxies_light.html
app/src/main/assets/en/guide_proxies_dark.html
app/src/main/assets/en/guide_proxies_light.html
app/src/main/assets/es/guide_proxies_dark.html
app/src/main/assets/es/guide_proxies_light.html
app/src/main/assets/fr/guide_proxies_dark.html
app/src/main/assets/fr/guide_proxies_light.html
app/src/main/assets/it/guide_proxies_dark.html
app/src/main/assets/it/guide_proxies_light.html
app/src/main/assets/ru/guide_proxies_dark.html
app/src/main/assets/ru/guide_proxies_light.html
app/src/main/assets/tr/guide_proxies_dark.html
app/src/main/assets/tr/guide_proxies_light.html
app/src/main/java/com/stoutner/privacybrowser/activities/ImportExportActivity.java
app/src/main/java/com/stoutner/privacybrowser/activities/LogcatActivity.java
app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java
app/src/main/java/com/stoutner/privacybrowser/dialogs/SaveWebpageDialog.java [new file with mode: 0644]
app/src/main/java/com/stoutner/privacybrowser/dialogs/SaveWebpageImageDialog.java [deleted file]
app/src/main/java/com/stoutner/privacybrowser/dialogs/StoragePermissionDialog.java
app/src/main/res/drawable/import_export_dark.xml
app/src/main/res/drawable/import_export_light.xml
app/src/main/res/menu/webview_options_menu.xml
app/src/main/res/values-de/strings.xml
app/src/main/res/values-es/strings.xml
app/src/main/res/values-fr/strings.xml
app/src/main/res/values-it/strings.xml
app/src/main/res/values-ru/strings.xml
app/src/main/res/values-tr/strings.xml
app/src/main/res/values/strings.xml

index 1ea8d8cc4776c6729e6a552f51f4ca3fe438bce4..f5f07022554375d57179e356cee629106544c797 100644 (file)
                 <data android:mimeType="text/*" />
             </intent-filter>
 
+            <!-- Process intents for MHT archives. -->
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+
+                <category android:name="android.intent.category.BROWSABLE" />
+                <category android:name="android.intent.category.DEFAULT" />
+
+                <data android:scheme="file" />
+                <data android:scheme="content" />
+
+                <data android:host="*" />
+
+                <!-- This pattern matches any file that starts with a `/`, has at least one character, followed by any number of other characters, terminating with `.mht`. -->
+                <data android:pathPattern="/.*\.mht" />
+                <data android:mimeType="*/*" />
+            </intent-filter>
+
             <!-- Process web search intents. -->
             <intent-filter>
                 <action android:name="android.intent.action.WEB_SEARCH" />
index 27d47e6c586a74f908e7c2a6b911ecaa1e0fd5af..5edfc551298838d5d6dad1737e473def8dde9d16 100644 (file)
@@ -77,7 +77,7 @@
         <h3><img class="title" src="../shared_images/open_in_browser_blue_dark.png"> Nutzung von Proxies</h3>
 
         <p>Trotz ihrer Einschränkungen können Proxies unter bestimmen Umständen durchaus nützlich sein.
-            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> und <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
+            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> und <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
             existieren Android-Apps, die die einfache Nutzung dieser Proxy-Netzwerke ermöglichen.
             Wird die Nutzung dieser Proxy-Netzwerke in Privacy Browser aktiviert, wird die App-Leiste mit einem hellblauen statt hellgrauen Hintergrund versehen.
             Da der Datenverkehr in solchen Fällen jedoch über mehrere Proxy-Knoten geleitet wird,
index 9aaa3b9bafda46ff8d662bb9c5a03b637a3406ba..841554df5049c284fd18857067e4204328fa6892 100644 (file)
@@ -77,7 +77,7 @@
         <h3><img class="title" src="../shared_images/open_in_browser_blue_light.png"> Nutzung von Proxies</h3>
 
         <p>Trotz ihrer Einschränkungen können Proxies unter bestimmen Umständen durchaus nützlich sein.
-            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> und <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
+            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> und <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
             existieren Android-Apps, die die einfache Nutzung dieser Proxy-Netzwerke ermöglichen.
             Wird die Nutzung dieser Proxy-Netzwerke in Privacy Browser aktiviert, wird die App-Leiste mit einem hellblauen statt hellgrauen Hintergrund versehen.
             Da der Datenverkehr in solchen Fällen jedoch über mehrere Proxy-Knoten geleitet wird,
index cc723eabc4204b2e56defe27ec08adbaa0a3bc4f..a02c6e677f94b6ef52e9226f8eaa076d4f9301e2 100644 (file)
@@ -68,7 +68,7 @@
         <h3><img class="title" src="../shared_images/open_in_browser_blue_dark.png"> Using Proxies</h3>
 
         <p>Despite their limitations, proxies can be useful in some circumstances.
-            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
+            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
             have Android apps that make it easy to use their proxy networks. When proxying is turned on in Privacy Browser, the app bar will have a light blue background instead of the default light grey.
             Because traffic is being routed through several proxy nodes, using a layered proxy is often much slower than connecting directly to the internet.</p>
 
index 26da4f9019da1132e2a9f6faf452f9000b553daa..2184b520b635c5fcfc98c626c99122c3fc8b3711 100644 (file)
@@ -68,7 +68,7 @@
         <h3><img class="title" src="../shared_images/open_in_browser_blue_light.png"> Using Proxies</h3>
 
         <p>Despite their limitations, proxies can be useful in some circumstances.
-            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
+            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
             have Android apps that make it easy to use their proxy networks. When proxying is turned on in Privacy Browser, the app bar will have a light blue background instead of the default light grey.
             Because traffic is being routed through several proxy nodes, using a layered proxy is often much slower than connecting directly to the internet.</p>
 
index 21408324395dfff103e0ebdf9706608e3e553629..beef54d83831d0fd928128bf3b7c8199d8deeca0 100644 (file)
@@ -76,7 +76,7 @@
         <h3><img class="title" src="../shared_images/open_in_browser_blue_dark.png"> Uso de Proxis</h3>
 
         <p>A pesar de sus limitaciones, los proxis pueden ser útiles en algunas circunstancias.
-            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> e <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
+            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> e <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
             tienen aplicaciones Android que facilitan el uso de sus redes de proxy. Cuando se activa el proxy en Navegador Privado,
             la barra de aplicaciones tendrá un fondo azul claro en lugar del gris claro predeterminado.
             Debido a que el tráfico está siendo enrutado a través de varios nodos proxy, usar un proxy en capas es a menudo mucho más lento que conectarse directamente a Internet.</p>
index 6dd1ee7d81edc61cf602a12660caf5ccfaa64907..df5f1bb6bd40165adba5bdb666d565e19cbe6ab5 100644 (file)
@@ -76,7 +76,7 @@
         <h3><img class="title" src="../shared_images/open_in_browser_blue_light.png"> Uso de Proxis</h3>
 
         <p>A pesar de sus limitaciones, los proxis pueden ser útiles en algunas circunstancias.
-            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> e <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
+            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> e <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
             tienen aplicaciones Android que facilitan el uso de sus redes de proxy. Cuando se activa el proxy en Navegador Privado,
             la barra de aplicaciones tendrá un fondo azul claro en lugar del gris claro predeterminado.
             Debido a que el tráfico está siendo enrutado a través de varios nodos proxy, usar un proxy en capas es a menudo mucho más lento que conectarse directamente a Internet.</p>
index 0b876b604f1e3cccd401f6697760b4423440b1f4..29384c5e3302f802afd532a27bde83dd5da17779 100644 (file)
@@ -76,7 +76,7 @@
         <h3><img class="title" src="../shared_images/open_in_browser_blue_dark.png"> Utiliser des Proxies</h3>
 
         <p>Malgré leurs limites, les proxies peuvent être utiles dans certaines circonstances.
-            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> et <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
+            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> et <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
             ont des applications Android qui facilitent l'utilisation de leurs réseaux proxy.
             Lorsque le proxy est activé dans Privacy Browser, la barre d'application aura un fond bleu clair au lieu du gris clair par défaut.
             Étant donné que le trafic est acheminé via plusieurs nœuds proxy, l'utilisation d'un proxy en couches est souvent beaucoup plus lente que la connexion directe à Internet.</p>
index 0ffb12e77a5a0ba360fcac4bd6b3ab8bab3d5b85..07db812be4992be78e8aab988c356f8bd106e4f3 100644 (file)
@@ -76,7 +76,7 @@
         <h3><img class="title" src="../shared_images/open_in_browser_blue_light.png"> Utiliser des Proxies</h3>
 
         <p>Malgré leurs limites, les proxies peuvent être utiles dans certaines circonstances.
-            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> et <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
+            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> et <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
             ont des applications Android qui facilitent l'utilisation de leurs réseaux proxy.
             Lorsque le proxy est activé dans Privacy Browser, la barre d'application aura un fond bleu clair au lieu du gris clair par défaut.
             Étant donné que le trafic est acheminé via plusieurs nœuds proxy, l'utilisation d'un proxy en couches est souvent beaucoup plus lente que la connexion directe à Internet.</p>
index 2ffbb3bd7c93833fdc42aec563262143e9f38cd6..a2d68bf4832efbf4d9f79b17e1da9e4f722c606a 100644 (file)
     </head>
 
     <body>
-        <h3><img class="title" src="../shared_images/vpn_key_blue_dark.png"> Proxies and Their Limits</h3>
+        <h3><img class="title" src="../shared_images/vpn_key_blue_dark.png"> I Proxy e i loro limiti</h3>
 
         <p>Esistono due categorie generali di cattivi soggetti che vogliono violare la privacy del web:
             governi maliziosi con accesso agli ISP (Internet Service Providers) e mega corporations che gestiscono social network e agenzie pubblicitarie.
-            Proxies like TOR (The Onion Router) and I2P (the Invisible Internet Project) are useful in protecting privacy from malicious governments (which spy on traffic in transit)
-            but not from mega corporations (which embed malicious code on web servers).</p>
+            Proxy come TOR (The Onion Router) e I2P (Invisible Internet Project) sono utili per la protezione della privacy da governi maliziosi (che spiano il traffico in transito)
+            ma non dalle mega corporations (che inseriscono codice malizioso sui web server).</p>
 
 
         <h3><img class="title" src="../shared_images/language_blue_dark.png"> Governi Maliziosi</h3>
 
         <p>I governi malizionsi spesso spiano i loro cittadini per punire il dissenso o le attività di difesa dei diritti umani.
             Solitamente, o gestiscono loro stessi gli ISP locali oppure li obbligano a rivelare informazioni mostrando tutti gli indirizzi IP visitati da ciascun utente.
-            Layered proxies are designed to defeat this infringement of privacy by encrypting the traffic from a user’s device and routing it through multiple servers on the internet
-            before sending it on to the final destination.
-            This means that no individual ISP, server, or website, can know both the <a href="https://ipleak.net">IP address of the user’s device</a> and the IP address of the final web server.
-            Malicious governments and the ISPs they control cannot tell which web servers a user is accessing, although they can tell that the user is using a layered proxy service.
-            In some parts of the world, using proxies could be construed as an evidence of illegal behavior (“If you didn’t have anything to hide you wouldn’t be encrypting your traffic”)
-            and users could be punished because governments assume they are doing something that is prohibited. Thus, proxies can be helpful, but they aren’t a panacea.</p>
+            I proxy a strati sono progettati per sconfiggere questa violazione di privacy crittografando il traffico dal dispositivo dell'utente e instradandolo attraverso server multipli su internet
+            prima di inviarlo alla destinazione finale.
+            Questo significa che nessun ISP individuale, server, o sito web,
+            può conoscere sia l'<a href="https://ipleak.net">indirizzo IP del dispositivo dell'utente</a> che l'indirizzo IP del web server finale.
+            I governi maliziosi e gli ISP che controllano, non possono conoscere i web server ai quali l'utente sta accedendo, sebbene sappiano che l'utente sta utilizzando un servizio di proxy a strati.
+            In alcune parti del mondo l'utilizzo di proxy può essere consideraro come evidenza di un comportamento illegale (“Se non hai nulla da nascondere non crittograferesti il tuo traffico”)
+            e gli utenti potrebbero essere perseguiti perchè il loro governo potrebbe assumere che stiano facendo qualcosa di proibito.
+            Per questo motivo i proxy possono essere utili ma non sono la soluzione di tutti i mali.</p>
 
 
         <h3><img class="title" src="../shared_images/language_blue_dark.png"> Mega corporations</h3>
 
         <p>Quando un utente si connette a un web server, il server può vedere l'indirizzo IP dell'utente.
             Nonostante non sia una scienza esatta, è possibile convertire l'IP in indirizzi fisici con <a href="https://www.whatismyip.com/">discreta accuratezza</a>.
-            Small web servers typically rely on IP addresses to identify the location of the users visiting their site. Proxies are a good solution to mask the user’s location from these servers.
+            I piccoli web servers solitamente si basano sull'indirizzo IP per identificare la posizione degli utenti che accedono al loro sito.
+            I Proxy sono una buona soluzione per mascherare la posizione dell'utente a questi server.
             Le mega corporations proprietarie di social media e agenzie pubblicitarie utilizzano però un intero profilo di informazioni con lo scopo di tracciare gli utenti sui dispositivi e sgli indirizzi IP.
             Questi profili utilizzano molte tecniche diverse per l'identificazione degli utenti, tra cui JavaScript, cookie, ID traccianti,
             e <a href="https://panopticlick.eff.org/">impronta digitale dei browser</a>.
         <p>Viene tracciato ogni sito visitato, ogni acquisto effettuato, ogni carta di credito utilizzata, ogni indirizzo di spedizione, i metadati GPS di ogni immagine che viene caricata su internet.
             Viene costruito il profilo per età, sesso, stato civile, indirizzo, appartenenza politica, religione, situazione familiare, animali domestici, e tutto ciò su cui possono mettere le mani.
             Le corporations acquistano anche i database delle transazioni con carta di credito effettuate nei negozi, per poter tracciare anche le abitudini di acquisto off-line degli utenti nei loro profili.
-            Because they already have much more accurate address information about a user than an IP address discloses, proxies provides no real privacy protection against mega corporations.</p>
+            Poichè hanno già informazioni molto più accurate sull'utente rispetto a quelle fornite dall'indirizzo IP, i proxy non forniscono alcuna vera protezione della privacy contro le mega corporations.</p>
 
         <p>La miglior protezione per la privacy contro le mega corporations è quella di navigare con JavaScript disabilitato, seguita dal bloccare gli annunci pubblicitari,
             disabilitare i cookie e il DOM storage, e utilizzare un browser di cui è difficile avere l'impronta digitale.</p>
 
 
-        <h3><img class="title" src="../shared_images/open_in_browser_blue_dark.png"> Using Proxies</h3>
+        <h3><img class="title" src="../shared_images/open_in_browser_blue_dark.png"> L'utilizzo di Proxy</h3>
 
-        <p>Despite their limitations, proxies can be useful in some circumstances.
-            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
-            have Android apps that make it easy to use their proxy networks. When proxying is turned on in Privacy Browser, the app bar will have a light blue background instead of the default light grey.
-            Because traffic is being routed through several proxy nodes, using a layered proxy is often much slower than connecting directly to the internet.</p>
+        <p>Nonostante i loro limiti, i proxy possono essere utili in alcune circostanze.
+            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> e <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
+            hanno app per Android che facilitano l'utilizzo delle loro reti proxy.
+            Quando si abilita il proxy in Privacy Browser la barra dell'app bar avrà una colorazione dello sfondo azzurra, rispetto a quella grigia di default.
+            Dal momento che il traffico è instradato attraverso diversi nodi proxy, l'utilizzo di un proxy a strati è spesso molto più lento di una connessione diretta a internet.</p>
 
         <img class="center" src="images/tor.png">
 
         <h3><img class="title" src="../shared_images/file_download_blue_dark.png"> Download di File con Tor</h3>
 
-        <p>When Orbot is operating in proxy mode, browsing the internet using Privacy Browser will be routed through the proxy, but file downloads will not.
-            This is because Privacy Browser uses Android’s builtin download manager to download files, which doesn’t have a proxy option.
-            Users who want to download files via Orbot need to enable its VPN mode.  There is currently no way to download files through I2P.</p>
+        <p>Quando Orbot sta funzionando in modalità proxy, la navigazione su internet con Privacy Browser è instradata attraverso il proxy, ma il download di file no.
+            Questo perchè Privacy Browser utilizza il download manager nativo di Android per lo scaricamento dei file, e questo non ha l'opzione proxy.
+            Gli utenti che vogliono scaricare i file via Orbot devono quindi abilitare la sua modalità VPN.  Attualmente non c'è ancora la possibilità di scaricare file con I2P.</p>
 
         <img class="center" src="../shared_images/vpn_mode.png">
     </body>
index 7a7598accac4de1d707be52782b527bc550b1aa7..3719b015736a3381493f5d79c112ec34a67042ed 100644 (file)
     </head>
 
     <body>
-        <h3><img class="title" src="../shared_images/vpn_key_blue_light.png"> Proxies and Their Limits</h3>
+        <h3><img class="title" src="../shared_images/vpn_key_blue_light.png"> I Proxy e i loro limiti</h3>
 
         <p>Esistono due categorie generali di cattivi soggetti che vogliono violare la privacy del web:
             governi maliziosi con accesso agli ISP (Internet Service Providers) e mega corporations che gestiscono social network e agenzie pubblicitarie.
-            Proxies like TOR (The Onion Router) and I2P (the Invisible Internet Project) are useful in protecting privacy from malicious governments (which spy on traffic in transit)
-            but not from mega corporations (which embed malicious code on web servers).</p>
+            Proxy come TOR (The Onion Router) e I2P (Invisible Internet Project) sono utili per la protezione della privacy da governi maliziosi (che spiano il traffico in transito)
+            ma non dalle mega corporations (che inseriscono codice malizioso sui web server).</p>
 
 
         <h3><img class="title" src="../shared_images/language_blue_light.png"> Governi Maliziosi</h3>
 
         <p>I governi malizionsi spesso spiano i loro cittadini per punire il dissenso o le attività di difesa dei diritti umani.
             Solitamente, o gestiscono loro stessi gli ISP locali oppure li obbligano a rivelare informazioni mostrando tutti gli indirizzi IP visitati da ciascun utente.
-            Layered proxies are designed to defeat this infringement of privacy by encrypting the traffic from a user’s device and routing it through multiple servers on the internet
-            before sending it on to the final destination.
-            This means that no individual ISP, server, or website, can know both the <a href="https://ipleak.net">IP address of the user’s device</a> and the IP address of the final web server.
-            Malicious governments and the ISPs they control cannot tell which web servers a user is accessing, although they can tell that the user is using a layered proxy service.
-            In some parts of the world, using proxies could be construed as an evidence of illegal behavior (“If you didn’t have anything to hide you wouldn’t be encrypting your traffic”)
-            and users could be punished because governments assume they are doing something that is prohibited. Thus, proxies can be helpful, but they aren’t a panacea.</p>
+            I proxy a strati sono progettati per sconfiggere questa violazione di privacy crittografando il traffico dal dispositivo dell'utente e instradandolo attraverso server multipli su internet
+            prima di inviarlo alla destinazione finale.
+            Questo significa che nessun ISP individuale, server, o sito web,
+            può conoscere sia l'<a href="https://ipleak.net">indirizzo IP del dispositivo dell'utente</a> che l'indirizzo IP del web server finale.
+            I governi maliziosi e gli ISP che controllano, non possono conoscere i web server ai quali l'utente sta accedendo, sebbene sappiano che l'utente sta utilizzando un servizio di proxy a strati.
+            In alcune parti del mondo l'utilizzo di proxy può essere consideraro come evidenza di un comportamento illegale (“Se non hai nulla da nascondere non crittograferesti il tuo traffico”)
+            e gli utenti potrebbero essere perseguiti perchè il loro governo potrebbe assumere che stiano facendo qualcosa di proibito.
+            Per questo motivo i proxy possono essere utili ma non sono la soluzione di tutti i mali.</p>
 
 
         <h3><img class="title" src="../shared_images/language_blue_light.png"> Mega corporations</h3>
 
         <p>Quando un utente si connette a un web server, il server può vedere l'indirizzo IP dell'utente.
             Nonostante non sia una scienza esatta, è possibile convertire l'IP in indirizzi fisici con <a href="https://www.whatismyip.com/">discreta accuratezza</a>.
-            Small web servers typically rely on IP addresses to identify the location of the users visiting their site. Proxies are a good solution to mask the user’s location from these servers.
+            I piccoli web servers solitamente si basano sull'indirizzo IP per identificare la posizione degli utenti che accedono al loro sito.
+            I Proxy sono una buona soluzione per mascherare la posizione dell'utente a questi server.
             Le mega corporations proprietarie di social media e agenzie pubblicitarie utilizzano però un intero profilo di informazioni con lo scopo di tracciare gli utenti sui dispositivi e sgli indirizzi IP.
             Questi profili utilizzano molte tecniche diverse per l'identificazione degli utenti, tra cui JavaScript, cookie, ID traccianti,
             e <a href="https://panopticlick.eff.org/">impronta digitale dei browser</a>.
         <p>Viene tracciato ogni sito visitato, ogni acquisto effettuato, ogni carta di credito utilizzata, ogni indirizzo di spedizione, i metadati GPS di ogni immagine che viene caricata su internet.
             Viene costruito il profilo per età, sesso, stato civile, indirizzo, appartenenza politica, religione, situazione familiare, animali domestici, e tutto ciò su cui possono mettere le mani.
             Le corporations acquistano anche i database delle transazioni con carta di credito effettuate nei negozi, per poter tracciare anche le abitudini di acquisto off-line degli utenti nei loro profili.
-            Because they already have much more accurate address information about a user than an IP address discloses, proxies provides no real privacy protection against mega corporations.</p>
+            Poichè hanno già informazioni molto più accurate sull'utente rispetto a quelle fornite dall'indirizzo IP, i proxy non forniscono alcuna vera protezione della privacy contro le mega corporations.</p>
 
         <p>La miglior protezione per la privacy contro le mega corporations è quella di navigare con JavaScript disabilitato, seguita dal bloccare gli annunci pubblicitari,
             disabilitare i cookie e il DOM storage, e utilizzare un browser di cui è difficile avere l'impronta digitale.</p>
 
 
-        <h3><img class="title" src="../shared_images/open_in_browser_blue_light.png"> Using Proxies</h3>
+        <h3><img class="title" src="../shared_images/open_in_browser_blue_light.png"> L'utilizzo di Proxy</h3>
 
-        <p>Despite their limitations, proxies can be useful in some circumstances.
-            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
-            have Android apps that make it easy to use their proxy networks. When proxying is turned on in Privacy Browser, the app bar will have a light blue background instead of the default light grey.
-            Because traffic is being routed through several proxy nodes, using a layered proxy is often much slower than connecting directly to the internet.</p>
+        <p>Nonostante i loro limiti, i proxy possono essere utili in alcune circostanze.
+            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> e <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
+            hanno app per Android che facilitano l'utilizzo delle loro reti proxy.
+            Quando si abilita il proxy in Privacy Browser la barra dell'app bar avrà una colorazione dello sfondo azzurra, rispetto a quella grigia di default.
+            Dal momento che il traffico è instradato attraverso diversi nodi proxy, l'utilizzo di un proxy a strati è spesso molto più lento di una connessione diretta a internet.</p>
 
         <img class="center" src="images/tor.png">
 
         <h3><img class="title" src="../shared_images/file_download_blue_light.png"> Download di File con Tor</h3>
 
-        <p>When Orbot is operating in proxy mode, browsing the internet using Privacy Browser will be routed through the proxy, but file downloads will not.
-            This is because Privacy Browser uses Android’s builtin download manager to download files, which doesn’t have a proxy option.
-            Users who want to download files via Orbot need to enable its VPN mode.  There is currently no way to download files through I2P.</p>
+        <p>Quando Orbot sta funzionando in modalità proxy, la navigazione su internet con Privacy Browser è instradata attraverso il proxy, ma il download di file no.
+            Questo perchè Privacy Browser utilizza il download manager nativo di Android per lo scaricamento dei file, e questo non ha l'opzione proxy.
+            Gli utenti che vogliono scaricare i file via Orbot devono quindi abilitare la sua modalità VPN.  Attualmente non c'è ancora la possibilità di scaricare file con I2P.</p>
 
         <img class="center" src="../shared_images/vpn_mode.png">
     </body>
index 94067ab714eb06b6ea1b4b577e0b656c3b2697d9..9141f5f3f507584d99b481acc1e610f4fb3c7693 100644 (file)
@@ -69,7 +69,7 @@
         <h3><img class="title" src="../shared_images/open_in_browser_blue_dark.png"> Using Proxies</h3>
 
         <p>Despite their limitations, proxies can be useful in some circumstances.
-            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
+            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
             have Android apps that make it easy to use their proxy networks. When proxying is turned on in Privacy Browser, the app bar will have a light blue background instead of the default light grey.
             Because traffic is being routed through several proxy nodes, using a layered proxy is often much slower than connecting directly to the internet.</p>
 
index 0e3946f47e4ccebde5c0c635a188c3fa0facb44b..15f97aa6eaeececf13255178f0570665eed98a85 100644 (file)
@@ -69,7 +69,7 @@
         <h3><img class="title" src="../shared_images/open_in_browser_blue_light.png"> Using Proxies</h3>
 
         <p>Despite their limitations, proxies can be useful in some circumstances.
-            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
+            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
             have Android apps that make it easy to use their proxy networks. When proxying is turned on in Privacy Browser, the app bar will have a light blue background instead of the default light grey.
             Because traffic is being routed through several proxy nodes, using a layered proxy is often much slower than connecting directly to the internet.</p>
 
index 049ed00837c5d8a3c17a136f7c5896e6cd1565c8..49d5b898a2f5002a2f38b7b7348ffd1603cdb0ac 100644 (file)
@@ -68,7 +68,7 @@
         <h3><img class="title" src="../shared_images/open_in_browser_blue_dark.png"> Using Proxies</h3>
 
         <p>Despite their limitations, proxies can be useful in some circumstances.
-            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
+            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
             have Android apps that make it easy to use their proxy networks. When proxying is turned on in Privacy Browser, the app bar will have a light blue background instead of the default light grey.
             Because traffic is being routed through several proxy nodes, using a layered proxy is often much slower than connecting directly to the internet.</p>
 
index e4915281fae006491a5a338692268e08a12701ec..d7205739199290d64d2e00a19052b7ae381247b1 100644 (file)
@@ -68,7 +68,7 @@
         <h3><img class="title" src="../shared_images/open_in_browser_blue_light.png"> Using Proxies</h3>
 
         <p>Despite their limitations, proxies can be useful in some circumstances.
-            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2p</a>
+            <a href="https://play.google.com/store/apps/details?id=org.torproject.android">Tor</a> and <a href="https://f-droid.org/en/packages/net.i2p.android.router/">I2P</a>
             have Android apps that make it easy to use their proxy networks. When proxying is turned on in Privacy Browser, the app bar will have a light blue background instead of the default light grey.
             Because traffic is being routed through several proxy nodes, using a layered proxy is often much slower than connecting directly to the internet.</p>
 
index 1c328c4d07119e759f3fb60b6a01a66781c02fe9..ca4703af5243f936774f8ffd68cf2ec7e57a7ab1 100644 (file)
@@ -117,7 +117,7 @@ public class ImportExportActivity extends AppCompatActivity implements StoragePe
         // Set the content view.
         setContentView(R.layout.import_export_coordinatorlayout);
 
-        // Use the `SupportActionBar` from `android.support.v7.app.ActionBar` until the minimum API is >= 21.
+        // Set the support action bar.
         Toolbar toolbar = findViewById(R.id.import_export_toolbar);
         setSupportActionBar(toolbar);
 
@@ -130,7 +130,7 @@ public class ImportExportActivity extends AppCompatActivity implements StoragePe
         // Display the home arrow on the support action bar.
         actionBar.setDisplayHomeAsUpEnabled(true);
 
-        // Find out if we are running KitKat
+        // Find out if the system is running KitKat
         boolean runningKitKat = (Build.VERSION.SDK_INT == 19);
 
         // Find out if OpenKeychain is installed.
@@ -519,7 +519,7 @@ public class ImportExportActivity extends AppCompatActivity implements StoragePe
                 // Check if the user has previously denied the storage permission.
                 if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {  // Show a dialog explaining the request first.
                     // Instantiate the storage permission alert dialog.
-                    DialogFragment storagePermissionDialogFragment = new StoragePermissionDialog();
+                    DialogFragment storagePermissionDialogFragment = StoragePermissionDialog.displayDialog(0);
 
                     // Show the storage permission alert dialog.  The permission will be requested when the dialog is closed.
                     storagePermissionDialogFragment.show(getSupportFragmentManager(), getString(R.string.storage_permission));
@@ -532,7 +532,7 @@ public class ImportExportActivity extends AppCompatActivity implements StoragePe
     }
 
     @Override
-    public void onCloseStoragePermissionDialog() {
+    public void onCloseStoragePermissionDialog(int type) {
         // Request the write external storage permission.  The import/export will be run when it finishes.
         ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
     }
index 754874d8b5986de422c0c05d156f921e5cbabc4f..c38181a60239d81e190b1274ba8e94422ac73de8 100644 (file)
@@ -235,7 +235,7 @@ public class LogcatActivity extends AppCompatActivity implements SaveLogcatDialo
                 // Check if the user has previously denied the storage permission.
                 if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {  // Show a dialog explaining the request first.
                     // Instantiate the storage permission alert dialog.
-                    DialogFragment storagePermissionDialogFragment = new StoragePermissionDialog();
+                    DialogFragment storagePermissionDialogFragment = StoragePermissionDialog.displayDialog(0);
 
                     // Show the storage permission alert dialog.  The permission will be requested when the dialog is closed.
                     storagePermissionDialogFragment.show(getSupportFragmentManager(), getString(R.string.storage_permission));
@@ -249,7 +249,7 @@ public class LogcatActivity extends AppCompatActivity implements SaveLogcatDialo
     }
 
     @Override
-    public void onCloseStoragePermissionDialog() {
+    public void onCloseStoragePermissionDialog(int type) {
         // Request the write external storage permission.  The logcat will be saved when it finishes.
         ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
     }
index 568a316ff199758af5ebf359731cd78d57319339..efa66ac9516ef9970b83216dbe23fb2e6f52a19f 100644 (file)
@@ -133,7 +133,7 @@ import com.stoutner.privacybrowser.dialogs.FontSizeDialog;
 import com.stoutner.privacybrowser.dialogs.HttpAuthenticationDialog;
 import com.stoutner.privacybrowser.dialogs.ProxyNotInstalledDialog;
 import com.stoutner.privacybrowser.dialogs.PinnedMismatchDialog;
-import com.stoutner.privacybrowser.dialogs.SaveWebpageImageDialog;
+import com.stoutner.privacybrowser.dialogs.SaveWebpageDialog;
 import com.stoutner.privacybrowser.dialogs.SslCertificateErrorDialog;
 import com.stoutner.privacybrowser.dialogs.StoragePermissionDialog;
 import com.stoutner.privacybrowser.dialogs.UrlHistoryDialog;
@@ -170,8 +170,9 @@ import java.util.Set;
 // AppCompatActivity from android.support.v7.app.AppCompatActivity must be used to have access to the SupportActionBar until the minimum API is >= 21.
 public class MainWebViewActivity extends AppCompatActivity implements CreateBookmarkDialog.CreateBookmarkListener, CreateBookmarkFolderDialog.CreateBookmarkFolderListener,
         DownloadFileDialog.DownloadFileListener, DownloadImageDialog.DownloadImageListener, DownloadLocationPermissionDialog.DownloadLocationPermissionDialogListener, EditBookmarkDialog.EditBookmarkListener,
-        EditBookmarkFolderDialog.EditBookmarkFolderListener, FontSizeDialog.UpdateFontSizeListener, NavigationView.OnNavigationItemSelectedListener, PinnedMismatchDialog.PinnedMismatchListener, PopulateBlocklists.PopulateBlocklistsListener, SaveWebpageImageDialog.SaveWebpageImageListener,
-        StoragePermissionDialog.StoragePermissionDialogListener, UrlHistoryDialog.NavigateHistoryListener, WebViewTabFragment.NewTabListener {
+        EditBookmarkFolderDialog.EditBookmarkFolderListener, FontSizeDialog.UpdateFontSizeListener, NavigationView.OnNavigationItemSelectedListener, PinnedMismatchDialog.PinnedMismatchListener,
+        PopulateBlocklists.PopulateBlocklistsListener, SaveWebpageDialog.SaveWebpageListener, StoragePermissionDialog.StoragePermissionDialogListener, UrlHistoryDialog.NavigateHistoryListener,
+        WebViewTabFragment.NewTabListener {
 
     // `orbotStatus` is public static so it can be accessed from `OrbotProxyHelper`.  It is also used in `onCreate()`, `onResume()`, and `applyProxy()`.
     public static String orbotStatus = "unknown";
@@ -200,7 +201,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
     // Start activity for result request codes.
     private final int FILE_UPLOAD_REQUEST_CODE = 0;
-    public final static int BROWSE_SAVE_WEBPAGE_IMAGE_REQUEST_CODE = 1;
+    public final static int BROWSE_SAVE_WEBPAGE_REQUEST_CODE = 1;
 
 
     // The current WebView is used in `onCreate()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, `onNavigationItemSelected()`, `onRestart()`, `onCreateContextMenu()`, `findPreviousOnPage()`,
@@ -311,13 +312,14 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     // `downloadImageUrl` is used in `onCreateContextMenu()` and `onRequestPermissionResult()`.
     private String downloadImageUrl;
 
-    // The save website image file path string is used in `onSaveWebpageImage()` and `onRequestPermissionResult()`
-    private String saveWebsiteImageFilePath;
+    // The save webpage file path string is used in `onSaveWebpageImage()` and `onRequestPermissionResult()`
+    private String saveWebpageFilePath;
 
     // The permission result request codes are used in `onCreateContextMenu()`, `onCloseDownloadLocationPermissionDialog()`, `onRequestPermissionResult()`, `onSaveWebpageImage()`,
     // `onCloseStoragePermissionDialog()`, and `initializeWebView()`.
-    private final int DOWNLOAD_FILE_REQUEST_CODE = 1;
-    private final int DOWNLOAD_IMAGE_REQUEST_CODE = 2;
+    private final int DOWNLOAD_FILE_REQUEST_CODE = 0;
+    private final int DOWNLOAD_IMAGE_REQUEST_CODE = 1;
+    private final int SAVE_WEBPAGE_ARCHIVE_REQUEST_CODE = 2;
     private final int SAVE_WEBPAGE_IMAGE_REQUEST_CODE = 3;
 
     @Override
@@ -1698,12 +1700,22 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // Consume the event.
                 return true;
 
+            case R.id.save_as_archive:
+                // Instantiate the save webpage archive dialog.
+                DialogFragment saveWebpageArchiveDialogFragment = SaveWebpageDialog.saveWebpage(SaveWebpageDialog.ARCHIVE);
+
+                // Show the save webpage archive dialog.
+                saveWebpageArchiveDialogFragment.show(getSupportFragmentManager(), getString(R.string.save_webpage));
+
+                // Consume the event.
+                return true;
+
             case R.id.save_as_image:
                 // Instantiate the save webpage image dialog.
-                DialogFragment saveWebpageImageDialogFragment = new SaveWebpageImageDialog();
+                DialogFragment saveWebpageImageDialogFragment = SaveWebpageDialog.saveWebpage(SaveWebpageDialog.IMAGE);
 
                 // Show the save webpage image dialog.
-                saveWebpageImageDialogFragment.show(getSupportFragmentManager(), getString(R.string.save_as_image));
+                saveWebpageImageDialogFragment.show(getSupportFragmentManager(), getString(R.string.save_webpage));
 
                 // Consume the event.
                 return true;
@@ -2680,18 +2692,32 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 downloadImageUrl = "";
                 break;
 
+            case SAVE_WEBPAGE_ARCHIVE_REQUEST_CODE:
+                // Check to see if the storage permission was granted.  If the dialog was canceled the grant results will be empty.
+                if ((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) {  // The storage permission was granted.
+                    // Save the webpage archive.
+                    currentWebView.saveWebArchive(saveWebpageFilePath);
+                } else {
+                    // Display an error snackbar.
+                    Snackbar.make(currentWebView, getString(R.string.cannot_use_location), Snackbar.LENGTH_LONG).show();
+                }
+
+                // Reset the save webpage file path.
+                saveWebpageFilePath = "";
+                break;
+
             case SAVE_WEBPAGE_IMAGE_REQUEST_CODE:
-                // Check to see if the storage permission was granted.  If the dialog was canceled the grant result will be empty.
+                // Check to see if the storage permission was granted.  If the dialog was canceled the grant results will be empty.
                 if ((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) {  // The storage permission was granted.
                     // Save the webpage image.
-                    new SaveWebpageImage(this, currentWebView).execute(saveWebsiteImageFilePath);
+                    new SaveWebpageImage(this, currentWebView).execute(saveWebpageFilePath);
                 } else {  // The storage permission was not granted.
                     // Display an error snackbar.
                     Snackbar.make(currentWebView, getString(R.string.cannot_use_location), Snackbar.LENGTH_LONG).show();
                 }
 
-                // Reset the save website image file path.
-                saveWebsiteImageFilePath = "";
+                // Reset the save webpage file path.
+                saveWebpageFilePath = "";
                 break;
         }
     }
@@ -2954,22 +2980,22 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 }
                 break;
 
-            case BROWSE_SAVE_WEBPAGE_IMAGE_REQUEST_CODE:
+            case BROWSE_SAVE_WEBPAGE_REQUEST_CODE:
                 // Don't do anything if the user pressed back from the file picker.
                 if (resultCode == Activity.RESULT_OK) {
                     // Get a handle for the save dialog fragment.
-                    DialogFragment saveWebpageImageDialogFragment= (DialogFragment) getSupportFragmentManager().findFragmentByTag(getString(R.string.save_as_image));
+                    DialogFragment saveWebpageDialogFragment= (DialogFragment) getSupportFragmentManager().findFragmentByTag(getString(R.string.save_webpage));
 
                     // Only update the file name if the dialog still exists.
-                    if (saveWebpageImageDialogFragment != null) {
-                        // Get a handle for the save webpage image dialog.
-                        Dialog saveWebpageImageDialog = saveWebpageImageDialogFragment.getDialog();
+                    if (saveWebpageDialogFragment != null) {
+                        // Get a handle for the save webpage dialog.
+                        Dialog saveWebpageDialog = saveWebpageDialogFragment.getDialog();
 
                         // Remove the incorrect lint warning below that the dialog might be null.
-                        assert saveWebpageImageDialog != null;
+                        assert saveWebpageDialog != null;
 
                         // Get a handle for the file name edit text.
-                        EditText fileNameEditText = saveWebpageImageDialog.findViewById(R.id.file_name_edittext);
+                        EditText fileNameEditText = saveWebpageDialog.findViewById(R.id.file_name_edittext);
 
                         // Instantiate the file name helper.
                         FileNameHelper fileNameHelper = new FileNameHelper();
@@ -3135,7 +3161,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     }
 
     @Override
-    public void onSaveWebpageImage(DialogFragment dialogFragment) {
+    public void onSaveWebpage(int saveType, DialogFragment dialogFragment) {
         // Get the dialog.
         Dialog dialog = dialogFragment.getDialog();
 
@@ -3146,12 +3172,22 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         EditText fileNameEditText = dialog.findViewById(R.id.file_name_edittext);
 
         // Get the file path string.
-        saveWebsiteImageFilePath = fileNameEditText.getText().toString();
+        saveWebpageFilePath = fileNameEditText.getText().toString();
 
         // Check to see if the storage permission is needed.
         if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {  // The storage permission has been granted.
-            // Save the webpage image.
-            new SaveWebpageImage(this, currentWebView).execute(saveWebsiteImageFilePath);
+            //Save the webpage according to the save type.
+            switch (saveType) {
+                case SaveWebpageDialog.ARCHIVE:
+                    // Save the webpage archive.
+                    currentWebView.saveWebArchive(saveWebpageFilePath);
+                    break;
+
+                case SaveWebpageDialog.IMAGE:
+                    // Save the webpage image.
+                    new SaveWebpageImage(this, currentWebView).execute(saveWebpageFilePath);
+                    break;
+            }
         } else {  // The storage permission has not been granted.
             // Get the external private directory `File`.
             File externalPrivateDirectoryFile = getExternalFilesDir(null);
@@ -3163,29 +3199,57 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             String externalPrivateDirectory = externalPrivateDirectoryFile.toString();
 
             // Check to see if the file path is in the external private directory.
-            if (saveWebsiteImageFilePath.startsWith(externalPrivateDirectory)) {  // The file path is in the external private directory.
-                // Save the webpage image.
-                new SaveWebpageImage(this, currentWebView).execute(saveWebsiteImageFilePath);
+            if (saveWebpageFilePath.startsWith(externalPrivateDirectory)) {  // The file path is in the external private directory.
+                //Save the webpage according to the save type.
+                switch (saveType) {
+                    case SaveWebpageDialog.ARCHIVE:
+                        // Save the webpage archive.
+                        currentWebView.saveWebArchive(saveWebpageFilePath);
+                        break;
+
+                    case SaveWebpageDialog.IMAGE:
+                        // Save the webpage image.
+                        new SaveWebpageImage(this, currentWebView).execute(saveWebpageFilePath);
+                        break;
+                }
             } else {  // The file path is in a public directory.
                 // Check if the user has previously denied the storage permission.
                 if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {  // Show a dialog explaining the request first.
                     // Instantiate the storage permission alert dialog.
-                    DialogFragment storagePermissionDialogFragment = new StoragePermissionDialog();
+                    DialogFragment storagePermissionDialogFragment = StoragePermissionDialog.displayDialog(saveType);
 
                     // Show the storage permission alert dialog.  The permission will be requested when the dialog is closed.
                     storagePermissionDialogFragment.show(getSupportFragmentManager(), getString(R.string.storage_permission));
                 } else {  // Show the permission request directly.
-                    // Request the write external storage permission.  The webpage image will be saved when it finishes.
-                    ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, SAVE_WEBPAGE_IMAGE_REQUEST_CODE);
+                    switch (saveType) {
+                        case SaveWebpageDialog.ARCHIVE:
+                            // Request the write external storage permission.  The webpage archive will be saved when it finishes.
+                            ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, SAVE_WEBPAGE_ARCHIVE_REQUEST_CODE);
+                            break;
+
+                        case SaveWebpageDialog.IMAGE:
+                            // Request the write external storage permission.  The webpage image will be saved when it finishes.
+                            ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, SAVE_WEBPAGE_IMAGE_REQUEST_CODE);
+                            break;
+                    }
                 }
             }
         }
     }
 
     @Override
-    public void onCloseStoragePermissionDialog() {
-        // Request the write external storage permission.  The webpage image will be saved when it finishes.
-        ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, SAVE_WEBPAGE_IMAGE_REQUEST_CODE);
+    public void onCloseStoragePermissionDialog(int saveType) {
+        switch (saveType) {
+            case SaveWebpageDialog.ARCHIVE:
+                // Request the write external storage permission.  The webpage archive will be saved when it finishes.
+                ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, SAVE_WEBPAGE_ARCHIVE_REQUEST_CODE);
+                break;
+
+            case SaveWebpageDialog.IMAGE:
+                // Request the write external storage permission.  The webpage image will be saved when it finishes.
+                ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, SAVE_WEBPAGE_IMAGE_REQUEST_CODE);
+                break;
+        }
     }
 
     private void applyAppSettings() {
diff --git a/app/src/main/java/com/stoutner/privacybrowser/dialogs/SaveWebpageDialog.java b/app/src/main/java/com/stoutner/privacybrowser/dialogs/SaveWebpageDialog.java
new file mode 100644 (file)
index 0000000..1c24e0b
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ * Copyright © 2019 Soren Stoutner <soren@stoutner.com>.
+ *
+ * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
+ *
+ * Privacy Browser is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Privacy Browser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.stoutner.privacybrowser.dialogs;
+
+import android.Manifest;
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Environment;
+import android.provider.DocumentsContract;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.core.content.ContextCompat;
+import androidx.fragment.app.DialogFragment;
+import androidx.preference.PreferenceManager;
+
+import com.stoutner.privacybrowser.R;
+import com.stoutner.privacybrowser.activities.MainWebViewActivity;
+
+public class SaveWebpageDialog extends DialogFragment {
+    // Define the save type constants.
+    public static final int ARCHIVE = 0;
+    public static final int IMAGE = 1;
+
+    // Define the save webpage listener.
+    private SaveWebpageListener saveWebpageListener;
+
+    // The public interface is used to send information back to the parent activity.
+    public interface SaveWebpageListener {
+        void onSaveWebpage(int saveType, DialogFragment dialogFragment);
+    }
+
+    @Override
+    public void onAttach(@NonNull Context context) {
+        // Run the default commands.
+        super.onAttach(context);
+
+        // Get a handle for the save webpage listener from the launching context.
+        saveWebpageListener = (SaveWebpageListener) context;
+    }
+
+    public static SaveWebpageDialog saveWebpage(int saveType) {
+        // Create an arguments bundle.
+        Bundle argumentsBundle = new Bundle();
+
+        // Store the save type in the bundle.
+        argumentsBundle.putInt("save_type", saveType);
+
+        // Create a new instance of the save webpage dialog.
+        SaveWebpageDialog saveWebpageDialog = new SaveWebpageDialog();
+
+        // Add the arguments bundle to the new dialog.
+        saveWebpageDialog.setArguments(argumentsBundle);
+
+        // Return the new dialog.
+        return saveWebpageDialog;
+    }
+
+    // `@SuppressLing("InflateParams")` removes the warning about using null as the parent view group when inflating the alert dialog.
+    @SuppressLint("InflateParams")
+    @Override
+    @NonNull
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        // Get a handle for the arguments.
+        Bundle arguments = getArguments();
+
+        // Remove the incorrect lint warning that the arguments might be null.
+        assert arguments != null;
+
+        // Get the save type.
+        int saveType = arguments.getInt("save_type");
+
+        // Get a handle for the activity and the context.
+        Activity activity = getActivity();
+        Context context = getContext();
+
+        // Remove the incorrect lint warnings below that the activity and context might be null.
+        assert activity != null;
+        assert context != null;
+
+        // Get a handle for the shared preferences.
+        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
+
+        // Get the screenshot and theme preferences.
+        boolean darkTheme = sharedPreferences.getBoolean("dark_theme", false);
+        boolean allowScreenshots = sharedPreferences.getBoolean("allow_screenshots", false);
+
+        // Use an alert dialog builder to create the alert dialog.
+        AlertDialog.Builder dialogBuilder;
+
+        // Set the style and icon according to the theme.
+        if (darkTheme) {
+            // Set the style.
+            dialogBuilder = new AlertDialog.Builder(activity, R.style.PrivacyBrowserAlertDialogDark);
+
+            // Set the icon according to the save type.
+            switch (saveType) {
+                case ARCHIVE:
+                    dialogBuilder.setIcon(R.drawable.dom_storage_cleared_dark);
+                    break;
+
+                case IMAGE:
+                    dialogBuilder.setIcon(R.drawable.images_enabled_dark);
+                    break;
+            }
+        } else {
+            // Set the style.
+            dialogBuilder = new AlertDialog.Builder(activity, R.style.PrivacyBrowserAlertDialogLight);
+
+            // Set the icon according to the save type.
+            switch (saveType) {
+                case ARCHIVE:
+                    dialogBuilder.setIcon(R.drawable.dom_storage_cleared_light);
+                    break;
+
+                case IMAGE:
+                    dialogBuilder.setIcon(R.drawable.images_enabled_light);
+                    break;
+            }
+        }
+
+        // Set the title according to the type.
+        switch (saveType) {
+            case ARCHIVE:
+                dialogBuilder.setTitle(R.string.save_archive);
+                break;
+
+            case IMAGE:
+                dialogBuilder.setTitle(R.string.save_image);
+                break;
+        }
+
+        // Set the view.  The parent view is null because it will be assigned by the alert dialog.
+        dialogBuilder.setView(activity.getLayoutInflater().inflate(R.layout.save_dialog, null));
+
+        // Set the cancel button listener.  Using `null` as the listener closes the dialog without doing anything else.
+        dialogBuilder.setNegativeButton(R.string.cancel, null);
+
+        // Set the save button listener.
+        dialogBuilder.setPositiveButton(R.string.save, (DialogInterface dialog, int which) -> {
+            // Return the dialog fragment to the parent activity.
+            saveWebpageListener.onSaveWebpage(saveType, this);
+        });
+
+        // Create an alert dialog from the builder.
+        AlertDialog alertDialog = dialogBuilder.create();
+
+        // Remove the incorrect lint warning below that `getWindow()` might be null.
+        assert alertDialog.getWindow() != null;
+
+        // Disable screenshots if not allowed.
+        if (!allowScreenshots) {
+            alertDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
+        }
+
+        // The alert dialog must be shown before items in the layout can be modified.
+        alertDialog.show();
+
+        // Get handles for the layout items.
+        EditText fileNameEditText = alertDialog.findViewById(R.id.file_name_edittext);
+        Button browseButton = alertDialog.findViewById(R.id.browse_button);
+        TextView storagePermissionTextView = alertDialog.findViewById(R.id.storage_permission_textview);
+        Button saveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
+
+        // Create a default file name string.
+        String defaultFileName = "";
+
+        // Set the default file name according to the type.
+        switch (saveType) {
+            case ARCHIVE:
+                defaultFileName = getString(R.string.webpage_mht);
+                break;
+
+            case IMAGE:
+                defaultFileName = getString(R.string.webpage_png);
+                break;
+        }
+
+        // Create a string for the default file path.
+        String defaultFilePath;
+
+        // Set the default file path according to the storage permission state.
+        if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {  // The storage permission has been granted.
+            // Set the default file path to use the external public directory.
+            defaultFilePath = Environment.getExternalStorageDirectory() + "/" + defaultFileName;
+        } else {  // The storage permission has not been granted.
+            // Set the default file path to use the external private directory.
+            defaultFilePath = context.getExternalFilesDir(null) + "/" + defaultFileName;
+        }
+
+        // Display the default file path.
+        fileNameEditText.setText(defaultFilePath);
+
+        // Update the status of the save button when the file name changes.
+        fileNameEditText.addTextChangedListener(new TextWatcher() {
+            @Override
+            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+                // Do nothing.
+            }
+
+            @Override
+            public void onTextChanged(CharSequence s, int start, int before, int count) {
+                // Do nothing.
+            }
+
+            @Override
+            public void afterTextChanged(Editable s) {
+                // // Enable the save button if a file name exists.
+                saveButton.setEnabled(!fileNameEditText.getText().toString().isEmpty());
+            }
+        });
+
+        // Handle clicks on the browse button.
+        browseButton.setOnClickListener((View view) -> {
+            // Create the file picker intent.
+            Intent browseIntent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
+
+            // Set the intent MIME type to include all files so that everything is visible.
+            browseIntent.setType("*/*");
+
+            // Set the initial file name according to the type.
+            switch (saveType) {
+                case ARCHIVE:
+                    browseIntent.putExtra(Intent.EXTRA_TITLE, getString(R.string.webpage_mht));
+                    break;
+
+                case IMAGE:
+                    browseIntent.putExtra(Intent.EXTRA_TITLE, getString(R.string.webpage_png));
+                    break;
+            }
+
+            // Set the initial directory if the minimum API >= 26.
+            if (Build.VERSION.SDK_INT >= 26) {
+                browseIntent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.getExternalStorageDirectory());
+            }
+
+            // Request a file that can be opened.
+            browseIntent.addCategory(Intent.CATEGORY_OPENABLE);
+
+            // Start the file picker.  This must be started under `activity` so that the request code is returned correctly.
+            activity.startActivityForResult(browseIntent, MainWebViewActivity.BROWSE_SAVE_WEBPAGE_REQUEST_CODE);
+        });
+
+        // Hide the storage permission text view on API < 23 as permissions on older devices are automatically granted.
+        if (Build.VERSION.SDK_INT < 23) {
+            storagePermissionTextView.setVisibility(View.GONE);
+        }
+
+        // Return the alert dialog.
+        return alertDialog;
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/stoutner/privacybrowser/dialogs/SaveWebpageImageDialog.java b/app/src/main/java/com/stoutner/privacybrowser/dialogs/SaveWebpageImageDialog.java
deleted file mode 100644 (file)
index a9277d9..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright © 2019 Soren Stoutner <soren@stoutner.com>.
- *
- * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
- *
- * Privacy Browser is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Privacy Browser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.stoutner.privacybrowser.dialogs;
-
-import android.Manifest;
-import android.annotation.SuppressLint;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Environment;
-import android.provider.DocumentsContract;
-import android.text.Editable;
-import android.text.TextWatcher;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.core.content.ContextCompat;
-import androidx.fragment.app.DialogFragment;
-import androidx.preference.PreferenceManager;
-
-import com.stoutner.privacybrowser.R;
-import com.stoutner.privacybrowser.activities.MainWebViewActivity;
-
-public class SaveWebpageImageDialog extends DialogFragment {
-    // Define the save webpage image listener.
-    private SaveWebpageImageListener saveWebpageImageListener;
-
-    // The public interface is used to send information back to the parent activity.
-    public interface SaveWebpageImageListener {
-        void onSaveWebpageImage(DialogFragment dialogFragment);
-    }
-
-    @Override
-    public void onAttach(@NonNull Context context) {
-        // Run the default commands.
-        super.onAttach(context);
-
-        // Get a handle for the save webpage image listener from the launching context.
-        saveWebpageImageListener = (SaveWebpageImageListener) context;
-    }
-
-    // `@SuppressLing("InflateParams")` removes the warning about using null as the parent view group when inflating the alert dialog.
-    @SuppressLint("InflateParams")
-    @Override
-    @NonNull
-    public Dialog onCreateDialog(Bundle savedInstanceState) {
-        // Get a handle for the activity and the context.
-        Activity activity = getActivity();
-        Context context = getContext();
-
-        // Remove the incorrect lint warnings below that the activity and context might be null.
-        assert activity != null;
-        assert context != null;
-
-        // Get a handle for the shared preferences.
-        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
-
-        // Get the screenshot and theme preferences.
-        boolean darkTheme = sharedPreferences.getBoolean("dark_theme", false);
-        boolean allowScreenshots = sharedPreferences.getBoolean("allow_screenshots", false);
-
-        // Use an alert dialog builder to create the alert dialog.
-        AlertDialog.Builder dialogBuilder;
-
-        // Set the style and icon according to the theme.
-        if (darkTheme) {
-            dialogBuilder = new AlertDialog.Builder(activity, R.style.PrivacyBrowserAlertDialogDark);
-            dialogBuilder.setIcon(R.drawable.images_enabled_dark);
-        } else {
-            dialogBuilder = new AlertDialog.Builder(activity, R.style.PrivacyBrowserAlertDialogLight);
-            dialogBuilder.setIcon(R.drawable.images_enabled_light);
-        }
-
-        // Set the title.
-        dialogBuilder.setTitle(R.string.save_image);
-
-        // Set the view.  The parent view is null because it will be assigned by the alert dialog.
-        dialogBuilder.setView(activity.getLayoutInflater().inflate(R.layout.save_dialog, null));
-
-        // Set the cancel button listener.  Using `null` as the listener closes the dialog without doing anything else.
-        dialogBuilder.setNegativeButton(R.string.cancel, null);
-
-        // Set the save button listener.
-        dialogBuilder.setPositiveButton(R.string.save, (DialogInterface dialog, int which) -> {
-            // Return the dialog fragment to the parent activity.
-            saveWebpageImageListener.onSaveWebpageImage(this);
-        });
-
-        // Create an alert dialog from the builder.
-        AlertDialog alertDialog = dialogBuilder.create();
-
-        // Remove the incorrect lint warning below that `getWindow()` might be null.
-        assert alertDialog.getWindow() != null;
-
-        // Disable screenshots if not allowed.
-        if (!allowScreenshots) {
-            alertDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
-        }
-
-        // The alert dialog must be shown before items in the layout can be modified.
-        alertDialog.show();
-
-        // Get handles for the layout items.
-        EditText fileNameEditText = alertDialog.findViewById(R.id.file_name_edittext);
-        Button browseButton = alertDialog.findViewById(R.id.browse_button);
-        TextView storagePermissionTextView = alertDialog.findViewById(R.id.storage_permission_textview);
-        Button saveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
-
-        // Create a string for the default file path.
-        String defaultFilePath;
-
-        // Set the default file path according to the storage permission state.
-        if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {  // The storage permission has been granted.
-            // Set the default file path to use the external public directory.
-            defaultFilePath = Environment.getExternalStorageDirectory() + "/" + getString(R.string.webpage_png);
-        } else {  // The storage permission has not been granted.
-            // Set the default file path to use the external private directory.
-            defaultFilePath = context.getExternalFilesDir(null) + "/" + getString(R.string.webpage_png);
-        }
-
-        // Display the default file path.
-        fileNameEditText.setText(defaultFilePath);
-
-        // Update the status of the save button when the file name changes.
-        fileNameEditText.addTextChangedListener(new TextWatcher() {
-            @Override
-            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
-                // Do nothing.
-            }
-
-            @Override
-            public void onTextChanged(CharSequence s, int start, int before, int count) {
-                // Do nothing.
-            }
-
-            @Override
-            public void afterTextChanged(Editable s) {
-                // // Enable the save button if a file name exists.
-                saveButton.setEnabled(!fileNameEditText.getText().toString().isEmpty());
-            }
-        });
-
-        // Handle clicks on the browse button.
-        browseButton.setOnClickListener((View view) -> {
-            // Create the file picker intent.
-            Intent browseIntent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
-
-            // Set the intent MIME type to include all files so that everything is visible.
-            browseIntent.setType("*/*");
-
-            // Set the initial file name.
-            browseIntent.putExtra(Intent.EXTRA_TITLE, getString(R.string.webpage_png));
-
-            // Set the initial directory if the minimum API >= 26.
-            if (Build.VERSION.SDK_INT >= 26) {
-                browseIntent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.getExternalStorageDirectory());
-            }
-
-            // Request a file that can be opened.
-            browseIntent.addCategory(Intent.CATEGORY_OPENABLE);
-
-            // Start the file picker.  This must be started under `activity` so that the request code is returned correctly.
-            activity.startActivityForResult(browseIntent, MainWebViewActivity.BROWSE_SAVE_WEBPAGE_IMAGE_REQUEST_CODE);
-        });
-
-        // Hide the storage permission text view on API < 23 as permissions on older devices are automatically granted.
-        if (Build.VERSION.SDK_INT < 23) {
-            storagePermissionTextView.setVisibility(View.GONE);
-        }
-
-        // Return the alert dialog.
-        return alertDialog;
-    }
-}
\ No newline at end of file
index 198eb509703ed9ee9d859238d0c58bafeafe10ab..1ee03b8f9db5abd4f64b4673abde160385434e6d 100644 (file)
@@ -39,7 +39,7 @@ public class StoragePermissionDialog extends DialogFragment {
 
     // The public interface is used to send information back to the parent activity.
     public interface StoragePermissionDialogListener {
-        void onCloseStoragePermissionDialog();
+        void onCloseStoragePermissionDialog(int saveType);
     }
 
     @Override
@@ -51,11 +51,34 @@ public class StoragePermissionDialog extends DialogFragment {
         storagePermissionDialogListener = (StoragePermissionDialogListener) context;
     }
 
+    public static StoragePermissionDialog displayDialog(int saveType) {
+        // Create an arguments bundle.
+        Bundle argumentsBundle = new Bundle();
+
+        // Store the save type in the bundle.
+        argumentsBundle.putInt("save_type", saveType);
+
+        // Create a new instance of the storage permission dialog.
+        StoragePermissionDialog storagePermissionDialog = new StoragePermissionDialog();
+
+        // Add the arguments bundle to the new dialog.
+        storagePermissionDialog.setArguments(argumentsBundle);
+
+        // Return the new dialog.
+        return storagePermissionDialog;
+    }
+
     @NonNull
     @Override
     public Dialog onCreateDialog(Bundle savedInstanceState) {
-        // Use a builder to create the alert dialog.
-        AlertDialog.Builder dialogBuilder;
+        // Get a handle for the arguments.
+        Bundle arguments = getArguments();
+
+        // Remove the incorrect lint warning that the arguments might be null.
+        assert arguments != null;
+
+        // Get the save type.
+        int saveType = arguments.getInt("save_type");
 
         // Get a handle for the shared preferences.
         SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getContext());
@@ -64,6 +87,9 @@ public class StoragePermissionDialog extends DialogFragment {
         boolean darkTheme = sharedPreferences.getBoolean("dark_theme", false);
         boolean allowScreenshots = sharedPreferences.getBoolean("allow_screenshots", false);
 
+        // Use a builder to create the alert dialog.
+        AlertDialog.Builder dialogBuilder;
+
         // Set the style and the icon according to the theme.
         if (darkTheme) {
             dialogBuilder = new AlertDialog.Builder(getActivity(), R.style.PrivacyBrowserAlertDialogDark);
@@ -79,10 +105,10 @@ public class StoragePermissionDialog extends DialogFragment {
         // Set the text.
         dialogBuilder.setMessage(R.string.storage_permission_message);
 
-        // Set an `onClick` listener on the negative button.
+        // Set an listener on the OK button.
         dialogBuilder.setNegativeButton(R.string.ok, (DialogInterface dialog, int which) -> {
             // Inform the parent activity that the dialog was closed.
-            storagePermissionDialogListener.onCloseStoragePermissionDialog();
+            storagePermissionDialogListener.onCloseStoragePermissionDialog(saveType);
         });
 
         // Create an alert dialog from the builder.
@@ -97,7 +123,7 @@ public class StoragePermissionDialog extends DialogFragment {
             alertDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
         }
 
-        // `onCreateDialog()` requires the return of an `AlertDialog`.
+        // Return the alert dialog.
         return alertDialog;
     }
 }
\ No newline at end of file
index 21cdea86aa78ccda627a5ffb3819325388bd5a5c..1847f4fcf47d4e0fd216d0d72d2688914bbd7e2f 100644 (file)
@@ -1,4 +1,4 @@
-<!-- `import_export_dark.xml` comes from the Android Material icon set, where it is called `import_export`.  It is released under the Apache License 2.0. -->
+<!-- This drawable comes from the Android Material icon set, where it is called `import_export`.  It is released under the Apache License 2.0. -->
 
 <!-- `tools:ignore="VectorRaster"` removes the lint warning about `android:autoMirrored="true"` not applying to API < 21. -->
 <vector
@@ -13,6 +13,6 @@
 
     <!-- A hard coded color must be used until API >= 21.  Then `@color` may be used. -->
     <path
-        android:fillColor="#FFE0E0E0"
+        android:fillColor="#FF1E88E5"
         android:pathData="M9,3L5,6.99h3L8,14h2L10,6.99h3L9,3zM16,17.01L16,10h-2v7.01h-3L15,21l4,-3.99h-3z" />
-</vector>
+</vector>
\ No newline at end of file
index 602cf376ab72aa5a73ef6d0f62b6b4cdd238b781..119da8c87e3652205bcaad603d8905f562dccd05 100644 (file)
@@ -1,4 +1,4 @@
-<!-- `import_export_light.xml` comes from the Android Material icon set, where it is called `import_export`.  It is released under the Apache License 2.0. -->
+<!-- This drawable comes from the Android Material icon set, where it is called `import_export`.  It is released under the Apache License 2.0. -->
 
 <!-- `tools:ignore="VectorRaster"` removes the lint warning about `android:autoMirrored="true"` not applying to API < 21. -->
 <vector
@@ -13,6 +13,6 @@
 
     <!-- A hard coded color must be used until API >= 21.  Then `@color` may be used. -->
     <path
-        android:fillColor="#FF000000"
+        android:fillColor="#FF1565C0"
         android:pathData="M9,3L5,6.99h3L8,14h2L10,6.99h3L9,3zM16,17.01L16,10h-2v7.01h-3L15,21l4,-3.99h-3z" />
-</vector>
+</vector>
\ No newline at end of file
index 744873fc92d9bea4e95e01f75faa8837e97e291d..28aed273f09ed874bc660329f60aa1646254f59d 100644 (file)
                 android:id="@+id/font_size"
                 android:title="@string/font_size"
                 android:orderInCategory="1070"
-                app:showAsAction="never" >
-            </item>
+                app:showAsAction="never" />
 
             <item
                 android:id="@+id/find_on_page"
                 app:showAsAction="never" />
 
             <item
-                android:id="@+id/save_as_image"
-                android:title="@string/save_as_image"
+                android:id="@+id/save"
+                android:title="@string/save"
                 android:orderInCategory="1100"
-                app:showAsAction="never" />
+                app:showAsAction="never" >
+
+                <menu>
+                    <item
+                        android:id="@+id/save_as_archive"
+                        android:title="@string/save_as_archive"
+                        android:orderInCategory="1101"
+                        app:showAsAction="never" />
+
+                    <item
+                        android:id="@+id/save_as_image"
+                        android:title="@string/save_as_image"
+                        android:orderInCategory="1102"
+                        app:showAsAction="never" />
+                </menu>
+            </item>
 
             <item
                 android:id="@+id/add_to_homescreen"
index 8c92e52879916ec1d928c4a347b24ed79a84cb84..46c55226e89fe47d491772b98bfbe03ff53aaa22 100644 (file)
         <string name="find_on_page">Auf Seite finden</string>
         <string name="print">Drucken</string>
             <string name="privacy_browser_web_page">Privacy Browser-Website</string>
-        <string name="save_as_image">Als Grafik speichern</string>
+        <string name="save">Speichern</string>
+            <string name="save_as_image">Als Grafik speichern</string>
         <string name="view_source">Quelltext anzeigen</string>
         <string name="add_to_home_screen">Zur Startseite hinzufügen</string>
     <string name="share">Teilen</string>
     <string name="edit_folder">Ordner bearbeiten</string>
     <string name="move_to_folder">In Ordner verschieben</string>
     <string name="move">Verschieben</string>
-    <string name="save">Speichern</string>
 
     <!-- Bookmarks Contextual App Bar. -->
     <string name="selected">Ausgewählt:</string>  <!--This is a plural adjective.-->
     <string name="i2p_not_installed_title">I2P ist nicht installiert</string>
     <string name="i2p_not_installed_message">Der I2P-Proxy kann erst nach Installation der I2P-App genutzt werden.</string>
     <string name="waiting_for_orbot">Warte auf die Verbindung zum Orbot-Proxy.</string>
+    <string name="custom_proxy_invalid">Die benutzerdefinierte Proxy-URL ist ungültig.</string>
+    <string name="socks_proxies_do_not_work_on_kitkat">SOCKS-Proxies funktionieren nicht unter Android KitKat.</string>
 
     <!-- About Activity. -->
     <string name="about_privacy_browser">Über Privacy Browser</string>
             <item>I2P</item>
             <item>Benutzerdefiniert</item>
         </string-array>
+        <string name="no_proxy_enabled">Keiner - direkte Verbindung zum Internet.</string>
+        <string name="tor_enabled">Tor - Verbidnung über socks://localhost:9050.</string>
+        <string name="tor_enabled_kitkat">Tor - Verbidnung über http://localhost:8118.</string>
+        <string name="i2p_enabled">I2P - Verbindung über http://localhost:4444.</string>
         <string name="custom_proxy">Benutzerdefinierter Proxy</string>
+        <string name="proxy_custom_url">Benutzerdefinierte Proxy-URL</string>
     <string name="full_screen">Vollbild-Modus</string>
         <string name="full_screen_browsing_mode">Vollbild-Browser-Modus</string>
         <string name="full_screen_browsing_mode_summary">Doppel-Tippen, um zwischen normalem und Vollbild-Modus umzuschalten.</string>
index ff1803e8f87ea9706b33d7678d87c365c8514a4f..983c125a3dd46ca33aabb8c63b0f812c898c51e0 100644 (file)
         <string name="find_on_page">Buscar en página</string>
         <string name="print">Imprimir</string>
             <string name="privacy_browser_web_page">Página web de Navegador Privado</string>
-        <string name="save_as_image">Guardar como imagen</string>
+        <string name="save">Guardar</string>
+            <string name="save_as_image">Guardar como imagen</string>
         <string name="add_to_home_screen">Añadir a la ventana de inicio</string>
         <string name="view_source">Ver la fuente</string>
     <string name="share">Compartir</string>
     <string name="edit_folder">Editar carpeta</string>
     <string name="move_to_folder">Mover a carpeta</string>
     <string name="move">Mover</string>
-    <string name="save">Guardar</string>
 
     <!-- Bookmarks Contextual App Bar. -->
     <string name="selected">Seleccionados:</string>  <!--This is a plural adjective.-->
     <string name="i2p_not_installed_title">I2P No Instalado</string>
     <string name="i2p_not_installed_message">El proxy a través de I2P no funcionará a menos que la aplicación I2P esté instalada.</string>
     <string name="waiting_for_orbot">Esperando a que Orbot se conecte.</string>
+    <string name="custom_proxy_invalid">La URL del proxy personalizado no es válida.</string>
+    <string name="socks_proxies_do_not_work_on_kitkat">SOCKS proxies do not work on Android KitKat.</string>
 
     <!-- About Activity. -->
     <string name="about_privacy_browser">Acerca de Navegador Privado</string>
             <item>Yahoo - Javascript habilitado</item>
             <item>Personalizado</item>
         </string-array>
+        <string name="no_proxy_enabled">Ninguno - conectar directamente a Internet.</string>
+        <string name="tor_enabled">Tor - conectar a través de socks://localhost:9050.</string>
+        <string name="tor_enabled_kitkat">Tor - conectar a través de http://localhost:8118.</string>
+        <string name="i2p_enabled">I2P - conectar a través de http://localhost:4444.</string>
         <string name="search_custom_url">URL personalizado de búsqueda</string>
         <string name="custom_url">URL personalizado</string>
+        <string name="proxy_custom_url">URL personalizada del proxy</string>
     <string name="proxy">Proxy</string>
         <string name="proxy_none">Ninguno</string>
         <string name="proxy_tor">Tor</string>
index 2a6668ea6b91bfb603186d0643fc9cd0f7a1446a..fc9a20ed6411c91f522b33428593a1a52a99aa0e 100644 (file)
         <string name="find_on_page">Chercher sur la page</string>
         <string name="print">Imprimer</string>
             <string name="privacy_browser_web_page">Site Web de Privacy Browser</string>
-        <string name="save_as_image">Sauvergarder comme image</string>
+        <string name="save">Sauvegarder</string>
+            <string name="save_as_image">Sauvergarder comme image</string>
         <string name="add_to_home_screen">Ajouter à l\'écran d\'accueil</string>
         <string name="view_source">Voir Source</string>
     <string name="share">Partager</string>
     <string name="edit_folder">Editer dossier</string>
     <string name="move_to_folder">Déplacer vers dossier</string>
     <string name="move">Déplacer</string>
-    <string name="save">Sauvegarder</string>
 
     <!-- Bookmarks Contextual App Bar. -->
     <string name="selected">Selectionnés :</string>  <!--This is a plural adjective.-->
     <string name="i2p_not_installed_title">I2P non installé</string>
     <string name="i2p_not_installed_message">Le proxy via I2P ne fonctionnera que si l\'application I2P est installée.</string>
     <string name="waiting_for_orbot">En attente de la connexion d\'Orbot.</string>
+    <string name="custom_proxy_invalid">L\'URL du proxy personnalisé n\'est pas valide.</string>
+    <string name="socks_proxies_do_not_work_on_kitkat">Les proxys de type SOCKS ne fonctionnent pas sur Android KitKat.</string>
 
     <!-- About Activity. -->
     <string name="about_privacy_browser">À propos</string>
             <item>I2P</item>
             <item>Personnalisé</item>
         </string-array>
+        <string name="no_proxy_enabled">Aucun - Connectez-vous directement à Internet.</string>
+        <string name="tor_enabled">Tor - Connectez-vous via socks://localhost:9050.</string>
+        <string name="tor_enabled_kitkat">Tor - Connectez-vous via http://localhost:8118.</string>
+        <string name="i2p_enabled">I2P - Connectez-vous via http://localhost:4444.</string>
         <string name="custom_proxy">Proxy personnalisé</string>
+        <string name="proxy_custom_url">URL personnalisée du proxy</string>
     <string name="full_screen">Plein écran</string>
         <string name="full_screen_browsing_mode">Navigation plein écran</string>
         <string name="full_screen_browsing_mode_summary">Appuyez deux fois pour basculer en mode de navigation en plein écran.</string>
index fdb966231478bc335e6a9b7497a7c3b352bd3004..757c3ee05199a941b0b7311d11de6e5da291beb2 100644 (file)
         <string name="find_on_page">Cerca nella pagina</string>
         <string name="print">Stampa</string>
             <string name="privacy_browser_web_page">Pagina web di Privacy Browser</string>
-        <string name="save_as_image">Salva come Immagine</string>
+        <string name="save">Salva</string>
+            <string name="save_as_image">Salva come Immagine</string>
         <string name="add_to_home_screen">Aggiungi collegamento</string>
         <string name="view_source">Visualizza sorgente</string>
     <string name="share">Condividi</string>
     <string name="edit_folder">Modifica Cartella</string>
     <string name="move_to_folder">Sposta nella Cartella</string>
     <string name="move">Sposta</string>
-    <string name="save">Salva</string>
 
     <!-- Bookmarks Contextual App Bar. -->
     <string name="selected">Selezionato:</string>  <!--This is a plural adjective.-->
     <string name="overview">Descrizione</string>
     <string name="local_storage">Archiviazione Locale</string>
     <string name="ssl_certificates">Certificati SSL</string>
+    <string name="proxies">Proxy</string>
     <string name="tracking_ids">Tracciamento utenti</string>
 
     <!-- Download Location -->
         Nel caso in cui il permesso sia negato sarà utilizzata la cartella di download dell\'applicazione.</string>
     <string name="ok">OK</string>
 
-    <!-- Orbot. -->
+    <!-- Proxy. -->
+    <string name="orbot_not_installed_title">Orbot Non Installato</string>
+    <string name="orbot_not_installed_message">Il Proxy con Orbot non funziona se non è installata la app Orbot.</string>
+    <string name="i2p_not_installed_title">I2P Non Installato</string>
+    <string name="i2p_not_installed_message">Il Proxy con I2P non funziona se non è installata la app I2P.</string>
     <string name="waiting_for_orbot">In attesa della connessione di Orbot.</string>
+    <string name="custom_proxy_invalid">La URL del proxy personalizzato non è valida.</string>
+    <string name="socks_proxies_do_not_work_on_kitkat">I proxy SOCKS non funzionano con Android KitKat.</string>
 
     <!-- About Activity. -->
     <string name="about_privacy_browser">Informazioni su Privacy Browser</string>
     <string name="webview_provider">Provider di WebView:</string>
     <string name="webview_version">Versione di WebView:</string>
     <string name="orbot">Orbot:</string>
+    <string name="i2p">I2P:</string>
     <string name="openkeychain">OpenKeychain:</string>
     <string name="easylist_label">EasyList:</string>
     <string name="easyprivacy_label">EasyPrivacy:</string>
         </string-array>
         <string name="search_custom_url">Ricerca personalizzata</string>
         <string name="custom_url">URL Personalizzata</string>
+    <string name="proxy">Proxy</string>
+        <string name="proxy_none">Nessuno</string>
+        <string name="proxy_tor">Tor</string>
+        <string name="proxy_i2p">I2P</string>
+        <string name="proxy_custom">Personalizzato</string>
+        <string-array name="proxy_entries">
+            <item>Nessuno</item>
+            <item>Tor</item>
+            <item>I2P</item>
+            <item>Personalizzato</item>
+        </string-array>
+        <string name="no_proxy_enabled">Nessuno - connessione diretta a internet.</string>
+        <string name="tor_enabled">Tor - connessione con socks://localhost:9050.</string>
+        <string name="tor_enabled_kitkat">Tor - connessione con http://localhost:8118.</string>
+        <string name="i2p_enabled">I2P - connessione con http://localhost:4444.</string>
+        <string name="custom_proxy">Proxy personalizzato</string>
+        <string name="proxy_custom_url">URL personalizzata del Proxy</string>
     <string name="full_screen">Schermo intero</string>
         <string name="full_screen_browsing_mode">Navigazione a schermo intero</string>
         <string name="full_screen_browsing_mode_summary">Toccare due volte per avviare la navigazione a schermo intero.</string>
index 83fdac30e3819f9b4ebf893aa9212e8cdb3b837b..6ee136bbc3c201c7fdf507e9d731fc02e6608cca 100644 (file)
         <string name="find_on_page">Найти на странице</string>
         <string name="print">Печать</string>
             <string name="privacy_browser_web_page">Privacy Browser веб-страница</string>
-        <string name="save_as_image">Сохранить как изображение</string>
+        <string name="save">Сохранить</string>
+            <string name="save_as_image">Сохранить как изображение</string>
         <string name="add_to_home_screen">Добавить на главный экран</string>
         <string name="view_source">Просмотр исходного кода</string>
     <string name="share">Поделиться</string>
     <string name="edit_folder">Изменить папку</string>
     <string name="move_to_folder">Переместить в папку</string>
     <string name="move">Переместить</string>
-    <string name="save">Сохранить</string>
 
     <!-- Bookmarks Contextual App Bar. -->
     <string name="selected">выбраны:</string>  <!--This is a plural adjective.-->
     <string name="i2p_not_installed_title">I2P не установлен</string>
     <string name="i2p_not_installed_message">Прокси через I2P работать не будет, если приложение I2P не установлено.</string>
     <string name="waiting_for_orbot">Ожидание подключения Orbot.</string>
+    <string name="custom_proxy_invalid">URL пользовательского прокси недействителен.</string>
+    <string name="socks_proxies_do_not_work_on_kitkat">SOCKS-прокси не работает на Android KitKat.</string>
 
     <!-- About Activity. -->
     <string name="about_privacy_browser">О Privacy Browser</string>
             <item>I2P</item>
             <item>Пользовательский</item>
         </string-array>
+        <string name="no_proxy_enabled">Нет - подключиться к интернету напрямую.</string>
+        <string name="tor_enabled">Tor - connect through socks://localhost:9050.</string>
+        <string name="tor_enabled_kitkat">Tor - подключиться через http://localhost:8118.</string>
+        <string name="i2p_enabled">I2P - подключиться через http://localhost:4444.</string>
         <string name="custom_proxy">Пользовательский прокси</string>
+        <string name="proxy_custom_url">URL пользовательского прокси</string>
     <string name="full_screen">Во весь экран</string>
         <string name="full_screen_browsing_mode">Полноэкранный режим просмотра</string>
         <string name="full_screen_browsing_mode_summary">Двойное касание переключает режим просмотра.</string>
index 73416b7672f206ae01e721866ec04e4e24507f24..c215b005063cdcfaef58c24e1b30953fc8c07799 100644 (file)
         <string name="find_on_page">Sayfada bul</string>
         <string name="print">Yazdır</string>
             <string name="privacy_browser_web_page">Privacy Browser Web Sayfası</string>
-        <string name="save_as_image">Resmi farklı kaydet</string>
+        <string name="save">Kaydet</string>
+            <string name="save_as_image">Resmi farklı kaydet</string>
         <string name="add_to_home_screen">Ana ekrana ekle</string>
         <string name="view_source">Kaynağı görüntüle</string>
     <string name="share">Paylaş</string>
     <string name="edit_folder">Klasörü düzenle</string>
     <string name="move_to_folder">Klasöre taşı</string>
     <string name="move">Taşı</string>
-    <string name="save">Kaydet</string>
 
     <!-- Bookmarks Contextual App Bar. -->
     <string name="selected">Seçili:</string>  <!--This is a plural adjective.-->
index 5e8575cfd0b7a9205e07626fa922c1db770f6397..c486baf3ffe2bf77c04eb5e0b93b92a1353029dc 100644 (file)
         <string name="find_on_page">Find on Page</string>
         <string name="print">Print</string>
             <string name="privacy_browser_web_page">Privacy Browser Web Page</string>
-        <string name="save_as_image">Save as Image</string>
+        <string name="save">Save</string>
+            <string name="save_as_archive">Save as Archive</string>
+            <string name="save_as_image">Save as Image</string>
         <string name="add_to_home_screen">Add to Home Screen</string>
         <string name="view_source">View Source</string>
     <string name="share">Share</string>
     <string name="previous">Previous</string>
     <string name="next">Next</string>
 
-    <!-- Save Webpage as Image. -->
+    <!-- Save Webpage. -->
+    <string name="save_webpage">Save Webpage</string>
+    <string name="save_archive">Save Archive</string>
     <string name="save_image">Save Image</string>
+    <string name="webpage_mht">Webpage.mht</string>
     <string name="webpage_png">Webpage.png</string>
     <string name="saving_image">Saving image…</string>
     <string name="image_saved">Image saved.</string>
     <string name="edit_folder">Edit Folder</string>
     <string name="move_to_folder">Move to Folder</string>
     <string name="move">Move</string>
-    <string name="save">Save</string>
 
     <!-- Bookmarks Contextual App Bar. -->
     <string name="selected">Selected:</string>  <!--This is a plural adjective.-->
         </string-array>
         <string name="no_proxy_enabled">None - connect directly to the internet.</string>
         <string name="tor_enabled">Tor - connect through socks://localhost:9050.</string>
-        <string name="tor_enabled_kitkat">Tor - connect through http://localhost:8118</string>
+        <string name="tor_enabled_kitkat">Tor - connect through http://localhost:8118.</string>
         <string name="i2p_enabled">I2P - connect through http://localhost:4444.</string>
         <string name="custom_proxy">Custom proxy</string>
         <string name="proxy_custom_url">Proxy custom URL</string>