X-Git-Url: https://gitweb.stoutner.com/?a=blobdiff_plain;f=app%2Fsrc%2Fmain%2Fjava%2Fcom%2Fstoutner%2Fprivacybrowser%2Factivities%2FMainWebViewActivity.java;h=9cb3a71a4ce61628206eef57e3b0e81a1b438adf;hb=65753c63057ebb382a4ff2b14c1cc27460dc15e6;hp=8aad8721b596501867e0a30f4fa9c759fabfa3cd;hpb=1cafe068c513943996a59c8ba94945832792061e;p=PrivacyBrowserAndroid.git diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java index 8aad8721..9cb3a71a 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java @@ -1,5 +1,5 @@ /* - * Copyright © 2015-2017 Soren Stoutner . + * Copyright © 2015-2018 Soren Stoutner . * * Download cookie code contributed 2017 Hendrik Knackstedt. Copyright assigned to Soren Stoutner . * @@ -54,6 +54,10 @@ import android.support.design.widget.NavigationView; import android.support.design.widget.Snackbar; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; +// `ShortcutInfoCompat`, `ShortcutManagerCompat`, and `IconCompat` can be switched to the non-compat version once API >= 26. +import android.support.v4.content.pm.ShortcutInfoCompat; +import android.support.v4.content.pm.ShortcutManagerCompat; +import android.support.v4.graphics.drawable.IconCompat; import android.support.v4.view.GravityCompat; import android.support.v4.widget.DrawerLayout; import android.support.v4.widget.SwipeRefreshLayout; @@ -66,6 +70,7 @@ import android.text.Editable; import android.text.Spanned; import android.text.TextWatcher; import android.text.style.ForegroundColorSpan; +import android.util.Log; import android.util.Patterns; import android.view.ContextMenu; import android.view.GestureDetector; @@ -163,6 +168,9 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD // `webViewTitle` is public static so it can be accessed from `CreateBookmarkDialog` and `CreateHomeScreenShortcutDialog`. It is also used in `onCreate()`. public static String webViewTitle; + // `appliedUserAgentString` is public static so it can be accessed from `ViewSourceActivity`. It is also used in `applyDomainSettings()`. + public static String appliedUserAgentString; + // `displayWebpageImagesBoolean` is public static so it can be accessed from `DomainSettingsFragment`. It is also used in `applyAppSettings()` and `applyDomainSettings()`. public static boolean displayWebpageImagesBoolean; @@ -175,6 +183,9 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD // `restartFromBookmarksActivity` is public static so it can be accessed from `BookmarksActivity`. It is also used in `onRestart()`. public static boolean restartFromBookmarksActivity; + // `easyListVersion` is public static so it can be accessed from `AboutTabFragment`. It is also used in `onCreate()`. + public static String easyListVersion; + // `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; @@ -323,13 +334,9 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD // `urlTextBox` is used in `onCreate()`, `onOptionsItemSelected()`, `loadUrlFromTextBox()`, `loadUrl()`, and `highlightUrlText()`. private EditText urlTextBox; - // `redColorSpan` is used in `onCreate()` and `highlightUrlText()`. + // The color spans are used in `onCreate()` and `highlightUrlText()`. private ForegroundColorSpan redColorSpan; - - // `initialGrayColorSpan` is sued in `onCreate()` and `highlightUrlText()`. private ForegroundColorSpan initialGrayColorSpan; - - // `finalGrayColorSpam` is used in `onCreate()` and `highlightUrlText()`. private ForegroundColorSpan finalGrayColorSpan; // `adView` is used in `onCreate()` and `onConfigurationChanged()`. @@ -393,6 +400,52 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD // Run the default commands. super.onCreate(savedInstanceState); + // **DEBUG** Log the beginning of the loading of the ad blocker. + Log.i("AdBlocker", "Begin loading ad blocker"); + + // Initialize `adServerSet`. + final Set adServersSet = new HashSet<>(); + + // Load the list of ad servers into memory. + try { + // Load `easylist.txt` into a `BufferedReader`. + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(getAssets().open("easylist.txt"))); + + // Create a string for storing each ad server. + String adBlockerEntry; + + // Populate `adServersSet`. + while ((adBlockerEntry = bufferedReader.readLine()) != null) { + //noinspection StatementWithEmptyBody + if (adBlockerEntry.contains("##") || adBlockerEntry.contains("#?#") || adBlockerEntry.contains("#@#") || adBlockerEntry.startsWith("[")) { + // Entries that contain `##`, `#?#`, and `#@#` are for hiding elements in the main page's HTML. Entries that start with `[` describe the AdBlock compatibility level. + + // Do nothing. Privacy Browser does not currently use these entries. + + // **DEBUG** Log the entries that are not added. + // Log.i("AdBlocker", "Not added: " + adBlockerEntry); + } else if (adBlockerEntry.startsWith("!")){ // Entries that begin with `!` are comments. + if (adBlockerEntry.startsWith("! Version:")) { + // Store the EasyList version number. + easyListVersion = adBlockerEntry.substring(11); + } + + // **DEBUG** Log the entries that are not added. + // Log.i("AdBlocker", "Not added: " + adBlockerEntry); + } else { + adServersSet.add(adBlockerEntry); + } + } + + // Close `bufferedReader`. + bufferedReader.close(); + } catch (IOException e) { + // The asset exists, so the `IOException` will never be thrown. + } + + // **DEBUG** Log the finishing of the loading of the ad blocker. + Log.i("AdBlocker", "Finish loading ad blocker"); + // Set the content view. setContentView(R.layout.main_drawerlayout); @@ -411,16 +464,16 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD appBar.setCustomView(R.layout.url_app_bar); appBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); - // Initialize the `ForegroundColorSpans` and `StyleSpan` for highlighting `urlTextBox`. We have to use the deprecated `getColor()` until API >= 23. + // Initialize the foreground color spans for highlighting the URLs. We have to use the deprecated `getColor()` until API >= 23. redColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.red_a700)); initialGrayColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.gray_500)); finalGrayColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.gray_500)); // Get a handle for `urlTextBox`. - urlTextBox = appBar.getCustomView().findViewById(R.id.url_edittext); + urlTextBox = findViewById(R.id.url_edittext); // Remove the formatting from `urlTextBar` when the user is editing the text. - urlTextBox.setOnFocusChangeListener((v, hasFocus) -> { + urlTextBox.setOnFocusChangeListener((View v, boolean hasFocus) -> { if (hasFocus) { // The user is editing `urlTextBox`. // Remove the highlighting. urlTextBox.getText().removeSpan(redColorSpan); @@ -432,8 +485,8 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD } }); - // Set the `Go` button on the keyboard to load the URL in `urlTextBox`. - urlTextBox.setOnKeyListener((v, keyCode, event) -> { + // Set the go button on the keyboard to load the URL in `urlTextBox`. + urlTextBox.setOnKeyListener((View v, int keyCode, KeyEvent event) -> { // If the event is a key-down event on the `enter` button, load the URL. if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) { // Load the URL into the mainWebView and consume the event. @@ -790,28 +843,6 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD // drawerToggle creates the hamburger icon at the start of the AppBar. drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, supportAppBar, R.string.open_navigation_drawer, R.string.close_navigation_drawer); - // Initialize `adServerSet`. - final Set adServersSet = new HashSet<>(); - - // Load the list of ad servers into memory. - try { - // Load `pgl.yoyo.org_adservers.txt` into a `BufferedReader`. - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(getAssets().open("pgl.yoyo.org_adservers.txt"))); - - // Create a string for storing each ad server. - String adServer; - - // Populate `adServersSet`. - while ((adServer = bufferedReader.readLine()) != null) { - adServersSet.add(adServer); - } - - // Close `bufferedReader`. - bufferedReader.close(); - } catch (IOException ioException) { - // We're pretty sure the asset exists, so we don't need to worry about the `IOException` ever being thrown. - } - mainWebView.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. // We have to use the deprecated `shouldOverrideUrlLoading` until API >= 24. @@ -1123,7 +1154,10 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD }); } + // Update the progress bar. progressBar.setProgress(progress); + + // Set the visibility of the progress bar. if (progress < 100) { // Show the progress bar. progressBar.setVisibility(View.VISIBLE); @@ -1217,7 +1251,7 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD registerForContextMenu(mainWebView); // Allow the downloading of files. - mainWebView.setDownloadListener((url, userAgent, contentDisposition, mimetype, contentLength) -> { + mainWebView.setDownloadListener((String url, String userAgent, String contentDisposition, String mimetype, long contentLength) -> { // Show the `DownloadFileDialog` `AlertDialog` and name this instance `@string/download`. AppCompatDialogFragment downloadFileDialogFragment = DownloadFileDialog.fromUrl(url, contentDisposition, contentLength); downloadFileDialogFragment.show(getSupportFragmentManager(), getString(R.string.download)); @@ -1456,6 +1490,7 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD 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); + MenuItem clearDataMenuItem = menu.findItem(R.id.clear_data); 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); @@ -1507,6 +1542,9 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD WebViewDatabase mainWebViewDatabase = WebViewDatabase.getInstance(this); clearFormDataMenuItem.setEnabled(mainWebViewDatabase.hasFormData()); + // Enable `Clear Data` if any of the submenu items are enabled. + clearDataMenuItem.setEnabled(clearCookiesMenuItem.isEnabled() || clearDOMStorageMenuItem.isEnabled() || clearFormDataMenuItem.isEnabled()); + // Initialize font size variables. int fontSize = mainWebView.getSettings().getTextZoom(); String fontSizeTitle; @@ -1570,7 +1608,7 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD // Run all the other default commands. super.onPrepareOptionsMenu(menu); - // `return true` displays the menu. + // Display the menu. return true; } @@ -1580,6 +1618,7 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD // removeAllCookies is deprecated, but it is required for API < 21. @SuppressWarnings("deprecation") public boolean onOptionsItemSelected(MenuItem menuItem) { + // Get the selected menu item ID. int menuItemId = menuItem.getItemId(); // Set the commands that relate to the menu entries. @@ -1774,9 +1813,16 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD WebStorage webStorage = WebStorage.getInstance(); webStorage.deleteAllData(); - // Manually remove `IndexedDB` if it exists. + // Manually delete the DOM storage files and directories. try { + // A `String[]` must be used because the directory contains a space and `Runtime.exec` will otherwise not escape the string correctly. + privacyBrowserRuntime.exec(new String[] {"rm", "-rf", privateDataDirectoryString + "/app_webview/Local Storage/"}); + + // Multiple commands must be used because `Runtime.exec()` does not like `*`. privacyBrowserRuntime.exec("rm -rf " + privateDataDirectoryString + "/app_webview/IndexedDB"); + privacyBrowserRuntime.exec("rm -f " + privateDataDirectoryString + "/app_webview/QuotaManager"); + privacyBrowserRuntime.exec("rm -f " + privateDataDirectoryString + "/app_webview/QuotaManager-journal"); + privacyBrowserRuntime.exec("rm -rf " + privateDataDirectoryString + "/app_webview/databases"); } catch (IOException e) { // Do nothing if an error is thrown. } @@ -1900,6 +1946,12 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD printManager.print(getString(R.string.privacy_browser_web_page), printDocumentAdapter, null); return true; + case R.id.view_source: + // Launch the Vew Source activity. + Intent viewSourceIntent = new Intent(this, ViewSourceActivity.class); + startActivity(viewSourceIntent); + return true; + case R.id.add_to_homescreen: // Show the `CreateHomeScreenShortcutDialog` `AlertDialog` and name this instance `R.string.create_shortcut`. AppCompatDialogFragment createHomeScreenShortcutDialogFragment = new CreateHomeScreenShortcutDialog(); @@ -2033,10 +2085,10 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD // Manually delete the DOM storage files and directories, as `WebStorage` sometimes will not flush its changes to disk before `System.exit(0)` is run. try { - // We have to use a `String[]` because the directory contains a space and `Runtime.exec` will not escape the string correctly otherwise. + // A `String[]` must be used because the directory contains a space and `Runtime.exec` will otherwise not escape the string correctly. privacyBrowserRuntime.exec(new String[] {"rm", "-rf", privateDataDirectoryString + "/app_webview/Local Storage/"}); - // We have to use multiple commands because `Runtime.exec()` does not like `*`. + // Multiple commands must be used because `Runtime.exec()` does not like `*`. privacyBrowserRuntime.exec("rm -rf " + privateDataDirectoryString + "/app_webview/IndexedDB"); privacyBrowserRuntime.exec("rm -f " + privateDataDirectoryString + "/app_webview/QuotaManager"); privacyBrowserRuntime.exec("rm -f " + privateDataDirectoryString + "/app_webview/QuotaManager-journal"); @@ -2244,7 +2296,7 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD }); // Add a `Download Image` entry. - menu.add(R.string.download_image).setOnMenuItemClickListener(item -> { + menu.add(R.string.download_image).setOnMenuItemClickListener((MenuItem item) -> { // Show the `DownloadImageDialog` `AlertDialog` and name this instance `@string/download`. AppCompatDialogFragment downloadImageDialogFragment = DownloadImageDialog.imageUrl(imageUrl); downloadImageDialogFragment.show(getSupportFragmentManager(), getString(R.string.download)); @@ -2281,7 +2333,7 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD }); // Add a `Download Image` entry. - menu.add(R.string.download_image).setOnMenuItemClickListener(item -> { + menu.add(R.string.download_image).setOnMenuItemClickListener((MenuItem item) -> { // Show the `DownloadImageDialog` `AlertDialog` and name this instance `@string/download`. AppCompatDialogFragment downloadImageDialogFragment = DownloadImageDialog.imageUrl(imageUrl); downloadImageDialogFragment.show(getSupportFragmentManager(), getString(R.string.download)); @@ -2409,21 +2461,28 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD @Override public void onCreateHomeScreenShortcut(AppCompatDialogFragment dialogFragment) { - // Get shortcutNameEditText from the alert dialog. + // Get the shortcut name. EditText shortcutNameEditText = dialogFragment.getDialog().findViewById(R.id.shortcut_name_edittext); + String shortcutNameString = shortcutNameEditText.getText().toString(); + + // Convert the favorite icon bitmap to an `Icon`. `IconCompat` is required until API >= 26. + IconCompat favoriteIcon = IconCompat.createWithBitmap(favoriteIconBitmap); - // Create the bookmark shortcut based on formattedUrlString. - Intent bookmarkShortcut = new Intent(); - bookmarkShortcut.setAction(Intent.ACTION_VIEW); - bookmarkShortcut.setData(Uri.parse(formattedUrlString)); - - // Place the bookmark shortcut on the home screen. - Intent placeBookmarkShortcut = new Intent(); - placeBookmarkShortcut.putExtra("android.intent.extra.shortcut.INTENT", bookmarkShortcut); - placeBookmarkShortcut.putExtra("android.intent.extra.shortcut.NAME", shortcutNameEditText.getText().toString()); - placeBookmarkShortcut.putExtra("android.intent.extra.shortcut.ICON", favoriteIconBitmap); - placeBookmarkShortcut.setAction("com.android.launcher.action.INSTALL_SHORTCUT"); - sendBroadcast(placeBookmarkShortcut); + // Setup the shortcut intent. + Intent shortcutIntent = new Intent(); + shortcutIntent.setAction(Intent.ACTION_VIEW); + shortcutIntent.setData(Uri.parse(formattedUrlString)); + + // Create a shortcut info builder. The shortcut name becomes the shortcut ID. + ShortcutInfoCompat.Builder shortcutInfoBuilder = new ShortcutInfoCompat.Builder(this, shortcutNameString); + + // Add the required fields to the shortcut info builder. + shortcutInfoBuilder.setIcon(favoriteIcon); + shortcutInfoBuilder.setIntent(shortcutIntent); + shortcutInfoBuilder.setShortLabel(shortcutNameString); + + // Request the pin. `ShortcutManagerCompat` can be switched to `ShortcutManager` once API >= 26. + ShortcutManagerCompat.requestPinShortcut(this, shortcutInfoBuilder.build(), null); } @Override @@ -2802,10 +2861,10 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD } private void applyAppSettings() { - // Get a handle for `sharedPreferences`. `this` references the current context. + // Get a handle for the shared preferences. SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); - // Store the values from `sharedPreferences` in variables. + // Store the values from the shared preferences in variables. String homepageString = sharedPreferences.getString("homepage", "https://start.duckduckgo.com"); String torHomepageString = sharedPreferences.getString("tor_homepage", "https://3g2upl4pq6kufc4m.onion"); String torSearchString = sharedPreferences.getString("tor_search", "https://3g2upl4pq6kufc4m.onion/html/?q="); @@ -3157,6 +3216,9 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD // Use the selected user agent. mainWebView.getSettings().setUserAgentString(userAgentString); } + + // Store the applied user agent string. + appliedUserAgentString = mainWebView.getSettings().getUserAgentString(); } // Set a green background on `urlTextBox` to indicate that custom domain settings are being used. We have to use the deprecated `.getDrawable()` until the minimum API >= 21. @@ -3219,6 +3281,9 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD // Use the selected user agent. mainWebView.getSettings().setUserAgentString(defaultUserAgentString); } + + // Store the applied user agent string. + appliedUserAgentString = mainWebView.getSettings().getUserAgentString(); } // Set a transparent background on `urlTextBox`. We have to use the deprecated `.getDrawable()` until the minimum API >= 21. @@ -3325,9 +3390,9 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD private void highlightUrlText() { String urlString = urlTextBox.getText().toString(); - if (urlString.startsWith("http://")) { // Highlight connections that are not encrypted. + if (urlString.startsWith("http://")) { // Highlight the protocol of connections that are not encrypted. urlTextBox.getText().setSpan(redColorSpan, 0, 7, Spanned.SPAN_INCLUSIVE_INCLUSIVE); - } else if (urlString.startsWith("https://")) { // Highlight connections that are encrypted. + } else if (urlString.startsWith("https://")) { // De-emphasize the protocol of connections that are encrypted. urlTextBox.getText().setSpan(initialGrayColorSpan, 0, 8, Spanned.SPAN_INCLUSIVE_INCLUSIVE); }