]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blobdiff - app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java
Fix a rare crash on resource requests. https://redmine.stoutner.com/issues/645
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / activities / MainWebViewActivity.java
index 7cbe286dcd81fdf529caed9acc2b8bc7547ea8f7..9d001fe0d2c990ae293973c02fc93837ca4aaaa6 100644 (file)
@@ -332,6 +332,13 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     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`.
@@ -404,6 +411,13 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         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();
@@ -454,17 +468,18 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // 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);
 
@@ -485,9 +500,12 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                     // 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.
@@ -593,14 +611,16 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // 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);
@@ -644,12 +664,14 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                 // 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.
@@ -739,9 +761,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         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);
@@ -767,18 +789,18 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // 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.
@@ -793,9 +815,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                 // 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);
                 }
             }
         }
@@ -1706,8 +1728,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             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);
@@ -3242,8 +3264,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         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);
@@ -3253,12 +3273,10 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // 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() {
@@ -4388,7 +4406,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             // 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.
@@ -4414,30 +4431,23 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 }
             }
 
-            // 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();
@@ -4661,7 +4671,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         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);
@@ -4706,12 +4716,13 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             // 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);
 
@@ -4732,9 +4743,12 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                     // 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.
@@ -4788,12 +4802,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     }
 
     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();
 
@@ -5788,15 +5799,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 // 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()));
 
@@ -6194,7 +6196,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     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) {
@@ -6203,9 +6205,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                         // 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);
                         }
                     }
                 }
@@ -6227,7 +6229,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     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) {
@@ -6415,6 +6417,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             // 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.
@@ -6430,13 +6433,12 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
                 // 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;
@@ -6451,6 +6453,10 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             } 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);