Jump to content

Webdriver, Websockets, and Chrome DevTools Protocol ... Oh my! β€‹πŸ˜œ


Recommended Posts

Hi All,

I have been working on an enhancement to the WebDriver UDF that will make _WD_ExecuteCDPCommand compatible with all major browsers instead of Chrome only. This involves using WebSockets to pass commands back and forth to the browser.

Attached to this post are two files --

  • winhttp_websocket.au3 -- This is a modified version of code originally posted to the forum by @FireFox.
  • genericcdp.au3 -- This contains the enhanced version of _WD_ExecuteCDPCommand (original version by @TheDcoder) and a new function named _WD_GetCDPSettings

You can run genericcdp.au3 for a brief example of how the new functionality works. Comment / uncomment the appropriate lines near the beginning to control while browser gets tested.

Prerequisites

  • You'll obviously need the WebDriver UDF installed and working for this code to have a chance of working correct. πŸ™„
  • You need to be running an OS that supports WebSockets natively (ie: Windows 8 / Windows Server 2012 or newer)

Caveats
Chromium-based browsers return some unexpected status codes in response to _WinHttpWebSocketClose and _WinHttpWebSocketQueryCloseStatus, so I've included checks to ignore these.

Needs
I would appreciate it if I could get some feedback / suggestions for improvement on these proposed changes.

FWIW, I have only performed these basic CDP commands. Feel free to experiment with other CDP commands and report back on your successes / failures.

Thanks,

Dan

genericcdp.au3 winhttp_websocket.au3

Edited by Danp2
Added OS restrictions
Link to comment
Share on other sites

You are using websocket APIs that state that they require a minimum client of Windows 8 or a minimum server of Windows 2012.Β  Shouldn't that be listed as a prerequisite?Β  :)

I just ran the genericCDP script using the latest 64-bit Firefox on Windows 7 and I got an @error = 2 from the _WD_ExecuteCDPCommand() function.Β  I ran the same test on a Windows 10 client and it worked as expected.

The log from Windows 7 PC is below:

