Skip to content

Commit bd10ff0

Browse files
fix(jetbrains): avoid connection loops
1 parent db6f5ed commit bd10ff0

File tree

2 files changed

+33
-1
lines changed

2 files changed

+33
-1
lines changed

components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/GitpodCLIService.kt

+7
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import com.intellij.openapi.diagnostic.thisLogger
1515
import com.intellij.openapi.project.Project
1616
import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream
1717
import com.intellij.openapi.util.io.FileUtilRt
18+
import com.intellij.openapi.wm.IdeFocusManager
19+
import com.intellij.ui.AppIcon
1820
import com.intellij.util.application
1921
import com.intellij.util.withFragment
2022
import com.intellij.util.withPath
@@ -65,6 +67,11 @@ class GitpodCLIService : RestService() {
6567
val file = parseFilePath(fileStr) ?: return "invalid file"
6668
val shouldWait = getBooleanParameter("wait", urlDecoder)
6769
return withClient(request, context) {
70+
val toFocus = IdeFocusManager.getGlobalInstance()?.lastFocusedFrame
71+
thisLogger().warn("toFocus = $toFocus")
72+
if (toFocus != null) {
73+
AppIcon.getInstance().requestFocus(toFocus)
74+
}
6875
CommandLineProcessor.doOpenFileOrProject(file, shouldWait).future.get()
6976
}
7077
}

components/ide/jetbrains/gateway-plugin/src/main/kotlin/io/gitpod/jetbrains/gateway/GitpodConnectionProvider.kt

+26-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import com.intellij.ide.BrowserUtil
1212
import com.intellij.openapi.components.service
1313
import com.intellij.openapi.diagnostic.thisLogger
1414
import com.intellij.openapi.progress.ProgressManager
15+
import com.intellij.openapi.ui.Messages
1516
import com.intellij.remote.RemoteCredentialsHolder
1617
import com.intellij.ssh.AskAboutHostKey
1718
import com.intellij.ssh.OpenSshLikeHostKeyVerifier
@@ -31,6 +32,7 @@ import com.jetbrains.gateway.ssh.ClientOverSshTunnelConnector
3132
import com.jetbrains.gateway.ssh.SshHostTunnelConnector
3233
import com.jetbrains.gateway.thinClientLink.ThinClientHandle
3334
import com.jetbrains.rd.util.URI
35+
import com.jetbrains.rd.util.concurrentMapOf
3436
import com.jetbrains.rd.util.lifetime.Lifetime
3537
import io.gitpod.gitpodprotocol.api.entities.WorkspaceInstance
3638
import io.gitpod.jetbrains.icons.GitpodIcons
@@ -49,7 +51,7 @@ import kotlin.coroutines.coroutineContext
4951

5052
@Suppress("UnstableApiUsage", "OPT_IN_USAGE")
5153
class GitpodConnectionProvider : GatewayConnectionProvider {
52-
54+
private val activeConnections = concurrentMapOf<String, Boolean>()
5355
private val gitpod = service<GitpodConnectionService>()
5456

5557
private val httpClient = HttpClient.newBuilder()
@@ -59,6 +61,7 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
5961
private val jacksonMapper = jacksonObjectMapper()
6062
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
6163

64+
6265
override suspend fun connect(
6366
parameters: Map<String, String>,
6467
requestor: ConnectionRequestor
@@ -74,6 +77,7 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
7477
parameters["workspaceId"]!!,
7578
parameters["backendPort"]
7679
)
80+
7781
val client = gitpod.obtainClient(connectParams.gitpodHost)
7882
val connectionLifetime = Lifetime.Eternal.createNested()
7983
val updates = client.listenToWorkspace(connectionLifetime, connectParams.workspaceId)
@@ -144,6 +148,22 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
144148
connectionPanel.repaint()
145149
}
146150

151+
val connectionKeyId = "${connectParams.gitpodHost}-${connectParams.workspaceId}-${connectParams.backendPort}"
152+
153+
if (activeConnections.containsKey(connectionKeyId)) {
154+
val message = "You are trying to connect to a workspace that has a session already open"
155+
val title = "Oops"
156+
val okButton = Messages.getOkButton()
157+
val options = arrayOf(okButton)
158+
val defaultIndex = 0
159+
val icon = Messages.getWarningIcon()
160+
Messages.showDialog(message, title, options, defaultIndex, icon)
161+
162+
val errMessage = "A connection to the same workspace already exists: $connectionKeyId"
163+
thisLogger().warn(errMessage)
164+
throw IllegalStateException(errMessage)
165+
}
166+
147167
GlobalScope.launch {
148168
var thinClient: ThinClientHandle? = null
149169
var thinClientJob: Job? = null
@@ -230,6 +250,10 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
230250
setErrorMessage("failed to fetch JetBrains Gateway Join Link.")
231251
return@launch
232252
}
253+
254+
// TODO: is this the right place?
255+
activeConnections[connectionKeyId] = true
256+
233257
val connector = ClientOverSshTunnelConnector(
234258
connectionLifetime,
235259
SshHostTunnelConnector(credentials),
@@ -239,6 +263,7 @@ class GitpodConnectionProvider : GatewayConnectionProvider {
239263
clientHandle.clientClosed.advise(connectionLifetime) {
240264
application.invokeLater {
241265
connectionLifetime.terminate()
266+
activeConnections.remove(connectionKeyId)
242267
}
243268
}
244269
clientHandle.onClientPresenceChanged.advise(connectionLifetime) {

0 commit comments

Comments
 (0)