- // 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();
-
- // Create a favorite icon byte array output stream.
- ByteArrayOutputStream favoriteIconByteArrayOutputStream = new ByteArrayOutputStream();
-
- // Convert the favorite icon bitmap to a byte array. `0` is for lossless compression (the only option for a PNG).
- favoriteIconBitmap.compress(Bitmap.CompressFormat.PNG, 0, favoriteIconByteArrayOutputStream);
-
- // Convert the favorite icon byte array stream to a byte array.
- byte[] favoriteIconByteArray = favoriteIconByteArrayOutputStream.toByteArray();
-
- // Create an intent to launch the bookmarks activity.
- Intent bookmarksIntent = new Intent(getApplicationContext(), BookmarksActivity.class);
-
- // Add the extra information to the intent.
- bookmarksIntent.putExtra("current_url", currentWebView.getUrl());
- bookmarksIntent.putExtra("current_title", currentWebView.getTitle());
- bookmarksIntent.putExtra("current_folder", currentBookmarksFolder);
- bookmarksIntent.putExtra("favorite_icon_byte_array", favoriteIconByteArray);
-
- // Make it so.
- startActivity(bookmarksIntent);
- });
-
- // 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());
-
- // 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());
-
- // Display the create bookmark dialog.
- createBookmarkDialog.show(getSupportFragmentManager(), getString(R.string.create_bookmark));
- });
-
- // Search for the string on the page whenever a character changes in the `findOnPageEditText`.
- findOnPageEditText.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- // Do nothing.
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- // Do nothing.
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- // Search for the text in the WebView if it is not null. Sometimes on resume after a period of non-use the WebView will be null.
- if (currentWebView != null) {
- currentWebView.findAllAsync(findOnPageEditText.getText().toString());
- }
- }
- });
-
- // Set the `check mark` button for the `findOnPageEditText` keyboard to close the soft keyboard.
- findOnPageEditText.setOnKeyListener((v, keyCode, event) -> {
- if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) { // The `enter` key was pressed.
- // Hide the soft keyboard.
- inputMethodManager.hideSoftInputFromWindow(currentWebView.getWindowToken(), 0);
-
- // Consume the event.
- return true;
- } else { // A different key was pressed.
- // Do not consume the event.
- return false;
- }
- });
-
- // Implement swipe to refresh.
- swipeRefreshLayout.setOnRefreshListener(() -> currentWebView.reload());
-
- // Store the default progress view offsets for use later in `initializeWebView()`.
- defaultProgressViewStartOffset = swipeRefreshLayout.getProgressViewStartOffset();
- defaultProgressViewEndOffset = swipeRefreshLayout.getProgressViewEndOffset();
-
- // Set the swipe to refresh color according to the theme.
- if (darkTheme) {
- swipeRefreshLayout.setColorSchemeResources(R.color.blue_800);
- swipeRefreshLayout.setProgressBackgroundColorSchemeResource(R.color.gray_850);
- } else {
- swipeRefreshLayout.setColorSchemeResources(R.color.blue_500);
- }
-
- // `DrawerTitle` identifies the `DrawerLayouts` in accessibility mode.
- drawerLayout.setDrawerTitle(GravityCompat.START, getString(R.string.navigation_drawer));
- drawerLayout.setDrawerTitle(GravityCompat.END, getString(R.string.bookmarks));
-
- // Initialize the bookmarks database helper. The `0` specifies a database version, but that is ignored and set instead using a constant in `BookmarksDatabaseHelper`.
- bookmarksDatabaseHelper = new BookmarksDatabaseHelper(this, null, null, 0);
-
- // Initialize `currentBookmarksFolder`. `""` is the home folder in the database.
- currentBookmarksFolder = "";
-
- // Load the home folder, which is `""` in the database.
- loadBookmarksFolder();
-
- 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;
-
- // Get the bookmark cursor for this ID and move it to the first row.
- Cursor bookmarkCursor = bookmarksDatabaseHelper.getBookmark(databaseID);
- bookmarkCursor.moveToFirst();
-
- // Act upon the bookmark according to the type.
- if (bookmarkCursor.getInt(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.IS_FOLDER)) == 1) { // The selected bookmark is a folder.
- // Store the new folder name in `currentBookmarksFolder`.
- currentBookmarksFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
-
- // Load the new folder.
- loadBookmarksFolder();
- } else { // The selected bookmark is not a folder.
- // Load the bookmark URL.
- loadUrl(bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_URL)));
-
- // Close the bookmarks drawer.
- drawerLayout.closeDrawer(GravityCompat.END);
- }
-
- // Close the `Cursor`.
- bookmarkCursor.close();
- });
-
- bookmarksListView.setOnItemLongClickListener((parent, view, position, id) -> {
- // Convert the database ID from `long` to `int`.
- int databaseId = (int) id;
-
- // Find out if the selected bookmark is a folder.
- boolean isFolder = bookmarksDatabaseHelper.isFolder(databaseId);
-
- if (isFolder) {
- // 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`.
- DialogFragment editBookmarkFolderDialog = EditBookmarkFolderDialog.folderDatabaseId(databaseId, currentWebView.getFavoriteOrDefaultIcon());
- 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));
- }
-
- // 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);
-
- // Get the shared preferences.
- SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
-
- // Add a new tab if specified in the preferences.
- if (sharedPreferences.getBoolean("open_intents_in_new_tab", true)) {
- // Set the loading new intent flag.
- loadingNewIntent = true;
-
- // 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;