From a54a66c7d169d2edf55ba560ec2d951e709188e6 Mon Sep 17 00:00:00 2001 From: Soren Stoutner Date: Wed, 21 Jun 2023 14:43:17 -0700 Subject: [PATCH] Use the secret built-in View Source. https://redmine.stoutner.com/issues/1023 --- app/src/main/AndroidManifest.xml | 6 +- .../activities/MainWebViewActivity.kt | 77 ++++++++++++++++--- ...urceActivity.kt => ViewHeadersActivity.kt} | 60 +++++++-------- ...undTask.kt => GetHeadersBackgroundTask.kt} | 16 ++-- ...rceDialog.kt => AboutViewHeadersDialog.kt} | 10 +-- ...SourceFactory.kt => ViewHeadersFactory.kt} | 8 +- .../{WebViewSource.kt => HeadersViewModel.kt} | 30 ++++---- ...ml => view_headers_appbar_custom_view.xml} | 4 +- ...bar.xml => view_headers_bottom_appbar.xml} | 10 +-- ...appbar.xml => view_headers_top_appbar.xml} | 8 +- ...menu.xml => view_headers_options_menu.xml} | 6 +- .../main/res/menu/webview_options_menu.xml | 10 ++- app/src/main/res/values-de/strings.xml | 3 +- app/src/main/res/values-es/strings.xml | 3 +- app/src/main/res/values-fr/strings.xml | 3 +- app/src/main/res/values-it/strings.xml | 3 +- app/src/main/res/values-pt-rBR/strings.xml | 3 +- app/src/main/res/values-ru/strings.xml | 3 +- app/src/main/res/values-tr/strings.xml | 3 +- app/src/main/res/values-zh-rCN/strings.xml | 3 +- app/src/main/res/values/strings.xml | 6 +- 21 files changed, 167 insertions(+), 108 deletions(-) rename app/src/main/java/com/stoutner/privacybrowser/activities/{ViewSourceActivity.kt => ViewHeadersActivity.kt} (87%) rename app/src/main/java/com/stoutner/privacybrowser/backgroundtasks/{GetSourceBackgroundTask.kt => GetHeadersBackgroundTask.kt} (97%) rename app/src/main/java/com/stoutner/privacybrowser/dialogs/{AboutViewSourceDialog.kt => AboutViewHeadersDialog.kt} (90%) rename app/src/main/java/com/stoutner/privacybrowser/viewmodelfactories/{WebViewSourceFactory.kt => ViewHeadersFactory.kt} (81%) rename app/src/main/java/com/stoutner/privacybrowser/viewmodels/{WebViewSource.kt => HeadersViewModel.kt} (72%) rename app/src/main/res/layout/{view_source_appbar_custom_view.xml => view_headers_appbar_custom_view.xml} (96%) rename app/src/main/res/layout/{view_source_bottom_appbar.xml => view_headers_bottom_appbar.xml} (96%) rename app/src/main/res/layout/{view_source_top_appbar.xml => view_headers_top_appbar.xml} (97%) rename app/src/main/res/menu/{view_source_options_menu.xml => view_headers_options_menu.xml} (91%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4cfa09bd..968bfeb1 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ { // View source. - // Create an intent to launch the view source activity. - val viewSourceIntent = Intent(this, ViewSourceActivity::class.java) + // Open a new tab according to the current URL. + if (currentWebView!!.currentUrl.startsWith("view-source:")) { // The source is currently viewed. + // Open the rendered website in a new tab. + addNewTab(currentWebView!!.currentUrl.substring(12, currentWebView!!.currentUrl.length), true) + } else { // The rendered website is currently viewed. + // Open the source in a new tab. + addNewTab("view-source:${currentWebView!!.currentUrl}", true) + } + + // Consume the event. + true + } + + R.id.view_headers -> { // View headers. + // Create an intent to launch the view headers activity. + val viewHeadersIntent = Intent(this, ViewHeadersActivity::class.java) // Add the variables to the intent. - viewSourceIntent.putExtra(CURRENT_URL, currentWebView!!.url) - viewSourceIntent.putExtra(USER_AGENT, currentWebView!!.settings.userAgentString) + viewHeadersIntent.putExtra(CURRENT_URL, currentWebView!!.url) + viewHeadersIntent.putExtra(USER_AGENT, currentWebView!!.settings.userAgentString) // Make it so. - startActivity(viewSourceIntent) + startActivity(viewHeadersIntent) // Consume the event. true @@ -2209,6 +2234,9 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook // Load the previous website in the history. currentWebView!!.goBack() + + // Update the URL edit text after a delay. + updateUrlEditTextAfterDelay() } } @@ -2226,6 +2254,9 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook // Load the next website in the history. currentWebView!!.goForward() + + // Update the URL edit text after a delay. + updateUrlEditTextAfterDelay() } } @@ -3394,6 +3425,10 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook if (reloadWebsite) nestedScrollWebView.reload() + // Disable the wide viewport if the source is being viewed. + if (url.startsWith("view-source:")) + nestedScrollWebView.settings.useWideViewPort = false + // Load the URL if directed. This makes sure that the domain settings are properly loaded before the URL. By using `loadUrl()`, instead of `loadUrlFromBase()`, the Referer header will never be sent. if (loadUrl) nestedScrollWebView.loadUrl(url) @@ -5346,8 +5381,8 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook // Update the URL text bar if the page is currently selected and the URL edit text is not currently being edited. if ((tabLayout.selectedTabPosition == currentPagePosition) && !urlEditText.hasFocus()) { - // Display the formatted URL text. - urlEditText.setText(url) + // Display the formatted URL text. The nested scroll WebView current URL preserves any initial `view-source:`, and opposed to the method URL variable. + urlEditText.setText(nestedScrollWebView.currentUrl) // Highlight the URL syntax. UrlHelper.highlightSyntax(urlEditText, initialGrayColorSpan, finalGrayColorSpan, redColorSpan) @@ -5689,7 +5724,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook var urlString = "" // Check to see if the unformatted URL string is a valid URL. Otherwise, convert it into a search. - if (unformattedUrlString.startsWith("content://")) { // This is a content URL. + if (unformattedUrlString.startsWith("content://") || unformattedUrlString.startsWith("view-source:")) { // This is a content or source URL. // Load the entire content URL. urlString = unformattedUrlString } else if (Patterns.WEB_URL.matcher(unformattedUrlString).matches() || unformattedUrlString.startsWith("http://") || unformattedUrlString.startsWith("https://") || @@ -5753,6 +5788,9 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook // Load the history entry. currentWebView!!.goBackOrForward(steps) + + // Update the URL edit text after a delay. + updateUrlEditTextAfterDelay() } override fun openFile(dialogFragment: DialogFragment) { @@ -5863,6 +5901,9 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook // Go back. currentWebView!!.goBack() + + // Update the URL edit text after a delay. + updateUrlEditTextAfterDelay() } private fun sanitizeUrl(urlString: String): String { @@ -6082,4 +6123,22 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook invalidateOptionsMenu() } } + + fun updateUrlEditTextAfterDelay() { + // Create a handler to update the URL edit box. + val urlEditTextUpdateHandler = Handler(Looper.getMainLooper()) + + // Create a runnable to update the URL edit box. + val urlEditTextUpdateRunnable = Runnable { + // Update the URL edit text. + urlEditText.setText(currentWebView!!.url) + + // Disable the wide viewport if the source is being viewed. + if (currentWebView!!.url!!.startsWith("view-source:")) + currentWebView!!.settings.useWideViewPort = false + } + + // Update the URL edit text after 50 milliseconds, so that the WebView has enough time to navigate to the new URL. + urlEditTextUpdateHandler.postDelayed(urlEditTextUpdateRunnable, 50) + } } diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/ViewSourceActivity.kt b/app/src/main/java/com/stoutner/privacybrowser/activities/ViewHeadersActivity.kt similarity index 87% rename from app/src/main/java/com/stoutner/privacybrowser/activities/ViewSourceActivity.kt rename to app/src/main/java/com/stoutner/privacybrowser/activities/ViewHeadersActivity.kt index 736f67d3..2f0aeb0b 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/ViewSourceActivity.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/ViewHeadersActivity.kt @@ -46,23 +46,23 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.google.android.material.snackbar.Snackbar import com.stoutner.privacybrowser.R -import com.stoutner.privacybrowser.dialogs.AboutViewSourceDialog +import com.stoutner.privacybrowser.dialogs.AboutViewHeadersDialog import com.stoutner.privacybrowser.dialogs.UntrustedSslCertificateDialog import com.stoutner.privacybrowser.dialogs.UntrustedSslCertificateDialog.UntrustedSslCertificateListener import com.stoutner.privacybrowser.helpers.ProxyHelper import com.stoutner.privacybrowser.helpers.UrlHelper -import com.stoutner.privacybrowser.viewmodelfactories.WebViewSourceFactory -import com.stoutner.privacybrowser.viewmodels.WebViewSource +import com.stoutner.privacybrowser.viewmodelfactories.ViewHeadersFactory +import com.stoutner.privacybrowser.viewmodels.HeadersViewModel // Define the public constants. const val USER_AGENT = "user_agent" -class ViewSourceActivity: AppCompatActivity(), UntrustedSslCertificateListener { +class ViewHeadersActivity: AppCompatActivity(), UntrustedSslCertificateListener { // Declare the class variables. + private lateinit var headersViewModel: HeadersViewModel private lateinit var initialGrayColorSpan: ForegroundColorSpan private lateinit var finalGrayColorSpan: ForegroundColorSpan private lateinit var redColorSpan: ForegroundColorSpan - private lateinit var webViewSource: WebViewSource // Declare the class views. private lateinit var urlEditText: EditText @@ -98,13 +98,13 @@ class ViewSourceActivity: AppCompatActivity(), UntrustedSslCertificateListener { // Set the content view. if (bottomAppBar) { - setContentView(R.layout.view_source_bottom_appbar) + setContentView(R.layout.view_headers_bottom_appbar) } else { - setContentView(R.layout.view_source_top_appbar) + setContentView(R.layout.view_headers_top_appbar) } // Get a handle for the toolbar. - val toolbar = findViewById(R.id.view_source_toolbar) + val toolbar = findViewById(R.id.toolbar) // Set the support action bar. setSupportActionBar(toolbar) @@ -113,7 +113,7 @@ class ViewSourceActivity: AppCompatActivity(), UntrustedSslCertificateListener { val actionBar = supportActionBar!! // Add the custom layout to the action bar. - actionBar.setCustomView(R.layout.view_source_appbar_custom_view) + actionBar.setCustomView(R.layout.view_headers_appbar_custom_view) // Instruct the action bar to display a custom layout. actionBar.displayOptions = ActionBar.DISPLAY_SHOW_CUSTOM @@ -121,7 +121,7 @@ class ViewSourceActivity: AppCompatActivity(), UntrustedSslCertificateListener { // Get handles for the views. urlEditText = findViewById(R.id.url_edittext) val progressBar = findViewById(R.id.progress_bar) - val swipeRefreshLayout = findViewById(R.id.view_source_swiperefreshlayout) + val swipeRefreshLayout = findViewById(R.id.swiperefreshlayout) requestHeadersTitleTextView = findViewById(R.id.request_headers_title_textview) requestHeadersTextView = findViewById(R.id.request_headers_textview) responseMessageTitleTextView = findViewById(R.id.response_message_title_textview) @@ -243,19 +243,19 @@ class ViewSourceActivity: AppCompatActivity(), UntrustedSslCertificateListener { // Update the layout. updateLayout(currentUrl) - // Instantiate the WebView source factory. - val webViewSourceFactory: ViewModelProvider.Factory = WebViewSourceFactory(currentUrl, userAgent, localesStringBuilder.toString(), proxy, contentResolver, MainWebViewActivity.executorService) + // Instantiate the view headers factory. + val viewHeadersFactory: ViewModelProvider.Factory = ViewHeadersFactory(currentUrl, userAgent, localesStringBuilder.toString(), proxy, contentResolver, MainWebViewActivity.executorService) - // Instantiate the WebView source view model class. - webViewSource = ViewModelProvider(this, webViewSourceFactory)[WebViewSource::class.java] + // Instantiate the headers view model. + headersViewModel = ViewModelProvider(this, viewHeadersFactory)[HeadersViewModel::class.java] - // Create a source observer. - webViewSource.observeSource().observe(this) { sourceStringArray: Array -> + // Create a headers observer. + headersViewModel.observeHeaders().observe(this) { headersStringArray: Array -> // Populate the text views. This can take a long time, and freezes the user interface, if the response body is particularly large. - requestHeadersTextView.text = sourceStringArray[0] - responseMessageTextView.text = sourceStringArray[1] - responseHeadersTextView.text = sourceStringArray[2] - responseBodyTextView.text = sourceStringArray[3] + requestHeadersTextView.text = headersStringArray[0] + responseMessageTextView.text = headersStringArray[1] + responseHeadersTextView.text = headersStringArray[2] + responseBodyTextView.text = headersStringArray[3] // Hide the progress bar. progressBar.isIndeterminate = false @@ -266,7 +266,7 @@ class ViewSourceActivity: AppCompatActivity(), UntrustedSslCertificateListener { } // Create an error observer. - webViewSource.observeErrors().observe(this) { errorString: String -> + headersViewModel.observeErrors().observe(this) { errorString: String -> // Display an error snackbar if the string is not `""`. if (errorString != "") { if (errorString.startsWith("javax.net.ssl.SSLHandshakeException")) { @@ -296,13 +296,13 @@ class ViewSourceActivity: AppCompatActivity(), UntrustedSslCertificateListener { // Update the layout. updateLayout(urlString) - // Get the updated source. - webViewSource.updateSource(urlString, false) + // Get the updated headers. + headersViewModel.updateHeaders(urlString, false) } - // Set the go button on the keyboard to request new source data. + // Set the go button on the keyboard to request new headers data. urlEditText.setOnKeyListener { _: View?, keyCode: Int, event: KeyEvent -> - // Request new source data if the enter key was pressed. + // Request new headers data if the enter key was pressed. if (event.action == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_ENTER) { // Hide the soft keyboard. inputMethodManager.hideSoftInputFromWindow(urlEditText.windowToken, 0) @@ -322,8 +322,8 @@ class ViewSourceActivity: AppCompatActivity(), UntrustedSslCertificateListener { // Update the layout. updateLayout(urlString) - // Get the updated source. - webViewSource.updateSource(urlString, false) + // Get the updated headers. + headersViewModel.updateHeaders(urlString, false) // Consume the key press. return@setOnKeyListener true @@ -336,7 +336,7 @@ class ViewSourceActivity: AppCompatActivity(), UntrustedSslCertificateListener { override fun onCreateOptionsMenu(menu: Menu): Boolean { // Inflate the menu. - menuInflater.inflate(R.menu.view_source_options_menu, menu) + menuInflater.inflate(R.menu.view_headers_options_menu, menu) // Display the menu. return true @@ -344,7 +344,7 @@ class ViewSourceActivity: AppCompatActivity(), UntrustedSslCertificateListener { override fun onOptionsItemSelected(menuItem: MenuItem): Boolean { // Instantiate the about dialog fragment. - val aboutDialogFragment: DialogFragment = AboutViewSourceDialog() + val aboutDialogFragment: DialogFragment = AboutViewHeadersDialog() // Show the about alert dialog. aboutDialogFragment.show(supportFragmentManager, getString(R.string.about)) @@ -361,7 +361,7 @@ class ViewSourceActivity: AppCompatActivity(), UntrustedSslCertificateListener { override fun loadAnyway() { // Load the URL anyway. - webViewSource.updateSource(urlEditText.text.toString(), true) + headersViewModel.updateHeaders(urlEditText.text.toString(), true) } private fun updateLayout(urlString: String) { diff --git a/app/src/main/java/com/stoutner/privacybrowser/backgroundtasks/GetSourceBackgroundTask.kt b/app/src/main/java/com/stoutner/privacybrowser/backgroundtasks/GetHeadersBackgroundTask.kt similarity index 97% rename from app/src/main/java/com/stoutner/privacybrowser/backgroundtasks/GetSourceBackgroundTask.kt rename to app/src/main/java/com/stoutner/privacybrowser/backgroundtasks/GetHeadersBackgroundTask.kt index f7ad0a5b..030ce4c6 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/backgroundtasks/GetSourceBackgroundTask.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/backgroundtasks/GetHeadersBackgroundTask.kt @@ -1,5 +1,5 @@ /* - * Copyright © 2017-2023 Soren Stoutner . + * Copyright 2017-2023 Soren Stoutner . * * This file is part of Privacy Browser Android . * @@ -28,7 +28,7 @@ import android.text.Spanned import android.text.style.StyleSpan import android.webkit.CookieManager -import com.stoutner.privacybrowser.viewmodels.WebViewSource +import com.stoutner.privacybrowser.viewmodels.HeadersViewModel import java.io.BufferedInputStream import java.io.BufferedReader @@ -52,8 +52,8 @@ import javax.net.ssl.TrustManager import javax.net.ssl.X509TrustManager -class GetSourceBackgroundTask { - fun acquire(urlString: String, userAgent: String, localeString: String, proxy: Proxy, contentResolver: ContentResolver, webViewSource: WebViewSource, ignoreSslErrors: Boolean): +class GetHeadersBackgroundTask { + fun acquire(urlString: String, userAgent: String, localeString: String, proxy: Proxy, contentResolver: ContentResolver, headersViewModel: HeadersViewModel, ignoreSslErrors: Boolean): Array { // Initialize the spannable string builders. @@ -105,7 +105,7 @@ class GetSourceBackgroundTask { } } catch (exception: Exception) { // Return the error message. - webViewSource.returnError(exception.toString()) + headersViewModel.returnError(exception.toString()) } } else { // This is not a content URL. // Because everything relating to requesting data from a webserver can throw errors, the entire section must catch `IOExceptions`. @@ -312,7 +312,7 @@ class GetSourceBackgroundTask { } } catch (exception: IOException) { // Return the error message. - webViewSource.returnError(exception.toString()) + headersViewModel.returnError(exception.toString()) } // Close the input stream. @@ -326,11 +326,11 @@ class GetSourceBackgroundTask { } } catch (exception: Exception) { // Return the error message. - webViewSource.returnError(exception.toString()) + headersViewModel.returnError(exception.toString()) } } // Return the spannable string builders. return arrayOf(requestHeadersBuilder, responseMessageBuilder, responseHeadersBuilder, responseBodyBuilder) } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/stoutner/privacybrowser/dialogs/AboutViewSourceDialog.kt b/app/src/main/java/com/stoutner/privacybrowser/dialogs/AboutViewHeadersDialog.kt similarity index 90% rename from app/src/main/java/com/stoutner/privacybrowser/dialogs/AboutViewSourceDialog.kt rename to app/src/main/java/com/stoutner/privacybrowser/dialogs/AboutViewHeadersDialog.kt index 8ac83313..f88da7b0 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/dialogs/AboutViewSourceDialog.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/dialogs/AboutViewHeadersDialog.kt @@ -1,5 +1,5 @@ /* - * Copyright © 2018-2022 Soren Stoutner . + * Copyright 2018-2023 Soren Stoutner . * * This file is part of Privacy Browser Android . * @@ -29,7 +29,7 @@ import androidx.preference.PreferenceManager import com.stoutner.privacybrowser.R -class AboutViewSourceDialog : DialogFragment() { +class AboutViewHeadersDialog : DialogFragment() { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { // Use a builder to create the alert dialog. val dialogBuilder = AlertDialog.Builder(requireContext(), R.style.PrivacyBrowserAlertDialog) @@ -38,10 +38,10 @@ class AboutViewSourceDialog : DialogFragment() { dialogBuilder.setIcon(R.drawable.about_blue) // Set the title. - dialogBuilder.setTitle(R.string.about_view_source) + dialogBuilder.setTitle(R.string.about_view_headers) // Set the text. - dialogBuilder.setMessage(R.string.about_view_source_message) + dialogBuilder.setMessage(R.string.about_view_headers_message) // Set the close button listener. Using `null` as the listener closes the dialog without doing anything else. dialogBuilder.setNegativeButton(R.string.close, null) @@ -63,4 +63,4 @@ class AboutViewSourceDialog : DialogFragment() { // Return the alert dialog. return alertDialog } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/stoutner/privacybrowser/viewmodelfactories/WebViewSourceFactory.kt b/app/src/main/java/com/stoutner/privacybrowser/viewmodelfactories/ViewHeadersFactory.kt similarity index 81% rename from app/src/main/java/com/stoutner/privacybrowser/viewmodelfactories/WebViewSourceFactory.kt rename to app/src/main/java/com/stoutner/privacybrowser/viewmodelfactories/ViewHeadersFactory.kt index f8de88fd..83f0a365 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/viewmodelfactories/WebViewSourceFactory.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/viewmodelfactories/ViewHeadersFactory.kt @@ -1,5 +1,5 @@ /* - * Copyright © 2020-2022 Soren Stoutner . + * Copyright 2020-2023 Soren Stoutner . * * This file is part of Privacy Browser Android . * @@ -27,12 +27,12 @@ import androidx.lifecycle.ViewModelProvider import java.net.Proxy import java.util.concurrent.ExecutorService -class WebViewSourceFactory (private val urlString: String, private val userAgent: String, private val localeString: String, private val proxy: Proxy, private val contentResolver: ContentResolver, - private val executorService: ExecutorService): ViewModelProvider.Factory { +class ViewHeadersFactory (private val urlString: String, private val userAgent: String, private val localeString: String, private val proxy: Proxy, private val contentResolver: ContentResolver, + private val executorService: ExecutorService): ViewModelProvider.Factory { // Override the create function in order to add the provided arguments. override fun create(modelClass: Class): T { // Return a new instance of the model class with the provided arguments. return modelClass.getConstructor(String::class.java, String::class.java, String::class.java, Proxy::class.java, ContentResolver::class.java, ExecutorService::class.java) .newInstance(urlString, userAgent, localeString, proxy, contentResolver, executorService) } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/stoutner/privacybrowser/viewmodels/WebViewSource.kt b/app/src/main/java/com/stoutner/privacybrowser/viewmodels/HeadersViewModel.kt similarity index 72% rename from app/src/main/java/com/stoutner/privacybrowser/viewmodels/WebViewSource.kt rename to app/src/main/java/com/stoutner/privacybrowser/viewmodels/HeadersViewModel.kt index d55540ec..ccfe79ab 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/viewmodels/WebViewSource.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/viewmodels/HeadersViewModel.kt @@ -1,5 +1,5 @@ /* - * Copyright © 2020-2022 Soren Stoutner . + * Copyright 2020-2023 Soren Stoutner . * * This file is part of Privacy Browser Android . * @@ -26,29 +26,29 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import com.stoutner.privacybrowser.backgroundtasks.GetSourceBackgroundTask +import com.stoutner.privacybrowser.backgroundtasks.GetHeadersBackgroundTask import java.net.Proxy import java.util.concurrent.ExecutorService -class WebViewSource(private val urlString: String, private val userAgent: String, private val localeString: String, private val proxy: Proxy, private val contentResolver: ContentResolver, - private val executorService: ExecutorService): ViewModel() { +class HeadersViewModel(private val urlString: String, private val userAgent: String, private val localeString: String, private val proxy: Proxy, private val contentResolver: ContentResolver, + private val executorService: ExecutorService): ViewModel() { // Initialize the mutable live data variables. private val mutableLiveDataSourceStringArray = MutableLiveData>() private val mutableLiveDataErrorString = MutableLiveData() // Initialize the view model. init { - // Instantiate the get source background task class. - val getSourceBackgroundTask = GetSourceBackgroundTask() + // Instantiate the get headers background task class. + val getSourceBackgroundTask = GetHeadersBackgroundTask() - // Get the source. + // Get the headers. executorService.execute { mutableLiveDataSourceStringArray.postValue(getSourceBackgroundTask.acquire(urlString, userAgent, localeString, proxy, contentResolver, this, false)) } } - // The source observer. - fun observeSource(): LiveData> { + // The headers observer. + fun observeHeaders(): LiveData> { // Return the source to the activity. return mutableLiveDataSourceStringArray } @@ -65,16 +65,16 @@ class WebViewSource(private val urlString: String, private val userAgent: String mutableLiveDataErrorString.postValue(errorString) } - // The workhorse that gets the source. - fun updateSource(urlString: String, ignoreSslErrors: Boolean) { + // The workhorse that gets the headers. + fun updateHeaders(urlString: String, ignoreSslErrors: Boolean) { // Reset the mutable live data error string. This prevents the snackbar from displaying later if the activity restarts. mutableLiveDataErrorString.postValue("") - // Instantiate the get source background task class. - val getSourceBackgroundTask = GetSourceBackgroundTask() + // Instantiate the get headers background task class. + val getSourceBackgroundTask = GetHeadersBackgroundTask() - // Get the source. + // Get the headers. executorService.execute { mutableLiveDataSourceStringArray.postValue(getSourceBackgroundTask.acquire(urlString, userAgent, localeString, proxy, contentResolver, this, ignoreSslErrors)) } } -} \ No newline at end of file +} diff --git a/app/src/main/res/layout/view_source_appbar_custom_view.xml b/app/src/main/res/layout/view_headers_appbar_custom_view.xml similarity index 96% rename from app/src/main/res/layout/view_source_appbar_custom_view.xml rename to app/src/main/res/layout/view_headers_appbar_custom_view.xml index 83a465c8..17982c08 100644 --- a/app/src/main/res/layout/view_source_appbar_custom_view.xml +++ b/app/src/main/res/layout/view_headers_appbar_custom_view.xml @@ -1,7 +1,7 @@ @@ -141,7 +141,7 @@ android:layout_width="match_parent" > diff --git a/app/src/main/res/layout/view_source_top_appbar.xml b/app/src/main/res/layout/view_headers_top_appbar.xml similarity index 97% rename from app/src/main/res/layout/view_source_top_appbar.xml rename to app/src/main/res/layout/view_headers_top_appbar.xml index a63e9419..3171bbcb 100644 --- a/app/src/main/res/layout/view_source_top_appbar.xml +++ b/app/src/main/res/layout/view_headers_top_appbar.xml @@ -1,7 +1,7 @@ @@ -67,7 +67,7 @@ diff --git a/app/src/main/res/menu/view_source_options_menu.xml b/app/src/main/res/menu/view_headers_options_menu.xml similarity index 91% rename from app/src/main/res/menu/view_source_options_menu.xml rename to app/src/main/res/menu/view_headers_options_menu.xml index 0843e1f0..d7439959 100644 --- a/app/src/main/res/menu/view_source_options_menu.xml +++ b/app/src/main/res/menu/view_headers_options_menu.xml @@ -1,7 +1,7 @@ - \ No newline at end of file + diff --git a/app/src/main/res/menu/webview_options_menu.xml b/app/src/main/res/menu/webview_options_menu.xml index 3e89db02..7ec11f85 100644 --- a/app/src/main/res/menu/webview_options_menu.xml +++ b/app/src/main/res/menu/webview_options_menu.xml @@ -1,7 +1,7 @@ diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index e2a9e08d..376e7c36 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -222,8 +222,7 @@ 内容数据 SSL证书不受信任. 仍然加载 - 查看源代码 - 因为安卓的网页不支持显示资源内容,一个另外的请求被系统调用来显示这个活动的信息,数据和网页主要活动可能存在差异,这个限制将会在隐私浏览器4.x系列解决。 + 因为安卓的网页不支持显示资源内容,一个另外的请求被系统调用来显示这个活动的信息,数据和网页主要活动可能存在差异,这个限制将会在隐私浏览器4.x系列解决。 创建标签 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bc89d4e3..8e57ec0d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -172,6 +172,8 @@ Save Add to Home Screen View Source + View Rendered Website + View Headers Share Share Message Share URL @@ -229,8 +231,8 @@ Content Data The SSL certificate is untrusted. Load anyway - About View Source - Because Android’s WebView does not expose the source information, + About View Headers + Because Android’s WebView does not expose the source information, a separate request was made using system tools to gather the information displayed in this activity. There may be some differences between this data and that used by the WebView in the main activity. This limitation will be removed in the 4.x series with the release of Privacy WebView. -- 2.45.2