Add expiration check on build freshness.

// FREEBIE
master
Moxie Marlinspike 2015-01-11 20:27:34 -08:00
parent 12845da91a
commit a0ed0842a0
15 changed files with 135 additions and 50 deletions

View File

@ -98,6 +98,8 @@ android {
defaultConfig {
minSdkVersion 9
targetSdkVersion 19
buildConfigField "long", "BUILD_TIMESTAMP", System.currentTimeMillis() + "L"
}
compileOptions {
@ -105,44 +107,39 @@ android {
targetCompatibility JavaVersion.VERSION_1_7
}
android {
buildTypes {
debug {
minifyEnabled false
}
release {
minifyEnabled false
}
}
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
androidTest {
java.srcDirs = ['androidTest/java']
resources.srcDirs = ['androidTest/java']
aidl.srcDirs = ['androidTest/java']
renderscript.srcDirs = ['androidTest/java']
}
}
}
signingConfigs {
release
}
buildTypes {
debug {
minifyEnabled false
}
release {
minifyEnabled false
signingConfig signingConfigs.release
}
}
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
androidTest {
java.srcDirs = ['androidTest/java']
resources.srcDirs = ['androidTest/java']
aidl.srcDirs = ['androidTest/java']
renderscript.srcDirs = ['androidTest/java']
}
}
lintOptions {
abortOnError false
}

View File

@ -816,6 +816,8 @@
<string name="text_secure_normal__mark_all_as_read">Mark all read</string>
<!-- reminder_header -->
<string name="reminder_header_expired_build">Your build of TextSecure has expired!</string>
<string name="reminder_header_expired_build_details">Messages will no longer send successfully, please update to the most recent version.</string>
<string name="reminder_header_sms_default_title">Use as default SMS app?</string>
<string name="reminder_header_sms_default_text">TextSecure is not currently your default SMS app.</string>
<string name="reminder_header_sms_import_title">Import system SMS?</string>

View File

