]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/commitdiff
Implement Orbot proxy support. Fixes https://redmine.stoutner.com/issues/26.
authorSoren Stoutner <soren@stoutner.com>
Thu, 15 Sep 2016 05:15:07 +0000 (22:15 -0700)
committerSoren Stoutner <soren@stoutner.com>
Thu, 15 Sep 2016 05:15:07 +0000 (22:15 -0700)
27 files changed:
.idea/dictionaries/soren.xml
app/src/main/assets/de/images/tor.png [new symlink]
app/src/main/assets/en/guide_tor.html
app/src/main/assets/en/images/tor.png [new file with mode: 0644]
app/src/main/java/com/stoutner/privacybrowser/AboutTabFragment.java
app/src/main/java/com/stoutner/privacybrowser/BookmarksDatabaseViewActivity.java
app/src/main/java/com/stoutner/privacybrowser/MainWebViewActivity.java
app/src/main/java/com/stoutner/privacybrowser/OrbotProxyHelper.java [new file with mode: 0644]
app/src/main/java/com/stoutner/privacybrowser/SettingsFragment.java
app/src/main/java/com/stoutner/privacybrowser/SslCertificateError.java
app/src/main/java/com/stoutner/privacybrowser/ViewSslCertificate.java
app/src/main/res/drawable/bookmarks_list_selector.xml
app/src/main/res/layout/about_coordinatorlayout.xml
app/src/main/res/layout/about_tab_version.xml
app/src/main/res/layout/bookmarks_coordinatorlayout.xml
app/src/main/res/layout/bookmarks_database_view_coordinatorlayout.xml
app/src/main/res/layout/bookmarks_database_view_item_linearlayout.xml
app/src/main/res/layout/guide_coordinatorlayout.xml
app/src/main/res/layout/main_coordinatorlayout.xml
app/src/main/res/layout/navigation_header.xml
app/src/main/res/layout/ssl_certificate_error.xml
app/src/main/res/layout/url_bar.xml
app/src/main/res/layout/view_ssl_certificate.xml
app/src/main/res/values/colors.xml
app/src/main/res/values/strings.xml
app/src/main/res/values/styles.xml
app/src/main/res/xml/preferences.xml

index c623c83507b93f04ae614b58606c05663d287b21..5818a70897aee182e62364428e36f137dde0f48c 100644 (file)
@@ -39,6 +39,7 @@
       <w>oname</w>
       <w>orbot</w>
       <w>panopticlick</w>
+      <w>parameterized</w>
       <w>parentfolder</w>
       <w>programatically</w>
       <w>qwant</w>
@@ -58,6 +59,7 @@
       <w>tablayout</w>
       <w>techrepublic</w>
       <w>textview</w>
+      <w>torproject</w>
       <w>uids</w>
       <w>uname</w>
       <w>webkay</w>
diff --git a/app/src/main/assets/de/images/tor.png b/app/src/main/assets/de/images/tor.png
new file mode 120000 (symlink)
index 0000000..4d657c3
--- /dev/null
@@ -0,0 +1 @@
+../../en/images/tor.png
\ No newline at end of file
index caab3b4c72feeaef5b8c268428db00bf18f59693..1ce0d59dfd4b813aceb477f327da483373f10626 100644 (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
diff --git a/app/src/main/assets/en/images/tor.png b/app/src/main/assets/en/images/tor.png
new file mode 100644 (file)
index 0000000..58dc7e1
Binary files /dev/null and b/app/src/main/assets/en/images/tor.png differ
index 5c670bcd5f0763472e307a3d8ad5daf71303e12e..7d63bb22908e13a62220d636078f986db7995485 100644 (file)
@@ -119,7 +119,7 @@ public class AboutTabFragment extends Fragment {
             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);
index db5b198e8cf8d213495f00378284badc49e33a8d..d4d0f4c6ce60eee68e58993122591f9383b5e3dc 100644 (file)
@@ -122,7 +122,7 @@ public class BookmarksDatabaseViewActivity extends AppCompatActivity {
                 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);
index 4433cf386ed82e30037aa660848c5950a5b2ee42..54f6d8ff1aa3cd2025f7dd3cf6e9903dac10c9c5 100644 (file)
@@ -23,6 +23,7 @@ import android.annotation.SuppressLint;
 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;
@@ -74,6 +75,14 @@ import java.util.Map;
 // 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;
@@ -162,10 +171,13 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         // 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;
@@ -200,7 +212,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         // 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() {
@@ -448,6 +460,10 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
             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();
@@ -469,7 +485,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         // 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();
         }
@@ -951,7 +967,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation
         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);
