Skip to content

Commit

Permalink
Begin using C++ coroutines for WebPageProxy::decidePolicyForNavigatio…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
achristensen07 committed May 20, 2024
1 parent 32a7acf commit e90f899
Show file tree
Hide file tree
Showing 6 changed files with 235 additions and 8 deletions.
183 changes: 183 additions & 0 deletions Source/WebKit/Platform/CoroutineUtilities.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
/*
* Copyright (C) 2024 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/

#pragma once

#include <wtf/CompletionHandler.h>

#if __has_include(<coroutine>)
#include <coroutine>
#else
// FIXME: Remove this once all supported toolchains have non-experimental coroutine support.
#include <experimental/coroutine>
namespace std {
using std::experimental::coroutine_handle;
using std::experimental::suspend_never;
using std::experimental::suspend_always;
}
#endif

namespace WebKit {

template<typename PromiseType>
class CoroutineHandle {
public:
CoroutineHandle() = default;
CoroutineHandle(std::coroutine_handle<PromiseType>&& handle)
: m_handle(std::exchange(handle, nullptr)) { }
CoroutineHandle(CoroutineHandle&& other)
: m_handle(std::exchange(other.m_handle, nullptr)) { }
CoroutineHandle& operator=(CoroutineHandle&& other)
{
m_handle = std::exchange(other.m_handle, nullptr);
return *this;
}
CoroutineHandle(const CoroutineHandle&) = delete;
CoroutineHandle& operator=(const CoroutineHandle&) = delete;
~CoroutineHandle()
{
if (m_handle)
m_handle.destroy();
}

std::coroutine_handle<PromiseType> handle() const { return m_handle; }
private:
std::coroutine_handle<PromiseType> m_handle;
};

// Name based on https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1056r1.html
template<typename T>
class Lazy {
public:
class PromiseBase {
public:
struct final_awaitable {
bool await_ready() const noexcept { return false; }
template<typename Promise>
std::coroutine_handle<> await_suspend(std::coroutine_handle<Promise> coroutine) noexcept { return coroutine.promise().handle(); }
void await_resume() noexcept { }
};
std::suspend_always initial_suspend() { return { }; }
final_awaitable final_suspend() noexcept { return { }; }
template<typename Promise>
void unhandled_exception() { }
void setHandle(std::coroutine_handle<> handle) { m_handle = handle; }
std::coroutine_handle<> handle() { return m_handle; }
private:
std::coroutine_handle<> m_handle;
};
template<typename U>
class Promise final : public PromiseBase {
public:
Lazy<U> get_return_object() { return Lazy<U> { std::coroutine_handle<Promise>::from_promise(*this) }; }
void return_value(U&& value) { m_value = WTFMove(value); }
U result() && { return std::exchange(m_value, { }); }
private:
U m_value;
};
template<std::same_as<void> U>
class Promise<U> : public PromiseBase {
public:
Lazy<void> get_return_object() { return Lazy<void> { std::coroutine_handle<Promise>::from_promise(*this) }; }
void return_void() { }
void result() { }
};
using promise_type = Promise<T>;

class Awaitable {
public:
Awaitable(std::coroutine_handle<promise_type> coroutine)
: m_coroutine(coroutine) { }
bool await_ready() const { return m_coroutine.done(); }
std::coroutine_handle<> await_suspend(std::coroutine_handle<> handle)
{
m_coroutine.promise().setHandle(handle);
return m_coroutine;
}
T await_resume() { return WTFMove(this->m_coroutine.promise()).result(); }
private:
std::coroutine_handle<promise_type> m_coroutine;
};
Lazy(std::coroutine_handle<promise_type> coroutine)
: m_coroutine(std::exchange(coroutine, nullptr)) { }
Awaitable operator co_await() const { return { m_coroutine.handle() }; }
private:
CoroutineHandle<promise_type> m_coroutine;
};

struct Task {
struct promise_type {
Task get_return_object() { return { std::coroutine_handle<promise_type>::from_promise(*this) }; }
std::suspend_never initial_suspend() { return { }; }
std::suspend_always final_suspend() noexcept { return { }; }
void unhandled_exception() { }
void return_void() { }
};
std::coroutine_handle<promise_type> handle;
};

class CoroutineCaller {
WTF_MAKE_FAST_ALLOCATED;
public:
CoroutineCaller() = default;
void setCoroutine(Function<Task()>&& coroutine)
{
m_coroutine = std::exchange(coroutine, { });
m_coroutine();
}
private:
Function<Task()> m_coroutine;
};

static void callCoroutine(auto coroutine)
{
CoroutineCaller* caller = new CoroutineCaller();
caller->setCoroutine([caller, coroutine = WTFMove(coroutine)] () mutable -> Task {
co_await coroutine();
delete caller;
});
}

template<typename T>
class AwaitableTaskWithCompletionHandler {
public:
using Task = CompletionHandler<void(CompletionHandler<void(T&&)>&&)>;
AwaitableTaskWithCompletionHandler(Task&& task)
: m_task(WTFMove(task)) { }
bool await_ready() { return !!m_result; }
void await_suspend(std::coroutine_handle<> handle)
{
m_task([this, handle] (T&& result) mutable {
m_result = WTFMove(result);
handle();
});
}
T await_resume() { return *std::exchange(m_result, { }); }
private:
Task m_task;
std::optional<T> m_result;
};

}
10 changes: 10 additions & 0 deletions Source/WebKit/Platform/IPC/Connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ extern ASCIILiteral errorAsString(Error);
#define CONNECTION_STRINGIFY_MACRO(line) CONNECTION_STRINGIFY(line)

#define MESSAGE_CHECK_BASE(assertion, connection) MESSAGE_CHECK_COMPLETION_BASE(assertion, connection, (void)0)
#define MESSAGE_CHECK_BASE_COROUTINE(assertion, connection) MESSAGE_CHECK_COMPLETION_BASE_COROUTINE(assertion, connection, (void)0)

#define MESSAGE_CHECK_COMPLETION_BASE(assertion, connection, completion) do { \
if (UNLIKELY(!(assertion))) { \
Expand All @@ -125,6 +126,15 @@ extern ASCIILiteral errorAsString(Error);
} \
} while (0)

#define MESSAGE_CHECK_COMPLETION_BASE_COROUTINE(assertion, connection, completion) do { \
if (UNLIKELY(!(assertion))) { \
RELEASE_LOG_FAULT(IPC, __FILE__ " " CONNECTION_STRINGIFY_MACRO(__LINE__) ": Invalid message dispatched %s", WTF_PRETTY_FUNCTION); \
(connection)->markCurrentlyDispatchedMessageAsInvalid(); \
{ completion; } \
co_return { }; \
} \
} while (0)

#define MESSAGE_CHECK_WITH_RETURN_VALUE_BASE(assertion, connection, returnValue) do { \
if (UNLIKELY(!(assertion))) { \
RELEASE_LOG_FAULT(IPC, __FILE__ " " CONNECTION_STRINGIFY_MACRO(__LINE__) ": Invalid message dispatched %" PUBLIC_LOG_STRING, WTF_PRETTY_FUNCTION); \
Expand Down
39 changes: 31 additions & 8 deletions Source/WebKit/UIProcess/WebPageProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
#include "AuthenticatorManager.h"
#include "BrowsingContextGroup.h"
#include "Connection.h"
#include "CoroutineUtilities.h"
#include "DidFilterKnownLinkDecoration.h"
#include "DownloadManager.h"
#include "DownloadProxy.h"
Expand Down Expand Up @@ -402,6 +403,7 @@

#define MESSAGE_CHECK(process, assertion) MESSAGE_CHECK_BASE(assertion, process->connection())
#define MESSAGE_CHECK_URL(process, url) MESSAGE_CHECK_BASE(checkURLReceivedFromCurrentOrPreviousWebProcess(process, url), process->connection())
#define MESSAGE_CHECK_URL_COROUTINE(process, url) MESSAGE_CHECK_BASE_COROUTINE(checkURLReceivedFromCurrentOrPreviousWebProcess(process, url), process->connection())
#define MESSAGE_CHECK_COMPLETION(process, assertion, completion) MESSAGE_CHECK_COMPLETION_BASE(assertion, process->connection(), completion)

#define WEBPAGEPROXY_RELEASE_LOG(channel, fmt, ...) RELEASE_LOG(channel, "%p - [pageProxyID=%" PRIu64 ", webPageID=%" PRIu64 ", PID=%i] WebPageProxy::" fmt, this, internals().identifier.toUInt64(), internals().webPageID.toUInt64(), m_process->processID(), ##__VA_ARGS__)
Expand Down Expand Up @@ -6938,6 +6940,13 @@ static bool frameSandboxAllowsOpeningExternalCustomProtocols(SandboxFlags sandbo
#endif

void WebPageProxy::decidePolicyForNavigationAction(Ref<WebProcessProxy>&& process, WebFrameProxy& frame, NavigationActionData&& navigationActionData, CompletionHandler<void(PolicyDecision&&)>&& completionHandler)
{
callCoroutine([this, protectedThis = Ref { *this }, process = WTFMove(process), frame = Ref { frame }, navigationActionData = WTFMove(navigationActionData), completionHandler = WTFMove(completionHandler)] () mutable -> Lazy<void> {
completionHandler(co_await awaitableDecidePolicyForNavigationAction(WTFMove(process), frame, WTFMove(navigationActionData)));
});
}

Lazy<PolicyDecision> WebPageProxy::awaitableDecidePolicyForNavigationAction(Ref<WebProcessProxy>&& process, WebFrameProxy& frame, NavigationActionData&& navigationActionData)
{
auto frameInfo = navigationActionData.frameInfo;
auto navigationID = navigationActionData.navigationID;
Expand All @@ -6952,19 +6961,18 @@ void WebPageProxy::decidePolicyForNavigationAction(Ref<WebProcessProxy>&& proces

Ref protectedPageClient { pageClient() };

auto transaction = internals().pageLoadState.transaction();
auto transaction = std::optional(internals().pageLoadState.transaction());

bool fromAPI = request.url() == internals().pageLoadState.pendingAPIRequestURL();
if (navigationID && !fromAPI)
internals().pageLoadState.clearPendingAPIRequest(transaction);
internals().pageLoadState.clearPendingAPIRequest(*transaction);

if (!checkURLReceivedFromCurrentOrPreviousWebProcess(process, request.url())) {
WEBPAGEPROXY_RELEASE_LOG_ERROR(Process, "Ignoring request to load this main resource because it is outside the sandbox");
completionHandler(PolicyDecision { isNavigatingToAppBoundDomain() });
return;
co_return PolicyDecision { isNavigatingToAppBoundDomain() };
}

MESSAGE_CHECK_URL(process, originalRequest.url());
MESSAGE_CHECK_URL_COROUTINE(process, originalRequest.url());

RefPtr<API::Navigation> navigation;
if (navigationID)
Expand Down Expand Up @@ -7029,7 +7037,10 @@ void WebPageProxy::decidePolicyForNavigationAction(Ref<WebProcessProxy>&& proces
#if ENABLE(CONTENT_FILTERING)
if (frame.didHandleContentFilterUnblockNavigation(request)) {
WEBPAGEPROXY_RELEASE_LOG_ERROR(Process, "Ignoring request to load this main resource because it was handled by content filter");
return receivedPolicyDecision(PolicyAction::Ignore, RefPtr { m_navigationState->navigation(navigationID) }.get(), nullptr, WTFMove(navigationAction), WillContinueLoadInNewProcess::No, std::nullopt, std::nullopt, WTFMove(completionHandler));
CompletionHandler<void(CompletionHandler<void(PolicyDecision&&)>&&)> completionHandler { [this, protectedThis = Ref { *this }, navigationAction = WTFMove(navigationAction), navigationID] (CompletionHandler<void(PolicyDecision&&)>&& completionHandler) mutable {
receivedPolicyDecision(PolicyAction::Ignore, RefPtr { m_navigationState->navigation(navigationID) }.get(), nullptr, WTFMove(navigationAction), WillContinueLoadInNewProcess::No, std::nullopt, { }, WTFMove(completionHandler));
} };
co_return co_await AwaitableTaskWithCompletionHandler<PolicyDecision>(WTFMove(completionHandler));
}
#endif

Expand All @@ -7047,7 +7058,10 @@ void WebPageProxy::decidePolicyForNavigationAction(Ref<WebProcessProxy>&& proces
MessageSource::Security,
"Ignoring request to load this main resource because it has a custom protocol and comes from a sandboxed iframe"_s
};
return receivedPolicyDecision(PolicyAction::Ignore, RefPtr { m_navigationState->navigation(navigationID) }.get(), nullptr, WTFMove(navigationAction), WillContinueLoadInNewProcess::No, std::nullopt, WTFMove(errorMessage), WTFMove(completionHandler));
CompletionHandler<void(CompletionHandler<void(PolicyDecision&&)>&&)> completionHandler { [this, protectedThis = Ref { *this }, navigationAction = WTFMove(navigationAction), navigationID] (CompletionHandler<void(PolicyDecision&&)>&& completionHandler) mutable {
receivedPolicyDecision(PolicyAction::Ignore, RefPtr { m_navigationState->navigation(navigationID) }.get(), nullptr, WTFMove(navigationAction), WillContinueLoadInNewProcess::No, std::nullopt, { }, WTFMove(completionHandler));
} };
co_return co_await AwaitableTaskWithCompletionHandler<PolicyDecision>(WTFMove(completionHandler));
}
message = PolicyDecisionConsoleMessage {
MessageLevel::Warning,
Expand All @@ -7074,6 +7088,15 @@ void WebPageProxy::decidePolicyForNavigationAction(Ref<WebProcessProxy>&& proces
sendCachedLinkDecorationFilteringData();
#endif

transaction = std::nullopt;
CompletionHandler<void(CompletionHandler<void(PolicyDecision&&)>&&)> completionHandler { [this, protectedThis = Ref { *this }, navigationAction = WTFMove(navigationAction), frame = Ref { frame }, process = WTFMove(process), navigation = WTFMove(navigation), frameInfo = WTFMove(frameInfo), shouldExpectSafeBrowsingResult, shouldExpectAppBoundDomainResult, shouldWaitForInitialLinkDecorationFilteringData, request = WTFMove(request), originalRequest = WTFMove(originalRequest), originatingFrame = WTFMove(originatingFrame), message = WTFMove(message)] (CompletionHandler<void(PolicyDecision&&)>&& completionHandler) mutable {
continueDecidePolicyForNavigationAction(WTFMove(navigationAction), frame, WTFMove(process), WTFMove(navigation), WTFMove(frameInfo), shouldExpectSafeBrowsingResult, shouldExpectAppBoundDomainResult, shouldWaitForInitialLinkDecorationFilteringData, WTFMove(request), WTFMove(originalRequest), WTFMove(originatingFrame), WTFMove(message), WTFMove(completionHandler));
} };
co_return co_await AwaitableTaskWithCompletionHandler<PolicyDecision>(WTFMove(completionHandler));
}

void WebPageProxy::continueDecidePolicyForNavigationAction(Ref<API::NavigationAction>&& navigationAction, WebFrameProxy& frame, Ref<WebProcessProxy>&& process, RefPtr<API::Navigation>&& navigation, FrameInfoData&& frameInfo, ShouldExpectSafeBrowsingResult shouldExpectSafeBrowsingResult, ShouldExpectAppBoundDomainResult shouldExpectAppBoundDomainResult, ShouldWaitForInitialLinkDecorationFilteringData shouldWaitForInitialLinkDecorationFilteringData, WebCore::ResourceRequest&& request, WebCore::ResourceRequest&& originalRequest, RefPtr<WebFrameProxy>&& originatingFrame, std::optional<PolicyDecisionConsoleMessage>&& message, CompletionHandler<void(PolicyDecision&&)>&& completionHandler)
{
Ref listener = frame.setUpPolicyListenerProxy([
this,
protectedThis = Ref { *this },
Expand All @@ -7085,7 +7108,7 @@ void WebPageProxy::decidePolicyForNavigationAction(Ref<WebProcessProxy>&& proces
message = WTFMove(message),
frameInfo,
requestURL = request.url(),
protectedPageClient
protectedPageClient = Ref { pageClient() }
] (PolicyAction policyAction, API::WebsitePolicies* policies, ProcessSwapRequestedByClient processSwapRequestedByClient, RefPtr<SafeBrowsingWarning>&& safeBrowsingWarning, std::optional<NavigatingToAppBoundDomain> isAppBoundDomain, WasNavigationIntercepted wasNavigationIntercepted) mutable {
WEBPAGEPROXY_RELEASE_LOG(Loading, "decidePolicyForNavigationAction: listener called: frameID=%" PRIu64 ", isMainFrame=%d, navigationID=%" PRIu64 ", policyAction=%u, safeBrowsingWarning=%d, isAppBoundDomain=%d, wasNavigationIntercepted=%d", frame->frameID().object().toUInt64(), frame->isMainFrame(), navigation ? navigation->navigationID() : 0, (unsigned)policyAction, !!safeBrowsingWarning, !!isAppBoundDomain, wasNavigationIntercepted == WasNavigationIntercepted::Yes);

Expand Down
6 changes: 6 additions & 0 deletions Source/WebKit/UIProcess/WebPageProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,9 @@ enum class SameDocumentNavigationType : uint8_t;
enum class SelectionFlags : uint8_t;
enum class SelectionTouch : uint8_t;
enum class ShouldDelayClosingUntilFirstLayerFlush : bool;
enum class ShouldExpectAppBoundDomainResult : bool;
enum class ShouldExpectSafeBrowsingResult : bool;
enum class ShouldWaitForInitialLinkDecorationFilteringData : bool;
enum class SyntheticEditingCommandType : uint8_t;
enum class TextRecognitionUpdateResult : uint8_t;
enum class TextIndicatorStyle : uint8_t;
Expand All @@ -540,6 +543,7 @@ enum class WebTextReplacementDataState : uint8_t;
enum class WebUnifiedTextReplacementSessionDataReplacementType : uint8_t;
enum class WindowKind : uint8_t;

template<typename> class Lazy;
template<typename> class MonotonicObjectIdentifier;

using ActivityStateChangeID = uint64_t;
Expand Down Expand Up @@ -2548,6 +2552,8 @@ class WebPageProxy final : public API::ObjectImpl<API::Object::Type::Page>, publ
void didDestroyNavigation(uint64_t navigationID);

void decidePolicyForNavigationAction(Ref<WebProcessProxy>&&, WebFrameProxy&, NavigationActionData&&, CompletionHandler<void(PolicyDecision&&)>&&);
Lazy<PolicyDecision> awaitableDecidePolicyForNavigationAction(Ref<WebProcessProxy>&&, WebFrameProxy&, NavigationActionData&&);
void continueDecidePolicyForNavigationAction(Ref<API::NavigationAction>&&, WebFrameProxy&, Ref<WebProcessProxy>&&, RefPtr<API::Navigation>&&, FrameInfoData&&, ShouldExpectSafeBrowsingResult, ShouldExpectAppBoundDomainResult, ShouldWaitForInitialLinkDecorationFilteringData, WebCore::ResourceRequest&&, WebCore::ResourceRequest&& originalRequest, RefPtr<WebFrameProxy>&& originatingFrame, std::optional<PolicyDecisionConsoleMessage>&&, CompletionHandler<void(PolicyDecision&&)>&&);
void decidePolicyForNavigationActionAsync(NavigationActionData&&, CompletionHandler<void(PolicyDecision&&)>&&);
void decidePolicyForNavigationActionSync(IPC::Connection&, NavigationActionData&&, CompletionHandler<void(PolicyDecision&&)>&&);
void decidePolicyForNewWindowAction(NavigationActionData&&, const String& frameName, CompletionHandler<void(PolicyDecision&&)>&&);
Expand Down
Loading

0 comments on commit e90f899

Please sign in to comment.