Fixed orientation changes in SSO dialog with WebView

This commit is contained in:
David A. Velasco 2013-08-21 18:51:13 +02:00
parent c88843916e
commit 37297fb7a9
5 changed files with 320 additions and 105 deletions

33
res/layout/sso_dialog.xml Normal file
View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
ownCloud Android client application
Copyright (C) 2012-2013 ownCloud Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2,
as published by the Free Software Foundation.
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/>.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<com.owncloud.android.ui.dialog.SsoWebView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/sso_webview"
android:focusable="true"
android:focusableInTouchMode="true"
android:clickable="true"
/>
</RelativeLayout>

View file

@ -20,7 +20,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="Animations" />
<!-- Default ownCloud app style -->
<!-- General ownCloud app style -->
<style name="Theme.ownCloud" parent="style/Theme.Sherlock.Light.DarkActionBar">
<item name="android:actionBarStyle">@style/Theme.ownCloud.Widget.ActionBar</item>
<item name="actionBarStyle">@style/Theme.ownCloud.Widget.ActionBar</item>
@ -47,6 +47,12 @@
<item name="android:shadowDy">1</item>
<item name="android:backgroundSplit">@drawable/split_action_bg</item>
</style>
<!-- Dialogs -->
<style name="Theme.ownCloud.Dialog" parent="style/Theme.Sherlock.Light.Dialog">
</style>
<!-- PopDownMenu -->
<style name="Animations.PopDownMenu" />

View file

