-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Webdriver BiDi support #113
Comments
Initial coding can be found here |
This comment was marked as outdated.
This comment was marked as outdated.
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. |
This comment was marked as outdated.
This comment was marked as outdated.
Here is the latest revision of code I'm using to test the new bidi commands -- CLICK ME
;~ #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 <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiComboBoxEx.au3>
#include <GuiListView.au3>
#include <GuiEdit.au3>
#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": "<context id>"}'], _
["browsingContext.getTree", "{}"], _
["browsingContext.navigate", '{"context": "<context id>", "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. |
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. |
https://github.com/w3c/webdriver-bidi
https://developer.chrome.com/blog/webdriver-bidi/
https://wiki.mozilla.org/WebDriver/RemoteProtocol/WebDriver_BiDi
The text was updated successfully, but these errors were encountered: