@@ -19,6 +19,7 @@ import React, { ReactNode } from 'react'
19
19
import { createStyles , Theme , withStyles } from '@material-ui/core'
20
20
import { StyleRules } from '@material-ui/core/styles'
21
21
import RFB from '@novnc/novnc/core/rfb'
22
+ import PasswordDialog from './PasswordDialog'
22
23
23
24
const useStyles = ( theme : Theme ) : StyleRules => createStyles (
24
25
{
@@ -47,14 +48,35 @@ interface LiveViewProps {
47
48
* smaller than its container, or handled according to `clipViewport` if it
48
49
* is larger. Default is false.
49
50
*/
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
51
57
}
52
58
53
- class LiveView extends React . Component < LiveViewProps , { } > {
59
+ interface PasswordDialogState {
60
+ open : boolean ,
61
+ message : string
62
+ }
54
63
64
+ class LiveView extends React . Component < LiveViewProps , PasswordDialogState > {
55
65
rfb : any = null
56
66
canvas : any = null
57
67
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
+
58
80
disconnect = ( ) => {
59
81
if ( ! this . rfb ) {
60
82
return
@@ -74,6 +96,8 @@ class LiveView extends React.Component<LiveViewProps, {}> {
74
96
this . rfb = new RFB ( this . canvas , this . props . url , { } )
75
97
this . rfb . scaleViewport = this . props . scaleViewport
76
98
this . rfb . background = 'rgb(247,248,248)'
99
+ this . rfb . addEventListener ( 'credentialsrequired' , this . handleCredentials )
100
+ this . rfb . addEventListener ( 'securityfailure' , this . securityFailed )
77
101
}
78
102
79
103
registerChild = ref => {
@@ -96,6 +120,30 @@ class LiveView extends React.Component<LiveViewProps, {}> {
96
120
this . rfb . scaleViewport = this . props . scaleViewport
97
121
}
98
122
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
+
99
147
handleMouseEnter = ( ) => {
100
148
if ( ! this . rfb ) {
101
149
return
@@ -113,6 +161,8 @@ class LiveView extends React.Component<LiveViewProps, {}> {
113
161
}
114
162
115
163
render ( ) : ReactNode {
164
+ const { open, message } = this . state
165
+
116
166
return (
117
167
< div
118
168
style = {
@@ -124,7 +174,16 @@ class LiveView extends React.Component<LiveViewProps, {}> {
124
174
ref = { this . registerChild }
125
175
onMouseEnter = { this . handleMouseEnter }
126
176
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 >
128
187
)
129
188
}
130
189
}
0 commit comments