diff --git a/app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.java b/app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.java index a24e7b9d6..cb9cdb911 100644 --- a/app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.java +++ b/app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.java @@ -31,6 +31,7 @@ import com.nextcloud.talk.dagger.modules.RestModule; import com.nextcloud.talk.jobs.AccountRemovalWorker; import com.nextcloud.talk.jobs.CapabilitiesWorker; import com.nextcloud.talk.jobs.PushRegistrationWorker; +import com.nextcloud.talk.jobs.SignalingSettingsJob; import com.nextcloud.talk.utils.ClosedInterfaceImpl; import com.nextcloud.talk.utils.DeviceUtils; import com.nextcloud.talk.utils.DisplayUtils; @@ -124,11 +125,13 @@ public class NextcloudTalkApplication extends MultiDexApplication implements Lif PeriodicWorkRequest periodicCapabilitiesUpdateWork = new PeriodicWorkRequest.Builder(CapabilitiesWorker.class, 1, TimeUnit.DAYS).build(); OneTimeWorkRequest capabilitiesUpdateWork = new OneTimeWorkRequest.Builder(CapabilitiesWorker.class).build(); + OneTimeWorkRequest signalingSettingsWork = new OneTimeWorkRequest.Builder(SignalingSettingsJob.class).build(); WorkManager.initialize(getApplicationContext(), new Configuration.Builder().build()); WorkManager.getInstance().enqueue(pushRegistrationWork); WorkManager.getInstance().enqueue(accountRemovalWork); WorkManager.getInstance().enqueue(capabilitiesUpdateWork); + WorkManager.getInstance().enqueue(signalingSettingsWork); // There is a bug with periodic work so we ignore this for now //WorkManager.getInstance().enqueueUniquePeriodicWork("DailyCapabilitiesUpdateWork", diff --git a/app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.java b/app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.java index d0ed781f5..b443c3da3 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.java +++ b/app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.java @@ -38,6 +38,7 @@ import com.nextcloud.talk.controllers.base.BaseController; import com.nextcloud.talk.events.EventStatus; import com.nextcloud.talk.jobs.CapabilitiesWorker; import com.nextcloud.talk.jobs.PushRegistrationWorker; +import com.nextcloud.talk.jobs.SignalingSettingsJob; import com.nextcloud.talk.models.database.UserEntity; import com.nextcloud.talk.models.json.generic.Status; import com.nextcloud.talk.models.json.rooms.RoomsOverall; @@ -251,7 +252,7 @@ public class AccountVerificationController extends BaseController { userUtils.createOrUpdateUser(username, token, baseUrl, displayName, null, true, userId, null, null, - appPreferences.getTemporaryClientCertAlias()) + appPreferences.getTemporaryClientCertAlias(), null) .subscribeOn(Schedulers.newThread()) .subscribe(new Observer() { @Override @@ -361,8 +362,15 @@ public class AccountVerificationController extends BaseController { } abortVerification(); } else if (internalAccountId == eventStatus.getUserId() && eventStatus.isAllGood()) { - proceedWithLogin(); + fetchAndStoreExternalSignalingSettings(); } + } else if (eventStatus.getEventType().equals(EventStatus.EventType.SIGNALING_SETTINGS)) { + if (getActivity() != null) { + getActivity().runOnUiThread(() -> progressText.setText(progressText.getText().toString() + "\n" + + getResources().getString(R.string.nc_external_server_failed))); + } + + proceedWithLogin(); } } @@ -378,6 +386,17 @@ public class AccountVerificationController extends BaseController { WorkManager.getInstance().enqueue(pushNotificationWork); } + private void fetchAndStoreExternalSignalingSettings() { + Data userData = new Data.Builder() + .putLong(BundleKeys.KEY_INTERNAL_USER_ID, internalAccountId) + .build(); + + OneTimeWorkRequest signalingSettings = new OneTimeWorkRequest.Builder(SignalingSettingsJob.class) + .setInputData(userData) + .build(); + WorkManager.getInstance().enqueue(signalingSettings); + } + private void proceedWithLogin() { cookieManager.getCookieStore().removeAll(); userUtils.disableAllUsersWithoutId(internalAccountId); diff --git a/app/src/main/java/com/nextcloud/talk/controllers/SettingsController.java b/app/src/main/java/com/nextcloud/talk/controllers/SettingsController.java index 6b775be14..ec0923522 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/SettingsController.java +++ b/app/src/main/java/com/nextcloud/talk/controllers/SettingsController.java @@ -300,7 +300,7 @@ public class SettingsController extends BaseController { userUtils.createOrUpdateUser(null, null, null, null, null, null, null, currentUser.getId(), - null, alias); + null, alias, null); }, new String[]{"RSA", "EC"}, null, finalHost, finalPort, currentUser.getClientCertificate ())); } @@ -402,7 +402,7 @@ public class SettingsController extends BaseController { dbQueryDisposable = userUtils.createOrUpdateUser(null, null, null, displayName, null, null, - null, currentUser.getId(), null, null) + null, currentUser.getId(), null, null, null) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(userEntityResult -> { diff --git a/app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.java b/app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.java index 4fe9efda9..52753ec6b 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.java +++ b/app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.java @@ -100,7 +100,7 @@ public class SwitchAccountController extends BaseController { UserEntity userEntity = ((AdvancedUserItem) userItems.get(position)).getEntity(); userUtils.createOrUpdateUser(null, null, null, null, - null, true, null, userEntity.getId(), null, null) + null, true, null, userEntity.getId(), null, null, null) .subscribe(new Observer() { @Override public void onSubscribe(Disposable d) { diff --git a/app/src/main/java/com/nextcloud/talk/controllers/WebViewLoginController.java b/app/src/main/java/com/nextcloud/talk/controllers/WebViewLoginController.java index 3f2d10417..7ddc59862 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/WebViewLoginController.java +++ b/app/src/main/java/com/nextcloud/talk/controllers/WebViewLoginController.java @@ -367,7 +367,7 @@ public class WebViewLoginController extends BaseController { if (currentUser != null) { userQueryDisposable = userUtils.createOrUpdateUser(null, null, null, null, null, true, - null, currentUser.getId(), null, appPreferences.getTemporaryClientCertAlias()). + null, currentUser.getId(), null, appPreferences.getTemporaryClientCertAlias(), null). subscribe(userEntity -> { if (finalMessageType != null) { ApplicationWideMessageHolder.getInstance().setMessageType(finalMessageType); diff --git a/app/src/main/java/com/nextcloud/talk/events/EventStatus.java b/app/src/main/java/com/nextcloud/talk/events/EventStatus.java index a0eea0bf9..b125c61bf 100644 --- a/app/src/main/java/com/nextcloud/talk/events/EventStatus.java +++ b/app/src/main/java/com/nextcloud/talk/events/EventStatus.java @@ -35,7 +35,7 @@ public class EventStatus { } public enum EventType { - PUSH_REGISTRATION, CAPABILITIES_FETCH + PUSH_REGISTRATION, CAPABILITIES_FETCH, SIGNALING_SETTINGS } } diff --git a/app/src/main/java/com/nextcloud/talk/jobs/CapabilitiesWorker.java b/app/src/main/java/com/nextcloud/talk/jobs/CapabilitiesWorker.java index e0101b7b0..17214100d 100644 --- a/app/src/main/java/com/nextcloud/talk/jobs/CapabilitiesWorker.java +++ b/app/src/main/java/com/nextcloud/talk/jobs/CapabilitiesWorker.java @@ -74,7 +74,7 @@ public class CapabilitiesWorker extends Worker { userUtils.createOrUpdateUser(null, null, null, null, null, null, null, internalUserEntity.getId(), - LoganSquare.serialize(capabilitiesOverall.getOcs().getData().getCapabilities()), null) + LoganSquare.serialize(capabilitiesOverall.getOcs().getData().getCapabilities()), null, null) .blockingSubscribe(new Observer() { @Override public void onSubscribe(Disposable d) { diff --git a/app/src/main/java/com/nextcloud/talk/jobs/SignalingSettingsJob.java b/app/src/main/java/com/nextcloud/talk/jobs/SignalingSettingsJob.java new file mode 100644 index 000000000..2ca384297 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/jobs/SignalingSettingsJob.java @@ -0,0 +1,152 @@ +/* + * Nextcloud Talk application + * + * @author Mario Danic + * Copyright (C) 2017-2018 Mario Danic + * + * 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 com.nextcloud.talk.jobs; + +import android.text.TextUtils; +import android.util.Log; + +import com.bluelinelabs.logansquare.LoganSquare; +import com.nextcloud.talk.api.NcApi; +import com.nextcloud.talk.application.NextcloudTalkApplication; +import com.nextcloud.talk.events.EventStatus; +import com.nextcloud.talk.models.ExternalSignalingServer; +import com.nextcloud.talk.models.database.UserEntity; +import com.nextcloud.talk.models.json.signaling.settings.SignalingSettingsOverall; +import com.nextcloud.talk.utils.ApiUtils; +import com.nextcloud.talk.utils.bundle.BundleKeys; +import com.nextcloud.talk.utils.database.user.UserUtils; + +import org.greenrobot.eventbus.EventBus; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +import androidx.annotation.NonNull; +import androidx.work.Data; +import androidx.work.OneTimeWorkRequest; +import androidx.work.WorkManager; +import androidx.work.Worker; +import autodagger.AutoInjector; +import io.reactivex.Observer; +import io.reactivex.disposables.Disposable; + +@AutoInjector(NextcloudTalkApplication.class) +public class SignalingSettingsJob extends Worker { + private static final String TAG = "SignalingSettingsJob"; + + @Inject + UserUtils userUtils; + + @Inject + NcApi ncApi; + + @Inject + EventBus eventBus; + + @NonNull + @Override + public Result doWork() { + NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this); + + Data data = getInputData(); + + long internalUserId = data.getLong(BundleKeys.KEY_INTERNAL_USER_ID, -1); + + List userEntityList = new ArrayList<>(); + UserEntity userEntity; + if (internalUserId == -1 || (userEntity = userUtils.getUserWithInternalId(internalUserId)) == null) { + userEntityList = userUtils.getUsers(); + } else { + userEntityList.add(userEntity); + } + + for (int i = 0; i < userEntityList.size(); i++) { + userEntity = userEntityList.get(i); + UserEntity finalUserEntity = userEntity; + ncApi.getSignalingSettings(ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken()), + ApiUtils.getUrlForSignalingSettings(userEntity.getBaseUrl())) + .blockingSubscribe(new Observer() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onNext(SignalingSettingsOverall signalingSettingsOverall) { + ExternalSignalingServer externalSignalingServer; + if (!TextUtils.isEmpty(signalingSettingsOverall.getOcs().getSettings().getExternalSignalingServer()) && + !TextUtils.isEmpty(signalingSettingsOverall.getOcs().getSettings().getExternalSignalingTicket())) { + externalSignalingServer = new ExternalSignalingServer(); + externalSignalingServer.setExternalSignalingServer(signalingSettingsOverall.getOcs().getSettings().getExternalSignalingServer()); + externalSignalingServer.setExternalSignalingTicket(signalingSettingsOverall.getOcs().getSettings().getExternalSignalingTicket()); + + try { + userUtils.createOrUpdateUser(null, null, null, null, null, + null, null, finalUserEntity.getId(), null, null, LoganSquare.serialize(externalSignalingServer)) + .subscribe(new Observer() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onNext(UserEntity userEntity) { + eventBus.post(new EventStatus(finalUserEntity.getId(), EventStatus.EventType.SIGNALING_SETTINGS, true)); + } + + @Override + public void onError(Throwable e) { + eventBus.post(new EventStatus(finalUserEntity.getId(), EventStatus.EventType.SIGNALING_SETTINGS, false)); + } + + @Override + public void onComplete() { + + } + }); + } catch (IOException e) { + Log.e(TAG, "Failed to serialize external signaling server"); + } + } + + } + + @Override + public void onError(Throwable e) { + eventBus.post(new EventStatus(finalUserEntity.getId(), EventStatus.EventType.SIGNALING_SETTINGS, false)); + } + + @Override + public void onComplete() { + + } + }); + } + + OneTimeWorkRequest websocketConnectionsWorker = new OneTimeWorkRequest.Builder(WebsocketConnectionsWorker.class).build(); + WorkManager.getInstance().enqueue(websocketConnectionsWorker); + + return Result.SUCCESS; + } +} diff --git a/app/src/main/java/com/nextcloud/talk/jobs/WebsocketConnectionsWorker.java b/app/src/main/java/com/nextcloud/talk/jobs/WebsocketConnectionsWorker.java new file mode 100644 index 000000000..aaa98426f --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/jobs/WebsocketConnectionsWorker.java @@ -0,0 +1,80 @@ +/* + * Nextcloud Talk application + * + * @author Mario Danic + * Copyright (C) 2017-2018 Mario Danic + * + * 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 com.nextcloud.talk.jobs; + +import android.annotation.SuppressLint; +import android.text.TextUtils; +import android.util.Log; + +import com.bluelinelabs.logansquare.LoganSquare; +import com.nextcloud.talk.application.NextcloudTalkApplication; +import com.nextcloud.talk.models.ExternalSignalingServer; +import com.nextcloud.talk.models.database.UserEntity; +import com.nextcloud.talk.utils.database.user.UserUtils; +import com.nextcloud.talk.webrtc.WebSocketConnectionHelper; + +import java.io.IOException; +import java.util.List; + +import javax.inject.Inject; + +import androidx.annotation.NonNull; +import androidx.work.Worker; +import autodagger.AutoInjector; + +@AutoInjector(NextcloudTalkApplication.class) +public class WebsocketConnectionsWorker extends Worker { + + private static final String TAG = "WebsocketConnectionsWorker"; + + @Inject + UserUtils userUtils; + + @SuppressLint("LongLogTag") + @NonNull + @Override + public Result doWork() { + NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this); + + List userEntityList = userUtils.getUsers(); + UserEntity userEntity; + ExternalSignalingServer externalSignalingServer; + WebSocketConnectionHelper webSocketConnectionHelper = new WebSocketConnectionHelper(); + for (int i = 0; i < userEntityList.size(); i++) { + userEntity = userEntityList.get(i); + if (!TextUtils.isEmpty(userEntity.getExternalSignalingServer())) { + try { + externalSignalingServer = LoganSquare.parse(userEntity.getExternalSignalingServer(), ExternalSignalingServer.class); + if (!TextUtils.isEmpty(externalSignalingServer.getExternalSignalingServer()) && + !TextUtils.isEmpty(externalSignalingServer.getExternalSignalingTicket())) { + webSocketConnectionHelper.getExternalSignalingInstanceForServer( + externalSignalingServer.getExternalSignalingServer(), false, + userEntity, externalSignalingServer.getExternalSignalingTicket()); + } + } catch (IOException e) { + Log.e(TAG, "Failed to parse external signaling server"); + } + } + } + + return Result.SUCCESS; + } +} diff --git a/app/src/main/java/com/nextcloud/talk/models/ExternalSignalingServer.java b/app/src/main/java/com/nextcloud/talk/models/ExternalSignalingServer.java index 9cbb1b1ba..8aeb1c17b 100644 --- a/app/src/main/java/com/nextcloud/talk/models/ExternalSignalingServer.java +++ b/app/src/main/java/com/nextcloud/talk/models/ExternalSignalingServer.java @@ -20,13 +20,19 @@ package com.nextcloud.talk.models; +import com.bluelinelabs.logansquare.annotation.JsonField; +import com.bluelinelabs.logansquare.annotation.JsonObject; + import org.parceler.Parcel; import lombok.Data; @Data @Parcel +@JsonObject public class ExternalSignalingServer { + @JsonField(name = "externalSignalingServer") String externalSignalingServer; + @JsonField(name = "externalSignalingTicket") String externalSignalingTicket; } diff --git a/app/src/main/java/com/nextcloud/talk/models/database/User.java b/app/src/main/java/com/nextcloud/talk/models/database/User.java index 58cc9fb1a..44003c64f 100644 --- a/app/src/main/java/com/nextcloud/talk/models/database/User.java +++ b/app/src/main/java/com/nextcloud/talk/models/database/User.java @@ -57,6 +57,8 @@ public interface User extends Parcelable, Persistable, Serializable { String getClientCertificate(); + String getExternalSignalingServer(); + boolean getCurrent(); boolean getScheduledForDeletion(); diff --git a/app/src/main/java/com/nextcloud/talk/utils/PushUtils.java b/app/src/main/java/com/nextcloud/talk/utils/PushUtils.java index e49c04a2c..4d7302cfe 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/PushUtils.java +++ b/app/src/main/java/com/nextcloud/talk/utils/PushUtils.java @@ -314,7 +314,7 @@ public class PushUtils { null, null, userEntity.getDisplayName(), LoganSquare.serialize(pushConfigurationState), null, - null, userEntity.getId(), null, null) + null, userEntity.getId(), null, null, null) .subscribe(new Observer() { @Override public void onSubscribe(Disposable d) { diff --git a/app/src/main/java/com/nextcloud/talk/utils/database/user/UserUtils.java b/app/src/main/java/com/nextcloud/talk/utils/database/user/UserUtils.java index a338b96e5..4c9f28ddb 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/database/user/UserUtils.java +++ b/app/src/main/java/com/nextcloud/talk/utils/database/user/UserUtils.java @@ -178,7 +178,8 @@ public class UserUtils { @Nullable String userId, @Nullable Long internalId, @Nullable String capabilities, - @Nullable String certificateAlias) { + @Nullable String certificateAlias, + @Nullable String externalSignalingServer) { Result findUserQueryResult; if (internalId == null) { findUserQueryResult = dataStore.select(User.class).where(UserEntity.USERNAME.eq(username). @@ -215,6 +216,10 @@ public class UserUtils { user.setClientCertificate(certificateAlias); } + if (!TextUtils.isEmpty(externalSignalingServer)) { + user.setExternalSignalingServer(externalSignalingServer); + } + user.setCurrent(true); } else { @@ -243,6 +248,9 @@ public class UserUtils { user.setClientCertificate(certificateAlias); } + if (externalSignalingServer != null && !externalSignalingServer.equals(user.getExternalSignalingServer())) { + user.setExternalSignalingServer(externalSignalingServer); + } if (currentUser != null) { user.setCurrent(currentUser); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index eed738704..bacbbcb24 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -42,6 +42,7 @@ Display name fetched Push notifications disabled Failed to fetch capabilities, aborting + Failed to fetch signaling settings Display name couldn\'t be fetched, aborting %1$s app found %1$s app not installed on the server, aborting