c6c465f061fd7b17dceb8e63820a394de6803688
[PrivacyBrowser.git] / app / src / main / java / com / stoutner / privacybrowser / fragments / DomainSettingsFragment.java
1 /*
2  * Copyright © 2017 Soren Stoutner <soren@stoutner.com>.
3  *
4  * Huawei spinner code fix contributed 2017 Thomas Jensen <lianergoist@vongriffen.dk>.  Copyright assigned to Soren Stoutner <soren@stoutner.com>.
5  *
6  * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
7  *
8  * Privacy Browser is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * Privacy Browser is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 package com.stoutner.privacybrowser.fragments;
23
24 import android.annotation.SuppressLint;
25 import android.content.Context;
26 import android.database.Cursor;
27 import android.os.Build;
28 import android.os.Bundle;
29 // We have to use `android.support.v4.app.Fragment` until minimum API >= 23.  Otherwise we cannot call `getContext()`.
30 import android.support.v4.app.Fragment;
31 import android.view.LayoutInflater;
32 import android.view.View;
33 import android.view.ViewGroup;
34 import android.webkit.WebView;
35 import android.widget.AdapterView;
36 import android.widget.ArrayAdapter;
37 import android.widget.CompoundButton;
38 import android.widget.EditText;
39 import android.widget.ImageView;
40 import android.widget.LinearLayout;
41 import android.widget.Spinner;
42 import android.widget.Switch;
43 import android.widget.TextView;
44
45 import com.stoutner.privacybrowser.R;
46 import com.stoutner.privacybrowser.activities.MainWebViewActivity;
47 import com.stoutner.privacybrowser.helpers.DomainsDatabaseHelper;
48
49 public class DomainSettingsFragment extends Fragment {
50     // `DATABASE_ID` is used by activities calling this fragment.
51     public static final String DATABASE_ID = "database_id";
52
53     // `databaseId` is used in `onCreate()` and `onCreateView()`.
54     private int databaseId;
55
56     @Override
57     public void onCreate(Bundle savedInstanceState) {
58         super.onCreate(savedInstanceState);
59
60         // Store the database id in `databaseId`.
61         databaseId = getArguments().getInt(DATABASE_ID);
62     }
63
64     // We have to use the deprecated `getDrawable()` until the minimum API >= 21.
65     @SuppressWarnings("deprecation")
66     @Override
67     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
68         // Inflate `domain_settings`.  `false` does not attach it to the root `container`.
69         View domainSettingsView = inflater.inflate(R.layout.domain_settings, container, false);
70
71         // Get a handle for the `Context`.
72         Context context = getContext();
73
74         // Get handles for the views in the fragment.
75         EditText domainNameEditText = (EditText) domainSettingsView.findViewById(R.id.domain_settings_name_edittext);
76         Switch javaScriptEnabledSwitch = (Switch) domainSettingsView.findViewById(R.id.domain_settings_javascript_switch);
77         final ImageView javaScriptImageView = (ImageView) domainSettingsView.findViewById(R.id.domain_settings_javascript_imageview);
78         Switch firstPartyCookiesEnabledSwitch = (Switch) domainSettingsView.findViewById(R.id.domain_settings_first_party_cookies_switch);
79         final ImageView firstPartyCookiesImageView = (ImageView) domainSettingsView.findViewById(R.id.domain_settings_first_party_cookies_imageview);
80         LinearLayout thirdPartyCookiesLinearLayout = (LinearLayout) domainSettingsView.findViewById(R.id.domain_settings_third_party_cookies_linearlayout);
81         final Switch thirdPartyCookiesEnabledSwitch = (Switch) domainSettingsView.findViewById(R.id.domain_settings_third_party_cookies_switch);
82         final ImageView thirdPartyCookiesImageView = (ImageView) domainSettingsView.findViewById(R.id.domain_settings_third_party_cookies_imageview);
83         final Switch domStorageEnabledSwitch = (Switch) domainSettingsView.findViewById(R.id.domain_settings_dom_storage_switch);
84         final ImageView domStorageImageView = (ImageView) domainSettingsView.findViewById(R.id.domain_settings_dom_storage_imageview);
85         Switch formDataEnabledSwitch = (Switch) domainSettingsView.findViewById(R.id.domain_settings_form_data_switch);
86         final ImageView formDataImageView = (ImageView) domainSettingsView.findViewById(R.id.domain_settings_form_data_imageview);
87         Spinner userAgentSpinner = (Spinner) domainSettingsView.findViewById(R.id.domain_settings_user_agent_spinner);
88         final TextView userAgentTextView = (TextView) domainSettingsView.findViewById(R.id.domain_settings_user_agent_textview);
89         final EditText customUserAgentEditText = (EditText) domainSettingsView.findViewById(R.id.domain_settings_custom_user_agent_edittext);
90         Spinner fontSizeSpinner = (Spinner) domainSettingsView.findViewById(R.id.domain_settings_font_size_spinner);
91         final ImageView displayWebpageImagesImageView = (ImageView) domainSettingsView.findViewById(R.id.domain_settings_display_webpage_images_imageview);
92         Spinner displayWebpageImagesSpinner = (Spinner) domainSettingsView.findViewById(R.id.domain_settings_display_webpage_images_spinner);
93
94         // Initialize the database handler.  `this` specifies the context.  The two `nulls` do not specify the database name or a `CursorFactory`.
95         // The `0` specifies the database version, but that is ignored and set instead using a constant in `DomainsDatabaseHelper`.
96         DomainsDatabaseHelper domainsDatabaseHelper = new DomainsDatabaseHelper(getContext(), null, null, 0);
97
98         // Get the database `Cursor` for this ID and move it to the first row.
99         Cursor domainCursor = domainsDatabaseHelper.getCursorForId(databaseId);
100         domainCursor.moveToFirst();
101
102         // Save the `Cursor` entries as variables.
103         String domainNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.DOMAIN_NAME));
104         int javaScriptEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_JAVASCRIPT));
105         int firstPartyCookiesEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FIRST_PARTY_COOKIES));
106         int thirdPartyCookiesEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_THIRD_PARTY_COOKIES));
107         int domStorageEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE));
108         int formDataEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA));
109         final String currentUserAgentString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT));
110         int fontSizeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE));
111         int displayImagesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES));
112
113         // Create `ArrayAdapters` for the `Spinners`and their `entry values`.
114         ArrayAdapter<CharSequence> userAgentArrayAdapter = ArrayAdapter.createFromResource(context, R.array.user_agent_entries, android.R.layout.simple_spinner_item);
115         final ArrayAdapter<CharSequence> userAgentEntryValuesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.user_agent_entry_values, android.R.layout.simple_spinner_item);
116         ArrayAdapter<CharSequence> fontSizeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.default_font_size_entries, android.R.layout.simple_spinner_item);
117         ArrayAdapter<CharSequence> fontSizeEntryValuesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.default_font_size_entry_values, android.R.layout.simple_spinner_item);
118         final ArrayAdapter<CharSequence> displayImagesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.display_website_images_array, android.R.layout.simple_spinner_item);
119
120         // Set the drop down style for the `ArrayAdapters`.
121         fontSizeArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
122         displayImagesArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
123
124         // Some phones running Huawei's customized Android 7.0 don't display a spinner that requires scrolling correctly with the default `simple_spinner_dropdown_item`.  The Huawei P9 Lite is known to be affected.
125         if (Build.BRAND.equals("HUAWEI") && (Build.VERSION.SDK_INT == 24)) {  // The device is manufactured by Huawei and is running Android 7.0.
126             // Use a customized `simple_spinner_dropdown_item`.  Huawei spinner code fix contributed 2017 Thomas Jensen <lianergoist@vongriffen.dk>.  Copyright assigned to Soren Stoutner <soren@stoutner.com>.
127             userAgentArrayAdapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item_huawei_fix);
128         } else {  // Use the standard `android.R.layout.simple_spinner_dropdown_item` on all other devices.
129             userAgentArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
130         }
131
132         // Set the `ArrayAdapters` for the `Spinners`.
133         userAgentSpinner.setAdapter(userAgentArrayAdapter);
134         fontSizeSpinner.setAdapter(fontSizeArrayAdapter);
135         displayWebpageImagesSpinner.setAdapter(displayImagesArrayAdapter);
136
137         // Set the domain name from the the database cursor.
138         domainNameEditText.setText(domainNameString);
139
140         // Set the JavaScript status.
141         if (javaScriptEnabledInt == 1) {  // JavaScript is enabled.
142             javaScriptEnabledSwitch.setChecked(true);
143             javaScriptImageView.setImageDrawable(getResources().getDrawable(R.drawable.javascript_enabled));
144         } else {  // JavaScript is disabled.
145             javaScriptEnabledSwitch.setChecked(false);
146             javaScriptImageView.setImageDrawable(getResources().getDrawable(R.drawable.privacy_mode));
147         }
148
149         // Set the first-party cookies status.  Once minimum API >= 21 we can use a selector as the tint mode instead of specifying different icons.
150         if (firstPartyCookiesEnabledInt == 1) {  // First-party cookies are enabled.
151             firstPartyCookiesEnabledSwitch.setChecked(true);
152             firstPartyCookiesImageView.setImageDrawable(getResources().getDrawable(R.drawable.cookies_enabled));
153         } else {  // First-party cookies are disabled.
154             firstPartyCookiesEnabledSwitch.setChecked(false);
155             firstPartyCookiesImageView.setImageDrawable(getResources().getDrawable(R.drawable.cookies_disabled));
156         }
157
158         // Only display third-party cookies if SDK_INT >= 21.
159         if (Build.VERSION.SDK_INT >= 21) {  // Third-party cookies can be configured for API >= 21.
160             // Only enable third-party-cookies if first-party cookies are enabled.
161             if (firstPartyCookiesEnabledInt == 1) {  // First-party cookies are enabled.
162                 // Set the third-party cookies status.  Once minimum API >= 21 we can use a selector as the tint mode instead of specifying different icons.
163                 if (thirdPartyCookiesEnabledInt == 1) {  // Both first-party and third-party cookies are enabled.
164                     thirdPartyCookiesEnabledSwitch.setChecked(true);
165                     thirdPartyCookiesImageView.setImageDrawable(getResources().getDrawable(R.drawable.cookies_warning));
166                 } else {  // First party cookies are enabled but third-party cookies are disabled.
167                     thirdPartyCookiesEnabledSwitch.setChecked(false);
168                     thirdPartyCookiesImageView.setImageDrawable(getResources().getDrawable(R.drawable.cookies_disabled));
169                 }
170             } else {  // First-party cookies are disabled.
171                 // Set the status of third-party cookies, but disable it.
172                 if (thirdPartyCookiesEnabledInt == 1) {  // Third-party cookies are enabled but first-party cookies are disabled.
173                     thirdPartyCookiesEnabledSwitch.setChecked(true);
174                     thirdPartyCookiesEnabledSwitch.setEnabled(false);
175                     thirdPartyCookiesImageView.setImageDrawable(getResources().getDrawable(R.drawable.cookies_ghosted));
176                 } else {  // Both first party and third-party cookies are disabled.
177                     thirdPartyCookiesEnabledSwitch.setChecked(false);
178                     thirdPartyCookiesEnabledSwitch.setEnabled(false);
179                     thirdPartyCookiesImageView.setImageDrawable(getResources().getDrawable(R.drawable.cookies_ghosted));
180                 }
181             }
182         } else {  // Third-party cookies cannot be configured for API <= 21.
183             // Hide the `LinearLayout` for third-party cookies.
184             thirdPartyCookiesLinearLayout.setVisibility(View.GONE);
185         }
186
187         // Only enable DOM storage if JavaScript is enabled.
188         if (javaScriptEnabledInt == 1) {  // JavaScript is enabled.
189             // Set the DOM storage status.  Once minimum API >= 21 we can use a selector as the tint mode instead of specifying different icons.
190             if (domStorageEnabledInt == 1) {  // Both JavaScript and DOM storage are enabled.
191                 domStorageEnabledSwitch.setChecked(true);
192                 domStorageImageView.setImageDrawable(getResources().getDrawable(R.drawable.dom_storage_enabled));
193             } else {  // JavaScript is enabled but DOM storage is disabled.
194                 domStorageEnabledSwitch.setChecked(false);
195                 domStorageImageView.setImageDrawable(getResources().getDrawable(R.drawable.dom_storage_disabled));
196             }
197         } else {  // JavaScript is disabled.
198             // Set the checked status of DOM storage.
199             if (domStorageEnabledInt == 1) {  // DOM storage is enabled but JavaScript is disabled.
200                 domStorageEnabledSwitch.setChecked(true);
201             } else {  // Both JavaScript and DOM storage are disabled.
202                 domStorageEnabledSwitch.setChecked(false);
203             }
204
205             // Disable `domStorageEnabledSwitch` and set the icon to be ghosted.
206             domStorageEnabledSwitch.setEnabled(false);
207             domStorageImageView.setImageDrawable(getResources().getDrawable(R.drawable.dom_storage_ghosted));
208         }
209
210         // Set the form data status.  Once minimum API >= 21 we can use a selector as the tint mode instead of specifying different icons.
211         if (formDataEnabledInt == 1) {  // Form data is enabled.
212             formDataEnabledSwitch.setChecked(true);
213             formDataImageView.setImageDrawable(getResources().getDrawable(R.drawable.form_data_enabled));
214         } else {  // Form data is disabled.
215             formDataEnabledSwitch.setChecked(false);
216             formDataImageView.setImageDrawable(getResources().getDrawable(R.drawable.form_data_disabled));
217         }
218
219         // We need to inflated a `WebView` to get the default user agent.
220         // `@SuppressLint("InflateParams")` removes the warning about using `null` as the `ViewGroup`, which in this case makes sense because we don't want to display `bare_webview` on the screen.  `false` does not attach the view to the root.
221         @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
222         WebView bareWebView = (WebView) bareWebViewLayout.findViewById(R.id.bare_webview);
223         final String webViewDefaultUserAgentString = bareWebView.getSettings().getUserAgentString();
224
225         // Get the position of the user agent in `userAgentEntryValuesArrayAdapter`.
226         int userAgentArrayPosition = userAgentEntryValuesArrayAdapter.getPosition(currentUserAgentString);
227
228         // Set the user agent.
229         if (userAgentArrayPosition == -1) {  // We are using a custom `userAgentString`.
230             // Set `userAgentSpinner` to `Custom`.
231             userAgentSpinner.setSelection(userAgentEntryValuesArrayAdapter.getPosition("Custom user agent"));
232
233             // Hide `userAgentTextView`.
234             userAgentTextView.setVisibility(View.GONE);
235
236             // Show `customUserAgentEditText` and set `userAgentString` as the text.
237             customUserAgentEditText.setVisibility(View.VISIBLE);
238             customUserAgentEditText.setText(currentUserAgentString);
239         } else if (currentUserAgentString.equals("WebView default user agent")) {  // We are using the `WebView` default user agent.
240             // Set the `userAgentSpinner` selection.
241             userAgentSpinner.setSelection(userAgentArrayPosition);
242
243             // Show `userAgentTextView` and set the text.
244             userAgentTextView.setVisibility(View.VISIBLE);
245             userAgentTextView.setText(webViewDefaultUserAgentString);
246
247             // Hide `customUserAgentEditText`.
248             customUserAgentEditText.setVisibility(View.GONE);
249         } else {  // We are using a standard user agent.
250             // Set the `userAgentSpinner` selection.
251             userAgentSpinner.setSelection(userAgentArrayPosition);
252
253             // Show `userAgentTextView` and set the text.
254             userAgentTextView.setVisibility(View.VISIBLE);
255             userAgentTextView.setText(currentUserAgentString);
256
257             // Hide `customUserAgentEditText`.
258             customUserAgentEditText.setVisibility(View.GONE);
259         }
260
261         // Set the selected font size.
262         int fontSizeArrayPosition = fontSizeEntryValuesArrayAdapter.getPosition(String.valueOf(fontSizeInt));
263         fontSizeSpinner.setSelection(fontSizeArrayPosition);
264
265         // Set the selected display website images mode.
266         displayWebpageImagesSpinner.setSelection(displayImagesInt);
267
268         // Set the display website images icon.
269         switch (displayImagesInt) {
270             case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_SYSTEM_DEFAULT:
271                 if (MainWebViewActivity.displayWebpageImagesBoolean) {
272                     displayWebpageImagesImageView.setImageDrawable(getResources().getDrawable(R.drawable.images_enabled));
273                 } else {
274                     displayWebpageImagesImageView.setImageDrawable(getResources().getDrawable(R.drawable.images_disabled));
275                 }
276                 break;
277
278             case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED:
279                 displayWebpageImagesImageView.setImageDrawable(getResources().getDrawable(R.drawable.images_enabled));
280                 break;
281
282             case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED:
283                 displayWebpageImagesImageView.setImageDrawable(getResources().getDrawable(R.drawable.images_disabled));
284                 break;
285         }
286
287
288         // Set the `javaScriptEnabledSwitch` `OnCheckedChangeListener()`.
289         javaScriptEnabledSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
290             @Override
291             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
292                 if (isChecked) {  // JavaScript is enabled.
293                     // Update the JavaScript icon.
294                     javaScriptImageView.setImageDrawable(getResources().getDrawable(R.drawable.javascript_enabled));
295
296                     // Enable the DOM storage `Switch`.
297                     domStorageEnabledSwitch.setEnabled(true);
298
299                     // Update the DOM storage icon.
300                     if (domStorageEnabledSwitch.isChecked()) {  // DOM storage is enabled.
301                         domStorageImageView.setImageDrawable(getResources().getDrawable(R.drawable.dom_storage_enabled));
302                     } else {  // DOM storage is disabled.
303                         domStorageImageView.setImageDrawable(getResources().getDrawable(R.drawable.dom_storage_disabled));
304                     }
305                 } else {  // JavaScript is disabled.
306                     // Update the JavaScript icon.
307                     javaScriptImageView.setImageDrawable(getResources().getDrawable(R.drawable.privacy_mode));
308
309                     // Disable the DOM storage `Switch`.
310                     domStorageEnabledSwitch.setEnabled(false);
311
312                     // Set the DOM storage icon to be ghosted.
313                     domStorageImageView.setImageDrawable(getResources().getDrawable(R.drawable.dom_storage_ghosted));
314                 }
315             }
316         });
317
318         // Set the `firstPartyCookiesEnabledSwitch` `OnCheckedChangeListener()`.
319         firstPartyCookiesEnabledSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
320             @Override
321             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
322                 if (isChecked) {  // First-party cookies are enabled.
323                     // Update the first-party cookies icon.
324                     firstPartyCookiesImageView.setImageDrawable(getResources().getDrawable(R.drawable.cookies_enabled));
325
326                     // Enable the third-party cookies `Switch`.
327                     thirdPartyCookiesEnabledSwitch.setEnabled(true);
328
329                     // Update the third-party cookies icon.
330                     if (thirdPartyCookiesEnabledSwitch.isChecked()) {  // Third-party cookies are enabled.
331                         thirdPartyCookiesImageView.setImageDrawable(getResources().getDrawable(R.drawable.cookies_warning));
332                     } else {  // Third-party cookies are disabled.
333                         thirdPartyCookiesImageView.setImageDrawable(getResources().getDrawable(R.drawable.cookies_disabled));
334                     }
335                 } else {  // First-party cookies are disabled.
336                     // Update the first-party cookies icon.
337                     firstPartyCookiesImageView.setImageDrawable(getResources().getDrawable(R.drawable.cookies_disabled));
338
339                     // Disable the third-party cookies `Switch`.
340                     thirdPartyCookiesEnabledSwitch.setEnabled(false);
341
342                     // Set the third-party cookies icon to be ghosted.
343                     thirdPartyCookiesImageView.setImageDrawable(getResources().getDrawable(R.drawable.cookies_ghosted));
344                 }
345             }
346         });
347
348         // Set the `thirdPartyCookiesEnabledSwitch` `OnCheckedChangeListener()`.
349         thirdPartyCookiesEnabledSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
350             @Override
351             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
352                 // Update the icon.
353                 if (isChecked) {
354                     thirdPartyCookiesImageView.setImageDrawable(getResources().getDrawable(R.drawable.cookies_warning));
355                 } else {
356                     thirdPartyCookiesImageView.setImageDrawable(getResources().getDrawable(R.drawable.cookies_disabled));
357                 }
358             }
359         });
360
361         // Set the `domStorageEnabledSwitch` `OnCheckedChangeListener()`.
362         domStorageEnabledSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
363             @Override
364             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
365                 // Update the icon.
366                 if (isChecked) {
367                     domStorageImageView.setImageDrawable(getResources().getDrawable(R.drawable.dom_storage_enabled));
368                 } else {
369                     domStorageImageView.setImageDrawable(getResources().getDrawable(R.drawable.dom_storage_disabled));
370                 }
371             }
372         });
373
374         // Set the `formDataEnabledSwitch` `OnCheckedChangeListener()`.
375         formDataEnabledSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
376             @Override
377             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
378                 // Update the icon.
379                 if (isChecked) {
380                     formDataImageView.setImageDrawable(getResources().getDrawable(R.drawable.form_data_enabled));
381                 } else {
382                     formDataImageView.setImageDrawable(getResources().getDrawable(R.drawable.form_data_disabled));
383                 }
384             }
385         });
386
387         // Set the `userAgentSpinner` `onItemClickListener()`.
388         userAgentSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
389             @Override
390             public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
391                 // Store the new user agent string.
392                 String newUserAgentString = getResources().getStringArray(R.array.user_agent_entry_values)[position];
393
394                 // Set the new user agent.
395                 switch (newUserAgentString) {
396                     case "Custom user agent":
397                         // Hide `userAgentTextView`.
398                         userAgentTextView.setVisibility(View.GONE);
399
400                         // Show `customUserAgentEditText` and set `userAgentString` as the text.
401                         customUserAgentEditText.setVisibility(View.VISIBLE);
402                         customUserAgentEditText.setText(currentUserAgentString);
403                         break;
404
405                     case "WebView default user agent":
406                         // Show `userAgentTextView` and set the text.
407                         userAgentTextView.setVisibility(View.VISIBLE);
408                         userAgentTextView.setText(webViewDefaultUserAgentString);
409
410                         // Hide `customUserAgentEditText`.
411                         customUserAgentEditText.setVisibility(View.GONE);
412                         break;
413
414                     default:
415                         // Show `userAgentTextView` and set the text.
416                         userAgentTextView.setVisibility(View.VISIBLE);
417                         userAgentTextView.setText(getResources().getStringArray(R.array.user_agent_entry_values)[position]);
418
419                         // Hide `customUserAgentEditText`.
420                         customUserAgentEditText.setVisibility(View.GONE);
421                         break;
422                 }
423             }
424
425             @Override
426             public void onNothingSelected(AdapterView<?> parent) {
427                 // Do nothing.
428             }
429         });
430
431         // Set the `displayImagesSwitch` `onItemClickListener()`.
432         displayWebpageImagesSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
433             @Override
434             public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
435                 // Update the icon.
436                 switch (position) {
437                     case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_SYSTEM_DEFAULT:
438                         if (MainWebViewActivity.displayWebpageImagesBoolean) {
439                             displayWebpageImagesImageView.setImageDrawable(getResources().getDrawable(R.drawable.images_enabled));
440                         } else {
441                             displayWebpageImagesImageView.setImageDrawable(getResources().getDrawable(R.drawable.images_disabled));
442                         }
443                         break;
444
445                     case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_ENABLED:
446                         displayWebpageImagesImageView.setImageDrawable(getResources().getDrawable(R.drawable.images_enabled));
447                         break;
448
449                     case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED:
450                         displayWebpageImagesImageView.setImageDrawable(getResources().getDrawable(R.drawable.images_disabled));
451                         break;
452                 }
453             }
454
455             @Override
456             public void onNothingSelected(AdapterView<?> parent) {
457                 // Do nothing.
458             }
459         });
460
461         return domainSettingsView;
462     }
463 }