@ -43,6 +43,7 @@ import android.widget.AdapterView;
import android.widget.ListView;
import org.thoughtcrime.securesms.components.DefaultSmsReminder;
import org.thoughtcrime.securesms.components.ExpiredBuildReminder;
import org.thoughtcrime.securesms.components.PushRegistrationReminder;
import org.thoughtcrime.securesms.components.ReminderView;
import org.thoughtcrime.securesms.components.SystemSmsImportReminder;
@ -163,7 +164,9 @@ public class ConversationListFragment extends ListFragment
}
private void initializeReminders() {
if (DefaultSmsReminder.isEligible(getActivity())) {
if (ExpiredBuildReminder.isEligible(getActivity())) {
reminderView.showReminder(new ExpiredBuildReminder());
} else if (DefaultSmsReminder.isEligible(getActivity())) {
reminderView.showReminder(new DefaultSmsReminder(getActivity()));
} else if (SystemSmsImportReminder.isEligible(getActivity())) {
reminderView.showReminder(new SystemSmsImportReminder(getActivity(), masterSecret));

View File

@ -0,0 +1,7 @@
package org.thoughtcrime.securesms;
public class TextSecureExpiredException extends Exception {
public TextSecureExpiredException(String message) {
super(message);
}
}

View File

@ -0,0 +1,35 @@
package org.thoughtcrime.securesms.components;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.provider.Telephony;
import android.util.Log;
import android.view.View;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.TextSecureExpiredException;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
public class ExpiredBuildReminder extends Reminder {
private static final String TAG = ExpiredBuildReminder.class.getSimpleName();
public ExpiredBuildReminder() {
super(R.drawable.ic_dialog_alert_holo_dark,
R.string.reminder_header_expired_build,
R.string.reminder_header_expired_build_details);
}
@Override
public boolean isDismissable() {
return false;
}
public static boolean isEligible(Context context) {
return !Util.isBuildFresh();
}
}

View File

@ -46,4 +46,8 @@ public abstract class Reminder {
public void setCancelListener(OnClickListener cancelListener) {
this.cancelListener = cancelListener;
}
public boolean isDismissable() {
return true;
}
}

View File

@ -56,15 +56,21 @@ public class ReminderView extends LinearLayout {
icon.setImageResource(reminder.getIconResId());
title.setText(reminder.getTitleResId());
text.setText(reminder.getTextResId());
ok.setOnClickListener(reminder.getOkListener());
cancel.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
hide();
if (reminder.getCancelListener() != null) reminder.getCancelListener().onClick(v);
}
});
container.setVisibility(View.VISIBLE);
if (reminder.isDismissable()) {
ok.setOnClickListener(reminder.getOkListener());
cancel.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
hide();
if (reminder.getCancelListener() != null) reminder.getCancelListener().onClick(v);
}
});
container.setVisibility(View.VISIBLE);
} else {
ok.setVisibility(View.GONE);
cancel.setVisibility(View.GONE);
}
}
public void hide() {

View File

@ -31,7 +31,6 @@ import org.whispersystems.libaxolotl.NoSessionException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import ws.com.google.android.mms.MmsException;
@ -43,7 +42,7 @@ import ws.com.google.android.mms.pdu.PduPart;
import ws.com.google.android.mms.pdu.SendConf;
import ws.com.google.android.mms.pdu.SendReq;
public class MmsSendJob extends MasterSecretJob {
public class MmsSendJob extends SendJob {
private static final String TAG = MmsSendJob.class.getSimpleName();
@ -66,7 +65,7 @@ public class MmsSendJob extends MasterSecretJob {
}
@Override
public void onRun(MasterSecret masterSecret) throws MmsException, NoSuchMessageException, IOException {
public void onSend(MasterSecret masterSecret) throws MmsException, NoSuchMessageException, IOException {
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
SendReq message = database.getOutgoingMessage(masterSecret, messageId);

View File

@ -66,7 +66,7 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
}
@Override
public void onRun(MasterSecret masterSecret) throws MmsException, IOException, NoSuchMessageException {
public void onSend(MasterSecret masterSecret) throws MmsException, IOException, NoSuchMessageException {
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
SendReq message = database.getOutgoingMessage(masterSecret, messageId);

View File

@ -57,7 +57,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
}
@Override
public void onRun(MasterSecret masterSecret)
public void onSend(MasterSecret masterSecret)
throws RetryLaterException, MmsException, NoSuchMessageException
{
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);

View File

@ -31,7 +31,7 @@ import ws.com.google.android.mms.ContentType;
import ws.com.google.android.mms.pdu.PduPart;
import ws.com.google.android.mms.pdu.SendReq;
public abstract class PushSendJob extends MasterSecretJob {
public abstract class PushSendJob extends SendJob {
private static final String TAG = PushSendJob.class.getSimpleName();

View File

@ -51,7 +51,7 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
}
@Override
public void onRun(MasterSecret masterSecret) throws NoSuchMessageException, RetryLaterException {
public void onSend(MasterSecret masterSecret) throws NoSuchMessageException, RetryLaterException {
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
SmsMessageRecord record = database.getMessage(masterSecret, messageId);
String destination = record.getIndividualRecipient().getNumber();

View File

@ -0,0 +1,29 @@
package org.thoughtcrime.securesms.jobs;
import android.content.Context;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.TextSecureExpiredException;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.jobqueue.JobParameters;
public abstract class SendJob extends MasterSecretJob {
public SendJob(Context context, JobParameters parameters) {
super(context, parameters);
}
@Override
public final void onRun(MasterSecret masterSecret) throws Exception {
if (!Util.isBuildFresh()) {
throw new TextSecureExpiredException(String.format("TextSecure expired (build %d, now %d)",
BuildConfig.BUILD_TIMESTAMP,
System.currentTimeMillis()));
}
onSend(masterSecret);
}
protected abstract void onSend(MasterSecret masterSecret) throws Exception;
}

View File

@ -31,7 +31,7 @@ import org.whispersystems.libaxolotl.NoSessionException;
import java.util.ArrayList;
public class SmsSendJob extends MasterSecretJob {
public class SmsSendJob extends SendJob {
private static final String TAG = SmsSendJob.class.getSimpleName();
@ -48,7 +48,7 @@ public class SmsSendJob extends MasterSecretJob {
}
@Override
public void onRun(MasterSecret masterSecret) throws NoSuchMessageException {
public void onSend(MasterSecret masterSecret) throws NoSuchMessageException {
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
SmsMessageRecord record = database.getMessage(masterSecret, messageId);

View File

@ -32,6 +32,8 @@ import android.text.TextUtils;
import android.text.style.StyleSpan;
import android.widget.EditText;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.TextSecureExpiredException;
import org.whispersystems.textsecure.api.util.InvalidNumberException;
import org.whispersystems.textsecure.api.util.PhoneNumberFormatter;
@ -288,6 +290,7 @@ public class Util {
}
}
public static boolean isBuildFresh() {
return BuildConfig.BUILD_TIMESTAMP + TimeUnit.DAYS.toMillis(180) > System.currentTimeMillis();
}
}