ce6fdb88ebb998db6a8f6cd30c59a328e6a802b6
[PrivacyBrowser.git] / app / src / main / java / com / stoutner / privacybrowser / Webview.java
1 package com.stoutner.privacybrowser;
2
3 import android.app.Activity;
4 import android.content.Intent;
5 import android.net.Uri;
6 import android.os.Bundle;
7 import android.support.v4.widget.SwipeRefreshLayout;
8 import android.support.v7.app.AppCompatActivity;
9 import android.util.Patterns;
10 import android.view.KeyEvent;
11 import android.view.Menu;
12 import android.view.MenuItem;
13 import android.view.View;
14 import android.view.ViewTreeObserver;
15 import android.view.inputmethod.InputMethodManager;
16 import android.webkit.WebChromeClient;
17 import android.webkit.WebView;
18 import android.webkit.WebViewClient;
19 import android.widget.EditText;
20 import android.widget.ProgressBar;
21 import java.io.UnsupportedEncodingException;
22 import java.net.MalformedURLException;
23 import java.net.URL;
24 import java.net.URLEncoder;
25
26 public class Webview extends AppCompatActivity {
27
28     static String formattedUrlString;
29     static WebView mainWebView;
30     static ProgressBar progressBar;
31     static SwipeRefreshLayout swipeToRefresh;
32     static EditText urlTextBox;
33     static final String homepage = "https://www.duckduckgo.com";
34
35     @Override
36     protected void onCreate(Bundle savedInstanceState) {
37         super.onCreate(savedInstanceState);
38         setContentView(R.layout.activity_webview);
39
40         urlTextBox = (EditText) findViewById(R.id.urlTextBox);
41         swipeToRefresh = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayoutContainer);
42         mainWebView = (WebView) findViewById(R.id.mainWebView);
43         progressBar = (ProgressBar) findViewById(R.id.progressBar);
44
45         // Implement swipe down to refresh.
46         swipeToRefresh.setColorSchemeColors(0xFF0097FF);
47         swipeToRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
48             @Override
49             public void onRefresh() {
50                 mainWebView.loadUrl(formattedUrlString);
51             }
52         });
53
54         // Only enable swipeToRefresh if is mainWebView is scrolled to the top.
55         mainWebView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
56             @Override
57             public void onScrollChanged() {
58                 if (mainWebView.getScrollY() == 0) {
59                     swipeToRefresh.setEnabled(true);
60                 } else {
61                     swipeToRefresh.setEnabled(false);
62                 }
63             }
64         });
65
66         // setWebViewClient makes this WebView the default handler for URLs inside the app, so that links are not kicked out to other apps.
67         // Save the URL to formattedUrlString and update urlTextBox before loading mainWebView.
68         mainWebView.setWebViewClient(new WebViewClient() {
69             public boolean shouldOverrideUrlLoading(WebView view, String url) {
70                 formattedUrlString = url;
71                 urlTextBox.setText(formattedUrlString);
72                 mainWebView.loadUrl(formattedUrlString);
73                 return true;
74             }
75         });
76
77         // Update the progress bar when a page is loading.
78         mainWebView.setWebChromeClient(new WebChromeClient() {
79             public void onProgressChanged(WebView view, int progress) {
80                 progressBar.setProgress(progress);
81                 if (progress < 100) {
82                     progressBar.setVisibility(View.VISIBLE);
83                 } else {
84                     progressBar.setVisibility(View.GONE);
85
86                     // Stop the refreshing indicator if it is running.
87                     swipeToRefresh.setRefreshing(false);
88
89                     // Update the URL in urlTextBox.  It is necessary to do this after the page finishes loading to get the final URL, which can change during load.
90                     formattedUrlString = mainWebView.getUrl();
91                     urlTextBox.setText(formattedUrlString);
92                 }
93             }
94         });
95
96         // Allow pinch to zoom.
97         mainWebView.getSettings().setBuiltInZoomControls(true);
98
99         // Hide zoom controls.
100         mainWebView.getSettings().setDisplayZoomControls(false);
101
102         // Enable JavaScript.
103         mainWebView.getSettings().setJavaScriptEnabled(true);
104
105         // Enable DOM Storage.
106         mainWebView.getSettings().setDomStorageEnabled(true);
107
108         // Get the intent information that started the app.
109         final Intent intent = getIntent();
110
111         if (intent.getData() != null) {
112             // Get the intent data and convert it to a string.
113             final Uri intentUriData = intent.getData();
114             Webview.formattedUrlString = intentUriData.toString();
115         }
116
117         // If formattedUrlString is null assign the homepage to it.
118         if (formattedUrlString == null) {
119             formattedUrlString = homepage;
120         }
121
122         // Place the formattedUrlString in the address bar and load the website.
123         urlTextBox.setText(formattedUrlString);
124         mainWebView.loadUrl(formattedUrlString);
125
126         // Set the "go" button on the keyboard to load the URL.
127         urlTextBox.setOnKeyListener(new View.OnKeyListener() {
128             public boolean onKey(View v, int keyCode, KeyEvent event) {
129                 // If the event is a key-down event on the "enter" button
130                 if ((event.getAction() == KeyEvent.ACTION_DOWN) &&
131                         (keyCode == KeyEvent.KEYCODE_ENTER)) {
132                     // Load the URL into the mainWebView and consume the event.
133                     try {
134                         loadUrlFromTextBox(mainWebView);
135                     } catch (UnsupportedEncodingException e) {
136                         e.printStackTrace();
137                     }
138                     return true;
139                 }
140                 // Do not consume the event.
141                 return false;
142             }
143         });
144
145     }
146
147     @Override
148     public boolean onCreateOptionsMenu(Menu menu) {
149         // Inflate the menu; this adds items to the action bar if it is present.
150         getMenuInflater().inflate(R.menu.menu_webview, menu);
151         return true;
152     }
153
154     @Override
155     public boolean onOptionsItemSelected(MenuItem menuItem) {
156         int menuItemId = menuItem.getItemId();
157         final WebView mainWebView = (WebView) findViewById(R.id.mainWebView);
158
159         // Sets the commands that relate to the menu entries.
160         switch (menuItemId) {
161             case R.id.home:
162                 formattedUrlString = homepage;
163                 urlTextBox.setText(formattedUrlString);
164                 mainWebView.loadUrl(formattedUrlString);
165                 break;
166             case R.id.back:
167                 mainWebView.goBack();
168
169                 // Update the URL in urlTextBox with the URL we are intending to load.  Because this can be altered during load, the final URL is loaded after the progress bar reaches 100%
170                 formattedUrlString = mainWebView.getOriginalUrl();
171                 urlTextBox.setText(formattedUrlString);
172                 break;
173             case R.id.forward:
174                 mainWebView.goForward();
175
176                 // Update the URL in urlTextBox with the URL we are intending to load.  Because this can be altered during load, the final URL is loaded after the progress bar reaches 100%
177                 formattedUrlString = mainWebView.getOriginalUrl();
178                 urlTextBox.setText(formattedUrlString);
179                 break;
180         }
181
182         return super.onOptionsItemSelected(menuItem);
183     }
184
185     // Override onBackPressed so that if mainWebView can go back it does when the system back button is pressed.
186     @Override
187     public void onBackPressed() {
188         if (mainWebView.canGoBack()) {
189             mainWebView.goBack();
190
191             // Update the URL in urlTextBox with the URL we are intending to load.  Because this can be altered during load, the final URL is loaded after the progress bar reaches 100%
192             formattedUrlString = mainWebView.getOriginalUrl();
193             urlTextBox.setText(formattedUrlString);
194         } else {
195             super.onBackPressed();
196         }
197     }
198
199     public void loadUrlFromTextBox(View view) throws UnsupportedEncodingException {
200         // Get the text from urlTextInput and convert it to a string.
201         final EditText urlTextBox = (EditText) findViewById(R.id.urlTextBox);
202         final WebView mainWebView = (WebView) findViewById(R.id.mainWebView);
203         String unformattedUrlString = urlTextBox.getText().toString();
204         URL unformattedUrl = null;
205         Uri.Builder formattedUri = new Uri.Builder();
206         String scheme;
207
208         // Check to see if unformattedUrlString is a valid URL.  Otherwise, convert it into a Duck Duck Go search.
209         if (Patterns.WEB_URL.matcher(unformattedUrlString).matches()) {
210
211             // Add http:// at the beginning if it is missing.  Otherwise the app will segfault.
212             if (!unformattedUrlString.startsWith("http")) {
213                 unformattedUrlString = "http://" + unformattedUrlString;
214             }
215
216             // Convert unformattedUrlString to a URL, then to a URI, and then back to a string, which sanitizes the input and adds in any missing components.
217             try {
218                 unformattedUrl = new URL(unformattedUrlString);
219             } catch (MalformedURLException e) {
220                 e.printStackTrace();
221             }
222
223             if (unformattedUrl.getProtocol() != null) {
224                 scheme = unformattedUrl.getProtocol();
225             } else {
226                 scheme = "http";
227             }
228
229             final String authority = unformattedUrl.getAuthority();
230             final String path = unformattedUrl.getPath();
231             final String query = unformattedUrl.getQuery();
232             final String fragment = unformattedUrl.getRef();
233
234             formattedUri.scheme(scheme).authority(authority).path(path).query(query).fragment(fragment);
235             formattedUrlString = formattedUri.build().toString();
236
237         } else {
238             // Sanitize the search input.
239             final String encodedUrlString = URLEncoder.encode(unformattedUrlString, "UTF-8");
240             formattedUrlString = "https://duckduckgo.com/?q=" + encodedUrlString;
241         }
242
243         // Place formattedUrlString back in the address bar and load the website.
244         urlTextBox.setText(formattedUrlString);
245         mainWebView.loadUrl(formattedUrlString);
246
247         // Hides the keyboard so we can see the webpage.
248         InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
249         inputMethodManager.hideSoftInputFromWindow(mainWebView.getWindowToken(), 0);
250     }
251 }