/* * Copyright (C) 2012 jonas.oreland@gmail.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.runnerup.export.oauth2client; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; import android.app.ProgressDialog; import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.view.Window; import android.webkit.CookieManager; import android.webkit.CookieSyncManager; import android.webkit.WebView; import android.webkit.WebViewClient; import org.runnerup.R; import org.runnerup.common.util.Constants.DB; import org.runnerup.export.Synchronizer; import org.runnerup.export.util.FormValues; import org.runnerup.export.util.SyncHelper; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; @TargetApi(Build.VERSION_CODES.FROYO) @SuppressLint("SetJavaScriptEnabled") public class OAuth2Activity extends AppCompatActivity { /** * Names used in Bundle to/from OAuth2Activity */ public interface OAuth2ServerCredentials { public static final String AUTH_ARGUMENTS = "auth_arguments"; /** * Used as title when opening authorization dialog * * @return */ public static final String NAME = "name"; public static final String CLIENT_ID = "client_id"; public static final String CLIENT_SECRET = "client_secret"; public static final String AUTH_URL = "auth_url"; public static final String AUTH_EXTRA = "auth_extra"; public static final String TOKEN_URL = "token_url"; public static final String REDIRECT_URI = "redirect_uri"; public static final String REVOKE_URL = "revoke_url"; public static final String AUTH_TOKEN = "auth_token"; } boolean mFinished = false; String mRedirectUri = null; ProgressDialog mSpinner = null; Bundle mArgs = null; @SuppressWarnings("deprecation") private void setSavedPassword(WebView wv, boolean val) { wv.getSettings().setSavePassword(false); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Intent intent = getIntent(); Bundle b = mArgs = intent .getBundleExtra(OAuth2ServerCredentials.AUTH_ARGUMENTS); String auth_url = b.getString(OAuth2ServerCredentials.AUTH_URL); String client_id = b.getString(OAuth2ServerCredentials.CLIENT_ID); mRedirectUri = b.getString(OAuth2ServerCredentials.REDIRECT_URI); String auth_extra = null; if (b.containsKey(OAuth2ServerCredentials.AUTH_EXTRA)) auth_extra = b.getString(OAuth2ServerCredentials.AUTH_EXTRA); mSpinner = new ProgressDialog(this); mSpinner.requestWindowFeature(Window.FEATURE_NO_TITLE); mSpinner.setMessage(getString(R.string.Loading)); final WebView wv = new WebView(this); wv.setVerticalScrollBarEnabled(false); wv.setHorizontalScrollBarEnabled(false); wv.getSettings().setJavaScriptEnabled(true); setSavedPassword(wv, false); StringBuilder tmp = new StringBuilder(); tmp.append(auth_url); tmp.append("?client_id=").append(SyncHelper.URLEncode(client_id)); tmp.append("&response_type=code"); tmp.append("&redirect_uri=").append(SyncHelper.URLEncode(mRedirectUri)); if (auth_extra != null) { tmp.append("&").append(auth_extra); } final String url = tmp.toString(); CookieSyncManager.createInstance(this); CookieManager.getInstance().removeAllCookie(); wv.loadUrl(url); wv.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String loadurl) { if (loadurl .startsWith("http://runkeeper.com/jsp/widgets/streetTeamWidgetClose.jsp") || loadurl.startsWith("http://runkeeper.com/jsp/widgets/friendWidgetClose.jsp")) { wv.loadUrl("http://runkeeper.com/facebookSignIn"); return true; } if (loadurl.startsWith("http://runkeeper.com/home")) { wv.loadUrl(url); return true; } return super.shouldOverrideUrlLoading(view, loadurl); } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); if (!isFinishing()) mSpinner.show(); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); try {// to avoid crashing the app add try-catch block, avoid // this stupid crash! if (mSpinner != null && mSpinner.isShowing()) mSpinner.dismiss(); } catch (Exception ex) { } if (url.startsWith(mRedirectUri)) { Uri u = Uri.parse(url); String e = null; String check[] = { "error", "error_type" }; for (String aCheck : check) { e = u.getQueryParameter(aCheck); if (e != null) { break; } } if (e != null) { Log.e(getClass().getName(), "e: " + e); Intent res = new Intent(); res.putExtra("error", e); OAuth2Activity.this.setResult(Activity.RESULT_CANCELED, res); OAuth2Activity.this.finish(); return; } synchronized (this) { if (mFinished) { return; } mFinished = true; } Bundle b = mArgs; String code = u.getQueryParameter("code"); final String token_url = b.getString(OAuth2ServerCredentials.TOKEN_URL); final FormValues fv = new FormValues(); fv.put("client_id", b.getString(OAuth2ServerCredentials.CLIENT_ID)); fv.put("client_secret", b.getString(OAuth2ServerCredentials.CLIENT_SECRET)); fv.put("grant_type", "authorization_code"); fv.put("redirect_uri", b.getString(OAuth2ServerCredentials.REDIRECT_URI)); fv.put("code", code); final Intent res = new Intent(); res.putExtra("url", token_url); new AsyncTask<String, String, Integer>() { @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected Integer doInBackground(String... params) { int resultCode = Activity.RESULT_OK; HttpURLConnection conn = null; try { URL newUrl = new URL(token_url); conn = (HttpURLConnection) newUrl.openConnection(); conn.setDoOutput(true); conn.setRequestMethod(Synchronizer.RequestMethod.POST.name()); conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); { OutputStream wr = new BufferedOutputStream(conn.getOutputStream()); fv.write(wr); wr.flush(); wr.close(); } StringBuilder obj = new StringBuilder(); BufferedReader in = new BufferedReader(new InputStreamReader(conn .getInputStream())); char buf[] = new char[1024]; int len; while ((len = in.read(buf)) != -1) { obj.append(buf, 0, len); } res.putExtra(DB.ACCOUNT.AUTH_CONFIG, obj.toString()); } catch (Exception ex) { ex.printStackTrace(System.err); res.putExtra("ex", ex.toString()); resultCode = Activity.RESULT_CANCELED; } if (conn != null) { conn.disconnect(); } return resultCode; } @Override protected void onPostExecute(Integer resultCode) { setResult(resultCode, res); finish(); } }.execute(); } } public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { if (failingUrl.startsWith(mRedirectUri)) { view.setVisibility(View.INVISIBLE); return; // we know this is will give error... } super.onReceivedError(view, errorCode, description, failingUrl); finish(); } }); setContentView(wv); } @Override public void onDestroy() { super.onDestroy(); } public static Intent getIntent(Activity activity, OAuth2Server server) { Intent args = new Intent(activity, OAuth2Activity.class); Bundle b = new Bundle(); b.putString(OAuth2ServerCredentials.CLIENT_ID, server.getClientId()); b.putString(OAuth2ServerCredentials.CLIENT_SECRET, server.getClientSecret()); b.putString(OAuth2ServerCredentials.AUTH_URL, server.getAuthUrl()); b.putString(OAuth2ServerCredentials.TOKEN_URL, server.getTokenUrl()); b.putString(OAuth2ServerCredentials.REDIRECT_URI, server.getRedirectUri()); String extra = server.getAuthExtra(); if (extra != null) { b.putString(OAuth2ServerCredentials.AUTH_EXTRA, extra); } args.putExtra(OAuth2Activity.OAuth2ServerCredentials.AUTH_ARGUMENTS, b); return args; } }