Bug Summary

File:Source/WebKit/UIProcess/WebFrameProxy.cpp
Warning:line 548, column 13
Call argument for 'this' parameter is uncounted and unsafe

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple arm64-apple-macosx15.5.0 -Os -Wundef-prefix=TARGET_OS_ -Werror=undef-prefix -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name UnifiedSource86.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=osx -analyzer-checker=security.insecureAPI.decodeValueOfObjCType -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=non-leaf -ffp-contract=on -fno-rounding-math -target-sdk-version=15.5 -fcompatibility-qualified-id-block-type-checking -fvisibility-inlines-hidden-static-local-var -fno-modulemap-allow-subdirectory-search -fdefine-target-os-macros -enable-tlsdesc -target-cpu apple-m1 -target-feature +v8.4a -target-feature +aes -target-feature +altnzcv -target-feature +ccdp -target-feature +ccpp -target-feature +complxnum -target-feature +crc -target-feature +dotprod -target-feature +flagm -target-feature +fp-armv8 -target-feature +fp16fml -target-feature +fptoint -target-feature +fullfp16 -target-feature +jsconv -target-feature +lse -target-feature +neon -target-feature +pauth -target-feature +perfmon -target-feature +predres -target-feature +ras -target-feature +rcpc -target-feature +rdm -target-feature +sb -target-feature +sha2 -target-feature +sha3 -target-feature +specrestrict -target-feature +ssbs -target-abi darwinpcs -dwarf-ext-refs -fmodule-format=obj -debug-info-kind=standalone -dwarf-version=5 -debugger-tuning=lldb -fdebug-compilation-dir=/Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/Source/WebKit -target-linker-version 1167.5 -fcoverage-compilation-dir=/Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/Source/WebKit -resource-dir /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/llvm-project/build/lib/clang/21 -dependency-file /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/scan-build-output/StaticAnalyzer/WebKit/WebKit/normal/arm64/UnifiedSource86.d -skip-unused-modulemap-deps -MT dependencies -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk -iquote /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebKit.build/Release/WebKit.build/WebKit-generated-files.hmap -iquote /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebKit.build/Release/WebKit.build/WebKit-project-headers.hmap -isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/local/include -iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/System/Library/PrivateFrameworks -iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/System/Library/PrivateFrameworks -isystem /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitLibraries/SDKs/macosx15.0-additions.sdk/usr/local/include -include-pch /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/PrecompiledHeaders/SharedPrecompiledHeaders/5548047481594725741/WebKit2Prefix.h.gch -D _LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE -D CLANG_WEBKIT_BRANCH=1 -D NDEBUG -D HAVE_CORE_PREDICTION -D ENABLE_LOWER_FORMATREADERBUNDLE_CODESIGNING_REQUIREMENTS -D WEBKIT_BUNDLE_VERSION="625.1.4+" -D FRAMEWORK_NAME=WebKit -D __clang_analyzer__ -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebKit.build/Release/WebKit.build/WebKit-own-target-headers.hmap -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebKit.build/Release/WebKit.build/WebKit-all-target-headers.hmap -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/include -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/usr/local/include -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/WebCore.framework/Versions/A/PrivateHeaders/ForwardingHeaders -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/DerivedSources/WebKit -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/usr/local/include/pal/graphics/WebGPU -I /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/local/include/pal/graphics/WebGPU -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/usr/local/include/WebKitAdditions -I /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/local/include/WebKitAdditions -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/usr/local/include/webrtc -I /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/local/include/webrtc -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/usr/local/include/webm -I /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/local/include/webm -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/Source/WebKit -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebKit.build/Release/WebKit.build/DerivedSources-normal/arm64 -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebKit.build/Release/WebKit.build/DerivedSources/arm64 -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebKit.build/Release/WebKit.build/DerivedSources -F/Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release -F/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/System/Library/Frameworks/WebKit.framework/Versions/A/Frameworks -D __STDC_WANT_LIB_EXT1__=1 -I/usr/local/include -stdlib=libc++ -internal-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/include/c++/v1 -internal-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/local/include -internal-isystem /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/llvm-project/build/lib/clang/21/include -internal-externc-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/include -internal-iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/System/Library/Frameworks -internal-iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/System/Library/SubFrameworks -internal-iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/Library/Frameworks -Wno-trigraphs -Werror -Wno-missing-field-initializers -Wmissing-prototypes -Wunreachable-code -Wnon-virtual-dtor -Wno-overloaded-virtual -Wno-exit-time-destructors -Wno-missing-braces -Wparentheses -Wswitch -Wunused-function -Wno-unused-label -Wno-unused-parameter -Wunused-variable -Wunused-value -Wempty-body -Wuninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wconstant-conversion -Wint-conversion -Wbool-conversion -Wenum-conversion -Wno-float-conversion -Wnon-literal-null-conversion -Wobjc-literal-conversion -Wsign-compare -Wno-shorten-64-to-32 -Wnewline-eof -Wno-c++11-extensions -Wno-implicit-fallthrough -Wdeprecated-declarations -Winvalid-offsetof -Wno-sign-conversion -Winfinite-recursion -Wmove -Wcomma -Wblock-capture-autoreleasing -Wstrict-prototypes -Wrange-loop-analysis -Wno-semicolon-before-method-body -Wall -Wc99-designator -Wconditional-uninitialized -Wextra -Wdeprecated-enum-enum-conversion -Wdeprecated-enum-float-conversion -Wenum-float-conversion -Wfinal-dtor-non-final-class -Wformat=2 -Wmisleading-indentation -Wpointer-to-int-cast -Wreorder-init-list -Wundef -Wunused-but-set-variable -Wvla -Werror=unguarded-availability -Wno-elaborated-enum-base -Wno-unused-parameter -Wcast-qual -Wchar-subscripts -Wextra-tokens -Winit-self -Wmissing-noreturn -Wpacked -Wpointer-arith -Wredundant-decls -Wwrite-strings -Wexit-time-destructors -Wglobal-constructors -Wtautological-compare -Wimplicit-fallthrough -Wvla -Wliteral-conversion -Wthread-safety -Wno-profile-instr-out-of-date -Wno-profile-instr-unprofiled -Wunsafe-buffer-usage -Wno-missing-field-initializers -Wno-nullability-completeness -std=c++2b -fdeprecated-macro -ferror-limit 19 -fmacro-backtrace-limit=0 -fvisibility=hidden -fvisibility-inlines-hidden -stack-protector 1 -fblocks -fencode-extended-block-signature -fno-rtti -fregister-global-dtors-with-atexit -fgnuc-version=4.2.1 -fno-cxx-modules -fno-implicit-modules -fskip-odr-check-in-gmf -fpascal-strings -fmax-type-align=16 -fdiagnostics-show-note-include-stack -vectorize-loops -vectorize-slp -fsafe-buffer-usage-suggestions -analyzer-output=html -analyzer-config report-in-main-source-file=true -analyzer-config nullability:NoDiagnoseCallsToSystemHeaders=true -analyzer-checker optin.osx.cocoa.localizability.NonLocalizedStringChecker -analyzer-checker security.insecureAPI.UncheckedReturn -analyzer-checker security.insecureAPI.getpw -analyzer-checker security.insecureAPI.gets -analyzer-checker security.insecureAPI.mkstemp -analyzer-checker security.insecureAPI.mktemp -analyzer-disable-checker security.insecureAPI.rand -analyzer-disable-checker security.insecureAPI.strcpy -analyzer-checker security.insecureAPI.vfork -analyzer-disable-checker alpha,apiModeling,core,cplusplus,deadcode,debug,fuchsia,nullability,optin,osx,security,unix,webkit -analyzer-checker alpha.webkit.ForwardDeclChecker,alpha.webkit.MemoryUnsafeCastChecker,alpha.webkit.NoUncheckedPtrMemberChecker,alpha.webkit.NoUnretainedMemberChecker,alpha.webkit.RetainPtrCtorAdoptChecker,alpha.webkit.UncheckedCallArgsChecker,alpha.webkit.UncheckedLocalVarsChecker,alpha.webkit.UncountedCallArgsChecker,alpha.webkit.UncountedLocalVarsChecker,alpha.webkit.UnretainedCallArgsChecker,alpha.webkit.UnretainedLambdaCapturesChecker,alpha.webkit.UnretainedLocalVarsChecker,webkit.NoUncountedMemberChecker,webkit.RefCntblBaseVirtualDtor,webkit.UncountedLambdaCapturesChecker -analyzer-config max-nodes=10000000 -analyzer-config verbose-report-filename=true -fdwarf2-cfi-asm -o /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/scan-build-output/StaticAnalyzer/WebKit/WebKit/normal/arm64/UnifiedSource86.plist -x c++ /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/DerivedSources/WebKit/unified-sources/UnifiedSource86.cpp
1/*
2 * Copyright (C) 2010-2025 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "WebFrameProxy.h"
28
29#include "APINavigation.h"
30#include "APIUIClient.h"
31#include "BrowsingContextGroup.h"
32#include "Connection.h"
33#include "DrawingAreaMessages.h"
34#include "DrawingAreaProxy.h"
35#include "FrameProcess.h"
36#include "FrameTreeCreationParameters.h"
37#include "FrameTreeNodeData.h"
38#include "JSHandleInfo.h"
39#include "LoadedWebArchive.h"
40#include "MessageSenderInlines.h"
41#include "NetworkProcessMessages.h"
42#include "ProvisionalFrameCreationParameters.h"
43#include "ProvisionalFrameProxy.h"
44#include "ProvisionalPageProxy.h"
45#include "RemotePageProxy.h"
46#include "WebBackForwardListFrameItem.h"
47#include "WebFrameInspectorTarget.h"
48#include "WebFrameMessages.h"
49#include "WebFramePolicyListenerProxy.h"
50#include "WebNavigationState.h"
51#include "WebPageInspectorController.h"
52#include "WebPageMessages.h"
53#include "WebPageProxy.h"
54#include "WebPageProxyMessages.h"
55#include "WebPasteboardProxy.h"
56#include "WebProcessMessages.h"
57#include "WebProcessPool.h"
58#include "WebsiteDataStore.h"
59#include "WebsitePoliciesData.h"
60#include <WebCore/FocusController.h>
61#include <WebCore/FocusControllerTypes.h>
62#include <WebCore/FocusEventData.h>
63#include <WebCore/FrameTreeSyncData.h>
64#include <WebCore/Image.h>
65#include <WebCore/MIMETypeRegistry.h>
66#include <WebCore/NavigationScheduler.h>
67#include <WebCore/RemoteFrameLayoutInfo.h>
68#include <WebCore/ShareableBitmapHandle.h>
69#include <WebCore/WebKitJSHandle.h>
70#include <stdio.h>
71#include <wtf/CallbackAggregator.h>
72#include <wtf/CheckedPtr.h>
73#include <wtf/RunLoop.h>
74#include <wtf/WeakRef.h>
75#include <wtf/text/WTFString.h>
76
77#if ENABLE(WEBDRIVER_BIDI)(defined 1 && 1)
78#include "WebAutomationSession.h"
79#endif
80
81#if ENABLE(APPLE_PAY)(defined 1 && 1)
82#include <WebCore/PaymentSession.h>
83#endif
84
85#if HAVE(WEBCONTENTRESTRICTIONS)(defined HAVE_WEBCONTENTRESTRICTIONS && HAVE_WEBCONTENTRESTRICTIONS
)
86#include <WebCore/ParentalControlsURLFilterParameters.h>
87#endif
88
89#define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, process().connection())do { if (!(assertion)) [[unlikely]] { os_fault_with_payload(31
, 0, nullptr, 0, makeString("/Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/Source/WebKit/UIProcess/WebFrameProxy.cpp"
" " "89" ": Invalid message dispatched "_s, unsafeSpan(__PRETTY_FUNCTION__
)).utf8().data(), 0); IPC::markCurrentlyDispatchedMessageAsInvalid
(process().connection(), "Message check failed: " "assertion"_s
); if (IPC::Connection::shouldCrashOnMessageCheckFailure()) {
do { __asm__ volatile ("brk #0xc471"); __builtin_unreachable
(); } while (0); } { (void)0; } return; } } while (0)
90
91namespace WebKit {
92using namespace WebCore;
93
94class WebPageProxy;
95
96static HashMap<FrameIdentifier, WeakRef<WebFrameProxy>>& allFrames()
97{
98 ASSERT(RunLoop::isMain())((void)0);
99 static NeverDestroyed<HashMap<FrameIdentifier, WeakRef<WebFrameProxy>>> map;
100 return map.get();
101}
102
103WebFrameProxy* WebFrameProxy::webFrame(std::optional<FrameIdentifier> identifier)
104{
105 if (!identifier || !std::remove_reference_t<decltype(allFrames())>::isValidKey(*identifier))
106 return nullptr;
107 return allFrames().get(*identifier);
108}
109
110bool WebFrameProxy::canCreateFrame(FrameIdentifier frameID)
111{
112 return std::remove_reference_t<decltype(allFrames())>::isValidKey(frameID)
113 && !allFrames().contains(frameID);
114}
115
116WebFrameProxy::WebFrameProxy(WebPageProxy& page, FrameProcess& process, FrameIdentifier frameID, SandboxFlags effectiveSandboxFlags, ReferrerPolicy effectiveReferrerPolicy, WebCore::ScrollbarMode scrollingMode, WebFrameProxy* opener, IsMainFrame isMainFrame)
117 : m_page(page)
118 , m_frameProcess(process)
119 , m_opener(opener)
120 , m_frameLoadState(isMainFrame)
121 , m_frameID(frameID)
122 , m_layerHostingContextIdentifier(LayerHostingContextIdentifier::generate())
123 , m_effectiveSandboxFlags(effectiveSandboxFlags)
124 , m_effectiveReferrerPolicy(effectiveReferrerPolicy)
125 , m_scrollingMode(scrollingMode)
126{
127 ASSERT(!allFrames().contains(frameID))((void)0);
128 allFrames().set(frameID, *this);
129 WebProcessPool::statistics().wkFrameCount++;
130
131 page.inspectorController().createWebFrameInspectorTarget(*this, WebFrameInspectorTarget::toTargetID(frameID));
132
133 m_frameProcess->addFrame(*this);
134}
135
136WebFrameProxy::~WebFrameProxy()
137{
138 if (RefPtr page = m_page.get())
139 page->inspectorController().destroyInspectorTarget(WebFrameInspectorTarget::toTargetID(frameID()));
140
141 WebProcessPool::statistics().wkFrameCount--;
142#if PLATFORM(GTK)(defined WTF_PLATFORM_GTK && WTF_PLATFORM_GTK)
143 WebPasteboardProxy::singleton().didDestroyFrame(this);
144#endif
145
146 if (m_navigateCallback)
147 m_navigateCallback({ }, { });
148
149 ASSERT(allFrames().get(m_frameID) == this)((void)0);
150 allFrames().remove(m_frameID);
151
152 m_frameProcess->removeFrame(*this);
153}
154
155template<typename M, typename C> void WebFrameProxy::sendWithAsyncReply(M&& message, C&& completionHandler)
156{
157 // Use AuxiliaryProcessProxy::sendMessage to handle process crashes and launches more gracefully.
158 protect(process())->sendWithAsyncReply(std::forward<M>(message), std::forward<C>(completionHandler), m_frameID);
159}
160
161template<typename M> void WebFrameProxy::send(M&& message)
162{
163 // Use AuxiliaryProcessProxy::sendMessage to handle process crashes and launches more gracefully.
164 protect(process())->send(std::forward<M>(message), m_frameID);
165}
166
167WebPageProxy* WebFrameProxy::page() const
168{
169 return m_page.get();
170}
171
172RefPtr<ProvisionalFrameProxy> WebFrameProxy::takeProvisionalFrame()
173{
174 return std::exchange(m_provisionalFrame, nullptr);
175}
176
177WebProcessProxy& WebFrameProxy::provisionalLoadProcess()
178{
179 if (RefPtr provisionalFrame = m_provisionalFrame)
180 return provisionalFrame->process();
181 if (isMainFrame()) {
182 if (WeakPtr provisionalPage = m_page ? m_page->provisionalPageProxy() : nullptr)
183 return provisionalPage->process();
184 }
185 return process();
186}
187
188void WebFrameProxy::webProcessWillShutDown()
189{
190 for (auto& childFrame : std::exchange(m_childFrames, { }))
191 childFrame->webProcessWillShutDown();
192
193 if (RefPtr page = m_page.get())
194 page->inspectorController().destroyInspectorTarget(WebFrameInspectorTarget::toTargetID(frameID()));
195
196 m_page = nullptr;
197
198 if (RefPtr activeListener = m_activeListener) {
199 activeListener->ignore();
200 m_activeListener = nullptr;
201 }
202
203 if (m_navigateCallback)
204 m_navigateCallback({ }, { });
205}
206
207WebProcessProxy& WebFrameProxy::process() const
208{
209 return m_frameProcess->process();
210}
211
212ProcessID WebFrameProxy::processID() const
213{
214 return process().processID();
215}
216
217std::optional<PageIdentifier> WebFrameProxy::pageIdentifier() const
218{
219 if (!m_page)
220 return { };
221 return m_page->webPageIDInMainFrameProcess();
222}
223
224void WebFrameProxy::navigateServiceWorkerClient(WebCore::ScriptExecutionContextIdentifier documentIdentifier, const URL& url, CompletionHandler<void(std::optional<PageIdentifier>, std::optional<FrameIdentifier>)>&& callback)
225{
226 if (!m_page) {
227 callback({ }, { });
228 return;
229 }
230
231 protect(page())->sendWithAsyncReplyToProcessContainingFrame(frameID(), Messages::WebPage::NavigateServiceWorkerClient { documentIdentifier, url }, CompletionHandler<void(WebCore::ScheduleLocationChangeResult)> { [this, protectedThis = Ref { *this }, callback = WTF::move(callback)](auto result) mutable {
232 switch (result) {
233 case WebCore::ScheduleLocationChangeResult::Stopped:
234 callback({ }, { });
235 return;
236 case WebCore::ScheduleLocationChangeResult::Completed:
237 callback(pageIdentifier(), frameID());
238 return;
239 case WebCore::ScheduleLocationChangeResult::Started:
240 if (m_navigateCallback)
241 m_navigateCallback({ }, { });
242
243 m_navigateCallback = WTF::move(callback);
244 return;
245 }
246 } });
247}
248
249void WebFrameProxy::bindAccessibilityFrameWithData(std::span<const uint8_t> data)
250{
251 if (RefPtr page = m_page.get())
252 page->sendToProcessContainingFrame(m_frameID, Messages::WebProcess::BindAccessibilityFrameWithData(m_frameID, data));
253}
254
255void WebFrameProxy::loadURL(const URL& url, const String& referrer)
256{
257 if (RefPtr page = m_page.get())
258 page->sendToProcessContainingFrame(m_frameID, Messages::WebPage::LoadURLInFrame(url, referrer, m_frameID));
259}
260
261void WebFrameProxy::loadData(std::span<const uint8_t> data, const String& type, const String& encodingName, const URL& baseURL)
262{
263 ASSERT(!isMainFrame())((void)0);
264 if (RefPtr page = m_page.get()) {
265 if (baseURL.protocolIsFile())
266 protect(process())->addPreviouslyApprovedFileURL(baseURL);
267 page->sendToProcessContainingFrame(m_frameID, Messages::WebPage::LoadDataInFrame(data, type, encodingName, baseURL, m_frameID));
268 }
269}
270
271bool WebFrameProxy::canProvideSource() const
272{
273 return isDisplayingMarkupDocument();
274}
275
276bool WebFrameProxy::isDisplayingStandaloneImageDocument() const
277{
278 return Image::supportsType(m_MIMEType);
279}
280
281bool WebFrameProxy::isDisplayingStandaloneMediaDocument() const
282{
283 return MIMETypeRegistry::isSupportedMediaMIMEType(m_MIMEType);
284}
285
286bool WebFrameProxy::isDisplayingMarkupDocument() const
287{
288 // FIXME: This should be a call to a single MIMETypeRegistry function; adding a new one if needed.
289 // FIXME: This is doing case sensitive comparisons on MIME types, should be using ASCII case insensitive instead.
290 return m_MIMEType == "text/html"_s || m_MIMEType == "image/svg+xml"_s || m_MIMEType == "application/x-webarchive"_s || MIMETypeRegistry::isXMLMIMEType(m_MIMEType);
291}
292
293bool WebFrameProxy::isDisplayingPDFDocument() const
294{
295 return MIMETypeRegistry::isPDFMIMEType(m_MIMEType);
296}
297
298void WebFrameProxy::didStartProvisionalLoad(URL&& url)
299{
300 m_frameLoadState.didStartProvisionalLoad(WTF::move(url));
301}
302
303void WebFrameProxy::didExplicitOpen(URL&& url, String&& mimeType)
304{
305 m_MIMEType = WTF::move(mimeType);
306 m_frameLoadState.didExplicitOpen(WTF::move(url));
307}
308
309void WebFrameProxy::didReceiveServerRedirectForProvisionalLoad(URL&& url)
310{
311 m_frameLoadState.didReceiveServerRedirectForProvisionalLoad(WTF::move(url));
312}
313
314void WebFrameProxy::didFailProvisionalLoad()
315{
316 m_frameLoadState.didFailProvisionalLoad();
317
318 if (m_navigateCallback)
319 m_navigateCallback({ }, { });
320}
321
322void WebFrameProxy::didCommitLoad(const String& contentType, const WebCore::CertificateInfo& certificateInfo, bool containsPluginDocument, DocumentSecurityPolicy&& documentSecurityPolicy)
323{
324 m_frameLoadState.didCommitLoad();
325
326 m_title = String();
327 m_MIMEType = contentType;
328 m_certificateInfo = certificateInfo;
329 m_containsPluginDocument = containsPluginDocument;
330 m_documentSecurityPolicy = WTF::move(documentSecurityPolicy);
331
332 RefPtr webPage = page();
333 if (webPage && protect(webPage->preferences())->siteIsolationEnabled())
334 broadcastFrameTreeSyncData(calculateFrameTreeSyncData());
335}
336
337void WebFrameProxy::didFinishLoad()
338{
339 m_frameLoadState.didFinishLoad();
340
341 if (m_navigateCallback)
342 m_navigateCallback(pageIdentifier(), frameID());
343}
344
345void WebFrameProxy::didFailLoad()
346{
347 m_frameLoadState.didFailLoad();
348
349 if (m_navigateCallback)
350 m_navigateCallback({ }, { });
351}
352
353void WebFrameProxy::didSameDocumentNavigation(URL&& url)
354{
355 m_frameLoadState.didSameDocumentNotification(WTF::move(url));
356}
357
358void WebFrameProxy::didChangeTitle(String&& title)
359{
360 m_title = WTF::move(title);
361}
362
363WebFramePolicyListenerProxy& WebFrameProxy::setUpPolicyListenerProxy(CompletionHandler<void(PolicyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient, std::optional<NavigatingToAppBoundDomain>, WasNavigationIntercepted)>&& completionHandler, ShouldExpectSafeBrowsingResult expectSafeBrowsingResult, ShouldExpectAppBoundDomainResult expectAppBoundDomainResult, ShouldWaitForInitialLinkDecorationFilteringData shouldWaitForInitialLinkDecorationFilteringData, ShouldWaitForSiteHasStorageCheck shouldWaitForSiteHasStorageCheck)
364{
365 if (RefPtr previousListener = m_activeListener)
366 previousListener->ignore();
367 m_activeListener = WebFramePolicyListenerProxy::create([this, protectedThis = Ref { *this }, completionHandler = WTF::move(completionHandler)] (PolicyAction action, API::WebsitePolicies* policies, ProcessSwapRequestedByClient processSwapRequestedByClient, std::optional<NavigatingToAppBoundDomain> isNavigatingToAppBoundDomain, WasNavigationIntercepted wasNavigationIntercepted) mutable {
368 if (action != PolicyAction::Use && m_navigateCallback)
369 m_navigateCallback(pageIdentifier(), frameID());
370
371 completionHandler(action, policies, processSwapRequestedByClient, isNavigatingToAppBoundDomain, wasNavigationIntercepted);
372 m_activeListener = nullptr;
373 }, expectSafeBrowsingResult, expectAppBoundDomainResult, shouldWaitForInitialLinkDecorationFilteringData, shouldWaitForSiteHasStorageCheck);
374 return *m_activeListener;
375}
376
377void WebFrameProxy::getWebArchive(CompletionHandler<void(API::Data*)>&& callback)
378{
379#if PLATFORM(COCOA)(defined 1 && 1)
380 if (RefPtr page = m_page.get()) {
381 page->getWebArchiveDataWithFrame(*this, WTF::move(callback));
382 return;
383 }
384#endif
385 callback(nullptr);
386}
387
388void WebFrameProxy::getMainResourceData(CompletionHandler<void(API::Data*)>&& callback)
389{
390 if (RefPtr page = m_page.get())
391 page->getMainResourceDataOfFrame(this, WTF::move(callback));
392 else
393 callback(nullptr);
394}
395
396void WebFrameProxy::getResourceData(API::URL* resourceURL, CompletionHandler<void(API::Data*)>&& callback)
397{
398 if (RefPtr page = m_page.get())
399 page->getResourceDataFromFrame(*this, resourceURL, WTF::move(callback));
400 else
401 callback(nullptr);
402}
403
404void WebFrameProxy::setUnreachableURL(const URL& unreachableURL)
405{
406 m_frameLoadState.setUnreachableURL(unreachableURL);
407}
408
409void WebFrameProxy::transferNavigationCallbackToFrame(WebFrameProxy& frame)
410{
411 frame.setNavigationCallback(WTF::move(m_navigateCallback));
412}
413
414void WebFrameProxy::setNavigationCallback(CompletionHandler<void(std::optional<WebCore::PageIdentifier>, std::optional<WebCore::FrameIdentifier>)>&& navigateCallback)
415{
416 ASSERT(!m_navigateCallback)((void)0);
417 m_navigateCallback = WTF::move(navigateCallback);
418}
419
420#if ENABLE(CONTENT_FILTERING)(defined 1 && 1)
421bool WebFrameProxy::didHandleContentFilterUnblockNavigation(const ResourceRequest& request)
422{
423 if (!m_contentFilterUnblockHandler.canHandleRequest(request)) {
424 m_contentFilterUnblockHandler = { };
425 return false;
426 }
427
428 RefPtr page = m_page.get();
429 ASSERT(page)((void)0);
430
431#if HAVE(WEBCONTENTRESTRICTIONS_PATH_SPI)(defined HAVE_WEBCONTENTRESTRICTIONS_PATH_SPI && HAVE_WEBCONTENTRESTRICTIONS_PATH_SPI
)
432 m_contentFilterUnblockHandler.setConfigurationPath(protect(page->websiteDataStore())->configuration().webContentRestrictionsConfigurationFile());
433#endif
434
435#if HAVE(WEBCONTENTRESTRICTIONS)(defined HAVE_WEBCONTENTRESTRICTIONS && HAVE_WEBCONTENTRESTRICTIONS
)
436 if (m_contentFilterUnblockHandler.needsNetworkProcess()) {
437 if (auto evaluatedURL = m_contentFilterUnblockHandler.evaluatedURL()) {
438 WebCore::ParentalControlsURLFilterParameters parameters {
439 *evaluatedURL,
440#if HAVE(WEBCONTENTRESTRICTIONS_PATH_SPI)(defined HAVE_WEBCONTENTRESTRICTIONS_PATH_SPI && HAVE_WEBCONTENTRESTRICTIONS_PATH_SPI
)
441 m_contentFilterUnblockHandler.configurationPath()
442#endif
443 };
444 protect(protect(page->websiteDataStore())->networkProcess())->allowEvaluatedURL(parameters, [page](bool unblocked) {
445 if (unblocked)
446 page->reload({ });
447 });
448 return true;
449 }
450 }
451#endif
452
453 m_contentFilterUnblockHandler.requestUnblockAsync([page](bool unblocked) {
454 if (unblocked)
455 page->reload({ });
456 });
457 return true;
458}
459#endif
460
461#if PLATFORM(GTK)(defined WTF_PLATFORM_GTK && WTF_PLATFORM_GTK)
462void WebFrameProxy::collapseSelection()
463{
464 if (RefPtr page = m_page.get())
465 page->sendToProcessContainingFrame(frameID(), Messages::WebPage::CollapseSelectionInFrame(m_frameID));
466}
467#endif
468
469void WebFrameProxy::disconnect()
470{
471 if (RefPtr parentFrame = m_parentFrame.get()) {
472#if ENABLE(WEBDRIVER_BIDI)(defined 1 && 1)
473 if (RefPtr page = m_page.get()) {
474 if (RefPtr session = page->activeAutomationSession())
475 session->willDestroyFrame(*this);
476 }
477#endif
478 parentFrame->m_childFrames.remove(*this);
479 }
480 m_parentFrame = nullptr;
481}
482
483bool WebFrameProxy::isConnected() const
484{
485 if (RefPtr parentFrame = m_parentFrame.get())
486 return parentFrame->m_childFrames.contains(*this);
487 return false;
488}
489
490void WebFrameProxy::didCreateSubframe(WebCore::FrameIdentifier frameID, String&& frameName, SandboxFlags effectiveSandboxFlags, ReferrerPolicy effectiveReferrerPolicy, WebCore::ScrollbarMode scrollingMode)
491{
492 // The DecidePolicyForNavigationActionSync IPC is synchronous and may therefore get processed before the DidCreateSubframe one.
493 // When this happens, decidePolicyForNavigationActionSync() calls didCreateSubframe() and we need to ignore the DidCreateSubframe
494 // IPC when it later gets processed.
495 if (WebFrameProxy::webFrame(frameID))
496 return;
497
498 RefPtr page = m_page.get();
499 MESSAGE_CHECK(page);
500 MESSAGE_CHECK(WebFrameProxy::canCreateFrame(frameID));
501
502 // This can happen with site isolation right after a frame does a cross-site navigation
503 // if the old process creates a subframe before it is told the frame has become a RemoteFrame.
504 if ((frameID.toUInt64() >> 32) != process().coreProcessIdentifier().toUInt64())
505 return;
506
507 Ref child = WebFrameProxy::create(*page, m_frameProcess, frameID, effectiveSandboxFlags, effectiveReferrerPolicy, scrollingMode, nullptr, IsMainFrame::No);
508 child->m_parentFrame = *this;
509 child->m_frameName = WTF::move(frameName);
510 page->observeAndCreateRemoteSubframesInOtherProcesses(child, child->m_frameName);
511 m_childFrames.add(child.copyRef());
512
513#if ENABLE(WEBDRIVER_BIDI)(defined 1 && 1)
514 if (RefPtr session = page->activeAutomationSession())
515 session->didCreateFrame(child);
516#endif
517}
518
519void WebFrameProxy::prepareForProvisionalLoadInProcess(WebProcessProxy& process, API::Navigation& navigation, BrowsingContextGroup& group, std::optional<SecurityOriginData> effectiveOrigin, CompletionHandler<void(WebCore::PageIdentifier)>&& completionHandler)
520{
521 if (isMainFrame())
522 return completionHandler(*webPageIDInCurrentProcess());
523
524 Site site = effectiveOrigin ? Site { *effectiveOrigin } : Site { navigation.currentRequest().url() };
525 RefPtr page = m_page.get();
526 // FIXME: Main resource (of main or subframe) request redirects should go straight from the network to UI process so we don't need to make the processes for each domain in a redirect chain. <rdar://116202119>
527 Site mainFrameSite(page->mainFrame()->url());
528 auto mainFrameDomain = mainFrameSite.domain();
529
530 // If we have an effectiveOrigin, it means we are loading about:blank which doesn't have any resources
531 // to load can commit it's provisional frame immediately
532 CommitTiming commitTiming = effectiveOrigin ? CommitTiming::Immediately : CommitTiming::WaitForLoad;
533
534 m_provisionalFrame = nullptr;
535 m_provisionalFrame = adoptRef(*new ProvisionalFrameProxy(*this, group.ensureProcessForSite(site, mainFrameSite, process, protect(page->preferences())), commitTiming));
536 protect(protect(page->websiteDataStore())->networkProcess())->addAllowedFirstPartyForCookies(process, mainFrameDomain, LoadedWebArchive::No, [pageID = page->webPageIDInProcess(process), completionHandler = WTF::move(completionHandler)] mutable {
537 completionHandler(pageID);
538 });
539}
540
541void WebFrameProxy::commitProvisionalFrame(IPC::Connection& connection, FrameIdentifier frameID, FrameInfoData&& frameInfo, ResourceRequest&& request, std::optional<WebCore::NavigationIdentifier> navigationID, String&& mimeType, bool frameHasCustomContentProvider, FrameLoadType frameLoadType, const CertificateInfo& certificateInfo, bool usedLegacyTLS, bool privateRelayed, String&& proxyName, WebCore::ResourceResponseSource source, bool containsPluginDocument, HasInsecureContent hasInsecureContent, MouseEventPolicy mouseEventPolicy, DocumentSecurityPolicy&& documentSecurityPolicy, const UserData& userData)
542{
543 ASSERT(m_page)((void)0);
544 if (m_provisionalFrame) {
545 protect(process())->send(Messages::WebPage::LoadDidCommitInAnotherProcess(frameID, m_layerHostingContextIdentifier), *webPageIDInCurrentProcess());
546
547 if (RefPtr process = std::exchange(m_provisionalFrame, nullptr)->takeFrameProcess()) {
548 m_frameProcess->removeFrame(*this);
Call argument for 'this' parameter is uncounted and unsafe
549 m_frameProcess = process.releaseNonNull();
550 m_frameProcess->addFrame(*this);
551 }
552 }
553
554 protect(page())->didCommitLoadForFrame(connection, frameID, WTF::move(frameInfo), WTF::move(request), navigationID, WTF::move(mimeType), frameHasCustomContentProvider, frameLoadType, certificateInfo, usedLegacyTLS, privateRelayed, WTF::move(proxyName), source, containsPluginDocument, hasInsecureContent, mouseEventPolicy, WTF::move(documentSecurityPolicy), userData);
555}
556
557void WebFrameProxy::getFrameInfo(CompletionHandler<void(std::optional<FrameInfoData>&&)>&& completionHandler)
558{
559 sendWithAsyncReply(Messages::WebFrame::GetFrameInfo(), WTF::move(completionHandler));
560}
561
562void WebFrameProxy::getFrameTree(CompletionHandler<void(std::optional<FrameTreeNodeData>&&)>&& completionHandler)
563{
564 class FrameInfoCallbackAggregator : public RefCounted<FrameInfoCallbackAggregator> {
565 public:
566 static Ref<FrameInfoCallbackAggregator> create(CompletionHandler<void(std::optional<FrameTreeNodeData>&&)>&& completionHandler, size_t childCount) { return adoptRef(*new FrameInfoCallbackAggregator(WTF::move(completionHandler), childCount)); }
567 void setCurrentFrameData(FrameInfoData&& data) { m_currentFrameData = WTF::move(data); }
568 void addChildFrameData(size_t index, FrameTreeNodeData&& data) { m_childFrameData[index] = WTF::move(data); }
569 ~FrameInfoCallbackAggregator()
570 {
571 // FIXME: We currently have to drop child frames that are currently not subframes of this frame
572 // (e.g. they are in the back/forward cache). They really should not be part of m_childFrames.
573 auto nonEmptyChildFrameData = WTF::compactMap(WTF::move(m_childFrameData), [](std::optional<FrameTreeNodeData>&& data) {
574 return std::forward<decltype(data)>(data);
575 });
576 m_completionHandler(m_currentFrameData ? std::optional(FrameTreeNodeData {
577 WTF::move(*m_currentFrameData),
578 WTF::move(nonEmptyChildFrameData)
579 }) : std::nullopt);
580 }
581
582 private:
583 FrameInfoCallbackAggregator(CompletionHandler<void(std::optional<FrameTreeNodeData>&&)>&& completionHandler, size_t childCount)
584 : m_completionHandler(WTF::move(completionHandler))
585 , m_childFrameData(childCount, { }) { }
586
587 CompletionHandler<void(std::optional<FrameTreeNodeData>&&)> m_completionHandler;
588 std::optional<FrameInfoData> m_currentFrameData;
589 Vector<std::optional<FrameTreeNodeData>> m_childFrameData;
590 };
591
592 Ref aggregator = FrameInfoCallbackAggregator::create(WTF::move(completionHandler), m_childFrames.size());
593 getFrameInfo([aggregator] (std::optional<FrameInfoData>&& info) {
594 if (info)
595 aggregator->setCurrentFrameData(WTF::move(*info));
596 });
597
598 RefPtr page = this->page();
599 bool isSiteIsolationEnabled = page && protect(page->preferences())->siteIsolationEnabled();
600 size_t index = 0;
601 for (Ref childFrame : m_childFrames) {
602 childFrame->getFrameTree([aggregator, index = index++, frameID = this->frameID(), isSiteIsolationEnabled] (std::optional<FrameTreeNodeData>&& data) {
603 if (!data)
604 return;
605
606 // FIXME: m_childFrames currently contains iframes that are in the back/forward cache, not currently
607 // connected to this parent frame. They should really not be part of m_childFrames anymore.
608 // FIXME: With site isolation enabled, remote frames currently don't have a parentFrameID so we temporarily
609 // ignore this check.
610 if (data->info.parentFrameID != frameID && !isSiteIsolationEnabled)
611 return;
612
613 aggregator->addChildFrameData(index, WTF::move(*data));
614 });
615 }
616}
617
618FrameTreeCreationParameters WebFrameProxy::frameTreeCreationParameters() const
619{
620 return {
621 m_frameID,
622 m_opener ? std::optional(m_opener->frameID()) : std::nullopt,
623 m_frameName,
624 calculateFrameTreeSyncData(),
625 WTF::map(m_childFrames, [] (auto& frame) {
626 return frame->frameTreeCreationParameters();
627 })
628 };
629}
630
631void WebFrameProxy::setProcess(FrameProcess& process)
632{
633 ASSERT(m_frameProcess.ptr() != &process)((void)0);
634
635 m_frameProcess->removeFrame(*this);
636 m_frameProcess = process;
637 m_frameProcess->addFrame(*this);
638}
639
640void WebFrameProxy::removeChildFrames()
641{
642 m_childFrames.clear();
643}
644
645bool WebFrameProxy::isFocused() const
646{
647 auto* webPage = page();
648 return webPage && webPage->focusedFrame() == this;
649}
650
651void WebFrameProxy::remoteProcessDidTerminate(WebProcessProxy& process, ClearFrameTreeSyncData clearFrameTreeSyncData)
652{
653 // Only clear the FrameTreeSyncData on all child processes once, when handling the main frame.
654 // No point in clearing it multiple times in a tight loop.
655 if (clearFrameTreeSyncData == ClearFrameTreeSyncData::Yes)
656 broadcastFrameTreeSyncData(FrameTreeSyncData::create());
657
658 for (Ref child : m_childFrames)
659 child->remoteProcessDidTerminate(process, ClearFrameTreeSyncData::No);
660 if (process.coreProcessIdentifier() != this->process().coreProcessIdentifier())
661 return;
662 if (m_frameLoadState.state() == FrameLoadState::State::Finished)
663 return;
664
665 notifyParentOfLoadCompletion(protect(this->process()));
666}
667
668Ref<FrameTreeSyncData> WebFrameProxy::calculateFrameTreeSyncData() const
669{
670#if ENABLE(APPLE_PAY)(defined 1 && 1)
671 std::optional<const CertificateInfo> certificateInfo = m_certificateInfo.isEmpty() ? std::nullopt : std::optional<const CertificateInfo>(m_certificateInfo);
672 bool isSecureForPaymentSession = PaymentSession::isSecureForSession(url(), WTF::move(certificateInfo));
673#else
674 bool isSecureForPaymentSession = false;
675#endif
676
677 return FrameTreeSyncData::create(isSecureForPaymentSession, securityOrigin(), m_documentSecurityPolicy, url().protocol().toString(), IntRect { }, LayoutRect { }, HashMap<FrameIdentifier, RemoteFrameLayoutInfo> { });
678}
679
680Ref<SecurityOrigin> WebFrameProxy::securityOrigin() const
681{
682 return SecurityOrigin::create(url());
683}
684
685bool WebFrameProxy::isSameOriginAs(const WebFrameProxy& frame) const
686{
687 return &frame == this || securityOrigin()->isSameOriginAs(frame.securityOrigin());
688}
689
690void WebFrameProxy::broadcastFrameTreeSyncData(Ref<FrameTreeSyncData>&& data)
691{
692 RefPtr webPage = m_page.get();
693 if (!webPage)
694 return;
695
696 RELEASE_ASSERT(protect(webPage->preferences())->siteIsolationEnabled())do { if (__builtin_expect(!!(!(protect(webPage->preferences
())->siteIsolationEnabled())), 0)) do { WTF::isIntegralOrPointerType
(); compilerFenceForCrash(); WTFCrashWithInfo(696, "/Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/Source/WebKit/UIProcess/WebFrameProxy.cpp"
, __PRETTY_FUNCTION__, 503 ); } while (false); } while (0)
;
697
698 webPage->forEachWebContentProcess([&](auto& webProcess, auto pageID) {
699 webProcess.send(Messages::WebPage::AllFrameTreeSyncDataChangedInAnotherProcess(m_frameID, data), pageID);
700 });
701}
702
703void WebFrameProxy::notifyParentOfLoadCompletion(WebProcessProxy& childFrameProcess)
704{
705 RefPtr parentFrame = this->parentFrame();
706 if (!parentFrame)
707 return;
708 auto webPageID = parentFrame->webPageIDInCurrentProcess();
709 if (!webPageID)
710 return;
711 Ref parentFrameProcess = parentFrame->process();
712 if (parentFrameProcess->coreProcessIdentifier() == childFrameProcess.coreProcessIdentifier())
713 return;
714
715 parentFrameProcess->send(Messages::WebPage::DidFinishLoadInAnotherProcess(frameID()), *webPageID);
716}
717
718std::optional<WebCore::PageIdentifier> WebFrameProxy::webPageIDInCurrentProcess()
719{
720 if (RefPtr page = m_page.get())
721 return page->webPageIDInProcess(protect(process()));
722 return std::nullopt;
723}
724
725auto WebFrameProxy::traverseNext() const -> TraversalResult
726{
727 if (RefPtr child = firstChild())
728 return { WTF::move(child), DidWrap::No };
729
730 RefPtr sibling = nextSibling();
731 if (sibling)
732 return { WTF::move(sibling), DidWrap::No };
733
734 RefPtr frame = this;
735 while (!sibling) {
736 frame = frame->parentFrame();
737 if (!frame)
738 return { };
739 sibling = frame->nextSibling();
740 }
741
742 if (frame)
743 return { WTF::move(sibling), DidWrap::No };
744
745 return { };
746}
747
748auto WebFrameProxy::traverseNext(CanWrap canWrap) const -> TraversalResult
749{
750 if (RefPtr frame = traverseNext().frame)
751 return { WTF::move(frame), DidWrap::No };
752
753 if (canWrap == CanWrap::Yes) {
754 if (RefPtr page = m_page.get())
755 return { protect(page->mainFrame()), DidWrap::Yes };
756
757 }
758 return { };
759}
760
761auto WebFrameProxy::traversePrevious(CanWrap canWrap) -> TraversalResult
762{
763 if (RefPtr previousSibling = this->previousSibling())
764 return { previousSibling->deepLastChild(), DidWrap::No };
765 if (RefPtr parent = parentFrame())
766 return { WTF::move(parent), DidWrap::No };
767
768 if (canWrap == CanWrap::Yes)
769 return { deepLastChild(), DidWrap::Yes };
770 return { };
771}
772
773RefPtr<WebFrameProxy> WebFrameProxy::deepLastChild()
774{
775 RefPtr result = this;
776 for (RefPtr last = lastChild(); last; last = last->lastChild())
777 result = last;
778 return result;
779}
780
781WebFrameProxy* WebFrameProxy::firstChild() const
782{
783 if (m_childFrames.isEmpty())
784 return nullptr;
785 return m_childFrames.first().ptr();
786}
787
788WebFrameProxy* WebFrameProxy::lastChild() const
789{
790 if (m_childFrames.isEmpty())
791 return nullptr;
792 return m_childFrames.last().ptr();
793}
794
795WebFrameProxy* WebFrameProxy::nextSibling() const
796{
797 if (!m_parentFrame)
798 return nullptr;
799
800 if (m_parentFrame->m_childFrames.last().ptr() == this)
801 return nullptr;
802
803 auto it = m_parentFrame->m_childFrames.find(this);
804 if (it == m_childFrames.end()) {
805 ASSERT_NOT_REACHED()((void)0);
806 return nullptr;
807 }
808 return (++it)->ptr();
809}
810
811WebFrameProxy* WebFrameProxy::previousSibling() const
812{
813 if (!m_parentFrame)
814 return nullptr;
815
816 if (m_parentFrame->m_childFrames.first().ptr() == this)
817 return nullptr;
818
819 auto it = m_parentFrame->m_childFrames.find(this);
820 if (it == m_childFrames.end()) {
821 ASSERT_NOT_REACHED()((void)0);
822 return nullptr;
823 }
824 return (--it)->ptr();
825}
826
827RefPtr<WebFrameProxy> WebFrameProxy::childFrame(uint64_t index) const
828{
829 RefPtr child = firstChild();
830 for (uint64_t i = 0; i < index && child; i++)
831 child = child->nextSibling();
832 return child;
833}
834
835void WebFrameProxy::updateOpener(std::optional<WebCore::FrameIdentifier> newOpener)
836{
837 RefPtr previousOpener = m_opener.get();
838 m_opener = WebFrameProxy::webFrame(newOpener);
839
840 RefPtr webPage = page();
841 if (!m_opener && webPage && !protect(webPage->preferences())->siteIsolationEnabled())
842 m_disownedOpener = previousOpener.get();
843}
844
845Ref<WebFrameProxy> WebFrameProxy::rootFrame()
846{
847 Ref rootFrame = *this;
848 while (rootFrame->m_parentFrame && rootFrame->m_parentFrame->process().coreProcessIdentifier() == process().coreProcessIdentifier())
849 rootFrame = *rootFrame->m_parentFrame;
850 return rootFrame;
851}
852
853bool WebFrameProxy::isMainFrame() const
854{
855 return m_frameLoadState.isMainFrame() == IsMainFrame::Yes;
856}
857
858void WebFrameProxy::updateScrollingMode(WebCore::ScrollbarMode scrollingMode)
859{
860 m_scrollingMode = scrollingMode;
861 if (RefPtr page = m_page.get())
862 page->sendToProcessContainingFrame(m_frameID, Messages::WebPage::UpdateFrameScrollingMode(m_frameID, scrollingMode));
863}
864
865void WebFrameProxy::setAppBadge(const WebCore::SecurityOriginData& origin, std::optional<uint64_t> badge)
866{
867 if (RefPtr webPageProxy = m_page.get())
868 webPageProxy->uiClient().updateAppBadge(*webPageProxy, origin, badge);
869}
870
871void WebFrameProxy::findFocusableElementDescendingIntoRemoteFrame(WebCore::FocusDirection direction, const WebCore::FocusEventData& focusEventData, WebCore::ShouldFocusElement shouldFocusElement, CompletionHandler<void(WebCore::FoundElementInRemoteFrame)>&& completionHandler)
872{
873 RefPtr page = m_page.get();
874 if (!page) {
875 completionHandler(WebCore::FoundElementInRemoteFrame::No);
876 return;
877 }
878
879 sendWithAsyncReply(Messages::WebFrame::FindFocusableElementDescendingIntoRemoteFrame(direction, focusEventData, shouldFocusElement), WTF::move(completionHandler));
880}
881
882std::optional<SharedPreferencesForWebProcess> WebFrameProxy::sharedPreferencesForWebProcess() const
883{
884 return process().sharedPreferencesForWebProcess();
885}
886
887void WebFrameProxy::takeSnapshotOfNode(JSHandleIdentifier identifier, CompletionHandler<void(std::optional<ShareableBitmapHandle>&&)>&& completion)
888{
889 if (!m_page)
890 return completion({ });
891
892 sendWithAsyncReply(Messages::WebFrame::TakeSnapshotOfNode(identifier), WTF::move(completion));
893}
894
895void WebFrameProxy::sendMessageToInspectorFrontend(const String& targetId, const String& message)
896{
897 if (RefPtr page = m_page.get())
898 page->inspectorController().sendMessageToInspectorFrontend(targetId, message);
899}
900
901void WebFrameProxy::requestTextExtraction(WebCore::TextExtraction::Request&& request, CompletionHandler<void(WebCore::TextExtraction::Item&&)>&& completion)
902{
903 if (RefPtr page = m_page.get(); !page || !page->hasRunningProcess())
904 return completion({ });
905
906 sendWithAsyncReply(Messages::WebFrame::RequestTextExtraction(WTF::move(request)), WTF::move(completion));
907}
908
909void WebFrameProxy::handleTextExtractionInteraction(TextExtraction::Interaction&& interaction, CompletionHandler<void(bool, String&&)>&& completion)
910{
911 if (RefPtr page = m_page.get(); !page || !page->hasRunningProcess()) {
912 ASSERT_NOT_REACHED()((void)0);
913 return completion(false, "Internal inconsistency / unexpected state. Please file a bug"_s);
914 }
915
916 sendWithAsyncReply(Messages::WebFrame::HandleTextExtractionInteraction(WTF::move(interaction)), WTF::move(completion));
917}
918
919void WebFrameProxy::takeSnapshotOfExtractedText(TextExtraction::ExtractedText&& extractedText, CompletionHandler<void(RefPtr<TextIndicator>&&)>&& completion)
920{
921 if (RefPtr page = m_page.get(); !page || !page->hasRunningProcess())
922 return completion({ });
923
924 sendWithAsyncReply(Messages::WebFrame::TakeSnapshotOfExtractedText(WTF::move(extractedText)), WTF::move(completion));
925}
926
927void WebFrameProxy::describeTextExtractionInteraction(TextExtraction::Interaction&& interaction, CompletionHandler<void(TextExtraction::InteractionDescription&&)>&& completion)
928{
929 if (RefPtr page = m_page.get(); !page || !page->hasRunningProcess()) {
930 ASSERT_NOT_REACHED()((void)0);
931 return completion({ "Internal inconsistency / unexpected state. Please file a bug"_s, { } });
932 }
933
934 sendWithAsyncReply(Messages::WebFrame::DescribeTextExtractionInteraction(WTF::move(interaction)), WTF::move(completion));
935}
936
937void WebFrameProxy::requestJSHandleForExtractedText(TextExtraction::ExtractedText&& extractedText, CompletionHandler<void(std::optional<JSHandleInfo>&&)>&& completion)
938{
939 if (RefPtr page = m_page.get(); !page || !page->hasRunningProcess())
940 return completion({ });
941
942 sendWithAsyncReply(Messages::WebFrame::RequestJSHandleForExtractedText(WTF::move(extractedText)), WTF::move(completion));
943}
944
945void WebFrameProxy::getSelectorPathsForNode(JSHandleInfo&& handle, CompletionHandler<void(Vector<HashSet<String>>&&)>&& completion)
946{
947 if (RefPtr page = m_page.get(); !page || !page->hasRunningProcess())
948 return completion({ });
949
950 sendWithAsyncReply(Messages::WebFrame::GetSelectorPathsForNode(WTF::move(handle)), WTF::move(completion));
951}
952
953void WebFrameProxy::getNodeForSelectorPaths(Vector<HashSet<String>>&& selectors, CompletionHandler<void(std::optional<JSHandleInfo>&&)>&& completion)
954{
955 if (RefPtr page = m_page.get(); !page || !page->hasRunningProcess())
956 return completion({ });
957
958 sendWithAsyncReply(Messages::WebFrame::GetNodeForSelectorPaths(WTF::move(selectors)), WTF::move(completion));
959}
960
961ProvisionalFrameCreationParameters WebFrameProxy::provisionalFrameCreationParameters(std::optional<WebCore::FrameIdentifier> frameIDBeforeProvisionalNavigation, std::optional<LayerHostingContextIdentifier> layerHostingContextIdentifier, CommitTiming commitTiming)
962{
963 return ProvisionalFrameCreationParameters {
964 frameID(),
965 frameIDBeforeProvisionalNavigation,
966 layerHostingContextIdentifier,
967 effectiveSandboxFlags(),
968 effectiveReferrerPolicy(),
969 scrollingMode(),
970 remoteFrameRect(),
971 commitTiming,
972 };
973}
974
975} // namespace WebKit
976
977#undef MESSAGE_CHECK