RunLoops
WebKit needs to be cross-platform. So instead of using BLooper
s directly like a native application, it uses a generic abstraction: RunLoop
s. We implement RunLoop
using our native classes.
Here's a good summary of what a RunLoop
does:
The job of a RunLoop in WebKit is to receive and perform tasks. A thread with a RunLoop running will do nothing until it receives a piece of work to perform. It will then perform the work and go back to doing nothing. If multiple pieces of work arrive at the same time, RunLoop will queue the work and work on them one at a time. If this sounds like BLoopers, that's because they are! In fact, we use BLoopers to implement RunLoops on HaikuWebKit!
We implement RunLoops using BHandler
s. If the thread has an existing BLooper
, we attach the BHandler
to that. If it doesn't, we create one.
Code:
- Source/WTF/wtf/haiku/RunLoopHaiku.cpp
### What events trigger a RunLoop to run code?
WebKit always runs code in response to something. Otherwise, it does nothing.
WebKit's UIProcess shares a looper with the BApplication. Code in the UIProcess therefore is run for one of two reasons: the BApplication called it, or it received a message that it decided to answer itself.
WebProcess and NetworkProcess each get their own BApplication, and so get their own BLooper. Code only runs there in response to being launched or because of receiving a message.
Now, WebProcess would like to rerender the WebPage 60 fps. How does it do that? With a timer! After a delay, the timer (BMessageRunner) sends a message to the WebProcess, letting it render everything again.
IPC ---
We use UNIX sockets for IPC. The reason we don't use BMessenger
s is that the API isn't quite powerful enough (for details, see the thread starting [here](https://discuss.haiku-os.org/t/gsoc-2024-fixing-ipc-in-webkit-haiku-project/15190/3)). BMessenger
s can be extended to have the capabilities required, but we decided to use UNIX sockets instead because they work and require very little maintenance on our part. When UIProcess launches a process, it will also create a UNIX connection to it (see Source/WebKit/UIProcess/Launcher/ProcessLauncherHaiku.cpp ProcessLauncher::launchProcess). Finally, WebProcess and NetworkProcess establish a connection directly with each other by passing a socket pair between themselves using UIProcess as the intermediary.
Code:
- Source/WebKit/Platform/IPC/unix/ConnectionUnix.cpp
- Source/WebKit/UIProcess/Launcher/ProcessLauncherHaiku.cpp
Further reading:
- [Fixing IPC in WebKit](https://discuss.haiku-os.org/t/gsoc-2024-fixing-ipc-in-webkit-haiku-project/15190)
- [Fixing IPC](https://www.haiku-os.org/blog/zardshard/2024-08-16_gsoc_2024_porting_webkit2_final_report#4-fixing-ipc)
WebKit2's processes
As mentioned before, the primary difference between WebKit2 and WebKitLegacy is that WebKit2 splits the browser up into several processes. We use three of those processes: UIProcess, NetworkProcess, and WebProcess. We do not use GPUProcess, PluginProcess, or ModelProcess at present.
### UIProcess
UIProcess refers to the process of the browser's UI. This process will be supplied by the browser, not WebKit. WebKit will simply run code from the UIProcess in the browser's process. It is responsible for drawing the web page to the screen after it has been rendered by WebProcess and notifying WebProcess of input events. If the user navigates to a new URL, it is UIProcesses's job to tell WebProcess to do that. UIProcess is responsible for starting WebProcess and NetworkProcess if necessary and closing them down if necessary.
### WebProcess
Each web page gets their own WebProcess. The WebProcess parses the HTML, calculates the layout of the page, reads CSS, and runs JavaScript code. It takes in inputs from the UIProcess and sends the rendered web page to the UIProcess using shared memory.
### NetworkProcess
NetworkProcess, naturally, is responsible for networking.