]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blobdiff - app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java
Allow uploading of files on API >= 21. Fixes https://redmine.stoutner.com/issues/1
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / activities / MainWebViewActivity.java
index 0e81bf4fd4dc03f03ca2d56085ae976885255bcd..0bf8d0d6e0929f9cc7efbe4e1fb468b54dba7f96 100644 (file)
@@ -88,6 +88,7 @@ import android.view.inputmethod.InputMethodManager;
 import android.webkit.CookieManager;
 import android.webkit.HttpAuthHandler;
 import android.webkit.SslErrorHandler;
+import android.webkit.ValueCallback;
 import android.webkit.WebBackForwardList;
 import android.webkit.WebChromeClient;
 import android.webkit.WebResourceResponse;
@@ -109,7 +110,6 @@ import android.widget.TextView;
 import com.stoutner.privacybrowser.BannerAd;
 import com.stoutner.privacybrowser.BuildConfig;
 import com.stoutner.privacybrowser.R;
-import com.stoutner.privacybrowser.dialogs.AddDomainDialog;
 import com.stoutner.privacybrowser.dialogs.CreateBookmarkDialog;
 import com.stoutner.privacybrowser.dialogs.CreateBookmarkFolderDialog;
 import com.stoutner.privacybrowser.dialogs.CreateHomeScreenShortcutDialog;
@@ -146,11 +146,11 @@ import java.util.Map;
 import java.util.Set;
 
 // AppCompatActivity from android.support.v7.app.AppCompatActivity must be used to have access to the SupportActionBar until the minimum API is >= 21.
-public class MainWebViewActivity extends AppCompatActivity implements AddDomainDialog.AddDomainListener, CreateBookmarkDialog.CreateBookmarkListener,
-        CreateBookmarkFolderDialog.CreateBookmarkFolderListener, CreateHomeScreenShortcutDialog.CreateHomeScreenSchortcutListener, DownloadFileDialog.DownloadFileListener,
-        DownloadImageDialog.DownloadImageListener, DownloadLocationPermissionDialog.DownloadLocationPermissionDialogListener, EditBookmarkDialog.EditBookmarkListener,
-        EditBookmarkFolderDialog.EditBookmarkFolderListener, HttpAuthenticationDialog.HttpAuthenticationListener, NavigationView.OnNavigationItemSelectedListener,
-        PinnedSslCertificateMismatchDialog.PinnedSslCertificateMismatchListener, SslCertificateErrorDialog.SslCertificateErrorListener, UrlHistoryDialog.UrlHistoryListener {
+public class MainWebViewActivity extends AppCompatActivity implements CreateBookmarkDialog.CreateBookmarkListener, CreateBookmarkFolderDialog.CreateBookmarkFolderListener,
+        CreateHomeScreenShortcutDialog.CreateHomeScreenSchortcutListener, DownloadFileDialog.DownloadFileListener, DownloadImageDialog.DownloadImageListener,
+        DownloadLocationPermissionDialog.DownloadLocationPermissionDialogListener, EditBookmarkDialog.EditBookmarkListener, EditBookmarkFolderDialog.EditBookmarkFolderListener,
+        HttpAuthenticationDialog.HttpAuthenticationListener, NavigationView.OnNavigationItemSelectedListener, PinnedSslCertificateMismatchDialog.PinnedSslCertificateMismatchListener,
+        SslCertificateErrorDialog.SslCertificateErrorListener, UrlHistoryDialog.UrlHistoryListener {
 
     // `darkTheme` is public static so it can be accessed from `AboutActivity`, `GuideActivity`, `AddDomainDialog`, `SettingsActivity`, `DomainsActivity`, `DomainsListFragment`, `BookmarksActivity`,
     // `BookmarksDatabaseViewActivity`, `CreateBookmarkDialog`, `CreateBookmarkFolderDialog`, `DownloadFileDialog`, `DownloadImageDialog`, `EditBookmarkDialog`, `EditBookmarkFolderDialog`,
@@ -289,6 +289,9 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD
     // `privacyBrowserRuntime` is used in `onCreate()`, `onOptionsItemSelected()`, and `applyAppSettings()`.
     private Runtime privacyBrowserRuntime;
 
+    // `proxyThroughOrbot` is used in `onRestart()` and `applyAppSettings()`.
+    boolean proxyThroughOrbot;
+
     // `incognitoModeEnabled` is used in `onCreate()` and `applyAppSettings()`.
     private boolean incognitoModeEnabled;
 
@@ -396,6 +399,9 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD
     // `oldFolderNameString` is used in `onCreate()` and `onSaveEditBookmarkFolder()`.
     private String oldFolderNameString;
 
+    // `fileChooserCallback` is used in `onCreate()` and `onActivityResult()`.
+    private ValueCallback<Uri[]> fileChooserCallback;
+
     // The download strings are used in `onCreate()` and `onRequestPermissionResult()`.
     private String downloadUrl;
     private String downloadContentDisposition;
@@ -904,7 +910,7 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD
                 webViewTitle = title;
             }
 
-            // Enter full screen video
+            // Enter full screen video.
             @Override
             public void onShowCustomView(View view, CustomViewCallback callback) {
                 // Pause the ad if this is the free flavor.
@@ -932,7 +938,8 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD
                 fullScreenVideoFrameLayout.setVisibility(View.VISIBLE);
             }
 
-            // Exit full screen video
+            // Exit full screen video.
+            @Override
             public void onHideCustomView() {
                 // Hide `fullScreenVideoFrameLayout`.
                 fullScreenVideoFrameLayout.removeAllViews();
@@ -953,6 +960,23 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD
                     adView = findViewById(R.id.adview);
                 }
             }
