Redirect app to login screen when operations in file details view fail due to bad...
authorDavid A. Velasco <dvelasco@solidgear.es>
Thu, 17 Jan 2013 12:01:51 +0000 (13:01 +0100)
committerDavid A. Velasco <dvelasco@solidgear.es>
Thu, 17 Jan 2013 12:01:51 +0000 (13:01 +0100)
src/com/owncloud/android/network/OwnCloudClientUtils.java
src/com/owncloud/android/operations/RemoteOperation.java
src/com/owncloud/android/ui/activity/AuthenticatorActivity.java
src/com/owncloud/android/ui/activity/FileDisplayActivity.java
src/com/owncloud/android/ui/fragment/FileDetailFragment.java
src/com/owncloud/android/ui/fragment/OCFileListFragment.java
src/eu/alefzero/webdav/WebdavClient.java

index 5fb765c..b334fdf 100644 (file)
@@ -44,10 +44,13 @@ import eu.alefzero.webdav.WebdavClient;
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
+import android.accounts.AccountManagerFuture;
 import android.accounts.AuthenticatorException;
 import android.accounts.OperationCanceledException;
+import android.app.Activity;
 import android.content.Context;
 import android.net.Uri;
+import android.os.Bundle;
 import android.util.Log;
 
 public class OwnCloudClientUtils {
@@ -103,6 +106,31 @@ public class OwnCloudClientUtils {
     }
     
     
+    public static WebdavClient createOwnCloudClient (Account account, Context appContext, Activity currentActivity) throws OperationCanceledException, AuthenticatorException, IOException {
+        Uri uri = Uri.parse(AccountUtils.constructFullURLForAccount(appContext, account));
+        WebdavClient client = createOwnCloudClient(uri, appContext);
+        AccountManager am = AccountManager.get(appContext);
+        if (am.getUserData(account, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null) {    // TODO avoid a call to getUserData here
+            AccountManagerFuture<Bundle> future =  am.getAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN, null, currentActivity, null, null);
+            Bundle result = future.getResult();
+            String accessToken = result.getString(AccountManager.KEY_AUTHTOKEN);
+            //String accessToken = am.blockingGetAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN, false);
+            if (accessToken == null) throw new AuthenticatorException("WTF!");
+            client.setBearerCredentials(accessToken);   // TODO not assume that the access token is a bearer token
+            
+        } else {
+            String username = account.name.substring(0, account.name.lastIndexOf('@'));
+            //String password = am.getPassword(account);
+            //String password = am.blockingGetAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_PASSWORD, false);
+            AccountManagerFuture<Bundle> future =  am.getAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_PASSWORD, null, currentActivity, null, null);
+            Bundle result = future.getResult();
+            String password = result.getString(AccountManager.KEY_AUTHTOKEN);
+            client.setBasicCredentials(username, password);
+        }
+        
+        return client;
+    }
+    
     /**
      * Creates a WebdavClient to try a new account before saving it
      * 
index b4f04be..6917cb1 100644 (file)
@@ -23,8 +23,7 @@ import com.owncloud.android.network.OwnCloudClientUtils;
 
 import android.accounts.Account;
 import android.accounts.AccountsException;
-import android.accounts.AuthenticatorException;
-import android.accounts.OperationCanceledException;
+import android.app.Activity;
 import android.content.Context;
 import android.os.Handler;
 import android.util.Log;
@@ -57,6 +56,9 @@ public abstract class RemoteOperation implements Runnable {
        /** Handler to the thread where mListener methods will be called */
        private Handler mListenerHandler = null;
 
+       /** Activity */
+    private Activity mCallerActivity;
+
        
        /**
         *  Abstract method to implement the operation in derived classes.
@@ -119,13 +121,14 @@ public abstract class RemoteOperation implements Runnable {
      * @param listenerHandler   Handler associated to the thread where the methods of the listener objects must be called.
      * @return                  Thread were the remote operation is executed.
      */
