diff --git a/.gitignore b/.gitignore index 4b62fc423f..a918936f20 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,5 @@ obj/ jni/libspeex/.deps/ *.sh pkcs11.password +fabric.properties +play diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 0e5a5d0654..6a3cd05962 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -38,58 +38,36 @@ - - - - - - - - - + + - + - - + - - + - - - + + - - + + + + + + + - - - - + + @@ -462,10 +431,6 @@ android:noHistory="true" android:stateNotNeeded="true" android:theme="@android:style/Theme.NoDisplay" /> - @@ -590,20 +555,6 @@ android:name="android.accounts.AccountAuthenticator" android:resource="@xml/authenticator" /> - - - - - - - - @@ -612,11 +563,6 @@ - - - - - if (file.exists()) { - MessageDigest md = MessageDigest.getInstance("SHA-256"); + MessageDigest md = MessageDigest.getInstance("SHA-256") file.eachByte 4096, {bytes, size -> - md.update(bytes, 0, size); + md.update(bytes, 0, size) } - String digest = md.digest().collect {String.format "%02x", it}.join(); + String digest = md.digest().collect {String.format "%02x", it}.join() String url = variant.productFlavors.get(0).ext.websiteUpdateUrl String apkName = file.getName() diff --git a/proguard-firebase-messaging.pro b/proguard-firebase-messaging.pro deleted file mode 100644 index 17af8ca94c..0000000000 --- a/proguard-firebase-messaging.pro +++ /dev/null @@ -1 +0,0 @@ --dontwarn com.google.firebase.analytics.connector.AnalyticsConnector \ No newline at end of file diff --git a/proguard-google-play-services.pro b/proguard-google-play-services.pro deleted file mode 100644 index ae70fc4e49..0000000000 --- a/proguard-google-play-services.pro +++ /dev/null @@ -1,19 +0,0 @@ -## Google Play Services 4.3.23 specific rules ## -## https://developer.android.com/google/play-services/setup.html#Proguard ## - --keep class * extends java.util.ListResourceBundle { - protected Object[][] getContents(); -} - --keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable { - public static final *** NULL; -} - --keepnames @com.google.android.gms.common.annotation.KeepName class * --keepclassmembernames class * { - @com.google.android.gms.common.annotation.KeepName *; -} - --keepnames class * implements android.os.Parcelable { - public static final ** CREATOR; -} \ No newline at end of file diff --git a/res/layout/conversation_item_footer.xml b/res/layout/conversation_item_footer.xml index f2d70188ab..740234f0e9 100644 --- a/res/layout/conversation_item_footer.xml +++ b/res/layout/conversation_item_footer.xml @@ -1,8 +1,6 @@ - - - + - - 1:312334754206:android:a9297b152879f266 - 312334754206 - 312334754206-dg1p1mtekis8ivja3ica50vonmrlunh4.apps.googleusercontent.com - https://api-project-312334754206.firebaseio.com - AIzaSyDrfzNAPBPzX6key51hqo3p5LZXF5Y-yxU - AIzaSyDrfzNAPBPzX6key51hqo3p5LZXF5Y-yxU - api-project-312334754206 - \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/ApplicationContext.java b/src/org/thoughtcrime/securesms/ApplicationContext.java index f8eed2a13d..ccef1114d2 100644 --- a/src/org/thoughtcrime/securesms/ApplicationContext.java +++ b/src/org/thoughtcrime/securesms/ApplicationContext.java @@ -16,7 +16,6 @@ */ package org.thoughtcrime.securesms; -import android.annotation.SuppressLint; import android.arch.lifecycle.DefaultLifecycleObserver; import android.arch.lifecycle.LifecycleOwner; import android.arch.lifecycle.ProcessLifecycleOwner; @@ -31,8 +30,6 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.multidex.MultiDexApplication; -import com.google.android.gms.security.ProviderInstaller; - import org.conscrypt.Conscrypt; import org.jetbrains.annotations.NotNull; import org.signal.aesgcmprovider.AesGcmProvider; @@ -53,7 +50,6 @@ import org.thoughtcrime.securesms.jobmanager.JobManager; import org.thoughtcrime.securesms.jobmanager.impl.JsonDataSerializer; import org.thoughtcrime.securesms.jobs.CreateSignedPreKeyJob; import org.thoughtcrime.securesms.jobs.FastJobStorage; -import org.thoughtcrime.securesms.jobs.FcmRefreshJob; import org.thoughtcrime.securesms.jobs.JobManagerFactories; import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob; import org.thoughtcrime.securesms.jobs.PushContentReceiveJob; @@ -115,7 +111,6 @@ import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.concurrent.TimeUnit; import dagger.ObjectGraph; import kotlin.Unit; @@ -176,10 +171,8 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc initializeExpiringMessageManager(); initializeTypingStatusRepository(); initializeTypingStatusSender(); - initializeGcmCheck(); initializeSignedPreKeyCheck(); initializePeriodicTasks(); - initializeCircumvention(); initializeWebRtc(); initializePendingMessages(); initializeUnidentifiedDeliveryAbilityRefresh(); @@ -194,6 +187,9 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc if (userHexEncodedPublicKey != null) { if (TextSecurePreferences.getNeedsIsRevokedSlaveDeviceCheck(this)) { MultiDeviceUtilities.checkIsRevokedSlaveDevice(this); + } else { + // We always update our current device links onto the server in case we failed to do so upon linking + MultiDeviceUtilities.updateDeviceLinksOnServer(this); } } } @@ -337,16 +333,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc this.objectGraph = ObjectGraph.create(communicationModule, new AxolotlStorageModule(this)); } - private void initializeGcmCheck() { - if (TextSecurePreferences.isPushRegistered(this)) { - long nextSetTime = TextSecurePreferences.getFcmTokenLastSetTime(this) + TimeUnit.HOURS.toMillis(6); - - if (TextSecurePreferences.getFcmToken(this) == null || nextSetTime <= System.currentTimeMillis()) { - this.jobManager.add(new FcmRefreshJob()); - } - } - } - private void initializeSignedPreKeyCheck() { if (!TextSecurePreferences.isSignedPreKeyRegistered(this)) { jobManager.add(new CreateSignedPreKeyJob(this)); @@ -413,25 +399,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc } } - @SuppressLint("StaticFieldLeak") - private void initializeCircumvention() { - AsyncTask task = new AsyncTask() { - @Override - protected Void doInBackground(Void... params) { - if (new SignalServiceNetworkAccess(ApplicationContext.this).isCensored(ApplicationContext.this)) { - try { - ProviderInstaller.installIfNeeded(ApplicationContext.this); - } catch (Throwable t) { - Log.w(TAG, t); - } - } - return null; - } - }; - - task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - } - private void executePendingContactSync() { if (TextSecurePreferences.needsFullContactSync(this)) { ApplicationContext.getInstance(this).getJobManager().add(new MultiDeviceContactUpdateJob(this, true)); diff --git a/src/org/thoughtcrime/securesms/PlayServicesProblemActivity.java b/src/org/thoughtcrime/securesms/PlayServicesProblemActivity.java deleted file mode 100644 index 216fab99f3..0000000000 --- a/src/org/thoughtcrime/securesms/PlayServicesProblemActivity.java +++ /dev/null @@ -1,30 +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.os.Bundle; -import android.support.v4.app.FragmentActivity; - -public class PlayServicesProblemActivity extends FragmentActivity { - - @Override - public void onCreate(Bundle bundle) { - super.onCreate(bundle); - PlayServicesProblemFragment fragment = new PlayServicesProblemFragment(); - fragment.show(getSupportFragmentManager(), "dialog"); - } -} diff --git a/src/org/thoughtcrime/securesms/PlayServicesProblemFragment.java b/src/org/thoughtcrime/securesms/PlayServicesProblemFragment.java deleted file mode 100644 index 6931e8430b..0000000000 --- a/src/org/thoughtcrime/securesms/PlayServicesProblemFragment.java +++ /dev/null @@ -1,67 +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.app.Activity; -import android.app.Dialog; -import android.content.DialogInterface; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.DialogFragment; -import android.support.v7.app.AlertDialog; - -import com.google.android.gms.common.GoogleApiAvailability; - -import network.loki.messenger.R; - -public class PlayServicesProblemFragment extends DialogFragment { - - @Override - public @NonNull Dialog onCreateDialog(@Nullable Bundle bundle) { - int code = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(getActivity()); - Dialog dialog = GoogleApiAvailability.getInstance().getErrorDialog(getActivity(), code, 9111); - - if (dialog == null) { - return new AlertDialog.Builder(requireActivity()) - .setNegativeButton(android.R.string.ok, null) - .setMessage(R.string.PlayServicesProblemFragment_the_version_of_google_play_services_you_have_installed_is_not_functioning) - .create(); - } else { - return dialog; - } - } - - @Override - public void onCancel(DialogInterface dialog) { - super.onCancel(dialog); - finish(); - } - - @Override - public void onDismiss(DialogInterface dialog) { - super.onDismiss(dialog); - finish(); - } - - private void finish() { - Activity activity = getActivity(); - if (activity != null) activity.finish(); - } - -} diff --git a/src/org/thoughtcrime/securesms/RegistrationActivity.java b/src/org/thoughtcrime/securesms/RegistrationActivity.java index b4c41c6b29..ff09e7ed93 100644 --- a/src/org/thoughtcrime/securesms/RegistrationActivity.java +++ b/src/org/thoughtcrime/securesms/RegistrationActivity.java @@ -3,10 +3,8 @@ package org.thoughtcrime.securesms; import android.Manifest; import android.animation.Animator; import android.annotation.SuppressLint; -import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.os.AsyncTask; import android.os.Bundle; import android.support.annotation.NonNull; @@ -29,17 +27,6 @@ import android.widget.TextView; import android.widget.Toast; import com.dd.CircularProgressButton; -import com.google.android.gms.auth.api.phone.SmsRetriever; -import com.google.android.gms.auth.api.phone.SmsRetrieverClient; -import com.google.android.gms.common.ConnectionResult; -import com.google.android.gms.common.GoogleApiAvailability; -import com.google.android.gms.common.api.CommonStatusCodes; -import com.google.android.gms.common.api.Status; -import com.google.android.gms.tasks.Task; -import com.google.i18n.phonenumbers.AsYouTypeFormatter; -import com.google.i18n.phonenumbers.NumberParseException; -import com.google.i18n.phonenumbers.PhoneNumberUtil; -import com.google.i18n.phonenumbers.Phonenumber; import net.sqlcipher.database.SQLiteDatabase; @@ -62,7 +49,6 @@ import org.thoughtcrime.securesms.database.Address; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.IdentityDatabase; import org.thoughtcrime.securesms.database.NoExternalStorageException; -import org.thoughtcrime.securesms.gcm.FcmUtil; import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob; import org.thoughtcrime.securesms.jobs.RotateCertificateJob; import org.thoughtcrime.securesms.lock.RegistrationLockReminders; @@ -73,12 +59,9 @@ import org.thoughtcrime.securesms.push.AccountManagerFactory; import org.thoughtcrime.securesms.registration.CaptchaActivity; import org.thoughtcrime.securesms.service.DirectoryRefreshListener; import org.thoughtcrime.securesms.service.RotateSignedPreKeyListener; -import org.thoughtcrime.securesms.service.VerificationCodeParser; import org.thoughtcrime.securesms.util.BackupUtil; import org.thoughtcrime.securesms.util.DateUtils; import org.thoughtcrime.securesms.util.Dialogs; -import org.thoughtcrime.securesms.util.PlayServicesUtil; -import org.thoughtcrime.securesms.util.PlayServicesUtil.PlayServicesStatus; import org.thoughtcrime.securesms.util.ServiceUtil; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.Util; @@ -121,7 +104,6 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif private static final String TAG = RegistrationActivity.class.getSimpleName(); - private AsYouTypeFormatter countryFormatter; private ArrayAdapter countrySpinnerAdapter; private Spinner countrySpinner; private LabeledEditText countryCode; @@ -149,7 +131,6 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif private VerificationPinKeyboard keyboard; private VerificationCodeView verificationCodeView; private RegistrationState registrationState; - private SmsRetrieverReceiver smsRetrieverReceiver; private SignalServiceAccountManager accountManager; private int debugTapCounter; @@ -163,13 +144,11 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif initializeSpinner(); initializeNumber(); initializeBackupDetection(); - initializeChallengeListener(); } @Override public void onDestroy() { super.onDestroy(); - shutdownChallengeListener(); markAsVerifying(false); EventBus.getDefault().unregister(this); } @@ -179,7 +158,6 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif if (requestCode == PICK_COUNTRY && resultCode == RESULT_OK && data != null) { this.countryCode.setText(String.valueOf(data.getIntExtra("country_code", 1))); setCountryDisplay(data.getStringExtra("country_name")); - setCountryFormatter(data.getIntExtra("country_code", 1)); } else if (requestCode == CAPTCHA && resultCode == RESULT_OK && data != null) { registrationState = new RegistrationState(Optional.fromNullable(data.getStringExtra(CaptchaActivity.KEY_TOKEN)), registrationState); @@ -286,24 +264,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif }); } - @SuppressLint("MissingPermission") private void initializeNumber() { - Optional localNumber = Optional.absent(); - - if (Permissions.hasAll(this, Manifest.permission.READ_PHONE_STATE)) { - localNumber = Util.getDeviceNumber(this); - } - - if (localNumber.isPresent()) { - this.countryCode.setText(String.valueOf(localNumber.get().getCountryCode())); - this.number.setText(String.valueOf(localNumber.get().getNationalNumber())); - } else { - Optional simCountryIso = Util.getSimCountryIso(this); - - if (simCountryIso.isPresent() && !TextUtils.isEmpty(simCountryIso.get())) { - this.countryCode.setText(String.valueOf(PhoneNumberUtil.getInstance().getCountryCodeForRegion(simCountryIso.get()))); - } - } } @SuppressLint("StaticFieldLeak") @@ -338,14 +299,6 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif this.countrySpinnerAdapter.add(value); } - private void setCountryFormatter(int countryCode) { - PhoneNumberUtil util = PhoneNumberUtil.getInstance(); - String regionCode = util.getRegionCodeForCountryCode(countryCode); - - if (regionCode == null) this.countryFormatter = null; - else this.countryFormatter = util.getAsYouTypeFormatter(regionCode); - } - private String getConfiguredE164Number() { return PhoneNumberFormatter.formatE164(countryCode.getText().toString(), number.getText().toString()); @@ -436,20 +389,6 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif Dialogs.showAlertDialog(this, getString(R.string.RegistrationActivity_invalid_number), String.format(getString(R.string.RegistrationActivity_the_number_you_specified_s_is_invalid), e164number)); - return; - } - - PlayServicesStatus gcmStatus = PlayServicesUtil.getPlayServicesStatus(this); - - if (gcmStatus == PlayServicesStatus.SUCCESS) { - handleRequestVerification(e164number, true); - } else if (gcmStatus == PlayServicesStatus.MISSING) { - handlePromptForNoPlayServices(e164number); - } else if (gcmStatus == PlayServicesStatus.NEEDS_UPDATE) { - GoogleApiAvailability.getInstance().getErrorDialog(this, ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED, 0).show(); - } else { - Dialogs.showAlertDialog(this, getString(R.string.RegistrationActivity_play_services_error), - getString(R.string.RegistrationActivity_google_play_services_is_updating_or_unavailable)); } } @@ -457,22 +396,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif createButton.setIndeterminateProgressMode(true); createButton.setProgress(50); - if (gcmSupported) { - SmsRetrieverClient client = SmsRetriever.getClient(this); - Task task = client.startSmsRetriever(); - - task.addOnSuccessListener(none -> { - Log.i(TAG, "Successfully registered SMS listener."); - requestVerificationCode(e164number, true, true); - }); - - task.addOnFailureListener(e -> { - Log.w(TAG, "Failed to register SMS listener.", e); - requestVerificationCode(e164number, true, false); - }); - } else { requestVerificationCode(e164number, false, false); - } } @SuppressLint("StaticFieldLeak") @@ -485,13 +409,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif String password = Util.getSecret(18); - Optional fcmToken; - - if (gcmSupported) { - fcmToken = FcmUtil.getToken(); - } else { - fcmToken = Optional.absent(); - } + Optional fcmToken = Optional.absent(); accountManager = AccountManagerFactory.createManager(RegistrationActivity.this, e164number, password); accountManager.requestSmsVerificationCode(smsRetrieverSupported, registrationState.captchaToken); @@ -939,19 +857,6 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif dialog.show(); } - private void initializeChallengeListener() { - smsRetrieverReceiver = new SmsRetrieverReceiver(); - IntentFilter filter = new IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION); - registerReceiver(smsRetrieverReceiver, filter); - } - - private void shutdownChallengeListener() { - if (smsRetrieverReceiver != null) { - unregisterReceiver(smsRetrieverReceiver); - smsRetrieverReceiver = null; - } - } - private void markAsVerifying(boolean verifying) { TextSecurePreferences.setVerifying(this, verifying); @@ -961,12 +866,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif } private String formatNumber(@NonNull String e164Number) { - try { - Phonenumber.PhoneNumber number = PhoneNumberUtil.getInstance().parse(e164Number, null); - return PhoneNumberUtil.getInstance().format(number, PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL); - } catch (NumberParseException e) { - return e164Number; - } + return e164Number; } private void onWrongNumberClicked() { @@ -980,53 +880,16 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif else restoreBackupProgress.setText(getString(R.string.RegistrationActivity_d_messages_so_far, event.getCount())); } - private class SmsRetrieverReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - Log.i(TAG, "SmsRetrieverReceiver received a broadcast..."); - - if (SmsRetriever.SMS_RETRIEVED_ACTION.equals(intent.getAction())) { - Bundle extras = intent.getExtras(); - Status status = (Status) extras.get(SmsRetriever.EXTRA_STATUS); - - switch (status.getStatusCode()) { - case CommonStatusCodes.SUCCESS: - Optional code = VerificationCodeParser.parse(context, (String) extras.get(SmsRetriever.EXTRA_SMS_MESSAGE)); - if (code.isPresent()) { - Log.i(TAG, "Received verification code."); - handleVerificationCodeReceived(code.get()); - } else { - Log.w(TAG, "Could not parse verification code."); - } - break; - case CommonStatusCodes.TIMEOUT: - Log.w(TAG, "Hit a timeout waiting for the SMS to arrive."); - break; - } - } else { - Log.w(TAG, "SmsRetrieverReceiver received the wrong action?"); - } - } - } - private class CountryCodeChangedListener implements TextWatcher { @Override public void afterTextChanged(Editable s) { if (TextUtils.isEmpty(s) || !TextUtils.isDigitsOnly(s)) { setCountryDisplay(getString(R.string.RegistrationActivity_select_your_country)); - countryFormatter = null; return; } int countryCode = Integer.parseInt(s.toString()); - String regionCode = PhoneNumberUtil.getInstance().getRegionCodeForCountryCode(countryCode); - - setCountryFormatter(countryCode); - setCountryDisplay(PhoneNumberFormatter.getRegionDisplayName(regionCode)); - - if (!TextUtils.isEmpty(regionCode) && !regionCode.equals("ZZ")) { - number.requestFocus(); - } + setCountryDisplay("N/A"); } @Override @@ -1042,24 +905,6 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif @Override public void afterTextChanged(Editable s) { - if (countryFormatter == null) - return; - - if (TextUtils.isEmpty(s)) - return; - - countryFormatter.clear(); - - String number = s.toString().replaceAll("[^\\d.]", ""); - String formattedNumber = null; - - for (int i=0;i subscriptionInfo = subscriptionManager.getActiveSubscriptionInfo(messageRecord.getSubscriptionId()); - - if (subscriptionInfo.isPresent() && messageRecord.isOutgoing()) { - simView.setText(getContext().getString(R.string.ConversationItem_from_s, subscriptionInfo.get().getDisplayName())); - simView.setVisibility(View.VISIBLE); - } else if (subscriptionInfo.isPresent()) { - simView.setText(getContext().getString(R.string.ConversationItem_to_s, subscriptionInfo.get().getDisplayName())); - simView.setVisibility(View.VISIBLE); - } else { - simView.setVisibility(View.GONE); - } - } - } - @SuppressLint("StaticFieldLeak") private void presentTimer(@NonNull final MessageRecord messageRecord) { if (messageRecord.getExpiresIn() > 0 && !messageRecord.isPending()) { diff --git a/src/org/thoughtcrime/securesms/components/location/SignalMapView.java b/src/org/thoughtcrime/securesms/components/location/SignalMapView.java index 1b4eb113ab..9061021f32 100644 --- a/src/org/thoughtcrime/securesms/components/location/SignalMapView.java +++ b/src/org/thoughtcrime/securesms/components/location/SignalMapView.java @@ -7,26 +7,18 @@ import android.os.Build; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; -import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; -import com.google.android.gms.location.places.Place; -import com.google.android.gms.maps.CameraUpdateFactory; -import com.google.android.gms.maps.GoogleMap; -import com.google.android.gms.maps.MapView; -import com.google.android.gms.maps.OnMapReadyCallback; -import com.google.android.gms.maps.model.MarkerOptions; - -import network.loki.messenger.R; import org.thoughtcrime.securesms.util.ViewUtil; import org.thoughtcrime.securesms.util.concurrent.ListenableFuture; import org.thoughtcrime.securesms.util.concurrent.SettableFuture; +import network.loki.messenger.R; + public class SignalMapView extends LinearLayout { - private MapView mapView; private ImageView imageView; private TextView textView; @@ -49,7 +41,6 @@ public class SignalMapView extends LinearLayout { setOrientation(LinearLayout.VERTICAL); LayoutInflater.from(context).inflate(R.layout.signal_map_view, this, true); - this.mapView = ViewUtil.findById(this, R.id.map_view); this.imageView = ViewUtil.findById(this, R.id.image_view); this.textView = ViewUtil.findById(this, R.id.address_view); } @@ -57,39 +48,8 @@ public class SignalMapView extends LinearLayout { public ListenableFuture display(final SignalPlace place) { final SettableFuture future = new SettableFuture<>(); - this.mapView.onCreate(null); - this.mapView.onResume(); - - this.mapView.setVisibility(View.VISIBLE); this.imageView.setVisibility(View.GONE); - this.mapView.getMapAsync(new OnMapReadyCallback() { - @Override - public void onMapReady(final GoogleMap googleMap) { - googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(place.getLatLong(), 13)); - googleMap.addMarker(new MarkerOptions().position(place.getLatLong())); - googleMap.setBuildingsEnabled(true); - googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL); - googleMap.getUiSettings().setAllGesturesEnabled(false); - googleMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() { - @Override - public void onMapLoaded() { - googleMap.snapshot(new GoogleMap.SnapshotReadyCallback() { - @Override - public void onSnapshotReady(Bitmap bitmap) { - future.set(bitmap); - imageView.setImageBitmap(bitmap); - imageView.setVisibility(View.VISIBLE); - mapView.setVisibility(View.GONE); - mapView.onPause(); - mapView.onDestroy(); - } - }); - } - }); - } - }); - this.textView.setText(place.getDescription()); return future; diff --git a/src/org/thoughtcrime/securesms/components/location/SignalPlace.java b/src/org/thoughtcrime/securesms/components/location/SignalPlace.java index b5a2219ee0..0519e8d2c2 100644 --- a/src/org/thoughtcrime/securesms/components/location/SignalPlace.java +++ b/src/org/thoughtcrime/securesms/components/location/SignalPlace.java @@ -7,8 +7,6 @@ import android.text.TextUtils; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.android.gms.location.places.Place; -import com.google.android.gms.maps.model.LatLng; import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.util.JsonUtils; @@ -17,6 +15,22 @@ import java.io.IOException; public class SignalPlace { + /* Loki - Temporary Placeholders */ + class LatLng { + double latitude; + double longitude; + LatLng(double latitude, double longitude) { + this.latitude = latitude; + this.longitude = longitude; + } + } + + class Place { + public CharSequence getName() { return ""; } + public CharSequence getAddress() { return ""; } + LatLng getLatLng() { return new LatLng(0, 0); } + } + private static final String URL = "https://maps.google.com/maps"; private static final String TAG = SignalPlace.class.getSimpleName(); diff --git a/src/org/thoughtcrime/securesms/contacts/ContactsSyncAdapter.java b/src/org/thoughtcrime/securesms/contacts/ContactsSyncAdapter.java deleted file mode 100644 index 71d3b790d1..0000000000 --- a/src/org/thoughtcrime/securesms/contacts/ContactsSyncAdapter.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.thoughtcrime.securesms.contacts; - -import android.accounts.Account; -import android.content.AbstractThreadedSyncAdapter; -import android.content.ContentProviderClient; -import android.content.Context; -import android.content.SyncResult; -import android.os.Bundle; -import org.thoughtcrime.securesms.logging.Log; - -import org.thoughtcrime.securesms.util.DirectoryHelper; -import org.thoughtcrime.securesms.util.TextSecurePreferences; - -import java.io.IOException; - -public class ContactsSyncAdapter extends AbstractThreadedSyncAdapter { - - private static final String TAG = ContactsSyncAdapter.class.getSimpleName(); - - public ContactsSyncAdapter(Context context, boolean autoInitialize) { - super(context, autoInitialize); - } - - @Override - public void onPerformSync(Account account, Bundle extras, String authority, - ContentProviderClient provider, SyncResult syncResult) - { - Log.i(TAG, "onPerformSync(" + authority +")"); - - if (TextSecurePreferences.isPushRegistered(getContext())) { - try { - DirectoryHelper.refreshDirectory(getContext(), true); - } catch (IOException e) { - Log.w(TAG, e); - } - } - } - - @Override - public void onSyncCanceled() { - Log.w(TAG, "onSyncCanceled()"); - } - - @Override - public void onSyncCanceled(Thread thread) { - Log.w(TAG, "onSyncCanceled(" + thread + ")"); - } - -} diff --git a/src/org/thoughtcrime/securesms/contactshare/ContactUtil.java b/src/org/thoughtcrime/securesms/contactshare/ContactUtil.java index cb4985892a..fbb7ddd641 100644 --- a/src/org/thoughtcrime/securesms/contactshare/ContactUtil.java +++ b/src/org/thoughtcrime/securesms/contactshare/ContactUtil.java @@ -13,11 +13,7 @@ import android.support.v7.app.AlertDialog; import android.text.TextUtils; import com.annimon.stream.Stream; -import com.google.i18n.phonenumbers.NumberParseException; -import com.google.i18n.phonenumbers.PhoneNumberUtil; -import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; -import network.loki.messenger.R; import org.thoughtcrime.securesms.components.emoji.EmojiStrings; import org.thoughtcrime.securesms.contactshare.Contact.Email; import org.thoughtcrime.securesms.contactshare.Contact.Phone; @@ -34,6 +30,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; +import network.loki.messenger.R; + public final class ContactUtil { private static final String TAG = ContactUtil.class.getSimpleName(); @@ -102,13 +100,7 @@ public final class ContactUtil { } private static @NonNull String getPrettyPhoneNumber(@NonNull String phoneNumber, @NonNull Locale fallbackLocale) { - PhoneNumberUtil util = PhoneNumberUtil.getInstance(); - try { - PhoneNumber parsed = util.parse(phoneNumber, fallbackLocale.getISO3Country()); - return util.format(parsed, PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL); - } catch (NumberParseException e) { - return phoneNumber; - } + return phoneNumber; } public static @NonNull String getNormalizedPhoneNumber(@NonNull Context context, @NonNull String number) { diff --git a/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java b/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java index 35d2193a27..628e8c85ba 100644 --- a/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java +++ b/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java @@ -77,7 +77,6 @@ import android.widget.TextView; import android.widget.Toast; import com.annimon.stream.Stream; -import com.google.android.gms.location.places.ui.PlacePicker; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; @@ -133,7 +132,6 @@ import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DraftDatabase; import org.thoughtcrime.securesms.database.DraftDatabase.Draft; import org.thoughtcrime.securesms.database.DraftDatabase.Drafts; -import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.database.IdentityDatabase; import org.thoughtcrime.securesms.database.IdentityDatabase.IdentityRecord; import org.thoughtcrime.securesms.database.IdentityDatabase.VerifiedStatus; @@ -179,7 +177,6 @@ import org.thoughtcrime.securesms.mms.ImageSlide; import org.thoughtcrime.securesms.mms.LocationSlide; import org.thoughtcrime.securesms.mms.MediaConstraints; import org.thoughtcrime.securesms.mms.OutgoingExpirationUpdateMessage; -import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage; import org.thoughtcrime.securesms.mms.OutgoingMediaMessage; import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage; import org.thoughtcrime.securesms.mms.QuoteId; @@ -662,10 +659,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity recipient.addListener(this); fragment.reloadList(); break; + /* case PICK_LOCATION: SignalPlace place = new SignalPlace(PlacePicker.getPlace(data, this)); attachmentManager.setLocation(place, getCurrentMediaConstraints()); break; + */ case PICK_GIF: setMedia(data.getData(), MediaType.GIF, @@ -1240,15 +1239,13 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity } private boolean handleDisplayQuickContact() { - if (recipient.getAddress().isGroup()) return false; + return !recipient.getAddress().isGroup(); // if (recipient.getContactUri() != null) { // ContactsContract.QuickContact.showQuickContact(ConversationActivity.this, titleView, recipient.getContactUri(), ContactsContract.QuickContact.MODE_LARGE, null); // } else { // handleAddToContacts(); // } - - return true; } private void handleAddAttachment() { diff --git a/src/org/thoughtcrime/securesms/database/Address.java b/src/org/thoughtcrime/securesms/database/Address.java index 1286b4b302..d777b6e86b 100644 --- a/src/org/thoughtcrime/securesms/database/Address.java +++ b/src/org/thoughtcrime/securesms/database/Address.java @@ -10,12 +10,6 @@ import android.support.annotation.VisibleForTesting; import android.text.TextUtils; import android.util.Pair; -import com.google.i18n.phonenumbers.NumberParseException; -import com.google.i18n.phonenumbers.PhoneNumberUtil; -import com.google.i18n.phonenumbers.Phonenumber; -import com.google.i18n.phonenumbers.ShortNumberInfo; - -import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.util.DelimiterUtil; import org.thoughtcrime.securesms.util.GroupUtil; import org.thoughtcrime.securesms.util.NumberUtil; @@ -111,7 +105,7 @@ public class Address implements Parcelable, Comparable
{ public boolean isGroup() { return GroupUtil.isEncodedGroup(address); } - public boolean isSignalGroup() { return !isPublicChat() && !isRSSFeed(); } + public boolean isSignalGroup() { return GroupUtil.isSignalGroup(address); } public boolean isPublicChat() { return GroupUtil.isPublicChat(address); } @@ -200,19 +194,10 @@ public class Address implements Parcelable, Comparable
{ private final Optional localNumber; private final String localCountryCode; - private final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance(); private final Pattern ALPHA_PATTERN = Pattern.compile("[a-zA-Z]"); ExternalAddressFormatter(@NonNull String localNumberString) { - try { - Phonenumber.PhoneNumber libNumber = phoneNumberUtil.parse(localNumberString, null); - int countryCode = libNumber.getCountryCode(); - - this.localNumber = Optional.of(new PhoneNumber(localNumberString, countryCode, parseAreaCode(localNumberString, countryCode))); - this.localCountryCode = phoneNumberUtil.getRegionCodeForNumber(libNumber); - } catch (NumberParseException e) { - throw new AssertionError(e); - } + throw new AssertionError("Not Implemented"); } ExternalAddressFormatter(@NonNull String localCountryCode, boolean countryCode) { @@ -222,61 +207,7 @@ public class Address implements Parcelable, Comparable
{ public String format(@Nullable String number) { if (number == null) return "Unknown"; - if (GroupUtil.isEncodedGroup(number)) return number; - if (ALPHA_PATTERN.matcher(number).find()) return number.trim(); - - String bareNumber = number.replaceAll("[^0-9+]", ""); - - if (bareNumber.length() == 0) { - if (number.trim().length() == 0) return "Unknown"; - else return number.trim(); - } - - // libphonenumber doesn't seem to be correct for Germany and Finland - if (bareNumber.length() <= 6 && ("DE".equals(localCountryCode) || "FI".equals(localCountryCode) || "SK".equals(localCountryCode))) { - return bareNumber; - } - - // libphonenumber seems incorrect for Russia and a few other countries with 4 digit short codes. - if (bareNumber.length() <= 4 && !SHORT_COUNTRIES.contains(localCountryCode)) { - return bareNumber; - } - - if (isShortCode(bareNumber, localCountryCode)) { - return bareNumber; - } - - String processedNumber = applyAreaCodeRules(localNumber, bareNumber); - - try { - Phonenumber.PhoneNumber parsedNumber = phoneNumberUtil.parse(processedNumber, localCountryCode); - return phoneNumberUtil.format(parsedNumber, PhoneNumberUtil.PhoneNumberFormat.E164); - } catch (NumberParseException e) { - Log.w(TAG, e); - if (bareNumber.charAt(0) == '+') - return bareNumber; - - String localNumberImprecise = localNumber.isPresent() ? localNumber.get().getE164Number() : ""; - - if (localNumberImprecise.charAt(0) == '+') - localNumberImprecise = localNumberImprecise.substring(1); - - if (localNumberImprecise.length() == bareNumber.length() || bareNumber.length() > localNumberImprecise.length()) - return "+" + number; - - int difference = localNumberImprecise.length() - bareNumber.length(); - - return "+" + localNumberImprecise.substring(0, difference) + bareNumber; - } - } - - private boolean isShortCode(@NonNull String bareNumber, String localCountryCode) { - try { - Phonenumber.PhoneNumber parsedNumber = phoneNumberUtil.parse(bareNumber, localCountryCode); - return ShortNumberInfo.getInstance().isPossibleShortNumberForRegion(parsedNumber, localCountryCode); - } catch (NumberParseException e) { - return false; - } + return number; } private @Nullable String parseAreaCode(@NonNull String e164Number, int countryCode) { diff --git a/src/org/thoughtcrime/securesms/database/helpers/ClassicOpenHelper.java b/src/org/thoughtcrime/securesms/database/helpers/ClassicOpenHelper.java index 5ad89598cf..8eb29d3509 100644 --- a/src/org/thoughtcrime/securesms/database/helpers/ClassicOpenHelper.java +++ b/src/org/thoughtcrime/securesms/database/helpers/ClassicOpenHelper.java @@ -1,24 +1,16 @@ package org.thoughtcrime.securesms.database.helpers; -import android.Manifest; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteConstraintException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; -import android.net.Uri; -import android.provider.ContactsContract; import android.support.annotation.Nullable; import android.text.TextUtils; -import org.thoughtcrime.securesms.logging.Log; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.i18n.phonenumbers.NumberParseException; -import com.google.i18n.phonenumbers.PhoneNumberUtil; -import com.google.i18n.phonenumbers.Phonenumber; -import com.google.i18n.phonenumbers.ShortNumberInfo; import org.thoughtcrime.securesms.DatabaseUpgradeActivity; import org.thoughtcrime.securesms.crypto.AttachmentSecret; @@ -26,7 +18,6 @@ import org.thoughtcrime.securesms.crypto.ClassicDecryptingPartInputStream; import org.thoughtcrime.securesms.crypto.MasterCipher; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecretUtil; -import org.thoughtcrime.securesms.database.Address; import org.thoughtcrime.securesms.database.AttachmentDatabase; import org.thoughtcrime.securesms.database.DraftDatabase; import org.thoughtcrime.securesms.database.GroupDatabase; @@ -37,8 +28,8 @@ import org.thoughtcrime.securesms.database.PushDatabase; import org.thoughtcrime.securesms.database.RecipientDatabase; import org.thoughtcrime.securesms.database.SmsDatabase; import org.thoughtcrime.securesms.database.ThreadDatabase; +import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.notifications.MessageNotifier; -import org.thoughtcrime.securesms.permissions.Permissions; import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.DelimiterUtil; import org.thoughtcrime.securesms.util.Hex; @@ -1385,71 +1376,18 @@ public class ClassicOpenHelper extends SQLiteOpenHelper { add("AC"); }}; - private final Phonenumber.PhoneNumber localNumber; private final String localNumberString; - private final String localCountryCode; - private final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance(); private final Pattern ALPHA_PATTERN = Pattern.compile("[a-zA-Z]"); public NumberMigrator(String localNumber) { - try { - this.localNumberString = localNumber; - this.localNumber = phoneNumberUtil.parse(localNumber, null); - this.localCountryCode = phoneNumberUtil.getRegionCodeForNumber(this.localNumber); - } catch (NumberParseException e) { - throw new AssertionError(e); - } + this.localNumberString = localNumber; } public String migrate(@Nullable String number) { - if (number == null) return "Unknown"; - if (number.startsWith("__textsecure_group__!")) return number; - if (ALPHA_PATTERN.matcher(number).find()) return number.trim(); - - String bareNumber = number.replaceAll("[^0-9+]", ""); - - if (bareNumber.length() == 0) { - if (TextUtils.isEmpty(number.trim())) return "Unknown"; - else return number.trim(); - } - - // libphonenumber doesn't seem to be correct for Germany and Finland - if (bareNumber.length() <= 6 && ("DE".equals(localCountryCode) || "FI".equals(localCountryCode) || "SK".equals(localCountryCode))) { - return bareNumber; - } - - // libphonenumber seems incorrect for Russia and a few other countries with 4 digit short codes. - if (bareNumber.length() <= 4 && !SHORT_COUNTRIES.contains(localCountryCode)) { - return bareNumber; - } - - try { - Phonenumber.PhoneNumber parsedNumber = phoneNumberUtil.parse(bareNumber, localCountryCode); - - if (ShortNumberInfo.getInstance().isPossibleShortNumberForRegion(parsedNumber, localCountryCode)) { - return bareNumber; - } - - return phoneNumberUtil.format(parsedNumber, PhoneNumberUtil.PhoneNumberFormat.E164); - } catch (NumberParseException e) { - Log.w(TAG, e); - if (bareNumber.charAt(0) == '+') - return bareNumber; - - String localNumberImprecise = localNumberString; - - if (localNumberImprecise.charAt(0) == '+') - localNumberImprecise = localNumberImprecise.substring(1); - - if (localNumberImprecise.length() == bareNumber.length() || bareNumber.length() > localNumberImprecise.length()) - return "+" + number; - - int difference = localNumberImprecise.length() - bareNumber.length(); - - return "+" + localNumberImprecise.substring(0, difference) + bareNumber; - } + if (number == null) return "Unknown"; + return number; } } diff --git a/src/org/thoughtcrime/securesms/database/loaders/CountryListLoader.java b/src/org/thoughtcrime/securesms/database/loaders/CountryListLoader.java index 22b85a19a8..2c36df2a59 100644 --- a/src/org/thoughtcrime/securesms/database/loaders/CountryListLoader.java +++ b/src/org/thoughtcrime/securesms/database/loaders/CountryListLoader.java @@ -1,19 +1,12 @@ package org.thoughtcrime.securesms.database.loaders; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - import android.content.Context; import android.support.v4.content.AsyncTaskLoader; - -import com.google.i18n.phonenumbers.PhoneNumberUtil; -import org.whispersystems.signalservice.api.util.PhoneNumberFormatter; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Map; public class CountryListLoader extends AsyncTaskLoader>> { @@ -23,19 +16,7 @@ public class CountryListLoader extends AsyncTaskLoader> loadInBackground() { - Set regions = PhoneNumberUtil.getInstance().getSupportedRegions(); - ArrayList> results = new ArrayList>(regions.size()); - - for (String region : regions) { - Map data = new HashMap(2); - data.put("country_name", PhoneNumberFormatter.getRegionDisplayName(region)); - data.put("country_code", "+" +PhoneNumberUtil.getInstance().getCountryCodeForRegion(region)); - results.add(data); - } - - Collections.sort(results, new RegionComparator()); - - return results; + return new ArrayList<>(); } private static class RegionComparator implements Comparator> { diff --git a/src/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java b/src/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java index c59224d481..1e7a3dfb4a 100644 --- a/src/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java +++ b/src/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java @@ -9,13 +9,11 @@ import org.thoughtcrime.securesms.DeviceListFragment; import org.thoughtcrime.securesms.crypto.storage.SignalProtocolStoreImpl; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.events.ReminderUpdateEvent; -import org.thoughtcrime.securesms.gcm.FcmService; import org.thoughtcrime.securesms.jobs.AttachmentDownloadJob; import org.thoughtcrime.securesms.jobs.AttachmentUploadJob; import org.thoughtcrime.securesms.jobs.AvatarDownloadJob; import org.thoughtcrime.securesms.jobs.CleanPreKeysJob; import org.thoughtcrime.securesms.jobs.CreateSignedPreKeyJob; -import org.thoughtcrime.securesms.jobs.FcmRefreshJob; import org.thoughtcrime.securesms.jobs.MultiDeviceBlockedUpdateJob; import org.thoughtcrime.securesms.jobs.MultiDeviceConfigurationUpdateJob; import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob; @@ -48,6 +46,7 @@ import org.thoughtcrime.securesms.jobs.TypingSendJob; import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository; import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.loki.LokiSessionResetImplementation; +import org.thoughtcrime.securesms.loki.MultiDeviceOpenGroupUpdateJob; import org.thoughtcrime.securesms.loki.PushMessageSyncSendJob; import org.thoughtcrime.securesms.preferences.AppProtectionPreferenceFragment; import org.thoughtcrime.securesms.push.MessageSenderEventListener; @@ -86,7 +85,6 @@ import network.loki.messenger.BuildConfig; MultiDeviceBlockedUpdateJob.class, DeviceListFragment.class, RefreshAttributesJob.class, - FcmRefreshJob.class, RequestGroupInfoJob.class, PushGroupUpdateJob.class, AvatarDownloadJob.class, @@ -99,7 +97,6 @@ import network.loki.messenger.BuildConfig; MultiDeviceProfileKeyUpdateJob.class, SendReadReceiptJob.class, AppProtectionPreferenceFragment.class, - FcmService.class, RotateCertificateJob.class, SendDeliveryReceiptJob.class, RotateProfileKeyJob.class, @@ -115,7 +112,8 @@ import network.loki.messenger.BuildConfig; MultiDeviceStickerPackOperationJob.class, MultiDeviceStickerPackSyncJob.class, LinkPreviewRepository.class, - PushMessageSyncSendJob.class}) + PushMessageSyncSendJob.class, + MultiDeviceOpenGroupUpdateJob.class}) public class SignalCommunicationModule { diff --git a/src/org/thoughtcrime/securesms/gcm/FcmService.java b/src/org/thoughtcrime/securesms/gcm/FcmService.java deleted file mode 100644 index cbb3da3807..0000000000 --- a/src/org/thoughtcrime/securesms/gcm/FcmService.java +++ /dev/null @@ -1,158 +0,0 @@ -package org.thoughtcrime.securesms.gcm; - -import android.content.Context; -import android.os.PowerManager; -import android.support.annotation.NonNull; - -import com.google.firebase.messaging.FirebaseMessagingService; -import com.google.firebase.messaging.RemoteMessage; - -import org.thoughtcrime.securesms.ApplicationContext; -import network.loki.messenger.R; -import org.thoughtcrime.securesms.dependencies.InjectableType; -import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; -import org.thoughtcrime.securesms.jobs.FcmRefreshJob; -import org.thoughtcrime.securesms.jobs.PushNotificationReceiveJob; -import org.thoughtcrime.securesms.logging.Log; -import org.thoughtcrime.securesms.notifications.NotificationChannels; -import org.thoughtcrime.securesms.service.GenericForegroundService; -import org.thoughtcrime.securesms.util.PowerManagerCompat; -import org.thoughtcrime.securesms.util.ServiceUtil; -import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.thoughtcrime.securesms.util.WakeLockUtil; -import org.thoughtcrime.securesms.util.concurrent.SignalExecutors; -import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; -import org.whispersystems.signalservice.internal.util.Util; - -import java.io.IOException; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Executor; -import java.util.concurrent.atomic.AtomicBoolean; - -import javax.inject.Inject; - -public class FcmService extends FirebaseMessagingService implements InjectableType { - - private static final String TAG = FcmService.class.getSimpleName(); - - private static final Executor MESSAGE_EXECUTOR = SignalExecutors.newCachedSingleThreadExecutor("FcmMessageProcessing"); - private static final String WAKE_LOCK_TAG = "FcmMessageProcessing"; - - @Inject SignalServiceMessageReceiver messageReceiver; - - private static int activeCount; - - @Override - public void onMessageReceived(RemoteMessage remoteMessage) { - Log.i(TAG, "FCM message... Original Priority: " + remoteMessage.getOriginalPriority() + ", Actual Priority: " + remoteMessage.getPriority()); - ApplicationContext.getInstance(getApplicationContext()).injectDependencies(this); - - WakeLockUtil.runWithLock(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK, 60000, WAKE_LOCK_TAG, () -> { - handleReceivedNotification(getApplicationContext()); - }); - } - - @Override - public void onNewToken(String token) { - Log.i(TAG, "onNewToken()"); - - if (!TextSecurePreferences.isPushRegistered(getApplicationContext())) { - Log.i(TAG, "Got a new FCM token, but the user isn't registered."); - return; - } - - ApplicationContext.getInstance(getApplicationContext()) - .getJobManager() - .add(new FcmRefreshJob()); - } - - private void handleReceivedNotification(Context context) { - if (!incrementActiveGcmCount()) { - Log.i(TAG, "Skipping FCM processing -- there's already one enqueued."); - return; - } - - TextSecurePreferences.setNeedsMessagePull(context, true); - - long startTime = System.currentTimeMillis(); - PowerManager powerManager = ServiceUtil.getPowerManager(getApplicationContext()); - boolean doze = PowerManagerCompat.isDeviceIdleMode(powerManager); - boolean network = new NetworkConstraint.Factory(ApplicationContext.getInstance(context)).create().isMet(); - - final Object foregroundLock = new Object(); - final AtomicBoolean foregroundRunning = new AtomicBoolean(false); - final AtomicBoolean taskCompleted = new AtomicBoolean(false); - final CountDownLatch latch = new CountDownLatch(1); - - if (doze || !network) { - Log.i(TAG, "Starting a foreground task because we may be operating in a constrained environment. Doze: " + doze + " Network: " + network); - showForegroundNotification(context); - foregroundRunning.set(true); - latch.countDown(); - } - - MESSAGE_EXECUTOR.execute(() -> { - try { - new PushNotificationReceiveJob(context).pullAndProcessMessages(messageReceiver, TAG, startTime); - } catch (IOException e) { - Log.i(TAG, "Failed to retrieve the envelope. Scheduling on JobManager.", e); - ApplicationContext.getInstance(context) - .getJobManager() - .add(new PushNotificationReceiveJob(context)); - } finally { - synchronized (foregroundLock) { - if (foregroundRunning.getAndSet(false)) { - GenericForegroundService.stopForegroundTask(context); - } else { - latch.countDown(); - } - taskCompleted.set(true); - } - - decrementActiveGcmCount(); - Log.i(TAG, "Processing complete."); - } - }); - - if (!foregroundRunning.get()) { - new Thread("FcmForegroundServiceTimer") { - @Override - public void run() { - Util.sleep(7000); - synchronized (foregroundLock) { - if (!taskCompleted.get() && !foregroundRunning.getAndSet(true)) { - Log.i(TAG, "Starting a foreground task because the job is running long."); - showForegroundNotification(context); - latch.countDown(); - } - } - } - }.start(); - } - - try { - latch.await(); - } catch (InterruptedException e) { - Log.w(TAG, "Latch was interrupted.", e); - } - } - - private void showForegroundNotification(@NonNull Context context) { - GenericForegroundService.startForegroundTask(context, - context.getString(R.string.GcmBroadcastReceiver_retrieving_a_message), - NotificationChannels.OTHER, - R.drawable.ic_signal_downloading); - } - - private static synchronized boolean incrementActiveGcmCount() { - if (activeCount < 2) { - activeCount++; - return true; - } - return false; - } - - private static synchronized void decrementActiveGcmCount() { - activeCount--; - } -} diff --git a/src/org/thoughtcrime/securesms/gcm/FcmUtil.java b/src/org/thoughtcrime/securesms/gcm/FcmUtil.java deleted file mode 100644 index 2a2e2b04d5..0000000000 --- a/src/org/thoughtcrime/securesms/gcm/FcmUtil.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.thoughtcrime.securesms.gcm; - -import android.support.annotation.WorkerThread; -import android.text.TextUtils; - -import com.google.firebase.iid.FirebaseInstanceId; - -import org.thoughtcrime.securesms.logging.Log; -import org.whispersystems.libsignal.util.guava.Optional; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicReference; - -public final class FcmUtil { - - private static final String TAG = FcmUtil.class.getSimpleName(); - - /** - * Retrieves the current FCM token. If one isn't available, it'll be generated. - */ - @WorkerThread - public static Optional getToken() { - CountDownLatch latch = new CountDownLatch(1); - AtomicReference token = new AtomicReference<>(null); - - FirebaseInstanceId.getInstance().getInstanceId().addOnCompleteListener(task -> { - if (task.isSuccessful() && task.getResult() != null && !TextUtils.isEmpty(task.getResult().getToken())) { - token.set(task.getResult().getToken()); - } else { - Log.w(TAG, "Failed to get the token.", task.getException()); - } - - latch.countDown(); - }); - - try { - latch.await(); - } catch (InterruptedException e) { - Log.w(TAG, "Was interrupted while waiting for the token."); - } - - return Optional.fromNullable(token.get()); - } -} diff --git a/src/org/thoughtcrime/securesms/jobmanager/migration/WorkManagerFactoryMappings.java b/src/org/thoughtcrime/securesms/jobmanager/migration/WorkManagerFactoryMappings.java index 156fdf9b0f..4957ebd72d 100644 --- a/src/org/thoughtcrime/securesms/jobmanager/migration/WorkManagerFactoryMappings.java +++ b/src/org/thoughtcrime/securesms/jobmanager/migration/WorkManagerFactoryMappings.java @@ -9,7 +9,6 @@ import org.thoughtcrime.securesms.jobs.AvatarDownloadJob; import org.thoughtcrime.securesms.jobs.CleanPreKeysJob; import org.thoughtcrime.securesms.jobs.CreateSignedPreKeyJob; import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob; -import org.thoughtcrime.securesms.jobs.FcmRefreshJob; import org.thoughtcrime.securesms.jobs.LocalBackupJob; import org.thoughtcrime.securesms.jobs.MmsDownloadJob; import org.thoughtcrime.securesms.jobs.MmsReceiveJob; @@ -59,7 +58,6 @@ public class WorkManagerFactoryMappings { put(CleanPreKeysJob.class.getName(), CleanPreKeysJob.KEY); put(CreateSignedPreKeyJob.class.getName(), CreateSignedPreKeyJob.KEY); put(DirectoryRefreshJob.class.getName(), DirectoryRefreshJob.KEY); - put(FcmRefreshJob.class.getName(), FcmRefreshJob.KEY); put(LocalBackupJob.class.getName(), LocalBackupJob.KEY); put(MmsDownloadJob.class.getName(), MmsDownloadJob.KEY); put(MmsReceiveJob.class.getName(), MmsReceiveJob.KEY); diff --git a/src/org/thoughtcrime/securesms/jobs/FcmRefreshJob.java b/src/org/thoughtcrime/securesms/jobs/FcmRefreshJob.java deleted file mode 100644 index 2f63316d2a..0000000000 --- a/src/org/thoughtcrime/securesms/jobs/FcmRefreshJob.java +++ /dev/null @@ -1,151 +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.jobs; - -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.graphics.BitmapFactory; -import android.support.annotation.NonNull; -import android.support.v4.app.NotificationCompat; - -import com.google.android.gms.common.ConnectionResult; -import com.google.android.gms.common.GoogleApiAvailability; - -import org.thoughtcrime.securesms.gcm.FcmUtil; -import org.thoughtcrime.securesms.jobmanager.Data; -import org.thoughtcrime.securesms.jobmanager.Job; -import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; -import org.thoughtcrime.securesms.logging.Log; - -import org.thoughtcrime.securesms.PlayServicesProblemActivity; -import network.loki.messenger.R; -import org.thoughtcrime.securesms.dependencies.InjectableType; -import org.thoughtcrime.securesms.notifications.NotificationChannels; -import org.thoughtcrime.securesms.transport.RetryLaterException; -import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.whispersystems.libsignal.util.guava.Optional; -import org.whispersystems.signalservice.api.SignalServiceAccountManager; -import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; - -import java.io.IOException; -import java.util.concurrent.TimeUnit; - -import javax.inject.Inject; - -public class FcmRefreshJob extends BaseJob implements InjectableType { - - public static final String KEY = "FcmRefreshJob"; - - private static final String TAG = FcmRefreshJob.class.getSimpleName(); - - @Inject SignalServiceAccountManager textSecureAccountManager; - - public FcmRefreshJob() { - this(new Job.Parameters.Builder() - .setQueue("FcmRefreshJob") - .addConstraint(NetworkConstraint.KEY) - .setMaxAttempts(1) - .setLifespan(TimeUnit.MINUTES.toMillis(5)) - .setMaxInstances(1) - .build()); - } - - private FcmRefreshJob(@NonNull Job.Parameters parameters) { - super(parameters); - } - - @Override - public @NonNull Data serialize() { - return Data.EMPTY; - } - - @Override - public @NonNull String getFactoryKey() { - return KEY; - } - - @Override - public void onRun() throws Exception { - if (TextSecurePreferences.isFcmDisabled(context)) return; - - Log.i(TAG, "Reregistering FCM..."); - - int result = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context); - - if (result != ConnectionResult.SUCCESS) { - notifyFcmFailure(); - } else { - Optional token = FcmUtil.getToken(); - - if (token.isPresent()) { - String oldToken = TextSecurePreferences.getFcmToken(context); - - if (!token.get().equals(oldToken)) { - int oldLength = oldToken != null ? oldToken.length() : -1; - Log.i(TAG, "Token changed. oldLength: " + oldLength + " newLength: " + token.get().length()); - } else { - Log.i(TAG, "Token didn't change."); - } - - textSecureAccountManager.setGcmId(token); - TextSecurePreferences.setFcmToken(context, token.get()); - TextSecurePreferences.setFcmTokenLastSetTime(context, System.currentTimeMillis()); - TextSecurePreferences.setWebsocketRegistered(context, true); - } else { - throw new RetryLaterException(new IOException("Failed to retrieve a token.")); - } - } - } - - @Override - public void onCanceled() { - Log.w(TAG, "GCM reregistration failed after retry attempt exhaustion!"); - } - - @Override - public boolean onShouldRetry(@NonNull Exception throwable) { - if (throwable instanceof NonSuccessfulResponseCodeException) return false; - return true; - } - - private void notifyFcmFailure() { - Intent intent = new Intent(context, PlayServicesProblemActivity.class); - PendingIntent pendingIntent = PendingIntent.getActivity(context, 1122, intent, PendingIntent.FLAG_CANCEL_CURRENT); - NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NotificationChannels.FAILURES); - - builder.setSmallIcon(R.drawable.ic_notification); - builder.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), - R.drawable.ic_action_warning_red)); - builder.setContentTitle(context.getString(R.string.GcmRefreshJob_Permanent_Signal_communication_failure)); - builder.setContentText(context.getString(R.string.GcmRefreshJob_Signal_was_unable_to_register_with_Google_Play_Services)); - builder.setTicker(context.getString(R.string.GcmRefreshJob_Permanent_Signal_communication_failure)); - builder.setVibrate(new long[] {0, 1000}); - builder.setContentIntent(pendingIntent); - - ((NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE)) - .notify(12, builder.build()); - } - - public static final class Factory implements Job.Factory { - @Override - public @NonNull FcmRefreshJob create(@NonNull Parameters parameters, @NonNull Data data) { - return new FcmRefreshJob(parameters); - } - } -} diff --git a/src/org/thoughtcrime/securesms/jobs/JobManagerFactories.java b/src/org/thoughtcrime/securesms/jobs/JobManagerFactories.java index cfa9aa7beb..3a375a6169 100644 --- a/src/org/thoughtcrime/securesms/jobs/JobManagerFactories.java +++ b/src/org/thoughtcrime/securesms/jobs/JobManagerFactories.java @@ -13,6 +13,7 @@ import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraintObserver; import org.thoughtcrime.securesms.jobmanager.impl.NetworkOrCellServiceConstraint; import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraint; import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraintObserver; +import org.thoughtcrime.securesms.loki.MultiDeviceOpenGroupUpdateJob; import org.thoughtcrime.securesms.loki.PushBackgroundMessageSendJob; import org.thoughtcrime.securesms.loki.PushMessageSyncSendJob; @@ -31,7 +32,6 @@ public final class JobManagerFactories { put(CleanPreKeysJob.KEY, new CleanPreKeysJob.Factory()); put(CreateSignedPreKeyJob.KEY, new CreateSignedPreKeyJob.Factory()); put(DirectoryRefreshJob.KEY, new DirectoryRefreshJob.Factory(application)); - put(FcmRefreshJob.KEY, new FcmRefreshJob.Factory()); put(LocalBackupJob.KEY, new LocalBackupJob.Factory()); put(MmsDownloadJob.KEY, new MmsDownloadJob.Factory()); put(MmsReceiveJob.KEY, new MmsReceiveJob.Factory()); @@ -74,6 +74,7 @@ public final class JobManagerFactories { put(UpdateApkJob.KEY, new UpdateApkJob.Factory()); put(PushMessageSyncSendJob.KEY, new PushMessageSyncSendJob.Factory()); put(PushBackgroundMessageSendJob.KEY, new PushBackgroundMessageSendJob.Factory()); + put(MultiDeviceOpenGroupUpdateJob.KEY, new MultiDeviceOpenGroupUpdateJob.Factory()); }}; } diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java index aa22fa51e5..7fde014469 100644 --- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java +++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java @@ -245,7 +245,7 @@ public class MultiDeviceContactUpdateJob extends BaseJob implements InjectableTy } private List getAllContacts() { - List
contactAddresses = DatabaseFactory.getRecipientDatabase(context).getRegistered(); + List
contactAddresses = new ArrayList<>(DatabaseFactory.getRecipientDatabase(context).getAllAddresses()); List contacts = new ArrayList<>(contactAddresses.size()); for (Address address : contactAddresses) { if (!address.isPhone()) { continue; } diff --git a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java index 6d7595b9b8..4fc2508de9 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java @@ -59,6 +59,7 @@ import org.thoughtcrime.securesms.database.model.MmsMessageRecord; import org.thoughtcrime.securesms.database.model.SmsMessageRecord; import org.thoughtcrime.securesms.database.model.StickerRecord; import org.thoughtcrime.securesms.dependencies.InjectableType; +import org.thoughtcrime.securesms.groups.GroupManager; import org.thoughtcrime.securesms.groups.GroupMessageProcessor; import org.thoughtcrime.securesms.jobmanager.Data; import org.thoughtcrime.securesms.jobmanager.Job; @@ -72,6 +73,7 @@ import org.thoughtcrime.securesms.loki.LokiMessageDatabase; import org.thoughtcrime.securesms.loki.LokiSessionResetImplementation; import org.thoughtcrime.securesms.loki.LokiThreadDatabase; import org.thoughtcrime.securesms.loki.MultiDeviceUtilities; +import org.thoughtcrime.securesms.loki.redesign.utilities.OpenGroupUtilities; import org.thoughtcrime.securesms.loki.redesign.activities.HomeActivity; import org.thoughtcrime.securesms.loki.redesign.messaging.LokiAPIUtilities; import org.thoughtcrime.securesms.loki.redesign.messaging.LokiPreKeyBundleDatabase; @@ -138,6 +140,8 @@ import org.whispersystems.signalservice.loki.api.DeviceLink; import org.whispersystems.signalservice.loki.api.DeviceLinkingSession; import org.whispersystems.signalservice.loki.api.LokiAPI; import org.whispersystems.signalservice.loki.api.LokiDeviceLinkUtilities; +import org.whispersystems.signalservice.loki.api.LokiPublicChat; +import org.whispersystems.signalservice.loki.api.LokiFileServerAPI; import org.whispersystems.signalservice.loki.crypto.LokiServiceCipher; import org.whispersystems.signalservice.loki.messaging.LokiMessageFriendRequestStatus; import org.whispersystems.signalservice.loki.messaging.LokiServiceMessage; @@ -393,6 +397,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType { else if (syncMessage.getStickerPackOperations().isPresent()) handleSynchronizeStickerPackOperation(syncMessage.getStickerPackOperations().get()); else if (syncMessage.getContacts().isPresent()) handleContactSyncMessage(syncMessage.getContacts().get()); else if (syncMessage.getGroups().isPresent()) handleGroupSyncMessage(content, syncMessage.getGroups().get()); + else if (syncMessage.getOpenGroups().isPresent()) handleOpenGroupSyncMessage(syncMessage.getOpenGroups().get()); else Log.w(TAG, "Contains no known sync types..."); } else if (content.getCallMessage().isPresent()) { Log.i(TAG, "Got call message..."); @@ -704,6 +709,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType { long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient); LokiThreadFriendRequestStatus status = DatabaseFactory.getLokiThreadDatabase(context).getFriendRequestStatus(threadID); if (status == LokiThreadFriendRequestStatus.NONE || status == LokiThreadFriendRequestStatus.REQUEST_EXPIRED) { + // TODO: We should ensure that our mapping has been uploaded to the server before sending out this message MessageSender.sendBackgroundFriendRequest(context, hexEncodedPublicKey, "Please accept to enable messages to be synced across devices"); Log.d("Loki", "Sent friend request to " + hexEncodedPublicKey); } else if (status == LokiThreadFriendRequestStatus.REQUEST_RECEIVED) { @@ -749,6 +755,24 @@ public class PushDecryptJob extends BaseJob implements InjectableType { } } + private void handleOpenGroupSyncMessage(@NonNull List openGroups) { + try { + for (LokiPublicChat openGroup : openGroups) { + long threadID = GroupManager.getPublicChatThreadId(openGroup.getId(), context); + if (threadID > -1) continue; + + String url = openGroup.getServer(); + long channel = openGroup.getChannel(); + OpenGroupUtilities.addGroup(context, url, channel).fail(e -> { + Log.d("Loki", "Failed to sync open group: " + url + " due to error: " + e + "."); + return Unit.INSTANCE; + }); + } + } catch (Exception e) { + Log.d("Loki", "Failed to sync open groups due to error: " + e + "."); + } + } + private void handleSynchronizeSentMessage(@NonNull SignalServiceContent content, @NonNull SentTranscriptMessage message) throws StorageFailedException @@ -1206,6 +1230,17 @@ public class PushDecryptJob extends BaseJob implements InjectableType { TextSecurePreferences.setMultiDevice(context, true); // Send a background message to the master device MessageSender.sendBackgroundMessage(context, deviceLink.getMasterHexEncodedPublicKey()); + /* + Update device link on the file server. + We put this here because after receiving the authorisation message, we will also receive all sync messages. + If these sync messages are contact syncs then we need to send them friend requests so that we can establish multi-device communication. + If our device mapping is not stored on the server before the other party receives our message, they will think that they got a friend request from a non-multi-device user. + */ + try { + PromiseUtil.timeout(LokiFileServerAPI.shared.addDeviceLink(deviceLink), 8000).get(); + } catch (Exception e) { + Log.w("Loki", "Failed to upload device links to the file server! " + e); + } // Update display name if needed if (content.senderDisplayName.isPresent() && content.senderDisplayName.get().length() > 0) { TextSecurePreferences.setProfileName(context, content.senderDisplayName.get()); @@ -1218,7 +1253,6 @@ public class PushDecryptJob extends BaseJob implements InjectableType { if (content.getSyncMessage().isPresent() && content.getSyncMessage().get().getContacts().isPresent()) { handleContactSyncMessage(content.getSyncMessage().get().getContacts().get()); } - // The device link is propagated to the file server in LandingActivity.onDeviceLinkAuthorized because we can handle the error there } private void setDisplayName(String hexEncodedPublicKey, String profileName) { diff --git a/src/org/thoughtcrime/securesms/loki/MultiDeviceOpenGroupUpdateJob.kt b/src/org/thoughtcrime/securesms/loki/MultiDeviceOpenGroupUpdateJob.kt new file mode 100644 index 0000000000..683eea84b6 --- /dev/null +++ b/src/org/thoughtcrime/securesms/loki/MultiDeviceOpenGroupUpdateJob.kt @@ -0,0 +1,80 @@ +package org.thoughtcrime.securesms.loki + +import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil +import org.thoughtcrime.securesms.database.DatabaseFactory +import org.thoughtcrime.securesms.dependencies.InjectableType +import org.thoughtcrime.securesms.groups.GroupManager +import org.thoughtcrime.securesms.jobmanager.Data +import org.thoughtcrime.securesms.jobmanager.Job +import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint +import org.thoughtcrime.securesms.jobs.BaseJob +import org.thoughtcrime.securesms.logging.Log +import org.thoughtcrime.securesms.util.TextSecurePreferences +import org.whispersystems.signalservice.api.SignalServiceMessageSender +import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage +import org.whispersystems.signalservice.loki.api.LokiPublicChat +import java.util.concurrent.TimeUnit +import javax.inject.Inject + +class MultiDeviceOpenGroupUpdateJob private constructor(parameters: Parameters) : BaseJob(parameters), InjectableType { + + companion object { + const val KEY = "MultiDeviceOpenGroupUpdateJob" + } + + @Inject + lateinit var messageSender: SignalServiceMessageSender + + constructor() : this(Parameters.Builder() + .addConstraint(NetworkConstraint.KEY) + .setQueue("MultiDeviceOpenGroupUpdateJob") + .setLifespan(TimeUnit.DAYS.toMillis(1)) + .setMaxAttempts(Parameters.UNLIMITED) + .build()) + + override fun getFactoryKey(): String { return KEY } + + override fun serialize(): Data { return Data.EMPTY } + + @Throws(Exception::class) + public override fun onRun() { + if (!TextSecurePreferences.isMultiDevice(context)) { + Log.d("Loki", "Not multi device; aborting...") + return + } + + val openGroups = mutableListOf() + DatabaseFactory.getGroupDatabase(context).groups.use { reader -> + while (true) { + val record = reader.next ?: return@use + if (!record.isPublicChat) { continue; } + + val threadID = GroupManager.getThreadIdFromGroupId(record.encodedId, context) + val openGroup = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(threadID) + if (openGroup != null) { + openGroups.add(openGroup) + } + } + } + + if (openGroups.size > 0) { + messageSender.sendMessage(0, SignalServiceSyncMessage.forOpenGroups(openGroups), + UnidentifiedAccessUtil.getAccessForSync(context)) + } else { + Log.d("Loki", "No open groups to sync.") + } + } + + public override fun onShouldRetry(exception: Exception): Boolean { + return false + } + + override fun onCanceled() { } + + class Factory : Job.Factory { + + override fun create(parameters: Parameters, data: Data): MultiDeviceOpenGroupUpdateJob { + return MultiDeviceOpenGroupUpdateJob(parameters) + } + } +} diff --git a/src/org/thoughtcrime/securesms/loki/MultiDeviceUtilities.kt b/src/org/thoughtcrime/securesms/loki/MultiDeviceUtilities.kt index 6afb77f165..8cbf546901 100644 --- a/src/org/thoughtcrime/securesms/loki/MultiDeviceUtilities.kt +++ b/src/org/thoughtcrime/securesms/loki/MultiDeviceUtilities.kt @@ -42,6 +42,12 @@ fun checkIsRevokedSlaveDevice(context: Context) { } } +fun updateDeviceLinksOnServer(context: Context) { + val hexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context) + val deviceLinks = DatabaseFactory.getLokiAPIDatabase(context).getDeviceLinks(hexEncodedPublicKey) + LokiFileServerAPI.shared.setDeviceLinks(deviceLinks) +} + fun getAllDeviceFriendRequestStatuses(context: Context, hexEncodedPublicKey: String): Promise, Exception> { val lokiThreadDatabase = DatabaseFactory.getLokiThreadDatabase(context) return LokiDeviceLinkUtilities.getAllLinkedDeviceHexEncodedPublicKeys(hexEncodedPublicKey).map { keys -> diff --git a/src/org/thoughtcrime/securesms/loki/redesign/activities/HomeActivity.kt b/src/org/thoughtcrime/securesms/loki/redesign/activities/HomeActivity.kt index 3993a93f10..44812f438d 100644 --- a/src/org/thoughtcrime/securesms/loki/redesign/activities/HomeActivity.kt +++ b/src/org/thoughtcrime/securesms/loki/redesign/activities/HomeActivity.kt @@ -194,7 +194,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe private fun openConversation(thread: ThreadRecord) { val intent = Intent(this, ConversationActivity::class.java) - intent.putExtra(ConversationActivity.ADDRESS_EXTRA, thread.recipient.getAddress()) + intent.putExtra(ConversationActivity.ADDRESS_EXTRA, thread.recipient.address) intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, thread.threadId) intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, thread.distributionType) intent.putExtra(ConversationActivity.TIMING_EXTRA, System.currentTimeMillis()) @@ -255,9 +255,9 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe val dialog = AlertDialog.Builder(activity) dialog.setMessage(dialogMessage) dialog.setPositiveButton(R.string.yes) { _, _ -> - val isGroup = recipient.isGroupRecipient + val isClosedGroup = recipient.address.isSignalGroup // Send a leave group message if this is an active closed group - if (isGroup && DatabaseFactory.getGroupDatabase(activity).isActive(recipient.address.toGroupString())) { + if (isClosedGroup && DatabaseFactory.getGroupDatabase(activity).isActive(recipient.address.toGroupString())) { if (!GroupUtil.leaveGroup(activity, recipient)) { Toast.makeText(activity, "Couldn't leave group", Toast.LENGTH_LONG).show() clearView(activity.recyclerView, viewHolder) @@ -267,10 +267,11 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe // Archive the conversation and then delete it after 10 seconds (the case where the // app was closed before the conversation could be deleted is handled in onCreate) threadDatabase.archiveConversation(threadID) + val delay = if (isClosedGroup) 10000L else 1000L val handler = Handler() - handler.postDelayed(deleteThread, 10000) + handler.postDelayed(deleteThread, delay) // Notify the user - val toastMessage = if (isGroup) R.string.MessageRecord_left_group else R.string.activity_home_conversation_deleted_message + val toastMessage = if (recipient.isGroupRecipient) R.string.MessageRecord_left_group else R.string.activity_home_conversation_deleted_message Toast.makeText(activity, toastMessage, Toast.LENGTH_LONG).show() } dialog.setNegativeButton(R.string.no) { _, _ -> diff --git a/src/org/thoughtcrime/securesms/loki/redesign/activities/JoinPublicChatActivity.kt b/src/org/thoughtcrime/securesms/loki/redesign/activities/JoinPublicChatActivity.kt index 6d3b940378..9364419d24 100644 --- a/src/org/thoughtcrime/securesms/loki/redesign/activities/JoinPublicChatActivity.kt +++ b/src/org/thoughtcrime/securesms/loki/redesign/activities/JoinPublicChatActivity.kt @@ -16,14 +16,12 @@ import kotlinx.android.synthetic.main.fragment_enter_chat_url.* import network.loki.messenger.R import nl.komponents.kovenant.ui.failUi import nl.komponents.kovenant.ui.successUi -import org.thoughtcrime.securesms.ApplicationContext import org.thoughtcrime.securesms.BaseActionBarActivity import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity -import org.thoughtcrime.securesms.crypto.ProfileKeyUtil -import org.thoughtcrime.securesms.database.DatabaseFactory +import org.thoughtcrime.securesms.loki.redesign.utilities.OpenGroupUtilities import org.thoughtcrime.securesms.loki.redesign.fragments.ScanQRCodeWrapperFragment import org.thoughtcrime.securesms.loki.redesign.fragments.ScanQRCodeWrapperFragmentDelegate -import org.thoughtcrime.securesms.util.TextSecurePreferences +import org.thoughtcrime.securesms.sms.MessageSender class JoinPublicChatActivity : PassphraseRequiredActionBarActivity(), ScanQRCodeWrapperFragmentDelegate { private val adapter = JoinPublicChatActivityAdapter(this) @@ -68,19 +66,11 @@ class JoinPublicChatActivity : PassphraseRequiredActionBarActivity(), ScanQRCode return Toast.makeText(this, "Invalid URL", Toast.LENGTH_SHORT).show() } showLoader() - val application = ApplicationContext.getInstance(this) + val channel: Long = 1 - val displayName = TextSecurePreferences.getProfileName(this) - val lokiPublicChatAPI = application.lokiPublicChatAPI!! - application.lokiPublicChatManager.addChat(url, channel).successUi { - DatabaseFactory.getLokiAPIDatabase(this).removeLastMessageServerID(channel, url) - DatabaseFactory.getLokiAPIDatabase(this).removeLastDeletionServerID(channel, url) - lokiPublicChatAPI.getMessages(channel, url) - lokiPublicChatAPI.setDisplayName(displayName, url) - lokiPublicChatAPI.join(channel, url) - val profileKey: ByteArray = ProfileKeyUtil.getProfileKey(this) - val profileUrl: String? = TextSecurePreferences.getProfileAvatarUrl(this) - lokiPublicChatAPI.setProfilePicture(url, profileKey, profileUrl) + OpenGroupUtilities.addGroup(this, url, channel).success { + MessageSender.syncAllOpenGroups(this) + }.successUi { finish() }.failUi { hideLoader() diff --git a/src/org/thoughtcrime/securesms/loki/redesign/activities/LandingActivity.kt b/src/org/thoughtcrime/securesms/loki/redesign/activities/LandingActivity.kt index f8031a22b7..130646d4fa 100644 --- a/src/org/thoughtcrime/securesms/loki/redesign/activities/LandingActivity.kt +++ b/src/org/thoughtcrime/securesms/loki/redesign/activities/LandingActivity.kt @@ -114,7 +114,6 @@ class LandingActivity : BaseActionBarActivity(), LinkDeviceSlaveModeDialogDelega } override fun onDeviceLinkRequestAuthorized(deviceLink: DeviceLink) { - LokiFileServerAPI.shared.addDeviceLink(deviceLink) TextSecurePreferences.setMasterHexEncodedPublicKey(this, deviceLink.masterHexEncodedPublicKey) val intent = Intent(this, HomeActivity::class.java) show(intent) diff --git a/src/org/thoughtcrime/securesms/loki/redesign/activities/LinkedDevicesActivity.kt b/src/org/thoughtcrime/securesms/loki/redesign/activities/LinkedDevicesActivity.kt index 759362b91c..d9147fbfdd 100644 --- a/src/org/thoughtcrime/securesms/loki/redesign/activities/LinkedDevicesActivity.kt +++ b/src/org/thoughtcrime/securesms/loki/redesign/activities/LinkedDevicesActivity.kt @@ -12,6 +12,7 @@ import android.view.View import android.widget.Toast import kotlinx.android.synthetic.main.activity_linked_devices.* import network.loki.messenger.R +import nl.komponents.kovenant.functional.bind import nl.komponents.kovenant.ui.failUi import nl.komponents.kovenant.ui.successUi import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity @@ -23,6 +24,7 @@ import org.thoughtcrime.securesms.loki.signAndSendDeviceLinkMessage import org.thoughtcrime.securesms.sms.MessageSender import org.thoughtcrime.securesms.util.TextSecurePreferences import org.whispersystems.signalservice.loki.api.DeviceLink +import org.whispersystems.signalservice.loki.api.LokiAPI import org.whispersystems.signalservice.loki.api.LokiFileServerAPI import java.util.* import kotlin.concurrent.schedule @@ -143,23 +145,21 @@ class LinkedDevicesActivity : PassphraseRequiredActionBarActivity, LoaderManager } override fun onDeviceLinkRequestAuthorized(deviceLink: DeviceLink) { - LokiFileServerAPI.shared.addDeviceLink(deviceLink).success { - signAndSendDeviceLinkMessage(this, deviceLink).successUi { - LoaderManager.getInstance(this).restartLoader(0, null, this) - }.success { - TextSecurePreferences.setMultiDevice(this, true) - Timer().schedule(4000) { - MessageSender.syncAllGroups(this@LinkedDevicesActivity) - MessageSender.syncAllContacts(this@LinkedDevicesActivity, Address.fromSerialized(deviceLink.slaveHexEncodedPublicKey)) - } - }.failUi { - Toast.makeText(this, "Couldn't link device", Toast.LENGTH_LONG).show() - }.fail { - LokiFileServerAPI.shared.removeDeviceLink(deviceLink) // If this fails we have a problem - DatabaseFactory.getLokiPreKeyBundleDatabase(this).removePreKeyBundle(deviceLink.slaveHexEncodedPublicKey) + LokiFileServerAPI.shared.addDeviceLink(deviceLink).bind(LokiAPI.sharedWorkContext) { + signAndSendDeviceLinkMessage(this, deviceLink) + }.successUi { + LoaderManager.getInstance(this).restartLoader(0, null, this) + }.success { + TextSecurePreferences.setMultiDevice(this, true) + Timer().schedule(4000) { + MessageSender.syncAllGroups(this@LinkedDevicesActivity) + MessageSender.syncAllContacts(this@LinkedDevicesActivity, Address.fromSerialized(deviceLink.slaveHexEncodedPublicKey)) + MessageSender.syncAllOpenGroups(this@LinkedDevicesActivity) } - }.failUi { + }.fail { + LokiFileServerAPI.shared.removeDeviceLink(deviceLink) // If this fails we have a problem DatabaseFactory.getLokiPreKeyBundleDatabase(this).removePreKeyBundle(deviceLink.slaveHexEncodedPublicKey) + }.failUi { Toast.makeText(this, "Couldn't link device", Toast.LENGTH_LONG).show() } } diff --git a/src/org/thoughtcrime/securesms/loki/redesign/utilities/OpenGroupUtilities.kt b/src/org/thoughtcrime/securesms/loki/redesign/utilities/OpenGroupUtilities.kt new file mode 100644 index 0000000000..87f7afdf6b --- /dev/null +++ b/src/org/thoughtcrime/securesms/loki/redesign/utilities/OpenGroupUtilities.kt @@ -0,0 +1,37 @@ +package org.thoughtcrime.securesms.loki.redesign.utilities + +import android.content.Context +import nl.komponents.kovenant.Promise +import nl.komponents.kovenant.then +import org.thoughtcrime.securesms.ApplicationContext +import org.thoughtcrime.securesms.crypto.ProfileKeyUtil +import org.thoughtcrime.securesms.database.DatabaseFactory +import org.thoughtcrime.securesms.groups.GroupManager +import org.thoughtcrime.securesms.util.TextSecurePreferences +import org.whispersystems.signalservice.loki.api.LokiPublicChat + +object OpenGroupUtilities { + + @JvmStatic fun addGroup(context: Context, url: String, channel: Long): Promise { + // Check for an existing group + val groupID = LokiPublicChat.getId(channel, url) + val threadID = GroupManager.getPublicChatThreadId(groupID, context) + val openGroup = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(threadID) + if (openGroup != null) { return Promise.of(openGroup) } + // Add the new group + val application = ApplicationContext.getInstance(context) + val displayName = TextSecurePreferences.getProfileName(context) + val lokiPublicChatAPI = application.lokiPublicChatAPI ?: throw Error("LokiPublicChatAPI is not initialized.") + return application.lokiPublicChatManager.addChat(url, channel).then { group -> + DatabaseFactory.getLokiAPIDatabase(context).removeLastMessageServerID(channel, url) + DatabaseFactory.getLokiAPIDatabase(context).removeLastDeletionServerID(channel, url) + lokiPublicChatAPI.getMessages(channel, url) + lokiPublicChatAPI.setDisplayName(displayName, url) + lokiPublicChatAPI.join(channel, url) + val profileKey: ByteArray = ProfileKeyUtil.getProfileKey(context) + val profileUrl: String? = TextSecurePreferences.getProfileAvatarUrl(context) + lokiPublicChatAPI.setProfilePicture(url, profileKey, profileUrl) + group + } + } +} \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/mms/AttachmentManager.java b/src/org/thoughtcrime/securesms/mms/AttachmentManager.java index 4483e20d2a..9ce2e90786 100644 --- a/src/org/thoughtcrime/securesms/mms/AttachmentManager.java +++ b/src/org/thoughtcrime/securesms/mms/AttachmentManager.java @@ -33,20 +33,12 @@ import android.provider.OpenableColumns; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.TextUtils; - -import org.thoughtcrime.securesms.TransportOption; -import org.thoughtcrime.securesms.mediasend.MediaSendActivity; -import org.thoughtcrime.securesms.logging.Log; import android.util.Pair; import android.view.View; import android.widget.Toast; -import com.google.android.gms.common.GooglePlayServicesNotAvailableException; -import com.google.android.gms.common.GooglePlayServicesRepairableException; -import com.google.android.gms.location.places.ui.PlacePicker; - import org.thoughtcrime.securesms.MediaPreviewActivity; -import network.loki.messenger.R; +import org.thoughtcrime.securesms.TransportOption; import org.thoughtcrime.securesms.attachments.Attachment; import org.thoughtcrime.securesms.components.AudioView; import org.thoughtcrime.securesms.components.DocumentView; @@ -55,6 +47,8 @@ import org.thoughtcrime.securesms.components.ThumbnailView; import org.thoughtcrime.securesms.components.location.SignalMapView; import org.thoughtcrime.securesms.components.location.SignalPlace; import org.thoughtcrime.securesms.giph.ui.GiphyActivity; +import org.thoughtcrime.securesms.logging.Log; +import org.thoughtcrime.securesms.mediasend.MediaSendActivity; import org.thoughtcrime.securesms.permissions.Permissions; import org.thoughtcrime.securesms.providers.BlobProvider; import org.thoughtcrime.securesms.providers.DeprecatedPersistentBlobProvider; @@ -77,6 +71,8 @@ import java.util.LinkedList; import java.util.List; import java.util.concurrent.ExecutionException; +import network.loki.messenger.R; + public class AttachmentManager { diff --git a/src/org/thoughtcrime/securesms/preferences/AdvancedPreferenceFragment.java b/src/org/thoughtcrime/securesms/preferences/AdvancedPreferenceFragment.java index 9ec8d17291..094f1fa12e 100644 --- a/src/org/thoughtcrime/securesms/preferences/AdvancedPreferenceFragment.java +++ b/src/org/thoughtcrime/securesms/preferences/AdvancedPreferenceFragment.java @@ -14,17 +14,14 @@ import android.support.annotation.Nullable; import android.support.v7.app.AlertDialog; import android.support.v7.preference.CheckBoxPreference; import android.support.v7.preference.Preference; -import org.thoughtcrime.securesms.logging.Log; import android.widget.Toast; -import com.google.firebase.iid.FirebaseInstanceId; - import org.thoughtcrime.securesms.ApplicationPreferencesActivity; import org.thoughtcrime.securesms.LogSubmitActivity; -import network.loki.messenger.R; import org.thoughtcrime.securesms.RegistrationActivity; import org.thoughtcrime.securesms.contacts.ContactAccessor; import org.thoughtcrime.securesms.contacts.ContactIdentityManager; +import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.push.AccountManagerFactory; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.task.ProgressDialogAsyncTask; @@ -34,6 +31,8 @@ import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedE import java.io.IOException; +import network.loki.messenger.R; + public class AdvancedPreferenceFragment extends CorrectedPreferenceFragment { private static final String TAG = AdvancedPreferenceFragment.class.getSimpleName(); @@ -187,15 +186,11 @@ public class AdvancedPreferenceFragment extends CorrectedPreferenceFragment { SignalServiceAccountManager accountManager = AccountManagerFactory.createManager(context); try { - accountManager.setGcmId(Optional.absent()); + accountManager.setGcmId(Optional.absent()); } catch (AuthorizationFailedException e) { Log.w(TAG, e); } - if (!TextSecurePreferences.isFcmDisabled(context)) { - FirebaseInstanceId.getInstance().deleteInstanceId(); - } - return SUCCESS; } catch (IOException ioe) { Log.w(TAG, ioe); diff --git a/src/org/thoughtcrime/securesms/push/AccountManagerFactory.java b/src/org/thoughtcrime/securesms/push/AccountManagerFactory.java index c8729b9ab7..883b5fe315 100644 --- a/src/org/thoughtcrime/securesms/push/AccountManagerFactory.java +++ b/src/org/thoughtcrime/securesms/push/AccountManagerFactory.java @@ -1,15 +1,12 @@ package org.thoughtcrime.securesms.push; import android.content.Context; -import android.os.AsyncTask; -import org.thoughtcrime.securesms.logging.Log; -import com.google.android.gms.security.ProviderInstaller; - -import network.loki.messenger.BuildConfig; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.signalservice.api.SignalServiceAccountManager; +import network.loki.messenger.BuildConfig; + public class AccountManagerFactory { private static final String TAG = AccountManagerFactory.class.getSimpleName(); @@ -22,20 +19,6 @@ public class AccountManagerFactory { } public static SignalServiceAccountManager createManager(final Context context, String number, String password) { - if (new SignalServiceNetworkAccess(context).isCensored(number)) { - new AsyncTask() { - @Override - protected Void doInBackground(Void... params) { - try { - ProviderInstaller.installIfNeeded(context); - } catch (Throwable t) { - Log.w(TAG, t); - } - return null; - } - }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - } - return new SignalServiceAccountManager(new SignalServiceNetworkAccess(context).getConfiguration(number), number, password, BuildConfig.USER_AGENT); } diff --git a/src/org/thoughtcrime/securesms/service/ContactsSyncAdapterService.java b/src/org/thoughtcrime/securesms/service/ContactsSyncAdapterService.java deleted file mode 100644 index c162d9104d..0000000000 --- a/src/org/thoughtcrime/securesms/service/ContactsSyncAdapterService.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.thoughtcrime.securesms.service; - -import android.app.Service; -import android.content.Intent; -import android.os.IBinder; -import android.support.annotation.Nullable; - -import org.thoughtcrime.securesms.contacts.ContactsSyncAdapter; - -public class ContactsSyncAdapterService extends Service { - - private static ContactsSyncAdapter syncAdapter; - - @Override - public synchronized void onCreate() { - if (syncAdapter == null) { - syncAdapter = new ContactsSyncAdapter(this, true); - } - } - - @Nullable - @Override - public IBinder onBind(Intent intent) { - return syncAdapter.getSyncAdapterBinder(); - } -} diff --git a/src/org/thoughtcrime/securesms/sms/MessageSender.java b/src/org/thoughtcrime/securesms/sms/MessageSender.java index 80a4baa482..7a72ac68d2 100644 --- a/src/org/thoughtcrime/securesms/sms/MessageSender.java +++ b/src/org/thoughtcrime/securesms/sms/MessageSender.java @@ -48,6 +48,7 @@ import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.loki.BackgroundMessage; import org.thoughtcrime.securesms.loki.FriendRequestHandler; import org.thoughtcrime.securesms.loki.GeneralUtilitiesKt; +import org.thoughtcrime.securesms.loki.MultiDeviceOpenGroupUpdateJob; import org.thoughtcrime.securesms.loki.MultiDeviceUtilities; import org.thoughtcrime.securesms.loki.PushBackgroundMessageSendJob; import org.thoughtcrime.securesms.loki.PushMessageSyncSendJob; @@ -86,6 +87,10 @@ public class MessageSender { ApplicationContext.getInstance(context).getJobManager().add(new MultiDeviceGroupUpdateJob()); } + public static void syncAllOpenGroups(Context context) { + ApplicationContext.getInstance(context).getJobManager().add(new MultiDeviceOpenGroupUpdateJob()); + } + /** * Send a contact sync message to all our devices telling them that we want to sync `contact` */ diff --git a/src/org/thoughtcrime/securesms/stickers/StickerPackPreviewRepository.java b/src/org/thoughtcrime/securesms/stickers/StickerPackPreviewRepository.java index da2371aa4d..9ef5b4a0f3 100644 --- a/src/org/thoughtcrime/securesms/stickers/StickerPackPreviewRepository.java +++ b/src/org/thoughtcrime/securesms/stickers/StickerPackPreviewRepository.java @@ -6,7 +6,6 @@ import android.support.annotation.NonNull; import android.support.annotation.WorkerThread; import com.annimon.stream.Stream; -import com.google.android.gms.common.util.Hex; import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.database.DatabaseFactory; @@ -15,6 +14,7 @@ import org.thoughtcrime.securesms.database.model.StickerPackRecord; import org.thoughtcrime.securesms.database.model.StickerRecord; import org.thoughtcrime.securesms.dependencies.InjectableType; import org.thoughtcrime.securesms.logging.Log; +import org.thoughtcrime.securesms.util.Hex; import org.thoughtcrime.securesms.util.concurrent.SignalExecutors; import org.whispersystems.libsignal.InvalidMessageException; import org.whispersystems.libsignal.util.guava.Optional; @@ -81,8 +81,8 @@ public final class StickerPackPreviewRepository implements InjectableType { @WorkerThread private Optional getManifestRemote(@NonNull String packId, @NonNull String packKey) { try { - byte[] packIdBytes = Hex.stringToBytes(packId); - byte[] packKeyBytes = Hex.stringToBytes(packKey); + byte[] packIdBytes = Hex.fromStringCondensed(packId); + byte[] packKeyBytes = Hex.fromStringCondensed(packKey); SignalServiceStickerManifest remoteManifest = receiver.retrieveStickerManifest(packIdBytes, packKeyBytes); StickerManifest localManifest = new StickerManifest(packId, packKey, diff --git a/src/org/thoughtcrime/securesms/stickers/StickerRemoteUriFetcher.java b/src/org/thoughtcrime/securesms/stickers/StickerRemoteUriFetcher.java index fcb30af9b5..f75c538838 100644 --- a/src/org/thoughtcrime/securesms/stickers/StickerRemoteUriFetcher.java +++ b/src/org/thoughtcrime/securesms/stickers/StickerRemoteUriFetcher.java @@ -5,9 +5,9 @@ import android.support.annotation.NonNull; import com.bumptech.glide.Priority; import com.bumptech.glide.load.DataSource; import com.bumptech.glide.load.data.DataFetcher; -import com.google.android.gms.common.util.Hex; import org.thoughtcrime.securesms.logging.Log; +import org.thoughtcrime.securesms.util.Hex; import org.whispersystems.libsignal.InvalidMessageException; import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; @@ -32,8 +32,8 @@ public final class StickerRemoteUriFetcher implements DataFetcher { @Override public void loadData(@NonNull Priority priority, @NonNull DataCallback callback) { try { - byte[] packIdBytes = Hex.stringToBytes(stickerUri.getPackId()); - byte[] packKeyBytes = Hex.stringToBytes(stickerUri.getPackKey()); + byte[] packIdBytes = Hex.fromStringCondensed(stickerUri.getPackId()); + byte[] packKeyBytes = Hex.fromStringCondensed(stickerUri.getPackKey()); InputStream stream = receiver.retrieveSticker(packIdBytes, packKeyBytes, stickerUri.getStickerId()); callback.onDataReady(stream); diff --git a/src/org/thoughtcrime/securesms/util/GroupUtil.java b/src/org/thoughtcrime/securesms/util/GroupUtil.java index d4bdffa291..907a21217e 100644 --- a/src/org/thoughtcrime/securesms/util/GroupUtil.java +++ b/src/org/thoughtcrime/securesms/util/GroupUtil.java @@ -4,15 +4,13 @@ import android.content.Context; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.WorkerThread; -import android.widget.Toast; import com.google.protobuf.ByteString; -import network.loki.messenger.R; import org.thoughtcrime.securesms.database.Address; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.GroupDatabase; -import org.thoughtcrime.securesms.database.GroupDatabase.*; +import org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord; import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage; import org.thoughtcrime.securesms.recipients.Recipient; @@ -26,6 +24,8 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; +import network.loki.messenger.R; + import static org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext; public class GroupUtil { @@ -87,6 +87,10 @@ public class GroupUtil { return groupId.startsWith(ENCODED_RSS_FEED_GROUP_PREFIX); } + public static boolean isSignalGroup(@NonNull String groupId) { + return groupId.startsWith(ENCODED_SIGNAL_GROUP_PREFIX); + } + @WorkerThread public static Optional createGroupLeaveMessage(@NonNull Context context, @NonNull Recipient groupRecipient) { String encodedGroupId = groupRecipient.getAddress().toGroupString(); @@ -114,6 +118,8 @@ public class GroupUtil { } public static boolean leaveGroup(@NonNull Context context, Recipient groupRecipient) { + if (!groupRecipient.getAddress().isSignalGroup()) { return true; } + long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient); Optional leaveMessage = GroupUtil.createGroupLeaveMessage(context, groupRecipient); diff --git a/src/org/thoughtcrime/securesms/util/PlayServicesUtil.java b/src/org/thoughtcrime/securesms/util/PlayServicesUtil.java deleted file mode 100644 index fe629ba904..0000000000 --- a/src/org/thoughtcrime/securesms/util/PlayServicesUtil.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.thoughtcrime.securesms.util; - - -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import org.thoughtcrime.securesms.logging.Log; - -import com.google.android.gms.common.ConnectionResult; -import com.google.android.gms.common.GoogleApiAvailability; - -public class PlayServicesUtil { - - private static final String TAG = PlayServicesUtil.class.getSimpleName(); - - public enum PlayServicesStatus { - SUCCESS, - MISSING, - NEEDS_UPDATE, - TRANSIENT_ERROR - } - - public static PlayServicesStatus getPlayServicesStatus(Context context) { - int gcmStatus = 0; - - try { - gcmStatus = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context); - } catch (Throwable t) { - Log.w(TAG, t); - return PlayServicesStatus.MISSING; - } - - Log.i(TAG, "Play Services: " + gcmStatus); - - switch (gcmStatus) { - case ConnectionResult.SUCCESS: - return PlayServicesStatus.SUCCESS; - case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED: - try { - ApplicationInfo applicationInfo = context.getPackageManager().getApplicationInfo("com.google.android.gms", 0); - - if (applicationInfo != null && !applicationInfo.enabled) { - return PlayServicesStatus.MISSING; - } - } catch (PackageManager.NameNotFoundException e) { - Log.w(TAG, e); - } - - return PlayServicesStatus.NEEDS_UPDATE; - case ConnectionResult.SERVICE_DISABLED: - case ConnectionResult.SERVICE_MISSING: - case ConnectionResult.SERVICE_INVALID: - case ConnectionResult.API_UNAVAILABLE: - case ConnectionResult.SERVICE_MISSING_PERMISSION: - return PlayServicesStatus.MISSING; - default: - return PlayServicesStatus.TRANSIENT_ERROR; - } - } - -} diff --git a/src/org/thoughtcrime/securesms/util/ShortCodeUtil.java b/src/org/thoughtcrime/securesms/util/ShortCodeUtil.java index a119213feb..8a4a9d9018 100644 --- a/src/org/thoughtcrime/securesms/util/ShortCodeUtil.java +++ b/src/org/thoughtcrime/securesms/util/ShortCodeUtil.java @@ -2,13 +2,6 @@ package org.thoughtcrime.securesms.util; import android.support.annotation.NonNull; -import com.google.i18n.phonenumbers.NumberParseException; -import com.google.i18n.phonenumbers.PhoneNumberUtil; -import com.google.i18n.phonenumbers.Phonenumber; -import com.google.i18n.phonenumbers.ShortNumberInfo; - -import org.thoughtcrime.securesms.logging.Log; - import java.util.HashSet; import java.util.Set; @@ -24,23 +17,7 @@ public class ShortCodeUtil { }}; public static boolean isShortCode(@NonNull String localNumber, @NonNull String number) { - try { - PhoneNumberUtil util = PhoneNumberUtil.getInstance(); - Phonenumber.PhoneNumber localNumberObject = util.parse(localNumber, null); - String localCountryCode = util.getRegionCodeForNumber(localNumberObject); - String bareNumber = number.replaceAll("[^0-9+]", ""); - - // libphonenumber seems incorrect for Russia and a few other countries with 4 digit short codes. - if (bareNumber.length() <= 4 && !SHORT_COUNTRIES.contains(localCountryCode)) { - return true; - } - - Phonenumber.PhoneNumber shortCode = util.parse(number, localCountryCode); - return ShortNumberInfo.getInstance().isPossibleShortNumberForRegion(shortCode, localCountryCode); - } catch (NumberParseException e) { - Log.w(TAG, e); - return false; - } + return false; } } diff --git a/src/org/thoughtcrime/securesms/util/Util.java b/src/org/thoughtcrime/securesms/util/Util.java index 24cfc6ba11..159cf26586 100644 --- a/src/org/thoughtcrime/securesms/util/Util.java +++ b/src/org/thoughtcrime/securesms/util/Util.java @@ -32,20 +32,14 @@ import android.os.Looper; import android.provider.Telephony; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.support.annotation.RequiresPermission; import android.telephony.TelephonyManager; import android.text.Spannable; import android.text.SpannableString; import android.text.TextUtils; import android.text.style.StyleSpan; -import com.google.android.mms.pdu_alt.CharacterSets; import com.google.android.mms.pdu_alt.EncodedStringValue; -import com.google.i18n.phonenumbers.NumberParseException; -import com.google.i18n.phonenumbers.PhoneNumberUtil; -import com.google.i18n.phonenumbers.Phonenumber; -import network.loki.messenger.BuildConfig; import org.thoughtcrime.securesms.components.ComposeText; import org.thoughtcrime.securesms.database.Address; import org.thoughtcrime.securesms.logging.Log; @@ -58,7 +52,7 @@ import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import java.security.SecureRandom; import java.text.DecimalFormat; import java.util.ArrayList; @@ -73,6 +67,8 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import network.loki.messenger.BuildConfig; + public class Util { private static final String TAG = Util.class.getSimpleName(); @@ -170,27 +166,15 @@ public class Util { } public static @NonNull String toIsoString(byte[] bytes) { - try { - return new String(bytes, CharacterSets.MIMENAME_ISO_8859_1); - } catch (UnsupportedEncodingException e) { - throw new AssertionError("ISO_8859_1 must be supported!"); - } + return new String(bytes, StandardCharsets.ISO_8859_1); } public static byte[] toIsoBytes(String isoString) { - try { - return isoString.getBytes(CharacterSets.MIMENAME_ISO_8859_1); - } catch (UnsupportedEncodingException e) { - throw new AssertionError("ISO_8859_1 must be supported!"); - } + return isoString.getBytes(StandardCharsets.ISO_8859_1); } public static byte[] toUtf8Bytes(String utf8String) { - try { - return utf8String.getBytes(CharacterSets.MIMENAME_UTF_8); - } catch (UnsupportedEncodingException e) { - throw new AssertionError("UTF_8 must be supported!"); - } + return utf8String.getBytes(StandardCharsets.UTF_8); } public static void wait(Object lock, long timeout) { @@ -279,27 +263,6 @@ public class Util { return total; } - @RequiresPermission(anyOf = { - android.Manifest.permission.READ_PHONE_STATE, - android.Manifest.permission.READ_SMS, - android.Manifest.permission.READ_PHONE_NUMBERS - }) - @SuppressLint("MissingPermission") - public static Optional getDeviceNumber(Context context) { - try { - final String localNumber = ((TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE)).getLine1Number(); - final Optional countryIso = getSimCountryIso(context); - - if (TextUtils.isEmpty(localNumber)) return Optional.absent(); - if (!countryIso.isPresent()) return Optional.absent(); - - return Optional.fromNullable(PhoneNumberUtil.getInstance().parse(localNumber, countryIso.get())); - } catch (NumberParseException e) { - Log.w(TAG, e); - return Optional.absent(); - } - } - public static Optional getSimCountryIso(Context context) { String simCountryIso = ((TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE)).getSimCountryIso(); return Optional.fromNullable(simCountryIso != null ? simCountryIso.toUpperCase() : null);