Teach resource requests to be tab aware.
[PrivacyBrowser.git] / app / src / main / java / com / stoutner / privacybrowser / dialogs / ViewRequestDialog.java
1 /*
2  * Copyright © 2018-2019 Soren Stoutner <soren@stoutner.com>.
3  *
4  * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
5  *
6  * Privacy Browser 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.
10  *
11  * Privacy Browser 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.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 package com.stoutner.privacybrowser.dialogs;
21
22 import android.annotation.SuppressLint;
23 import android.app.AlertDialog;
24 import android.app.Dialog;
25 import android.content.Context;
26 import android.content.DialogInterface;
27 import android.content.SharedPreferences;
28 import android.os.Bundle;
29 import android.preference.PreferenceManager;
30 import android.view.View;
31 import android.view.WindowManager;
32 import android.widget.Button;
33 import android.widget.TextView;
34
35 import androidx.annotation.NonNull;
36 import androidx.fragment.app.DialogFragment;
37
38 import com.stoutner.privacybrowser.R;
39 import com.stoutner.privacybrowser.helpers.BlockListHelper;
40
41 public class ViewRequestDialog extends DialogFragment {
42     // The public interface is used to send information back to the parent activity.
43     public interface ViewRequestListener {
44         void onPrevious(int id);
45
46         void onNext(int id);
47     }
48
49     // `viewRequestListener` is used in `onAttach()` and `onCreateDialog()`.
50     private ViewRequestListener viewRequestListener;
51
52     public void onAttach(Context context) {
53         // Run the default commands.
54         super.onAttach(context);
55
56         // Get a handle for the listener from the launching context.
57         viewRequestListener = (ViewRequestListener) context;
58     }
59
60     public static ViewRequestDialog request(int id, boolean isLastRequest, String[] requestDetails) {
61         // Create a bundle.
62         Bundle bundle = new Bundle();
63
64         // Store the request details.
65         bundle.putInt("ID", id);
66         bundle.putBoolean("Is Last Request", isLastRequest);
67         bundle.putStringArray("Request Details", requestDetails);
68
69         // Add the bundle to the dialog.
70         ViewRequestDialog viewRequestDialog = new ViewRequestDialog();
71         viewRequestDialog.setArguments(bundle);
72
73         // Return the new dialog.
74         return viewRequestDialog;
75     }
76
77     @Override
78     @NonNull
79     // `@SuppressLing("InflateParams")` removes the warning about using `null` as the parent view group when inflating the `AlertDialog`.
80     @SuppressLint("InflateParams")
81     public Dialog onCreateDialog(Bundle savedInstanceState) {
82         // Get a handle for the shared preferences.
83         SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getContext());
84
85         // Get the theme and screenshot preferences.
86         boolean darkTheme = sharedPreferences.getBoolean("dark_theme", false);
87         boolean allowScreenshots = sharedPreferences.getBoolean("allow_screenshots", false);
88
89         // Remove the incorrect lint warning that `getInt()` might be null.
90         assert getArguments() != null;
91
92         // Get the info from the bundle.
93         int id = getArguments().getInt("ID");
94         boolean isLastRequest = getArguments().getBoolean("Is Last Request");
95         String[] requestDetails = getArguments().getStringArray("Request Details");
96
97         // Use an alert dialog builder to create the alert dialog.
98         AlertDialog.Builder dialogBuilder;
99
100         // Set the style and icon according to the theme.
101         if (darkTheme) {
102             dialogBuilder = new AlertDialog.Builder(getActivity(), R.style.PrivacyBrowserAlertDialogDark);
103             dialogBuilder.setIcon(R.drawable.block_ads_enabled_dark);
104         } else {
105             dialogBuilder = new AlertDialog.Builder(getActivity(), R.style.PrivacyBrowserAlertDialogLight);
106             dialogBuilder.setIcon(R.drawable.block_ads_enabled_light);
107         }
108
109         // Create the dialog title.
110         String title = getResources().getString(R.string.request_details) + " - " + id;
111
112         // Set the title.
113         dialogBuilder.setTitle(title);
114
115         // Remove the incorrect lint warnings about items being null.
116         assert requestDetails != null;
117         assert getActivity() != null;
118
119         // Set the view.  The parent view is null because it will be assigned by the alert dialog.
120         dialogBuilder.setView(getActivity().getLayoutInflater().inflate(R.layout.view_request_dialog, null));
121
122         // Set the close button.
123         dialogBuilder.setNeutralButton(R.string.close, (DialogInterface dialog, int which) -> {
124             // Do nothing.  The dialog will close automatically.
125         });
126
127         // Set the previous button.
128         dialogBuilder.setNegativeButton(R.string.previous, (DialogInterface dialog, int which) -> {
129             // Load the previous request.
130             viewRequestListener.onPrevious(id);
131         });
132
133         // Set the next button.
134         dialogBuilder.setPositiveButton(R.string.next, (DialogInterface dialog, int which) -> {
135             // Load the next request.
136             viewRequestListener.onNext(id);
137         });
138
139         // Create an alert dialog from the alert dialog builder.
140         final AlertDialog alertDialog = dialogBuilder.create();
141
142         // Disable screenshots if not allowed.
143         if (!allowScreenshots) {
144             // Remove the warning below that `getWindow()` might be null.
145             assert alertDialog.getWindow() != null;
146
147             // Disable screenshots.
148             alertDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
149         }
150
151         //The alert dialog must be shown before the contents can be modified.
152         alertDialog.show();
153
154         // Get handles for the dialog views.
155         TextView requestDisposition = alertDialog.findViewById(R.id.request_disposition);
156         TextView requestUrl = alertDialog.findViewById(R.id.request_url);
157         TextView requestBlockListLabel = alertDialog.findViewById(R.id.request_blocklist_label);
158         TextView requestBlockList = alertDialog.findViewById(R.id.request_blocklist);
159         TextView requestSubListLabel = alertDialog.findViewById(R.id.request_sublist_label);
160         TextView requestSubList = alertDialog.findViewById(R.id.request_sublist);
161         TextView requestBlockListEntriesLabel = alertDialog.findViewById(R.id.request_blocklist_entries_label);
162         TextView requestBlockListEntries = alertDialog.findViewById(R.id.request_blocklist_entries);
163         TextView requestBlockListOriginalEntryLabel = alertDialog.findViewById(R.id.request_blocklist_original_entry_label);
164         TextView requestBlockListOriginalEntry = alertDialog.findViewById(R.id.request_blocklist_original_entry);
165         Button previousButton = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
166         Button nextButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
167
168         // Disable the previous button if the first resource request is displayed.
169         previousButton.setEnabled(!(id == 1));
170
171         // Disable the next button if the last resource request is displayed.
172         nextButton.setEnabled(!isLastRequest);
173
174         // Set the request action text.
175         switch (requestDetails[BlockListHelper.REQUEST_DISPOSITION]) {
176             case BlockListHelper.REQUEST_DEFAULT:
177                 // Set the text.
178                 requestDisposition.setText(R.string.default_allowed);
179
180                 // Set the background color.
181                 requestDisposition.setBackgroundColor(getResources().getColor(R.color.transparent));
182                 break;
183
184             case BlockListHelper.REQUEST_ALLOWED:
185                 // Set the text.
186                 requestDisposition.setText(R.string.allowed);
187
188                 // Set the background color.
189                 if (darkTheme) {
190                     requestDisposition.setBackgroundColor(getResources().getColor(R.color.blue_700_50));
191                 } else {
192                     requestDisposition.setBackgroundColor(getResources().getColor(R.color.blue_100));
193                 }
194                 break;
195
196             case BlockListHelper.REQUEST_THIRD_PARTY:
197                 // Set the text.
198                 requestDisposition.setText(R.string.third_party_blocked);
199
200                 // Set the background color.
201                 if (darkTheme) {
202                     requestDisposition.setBackgroundColor(getResources().getColor(R.color.yellow_700_50));
203                 } else {
204                     requestDisposition.setBackgroundColor(getResources().getColor(R.color.yellow_100));
205                 }
206                 break;
207
208             case BlockListHelper.REQUEST_BLOCKED:
209                 // Set the text.
210                 requestDisposition.setText(R.string.blocked);
211
212                 // Set the background color.
213                 if (darkTheme) {
214                     requestDisposition.setBackgroundColor(getResources().getColor(R.color.red_700_40));
215                 } else {
216                     requestDisposition.setBackgroundColor(getResources().getColor(R.color.red_100));
217                 }
218                 break;
219         }
220
221         // Display the request URL.
222         requestUrl.setText(requestDetails[BlockListHelper.REQUEST_URL]);
223
224         // Modify the dialog based on the request action.
225         if (requestDetails.length == 2) {  // A default request.
226             // Hide the unused views.
227             requestBlockListLabel.setVisibility(View.GONE);
228             requestBlockList.setVisibility(View.GONE);
229             requestSubListLabel.setVisibility(View.GONE);
230             requestSubList.setVisibility(View.GONE);
231             requestBlockListEntriesLabel.setVisibility(View.GONE);
232             requestBlockListEntries.setVisibility(View.GONE);
233             requestBlockListOriginalEntryLabel.setVisibility(View.GONE);
234             requestBlockListOriginalEntry.setVisibility(View.GONE);
235         } else {  // A blocked or allowed request.
236             // Set the text on the text views.
237             requestBlockList.setText(requestDetails[BlockListHelper.REQUEST_BLOCKLIST]);
238             requestBlockListEntries.setText(requestDetails[BlockListHelper.REQUEST_BLOCKLIST_ENTRIES]);
239             requestBlockListOriginalEntry.setText(requestDetails[BlockListHelper.REQUEST_BLOCKLIST_ORIGINAL_ENTRY]);
240
241             // Set the sublist text.
242             switch (requestDetails[BlockListHelper.REQUEST_SUBLIST]) {
243                 case BlockListHelper.MAIN_WHITELIST:
244                     requestSubList.setText(R.string.main_whitelist);
245                     break;
246
247                 case BlockListHelper.FINAL_WHITELIST:
248                     requestSubList.setText(R.string.final_whitelist);
249                     break;
250
251                 case BlockListHelper.DOMAIN_WHITELIST:
252                     requestSubList.setText(R.string.domain_whitelist);
253                     break;
254
255                 case BlockListHelper.DOMAIN_INITIAL_WHITELIST:
256                     requestSubList.setText(R.string.domain_initial_whitelist);
257                     break;
258
259                 case BlockListHelper.DOMAIN_FINAL_WHITELIST:
260                     requestSubList.setText(R.string.domain_final_whitelist);
261                     break;
262
263                 case BlockListHelper.THIRD_PARTY_WHITELIST:
264                     requestSubList.setText(R.string.third_party_whitelist);
265                     break;
266
267                 case BlockListHelper.THIRD_PARTY_DOMAIN_WHITELIST:
268                     requestSubList.setText(R.string.third_party_domain_whitelist);
269                     break;
270
271                 case BlockListHelper.THIRD_PARTY_DOMAIN_INITIAL_WHITELIST:
272                     requestSubList.setText(R.string.third_party_domain_initial_whitelist);
273                     break;
274
275                 case BlockListHelper.MAIN_BLACKLIST:
276                     requestSubList.setText(R.string.main_blacklist);
277                     break;
278
279                 case BlockListHelper.INITIAL_BLACKLIST:
280                     requestSubList.setText(R.string.initial_blacklist);
281                     break;
282
283                 case BlockListHelper.FINAL_BLACKLIST:
284                     requestSubList.setText(R.string.final_blacklist);
285                     break;
286
287                 case BlockListHelper.DOMAIN_BLACKLIST:
288                     requestSubList.setText(R.string.domain_blacklist);
289                     break;
290
291                 case BlockListHelper.DOMAIN_INITIAL_BLACKLIST:
292                     requestSubList.setText(R.string.domain_initial_blacklist);
293                     break;
294
295                 case BlockListHelper.DOMAIN_FINAL_BLACKLIST:
296                     requestSubList.setText(R.string.domain_final_blacklist);
297                     break;
298
299                 case BlockListHelper.DOMAIN_REGULAR_EXPRESSION_BLACKLIST:
300                     requestSubList.setText(R.string.domain_regular_expression_blacklist);
301                     break;
302
303                 case BlockListHelper.THIRD_PARTY_BLACKLIST:
304                     requestSubList.setText(R.string.third_party_blacklist);
305                     break;
306
307                 case BlockListHelper.THIRD_PARTY_INITIAL_BLACKLIST:
308                     requestSubList.setText(R.string.third_party_initial_blacklist);
309                     break;
310
311                 case BlockListHelper.THIRD_PARTY_DOMAIN_BLACKLIST:
312                     requestSubList.setText(R.string.third_party_domain_blacklist);
313                     break;
314
315                 case BlockListHelper.THIRD_PARTY_DOMAIN_INITIAL_BLACKLIST:
316                     requestSubList.setText(R.string.third_party_domain_initial_blacklist);
317                     break;
318
319                 case BlockListHelper.THIRD_PARTY_REGULAR_EXPRESSION_BLACKLIST:
320                     requestSubList.setText(R.string.third_party_regular_expression_blacklist);
321                     break;
322
323                 case BlockListHelper.THIRD_PARTY_DOMAIN_REGULAR_EXPRESSION_BLACKLIST:
324                     requestSubList.setText(R.string.third_party_domain_regular_expression_blacklist);
325                     break;
326
327                 case BlockListHelper.REGULAR_EXPRESSION_BLACKLIST:
328                     requestSubList.setText(R.string.regular_expression_blacklist);
329                     break;
330             }
331         }
332
333         // `onCreateDialog` requires the return of an alert dialog.
334         return alertDialog;
335     }
336 }