---
title: "Commands and events"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Commands and Events}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}

editor:
  markdown:
    wrap: sentence
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

# Commands and Events

The Chrome DevTools Protocol has two types of methods: *commands* and *events*.
Methods like `Page$navigate()` and `DOM$querySelector()` are **commands**.
That is, they tell the browser to do something; the browser does it, and then sends back some data.

**Events** are quite different from commands.
When, for example, you run `b$Page$loadEventFired()`, it does not send a message to the browser.
Rather, this method tells the R process to wait until it receives a `Page.loadEventFired` message from the browser.

Here is an example of how that event can be used.
Note that these two lines of code must be run together, without any delay at all (this can be enforced by wrapping both lines of code in `{ .... }`).

``` r
library(chromote)
b <- ChromoteSession$new()

# Send a command to navigate to a page
b$Page$navigate("https://www.r-project.org")
#> $frameId
#> [1] "0ADE3CFBAF764B0308ADE1ACCC33358B"
#>
#> $loaderId
#> [1] "112AF4AC0C13FF4A95BED8173C3F4C7F"

# Wait for the Page.loadEventFired event
b$Page$loadEventFired()
#> $timestamp
#> [1] 680.7603
```

After running these two lines, the R process will be blocked.
While it's blocked, the browser will load the page, and then send a message to the R process saying that the `Page.loadEventFired` event has occurred.
The message looks something like this:

``` json
{"method":"Page.loadEventFired","params":{"timestamp":699232.345338}}
```

After the R process receives this message, the function returns the value, which looks like this:

```         
$timestamp
[1] 699232.3
```

> **Note:** This sequence of commands, with `Page$navigate()` and then `Page$loadEventFired()` works interactively when you run the commands slowly, but it will not work 100% of the time.
> See `vignette("example-loading-page")` for a reliable approach to page loading that works in all situations.

## Automatic Events

Chromote insulates the user from some of the details of how the CDP implements event notifications.
Event notifications are not sent from the browser to the R process by default; you must first send a command to enable event notifications for a domain.
For example `Page.enable` enables event notifications for the `Page` domain -- the browser will send messages for *all* `Page` events.
(See the Events section in [this page](https://chromedevtools.github.io/devtools-protocol/tot/Page/)).
These notifications will continue to be sent until the browser receives a `Page.disable` command.

By default, Chromote hides this implementation detail.
When you call `b$Page$loadEventFired()`, Chromote sends a `Page.enable` command automatically, and then waits until it receives the `Page.loadEventFired` event notification.
Then it sends a `Page.disable` command.

Note that in asynchronous mode, the behavior is slightly more sophisticated: it maintains a counter of how many outstanding events it is waiting for in a given domain.
When that count goes from 0 to 1, it sends the `X.enable` command; when the count goes from 1 to 0, it sends the `X.disable` command.
For more information, see `vignette("sync-async")`.

If you need to customize the arguments used by the automatically-run `enable` command, you can use the `$auto_events_enable_args()` method of a `Chromote` or `ChromoteSession` instance, e.g. `b$auto_events_enable_args("Page", enableFileChooserOpenedEvent = TRUE)`.

If you do not want automatic event enabling and disabling, then when creating the ChromoteSession object, use `ChromoteSession$new(auto_events = FALSE)`.