Chromium WebGadget v4

Developed or developing a new product in PureBasic? Tell the world about it.
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: Chromium WebGadget

Post by JHPJHP »

Hi zikitrake,
zikitrake wrote:Is there any way to check that a page has actually finished loading?
Yes, and all the control is in the hands of the programmer; no predefined function, but still very simple.

Some Information
EventID is user-defined and can be any number.
You can use the same number for every command.
You can change the number when executing the same command multiple times.
But, it becomes important to keep track of the number when you need to monitor an event, especially for returned data.

Other events are predefined, and once a Domain is enabled can be easily tracked. Personally, when I finish using a Domain I disable it.

Here is a simple test using CDP Control Panel.
1. Select browser.
2. Listen Port.
3. Connect DevTools.
4. Press F1 to open Display Area.
5. Right mouse click Page.navigate in Command List.
6. Choose Send Selected.

In the Display Area the only event you see is Page.navigate.
1. Enter 12345 in the EventID field.
2. Enter Page.enable in the Method field.
3. Press the Send Command button.

In the Display Area you see your event.
1. Right mouse click Page.navigate in Command List.
2. Choose Send Selected.

The event you're looking for is Page.frameStoppedLoading with a FrameId that matches the PageID; the DevTools Protocol is your friend.

The following script is a bit advanced, but should provide a better understanding of the WebGadget and answer your question.

Code: Select all

Enumeration
  #MainWindow
  #CB_WebGadget
  #ButtonGadget
EndEnumeration

#CB_WebGadget_User_Directory_Override = #True
#CB_WebGadget_User_Directory_Name = #PB_Compiler_Filename
#CB_WebSocket_Enable_DevTools_Protocol = #True

Enumeration #PB_Event_FirstCustomValue
  #CBWS_Event_Port_Listen_Connection
  #CBWS_Event_Page_Loaded
EndEnumeration

IncludeFile "..\CBWG Sources\cbwg_sources.pbi"

