- // Consume the event.
- return true;
- });
-
- // Get the status bar pixel size.
- int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
- int statusBarPixelSize = getResources().getDimensionPixelSize(statusBarResourceId);
-
- // Get the resource density.
- float screenDensity = getResources().getDisplayMetrics().density;
-
- // Calculate the drawer header padding. This is used to move the text in the drawer headers below any cutouts.
- drawerHeaderPaddingLeftAndRight = (int) (15 * screenDensity);
- drawerHeaderPaddingTop = statusBarPixelSize + (int) (4 * screenDensity);
- drawerHeaderPaddingBottom = (int) (8 * screenDensity);
-
- // The drawer listener is used to update the navigation menu.`
- drawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() {
- @Override
- public void onDrawerSlide(@NonNull View drawerView, float slideOffset) {
- }
-
- @Override
- public void onDrawerOpened(@NonNull View drawerView) {
- }
-
- @Override
- public void onDrawerClosed(@NonNull View drawerView) {
- }
-
- @Override
- public void onDrawerStateChanged(int newState) {
- if ((newState == DrawerLayout.STATE_SETTLING) || (newState == DrawerLayout.STATE_DRAGGING)) { // A drawer is opening or closing.
- // Get handles for the drawer headers.
- TextView navigationHeaderTextView = findViewById(R.id.navigationText);
- TextView bookmarksHeaderTextView = findViewById(R.id.bookmarks_title_textview);
-
- // Apply the navigation header paddings if the view is not null (sometimes it is null if another activity has already started). This moves the text in the header below any cutouts.
- if (navigationHeaderTextView != null) {
- navigationHeaderTextView.setPadding(drawerHeaderPaddingLeftAndRight, drawerHeaderPaddingTop, drawerHeaderPaddingLeftAndRight, drawerHeaderPaddingBottom);
- }
-
- // Apply the bookmarks header paddings if the view is not null (sometimes it is null if another activity has already started). This moves the text in the header below any cutouts.
- if (bookmarksHeaderTextView != null) {
- bookmarksHeaderTextView.setPadding(drawerHeaderPaddingLeftAndRight, drawerHeaderPaddingTop, drawerHeaderPaddingLeftAndRight, drawerHeaderPaddingBottom);
- }
-
- // Update the navigation menu items.
- navigationCloseTabMenuItem.setEnabled(tabLayout.getTabCount() > 1);
- navigationBackMenuItem.setEnabled(currentWebView.canGoBack());
- navigationForwardMenuItem.setEnabled(currentWebView.canGoForward());
- navigationHistoryMenuItem.setEnabled((currentWebView.canGoBack() || currentWebView.canGoForward()));
- navigationRequestsMenuItem.setTitle(getString(R.string.requests) + " - " + currentWebView.getRequestsCount(NestedScrollWebView.BLOCKED_REQUESTS));
-
- // Hide the keyboard (if displayed).
- inputMethodManager.hideSoftInputFromWindow(currentWebView.getWindowToken(), 0);
-
- // Clear the focus from from the URL text box and the WebView. This removes any text selection markers and context menus, which otherwise draw above the open drawers.
- urlEditText.clearFocus();
- currentWebView.clearFocus();
- }
- }
- });
-
- // Create the hamburger icon at the start of the AppBar.
- actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.open_navigation_drawer, R.string.close_navigation_drawer);
-
- // Replace the header that `WebView` creates for `X-Requested-With` with a null value. The default value is the application ID (com.stoutner.privacybrowser.standard).
- customHeaders.put("X-Requested-With", "");
-
- // Initialize the default preference values the first time the program is run. `false` keeps this command from resetting any current preferences back to default.
- PreferenceManager.setDefaultValues(this, R.xml.preferences, 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.
- webViewDefaultUserAgent = bareWebView.getSettings().getUserAgentString();
-
- // Destroy the bare WebView.
- bareWebView.destroy();
- }
-
- @Override
- protected void onNewIntent(Intent intent) {
- // Get the information from the intent.
- String intentAction = intent.getAction();
- Uri intentUriData = intent.getData();
-
- // Only process the URI if it contains data. If the user pressed the desktop icon after the app was already running the URI will be null.
- if (intentUriData != null) {
- // Sets the new intent as the activity intent, which replaces the one that originally started the app.
- setIntent(intent);
-
- // Add a new tab.
- addTab(null);
-
- // Create a URL string.
- String url;
-
- // If the intent action is a web search, perform the search.
- if ((intentAction != null) && intentAction.equals(Intent.ACTION_WEB_SEARCH)) {
- // Create an encoded URL string.
- String encodedUrlString;
-
- // Sanitize the search input and convert it to a search.
- try {
- encodedUrlString = URLEncoder.encode(intent.getStringExtra(SearchManager.QUERY), "UTF-8");
- } catch (UnsupportedEncodingException exception) {
- encodedUrlString = "";
- }
-
- // Add the base search URL.
- url = searchURL + encodedUrlString;
- } else { // The intent should contain a URL.
- // Set the intent data as the URL.
- url = intentUriData.toString();
- }
-
- // Load the URL.
- loadUrl(url);
-
- // Get a handle for the drawer layout.
- DrawerLayout drawerLayout = findViewById(R.id.drawerlayout);
-
- // Close the navigation drawer if it is open.
- if (drawerLayout.isDrawerVisible(GravityCompat.START)) {
- drawerLayout.closeDrawer(GravityCompat.START);
- }
-
- // Close the bookmarks drawer if it is open.
- if (drawerLayout.isDrawerVisible(GravityCompat.END)) {
- drawerLayout.closeDrawer(GravityCompat.END);
- }
-
- // Clear the keyboard if displayed and remove the focus on the urlTextBar if it has it.
- currentWebView.requestFocus();
- }
- }
-
- @Override
- public void onRestart() {
- // Run the default commands.
- super.onRestart();
-
- // Make sure Orbot is running if Privacy Browser is proxying through Orbot.
- if (proxyThroughOrbot) {
- // Request Orbot to start. If Orbot is already running no hard will be caused by this request.
- Intent orbotIntent = new Intent("org.torproject.android.intent.action.START");
-
- // Send the intent to the Orbot package.
- orbotIntent.setPackage("org.torproject.android");
-
- // Make it so.
- sendBroadcast(orbotIntent);
- }
-
- // Apply the app settings if returning from the Settings activity.
- if (reapplyAppSettingsOnRestart) {
- // Reset the reapply app settings on restart tracker.
- reapplyAppSettingsOnRestart = false;
-
- // Apply the app settings.
- applyAppSettings();
- }
-
- // Apply the domain settings if returning from the settings or domains activity.
- if (reapplyDomainSettingsOnRestart) {
- // Reset the reapply domain settings on restart tracker.
- reapplyDomainSettingsOnRestart = false;
-
- // Reapply the domain settings for each tab.
- for (int i = 0; i < webViewPagerAdapter.getCount(); i++) {
- // Get the WebView tab fragment.
- WebViewTabFragment webViewTabFragment = webViewPagerAdapter.getPageFragment(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);
-
- // Reset the current domain name so the domain settings will be reapplied.
- nestedScrollWebView.resetCurrentDomainName();
-
- // Reapply the domain settings.
- applyDomainSettings(nestedScrollWebView, nestedScrollWebView.getUrl(), false, true);
- }
- }
- }
-
- // Load the URL on restart (used when loading a bookmark).
- if (loadUrlOnRestart) {
- // Load the specified URL.
- loadUrl(urlToLoadOnRestart);
-
- // Reset the load on restart tracker.
- loadUrlOnRestart = false;
- }
-
- // Update the bookmarks drawer if returning from the Bookmarks activity.
- if (restartFromBookmarksActivity) {
- // Get a handle for the drawer layout.
- DrawerLayout drawerLayout = findViewById(R.id.drawerlayout);
-
- // Close the bookmarks drawer.
- drawerLayout.closeDrawer(GravityCompat.END);
-
- // Reload the bookmarks drawer.
- loadBookmarksFolder();
-
- // Reset `restartFromBookmarksActivity`.
- restartFromBookmarksActivity = false;
- }
-
- // Update the privacy icon. `true` runs `invalidateOptionsMenu` as the last step. This can be important if the screen was rotated.
- updatePrivacyIcons(true);
- }
-
- // `onResume()` runs after `onStart()`, which runs after `onCreate()` and `onRestart()`.
- @Override
- public void onResume() {
- // Run the default commands.
- super.onResume();
-
- for (int i = 0; i < webViewPagerAdapter.getCount(); i++) {
- // Get the WebView tab fragment.
- WebViewTabFragment webViewTabFragment = webViewPagerAdapter.getPageFragment(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 the nested scroll WebView JavaScript timers.
- nestedScrollWebView.resumeTimers();
-
- // Resume the nested scroll WebView.
- nestedScrollWebView.onResume();
- }
- }
-
- // Display a message to the user if waiting for Orbot.
- if (waitingForOrbot && !orbotStatus.equals("ON")) {
- // Disable the wide view port so that the waiting for Orbot text is displayed correctly.
- currentWebView.getSettings().setUseWideViewPort(false);
-
- // Load a waiting page. `null` specifies no encoding, which defaults to ASCII.
- currentWebView.loadData("<html><body><br/><center><h1>" + getString(R.string.waiting_for_orbot) + "</h1></center></body></html>", "text/html", null);
- }
-
- if (displayingFullScreenVideo || inFullScreenBrowsingMode) {
- // Get a handle for the root frame layouts.
- FrameLayout rootFrameLayout = findViewById(R.id.root_framelayout);
-
- // 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 if (BuildConfig.FLAVOR.contentEquals("free")) { // Resume the adView for the free flavor.
- // Resume the ad.
- AdHelper.resumeAd(findViewById(R.id.adview));
- }
- }
-
- @Override
- public void onPause() {
- // Run the default commands.
- super.onPause();
-
- for (int i = 0; i < webViewPagerAdapter.getCount(); i++) {
- // Get the WebView tab fragment.
- WebViewTabFragment webViewTabFragment = webViewPagerAdapter.getPageFragment(i);
-
- // 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")) {
- // Pause the ad.
- AdHelper.pauseAd(findViewById(R.id.adview));
- }
- }
-
- @Override
- public void onDestroy() {
- // Unregister the Orbot status broadcast receiver.
- this.unregisterReceiver(orbotStatusBroadcastReceiver);
-
- // Close the bookmarks cursor and database.
- bookmarksCursor.close();
- bookmarksDatabaseHelper.close();
-
- // Run the default commands.
- super.onDestroy();
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- // Inflate the menu. This adds items to the action bar if it is present.
- getMenuInflater().inflate(R.menu.webview_options_menu, menu);
-
- // Store a handle for the options menu so it can be used by `onOptionsItemSelected()` and `updatePrivacyIcons()`.
- optionsMenu = menu;
-
- // Set the initial status of the privacy icons. `false` does not call `invalidateOptionsMenu` as the last step.
- updatePrivacyIcons(false);
-
- // Get handles for the menu items.
- MenuItem toggleFirstPartyCookiesMenuItem = menu.findItem(R.id.toggle_first_party_cookies);
- MenuItem toggleThirdPartyCookiesMenuItem = menu.findItem(R.id.toggle_third_party_cookies);
- MenuItem toggleDomStorageMenuItem = menu.findItem(R.id.toggle_dom_storage);
- MenuItem toggleSaveFormDataMenuItem = menu.findItem(R.id.toggle_save_form_data); // Form data can be removed once the minimum API >= 26.
- MenuItem clearFormDataMenuItem = menu.findItem(R.id.clear_form_data); // Form data can be removed once the minimum API >= 26.
- MenuItem refreshMenuItem = menu.findItem(R.id.refresh);
- MenuItem adConsentMenuItem = menu.findItem(R.id.ad_consent);
-
- // Only display third-party cookies if API >= 21
- toggleThirdPartyCookiesMenuItem.setVisible(Build.VERSION.SDK_INT >= 21);
-
- // Only display the form data menu items if the API < 26.
- toggleSaveFormDataMenuItem.setVisible(Build.VERSION.SDK_INT < 26);
- clearFormDataMenuItem.setVisible(Build.VERSION.SDK_INT < 26);
-
- // Disable the clear form data menu item if the API >= 26 so that the status of the main Clear Data is calculated correctly.
- clearFormDataMenuItem.setEnabled(Build.VERSION.SDK_INT < 26);
-
- // Only show Ad Consent if this is the free flavor.
- adConsentMenuItem.setVisible(BuildConfig.FLAVOR.contentEquals("free"));
-
- // Get the shared preference values.
- SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
-
- // Get the dark theme and app bar preferences..
- boolean displayAdditionalAppBarIcons = sharedPreferences.getBoolean("display_additional_app_bar_icons", false);
- boolean darkTheme = sharedPreferences.getBoolean("dark_theme", false);
-
- // Set the status of the additional app bar icons. Setting the refresh menu item to `SHOW_AS_ACTION_ALWAYS` makes it appear even on small devices like phones.
- if (displayAdditionalAppBarIcons) {
- toggleFirstPartyCookiesMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
- toggleDomStorageMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
- refreshMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
- } else { //Do not display the additional icons.
- toggleFirstPartyCookiesMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
- toggleDomStorageMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
- refreshMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
- }
-
- // Replace Refresh with Stop if a URL is already loading.
- if (currentWebView != null && currentWebView.getProgress() != 100) {
- // Set the title.
- refreshMenuItem.setTitle(R.string.stop);
-
- // If the icon is displayed in the AppBar, set it according to the theme.
- if (displayAdditionalAppBarIcons) {
- if (darkTheme) {
- refreshMenuItem.setIcon(R.drawable.close_dark);
- } else {
- refreshMenuItem.setIcon(R.drawable.close_light);
- }
- }
- }
-