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