/* * This software is released under the GNU Lesser General Public License v3. * For more information see http://www.gnu.org/licenses/lgpl.html * * Copyright (c) 2011, Peter Knego & Matjaz Tercelj * All rights reserved. */ package com.leanengine; import android.app.Dialog; import android.app.ProgressDialog; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Color; import android.net.UrlQuerySanitizer; import android.os.Bundle; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.Window; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Button; import android.widget.FrameLayout; import android.widget.LinearLayout; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; /** * A subclass of {@link Dialog} for performing login procedure against various authentication providers. */ public class LoginDialog extends Dialog { static final FrameLayout.LayoutParams FILL = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT); private String mUrl; private LoginListener mListener; private ProgressDialog mSpinner; private Button cancelButton; private WebView mWebView; private FrameLayout frameLayout; private LinearLayout content; private LinearLayout buttonContainer; /** * Constructs a LoginDialog. * @param context Activity context. * @param url URL of the authentication service. URLs are provided by {@link LeanEngine#getFacebookLoginUri()}, * {@link com.leanengine.LeanEngine#getGoogleLoginUri()}, etc.. * @param listener {@link LoginListener} that will be invoked when authentication procedure finishes or in case * of errors. */ public LoginDialog(Context context, String url, LoginListener listener) { super(context, android.R.style.Theme_Translucent_NoTitleBar); mUrl = url; mListener = listener; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mSpinner = new ProgressDialog(getContext()); mSpinner.requestWindowFeature(Window.FEATURE_NO_TITLE); mSpinner.setMessage("Loading..."); requestWindowFeature(Window.FEATURE_NO_TITLE); frameLayout = new FrameLayout(getContext()); content = new LinearLayout(getContext()); content.setOrientation(LinearLayout.VERTICAL); content.setLayoutParams(FILL); content.setBackgroundColor(Color.LTGRAY); createCancelButton(); setUpWebView(5); frameLayout.addView(content, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); frameLayout.setPadding(5, 5, 5, 5); addContentView(frameLayout, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); } private void createCancelButton() { buttonContainer = new LinearLayout(getContext()); buttonContainer.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); buttonContainer.setBackgroundColor(Color.LTGRAY); buttonContainer.setPadding(5, 5, 5, 0); buttonContainer.setGravity(Gravity.CENTER_VERTICAL); cancelButton = new Button(getContext()); cancelButton.setText("Cancel"); cancelButton.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); cancelButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mListener.onCancel(); LoginDialog.this.dismiss(); } }); buttonContainer.addView(cancelButton, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); content.addView(buttonContainer); buttonContainer.setVisibility(View.INVISIBLE); } private void setUpWebView(int margin) { LinearLayout webViewContainer = new LinearLayout(getContext()); mWebView = new WebView(getContext()); mWebView.setVerticalScrollBarEnabled(false); mWebView.setHorizontalScrollBarEnabled(false); mWebView.setWebViewClient(new InternalWebViewClient()); mWebView.getSettings().setJavaScriptEnabled(true); mWebView.loadUrl(mUrl); mWebView.setLayoutParams(FILL); mWebView.setVisibility(View.INVISIBLE); webViewContainer.setPadding(margin, margin, margin, margin); webViewContainer.addView(mWebView); content.addView(webViewContainer, FILL); } private class InternalWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url != null && url.startsWith("leanengine://")) { UrlQuerySanitizer query = new UrlQuerySanitizer(url); String token = query.getValue("auth_token"); if (token != null) { LoginDialog.this.dismiss(); LeanEngine.saveAuthData(token); mListener.onSuccess(); } else { String errorCode = query.getValue("errorcode"); String errorMsg = null; try { errorMsg = URLDecoder.decode(query.getValue("errormsg"), "UTF-8"); } catch (UnsupportedEncodingException e) { // should not happen - UTF-8 is always supported } LoginDialog.this.dismiss(); mListener.onError(new LeanError(LeanError.Type.NotAuthorizedError, "Authorization error: error. errorCode=" + errorCode + " errorMsg=" + errorMsg)); } return true; } return false; } @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { super.onReceivedError(view, errorCode, description, failingUrl); mListener.onError(new LeanError(LeanError.Type.ServerError, " Could not connect to Facebook authorization server.")); LoginDialog.this.dismiss(); } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); mSpinner.show(); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); mSpinner.dismiss(); frameLayout.setBackgroundColor(Color.TRANSPARENT); mWebView.setVisibility(View.VISIBLE); buttonContainer.setVisibility(View.VISIBLE); } } }