Procedure DevToolsEvent(JSONValue, Connection, PageID.s)
  If ExamineJSONMembers(JSONValue)
    SendData.SEND_DATA

    If NextJSONMember(JSONValue)
      JSONMemberValue = JSONMemberValue(JSONValue)

      Select JSONType(JSONMemberValue)
        Case #PB_JSON_Number
          If JSONMemberKey(JSONValue) = "id"
            EventID = GetJSONInteger(JSONMemberValue)

            Select EventID
              Case 12345 : Debug "Domain Page enabled"
            EndSelect
          EndIf
        Case #PB_JSON_String
          If JSONMemberKey(JSONValue) = "method"
            Method$ = GetJSONString(JSONMemberValue)

            Select Method$
              Case "Page.frameStoppedLoading"
                JSONParams = GetJSONMember(JSONValue, "params")

                If JSONParams
                  JSONOFrameId = GetJSONMember(JSONParams, "frameId")

                  If JSONOFrameId
                    FrameId$ = GetJSONString(JSONOFrameId)

                    If FrameId$ = PageID
                      PostEvent(#CBWS_Event_Page_Loaded)
                      SendData\EventID = 54321
                      SendData\Method = "Page.disable"
                      SendData\Params = #Null$
                      CB_WebSocket_Send(Connection, @SendData)
                    EndIf
                  EndIf
                EndIf
            EndSelect
          EndIf
      EndSelect
    EndIf
  EndIf
EndProcedure

WindowWidth = 800 : WindowHeight = 600
nFlags = #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered

If OpenWindow(#MainWindow, 0, 0, WindowWidth, WindowHeight, "Chromium Browser WebGadget", nFlags)
  CB_WebGadget(#CB_WebGadget, 10, 50, 780, 540, #CB_WebGadget_Flat)
  ButtonGadget(#ButtonGadget, 10, 10, 150, 30, "Page.navigate")
  DisableGadget(#ButtonGadget, #True)
  cbwg_data.CBWG_DATA
  cbwg_data\GadgetNumber = #CB_WebGadget
  cbwg_data\SourceURL = "https://start.duckduckgo.com"
  CB_WebGadget_Init(cbwg_data)
  SendData.SEND_DATA

  Repeat
    If Connection
      NetworkClientEvent = NetworkClientEvent(Connection)

      Select NetworkClientEvent
        Case #PB_NetworkEvent_Data
          *Response = CB_WebSocket_Receive(Connection)

          If *Response
            Response$ = Trim(PeekS(*Response, -1, #PB_UTF8 | #PB_ByteLength))

            If Response$
              nCount = CountString(Response$, #LF$)

              If nCount
                For rtnCount = 1 To nCount + 1
                  ResponseItem$ = StringField(Response$, rtnCount, #LF$)
                  JSON_Event_1 = ParseJSON(#PB_Any, ResponseItem$)
                  JSONValue = JSONValue(JSON_Event_1)

                  If IsJSON(JSON_Event_1) And JSONType(JSONValue) = #PB_JSON_Object
                    DevToolsEvent(JSONValue, Connection, PageID$)
                    FreeJSON(JSON_Event_1)
                  EndIf
                Next
              Else
                JSON_Event_2 = ParseJSON(#PB_Any, Response$)
                JSONValue = JSONValue(JSON_Event_2)

                If IsJSON(JSON_Event_2) And JSONType(JSONValue) = #PB_JSON_Object
                  DevToolsEvent(JSONValue, Connection, PageID$)
                  FreeJSON(JSON_Event_2)
                EndIf
              EndIf
            EndIf
          EndIf
          FreeMemory(*Response)
        Case #PB_NetworkEvent_None
        Case #PB_NetworkEvent_Disconnect
      EndSelect
    EndIf
    Event = WindowEvent()

    Select Event
      Case #CBWS_Event_Port_Listen_Connection
        *EventData = EventData()

        If *EventData
          EventData$ = PeekS(*EventData, -1, #PB_UTF8)

          If Not Len(PageID$)
            JSON_Port = ParseJSON(#PB_Any, EventData$)

            If IsJSON(JSON_Port)
              NewList PortData.PORT_DATA()
              ExtractJSONList(JSONValue(JSON_Port), PortData())

              ForEach PortData()
                If PortData()\type = "page"
                  PageID$ = PortData()\id
                  Connection = CB_WebSocket_Connect(PageID$)

                  If Connection : DisableGadget(#ButtonGadget, #False) : EndIf

                  Break
                EndIf
              Next
              FreeJSON(JSON_Port)
            EndIf
          EndIf
          FreeMemory(*EventData)
        EndIf
      Case #CBWS_Event_Page_Loaded
        MessageRequester("Chromium Browser WebGadget", "Page Loaded", #PB_MessageRequester_Info)
      Case #PB_Event_Gadget
        Select EventGadget()
          Case #ButtonGadget
            If Connection
              SendData\EventID = 12345
              SendData\Method = "Page.enable"
              SendData\Params = #Null$
              CB_WebSocket_Send(Connection, @SendData)
              SendData\EventID = 20300
              SendData\Method = "Page.navigate"
              SendData\Params = #DQUOTE$ + "url" + #DQUOTE$ + ":" + #DQUOTE$ + "https://www.purebasic.fr/english/index.php" + #DQUOTE$
              CB_WebSocket_Send(Connection, @SendData)
            EndIf
        EndSelect
      Case #PB_Event_CloseWindow : Break
    EndSelect
  ForEver
EndIf
Last edited by JHPJHP on Sun Jul 31, 2022 5:40 am, edited 7 times in total.
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: Chromium WebGadget

Post by JHPJHP »

Hi zikitrake,

Because Page.frameStoppedLoading is still listed as Experimental you may want to use Page.frameNavigated?

Code: Select all

Select Method$
  Case "Page.frameNavigated"
    JSONParams = GetJSONMember(JSONValue, "params")

    If JSONParams
      JSONFrame = GetJSONMember(JSONParams, "frame")

      If JSONFrame
        JSONOId = GetJSONMember(JSONFrame, "id")

        If JSONOId
          FrameId$ = GetJSONString(JSONOId)

          If FrameId$ = PageID
            PostEvent(#CBWS_Event_Page_Loaded)
            SendData\EventID = 54321
            SendData\Method = "Page.disable"
            SendData\Params = #Null$
            CB_WebSocket_Send(Connection, @SendData)
          EndIf
        EndIf
      EndIf
    EndIf
EndSelect
Last edited by JHPJHP on Tue Jul 26, 2022 6:23 am, edited 1 time in total.
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: Chromium WebGadget

Post by JHPJHP »

Updated:
- improved DevTools examples
- small update to Target Structure

DevTools Examples
Improved event script to stop new tabs and windows from opening, redirecting the current page to the selected URL.
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: Chromium WebGadget

Post by JHPJHP »

Updated:
- various minor improvements

Example in previous post has been updated.

NOTE: With the new update the following script must be removed from your working code as it is now part of the include file.

Code: Select all

CreateThread(@CB_WebSocket_Listen(), #Null)
Last edited by JHPJHP on Sun Jul 31, 2022 9:34 pm, edited 1 time in total.
zikitrake
Addict
Addict
Posts: 834
Joined: Thu Mar 25, 2004 2:15 pm
Location: Spain

Re: Chromium WebGadget

Post by zikitrake »

JHPJHP wrote: Tue Jul 26, 2022 5:35 am Hi zikitrake,

Because Page.frameStoppedLoading is still listed as Experimental you may want to use Page.frameNavigated?...
Thank you very much for your explanations, links and examples. Now it is much clearer to me how to work with the DevToolsEvent() procedure and how to use and add my own events and methods..

Regarding the two you give me, the experimental one (Page.frameStoppedLoading), I have seen that sometimes it is not captured.

I have added to your code two global variables to count button clicks and event captures and, for example, with https://docs.google.com, Page.frameStoppedLoading is not always obtained. With Page.frameNavigated however, it always works :)

Code: Select all

Global countClicks, countLoaded

Enumeration
  #MainWindow
  #CB_WebGadget
  #ButtonGadget
EndEnumeration

#CB_WebGadget_User_Directory_Override  = #True
#CB_WebGadget_User_Directory_Name      = #PB_Compiler_Filename
#CB_WebSocket_Enable_DevTools_Protocol = #True

Enumeration #PB_Event_FirstCustomValue
  #CBWS_Event_Listen_Port_Connection
  #CBWS_Event_Page_Loaded
EndEnumeration

IncludeFile "..\CBWG Sources\cbwg_sources.pbi"

Procedure DevToolsEvent(JSONValue, Connection, PageID.s)
  If ExamineJSONMembers(JSONValue)
    SendData.SEND_DATA
    
    If NextJSONMember(JSONValue)
      JSONMemberValue = JSONMemberValue(JSONValue)
      
      Select JSONType(JSONMemberValue)
        Case #PB_JSON_Number
          If JSONMemberKey(JSONValue) = "id"
            EventID = GetJSONInteger(JSONMemberValue)
            
            Select EventID
              Case 12345 : ;Debug "Domain Page enabled"
            EndSelect
          EndIf
        Case #PB_JSON_String
          If JSONMemberKey(JSONValue) = "method"
            Method$ = GetJSONString(JSONMemberValue)
            Select Method$
                
;               Case "Page.frameNavigated"
;                 
;                 JSONParams = GetJSONMember(JSONValue, "params")
; 
;                 If JSONParams
;                   JSONFrame = GetJSONMember(JSONParams, "frame")
;             
;                   If JSONFrame
;                     JSONOId = GetJSONMember(JSONFrame, "id")
;             
;                     If JSONOId
;                       FrameId$ = GetJSONString(JSONOId)
;                       Debug "Frame: " + FrameId$
;                       Debug "Page: " + PageID
;                       If FrameId$ = PageID                      
;                         PostEvent(#CBWS_Event_Page_Loaded)
;                         SendData\EventID = 54321
;                         SendData\Method = "Page.disable"
;                         SendData\Params = #Null$
;                         CB_WebSocket_Send(Connection, @SendData)
;                       EndIf
;                     EndIf
;                   EndIf
;                 EndIf
                
              Case "Page.frameStoppedLoading"
                JSONParams = GetJSONMember(JSONValue, "params")
                
                If JSONParams
                  JSONOFrameId = GetJSONMember(JSONParams, "frameId")
                  
                  If JSONOFrameId
                    FrameId$ = GetJSONString(JSONOFrameId)
                    If FrameId$ = PageID
                      PostEvent(#CBWS_Event_Page_Loaded)
                      SendData\EventID = 54321
                      SendData\Method  = "Page.disable"
                      SendData\Params  = #Null$
                      CB_WebSocket_Send(Connection, @SendData)
                    EndIf
                  EndIf
                EndIf
            EndSelect
          EndIf
      EndSelect
    EndIf
  EndIf
EndProcedure

WindowWidth = 800 : WindowHeight = 600
nFlags      = #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered

If OpenWindow(#MainWindow, 0, 0, WindowWidth, WindowHeight, "Chromium Browser WebGadget", nFlags)
  CB_WebGadget(#CB_WebGadget, 10, 50, 780, 540, #CB_WebGadget_Flat)
  ButtonGadget(#ButtonGadget, 10, 10, 150, 30, "Page.navigate")
  DisableGadget(#ButtonGadget, #True)
  cbwg_data.CBWG_DATA
  cbwg_data\GadgetNumber = #CB_WebGadget
  cbwg_data\SourceURL    = "https://start.duckduckgo.com"
  CB_WebGadget_Init(cbwg_data)
  SendData.SEND_DATA
  
  Repeat
    If Connection
      NetworkClientEvent = NetworkClientEvent(Connection)
      
      Select NetworkClientEvent
        Case #PB_NetworkEvent_Connect
        Case #PB_NetworkEvent_Data
          *Response = CB_WebSocket_Receive(Connection)
          
          If *Response
            Response$ = Trim(PeekS(*Response, -1, #PB_UTF8 | #PB_ByteLength))
            
            If Response$
              nCount = CountString(Response$, #LF$)
              
              If nCount
                For rtnCount = 1 To nCount + 1
                  ResponseItem$ = StringField(Response$, rtnCount, #LF$)
                  JSON_Event_1  = ParseJSON(#PB_Any, ResponseItem$)
                  JSONValue     = JSONValue(JSON_Event_1)
                  
                  If IsJSON(JSON_Event_1) And JSONType(JSONValue) = #PB_JSON_Object
                    DevToolsEvent(JSONValue, Connection, PageID$)
                    FreeJSON(JSON_Event_1)
                  EndIf
                Next
              Else
                JSON_Event_2 = ParseJSON(#PB_Any, Response$)
                JSONValue    = JSONValue(JSON_Event_2)
                
                If IsJSON(JSON_Event_2) And JSONType(JSONValue) = #PB_JSON_Object
                  DevToolsEvent(JSONValue, Connection, PageID$)
                  FreeJSON(JSON_Event_2)
                EndIf
              EndIf
            EndIf
          EndIf
          FreeMemory(*Response)
        Case #PB_NetworkEvent_None
        Case #PB_NetworkEvent_Disconnect
      EndSelect
    EndIf
    Event = WaitWindowEvent()
    
    Select Event
      Case #CBWS_Event_Listen_Port_Connection
        *EventData = EventData()
        
        If *EventData
          EventData$ = PeekS(*EventData, -1, #PB_UTF8)
          
          If Not Len(PageID$)
            JSON_Port = ParseJSON(#PB_Any, EventData$)
            
            If IsJSON(JSON_Port)
              NewList PortData.PORT_DATA()
              ExtractJSONList(JSONValue(JSON_Port), PortData())
              
              ForEach PortData()
                If PortData()\type = "page"
                  PageID$    = PortData()\id
                  Connection = CB_WebSocket_Connect(PageID$)
                  
                  If Connection : DisableGadget(#ButtonGadget, #False) : EndIf
                  
                  Break
                EndIf
              Next
              FreeJSON(JSON_Port)
            EndIf
          EndIf
          FreeMemory(*EventData)
        EndIf
      Case #CBWS_Event_Page_Loaded
        ;MessageRequester("Chromium Browser WebGadget", "Page Loaded", #PB_MessageRequester_Info)
        countLoaded + 1
        Debug "CountLoaded: " + "" + countLoaded
        
      Case #PB_Event_Gadget
        Select EventGadget()
          Case #ButtonGadget
            If Connection
              SendData\EventID = 12345
              SendData\Method  = "Page.enable"
              SendData\Params  = #Null$
              CB_WebSocket_Send(Connection, @SendData)
              SendData\EventID = 20300
              SendData\Method  = "Page.navigate"
              SendData\Params  = #DQUOTE$ + "url" + #DQUOTE$ + ":" + #DQUOTE$ + "https://docs.google.com" + #DQUOTE$
              CB_WebSocket_Send(Connection, @SendData)
              countClicks + 1
              Debug "CountClicks: " + "" + countClicks
            EndIf
        EndSelect
      Case #PB_Event_CloseWindow : Break
    EndSelect
    Delay(1)
  ForEver
EndIf
Image

Translated with www.DeepL.com/Translator (free version)
zikitrake
Addict
Addict
Posts: 834
Joined: Thu Mar 25, 2004 2:15 pm
Location: Spain

Re: Chromium WebGadget

Post by zikitrake »

On another side of things,

In CB_WebGadget_Basic.pb, I'm trying to use Click() on an element obtained via xPath instead of by its ID, but I find it impossible. Any trick?

I changed original code:

Code: Select all

document.getElementById('guide-icon').click();
to

Code: Select all

var elementZ = document.evaluate("(//button[@id='button' and contains(@class,'yt-icon-button')])[5]", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; elementZ.click();
But it doesn't seem to work :shock:

EDIT: MY FAULT!! change " to \" solve my error:

Code: Select all

var elementZ = document.evaluate(\"(//button[@id='button' and contains(@class,'yt-icon-button')])[5]\", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; elementZ.click();
Thank you, again
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: Chromium WebGadget

Post by JHPJHP »

Hi zikitrake,

Thank you for your detailed response. You seem to be grasping the Chromium WebGadget and DevTools Protocol quickly.
zikitrake wrote:Regarding the two you give me, the experimental one (Page.frameStoppedLoading), I have seen that sometimes it is not captured.
This might be because the event is still experimental, or possibly a timing issue caused by sending the navigate command immediately after enabling the Page Domain? I noticed when sending multiple methods, returned events are not always ordered. Which may indicate that sending methods too close together can result in commands executing out of sequence?

Here are a couple ways to handle multiple events.
1. New methods are posted from the DevToolsEvent Procedure after a previous method is processed.
2. Use a delay between methods...

Do not use a standard delay that halts program execution as there is a greater chance of missing events. Instead, treat the main program event loop as you would when programming sprites; do not pause the event loop and only process frames when required.

The first option is probably the better one under most circumstances, but there may be times when a delay is required.

If you haven't seen the following post, it hosts two examples demonstrating separate techniques for sending multiple methods.
https://www.purebasic.fr/english/viewto ... 40#p586540

Before sending JavaScript I first pass the expression through the following Procedure (CB_WebGadget_Detail.pb).
- works well for a small amount of code, but will probably need modifying for more complex algorithms

Code: Select all

Procedure.s FormatExpression(Expression.s)
  Expression = ReplaceString(Expression, #CRLF$, "\r")
  Expression = ReplaceString(Expression, #CR$, "\r")
  Expression = ReplaceString(Expression, #LF$, "\r")
  Expression = ReplaceString(Expression, #TAB$, "\t")
  Expression = ReplaceString(Expression, #DQUOTE$, "\" + #DQUOTE$)
  ProcedureReturn Expression
EndProcedure
zikitrake
Addict
Addict
Posts: 834
Joined: Thu Mar 25, 2004 2:15 pm
Location: Spain

Re: Chromium WebGadget

Post by zikitrake »

Thank you very much for all the advice (and patience!).

As you tell me, yes, it seems better the first option (I will study CDP_CONTROL_PANEL and the use of CommandQueue() ) :)

Anyway, I'll keep the FormatExpression() procedure, which will also come in handy.

This is an example (very ugly, that yes) on how I am working right now...

Code: Select all

Procedure.s WebGadget_ReturnResult(Connection, timeout.l = 5000)
  Protected res.s
  Protected NetworkClientEvent 
  Protected Response$
  Protected JSON_Event_1, JSONValue
  Protected tini.f
  
  tini = ElapsedMilliseconds()
  
  Repeat

    NetworkClientEvent = NetworkClientEvent(Connection)

    Select NetworkClientEvent
      Case #PB_NetworkEvent_None
        Break
      Case #PB_NetworkEvent_Connect
      Case #PB_NetworkEvent_Data
        Protected *Response = CB_WebSocket_Receive(Connection)
        If *Response
          Response$ = Trim(PeekS(*Response, -1, #PB_UTF8 | #PB_ByteLength))
          If Response$
            Debug Response$
            JSON_Event_1  = ParseJSON(#PB_Any, Response$)
            JSONValue     = JSONValue(JSON_Event_1)              
            If IsJSON(JSON_Event_1) And JSONType(JSONValue) = #PB_JSON_Object
               res = DevToolsEvent(JSONValue, Connection, "")
               FreeJSON(JSON_Event_1)
               Break
            EndIf
          EndIf
        EndIf
    EndSelect  
    
    If ElapsedMilliseconds() - tini > timeout
      res = ""
      Break
    EndIf
    
  ForEver
  
  ProcedureReturn res
  
EndProcedure

Procedure.s WebGadget_ElementGetID(Connection, sFieldId.s, onlyThisType.s = "", elemento.s = "elementoZ")
  ;********************************************************************************
  ; Return ID of an element
  ; type.s must be: "xpath"
  ;                 "css selector"
  ; onlyThisType can be: "xpath|css selector|id|link text|partial link text|tag name" (used for faster ID search)
  ;********************************************************************************
  
  Protected SendData.SEND_DATA
  Protected Connection = 
  Protected MethodParam$
    Protected res.s
  Protected sScript.s
  Protected typesID.s = "xpath|css selector"; |id|link text|partial link text|tag name"

  If Len(onlyThisType): typesID = onlyThisType: EndIf
  
  Protected idxTypes.l
  Protected type.s
  
  sFieldId = "\" + #DQUOTE$ + sFieldId + "\" + #DQUOTE$
  
  sScript = ""
  
  For idxTypes = 1 To CountString(typesID, "|") + 1
    type    = StringField(typesID, idxTypes, "|")
    sScript = "// WebGadget_ElementGetID()" + #CRLF$
    Select type
      Case "xpath"
        sScript + "var " + elemento + " = document.evaluate(" + sFieldId + ", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;" + #CRLF$
      Case "css selector"
        sScript + "var " + elemento + " = document.querySelector(" + sFieldId + ");" + #CRLF$
    EndSelect
    
    sScript + "if (" + elemento + "!=null) {" + #CRLF$
    sScript + "'OK_'+" + elemento + ";" + #CRLF$
    sScript + "}" + #CRLF$
    sScript + "else {" + #CRLF$
    sScript + ~"  'ElementoNulo';" + #CRLF$
    sScript + "}" + #CRLF$
    
    MethodParam$ = ~"\"expression\":\"" + sScript + ~"\",\"awaitPromise\":true"
    
    SendData\EventID = 16003
    SendData\Method  = "Runtime.evaluate"
    SendData\Params  = MethodParam$
    
    If Not CB_WebSocket_Send(Connection, @SendData) : AudioAlert() : EndIf
    
    res = WebGadget_ReturnResult(Connection)
    
    If res = "ElementoNulo"
      ;Debug "ELEMENT NOT FOUND: " + sFieldId + " As " + type
      res = ""
    ElseIf Left(res, 3) = "OK_" And Len(res) > 3
      res = Trim(Mid(res, 4))
      ;Debug "RES: " + res
      Break
    Else
      res = ""
    EndIf
  Next
  
  ProcedureReturn res
  
EndProcedure

And added in DevToolsEvents()

Code: Select all

...
              Case 16003; WebGadget_ElementGetID()
                Debug "elementGetID"
                JSONParams = GetJSONMember(JSONValue, "result")
                If JSONParams
                  JSONParams = GetJSONMember(JSONParams, "result")
                  If JSONParams
                    JSONParams = GetJSONMember(JSONParams, "value")
                    If JSONParams
                      JSONvalor = GetJSONString(JSONParams)
                      res$ = JSONvalor
                      ProcedureReturn res$
                    EndIf
                  EndIf
                EndIf
...
yes! I have to review seriously how to order the sending and receiving of methods and events, yes :oops:
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: Chromium WebGadget

Post by JHPJHP »

Hi zikitrake,

NOTE: The following comments were made without knowing how you're using the Chromium WebGadget, and may not apply to your environment.

Moving the NetworkClientEvent scripts to a Procedure may work, but will also limit returned events and unnecessarily pause the main program loop. An exception would be to run the scripts in a separate thread, something I am considering for a new example.

In addition, removing the Response loop associated with the CB_WebSocket_Receive Procedure may work, but will potentially exclude relevant events, especially when enabling multiple Domains (Page, Network, etc.).

If you're working on scripts to automate a process, but don't require a visual component, then the WebGadget may be overkill.
The CDP Control Panel provides a good example of running a headless browser while still maintaining remote access.

NB*: All of the CDP Procedures should be cross-platform and work with any Chromium based browser.

------------------------------------

Updated:
- added Procedure to stop Port Listen thread
- small changes to CDP Control Panel
- small changes to DevTools examples
- some name changes

Stop Port Listen
Originally written for the CDP Control Panel when connecting to a new tab.
Added to the main window close event, but I don't believe it mandatory under these conditions to end the thread before closing the window.

With the latest update the Constant #CBWS_Event_Listen_Port_Connection must be changed to the following.

Code: Select all

Enumeration #PB_Event_FirstCustomValue
  #CBWS_Event_Port_Listen_Connection
EndEnumeration
NB*: Free executables (x86/x64) can be downloaded from My PureBasic Stuff; see FREE STUFF.
zikitrake
Addict
Addict
Posts: 834
Joined: Thu Mar 25, 2004 2:15 pm
Location: Spain

Re: Chromium WebGadget

Post by zikitrake »

Thank you for your comprehensive answers and advice.

I will try to rethink the event processing, although it is still not very clear to me on how to do it :)

What I do are small automated processes that don't need the visual part (a little example, choose between two dates, click on "hours performed" and get the content of a table of weekly hours performed by the company's employees).

I don't need a visual part but I have this mania to see how the process is done on screen.

Translated with www.DeepL.com/Translator (free version)
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: Chromium WebGadget

Post by JHPJHP »

Updated:
- squashed a bug in the example CDP_Control_Panel.pb

Bug was found in the Close Window routine.

NB*: Bug was fixed approximately one week ago, but I'm just getting around to posting about it now.
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: Chromium WebGadget

Post by JHPJHP »

Updated:
- modified (Edge) browser default preferences

Because the framework uses its own profile, I have standardized the way the browser initially opens. The Microsoft Edge browser changed its default preferences to include the side bar, this update sets the bar hidden when the profile is first created.

NB*: Free executables (x86/x64) can be downloaded from My PureBasic Stuff; see FREE STUFF.
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: Chromium WebGadget

Post by JHPJHP »

Updated:
- added \Standalone Examples\CDP_ISAPI_DLL.pb

The example uses an ISAPI Extension to control a local browser from a remote device (i.e., smart phone).

NB*: Once the development is further along, I'll post basic instructions on how to use the extension.
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: Chromium WebGadget

Post by JHPJHP »

Updated:
- improved \Standalone Examples\CDP_ISAPI_DLL.pb

Clicking the PureBasic image sends the Navigate command to the local browser, changing the URL to the PureBasic website.
Clicking the camera image sends the screenshot command to the local browser (Windows 10 / Chromium Edge).
The screenshot (base64) is then returned to the ISAPI extension and displayed on the iPhone.
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: Chromium WebGadget

Post by JHPJHP »

Updated:
- improved \Standalone Examples\CDP_ISAPI_DLL.pb

NB*: While I'm only demonstrating two buttons, there is no limit to the information that can be retrieved / manipulated.
Locked