Danp2 / au3WebDriver

Web Driver UDF for AutoIt
MIT License
108 stars 23 forks source link

Webdriver BiDi support #113

Open Danp2 opened 2 years ago

Danp2 commented 2 years ago

https://github.com/w3c/webdriver-bidi https://developer.chrome.com/blog/webdriver-bidi/ https://wiki.mozilla.org/WebDriver/RemoteProtocol/WebDriver_BiDi

Danp2 commented 2 years ago

Chromium BiDi progress [Outdated]

Mozilla BiDi progress

Mozilla BiDi status wiki

Danp2 commented 2 years ago

Initial coding can be found here

Danp2 commented 2 years ago

Here is what I'm currently using to test the new bidi commands --

CLICK ME

```autoit #include "wd_core.au3" #include "wd_capabilities.au3" #include "wd_bidi.au3" ;~ $_WD_Debug = $_WD_DEBUG_Full _WD_CapabilitiesDefine($_WD_KEYS__STANDARD_PRIMITIVE, 'webSocketUrl') _WD_CapabilitiesDefine($_WD_KEYS__STANDARD_PRIMITIVE, '"moz:debuggerAddress"') Global $url = 'https://google.com/' Global $bHeadless = False Global $sCapabilities = SetupGecko($bHeadless) ;~ Local $sCapabilities = SetupChrome($bHeadless) Global $iWebDriver_PID = _WD_Startup() Global $sSession = _WD_CreateSession($sCapabilities) If @error <> $_WD_ERROR_Success Then ConsoleWrite("Session not created..." & @error) Exit EndIf _WD_Navigate($sSession, $url) Global $sURL = _WD_BidiGetWebsocketURL($sSession) Global $hWS = _WD_BidiConnect($sURL) Global $sContext = _WD_BidiGetContextID() Global $oParams = Json_ObjCreate() Global $sResult = _WD_BidiExecute('session.status', $oParams) ;### Debug CONSOLE ↓↓↓ ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $sResult = ' & $sResult & @CRLF & '>Error code: ' & @error & @CRLF) Json_ObjPut($oParams, 'context', $sContext) $sResult = _WD_BidiExecute('browsingContext.close', $oParams) ;### Debug CONSOLE ↓↓↓ ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $sResult = ' & $sResult & @CRLF & '>Error code: ' & @error & @CRLF) $sResult = _WD_BidiDisconnect() ;### Debug CONSOLE ↓↓↓ ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $sResult = ' & $sResult & @CRLF & '>Error code: ' & @error & @CRLF) Func SetupGecko($bHeadless) _WD_Option('Driver', 'geckodriver.exe') _WD_Option('DriverParams', '--log trace') _WD_Option('Port', 4444) _WD_CapabilitiesStartup() _WD_CapabilitiesAdd('alwaysMatch', 'firefox') _WD_CapabilitiesAdd('browserName', 'firefox') _WD_CapabilitiesAdd('acceptInsecureCerts', True) _WD_CapabilitiesAdd('webSocketUrl', True) _WD_CapabilitiesAdd('"moz:debuggerAddress"', True) If $bHeadless Then _WD_CapabilitiesAdd('args', '--headless') _WD_CapabilitiesDump(@ScriptLineNumber) ; dump current Capabilities setting to console - only for testing in this demo Local $sCapabilities = _WD_CapabilitiesGet() Return $sCapabilities EndFunc ;==>SetupGecko Func SetupChrome($bHeadless) _WD_Option('Driver', 'chromedriver.exe') _WD_Option('Port', 9515) _WD_Option('DriverParams', '--verbose --log-path="' & @ScriptDir & '\chrome.log"') ;~ Local $sCapabilities = '{"capabilities": {"alwaysMatch": {"goog:chromeOptions": {"w3c": true, "excludeSwitches": [ "enable-automation"]}}}}' _WD_CapabilitiesStartup() _WD_CapabilitiesAdd('alwaysMatch', 'chrome') _WD_CapabilitiesAdd('w3c', True) _WD_CapabilitiesAdd('excludeSwitches', 'enable-automation') _WD_CapabilitiesAdd('webSocketUrl', True) If $bHeadless Then _WD_CapabilitiesAdd('args', '--headless') ;~ _WD_CapabilitiesDump(@ScriptLineNumber) ; dump current Capabilities setting to console - only for testing in this demo Local $sCapabilities = _WD_CapabilitiesGet() Return $sCapabilities EndFunc ;==>SetupChrome ```

Works fine for me with Firefox. Chrome responds with "not supported"

