mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 09:20:19 +01:00
Allow using a proxy during registration.
This commit is contained in:
@@ -184,12 +184,10 @@ public class ApplicationDependencies {
|
||||
}
|
||||
}
|
||||
|
||||
public static void resetNetworkConnectionsAfterProxyChange() {
|
||||
public static void closeConnectionsAfterProxyFailure() {
|
||||
synchronized (LOCK) {
|
||||
getPipeListener().reset();
|
||||
|
||||
if (incomingMessageObserver != null) {
|
||||
incomingMessageObserver.terminate();
|
||||
incomingMessageObserver.terminateAsync();
|
||||
}
|
||||
|
||||
if (messageSender != null) {
|
||||
@@ -203,6 +201,13 @@ public class ApplicationDependencies {
|
||||
}
|
||||
}
|
||||
|
||||
public static void resetNetworkConnectionsAfterProxyChange() {
|
||||
synchronized (LOCK) {
|
||||
getPipeListener().reset();
|
||||
closeConnectionsAfterProxyFailure();
|
||||
}
|
||||
}
|
||||
|
||||
public static @NonNull SignalServiceNetworkAccess getSignalServiceNetworkAccess() {
|
||||
return provider.provideSignalServiceNetworkAccess();
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import androidx.lifecycle.DefaultLifecycleObserver;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.ProcessLifecycleOwner;
|
||||
|
||||
import org.signal.core.util.concurrent.SignalExecutors;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
@@ -160,10 +161,12 @@ public class IncomingMessageObserver {
|
||||
}
|
||||
}
|
||||
|
||||
public void terminate() {
|
||||
Log.w(TAG, "Beginning termination.");
|
||||
terminated = true;
|
||||
shutdown(pipe, unidentifiedPipe);
|
||||
public void terminateAsync() {
|
||||
SignalExecutors.BOUNDED.execute(() -> {
|
||||
Log.w(TAG, "Beginning termination.");
|
||||
terminated = true;
|
||||
shutdown(pipe, unidentifiedPipe);
|
||||
});
|
||||
}
|
||||
|
||||
private void shutdown(@Nullable SignalServiceMessagePipe pipe, @Nullable SignalServiceMessagePipe unidentifiedPipe) {
|
||||
|
||||
@@ -47,7 +47,10 @@ public class PipeConnectivityListener implements ConnectivityListener {
|
||||
@Override
|
||||
public void onDisconnected() {
|
||||
Log.w(TAG, "onDisconnected()");
|
||||
state.postValue(State.DISCONNECTED);
|
||||
|
||||
if (state.getValue() != State.FAILURE) {
|
||||
state.postValue(State.DISCONNECTED);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,7 +68,7 @@ public class PipeConnectivityListener implements ConnectivityListener {
|
||||
|
||||
if (SignalStore.proxy().isProxyEnabled()) {
|
||||
Log.w(TAG, "Encountered an error while we had a proxy set! Terminating the connection to prevent retry spam.");
|
||||
ApplicationDependencies.getIncomingMessageObserver().terminate();
|
||||
ApplicationDependencies.closeConnectionsAfterProxyFailure();
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
|
||||
@@ -5,24 +5,24 @@ import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.SwitchCompat;
|
||||
import androidx.core.app.ShareCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
import androidx.navigation.Navigation;
|
||||
|
||||
import com.dd.CircularProgressButton;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.net.PipeConnectivityListener;
|
||||
import org.thoughtcrime.securesms.util.SignalProxyUtil;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.internal.configuration.SignalProxy;
|
||||
|
||||
@@ -62,12 +62,15 @@ public class EditProxyFragment extends Fragment {
|
||||
saveButton.setOnClickListener(v -> onSaveClicked());
|
||||
shareButton.setOnClickListener(v -> onShareClicked());
|
||||
proxySwitch.setOnCheckedChangeListener((buttonView, isChecked) -> viewModel.onToggleProxy(isChecked));
|
||||
|
||||
requireActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
((ApplicationPreferencesActivity) requireActivity()).requireSupportActionBar().setTitle(R.string.preferences_use_proxy);
|
||||
((AppCompatActivity) requireActivity()).getSupportActionBar().setTitle(R.string.preferences_use_proxy);
|
||||
SignalProxyUtil.startListeningToWebsocket();
|
||||
}
|
||||
|
||||
private void initViewModel() {
|
||||
@@ -99,26 +102,30 @@ public class EditProxyFragment extends Fragment {
|
||||
shareButton.setEnabled(false);
|
||||
shareButton.setAlpha(0.5f);
|
||||
proxyTitle.setAlpha(0.5f);
|
||||
proxyStatus.setVisibility(View.GONE);
|
||||
proxyStatus.setVisibility(View.INVISIBLE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void presentProxyState(@NonNull PipeConnectivityListener.State proxyState) {
|
||||
switch (proxyState) {
|
||||
case DISCONNECTED:
|
||||
case CONNECTING:
|
||||
proxyStatus.setText(R.string.preferences_connecting_to_proxy);
|
||||
proxyStatus.setTextColor(getResources().getColor(R.color.signal_text_secondary));
|
||||
break;
|
||||
case CONNECTED:
|
||||
proxyStatus.setText(R.string.preferences_connected_to_proxy);
|
||||
proxyStatus.setTextColor(getResources().getColor(R.color.signal_accent_green));
|
||||
break;
|
||||
case FAILURE:
|
||||
proxyStatus.setText(R.string.preferences_connection_failed);
|
||||
proxyStatus.setTextColor(getResources().getColor(R.color.signal_alert_primary));
|
||||
break;
|
||||
if (SignalStore.proxy().getProxy() != null) {
|
||||
switch (proxyState) {
|
||||
case DISCONNECTED:
|
||||
case CONNECTING:
|
||||
proxyStatus.setText(R.string.preferences_connecting_to_proxy);
|
||||
proxyStatus.setTextColor(getResources().getColor(R.color.signal_text_secondary));
|
||||
break;
|
||||
case CONNECTED:
|
||||
proxyStatus.setText(R.string.preferences_connected_to_proxy);
|
||||
proxyStatus.setTextColor(getResources().getColor(R.color.signal_accent_green));
|
||||
break;
|
||||
case FAILURE:
|
||||
proxyStatus.setText(R.string.preferences_connection_failed);
|
||||
proxyStatus.setTextColor(getResources().getColor(R.color.signal_alert_primary));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
proxyStatus.setText("");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,7 +141,7 @@ public class EditProxyFragment extends Fragment {
|
||||
.show();
|
||||
break;
|
||||
case PROXY_FAILURE:
|
||||
proxyStatus.setVisibility(View.GONE);
|
||||
proxyStatus.setVisibility(View.INVISIBLE);
|
||||
proxyText.setText(Optional.fromNullable(SignalStore.proxy().getProxy()).transform(SignalProxy::getHost).or(""));
|
||||
new AlertDialog.Builder(requireContext())
|
||||
.setTitle(R.string.preferences_failed_to_connect)
|
||||
|
||||
@@ -11,20 +11,24 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.net.PipeConnectivityListener;
|
||||
import org.thoughtcrime.securesms.util.SignalProxyUtil;
|
||||
import org.thoughtcrime.securesms.util.SingleLiveEvent;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.signalservice.internal.configuration.SignalProxy;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class EditProxyViewModel extends ViewModel {
|
||||
|
||||
private final SingleLiveEvent<Event> events;
|
||||
private final MutableLiveData<UiState> uiState;
|
||||
private final MutableLiveData<SaveState> saveState;
|
||||
private final SingleLiveEvent<Event> events;
|
||||
private final MutableLiveData<UiState> uiState;
|
||||
private final MutableLiveData<SaveState> saveState;
|
||||
private final LiveData<PipeConnectivityListener.State> pipeState;
|
||||
|
||||
public EditProxyViewModel() {
|
||||
this.events = new SingleLiveEvent<>();
|
||||
this.uiState = new MutableLiveData<>();
|
||||
this.saveState = new MutableLiveData<>(SaveState.IDLE);
|
||||
this.pipeState = TextSecurePreferences.getLocalNumber(ApplicationDependencies.getApplication()) == null ? new MutableLiveData<>()
|
||||
: ApplicationDependencies.getPipeListener().getState();
|
||||
|
||||
if (SignalStore.proxy().isProxyEnabled()) {
|
||||
uiState.setValue(UiState.ALL_ENABLED);
|
||||
@@ -78,7 +82,7 @@ public class EditProxyViewModel extends ViewModel {
|
||||
}
|
||||
|
||||
@NonNull LiveData<PipeConnectivityListener.State> getProxyState() {
|
||||
return ApplicationDependencies.getPipeListener().getState();
|
||||
return pipeState;
|
||||
}
|
||||
|
||||
public @NonNull LiveData<SaveState> getSaveState() {
|
||||
|
||||
@@ -7,6 +7,9 @@ import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -20,6 +23,8 @@ import android.widget.Toast;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.navigation.NavController;
|
||||
import androidx.navigation.Navigation;
|
||||
|
||||
@@ -55,6 +60,12 @@ public final class EnterPhoneNumberFragment extends BaseRegistrationFragment {
|
||||
private View cancel;
|
||||
private ScrollView scrollView;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
@@ -99,6 +110,25 @@ public final class EnterPhoneNumberFragment extends BaseRegistrationFragment {
|
||||
}
|
||||
|
||||
countryCode.getInput().setImeOptions(EditorInfo.IME_ACTION_NEXT);
|
||||
|
||||
Toolbar toolbar = view.findViewById(R.id.toolbar);
|
||||
((AppCompatActivity) requireActivity()).setSupportActionBar(toolbar);
|
||||
((AppCompatActivity) requireActivity()).getSupportActionBar().setTitle(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.enter_phone_number, menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
||||
if (item.getItemId() == R.id.phone_menu_use_proxy) {
|
||||
Navigation.findNavController(requireView()).navigate(EnterPhoneNumberFragmentDirections.actionEditProxy());
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void setUpNumberInput() {
|
||||
|
||||
@@ -27,6 +27,11 @@ public final class SignalProxyUtil {
|
||||
private SignalProxyUtil() {}
|
||||
|
||||
public static void startListeningToWebsocket() {
|
||||
if (SignalStore.proxy().isProxyEnabled() && ApplicationDependencies.getPipeListener().getState().getValue() == PipeConnectivityListener.State.FAILURE) {
|
||||
Log.w(TAG, "Proxy is in a failed state. Restarting.");
|
||||
ApplicationDependencies.closeConnectionsAfterProxyFailure();
|
||||
}
|
||||
|
||||
ApplicationDependencies.getIncomingMessageObserver();
|
||||
}
|
||||
|
||||
@@ -63,6 +68,11 @@ public final class SignalProxyUtil {
|
||||
public static boolean testWebsocketConnection(long timeout) {
|
||||
startListeningToWebsocket();
|
||||
|
||||
if (TextSecurePreferences.getLocalNumber(ApplicationDependencies.getApplication()) == null) {
|
||||
Log.i(TAG, "User is unregistered! Assuming success.");
|
||||
return true;
|
||||
}
|
||||
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
AtomicBoolean success = new AtomicBoolean(false);
|
||||
|
||||
@@ -105,17 +115,17 @@ public final class SignalProxyUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
String path = uri.getPath();
|
||||
String fragment = uri.getFragment();
|
||||
|
||||
if (Util.isEmpty(path) || "/".equals(path)) {
|
||||
if (Util.isEmpty(fragment)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (path.startsWith("/")) {
|
||||
return path.substring(1);
|
||||
} else {
|
||||
return path;
|
||||
if (fragment.startsWith("#")) {
|
||||
fragment = fragment.substring(1);
|
||||
}
|
||||
|
||||
return Util.isEmpty(fragment) ? null : fragment;
|
||||
} catch (URISyntaxException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user