Merge remote-tracking branch 'origin/operations_service' into operations_service
authorDavid A. Velasco <dvelasco@solidgear.es>
Tue, 1 Apr 2014 13:17:33 +0000 (15:17 +0200)
committerDavid A. Velasco <dvelasco@solidgear.es>
Tue, 1 Apr 2014 13:17:33 +0000 (15:17 +0200)
owncloud-android-library
src/com/owncloud/android/authentication/AuthenticatorActivity.java
src/com/owncloud/android/operations/DetectAuthenticationMethodOperation.java
src/com/owncloud/android/operations/GetServerInfoOperation.java [new file with mode: 0644]
src/com/owncloud/android/operations/OAuth2GetAccessToken.java
src/com/owncloud/android/services/OperationsService.java
src/com/owncloud/android/ui/dialog/SamlWebViewDialog.java

index cecda33..6b69b5a 160000 (submodule)
@@ -1 +1 @@
-Subproject commit cecda3333ac511267d6a70c61b1475211484ec84
+Subproject commit 6b69b5af1a79275a23339ad6382210d75b061f9f
index 3c14404..fc1e398 100644 (file)
@@ -19,6 +19,7 @@
 package com.owncloud.android.authentication;\r
 \r
 import java.security.cert.X509Certificate;\r
+import java.util.Map;\r
 \r
 import android.accounts.Account;\r
 import android.accounts.AccountManager;\r
@@ -45,7 +46,6 @@ import android.support.v4.app.FragmentTransaction;
 import android.text.Editable;\r
 import android.text.InputType;\r
 import android.text.TextWatcher;\r
-import android.util.Log;\r
 import android.view.KeyEvent;\r
 import android.view.MotionEvent;\r
 import android.view.View;\r
@@ -69,13 +69,12 @@ import com.owncloud.android.lib.common.accounts.AccountTypeUtils;
 import com.owncloud.android.lib.common.accounts.AccountUtils.Constants;\r
 import com.owncloud.android.lib.common.OwnCloudClientFactory;\r
 import com.owncloud.android.lib.common.OwnCloudClient;\r
-import com.owncloud.android.operations.DetectAuthenticationMethodOperation;\r
 import com.owncloud.android.operations.DetectAuthenticationMethodOperation.AuthenticationMethod;\r
+import com.owncloud.android.operations.GetServerInfoOperation;\r
 import com.owncloud.android.operations.OAuth2GetAccessToken;\r
 
 import com.owncloud.android.lib.common.network.CertificateCombinedException;\r
 import com.owncloud.android.lib.common.operations.OnRemoteOperationListener;\r
-import com.owncloud.android.lib.resources.status.GetRemoteStatusOperation;\r
 import com.owncloud.android.lib.common.operations.RemoteOperation;\r
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;\r
 import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;\r
@@ -141,21 +140,24 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
 \r
     private static final String TAG_SAML_DIALOG = "samlWebViewDialog";\r
 \r
-    private String mHostBaseUrl;\r
-    private OwnCloudVersion mDiscoveredVersion;\r
+    private String mHostBaseUrl;                // TODO remove\r
+    private OwnCloudVersion mDiscoveredVersion; // TODO remove\r
 \r
     private String mAuthMessageText;\r
     private int mAuthMessageVisibility, mServerStatusText, mServerStatusIcon;\r
     private boolean mServerIsChecked, mServerIsValid, mIsSslConn;\r
     private AuthenticationMethod mServerAuthMethod = AuthenticationMethod.UNKNOWN;\r
-    private int mDetectAuthOpId = -1;\r
+\r
+    private int mGetServerInfoOpId = -1;\r
+    private int mOauth2GetAccessTokenOpId = -1;\r
 \r
     private int mAuthStatusText, mAuthStatusIcon;    \r
     private TextView mAuthStatusLayout;\r
 \r
     private final Handler mHandler = new Handler();\r
     private Thread mOperationThread;\r
-    private GetRemoteStatusOperation mOcServerChkOperation;\r
+    private GetServerInfoOperation mServerInfoOperation;\r
+\r
     //private ExistenceCheckRemoteOperation mAuthCheckOperation;\r
     private int mExistenceCheckOpId = -1;\r
     \r