+
+            // Upload files.
+            @Override
+            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
+                // Show the file chooser if the device is running API >= 21.
+                if (Build.VERSION.SDK_INT >= 21) {
+                    // Store the file path callback.
+                    fileChooserCallback = filePathCallback;
+
+                    // Create an intent to open a chooser based ont the file chooser parameters.
+                    Intent fileChooserIntent = fileChooserParams.createIntent();
+
+                    // Open the file chooser.  Currently only one `startActivityForResult` exists in this activity, so the request code, used to differentiate them, is simply `0`.
+                    startActivityForResult(fileChooserIntent, 0);
+                }
+                return true;
+            }
         });
 
         // Register `mainWebView` for a context menu.  This is used to see link targets and download images.
@@ -1247,11 +1271,12 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD
 
                     // Manually delete cache folders.
                     try {
-                        // Delete the main `cache` folder.
+                        // Delete the main cache directory.
                         privacyBrowserRuntime.exec("rm -rf " + privateDataDirectoryString + "/cache");
 
-                        // Delete the `app_webview` folder, which contains an additional `WebView` cache.  See `https://code.google.com/p/android/issues/detail?id=233826&thanks=233826&ts=1486670530`.
-                        privacyBrowserRuntime.exec("rm -rf " + privateDataDirectoryString + "/app_webview");
+                        // Delete the secondary `Service Worker` cache directory.
+                        // A `String[]` must be used because the directory contains a space and `Runtime.exec` will not escape the string correctly otherwise.
+                        privacyBrowserRuntime.exec(new String[] {"rm", "-rf", privateDataDirectoryString + "/app_webview/Service Worker/"});
                     } catch (IOException e) {
                         // Do nothing if an error is thrown.
                     }
@@ -1429,6 +1454,18 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD
         // Run the default commands.
         super.onRestart();
 
+        // Make sure Orbot is running if Privacy Browser is proxying through Orbot.
+        if (proxyThroughOrbot) {
+            // Request Orbot to start.  If Orbot is already running no hard will be caused by this request.
+            Intent orbotIntent = new Intent("org.torproject.android.intent.action.START");
+
+            // Send the intent to the Orbot package.
+            orbotIntent.setPackage("org.torproject.android");
+
+            // Make it so.
+            sendBroadcast(orbotIntent);
+        }
+
         // Apply the app settings if returning from the Settings activity..
         if (reapplyAppSettingsOnRestart) {
             // Apply the app settings.
@@ -1702,15 +1739,36 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD
                     // Create an intent to launch the domains activity.
                     Intent domainsIntent = new Intent(this, DomainsActivity.class);
 
-                    // Put extra information instructing the domains activity to directly load the current domain.
-                    domainsIntent.putExtra("LoadDomain", domainSettingsDatabaseId);
+                    // Put extra information instructing the domains activity to directly load the current domain and close on back instread of returning to the domains list.
+                    domainsIntent.putExtra("loadDomain", domainSettingsDatabaseId);
+                    domainsIntent.putExtra("closeOnBack", true);
 
                     // Make it so.
                     startActivity(domainsIntent);
                 } else {  // Add a new domain.
-                    // Show the add domain `AlertDialog`.
-                    AppCompatDialogFragment addDomainDialog = new AddDomainDialog();
-                    addDomainDialog.show(getSupportFragmentManager(), getResources().getString(R.string.add_domain));
+                    // Apply the new domain settings on returning to `MainWebViewActivity`.
+                    reapplyDomainSettingsOnRestart = true;
+                    currentDomainName = "";
+
+                    // Get the current domain
+                    Uri currentUri = Uri.parse(formattedUrlString);
+                    String currentDomain = currentUri.getHost();
+
+                    // Initialize the database handler.  The `0` specifies the database version, but that is ignored and set instead using a constant in `DomainsDatabaseHelper`.
+                    DomainsDatabaseHelper domainsDatabaseHelper = new DomainsDatabaseHelper(this, null, null, 0);
+
+                    // Create the domain and store the database ID.
+                    int newDomainDatabaseId = domainsDatabaseHelper.addDomain(currentDomain);
+
+                    // Create an intent to launch the domains activity.
+                    Intent domainsIntent = new Intent(this, DomainsActivity.class);
+
+                    // Put extra information instructing the domains activity to directly load the new domain and close on back instead of returning to the domains list.
+                    domainsIntent.putExtra("loadDomain", newDomainDatabaseId);
+                    domainsIntent.putExtra("closeOnBack", true);
+
+                    // Make it so.
+                    startActivity(domainsIntent);
                 }
                 return true;
 
