ソースを参照

Fixed orientation changes in SSO dialog with WebView

David A. Velasco 11 年 前
コミット
37297fb7a9

+ 33 - 0
res/layout/sso_dialog.xml

@@ -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>

+ 7 - 1
res/values/styles.xml

@@ -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" />

+ 36 - 26
src/com/owncloud/android/authentication/SsoWebViewClient.java

@@ -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;
     }
     */
-    
 }

+ 197 - 71
src/com/owncloud/android/ui/dialog/SamlWebViewDialog.java

@@ -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);
-        
-        // Save the state of the WebView
-        mSsoWebView.saveState(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
+    @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);
+        }
+        
+        setStyle(SherlockDialogFragment.STYLE_NO_TITLE, R.style.Theme_ownCloud_Dialog);
+    }
+    
+    @Override
     public Dialog onCreateDialog(Bundle savedInstanceState) {
-        Log_OC.d(TAG, "On Create Dialog");
+        Log_OC.d(TAG, "onCreateDialog");
 
-        mHandler = new Handler();
+        /*
+        // 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();
+        */
         
-        mSsoWebView = new WebView(getActivity()) {
-            @Override
-            public boolean onCheckIsTextEditor() {
-                return true; 
-            }            
-        };
+        return super.onCreateDialog(savedInstanceState);
+    }
 
+    @SuppressLint("SetJavaScriptEnabled")
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+        Log_OC.d(TAG, "onCreateView");
         
-        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);
-        }
+        return rootView;
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        Log_OC.d(SAML_DIALOG_TAG, "onSaveInstanceState being CALLED");
+        super.onSaveInstanceState(outState);
         
-        // build the dialog
-        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 
-        Dialog dialog = builder.setView(mSsoWebView).create();
+        // save URLs
+        outState.putString(ARG_INITIAL_URL, mInitialUrl);
+        outState.putString(ARG_TARGET_URL, mTargetUrl);
         
-        return dialog;
+        // 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);
     }
 
-    @SuppressLint("SetJavaScriptEnabled")
-    private void initWebView() {
-        CookieManager cookieManager = CookieManager.getInstance();
-        cookieManager.setAcceptCookie(true);
-        cookieManager.removeAllCookie();
-
-        mSsoWebView.loadUrl(mUrl);
+    @Override
+    public void onDestroyView() {
+        Log_OC.d(TAG, "onDestroyView");
+        
+        // Work around bug: http://code.google.com/p/android/issues/detail?id=17423
+        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();
     }
 
-    @SuppressLint("SetJavaScriptEnabled")
-    private void restoreWebView(Bundle savedInstanceState) {
-        mSsoWebView.restoreState(savedInstanceState);
-        
-        CookieManager cookieManager = CookieManager.getInstance();
-        Log_OC.e(TAG, "Accept Cookie: " + cookieManager.acceptCookie());
+    @Override
+    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 onDestroyView() {
-        Dialog dialog = getDialog();
-        Log_OC.d(TAG, "On Destroy");
-        // Work around bug: http://code.google.com/p/android/issues/detail?id=17423
-        if ((dialog != null) && getRetainInstance())
-            getDialog().setOnDismissListener(null);
+    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();
+    }
 
-        super.onDestroyView();
+    @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 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 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);
+    }
+
 }

+ 40 - 0
src/com/owncloud/android/ui/dialog/SsoWebView.java

@@ -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;
+    }
+    
+}
+