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=252609212a83251a57f041d7bd437fff1680d09b;hp=d13c4d27bb0ff149fffeb19064b2564f7a2f3f3c;hb=ca7516a7edb9e06d0f9fe9186513986cd82be716;hpb=de4e15cd445f2659165676e524a99f3c0f42033c 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 d13c4d27..25260921 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java @@ -73,6 +73,7 @@ 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; import android.webkit.WebSettings; @@ -128,7 +129,9 @@ import com.stoutner.privacybrowser.dialogs.DownloadImageDialog; import com.stoutner.privacybrowser.dialogs.DownloadLocationPermissionDialog; import com.stoutner.privacybrowser.dialogs.EditBookmarkDialog; import com.stoutner.privacybrowser.dialogs.EditBookmarkFolderDialog; +import com.stoutner.privacybrowser.dialogs.FontSizeDialog; import com.stoutner.privacybrowser.dialogs.HttpAuthenticationDialog; +import com.stoutner.privacybrowser.dialogs.PinnedMismatchDialog; import com.stoutner.privacybrowser.dialogs.SaveWebpageImageDialog; import com.stoutner.privacybrowser.dialogs.SslCertificateErrorDialog; import com.stoutner.privacybrowser.dialogs.StoragePermissionDialog; @@ -159,13 +162,14 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; 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 CreateBookmarkDialog.CreateBookmarkListener, CreateBookmarkFolderDialog.CreateBookmarkFolderListener, DownloadFileDialog.DownloadFileListener, DownloadImageDialog.DownloadImageListener, DownloadLocationPermissionDialog.DownloadLocationPermissionDialogListener, EditBookmarkDialog.EditBookmarkListener, - EditBookmarkFolderDialog.EditBookmarkFolderListener, NavigationView.OnNavigationItemSelectedListener, PopulateBlocklists.PopulateBlocklistsListener, SaveWebpageImageDialog.SaveWebpageImageListener, - StoragePermissionDialog.StoragePermissionDialogListener, WebViewTabFragment.NewTabListener { + EditBookmarkFolderDialog.EditBookmarkFolderListener, FontSizeDialog.UpdateFontSizeListener, NavigationView.OnNavigationItemSelectedListener, PinnedMismatchDialog.PinnedMismatchListener, PopulateBlocklists.PopulateBlocklistsListener, SaveWebpageImageDialog.SaveWebpageImageListener, + StoragePermissionDialog.StoragePermissionDialogListener, UrlHistoryDialog.NavigateHistoryListener, WebViewTabFragment.NewTabListener { // `orbotStatus` is public static so it can be accessed from `OrbotProxyHelper`. It is also used in `onCreate()`, `onResume()`, and `applyProxyThroughOrbot()`. public static String orbotStatus; @@ -388,6 +392,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook @Override protected void onNewIntent(Intent intent) { + // Run the default commands. + super.onNewIntent(intent); + // Replace the intent that started the app with this one. setIntent(intent); @@ -433,7 +440,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook loadingNewIntent = true; // Add a new tab. - addNewTab(url); + addNewTab(url, true); } else { // Load the URL in the current tab. // Make it so. loadUrl(url); @@ -810,14 +817,16 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook File localStorageDirectory = new File (privateDataDirectoryString + "/app_webview/Local Storage/"); int localStorageDirectoryNumberOfFiles = 0; if (localStorageDirectory.exists()) { - localStorageDirectoryNumberOfFiles = localStorageDirectory.list().length; + // `Objects.requireNonNull` removes a lint warning that `localStorageDirectory.list` might produce a null pointed exception if it is dereferenced. + localStorageDirectoryNumberOfFiles = Objects.requireNonNull(localStorageDirectory.list()).length; } // Get a count of the number of files in the IndexedDB directory. File indexedDBDirectory = new File (privateDataDirectoryString + "/app_webview/IndexedDB"); int indexedDBDirectoryNumberOfFiles = 0; if (indexedDBDirectory.exists()) { - indexedDBDirectoryNumberOfFiles = indexedDBDirectory.list().length; + // `Objects.requireNonNull` removes a lint warning that `indexedDBDirectory.list` might produce a null pointed exception if it is dereferenced. + indexedDBDirectoryNumberOfFiles = Objects.requireNonNull(indexedDBDirectory.list()).length; } // Enable Clear DOM Storage if there is any. @@ -867,61 +876,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook menu.findItem(R.id.user_agent_custom).setChecked(true); } - // Instantiate the font size title and the selected font size menu item. - String fontSizeTitle; - MenuItem selectedFontSizeMenuItem; - - // Prepare the font size title and current size menu item. - switch (fontSize) { - case 25: - fontSizeTitle = getString(R.string.font_size) + " - " + getString(R.string.twenty_five_percent); - selectedFontSizeMenuItem = menu.findItem(R.id.font_size_twenty_five_percent); - break; - - case 50: - fontSizeTitle = getString(R.string.font_size) + " - " + getString(R.string.fifty_percent); - selectedFontSizeMenuItem = menu.findItem(R.id.font_size_fifty_percent); - break; - - case 75: - fontSizeTitle = getString(R.string.font_size) + " - " + getString(R.string.seventy_five_percent); - selectedFontSizeMenuItem = menu.findItem(R.id.font_size_seventy_five_percent); - break; - - case 100: - fontSizeTitle = getString(R.string.font_size) + " - " + getString(R.string.one_hundred_percent); - selectedFontSizeMenuItem = menu.findItem(R.id.font_size_one_hundred_percent); - break; - - case 125: - fontSizeTitle = getString(R.string.font_size) + " - " + getString(R.string.one_hundred_twenty_five_percent); - selectedFontSizeMenuItem = menu.findItem(R.id.font_size_one_hundred_twenty_five_percent); - break; - - case 150: - fontSizeTitle = getString(R.string.font_size) + " - " + getString(R.string.one_hundred_fifty_percent); - selectedFontSizeMenuItem = menu.findItem(R.id.font_size_one_hundred_fifty_percent); - break; - - case 175: - fontSizeTitle = getString(R.string.font_size) + " - " + getString(R.string.one_hundred_seventy_five_percent); - selectedFontSizeMenuItem = menu.findItem(R.id.font_size_one_hundred_seventy_five_percent); - break; - - case 200: - fontSizeTitle = getString(R.string.font_size) + " - " + getString(R.string.two_hundred_percent); - selectedFontSizeMenuItem = menu.findItem(R.id.font_size_two_hundred_percent); - break; - - default: - fontSizeTitle = getString(R.string.font_size) + " - " + getString(R.string.one_hundred_percent); - selectedFontSizeMenuItem = menu.findItem(R.id.font_size_one_hundred_percent); - break; - } - - // Set the font size title and select the current size menu item. - fontSizeMenuItem.setTitle(fontSizeTitle); - selectedFontSizeMenuItem.setChecked(true); + // Set the font size title. + fontSizeMenuItem.setTitle(getString(R.string.font_size) + " - " + fontSize + "%"); // Run all the other default commands. super.onPrepareOptionsMenu(menu); @@ -1500,58 +1456,12 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Consume the event. return true; - case R.id.font_size_twenty_five_percent: - // Set the font size. - currentWebView.getSettings().setTextZoom(25); - - // Consume the event. - return true; + case R.id.font_size: + // Instantiate the font size dialog. + DialogFragment fontSizeDialogFragment = FontSizeDialog.displayDialog(currentWebView.getSettings().getTextZoom()); - case R.id.font_size_fifty_percent: - // Set the font size. - currentWebView.getSettings().setTextZoom(50); - - // Consume the event. - return true; - - case R.id.font_size_seventy_five_percent: - // Set the font size. - currentWebView.getSettings().setTextZoom(75); - - // Consume the event. - return true; - - case R.id.font_size_one_hundred_percent: - // Set the font size. - currentWebView.getSettings().setTextZoom(100); - - // Consume the event. - return true; - - case R.id.font_size_one_hundred_twenty_five_percent: - // Set the font size. - currentWebView.getSettings().setTextZoom(125); - - // Consume the event. - return true; - - case R.id.font_size_one_hundred_fifty_percent: - // Set the font size. - currentWebView.getSettings().setTextZoom(150); - - // Consume the event. - return true; - - case R.id.font_size_one_hundred_seventy_five_percent: - // Set the font size. - currentWebView.getSettings().setTextZoom(175); - - // Consume the event. - return true; - - case R.id.font_size_two_hundred_percent: - // Set the font size. - currentWebView.getSettings().setTextZoom(200); + // Show the font size dialog. + fontSizeDialogFragment.show(getSupportFragmentManager(), getString(R.string.font_size)); // Consume the event. return true; @@ -1803,11 +1713,14 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook case R.id.back: if (currentWebView.canGoBack()) { - // Reset the current domain name so that navigation works if third-party requests are blocked. - currentWebView.resetCurrentDomainName(); + // Get the current web back forward list. + WebBackForwardList webBackForwardList = currentWebView.copyBackForwardList(); + + // Get the previous entry URL. + String previousUrl = webBackForwardList.getItemAtIndex(webBackForwardList.getCurrentIndex() - 1).getUrl(); - // Set navigating history so that the domain settings are applied when the new URL is loaded. - currentWebView.setNavigatingHistory(true); + // Apply the domain settings. + applyDomainSettings(currentWebView, previousUrl, false, false); // Load the previous website in the history. currentWebView.goBack(); @@ -1816,11 +1729,14 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook case R.id.forward: if (currentWebView.canGoForward()) { - // Reset the current domain name so that navigation works if third-party requests are blocked. - currentWebView.resetCurrentDomainName(); + // Get the current web back forward list. + WebBackForwardList webBackForwardList = currentWebView.copyBackForwardList(); + + // Get the next entry URL. + String nextUrl = webBackForwardList.getItemAtIndex(webBackForwardList.getCurrentIndex() + 1).getUrl(); - // Set navigating history so that the domain settings are applied when the new URL is loaded. - currentWebView.setNavigatingHistory(true); + // Apply the domain settings. + applyDomainSettings(currentWebView, nextUrl, false, false); // Load the next website in the history. currentWebView.goForward(); @@ -1969,7 +1885,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook } @Override - public void onConfigurationChanged(Configuration newConfig) { + public void onConfigurationChanged(@NonNull Configuration newConfig) { // Run the default commands. super.onConfigurationChanged(newConfig); @@ -2025,8 +1941,17 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Add an Open in New Tab entry. menu.add(R.string.open_in_new_tab).setOnMenuItemClickListener((MenuItem item) -> { - // Load the link URL in a new tab. - addNewTab(linkUrl); + // Load the link URL in a new tab and move to it. + addNewTab(linkUrl, true); + + // Consume the event. + return true; + }); + + // Add an Open in Background entry. + menu.add(R.string.open_in_background).setOnMenuItemClickListener((MenuItem item) -> { + // Load the link URL in a new tab but do not move to it. + addNewTab(linkUrl, false); // Consume the event. return true; @@ -2151,9 +2076,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook menu.setHeaderTitle(imageUrl); // Add an Open in New Tab entry. - menu.add(R.string.open_in_new_tab).setOnMenuItemClickListener((MenuItem item) -> { - // Load the image URL in a new tab. - addNewTab(imageUrl); + menu.add(R.string.open_image_in_new_tab).setOnMenuItemClickListener((MenuItem item) -> { + // Load the image in a new tab. + addNewTab(imageUrl, true); // Consume the event. return true; @@ -2259,8 +2184,26 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Add an Open in New Tab entry. menu.add(R.string.open_in_new_tab).setOnMenuItemClickListener((MenuItem item) -> { - // Load the link URL in a new tab. - addNewTab(linkUrl); + // Load the link URL in a new tab and move to it. + addNewTab(linkUrl, true); + + // Consume the event. + return true; + }); + + // Add an Open in Background entry. + menu.add(R.string.open_in_background).setOnMenuItemClickListener((MenuItem item) -> { + // Lod the link URL in a new tab but do not move to it. + addNewTab(linkUrl, false); + + // Consume the event. + return true; + }); + + // Add an Open Image in New Tab entry. + menu.add(R.string.open_image_in_new_tab).setOnMenuItemClickListener((MenuItem item) -> { + // Load the image in a new tab and move to it. + addNewTab(imageUrl, true); // Consume the event. return true; @@ -2351,9 +2294,15 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Get a handle for the bookmarks list view. ListView bookmarksListView = findViewById(R.id.bookmarks_drawer_listview); + // Get the dialog. + Dialog dialog = dialogFragment.getDialog(); + + // Remove the incorrect lint warning below that the dialog might be null. + assert dialog != null; + // Get the views from the dialog fragment. - EditText createBookmarkNameEditText = dialogFragment.getDialog().findViewById(R.id.create_bookmark_name_edittext); - EditText createBookmarkUrlEditText = dialogFragment.getDialog().findViewById(R.id.create_bookmark_url_edittext); + EditText createBookmarkNameEditText = dialog.findViewById(R.id.create_bookmark_name_edittext); + EditText createBookmarkUrlEditText = dialog.findViewById(R.id.create_bookmark_url_edittext); // Extract the strings from the edit texts. String bookmarkNameString = createBookmarkNameEditText.getText().toString(); @@ -2389,10 +2338,16 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Get a handle for the bookmarks list view. ListView bookmarksListView = findViewById(R.id.bookmarks_drawer_listview); + // Get the dialog. + Dialog dialog = dialogFragment.getDialog(); + + // Remove the incorrect lint warning below that the dialog might be null. + assert dialog != null; + // Get handles for the views in the dialog fragment. - EditText createFolderNameEditText = dialogFragment.getDialog().findViewById(R.id.create_folder_name_edittext); - RadioButton defaultFolderIconRadioButton = dialogFragment.getDialog().findViewById(R.id.create_folder_default_icon_radiobutton); - ImageView folderIconImageView = dialogFragment.getDialog().findViewById(R.id.create_folder_default_icon); + EditText createFolderNameEditText = dialog.findViewById(R.id.create_folder_name_edittext); + RadioButton defaultFolderIconRadioButton = dialog.findViewById(R.id.create_folder_default_icon_radiobutton); + ImageView folderIconImageView = dialog.findViewById(R.id.create_folder_default_icon); // Get new folder name string. String folderNameString = createFolderNameEditText.getText().toString(); @@ -2445,10 +2400,16 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook @Override public void onSaveBookmark(DialogFragment dialogFragment, int selectedBookmarkDatabaseId, Bitmap favoriteIconBitmap) { - // Get handles for the views from `dialogFragment`. - EditText editBookmarkNameEditText = dialogFragment.getDialog().findViewById(R.id.edit_bookmark_name_edittext); - EditText editBookmarkUrlEditText = dialogFragment.getDialog().findViewById(R.id.edit_bookmark_url_edittext); - RadioButton currentBookmarkIconRadioButton = dialogFragment.getDialog().findViewById(R.id.edit_bookmark_current_icon_radiobutton); + // Get the dialog. + Dialog dialog = dialogFragment.getDialog(); + + // Remove the incorrect lint warning below that the dialog might be null. + assert dialog != null; + + // Get handles for the views from the dialog. + EditText editBookmarkNameEditText = dialog.findViewById(R.id.edit_bookmark_name_edittext); + EditText editBookmarkUrlEditText = dialog.findViewById(R.id.edit_bookmark_url_edittext); + RadioButton currentBookmarkIconRadioButton = dialog.findViewById(R.id.edit_bookmark_current_icon_radiobutton); // Store the bookmark strings. String bookmarkNameString = editBookmarkNameEditText.getText().toString(); @@ -2480,11 +2441,17 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook @Override public void onSaveBookmarkFolder(DialogFragment dialogFragment, int selectedFolderDatabaseId, Bitmap favoriteIconBitmap) { + // Get the dialog. + Dialog dialog = dialogFragment.getDialog(); + + // Remove the incorrect lint warning below that the dialog might be null. + assert dialog != null; + // Get handles for the views from `dialogFragment`. - EditText editFolderNameEditText = dialogFragment.getDialog().findViewById(R.id.edit_folder_name_edittext); - RadioButton currentFolderIconRadioButton = dialogFragment.getDialog().findViewById(R.id.edit_folder_current_icon_radiobutton); - RadioButton defaultFolderIconRadioButton = dialogFragment.getDialog().findViewById(R.id.edit_folder_default_icon_radiobutton); - ImageView defaultFolderIconImageView = dialogFragment.getDialog().findViewById(R.id.edit_folder_default_icon_imageview); + EditText editFolderNameEditText = dialog.findViewById(R.id.edit_folder_name_edittext); + RadioButton currentFolderIconRadioButton = dialog.findViewById(R.id.edit_folder_current_icon_radiobutton); + RadioButton defaultFolderIconRadioButton = dialog.findViewById(R.id.edit_folder_default_icon_radiobutton); + ImageView defaultFolderIconImageView = dialog.findViewById(R.id.edit_folder_default_icon_imageview); // Get the new folder name. String newFolderNameString = editFolderNameEditText.getText().toString(); @@ -2652,8 +2619,14 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook downloadRequest.addRequestHeader("Cookie", cookies); } + // Get the dialog. + Dialog dialog = dialogFragment.getDialog(); + + // Remove the incorrect lint warning below that the dialog might be null. + assert dialog != null; + // Get the file name from the dialog fragment. - EditText downloadImageNameEditText = dialogFragment.getDialog().findViewById(R.id.download_image_name); + EditText downloadImageNameEditText = dialog.findViewById(R.id.download_image_name); String imageName = downloadImageNameEditText.getText().toString(); // Specify the download location. @@ -2707,8 +2680,14 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook downloadRequest.addRequestHeader("Cookie", cookies); } - // Get the file name from the dialog fragment. - EditText downloadFileNameEditText = dialogFragment.getDialog().findViewById(R.id.download_file_name); + // Get the dialog. + Dialog dialog = dialogFragment.getDialog(); + + // Remove the incorrect lint warning below that the dialog might be null. + assert dialog != null; + + // Get the file name from the dialog. + EditText downloadFileNameEditText = dialog.findViewById(R.id.download_file_name); String fileName = downloadFileNameEditText.getText().toString(); // Specify the download location. @@ -2739,7 +2718,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook } } - // Override `onBackPressed` to handle the navigation drawer and and the WebView. + // Override `onBackPressed` to handle the navigation drawer and and the WebViews. @Override public void onBackPressed() { // Get a handle for the drawer layout and the tab layout. @@ -2760,12 +2739,86 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Load the new folder. loadBookmarksFolder(); } + } else if (displayingFullScreenVideo) { // A full screen video is shown. + // Get a handle for the layouts. + FrameLayout rootFrameLayout = findViewById(R.id.root_framelayout); + RelativeLayout mainContentRelativeLayout = findViewById(R.id.main_content_relativelayout); + FrameLayout fullScreenVideoFrameLayout = findViewById(R.id.full_screen_video_framelayout); + + // Re-enable the screen timeout. + fullScreenVideoFrameLayout.setKeepScreenOn(false); + + // Unset the full screen video flag. + displayingFullScreenVideo = false; + + // Remove all the views from the full screen video frame layout. + fullScreenVideoFrameLayout.removeAllViews(); + + // Hide the full screen video frame layout. + fullScreenVideoFrameLayout.setVisibility(View.GONE); + + // Enable the sliding drawers. + drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED); + + // Show the main content relative layout. + mainContentRelativeLayout.setVisibility(View.VISIBLE); + + // Apply the appropriate full screen mode flags. + if (fullScreenBrowsingModeEnabled && inFullScreenBrowsingMode) { // Privacy Browser is currently in full screen browsing mode. + // Hide the app bar if specified. + if (hideAppBar) { + // Get handles for the views. + LinearLayout tabsLinearLayout = findViewById(R.id.tabs_linearlayout); + ActionBar actionBar = getSupportActionBar(); + + // Remove the incorrect lint warning below that the action bar might be null. + assert actionBar != null; + + // Hide the tab linear layout. + tabsLinearLayout.setVisibility(View.GONE); + + // Hide the action bar. + actionBar.hide(); + } + + // Hide the banner ad in the free flavor. + if (BuildConfig.FLAVOR.contentEquals("free")) { + AdHelper.hideAd(findViewById(R.id.adview)); + } + + // Remove the translucent status flag. This is necessary so the root frame layout can fill the entire screen. + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + + /* Hide the system bars. + * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen. + * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar. + * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen. + * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown. + */ + rootFrameLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); + } else { // Switch to normal viewing mode. + // Remove the `SYSTEM_UI` flags from the root frame layout. + rootFrameLayout.setSystemUiVisibility(0); + + // Add the translucent status flag. + getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + } + + // Reload the ad for the free flavor if not in full screen mode. + if (BuildConfig.FLAVOR.contentEquals("free") && !inFullScreenBrowsingMode) { + // Reload the ad. + AdHelper.loadAd(findViewById(R.id.adview), getApplicationContext(), getString(R.string.ad_unit_id)); + } } else if (currentWebView.canGoBack()) { // There is at least one item in the current WebView history. - // Reset the current domain name so that navigation works if third-party requests are blocked. - currentWebView.resetCurrentDomainName(); + // Get the current web back forward list. + WebBackForwardList webBackForwardList = currentWebView.copyBackForwardList(); + + // Get the previous entry URL. + String previousUrl = webBackForwardList.getItemAtIndex(webBackForwardList.getCurrentIndex() - 1).getUrl(); - // Set navigating history so that the domain settings are applied when the new URL is loaded. - currentWebView.setNavigatingHistory(true); + // Apply the domain settings. + applyDomainSettings(currentWebView, previousUrl, false, false); // Go back. currentWebView.goBack(); @@ -2773,8 +2826,12 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Close the current tab. closeCurrentTab(); } else { // There isn't anything to do in Privacy Browser. - // Run the default commands. - super.onBackPressed(); + // Close Privacy Browser. `finishAndRemoveTask()` also removes Privacy Browser from the recent app list. + if (Build.VERSION.SDK_INT >= 21) { + finishAndRemoveTask(); + } else { + finish(); + } // Manually kill Privacy Browser. Otherwise, it is glitchy when restarted. System.exit(0); @@ -2784,6 +2841,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Process the results of a file browse. @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { + // Run the default commands. + super.onActivityResult(requestCode, resultCode, data); + // Run the commands that correlate to the specified request code. switch (requestCode) { case FILE_UPLOAD_REQUEST_CODE: @@ -2805,17 +2865,23 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Get a handle for the save webpage image dialog. Dialog saveWebpageImageDialog = saveWebpageImageDialogFragment.getDialog(); + // Remove the incorrect lint warning below that the dialog might be null. + assert saveWebpageImageDialog != null; + // Get a handle for the file name edit text. EditText fileNameEditText = saveWebpageImageDialog.findViewById(R.id.file_name_edittext); // Instantiate the file name helper. FileNameHelper fileNameHelper = new FileNameHelper(); - // Convert the file name URI to a file name path. - String fileNamePath = fileNameHelper.convertUriToFileNamePath(data.getData()); + // Get the file path if it isn't null. + if (data.getData() != null) { + // Convert the file name URI to a file name path. + String fileNamePath = fileNameHelper.convertUriToFileNamePath(data.getData()); - // Set the file name path as the text of the file name edit text. - fileNameEditText.setText(fileNamePath); + // Set the file name path as the text of the file name edit text. + fileNameEditText.setText(fileNamePath); + } } } break; @@ -2943,10 +3009,41 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook inputMethodManager.hideSoftInputFromWindow(toolbar.getWindowToken(), 0); } + @Override + public void onApplyNewFontSize(DialogFragment dialogFragment) { + // Get the dialog. + Dialog dialog = dialogFragment.getDialog(); + + // Remove the incorrect lint warning below tha the dialog might be null. + assert dialog != null; + + // Get a handle for the font size edit text. + EditText fontSizeEditText = dialog.findViewById(R.id.font_size_edittext); + + // Initialize the new font size variable with the current font size. + int newFontSize = currentWebView.getSettings().getTextZoom(); + + // Get the font size from the edit text. + try { + newFontSize = Integer.valueOf(fontSizeEditText.getText().toString()); + } catch (Exception exception) { + // If the edit text does not contain a valid font size do nothing. + } + + // Apply the new font size. + currentWebView.getSettings().setTextZoom(newFontSize); + } + @Override public void onSaveWebpageImage(DialogFragment dialogFragment) { + // Get the dialog. + Dialog dialog = dialogFragment.getDialog(); + + // Remove the incorrect lint warning below that the dialog might be null. + assert dialog != null; + // Get a handle for the file name edit text. - EditText fileNameEditText = dialogFragment.getDialog().findViewById(R.id.file_name_edittext); + EditText fileNameEditText = dialog.findViewById(R.id.file_name_edittext); // Get the file path string. saveWebsiteImageFilePath = fileNameEditText.getText().toString(); @@ -3202,7 +3299,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook orbotStatus = intent.getStringExtra("org.torproject.android.intent.extra.STATUS"); // If Privacy Browser is waiting on Orbot, load the website now that Orbot is connected. - if (orbotStatus.equals("ON") && waitingForOrbot) { + if ((orbotStatus != null) && orbotStatus.equals("ON") && waitingForOrbot) { // Reset the waiting for Orbot status. waitingForOrbot = false; @@ -3459,10 +3556,12 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook bookmarksListView.setOnItemClickListener((parent, view, position, id) -> { // Convert the id from long to int to match the format of the bookmarks database. - int databaseID = (int) id; + int databaseId = (int) id; + + // Get the bookmark cursor for this ID. + Cursor bookmarkCursor = bookmarksDatabaseHelper.getBookmark(databaseId); - // Get the bookmark cursor for this ID and move it to the first row. - Cursor bookmarkCursor = bookmarksDatabaseHelper.getBookmark(databaseID); + // Move the bookmark cursor to the first row. bookmarkCursor.moveToFirst(); // Act upon the bookmark according to the type. @@ -3495,13 +3594,20 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Save the current folder name, which is used in `onSaveEditBookmarkFolder()`. oldFolderNameString = bookmarksCursor.getString(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME)); - // Show the edit bookmark folder `AlertDialog` and name the instance `@string/edit_folder`. + // Instantiate the edit folder bookmark dialog. DialogFragment editBookmarkFolderDialog = EditBookmarkFolderDialog.folderDatabaseId(databaseId, currentWebView.getFavoriteOrDefaultIcon()); + + // Show the edit folder bookmark dialog. editBookmarkFolderDialog.show(getSupportFragmentManager(), getString(R.string.edit_folder)); } else { - // Show the edit bookmark `AlertDialog` and name the instance `@string/edit_bookmark`. - DialogFragment editBookmarkDialog = EditBookmarkDialog.bookmarkDatabaseId(databaseId, currentWebView.getFavoriteOrDefaultIcon()); - editBookmarkDialog.show(getSupportFragmentManager(), getString(R.string.edit_bookmark)); + // Get the bookmark cursor for this ID. + Cursor bookmarkCursor = bookmarksDatabaseHelper.getBookmark(databaseId); + + // 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.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_URL)), false); } // Consume the event. @@ -3585,6 +3691,30 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook bareWebView.destroy(); } + @Override + public void navigateHistory(String url, int steps) { + // Apply the domain settings. + applyDomainSettings(currentWebView, url, false, false); + + // Load the history entry. + currentWebView.goBackOrForward(steps); + } + + @Override + public void pinnedErrorGoBack() { + // Get the current web back forward list. + WebBackForwardList webBackForwardList = currentWebView.copyBackForwardList(); + + // Get the previous entry URL. + String previousUrl = webBackForwardList.getItemAtIndex(webBackForwardList.getCurrentIndex() - 1).getUrl(); + + // Apply the domain settings. + applyDomainSettings(currentWebView, previousUrl, false, false); + + // Go back. + currentWebView.goBack(); + } + // `reloadWebsite` is used if returning from the Domains activity. Otherwise JavaScript might not function correctly if it is newly enabled. @SuppressLint("SetJavaScriptEnabled") private boolean applyDomainSettings(NestedScrollWebView nestedScrollWebView, String url, boolean resetTab, boolean reloadWebsite) { @@ -3842,10 +3972,16 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook } // Apply the font size. - if (fontSize == 0) { // Apply the default font size. - nestedScrollWebView.getSettings().setTextZoom(Integer.valueOf(defaultFontSizeString)); - } else { // Apply the specified font size. - nestedScrollWebView.getSettings().setTextZoom(fontSize); + try { // Try the specified font size to see if it is valid. + if (fontSize == 0) { // Apply the default font size. + // Try to set the font size from the value in the app settings. + nestedScrollWebView.getSettings().setTextZoom(Integer.valueOf(defaultFontSizeString)); + } else { // Apply the font size from domain settings. + nestedScrollWebView.getSettings().setTextZoom(fontSize); + } + } catch (Exception exception) { // The specified font size is invalid + // Set the font size to be 100% + nestedScrollWebView.getSettings().setTextZoom(100); } // Set the user agent. @@ -3981,9 +4117,17 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook nestedScrollWebView.getSettings().setJavaScriptEnabled(defaultJavaScriptEnabled); } - // Apply the default settings. + // Apply the default first-party cookie setting. cookieManager.setAcceptCookie(nestedScrollWebView.getAcceptFirstPartyCookies()); - nestedScrollWebView.getSettings().setTextZoom(Integer.valueOf(defaultFontSizeString)); + + // Apply the default font size setting. + try { + // Try to set the font size from the value in the app settings. + nestedScrollWebView.getSettings().setTextZoom(Integer.valueOf(defaultFontSizeString)); + } catch (Exception exception) { + // If the app settings value is invalid, set the font size to 100%. + nestedScrollWebView.getSettings().setTextZoom(100); + } // Apply the form data setting if the API < 26. if (Build.VERSION.SDK_INT < 26) { @@ -4410,6 +4554,16 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook if (url.contains("&fbclid=")) { url = url.substring(0, url.indexOf("&fbclid=")); } + + // Remove `?fbadid=`. + if (url.contains("?fbadid=")) { + url = url.substring(0, url.indexOf("?fbadid=")); + } + + // Remove `&fbadid=`. + if (url.contains("&fbadid=")) { + url = url.substring(0, url.indexOf("&fbadid=")); + } } // Sanitize Twitter AMP redirects. @@ -4434,15 +4588,15 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook ultraPrivacy = combinedBlocklists.get(5); // Add the first tab. - addNewTab(""); + addNewTab("", true); } public void addTab(View view) { // Add a new tab with a blank URL. - addNewTab(""); + addNewTab("", true); } - private void addNewTab(String url) { + private void addNewTab(String url, boolean moveToTab) { // Sanitize the URL. url = sanitizeUrl(url); @@ -4466,7 +4620,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook newTab.setCustomView(R.layout.tab_custom_view); // Add the new WebView page. - webViewPagerAdapter.addPage(newTabNumber, webViewPager, url); + webViewPagerAdapter.addPage(newTabNumber, webViewPager, url, moveToTab); } public void closeTab(View view) { @@ -5183,6 +5337,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Show the full screen video frame layout. fullScreenVideoFrameLayout.setVisibility(View.VISIBLE); + + // Disable the screen timeout while the video is playing. YouTube does this automatically, but not all other videos do. + fullScreenVideoFrameLayout.setKeepScreenOn(true); } // Exit full screen video. @@ -5191,6 +5348,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Get a handle for the full screen video frame layout. FrameLayout fullScreenVideoFrameLayout = findViewById(R.id.full_screen_video_framelayout); + // Re-enable the screen timeout. + fullScreenVideoFrameLayout.setKeepScreenOn(false); + // Unset the full screen video flag. displayingFullScreenVideo = false; @@ -5782,20 +5942,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Get the IP addresses for the host. new GetHostIpAddresses(activity, getSupportFragmentManager(), nestedScrollWebView).execute(currentUri.getHost()); - // Apply any custom domain settings if the URL was loaded by navigating history. - if (nestedScrollWebView.getNavigatingHistory()) { - // Reset navigating history. - nestedScrollWebView.setNavigatingHistory(false); - - // Apply the domain settings. - boolean userAgentChanged = applyDomainSettings(nestedScrollWebView, url, true, false); - - // Manually load the URL if the user agent has changed, which will have caused the previous URL to be reloaded. - if (userAgentChanged) { - loadUrl(url); - } - } - // 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) { // Get a handle for the refresh menu item. @@ -5923,11 +6069,17 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook tabTitleTextView.setText(R.string.new_tab); } } else { // The WebView has loaded a webpage. - // Display the final URL. Getting the URL from the WebView instead of using the one provided by `onPageFinished()` makes websites like YouTube function correctly. - urlEditText.setText(currentUrl); + // Update the URL edit text if it is not currently being edited. + if (!urlEditText.hasFocus()) { + // Sanitize the current URL. This removes unwanted URL elements that were added by redirects, so that they won't be included if the URL is shared. + String sanitizedUrl = sanitizeUrl(currentUrl); - // Apply text highlighting to the URL. - highlightUrlText(); + // Display the final URL. Getting the URL from the WebView instead of using the one provided by `onPageFinished()` makes websites like YouTube function correctly. + urlEditText.setText(sanitizedUrl); + + // Apply text highlighting to the URL. + highlightUrlText(); + } // Only populate the title text view if the tab has been fully created. if (tab != null) {