@@ -196,6 +198,8 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
     \r
     private OperationsServiceBinder mOperationsServiceBinder = null;\r
 \r
+    private GetServerInfoOperation.ServerInfo mServerInfo;\r
+\r
     /**\r
      * {@inheritDoc}\r
      * \r
@@ -336,7 +340,7 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
 \r
             mServerAuthMethod = AuthenticationMethod.valueOf(\r
                     savedInstanceState.getString(KEY_SERVER_AUTH_METHOD));\r
-            mDetectAuthOpId = savedInstanceState.getInt(KEY_DETECT_AUTH_OP_ID);\r
+            mGetServerInfoOpId = savedInstanceState.getInt(KEY_DETECT_AUTH_OP_ID);\r
 \r
         }\r
 \r
@@ -359,8 +363,7 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
             mOAuth2Check.setVisibility(View.GONE);\r
         }\r
 \r
-        //if (mServerIsChecked && !mServerIsValid && mRefreshButtonEnabled) showRefreshButton();\r
-        if (mServerIsChecked && !mServerIsValid && refreshButtonEnabled) showRefreshButton();\r
+        showRefreshButton(mServerIsChecked && !mServerIsValid && refreshButtonEnabled);\r
         mOkButton.setEnabled(mServerIsValid); // state not automatically recovered in configuration changes\r
 \r
         if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType) || \r
@@ -486,7 +489,7 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
         outState.putInt(KEY_SERVER_STATUS_ICON, mServerStatusIcon);\r
         outState.putBoolean(KEY_SERVER_VALID, mServerIsValid);\r
         outState.putBoolean(KEY_SERVER_CHECKED, mServerIsChecked);\r
-        outState.putBoolean(KEY_SERVER_CHECK_IN_PROGRESS, (!mServerIsValid && mOcServerChkOperation != null));\r
+        outState.putBoolean(KEY_SERVER_CHECK_IN_PROGRESS, (!mServerIsValid && mServerInfoOperation != null));\r
         outState.putBoolean(KEY_IS_SSL_CONN, mIsSslConn);\r
         outState.putBoolean(KEY_PASSWORD_VISIBLE, isPasswordVisible());\r
         outState.putInt(KEY_AUTH_STATUS_ICON, mAuthStatusIcon);\r
@@ -508,7 +511,7 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
         outState.putBoolean(KEY_REFRESH_BUTTON_ENABLED, (mRefreshButton.getVisibility() == View.VISIBLE));\r
         \r
         outState.putString(KEY_SERVER_AUTH_METHOD, mServerAuthMethod.name());\r
-        outState.putInt(KEY_DETECT_AUTH_OP_ID, mDetectAuthOpId);\r
+        outState.putInt(KEY_DETECT_AUTH_OP_ID, mGetServerInfoOpId);\r
         //Log.wtf(TAG, "onSaveInstanceState end" );\r
     }\r
 \r
@@ -599,7 +602,24 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
         /// Showing the dialog with instructions for the user.\r
         showDialog(DIALOG_OAUTH2_LOGIN_PROGRESS);\r
 \r
-        /// GET ACCESS TOKEN to the oAuth server \r
+        /// GET ACCESS TOKEN to the oAuth server\r
+        Intent getServerInfoIntent = new Intent();\r
+        getServerInfoIntent.setAction(OperationsService.ACTION_OAUTH2_GET_ACCESS_TOKEN);\r
+        \r
+        getServerInfoIntent.putExtra(\r
+                OperationsService.EXTRA_SERVER_URL, \r
+                mOAuthTokenEndpointText.getText().toString().trim());\r
+        \r
+        getServerInfoIntent.putExtra(\r
+                OperationsService.EXTRA_OAUTH2_QUERY_PARAMETERS, \r
+                queryParameters);\r
+        \r
+        if (mOperationsServiceBinder != null) {\r
+            //Log.wtf(TAG, "getting access token..." );\r
+            mOauth2GetAccessTokenOpId = mOperationsServiceBinder.newOperation(getServerInfoIntent);\r
+        }\r
+        \r
+        /*\r
         RemoteOperation operation = new OAuth2GetAccessToken(   getString(R.string.oauth2_client_id), \r
                 getString(R.string.oauth2_redirect_uri),       \r
                 getString(R.string.oauth2_grant_type),\r
@@ -607,6 +627,8 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
         //OwnCloudClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(getString(R.string.oauth2_url_endpoint_access)), getApplicationContext());\r
         OwnCloudClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mOAuthTokenEndpointText.getText().toString().trim()), getApplicationContext(), true);\r
         operation.execute(client, this, mHandler);\r
+        */\r
+        \r
     }\r
 \r
 \r
