package de.westnordost.streetcomplete.oauth; import android.annotation.TargetApi; import android.graphics.Bitmap; import android.net.http.SslError; import android.support.annotation.NonNull; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.webkit.SslErrorHandler; import android.webkit.WebResourceError; import android.webkit.WebResourceRequest; import android.webkit.WebResourceResponse; import android.webkit.WebView; import android.webkit.WebViewClient; import java.net.URI; import java.net.URISyntaxException; import java.util.HashMap; import java.util.Map; import de.westnordost.streetcomplete.util.AsyncTaskListener; /** WebViewClient that fetches the OAuth verification code from the OAuth authentication webpage */ public class OAuthCallbackWebViewClient extends WebViewClient { public static final String TAG = "OAuth"; // magic callback url for webpage to tell this dialog that the user has confirmed the authorization private static final String CALLBACK_URL = "streetcomplete://oauth/"; private AsyncTaskListener<String> listener; private ViewGroup progressDisplay; private WebView webView; private boolean errorOccured; public OAuthCallbackWebViewClient(AsyncTaskListener<String> listener, WebView webView, ViewGroup progressDisplay) { this.listener = listener; this.progressDisplay = progressDisplay; this.webView = webView; } @Override @SuppressWarnings("deprecation") public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { // TODO pass the error code up here... onError(null); } @Override public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) { onError(null); } @TargetApi(23) public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { onError(null); } @Override public void onReceivedSslError(WebView view, @NonNull SslErrorHandler handler, SslError error) { onError(null); } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { errorOccured = false; progressDisplay.setVisibility(View.VISIBLE); webView.setVisibility(View.INVISIBLE); } @Override public void onPageFinished(WebView view, String url) { if(errorOccured) return; if(url.startsWith(CALLBACK_URL)) return; progressDisplay.setVisibility(View.INVISIBLE); webView.setVisibility(View.VISIBLE); } @Override public boolean shouldOverrideUrlLoading(WebView view, String stringUrl) { Log.i(TAG, "Loading URL " + stringUrl); if (!stringUrl.startsWith(CALLBACK_URL)) return false; try { URI url = new URI(stringUrl); Map<String, String> params = getQueryMap(url.getQuery()); // also available but not needed: //String token = params.get("oauth_token"); listener.onSuccess(params.get("oauth_verifier")); } catch(URISyntaxException e) { listener.onError(e); } return true; } private void onError(Exception e) { listener.onError(e); errorOccured = true; } private static Map<String, String> getQueryMap(String query) { if (query == null) return null; String[] params = query.split("&"); Map<String, String> map = new HashMap<>(); for (String param : params) { String[] keyValue = param.split("="); String name = param.split("=")[0]; String value = null; if (keyValue.length > 1) { value = param.split("=")[1]; } map.put(name, value); } return map; } }