diff --git a/app/core/src/main/java/com/fsck/k9/controller/MessagingController.java b/app/core/src/main/java/com/fsck/k9/controller/MessagingController.java index 04ebc692f..337b8c54a 100644 --- a/app/core/src/main/java/com/fsck/k9/controller/MessagingController.java +++ b/app/core/src/main/java/com/fsck/k9/controller/MessagingController.java @@ -7,14 +7,12 @@ import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; @@ -69,8 +67,6 @@ import com.fsck.k9.mail.Message.RecipientType; import com.fsck.k9.mail.MessageRetrievalListener; import com.fsck.k9.mail.MessagingException; import com.fsck.k9.mail.Part; -import com.fsck.k9.mail.PushReceiver; -import com.fsck.k9.mail.Pusher; import com.fsck.k9.mail.internet.MessageExtractor; import com.fsck.k9.mail.internet.MimeUtility; import com.fsck.k9.mailstore.LocalFolder; @@ -127,7 +123,6 @@ public class MessagingController { private final BlockingQueue queuedCommands = new PriorityBlockingQueue<>(); private final Set listeners = new CopyOnWriteArraySet<>(); - private final ConcurrentHashMap pushers = new ConcurrentHashMap<>(); private final ExecutorService threadPool = Executors.newCachedThreadPool(); private final MemorizingMessagingListener memorizingMessagingListener = new MemorizingMessagingListener(); private final UnreadMessageCountProvider unreadMessageCountProvider; @@ -2657,116 +2652,6 @@ public class MessagingController { } } - public Collection getPushers() { - return pushers.values(); - } - - public Pusher getPusher(Account account) { - return pushers.get(account); - } - - public boolean setupPushing(final Account account) { - try { - Pusher previousPusher = pushers.remove(account); - if (previousPusher != null) { - previousPusher.stop(); - } - - Account.FolderMode aDisplayMode = account.getFolderDisplayMode(); - Account.FolderMode aPushMode = account.getFolderPushMode(); - - List names = new ArrayList<>(); - - LocalStore localStore = localStoreProvider.getInstance(account); - for (final LocalFolder folder : localStore.getPersonalNamespaces(false)) { - if (folder.getServerId().equals(account.getOutboxFolder())) { - continue; - } - folder.open(); - - FolderClass fDisplayClass = folder.getDisplayClass(); - FolderClass fPushClass = folder.getPushClass(); - - if (LocalFolder.isModeMismatch(aDisplayMode, fDisplayClass)) { - // Never push a folder that isn't displayed - /* - if (K9.DEBUG) { - Log.v(K9.LOG_TAG, "Not pushing folder " + folder.getName() + - " which is in display class " + fDisplayClass + " while account is in display mode " + aDisplayMode); - } - */ - - continue; - } - - if (LocalFolder.isModeMismatch(aPushMode, fPushClass)) { - // Do not push folders in the wrong class - /* - if (K9.DEBUG) { - Log.v(K9.LOG_TAG, "Not pushing folder " + folder.getName() + - " which is in push mode " + fPushClass + " while account is in push mode " + aPushMode); - } - */ - - continue; - } - - Timber.i("Starting pusher for %s:%s", account.getDescription(), folder.getServerId()); - - names.add(folder.getServerId()); - } - - if (!names.isEmpty()) { - PushReceiver receiver = new MessagingControllerPushReceiver(context, localStoreProvider, account, this); - int maxPushFolders = account.getMaxPushFolders(); - - if (names.size() > maxPushFolders) { - Timber.i("Count of folders to push for account %s is %d, greater than limit of %d, truncating", - account.getDescription(), names.size(), maxPushFolders); - - names = names.subList(0, maxPushFolders); - } - - try { - Backend backend = getBackend(account); - if (!backend.isPushCapable()) { - Timber.i("Account %s is not push capable, skipping", account.getDescription()); - - return false; - } - Pusher pusher = backend.createPusher(receiver); - Pusher oldPusher = pushers.putIfAbsent(account, pusher); - if (oldPusher == null) { - pusher.start(names); - } - } catch (Exception e) { - Timber.e(e, "Could not get remote store"); - return false; - } - - return true; - } else { - Timber.i("No folders are configured for pushing in account %s", account.getDescription()); - return false; - } - - } catch (Exception e) { - Timber.e(e, "Got exception while setting up pushing"); - } - return false; - } - - public void stopAllPushing() { - Timber.i("Stopping all pushers"); - - Iterator iter = pushers.values().iterator(); - while (iter.hasNext()) { - Pusher pusher = iter.next(); - iter.remove(); - pusher.stop(); - } - } - public void cancelNotificationsForAccount(Account account) { notificationController.clearNewMailNotifications(account); } diff --git a/app/core/src/main/java/com/fsck/k9/controller/MessagingControllerPushReceiver.java b/app/core/src/main/java/com/fsck/k9/controller/MessagingControllerPushReceiver.java deleted file mode 100644 index 215590c8d..000000000 --- a/app/core/src/main/java/com/fsck/k9/controller/MessagingControllerPushReceiver.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.fsck.k9.controller; - - -import java.util.List; -import java.util.concurrent.CountDownLatch; - -import android.content.Context; - -import com.fsck.k9.Account; -import com.fsck.k9.K9; -import com.fsck.k9.mail.Message; -import com.fsck.k9.mail.PushReceiver; -import com.fsck.k9.mail.power.WakeLock; -import com.fsck.k9.mailstore.LocalFolder; -import com.fsck.k9.mailstore.LocalStore; -import com.fsck.k9.mailstore.LocalStoreProvider; -import com.fsck.k9.service.SleepService; -import timber.log.Timber; - -public class MessagingControllerPushReceiver implements PushReceiver { - final Account account; - final MessagingController controller; - final Context context; - final LocalStoreProvider localStoreProvider; - - public MessagingControllerPushReceiver(Context context, LocalStoreProvider localStoreProvider, - Account nAccount, MessagingController nController) { - account = nAccount; - controller = nController; - this.localStoreProvider = localStoreProvider; - this.context = context; - } - - public void messagesFlagsChanged(String folderServerId, List messages) { - syncFolder(folderServerId); - } - public void messagesArrived(String folderServerId, List messages) { - syncFolder(folderServerId); - } - public void messagesRemoved(String folderServerId, List messages) { - syncFolder(folderServerId); - } - - public void syncFolder(String folderServerId) { - Timber.v("syncFolder(%s)", folderServerId); - - final CountDownLatch latch = new CountDownLatch(1); - controller.synchronizeMailbox(account, folderServerId, new SimpleMessagingListener() { - @Override - public void synchronizeMailboxFinished(Account account, String folderServerId) { - latch.countDown(); - } - - @Override - public void synchronizeMailboxFailed(Account account, String folderServerId, - String message) { - latch.countDown(); - } - }); - - Timber.v("syncFolder(%s) about to await latch release", folderServerId); - - try { - latch.await(); - Timber.v("syncFolder(%s) got latch release", folderServerId); - } catch (Exception e) { - Timber.e(e, "Interrupted while awaiting latch release"); - } - } - - @Override - public void sleep(WakeLock wakeLock, long millis) { - SleepService.sleep(context, millis, wakeLock, K9.PUSH_WAKE_LOCK_TIMEOUT); - } - - public void pushError(String errorMessage, Exception e) { - String errMess = errorMessage; - - controller.notifyUserIfCertificateProblem(account, e, true); - if (errMess == null && e != null) { - errMess = e.getMessage(); - } - Timber.e(e, errMess); - } - - @Override - public void authenticationFailed() { - controller.handleAuthenticationFailure(account, true); - } - - public String getPushState(String folderServerId) { - LocalFolder localFolder = null; - try { - LocalStore localStore = localStoreProvider.getInstance(account); - localFolder = localStore.getFolder(folderServerId); - localFolder.open(); - return localFolder.getPushState(); - } catch (Exception e) { - Timber.e(e, "Unable to get push state from account %s, folder %s", account.getDescription(), folderServerId); - return null; - } finally { - if (localFolder != null) { - localFolder.close(); - } - } - } - - public void setPushActive(String folderServerId, boolean enabled) { - // Nothing to do for now - } -} diff --git a/app/core/src/main/java/com/fsck/k9/mailstore/K9BackendFolder.kt b/app/core/src/main/java/com/fsck/k9/mailstore/K9BackendFolder.kt index 13eb7bd1c..46cc91a51 100644 --- a/app/core/src/main/java/com/fsck/k9/mailstore/K9BackendFolder.kt +++ b/app/core/src/main/java/com/fsck/k9/mailstore/K9BackendFolder.kt @@ -115,14 +115,6 @@ class K9BackendFolder( database.setString(column = "status", value = status) } - override fun getPushState(): String? { - return database.getString(column = "push_state") - } - - override fun setPushState(pushState: String?) { - return database.setString(column = "push_state", value = pushState) - } - override fun isMessagePresent(messageServerId: String): Boolean { return database.execute(false) { db -> val cursor = db.query( diff --git a/app/core/src/main/java/com/fsck/k9/service/PushService.java b/app/core/src/main/java/com/fsck/k9/service/PushService.java deleted file mode 100644 index 1062709c2..000000000 --- a/app/core/src/main/java/com/fsck/k9/service/PushService.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.fsck.k9.service; - -import android.content.Context; -import android.content.Intent; -import android.os.IBinder; -import timber.log.Timber; - -public class PushService extends CoreService { - private static final String START_SERVICE = "com.fsck.k9.service.PushService.startService"; - private static final String STOP_SERVICE = "com.fsck.k9.service.PushService.stopService"; - - public static void startService(Context context) { - Intent i = new Intent(); - i.setClass(context, PushService.class); - i.setAction(PushService.START_SERVICE); - addWakeLock(context, i); - context.startService(i); - } - - public static void stopService(Context context) { - Intent i = new Intent(); - i.setClass(context, PushService.class); - i.setAction(PushService.STOP_SERVICE); - addWakeLock(context, i); - context.startService(i); - } - - @Override - public int startService(Intent intent, int startId) { - int startFlag = START_STICKY; - if (START_SERVICE.equals(intent.getAction())) { - Timber.i("PushService started with startId = %d", startId); - } else if (STOP_SERVICE.equals(intent.getAction())) { - Timber.i("PushService stopping with startId = %d", startId); - stopSelf(startId); - startFlag = START_NOT_STICKY; - } - - return startFlag; - } - - @Override - public void onCreate() { - super.onCreate(); - setAutoShutdown(false); - } - - - @Override - public IBinder onBind(Intent arg0) { - // TODO Auto-generated method stub - return null; - } -} diff --git a/app/core/src/main/java/com/fsck/k9/service/SleepService.java b/app/core/src/main/java/com/fsck/k9/service/SleepService.java deleted file mode 100644 index 06d343a56..000000000 --- a/app/core/src/main/java/com/fsck/k9/service/SleepService.java +++ /dev/null @@ -1,139 +0,0 @@ -package com.fsck.k9.service; - - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import android.content.Context; -import android.content.Intent; -import android.os.SystemClock; - -import com.fsck.k9.mail.power.WakeLock; -import timber.log.Timber; - -import static java.lang.Thread.currentThread; - - -public class SleepService extends CoreService { - - private static final String ALARM_FIRED = "com.fsck.k9.service.SleepService.ALARM_FIRED"; - private static final String LATCH_ID = "com.fsck.k9.service.SleepService.LATCH_ID_EXTRA"; - - - private static ConcurrentHashMap sleepData = new ConcurrentHashMap<>(); - - private static AtomicInteger latchId = new AtomicInteger(); - - public static void sleep(Context context, long sleepTime, WakeLock wakeLock, long wakeLockTimeout) { - Integer id = latchId.getAndIncrement(); - Timber.d("SleepService Preparing CountDownLatch with id = %d, thread %s", id, currentThread().getName()); - - SleepDatum sleepDatum = new SleepDatum(); - CountDownLatch latch = new CountDownLatch(1); - sleepDatum.latch = latch; - sleepDatum.reacquireLatch = new CountDownLatch(1); - sleepData.put(id, sleepDatum); - - Intent i = new Intent(context, SleepService.class); - i.putExtra(LATCH_ID, id); - i.setAction(ALARM_FIRED + "." + id); - long startTime = SystemClock.elapsedRealtime(); - long nextTime = startTime + sleepTime; - BootReceiver.scheduleIntent(context, nextTime, i); - if (wakeLock != null) { - sleepDatum.wakeLock = wakeLock; - sleepDatum.timeout = wakeLockTimeout; - wakeLock.release(); - } - try { - boolean countedDown = latch.await(sleepTime, TimeUnit.MILLISECONDS); - if (!countedDown) { - Timber.d("SleepService latch timed out for id = %d, thread %s", id, currentThread().getName()); - } - } catch (InterruptedException ie) { - Timber.e(ie, "SleepService Interrupted while awaiting latch"); - } - SleepDatum releaseDatum = sleepData.remove(id); - if (releaseDatum == null) { - try { - Timber.d("SleepService waiting for reacquireLatch for id = %d, thread %s", - id, currentThread().getName()); - - if (!sleepDatum.reacquireLatch.await(5000, TimeUnit.MILLISECONDS)) { - Timber.w("SleepService reacquireLatch timed out for id = %d, thread %s", - id, currentThread().getName()); - } else { - Timber.d("SleepService reacquireLatch finished for id = %d, thread %s", - id, currentThread().getName()); - } - } catch (InterruptedException ie) { - Timber.e(ie, "SleepService Interrupted while awaiting reacquireLatch"); - } - } else { - reacquireWakeLock(releaseDatum); - } - - long endTime = SystemClock.elapsedRealtime(); - long actualSleep = endTime - startTime; - - if (actualSleep < sleepTime) { - Timber.w("SleepService sleep time too short: requested was %d, actual was %d", sleepTime, actualSleep); - } else { - Timber.d("SleepService requested sleep time was %d, actual was %d", sleepTime, actualSleep); - } - } - - private static void endSleep(Integer id) { - if (id != -1) { - SleepDatum sleepDatum = sleepData.remove(id); - if (sleepDatum != null) { - CountDownLatch latch = sleepDatum.latch; - if (latch == null) { - Timber.e("SleepService No CountDownLatch available with id = %s", id); - } else { - Timber.d("SleepService Counting down CountDownLatch with id = %d", id); - latch.countDown(); - } - reacquireWakeLock(sleepDatum); - sleepDatum.reacquireLatch.countDown(); - } else { - Timber.d("SleepService Sleep for id %d already finished", id); - } - } - } - - private static void reacquireWakeLock(SleepDatum sleepDatum) { - WakeLock wakeLock = sleepDatum.wakeLock; - if (wakeLock != null) { - synchronized (wakeLock) { - long timeout = sleepDatum.timeout; - Timber.d("SleepService Acquiring wakeLock for %d ms", timeout); - wakeLock.acquire(timeout); - } - } - } - - @Override - public int startService(Intent intent, int startId) { - try { - if (intent.getAction().startsWith(ALARM_FIRED)) { - Integer id = intent.getIntExtra(LATCH_ID, -1); - endSleep(id); - } - return START_NOT_STICKY; - } - finally { - stopSelf(startId); - } - } - - private static class SleepDatum { - CountDownLatch latch; - WakeLock wakeLock; - long timeout; - CountDownLatch reacquireLatch; - } - -} diff --git a/app/k9mail-jmap/src/main/AndroidManifest.xml b/app/k9mail-jmap/src/main/AndroidManifest.xml index b39ac4bd0..506766a7f 100644 --- a/app/k9mail-jmap/src/main/AndroidManifest.xml +++ b/app/k9mail-jmap/src/main/AndroidManifest.xml @@ -278,14 +278,6 @@ android:name="com.fsck.k9.notification.NotificationActionService" android:enabled="true"/> - - - - diff --git a/app/k9mail/src/main/AndroidManifest.xml b/app/k9mail/src/main/AndroidManifest.xml index fae9b7b7a..e63e1feb4 100644 --- a/app/k9mail/src/main/AndroidManifest.xml +++ b/app/k9mail/src/main/AndroidManifest.xml @@ -360,14 +360,6 @@ android:name=".notification.NotificationActionService" android:enabled="true"/> - - - - diff --git a/backend/api/src/main/java/com/fsck/k9/backend/api/Backend.kt b/backend/api/src/main/java/com/fsck/k9/backend/api/Backend.kt index d8f841d31..bce4c7553 100644 --- a/backend/api/src/main/java/com/fsck/k9/backend/api/Backend.kt +++ b/backend/api/src/main/java/com/fsck/k9/backend/api/Backend.kt @@ -6,8 +6,6 @@ import com.fsck.k9.mail.Flag import com.fsck.k9.mail.Message import com.fsck.k9.mail.MessagingException import com.fsck.k9.mail.Part -import com.fsck.k9.mail.PushReceiver -import com.fsck.k9.mail.Pusher interface Backend { val supportsSeenFlag: Boolean @@ -88,8 +86,6 @@ interface Backend { @Throws(MessagingException::class) fun uploadMessage(folderServerId: String, message: Message): String? - fun createPusher(receiver: PushReceiver): Pusher - @Throws(MessagingException::class) fun checkIncomingServerSettings() diff --git a/backend/api/src/main/java/com/fsck/k9/backend/api/BackendFolder.kt b/backend/api/src/main/java/com/fsck/k9/backend/api/BackendFolder.kt index 9f988a7da..914b15691 100644 --- a/backend/api/src/main/java/com/fsck/k9/backend/api/BackendFolder.kt +++ b/backend/api/src/main/java/com/fsck/k9/backend/api/BackendFolder.kt @@ -18,8 +18,6 @@ interface BackendFolder { fun setMoreMessages(moreMessages: MoreMessages) fun setLastChecked(timestamp: Long) fun setStatus(status: String?) - fun getPushState(): String? - fun setPushState(pushState: String?) fun isMessagePresent(messageServerId: String): Boolean fun getMessageFlags(messageServerId: String): Set fun setMessageFlag(messageServerId: String, flag: Flag, value: Boolean) diff --git a/backend/imap/src/main/java/com/fsck/k9/backend/imap/ImapBackend.java b/backend/imap/src/main/java/com/fsck/k9/backend/imap/ImapBackend.java index 0bae0076e..f17954afe 100644 --- a/backend/imap/src/main/java/com/fsck/k9/backend/imap/ImapBackend.java +++ b/backend/imap/src/main/java/com/fsck/k9/backend/imap/ImapBackend.java @@ -16,10 +16,7 @@ import com.fsck.k9.mail.Flag; import com.fsck.k9.mail.Message; import com.fsck.k9.mail.MessagingException; import com.fsck.k9.mail.Part; -import com.fsck.k9.mail.PushReceiver; -import com.fsck.k9.mail.Pusher; import com.fsck.k9.mail.power.PowerManager; -import com.fsck.k9.mail.store.imap.ImapPusher; import com.fsck.k9.mail.store.imap.ImapStore; import com.fsck.k9.mail.transport.smtp.SmtpTransport; import org.jetbrains.annotations.NotNull; @@ -215,12 +212,6 @@ public class ImapBackend implements Backend { return commandUploadMessage.uploadMessage(folderServerId, message); } - @NotNull - @Override - public Pusher createPusher(@NotNull PushReceiver receiver) { - return new ImapPusher(imapStore, receiver, powerManager); - } - @Override public void checkIncomingServerSettings() throws MessagingException { imapStore.checkSettings(); diff --git a/backend/imap/src/main/java/com/fsck/k9/backend/imap/ImapSync.java b/backend/imap/src/main/java/com/fsck/k9/backend/imap/ImapSync.java index c5568ac9b..2ca3e80a7 100644 --- a/backend/imap/src/main/java/com/fsck/k9/backend/imap/ImapSync.java +++ b/backend/imap/src/main/java/com/fsck/k9/backend/imap/ImapSync.java @@ -336,15 +336,6 @@ class ImapSync { fetchUnsyncedMessages(syncConfig, remoteFolder, unsyncedMessages, smallMessages, largeMessages, progress, todo, fp, listener); - String updatedPushState = backendFolder.getPushState(); - for (ImapMessage message : unsyncedMessages) { - String newPushState = remoteFolder.getNewPushState(updatedPushState, message); - if (newPushState != null) { - updatedPushState = newPushState; - } - } - backendFolder.setPushState(updatedPushState); - Timber.d("SYNC: Synced unsynced messages for folder %s", folder); } @@ -416,10 +407,6 @@ class ImapSync { unsyncedMessages.add(message); } else { - String newPushState = remoteFolder.getNewPushState(backendFolder.getPushState(), message); - if (newPushState != null) { - backendFolder.setPushState(newPushState); - } syncFlagMessages.add(message); } } else { diff --git a/backend/jmap/src/main/java/com/fsck/k9/backend/jmap/JmapBackend.kt b/backend/jmap/src/main/java/com/fsck/k9/backend/jmap/JmapBackend.kt index 1f4a42f63..6c96b14bb 100644 --- a/backend/jmap/src/main/java/com/fsck/k9/backend/jmap/JmapBackend.kt +++ b/backend/jmap/src/main/java/com/fsck/k9/backend/jmap/JmapBackend.kt @@ -9,8 +9,6 @@ import com.fsck.k9.mail.FetchProfile import com.fsck.k9.mail.Flag import com.fsck.k9.mail.Message import com.fsck.k9.mail.Part -import com.fsck.k9.mail.PushReceiver -import com.fsck.k9.mail.Pusher import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import okhttp3.OkHttpClient import rs.ltt.jmap.client.JmapClient @@ -121,10 +119,6 @@ class JmapBackend( return commandUpload.uploadMessage(folderServerId, message) } - override fun createPusher(receiver: PushReceiver): Pusher { - throw UnsupportedOperationException("not implemented") - } - override fun checkIncomingServerSettings() { jmapClient.call(EchoMethodCall()).get() } diff --git a/backend/jmap/src/test/java/com/fsck/k9/backend/jmap/InMemoryBackendFolder.kt b/backend/jmap/src/test/java/com/fsck/k9/backend/jmap/InMemoryBackendFolder.kt index 293f87570..b3c5a1997 100644 --- a/backend/jmap/src/test/java/com/fsck/k9/backend/jmap/InMemoryBackendFolder.kt +++ b/backend/jmap/src/test/java/com/fsck/k9/backend/jmap/InMemoryBackendFolder.kt @@ -91,14 +91,6 @@ class InMemoryBackendFolder(override var name: String, var type: FolderType) : B throw UnsupportedOperationException("not implemented") } - override fun getPushState(): String? { - throw UnsupportedOperationException("not implemented") - } - - override fun setPushState(pushState: String?) { - throw UnsupportedOperationException("not implemented") - } - override fun isMessagePresent(messageServerId: String): Boolean { throw UnsupportedOperationException("not implemented") } diff --git a/backend/pop3/src/main/java/com/fsck/k9/backend/pop3/Pop3Backend.kt b/backend/pop3/src/main/java/com/fsck/k9/backend/pop3/Pop3Backend.kt index 420c63d81..a47a8c1eb 100644 --- a/backend/pop3/src/main/java/com/fsck/k9/backend/pop3/Pop3Backend.kt +++ b/backend/pop3/src/main/java/com/fsck/k9/backend/pop3/Pop3Backend.kt @@ -9,8 +9,6 @@ import com.fsck.k9.mail.FetchProfile import com.fsck.k9.mail.Flag import com.fsck.k9.mail.Message import com.fsck.k9.mail.Part -import com.fsck.k9.mail.PushReceiver -import com.fsck.k9.mail.Pusher import com.fsck.k9.mail.store.pop3.Pop3Store import com.fsck.k9.mail.transport.smtp.SmtpTransport @@ -120,10 +118,6 @@ class Pop3Backend( throw UnsupportedOperationException("not supported") } - override fun createPusher(receiver: PushReceiver): Pusher { - throw UnsupportedOperationException("not supported") - } - override fun checkIncomingServerSettings() { pop3Store.checkSettings() } diff --git a/backend/webdav/src/main/java/com/fsck/k9/backend/webdav/WebDavBackend.kt b/backend/webdav/src/main/java/com/fsck/k9/backend/webdav/WebDavBackend.kt index 44a83456d..887a187d3 100644 --- a/backend/webdav/src/main/java/com/fsck/k9/backend/webdav/WebDavBackend.kt +++ b/backend/webdav/src/main/java/com/fsck/k9/backend/webdav/WebDavBackend.kt @@ -10,8 +10,6 @@ import com.fsck.k9.mail.Flag import com.fsck.k9.mail.Message import com.fsck.k9.mail.MessagingException import com.fsck.k9.mail.Part -import com.fsck.k9.mail.PushReceiver -import com.fsck.k9.mail.Pusher import com.fsck.k9.mail.store.webdav.WebDavStore import com.fsck.k9.mail.transport.WebDavTransport import timber.log.Timber @@ -130,10 +128,6 @@ class WebDavBackend( return commandUploadMessage.uploadMessage(folderServerId, message) } - override fun createPusher(receiver: PushReceiver): Pusher { - throw UnsupportedOperationException("not supported") - } - override fun checkIncomingServerSettings() { webDavStore.checkSettings() } diff --git a/mail/common/src/main/java/com/fsck/k9/mail/PushReceiver.java b/mail/common/src/main/java/com/fsck/k9/mail/PushReceiver.java deleted file mode 100644 index 905f9c30f..000000000 --- a/mail/common/src/main/java/com/fsck/k9/mail/PushReceiver.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.fsck.k9.mail; - - -import java.util.List; - -import com.fsck.k9.mail.power.WakeLock; - - -public interface PushReceiver { - void syncFolder(String folderServerId); - void messagesArrived(String folderServerId, List mess); - void messagesFlagsChanged(String folderServerId, List mess); - void messagesRemoved(String folderServerId, List mess); - String getPushState(String folderServerId); - void pushError(String errorMessage, Exception e); - void authenticationFailed(); - void setPushActive(String folderServerId, boolean enabled); - void sleep(WakeLock wakeLock, long millis); -} diff --git a/mail/common/src/main/java/com/fsck/k9/mail/Pusher.java b/mail/common/src/main/java/com/fsck/k9/mail/Pusher.java deleted file mode 100644 index fba92ac36..000000000 --- a/mail/common/src/main/java/com/fsck/k9/mail/Pusher.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.fsck.k9.mail; - -import java.util.List; - - -public interface Pusher { - void start(List folderServerIds); - void refresh(); - void stop(); - /** - * - * @return milliseconds of required refresh interval - */ - int getRefreshInterval(); - void setLastRefresh(long lastRefresh); - long getLastRefresh(); -} diff --git a/mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/ImapFolder.java b/mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/ImapFolder.java index 4a54fbe1e..15b7993ca 100644 --- a/mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/ImapFolder.java +++ b/mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/ImapFolder.java @@ -1261,27 +1261,6 @@ public class ImapFolder { } } - public String getNewPushState(String oldSerializedPushState, Message message) { - try { - String uid = message.getUid(); - long messageUid = Long.parseLong(uid); - - ImapPushState oldPushState = ImapPushState.parse(oldSerializedPushState); - - if (messageUid >= oldPushState.uidNext) { - long uidNext = messageUid + 1; - ImapPushState newPushState = new ImapPushState(uidNext); - - return newPushState.toString(); - } else { - return null; - } - } catch (Exception e) { - Timber.e(e, "Exception while updated push state for %s", getLogId()); - return null; - } - } - public void setFlags(List messages, final Set flags, boolean value) throws MessagingException { open(OPEN_MODE_RW); diff --git a/mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/ImapFolderPusher.java b/mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/ImapFolderPusher.java deleted file mode 100644 index ab639d9d2..000000000 --- a/mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/ImapFolderPusher.java +++ /dev/null @@ -1,728 +0,0 @@ -package com.fsck.k9.mail.store.imap; - - -import java.io.IOException; -import java.net.SocketException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; - -import com.fsck.k9.mail.AuthenticationFailedException; -import com.fsck.k9.mail.CertificateValidationException; -import com.fsck.k9.mail.Flag; -import com.fsck.k9.mail.K9MailLib; -import com.fsck.k9.mail.Message; -import com.fsck.k9.mail.MessagingException; -import com.fsck.k9.mail.PushReceiver; -import com.fsck.k9.mail.power.PowerManager; -import com.fsck.k9.mail.power.WakeLock; -import timber.log.Timber; - -import static com.fsck.k9.mail.K9MailLib.PUSH_WAKE_LOCK_TIMEOUT; -import static com.fsck.k9.mail.NetworkTimeouts.SOCKET_READ_TIMEOUT; -import static com.fsck.k9.mail.store.imap.ImapResponseParser.equalsIgnoreCase; - - -class ImapFolderPusher extends ImapFolder { - private static final int IDLE_READ_TIMEOUT_INCREMENT = 5 * 60 * 1000; - private static final int IDLE_FAILURE_COUNT_LIMIT = 10; - private static final int MAX_DELAY_TIME = 5 * 60 * 1000; // 5 minutes - private static final int NORMAL_DELAY_TIME = 5000; - - - private final PushReceiver pushReceiver; - private final Object threadLock = new Object(); - private final IdleStopper idleStopper = new IdleStopper(); - private final WakeLock wakeLock; - private final List storedUntaggedResponses = new ArrayList<>(); - private Thread listeningThread; - private volatile boolean stop = false; - private volatile boolean idling = false; - - - public ImapFolderPusher(ImapStore store, String serverId, PushReceiver pushReceiver, PowerManager powerManager) { - super(store, serverId); - this.pushReceiver = pushReceiver; - - String tag = "ImapFolderPusher " + store.getStoreConfig().toString() + ":" + getServerId(); - wakeLock = powerManager.newWakeLock(tag); - wakeLock.setReferenceCounted(false); - } - - public void start() { - synchronized (threadLock) { - if (listeningThread != null) { - throw new IllegalStateException("start() called twice"); - } - - listeningThread = new Thread(new PushRunnable()); - listeningThread.start(); - } - } - - public void refresh() { - if (idling) { - wakeLock.acquire(PUSH_WAKE_LOCK_TIMEOUT); - idleStopper.stopIdle(); - } - } - - public void stop() { - synchronized (threadLock) { - if (listeningThread == null) { - throw new IllegalStateException("stop() called twice"); - } - - stop = true; - - listeningThread.interrupt(); - listeningThread = null; - } - - ImapConnection conn = connection; - if (conn != null) { - if (K9MailLib.isDebug()) { - Timber.v("Closing connection to stop pushing for %s", getLogId()); - } - - conn.close(); - } else { - Timber.w("Attempt to interrupt null connection to stop pushing on folderPusher for %s", getLogId()); - } - } - - @Override - protected void handleUntaggedResponse(ImapResponse response) { - if (response.getTag() == null && response.size() > 1) { - Object responseType = response.get(1); - if (equalsIgnoreCase(responseType, "FETCH") || equalsIgnoreCase(responseType, "EXPUNGE") || - equalsIgnoreCase(responseType, "EXISTS")) { - - if (K9MailLib.isDebug()) { - Timber.d("Storing response %s for later processing", response); - } - - synchronized (storedUntaggedResponses) { - storedUntaggedResponses.add(response); - } - } - - handlePossibleUidNext(response); - } - } - - private void superHandleUntaggedResponse(ImapResponse response) { - super.handleUntaggedResponse(response); - } - - - private class PushRunnable implements Runnable, UntaggedHandler { - private int delayTime = NORMAL_DELAY_TIME; - private int idleFailureCount = 0; - private boolean needsPoll = false; - - @Override - public void run() { - wakeLock.acquire(PUSH_WAKE_LOCK_TIMEOUT); - - if (K9MailLib.isDebug()) { - Timber.i("Pusher starting for %s", getLogId()); - } - - long lastUidNext = -1L; - while (!stop) { - try { - long oldUidNext = getOldUidNext(); - - /* - * This makes sure 'oldUidNext' is never smaller than 'UIDNEXT' from - * the last loop iteration. This way we avoid looping endlessly causing - * the battery to drain. - * - * See issue 4907 - */ - if (oldUidNext < lastUidNext) { - oldUidNext = lastUidNext; - } - - boolean openedNewConnection = openConnectionIfNecessary(); - - if (stop) { - break; - } - - boolean pushPollOnConnect = store.getStoreConfig().isPushPollOnConnect(); - if (pushPollOnConnect && (openedNewConnection || needsPoll)) { - needsPoll = false; - syncFolderOnConnect(); - } - - if (stop) { - break; - } - - long newUidNext = getNewUidNext(); - lastUidNext = newUidNext; - long startUid = getStartUid(oldUidNext, newUidNext); - - if (newUidNext > startUid) { - notifyMessagesArrived(startUid, newUidNext); - } else { - processStoredUntaggedResponses(); - - if (K9MailLib.isDebug()) { - Timber.i("About to IDLE for %s", getLogId()); - } - - prepareForIdle(); - - ImapConnection conn = connection; - setReadTimeoutForIdle(conn); - sendIdle(conn); - - returnFromIdle(); - } - } catch (AuthenticationFailedException e) { - reacquireWakeLockAndCleanUp(); - - if (K9MailLib.isDebug()) { - Timber.e(e, "Authentication failed. Stopping ImapFolderPusher."); - } - - pushReceiver.authenticationFailed(); - stop = true; - } catch (CertificateValidationException e) { - reacquireWakeLockAndCleanUp(); - - Timber.e(e, "Certificate check failed. Stopping ImapFolderPusher."); - stop = true; - pushReceiver.pushError("Push error for " + getServerId(), e); - } catch (Exception e) { - reacquireWakeLockAndCleanUp(); - - if (stop) { - Timber.i("Got exception while idling, but stop is set for %s", getLogId()); - } else { - pushReceiver.pushError("Push error for " + getServerId(), e); - Timber.e("Got exception while idling for %s", getLogId()); - - pushReceiver.sleep(wakeLock, delayTime); - - delayTime *= 2; - if (delayTime > MAX_DELAY_TIME) { - delayTime = MAX_DELAY_TIME; - } - - idleFailureCount++; - if (idleFailureCount > IDLE_FAILURE_COUNT_LIMIT) { - Timber.e("Disabling pusher for %s after %d consecutive errors", getLogId(), idleFailureCount); - pushReceiver.pushError("Push disabled for " + getServerId() + " after " + idleFailureCount + - " consecutive errors", e); - stop = true; - } - } - } - } - - pushReceiver.setPushActive(getServerId(), false); - - try { - if (K9MailLib.isDebug()) { - Timber.i("Pusher for %s is exiting", getLogId()); - } - - close(); - } catch (Exception me) { - Timber.e(me, "Got exception while closing for %s", getLogId()); - } finally { - wakeLock.release(); - } - } - - private void reacquireWakeLockAndCleanUp() { - wakeLock.acquire(PUSH_WAKE_LOCK_TIMEOUT); - - clearStoredUntaggedResponses(); - idling = false; - pushReceiver.setPushActive(getServerId(), false); - - try { - connection.close(); - } catch (Exception me) { - Timber.e(me, "Got exception while closing for exception for %s", getLogId()); - } - - connection = null; - } - - private long getNewUidNext() throws MessagingException { - long newUidNext = uidNext; - if (newUidNext != -1L) { - return newUidNext; - } - - if (K9MailLib.isDebug()) { - Timber.d("uidNext is -1, using search to find highest UID"); - } - - long highestUid = getHighestUid(); - if (highestUid == -1L) { - return -1L; - } - - newUidNext = highestUid + 1; - - if (K9MailLib.isDebug()) { - Timber.d("highest UID = %d, set newUidNext to %d", highestUid, newUidNext); - } - - return newUidNext; - } - - private long getStartUid(long oldUidNext, long newUidNext) { - long startUid = oldUidNext; - int displayCount = store.getStoreConfig().getDisplayCount(); - - if (startUid < newUidNext - displayCount) { - startUid = newUidNext - displayCount; - } - - if (startUid < 1) { - startUid = 1; - } - - return startUid; - } - - private void prepareForIdle() { - pushReceiver.setPushActive(getServerId(), true); - idling = true; - } - - private void sendIdle(ImapConnection conn) throws MessagingException, IOException { - String tag = conn.sendCommand(Commands.IDLE, false); - - List responses; - try { - try { - responses = conn.readStatusResponse(tag, Commands.IDLE, this); - } finally { - idleStopper.stopAcceptingDoneContinuation(); - } - } catch (IOException e) { - conn.close(); - throw e; - } - - handleUntaggedResponses(responses); - } - - private void returnFromIdle() { - idling = false; - delayTime = NORMAL_DELAY_TIME; - idleFailureCount = 0; - } - - private boolean openConnectionIfNecessary() throws MessagingException { - ImapConnection oldConnection = connection; - internalOpen(OPEN_MODE_RO); - - ImapConnection conn = connection; - - checkConnectionNotNull(conn); - checkConnectionIdleCapable(conn); - - return conn != oldConnection; - } - - private void checkConnectionNotNull(ImapConnection conn) throws MessagingException { - if (conn == null) { - String message = "Could not establish connection for IDLE"; - pushReceiver.pushError(message, null); - - throw new MessagingException(message); - } - } - - private void checkConnectionIdleCapable(ImapConnection conn) throws MessagingException { - if (!conn.isIdleCapable()) { - stop = true; - - String message = "IMAP server is not IDLE capable: " + conn.toString(); - pushReceiver.pushError(message, null); - - throw new MessagingException(message); - } - } - - private void setReadTimeoutForIdle(ImapConnection conn) throws SocketException { - int idleRefreshTimeout = store.getStoreConfig().getIdleRefreshMinutes() * 60 * 1000; - conn.setReadTimeout(idleRefreshTimeout + IDLE_READ_TIMEOUT_INCREMENT); - } - - @Override - public void handleAsyncUntaggedResponse(ImapResponse response) { - if (K9MailLib.isDebug()) { - Timber.v("Got async response: %s", response); - } - - if (stop) { - if (K9MailLib.isDebug()) { - Timber.d("Got async untagged response: %s, but stop is set for %s", response, getLogId()); - } - - idleStopper.stopIdle(); - } else { - if (response.getTag() == null) { - if (response.size() > 1) { - Object responseType = response.get(1); - if (equalsIgnoreCase(responseType, "EXISTS") || equalsIgnoreCase(responseType, "EXPUNGE") || - equalsIgnoreCase(responseType, "FETCH")) { - - wakeLock.acquire(PUSH_WAKE_LOCK_TIMEOUT); - - if (K9MailLib.isDebug()) { - Timber.d("Got useful async untagged response: %s for %s", response, getLogId()); - } - - idleStopper.stopIdle(); - } - } else if (response.isContinuationRequested()) { - if (K9MailLib.isDebug()) { - Timber.d("Idling %s", getLogId()); - } - - idleStopper.startAcceptingDoneContinuation(connection); - wakeLock.release(); - } - } - } - } - - private void clearStoredUntaggedResponses() { - synchronized (storedUntaggedResponses) { - storedUntaggedResponses.clear(); - } - } - - private void processStoredUntaggedResponses() throws MessagingException { - while (true) { - List untaggedResponses = getAndClearStoredUntaggedResponses(); - if (untaggedResponses.isEmpty()) { - break; - } - - if (K9MailLib.isDebug()) { - Timber.i("Processing %d untagged responses from previous commands for %s", - untaggedResponses.size(), getLogId()); - } - - processUntaggedResponses(untaggedResponses); - } - } - - private List getAndClearStoredUntaggedResponses() { - synchronized (storedUntaggedResponses) { - if (storedUntaggedResponses.isEmpty()) { - return Collections.emptyList(); - } - - List untaggedResponses = new ArrayList<>(storedUntaggedResponses); - storedUntaggedResponses.clear(); - - return untaggedResponses; - } - } - - private void processUntaggedResponses(List responses) throws MessagingException { - boolean skipSync = false; - - int oldMessageCount = messageCount; - if (oldMessageCount == -1) { - skipSync = true; - } - - List flagSyncMsgSeqs = new ArrayList<>(); - List removeMsgUids = new LinkedList<>(); - - for (ImapResponse response : responses) { - oldMessageCount += processUntaggedResponse(oldMessageCount, response, flagSyncMsgSeqs, removeMsgUids); - } - - if (!skipSync) { - if (oldMessageCount < 0) { - oldMessageCount = 0; - } - - if (messageCount > oldMessageCount) { - syncMessages(messageCount); - } - } - - if (K9MailLib.isDebug()) { - Timber.d("UIDs for messages needing flag sync are %s for %s", flagSyncMsgSeqs, getLogId()); - } - - if (!flagSyncMsgSeqs.isEmpty()) { - syncMessages(flagSyncMsgSeqs); - } - - if (!removeMsgUids.isEmpty()) { - removeMessages(removeMsgUids); - } - } - - private int processUntaggedResponse(long oldMessageCount, ImapResponse response, List flagSyncMsgSeqs, - List removeMsgUids) { - superHandleUntaggedResponse(response); - - int messageCountDelta = 0; - if (response.getTag() == null && response.size() > 1) { - try { - Object responseType = response.get(1); - if (equalsIgnoreCase(responseType, "FETCH")) { - Timber.i("Got FETCH %s", response); - - long msgSeq = response.getLong(0); - - if (K9MailLib.isDebug()) { - Timber.d("Got untagged FETCH for msgseq %d for %s", msgSeq, getLogId()); - } - - if (!flagSyncMsgSeqs.contains(msgSeq)) { - flagSyncMsgSeqs.add(msgSeq); - } - } - - if (equalsIgnoreCase(responseType, "EXPUNGE")) { - long msgSeq = response.getLong(0); - if (msgSeq <= oldMessageCount) { - messageCountDelta = -1; - } - - if (K9MailLib.isDebug()) { - Timber.d("Got untagged EXPUNGE for msgseq %d for %s", msgSeq, getLogId()); - } - - List newSeqs = new ArrayList<>(); - Iterator flagIter = flagSyncMsgSeqs.iterator(); - while (flagIter.hasNext()) { - long flagMsg = flagIter.next(); - if (flagMsg >= msgSeq) { - flagIter.remove(); - if (flagMsg > msgSeq) { - newSeqs.add(flagMsg); - } - } - } - - flagSyncMsgSeqs.addAll(newSeqs); - - List msgSeqs = new ArrayList<>(msgSeqUidMap.keySet()); - Collections.sort(msgSeqs); // Have to do comparisons in order because of msgSeq reductions - - for (long msgSeqNum : msgSeqs) { - if (K9MailLib.isDebug()) { - Timber.v("Comparing EXPUNGEd msgSeq %d to %d", msgSeq, msgSeqNum); - } - - if (msgSeqNum == msgSeq) { - String uid = msgSeqUidMap.get(msgSeqNum); - - if (K9MailLib.isDebug()) { - Timber.d("Scheduling removal of UID %s because msgSeq %d was expunged", uid, msgSeqNum); - } - - removeMsgUids.add(uid); - msgSeqUidMap.remove(msgSeqNum); - } else if (msgSeqNum > msgSeq) { - String uid = msgSeqUidMap.get(msgSeqNum); - - if (K9MailLib.isDebug()) { - Timber.d("Reducing msgSeq for UID %s from %d to %d", uid, msgSeqNum, (msgSeqNum - 1)); - } - - msgSeqUidMap.remove(msgSeqNum); - msgSeqUidMap.put(msgSeqNum - 1, uid); - } - } - } - } catch (Exception e) { - Timber.e(e, "Could not handle untagged FETCH for %s", getLogId()); - } - } - - return messageCountDelta; - } - - private void syncMessages(int end) throws MessagingException { - long oldUidNext = getOldUidNext(); - - List messageList = getMessages(end, end, null, true, null); - - if (messageList != null && messageList.size() > 0) { - long newUid = Long.parseLong(messageList.get(0).getUid()); - - if (K9MailLib.isDebug()) { - Timber.i("Got newUid %s for message %d on %s", newUid, end, getLogId()); - } - - long startUid = oldUidNext; - if (startUid < newUid - 10) { - startUid = newUid - 10; - } - - if (startUid < 1) { - startUid = 1; - } - - if (newUid >= startUid) { - if (K9MailLib.isDebug()) { - Timber.i("Needs sync from uid %d to %d for %s", startUid, newUid, getLogId()); - } - - List messages = new ArrayList<>(); - for (long uid = startUid; uid <= newUid; uid++) { - ImapMessage message = new ImapMessage(Long.toString(uid)); - messages.add(message); - } - - if (!messages.isEmpty()) { - pushReceiver.messagesArrived(getServerId(), messages); - } - } - } - } - - private void syncMessages(List flagSyncMsgSeqs) { - try { - Set messageSeqSet = new HashSet<>(flagSyncMsgSeqs); - List messageList = getMessages(messageSeqSet, true, null); - - List messages = new ArrayList<>(messageList); - pushReceiver.messagesFlagsChanged(getServerId(), messages); - } catch (Exception e) { - pushReceiver.pushError("Exception while processing Push untagged responses", e); - } - } - - private void removeMessages(List removeUids) { - List messages = new ArrayList<>(removeUids.size()); - - try { - List existingMessages = getMessagesFromUids(removeUids); - for (Message existingMessage : existingMessages) { - needsPoll = true; - msgSeqUidMap.clear(); - - String existingUid = existingMessage.getUid(); - Timber.w("Message with UID %s still exists on server, not expunging", existingUid); - - removeUids.remove(existingUid); - } - - for (String uid : removeUids) { - ImapMessage message = new ImapMessage(uid); - - try { - message.setFlag(Flag.DELETED, true); - } catch (MessagingException me) { - Timber.e("Unable to set DELETED flag on message %s", message.getUid()); - } - - messages.add(message); - } - - pushReceiver.messagesRemoved(getServerId(), messages); - } catch (Exception e) { - Timber.e("Cannot remove EXPUNGEd messages"); - } - } - - private void syncFolderOnConnect() throws MessagingException { - processStoredUntaggedResponses(); - - if (messageCount == -1) { - throw new MessagingException("Message count = -1 for idling"); - } - - pushReceiver.syncFolder(getServerId()); - } - - private void notifyMessagesArrived(long startUid, long uidNext) { - if (K9MailLib.isDebug()) { - Timber.i("Needs sync from uid %d to %d for %s", startUid, uidNext, getLogId()); - } - - int count = (int) (uidNext - startUid); - List messages = new ArrayList<>(count); - - for (long uid = startUid; uid < uidNext; uid++) { - ImapMessage message = new ImapMessage(Long.toString(uid)); - messages.add(message); - } - - pushReceiver.messagesArrived(getServerId(), messages); - } - - private long getOldUidNext() { - long oldUidNext = -1L; - try { - String serializedPushState = pushReceiver.getPushState(getServerId()); - ImapPushState pushState = ImapPushState.parse(serializedPushState); - oldUidNext = pushState.uidNext; - - if (K9MailLib.isDebug()) { - Timber.i("Got oldUidNext %d for %s", oldUidNext, getLogId()); - } - } catch (Exception e) { - Timber.e(e, "Unable to get oldUidNext for %s", getLogId()); - } - - return oldUidNext; - } - } - - /** - * Ensure the DONE continuation is only sent when the IDLE command was sent and hasn't completed yet. - */ - private static class IdleStopper { - private boolean acceptDoneContinuation = false; - private ImapConnection imapConnection; - - - public synchronized void startAcceptingDoneContinuation(ImapConnection connection) { - if (connection == null) { - throw new NullPointerException("connection must not be null"); - } - - acceptDoneContinuation = true; - imapConnection = connection; - } - - public synchronized void stopAcceptingDoneContinuation() { - acceptDoneContinuation = false; - imapConnection = null; - } - - public synchronized void stopIdle() { - if (acceptDoneContinuation) { - acceptDoneContinuation = false; - sendDone(); - } - } - - private void sendDone() { - try { - imapConnection.setReadTimeout(SOCKET_READ_TIMEOUT); - imapConnection.sendContinuation("DONE"); - } catch (IOException e) { - imapConnection.close(); - } - } - } -} diff --git a/mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/ImapPushState.java b/mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/ImapPushState.java deleted file mode 100644 index b784e7f4b..000000000 --- a/mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/ImapPushState.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.fsck.k9.mail.store.imap; - - -import timber.log.Timber; - - -class ImapPushState { - private static final long DEFAULT_UID_NEXT = -1L; - private static final String PUSH_STATE_PREFIX = "uidNext="; - private static final int PUSH_STATE_PREFIX_LENGTH = 8; - - - public final long uidNext; - - public static ImapPushState parse(String pushState) { - if (pushState == null || !pushState.startsWith(PUSH_STATE_PREFIX)) { - return createDefaultImapPushState(); - } - - String value = pushState.substring(PUSH_STATE_PREFIX_LENGTH); - try { - long newUidNext = Long.parseLong(value); - - return new ImapPushState(newUidNext); - } catch (NumberFormatException e) { - Timber.e(e, "Unable to part uidNext value %s", value); - } - - return createDefaultImapPushState(); - } - - static ImapPushState createDefaultImapPushState() { - return new ImapPushState(DEFAULT_UID_NEXT); - } - - public ImapPushState(long uidNext) { - this.uidNext = uidNext; - } - - @Override - public String toString() { - return "uidNext=" + uidNext; - } -} diff --git a/mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/ImapPusher.java b/mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/ImapPusher.java deleted file mode 100644 index 38297f4d4..000000000 --- a/mail/protocols/imap/src/main/java/com/fsck/k9/mail/store/imap/ImapPusher.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.fsck.k9.mail.store.imap; - - -import java.util.ArrayList; -import java.util.List; - -import com.fsck.k9.mail.K9MailLib; -import com.fsck.k9.mail.PushReceiver; -import com.fsck.k9.mail.Pusher; -import com.fsck.k9.mail.power.PowerManager; -import timber.log.Timber; - - -public class ImapPusher implements Pusher { - private final ImapStore store; - private final PushReceiver pushReceiver; - private final PowerManager powerManager; - - private final List folderPushers = new ArrayList<>(); - - private long lastRefresh = -1; - - - public ImapPusher(ImapStore store, PushReceiver pushReceiver, PowerManager powerManager) { - this.store = store; - this.pushReceiver = pushReceiver; - this.powerManager = powerManager; - } - - @Override - public void start(List folderServerIds) { - synchronized (folderPushers) { - stop(); - - setLastRefresh(currentTimeMillis()); - - for (String folderName : folderServerIds) { - ImapFolderPusher pusher = createImapFolderPusher(folderName); - folderPushers.add(pusher); - - pusher.start(); - } - } - } - - @Override - public void refresh() { - synchronized (folderPushers) { - for (ImapFolderPusher folderPusher : folderPushers) { - try { - folderPusher.refresh(); - } catch (Exception e) { - Timber.e(e, "Got exception while refreshing for %s", folderPusher.getServerId()); - } - } - } - } - - @Override - public void stop() { - if (K9MailLib.isDebug()) { - Timber.i("Requested stop of IMAP pusher"); - } - - synchronized (folderPushers) { - for (ImapFolderPusher folderPusher : folderPushers) { - try { - if (K9MailLib.isDebug()) { - Timber.i("Requesting stop of IMAP folderPusher %s", folderPusher.getServerId()); - } - - folderPusher.stop(); - } catch (Exception e) { - Timber.e(e, "Got exception while stopping %s", folderPusher.getServerId()); - } - } - - folderPushers.clear(); - } - } - - @Override - public int getRefreshInterval() { - return (store.getStoreConfig().getIdleRefreshMinutes() * 60 * 1000); - } - - @Override - public long getLastRefresh() { - return lastRefresh; - } - - @Override - public void setLastRefresh(long lastRefresh) { - this.lastRefresh = lastRefresh; - } - - ImapFolderPusher createImapFolderPusher(String folderName) { - return new ImapFolderPusher(store, folderName, pushReceiver, powerManager); - } - - long currentTimeMillis() { - return System.currentTimeMillis(); - } -} diff --git a/mail/protocols/imap/src/test/java/com/fsck/k9/mail/store/imap/ImapFolderTest.java b/mail/protocols/imap/src/test/java/com/fsck/k9/mail/store/imap/ImapFolderTest.java index 40f8ea713..767378f07 100644 --- a/mail/protocols/imap/src/test/java/com/fsck/k9/mail/store/imap/ImapFolderTest.java +++ b/mail/protocols/imap/src/test/java/com/fsck/k9/mail/store/imap/ImapFolderTest.java @@ -966,28 +966,6 @@ public class ImapFolderTest { assertCommandIssued("UID STORE 1:* +FLAGS.SILENT (\\Seen)"); } - @Test - public void getNewPushState_withNewerUid_shouldReturnNewPushState() throws Exception { - ImapFolder folder = createFolder("Folder"); - prepareImapFolderForOpen(OPEN_MODE_RW); - ImapMessage message = createImapMessage("2"); - - String newPushState = folder.getNewPushState("uidNext=2", message); - - assertEquals("uidNext=3", newPushState); - } - - @Test - public void getNewPushState_withoutNewerUid_shouldReturnNull() throws Exception { - ImapFolder folder = createFolder("Folder"); - prepareImapFolderForOpen(OPEN_MODE_RW); - ImapMessage message = createImapMessage("1"); - - String newPushState = folder.getNewPushState("uidNext=2", message); - - assertNull(newPushState); - } - @Test public void search_withFullTextSearchEnabled_shouldIssueRespectiveCommand() throws Exception { ImapFolder folder = createFolder("Folder"); diff --git a/mail/protocols/imap/src/test/java/com/fsck/k9/mail/store/imap/ImapPushStateTest.java b/mail/protocols/imap/src/test/java/com/fsck/k9/mail/store/imap/ImapPushStateTest.java deleted file mode 100644 index 70e4950a4..000000000 --- a/mail/protocols/imap/src/test/java/com/fsck/k9/mail/store/imap/ImapPushStateTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.fsck.k9.mail.store.imap; - - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - - -public class ImapPushStateTest { - @Test - public void parse_withValidArgument() throws Exception { - ImapPushState result = ImapPushState.parse("uidNext=42"); - - assertNotNull(result); - assertEquals(42L, result.uidNext); - } - - @Test - public void parse_withNullArgument_shouldReturnUidNextOfMinusOne() throws Exception { - ImapPushState result = ImapPushState.parse(null); - - assertNotNull(result); - assertEquals(-1L, result.uidNext); - } - - @Test - public void parse_withEmptyArgument_shouldReturnUidNextOfMinusOne() throws Exception { - ImapPushState result = ImapPushState.parse(""); - - assertNotNull(result); - assertEquals(-1L, result.uidNext); - } - - @Test - public void parse_withInvalidArgument_shouldReturnUidNextOfMinusOne() throws Exception { - ImapPushState result = ImapPushState.parse("xyz"); - - assertNotNull(result); - assertEquals(-1L, result.uidNext); - } - - @Test - public void parse_withIncompleteArgument_shouldReturnUidNextOfMinusOne() throws Exception { - ImapPushState result = ImapPushState.parse("uidNext="); - - assertNotNull(result); - assertEquals(-1L, result.uidNext); - } - - @Test - public void parse_withoutIntegerAsUidNext_shouldReturnUidNextOfMinusOne() throws Exception { - ImapPushState result = ImapPushState.parse("uidNext=xyz"); - - assertNotNull(result); - assertEquals(-1L, result.uidNext); - } - - @Test - public void toString_shouldReturnExpectedResult() throws Exception { - ImapPushState imapPushState = new ImapPushState(23L); - - String result = imapPushState.toString(); - - assertEquals("uidNext=23", result); - } -} diff --git a/mail/protocols/imap/src/test/java/com/fsck/k9/mail/store/imap/ImapPusherTest.java b/mail/protocols/imap/src/test/java/com/fsck/k9/mail/store/imap/ImapPusherTest.java deleted file mode 100644 index 7aeae8322..000000000 --- a/mail/protocols/imap/src/test/java/com/fsck/k9/mail/store/imap/ImapPusherTest.java +++ /dev/null @@ -1,181 +0,0 @@ -package com.fsck.k9.mail.store.imap; - - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import com.fsck.k9.mail.PushReceiver; -import com.fsck.k9.mail.power.PowerManager; -import com.fsck.k9.mail.store.StoreConfig; -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - - -public class ImapPusherTest { - private ImapStore imapStore; - private TestImapPusher imapPusher; - - - @Before - public void setUp() throws Exception { - imapStore = mock(ImapStore.class); - - PushReceiver pushReceiver = mock(PushReceiver.class); - PowerManager powerManager = mock(PowerManager.class); - imapPusher = new TestImapPusher(imapStore, pushReceiver, powerManager); - } - - @Test - public void start_shouldSetLastRefreshToCurrentTime() throws Exception { - List folderNames = Collections.singletonList("INBOX"); - - imapPusher.start(folderNames); - - assertEquals(TestImapPusher.CURRENT_TIME_MILLIS, imapPusher.getLastRefresh()); - } - - @Test - public void start_withSingleFolderName_shouldCreateImapFolderPusherAndCallStartOnIt() throws Exception { - List folderNames = Collections.singletonList("INBOX"); - - imapPusher.start(folderNames); - - List imapFolderPushers = imapPusher.getImapFolderPushers(); - assertEquals(1, imapFolderPushers.size()); - ImapFolderPusher imapFolderPusher = imapFolderPushers.get(0); - verify(imapFolderPusher).start(); - } - - @Test - public void start_calledAfterStart_shouldStopFirstImapFolderPusher() throws Exception { - imapPusher.start(Collections.singletonList("Drafts")); - - imapPusher.start(Collections.singletonList("INBOX")); - - ImapFolderPusher draftsPusher = imapPusher.getImapFolderPushers().get(0); - verify(draftsPusher).stop(); - } - - @Test - public void start_withTwoFolderNames_shouldCreateTwoImapFolderPushersAndCallStart() throws Exception { - List folderNames = Arrays.asList("Important", "Drafts"); - - imapPusher.start(folderNames); - - List imapFolderPushers = imapPusher.getImapFolderPushers(); - assertEquals(2, imapFolderPushers.size()); - ImapFolderPusher imapFolderPusherOne = imapFolderPushers.get(0); - ImapFolderPusher imapFolderPusherTwo = imapFolderPushers.get(1); - verify(imapFolderPusherOne).start(); - verify(imapFolderPusherTwo).start(); - } - - @Test - public void stop_withoutStartBeingCalled_shouldNotCreateAnyImapFolderPushers() throws Exception { - imapPusher.stop(); - - List imapFolderPushers = imapPusher.getImapFolderPushers(); - assertEquals(0, imapFolderPushers.size()); - } - - @Test - public void stop_afterStartWithSingleFolderName_shouldStopImapFolderPusher() throws Exception { - List folderNames = Collections.singletonList("Archive"); - imapPusher.start(folderNames); - - imapPusher.stop(); - - List imapFolderPushers = imapPusher.getImapFolderPushers(); - assertEquals(1, imapFolderPushers.size()); - ImapFolderPusher imapFolderPusher = imapFolderPushers.get(0); - verify(imapFolderPusher).stop(); - } - - @Test - public void stop_withImapFolderPusherThrowing_shouldNotThrow() throws Exception { - List folderNames = Collections.singletonList("Archive"); - imapPusher.start(folderNames); - ImapFolderPusher imapFolderPusher = imapPusher.getImapFolderPushers().get(0); - doThrow(RuntimeException.class).when(imapFolderPusher).stop(); - - imapPusher.stop(); - } - - @Test - public void refresh_shouldCallRefreshOnStartedImapFolderPusher() throws Exception { - List folderNames = Collections.singletonList("Trash"); - imapPusher.start(folderNames); - - imapPusher.refresh(); - - List imapFolderPushers = imapPusher.getImapFolderPushers(); - assertEquals(1, imapFolderPushers.size()); - ImapFolderPusher imapFolderPusher = imapFolderPushers.get(0); - verify(imapFolderPusher).refresh(); - } - - @Test - public void refresh_withImapFolderPusherThrowing_shouldNotThrow() throws Exception { - List folderNames = Collections.singletonList("Folder"); - imapPusher.start(folderNames); - ImapFolderPusher imapFolderPusher = imapPusher.getImapFolderPushers().get(0); - doThrow(RuntimeException.class).when(imapFolderPusher).refresh(); - - imapPusher.refresh(); - } - - @Test - public void getRefreshInterval() throws Exception { - StoreConfig storeConfig = mock(StoreConfig.class); - when(storeConfig.getIdleRefreshMinutes()).thenReturn(23); - when(imapStore.getStoreConfig()).thenReturn(storeConfig); - - int result = imapPusher.getRefreshInterval(); - - assertEquals(23 * 60 * 1000, result); - } - - @Test - public void getLastRefresh_shouldBeMinusOneInitially() throws Exception { - long result = imapPusher.getLastRefresh(); - - assertEquals(-1L, result); - } - - - static class TestImapPusher extends ImapPusher { - public static final long CURRENT_TIME_MILLIS = 1454375675162L; - - - private final List imapFolderPushers = new ArrayList<>(); - - - public TestImapPusher(ImapStore store, PushReceiver receiver, PowerManager powerManager) { - super(store, receiver, powerManager); - } - - @Override - ImapFolderPusher createImapFolderPusher(String folderName) { - ImapFolderPusher imapFolderPusher = mock(ImapFolderPusher.class); - imapFolderPushers.add(imapFolderPusher); - return imapFolderPusher; - } - - public List getImapFolderPushers() { - return imapFolderPushers; - } - - @Override - long currentTimeMillis() { - return CURRENT_TIME_MILLIS; - } - } -}