move routing logic to all activities

Fixes #2239
Closes #27923

// FREEBIE
This commit is contained in:
Jake McGinty 2014-12-15 12:25:55 -08:00 committed by Moxie Marlinspike
parent 141ee6565d
commit 0ff99258ac
52 changed files with 503 additions and 984 deletions

View File

@ -45,36 +45,6 @@
<meta-data android:name="com.google.android.gms.version" <meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" /> android:value="@integer/google_play_services_version" />
<activity android:name=".RoutingActivity"
android:theme="@style/NoAnimation.Theme.BlackScreen"
android:launchMode="singleTask"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SENDTO"/>
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="audio/*" />
<data android:mimeType="image/*" />
<data android:mimeType="text/plain" />
<data android:mimeType="video/*" />
</intent-filter>
</activity>
<activity android:name=".RegistrationProblemsActivity" <activity android:name=".RegistrationProblemsActivity"
android:theme="@style/TextSecure.Light.Dialog" android:theme="@style/TextSecure.Light.Dialog"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/> android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
@ -109,17 +79,35 @@
android:launchMode="singleTask" android:launchMode="singleTask"
android:noHistory="true" android:noHistory="true"
android:windowSoftInputMode="stateHidden" android:windowSoftInputMode="stateHidden"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/> android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="audio/*" />
<data android:mimeType="image/*" />
<data android:mimeType="text/plain" />
<data android:mimeType="video/*" />
</intent-filter>
</activity>
<activity android:name=".ConversationListActivity" <activity android:name=".ConversationListActivity"
android:label="@string/app_name" android:label="@string/app_name"
android:launchMode="singleTask" android:launchMode="singleTask"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/> android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ConversationActivity" <activity android:name=".ConversationActivity"
android:windowSoftInputMode="stateUnchanged" android:windowSoftInputMode="stateUnchanged"
android:launchMode="singleTask" android:launchMode="singleTask"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/> android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
<activity android:name=".MessageDetailsActivity" <activity android:name=".MessageDetailsActivity"
android:label="Message Details" android:label="Message Details"
@ -145,12 +133,12 @@
android:label="@string/AndroidManifest__create_passphrase" android:label="@string/AndroidManifest__create_passphrase"
android:windowSoftInputMode="stateUnchanged" android:windowSoftInputMode="stateUnchanged"
android:theme="@style/TextSecure.IntroTheme" android:theme="@style/TextSecure.IntroTheme"
android:launchMode="singleTop" android:launchMode="singleTask"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/> android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".PassphrasePromptActivity" <activity android:name=".PassphrasePromptActivity"
android:label="@string/AndroidManifest__enter_passphrase" android:label="@string/AndroidManifest__enter_passphrase"
android:launchMode="singleTop" android:launchMode="singleTask"
android:theme="@style/TextSecure.IntroTheme" android:theme="@style/TextSecure.IntroTheme"
android:windowSoftInputMode="stateAlwaysVisible" android:windowSoftInputMode="stateAlwaysVisible"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/> android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
@ -224,6 +212,17 @@
android:theme="@android:style/Theme.Translucent.NoTitleBar" android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/> android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".SmsSendtoActivity">
<intent-filter>
<action android:name="android.intent.action.SENDTO" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</activity>
<activity android:name="com.soundcloud.android.crop.CropImageActivity" /> <activity android:name="com.soundcloud.android.crop.CropImageActivity" />
<service android:enabled="true" android:name=".service.ApplicationMigrationService"/> <service android:enabled="true" android:name=".service.ApplicationMigrationService"/>
@ -245,14 +244,6 @@
</service> </service>
<!-- <receiver android:name=".service.BootListener" -->
<!-- android:enabled="true" -->
<!-- android:exported="false">-->
<!-- <intent-filter>-->
<!-- <action android:name="android.intent.action.BOOT_COMPLETED" />-->
<!-- </intent-filter>-->
<!-- </receiver>-->
<receiver android:name=".gcm.GcmBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND" > <receiver android:name=".gcm.GcmBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter> <intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" /> <action android:name="com.google.android.c2dm.intent.RECEIVE" />

View File

@ -14,9 +14,7 @@
android:orientation="vertical" android:orientation="vertical"
android:gravity="bottom"> android:gravity="bottom">
<fragment <FrameLayout android:id="@+id/fragment_content"
android:id="@+id/fragment_content"
android:name="org.thoughtcrime.securesms.ConversationFragment"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_above="@+id/bottom_container" /> android:layout_above="@+id/bottom_container" />

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/fragment_content"
android:name="org.thoughtcrime.securesms.ConversationListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="@layout/conversation_list_fragment" />
</LinearLayout>

View File

@ -1,13 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout" android:id="@+id/drawer_layout"
android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<fragment android:id="@+id/fragment_content" </FrameLayout>
android:name="org.thoughtcrime.securesms.ShareFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>

View File

@ -115,6 +115,7 @@
<string name="ConversationActivity_error_leaving_group">Error leaving group...</string> <string name="ConversationActivity_error_leaving_group">Error leaving group...</string>
<string name="ConversationActivity_mms_not_supported_title">MMS not supported</string> <string name="ConversationActivity_mms_not_supported_title">MMS not supported</string>
<string name="ConversationActivity_mms_not_supported_message">This message cannot be sent since your carrier doesn\'t support MMS.</string> <string name="ConversationActivity_mms_not_supported_message">This message cannot be sent since your carrier doesn\'t support MMS.</string>
<string name="ConversationActivity_specify_recipient">Please choose a contact</string>
<!-- ConversationFragment --> <!-- ConversationFragment -->
<string name="ConversationFragment_message_details">Message details</string> <string name="ConversationFragment_message_details">Message details</string>

View File

@ -1,36 +0,0 @@
package org.thoughtcrime.securesms;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.HeaderViewListAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
public abstract class ActionBarListActivity extends ActionBarActivity {
private ListView mListView;
protected ListView getListView() {
if (mListView == null) {
mListView = (ListView) findViewById(android.R.id.list);
}
return mListView;
}
protected void setListAdapter(ListAdapter adapter) {
getListView().setAdapter(adapter);
}
protected ListAdapter getListAdapter() {
ListAdapter adapter = getListView().getAdapter();
if (adapter instanceof HeaderViewListAdapter) {
return ((HeaderViewListAdapter)adapter).getWrappedAdapter();
} else {
return adapter;
}
}
protected void onListItemClick(ListView lv, View v, int position, long id) {
getListView().getOnItemClickListener().onItemClick(lv, v, position, id);
}
}

View File

