• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.hotspot2.osulogin;
18 
19 import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
20 
21 import android.app.Activity;
22 import android.content.Context;
23 import android.graphics.Bitmap;
24 import android.net.ConnectivityManager;
25 import android.net.Network;
26 import android.net.NetworkCapabilities;
27 import android.net.NetworkRequest;
28 import android.net.wifi.WifiManager;
29 import android.os.Bundle;
30 import android.util.Log;
31 import android.view.KeyEvent;
32 import android.view.View;
33 import android.webkit.WebChromeClient;
34 import android.webkit.WebResourceError;
35 import android.webkit.WebResourceRequest;
36 import android.webkit.WebSettings;
37 import android.webkit.WebView;
38 import android.webkit.WebViewClient;
39 import android.widget.ProgressBar;
40 import android.widget.Toast;
41 
42 import androidx.annotation.Nullable;
43 import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
44 
45 import java.net.MalformedURLException;
46 import java.net.URL;
47 
48 /**
49  * Online Sign Up Login Web View launched during Provision Process of Hotspot 2.0 rel2.
50  */
51 public class OsuLoginActivity extends Activity {
52     private static final String TAG = "OsuLogin";
53     private static final boolean DBG = true;
54 
55     private String mUrl;
56     private String mHostName;
57     private Network mNetwork;
58     private ConnectivityManager mCm;
59     private ConnectivityManager.NetworkCallback mNetworkCallback;
60     private WifiManager mWifiManager;
61     private WebView mWebView;
62     private SwipeRefreshLayout mSwipeRefreshLayout;
63     private ProgressBar mProgressBar;
64     private boolean mForceDisconnect = true;
65     boolean mRedirectResponseReceived = false;
66 
67     @Override
onCreate(@ullable Bundle savedInstanceState)68     protected void onCreate(@Nullable Bundle savedInstanceState) {
69         super.onCreate(savedInstanceState);
70         if (DBG) {
71             Log.d(TAG, "onCreate: Opening OSU Web View");
72         }
73 
74         mWifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
75         if (mWifiManager == null) {
76             Log.e(TAG, "Cannot get wifi service");
77             finishAndRemoveTask();
78             return;
79         }
80 
81         if (getIntent() == null) {
82             Log.e(TAG, "Intent is null");
83             finishAndRemoveTask();
84             return;
85         }
86 
87         mNetwork = getIntent().getParcelableExtra(WifiManager.EXTRA_OSU_NETWORK);
88         if (mNetwork == null) {
89             Log.e(TAG, "Cannot get the network instance for OSU from intent");
90             finishAndRemoveTask();
91             return;
92         }
93 
94         mUrl = getIntent().getStringExtra(WifiManager.EXTRA_URL);
95         if (mUrl == null) {
96             Log.e(TAG, "Cannot get OSU server url from intent");
97             finishAndRemoveTask();
98             return;
99         }
100 
101         mHostName = getHost(mUrl);
102         if (mHostName == null) {
103             Log.e(TAG, "Cannot get host from the url");
104             finishAndRemoveTask();
105             return;
106         }
107 
108         mCm = (ConnectivityManager) getApplicationContext().getSystemService(
109                 Context.CONNECTIVITY_SERVICE);
110         if (mCm == null) {
111             Log.e(TAG, "Cannot get connectivity service");
112             finishAndRemoveTask();
113             return;
114         }
115 
116         if (!mCm.bindProcessToNetwork(mNetwork)) {
117             Log.e(TAG, "Network is no longer valid");
118             finishAndRemoveTask();
119             return;
120         }
121 
122         final NetworkCapabilities networkCapabilities = mCm.getNetworkCapabilities(mNetwork);
123         if (networkCapabilities == null || !networkCapabilities.hasTransport(
124                 NetworkCapabilities.TRANSPORT_WIFI)) {
125             Log.e(TAG, "WiFi is not supported for the Network");
126             finishAndRemoveTask();
127             return;
128         }
129 
130         getActionBar().setDisplayShowHomeEnabled(false);
131         getActionBar().setElevation(0); // remove shadow
132         getActionBar().setTitle(getString(R.string.action_bar_label));
133         getActionBar().setSubtitle("");
134         setContentView(R.layout.osu_web_view);
135 
136         // Exit this app if network disappeared.
137         mNetworkCallback = new ConnectivityManager.NetworkCallback() {
138             @Override
139             public void onLost(Network network) {
140                 if (DBG) {
141                     Log.d(TAG, "Lost for the current Network, close the browser");
142                 }
143                 mForceDisconnect = false; // It is already disconnected.
144                 if (!mRedirectResponseReceived) {
145                     showSignUpFailedToast();
146                 }
147                 if (mNetwork.equals(network)) {
148                     finishAndRemoveTask();
149                 }
150             }
151         };
152 
153         mCm.registerNetworkCallback(
154                 new NetworkRequest.Builder().addTransportType(
155                         NetworkCapabilities.TRANSPORT_WIFI).removeCapability(
156                         NET_CAPABILITY_TRUSTED).build(),
157                 mNetworkCallback);
158 
159         mWebView = findViewById(R.id.webview);
160         mWebView.clearCache(true);
161         WebSettings webSettings = mWebView.getSettings();
162         webSettings.setJavaScriptEnabled(true);
163         webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
164         webSettings.setUseWideViewPort(true);
165         webSettings.setLoadWithOverviewMode(true);
166         webSettings.setSupportZoom(true);
167         webSettings.setBuiltInZoomControls(true);
168         webSettings.setDisplayZoomControls(false);
169         mProgressBar = findViewById(R.id.progress_bar);
170         mWebView.setWebViewClient(new OsuWebViewClient());
171         mWebView.setWebChromeClient(new WebChromeClient() {
172             @Override
173             public void onProgressChanged(WebView view, int newProgress) {
174                 mProgressBar.setProgress(newProgress);
175             }
176         });
177 
178         if (DBG) {
179             Log.d(TAG, "OSU Web View to " + mUrl);
180         }
181 
182         mWebView.loadUrl(mUrl);
183         mSwipeRefreshLayout = findViewById(R.id.swipe_refresh);
184         mSwipeRefreshLayout.setOnRefreshListener(() -> {
185             mWebView.reload();
186             mSwipeRefreshLayout.setRefreshing(true);
187         });
188     }
189 
190     @Override
onKeyDown(int keyCode, KeyEvent event)191     public boolean onKeyDown(int keyCode, KeyEvent event) {
192         // Check if the key event was the Back button.
193         if ((keyCode == KeyEvent.KEYCODE_BACK)) {
194             // If there is a history to move back
195             if (mWebView.canGoBack()) {
196                 mWebView.goBack();
197                 return true;
198             }
199         }
200         return super.onKeyDown(keyCode, event);
201     }
202 
203     @Override
onDestroy()204     protected void onDestroy() {
205         if (mNetworkCallback != null) {
206             mCm.unregisterNetworkCallback(mNetworkCallback);
207             mNetworkCallback = null;
208         }
209         if (mWifiManager != null && mForceDisconnect) {
210             mWifiManager.disconnect();
211             mWifiManager = null;
212         }
213         super.onDestroy();
214     }
215 
getHost(String url)216     private String getHost(String url) {
217         try {
218             return new URL(url).getHost();
219         } catch (MalformedURLException e) {
220             Log.e(TAG, "Invalid URL " + url);
221         }
222         return null;
223     }
224 
getHeaderSubtitle(String urlString)225     private String getHeaderSubtitle(String urlString) {
226         try {
227             URL url = new URL(urlString);
228             return url.getProtocol() + "://" +  url.getHost();
229         } catch (MalformedURLException e) {
230             Log.e(TAG, "Invalid URL " + urlString);
231         }
232         return "";
233     }
234 
showSignUpFailedToast()235     private void showSignUpFailedToast() {
236         Toast.makeText(getApplicationContext(), R.string.sign_up_failed,
237                 Toast.LENGTH_SHORT).show();
238     }
239 
240     private class OsuWebViewClient extends WebViewClient {
241         boolean mPageError = false;
242 
243         @Override
onPageStarted(WebView view, String urlString, Bitmap favicon)244         public void onPageStarted(WebView view, String urlString, Bitmap favicon) {
245             String subtitle = getHeaderSubtitle(urlString);
246             getActionBar().setSubtitle(subtitle);
247             mProgressBar.setVisibility(View.VISIBLE);
248         }
249 
250         @Override
onPageFinished(WebView view, String url)251         public void onPageFinished(WebView view, String url) {
252             mProgressBar.setVisibility(View.INVISIBLE);
253             mSwipeRefreshLayout.setRefreshing(false);
254 
255             // Do not show the page error on UI.
256             if (mPageError) {
257                 if (mRedirectResponseReceived) {
258                     // Do not disconnect current connection while provisioning is in progress.
259                     mForceDisconnect = false;
260                 }
261                 finishAndRemoveTask();
262             }
263         }
264 
265         @Override
onReceivedError(WebView view, WebResourceRequest request, WebResourceError error)266         public void onReceivedError(WebView view, WebResourceRequest request,
267                 WebResourceError error) {
268             if (request.getUrl().toString().startsWith("http://127.0.0.1")) {
269                 mRedirectResponseReceived = true;
270                 view.stopLoading();
271             }
272 
273             if (request.isForMainFrame()) {
274                 // This happens right after getting HTTP redirect response from an OSU server
275                 // since no more Http request is allowed to send to the OSU server.
276                 mPageError = true;
277                 Log.e(TAG, "onReceived Error for MainFrame: " + error.getErrorCode());
278             }
279         }
280     }
281 }
282