]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blobdiff - app/src/main/java/com/stoutner/privacybrowser/activities/MainWebView.java
Display a waiting message if proxying through Orbot is enabled but Orbot is not yet...
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / activities / MainWebView.java
index cf7cbdad3fb7f817f4e9d172b9699fabcee0b71e..e0cd539456b5eb0c005686b74706ef883c4412ca 100644 (file)
@@ -24,10 +24,12 @@ package com.stoutner.privacybrowser.activities;
 import android.annotation.SuppressLint;
 import android.app.DialogFragment;
 import android.app.DownloadManager;
+import android.content.BroadcastReceiver;
 import android.content.ClipData;
 import android.content.ClipboardManager;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.SharedPreferences;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
@@ -57,7 +59,6 @@ import android.support.v7.app.AppCompatDialogFragment;
 import android.support.v7.widget.Toolbar;
 import android.text.Editable;
 import android.text.TextWatcher;
-import android.util.Log;
 import android.util.Patterns;
 import android.view.ContextMenu;
 import android.view.GestureDetector;
@@ -129,6 +130,9 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
     // `sslCertificate` is public static so it can be accessed from `ViewSslCertificate`.  It is also used in `onCreate()`.
     public static SslCertificate sslCertificate;
 
+    // `orbotStatus` is public static so it can be accessed from `OrbotProxyHelper`.  It is also used in `onCreate()`.
+    public static String orbotStatus;
+
 
     // `drawerLayout` is used in `onCreate()`, `onNewIntent()`, and `onBackPressed()`.
     private DrawerLayout drawerLayout;
@@ -194,6 +198,12 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
     // `translucentNavigationBarOnFullscreen` is used in `onCreate()` and `applySettings()`.
     private boolean translucentNavigationBarOnFullscreen;
 
+    // `proxyThroughOrbot` is used in `onCreate()` and `applySettings()`
+    private boolean proxyThroughOrbot;
+
+    // `pendingUrl` is used in `onCreate()` and `applySettings()`
+    private String pendingUrl;
+
     // `findOnPageLinearLayout` is used in `onCreate()`, `onOptionsItemSelected()`, and `closeFindOnPage()`.
     private LinearLayout findOnPageLinearLayout;
 
@@ -559,25 +569,31 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
             // Update the URL in urlTextBox when the page starts to load.
             @Override
             public void onPageStarted(WebView view, String url, Bitmap favicon) {
-                // We need to update `formattedUrlString` at the beginning of the load, so that if the user toggles JavaScript during the load the new website is reloaded.
-                formattedUrlString = url;
+                // Check to see if we are waiting on Orbot.
+                if (pendingUrl.isEmpty()) {  // We are not waiting on Orbot, so we need to process the URL.
+                    // We need to update `formattedUrlString` at the beginning of the load, so that if the user toggles JavaScript during the load the new website is reloaded.
+                    formattedUrlString = url;
 
-                // Display the loading URL is the URL text box.
-                urlTextBox.setText(url);
+                    // Display the loading URL is the URL text box.
+                    urlTextBox.setText(url);
+                }
             }
 
             // Update formattedUrlString and urlTextBox.  It is necessary to do this after the page finishes loading because the final URL can change during load.
             @Override
             public void onPageFinished(WebView view, String url) {
-                formattedUrlString = url;
+                // Check to see if we are waiting on Orbot.
+                if (pendingUrl.isEmpty()) {  // we are not waiting on Orbot, so we need to process the URL.
+                    formattedUrlString = url;
 
-                // Only update urlTextBox if the user is not typing in it.
-                if (!urlTextBox.hasFocus()) {
-                    urlTextBox.setText(formattedUrlString);
-                }
+                    // Only update urlTextBox if the user is not typing in it.
+                    if (!urlTextBox.hasFocus()) {
+                        urlTextBox.setText(formattedUrlString);
+                    }
 
-                // Store the SSL certificate so it can be accessed from `ViewSslCertificate`.
-                sslCertificate = mainWebView.getCertificate();
+                    // Store the SSL certificate so it can be accessed from `ViewSslCertificate`.
+                    sslCertificate = mainWebView.getCertificate();
+                }
             }
 
             // Handle SSL Certificate errors.
@@ -695,6 +711,39 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
         // Replace the header that `WebView` creates for `X-Requested-With` with a null value.  The default value is the application ID (com.stoutner.privacybrowser.standard).
         customHeaders.put("X-Requested-With", "");
 
