Bug Summary

File:Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/Source/WebCore/accessibility/AccessibilityScrollView.cpp
Warning:line 112, column 54
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 -O2 -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 UnifiedSource110.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/WebCore -target-linker-version 1167.5 -fcoverage-compilation-dir=/Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/Source/WebCore -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/WebCore/WebCore/normal/arm64/UnifiedSource110.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/WebCore.build/Release/WebCore.build/WebCore-generated-files.hmap -iquote /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release/WebCore.build/WebCore-project-headers.hmap -isystem /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/Source/WebCore/PAL/ThirdParty/dav1d/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/Frameworks -include-pch /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/PrecompiledHeaders/SharedPrecompiledHeaders/12902642326230122134/WebCorePrefix.h.gch -D _LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE -D CLANG_WEBKIT_BRANCH=1 -D NDEBUG -D BUILDING_WEBKIT -D GL_SILENCE_DEPRECATION=1 -D GLES_SILENCE_DEPRECATION=1 -D __clang_analyzer__ -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release/WebCore.build/WebCore-own-target-headers.hmap -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release/WebCore.build/WebCore-all-target-headers.hmap -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/include -I PAL -I ForwardingHeaders -I /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/include/libxslt -I /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/include/libxml2 -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/DerivedSources/WebCore -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/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 -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitLibraries/SDKs/macosx15.0-additions.sdk/usr/local/include -I /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/usr/local/include -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/WebKitBuild/PAL.build/PAL.build/DerivedSources -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/PAL.build/Release/PAL.build/DerivedSources -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/Source/WebCore -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release/WebCore.build/DerivedSources-normal/arm64 -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release/WebCore.build/DerivedSources/arm64 -I /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release/WebCore.build/DerivedSources -F/Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release -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 -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 -Wno-unknown-warning-option -Wliteral-conversion -Wthread-safety -Wno-profile-instr-out-of-date -Wno-profile-instr-unprofiled -Wunsafe-buffer-usage -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.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/WebCore/WebCore/normal/arm64/UnifiedSource110.plist -x c++ /Volumes/Data/worker/macOS-Safer-CPP-Checks-EWS/build/WebKitBuild/Release/DerivedSources/WebCore/unified-sources/UnifiedSource110.cpp
1/*
2 * Copyright (C) 2011 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 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "AccessibilityScrollView.h"
28
29#include "AXLoggerBase.h"
30#include "AXObjectCacheInlines.h"
31#include "AXLocalFrame.h"
32#include "AXRemoteFrame.h"
33#include "AccessibilityObjectInlines.h"
34#include "AccessibilityScrollbar.h"
35#include "ContainerNodeInlines.h"
36#include "DocumentView.h"
37#include "FrameInlines.h"
38#include "HTMLFrameOwnerElement.h"
39#include "LocalFrameInlines.h"
40#include "LocalFrameView.h"
41#include "RemoteFrameView.h"
42#include "RenderElement.h"
43#include "Widget.h"
44
45namespace WebCore {
46
47AccessibilityScrollView::AccessibilityScrollView(AXID axID, ScrollView& view, AXObjectCache& cache)
48 : AccessibilityObject(axID, cache)
49 , m_childrenDirty(false)
50 , m_scrollView(view)
51{
52 if (RefPtr localFrameView = dynamicDowncast<LocalFrameView>(view))
53 m_frameOwnerElement = localFrameView->frame().ownerElement();
54 else if (RefPtr remoteFrameView = dynamicDowncast<RemoteFrameView>(view))
55 m_frameOwnerElement = remoteFrameView->frame().ownerElement();
56}
57
58AccessibilityScrollView::~AccessibilityScrollView()
59{
60 AX_ASSERT(isDetached())((void)0);
61}
62
63bool AccessibilityScrollView::isRoot() const
64{
65 RefPtr frameView = dynamicDowncast<FrameView>(m_scrollView.get());
66
67#if ENABLE(ACCESSIBILITY_LOCAL_FRAME)(defined 0 && 0)
68 // A remote frame is not a root.
69 if (frameView && frameView->isRemoteFrameView())
70 return false;
71
72 // Interpret this as "is this the root of the local frame"
73 WeakPtr cache = axObjectCache();
74 if (!cache)
75 return false;
76
77 return document() == cache->document();
78#else
79 // Interpret this as "is this the root of the whole page"
80 return frameView && frameView->frame().isMainFrame();
81#endif
82}
83
84String AccessibilityScrollView::ownerDebugDescription() const
85{
86 if (!m_frameOwnerElement) {
87 StringBuilder builder;
88 builder.append("null frame owner"_s);
89 if (isRoot())
90 builder.append(" (root)"_s);
91 return builder.toString();
92 }
93
94 CheckedPtr renderer = m_frameOwnerElement->renderer();
95 return makeString("owned by: "_s, renderer ? renderer->debugDescription() : protect(frameOwnerElement())->debugDescription());
96}
97
98String AccessibilityScrollView::extraDebugInfo() const
99{
100 Vector<String> debugStrings = { ownerDebugDescription(), AccessibilityObject::extraDebugInfo() };
101 return makeStringByJoining(debugStrings, ","_s);
102}
103
104void AccessibilityScrollView::detachRemoteParts(AccessibilityDetachmentType detachmentType)
105{
106 AccessibilityObject::detachRemoteParts(detachmentType);
107
108 RefPtr remoteFrameView = dynamicDowncast<RemoteFrameView>(m_scrollView.get());
109 if (remoteFrameView && m_remoteFrame && (detachmentType == AccessibilityDetachmentType::ElementDestroyed || detachmentType == AccessibilityDetachmentType::CacheDestroyed)) {
110#if PLATFORM(MAC)(defined 1 && 1)
111 Ref remoteFrame = remoteFrameView->frame();
112 remoteFrame->unbindRemoteAccessibilityFrames(m_remoteFrame->remoteFramePID());
Call argument for 'this' parameter is uncounted and unsafe
113#endif
114 m_remoteFrame = nullptr;
115 }
116
117 m_scrollView = nullptr;
118 m_frameOwnerElement = nullptr;
119}
120
121Ref<AccessibilityScrollView> AccessibilityScrollView::create(AXID axID, ScrollView& view, AXObjectCache& cache)
122{
123 return adoptRef(*new AccessibilityScrollView(axID, view, cache));
124}
125
126ScrollView* AccessibilityScrollView::currentScrollView() const
127{
128 return m_scrollView ? m_scrollView.get() : documentFrameView();
129}
130
131AccessibilityObject* AccessibilityScrollView::scrollBar(AccessibilityOrientation orientation)
132{
133 updateScrollbars();
134
135 switch (orientation) {
136 // ARIA 1.1 Elements with the role scrollbar have an implicit aria-orientation value of vertical.
137 case AccessibilityOrientation::Undefined:
138 case AccessibilityOrientation::Vertical:
139 return m_verticalScrollbar ? m_verticalScrollbar.get() : nullptr;
140 case AccessibilityOrientation::Horizontal:
141 return m_horizontalScrollbar ? m_horizontalScrollbar.get() : nullptr;
142 }
143
144 return nullptr;
145}
146
147// If this is WebKit1 then the native scroll view needs to return the
148// AX information (because there are no scroll bar children in the ScrollView object in WK1).
149// In WebKit2, the ScrollView object will return the AX information (because there are no platform widgets).
150bool AccessibilityScrollView::isAttachment() const
151{
152 if (RefPtr scrollView = currentScrollView())
153 return scrollView->platformWidget();
154 return false;
155}
156
157PlatformWidget AccessibilityScrollView::platformWidget() const
158{
159 if (RefPtr scrollView = currentScrollView())
160 return scrollView->platformWidget();
161 return nullptr;
162}
163
164bool AccessibilityScrollView::canSetFocusAttribute() const
165{
166 RefPtr webArea = webAreaObject();
167 return webArea && webArea->canSetFocusAttribute();
168}
169
170bool AccessibilityScrollView::isFocused() const
171{
172 RefPtr webArea = webAreaObject();
173 return webArea && webArea->isFocused();
174}
175
176void AccessibilityScrollView::setFocused(bool focused)
177{
178 // Call the base class setFocused to ensure the view is focused and active.
179 AccessibilityObject::setFocused(focused);
180
181 if (RefPtr webArea = webAreaObject())
182 webArea->setFocused(focused);
183}
184
185void AccessibilityScrollView::updateChildrenIfNecessary()
186{
187 // Always update our children when asked for them so that we don't inadvertently cache them after
188 // a new web area has been created for this scroll view (like when moving back and forth through history).
189 // Since a ScrollViews children will always be relatively small and limited this should not be a performance problem.
190 clearChildren();
191 addChildren();
192}
193
194void AccessibilityScrollView::updateScrollbars()
195{
196 RefPtr scrollView = currentScrollView();
197 if (!scrollView)
198 return;
199
200 bool shouldHideScrollBars = isWithinHiddenWebArea();
201
202#if ENABLE(ACCESSIBILITY_LOCAL_FRAME)(defined 0 && 0)
203 if (!isRoot())
204 shouldHideScrollBars = true;
205#endif
206
207 if (shouldHideScrollBars) {
208 removeChildScrollbar(m_horizontalScrollbar.get());
209 m_horizontalScrollbar = nullptr;
210
211 removeChildScrollbar(m_verticalScrollbar.get());
212 m_verticalScrollbar = nullptr;
213 return;
214 }
215
216 if (scrollView->horizontalScrollbar() && !m_horizontalScrollbar)
217 m_horizontalScrollbar = addChildScrollbar(protect(scrollView->horizontalScrollbar()).get());
218 else if (!scrollView->horizontalScrollbar() && m_horizontalScrollbar) {
219 removeChildScrollbar(m_horizontalScrollbar.get());
220 m_horizontalScrollbar = nullptr;
221 }
222
223 if (scrollView->verticalScrollbar() && !m_verticalScrollbar)
224 m_verticalScrollbar = addChildScrollbar(protect(scrollView->verticalScrollbar()).get());
225 else if (!scrollView->verticalScrollbar() && m_verticalScrollbar) {
226 removeChildScrollbar(m_verticalScrollbar.get());
227 m_verticalScrollbar = nullptr;
228 }
229}
230
231void AccessibilityScrollView::removeChildScrollbar(AccessibilityObject* scrollbar)
232{
233 if (!scrollbar)
234 return;
235
236 size_t position = m_children.findIf([&scrollbar] (const Ref<AXCoreObject>& child) {
237 return child.ptr() == scrollbar;
238 });
239 if (position != notFound) {
240 Ref { m_children[position] }->detachFromParent();
241 m_children.removeAt(position);
242 resetChildrenIndexInParent();
243
244 if (CheckedPtr cache = axObjectCache())
245 cache->remove(scrollbar->objectID());
246 }
247}
248
249AccessibilityScrollbar* AccessibilityScrollView::addChildScrollbar(Scrollbar* scrollbar)
250{
251 if (!scrollbar)
252 return nullptr;
253
254 WeakPtr cache = axObjectCache();
255 if (!cache)
256 return nullptr;
257
258 Ref scrollBarObject = uncheckedDowncast<AccessibilityScrollbar>(*cache->getOrCreate(*scrollbar));
259 scrollBarObject->setParent(this);
260 addChild(scrollBarObject.get());
261 return scrollBarObject.unsafePtr();
262}
263
264void AccessibilityScrollView::clearChildren()
265{
266 AccessibilityObject::clearChildren();
267
268 m_verticalScrollbar = nullptr;
269 m_horizontalScrollbar = nullptr;
270
271 m_childrenDirty = false;
272}
273
274AccessibilityRole AccessibilityScrollView::determineAccessibilityRole()
275{
276#if ENABLE(ACCESSIBILITY_LOCAL_FRAME)(defined 0 && 0)
277 if (!isRoot())
278 return AccessibilityRole::FrameHost;
279#endif
280
281 return AccessibilityRole::ScrollArea;
282}
283
284bool AccessibilityScrollView::computeIsIgnored() const
285{
286#if ENABLE(ACCESSIBILITY_LOCAL_FRAME)(defined 0 && 0)
287 WeakPtr cache = axObjectCache();
288 if (!cache)
289 return true;
290
291 // If this is the child of an iframe element, ignore it in favor of the scroll view from the frame's AXObjectCache.
292 if (!isRoot())
293 return true;
294#endif
295
296 // Scroll view's that host remote frames won't have web area objects, but shouldn't be ignored so that they are also available in the isolated tree.
297 if (m_remoteFrame)
298 return false;
299
300 RefPtr webArea = webAreaObject();
301 if (!webArea)
302 return true;
303
304 return webArea->isIgnored();
305}
306
307void AccessibilityScrollView::addLocalFrameChild()
308{
309#if ENABLE(ACCESSIBILITY_LOCAL_FRAME)(defined 0 && 0)
310 WeakPtr cache = axObjectCache();
311 if (!cache)
312 return;
313
314 if (!m_localFrame) {
315 RefPtr localFrameView = dynamicDowncast<LocalFrameView>(m_scrollView.get());
316 if (!localFrameView)
317 return;
318
319 RefPtr localFrame = localFrameView->frame();
320 if (!localFrame)
321 return;
322
323 RefPtr document = localFrame->document();
324 if (!document)
325 return;
326
327 WeakPtr frameAXObjectCache = document->axObjectCache();
328 if (!frameAXObjectCache)
329 return;
330
331#if ENABLE(ACCESSIBILITY_ISOLATED_TREE)(defined 1 && 1)
332 frameAXObjectCache->buildIsolatedTreeIfNeeded();
333#endif
334
335 RefPtr frameRoot = frameAXObjectCache->rootObjectForFrame(*localFrame);
336 if (!frameRoot)
337 return;
338
339 // Set the initial hosting node state on the child frame's root scroll view.
340 if (RefPtr childScrollView = dynamicDowncast<AccessibilityScrollView>(frameRoot.get()))
341 childScrollView->setInheritedFrameState({ isHostingFrameHidden(), isHostingFrameInert(), isHostingFrameRenderHidden() });
342
343 m_localFrame = downcast<AXLocalFrame>(cache->create(AccessibilityRole::LocalFrame));
344 m_localFrame->setLocalFrameView(localFrameView.get());
345 m_localFrame->setWrapper(frameRoot->wrapper());
346 }
347
348 m_localFrame->setParent(this);
349 addChild(*m_localFrame);
350#endif // ENABLE(ACCESSIBILITY_LOCAL_FRAME)
351}
352
353void AccessibilityScrollView::addRemoteFrameChild()
354{
355 RefPtr scrollFrameView = dynamicDowncast<RemoteFrameView>(m_scrollView.get());
356 if (!scrollFrameView)
357 return;
358
359 WeakPtr cache = axObjectCache();
360 if (!cache)
361 return;
362
363 RefPtr remoteFrame = m_remoteFrame;
364 if (!remoteFrame) {
365 // Make the faux element that represents the remote transfer element for AX.
366 m_remoteFrame = downcast<AXRemoteFrame>(cache->create(AccessibilityRole::RemoteFrame));
367 remoteFrame = m_remoteFrame;
368 remoteFrame->setParent(this);
369
370#if PLATFORM(COCOA)(defined 1 && 1)
371 // Generate a new token and pass it back to the other remote frame so it can bind these objects together.
372 Ref scrollFrame = scrollFrameView->frame();
373 remoteFrame->setFrameID(scrollFrame->frameID());
374 scrollFrame->bindRemoteAccessibilityFrames(getpid(), remoteFrame->generateRemoteToken(), [this, protectedThis = Ref { *this }, weakScrollFrame = WeakPtr { scrollFrame.get() }, protectedRemoteFrame = Ref { *remoteFrame }] (AccessibilityRemoteToken token, int processIdentifier) mutable {
375 protectedRemoteFrame->initializePlatformElementWithRemoteToken(token, processIdentifier);
376
377 RefPtr scrollFrame = weakScrollFrame.get();
378 if (!scrollFrame)
379 return;
380
381 // Update the remote side with the offset of this object so it can calculate frames correctly.
382 auto location = elementRect().location();
383 scrollFrame->updateRemoteFrameAccessibilityOffset(flooredIntPoint(location));
384
385#if ENABLE(ACCESSIBILITY_LOCAL_FRAME)(defined 0 && 0)
386 // Send initial InheritedFrameState via IPC.
387 scrollFrame->updateRemoteFrameAccessibilityInheritedState({ isHostingFrameHidden(), isHostingFrameInert(), isHostingFrameRenderHidden() });
388#endif
389 });
390#endif // PLATFORM(COCOA)
391 } else
392 remoteFrame->setParent(this);
393
394 addChild(*remoteFrame);
395}
396
397void AccessibilityScrollView::addChildren()
398{
399 AX_ASSERT(!m_childrenInitialized)((void)0);
400 m_childrenInitialized = true;
401
402#if ENABLE(ACCESSIBILITY_LOCAL_FRAME)(defined 0 && 0)
403 if (isRoot())
404 addChild(webAreaObject());
405 else {
406 // Always add frame children, even if ignored. Ignored state propagates naturally through the tree.
407 addLocalFrameChild();
408 addRemoteFrameChild();
409 }
410#else
411 addRemoteFrameChild();
412 addChild(RefPtr { webAreaObject() }.get());
413#endif
414
415 updateScrollbars();
416
417#ifndef NDEBUG1
418 verifyChildrenIndexInParent();
419#endif
420}
421
422AccessibilityObject* AccessibilityScrollView::webAreaObject() const
423{
424 RefPtr document = this->document();
425 if (!document || !document->hasLivingRenderTree() || m_remoteFrame)
426 return nullptr;
427
428 if (CheckedPtr cache = axObjectCache())
429 return cache->getOrCreate(*document);
430
431 return nullptr;
432}
433
434RefPtr<AXCoreObject> AccessibilityScrollView::accessibilityHitTest(const IntPoint& point) const
435{
436 RefPtr webArea = webAreaObject();
437 if (!webArea)
438 return nullptr;
439
440 if (m_horizontalScrollbar && protect(m_horizontalScrollbar)->elementRect().contains(point))
441 return m_horizontalScrollbar.get();
442 if (m_verticalScrollbar && protect(m_verticalScrollbar)->elementRect().contains(point))
443 return m_verticalScrollbar.get();
444
445 return webArea->accessibilityHitTest(point);
446}
447
448LayoutRect AccessibilityScrollView::elementRect() const
449{
450 RefPtr scrollView = currentScrollView();
451 return scrollView ? scrollView->frameRectShrunkByInset() : LayoutRect();
452}
453
454Document* AccessibilityScrollView::document() const
455{
456 if (RefPtr frameView = dynamicDowncast<LocalFrameView>(m_scrollView.get()))
457 return frameView->frame().document();
458
459 // For the RemoteFrameView case, we need to return the document of our hosting parent so axObjectCache() resolves correctly.
460 if (RefPtr remoteFrameView = dynamicDowncast<RemoteFrameView>(m_scrollView.get())) {
461 if (auto* owner = remoteFrameView->frame().ownerElement())
462 return &(owner->document());
463 }
464
465 return AccessibilityObject::document();
466}
467
468LocalFrameView* AccessibilityScrollView::documentFrameView() const
469{
470 if (auto* localFrameView = dynamicDowncast<LocalFrameView>(m_scrollView.get()))
471 return localFrameView;
472
473 RefPtr element = m_frameOwnerElement.get();
474 if (element && element->contentDocument())
475 return element->contentDocument()->view();
476 return nullptr;
477}
478
479AccessibilityObject* AccessibilityScrollView::parentObject() const
480{
481 WeakPtr cache = axObjectCache();
482 if (!cache)
483 return nullptr;
484
485#if ENABLE(ACCESSIBILITY_LOCAL_FRAME)(defined 0 && 0)
486 if (isRoot())
487 return nullptr;
488#endif
489
490 RefPtr<Element> ancestorElement;
491 ancestorElement = m_frameOwnerElement.get();
492 if (RefPtr localFrameView = dynamicDowncast<LocalFrameView>(m_scrollView.get()))
493 ancestorElement = localFrameView->frame().ownerElement();
494
495 if (!ancestorElement) {
496 if (RefPtr remoteFrameView = dynamicDowncast<RemoteFrameView>(m_scrollView.get()))
497 ancestorElement = remoteFrameView->frame().ownerElement();
498 }
499
500 RefPtr<AccessibilityObject> ancestorAccessibilityObject;
501 while (ancestorElement && !ancestorAccessibilityObject) {
502 if ((ancestorAccessibilityObject = cache->getOrCreate(*ancestorElement)))
503 break;
504 ancestorElement = ancestorElement->parentElementInComposedTree();
505 }
506 return ancestorAccessibilityObject.unsafeGet();
507}
508
509#if ENABLE(ACCESSIBILITY_LOCAL_FRAME)(defined 0 && 0)
510
511AccessibilityObject* AccessibilityScrollView::crossFrameParentObject() const
512{
513 WeakPtr cache = axObjectCache();
514 if (!cache)
515 return nullptr;
516
517 // If this is the child of an iframe element, do nothing.
518 if (!isRoot())
519 return nullptr;
520
521 // If this is the main frame, do nothing.
522 RefPtr frameView = dynamicDowncast<FrameView>(m_scrollView.get());
523 if (!frameView)
524 return nullptr;
525 if (frameView->frame().isMainFrame())
526 return nullptr;
527
528 RefPtr<Element> ancestorElement;
529 ancestorElement = m_frameOwnerElement.get();
530 if (RefPtr localFrameView = dynamicDowncast<LocalFrameView>(m_scrollView.get()))
531 ancestorElement = localFrameView->frame().ownerElement();
532
533 if (!ancestorElement)
534 return nullptr;
535
536 RefPtr ancestorDocument = ancestorElement->document();
537 if (!ancestorDocument || ancestorDocument.get() == cache->document())
538 return nullptr;
539
540 WeakPtr ancestorCache = ancestorDocument->axObjectCache();
541 RefPtr<AccessibilityObject> ancestorAccessibilityObject;
542 while (ancestorElement && !ancestorAccessibilityObject) {
543 if ((ancestorAccessibilityObject = ancestorCache->getOrCreate(*ancestorElement)))
544 break;
545 ancestorElement = ancestorElement->parentElementInComposedTree();
546 }
547
548 if (ancestorAccessibilityObject && ancestorAccessibilityObject->isIgnored())
549 return ancestorAccessibilityObject->parentObjectUnignored();
550
551 // TODO: this should return a RefPtr
552 return ancestorAccessibilityObject.unsafeGet(); // NOLINT
553}
554
555AccessibilityObject* AccessibilityScrollView::crossFrameChildObject() const
556{
557 return nullptr;
558}
559
560bool AccessibilityScrollView::isAXHidden() const
561{
562 // If this is the root scroll view, use the inherited state from the parent frame.
563 if (isRoot())
564 return m_inheritedFrameState.isAXHidden;
565
566 return AccessibilityObject::isAXHidden();
567}
568
569bool AccessibilityScrollView::isARIAHidden() const
570{
571 // This is necessary to implement on root scrollviews so that the base isAXHidden ancestor traversal works as expected.
572 // If this is the root scroll view, use the inherited state from the parent frame.
573 if (isRoot())
574 return m_inheritedFrameState.isAXHidden;
575
576 return AccessibilityObject::isARIAHidden();
577}
578
579bool AccessibilityScrollView::isHostingFrameInert() const
580{
581 if (isRoot())
582 return m_inheritedFrameState.isInert;
583
584 RefPtr frameOwner = frameOwnerElement();
585 if (CheckedPtr renderer = frameOwner ? frameOwner->renderer() : nullptr)
586 return renderer->style().effectiveInert();
587
588 return false;
589}
590
591bool AccessibilityScrollView::isHostingFrameRenderHidden() const
592{
593 if (isRoot())
594 return m_inheritedFrameState.isRenderHidden;
595
596 RefPtr frameOwner = frameOwnerElement();
597 if (CheckedPtr renderer = frameOwner ? frameOwner->renderer() : nullptr)
598 return WebCore::isRenderHidden(renderer->style());
599
600 return false;
601}
602
603void AccessibilityScrollView::setInheritedFrameState(InheritedFrameState state)
604{
605 if (m_inheritedFrameState.isAXHidden == state.isAXHidden
606 && m_inheritedFrameState.isInert == state.isInert
607 && m_inheritedFrameState.isRenderHidden == state.isRenderHidden)
608 return;
609
610 m_inheritedFrameState = state;
611
612#if ENABLE(INCLUDE_IGNORED_IN_CORE_AX_TREE)(defined 1 && 1)
613 recomputeIsIgnoredForDescendants(/* includeSelf */ true);
614#else
615 if (WeakPtr cache = axObjectCache())
616 cache->childrenChanged(this);
617#endif
618}
619
620void AccessibilityScrollView::updateHostedFrameInheritedState()
621{
622 if (m_localFrame) {
623 RefPtr localFrameView = m_localFrame->localFrameView();
624 if (!localFrameView)
625 return;
626
627 RefPtr document = localFrameView->frame().document();
628 if (!document)
629 return;
630
631 WeakPtr hostedFrameCache = document->axObjectCache();
632 if (!hostedFrameCache)
633 return;
634
635 RefPtr hostedFrameScrollView = dynamicDowncast<AccessibilityScrollView>(hostedFrameCache->rootObjectForFrame(localFrameView->frame()));
636 if (!hostedFrameScrollView)
637 return;
638
639 InheritedFrameState state = { isHostingFrameHidden(), isHostingFrameInert(), isHostingFrameRenderHidden() };
640 hostedFrameScrollView->setInheritedFrameState(state);
641 }
642
643 if (m_remoteFrame) {
644 RefPtr remoteFrameView = dynamicDowncast<RemoteFrameView>(m_scrollView.get());
645 if (!remoteFrameView)
646 return;
647
648 Ref remoteFrame = remoteFrameView->frame();
649 InheritedFrameState state = { isHostingFrameHidden(), isHostingFrameInert(), isHostingFrameRenderHidden() };
650 remoteFrame->updateRemoteFrameAccessibilityInheritedState(state);
651 }
652}
653
654#endif // ENABLE(ACCESSIBILITY_LOCAL_FRAME)
655
656
657void AccessibilityScrollView::scrollTo(const IntPoint& point) const
658{
659 if (RefPtr scrollView = currentScrollView())
660 scrollView->setScrollPosition(point);
661}
662
663} // namespace WebCore