@ -20,6 +20,7 @@ import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.preference.Preference; import android.preference.Preference;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction; import android.support.v4.app.FragmentTransaction;
@ -35,7 +36,6 @@ import org.thoughtcrime.securesms.preferences.StoragePreferenceFragment;
import org.thoughtcrime.securesms.service.KeyCachingService; import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.MemoryCleaner;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
/** /**
@ -61,18 +61,24 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
@Override @Override
protected void onCreate(Bundle icicle) { protected void onPreCreate() {
dynamicTheme.onCreate(this); dynamicTheme.onCreate(this);
dynamicLanguage.onCreate(this); dynamicLanguage.onCreate(this);
super.onCreate(icicle); }
@Override
protected void onCreate(Bundle icicle, @NonNull MasterSecret masterSecret) {
this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); this.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Bundle fragmentArgs = new Bundle();
Fragment fragment = new ApplicationPreferenceFragment(); Fragment fragment = new ApplicationPreferenceFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentArgs.putParcelable("master_secret", masterSecret);
fragmentTransaction.replace(android.R.id.content, fragment); fragment.setArguments(fragmentArgs);
fragmentTransaction.commit();
getSupportFragmentManager().beginTransaction()
.replace(android.R.id.content, fragment)
.commit();
} }
@Override @Override
@ -104,12 +110,6 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
return true; return true;
} }
@Override
public void onDestroy() {
MemoryCleaner.clean((MasterSecret) getIntent().getParcelableExtra("master_secret"));
super.onDestroy();
}
@Override @Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals(TextSecurePreferences.THEME_PREF)) { if (key.equals(TextSecurePreferences.THEME_PREF)) {
@ -129,18 +129,19 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
super.onCreate(icicle); super.onCreate(icicle);
addPreferencesFromResource(R.xml.preferences); addPreferencesFromResource(R.xml.preferences);
MasterSecret masterSecret = getArguments().getParcelable("master_secret");
this.findPreference(PREFERENCE_CATEGORY_SMS_MMS) this.findPreference(PREFERENCE_CATEGORY_SMS_MMS)
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_SMS_MMS)); .setOnPreferenceClickListener(new CategoryClickListener(masterSecret, PREFERENCE_CATEGORY_SMS_MMS));
this.findPreference(PREFERENCE_CATEGORY_NOTIFICATIONS) this.findPreference(PREFERENCE_CATEGORY_NOTIFICATIONS)
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_NOTIFICATIONS)); .setOnPreferenceClickListener(new CategoryClickListener(masterSecret, PREFERENCE_CATEGORY_NOTIFICATIONS));
this.findPreference(PREFERENCE_CATEGORY_APP_PROTECTION) this.findPreference(PREFERENCE_CATEGORY_APP_PROTECTION)
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_APP_PROTECTION)); .setOnPreferenceClickListener(new CategoryClickListener(masterSecret, PREFERENCE_CATEGORY_APP_PROTECTION));
this.findPreference(PREFERENCE_CATEGORY_APPEARANCE) this.findPreference(PREFERENCE_CATEGORY_APPEARANCE)
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_APPEARANCE)); .setOnPreferenceClickListener(new CategoryClickListener(masterSecret, PREFERENCE_CATEGORY_APPEARANCE));
this.findPreference(PREFERENCE_CATEGORY_STORAGE) this.findPreference(PREFERENCE_CATEGORY_STORAGE)
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_STORAGE)); .setOnPreferenceClickListener(new CategoryClickListener(masterSecret, PREFERENCE_CATEGORY_STORAGE));
this.findPreference(PREFERENCE_CATEGORY_ADVANCED) this.findPreference(PREFERENCE_CATEGORY_ADVANCED)
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_ADVANCED)); .setOnPreferenceClickListener(new CategoryClickListener(masterSecret, PREFERENCE_CATEGORY_ADVANCED));
} }
@Override @Override
@ -164,9 +165,11 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
} }
private class CategoryClickListener implements Preference.OnPreferenceClickListener { private class CategoryClickListener implements Preference.OnPreferenceClickListener {
private MasterSecret masterSecret;
private String category; private String category;
public CategoryClickListener(String category) { public CategoryClickListener(MasterSecret masterSecret, String category) {
this.masterSecret = masterSecret;
this.category = category; this.category = category;
} }
@ -182,7 +185,10 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
fragment = new NotificationsPreferenceFragment(); fragment = new NotificationsPreferenceFragment();
break; break;
case PREFERENCE_CATEGORY_APP_PROTECTION: case PREFERENCE_CATEGORY_APP_PROTECTION:
Bundle args = new Bundle();
args.putParcelable("master_secret", masterSecret);
fragment = new AppProtectionPreferenceFragment(); fragment = new AppProtectionPreferenceFragment();
fragment.setArguments(args);
break; break;
case PREFERENCE_CATEGORY_APPEARANCE: case PREFERENCE_CATEGORY_APPEARANCE:
fragment = new AppearancePreferenceFragment(); fragment = new AppearancePreferenceFragment();

View File

@ -27,6 +27,7 @@ import android.os.AsyncTask;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.provider.ContactsContract; import android.provider.ContactsContract;
import android.support.annotation.NonNull;
import android.telephony.PhoneNumberUtils; import android.telephony.PhoneNumberUtils;
import android.text.Editable; import android.text.Editable;
import android.text.InputType; import android.text.InputType;
@ -94,7 +95,6 @@ import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.Emoji; import org.thoughtcrime.securesms.util.Emoji;
import org.thoughtcrime.securesms.util.GroupUtil; import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.MemoryCleaner;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libaxolotl.InvalidMessageException; import org.whispersystems.libaxolotl.InvalidMessageException;
@ -126,7 +126,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
public static final String RECIPIENTS_EXTRA = "recipients"; public static final String RECIPIENTS_EXTRA = "recipients";
public static final String THREAD_ID_EXTRA = "thread_id"; public static final String THREAD_ID_EXTRA = "thread_id";
public static final String MASTER_SECRET_EXTRA = "master_secret";
public static final String DRAFT_TEXT_EXTRA = "draft_text"; public static final String DRAFT_TEXT_EXTRA = "draft_text";
public static final String DRAFT_IMAGE_EXTRA = "draft_image"; public static final String DRAFT_IMAGE_EXTRA = "draft_image";
public static final String DRAFT_AUDIO_EXTRA = "draft_audio"; public static final String DRAFT_AUDIO_EXTRA = "draft_audio";
@ -143,6 +142,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private ComposeText composeText; private ComposeText composeText;
private SendButton sendButton; private SendButton sendButton;
private TextView charactersLeft; private TextView charactersLeft;
private ConversationFragment fragment;
private AttachmentTypeSelectorAdapter attachmentAdapter; private AttachmentTypeSelectorAdapter attachmentAdapter;
private AttachmentManager attachmentManager; private AttachmentManager attachmentManager;
@ -161,14 +161,19 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private DynamicLanguage dynamicLanguage = new DynamicLanguage(); private DynamicLanguage dynamicLanguage = new DynamicLanguage();
@Override @Override
protected void onCreate(Bundle state) { protected void onPreCreate() {
overridePendingTransition(R.anim.slide_from_right, R.anim.fade_scale_out);
dynamicTheme.onCreate(this); dynamicTheme.onCreate(this);
dynamicLanguage.onCreate(this); dynamicLanguage.onCreate(this);
super.onCreate(state); overridePendingTransition(R.anim.slide_from_right, R.anim.fade_scale_out);
}
@Override
protected void onCreate(Bundle state, @NonNull MasterSecret masterSecret) {
this.masterSecret = masterSecret;
setContentView(R.layout.conversation_activity); setContentView(R.layout.conversation_activity);
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
fragment = initFragment(R.id.fragment_content, new ConversationFragment(), masterSecret);
initializeReceivers(); initializeReceivers();
initializeViews(); initializeViews();
@ -178,6 +183,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@Override @Override
protected void onNewIntent(Intent intent) { protected void onNewIntent(Intent intent) {
Log.w(TAG, "onNewIntent()");
if (!Util.isEmpty(composeText) || attachmentManager.isAttachmentPresent()) { if (!Util.isEmpty(composeText) || attachmentManager.isAttachmentPresent()) {
saveDraft(); saveDraft();
attachmentManager.clear(); attachmentManager.clear();
@ -185,12 +192,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
} }
setIntent(intent); setIntent(intent);
initializeResources(); initializeResources();
initializeDraft(); initializeDraft();
ConversationFragment fragment = getFragment();
if (fragment != null) { if (fragment != null) {
fragment.onNewIntent(); fragment.onNewIntent();
} }
@ -223,10 +227,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@Override @Override
protected void onDestroy() { protected void onDestroy() {
saveDraft(); saveDraft();
recipients.removeListener(this); if (recipients != null) recipients.removeListener(this);
unregisterReceiver(securityUpdateReceiver); if (securityUpdateReceiver != null) unregisterReceiver(securityUpdateReceiver);
unregisterReceiver(groupUpdateReceiver); if (groupUpdateReceiver != null) unregisterReceiver(groupUpdateReceiver);
MemoryCleaner.clean(masterSecret);
super.onDestroy(); super.onDestroy();
} }
@ -333,7 +336,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private void handleReturnToConversationList() { private void handleReturnToConversationList() {
Intent intent = new Intent(this, ConversationListActivity.class); Intent intent = new Intent(this, ConversationListActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("master_secret", masterSecret);
startActivity(intent); startActivity(intent);
finish(); finish();
} }
@ -351,7 +353,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private void handleVerifyIdentity() { private void handleVerifyIdentity() {
Intent verifyIdentityIntent = new Intent(this, VerifyIdentityActivity.class); Intent verifyIdentityIntent = new Intent(this, VerifyIdentityActivity.class);
verifyIdentityIntent.putExtra("recipient", getRecipients().getPrimaryRecipient().getRecipientId()); verifyIdentityIntent.putExtra("recipient", getRecipients().getPrimaryRecipient().getRecipientId());
verifyIdentityIntent.putExtra("master_secret", masterSecret);
startActivity(verifyIdentityIntent); startActivity(verifyIdentityIntent);
} }
@ -392,7 +393,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
Intent intent = new Intent(this, MediaOverviewActivity.class); Intent intent = new Intent(this, MediaOverviewActivity.class);
intent.putExtra(MediaOverviewActivity.THREAD_ID_EXTRA, threadId); intent.putExtra(MediaOverviewActivity.THREAD_ID_EXTRA, threadId);
intent.putExtra(MediaOverviewActivity.RECIPIENT_EXTRA, recipients.getPrimaryRecipient().getRecipientId()); intent.putExtra(MediaOverviewActivity.RECIPIENT_EXTRA, recipients.getPrimaryRecipient().getRecipientId());
intent.putExtra(MediaOverviewActivity.MASTER_SECRET_EXTRA, masterSecret);
startActivity(intent); startActivity(intent);
} }
@ -439,7 +439,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private void handleEditPushGroup() { private void handleEditPushGroup() {
Intent intent = new Intent(ConversationActivity.this, GroupCreateActivity.class); Intent intent = new Intent(ConversationActivity.this, GroupCreateActivity.class);
intent.putExtra(GroupCreateActivity.MASTER_SECRET_EXTRA, masterSecret);
intent.putExtra(GroupCreateActivity.GROUP_RECIPIENT_EXTRA, recipients.getPrimaryRecipient().getRecipientId()); intent.putExtra(GroupCreateActivity.GROUP_RECIPIENT_EXTRA, recipients.getPrimaryRecipient().getRecipientId());
startActivityForResult(intent, GROUP_EDIT); startActivityForResult(intent, GROUP_EDIT);
} }
@ -724,7 +723,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
recipients = RecipientFactory.getRecipientsForIds(this, getIntent().getLongArrayExtra(RECIPIENTS_EXTRA), true); recipients = RecipientFactory.getRecipientsForIds(this, getIntent().getLongArrayExtra(RECIPIENTS_EXTRA), true);
threadId = getIntent().getLongExtra(THREAD_ID_EXTRA, -1); threadId = getIntent().getLongExtra(THREAD_ID_EXTRA, -1);
distributionType = getIntent().getIntExtra(DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT); distributionType = getIntent().getIntExtra(DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT);
masterSecret = getIntent().getParcelableExtra(MASTER_SECRET_EXTRA);
recipients.addListener(this); recipients.addListener(this);
} }
@ -901,8 +899,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
} else if (threadId > 0) { } else if (threadId > 0) {
threadDatabase.update(threadId); threadDatabase.update(threadId);
} }
MemoryCleaner.clean(thisMasterSecret);
return null; return null;
} }
}.execute(thisThreadId); }.execute(thisThreadId);
@ -978,8 +974,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
boolean refreshFragment = (threadId != this.threadId); boolean refreshFragment = (threadId != this.threadId);
this.threadId = threadId; this.threadId = threadId;
ConversationFragment fragment = getFragment();
if (fragment == null) { if (fragment == null) {
return; return;
} }
@ -994,10 +988,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
fragment.scrollToBottom(); fragment.scrollToBottom();
} }
private ConversationFragment getFragment() {
return (ConversationFragment)getSupportFragmentManager().findFragmentById(R.id.fragment_content);
}
private void sendMessage() { private void sendMessage() {
try { try {
Recipients recipients = getRecipients(); Recipients recipients = getRecipients();

View File

@ -61,6 +61,12 @@ public class ConversationFragment extends ListFragment
private long threadId; private long threadId;
private ActionMode actionMode; private ActionMode actionMode;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
this.masterSecret = getArguments().getParcelable("master_secret");
}
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
return inflater.inflate(R.layout.conversation_fragment, container, false); return inflater.inflate(R.layout.conversation_fragment, container, false);
@ -101,7 +107,6 @@ public class ConversationFragment extends ListFragment
} }
private void initializeResources() { private void initializeResources() {
this.masterSecret = this.getActivity().getIntent().getParcelableExtra("master_secret");
this.recipients = RecipientFactory.getRecipientsForIds(getActivity(), getActivity().getIntent().getLongArrayExtra("recipients"), true); this.recipients = RecipientFactory.getRecipientsForIds(getActivity(), getActivity().getIntent().getLongArrayExtra("recipients"), true);
this.threadId = this.getActivity().getIntent().getLongExtra("thread_id", -1); this.threadId = this.getActivity().getIntent().getLongExtra("thread_id", -1);
} }
@ -233,7 +238,6 @@ public class ConversationFragment extends ListFragment
private void handleForwardMessage(MessageRecord message) { private void handleForwardMessage(MessageRecord message) {
Intent composeIntent = new Intent(getActivity(), ShareActivity.class); Intent composeIntent = new Intent(getActivity(), ShareActivity.class);
composeIntent.putExtra(ConversationActivity.DRAFT_TEXT_EXTRA, message.getDisplayBody().toString()); composeIntent.putExtra(ConversationActivity.DRAFT_TEXT_EXTRA, message.getDisplayBody().toString());
composeIntent.putExtra(ShareActivity.MASTER_SECRET_EXTRA, masterSecret);
startActivity(composeIntent); startActivity(composeIntent);
} }

View File

@ -426,7 +426,6 @@ public class ConversationItem extends LinearLayout {
intent.putExtra("is_bundle", messageRecord.isBundleKeyExchange()); intent.putExtra("is_bundle", messageRecord.isBundleKeyExchange());
intent.putExtra("is_identity_update", messageRecord.isIdentityUpdate()); intent.putExtra("is_identity_update", messageRecord.isIdentityUpdate());
intent.putExtra("is_push", messageRecord.isPush()); intent.putExtra("is_push", messageRecord.isPush());
intent.putExtra("master_secret", masterSecret);
intent.putExtra("sent", messageRecord.isOutgoing()); intent.putExtra("sent", messageRecord.isOutgoing());
context.startActivity(intent); context.startActivity(intent);
} }
@ -458,7 +457,6 @@ public class ConversationItem extends LinearLayout {
Intent intent = new Intent(context, MediaPreviewActivity.class); Intent intent = new Intent(context, MediaPreviewActivity.class);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(slide.getUri(), slide.getContentType()); intent.setDataAndType(slide.getUri(), slide.getContentType());
intent.putExtra(MediaPreviewActivity.MASTER_SECRET_EXTRA, masterSecret);
if (!messageRecord.isOutgoing()) intent.putExtra(MediaPreviewActivity.RECIPIENT_EXTRA, messageRecord.getIndividualRecipient().getRecipientId()); if (!messageRecord.isOutgoing()) intent.putExtra(MediaPreviewActivity.RECIPIENT_EXTRA, messageRecord.getIndividualRecipient().getRecipientId());
intent.putExtra(MediaPreviewActivity.DATE_EXTRA, messageRecord.getDateReceived()); intent.putExtra(MediaPreviewActivity.DATE_EXTRA, messageRecord.getDateReceived());

View File

@ -21,6 +21,7 @@ import android.database.ContentObserver;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.provider.ContactsContract; import android.provider.ContactsContract;
import android.support.annotation.NonNull;
import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBar;
import android.util.Log; import android.util.Log;
import android.support.v4.view.MenuItemCompat; import android.support.v4.view.MenuItemCompat;
@ -38,41 +39,36 @@ import org.thoughtcrime.securesms.service.DirectoryRefreshListener;
import org.thoughtcrime.securesms.service.KeyCachingService; import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.MemoryCleaner;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
public class ConversationListActivity extends PassphraseRequiredActionBarActivity public class ConversationListActivity extends PassphraseRequiredActionBarActivity
implements ConversationListFragment.ConversationSelectedListener implements ConversationListFragment.ConversationSelectedListener
{ {
private final DynamicTheme dynamicTheme = new DynamicTheme (); private final DynamicTheme dynamicTheme = new DynamicTheme ();
private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
private ConversationListFragment fragment; private ConversationListFragment fragment;
private MasterSecret masterSecret;
private ContentObserver observer; private ContentObserver observer;
private MasterSecret masterSecret;
@Override @Override
public void onCreate(Bundle icicle) { protected void onPreCreate() {
dynamicTheme.onCreate(this); dynamicTheme.onCreate(this);
dynamicLanguage.onCreate(this); dynamicLanguage.onCreate(this);
super.onCreate(icicle);
getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE);
setContentView(R.layout.conversation_list_activity);
getSupportActionBar().setTitle(R.string.app_name);
initializeResources();
initializeContactUpdatesReceiver();
DirectoryRefreshListener.schedule(this);
} }
@Override @Override
public void onPostCreate(Bundle bundle) { protected void onCreate(Bundle icicle, @NonNull MasterSecret masterSecret) {
super.onPostCreate(bundle); this.masterSecret = masterSecret;
getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE);
getSupportActionBar().setTitle(R.string.app_name);
fragment = initFragment(android.R.id.content, new ConversationListFragment(), masterSecret);
initializeContactUpdatesReceiver();
DirectoryRefreshListener.schedule(this);
} }
@Override @Override
@ -84,19 +80,10 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
@Override @Override
public void onDestroy() { public void onDestroy() {
Log.w("ConversationListActivity", "onDestroy...");
MemoryCleaner.clean(masterSecret);
if (observer != null) getContentResolver().unregisterContentObserver(observer); if (observer != null) getContentResolver().unregisterContentObserver(observer);
super.onDestroy(); super.onDestroy();
} }
@Override
public void onMasterSecretCleared() {
// this.fragment.setMasterSecret(null);
startActivity(new Intent(this, RoutingActivity.class));
super.onMasterSecretCleared();
}
@Override @Override
public boolean onPrepareOptionsMenu(Menu menu) { public boolean onPrepareOptionsMenu(Menu menu) {
MenuInflater inflater = this.getMenuInflater(); MenuInflater inflater = this.getMenuInflater();
@ -106,13 +93,9 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
menu.findItem(R.id.menu_clear_passphrase).setVisible(!TextSecurePreferences.isPasswordDisabled(this)); menu.findItem(R.id.menu_clear_passphrase).setVisible(!TextSecurePreferences.isPasswordDisabled(this));
if (this.masterSecret != null) {
inflater.inflate(R.menu.conversation_list, menu); inflater.inflate(R.menu.conversation_list, menu);
MenuItem menuItem = menu.findItem(R.id.menu_search); MenuItem menuItem = menu.findItem(R.id.menu_search);
initializeSearch(menuItem); initializeSearch(menuItem);
} else {
inflater.inflate(R.menu.conversation_list_empty, menu);
}
super.onPrepareOptionsMenu(menu); super.onPrepareOptionsMenu(menu);
return true; return true;
@ -177,7 +160,6 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
private void createGroup() { private void createGroup() {
Intent intent = new Intent(this, GroupCreateActivity.class); Intent intent = new Intent(this, GroupCreateActivity.class);
intent.putExtra("master_secret", masterSecret);
startActivity(intent); startActivity(intent);
} }
@ -185,7 +167,6 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
Intent intent = new Intent(this, ConversationActivity.class); Intent intent = new Intent(this, ConversationActivity.class);
intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients.getIds()); intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients.getIds());
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId); intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
intent.putExtra(ConversationActivity.MASTER_SECRET_EXTRA, masterSecret);
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, distributionType); intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, distributionType);
startActivity(intent); startActivity(intent);
@ -193,7 +174,6 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
private void handleDisplaySettings() { private void handleDisplaySettings() {
Intent preferencesIntent = new Intent(this, ApplicationPreferencesActivity.class); Intent preferencesIntent = new Intent(this, ApplicationPreferencesActivity.class);
preferencesIntent.putExtra("master_secret", masterSecret);
startActivity(preferencesIntent); startActivity(preferencesIntent);
} }
@ -204,15 +184,11 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
} }
private void handleImportExport() { private void handleImportExport() {
final Intent intent = new Intent(this, ImportExportActivity.class); startActivity(new Intent(this, ImportExportActivity.class));
intent.putExtra("master_secret", masterSecret);
startActivity(intent);
} }
private void handleMyIdentity() { private void handleMyIdentity() {
final Intent intent = new Intent(this, ViewLocalIdentityActivity.class); startActivity(new Intent(this, ViewLocalIdentityActivity.class));
intent.putExtra("master_secret", masterSecret);
startActivity(intent);
} }
private void handleMarkAllRead() { private void handleMarkAllRead() {
@ -246,13 +222,4 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI,
true, observer); true, observer);
} }
private void initializeResources() {
this.masterSecret = getIntent().getParcelableExtra("master_secret");
this.fragment = (ConversationListFragment)this.getSupportFragmentManager()
.findFragmentById(R.id.fragment_content);
this.fragment.setMasterSecret(masterSecret);
}
} }

View File

@ -61,13 +61,18 @@ public class ConversationListFragment extends ListFragment
implements LoaderManager.LoaderCallbacks<Cursor>, ActionMode.Callback implements LoaderManager.LoaderCallbacks<Cursor>, ActionMode.Callback
{ {
private ConversationSelectedListener listener;
private MasterSecret masterSecret; private MasterSecret masterSecret;
private ActionMode actionMode; private ActionMode actionMode;
private ReminderView reminderView; private ReminderView reminderView;
private FloatingActionButton fab; private FloatingActionButton fab;
private String queryFilter = ""; private String queryFilter = "";
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
masterSecret = getArguments().getParcelable("master_secret");
}
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
final View view = inflater.inflate(R.layout.conversation_list_fragment, container, false); final View view = inflater.inflate(R.layout.conversation_list_fragment, container, false);
@ -76,12 +81,6 @@ public class ConversationListFragment extends ListFragment
return view; return view;
} }
@Override
public void onDestroyView() {
super.onDestroyView();
getListView().setAdapter(null);
}
@Override @Override
public void onActivityCreated(Bundle bundle) { public void onActivityCreated(Bundle bundle) {
super.onActivityCreated(bundle); super.onActivityCreated(bundle);
@ -92,9 +91,7 @@ public class ConversationListFragment extends ListFragment
fab.setOnClickListener(new OnClickListener() { fab.setOnClickListener(new OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
Intent intent = new Intent(getActivity(), NewConversationActivity.class); startActivity(new Intent(getActivity(), NewConversationActivity.class));
intent.putExtra(NewConversationActivity.MASTER_SECRET_EXTRA, masterSecret);
startActivity(intent);
} }
}); });
initializeListAdapter(); initializeListAdapter();
@ -111,12 +108,6 @@ public class ConversationListFragment extends ListFragment
((ConversationListAdapter)getListAdapter()).notifyDataSetChanged(); ((ConversationListAdapter)getListAdapter()).notifyDataSetChanged();
} }
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
this.listener = (ConversationSelectedListener)activity;
}
@Override @Override
public void onListItemClick(ListView l, View v, int position, long id) { public void onListItemClick(ListView l, View v, int position, long id) {
if (v instanceof ConversationListItem) { if (v instanceof ConversationListItem) {
@ -140,13 +131,6 @@ public class ConversationListFragment extends ListFragment
} }
} }
public void setMasterSecret(MasterSecret masterSecret) {
if (this.masterSecret != masterSecret) {
this.masterSecret = masterSecret;
initializeListAdapter();
}
}
public void setQueryFilter(String query) { public void setQueryFilter(String query) {
this.queryFilter = query; this.queryFilter = query;
getLoaderManager().restartLoader(0, null, this); getLoaderManager().restartLoader(0, null, this);
@ -250,7 +234,7 @@ public class ConversationListFragment extends ListFragment
} }
private void handleCreateConversation(long threadId, Recipients recipients, int distributionType) { private void handleCreateConversation(long threadId, Recipients recipients, int distributionType) {
listener.onCreateConversation(threadId, recipients, distributionType); ((ConversationSelectedListener)getActivity()).onCreateConversation(threadId, recipients, distributionType);
} }
@Override @Override

View File

@ -10,12 +10,14 @@ import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.os.Message; import android.os.Message;
import android.support.annotation.NonNull;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.SmsMigrator.ProgressDescription; import org.thoughtcrime.securesms.database.SmsMigrator.ProgressDescription;
import org.thoughtcrime.securesms.service.ApplicationMigrationService; import org.thoughtcrime.securesms.service.ApplicationMigrationService;
import org.thoughtcrime.securesms.service.ApplicationMigrationService.ImportState; import org.thoughtcrime.securesms.service.ApplicationMigrationService.ImportState;
@ -37,8 +39,7 @@ public class DatabaseMigrationActivity extends PassphraseRequiredActionBarActivi
private boolean isVisible = false; private boolean isVisible = false;
@Override @Override
public void onCreate(Bundle bundle) { protected void onCreate(Bundle bundle, @NonNull MasterSecret masterSecret) {
super.onCreate(bundle);
setContentView(R.layout.database_migration_activity); setContentView(R.layout.database_migration_activity);
initializeResources(); initializeResources();

View File

@ -5,6 +5,7 @@ import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener; import android.content.DialogInterface.OnDismissListener;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.SpannableStringBuilder; import android.text.SpannableStringBuilder;
import android.util.Log; import android.util.Log;
@ -40,9 +41,13 @@ public class DeviceProvisioningActivity extends PassphraseRequiredActionBarActiv
private MasterSecret masterSecret; private MasterSecret masterSecret;
@Override @Override
public void onCreate(Bundle bundle) { protected void onPreCreate() {
supportRequestWindowFeature(Window.FEATURE_NO_TITLE); supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(bundle); }
@Override
protected void onCreate(Bundle bundle, @NonNull MasterSecret masterSecret) {
this.masterSecret = masterSecret;
getSupportActionBar().hide(); getSupportActionBar().hide();
initializeResources(); initializeResources();
@ -80,11 +85,6 @@ public class DeviceProvisioningActivity extends PassphraseRequiredActionBarActiv
.show(); .show();
} }
@Override
public void onNewMasterSecret(MasterSecret masterSecret) {
this.masterSecret = masterSecret;
}
private void initializeResources() { private void initializeResources() {
this.uri = getIntent().getData(); this.uri = getIntent().getData();
} }

View File

@ -25,6 +25,7 @@ import android.graphics.BitmapFactory;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.util.Log; import android.util.Log;
@ -51,7 +52,6 @@ import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage; import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory; import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
import org.thoughtcrime.securesms.recipients.Recipients; import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.sms.MessageSender; import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.util.BitmapDecodingException; import org.thoughtcrime.securesms.util.BitmapDecodingException;
@ -70,7 +70,6 @@ import org.whispersystems.textsecure.api.util.InvalidNumberException;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -95,7 +94,6 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity {
public static final String GROUP_RECIPIENT_EXTRA = "group_recipient"; public static final String GROUP_RECIPIENT_EXTRA = "group_recipient";
public static final String GROUP_THREAD_EXTRA = "group_thread"; public static final String GROUP_THREAD_EXTRA = "group_thread";
public static final String MASTER_SECRET_EXTRA = "master_secret";
private final DynamicTheme dynamicTheme = new DynamicTheme(); private final DynamicTheme dynamicTheme = new DynamicTheme();
private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
@ -122,15 +120,19 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity {
private Set<Recipient> selectedContacts; private Set<Recipient> selectedContacts;
@Override @Override
public void onCreate(Bundle state) { protected void onPreCreate() {
dynamicTheme.onCreate(this); dynamicTheme.onCreate(this);
dynamicLanguage.onCreate(this); dynamicLanguage.onCreate(this);
super.onCreate(state); }
@Override
protected void onCreate(Bundle state, @NonNull MasterSecret masterSecret) {
this.masterSecret = masterSecret;
setContentView(R.layout.group_create_activity); setContentView(R.layout.group_create_activity);
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
selectedContacts = new HashSet<Recipient>(); selectedContacts = new HashSet<>();
initializeResources(); initializeResources();
} }
@ -234,8 +236,6 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity {
} }
} }
masterSecret = getIntent().getParcelableExtra(MASTER_SECRET_EXTRA);
lv = (ListView) findViewById(R.id.selected_contacts_list); lv = (ListView) findViewById(R.id.selected_contacts_list);
avatar = (ImageView) findViewById(R.id.avatar); avatar = (ImageView) findViewById(R.id.avatar);
groupName = (EditText) findViewById(R.id.group_name); groupName = (EditText) findViewById(R.id.group_name);
@ -531,7 +531,6 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity {
protected void onPostExecute(Long resultThread) { protected void onPostExecute(Long resultThread) {
if (resultThread > -1) { if (resultThread > -1) {
Intent intent = new Intent(GroupCreateActivity.this, ConversationActivity.class); Intent intent = new Intent(GroupCreateActivity.this, ConversationActivity.class);
intent.putExtra(ConversationActivity.MASTER_SECRET_EXTRA, masterSecret);
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, resultThread.longValue()); intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, resultThread.longValue());
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT); intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT);
@ -632,7 +631,6 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity {
final Recipients recipients = groupInfo.second; final Recipients recipients = groupInfo.second;
if (threadId > -1) { if (threadId > -1) {
Intent intent = new Intent(GroupCreateActivity.this, ConversationActivity.class); Intent intent = new Intent(GroupCreateActivity.this, ConversationActivity.class);
intent.putExtra(ConversationActivity.MASTER_SECRET_EXTRA, masterSecret);
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId); intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT); intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT);
intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients.getIds()); intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients.getIds());

View File

@ -114,7 +114,6 @@ public class ImageMediaAdapter extends CursorRecyclerViewAdapter<ViewHolder> {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
Intent intent = new Intent(getContext(), MediaPreviewActivity.class); Intent intent = new Intent(getContext(), MediaPreviewActivity.class);
intent.putExtra(MediaPreviewActivity.MASTER_SECRET_EXTRA, masterSecret);
intent.putExtra(MediaPreviewActivity.DATE_EXTRA, record.getDate()); intent.putExtra(MediaPreviewActivity.DATE_EXTRA, record.getDate());
if (!TextUtils.isEmpty(record.getAddress())) { if (!TextUtils.isEmpty(record.getAddress())) {

View File

@ -1,6 +1,7 @@
package org.thoughtcrime.securesms; package org.thoughtcrime.securesms;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter; import android.support.v4.app.FragmentStatePagerAdapter;
@ -15,16 +16,20 @@ import org.thoughtcrime.securesms.util.DynamicTheme;
public class ImportExportActivity extends PassphraseRequiredActionBarActivity { public class ImportExportActivity extends PassphraseRequiredActionBarActivity {
private MasterSecret masterSecret;
private TabPagerAdapter tabPagerAdapter; private TabPagerAdapter tabPagerAdapter;
private ViewPager viewPager; private ViewPager viewPager;
private MasterSecret masterSecret;
private DynamicTheme dynamicTheme = new DynamicTheme(); private DynamicTheme dynamicTheme = new DynamicTheme();
@Override @Override
public void onCreate(Bundle savedInstanceState) { protected void onPreCreate() {
dynamicTheme.onCreate(this); dynamicTheme.onCreate(this);
super.onCreate(savedInstanceState); }
@Override
protected void onCreate(Bundle savedInstanceState, @NonNull MasterSecret masterSecret) {
this.masterSecret = masterSecret;
setContentView(R.layout.import_export_activity); setContentView(R.layout.import_export_activity);
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
@ -51,7 +56,6 @@ public class ImportExportActivity extends PassphraseRequiredActionBarActivity {
} }
private void initializeResources() { private void initializeResources() {
this.masterSecret = getIntent().getParcelableExtra("master_secret");
this.viewPager = (ViewPager) findViewById(R.id.import_export_pager); this.viewPager = (ViewPager) findViewById(R.id.import_export_pager);
this.tabPagerAdapter = new TabPagerAdapter(getSupportFragmentManager()); this.tabPagerAdapter = new TabPagerAdapter(getSupportFragmentManager());

View File

@ -95,10 +95,8 @@ public class ImportFragment extends Fragment {
getActivity().startService(intent); getActivity().startService(intent);
Intent nextIntent = new Intent(getActivity(), ConversationListActivity.class); Intent nextIntent = new Intent(getActivity(), ConversationListActivity.class);
intent.putExtra("master_secret", masterSecret);
Intent activityIntent = new Intent(getActivity(), DatabaseMigrationActivity.class); Intent activityIntent = new Intent(getActivity(), DatabaseMigrationActivity.class);
activityIntent.putExtra("master_secret", masterSecret);
activityIntent.putExtra("next_intent", nextIntent); activityIntent.putExtra("next_intent", nextIntent);
getActivity().startActivity(activityIntent); getActivity().startActivity(activityIntent);
} }

View File

@ -26,6 +26,7 @@ import android.widget.Toast;
import com.google.zxing.integration.android.IntentIntegrator; import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult; import com.google.zxing.integration.android.IntentResult;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.Base64;
import org.thoughtcrime.securesms.util.Dialogs; import org.thoughtcrime.securesms.util.Dialogs;
import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicLanguage;
@ -43,10 +44,9 @@ public abstract class KeyScanningActivity extends PassphraseRequiredActionBarAct
private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
@Override @Override
protected void onCreate(Bundle bundle) { protected void onPreCreate() {
dynamicTheme.onCreate(this); dynamicTheme.onCreate(this);
dynamicLanguage.onCreate(this); dynamicLanguage.onCreate(this);
super.onCreate(bundle);
} }
@Override @Override

View File

@ -0,0 +1,5 @@
package org.thoughtcrime.securesms;
public interface MasterSecretListener {
void onMasterSecretCleared();
}

View File

@ -23,6 +23,7 @@ import android.database.Cursor;
import android.os.Build.VERSION; import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES; import android.os.Build.VERSION_CODES;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.LoaderManager; import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader; import android.support.v4.content.Loader;
import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.GridLayoutManager;
@ -48,9 +49,8 @@ import org.thoughtcrime.securesms.util.DynamicLanguage;
public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity implements LoaderManager.LoaderCallbacks<Cursor> { public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity implements LoaderManager.LoaderCallbacks<Cursor> {
private final static String TAG = MediaOverviewActivity.class.getSimpleName(); private final static String TAG = MediaOverviewActivity.class.getSimpleName();
public final static String MASTER_SECRET_EXTRA = "master_secret"; public static final String RECIPIENT_EXTRA = "recipient";
public final static String RECIPIENT_EXTRA = "recipient"; public static final String THREAD_ID_EXTRA = "thread_id";
public final static String THREAD_ID_EXTRA = "thread_id";
private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
@ -63,11 +63,14 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity i
private long threadId; private long threadId;
@Override @Override
protected void onCreate(Bundle bundle) { protected void onPreCreate() {
this.setTheme(R.style.TextSecure_DarkTheme); this.setTheme(R.style.TextSecure_DarkTheme);
dynamicLanguage.onCreate(this); dynamicLanguage.onCreate(this);
}
super.onCreate(bundle); @Override
protected void onCreate(Bundle bundle, @NonNull MasterSecret masterSecret) {
this.masterSecret = masterSecret;
setFullscreenIfPossible(); setFullscreenIfPossible();
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
@ -112,7 +115,6 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity i
} }
private void initializeResources() { private void initializeResources() {
masterSecret = getIntent().getParcelableExtra(MASTER_SECRET_EXTRA);
threadId = getIntent().getLongExtra(THREAD_ID_EXTRA, -1); threadId = getIntent().getLongExtra(THREAD_ID_EXTRA, -1);
noImages = (TextView ) findViewById(R.id.no_images ); noImages = (TextView ) findViewById(R.id.no_images );

View File

@ -20,26 +20,24 @@ import android.annotation.TargetApi;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri; import android.net.Uri;
import android.opengl.GLES20; import android.opengl.GLES20;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build.VERSION; import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES; import android.os.Build.VERSION_CODES;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.util.Log; import android.util.Log;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.mms.PartAuthority;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.Recipient.RecipientModifiedListener; import org.thoughtcrime.securesms.recipients.Recipient.RecipientModifiedListener;
import org.thoughtcrime.securesms.recipients.RecipientFactory; import org.thoughtcrime.securesms.recipients.RecipientFactory;
@ -60,9 +58,8 @@ import uk.co.senab.photoview.PhotoViewAttacher;
public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity implements RecipientModifiedListener { public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity implements RecipientModifiedListener {
private final static String TAG = MediaPreviewActivity.class.getSimpleName(); private final static String TAG = MediaPreviewActivity.class.getSimpleName();
public final static String MASTER_SECRET_EXTRA = "master_secret"; public static final String RECIPIENT_EXTRA = "recipient";
public final static String RECIPIENT_EXTRA = "recipient"; public static final String DATE_EXTRA = "date";
public final static String DATE_EXTRA = "date";
private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
@ -79,12 +76,11 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
private long date; private long date;
@Override @Override
protected void onCreate(Bundle bundle) { protected void onCreate(Bundle bundle, @NonNull MasterSecret masterSecret) {
this.masterSecret = masterSecret;
this.setTheme(R.style.TextSecure_DarkTheme); this.setTheme(R.style.TextSecure_DarkTheme);
dynamicLanguage.onCreate(this); dynamicLanguage.onCreate(this);
super.onCreate(bundle);
setFullscreenIfPossible(); setFullscreenIfPossible();
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN); WindowManager.LayoutParams.FLAG_FULLSCREEN);
@ -157,7 +153,6 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
private void initializeResources() { private void initializeResources() {
final long recipientId = getIntent().getLongExtra(RECIPIENT_EXTRA, -1); final long recipientId = getIntent().getLongExtra(RECIPIENT_EXTRA, -1);
masterSecret = getIntent().getParcelableExtra(MASTER_SECRET_EXTRA);
mediaUri = getIntent().getData(); mediaUri = getIntent().getData();
mediaType = getIntent().getType(); mediaType = getIntent().getType();
date = getIntent().getLongExtra(DATE_EXTRA, -1); date = getIntent().getLongExtra(DATE_EXTRA, -1);

View File

@ -20,6 +20,7 @@ import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader; import android.support.v4.content.Loader;
import android.util.Log; import android.util.Log;
@ -83,10 +84,13 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
private DynamicLanguage dynamicLanguage = new DynamicLanguage(); private DynamicLanguage dynamicLanguage = new DynamicLanguage();
@Override @Override
public void onCreate(Bundle bundle) { protected void onPreCreate() {
dynamicTheme.onCreate(this); dynamicTheme.onCreate(this);
dynamicLanguage.onCreate(this); dynamicLanguage.onCreate(this);
super.onCreate(bundle); }
@Override
public void onCreate(Bundle bundle, @NonNull MasterSecret masterSecret) {
setContentView(R.layout.message_details_activity); setContentView(R.layout.message_details_activity);
initializeResources(); initializeResources();

View File

@ -18,6 +18,7 @@ package org.thoughtcrime.securesms;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.util.Log; import android.util.Log;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
@ -50,21 +51,21 @@ import static org.thoughtcrime.securesms.contacts.ContactAccessor.ContactData;
* *
*/ */
public class NewConversationActivity extends PassphraseRequiredActionBarActivity { public class NewConversationActivity extends PassphraseRequiredActionBarActivity {
private final static String TAG = "ContactSelectActivity"; private static final String TAG = NewConversationActivity.class.getSimpleName();
public final static String MASTER_SECRET_EXTRA = "master_secret";
private final DynamicTheme dynamicTheme = new DynamicTheme (); private final DynamicTheme dynamicTheme = new DynamicTheme ();
private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
private MasterSecret masterSecret;
private PushContactSelectionListFragment contactsFragment; private PushContactSelectionListFragment contactsFragment;
@Override @Override
protected void onCreate(Bundle icicle) { protected void onPreCreate() {
dynamicTheme.onCreate(this); dynamicTheme.onCreate(this);
dynamicLanguage.onCreate(this); dynamicLanguage.onCreate(this);
super.onCreate(icicle); }
@Override
protected void onCreate(Bundle icicle, @NonNull MasterSecret masterSecret) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
setContentView(R.layout.new_conversation_activity); setContentView(R.layout.new_conversation_activity);
@ -77,7 +78,6 @@ public class NewConversationActivity extends PassphraseRequiredActionBarActivity
dynamicTheme.onResume(this); dynamicTheme.onResume(this);
dynamicLanguage.onResume(this); dynamicLanguage.onResume(this);
getSupportActionBar().setTitle(R.string.AndroidManifest__select_contacts); getSupportActionBar().setTitle(R.string.AndroidManifest__select_contacts);
masterSecret = getIntent().getParcelableExtra(MASTER_SECRET_EXTRA);
} }
@Override @Override
@ -116,7 +116,7 @@ public class NewConversationActivity extends PassphraseRequiredActionBarActivity
final Intent resultIntent = getIntent(); final Intent resultIntent = getIntent();
final List<ContactData> selectedContacts = contactsFragment.getSelectedContacts(); final List<ContactData> selectedContacts = contactsFragment.getSelectedContacts();
if (selectedContacts != null) { if (selectedContacts != null) {
resultIntent.putParcelableArrayListExtra("contacts", new ArrayList<ContactData>(contactsFragment.getSelectedContacts())); resultIntent.putParcelableArrayListExtra("contacts", new ArrayList<>(contactsFragment.getSelectedContacts()));
} }
setResult(RESULT_OK, resultIntent); setResult(RESULT_OK, resultIntent);
finish(); finish();
@ -149,7 +149,6 @@ public class NewConversationActivity extends PassphraseRequiredActionBarActivity
if (recipients != null) { if (recipients != null) {
Intent intent = new Intent(this, ConversationActivity.class); Intent intent = new Intent(this, ConversationActivity.class);
intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients.getIds()); intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients.getIds());
intent.putExtra(ConversationActivity.MASTER_SECRET_EXTRA, masterSecret);
intent.putExtra(ConversationActivity.DRAFT_TEXT_EXTRA, getIntent().getStringExtra(ConversationActivity.DRAFT_TEXT_EXTRA)); intent.putExtra(ConversationActivity.DRAFT_TEXT_EXTRA, getIntent().getStringExtra(ConversationActivity.DRAFT_TEXT_EXTRA));
intent.putExtra(ConversationActivity.DRAFT_AUDIO_EXTRA, getIntent().getParcelableExtra(ConversationActivity.DRAFT_AUDIO_EXTRA)); intent.putExtra(ConversationActivity.DRAFT_AUDIO_EXTRA, getIntent().getParcelableExtra(ConversationActivity.DRAFT_AUDIO_EXTRA));
intent.putExtra(ConversationActivity.DRAFT_VIDEO_EXTRA, getIntent().getParcelableExtra(ConversationActivity.DRAFT_VIDEO_EXTRA)); intent.putExtra(ConversationActivity.DRAFT_VIDEO_EXTRA, getIntent().getParcelableExtra(ConversationActivity.DRAFT_VIDEO_EXTRA));

View File

@ -21,11 +21,9 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.os.IBinder; import android.os.IBinder;
import android.support.v7.app.ActionBarActivity;
import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.service.KeyCachingService; import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.util.MemoryCleaner;
/** /**
@ -41,13 +39,10 @@ public abstract class PassphraseActivity extends BaseActionBarActivity {
protected void setMasterSecret(MasterSecret masterSecret) { protected void setMasterSecret(MasterSecret masterSecret) {
this.masterSecret = masterSecret; this.masterSecret = masterSecret;
Intent bindIntent = new Intent(this, KeyCachingService.class); Intent bindIntent = new Intent(this, KeyCachingService.class);
startService(bindIntent);
bindService(bindIntent, serviceConnection, Context.BIND_AUTO_CREATE); bindService(bindIntent, serviceConnection, Context.BIND_AUTO_CREATE);
} }
protected MasterSecret getMasterSecret() {
return masterSecret;
}
protected abstract void cleanup(); protected abstract void cleanup();
private ServiceConnection serviceConnection = new ServiceConnection() { private ServiceConnection serviceConnection = new ServiceConnection() {
@ -58,11 +53,12 @@ public abstract class PassphraseActivity extends BaseActionBarActivity {
PassphraseActivity.this.unbindService(PassphraseActivity.this.serviceConnection); PassphraseActivity.this.unbindService(PassphraseActivity.this.serviceConnection);
MemoryCleaner.clean(masterSecret); masterSecret = null;
cleanup(); cleanup();
PassphraseActivity.this.setResult(RESULT_OK); Intent nextIntent = getIntent().getParcelableExtra("next_intent");
PassphraseActivity.this.finish(); if (nextIntent != null) startActivity(nextIntent);
finish();
} }
@Override @Override

View File

@ -28,7 +28,6 @@ import android.widget.Toast;
import org.thoughtcrime.securesms.crypto.InvalidPassphraseException; import org.thoughtcrime.securesms.crypto.InvalidPassphraseException;
import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.MasterSecretUtil; import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
import org.thoughtcrime.securesms.util.MemoryCleaner;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
/** /**
@ -104,10 +103,6 @@ public class PassphraseChangeActivity extends PassphraseActivity {
MasterSecret masterSecret = MasterSecretUtil.changeMasterSecretPassphrase(this, original, passphrase); MasterSecret masterSecret = MasterSecretUtil.changeMasterSecretPassphrase(this, original, passphrase);
TextSecurePreferences.setPasswordDisabled(this, false); TextSecurePreferences.setPasswordDisabled(this, false);
MemoryCleaner.clean(original);
MemoryCleaner.clean(passphrase);
MemoryCleaner.clean(passphraseRepeat);
setMasterSecret(masterSecret); setMasterSecret(masterSecret);
} }
} catch (InvalidPassphraseException e) { } catch (InvalidPassphraseException e) {

View File

@ -23,7 +23,6 @@ import android.support.v7.app.ActionBar;
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.MasterSecretUtil; import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
import org.thoughtcrime.securesms.util.MemoryCleaner;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.VersionTracker; import org.thoughtcrime.securesms.util.VersionTracker;
@ -66,8 +65,6 @@ public class PassphraseCreateActivity extends PassphraseActivity {
masterSecret = MasterSecretUtil.generateMasterSecret(PassphraseCreateActivity.this, masterSecret = MasterSecretUtil.generateMasterSecret(PassphraseCreateActivity.this,
passphrase); passphrase);
MemoryCleaner.clean(passphrase);
MasterSecretUtil.generateAsymmetricMasterSecret(PassphraseCreateActivity.this, masterSecret); MasterSecretUtil.generateAsymmetricMasterSecret(PassphraseCreateActivity.this, masterSecret);
IdentityKeyUtil.generateIdentityKeys(PassphraseCreateActivity.this, masterSecret); IdentityKeyUtil.generateIdentityKeys(PassphraseCreateActivity.this, masterSecret);
VersionTracker.updateLastSeenVersion(PassphraseCreateActivity.this); VersionTracker.updateLastSeenVersion(PassphraseCreateActivity.this);

View File

@ -43,7 +43,6 @@ import android.widget.Toast;
import org.thoughtcrime.securesms.crypto.InvalidPassphraseException; import org.thoughtcrime.securesms.crypto.InvalidPassphraseException;
import org.thoughtcrime.securesms.crypto.MasterSecretUtil; import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.MemoryCleaner;
import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.Util;
@ -73,6 +72,12 @@ public class PassphrasePromptActivity extends PassphraseActivity {
dynamicLanguage.onResume(this); dynamicLanguage.onResume(this);
} }
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
}
@Override @Override
public boolean onPrepareOptionsMenu(Menu menu) { public boolean onPrepareOptionsMenu(Menu menu) {
MenuInflater inflater = this.getMenuInflater(); MenuInflater inflater = this.getMenuInflater();
@ -102,9 +107,8 @@ public class PassphrasePromptActivity extends PassphraseActivity {
try { try {
Editable text = passphraseText.getText(); Editable text = passphraseText.getText();
String passphrase = (text == null ? "" : text.toString()); String passphrase = (text == null ? "" : text.toString());
MasterSecret masterSecret = MasterSecretUtil.getMasterSecret(PassphrasePromptActivity.this, passphrase); MasterSecret masterSecret = MasterSecretUtil.getMasterSecret(this, passphrase);
MemoryCleaner.clean(passphrase);
setMasterSecret(masterSecret); setMasterSecret(masterSecret);
} catch (InvalidPassphraseException ipe) { } catch (InvalidPassphraseException ipe) {
passphraseText.setText(""); passphraseText.setText("");

View File

@ -1,42 +1,186 @@
package org.thoughtcrime.securesms; package org.thoughtcrime.securesms;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.WindowManager;
import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.service.MessageRetrievalService;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
public class PassphraseRequiredActionBarActivity extends BaseActionBarActivity implements PassphraseRequiredActivity { public abstract class PassphraseRequiredActionBarActivity extends BaseActionBarActivity implements MasterSecretListener {
private static final String TAG = PassphraseRequiredActionBarActivity.class.getSimpleName();
private final PassphraseRequiredMixin delegate = new PassphraseRequiredMixin(); private static final int STATE_NORMAL = 0;
private static final int STATE_CREATE_PASSPHRASE = 1;
private static final int STATE_PROMPT_PASSPHRASE = 2;
private static final int STATE_UPGRADE_DATABASE = 3;
private static final int STATE_PROMPT_PUSH_REGISTRATION = 4;
private BroadcastReceiver clearKeyReceiver;
private boolean isVisible;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected final void onCreate(Bundle savedInstanceState) {
onPreCreate();
final MasterSecret masterSecret = KeyCachingService.getMasterSecret(this);
routeApplicationState(masterSecret);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
delegate.onCreate(this); if (!isFinishing()) {
initializeClearKeyReceiver();
onCreate(savedInstanceState, masterSecret);
} }
}
protected void onPreCreate() {}
protected void onCreate(Bundle savedInstanceState, @NonNull MasterSecret masterSecret) {}
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
delegate.onResume(this); initializeScreenshotSecurity();
KeyCachingService.registerPassphraseActivityStarted(this);
MessageRetrievalService.registerActivityStarted(this);
isVisible = true;
} }
@Override @Override
protected void onPause() { protected void onPause() {
super.onPause(); super.onPause();
delegate.onPause(this); KeyCachingService.registerPassphraseActivityStopped(this);
MessageRetrievalService.registerActivityStopped(this);
isVisible = false;
} }
@Override @Override
protected void onDestroy() { protected void onDestroy() {
super.onDestroy(); super.onDestroy();
delegate.onDestroy(this); removeClearKeyReceiver(this);
} }
@Override @Override
public void onMasterSecretCleared() { public void onMasterSecretCleared() {
finish(); Log.w(TAG, "onMasterSecretCleared()");
if (isVisible) routeApplicationState(null);
else finish();
} }
protected <T extends Fragment> T initFragment(@IdRes int target,
@NonNull T fragment,
@NonNull MasterSecret masterSecret) {
Bundle args = new Bundle();
args.putParcelable("master_secret", masterSecret);
fragment.setArguments(args);
getSupportFragmentManager().beginTransaction()
.replace(target, fragment)
.commit();
return fragment;
}
private void routeApplicationState(MasterSecret masterSecret) {
Intent intent = getIntentForState(masterSecret, getApplicationState(masterSecret));
if (intent != null) {
startActivity(intent);
finish();
}
}
private Intent getIntentForState(MasterSecret masterSecret, int state) {
Log.w(TAG, "routeApplicationState(), state: " + state);
switch (state) {
case STATE_CREATE_PASSPHRASE: return getCreatePassphraseIntent();
case STATE_PROMPT_PASSPHRASE: return getPromptPassphraseIntent();
case STATE_UPGRADE_DATABASE: return getUpgradeDatabaseIntent(masterSecret);
case STATE_PROMPT_PUSH_REGISTRATION: return getPushRegistrationIntent(masterSecret);
default: return null;
}
}
private int getApplicationState(MasterSecret masterSecret) {
if (!MasterSecretUtil.isPassphraseInitialized(this)) {
return STATE_CREATE_PASSPHRASE;
} else if (masterSecret == null) {
return STATE_PROMPT_PASSPHRASE;
} else if (DatabaseUpgradeActivity.isUpdate(this)) {
return STATE_UPGRADE_DATABASE;
} else if (!TextSecurePreferences.hasPromptedPushRegistration(this)) {
return STATE_PROMPT_PUSH_REGISTRATION;
} else {
return STATE_NORMAL;
}
}
private Intent getCreatePassphraseIntent() {
return getRoutedIntent(PassphraseCreateActivity.class, getIntent(), null);
}
private Intent getPromptPassphraseIntent() {
return getRoutedIntent(PassphrasePromptActivity.class, getIntent(), null);
}
private Intent getUpgradeDatabaseIntent(MasterSecret masterSecret) {
return getRoutedIntent(DatabaseUpgradeActivity.class,
TextSecurePreferences.hasPromptedPushRegistration(this)
? getConversationListIntent()
: getPushRegistrationIntent(masterSecret),
masterSecret);
}
private Intent getPushRegistrationIntent(MasterSecret masterSecret) {
return getRoutedIntent(RegistrationActivity.class, getConversationListIntent(), masterSecret);
}
private Intent getRoutedIntent(Class<?> destination, @Nullable Intent nextIntent, @Nullable MasterSecret masterSecret) {
final Intent intent = new Intent(this, destination);
if (nextIntent != null) intent.putExtra("next_intent", nextIntent);
if (masterSecret != null) intent.putExtra("master_secret", masterSecret);
return intent;
}
private Intent getConversationListIntent() {
return new Intent(this, ConversationListActivity.class);
}
private void initializeScreenshotSecurity() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH &&
TextSecurePreferences.isScreenSecurityEnabled(this))
{
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
} else {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
}
private void initializeClearKeyReceiver() {
Log.w(TAG, "initializeClearKeyReceiver()");
this.clearKeyReceiver = new BroadcastReceiver() {
@Override @Override
public void onNewMasterSecret(MasterSecret masterSecret) {} public void onReceive(Context context, Intent intent) {
Log.w(TAG, "onReceive() for clear key event");
onMasterSecretCleared();
}
};
IntentFilter filter = new IntentFilter(KeyCachingService.CLEAR_KEY_EVENT);
registerReceiver(clearKeyReceiver, filter, KeyCachingService.KEY_PERMISSION, null);
}
private void removeClearKeyReceiver(Context context) {
if (clearKeyReceiver != null) {
context.unregisterReceiver(clearKeyReceiver);
clearKeyReceiver = null;
}
}
} }

View File

@ -1,8 +0,0 @@
package org.thoughtcrime.securesms;
import org.thoughtcrime.securesms.crypto.MasterSecret;
public interface PassphraseRequiredActivity {
public void onMasterSecretCleared();
public void onNewMasterSecret(MasterSecret masterSecret);
}

View File

@ -1,102 +0,0 @@
package org.thoughtcrime.securesms;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.view.WindowManager;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.service.MessageRetrievalService;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
public class PassphraseRequiredMixin {
private BroadcastReceiver clearKeyReceiver;
private BroadcastReceiver newKeyReceiver;
public <T extends Activity & PassphraseRequiredActivity> void onCreate(T activity) {
initializeClearKeyReceiver(activity);
}
public <T extends Activity & PassphraseRequiredActivity> void onResume(T activity) {
initializeScreenshotSecurity(activity);
initializeNewKeyReceiver(activity);
initializeFromMasterSecret(activity);
KeyCachingService.registerPassphraseActivityStarted(activity);
MessageRetrievalService.registerActivityStarted(activity);
}
public <T extends Activity & PassphraseRequiredActivity> void onPause(T activity) {
removeNewKeyReceiver(activity);
KeyCachingService.registerPassphraseActivityStopped(activity);
MessageRetrievalService.registerActivityStopped(activity);
}
public <T extends Activity & PassphraseRequiredActivity> void onDestroy(T activity) {
removeClearKeyReceiver(activity);
}
private <T extends Activity & PassphraseRequiredActivity> void initializeScreenshotSecurity(T activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
if (TextSecurePreferences.isScreenSecurityEnabled(activity)) {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
} else {
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
}
}
private <T extends Activity & PassphraseRequiredActivity> void initializeClearKeyReceiver(final T activity) {
this.clearKeyReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
activity.onMasterSecretCleared();
}
};
IntentFilter filter = new IntentFilter(KeyCachingService.CLEAR_KEY_EVENT);
activity.registerReceiver(clearKeyReceiver, filter, KeyCachingService.KEY_PERMISSION, null);
}
private <T extends Activity & PassphraseRequiredActivity> void initializeNewKeyReceiver(final T activity) {
this.newKeyReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
activity.onNewMasterSecret((MasterSecret)intent.getParcelableExtra("master_secret"));
}
};
IntentFilter filter = new IntentFilter(KeyCachingService.NEW_KEY_EVENT);
activity.registerReceiver(newKeyReceiver, filter, KeyCachingService.KEY_PERMISSION, null);
}
private <T extends Activity & PassphraseRequiredActivity> void initializeFromMasterSecret(T activity) {
MasterSecret masterSecret = KeyCachingService.getMasterSecret(activity);
if (masterSecret == null) {
activity.onMasterSecretCleared();
} else {
activity.onNewMasterSecret(masterSecret);
}
}
private void removeClearKeyReceiver(Context context) {
if (clearKeyReceiver != null) {
context.unregisterReceiver(clearKeyReceiver);
clearKeyReceiver = null;
}
}
private void removeNewKeyReceiver(Context context) {
if (newKeyReceiver != null) {
context.unregisterReceiver(newKeyReceiver);
newKeyReceiver = null;
}
}
}

View File

@ -1,45 +0,0 @@
package org.thoughtcrime.securesms;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import org.thoughtcrime.securesms.crypto.MasterSecret;
public class PassphraseRequiredSherlockListActivity extends ActionBarListActivity implements PassphraseRequiredActivity {
private final PassphraseRequiredMixin delegate = new PassphraseRequiredMixin();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
delegate.onCreate(this);
}
@Override
protected void onResume() {
super.onResume();
delegate.onResume(this);
}
@Override
protected void onPause() {
super.onPause();
delegate.onPause(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
delegate.onDestroy(this);
}
@Override
public void onMasterSecretCleared() {
finish();
}
@Override
public void onNewMasterSecret(MasterSecret masterSecret) {}
}

View File

@ -2,10 +2,12 @@ package org.thoughtcrime.securesms;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
import org.thoughtcrime.securesms.preferences.MmsPreferencesActivity; import org.thoughtcrime.securesms.preferences.MmsPreferencesActivity;
import org.thoughtcrime.securesms.crypto.MasterSecret;
public class PromptMmsActivity extends PassphraseRequiredActionBarActivity { public class PromptMmsActivity extends PassphraseRequiredActionBarActivity {
@ -13,9 +15,7 @@ public class PromptMmsActivity extends PassphraseRequiredActionBarActivity {
private Button cancelButton; private Button cancelButton;
@Override @Override
public void onCreate(Bundle bundle) { protected void onCreate(Bundle bundle, @NonNull MasterSecret masterSecret) {
super.onCreate(bundle);
setContentView(R.layout.prompt_apn_activity); setContentView(R.layout.prompt_apn_activity);
initializeResources(); initializeResources();
} }

View File

@ -18,11 +18,13 @@ package org.thoughtcrime.securesms;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.util.Log; import android.util.Log;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.util.DirectoryHelper; import org.thoughtcrime.securesms.util.DirectoryHelper;
import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.DynamicTheme;
@ -50,11 +52,13 @@ public class PushContactSelectionActivity extends PassphraseRequiredActionBarAct
private PushContactSelectionListFragment contactsFragment; private PushContactSelectionListFragment contactsFragment;
@Override @Override
protected void onCreate(Bundle icicle) { protected void onPreCreate() {
dynamicTheme.onCreate(this); dynamicTheme.onCreate(this);
dynamicLanguage.onCreate(this); dynamicLanguage.onCreate(this);
super.onCreate(icicle); }
@Override
protected void onCreate(Bundle icicle, @NonNull MasterSecret masterSecret) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
setContentView(R.layout.push_contact_selection_activity); setContentView(R.layout.push_contact_selection_activity);

View File

@ -21,6 +21,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.Spanned; import android.text.Spanned;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
@ -41,7 +42,6 @@ import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.sms.IncomingPreKeyBundleMessage; import org.thoughtcrime.securesms.sms.IncomingPreKeyBundleMessage;
import org.thoughtcrime.securesms.sms.IncomingTextMessage; import org.thoughtcrime.securesms.sms.IncomingTextMessage;
import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.Base64;
import org.thoughtcrime.securesms.util.MemoryCleaner;
import org.whispersystems.libaxolotl.IdentityKey; import org.whispersystems.libaxolotl.IdentityKey;
import org.whispersystems.libaxolotl.InvalidKeyException; import org.whispersystems.libaxolotl.InvalidKeyException;
import org.whispersystems.libaxolotl.InvalidMessageException; import org.whispersystems.libaxolotl.InvalidMessageException;
@ -60,7 +60,7 @@ import java.io.IOException;
* @author Moxie Marlinspike * @author Moxie Marlinspike
*/ */
public class ReceiveKeyActivity extends BaseActivity { public class ReceiveKeyActivity extends PassphraseRequiredActionBarActivity {
private TextView descriptionText; private TextView descriptionText;
@ -76,8 +76,8 @@ public class ReceiveKeyActivity extends BaseActivity {
private IdentityKey identityKey; private IdentityKey identityKey;
@Override @Override
protected void onCreate(Bundle state) { protected void onCreate(Bundle state, @NonNull MasterSecret masterSecret) {
super.onCreate(state); this.masterSecret = masterSecret;
setContentView(R.layout.receive_key_activity); setContentView(R.layout.receive_key_activity);
initializeResources(); initializeResources();
@ -91,12 +91,6 @@ public class ReceiveKeyActivity extends BaseActivity {
initializeListeners(); initializeListeners();
} }
@Override
protected void onDestroy() {
MemoryCleaner.clean(masterSecret);
super.onDestroy();
}
private void initializeText() { private void initializeText() {
SpannableString spannableString = new SpannableString(getString(R.string.ReceiveKeyActivity_the_signature_on_this_key_exchange_is_different) + " " + SpannableString spannableString = new SpannableString(getString(R.string.ReceiveKeyActivity_the_signature_on_this_key_exchange_is_different) + " " +
getString(R.string.ReceiveKeyActivity_you_may_wish_to_verify_this_contact)); getString(R.string.ReceiveKeyActivity_you_may_wish_to_verify_this_contact));
@ -105,7 +99,6 @@ public class ReceiveKeyActivity extends BaseActivity {
public void onClick(View widget) { public void onClick(View widget) {
Intent intent = new Intent(ReceiveKeyActivity.this, VerifyIdentityActivity.class); Intent intent = new Intent(ReceiveKeyActivity.this, VerifyIdentityActivity.class);
intent.putExtra("recipient", recipient.getRecipientId()); intent.putExtra("recipient", recipient.getRecipientId());
intent.putExtra("master_secret", masterSecret);
intent.putExtra("remote_identity", new IdentityKeyParcelable(identityKey)); intent.putExtra("remote_identity", new IdentityKeyParcelable(identityKey));
startActivity(intent); startActivity(intent);
} }
@ -137,7 +130,6 @@ public class ReceiveKeyActivity extends BaseActivity {
this.recipient = RecipientFactory.getRecipientForId(this, getIntent().getLongExtra("recipient", -1), true); this.recipient = RecipientFactory.getRecipientForId(this, getIntent().getLongExtra("recipient", -1), true);
this.recipientDeviceId = getIntent().getIntExtra("recipient_device_id", -1); this.recipientDeviceId = getIntent().getIntExtra("recipient_device_id", -1);
this.messageId = getIntent().getLongExtra("message_id", -1); this.messageId = getIntent().getLongExtra("message_id", -1);
this.masterSecret = getIntent().getParcelableExtra("master_secret");
} }
private void initializeListeners() { private void initializeListeners() {

View File

@ -25,9 +25,9 @@ import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberUtil; import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber; import com.google.i18n.phonenumbers.Phonenumber;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.util.Dialogs; import org.thoughtcrime.securesms.util.Dialogs;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.textsecure.api.util.PhoneNumberFormatter; import org.whispersystems.textsecure.api.util.PhoneNumberFormatter;
@ -284,7 +284,7 @@ public class RegistrationActivity extends BaseActionBarActivity {
Intent nextIntent = getIntent().getParcelableExtra("next_intent"); Intent nextIntent = getIntent().getParcelableExtra("next_intent");
if (nextIntent == null) { if (nextIntent == null) {
nextIntent = new Intent(RegistrationActivity.this, RoutingActivity.class); nextIntent = new Intent(RegistrationActivity.this, ConversationListActivity.class);
} }
startActivity(nextIntent); startActivity(nextIntent);

View File

@ -33,6 +33,7 @@ import android.widget.Toast;
import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.push.TextSecureCommunicationFactory; import org.thoughtcrime.securesms.push.TextSecureCommunicationFactory;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.service.RegistrationService; import org.thoughtcrime.securesms.service.RegistrationService;
import org.thoughtcrime.securesms.util.Dialogs; import org.thoughtcrime.securesms.util.Dialogs;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
@ -330,7 +331,7 @@ public class RegistrationProgressActivity extends BaseActionBarActivity {
} }
shutdownService(); shutdownService();
startActivity(new Intent(this, RoutingActivity.class)); startActivity(new Intent(this, ConversationListActivity.class));
finish(); finish();
} }

View File

@ -1,284 +0,0 @@
package org.thoughtcrime.securesms;
import android.content.Intent;
import android.net.Uri;
import android.webkit.MimeTypeMap;
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.crypto.MasterSecret;
public class RoutingActivity extends PassphraseRequiredActionBarActivity {
private static final int STATE_CREATE_PASSPHRASE = 1;
private static final int STATE_PROMPT_PASSPHRASE = 2;
private static final int STATE_CONVERSATION_OR_LIST = 3;
private static final int STATE_UPGRADE_DATABASE = 4;
private static final int STATE_PROMPT_PUSH_REGISTRATION = 5;
private MasterSecret masterSecret = null;
private boolean isVisible = false;
private boolean canceledResult = false;
private boolean newIntent = false;
@Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
this.newIntent = true;
}
@Override
public void onResume() {
if (this.canceledResult && !this.newIntent) {
finish();
}
this.newIntent = false;
this.canceledResult = false;
this.isVisible = true;
super.onResume();
}
@Override
public void onPause() {
this.isVisible = false;
super.onPause();
}
@Override
public void onNewMasterSecret(MasterSecret masterSecret) {
this.masterSecret = masterSecret;
if (isVisible) {
routeApplicationState();
}
}
@Override
public void onMasterSecretCleared() {
this.masterSecret = null;
if (isVisible) {
routeApplicationState();
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_CANCELED) {
canceledResult = true;
}
}
private void routeApplicationState() {
int state = getApplicationState();
switch (state) {
case STATE_CREATE_PASSPHRASE: handleCreatePassphrase(); break;
case STATE_PROMPT_PASSPHRASE: handlePromptPassphrase(); break;
case STATE_CONVERSATION_OR_LIST: handleDisplayConversationOrList(); break;
case STATE_UPGRADE_DATABASE: handleUpgradeDatabase(); break;
case STATE_PROMPT_PUSH_REGISTRATION: handlePushRegistration(); break;
}
}
private void handleCreatePassphrase() {
Intent intent = new Intent(this, PassphraseCreateActivity.class);
startActivityForResult(intent, 1);
}
private void handlePromptPassphrase() {
Intent intent = new Intent(this, PassphrasePromptActivity.class);
startActivityForResult(intent, 2);
}
private void handleUpgradeDatabase() {
Intent intent = new Intent(this, DatabaseUpgradeActivity.class);
intent.putExtra("master_secret", masterSecret);
intent.putExtra("next_intent", TextSecurePreferences.hasPromptedPushRegistration(this) ?
getConversationListIntent() : getPushRegistrationIntent());
startActivity(intent);
finish();
}
private void handlePushRegistration() {
Intent intent = getPushRegistrationIntent();
intent.putExtra("next_intent", getConversationListIntent());
startActivity(intent);
finish();
}
private void handleDisplayConversationOrList() {
final ConversationParameters parameters = getConversationParameters();
final Intent intent;
if (isShareAction()) intent = getShareIntent(parameters);
else if (parameters.recipients != null) intent = getConversationIntent(parameters);
else intent = getConversationListIntent();
startActivity(intent);
finish();
}
private Intent getConversationIntent(ConversationParameters parameters) {
Intent intent = new Intent(this, ConversationActivity.class);
intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, parameters.recipients != null ? parameters.recipients.getIds() : new long[]{});
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, parameters.thread);
intent.putExtra(ConversationActivity.MASTER_SECRET_EXTRA, masterSecret);
intent.putExtra(ConversationActivity.DRAFT_TEXT_EXTRA, parameters.draftText);
intent.putExtra(ConversationActivity.DRAFT_IMAGE_EXTRA, parameters.draftImage);
intent.putExtra(ConversationActivity.DRAFT_AUDIO_EXTRA, parameters.draftAudio);
intent.putExtra(ConversationActivity.DRAFT_VIDEO_EXTRA, parameters.draftVideo);
return intent;
}
private Intent getShareIntent(ConversationParameters parameters) {
Intent intent = new Intent(this, ShareActivity.class);
intent.putExtra("master_secret", masterSecret);
if (parameters != null) {
intent.putExtra(ConversationActivity.DRAFT_TEXT_EXTRA, parameters.draftText);
intent.putExtra(ConversationActivity.DRAFT_IMAGE_EXTRA, parameters.draftImage);
intent.putExtra(ConversationActivity.DRAFT_AUDIO_EXTRA, parameters.draftAudio);
intent.putExtra(ConversationActivity.DRAFT_VIDEO_EXTRA, parameters.draftVideo);
}
return intent;
}
private Intent getConversationListIntent() {
Intent intent = new Intent(this, ConversationListActivity.class);
intent.putExtra("master_secret", masterSecret);
return intent;
}
private Intent getPushRegistrationIntent() {
Intent intent = new Intent(this, RegistrationActivity.class);
intent.putExtra("master_secret", masterSecret);
return intent;
}
private int getApplicationState() {
if (!MasterSecretUtil.isPassphraseInitialized(this))
return STATE_CREATE_PASSPHRASE;
if (masterSecret == null)
return STATE_PROMPT_PASSPHRASE;
if (DatabaseUpgradeActivity.isUpdate(this))
return STATE_UPGRADE_DATABASE;
if (!TextSecurePreferences.hasPromptedPushRegistration(this))
return STATE_PROMPT_PUSH_REGISTRATION;
return STATE_CONVERSATION_OR_LIST;
}
private ConversationParameters getConversationParameters() {
if (isSendAction()) {
return getConversationParametersForSendAction();
} else if (isShareAction()) {
return getConversationParametersForShareAction();
} else {
return getConversationParametersForInternalAction();
}
}
private ConversationParameters getConversationParametersForSendAction() {
Recipients recipients;
String body = getIntent().getStringExtra("sms_body");
long threadId = getIntent().getLongExtra("thread_id", -1);
Uri data = getIntent().getData();
if (data != null && data.getSchemeSpecificPart() != null) {
recipients = RecipientFactory.getRecipientsFromString(this, data.getSchemeSpecificPart(), false);
threadId = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipients);
} else {
recipients = null;
}
return new ConversationParameters(threadId, recipients, body, null, null, null);
}
private ConversationParameters getConversationParametersForShareAction() {
String type = getIntent().getType();
String draftText = getIntent().getStringExtra(Intent.EXTRA_TEXT);
Uri draftImage = null;
Uri draftAudio = null;
Uri draftVideo = null;
Uri streamExtra = getIntent().getParcelableExtra(Intent.EXTRA_STREAM);
if (streamExtra != null) {
type = getMimeType(streamExtra);
}
if (type != null && type.startsWith("image/")) {
draftImage = streamExtra;
} else if (type != null && type.startsWith("audio/")) {
draftAudio = streamExtra;
} else if (type != null && type.startsWith("video/")) {
draftVideo = streamExtra;
}
return new ConversationParameters(-1, null, draftText, draftImage, draftAudio, draftVideo);
}
private String getMimeType(Uri uri) {
String type = getContentResolver().getType(uri);
if (type == null) {
String extension = MimeTypeMap.getFileExtensionFromUrl(uri.toString());
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}
return type;
}
private ConversationParameters getConversationParametersForInternalAction() {
long threadId = getIntent().getLongExtra("thread_id", -1);
long[] recipientIds = getIntent().getLongArrayExtra("recipients");
Recipients recipients = recipientIds == null ? null : RecipientFactory.getRecipientsForIds(this, recipientIds, true);
return new ConversationParameters(threadId, recipients, null, null, null, null);
}
private boolean isShareAction() {
return Intent.ACTION_SEND.equals(getIntent().getAction());
}
private boolean isSendAction() {
return Intent.ACTION_SENDTO.equals(getIntent().getAction());
}
private static class ConversationParameters {
public final long thread;
public final Recipients recipients;
public final String draftText;
public final Uri draftImage;
public final Uri draftAudio;
public final Uri draftVideo;
public ConversationParameters(long thread, Recipients recipients,
String draftText, Uri draftImage, Uri draftAudio, Uri draftVideo)
{
this.thread = thread;
this.recipients = recipients;
this.draftText = draftText;
this.draftImage = draftImage;
this.draftAudio = draftAudio;
this.draftVideo = draftVideo;
}
}
}

View File

@ -20,15 +20,18 @@ package org.thoughtcrime.securesms;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.webkit.MimeTypeMap;
import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.recipients.Recipients; import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.MemoryCleaner;
import ws.com.google.android.mms.ContentType;
/** /**
* An activity to quickly share content with contacts * An activity to quickly share content with contacts
@ -37,23 +40,20 @@ import org.thoughtcrime.securesms.util.MemoryCleaner;
*/ */
public class ShareActivity extends PassphraseRequiredActionBarActivity public class ShareActivity extends PassphraseRequiredActionBarActivity
implements ShareFragment.ConversationSelectedListener implements ShareFragment.ConversationSelectedListener
{ {
public final static String MASTER_SECRET_EXTRA = "master_secret";
private final DynamicTheme dynamicTheme = new DynamicTheme (); private final DynamicTheme dynamicTheme = new DynamicTheme ();
private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
private ShareFragment fragment;
private MasterSecret masterSecret;
@Override @Override
public void onCreate(Bundle icicle) { protected void onPreCreate() {
dynamicTheme.onCreate(this); dynamicTheme.onCreate(this);
dynamicLanguage.onCreate(this); dynamicLanguage.onCreate(this);
super.onCreate(icicle); }
@Override
protected void onCreate(Bundle icicle, @NonNull MasterSecret masterSecret) {
setContentView(R.layout.share_activity); setContentView(R.layout.share_activity);
initializeResources(); initFragment(R.id.drawer_layout, new ShareFragment(), masterSecret);
} }
@Override @Override
@ -76,12 +76,6 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
if (!isFinishing()) finish(); if (!isFinishing()) finish();
} }
@Override
public void onDestroy() {
MemoryCleaner.clean(masterSecret);
super.onDestroy();
}
@Override @Override
public boolean onPrepareOptionsMenu(Menu menu) { public boolean onPrepareOptionsMenu(Menu menu) {
MenuInflater inflater = this.getMenuInflater(); MenuInflater inflater = this.getMenuInflater();
@ -102,12 +96,6 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
return false; return false;
} }
@Override
public void onMasterSecretCleared() {
startActivity(new Intent(this, RoutingActivity.class));
super.onMasterSecretCleared();
}
private void handleNewConversation() { private void handleNewConversation() {
Intent intent = getBaseShareIntent(NewConversationActivity.class); Intent intent = getBaseShareIntent(NewConversationActivity.class);
startActivity(intent); startActivity(intent);
@ -127,29 +115,32 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
startActivity(intent); startActivity(intent);
} }
private void initializeResources() {
this.masterSecret = getIntent().getParcelableExtra(MASTER_SECRET_EXTRA);
this.fragment = (ShareFragment)this.getSupportFragmentManager()
.findFragmentById(R.id.fragment_content);
this.fragment.setMasterSecret(masterSecret);
}
private Intent getBaseShareIntent(final Class<?> target) { private Intent getBaseShareIntent(final Class<?> target) {
final Intent intent = new Intent(this, target); final Intent intent = new Intent(this, target);
final Intent originalIntent = getIntent(); final String textExtra = getIntent().getStringExtra(ConversationActivity.DRAFT_TEXT_EXTRA);
final String draftText = originalIntent.getStringExtra(ConversationActivity.DRAFT_TEXT_EXTRA); final Uri streamExtra = getIntent().getParcelableExtra(Intent.EXTRA_STREAM);
final Uri draftImage = originalIntent.getParcelableExtra(ConversationActivity.DRAFT_IMAGE_EXTRA); final String type = streamExtra != null ? getMimeType(streamExtra) : getIntent().getType();
final Uri draftAudio = originalIntent.getParcelableExtra(ConversationActivity.DRAFT_AUDIO_EXTRA);
final Uri draftVideo = originalIntent.getParcelableExtra(ConversationActivity.DRAFT_VIDEO_EXTRA);
intent.putExtra(ConversationActivity.DRAFT_TEXT_EXTRA, draftText); if (ContentType.isImageType(type)) {
intent.putExtra(ConversationActivity.DRAFT_IMAGE_EXTRA, draftImage); intent.putExtra(ConversationActivity.DRAFT_IMAGE_EXTRA, streamExtra);
intent.putExtra(ConversationActivity.DRAFT_AUDIO_EXTRA, draftAudio); } else if (ContentType.isAudioType(type)) {
intent.putExtra(ConversationActivity.DRAFT_VIDEO_EXTRA, draftVideo); intent.putExtra(ConversationActivity.DRAFT_AUDIO_EXTRA, streamExtra);
intent.putExtra(NewConversationActivity.MASTER_SECRET_EXTRA, masterSecret); } else if (ContentType.isVideoType(type)) {
intent.putExtra(ConversationActivity.DRAFT_VIDEO_EXTRA, streamExtra);
}
intent.putExtra(ConversationActivity.DRAFT_TEXT_EXTRA, textExtra);
return intent; return intent;
} }
private String getMimeType(Uri uri) {
String type = getContentResolver().getType(uri);
if (type == null) {
String extension = MimeTypeMap.getFileExtensionFromUrl(uri.toString());
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}
return type;
}
} }

View File

@ -43,6 +43,12 @@ public class ShareFragment extends ListFragment implements LoaderManager.LoaderC
private ConversationSelectedListener listener; private ConversationSelectedListener listener;
private MasterSecret masterSecret; private MasterSecret masterSecret;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
masterSecret = getArguments().getParcelable("master_secret");
}
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
return inflater.inflate(R.layout.share_fragment, container, false); return inflater.inflate(R.layout.share_fragment, container, false);
@ -72,13 +78,6 @@ public class ShareFragment extends ListFragment implements LoaderManager.LoaderC
} }
} }
public void setMasterSecret(MasterSecret masterSecret) {
if (this.masterSecret != masterSecret) {
this.masterSecret = masterSecret;
initializeListAdapter();
}
}
private void initializeListAdapter() { private void initializeListAdapter() {
this.setListAdapter(new ShareListAdapter(getActivity(), null, masterSecret)); this.setListAdapter(new ShareListAdapter(getActivity(), null, masterSecret));
getListView().setRecyclerListener((ShareListAdapter) getListAdapter()); getListView().setRecyclerListener((ShareListAdapter) getListAdapter());

View File

@ -0,0 +1,39 @@
package org.thoughtcrime.securesms;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
public class SmsSendtoActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
startActivity(getNextIntent(getIntent()));
finish();
super.onCreate(savedInstanceState);
}
private Intent getNextIntent(Intent original) {
String body = original.getStringExtra("sms_body");
String data = original.getData().getSchemeSpecificPart();
Recipients recipients = RecipientFactory.getRecipientsFromString(this, data, false);
long threadId = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipients);
final Intent nextIntent;
if (recipients == null || recipients.isEmpty()) {
nextIntent = new Intent(this, NewConversationActivity.class);
nextIntent.putExtra(ConversationActivity.DRAFT_TEXT_EXTRA, body);
Toast.makeText(this, R.string.ConversationActivity_specify_recipient, Toast.LENGTH_LONG).show();
} else {
nextIntent = new Intent(this, ConversationActivity.class);
nextIntent.putExtra(ConversationActivity.DRAFT_TEXT_EXTRA, body);
nextIntent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
nextIntent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients.getIds());
}
return nextIntent;
}
}

