</value>
</option>
</JavaCodeStyleSettings>
- <Objective-C-extensions>
- <file>
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
- </file>
- <class>
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
- <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
- </class>
- <extensions>
- <pair source="cpp" header="h" fileNamingConvention="NONE" />
- <pair source="c" header="h" fileNamingConvention="NONE" />
- </extensions>
- </Objective-C-extensions>
<XML>
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
</XML>
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
+import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
import com.stoutner.privacybrowser.R;
-import com.stoutner.privacybrowser.activities.MainWebViewActivity;
import com.stoutner.privacybrowser.helpers.AdConsentDatabaseHelper;
import com.stoutner.privacybrowser.helpers.AdHelper;
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
+ // Get a handle for the shared preferences.
+ SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getContext());
+
+ // Get the screenshot and theme preferences.
+ boolean darkTheme = sharedPreferences.getBoolean("dark_theme", false);
+ boolean allowScreenshots = sharedPreferences.getBoolean("allow_screenshots", false);
+
// Use a builder to create the alert dialog.
AlertDialog.Builder dialogBuilder;
// Set the style and the icon according to the theme.
- if (MainWebViewActivity.darkTheme) {
+ if (darkTheme) {
dialogBuilder = new AlertDialog.Builder(getActivity(), R.style.PrivacyBrowserAlertDialogDark);
dialogBuilder.setIcon(R.drawable.block_ads_enabled_dark);
} else {
AdHelper.loadAd(getActivity().findViewById(R.id.adview), getActivity().getApplicationContext(), getString(R.string.ad_unit_id));
});
+ // Create an alert dialog from the alert dialog builder.
+ AlertDialog alertDialog = dialogBuilder.create();
+
+ // Disable screenshots if not allowed.
+ if (!allowScreenshots) {
+ // Remove the warning below that `getWindow()` might be null.
+ assert alertDialog.getWindow() != null;
+
+ // Disable screenshots.
+ alertDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
+ }
+
// Return the alert dialog.
- return dialogBuilder.create();
+ return alertDialog;
}
// Close Privacy Browser Free if the dialog is cancelled without selecting a button (by tapping on the background).
package com.stoutner.privacybrowser.activities;
+import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
-import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentManager;
-import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout;
-import com.stoutner.privacybrowser.fragments.AboutTabFragment;
+import com.stoutner.privacybrowser.adapters.AboutPagerAdapter;
import com.stoutner.privacybrowser.R;
public class AboutActivity extends AppCompatActivity {
// Run the default commands.
super.onCreate(savedInstanceState);
+ // Get the intent that launched the activity.
+ Intent launchingIntent = getIntent();
+
+ // Store the blocklist versions.
+ String[] blocklistVersions = launchingIntent.getStringArrayExtra("blocklist_versions");
+
// Set the content view.
setContentView(R.layout.about_coordinatorlayout);
actionBar.setDisplayHomeAsUpEnabled(true);
// Setup the ViewPager.
- aboutViewPager.setAdapter(new AboutPagerAdapter(getSupportFragmentManager()));
+ aboutViewPager.setAdapter(new AboutPagerAdapter(getSupportFragmentManager(), getApplicationContext(), blocklistVersions));
// Connect the tab layout to the view pager.
aboutTabLayout.setupWithViewPager(aboutViewPager);
}
-
- private class AboutPagerAdapter extends FragmentPagerAdapter {
- private AboutPagerAdapter(FragmentManager fragmentManager) {
- // Run the default commands.
- super(fragmentManager);
- }
-
- @Override
- // Get the count of the number of tabs.
- public int getCount() {
- return 7;
- }
-
- @Override
- // Get the name of each tab. Tab numbers start at 0.
- public CharSequence getPageTitle(int tab) {
- switch (tab) {
- case 0:
- return getString(R.string.version);
-
- case 1:
- return getString(R.string.permissions);
-
- case 2:
- return getString(R.string.privacy_policy);
-
- case 3:
- return getString(R.string.changelog);
-
- case 4:
- return getString(R.string.licenses);
-
- case 5:
- return getString(R.string.contributors);
-
- case 6:
- return getString(R.string.links);
-
- default:
- return "";
- }
- }
-
- @Override
- // Setup each tab.
- public Fragment getItem(int tab) {
- return AboutTabFragment.createTab(tab);
- }
- }
-}
+}
\ No newline at end of file
@SuppressLint("SwitchIntDef") // Ignore the lint warning about not handling the other possible events as they are covered by `default:`.
@Override
public void onDismissed(Snackbar snackbar, int event) {
- switch (event) {
- // The user pushed the `Undo` button.
- case Snackbar.Callback.DISMISS_EVENT_ACTION:
- // Update the bookmarks cursor with the current contents of the bookmarks database, including the "deleted" bookmarks.
- bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrder(currentFolder);
-
- // Update the list view.
- bookmarksCursorAdapter.changeCursor(bookmarksCursor);
-
- // Re-select the previously selected bookmarks.
- for (int i = 0; i < selectedBookmarksPositionsSparseBooleanArray.size(); i++) {
- bookmarksListView.setItemChecked(selectedBookmarksPositionsSparseBooleanArray.keyAt(i), true);
- }
- break;
-
- // The Snackbar was dismissed without the `Undo` button being pushed.
- default:
- // Delete each selected bookmark.
- for (long databaseIdLong : selectedBookmarksIdsLongArray) {
- // Convert `databaseIdLong` to an int.
- int databaseIdInt = (int) databaseIdLong;
-
- // Delete the contents of the folder if the selected bookmark is a folder.
- if (bookmarksDatabaseHelper.isFolder(databaseIdInt)) {
- deleteBookmarkFolderContents(databaseIdInt);
- }
-
- // Delete the selected bookmark.
- bookmarksDatabaseHelper.deleteBookmark(databaseIdInt);
+ if (event == Snackbar.Callback.DISMISS_EVENT_ACTION) { // The user pushed the undo button.
+ // Update the bookmarks cursor with the current contents of the bookmarks database, including the "deleted" bookmarks.
+ bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrder(currentFolder);
+
+ // Update the list view.
+ bookmarksCursorAdapter.changeCursor(bookmarksCursor);
+
+ // Re-select the previously selected bookmarks.
+ for (int i = 0; i < selectedBookmarksPositionsSparseBooleanArray.size(); i++) {
+ bookmarksListView.setItemChecked(selectedBookmarksPositionsSparseBooleanArray.keyAt(i), true);
+ }
+ } else { // The snackbar was dismissed without the undo button being pushed.
+ // Delete each selected bookmark.
+ for (long databaseIdLong : selectedBookmarksIdsLongArray) {
+ // Convert `databaseIdLong` to an int.
+ int databaseIdInt = (int) databaseIdLong;
+
+ // Delete the contents of the folder if the selected bookmark is a folder.
+ if (bookmarksDatabaseHelper.isFolder(databaseIdInt)) {
+ deleteBookmarkFolderContents(databaseIdInt);
}
- // Update the display order.
- for (int i = 0; i < bookmarksListView.getCount(); i++) {
- // Get the database ID for the current bookmark.
- int currentBookmarkDatabaseId = (int) bookmarksListView.getItemIdAtPosition(i);
+ // Delete the selected bookmark.
+ bookmarksDatabaseHelper.deleteBookmark(databaseIdInt);
+ }
+
+ // Update the display order.
+ for (int i = 0; i < bookmarksListView.getCount(); i++) {
+ // Get the database ID for the current bookmark.
+ int currentBookmarkDatabaseId = (int) bookmarksListView.getItemIdAtPosition(i);
- // Move `bookmarksCursor` to the current bookmark position.
- bookmarksCursor.moveToPosition(i);
+ // Move `bookmarksCursor` to the current bookmark position.
+ bookmarksCursor.moveToPosition(i);
- // Update the display order only if it is not correct in the database.
- if (bookmarksCursor.getInt(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.DISPLAY_ORDER)) != i) {
- bookmarksDatabaseHelper.updateDisplayOrder(currentBookmarkDatabaseId, i);
- }
+ // Update the display order only if it is not correct in the database.
+ if (bookmarksCursor.getInt(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.DISPLAY_ORDER)) != i) {
+ bookmarksDatabaseHelper.updateDisplayOrder(currentBookmarkDatabaseId, i);
}
+ }
}
// Reset the deleting bookmarks flag.
// TODO. Store up reloads for tabs that are not visible.
// TODO. New tabs are white in dark mode.
// TODO. Hide the tabs in full screen mode.
+// TODO. Find on page.
+// TODO. Use TabLayout.setScrollPosition to scroll to new tabs.
// 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, HttpAuthenticationDialog.HttpAuthenticationListener, NavigationView.OnNavigationItemSelectedListener, WebViewTabFragment.NewTabListener,
- PinnedMismatchDialog.PinnedMismatchListener, SslCertificateErrorDialog.SslCertificateErrorListener, UrlHistoryDialog.UrlHistoryListener {
+ EditBookmarkFolderDialog.EditBookmarkFolderListener, NavigationView.OnNavigationItemSelectedListener, WebViewTabFragment.NewTabListener, PinnedMismatchDialog.PinnedMismatchListener,
+ UrlHistoryDialog.UrlHistoryListener {
// `orbotStatus` is public static so it can be accessed from `OrbotProxyHelper`. It is also used in `onCreate()`, `onResume()`, and `applyProxyThroughOrbot()`.
public static String orbotStatus;
- // The WebView pager adapter is accessed from `PinnedMismatchDialog`. It is also used in `onCreate()`, `onResume()`, and `addTab()`.
+ // The WebView pager adapter is accessed from `HttpAuthenticationDialog`, `PinnedMismatchDialog`, and `SslCertificateErrorDialog`. It is also used in `onCreate()`, `onResume()`, and `addTab()`.
public static WebViewPagerAdapter webViewPagerAdapter;
// `reloadOnRestart` is public static so it can be accessed from `SettingsFragment`. It is used in `onRestart()`
// `restartFromBookmarksActivity` is public static so it can be accessed from `BookmarksActivity`. It is also used in `onRestart()`.
public static boolean restartFromBookmarksActivity;
- // The blocklist versions are public static so they can be accessed from `AboutTabFragment`. They are also used in `onCreate()`. // TODO.
- public static String easyListVersion;
- public static String easyPrivacyVersion;
- public static String fanboysAnnoyanceVersion;
- public static String fanboysSocialVersion;
- public static String ultraPrivacyVersion;
-
// `currentBookmarksFolder` is public static so it can be accessed from `BookmarksActivity`. It is also used in `onCreate()`, `onBackPressed()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`,
// `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, and `loadBookmarksFolder()`.
public static String currentBookmarksFolder;
- // `navigatingHistory` is used in `onCreate()`, `onNavigationItemSelected()`, `onSslMismatchBack()`, and `applyDomainSettings()`.
- private boolean navigatingHistory; // TODO.
-
// The current WebView is used in `onCreate()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, `onNavigationItemSelected()`, `onRestart()`, `onCreateContextMenu()`, `findPreviousOnPage()`,
// `findNextOnPage()`, `closeFindOnPage()`, `loadUrlFromTextBox()`, `onSslMismatchBack()`, `applyProxyThroughOrbot()`, and `applyDomainSettings()`.
private NestedScrollWebView currentWebView;
// The options menu is set in `onCreateOptionsMenu()` and used in `onOptionsItemSelected()`, `updatePrivacyIcons()`, and `initializeWebView()`.
private Menu optionsMenu;
- // TODO. This could probably be removed.
- // The blocklist helper is used in `onCreate()` and `WebViewPagerAdapter`.
- private BlockListHelper blockListHelper;
-
- // The blocklists are populated in `onCreate()` and accessed from `WebViewPagerAdapter`.
+ // The blocklists are populated in `onCreate()` and accessed from `initializeWebView()`.
private ArrayList<List<String[]>> easyList;
private ArrayList<List<String[]>> easyPrivacy;
private ArrayList<List<String[]>> fanboysAnnoyanceList;
private ArrayList<List<String[]>> fanboysSocialList;
private ArrayList<List<String[]>> ultraPrivacy;
- // The blocklist menu items are used in `onCreateOptionsMenu()`, `onPrepareOptionsMenu()`, and `initializeWebView()`. // TODO.
- private MenuItem blocklistsMenuItem;
- private MenuItem easyListMenuItem;
- private MenuItem easyPrivacyMenuItem;
- private MenuItem fanboysAnnoyanceListMenuItem;
- private MenuItem fanboysSocialBlockingListMenuItem;
- private MenuItem ultraPrivacyMenuItem;
- private MenuItem blockAllThirdPartyRequestsMenuItem;
-
// `webViewDefaultUserAgent` is used in `onCreate()` and `onPrepareOptionsMenu()`.
private String webViewDefaultUserAgent;
// `proxyThroughOrbot` is used in `onRestart()`, `onOptionsItemSelected()`, `applyAppSettings()`, and `applyProxyThroughOrbot()`.
private boolean proxyThroughOrbot;
- // `incognitoModeEnabled` is used in `onCreate()` and `applyAppSettings()`.
- private boolean incognitoModeEnabled; // TODO.
+ // The incognito mode is set in `applyAppSettings()` and used in `initializeWebView()`.
+ private boolean incognitoModeEnabled;
- // `fullScreenBrowsingModeEnabled` is used in `onCreate()` and `applyAppSettings()`.
- private boolean fullScreenBrowsingModeEnabled; // TODO.
+ // The full screen browsing mode tracker is set it `applyAppSettings()` and used in `initializeWebView()`.
+ private boolean fullScreenBrowsingModeEnabled;
// `inFullScreenBrowsingMode` is used in `onCreate()`, `onConfigurationChanged()`, and `applyAppSettings()`.
private boolean inFullScreenBrowsingMode;
- // Hide app bar is used in `onCreate()` and `applyAppSettings()`.
- private boolean hideAppBar; // TODO.
+ // Hide app bar is used in `applyAppSettings()` and `initializeWebView()`.
+ private boolean hideAppBar;
// `reapplyDomainSettingsOnRestart` is used in `onCreate()`, `onOptionsItemSelected()`, `onNavigationItemSelected()`, `onRestart()`, and `onAddDomain()`, .
private boolean reapplyDomainSettingsOnRestart;
// `displayingFullScreenVideo` is used in `onCreate()` and `onResume()`.
private boolean displayingFullScreenVideo;
- // `downloadWithExternalApp` is used in `onCreate()`, `onCreateContextMenu()`, and `applyDomainSettings()`.
- private boolean downloadWithExternalApp; // TODO.
-
// `orbotStatusBroadcastReceiver` is used in `onCreate()` and `onDestroy()`.
private BroadcastReceiver orbotStatusBroadcastReceiver;
// `waitingForOrbot` is used in `onCreate()`, `onResume()`, and `applyProxyThroughOrbot()`.
private boolean waitingForOrbot;
- // `domainSettingsJavaScriptEnabled` is used in `onOptionsItemSelected()` and `applyDomainSettings()`.
- private Boolean domainSettingsJavaScriptEnabled; // TODO.
-
- // `waitingForOrbotHtmlString` is used in `onCreate()` and `applyProxyThroughOrbot()`.
- private String waitingForOrbotHtmlString; // TODO.
-
- // `privateDataDirectoryString` is used in `onCreate()`, `onOptionsItemSelected()`, and `onNavigationItemSelected()`.
- private String privateDataDirectoryString; // TODO.
-
// The action bar drawer toggle is initialized in `onCreate()` and used in `onResume()`.
private ActionBarDrawerToggle actionBarDrawerToggle;
private int drawerHeaderPaddingTop;
private int drawerHeaderPaddingBottom;
- // `sslErrorHandler` is used in `onCreate()`, `onSslErrorCancel()`, and `onSslErrorProceed`.
- private SslErrorHandler sslErrorHandler; // TODO.
-
- // `httpAuthHandler` is used in `onCreate()`, `onHttpAuthenticationCancel()`, and `onHttpAuthenticationProceed()`.
- private static HttpAuthHandler httpAuthHandler; // TODO.
-
// `bookmarksDatabaseHelper` is used in `onCreate()`, `onDestroy`, `onOptionsItemSelected()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`,
// and `loadBookmarksFolder()`.
private BookmarksDatabaseHelper bookmarksDatabaseHelper;
}
});
- // Set `waitingForOrbotHTMLString`.
- waitingForOrbotHtmlString = "<html><body><br/><center><h1>" + getString(R.string.waiting_for_orbot) + "</h1></center></body></html>";
-
// Initialize the Orbot status and the waiting for Orbot trackers.
orbotStatus = "unknown";
waitingForOrbot = false;
// Register `orbotStatusBroadcastReceiver` on `this` context.
this.registerReceiver(orbotStatusBroadcastReceiver, new IntentFilter("org.torproject.android.intent.action.STATUS"));
- // Instantiate the block list helper.
- blockListHelper = new BlockListHelper();
+ // Instantiate the blocklist helper.
+ BlockListHelper blockListHelper = new BlockListHelper();
// Parse the block lists.
easyList = blockListHelper.parseBlockList(getAssets(), "blocklists/easylist.txt");
fanboysSocialList = blockListHelper.parseBlockList(getAssets(), "blocklists/fanboy-social.txt");
ultraPrivacy = blockListHelper.parseBlockList(getAssets(), "blocklists/ultraprivacy.txt");
- // Store the list versions.
- easyListVersion = easyList.get(0).get(0)[0];
- easyPrivacyVersion = easyPrivacy.get(0).get(0)[0];
- fanboysAnnoyanceVersion = fanboysAnnoyanceList.get(0).get(0)[0];
- fanboysSocialVersion = fanboysSocialList.get(0).get(0)[0];
- ultraPrivacyVersion = ultraPrivacy.get(0).get(0)[0];
-
// Get handles for views that need to be modified.
DrawerLayout drawerLayout = findViewById(R.id.drawerlayout);
NavigationView navigationView = findViewById(R.id.navigationview);
// 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);
- // Store the application's private data directory.
- privateDataDirectoryString = getApplicationInfo().dataDir;
- // `dataDir` will vary, but will be something like `/data/user/0/com.stoutner.privacybrowser.standard`, which links to `/data/data/com.stoutner.privacybrowser.standard`.
-
- // Initialize `inFullScreenBrowsingMode`, which is always false at this point because Privacy Browser never starts in full screen browsing mode.
- inFullScreenBrowsingMode = 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);
currentWebView.getSettings().setUseWideViewPort(false);
// Load a waiting page. `null` specifies no encoding, which defaults to ASCII.
- currentWebView.loadData(waitingForOrbotHtmlString, "text/html", null);
+ currentWebView.loadData("<html><body><br/><center><h1>" + getString(R.string.waiting_for_orbot) + "</h1></center></body></html>", "text/html", null);
}
if (displayingFullScreenVideo || inFullScreenBrowsingMode) {
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);
- blocklistsMenuItem = menu.findItem(R.id.blocklists);
- easyListMenuItem = menu.findItem(R.id.easylist);
- easyPrivacyMenuItem = menu.findItem(R.id.easyprivacy);
- fanboysAnnoyanceListMenuItem = menu.findItem(R.id.fanboys_annoyance_list);
- fanboysSocialBlockingListMenuItem = menu.findItem(R.id.fanboys_social_blocking_list);
- ultraPrivacyMenuItem = menu.findItem(R.id.ultraprivacy);
- blockAllThirdPartyRequestsMenuItem = menu.findItem(R.id.block_all_third_party_requests);
MenuItem adConsentMenuItem = menu.findItem(R.id.ad_consent);
// Only display third-party cookies if API >= 21
MenuItem clearCookiesMenuItem = menu.findItem(R.id.clear_cookies);
MenuItem clearDOMStorageMenuItem = menu.findItem(R.id.clear_dom_storage);
MenuItem clearFormDataMenuItem = menu.findItem(R.id.clear_form_data); // Form data can be removed once the minimum API >= 26.
+ MenuItem blocklistsMenuItem = menu.findItem(R.id.blocklists);
+ MenuItem easyListMenuItem = menu.findItem(R.id.easylist);
+ MenuItem easyPrivacyMenuItem = menu.findItem(R.id.easyprivacy);
+ MenuItem fanboysAnnoyanceListMenuItem = menu.findItem(R.id.fanboys_annoyance_list);
+ MenuItem fanboysSocialBlockingListMenuItem = menu.findItem(R.id.fanboys_social_blocking_list);
+ MenuItem ultraPrivacyMenuItem = menu.findItem(R.id.ultraprivacy);
+ MenuItem blockAllThirdPartyRequestsMenuItem = menu.findItem(R.id.block_all_third_party_requests);
MenuItem fontSizeMenuItem = menu.findItem(R.id.font_size);
MenuItem swipeToRefreshMenuItem = menu.findItem(R.id.swipe_to_refresh);
MenuItem displayImagesMenuItem = menu.findItem(R.id.display_images);
// Enable Clear Cookies if there are any.
clearCookiesMenuItem.setEnabled(cookieManager.hasCookies());
+ // Get the application's private data directory, which will be something like `/data/user/0/com.stoutner.privacybrowser.standard`, which links to `/data/data/com.stoutner.privacybrowser.standard`.
+ String privateDataDirectoryString = getApplicationInfo().dataDir;
+
// Get a count of the number of files in the Local Storage directory.
File localStorageDirectory = new File (privateDataDirectoryString + "/app_webview/Local Storage/");
int localStorageDirectoryNumberOfFiles = 0;
@SuppressLint("SwitchIntDef") // Ignore the lint warning about not handling the other possible events as they are covered by `default:`.
@Override
public void onDismissed(Snackbar snackbar, int event) {
- switch (event) {
- // The user pushed the undo button.
- case Snackbar.Callback.DISMISS_EVENT_ACTION:
- // Do nothing.
- break;
-
- // The snackbar was dismissed without the undo button being pushed.
- default:
- // `cookieManager.removeAllCookie()` varies by SDK.
- if (Build.VERSION.SDK_INT < 21) {
- cookieManager.removeAllCookie();
- } else {
- cookieManager.removeAllCookies(null);
- }
+ if (event != Snackbar.Callback.DISMISS_EVENT_ACTION) { // The snackbar was dismissed without the undo button being pushed.
+ // Delete the cookies, which command varies by SDK.
+ if (Build.VERSION.SDK_INT < 21) {
+ cookieManager.removeAllCookie();
+ } else {
+ cookieManager.removeAllCookies(null);
+ }
}
}
})
@SuppressLint("SwitchIntDef") // Ignore the lint warning about not handling the other possible events as they are covered by `default:`.
@Override
public void onDismissed(Snackbar snackbar, int event) {
- switch (event) {
- // The user pushed the undo button.
- case Snackbar.Callback.DISMISS_EVENT_ACTION:
- // Do nothing.
- break;
-
- // The snackbar was dismissed without the undo button being pushed.
- default:
- // Delete the DOM Storage.
- WebStorage webStorage = WebStorage.getInstance();
- webStorage.deleteAllData();
-
- // Initialize a handler to manually delete the DOM storage files and directories.
- Handler deleteDomStorageHandler = new Handler();
-
- // Setup a runnable to manually delete the DOM storage files and directories.
- Runnable deleteDomStorageRunnable = () -> {
- try {
- // Get a handle for the runtime.
- Runtime runtime = Runtime.getRuntime();
-
- // A string array must be used because the directory contains a space and `Runtime.exec` will otherwise not escape the string correctly.
- Process deleteLocalStorageProcess = runtime.exec(new String[]{"rm", "-rf", privateDataDirectoryString + "/app_webview/Local Storage/"});
-
- // Multiple commands must be used because `Runtime.exec()` does not like `*`.
- Process deleteIndexProcess = runtime.exec("rm -rf " + privateDataDirectoryString + "/app_webview/IndexedDB");
- Process deleteQuotaManagerProcess = runtime.exec("rm -f " + privateDataDirectoryString + "/app_webview/QuotaManager");
- Process deleteQuotaManagerJournalProcess = runtime.exec("rm -f " + privateDataDirectoryString + "/app_webview/QuotaManager-journal");
- Process deleteDatabasesProcess = runtime.exec("rm -rf " + privateDataDirectoryString + "/app_webview/databases");
-
- // Wait for the processes to finish.
- deleteLocalStorageProcess.waitFor();
- deleteIndexProcess.waitFor();
- deleteQuotaManagerProcess.waitFor();
- deleteQuotaManagerJournalProcess.waitFor();
- deleteDatabasesProcess.waitFor();
- } catch (Exception exception) {
- // Do nothing if an error is thrown.
- }
- };
-
- // Manually delete the DOM storage files after 200 milliseconds.
- deleteDomStorageHandler.postDelayed(deleteDomStorageRunnable, 200);
+ if (event != Snackbar.Callback.DISMISS_EVENT_ACTION) { // The snackbar was dismissed without the undo button being pushed.
+ // Delete the DOM Storage.
+ WebStorage webStorage = WebStorage.getInstance();
+ webStorage.deleteAllData();
+
+ // Initialize a handler to manually delete the DOM storage files and directories.
+ Handler deleteDomStorageHandler = new Handler();
+
+ // Setup a runnable to manually delete the DOM storage files and directories.
+ Runnable deleteDomStorageRunnable = () -> {
+ try {
+ // Get a handle for the runtime.
+ Runtime runtime = Runtime.getRuntime();
+
+ // Get the application's private data directory, which will be something like `/data/user/0/com.stoutner.privacybrowser.standard`,
+ // which links to `/data/data/com.stoutner.privacybrowser.standard`.
+ String privateDataDirectoryString = getApplicationInfo().dataDir;
+
+ // A string array must be used because the directory contains a space and `Runtime.exec` will otherwise not escape the string correctly.
+ Process deleteLocalStorageProcess = runtime.exec(new String[]{"rm", "-rf", privateDataDirectoryString + "/app_webview/Local Storage/"});
+
+ // Multiple commands must be used because `Runtime.exec()` does not like `*`.
+ Process deleteIndexProcess = runtime.exec("rm -rf " + privateDataDirectoryString + "/app_webview/IndexedDB");
+ Process deleteQuotaManagerProcess = runtime.exec("rm -f " + privateDataDirectoryString + "/app_webview/QuotaManager");
+ Process deleteQuotaManagerJournalProcess = runtime.exec("rm -f " + privateDataDirectoryString + "/app_webview/QuotaManager-journal");
+ Process deleteDatabasesProcess = runtime.exec("rm -rf " + privateDataDirectoryString + "/app_webview/databases");
+
+ // Wait for the processes to finish.
+ deleteLocalStorageProcess.waitFor();
+ deleteIndexProcess.waitFor();
+ deleteQuotaManagerProcess.waitFor();
+ deleteQuotaManagerJournalProcess.waitFor();
+ deleteDatabasesProcess.waitFor();
+ } catch (Exception exception) {
+ // Do nothing if an error is thrown.
+ }
+ };
+
+ // Manually delete the DOM storage files after 200 milliseconds.
+ deleteDomStorageHandler.postDelayed(deleteDomStorageRunnable, 200);
}
}
})
@SuppressLint("SwitchIntDef") // Ignore the lint warning about not handling the other possible events as they are covered by `default:`.
@Override
public void onDismissed(Snackbar snackbar, int event) {
- switch (event) {
- // The user pushed the undo button.
- case Snackbar.Callback.DISMISS_EVENT_ACTION:
- // Do nothing.
- break;
-
- // The snackbar was dismissed without the `Undo` button being pushed.
- default:
- // Delete the form data.
- WebViewDatabase mainWebViewDatabase = WebViewDatabase.getInstance(getApplicationContext());
- mainWebViewDatabase.clearFormData();
+ if (event != Snackbar.Callback.DISMISS_EVENT_ACTION) { // The snackbar was dismissed without the undo button being pushed.
+ // Delete the form data.
+ WebViewDatabase mainWebViewDatabase = WebViewDatabase.getInstance(getApplicationContext());
+ mainWebViewDatabase.clearFormData();
}
}
})
currentWebView.getSettings().setJavaScriptEnabled(true);
} else if (currentWebView.getDomainSettingsApplied()) { // Night mode is disabled and domain settings are applied. Set JavaScript according to the domain settings.
// Apply the JavaScript preference that was stored the last time domain settings were loaded.
- currentWebView.getSettings().setJavaScriptEnabled(domainSettingsJavaScriptEnabled); // TODO.
+ currentWebView.getSettings().setJavaScriptEnabled(currentWebView.getDomainSettingsJavaScriptEnabled());
} else { // Night mode is disabled and domain settings are not applied. Set JavaScript according to the global preference.
// Apply the JavaScript preference.
currentWebView.getSettings().setJavaScriptEnabled(sharedPreferences.getBoolean("javascript", false));
}
// removeAllCookies is deprecated, but it is required for API < 21.
- @SuppressWarnings("deprecation")
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
// Get the menu item ID.
// Get a handle for the runtime.
Runtime runtime = Runtime.getRuntime();
+ // Get the application's private data directory, which will be something like `/data/user/0/com.stoutner.privacybrowser.standard`,
+ // which links to `/data/data/com.stoutner.privacybrowser.standard`.
+ String privateDataDirectoryString = getApplicationInfo().dataDir;
+
// Clear cookies.
if (clearEverything || sharedPreferences.getBoolean("clear_cookies", true)) {
// The command to remove cookies changed slightly in API 21.
// Reset the current domain name so that navigation works if third-party requests are blocked.
currentWebView.resetCurrentDomainName();
- // Set `navigatingHistory` so that the domain settings are applied when the new URL is loaded.
- navigatingHistory = true;
+ // Set navigating history so that the domain settings are applied when the new URL is loaded.
+ currentWebView.setNavigatingHistory(true);
// Load the previous website in the history.
currentWebView.goBack();
// Reset the current domain name so that navigation works if third-party requests are blocked.
currentWebView.resetCurrentDomainName();
- // Set `navigatingHistory` so that the domain settings are applied when the new URL is loaded.
- navigatingHistory = true;
+ // Set navigating history so that the domain settings are applied when the new URL is loaded.
+ currentWebView.setNavigatingHistory(true);
// Load the next website in the history.
currentWebView.goForward();
break;
case R.id.about:
- // Launch `AboutActivity`.
+ // Create an intent to launch the about activity.
Intent aboutIntent = new Intent(this, AboutActivity.class);
+
+ // Create a string array for the blocklist versions.
+ String[] blocklistVersions = new String[] {easyList.get(0).get(0)[0], easyPrivacy.get(0).get(0)[0], fanboysAnnoyanceList.get(0).get(0)[0], fanboysSocialList.get(0).get(0)[0],
+ ultraPrivacy.get(0).get(0)[0]};
+
+ // Add the blocklist versions to the intent.
+ aboutIntent.putExtra("blocklist_versions", blocklistVersions);
+
+ // Make it so.
startActivity(aboutIntent);
break;
}
final String imageUrl;
final String linkUrl;
- // Get handles for the the clipboard and fragment managers.
+ // Get handles for the system managers.
final ClipboardManager clipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
FragmentManager fragmentManager = getSupportFragmentManager();
+ SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
// Remove the lint errors below that the clipboard manager might be null.
assert clipboardManager != null;
// Add a Download URL entry.
menu.add(R.string.download_url).setOnMenuItemClickListener((MenuItem item) -> {
// Check if the download should be processed by an external app.
- if (downloadWithExternalApp) { // Download with an external app.
+ if (sharedPreferences.getBoolean("download_with_external_app", false)) { // Download with an external app.
openUrlWithExternalApp(linkUrl);
} else { // Download with Android's download manager.
// Check to see if the storage permission has already been granted.
// Add a Download Image entry.
menu.add(R.string.download_image).setOnMenuItemClickListener((MenuItem item) -> {
// Check if the download should be processed by an external app.
- if (downloadWithExternalApp) { // Download with an external app.
+ if (sharedPreferences.getBoolean("download_with_external_app", false)) { // Download with an external app.
openUrlWithExternalApp(imageUrl);
} else { // Download with Android's download manager.
// Check to see if the storage permission has already been granted.
// Add a `Download Image` entry.
menu.add(R.string.download_image).setOnMenuItemClickListener((MenuItem item) -> {
// Check if the download should be processed by an external app.
- if (downloadWithExternalApp) { // Download with an external app.
+ if (sharedPreferences.getBoolean("download_with_external_app", false)) { // Download with an external app.
openUrlWithExternalApp(imageUrl);
} else { // Download with Android's download manager.
// Check to see if the storage permission has already been granted.
}
}
- @Override
- public void onHttpAuthenticationCancel() {
- // Cancel the `HttpAuthHandler`.
- httpAuthHandler.cancel();
- }
-
- @Override
- public void onHttpAuthenticationProceed(DialogFragment dialogFragment) {
- // Get handles for the `EditTexts`.
- EditText usernameEditText = dialogFragment.getDialog().findViewById(R.id.http_authentication_username);
- EditText passwordEditText = dialogFragment.getDialog().findViewById(R.id.http_authentication_password);
-
- // Proceed with the HTTP authentication.
- httpAuthHandler.proceed(usernameEditText.getText().toString(), passwordEditText.getText().toString());
- }
-
- @Override
- public void onSslErrorCancel() { // TODO. How to handle this with multiple tabs? There could be multiple errors at once.
- sslErrorHandler.cancel();
- }
-
- @Override
- public void onSslErrorProceed() { // TODO. How to handle this with multiple tabs? There could be multiple errors at once.
- sslErrorHandler.proceed();
- }
-
@Override
public void onPinnedMismatchBack() { // TODO. Move this logic to the dialog.
if (currentWebView.canGoBack()) { // There is a back page in the history.
// Reset the current domain name so that navigation works if third-party requests are blocked.
currentWebView.resetCurrentDomainName();
- // Set `navigatingHistory` so that the domain settings are applied when the new URL is loaded.
- navigatingHistory = true; // TODO.
+ // Set navigating history so that the domain settings are applied when the new URL is loaded.
+ currentWebView.setNavigatingHistory(true);
// Go back.
currentWebView.goBack();
}
@Override
- public void onUrlHistoryEntrySelected(int moveBackOrForwardSteps) {
+ public void onUrlHistoryEntrySelected(int moveBackOrForwardSteps) { // TODO. Move this logic to the dialog.
// Reset the current domain name so that navigation works if third-party requests are blocked.
currentWebView.resetCurrentDomainName();
- // Set `navigatingHistory` so that the domain settings are applied when the new URL is loaded.
- navigatingHistory = true;
+ // Set navigating history so that the domain settings are applied when the new URL is loaded.
+ currentWebView.setNavigatingHistory(true);
// Load the history entry.
currentWebView.goBackOrForward(moveBackOrForwardSteps);
}
@Override
- public void onClearHistory() {
+ public void onClearHistory() { // TODO. Move this logic to the dialog.
// Clear the history.
currentWebView.clearHistory();
}
// Reset the current domain name so that navigation works if third-party requests are blocked.
currentWebView.resetCurrentDomainName();
- // Set `navigatingHistory` so that the domain settings are applied when the new URL is loaded.
- navigatingHistory = true;
+ // Set navigating history so that the domain settings are applied when the new URL is loaded.
+ currentWebView.setNavigatingHistory(true);
// Go back.
currentWebView.goBack();
proxyThroughOrbot = sharedPreferences.getBoolean("proxy_through_orbot", false);
fullScreenBrowsingModeEnabled = sharedPreferences.getBoolean("full_screen_browsing_mode", false);
hideAppBar = sharedPreferences.getBoolean("hide_app_bar", true);
- downloadWithExternalApp = sharedPreferences.getBoolean("download_with_external_app", false);
// Get handles for the views that need to be modified. `getSupportActionBar()` must be used until the minimum API >= 21.
FrameLayout rootFrameLayout = findViewById(R.id.root_framelayout);
// Get the settings from the cursor.
nestedScrollWebView.setDomainSettingsDatabaseId(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper._ID)));
- boolean domainJavaScriptEnabled = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_JAVASCRIPT)) == 1);
+ nestedScrollWebView.setDomainSettingsJavaScriptEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_JAVASCRIPT)) == 1);
nestedScrollWebView.setAcceptFirstPartyCookies(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FIRST_PARTY_COOKIES)) == 1);
boolean domainThirdPartyCookiesEnabled = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_THIRD_PARTY_COOKIES)) == 1);
nestedScrollWebView.getSettings().setDomStorageEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE)) == 1);
break;
}
- // TODO.
- // Store the domain JavaScript status. This is used by the options menu night mode toggle.
- domainSettingsJavaScriptEnabled = domainJavaScriptEnabled;
-
// Enable JavaScript if night mode is enabled.
if (nestedScrollWebView.getNightMode()) {
// Enable JavaScript.
nestedScrollWebView.getSettings().setJavaScriptEnabled(true);
} else {
// Set JavaScript according to the domain settings.
- nestedScrollWebView.getSettings().setJavaScriptEnabled(domainJavaScriptEnabled);
+ nestedScrollWebView.getSettings().setJavaScriptEnabled(nestedScrollWebView.getDomainSettingsJavaScriptEnabled());
}
// Close the current host domain settings cursor.
currentWebView.getSettings().setUseWideViewPort(false);
// Load a waiting page. `null` specifies no encoding, which defaults to ASCII.
- currentWebView.loadData(waitingForOrbotHtmlString, "text/html", null);
+ currentWebView.loadData("<html><body><br/><center><h1>" + getString(R.string.waiting_for_orbot) + "</h1></center></body></html>", "text/html", null);
} else if (reloadWebsite) { // Orbot is ready and the website should be reloaded.
// Reload the website.
currentWebView.reload();
// Get the fragment view.
View fragmentView = webViewTabFragment.getView();
- // Remove the incorrect lint warning below that the fragment view might be null.
- assert fragmentView != null;
-
- // Store the current WebView.
- currentWebView = fragmentView.findViewById(R.id.nestedscroll_webview);
+ // Set the current WebView if the fragment view is not null.
+ if (fragmentView != null) {
+ // Store the current WebView.
+ currentWebView = fragmentView.findViewById(R.id.nestedscroll_webview);
- // Update the status of swipe to refresh.
- if (currentWebView.getSwipeToRefresh()) { // Swipe to refresh is enabled.
- if (Build.VERSION.SDK_INT >= 23) { // For API >= 23, swipe refresh layout is continuously updated with an on scroll change listener and only enabled if the WebView is scrolled to the top.
- // Enable the swipe refresh layout if the WebView is scrolled all the way to the top.
- swipeRefreshLayout.setEnabled(currentWebView.getY() == 0);
- } else {
- // Enable the swipe refresh layout.
- swipeRefreshLayout.setEnabled(true);
+ // Update the status of swipe to refresh.
+ if (currentWebView.getSwipeToRefresh()) { // Swipe to refresh is enabled.
+ if (Build.VERSION.SDK_INT >= 23) { // For API >= 23, swipe refresh layout is continuously updated with an on scroll change listener and only enabled if the WebView is scrolled to the top.
+ // Enable the swipe refresh layout if the WebView is scrolled all the way to the top.
+ swipeRefreshLayout.setEnabled(currentWebView.getY() == 0);
+ } else {
+ // Enable the swipe refresh layout.
+ swipeRefreshLayout.setEnabled(true);
+ }
+ } else { // Swipe to refresh is disabled.
+ // Disable the swipe refresh layout.
+ swipeRefreshLayout.setEnabled(false);
}
- } else { // Swipe to refresh is disabled.
- // Disable the swipe refresh layout.
- swipeRefreshLayout.setEnabled(false);
- }
- // Get a handle for the cookie manager.
- CookieManager cookieManager = CookieManager.getInstance();
+ // Get a handle for the cookie manager.
+ CookieManager cookieManager = CookieManager.getInstance();
- // Set the first-party cookie status.
- cookieManager.setAcceptCookie(currentWebView.getAcceptFirstPartyCookies());
+ // Set the first-party cookie status.
+ cookieManager.setAcceptCookie(currentWebView.getAcceptFirstPartyCookies());
- // Update the privacy icons. `true` redraws the icons in the app bar.
- updatePrivacyIcons(true);
+ // Update the privacy icons. `true` redraws the icons in the app bar.
+ updatePrivacyIcons(true);
- // Clear the focus from the URL text box.
- urlEditText.clearFocus();
+ // Clear the focus from the URL text box.
+ urlEditText.clearFocus();
- // Get a handle for the input method manager.
- InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+ // Get a handle for the input method manager.
+ InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
- // Remove the lint warning below that the input method manager might be null.
- assert inputMethodManager != null;
+ // Remove the lint warning below that the input method manager might be null.
+ assert inputMethodManager != null;
- // Hide the soft keyboard.
- inputMethodManager.hideSoftInputFromWindow(currentWebView.getWindowToken(), 0);
+ // Hide the soft keyboard.
+ inputMethodManager.hideSoftInputFromWindow(currentWebView.getWindowToken(), 0);
- // Display the current URL in the URL text box.
- urlEditText.setText(currentWebView.getUrl());
+ // Display the current URL in the URL text box.
+ urlEditText.setText(currentWebView.getUrl());
- // Highlight the URL text.
- highlightUrlText();
+ // Highlight the URL text.
+ highlightUrlText();
- // Set the background to indicate the domain settings status.
- if (currentWebView.getDomainSettingsApplied()) {
- // Set a green background on the URL relative layout to indicate that custom domain settings are being used. The deprecated `.getDrawable()` must be used until the minimum API >= 21.
- if (darkTheme) {
- urlRelativeLayout.setBackground(getResources().getDrawable(R.drawable.url_bar_background_dark_blue));
+ // Set the background to indicate the domain settings status.
+ if (currentWebView.getDomainSettingsApplied()) {
+ // Set a green background on the URL relative layout to indicate that custom domain settings are being used. The deprecated `.getDrawable()` must be used until the minimum API >= 21.
+ if (darkTheme) {
+ urlRelativeLayout.setBackground(getResources().getDrawable(R.drawable.url_bar_background_dark_blue));
+ } else {
+ urlRelativeLayout.setBackground(getResources().getDrawable(R.drawable.url_bar_background_light_green));
+ }
} else {
- urlRelativeLayout.setBackground(getResources().getDrawable(R.drawable.url_bar_background_light_green));
+ urlRelativeLayout.setBackground(getResources().getDrawable(R.color.transparent));
}
- } else {
- urlRelativeLayout.setBackground(getResources().getDrawable(R.color.transparent));
}
}
// Get a handle for the input method manager.
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+ // Instantiate the blocklist helper.
+ BlockListHelper blockListHelper = new BlockListHelper();
+
// Remove the lint warning below that the input method manager might be null.
assert inputMethodManager != null;
// Get the current tab.
TabLayout.Tab tab = tabLayout.getTabAt(currentPosition);
- // Remove the lint warning below that the current tab might be null.
- assert tab != null;
-
- // Get the custom view from the tab.
- View tabView = tab.getCustomView();
-
- // Remove the incorrect warning below that the current tab view might be null.
- assert tabView != null;
+ // Check to see if the tab has been populated.
+ if (tab != null) {
+ // Get the custom view from the tab.
+ View tabView = tab.getCustomView();
- // Get the favorite icon image view from the tab.
- ImageView tabFavoriteIconImageView = tabView.findViewById(R.id.favorite_icon_imageview);
+ // Check to see if the custom tab view has been populated.
+ if (tabView != null) {
+ // Get the favorite icon image view from the tab.
+ ImageView tabFavoriteIconImageView = tabView.findViewById(R.id.favorite_icon_imageview);
- // Display the favorite icon in the tab.
- tabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(icon, 64, 64, true));
+ // Display the favorite icon in the tab.
+ tabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(icon, 64, 64, true));
+ }
+ }
}
}
// Show the main content relative layout.
mainContentRelativeLayout.setVisibility(View.VISIBLE);
- // Apply the appropriate full screen mode the `SYSTEM_UI` flags.
+ // 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) {
nestedScrollWebView.setWebViewClient(new WebViewClient() {
// `shouldOverrideUrlLoading` makes this `WebView` the default handler for URLs inside the app, so that links are not kicked out to other apps.
// The deprecated `shouldOverrideUrlLoading` must be used until API >= 24.
- @SuppressWarnings("deprecation")
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("http")) { // Load the URL in Privacy Browser.
}
// Check requests against the block lists. The deprecated `shouldInterceptRequest()` must be used until minimum API >= 21.
- @SuppressWarnings("deprecation")
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
// Get a handle for the navigation view.
// Get a handle for the navigation requests menu item. The menu is 0 based.
MenuItem navigationRequestsMenuItem = navigationMenu.getItem(6);
+ // Get handles for the options menu items.
+ MenuItem blocklistsMenuItem = optionsMenu.findItem(R.id.blocklists);
+ MenuItem easyListMenuItem = optionsMenu.findItem(R.id.easylist);
+ MenuItem easyPrivacyMenuItem = optionsMenu.findItem(R.id.easyprivacy);
+ MenuItem fanboysAnnoyanceListMenuItem = optionsMenu.findItem(R.id.fanboys_annoyance_list);
+ MenuItem fanboysSocialBlockingListMenuItem = optionsMenu.findItem(R.id.fanboys_social_blocking_list);
+ MenuItem ultraPrivacyMenuItem = optionsMenu.findItem(R.id.ultraprivacy);
+ MenuItem blockAllThirdPartyRequestsMenuItem = optionsMenu.findItem(R.id.block_all_third_party_requests);
+
// Create an empty web resource response to be used if the resource request is blocked.
WebResourceResponse emptyWebResourceResponse = new WebResourceResponse("text/plain", "utf8", new ByteArrayInputStream("".getBytes()));
// Handle HTTP authentication requests.
@Override
public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) {
- // Store `handler` so it can be accessed from `onHttpAuthenticationCancel()` and `onHttpAuthenticationProceed()`.
- httpAuthHandler = handler;
+ // Store the handler.
+ nestedScrollWebView.setHttpAuthHandler(handler);
- // Display the HTTP authentication dialog.
- DialogFragment httpAuthenticationDialogFragment = HttpAuthenticationDialog.displayDialog(host, realm);
+ // Instantiate an HTTP authentication dialog.
+ DialogFragment httpAuthenticationDialogFragment = HttpAuthenticationDialog.displayDialog(host, realm, nestedScrollWebView.getWebViewFragmentId());
+
+ // Show the HTTP authentication dialog.
httpAuthenticationDialogFragment.show(getSupportFragmentManager(), getString(R.string.http_authentication));
}
new GetHostIpAddresses(activity, getSupportFragmentManager(), nestedScrollWebView).execute(currentUri.getHost());
// Apply any custom domain settings if the URL was loaded by navigating history.
- if (navigatingHistory) {
+ if (nestedScrollWebView.getNavigatingHistory()) {
+ // Reset navigating history.
+ nestedScrollWebView.setNavigatingHistory(false);
+
// Apply the domain settings.
boolean userAgentChanged = applyDomainSettings(nestedScrollWebView, url, true, false);
- // Reset `navigatingHistory`.
- navigatingHistory = 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);
// Manually delete cache folders.
try {
+ // Get the application's private data directory, which will be something like `/data/user/0/com.stoutner.privacybrowser.standard`,
+ // which links to `/data/data/com.stoutner.privacybrowser.standard`.
+ String privateDataDirectoryString = getApplicationInfo().dataDir;
+
// Delete the main cache directory.
Runtime.getRuntime().exec("rm -rf " + privateDataDirectoryString + "/cache");
handler.proceed();
}
} else { // Either there isn't a pinned SSL certificate or it doesn't match the current website certificate.
- // Store `handler` so it can be accesses from `onSslErrorCancel()` and `onSslErrorProceed()`.
- sslErrorHandler = handler; // TODO. We need to pass this in instead of using a static variable. Because multiple could be displayed at once from different tabs.
+ // Store the SSL error handler.
+ nestedScrollWebView.setSslErrorHandler(handler);
+
+ // Instantiate an SSL certificate error alert dialog.
+ DialogFragment sslCertificateErrorDialogFragment = SslCertificateErrorDialog.displayDialog(error, nestedScrollWebView.getWebViewFragmentId());
- // Display the SSL error `AlertDialog`.
- DialogFragment sslCertificateErrorDialogFragment = SslCertificateErrorDialog.displayDialog(error);
+ // Show the SSL certificate error dialog.
sslCertificateErrorDialogFragment.show(getSupportFragmentManager(), getString(R.string.ssl_certificate_error));
}
}
--- /dev/null
+/*
+ * Copyright © 2016-2019 Soren Stoutner <soren@stoutner.com>.
+ *
+ * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
+ *
+ * Privacy Browser is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Privacy Browser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Privacy Browser. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.stoutner.privacybrowser.adapters;
+
+import android.content.Context;
+
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentPagerAdapter;
+
+import com.stoutner.privacybrowser.R;
+import com.stoutner.privacybrowser.fragments.AboutTabFragment;
+
+public class AboutPagerAdapter extends FragmentPagerAdapter {
+ // Define the class variable to store the blocklist versions.
+ private Context context;
+ private String[] blocklistVersions;
+
+ public AboutPagerAdapter(FragmentManager fragmentManager, Context context, String[] blocklistVersions) {
+ // Run the default commands.
+ super(fragmentManager);
+
+ // Store the context in a class variable.
+ this.context = context;
+
+ // Store the blocklist versions in a class variable.
+ this.blocklistVersions = blocklistVersions;
+ }
+
+ @Override
+ // Get the count of the number of tabs.
+ public int getCount() {
+ return 7;
+ }
+
+ @Override
+ // Get the name of each tab. Tab numbers start at 0.
+ public CharSequence getPageTitle(int tab) {
+ switch (tab) {
+ case 0:
+ return context.getResources().getString(R.string.version);
+
+ case 1:
+ return context.getResources().getString(R.string.permissions);
+
+ case 2:
+ return context.getResources().getString(R.string.privacy_policy);
+
+ case 3:
+ return context.getResources().getString(R.string.changelog);
+
+ case 4:
+ return context.getResources().getString(R.string.licenses);
+
+ case 5:
+ return context.getResources().getString(R.string.contributors);
+
+ case 6:
+ return context.getResources().getString(R.string.links);
+
+ default:
+ return "";
+ }
+ }
+
+ @Override
+ // Setup each tab.
+ public Fragment getItem(int tabNumber) {
+ return AboutTabFragment.createTab(tabNumber, blocklistVersions);
+ }
+}
\ No newline at end of file
dialogBuilder.setMessage(R.string.about_view_source_message);
// Create an alert dialog from the alert dialog builder.
- final AlertDialog alertDialog = dialogBuilder.create();
+ AlertDialog alertDialog = dialogBuilder.create();
// Disable screenshots if not allowed.
if (!allowScreenshots) {
alertDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
- // `onCreateDialog` requires the return of an `AlertDialog`.
+ // Return the alert dialog.
return alertDialog;
}
}
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.Dialog;
-import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
+import android.webkit.HttpAuthHandler;
import android.widget.EditText;
import android.widget.TextView;
import androidx.fragment.app.DialogFragment; // The AndroidX dialog fragment must be used or an error is produced on API <=22.
import com.stoutner.privacybrowser.R;
+import com.stoutner.privacybrowser.activities.MainWebViewActivity;
+import com.stoutner.privacybrowser.fragments.WebViewTabFragment;
+import com.stoutner.privacybrowser.views.NestedScrollWebView;
public class HttpAuthenticationDialog extends DialogFragment{
- // `httpAuthenticationListener` is used in `onAttach()` and `onCreateDialog()`
- private HttpAuthenticationListener httpAuthenticationListener;
+ // Define the class variables.
+ private EditText usernameEditText;
+ private EditText passwordEditText;
- // The public interface is used to send information back to the parent activity.
- public interface HttpAuthenticationListener {
- void onHttpAuthenticationCancel();
-
- void onHttpAuthenticationProceed(DialogFragment dialogFragment);
- }
-
- public void onAttach(Context context) {
- super.onAttach(context);
-
- // Get a handle for `httpAuthenticationListener` from `context`.
- httpAuthenticationListener = (HttpAuthenticationListener) context;
- }
-
- public static HttpAuthenticationDialog displayDialog(String host, String realm) {
- // Store the strings in a `Bundle`.
+ public static HttpAuthenticationDialog displayDialog(String host, String realm, long webViewFragmentId) {
+ // Create an arguments bundle.
Bundle argumentsBundle = new Bundle();
- argumentsBundle.putString("Host", host);
- argumentsBundle.putString("Realm", realm);
- // Add `argumentsBundle` to this instance of `HttpAuthenticationDialog`.
+ // Store the variables in the bundle.
+ argumentsBundle.putString("host", host);
+ argumentsBundle.putString("realm", realm);
+ argumentsBundle.putLong("webview_fragment_id", webViewFragmentId);
+
+ // Create a new instance of the HTTP authentication dialog.
HttpAuthenticationDialog thisHttpAuthenticationDialog = new HttpAuthenticationDialog();
+
+ // Add the arguments bundle to the new dialog.
thisHttpAuthenticationDialog.setArguments(argumentsBundle);
+
+ // Return the new dialog.
return thisHttpAuthenticationDialog;
}
@Override
@NonNull
public Dialog onCreateDialog(Bundle savedInstanceState) {
- // Remove the incorrect lint warnings that `getString()` might be null.
- assert getArguments() != null;
+ // Get a handle for the arguments.
+ Bundle arguments = getArguments();
+
+ // Remove the incorrect lint warning below that arguments might be null.
+ assert arguments != null;
- // Get the host and realm variables from the bundle.
- String httpAuthHost = getArguments().getString("Host");
- String httpAuthRealm = getArguments().getString("Realm");
+ // Get the variables from the bundle.
+ String httpAuthHost = arguments.getString("host");
+ String httpAuthRealm = arguments.getString("realm");
+ long webViewFragmentId = arguments.getLong("webview_fragment_id");
+
+ // Get the current position of this WebView fragment.
+ int webViewPosition = MainWebViewActivity.webViewPagerAdapter.getPositionForId(webViewFragmentId);
+
+ // Get the WebView tab fragment.
+ WebViewTabFragment webViewTabFragment = MainWebViewActivity.webViewPagerAdapter.getPageFragment(webViewPosition);
+
+ // Get the fragment view.
+ View fragmentView = webViewTabFragment.getView();
+
+ // Remove the incorrect lint warning below that the fragment view might be null.
+ assert fragmentView != null;
+
+ // Get a handle for the current WebView.
+ NestedScrollWebView nestedScrollWebView = fragmentView.findViewById(R.id.nestedscroll_webview);
+
+ // Get a handle for the HTTP authentication handler.
+ HttpAuthHandler httpAuthHandler = nestedScrollWebView.getHttpAuthHandler();
// Remove the incorrect lint warning that `getActivity()` might be null.
assert getActivity() != null;
// Set the layout. The parent view is `null` because it will be assigned by `AlertDialog`.
dialogBuilder.setView(layoutInflater.inflate(R.layout.http_authentication_dialog, null));
- // Setup the negative button.
+ // Setup the close button.
dialogBuilder.setNegativeButton(R.string.close, (DialogInterface dialog, int which) -> {
- // Call `onHttpAuthenticationCancel()` and return the `DialogFragment` to the parent activity.
- httpAuthenticationListener.onHttpAuthenticationCancel();
+ // Cancel the HTTP authentication request.
+ httpAuthHandler.cancel();
+
+ // Reset the HTTP authentication handler.
+ nestedScrollWebView.resetHttpAuthHandler();
});
- // Setup the positive button.
+ // Setup the proceed button.
dialogBuilder.setPositiveButton(R.string.proceed, (DialogInterface dialog, int which) -> {
- // Call `onHttpAuthenticationProceed()` and return the `DialogFragment` to the parent activity.
- httpAuthenticationListener.onHttpAuthenticationProceed(HttpAuthenticationDialog.this);
+ // Send the login information
+ login(httpAuthHandler);
+
+ // Reset the HTTP authentication handler.
+ nestedScrollWebView.resetHttpAuthHandler();
});
// Create an alert dialog from the alert dialog builder.
alertDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
- // Show the keyboard when the `AlertDialog` is displayed on the screen.
+ // Show the keyboard when the alert dialog is displayed on the screen.
alertDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
// The alert dialog needs to be shown before the contents can be modified.
alertDialog.show();
- // Get handles for the views in `alertDialog`.
+ // Get handles for the views.
TextView realmTextView = alertDialog.findViewById(R.id.http_authentication_realm);
TextView hostTextView = alertDialog.findViewById(R.id.http_authentication_host);
- EditText usernameEditText = alertDialog.findViewById(R.id.http_authentication_username);
- EditText passwordEditText = alertDialog.findViewById(R.id.http_authentication_password);
+ usernameEditText = alertDialog.findViewById(R.id.http_authentication_username);
+ passwordEditText = alertDialog.findViewById(R.id.http_authentication_password);
// Set the realm text.
realmTextView.setText(httpAuthRealm);
// Set the realm text color according to the theme. The deprecated `.getColor()` must be used until API >= 23.
if (darkTheme) {
- //noinspection deprecation
realmTextView.setTextColor(getResources().getColor(R.color.gray_300));
} else {
- //noinspection deprecation
realmTextView.setTextColor(getResources().getColor(R.color.black));
}
// Set `blueColorSpan` according to the theme. The deprecated `getColor()` must be used until API >= 23.
if (darkTheme) {
- //noinspection deprecation
blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue_400));
} else {
- //noinspection deprecation
blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue_700));
}
usernameEditText.setOnKeyListener((View view, int keyCode, KeyEvent event) -> {
// If the event is a key-down on the `enter` key, call `onHttpAuthenticationProceed()`.
if ((keyCode == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN)) {
- // Trigger `onHttpAuthenticationProceed` and return the `DialogFragment` to the parent activity.
- httpAuthenticationListener.onHttpAuthenticationProceed(HttpAuthenticationDialog.this);
+ // Send the login information.
+ login(httpAuthHandler);
- // Manually dismiss the `AlertDialog`.
+ // Manually dismiss the alert dialog.
alertDialog.dismiss();
// Consume the event.
passwordEditText.setOnKeyListener((View view, int keyCode, KeyEvent event) -> {
// If the event is a key-down on the `enter` key, call `onHttpAuthenticationProceed()`.
if ((keyCode == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN)) {
- // Trigger `onHttpAuthenticationProceed` and return the `DialogFragment` to the parent activity.
- httpAuthenticationListener.onHttpAuthenticationProceed(HttpAuthenticationDialog.this);
+ // Send the login information.
+ login(httpAuthHandler);
- // Manually dismiss the `AlertDialog`.
+ // Manually dismiss the alert dialog.
alertDialog.dismiss();
// Consume the event.
}
});
- // `onCreateDialog()` requires the return of an `AlertDialog`.
+ // Return the alert dialog.
return alertDialog;
}
+
+ private void login(HttpAuthHandler httpAuthHandler) {
+ // Send the login information.
+ httpAuthHandler.proceed(usernameEditText.getText().toString(), passwordEditText.getText().toString());
+ }
}
\ No newline at end of file
boolean darkTheme = sharedPreferences.getBoolean("dark_theme", false);
// Create a red foreground color span. The deprecated `getResources().getColor` must be used until the minimum API >= 23.
- @SuppressWarnings("deprecation") ForegroundColorSpan redColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.red_a700));
+ ForegroundColorSpan redColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.red_a700));
// Create a blue foreground color span.
ForegroundColorSpan blueColorSpan;
// Set the blue color span according to the theme. The deprecated `getResources().getColor` must be used until the minimum API >= 23.
if (darkTheme) {
- //noinspection deprecation
blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue_400));
} else {
- //noinspection deprecation
blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue_700));
}
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
-import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.net.Uri;
import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import android.view.LayoutInflater;
+import android.view.View;
import android.view.WindowManager;
+import android.webkit.SslErrorHandler;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment; // The AndroidX dialog fragment must be used or an error is produced on API <=22.
import com.stoutner.privacybrowser.R;
+import com.stoutner.privacybrowser.activities.MainWebViewActivity;
+import com.stoutner.privacybrowser.fragments.WebViewTabFragment;
+import com.stoutner.privacybrowser.views.NestedScrollWebView;
import java.lang.ref.WeakReference;
import java.net.InetAddress;
import java.util.Date;
public class SslCertificateErrorDialog extends DialogFragment {
- // `sslCertificateErrorListener` is used in `onAttach` and `onCreateDialog`.
- private SslCertificateErrorListener sslCertificateErrorListener;
-
- // The public interface is used to send information back to the parent activity.
- public interface SslCertificateErrorListener {
- void onSslErrorCancel();
-
- void onSslErrorProceed();
- }
-
- public void onAttach(Context context) {
- // Run the default commands.
- super.onAttach(context);
-
- // Get a handle for `SslCertificateErrorListener` from the launching context.
- sslCertificateErrorListener = (SslCertificateErrorListener) context;
- }
-
- public static SslCertificateErrorDialog displayDialog(SslError error) {
+ public static SslCertificateErrorDialog displayDialog(SslError error, long webViewFragmentId) {
// Get the various components of the SSL error message.
int primaryErrorIntForBundle = error.getPrimaryError();
String urlWithErrorForBundle = error.getUrl();
Date startDateForBundle = sslCertificate.getValidNotBeforeDate();
Date endDateForBundle = sslCertificate.getValidNotAfterDate();
- // Store the SSL error message components in a `Bundle`.
+ // Create an arguments bundle.
Bundle argumentsBundle = new Bundle();
- argumentsBundle.putInt("PrimaryErrorInt", primaryErrorIntForBundle);
- argumentsBundle.putString("UrlWithError", urlWithErrorForBundle);
- argumentsBundle.putString("IssuedToCName", issuedToCNameForBundle);
- argumentsBundle.putString("IssuedToOName", issuedToONameForBundle);
- argumentsBundle.putString("IssuedToUName", issuedToUNameForBundle);
- argumentsBundle.putString("IssuedByCName", issuedByCNameForBundle);
- argumentsBundle.putString("IssuedByOName", issuedByONameForBundle);
- argumentsBundle.putString("IssuedByUName", issuedByUNameForBundle);
- argumentsBundle.putString("StartDate", DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(startDateForBundle));
- argumentsBundle.putString("EndDate", DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(endDateForBundle));
-
- // Add `argumentsBundle` to this instance of `SslCertificateErrorDialog`.
+
+ // Store the SSL error message components in a `Bundle`.
+ argumentsBundle.putInt("primary_error_int", primaryErrorIntForBundle);
+ argumentsBundle.putString("url_with_error", urlWithErrorForBundle);
+ argumentsBundle.putString("issued_to_cname", issuedToCNameForBundle);
+ argumentsBundle.putString("issued_to_oname", issuedToONameForBundle);
+ argumentsBundle.putString("issued_to_uname", issuedToUNameForBundle);
+ argumentsBundle.putString("issued_by_cname", issuedByCNameForBundle);
+ argumentsBundle.putString("issued_by_oname", issuedByONameForBundle);
+ argumentsBundle.putString("issued_by_uname", issuedByUNameForBundle);
+ argumentsBundle.putString("start_date", DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(startDateForBundle));
+ argumentsBundle.putString("end_date", DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(endDateForBundle));
+ argumentsBundle.putLong("webview_fragment_id", webViewFragmentId);
+
+ // Create a new instance of the SSL certificate error dialog.
SslCertificateErrorDialog thisSslCertificateErrorDialog = new SslCertificateErrorDialog();
+
+ // Add the arguments bundle to the new dialog.
thisSslCertificateErrorDialog.setArguments(argumentsBundle);
+
+ // Return the new dialog.
return thisSslCertificateErrorDialog;
}
// `@SuppressLing("InflateParams")` removes the warning about using `null` as the parent view group when inflating the `AlertDialog`.
@SuppressLint("InflateParams")
- @SuppressWarnings("deprecation")
@Override
@NonNull
public Dialog onCreateDialog(Bundle savedInstanceState) {
- // Remove the incorrect lint warning that `getArguments()` might be null.
- assert getArguments() != null;
-
- // Get the components of the SSL error message from the bundle.
- int primaryErrorInt = getArguments().getInt("PrimaryErrorInt");
- String urlWithErrors = getArguments().getString("UrlWithError");
- String issuedToCName = getArguments().getString("IssuedToCName");
- String issuedToOName = getArguments().getString("IssuedToOName");
- String issuedToUName = getArguments().getString("IssuedToUName");
- String issuedByCName = getArguments().getString("IssuedByCName");
- String issuedByOName = getArguments().getString("IssuedByOName");
- String issuedByUName = getArguments().getString("IssuedByUName");
- String startDate = getArguments().getString("StartDate");
- String endDate = getArguments().getString("EndDate");
+ // Get a handle for the arguments.
+ Bundle arguments = getArguments();
+
+ // Remove the incorrect lint warning that the arguments might be null.
+ assert arguments != null;
+
+ // Get the variables from the bundle.
+ int primaryErrorInt = arguments.getInt("primary_error_int");
+ String urlWithErrors = arguments.getString("url_with_error");
+ String issuedToCName = arguments.getString("issued_to_cname");
+ String issuedToOName = arguments.getString("issued_to_oname");
+ String issuedToUName = arguments.getString("issued_to_uname");
+ String issuedByCName = arguments.getString("issued_by_cname");
+ String issuedByOName = arguments.getString("issued_by_oname");
+ String issuedByUName = arguments.getString("issued_by_uname");
+ String startDate = arguments.getString("start_date");
+ String endDate = arguments.getString("end_date");
+ long webViewFragmentId = arguments.getLong("webview_fragment_id");
+
+ // Get the current position of this WebView fragment.
+ int webViewPosition = MainWebViewActivity.webViewPagerAdapter.getPositionForId(webViewFragmentId);
+
+ // Get the WebView tab fragment.
+ WebViewTabFragment webViewTabFragment = MainWebViewActivity.webViewPagerAdapter.getPageFragment(webViewPosition);
+
+ // Get the fragment view.
+ View fragmentView = webViewTabFragment.getView();
+
+ // Remove the incorrect lint warning below that the fragment view might be null.
+ assert fragmentView != null;
+
+ // Get a handle for the current WebView.
+ NestedScrollWebView nestedScrollWebView = fragmentView.findViewById(R.id.nestedscroll_webview);
+
+ // Get a handle for the SSL error handler.
+ SslErrorHandler sslErrorHandler = nestedScrollWebView.getSslErrorHandler();
// Remove the incorrect lint warning that `getActivity()` might be null.
assert getActivity() != null;
// Set the view. The parent view is `null` because it will be assigned by `AlertDialog`.
dialogBuilder.setView(layoutInflater.inflate(R.layout.ssl_certificate_error, null));
- // Set a listener on the negative button.
- dialogBuilder.setNegativeButton(R.string.cancel, (DialogInterface dialog, int which) -> sslCertificateErrorListener.onSslErrorCancel());
+ // Set a listener on the cancel button.
+ dialogBuilder.setNegativeButton(R.string.cancel, (DialogInterface dialog, int which) -> {
+ // Check to make sure the SSL error handler is not null. This might happen if multiple dialogs are displayed at once.
+ if (sslErrorHandler != null) {
+ // Cancel the request.
+ sslErrorHandler.cancel();
+
+ // Reset the SSL error handler.
+ nestedScrollWebView.resetSslErrorHandler();
+ }
+ });
+
+ // Set a listener on the proceed button.
+ dialogBuilder.setPositiveButton(R.string.proceed, (DialogInterface dialog, int which) -> {
+ // Check to make sure the SSL error handler is not null. This might happen if multiple dialogs are displayed at once.
+ if (sslErrorHandler != null) {
+ // Cancel the request.
+ sslErrorHandler.proceed();
- // Set a listener on the positive button.
- dialogBuilder.setPositiveButton(R.string.proceed, (DialogInterface dialog, int which) -> sslCertificateErrorListener.onSslErrorProceed());
+ // Reset the SSL error handler.
+ nestedScrollWebView.resetSslErrorHandler();
+ }
+ });
// Create an alert dialog from the alert dialog builder.
SpannableStringBuilder endDateStringBuilder = new SpannableStringBuilder((endDateLabel + endDate));
// Create a red foreground color span. The deprecated `getResources().getColor` must be used until the minimum API >= 23.
- @SuppressWarnings("deprecation") ForegroundColorSpan redColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.red_a700));
+ ForegroundColorSpan redColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.red_a700));
// Create a blue `ForegroundColorSpan`.
ForegroundColorSpan blueColorSpan;
// Set a blue color span according to the theme. The deprecated `getResources().getColor` must be used until the minimum API >= 23.
if (darkTheme) {
- //noinspection deprecation
blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue_400));
} else {
- //noinspection deprecation
blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue_700));
}
// Set the blue color span according to the theme. The deprecated `getColor()` must be used until the minimum API >= 23.
if (darkTheme) {
- //noinspection deprecation
blueColorSpan = new ForegroundColorSpan(activity.getResources().getColor(R.color.blue_400));
} else {
- //noinspection deprecation
blueColorSpan = new ForegroundColorSpan(activity.getResources().getColor(R.color.blue_700));
}
import com.stoutner.privacybrowser.BuildConfig;
import com.stoutner.privacybrowser.R;
-import com.stoutner.privacybrowser.activities.MainWebViewActivity;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Date;
public class AboutTabFragment extends Fragment {
- // Track the current tab number.
+ // Declare the class variables.
private int tabNumber;
+ private String[] blocklistVersions;
- // Store the tab number in the arguments bundle.
- public static AboutTabFragment createTab(int tab) {
+ public static AboutTabFragment createTab(int tabNumber, String[] blocklistVersions) {
// Create a bundle.
- Bundle bundle = new Bundle();
+ Bundle argumentsBundle = new Bundle();
// Store the tab number in the bundle.
- bundle.putInt("Tab", tab);
+ argumentsBundle.putInt("tab_number", tabNumber);
+ argumentsBundle.putStringArray("blocklist_versions", blocklistVersions);
- // Add the bundle to the fragment.
+ // Create a new instance of the tab fragment.
AboutTabFragment aboutTabFragment = new AboutTabFragment();
- aboutTabFragment.setArguments(bundle);
+
+ // Add the arguments bundle to the fragment.
+ aboutTabFragment.setArguments(argumentsBundle);
// Return the new fragment.
return aboutTabFragment;
// Run the default commands.
super.onCreate(savedInstanceState);
- // Remove the lint warning that `getArguments()` might be null.
- assert getArguments() != null;
+ // Get a handle for the arguments.
+ Bundle arguments = getArguments();
+
+ // Remove the incorrect lint warning below that arguments might be null.
+ assert arguments != null;
- // Store the tab number in a class variable.
- tabNumber = getArguments().getInt("Tab");
+ // Store the arguments in class variables.
+ tabNumber = getArguments().getInt("tab_number");
+ blocklistVersions = getArguments().getStringArray("blocklist_versions");
}
@Override
TextView certificateSignatureAlgorithmTextView = tabLayout.findViewById(R.id.certificate_signature_algorithm);
// Setup the labels.
- String version = getString(R.string.version) + " " + BuildConfig.VERSION_NAME + " (" + getString(R.string.version_code) + " " + Integer.toString(BuildConfig.VERSION_CODE) + ")";
+ String version = getString(R.string.version) + " " + BuildConfig.VERSION_NAME + " (" + getString(R.string.version_code) + " " + BuildConfig.VERSION_CODE + ")";
String brandLabel = getString(R.string.brand) + " ";
String manufacturerLabel = getString(R.string.manufacturer) + " ";
String modelLabel = getString(R.string.model) + " ";
String device = Build.DEVICE;
String bootloader = Build.BOOTLOADER;
String radio = Build.getRadioVersion();
- String android = Build.VERSION.RELEASE + " (" + getString(R.string.api) + " " + Integer.toString(Build.VERSION.SDK_INT) + ")";
+ String android = Build.VERSION.RELEASE + " (" + getString(R.string.api) + " " + Build.VERSION.SDK_INT + ")";
String build = Build.DISPLAY;
// Select the substring that begins after `Chrome/` and goes until the next ` `.
String webView = userAgentString.substring(userAgentString.indexOf("Chrome/") + 7, userAgentString.indexOf(" ", userAgentString.indexOf("Chrome/")));
SpannableStringBuilder androidStringBuilder = new SpannableStringBuilder(androidLabel + android);
SpannableStringBuilder buildStringBuilder = new SpannableStringBuilder(buildLabel + build);
SpannableStringBuilder webViewStringBuilder = new SpannableStringBuilder(webViewLabel + webView);
- SpannableStringBuilder easyListStringBuilder = new SpannableStringBuilder(easyListLabel + MainWebViewActivity.easyListVersion);
- SpannableStringBuilder easyPrivacyStringBuilder = new SpannableStringBuilder(easyPrivacyLabel + MainWebViewActivity.easyPrivacyVersion);
- SpannableStringBuilder fanboyAnnoyanceStringBuilder = new SpannableStringBuilder(fanboyAnnoyanceLabel + MainWebViewActivity.fanboysAnnoyanceVersion);
- SpannableStringBuilder fanboySocialStringBuilder = new SpannableStringBuilder(fanboySocialLabel + MainWebViewActivity.fanboysSocialVersion);
- SpannableStringBuilder ultraPrivacyStringBuilder = new SpannableStringBuilder(ultraPrivacyLabel + MainWebViewActivity.ultraPrivacyVersion);
+ SpannableStringBuilder easyListStringBuilder = new SpannableStringBuilder(easyListLabel + blocklistVersions[0]);
+ SpannableStringBuilder easyPrivacyStringBuilder = new SpannableStringBuilder(easyPrivacyLabel + blocklistVersions[1]);
+ SpannableStringBuilder fanboyAnnoyanceStringBuilder = new SpannableStringBuilder(fanboyAnnoyanceLabel + blocklistVersions[2]);
+ SpannableStringBuilder fanboySocialStringBuilder = new SpannableStringBuilder(fanboySocialLabel + blocklistVersions[3]);
+ SpannableStringBuilder ultraPrivacyStringBuilder = new SpannableStringBuilder(ultraPrivacyLabel + blocklistVersions[4]);
// Create the `blueColorSpan` variable.
ForegroundColorSpan blueColorSpan;
// Set `blueColorSpan` according to the theme. We have to use the deprecated `getColor()` until API >= 23.
if (darkTheme) {
- //noinspection deprecation
blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue_400));
} else {
- //noinspection deprecation
blueColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.blue_700));
}
// Load the tabs according to the theme.
if (darkTheme) { // The dark theme is applied.
// Set the background color. The deprecated `.getColor()` must be used until the minimum API >= 23.
- //noinspection deprecation
tabWebView.setBackgroundColor(getResources().getColor(R.color.gray_850));
switch (tabNumber) {
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
+import android.webkit.HttpAuthHandler;
+import android.webkit.SslErrorHandler;
import android.webkit.WebView;
import androidx.annotation.NonNull;
// Keep a copy of the WebView fragment ID.
private long webViewFragmentId;
+ // Store the handlers.
+ private SslErrorHandler sslErrorHandler;
+ private HttpAuthHandler httpAuthHandler;
+
// Track if domain settings are applied to this nested scroll WebView and, if so, the database ID.
private boolean domainSettingsApplied;
private int domainSettingsDatabaseId;
// Track the status of first-party cookies.
private boolean acceptFirstPartyCookies;
+ // Track the domain settings JavaScript status. This can be removed once night mode does not require JavaScript.
+ private boolean domainSettingsJavaScriptEnabled;
+
// Track the resource requests.
private ArrayList<String[]> resourceRequests = new ArrayList<>();
private boolean easyListEnabled;
// The ignore pinned domain information tracker. This is set when a user proceeds past a pinned mismatch dialog to prevent the dialog from showing again until after the domain changes.
private boolean ignorePinnedDomainInformation;
+ // Track navigation of history.
+ private boolean navigatingHistory;
+
// The default or favorite icon.
- Bitmap favoriteOrDefaultIcon;
+ private Bitmap favoriteOrDefaultIcon;
// Track night mode.
private boolean nightMode;
}
+ // SSL error handler.
+ public void setSslErrorHandler(SslErrorHandler sslErrorHandler) {
+ // Store the current SSL error handler.
+ this.sslErrorHandler = sslErrorHandler;
+ }
+
+ public SslErrorHandler getSslErrorHandler() {
+ // Return the current SSL error handler.
+ return sslErrorHandler;
+ }
+
+ public void resetSslErrorHandler() {
+ // Reset the current SSL error handler.
+ sslErrorHandler = null;
+ }
+
+
+ // HTTP authentication handler.
+ public void setHttpAuthHandler(HttpAuthHandler httpAuthHandler) {
+ // Store the current HTTP authentication handler.
+ this.httpAuthHandler = httpAuthHandler;
+ }
+
+ public HttpAuthHandler getHttpAuthHandler() {
+ // Return the current HTTP authentication handler.
+ return httpAuthHandler;
+ }
+
+ public void resetHttpAuthHandler() {
+ // Reset the current HTTP authentication handler.
+ httpAuthHandler = null;
+ }
+
+
// Domain settings.
public void setDomainSettingsApplied(boolean applied) {
// Store the domain settings applied status.
}
+ // Domain settings JavaScript enabled. This can be removed once night mode does not require JavaScript.
+ public void setDomainSettingsJavaScriptEnabled(boolean status) {
+ // Store the domain settings JavaScript status.
+ domainSettingsJavaScriptEnabled = status;
+ }
+
+ public boolean getDomainSettingsJavaScriptEnabled() {
+ // Return the domain settings JavaScript status.
+ return domainSettingsJavaScriptEnabled;
+ }
+
+
// Resource requests.
public void addResourceRequest(String[] resourceRequest) {
// Add the resource request to the list.
}
- // Ignore pinned information. The syntax looks better as written, even if it is always inverted.
+ // Ignore pinned information.
+ public void setIgnorePinnedDomainInformation(boolean status) {
+ // Set the status of the ignore pinned domain information tracker.
+ ignorePinnedDomainInformation = status;
+ }
+
+ // The syntax looks better as written, even if it is always inverted.
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
public boolean ignorePinnedDomainInformation() {
// Return the status of the ignore pinned domain information tracker.
return ignorePinnedDomainInformation;
}
- public void setIgnorePinnedDomainInformation(boolean status) {
- // Set the status of the ignore pinned domain information tracker.
- ignorePinnedDomainInformation = status;
+
+ // Navigating history.
+ public void setNavigatingHistory(boolean status) {
+ // Set the status of navigating history.
+ navigatingHistory = status;
+ }
+
+ public boolean getNavigatingHistory() {
+ // Return the status of navigating history.
+ return navigatingHistory;
}
android:id="@+id/tablayout"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
+ app:tabIndicatorGravity="top"
app:tabMode="scrollable" />
<!-- `style="?android:borderlessButtonStyle"` shows a visual indication when the image view is tapped. -->
android:layout_height="3dp"
android:layout_width="match_parent"
android:max="100"
- android:progressTint="@color/yellow_a700"
+ android:progressTint="?attr/progressTintColor"
android:progressBackgroundTint="@color/transparent"
android:visibility="gone"
tools:ignore="UnusedAttribute" />
<string name="no_title">Kein Titel</string>
<string name="unrecognized_url">Unbekannte URL:</string>
<string name="open_with">Öffnen mit</string>
+ <string name="new_tab">Neuer Tab</string>
+ <string name="add_tab">Tab hinzufügen</string>
<!-- Save As. -->
<string name="save_as">Speichern Unter</string>
<!-- MainWebViewActivity Navigation Menu. -->
<string name="navigation_drawer">Navigationspanel</string>
<string name="navigation">Navigation</string>
+ <string name="close_tab">Tab schließen</string>
<string name="clear_and_exit">Leeren und verlassen</string>
<string name="home">Startseite</string>
<string name="back">Zurück</string>
<string name="stop">Stop</string>
<!-- Context Menus. -->
+ <string name="open_in_new_tab">In neuem Tab öffnen</string>
<string name="copy_url">URL kopieren</string>
<string name="download_url">Download URL</string>
<string name="email_address">E-Mail-Adresse</string>
<string name="javascript_preference">JavaScript standardmäßig aktivieren</string>
<string name="javascript_preference_summary">JavaScript ermöglicht es Websites, Programme (Scripts) auf Ihrem Gerät auszuführen.</string>
<string name="first_party_cookies_preference">Erstanbieter-Cookies standardmäßig aktivieren</string>
+ <string name="first_party_cookies_preference_summary">Da die Cookie-Einstellungen App-weit gelten, werden, wenn im aktiven Tab Cookies erlaubt sind,
+ auch in den Hintergrund-Tabs Cookies der dort angezeigten Seiten und deren Domains angenommen.
+ Unter Android KitKat (version 4.4.x) wird nicht zwischen Cookies und Drittanbieter-Cookies unterschieden,
+ sodass in dieser Version mit dieser Einstellung beide Cookie-Varianten aktiviert werden.</string>
<string name="third_party_cookies_preference">Drittanbieter-Cookies standardmäßig aktivieren</string>
<string name="third_party_cookies_summary">Diese Option benötigt Android Lollipop (Version 5.0) oder höher. Sie hat keine Auswirkungen, wenn Erstanbieter-Cookies deaktiviert sind.</string>
<string name="dom_storage_preference">DOM-Speicher standardmäßig aktivieren</string>
<string name="no_title">Nessun titolo</string>
<string name="unrecognized_url">URL non riconosciuta:</string>
<string name="open_with">Apri con</string>
+ <string name="new_tab">Nuova Scheda</string>
+ <string name="add_tab">Aggiungi Scheda</string>
<!-- Save As. -->
<string name="save_as">Salva come</string>
<!-- MainWebViewActivity Navigation Menu. -->
<string name="navigation_drawer">Menù di navigazione</string>
<string name="navigation">Navigazione</string>
+ <string name="close_tab">Chiudi Scheda</string>
<string name="clear_and_exit">Elimina dati ed esci</string>
<string name="home">Home</string>
<string name="back">Indietro</string>
<string name="stop">Stop</string>
<!-- Context Menus. -->
+ <string name="open_in_new_tab">Apri in una nuova Scheda</string>
<string name="copy_url">Copia URL</string>
<string name="download_url">Scarica URL</string>
<string name="email_address">Indirizzo Email</string>
<string name="javascript_preference">Abilita JavaScript</string>
<string name="javascript_preference_summary">Permetti a JavaScript di eseguire programmi (script) sul dispositivo.</string>
<string name="first_party_cookies_preference">Abilita cookies proprietari</string>
+ <string name="first_party_cookies_preference_summary">Dal momento che i cookie proprietari sono un\'impostazione a livello di applicazione,
+ quando la scheda attiva ha i cookie proprietari attivati anche ogni richiesta di rete in background da parte delle altre schede includerà i cookie per i relativi domini.
+ Android KitKat (versione 4.4.x) inoltre non distingue tra cookie proprietari e cookie di terze parti e pertanto li abiliterà entrambi con questa impostazione.</string>
<string name="third_party_cookies_preference">Abilita cookies di terze parti</string>
<string name="third_party_cookies_summary">Questa impostazione richiede Android Lollipop (version 5.0) o successivo. Non ha effetti se i cookies proprietari sono disabilitati.</string>
<string name="dom_storage_preference">Abilita DOM Storage</string>
<string name="no_title">Başlıksız</string>
<string name="unrecognized_url">Onaylanmayan URL:</string>
<string name="open_with">Bununla aç</string>
+ <string name="new_tab">Yeni Sekme</string>
+ <string name="add_tab">Sekme Ekle</string>
<!-- Save As. -->
<string name="save_as">Farklı Kaydet</string>
<!-- MainWebViewActivity Navigation Menu. -->
<string name="navigation_drawer">Açılır Menü</string>
<string name="navigation">Gezinti</string>
+ <string name="close_tab">Sekmeyi Kapa</string>
<string name="clear_and_exit">Temizle ve Çık</string>
<string name="home">Anasayfa</string>
<string name="back">Geri</string>
<string name="stop">Dur</string>
<!-- Context Menus. -->
+ <string name="open_in_new_tab">Yeni Sekmede Aç</string>
<string name="copy_url">URL Kopyala</string>
<string name="download_url">URL İndir</string>
<string name="email_address">Eposta Adresi</string>
<string name="javascript_preference">JavaScript\'i varsayılan olarak etkinleştir</string>
<string name="javascript_preference_summary">JavaScript web sitelerin cihazdaki programları(scriptler) çalıştırmasına izin verir.</string>
<string name="first_party_cookies_preference">Birinci taraf çerezleri varsayılan olarak etkinleştir</string>
+ <string name="first_party_cookies_preference_summary">Birinci taraf çerezleri uygulama düzeyinde bir ayar olduğundan, aktif sekmede çerezler etkinleştirildiğinde,
+ arka plandaki diğer sekmeler tarafından yapılan herhangi ağ istekleri, domainler için kayıtlı çerezleri de içerecektir.
+ Android KitKat (sürüm 4.4.x), birinci ve üçüncü taraf çerezleri arasında ayrım yapmaz ve bu ayarda ikisini de etkinleştirir.</string>
<string name="third_party_cookies_preference">Üçüncü taraf çerezleri varsayılan olarak etkinleştir</string>
<string name="third_party_cookies_summary">Bu ayarı etkinleştirmek için Android Lollipop sürümüne(5.0) ya da daha üst sürümlere sahip olmak gerekir.
Birinci taraf çerezler devre dışı olduğu takdirde etkisi yoktur.</string>
<!-- `android:windowTranslucentStatus` makes the system status bar translucent. When it is specified the root layout should include `android:fitsSystemWindows="true"`. -->
<style name="PrivacyBrowserLight" parent="Theme.AppCompat.Light.NoActionBar" >
+ <item name="aboutIcon">@drawable/about_light</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="addTabIconTintColor">@color/gray_700</item>
<item name="android:textColorPrimary">@color/primary_text_color_selector_light</item>
<item name="colorAccent">@color/blue_700</item>
+ <item name="dialogTabLayoutTheme">@style/PrivacyBrowserTabLayoutDialogLight</item>
<item name="android:textColorHighlight">@color/blue_200</item>
<item name="mainStatusBarBackground">@color/gray_500</item>
<item name="navigationHeaderBackground">@color/blue_700</item>
<item name="appBarTheme">@style/PrivacyBrowserAppBarLight</item>
<item name="navigationIconTintColor">@color/blue_800</item>
<item name="findOnPageIconTintColor">@color/blue_800</item>
- <item name="viewSourceIconTintColor">@color/black</item>
+ <item name="progressTintColor">@color/blue_700</item>
+ <item name="redText">@color/red_a700</item>
<item name="sslHeader">@color/blue_700</item>
<item name="sslTitle">@color/blue_900</item>
<item name="urlHistoryText">@color/black</item>
- <item name="redText">@color/red_a700</item>
- <item name="aboutIcon">@drawable/about_light</item>
- <item name="dialogTabLayoutTheme">@style/PrivacyBrowserTabLayoutDialogLight</item>
+ <item name="viewSourceIconTintColor">@color/black</item>
</style>
<!-- `windowActionModeOverlay` makes the contextual app bar cover the support app bar. -->
<!-- `android:windowTranslucentStatus` makes the system status bar translucent. When it is specified the root layout should include `android:fitsSystemWindows="true"`. -->
<style name="PrivacyBrowserDark" parent="Theme.AppCompat.NoActionBar" >
+ <item name="aboutIcon">@drawable/about_dark</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="addTabIconTintColor">@color/gray_400</item>
<item name="android:textColorPrimary">@color/primary_text_color_selector_dark</item>
<item name="navigationHeaderBackground">@color/blue_800</item>
<item name="navigationHeaderTextColor">@color/gray_300</item>
<item name="appBarTheme">@style/PrivacyBrowserAppBarDark</item>
- <item name="navigationIconTintColor">@color/blue_600</item>
<item name="findOnPageIconTintColor">@color/blue_600</item>
- <item name="viewSourceIconTintColor">@color/gray_300</item>
+ <item name="navigationIconTintColor">@color/blue_600</item>
+ <item name="progressTintColor">@color/blue_600</item>
+ <item name="redText">@color/red_900</item>
<item name="sslHeader">@color/blue_400</item>
<item name="sslTitle">@color/blue_700</item>
<item name="urlHistoryText">@color/gray_200</item>
- <item name="redText">@color/red_900</item>
- <item name="aboutIcon">@drawable/about_dark</item>
+ <item name="viewSourceIconTintColor">@color/gray_300</item>
</style>
<!-- `windowActionModeOverlay` makes the contextual app bar cover the support app bar. `colorPrimaryDark` goes behind the status bar, which is then darkened by the overlay.-->
<attr name="domainSettingsIconTintColor" format="reference" />
<attr name="findOnPageIconTintColor" format="reference" />
<attr name="navigationIconTintColor" format="reference" />
+ <attr name="progressTintColor" format="reference" />
<attr name="viewSourceIconTintColor" format="reference" />
<attr name="listSelectorDrawable" format="reference" />
<!-- `android:windowTranslucentStatus` makes the system status bar translucent. When it is specified the root layout should include `android:fitsSystemWindows="true"`. -->
<style name="PrivacyBrowserLight" parent="Theme.AppCompat.Light.NoActionBar" >
+ <item name="aboutIcon">@drawable/about_light</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="addTabIconTintColor">@color/gray_700</item>
<item name="android:textColorPrimary">@color/primary_text_color_selector_light</item>
<item name="colorAccent">@color/blue_700</item>
+ <item name="dialogTabLayoutTheme">@style/PrivacyBrowserTabLayoutDialogLight</item>
<item name="android:textColorHighlight">@color/blue_200</item>
<item name="mainStatusBarBackground">@color/gray_500</item>
<item name="navigationHeaderBackground">@color/blue_700</item>
<item name="appBarTheme">@style/PrivacyBrowserAppBarLight</item>
<item name="navigationIconTintColor">@color/blue_800</item>
<item name="findOnPageIconTintColor">@color/blue_800</item>
- <item name="viewSourceIconTintColor">@color/black</item>
+ <item name="progressTintColor">@color/blue_700</item>
+ <item name="redText">@color/red_a700</item>
<item name="sslHeader">@color/blue_700</item>
<item name="sslTitle">@color/blue_900</item>
<item name="urlHistoryText">@color/black</item>
- <item name="redText">@color/red_a700</item>
- <item name="aboutIcon">@drawable/about_light</item>
- <item name="dialogTabLayoutTheme">@style/PrivacyBrowserTabLayoutDialogLight</item>
+ <item name="viewSourceIconTintColor">@color/black</item>
</style>
<!-- `windowActionModeOverlay` makes the contextual app bar cover the support app bar. -->
<!-- `android:windowTranslucentStatus` makes the system status bar translucent. When it is specified the root layout should include `android:fitsSystemWindows="true"`. -->
<style name="PrivacyBrowserDark" parent="Theme.AppCompat.NoActionBar" >
+ <item name="aboutIcon">@drawable/about_dark</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="addTabIconTintColor">@color/gray_400</item>
<item name="android:textColorPrimary">@color/primary_text_color_selector_dark</item>
<item name="navigationHeaderBackground">@color/blue_800</item>
<item name="navigationHeaderTextColor">@color/gray_300</item>
<item name="appBarTheme">@style/PrivacyBrowserAppBarDark</item>
- <item name="navigationIconTintColor">@color/blue_600</item>
<item name="findOnPageIconTintColor">@color/blue_600</item>
- <item name="viewSourceIconTintColor">@color/gray_300</item>
+ <item name="navigationIconTintColor">@color/blue_600</item>
+ <item name="progressTintColor">@color/blue_600</item>
+ <item name="redText">@color/red_900</item>
<item name="sslHeader">@color/blue_400</item>
<item name="sslTitle">@color/blue_700</item>
<item name="urlHistoryText">@color/gray_200</item>
- <item name="redText">@color/red_900</item>
- <item name="aboutIcon">@drawable/about_dark</item>
+ <item name="viewSourceIconTintColor">@color/gray_300</item>
</style>
<!-- `windowActionModeOverlay` makes the contextual app bar cover the support app bar. `colorPrimaryDark` goes behind the status bar, which is then darkened by the overlay.-->
google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.3.2'
+ classpath 'com.android.tools.build:gradle:3.4.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
-#Tue Jan 15 11:00:04 MST 2019
+#Wed Apr 17 14:57:58 MST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip