RLesur / crrri

A Chrome Remote Interface written in R
https://rlesur.github.io/crrri/
Other
157 stars 12 forks source link

WIP: Rewrite crrri based on EventEmitter - a puppeeter like #28

Closed cderv closed 5 years ago

cderv commented 5 years ago

This issue is there to follow work based on rewriting crrri to change API toward a more puppeeter-like 📦 .

This follows and relates to #8, #15, #27 .

The first idea is to have a 📦 that do not use promises at all.

The steps are in order :

There is still a choice to make on what features from puppeeter we like included in crri. The puppeeter code is rather complex with a mix between EventEmitter inherited class and use of promises. This is something to discuss.

cderv commented 5 years ago

After 1 and 2, we have something that look like this:

  1. Create the connexion to the page directly. CDPSession class will create a websocket connection that will listen to chrome message and
    • emits an error events in case of a message received with an error
    • emits the name of the command sent when it received a message that correspond to the good reception of a command (a message with no error and an id)
    • emits the name of the method received for a message that contains a method. These are the three types of message that we can receive from chrome.
  2. Defines every action in chaining using events, based on the previous emission explained above.
  3. send the first command to start the all flow.
devtools::load_all()

work_dir <- chr_new_data_dir()
chrome <- chr_launch(work_dir = work_dir, headless = TRUE)
ws_endpoint <- chr_get_ws_addr(debug_port = 9222, type = 'page')

# connexion to the session using page endpoint
page_session <- CDPSession$new(ws_endpoint)

page_session$once("Runtime.executionContextCreated", function(...) cat("First command passed!"))

page_session$once("Runtime.enable",
                ~ page_session$sendCommand('Page.enable'))
page_session$once("Page.enable",
                ~ page_session$sendCommand('Runtime.addBinding', params = list(name = "pagedownListener")))
page_session$once("Runtime.addBinding",
                ~ page_session$sendCommand('Page.navigate',
                                         params = list(url = "file:///C:/Users/chris/Documents/test.nb.html")))
page_session$once('Page.domContentEventFired',
                ~ page_session$sendCommand('Runtime.evaluate',
                                           params = list(expression = "!!window.PagedPolyfill")
                ))
page_session$once("Runtime.evaluate",
                function(data) if (!isTRUE(data$result$result$value)) {
                    page_session$sendCommand("Page.printToPDF",
                                    params = list(printBackground = TRUE, preferCSSPageSize = TRUE))
})
page_session$once('Runtime.bindingCalled',
                ~ page_session$sendCommand("Page.printToPDF",
                                    params = list(printBackground = TRUE, preferCSSPageSize = TRUE)
                ))
page_session$once("Page.printToPDF",
               function(data) writeBin(jsonlite::base64_dec(data$result$data), "test.pdf"))

# will launch all the registered events in sequence
page_session$sendCommand('Runtime.enable')
cderv commented 5 years ago

Idea: with event emitter API, it would be possible to register some callback for event known as error, like Network.loadingFailed. This way, if this message is received from chrome, we know that something went wrong and we could throw an error or a warning.

cderv commented 5 years ago

Following a discussion on slack, it seems possible to offer several working APIs if we organize things correctly by stage:

This seems like a very good idea.

cderv commented 5 years ago

This has been going well with #38 and #35. This issue needs to be split in several ideas that we still want to implement and be closed.

cderv commented 5 years ago

This is now handle in #40 and will be closed by the merge I think. Are we ok on this ?

RLesur commented 5 years ago

Sounds good to me