diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1c47ced4b8f66e63166711e90003ef99f349d1ca..74e129aa668e3cead4441cba14f6d9a283f75909 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -83,14 +83,6 @@ - - - - - @@ -113,5 +105,13 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/java/foundation/e/drive/receivers/AccountRemoveCallbackReceiver.java b/app/src/main/java/foundation/e/drive/receivers/AccountRemoveCallbackReceiver.java new file mode 100644 index 0000000000000000000000000000000000000000..6a95cef6e38de915298bfccbb4c41d288ec34d39 --- /dev/null +++ b/app/src/main/java/foundation/e/drive/receivers/AccountRemoveCallbackReceiver.java @@ -0,0 +1,137 @@ +/* + * Copyright © ECORP SAS 2023. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Public License v3.0 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/gpl.html + */ + +package foundation.e.drive.receivers; + +import static foundation.e.drive.utils.AppConstants.INITIALFOLDERS_NUMBER; +import static foundation.e.drive.utils.AppConstants.INITIALIZATION_HAS_BEEN_DONE; + +import android.accounts.AccountManager; +import android.annotation.SuppressLint; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; + +import androidx.annotation.NonNull; + +import java.io.File; + +import foundation.e.drive.EdriveApplication; +import foundation.e.drive.database.DbHelper; +import foundation.e.drive.database.FailedSyncPrefsManager; +import foundation.e.drive.services.InitializerService; +import foundation.e.drive.services.ObserverService; +import foundation.e.drive.services.SynchronizationService; +import foundation.e.drive.utils.AppConstants; +import timber.log.Timber; + +public class AccountRemoveCallbackReceiver extends BroadcastReceiver { + + @SuppressLint("UnsafeProtectedBroadcastReceiver") + @Override + public void onReceive(Context context, Intent intent) { + if (context == null || intent == null) { + return; + } + + final Context applicationContext = context.getApplicationContext(); + + final SharedPreferences preferences = applicationContext.getSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE); + + if (!shouldProceedWithRemoval(intent, preferences)) { + return; + } + + stopRecursiveFileObserver(applicationContext); + stopAllServices(applicationContext); + deleteDatabase(applicationContext); + cleanSharedPreferences(applicationContext, preferences); + removeCachedFiles(applicationContext); + } + + private void deleteDatabase(@NonNull Context applicationContext) { + final boolean result = applicationContext.deleteDatabase(DbHelper.DATABASE_NAME); + Timber.d("Remove Database: %s", result); + } + + private void stopRecursiveFileObserver(@NonNull Context applicationContext) { + if (applicationContext instanceof EdriveApplication) { + ((EdriveApplication) applicationContext).stopRecursiveFileObserver(); + } + } + + private boolean shouldProceedWithRemoval(@NonNull Intent intent, @NonNull SharedPreferences preferences) { + if (isInvalidAction(intent)) { + return false; + } + + String currentAccount = preferences.getString(AccountManager.KEY_ACCOUNT_NAME, ""); + String currentAccountType = preferences.getString(AccountManager.KEY_ACCOUNT_TYPE, ""); + + if (currentAccount.isEmpty() || currentAccountType.isEmpty()) { + return false; + } + + final String accountType = intent.getExtras().getString(AccountManager.KEY_ACCOUNT_TYPE); + final String accountName = intent.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME); + + return (currentAccount.equals(accountName) && currentAccountType.equals(accountType)); + } + + private boolean isInvalidAction(@NonNull Intent intent) { + return !"android.accounts.action.ACCOUNT_REMOVED".equals(intent.getAction()); + } + + private void stopAllServices(@NonNull Context applicationContext) { + Intent observerServiceIntent = new Intent(applicationContext, ObserverService.class); + boolean observerServiceStopResult = applicationContext.stopService(observerServiceIntent); + Timber.d("stop ObserverService: %s", observerServiceStopResult); + + Intent initializerServiceIntent = new Intent(applicationContext, InitializerService.class); + boolean initServiceStopResult = applicationContext.stopService(initializerServiceIntent); + Timber.d("stop InitializerService: %s", initServiceStopResult); + + Intent synchronizationServiceIntent = new Intent(applicationContext, SynchronizationService.class); + boolean syncServiceStopResult = applicationContext.stopService(synchronizationServiceIntent); + Timber.d("stop SynchronizationService: %s", syncServiceStopResult); + } + + private void cleanSharedPreferences(@NonNull Context applicationContext, @NonNull SharedPreferences prefs) { + if (!applicationContext.deleteSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME)) { + //If removal failed, clear all data inside + prefs.edit().remove(AccountManager.KEY_ACCOUNT_NAME) + .remove(AccountManager.KEY_ACCOUNT_TYPE) + .remove(INITIALIZATION_HAS_BEEN_DONE) + .remove(INITIALFOLDERS_NUMBER) + .remove(AppConstants.KEY_LAST_SYNC_TIME) + .apply(); + } + + applicationContext.deleteSharedPreferences(FailedSyncPrefsManager.PREF_NAME); + } + + private void removeCachedFiles(@NonNull Context applicationContext) { + final File[] cachedFiles = applicationContext.getExternalCacheDir().listFiles(); + if (cachedFiles == null) { + Timber.w("listFiles() returned null. preventing a NPE"); + return; + } + + for (File file : cachedFiles) { + try { + boolean removed = file.delete(); + if (!removed) { + Timber.w("Failed to remove the cached file: %s", file.getName()); + } + } catch (SecurityException e) { + Timber.e(e, "failed to delete cached file on account removal call"); + } + } + } +} diff --git a/app/src/main/java/foundation/e/drive/services/ResetService.java b/app/src/main/java/foundation/e/drive/services/ResetService.java deleted file mode 100644 index a5cfb928dc4ba2d160dcb7fc64d9dc11a55093e8..0000000000000000000000000000000000000000 --- a/app/src/main/java/foundation/e/drive/services/ResetService.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright © CLEUS SAS 2018-2019. - * Copyright © ECORP SAS 2022. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Public License v3.0 - * which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/gpl.html - */ - -package foundation.e.drive.services; - -import android.accounts.AccountManager; -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.os.IBinder; - -import java.io.File; - -import foundation.e.drive.EdriveApplication; -import foundation.e.drive.database.DbHelper; -import foundation.e.drive.database.FailedSyncPrefsManager; -import foundation.e.drive.utils.AppConstants; -import timber.log.Timber; - -import static foundation.e.drive.utils.AppConstants.INITIALFOLDERS_NUMBER; -import static foundation.e.drive.utils.AppConstants.INITIALIZATION_HAS_BEEN_DONE; - -import androidx.annotation.Nullable; -import androidx.work.WorkManager; - -/** - * @author Vincent Bourgmayer - * Service which stop others, remove DB, clear sharedPrefs and unregister ScreenOffReceiver - */ -public class ResetService extends Service { - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - Timber.tag(ResetService.class.getSimpleName()).i("onStartCommand()"); - if ( intent.getExtras() != null ) { - final String intent_accountName = intent.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME, ""); - final String intent_accountType = intent.getExtras().getString(AccountManager.KEY_ACCOUNT_TYPE, ""); - - if (!intent_accountName.isEmpty() && !intent_accountType.isEmpty()) { - final SharedPreferences prefs = this.getSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE); - - if (intent_accountName.equals(prefs.getString(AccountManager.KEY_ACCOUNT_NAME, "")) - && intent_accountType.equals(prefs.getString(AccountManager.KEY_ACCOUNT_TYPE, ""))) { - WorkManager.getInstance(this).cancelAllWorkByTag(AppConstants.WORK_GENERIC_TAG); - ( (EdriveApplication) this.getApplication() ).stopRecursiveFileObserver(); - - stopAllServices(); - - final boolean result = deleteDatabase(DbHelper.DATABASE_NAME); - Timber.d("Remove Database: %s", result); - - cleanSharedPreferences(prefs); - removeCachedFiles(); - } - } - } - stopSelf(); - return super.onStartCommand(intent, flags, startId); - } - - - private void stopAllServices() { - Intent stopperIntent = new Intent(getApplicationContext(), ObserverService.class); - boolean result = getApplicationContext().stopService( stopperIntent ); - Timber.d("stop ObserverService: %s", result); - - stopperIntent = new Intent(getApplicationContext(), InitializerService.class); - result = getApplicationContext().stopService( stopperIntent ); - Timber.d("stop InitializerService: %s", result); - - stopperIntent = new Intent(getApplicationContext(), SynchronizationService.class); - result = getApplicationContext().stopService( stopperIntent ); - - Timber.d("stop SynchronizationService: %s", result); - } - - private void cleanSharedPreferences(SharedPreferences prefs) { - if (!this.deleteSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME)) { - - //If removal failed, clear all data inside - prefs.edit().remove(AccountManager.KEY_ACCOUNT_NAME) - .remove(AccountManager.KEY_ACCOUNT_TYPE) - .putBoolean(INITIALIZATION_HAS_BEEN_DONE, false) - .remove(INITIALFOLDERS_NUMBER) - .remove(AppConstants.KEY_LAST_SYNC_TIME) - .apply(); - } - - deleteSharedPreferences(FailedSyncPrefsManager.PREF_NAME); - } - - private void removeCachedFiles() { - final File[] cachedFiles = this.getApplicationContext().getExternalCacheDir().listFiles(); - if (cachedFiles == null) { - Timber.e("listFiles() returned null. preventing a NPE"); - return; - } - - for (File f : cachedFiles) { - f.delete(); - } - } - - @Nullable - @Override - public IBinder onBind(Intent intent) { - return null; - } -} \ No newline at end of file