-    public final Thread execute(Account account, Context context, OnRemoteOperationListener listener, Handler listenerHandler) {
+    public final Thread execute(Account account, Context context, OnRemoteOperationListener listener, Handler listenerHandler, Activity callerActivity) {
         if (account == null)
             throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Account");
         if (context == null)
             throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Context");
         mAccount = account;
         mContext = context.getApplicationContext();
+        mCallerActivity = callerActivity;
         mClient = null;     // the client instance will be created from mAccount and mContext in the runnerThread to create below
         
         if (listener == null) {
@@ -207,15 +210,18 @@ public abstract class RemoteOperation implements Runnable {
         try{
             if (mClient == null) {
                 if (mAccount != null && mContext != null) {
-                    mClient = OwnCloudClientUtils.createOwnCloudClient(mAccount, mContext);
+                    if (mCallerActivity != null) {
+                        mClient = OwnCloudClientUtils.createOwnCloudClient(mAccount, mContext, mCallerActivity);
+                    } else {
+                        mClient = OwnCloudClientUtils.createOwnCloudClient(mAccount, mContext);
+                    }
                 } else {
                     throw new IllegalStateException("Trying to run a remote operation asynchronously with no client instance or account");
                 }
             }
-            result = run(mClient);
             
         } catch (IOException e) {
-            Log.e(TAG, "Error while trying to access to " + mAccount.name, e);
+            Log.e(TAG, "Error while trying to access to " + mAccount.name, new AccountsException("I/O exception while trying to authorize the account", e));
             result = new RemoteOperationResult(e);
             
         } catch (AccountsException e) {
@@ -223,6 +229,9 @@ public abstract class RemoteOperation implements Runnable {
             result = new RemoteOperationResult(e);
         }
        
+        if (result == null)
+            result = run(mClient);
+        
         final RemoteOperationResult resultToSend = result;
         if (mListenerHandler != null && mListener != null) {
                mListenerHandler.post(new Runnable() {
@@ -233,6 +242,15 @@ public abstract class RemoteOperation implements Runnable {
             });
         }
     }
-       
-       
+
+
+    /**
+     * Returns the current client instance to access the remote server.
+     * 
+     * @return      Current client instance to access the remote server.
+     */
+    public final WebdavClient getClient() {
+        return mClient;
+    }
+
 }
index ecf71e0..fb5c711 100644 (file)
@@ -112,6 +112,8 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
     private boolean mStatusCorrect, mIsSslConn;\r
     private RemoteOperationResult mLastSslUntrustedServerResult;\r
 \r
+    public static final String PARAM_ACCOUNTNAME = "param_Accountname";\r
+    \r
     public static final String PARAM_USERNAME = "param_Username";\r
     public static final String PARAM_HOSTNAME = "param_Hostname";\r
 \r
@@ -196,6 +198,19 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
             mStatusText = mStatusIcon = 0;\r
             mStatusCorrect = false;\r
             mIsSslConn = false;\r
+            \r
+            String accountName = getIntent().getExtras().getString(PARAM_ACCOUNTNAME);\r
+            String tokenType = getIntent().getExtras().getString(AccountAuthenticator.KEY_AUTH_TOKEN_TYPE);\r
+            if (AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN.equals(tokenType)) {\r
+                CheckBox oAuth2Check = (CheckBox) findViewById(R.id.oauth_onOff_check);\r
+                oAuth2Check.setChecked(true);\r
+                changeViewByOAuth2Check(true);\r
+            } \r
+            \r
+            if (accountName != null) {\r
+                ((TextView) findViewById(R.id.account_username)).setText(accountName.substring(0, accountName.lastIndexOf('@')));\r
+                tv.setText(accountName.substring(accountName.lastIndexOf('@') + 1));\r
+            }\r
         }\r
         iv.setOnClickListener(this);\r
         iv2.setOnClickListener(this);\r
index d72fb4d..a717f0c 100644 (file)
@@ -658,7 +658,8 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
                             operation.execute(  AccountUtils.getCurrentOwnCloudAccount(FileDisplayActivity.this), \r
                                                 FileDisplayActivity.this, \r
                                                 FileDisplayActivity.this, \r
-                                                mHandler);\r
+                                                mHandler,\r
+                                                FileDisplayActivity.this);\r
                             \r
                             dialog.dismiss();\r
                             \r
index 64e3cca..8740f83 100644 (file)
 package com.owncloud.android.ui.fragment;\r
 \r
 import java.io.File;\r
-import java.util.ArrayList;\r
-import java.util.List;\r
 \r
-import org.apache.commons.httpclient.methods.GetMethod;\r
-import org.apache.commons.httpclient.methods.PostMethod;\r
-import org.apache.commons.httpclient.methods.StringRequestEntity;\r
-import org.apache.commons.httpclient.params.HttpConnectionManagerParams;\r
-import org.apache.http.HttpStatus;\r
-import org.apache.http.NameValuePair;\r
-import org.apache.http.client.utils.URLEncodedUtils;\r
-import org.apache.http.message.BasicNameValuePair;\r
-import org.apache.http.protocol.HTTP;\r
-import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;\r
-import org.json.JSONObject;\r
+import org.apache.commons.httpclient.Credentials;\r
+import org.apache.commons.httpclient.UsernamePasswordCredentials;\r
 \r
 import android.accounts.Account;\r
 import android.accounts.AccountManager;\r
@@ -66,7 +55,6 @@ import android.widget.TextView;
 import android.widget.Toast;\r
 \r
 import com.actionbarsherlock.app.SherlockFragment;\r
-import com.owncloud.android.AccountUtils;\r
 import com.owncloud.android.DisplayUtils;\r
 import com.owncloud.android.authenticator.AccountAuthenticator;\r
 import com.owncloud.android.datamodel.FileDataStorageManager;\r
@@ -76,6 +64,7 @@ import com.owncloud.android.files.services.FileObserverService;
 import com.owncloud.android.files.services.FileUploader;\r
 import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;\r
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;\r
+import com.owncloud.android.network.BearerCredentials;\r
 import com.owncloud.android.network.OwnCloudClientUtils;\r
 import com.owncloud.android.operations.OnRemoteOperationListener;\r
 import com.owncloud.android.operations.RemoteOperation;\r
@@ -90,10 +79,8 @@ import com.owncloud.android.ui.activity.FileDisplayActivity;
 import com.owncloud.android.ui.activity.TransferServiceGetter;\r
 import com.owncloud.android.ui.dialog.EditNameDialog;\r
 import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener;\r
-import com.owncloud.android.utils.OwnCloudVersion;\r
 \r
 import com.owncloud.android.R;\r
-import eu.alefzero.webdav.WebdavClient;\r
 import eu.alefzero.webdav.WebdavUtils;\r
 \r
 /**\r
@@ -308,7 +295,7 @@ public class FileDetailFragment extends SherlockFragment implements
                     \r
                 } else {\r
                     mLastRemoteOperation = new SynchronizeFileOperation(mFile, null, mStorageManager, mAccount, true, false, getActivity());\r
-                    mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler);\r
+                    mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity());\r
                 \r
                     // update ui \r
                     boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;\r
@@ -422,7 +409,7 @@ public class FileDetailFragment extends SherlockFragment implements
                 mLastRemoteOperation = new RemoveFileOperation( mFile, \r
                                                                 true, \r
                                                                 mStorageManager);\r
-                mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler);\r
+                mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity());\r
                 \r
                 boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;\r
                 getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);\r
@@ -863,7 +850,7 @@ public class FileDetailFragment extends SherlockFragment implements
                                                             mAccount, \r
                                                             newFilename, \r
                                                             new FileDataStorageManager(mAccount, getActivity().getContentResolver()));\r
-            mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler);\r
+            mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity());\r
             boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;\r
             getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);\r
         }\r
@@ -949,7 +936,19 @@ public class FileDetailFragment extends SherlockFragment implements
      */\r
     @Override\r
     public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {\r
-        if (operation.equals(mLastRemoteOperation)) {\r
+        if (!result.isSuccess() && result.getCode() == ResultCode.UNAUTHORIZED) {\r
+            AccountManager am = AccountManager.get(getSherlockActivity());\r
+            //am.invalidateAuthToken(AccountAuthenticator.ACCOUNT_TYPE, OwnCloudClientUtils.getAuthorizationTokenType(operation.getClient().getCredentials()));\r
+            Credentials cred = operation.getClient().getCredentials();\r
+            if (cred instanceof BearerCredentials) {\r
+                am.invalidateAuthToken(AccountAuthenticator.ACCOUNT_TYPE, ((BearerCredentials)cred).getAccessToken());\r
+            } else {\r
+                am.clearPassword(mAccount);\r
+            }\r
+            operation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity());  // need a new client instance, so avoid retry()\r
+                // TODO si el usuario no se autoriza de nuevo, esto genera un bucle infinito; o un error en la creación del objecto cliente\r
+            \r
+        } else {\r
             if (operation instanceof RemoveFileOperation) {\r
                 onRemoveFileOperationFinish((RemoveFileOperation)operation, result);\r
                 \r
index b132892..751de9e 100644 (file)
@@ -316,7 +316,7 @@ public class OCFileListFragment extends FragmentListView implements EditNameDial
             case R.id.download_file_item: {
                 Account account = AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity());
                 RemoteOperation operation = new SynchronizeFileOperation(mTargetFile, null, mContainerActivity.getStorageManager(), account, true, false, getSherlockActivity());
-                operation.execute(account, getSherlockActivity(), mContainerActivity, mHandler);
+                operation.execute(account, getSherlockActivity(), mContainerActivity, mHandler, getSherlockActivity());
                 getSherlockActivity().showDialog(FileDisplayActivity.DIALOG_SHORT_WAIT);
                 return true;
             }
@@ -478,7 +478,7 @@ public class OCFileListFragment extends FragmentListView implements EditNameDial
                                                                 AccountUtils.getCurrentOwnCloudAccount(getActivity()), 
                                                                 newFilename, 
                                                                 mContainerActivity.getStorageManager());
-            operation.execute(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity(), mContainerActivity, mHandler);
+            operation.execute(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity(), mContainerActivity, mHandler, getSherlockActivity());
             getActivity().showDialog(FileDisplayActivity.DIALOG_SHORT_WAIT);
         }
     }
@@ -491,7 +491,7 @@ public class OCFileListFragment extends FragmentListView implements EditNameDial
                 RemoteOperation operation = new RemoveFileOperation( mTargetFile, 
                                                                     true, 
                                                                     mContainerActivity.getStorageManager());
-                operation.execute(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity(), mContainerActivity, mHandler);
+                operation.execute(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity(), mContainerActivity, mHandler, getSherlockActivity());
                 
                 getActivity().showDialog(FileDisplayActivity.DIALOG_SHORT_WAIT);
             }
index d92d097..312b828 100644 (file)
@@ -335,4 +335,10 @@ public class WebdavClient extends HttpClient {
         }\r
         return super.executeMethod(hostconfig, method, state);\r
     }\r
+\r
+    \r
+    public final Credentials getCredentials() {\r
+        return mCredentials;\r
+    }\r
+\r
 }\r