Danp2 commented 2 years ago

WPT tracker

Danp2 commented 2 years ago

Found that calls to WinHttpWebSocketReceive would cause the process to hang when there wasn't pending data to receive. Switched to using websocat to perform all websocket activity.

Danp2 commented 2 years ago

Here is the latest revision of code I'm using to test the new bidi commands --

CLICK ME

```autoit #AutoIt3Wrapper_au3check_parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 #include #include #include #include #include #include #include #include #include "wd_core.au3" #include "wd_helper.au3" #include "wd_capabilities.au3" #include "wd_bidi.au3" Global $sSession Global Const $aBrowsers[][2] = _ [ _ ["Firefox", SetupGecko], _ ["Chrome", SetupChrome], _ ["MSEdge", SetupEdge], _ ["Opera", SetupOpera] _ ] Global Const $aCommands[][3] = _ [ _ ["Session Status", "session.status", "{}"], _ ["Session New", "session.new", "{}"], _ ["Session Subscribe", "session.subscribe", '{"events":["log.entryAdded"]}'], _ ["Session Unsubscribe", "session.unsubscribe", '{"events":["log.entryAdded"]}'] _ ] Main() Func Main() ;~ $_WD_Debug = $_WD_DEBUG_Full _WD_CapabilitiesDefine($_WD_KEYS__STANDARD_PRIMITIVE, 'webSocketUrl') _WD_CapabilitiesDefine($_WD_KEYS__STANDARD_PRIMITIVE, '"moz:debuggerAddress"') Local $hGUI = GUICreate("BiDi Tester", 615, 325, -1, -1) GUICtrlCreateLabel("Command", 15, 15) Local $idCommands = GUICtrlCreateCombo("", 75, 12, 200, 20, $CBS_DROPDOWNLIST) Local $sData = _ArrayToString($aCommands, Default, Default, Default, "|", 0, 0) GUICtrlSetData($idCommands, $sData) GUICtrlSetData($idCommands, $aCommands[0][0]) Local $iCommand = GUICtrlCreateInput($aCommands[0][1] & "|" & $aCommands[0][2], 24, 40, 409, 21) Local $iSend = GUICtrlCreateButton("Send", 448, 39, 75, 25) Local $iAsync = GUICtrlCreateCheckbox("Async?", 530, 40) Local $iLaunch = GUICtrlCreateButton("Launch", 15, 75, 75, 25) Local $iMenu = GUICtrlCreateContextMenu($iLaunch) For $i = 0 To UBound($aBrowsers, 1) - 1 GUICtrlCreateMenuItem($aBrowsers[$i][0], $iMenu, Default, 1) Next Local $iShow = GUICtrlCreateButton("Show Maps", 95, 75, 75, 25) Local $iMenu2 = GUICtrlCreateContextMenu($iShow) Local $iEvents = GUICtrlCreateMenuItem("Events", $iMenu2, Default, 1) Local $iResults = GUICtrlCreateMenuItem("Results", $iMenu2, Default, 1) GUICtrlSetState($iEvents, $GUI_CHECKED) Local $iPollEvents = GUICtrlCreateCheckbox("Poll Events?", 175, 77) Local $iEdit = GUICtrlCreateEdit("", 15, 110, 585, 200) Local $iBrowser = 0, $iStartPopup = $iMenu + 1, $iEndPopup = $iStartPopup + UBound($aBrowsers, 1) Local $iSelect, $aCmd, $sCmd, $sOpt, $bAsync, $sResult, $mMap, $nMsg GUICtrlSetState($iStartPopup, $GUI_CHECKED) GUISetState(@SW_SHOW) #forceref $iResults While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE _WD_BidiDisconnect() Exit Case $iSend $aCmd = StringSplit(GUICtrlRead($iCommand), '|') $sCmd = $aCmd[0] ? $aCmd[1] : "" $sOpt = ($aCmd[0] = 2) ? Json_Decode($aCmd[2]) : "" $bAsync = (GUICtrlRead($iAsync) = $GUI_CHECKED) $sResult = DoSend($sCmd, $sOpt, $bAsync) GUICtrlSetData($iEdit, $sResult & @CRLF, 1) Case $iLaunch DoLaunch($iBrowser) Case $idCommands $iSelect = _GUICtrlComboBox_GetCurSel($idCommands) GUICtrlSetData($iCommand, $aCommands[$iSelect][1] & "|" & $aCommands[$iSelect][2]) Case $iShow If BitAnd(GUICtrlRead($iEvents), $GUI_CHECKED) Then $mMap = __WD_BidiActions('maps', 'event') _Map_Display($mMap, 'events') Else $mMap = __WD_BidiActions('maps', 'result') _Map_Display($mMap, 'results') EndIf ;~ Case $iEvents To $iResults ;~ $iMap = $nMsg - $iEvents Case $iStartPopup To $iEndPopup $iBrowser = $nMsg - $iStartPopup EndSwitch DoPoll($iPollEvents, $iEdit) WEnd GUIDelete($hGUI) EndFunc Func DoLaunch($iBrowser) Local $bHeadless = False Local $sURL = 'https://google.com/' ; Execute browser setup routine for user's browser selection Local $sCapabilities = Call($aBrowsers[$iBrowser][1], $bHeadless) _WD_Startup() $sSession = _WD_CreateSession($sCapabilities) _WD_Navigate($sSession, $sURL) _WD_BidiConnect($sSession) EndFunc Func DoSend($sCommand, $oParams, $bAsync) ;~ Local $oParams = Json_ObjCreate() Local $sResult = _WD_BidiExecute($sCommand, $oParams, $bAsync) Return $sResult EndFunc Func DoPoll($iPollEvents, $iEdit) Local $_WD_DEBUG_Saved = $_WD_DEBUG ; save current DEBUG level If $_WD_DEBUG <> $_WD_DEBUG_Full Then $_WD_DEBUG = $_WD_DEBUG_None __WD_BidiActions('receive') If GUICtrlRead($iPollEvents) = $GUI_CHECKED Then Local $sResult = _WD_BidiGetEvent() If $sResult Then GUICtrlSetData($iEdit, $sResult & @CRLF, 1) Endif $_WD_DEBUG = $_WD_DEBUG_Saved ; restore DEBUG level EndFunc ;~ __TCPSendLine($_WD_BiDi_Socket, '{"id":2,"method":"session.subscribe","params":{"events":["log.entryAdded"]}}') ; Prevent logging from __WD_BidiActions if not in Full debug mode #cs While Not $bExitFlag If @error Then ExitLoop If $bLine Then ;### Debug CONSOLE ↓↓↓ ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $bLine = ' & $bLine & @CRLF & '>Error code: ' & @error & @CRLF) ElseIf _IsPressed("12", $hDLL) Then ;~ __TCPSendLine($_WD_BiDi_Socket, '{"id":1,"method":"session.status","params":{}}') ;~ $oParams = Json_ObjCreate() ;~ _WD_BidiExecute("session.status", $oParams) Local $sResult = __WD_BidiActions("receive", "event") If $sResult Then ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $sResult = ' & $sResult & @CRLF & '>Error code: ' & @error & @CRLF) EndIf Sleep(100) WEnd #ce Func SetupGecko($bHeadless) _WD_Option('Driver', 'geckodriver.exe') _WD_Option('DriverParams', '--log trace') _WD_Option('Port', 4444) _WD_CapabilitiesStartup() _WD_CapabilitiesAdd('alwaysMatch', 'firefox') _WD_CapabilitiesAdd('browserName', 'firefox') _WD_CapabilitiesAdd('acceptInsecureCerts', True) _WD_CapabilitiesAdd('webSocketUrl', True) _WD_CapabilitiesAdd('"moz:debuggerAddress"', True) ; enable experimental BiDi commands _WD_CapabilitiesAdd('prefs', 'remote.experimental.enabled', true) If $bHeadless Then _WD_CapabilitiesAdd('args', '--headless') _WD_CapabilitiesDump(@ScriptLineNumber) ; dump current Capabilities setting to console - only for testing in this demo Local $sCapabilities = _WD_CapabilitiesGet() Return $sCapabilities EndFunc ;==>SetupGecko Func SetupChrome($bHeadless) _WD_Option('Driver', 'chromedriver.exe') _WD_Option('Port', 9515) _WD_Option('DriverParams', '--verbose --log-path="' & @ScriptDir & '\chrome.log"') ;~ Local $sCapabilities = '{"capabilities": {"alwaysMatch": {"goog:chromeOptions": {"w3c": true, "excludeSwitches": [ "enable-automation"]}}}}' _WD_CapabilitiesStartup() _WD_CapabilitiesAdd('alwaysMatch', 'chrome') _WD_CapabilitiesAdd('w3c', True) _WD_CapabilitiesAdd('webSocketUrl', True) _WD_CapabilitiesAdd('excludeSwitches', 'enable-automation') If $bHeadless Then _WD_CapabilitiesAdd('args', '--headless') _WD_CapabilitiesDump(@ScriptLineNumber) ; dump current Capabilities setting to console - only for testing in this demo Local $sCapabilities = _WD_CapabilitiesGet() Return $sCapabilities EndFunc ;==>SetupChrome Func SetupEdge($bHeadless) _WD_Option('Driver', 'msedgedriver.exe') _WD_Option('Port', 9515) _WD_Option('DriverParams', '--verbose --log-path="' & @ScriptDir & '\msedge.log"') ;~ Local $sCapabilities = '{"capabilities": {"alwaysMatch": {"ms:edgeOptions": {"excludeSwitches": [ "enable-automation"]}}}}' _WD_CapabilitiesStartup() _WD_CapabilitiesAdd('alwaysMatch', 'msedge') _WD_CapabilitiesAdd('webSocketUrl', True) _WD_CapabilitiesAdd('excludeSwitches', 'enable-automation') If $bHeadless Then _WD_CapabilitiesAdd('args', '--headless') _WD_CapabilitiesDump(@ScriptLineNumber) ; dump current Capabilities setting to console - only for testing in this demo Local $sCapabilities = _WD_CapabilitiesGet() Return $sCapabilities EndFunc ;==>SetupEdge Func SetupOpera($bHeadless) _WD_Option('Driver', 'operadriver.exe') _WD_Option('Port', 9515) _WD_Option('DriverParams', '--verbose --log-path="' & @ScriptDir & '\opera.log"') ;~ Local $sCapabilities = '{"capabilities": {"alwaysMatch":{"goog:chromeOptions": {"w3c":true, "excludeSwitches":["enable-automation"], "binary":"C:\\Users\\......\\AppData\\Local\\Programs\\Opera\\opera.exe"}}}}' _WD_CapabilitiesStartup() _WD_CapabilitiesAdd('alwaysMatch', 'opera') _WD_CapabilitiesAdd('w3c', True) _WD_CapabilitiesAdd('webSocketUrl', True) _WD_CapabilitiesAdd('excludeSwitches', 'enable-automation') ; REMARK ; using 32bit operadriver.exe requires to set 'binary' capabilities, ; using 64bit operadriver.exe dosen't require to set this capability, but at the same time setting is not affecting the script ; So this is good habit to setup for any case. _WD_CapabilitiesAdd('binary', _WD_GetBrowserPath("opera")) ConsoleWrite("wd_demo.au3: _WD_GetBrowserPath() > " & _WD_GetBrowserPath("opera") & @CRLF) If $bHeadless Then _WD_CapabilitiesAdd('args', '--headless') _WD_CapabilitiesDump(@ScriptLineNumber) ; dump current Capabilities setting to console - only for testing in this demo Local $sCapabilities = _WD_CapabilitiesGet() Return $sCapabilities EndFunc ;==>SetupOpera ; #FUNCTION# ==================================================================================================================== ; Name ..........: _Map_Display ; Description ...: Displays the Key & Value pair in a ListView. ; Syntax ........: _Map_Display(Byref $mMap[, $sTitle = "Map Display"]) ; Parameters ....: $mMap - [in/out] Map to display. ; $sTitle - [optional] Title for the Display window. Default is "Map Display". ; Return values .: Success: True ; Failure: False & @error is set to non-zero ; Author ........: Damon Harris (TheDcoder) ; Modified ......: ; Remarks .......: This function is intended to be used for Debugging. Its still in development, so it does not provide flexible ; functionality like _ArrayDisplay ; Related .......: _ArrayDisplay ; Link ..........: ; Example .......: Yes ; =============================================================================================================================== Func _Map_Display(ByRef $mMap, $sTitle = "Map Display") If Not IsMap($mMap) Then Return SetError(1, 0, False) EndIf Local Const $esDataSepChar = Opt("GUIDataSeparatorChar") ; Get the GUIDataSeparatorChar Local $hGUI = GUICreate($sTitle, 300, 300, -1, -1, BitOR($WS_MINIMIZEBOX, $WS_CAPTION, $WS_POPUP, $WS_SYSMENU, $WS_SIZEBOX, $WS_MAXIMIZEBOX)) ; Create the $hGUI Local $idListView = GUICtrlCreateListView("Key|Value", 0, 0, 300, 264) ; Create the $idListView Local $idCopyButton = GUICtrlCreateButton("Copy Text", 3, 268, 146, 30) ; Create the $idCopyButton GUICtrlSetResizing(-1, $GUI_DOCKAUTO) ; Set Resizing Local $idExitButton = GUICtrlCreateButton("Exit Script", 149, 268, 148, 30) ; Create the $idExitButton GUICtrlSetResizing(-1, $GUI_DOCKAUTO) ; Set Resizing Local $aKeys = MapKeys($mMap) ; Get the $aKeys in the map ;Local $iKeyCount = UBound($mMap) ; Get the $iKeyCount Local $sContents = "" ; Declare the variable in which the contents will be stored For $vKey In $aKeys ; Loop... $sContents = $vKey & $esDataSepChar Switch VarGetType($mMap[$vKey]) ; Switch to the Var Type Case "Map" $sContents &= '{Map}' ; Store the contents Case "Array" $sContents &= '{Array}' ; Store the contents Case "Object" $sContents &= '{Object}' ; Store the contents Case "DLLStruct" $sContents &= '{Struct}' ; Store the contents Case "Function" $sContents &= '{Function}' ; Store the contents Case "UserFunction" $sContents &= '{UDF}' ; Store the contents Case Else $sContents &= $mMap[$vKey] ; Store the contents EndSwitch GUICtrlCreateListViewItem($sContents, $idListView) ; Create the ListViewItem in $idListView Next _GUICtrlListView_SetColumnWidth($idListView, 0, $LVSCW_AUTOSIZE) ; Autosize the $idListView to fit the text GUISetState() ; Display the GUI Local $nMsg = 0 While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE GUIDelete($hGUI) ; Delete the GUI Return True ; Return True Case $idExitButton Exit ; Exit Case $idCopyButton $sContents = GUICtrlRead(GUICtrlRead($idListView)) ; Copy the $sContents of the ListViewItem ClipPut($sContents) ; ClipPut them! MsgBox($MB_ICONINFORMATION, $sTitle, "The following has been copied to your clipboard: " & @CRLF & @CRLF & $sContents) ; Display a message EndSwitch WEnd EndFunc ;==>_Map_Display ```