_WD_Startup: OS:    WIN_7 WIN32_NT 7601 Service Pack 1
_WD_Startup: AutoIt:    3.3.14.5
_WD_Startup: WD.au3:    0.4.0.5
_WD_Startup: WinHTTP:   1.6.4.2
_WD_Startup: Driver:    C:\Portable Apps\AutoIt3\Include\MyIncludes\WebDriver\Drivers\geckodriver_x64.exe
_WD_Startup: Params:    --log trace
_WD_Startup: Port:  4444
__WD_Post: URL=HTTP://127.0.0.1:4444/session; $sData={"capabilities":{"alwaysMatch": {"moz:debuggerAddress": true, "moz:firefoxOptions": {"log": {"level": "trace"}}}}}
__WD_Post: StatusCode=200; ResponseText={"value":{"sessionId":"38491b67-3b02-4638-a7fd-077cf118e04f","capabilities":{"acceptInsecureCerts":f...
_WD_CreateSession: {"value":{"sessionId":"38491b67-3b02-4638-a7fd-077cf118e04f","capabilities":{"acceptInsecureCerts":false,"browserName":"firefox","browserVersion":"90.0","moz:accessibilityChecks":false,"moz:buildID":"20210705185941","moz:debuggerAddress":"localhost:60972","moz:geckodriverVersion":"0.29.1","moz:headless":false,"moz:processID":6528,"moz:profile":"C:\\Temp\\rust_mozprofile0i0kl3","moz:shutdownTimeout":60000,"moz:useNonSpecCompliantPointerOrigin":false,"moz:webdriverClick":true,"pageLoadStrategy":"normal","platformName":"windows","platformVersion":"6.1","proxy":{},"setWindowRect":true,"strictFileInteractability":false,"timeouts":{"implicit":0,"pageLoad":300000,"script":30000},"unhandledPromptBehavior":"dismiss and notify"}}}
__WD_Post: URL=HTTP://127.0.0.1:4444/session/38491b67-3b02-4638-a7fd-077cf118e04f/url; $sData={"url":"http://google.com"}
__WD_Post: StatusCode=200; ResponseText={"value":null}...
_WD_Navigate: {"value":null}
__WD_Post: URL=HTTP://127.0.0.1:4444/session/38491b67-3b02-4638-a7fd-077cf118e04f/window/new; $sData={"type":"tab"}
__WD_Post: StatusCode=200; ResponseText={"value":{"handle":"64c6d394-1b1b-46d6-bb8f-d1599fbfe0f2","type":"tab"}}...
_WD_Window: {"value":{"handle":"64c6d394-1b1b-46d6-bb8f-d1599fbfe0f2","type":"tab"}}...
__WD_Post: URL=HTTP://127.0.0.1:4444/session/38491b67-3b02-4638-a7fd-077cf118e04f/window; $sData={"handle":"64c6d394-1b1b-46d6-bb8f-d1599fbfe0f2"}
__WD_Post: StatusCode=200; ResponseText={"value":null}...
_WD_Window: {"value":null}...
__WD_Post: URL=HTTP://127.0.0.1:4444/session/38491b67-3b02-4638-a7fd-077cf118e04f/url; $sData={"url":"http://yahoo.com"}
__WD_Post: StatusCode=200; ResponseText={"value":null}...
_WD_Navigate: {"value":null}
__WD_Get: URL=http://localhost:60972/json/list
__WD_Get: StatusCode=200; $iResult = 0; $sResponseText=[
    {
        "description": "",
        "devtoolsFrontendUrl": null,
        "faviconUrl": "",
        "id": "a881de60-63d7-...
_WD_ExecuteCDPCommand: ...
_WD_ExecuteCDPCommand ==> Socket Error: SetOption error

Β 

Edited by TheXman
Link to comment
Share on other sites

55 minutes ago, TheXman said:

You are using websocket APIs that state that they require a minimum client of Windows 8 or a minimum server of Windows 2012.Β  Shouldn't that be listed as a prerequisite?Β 

Very true. I will update the OP.

55 minutes ago, TheXman said:

I just ran the genericCDP script using the latest 64-bit Firefox on Windows 7 and I got an @error = 2

That makes sense given the above prerequisite.

P.S. Thanks for testing!

Edited by Danp2
Link to comment
Share on other sites

I only use Firefox and my primary PCs are Windows 7.Β  However, I do have a Windows 10 PC with MS Edge that I can run tests on.Β  I'll take a look at the error when you're closing a websocket, on MS Edge, and see if I can find the root cause.Β  Can you explain the issue that you are seeing so I know that I'm chasing the right problem? If you have implemented any workarounds that may be masking the issue, can you provide either a script that reproduces the issue or tell me what steps I need to take to reproduce it?

Edited by TheXman
Link to comment
Share on other sites

Vacation Mode.

SorryΒ 

;)

Β 

Signature beginning:
*Β Please remember: "AutoIt".....Β *Β Β Wondering who uses AutoIt and what it can be used for ?Β *Β Forum RulesΒ *
*Β ADO.au3 UDFΒ *Β POP3.au3 UDFΒ *Β XML.au3 UDFΒ *Β IE on Windows 11 * How to ask ChatGPT for AutoIt Code *Β for other useful stuffΒ click the following button:

Spoiler

AnyΒ of myΒ own codeΒ posted anywhere on the forumΒ isΒ available for use by others without any restrictionΒ of any kind.Β 

My contribution (my own projects):Β *Β Debenu Quick PDF Library - UDFΒ *Β Debenu PDF Viewer SDK - UDFΒ *Β Acrobat Reader - ActiveX ViewerΒ * UDF for PDFCreator v1.x.xΒ *Β XZip - UDFΒ *Β AppCompatFlagsΒ UDFΒ *Β CrowdinAPIΒ UDFΒ *Β _WinMergeCompare2Files()Β *Β _JavaExceptionAdd()Β *Β _IsBeta()Β *Β Writing DPI Awareness App - workaroundΒ *Β _AutoIt_RequiredVersion()Β * Chilkatsoft.au3 UDFΒ *Β TeamViewer.au3 UDFΒ *Β JavaManagement UDFΒ *Β VIES over SOAPΒ * WinSCP UDFΒ * GHAPI UDF - modest begining - comunication with GitHub REST API *Β ErrorLog.au3 UDF - A logging LibraryΒ *Β Include Dependency Tree (Tool for analyzing script relations)Β *Β Show_Macro_Values.au3 *

Β 

My contribution to others projects or UDF based on Β others projects:Β *Β _sql.au3 UDFΒ Β * POP3.au3 UDFΒ * Β RTF Printer - UDFΒ * XML.au3 UDFΒ * ADO.au3 UDF *Β SMTP Mailer UDFΒ *Β Dual Monitor resolution detection * *Β 2GUI on Dual Monitor System * _SciLexer.au3 UDFΒ *Β SciTE - Lexer for console pane *Β 

Useful links:Β * Forum RulesΒ *Β Forum etiquetteΒ *Β  Forum Information and FAQsΒ *Β How to post code on the forumΒ *Β AutoIt Online DocumentationΒ *Β AutoIt Online Beta DocumentationΒ *Β SciTE4AutoIt3 getting startedΒ *Β Convert text blocks to AutoIt codeΒ *Β Games made in AutoitΒ *Β Programming related sitesΒ *Β Polish AutoIt TutorialΒ *Β DllCall Code GeneratorΒ *Β 

Wiki:Β *Β Expand your knowledge - AutoIt WikiΒ *Β Collection of User Defined FunctionsΒ *Β How to use HelpFileΒ *Β Good coding practices in AutoItΒ *Β 

OpenOffice/LibreOffice/XLS Related:Β WriterDemo.au3Β *Β XLS/MDB from scratch with ADOX

IE Related:Β Β *Β How to use IE.au3 Β UDF with Β AutoIt v3.3.14.xΒ *Β Why isn't Autoit able to click a Javascript Dialog?Β *Β Clicking javascript button with no IDΒ *Β IE document >> save as MHT fileΒ * IETab Switcher (by LarsJ )Β *Β HTML Entities * _IEquerySelectorAll() (by uncommon)Β *Β IE in TaskScheduler *Β IE Embedded Control Versioning (use IE9+ and HTML5 in a GUI)Β *Β PDFΒ Related: *Β How to get reference to PDF object embeded in IE * IE on Windows 11 *Β 

I encourage you to read:Β * Global VarsΒ * Best Coding PracticesΒ *Β Please explain code used in Help file for several File functionsΒ *Β OOP-like approach in AutoItΒ * UDF-Spec QuestionsΒ *Β  EXAMPLE: How To Catch ConsoleWrite() output to a file or to CMDΒ *

I also encourage you to check awesome @trancexxΒ code:Β  *Β Create COM objects from modules without any demand on user to register anything. * Another COM object registering stuff *Β OnHungApp handler *Β Avoid "AutoIt Error" message box in unknown errorsΒ Β *Β HTML editor *Β 

winhttp.au3 related :Β *Β https://www.autoitscript.com/forum/topic/206771-winhttpau3-download-problem-youre-speaking-plain-http-to-an-ssl-enabled-server-port/

"Homo sum; humani nil a me alienum puto" - Publius Terentius Afer
"Program are meant to be read by humans and only incidentally for computers and execute" - Donald Knuth, "The Art of Computer Programming"
:naughty:Β Β :ranting:, beΒ Β :)Β and Β  Β  Β  \\//_.

Anticipating ErrorsΒ :Β Β "Any program that accepts data from a user must include code to validate that data before sending it to the data store. You cannot rely on the data store, ...., or even your programming language to notify you of problems. You must check every byte entered by your users, making sure that data is the correct type for its field and that required fields are not empty."

Signature last update: 2023-04-24

Link to comment
Share on other sites

@TheXmanThat's for the offer. Look at the error checking in _WD_ExecuteCDPCommand following the calls toΒ _WinHttpWebSocketClose and _WinHttpWebSocketQueryCloseStatus. I don't encounter these error codes (ERROR_WINHTTP_CONNECTION_ERROR and ERROR_INVALID_OPERATION) with Firefox, but I do consistently with Chrome and Edge.

@mLipokI knew it. Otherwise, you would have already torn it apart and complete rewritten it. 😜

Link to comment
Share on other sites

I just starting taking a look.Β  Before getting too deep, I noticed something that I couldn't figure out.

Β 

Microsoft defines the _WINHTTP_WEB_SOCKET_CLOSE_STATUS enumerators as: (starting at 0)

typedef enum _WINHTTP_WEB_SOCKET_CLOSE_STATUS {
  WINHTTP_WEB_SOCKET_SUCCESS_CLOSE_STATUS,
  WINHTTP_WEB_SOCKET_ENDPOINT_TERMINATED_CLOSE_STATUS,
  WINHTTP_WEB_SOCKET_PROTOCOL_ERROR_CLOSE_STATUS,
  WINHTTP_WEB_SOCKET_INVALID_DATA_TYPE_CLOSE_STATUS,
  WINHTTP_WEB_SOCKET_EMPTY_CLOSE_STATUS,
  WINHTTP_WEB_SOCKET_ABORTED_CLOSE_STATUS,
  WINHTTP_WEB_SOCKET_INVALID_PAYLOAD_CLOSE_STATUS,
  WINHTTP_WEB_SOCKET_POLICY_VIOLATION_CLOSE_STATUS,
  WINHTTP_WEB_SOCKET_MESSAGE_TOO_BIG_CLOSE_STATUS,
  WINHTTP_WEB_SOCKET_UNSUPPORTED_EXTENSIONS_CLOSE_STATUS,
  WINHTTP_WEB_SOCKET_SERVER_ERROR_CLOSE_STATUS,
  WINHTTP_WEB_SOCKET_SECURE_HANDSHAKE_ERROR_CLOSE_STATUS
} WINHTTP_WEB_SOCKET_CLOSE_STATUS;

However, in the winhttp_websocket.au3 UDF lib, the enum is defined as: (starting at 1000)

Global Enum _
        $WINHTTP_WEB_SOCKET_SUCCESS_CLOSE_STATUS = 1000, _
        $WINHTTP_WEB_SOCKET_ENDPOINT_TERMINATED_CLOSE_STATUS, _
        $WINHTTP_WEB_SOCKET_PROTOCOL_ERROR_CLOSE_STATUS, _
        $WINHTTP_WEB_SOCKET_INVALID_DATA_TYPE_CLOSE_STATUS, _
        $WINHTTP_WEB_SOCKET_EMPTY_CLOSE_STATUS, _
        $WINHTTP_WEB_SOCKET_ABORTED_CLOSE_STATUS, _
        $WINHTTP_WEB_SOCKET_INVALID_PAYLOAD_CLOSE_STATUS, _
        $WINHTTP_WEB_SOCKET_POLICY_VIOLATION_CLOSE_STATUS, _
        $WINHTTP_WEB_SOCKET_MESSAGE_TOO_BIG_CLOSE_STATUS, _
        $WINHTTP_WEB_SOCKET_UNSUPPORTED_EXTENSIONS_CLOSE_STATUS, _
        $WINHTTP_WEB_SOCKET_SERVER_ERROR_CLOSE_STATUS, _
        $WINHTTP_WEB_SOCKET_SECURE_HANDSHAKE_ERROR_CLOSE_STATUS

I haven't been able to figure out why you start your enumerators at 1000?Β  That would throw off all of the statuses by 1000, including a successful status.Β  :think:

Edited by TheXman
Added link to MS enum definition
Link to comment
Share on other sites

That is very odd.Β  Looking at sources other than Microsoft, I do see references to the enumerator starting at 1000.

I added a link, in my previous post, to the definition on Microsoft's site.Β  I'll keep digging to see if I can find more information as to why there's a discrepancy.

Link to comment
Share on other sites

After reading thru the WebSocket RFC as it relates to closing a WebSocket connection, in this specific use case where you are just communicating with the browser (CDP), there's really no need for the client to close the WebSocket, it'll be closed when the underlying TCP connection is closed.Β  I guess if you wanted to do some tidying up, you could close the WebSocket's handle before exiting the script.Β  ;)Β  I commented out all of the relevant "close" logic (WebSocketShutdown, WebSocketClose, & WebSocketQueryCloseStatus) and saw no ill effects or remnants left behind.

There's definitely something different between the way Firefox handles the CDP commands and the way MS Edge handles them.Β  I noticed when running the script in MS Edge, the script switches from the Yahoo page to the Google page and then back to the Yahoo page before exiting.Β  When running the script against Firefox, it doesn't do the last switch from Google back to Yahoo before exiting, it exits while on the Google page.

Edited by TheXman
Link to comment
Share on other sites

Pretty sure what you are encountering is a different in the order that items appear in output from /json/list. You would experience the opposite if you change the line

For $x = UBound($aList, $UBOUND_COLUMNS) - 1 to 1 Step -1

to

For $x = 1 to UBound($aList, $UBOUND_COLUMNS) - 1

It was just a Q&D example, so feel free to suggest improvements. :thumbsup:

Appreciate the feedback on the WebSocket handling. I think that I'll leave the coding as-is for now.

Link to comment
Share on other sites

  • Danp2 changed the title to Webdriver, Websockets, and Chrome DevTools Protocol ... Oh my! β€‹πŸ˜œ

Does this mean I might be able to manipulate discarded tabs now? Time to dive in!

All my code provided is Public Domain...Β but it may not work.Β ;)Β Use it, change it, break it, whatever you want.

Spoiler

My Humble Contributions:
Personal Function DocumentationΒ - A personal HelpFile for your functions
Acro.au3 UDFΒ - Automating Acrobat Pro
ToDo FinderΒ - Find #ToDo: lines in your scripts
UI-SimpleWrappers UDFΒ - Use UI Automation more Simply-er
KeePass UDFΒ - Automate KeePass, a password manager
InputBoxes - Simple Input boxes for various variable types

Link to comment
Share on other sites

@Danp2Β I'm not sure how to use this UDF yet :)

I was hoping to find something to help keep tabs from being discarded (same thing as here). I've still been poking around the issue, but for now I keep the browser visible on my 3rd screen.

All my code provided is Public Domain...Β but it may not work.Β ;)Β Use it, change it, break it, whatever you want.

Spoiler

My Humble Contributions:
Personal Function DocumentationΒ - A personal HelpFile for your functions
Acro.au3 UDFΒ - Automating Acrobat Pro
ToDo FinderΒ - Find #ToDo: lines in your scripts
UI-SimpleWrappers UDFΒ - Use UI Automation more Simply-er
KeePass UDFΒ - Automate KeePass, a password manager
InputBoxes - Simple Input boxes for various variable types

Link to comment
Share on other sites

  • 7 months later...

I found another topic on this CDP protocol using pipesΒ Automate Chrome / Edge using VBA - CodeProject
Β 

Quote

The low-level access to the CDP protocol is avaible by two means: Either Edge starts a small Webserver on a specific port or via pipes. The Webserver lacks any security features. Any user on the computer has access to the webserver. This may pose no risks on single user computers or dedicated virtual containers. But if the process is run on a terminal server with more than one user, this is not acceptable. That's why the code uses pipes to communicate with Edge.

Β 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...