@@ -620,7 +642,7 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
                 onUrlInputFocusLost((TextView) view);\r
             }\r
             else {\r
-                hideRefreshButton();\r
+                showRefreshButton(false);\r
             }\r
 \r
         } else if (view.getId() == R.id.account_password) {\r
@@ -645,32 +667,39 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
             checkOcServer();\r
         } else {\r
             mOkButton.setEnabled(mServerIsValid);\r
-            if (!mServerIsValid) {\r
-                showRefreshButton();\r
-            }\r
+            showRefreshButton(!mServerIsValid);\r
         }\r
     }\r
 \r
 \r
     private void checkOcServer() {\r
-        String uri = trimUrlWebdav(mHostUrlInput.getText().toString().trim());\r
+        String uri = mHostUrlInput.getText().toString().trim();\r
 \r
         if (!mHostUrlInputEnabled){\r
-            uri = getString(R.string.server_url);\r
+            uri = getString(R.string.server_url).trim();\r
         }\r
 \r
         mServerIsValid = false;\r
         mServerIsChecked = false;\r
         mOkButton.setEnabled(false);\r
         mDiscoveredVersion = null;\r
-        hideRefreshButton();\r
+        mServerAuthMethod = AuthenticationMethod.UNKNOWN;\r
+        showRefreshButton(false);\r
+        \r
         if (uri.length() != 0) {\r
             mServerStatusText = R.string.auth_testing_connection;\r
             mServerStatusIcon = R.drawable.progress_small;\r
             showServerStatus();\r
-            mOcServerChkOperation = new  GetRemoteStatusOperation(uri, this);\r
-            OwnCloudClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(uri), this, true);\r
-            mOperationThread = mOcServerChkOperation.execute(client, this, mHandler);\r
+            \r
+            Intent getServerInfoIntent = new Intent();\r
+            getServerInfoIntent.setAction(OperationsService.ACTION_GET_SERVER_INFO);\r
+            getServerInfoIntent.putExtra(OperationsService.EXTRA_SERVER_URL, uri);\r
+            getServerInfoIntent.putExtra(OperationsService.EXTRA_AUTH_TOKEN_TYPE, mAuthTokenType);\r
+            if (mOperationsServiceBinder != null) {\r
+                //Log.wtf(TAG, "checking server..." );\r
+                mGetServerInfoOpId = mOperationsServiceBinder.newOperation(getServerInfoIntent);\r
+            }\r
+            \r
         } else {\r
             mServerStatusText = 0;\r
             mServerStatusIcon = 0;\r
@@ -817,7 +846,7 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
         existenceCheckIntent.putExtra(OperationsService.EXTRA_FOLLOW_REDIRECTS, followRedirects);\r
         \r
         if (mOperationsServiceBinder != null) {\r
-            Log.wtf(TAG, "starting existenceCheckRemoteOperation..." );\r
+            Log_OC.wtf(TAG, "starting existenceCheckRemoteOperation..." );\r
             mExistenceCheckOpId = mOperationsServiceBinder.newOperation(existenceCheckIntent);\r
         }\r
     }\r
@@ -832,7 +861,6 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
         mAuthStatusText = R.string.oauth_login_connection;\r
         showAuthStatus();\r
 \r
-\r
         // GET AUTHORIZATION request\r
         //Uri uri = Uri.parse(getString(R.string.oauth2_url_endpoint_auth));\r
         Uri uri = Uri.parse(mOAuthAuthEndpointText.getText().toString().trim());\r
