@@ -169,13 +169,15 @@ type CDPTypesConfig struct {
169169}
170170
171171type ServerConfig struct {
172- Upstream UpstreamTransportConfig `json:"upstream,omitempty"`
173- Router RouterConfig `json:"router,omitempty"`
174- ClientConfig ClientConfig `json:"client_config,omitempty"`
175- CustomCommands []CustomCommand `json:"custom_commands,omitempty"`
176- CustomEvents []CustomEvent `json:"custom_events,omitempty"`
177- CustomMiddlewares []CustomMiddleware `json:"custom_middlewares,omitempty"`
178- disabled bool
172+ Upstream UpstreamTransportConfig `json:"upstream,omitempty"`
173+ Router RouterConfig `json:"router,omitempty"`
174+ ClientConfig ClientConfig `json:"client_config,omitempty"`
175+ Downstream types.ModCDPDownstreamConfig `json:"downstream,omitempty"`
176+ ServerBrowserToken string `json:"server_browser_token,omitempty"`
177+ CustomCommands []CustomCommand `json:"custom_commands,omitempty"`
178+ CustomEvents []CustomEvent `json:"custom_events,omitempty"`
179+ CustomMiddlewares []CustomMiddleware `json:"custom_middlewares,omitempty"`
180+ disabled bool
179181}
180182
181183var ServerConfigNone = & ServerConfig {disabled : true }
@@ -222,10 +224,10 @@ func (o *Config) UnmarshalJSON(data []byte) error {
222224 return nil
223225}
224226
225- type Handler func ( data any )
227+ type Handler any
226228
227229type handlerEntry struct {
228- handler Handler
230+ handler reflect. Value
229231 pointer uintptr
230232}
231233
@@ -796,6 +798,19 @@ func (c *ModCDPClient) serverConfigureParams(customCommands []map[string]any, cu
796798 if c .Config .ServerConfig .ClientConfig .ClientCDPSendTimeoutMS != 0 {
797799 clientConfig ["client_cdp_send_timeout_ms" ] = c .Config .ServerConfig .ClientConfig .ClientCDPSendTimeoutMS
798800 }
801+ downstream := map [string ]any {}
802+ if c .Config .ServerConfig .Downstream .DownstreamClientTimeoutMS != 0 {
803+ downstream ["downstream_client_timeout_ms" ] = c .Config .ServerConfig .Downstream .DownstreamClientTimeoutMS
804+ }
805+ if c .Config .ServerConfig .Downstream .DownstreamCloseBrowserOnDisconnect != nil {
806+ downstream ["downstream_close_browser_on_disconnect" ] = * c .Config .ServerConfig .Downstream .DownstreamCloseBrowserOnDisconnect
807+ }
808+ if len (downstream ) > 0 {
809+ params ["downstream" ] = downstream
810+ }
811+ if c .Config .ServerConfig .ServerBrowserToken != "" {
812+ params ["server_browser_token" ] = c .Config .ServerConfig .ServerBrowserToken
813+ }
799814 }
800815 if hasUpstreamConfig {
801816 if _ , ok := upstream ["upstream_ws_connect_error_settle_timeout_ms" ]; ! ok {
@@ -1028,23 +1043,27 @@ func (c *ModCDPClient) sendCommand(method string, params map[string]any, cdpSess
10281043}
10291044
10301045func (c * ModCDPClient ) On (event string , handler Handler ) * ModCDPClient {
1046+ handlerValue := reflect .ValueOf (handler )
1047+ if handlerValue .Kind () != reflect .Func {
1048+ panic ("handler must be a function" )
1049+ }
10311050 c .handlersMu .Lock ()
10321051 defer c .handlersMu .Unlock ()
1033- pointer := handlerPointer ( handler )
1052+ pointer := handlerValue . Pointer ( )
10341053 for _ , existing := range c .handlers [event ] {
10351054 if existing .pointer == pointer {
10361055 return c
10371056 }
10381057 }
1039- c .handlers [event ] = append (c .handlers [event ], handlerEntry {handler : handler , pointer : pointer })
1058+ c .handlers [event ] = append (c .handlers [event ], handlerEntry {handler : handlerValue , pointer : pointer })
10401059 return c
10411060}
10421061
10431062func (c * ModCDPClient ) Once (event string , handler Handler ) * ModCDPClient {
10441063 var wrapped Handler
1045- wrapped = func (data any ) {
1064+ wrapped = func (args ... any ) {
10461065 c .Off (event , wrapped )
1047- handler ( data )
1066+ callHandler ( reflect . ValueOf ( handler ), args ... )
10481067 }
10491068 return c .On (event , wrapped )
10501069}
@@ -1075,6 +1094,32 @@ func handlerPointer(handler Handler) uintptr {
10751094 return reflect .ValueOf (handler ).Pointer ()
10761095}
10771096
1097+ func callHandler (handler reflect.Value , args ... any ) {
1098+ handlerType := handler .Type ()
1099+ inputs := make ([]reflect.Value , 0 , len (args ))
1100+ if handlerType .IsVariadic () {
1101+ for _ , arg := range args {
1102+ inputs = append (inputs , reflect .ValueOf (arg ))
1103+ }
1104+ handler .Call (inputs )
1105+ return
1106+ }
1107+ for index := 0 ; index < handlerType .NumIn () && index < len (args ); index ++ {
1108+ input := reflect .ValueOf (args [index ])
1109+ expected := handlerType .In (index )
1110+ if input .IsValid () && input .Type ().AssignableTo (expected ) {
1111+ inputs = append (inputs , input )
1112+ continue
1113+ }
1114+ if input .IsValid () && input .Type ().ConvertibleTo (expected ) {
1115+ inputs = append (inputs , input .Convert (expected ))
1116+ continue
1117+ }
1118+ inputs = append (inputs , reflect .Zero (expected ))
1119+ }
1120+ handler .Call (inputs )
1121+ }
1122+
10781123func (c * ModCDPClient ) Close () {
10791124 c .stopHeartbeat ()
10801125 c .Router .Stop ()
@@ -1258,6 +1303,27 @@ func (c *ModCDPClient) startPingLatencyMeasurement() {
12581303
12591304func (c * ModCDPClient ) startHeartbeat () {
12601305 c .stopHeartbeat ()
1306+ if c .Config .ServerConfig == nil || c .Config .ServerConfig .Downstream .DownstreamCloseBrowserOnDisconnect == nil {
1307+ return
1308+ }
1309+ if ! * c .Config .ServerConfig .Downstream .DownstreamCloseBrowserOnDisconnect {
1310+ return
1311+ }
1312+ stop := make (chan struct {})
1313+ c .heartbeatStop = stop
1314+ interval := time .Duration (c .Config .ClientConfig .ClientHeartbeatIntervalMS ) * time .Millisecond
1315+ go func () {
1316+ ticker := time .NewTicker (interval )
1317+ defer ticker .Stop ()
1318+ for {
1319+ select {
1320+ case <- stop :
1321+ return
1322+ case <- ticker .C :
1323+ _ , _ = c .Send ("Mod.ping" , map [string ]any {"sent_at" : time .Now ().UnixMilli ()})
1324+ }
1325+ }
1326+ }()
12611327}
12621328
12631329func (c * ModCDPClient ) stopHeartbeat () {
@@ -1294,29 +1360,41 @@ func (c *ModCDPClient) handleEventMessage(msg map[string]any) {
12941360 params , _ := msg ["params" ].(map [string ]any )
12951361 if c .Injector != nil && c .Injector .SessionID != "" && sessionID == c .Injector .SessionID {
12961362 if unwrapped , ok := translate .UnwrapEventIfNeeded (method , params , sessionID , c .Injector .SessionID ); ok {
1297- validatedData , valid := c .Types .ParseEventPayload (unwrapped .Event , unwrapped .Data )
1298- if ! valid {
1299- return
1363+ validatedData , err := c .Types .ParseEventPayload (unwrapped .Event , unwrapped .Data )
1364+ if err != nil {
1365+ panic ( err )
13001366 }
13011367 c .handlersMu .Lock ()
13021368 hs := append ([]handlerEntry (nil ), c .handlers [unwrapped .Event ]... )
13031369 c .handlersMu .Unlock ()
13041370 for _ , h := range hs {
1305- go h .handler (validatedData )
1371+ go callHandler (h .handler , validatedData , unwrapped .SessionID )
1372+ }
1373+ c .handlersMu .Lock ()
1374+ wildcardHandlers := append ([]handlerEntry (nil ), c .handlers ["*" ]... )
1375+ c .handlersMu .Unlock ()
1376+ for _ , h := range wildcardHandlers {
1377+ go callHandler (h .handler , unwrapped .Event , validatedData , unwrapped .SessionID )
13061378 }
13071379 }
13081380 return
13091381 }
13101382 if method != "" {
1311- validatedParams , valid := c .Types .ParseEventPayload (method , params )
1312- if ! valid {
1313- return
1383+ validatedParams , err := c .Types .ParseEventPayload (method , params )
1384+ if err != nil {
1385+ panic ( err )
13141386 }
13151387 c .handlersMu .Lock ()
13161388 hs := append ([]handlerEntry (nil ), c .handlers [method ]... )
13171389 c .handlersMu .Unlock ()
13181390 for _ , h := range hs {
1319- go h .handler (validatedParams )
1391+ go callHandler (h .handler , validatedParams , sessionID )
1392+ }
1393+ c .handlersMu .Lock ()
1394+ wildcardHandlers := append ([]handlerEntry (nil ), c .handlers ["*" ]... )
1395+ c .handlersMu .Unlock ()
1396+ for _ , h := range wildcardHandlers {
1397+ go callHandler (h .handler , method , validatedParams , sessionID )
13201398 }
13211399 }
13221400}
0 commit comments