2 * Copyright 2018-2023 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
6 * Privacy Browser Android is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * Privacy Browser Android is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Privacy Browser Android. If not, see <http://www.gnu.org/licenses/>.
20 package com.stoutner.privacybrowser.dialogs
22 import android.app.Dialog
23 import android.content.Context
24 import android.content.DialogInterface
25 import android.os.Bundle
26 import android.view.View
27 import android.view.WindowManager
28 import android.widget.TextView
30 import androidx.appcompat.app.AlertDialog
31 import androidx.core.content.ContextCompat.getColor
32 import androidx.fragment.app.DialogFragment
33 import androidx.preference.PreferenceManager
35 import com.stoutner.privacybrowser.R
36 import com.stoutner.privacybrowser.helpers.DOMAIN_ALLOWLIST
37 import com.stoutner.privacybrowser.helpers.DOMAIN_BLOCKLIST
38 import com.stoutner.privacybrowser.helpers.DOMAIN_FINAL_ALLOWLIST
39 import com.stoutner.privacybrowser.helpers.DOMAIN_FINAL_BLOCKLIST
40 import com.stoutner.privacybrowser.helpers.DOMAIN_INITIAL_ALLOWLIST
41 import com.stoutner.privacybrowser.helpers.DOMAIN_INITIAL_BLOCKLIST
42 import com.stoutner.privacybrowser.helpers.DOMAIN_REGULAR_EXPRESSION_BLOCKLIST
43 import com.stoutner.privacybrowser.helpers.INITIAL_BLOCKLIST
44 import com.stoutner.privacybrowser.helpers.REQUEST_ALLOWED
45 import com.stoutner.privacybrowser.helpers.REQUEST_BLOCKED
46 import com.stoutner.privacybrowser.helpers.REQUEST_BLOCKLIST
47 import com.stoutner.privacybrowser.helpers.REQUEST_BLOCKLIST_ENTRIES
48 import com.stoutner.privacybrowser.helpers.REQUEST_BLOCKLIST_ORIGINAL_ENTRY
49 import com.stoutner.privacybrowser.helpers.REQUEST_DEFAULT
50 import com.stoutner.privacybrowser.helpers.REQUEST_DISPOSITION
51 import com.stoutner.privacybrowser.helpers.FINAL_ALLOWLIST
52 import com.stoutner.privacybrowser.helpers.FINAL_BLOCKLIST
53 import com.stoutner.privacybrowser.helpers.MAIN_ALLOWLIST
54 import com.stoutner.privacybrowser.helpers.MAIN_BLOCKLIST
55 import com.stoutner.privacybrowser.helpers.REGULAR_EXPRESSION_BLOCKLIST
56 import com.stoutner.privacybrowser.helpers.REQUEST_SUBLIST
57 import com.stoutner.privacybrowser.helpers.REQUEST_THIRD_PARTY
58 import com.stoutner.privacybrowser.helpers.REQUEST_URL
59 import com.stoutner.privacybrowser.helpers.THIRD_PARTY_BLOCKLIST
60 import com.stoutner.privacybrowser.helpers.THIRD_PARTY_DOMAIN_BLOCKLIST
61 import com.stoutner.privacybrowser.helpers.THIRD_PARTY_DOMAIN_INITIAL_ALLOWLIST
62 import com.stoutner.privacybrowser.helpers.THIRD_PARTY_DOMAIN_INITIAL_BLOCKLIST
63 import com.stoutner.privacybrowser.helpers.THIRD_PARTY_DOMAIN_REGULAR_EXPRESSION_BLOCKLIST
64 import com.stoutner.privacybrowser.helpers.THIRD_PARTY_DOMAIN_ALLOWLIST
65 import com.stoutner.privacybrowser.helpers.THIRD_PARTY_INITIAL_BLOCKLIST
66 import com.stoutner.privacybrowser.helpers.THIRD_PARTY_ALLOWLIST
67 import com.stoutner.privacybrowser.helpers.THIRD_PARTY_REGULAR_EXPRESSION_BLOCKLIST
69 // Define the class constants.
70 private const val ID = "id"
71 private const val IS_LAST_REQUEST = "is_last_request"
72 private const val REQUEST_DETAILS = "request_details"
74 class ViewRequestDialog : DialogFragment() {
76 fun request(id: Int, isLastRequest: Boolean, requestDetails: Array<String>): ViewRequestDialog {
80 // Store the request details.
82 bundle.putBoolean(IS_LAST_REQUEST, isLastRequest)
83 bundle.putStringArray(REQUEST_DETAILS, requestDetails)
85 // Create a new instance of the view request dialog.
86 val viewRequestDialog = ViewRequestDialog()
88 // Add the arguments to the new dialog.
89 viewRequestDialog.arguments = bundle
91 // Return the new dialog.
92 return viewRequestDialog
96 // Define the class variables.
97 private lateinit var viewRequestListener: ViewRequestListener
99 // The public interface is used to send information back to the parent activity.
100 interface ViewRequestListener {
101 // Show the previous request.
102 fun onPrevious(currentId: Int)
104 // Show the next request.
105 fun onNext(currentId: Int)
108 override fun onAttach(context: Context) {
109 // Run the default commands.
110 super.onAttach(context)
112 // Get a handle for the listener from the launching context.
113 viewRequestListener = context as ViewRequestListener
116 override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
117 // Get the arguments from the bundle.
118 val id = requireArguments().getInt(ID)
119 val isLastRequest = requireArguments().getBoolean(IS_LAST_REQUEST)
120 val requestDetails = requireArguments().getStringArray(REQUEST_DETAILS)!!
122 // Use an alert dialog builder to create the alert dialog.
123 val dialogBuilder = AlertDialog.Builder(requireContext(), R.style.PrivacyBrowserAlertDialog)
126 dialogBuilder.setIcon(R.drawable.block_ads_enabled)
129 dialogBuilder.setTitle(resources.getString(R.string.request_details) + " - " + id)
132 dialogBuilder.setView(R.layout.view_request_dialog)
134 // Set the close button. Using `null` as the listener closes the dialog without doing anything else.
135 dialogBuilder.setNeutralButton(R.string.close, null)
137 // Set the previous button.
138 dialogBuilder.setNegativeButton(R.string.previous) { _: DialogInterface?, _: Int ->
139 // Load the previous request.
140 viewRequestListener.onPrevious(id)
143 // Set the next button.
144 dialogBuilder.setPositiveButton(R.string.next) { _: DialogInterface?, _: Int ->
145 // Load the next request.
146 viewRequestListener.onNext(id)
149 // Create an alert dialog from the alert dialog builder.
150 val alertDialog = dialogBuilder.create()
152 // Get a handle for the shared preferences.
153 val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
155 // Get the screenshot preference.
156 val allowScreenshots = sharedPreferences.getBoolean(getString(R.string.allow_screenshots_key), false)
158 // Disable screenshots if not allowed.
159 if (!allowScreenshots) {
160 // Disable screenshots.
161 alertDialog.window!!.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
164 //The alert dialog must be shown before the contents can be modified.
167 // Get handles for the dialog views.
168 val requestDisposition = alertDialog.findViewById<TextView>(R.id.request_disposition)!!
169 val requestUrl = alertDialog.findViewById<TextView>(R.id.request_url)!!
170 val requestFilterListLabel = alertDialog.findViewById<TextView>(R.id.request_filterlist_label)!!
171 val requestFilterList = alertDialog.findViewById<TextView>(R.id.request_filterlist)!!
172 val requestSubListLabel = alertDialog.findViewById<TextView>(R.id.request_sublist_label)!!
173 val requestSubList = alertDialog.findViewById<TextView>(R.id.request_sublist)!!
174 val requestFilterListEntriesLabel = alertDialog.findViewById<TextView>(R.id.request_filterlist_entries_label)!!
175 val requestFilterListEntries = alertDialog.findViewById<TextView>(R.id.request_filterlist_entries)!!
176 val requestFilterListOriginalEntryLabel = alertDialog.findViewById<TextView>(R.id.request_filterlist_original_entry_label)!!
177 val requestFilterListOriginalEntry = alertDialog.findViewById<TextView>(R.id.request_filterlist_original_entry)!!
178 val previousButton = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE)
179 val nextButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE)
181 // Disable the previous button if the first resource request is displayed.
182 previousButton.isEnabled = (id != 1)
184 // Disable the next button if the last resource request is displayed.
185 nextButton.isEnabled = !isLastRequest
187 // Set the request action text.
188 when (requestDetails[REQUEST_DISPOSITION]) {
191 requestDisposition.setText(R.string.default_allowed)
193 // Set the background color to be transparent.
194 requestDisposition.setBackgroundColor(getColor(requireContext(), R.color.transparent))
199 requestDisposition.setText(R.string.allowed)
201 // Set the background color to be blue.
202 requestDisposition.setBackgroundColor(getColor(requireContext(), R.color.requests_blue_background))
205 REQUEST_THIRD_PARTY -> {
207 requestDisposition.setText(R.string.third_party_blocked)
209 // Set the background color to be yellow.
210 requestDisposition.setBackgroundColor(getColor(requireContext(), R.color.yellow_background))
215 requestDisposition.setText(R.string.blocked)
217 // Set the background color to be red.
218 requestDisposition.setBackgroundColor(getColor(requireContext(), R.color.red_background))
222 // Display the request URL.
223 requestUrl.text = requestDetails[REQUEST_URL]
225 // Modify the dialog based on the request action.
226 if (requestDetails.size == 2) { // A default request.
227 // Hide the unused views.
228 requestFilterListLabel.visibility = View.GONE
229 requestFilterList.visibility = View.GONE
230 requestSubListLabel.visibility = View.GONE
231 requestSubList.visibility = View.GONE
232 requestFilterListEntriesLabel.visibility = View.GONE
233 requestFilterListEntries.visibility = View.GONE
234 requestFilterListOriginalEntryLabel.visibility = View.GONE
235 requestFilterListOriginalEntry.visibility = View.GONE
236 } else { // A blocked or allowed request.
237 // Set the text on the text views.
238 requestFilterList.text = requestDetails[REQUEST_BLOCKLIST]
239 requestFilterListEntries.text = requestDetails[REQUEST_BLOCKLIST_ENTRIES]
240 requestFilterListOriginalEntry.text = requestDetails[REQUEST_BLOCKLIST_ORIGINAL_ENTRY]
241 when (requestDetails[REQUEST_SUBLIST]) {
242 MAIN_ALLOWLIST -> requestSubList.setText(R.string.main_allowlist)
243 FINAL_ALLOWLIST -> requestSubList.setText(R.string.final_allowlist)
244 DOMAIN_ALLOWLIST -> requestSubList.setText(R.string.domain_allowlist)
245 DOMAIN_INITIAL_ALLOWLIST -> requestSubList.setText(R.string.domain_initial_allowlist)
246 DOMAIN_FINAL_ALLOWLIST -> requestSubList.setText(R.string.domain_final_allowlist)
247 THIRD_PARTY_ALLOWLIST -> requestSubList.setText(R.string.third_party_allowlist)
248 THIRD_PARTY_DOMAIN_ALLOWLIST -> requestSubList.setText(R.string.third_party_domain_allowlist)
249 THIRD_PARTY_DOMAIN_INITIAL_ALLOWLIST -> requestSubList.setText(R.string.third_party_domain_initial_allowlist)
250 MAIN_BLOCKLIST -> requestSubList.setText(R.string.main_blocklist)
251 INITIAL_BLOCKLIST -> requestSubList.setText(R.string.initial_blocklist)
252 FINAL_BLOCKLIST -> requestSubList.setText(R.string.final_blocklist)
253 DOMAIN_BLOCKLIST -> requestSubList.setText(R.string.domain_blocklist)
254 DOMAIN_INITIAL_BLOCKLIST -> requestSubList.setText(R.string.domain_initial_blocklist)
255 DOMAIN_FINAL_BLOCKLIST -> requestSubList.setText(R.string.domain_final_blocklist)
256 DOMAIN_REGULAR_EXPRESSION_BLOCKLIST -> requestSubList.setText(R.string.domain_regular_expression_blocklist)
257 THIRD_PARTY_BLOCKLIST -> requestSubList.setText(R.string.third_party_blocklist)
258 THIRD_PARTY_INITIAL_BLOCKLIST -> requestSubList.setText(R.string.third_party_initial_blocklist)
259 THIRD_PARTY_DOMAIN_BLOCKLIST -> requestSubList.setText(R.string.third_party_domain_blocklist)
260 THIRD_PARTY_DOMAIN_INITIAL_BLOCKLIST -> requestSubList.setText(R.string.third_party_domain_initial_blocklist)
261 THIRD_PARTY_REGULAR_EXPRESSION_BLOCKLIST -> requestSubList.setText(R.string.third_party_regular_expression_blocklist)
262 THIRD_PARTY_DOMAIN_REGULAR_EXPRESSION_BLOCKLIST -> requestSubList.setText(R.string.third_party_domain_regular_expression_blocklist)
263 REGULAR_EXPRESSION_BLOCKLIST -> requestSubList.setText(R.string.regular_expression_blocklist)
267 // Return the alert dialog.