+        // Set the initial Orbot status.
+        orbotStatus = "unknown";
+
+        // Create a Orbot status `BroadcastReceiver`.
+        BroadcastReceiver orbotStatusBroadcastReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                // Store the content of the status message in `orbotStatus`.
+                orbotStatus = intent.getStringExtra("org.torproject.android.intent.extra.STATUS");
+
+                // If we are waiting on `pendingUrl`, load it now that Orbot is connected.
+                if (orbotStatus.equals("ON") && !pendingUrl.isEmpty()) {
+
+                    // Wait 500 milliseconds, because Orbot isn't really ready yet.
+                    try {
+                        Thread.sleep(500);
+                    } catch (InterruptedException exception) {
+                        // Do nothing.
+                    }
+
+                    // Load `pendingUrl`.
+                    formattedUrlString = pendingUrl;
+                    mainWebView.loadUrl(formattedUrlString, customHeaders);
+
+                    // Reset `pendingUrl` to be empty.
+                    pendingUrl = "";
+                }
+            }
+        };
+
+        // Register `orbotStatusBroadcastReceiver` on `this` context.
+        this.registerReceiver(orbotStatusBroadcastReceiver, new IntentFilter("org.torproject.android.intent.action.STATUS"));
+
         // Initialize the default preference values the first time the program is run.  `this` is the context.  `false` keeps this command from resetting any current preferences back to default.
         PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
 
@@ -715,8 +764,19 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
             formattedUrlString = homepage;
         }
 
-        // Load the initial website.
-        mainWebView.loadUrl(formattedUrlString, customHeaders);
+        // Initialize `pendingUrl`.
+        pendingUrl = "";
+
+        if (proxyThroughOrbot & !orbotStatus.equals("ON")) {  // We are waiting on Orbot.
+            // Save `formattedUrlString` in `pendingUrl`.
+            pendingUrl = formattedUrlString;
+
+            // Load a waiting page.  `null` specifies no encoding, which defaults to ASCII.
+            mainWebView.loadData("<html><body><br/><center><h1>Waiting for Orbot to connect...</h1></center></body></html>", "text/html", null);
+        } else {
+            // Load the initial website.
+            mainWebView.loadUrl(formattedUrlString, customHeaders);
+        }
 
         // If the favorite icon is null, load the default.
         if (favoriteIcon == null) {
@@ -1181,6 +1241,14 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
                 startActivity(settingsIntent);
                 break;
 
+            /*
+            case R.id.domains:
+                // Launch `DomainsList`.
+                Intent domainsIntent = new Intent(this, DomainsList.class);
+                startActivity(domainsIntent);
+                break;
+            */
+
             case R.id.guide:
                 // Launch `Guide`.
                 Intent guideIntent = new Intent(this, Guide.class);
@@ -1751,15 +1819,20 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
         String userAgentString = sharedPreferences.getString("user_agent", "PrivacyBrowser/1.0");
         String customUserAgentString = sharedPreferences.getString("custom_user_agent", "PrivacyBrowser/1.0");
         String javaScriptDisabledSearchString = sharedPreferences.getString("javascript_disabled_search", "https://duckduckgo.com/html/?q=");
-        String javaScriptDisabledCustomSearchString = sharedPreferences.getString("javascript_disabled_search_custom_url", "");
+        String javaScriptDisabledSearchCustomURLString = sharedPreferences.getString("javascript_disabled_search_custom_url", "");
         String javaScriptEnabledSearchString = sharedPreferences.getString("javascript_enabled_search", "https://duckduckgo.com/?q=");
-        String javaScriptEnabledCustomSearchString = sharedPreferences.getString("javascript_enabled_search_custom_url", "");
+        String javaScriptEnabledSearchCustomURLString = sharedPreferences.getString("javascript_enabled_search_custom_url", "");
         String homepageString = sharedPreferences.getString("homepage", "https://www.duckduckgo.com");
+        String torHomepageString = sharedPreferences.getString("tor_homepage", "https://3g2upl4pq6kufc4m.onion");
+        String torJavaScriptDisabledSearchString = sharedPreferences.getString("tor_javascript_disabled_search", "https://3g2upl4pq6kufc4m.onion/html/?q=");
+        String torJavaScriptDisabledSearchCustomURLString = sharedPreferences.getString("tor_javascript_disabled_search_custom_url", "");
+        String torJavaScriptEnabledSearchString = sharedPreferences.getString("tor_javascript_enabled_search", "https://3g2upl4pq6kufc4m.onion/?q=");
+        String torJavaScriptEnabledSearchCustomURLString = sharedPreferences.getString("tor_javascript_enabled_search_custom_url", "");
         String defaultFontSizeString = sharedPreferences.getString("default_font_size", "100");
         swipeToRefreshEnabled = sharedPreferences.getBoolean("swipe_to_refresh_enabled", false);
         adBlockerEnabled = sharedPreferences.getBoolean("block_ads", true);
         boolean doNotTrackEnabled = sharedPreferences.getBoolean("do_not_track", false);
-        boolean proxyThroughOrbot = sharedPreferences.getBoolean("proxy_through_orbot", false);
+        proxyThroughOrbot = sharedPreferences.getBoolean("proxy_through_orbot", false);
         fullScreenBrowsingModeEnabled = sharedPreferences.getBoolean("enable_full_screen_browsing_mode", false);
         hideSystemBarsOnFullscreen = sharedPreferences.getBoolean("hide_system_bars", false);
         translucentNavigationBarOnFullscreen = sharedPreferences.getBoolean("translucent_navigation_bar", true);
@@ -1786,8 +1859,50 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
             }
         }
 
