/*
- * Copyright 2017-2020,2022 Soren Stoutner <soren@stoutner.com>.
+ * Copyright 2017-2020, 2022 Soren Stoutner <soren@stoutner.com>.
*
- * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
+ * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
*
* Privacy Browser Android is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
<!--
- Copyright © 2016-2018,2020-2022 Soren Stoutner <soren@stoutner.com>.
+ Copyright 2016-2018, 2020-2022, 2024 Soren Stoutner <soren@stoutner.com>.
- Translation 2019,2021-2022 Bernhard G. Keller. Copyright assigned to Soren Stoutner <soren@stoutner.com>.
+ Translation 2019, 2021-2022 Bernhard G. Keller. Copyright assigned to Soren Stoutner <soren@stoutner.com>.
Translation 2016 Aaron Gerlach <aaron@gerlach.com>. Copyright assigned to Soren Stoutner <soren@stoutner.com>.
- This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
+ This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
Privacy Browser Android is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
You should have received a copy of the GNU General Public License
along with Privacy Browser Android. If not, see <http://www.gnu.org/licenses/>. -->
-<html>
+<html lang="de">
<head>
<meta charset="UTF-8">
+ <title>Local Storage</title>
<link rel="stylesheet" href="../css/theme.css">
wodurch sie ggf. von der Website abgemeldet werden.
Diese Einschränkung wird mit <a href="https://www.stoutner.com/category/privacy-browser-android-roadmap/">Privacy WebView</a> in den Versionen 4.x von Privacy Browser behoben werden.</p>
- <p>Wenn Cookies aktiviert sind, aber JavaScript deaktiviert ist, wird das Privatsphären-Icon <img class="inline" src="../shared_images/warning.svg"> zur Warnung in gelb dargestellt.</p>
+ <p>Wenn Cookies aktiviert sind, aber JavaScript deaktiviert ist, wird das Privatsphären-Icon <img class="inline" src="../shared_images/warning.svg" alt="Warning"> zur Warnung in gelb dargestellt.</p>
+
<h3><svg class="header"><use href="../shared_images/cookie.svg#icon"/></svg> Drittanbieter-Cookies</h3>
Es gibt eigentlich keinen guten Grund, solche Cookies überhaupt zuzulassen. Ab Privacy Browser Version 3.8 wurde die Option daher entfernt und selbst Google plant,
<a href="https://www.theverge.com/2020/1/14/21064698/google-third-party-cookies-chrome-two-years-privacy-safari-firefox">Drittanbieter-Cookies in Zukunft zu deaktivieren</a>.</p>
+
<h3><svg class="header"><use href="../shared_images/web.svg#icon"/></svg> DOM-Speicher</h3>
<p>Der Document-Object-Model-Speicher - auch als Web-Speicher bekannt - funktioniert wie "gedopte" Cookies.
Die gespeicherten Daten werden dabei - im Gegensatz zu Cookies - nicht bei jeder Anfrage zur Gänze im Header mitgeschickt,
sondern mittels JavaScript gelesen und geschrieben, sodass diese Form der Datenspeicherung nicht funktioniert, wenn JavaScript deaktiviert ist.</p>
- <h3><svg class="header"><use href="../shared_images/subtitles.svg#icon"/></svg> Formulardaten</h3>
-
- <p>Formulardaten enthalten Informationen, die in Web-Formulare eingegeben wurden (wie z.B. Benutzernamen, Adressen, Telefonnummern, usw.) und werden bei späteren Besuchen in Auswahl-Dialogen angezeigt.
- Im Gegensatz zu in Cookies und im DOM-Speicher gespeicherten Daten werden diese Informationen nur nach Benutzer-Interaktion an den Webserver gesandt. Ab Android Oreo (Version 8.0, API 26) wurden
- WebViews Formulardaten durch <a href="https://medium.com/@bherbst/getting-androids-autofill-to-work-for-you-21435debea1">Googles Autofill-Service</a> ersetzt.
- Daher erscheinen Formulardaten auf neueren Android-Geräten nicht mehr.</p>
-
<h3><svg class="header"><use href="../shared_images/delete_forever.svg#icon"/></svg> Bereinigen und Schließen</h3>
danach werden alle <code>App-WebView-</code> und <code>Cache-</code> Verzeichnisse gelöscht.
Das Verhalten von "Bereinigen und Schließen" kann in den Einstellungen konfiguriert werden.</p>
</body>
-</html>
\ No newline at end of file
+</html>
<!--
- Copyright © 2016-2018,2020-2022 Soren Stoutner <soren@stoutner.com>.
+ Copyright 2016-2018, 2020-2022, 2024 Soren Stoutner <soren@stoutner.com>.
- This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
+ This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
Privacy Browser Android is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
You should have received a copy of the GNU General Public License
along with Privacy Browser Android. If not, see <http://www.gnu.org/licenses/>. -->
-<html>
+<html lang="en">
<head>
<meta charset="UTF-8">
+ <title>Local Storage</title>
<link rel="stylesheet" href="../css/theme.css">
If the background tab makes a request, for example, to see if there is updated information, that request will be sent without cookies, which will cause the website to log you out.
This is a limitation that will be removed with the release of <a href="https://www.stoutner.com/category/privacy-browser-android-roadmap/">Privacy WebView</a> in the 4.x series.</p>
- <p>If cookies are enabled but JavaScript is disabled, the privacy icon will be yellow <img class="inline" src="../shared_images/warning.svg"> as a warning.</p>
+ <p>If cookies are enabled but JavaScript is disabled, the privacy icon will be yellow <img class="inline" src="../shared_images/warning.svg" alt="Warning"> as a warning.</p>
<h3><svg class="header"><use href="../shared_images/cookie.svg#icon"/></svg> Third-Party Cookies</h3>
Rather, it uses JavaScript to read and write data, which means it does not function when JavaScript is disabled.</p>
- <h3><svg class="header"><use href="../shared_images/subtitles.svg#icon"/></svg> Form Data</h3>
-
- <p>Form data contains information typed into web forms, like usernames, addresses, phone numbers, etc., and lists them in a drop-down box on future visits.
- Unlike the other forms of local storage, form data is not sent to the web server without specific user interaction. Beginning in Android Oreo (version 8.0, API 26),
- WebView’s form data was replaced by the <a href="https://medium.com/@bherbst/getting-androids-autofill-to-work-for-you-21435debea1">Autofill service</a>.
- As such, controls for form data no longer appear on newer Android devices.</p>
-
-
<h3><svg class="header"><use href="../shared_images/delete_forever.svg#icon"/></svg> Clear and Exit</h3>
<p>Clear and Exit runs every time the last tab is closed or Clear and Exit is selected from the navigation menu.
By default it clears the cookies, DOM storage, form data, the logcat, and the WebView cache. Then it manually deletes the entire <code>app_webview</code> and <code>cache</code> directories.
The behavior of Clear and Exit can be configured in the settings.</p>
</body>
-</html>
\ No newline at end of file
+</html>
<!--
- Copyright 2016-2022 Soren Stoutner <soren@stoutner.com>.
+ Copyright 2016-2022, 2024 Soren Stoutner <soren@stoutner.com>.
- This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
+ This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
Privacy Browser Android is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
You should have received a copy of the GNU General Public License
along with Privacy Browser Android. If not, see <http://www.gnu.org/licenses/>. -->
-<html>
+<html lang="en">
<head>
<meta charset="UTF-8">
+ <title>Tracking IDs</title>
<link rel="stylesheet" href="../css/theme.css">
<!--
- Copyright 2016-2020,2022 Soren Stoutner <soren@stoutner.com>.
+ Copyright 2016-2020, 2022, 2024 Soren Stoutner <soren@stoutner.com>.
- This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
+ This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
Privacy Browser Android is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
You should have received a copy of the GNU General Public License
along with Privacy Browser Android. If not, see <http://www.gnu.org/licenses/>. -->
-<html>
+<html lang="en">
<head>
<meta charset="UTF-8">
+ <title>User Agent</title>
<link rel="stylesheet" href="../css/theme.css">
The screenshot below shows a Pixel 2 XL running Android 10 with Android System WebView 84.0.4147.125 installed.
Most web servers will recognize this as a mobile browser and will display the mobile version of the site if they have one.</p>
- <img class="center" src="images/user_agent.png">
+ <img class="center" src="images/user_agent.png" alt="User Agent">
<p>There is enough information in the user agent that sometimes only a few visitors to a website will be the same.
If the user agent is combined with another piece of non-unique identifying information, often it results in a unique fingerprint.
<!--
- Copyright © 2016-2018,2020-2022 Soren Stoutner <soren@stoutner.com>.
+ Copyright © 2016-2018, 2020-2022, 2024 Soren Stoutner <soren@stoutner.com>.
- Translation 2017-2018,2021 Jose A. León. Copyright assigned to Soren Stoutner <soren@stoutner.com>.
+ Translation 2017-2018, 2021 Jose A. León. Copyright assigned to Soren Stoutner <soren@stoutner.com>.
- This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
+ This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
Privacy Browser Android is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
You should have received a copy of the GNU General Public License
along with Privacy Browser Android. If not, see <http://www.gnu.org/licenses/>. -->
-<html>
+<html lang="es">
<head>
<meta charset="UTF-8">
+ <title>Local Storage</title>
<link rel="stylesheet" href="../css/theme.css">
Si la pestaña en segundo plano hace una petición, por ejemplo, para ver si hay información actualizada, esa petición se enviará sin cookies, lo que hará que el sitio web cierre la sesión.
Esta es una limitación que se eliminará con el lanzamiento de <a href="https://www.stoutner.com/category/privacy-browser-android-roadmap/">Privacy WebView</a> en la serie 4.x.</p>
- <p>Si las cookies están activadas pero JavaScript está desactivado, el icono de privacidad será amarillo <img class="inline" src="../shared_images/warning.svg"> como advertencia.</p>
+ <p>Si las cookies están activadas pero JavaScript está desactivado, el icono de privacidad será amarillo <img class="inline" src="../shared_images/warning.svg" alt="Warning"> como advertencia.</p>
<h3><svg class="header"><use href="../shared_images/cookie.svg#icon"/></svg> Cookies de terceros</h3>
Más bien, utiliza JavaScript para leer y escribir datos, lo que significa que no funciona cuando JavaScript está desactivado.</p>
- <h3><svg class="header"><use href="../shared_images/subtitles.svg#icon"/></svg> Datos de formulario</h3>
-
- <p>Los datos de formulario contienen la información introducida en los formularios web, como los nombres de los usuarios, las direcciones, los números de teléfono, etc.,
- y los listan en un cuadro desplegable en futuras visitas.
- A diferencia de las otras formas de almacenamiento local, los datos de los formularios no se envían al servidor web sin una interacción específica del usuario.
- A partir de Android Oreo (versión 8.0, API 26), los datos de formulario de WebView fueron sustituidos por el
- <a href="https://medium.com/@bherbst/getting-androids-autofill-to-work-for-you-21435debea1">servicio Autofill o Autorelleno</a>.
- Por ello, los controles para los datos de los formularios ya no aparecen en los dispositivos Android más nuevos.</p>
-
-
<h3><svg class="header"><use href="../shared_images/delete_forever.svg#icon"/></svg> Borrar y Salir</h3>
<p>Borrar y salir se ejecuta cada vez que se cierra la última pestaña o se selecciona Borrar y salir en el menú de navegación.
Luego borra manualmente los directorios <code>app_webview</code> y <code>cache</code>.
El comportamiento de Borrar y Salir se puede configurar en los ajustes.</p>
</body>
-</html>
\ No newline at end of file
+</html>
<!--
- Copyright © 2016-2018,2020-2022 Soren Stoutner <soren@stoutner.com>.
+ Copyright 2016-2018, 2020-2022, 2024 Soren Stoutner <soren@stoutner.com>.
- Translation 2019,2021-2022 Kévin L. <kevinliste@framalistes.org>. Copyright assigned to Soren Stoutner <soren@stoutner.com>.
+ Translation 2019, 2021-2022 Kévin L. <kevinliste@framalistes.org>. Copyright assigned to Soren Stoutner <soren@stoutner.com>.
- This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
+ This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
Privacy Browser Android is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
You should have received a copy of the GNU General Public License
along with Privacy Browser Android. If not, see <http://www.gnu.org/licenses/>. -->
-<html>
+<html lang="fr">
<head>
<meta charset="UTF-8">
+ <title>Local Storage</title>
<link rel="stylesheet" href="../css/theme.css">
Si l'onglet d'arrière-plan fait une demande, par exemple, pour voir s'il y a des informations mises à jour, cette demande sera envoyée sans cookies, ce qui fera que le site web vous déconnectera.
Il s'agit d'une limitation qui sera supprimée avec la sortie de <a href="https://www.stoutner.com/category/privacy-browser-android-roadmap/">Privacy WebView</a> dans la série 4.x.</p>
- <p>Si les cookies sont activés mais que JavaScript est désactivé, l'icône de confidentialité sera jaune <img class="inline" src="../shared_images/warning.svg"> en guise d'avertissement.</p>
+ <p>Si les cookies sont activés mais que JavaScript est désactivé, l'icône de confidentialité sera jaune <img class="inline" src="../shared_images/warning.svg" alt="Warning"> en guise d'avertissement.</p>
<h3><svg class="header"><use href="../shared_images/cookie.svg#icon"/></svg> Cookies tiers</h3>
Il utilise plutôt JavaScript pour lire et écrire les données, ce qui signifie qu'il ne fonctionne pas lorsque JavaScript est désactivé.</p>
- <h3> <svg class="header"><use href="../shared_images/subtitles.svg#icon"/></svg> Données de formulaire</h3>
-
- <p>Les données de formulaire contiennent les informations saisies dans les formulaires web, comme les noms d'utilisateur, les adresses, les numéros de téléphone,
- etc. et les répertorient dans une boîte déroulante lors de visites ultérieures.
- Contrairement aux autres formes de stockage local, les données de formulaire ne sont pas envoyées au serveur web sans interaction spécifique de l'utilisateur.
- À partir d'Android Oreo (version 8.0, API 26), les données de formulaire de WebView ont été remplacées par le
- <a href="https://medium.com/@bherbst/getting-androids-autofill-to-work-for-you-21435debea1">service Autofill</a>.
- Ainsi, les contrôles des données de formulaire n'apparaissent plus sur les appareils Android plus récents.</p>
-
-
- <h3><svg class="header"><use href="../shared_images/delete_forever.svg#icon"/></svg> Nettoyer et Quitter<</h3>
+ <h3><svg class="header"><use href="../shared_images/delete_forever.svg#icon"/></svg> Nettoyer et Quitter</h3>
<p>La fonction Nettoyer et Quitter s'exécute chaque fois que le dernier onglet est fermé ou que Nettoyer et Quitter est sélectionnée dans le menu de navigation.
Par défaut, elle efface les cookies, le stockage DOM, les données de formulaire, le logcat et le cache WebView.
Ensuite, elle supprime manuellement l'ensemble des répertoires <code>app_webview</code> et <code>cache</code>. Le comportement de Nettoyer et Quitter peut être configuré dans les paramètres.</p>
</body>
-</html>
\ No newline at end of file
+</html>
<!--
- Copyright © 2017-2018,2020-2022 Soren Stoutner <soren@stoutner.com>.
+ Copyright 2017-2018, 2020-2022, 2024 Soren Stoutner <soren@stoutner.com>.
- Translation 2017-2018,2021-2022 Francesco Buratti. Copyright assigned to Soren Stoutner <soren@stoutner.com>.
+ Translation 2017-2018, 2021-2022 Francesco Buratti. Copyright assigned to Soren Stoutner <soren@stoutner.com>.
- This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
+ This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
Privacy Browser Android is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
You should have received a copy of the GNU General Public License
along with Privacy Browser Android. If not, see <http://www.gnu.org/licenses/>. -->
-<html>
+<html lang="it">
<head>
<meta charset="UTF-8">
+ <title>Local Storage</title>
<link rel="stylesheet" href="../css/theme.css">
quella richiesta sarà inviata senza cookie e questo provocherà il log out dal sito.
Questa è una limitazione che sarà rimossa con il rilascio di <a href="https://www.stoutner.com/category/privacy-browser-android-roadmap/">Privacy WebView</a> nella serie 4.x.</p>
- <p>Se i cookies sono abilitati ma JavaScript è disabilitato, l'icona della privacy sarà gialla <img class="inline" src="../shared_images/warning.svg"> come avvertimento.</p>
+ <p>Se i cookies sono abilitati ma JavaScript è disabilitato, l'icona della privacy sarà gialla <img class="inline" src="../shared_images/warning.svg" alt="Warning"> come avvertimento.</p>
<h3><svg class="header"><use href="../shared_images/cookie.svg#icon"/></svg> Cookies di terze parti</h3>
Al contrario utilizza JavaScript per leggere e scrivere i dati, il che significa che non può funzionare se JavaScript è disabilitato.</p>
- <h3><svg class="header"><use href="../shared_images/subtitles.svg#icon"/></svg> Dati dei moduli</h3>
-
- <p>I dati dei moduli contengono informazioni che sono digitate nei web forms, come il nome dell'utente, gli indirizzi, numeri di telefono, ecc.,
- e li elenca in un menù a tendina in caso di accessi futuri.
- A differenza delle altre modalità di memorizzazione locale, i dati dei moduli non vengono inviati ai web server senza che ci sia una interazione con l'utente.
- A partire da Android Oreo (versione 8.0, API 26), i dati dei moduli di WebView sono stati sostituiti dal
- <a href="https://medium.com/@bherbst/getting-androids-autofill-to-work-for-you-21435debea1">servizio Autofill</a>.
- Per questo motivo i controlli dei dati dei moduli non sono presenti nei dispositivi Android più recenti.</p>
-
-
<h3><svg class="header"><use href="../shared_images/delete_forever.svg#icon"/></svg> Elimina dati ed esci</h3>
<p>Elimina dati ed esci viene eseguito ogni volta che viene chiusa l'ultima scheda oppure quando viene selezionato il comando Elimina dati ed esci dal menù di navigazione.
Di default questo comando cancella i cookie, il DOM storage, i dati dei moduli, il logcat e la cache di WebView.
In sostanza elimina completamente le cartelle <code>app_webview</code> e <code>cache</code>. Il comportamento di Elimina dati ed esci può essere configurato nelle impostazioni.</p>
</body>
-</html>
\ No newline at end of file
+</html>
<!--
- Copyright © 2016-2018,2020-2022 Soren Stoutner <soren@stoutner.com>.
+ Copyright 2016-2018, 2020-2022, 2024 Soren Stoutner <soren@stoutner.com>.
Translation 2021 Thiago Nazareno Conceição Silva de Jesus <mochileiro2006-trilhas@yahoo.com.br>. Copyright assigned to Soren Stoutner <soren@stoutner.com>.
- This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
+ This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
Privacy Browser Android is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
You should have received a copy of the GNU General Public License
along with Privacy Browser Android. If not, see <http://www.gnu.org/licenses/>. -->
-<html>
+<html lang="pt">
<head>
<meta charset="UTF-8">
+ <title>Local Storage</title>
<link rel="stylesheet" href="../css/theme.css">
Se a guia em segundo plano fizer uma solicitação, por exemplo, para ver se há informações atualizadas, essa solicitação será enviada sem cookies, oque fará com que o site desconecte você.
Esta é uma limitação que será removida com o lançamento do <a href="https://www.stoutner.com/category/privacy-browser-android-roadmap/">Privacy WebView</a> no 4.x série.</p>
- <p>Se os cookies estiverem habilitados, mas o JavaScript estiver desabilitado, o ícone de privacidade ficará amarelo <img class="inline" src="../shared_images/warning.svg"> como um aviso.</p>
+ <p>Se os cookies estiverem habilitados, mas o JavaScript estiver desabilitado, o ícone de privacidade ficará amarelo <img class="inline" src="../shared_images/warning.svg" alt="Warning"> como um aviso.</p>
<h3><svg class="header"><use href="../shared_images/cookie.svg#icon"/></svg> Cookies de terceiros</h3>
Em vez disso, ele usa JavaScript para ler e gravar dados, o que significa que não funciona quando o JavaScript está desabilitado.</p>
- <h3><svg class="header"><use href="../shared_images/subtitles.svg#icon"/></svg> Dados do Formulário</h3>
-
- <p>Os dados do formulário contêm informações digitadas em formulários da web, como nomes de usuário, endereços, números de telefone, etc., e os relaciona em uma caixa suspensa em visitas futuras.
- Ao contrário de outras formas de armazenamento local, os dados do formulário não são enviados ao servidor da web sem interação específica do usuário.
- A partir do Android Oreo (versão 8.0, API 26), os dados do formulário WebView foram substituídos pelo
- <a href="https://medium.com/@bherbst/getting-androids-autofill-to-work-for-you-21435debea1">Autofill service</a>.
- Como tal, os controles para dados de formulário não aparecem mais em dispositivos Android mais recentes.</p>
-
-
<h3><svg class="header"><use href="../shared_images/delete_forever.svg#icon"/></svg> Limpar e fechar</h3>
<p>Limpar e Fechar é executado sempre que a última guia é fechada ou Limpar e Fechar é selecionado no menu de navegação.
Por padrão, ele limpa os cookies, o armazenamento DOM, os dados do formulário, o logcat e o cache do WebView.
Em seguida, ele exclui manualmente todos os diretórios <code>app_webview</code> e <code>cache</code>. O comportamento de Limpar e Fechar pode ser configurado nas configurações.</p>
</body>
-</html>
\ No newline at end of file
+</html>
<!--
- Copyright © 2016-2018,2020-2022 Soren Stoutner <soren@stoutner.com>.
+ Copyright 2016-2018, 2020-2022, 2024 Soren Stoutner <soren@stoutner.com>.
- This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
+ This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
Privacy Browser Android is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
You should have received a copy of the GNU General Public License
along with Privacy Browser Android. If not, see <http://www.gnu.org/licenses/>. -->
-<html>
+<html lang="ru">
<head>
<meta charset="UTF-8">
+ <title>Local Storage</title>
<link rel="stylesheet" href="../css/theme.css">
Если фоновая вкладка делает запрос, например, чтобы узнать, есть ли обновленная информация, этот запрос будет отправлен без файлов cookie, что приведет к разлогиниванию.
Это ограничение будет устранено с выходом <a href="https://www.stoutner.com/category/privacy-browser-android-roadmap/">Privacy WebView</a> в версии 4.x.</p>
- <p>Если cookie включены и при этом JavaScript отключен, то значок конфиденциальности будет желтого цвета <img class="inline" src="../shared_images/warning.svg"> в качестве предупреждения.</p>
+ <p>Если cookie включены и при этом JavaScript отключен, то значок конфиденциальности будет желтого цвета <img class="inline" src="../shared_images/warning.svg" alt="Warning"> в качестве предупреждения.</p>
<h3><svg class="header"><use href="../shared_images/cookie.svg#icon"/></svg> Сторонние файлы cookie</h3>
Вместо этого оно использует JavaScript для чтения и записи данных, а это означает, что оно не работает, когда JavaScript отключен.</p>
- <h3><svg class="header"><use href="../shared_images/subtitles.svg#icon"/></svg> Данные форм</h3>
-
- <p>Данные форм содержат информацию, введенную в веб-формы, такую как имена пользователей, адреса, номера телефонов и т.д., и отображаются в выпадающем списке при последующих посещениях.
- В отличие от других форм локального хранилища, данные форм не передаются на веб-сервер без определенного взаимодействия с пользователем. Начиная с Android Oreo (версия 8.0, API 26),
- данные форм WebView были заменены <a href="https://medium.com/@bherbst/getting-androids-autofill-to-work-for-you-21435debea1">сервисом автозаполнения</a>.
- Таким образом, элементы управления данными формы больше не отображаются на новых Android-устройствах.</p>
-
-
<h3><svg class="header"><use href="../shared_images/delete_forever.svg#icon"/></svg> Очистить и выйти</h3>
<p>Функция Очистить и выйти запускается каждый раз при закрытии последней вкладки или выборе Очистить и выйти из меню навигации.
По умолчанию очищаются cookie, DOM-хранилище, данные формы, logcat и кэш WebView. Затем происходит ручное удаление всех каталогов <code>app_webview</code> и <code>cache</code>.
Поведение опции Очистить и выйти можно настроить в настройках.</p>
</body>
-</html>
\ No newline at end of file
+</html>
<!--
- Copyright © 2016-2022 Soren Stoutner <soren@stoutner.com>.
+ Copyright 2016-2022, 2024 Soren Stoutner <soren@stoutner.com>.
- This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
+ This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
Privacy Browser Android is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
You should have received a copy of the GNU General Public License
along with Privacy Browser Android. If not, see <http://www.gnu.org/licenses/>. -->
-<html>
+<html lang="tr">
<head>
<meta charset="UTF-8">
+ <title>Local Storage</title>
<link rel="stylesheet" href="../css/theme.css">
If the background tab makes a request, for example, to see if there is updated information, that request will be sent without cookies, which will cause the website to log you out.
This is a limitation that will be removed with the release of <a href="https://www.stoutner.com/category/privacy-browser-android-roadmap/">Privacy WebView</a> in the 4.x series.</p>
- <p>If cookies are enabled but JavaScript is disabled, the privacy icon will be yellow <img class="inline" src="../shared_images/warning.svg"> as a warning.</p>
+ <p>If cookies are enabled but JavaScript is disabled, the privacy icon will be yellow <img class="inline" src="../shared_images/warning.svg" alt="Warning"> as a warning.</p>
<h3><svg class="header"><use href="../shared_images/cookie.svg#icon"/></svg> Üçüncü Taraf Çerezler</h3>
Rather, it uses JavaScript to read and write data, which means it does not function when JavaScript is disabled.</p>
- <h3><svg class="header"><use href="../shared_images/subtitles.svg#icon"/></svg> Form Verisi</h3>
-
- <p>Form data contains information typed into web forms, like usernames, addresses, phone numbers, etc., and lists them in a drop-down box on future visits.
- Unlike the other forms of local storage, form data is not sent to the web server without specific user interaction. Beginning in Android Oreo (version 8.0, API 26),
- WebView’s form data was replaced by the <a href="https://medium.com/@bherbst/getting-androids-autofill-to-work-for-you-21435debea1">Autofill service</a>.
- As such, controls for form data no longer appear on newer Android devices.</p>
-
-
<h3><svg class="header"><use href="../shared_images/delete_forever.svg#icon"/></svg> Clear and Exit</h3>
<p>Clear and Exit runs every time the last tab is closed or Clear and Exit is selected from the navigation menu.
By default it clears the cookies, DOM storage, form data, the logcat, and the WebView cache. Then it manually deletes the entire <code>app_webview</code> and <code>cache</code> directories.
The behavior of Clear and Exit can be configured in the settings.</p>
</body>
-</html>
\ No newline at end of file
+</html>
<!--
- Copyright 2016-2018,2020-2023 Soren Stoutner <soren@stoutner.com>.
+ Copyright 2016-2018, 2020-2024 Soren Stoutner <soren@stoutner.com>.
Translation 2023 Xin. Copyright assigned to Soren Stoutner <soren@stoutner.com>.
- This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
+ This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
Privacy Browser Android is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
You should have received a copy of the GNU General Public License
along with Privacy Browser Android. If not, see <http://www.gnu.org/licenses/>. -->
-<html>
+<html lang="zh">
<head>
<meta charset="UTF-8">
+ <title>Local Storage</title>
<link rel="stylesheet" href="../css/theme.css">
如果你在后台有一个页面需要cookies来登录,而你在一个页面里关闭了cookies,所有页面的cookies都会被关闭。如果在后台的页面发出请求,例如,看有没有新消息,而在没有cookies的情况下需要你重新登录。
这个限制会在<a href="https://www.stoutner.com/category/privacy-browser-android-roadmap/">隐私浏览器</a> 4.x系列中移除。</p>
- <p>如果cookies允许,而JavaScript不允许,隐私盾牌会变成黄色<img class="inline" src="../shared_images/warning.svg">来示警</p>
+ <p>如果cookies允许,而JavaScript不允许,隐私盾牌会变成黄色<img class="inline" src="../shared_images/warning.svg" alt="Warning">来示警</p>
<h3><svg class="header"><use href="../shared_images/cookie.svg#icon"/></svg> 第三方Cookies</h3>
不像cookies,DOM储存不在请求头中发送数据,相反,它使用JavaScript来读写数据,意味着在禁用JavaScript时DOM不能工作。</p>
- <h3><svg class="header"><use href="../shared_images/subtitles.svg#icon"/></svg> 表单数据</h3>
-
- <p>表单数据包含输入到web表单中的信息,包括用户名。地址,电话等等,并且在表中罗列。不像其他本地存储的表单,没有特定的用户需求,表单不会发送到web中。
- 从Android Oreo (version 8.0, API 26)开始,WebView的表单数据被<a href="https://medium.com/@bherbst/getting-androids-autofill-to-work-for-you-21435debea1">Autofill service</a>取代。
- 因此表单数据控件不会在新的安卓设备中出现</p>
-
-
<h3><svg class="header"><use href="../shared_images/delete_forever.svg#icon"/></svg> 清除并退出</h3>
<p>清除并退出会在最后一个页面退出或在导航栏选中时运行,默认清除cookies,DOM储存,表单数据,日志和WebView缓存。然后需要手动删除app_webview和cache目录。可以在设置中配置清除并退出的行为。</p>
/*
- * Copyright 2016-2023 Soren Stoutner <soren@stoutner.com>.
+ * Copyright 2016-2024 Soren Stoutner <soren@stoutner.com>.
*
- * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
+ * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
*
* Privacy Browser Android is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
val bottomAppBar = sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false)
// Disable screenshots if not allowed.
- if (!allowScreenshots) {
+ if (!allowScreenshots)
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
- }
// Run the default commands.
super.onCreate(savedInstanceState)
// Set the content view.
- if (bottomAppBar) {
+ if (bottomAppBar)
setContentView(R.layout.guide_bottom_appbar)
- } else {
+ else
setContentView(R.layout.guide_top_appbar)
- }
// Get handles for the views.
val toolbar = findViewById<Toolbar>(R.id.guide_toolbar)
/*
* Copyright 2019-2024 Soren Stoutner <soren@stoutner.com>.
*
- * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
+ * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
*
* Privacy Browser Android is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
import android.os.Build
import android.os.Bundle
import android.provider.OpenableColumns
+import android.util.Base64
import android.util.TypedValue
import android.view.Menu
import android.view.MenuItem
import android.view.WindowManager
-import android.widget.TextView
-import android.widget.ScrollView
+import android.webkit.WebView
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStreamReader
-import java.lang.Exception
+
import java.nio.charset.StandardCharsets
// Define the class constants.
-private const val SCROLLVIEW_POSITION = "scrollview_position"
+private const val SCROLL_Y = "A"
class LogcatActivity : AppCompatActivity() {
- // Define the class variables.
- private var scrollViewYPositionInt = 0
+ // Declare the class variables.
+ private lateinit var logcatPlainTextStringBuilder: StringBuilder
- // Define the class views.
+ // Declare the class views.
private lateinit var swipeRefreshLayout: SwipeRefreshLayout
- private lateinit var logcatScrollView: ScrollView
- private lateinit var logcatTextView: TextView
+ private lateinit var logcatWebView: WebView
// Define the save logcat activity result launcher. It must be defined before `onCreate()` is run or the app will crash.
private val saveLogcatActivityResultLauncher = registerForActivityResult(ActivityResultContracts.CreateDocument("text/plain")) { fileUri ->
// Only save the file if the URI is not null, which happens if the user exited the file picker by pressing back.
if (fileUri != null) {
try {
- // Get the logcat string.
- val logcatString = logcatTextView.text.toString()
-
// Open an output stream.
val outputStream = contentResolver.openOutputStream(fileUri)!!
CoroutineScope(Dispatchers.Main).launch {
withContext(Dispatchers.IO) {
// Write the logcat string to the output stream.
- outputStream.write(logcatString.toByteArray(StandardCharsets.UTF_8))
+ outputStream.write(logcatPlainTextStringBuilder.toString().toByteArray(StandardCharsets.UTF_8))
// Close the output stream.
outputStream.close()
contentResolverCursor.close()
// Display a snackbar with the saved logcat information.
- Snackbar.make(logcatTextView, getString(R.string.saved, fileNameString), Snackbar.LENGTH_SHORT).show()
+ Snackbar.make(logcatWebView, getString(R.string.saved, fileNameString), Snackbar.LENGTH_SHORT).show()
} catch (exception: Exception) {
// Display a snackbar with the error message.
- Snackbar.make(logcatTextView, getString(R.string.error_saving_logcat, exception.toString()), Snackbar.LENGTH_INDEFINITE).show()
+ Snackbar.make(logcatWebView, getString(R.string.error_saving_logcat, exception.toString()), Snackbar.LENGTH_INDEFINITE).show()
}
}
}
val bottomAppBar = sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false)
// Disable screenshots if not allowed.
- if (!allowScreenshots) {
+ if (!allowScreenshots)
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
- }
// Run the default commands.
super.onCreate(savedInstanceState)
// Set the content view.
- if (bottomAppBar) {
+ if (bottomAppBar)
setContentView(R.layout.logcat_bottom_appbar)
- } else {
+ else
setContentView(R.layout.logcat_top_appbar)
- }
// Get handles for the views.
val toolbar = findViewById<Toolbar>(R.id.toolbar)
swipeRefreshLayout = findViewById(R.id.swiperefreshlayout)
- logcatScrollView = findViewById(R.id.scrollview)
- logcatTextView = findViewById(R.id.logcat_textview)
+ logcatWebView = findViewById(R.id.logcat_webview)
// Set the toolbar as the action bar.
setSupportActionBar(toolbar)
// Implement swipe to refresh.
swipeRefreshLayout.setOnRefreshListener {
- // Get the current logcat.
- getLogcat()
+ // Populate the current logcat.
+ populateLogcat()
}
// Set the swipe refresh color scheme according to the theme.
// Set the swipe refresh background color.
swipeRefreshLayout.setProgressBackgroundColorSchemeColor(colorBackgroundInt)
- // Check to see if the activity has been restarted.
- if (savedInstanceState != null) {
- // Get the saved scrollview position.
- scrollViewYPositionInt = savedInstanceState.getInt(SCROLLVIEW_POSITION)
- }
+ // Restore the WebView scroll position if the activity has been restarted.
+ if (savedInstanceState != null)
+ logcatWebView.scrollY = savedInstanceState.getInt(SCROLL_Y)
+
+ // Allow loading of file:// URLs.
+ logcatWebView.settings.allowFileAccess = true
- // Get the logcat.
- getLogcat()
+ // Populate the logcat.
+ populateLogcat()
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
val clipboardManager = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
// Save the logcat in a clip data.
- val logcatClipData = ClipData.newPlainText(getString(R.string.logcat), logcatTextView.text)
+ val logcatClipData = ClipData.newPlainText(getString(R.string.logcat), logcatPlainTextStringBuilder)
// Place the clip data on the clipboard.
clipboardManager.setPrimaryClip(logcatClipData)
// Display a snackbar if the API <= 32 (Android 12L). Beginning in Android 13 the OS displays a notification that covers up the snackbar.
if (Build.VERSION.SDK_INT <= 32)
- Snackbar.make(logcatTextView, R.string.logcat_copied, Snackbar.LENGTH_SHORT).show()
+ Snackbar.make(logcatWebView, R.string.logcat_copied, Snackbar.LENGTH_SHORT).show()
// Consume the event.
true
// Wait for the process to finish.
process.waitFor()
- // Reset the scroll view Y position int.
- scrollViewYPositionInt = 0
-
// Reload the logcat.
- getLogcat()
+ populateLogcat()
} catch (exception: Exception) {
// Do nothing.
}
// Run the default commands.
super.onSaveInstanceState(savedInstanceState)
- // Get the scrollview Y position.
- val scrollViewYPositionInt = logcatScrollView.scrollY
-
- // Store the scrollview Y position in the bundle.
- savedInstanceState.putInt(SCROLLVIEW_POSITION, scrollViewYPositionInt)
+ // Store the scroll Y position in the bundle.
+ savedInstanceState.putInt(SCROLL_Y, logcatWebView.scrollY)
}
- private fun getLogcat() {
+ private fun populateLogcat() {
try {
// Get the logcat. `-b all` gets all the buffers (instead of just crash, main, and system). `-v long` produces more complete information. `-d` dumps the logcat and exits.
val getLogcatProcess = Runtime.getRuntime().exec("logcat -b all -v long -d")
// Wrap the logcat in a buffered reader.
val logcatBufferedReader = BufferedReader(InputStreamReader(getLogcatProcess.inputStream))
- // Display the logcat.
- logcatTextView.text = logcatBufferedReader.readText()
+ // Reset the logcat plain text string.
+ logcatPlainTextStringBuilder = StringBuilder()
+
+ // Create a logcat HTML string builder.
+ val logcatHtmlStringBuilder = StringBuilder()
+
+ // Populate the initial HTML.
+ logcatHtmlStringBuilder.append("<html>")
+ logcatHtmlStringBuilder.append("<head>")
+ logcatHtmlStringBuilder.append("<style>")
+
+ // Set the word break so that lines never exceed the width of the screen.
+ logcatHtmlStringBuilder.append("body { word-break: break-word; }")
+
+ // Set the colors.
+ logcatHtmlStringBuilder.append("@media (prefers-color-scheme: dark) { body { color: #C1C1C1; /* Gray 350 */ background-color: #303030; /* Gray 860 */ } }")
+ logcatHtmlStringBuilder.append("span.header { color: #0D47A1; /* Blue 900 */ } @media (prefers-color-scheme: dark) { span.header { color: #8AB4F8; /* Violet 500 */ } }")
+ logcatHtmlStringBuilder.append("strong.crash { color: #B71C1C; /* Red 900. */ } @media (prefers-color-scheme: dark) { strong.crash { color: #E24B4C; /* Red Night. */ } }")
+ logcatHtmlStringBuilder.append("span.crash { color: #EF5350; /* Red 400. */ } @media (prefers-color-scheme: dark) { span.crash { color: #EF9A9A; /* Red Night. */ } }")
+
+ // Close the style tag.
+ logcatHtmlStringBuilder.append("</style>")
+
+ // Respect dark mode.
+ logcatHtmlStringBuilder.append("<meta name=\"color-scheme\" content=\"light dark\">")
+
+ // Start the HTML body.
+ logcatHtmlStringBuilder.append("</head>")
+ logcatHtmlStringBuilder.append("<body>")
+
+ // Create a logcat line string.
+ var logcatLineString: String?
+
+ while (logcatBufferedReader.readLine().also { logcatLineString = it } != null) {
+ // Populate the logcat plain text string builder.
+ logcatPlainTextStringBuilder.append(logcatLineString)
+
+ // Add a line break.
+ logcatPlainTextStringBuilder.append("\n")
+
+ // Trim the string, which is necessary for correct detection of lines that start with `at`.
+ logcatLineString = logcatLineString!!.trim()
+
+ // Apply syntax highlighting to the logcat.
+ if (logcatLineString!!.contains("crash") || logcatLineString!!.contains("Exception") ) { // Colorize crashes.
+ logcatHtmlStringBuilder.append("<strong class=\"crash\">")
+ logcatHtmlStringBuilder.append(logcatLineString)
+ logcatHtmlStringBuilder.append("</strong>")
+ } else if (logcatLineString!!.startsWith("at") || logcatLineString!!.startsWith("Process:") || logcatLineString!!.contains("FATAL")) { // Colorize lines relating to crashes.
+ logcatHtmlStringBuilder.append("<span class=\"crash\">")
+ logcatHtmlStringBuilder.append(logcatLineString)
+ logcatHtmlStringBuilder.append("</span>")
+ } else if (logcatLineString!!.startsWith("-")) { // Colorize the headers.
+ logcatHtmlStringBuilder.append("<span class=\"header\">")
+ logcatHtmlStringBuilder.append(logcatLineString)
+ logcatHtmlStringBuilder.append("</span>")
+ } else if (logcatLineString!!.startsWith("[ ")) { // Colorize the time stamps.
+ logcatHtmlStringBuilder.append("<span style=color:gray>")
+ logcatHtmlStringBuilder.append(logcatLineString)
+ logcatHtmlStringBuilder.append("</span>")
+ } else { // Display the standard lines.
+ logcatHtmlStringBuilder.append(logcatLineString)
+ }
+
+ // Add a line break.
+ logcatHtmlStringBuilder.append("<br>")
+ }
+
+ // Close the HTML.
+ logcatHtmlStringBuilder.append("</body>")
+ logcatHtmlStringBuilder.append("</html>")
+
+ // Encode the logcat HTML.
+ val base64EncodedLogcatHtml: String = Base64.encodeToString(logcatHtmlStringBuilder.toString().toByteArray(Charsets.UTF_8), Base64.NO_PADDING)
+
+ // Load the encoded logcat.
+ logcatWebView.loadData(base64EncodedLogcatHtml, "text/html", "base64")
// Close the buffered reader.
logcatBufferedReader.close()
// Do nothing.
}
- // Update the scroll position after the text is populated.
- logcatTextView.post {
- // Set the scroll position.
- logcatScrollView.scrollY = scrollViewYPositionInt
- }
-
// Stop the swipe to refresh animation if it is displayed.
swipeRefreshLayout.isRefreshing = false
}
/*
- * Copyright 2017-2023 Soren Stoutner <soren@stoutner.com>.
+ * Copyright 2017-2024 Soren Stoutner <soren@stoutner.com>.
*
- * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
+ * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
*
* Privacy Browser Android is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
// Create a buffered string reader for the content data.
val bufferedReader = BufferedReader(InputStreamReader(contentResolver.openInputStream(contentUri)))
- // Create a buffered string reader for the content data.
+ // Create a content line string.
var contentLineString: String?
// Get the data from the buffered reader one line at a time.
/*
- * Copyright 2016-2023 Soren Stoutner <soren@stoutner.com>.
+ * Copyright 2016-2024 Soren Stoutner <soren@stoutner.com>.
*
- * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
+ * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
*
* Privacy Browser Android is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
import com.stoutner.privacybrowser.R
// Define the class constants.
-private const val TAB_NUMBER = "tab_number"
-private const val SCROLL_Y = "scroll_y"
+private const val TAB_NUMBER = "A"
+private const val SCROLL_Y = "B"
class GuideWebViewFragment : Fragment() {
// Define the class variables.
9 -> tabWebView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.android_asset_path) + "/guide_interface.html")
}
- // Scroll the WebView if the saved instance state is not null.
+ // Restore the WebView scroll position if the activity has been restarted.
if (savedInstanceState != null) {
tabWebView.post {
tabWebView.scrollY = savedInstanceState.getInt(SCROLL_Y)
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright 2018-2023 Soren Stoutner <soren@stoutner.com>.
+ Copyright 2018-2024 Soren Stoutner <soren@stoutner.com>.
- This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
+ This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
Privacy Browser Android is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
android:layout_width="match_parent"
android:layout_weight="1" >
- <ScrollView
- android:id="@+id/scrollview"
+ <WebView
+ android:id="@+id/logcat_webview"
android:layout_height="wrap_content"
- android:layout_width="match_parent" >
-
- <TextView
- android:id="@+id/logcat_textview"
- android:layout_height="wrap_content"
- android:layout_width="match_parent"
- android:layout_margin="10dp"
- android:textIsSelectable="true" />
- </ScrollView>
+ android:layout_width="match_parent" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<!-- The app bar theme must be specified here because the activity uses a `NoActionBar` theme. -->
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright 2018-2023 Soren Stoutner <soren@stoutner.com>.
+ Copyright 2018-2024 Soren Stoutner <soren@stoutner.com>.
- This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
+ This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
Privacy Browser Android is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
android:layout_height="match_parent"
android:layout_width="match_parent" >
- <ScrollView
- android:id="@+id/scrollview"
+ <WebView
+ android:id="@+id/logcat_webview"
android:layout_height="wrap_content"
- android:layout_width="match_parent" >
-
- <TextView
- android:id="@+id/logcat_textview"
- android:layout_height="wrap_content"
- android:layout_width="match_parent"
- android:layout_margin="10dp"
- android:textIsSelectable="true" />
- </ScrollView>
+ android:layout_width="match_parent" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>