<w>oname</w>
<w>orbot</w>
<w>panopticlick</w>
+ <w>parameterized</w>
<w>parentfolder</w>
<w>programatically</w>
<w>qwant</w>
<w>tablayout</w>
<w>techrepublic</w>
<w>textview</w>
+ <w>torproject</w>
<w>uids</w>
<w>uname</w>
<w>webkay</w>
--- /dev/null
+../../en/images/tor.png
\ No newline at end of file
color: 0D4781;
}
- strong {
- color: BF360C;
+ img.center {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
}
</style>
</head>
<body>
-<h3>Masking IP Addresses</h3>
-
-<p>Although it isn't a perfect science, IP addresses can be turned into physical addresses with increasing accuracy.
- There are <a href="https://www.whatismyip.com/">public databases</a> that show which ISP owns which IP address with a
- good sense of which region they use it in. There are private databases with more accurate information. And, of course,
- the ISP knows the exact service address of each IP address.</p>
-
-<p>VPN services can mask a device's IP address from a web server. When a VPN service is engaged, all traffic is encrypted and routed
- through the VPN server. The web server only sees the IP address of the VPN server. This is sufficient for maintaining anonymity
- from web server operators and advertisers, as well as accessing websites that intentionally block access from particular countries
- (like some music and video streaming services), but it isn't sufficient for maintaining anonymity from oppressive regimes which might
- be able to lean on VPN operators to turn over their logs showing the original IP addresses. Those looking for safety from such
- regimes or desiring to blow the whistle on government agencies need something more.</p>
-
-<p>The TOR (The Onion Router) network was designed for just such purposes. It bounces encrypted web traffic through at least three independent servers
- that volunteer bandwidth to the project. None of the servers have enough information to identify both the IP address of the original computer
- and the final destination. Therefore, any government agency wanting to access the information would have to compromise all the machines in the
- link, which are dispersed over the globe. This doesn't provide perfect privacy, but it gets pretty close.</p>
-
-<p>The Tor project has an app for Android called Orbot, which is available on <a href="https://f-droid.org/repository/browse/?fdfilter=orbot&fdid=org.torproject.android">F-Droid</a>
- and everywhere else Privacy Browser is distributed. Orbot can operate in three modes.</p>
-
-<ul>
- <li><strong>Proxy mode</strong> Apps have to request to proxy their traffic through Orbot, meaning that each app developer has to add code to
- their project to make it work.</li>
- <li><strong>Transparent proxy mode</strong> Orbot intercepts traffic from other apps as it heads out onto the network and redirects it to the
- Tor network. Apps do not need to be modified by their developer to work with transparent proxy mode, but it does require that Orbot have
- root access on the device.</li>
- <li><strong>VPN mode</strong> Orbot registers itself as a VPN using Android's builtin VPN interface. Apps do not need to be modified by the
- developer to work with Orbot in VPN mode and root is not required.</li>
-</ul>
-
-<p>Currently, Privacy Browser works with Orbot in transparent proxy and VPN modes. Support for the standard proxy mode will be added in a
- <a href="https://redmine.stoutner.com/issues/26">future release</a>.</p>
-
-<p>Because traffic is being routed through several Tor nodes, using Tor is often much slower than connecting straight to the internet.</p>
+<h3>Tor and Its Limits</h3>
+
+<p>There are two general categories of bad actors that want to infringe on the privacy of the web: malicious governments
+ with access to ISPs (Internet Service Providers) and mega corporations that run social and advertising networks.
+ TOR (The Onion Router) is useful in protecting privacy from malicious governments but not from mega corporations.</p>
+
+
+<h3>Malicious Governments</h3>
+
+<p>Malicious governments often spy on their citizens to punish dissent or human rights activity. They commonly either
+ operate the local ISPs or they can force them to disclose information showing every IP address that is visited
+ by each user. Tor is designed to defeat this infringement of privacy by encrypting the traffic
+ from a user's device and routing it through three separate 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 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 Tor. In some parts of
+ the world, using Tor could be construed as an evidence of illegal behavior ("if you didn't have anything
+ to hide you wouldn't be hiding your traffic from us") and users could be punished because governments
+ assume they are doing something that is prohibited. Thus, Tor can be helpful, but isn't a panacea.</p>
+
+
+<h3>Mega Corporations</h3>
+
+<p>When a user connects to a web server, the web server can see the user's IP address. Although it isn't a perfect science,
+ IP addresses can be turned into physical addresses with a <a href="https://www.whatismyip.com/">fair amount of accuracy</a>.
+ Small web servers typically rely on IP addresses to identify the location of the users visiting their site.
+ Tor is a good solution to mask the user's location from these servers. But large mega corporations
+ that own social media and advertising networks use a whole profile of information that is designed to track users
+ across devices and IP addresses. These profiles employ a variety of techniques to identify users, including JavaScript,
+ cookies, tracking IDs, and <a href="https://panopticlick.eff.org/">browser fingerprinting</a>. Because the vast majority
+ of the websites on the internet either load an ad from one of the major networks or embed social media icons with their
+ associated JavaScript, these corporations have build profiles for almost every user online and can track their internet
+ activity across unrelated sites.</p>
+
+<p>They track every site that is visited, everything that is purchased, every credit card that is used to
+ make a purchase, every address that items are shipped to, and the GPS metadata of every picture that is
+ uploaded to the internet. They build a profile of a user's age, gender, marital status, address, political affiliations,
+ religious affiliations, family circumstance, number of pets, and everything else they can get their hands on.
+ They even buy up databases of credit card usage at stores, so they can track the off-line purchasing patterns of the users
+ in their profiles. Because they already have much more accurate address information about a user than an IP address discloses,
+ Tor provides no real privacy protection against mega corporations.</p>
+
+<p>The single best privacy protection against mega corporations is to browse the web with JavaScript disabled, followed
+ by blocking ad networks, disabling cookies and DOM storage, and using a browser that is difficult to fingerprint.</p>
+
+
+<h3>Using Tor</h3>
+
+<p>Despite the limitations, Tor can be useful in some circumstances. The Tor project has an app for Android called Orbot,
+ which is available on <a href="https://f-droid.org/repository/browse/?fdfilter=orbot&fdid=org.torproject.android">F-Droid</a>
+ and everywhere else that Privacy Browser is distributed. Privacy Browser has a setting to use Orbot as
+ a proxy. When this is turned on, Privacy Browser's app bar will have a light blue background instead of
+ the default light grey. When Privacy Browser's Orbot proxy setting is enabled, internet access
+ will not work unless Orbot is running and connected to Tor. Because traffic is being routed through several Tor nodes,
+ using Tor is often much slower than connecting straight to the internet.</p>
+
+<img class="center" src="images/tor.png" height="640" width="360">
</body>
</html>
\ No newline at end of file
SpannableStringBuilder chromeStringBuilder = new SpannableStringBuilder(chromeLabel + chrome);
// Create a blue `ForegroundColorSpan`. We have to use the deprecated `getColor` until API >= 23.
- ForegroundColorSpan blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue));
+ ForegroundColorSpan blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue_700));
// Setup the spans to display the device information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
brandStringBuilder.setSpan(blueColorSpan, brandLabel.length(), brandStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
if (bookmarkParentFolder.isEmpty()) {
parentFolderImageView.setImageDrawable(ContextCompat.getDrawable(getApplicationContext(), R.drawable.folder_grey));
bookmarkParentFolderTextView.setText(R.string.home_folder);
- bookmarkParentFolderTextView.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.grey));
+ bookmarkParentFolderTextView.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.grey_500));
} else {
parentFolderImageView.setImageDrawable(ContextCompat.getDrawable(getApplicationContext(), R.drawable.folder_dark_blue));
bookmarkParentFolderTextView.setText(bookmarkParentFolder);
import android.app.Activity;
import android.app.DialogFragment;
import android.app.DownloadManager;
+import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
// We need to use AppCompatActivity from android.support.v7.app.AppCompatActivity to have access to the SupportActionBar until the minimum API is >= 21.
public class MainWebViewActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, CreateHomeScreenShortcut.CreateHomeScreenSchortcutListener,
SslCertificateError.SslCertificateErrorListener, DownloadFile.DownloadFileListener {
+ // `privacyBrowserContext` is public static so it can be accessed from `SettingsFragment`.
+ // It is also used in `onCreate()` and `onConfigurationChanged()`.
+ public static Context privacyBrowserContext;
+
+ // `appBar` is public static so it can be accessed from `OrbotProxyHelper`.
+ // It is also used in `onCreate()`.
+ public static ActionBar appBar;
+
// `favoriteIcon` is public static so it can be accessed from `CreateHomeScreenShortcut`, `BookmarksActivity`, `CreateBookmark`, `CreateBookmarkFolder`, and `EditBookmark`.
// It is also used in `onCreate()` and `onCreateHomeScreenShortcutCreate()`.
public static Bitmap favoriteIcon;
// We need a handle for the activity, which is accessed from `SettingsFragment` and fed into `updatePrivacyIcons()`.
privacyBrowserActivity = this;
+ // Get a handle for the application context.
+ privacyBrowserContext = getApplicationContext();
+
// We need to use the SupportActionBar from android.support.v7.app.ActionBar until the minimum API is >= 21.
Toolbar supportAppBar = (Toolbar) findViewById(R.id.appBar);
setSupportActionBar(supportAppBar);
- final ActionBar appBar = getSupportActionBar();
+ appBar = getSupportActionBar();
// This is needed to get rid of the Android Studio warning that appBar might be null.
assert appBar != null;
// Implement swipe to refresh
swipeToRefresh = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout);
assert swipeToRefresh != null; //This assert removes the incorrect warning on the following line that swipeToRefresh might be null.
- swipeToRefresh.setColorSchemeResources(R.color.blue);
+ swipeToRefresh.setColorSchemeResources(R.color.blue_700);
swipeToRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
customHeaders.put("DNT", "1");
}
+ // Set Orbot proxy status. The default is `false`.
+ if (sharedPreferences.getBoolean("proxy_through_orbot", false)) {
+ OrbotProxyHelper.setProxy(privacyBrowserContext, privacyBrowserActivity, "localhost", "8118");
+ }
// Get the intent information that started the app.
final Intent intent = getIntent();
// If the favorite icon is null, load the default.
if (favoriteIcon == null) {
// We have to use `ContextCompat` until API >= 21.
- Drawable favoriteIconDrawable = ContextCompat.getDrawable(getApplicationContext(), R.drawable.world);
+ Drawable favoriteIconDrawable = ContextCompat.getDrawable(privacyBrowserContext, R.drawable.world);
BitmapDrawable favoriteIconBitmapDrawable = (BitmapDrawable) favoriteIconDrawable;
favoriteIcon = favoriteIconBitmapDrawable.getBitmap();
}
super.onConfigurationChanged(newConfig);
// Reload the ad if this is the free flavor.
- BannerAd.reloadAfterRotate(adView, getApplicationContext(), getString(R.string.ad_id));
+ BannerAd.reloadAfterRotate(adView, privacyBrowserContext, getString(R.string.ad_id));
// Reinitialize the adView variable, as the View will have been removed and re-added in the free flavor by BannerAd.reloadAfterRotate().
adView = findViewById(R.id.adView);
--- /dev/null
+/**
+ * Copyright 2016 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;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.Proxy;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.app.AlertDialog;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class OrbotProxyHelper {
+ public static void setProxy(Context privacyBrowserContext, Activity parentActivity, String proxyHost, String proxyPort) {
+ // Set the proxy values
+ System.setProperty("http.proxyHost", proxyHost);
+ System.setProperty("http.proxyPort", proxyPort);
+ System.setProperty("https.proxyHost", proxyHost);
+ System.setProperty("https.proxyPort", proxyPort);
+
+ // Use reflection to apply the new proxy values.
+ try {
+ Class applicationClass = Class.forName("android.app.Application");
+ Field mLoadedApkField = applicationClass.getDeclaredField("mLoadedApk");
+ // `setAccessible(true)` allows us to change the value of `mLoadedApkField`.
+ mLoadedApkField.setAccessible(true);
+ Object mLoadedApkObject = mLoadedApkField.get(privacyBrowserContext);
+
+ Class loadedApkClass = Class.forName("android.app.LoadedApk");
+ Field mReceiversField = loadedApkClass.getDeclaredField("mReceivers");
+ // `setAccessible(true)` allows us to change the value of `mReceiversField`.
+ mReceiversField.setAccessible(true);
+
+ ArrayMap receivers = (ArrayMap) mReceiversField.get(mLoadedApkObject);
+
+ for (Object receiverMap : receivers.values()) {
+ for (Object receiver : ((ArrayMap) receiverMap).keySet()) {
+ // We have to use `Class<?>`, which is an `unbounded wildcard parameterized type`, instead of `Class`, which is a `raw type`, or `receiveClass.getDeclaredMethod` below will produce an error.
+ Class<?> receiverClass = receiver.getClass();
+ if (receiverClass.getName().contains("ProxyChangeListener")) {
+ Method onReceiveMethod = receiverClass.getDeclaredMethod("onReceive", Context.class, Intent.class);
+ Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
+ onReceiveMethod.invoke(receiver, privacyBrowserContext, intent);
+ }
+ }
+ }
+ } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException | NoSuchMethodException | InvocationTargetException exception) {
+ Log.d("enableProxyThroughOrbot", "Exception: " + exception);
+ }
+
+ if (proxyPort.equals("8118")) { // Orbot proxy was turned on.
+ // Set the `appBar` background to be light blue if Orbot proxy support is enabled.
+ MainWebViewActivity.appBar.setBackgroundDrawable(ContextCompat.getDrawable(privacyBrowserContext, R.color.blue_50));
+
+ try { // Check to see if Orbot is installed.
+ PackageManager packageManager = privacyBrowserContext.getPackageManager();
+ packageManager.getPackageInfo("org.torproject.android", PackageManager.GET_ACTIVITIES);
+ } catch (PackageManager.NameNotFoundException exception){ // If an exception is thrown, Orbot is not installed.
+ // Build an `AlertDialog`. `R.style.LightAlertDialog` formats the color of the button text.
+ AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(parentActivity, R.style.LightAlertDialog);
+ dialogBuilder.setMessage(R.string.orbot_proxy_not_installed);
+ dialogBuilder.setPositiveButton(R.string.close, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ // Do nothing. The `AlertDialog` will close automatically.
+ }
+ });
+
+ // Convert `dialogBuilder` to `alertDialog` and display it on the screen.
+ AlertDialog alertDialog = dialogBuilder.create();
+ alertDialog.show();
+ }
+ } else { // Otherwise set the default grey `appBar` background.
+ MainWebViewActivity.appBar.setBackgroundDrawable(ContextCompat.getDrawable(privacyBrowserContext, R.color.grey_100));
+ }
+ }
+}
package com.stoutner.privacybrowser;
import android.annotation.SuppressLint;
+import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
MainWebViewActivity.mainWebView.getSettings().setUserAgentString(sharedPreferences.getString("custom_user_agent", "PrivacyBrowser/1.0"));
break;
+ case "proxy_through_orbot":
+ // Get a handle for `settingsActivity`.
+ Activity settingsActivity = getActivity();
+
+ // Update the proxy. The default is `false`
+ if (sharedPreferences.getBoolean("proxy_through_orbot", false)) { // Orbot proxies on localhost port 8118.
+ OrbotProxyHelper.setProxy(MainWebViewActivity.privacyBrowserContext, settingsActivity, "localhost", "8118");
+ } else { // Disable the proxy by setting the host to `null` and the port to `0`.
+ OrbotProxyHelper.setProxy(MainWebViewActivity.privacyBrowserContext, settingsActivity, "", "0");
+ }
+
case "javascript_disabled_search":
String newJavaScriptDisabledSearchString = sharedPreferences.getString("javascript_disabled_search", "https://duckduckgo.com/html/?q=");
if (newJavaScriptDisabledSearchString.equals("Custom URL")) {
SpannableStringBuilder endDateStringBuilder = new SpannableStringBuilder((endDateLabel + endDate));
// Create a blue `ForegroundColorSpan`. We have to use the deprecated `getColor` until API >= 23.
- ForegroundColorSpan blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue));
+ ForegroundColorSpan blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue_700));
// Setup the spans to display the certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
urlStringBuilder.setSpan(blueColorSpan, urlLabel.length(), urlStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
import android.graphics.drawable.Drawable;
import android.net.http.SslCertificate;
import android.os.Bundle;
-import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import android.view.LayoutInflater;
import android.widget.TextView;
-import org.w3c.dom.Text;
-
import java.util.Date;
public class ViewSslCertificate extends DialogFragment {
SpannableStringBuilder endDateStringBuilder = new SpannableStringBuilder(endDateLabel + endDate.toString());
// Create a blue `ForegroundColorSpan`. We have to use the deprecated `getColor` until API >= 23.
- ForegroundColorSpan blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue));
+ ForegroundColorSpan blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue_700));
// Setup the spans to display the certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
issuedToCNameStringBuilder.setSpan(blueColorSpan, cNameLabel.length(), issuedToCNameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_activated="true"
- android:drawable="@color/light_blue" />
+ android:drawable="@color/blue_100" />
</selector>
\ No newline at end of file
android:layout_width="match_parent"
android:orientation="vertical" >
- <!-- We need to set android:background="@color/blue" here or any space to the right of the TabLayout on large devices will be white. -->
+ <!-- We need to set android:background="@color/blue_700" here or any space to the right of the TabLayout on large devices will be white. -->
<android.support.design.widget.AppBarLayout
android:id="@+id/about_appbarlayout"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- android:background="@color/blue"
+ android:background="@color/blue_700"
android:theme="@style/AppBarOverlay" >
<!-- android:theme="@style/PrivacyBrowser.DarkAppBar" makes the text and icons in the AppBar white. -->
android:id="@+id/about_toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- android:background="@color/blue"
+ android:background="@color/blue_700"
android:theme="@style/DarkAppBar"
app:popupTheme="@style/LightPopupOverlay" />
xmlns:android.support.design="http://schemas.android.com/apk/res-auto"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- android.support.design:tabBackground="@color/blue"
- android.support.design:tabTextColor="@color/light_blue"
+ android.support.design:tabBackground="@color/blue_700"
+ android.support.design:tabTextColor="@color/blue_100"
android.support.design:tabSelectedTextColor="@color/white"
android.support.design:tabIndicatorColor="@color/white"
android.support.design:tabMode="scrollable" />
android:id="@+id/about_version_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textColor="@color/blue"
+ android:textColor="@color/blue_700"
android:layout_below="@id/about_version_privacy_browser_textview"
android:layout_toEndOf="@id/about_version_icon" />
</RelativeLayout>
android:text="@string/hardware"
android:textStyle="bold"
android:textSize="18sp"
- android:textColor="@color/dark_blue" />
+ android:textColor="@color/blue_900" />
<TextView
android:id="@+id/about_version_brand"
android:text="@string/software"
android:textStyle="bold"
android:textSize="18sp"
- android:textColor="@color/dark_blue"
+ android:textColor="@color/blue_900"
android:paddingTop="12dp" />
<TextView
android:id="@+id/bookmarks_toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- android:background="@color/blue"
+ android:background="@color/blue_700"
android:theme="@style/DarkAppBar"
app:popupTheme="@style/LightPopupOverlay" />
</android.support.design.widget.AppBarLayout>
android:id="@+id/bookmarks_database_view_toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- android:background="@color/blue"
+ android:background="@color/blue_700"
android:theme="@style/DarkAppBar"
app:popupTheme="@style/LightPopupOverlay" />
</android.support.design.widget.AppBarLayout>
android:layout_width="50dp"
android:layout_marginEnd="10dp"
android:gravity="end"
- android:textColor="@color/grey"
+ android:textColor="@color/grey_500"
android:textSize="22sp" />
<ImageView
android:layout_height="match_parent"
android:orientation="vertical" >
- <!-- We need to set android:background="@color/blue" here or any space to the right of the TabLayout on large devices will be white. -->
+ <!-- We need to set android:background="@color/blue_700" here or any space to the right of the TabLayout on large devices will be white. -->
<android.support.design.widget.AppBarLayout
android:id="@+id/guide_appbarlayout"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- android:background="@color/blue"
+ android:background="@color/blue_700"
android:theme="@style/AppBarOverlay" >
<!-- android:theme="@style/PrivacyBrowser.DarkAppBar" makes the text and icons in the AppBar white. -->
android:id="@+id/guide_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="@color/blue"
+ android:background="@color/blue_700"
android:theme="@style/DarkAppBar"
app:popupTheme="@style/LightPopupOverlay" />
xmlns:android.support.design="http://schemas.android.com/apk/res-auto"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- android.support.design:tabBackground="@color/blue"
- android.support.design:tabTextColor="@color/light_blue"
+ android.support.design:tabBackground="@color/blue_700"
+ android.support.design:tabTextColor="@color/blue_100"
android.support.design:tabSelectedTextColor="@color/white"
android.support.design:tabIndicatorColor="@color/white"
android.support.design:tabMode="scrollable" />
android:id="@+id/appBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="?attr/colorPrimary"
+ android:background="@color/grey_100"
app:popupTheme="@style/LightPopupOverlay" />
</android.support.design.widget.AppBarLayout>
android:layout_gravity="start"
app:headerLayout="@layout/navigation_header"
app:menu="@menu/webview_navigation_menu"
- app:itemIconTint="@color/blue_grey" />
+ app:itemIconTint="@color/blue_800" />
</android.support.v4.widget.DrawerLayout>
\ No newline at end of file
android:paddingStart="15dp"
android:textStyle="bold"
android:textSize="20sp"
- android:background="@color/blue"
+ android:background="@color/blue_700"
android:textColor="@color/white" />
android:id="@+id/primary_error"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:textColor="@color/red"
+ android:textColor="@color/red_a700"
android:textStyle="bold"/>
<!-- URL. -->
android:text="@string/url"
android:textAllCaps="true"
android:textStyle="bold"
- android:textColor="@color/dark_blue" />
+ android:textColor="@color/blue_900" />
<TextView
android:id="@+id/url_error_dialog"
android:text="@string/issued_to"
android:textAllCaps="true"
android:textStyle="bold"
- android:textColor="@color/dark_blue" />
+ android:textColor="@color/blue_900" />
<TextView
android:id="@+id/issued_to_cname_error_dialog"
android:text="@string/issued_by"
android:textAllCaps="true"
android:textStyle="bold"
- android:textColor="@color/dark_blue"/>
+ android:textColor="@color/blue_900"/>
<TextView
android:id="@+id/issued_by_cname_error_dialog"
android:text="@string/valid_dates"
android:textAllCaps="true"
android:textStyle="bold"
- android:textColor="@color/dark_blue"/>
+ android:textColor="@color/blue_900"/>
<TextView
android:id="@+id/start_date_error_dialog"
android:layout_height="3dp"
android:layout_gravity="bottom"
android:max="100"
- android:progressTint="@color/blue"
+ android:progressTint="@color/blue_700"
android:progressBackgroundTint="@color/white"
android:visibility="gone" />
</FrameLayout>
\ No newline at end of file
android:text="@string/issued_to"
android:textAllCaps="true"
android:textStyle="bold"
- android:textColor="@color/dark_blue" />
+ android:textColor="@color/blue_900" />
<TextView
android:id="@+id/issued_to_cname"
android:text="@string/issued_by"
android:textAllCaps="true"
android:textStyle="bold"
- android:textColor="@color/dark_blue"/>
+ android:textColor="@color/blue_900"/>
<TextView
android:id="@+id/issued_by_cname"
android:text="@string/valid_dates"
android:textAllCaps="true"
android:textStyle="bold"
- android:textColor="@color/dark_blue"/>
+ android:textColor="@color/blue_900"/>
<TextView
android:id="@+id/start_date"
<!-- These color resources are hardcoded for vector drawables. Once the minimum API is >= 22 we can remove the hardcoded colors and reference these entries. -->
<resources>
<color name="black">#FF000000</color>
- <color name="blue">#FF1976D2</color>
- <color name="dark_blue">#FF0D47A1</color>
- <color name="blue_grey">#FF607D8B</color>
- <color name="grey">#FF9E9E9E</color>
- <color name="green">#FF64DD17</color>
- <color name="light_blue">#FFBBDEFB</color>
- <color name="medium_light_blue">#FF42A5F5</color>
- <color name="orange">#FFF57F17</color>
- <color name="red">#FFD50000</color>
+
+ <color name="blue_50">#FFE3F2FD</color>
+ <color name="blue_100">#FFBBDEFB</color>
+ <color name="blue_200">#FF90CAF9</color>
+ <color name="blue_300">#FF64B5F6</color>
+ <color name="blue_400">#FF42A5F5</color>
+ <color name="blue_500">#FF2196F3</color>
+ <color name="blue_600">#FF1E88E5</color>
+ <color name="blue_700">#FF1976D2</color>
+ <color name="blue_800">#FF1565C0</color>
+ <color name="blue_900">#FF0D47A1</color>
+ <color name="blue_a700">#FF2962FF</color>
+
+ <color name="blue_grey_500">#FF607D8B</color>
+
+ <color name="grey_100">#FFF5F5F5</color>
+ <color name="grey_500">#FF9E9E9E</color>
+
+ <color name="light_green_a700">#FF64DD17</color>
+
+ <color name="red_a700">#FFD50000</color>
+
<color name="white">#FFFFFFFF</color>
- <color name="yellow">#FFFFD600</color>
+
+ <color name="yellow_900">#FFF57F17</color>
+ <color name="yellow_a700">#FFFFD600</color>
</resources>
\ No newline at end of file
<!-- Preferences. -->
<string name="privacy">Privacy</string>
- <string name="javascript_preference">Enable JavaScript by default</string>
- <string name="javascript_preference_summary">JavaScript allows websites to run programs (scripts) on your device.</string>
- <string name="first_party_cookies_preference">Enable first-party cookies by default</string>
- <string name="first_party_cookies_preference_summary">Devices with versions of Android older than Lollipop (version 5.0) will also enable third-party cookies with this setting.</string>
- <string name="third_party_cookies_preference">Enable third-party cookies by default</string>
- <string name="third_party_cookies_summary">This setting requires Android Lollipop (version 5.0) or higher. It has no effect if first-party cookies are disabled.</string>
- <string name="dom_storage_preference">Enable DOM storage by default</string>
- <string name="dom_storage_preference_summary">JavaScript must be enabled for DOM storage to function.</string>
- <string name="save_form_data_preference">Enable saving of form data by default</string>
- <string name="save_form_data_preference_summary">Saved form data can auto-populate fields on websites.</string>
- <string name="user_agent">User agent</string>
- <string-array name="user_agent_entries">
- <item>WebView Default</item>
- <item>Privacy Browser 1.0</item>
- <item>Firefox 48 on Android 6.0.1</item>
- <item>Chrome 52 on Android 6.0.1</item>
- <item>Safari on iOS 10</item>
- <item>Firefox 45 on Linux</item>
- <item>Chromium 52 on Linux</item>
- <item>Konqueror 4.14.23 on Linux</item>
- <item>Firefox 48 on Windows 10</item>
- <item>Chrome 52 on Windows 10</item>
- <item>Internet Explorer 11 on Windows 10</item>
- <item>Edge 14 on Windows 10</item>
- <item>Safari 9.1.2 on OS X 10.11.6</item>
- <item>Custom</item>
- </string-array>
- <string-array name="user_agent_entry_values" translatable="false"> <!-- None of the items in this `string-array` should be translated. -->
- <item>Default user agent</item> <!-- This item must not be translated into other languages because it is referenced in code. It is never displayed on the screen. -->
- <item>PrivacyBrowser/1.0</item>
- <item>Mozilla/5.0 (Android 6.0.1; Mobile; rv:48.0) Gecko/48.0 Firefox/48.0</item>
- <item>Mozilla/5.0 (Linux; Android 6.0.1; Nexus 6P Build/MTC20F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.36</item>
- <item>Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Mobile/14A5345a Safari/602.1</item>
- <item>Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0</item>
- <item>Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36</item>
- <item>Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.21 (KHTML, like Gecko) konqueror/4.14.23 Safari/537.21</item>
- <item>Mozilla/5.0 (Windows NT 10.0; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0</item>
- <item>Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36</item>
- <item>Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko</item>
- <item>Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393</item>
- <item>Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/601.7.7 (KHTML, like Gecko) Version/9.1.2 Safari/601.7.7</item>
- <item>Custom user agent</item> <!-- This item must not be translated into other languages because it is referenced in code. It is never displayed on the screen. -->
- </string-array>
- <string name="custom_user_agent">Custom user agent</string>
- <string name="do_not_track">Do not track</string>
- <string name="do_not_track_summary">Send the Do Not Track header which politely suggests that web servers not track this browser.</string>
+ <string name="javascript_preference">Enable JavaScript by default</string>
+ <string name="javascript_preference_summary">JavaScript allows websites to run programs (scripts) on your device.</string>
+ <string name="first_party_cookies_preference">Enable first-party cookies by default</string>
+ <string name="first_party_cookies_preference_summary">Devices with versions of Android older than Lollipop (version 5.0) will also enable third-party cookies with this setting.</string>
+ <string name="third_party_cookies_preference">Enable third-party cookies by default</string>
+ <string name="third_party_cookies_summary">This setting requires Android Lollipop (version 5.0) or higher. It has no effect if first-party cookies are disabled.</string>
+ <string name="dom_storage_preference">Enable DOM storage by default</string>
+ <string name="dom_storage_preference_summary">JavaScript must be enabled for DOM storage to function.</string>
+ <string name="save_form_data_preference">Enable saving of form data by default</string>
+ <string name="save_form_data_preference_summary">Saved form data can auto-populate fields on websites.</string>
+ <string name="user_agent">User agent</string>
+ <string-array name="user_agent_entries">
+ <item>WebView Default</item>
+ <item>Privacy Browser 1.0</item>
+ <item>Firefox 48 on Android 6.0.1</item>
+ <item>Chrome 52 on Android 6.0.1</item>
+ <item>Safari on iOS 10</item>
+ <item>Firefox 45 on Linux</item>
+ <item>Chromium 52 on Linux</item>
+ <item>Konqueror 4.14.23 on Linux</item>
+ <item>Firefox 48 on Windows 10</item>
+ <item>Chrome 52 on Windows 10</item>
+ <item>Internet Explorer 11 on Windows 10</item>
+ <item>Edge 14 on Windows 10</item>
+ <item>Safari 9.1.2 on OS X 10.11.6</item>
+ <item>Custom</item>
+ </string-array>
+ <string-array name="user_agent_entry_values" translatable="false"> <!-- None of the items in this `string-array` should be translated. -->
+ <item>Default user agent</item> <!-- This item must not be translated into other languages because it is referenced in code. It is never displayed on the screen. -->
+ <item>PrivacyBrowser/1.0</item>
+ <item>Mozilla/5.0 (Android 6.0.1; Mobile; rv:48.0) Gecko/48.0 Firefox/48.0</item>
+ <item>Mozilla/5.0 (Linux; Android 6.0.1; Nexus 6P Build/MTC20F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.36</item>
+ <item>Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Mobile/14A5345a Safari/602.1</item>
+ <item>Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0</item>
+ <item>Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36</item>
+ <item>Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.21 (KHTML, like Gecko) konqueror/4.14.23 Safari/537.21</item>
+ <item>Mozilla/5.0 (Windows NT 10.0; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0</item>
+ <item>Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36</item>
+ <item>Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko</item>
+ <item>Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393</item>
+ <item>Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/601.7.7 (KHTML, like Gecko) Version/9.1.2 Safari/601.7.7</item>
+ <item>Custom user agent</item> <!-- This item must not be translated into other languages because it is referenced in code. It is never displayed on the screen. -->
+ </string-array>
+ <string name="custom_user_agent">Custom user agent</string>
+ <string name="do_not_track">Do not track</string>
+ <string name="do_not_track_summary">Send the Do Not Track header which politely suggests that web servers not track this browser.</string>
+ <string name="proxy_through_orbot">Proxy through Orbot</string>
+ <string name="proxy_through_orbot_summary">Proxy all web traffic through Orbot on localhost:8118.</string>
<string name="search">Search</string>
- <string name="javascript_disabled_search">JavaScript-disabled search</string>
- <string-array name="javascript_disabled_search_entries">
- <item>DuckDuckGo</item>
- <item>Google</item>
- <item>Bing</item>
- <item>Yahoo</item>
- <item>StartPage</item>
- <item>Qwant</item>
- <item>Custom</item>
- </string-array>
- <string-array name="javascript_disabled_search_entry_values" translatable="false"> <!-- None of the items in this `string-array` should be translated. -->
- <item>https://duckduckgo.com/html/?q=</item>
- <item>https://www.google.com/search?q=</item>
- <item>https://www.bing.com/search?q=</item>
- <item>https://search.yahoo.com/mobile/s?nojs=1&p=</item>
- <item>https://www.startpage.com/do/search?q=</item>
- <item>https://lite.qwant.com/?q=</item>
- <item>Custom URL</item> <!-- This item must not be translated into other languages because it is referenced in code. It is never displayed on the screen. -->
- </string-array>
- <string name="javascript_disabled_search_custom_url">JavaScript-disabled search custom URL</string>
- <string name="javascript_enabled_search">JavaScript-enabled search</string>
- <string-array name="javascript_enabled_search_entries">
- <item>DuckDuckGo</item>
- <item>Google</item>
- <item>Bing</item>
- <item>Yahoo</item>
- <item>StartPage</item>
- <item>Qwant</item>
- <item>Custom</item>
- </string-array>
- <string-array name="javascript_enabled_search_entry_values" translatable="false"> <!-- None of the items in this `string-array` should be translated. -->
- <item>https://duckduckgo.com/?q=</item>
- <item>https://www.google.com/search?q=</item>
- <item>https://www.bing.com/search?q=</item>
- <item>https://search.yahoo.com/mobile/s?p=</item>
- <item>https://www.startpage.com/do/search?q=</item>
- <item>https://www.qwant.com/?q=</item>
- <item>Custom URL</item> <!-- This item must not be translated into other languages because it is referenced in code. It is never displayed on the screen. -->
- </string-array>
- <string name="javascript_enabled_search_custom_url">JavaScript-enabled search custom URL</string>
- <string name="custom_url">Custom URL</string>
+ <string name="javascript_disabled_search">JavaScript-disabled search</string>
+ <string-array name="javascript_disabled_search_entries">
+ <item>DuckDuckGo</item>
+ <item>Google</item>
+ <item>Bing</item>
+ <item>Yahoo</item>
+ <item>StartPage</item>
+ <item>Qwant</item>
+ <item>Custom</item>
+ </string-array>
+ <string-array name="javascript_disabled_search_entry_values" translatable="false"> <!-- None of the items in this `string-array` should be translated. -->
+ <item>https://duckduckgo.com/html/?q=</item>
+ <item>https://www.google.com/search?q=</item>
+ <item>https://www.bing.com/search?q=</item>
+ <item>https://search.yahoo.com/mobile/s?nojs=1&p=</item>
+ <item>https://www.startpage.com/do/search?q=</item>
+ <item>https://lite.qwant.com/?q=</item>
+ <item>Custom URL</item> <!-- This item must not be translated into other languages because it is referenced in code. It is never displayed on the screen. -->
+ </string-array>
+ <string name="javascript_disabled_search_custom_url">JavaScript-disabled search custom URL</string>
+ <string name="javascript_enabled_search">JavaScript-enabled search</string>
+ <string-array name="javascript_enabled_search_entries">
+ <item>DuckDuckGo</item>
+ <item>Google</item>
+ <item>Bing</item>
+ <item>Yahoo</item>
+ <item>StartPage</item>
+ <item>Qwant</item>
+ <item>Custom</item>
+ </string-array>
+ <string-array name="javascript_enabled_search_entry_values" translatable="false"> <!-- None of the items in this `string-array` should be translated. -->
+ <item>https://duckduckgo.com/?q=</item>
+ <item>https://www.google.com/search?q=</item>
+ <item>https://www.bing.com/search?q=</item>
+ <item>https://search.yahoo.com/mobile/s?p=</item>
+ <item>https://www.startpage.com/do/search?q=</item>
+ <item>https://www.qwant.com/?q=</item>
+ <item>Custom URL</item> <!-- This item must not be translated into other languages because it is referenced in code. It is never displayed on the screen. -->
+ </string-array>
+ <string name="javascript_enabled_search_custom_url">JavaScript-enabled search custom URL</string>
+ <string name="custom_url">Custom URL</string>
<string name="general">General</string>
- <string name="homepage_preference">Homepage</string>
- <string name="default_font_size">Default font size</string>
- <string-array name="default_font_size_entries">
- <item>50%</item>
- <item>75%</item>
- <item>100%</item>
- <item>125%</item>
- <item>150%</item>
- <item>175%</item>
- <item>200%</item>
- </string-array>
- <string-array name="default_font_size_entry_values" translatable="false"> <!-- None of the items in this `string-array` should be translated. -->
- <item>50</item>
- <item>75</item>
- <item>100</item>
- <item>125</item>
- <item>150</item>
- <item>175</item>
- <item>200</item>
- </string-array>
- <string name="swipe_to_refresh_enabled">Swipe to refresh</string>
- <string name="swipe_to_refresh_enabled_summary">Some websites don\'t work well if swipe to refresh is enabled.</string>
- <string name="display_additional_app_bar_icons">Display additional app bar icons</string>
- <string name="display_additional_app_bar_icons_summary">Display icons for toggling cookies, DOM storage, and form data in the app bar if there is room.</string>
+ <string name="homepage_preference">Homepage</string>
+ <string name="default_font_size">Default font size</string>
+ <string-array name="default_font_size_entries">
+ <item>50%</item>
+ <item>75%</item>
+ <item>100%</item>
+ <item>125%</item>
+ <item>150%</item>
+ <item>175%</item>
+ <item>200%</item>
+ </string-array>
+ <string-array name="default_font_size_entry_values" translatable="false"> <!-- None of the items in this `string-array` should be translated. -->
+ <item>50</item>
+ <item>75</item>
+ <item>100</item>
+ <item>125</item>
+ <item>150</item>
+ <item>175</item>
+ <item>200</item>
+ </string-array>
+ <string name="swipe_to_refresh_enabled">Swipe to refresh</string>
+ <string name="swipe_to_refresh_enabled_summary">Some websites don\'t work well if swipe to refresh is enabled.</string>
+ <string name="display_additional_app_bar_icons">Display additional app bar icons</string>
+ <string name="display_additional_app_bar_icons_summary">Display icons for toggling cookies, DOM storage, and form data in the app bar if there is room.</string>
+
+ <!-- Orbot. -->
+ <string name="orbot_proxy_not_installed">Orbot proxy will not work unless Orbot is installed.</string>
<!-- About Activity. -->
<string name="about_privacy_browser">About Privacy Browser</string>
When it is specified the root layout should include android:fitsSystemWindows="true". -->
<style name="PrivacyBrowser" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowTranslucentStatus">true</item>
- <item name="colorAccent">@color/blue</item>
+ <item name="colorAccent">@color/blue_700</item>
</style>
<!-- `colorPrimaryDark` goes behind the status bar, which is then darkened by the overlay.
`windowActionModeOverlay` makes the contextual app bar cover the support app bar. -->
<style name="PrivacyBrowser.SecondaryActivity">
- <item name="colorPrimaryDark">@color/blue</item>
+ <item name="colorPrimaryDark">@color/blue_700</item>
<item name="windowActionModeOverlay">true</item>
- <item name="android:actionModeBackground">@color/blue</item>
+ <item name="android:actionModeBackground">@color/blue_700</item>
<item name="actionBarPopupTheme">@style/LightPopupOverlay</item>
</style>
<!-- `colorPrimaryDark` is the color of the status bar. -->
<style name="Settings" parent="Theme.AppCompat.Light.DarkActionBar">
- <item name="colorPrimary">@color/blue</item>
- <item name="colorPrimaryDark">@color/dark_blue</item>
- <item name="colorAccent">@color/blue</item>
+ <item name="colorPrimary">@color/blue_700</item>
+ <item name="colorPrimaryDark">@color/blue_900</item>
+ <item name="colorAccent">@color/blue_700</item>
</style>
<!-- `ThemeOverlay.AppCompat.Dark.ActionBar` makes the text and the icons in the AppBar white. -->
<style name="LightPopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
<style name="LightAlertDialog" parent="Theme.AppCompat.Light.Dialog.Alert" >
- <item name="colorAccent">@color/blue</item>
+ <item name="colorAccent">@color/blue_700</item>
</style>
</resources>
\ No newline at end of file
android:summary="@string/do_not_track_summary"
android:defaultValue="true" />
+ <SwitchPreference
+ android:key="proxy_through_orbot"
+ android:title="@string/proxy_through_orbot"
+ android:summary="@string/proxy_through_orbot_summary"
+ android:defaultValue="false" />
+
</PreferenceCategory>
<PreferenceCategory