Volume II / CHAPTER 06
For understanding and contributing
Opening and closing a window
The page can be the same across engines. The work needed to open its window depends on the platform.
Notation conventions
Function names, types, commands, options and filenames appear in monospace, for example describe, wf test or main.cpp. Italics introduce a term at its definition. Code blocks give the fragments to enter; the preceding text states their location and prerequisites.
What changes with the window
Suppose we want to display our application in WKWebView rather than the system browser. We want to keep the pages and C++ functions already written. What we replace is the part responsible for initialising the engine and opening the page: the frontend.
frontend::FrontendType describes what that part must provide. Resources still come from the HTTP server and calls use the same bridge.
Enabling an engine in CMake makes it available to the build. Choosing to use it remains a decision in the application type. Enabling CEF therefore does not silently change the system browser selected by webfront::WebFront.
When opening returns
For an embedded window, open() generally remains active until closure. The frontend’s action then tells the owner whether to close the server. The system browser differs: the application cannot observe its tab closing in the same way.
The error path deserves as much attention as normal execution. If opening fails after server startup, the server must be stopped and joined before the exception propagates. Otherwise, the caller would receive an error while a forgotten thread continued to use its objects.
Contract tests reproduce these situations with deterministic doubles. We can therefore study operation ordering without opening a window for every test.
The right thread for the toolkit
An adapter can satisfy the C++ concept and still be wrong at runtime. Its function signatures may be correct, but that says nothing about the thread on which they are called.
AppKit, GTK and WebView2 have their own requirements. With an embedded window, application construction and show() belong on the thread appropriate to the engine, usually the main thread. Meanwhile, the server works on its context.
When adding an adapter, we must therefore follow initialisation into the toolkit and examine its return and exception paths. That is where we find constraints the compiler cannot check for us.
The page receives authority
A callback that opens a file or starts a calculation gives the page a way to request that operation. Displaying the page in our window does not remove that authority from the JavaScript it executes.
Content policy limits admitted bridge origins and embedded navigation. Archive verification tells us we received the expected bytes. Neither makes code we choose to execute harmless.
We must also be careful with shortcuts when identifying clients. A loopback address may belong to a proxy or tunnel. To understand why a connection receives a permission, we need to follow the association or authorisation mechanism for that permission through to its check.
Check your understanding