View File

@ -18,6 +18,7 @@
package org.thoughtcrime.securesms; package org.thoughtcrime.securesms;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
@ -29,7 +30,6 @@ import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory; import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.MemoryCleaner;
import org.whispersystems.libaxolotl.AxolotlAddress; import org.whispersystems.libaxolotl.AxolotlAddress;
import org.whispersystems.libaxolotl.IdentityKey; import org.whispersystems.libaxolotl.IdentityKey;
import org.whispersystems.libaxolotl.state.SessionRecord; import org.whispersystems.libaxolotl.state.SessionRecord;
@ -53,10 +53,14 @@ public class VerifyIdentityActivity extends KeyScanningActivity {
private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
@Override @Override
public void onCreate(Bundle state) { protected void onPreCreate() {
dynamicTheme.onCreate(this); dynamicTheme.onCreate(this);
dynamicLanguage.onCreate(this); dynamicLanguage.onCreate(this);
super.onCreate(state); }
@Override
protected void onCreate(Bundle state, @NonNull MasterSecret masterSecret) {
this.masterSecret = masterSecret;
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
setContentView(R.layout.verify_identity_activity); setContentView(R.layout.verify_identity_activity);
@ -73,12 +77,6 @@ public class VerifyIdentityActivity extends KeyScanningActivity {
} }
@Override
protected void onDestroy() {
MemoryCleaner.clean(masterSecret);
super.onDestroy();
}
private void initializeLocalIdentityKey() { private void initializeLocalIdentityKey() {
if (!IdentityKeyUtil.hasIdentityKey(this)) { if (!IdentityKeyUtil.hasIdentityKey(this)) {
localIdentityFingerprint.setText(R.string.VerifyIdentityActivity_you_do_not_have_an_identity_key); localIdentityFingerprint.setText(R.string.VerifyIdentityActivity_you_do_not_have_an_identity_key);
@ -116,7 +114,6 @@ public class VerifyIdentityActivity extends KeyScanningActivity {
this.localIdentityFingerprint = (TextView)findViewById(R.id.you_read); this.localIdentityFingerprint = (TextView)findViewById(R.id.you_read);
this.remoteIdentityFingerprint = (TextView)findViewById(R.id.friend_reads); this.remoteIdentityFingerprint = (TextView)findViewById(R.id.friend_reads);
this.recipient = RecipientFactory.getRecipientForId(this, this.getIntent().getLongExtra("recipient", -1), true); this.recipient = RecipientFactory.getRecipientForId(this, this.getIntent().getLongExtra("recipient", -1), true);
this.masterSecret = this.getIntent().getParcelableExtra("master_secret");
} }
@Override @Override

View File

@ -17,8 +17,10 @@
package org.thoughtcrime.securesms; package org.thoughtcrime.securesms;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.widget.TextView; import android.widget.TextView;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.whispersystems.libaxolotl.IdentityKey; import org.whispersystems.libaxolotl.IdentityKey;
import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable; import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable;
@ -36,8 +38,7 @@ public class ViewIdentityActivity extends KeyScanningActivity {
private IdentityKey identityKey; private IdentityKey identityKey;
@Override @Override
public void onCreate(Bundle state) { protected void onCreate(Bundle state, @NonNull MasterSecret masterSecret) {
super.onCreate(state);
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
setContentView(R.layout.view_identity_activity); setContentView(R.layout.view_identity_activity);

View File

@ -18,13 +18,14 @@
package org.thoughtcrime.securesms; package org.thoughtcrime.securesms;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.widget.Toast;
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable; import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable;
import org.thoughtcrime.securesms.crypto.MasterSecret;
/** /**
* Activity that displays the local identity key and offers the option to regenerate it. * Activity that displays the local identity key and offers the option to regenerate it.
@ -33,12 +34,13 @@ import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable;
*/ */
public class ViewLocalIdentityActivity extends ViewIdentityActivity { public class ViewLocalIdentityActivity extends ViewIdentityActivity {
public void onCreate(Bundle bundle) { @Override
protected void onCreate(Bundle icicle, @NonNull MasterSecret masterSecret) {
getIntent().putExtra(ViewIdentityActivity.IDENTITY_KEY, getIntent().putExtra(ViewIdentityActivity.IDENTITY_KEY,
new IdentityKeyParcelable(IdentityKeyUtil.getIdentityKey(this))); new IdentityKeyParcelable(IdentityKeyUtil.getIdentityKey(this)));
getIntent().putExtra(ViewIdentityActivity.TITLE, getIntent().putExtra(ViewIdentityActivity.TITLE,
getString(R.string.ViewIdentityActivity_my_identity_fingerprint)); getString(R.string.ViewIdentityActivity_my_identity_fingerprint));
super.onCreate(bundle); super.onCreate(icicle, masterSecret);
} }
@Override @Override

View File

@ -39,8 +39,8 @@ import android.text.TextUtils;
import android.text.style.StyleSpan; import android.text.style.StyleSpan;
import android.util.Log; import android.util.Log;
import org.thoughtcrime.securesms.ConversationActivity;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.RoutingActivity;
import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsSmsDatabase; import org.thoughtcrime.securesms.database.MmsSmsDatabase;
@ -84,7 +84,7 @@ public class MessageNotifier {
if (visibleThread == threadId) { if (visibleThread == threadId) {
sendInThreadNotification(context); sendInThreadNotification(context);
} else { } else {
Intent intent = new Intent(context, RoutingActivity.class); Intent intent = new Intent(context, ConversationActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra("recipients", recipients.getIds()); intent.putExtra("recipients", recipients.getIds());
intent.putExtra("thread_id", threadId); intent.putExtra("thread_id", threadId);
@ -228,7 +228,7 @@ public class MessageNotifier {
notificationState.getMessageCount())); notificationState.getMessageCount()));
builder.setContentText(String.format(context.getString(R.string.MessageNotifier_most_recent_from_s), builder.setContentText(String.format(context.getString(R.string.MessageNotifier_most_recent_from_s),
notifications.get(0).getIndividualRecipientName())); notifications.get(0).getIndividualRecipientName()));
builder.setContentIntent(PendingIntent.getActivity(context, 0, new Intent(context, RoutingActivity.class), 0)); builder.setContentIntent(PendingIntent.getActivity(context, 0, new Intent(context, ConversationActivity.class), 0));
builder.setContentInfo(String.valueOf(notificationState.getMessageCount())); builder.setContentInfo(String.valueOf(notificationState.getMessageCount()));
builder.setNumber(notificationState.getMessageCount()); builder.setNumber(notificationState.getMessageCount());

View File

@ -6,7 +6,7 @@ import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.text.SpannableStringBuilder; import android.text.SpannableStringBuilder;
import org.thoughtcrime.securesms.RoutingActivity; import org.thoughtcrime.securesms.ConversationActivity;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.Recipients; import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.Util;
@ -70,16 +70,12 @@ public class NotificationItem {
} }
public PendingIntent getPendingIntent(Context context) { public PendingIntent getPendingIntent(Context context) {
Intent intent = new Intent(context, RoutingActivity.class); Intent intent = new Intent(context, ConversationActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
if (recipients != null || threadRecipients != null) { Recipients notifyRecipients = threadRecipients != null ? threadRecipients : recipients;
if (threadRecipients != null) intent.putExtra("recipients", threadRecipients.getIds()); if (notifyRecipients != null) intent.putExtra("recipients", notifyRecipients.getIds());
else intent.putExtra("recipients", recipients.getIds());
intent.putExtra("thread_id", threadId); intent.putExtra("thread_id", threadId);
}
intent.setData((Uri.parse("custom://"+System.currentTimeMillis()))); intent.setData((Uri.parse("custom://"+System.currentTimeMillis())));
return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

View File

@ -27,6 +27,7 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
public class AppProtectionPreferenceFragment extends PreferenceFragment { public class AppProtectionPreferenceFragment extends PreferenceFragment {
private MasterSecret masterSecret;
private CheckBoxPreference disablePassphrase; private CheckBoxPreference disablePassphrase;
@Override @Override
@ -34,6 +35,7 @@ public class AppProtectionPreferenceFragment extends PreferenceFragment {
super.onCreate(paramBundle); super.onCreate(paramBundle);
addPreferencesFromResource(R.xml.preferences_app_protection); addPreferencesFromResource(R.xml.preferences_app_protection);
masterSecret = getArguments().getParcelable("master_secret");
disablePassphrase = (CheckBoxPreference) this.findPreference("pref_enable_passphrase_temporary"); disablePassphrase = (CheckBoxPreference) this.findPreference("pref_enable_passphrase_temporary");
this.findPreference(TextSecurePreferences.CHANGE_PASSPHRASE_PREF) this.findPreference(TextSecurePreferences.CHANGE_PASSPHRASE_PREF)
@ -126,12 +128,10 @@ public class AppProtectionPreferenceFragment extends PreferenceFragment {
builder.setPositiveButton(R.string.ApplicationPreferencesActivity_disable, new DialogInterface.OnClickListener() { builder.setPositiveButton(R.string.ApplicationPreferencesActivity_disable, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
MasterSecret masterSecret = getActivity().getIntent().getParcelableExtra("master_secret");
MasterSecretUtil.changeMasterSecretPassphrase(getActivity(), MasterSecretUtil.changeMasterSecretPassphrase(getActivity(),
masterSecret, masterSecret,
MasterSecretUtil.UNENCRYPTED_PASSPHRASE); MasterSecretUtil.UNENCRYPTED_PASSPHRASE);
TextSecurePreferences.setPasswordDisabled(getActivity(), true); TextSecurePreferences.setPasswordDisabled(getActivity(), true);
((CheckBoxPreference)preference).setChecked(false); ((CheckBoxPreference)preference).setChecked(false);

View File

@ -17,6 +17,7 @@
package org.thoughtcrime.securesms.preferences; package org.thoughtcrime.securesms.preferences;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction; import android.support.v4.app.FragmentTransaction;
@ -26,25 +27,22 @@ import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity;
import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.MemoryCleaner;
public class MmsPreferencesActivity extends PassphraseRequiredActionBarActivity { public class MmsPreferencesActivity extends PassphraseRequiredActionBarActivity {
private MasterSecret masterSecret;
private final DynamicTheme dynamicTheme = new DynamicTheme(); private final DynamicTheme dynamicTheme = new DynamicTheme();
private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
@Override @Override
protected void onCreate(Bundle icicle) { protected void onPreCreate() {
dynamicTheme.onCreate(this); dynamicTheme.onCreate(this);
dynamicLanguage.onCreate(this); dynamicLanguage.onCreate(this);
super.onCreate(icicle); }
@Override
protected void onCreate(Bundle icicle, @NonNull MasterSecret masterSecret) {
this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); this.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
masterSecret = getIntent().getParcelableExtra("master_secret");
Fragment fragment = new MmsPreferencesFragment(); Fragment fragment = new MmsPreferencesFragment();
FragmentManager fragmentManager = getSupportFragmentManager(); FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
@ -60,13 +58,6 @@ public class MmsPreferencesActivity extends PassphraseRequiredActionBarActivity
dynamicLanguage.onResume(this); dynamicLanguage.onResume(this);
} }
@Override
public void onDestroy() {
MemoryCleaner.clean(masterSecret);
MemoryCleaner.clean((MasterSecret) getIntent().getParcelableExtra("master_secret"));
super.onDestroy();
}
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {

View File

@ -17,8 +17,8 @@ import android.os.PowerManager.WakeLock;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import android.util.Log; import android.util.Log;
import org.thoughtcrime.securesms.ConversationListActivity;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.RoutingActivity;
import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.SmsMigrator; import org.thoughtcrime.securesms.database.SmsMigrator;
import org.thoughtcrime.securesms.database.SmsMigrator.ProgressDescription; import org.thoughtcrime.securesms.database.SmsMigrator.ProgressDescription;
@ -28,8 +28,8 @@ import java.util.concurrent.Executors;
public class ApplicationMigrationService extends Service public class ApplicationMigrationService extends Service
implements SmsMigrator.SmsMigrationProgressListener implements SmsMigrator.SmsMigrationProgressListener
{ {
private static final String TAG = ApplicationMigrationService.class.getSimpleName();
public static final String MIGRATE_DATABASE = "org.thoughtcrime.securesms.ApplicationMigration.MIGRATE_DATABSE"; public static final String MIGRATE_DATABASE = "org.thoughtcrime.securesms.ApplicationMigration.MIGRATE_DATABSE";
public static final String COMPLETED_ACTION = "org.thoughtcrime.securesms.ApplicationMigrationService.COMPLETED"; public static final String COMPLETED_ACTION = "org.thoughtcrime.securesms.ApplicationMigrationService.COMPLETED";
private static final String PREFERENCES_NAME = "SecureSMS"; private static final String PREFERENCES_NAME = "SecureSMS";
@ -128,7 +128,7 @@ public class ApplicationMigrationService extends Service
builder.setContentText(getString(R.string.ApplicationMigrationService_import_in_progress)); builder.setContentText(getString(R.string.ApplicationMigrationService_import_in_progress));
builder.setOngoing(true); builder.setOngoing(true);
builder.setProgress(100, 0, false); builder.setProgress(100, 0, false);
builder.setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, RoutingActivity.class), 0)); builder.setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, ConversationListActivity.class), 0));
stopForeground(true); stopForeground(true);
startForeground(4242, builder.build()); startForeground(4242, builder.build());
@ -141,7 +141,7 @@ public class ApplicationMigrationService extends Service
public ImportRunnable(Intent intent) { public ImportRunnable(Intent intent) {
this.masterSecret = intent.getParcelableExtra("master_secret"); this.masterSecret = intent.getParcelableExtra("master_secret");
Log.w("ApplicationMigrationService", "Service got mastersecret: " + masterSecret); Log.w(TAG, "Service got mastersecret: " + masterSecret);
} }
@Override @Override
@ -184,7 +184,7 @@ public class ApplicationMigrationService extends Service
builder.setSmallIcon(R.drawable.icon_notification); builder.setSmallIcon(R.drawable.icon_notification);
builder.setContentTitle("Import Complete"); builder.setContentTitle("Import Complete");
builder.setContentText("TextSecure system database import is complete."); builder.setContentText("TextSecure system database import is complete.");
builder.setContentIntent(PendingIntent.getActivity(context, 0, new Intent(context, RoutingActivity.class), 0)); builder.setContentIntent(PendingIntent.getActivity(context, 0, new Intent(context, ConversationListActivity.class), 0));
builder.setWhen(System.currentTimeMillis()); builder.setWhen(System.currentTimeMillis());
builder.setDefaults(Notification.DEFAULT_VIBRATE); builder.setDefaults(Notification.DEFAULT_VIBRATE);
builder.setAutoCancel(true); builder.setAutoCancel(true);

View File

@ -33,10 +33,10 @@ import android.util.Log;
import android.widget.RemoteViews; import android.widget.RemoteViews;
import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.ConversationListActivity;
import org.thoughtcrime.securesms.DatabaseUpgradeActivity; import org.thoughtcrime.securesms.DatabaseUpgradeActivity;
import org.thoughtcrime.securesms.DummyActivity; import org.thoughtcrime.securesms.DummyActivity;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.RoutingActivity;
import org.thoughtcrime.securesms.crypto.InvalidPassphraseException; import org.thoughtcrime.securesms.crypto.InvalidPassphraseException;
import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.MasterSecretUtil; import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
@ -121,6 +121,7 @@ public class KeyCachingService extends Service {
@Override @Override
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
if (intent == null) return START_NOT_STICKY; if (intent == null) return START_NOT_STICKY;
Log.w("KeyCachingService", "onStartCommand, " + intent.getAction());
if (intent.getAction() != null) { if (intent.getAction() != null) {
switch (intent.getAction()) { switch (intent.getAction()) {
@ -138,6 +139,7 @@ public class KeyCachingService extends Service {
@Override @Override
public void onCreate() { public void onCreate() {
Log.w("KeyCachingService", "onCreate()");
super.onCreate(); super.onCreate();
this.pending = PendingIntent.getService(this, 0, new Intent(PASSPHRASE_EXPIRED_EVENT, null, this.pending = PendingIntent.getService(this, 0, new Intent(PASSPHRASE_EXPIRED_EVENT, null,
this, KeyCachingService.class), 0); this, KeyCachingService.class), 0);
@ -186,7 +188,8 @@ public class KeyCachingService extends Service {
} }
private void handleClearKey() { private void handleClearKey() {
this.masterSecret = null; Log.w("KeyCachingService", "handleClearKey()");
KeyCachingService.masterSecret = null;
stopForeground(true); stopForeground(true);
Intent intent = new Intent(CLEAR_KEY_EVENT); Intent intent = new Intent(CLEAR_KEY_EVENT);
@ -216,7 +219,7 @@ public class KeyCachingService extends Service {
private void startTimeoutIfAppropriate() { private void startTimeoutIfAppropriate() {
boolean timeoutEnabled = TextSecurePreferences.isPassphraseTimeoutEnabled(this); boolean timeoutEnabled = TextSecurePreferences.isPassphraseTimeoutEnabled(this);
if ((activitiesRunning == 0) && (this.masterSecret != null) && timeoutEnabled && !TextSecurePreferences.isPasswordDisabled(this)) { if ((activitiesRunning == 0) && (KeyCachingService.masterSecret != null) && timeoutEnabled && !TextSecurePreferences.isPasswordDisabled(this)) {
long timeoutMinutes = TextSecurePreferences.getPassphraseTimeoutInterval(this); long timeoutMinutes = TextSecurePreferences.getPassphraseTimeoutInterval(this);
long timeoutMillis = TimeUnit.MINUTES.toMillis(timeoutMinutes); long timeoutMillis = TimeUnit.MINUTES.toMillis(timeoutMinutes);
@ -230,6 +233,7 @@ public class KeyCachingService extends Service {
@TargetApi(Build.VERSION_CODES.JELLY_BEAN) @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void foregroundServiceModern() { private void foregroundServiceModern() {
Log.w("KeyCachingService", "foregrounding KCS");
NotificationCompat.Builder builder = new NotificationCompat.Builder(this); NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentTitle(getString(R.string.KeyCachingService_passphrase_cached)); builder.setContentTitle(getString(R.string.KeyCachingService_passphrase_cached));
@ -292,7 +296,6 @@ public class KeyCachingService extends Service {
Log.w("service", "Broadcasting new secret..."); Log.w("service", "Broadcasting new secret...");
Intent intent = new Intent(NEW_KEY_EVENT); Intent intent = new Intent(NEW_KEY_EVENT);
intent.putExtra("master_secret", masterSecret);
intent.setPackage(getApplicationContext().getPackageName()); intent.setPackage(getApplicationContext().getPackageName());
sendBroadcast(intent, KEY_PERMISSION); sendBroadcast(intent, KEY_PERMISSION);
@ -306,7 +309,7 @@ public class KeyCachingService extends Service {
} }
private PendingIntent buildLaunchIntent() { private PendingIntent buildLaunchIntent() {
Intent intent = new Intent(this, RoutingActivity.class); Intent intent = new Intent(this, ConversationListActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent launchIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0); PendingIntent launchIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0);
return launchIntent; return launchIntent;

View File

@ -8,8 +8,8 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import org.thoughtcrime.securesms.ConversationListActivity;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.RoutingActivity;
public class RegistrationNotifier extends BroadcastReceiver { public class RegistrationNotifier extends BroadcastReceiver {
@Override @Override
@ -18,7 +18,7 @@ public class RegistrationNotifier extends BroadcastReceiver {
builder.setSmallIcon(R.drawable.icon_notification); builder.setSmallIcon(R.drawable.icon_notification);
builder.setContentTitle(intent.getStringExtra(RegistrationService.NOTIFICATION_TITLE)); builder.setContentTitle(intent.getStringExtra(RegistrationService.NOTIFICATION_TITLE));
builder.setContentText(intent.getStringExtra(RegistrationService.NOTIFICATION_TEXT)); builder.setContentText(intent.getStringExtra(RegistrationService.NOTIFICATION_TEXT));
builder.setContentIntent(PendingIntent.getActivity(context, 0, new Intent(context, RoutingActivity.class), 0)); builder.setContentIntent(PendingIntent.getActivity(context, 0, new Intent(context, ConversationListActivity.class), 0));
builder.setWhen(System.currentTimeMillis()); builder.setWhen(System.currentTimeMillis());
builder.setDefaults(Notification.DEFAULT_VIBRATE); builder.setDefaults(Notification.DEFAULT_VIBRATE);
builder.setAutoCancel(true); builder.setAutoCancel(true);

View File

@ -1,82 +0,0 @@
/**
* Copyright (C) 2011 Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms.util;
import org.thoughtcrime.securesms.crypto.MasterSecret;
/**
* This is not straightforward in Java, but this class makes
* a best-effort attempt to clean up memory in immutable objects.
*
* @author Moxie Marlinspike
*/
public class MemoryCleaner {
// XXX This is basically not happening for now.
// The problem is that now secrets are moving
// through both Intents and binder calls, which
// means sometimes they're shared memory and sometimes
// they're not. We're going to need to do a lot more
// work in order to accurately keep track of when to
// wipe this within an Activity lifecycle. =(
public static void clean(MasterSecret masterSecret) {
// if (masterSecret == null)
// return;
//
// try {
// SecretKeySpec cipherKey = masterSecret.getEncryptionKey();
// SecretKeySpec macKey = masterSecret.getMacKey();
//
// Field keyField = SecretKeySpec.class.getDeclaredField("key");
// keyField.setAccessible(true);
//
// byte[] cipherKeyField = (byte[]) keyField.get(cipherKey);
// byte[] macKeyField = (byte[]) keyField.get(macKey);
//
// Arrays.fill(cipherKeyField, (byte)0x00);
// Arrays.fill(macKeyField, (byte)0x00);
//
// } catch (NoSuchFieldException nsfe) {
// Log.w("MemoryCleaner", nsfe);
// } catch (IllegalArgumentException e) {
// Log.w("MemoryCleaner", e);
// } catch (IllegalAccessException e) {
// Log.w("MemoryCleaner", e);
// }
}
public static void clean(String string) {
// if (string == null)
// return;
//
// try {
// Field charArrayField = String.class.getDeclaredField("value");
// charArrayField.setAccessible(true);
//
// char[] internalBuffer = (char[])charArrayField.get(string);
//
// Arrays.fill(internalBuffer, 'A');
// } catch (NoSuchFieldException nsfe) {
// Log.w("MemoryCleaner", nsfe);
// } catch (IllegalArgumentException e) {
// Log.w("MemoryCleaner", e);
// } catch (IllegalAccessException e) {
// Log.w("MemoryCleaner", e);
// }
}
}