Merge pull request #3558 from k9mail/controller_extension

Add ControllerExtension to allow accessing MessagingController internals
This commit is contained in:
cketti 2018-08-17 22:21:05 +02:00 committed by GitHub
commit f3ef980587
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 72 additions and 43 deletions

View file

@ -9,6 +9,7 @@ import android.os.Handler
import android.os.Looper
import android.os.StrictMode
import com.fsck.k9.autocrypt.autocryptModule
import com.fsck.k9.controller.controllerModule
import com.fsck.k9.crypto.openPgpModule
import com.fsck.k9.mail.internet.BinaryTempFileBody
import com.fsck.k9.mail.ssl.LocalKeyStore
@ -39,7 +40,8 @@ object Core : KoinComponent {
mailStoreModule,
extractorModule,
htmlModule,
coreNotificationModule
coreNotificationModule,
controllerModule
)
/**

View file

@ -1,7 +1,7 @@
package com.fsck.k9
import android.content.Context
import com.fsck.k9.controller.MessagingController
import com.fsck.k9.helper.Contacts
import com.fsck.k9.mail.power.PowerManager
import com.fsck.k9.mailstore.StorageManager
import com.fsck.k9.power.TracingPowerManager
@ -9,8 +9,8 @@ import org.koin.dsl.module.applicationContext
val mainModule = applicationContext {
bean { Preferences.getPreferences(get()) }
bean { MessagingController.getInstance(get()) }
bean { get<Context>().resources }
bean { StorageManager.getInstance(get()) }
bean { TracingPowerManager.getPowerManager(get()) as PowerManager }
bean { Contacts.getInstance(get()) }
}

View file

@ -0,0 +1,13 @@
package com.fsck.k9.controller
import com.fsck.k9.backend.BackendManager
interface ControllerExtension {
fun init(controller: MessagingController, backendManager: BackendManager, controllerInternals: ControllerInternals)
interface ControllerInternals {
fun put(description: String, listener: MessagingListener?, runnable: Runnable)
fun putBackground(description: String, listener: MessagingListener?, runnable: Runnable)
}
}

View file

@ -0,0 +1,8 @@
package com.fsck.k9.controller
import org.koin.dsl.module.applicationContext
val controllerModule = applicationContext {
bean { MessagingController(get(), get(), get(), get(), get(), get(), get("controllerExtensions")) }
bean { DefaultAccountStatsCollector(get()) as AccountStatsCollector }
}

View file

@ -37,6 +37,7 @@ import com.fsck.k9.Account.DeletePolicy;
import com.fsck.k9.Account.Expunge;
import com.fsck.k9.AccountStats;
import com.fsck.k9.CoreResourceProvider;
import com.fsck.k9.controller.ControllerExtension.ControllerInternals;
import com.fsck.k9.core.BuildConfig;
import com.fsck.k9.DI;
import com.fsck.k9.K9;
@ -83,6 +84,7 @@ import com.fsck.k9.search.LocalSearch;
import com.fsck.k9.search.SearchAccount;
import com.fsck.k9.search.SearchSpecification;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import timber.log.Timber;
import static com.fsck.k9.K9.MAX_SEND_ATTEMPTS;
@ -109,13 +111,10 @@ public class MessagingController {
public static final Set<Flag> SYNC_FLAGS = EnumSet.of(Flag.SEEN, Flag.FLAGGED, Flag.ANSWERED, Flag.FORWARDED);
private static MessagingController inst = null;
private final Context context;
private final Contacts contacts;
private final NotificationController notificationController;
private final BackendManager backendManager = DI.get(BackendManager.class);
private final BackendManager backendManager;
private final Thread controllerThread;
@ -133,28 +132,20 @@ public class MessagingController {
private volatile boolean stopped = false;
public static synchronized MessagingController getInstance(Context context) {
if (inst == null) {
Context appContext = context.getApplicationContext();
NotificationController notificationController = DI.get(NotificationController.class);
Contacts contacts = Contacts.getInstance(context);
AccountStatsCollector accountStatsCollector = new DefaultAccountStatsCollector(context);
CoreResourceProvider resourceProvider = DI.get(CoreResourceProvider.class);
inst = new MessagingController(appContext, notificationController, contacts,
accountStatsCollector, resourceProvider);
}
return inst;
public static MessagingController getInstance(Context context) {
return DI.get(MessagingController.class);
}
@VisibleForTesting
MessagingController(Context context, NotificationController notificationController, Contacts contacts,
AccountStatsCollector accountStatsCollector, CoreResourceProvider resourceProvider) {
AccountStatsCollector accountStatsCollector, CoreResourceProvider resourceProvider,
BackendManager backendManager, List<ControllerExtension> controllerExtensions) {
this.context = context;
this.notificationController = notificationController;
this.contacts = contacts;
this.accountStatsCollector = accountStatsCollector;
this.resourceProvider = resourceProvider;
this.backendManager = backendManager;
controllerThread = new Thread(new Runnable() {
@Override
@ -165,6 +156,32 @@ public class MessagingController {
controllerThread.setName("MessagingController");
controllerThread.start();
addListener(memorizingMessagingListener);
initializeControllerExtensions(controllerExtensions);
}
private void initializeControllerExtensions(List<ControllerExtension> controllerExtensions) {
if (controllerExtensions.isEmpty()) {
return;
}
ControllerInternals internals = new ControllerInternals() {
@Override
public void put(@NotNull String description, @Nullable MessagingListener listener,
@NotNull Runnable runnable) {
MessagingController.this.put(description, listener, runnable);
}
@Override
public void putBackground(@NotNull String description, @Nullable MessagingListener listener,
@NotNull Runnable runnable) {
MessagingController.this.putBackground(description, listener, runnable);
}
};
for (ControllerExtension extension : controllerExtensions) {
extension.init(this, backendManager, internals);
}
}
@VisibleForTesting

View file

@ -16,6 +16,7 @@ import com.fsck.k9.CoreResourceProvider;
import com.fsck.k9.K9;
import com.fsck.k9.K9RobolectricTest;
import com.fsck.k9.Preferences;
import com.fsck.k9.backend.BackendManager;
import com.fsck.k9.backend.api.Backend;
import com.fsck.k9.helper.Contacts;
import com.fsck.k9.mail.AuthenticationFailedException;
@ -74,6 +75,8 @@ public class MessagingControllerTest extends K9RobolectricTest {
private MessagingController controller;
@Mock
private BackendManager backendManager;
@Mock
private Backend backend;
@Mock
private Contacts contacts;
@ -134,11 +137,11 @@ public class MessagingControllerTest extends K9RobolectricTest {
MockitoAnnotations.initMocks(this);
appContext = RuntimeEnvironment.application;
MessagingControllerTestExtra.backendManagerProvides(backend);
controller = new MessagingController(appContext, notificationController, contacts,
accountStatsCollector, mock(CoreResourceProvider.class));
accountStatsCollector, mock(CoreResourceProvider.class), backendManager,
Collections.<ControllerExtension>emptyList());
configureBackendManager();
configureAccount();
configureLocalStore();
}
@ -527,6 +530,10 @@ public class MessagingControllerTest extends K9RobolectricTest {
controller.addListener(listener);
}
private void configureBackendManager() {
when(backendManager.getBackend(account)).thenReturn(backend);
}
private void configureAccount() throws MessagingException {
when(account.isAvailable(appContext)).thenReturn(true);
when(account.getLocalStore()).thenReturn(localStore);

View file

@ -1,20 +0,0 @@
@file:JvmName("MessagingControllerTestExtra")
package com.fsck.k9.controller
import com.fsck.k9.backend.BackendManager
import com.fsck.k9.backend.api.Backend
import com.nhaarman.mockito_kotlin.any
import com.nhaarman.mockito_kotlin.doReturn
import com.nhaarman.mockito_kotlin.mock
import org.koin.dsl.module.applicationContext
import org.koin.standalone.StandAloneContext.loadKoinModules
fun backendManagerProvides(backend: Backend) {
val backendManager = mock<BackendManager> {
on { getBackend(any()) } doReturn backend
}
loadKoinModules(applicationContext {
bean { backendManager }
})
}

View file

@ -1,6 +1,7 @@
package com.fsck.k9
import com.fsck.k9.backends.backendsModule
import com.fsck.k9.controller.ControllerExtension
import com.fsck.k9.external.BroadcastSenderListener
import com.fsck.k9.external.externalModule
import com.fsck.k9.notification.notificationModule
@ -20,6 +21,7 @@ private val mainAppModule = applicationContext {
get<BroadcastSenderListener>()
))
}
bean("controllerExtensions") { emptyList<ControllerExtension>() }
}
val appModules = listOf(