diff --git a/AndroidManifest.xml b/AndroidManifest.xml index c358708658..9e3f11d970 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -101,7 +101,7 @@ - + + + + + + + + + \ No newline at end of file diff --git a/res/values/arrays.xml b/res/values/arrays.xml index 82a63eafda..e84a532aa3 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -202,4 +202,15 @@ 5 10 + + + default + custom + + + + @string/arrays__use_default + @string/arrays__use_custom + + diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 703f2eeccb..eb980a52bc 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -101,4 +101,9 @@ + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index d81a30892a..964017fbac 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -153,6 +153,11 @@ Key exchange message... + + Using custom: %s + Using default: %s + None + Now @@ -691,6 +696,8 @@ Import / export My identity key + Use default + Use custom @@ -775,11 +782,11 @@ Manual MMS settings Use manual MMS settings Override system MMS settings with the information below. - MMSC URL (Required) - MMS Proxy Host (Optional) - MMS Proxy Port (Optional) - MMSC Username (Optional) - MMSC Password (Optional) + MMSC URL + MMS Proxy Host + MMS Proxy Port + MMSC Username + MMSC Password SMS delivery reports Request a delivery report for each SMS message you send Automatically delete older messages once a conversation thread exceeds a specified length diff --git a/res/xml/preferences_manual_mms.xml b/res/xml/preferences_manual_mms.xml index 65a70a8ba7..abfde94989 100644 --- a/res/xml/preferences_manual_mms.xml +++ b/res/xml/preferences_manual_mms.xml @@ -1,33 +1,36 @@ - - + - + - + - + - + + + - \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/DatabaseUpgradeActivity.java b/src/org/thoughtcrime/securesms/DatabaseUpgradeActivity.java index 5d3fc29553..42aa764548 100644 --- a/src/org/thoughtcrime/securesms/DatabaseUpgradeActivity.java +++ b/src/org/thoughtcrime/securesms/DatabaseUpgradeActivity.java @@ -39,6 +39,7 @@ import org.thoughtcrime.securesms.jobs.PushDecryptJob; import org.thoughtcrime.securesms.jobs.SmsDecryptJob; import org.thoughtcrime.securesms.notifications.MessageNotifier; import org.thoughtcrime.securesms.util.ParcelUtil; +import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.VersionTracker; import org.whispersystems.jobqueue.EncryptionKeys; diff --git a/src/org/thoughtcrime/securesms/MmsPreferencesFragment.java b/src/org/thoughtcrime/securesms/MmsPreferencesFragment.java deleted file mode 100644 index 918e42b6dd..0000000000 --- a/src/org/thoughtcrime/securesms/MmsPreferencesFragment.java +++ /dev/null @@ -1,143 +0,0 @@ -/** - * Copyright (C) 2014 Open 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; - -import android.content.Context; -import android.os.Bundle; -import android.preference.EditTextPreference; -import android.preference.Preference; -import android.preference.Preference.OnPreferenceChangeListener; -import android.support.v4.preference.PreferenceFragment; -import android.text.TextUtils; -import android.widget.Toast; - -import org.thoughtcrime.securesms.mms.OutgoingMmsConnection; -import org.thoughtcrime.securesms.util.TextSecurePreferences; - -import java.net.URI; -import java.net.URISyntaxException; - - -public class MmsPreferencesFragment extends PreferenceFragment { - - @Override - public void onCreate(Bundle paramBundle) { - super.onCreate(paramBundle); - initializePreferences(); - initializeEditTextSummaries(); - ((PassphraseRequiredActionBarActivity) getActivity()).getSupportActionBar() - .setTitle(R.string.preferences__advanced_mms_access_point_names); - } - - private void initializePreferences() { - if (!OutgoingMmsConnection.isConnectionPossible(getActivity())) { - TextSecurePreferences.setUseLocalApnsEnabled(getActivity(), true); - addPreferencesFromResource(R.xml.preferences_manual_mms); - this.findPreference(TextSecurePreferences.ENABLE_MANUAL_MMS_PREF) - .setOnPreferenceChangeListener(new OverrideMmsChangeListener()); - } else { - addPreferencesFromResource(R.xml.preferences_manual_mms); - } - this.findPreference(TextSecurePreferences.MMSC_HOST_PREF).setOnPreferenceChangeListener(new ValidUriVerificationListener()); - this.findPreference(TextSecurePreferences.MMSC_PROXY_HOST_PREF).setOnPreferenceChangeListener(new ValidHostnameVerificationListener()); - this.findPreference(TextSecurePreferences.MMSC_PROXY_PORT_PREF).setOnPreferenceChangeListener(new EditTextVerificationListener()); - this.findPreference(TextSecurePreferences.MMSC_USERNAME_PREF).setOnPreferenceChangeListener(new EditTextVerificationListener()); - this.findPreference(TextSecurePreferences.MMSC_PASSWORD_PREF).setOnPreferenceChangeListener(new EditTextVerificationListener()); - } - - private void initializeEditTextSummary(final EditTextPreference preference) { - preference.setSummary(TextUtils.isEmpty(preference.getText()) ? getString(R.string.MmsPreferencesFragment__not_set) : preference.getText()); - } - - private void initializeEditTextSummaries() { - initializeEditTextSummary((EditTextPreference)this.findPreference(TextSecurePreferences.MMSC_HOST_PREF)); - initializeEditTextSummary((EditTextPreference)this.findPreference(TextSecurePreferences.MMSC_PROXY_HOST_PREF)); - initializeEditTextSummary((EditTextPreference)this.findPreference(TextSecurePreferences.MMSC_PROXY_PORT_PREF)); - initializeEditTextSummary((EditTextPreference)this.findPreference(TextSecurePreferences.MMSC_USERNAME_PREF)); - initializeEditTextSummary((EditTextPreference)this.findPreference(TextSecurePreferences.MMSC_PASSWORD_PREF)); - } - - private class OverrideMmsChangeListener implements Preference.OnPreferenceChangeListener { - @Override - public boolean onPreferenceChange(Preference preference, Object o) { - TextSecurePreferences.setUseLocalApnsEnabled(getActivity(), true); - Toast.makeText(getActivity(), R.string.MmsPreferencesFragment__manual_mms_settings_are_required, - Toast.LENGTH_SHORT).show(); - return false; - } - } - - public static CharSequence getSummary(Context context) { - final int enabledResId = R.string.MmsPreferencesFragment__enabled; - final int disabledResId = R.string.MmsPreferencesFragment__disabled; - - return context.getString(TextSecurePreferences.isUseLocalApnsEnabled(context) ? enabledResId : disabledResId); - } - - private class EditTextVerificationListener implements OnPreferenceChangeListener { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - String newString = (String)newValue; - if (isValid(newString)) { - preference.setSummary(TextUtils.isEmpty(newString) ? getString(R.string.MmsPreferencesFragment__not_set) : newString); - return true; - } else { - Toast.makeText(getActivity(), getErrorMessage(), Toast.LENGTH_LONG).show(); - return false; - } - } - - protected boolean isValid(String newString) { return true; } - protected int getErrorMessage() { return 0; } - } - - private class ValidUriVerificationListener extends EditTextVerificationListener { - @Override - protected boolean isValid(String newString) { - if (TextUtils.isEmpty(newString)) return true; - try { - new URI(newString); - return true; - } catch (URISyntaxException mue) { - return false; - } - } - - @Override - protected int getErrorMessage() { - return R.string.MmsPreferencesFragment__invalid_uri; - } - } - - private class ValidHostnameVerificationListener extends EditTextVerificationListener { - @Override - protected boolean isValid(String newString) { - if (TextUtils.isEmpty(newString)) return true; - try { - URI uri = new URI(null, newString, null, null); - return true; - } catch (URISyntaxException mue) { - return false; - } - } - - @Override - protected int getErrorMessage() { - return R.string.MmsPreferencesFragment__invalid_host; - } - } -} diff --git a/src/org/thoughtcrime/securesms/PromptMmsActivity.java b/src/org/thoughtcrime/securesms/PromptMmsActivity.java index 0e4abc51ab..2e495b9a74 100644 --- a/src/org/thoughtcrime/securesms/PromptMmsActivity.java +++ b/src/org/thoughtcrime/securesms/PromptMmsActivity.java @@ -5,6 +5,8 @@ import android.os.Bundle; import android.view.View; import android.widget.Button; +import org.thoughtcrime.securesms.preferences.MmsPreferencesActivity; + public class PromptMmsActivity extends PassphraseRequiredActionBarActivity { private Button okButton; diff --git a/src/org/thoughtcrime/securesms/components/CustomDefaultPreference.java b/src/org/thoughtcrime/securesms/components/CustomDefaultPreference.java new file mode 100644 index 0000000000..874d0470b7 --- /dev/null +++ b/src/org/thoughtcrime/securesms/components/CustomDefaultPreference.java @@ -0,0 +1,227 @@ +package org.thoughtcrime.securesms.components; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.res.TypedArray; +import android.os.Bundle; +import android.preference.DialogPreference; +import android.support.annotation.NonNull; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.util.AttributeSet; +import android.util.Log; +import android.view.View; +import android.widget.AdapterView; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Spinner; +import android.widget.TextView; + +import org.thoughtcrime.securesms.R; +import org.thoughtcrime.securesms.util.TextSecurePreferences; + +import java.net.URI; +import java.net.URISyntaxException; + + +public class CustomDefaultPreference extends DialogPreference { + + private static final String TAG = CustomDefaultPreference.class.getSimpleName(); + + private final int inputType; + private final String customPreference; + private final String customToggle; + + private CustomPreferenceValidator validator; + private String defaultValue; + + private Spinner spinner; + private EditText customText; + private TextView defaultLabel; + private Button positiveButton; + + public CustomDefaultPreference(Context context, AttributeSet attrs) { + super(context, attrs); + + int[] attributeNames = new int[]{android.R.attr.inputType, R.attr.custom_pref_toggle}; + TypedArray attributes = context.obtainStyledAttributes(attrs, attributeNames); + + this.inputType = attributes.getInt(0, 0); + this.customPreference = getKey(); + this.customToggle = attributes.getString(1); + this.validator = new NullValidator(); + + attributes.recycle(); + + setPersistent(false); + setDialogLayoutResource(R.layout.custom_default_preference_dialog); + } + + public CustomDefaultPreference setValidator(CustomPreferenceValidator validator) { + this.validator = validator; + return this; + } + + public CustomDefaultPreference setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + this.setSummary(getSummary()); + return this; + } + + @Override + public String getSummary() { + if (isCustom()) { + return getContext().getString(R.string.CustomDefaultPreference_using_custom, + getPrettyPrintValue(getCustomValue())); + } else { + return getContext().getString(R.string.CustomDefaultPreference_using_default, + getPrettyPrintValue(getDefaultValue())); + } + } + + @Override + protected void onBindDialogView(@NonNull View view) { + super.onBindDialogView(view); + + this.spinner = (Spinner) view.findViewById(R.id.default_or_custom); + this.defaultLabel = (TextView) view.findViewById(R.id.default_label); + this.customText = (EditText) view.findViewById(R.id.custom_edit); + + this.customText.setInputType(inputType); + this.customText.addTextChangedListener(new TextValidator()); + this.customText.setText(getCustomValue()); + this.spinner.setOnItemSelectedListener(new SelectionLister()); + this.defaultLabel.setText(getPrettyPrintValue(defaultValue)); + } + + @Override + protected void showDialog(Bundle instanceState) { + super.showDialog(instanceState); + positiveButton = ((AlertDialog)getDialog()).getButton(AlertDialog.BUTTON_POSITIVE); + + if (isCustom()) spinner.setSelection(1, true); + else spinner.setSelection(0, true); + } + + @Override + protected void onDialogClosed(boolean positiveResult) { + if (positiveResult) { + if (spinner != null) setCustom(spinner.getSelectedItemPosition() == 1); + if (customText != null) setCustomValue(customText.getText().toString()); + + setSummary(getSummary()); + } + } + + private String getPrettyPrintValue(String value) { + if (TextUtils.isEmpty(value)) return getContext().getString(R.string.CustomDefaultPreference_none); + else return value; + } + + private boolean isCustom() { + return TextSecurePreferences.getBooleanPreference(getContext(), customToggle, false); + } + + private void setCustom(boolean custom) { + TextSecurePreferences.setBooleanPreference(getContext(), customToggle, custom); + } + + private String getCustomValue() { + return TextSecurePreferences.getStringPreference(getContext(), customPreference, ""); + } + + private void setCustomValue(String value) { + TextSecurePreferences.setStringPreference(getContext(), customPreference, value); + } + + private String getDefaultValue() { + return defaultValue; + } + + private class SelectionLister implements AdapterView.OnItemSelectedListener { + + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + defaultLabel.setVisibility(position == 0 ? View.VISIBLE : View.GONE); + customText.setVisibility(position == 0 ? View.GONE : View.VISIBLE); + positiveButton.setEnabled(position == 0 || validator.isValid(customText.getText().toString())); + } + + @Override + public void onNothingSelected(AdapterView parent) { + defaultLabel.setVisibility(View.VISIBLE); + customText.setVisibility(View.GONE); + } + } + + private class TextValidator implements TextWatcher { + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) {} + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) {} + + @Override + public void afterTextChanged(Editable s) { + if (spinner.getSelectedItemPosition() == 1) { + positiveButton.setEnabled(validator.isValid(s.toString())); + } + } + } + + protected interface CustomPreferenceValidator { + public boolean isValid(String value); + } + + private static class NullValidator implements CustomPreferenceValidator { + @Override + public boolean isValid(String value) { + return true; + } + } + + public static class UriValidator implements CustomPreferenceValidator { + @Override + public boolean isValid(String value) { + if (TextUtils.isEmpty(value)) return true; + + try { + new URI(value); + return true; + } catch (URISyntaxException mue) { + return false; + } + } + } + + public static class HostnameValidator implements CustomPreferenceValidator { + @Override + public boolean isValid(String value) { + if (TextUtils.isEmpty(value)) return true; + + try { + URI uri = new URI(null, value, null, null); + return true; + } catch (URISyntaxException mue) { + return false; + } + } + } + + public static class PortValidator implements CustomPreferenceValidator { + @Override + public boolean isValid(String value) { + try { + Integer.parseInt(value); + return true; + } catch (NumberFormatException e) { + return false; + } + } + } + + + +} diff --git a/src/org/thoughtcrime/securesms/database/ApnDatabase.java b/src/org/thoughtcrime/securesms/database/ApnDatabase.java index a136ceac4f..a6694d9b75 100644 --- a/src/org/thoughtcrime/securesms/database/ApnDatabase.java +++ b/src/org/thoughtcrime/securesms/database/ApnDatabase.java @@ -27,6 +27,7 @@ import org.thoughtcrime.securesms.mms.ApnUnavailableException; import org.thoughtcrime.securesms.mms.MmsConnection.Apn; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.Util; +import org.whispersystems.libaxolotl.util.guava.Optional; import java.io.File; import java.io.FileOutputStream; @@ -93,13 +94,11 @@ public class ApnDatabase { null, SQLiteDatabase.OPEN_READONLY | SQLiteDatabase.NO_LOCALIZED_COLLATORS); } - protected Apn getLocallyConfiguredMmsConnectionParameters() throws ApnUnavailableException { - if (TextSecurePreferences.isUseLocalApnsEnabled(context)) { - String mmsc = TextSecurePreferences.getMmscUrl(context).trim(); - if (TextUtils.isEmpty(mmsc)) - throw new ApnUnavailableException("Malformed locally configured MMSC."); - if (!mmsc.startsWith("http")) + private Apn getCustomApnParameters() { + String mmsc = TextSecurePreferences.getMmscUrl(context).trim(); + + if (!TextUtils.isEmpty(mmsc) && !mmsc.startsWith("http")) mmsc = "http://" + mmsc; String proxy = TextSecurePreferences.getMmscProxy(context); @@ -108,26 +107,12 @@ public class ApnDatabase { String pass = TextSecurePreferences.getMmscPassword(context); return new Apn(mmsc, proxy, port, user, pass); - } - - throw new ApnUnavailableException("No locally configured parameters available"); - } - public Apn getMmsConnectionParameters(final String mccmnc, final String apn) { - - if (TextSecurePreferences.isUseLocalApnsEnabled(context)) { - Log.w(TAG, "Choosing locally-overridden MMS settings"); - try { - return getLocallyConfiguredMmsConnectionParameters(); - } catch (ApnUnavailableException aue) { - Log.w(TAG, "preference to use local apn set, but no parameters avaiable. falling back."); - } - } - + public Apn getDefaultApnParameters(String mccmnc, String apn) { if (mccmnc == null) { Log.w(TAG, "mccmnc was null, returning null"); - return null; + return Apn.EMPTY; } Cursor cursor = null; @@ -161,9 +146,25 @@ public class ApnDatabase { } Log.w(TAG, "No matching APNs found, returning null"); - return null; + + return Apn.EMPTY; } finally { if (cursor != null) cursor.close(); } + + } + + public Optional getMmsConnectionParameters(String mccmnc, String apn) { + Apn customApn = getCustomApnParameters(); + Apn defaultApn = getDefaultApnParameters(mccmnc, apn); + Apn result = new Apn(customApn, defaultApn, + TextSecurePreferences.getUseCustomMmsc(context), + TextSecurePreferences.getUseCustomMmscProxy(context), + TextSecurePreferences.getUseCustomMmscProxyPort(context), + TextSecurePreferences.getUseCustomMmscUsername(context), + TextSecurePreferences.getUseCustomMmscPassword(context)); + + if (TextUtils.isEmpty(result.getMmsc())) return Optional.absent(); + else return Optional.of(result); } } diff --git a/src/org/thoughtcrime/securesms/mms/MmsConnection.java b/src/org/thoughtcrime/securesms/mms/MmsConnection.java index db13f061b7..de91f9234d 100644 --- a/src/org/thoughtcrime/securesms/mms/MmsConnection.java +++ b/src/org/thoughtcrime/securesms/mms/MmsConnection.java @@ -37,6 +37,7 @@ import org.thoughtcrime.securesms.database.ApnDatabase; import org.thoughtcrime.securesms.util.TelephonyUtil; import org.thoughtcrime.securesms.util.Conversions; import org.thoughtcrime.securesms.util.Util; +import org.whispersystems.libaxolotl.util.guava.Optional; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; @@ -56,27 +57,24 @@ public abstract class MmsConnection { this.apn = apn; } - protected static Apn getLocalApn(Context context) throws ApnUnavailableException { - try { - Apn params = ApnDatabase.getInstance(context) - .getMmsConnectionParameters(TelephonyUtil.getMccMnc(context), - TelephonyUtil.getApn(context)); + public static Apn getApn(Context context, String apnName) throws ApnUnavailableException { + Log.w(TAG, "Getting MMSC params for apn " + apnName); - if (params == null) { + try { + Optional params = ApnDatabase.getInstance(context) + .getMmsConnectionParameters(TelephonyUtil.getMccMnc(context), + TelephonyUtil.getApn(context)); + + if (!params.isPresent()) { throw new ApnUnavailableException("No parameters available from ApnDefaults."); } - return params; + return params.get(); } catch (IOException ioe) { throw new ApnUnavailableException("ApnDatabase threw an IOException", ioe); } } - public static Apn getApn(Context context, String apnName) throws ApnUnavailableException { - Log.w(TAG, "Getting MMSC params for apn " + apnName); - return getLocalApn(context); - } - protected static boolean checkRouteToHost(Context context, String host, boolean usingMmsRadio) throws IOException { @@ -171,6 +169,9 @@ public abstract class MmsConnection { protected abstract HttpUriRequest constructRequest(boolean useProxy) throws IOException; public static class Apn { + + public static Apn EMPTY = new Apn("", "", "", "", ""); + private final String mmsc; private final String proxy; private final String port; @@ -185,6 +186,20 @@ public abstract class MmsConnection { this.password = password; } + public Apn(Apn customApn, Apn defaultApn, + boolean useCustomMmsc, + boolean useCustomProxy, + boolean useCustomProxyPort, + boolean useCustomUsername, + boolean useCustomPassword) + { + this.mmsc = useCustomMmsc ? customApn.mmsc : defaultApn.mmsc; + this.proxy = useCustomProxy ? customApn.proxy : defaultApn.proxy; + this.port = useCustomProxyPort ? customApn.port : defaultApn.port; + this.username = useCustomUsername ? customApn.username : defaultApn.username; + this.password = useCustomPassword ? customApn.password : defaultApn.password; + } + public boolean hasProxy() { return !TextUtils.isEmpty(proxy); } diff --git a/src/org/thoughtcrime/securesms/MmsPreferencesActivity.java b/src/org/thoughtcrime/securesms/preferences/MmsPreferencesActivity.java similarity index 95% rename from src/org/thoughtcrime/securesms/MmsPreferencesActivity.java rename to src/org/thoughtcrime/securesms/preferences/MmsPreferencesActivity.java index d3f7682728..b51aa25baa 100644 --- a/src/org/thoughtcrime/securesms/MmsPreferencesActivity.java +++ b/src/org/thoughtcrime/securesms/preferences/MmsPreferencesActivity.java @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.thoughtcrime.securesms; +package org.thoughtcrime.securesms.preferences; import android.os.Bundle; import android.support.v4.app.Fragment; @@ -22,6 +22,7 @@ import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.view.MenuItem; +import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicTheme; diff --git a/src/org/thoughtcrime/securesms/preferences/MmsPreferencesFragment.java b/src/org/thoughtcrime/securesms/preferences/MmsPreferencesFragment.java new file mode 100644 index 0000000000..48f6409138 --- /dev/null +++ b/src/org/thoughtcrime/securesms/preferences/MmsPreferencesFragment.java @@ -0,0 +1,96 @@ +/** + * Copyright (C) 2014 Open 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.preferences; + +import android.content.Context; +import android.os.AsyncTask; +import android.os.Bundle; +import android.support.v4.preference.PreferenceFragment; +import android.util.Log; + +import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity; +import org.thoughtcrime.securesms.R; +import org.thoughtcrime.securesms.components.CustomDefaultPreference; +import org.thoughtcrime.securesms.database.ApnDatabase; +import org.thoughtcrime.securesms.mms.MmsConnection; +import org.thoughtcrime.securesms.util.TelephonyUtil; +import org.thoughtcrime.securesms.util.TextSecurePreferences; + +import java.io.IOException; + + +public class MmsPreferencesFragment extends PreferenceFragment { + + private static final String TAG = MmsPreferencesFragment.class.getSimpleName(); + + @Override + public void onCreate(Bundle paramBundle) { + super.onCreate(paramBundle); + addPreferencesFromResource(R.xml.preferences_manual_mms); + + ((PassphraseRequiredActionBarActivity) getActivity()).getSupportActionBar() + .setTitle(R.string.preferences__advanced_mms_access_point_names); + } + + @Override + public void onResume() { + super.onResume(); + new LoadApnDefaultsTask().execute(); + } + + private class LoadApnDefaultsTask extends AsyncTask { + + @Override + protected MmsConnection.Apn doInBackground(Void... params) { + try { + Context context = getActivity(); + + if (context != null) { + return ApnDatabase.getInstance(context) + .getDefaultApnParameters(TelephonyUtil.getMccMnc(context), + TelephonyUtil.getApn(context)); + } + } catch (IOException e) { + Log.w(TAG, e); + } + + return null; + } + + @Override + protected void onPostExecute(MmsConnection.Apn apnDefaults) { + ((CustomDefaultPreference)findPreference(TextSecurePreferences.MMSC_HOST_PREF)) + .setValidator(new CustomDefaultPreference.UriValidator()) + .setDefaultValue(apnDefaults.getMmsc()); + + ((CustomDefaultPreference)findPreference(TextSecurePreferences.MMSC_PROXY_HOST_PREF)) + .setValidator(new CustomDefaultPreference.HostnameValidator()) + .setDefaultValue(apnDefaults.getProxy()); + + ((CustomDefaultPreference)findPreference(TextSecurePreferences.MMSC_PROXY_PORT_PREF)) + .setValidator(new CustomDefaultPreference.PortValidator()) + .setDefaultValue(apnDefaults.getPort()); + + ((CustomDefaultPreference)findPreference(TextSecurePreferences.MMSC_USERNAME_PREF)) + .setDefaultValue(apnDefaults.getPort()); + + ((CustomDefaultPreference)findPreference(TextSecurePreferences.MMSC_PASSWORD_PREF)) + .setDefaultValue(apnDefaults.getPassword()); + } + } + +} diff --git a/src/org/thoughtcrime/securesms/preferences/SmsMmsPreferenceFragment.java b/src/org/thoughtcrime/securesms/preferences/SmsMmsPreferenceFragment.java index 81f0c0d85e..191343097f 100644 --- a/src/org/thoughtcrime/securesms/preferences/SmsMmsPreferenceFragment.java +++ b/src/org/thoughtcrime/securesms/preferences/SmsMmsPreferenceFragment.java @@ -15,7 +15,6 @@ import android.support.v4.preference.PreferenceFragment; import android.text.TextUtils; import org.thoughtcrime.securesms.ApplicationPreferencesActivity; -import org.thoughtcrime.securesms.MmsPreferencesFragment; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.components.OutgoingSmsPreference; import org.thoughtcrime.securesms.util.TextSecurePreferences; @@ -46,8 +45,6 @@ public class SmsMmsPreferenceFragment extends PreferenceFragment { public void onResume() { super.onResume(); ((ApplicationPreferencesActivity) getActivity()).getSupportActionBar().setTitle(R.string.preferences__sms_mms); - this.findPreference(MMS_PREF) - .setSummary(MmsPreferencesFragment.getSummary(getActivity())); initializePlatformSpecificOptions(); } diff --git a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java index 6082af1d5a..5dbb6d145c 100644 --- a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java +++ b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java @@ -15,10 +15,15 @@ public class TextSecurePreferences { public static final String DISABLE_PASSPHRASE_PREF = "pref_disable_passphrase"; public static final String THEME_PREF = "pref_theme"; public static final String LANGUAGE_PREF = "pref_language"; + private static final String MMSC_CUSTOM_HOST_PREF = "pref_apn_mmsc_custom_host"; public static final String MMSC_HOST_PREF = "pref_apn_mmsc_host"; + private static final String MMSC_CUSTOM_PROXY_PREF = "pref_apn_mms_custom_proxy"; public static final String MMSC_PROXY_HOST_PREF = "pref_apn_mms_proxy"; + private static final String MMSC_CUSTOM_PROXY_PORT_PREF = "pref_apn_mms_custom_proxy_port"; public static final String MMSC_PROXY_PORT_PREF = "pref_apn_mms_proxy_port"; + private static final String MMSC_CUSTOM_USERNAME_PREF = "pref_apn_mmsc_custom_username"; public static final String MMSC_USERNAME_PREF = "pref_apn_mmsc_username"; + private static final String MMSC_CUSTOM_PASSWORD_PREF = "pref_apn_mmsc_custom_password"; public static final String MMSC_PASSWORD_PREF = "pref_apn_mmsc_password"; public static final String THREAD_TRIM_LENGTH = "pref_trim_length"; public static final String THREAD_TRIM_NOW = "pref_trim_now"; @@ -206,26 +211,91 @@ public class TextSecurePreferences { setBooleanPreference(context, DISABLE_PASSPHRASE_PREF, disabled); } + public static boolean getUseCustomMmsc(Context context) { + boolean legacy = TextSecurePreferences.isLegacyUseLocalApnsEnabled(context); + return getBooleanPreference(context, MMSC_CUSTOM_HOST_PREF, legacy); + } + + public static void setUseCustomMmsc(Context context, boolean value) { + setBooleanPreference(context, MMSC_CUSTOM_HOST_PREF, value); + } + public static String getMmscUrl(Context context) { return getStringPreference(context, MMSC_HOST_PREF, ""); } + public static void setMmscUrl(Context context, String mmsc) { + setStringPreference(context, MMSC_HOST_PREF, mmsc); + } + + public static boolean getUseCustomMmscProxy(Context context) { + boolean legacy = TextSecurePreferences.isLegacyUseLocalApnsEnabled(context); + return getBooleanPreference(context, MMSC_CUSTOM_PROXY_PREF, legacy); + } + + public static void setUseCustomMmscProxy(Context context, boolean value) { + setBooleanPreference(context, MMSC_CUSTOM_PROXY_PREF, value); + } + public static String getMmscProxy(Context context) { return getStringPreference(context, MMSC_PROXY_HOST_PREF, ""); } + public static void setMmscProxy(Context context, String value) { + setStringPreference(context, MMSC_PROXY_HOST_PREF, value); + } + + public static boolean getUseCustomMmscProxyPort(Context context) { + boolean legacy = TextSecurePreferences.isLegacyUseLocalApnsEnabled(context); + return getBooleanPreference(context, MMSC_CUSTOM_PROXY_PORT_PREF, legacy); + } + + public static void setUseCustomMmscProxyPort(Context context, boolean value) { + setBooleanPreference(context, MMSC_CUSTOM_PROXY_PORT_PREF, value); + } + public static String getMmscProxyPort(Context context) { return getStringPreference(context, MMSC_PROXY_PORT_PREF, ""); } + public static void setMmscProxyPort(Context context, String value) { + setStringPreference(context, MMSC_PROXY_PORT_PREF, value); + } + + public static boolean getUseCustomMmscUsername(Context context) { + boolean legacy = TextSecurePreferences.isLegacyUseLocalApnsEnabled(context); + return getBooleanPreference(context, MMSC_CUSTOM_USERNAME_PREF, legacy); + } + + public static void setUseCustomMmscUsername(Context context, boolean value) { + setBooleanPreference(context, MMSC_CUSTOM_USERNAME_PREF, value); + } + public static String getMmscUsername(Context context) { return getStringPreference(context, MMSC_USERNAME_PREF, ""); } + public static void setMmscUsername(Context context, String value) { + setStringPreference(context, MMSC_USERNAME_PREF, value); + } + + public static boolean getUseCustomMmscPassword(Context context) { + boolean legacy = TextSecurePreferences.isLegacyUseLocalApnsEnabled(context); + return getBooleanPreference(context, MMSC_CUSTOM_PASSWORD_PREF, legacy); + } + + public static void setUseCustomMmscPassword(Context context, boolean value) { + setBooleanPreference(context, MMSC_CUSTOM_PASSWORD_PREF, value); + } + public static String getMmscPassword(Context context) { return getStringPreference(context, MMSC_PASSWORD_PREF, ""); } + public static void setMmscPassword(Context context, String value) { + setStringPreference(context, MMSC_PASSWORD_PREF, value); + } + public static String getIdentityContactUri(Context context) { return getStringPreference(context, IDENTITY_PREF, null); } @@ -242,14 +312,10 @@ public class TextSecurePreferences { return getBooleanPreference(context, SCREEN_SECURITY_PREF, true); } - public static boolean isUseLocalApnsEnabled(Context context) { + public static boolean isLegacyUseLocalApnsEnabled(Context context) { return getBooleanPreference(context, ENABLE_MANUAL_MMS_PREF, false); } - public static void setUseLocalApnsEnabled(Context context, boolean useLocal) { - setBooleanPreference(context, ENABLE_MANUAL_MMS_PREF, useLocal); - } - public static int getLastVersionCode(Context context) { return getIntegerPreference(context, LAST_VERSION_CODE_PREF, 0); } @@ -373,11 +439,11 @@ public class TextSecurePreferences { setLongPreference(context, PUSH_REGISTRATION_REMINDER_PREF, time); } - private static void setBooleanPreference(Context context, String key, boolean value) { + public static void setBooleanPreference(Context context, String key, boolean value) { PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean(key, value).apply(); } - private static boolean getBooleanPreference(Context context, String key, boolean defaultValue) { + public static boolean getBooleanPreference(Context context, String key, boolean defaultValue) { return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(key, defaultValue); } @@ -385,7 +451,7 @@ public class TextSecurePreferences { PreferenceManager.getDefaultSharedPreferences(context).edit().putString(key, value).apply(); } - private static String getStringPreference(Context context, String key, String defaultValue) { + public static String getStringPreference(Context context, String key, String defaultValue) { return PreferenceManager.getDefaultSharedPreferences(context).getString(key, defaultValue); }