X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/blobdiff_plain/46d045fd62a7637baa84561ccf2ccb726a02f607..d83491f62df97f912c650f0de499a87d14a494d0:/src/com/owncloud/android/services/OperationsService.java diff --git a/src/com/owncloud/android/services/OperationsService.java b/src/com/owncloud/android/services/OperationsService.java index 2b51660d..6a32af06 100644 --- a/src/com/owncloud/android/services/OperationsService.java +++ b/src/com/owncloud/android/services/OperationsService.java @@ -1,5 +1,7 @@ -/* ownCloud Android client application - * Copyright (C) 2012-2014 ownCloud Inc. +/** + * ownCloud Android client application + * + * Copyright (C) 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, @@ -27,7 +29,6 @@ import com.owncloud.android.MainApp; import com.owncloud.android.R; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; -import com.owncloud.android.files.services.FileDownloader; import com.owncloud.android.lib.common.OwnCloudAccount; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClientManagerFactory; @@ -38,7 +39,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 com.owncloud.android.lib.common.utils.Log_OC; -import com.owncloud.android.lib.resources.files.ExistenceCheckRemoteOperation; import com.owncloud.android.lib.resources.shares.ShareType; import com.owncloud.android.lib.resources.users.GetRemoteUserNameOperation; import com.owncloud.android.operations.common.SyncOperation; @@ -52,7 +52,6 @@ import com.owncloud.android.operations.RenameFileOperation; import com.owncloud.android.operations.SynchronizeFileOperation; import com.owncloud.android.operations.SynchronizeFolderOperation; import com.owncloud.android.operations.UnshareLinkOperation; -import com.owncloud.android.utils.FileStorageUtils; import android.accounts.Account; import android.accounts.AccountsException; @@ -86,26 +85,20 @@ public class OperationsService extends Service { public static final String EXTRA_RESULT = "RESULT"; public static final String EXTRA_NEW_PARENT_PATH = "NEW_PARENT_PATH"; public static final String EXTRA_FILE = "FILE"; + public static final String EXTRA_PASSWORD_SHARE = "PASSWORD_SHARE"; - // TODO review if ALL OF THEM are necessary - 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_COOKIE = "COOKIE"; public static final String ACTION_CREATE_SHARE = "CREATE_SHARE"; public static final String ACTION_UNSHARE = "UNSHARE"; 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_GET_USER_NAME = "GET_USER_NAME"; public static final String ACTION_RENAME = "RENAME"; public static final String ACTION_REMOVE = "REMOVE"; public static final String ACTION_CREATE_FOLDER = "CREATE_FOLDER"; public static final String ACTION_SYNC_FILE = "SYNC_FILE"; public static final String ACTION_SYNC_FOLDER = "SYNC_FOLDER"; // for the moment, just to download - public static final String ACTION_CANCEL_SYNC_FOLDER = "CANCEL_SYNC_FOLDER"; // for the moment, just to download public static final String ACTION_MOVE_FILE = "MOVE_FILE"; public static final String ACTION_OPERATION_ADDED = OperationsService.class.getName() + ".OPERATION_ADDED"; @@ -119,18 +112,11 @@ public class OperationsService extends Service { private static class Target { public Uri mServerUrl = null; public Account mAccount = null; - public String mUsername = null; - public String mPassword = null; - public String mAuthToken = null; public String mCookie = null; - public Target(Account account, Uri serverUrl, String username, String password, String authToken, - String cookie) { + public Target(Account account, Uri serverUrl, String cookie) { mAccount = account; mServerUrl = serverUrl; - mUsername = username; - mPassword = password; - mAuthToken = authToken; mCookie = cookie; } } @@ -146,6 +132,8 @@ public class OperationsService extends Service { @Override public void onCreate() { super.onCreate(); + Log_OC.d(TAG, "Creating service"); + /// First worker thread for most of operations HandlerThread thread = new HandlerThread("Operations thread", Process.THREAD_PRIORITY_BACKGROUND); thread.start(); @@ -167,9 +155,12 @@ public class OperationsService extends Service { */ @Override public int onStartCommand(Intent intent, int flags, int startId) { - // WIP: for the moment, only SYNC_FOLDER and CANCEL_SYNC_FOLDER is expected here; + Log_OC.d(TAG, "Starting command with id " + startId); + + // WIP: for the moment, only SYNC_FOLDER is expected here; // the rest of the operations are requested through the Binder if (ACTION_SYNC_FOLDER.equals(intent.getAction())) { + if (!intent.hasExtra(EXTRA_ACCOUNT) || !intent.hasExtra(EXTRA_REMOTE_PATH)) { Log_OC.e(TAG, "Not enough information provided in intent"); return START_NOT_STICKY; @@ -182,22 +173,12 @@ public class OperationsService extends Service { Pair itemToQueue = newOperation(intent); if (itemToQueue != null) { mSyncFolderHandler.add(account, remotePath, (SynchronizeFolderOperation)itemToQueue.second); - sendBroadcastNewSyncFolder(account, remotePath); Message msg = mSyncFolderHandler.obtainMessage(); msg.arg1 = startId; msg.obj = itemSyncKey; mSyncFolderHandler.sendMessage(msg); } - } else if (ACTION_CANCEL_SYNC_FOLDER.equals(intent.getAction())) { - if (!intent.hasExtra(EXTRA_ACCOUNT) || !intent.hasExtra(EXTRA_FILE)) { - Log_OC.e(TAG, "Not enough information provided in intent"); - return START_NOT_STICKY; - } - Account account = intent.getParcelableExtra(EXTRA_ACCOUNT); - OCFile file = intent.getParcelableExtra(EXTRA_FILE); - // Cancel operation - mSyncFolderHandler.cancel(account,file); } else { Message msg = mOperationsHandler.obtainMessage(); msg.arg1 = startId; @@ -207,22 +188,9 @@ public class OperationsService extends Service { return START_NOT_STICKY; } - /** - * TODO remove this method when "folder synchronization" replaces "folder download"; this is a fast and ugly - * patch. - */ - private void sendBroadcastNewSyncFolder(Account account, String remotePath) { - Intent added = new Intent(FileDownloader.getDownloadAddedMessage()); - added.putExtra(FileDownloader.ACCOUNT_NAME, account.name); - added.putExtra(FileDownloader.EXTRA_REMOTE_PATH, remotePath); - added.putExtra(FileDownloader.EXTRA_FILE_PATH, FileStorageUtils.getSavePath(account.name) + remotePath); - sendStickyBroadcast(added); - } - - @Override public void onDestroy() { - //Log_OC.wtf(TAG, "onDestroy init" ); + Log_OC.v(TAG, "Destroying service" ); // Saving cookies try { OwnCloudClientManagerFactory.getDefaultSingleton(). @@ -239,10 +207,16 @@ public class OperationsService extends Service { e.printStackTrace(); } - //Log_OC.wtf(TAG, "Clear mUndispatchedFinisiedOperations" ); mUndispatchedFinishedOperations.clear(); - - //Log_OC.wtf(TAG, "onDestroy end" ); + + mOperationsBinder = null; + + mOperationsHandler.getLooper().quit(); + mOperationsHandler = null; + + mSyncFolderHandler.getLooper().quit(); + mSyncFolderHandler = null; + super.onDestroy(); } @@ -262,7 +236,7 @@ public class OperationsService extends Service { */ @Override public boolean onUnbind(Intent intent) { - ((OperationsServiceBinder)mOperationsBinder).clearListeners(); + mOperationsBinder.clearListeners(); return false; // not accepting rebinding (default behaviour) } @@ -281,23 +255,23 @@ public class OperationsService extends Service { new ConcurrentHashMap(); private ServiceHandler mServiceHandler = null; - - + public OperationsServiceBinder(ServiceHandler serviceHandler) { mServiceHandler = serviceHandler; } /** - * Cancels an operation + * Cancels a pending or current synchronization. * - * TODO + * @param account ownCloud account where the remote folder is stored. + * @param file A folder in the queue of pending synchronizations */ - public void cancel() { - // TODO + public void cancel(Account account, OCFile file) { + mSyncFolderHandler.cancel(account, file); } - - + + public void clearListeners() { mBoundListeners.clear(); @@ -379,12 +353,15 @@ public class OperationsService extends Service { /** - * Returns True when the file described by 'file' in the ownCloud account 'account' is downloading or waiting to download. + * Returns True when the file described by 'file' in the ownCloud account 'account' is downloading or waiting + * to download. * - * If 'file' is a directory, returns 'true' if some of its descendant files is downloading or waiting to download. + * If 'file' is a directory, returns 'true' if some of its descendant files is downloading or waiting + * to download. * * @param account ownCloud account where the remote file is stored. - * @param file A file that could be affected + * @param remotePath Path of the folder to check if something is synchronizing / downloading / uploading + * inside. */ public boolean isSynchronizing(Account account, String remotePath) { return mSyncFolderHandler.isSynchronizing(account, remotePath); @@ -394,132 +371,6 @@ public class OperationsService extends Service { /** - * SyncFolder worker. Performs the pending operations in the order they were requested. - * - * Created with the Looper of a new thread, started in {@link OperationsService#onCreate()}. - */ - private static class SyncFolderHandler extends Handler { - - // don't make it a final class, and don't remove the static ; lint will warn about a possible memory leak - - OperationsService mService; - - private ConcurrentMap mPendingOperations = - new ConcurrentHashMap(); - private OwnCloudClient mOwnCloudClient = null; - private FileDataStorageManager mStorageManager; - private SynchronizeFolderOperation mCurrentSyncOperation; - - - public SyncFolderHandler(Looper looper, OperationsService service) { - super(looper); - if (service == null) { - throw new IllegalArgumentException("Received invalid NULL in parameter 'service'"); - } - mService = service; - } - - - public boolean isSynchronizing(Account account, String remotePath) { - if (account == null || remotePath == null) return false; - String targetKey = buildRemoteName(account, remotePath); - synchronized (mPendingOperations) { - return (mPendingOperations.containsKey(targetKey)); - } - } - - - @Override - public void handleMessage(Message msg) { - Pair itemSyncKey = (Pair) msg.obj; - doOperation(itemSyncKey.first, itemSyncKey.second); - mService.stopSelf(msg.arg1); - } - - - /** - * Performs the next operation in the queue - */ - private void doOperation(Account account, String remotePath) { - - String syncKey = buildRemoteName(account,remotePath); - - synchronized(mPendingOperations) { - mCurrentSyncOperation = mPendingOperations.get(syncKey); - } - - if (mCurrentSyncOperation != null) { - RemoteOperationResult result = null; - - try { - - OwnCloudAccount ocAccount = new OwnCloudAccount(account, mService); - mOwnCloudClient = OwnCloudClientManagerFactory.getDefaultSingleton(). - getClientFor(ocAccount, mService); - mStorageManager = new FileDataStorageManager( - account, - mService.getContentResolver() - ); - - result = mCurrentSyncOperation.execute(mOwnCloudClient, mStorageManager); - - } catch (AccountsException e) { - Log_OC.e(TAG, "Error while trying to get autorization", e); - } catch (IOException e) { - Log_OC.e(TAG, "Error while trying to get autorization", e); - } finally { - synchronized(mPendingOperations) { - mPendingOperations.remove(syncKey); - } - - mService.dispatchResultToOperationListeners(null, mCurrentSyncOperation, result); - } - } - } - - public void add(Account account, String remotePath, SynchronizeFolderOperation syncFolderOperation){ - String syncKey = buildRemoteName(account,remotePath); - mPendingOperations.putIfAbsent(syncKey,syncFolderOperation); - } - - - /** - * Cancels a pending or current sync operation. - * - * @param account Owncloud account where the remote file is stored. - * @param file File - */ - public void cancel(Account account, OCFile file) { - SynchronizeFolderOperation syncOperation = null; - synchronized (mPendingOperations) { - syncOperation = mPendingOperations.remove(buildRemoteName(account, file.getRemotePath())); - } - if (syncOperation != null) { - syncOperation.cancel(); - } - - /// cancellation of download needs to be done separately in any case; a SynchronizeFolderOperation - // may finish much sooner than the real download of the files in the folder - Intent intent = new Intent(mService, FileDownloader.class); - intent.setAction(FileDownloader.ACTION_CANCEL_FILE_DOWNLOAD); - intent.putExtra(FileDownloader.EXTRA_ACCOUNT, account); - intent.putExtra(FileDownloader.EXTRA_FILE, file); - mService.startService(intent); - } - - /** - * Builds a key from the account and file to download - * - * @param account Account where the file to download is stored - * @param path File path - */ - private String buildRemoteName(Account account, String path) { - return account.name + path; - } - } - - - /** * Operations worker. Performs the pending operations in the order they were requested. * * Created with the Looper of a new thread, started in {@link OperationsService#onCreate()}. @@ -550,6 +401,7 @@ public class OperationsService extends Service { @Override public void handleMessage(Message msg) { nextOperation(); + Log_OC.d(TAG, "Stopping after command with id " + msg.arg1); mService.stopSelf(msg.arg1); } @@ -584,19 +436,10 @@ public class OperationsService extends Service { ); } else { 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 && + if (mLastTarget.mCookie != null && mLastTarget.mCookie.length() > 0) { + // just used for GetUserName + // TODO refactor to run GetUserName as AsyncTask in the context of AuthenticatorActivity credentials = OwnCloudCredentialsFactory.newSamlSsoCredentials( mLastTarget.mCookie); // SAML SSO } @@ -645,7 +488,7 @@ public class OperationsService extends Service { } //sendBroadcastOperationFinished(mLastTarget, mCurrentOperation, result); - mService.dispatchResultToOperationListeners(mLastTarget, mCurrentOperation, result); + mService.dispatchResultToOperationListeners(mCurrentOperation, result); } } @@ -673,26 +516,22 @@ public class OperationsService extends Service { } else { Account account = operationIntent.getParcelableExtra(EXTRA_ACCOUNT); String serverUrl = operationIntent.getStringExtra(EXTRA_SERVER_URL); - String username = operationIntent.getStringExtra(EXTRA_USERNAME); - String password = operationIntent.getStringExtra(EXTRA_PASSWORD); - String authToken = operationIntent.getStringExtra(EXTRA_AUTH_TOKEN); String cookie = operationIntent.getStringExtra(EXTRA_COOKIE); target = new Target( account, (serverUrl == null) ? null : Uri.parse(serverUrl), - username, - password, - authToken, cookie ); String action = operationIntent.getAction(); if (action.equals(ACTION_CREATE_SHARE)) { // Create Share String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); + String password = operationIntent.getStringExtra(EXTRA_PASSWORD_SHARE); Intent sendIntent = operationIntent.getParcelableExtra(EXTRA_SEND_INTENT); if (remotePath.length() > 0) { - operation = new CreateShareOperation(OperationsService.this, remotePath, ShareType.PUBLIC_LINK, - "", false, "", 1, sendIntent); + operation = new CreateShareOperation(OperationsService.this, remotePath, + ShareType.PUBLIC_LINK, + "", false, password, 1, sendIntent); } } else if (action.equals(ACTION_UNSHARE)) { // Unshare file @@ -717,12 +556,6 @@ public class OperationsService extends Service { getString(R.string.oauth2_grant_type), oauth2QueryParameters); - } else if (action.equals(ACTION_EXISTENCE_CHECK)) { - // Existence Check - String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH); - boolean successIfAbsent = operationIntent.getBooleanExtra(EXTRA_SUCCESS_IF_ABSENT, false); - operation = new ExistenceCheckRemoteOperation(remotePath, OperationsService.this, successIfAbsent); - } else if (action.equals(ACTION_GET_USER_NAME)) { // Get User Name operation = new GetRemoteUserNameOperation(); @@ -834,12 +667,12 @@ public class OperationsService extends Service { /** * Notifies the currently subscribed listeners about the end of an operation. * - * @param target Account or URL pointing to an OC server. * @param operation Finished operation. * @param result Result of the operation. */ - private void dispatchResultToOperationListeners( - Target target, final RemoteOperation operation, final RemoteOperationResult result) { + protected void dispatchResultToOperationListeners( + final RemoteOperation operation, final RemoteOperationResult result + ) { int count = 0; Iterator listeners = mOperationsBinder.mBoundListeners.keySet().iterator(); while (listeners.hasNext()) {