diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 73e3e51c40..adbefd5d03 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -9,7 +9,7 @@ android:label="Access to TextSecure Secrets" android:protectionLevel="signature" /> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"> + + + + + + + + + + + + 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:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/> + + + + + + + + + + + @@ -245,14 +244,6 @@ - - - - - - - - diff --git a/res/layout/conversation_activity.xml b/res/layout/conversation_activity.xml index a8d5a685d0..9fe067a22e 100644 --- a/res/layout/conversation_activity.xml +++ b/res/layout/conversation_activity.xml @@ -14,12 +14,10 @@ android:orientation="vertical" android:gravity="bottom"> - + - - - - - \ No newline at end of file diff --git a/res/layout/share_activity.xml b/res/layout/share_activity.xml index 63dfc53ede..366cf777e1 100644 --- a/res/layout/share_activity.xml +++ b/res/layout/share_activity.xml @@ -1,13 +1,9 @@ - + - - - + diff --git a/res/values/strings.xml b/res/values/strings.xml index 2b454ba664..223afe0f62 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -115,6 +115,7 @@ Error leaving group... MMS not supported This message cannot be sent since your carrier doesn\'t support MMS. + Please choose a contact Message details diff --git a/src/org/thoughtcrime/securesms/ActionBarListActivity.java b/src/org/thoughtcrime/securesms/ActionBarListActivity.java deleted file mode 100644 index af4b7a07d9..0000000000 --- a/src/org/thoughtcrime/securesms/ActionBarListActivity.java +++ /dev/null @@ -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); - } -} diff --git a/src/org/thoughtcrime/securesms/ApplicationPreferencesActivity.java b/src/org/thoughtcrime/securesms/ApplicationPreferencesActivity.java index fc0f5e2e46..558b18c5ee 100644 --- a/src/org/thoughtcrime/securesms/ApplicationPreferencesActivity.java +++ b/src/org/thoughtcrime/securesms/ApplicationPreferencesActivity.java @@ -20,6 +20,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.preference.Preference; +import android.support.annotation.NonNull; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; 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.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicTheme; -import org.thoughtcrime.securesms.util.MemoryCleaner; import org.thoughtcrime.securesms.util.TextSecurePreferences; /** @@ -61,18 +61,24 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); @Override - protected void onCreate(Bundle icicle) { + protected void onPreCreate() { dynamicTheme.onCreate(this); dynamicLanguage.onCreate(this); - super.onCreate(icicle); + } + @Override + protected void onCreate(Bundle icicle, @NonNull MasterSecret masterSecret) { this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); - Fragment fragment = new ApplicationPreferenceFragment(); - FragmentManager fragmentManager = getSupportFragmentManager(); - FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); - fragmentTransaction.replace(android.R.id.content, fragment); - fragmentTransaction.commit(); + Bundle fragmentArgs = new Bundle(); + Fragment fragment = new ApplicationPreferenceFragment(); + + fragmentArgs.putParcelable("master_secret", masterSecret); + fragment.setArguments(fragmentArgs); + + getSupportFragmentManager().beginTransaction() + .replace(android.R.id.content, fragment) + .commit(); } @Override @@ -104,12 +110,6 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA return true; } - @Override - public void onDestroy() { - MemoryCleaner.clean((MasterSecret) getIntent().getParcelableExtra("master_secret")); - super.onDestroy(); - } - @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (key.equals(TextSecurePreferences.THEME_PREF)) { @@ -129,18 +129,19 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA super.onCreate(icicle); addPreferencesFromResource(R.xml.preferences); + MasterSecret masterSecret = getArguments().getParcelable("master_secret"); 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) - .setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_NOTIFICATIONS)); + .setOnPreferenceClickListener(new CategoryClickListener(masterSecret, PREFERENCE_CATEGORY_NOTIFICATIONS)); 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) - .setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_APPEARANCE)); + .setOnPreferenceClickListener(new CategoryClickListener(masterSecret, PREFERENCE_CATEGORY_APPEARANCE)); this.findPreference(PREFERENCE_CATEGORY_STORAGE) - .setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_STORAGE)); + .setOnPreferenceClickListener(new CategoryClickListener(masterSecret, PREFERENCE_CATEGORY_STORAGE)); this.findPreference(PREFERENCE_CATEGORY_ADVANCED) - .setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_ADVANCED)); + .setOnPreferenceClickListener(new CategoryClickListener(masterSecret, PREFERENCE_CATEGORY_ADVANCED)); } @Override @@ -164,10 +165,12 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA } private class CategoryClickListener implements Preference.OnPreferenceClickListener { - private String category; + private MasterSecret masterSecret; + private String category; - public CategoryClickListener(String category) { - this.category = category; + public CategoryClickListener(MasterSecret masterSecret, String category) { + this.masterSecret = masterSecret; + this.category = category; } @Override @@ -182,7 +185,10 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA fragment = new NotificationsPreferenceFragment(); break; case PREFERENCE_CATEGORY_APP_PROTECTION: + Bundle args = new Bundle(); + args.putParcelable("master_secret", masterSecret); fragment = new AppProtectionPreferenceFragment(); + fragment.setArguments(args); break; case PREFERENCE_CATEGORY_APPEARANCE: fragment = new AppearancePreferenceFragment(); diff --git a/src/org/thoughtcrime/securesms/ConversationActivity.java b/src/org/thoughtcrime/securesms/ConversationActivity.java index 6e96c98a5c..7c16fa33b7 100644 --- a/src/org/thoughtcrime/securesms/ConversationActivity.java +++ b/src/org/thoughtcrime/securesms/ConversationActivity.java @@ -27,6 +27,7 @@ import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.provider.ContactsContract; +import android.support.annotation.NonNull; import android.telephony.PhoneNumberUtils; import android.text.Editable; 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.Emoji; import org.thoughtcrime.securesms.util.GroupUtil; -import org.thoughtcrime.securesms.util.MemoryCleaner; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.Util; 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 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_IMAGE_EXTRA = "draft_image"; public static final String DRAFT_AUDIO_EXTRA = "draft_audio"; @@ -139,10 +138,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity private static final int PICK_CONTACT_INFO = 4; private static final int GROUP_EDIT = 5; - private MasterSecret masterSecret; - private ComposeText composeText; - private SendButton sendButton; - private TextView charactersLeft; + private MasterSecret masterSecret; + private ComposeText composeText; + private SendButton sendButton; + private TextView charactersLeft; + private ConversationFragment fragment; private AttachmentTypeSelectorAdapter attachmentAdapter; private AttachmentManager attachmentManager; @@ -161,14 +161,19 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity private DynamicLanguage dynamicLanguage = new DynamicLanguage(); @Override - protected void onCreate(Bundle state) { - overridePendingTransition(R.anim.slide_from_right, R.anim.fade_scale_out); + protected void onPreCreate() { dynamicTheme.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); getSupportActionBar().setDisplayHomeAsUpEnabled(true); + fragment = initFragment(R.id.fragment_content, new ConversationFragment(), masterSecret); initializeReceivers(); initializeViews(); @@ -178,6 +183,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity @Override protected void onNewIntent(Intent intent) { + Log.w(TAG, "onNewIntent()"); + if (!Util.isEmpty(composeText) || attachmentManager.isAttachmentPresent()) { saveDraft(); attachmentManager.clear(); @@ -185,12 +192,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity } setIntent(intent); - initializeResources(); initializeDraft(); - ConversationFragment fragment = getFragment(); - if (fragment != null) { fragment.onNewIntent(); } @@ -223,10 +227,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity @Override protected void onDestroy() { saveDraft(); - recipients.removeListener(this); - unregisterReceiver(securityUpdateReceiver); - unregisterReceiver(groupUpdateReceiver); - MemoryCleaner.clean(masterSecret); + if (recipients != null) recipients.removeListener(this); + if (securityUpdateReceiver != null) unregisterReceiver(securityUpdateReceiver); + if (groupUpdateReceiver != null) unregisterReceiver(groupUpdateReceiver); super.onDestroy(); } @@ -333,7 +336,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity private void handleReturnToConversationList() { Intent intent = new Intent(this, ConversationListActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - intent.putExtra("master_secret", masterSecret); startActivity(intent); finish(); } @@ -351,7 +353,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity private void handleVerifyIdentity() { Intent verifyIdentityIntent = new Intent(this, VerifyIdentityActivity.class); verifyIdentityIntent.putExtra("recipient", getRecipients().getPrimaryRecipient().getRecipientId()); - verifyIdentityIntent.putExtra("master_secret", masterSecret); startActivity(verifyIdentityIntent); } @@ -392,7 +393,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity Intent intent = new Intent(this, MediaOverviewActivity.class); intent.putExtra(MediaOverviewActivity.THREAD_ID_EXTRA, threadId); intent.putExtra(MediaOverviewActivity.RECIPIENT_EXTRA, recipients.getPrimaryRecipient().getRecipientId()); - intent.putExtra(MediaOverviewActivity.MASTER_SECRET_EXTRA, masterSecret); startActivity(intent); } @@ -439,7 +439,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity private void handleEditPushGroup() { Intent intent = new Intent(ConversationActivity.this, GroupCreateActivity.class); - intent.putExtra(GroupCreateActivity.MASTER_SECRET_EXTRA, masterSecret); intent.putExtra(GroupCreateActivity.GROUP_RECIPIENT_EXTRA, recipients.getPrimaryRecipient().getRecipientId()); startActivityForResult(intent, GROUP_EDIT); } @@ -724,7 +723,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity recipients = RecipientFactory.getRecipientsForIds(this, getIntent().getLongArrayExtra(RECIPIENTS_EXTRA), true); threadId = getIntent().getLongExtra(THREAD_ID_EXTRA, -1); distributionType = getIntent().getIntExtra(DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT); - masterSecret = getIntent().getParcelableExtra(MASTER_SECRET_EXTRA); recipients.addListener(this); } @@ -901,8 +899,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity } else if (threadId > 0) { threadDatabase.update(threadId); } - - MemoryCleaner.clean(thisMasterSecret); return null; } }.execute(thisThreadId); @@ -978,8 +974,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity boolean refreshFragment = (threadId != this.threadId); this.threadId = threadId; - ConversationFragment fragment = getFragment(); - if (fragment == null) { return; } @@ -994,10 +988,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity fragment.scrollToBottom(); } - private ConversationFragment getFragment() { - return (ConversationFragment)getSupportFragmentManager().findFragmentById(R.id.fragment_content); - } - private void sendMessage() { try { Recipients recipients = getRecipients(); diff --git a/src/org/thoughtcrime/securesms/ConversationFragment.java b/src/org/thoughtcrime/securesms/ConversationFragment.java index d415b28fc7..6a19c6c216 100644 --- a/src/org/thoughtcrime/securesms/ConversationFragment.java +++ b/src/org/thoughtcrime/securesms/ConversationFragment.java @@ -61,6 +61,12 @@ public class ConversationFragment extends ListFragment private long threadId; private ActionMode actionMode; + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + this.masterSecret = getArguments().getParcelable("master_secret"); + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) { return inflater.inflate(R.layout.conversation_fragment, container, false); @@ -101,7 +107,6 @@ public class ConversationFragment extends ListFragment } private void initializeResources() { - this.masterSecret = this.getActivity().getIntent().getParcelableExtra("master_secret"); this.recipients = RecipientFactory.getRecipientsForIds(getActivity(), getActivity().getIntent().getLongArrayExtra("recipients"), true); this.threadId = this.getActivity().getIntent().getLongExtra("thread_id", -1); } @@ -233,7 +238,6 @@ public class ConversationFragment extends ListFragment private void handleForwardMessage(MessageRecord message) { Intent composeIntent = new Intent(getActivity(), ShareActivity.class); composeIntent.putExtra(ConversationActivity.DRAFT_TEXT_EXTRA, message.getDisplayBody().toString()); - composeIntent.putExtra(ShareActivity.MASTER_SECRET_EXTRA, masterSecret); startActivity(composeIntent); } diff --git a/src/org/thoughtcrime/securesms/ConversationItem.java b/src/org/thoughtcrime/securesms/ConversationItem.java index d6179bad04..a190c2b767 100644 --- a/src/org/thoughtcrime/securesms/ConversationItem.java +++ b/src/org/thoughtcrime/securesms/ConversationItem.java @@ -426,7 +426,6 @@ public class ConversationItem extends LinearLayout { intent.putExtra("is_bundle", messageRecord.isBundleKeyExchange()); intent.putExtra("is_identity_update", messageRecord.isIdentityUpdate()); intent.putExtra("is_push", messageRecord.isPush()); - intent.putExtra("master_secret", masterSecret); intent.putExtra("sent", messageRecord.isOutgoing()); context.startActivity(intent); } @@ -458,7 +457,6 @@ public class ConversationItem extends LinearLayout { Intent intent = new Intent(context, MediaPreviewActivity.class); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.setDataAndType(slide.getUri(), slide.getContentType()); - intent.putExtra(MediaPreviewActivity.MASTER_SECRET_EXTRA, masterSecret); if (!messageRecord.isOutgoing()) intent.putExtra(MediaPreviewActivity.RECIPIENT_EXTRA, messageRecord.getIndividualRecipient().getRecipientId()); intent.putExtra(MediaPreviewActivity.DATE_EXTRA, messageRecord.getDateReceived()); diff --git a/src/org/thoughtcrime/securesms/ConversationListActivity.java b/src/org/thoughtcrime/securesms/ConversationListActivity.java index 6505b3eee0..44f23dcca9 100644 --- a/src/org/thoughtcrime/securesms/ConversationListActivity.java +++ b/src/org/thoughtcrime/securesms/ConversationListActivity.java @@ -21,6 +21,7 @@ import android.database.ContentObserver; import android.os.AsyncTask; import android.os.Bundle; import android.provider.ContactsContract; +import android.support.annotation.NonNull; import android.support.v7.app.ActionBar; import android.util.Log; 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.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicTheme; -import org.thoughtcrime.securesms.util.MemoryCleaner; import org.thoughtcrime.securesms.util.TextSecurePreferences; public class ConversationListActivity extends PassphraseRequiredActionBarActivity implements ConversationListFragment.ConversationSelectedListener - { +{ private final DynamicTheme dynamicTheme = new DynamicTheme (); private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); private ConversationListFragment fragment; - private MasterSecret masterSecret; private ContentObserver observer; + private MasterSecret masterSecret; @Override - public void onCreate(Bundle icicle) { + protected void onPreCreate() { dynamicTheme.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 - public void onPostCreate(Bundle bundle) { - super.onPostCreate(bundle); + protected void onCreate(Bundle icicle, @NonNull MasterSecret masterSecret) { + 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 @@ -84,19 +80,10 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit @Override public void onDestroy() { - Log.w("ConversationListActivity", "onDestroy..."); - MemoryCleaner.clean(masterSecret); if (observer != null) getContentResolver().unregisterContentObserver(observer); super.onDestroy(); } - @Override - public void onMasterSecretCleared() { -// this.fragment.setMasterSecret(null); - startActivity(new Intent(this, RoutingActivity.class)); - super.onMasterSecretCleared(); - } - @Override public boolean onPrepareOptionsMenu(Menu menu) { MenuInflater inflater = this.getMenuInflater(); @@ -106,13 +93,9 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit menu.findItem(R.id.menu_clear_passphrase).setVisible(!TextSecurePreferences.isPasswordDisabled(this)); - if (this.masterSecret != null) { - inflater.inflate(R.menu.conversation_list, menu); - MenuItem menuItem = menu.findItem(R.id.menu_search); - initializeSearch(menuItem); - } else { - inflater.inflate(R.menu.conversation_list_empty, menu); - } + inflater.inflate(R.menu.conversation_list, menu); + MenuItem menuItem = menu.findItem(R.id.menu_search); + initializeSearch(menuItem); super.onPrepareOptionsMenu(menu); return true; @@ -177,7 +160,6 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit private void createGroup() { Intent intent = new Intent(this, GroupCreateActivity.class); - intent.putExtra("master_secret", masterSecret); startActivity(intent); } @@ -185,7 +167,6 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit Intent intent = new Intent(this, ConversationActivity.class); intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients.getIds()); intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId); - intent.putExtra(ConversationActivity.MASTER_SECRET_EXTRA, masterSecret); intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, distributionType); startActivity(intent); @@ -193,7 +174,6 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit private void handleDisplaySettings() { Intent preferencesIntent = new Intent(this, ApplicationPreferencesActivity.class); - preferencesIntent.putExtra("master_secret", masterSecret); startActivity(preferencesIntent); } @@ -204,15 +184,11 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit } private void handleImportExport() { - final Intent intent = new Intent(this, ImportExportActivity.class); - intent.putExtra("master_secret", masterSecret); - startActivity(intent); + startActivity(new Intent(this, ImportExportActivity.class)); } private void handleMyIdentity() { - final Intent intent = new Intent(this, ViewLocalIdentityActivity.class); - intent.putExtra("master_secret", masterSecret); - startActivity(intent); + startActivity(new Intent(this, ViewLocalIdentityActivity.class)); } private void handleMarkAllRead() { @@ -237,8 +213,8 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit ConversationListActivity.this.runOnUiThread(new Runnable() { @Override public void run() { - ((ConversationListAdapter)fragment.getListAdapter()).notifyDataSetChanged(); - } + ((ConversationListAdapter)fragment.getListAdapter()).notifyDataSetChanged(); + } }); } }; @@ -246,13 +222,4 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, 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); - } } diff --git a/src/org/thoughtcrime/securesms/ConversationListFragment.java b/src/org/thoughtcrime/securesms/ConversationListFragment.java index 0cef89dea5..8e2d5c23ec 100644 --- a/src/org/thoughtcrime/securesms/ConversationListFragment.java +++ b/src/org/thoughtcrime/securesms/ConversationListFragment.java @@ -61,13 +61,18 @@ public class ConversationListFragment extends ListFragment implements LoaderManager.LoaderCallbacks, ActionMode.Callback { - private ConversationSelectedListener listener; private MasterSecret masterSecret; private ActionMode actionMode; private ReminderView reminderView; private FloatingActionButton fab; private String queryFilter = ""; + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + masterSecret = getArguments().getParcelable("master_secret"); + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) { final View view = inflater.inflate(R.layout.conversation_list_fragment, container, false); @@ -76,12 +81,6 @@ public class ConversationListFragment extends ListFragment return view; } - @Override - public void onDestroyView() { - super.onDestroyView(); - getListView().setAdapter(null); - } - @Override public void onActivityCreated(Bundle bundle) { super.onActivityCreated(bundle); @@ -92,9 +91,7 @@ public class ConversationListFragment extends ListFragment fab.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - Intent intent = new Intent(getActivity(), NewConversationActivity.class); - intent.putExtra(NewConversationActivity.MASTER_SECRET_EXTRA, masterSecret); - startActivity(intent); + startActivity(new Intent(getActivity(), NewConversationActivity.class)); } }); initializeListAdapter(); @@ -111,12 +108,6 @@ public class ConversationListFragment extends ListFragment ((ConversationListAdapter)getListAdapter()).notifyDataSetChanged(); } - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - this.listener = (ConversationSelectedListener)activity; - } - @Override public void onListItemClick(ListView l, View v, int position, long id) { 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) { this.queryFilter = query; getLoaderManager().restartLoader(0, null, this); @@ -250,7 +234,7 @@ public class ConversationListFragment extends ListFragment } private void handleCreateConversation(long threadId, Recipients recipients, int distributionType) { - listener.onCreateConversation(threadId, recipients, distributionType); + ((ConversationSelectedListener)getActivity()).onCreateConversation(threadId, recipients, distributionType); } @Override diff --git a/src/org/thoughtcrime/securesms/DatabaseMigrationActivity.java b/src/org/thoughtcrime/securesms/DatabaseMigrationActivity.java index 6b4fc7a6ac..02619cf860 100644 --- a/src/org/thoughtcrime/securesms/DatabaseMigrationActivity.java +++ b/src/org/thoughtcrime/securesms/DatabaseMigrationActivity.java @@ -10,12 +10,14 @@ import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; +import android.support.annotation.NonNull; import android.view.View; import android.widget.Button; import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.TextView; +import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.database.SmsMigrator.ProgressDescription; import org.thoughtcrime.securesms.service.ApplicationMigrationService; import org.thoughtcrime.securesms.service.ApplicationMigrationService.ImportState; @@ -37,8 +39,7 @@ public class DatabaseMigrationActivity extends PassphraseRequiredActionBarActivi private boolean isVisible = false; @Override - public void onCreate(Bundle bundle) { - super.onCreate(bundle); + protected void onCreate(Bundle bundle, @NonNull MasterSecret masterSecret) { setContentView(R.layout.database_migration_activity); initializeResources(); diff --git a/src/org/thoughtcrime/securesms/DeviceProvisioningActivity.java b/src/org/thoughtcrime/securesms/DeviceProvisioningActivity.java index 7f2c310e46..2749ad5421 100644 --- a/src/org/thoughtcrime/securesms/DeviceProvisioningActivity.java +++ b/src/org/thoughtcrime/securesms/DeviceProvisioningActivity.java @@ -5,6 +5,7 @@ import android.content.DialogInterface; import android.content.DialogInterface.OnDismissListener; import android.net.Uri; import android.os.Bundle; +import android.support.annotation.NonNull; import android.text.SpannableString; import android.text.SpannableStringBuilder; import android.util.Log; @@ -40,9 +41,13 @@ public class DeviceProvisioningActivity extends PassphraseRequiredActionBarActiv private MasterSecret masterSecret; @Override - public void onCreate(Bundle bundle) { + protected void onPreCreate() { supportRequestWindowFeature(Window.FEATURE_NO_TITLE); - super.onCreate(bundle); + } + + @Override + protected void onCreate(Bundle bundle, @NonNull MasterSecret masterSecret) { + this.masterSecret = masterSecret; getSupportActionBar().hide(); initializeResources(); @@ -80,11 +85,6 @@ public class DeviceProvisioningActivity extends PassphraseRequiredActionBarActiv .show(); } - @Override - public void onNewMasterSecret(MasterSecret masterSecret) { - this.masterSecret = masterSecret; - } - private void initializeResources() { this.uri = getIntent().getData(); } diff --git a/src/org/thoughtcrime/securesms/GroupCreateActivity.java b/src/org/thoughtcrime/securesms/GroupCreateActivity.java index a8d8f46ad7..c12219d4de 100644 --- a/src/org/thoughtcrime/securesms/GroupCreateActivity.java +++ b/src/org/thoughtcrime/securesms/GroupCreateActivity.java @@ -25,6 +25,7 @@ import android.graphics.BitmapFactory; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; +import android.support.annotation.NonNull; import android.text.Editable; import android.text.TextWatcher; import android.util.Log; @@ -51,7 +52,6 @@ import org.thoughtcrime.securesms.database.ThreadDatabase; import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientFactory; -import org.thoughtcrime.securesms.recipients.RecipientFormattingException; import org.thoughtcrime.securesms.recipients.Recipients; import org.thoughtcrime.securesms.sms.MessageSender; import org.thoughtcrime.securesms.util.BitmapDecodingException; @@ -70,7 +70,6 @@ import org.whispersystems.textsecure.api.util.InvalidNumberException; import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; 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_THREAD_EXTRA = "group_thread"; - public static final String MASTER_SECRET_EXTRA = "master_secret"; private final DynamicTheme dynamicTheme = new DynamicTheme(); private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); @@ -117,20 +115,24 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity { private String existingTitle = null; private Bitmap existingAvatarBmp = null; - private MasterSecret masterSecret; - private Bitmap avatarBmp; + private MasterSecret masterSecret; + private Bitmap avatarBmp; private Set selectedContacts; @Override - public void onCreate(Bundle state) { + protected void onPreCreate() { dynamicTheme.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); getSupportActionBar().setDisplayHomeAsUpEnabled(true); - selectedContacts = new HashSet(); + selectedContacts = new HashSet<>(); initializeResources(); } @@ -234,8 +236,6 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity { } } - masterSecret = getIntent().getParcelableExtra(MASTER_SECRET_EXTRA); - lv = (ListView) findViewById(R.id.selected_contacts_list); avatar = (ImageView) findViewById(R.id.avatar); groupName = (EditText) findViewById(R.id.group_name); @@ -531,7 +531,6 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity { protected void onPostExecute(Long resultThread) { if (resultThread > -1) { 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.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT); @@ -632,7 +631,6 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity { final Recipients recipients = groupInfo.second; if (threadId > -1) { 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.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT); intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients.getIds()); diff --git a/src/org/thoughtcrime/securesms/ImageMediaAdapter.java b/src/org/thoughtcrime/securesms/ImageMediaAdapter.java index 9e428b99d6..2670172e4d 100644 --- a/src/org/thoughtcrime/securesms/ImageMediaAdapter.java +++ b/src/org/thoughtcrime/securesms/ImageMediaAdapter.java @@ -114,7 +114,6 @@ public class ImageMediaAdapter extends CursorRecyclerViewAdapter { @Override public void onClick(View v) { Intent intent = new Intent(getContext(), MediaPreviewActivity.class); - intent.putExtra(MediaPreviewActivity.MASTER_SECRET_EXTRA, masterSecret); intent.putExtra(MediaPreviewActivity.DATE_EXTRA, record.getDate()); if (!TextUtils.isEmpty(record.getAddress())) { diff --git a/src/org/thoughtcrime/securesms/ImportExportActivity.java b/src/org/thoughtcrime/securesms/ImportExportActivity.java index 7f4fee383a..498fd0372c 100644 --- a/src/org/thoughtcrime/securesms/ImportExportActivity.java +++ b/src/org/thoughtcrime/securesms/ImportExportActivity.java @@ -1,6 +1,7 @@ package org.thoughtcrime.securesms; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentStatePagerAdapter; @@ -15,16 +16,20 @@ import org.thoughtcrime.securesms.util.DynamicTheme; public class ImportExportActivity extends PassphraseRequiredActionBarActivity { + private MasterSecret masterSecret; private TabPagerAdapter tabPagerAdapter; - private ViewPager viewPager; - private MasterSecret masterSecret; + private ViewPager viewPager; private DynamicTheme dynamicTheme = new DynamicTheme(); @Override - public void onCreate(Bundle savedInstanceState) { + protected void onPreCreate() { dynamicTheme.onCreate(this); - super.onCreate(savedInstanceState); + } + + @Override + protected void onCreate(Bundle savedInstanceState, @NonNull MasterSecret masterSecret) { + this.masterSecret = masterSecret; setContentView(R.layout.import_export_activity); getSupportActionBar().setDisplayHomeAsUpEnabled(true); @@ -51,7 +56,6 @@ public class ImportExportActivity extends PassphraseRequiredActionBarActivity { } private void initializeResources() { - this.masterSecret = getIntent().getParcelableExtra("master_secret"); this.viewPager = (ViewPager) findViewById(R.id.import_export_pager); this.tabPagerAdapter = new TabPagerAdapter(getSupportFragmentManager()); @@ -116,4 +120,4 @@ public class ImportExportActivity extends PassphraseRequiredActionBarActivity { } } -} \ No newline at end of file +} diff --git a/src/org/thoughtcrime/securesms/ImportFragment.java b/src/org/thoughtcrime/securesms/ImportFragment.java index 08ada1c12c..3b57376b3f 100644 --- a/src/org/thoughtcrime/securesms/ImportFragment.java +++ b/src/org/thoughtcrime/securesms/ImportFragment.java @@ -95,10 +95,8 @@ public class ImportFragment extends Fragment { getActivity().startService(intent); Intent nextIntent = new Intent(getActivity(), ConversationListActivity.class); - intent.putExtra("master_secret", masterSecret); Intent activityIntent = new Intent(getActivity(), DatabaseMigrationActivity.class); - activityIntent.putExtra("master_secret", masterSecret); activityIntent.putExtra("next_intent", nextIntent); getActivity().startActivity(activityIntent); } diff --git a/src/org/thoughtcrime/securesms/KeyScanningActivity.java b/src/org/thoughtcrime/securesms/KeyScanningActivity.java index 7e39a5b9a9..8e745b8fe2 100644 --- a/src/org/thoughtcrime/securesms/KeyScanningActivity.java +++ b/src/org/thoughtcrime/securesms/KeyScanningActivity.java @@ -26,6 +26,7 @@ import android.widget.Toast; import com.google.zxing.integration.android.IntentIntegrator; import com.google.zxing.integration.android.IntentResult; +import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.Dialogs; import org.thoughtcrime.securesms.util.DynamicLanguage; @@ -43,10 +44,9 @@ public abstract class KeyScanningActivity extends PassphraseRequiredActionBarAct private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); @Override - protected void onCreate(Bundle bundle) { + protected void onPreCreate() { dynamicTheme.onCreate(this); dynamicLanguage.onCreate(this); - super.onCreate(bundle); } @Override diff --git a/src/org/thoughtcrime/securesms/MasterSecretListener.java b/src/org/thoughtcrime/securesms/MasterSecretListener.java new file mode 100644 index 0000000000..66070e6b26 --- /dev/null +++ b/src/org/thoughtcrime/securesms/MasterSecretListener.java @@ -0,0 +1,5 @@ +package org.thoughtcrime.securesms; + +public interface MasterSecretListener { + void onMasterSecretCleared(); +} diff --git a/src/org/thoughtcrime/securesms/MediaOverviewActivity.java b/src/org/thoughtcrime/securesms/MediaOverviewActivity.java index 63b630bcb9..57956c8c8a 100644 --- a/src/org/thoughtcrime/securesms/MediaOverviewActivity.java +++ b/src/org/thoughtcrime/securesms/MediaOverviewActivity.java @@ -23,6 +23,7 @@ import android.database.Cursor; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.v4.app.LoaderManager; import android.support.v4.content.Loader; import android.support.v7.widget.GridLayoutManager; @@ -48,9 +49,8 @@ import org.thoughtcrime.securesms.util.DynamicLanguage; public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity implements LoaderManager.LoaderCallbacks { private final static String TAG = MediaOverviewActivity.class.getSimpleName(); - public final static String MASTER_SECRET_EXTRA = "master_secret"; - public final static String RECIPIENT_EXTRA = "recipient"; - public final static String THREAD_ID_EXTRA = "thread_id"; + public static final String RECIPIENT_EXTRA = "recipient"; + public static final String THREAD_ID_EXTRA = "thread_id"; private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); @@ -63,11 +63,14 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity i private long threadId; @Override - protected void onCreate(Bundle bundle) { + protected void onPreCreate() { this.setTheme(R.style.TextSecure_DarkTheme); dynamicLanguage.onCreate(this); + } - super.onCreate(bundle); + @Override + protected void onCreate(Bundle bundle, @NonNull MasterSecret masterSecret) { + this.masterSecret = masterSecret; setFullscreenIfPossible(); getSupportActionBar().setDisplayHomeAsUpEnabled(true); @@ -112,8 +115,7 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity i } 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 ); gridView = (RecyclerView) findViewById(R.id.media_grid); diff --git a/src/org/thoughtcrime/securesms/MediaPreviewActivity.java b/src/org/thoughtcrime/securesms/MediaPreviewActivity.java index 5fc4006bcf..09198f5771 100644 --- a/src/org/thoughtcrime/securesms/MediaPreviewActivity.java +++ b/src/org/thoughtcrime/securesms/MediaPreviewActivity.java @@ -20,26 +20,24 @@ import android.annotation.TargetApi; import android.content.DialogInterface; import android.content.Intent; import android.graphics.Bitmap; -import android.graphics.BitmapFactory; import android.net.Uri; import android.opengl.GLES20; import android.os.AsyncTask; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; import android.os.Bundle; +import android.support.annotation.NonNull; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; -import android.view.Window; import android.view.WindowManager; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import org.thoughtcrime.securesms.crypto.MasterSecret; -import org.thoughtcrime.securesms.mms.PartAuthority; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient.RecipientModifiedListener; import org.thoughtcrime.securesms.recipients.RecipientFactory; @@ -60,9 +58,8 @@ import uk.co.senab.photoview.PhotoViewAttacher; public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity implements RecipientModifiedListener { private final static String TAG = MediaPreviewActivity.class.getSimpleName(); - public final static String MASTER_SECRET_EXTRA = "master_secret"; - public final static String RECIPIENT_EXTRA = "recipient"; - public final static String DATE_EXTRA = "date"; + public static final String RECIPIENT_EXTRA = "recipient"; + public static final String DATE_EXTRA = "date"; private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); @@ -79,12 +76,11 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im private long date; @Override - protected void onCreate(Bundle bundle) { + protected void onCreate(Bundle bundle, @NonNull MasterSecret masterSecret) { + this.masterSecret = masterSecret; this.setTheme(R.style.TextSecure_DarkTheme); dynamicLanguage.onCreate(this); - super.onCreate(bundle); - setFullscreenIfPossible(); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); @@ -157,7 +153,6 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im private void initializeResources() { final long recipientId = getIntent().getLongExtra(RECIPIENT_EXTRA, -1); - masterSecret = getIntent().getParcelableExtra(MASTER_SECRET_EXTRA); mediaUri = getIntent().getData(); mediaType = getIntent().getType(); date = getIntent().getLongExtra(DATE_EXTRA, -1); diff --git a/src/org/thoughtcrime/securesms/MessageDetailsActivity.java b/src/org/thoughtcrime/securesms/MessageDetailsActivity.java index 275f1e4823..3748028ea4 100644 --- a/src/org/thoughtcrime/securesms/MessageDetailsActivity.java +++ b/src/org/thoughtcrime/securesms/MessageDetailsActivity.java @@ -20,6 +20,7 @@ import android.content.Context; import android.database.Cursor; import android.os.AsyncTask; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.support.v4.content.Loader; import android.util.Log; @@ -83,10 +84,13 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity private DynamicLanguage dynamicLanguage = new DynamicLanguage(); @Override - public void onCreate(Bundle bundle) { + protected void onPreCreate() { dynamicTheme.onCreate(this); dynamicLanguage.onCreate(this); - super.onCreate(bundle); + } + + @Override + public void onCreate(Bundle bundle, @NonNull MasterSecret masterSecret) { setContentView(R.layout.message_details_activity); initializeResources(); diff --git a/src/org/thoughtcrime/securesms/NewConversationActivity.java b/src/org/thoughtcrime/securesms/NewConversationActivity.java index 660de95696..9b7e707f17 100644 --- a/src/org/thoughtcrime/securesms/NewConversationActivity.java +++ b/src/org/thoughtcrime/securesms/NewConversationActivity.java @@ -18,6 +18,7 @@ package org.thoughtcrime.securesms; import android.content.Intent; import android.os.Bundle; +import android.support.annotation.NonNull; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; @@ -50,21 +51,21 @@ import static org.thoughtcrime.securesms.contacts.ContactAccessor.ContactData; * */ public class NewConversationActivity extends PassphraseRequiredActionBarActivity { - private final static String TAG = "ContactSelectActivity"; - public final static String MASTER_SECRET_EXTRA = "master_secret"; + private static final String TAG = NewConversationActivity.class.getSimpleName(); private final DynamicTheme dynamicTheme = new DynamicTheme (); private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); - private MasterSecret masterSecret; private PushContactSelectionListFragment contactsFragment; @Override - protected void onCreate(Bundle icicle) { + protected void onPreCreate() { dynamicTheme.onCreate(this); dynamicLanguage.onCreate(this); - super.onCreate(icicle); + } + @Override + protected void onCreate(Bundle icicle, @NonNull MasterSecret masterSecret) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); setContentView(R.layout.new_conversation_activity); @@ -77,7 +78,6 @@ public class NewConversationActivity extends PassphraseRequiredActionBarActivity dynamicTheme.onResume(this); dynamicLanguage.onResume(this); getSupportActionBar().setTitle(R.string.AndroidManifest__select_contacts); - masterSecret = getIntent().getParcelableExtra(MASTER_SECRET_EXTRA); } @Override @@ -116,7 +116,7 @@ public class NewConversationActivity extends PassphraseRequiredActionBarActivity final Intent resultIntent = getIntent(); final List selectedContacts = contactsFragment.getSelectedContacts(); if (selectedContacts != null) { - resultIntent.putParcelableArrayListExtra("contacts", new ArrayList(contactsFragment.getSelectedContacts())); + resultIntent.putParcelableArrayListExtra("contacts", new ArrayList<>(contactsFragment.getSelectedContacts())); } setResult(RESULT_OK, resultIntent); finish(); @@ -149,7 +149,6 @@ public class NewConversationActivity extends PassphraseRequiredActionBarActivity if (recipients != null) { Intent intent = new Intent(this, ConversationActivity.class); 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_AUDIO_EXTRA, getIntent().getParcelableExtra(ConversationActivity.DRAFT_AUDIO_EXTRA)); intent.putExtra(ConversationActivity.DRAFT_VIDEO_EXTRA, getIntent().getParcelableExtra(ConversationActivity.DRAFT_VIDEO_EXTRA)); diff --git a/src/org/thoughtcrime/securesms/PassphraseActivity.java b/src/org/thoughtcrime/securesms/PassphraseActivity.java index 17ea0e61eb..11935f8fe0 100644 --- a/src/org/thoughtcrime/securesms/PassphraseActivity.java +++ b/src/org/thoughtcrime/securesms/PassphraseActivity.java @@ -21,11 +21,9 @@ import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; -import android.support.v7.app.ActionBarActivity; import org.thoughtcrime.securesms.crypto.MasterSecret; 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) { this.masterSecret = masterSecret; Intent bindIntent = new Intent(this, KeyCachingService.class); + startService(bindIntent); bindService(bindIntent, serviceConnection, Context.BIND_AUTO_CREATE); } - protected MasterSecret getMasterSecret() { - return masterSecret; - } - protected abstract void cleanup(); private ServiceConnection serviceConnection = new ServiceConnection() { @@ -58,11 +53,12 @@ public abstract class PassphraseActivity extends BaseActionBarActivity { PassphraseActivity.this.unbindService(PassphraseActivity.this.serviceConnection); - MemoryCleaner.clean(masterSecret); + masterSecret = null; cleanup(); - PassphraseActivity.this.setResult(RESULT_OK); - PassphraseActivity.this.finish(); + Intent nextIntent = getIntent().getParcelableExtra("next_intent"); + if (nextIntent != null) startActivity(nextIntent); + finish(); } @Override diff --git a/src/org/thoughtcrime/securesms/PassphraseChangeActivity.java b/src/org/thoughtcrime/securesms/PassphraseChangeActivity.java index e9c9f6349d..28652be734 100644 --- a/src/org/thoughtcrime/securesms/PassphraseChangeActivity.java +++ b/src/org/thoughtcrime/securesms/PassphraseChangeActivity.java @@ -28,7 +28,6 @@ import android.widget.Toast; import org.thoughtcrime.securesms.crypto.InvalidPassphraseException; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecretUtil; -import org.thoughtcrime.securesms.util.MemoryCleaner; import org.thoughtcrime.securesms.util.TextSecurePreferences; /** @@ -104,10 +103,6 @@ public class PassphraseChangeActivity extends PassphraseActivity { MasterSecret masterSecret = MasterSecretUtil.changeMasterSecretPassphrase(this, original, passphrase); TextSecurePreferences.setPasswordDisabled(this, false); - MemoryCleaner.clean(original); - MemoryCleaner.clean(passphrase); - MemoryCleaner.clean(passphraseRepeat); - setMasterSecret(masterSecret); } } catch (InvalidPassphraseException e) { diff --git a/src/org/thoughtcrime/securesms/PassphraseCreateActivity.java b/src/org/thoughtcrime/securesms/PassphraseCreateActivity.java index b0f5e5fb67..c3fb1847ef 100644 --- a/src/org/thoughtcrime/securesms/PassphraseCreateActivity.java +++ b/src/org/thoughtcrime/securesms/PassphraseCreateActivity.java @@ -23,7 +23,6 @@ import android.support.v7.app.ActionBar; import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecretUtil; -import org.thoughtcrime.securesms.util.MemoryCleaner; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.VersionTracker; @@ -66,8 +65,6 @@ public class PassphraseCreateActivity extends PassphraseActivity { masterSecret = MasterSecretUtil.generateMasterSecret(PassphraseCreateActivity.this, passphrase); - MemoryCleaner.clean(passphrase); - MasterSecretUtil.generateAsymmetricMasterSecret(PassphraseCreateActivity.this, masterSecret); IdentityKeyUtil.generateIdentityKeys(PassphraseCreateActivity.this, masterSecret); VersionTracker.updateLastSeenVersion(PassphraseCreateActivity.this); diff --git a/src/org/thoughtcrime/securesms/PassphrasePromptActivity.java b/src/org/thoughtcrime/securesms/PassphrasePromptActivity.java index 984172e654..dd4d1eff29 100644 --- a/src/org/thoughtcrime/securesms/PassphrasePromptActivity.java +++ b/src/org/thoughtcrime/securesms/PassphrasePromptActivity.java @@ -43,7 +43,6 @@ import android.widget.Toast; import org.thoughtcrime.securesms.crypto.InvalidPassphraseException; import org.thoughtcrime.securesms.crypto.MasterSecretUtil; import org.thoughtcrime.securesms.util.DynamicLanguage; -import org.thoughtcrime.securesms.util.MemoryCleaner; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.util.Util; @@ -73,6 +72,12 @@ public class PassphrasePromptActivity extends PassphraseActivity { dynamicLanguage.onResume(this); } + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + setIntent(intent); + } + @Override public boolean onPrepareOptionsMenu(Menu menu) { MenuInflater inflater = this.getMenuInflater(); @@ -102,9 +107,8 @@ public class PassphrasePromptActivity extends PassphraseActivity { try { Editable text = passphraseText.getText(); String passphrase = (text == null ? "" : text.toString()); - MasterSecret masterSecret = MasterSecretUtil.getMasterSecret(PassphrasePromptActivity.this, passphrase); + MasterSecret masterSecret = MasterSecretUtil.getMasterSecret(this, passphrase); - MemoryCleaner.clean(passphrase); setMasterSecret(masterSecret); } catch (InvalidPassphraseException ipe) { passphraseText.setText(""); diff --git a/src/org/thoughtcrime/securesms/PassphraseRequiredActionBarActivity.java b/src/org/thoughtcrime/securesms/PassphraseRequiredActionBarActivity.java index d94092bf91..ab7835f4c7 100644 --- a/src/org/thoughtcrime/securesms/PassphraseRequiredActionBarActivity.java +++ b/src/org/thoughtcrime/securesms/PassphraseRequiredActionBarActivity.java @@ -1,42 +1,186 @@ 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.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.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 - protected void onCreate(Bundle savedInstanceState) { + protected final void onCreate(Bundle savedInstanceState) { + onPreCreate(); + final MasterSecret masterSecret = KeyCachingService.getMasterSecret(this); + routeApplicationState(masterSecret); super.onCreate(savedInstanceState); - delegate.onCreate(this); + if (!isFinishing()) { + initializeClearKeyReceiver(); + onCreate(savedInstanceState, masterSecret); + } } + protected void onPreCreate() {} + protected void onCreate(Bundle savedInstanceState, @NonNull MasterSecret masterSecret) {} + @Override protected void onResume() { super.onResume(); - delegate.onResume(this); + initializeScreenshotSecurity(); + KeyCachingService.registerPassphraseActivityStarted(this); + MessageRetrievalService.registerActivityStarted(this); + isVisible = true; } @Override protected void onPause() { super.onPause(); - delegate.onPause(this); + KeyCachingService.registerPassphraseActivityStopped(this); + MessageRetrievalService.registerActivityStopped(this); + isVisible = false; } @Override protected void onDestroy() { super.onDestroy(); - delegate.onDestroy(this); + removeClearKeyReceiver(this); } @Override public void onMasterSecretCleared() { - finish(); + Log.w(TAG, "onMasterSecretCleared()"); + if (isVisible) routeApplicationState(null); + else finish(); } - @Override - public void onNewMasterSecret(MasterSecret masterSecret) {} + protected 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 + 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; + } + } } diff --git a/src/org/thoughtcrime/securesms/PassphraseRequiredActivity.java b/src/org/thoughtcrime/securesms/PassphraseRequiredActivity.java deleted file mode 100644 index 45fd862676..0000000000 --- a/src/org/thoughtcrime/securesms/PassphraseRequiredActivity.java +++ /dev/null @@ -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); -} diff --git a/src/org/thoughtcrime/securesms/PassphraseRequiredMixin.java b/src/org/thoughtcrime/securesms/PassphraseRequiredMixin.java deleted file mode 100644 index 80aa544305..0000000000 --- a/src/org/thoughtcrime/securesms/PassphraseRequiredMixin.java +++ /dev/null @@ -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 void onCreate(T activity) { - initializeClearKeyReceiver(activity); - } - - public void onResume(T activity) { - initializeScreenshotSecurity(activity); - initializeNewKeyReceiver(activity); - initializeFromMasterSecret(activity); - KeyCachingService.registerPassphraseActivityStarted(activity); - MessageRetrievalService.registerActivityStarted(activity); - } - - public void onPause(T activity) { - removeNewKeyReceiver(activity); - KeyCachingService.registerPassphraseActivityStopped(activity); - MessageRetrievalService.registerActivityStopped(activity); - } - - public void onDestroy(T activity) { - removeClearKeyReceiver(activity); - } - - private 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 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 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 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; - } - } -} diff --git a/src/org/thoughtcrime/securesms/PassphraseRequiredSherlockListActivity.java b/src/org/thoughtcrime/securesms/PassphraseRequiredSherlockListActivity.java deleted file mode 100644 index fcf0dd49d4..0000000000 --- a/src/org/thoughtcrime/securesms/PassphraseRequiredSherlockListActivity.java +++ /dev/null @@ -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) {} - -} diff --git a/src/org/thoughtcrime/securesms/PromptMmsActivity.java b/src/org/thoughtcrime/securesms/PromptMmsActivity.java index 2e495b9a74..a9286da08a 100644 --- a/src/org/thoughtcrime/securesms/PromptMmsActivity.java +++ b/src/org/thoughtcrime/securesms/PromptMmsActivity.java @@ -2,10 +2,12 @@ package org.thoughtcrime.securesms; import android.content.Intent; import android.os.Bundle; +import android.support.annotation.NonNull; import android.view.View; import android.widget.Button; import org.thoughtcrime.securesms.preferences.MmsPreferencesActivity; +import org.thoughtcrime.securesms.crypto.MasterSecret; public class PromptMmsActivity extends PassphraseRequiredActionBarActivity { @@ -13,9 +15,7 @@ public class PromptMmsActivity extends PassphraseRequiredActionBarActivity { private Button cancelButton; @Override - public void onCreate(Bundle bundle) { - super.onCreate(bundle); - + protected void onCreate(Bundle bundle, @NonNull MasterSecret masterSecret) { setContentView(R.layout.prompt_apn_activity); initializeResources(); } diff --git a/src/org/thoughtcrime/securesms/PushContactSelectionActivity.java b/src/org/thoughtcrime/securesms/PushContactSelectionActivity.java index 6075c04545..8a580a16c9 100644 --- a/src/org/thoughtcrime/securesms/PushContactSelectionActivity.java +++ b/src/org/thoughtcrime/securesms/PushContactSelectionActivity.java @@ -18,11 +18,13 @@ package org.thoughtcrime.securesms; import android.content.Intent; import android.os.Bundle; +import android.support.annotation.NonNull; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; +import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.util.DirectoryHelper; import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicTheme; @@ -50,11 +52,13 @@ public class PushContactSelectionActivity extends PassphraseRequiredActionBarAct private PushContactSelectionListFragment contactsFragment; @Override - protected void onCreate(Bundle icicle) { + protected void onPreCreate() { dynamicTheme.onCreate(this); dynamicLanguage.onCreate(this); - super.onCreate(icicle); + } + @Override + protected void onCreate(Bundle icicle, @NonNull MasterSecret masterSecret) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); setContentView(R.layout.push_contact_selection_activity); diff --git a/src/org/thoughtcrime/securesms/ReceiveKeyActivity.java b/src/org/thoughtcrime/securesms/ReceiveKeyActivity.java index 91f150ac32..419cd35ee5 100644 --- a/src/org/thoughtcrime/securesms/ReceiveKeyActivity.java +++ b/src/org/thoughtcrime/securesms/ReceiveKeyActivity.java @@ -21,6 +21,7 @@ import android.content.Context; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; +import android.support.annotation.NonNull; import android.text.SpannableString; import android.text.Spanned; 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.IncomingTextMessage; import org.thoughtcrime.securesms.util.Base64; -import org.thoughtcrime.securesms.util.MemoryCleaner; import org.whispersystems.libaxolotl.IdentityKey; import org.whispersystems.libaxolotl.InvalidKeyException; import org.whispersystems.libaxolotl.InvalidMessageException; @@ -60,7 +60,7 @@ import java.io.IOException; * @author Moxie Marlinspike */ -public class ReceiveKeyActivity extends BaseActivity { +public class ReceiveKeyActivity extends PassphraseRequiredActionBarActivity { private TextView descriptionText; @@ -76,8 +76,8 @@ public class ReceiveKeyActivity extends BaseActivity { private IdentityKey identityKey; @Override - protected void onCreate(Bundle state) { - super.onCreate(state); + protected void onCreate(Bundle state, @NonNull MasterSecret masterSecret) { + this.masterSecret = masterSecret; setContentView(R.layout.receive_key_activity); initializeResources(); @@ -91,12 +91,6 @@ public class ReceiveKeyActivity extends BaseActivity { initializeListeners(); } - @Override - protected void onDestroy() { - MemoryCleaner.clean(masterSecret); - super.onDestroy(); - } - private void initializeText() { 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)); @@ -105,7 +99,6 @@ public class ReceiveKeyActivity extends BaseActivity { public void onClick(View widget) { Intent intent = new Intent(ReceiveKeyActivity.this, VerifyIdentityActivity.class); intent.putExtra("recipient", recipient.getRecipientId()); - intent.putExtra("master_secret", masterSecret); intent.putExtra("remote_identity", new IdentityKeyParcelable(identityKey)); startActivity(intent); } @@ -137,7 +130,6 @@ public class ReceiveKeyActivity extends BaseActivity { this.recipient = RecipientFactory.getRecipientForId(this, getIntent().getLongExtra("recipient", -1), true); this.recipientDeviceId = getIntent().getIntExtra("recipient_device_id", -1); this.messageId = getIntent().getLongExtra("message_id", -1); - this.masterSecret = getIntent().getParcelableExtra("master_secret"); } private void initializeListeners() { diff --git a/src/org/thoughtcrime/securesms/RegistrationActivity.java b/src/org/thoughtcrime/securesms/RegistrationActivity.java index a99597f619..817a903fd3 100644 --- a/src/org/thoughtcrime/securesms/RegistrationActivity.java +++ b/src/org/thoughtcrime/securesms/RegistrationActivity.java @@ -25,9 +25,9 @@ import com.google.i18n.phonenumbers.NumberParseException; import com.google.i18n.phonenumbers.PhoneNumberUtil; import com.google.i18n.phonenumbers.Phonenumber; +import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.util.Dialogs; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.util.Util; import org.whispersystems.textsecure.api.util.PhoneNumberFormatter; @@ -284,7 +284,7 @@ public class RegistrationActivity extends BaseActionBarActivity { Intent nextIntent = getIntent().getParcelableExtra("next_intent"); if (nextIntent == null) { - nextIntent = new Intent(RegistrationActivity.this, RoutingActivity.class); + nextIntent = new Intent(RegistrationActivity.this, ConversationListActivity.class); } startActivity(nextIntent); diff --git a/src/org/thoughtcrime/securesms/RegistrationProgressActivity.java b/src/org/thoughtcrime/securesms/RegistrationProgressActivity.java index 7f15272f0e..c696b2c7cc 100644 --- a/src/org/thoughtcrime/securesms/RegistrationProgressActivity.java +++ b/src/org/thoughtcrime/securesms/RegistrationProgressActivity.java @@ -33,6 +33,7 @@ import android.widget.Toast; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.push.TextSecureCommunicationFactory; +import org.thoughtcrime.securesms.service.KeyCachingService; import org.thoughtcrime.securesms.service.RegistrationService; import org.thoughtcrime.securesms.util.Dialogs; import org.thoughtcrime.securesms.util.TextSecurePreferences; @@ -330,7 +331,7 @@ public class RegistrationProgressActivity extends BaseActionBarActivity { } shutdownService(); - startActivity(new Intent(this, RoutingActivity.class)); + startActivity(new Intent(this, ConversationListActivity.class)); finish(); } diff --git a/src/org/thoughtcrime/securesms/RoutingActivity.java b/src/org/thoughtcrime/securesms/RoutingActivity.java deleted file mode 100644 index a4f09ed5e8..0000000000 --- a/src/org/thoughtcrime/securesms/RoutingActivity.java +++ /dev/null @@ -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; - } - } - -} diff --git a/src/org/thoughtcrime/securesms/ShareActivity.java b/src/org/thoughtcrime/securesms/ShareActivity.java index 81ae9e5bb3..360f5650ef 100644 --- a/src/org/thoughtcrime/securesms/ShareActivity.java +++ b/src/org/thoughtcrime/securesms/ShareActivity.java @@ -20,15 +20,18 @@ package org.thoughtcrime.securesms; import android.content.Intent; import android.net.Uri; import android.os.Bundle; +import android.support.annotation.NonNull; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; +import android.webkit.MimeTypeMap; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.recipients.Recipients; import org.thoughtcrime.securesms.util.DynamicLanguage; 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 @@ -37,23 +40,20 @@ import org.thoughtcrime.securesms.util.MemoryCleaner; */ public class ShareActivity extends PassphraseRequiredActionBarActivity implements ShareFragment.ConversationSelectedListener - { - public final static String MASTER_SECRET_EXTRA = "master_secret"; - +{ private final DynamicTheme dynamicTheme = new DynamicTheme (); private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); - private ShareFragment fragment; - private MasterSecret masterSecret; - @Override - public void onCreate(Bundle icicle) { + protected void onPreCreate() { dynamicTheme.onCreate(this); dynamicLanguage.onCreate(this); - super.onCreate(icicle); + } + @Override + protected void onCreate(Bundle icicle, @NonNull MasterSecret masterSecret) { setContentView(R.layout.share_activity); - initializeResources(); + initFragment(R.id.drawer_layout, new ShareFragment(), masterSecret); } @Override @@ -76,12 +76,6 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity if (!isFinishing()) finish(); } - @Override - public void onDestroy() { - MemoryCleaner.clean(masterSecret); - super.onDestroy(); - } - @Override public boolean onPrepareOptionsMenu(Menu menu) { MenuInflater inflater = this.getMenuInflater(); @@ -102,12 +96,6 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity return false; } - @Override - public void onMasterSecretCleared() { - startActivity(new Intent(this, RoutingActivity.class)); - super.onMasterSecretCleared(); - } - private void handleNewConversation() { Intent intent = getBaseShareIntent(NewConversationActivity.class); startActivity(intent); @@ -127,29 +115,32 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity 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) { - final Intent intent = new Intent(this, target); - final Intent originalIntent = getIntent(); - final String draftText = originalIntent.getStringExtra(ConversationActivity.DRAFT_TEXT_EXTRA); - final Uri draftImage = originalIntent.getParcelableExtra(ConversationActivity.DRAFT_IMAGE_EXTRA); - final Uri draftAudio = originalIntent.getParcelableExtra(ConversationActivity.DRAFT_AUDIO_EXTRA); - final Uri draftVideo = originalIntent.getParcelableExtra(ConversationActivity.DRAFT_VIDEO_EXTRA); + final Intent intent = new Intent(this, target); + final String textExtra = getIntent().getStringExtra(ConversationActivity.DRAFT_TEXT_EXTRA); + final Uri streamExtra = getIntent().getParcelableExtra(Intent.EXTRA_STREAM); + final String type = streamExtra != null ? getMimeType(streamExtra) : getIntent().getType(); - intent.putExtra(ConversationActivity.DRAFT_TEXT_EXTRA, draftText); - intent.putExtra(ConversationActivity.DRAFT_IMAGE_EXTRA, draftImage); - intent.putExtra(ConversationActivity.DRAFT_AUDIO_EXTRA, draftAudio); - intent.putExtra(ConversationActivity.DRAFT_VIDEO_EXTRA, draftVideo); - intent.putExtra(NewConversationActivity.MASTER_SECRET_EXTRA, masterSecret); + if (ContentType.isImageType(type)) { + intent.putExtra(ConversationActivity.DRAFT_IMAGE_EXTRA, streamExtra); + } else if (ContentType.isAudioType(type)) { + intent.putExtra(ConversationActivity.DRAFT_AUDIO_EXTRA, streamExtra); + } else if (ContentType.isVideoType(type)) { + intent.putExtra(ConversationActivity.DRAFT_VIDEO_EXTRA, streamExtra); + } + intent.putExtra(ConversationActivity.DRAFT_TEXT_EXTRA, textExtra); 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; + } +} \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/ShareFragment.java b/src/org/thoughtcrime/securesms/ShareFragment.java index d537b6eecd..0577077dfa 100644 --- a/src/org/thoughtcrime/securesms/ShareFragment.java +++ b/src/org/thoughtcrime/securesms/ShareFragment.java @@ -43,6 +43,12 @@ public class ShareFragment extends ListFragment implements LoaderManager.LoaderC private ConversationSelectedListener listener; private MasterSecret masterSecret; + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + masterSecret = getArguments().getParcelable("master_secret"); + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) { 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() { this.setListAdapter(new ShareListAdapter(getActivity(), null, masterSecret)); getListView().setRecyclerListener((ShareListAdapter) getListAdapter()); diff --git a/src/org/thoughtcrime/securesms/SmsSendtoActivity.java b/src/org/thoughtcrime/securesms/SmsSendtoActivity.java new file mode 100644 index 0000000000..0040e4098f --- /dev/null +++ b/src/org/thoughtcrime/securesms/SmsSendtoActivity.java @@ -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; + } +} diff --git a/src/org/thoughtcrime/securesms/VerifyIdentityActivity.java b/src/org/thoughtcrime/securesms/VerifyIdentityActivity.java index 432ba8a561..fcf5536b85 100644 --- a/src/org/thoughtcrime/securesms/VerifyIdentityActivity.java +++ b/src/org/thoughtcrime/securesms/VerifyIdentityActivity.java @@ -18,6 +18,7 @@ package org.thoughtcrime.securesms; import android.os.Bundle; +import android.support.annotation.NonNull; import android.widget.TextView; import android.widget.Toast; @@ -29,7 +30,6 @@ import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientFactory; import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicTheme; -import org.thoughtcrime.securesms.util.MemoryCleaner; import org.whispersystems.libaxolotl.AxolotlAddress; import org.whispersystems.libaxolotl.IdentityKey; import org.whispersystems.libaxolotl.state.SessionRecord; @@ -53,10 +53,14 @@ public class VerifyIdentityActivity extends KeyScanningActivity { private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); @Override - public void onCreate(Bundle state) { + protected void onPreCreate() { dynamicTheme.onCreate(this); dynamicLanguage.onCreate(this); - super.onCreate(state); + } + + @Override + protected void onCreate(Bundle state, @NonNull MasterSecret masterSecret) { + this.masterSecret = masterSecret; getSupportActionBar().setDisplayHomeAsUpEnabled(true); 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() { if (!IdentityKeyUtil.hasIdentityKey(this)) { 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.remoteIdentityFingerprint = (TextView)findViewById(R.id.friend_reads); this.recipient = RecipientFactory.getRecipientForId(this, this.getIntent().getLongExtra("recipient", -1), true); - this.masterSecret = this.getIntent().getParcelableExtra("master_secret"); } @Override diff --git a/src/org/thoughtcrime/securesms/ViewIdentityActivity.java b/src/org/thoughtcrime/securesms/ViewIdentityActivity.java index 97853ed0cf..aae6f223d4 100644 --- a/src/org/thoughtcrime/securesms/ViewIdentityActivity.java +++ b/src/org/thoughtcrime/securesms/ViewIdentityActivity.java @@ -17,8 +17,10 @@ package org.thoughtcrime.securesms; import android.os.Bundle; +import android.support.annotation.NonNull; import android.widget.TextView; +import org.thoughtcrime.securesms.crypto.MasterSecret; import org.whispersystems.libaxolotl.IdentityKey; import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable; @@ -36,8 +38,7 @@ public class ViewIdentityActivity extends KeyScanningActivity { private IdentityKey identityKey; @Override - public void onCreate(Bundle state) { - super.onCreate(state); + protected void onCreate(Bundle state, @NonNull MasterSecret masterSecret) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); setContentView(R.layout.view_identity_activity); diff --git a/src/org/thoughtcrime/securesms/ViewLocalIdentityActivity.java b/src/org/thoughtcrime/securesms/ViewLocalIdentityActivity.java index 15faa29cb7..d915b11eb9 100644 --- a/src/org/thoughtcrime/securesms/ViewLocalIdentityActivity.java +++ b/src/org/thoughtcrime/securesms/ViewLocalIdentityActivity.java @@ -18,13 +18,14 @@ package org.thoughtcrime.securesms; import android.os.Bundle; +import android.support.annotation.NonNull; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; -import android.widget.Toast; import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; 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. @@ -33,12 +34,13 @@ import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable; */ public class ViewLocalIdentityActivity extends ViewIdentityActivity { - public void onCreate(Bundle bundle) { + @Override + protected void onCreate(Bundle icicle, @NonNull MasterSecret masterSecret) { getIntent().putExtra(ViewIdentityActivity.IDENTITY_KEY, new IdentityKeyParcelable(IdentityKeyUtil.getIdentityKey(this))); getIntent().putExtra(ViewIdentityActivity.TITLE, getString(R.string.ViewIdentityActivity_my_identity_fingerprint)); - super.onCreate(bundle); + super.onCreate(icicle, masterSecret); } @Override diff --git a/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java b/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java index 27b4f083dd..aba03d401e 100644 --- a/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java +++ b/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java @@ -39,8 +39,8 @@ import android.text.TextUtils; import android.text.style.StyleSpan; import android.util.Log; +import org.thoughtcrime.securesms.ConversationActivity; import org.thoughtcrime.securesms.R; -import org.thoughtcrime.securesms.RoutingActivity; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.MmsSmsDatabase; @@ -84,7 +84,7 @@ public class MessageNotifier { if (visibleThread == threadId) { sendInThreadNotification(context); } else { - Intent intent = new Intent(context, RoutingActivity.class); + Intent intent = new Intent(context, ConversationActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); intent.putExtra("recipients", recipients.getIds()); intent.putExtra("thread_id", threadId); @@ -228,7 +228,7 @@ public class MessageNotifier { notificationState.getMessageCount())); builder.setContentText(String.format(context.getString(R.string.MessageNotifier_most_recent_from_s), 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.setNumber(notificationState.getMessageCount()); diff --git a/src/org/thoughtcrime/securesms/notifications/NotificationItem.java b/src/org/thoughtcrime/securesms/notifications/NotificationItem.java index 8ff45fcc84..4b1d6f378b 100644 --- a/src/org/thoughtcrime/securesms/notifications/NotificationItem.java +++ b/src/org/thoughtcrime/securesms/notifications/NotificationItem.java @@ -6,7 +6,7 @@ import android.content.Intent; import android.net.Uri; 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.Recipients; import org.thoughtcrime.securesms.util.Util; @@ -70,16 +70,12 @@ public class NotificationItem { } public PendingIntent getPendingIntent(Context context) { - Intent intent = new Intent(context, RoutingActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + Intent intent = new Intent(context, ConversationActivity.class); - if (recipients != null || threadRecipients != null) { - if (threadRecipients != null) intent.putExtra("recipients", threadRecipients.getIds()); - else intent.putExtra("recipients", recipients.getIds()); - - intent.putExtra("thread_id", threadId); - } + Recipients notifyRecipients = threadRecipients != null ? threadRecipients : recipients; + if (notifyRecipients != null) intent.putExtra("recipients", notifyRecipients.getIds()); + intent.putExtra("thread_id", threadId); intent.setData((Uri.parse("custom://"+System.currentTimeMillis()))); return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); diff --git a/src/org/thoughtcrime/securesms/preferences/AppProtectionPreferenceFragment.java b/src/org/thoughtcrime/securesms/preferences/AppProtectionPreferenceFragment.java index 736d1c7477..e332820965 100644 --- a/src/org/thoughtcrime/securesms/preferences/AppProtectionPreferenceFragment.java +++ b/src/org/thoughtcrime/securesms/preferences/AppProtectionPreferenceFragment.java @@ -27,6 +27,7 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences; import java.util.concurrent.TimeUnit; public class AppProtectionPreferenceFragment extends PreferenceFragment { + private MasterSecret masterSecret; private CheckBoxPreference disablePassphrase; @Override @@ -34,6 +35,7 @@ public class AppProtectionPreferenceFragment extends PreferenceFragment { super.onCreate(paramBundle); addPreferencesFromResource(R.xml.preferences_app_protection); + masterSecret = getArguments().getParcelable("master_secret"); disablePassphrase = (CheckBoxPreference) this.findPreference("pref_enable_passphrase_temporary"); this.findPreference(TextSecurePreferences.CHANGE_PASSPHRASE_PREF) @@ -126,12 +128,10 @@ public class AppProtectionPreferenceFragment extends PreferenceFragment { builder.setPositiveButton(R.string.ApplicationPreferencesActivity_disable, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - MasterSecret masterSecret = getActivity().getIntent().getParcelableExtra("master_secret"); MasterSecretUtil.changeMasterSecretPassphrase(getActivity(), masterSecret, MasterSecretUtil.UNENCRYPTED_PASSPHRASE); - TextSecurePreferences.setPasswordDisabled(getActivity(), true); ((CheckBoxPreference)preference).setChecked(false); diff --git a/src/org/thoughtcrime/securesms/preferences/MmsPreferencesActivity.java b/src/org/thoughtcrime/securesms/preferences/MmsPreferencesActivity.java index b51aa25baa..5ec64ee8d9 100644 --- a/src/org/thoughtcrime/securesms/preferences/MmsPreferencesActivity.java +++ b/src/org/thoughtcrime/securesms/preferences/MmsPreferencesActivity.java @@ -17,6 +17,7 @@ package org.thoughtcrime.securesms.preferences; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; 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.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicTheme; -import org.thoughtcrime.securesms.util.MemoryCleaner; public class MmsPreferencesActivity extends PassphraseRequiredActionBarActivity { - private MasterSecret masterSecret; - private final DynamicTheme dynamicTheme = new DynamicTheme(); private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); @Override - protected void onCreate(Bundle icicle) { + protected void onPreCreate() { dynamicTheme.onCreate(this); dynamicLanguage.onCreate(this); - super.onCreate(icicle); + } + @Override + protected void onCreate(Bundle icicle, @NonNull MasterSecret masterSecret) { this.getSupportActionBar().setDisplayHomeAsUpEnabled(true); - masterSecret = getIntent().getParcelableExtra("master_secret"); - Fragment fragment = new MmsPreferencesFragment(); FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); @@ -60,13 +58,6 @@ public class MmsPreferencesActivity extends PassphraseRequiredActionBarActivity dynamicLanguage.onResume(this); } - @Override - public void onDestroy() { - MemoryCleaner.clean(masterSecret); - MemoryCleaner.clean((MasterSecret) getIntent().getParcelableExtra("master_secret")); - super.onDestroy(); - } - @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { diff --git a/src/org/thoughtcrime/securesms/service/ApplicationMigrationService.java b/src/org/thoughtcrime/securesms/service/ApplicationMigrationService.java index 3b1ada766e..d0bd5c253a 100644 --- a/src/org/thoughtcrime/securesms/service/ApplicationMigrationService.java +++ b/src/org/thoughtcrime/securesms/service/ApplicationMigrationService.java @@ -17,8 +17,8 @@ import android.os.PowerManager.WakeLock; import android.support.v4.app.NotificationCompat; import android.util.Log; +import org.thoughtcrime.securesms.ConversationListActivity; import org.thoughtcrime.securesms.R; -import org.thoughtcrime.securesms.RoutingActivity; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.database.SmsMigrator; import org.thoughtcrime.securesms.database.SmsMigrator.ProgressDescription; @@ -28,8 +28,8 @@ import java.util.concurrent.Executors; public class ApplicationMigrationService extends Service 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 COMPLETED_ACTION = "org.thoughtcrime.securesms.ApplicationMigrationService.COMPLETED"; 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.setOngoing(true); 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); startForeground(4242, builder.build()); @@ -141,7 +141,7 @@ public class ApplicationMigrationService extends Service public ImportRunnable(Intent intent) { this.masterSecret = intent.getParcelableExtra("master_secret"); - Log.w("ApplicationMigrationService", "Service got mastersecret: " + masterSecret); + Log.w(TAG, "Service got mastersecret: " + masterSecret); } @Override @@ -184,7 +184,7 @@ public class ApplicationMigrationService extends Service builder.setSmallIcon(R.drawable.icon_notification); builder.setContentTitle("Import 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.setDefaults(Notification.DEFAULT_VIBRATE); builder.setAutoCancel(true); diff --git a/src/org/thoughtcrime/securesms/service/KeyCachingService.java b/src/org/thoughtcrime/securesms/service/KeyCachingService.java index 0df6c42094..40e50aefb3 100644 --- a/src/org/thoughtcrime/securesms/service/KeyCachingService.java +++ b/src/org/thoughtcrime/securesms/service/KeyCachingService.java @@ -33,10 +33,10 @@ import android.util.Log; import android.widget.RemoteViews; import org.thoughtcrime.securesms.ApplicationContext; +import org.thoughtcrime.securesms.ConversationListActivity; import org.thoughtcrime.securesms.DatabaseUpgradeActivity; import org.thoughtcrime.securesms.DummyActivity; import org.thoughtcrime.securesms.R; -import org.thoughtcrime.securesms.RoutingActivity; import org.thoughtcrime.securesms.crypto.InvalidPassphraseException; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecretUtil; @@ -121,6 +121,7 @@ public class KeyCachingService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { if (intent == null) return START_NOT_STICKY; + Log.w("KeyCachingService", "onStartCommand, " + intent.getAction()); if (intent.getAction() != null) { switch (intent.getAction()) { @@ -138,6 +139,7 @@ public class KeyCachingService extends Service { @Override public void onCreate() { + Log.w("KeyCachingService", "onCreate()"); super.onCreate(); this.pending = PendingIntent.getService(this, 0, new Intent(PASSPHRASE_EXPIRED_EVENT, null, this, KeyCachingService.class), 0); @@ -186,7 +188,8 @@ public class KeyCachingService extends Service { } private void handleClearKey() { - this.masterSecret = null; + Log.w("KeyCachingService", "handleClearKey()"); + KeyCachingService.masterSecret = null; stopForeground(true); Intent intent = new Intent(CLEAR_KEY_EVENT); @@ -216,7 +219,7 @@ public class KeyCachingService extends Service { private void startTimeoutIfAppropriate() { 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 timeoutMillis = TimeUnit.MINUTES.toMillis(timeoutMinutes); @@ -230,6 +233,7 @@ public class KeyCachingService extends Service { @TargetApi(Build.VERSION_CODES.JELLY_BEAN) private void foregroundServiceModern() { + Log.w("KeyCachingService", "foregrounding KCS"); NotificationCompat.Builder builder = new NotificationCompat.Builder(this); builder.setContentTitle(getString(R.string.KeyCachingService_passphrase_cached)); @@ -292,7 +296,6 @@ public class KeyCachingService extends Service { Log.w("service", "Broadcasting new secret..."); Intent intent = new Intent(NEW_KEY_EVENT); - intent.putExtra("master_secret", masterSecret); intent.setPackage(getApplicationContext().getPackageName()); sendBroadcast(intent, KEY_PERMISSION); @@ -306,7 +309,7 @@ public class KeyCachingService extends Service { } private PendingIntent buildLaunchIntent() { - Intent intent = new Intent(this, RoutingActivity.class); + Intent intent = new Intent(this, ConversationListActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); PendingIntent launchIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0); return launchIntent; diff --git a/src/org/thoughtcrime/securesms/service/RegistrationNotifier.java b/src/org/thoughtcrime/securesms/service/RegistrationNotifier.java index 69299055ea..99bb5ad707 100644 --- a/src/org/thoughtcrime/securesms/service/RegistrationNotifier.java +++ b/src/org/thoughtcrime/securesms/service/RegistrationNotifier.java @@ -8,8 +8,8 @@ import android.content.Context; import android.content.Intent; import android.support.v4.app.NotificationCompat; +import org.thoughtcrime.securesms.ConversationListActivity; import org.thoughtcrime.securesms.R; -import org.thoughtcrime.securesms.RoutingActivity; public class RegistrationNotifier extends BroadcastReceiver { @Override @@ -18,7 +18,7 @@ public class RegistrationNotifier extends BroadcastReceiver { builder.setSmallIcon(R.drawable.icon_notification); builder.setContentTitle(intent.getStringExtra(RegistrationService.NOTIFICATION_TITLE)); 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.setDefaults(Notification.DEFAULT_VIBRATE); builder.setAutoCancel(true); diff --git a/src/org/thoughtcrime/securesms/util/MemoryCleaner.java b/src/org/thoughtcrime/securesms/util/MemoryCleaner.java deleted file mode 100644 index 1d48af31e6..0000000000 --- a/src/org/thoughtcrime/securesms/util/MemoryCleaner.java +++ /dev/null @@ -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 . - */ -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); -// } - } -}