import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.navigation.NavigationView;
import com.google.android.material.snackbar.Snackbar;
-
import com.google.android.material.tabs.TabLayout;
+
import com.stoutner.privacybrowser.BuildConfig;
import com.stoutner.privacybrowser.R;
import com.stoutner.privacybrowser.asynctasks.GetHostIpAddresses;
import com.stoutner.privacybrowser.dialogs.CreateBookmarkDialog;
import com.stoutner.privacybrowser.dialogs.CreateBookmarkFolderDialog;
import com.stoutner.privacybrowser.dialogs.CreateHomeScreenShortcutDialog;
+import com.stoutner.privacybrowser.dialogs.DownloadFileDialog;
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.HttpAuthenticationDialog;
import com.stoutner.privacybrowser.dialogs.PinnedMismatchDialog;
+import com.stoutner.privacybrowser.dialogs.SslCertificateErrorDialog;
import com.stoutner.privacybrowser.dialogs.UrlHistoryDialog;
import com.stoutner.privacybrowser.dialogs.ViewSslCertificateDialog;
import com.stoutner.privacybrowser.fragments.WebViewTabFragment;
import com.stoutner.privacybrowser.helpers.BookmarksDatabaseHelper;
import com.stoutner.privacybrowser.helpers.DomainsDatabaseHelper;
import com.stoutner.privacybrowser.helpers.OrbotProxyHelper;
-import com.stoutner.privacybrowser.dialogs.DownloadFileDialog;
-import com.stoutner.privacybrowser.dialogs.SslCertificateErrorDialog;
import com.stoutner.privacybrowser.views.NestedScrollWebView;
import java.io.ByteArrayInputStream;
EditBookmarkFolderDialog.EditBookmarkFolderListener, HttpAuthenticationDialog.HttpAuthenticationListener, NavigationView.OnNavigationItemSelectedListener, WebViewTabFragment.NewTabListener,
PinnedMismatchDialog.PinnedMismatchListener, SslCertificateErrorDialog.SslCertificateErrorListener, UrlHistoryDialog.UrlHistoryListener {
+ // TODO Consider removing
// `darkTheme` is public static so it can be accessed from everywhere.
public static boolean darkTheme;
+ // TODO Consider removing
// `allowScreenshots` is public static so it can be accessed from everywhere. It is also used in `onCreate()`.
public static boolean allowScreenshots;
- // `favoriteIconBitmap` is public static so it can be accessed from `CreateHomeScreenShortcutDialog`, `BookmarksActivity`, `BookmarksDatabaseViewActivity`, `CreateBookmarkDialog`,
- // `CreateBookmarkFolderDialog`, `EditBookmarkDialog`, `EditBookmarkFolderDialog`, `EditBookmarkDatabaseViewDialog`, and `ViewSslCertificateDialog`. It is also used in `onCreate()`,
- // `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onCreateHomeScreenShortcut()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, and `applyDomainSettings()`.
+ // TODO Remove
+ // `favoriteIconBitmap` is public static so it can be accessed from `BookmarksActivity`, `BookmarksDatabaseViewActivity`, `CreateBookmarkFolderDialog`,
+ // `EditBookmarkDialog`, `EditBookmarkFolderDialog`, `EditBookmarkDatabaseViewDialog`, and `ViewSslCertificateDialog`. It is also used in `onCreate()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`,
+ // `onCreateHomeScreenShortcut()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, and `applyDomainSettings()`.
public static Bitmap favoriteIconBitmap;
+ // TODO Remove
// `favoriteIconDefaultBitmap` public static so it can be accessed from `PinnedMismatchDialog`. It is also used in `onCreate()` and `applyDomainSettings`.
public static Bitmap favoriteIconDefaultBitmap;
- // `formattedUrlString` is public static so it can be accessed from `AddDomainDialog`, `BookmarksActivity`, `DomainSettingsFragment`, `CreateBookmarkDialog`,
- // and `PinnedMismatchDialog`.
+ // TODO Consider removing the formatted URL string.
+ // `formattedUrlString` is public static so it can be accessed from `AddDomainDialog`, `BookmarksActivity`, `DomainSettingsFragment`, and `PinnedMismatchDialog`.
// It is also used in `onCreate()`, `onOptionsItemSelected()`, `onNavigationItemSelected()`, `onCreateHomeScreenShortcutCreate()`, `loadUrlFromTextBox()`, and `applyProxyThroughOrbot()`.
public static String formattedUrlString;
// `orbotStatus` is public static so it can be accessed from `OrbotProxyHelper`. It is also used in `onCreate()`, `onResume()`, and `applyProxyThroughOrbot()`.
public static String orbotStatus;
- // `webViewTitle` is public static so it can be accessed from `CreateBookmarkDialog`. It is also used in `onCreate()`.
- public static String webViewTitle;
-
// `appliedUserAgentString` is public static so it can be accessed from `ViewSourceActivity`. It is also used in `applyDomainSettings()`.
public static String appliedUserAgentString;
@Override
public void onPageSelected(int position) {
- // TODO. Consider using an array of the WebViews.
- // Get the current WebView fragment. Instantiate item returns the current item if it already exists.
- Fragment webViewFragment = (Fragment) webViewPagerAdapter.instantiateItem(webViewPager, position);
+ // Get the WebView tab fragment.
+ WebViewTabFragment webViewTabFragment = webViewPagerAdapter.webViewFragmentsList.get(position);
+
+ // Get the fragment view.
+ View fragmentView = webViewTabFragment.getView();
- // Remove the lint error below that the WebView fragment might be null.
- assert webViewFragment.getView() != null;
+ // Remove the incorrect lint warning below that the fragment view might be null.
+ assert fragmentView != null;
// Store the current WebView.
- currentWebView = webViewFragment.getView().findViewById(R.id.nestedscroll_webview);
+ currentWebView = fragmentView.findViewById(R.id.nestedscroll_webview);
// Store the current formatted URL string.
formattedUrlString = currentWebView.getUrl();
// Hide the soft keyboard.
inputMethodManager.hideSoftInputFromWindow(currentWebView.getWindowToken(), 0);
- // Apply the current URL in the URL text box.
+ // Display the current URL in the URL text box.
urlEditText.setText(formattedUrlString);
// Highlight the URL text.
// Set the launch bookmarks activity FAB to launch the bookmarks activity.
launchBookmarksActivityFab.setOnClickListener(v -> {
+ // Store the current WebView url and title in the bookmarks activity.
+ BookmarksActivity.currentWebViewUrl = currentWebView.getUrl();
+ BookmarksActivity.currentWebViewTitle = currentWebView.getTitle();
+
// Create an intent to launch the bookmarks activity.
Intent bookmarksIntent = new Intent(getApplicationContext(), BookmarksActivity.class);
// Set the create new bookmark FAB to display an alert dialog.
createBookmarkFab.setOnClickListener(view -> {
- // Show the create bookmark dialog and name the instance `@string/create_bookmark`.
- DialogFragment createBookmarkDialog = new CreateBookmarkDialog();
+ // Instantiate the create bookmark dialog.
+ DialogFragment createBookmarkDialog = CreateBookmarkDialog.createBookmark(currentWebView.getUrl(), currentWebView.getTitle(), favoriteIconBitmap);
+
+ // Display the create bookmark dialog.
createBookmarkDialog.show(fragmentManager, resources.getString(R.string.create_bookmark));
});
saveFormDataEnabled = false; // Form data can be removed once the minimum API >= 26.
nightMode = false;
+ // Inflate a bare WebView to get the default user agent. It is not used to render content on the screen.
+ @SuppressLint("InflateParams") View webViewLayout = getLayoutInflater().inflate(R.layout.bare_webview, null, false);
+
+ // Get a handle for the WebView.
+ WebView bareWebView = webViewLayout.findViewById(R.id.bare_webview);
+
// Store the default user agent.
- // TODO webViewDefaultUserAgent = mainWebView.getSettings().getUserAgentString();
+ webViewDefaultUserAgent = bareWebView.getSettings().getUserAgentString();
- // Initialize the WebView title.
- webViewTitle = getString(R.string.no_title);
+ // Destroy the bare WebView.
+ bareWebView.destroy();
// Initialize the favorite icon bitmap. `ContextCompat` must be used until API >= 21.
Drawable favoriteIconDrawable = ContextCompat.getDrawable(getApplicationContext(), R.drawable.world);
// Reload the webpage if displaying of images has been disabled in the Settings activity.
if (reloadOnRestart) {
// Reload the WebViews.
- // TODO
- currentWebView.reload();
+ for (int i = 0; i < webViewPagerAdapter.webViewFragmentsList.size(); i++) {
+ // Get the WebView tab fragment.
+ WebViewTabFragment webViewTabFragment = webViewPagerAdapter.webViewFragmentsList.get(i);
+
+ // Get the fragment view.
+ View fragmentView = webViewTabFragment.getView();
+
+ // Only reload the WebViews if they exist.
+ if (fragmentView != null) {
+ // Get the nested scroll WebView from the tab fragment.
+ NestedScrollWebView nestedScrollWebView = fragmentView.findViewById(R.id.nestedscroll_webview);
+
+ // TODO this doesn't seem to work if for WebViews that aren't visible.
+ // Reload the WebView.
+ nestedScrollWebView.reload();
+ }
+ }
// Reset `reloadOnRestartBoolean`.
reloadOnRestart = false;
// Run the default commands.
super.onResume();
- // Resume JavaScript (if enabled).
- // TODO mainWebView.resumeTimers();
+ for (int i = 0; i < webViewPagerAdapter.webViewFragmentsList.size(); i++) {
+ // Get the WebView tab fragment.
+ WebViewTabFragment webViewTabFragment = webViewPagerAdapter.webViewFragmentsList.get(i);
+
+ // Get the fragment view.
+ View fragmentView = webViewTabFragment.getView();
+
+ // Only resume the WebViews if they exist (they won't when the app is first created).
+ if (fragmentView != null) {
+ // Get the nested scroll WebView from the tab fragment.
+ NestedScrollWebView nestedScrollWebView = fragmentView.findViewById(R.id.nestedscroll_webview);
- // Resume `mainWebView`.
- // TODO mainWebView.onResume();
+ // Pause the nested scroll WebView JavaScript timers.
+ nestedScrollWebView.resumeTimers();
+
+ // Pause the nested scroll WebView.
+ nestedScrollWebView.onResume();
+ }
+ }
// Display a message to the user if waiting for Orbot.
if (waitingForOrbot && !orbotStatus.equals("ON")) {
// Run the default commands.
super.onPause();
- // Pause `mainWebView`.
- // TODO
- currentWebView.onPause();
+ for (int i = 0; i < webViewPagerAdapter.webViewFragmentsList.size(); i++) {
+ // Get the WebView tab fragment.
+ WebViewTabFragment webViewTabFragment = webViewPagerAdapter.webViewFragmentsList.get(i);
- // Stop all JavaScript.
- // TODO
- currentWebView.pauseTimers();
+ // Get the fragment view.
+ View fragmentView = webViewTabFragment.getView();
+
+ // Only pause the WebViews if they exist (they won't when the app is first created).
+ if (fragmentView != null) {
+ // Get the nested scroll WebView from the tab fragment.
+ NestedScrollWebView nestedScrollWebView = fragmentView.findViewById(R.id.nestedscroll_webview);
+
+ // Pause the nested scroll WebView.
+ nestedScrollWebView.onPause();
+
+ // Pause the nested scroll WebView JavaScript timers.
+ nestedScrollWebView.pauseTimers();
+ }
+ }
// Pause the ad or it will continue to consume resources in the background on the free flavor.
if (BuildConfig.FLAVOR.contentEquals("free")) {
ultraPrivacyMenuItem.setChecked(ultraPrivacyEnabled);
blockAllThirdPartyRequestsMenuItem.setChecked(blockAllThirdPartyRequests);
swipeToRefreshMenuItem.setChecked(swipeRefreshLayout.isEnabled());
- // TODO displayImagesMenuItem.setChecked(mainWebView.getSettings().getLoadsImagesAutomatically());
+ displayImagesMenuItem.setChecked(currentWebView.getSettings().getLoadsImagesAutomatically());
nightModeMenuItem.setChecked(nightMode);
proxyThroughOrbotMenuItem.setChecked(proxyThroughOrbot);
blockAllThirdPartyRequestsMenuItem.setTitle(thirdPartyBlockedRequests + " - " + getString(R.string.block_all_third_party_requests));
// Get the current user agent.
- // TODO String currentUserAgent = mainWebView.getSettings().getUserAgentString();
- String currentUserAgent = "";
+ String currentUserAgent = currentWebView.getSettings().getUserAgentString();
// Select the current user agent menu item. A switch statement cannot be used because the user agents are not compile time constants.
if (currentUserAgent.equals(getResources().getStringArray(R.array.user_agent_data)[0])) { // Privacy Browser.
}
// Initialize font size variables.
- // TODO int fontSize = mainWebView.getSettings().getTextZoom();
- int fontSize = 100;
+ int fontSize = currentWebView.getSettings().getTextZoom();
String fontSizeTitle;
MenuItem selectedFontSizeMenuItem;
case R.id.share_url:
// Setup the share string.
- String shareString = webViewTitle + " – " + formattedUrlString;
+ String shareString = currentWebView.getTitle() + " – " + formattedUrlString;
// Create the share intent.
Intent shareIntent = new Intent(Intent.ACTION_SEND);
customHeaders.remove("DNT");
}
- // Set the app bar scrolling.
- currentWebView.setNestedScrollingEnabled(sharedPreferences.getBoolean("scroll_app_bar", true));
+ // TODO this also needs to be set when creating a new tab.
+ // Set the app bar scrolling for each WebView.
+ for (int i = 0; i < webViewPagerAdapter.webViewFragmentsList.size(); i++) {
+ // Get the WebView tab fragment.
+ WebViewTabFragment webViewTabFragment = webViewPagerAdapter.webViewFragmentsList.get(i);
+
+ // Get the fragment view.
+ View fragmentView = webViewTabFragment.getView();
+
+ // Only modify the WebViews if they exist.
+ if (fragmentView != null) {
+ // Get the nested scroll WebView from the tab fragment.
+ NestedScrollWebView nestedScrollWebView = fragmentView.findViewById(R.id.nestedscroll_webview);
+
+ // Set the app bar scrolling.
+ nestedScrollWebView.setNestedScrollingEnabled(sharedPreferences.getBoolean("scroll_app_bar", true));
+ }
+ }
// Update the full screen browsing mode settings.
if (fullScreenBrowsingModeEnabled && inFullScreenBrowsingMode) { // Privacy Browser is currently in full screen browsing mode.
// Reset `waitingForOrbot.
waitingForOrbot = false;
- // Reload the website if requested.
+ // Reload the WebViews if requested.
if (reloadWebsite) {
- currentWebView.reload();
+ // Reload the WebViews.
+ for (int i = 0; i < webViewPagerAdapter.webViewFragmentsList.size(); i++) {
+ // Get the WebView tab fragment.
+ WebViewTabFragment webViewTabFragment = webViewPagerAdapter.webViewFragmentsList.get(i);
+
+ // Get the fragment view.
+ View fragmentView = webViewTabFragment.getView();
+
+ // Only reload the WebViews if they exist.
+ if (fragmentView != null) {
+ // Get the nested scroll WebView from the tab fragment.
+ NestedScrollWebView nestedScrollWebView = fragmentView.findViewById(R.id.nestedscroll_webview);
+
+ // Reload the WebView.
+ nestedScrollWebView.reload();
+ }
+ }
}
}
}
// Save a copy of the title when it changes.
@Override
public void onReceivedTitle(WebView view, String title) {
- // Save a copy of the title.
- // TODO. Replace `webViewTitle` with `currentWebView.getTitle()`.
- webViewTitle = title;
-
// Set the title as the tab text.
- tabTitleTextView.setText(webViewTitle);
+ tabTitleTextView.setText(title);
}
// Enter full screen video.