-        // Apply the other settings from `sharedPreferences`.
-        homepage = homepageString;
+        // Set the homepage, search, and proxy options.
+        if (proxyThroughOrbot) {  // Set the Tor options.
+            // Set `torHomepageString` as `homepage`.
+            homepage = torHomepageString;
+
+            // Set JavaScript disabled search.
+            if (torJavaScriptDisabledSearchString.equals("Custom URL")) {  // Get the custom URL string.
+                javaScriptDisabledSearchURL = torJavaScriptDisabledSearchCustomURLString;
+            } else {  // Use the string from the pre-built list.
+                javaScriptDisabledSearchURL = torJavaScriptDisabledSearchString;
+            }
+
+            // Set JavaScript enabled search.
+            if (torJavaScriptEnabledSearchString.equals("Custom URL")) {  // Get the custom URL string.
+                javaScriptEnabledSearchURL = torJavaScriptEnabledSearchCustomURLString;
+            } else {  // Use the string from the pre-built list.
+                javaScriptEnabledSearchURL = torJavaScriptEnabledSearchString;
+            }
+
+            // Set the proxy.  `this` refers to the current activity where an `AlertDialog` might be displayed.
+            OrbotProxyHelper.setProxy(getApplicationContext(), this, "localhost", "8118");
+        } else {  // Set the non-Tor options.
+            // Set `homepageString` as `homepage`.
+            homepage = homepageString;
+
+            // Set JavaScript disabled search.
+            if (javaScriptDisabledSearchString.equals("Custom URL")) {  // Get the custom URL string.
+                javaScriptDisabledSearchURL = javaScriptDisabledSearchCustomURLString;
+            } else {  // Use the string from the pre-built list.
+                javaScriptDisabledSearchURL = javaScriptDisabledSearchString;
+            }
+
+            // Set JavaScript enabled search.
+            if (javaScriptEnabledSearchString.equals("Custom URL")) {  // Get the custom URL string.
+                javaScriptEnabledSearchURL = javaScriptEnabledSearchCustomURLString;
+            } else {  // Use the string from the pre-built list.
+                javaScriptEnabledSearchURL = javaScriptEnabledSearchString;
+            }
+
+            // Reset the proxy to default.  The host is `""` and the port is `"0"`.
+            OrbotProxyHelper.setProxy(getApplicationContext(), this, "", "0");
+        }
+
+        // Set swipe to refresh.
         swipeRefreshLayout.setEnabled(swipeToRefreshEnabled);
 
         // Set the user agent initial status.
@@ -1808,20 +1923,6 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
                 break;
         }
 
-        // Set JavaScript disabled search.
-        if (javaScriptDisabledSearchString.equals("Custom URL")) {  // Get the custom URL string.
-            javaScriptDisabledSearchURL = javaScriptDisabledCustomSearchString;
-        } else {  // Use the string from the pre-built list.
-            javaScriptDisabledSearchURL = javaScriptDisabledSearchString;
-        }
-
-        // Set JavaScript enabled search.
-        if (javaScriptEnabledSearchString.equals("Custom URL")) {  // Get the custom URL string.
-            javaScriptEnabledSearchURL = javaScriptEnabledCustomSearchString;
-        } else {  // Use the string from the pre-built list.
-            javaScriptEnabledSearchURL = javaScriptEnabledSearchString;
-        }
-
         // Set Do Not Track status.
         if (doNotTrackEnabled) {
             customHeaders.put("DNT", "1");
@@ -1829,14 +1930,6 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
             customHeaders.remove("DNT");
         }
 
-        // Set Orbot proxy status.
-        if (proxyThroughOrbot) {
-            // Set the proxy.  `this` refers to the current activity where an `AlertDialog` might be displayed.
-            OrbotProxyHelper.setProxy(getApplicationContext(), this, "localhost", "8118");
-        } else {  // Reset the proxy to default.  The host is `""` and the port is `"0"`.
-            OrbotProxyHelper.setProxy(getApplicationContext(), this, "", "0");
-        }
-
         // If we are in full screen mode update the `SYSTEM_UI` flags.
         if (inFullScreenBrowsingMode) {
             if (hideSystemBarsOnFullscreen) {  // Hide everything.
@@ -1867,6 +1960,14 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN
                 }
             }
         }
+
+        if (proxyThroughOrbot & !orbotStatus.equals("ON")) {  // We are waiting on Orbot.
+            // Save `formattedUrlString` in `pendingUrl`.
+            pendingUrl = formattedUrlString;
+
+            // Load a waiting page.  `null` specifies no encoding, which defaults to ASCII.
+            mainWebView.loadData("<html><body><br/><center><h1>Waiting for Orbot to connect...</h1></center></body></html>", "text/html", null);
+        }
     }
 
     private void updatePrivacyIcons(boolean runInvalidateOptionsMenu) {