Ver código fonte

GetRemoteStatusOperation and DetectAuthenticationMethodOperations are joint in GetServerInfoOperation

David A. Velasco 11 anos atrás
pai
commit
022c555aca

+ 1 - 1
owncloud-android-library

@@ -1 +1 @@
-Subproject commit 25c53f3bf978f53cceed125edfb9a37eecfa15a8
+Subproject commit a3683116ae04f639ff39484b1c54788bbce9fd30

+ 98 - 55
src/com/owncloud/android/authentication/AuthenticatorActivity.java

@@ -71,11 +71,11 @@ import com.owncloud.android.lib.common.OwnCloudClientFactory;
 import com.owncloud.android.lib.common.OwnCloudClient;
 import com.owncloud.android.operations.DetectAuthenticationMethodOperation;
 import com.owncloud.android.operations.DetectAuthenticationMethodOperation.AuthenticationMethod;
+import com.owncloud.android.operations.GetServerInfoOperation;
 import com.owncloud.android.operations.OAuth2GetAccessToken;
 
 import com.owncloud.android.lib.common.network.CertificateCombinedException;
 import com.owncloud.android.lib.common.operations.OnRemoteOperationListener;
-import com.owncloud.android.lib.resources.status.GetRemoteStatusOperation;
 import com.owncloud.android.lib.common.operations.RemoteOperation;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
@@ -142,8 +142,8 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
 
     private static final String TAG_SAML_DIALOG = "samlWebViewDialog";
 
-    private String mHostBaseUrl;
-    private OwnCloudVersion mDiscoveredVersion;
+    private String mHostBaseUrl;                // TODO remove
+    private OwnCloudVersion mDiscoveredVersion; // TODO remove
 
     private String mAuthMessageText;
     private int mAuthMessageVisibility, mServerStatusText, mServerStatusIcon;
@@ -156,7 +156,8 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
 
     private final Handler mHandler = new Handler();
     private Thread mOperationThread;
-    private GetRemoteStatusOperation mOcServerChkOperation;
+    //private GetRemoteStatusOperation mOcServerChkOperation;
+    private GetServerInfoOperation mServerInfoOperation;
     private ExistenceCheckRemoteOperation mAuthCheckOperation;
 
     private Uri mNewCapturedUriFromOAuth2Redirection;
@@ -196,6 +197,8 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
     
     private OperationsServiceBinder mOperationsServiceBinder = null;
 