@@ -879,14 +907,17 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
     @Override\r
     public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {\r
 \r
-        if (operation instanceof GetRemoteStatusOperation) {\r
-            onOcServerCheckFinish((GetRemoteStatusOperation) operation, result);\r
+        if (operation instanceof GetServerInfoOperation) {\r
+            if (operation.hashCode() == mGetServerInfoOpId) {\r
+                onGetServerInfoFinish(result);\r
+            }   // else nothing ; only the last check operation is considered; \r
+                // multiple can be started if the user amends a URL quickly\r
 \r
         } else if (operation instanceof OAuth2GetAccessToken) {\r
-            onGetOAuthAccessTokenFinish((OAuth2GetAccessToken)operation, result);\r
+            onGetOAuthAccessTokenFinish(result);\r
 \r
         } else if (operation instanceof ExistenceCheckRemoteOperation)  {\r
-            Log.wtf(TAG, "received detection response through callback" );\r
+            Log_OC.wtf(TAG, "received detection response through callback" );\r
             if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType)) {\r
                 onSamlBasedFederatedSingleSignOnAuthorizationStart(result);\r
 \r
@@ -896,44 +927,10 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
         } else if (operation instanceof GetRemoteUserNameOperation) {\r
             onGetUserNameFinish((GetRemoteUserNameOperation) operation, result);\r
 \r
-        } else if (operation instanceof DetectAuthenticationMethodOperation) {\r
-            Log.wtf(TAG, "received detection response through callback" );\r
-            onDetectAuthenticationFinish(result);\r
         }\r
 \r
     }\r
 \r
