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_BLACKLIST
37 import com.stoutner.privacybrowser.helpers.DOMAIN_FINAL_BLACKLIST
38 import com.stoutner.privacybrowser.helpers.DOMAIN_FINAL_WHITELIST
39 import com.stoutner.privacybrowser.helpers.DOMAIN_INITIAL_BLACKLIST
40 import com.stoutner.privacybrowser.helpers.DOMAIN_INITIAL_WHITELIST
41 import com.stoutner.privacybrowser.helpers.DOMAIN_REGULAR_EXPRESSION_BLACKLIST
42 import com.stoutner.privacybrowser.helpers.DOMAIN_WHITELIST
43 import com.stoutner.privacybrowser.helpers.INITIAL_BLACKLIST
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_BLACKLIST
52 import com.stoutner.privacybrowser.helpers.FINAL_WHITELIST
53 import com.stoutner.privacybrowser.helpers.MAIN_BLACKLIST
54 import com.stoutner.privacybrowser.helpers.MAIN_WHITELIST
55 import com.stoutner.privacybrowser.helpers.REGULAR_EXPRESSION_BLACKLIST
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_BLACKLIST
60 import com.stoutner.privacybrowser.helpers.THIRD_PARTY_DOMAIN_BLACKLIST
61 import com.stoutner.privacybrowser.helpers.THIRD_PARTY_DOMAIN_INITIAL_BLACKLIST
62 import com.stoutner.privacybrowser.helpers.THIRD_PARTY_DOMAIN_INITIAL_WHITELIST
63 import com.stoutner.privacybrowser.helpers.THIRD_PARTY_DOMAIN_REGULAR_EXPRESSION_BLACKLIST
64 import com.stoutner.privacybrowser.helpers.THIRD_PARTY_DOMAIN_WHITELIST
65 import com.stoutner.privacybrowser.helpers.THIRD_PARTY_INITIAL_BLACKLIST
66 import com.stoutner.privacybrowser.helpers.THIRD_PARTY_REGULAR_EXPRESSION_BLACKLIST
67 import com.stoutner.privacybrowser.helpers.THIRD_PARTY_WHITELIST
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 requestBlockListLabel = alertDialog.findViewById<TextView>(R.id.request_blocklist_label)!!
171 val requestBlockList = alertDialog.findViewById<TextView>(R.id.request_blocklist)!!
172 val requestSubListLabel = alertDialog.findViewById<TextView>(R.id.request_sublist_label)!!
173 val requestSubList = alertDialog.findViewById<TextView>(R.id.request_sublist)!!
174 val requestBlockListEntriesLabel = alertDialog.findViewById<TextView>(R.id.request_blocklist_entries_label)!!
175 val requestBlockListEntries = alertDialog.findViewById<TextView>(R.id.request_blocklist_entries)!!
176 val requestBlockListOriginalEntryLabel = alertDialog.findViewById<TextView>(R.id.request_blocklist_original_entry_label)!!
177 val requestBlockListOriginalEntry = alertDialog.findViewById<TextView>(R.id.request_blocklist_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.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 requestBlockListLabel.visibility = View.GONE
229 requestBlockList.visibility = View.GONE
230 requestSubListLabel.visibility = View.GONE
231 requestSubList.visibility = View.GONE
232 requestBlockListEntriesLabel.visibility = View.GONE
233 requestBlockListEntries.visibility = View.GONE
234 requestBlockListOriginalEntryLabel.visibility = View.GONE
235 requestBlockListOriginalEntry.visibility = View.GONE
236 } else { // A blocked or allowed request.
237 // Set the text on the text views.
238 requestBlockList.text = requestDetails[REQUEST_BLOCKLIST]
239 requestBlockListEntries.text = requestDetails[REQUEST_BLOCKLIST_ENTRIES]
240 requestBlockListOriginalEntry.text = requestDetails[REQUEST_BLOCKLIST_ORIGINAL_ENTRY]
241 when (requestDetails[REQUEST_SUBLIST]) {
242 MAIN_WHITELIST -> requestSubList.setText(R.string.main_whitelist)
243 FINAL_WHITELIST -> requestSubList.setText(R.string.final_whitelist)
244 DOMAIN_WHITELIST -> requestSubList.setText(R.string.domain_whitelist)
245 DOMAIN_INITIAL_WHITELIST -> requestSubList.setText(R.string.domain_initial_whitelist)
246 DOMAIN_FINAL_WHITELIST -> requestSubList.setText(R.string.domain_final_whitelist)
247 THIRD_PARTY_WHITELIST -> requestSubList.setText(R.string.third_party_whitelist)
248 THIRD_PARTY_DOMAIN_WHITELIST -> requestSubList.setText(R.string.third_party_domain_whitelist)
249 THIRD_PARTY_DOMAIN_INITIAL_WHITELIST -> requestSubList.setText(R.string.third_party_domain_initial_whitelist)
250 MAIN_BLACKLIST -> requestSubList.setText(R.string.main_blacklist)
251 INITIAL_BLACKLIST -> requestSubList.setText(R.string.initial_blacklist)
252 FINAL_BLACKLIST -> requestSubList.setText(R.string.final_blacklist)
253 DOMAIN_BLACKLIST -> requestSubList.setText(R.string.domain_blacklist)
254 DOMAIN_INITIAL_BLACKLIST -> requestSubList.setText(R.string.domain_initial_blacklist)
255 DOMAIN_FINAL_BLACKLIST -> requestSubList.setText(R.string.domain_final_blacklist)
256 DOMAIN_REGULAR_EXPRESSION_BLACKLIST -> requestSubList.setText(R.string.domain_regular_expression_blacklist)
257 THIRD_PARTY_BLACKLIST -> requestSubList.setText(R.string.third_party_blacklist)
258 THIRD_PARTY_INITIAL_BLACKLIST -> requestSubList.setText(R.string.third_party_initial_blacklist)
259 THIRD_PARTY_DOMAIN_BLACKLIST -> requestSubList.setText(R.string.third_party_domain_blacklist)
260 THIRD_PARTY_DOMAIN_INITIAL_BLACKLIST -> requestSubList.setText(R.string.third_party_domain_initial_blacklist)
261 THIRD_PARTY_REGULAR_EXPRESSION_BLACKLIST -> requestSubList.setText(R.string.third_party_regular_expression_blacklist)
262 THIRD_PARTY_DOMAIN_REGULAR_EXPRESSION_BLACKLIST -> requestSubList.setText(R.string.third_party_domain_regular_expression_blacklist)
263 REGULAR_EXPRESSION_BLACKLIST -> requestSubList.setText(R.string.regular_expression_blacklist)
267 // Return the alert dialog.