@@ -2196,8 +2254,9 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD
                     try {
                         // Delete the main cache directory.
                         privacyBrowserRuntime.exec("rm -rf " + privateDataDirectoryString + "/cache");
+
                         // Delete the secondary `Service Worker` cache directory.
-                        // We have to use a `String[]` because the directory contains a space and `Runtime.exec` will not escape the string correctly otherwise.
+                        // A `String[]` must be used because the directory contains a space and `Runtime.exec` will not escape the string correctly otherwise.
                         privacyBrowserRuntime.exec(new String[] {"rm", "-rf", privateDataDirectoryString + "/app_webview/Service Worker/"});
                     } catch (IOException e) {
                         // Do nothing if an error is thrown.
@@ -2475,33 +2534,6 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD
         }
     }
 
-    @Override
-    public void onAddDomain(AppCompatDialogFragment dialogFragment) {
-        // Reapply the domain settings on returning to `MainWebViewActivity`.
-        reapplyDomainSettingsOnRestart = true;
-        currentDomainName = "";
-
-        // Get the new domain name `String` from `dialogFragment`.
-        EditText domainNameEditText = dialogFragment.getDialog().findViewById(R.id.domain_name_edittext);
-        String domainNameString = domainNameEditText.getText().toString();
-
-        // Initialize the database handler.  `this` specifies the context.  The two `nulls` do not specify the database name or a `CursorFactory`.
-        // The `0` specifies the database version, but that is ignored and set instead using a constant in `DomainsDatabaseHelper`.
-        DomainsDatabaseHelper domainsDatabaseHelper = new DomainsDatabaseHelper(this, null, null, 0);
-
-        // Create the domain and store the database ID in `currentDomainDatabaseId`.
-        int newDomainDatabaseId = domainsDatabaseHelper.addDomain(domainNameString);
-
-        // Create an intent to launch the domains activity.
-        Intent domainsIntent = new Intent(this, DomainsActivity.class);
-
-        // Put extra information instructing the domains activity to directly load the current domain.
-        domainsIntent.putExtra("LoadDomain", newDomainDatabaseId);
-
-        // Make it so.
-        startActivity(domainsIntent);
-    }
-
     @Override
     public void onCreateBookmark(AppCompatDialogFragment dialogFragment) {
         // Get the `EditTexts` from the `dialogFragment`.
@@ -2950,6 +2982,16 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD
         }
     }
 
+    // Process the results of an upload file chooser.  Currently there is only one `startActivityForResult` in this activity, so the request code, used to differentiate them, is ignored.
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        // File uploads only work on API >= 21.
+        if (Build.VERSION.SDK_INT >= 21) {
+            // Pass the file to the WebView.
+            fileChooserCallback.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data));
+        }
+    }
+
     private void loadUrlFromTextBox() throws UnsupportedEncodingException {
         // Get the text from urlTextBox and convert it to a string.  trim() removes white spaces from the beginning and end of the string.
         String unformattedUrlString = urlTextBox.getText().toString().trim();
@@ -3050,7 +3092,7 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD
         String searchCustomURLString = sharedPreferences.getString("search_custom_url", "");
         incognitoModeEnabled = sharedPreferences.getBoolean("incognito_mode", false);
         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("full_screen_browsing_mode", false);
         hideSystemBarsOnFullscreen = sharedPreferences.getBoolean("hide_system_bars", false);
         translucentNavigationBarOnFullscreen = sharedPreferences.getBoolean("translucent_navigation_bar", true);