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 NOBODY (OOPS!).

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::promise_type::final_awaitable::await_suspend):
(WebKit::Lazy::promise_type::initial_suspend):
(WebKit::Lazy::promise_type::get_return_object):
(WebKit::Lazy::promise_type::unhandled_exception):
(WebKit::Lazy::promise_type::return_value):
(WebKit::Lazy::promise_type::result):
(WebKit::Lazy::promise_type::setHandle):
(WebKit::Lazy::promise_type::handle):
(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::AwaitableTaskWithCompletionHandler::AwaitableTaskWithCompletionHandler):
(WebKit::AwaitableTaskWithCompletionHandler::await_ready):
(WebKit::AwaitableTaskWithCompletionHandler::await_suspend):
(WebKit::AwaitableTaskWithCompletionHandler::await_resume):
* Source/WebKit/UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::awaitableDecidePolicyForNavigationAction):
(WebKit::WebPageProxy::decidePolicyForNavigationAction):
(WebKit::WebPageProxy::continueDecidePolicyForNavigationAction):
* Source/WebKit/UIProcess/WebPageProxy.h:
* Source/WebKit/WebKit.xcodeproj/project.pbxproj:
  • Loading branch information
achristensen07 committed Jan 23, 2024
1 parent 05bdebf commit 09ea55c
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 9 deletions.
157 changes: 157 additions & 0 deletions Source/WebKit/Platform/CoroutineUtilities.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/*
* 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
#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 promise_type {
public:
struct final_awaitable {
bool await_ready() const noexcept { return false; }
std::coroutine_handle<> await_suspend(std::coroutine_handle<promise_type> coroutine) noexcept { return coroutine.promise().handle(); }
void await_resume() noexcept { }
};
std::suspend_always initial_suspend() { return { }; }
final_awaitable final_suspend() noexcept { return { }; }
Lazy<T> get_return_object() { return Lazy<T>{ std::coroutine_handle<promise_type>::from_promise(*this) }; }
void unhandled_exception() { }
void return_value(T&& value) { m_value = WTFMove(value); }
T result() && { return std::exchange(m_value, { }); }
void setHandle(std::coroutine_handle<> handle) { m_handle = handle; }
std::coroutine_handle<> handle() { return m_handle; }
private:
std::coroutine_handle<> m_handle;
T m_value;
};
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;
};

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 @@ -123,6 +123,7 @@ extern const char* 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 @@ -133,6 +134,15 @@ extern const char* 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
43 changes: 34 additions & 9 deletions Source/WebKit/UIProcess/WebPageProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
#include "AuthenticatorManager.h"
#include "BrowsingContextGroup.h"
#include "Connection.h"
#include "CoroutineUtilities.h"
#include "DownloadManager.h"
#include "DownloadProxy.h"
#include "DragControllerAction.h"
Expand Down Expand Up @@ -378,6 +379,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 @@ -6645,10 +6647,19 @@ static bool frameSandboxAllowsOpeningExternalCustomProtocols(SandboxFlags sandbo
}
#endif

void WebPageProxy::decidePolicyForNavigationAction(Ref<WebProcessProxy>&& process, PageIdentifier webPageID, WebFrameProxy& frame, NavigationActionPolicyParameters&& parameters, CompletionHandler<void(PolicyDecision&&)>&& completionHandler)
void WebPageProxy::decidePolicyForNavigationAction(Ref<WebProcessProxy>&& process, PageIdentifier pageID, WebFrameProxy& frame, NavigationActionPolicyParameters&& parameters, CompletionHandler<void(PolicyDecision&&)>&& completionHandler)
{
CoroutineCaller* caller = new CoroutineCaller();
caller->setCoroutine([this, protectedThis = Ref { *this }, caller, process = WTFMove(process), pageID, frame = Ref { frame }, parameters = WTFMove(parameters), completionHandler = WTFMove(completionHandler)] () mutable -> Task {
completionHandler(co_await awaitableDecidePolicyForNavigationAction(WTFMove(process), pageID, frame, WTFMove(parameters)));
delete caller;
});
}

Lazy<PolicyDecision> WebPageProxy::awaitableDecidePolicyForNavigationAction(Ref<WebProcessProxy>&& process, PageIdentifier webPageID, WebFrameProxy& frame, NavigationActionPolicyParameters&& parameters)
{
auto& frameInfo = parameters.frameInfo;
auto& navigationID = parameters.navigationID;
auto navigationID = parameters.navigationID;
auto& navigationActionData = parameters.navigationActionData;
auto& originatingFrameInfoData = parameters.originatingFrameInfoData;
auto& originatingPageID = parameters.originatingPageID;
Expand All @@ -6661,19 +6672,18 @@ void WebPageProxy::decidePolicyForNavigationAction(Ref<WebProcessProxy>&& proces

PageClientProtector protector(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 @@ -6738,7 +6748,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, 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 @@ -6750,7 +6763,10 @@ void WebPageProxy::decidePolicyForNavigationAction(Ref<WebProcessProxy>&& proces
if (!sourceFrameInfo || !m_preferences->needsSiteSpecificQuirks() || !Quirks::shouldAllowNavigationToCustomProtocolWithoutUserGesture(request.url().protocol(), sourceFrameInfo->securityOrigin())) {
WEBPAGEPROXY_RELEASE_LOG_ERROR(Process, "Ignoring request to load this main resource because it has a custom protocol and comes from a sandboxed iframe");
process->send(Messages::WebPage::AddConsoleMessage(frame.frameID(), MessageSource::Security, MessageLevel::Error, "Ignoring request to load this main resource because it has a custom protocol and comes from a sandboxed iframe"_s, std::nullopt), webPageID);
return receivedPolicyDecision(PolicyAction::Ignore, RefPtr { m_navigationState->navigation(navigationID) }.get(), nullptr, WTFMove(navigationAction), WillContinueLoadInNewProcess::No, 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));
}
process->send(Messages::WebPage::AddConsoleMessage(frame.frameID(), MessageSource::Security, MessageLevel::Warning, "In the future, requests to navigate to a URL with custom protocol from a sandboxed iframe will be ignored"_s, std::nullopt), webPageID);
}
Expand All @@ -6773,6 +6789,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)] (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(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, CompletionHandler<void(PolicyDecision&&)>&& completionHandler)
{
// FIXME: preferences().siteIsolationEnabled() here indicates there's an issue.
// See rdar://118574473 and rdar://118575766 for the kinds of things that might
// be broken with site isolation enabled.
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 @@ -493,6 +493,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 UndoOrRedo : bool;
Expand All @@ -502,6 +505,7 @@ enum class WebEventModifier : uint8_t;
enum class WebEventType : uint8_t;
enum class WindowKind : uint8_t;

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

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

void decidePolicyForNavigationAction(Ref<WebProcessProxy>&&, WebCore::PageIdentifier, WebFrameProxy&, NavigationActionPolicyParameters&&, CompletionHandler<void(PolicyDecision&&)>&&);
Lazy<PolicyDecision> awaitableDecidePolicyForNavigationAction(Ref<WebProcessProxy>&&, WebCore::PageIdentifier, WebFrameProxy&, NavigationActionPolicyParameters&&);
void continueDecidePolicyForNavigationAction(Ref<API::NavigationAction>&&, WebFrameProxy&, Ref<WebProcessProxy>&&, RefPtr<API::Navigation>&&, FrameInfoData&&, ShouldExpectSafeBrowsingResult, ShouldExpectAppBoundDomainResult, ShouldWaitForInitialLinkDecorationFilteringData, WebCore::ResourceRequest&&, WebCore::ResourceRequest&& originalRequest, RefPtr<WebFrameProxy>&& originatingFrame, CompletionHandler<void(PolicyDecision&&)>&&);
void decidePolicyForNavigationActionAsync(NavigationActionPolicyParameters&&, CompletionHandler<void(PolicyDecision&&)>&&);
void decidePolicyForNavigationActionSync(NavigationActionPolicyParameters&&, CompletionHandler<void(PolicyDecision&&)>&&);
void decidePolicyForNewWindowAction(FrameInfoData&&, NavigationActionData&&, WebCore::ResourceRequest&&, const String& frameName, CompletionHandler<void(PolicyDecision&&)>&&);
Expand Down
2 changes: 2 additions & 0 deletions Source/WebKit/WebKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7906,6 +7906,7 @@
FA39AE4E2B22DA68008F93CD /* UserData.serialization.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = UserData.serialization.in; sourceTree = "<group>"; };
FA39AE662B23972A008F93CD /* CoreIPCAuditToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CoreIPCAuditToken.h; sourceTree = "<group>"; };
FA39AE672B23972A008F93CD /* CoreIPCAuditToken.serialization.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CoreIPCAuditToken.serialization.in; sourceTree = "<group>"; };
FA3FD5FC2B5B84B200F6CF33 /* CoroutineUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CoroutineUtilities.h; sourceTree = "<group>"; };
FA651BA42AA3CBB500747576 /* NetworkTransportBidirectionalStream.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NetworkTransportBidirectionalStream.h; sourceTree = "<group>"; };
FA651BA52AA3CBB500747576 /* NetworkTransportBidirectionalStream.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkTransportBidirectionalStream.cpp; sourceTree = "<group>"; };
FA651BA62AA3CBB600747576 /* NetworkTransportReceiveStream.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkTransportReceiveStream.cpp; sourceTree = "<group>"; };
Expand Down Expand Up @@ -13910,6 +13911,7 @@
1A7E814E1152D2240003695B /* mac */,
CE1A0BCA1A48E6C60054EF74 /* spi */,
51B15A7D138439B200321AD8 /* unix */,
FA3FD5FC2B5B84B200F6CF33 /* CoroutineUtilities.h */,
ECA680D31E6904B500731D20 /* ExtraPrivateSymbolsForTAPI.h */,
ECBFC1DB1E6A4D66000300C7 /* ExtraPublicSymbolsForTAPI.h */,
51A7F2F4125BF8D4008AEB1D /* Logging.cpp */,
Expand Down

0 comments on commit 09ea55c

Please sign in to comment.