Add on-the-fly blocklist controls. https://redmine.stoutner.com/issues/279
[PrivacyBrowser.git] / app / src / main / java / com / stoutner / privacybrowser / activities / RequestsActivity.java
1 /*
2  * Copyright © 2018 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.activities;
21
22 import android.content.Context;
23 import android.database.Cursor;
24 import android.database.MatrixCursor;
25 import android.os.Bundle;
26 import android.support.v7.app.ActionBar;
27 import android.support.v7.app.AppCompatActivity;
28 import android.support.v7.app.AppCompatDialogFragment;
29 import android.support.v7.widget.Toolbar;
30 import android.view.View;
31 import android.view.WindowManager;
32 import android.widget.AdapterView;
33 import android.widget.ArrayAdapter;
34 import android.widget.ListView;
35 import android.widget.ResourceCursorAdapter;
36 import android.widget.Spinner;
37 import android.widget.TextView;
38
39 import com.stoutner.privacybrowser.R;
40 import com.stoutner.privacybrowser.adapters.RequestsArrayAdapter;
41 import com.stoutner.privacybrowser.dialogs.ViewRequestDialog;
42
43 import java.util.ArrayList;
44 import java.util.List;
45
46 public class RequestsActivity extends AppCompatActivity implements ViewRequestDialog.ViewRequestListener {
47     // The list view is used in `onCreate()` and `launchViewRequestDialog()`.
48     private ListView resourceRequestsListView;
49
50     @Override
51     public void onCreate(Bundle savedInstanceState) {
52         // Disable screenshots if not allowed.
53         if (!MainWebViewActivity.allowScreenshots) {
54             getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
55         }
56
57         // Set the activity theme.
58         if (MainWebViewActivity.darkTheme) {
59             setTheme(R.style.PrivacyBrowserDark_SecondaryActivity);
60         } else {
61             setTheme(R.style.PrivacyBrowserLight_SecondaryActivity);
62         }
63
64         // Run the default commands.
65         super.onCreate(savedInstanceState);
66
67         // Set the content view.
68         setContentView(R.layout.requests_coordinatorlayout);
69
70         // Use the `SupportActionBar` from `android.support.v7.app.ActionBar` until the minimum API is >= 21.
71         Toolbar blockListsAppBar = findViewById(R.id.blocklists_toolbar);
72         setSupportActionBar(blockListsAppBar);
73
74         // Get a handle for the app bar and the list view.
75         ActionBar appBar = getSupportActionBar();
76         resourceRequestsListView = findViewById(R.id.resource_requests_listview);
77
78         // Remove the incorrect lint warning that `appBar` might be null.
79         assert appBar != null;
80
81         // Display the spinner and the back arrow in the app bar.
82         appBar.setCustomView(R.layout.requests_spinner);
83         appBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_HOME_AS_UP);
84
85         // 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.
86         List<String[]> allResourceRequests = new ArrayList<>();
87         List<String[]> defaultResourceRequests = new ArrayList<>();
88         List<String[]> allowedResourceRequests = new ArrayList<>();
89         List<String[]> blockedResourceRequests = new ArrayList<>();
90
91         // Populate the resource array lists.
92         for (String[] request : MainWebViewActivity.resourceRequests) {
93             switch (Integer.valueOf(request[MainWebViewActivity.REQUEST_DISPOSITION])) {
94                 case MainWebViewActivity.REQUEST_DEFAULT:
95                     // Add the request to the list of all requests.
96                     allResourceRequests.add(request);
97
98                     // Add the request to the list of default requests.
99                     defaultResourceRequests.add(request);
100                     break;
101
102                 case MainWebViewActivity.REQUEST_ALLOWED:
103                     // Add the request to the list of all requests.
104                     allResourceRequests.add(request);
105
106                     // Add the request to the list of allowed requests.
107                     allowedResourceRequests.add(request);
108                     break;
109
110                 case MainWebViewActivity.REQUEST_BLOCKED:
111                     // Add the request to the list of all requests.
112                     allResourceRequests.add(request);
113
114                     // Add the request to the list of blocked requests.
115                     blockedResourceRequests.add(request);
116                     break;
117             }
118         }
119
120         // Setup a matrix cursor for the resource lists.
121         MatrixCursor spinnerCursor = new MatrixCursor(new String[]{"_id", "Requests"});
122         spinnerCursor.addRow(new Object[]{0, getString(R.string.all) + " - " + allResourceRequests.size()});
123         spinnerCursor.addRow(new Object[]{1, getString(R.string.default_label) + " - " + defaultResourceRequests.size()});
124         spinnerCursor.addRow(new Object[]{2, getString(R.string.allowed_plural) + " - " + allowedResourceRequests.size()});
125         spinnerCursor.addRow(new Object[]{3, getString(R.string.blocked_plural) + " - " + blockedResourceRequests.size()});
126
127         // Create a resource cursor adapter for the spinner.
128         ResourceCursorAdapter spinnerCursorAdapter = new ResourceCursorAdapter(this, R.layout.requests_spinner_item, spinnerCursor, 0) {
129             @Override
130             public void bindView(View view, Context context, Cursor cursor) {
131                 // Get a handle for the spinner item text view.
132                 TextView spinnerItemTextView = view.findViewById(R.id.spinner_item_textview);
133
134                 // Set the text view to display the resource list.
135                 spinnerItemTextView.setText(cursor.getString(1));
136             }
137         };
138
139         // Set the resource cursor adapter drop down view resource.
140         spinnerCursorAdapter.setDropDownViewResource(R.layout.requests_spinner_dropdown_item);
141
142         // Get a handle for the app bar spinner and set the adapter.
143         Spinner appBarSpinner = findViewById(R.id.requests_spinner);
144         appBarSpinner.setAdapter(spinnerCursorAdapter);
145
146         // Handle clicks on the spinner dropdown.
147         appBarSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
148             @Override
149             public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
150                 switch (position) {
151                     case 0:  // All requests.
152                         // Get an adapter for all the request.
153                         ArrayAdapter<String[]> allResourceRequestsArrayAdapter = new RequestsArrayAdapter(getApplicationContext(), allResourceRequests);
154
155                         // Display the adapter in the list view.
156                         resourceRequestsListView.setAdapter(allResourceRequestsArrayAdapter);
157                         break;
158
159                     case 1:  // Default requests.
160                         // Get an adapter for the default requests.
161                         ArrayAdapter<String[]> defaultResourceRequestsArrayAdapter = new RequestsArrayAdapter(getApplicationContext(), defaultResourceRequests);
162
163                         // Display the adapter in the list view.
164                         resourceRequestsListView.setAdapter(defaultResourceRequestsArrayAdapter);
165                         break;
166
167                     case 2:  // Allowed requests.
168                         // Get an adapter for the allowed requests.
169                         ArrayAdapter<String[]> allowedResourceRequestsArrayAdapter = new RequestsArrayAdapter(getApplicationContext(), allowedResourceRequests);
170
171                         // Display the adapter in the list view.
172                         resourceRequestsListView.setAdapter(allowedResourceRequestsArrayAdapter);
173                         break;
174
175                     case 3:  // Blocked requests.
176                         // Get an adapter fo the blocked requests.
177                         ArrayAdapter<String[]> blockedResourceRequestsArrayAdapter = new RequestsArrayAdapter(getApplicationContext(), blockedResourceRequests);
178
179                         // Display the adapter in the list view.
180                         resourceRequestsListView.setAdapter(blockedResourceRequestsArrayAdapter);
181                         break;
182                 }
183             }
184
185             @Override
186             public void onNothingSelected(AdapterView<?> parent) {
187                 // Do nothing.
188             }
189         });
190
191         // Create an array adapter with the list of the resource requests.
192         ArrayAdapter<String[]> resourceRequestsArrayAdapter = new RequestsArrayAdapter(getApplicationContext(), allResourceRequests);
193
194         // Populate the list view with the resource requests adapter.
195         resourceRequestsListView.setAdapter(resourceRequestsArrayAdapter);
196
197         // Listen for taps on entries in the list view.
198         resourceRequestsListView.setOnItemClickListener((AdapterView<?> parent, View view, int position, long id) -> {
199             // Display the view request dialog.  The list view is 0 based, so the position must be incremented by 1.
200             launchViewRequestDialog(position + 1);
201         });
202     }
203
204     @Override
205     public void onPrevious(int id) {
206         // Show the previous dialog.
207         launchViewRequestDialog(id -1);
208     }
209
210     @Override
211     public void onNext(int id) {
212         // Show the next dialog.
213         launchViewRequestDialog(id + 1);
214     }
215
216     private void launchViewRequestDialog(int id) {
217         // Determine if this is the last request in the list.
218         boolean isLastRequest = (id == resourceRequestsListView.getCount());
219
220         // Get the string array for the selected resource request.  The resource requests list view is zero based.
221         String[] selectedRequestStringArray = (String[]) resourceRequestsListView.getItemAtPosition(id - 1);
222
223         // Remove the warning that `selectedRequest` might be null.
224         assert selectedRequestStringArray != null;
225
226         // Show the request detail dialog.
227         AppCompatDialogFragment viewRequestDialogFragment = ViewRequestDialog.request(id, isLastRequest, selectedRequestStringArray);
228         viewRequestDialogFragment.show(getSupportFragmentManager(), getString(R.string.request_details));
229     }
230 }