2 * Copyright © 2020-2022 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
6 * Privacy Browser Android 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 Android 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 Android. If not, see <http://www.gnu.org/licenses/>.
20 package com.stoutner.privacybrowser.asynctasks;
22 import android.content.Context;
23 import android.os.AsyncTask;
24 import android.webkit.CookieManager;
25 import android.widget.TextView;
27 import androidx.appcompat.app.AlertDialog;
29 import com.stoutner.privacybrowser.R;
30 import com.stoutner.privacybrowser.helpers.ProxyHelper;
32 import java.lang.ref.WeakReference;
33 import java.net.HttpURLConnection;
34 import java.net.Proxy;
36 import java.text.NumberFormat;
38 public class GetUrlSize extends AsyncTask<String, Void, String> {
39 // Define weak references for the calling context and alert dialog.
40 private final WeakReference<Context> contextWeakReference;
41 private final WeakReference<AlertDialog> alertDialogWeakReference;
43 // Define the class variables.
44 private final String userAgent;
45 private final boolean cookiesEnabled;
47 // The public constructor.
48 public GetUrlSize(Context context, AlertDialog alertDialog, String userAgent, boolean cookiesEnabled) {
49 // Populate the week references for the context and alert dialog.
50 contextWeakReference = new WeakReference<>(context);
51 alertDialogWeakReference = new WeakReference<>(alertDialog);
53 // Store the class variables.
54 this.userAgent = userAgent;
55 this.cookiesEnabled = cookiesEnabled;
59 protected String doInBackground(String... urlToSave) {
60 // Get a handle for the context and the fragment.
61 Context context = contextWeakReference.get();
62 AlertDialog alertDialog = alertDialogWeakReference.get();
64 // Abort if the fragment is gone.
65 if (alertDialog == null) {
69 // Initialize the formatted file size string.
70 String formattedFileSize = context.getString(R.string.unknown_size);
72 // Because everything relating to requesting data from a webserver can throw errors, the entire section must catch exceptions.
74 // Get the URL from the calling fragment.
75 URL url = new URL(urlToSave[0]);
77 // Instantiate the proxy helper.
78 ProxyHelper proxyHelper = new ProxyHelper();
80 // Get the current proxy.
81 Proxy proxy = proxyHelper.getCurrentProxy(context);
83 // Open a connection to the URL. No data is actually sent at this point.
84 HttpURLConnection httpUrlConnection = (HttpURLConnection) url.openConnection(proxy);
86 // Add the user agent to the header property.
87 httpUrlConnection.setRequestProperty("User-Agent", userAgent);
89 // Add the cookies if they are enabled.
91 // Get the cookies for the current domain.
92 String cookiesString = CookieManager.getInstance().getCookie(url.toString());
94 // Only add the cookies if they are not null.
95 if (cookiesString != null) {
96 // Add the cookies to the header property.
97 httpUrlConnection.setRequestProperty("Cookie", cookiesString);
101 // The actual network request is in a `try` bracket so that `disconnect()` is run in the `finally` section even if an error is encountered in the main block.
103 // Exit if the task has been cancelled.
105 // Disconnect the HTTP URL connection.
106 httpUrlConnection.disconnect();
108 // Return the formatted file size string.
109 return formattedFileSize;
112 // Get the status code. This initiates a network connection.
113 int responseCode = httpUrlConnection.getResponseCode();
115 // Exit if the task has been cancelled.
117 // Disconnect the HTTP URL connection.
118 httpUrlConnection.disconnect();
120 // Return the formatted file size string.
121 return formattedFileSize;
124 // Check the response code.
125 if (responseCode >= 400) { // The response code is an error message.
126 // Set the formatted file size to indicate a bad URL.
127 formattedFileSize = context.getString(R.string.invalid_url);
128 } else { // The response code is not an error message.
129 // Get the content length header.
130 String contentLengthString = httpUrlConnection.getHeaderField("Content-Length");
132 // Only process the content length string if it isn't null.
133 if (contentLengthString != null) {
134 // Convert the content length string to a long.
135 long fileSize = Long.parseLong(contentLengthString);
137 // Format the file size.
138 formattedFileSize = NumberFormat.getInstance().format(fileSize) + " " + context.getString(R.string.bytes);
142 // Disconnect the HTTP URL connection.
143 httpUrlConnection.disconnect();
145 } catch (Exception exception) {
146 // Set the formatted file size to indicate a bad URL.
147 formattedFileSize = context.getString(R.string.invalid_url);
150 // Return the formatted file size string.
151 return formattedFileSize;
154 // `onPostExecute()` operates on the UI thread.
156 protected void onPostExecute(String fileSize) {
157 // Get a handle for the alert dialog.
158 AlertDialog alertDialog = alertDialogWeakReference.get();
160 // Abort if the alert dialog is gone.
161 if (alertDialog == null) {
165 // Get a handle for the file size text view.
166 TextView fileSizeTextView = alertDialog.findViewById(R.id.file_size_textview);
168 // Remove the incorrect warning below that the file size text view might be null.
169 assert fileSizeTextView != null;
171 // Update the file size.
172 fileSizeTextView.setText(fileSize);