Note that you can right click on the Launch and Show Maps buttons to alter their functionality.

Danp2 commented 1 year ago

Here is the latest revision of code I'm using to test the new bidi commands --

CLICK ME

```autoit ;~ #AutoIt3Wrapper_au3check_parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 ;~ #AutoIt3Wrapper_AutoIt3Dir="C:\AutoitPortable\3.3.16.0" #include #include #include #include #include #include #include #include "wd_core.au3" #include "wd_helper.au3" #include "wd_capabilities.au3" #include "wd_bidi.au3" Global $sSession Global Const $aBrowsers[][2] = _         [ _         ["Firefox", SetupGecko], _         ["Chrome", SetupChrome], _         ["MSEdge", SetupEdge], _         ["Opera", SetupOpera] _         ] Global Const $aCommands[][2] = _         [ _             ["browsingContext.create", '{ "type": "tab" }'], _             ["browsingContext.close", '{"context": ""}'], _             ["browsingContext.getTree", "{}"], _             ["browsingContext.navigate", '{"context": "", "url": "https://google.com"}'], _             ["session.status",  "{}"], _             ["session.new", "{}"], _             ["session.subscribe", '{"events":["log.entryAdded"]}'], _             ["session.unsubscribe", '{"events":["log.entryAdded"]}'] _         ] Opt('TrayIconDebug',1) Main() Func Main()     $_WD_Debug = $_WD_DEBUG_Full     _WD_BidiSetClient('websocat')     _WD_CapabilitiesDefine($_WD_KEYS__STANDARD_PRIMITIVE, 'webSocketUrl')     _WD_CapabilitiesDefine($_WD_KEYS__STANDARD_PRIMITIVE, '"moz:debuggerAddress"')     Local $hGUI = GUICreate("BiDi Tester", 615, 325, -1, -1)     GUICtrlCreateLabel("Command", 15, 15)     Local $idCommands = GUICtrlCreateCombo("", 75, 12, 200, 20, $CBS_DROPDOWNLIST)     Local $sData = _ArrayToString($aCommands, Default, Default, Default, "|", 0, 0)     GUICtrlSetData($idCommands, $sData)     GUICtrlSetData($idCommands, $aCommands[0][0])     Local $iCommand = GUICtrlCreateInput($aCommands[0][0] & "|" & $aCommands[0][1], 24, 40, 409, 21)     Local $iSend = GUICtrlCreateButton("Send", 448, 39, 75, 25)     Local $iAsync = GUICtrlCreateCheckbox("Async?", 530, 40)     Local $iLaunch = GUICtrlCreateButton("Launch", 15, 75, 75, 25)     Local $iMenu = GUICtrlCreateContextMenu($iLaunch)     For $i = 0 To UBound($aBrowsers, 1) - 1         GUICtrlCreateMenuItem($aBrowsers[$i][0], $iMenu, Default, 1)     Next     Local $iShow = GUICtrlCreateButton("Show Maps", 95, 75, 75, 25)     Local $iMenu2 = GUICtrlCreateContextMenu($iShow)     Local $iEvents = GUICtrlCreateMenuItem("Events", $iMenu2, Default, 1)     Local $iResults = GUICtrlCreateMenuItem("Results", $iMenu2, Default, 1)     GUICtrlSetState($iEvents, $GUI_CHECKED)     Local $iGetResult = GUICtrlCreateButton("Get Result", 175, 75, 75, 25)     Local $iEdit = GUICtrlCreateEdit("", 15, 110, 585, 200)     Local $iBrowser = 0, $iStartPopup = $iMenu + 1, $iEndPopup = $iStartPopup + UBound($aBrowsers, 1)     Local $iSelect, $aCmd, $sCmd, $sOpt, $bAsync, $sResult, $mMap, $nMsg, $iLastID = 0, $sAnswer, $aPos     Local $iDiff = 0, $hTimer = TimerInit()     GUICtrlSetState($iStartPopup, $GUI_CHECKED)     GUISetState(@SW_SHOW) #forceref $iResults     While 1         $nMsg = GUIGetMsg()         Switch $nMsg             Case $GUI_EVENT_CLOSE                 ExitLoop             Case $iSend                 If _WD_BidiIsConnected() Then                     $aCmd = StringSplit(GUICtrlRead($iCommand), '|')                     $sCmd = $aCmd[0] ? $aCmd[1] : ""                     $sOpt = ($aCmd[0] = 2) ? Json_Decode($aCmd[2]) : Json_ObjCreate()                     $bAsync = (GUICtrlRead($iAsync) = $GUI_CHECKED)                     $sResult = DoSend($sCmd, $sOpt, $bAsync)                     If $bAsync Then                         $iLastID = Number($sResult)                         $sResult = "Request ID: " & $sResult                     EndIf                 Else                     $sResult = "Not connected!"                 EndIf                 _GUICtrlEdit_AppendText($iEdit, $sResult & @CRLF)             Case $iLaunch                 DoLaunch($iBrowser)             Case $idCommands                 $iSelect = _GUICtrlComboBox_GetCurSel($idCommands)                 GUICtrlSetData($iCommand,  $aCommands[$iSelect][0] & "|" & $aCommands[$iSelect][1])             Case $iShow                 If BitAnd(GUICtrlRead($iEvents), $GUI_CHECKED) Then                     $mMap = __WD_BidiActions('maps', 'event')                     _Map_Display($mMap, 'events')                 Else                     $mMap = __WD_BidiActions('maps', 'result')                     _Map_Display($mMap, 'results')                 EndIf             Case $iStartPopup To $iEndPopup                 $iBrowser = $nMsg - $iStartPopup             Case $iGetResult                 $aPos = WinGetPos($hGUI)                 $sAnswer = InputBox("Result", "Enter the Request ID of the result to retrieve", $iLastID, Default, Default, Default, $aPos[0]+($aPos[2]/3), $aPos[1]+($aPos[3]/3))                 If @error = $_WD_ERROR_Success Then                     $sResult = _WD_BidiGetResult(Number($sAnswer))                     If @error Then _                         $sResult = $aWD_ERROR_DESC[@error] & " [" & @error & "]"                     _GUICtrlEdit_AppendText($iEdit, $sResult & @CRLF)                 EndIf                         EndSwitch         If TimerDiff($hTimer) > $iDiff Then             DoPoll($iEdit)             $iDiff = TimerDiff($hTimer) + 500         EndIf     WEnd     _WD_BidiDisconnect()     GUIDelete($hGUI) EndFunc Func DoLaunch($iBrowser)     Local $bHeadless = False     Local $sURL = 'https://google.com/'     ; Execute browser setup routine for user's browser selection     Local $sCapabilities = Call($aBrowsers[$iBrowser][1], $bHeadless)     _WD_Startup()     $sSession = _WD_CreateSession($sCapabilities)     If @error = $_WD_ERROR_Success Then         _WD_Navigate($sSession, $sURL)         _WD_BidiConnect($sSession)     Endif EndFunc Func DoSend($sCommand, $oParams, $bAsync)     Local $sResult = _WD_BidiExecute($sCommand, $oParams, $bAsync)     Return $sResult EndFunc Func DoPoll($iEdit)     Local $sResult     Local $_WD_DEBUG_Saved = $_WD_DEBUG ; save current DEBUG level     $_WD_DEBUG = $_WD_DEBUG_None     If _WD_BidiIsConnected() Then         $sResult = _WD_BidiGetEvent()         If $sResult Then             _GUICtrlEdit_AppendText($iEdit, $sResult & @CRLF)         EndIf     EndIf     $_WD_DEBUG = $_WD_DEBUG_Saved ; restore DEBUG level EndFunc Func SetupGecko($bHeadless)     _WD_Option('Driver', 'geckodriver.exe')     ;~ _WD_Option('DriverParams', '--log trace --websocket-port=60000 --allow-hosts 127.0.0.1 --allow-origins http://127.0.0.1:60000 http://localhost:60000')     _WD_Option('DriverParams', '--log trace')     _WD_Option('Port', 4444)     _WD_CapabilitiesStartup()     _WD_CapabilitiesAdd('alwaysMatch', 'firefox')     _WD_CapabilitiesAdd('browserName', 'firefox')     _WD_CapabilitiesAdd('acceptInsecureCerts', True)     _WD_CapabilitiesAdd('webSocketUrl', True)     _WD_CapabilitiesAdd('"moz:debuggerAddress"', True)     ; enable experimental BiDi commands     _WD_CapabilitiesAdd('prefs', 'remote.experimental.enabled', true)     ;~ _WD_CapabilitiesAdd('prefs', 'remote.hosts.allowed', "127.0.0.1")     ;~ _WD_CapabilitiesAdd('prefs', 'remote.origins.allowed', "http://127.0.0.1")     If $bHeadless Then _WD_CapabilitiesAdd('args', '--headless')     Local $sCapabilities = _WD_CapabilitiesGet()     Return $sCapabilities EndFunc   ;==>SetupGecko Func SetupChrome($bHeadless)     _WD_Option('Driver', 'chromedriver.exe')     _WD_Option('Port', 9515)     _WD_Option('DriverParams', '--verbose --log-path="' & @ScriptDir & '\chrome.log"')     _WD_CapabilitiesStartup()     _WD_CapabilitiesAdd('alwaysMatch', 'chrome')     _WD_CapabilitiesAdd('w3c', True)     _WD_CapabilitiesAdd('webSocketUrl', True)     _WD_CapabilitiesAdd('excludeSwitches', 'enable-automation')     If $bHeadless Then _WD_CapabilitiesAdd('args', '--headless')     Local $sCapabilities = _WD_CapabilitiesGet()     Return $sCapabilities EndFunc   ;==>SetupChrome Func SetupEdge($bHeadless)     _WD_Option('Driver', 'msedgedriver.exe')     _WD_Option('Port', 9515)     _WD_Option('DriverParams', '--verbose --log-path="' & @ScriptDir & '\msedge.log"')     _WD_CapabilitiesStartup()     _WD_CapabilitiesAdd('alwaysMatch', 'msedge')     _WD_CapabilitiesAdd('webSocketUrl', True)     _WD_CapabilitiesAdd('excludeSwitches', 'enable-automation')     If $bHeadless Then _WD_CapabilitiesAdd('args', '--headless')     Local $sCapabilities = _WD_CapabilitiesGet()     Return $sCapabilities EndFunc   ;==>SetupEdge Func SetupOpera($bHeadless)     _WD_Option('Driver', 'operadriver.exe')     _WD_Option('Port', 9515)     _WD_Option('DriverParams', '--verbose --log-path="' & @ScriptDir & '\opera.log"')     _WD_CapabilitiesStartup()     _WD_CapabilitiesAdd('alwaysMatch', 'opera')     _WD_CapabilitiesAdd('w3c', True)     _WD_CapabilitiesAdd('webSocketUrl', True)     _WD_CapabilitiesAdd('excludeSwitches', 'enable-automation')     ; REMARK     ; using 32bit operadriver.exe requires to set 'binary' capabilities,     ; using 64bit operadriver.exe dosen't require to set this capability, but at the same time setting is not affecting the script     ; So this is good habit to setup for any case.     _WD_CapabilitiesAdd('binary', _WD_GetBrowserPath("opera"))     ConsoleWrite("wd_demo.au3: _WD_GetBrowserPath() > " & _WD_GetBrowserPath("opera") & @CRLF)     If $bHeadless Then _WD_CapabilitiesAdd('args', '--headless')     Local $sCapabilities = _WD_CapabilitiesGet()     Return $sCapabilities EndFunc   ;==>SetupOpera ; #FUNCTION# ==================================================================================================================== ; Name ..........: _Map_Display ; Description ...: Displays the Key & Value pair in a ListView. ; Syntax ........: _Map_Display(Byref $mMap[, $sTitle = "Map Display"]) ; Parameters ....: $mMap                - [in/out] Map to display. ;                  $sTitle              - [optional] Title for the Display window. Default is "Map Display". ; Return values .: Success: True ;                  Failure: False & @error is set to non-zero ; Author ........: Damon Harris (TheDcoder) ; Modified ......: ; Remarks .......: This function is intended to be used for Debugging. Its still in development, so it does not provide flexible ;                  functionality like _ArrayDisplay ; Related .......: _ArrayDisplay ; Link ..........: ; Example .......: Yes ; =============================================================================================================================== Func _Map_Display(ByRef $mMap, $sTitle = "Map Display")     If Not IsMap($mMap) Then         Return SetError(1, 0, False)     EndIf     Local Const $esDataSepChar = Opt("GUIDataSeparatorChar") ; Get the GUIDataSeparatorChar     Local $hGUI = GUICreate($sTitle, 300, 300, -1, -1, BitOR($WS_MINIMIZEBOX, $WS_CAPTION, $WS_POPUP, $WS_SYSMENU, $WS_SIZEBOX, $WS_MAXIMIZEBOX)) ; Create the $hGUI     Local $idListView = GUICtrlCreateListView("Key|Value", 0, 0, 300, 264) ; Create the $idListView     Local $idCopyButton = GUICtrlCreateButton("Copy Text", 3, 268, 146, 30) ; Create the $idCopyButton     GUICtrlSetResizing(-1, $GUI_DOCKAUTO) ; Set Resizing     Local $idExitButton = GUICtrlCreateButton("Exit Script", 149, 268, 148, 30) ; Create the $idExitButton     GUICtrlSetResizing(-1, $GUI_DOCKAUTO) ; Set Resizing     Local $aKeys = MapKeys($mMap) ; Get the $aKeys in the map     ;Local $iKeyCount = UBound($mMap) ; Get the $iKeyCount     Local $sContents = "" ; Declare the variable in which the contents will be stored     For $vKey In $aKeys ; Loop...         $sContents = $vKey & $esDataSepChar         Switch VarGetType($mMap[$vKey]) ; Switch to the Var Type             Case "Map"                 $sContents &= '{Map}' ; Store the contents             Case "Array"                 $sContents &= '{Array}' ; Store the contents             Case "Object"                 $sContents &= '{Object}' ; Store the contents             Case "DLLStruct"                 $sContents &= '{Struct}' ; Store the contents             Case "Function"                 $sContents &= '{Function}' ; Store the contents             Case "UserFunction"                 $sContents &= '{UDF}' ; Store the contents             Case Else                 $sContents &= $mMap[$vKey] ; Store the contents         EndSwitch         GUICtrlCreateListViewItem($sContents, $idListView) ; Create the ListViewItem in $idListView     Next     _GUICtrlListView_SetColumnWidth($idListView, 0, $LVSCW_AUTOSIZE) ; Autosize the $idListView to fit the text     GUISetState() ; Display the GUI     Local $nMsg = 0     While 1         $nMsg = GUIGetMsg()         Switch $nMsg             Case $GUI_EVENT_CLOSE                 GUIDelete($hGUI) ; Delete the GUI                 Return True ; Return True             Case $idExitButton                 Exit ; Exit             Case $idCopyButton                 $sContents = GUICtrlRead(GUICtrlRead($idListView)) ; Copy the $sContents of the ListViewItem                 ClipPut($sContents) ; ClipPut them!                 MsgBox($MB_ICONINFORMATION, $sTitle, "The following has been copied to your clipboard: " & @CRLF & @CRLF & $sContents) ; Display a message         EndSwitch     WEnd EndFunc   ;==>_Map_Display ```

Note that you can right click on the Launch and Show Maps buttons to alter their functionality.

Danp2 commented 1 year ago

WebDriver BiDi for Chromium

mlipok commented 1 year ago

https://developer.chrome.com/articles/webdriver-bidi/

Danp2 commented 1 year ago

I have been successful at creating a BiDi session in Firefox without the need of geckodriver. I don't believe that this feature is currently supported by Chrome or Edge.