Bug Summary

File:Source/WebKit/WebProcess/WebPage/WebFrame.cpp
Warning:line 641, column 15
Local variable 'localFrame' is uncounted and unsafe

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple arm64-apple-macosx26.2.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 UnifiedSource145.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=26.2 -fdepfile-entry=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.2.sdk/SDKSettings.json -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 1230.1 -fcoverage-compilation-dir=/Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/Source/WebKit -resource-dir /Users/buildbot/Library/Developer/Toolchains/swift-webkit.xctoolchain/usr/lib/clang/21 -dependency-file /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/scan-build-output/StaticAnalyzer/WebKit/WebKit/normal/arm64/UnifiedSource145.d -skip-unused-modulemap-deps -MT dependencies -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.2.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/MacOSX26.2.sdk/usr/local/include -iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.2.sdk/System/Library/PrivateFrameworks -iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.2.sdk/System/Library/PrivateFrameworks -isystem /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitLibraries/SDKs/macosx26.0-additions.sdk/usr/local/include -include-pch /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/PrecompiledHeaders/SharedPrecompiledHeaders/7226384000658175008/WebKitPrefix.h.gch -D _LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE -D NDEBUG -D HAVE_CORE_PREDICTION -D ENABLE_LOWER_FORMATREADERBUNDLE_CODESIGNING_REQUIREMENTS -D WEBKIT_BUNDLE_VERSION="625.1.19+" -D ENGINEERING_BUILD=1 -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/DerivedSources/WebKit/IPC -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/MacOSX26.2.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/MacOSX26.2.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/MacOSX26.2.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/MacOSX26.2.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/MacOSX26.2.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/MacOSX26.2.sdk/usr/include/c++/v1 -internal-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.2.sdk/usr/local/include -internal-isystem /Users/buildbot/Library/Developer/Toolchains/swift-webkit.xctoolchain/usr/lib/clang/21/include -internal-externc-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.2.sdk/usr/include -internal-iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.2.sdk/System/Library/Frameworks -internal-iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.2.sdk/System/Library/SubFrameworks -internal-iframework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.2.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 -Wno-backend-plugin -Wunsafe-buffer-usage -Wno-unknown-warning-option -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 -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.NoDeleteChecker,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/UnifiedSource145.plist -x c++ /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/DerivedSources/WebKit/unified-sources/UnifiedSource145.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 "WebFrame.h"
28
29#include "APIArray.h"
30#include "ContentWorldShared.h"
31#include "DownloadManager.h"
32#include "DrawingArea.h"
33#include "FrameInfoData.h"
34#include "FrameInspectorTarget.h"
35#include "FrameTreeNodeData.h"
36#include "InjectedBundleCSSStyleDeclarationHandle.h"
37#include "InjectedBundleHitTestResult.h"
38#include "InjectedBundleNodeHandle.h"
39#include "InjectedBundleRangeHandle.h"
40#include "InjectedBundleScriptWorld.h"
41#include "JSHandleInfo.h"
42#include "Logging.h"
43#include "MessageSenderInlines.h"
44#include "NetworkConnectionToWebProcessMessages.h"
45#include "NetworkProcessConnection.h"
46#include "PluginView.h"
47#include "ProvisionalFrameCreationParameters.h"
48#include "SessionStateConversion.h"
49#include "WKAPICast.h"
50#include "WKBundleAPICast.h"
51#include "WebChromeClient.h"
52#include "WebContextMenu.h"
53#include "WebEventConversion.h"
54#include "WebEventFactory.h"
55#include "WebFrameProxyMessages.h"
56#include "WebHistoryItemClient.h"
57#include "WebImage.h"
58#include "WebInspectorBackend.h"
59#include "WebKeyboardEvent.h"
60#include "WebLocalFrameLoaderClient.h"
61#include "WebPage.h"
62#include "WebPageProxyMessages.h"
63#include "WebProcess.h"
64#include "WebRemoteFrameClient.h"
65#include "WebsitePoliciesData.h"
66#include <JavaScriptCore/APICast.h>
67#include <JavaScriptCore/JSContextRef.h>
68#include <JavaScriptCore/JSGlobalObjectInlines.h>
69#include <JavaScriptCore/JSLock.h>
70#include <JavaScriptCore/JSValueRef.h>
71#include <WebCore/AXObjectCache.h>
72#include <WebCore/ArchiveResource.h>
73#include <WebCore/CertificateInfo.h>
74#include <WebCore/Chrome.h>
75#include <WebCore/ContainerNodeInlines.h>
76#include <WebCore/ContextMenuController.h>
77#include <WebCore/DOMWrapperWorld.h>
78#include <WebCore/DocumentInlines.h>
79#include <WebCore/DocumentLoader.h>
80#include <WebCore/DocumentPage.h>
81#include <WebCore/DocumentQuirks.h>
82#include <WebCore/DocumentSecurityOrigin.h>
83#include <WebCore/DocumentView.h>
84#include <WebCore/DocumentWindow.h>
85#include <WebCore/Editor.h>
86#include <WebCore/ElementChildIteratorInlines.h>
87#include <WebCore/ElementInlines.h>
88#include <WebCore/ElementTargetingController.h>
89#include <WebCore/EventHandler.h>
90#include <WebCore/File.h>
91#include <WebCore/FocusController.h>
92#include <WebCore/FocusControllerTypes.h>
93#include <WebCore/FocusEventData.h>
94#include <WebCore/FrameDestructionObserverInlines.h>
95#include <WebCore/FrameInlines.h>
96#include <WebCore/FrameLoader.h>
97#include <WebCore/FrameSnapshotting.h>
98#include <WebCore/HTMLFormElement.h>
99#include <WebCore/HTMLFrameOwnerElement.h>
100#include <WebCore/HTMLInputElement.h>
101#include <WebCore/HTMLNames.h>
102#include <WebCore/HTMLSelectElement.h>
103#include <WebCore/HTMLTextAreaElement.h>
104#include <WebCore/HandleUserInputEventResult.h>
105#include <WebCore/ImageBuffer.h>
106#include <WebCore/JSCSSStyleDeclaration.h>
107#include <WebCore/JSElement.h>
108#include <WebCore/JSFile.h>
109#include <WebCore/JSNode.h>
110#include <WebCore/JSRange.h>
111#include <WebCore/LocalFrameInlines.h>
112#include <WebCore/LocalFrameView.h>
113#include <WebCore/MouseEventTypes.h>
114#include <WebCore/NavigationActivation.h>
115#include <WebCore/NodeDocument.h>
116#include <WebCore/OriginAccessPatterns.h>
117#include <WebCore/PluginDocument.h>
118#include <WebCore/PointerCaptureController.h>
119#include <WebCore/ReferrerPolicy.h>
120#include <WebCore/RemoteDOMWindow.h>
121#include <WebCore/RemoteFrame.h>
122#include <WebCore/RemoteFrameView.h>
123#include <WebCore/RemoteUserInputEventData.h>
124#include <WebCore/RenderLayerCompositor.h>
125#include <WebCore/RenderTreeAsText.h>
126#include <WebCore/RenderView.h>
127#include <WebCore/ScriptController.h>
128#include <WebCore/SecurityOrigin.h>
129#include <WebCore/ShareableBitmapHandle.h>
130#include <WebCore/SharedMemory.h>
131#include <WebCore/SubresourceLoader.h>
132#include <WebCore/TextExtraction.h>
133#include <WebCore/TextIterator.h>
134#include <WebCore/TextResourceDecoder.h>
135#include <WebCore/WebKitJSHandle.h>
136#include <wtf/CoroutineUtilities.h>
137#include <wtf/text/MakeString.h>
138#include <wtf/text/StringBuilder.h>
139
140#if PLATFORM(COCOA)(defined 1 && 1)
141#include <WebCore/LegacyWebArchive.h>
142#endif
143
144namespace WebKit {
145using namespace WebCore;
146
147static uint64_t NODELETE[[clang::annotate_type("webkit.nodelete")]] generateListenerID()
148{
149 static uint64_t uniqueListenerID = 1;
150 return uniqueListenerID++;
151}
152
153void WebFrame::initWithCoreMainFrame(WebPage& page, Frame& coreFrame)
154{
155 m_coreFrame = coreFrame;
156 m_coreFrame->tree().setSpecifiedName(nullAtom());
157 if (auto* localFrame = dynamicDowncast<LocalFrame>(coreFrame))
158 localFrame->init();
159}
160
161Ref<WebFrame> WebFrame::createSubframe(WebPage& page, WebFrame& parent, const AtomString& frameName, HTMLFrameOwnerElement& ownerElement)
162{
163 auto effectiveSandboxFlags = ownerElement.sandboxFlags();
164 if (RefPtr parentLocalFrame = parent.coreLocalFrame())
165 effectiveSandboxFlags.add(parentLocalFrame->effectiveSandboxFlags());
166 auto effectiveReferrerPolicy = ownerElement.referrerPolicy();
167 if (RefPtr localTopDocument = page.localTopDocument(); effectiveReferrerPolicy == ReferrerPolicy::EmptyString && localTopDocument)
168 effectiveReferrerPolicy = localTopDocument->referrerPolicy();
169
170 auto frameID = WebCore::generateFrameIdentifier();
171 auto frame = create(page, frameID);
172 ASSERT(page.corePage())((void)0);
173 auto coreFrame = LocalFrame::createSubframe(*protect(page.corePage()), [frame] (auto& localFrame, auto& frameLoader) {
174 return makeUniqueRefWithoutRefCountedCheck<WebLocalFrameLoaderClient>(localFrame, frameLoader, frame.get(), frame->makeInvalidator());
175 }, frameID, effectiveSandboxFlags, effectiveReferrerPolicy, ownerElement, WebCore::FrameTreeSyncData::create());
176 frame->m_coreFrame = coreFrame.get();
177
178 page.send(Messages::WebPageProxy::DidCreateSubframe(parent.frameID(), coreFrame->frameID(), frameName, effectiveSandboxFlags, effectiveReferrerPolicy, ownerElement.scrollingMode()));
179
180 coreFrame->tree().setSpecifiedName(frameName);
181 ASSERT(ownerElement.document().frame())((void)0);
182 coreFrame->init();
183
184 if (RefPtr backend = Ref { page }->inspector(WebPage::LazyCreationPolicy::UseExistingOnly))
185 backend->ensureInstrumentationForFrame(coreFrame.get());
186
187 return frame;
188}
189
190Ref<WebFrame> WebFrame::createRemoteSubframe(WebPage& page, WebFrame& parent, WebCore::FrameIdentifier frameID, const String& frameName, std::optional<WebCore::FrameIdentifier> openerFrameID, Ref<WebCore::FrameTreeSyncData>&& frameTreeSyncData)
191{
192 RefPtr<WebCore::Frame> opener;
193 if (openerFrameID) {
194 if (RefPtr openerWebFrame = WebProcess::singleton().webFrame(*openerFrameID))
195 opener = openerWebFrame->coreFrame();
196 }
197
198 RefPtr corePage = page.corePage();
199 RefPtr parentCoreFrame = parent.coreFrame();
200
201 auto frame = create(page, frameID);
202 RELEASE_ASSERT(corePage)do { if (__builtin_expect(!!(!(corePage)), 0)) do { WTF::isIntegralOrPointerType
(); compilerFenceForCrash(); WTFCrashWithInfo(202, "/Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/Source/WebKit/WebProcess/WebPage/WebFrame.cpp"
, __PRETTY_FUNCTION__ ); } while (false); } while (0)
;
203 RELEASE_ASSERT(parentCoreFrame)do { if (__builtin_expect(!!(!(parentCoreFrame)), 0)) do { WTF
::isIntegralOrPointerType(); compilerFenceForCrash(); WTFCrashWithInfo
(203, "/Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/Source/WebKit/WebProcess/WebPage/WebFrame.cpp"
, __PRETTY_FUNCTION__ ); } while (false); } while (0)
;
204 auto coreFrame = RemoteFrame::createSubframe(*corePage, [frame] (auto&) {
205 return makeUniqueRef<WebRemoteFrameClient>(frame.copyRef(), frame->makeInvalidator());
206 }, frameID, *parentCoreFrame, opener.get(), std::nullopt, WTF::move(frameTreeSyncData), WebCore::Frame::AddToFrameTree::Yes);
207 frame->m_coreFrame = coreFrame.get();
208 coreFrame->tree().setSpecifiedName(AtomString(frameName));
209 return frame;
210}
211
212WebFrame::WebFrame(WebPage& page, WebCore::FrameIdentifier frameID)
213 : m_page(page)
214 , m_frameID(frameID)
215{
216 ASSERT(!WebProcess::singleton().webFrame(m_frameID))((void)0);
217 WebProcess::singleton().addWebFrame(m_frameID, this);
218}
219
220WebLocalFrameLoaderClient* WebFrame::localFrameLoaderClient() const
221{
222 if (auto* localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get()))
223 return dynamicDowncast<WebLocalFrameLoaderClient>(localFrame->loader().client());
224 return nullptr;
225}
226
227WebRemoteFrameClient* WebFrame::remoteFrameClient() const
228{
229 if (auto* remoteFrame = dynamicDowncast<RemoteFrame>(m_coreFrame.get()))
230 return downcast<WebRemoteFrameClient>(&remoteFrame->client());
231 return nullptr;
232}
233
234WebFrameLoaderClient* WebFrame::frameLoaderClient() const
235{
236 if (auto* localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get()))
237 return dynamicDowncast<WebLocalFrameLoaderClient>(localFrame->loader().client());
238 if (auto* remoteFrame = dynamicDowncast<RemoteFrame>(m_coreFrame.get()))
239 return downcast<WebRemoteFrameClient>(&remoteFrame->client());
240 return nullptr;
241}
242
243WebFrame::~WebFrame()
244{
245 ASSERT(!m_coreFrame)((void)0);
246
247 ASSERT_WITH_MESSAGE(WebProcess::singleton().webFrame(m_frameID) != this, "invalidate should have removed this WebFrame before destruction")((void)0);
248}
249
250WebPage* WebFrame::page() const
251{
252 if (!m_coreFrame)
253 return nullptr;
254
255 RefPtr page = m_coreFrame->page();
256 return page ? WebPage::fromCorePage(*page) : nullptr;
257}
258
259WebFrame* WebFrame::fromCoreFrame(const Frame& frame)
260{
261 if (auto* localFrame = dynamicDowncast<LocalFrame>(frame)) {
262 auto* webLocalFrameLoaderClient = dynamicDowncast<WebLocalFrameLoaderClient>(localFrame->loader().client());
263 if (!webLocalFrameLoaderClient)
264 return nullptr;
265 return &webLocalFrameLoaderClient->webFrame();
266 }
267 if (auto* remoteFrame = dynamicDowncast<RemoteFrame>(frame)) {
268 auto& client = downcast<WebRemoteFrameClient>(remoteFrame->client());
269 return &client.webFrame();
270 }
271 return nullptr;
272}
273
274WebCore::LocalFrame* WebFrame::coreLocalFrame() const
275{
276 return dynamicDowncast<LocalFrame>(m_coreFrame.get());
277}
278
279WebCore::RemoteFrame* WebFrame::coreRemoteFrame() const
280{
281 return dynamicDowncast<RemoteFrame>(m_coreFrame.get());
282}
283
284WebCore::Frame* WebFrame::coreFrame() const
285{
286 return m_coreFrame.get();
287}
288
289Awaitable<std::optional<FrameInfoData>> WebFrame::getFrameInfo()
290{
291 co_return info(WithCertificateInfo::Yes);
292}
293
294FrameInfoData WebFrame::info(WithCertificateInfo withCertificateInfo) const
295{
296 RefPtr parent = parentFrame();
297 RefPtr coreFrame = this->coreFrame();
298 RefPtr coreLocalFrame = this->coreLocalFrame();
299 RefPtr document = coreLocalFrame ? coreLocalFrame->document() : nullptr;
300 RefPtr page = m_page.get();
301 RefPtr loadingFrame = m_provisionalFrame ? m_provisionalFrame : coreLocalFrame;
302
303 WebFrameMetrics metrics;
304 SecurityOriginData securityOriginData;
305 FrameType frameType = FrameType::Local;
306 String frameName;
307 if (coreFrame) {
308 if (RefPtr coreView = coreFrame->virtualView()) {
309 IsScrollable isScrollable = hasHorizontalScrollbar() || hasVerticalScrollbar() ? IsScrollable::Yes : IsScrollable::No;
310 IntSize contentSize { coreView->contentsWidth(), coreView->contentsHeight() };
311 auto visibleContentSize = coreView->visibleContentRectIncludingScrollbars().size();
312 auto visibleContentSizeExcludingScrollbars = coreView->visibleContentRect().size();
313 metrics = { isScrollable, contentSize, visibleContentSize, visibleContentSizeExcludingScrollbars };
314 }
315 securityOriginData = SecurityOriginData::fromFrame(*coreFrame);
316 if (coreFrame->frameType() == WebCore::Frame::FrameType::Remote)
317 frameType = FrameType::Remote;
318 frameName = coreFrame->tree().specifiedName().string();
319 }
320
321 return {
322 isMainFrame(),
323 frameType,
324 // FIXME: This should use the full request.
325 ResourceRequest(url()),
326 WTF::move(securityOriginData),
327 WTF::move(frameName),
328 frameID(),
329 page ? std::optional { page->webPageProxyIdentifier() } : std::nullopt,
330 parent ? std::optional { parent->frameID() } : std::nullopt,
331 document ? std::optional { document->identifier() } : std::nullopt,
332 withCertificateInfo == WithCertificateInfo::Yes ? certificateInfo() : CertificateInfo(),
333 getCurrentProcessID(),
334 isFocused(),
335 loadingFrame && loadingFrame->loader().errorOccurredInLoading(),
336 WTF::move(metrics)
337 };
338}
339
340FrameTreeNodeData WebFrame::frameTreeData() const
341{
342 FrameTreeNodeData data {
343 info(),
344 { }
345 };
346
347 if (!m_coreFrame) {
348 ASSERT_NOT_REACHED()((void)0);
349 return data;
350 }
351
352 data.children.reserveInitialCapacity(m_coreFrame->tree().childCount());
353
354 for (RefPtr child = m_coreFrame->tree().firstChild(); child; child = child->tree().nextSibling()) {
355 RefPtr childWebFrame = WebFrame::fromCoreFrame(*child);
356 if (!childWebFrame) {
357 ASSERT_NOT_REACHED()((void)0);
358 continue;
359 }
360 data.children.append(childWebFrame->frameTreeData());
361 }
362
363 return data;
364}
365
366void WebFrame::invalidate()
367{
368 ASSERT(!WebProcess::singleton().webFrame(m_frameID) || WebProcess::singleton().webFrame(m_frameID) == this)((void)0);
369 RefPtr page = m_page.get();
370 WebProcess::singleton().removeWebFrame(frameID(), page.get());
371 m_coreFrame = nullptr;
372}
373
374ScopeExit<Function<void()>> WebFrame::makeInvalidator()
375{
376 return makeScopeExit<Function<void()>>([protectedThis = Ref { *this }] {
377 protectedThis->invalidate();
378 });
379}
380
381uint64_t WebFrame::setUpPolicyListener(WebCore::FramePolicyFunction&& policyFunction, ForNavigationAction forNavigationAction)
382{
383 auto policyListenerID = generateListenerID();
384 m_pendingPolicyChecks.add(policyListenerID, PolicyCheck {
385 forNavigationAction,
386 WTF::move(policyFunction)
387 });
388
389 return policyListenerID;
390}
391
392void WebFrame::loadDidCommitInAnotherProcess(std::optional<WebCore::LayerHostingContextIdentifier> layerHostingContextIdentifier)
393{
394 RefPtr localFrame = coreLocalFrame();
395 if (!localFrame) {
396 ASSERT_NOT_REACHED()((void)0);
397 return;
398 }
399
400 RefPtr corePage = localFrame->page();
401 if (!corePage) {
402 ASSERT_NOT_REACHED()((void)0);
403 return;
404 }
405
406 RefPtr parent = localFrame->tree().parent();
407 RefPtr ownerElement = localFrame->ownerElement();
408
409 // loadDidCommitInAnotherProcess implies the new frame is cross-origin to the current frame.
410 // Cross-origin navigation doesn't trigger view transitions, and does not provide any activation information.
411 protect(localFrame->document())->dispatchPageswapEvent(CanTriggerCrossDocumentViewTransition::No, nullptr);
412
413 RefPtr ownerRenderer = localFrame->ownerRenderer();
414
415 auto newFrame = [&]() {
416 // Don't reuse the dying LocalFrame's sync data — its pre-swap origin would remain visible
417 // until the post-commit FrameTreeSyncDataChangedInAnotherProcess IPC arrives. Opaque is
418 // an honest placeholder that never spuriously matches the active document.
419 Ref frameTreeSyncData = FrameTreeSyncData::create();
420
421 auto invalidator = protect(localFrameLoaderClient())->takeFrameInvalidator();
422 auto clientCreator = [protectedThis = Ref { *this }, invalidator = WTF::move(invalidator)] (auto&) mutable {
423 return makeUniqueRef<WebRemoteFrameClient>(WTF::move(protectedThis), WTF::move(invalidator));
424 };
425
426 if (ownerElement)
427 ASSERT(ownerElement->document().frame() == parent.get())((void)0);
428
429 if (parent)
430 return WebCore::RemoteFrame::createSubframe(*corePage, WTF::move(clientCreator), m_frameID, *parent, nullptr, layerHostingContextIdentifier, WTF::move(frameTreeSyncData), WebCore::Frame::AddToFrameTree::No);
431
432 return WebCore::RemoteFrame::createMainFrame(*corePage, WTF::move(clientCreator), m_frameID, nullptr, WTF::move(frameTreeSyncData));
433 }();
434 m_coreFrame = newFrame.get();
435
436 if (parent)
437 parent->tree().replaceChild(*localFrame, newFrame);
438 else {
439 localFrame->loader().detachFromParent();
440 corePage->setMainFrame(newFrame.copyRef());
441 }
442
443 if (ownerElement) {
444 localFrame->disconnectOwnerElement();
445 newFrame->setOwnerElement(ownerElement);
446 }
447
448 newFrame->takeWindowProxyAndOpenerFrom(*localFrame);
449
450 newFrame->tree().setSpecifiedName(localFrame->tree().specifiedName());
451 if (ownerRenderer)
452 ownerRenderer->setWidget(newFrame->view());
453
454 if (corePage->focusController().focusedFrame() == localFrame.get())
455 corePage->focusController().setFocusedFrame(newFrame.ptr(), WebCore::BroadcastFocusedFrame::No);
456
457 if (ownerElement)
458 ownerElement->scheduleInvalidateStyleAndLayerComposition();
459}
460
461void WebFrame::createProvisionalFrame(ProvisionalFrameCreationParameters&& parameters)
462{
463 RefPtr remoteFrame = coreRemoteFrame();
464 if (!remoteFrame) {
465 ASSERT_NOT_REACHED()((void)0);
466 return;
467 }
468
469 RefPtr corePage = remoteFrame->page();
470 if (!corePage) {
471 ASSERT_NOT_REACHED()((void)0);
472 return;
473 }
474
475 RefPtr parent = remoteFrame->tree().parent();
476 auto clientCreator = [this, protectedThis = Ref { *this }] (auto& localFrame, auto& frameLoader) mutable {
477 return makeUniqueRefWithoutRefCountedCheck<WebLocalFrameLoaderClient>(localFrame, frameLoader, WTF::move(protectedThis), makeInvalidator());
478 };
479 auto localFrame = parent ? LocalFrame::createProvisionalSubframe(*corePage, WTF::move(clientCreator), m_frameID, parameters.effectiveSandboxFlags, parameters.effectiveReferrerPolicy, parameters.scrollingMode, *parent, Ref { remoteFrame->frameTreeSyncData() }) : LocalFrame::createMainFrame(*corePage, WTF::move(clientCreator), m_frameID, parameters.effectiveSandboxFlags, parameters.effectiveReferrerPolicy, nullptr, Ref { remoteFrame->frameTreeSyncData() });
480 ASSERT(!m_provisionalFrame)((void)0);
481 m_provisionalFrame = localFrame.ptr();
482 m_frameIDBeforeProvisionalNavigation = parameters.frameIDBeforeProvisionalNavigation;
483 localFrame->init();
484 if (!localFrame->isMainFrame())
485 protect(localFrame->document())->setURL(URL { aboutBlankURL() });
486
487 // If network instrumentation was enabled via WebPageCreationParameters (before
488 // this frame existed), create the FrameNetworkAgentProxy for it now.
489 if (RefPtr page = m_page.get()) {
490 if (RefPtr backend = page->inspector(WebPage::LazyCreationPolicy::UseExistingOnly))
491 backend->ensureInstrumentationForFrame(localFrame.get());
492 }
493
494 if (parameters.layerHostingContextIdentifier)
495 setLayerHostingContextIdentifier(*parameters.layerHostingContextIdentifier);
496 if (parameters.initialRect)
497 updateLocalFrameRect(localFrame, *parameters.initialRect);
498
499 if (parameters.commitTiming == CommitTiming::Immediately)
500 commitProvisionalFrame();
501}
502
503void WebFrame::destroyProvisionalFrame()
504{
505 if (RefPtr frame = std::exchange(m_provisionalFrame, nullptr)) {
506 if (auto* client = dynamicDowncast<WebLocalFrameLoaderClient>(frame->loader().client()))
507 client->takeFrameInvalidator().release();
508 frame->loader().detachFromParent();
509 frame->setView(nullptr);
510 m_frameIDBeforeProvisionalNavigation = std::nullopt;
511 }
512}
513
514void WebFrame::commitProvisionalFrame()
515{
516 RefPtr localFrame = std::exchange(m_provisionalFrame, nullptr);
517 if (!localFrame)
518 return;
519
520 RefPtr remoteFrame = coreRemoteFrame();
521 if (!remoteFrame) {
522 ASSERT_NOT_REACHED()((void)0);
523 return;
524 }
525
526 RefPtr corePage = remoteFrame->page();
527 if (!corePage) {
528 ASSERT_NOT_REACHED()((void)0);
529 return;
530 }
531
532 if (RefPtr frame = WebProcess::singleton().webFrame(std::exchange(m_frameIDBeforeProvisionalNavigation, { }))) {
533 if (RefPtr coreFrame = frame->coreFrame())
534 remoteFrame->takeWindowProxyAndOpenerFrom(*coreFrame);
535 }
536
537 RefPtr parent = remoteFrame->tree().parent();
538 RefPtr ownerElement = remoteFrame->ownerElement();
539 RefPtr ownerRenderer = remoteFrame->ownerRenderer();
540
541 if (parent)
542 parent->tree().replaceChild(*remoteFrame, *localFrame);
543 remoteFrame->disconnectOwnerElement();
544 downcast<WebRemoteFrameClient>(remoteFrame->client()).takeFrameInvalidator().release();
545
546 m_coreFrame = localFrame.get();
547 remoteFrame->setView(nullptr);
548 localFrame->tree().setSpecifiedName(remoteFrame->tree().specifiedName());
549
550 if (ownerRenderer)
551 ownerRenderer->setWidget(localFrame->view());
552
553 localFrame->setOwnerElement(ownerElement.get());
554 if (remoteFrame->isMainFrame())
555 corePage->setMainFrame(*localFrame);
556 localFrame->takeWindowProxyAndOpenerFrom(*remoteFrame);
557 if (RefPtr document = localFrame->document())
558 document->didBecomeCurrentDocumentInFrame();
559
560 if (corePage->focusController().focusedFrame() == remoteFrame.get())
561 corePage->focusController().setFocusedFrame(localFrame.get(), WebCore::BroadcastFocusedFrame::No);
562
563 if (ownerElement)
564 ownerElement->scheduleInvalidateStyleAndLayerComposition();
565}
566
567void WebFrame::removeFromTree()
568{
569 RefPtr coreFrame = m_coreFrame.get();
570 if (!coreFrame) {
571 ASSERT_NOT_REACHED()((void)0);
572 return;
573 }
574
575 RefPtr webPage = m_page.get();
576 if (!webPage) {
577 ASSERT_NOT_REACHED()((void)0);
578 return;
579 }
580
581 RefPtr corePage = webPage->corePage();
582 if (!corePage) {
583 ASSERT_NOT_REACHED()((void)0);
584 return;
585 }
586
587 if (RefPtr client = localFrameLoaderClient())
588 client->removeStorageAccess();
589
590 if (RefPtr parent = coreFrame->tree().parent())
591 parent->tree().removeChild(*coreFrame);
592 coreFrame->disconnectView();
593}
594
595void WebFrame::didFinishLoadInAnotherProcess()
596{
597 if (RefPtr coreFrame = m_coreFrame.get())
598 coreFrame->didFinishLoadInAnotherProcess();
599}
600
601void WebFrame::invalidatePolicyListeners()
602{
603 Ref protectedThis { *this };
604
605 m_policyDownloadID = { };
606
607 auto pendingPolicyChecks = std::exchange(m_pendingPolicyChecks, { });
608 for (auto& policyCheck : pendingPolicyChecks.values())
609 policyCheck.policyFunction(PolicyAction::Ignore);
610}
611
612void WebFrame::didReceivePolicyDecision(uint64_t listenerID, PolicyDecision&& policyDecision)
613{
614 if (RefPtr page = m_page.get()) {
615#if ENABLE(APP_BOUND_DOMAINS)(defined ENABLE_APP_BOUND_DOMAINS && ENABLE_APP_BOUND_DOMAINS
)
616 page->setIsNavigatingToAppBoundDomain(policyDecision.isNavigatingToAppBoundDomain, Ref { *this });
617#endif
618 if (auto& message = policyDecision.consoleMessage)
619 page->addConsoleMessage(m_frameID, message->messageSource, message->messageLevel, message->message);
620 }
621
622 if (!m_coreFrame)
623 return;
624 setIsSafeBrowsingCheckOngoing(policyDecision.isSafeBrowsingCheckOngoing);
625
626 auto policyCheck = m_pendingPolicyChecks.take(listenerID);
627 if (!policyCheck.policyFunction)
628 return;
629
630 FramePolicyFunction function = WTF::move(policyCheck.policyFunction);
631 bool forNavigationAction = policyCheck.forNavigationAction == ForNavigationAction::Yes;
632
633 if (forNavigationAction && localFrameLoaderClient() && policyDecision.websitePoliciesData) {
634 ASSERT(page())((void)0);
635 if (page())
636 page()->setAllowsContentJavaScriptFromMostRecentNavigation(policyDecision.websitePoliciesData->allowsContentJavaScript);
637 protect(localFrameLoaderClient())->applyWebsitePolicies(WTF::move(*policyDecision.websitePoliciesData));
638 }
639
640 m_policyDownloadID = policyDecision.downloadID;
641 if (auto* localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get())) {
Local variable 'localFrame' is uncounted and unsafe
642 auto& loader = localFrame->loader();
643 if (RefPtr policyDocumentLoader = loader.policyDocumentLoader()) {
644 if (policyDecision.navigationID)
645 policyDocumentLoader->setNavigationID(*policyDecision.navigationID);
646 policyDocumentLoader->setIsOriginKeyedFromUIProcess(policyDecision.isOriginKeyed);
647 } else if (RefPtr provisionalDocumentLoader = loader.provisionalDocumentLoader())
648 provisionalDocumentLoader->setIsOriginKeyedFromUIProcess(policyDecision.isOriginKeyed);
649 }
650
651 if (policyDecision.backForwardFrameState) {
652 RELEASE_LOG(Loading, "didReceivePolicyDecision: Received FrameState for child frame, URL=%" SENSITIVE_LOG_STRING, policyDecision.backForwardFrameState->urlString.utf8().data())clang diagnostic push clang diagnostic ignored "-Wunknown-warning-option"
clang diagnostic ignored "-Wunsafe-buffer-usage" clang diagnostic
ignored "-Wunsafe-buffer-usage-in-libc-call" clang diagnostic
ignored "-Wunsafe-buffer-usage-in-format-attr-call" [[clang
::suppress]] __extension__({ os_log_t _log_tmp = (WebKit2LogLoading
.osLogChannel); os_log_type_t _type_tmp = (OS_LOG_TYPE_DEFAULT
); if (os_log_type_enabled(_log_tmp, _type_tmp)) { __extension__
({ clang diagnostic push clang diagnostic ignored "-Wvla" clang
diagnostic error "-Wformat" _Static_assert(__builtin_constant_p
("didReceivePolicyDecision: Received FrameState for child frame, URL=%"
"{sensitive}" "s"), "format/label/description argument must be a string constant"
); __attribute__((section("__TEXT,__oslogstring,cstring_literals"
),internal_linkage)) static const char _os_fmt_str[] __asm("LOS_LOG66"
) = "didReceivePolicyDecision: Received FrameState for child frame, URL=%"
"{sensitive}" "s"; uint8_t _Alignas(16) __attribute__((uninitialized
)) _os_fmt_buf[__builtin_os_log_format_buffer_size("didReceivePolicyDecision: Received FrameState for child frame, URL=%"
"{sensitive}" "s", policyDecision.backForwardFrameState->
urlString.utf8().data())]; _os_log_impl(&__dso_handle, _log_tmp
, _type_tmp, _os_fmt_str, (uint8_t *)__builtin_os_log_format(
_os_fmt_buf, "didReceivePolicyDecision: Received FrameState for child frame, URL=%"
"{sensitive}" "s", policyDecision.backForwardFrameState->
urlString.utf8().data()), (uint32_t)sizeof(_os_fmt_buf)) clang
diagnostic pop ; }); } }) clang diagnostic pop
;
653 setHistoryItemForBackForwardNavigation(protect(*policyDecision.backForwardFrameState));
654 }
655
656 if (policyDecision.policyAction == PolicyAction::Use && policyDecision.sandboxExtensionHandle) {
657 if (RefPtr page = this->page()) {
658 Ref mainWebFrame = page->mainWebFrame();
659 page->sandboxExtensionTracker().beginLoad(WTF::move(*(policyDecision.sandboxExtensionHandle)));
660 }
661 }
662
663 function(policyDecision.policyAction);
664}
665
666void WebFrame::setHistoryItemForBackForwardNavigation(const FrameState& frameState)
667{
668 RefPtr page = m_page.get();
669 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
670 if (!localFrame || !page)
671 return;
672
673 // Build HistoryItem from FrameState
674 Ref historyItemClient = page->historyItemClient();
675 auto ignoreHistoryItemChangesForScope = historyItemClient->ignoreChangesForScope();
676 ASSERT(!page->corePage()->settings().useUIProcessForBackForwardItemLoading() || frameState.children.isEmpty())((void)0);
677 Ref historyItem = toHistoryItem(historyItemClient, protect(frameState));
678
679 Ref frameLoader = localFrame->loader();
680 frameLoader->setRequestedHistoryItem(historyItem);
681}
682
683void WebFrame::startDownload(const WebCore::ResourceRequest& request, const String& suggestedName, FromDownloadAttribute fromDownloadAttribute)
684{
685 if (!m_policyDownloadID) {
686 ASSERT_NOT_REACHED()((void)0);
687 return;
688 }
689 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
690 auto topOrigin = localFrame && localFrame->document() ? std::optional { protect(localFrame->document())->topOrigin().data() } : std::nullopt;
691 auto policyDownloadID = *std::exchange(m_policyDownloadID, std::nullopt);
692
693 std::optional<NavigatingToAppBoundDomain> isAppBound = NavigatingToAppBoundDomain::No;
694 isAppBound = m_isNavigatingToAppBoundDomain;
695 if (localFrame)
696 WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::StartDownload(policyDownloadID, request, topOrigin, isAppBound, suggestedName, fromDownloadAttribute, localFrame->frameID(), localFrame->pageID()), 0);
697}
698
699void WebFrame::convertMainResourceLoadToDownload(DocumentLoader* documentLoader, const ResourceRequest& request, const ResourceResponse& response)
700{
701 if (!m_policyDownloadID) {
702 ASSERT_NOT_REACHED()((void)0);
703 return;
704 }
705 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
706 auto topOrigin = localFrame && localFrame->document() ? std::optional { protect(localFrame->document())->topOrigin().data() } : std::nullopt;
707 auto policyDownloadID = *std::exchange(m_policyDownloadID, std::nullopt);
708
709 RefPtr mainResourceLoader = documentLoader->mainResourceLoader();
710
711 auto& webProcess = WebProcess::singleton();
712 // Use std::nullopt to indicate that the resource load can't be converted and a new download must be started.
713 // This can happen if there is no loader because the main resource is in the WebCore memory cache,
714 // or because the conversion was attempted when not calling SubresourceLoader::didReceiveResponse().
715 std::optional<WebCore::ResourceLoaderIdentifier> mainResourceLoadIdentifier;
716 if (mainResourceLoader)
717 mainResourceLoadIdentifier = mainResourceLoader->identifier();
718
719 std::optional<NavigatingToAppBoundDomain> isAppBound = NavigatingToAppBoundDomain::No;
720 isAppBound = m_isNavigatingToAppBoundDomain;
721 webProcess.ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::ConvertMainResourceLoadToDownload(mainResourceLoadIdentifier, policyDownloadID, request, topOrigin, response, isAppBound), 0);
722}
723
724void WebFrame::addConsoleMessage(MessageSource messageSource, MessageLevel messageLevel, const String& message, uint64_t requestID)
725{
726 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
727 if (!localFrame)
728 localFrame = m_provisionalFrame.get();
729
730 if (!localFrame)
731 return;
732
733 if (RefPtr document = localFrame->document())
734 document->addConsoleMessage(messageSource, messageLevel, message, requestID);
735}
736
737String WebFrame::source() const
738{
739 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
740 if (!localFrame)
741 return String();
742 RefPtr document = localFrame->document();
743 if (!document)
744 return String();
745 RefPtr decoder = document->decoder();
746 if (!decoder)
747 return String();
748 RefPtr documentLoader = localFrame->loader().activeDocumentLoader();
749 if (!documentLoader)
750 return String();
751 RefPtr<FragmentedSharedBuffer> mainResourceData = documentLoader->mainResourceData();
752 if (!mainResourceData)
753 return String();
754 return decoder->encoding().decode(mainResourceData->makeContiguous()->span());
755}
756
757String WebFrame::contentsAsString() const
758{
759 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
760 if (!localFrame)
761 return String();
762
763 if (isFrameSet()) {
764 StringBuilder builder;
765 for (RefPtr child = m_coreFrame->tree().firstChild(); child; child = child->tree().nextSibling()) {
766 if (!builder.isEmpty())
767 builder.append(' ');
768
769 RefPtr webFrame = WebFrame::fromCoreFrame(*child);
770 ASSERT(webFrame)((void)0);
771 if (!webFrame)
772 continue;
773
774 builder.append(webFrame->contentsAsString());
775 }
776 // FIXME: It may make sense to use toStringPreserveCapacity() here.
777 return builder.toString();
778 }
779
780 RefPtr document = localFrame->document();
781 if (!document)
782 return String();
783
784 RefPtr documentElement = document->documentElement();
785 if (!documentElement)
786 return String();
787
788 return plainText(makeRangeSelectingNodeContents(*documentElement));
789}
790
791String WebFrame::selectionAsString() const
792{
793 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
794 if (!localFrame)
795 return String();
796
797 return localFrame->displayStringModifiedByEncoding(protect(localFrame->editor())->selectedText());
798}
799
800IntSize WebFrame::size() const
801{
802 RefPtr localFrame = coreFrame();
803 if (!localFrame)
804 return IntSize();
805
806 RefPtr frameView = localFrame->virtualView();
807 if (!frameView)
808 return IntSize();
809
810 return frameView->contentsSize();
811}
812
813bool WebFrame::isFrameSet() const
814{
815 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
816 if (!localFrame)
817 return false;
818
819 RefPtr document = localFrame->document();
820 if (!document)
821 return false;
822 return document->isFrameSet();
823}
824
825bool WebFrame::isMainFrame() const
826{
827 auto* coreFrame = m_coreFrame.get();
828 return coreFrame && coreFrame->isMainFrame();
829}
830
831bool WebFrame::isRootFrame() const
832{
833 RefPtr coreFrame = m_coreFrame.get();
834 return coreFrame && coreFrame->isRootFrame();
835}
836
837String WebFrame::name() const
838{
839 RefPtr coreFrame = m_coreFrame.get();
840 if (!coreFrame)
841 return String();
842
843 return coreFrame->tree().uniqueName();
844}
845
846URL WebFrame::url() const
847{
848 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
849 if (!localFrame)
850 return { };
851
852 RefPtr documentLoader = localFrame->loader().documentLoader();
853 if (!documentLoader)
854 return { };
855
856 return documentLoader->url();
857}
858
859CertificateInfo WebFrame::certificateInfo() const
860{
861 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
862 if (!localFrame)
863 return { };
864
865 RefPtr documentLoader = localFrame->loader().documentLoader();
866 if (!documentLoader)
867 return { };
868
869 return valueOrCompute(documentLoader->response().certificateInfo(), [] { return CertificateInfo(); });
870}
871
872String WebFrame::innerText() const
873{
874 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
875 if (!localFrame)
876 return String();
877
878 if (!localFrame->document()->documentElement())
879 return String();
880
881 return protect(protect(localFrame->document())->documentElement())->innerText();
882}
883
884RefPtr<WebFrame> WebFrame::parentFrame() const
885{
886 auto* frame = m_coreFrame.get();
887 if (!frame)
888 return nullptr;
889
890 auto* parentFrame = frame->tree().parent();
891 if (!parentFrame)
892 return nullptr;
893
894 return WebFrame::fromCoreFrame(*parentFrame);
895}
896
897Ref<API::Array> WebFrame::childFrames()
898{
899 if (!m_coreFrame)
900 return API::Array::create();
901
902 size_t size = m_coreFrame->tree().childCount();
903 if (!size)
904 return API::Array::create();
905
906 Vector<RefPtr<API::Object>> vector;
907 vector.reserveInitialCapacity(size);
908
909 for (RefPtr child = m_coreFrame->tree().firstChild(); child; child = child->tree().nextSibling()) {
910 RefPtr webFrame = WebFrame::fromCoreFrame(*child);
911 ASSERT(webFrame)((void)0);
912 if (!webFrame)
913 continue;
914 vector.append(webFrame);
915 }
916
917 return API::Array::create(WTF::move(vector));
918}
919
920String WebFrame::layerTreeAsText() const
921{
922 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
923 if (!localFrame)
924 return emptyString();
925
926 return protect(protect(localFrame->contentRenderer())->compositor())->layerTreeAsText();
927}
928
929unsigned WebFrame::pendingUnloadCount() const
930{
931 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
932 if (!localFrame)
933 return 0;
934
935 return protect(protect(localFrame->document())->window())->pendingUnloadEventListeners();
936}
937
938bool WebFrame::allowsFollowingLink(const URL& url) const
939{
940 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
941 if (!localFrame)
942 return true;
943
944 return protect(protect(localFrame->document())->securityOrigin())->canDisplay(url, WebCore::OriginAccessPatternsForWebProcess::singleton());
945}
946
947JSGlobalContextRef WebFrame::jsContext()
948{
949 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
950 if (!localFrame)
951 return nullptr;
952
953 return toGlobalRef(protect(localFrame->script())->globalObject(mainThreadNormalWorldSingleton()));
954}
955
956JSGlobalContextRef WebFrame::jsContextForWorld(DOMWrapperWorld& world)
957{
958 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
959 if (!localFrame)
960 return nullptr;
961
962 return toGlobalRef(protect(localFrame->script())->globalObject(world));
963}
964
965JSGlobalContextRef WebFrame::jsContextForWorld(InjectedBundleScriptWorld* world)
966{
967 return jsContextForWorld(protect(world->coreWorld()));
968}
969
970JSGlobalContextRef WebFrame::jsContextForServiceWorkerWorld(DOMWrapperWorld& world)
971{
972 if (!m_coreFrame || !m_coreFrame->page())
973 return nullptr;
974
975 return toGlobalRef(protect(m_coreFrame->page())->serviceWorkerGlobalObject(world));
976}
977
978JSGlobalContextRef WebFrame::jsContextForServiceWorkerWorld(InjectedBundleScriptWorld* world)
979{
980 return jsContextForServiceWorkerWorld(protect(world->coreWorld()));
981}
982
983void WebFrame::setAccessibleName(const AtomString& accessibleName)
984{
985 if (!AXObjectCache::accessibilityEnabled())
986 return;
987
988 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
989 if (!localFrame)
990 return;
991
992 RefPtr document = localFrame->document();
993 if (!document)
994 return;
995
996 RefPtr rootObject = protect(document->axObjectCache())->rootObjectForFrame(*localFrame);
997 if (!rootObject)
998 return;
999
1000 rootObject->setAccessibleName(accessibleName);
1001}
1002
1003IntRect WebFrame::contentBounds() const
1004{
1005 RefPtr localCoreFrame = coreFrame();
1006 if (!localCoreFrame)
1007 return IntRect();
1008
1009 RefPtr view = localCoreFrame->virtualView();
1010 if (!view)
1011 return IntRect();
1012
1013 return IntRect(0, 0, view->contentsWidth(), view->contentsHeight());
1014}
1015
1016IntRect WebFrame::visibleContentBounds() const
1017{
1018 RefPtr coreFrame = m_coreFrame.get();
1019 if (!coreFrame)
1020 return IntRect();
1021
1022 RefPtr view = coreFrame->virtualView();
1023 if (!view)
1024 return IntRect();
1025
1026 IntRect contentRect = view->visibleContentRectIncludingScrollbars();
1027 return IntRect(0, 0, contentRect.width(), contentRect.height());
1028}
1029
1030IntRect WebFrame::visibleContentBoundsExcludingScrollbars() const
1031{
1032 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
1033 if (!localFrame)
1034 return IntRect();
1035
1036 RefPtr view = localFrame->view();
1037 if (!view)
1038 return IntRect();
1039
1040 IntRect contentRect = view->visibleContentRect();
1041 return IntRect(0, 0, contentRect.width(), contentRect.height());
1042}
1043
1044IntSize WebFrame::scrollOffset() const
1045{
1046 RefPtr localCoreFrame = coreFrame();
1047 if (!localCoreFrame)
1048 return IntSize();
1049
1050 RefPtr view = localCoreFrame->virtualView();
1051 if (!view)
1052 return IntSize();
1053
1054 return toIntSize(view->scrollPosition());
1055}
1056
1057bool WebFrame::hasHorizontalScrollbar() const
1058{
1059 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
1060 if (!localFrame)
1061 return false;
1062
1063 RefPtr view = localFrame->view();
1064 if (!view)
1065 return false;
1066
1067 return view->horizontalScrollbar();
1068}
1069
1070bool WebFrame::hasVerticalScrollbar() const
1071{
1072 RefPtr localCoreFrame = coreFrame();
1073 if (!localCoreFrame)
1074 return false;
1075
1076 RefPtr view = localCoreFrame->virtualView();
1077 if (!view)
1078 return false;
1079
1080 return view->verticalScrollbar();
1081}
1082
1083RefPtr<InjectedBundleHitTestResult> WebFrame::hitTest(const IntPoint point, OptionSet<HitTestRequest::Type> types) const
1084{
1085 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
1086 if (!localFrame)
1087 return nullptr;
1088
1089 return InjectedBundleHitTestResult::create(localFrame->eventHandler().hitTestResultAtPoint(point, types));
1090}
1091
1092bool WebFrame::getDocumentBackgroundColor(double* red, double* green, double* blue, double* alpha)
1093{
1094 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
1095 if (!localFrame)
1096 return false;
1097
1098 RefPtr view = localFrame->view();
1099 if (!view)
1100 return false;
1101
1102 Color bgColor = view->documentBackgroundColor();
1103 if (!bgColor.isValid())
1104 return false;
1105
1106 auto [r, g, b, a] = bgColor.toColorTypeLossy<SRGBA<float>>().resolved();
1107 *red = r;
1108 *green = g;
1109 *blue = b;
1110 *alpha = a;
1111 return true;
1112}
1113
1114bool WebFrame::containsAnyFormElements() const
1115{
1116 auto* localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
1117 if (!localFrame)
1118 return false;
1119
1120 auto* document = localFrame->document();
1121 return document && childrenOfType<HTMLFormElement>(*document).first();
1122}
1123
1124bool WebFrame::containsAnyFormControls() const
1125{
1126 auto* localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
1127 if (!localFrame)
1128 return false;
1129
1130 auto* document = localFrame->document();
1131 if (!document)
1132 return false;
1133
1134 for (auto& child : childrenOfType<Element>(*document)) {
1135 if (is<HTMLTextFormControlElement>(child) || is<HTMLSelectElement>(child))
1136 return true;
1137 }
1138 return false;
1139}
1140
1141void WebFrame::stopLoading()
1142{
1143 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
1144 if (!localFrame)
1145 return;
1146
1147 localFrame->loader().stopForUserCancel();
1148}
1149
1150RefPtr<WebFrame> WebFrame::frameForContext(JSContextRef context)
1151{
1152 RefPtr coreFrame = LocalFrame::fromJSContext(context);
1153 return coreFrame ? WebFrame::fromCoreFrame(*coreFrame) : nullptr;
1154}
1155
1156RefPtr<WebFrame> WebFrame::contentFrameForWindowOrFrameElement(JSContextRef context, JSValueRef value)
1157{
1158 RefPtr coreFrame = LocalFrame::contentFrameFromWindowOrFrameElement(context, value);
1159 return coreFrame ? WebFrame::fromCoreFrame(*coreFrame) : nullptr;
1160}
1161
1162JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleCSSStyleDeclarationHandle* cssStyleDeclarationHandle, InjectedBundleScriptWorld* world)
1163{
1164 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
1165 if (!localFrame)
1166 return nullptr;
1167
1168 auto* globalObject = protect(localFrame->script())->globalObject(protect(world->coreWorld()));
1169
1170 JSC::JSLockHolder lock(globalObject);
1171 return toRef(globalObject, toJS(globalObject, globalObject, cssStyleDeclarationHandle->coreCSSStyleDeclaration()));
1172}
1173
1174JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleNodeHandle* nodeHandle, InjectedBundleScriptWorld* world)
1175{
1176 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
1177 if (!localFrame)
1178 return nullptr;
1179
1180 auto* globalObject = protect(localFrame->script())->globalObject(protect(world->coreWorld()));
1181
1182 JSC::JSLockHolder lock(globalObject);
1183 RefPtr coreNode = nodeHandle->coreNode();
1184 return toRef(globalObject, coreNode ? toJS(globalObject, globalObject, coreNode.releaseNonNull()) : JSC::jsNull());
1185}
1186
1187JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleRangeHandle* rangeHandle, InjectedBundleScriptWorld* world)
1188{
1189 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
1190 if (!localFrame)
1191 return nullptr;
1192
1193 auto* globalObject = protect(localFrame->script())->globalObject(protect(world->coreWorld()));
1194
1195 JSC::JSLockHolder lock(globalObject);
1196 return toRef(globalObject, toJS(globalObject, globalObject, Ref { rangeHandle->coreRange() }.get()));
1197}
1198
1199String WebFrame::counterValue(JSObjectRef element)
1200{
1201 if (!toJS(element)->inherits<JSElement>())
1202 return String();
1203
1204 Ref coreElement = downcast<JSElement>(toJS(element))->wrapped();
1205 return counterValueForElement(coreElement.ptr());
1206}
1207
1208String WebFrame::provisionalURL() const
1209{
1210 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
1211 if (!localFrame)
1212 return String();
1213
1214 RefPtr provisionalDocumentLoader = localFrame->loader().provisionalDocumentLoader();
1215 if (!provisionalDocumentLoader)
1216 return String();
1217
1218 return provisionalDocumentLoader->url().string();
1219}
1220
1221String WebFrame::suggestedFilenameForResourceWithURL(const URL& url) const
1222{
1223 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
1224 if (!localFrame)
1225 return String();
1226
1227 RefPtr loader = localFrame->loader().documentLoader();
1228 if (!loader)
1229 return String();
1230
1231 // First, try the main resource.
1232 if (loader->url() == url)
1233 return loader->response().suggestedFilename();
1234
1235 // Next, try subresources.
1236 RefPtr<ArchiveResource> resource = loader->subresource(url);
1237 if (resource)
1238 return resource->response().suggestedFilename();
1239
1240 return String();
1241}
1242
1243String WebFrame::mimeTypeForResourceWithURL(const URL& url) const
1244{
1245 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
1246 if (!localFrame)
1247 return String();
1248
1249 RefPtr loader = localFrame->loader().documentLoader();
1250 if (!loader)
1251 return String();
1252
1253 // First, try the main resource.
1254 if (loader->url() == url)
1255 return loader->response().mimeType();
1256
1257 // Next, try subresources.
1258 RefPtr<ArchiveResource> resource = loader->subresource(url);
1259 if (resource)
1260 return resource->mimeType();
1261
1262 return String();
1263}
1264
1265void WebFrame::updateFrameRectFromRemote(WebCore::IntRect newRect)
1266{
1267 ASSERT(m_page->corePage()->settings().siteIsolationEnabled())((void)0);
1268 if (RefPtr localFrame = coreLocalFrame())
1269 updateLocalFrameRect(*localFrame, newRect);
1270 else {
1271 RefPtr remoteFrame = coreRemoteFrame();
1272 RefPtr remoteFrameView = remoteFrame->view();
1273
1274 if (remoteFrameView->frameRect() != newRect)
1275 remoteFrameView->setFrameRectWithoutSync(newRect);
1276 }
1277}
1278
1279void WebFrame::updateLocalFrameRect(WebCore::LocalFrame& localFrame, WebCore::IntRect newRect)
1280{
1281 RefPtr frameView = localFrame.view();
1282 if (!frameView)
1283 return;
1284
1285 auto oldRect = frameView->frameRect();
1286
1287 if (oldRect == newRect)
1288 return;
1289 frameView->setFrameRect(newRect);
1290
1291#if PLATFORM(IOS_FAMILY)(defined WTF_PLATFORM_IOS_FAMILY && WTF_PLATFORM_IOS_FAMILY
)
1292 if (oldRect.size() != frameView->size()) {
1293 // FIXME: This ensures cross-site iframe render correctly;
1294 // it should be removed after rdar://122429810 is fixed.
1295 frameView->setExposedContentRect(FloatRect { { }, frameView->size() });
1296 frameView->setUnobscuredContentSize(frameView->size());
1297 }
1298#endif
1299
1300
1301 if (RefPtr drawingArea = m_page ? m_page->drawingArea() : nullptr) {
1302 drawingArea->setNeedsDisplay();
1303 drawingArea->triggerRenderingUpdate();
1304 }
1305}
1306
1307void WebFrame::setTextDirection(const String& direction)
1308{
1309 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
1310 if (!localFrame)
1311 return;
1312
1313 if (direction == "auto"_s)
1314 protect(localFrame->editor())->setBaseWritingDirection(WritingDirection::Natural);
1315 else if (direction == "ltr"_s)
1316 protect(localFrame->editor())->setBaseWritingDirection(WritingDirection::LeftToRight);
1317 else if (direction == "rtl"_s)
1318 protect(localFrame->editor())->setBaseWritingDirection(WritingDirection::RightToLeft);
1319}
1320
1321#if PLATFORM(COCOA)(defined 1 && 1)
1322RetainPtr<CFDataRef> WebFrame::webArchiveData(FrameFilterFunction callback, void* context, const Vector<WebCore::MarkupExclusionRule>& exclusionRules, const String& mainResourceFileName)
1323{
1324 Ref document = *coreLocalFrame()->document();
1325 LegacyWebArchive::ArchiveOptions options {
1326 LegacyWebArchive::ShouldSaveScriptsFromMemoryCache::Yes,
1327 LegacyWebArchive::ShouldArchiveSubframes::Yes,
1328 exclusionRules,
1329 mainResourceFileName
1330 };
1331 auto archive = LegacyWebArchive::create(document, WTF::move(options), [this, callback, context](auto& frame) -> bool {
1332 if (!callback)
1333 return true;
1334
1335 RefPtr webFrame = WebFrame::fromCoreFrame(frame);
1336 ASSERT(webFrame)((void)0);
1337
1338 return callback(toAPI(this), toAPI(webFrame.get()), context);
1339 });
1340
1341 if (!archive)
1342 return nullptr;
1343
1344 return archive->rawDataRepresentation();
1345}
1346#endif
1347
1348RefPtr<WebImage> WebFrame::createSelectionSnapshot() const
1349{
1350 auto snapshot = snapshotSelection(*protect(coreLocalFrame()), { { WebCore::SnapshotFlags::ForceBlackText, WebCore::SnapshotFlags::Shareable }, PixelFormat::BGRA8, DestinationColorSpace::SRGB() });
1351 if (!snapshot)
1352 return nullptr;
1353
1354 return WebImage::create(snapshot.releaseNonNull());
1355}
1356
1357#if ENABLE(APP_BOUND_DOMAINS)(defined ENABLE_APP_BOUND_DOMAINS && ENABLE_APP_BOUND_DOMAINS
)
1358bool WebFrame::shouldEnableInAppBrowserPrivacyProtections()
1359{
1360 if (page() && page()->needsInAppBrowserPrivacyQuirks())
1361 return false;
1362
1363 bool treeHasNonAppBoundFrame = m_isNavigatingToAppBoundDomain && m_isNavigatingToAppBoundDomain == NavigatingToAppBoundDomain::No;
1364 if (!treeHasNonAppBoundFrame) {
1365 for (RefPtr frame = this; frame; frame = frame->parentFrame()) {
1366 if (frame->isNavigatingToAppBoundDomain() && frame->isNavigatingToAppBoundDomain() == NavigatingToAppBoundDomain::No) {
1367 treeHasNonAppBoundFrame = true;
1368 break;
1369 }
1370 }
1371 }
1372 return treeHasNonAppBoundFrame;
1373}
1374
1375std::optional<NavigatingToAppBoundDomain> WebFrame::isTopFrameNavigatingToAppBoundDomain() const
1376{
1377 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
1378 if (!localFrame)
1379 return std::nullopt;
1380 RefPtr localMainFrame = dynamicDowncast<LocalFrame>(localFrame->mainFrame());
1381 if (!localMainFrame)
1382 return std::nullopt;
1383 return fromCoreFrame(*localMainFrame)->isNavigatingToAppBoundDomain();
1384}
1385#endif
1386
1387inline DocumentLoader* WebFrame::policySourceDocumentLoader() const
1388{
1389 RefPtr coreFrame = coreLocalFrame();
1390 if (!coreFrame)
1391 return nullptr;
1392
1393 RefPtr document = coreFrame->document();
1394 if (!document)
1395 return nullptr;
1396
1397 RefPtr mainFrameDocument = document->mainFrameDocument();
1398 if (!mainFrameDocument) {
1399 LOG_ONCE(SiteIsolation, "Unable to properly calculate WebFrame::policySourceDocumentLoader() without access to the main frame document ")((void)0);
1400 return nullptr;
1401 }
1402
1403 WeakPtr mainFrameDocumentLoader = mainFrameDocument->loader();
1404 if (!mainFrameDocumentLoader)
1405 return nullptr;
1406
1407 if (mainFrameDocumentLoader->request().url().hasSpecialScheme() && document->url().protocolIsInHTTPFamily())
1408 return document->loader();
1409
1410 return mainFrameDocumentLoader.get();
1411}
1412
1413OptionSet<WebCore::AdvancedPrivacyProtections> WebFrame::advancedPrivacyProtections() const
1414{
1415 RefPtr loader = policySourceDocumentLoader();
1416 if (!loader)
1417 return { };
1418
1419 return loader->advancedPrivacyProtections();
1420}
1421
1422std::optional<OptionSet<WebCore::AdvancedPrivacyProtections>> WebFrame::originatorAdvancedPrivacyProtections() const
1423{
1424 RefPtr loader = policySourceDocumentLoader();
1425 if (!loader)
1426 return { };
1427
1428 return loader->originatorAdvancedPrivacyProtections();
1429}
1430
1431#if ENABLE(CONTEXT_MENU_EVENT)(defined 1 && 1)
1432static bool NODELETE[[clang::annotate_type("webkit.nodelete")]] isContextClick(const PlatformMouseEvent& event)
1433{
1434#if USE(APPKIT)(defined 1 && 1)
1435 return WebEventFactory::shouldBeHandledAsContextClick(event);
1436#else
1437 return event.button() == WebCore::MouseButton::Right;
1438#endif
1439}
1440
1441bool WebFrame::handleContextMenuEvent(const PlatformMouseEvent& platformMouseEvent)
1442{
1443 RefPtr coreLocalFrame = dynamicDowncast<LocalFrame>(coreFrame());
1444 if (!coreLocalFrame)
1445 return false;
1446 IntPoint point = protect(coreLocalFrame->view())->windowToContents(flooredIntPoint(platformMouseEvent.position()));
1447 constexpr OptionSet<HitTestRequest::Type> hitType { HitTestRequest::Type::ReadOnly, HitTestRequest::Type::Active, HitTestRequest::Type::DisallowUserAgentShadowContent, HitTestRequest::Type::AllowChildFrameContent };
1448 HitTestResult result = coreLocalFrame->eventHandler().hitTestResultAtPoint(point, hitType);
1449
1450 Ref frame = *coreLocalFrame;
1451 if (result.innerNonSharedNode())
1452 frame = *result.innerNonSharedNode()->document().frame();
1453
1454 bool handled = frame->eventHandler().sendContextMenuEvent(platformMouseEvent);
1455#if ENABLE(CONTEXT_MENUS)(defined 1 && 1)
1456 if (handled && protect(protect(page())->contextMenu())->show())
1457 page()->corePage()->pointerCaptureController().clearUnmatchedMouseDown(platformMouseEvent.pointerId());
1458
1459#endif
1460 return handled;
1461}
1462#endif
1463
1464WebCore::HandleUserInputEventResult WebFrame::handleMouseEvent(const WebMouseEvent& mouseEvent)
1465{
1466 RefPtr coreLocalFrame = dynamicDowncast<LocalFrame>(coreFrame());
1467 if (!coreLocalFrame)
1468 return false;
1469
1470 if (!coreLocalFrame->view())
1471 return false;
1472
1473 PlatformMouseEvent platformMouseEvent = platform(mouseEvent);
1474
1475 switch (platformMouseEvent.type()) {
1476 case PlatformEvent::Type::MousePressed: {
1477#if ENABLE(CONTEXT_MENUS)(defined 1 && 1)
1478 if (isContextClick(platformMouseEvent))
1479 page()->corePage()->contextMenuController().clearContextMenu();
1480#endif
1481
1482 auto mousePressEventResult = coreLocalFrame->eventHandler().handleMousePressEvent(platformMouseEvent);
1483#if ENABLE(CONTEXT_MENU_EVENT)(defined 1 && 1)
1484 if (isContextClick(platformMouseEvent) && !mousePressEventResult.remoteUserInputEventData())
1485 mousePressEventResult.setHandled(handleContextMenuEvent(platformMouseEvent));
1486#endif
1487 return mousePressEventResult;
1488 }
1489 case PlatformEvent::Type::MouseReleased:
1490 if (mouseEvent.gestureWasCancelled() == GestureWasCancelled::Yes)
1491 coreLocalFrame->eventHandler().invalidateClick();
1492 return coreLocalFrame->eventHandler().handleMouseReleaseEvent(platformMouseEvent);
1493
1494 case PlatformEvent::Type::MouseMoved:
1495#if PLATFORM(COCOA)(defined 1 && 1)
1496 // We need to do a full, normal hit test during this mouse event if the page is active or if a mouse
1497 // button is currently pressed. It is possible that neither of those things will be true since on
1498 // Lion when legacy scrollbars are enabled, WebKit receives mouse events all the time. If it is one
1499 // of those cases where the page is not active and the mouse is not pressed, then we can fire a more
1500 // efficient scrollbars-only version of the event.
1501 if (!(page()->corePage()->focusController().isActive() || (mouseEvent.button() != WebMouseEventButton::None)))
1502 return coreLocalFrame->eventHandler().passMouseMovedEventToScrollbars(platformMouseEvent);
1503#endif
1504 return coreLocalFrame->eventHandler().mouseMoved(platformMouseEvent);
1505
1506 case PlatformEvent::Type::MouseForceChanged:
1507 case PlatformEvent::Type::MouseForceDown:
1508 case PlatformEvent::Type::MouseForceUp:
1509 return coreLocalFrame->eventHandler().handleMouseForceEvent(platformMouseEvent);
1510
1511 default:
1512 ASSERT_NOT_REACHED()((void)0);
1513 return false;
1514 }
1515}
1516
1517bool WebFrame::handleKeyEvent(const WebKeyboardEvent& keyboardEvent)
1518{
1519 RefPtr coreFrame = coreLocalFrame();
1520 if (!coreFrame)
1521 return false;
1522
1523 if (keyboardEvent.type() == WebEventType::Char && keyboardEvent.isSystemKey())
1524 return coreFrame->eventHandler().handleAccessKey(platform(keyboardEvent));
1525 return coreFrame->eventHandler().keyEvent(platform(keyboardEvent));
1526}
1527
1528bool WebFrame::isFocused() const
1529{
1530 if (!m_coreFrame)
1531 return false;
1532
1533 auto* page = m_coreFrame->page();
1534 if (!page)
1535 return false;
1536
1537 return m_coreFrame->page()->focusController().focusedFrame() == coreFrame();
1538}
1539
1540String WebFrame::frameTextForTesting(bool includeSubframes)
1541{
1542 if (!m_coreFrame)
1543 return { };
1544
1545 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
1546 if (!localFrame || !localFrame->document() || !localFrame->document()->documentElement())
1547 return { };
1548
1549 StringBuilder builder;
1550
1551 // Use plainText() directly instead of innerText() to avoid the WHATWG
1552 // spec-compliant newline changes (e.g. blank lines around <p>) that
1553 // would require rebaselining hundreds of layout tests.
1554 Ref documentElement = *protect(protect(localFrame->document())->documentElement());
1555 protect(localFrame->document())->updateLayoutIgnorePendingStylesheets();
1556 String text = documentElement->renderer()
1557 ? plainText(makeRangeSelectingNodeContents(documentElement))
1558 : documentElement->textContent(true);
1559 if (text.isNull())
1560 return { };
1561
1562 // To keep things tidy, strip all trailing spaces: they are not a meaningful part of dumpAsText test output.
1563 // Breaking the string up into lines lets us efficiently strip and has a side effect of adding a newline after the last line.
1564 for (auto line : StringView(text).splitAllowingEmptyEntries('\n')) {
1565 while (line.endsWith(' '))
1566 line = line.left(line.length() - 1);
1567 builder.append(line, '\n');
1568 }
1569
1570 if (!includeSubframes)
1571 return builder.toString();
1572
1573 for (RefPtr child = m_coreFrame->tree().firstChild(); child; child = child->tree().nextSibling()) {
1574 RefPtr childWebFrame = fromCoreFrame(*child);
1575 if (!childWebFrame)
1576 continue;
1577 auto frameName = makeAtomString("\n--------\nFrame: '"_s, childWebFrame->name(), "'\n--------\n"_s);
1578 if (is<RemoteFrame>(*child))
1579 builder.append(frameName, m_page->sendSync(Messages::WebPageProxy::FrameTextForTesting(child->frameID())).takeReplyOr("Sending WebPageProxy::FrameTextForTesting failed"_s));
1580 else if (!childWebFrame->innerText().isNull())
1581 builder.append(frameName, childWebFrame->frameTextForTesting(includeSubframes));
1582 }
1583
1584 return builder.toString();
1585}
1586
1587static Ref<WebKitJSHandle> createJSHandle(Node& node)
1588{
1589 Ref document = node.document();
1590 auto* lexicalGlobalObject = document->globalObject();
1591 RELEASE_ASSERT(lexicalGlobalObject->template inherits<JSDOMGlobalObject>())do { if (__builtin_expect(!!(!(lexicalGlobalObject->template
inherits<JSDOMGlobalObject>())), 0)) do { WTF::isIntegralOrPointerType
(); compilerFenceForCrash(); WTFCrashWithInfo(1591, "/Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/Source/WebKit/WebProcess/WebPage/WebFrame.cpp"
, __PRETTY_FUNCTION__ ); } while (false); } while (0)
;
1592 auto* domGlobalObject = downcast<JSDOMGlobalObject>(lexicalGlobalObject);
1593 JSC::JSLockHolder locker { lexicalGlobalObject };
1594 return WebKitJSHandle::create(toJS(lexicalGlobalObject, domGlobalObject, node).toObject(lexicalGlobalObject));
1595}
1596
1597std::pair<Ref<WebKitJSHandle>, JSHandleInfo> WebFrame::createAndPrepareToSendJSHandle(Node& node) const
1598{
1599 Ref handle = createJSHandle(node);
1600 WebKitJSHandle::jsHandleSentToAnotherProcess(handle->identifier());
1601 JSHandleInfo handleInfo { handle->identifier(), pageContentWorldIdentifier(), info(), handle->windowFrameIdentifier() };
1602 return { WTF::move(handle), WTF::move(handleInfo) };
1603}
1604
1605WebFrame* WebFrame::webFrame(std::optional<WebCore::FrameIdentifier> frameID)
1606{
1607 return WebProcess::singleton().webFrame(frameID);
1608}
1609
1610IPC::Connection* WebFrame::messageSenderConnection() const
1611{
1612 return WebProcess::singleton().parentProcessConnection();
1613}
1614
1615uint64_t WebFrame::messageSenderDestinationID() const
1616{
1617 return m_frameID.toUInt64();
1618}
1619
1620void WebFrame::setAppBadge(const WebCore::SecurityOriginData& origin, std::optional<uint64_t> badge)
1621{
1622 send(Messages::WebFrameProxy::SetAppBadge(origin, badge));
1623}
1624
1625std::optional<ResourceResponse> WebFrame::resourceResponseForURL(const URL& url) const
1626{
1627 RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get());
1628 if (!localFrame)
1629 return std::nullopt;
1630
1631 RefPtr loader = localFrame->loader().documentLoader();
1632 if (!loader)
1633 return std::nullopt;
1634
1635 if (loader->url() == url)
1636 return loader->response();
1637
1638 RefPtr resource = loader->subresource(url);
1639 if (resource)
1640 return resource->response();
1641
1642 return std::nullopt;
1643}
1644
1645void WebFrame::findFocusableElementDescendingIntoRemoteFrame(WebCore::FocusDirection direction, const WebCore::FocusEventData& focusEventData, WebCore::ShouldFocusElement shouldFocusElement, CompletionHandler<void(WebCore::FoundElementInRemoteFrame)>&& completionHandler)
1646{
1647 auto foundElementInRemoteFrame = WebCore::FoundElementInRemoteFrame::No;
1648
1649 if (m_coreFrame) {
1650 if (RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get())) {
1651 if (RefPtr page = localFrame->page()) {
1652 auto result = page->focusController().findFocusableElementStartingWithLocalFrame(direction, focusEventData, *localFrame, shouldFocusElement);
1653 if (result.element)
1654 foundElementInRemoteFrame = WebCore::FoundElementInRemoteFrame::Yes;
1655 }
1656 }
1657 }
1658
1659 completionHandler(foundElementInRemoteFrame);
1660}
1661
1662void WebFrame::findFocusableElementContinuingFromFrame(WebCore::FocusDirection direction, WebCore::FrameIdentifier frameID, const WebCore::FocusEventData& focusEventData, WebCore::ShouldFocusElement shouldFocusElement)
1663{
1664 if (!m_coreFrame)
1665 return;
1666
1667 if (RefPtr localFrame = dynamicDowncast<LocalFrame>(m_coreFrame.get())) {
1668 if (RefPtr page = localFrame->page())
1669 page->focusController().findFocusableElementContinuingFromFrame(direction, frameID, focusEventData, *localFrame, shouldFocusElement);
1670 }
1671}
1672
1673static RefPtr<Node> NODELETE[[clang::annotate_type("webkit.nodelete")]] nodeFromJSHandleIdentifier(JSHandleIdentifier identifier)
1674{
1675 auto* object = WebKitJSHandle::objectForIdentifier(identifier);
1676 if (!object)
1677 return { };
1678
1679 auto* jsNode = dynamicDowncast<JSNode>(object);
1680 if (!jsNode)
1681 return { };
1682
1683 return jsNode->wrapped();
1684}
1685
1686void WebFrame::takeSnapshotOfNode(JSHandleIdentifier identifier, CompletionHandler<void(std::optional<ShareableBitmapHandle>&&)>&& completion)
1687{
1688 RefPtr page = m_page.get();
1689 if (!page)
1690 return completion({ });
1691
1692 RefPtr node = nodeFromJSHandleIdentifier(identifier);
1693 if (!node)
1694 return completion({ });
1695
1696 RefPtr bitmap = page->shareableBitmapSnapshotForNode(*node);
1697 if (!bitmap)
1698 return completion({ });
1699
1700 completion(bitmap->createHandle(SharedMemory::Protection::ReadOnly));
1701}
1702
1703CheckedRef<FrameInspectorTarget> WebFrame::ensureInspectorTarget()
1704{
1705 if (!m_inspectorTarget)
1706 m_inspectorTarget = makeUnique<FrameInspectorTarget>(*this);
1707 return *m_inspectorTarget;
1708}
1709
1710void WebFrame::connectInspector(Inspector::FrontendChannel::ConnectionType connectionType)
1711{
1712 ensureInspectorTarget()->connect(connectionType);
1713}
1714
1715void WebFrame::disconnectInspector()
1716{
1717 ensureInspectorTarget()->disconnect();
1718}
1719
1720void WebFrame::sendMessageToInspectorTarget(const String& message)
1721{
1722 ensureInspectorTarget()->sendMessageToTargetBackend(message);
1723}
1724
1725void WebFrame::requestTextExtraction(TextExtraction::Request&& request, CompletionHandler<void(TextExtraction::Result&&)>&& completion)
1726{
1727 RefPtr frame = coreLocalFrame();
1728 if (!frame)
1729 return completion({ });
1730
1731 completion(TextExtraction::extractItem(WTF::move(request), *frame));
1732}
1733
1734void WebFrame::takeSnapshotOfExtractedText(TextExtraction::ExtractedText&& extractedText, CompletionHandler<void(RefPtr<TextIndicator>&&)>&& completion)
1735{
1736 RefPtr frame = coreLocalFrame();
1737 if (!frame)
1738 return completion({ });
1739
1740 auto range = TextExtraction::rangeForExtractedText(*frame, WTF::move(extractedText));
1741 if (!range)
1742 return completion({ });
1743
1744 using enum WebCore::TextIndicatorOption;
1745 constexpr OptionSet options {
1746 RespectTextColor,
1747 PaintBackgrounds,
1748 PaintAllContent,
1749 TightlyFitContent,
1750 UseBoundingRectAndPaintAllContentForComplexRanges,
1751 DoNotClipToVisibleRect
1752 };
1753
1754 completion(TextIndicator::createWithRange(*range, options, TextIndicatorPresentationTransition::None));
1755}
1756
1757void WebFrame::describeTextExtractionInteraction(TextExtraction::Interaction&& interaction, CompletionHandler<void(TextExtraction::InteractionDescription&&)>&& completion)
1758{
1759 RefPtr frame = coreLocalFrame();
1760 if (!frame)
1761 return completion({ });
1762
1763 completion(TextExtraction::interactionDescription(interaction, *frame));
1764}
1765
1766void WebFrame::handleTextExtractionInteraction(TextExtraction::Interaction&& interaction, CompletionHandler<void(bool, String&&, FloatRect)>&& completion)
1767{
1768 RefPtr frame = coreLocalFrame();
1769 if (!frame)
1770 return completion(false, "Browsing context is unavailable"_s, { });
1771
1772 auto summary = TextExtraction::interactionDescription(interaction, *frame, TextExtraction::Tense::Past).description;
1773 TextExtraction::handleInteraction(WTF::move(interaction), *frame, [completion = WTF::move(completion), summary = WTF::move(summary)](bool success, String&& message, FloatRect interactedElementBounds) mutable {
1774 if (success && message.isEmpty())
1775 message = WTF::move(summary);
1776 completion(success, WTF::move(message), interactedElementBounds);
1777 });
1778}
1779
1780void WebFrame::requestJSHandleForExtractedText(TextExtraction::ExtractedText&& extractedText, CompletionHandler<void(std::optional<JSHandleInfo>&&)>&& completion)
1781{
1782 RefPtr frame = coreLocalFrame();
1783 if (!frame)
1784 return completion({ });
1785
1786 RefPtr element = TextExtraction::elementForExtractedText(*frame, WTF::move(extractedText));
1787 if (!element)
1788 return completion({ });
1789
1790 auto [handle, info] = createAndPrepareToSendJSHandle(*element);
1791 completion({ WTF::move(info) });
1792}
1793
1794void WebFrame::requestContainerJSHandleForExtractedText(TextExtraction::ExtractedText&& extractedText, CompletionHandler<void(std::optional<JSHandleInfo>&&)>&& completion)
1795{
1796 RefPtr frame = coreLocalFrame();
1797 if (!frame)
1798 return completion({ });
1799
1800 RefPtr element = TextExtraction::containerElementForExtractedText(*frame, WTF::move(extractedText));
1801 if (!element)
1802 return completion({ });
1803
1804 auto [handle, info] = createAndPrepareToSendJSHandle(*element);
1805 completion({ WTF::move(info) });
1806}
1807
1808void WebFrame::requestContainerJSHandleForSearchTexts(Vector<String>&& searchTexts, std::optional<NodeIdentifier>&& targetNodeIdentifier, CompletionHandler<void(std::optional<JSHandleInfo>&&)>&& completion)
1809{
1810 RefPtr frame = coreLocalFrame();
1811 if (!frame)
1812 return completion({ });
1813
1814 RefPtr element = TextExtraction::containerElementForSearchTexts(*frame, WTF::move(searchTexts), WTF::move(targetNodeIdentifier));
1815 if (!element)
1816 return completion({ });
1817
1818 auto [handle, info] = createAndPrepareToSendJSHandle(*element);
1819 completion({ WTF::move(info) });
1820}
1821
1822void WebFrame::getSelectorPathsForNode(JSHandleInfo&& handle, CompletionHandler<void(Vector<HashSet<String>>&&)>&& completion)
1823{
1824 RefPtr node = nodeFromJSHandleIdentifier(handle.identifier);
1825 if (!node)
1826 return completion({ });
1827
1828 RefPtr element = dynamicDowncast<Element>(*node) ?: node->parentElementInComposedTree();
1829 if (!element)
1830 return completion({ });
1831
1832 completion(ElementTargetingController::selectorsForElement(*element));
1833}
1834
1835void WebFrame::getNodeForSelectorPaths(Vector<HashSet<String>>&& selectors, CompletionHandler<void(std::optional<JSHandleInfo>&&)>&& completion)
1836{
1837 RefPtr frame = coreLocalFrame();
1838 if (!frame)
1839 return completion({ });
1840
1841 RefPtr document = frame->document();
1842 if (!document)
1843 return completion({ });
1844
1845 RefPtr element = ElementTargetingController::elementFromSelectors(*document, selectors);
1846 if (!element)
1847 return completion({ });
1848
1849 auto [handle, info] = createAndPrepareToSendJSHandle(*element);
1850 completion({ WTF::move(info) });
1851}
1852
1853} // namespace WebKit