Suspend: continue cleaning

This commit is contained in:
ganfra 2022-04-14 15:36:03 +02:00
parent ed84e38a9b
commit 91daa1ab90
18 changed files with 132 additions and 91 deletions

View File

@ -100,7 +100,7 @@ interface CryptoService {
fun getDeviceInfo(deviceId: String, callback: MatrixCallback<DeviceInfo>)
fun inboundGroupSessionsCount(onlyBackedUp: Boolean): Int
suspend fun inboundGroupSessionsCount(onlyBackedUp: Boolean): Int
fun isRoomEncrypted(roomId: String): Boolean

View File

@ -26,6 +26,7 @@ import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult
import org.matrix.android.sdk.internal.crypto.store.SavedKeyBackupKeyInfo
interface KeysBackupService {
/**
* Retrieve the current version of the backup from the homeserver
*
@ -45,12 +46,12 @@ interface KeysBackupService {
/**
* Facility method to get the total number of locally stored keys
*/
fun getTotalNumbersOfKeys(): Int
suspend fun getTotalNumbersOfKeys(): Int
/**
* Facility method to get the number of backed up keys
*/
fun getTotalNumbersOfBackedUpKeys(): Int
suspend fun getTotalNumbersOfBackedUpKeys(): Int
// /**
// * Start to back up keys immediately.
@ -71,7 +72,7 @@ interface KeysBackupService {
/**
* Return the current progress of the backup
*/
fun getBackupProgress(progressListener: ProgressListener)
suspend fun getBackupProgress(progressListener: ProgressListener)
/**
* Get information about a backup version defined on the homeserver.
@ -128,7 +129,7 @@ interface KeysBackupService {
* Ask if the backup on the server contains keys that we may do not have locally.
* This should be called when entering in the state READY_TO_BACKUP
*/
fun canRestoreKeys(): Boolean
suspend fun canRestoreKeys(): Boolean
/**
* Set trust on a keys backup version.
@ -199,7 +200,7 @@ interface KeysBackupService {
// For gossiping
fun saveBackupRecoveryKey(recoveryKey: String?, version: String?)
fun getKeyBackupRecoveryKeyInfo(): SavedKeyBackupKeyInfo?
suspend fun getKeyBackupRecoveryKeyInfo(): SavedKeyBackupKeyInfo?
suspend fun isValidRecoveryKeyForCurrentVersion(recoveryKey: String): Boolean
}

View File

@ -132,7 +132,7 @@ internal class DefaultCryptoService @Inject constructor(
private val coroutineDispatchers: MatrixCoroutineDispatchers,
private val taskExecutor: TaskExecutor,
private val cryptoCoroutineScope: CoroutineScope,
private val sender: RequestSender,
private val requestSender: RequestSender,
private val crossSigningService: CrossSigningService,
private val verificationService: RustVerificationService,
private val keysBackupService: RustKeyBackupService,
@ -248,7 +248,7 @@ internal class DefaultCryptoService @Inject constructor(
.executeBy(taskExecutor)
}
override fun inboundGroupSessionsCount(onlyBackedUp: Boolean): Int {
override suspend fun inboundGroupSessionsCount(onlyBackedUp: Boolean): Int {
return if (onlyBackedUp) {
keysBackupService.getTotalNumbersOfBackedUpKeys()
} else {
@ -594,7 +594,6 @@ internal class DefaultCryptoService @Inject constructor(
// Timber.e(throwable, "## CRYPTO | onRoomEncryptionEvent ERROR FAILED TO SETUP CRYPTO ")
// } finally {
val userIds = getRoomUserIds(roomId)
olmMachine.updateTrackedUsers(userIds)
setEncryptionInRoom(roomId, event.content?.get("algorithm")?.toString(), userIds)
// }
}
@ -758,14 +757,18 @@ internal class DefaultCryptoService @Inject constructor(
}
private suspend fun uploadKeys(request: Request.KeysUpload) {
val response = this.sender.uploadKeys(request)
this.olmMachine.markRequestAsSent(request.requestId, RequestType.KEYS_UPLOAD, response)
try {
val response = requestSender.uploadKeys(request)
olmMachine.markRequestAsSent(request.requestId, RequestType.KEYS_UPLOAD, response)
} catch (throwable: Throwable) {
Timber.tag(loggerTag.value).e(throwable, "## CRYPTO uploadKeys(): error")
}
}
private suspend fun queryKeys(request: Request.KeysQuery) {
try {
val response = this.sender.queryKeys(request)
this.olmMachine.markRequestAsSent(request.requestId, RequestType.KEYS_QUERY, response)
val response = requestSender.queryKeys(request)
olmMachine.markRequestAsSent(request.requestId, RequestType.KEYS_QUERY, response)
// Update the shields!
cryptoCoroutineScope.launch {
@ -781,18 +784,38 @@ internal class DefaultCryptoService @Inject constructor(
}
private suspend fun sendToDevice(request: Request.ToDevice) {
this.sender.sendToDevice(request)
olmMachine.markRequestAsSent(request.requestId, RequestType.TO_DEVICE, "{}")
try {
requestSender.sendToDevice(request)
olmMachine.markRequestAsSent(request.requestId, RequestType.TO_DEVICE, "{}")
} catch (throwable: Throwable) {
Timber.tag(loggerTag.value).e(throwable, "## CRYPTO sendToDevice(): error")
}
}
private suspend fun claimKeys(request: Request.KeysClaim) {
val response = this.sender.claimKeys(request)
olmMachine.markRequestAsSent(request.requestId, RequestType.KEYS_CLAIM, response)
try {
val response = requestSender.claimKeys(request)
olmMachine.markRequestAsSent(request.requestId, RequestType.KEYS_CLAIM, response)
} catch (throwable: Throwable) {
Timber.tag(loggerTag.value).e(throwable, "## CRYPTO claimKeys(): error")
}
}
private suspend fun signatureUpload(request: Request.SignatureUpload) {
this.sender.sendSignatureUpload(request)
olmMachine.markRequestAsSent(request.requestId, RequestType.SIGNATURE_UPLOAD, "{}")
try {
requestSender.sendSignatureUpload(request)
olmMachine.markRequestAsSent(request.requestId, RequestType.SIGNATURE_UPLOAD, "{}")
} catch (throwable: Throwable) {
Timber.tag(loggerTag.value).e(throwable, "## CRYPTO signatureUpload(): error")
}
}
private suspend fun sendRoomMessage(request: Request.RoomMessage){
try {
requestSender.sendRoomMessage(request)
} catch (throwable: Throwable) {
Timber.tag(loggerTag.value).e(throwable, "## CRYPTO sendRoomMessage(): error")
}
}
private suspend fun sendOutgoingRequests() {
@ -822,7 +845,7 @@ internal class DefaultCryptoService @Inject constructor(
}
is Request.RoomMessage -> {
async {
sender.sendRoomMessage(it)
sendRoomMessage(it)
}
}
is Request.SignatureUpload -> {

View File

@ -833,21 +833,24 @@ internal class OlmMachine(
}
@Throws(CryptoStoreException::class)
fun roomKeyCounts(): RoomKeyCounts {
// TODO convert this to a suspendable method
return inner.roomKeyCounts()
suspend fun roomKeyCounts(): RoomKeyCounts {
return withContext(Dispatchers.Default) {
inner.roomKeyCounts()
}
}
@Throws(CryptoStoreException::class)
fun getBackupKeys(): BackupKeys? {
// TODO this needs to be suspendable
return inner.getBackupKeys()
suspend fun getBackupKeys(): BackupKeys? {
return withContext(Dispatchers.Default) {
inner.getBackupKeys()
}
}
@Throws(CryptoStoreException::class)
fun saveRecoveryKey(key: String?, version: String?) {
// TODO convert this to a suspendable method
inner.saveRecoveryKey(key, version)
suspend fun saveRecoveryKey(key: String?, version: String?) {
withContext(Dispatchers.Default) {
inner.saveRecoveryKey(key, version)
}
}
@Throws(CryptoStoreException::class)

View File

@ -16,6 +16,7 @@
package org.matrix.android.sdk.internal.crypto
import com.squareup.moshi.Moshi
import com.squareup.moshi.Types
import dagger.Lazy
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
@ -80,6 +81,7 @@ internal class RequestSender @Inject constructor(
private val getSessionsDataTask: GetSessionsDataTask,
private val getRoomSessionsDataTask: GetRoomSessionsDataTask,
private val getRoomSessionDataTask: GetRoomSessionDataTask,
private val moshi: Moshi
) {
companion object {
const val REQUEST_RETRY_COUNT = 3
@ -97,16 +99,16 @@ internal class RequestSender @Inject constructor(
suspend fun queryKeys(request: Request.KeysQuery): String {
val params = DownloadKeysForUsersTask.Params(request.users, null)
val response = downloadKeysForUsersTask.executeRetry(params, REQUEST_RETRY_COUNT)
val adapter = MoshiProvider.providesMoshi().adapter(KeysQueryResponse::class.java)
val adapter = moshi.adapter(KeysQueryResponse::class.java)
return adapter.toJson(response)!!
}
suspend fun uploadKeys(request: Request.KeysUpload): String {
val body = MoshiProvider.providesMoshi().adapter<JsonDict>(Map::class.java).fromJson(request.body)!!
val body = moshi.adapter<JsonDict>(Map::class.java).fromJson(request.body)!!
val params = UploadKeysTask.Params(body)
val response = uploadKeysTask.executeRetry(params, REQUEST_RETRY_COUNT)
val adapter = MoshiProvider.providesMoshi().adapter(KeysUploadResponse::class.java)
val adapter = moshi.adapter(KeysUploadResponse::class.java)
return adapter.toJson(response)!!
}
@ -127,7 +129,7 @@ internal class RequestSender @Inject constructor(
}
suspend fun sendRoomMessage(eventType: String, roomId: String, content: String, transactionId: String): String {
val adapter = MoshiProvider.providesMoshi().adapter<Content>(Map::class.java)
val adapter = moshi.adapter<Content>(Map::class.java)
val jsonContent = adapter.fromJson(content)
val event = Event(eventType, transactionId, jsonContent, roomId = roomId)
val params = SendVerificationMessageTask.Params(event)
@ -143,7 +145,7 @@ internal class RequestSender @Inject constructor(
}
private suspend fun sendSignatureUpload(body: String) {
val adapter = MoshiProvider.providesMoshi().adapter<Map<String, Map<String, Any>>>(Map::class.java)
val adapter = moshi.adapter<Map<String, Map<String, Any>>>(Map::class.java)
val signatures = adapter.fromJson(body)!!
val params = UploadSignaturesTask.Params(signatures)
this.signaturesUploadTask.executeRetry(params, REQUEST_RETRY_COUNT)
@ -153,7 +155,7 @@ internal class RequestSender @Inject constructor(
request: UploadSigningKeysRequest,
interactiveAuthInterceptor: UserInteractiveAuthInterceptor?
) {
val adapter = MoshiProvider.providesMoshi().adapter(RestKeyInfo::class.java)
val adapter = moshi.adapter(RestKeyInfo::class.java)
val masterKey = adapter.fromJson(request.masterKey)!!.toCryptoModel()
val selfSigningKey = adapter.fromJson(request.selfSigningKey)!!.toCryptoModel()
val userSigningKey = adapter.fromJson(request.userSigningKey)!!.toCryptoModel()
@ -195,8 +197,7 @@ internal class RequestSender @Inject constructor(
}
suspend fun sendToDevice(eventType: String, body: String, transactionId: String) {
val adapter = MoshiProvider
.providesMoshi()
val adapter = moshi
.newBuilder()
.add(CheckNumberType.JSON_ADAPTER_FACTORY)
.build()
@ -252,7 +253,7 @@ internal class RequestSender @Inject constructor(
val keys = adapter.fromJson(request.rooms)!!
val params = StoreSessionsDataTask.Params(request.version, KeysBackupData(keys))
val response = backupRoomKeysTask.executeRetry(params, REQUEST_RETRY_COUNT)
val responseAdapter = MoshiProvider.providesMoshi().adapter(BackupKeysResult::class.java)
val responseAdapter = moshi.adapter(BackupKeysResult::class.java)
return responseAdapter.toJson(response)!!
}

View File

@ -237,7 +237,7 @@ internal class RustKeyBackupService @Inject constructor(
}
}
override fun canRestoreKeys(): Boolean {
override suspend fun canRestoreKeys(): Boolean {
val keyCountOnServer = keysBackupVersion?.count ?: return false
val keyCountLocally = getTotalNumbersOfKeys()
@ -246,11 +246,11 @@ internal class RustKeyBackupService @Inject constructor(
return keyCountLocally < keyCountOnServer
}
override fun getTotalNumbersOfKeys(): Int {
override suspend fun getTotalNumbersOfKeys(): Int {
return olmMachine.roomKeyCounts().total.toInt()
}
override fun getTotalNumbersOfBackedUpKeys(): Int {
override suspend fun getTotalNumbersOfBackedUpKeys(): Int {
return olmMachine.roomKeyCounts().backedUp.toInt()
}
@ -405,7 +405,7 @@ internal class RustKeyBackupService @Inject constructor(
}
}
override fun getBackupProgress(progressListener: ProgressListener) {
override suspend fun getBackupProgress(progressListener: ProgressListener) {
val backedUpKeys = getTotalNumbersOfBackedUpKeys()
val total = getTotalNumbersOfKeys()
@ -725,7 +725,7 @@ internal class RustKeyBackupService @Inject constructor(
}
}
override fun getKeyBackupRecoveryKeyInfo(): SavedKeyBackupKeyInfo? {
override suspend fun getKeyBackupRecoveryKeyInfo(): SavedKeyBackupKeyInfo? {
val info = olmMachine.getBackupKeys() ?: return null
return SavedKeyBackupKeyInfo(info.recoveryKey, info.backupVersion)
}

View File

@ -64,12 +64,12 @@ fun Session.startSyncing(context: Context) {
/**
* Tell is the session has unsaved e2e keys in the backup
*/
fun Session.hasUnsavedKeys(): Boolean {
suspend fun Session.hasUnsavedKeys(): Boolean {
return cryptoService().inboundGroupSessionsCount(false) > 0 &&
cryptoService().keysBackupService().state != KeysBackupState.ReadyToBackUp
}
fun Session.cannotLogoutSafely(): Boolean {
suspend fun Session.cannotLogoutSafely(): Boolean {
// has some encrypted chat
return hasUnsavedKeys() ||
// has local cross signing keys

View File

@ -26,5 +26,8 @@ import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionR
data class KeysBackupSettingViewState(val keysBackupVersionTrust: Async<KeysBackupVersionTrust> = Uninitialized,
val keysBackupState: KeysBackupState? = null,
val keysBackupVersion: KeysVersionResult? = null,
val remainingKeysToBackup: Int = 0,
val deleteBackupRequest: Async<Unit> = Uninitialized) :
MavericksState

View File

@ -124,10 +124,7 @@ class KeysBackupSettingsRecyclerViewController @Inject constructor(
style(ItemStyle.BIG_TEXT)
hasIndeterminateProcess(true)
val totalKeys = host.session.cryptoService().inboundGroupSessionsCount(false)
val backedUpKeys = host.session.cryptoService().inboundGroupSessionsCount(true)
val remainingKeysToBackup = totalKeys - backedUpKeys
val remainingKeysToBackup = data.remainingKeysToBackup
if (data.keysBackupVersionTrust()?.usable == false) {
description(host.stringProvider.getString(R.string.keys_backup_settings_untrusted_backup).toEpoxyCharSequence())

View File

@ -18,7 +18,6 @@ package im.vector.app.features.crypto.keysbackup.settings
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.MavericksViewModelFactory
import com.airbnb.mvrx.Success
import com.airbnb.mvrx.Uninitialized
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
@ -32,7 +31,6 @@ import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener
import timber.log.Timber
class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialState: KeysBackupSettingViewState,
session: Session
@ -46,6 +44,7 @@ class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialS
companion object : MavericksViewModelFactory<KeysBackupSettingsViewModel, KeysBackupSettingViewState> by hiltMavericksViewModelFactory()
private val cryptoService = session.cryptoService()
private val keysBackupService: KeysBackupService = session.cryptoService().keysBackupService()
init {
@ -75,34 +74,12 @@ class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialS
private fun getKeysBackupTrust() = withState { state ->
val versionResult = keysBackupService.keysBackupVersion
Timber.d("BACKUP: HEEEEEEE $versionResult ${state.keysBackupVersionTrust}")
if (state.keysBackupVersionTrust is Uninitialized && versionResult != null) {
setState {
copy(
keysBackupVersionTrust = Loading(),
deleteBackupRequest = Uninitialized
)
}
Timber.d("BACKUP: HEEEEEEE TWO")
viewModelScope.launch {
try {
val data = keysBackupService.getKeysBackupTrust(versionResult)
Timber.d("BACKUP: HEEEE suceeeded $data")
setState {
copy(
keysBackupVersionTrust = Success(data)
)
}
} catch (failure: Throwable) {
Timber.d("BACKUP: HEEEE FAILED $failure")
setState {
copy(
keysBackupVersionTrust = Fail(failure)
)
}
}
setState { copy(deleteBackupRequest = Uninitialized) }
suspend {
keysBackupService.getKeysBackupTrust(versionResult)
}.execute {
copy(keysBackupVersionTrust = it)
}
}
}
@ -119,10 +96,24 @@ class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialS
keysBackupVersion = keysBackupService.keysBackupVersion
)
}
when (newState) {
KeysBackupState.BackingUp, KeysBackupState.WillBackUp -> updateKeysCount()
else -> Unit
}
getKeysBackupTrust()
}
private fun updateKeysCount() {
viewModelScope.launch {
val totalKeys = cryptoService.inboundGroupSessionsCount(false)
val backedUpKeys = cryptoService.inboundGroupSessionsCount(true)
val remainingKeysToBackup = totalKeys - backedUpKeys
setState {
copy(remainingKeysToBackup = remainingKeysToBackup)
}
}
}
private fun deleteCurrentBackup() {
val keysBackupService = keysBackupService

View File

@ -80,6 +80,7 @@ class HomeDrawerFragment @Inject constructor(
}
// Sign out
views.homeDrawerHeaderSignoutView.debouncedClicks {
signout()
sharedActionViewModel.post(HomeActivitySharedAction.CloseDrawer)
SignOutUiWorker(requireActivity()).perform()
}
@ -118,4 +119,8 @@ class HomeDrawerFragment @Inject constructor(
navigator.openDebug(requireActivity())
}
}
private fun signout() {
}
}

View File

@ -95,7 +95,7 @@ class SoftLogoutActivity : LoginActivity() {
MainActivity.restartApp(this, MainActivityArgs())
}
views.loginLoading.isVisible = softLogoutViewState.isLoading()
views.loginLoading.isVisible = softLogoutViewState.isLoading
}
companion object {

View File

@ -34,6 +34,7 @@ import im.vector.app.features.signout.soft.epoxy.loginRedButtonItem
import im.vector.app.features.signout.soft.epoxy.loginTextItem
import im.vector.app.features.signout.soft.epoxy.loginTitleItem
import im.vector.app.features.signout.soft.epoxy.loginTitleSmallItem
import org.matrix.android.sdk.api.extensions.orFalse
import javax.inject.Inject
class SoftLogoutController @Inject constructor(
@ -52,6 +53,7 @@ class SoftLogoutController @Inject constructor(
override fun buildModels() {
val safeViewState = viewState ?: return
if (safeViewState.hasUnsavedKeys is Incomplete) return
buildHeader(safeViewState)
buildForm(safeViewState)
@ -78,7 +80,7 @@ class SoftLogoutController @Inject constructor(
state.userDisplayName,
state.userId))
}
if (state.hasUnsavedKeys) {
if (state.hasUnsavedKeys().orFalse()) {
loginTextItem {
id("signText2")
text(host.stringProvider.getString(R.string.soft_logout_signin_e2e_warning_notice))

View File

@ -32,6 +32,7 @@ import im.vector.app.features.login.AbstractLoginFragment
import im.vector.app.features.login.LoginAction
import im.vector.app.features.login.LoginMode
import im.vector.app.features.login.LoginViewEvents
import org.matrix.android.sdk.api.extensions.orFalse
import javax.inject.Inject
/**
@ -118,7 +119,7 @@ class SoftLogoutFragment @Inject constructor(
withState(softLogoutViewModel) { state ->
cleanupUi()
val messageResId = if (state.hasUnsavedKeys) {
val messageResId = if (state.hasUnsavedKeys().orFalse()) {
R.string.soft_logout_clear_data_dialog_e2e_warning_content
} else {
R.string.soft_logout_clear_data_dialog_content

View File

@ -69,7 +69,6 @@ class SoftLogoutViewModel @AssistedInject constructor(
userId = userId,
deviceId = session.sessionParams.deviceId.orEmpty(),
userDisplayName = session.getUser(userId)?.displayName ?: userId,
hasUnsavedKeys = session.hasUnsavedKeys()
)
} else {
SoftLogoutViewState(
@ -77,17 +76,25 @@ class SoftLogoutViewModel @AssistedInject constructor(
userId = "",
deviceId = "",
userDisplayName = "",
hasUnsavedKeys = false
)
}
}
}
init {
checkHasUnsavedKeys()
// Get the supported login flow
getSupportedLoginFlow()
}
private fun checkHasUnsavedKeys() {
suspend {
session.hasUnsavedKeys()
}.execute {
copy(hasUnsavedKeys = it)
}
}
private fun getSupportedLoginFlow() {
viewModelScope.launch {
authenticationService.cancelPendingLoginOrRegistration()

View File

@ -30,13 +30,12 @@ data class SoftLogoutViewState(
val userId: String,
val deviceId: String,
val userDisplayName: String,
val hasUnsavedKeys: Boolean,
val hasUnsavedKeys: Async<Boolean> = Uninitialized,
val enteredPassword: String = ""
) : MavericksState {
fun isLoading(): Boolean {
return asyncLoginAction is Loading ||
val isLoading: Boolean =
asyncLoginAction is Loading ||
// Keep loading when it is success because of the delay to switch to the next Activity
asyncLoginAction is Success
}
}

View File

@ -130,14 +130,14 @@ class ServerBackupStatusViewModel @AssistedInject constructor(@Assisted initialS
/**
* Safe way to get the number of keys to backup
*/
fun getNumberOfKeysToBackup(): Int {
private suspend fun getNumberOfKeysToBackup(): Int {
return session.cryptoService().inboundGroupSessionsCount(false)
}
/**
* Safe way to tell if there are more keys on the server
*/
fun canRestoreKeys(): Boolean {
private suspend fun canRestoreKeys(): Boolean {
return session.cryptoService().keysBackupService().canRestoreKeys()
}
@ -161,5 +161,5 @@ class ServerBackupStatusViewModel @AssistedInject constructor(@Assisted initialS
}
}
override fun handle(action: EmptyAction) {}
override fun handle(action: EmptyAction) = Unit
}

View File

@ -17,17 +17,25 @@
package im.vector.app.features.workers.signout
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.lifecycleScope
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.extensions.cannotLogoutSafely
import im.vector.app.core.extensions.singletonEntryPoint
import im.vector.app.features.MainActivity
import im.vector.app.features.MainActivityArgs
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.session.Session
class SignOutUiWorker(private val activity: FragmentActivity) {
fun perform() {
val session = activity.singletonEntryPoint().activeSessionHolder().getSafeActiveSession() ?: return
activity.lifecycleScope.perform(session)
}
private fun CoroutineScope.perform(session: Session) = launch {
if (session.cannotLogoutSafely()) {
// The backup check on logout flow has to be displayed if there are keys in the store, and the keys backup state is not Ready
val signOutDialog = SignOutBottomSheetDialogFragment.newInstance()