+    private GetServerInfoOperation.ServerInfo mServerInfo;
+
     /**
      * {@inheritDoc}
      * 
@@ -361,8 +364,8 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
             mOAuth2Check.setVisibility(View.GONE);
         }
 
-        //if (mServerIsChecked && !mServerIsValid && mRefreshButtonEnabled) showRefreshButton();
-        if (mServerIsChecked && !mServerIsValid && refreshButtonEnabled) showRefreshButton();
+        //showRefreshButton(mServerIsChecked && !mServerIsValid && mRefreshButtonEnabled);
+        showRefreshButton(mServerIsChecked && !mServerIsValid && refreshButtonEnabled);
         mOkButton.setEnabled(mServerIsValid); // state not automatically recovered in configuration changes
 
         if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType) || 
@@ -488,7 +491,7 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
         outState.putInt(KEY_SERVER_STATUS_ICON, mServerStatusIcon);
         outState.putBoolean(KEY_SERVER_VALID, mServerIsValid);
         outState.putBoolean(KEY_SERVER_CHECKED, mServerIsChecked);
-        outState.putBoolean(KEY_SERVER_CHECK_IN_PROGRESS, (!mServerIsValid && mOcServerChkOperation != null));
+        outState.putBoolean(KEY_SERVER_CHECK_IN_PROGRESS, (!mServerIsValid && mServerInfoOperation != null));
         outState.putBoolean(KEY_IS_SSL_CONN, mIsSslConn);
         outState.putBoolean(KEY_PASSWORD_VISIBLE, isPasswordVisible());
         outState.putInt(KEY_AUTH_STATUS_ICON, mAuthStatusIcon);
@@ -623,7 +626,7 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
                 onUrlInputFocusLost((TextView) view);
             }
             else {
-                hideRefreshButton();
+                showRefreshButton(false);
             }
 
         } else if (view.getId() == R.id.account_password) {
@@ -648,32 +651,45 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
             checkOcServer();
         } else {
             mOkButton.setEnabled(mServerIsValid);
-            if (!mServerIsValid) {
-                showRefreshButton();
-            }
+            showRefreshButton(!mServerIsValid);
         }
     }
 
 
     private void checkOcServer() {
-        String uri = trimUrlWebdav(mHostUrlInput.getText().toString().trim());
+        String uri = mHostUrlInput.getText().toString().trim();
 
         if (!mHostUrlInputEnabled){
-            uri = getString(R.string.server_url);
+            uri = getString(R.string.server_url).trim();
         }
 
         mServerIsValid = false;
         mServerIsChecked = false;
         mOkButton.setEnabled(false);
         mDiscoveredVersion = null;
-        hideRefreshButton();
+        mServerAuthMethod = AuthenticationMethod.UNKNOWN;
+        showRefreshButton(false);
+        
         if (uri.length() != 0) {
             mServerStatusText = R.string.auth_testing_connection;
             mServerStatusIcon = R.drawable.progress_small;
             showServerStatus();
-            mOcServerChkOperation = new  GetRemoteStatusOperation(uri, this);
+            mServerInfoOperation = new GetServerInfoOperation(uri, mAuthTokenType, this);
             OwnCloudClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(uri), this, true);
-            mOperationThread = mOcServerChkOperation.execute(client, this, mHandler);
+            mServerInfoOperation.execute(client, this, mHandler);
+            
+            /*
+             * TODO start joint operation in OperationsService
+            Intent detectAuthIntent = new Intent();
+            detectAuthIntent.setAction(OperationsService.ACTION_DETECT_AUTHENTICATION_METHOD);
+            detectAuthIntent.putExtra(OperationsService.EXTRA_SERVER_URL, mBaseUrl);
+            detectAuthIntent.putExtra(OperationsService.EXTRA_WEBDAV_PATH, webdav_path);
+            if (mOperationsServiceBinder != null) {
+                //Log.wtf(TAG, "starting detection..." );
+                mDetectAuthOpId = mOperationsServiceBinder.newOperation(detectAuthIntent);
+            }
+            */
+            
         } else {
             mServerStatusText = 0;
             mServerStatusIcon = 0;
@@ -861,8 +877,12 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
     @Override
     public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
 
-        if (operation instanceof GetRemoteStatusOperation) {
-            onOcServerCheckFinish((GetRemoteStatusOperation) operation, result);
+        if (operation instanceof GetServerInfoOperation) {
+            if (operation.equals(mServerInfoOperation)) {
+                onGetServerInfoFinish(result);
+            }   // else nothing ; only the last check operation is considered; 
+                // multiple can be triggered if the user amends a URL before a previous check 
+                // can be triggered
 
         } else if (operation instanceof OAuth2GetAccessToken) {
             onGetOAuthAccessTokenFinish((OAuth2GetAccessToken)operation, result);
@@ -983,42 +1003,63 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
      * @param operation     Server check performed.
      * @param result        Result of the check.
      */
-    private void onOcServerCheckFinish(GetRemoteStatusOperation operation, RemoteOperationResult result) {
-        if (operation.equals(mOcServerChkOperation)) {
-            /// save result state
-            mServerIsChecked = true;
-            mServerIsValid = result.isSuccess();
-            mIsSslConn = (result.getCode() == ResultCode.OK_SSL);
-            mOcServerChkOperation = null;
-
-
-            /// retrieve discovered version and normalize server URL
-            mDiscoveredVersion = operation.getDiscoveredVersion();
-            mHostBaseUrl = normalizeUrl(mHostUrlInput.getText().toString());
+    private void onGetServerInfoFinish(RemoteOperationResult result) {
+        /// update activity state
+        mServerIsChecked = true;
+        mIsSslConn = (result.getCode() == ResultCode.OK_SSL);
+        mServerInfoOperation = null;
+        mDetectAuthOpId = -1;
+        
+        // update server status, but don't show it yet
+        updateServerStatusIconAndText(result);
 
-            // Refresh server status, but don't show it
-            updateServerStatusIconAndText(result);
+        if (result.isSuccess()) {
+            /// SUCCESS means:
+            //      1. connection succeeded, and we know if it's SSL or not
+            //      2. server is installed
+            //      3. we got the server version
+            //      4. we got the authentication method required by the server 
+            mServerInfo = (GetServerInfoOperation.ServerInfo) (result.getData().get(0));
+            mDiscoveredVersion = mServerInfo.mVersion;
+            mHostBaseUrl = mServerInfo.mBaseUrl;
+            
+            if (!authSupported(mServerInfo.mAuthMethod)) {
+                
+                updateServerStatusIconNoRegularAuth();  // overrides updateServerStatusIconAndText()  
+                mServerIsValid = false;
 
-            /// update status icon and text
-            if (mServerIsValid) {
-                hideRefreshButton();
-                // Try to create an account with user and pass "", to know if it is a regular server
-                // Update connect button in the answer of this method
-                detectAuthorizationMethod();
             } else {
-                showRefreshButton();
-                // Show server status
-                showServerStatus();
+                mServerIsValid = true;
             }
+            
+        } else {
+            mServerIsValid = false;
+        }
 
-            /// very special case (TODO: move to a common place for all the remote operations)
-            if (result.getCode() == ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED) {
-                showUntrustedCertDialog(result);
-            }
+        // refresh UI
+        showRefreshButton(!mServerIsValid);
+        showServerStatus();
+        mOkButton.setEnabled(mServerIsValid);
+        
+        /// very special case (TODO: move to a common place for all the remote operations)
+        if (result.getCode() == ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED) {
+            showUntrustedCertDialog(result);
+        }
+    }
 
 
-        }   // else nothing ; only the last check operation is considered; 
-        // multiple can be triggered if the user amends a URL before a previous check can be triggered
+    private boolean authSupported(AuthenticationMethod authMethod) {
+        String basic = AccountTypeUtils.getAuthTokenTypePass(MainApp.getAccountType());
+        String oAuth = AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType());
+        String saml =  AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType());
+        
+        return (( mAuthTokenType.equals(basic) && 
+                    authMethod.equals(AuthenticationMethod.BASIC_HTTP_AUTH) ) ||
+                ( mAuthTokenType.equals(oAuth) && 
+                    authMethod.equals(AuthenticationMethod.BEARER_TOKEN)) ||
+                ( mAuthTokenType.equals(saml)  && 
+                    authMethod.equals(AuthenticationMethod.SAML_WEB_SSO))
+        );
     }
 
 
@@ -1048,6 +1089,7 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
     }
 
 
+    // TODO remove, if possible
     private String normalizeUrl(String url) {
         if (url != null && url.length() > 0) {
             url = url.trim();
@@ -1072,6 +1114,7 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
     }
 
 
+    // TODO remove, if possible
     private String trimUrlWebdav(String url){       
         if(url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_4_0)){
             url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_4_0.length());             
@@ -1325,7 +1368,7 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
             mServerIsChecked = true;
             mServerIsValid = false;
             mIsSslConn = false;
-            mOcServerChkOperation = null;
+            mServerInfoOperation = null;
             mDiscoveredVersion = null;
             mHostBaseUrl = normalizeUrl(mHostUrlInput.getText().toString());
 
@@ -1337,7 +1380,7 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
             showAuthStatus();
 
             // update input controls state
-            showRefreshButton();
+            showRefreshButton(true);
             mOkButton.setEnabled(false);
 
             // very special case (TODO: move to a common place for all the remote operations) (dangerous here?)
@@ -1592,12 +1635,12 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
     }     
 
 
-    private void showRefreshButton() {
-        mRefreshButton.setVisibility(View.VISIBLE);
-    }
-
-    private void hideRefreshButton() {
-        mRefreshButton.setVisibility(View.GONE);
+    private void showRefreshButton (boolean show) {
+        if (show)  {
+            mRefreshButton.setVisibility(View.VISIBLE);
+        } else {
+            mRefreshButton.setVisibility(View.GONE);
+        }
     }
 
     /**

+ 3 - 0
src/com/owncloud/android/operations/DetectAuthenticationMethodOperation.java

@@ -126,6 +126,9 @@ public class DetectAuthenticationMethodOperation extends RemoteOperation {
         // else - fall back to UNKNOWN
         Log.d(TAG, "Authentication method found: " + authenticationMethodToString(authMethod));
         
+        if (!authMethod.equals(AuthenticationMethod.UNKNOWN)) {
+            result = new RemoteOperationResult(true, result.getHttpCode(), null);
+        }
         ArrayList<Object> data = new ArrayList<Object>();
         data.add(authMethod);
         result.setData(data);

+ 163 - 0
src/com/owncloud/android/operations/GetServerInfoOperation.java

@@ -0,0 +1,163 @@
+/* ownCloud Android Library is available under MIT license
+ *   Copyright (C) 2014 ownCloud Inc.
+ *   
+ *   Permission is hereby granted, free of charge, to any person obtaining a copy
+ *   of this software and associated documentation files (the "Software"), to deal
+ *   in the Software without restriction, including without limitation the rights
+ *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *   copies of the Software, and to permit persons to whom the Software is
+ *   furnished to do so, subject to the following conditions:
+ *   
+ *   The above copyright notice and this permission notice shall be included in
+ *   all copies or substantial portions of the Software.
+ *   
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
+ *   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
+ *   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
+ *   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ *   THE SOFTWARE.
+ *
+ */
+
+package com.owncloud.android.operations;
+
+import java.util.ArrayList;
+
+import com.owncloud.android.authentication.AccountUtils;
+import com.owncloud.android.lib.common.OwnCloudClient;
+import com.owncloud.android.lib.common.operations.RemoteOperation;
+import com.owncloud.android.lib.common.operations.RemoteOperationResult;
+import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.lib.resources.status.GetRemoteStatusOperation;
+import com.owncloud.android.lib.resources.status.OwnCloudVersion;
+import com.owncloud.android.operations.DetectAuthenticationMethodOperation.AuthenticationMethod;
+import com.owncloud.android.utils.Log_OC;
+
+import android.content.Context;
+
+/**
+ * Get basic information from an ownCloud server given its URL.
+ * 
+ * Checks the existence of a configured ownCloud server in the URL, gets its version 
+ * and finds out what authentication method is needed to access files in it.
+ * 
+ * @author David A. Velasco
+ * @author masensio
+ */
+
+public class GetServerInfoOperation extends RemoteOperation {
+    
+    private static final String TAG = GetServerInfoOperation.class.getSimpleName();
+    
+    private String mUrl;
+    private String mAuthTokenType;
+    private Context mContext;
+    
+    private ServerInfo mResultData;
+
+    /** 
+     * Constructor.
+     * 
+     * @param url               URL to an ownCloud server.
+     * @param authTokenType     Identifies the authorization token supported by the caller;
+     *                          TODO ugly dependency, get rid of it. 
+     * @param context           Android context; needed to check network state
+     *                          TODO ugly dependency, get rid of it. 
+     */
+    public GetServerInfoOperation(String url, String authTokenType, Context context) {
+        mUrl = trimWebdavSuffix(url);
+        mAuthTokenType = authTokenType;
+        mContext = context;
+        
+        mResultData = new ServerInfo();
+    }
+    
+    
+    /**
+     * Performs the operation
+     * 
+     * @return      Result of the operation. If successful, includes an instance of 
+     *              {@link ServerInfo} with the information retrieved from the server. 
+     *              Call {@link RemoteOperationResult#getData()}.get(0) to get it.
+     */
+	@Override
+	protected RemoteOperationResult run(OwnCloudClient client) {
+	    
+	    // first: check the status of the server (including its version)
+	    GetRemoteStatusOperation getStatus = new GetRemoteStatusOperation(mUrl, mContext);
+	    RemoteOperationResult result = getStatus.execute(client);
+
+        if (result.isSuccess()) {
+            // second: get authentication method required by the server
+            mResultData.mVersion = (OwnCloudVersion)(result.getData().get(0));
+            boolean isSslConn = (result.getCode() == ResultCode.OK_SSL);
+            mResultData.mBaseUrl = normalizeProtocolPrefix(mUrl, isSslConn);
+            RemoteOperationResult detectAuthResult = detectAuthorizationMethod(client);
+            
+            // third: merge results
+            if (detectAuthResult.isSuccess()) {
+                mResultData.mAuthMethod = 
+                        (AuthenticationMethod)detectAuthResult.getData().get(0);
+                ArrayList<Object> data = new ArrayList<Object>();
+                data.add(mResultData);
+                result.setData(data);
+            } else {
+                result = detectAuthResult;
+            }
+        }
+        return result;
+	}
+
+	
+    private RemoteOperationResult detectAuthorizationMethod(OwnCloudClient client) {
+        Log_OC.d(TAG, "Trying empty authorization to detect authentication method");
+        String webdav_path = AccountUtils.getWebdavPath(mResultData.mVersion, mAuthTokenType);
+        String webdav_url = mResultData.mBaseUrl + webdav_path;
+        DetectAuthenticationMethodOperation operation = 
+                new DetectAuthenticationMethodOperation(mContext, webdav_url);
+        return operation.execute(client);
+    }
+    
+
+    private String trimWebdavSuffix(String url) {
+        if (url == null) {
+            url = "";
+        } else {
+            if (url.endsWith("/")) {
+                url = url.substring(0, url.length() - 1);
+            }
+            if(url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_4_0)){
+                url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_4_0.length());
+            } else if(url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_2_0)){
+                url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_2_0.length());
+            } else if (url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_1_2)){
+                url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_1_2.length());
+            }
+        }
+        return url;
+    }
+
+    
+    private String normalizeProtocolPrefix(String url, boolean isSslConn) {
+        if (!url.toLowerCase().startsWith("http://") &&
+                !url.toLowerCase().startsWith("https://")) {
+            if (isSslConn) {
+                return "https://" + url;
+            } else {
+                return "http://" + url;
+            }
+        }
+        return url;
+    }
+    
+    
+    public static class ServerInfo {
+        public OwnCloudVersion mVersion;
+        public String mBaseUrl;
+        public AuthenticationMethod mAuthMethod;
+    }
+	
+}

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

@@ -72,7 +72,7 @@ public class SamlWebViewDialog extends SherlockDialogFragment {
      * 
      * @param handler
      * @param Url           Url to open at WebView
-     * @param targetURL     mHostBaseUrl + AccountUtils.getWebdavPath(mDiscoveredVersion, mCurrentAuthTokenType)
+     * @param targetURL     mBaseUrl + AccountUtils.getWebdavPath(mDiscoveredVersion, mCurrentAuthTokenType)
      * @return              New dialog instance, ready to show.
      */
     public static SamlWebViewDialog newInstance(String url, String targetUrl) {