@ -19,6 +19,8 @@ package com.owncloud.android.authentication;
import java.lang.ref.WeakReference;
import com.owncloud.android.Log_OC;
import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Message;
@ -39,7 +41,7 @@ import android.webkit.WebViewClient;
*/
public class SsoWebViewClient extends WebViewClient {
//private static final String TAG = SsoWebViewClient.class.getSimpleName();
private static final String TAG = SsoWebViewClient.class.getSimpleName();
public interface SsoWebViewClientListener {
public void onSsoFinished(String sessionCookie);
@ -48,11 +50,13 @@ public class SsoWebViewClient extends WebViewClient {
private Handler mListenerHandler;
private WeakReference<SsoWebViewClientListener> mListenerRef;
private String mTargetUrl;
private String mLastReloadedUrlAtError;
public SsoWebViewClient (Handler listenerHandler, SsoWebViewClientListener listener) {
mListenerHandler = listenerHandler;
mListenerRef = new WeakReference<SsoWebViewClient.SsoWebViewClientListener>(listener);
mTargetUrl = "fake://url.to.be.set";
mLastReloadedUrlAtError = null;
}
public String getTargetUrl() {
@ -65,12 +69,12 @@ public class SsoWebViewClient extends WebViewClient {
@Override
public void onPageStarted (WebView view, String url, Bitmap favicon) {
//Log_OC.e(TAG, "onPageStarted : " + url);
Log_OC.d(TAG, "onPageStarted : " + url);
if (url.startsWith(mTargetUrl)) {
view.setVisibility(View.GONE);
CookieManager cookieManager = CookieManager.getInstance();
final String cookies = cookieManager.getCookie(url);
//Log_OC.e(TAG, cookies);
//Log_OC.d(TAG, cookies);
if (mListenerHandler != null && mListenerRef != null) {
// this is good idea because onPageStarted is not running in the UI thread
mListenerHandler.post(new Runnable() {
@ -88,75 +92,81 @@ public class SsoWebViewClient extends WebViewClient {
@Override
public void onFormResubmission (WebView view, Message dontResend, Message resend) {
//Log_OC.e(TAG, "onFormResubMission ");
Log_OC.d(TAG, "onFormResubMission ");
// necessary to grant reload of last page when device orientation is changed after sending a form
resend.sendToTarget();
resend.sendToTarget();
}
/*
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//view.loadUrl(url);
return false;
}
@Override
public void onReceivedError (WebView view, int errorCode, String description, String failingUrl) {
Log_OC.e(TAG, "onReceivedError : " + failingUrl);
Log_OC.e(TAG, "onReceivedError : " + failingUrl + ", code " + errorCode + ", description: " + description);
if (!failingUrl.equals(mLastReloadedUrlAtError)) {
view.reload();
mLastReloadedUrlAtError = failingUrl;
} else {
mLastReloadedUrlAtError = null;
}
}
@Override
public void onPageFinished (WebView view, String url) {
Log_OC.d(TAG, "onPageFinished : " + url);
mLastReloadedUrlAtError = null;
}
/*
@Override
public void doUpdateVisitedHistory (WebView view, String url, boolean isReload) {
Log_OC.e(TAG, "doUpdateVisitedHistory : " + url);
Log_OC.d(TAG, "doUpdateVisitedHistory : " + url);
}
@Override
public void onReceivedSslError (WebView view, SslErrorHandler handler, SslError error) {
Log_OC.e(TAG, "onReceivedSslError : " + error);
Log_OC.d(TAG, "onReceivedSslError : " + error);
}
@Override
public void onReceivedHttpAuthRequest (WebView view, HttpAuthHandler handler, String host, String realm) {
Log_OC.e(TAG, "onReceivedHttpAuthRequest : " + host);
Log_OC.d(TAG, "onReceivedHttpAuthRequest : " + host);
}
@Override
public void onPageFinished (WebView view, String url) {
Log_OC.e(TAG, "onPageFinished : " + url);
}
@Override
public WebResourceResponse shouldInterceptRequest (WebView view, String url) {
Log_OC.e(TAG, "shouldInterceptRequest : " + url);
Log_OC.d(TAG, "shouldInterceptRequest : " + url);
return null;
}
@Override
public void onLoadResource (WebView view, String url) {
Log_OC.e(TAG, "onLoadResource : " + url);
Log_OC.d(TAG, "onLoadResource : " + url);
}
@Override
public void onReceivedLoginRequest (WebView view, String realm, String account, String args) {
Log_OC.e(TAG, "onReceivedLoginRequest : " + realm + ", " + account + ", " + args);
Log_OC.d(TAG, "onReceivedLoginRequest : " + realm + ", " + account + ", " + args);
}
@Override
public void onScaleChanged (WebView view, float oldScale, float newScale) {
Log_OC.e(TAG, "onScaleChanged : " + oldScale + " -> " + newScale);
Log_OC.d(TAG, "onScaleChanged : " + oldScale + " -> " + newScale);
super.onScaleChanged(view, oldScale, newScale);
}
@Override
public void onUnhandledKeyEvent (WebView view, KeyEvent event) {
Log_OC.e(TAG, "onUnhandledKeyEvent : " + event);
Log_OC.d(TAG, "onUnhandledKeyEvent : " + event);
}
@Override
public boolean shouldOverrideKeyEvent (WebView view, KeyEvent event) {
Log_OC.e(TAG, "shouldOverrideKeyEvent : " + event);
Log_OC.d(TAG, "shouldOverrideKeyEvent : " + event);
return false;
}
*/
}

View file

@ -1,17 +1,41 @@
/* ownCloud Android client application
* Copyright (C) 2012-2013 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* 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 com.owncloud.android.ui.dialog;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.FragmentManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.CookieManager;
import android.webkit.WebBackForwardList;
import android.webkit.WebSettings;
import android.webkit.WebView;
import com.actionbarsherlock.app.SherlockDialogFragment;
import com.owncloud.android.Log_OC;
import com.owncloud.android.R;
import com.owncloud.android.authentication.SsoWebViewClient;
import com.owncloud.android.authentication.SsoWebViewClient.SsoWebViewClientListener;
@ -21,24 +45,30 @@ import eu.alefzero.webdav.WebdavClient;
* Dialog to show the WebView for SAML Authentication
*
* @author Maria Asensio
* @author David A. Velasco
*/
public class SamlWebViewDialog extends DialogFragment
{
public class SamlWebViewDialog extends SherlockDialogFragment {
public final String SAML_DIALOG_TAG = "SamlWebViewDialog";
private final static String TAG = SamlWebViewDialog.class.getSimpleName();
private static final String ARG_INITIAL_URL = "INITIAL_URL";
private static final String ARG_TARGET_URL = "TARGET_URL";
private static final String KEY_WEBVIEW_STATE = "WEBVIEW_STATE";
private WebView mSsoWebView;
//private WebView mSsoWebView;
private SsoWebViewClient mWebViewClient;
private static String mUrl;
private static String mTargetUrl;
private String mInitialUrl;
private String mTargetUrl;
private Handler mHandler;
private SsoWebViewClientListener mSsoWebViewClientListener;
//private View mSsoRootView;
/**
* Public factory method to get dialog instances.
@ -49,105 +79,201 @@ public class SamlWebViewDialog extends DialogFragment
* @return New dialog instance, ready to show.
*/
public static SamlWebViewDialog newInstance(String url, String targetUrl) {
Log_OC.d(TAG, "New instance");
SamlWebViewDialog fragment = new SamlWebViewDialog();
mUrl = url;
mTargetUrl = targetUrl;
Bundle args = new Bundle();
args.putString(ARG_INITIAL_URL, url);
args.putString(ARG_TARGET_URL, targetUrl);
fragment.setArguments(args);
return fragment;
}
public SamlWebViewDialog() {
super();
Log_OC.d(TAG, "constructor");
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
public void onAttach(Activity activity) {
Log_OC.d(TAG, "onAttach");
super.onAttach(activity);
try {
mSsoWebViewClientListener = (SsoWebViewClientListener) activity;
mHandler = new Handler();
mWebViewClient = new SsoWebViewClient(mHandler, mSsoWebViewClientListener);
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement " + SsoWebViewClientListener.class.getSimpleName());
}
}
@SuppressLint("SetJavaScriptEnabled")
@Override
public void onCreate(Bundle savedInstanceState) {
Log_OC.d(TAG, "onCreate");
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
mInitialUrl = getArguments().getString(ARG_INITIAL_URL);
mTargetUrl = getArguments().getString(ARG_TARGET_URL);
} else {
mInitialUrl = savedInstanceState.getString(ARG_INITIAL_URL);
mTargetUrl = savedInstanceState.getString(ARG_TARGET_URL);
}
// Save the state of the WebView
mSsoWebView.saveState(outState);
setStyle(SherlockDialogFragment.STYLE_NO_TITLE, R.style.Theme_ownCloud_Dialog);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Log_OC.d(TAG, "onCreateDialog");
/*
// build the dialog
AlertDialog.Builder builder = new AlertDialog.Builder(getSherlockActivity());
if (mSsoRootView.getParent() != null) {
((ViewGroup)(mSsoRootView.getParent())).removeView(mSsoRootView);
}
builder.setView(mSsoRootView);
//builder.setView(mSsoWebView);
Dialog dialog = builder.create();
*/
return super.onCreateDialog(savedInstanceState);
}
@SuppressLint("SetJavaScriptEnabled")
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Log_OC.d(TAG, "On Create Dialog");
mHandler = new Handler();
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log_OC.d(TAG, "onCreateView");
mSsoWebView = new WebView(getActivity()) {
@Override
public boolean onCheckIsTextEditor() {
return true;
}
};
mWebViewClient = new SsoWebViewClient(mHandler, mSsoWebViewClientListener);
mSsoWebView.setWebViewClient(mWebViewClient);
// Inflate layout of the dialog
View rootView = inflater.inflate(R.layout.sso_dialog, container, false); // null parent view because it will go in the dialog layout
WebView ssoWebView = (WebView) rootView.findViewById(R.id.sso_webview);
mWebViewClient.setTargetUrl(mTargetUrl);
ssoWebView.setWebViewClient(mWebViewClient);
mSsoWebView.setFocusable(true);
mSsoWebView.setFocusableInTouchMode(true);
mSsoWebView.setClickable(true);
WebSettings webSettings = mSsoWebView.getSettings();
if (savedInstanceState == null) {
Log_OC.d(TAG, " initWebView start");
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
cookieManager.removeAllCookie();
ssoWebView.loadUrl(mInitialUrl);
} else {
Log_OC.d(TAG, " restoreWebView start");
WebBackForwardList history = ssoWebView.restoreState(savedInstanceState.getBundle(KEY_WEBVIEW_STATE));
if (history == null) {
Log_OC.e(TAG, "Error restoring WebView state ; back to starting URL");
ssoWebView.loadUrl(mInitialUrl);
}
}
WebSettings webSettings = ssoWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setBuiltInZoomControls(true);
webSettings.setLoadWithOverviewMode(false);
webSettings.setSavePassword(false);
webSettings.setUserAgentString(WebdavClient.USER_AGENT);
webSettings.setSaveFormData(false);
// load the dialog
if (savedInstanceState == null) {
initWebView();
}
else {
restoreWebView(savedInstanceState);
}
// build the dialog
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
Dialog dialog = builder.setView(mSsoWebView).create();
return dialog;
return rootView;
}
@SuppressLint("SetJavaScriptEnabled")
private void initWebView() {
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
cookieManager.removeAllCookie();
mSsoWebView.loadUrl(mUrl);
}
@SuppressLint("SetJavaScriptEnabled")
private void restoreWebView(Bundle savedInstanceState) {
mSsoWebView.restoreState(savedInstanceState);
@Override
public void onSaveInstanceState(Bundle outState) {
Log_OC.d(SAML_DIALOG_TAG, "onSaveInstanceState being CALLED");
super.onSaveInstanceState(outState);
CookieManager cookieManager = CookieManager.getInstance();
Log_OC.e(TAG, "Accept Cookie: " + cookieManager.acceptCookie());
// save URLs
outState.putString(ARG_INITIAL_URL, mInitialUrl);
outState.putString(ARG_TARGET_URL, mTargetUrl);
// Save the state of the WebView
Bundle webviewState = new Bundle();
((WebView) getDialog().findViewById(R.id.sso_webview)).saveState(webviewState);
outState.putBundle(KEY_WEBVIEW_STATE, webviewState);
}
@Override
public void onDestroyView() {
Dialog dialog = getDialog();
Log_OC.d(TAG, "On Destroy");
Log_OC.d(TAG, "onDestroyView");
// Work around bug: http://code.google.com/p/android/issues/detail?id=17423
if ((dialog != null) && getRetainInstance())
getDialog().setOnDismissListener(null);
Dialog dialog = getDialog();
if ((dialog != null)) {
dialog.setOnDismissListener(null);
//dialog.dismiss();
//dialog.setDismissMessage(null);
}
super.onDestroyView();
}
@Override
public void onDestroy() {
Log_OC.d(TAG, "onDestroy");
super.onDestroy();
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
Log_OC.e(TAG, "onAttach");
try {
mSsoWebViewClientListener = (SsoWebViewClientListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement " + SsoWebViewClientListener.class.getSimpleName());
}
public void onDetach() {
Log_OC.d(TAG, "onDetach");
mSsoWebViewClientListener = null;
mWebViewClient = null;
super.onDetach();
}
@Override
public void onCancel (DialogInterface dialog) {
Log_OC.d(SAML_DIALOG_TAG, "onCancel");
super.onCancel(dialog);
}
@Override
public void onDismiss (DialogInterface dialog) {
Log_OC.d(SAML_DIALOG_TAG, "onDismiss");
super.onDismiss(dialog);
}
@Override
public void onStart() {
Log_OC.d(SAML_DIALOG_TAG, "onStart");
super.onStart();
}
@Override
public void onStop() {
Log_OC.d(SAML_DIALOG_TAG, "onStop");
super.onStop();
}
@Override
public void onResume() {
Log_OC.d(SAML_DIALOG_TAG, "onResume");
super.onResume();
}
@Override
public void onPause() {
Log_OC.d(SAML_DIALOG_TAG, "onPause");
super.onPause();
}
@Override
public int show (FragmentTransaction transaction, String tag) {
Log_OC.d(SAML_DIALOG_TAG, "show (transaction)");
return super.show(transaction, tag);
}
@Override
public void show (FragmentManager manager, String tag) {
Log_OC.d(SAML_DIALOG_TAG, "show (manager)");
super.show(manager, tag);
}
}

View file

@ -0,0 +1,40 @@
/* ownCloud Android client application
* Copyright (C) 2012-2013 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* 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 com.owncloud.android.ui.dialog;
import android.content.Context;
import android.util.AttributeSet;
import android.webkit.WebView;
public class SsoWebView extends WebView {
public SsoWebView(Context context) {
super(context);
}
public SsoWebView(Context context, AttributeSet attr) {
super(context, attr);
}
@Override
public boolean onCheckIsTextEditor () {
return false;
}
}