// Declare the class views.
private DrawerLayout drawerLayout;
private AppBarLayout appBarLayout;
+ private Toolbar toolbar;
+ private LinearLayout findOnPageLinearLayout;
+ private LinearLayout tabsLinearLayout;
private TabLayout tabLayout;
+ private SwipeRefreshLayout swipeRefreshLayout;
private ViewPager webViewPager;
+ private NavigationView navigationView;
+
+ // Declare the class menus.
+ private Menu navigationMenu;
+
+ // Declare the class menu items.
+ private MenuItem navigationRequestsMenuItem;
@Override
// Remove the warning about needing to override `performClick()` when using an `OnTouchListener` with `WebView`.
// Get handles for the views.
drawerLayout = findViewById(R.id.drawerlayout);
appBarLayout = findViewById(R.id.appbar_layout);
- Toolbar toolbar = findViewById(R.id.toolbar);
+ toolbar = findViewById(R.id.toolbar);
+ findOnPageLinearLayout = findViewById(R.id.find_on_page_linearlayout);
+ tabsLinearLayout = findViewById(R.id.tabs_linearlayout);
tabLayout = findViewById(R.id.tablayout);
+ swipeRefreshLayout = findViewById(R.id.swiperefreshlayout);
webViewPager = findViewById(R.id.webviewpager);
+ navigationView = findViewById(R.id.navigationview);
+
+ // Get handles for the class menus.
+ navigationMenu = navigationView.getMenu();
+
+ // Get a handle for the navigation requests menu item.
+ navigationRequestsMenuItem = navigationMenu.findItem(R.id.requests);
// Get a handle for the app compat delegate.
AppCompatDelegate appCompatDelegate = getDelegate();
// Replace the intent that started the app with this one.
setIntent(intent);
- // Check to see if the app is being restarted.
- if (savedStateArrayList == null || savedStateArrayList.size() == 0) { // The activity is running for the first time.
+ // Check to see if the app is being restarted from a saved state.
+ if (savedStateArrayList == null || savedStateArrayList.size() == 0) { // The activity is not being restarted from a saved state.
// Get the information from the intent.
String intentAction = intent.getAction();
Uri intentUriData = intent.getData();
+ String intentStringExtra = intent.getStringExtra(Intent.EXTRA_TEXT);
// Determine if this is a web search.
boolean isWebSearch = ((intentAction != null) && intentAction.equals(Intent.ACTION_WEB_SEARCH));
// Only process the URI if it contains data or it is a web search. If the user pressed the desktop icon after the app was already running the URI will be null.
- if (intentUriData != null || isWebSearch) {
+ if (intentUriData != null || intentStringExtra != null || isWebSearch) {
// Get the shared preferences.
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
// Add the base search URL.
url = searchURL + encodedUrlString;
- } else { // The intent should contain a URL.
+ } else if (intentUriData != null) { // The intent contains a URL formatted as a URI.
// Set the intent data as the URL.
url = intentUriData.toString();
+ } else { // The intent contains a string, which might be a URL.
+ // Set the intent string as the URL.
+ url = intentStringExtra;
}
// Add a new tab if specified in the preferences.
// Get the nested scroll WebView from the tab fragment.
NestedScrollWebView nestedScrollWebView = fragmentView.findViewById(R.id.nestedscroll_webview);
- // Resume the nested scroll WebView JavaScript timers.
- nestedScrollWebView.resumeTimers();
-
// Resume the nested scroll WebView.
nestedScrollWebView.onResume();
}
}
+ // Resume the nested scroll WebView JavaScript timers. This is a global command that resumes JavaScript timers on all WebViews.
+ if (currentWebView != null) {
+ currentWebView.resumeTimers();
+ }
+
// Reapply the proxy settings if the system is using a proxy. This redisplays the appropriate alert dialog.
if (!proxyMode.equals(ProxyHelper.NONE)) {
applyProxy(false);
// Pause the nested scroll WebView.
nestedScrollWebView.onPause();
-
- // Pause the nested scroll WebView JavaScript timers.
- nestedScrollWebView.pauseTimers();
}
}
+ // Pause the WebView JavaScript timers. This is a global command that pauses JavaScript on all WebViews.
+ if (currentWebView != null) {
+ currentWebView.pauseTimers();
+ }
+
// Pause the ad or it will continue to consume resources in the background on the free flavor.
if (BuildConfig.FLAVOR.contentEquals("free")) {
// Pause the ad.
updatePrivacyIcons(false);
// Get handles for the menu items.
+ MenuItem bookmarksMenuItem = menu.findItem(R.id.bookmarks);
MenuItem toggleFirstPartyCookiesMenuItem = menu.findItem(R.id.toggle_first_party_cookies);
MenuItem toggleThirdPartyCookiesMenuItem = menu.findItem(R.id.toggle_third_party_cookies);
- MenuItem toggleDomStorageMenuItem = menu.findItem(R.id.toggle_dom_storage);
MenuItem toggleSaveFormDataMenuItem = menu.findItem(R.id.toggle_save_form_data); // Form data can be removed once the minimum API >= 26.
MenuItem clearFormDataMenuItem = menu.findItem(R.id.clear_form_data); // Form data can be removed once the minimum API >= 26.
MenuItem refreshMenuItem = menu.findItem(R.id.refresh);
// Get the shared preferences.
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
- // Get the dark theme and app bar preferences..
- boolean displayAdditionalAppBarIcons = sharedPreferences.getBoolean("display_additional_app_bar_icons", false);
+ // Get the dark theme and app bar preferences.
+ boolean displayAdditionalAppBarIcons = sharedPreferences.getBoolean(getString(R.string.display_additional_app_bar_icons_key), false);
// Set the status of the additional app bar icons. Setting the refresh menu item to `SHOW_AS_ACTION_ALWAYS` makes it appear even on small devices like phones.
if (displayAdditionalAppBarIcons) {
- toggleFirstPartyCookiesMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
- toggleDomStorageMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
refreshMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+ bookmarksMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ toggleFirstPartyCookiesMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
} else { //Do not display the additional icons.
- toggleFirstPartyCookiesMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
- toggleDomStorageMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
refreshMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+ bookmarksMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+ toggleFirstPartyCookiesMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
}
// Replace Refresh with Stop if a URL is already loading.
// Set the icon according to the current theme status.
if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
- refreshMenuItem.setIcon(R.drawable.close_day);
+ refreshMenuItem.setIcon(R.drawable.close_blue_day);
} else {
- refreshMenuItem.setIcon(R.drawable.close_night);
+ refreshMenuItem.setIcon(R.drawable.close_blue_night);
}
}
}
Intent viewSourceIntent = new Intent(this, ViewSourceActivity.class);
// Add the variables to the intent.
- viewSourceIntent.putExtra("user_agent", currentWebView.getSettings().getUserAgentString());
- viewSourceIntent.putExtra("current_url", currentWebView.getUrl());
+ viewSourceIntent.putExtra(ViewSourceActivityKt.CURRENT_URL, currentWebView.getUrl());
+ viewSourceIntent.putExtra(ViewSourceActivityKt.USER_AGENT, currentWebView.getSettings().getUserAgentString());
// Make it so.
startActivity(viewSourceIntent);
this.registerReceiver(orbotStatusBroadcastReceiver, new IntentFilter("org.torproject.android.intent.action.STATUS"));
// Get handles for views that need to be modified.
- NavigationView navigationView = findViewById(R.id.navigationview);
- SwipeRefreshLayout swipeRefreshLayout = findViewById(R.id.swiperefreshlayout);
ListView bookmarksListView = findViewById(R.id.bookmarks_drawer_listview);
FloatingActionButton launchBookmarksActivityFab = findViewById(R.id.launch_bookmarks_activity_fab);
FloatingActionButton createBookmarkFolderFab = findViewById(R.id.create_bookmark_folder_fab);
// Listen for touches on the navigation menu.
navigationView.setNavigationItemSelectedListener(this);
- // Get handles for the navigation menu and the back and forward menu items.
- Menu navigationMenu = navigationView.getMenu();
+ // Get handles for the navigation menu items.
MenuItem navigationBackMenuItem = navigationMenu.findItem(R.id.back);
MenuItem navigationForwardMenuItem = navigationMenu.findItem(R.id.forward);
MenuItem navigationHistoryMenuItem = navigationMenu.findItem(R.id.history);
- MenuItem navigationRequestsMenuItem = navigationMenu.findItem(R.id.requests);
// Update the web view pager every time a tab is modified.
webViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
// Get handles for the views that need to be modified.
FrameLayout rootFrameLayout = findViewById(R.id.root_framelayout);
ActionBar actionBar = appCompatDelegate.getSupportActionBar();
- Toolbar toolbar = findViewById(R.id.toolbar);
- LinearLayout findOnPageLinearLayout = findViewById(R.id.find_on_page_linearlayout);
- LinearLayout tabsLinearLayout = findViewById(R.id.tabs_linearlayout);
- SwipeRefreshLayout swipeRefreshLayout = findViewById(R.id.swiperefreshlayout);
// Remove the incorrect lint warning below that the action bar might be null.
assert actionBar != null;
// Get handles for the menu items.
MenuItem privacyMenuItem = optionsMenu.findItem(R.id.toggle_javascript);
MenuItem firstPartyCookiesMenuItem = optionsMenu.findItem(R.id.toggle_first_party_cookies);
- MenuItem domStorageMenuItem = optionsMenu.findItem(R.id.toggle_dom_storage);
MenuItem refreshMenuItem = optionsMenu.findItem(R.id.refresh);
// Update the privacy icon.
}
}
- // Update the DOM storage icon.
- if (currentWebView.getSettings().getJavaScriptEnabled() && currentWebView.getSettings().getDomStorageEnabled()) { // Both JavaScript and DOM storage are enabled.
- domStorageMenuItem.setIcon(R.drawable.dom_storage_enabled);
- } else if (currentWebView.getSettings().getJavaScriptEnabled()) { // JavaScript is enabled but DOM storage is disabled.
+ // Update the refresh icon.
+ if (refreshMenuItem.getTitle() == getString(R.string.refresh)) { // The refresh icon is displayed.
+ // Set the icon according to the theme.
if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
- domStorageMenuItem.setIcon(R.drawable.dom_storage_disabled_day);
+ refreshMenuItem.setIcon(R.drawable.refresh_enabled_day);
} else {
- domStorageMenuItem.setIcon(R.drawable.dom_storage_disabled_night);
+ refreshMenuItem.setIcon(R.drawable.refresh_enabled_night);
}
- } else { // JavaScript is disabled, so DOM storage is ghosted.
+ } else { // The stop icon is displayed.
+ // Set the icon according to the theme.
if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
- domStorageMenuItem.setIcon(R.drawable.dom_storage_ghosted_day);
+ refreshMenuItem.setIcon(R.drawable.close_blue_day);
} else {
- domStorageMenuItem.setIcon(R.drawable.dom_storage_ghosted_night);
+ refreshMenuItem.setIcon(R.drawable.close_blue_night);
}
}
- // Update the refresh icon.
- if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
- refreshMenuItem.setIcon(R.drawable.refresh_enabled_day);
- } else {
- refreshMenuItem.setIcon(R.drawable.refresh_enabled_night);
- }
-
// `invalidateOptionsMenu()` calls `onPrepareOptionsMenu()` and redraws the icons in the app bar.
if (runInvalidateOptionsMenu) {
invalidateOptionsMenu();
ultraList = combinedBlocklists.get(4);
ultraPrivacy = combinedBlocklists.get(5);
- // Check to see if the activity has been restarted.
+ // Check to see if the activity has been restarted with a saved state.
if ((savedStateArrayList == null) || (savedStateArrayList.size() == 0)) { // The activity has not been restarted or it was restarted on start to force the night theme.
// Add the first tab.
addNewTab("", true);
// Get the information from the intent.
String intentAction = intent.getAction();
Uri intentUriData = intent.getData();
+ String intentStringExtra = intent.getStringExtra(Intent.EXTRA_TEXT);
// Determine if this is a web search.
boolean isWebSearch = ((intentAction != null) && intentAction.equals(Intent.ACTION_WEB_SEARCH));
// Only process the URI if it contains data or it is a web search. If the user pressed the desktop icon after the app was already running the URI will be null.
- if (intentUriData != null || isWebSearch) {
+ if (intentUriData != null || intentStringExtra != null || isWebSearch) {
// Get the shared preferences.
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
// Add the base search URL.
url = searchURL + encodedUrlString;
- } else { // The intent should contain a URL.
- // Set the intent data as the url.
+ } else if (intentUriData != null) { // The intent contains a URL formatted as a URI.
+ // Set the intent data as the URL.
url = intentUriData.toString();
+ } else { // The intent contains a string, which might be a URL.
+ // Set the intent string as the URL.
+ url = intentStringExtra;
}
// Add a new tab if specified in the preferences.
}
private void closeCurrentTab() {
- // Pause the current WebView.
+ // Pause the current WebView. This prevents buffered audio from playing after the tab is closed.
currentWebView.onPause();
- // Pause the current WebView JavaScript timers.
- currentWebView.pauseTimers();
-
// Get the current tab number.
int currentTabNumber = tabLayout.getSelectedTabPosition();
// Hide the action bar.
actionBar.hide();
- // If the app bar is not being scrolled, the swipe refresh layout needs to be adjusted.
- if (!scrollAppBar) {
+ // Check to see if the app bar is normally scrolled.
+ if (scrollAppBar) { // The app bar is scrolled when it is displayed.
+ // Get the swipe refresh layout parameters.
+ CoordinatorLayout.LayoutParams swipeRefreshLayoutParams = (CoordinatorLayout.LayoutParams) swipeRefreshLayout.getLayoutParams();
+
+ // Remove the off-screen scrolling layout.
+ swipeRefreshLayoutParams.setBehavior(null);
+ } else { // The app bar is not scrolled when it is displayed.
// Remove the padding from the top of the swipe refresh layout.
swipeRefreshLayout.setPadding(0, 0, 0, 0);
// Show the action bar.
actionBar.show();
- // If the app bar is not being scrolled, the swipe refresh layout needs to be adjusted.
- if (!scrollAppBar) {
+ // Check to see if the app bar is normally scrolled.
+ if (scrollAppBar) { // The app bar is scrolled when it is displayed.
+ // Get the swipe refresh layout parameters.
+ CoordinatorLayout.LayoutParams swipeRefreshLayoutParams = (CoordinatorLayout.LayoutParams) swipeRefreshLayout.getLayoutParams();
+
+ // Add the off-screen scrolling layout.
+ swipeRefreshLayoutParams.setBehavior(new AppBarLayout.ScrollingViewBehavior());
+ } else { // The app bar is not scrolled when it is displayed.
// The swipe refresh layout must be manually moved below the app bar layout.
swipeRefreshLayout.setPadding(0, appBarHeight, 0, 0);
// Sanitize the URL.
url = sanitizeUrl(url);
- // Get a handle for the navigation view.
- NavigationView navigationView = findViewById(R.id.navigationview);
-
- // Get a handle for the navigation menu.
- Menu navigationMenu = navigationView.getMenu();
-
- // Get a handle for the navigation requests menu item.
- MenuItem navigationRequestsMenuItem = navigationMenu.findItem(R.id.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()));
refreshMenuItem.setTitle(R.string.stop);
// Get the app bar and theme preferences.
- boolean displayAdditionalAppBarIcons = sharedPreferences.getBoolean("display_additional_app_bar_icons", false);
+ boolean displayAdditionalAppBarIcons = sharedPreferences.getBoolean(getString(R.string.display_additional_app_bar_icons_key), false);
// If the icon is displayed in the AppBar, set it according to the theme.
if (displayAdditionalAppBarIcons) {
// Set the stop icon according to the theme.
if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
- refreshMenuItem.setIcon(R.drawable.close_day);
+ refreshMenuItem.setIcon(R.drawable.close_blue_day);
} else {
- refreshMenuItem.setIcon(R.drawable.close_night);
+ refreshMenuItem.setIcon(R.drawable.close_blue_night);
}
}
}
refreshMenuItem.setTitle(R.string.refresh);
// Get the app bar and theme preferences.
- boolean displayAdditionalAppBarIcons = sharedPreferences.getBoolean("display_additional_app_bar_icons", false);
+ boolean displayAdditionalAppBarIcons = sharedPreferences.getBoolean(getString(R.string.display_additional_app_bar_icons_key), false);
// If the icon is displayed in the app bar, reset it according to the theme.
if (displayAdditionalAppBarIcons) {
// Get the information from the intent.
String launchingIntentAction = launchingIntent.getAction();
Uri launchingIntentUriData = launchingIntent.getData();
+ String launchingIntentStringExtra = launchingIntent.getStringExtra(Intent.EXTRA_TEXT);
// Parse the launching intent URL.
if ((launchingIntentAction != null) && launchingIntentAction.equals(Intent.ACTION_WEB_SEARCH)) { // The intent contains a search string.
// Store the web search as the URL to load.
urlToLoadString = searchURL + encodedUrlString;
- } else if (launchingIntentUriData != null){ // The intent contains a URL.
- // Store the URL.
+ } else if (launchingIntentUriData != null) { // The launching intent contains a URL formatted as a URI.
+ // Store the URI as a URL.
urlToLoadString = launchingIntentUriData.toString();
-
- // Reset the intent. This prevents a duplicate tab from being created on a subsequent restart if loading an link from a new intent on restart.
- // For example, this prevents a duplicate tab if a link is loaded from the Guide after changing the theme in the guide and then changing the theme again in the main activity.
- setIntent(new Intent());
+ } else if (launchingIntentStringExtra != null) { // The launching intent contains text that might be a URL.
+ // Store the URL.
+ urlToLoadString = launchingIntentStringExtra;
} else if (!url.equals("")) { // The activity has been restarted.
// Load the saved URL.
urlToLoadString = url;
} else { // Load the URL.
loadUrl(nestedScrollWebView, urlToLoadString);
}
+
+ // Reset the intent. This prevents a duplicate tab from being created on a subsequent restart if loading an link from a new intent on restart.
+ // For example, this prevents a duplicate tab if a link is loaded from the Guide after changing the theme in the guide and then changing the theme again in the main activity.
+ setIntent(new Intent());
} else { // This is not the first tab.
// Load the URL.
loadUrl(nestedScrollWebView, url);