Ich mach's kurz: Nachdem ich mir drei Tage lang durch eine abartige Chrome-API-Dokumentation gewühlt habe , habe ich eine, zumindest bruchstrückhafte, Steuerung von Chrome hingeklatscht . Ist nicht schön, längst nicht vollständig, aber wer den Code liest versteht, wie man es richtig machen muss. Hab nix anderes sonst wo gefunden, (auch nicht außerhab der größten Comunity ever #PbFTW. Optimierungen und Weiterentwicklung erwünscht. Werde hier auch immer mal wieder reinschauen.
los gehts:
Chrome braucht Websockets, also geben wir ihm Websockets: [speichern als Websocket_Client.pb]
Code: Alles auswählen
; Websocketclient by Netzvamp
; Version: 2016/01/08
;[Von mir überarbeitet]
DeclareModule WebsocketClient
Declare OpenWebsocketConnection(URL.s)
Declare SendTextFrame(connection, message.s)
Declare ReceiveFrame(connection, *MsgBuffer)
Declare SetSSLProxy(ProxyServer.s = "", ProxyPort.l = 8182)
Enumeration 1000
#frame_text
#frame_binary
#frame_closing
#frame_ping
#frame_unknown
EndEnumeration
EndDeclareModule
Module WebsocketClient
;TODO: Add function to send binary frame
;TODO: We don't support fragmetation right now
;TODO: We should send an closing frame, but server will also just close
;TODO: Support to send receive bigger frames
debugmode = 0
Structure WebSocket
Frametyp.i
FrameMemory.i
EndStructure
Declare Handshake(Connection, Servername.s, Path.s)
Declare ApplyMasking(Array Mask.a(1), *Buffer)
Global Proxy_Server.s, Proxy_Port.l
Macro dbg(txt)
If Debugmode = 1
Debug "WebsocketClient: " + FormatDate("%yyyy-%mm-%dd %hh:%ii:%ss",Date()) + " > " + txt
EndIf
EndMacro
Procedure SetSSLProxy(ProxyServer.s = "", ProxyPort.l = 8182)
Proxy_Server.s = ProxyServer.s
Proxy_Port.l = ProxyPort.l
EndProcedure
Procedure OpenWebsocketConnection(URL.s)
Protokol.s = GetURLPart(URL.s, #PB_URL_Protocol)
Servername.s = GetURLPart(URL.s, #PB_URL_Site)
Port.l = Val(GetURLPart(URL.s, #PB_URL_Port))
If Port.l = 0 : Port.l = 80 : EndIf
Path.s = GetURLPart(URL.s, #PB_URL_Path)
If Path.s = "" : Path.s = "/" : EndIf
;InitNetwork()
If Protokol.s = "wss" ; If we connect with encryption (https)
If Proxy_Port
Connection = OpenNetworkConnection(Proxy_Server.s, Proxy_Port.l, #PB_Network_TCP, 1000)
Else
dbg("We need an SSL-Proxy like stunnel for encryption. Configure the proxy with SetSSLProxy().")
EndIf
ElseIf Protokol.s = "ws"
Connection = OpenNetworkConnection(Servername.s, Port.l, #PB_Network_TCP, 1000)
EndIf
If Connection
If Handshake(Connection, Servername.s, Path.s)
dbg("Connection and Handshake ok")
ProcedureReturn Connection
Else
dbg("Handshake-Error")
ProcedureReturn #False
EndIf
Else
dbg("Couldn't connect")
ProcedureReturn #False
EndIf
EndProcedure
Procedure Handshake(Connection, Servername.s, Path.s)
Request.s = "GET /" + Path.s + " HTTP/1.1"+ #CRLF$ +
"Host: " + Servername.s + #CRLF$ +
"Upgrade: websocket" + #CRLF$ +
"CONNECTION: UPGRADE" + #CRLF$ +
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" + #CRLF$ +
"Sec-WebSocket-Version: 13" + #CRLF$ +
"User-Agent: CustomWebsocketClient"+ #CRLF$ + #CRLF$
SendNetworkString(Connection, Request.s, #PB_UTF8)
*Buffer = AllocateMemory(65536)
; We wait for answer
Repeat
Size = ReceiveNetworkData(connection, *Buffer, 65536)
Answer.s = Answer.s + PeekS(*Buffer, Size, #PB_UTF8)
If FindString(Answer, #CRLF$ + #CRLF$)
Break
EndIf
Until Size <> 65536
Answer.s = UCase(Answer.s)
; Check answer
If FindString(Answer.s, "HTTP/1.1 101") And FindString(Answer.s, "CONNECTION: UPGRADE") And FindString(Answer.s, "UPGRADE: WEBSOCKET")
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndProcedure
Procedure ApplyMasking(Array Mask.a(1), *Buffer)
For i = 0 To MemorySize(*Buffer) - 1
PokeA(*Buffer + i, PeekA(*Buffer + i) ! Mask(i % 4))
Next
EndProcedure
Procedure SendTextFrame(connection, message.s)
; Put String in Buffer
MsgLength.l = StringByteLength(message.s, #PB_UTF8)
*MsgBuffer = AllocateMemory(MsgLength)
PokeS(*MsgBuffer, message.s, MsgLength, #PB_UTF8|#PB_String_NoZero)
dbg("Messagelength to send: " + Str(MsgLength))
; The Framebuffer, we fill with senddata
If MsgLength <= 125
Fieldlength = 6
ElseIf MsgLength >= 126 And MsgLength <= 65535
Fieldlength = 8
Else
Fieldlength = 14
EndIf
dbg("Fieldlength to send: " + Str(Fieldlength))
*FrameBuffer = AllocateMemory(Fieldlength + MsgLength)
; We generate 4 random masking bytes
Dim Mask.a(3)
Mask(0) = Random(255,0)
Mask(1) = Random(255,0)
Mask(2) = Random(255,0)
Mask(3) = Random(255,0)
pos = 0 ; The byteposotion in the framebuffer
; First Byte: FIN(1=finished with this Frame),RSV(0),RSV(0),RSV(0),OPCODE(4 byte)=0001(text)
PokeB(*FrameBuffer, %10000001) : pos + 1 ; = 129
; Second Byte: Masking(1),length(to 125bytes, else we have to extend)
If MsgLength <= 125 ; Length fits in first byte
PokeA(*Framebuffer + pos, MsgLength + 128) : pos + 1 ; + 128 for Masking
ElseIf MsgLength >= 126 And MsgLength <= 65535 ; We have to extend length to third byte
PokeA(*Framebuffer + pos, 126 + 128) : pos + 1 ; 126 for 2 extra length bytes and + 128 for Masking
PokeA(*FrameBuffer + pos, (MsgLength >> 8)) : pos + 1 ; First Byte
PokeA(*FrameBuffer + pos, MsgLength) : pos + 1 ; Second Byte
Else ; It's bigger than 65535, we also use 8 extra bytes
PokeA(*Framebuffer + pos, 127 + 128) : pos + 1 ; 127 for 8 extra length bytes and + 128 for Masking
PokeA(*Framebuffer + pos, 0) : pos + 1 ; 8 Bytes for payload lenght. We don't support giant packages for now, so first bytes are zero :P
PokeA(*Framebuffer + pos, 0) : pos + 1
PokeA(*Framebuffer + pos, 0) : pos + 1
PokeA(*Framebuffer + pos, 0) : pos + 1
PokeA(*Framebuffer + pos, MsgLength >> 24) : pos + 1
PokeA(*Framebuffer + pos, MsgLength >> 16) : pos + 1
PokeA(*Framebuffer + pos, MsgLength >> 8) : pos + 1
PokeA(*Framebuffer + pos, MsgLength) : pos + 1 ; = 10 Byte
EndIf
; Write Masking Bytes
PokeA(*FrameBuffer + pos, Mask(0)) : pos + 1
PokeA(*FrameBuffer + pos, Mask(1)) : pos + 1
PokeA(*FrameBuffer + pos, Mask(2)) : pos + 1
PokeA(*FrameBuffer + pos, Mask(3)) : pos + 1
ApplyMasking(Mask(), *MsgBuffer)
CopyMemory(*MsgBuffer, *FrameBuffer + pos, MsgLength)
;For x = 0 To 100 Step 5
;Debug Str(PeekA(*FrameBuffer + x)) + " | " + Str(PeekA(*FrameBuffer + x + 1)) + " | " + Str(PeekA(*FrameBuffer + x + 2)) + " | " + Str(PeekA(*FrameBuffer + x + 3)) + " | " + Str(PeekA(*FrameBuffer + x + 4))
;Next
If SendNetworkData(connection, *FrameBuffer, Fieldlength + MsgLength) = Fieldlength + MsgLength
dbg("Textframe send, Bytes: " + Str(Fieldlength + MsgLength))
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndProcedure
Procedure ReceiveFrame(connection, *Frametyp.WebSocket)
*FrameBuffer = AllocateMemory(65536)
Repeat
*FrameBuffer = ReAllocateMemory(*FrameBuffer, 65536)
Size = ReceiveNetworkData(connection, *FrameBuffer, 65536)
;Answer.s = Answer.s + PeekS(*FrameBuffer, Size, #PB_UTF8)
Until Size <> 65536
dbg("Received Frame, Bytes: " + Str(Size))
*FrameBuffer = ReAllocateMemory(*FrameBuffer, Size)
; ; debug: output any single byte
; If #PB_Compiler_Debugger
; For x = 0 To Size - 1 Step 1
; dbg_bytes.s + Str(PeekA(*FrameBuffer + x)) + " | "
; Next
; dbg(dbg_bytes)
; EndIf
; Getting informations about package
If PeekA(*FrameBuffer) & %10000000 > #False
;dbg("Frame not fragmented")
fragmentation.b = #False
Else
dbg("Frame fragmented! This not supported for now!")
fragmentation.b = #True
EndIf
; Check for Opcodes
If PeekA(*FrameBuffer) = %10000001 ; Textframe
dbg("Text frame")
frame_typ.w = #frame_text
ElseIf PeekA(*FrameBuffer) = %10000010 ; Binary Frame
dbg("Binary frame")
frame_typ.w = #frame_binary
ElseIf PeekA(*FrameBuffer) = %10001000 ; Closing Frame
dbg("Closing frame")
frame_typ.w = #frame_closing
ElseIf PeekA(*FrameBuffer) = %10001001 ; Ping
; We just answer pings
*pongbuffer = AllocateMemory(2)
PokeA(*pongbuffer, 138)
PokeA(*pongbuffer+1, 0)
SendNetworkData(connection, *pongbuffer, 2)
dbg("Received Ping, answered with Pong")
frame_typ.w = #frame_ping
FreeMemory(*pongbuffer)
FreeMemory (*FrameBuffer)
ProcedureReturn
Else
dbg("Opcode unknown")
frame_typ.w = #frame_unknown
FreeMemory(*FrameBuffer)
ProcedureReturn #False
EndIf
; Check masking
If PeekA(*FrameBuffer + 1) & %10000000 = 128 : masking.b = #True : Else : masking.b = #False : EndIf
dbg("Masking: " + Str(masking))
pos.l = 1
; check size
If PeekA(*FrameBuffer + 1) & %01111111 <= 125 ; size is in this byte
frame_size.l = PeekA(*FrameBuffer + pos) & %01111111 : pos + 1
ElseIf PeekA(*FrameBuffer + 1) & %01111111 >= 126 ; Size is in 2 extra bytes
frame_size.l = PeekA(*FrameBuffer + 2) << 8 + PeekA(*FrameBuffer + 3) : pos + 2
EndIf
dbg("FrameSize: " + Str(frame_size.l))
If masking = #True
Dim Mask.a(3)
Mask(0) = PeekA(*FrameBuffer + pos) : pos + 1
Mask(1) = PeekA(*FrameBuffer + pos) : pos + 1
Mask(2) = PeekA(*FrameBuffer + pos) : pos + 1
Mask(3) = PeekA(*FrameBuffer + pos) : pos + 1
*Frametyp\FrameMemory = ReAllocateMemory(*Frametyp\FrameMemory ,frame_size)
CopyMemory(*FrameBuffer + pos, *Frametyp\FrameMemory, frame_size)
ApplyMasking(Mask(), *Frametyp\FrameMemory)
FreeArray(Mask())
Else
*Frametyp\FrameMemory = ReAllocateMemory(*Frametyp\FrameMemory,frame_size+1)
CopyMemory(*FrameBuffer + pos, *Frametyp\FrameMemory, frame_size)
EndIf
FreeMemory(*FrameBuffer)
ProcedureReturn frame_typ
EndProcedure
EndModule
CompilerIf #PB_Compiler_IsMainFile
Structure WebSocket
Frametyp.i
FrameMemory.i
EndStructure
; Minimal example to send and receive textmessages
; The preconfigured testserver "echo.websocket.org" will just echo back everything you've send.
XIncludeFile "module_websocketclient_gui.pbf"
Global connection
Procedure gui_button_connect(EventType)
If EventType = #PB_EventType_LeftClick
Debug "Connect clicked"
;connection = WebsocketClient::OpenWebsocketConnection(GetGadgetText(#String_url))
connection = WebsocketClient::OpenWebsocketConnection(GetGadgetText(#String_url))
AddGadgetItem(#ListView_Output, -1, "# Connected to " + GetGadgetText(#String_url))
EndIf
EndProcedure
Procedure gui_button_send(EventType)
Debug "Send clicked"
If WebsocketClient::SendTextFrame(connection, GetGadgetText(#String_send)) = #False
Debug "Couldn't send. Are we disconnected?"
Else
AddGadgetItem(#ListView_Output, -1, "> " + GetGadgetText(#String_send))
EndIf
EndProcedure
OpenWindow_Websocketclient()
; Proxy Setting:
; If you need an encyrpted connection (https/wss), you currently have to use an
; proxy software like stunnel (https://www.stunnel.org) to redirect unencrypted data into an encrypted connection
; Example stunnel.conf section:
; [websocket]
; client = yes
; accept = 127.0.0.1:8182
; connect = echo.websocket.org:443
WebsocketClient::SetSSLProxy("127.0.0.1",8182)
Repeat
If Window_Websocketclient_Events( WaitWindowEvent(1) ) = #False : End : EndIf
If connection
NetworkEvent = NetworkClientEvent(connection)
Select NetworkEvent
Case #PB_NetworkEvent_Data
Debug "data coming"
Frametyp.Websocket\FrameMemory = AllocateMemory(1)
Frametyp\Frametyp = WebsocketClient::ReceiveFrame(connection,@Frametyp)
If Frametyp\Frametyp = WebsocketClient::#frame_text
Debug MemorySize(Frametyp\FrameMemory)
Packet$ = PeekS(Frametyp\FrameMemory,MemoryStringLength(Frametyp\FrameMemory,#PB_UTF8)-1,#PB_UTF8)
Debug Packet$
ElseIf Frametyp\Frametyp = WebsocketClient::#frame_binary
Debug "Received Binaryframe"
EndIf
FreeMemory(Frametyp\FrameMemory)
Case #PB_NetworkEvent_Disconnect
If disconnected = #False
Debug "Disconnected"
EndIf
disconnected = #True
NetworkEvent = #PB_NetworkEvent_None
Case #PB_NetworkEvent_None
Debug "idle"
EndSelect
EndIf
ForEver
CompilerEndIf
Code: Alles auswählen
InitNetwork()
#SystemProcessInformation = $0005
IncludeFile "Websocket_Client.pb"
Structure WebSocket
Frametyp.i
FrameMemory.i
EndStructure
Structure _UNICODE_STRING Align #PB_Structure_AlignC
usLength.w
usMaximumLength.w
usBuffer.i
EndStructure
Structure _SYSTEM_PROCESS_INFO Align #PB_Structure_AlignC
NextEntryOffset.l
NumberOfThreads.l
Reserved.q[3]
CreateTime.q
UserTime.q
KernelTime.q
ImageName._UNICODE_STRING
BasePriority.l
ProcessId.i
InheritedFromProcessId.i
EndStructure
Structure co
description.s
devtoolsFrontendUrl.s
title.s
type.s
url.s
webSocketDebuggerUrl.s
WsConnection.i
EndStructure
Structure vs
Browser.s
ProtocolVersion.s
UserAgent.s
V8Version.s
WebKitVersion.s
webSocketDebuggerUrl.s
EndStructure
Structure All
Map Objects.co()
Version.vs
RequestId.i
EndStructure
Global DebugPort = 9222
Global Chrome.All
Procedure KillProcess (pid)
phandle = OpenProcess_ (#PROCESS_TERMINATE, #False, pid)
If phandle <> #Null
If TerminateProcess_ (phandle, 1)
result = #True
EndIf
CloseHandle_ (phandle)
EndIf
ProcedureReturn result
EndProcedure
Procedure CloseAllProcess(name.s)
Define dwlen, *Buffer, *SPI._SYSTEM_PROCESS_INFO
NtQuerySystemInformation_(#SystemProcessInformation, 0, 0, @dwlen)
If dwlen
dwlen * 2
*Buffer = AllocateMemory(dwlen)
If *Buffer
If NtQuerySystemInformation_(#SystemProcessInformation, *Buffer, dwlen, @dwlen) = #ERROR_SUCCESS
*SPI = *Buffer
While *SPI\NextEntryOffset
If *SPI\ImageName\usBuffer
If PeekS(*SPI\ImageName\usBuffer, -1, #PB_Unicode) = name
KillProcess(*SPI\ProcessId)
EndIf
EndIf
*SPI + *SPI\NextEntryOffset
Wend
EndIf
FreeMemory(*Buffer)
EndIf
EndIf
EndProcedure
;Internal Functions
Procedure ChromeDefaultObjectAdd(JsonObject)
If JSONType(JsonObject) = #PB_JSON_Object
id.s = GetJSONString(GetJSONMember(JsonObject,"id"))
Chrome\Objects(id)\description = GetJSONString(GetJSONMember(JsonObject,"description"))
Chrome\Objects(id)\devtoolsFrontendUrl = GetJSONString(GetJSONMember(JsonObject,"devtoolsFrontendUrl"))
Chrome\Objects(id)\title = GetJSONString(GetJSONMember(JsonObject,"title"))
Chrome\Objects(id)\type = GetJSONString(GetJSONMember(JsonObject,"type"))
Chrome\Objects(id)\url = GetJSONString(GetJSONMember(JsonObject,"url"))
Chrome\Objects(id)\webSocketDebuggerUrl = GetJSONString(GetJSONMember(JsonObject,"webSocketDebuggerUrl"))
EndIf
EndProcedure
Procedure ChromeDefaultJson(json.i,Method.s)
mainobj = SetJSONObject(JSONValue(json))
SetJSONInteger(AddJSONMember(mainobj, "id"), Chrome\RequestId) : Chrome\RequestId = Chrome\RequestId+1
SetJSONString(AddJSONMember(mainobj, "method"), Method)
params = AddJSONMember(mainobj,"params")
SetJSONObject(params)
ProcedureReturn params
EndProcedure
Procedure Chrome_OpenWebSocket(TabID.s)
Chrome\Objects(TabID)\WsConnection = WebsocketClient::OpenWebsocketConnection(Chrome\Objects(TabID)\webSocketDebuggerUrl)
ProcedureReturn #True
EndProcedure
Procedure.s Chrome_GetWebsocketResponse(connection,timeout = 0)
p = ElapsedMilliseconds()
Packet$ = ""
Repeat
Delay(1)
If connection
NetworkEvent = NetworkClientEvent(connection)
Select NetworkEvent
Case #PB_NetworkEvent_Data
Frametyp.Websocket\FrameMemory = AllocateMemory(1)
Frametyp\Frametyp = WebsocketClient::ReceiveFrame(connection,@Frametyp)
If Frametyp\Frametyp = WebsocketClient::#frame_text
Packet$ + PeekS(Frametyp\FrameMemory,MemoryStringLength(Frametyp\FrameMemory,#PB_UTF8)-1,#PB_UTF8)
ElseIf Frametyp\Frametyp = WebsocketClient::#frame_binary
Debug "Received Binaryframe"
EndIf
FreeMemory(Frametyp\FrameMemory)
p = ElapsedMilliseconds()
Case #PB_NetworkEvent_Disconnect
ProcedureReturn ""
Case #PB_NetworkEvent_None
If Len(Packet$) > 0
If Not timeout
ProcedureReturn Packet$
EndIf
EndIf
EndSelect
Else
Debug "Connection lost?"
Break
EndIf
Until ElapsedMilliseconds() - p > timeout And timeout > 0
ProcedureReturn Packet$
EndProcedure
;Fuctions from HTTP-Endpoints
Procedure Chrome_List()
HttpRequest = HTTPRequestMemory(#PB_HTTP_Get, "localhost:"+Str(DebugPort)+"/json/list")
If HttpRequest
Response$ = HTTPInfo(HTTPRequest, #PB_HTTP_Response)
FinishHTTP(HTTPRequest)
Else
ProcedureReturn -1
EndIf
json = ParseJSON(#PB_Any,Response$)
If json
If JSONType(JSONValue(json)) = #PB_JSON_Array
For i = 0 To JSONArraySize(JSONValue(json)) - 1
Element = GetJSONElement(JSONValue(json), i)
ChromeDefaultObjectAdd(Element)
Next
EndIf
FreeJSON(json)
EndIf
EndProcedure
Procedure Chrome_GetVersion()
HttpRequest = HTTPRequestMemory(#PB_HTTP_Get, "localhost:"+Str(DebugPort)+"/json/version")
If HttpRequest
Response$ = HTTPInfo(HTTPRequest, #PB_HTTP_Response)
FinishHTTP(HTTPRequest)
Else
ProcedureReturn -1
EndIf
json = ParseJSON(#PB_Any,Response$)
If json
value = JSONValue(json)
If JSONType(value) = #PB_JSON_Object
Chrome\Version\Browser= GetJSONString(GetJSONMember(value,"Browser"))
Chrome\Version\ProtocolVersion= GetJSONString(GetJSONMember(value,"Protocol-Version"))
Chrome\Version\UserAgent= GetJSONString(GetJSONMember(value,"User-Agent"))
Chrome\Version\V8Version= GetJSONString(GetJSONMember(value,"V8-Version"))
Chrome\Version\WebKitVersion= GetJSONString(GetJSONMember(value,"WebKit-Version"))
Chrome\Version\webSocketDebuggerUrl= GetJSONString(GetJSONMember(value,"webSocketDebuggerUrl"))
EndIf
EndIf
FreeJSON(json)
EndProcedure
Procedure.s Chrome_NewTab();Returns ID
HttpRequest = HTTPRequestMemory(#PB_HTTP_Get, "localhost:"+Str(DebugPort)+"/json/new")
If HttpRequest
Response$ = HTTPInfo(HTTPRequest, #PB_HTTP_Response)
FinishHTTP(HTTPRequest)
Else
ProcedureReturn ""
EndIf
json = ParseJSON(#PB_Any,Response$)
If json
ChromeDefaultObjectAdd(JSONValue(json))
FreeJSON(json)
EndIf
ProcedureReturn MapKey(Chrome\Objects())
EndProcedure
Procedure Chrome_ActivateTab(TabID.s)
HttpRequest = HTTPRequestMemory(#PB_HTTP_Get, "localhost:"+Str(DebugPort)+"/json/activate/"+TabID)
If HttpRequest
Response$ = HTTPInfo(HTTPRequest, #PB_HTTP_Response)
FinishHTTP(HTTPRequest)
Else
ProcedureReturn -1
EndIf
If Response$ = "Target activated"
ProcedureReturn 1
Else
ProcedureReturn 0
EndIf
EndProcedure
Procedure Chrome_CloseTab(TabID.s)
HttpRequest = HTTPRequestMemory(#PB_HTTP_Get, "localhost:"+Str(DebugPort)+"/json/close/"+TabID)
If HttpRequest
Response$ = HTTPInfo(HTTPRequest, #PB_HTTP_Response)
FinishHTTP(HTTPRequest)
Else
ProcedureReturn -1
EndIf
If Response$ = "Target is closing"
ProcedureReturn 1
Else
ProcedureReturn 0
EndIf
EndProcedure
; Functions for Websocket
; More commands can be found here(also browse left nav-bar):
; https://chromedevtools.github.io/devtools-protocol/tot/Browser/
Structure PageNavigateReturn
frameId.s
loaderId.s
errorText.s
EndStructure
Procedure.i Chrome_PageNavigate(TabID.s,*Returnvalue.PageNavigateReturn,url.s,referrer.s="",transitionType.i=-1,frameId.i=-1,referrerPolicy.i=-1)
json = CreateJSON(#PB_Any)
params = ChromeDefaultJson(json,"Page.navigate");erstelle schonmal en JSON mit Requestid(ein counter) und Methode
;Page.navigate Parameters
SetJSONString(AddJSONMember(params, "url"), url)
If Len(referrer ) > 0 : SetJSONString(AddJSONMember(params, "referrer"), referrer) :EndIf
If transitionType > 0 : SetJSONInteger(AddJSONMember(params, "transitionType"), transitionType) :EndIf
If frameId > 0 : SetJSONInteger(AddJSONMember(params, "frameId"), frameId) :EndIf
If referrerPolicy > 0 : SetJSONInteger(AddJSONMember(params, "referrerPolicy"), referrerPolicy) :EndIf
request$ = ComposeJSON(json):FreeJSON(json)
;Hau raus die Scheisse
WebsocketClient::SendTextFrame(Chrome\Objects(TabID)\WsConnection,request$)
Chrome_GetWebsocketResponse(Chrome\Objects(TabID)\WsConnection)
EndProcedure
Procedure.s Chrome_DOMenable(TabID.s,enable)
json = CreateJSON(#PB_Any)
If enable
params = ChromeDefaultJson(json,"DOM.enable");erstelle schonmal en JSON mit Requestid(ein counter) und Methode
Else
params = ChromeDefaultJson(json,"DOM.disable");erstelle schonmal en JSON mit Requestid(ein counter) und Methode
EndIf
request$ = ComposeJSON(json):FreeJSON(json)
WebsocketClient::SendTextFrame(Chrome\Objects(TabID)\WsConnection,request$)
EndProcedure
Procedure Chrome_DOMgetDocument(TabID.s,depth.i=-1,pierce.b=0) ;NOT WORKING
json = CreateJSON(#PB_Any)
params = ChromeDefaultJson(json,"DOM.getDocument");erstelle schonmal en JSON mit Requestid(ein counter) und Methode
SetJSONInteger(AddJSONMember(params, "depth"), depth)
; SetJSONInteger(AddJSONMember(params, "pierce"), pierce)
Debug Chrome_GetWebsocketResponse(Chrome\Objects(TabID)\WsConnection,200)
request$ = ComposeJSON(json):FreeJSON(json)
WebsocketClient::SendTextFrame(Chrome\Objects(TabID)\WsConnection,request$)
Result$ = Chrome_GetWebsocketResponse(Chrome\Objects(TabID)\WsConnection,5000)
Debug Result$
nodeID = Val(StringField(Mid(Result$,FindString(Result$,"nodeId"+Chr(34)+":")+8),1,","))
ProcedureReturn NodeID ; I only want the root nodeID
EndProcedure
Procedure.s Chrome_DOMgetOuterHTML(TabID.s,NodeId.i=-1,BackendNodeId=-1,RuntomeRometObjectID.i=-1)
json = CreateJSON(#PB_Any)
params = ChromeDefaultJson(json,"DOM.getOuterHTML");erstelle schonmal en JSON mit Requestid(ein counter) und Methode
If NodeID > -1
SetJSONInteger(AddJSONMember(params, "nodeId"), NodeId)
EndIf
request$ = ComposeJSON(json):FreeJSON(json)
WebsocketClient::SendTextFrame(Chrome\Objects(TabID)\WsConnection,request$)
Debug Chrome_GetWebsocketResponse(Chrome\Objects(TabID)\WsConnection,500)
EndProcedure
Procedure.s Chrome_Runtimeenable(TabID.s,enable)
json = CreateJSON(#PB_Any)
If enable
params = ChromeDefaultJson(json,"Runtime.enable");erstelle schonmal en JSON mit Requestid(ein counter) und Methode
Else
params = ChromeDefaultJson(json,"Runtime.disable");erstelle schonmal en JSON mit Requestid(ein counter) und Methode
EndIf
request$ = ComposeJSON(json):FreeJSON(json)
WebsocketClient::SendTextFrame(Chrome\Objects(TabID)\WsConnection,request$)
EndProcedure
Procedure.s Chrome_Logenable(TabID.s,enable)
json = CreateJSON(#PB_Any)
If enable
params = ChromeDefaultJson(json,"Log.enable");erstelle schonmal en JSON mit Requestid(ein counter) und Methode
Else
params = ChromeDefaultJson(json,"Log.disable");erstelle schonmal en JSON mit Requestid(ein counter) und Methode
EndIf
request$ = ComposeJSON(json):FreeJSON(json)
WebsocketClient::SendTextFrame(Chrome\Objects(TabID)\WsConnection,request$)
EndProcedure
Procedure.s Chrome_Runtimeevaluate(TabID.s,expression.s)
If Len(expression) = 0
ProcedureReturn ""
EndIf
json = CreateJSON(#PB_Any)
params = ChromeDefaultJson(json,"Runtime.evaluate");erstelle schonmal en JSON mit Requestid(ein counter) und Methode
SetJSONString (AddJSONMember(params, "expression"), expression)
request$ = ComposeJSON(json):FreeJSON(json)
WebsocketClient::SendTextFrame(Chrome\Objects(TabID)\WsConnection,request$)
EndProcedure
Procedure Chrome_BrowsersetDownloadBehavior(behaviour.s,browserContextId=-1,downloadPath.s="",eventsEnabled=-1)
;Not working?
If Len(behaviour) = 0
ProcedureReturn 0
EndIf
json = CreateJSON(#PB_Any)
params = ChromeDefaultJson(json,"Browser.setDownloadBehavior");erstelle schonmal en JSON mit Requestid(ein counter) und Methode
SetJSONString (AddJSONMember(params, "behaviour"), behaviour)
If browserContextId > -1 : SetJSONInteger (AddJSONMember(params, "browserContextId"), browserContextId):EndIf
If Len(downloadPath) > -1 : SetJSONString (AddJSONMember(params, "downloadPath"), downloadPath):EndIf
If eventsEnabled > -1 : SetJSONInteger (AddJSONMember(params, "eventsEnabled"), eventsEnabled):EndIf
request$ = ComposeJSON(json):FreeJSON(json)
EndProcedure
Procedure.s Chrome_GetHMTL(TabID.s)
; Bishierhin war noch alles gut. Jetzt kommt Dreck. Ausleiten des HTML als Download...
Filename$ = "Controller_Download_Text"
Filepath.s = GetUserDirectory(#PB_Directory_Downloads)+Filename$ +".txt"
If FileSize(Filepath) > 0
DeleteFile(Filepath)
EndIf
Chrome_Runtimeevaluate(TabID,"const data = new XMLSerializer().serializeToString(document); const a = document.createElement('a');const blob = new Blob([JSON.stringify(data)]);a.href = URL.createObjectURL(blob);a.download = '"+Filename$+"';a.click();")
Delay(600);min 450
;Noch am schreiben?
Repeat
Delay(10)
f = ReadFile(#PB_Any,Filepath)
Until f
content$ = ReadString(f,#PB_UTF8,FileSize(Filepath))
CloseFile(f)
DeleteFile(Filepath)
ProcedureReturn content$
EndProcedure
Procedure Chrome_JS_ClickOnButtonByID(TabID.s,ButtonID.s)
Chrome_Runtimeevaluate(TabID,"document.getElementById('"+ButtonID+"').click();")
EndProcedure
Procedure Chrome_JS_ClickOnButtonByClass(TabID.s,Classname.s)
Chrome_Runtimeevaluate(TabID,"document.querySelector('."+ReplaceString(Classname," ",".")+"').click();")
EndProcedure
Code: Alles auswählen
;Ka wie das Messaging funktioniert. Daher arbeite ich nur mit Funktionen und Rückgabewerten. Ausleiten von Console und allgemeinen Events fehlt daher.
;Kill all other Chrome Tabs (important to kill tabs, not process)
CloseAllProcess("chrome.exe")
;Start new one
Phwnd = RunProgram("chrome.exe","--remote-debugging-port="+DebugPort,GetCurrentDirectory())
;{ Wait for start
Repeat
conn = OpenNetworkConnection("127.0.0.1",9222)
If conn
Break
EndIf
Delay(100)
ForEver
CloseNetworkConnection(conn)
;}
Chrome_List()
;{ Close all Extentions and other tabs
; ForEach Chrome\Objects()
; If Chrome\Objects()\type = "page"
; Continue
; Else
; Chrome_CloseTab(MapKey(Chrome\Objects()))
; EndIf
; Next
; Chrome_List()
;}
;{ Get first page ID
ForEach Chrome\Objects()
If Chrome\Objects()\type = "page"
Break
EndIf
Next
;}
ID.s = MapKey(Chrome\Objects())
Chrome_OpenWebSocket(ID)
Chrome_Runtimeenable(ID,1)
Chrome_PageNavigate(ID,@ReturnValue.PageNavigateReturn,"https://www.w3schools.com/tags/tag_button.asp")
Delay(1000)
Chrome_JS_ClickOnButtonByID(ID,"w3loginbtn")
Delay(5000)
HTML$ = Chrome_GetHMTL(ID)
Debug HTML$
CloseNetworkConnection(Chrome\Objects()\WsConnection)
Lieferumfang:
Per HTTP-Endpoints
Tabs Öffnen, schliessen, fokusieren, Liste mit allen Tabs und Objekten bekommen
Per Process-Control
Chrome im debug-modus starten, "--headless" könnte man auch noch nehmen, dann wäre der Spass auch noch unsichtbar m Hintergrund. (Was eigentlich der ganze Sinn der Sache ist)
Per Websocket & Chromedevtools
Siehe: chromedevtools.github.io
Implementiert und getestet hab ich: Page.Navigate,DOM.enable,DOMget.OuterHTML,Runtime.Evaluate [weitere Funktionen einbauen ist ein Klacks, orientiert euch einfach anderen]
Per Javascript -> Websocket
Button-clilck über ID oder Classname
HTML ausleiten
Ganz behindert, über ein JS-Befehl der das Ding runterlädt. Danach lese ich die Datei ein *sorry*. Bitte um Verbesserung!
Gruß
Syr2