+ // The default progress view offsets are set in `onCreate()` and used in `initializeWebView()`.
+ private int appBarHeight;
+ private int defaultProgressViewStartOffset;
+ private int defaultProgressViewEndOffset;
+
+ // The URL sanitizers are set in `applyAppSettings()` and used in `sanitizeUrl()`.
+ private boolean sanitizeGoogleAnalytics;
+ private boolean sanitizeFacebookClickIds;
+ private boolean sanitizeTwitterAmpRedirects;
+
+ // Declare the class variables
+ private BroadcastReceiver orbotStatusBroadcastReceiver;
+ private String webViewDefaultUserAgent;
+ private boolean incognitoModeEnabled;
+ private boolean fullScreenBrowsingModeEnabled;
+ private boolean inFullScreenBrowsingMode;
+ private boolean downloadWithExternalApp;
+ private boolean hideAppBar;
+ private boolean scrollAppBar;
+ private boolean bottomAppBar;
+ private boolean loadingNewIntent;
+ private boolean reapplyDomainSettingsOnRestart;
+ private boolean reapplyAppSettingsOnRestart;
+ private boolean displayingFullScreenVideo;
+ private boolean waitingForProxy;
+
+ // Define the class variables.
+ private long lastScrollUpdate = 0;
+ private String saveUrlString = "";
+
+ // Declare the class views.
+ private FrameLayout rootFrameLayout;
+ private DrawerLayout drawerLayout;
+ private RelativeLayout mainContentRelativeLayout;
+ private AppBarLayout appBarLayout;
+ private Toolbar toolbar;
+ private RelativeLayout urlRelativeLayout;
+ private EditText urlEditText;
+ private ActionBar actionBar;
+ private LinearLayout findOnPageLinearLayout;
+ private LinearLayout tabsLinearLayout;
+ private TabLayout tabLayout;
+ private SwipeRefreshLayout swipeRefreshLayout;
+ private ViewPager webViewPager;
+ private FrameLayout fullScreenVideoFrameLayout;
+
+ // Declare the class menus.
+ private Menu optionsMenu;
+
+ // Declare the class menu items.
+ private MenuItem navigationBackMenuItem;
+ private MenuItem navigationForwardMenuItem;
+ private MenuItem navigationHistoryMenuItem;
+ private MenuItem navigationRequestsMenuItem;
+ private MenuItem optionsPrivacyMenuItem;
+ private MenuItem optionsRefreshMenuItem;
+ private MenuItem optionsCookiesMenuItem;
+ private MenuItem optionsDomStorageMenuItem;
+ private MenuItem optionsSaveFormDataMenuItem;
+ private MenuItem optionsClearDataMenuItem;
+ private MenuItem optionsClearCookiesMenuItem;
+ private MenuItem optionsClearDomStorageMenuItem;
+ private MenuItem optionsClearFormDataMenuItem;
+ private MenuItem optionsBlocklistsMenuItem;
+ private MenuItem optionsEasyListMenuItem;
+ private MenuItem optionsEasyPrivacyMenuItem;
+ private MenuItem optionsFanboysAnnoyanceListMenuItem;
+ private MenuItem optionsFanboysSocialBlockingListMenuItem;
+ private MenuItem optionsUltraListMenuItem;
+ private MenuItem optionsUltraPrivacyMenuItem;
+ private MenuItem optionsBlockAllThirdPartyRequestsMenuItem;
+ private MenuItem optionsProxyMenuItem;
+ private MenuItem optionsProxyNoneMenuItem;
+ private MenuItem optionsProxyTorMenuItem;
+ private MenuItem optionsProxyI2pMenuItem;
+ private MenuItem optionsProxyCustomMenuItem;
+ private MenuItem optionsUserAgentMenuItem;
+ private MenuItem optionsUserAgentPrivacyBrowserMenuItem;
+ private MenuItem optionsUserAgentWebViewDefaultMenuItem;
+ private MenuItem optionsUserAgentFirefoxOnAndroidMenuItem;
+ private MenuItem optionsUserAgentChromeOnAndroidMenuItem;
+ private MenuItem optionsUserAgentSafariOnIosMenuItem;
+ private MenuItem optionsUserAgentFirefoxOnLinuxMenuItem;
+ private MenuItem optionsUserAgentChromiumOnLinuxMenuItem;
+ private MenuItem optionsUserAgentFirefoxOnWindowsMenuItem;
+ private MenuItem optionsUserAgentChromeOnWindowsMenuItem;
+ private MenuItem optionsUserAgentEdgeOnWindowsMenuItem;
+ private MenuItem optionsUserAgentInternetExplorerOnWindowsMenuItem;
+ private MenuItem optionsUserAgentSafariOnMacosMenuItem;
+ private MenuItem optionsUserAgentCustomMenuItem;
+ private MenuItem optionsSwipeToRefreshMenuItem;
+ private MenuItem optionsWideViewportMenuItem;
+ private MenuItem optionsDisplayImagesMenuItem;
+ private MenuItem optionsDarkWebViewMenuItem;
+ private MenuItem optionsFontSizeMenuItem;
+ private MenuItem optionsAddOrEditDomainMenuItem;
+
+ // This variable won't be needed once the class is migrated to Kotlin, as can be seen in LogcatActivity or AboutVersionFragment.
+ 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<String> saveUrlActivityResultLauncher = registerForActivityResult(new ActivityResultContracts.CreateDocument(),
+ new ActivityResultCallback<Uri>() {
+ @Override
+ public void onActivityResult(Uri fileUri) {
+ // Only save the URL if the file URI is not null, which happens if the user exited the file picker by pressing back.
+ if (fileUri != null) {
+ new SaveUrl(getApplicationContext(), resultLauncherActivityHandle, fileUri, currentWebView.getSettings().getUserAgentString(), currentWebView.getAcceptCookies()).execute(saveUrlString);
+ }
+
+ // Reset the save URL string.
+ saveUrlString = "";
+ }
+ });
+
+ // Define the save webpage archive activity result launcher. It must be defined before `onCreate()` is run or the app will crash.
+ private final ActivityResultLauncher<String> saveWebpageArchiveActivityResultLauncher = registerForActivityResult(new ActivityResultContracts.CreateDocument(),
+ new ActivityResultCallback<Uri>() {
+ @Override
+ 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) {
+ 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 {
+ // Create a temporary MHT file input stream.
+ FileInputStream temporaryMhtFileInputStream = new FileInputStream(temporaryMhtFile);
+
+ // Get an output stream for the save webpage file path.
+ OutputStream mhtOutputStream = getContentResolver().openOutputStream(fileUri);
+
+ // Create a transfer byte array.
+ byte[] transferByteArray = new byte[1024];
+
+ // Create an integer to track the number of bytes read.
+ int bytesRead;
+
+ // Copy the temporary MHT file input stream to the MHT output stream.
+ while ((bytesRead = temporaryMhtFileInputStream.read(transferByteArray)) > 0) {
+ mhtOutputStream.write(transferByteArray, 0, bytesRead);
+ }
+
+ // Close the streams.
+ mhtOutputStream.close();
+ temporaryMhtFileInputStream.close();
+
+ // Initialize the file name string from the file URI last path segment.
+ String fileNameString = fileUri.getLastPathSegment();