Skip to content

Commit 7037a70

Browse files
committed
[grid] Password dialog when the VNC stream is protected
Fixes SeleniumHQ/docker-selenium#1333
1 parent 13c7ef0 commit 7037a70

File tree

3 files changed

+68
-5
lines changed

3 files changed

+68
-5
lines changed

javascript/grid-ui/src/components/LiveView/LiveView.tsx

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import React, { ReactNode } from 'react'
1919
import { createStyles, Theme, withStyles } from '@material-ui/core'
2020
import { StyleRules } from '@material-ui/core/styles'
2121
import RFB from '@novnc/novnc/core/rfb'
22+
import PasswordDialog from './PasswordDialog'
2223

2324
const useStyles = (theme: Theme): StyleRules => createStyles(
2425
{
@@ -47,14 +48,35 @@ interface LiveViewProps {
4748
* smaller than its container, or handled according to `clipViewport` if it
4849
* is larger. Default is false.
4950
*/
50-
scaleViewport?: boolean
51+
scaleViewport?: boolean,
52+
/**
53+
* Callback to close the Live View when the PasswordDialog is prompted and
54+
* the user clicks 'Cancel'
55+
*/
56+
onClose: () => void
5157
}
5258

53-
class LiveView extends React.Component<LiveViewProps, {}> {
59+
interface PasswordDialogState {
60+
open: boolean,
61+
message: string
62+
}
5463

64+
class LiveView extends React.Component<LiveViewProps, PasswordDialogState> {
5565
rfb: any = null
5666
canvas: any = null
5767

68+
constructor (props) {
69+
super(props)
70+
this.state = {
71+
open: false,
72+
message: ''
73+
}
74+
}
75+
76+
handlePasswordDialog = (state: boolean): void => {
77+
this.setState({ open: state })
78+
}
79+
5880
disconnect = () => {
5981
if (!this.rfb) {
6082
return
@@ -74,6 +96,8 @@ class LiveView extends React.Component<LiveViewProps, {}> {
7496
this.rfb = new RFB(this.canvas, this.props.url, {})
7597
this.rfb.scaleViewport = this.props.scaleViewport
7698
this.rfb.background = 'rgb(247,248,248)'
99+
this.rfb.addEventListener('credentialsrequired', this.handleCredentials)
100+
this.rfb.addEventListener('securityfailure', this.securityFailed)
77101
}
78102

79103
registerChild = ref => {
@@ -96,6 +120,30 @@ class LiveView extends React.Component<LiveViewProps, {}> {
96120
this.rfb.scaleViewport = this.props.scaleViewport
97121
}
98122

123+
securityFailed = (event: any) => {
124+
let errorMessage
125+
if ('reason' in event.detail) {
126+
errorMessage =
127+
'Connection has been rejected with reason: ' + event.detail.reason
128+
} else {
129+
errorMessage = 'New connection has been rejected'
130+
}
131+
this.setState({ message: errorMessage })
132+
this.connect()
133+
}
134+
135+
handleCredentials = () => {
136+
this.handlePasswordDialog(true)
137+
}
138+
139+
handleCredentialsEntered = (password: string) => {
140+
this.rfb.sendCredentials({ username: '', password: password })
141+
}
142+
143+
handlePasswordDialogClose = () => {
144+
this.props.onClose()
145+
}
146+
99147
handleMouseEnter = () => {
100148
if (!this.rfb) {
101149
return
@@ -113,6 +161,8 @@ class LiveView extends React.Component<LiveViewProps, {}> {
113161
}
114162

115163
render (): ReactNode {
164+
const { open, message } = this.state
165+
116166
return (
117167
<div
118168
style={
@@ -124,7 +174,16 @@ class LiveView extends React.Component<LiveViewProps, {}> {
124174
ref={this.registerChild}
125175
onMouseEnter={this.handleMouseEnter}
126176
onMouseLeave={this.handleMouseLeave}
127-
/>
177+
>
178+
<PasswordDialog title={'LiveView (VNC) Password'}
179+
open={open}
180+
setOpen={this.handlePasswordDialog}
181+
onConfirm={this.handleCredentialsEntered}
182+
onCancel={this.handlePasswordDialogClose}
183+
>
184+
{message}
185+
</PasswordDialog>
186+
</div>
128187
)
129188
}
130189
}

javascript/grid-ui/src/components/LiveView/PasswordDialog.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ interface State {
6161
}
6262

6363
const PasswordDialog = (props) => {
64-
const { title, children, open, setOpen, onConfirm } = props
64+
const { title, children, open, setOpen, onConfirm, onCancel } = props
6565
const classes = useStyles()
6666
const [values, setValues] = React.useState<State>({
6767
amount: '',
@@ -119,7 +119,10 @@ const PasswordDialog = (props) => {
119119
</DialogContent>
120120
<DialogActions>
121121
<Button variant={'contained'}
122-
onClick={() => setOpen(false)}
122+
onClick={() => {
123+
setOpen(false)
124+
onCancel()
125+
}}
123126
color={'secondary'}>
124127
Cancel
125128
</Button>

javascript/grid-ui/src/components/RunningSessions/RunningSessions.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,7 @@ class RunningSessions extends React.Component<RunningSessionsProps, RunningSessi
464464
<LiveView
465465
url={row.vnc as string}
466466
scaleViewport={true}
467+
onClose={this.handleLiveViewClose}
467468
/>
468469
</DialogContent>
469470
<DialogActions>

0 commit comments

Comments
 (0)