cryptpad / cryptpad/cryptpad

Browsers throttle in embedded mode when an OnlyOffice document is loaded

Open
#2,293 1 comment 1 reaction 0 assignees View on GitHub
Dominant language
JavaScript
Stars
7.9k
Forks
849
PR merge metrics
No merged PRs in 30d

Description

Hello there!

We're using Cryptpad in embedded mode in our own app (https://github.com/Scille/parsec-cloud).

To do that, we deploy a Cryptpad server and we're hosting a html file that contains an iframe and some scripting to call `CryptPadAPI()` and load a document into the frame. In our app, we're loading this html file into another iframe (so we're not on same-origin) and we communicate through postMessage/addEventListener('message'). So our app sends the document with postMessage, the iframe retrieves it with an addEventListener, and then calls CryptPadAPI to load the document.

It does work, but we've noticed that opening a file was a bit slow (seems to happen only with OnlyOffice).

Using the profile in Chrome's devtools, I've noticed a lot of down time where nothing is being done (no network, no CPU), and it seems to be happening at regular intervals, which made me think of something going on with setInterval/setTimeout.

With futher investigation, I've found out that browsers voluntarily throttle iframes that are not directly rendered, and that leads to very short timeouts and intervals being rounded up to a full second. There are multiple examples of this in `sframe-boot.js`, with a `setInterval(..., 1)` or uses of `setTimeout` to defer function calls. This throttling can be turned off (on Chrome with `--disable-background-timer-throttling --disable-renderer-backgrounding` and on Firefox in `about:config` with `dom.min_background_timeout_value` and `dom.min_background_timeout_value_without_budget_throttling`). Indeed, when it's off the problem disappears and the file loads way faster.

Here are two screenshots of the profiling, with and without the throttle turned off.

Image

_In red, the intervals when nothing is done._

Image

I've managed to produce a small example to illustrate the problem.

```
> clone https://github.com/Scille/cryptpad/tree/iframe-throttling-on-load
> npm install && npm run install:components
> ./install-onlyoffice.sh --accept-license --no-rdfind
> npm run dev
> python -m http.server 8000
> Navigate to http://localhost:8000/page.html > Open the dev tools > Choose file > .docx file > Open
```

The number of seconds it took is displayed in the console when the `onReady` event is received. Should take about 15 seconds.

Now with the throttling turned off:

```
> Chrome: Launch with `--disable-background-timer-throttling --disable-renderer-backgrounding`
> Firefox: go to `about:config` > Look for `min_background_` and set `dom.min_background_timeout_value` and `dom.min_background_timeout_value_without_budget_throttling` to 1
> Refresh http://localhost:8000/page.html and load the file again.
```

The difference should be quite obvious.

I've observed this problem only when loading a file, and I'm guessing (naively) that this could be fixed by:
- replacing the polling done by `setInterval` with an event listener in `sframe-boot.js`
- replacing the deferring of functions done by `setTimeout` with `queueMicrotask` in `sframe-boot.js`

Thank you for your time, and I'm available if you need more precisions!

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.