…nAction
https://bugs.webkit.org/show_bug.cgi?id=267827
Reviewed by Abrar Rahman Protyasha.
WebKit has a long history with C++ and asynchrony. Deciding whether to proceed with
a navigation has always had the ability to be done asynchronously. Before C++11, we
made our own object that contained state and context for a call to indicate continuation.
With https://commits.webkit.org/193766@main we finished the transition from this object,
WebCore::PolicyCallback, to C++ lambdas.
Since then, a large and growing amount of our code has developed the ability to do things
asynchronously using WTF::CompletionHandler, a std::function-like object that contains
state and context to use when continuing. Also since then, C++ has added coroutine support
in C++20, including the co_await keyword. This has the potential to allow us to more elegantly
write code that does many things asynchronously.
WebPageProxy::decidePolicyForNavigationAction has a growing amount of complexity, with
deeply nested lambdas and many functions calling another function to continue the logic,
trying to break up the logic. With site isolation, I've needed to add many things to this
already complex area of the code, and more are needed still. I've had difficulty passing
parameters from one end of the flow to the other, through the many nested lambdas. This
has led me to do introduce things like ProvisionalPageProxy's needsCookieAccessAddedInNetworkProcess,
where I set a bool early in the flow and query the bool much later in the flow. This needs
a better solution.
In order to begin using C++ coroutines, we need a way to get into a coroutine from a function
with a CompletionHandler parameter, and we also need a way to get from a coroutine to a function
with a CompletionHandler parameter and await its result. For these two operations, I introduce
CoroutineCaller and AwaitableTaskWithCompletionHandler. Task is the object that an asynchronous
coroutine returns. Lazy<T> is what a coroutine returns for its resulting T to be awaitable,
analogous to a CompletionHandler<void(T)> which is called with the resulting T.
These primitives are used to make WebPageProxy::decidePolicyForNavigationAction an asynchronous
coroutine. The introduction of this new technology in such a small scope makes it look like
most of the code is just the CoroutineCaller/AwaitableTaskWithCompletionHandler borders to call
to and from existing code, but as coroutine adoption increases we will see simpler and simpler
code, where we can easily and elegantly add new steps in the logic flow by just awaiting another
asynchronous step or calling a synchronous step directly.
* Source/WebKit/Platform/CoroutineUtilities.h: Added.
(WebKit::CoroutineHandle::CoroutineHandle):
(WebKit::CoroutineHandle::operator=):
(WebKit::CoroutineHandle::~CoroutineHandle):
(WebKit::CoroutineHandle::handle const):
(WebKit::Lazy::PromiseBase::initial_suspend):
(WebKit::Lazy::PromiseBase::unhandled_exception):
(WebKit::Lazy::PromiseBase::setHandle):
(WebKit::Lazy::PromiseBase::handle):
(WebKit::Lazy::Promise<void>::get_return_object):
(WebKit::Lazy::Promise<void>::return_void):
(WebKit::Lazy::Promise<void>::result):
(WebKit::Lazy::Awaitable::Awaitable):
(WebKit::Lazy::Awaitable::await_ready const):
(WebKit::Lazy::Awaitable::await_suspend):
(WebKit::Lazy::Awaitable::await_resume):
(WebKit::Lazy::Lazy):
(WebKit::Lazy::operator co_await const):
(WebKit::Task::promise_type::get_return_object):
(WebKit::Task::promise_type::initial_suspend):
(WebKit::Task::promise_type::unhandled_exception):
(WebKit::Task::promise_type::return_void):
(WebKit::CoroutineCaller::setCoroutine):
(WebKit::callCoroutine):
(WebKit::AwaitableTaskWithCompletionHandler::AwaitableTaskWithCompletionHandler):
(WebKit::AwaitableTaskWithCompletionHandler::await_ready):
(WebKit::AwaitableTaskWithCompletionHandler::await_suspend):
(WebKit::AwaitableTaskWithCompletionHandler::await_resume):
* Source/WebKit/Platform/IPC/Connection.h:
* Source/WebKit/UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::decidePolicyForNavigationAction):
(WebKit::WebPageProxy::awaitableDecidePolicyForNavigationAction):
(WebKit::WebPageProxy::continueDecidePolicyForNavigationAction):
* Source/WebKit/UIProcess/WebPageProxy.h:
* Source/WebKit/WebKit.xcodeproj/project.pbxproj:
Canonical link: https://commits.webkit.org/278995@main