]> gitweb.stoutner.com Git - PrivacyCell.git/blob - app/src/main/java/com/stoutner/privacycell/dialogs/WebViewDialog.kt
Release 1.10.
[PrivacyCell.git] / app / src / main / java / com / stoutner / privacycell / dialogs / WebViewDialog.kt
1 /*
2  * Copyright 2021-2022 Soren Stoutner <soren@stoutner.com>.
3  *
4  * This file is part of Privacy Cell <https://www.stoutner.com/privacy-cell>.
5  *
6  * Privacy Cell 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 Cell 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 Cell.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 package com.stoutner.privacycell.dialogs
21
22 import android.app.Dialog
23 import android.content.Intent
24 import android.os.Bundle
25 import android.webkit.WebResourceRequest
26 import android.webkit.WebResourceResponse
27 import android.webkit.WebView
28 import android.webkit.WebViewClient
29
30 import androidx.appcompat.app.AlertDialog
31 import androidx.fragment.app.DialogFragment
32 import androidx.webkit.WebViewAssetLoader
33
34 import com.stoutner.privacycell.R
35
36 // Define the class constants.
37 private const val DIALOG_TYPE = "dialog_type"
38 private const val SCROLL_Y = "scroll_y"
39
40 class WebViewDialog : DialogFragment() {
41     companion object {
42         // Define the public constants.
43         const val PERMISSIONS = 0
44         const val PRIVACY_POLICY = 1
45         const val CHANGELOG = 2
46         const val LICENSES = 3
47         const val CONTRIBUTORS = 4
48         const val STINGRAY = 5
49         const val ANTIQUATED_NETWORK = 6
50         const val NETWORK_UNKNOWN = 7
51         const val NETWORK_GPRS = 8
52         const val NETWORK_EDGE = 9
53         const val NETWORK_UMTS = 10
54         const val NETWORK_CDMA = 11
55         const val NETWORK_EVDO_0 = 12
56         const val NETWORK_EVDO_A = 13
57         const val NETWORK_1xRTT = 14
58         const val NETWORK_HSDPA = 15
59         const val NETWORK_HSUPA = 16
60         const val NETWORK_HSPA = 17
61         const val NETWORK_IDEN = 18
62         const val NETWORK_EVDO_B = 19
63         const val NETWORK_LTE = 20
64         const val NETWORK_EHRPD = 21
65         const val NETWORK_HSPAP = 22
66         const val NETWORK_GSM = 23
67         const val NETWORK_TD_SCDMA = 24
68         const val NETWORK_IWLAN = 25
69         const val NETWORK_NR = 26
70         const val OVERRIDE_NETWORK_NONE = 27
71         const val OVERRIDE_NETWORK_LTE_CA = 28
72         const val OVERRIDE_NETWORK_LTE_ADVANCED_PRO = 29
73         const val OVERRIDE_NETWORK_NR_NSA = 30
74         const val OVERRIDE_NETWORK_NR_NSA_MMWAVE = 31  // Can be removed once the minimum API >= 31.
75         const val OVERRIDE_NETWORK_NR_ADVANCED = 32
76     }
77
78     // Define the class views.
79     private lateinit var webView: WebView
80
81     // Populate the WebView dialog type.
82     fun type(dialogType: Int): WebViewDialog {
83         // Create an arguments bundle.
84         val argumentsBundle = Bundle()
85
86         // Add the dialog type to the bundle.
87         argumentsBundle.putInt(DIALOG_TYPE, dialogType)
88
89         // Create a new instance of the WebView dialog.
90         val webViewDialog = WebViewDialog()
91
92         // Add the arguments bundle to the new dialog.
93         webViewDialog.arguments = argumentsBundle
94
95         // Return the new dialog.
96         return webViewDialog
97     }
98
99     override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
100         // Get the dialog type from the arguments bundle.
101         val dialogType = requireArguments().getInt(DIALOG_TYPE)
102
103         // Use a builder to create the alert dialog.
104         val dialogBuilder = AlertDialog.Builder(requireContext(), R.style.Theme_PrivacyCellAlertDialog)
105
106         // Set the icon and the title according to the dialog type.
107         when (dialogType) {
108             PERMISSIONS -> {
109                 // Set the icon.
110                 dialogBuilder.setIcon(R.drawable.permissions)
111
112                 // Set the title.
113                 dialogBuilder.setTitle(R.string.permissions)
114             }
115
116             PRIVACY_POLICY -> {
117                 // Set the icon.
118                 dialogBuilder.setIcon(R.drawable.privacy_policy)
119
120                 // Set the title.
121                 dialogBuilder.setTitle(R.string.privacy_policy)
122             }
123
124             CHANGELOG -> {
125                 // Set the icon.
126                 dialogBuilder.setIcon(R.drawable.changelog)
127
128                 // Set the title.
129                 dialogBuilder.setTitle(R.string.changelog)
130             }
131
132             LICENSES -> {
133                 // Set the icon.
134                 dialogBuilder.setIcon(R.drawable.licenses)
135
136                 // Set the title.
137                 dialogBuilder.setTitle(R.string.licenses)
138             }
139
140             CONTRIBUTORS -> {
141                 // Set the icon.
142                 dialogBuilder.setIcon(R.drawable.contributors)
143
144                 // Set the tile.
145                 dialogBuilder.setTitle(R.string.contributors)
146             }
147
148             STINGRAY -> {
149                 // Set the icon.
150                 dialogBuilder.setIcon(R.drawable.secure)
151
152                 // Set the tile.
153                 dialogBuilder.setTitle(R.string.stingrays)
154             }
155
156             ANTIQUATED_NETWORK -> {
157                 // Set the icon.
158                 dialogBuilder.setIcon(R.drawable.antiquated)
159
160                 // Set the title.
161                 dialogBuilder.setTitle(R.string.antiquated_network_title)
162             }
163
164             NETWORK_UNKNOWN -> {
165                 // Set the icon.
166                 dialogBuilder.setIcon(R.drawable.protocols)
167
168                 // Set the title.
169                 dialogBuilder.setTitle(R.string.unknown)
170             }
171
172             NETWORK_GPRS -> {
173                 // Set the icon.
174                 dialogBuilder.setIcon(R.drawable.protocols)
175
176                 // Set the title.
177                 dialogBuilder.setTitle(R.string.gprs)
178             }
179
180             NETWORK_EDGE -> {
181                 // Set the icon.
182                 dialogBuilder.setIcon(R.drawable.protocols)
183
184                 // Set the title.
185                 dialogBuilder.setTitle(R.string.edge)
186             }
187
188             NETWORK_UMTS -> {
189                 // Set the icon.
190                 dialogBuilder.setIcon(R.drawable.protocols)
191
192                 // Set the title.
193                 dialogBuilder.setTitle(R.string.umts)
194             }
195
196             NETWORK_CDMA -> {
197                 // Set the icon.
198                 dialogBuilder.setIcon(R.drawable.protocols)
199
200                 // Set the title.
201                 dialogBuilder.setTitle(R.string.cdma)
202             }
203
204             NETWORK_EVDO_0 -> {
205                 // Set the icon.
206                 dialogBuilder.setIcon(R.drawable.protocols)
207
208                 // Set the title.
209                 dialogBuilder.setTitle(R.string.evdo_0)
210             }
211
212             NETWORK_EVDO_A -> {
213                 // Set the icon.
214                 dialogBuilder.setIcon(R.drawable.protocols)
215
216                 // Set the title.
217                 dialogBuilder.setTitle(R.string.evdo_a)
218             }
219
220             NETWORK_1xRTT -> {
221                 // Set the icon.
222                 dialogBuilder.setIcon(R.drawable.protocols)
223
224                 // Set the title.
225                 dialogBuilder.setTitle(R.string.rtt)
226             }
227
228             NETWORK_HSDPA -> {
229                 // Set the icon.
230                 dialogBuilder.setIcon(R.drawable.protocols)
231
232                 // Set the title.
233                 dialogBuilder.setTitle(R.string.hsdpa)
234             }
235
236             NETWORK_HSUPA -> {
237                 // Set the icon.
238                 dialogBuilder.setIcon(R.drawable.protocols)
239
240                 // Set the title.
241                 dialogBuilder.setTitle(R.string.hsupa)
242             }
243
244             NETWORK_HSPA -> {
245                 // Set the icon.
246                 dialogBuilder.setIcon(R.drawable.protocols)
247
248                 // Set the title.
249                 dialogBuilder.setTitle(R.string.hspa)
250             }
251
252             NETWORK_IDEN -> {
253                 // Set the icon.
254                 dialogBuilder.setIcon(R.drawable.protocols)
255
256                 // Set the title.
257                 dialogBuilder.setTitle(R.string.iden)
258             }
259
260             NETWORK_EVDO_B -> {
261                 // Set the icon.
262                 dialogBuilder.setIcon(R.drawable.protocols)
263
264                 // Set the title.
265                 dialogBuilder.setTitle(R.string.evdo_b)
266             }
267
268             NETWORK_LTE -> {
269                 // Set the icon.
270                 dialogBuilder.setIcon(R.drawable.protocols)
271
272                 // Set the title.
273                 dialogBuilder.setTitle(R.string.lte)
274             }
275
276             NETWORK_EHRPD -> {
277                 // Set the icon.
278                 dialogBuilder.setIcon(R.drawable.protocols)
279
280                 // Set the title.
281                 dialogBuilder.setTitle(R.string.ehrpd)
282             }
283
284             NETWORK_HSPAP -> {
285                 // Set the icon.
286                 dialogBuilder.setIcon(R.drawable.protocols)
287
288                 // Set the title.
289                 dialogBuilder.setTitle(R.string.hspap)
290             }
291
292             NETWORK_GSM -> {
293                 // Set the icon.
294                 dialogBuilder.setIcon(R.drawable.protocols)
295
296                 // Set the title.
297                 dialogBuilder.setTitle(R.string.gsm)
298             }
299
300             NETWORK_TD_SCDMA -> {
301                 // Set the icon.
302                 dialogBuilder.setIcon(R.drawable.protocols)
303
304                 // Set the title.
305                 dialogBuilder.setTitle(R.string.td_scdma)
306             }
307
308             NETWORK_IWLAN -> {
309                 // Set the icon.
310                 dialogBuilder.setIcon(R.drawable.protocols)
311
312                 // Set the title.
313                 dialogBuilder.setTitle(R.string.iwlan)
314             }
315
316             NETWORK_NR -> {
317                 // Set the icon.
318                 dialogBuilder.setIcon(R.drawable.protocols)
319
320                 // Set the title.
321                 dialogBuilder.setTitle(R.string.nr)
322             }
323
324             OVERRIDE_NETWORK_NONE -> {
325                 // Set the icon.
326                 dialogBuilder.setIcon(R.drawable.protocols)
327
328                 // Set the title.
329                 dialogBuilder.setTitle(R.string.none)
330             }
331
332             OVERRIDE_NETWORK_LTE_CA -> {
333                 // Set the icon.
334                 dialogBuilder.setIcon(R.drawable.protocols)
335
336                 // Set the title.
337                 dialogBuilder.setTitle(R.string.lte_ca)
338             }
339
340             OVERRIDE_NETWORK_LTE_ADVANCED_PRO -> {
341                 // Set the icon.
342                 dialogBuilder.setIcon(R.drawable.protocols)
343
344                 // Set the title.
345                 dialogBuilder.setTitle(R.string.lte_advanced_pro)
346             }
347
348             OVERRIDE_NETWORK_NR_NSA -> {
349                 // Set the icon.
350                 dialogBuilder.setIcon(R.drawable.protocols)
351
352                 // Set the title.
353                 dialogBuilder.setTitle(R.string.nr_nsa)
354             }
355
356             OVERRIDE_NETWORK_NR_NSA_MMWAVE -> {
357                 // Set the icon.
358                 dialogBuilder.setIcon(R.drawable.protocols)
359
360                 // Set the title.
361                 dialogBuilder.setTitle(R.string.nr_nsa_mmwave)
362             }
363
364             OVERRIDE_NETWORK_NR_ADVANCED -> {
365                 // Set the icon.
366                 dialogBuilder.setIcon(R.drawable.protocols)
367
368                 // Set the title.
369                 dialogBuilder.setTitle(R.string.nr_advanced)
370             }
371         }
372
373         // Set the view.
374         dialogBuilder.setView(R.layout.webview_dialog)
375
376         // Set a listener on the close button.  Using `null` as the listener closes the dialog without doing anything else.
377         dialogBuilder.setNegativeButton(R.string.close, null)
378
379         // Create an alert dialog from the builder.
380         val alertDialog = dialogBuilder.create()
381
382         // The alert dialog needs to be shown before the contents can be modified.
383         alertDialog.show()
384
385         // Get a handle for the WebView.
386         webView = alertDialog.findViewById(R.id.webview)!!
387
388         // Create a WebView asset loader.
389         val webViewAssetLoader = WebViewAssetLoader.Builder().addPathHandler("/assets/", WebViewAssetLoader.AssetsPathHandler(requireContext())).build()
390
391         // Set a WebView client.
392         webView.webViewClient = object : WebViewClient() {
393             // Send external links to a web browser.
394             override fun shouldOverrideUrlLoading(view: WebView, webResourceRequest: WebResourceRequest): Boolean {
395                 // Create an intent to view the URL.
396                 val urlIntent = Intent(Intent.ACTION_VIEW)
397
398                 // Add the URL to the intent.
399                 urlIntent.data = webResourceRequest.url
400
401                 // Make it so.
402                 startActivity(urlIntent)
403
404                 // Consume the click.
405                 return true
406             }
407
408             // Process asset requests with the asset loader.
409             override fun shouldInterceptRequest(webView: WebView, webResourceRequest: WebResourceRequest): WebResourceResponse? {
410                 // This allows using the `appassets.androidplatform.net` URL, which handles the loading of SVG files, which otherwise is prevented by the CORS policy.
411                 return webViewAssetLoader.shouldInterceptRequest(webResourceRequest.url)
412             }
413         }
414
415         // Load the WebView data according to the dialog type.
416         when (dialogType) {
417             PERMISSIONS -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/permissions.html")
418             PRIVACY_POLICY -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/privacy_policy.html")
419             CHANGELOG -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/changelog.html")
420             LICENSES -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/licenses.html")
421             CONTRIBUTORS -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/contributors.html")
422             STINGRAY -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/stingrays.html")
423             ANTIQUATED_NETWORK -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/antiquated_network.html")
424             NETWORK_UNKNOWN -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/network_unknown.html")
425             NETWORK_GPRS -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/network_gprs.html")
426             NETWORK_EDGE -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/network_edge.html")
427             NETWORK_UMTS -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/network_umts.html")
428             NETWORK_CDMA -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/network_cdma.html")
429             NETWORK_EVDO_0 -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/network_evdo_0.html")
430             NETWORK_EVDO_A -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/network_evdo_a.html")
431             NETWORK_1xRTT -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/network_1xrtt.html")
432             NETWORK_HSDPA -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/network_hsdpa.html")
433             NETWORK_HSUPA -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/network_hsupa.html")
434             NETWORK_HSPA -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/network_hspa.html")
435             NETWORK_IDEN -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/network_iden.html")
436             NETWORK_EVDO_B -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/network_evdo_b.html")
437             NETWORK_LTE -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/network_lte.html")
438             NETWORK_EHRPD -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/network_ehrpd.html")
439             NETWORK_HSPAP -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/network_hspap.html")
440             NETWORK_GSM -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/network_gsm.html")
441             NETWORK_TD_SCDMA -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/network_td_scdma.html")
442             NETWORK_IWLAN -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/network_iwlan.html")
443             NETWORK_NR -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/network_nr.html")
444             OVERRIDE_NETWORK_NONE -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/override_network_none.html")
445             OVERRIDE_NETWORK_LTE_CA -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/override_network_lte_ca.html")
446             OVERRIDE_NETWORK_LTE_ADVANCED_PRO -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) +
447                     "/explanations/override_network_lte_advanced_pro.html")
448             OVERRIDE_NETWORK_NR_NSA -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/override_network_nr_nsa.html")
449             // The item below can be removed once the minimum API >= 31.
450             OVERRIDE_NETWORK_NR_NSA_MMWAVE -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/override_network_nr_nsa_mmwave.html")
451             OVERRIDE_NETWORK_NR_ADVANCED -> webView.loadUrl("https://appassets.androidplatform.net/assets/" + getString(R.string.asset_directory) + "/explanations/override_network_nr_advanced.html")
452         }
453
454         // Scroll the WebView if the saved instance state is not null.
455         if (savedInstanceState != null) {
456             webView.post {
457                 webView.scrollY = savedInstanceState.getInt(SCROLL_Y)
458             }
459         }
460
461         // Return the alert dialog.
462         return alertDialog
463     }
464
465     override fun onSaveInstanceState(savedInstanceState: Bundle) {
466         // Run the default commands.
467         super.onSaveInstanceState(savedInstanceState)
468
469         // Save the scroll position.
470         savedInstanceState.putInt(SCROLL_Y, webView.scrollY)
471     }
472 }