Merge branch 'develop' into enable_cookies
authormasensio <masensio@solidgear.es>
Thu, 19 Feb 2015 12:02:53 +0000 (13:02 +0100)
committermasensio <masensio@solidgear.es>
Thu, 19 Feb 2015 12:02:53 +0000 (13:02 +0100)
Conflicts:
src/com/owncloud/android/authentication/AuthenticatorActivity.java

1  2 
src/com/owncloud/android/MainApp.java
src/com/owncloud/android/authentication/AuthenticatorActivity.java

@@@ -1,5 -1,5 +1,5 @@@
  /* ownCloud Android client application
 - *   Copyright (C) 2012-2013 ownCloud Inc.
 + *   Copyright (C) 2012-2015 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,
@@@ -36,15 -36,26 +36,26 @@@ public class MainApp extends Applicatio
      
      private static final String AUTH_ON = "on";
      
+     @SuppressWarnings("unused")
+     private static final String POLICY_SINGLE_SESSION_PER_ACCOUNT = "single session per account";
+     @SuppressWarnings("unused")
+     private static final String POLICY_ALWAYS_NEW_CLIENT = "always new client";
      private static Context mContext;
      
      public void onCreate(){
          super.onCreate();
          MainApp.mContext = getApplicationContext();
-         // keep a single session per account handling session cookie in requests (& all the other cookies)
-         OwnCloudClientManagerFactory.setDefaultPolicy(Policy.SINGLE_SESSION_PER_ACCOUNT);
+         
+         boolean isSamlAuth = AUTH_ON.equals(getString(R.string.auth_method_saml_web_sso));
+         
+         if (isSamlAuth) {   
+             OwnCloudClientManagerFactory.setDefaultPolicy(Policy.SINGLE_SESSION_PER_ACCOUNT);
              
+         } else {
+             OwnCloudClientManagerFactory.setDefaultPolicy(Policy.ALWAYS_NEW_CLIENT);
+         }
          // initialise thumbnails cache on background thread
          new ThumbnailsCacheManager.InitDiskCacheTask().execute();
          
@@@ -1,6 -1,6 +1,6 @@@
  /* ownCloud Android client application\r
   *   Copyright (C) 2012  Bartek Przybylski\r
 - *   Copyright (C) 2012-2014 ownCloud Inc.\r
 + *   Copyright (C) 2012-2015 ownCloud Inc.\r
   *\r
   *   This program is free software: you can redistribute it and/or modify\r
   *   it under the terms of the GNU General Public License version 2,\r
@@@ -33,7 -33,6 +33,7 @@@ import android.graphics.Rect
  import android.graphics.drawable.Drawable;\r
  import android.net.Uri;\r
  import android.net.http.SslError;\r
 +import android.os.AsyncTask;\r
  import android.os.Bundle;\r
  import android.os.Handler;\r
  import android.os.IBinder;\r
@@@ -65,10 -64,7 +65,10 @@@ import com.actionbarsherlock.app.Sherlo
  import com.owncloud.android.MainApp;\r
  import com.owncloud.android.R;\r
  import com.owncloud.android.authentication.SsoWebViewClient.SsoWebViewClientListener;\r
 +import com.owncloud.android.lib.common.OwnCloudAccount;\r
 +import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;\r
  import com.owncloud.android.lib.common.accounts.AccountTypeUtils;\r
 +import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;\r
  import com.owncloud.android.lib.common.accounts.AccountUtils.Constants;\r
  import com.owncloud.android.lib.common.network.CertificateCombinedException;\r
  import com.owncloud.android.lib.common.operations.OnRemoteOperationListener;\r
@@@ -99,9 -95,8 +99,9 @@@ import com.owncloud.android.utils.Displ
   * @author masensio\r
   */\r
  public class AuthenticatorActivity extends AccountAuthenticatorActivity\r
 -implements  OnRemoteOperationListener, OnFocusChangeListener, OnEditorActionListener, \r
 -SsoWebViewClientListener, OnSslUntrustedCertListener {\r
 +        implements  OnRemoteOperationListener, OnFocusChangeListener, OnEditorActionListener,\r
 +        SsoWebViewClientListener, OnSslUntrustedCertListener,\r
 +        AuthenticatorAsyncTask.OnAuthenticatorTaskListener {\r
  \r
      private static final String TAG = AuthenticatorActivity.class.getSimpleName();\r
  \r
      private static final String CREDENTIALS_DIALOG_TAG = "CREDENTIALS_DIALOG";\r
      private static final String KEY_AUTH_IS_FIRST_ATTEMPT_TAG = "KEY_AUTH_IS_FIRST_ATTEMPT";\r
  \r
 +    private static final String KEY_USERNAME = "USERNAME";\r
 +    private static final String KEY_PASSWORD = "PASSWORD";\r
 +    private static final String KEY_ASYNC_TASK_IN_PROGRESS = "AUTH_IN_PROGRESS";\r
      \r
      /// parameters from EXTRAs in starter Intent\r
      private byte mAction;\r
      private int mAuthStatusText = 0, mAuthStatusIcon = 0;\r
      \r
      private String mAuthToken = "";\r
 +    private AuthenticatorAsyncTask mAsyncTask;\r
  \r
      private boolean mIsFirstAuthAttempt;\r
 -\r
      \r
      /// Identifier of operation in progress which result shouldn't be lost \r
      private long mWaitingForOpId = Long.MAX_VALUE;\r
              mWaitingForOpId = savedInstanceState.getLong(KEY_WAITING_FOR_OP_ID);\r
              mIsFirstAuthAttempt = savedInstanceState.getBoolean(KEY_AUTH_IS_FIRST_ATTEMPT_TAG);\r
          }\r
\r
\r
          \r
          /// load user interface\r
          setContentView(R.layout.account_setup);\r
                      if (\r
                              AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(\r
                                      MainApp.getAccountType()\r
 -                                    ).equals(mAuthTokenType) &&\r
 -                            mHostUrlInput.hasFocus()\r
 -                    ) {\r
 +                            ).equals(mAuthTokenType) &&\r
 +                                    mHostUrlInput.hasFocus()\r
 +                            ) {\r
                          checkOcServer();\r
                      }\r
                  }\r
       * intended to defer the processing of the redirection caught in \r
       * {@link #onNewIntent(Intent)} until {@link #onResume()} \r
       * \r
 -     * See {@link #loadSavedInstanceState(Bundle)}\r
 +     * See {@link #onSaveInstanceState(Bundle)}\r
       */\r
      @Override\r
      protected void onSaveInstanceState(Bundle outState) {\r
          /// authentication\r
          outState.putBoolean(KEY_AUTH_IS_FIRST_ATTEMPT_TAG, mIsFirstAuthAttempt);\r
  \r
 +        /// AsyncTask (User and password)\r
 +        outState.putString(KEY_USERNAME, mUsernameInput.getText().toString());\r
 +        outState.putString(KEY_PASSWORD, mPasswordInput.getText().toString());\r
 +\r
 +        if (mAsyncTask != null) {\r
 +            mAsyncTask.cancel(true);\r
 +            outState.putBoolean(KEY_ASYNC_TASK_IN_PROGRESS, true);\r
 +        } else {\r
 +            outState.putBoolean(KEY_ASYNC_TASK_IN_PROGRESS, false);\r
 +        }\r
 +        mAsyncTask = null;\r
 +\r
          //Log_OC.wtf(TAG, "onSaveInstanceState end" );\r
      }\r
  \r
 +    @Override\r
 +    public void onRestoreInstanceState(Bundle savedInstanceState) {\r
 +        super.onRestoreInstanceState(savedInstanceState);\r
 +\r
 +        // AsyncTask\r
 +        boolean inProgress = savedInstanceState.getBoolean(KEY_ASYNC_TASK_IN_PROGRESS);\r
 +        if (inProgress){\r
 +            mAsyncTask = new AuthenticatorAsyncTask(this);\r
 +            String username = savedInstanceState.getString(KEY_USERNAME);\r
 +            String password = savedInstanceState.getString(KEY_PASSWORD);\r
 +            String[] params = {mServerInfo.mBaseUrl, username, password, mAuthToken, mAuthTokenType};\r
 +            mAsyncTask.execute(params);\r
 +        }\r
 +    }\r
  \r
      /**\r
       * The redirection triggered by the OAuth authentication server as response to the \r
      }\r
  \r
      private void accessRootFolderRemoteOperation(String username, String password) {\r
 -        Intent existenceCheckIntent = new Intent();\r
 -        existenceCheckIntent.setAction(OperationsService.ACTION_EXISTENCE_CHECK);\r
 -        existenceCheckIntent.putExtra(OperationsService.EXTRA_SERVER_URL, mServerInfo.mBaseUrl);\r
 -        existenceCheckIntent.putExtra(OperationsService.EXTRA_REMOTE_PATH, "/");\r
 -        existenceCheckIntent.putExtra(OperationsService.EXTRA_USERNAME, username);\r
 -        existenceCheckIntent.putExtra(OperationsService.EXTRA_PASSWORD, password);\r
 -        existenceCheckIntent.putExtra(OperationsService.EXTRA_AUTH_TOKEN, mAuthToken);\r
 -        \r
 -        if (mOperationsServiceBinder != null) {\r
 -            //Log_OC.wtf(TAG, "starting existenceCheckRemoteOperation..." );\r
 -            mWaitingForOpId = mOperationsServiceBinder.queueNewOperation(existenceCheckIntent);\r
 +        // delete the account if the token has changed\r
 +        if (mAction == ACTION_UPDATE_TOKEN || mAction == ACTION_UPDATE_EXPIRED_TOKEN) {\r
 +            // Remove the cookies in AccountManager\r
 +            mAccountMgr.setUserData(mAccount, Constants.KEY_COOKIES, null);\r
          }\r
 +\r
 +        mAsyncTask = new AuthenticatorAsyncTask(this);\r
 +        String[] params = { mServerInfo.mBaseUrl, username, password, mAuthToken, mAuthTokenType};\r
 +        mAsyncTask.execute(params);\r
 +\r
      }\r
  \r
      /**\r
              onGetOAuthAccessTokenFinish(result);\r
  \r
          } else if (operation instanceof ExistenceCheckRemoteOperation)  {\r
 +            // TODO : remove this response??\r
              //Log_OC.wtf(TAG, "received detection response through callback" );\r
              if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).\r
                      equals(mAuthTokenType)) {\r
                  if (!mUsernameInput.getText().toString().equals(username)) {\r
                      // fail - not a new account, but an existing one; disallow\r
                      result = new RemoteOperationResult(ResultCode.ACCOUNT_NOT_THE_SAME);\r
 -                    /*\r
 -                    OwnCloudClientManagerFactory.getDefaultSingleton().removeClientFor(\r
 -                            new OwnCloudAccount(\r
 -                                    Uri.parse(mServerInfo.mBaseUrl),\r
 -                                    OwnCloudCredentialsFactory.newSamlSsoCredentials(mAuthToken))\r
 -                            );\r
 -                            */\r
                      mAuthToken = "";\r
                      updateAuthStatusIconAndText(result);\r
                      showAuthStatus();\r
                      Log_OC.d(TAG, result.getLogMessage());\r
                  } else {\r
 -                    updateToken();\r
 -                    success = true;\r
 +                    try {\r
 +                        updateAccountAuthentication();\r
 +                        success = true;\r
 +\r
 +                    } catch (AccountNotFoundException e) {\r
 +                        Log_OC.e(TAG, "Account " + mAccount + " was removed!", e);\r
 +                        Toast.makeText(this, R.string.auth_account_does_not_exist, Toast.LENGTH_SHORT).show();\r
 +                        finish();\r
 +                    }\r
                  }\r
              }\r
  \r
      private void onSamlBasedFederatedSingleSignOnAuthorizationStart(RemoteOperationResult result) {\r
          mWaitingForOpId = Long.MAX_VALUE;\r
          dismissDialog(WAIT_DIALOG_TAG);\r
 -
 -        if (result.isIdPRedirection()) {
 +\r
 +        if (result.isIdPRedirection()) {\r
              String targetUrl = mServerInfo.mBaseUrl \r
                      + AccountUtils.getWebdavPath(mServerInfo.mVersion, mAuthTokenType);\r
  \r
      /**\r
       * Processes the result of the server check performed when the user finishes the enter of the\r
       * server URL.\r
 -     * \r
 -     * @param operation     Server check performed.\r
 +     *\r
       * @param result        Result of the check.\r
       */\r
      private void onGetServerInfoFinish(RemoteOperationResult result) {\r
       * Processes the result of the access check performed to try the user credentials.\r
       * \r
       * Creates a new account through the AccountManager.\r
 -     * \r
 -     * @param operation     Access check performed.\r
 +     *\r
       * @param result        Result of the operation.\r
       */\r
      private void onAuthorizationCheckFinish(RemoteOperationResult result) {\r
                  success = createAccount();\r
  \r
              } else {\r
 -                updateToken();\r
 -                success = true;\r
 +                try {\r
 +                    updateAccountAuthentication();\r
 +                    success = true;\r
 +\r
 +                } catch (AccountNotFoundException e) {\r
 +                    Log_OC.e(TAG, "Account " + mAccount + " was removed!", e);\r
 +                    Toast.makeText(this, R.string.auth_account_does_not_exist, Toast.LENGTH_SHORT).show();\r
 +                    finish();\r
 +                }\r
              }\r
  \r
              if (success) {\r
                  finish();\r
              }\r
              \r
 -        } else if (result.isServerFail() || result.isException()) {
 +        } else if (result.isServerFail() || result.isException()) {\r
              /// server errors or exceptions in authorization take to requiring a new check of \r
              /// the server\r
              mServerIsChecked = true;\r
  \r
  \r
      /**\r
 -     * Sets the proper response to get that the Account Authenticator that started this activity \r
 +     * Updates the authentication token.\r
 +     *\r
 +     * Sets the proper response so that the AccountAuthenticator that started this activity\r
       * saves a new authorization token for mAccount.\r
 +     *\r
 +     * Kills the session kept by OwnCloudClientManager so that a new one will created with\r
 +     * the new credentials when needed.\r
       */\r
 -    private void updateToken() {\r
 +    private void updateAccountAuthentication() throws AccountNotFoundException {\r
 +        \r
 +//        OwnCloudClientManagerFactory.getDefaultSingleton().removeClientFor(\r
 +//                new OwnCloudAccount(mAccount, this)\r
 +//        );\r
 +\r
          Bundle response = new Bundle();\r
          response.putString(AccountManager.KEY_ACCOUNT_NAME, mAccount.name);\r
          response.putString(AccountManager.KEY_ACCOUNT_TYPE, mAccount.type);\r
                  mAccountMgr.setAuthToken(mAccount, mAuthTokenType, mAuthToken);\r
              }\r
              /// add user data to the new account; TODO probably can be done in the last parameter \r
 -            //      addAccountExplicitly, or in KEY_USERDATA
 +            //      addAccountExplicitly, or in KEY_USERDATA\r
              mAccountMgr.setUserData(\r
                      mAccount, Constants.KEY_OC_VERSION,    mServerInfo.mVersion.getVersion()\r
              );\r
              mAccountMgr.setUserData(\r
                      mAccount, Constants.KEY_OC_BASE_URL,   mServerInfo.mBaseUrl\r
              );\r
 -
 +\r
              if (isSaml) {\r
                  mAccountMgr.setUserData(mAccount, Constants.KEY_SUPPORTS_SAML_WEB_SSO, "TRUE"); \r
              } else if (isOAuth) {\r
      /**\r
       * Updates the content and visibility state of the icon and text associated\r
       * to the last check on the ownCloud server.\r
 -     * \r
 -     * @param serverStatusText      Resource identifier of the text to show.\r
 -     * @param serverStatusIcon      Resource identifier of the icon to show.\r
++     *\r
       */\r
      private void showServerStatus() {\r
          if (mServerStatusIcon == 0 && mServerStatusText == 0) {\r
      public void doNegativeAuthenticatioDialogClick(){\r
          mIsFirstAuthAttempt = true;\r
      }\r
 +\r
 +\r
 +    @Override\r
 +    public void onAuthenticatorTaskCallback(RemoteOperationResult result) {\r
 +        //Log_OC.wtf(TAG, "received detection response through callback" );\r
 +        if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).\r
 +                equals(mAuthTokenType)) {\r
 +            onSamlBasedFederatedSingleSignOnAuthorizationStart(result);\r
 +\r
 +        } else {\r
 +            onAuthorizationCheckFinish(result);\r
 +        }\r
 +    }\r
  }\r