-    private void onDetectAuthenticationFinish(RemoteOperationResult result) {\r
-        // Read authentication method\r
-        mDetectAuthOpId = -1;\r
-        if (result.getData().size() > 0) {\r
-            AuthenticationMethod authMethod = (AuthenticationMethod) result.getData().get(0);\r
-            String basic = AccountTypeUtils.getAuthTokenTypePass(MainApp.getAccountType());\r
-            String oAuth = AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType());\r
-            String saml =  AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType());\r
-\r
-            if ( ( mAuthTokenType.equals(basic) && !authMethod.equals(AuthenticationMethod.BASIC_HTTP_AUTH) ) ||\r
-                    ( mAuthTokenType.equals(oAuth) && !authMethod.equals(AuthenticationMethod.BEARER_TOKEN) ) || \r
-                    ( mAuthTokenType.equals(saml)  && !authMethod.equals(AuthenticationMethod.SAML_WEB_SSO) ) ) {\r
-\r
-                mOkButton.setEnabled(false);\r
-                mServerIsValid = false;\r
-                //show an alert message ( Server Status )\r
-                updateServerStatusIconNoRegularAuth();\r
-                showServerStatus();\r
-\r
-            } else {\r
-                mOkButton.setEnabled(true);\r
-\r
-                // Show server status\r
-                showServerStatus();\r
-            }\r
-\r
-        }\r
-    }\r
-\r
-\r
-\r
     private void onGetUserNameFinish(GetRemoteUserNameOperation operation, RemoteOperationResult result) {\r
 \r
         if (result.isSuccess()) {\r
@@ -968,6 +965,7 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
     }\r
 \r
     private void onSamlBasedFederatedSingleSignOnAuthorizationStart(RemoteOperationResult result) {\r
+        mExistenceCheckOpId = -1;\r
         try {\r
             dismissDialog(DIALOG_LOGIN_PROGRESS);\r
         } catch (IllegalArgumentException e) {\r
@@ -1002,71 +1000,68 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
      * @param operation     Server check performed.\r
      * @param result        Result of the check.\r
      */\r
-    private void onOcServerCheckFinish(GetRemoteStatusOperation operation, RemoteOperationResult result) {\r
-        if (operation.equals(mOcServerChkOperation)) {\r
-            /// save result state\r
-            mServerIsChecked = true;\r
-            mServerIsValid = result.isSuccess();\r
-            mIsSslConn = (result.getCode() == ResultCode.OK_SSL);\r
-            mOcServerChkOperation = null;\r
-\r
-\r
-            /// retrieve discovered version and normalize server URL\r
-            mDiscoveredVersion = operation.getDiscoveredVersion();\r
-            mHostBaseUrl = normalizeUrl(mHostUrlInput.getText().toString());\r
+    private void onGetServerInfoFinish(RemoteOperationResult result) {\r
+        /// update activity state\r
+        mServerIsChecked = true;\r
+        mIsSslConn = (result.getCode() == ResultCode.OK_SSL);\r
+        mServerInfoOperation = null;\r
+        mGetServerInfoOpId = -1;\r
+        \r
+        // update server status, but don't show it yet\r
+        updateServerStatusIconAndText(result);\r
 \r
-            // Refresh server status, but don't show it\r
-            updateServerStatusIconAndText(result);\r
+        if (result.isSuccess()) {\r
+            /// SUCCESS means:\r
+            //      1. connection succeeded, and we know if it's SSL or not\r
+            //      2. server is installed\r
+            //      3. we got the server version\r
+            //      4. we got the authentication method required by the server \r
+            mServerInfo = (GetServerInfoOperation.ServerInfo) (result.getData().get(0));\r
+            mDiscoveredVersion = mServerInfo.mVersion;\r
+            mHostBaseUrl = mServerInfo.mBaseUrl;\r
+            mServerAuthMethod = mServerInfo.mAuthMethod;\r
+            \r
+            if (!authSupported(mServerAuthMethod)) {\r
+                \r
+                updateServerStatusIconNoRegularAuth();  // overrides updateServerStatusIconAndText()  \r
+                mServerIsValid = false;\r
 \r
-            /// update status icon and text\r
-            if (mServerIsValid) {\r
-                hideRefreshButton();\r
-                // Try to create an account with user and pass "", to know if it is a regular server\r
-                // Update connect button in the answer of this method\r
-                detectAuthorizationMethod();\r
             } else {\r
-                showRefreshButton();\r
-                // Show server status\r
-                showServerStatus();\r
+                mServerIsValid = true;\r
             }\r
+            \r
+        } else {\r
+            mServerIsValid = false;\r
+        }\r
 \r
-            /// very special case (TODO: move to a common place for all the remote operations)\r
-            if (result.getCode() == ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED) {\r
-                showUntrustedCertDialog(result);\r
-            }\r
-\r
-\r
-        }   // else nothing ; only the last check operation is considered; \r
-        // multiple can be triggered if the user amends a URL before a previous check can be triggered\r
+        // refresh UI\r
+        showRefreshButton(!mServerIsValid);\r
+        showServerStatus();\r
+        mOkButton.setEnabled(mServerIsValid);\r
+        \r
+        /// very special case (TODO: move to a common place for all the remote operations)\r
+        if (result.getCode() == ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED) {\r
+            showUntrustedCertDialog(result);\r
+        }\r
     }\r
 \r
 \r
-    /**\r
-     *  Try to access with  user/pass ""/"", to know if it is a regular server\r
-     */\r
-    private void detectAuthorizationMethod() {\r
-\r
-        Log_OC.d(TAG, "Trying empty authorization to detect authentication method");\r
-        \r
-        String webdav_path = AccountUtils.getWebdavPath(mDiscoveredVersion, mAuthTokenType);\r
+    private boolean authSupported(AuthenticationMethod authMethod) {\r
+        String basic = AccountTypeUtils.getAuthTokenTypePass(MainApp.getAccountType());\r
+        String oAuth = AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType());\r
+        String saml =  AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType());\r
         \r
-        /// test credentials \r
-        //Intent detectAuthIntent = new Intent(this, OperationsService.class);\r
-        Intent detectAuthIntent = new Intent();\r
-        detectAuthIntent.setAction(OperationsService.ACTION_DETECT_AUTHENTICATION_METHOD);\r
-        detectAuthIntent.putExtra(OperationsService.EXTRA_SERVER_URL, mHostBaseUrl);\r
-        detectAuthIntent.putExtra(OperationsService.EXTRA_WEBDAV_PATH, webdav_path);\r
-        \r
-        //if (mOperationsBinder != null) {  // let's let it crash to detect if is really possible\r
-        mServerAuthMethod = AuthenticationMethod.UNKNOWN;\r
-        if (mOperationsServiceBinder != null) {\r
-            //Log.wtf(TAG, "starting detection..." );\r
-            mDetectAuthOpId = mOperationsServiceBinder.newOperation(detectAuthIntent);\r
-        }\r
-        //}\r
+        return (( mAuthTokenType.equals(basic) && \r
+                    authMethod.equals(AuthenticationMethod.BASIC_HTTP_AUTH) ) ||\r
+                ( mAuthTokenType.equals(oAuth) && \r
+                    authMethod.equals(AuthenticationMethod.BEARER_TOKEN)) ||\r
+                ( mAuthTokenType.equals(saml)  && \r
+                    authMethod.equals(AuthenticationMethod.SAML_WEB_SSO))\r
+        );\r
     }\r
 \r
 \r
+    // TODO remove, if possible\r
     private String normalizeUrl(String url) {\r
         if (url != null && url.length() > 0) {\r
             url = url.trim();\r
@@ -1090,6 +1085,7 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
     }\r
 \r
 \r
+    // TODO remove, if possible\r
     private String trimUrlWebdav(String url){       \r
         if(url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_4_0)){\r
             url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_4_0.length());             \r
@@ -1276,10 +1272,10 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
      * Processes the result of the request for and access token send \r
      * to an OAuth authorization server.\r
      * \r
-     * @param operation     Operation performed requesting the access token.\r
      * @param result        Result of the operation.\r
      */\r
-    private void onGetOAuthAccessTokenFinish(OAuth2GetAccessToken operation, RemoteOperationResult result) {\r
+    private void onGetOAuthAccessTokenFinish(RemoteOperationResult result) {\r
+        mOauth2GetAccessTokenOpId = -1;\r
         try {\r
             dismissDialog(DIALOG_OAUTH2_LOGIN_PROGRESS);\r
         } catch (IllegalArgumentException e) {\r
@@ -1292,7 +1288,10 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
             showDialog(DIALOG_LOGIN_PROGRESS);\r
 \r
             /// time to test the retrieved access token on the ownCloud server\r
-            mAuthToken = ((OAuth2GetAccessToken)operation).getResultTokenMap().get(OAuth2Constants.KEY_ACCESS_TOKEN);\r
+            @SuppressWarnings("unchecked")\r
+            Map<String, String> tokens = (Map<String, String>)(result.getData().get(0));\r
+            mAuthToken = tokens.get(OAuth2Constants.KEY_ACCESS_TOKEN);\r
+            //mAuthToken = ((OAuth2GetAccessToken)operation).getResultTokenMap().get(OAuth2Constants.KEY_ACCESS_TOKEN);\r
             Log_OC.d(TAG, "Got ACCESS TOKEN: " + mAuthToken);\r
             \r
             String remotePath ="";\r
@@ -1317,6 +1316,7 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
      * @param result        Result of the operation.\r
      */\r
     private void onAuthorizationCheckFinish(RemoteOperationResult result) {\r
+        mExistenceCheckOpId = -1;\r
         try {\r
             dismissDialog(DIALOG_LOGIN_PROGRESS);\r
         } catch (IllegalArgumentException e) {\r
@@ -1344,7 +1344,7 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
             mServerIsChecked = true;\r
             mServerIsValid = false;\r
             mIsSslConn = false;\r
-            mOcServerChkOperation = null;\r
+            mServerInfoOperation = null;\r
             mDiscoveredVersion = null;\r
             mHostBaseUrl = normalizeUrl(mHostUrlInput.getText().toString());\r
 \r
@@ -1356,7 +1356,7 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
             showAuthStatus();\r
 \r
             // update input controls state\r
-            showRefreshButton();\r
+            showRefreshButton(true);\r
             mOkButton.setEnabled(false);\r
 \r
             // very special case (TODO: move to a common place for all the remote operations) (dangerous here?)\r
@@ -1610,12 +1610,12 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
     }     \r
 \r
 \r
-    private void showRefreshButton() {\r
-        mRefreshButton.setVisibility(View.VISIBLE);\r
-    }\r
-\r
-    private void hideRefreshButton() {\r
-        mRefreshButton.setVisibility(View.GONE);\r
+    private void showRefreshButton (boolean show) {\r
+        if (show)  {\r
+            mRefreshButton.setVisibility(View.VISIBLE);\r
+        } else {\r
+            mRefreshButton.setVisibility(View.GONE);\r
+        }\r
     }\r
 \r
     /**\r
@@ -1893,21 +1893,30 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
         //Log.wtf(TAG, "registering to listen for operation callbacks" );\r
         mOperationsServiceBinder.addOperationListener(AuthenticatorActivity.this, mHandler);\r
         \r
-        if (mDetectAuthOpId != -1) {\r
+        if (mGetServerInfoOpId != -1) {\r
             RemoteOperationResult result = \r
-                    mOperationsServiceBinder.getOperationResultIfFinished(mDetectAuthOpId);\r
+                    mOperationsServiceBinder.getOperationResultIfFinished(mGetServerInfoOpId);\r
             if (result != null) {\r
-                //Log.wtf(TAG, "found result of operation finished while rotating");\r
-                onDetectAuthenticationFinish(result);\r
+                //Log_OC.wtf(TAG, "found result of operation finished while rotating");\r
+                onGetServerInfoFinish(result);\r
             }\r
-        }\r
-        \r
-        if (mExistenceCheckOpId != -1) {\r
+            \r
+        } else if (mOauth2GetAccessTokenOpId != -1) {\r
+            RemoteOperationResult result = \r
+                    mOperationsServiceBinder.getOperationResultIfFinished(\r
+                            mOauth2GetAccessTokenOpId);\r
+            if (result != null) {\r
+                //Log_OC.wtf(TAG, "found result of operation finished while rotating");\r
+                onGetOAuthAccessTokenFinish(result);\r
+            }\r
+            \r
+        } else if (mExistenceCheckOpId != -1) {\r
             RemoteOperationResult result = \r
                     mOperationsServiceBinder.getOperationResultIfFinished(mExistenceCheckOpId);\r
             if (result != null) {\r
-                Log.wtf(TAG, "found result of operation finished while rotating");\r
-                if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType)) {\r
+                //Log_OC.wtf(TAG, "found result of operation finished while rotating");\r
+                if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(\r
+                        MainApp.getAccountType()).equals(mAuthTokenType)) {\r
                     onSamlBasedFederatedSingleSignOnAuthorizationStart(result);\r
 \r
                 } else {\r
index 6bc8750..b817e72 100644 (file)
@@ -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);
diff --git a/src/com/owncloud/android/operations/GetServerInfoOperation.java b/src/com/owncloud/android/operations/GetServerInfoOperation.java
new file mode 100644 (file)
index 0000000..c210153
--- /dev/null
@@ -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;
+    }
+       
+}
index e2d72c5..5f6a085 100644 (file)
@@ -1,5 +1,6 @@
 package com.owncloud.android.operations;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -37,15 +38,12 @@ public class OAuth2GetAccessToken extends RemoteOperation {
         mOAuth2ParsedAuthorizationResponse = new HashMap<String, String>();
         mResultTokenMap = null;
     }
-    
-    
-    public Map<String, String> getOauth2AutorizationResponse() {
-        return mOAuth2ParsedAuthorizationResponse;
-    }
 
+    /*
     public Map<String, String> getResultTokenMap() {
         return mResultTokenMap;
     }
+    */
     
     @Override
     protected RemoteOperationResult run(OwnCloudClient client) {
@@ -83,6 +81,9 @@ public class OAuth2GetAccessToken extends RemoteOperation {
                     
                     } else {
                         result = new RemoteOperationResult(true, status, postMethod.getResponseHeaders());
+                        ArrayList<Object> data = new ArrayList<Object>();
+                        data.add(mResultTokenMap);
+                        result.setData(data);
                     }
                     
                 } else {
index d44a3af..f0f37f5 100644 (file)
@@ -23,6 +23,7 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.ConcurrentMap;
 
+import com.owncloud.android.R;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.lib.common.OwnCloudClientFactory;
 import com.owncloud.android.lib.common.OwnCloudClient;
@@ -33,7 +34,8 @@ import com.owncloud.android.lib.resources.files.ExistenceCheckRemoteOperation;
 import com.owncloud.android.lib.resources.shares.ShareType;
 import com.owncloud.android.operations.common.SyncOperation;
 import com.owncloud.android.operations.CreateShareOperation;
-import com.owncloud.android.operations.DetectAuthenticationMethodOperation;
+import com.owncloud.android.operations.GetServerInfoOperation;
+import com.owncloud.android.operations.OAuth2GetAccessToken;
 import com.owncloud.android.operations.UnshareLinkOperation;
 import com.owncloud.android.utils.Log_OC;
 
@@ -57,9 +59,13 @@ public class OperationsService extends Service {
     
     public static final String EXTRA_ACCOUNT = "ACCOUNT";
     public static final String EXTRA_SERVER_URL = "SERVER_URL";
+    public static final String EXTRA_AUTH_TOKEN_TYPE = "AUTH_TOKEN_TYPE";
+    public static final String EXTRA_OAUTH2_QUERY_PARAMETERS = "OAUTH2_QUERY_PARAMETERS";
     public static final String EXTRA_REMOTE_PATH = "REMOTE_PATH";
     public static final String EXTRA_SEND_INTENT = "SEND_INTENT";
     public static final String EXTRA_RESULT = "RESULT";
+    
+    // TODO review if ALL OF THEM are necessary
     public static final String EXTRA_WEBDAV_PATH = "WEBDAV_PATH";
     public static final String EXTRA_SUCCESS_IF_ABSENT = "SUCCESS_IF_ABSENT";
     public static final String EXTRA_USERNAME = "USERNAME";
@@ -69,7 +75,8 @@ public class OperationsService extends Service {
     
     public static final String ACTION_CREATE_SHARE = "CREATE_SHARE";
     public static final String ACTION_UNSHARE = "UNSHARE";
-    public static final String ACTION_DETECT_AUTHENTICATION_METHOD = "DETECT_AUTHENTICATION_METHOD";
+    public static final String ACTION_GET_SERVER_INFO = "GET_SERVER_INFO";
+    public static final String ACTION_OAUTH2_GET_ACCESS_TOKEN = "OAUTH2_GET_ACCESS_TOKEN";
     public static final String ACTION_EXISTENCE_CHECK = "EXISTENCE_CHECK";
     
     public static final String ACTION_OPERATION_ADDED = OperationsService.class.getName() + ".OPERATION_ADDED";
@@ -271,6 +278,7 @@ public class OperationsService extends Service {
                             operation = new CreateShareOperation(remotePath, ShareType.PUBLIC_LINK, 
                                     "", false, "", 1, sendIntent);
                         }
+                        
                     } else if (action.equals(ACTION_UNSHARE)) {  // Unshare file
                         String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
                         if (remotePath.length() > 0) {
@@ -278,13 +286,24 @@ public class OperationsService extends Service {
                                     remotePath, 
                                     OperationsService.this);
                         }
-                    } else if (action.equals(ACTION_DETECT_AUTHENTICATION_METHOD)) { 
-                        // Detect Authentication Method
-                        String webdav_url = 
-                                serverUrl + operationIntent.getStringExtra(EXTRA_WEBDAV_PATH);
-                        operation = new DetectAuthenticationMethodOperation(
-                                OperationsService.this, 
-                                webdav_url);
+                        
+                    } else if (action.equals(ACTION_GET_SERVER_INFO)) { 
+                        // check OC server and get basic information from it
+                        String authTokenType = 
+                                operationIntent.getStringExtra(EXTRA_AUTH_TOKEN_TYPE);
+                        operation = new GetServerInfoOperation(
+                                serverUrl, authTokenType, OperationsService.this);
+                        
+                    } else if (action.equals(ACTION_OAUTH2_GET_ACCESS_TOKEN)) {
+                        /// GET ACCESS TOKEN to the OAuth server
+                        String oauth2QueryParameters =
+                                operationIntent.getStringExtra(EXTRA_OAUTH2_QUERY_PARAMETERS);
+                        operation = new OAuth2GetAccessToken(
+                                getString(R.string.oauth2_client_id), 
+                                getString(R.string.oauth2_redirect_uri),       
+                                getString(R.string.oauth2_grant_type),
+                                oauth2QueryParameters);
+                        
                     } else if (action.equals(ACTION_EXISTENCE_CHECK)) {
                         // Existence Check 
                         String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
index cbf1acb..0c17a6f 100644 (file)
@@ -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) {