X-Git-Url: https://gitweb.stoutner.com/?p=PrivacyBrowserAndroid.git;a=blobdiff_plain;f=app%2Fsrc%2Fmain%2Fjava%2Fcom%2Fstoutner%2Fprivacybrowser%2Factivities%2FMainWebViewActivity.java;h=1ee31db40a03cb8dfe9996eacfeaa79140aa230e;hp=a7cbffb53280f5ee365ef22be77fdd4b17e17cb5;hb=ff3641c1e0edbe729f4e09b804081d35185976e3;hpb=f3a2827543d388de53b27a124663c5f84af764c9 diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java index a7cbffb5..1ee31db4 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java @@ -190,9 +190,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook WebViewTabFragment.NewTabListener { // Define the public static variables. - public static ExecutorService executorService = Executors.newFixedThreadPool(4); + public static final ExecutorService executorService = Executors.newFixedThreadPool(4); public static String orbotStatus = "unknown"; - public static ArrayList pendingDialogsArrayList = new ArrayList<>(); + public static final ArrayList pendingDialogsArrayList = new ArrayList<>(); public static String proxyMode = ProxyHelper.NONE; // Declare the public static variables. @@ -370,7 +370,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook private Activity resultLauncherActivityHandle; // Define the save URL activity result launcher. It must be defined before `onCreate()` is run or the app will crash. - private final ActivityResultLauncher saveUrlActivityResultLauncher = registerForActivityResult(new ActivityResultContracts.CreateDocument("text/*"), + private final ActivityResultLauncher saveUrlActivityResultLauncher = registerForActivityResult(new ActivityResultContracts.CreateDocument("*/*"), new ActivityResultCallback() { @Override public void onActivityResult(Uri fileUri) { @@ -391,11 +391,30 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook public void onActivityResult(Uri fileUri) { // Only save the webpage archive if the file URI is not null, which happens if the user exited the file picker by pressing back. if (fileUri != null) { + // Initialize the file name string from the file URI last path segment. + String temporaryFileNameString = fileUri.getLastPathSegment(); + + // Query the exact file name if the API >= 26. + if (Build.VERSION.SDK_INT >= 26) { + // Get a cursor from the content resolver. + Cursor contentResolverCursor = resultLauncherActivityHandle.getContentResolver().query(fileUri, null, null, null); + + // Move to the fist row. + contentResolverCursor.moveToFirst(); + + // Get the file name from the cursor. + temporaryFileNameString = contentResolverCursor.getString(contentResolverCursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME)); + + // Close the cursor. + contentResolverCursor.close(); + } + + // Save the final file name string so it can be used inside the lambdas. This will no longer be needed once this activity has transitioned to Kotlin. + String finalFileNameString = temporaryFileNameString; + try { // Create a temporary MHT file. File temporaryMhtFile = File.createTempFile("temporary_mht_file", ".mht", getCacheDir()); - - // Save the temporary MHT file. currentWebView.saveWebArchive(temporaryMhtFile.toString(), false, callbackValue -> { if (callbackValue != null) { // The temporary MHT file was saved successfully. try { @@ -420,29 +439,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook mhtOutputStream.close(); temporaryMhtFileInputStream.close(); - // Initialize the file name string from the file URI last path segment. - String fileNameString = fileUri.getLastPathSegment(); - - // Query the exact file name if the API >= 26. - if (Build.VERSION.SDK_INT >= 26) { - // Get a cursor from the content resolver. - Cursor contentResolverCursor = resultLauncherActivityHandle.getContentResolver().query(fileUri, null, null, null); - - // Move to the fist row. - contentResolverCursor.moveToFirst(); - - // Get the file name from the cursor. - fileNameString = contentResolverCursor.getString(contentResolverCursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME)); - - // Close the cursor. - contentResolverCursor.close(); - } - // Display a snackbar. - Snackbar.make(currentWebView, getString(R.string.file_saved) + " " + fileNameString, Snackbar.LENGTH_SHORT).show(); + Snackbar.make(currentWebView, getString(R.string.saved, finalFileNameString), Snackbar.LENGTH_SHORT).show(); } catch (Exception exception) { // Display a snackbar with the exception. - Snackbar.make(currentWebView, getString(R.string.error_saving_file) + " " + exception, Snackbar.LENGTH_INDEFINITE).show(); + Snackbar.make(currentWebView, getString(R.string.error_saving_file, finalFileNameString, exception), Snackbar.LENGTH_INDEFINITE).show(); } finally { // Delete the temporary MHT file. //noinspection ResultOfMethodCallIgnored @@ -450,12 +451,12 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook } } else { // There was an unspecified error while saving the temporary MHT file. // Display an error snackbar. - Snackbar.make(currentWebView, getString(R.string.error_saving_file), Snackbar.LENGTH_INDEFINITE).show(); + Snackbar.make(currentWebView, getString(R.string.error_saving_file, finalFileNameString, getString(R.string.unknown_error)), Snackbar.LENGTH_INDEFINITE).show(); } }); } catch (IOException ioException) { // Display a snackbar with the IO exception. - Snackbar.make(currentWebView, getString(R.string.error_saving_file) + " " + ioException, Snackbar.LENGTH_INDEFINITE).show(); + Snackbar.make(currentWebView, getString(R.string.error_saving_file, finalFileNameString, ioException), Snackbar.LENGTH_INDEFINITE).show(); } } } @@ -589,6 +590,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Initially disable the sliding drawers. They will be enabled once the blocklists are loaded. drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED); + // Initially hide the user interface so that only the blocklist loading screen is shown (if reloading). + drawerLayout.setVisibility(View.GONE); + // Initialize the web view pager adapter. webViewPagerAdapter = new WebViewPagerAdapter(getSupportFragmentManager()); @@ -2233,6 +2237,15 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Make it so. startActivity(logcatIntent); + } else if (menuItemId == R.id.webview_devtools) { // WebView Dev. + // Create a WebView DevTools intent. + Intent webViewDevToolsIntent = new Intent("com.android.webview.SHOW_DEV_UI"); + + // Launch as a new task so that the WebView DevTools and Privacy Browser show as a separate windows in the recent tasks list. + webViewDevToolsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + + // Make it so. + startActivity(webViewDevToolsIntent); } else if (menuItemId == R.id.guide) { // Guide. // Create an intent to launch the guide activity. Intent guideIntent = new Intent(this, GuideActivity.class); @@ -2712,7 +2725,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Update the bookmarks cursor with the current contents of this folder. bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrder(currentBookmarksFolder); - // Update the `ListView`. + // Update the list view. bookmarksCursorAdapter.changeCursor(bookmarksCursor); // Scroll to the new folder. @@ -2806,7 +2819,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Update the bookmarks cursor with the current contents of this folder. bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrder(currentBookmarksFolder); - // Update the `ListView`. + // Update the list view. bookmarksCursorAdapter.changeCursor(bookmarksCursor); } @@ -3106,19 +3119,10 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Remove the lint warning below that the input method manager might be null. assert inputMethodManager != null; - // Initialize the gray foreground color spans for highlighting the URLs. + // Initialize the color spans for highlighting the URLs. initialGrayColorSpan = new ForegroundColorSpan(getColor(R.color.gray_500)); finalGrayColorSpan = new ForegroundColorSpan(getColor(R.color.gray_500)); - - // Get the current theme status. - int currentThemeStatus = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK; - - // Set the red color span according to the theme. - if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) { - redColorSpan = new ForegroundColorSpan(getColor(R.color.red_a700)); - } else { - redColorSpan = new ForegroundColorSpan(getColor(R.color.red_900)); - } + redColorSpan = new ForegroundColorSpan(getColor(R.color.red_text)); // Remove the formatting from the URL edit text when the user is editing the text. urlEditText.setOnFocusChangeListener((View v, boolean hasFocus) -> { @@ -3454,11 +3458,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Move the bookmark cursor to the first row. bookmarkCursor.moveToFirst(); - // Load the bookmark in a new tab but do not switch to the tab or close the drawer. - addNewTab(bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_URL)), false); + // Load the bookmark in a new tab. + addNewTab(bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_URL)), true); - // Display a snackbar. - Snackbar.make(drawerLayout, R.string.bookmark_opened_in_background, Snackbar.LENGTH_SHORT).show(); + // Close the bookmarks drawer. + drawerLayout.closeDrawer(GravityCompat.END); } // Consume the event. @@ -3797,7 +3801,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); // Store the general preference information. - boolean defaultXRequestedWithHeader = sharedPreferences.getBoolean(getString(R.string.x_requested_with_header_key), true); String defaultFontSizeString = sharedPreferences.getString(getString(R.string.font_size_key), getString(R.string.font_size_default_value)); String defaultUserAgentName = sharedPreferences.getString(getString(R.string.user_agent_key), getString(R.string.user_agent_default_value)); boolean defaultSwipeToRefresh = sharedPreferences.getBoolean(getString(R.string.swipe_to_refresh_key), true); @@ -3843,7 +3846,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook nestedScrollWebView.setBlockAllThirdPartyRequests(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow( DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)) == 1); String userAgentName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.USER_AGENT)); - int xRequestedWithHeaderInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.X_REQUESTED_WITH_HEADER)); int fontSize = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.FONT_SIZE)); int swipeToRefreshInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SWIPE_TO_REFRESH)); int webViewThemeInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.WEBVIEW_THEME)); @@ -3883,24 +3885,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook nestedScrollWebView.getSettings().setSaveFormData(saveFormData); } - // Set the X-Requested-With header. - switch (xRequestedWithHeaderInt) { - case DomainsDatabaseHelper.SYSTEM_DEFAULT: - if (defaultXRequestedWithHeader) - nestedScrollWebView.setXRequestedWithHeader(); - else - nestedScrollWebView.resetXRequestedWithHeader(); - break; - - case DomainsDatabaseHelper.ENABLED: - nestedScrollWebView.setXRequestedWithHeader(); - break; - - case DomainsDatabaseHelper.DISABLED: - nestedScrollWebView.resetXRequestedWithHeader(); - break; - } - // Apply the font size. try { // Try the specified font size to see if it is valid. if (fontSize == 0) { // Apply the default font size. @@ -4131,12 +4115,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook nestedScrollWebView.getSettings().setSaveFormData(saveFormData); } - // Store the X-Requested-With header status in the nested scroll WebView. - if (defaultXRequestedWithHeader) - nestedScrollWebView.setXRequestedWithHeader(); - else - nestedScrollWebView.resetXRequestedWithHeader(); - // Store the swipe to refresh status in the nested scroll WebView. nestedScrollWebView.setSwipeToRefresh(defaultSwipeToRefresh); @@ -4244,7 +4222,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Load the URL if directed. This makes sure that the domain settings are properly loaded before the URL. By using `loadUrl()`, instead of `loadUrlFromBase()`, the Referer header will never be sent. if (loadUrl) { - nestedScrollWebView.loadUrl(url, nestedScrollWebView.getXRequestedWithHeader()); + nestedScrollWebView.loadUrl(url); } } @@ -4335,27 +4313,31 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook } else { appBarLayout.setBackgroundResource(R.color.dark_blue_30); } + // Get the package manager. + PackageManager packageManager = getPackageManager(); // Check to see if I2P is installed. try { - // Get the package manager. - PackageManager packageManager = getPackageManager(); - - // Check to see if I2P is in the list. This will throw an error and drop to the catch section if it isn't installed. + // Check to see if the F-Droid flavor is installed. This will throw an error and drop to the catch section if it isn't installed. packageManager.getPackageInfo("net.i2p.android.router", 0); - } catch (PackageManager.NameNotFoundException exception) { // I2P is not installed. - // Sow the I2P not installed dialog if it is not already displayed. - if (getSupportFragmentManager().findFragmentByTag(getString(R.string.proxy_not_installed_dialog)) == null) { - // Get a handle for the waiting for proxy alert dialog. - DialogFragment i2pNotInstalledDialogFragment = ProxyNotInstalledDialog.displayDialog(proxyMode); + } catch (PackageManager.NameNotFoundException fdroidException) { // The F-Droid flavor is not installed. + try { + // Check to see if the Google Play flavor is installed. This will throw an error and drop to the catch section if it isn't installed. + packageManager.getPackageInfo("net.i2p.android", 0); + } catch (PackageManager.NameNotFoundException googlePlayException) { // The Google Play flavor is not installed. + // Sow the I2P not installed dialog if it is not already displayed. + if (getSupportFragmentManager().findFragmentByTag(getString(R.string.proxy_not_installed_dialog)) == null) { + // Get a handle for the waiting for proxy alert dialog. + DialogFragment i2pNotInstalledDialogFragment = ProxyNotInstalledDialog.displayDialog(proxyMode); - // Try to show the dialog. Sometimes the window is not yet active if returning from Settings. - try { - // Display the I2P not installed alert dialog. - i2pNotInstalledDialogFragment.show(getSupportFragmentManager(), getString(R.string.proxy_not_installed_dialog)); - } catch (Exception i2pNotInstalledException) { - // Add the dialog to the pending dialog array list. It will be displayed in `onStart()`. - pendingDialogsArrayList.add(new PendingDialog(i2pNotInstalledDialogFragment, getString(R.string.proxy_not_installed_dialog))); + // Try to show the dialog. Sometimes the window is not yet active if returning from Settings. + try { + // Display the I2P not installed alert dialog. + i2pNotInstalledDialogFragment.show(getSupportFragmentManager(), getString(R.string.proxy_not_installed_dialog)); + } catch (Exception i2pNotInstalledException) { + // Add the dialog to the pending dialog array list. It will be displayed in `onStart()`. + pendingDialogsArrayList.add(new PendingDialog(i2pNotInstalledDialogFragment, getString(R.string.proxy_not_installed_dialog))); + } } } }