浏览代码

Merge pull request #551 from owncloud/add_cookie_based_session_support

Added cookie based session support
rperezb 10 年之前
父节点
当前提交
0238522c54

+ 1 - 1
owncloud-android-library

@@ -1 +1 @@
-Subproject commit f323dda0445b455af638c7e8e4653c22959adb91
+Subproject commit e72fec72a3138d4e714a9db37eb87cb76a958bdf

+ 1 - 0
res/values/strings.xml

@@ -97,6 +97,7 @@
     <string name="downloader_download_failed_credentials_error">Download failed, you need to relogin</string>
     <string name="common_choose_account">Choose account</string>
     <string name="sync_fail_ticker">Synchronization failed</string>
+    <string name="sync_fail_ticker_unauthorized">Synchronization failed, you need to relogin</string>
     <string name="sync_fail_content">Synchronization of %1$s could not be completed</string>
     <string name="sync_fail_content_unauthorized">Invalid password for %1$s</string>
 	<string name="sync_conflicts_in_favourites_ticker">Conflicts found</string>

+ 25 - 2
src/com/owncloud/android/MainApp.java

@@ -16,22 +16,44 @@
  */
 package com.owncloud.android;
 
+import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
+import com.owncloud.android.lib.common.OwnCloudClientManagerFactory.Policy;
+
 import android.app.Application;
 import android.content.Context;
 /**
  * Main Application of the project
  * 
- * Contains methods to build the "static" strings. These strings were before constants in different classes
+ * Contains methods to build the "static" strings. These strings were before constants in different
+ * classes
  * 
  * @author masensio
+ * @author David A. Velasco
  */
 public class MainApp extends Application {
+    
+    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();
+        
+        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);
+        }
+        
     }
 
     public static Context getAppContext() {
@@ -78,4 +100,5 @@ public class MainApp extends Application {
     public static String getLogName() {
         return getAppContext().getResources().getString(R.string.log_name);
     }
+
 }

+ 22 - 36
src/com/owncloud/android/authentication/AuthenticatorActivity.java

@@ -62,6 +62,9 @@ import com.actionbarsherlock.app.SherlockDialogFragment;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.authentication.SsoWebViewClient.SsoWebViewClientListener;
+import com.owncloud.android.lib.common.OwnCloudAccount;
+import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
+import com.owncloud.android.lib.common.OwnCloudCredentialsFactory;
 import com.owncloud.android.lib.common.accounts.AccountTypeUtils;
 import com.owncloud.android.lib.common.accounts.AccountUtils.Constants;
 import com.owncloud.android.operations.DetectAuthenticationMethodOperation.AuthenticationMethod;
@@ -723,9 +726,7 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
             Intent getServerInfoIntent = new Intent();
             getServerInfoIntent.setAction(OperationsService.ACTION_GET_SERVER_INFO);
             getServerInfoIntent.putExtra(OperationsService.EXTRA_SERVER_URL, uri);
-            getServerInfoIntent.putExtra(OperationsService.EXTRA_AUTH_TOKEN_TYPE, mAuthTokenType);
             if (mOperationsServiceBinder != null) {
-                //Log_OC.wtf(TAG, "checking server..." );
                 mWaitingForOpId = mOperationsServiceBinder.newOperation(getServerInfoIntent);
             } else {
               Log_OC.wtf(TAG, "Server check tried with OperationService unbound!" );
@@ -828,9 +829,6 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
      * the root folder of the ownCloud server.
      */
     private void checkBasicAuthorization() {
-        /// get the path to the root folder through WebDAV from the version server
-        String webdav_path = AccountUtils.getWebdavPath(mServerInfo.mVersion, mAuthTokenType);
-
         /// get basic credentials entered by user
         String username = mUsernameInput.getText().toString();
         String password = mPasswordInput.getText().toString();
@@ -840,26 +838,19 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
                 IndeterminateProgressDialog.newInstance(R.string.auth_trying_to_login, true);
         dialog.show(getSupportFragmentManager(), WAIT_DIALOG_TAG);
 
-        /// test credentials accessing the root folder
-        String remotePath ="";
-        boolean successIfAbsent = false;
-        boolean followRedirects = true;
-        startExistenceCheckRemoteOperation(remotePath, this, successIfAbsent, webdav_path, username, password, followRedirects);
+        /// validate credentials accessing the root folder
+        accessRootFolderRemoteOperation(username, password);
         
     }
 
-    private void startExistenceCheckRemoteOperation(String remotePath, Context context, boolean successIfAbsent, String webdav_path,
-            String username, String password, boolean followRedirects) {
+    private void accessRootFolderRemoteOperation(String username, String password) {
         Intent existenceCheckIntent = new Intent();
         existenceCheckIntent.setAction(OperationsService.ACTION_EXISTENCE_CHECK);
         existenceCheckIntent.putExtra(OperationsService.EXTRA_SERVER_URL, mServerInfo.mBaseUrl);
-        existenceCheckIntent.putExtra(OperationsService.EXTRA_REMOTE_PATH, remotePath);
-        existenceCheckIntent.putExtra(OperationsService.EXTRA_SUCCESS_IF_ABSENT, successIfAbsent);
-        existenceCheckIntent.putExtra(OperationsService.EXTRA_WEBDAV_PATH, webdav_path);
+        existenceCheckIntent.putExtra(OperationsService.EXTRA_REMOTE_PATH, "/");
         existenceCheckIntent.putExtra(OperationsService.EXTRA_USERNAME, username);
         existenceCheckIntent.putExtra(OperationsService.EXTRA_PASSWORD, password);
         existenceCheckIntent.putExtra(OperationsService.EXTRA_AUTH_TOKEN, mAuthToken);
-        existenceCheckIntent.putExtra(OperationsService.EXTRA_FOLLOW_REDIRECTS, followRedirects);
         
         if (mOperationsServiceBinder != null) {
             //Log_OC.wtf(TAG, "starting existenceCheckRemoteOperation..." );
@@ -904,14 +895,8 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
                 IndeterminateProgressDialog.newInstance(R.string.auth_trying_to_login, true);
         dialog.show(getSupportFragmentManager(), WAIT_DIALOG_TAG);
 
-        /// get the path to the root folder through WebDAV from the version server
-        String webdav_path = AccountUtils.getWebdavPath(mServerInfo.mVersion, mAuthTokenType);
-
-        /// test credentials accessing the root folder
-        String remotePath ="";
-        boolean successIfAbsent = false;
-        boolean followRedirections = false;
-        startExistenceCheckRemoteOperation(remotePath, this, successIfAbsent, webdav_path, "", "", followRedirections);
+        /// validate credentials accessing the root folder
+        accessRootFolderRemoteOperation("", "");
 
     }
 
@@ -959,7 +944,15 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
 
                 if (!mUsernameInput.getText().toString().equals(username)) {
                     // fail - not a new account, but an existing one; disallow
-                    result = new RemoteOperationResult(ResultCode.ACCOUNT_NOT_THE_SAME); 
+                    result = new RemoteOperationResult(ResultCode.ACCOUNT_NOT_THE_SAME);
+                    /*
+                    OwnCloudClientManagerFactory.getDefaultSingleton().removeClientFor(
+                            new OwnCloudAccount(
+                                    Uri.parse(mServerInfo.mBaseUrl),
+                                    OwnCloudCredentialsFactory.newSamlSsoCredentials(mAuthToken))
+                            );
+                            */
+                    mAuthToken = "";
                     updateAuthStatusIconAndText(result);
                     showAuthStatus();
                     Log_OC.d(TAG, result.getLogMessage());
@@ -1284,8 +1277,7 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
         mWaitingForOpId = Long.MAX_VALUE;
         dismissDialog(WAIT_DIALOG_TAG);
 
-        String webdav_path = AccountUtils.getWebdavPath(mServerInfo.mVersion, mAuthTokenType);
-        if (result.isSuccess() && webdav_path != null) {
+        if (result.isSuccess()) {
             /// be gentle with the user
             IndeterminateProgressDialog dialog = 
                     IndeterminateProgressDialog.newInstance(R.string.auth_trying_to_login, true);
@@ -1298,10 +1290,7 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
             //mAuthToken = ((OAuth2GetAccessToken)operation).getResultTokenMap().get(OAuth2Constants.KEY_ACCESS_TOKEN);
             Log_OC.d(TAG, "Got ACCESS TOKEN: " + mAuthToken);
             
-            String remotePath ="";
-            boolean successIfAbsent = false;
-            boolean followRedirects = true;
-            startExistenceCheckRemoteOperation(remotePath, this, successIfAbsent, webdav_path, "", "", followRedirects);
+            accessRootFolderRemoteOperation("", "");
 
         } else {
             updateAuthStatusIconAndText(result);
@@ -1417,11 +1406,9 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
         String username = mUsernameInput.getText().toString().trim();
         if (isOAuth) {
             username = "OAuth_user" + (new java.util.Random(System.currentTimeMillis())).nextLong();
-        }            
-        String accountName = username + "@" + uri.getHost();
-        if (uri.getPort() >= 0) {
-            accountName += ":" + uri.getPort();
         }
+        String accountName = com.owncloud.android.lib.common.accounts.AccountUtils.
+                buildAccountName(uri, username);
         Account newAccount = new Account(accountName, MainApp.getAccountType());
         if (AccountUtils.exists(newAccount, getApplicationContext())) {
             // fail - not a new account, but an existing one; disallow
@@ -1642,7 +1629,6 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
         getUserNameIntent.setAction(OperationsService.ACTION_GET_USER_NAME);
         getUserNameIntent.putExtra(OperationsService.EXTRA_SERVER_URL, mServerInfo.mBaseUrl);
         getUserNameIntent.putExtra(OperationsService.EXTRA_COOKIE, sessionCookie);
-        getUserNameIntent.putExtra(OperationsService.EXTRA_FOLLOW_REDIRECTS, followRedirects);
         
         if (mOperationsServiceBinder != null) {
             //Log_OC.wtf(TAG, "starting getRemoteUserNameOperation..." );

+ 0 - 75
src/com/owncloud/android/authentication/OwnCloudAccount.java

@@ -1,75 +0,0 @@
-/* ownCloud Android client application
- *   Copyright (C) 2014 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package com.owncloud.android.authentication;
-
-import android.accounts.Account;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Account with extra information specific for ownCloud accounts.
- * 
- * TODO integrate in the main app
- * 
- * @author David A. Velasco
- */
-public class OwnCloudAccount extends Account {
-
-	private String mAuthTokenType;
-
-	public OwnCloudAccount(String name, String type, String authTokenType) {
-		super(name, type);
-		// TODO validate authTokentype as supported
-		mAuthTokenType = authTokenType;
-	}
-	
-    /**
-     * Reconstruct from parcel
-     * 
-     * @param source The source parcel
-     */
-	public OwnCloudAccount(Parcel source) {
-		super(source);
-        mAuthTokenType = source.readString();
-	}
-	
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-    	super.writeToParcel(dest, flags);
-        dest.writeString(mAuthTokenType);
-    }
-	
-	
-	public String getAuthTokenType() {
-		return mAuthTokenType;
-	}
-
-	
-    public static final Parcelable.Creator<OwnCloudAccount> CREATOR = new Parcelable.Creator<OwnCloudAccount>() {
-        @Override
-        public OwnCloudAccount createFromParcel(Parcel source) {
-            return new OwnCloudAccount(source);
-        }
-
-        @Override
-        public OwnCloudAccount [] newArray(int size) {
-            return new OwnCloudAccount[size];
-        }
-    };
-	
-}

+ 12 - 7
src/com/owncloud/android/files/services/FileDownloader.java

@@ -34,14 +34,15 @@ import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 
 import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
-import com.owncloud.android.lib.common.OwnCloudClientFactory;
+import com.owncloud.android.lib.common.OwnCloudAccount;
 import com.owncloud.android.lib.common.OwnCloudClient;
+import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
 import com.owncloud.android.notifications.NotificationBuilderWithProgressBar;
 import com.owncloud.android.notifications.NotificationDelayer;
-import com.owncloud.android.operations.DownloadFileOperation;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
 import com.owncloud.android.lib.resources.files.FileUtils;
+import com.owncloud.android.operations.DownloadFileOperation;
 import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.activity.FileDisplayActivity;
 import com.owncloud.android.ui.preview.PreviewImageActivity;
@@ -347,8 +348,11 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
                 /// prepare client object to send the request to the ownCloud server
                 if (mDownloadClient == null || !mLastAccount.equals(mCurrentDownload.getAccount())) {
                     mLastAccount = mCurrentDownload.getAccount();
-                    mStorageManager = new FileDataStorageManager(mLastAccount, getContentResolver());
-                    mDownloadClient = OwnCloudClientFactory.createOwnCloudClient(mLastAccount, getApplicationContext());
+                    mStorageManager = 
+                            new FileDataStorageManager(mLastAccount, getContentResolver());
+                    OwnCloudAccount ocAccount = new OwnCloudAccount(mLastAccount, this);
+                    mDownloadClient = OwnCloudClientManagerFactory.getDefaultSingleton().
+                            getClientFor(ocAccount, this);
                 }
 
                 /// perform the download
@@ -466,9 +470,10 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
             int tickerId = (downloadResult.isSuccess()) ? R.string.downloader_download_succeeded_ticker : 
                 R.string.downloader_download_failed_ticker;
             
-            boolean needsToUpdateCredentials = (downloadResult.getCode() == ResultCode.UNAUTHORIZED ||
-                                                  (downloadResult.isIdPRedirection()
-                                                        && mDownloadClient.getCredentials() == null));
+            boolean needsToUpdateCredentials = (
+                    downloadResult.getCode() == ResultCode.UNAUTHORIZED ||
+                    downloadResult.isIdPRedirection()
+            );
             tickerId = (needsToUpdateCredentials) ? 
                     R.string.downloader_download_failed_credentials_error : tickerId;
             

+ 11 - 6
src/com/owncloud/android/files/services/FileUploader.java

@@ -48,8 +48,9 @@ import com.owncloud.android.lib.resources.files.FileUtils;
 import com.owncloud.android.lib.resources.status.OwnCloudVersion;
 import com.owncloud.android.lib.common.accounts.AccountUtils.Constants;
 import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
-import com.owncloud.android.lib.common.OwnCloudClientFactory;
+import com.owncloud.android.lib.common.OwnCloudAccount;
 import com.owncloud.android.lib.common.OwnCloudClient;
+import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
 import com.owncloud.android.ui.activity.FailedUploadActivity;
 import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.activity.FileDisplayActivity;
@@ -486,8 +487,11 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
                 /// prepare client object to send requests to the ownCloud server
                 if (mUploadClient == null || !mLastAccount.equals(mCurrentUpload.getAccount())) {
                     mLastAccount = mCurrentUpload.getAccount();
-                    mStorageManager = new FileDataStorageManager(mLastAccount, getContentResolver());
-                    mUploadClient = OwnCloudClientFactory.createOwnCloudClient(mLastAccount, getApplicationContext());
+                    mStorageManager = 
+                            new FileDataStorageManager(mLastAccount, getContentResolver());
+                    OwnCloudAccount ocAccount = new OwnCloudAccount(mLastAccount, this);
+                    mUploadClient = OwnCloudClientManagerFactory.getDefaultSingleton().
+                            getClientFor(ocAccount, this);
                 }
                 
                 /// check the existence of the parent folder for the file to upload
@@ -737,9 +741,10 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
             String content = null;
 
             // check credentials error
-            boolean needsToUpdateCredentials = (uploadResult.getCode() == ResultCode.UNAUTHORIZED || 
-                    (uploadResult.isIdPRedirection() &&
-                            mUploadClient.getCredentials() == null));
+            boolean needsToUpdateCredentials = (
+                    uploadResult.getCode() == ResultCode.UNAUTHORIZED || 
+                    uploadResult.isIdPRedirection()
+            );
             tickerId = (needsToUpdateCredentials) ? 
                     R.string.uploader_upload_failed_credentials_error : tickerId;
 

+ 5 - 7
src/com/owncloud/android/operations/DetectAuthenticationMethodOperation.java

@@ -64,7 +64,6 @@ public class DetectAuthenticationMethodOperation extends RemoteOperation {
     }
     
     private Context mContext;
-    private String mWebDavUrl;
     
     /**
      * Constructor
@@ -72,9 +71,8 @@ public class DetectAuthenticationMethodOperation extends RemoteOperation {
      * @param context       Android context of the caller.
      * @param webdavUrl
      */
-    public DetectAuthenticationMethodOperation(Context context, String webdavUrl) {
+    public DetectAuthenticationMethodOperation(Context context) {
         mContext = context;
-        mWebDavUrl = webdavUrl;
     }
     
 
@@ -93,15 +91,15 @@ public class DetectAuthenticationMethodOperation extends RemoteOperation {
         AuthenticationMethod authMethod = AuthenticationMethod.UNKNOWN;
         
         RemoteOperation operation = new ExistenceCheckRemoteOperation("", mContext, false);
-        client.setWebdavUri(Uri.parse(mWebDavUrl));
-        client.setBasicCredentials("", "");
+        client.clearCredentials();
         client.setFollowRedirects(false);
         
         // try to access the root folder, following redirections but not SAML SSO redirections
         result = operation.execute(client);
         String redirectedLocation = result.getRedirectedLocation(); 
-        while (redirectedLocation != null && redirectedLocation.length() > 0 && !result.isIdPRedirection()) {
-            client.setWebdavUri(Uri.parse(result.getRedirectedLocation()));
+        while (redirectedLocation != null && redirectedLocation.length() > 0 && 
+                !result.isIdPRedirection()) {
+            client.setBaseUri(Uri.parse(result.getRedirectedLocation()));
             result = operation.execute(client);
             redirectedLocation = result.getRedirectedLocation();
         } 

+ 4 - 10
src/com/owncloud/android/operations/GetServerInfoOperation.java

@@ -53,7 +53,6 @@ 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;
@@ -62,14 +61,11 @@ public class GetServerInfoOperation extends RemoteOperation {
      * 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) {
+    public GetServerInfoOperation(String url, Context context) {
         mUrl = trimWebdavSuffix(url);
-        mAuthTokenType = authTokenType;
         mContext = context;
         
         mResultData = new ServerInfo();
@@ -87,9 +83,9 @@ public class GetServerInfoOperation extends RemoteOperation {
 	protected RemoteOperationResult run(OwnCloudClient client) {
 	    
 	    // first: check the status of the server (including its version)
-	    GetRemoteStatusOperation getStatus = new GetRemoteStatusOperation(mUrl, mContext);
+	    GetRemoteStatusOperation getStatus = new GetRemoteStatusOperation(mContext);
 	    RemoteOperationResult result = getStatus.execute(client);
-
+	    
         if (result.isSuccess()) {
             // second: get authentication method required by the server
             mResultData.mVersion = (OwnCloudVersion)(result.getData().get(0));
@@ -114,10 +110,8 @@ public class GetServerInfoOperation extends RemoteOperation {
 	
     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);
+                new DetectAuthenticationMethodOperation(mContext);
         return operation.execute(client);
     }
     

+ 2 - 1
src/com/owncloud/android/operations/common/SyncOperation.java

@@ -23,7 +23,6 @@ import com.owncloud.android.lib.common.operations.OnRemoteOperationListener;
 import com.owncloud.android.lib.common.operations.RemoteOperation;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 
-import android.app.Activity;
 import android.content.Context;
 import android.os.Handler;
 
@@ -97,6 +96,7 @@ public abstract class SyncOperation extends RemoteOperation {
      * @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 Thread execute(FileDataStorageManager storageManager, Context context, OnRemoteOperationListener listener, Handler listenerHandler, Activity callerActivity) {
         if (storageManager == null) {
             throw new IllegalArgumentException("Trying to execute a sync operation with a NULL storage manager");
@@ -107,6 +107,7 @@ public abstract class SyncOperation extends RemoteOperation {
         mStorageManager = storageManager;
         return super.execute(storageManager.getAccount(), context, listener, listenerHandler, callerActivity);
     }
+    */
 
     
 	/**

+ 56 - 33
src/com/owncloud/android/services/OperationsService.java

@@ -23,10 +23,15 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.ConcurrentMap;
 
+import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.FileDataStorageManager;
-import com.owncloud.android.lib.common.OwnCloudClientFactory;
+import com.owncloud.android.lib.common.OwnCloudAccount;
 import com.owncloud.android.lib.common.OwnCloudClient;
+import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
+import com.owncloud.android.lib.common.OwnCloudCredentials;
+import com.owncloud.android.lib.common.OwnCloudCredentialsFactory;
+import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
 import com.owncloud.android.lib.common.operations.OnRemoteOperationListener;
 import com.owncloud.android.lib.common.operations.RemoteOperation;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
@@ -46,6 +51,8 @@ import com.owncloud.android.utils.Log_OC;
 
 import android.accounts.Account;
 import android.accounts.AccountsException;
+import android.accounts.AuthenticatorException;
+import android.accounts.OperationCanceledException;
 import android.app.Service;
 import android.content.Intent;
 import android.net.Uri;
@@ -64,7 +71,6 @@ 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";
@@ -75,12 +81,10 @@ public class OperationsService extends Service {
     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";
     public static final String EXTRA_PASSWORD = "PASSWORD";
     public static final String EXTRA_AUTH_TOKEN = "AUTH_TOKEN";
-    public static final String EXTRA_FOLLOW_REDIRECTS = "FOLLOW_REDIRECTS";
     public static final String EXTRA_COOKIE = "COOKIE";
     
     public static final String ACTION_CREATE_SHARE = "CREATE_SHARE";
@@ -107,22 +111,18 @@ public class OperationsService extends Service {
     private static class Target {
         public Uri mServerUrl = null;
         public Account mAccount = null;
-        public String mWebDavUrl = null;
         public String mUsername = null;
         public String mPassword = null;
         public String mAuthToken = null;
-        public boolean mFollowRedirects = true;
         public String mCookie = null;
         
-        public Target(Account account, Uri serverUrl, String webdavUrl, String username, String password, String authToken,
-                boolean followRedirects, String cookie) {
+        public Target(Account account, Uri serverUrl, String username, String password, String authToken,
+                String cookie) {
             mAccount = account;
             mServerUrl = serverUrl;
-            mWebDavUrl = webdavUrl;
             mUsername = username;
             mPassword = password;
             mAuthToken = authToken;
-            mFollowRedirects = followRedirects;
             mCookie = cookie;
         }
     }
@@ -172,8 +172,25 @@ public class OperationsService extends Service {
     @Override
     public void onDestroy() {
         //Log_OC.wtf(TAG, "onDestroy init" );
+        // Saving cookies
+        try {
+            OwnCloudClientManagerFactory.getDefaultSingleton().
+                saveAllClients(this, MainApp.getAccountType());
+            
+            // TODO - get rid of these exceptions
+        } catch (AccountNotFoundException e) {
+            e.printStackTrace();
+        } catch (AuthenticatorException e) {
+            e.printStackTrace();
+        } catch (OperationCanceledException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        
         //Log_OC.wtf(TAG, "Clear mUndispatchedFinisiedOperations" );
         mUndispatchedFinishedOperations.clear();
+        
         //Log_OC.wtf(TAG, "onDestroy end" );
         super.onDestroy();
     }
@@ -281,21 +298,16 @@ public class OperationsService extends Service {
                 } else {
                     Account account = operationIntent.getParcelableExtra(EXTRA_ACCOUNT);
                     String serverUrl = operationIntent.getStringExtra(EXTRA_SERVER_URL);
-                    String webDavPath = operationIntent.getStringExtra(EXTRA_WEBDAV_PATH);
-                    String webDavUrl = serverUrl + webDavPath;
                     String username = operationIntent.getStringExtra(EXTRA_USERNAME);
                     String password = operationIntent.getStringExtra(EXTRA_PASSWORD);
                     String authToken = operationIntent.getStringExtra(EXTRA_AUTH_TOKEN);
-                    boolean followRedirects = operationIntent.getBooleanExtra(EXTRA_FOLLOW_REDIRECTS, true);
                     String cookie = operationIntent.getStringExtra(EXTRA_COOKIE);
                     target = new Target(
                             account, 
                             (serverUrl == null) ? null : Uri.parse(serverUrl),
-                            ((webDavPath == null) || (serverUrl == null)) ? null : webDavUrl,
                             username,
                             password,
                             authToken,
-                            followRedirects,
                             cookie
                     );
                     
@@ -318,10 +330,7 @@ public class OperationsService extends Service {
                         
                     } 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);
+                        operation = new GetServerInfoOperation(serverUrl, OperationsService.this);
                         
                     } else if (action.equals(ACTION_OAUTH2_GET_ACCESS_TOKEN)) {
                         /// GET ACCESS TOKEN to the OAuth server
@@ -336,7 +345,7 @@ public class OperationsService extends Service {
                     } else if (action.equals(ACTION_EXISTENCE_CHECK)) {
                         // Existence Check 
                         String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
-                        boolean successIfAbsent = operationIntent.getBooleanExtra(EXTRA_SUCCESS_IF_ABSENT, true);
+                        boolean successIfAbsent = operationIntent.getBooleanExtra(EXTRA_SUCCESS_IF_ABSENT, false);
                         operation = new ExistenceCheckRemoteOperation(remotePath, OperationsService.this, successIfAbsent);
                         
                     } else if (action.equals(ACTION_GET_USER_NAME)) {
@@ -453,21 +462,35 @@ public class OperationsService extends Service {
                 if (mLastTarget == null || !mLastTarget.equals(next.first)) {
                     mLastTarget = next.first;
                     if (mLastTarget.mAccount != null) {
-                        mOwnCloudClient = OwnCloudClientFactory.createOwnCloudClient(mLastTarget.mAccount, getApplicationContext());
-                        mStorageManager = new FileDataStorageManager(mLastTarget.mAccount, getContentResolver());
+                        OwnCloudAccount ocAccount = new OwnCloudAccount(mLastTarget.mAccount, this);
+                        mOwnCloudClient = OwnCloudClientManagerFactory.getDefaultSingleton().
+                                getClientFor(ocAccount, this);
+                        mStorageManager = 
+                                new FileDataStorageManager(
+                                        mLastTarget.mAccount, 
+                                        getContentResolver());
                     } else {
-                        mOwnCloudClient = OwnCloudClientFactory.createOwnCloudClient(mLastTarget.mServerUrl, getApplicationContext(), 
-                                mLastTarget.mFollowRedirects);    // this is not good enough
-                        if (mLastTarget.mWebDavUrl != null) {
-                            mOwnCloudClient.setWebdavUri(Uri.parse(mLastTarget.mWebDavUrl));
-                        }
-                        if (mLastTarget.mUsername != null && mLastTarget.mPassword != null) {
-                            mOwnCloudClient.setBasicCredentials(mLastTarget.mUsername, mLastTarget.mPassword);
-                        } else if (mLastTarget.mAuthToken != null) {
-                            mOwnCloudClient.setBearerCredentials(mLastTarget.mAuthToken);
-                        } else if (mLastTarget.mCookie != null) {
-                            mOwnCloudClient.setSsoSessionCookie(mLastTarget.mCookie);
+                        OwnCloudCredentials credentials = null;
+                        if (mLastTarget.mUsername != null && 
+                                mLastTarget.mUsername.length() > 0) {
+                            credentials = OwnCloudCredentialsFactory.newBasicCredentials(
+                                    mLastTarget.mUsername, 
+                                    mLastTarget.mPassword);  // basic
+                            
+                        } else if (mLastTarget.mAuthToken != null && 
+                                mLastTarget.mAuthToken.length() > 0) {
+                            credentials = OwnCloudCredentialsFactory.newBearerCredentials(
+                                    mLastTarget.mAuthToken);  // bearer token
+                            
+                        } else if (mLastTarget.mCookie != null &&
+                                mLastTarget.mCookie.length() > 0) {
+                            credentials = OwnCloudCredentialsFactory.newSamlSsoCredentials(
+                                    mLastTarget.mCookie); // SAML SSO
                         }
+                        OwnCloudAccount ocAccount = new OwnCloudAccount(
+                                mLastTarget.mServerUrl, credentials);
+                        mOwnCloudClient = OwnCloudClientManagerFactory.getDefaultSingleton().
+                                getClientFor(ocAccount, this);
                         mStorageManager = null;
                     }
                 }

+ 5 - 3
src/com/owncloud/android/syncadapter/AbstractOwnCloudSyncAdapter.java

@@ -27,9 +27,9 @@ import org.apache.http.client.ClientProtocolException;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.lib.common.accounts.AccountUtils;
 import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
-import com.owncloud.android.lib.common.OwnCloudClientFactory;
+import com.owncloud.android.lib.common.OwnCloudAccount;
 import com.owncloud.android.lib.common.OwnCloudClient;
-
+import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
@@ -102,7 +102,9 @@ public abstract class AbstractOwnCloudSyncAdapter extends
 
     protected void initClientForCurrentAccount() throws OperationCanceledException, AuthenticatorException, IOException, AccountNotFoundException {
         AccountUtils.constructFullURLForAccount(getContext(), account);
-        mClient = OwnCloudClientFactory.createOwnCloudClient(account, getContext());
+        OwnCloudAccount ocAccount = new OwnCloudAccount(account, getContext());
+        mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
+                getClientFor(ocAccount, getContext());
     }
     
     protected OwnCloudClient getClient() {

+ 13 - 14
src/com/owncloud/android/syncadapter/FileSyncAdapter.java

@@ -292,10 +292,9 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
             
         } else {
             // in failures, the statistics for the global result are updated
-            if (result.getCode() == RemoteOperationResult.ResultCode.UNAUTHORIZED ||
-                    ( result.isIdPRedirection() &&
-                            getClient().getCredentials() == null      )) {
-                            //MainApp.getAuthTokenTypeSamlSessionCookie().equals(getClient().getAuthTokenType()))) {
+            if (    result.getCode() == RemoteOperationResult.ResultCode.UNAUTHORIZED ||
+                    result.isIdPRedirection()
+                ) {
                 mSyncResult.stats.numAuthExceptions++;
                 
             } else if (result.getException() instanceof DavException) {
@@ -383,16 +382,12 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
      */
     private void notifyFailedSynchronization() {
         NotificationCompat.Builder notificationBuilder = createNotificationBuilder();
-        notificationBuilder.setTicker(i18n(R.string.sync_fail_ticker));
-        boolean needsToUpdateCredentials = (mLastFailedResult != null && 
-                                             (  mLastFailedResult.getCode() == ResultCode.UNAUTHORIZED ||
-                                                ( mLastFailedResult.isIdPRedirection() && 
-                                                  getClient().getCredentials() == null      )
-                                                 //MainApp.getAuthTokenTypeSamlSessionCookie().equals(getClient().getAuthTokenType()))
-                                             )
-                                           );
-        // TODO put something smart in the contentIntent below for all the possible errors
-        notificationBuilder.setContentTitle(i18n(R.string.sync_fail_ticker));
+        boolean needsToUpdateCredentials = (
+                mLastFailedResult != null && (  
+                        mLastFailedResult.getCode() == ResultCode.UNAUTHORIZED ||
+                        mLastFailedResult.isIdPRedirection()
+                )
+        );
         if (needsToUpdateCredentials) {
             // let the user update credentials with one click
             Intent updateAccountCredentials = new Intent(getContext(), AuthenticatorActivity.class);
@@ -402,12 +397,16 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
             updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
             updateAccountCredentials.addFlags(Intent.FLAG_FROM_BACKGROUND);
             notificationBuilder
+                .setTicker(i18n(R.string.sync_fail_ticker_unauthorized))
+                .setContentTitle(i18n(R.string.sync_fail_ticker_unauthorized))
                 .setContentIntent(PendingIntent.getActivity(
                     getContext(), (int)System.currentTimeMillis(), updateAccountCredentials, PendingIntent.FLAG_ONE_SHOT
                 ))
                 .setContentText(i18n(R.string.sync_fail_content_unauthorized, getAccount().name));
         } else {
             notificationBuilder
+                .setTicker(i18n(R.string.sync_fail_ticker))
+                .setContentTitle(i18n(R.string.sync_fail_ticker))
                 .setContentText(i18n(R.string.sync_fail_content, getAccount().name));
         }
         

+ 2 - 1
src/com/owncloud/android/ui/activity/FileActivity.java

@@ -195,6 +195,7 @@ implements OnRemoteOperationListener, ComponentsGetter {
     
     @Override
     protected void onPause()  {
+        
         if (mOperationsServiceBinder != null) {
             mOperationsServiceBinder.removeOperationListener(this);
         }
@@ -464,7 +465,7 @@ implements OnRemoteOperationListener, ComponentsGetter {
         } 
     }
 
-    private void requestCredentialsUpdate() {
+    protected void requestCredentialsUpdate() {
         Intent updateAccountCredentials = new Intent(this, AuthenticatorActivity.class);
         updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACCOUNT, getAccount());
         updateAccountCredentials.putExtra(

+ 57 - 4
src/com/owncloud/android/ui/activity/FileDisplayActivity.java

@@ -19,8 +19,12 @@
 package com.owncloud.android.ui.activity;
 
 import java.io.File;
+import java.io.IOException;
 
 import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AuthenticatorException;
+import android.accounts.OperationCanceledException;
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.ProgressDialog;
@@ -68,6 +72,11 @@ import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
 import com.owncloud.android.operations.CreateFolderOperation;
 
+import com.owncloud.android.lib.common.OwnCloudAccount;
+import com.owncloud.android.lib.common.OwnCloudClient;
+import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
+import com.owncloud.android.lib.common.OwnCloudCredentials;
+import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException;
 import com.owncloud.android.lib.common.network.CertificateCombinedException;
 import com.owncloud.android.lib.common.operations.RemoteOperation;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
@@ -918,10 +927,54 @@ FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener
                         
                         mSyncInProgress = (!FileSyncAdapter.EVENT_FULL_SYNC_END.equals(event) && !SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED.equals(event));
                                 
+                        if (SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED.
+                                    equals(event) &&
+                                /// TODO refactor and make common
+                                synchResult != null && !synchResult.isSuccess() &&  
+                                (synchResult.getCode() == ResultCode.UNAUTHORIZED   || 
+                                    synchResult.isIdPRedirection()                  ||
+                                    (synchResult.isException() && synchResult.getException() 
+                                            instanceof AuthenticatorException))) {
+
+                            OwnCloudClient client = null;
+                            try {
+                                OwnCloudAccount ocAccount = 
+                                        new OwnCloudAccount(getAccount(), context);
+                                client = (OwnCloudClientManagerFactory.getDefaultSingleton().
+                                        removeClientFor(ocAccount));
+                                // TODO get rid of these exceptions
+                            } catch (AccountNotFoundException e) {
+                                e.printStackTrace();
+                            } catch (AuthenticatorException e) {
+                                e.printStackTrace();
+                            } catch (OperationCanceledException e) {
+                                e.printStackTrace();
+                            } catch (IOException e) {
+                                e.printStackTrace();
+                            }
+                            
+                            if (client != null) {
+                                OwnCloudCredentials cred = client.getCredentials();
+                                if (cred != null) {
+                                    AccountManager am = AccountManager.get(context);
+                                    if (cred.authTokenExpires()) {
+                                        am.invalidateAuthToken(
+                                                getAccount().type, 
+                                                cred.getAuthToken()
+                                        );
+                                    } else {
+                                        am.clearPassword(getAccount());
+                                    }
+                                }
+                            }
+                            
+                            requestCredentialsUpdate();
+                            
                         }
-                        removeStickyBroadcast(intent);
-                        Log_OC.d(TAG, "Setting progress visibility to " + mSyncInProgress);
-                        setSupportProgressBarIndeterminateVisibility(mSyncInProgress /*|| mRefreshSharesInProgress*/);
+                    }
+                    removeStickyBroadcast(intent);
+                    Log_OC.d(TAG, "Setting progress visibility to " + mSyncInProgress);
+                    setSupportProgressBarIndeterminateVisibility(mSyncInProgress /*|| mRefreshSharesInProgress*/);
                         
                 }
                 
@@ -1478,7 +1531,7 @@ FileFragment.ContainerActivity, OnNavigationListener, OnSslUntrustedCertListener
                                                                         getAccount(), 
                                                                         getApplicationContext()
                                                                       );
-        synchFolderOp.execute(getAccount(), this, null, null, this);
+        synchFolderOp.execute(getAccount(), this, null, null);
         
         setSupportProgressBarIndeterminateVisibility(true);
     }

+ 0 - 9
src/com/owncloud/android/ui/activity/Uploader.java

@@ -329,19 +329,10 @@ public class Uploader extends ListActivity implements OnItemClickListener, andro
 
     public void uploadFiles() {
         try {
-            //OwnCloudClient webdav = OwnCloudClientUtils.createOwnCloudClient(mAccount, getApplicationContext());
 
             ArrayList<String> local = new ArrayList<String>();
             ArrayList<String> remote = new ArrayList<String>();
             
-            /* TODO - mCreateDir can never be true at this moment; we will replace wdc.createDirectory by CreateFolderOperation when that is fixed 
-            OwnCloudClient wdc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getApplicationContext());
-            // create last directory in path if necessary
-            if (mCreateDir) {
-                wdc.createDirectory(mUploadPath);
-            }
-            */
-            
             // this checks the mimeType 
             for (Parcelable mStream : mStreamsToUpload) {