diff --git a/app/src/main/java/com/stoutner/privacybrowser/OrbotProxyHelper.java b/app/src/main/java/com/stoutner/privacybrowser/OrbotProxyHelper.java
new file mode 100644 (file)
index 0000000..ec9ad58
--- /dev/null
@@ -0,0 +1,101 @@
+/**
+ * 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));
+        }
+    }
+}
index 7446ce61c814219dc6ed37ed84901facb62d037a..60e250b2241f0337f86251cf64b8e4d27ba13fe2 100644 (file)
@@ -20,6 +20,7 @@
 package com.stoutner.privacybrowser;
 
 import android.annotation.SuppressLint;
+import android.app.Activity;
 import android.content.SharedPreferences;
 import android.os.Build;
 import android.os.Bundle;
@@ -241,6 +242,17 @@ public class SettingsFragment extends PreferenceFragment {
                         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")) {
index e42b39269618b60c0b308b84bf560ae933d2ab93..3ee666f83d633e098e06a2f40987f612ea9d6a3b 100644 (file)
@@ -212,7 +212,7 @@ public class SslCertificateError extends DialogFragment{
         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);
index 2a81362a800f9f90d46a090eb8309b90774eea38..f68f503c1288616e3ef7fe3387731a205fcaf8a0 100644 (file)
@@ -26,15 +26,12 @@ import android.graphics.drawable.BitmapDrawable;
 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 {
@@ -123,7 +120,7 @@ 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);
index 834b9ec67a92b183e8df8caae31abeba5d95c63b..30e99383d8fdbc088dc0168d2664049db50f0743 100644 (file)
@@ -22,5 +22,5 @@
 <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
index a0d221e6a7a7270e37ccdf34f298691e02da1c0b..6821c44687734b99064d925207911fce95e6d212 100644 (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. -->
@@ -48,7 +48,7 @@
                 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" />
 
@@ -57,8 +57,8 @@
                 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" />
index 0fd5201355cba484e49305dfd086dff8456a3680..7196450c9d3d189435e41bc00223907db3aac4c9 100644 (file)
@@ -60,7 +60,7 @@
                 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>
@@ -82,7 +82,7 @@
                 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
index 4ebdaaa5a729ce834d83c51026052bf37b5afffb..c055ea9984aafa47013a30f84e42b3d61a2ba1b9 100644 (file)
@@ -46,7 +46,7 @@
                 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>
index 2db02819be5947ecef1a131031aa159299f4c3dd..b1aa243db0196181a409a9aa1859cb785875b7ff 100644 (file)
@@ -45,7 +45,7 @@
                 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>
index 393ac28fde2b96c58802fe734ecea8ba2787d358..8bbaf1bfd7f99c6a32918062d0004677a0cd1cd5 100644 (file)
@@ -41,7 +41,7 @@
             android:layout_width="50dp"
             android:layout_marginEnd="10dp"
             android:gravity="end"
-            android:textColor="@color/grey"
+            android:textColor="@color/grey_500"
             android:textSize="22sp" />
 
         <ImageView
index 9f755e792160cdbcd5d4c2c0dc9ff0bbe0f0ce30..2cdcc95db4c03341957f75170a8e0b0e740c7f4e 100644 (file)
         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. -->
@@ -48,7 +48,7 @@
                 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" />
 
@@ -57,8 +57,8 @@
                 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" />
index 0dba1f956852a28b8211221d1f93e1e8b2af5665..b0d9c1f2a257b6eb96cfb447f9b762576e3cd011 100644 (file)
@@ -56,7 +56,7 @@
                     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>
 
@@ -81,5 +81,5 @@
         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
index 7ed9685ec9653b1b18c116b435e91df814e0450c..0f6c443aaf5be1bf3fa103a68aff63bf1715af10 100644 (file)
@@ -32,6 +32,6 @@
     android:paddingStart="15dp"
     android:textStyle="bold"
     android:textSize="20sp"
-    android:background="@color/blue"
+    android:background="@color/blue_700"
     android:textColor="@color/white" />
 
index c96265121c1cdcf885cb60dd52360523398026b8..08e8ca79c69e38dfa6917b7dcd515f5664fb3692 100644 (file)
@@ -33,7 +33,7 @@
             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. -->
@@ -44,7 +44,7 @@
             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"
@@ -59,7 +59,7 @@
             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"
@@ -85,7 +85,7 @@
             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"
index 19751aa510b4b95d9f581a0ac26d624718068b15..7421467038ff842219b43e764c4f1c7123b43e27 100644 (file)
@@ -64,7 +64,7 @@
         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
index cdb5cebed485439d4d5f1617931eaf3aead55004..ccef2701151629daea357a824df6dcebd147de28 100644 (file)
@@ -36,7 +36,7 @@
             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"
@@ -62,7 +62,7 @@
             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"
@@ -88,7 +88,7 @@
             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"
index 46a5fb5a27477da35258dad5830af35634aa8c1f..f72cc34db90678a6d92534a0a205e9fac946c462 100644 (file)
 <!-- 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
index 628548f3e33af3d49593b1e6fc5c101fbd4eb2fb..9b6a969d939b1d85ec15347dcb11d4bebde9d319 100644 (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&amp;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&amp;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>
index 25ca3a0d59f9946efef73c32c45ea2cdf7874d93..74364f582950d315a008fe9cc0850d137f732ca8 100644 (file)
         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. -->
@@ -51,6 +51,6 @@
     <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
index 4441ca6a5dfc3aed53ef8f3308be0028d46ca207..35d9ed1b6b4ec7c3a7413697da32a055940bcb67 100644 (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