import android.net.Uri;
import android.net.http.SslCertificate;
import android.net.http.SslError;
-import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import com.stoutner.privacybrowser.R;
import com.stoutner.privacybrowser.adapters.WebViewPagerAdapter;
-import com.stoutner.privacybrowser.asynctasks.GetHostIpAddresses;
-import com.stoutner.privacybrowser.asynctasks.PopulateBlocklists;
-import com.stoutner.privacybrowser.asynctasks.PrepareSaveDialog;
import com.stoutner.privacybrowser.asynctasks.SaveUrl;
import com.stoutner.privacybrowser.asynctasks.SaveWebpageImage;
-import com.stoutner.privacybrowser.dataclasses.PendingDialog;
+import com.stoutner.privacybrowser.coroutines.GetHostIpAddressesCoroutine;
+import com.stoutner.privacybrowser.coroutines.PopulateBlocklistsCoroutine;
+import com.stoutner.privacybrowser.coroutines.PrepareSaveDialogCoroutine;
+import com.stoutner.privacybrowser.dataclasses.PendingDialogDataClass;
import com.stoutner.privacybrowser.dialogs.CreateBookmarkDialog;
import com.stoutner.privacybrowser.dialogs.CreateBookmarkFolderDialog;
import com.stoutner.privacybrowser.dialogs.CreateHomeScreenShortcutDialog;
public class MainWebViewActivity extends AppCompatActivity implements CreateBookmarkDialog.CreateBookmarkListener, CreateBookmarkFolderDialog.CreateBookmarkFolderListener,
FontSizeDialog.UpdateFontSizeListener, NavigationView.OnNavigationItemSelectedListener, OpenDialog.OpenListener, PinnedMismatchDialog.PinnedMismatchListener,
- PopulateBlocklists.PopulateBlocklistsListener, SaveDialog.SaveListener, UrlHistoryDialog.NavigateHistoryListener, WebViewTabFragment.NewTabListener {
+ PopulateBlocklistsCoroutine.PopulateBlocklistsListener, SaveDialog.SaveListener, UrlHistoryDialog.NavigateHistoryListener, WebViewTabFragment.NewTabListener {
// Define the public static variables.
public static final ExecutorService executorService = Executors.newFixedThreadPool(4);
public static String orbotStatus = "unknown";
- public static final ArrayList<PendingDialog> pendingDialogsArrayList = new ArrayList<>();
+ public static final ArrayList<PendingDialogDataClass> pendingDialogsArrayList = new ArrayList<>();
public static String proxyMode = ProxyHelper.NONE;
// Declare the public static variables.
private int savedTabPosition;
private String savedProxyMode;
- // Define the class variables.
- @SuppressWarnings("rawtypes")
- AsyncTask populateBlocklists;
-
// The current WebView is used in `onCreate()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, `onNavigationItemSelected()`, `onRestart()`, `onCreateContextMenu()`, `findPreviousOnPage()`,
// `findNextOnPage()`, `closeFindOnPage()`, `loadUrlFromTextBox()`, `onSslMismatchBack()`, `applyProxy()`, and `applyDomainSettings()`.
private NestedScrollWebView currentWebView;
} else if (displayingFullScreenVideo) { // A full screen video is shown.
// Exit the full screen video.
exitFullScreenVideo();
- } else if (currentWebView.canGoBack()) { // There is at least one item in the current WebView history.
+ // It shouldn't be possible for the currentWebView to be null, but crash logs indicate it sometimes happens.
+ } else if ((currentWebView != null) && (currentWebView.canGoBack())) { // There is at least one item in the current WebView history.
// Get the current web back forward list.
WebBackForwardList webBackForwardList = currentWebView.copyBackForwardList();
// Register the on back pressed callback.
getOnBackPressedDispatcher().addCallback(this, onBackPressedCallback);
+ // Instantiate the populate blocklists coroutine.
+ PopulateBlocklistsCoroutine populateBlocklistsCoroutine = new PopulateBlocklistsCoroutine(this);
+
// Populate the blocklists.
- populateBlocklists = new PopulateBlocklists(this, this).execute();
+ populateBlocklistsCoroutine.populateBlocklists(this);
}
@Override
// Show any pending dialogs.
for (int i = 0; i < pendingDialogsArrayList.size(); i++) {
// Get the pending dialog from the array list.
- PendingDialog pendingDialog = pendingDialogsArrayList.get(i);
+ PendingDialogDataClass pendingDialogDataClass = pendingDialogsArrayList.get(i);
// Show the pending dialog.
- pendingDialog.dialogFragment.show(getSupportFragmentManager(), pendingDialog.tag);
+ pendingDialogDataClass.dialogFragment.show(getSupportFragmentManager(), pendingDialogDataClass.tag);
}
// Clear the pending dialogs array list.
bookmarksDatabaseHelper.close();
}
- // Stop populating the blocklists if the AsyncTask is running in the background.
- if (populateBlocklists != null) {
- populateBlocklists.cancel(true);
- }
-
// Run the default commands.
super.onDestroy();
}
downloadUrlWithExternalApp(currentWebView.getCurrentUrl());
} else { // Handle the download inside of Privacy Browser.
// Prepare the save dialog. The dialog will be displayed once the file size and the content disposition have been acquired.
- new PrepareSaveDialog(this, this, getSupportFragmentManager(), currentWebView.getSettings().getUserAgentString(),
- currentWebView.getAcceptCookies()).execute(currentWebView.getCurrentUrl());
+ PrepareSaveDialogCoroutine.prepareSaveDialog(this, getSupportFragmentManager(), currentWebView.getCurrentUrl(), currentWebView.getSettings().getUserAgentString(),
+ currentWebView.getAcceptCookies());
}
// Consume the event.
} else if (menuItemId == R.id.add_to_homescreen) { // Add to homescreen.
// Instantiate the create home screen shortcut dialog.
DialogFragment createHomeScreenShortcutDialogFragment = CreateHomeScreenShortcutDialog.createDialog(currentWebView.getTitle(), currentWebView.getUrl(),
- currentWebView.getFavoriteOrDefaultIcon());
+ currentWebView.getFavoriteIcon());
// Show the create home screen shortcut dialog.
createHomeScreenShortcutDialogFragment.show(getSupportFragmentManager(), getString(R.string.create_shortcut));
downloadUrlWithExternalApp(linkUrl);
} else { // Handle the download inside of Privacy Browser.
// Prepare the save dialog. The dialog will be displayed once the file size and the content disposition have been acquired.
- new PrepareSaveDialog(this, this, getSupportFragmentManager(), currentWebView.getSettings().getUserAgentString(),
- currentWebView.getAcceptCookies()).execute(linkUrl);
+ PrepareSaveDialogCoroutine.prepareSaveDialog(this, getSupportFragmentManager(), linkUrl, currentWebView.getSettings().getUserAgentString(), currentWebView.getAcceptCookies());
}
// Consume the event.
downloadUrlWithExternalApp(imageUrl);
} else { // Handle the download inside of Privacy Browser.
// Prepare the save dialog. The dialog will be displayed once the file size and the content disposition have been acquired.
- new PrepareSaveDialog(this, this, getSupportFragmentManager(), currentWebView.getSettings().getUserAgentString(),
- currentWebView.getAcceptCookies()).execute(imageUrl);
+ PrepareSaveDialogCoroutine.prepareSaveDialog(this, getSupportFragmentManager(), imageUrl, currentWebView.getSettings().getUserAgentString(), currentWebView.getAcceptCookies());
}
// Consume the event.
downloadUrlWithExternalApp(imageUrl);
} else { // Handle the download inside of Privacy Browser.
// Prepare the save dialog. The dialog will be displayed once the file size and the content disposition have been acquired.
- new PrepareSaveDialog(this, this, getSupportFragmentManager(), currentWebView.getSettings().getUserAgentString(),
- currentWebView.getAcceptCookies()).execute(imageUrl);
+ PrepareSaveDialogCoroutine.prepareSaveDialog(this, getSupportFragmentManager(), imageUrl, currentWebView.getSettings().getUserAgentString(), currentWebView.getAcceptCookies());
}
// Consume the event.
downloadUrlWithExternalApp(linkUrl);
} else { // Handle the download inside of Privacy Browser.
// Prepare the save dialog. The dialog will be displayed once the file size and the content disposition have been acquired.
- new PrepareSaveDialog(this, this, getSupportFragmentManager(), currentWebView.getSettings().getUserAgentString(),
- currentWebView.getAcceptCookies()).execute(linkUrl);
+ PrepareSaveDialogCoroutine.prepareSaveDialog(this, getSupportFragmentManager(), linkUrl, currentWebView.getSettings().getUserAgentString(), currentWebView.getAcceptCookies());
}
// Consume the event.
@Override
public void onTabReselected(TabLayout.Tab tab) {
// Instantiate the View SSL Certificate dialog.
- DialogFragment viewSslCertificateDialogFragment = ViewSslCertificateDialog.displayDialog(currentWebView.getWebViewFragmentId(), currentWebView.getFavoriteOrDefaultIcon());
+ DialogFragment viewSslCertificateDialogFragment = ViewSslCertificateDialog.displayDialog(currentWebView.getWebViewFragmentId(), currentWebView.getFavoriteIcon());
// Display the View SSL Certificate dialog.
viewSslCertificateDialogFragment.show(getSupportFragmentManager(), getString(R.string.view_ssl_certificate));
// Set the launch bookmarks activity FAB to launch the bookmarks activity.
launchBookmarksActivityFab.setOnClickListener(v -> {
// Get a copy of the favorite icon bitmap.
- Bitmap favoriteIconBitmap = currentWebView.getFavoriteOrDefaultIcon();
+ Bitmap favoriteIconBitmap = currentWebView.getFavoriteIcon();
// Create a favorite icon byte array output stream.
ByteArrayOutputStream favoriteIconByteArrayOutputStream = new ByteArrayOutputStream();
// Set the create new bookmark folder FAB to display an alert dialog.
createBookmarkFolderFab.setOnClickListener(v -> {
// Create a create bookmark folder dialog.
- DialogFragment createBookmarkFolderDialog = CreateBookmarkFolderDialog.createBookmarkFolder(currentWebView.getFavoriteOrDefaultIcon());
+ DialogFragment createBookmarkFolderDialog = CreateBookmarkFolderDialog.createBookmarkFolder(currentWebView.getFavoriteIcon());
// Show the create bookmark folder dialog.
createBookmarkFolderDialog.show(getSupportFragmentManager(), getString(R.string.create_folder));
// Set the create new bookmark FAB to display an alert dialog.
createBookmarkFab.setOnClickListener(view -> {
// Instantiate the create bookmark dialog.
- DialogFragment createBookmarkDialog = CreateBookmarkDialog.createBookmark(currentWebView.getUrl(), currentWebView.getTitle(), currentWebView.getFavoriteOrDefaultIcon());
+ DialogFragment createBookmarkDialog = CreateBookmarkDialog.createBookmark(currentWebView.getUrl(), currentWebView.getTitle(), currentWebView.getFavoriteIcon());
// Display the create bookmark dialog.
createBookmarkDialog.show(getSupportFragmentManager(), getString(R.string.create_bookmark));
TextView tabTitleTextView = tabCustomView.findViewById(R.id.title_textview);
// Set the default favorite icon as the favorite icon for this tab.
- tabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(nestedScrollWebView.getFavoriteOrDefaultIcon(), 64, 64, true));
+ tabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(nestedScrollWebView.getFavoriteIcon(), 64, 64, true));
// Set the loading title text.
tabTitleTextView.setText(R.string.loading);
waitingForProxyDialogFragment.show(getSupportFragmentManager(), getString(R.string.waiting_for_proxy_dialog));
} catch (Exception waitingForTorException) {
// Add the dialog to the pending dialog array list. It will be displayed in `onStart()`.
- pendingDialogsArrayList.add(new PendingDialog(waitingForProxyDialogFragment, getString(R.string.waiting_for_proxy_dialog)));
+ pendingDialogsArrayList.add(new PendingDialogDataClass(waitingForProxyDialogFragment, getString(R.string.waiting_for_proxy_dialog)));
}
}
}
orbotNotInstalledDialogFragment.show(getSupportFragmentManager(), getString(R.string.proxy_not_installed_dialog));
} catch (Exception orbotNotInstalledException) {
// Add the dialog to the pending dialog array list. It will be displayed in `onStart()`.
- pendingDialogsArrayList.add(new PendingDialog(orbotNotInstalledDialogFragment, getString(R.string.proxy_not_installed_dialog)));
+ pendingDialogsArrayList.add(new PendingDialogDataClass(orbotNotInstalledDialogFragment, getString(R.string.proxy_not_installed_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)));
+ pendingDialogsArrayList.add(new PendingDialogDataClass(i2pNotInstalledDialogFragment, getString(R.string.proxy_not_installed_dialog)));
}
}
}
}
// Get the file name from the content disposition.
- String fileNameString = PrepareSaveDialog.getFileNameFromHeaders(this, contentDisposition, mimetype, downloadUrl);
+ String fileNameString = PrepareSaveDialogCoroutine.getFileNameFromHeaders(this, contentDisposition, mimetype, downloadUrl);
// Instantiate the save dialog.
DialogFragment saveDialogFragment = SaveDialog.saveUrl(downloadUrl, formattedFileSizeString, fileNameString, userAgent,
saveDialogFragment.show(getSupportFragmentManager(), getString(R.string.save_dialog));
} catch (Exception exception) { // The dialog could not be shown.
// Add the dialog to the pending dialog array list. It will be displayed in `onStart()`.
- pendingDialogsArrayList.add(new PendingDialog(saveDialogFragment, getString(R.string.save_dialog)));
+ pendingDialogsArrayList.add(new PendingDialogDataClass(saveDialogFragment, getString(R.string.save_dialog)));
}
}
});
// Set the favorite icon when it changes.
@Override
public void onReceivedIcon(WebView view, Bitmap icon) {
- // Only update the favorite icon if the website has finished loading.
- if (progressBar.getVisibility() == View.GONE) {
+ // Only update the favorite icon if the website has finished loading and the new favorite icon height is greater than the current favorite icon height.
+ // This prevents low resolution icons from replacing high resolution one.
+ // The check for the visibility of the progress bar can possibly be removed once https://redmine.stoutner.com/issues/747 is fixed.
+ if ((progressBar.getVisibility() == View.GONE) && (icon.getHeight() > nestedScrollWebView.getFavoriteIconHeight())) {
// Store the new favorite icon.
- nestedScrollWebView.setFavoriteOrDefaultIcon(icon);
+ nestedScrollWebView.setFavoriteIcon(icon);
// Get the current page position.
int currentPosition = webViewPagerAdapter.getPositionForId(nestedScrollWebView.getWebViewFragmentId());
// Get a URI for the current URL.
Uri currentUri = Uri.parse(url);
- // Get the IP addresses for the host.
- new GetHostIpAddresses(activity, getSupportFragmentManager(), nestedScrollWebView).execute(currentUri.getHost());
+ // Get the current domain name.
+ String currentDomainName = currentUri.getHost();
+
+ if ((currentDomainName != null) && !currentDomainName.isEmpty()) {
+ // Get the IP addresses for the current URI.
+ GetHostIpAddressesCoroutine.getAddresses(currentDomainName, nestedScrollWebView, getSupportFragmentManager(), getString(R.string.pinned_mismatch));
+ }
// Replace Refresh with Stop if the options menu has been created. (The first WebView typically begins loading before the menu items are instantiated.)
if (optionsMenu != null) {
sslCertificateErrorDialogFragment.show(getSupportFragmentManager(), getString(R.string.ssl_certificate_error));
} catch (Exception exception) {
// Add the dialog to the pending dialog array list. It will be displayed in `onStart()`.
- pendingDialogsArrayList.add(new PendingDialog(sslCertificateErrorDialogFragment, getString(R.string.ssl_certificate_error)));
+ pendingDialogsArrayList.add(new PendingDialogDataClass(sslCertificateErrorDialogFragment, getString(R.string.ssl_certificate_error)));
}
}
}