2 * Copyright © 2018-2019 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
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.
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.
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/>.
20 package com.stoutner.privacybrowser.activities;
22 import android.content.Context;
23 import android.content.SharedPreferences;
24 import android.database.Cursor;
25 import android.database.MatrixCursor;
26 import android.os.Bundle;
27 import android.preference.PreferenceManager;
28 import android.view.View;
29 import android.view.WindowManager;
30 import android.widget.AdapterView;
31 import android.widget.ArrayAdapter;
32 import android.widget.ListView;
33 import android.widget.ResourceCursorAdapter;
34 import android.widget.Spinner;
35 import android.widget.TextView;
37 import androidx.appcompat.app.ActionBar;
38 import androidx.appcompat.app.AppCompatActivity;
39 import androidx.appcompat.widget.Toolbar; // The AndroidX toolbar must be used until the minimum API >= 21.
40 import androidx.fragment.app.DialogFragment;
42 import com.stoutner.privacybrowser.R;
43 import com.stoutner.privacybrowser.adapters.RequestsArrayAdapter;
44 import com.stoutner.privacybrowser.dialogs.ViewRequestDialog;
45 import com.stoutner.privacybrowser.helpers.BlockListHelper;
47 import java.util.ArrayList;
48 import java.util.List;
50 public class RequestsActivity extends AppCompatActivity implements ViewRequestDialog.ViewRequestListener {
51 // The resource requests are populated by `MainWebViewActivity` before `RequestsActivity` is launched.
52 public static ArrayList<String[]> resourceRequests;
54 // The list view is used in `onCreate()` and `launchViewRequestDialog()`.
55 private ListView requestsListView;
58 public void onCreate(Bundle savedInstanceState) {
59 // Get a handle for the shared preferences.
60 SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
62 // Get the screenshot and theme preferences.
63 boolean allowScreenshots = sharedPreferences.getBoolean("allow_screenshots", false);
64 boolean darkTheme = sharedPreferences.getBoolean("dark_theme", false);
66 // Disable screenshots if not allowed.
67 if (!allowScreenshots) {
68 getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
71 // Set the activity theme.
73 setTheme(R.style.PrivacyBrowserDark_SecondaryActivity);
75 setTheme(R.style.PrivacyBrowserLight_SecondaryActivity);
78 // Run the default commands.
79 super.onCreate(savedInstanceState);
81 // Set the content view.
82 setContentView(R.layout.requests_coordinatorlayout);
84 // Use the AndroidX toolbar until the minimum API is >= 21.
85 Toolbar toolbar = findViewById(R.id.requests_toolbar);
86 setSupportActionBar(toolbar);
88 // Get a handle for the app bar and the list view.
89 ActionBar appBar = getSupportActionBar();
90 requestsListView = findViewById(R.id.requests_listview);
92 // Remove the incorrect lint warning that `appBar` might be null.
93 assert appBar != null;
95 // Display the spinner and the back arrow in the app bar.
96 appBar.setCustomView(R.layout.spinner);
97 appBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_HOME_AS_UP);
99 // Initialize the resource array lists. A list is needed for all the resource requests, or the activity can crash if `MainWebViewActivity.resourceRequests` is modified after the activity loads.
100 List<String[]> allResourceRequests = new ArrayList<>();
101 List<String[]> defaultResourceRequests = new ArrayList<>();
102 List<String[]> allowedResourceRequests = new ArrayList<>();
103 List<String[]> thirdPartyResourceRequests = new ArrayList<>();
104 List<String[]> blockedResourceRequests = new ArrayList<>();
106 // Populate the resource array lists.
107 for (String[] request : resourceRequests) {
108 switch (request[BlockListHelper.REQUEST_DISPOSITION]) {
109 case BlockListHelper.REQUEST_DEFAULT:
110 // Add the request to the list of all requests.
111 allResourceRequests.add(request);
113 // Add the request to the list of default requests.
114 defaultResourceRequests.add(request);
117 case BlockListHelper.REQUEST_ALLOWED:
118 // Add the request to the list of all requests.
119 allResourceRequests.add(request);
121 // Add the request to the list of allowed requests.
122 allowedResourceRequests.add(request);
125 case BlockListHelper.REQUEST_THIRD_PARTY:
126 // Add the request to the list of all requests.
127 allResourceRequests.add(request);
129 // Add the request to the list of third-party requests.
130 thirdPartyResourceRequests.add(request);
133 case BlockListHelper.REQUEST_BLOCKED:
134 // Add the request to the list of all requests.
135 allResourceRequests.add(request);
137 // Add the request to the list of blocked requests.
138 blockedResourceRequests.add(request);
143 // Setup a matrix cursor for the resource lists.
144 MatrixCursor spinnerCursor = new MatrixCursor(new String[]{"_id", "Requests"});
145 spinnerCursor.addRow(new Object[]{0, getString(R.string.all) + " - " + allResourceRequests.size()});
146 spinnerCursor.addRow(new Object[]{1, getString(R.string.default_label) + " - " + defaultResourceRequests.size()});
147 spinnerCursor.addRow(new Object[]{2, getString(R.string.allowed_plural) + " - " + allowedResourceRequests.size()});
148 if (MainWebViewActivity.blockAllThirdPartyRequests) {
149 spinnerCursor.addRow(new Object[]{3, getString(R.string.third_party_plural) + " - " + thirdPartyResourceRequests.size()});
151 spinnerCursor.addRow(new Object[]{4, getString(R.string.blocked_plural) + " - " + blockedResourceRequests.size()});
153 // Create a resource cursor adapter for the spinner.
154 ResourceCursorAdapter spinnerCursorAdapter = new ResourceCursorAdapter(this, R.layout.requests_appbar_spinner_item, spinnerCursor, 0) {
156 public void bindView(View view, Context context, Cursor cursor) {
157 // Get a handle for the spinner item text view.
158 TextView spinnerItemTextView = view.findViewById(R.id.spinner_item_textview);
160 // Set the text view to display the resource list.
161 spinnerItemTextView.setText(cursor.getString(1));
165 // Set the resource cursor adapter drop down view resource.
166 spinnerCursorAdapter.setDropDownViewResource(R.layout.requests_appbar_spinner_dropdown_item);
168 // Get a handle for the app bar spinner and set the adapter.
169 Spinner appBarSpinner = findViewById(R.id.spinner);
170 appBarSpinner.setAdapter(spinnerCursorAdapter);
172 // Handle clicks on the spinner dropdown.
173 appBarSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
175 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
177 case 0: // All requests.
178 // Get an adapter for all the request.
179 ArrayAdapter<String[]> allResourceRequestsArrayAdapter = new RequestsArrayAdapter(getApplicationContext(), allResourceRequests);
181 // Display the adapter in the list view.
182 requestsListView.setAdapter(allResourceRequestsArrayAdapter);
185 case 1: // Default requests.
186 // Get an adapter for the default requests.
187 ArrayAdapter<String[]> defaultResourceRequestsArrayAdapter = new RequestsArrayAdapter(getApplicationContext(), defaultResourceRequests);
189 // Display the adapter in the list view.
190 requestsListView.setAdapter(defaultResourceRequestsArrayAdapter);
193 case 2: // Allowed requests.
194 // Get an adapter for the allowed requests.
195 ArrayAdapter<String[]> allowedResourceRequestsArrayAdapter = new RequestsArrayAdapter(getApplicationContext(), allowedResourceRequests);
197 // Display the adapter in the list view.
198 requestsListView.setAdapter(allowedResourceRequestsArrayAdapter);
201 case 3: // Third-party requests.
202 // Get an adapter for the third-party requests.
203 ArrayAdapter<String[]> thirdPartyResourceRequestsArrayAdapter = new RequestsArrayAdapter(getApplicationContext(), thirdPartyResourceRequests);
205 //Display the adapter in the list view.
206 requestsListView.setAdapter(thirdPartyResourceRequestsArrayAdapter);
209 case 4: // Blocked requests.
210 // Get an adapter fo the blocked requests.
211 ArrayAdapter<String[]> blockedResourceRequestsArrayAdapter = new RequestsArrayAdapter(getApplicationContext(), blockedResourceRequests);
213 // Display the adapter in the list view.
214 requestsListView.setAdapter(blockedResourceRequestsArrayAdapter);
220 public void onNothingSelected(AdapterView<?> parent) {
225 // Create an array adapter with the list of the resource requests.
226 ArrayAdapter<String[]> resourceRequestsArrayAdapter = new RequestsArrayAdapter(getApplicationContext(), allResourceRequests);
228 // Populate the list view with the resource requests adapter.
229 requestsListView.setAdapter(resourceRequestsArrayAdapter);
231 // Listen for taps on entries in the list view.
232 requestsListView.setOnItemClickListener((AdapterView<?> parent, View view, int position, long id) -> {
233 // Display the view request dialog. The list view is 0 based, so the position must be incremented by 1.
234 launchViewRequestDialog(position + 1);
239 public void onPrevious(int id) {
240 // Show the previous dialog.
241 launchViewRequestDialog(id -1);
245 public void onNext(int id) {
246 // Show the next dialog.
247 launchViewRequestDialog(id + 1);
250 private void launchViewRequestDialog(int id) {
251 // Determine if this is the last request in the list.
252 boolean isLastRequest = (id == requestsListView.getCount());
254 // Get the string array for the selected resource request. The resource requests list view is zero based.
255 String[] selectedRequestStringArray = (String[]) requestsListView.getItemAtPosition(id - 1);
257 // Remove the warning that `selectedRequest` might be null.
258 assert selectedRequestStringArray != null;
260 // Show the request detail dialog.
261 DialogFragment viewRequestDialogFragment = ViewRequestDialog.request(id, isLastRequest, selectedRequestStringArray);
262 viewRequestDialogFragment.show(getSupportFragmentManager(), getString(R.string.request_details));