Bug Summary

File:Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/Source/WebCore/Modules/model-element/HTMLModelElement.cpp
Warning:line 1291, column 9
Call argument for 'this' parameter is uncounted and unsafe

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple arm64-apple-ios26.2.0-simulator -O3 -Wundef-prefix=TARGET_OS_ -Werror=undef-prefix -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -Werror=implicit-function-declaration -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name UnifiedSource70.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/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.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/Apple-iOS-26-Safer-CPP-Checks-EWS/build/Source/WebCore -target-linker-version 1230.1 -fcoverage-compilation-dir=/Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/Source/WebCore -resource-dir /Users/buildbot/Library/Developer/Toolchains/swift-webkit.xctoolchain/usr/lib/clang/21 -dependency-file /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/scan-build-output/StaticAnalyzer/WebCore/WebCore/normal/arm64/UnifiedSource70.d -skip-unused-modulemap-deps -MT dependencies -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.sdk -iquote /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release-iphonesimulator/WebCore.build/WebCore-generated-files.hmap -iquote /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release-iphonesimulator/WebCore.build/WebCore-project-headers.hmap -isystem /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/Source/WebCore/PAL/ThirdParty/dav1d/include -isystem /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/Release-iphonesimulator/SDKAdditions/usr/include -iframework /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/Release-iphonesimulator/SDKAdditions/System/Library/Frameworks -iframework /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitLibraries/SDKs/iphonesimulator26.0-additions.sdk/System/Library/PrivateFrameworks -iframework /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.sdk/System/Library/Frameworks -include-pch /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/PrecompiledHeaders/SharedPrecompiledHeaders/11721353671419897710/WebCorePrefix.h.gch -D _LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE -D NDEBUG -D BUILDING_WEBKIT -D GL_SILENCE_DEPRECATION=1 -D GLES_SILENCE_DEPRECATION=1 -D __clang_analyzer__ -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release-iphonesimulator/WebCore.build/WebCore-own-target-headers.hmap -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release-iphonesimulator/WebCore.build/WebCore-all-target-headers.hmap -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/Release-iphonesimulator/include -I PAL -I ForwardingHeaders -I /usr/include/libxslt -I /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.sdk/usr/include/libxml2 -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/Release-iphonesimulator/DerivedSources/WebCore -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/Release-iphonesimulator/usr/local/include -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/Release-iphonesimulator/usr/local/include/WebKitAdditions -I /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.sdk/usr/local/include/WebKitAdditions -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/Release-iphonesimulator/usr/local/include -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitLibraries/SDKs/iphonesimulator26.0-additions.sdk/usr/local/include -I /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.sdk/usr/local/include -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/Release-iphonesimulator/usr/local/include/webrtc -I /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.sdk/usr/local/include/webrtc -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/Release-iphonesimulator/usr/local/include/webm -I /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.sdk/usr/local/include/webm -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/PAL.build/PAL.build/DerivedSources -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/PAL.build/Release-iphonesimulator/PAL.build/DerivedSources -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/Source/WebCore -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release-iphonesimulator/WebCore.build/DerivedSources-normal/arm64 -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release-iphonesimulator/WebCore.build/DerivedSources/arm64 -I /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/WebCore.build/Release-iphonesimulator/WebCore.build/DerivedSources -F/Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/Release-iphonesimulator -F/Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/Release-iphonesimulator -I/usr/local/include -stdlib=libc++ -internal-isystem /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.sdk/usr/include/c++/v1 -internal-isystem /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.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/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.sdk/usr/include -internal-iframework /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.sdk/System/Library/Frameworks -internal-iframework /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.2.sdk/System/Library/SubFrameworks -internal-iframework /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator26.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 -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 -Wno-backend-plugin -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/Apple-iOS-26-Safer-CPP-Checks-EWS/build/scan-build-output/StaticAnalyzer/WebCore/WebCore/normal/arm64/UnifiedSource70.plist -x c++ /Volumes/Data/worker/Apple-iOS-26-Safer-CPP-Checks-EWS/build/WebKitBuild/Release-iphonesimulator/DerivedSources/WebCore/unified-sources/UnifiedSource70.cpp
1/*
2 * Copyright (C) 2020-2025 Apple Inc. All rights reserved.
3 * Copyright (C) 2025 Samuel Weinig <sam@webkit.org>
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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 INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "config.h"
28#include "HTMLModelElement.h"
29
30#if ENABLE(MODEL_ELEMENT)(defined 1 && 1)
31
32#include "AbortSignal.h"
33#include "ContainerNodeInlines.h"
34#include "DOMMatrixReadOnly.h"
35#include "DOMPointReadOnly.h"
36#include "DOMPromiseProxy.h"
37#include "DocumentEventLoop.h"
38#include "DocumentPage.h"
39#include "DocumentResourceLoader.h"
40#include "DocumentView.h"
41#include "ElementChildIteratorInlines.h"
42#include "ElementInlines.h"
43#include "EventHandler.h"
44#include "EventNames.h"
45#include "Exception.h"
46#include "FloatPoint3D.h"
47#include "FrameDestructionObserverInlines.h"
48#include "GraphicsLayer.h"
49#include "GraphicsLayerCA.h"
50#include "HTMLModelElementCamera.h"
51#include "HTMLNames.h"
52#include "HTMLParserIdioms.h"
53#include "HTMLSourceElement.h"
54#include "JSDOMPromiseDeferred.h"
55#include "JSEventTarget.h"
56#include "JSHTMLModelElement.h"
57#include "JSHTMLModelElementCamera.h"
58#include "LayoutRect.h"
59#include "LayoutSize.h"
60#include "LazyLoadModelObserver.h"
61#include "LegacySchemeRegistry.h"
62#include "Logging.h"
63#include "MIMETypeRegistry.h"
64#include "Model.h"
65#include "ModelPlayer.h"
66#include "ModelPlayerAnimationState.h"
67#include "ModelPlayerGraphicsLayerConfiguration.h"
68#include "ModelPlayerProvider.h"
69#include "ModelPlayerTransformState.h"
70#include "MouseEvent.h"
71#include "NodeInlines.h"
72#include "Page.h"
73#include "PlaceholderModelPlayer.h"
74#include "RenderBoxInlines.h"
75#include "RenderLayer.h"
76#include "RenderLayerBacking.h"
77#include "RenderLayerModelObject.h"
78#include "RenderModel.h"
79#include "RenderReplaced.h"
80#include "ScriptController.h"
81#include "Settings.h"
82#include <JavaScriptCore/ConsoleTypes.h>
83#include <wtf/Seconds.h>
84#include <wtf/TZoneMallocInlines.h>
85#include <wtf/URL.h>
86
87#if ENABLE(MODEL_CONTEXT)(defined (0 || 0) && (0 || 0))
88#include "ModelContext.h"
89#endif
90
91#if ENABLE(MODEL_ELEMENT_IMMERSIVE)(defined ENABLE_MODEL_ELEMENT_IMMERSIVE && ENABLE_MODEL_ELEMENT_IMMERSIVE
)
92#include "DocumentImmersive.h"
93#endif
94
95#if ENABLE(TOUCH_EVENTS)(defined 0 && 0) && ENABLE(GPU_PROCESS_MODEL)(defined 0 && 0)
96#include <WebCore/TouchEvent.h>
97#endif
98
99namespace WebCore {
100
101using namespace HTMLNames;
102
103WTF_MAKE_TZONE_ALLOCATED_IMPL(HTMLModelElement)::bmalloc::api::HeapRef HTMLModelElement::s_heapRef; const TZoneSpecification
HTMLModelElement::s_heapSpec = { &HTMLModelElement::s_heapRef
, TZoneSpecification::encodeSize<HTMLModelElement>(), TZoneSpecification
::encodeAlignment<HTMLModelElement>(), TZoneSpecification
::encodeCategory<HTMLModelElement>(), ::bmalloc::api::compactAllocationMode
<HTMLModelElement>(), TZoneSpecification::encodeDescriptor
<HTMLModelElement>(), }; void* HTMLModelElement::operatorNewSlow
(size_t size) { if constexpr (::bmalloc::api::compactAllocationMode
<HTMLModelElement>() == CompactAllocationMode::Compact)
return ::bmalloc::api::tzoneAllocateCompactSlow(size, s_heapSpec
); return ::bmalloc::api::tzoneAllocateNonCompactSlow(size, s_heapSpec
); } using __makeBtzoneMallocedInlineMacroSemicolonifier __attribute__
((unused)) = int
;
104
105static const Seconds reloadModelDelay { 1_s };
106
107#if ENABLE(TOUCH_EVENTS)(defined 0 && 0)
108class HTMLModelElementEventListener final : public EventListener {
109public:
110 static Ref<HTMLModelElementEventListener> create()
111 {
112 return adoptRef(*new HTMLModelElementEventListener());
113 }
114
115 void handleEvent(ScriptExecutionContext&, Event&) override { }
116
117private:
118 explicit HTMLModelElementEventListener()
119 : EventListener(EventListener::CPPEventListenerType)
120 { }
121};
122#endif
123
124HTMLModelElement::HTMLModelElement(const QualifiedName& tagName, Document& document)
125 : HTMLElement(tagName, document, { TypeFlag::HasCustomStyleResolveCallbacks, TypeFlag::HasDidMoveToNewDocument })
126 , ActiveDOMObject(document)
127 , m_readyPromise { makeUniqueRef<ReadyPromise>(*this, &HTMLModelElement::readyPromiseResolve) }
128#if ENABLE(MODEL_ELEMENT_ENTITY_TRANSFORM)(defined (0 || 0) && (0 || 0))
129 , m_entityTransform(DOMMatrixReadOnly::create(TransformationMatrix::identity, DOMMatrixReadOnly::Is2D::No))
130#endif
131#if ENABLE(MODEL_ELEMENT_BOUNDING_BOX)(defined (0 || 0) && (0 || 0))
132 , m_boundingBoxCenter(DOMPointReadOnly::create({ }))
133 , m_boundingBoxExtents(DOMPointReadOnly::create({ }))
134#endif
135#if ENABLE(MODEL_ELEMENT_ENVIRONMENT_MAP)(defined (0 || 0) && (0 || 0))
136 , m_environmentMapReadyPromise(makeUniqueRef<EnvironmentMapPromise>())
137#endif
138{
139}
140
141HTMLModelElement::~HTMLModelElement()
142{
143 if (m_resource) {
144 m_resource->removeClient(*this);
145 m_resource = nullptr;
146 }
147
148#if ENABLE(MODEL_ELEMENT_ENVIRONMENT_MAP)(defined (0 || 0) && (0 || 0))
149 if (m_environmentMapResource) {
150 m_environmentMapResource->removeClient(*this);
151 m_environmentMapResource = nullptr;
152 }
153#endif
154
155 LazyLoadModelObserver::unobserve(*this, protect(document()));
156
157 m_loadModelTimer = nullptr;
158
159 deleteModelPlayer();
160}
161
162Ref<HTMLModelElement> HTMLModelElement::create(const QualifiedName& tagName, Document& document)
163{
164 auto model = adoptRef(*new HTMLModelElement(tagName, document));
165 model->suspendIfNeeded();
166 return model;
167}
168
169void HTMLModelElement::suspend(ReasonForSuspension reasonForSuspension)
170{
171 RELEASE_LOG(ModelElement, "%p - HTMLModelElement::suspend(): %d", this, static_cast<int>(reasonForSuspension))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 = (LogModelElement
.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
("%p - HTMLModelElement::suspend(): %d"), "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_LOG19"
) = "%p - HTMLModelElement::suspend(): %d"; uint8_t _Alignas(
16) __attribute__((uninitialized)) _os_fmt_buf[__builtin_os_log_format_buffer_size
("%p - HTMLModelElement::suspend(): %d", this, static_cast<
int>(reasonForSuspension))]; _os_log_impl(&__dso_handle
, _log_tmp, _type_tmp, _os_fmt_str, (uint8_t *)__builtin_os_log_format
(_os_fmt_buf, "%p - HTMLModelElement::suspend(): %d", this, static_cast
<int>(reasonForSuspension)), (uint32_t)sizeof(_os_fmt_buf
)) clang diagnostic pop ; }); } }) clang diagnostic pop
;
172
173 if (reasonForSuspension == ReasonForSuspension::BackForwardCache)
174 unloadModelPlayer(true);
175}
176
177void HTMLModelElement::resume()
178{
179 RELEASE_LOG(ModelElement, "%p - HTMLModelElement::resume()", this)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 = (LogModelElement
.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
("%p - HTMLModelElement::resume()"), "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_LOG20"
) = "%p - HTMLModelElement::resume()"; uint8_t _Alignas(16) __attribute__
((uninitialized)) _os_fmt_buf[__builtin_os_log_format_buffer_size
("%p - HTMLModelElement::resume()", this)]; _os_log_impl(&
__dso_handle, _log_tmp, _type_tmp, _os_fmt_str, (uint8_t *)__builtin_os_log_format
(_os_fmt_buf, "%p - HTMLModelElement::resume()", this), (uint32_t
)sizeof(_os_fmt_buf)) clang diagnostic pop ; }); } }) clang diagnostic
pop
;
180 startLoadModelTimer();
181}
182
183RefPtr<Model> HTMLModelElement::model() const
184{
185 if (!m_dataComplete)
186 return nullptr;
187
188 return m_model;
189}
190
191static bool isSupportedModelType(const AtomString& type)
192{
193 return type.isEmpty() || MIMETypeRegistry::isSupportedModelMIMEType(type);
194}
195
196URL HTMLModelElement::selectModelSource() const
197{
198 // FIXME: This should probably work more like media element resource
199 // selection, where if a <source> element fails to load, an error event
200 // is dispatched to it, and we continue to try subsequent <source>s.
201
202 if (!document().hasBrowsingContext())
203 return { };
204
205 if (auto src = getNonEmptyURLAttribute(srcAttr); src.isValid())
206 return src;
207
208 for (Ref element : childrenOfType<HTMLSourceElement>(*this)) {
209 if (!isSupportedModelType(element->attributeWithoutSynchronization(typeAttr)))
210 continue;
211
212 if (auto src = element->getNonEmptyURLAttribute(srcAttr); src.isValid())
213 return src;
214 }
215
216 return { };
217}
218
219void HTMLModelElement::sourcesChanged()
220{
221 setSourceURL(selectModelSource());
222}
223
224CachedResourceRequest HTMLModelElement::createResourceRequest(const URL& resourceURL, FetchOptions::Destination destination)
225{
226 ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
227 options.destination = destination;
228 options.sameOriginDataURLFlag = SameOriginDataURLFlag::Set;
229
230 auto crossOriginAttribute = parseCORSSettingsAttribute(attributeWithoutSynchronization(HTMLNames::crossoriginAttr));
231 // Make sure CORS is always enabled by passing a non-null cross origin attribute
232 Ref document = this->document();
233 if (crossOriginAttribute.isNull()) {
234 Ref documentOrigin = document->securityOrigin();
235 if (LegacySchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(documentOrigin->protocol()) || documentOrigin->protocol() != resourceURL.protocol())
236 crossOriginAttribute = "anonymous"_s;
237 }
238 auto request = createPotentialAccessControlRequest(ResourceRequest { URL { resourceURL } }, WTF::move(options), document, crossOriginAttribute);
239 request.setInitiator(*this);
240
241 return request;
242}
243
244void HTMLModelElement::setSourceURL(const URL& url)
245{
246 if (url == m_sourceURL)
247 return;
248
249 m_sourceURL = url;
250
251 m_data.reset();
252 m_dataMemoryCost.store(0, std::memory_order_relaxed);
253 m_dataComplete = false;
254 m_model = nullptr;
255
256 if (m_resource) {
257 m_resource->removeClient(*this);
258 m_resource = nullptr;
259 }
260
261 deleteModelPlayer();
262
263#if ENABLE(MODEL_ELEMENT_ENTITY_TRANSFORM)(defined (0 || 0) && (0 || 0))
264 m_entityTransform = DOMMatrixReadOnly::create(TransformationMatrix::identity, DOMMatrixReadOnly::Is2D::No);
265#endif
266#if ENABLE(MODEL_ELEMENT_BOUNDING_BOX)(defined (0 || 0) && (0 || 0))
267 m_boundingBoxCenter = DOMPointReadOnly::create({ });
268 m_boundingBoxExtents = DOMPointReadOnly::create({ });
269#endif
270
271 if (!m_readyPromise->isFulfilled())
272 m_readyPromise->reject(Exception { ExceptionCode::AbortError });
273
274 triggerModelPlayerCreationCallbacksIfNeeded(Exception { ExceptionCode::AbortError, "The model URL was updated"_s });
275
276 m_readyPromise = makeUniqueRef<ReadyPromise>(*this, &HTMLModelElement::readyPromiseResolve);
277 m_shouldCreateModelPlayerUponRendererAttachment = false;
278
279 if (m_sourceURL.isEmpty()) {
280 ActiveDOMObject::queueTaskToDispatchEvent(*this, TaskSource::DOMManipulation, Event::create(eventNames().errorEvent, Event::CanBubble::No, Event::IsCancelable::No));
281 reportExtraMemoryCost();
282 return;
283 }
284
285 if (shouldDeferLoading())
286 return;
287
288 sourceRequestResource();
289}
290
291HTMLModelElement& HTMLModelElement::readyPromiseResolve()
292{
293 return *this;
294}
295
296// MARK: - VisibilityChangeClient overrides.
297
298void HTMLModelElement::visibilityStateChanged()
299{
300 RefPtr modelPlayer = m_modelPlayer;
301 if (modelPlayer)
302 modelPlayer->visibilityStateDidChange();
303
304 if (!isVisible()) {
305 m_loadModelTimer = nullptr;
306 return;
307 }
308
309 if (modelPlayer && !modelPlayer->isPlaceholder())
310 return;
311
312 startLoadModelTimer();
313}
314
315// MARK: - DOM overrides.
316
317void HTMLModelElement::didMoveToNewDocument(Document& oldDocument, Document& newDocument)
318{
319 ActiveDOMObject::didMoveToNewDocument(newDocument);
320 HTMLElement::didMoveToNewDocument(oldDocument, newDocument);
321 sourcesChanged();
322}
323
324// MARK: - Rendering overrides.
325
326RenderPtr<RenderElement> HTMLModelElement::createElementRenderer(RenderStyle&& style, const RenderTreePosition&)
327{
328 return createRenderer<RenderModel>(*this, WTF::move(style));
329}
330
331void HTMLModelElement::didAttachRenderers()
332{
333 if (!m_shouldCreateModelPlayerUponRendererAttachment)
334 return;
335
336 m_shouldCreateModelPlayerUponRendererAttachment = false;
337 createModelPlayer();
338}
339
340// MARK: - CachedRawResourceClient overrides.
341
342void HTMLModelElement::dataReceived(CachedResource& resource, const SharedBuffer& buffer)
343{
344 if (&resource == m_resource)
345 m_data.append(buffer);
346#if ENABLE(MODEL_ELEMENT_ENVIRONMENT_MAP)(defined (0 || 0) && (0 || 0))
347 else if (&resource == m_environmentMapResource)
348 m_environmentMapData.append(buffer);
349#endif
350 else
351 ASSERT_NOT_REACHED()((void)0);
352}
353
354void HTMLModelElement::notifyFinished(CachedResource& resource, const NetworkLoadMetrics&, LoadWillContinueInAnotherProcess)
355{
356 if (&resource == m_resource)
357 modelResourceFinished();
358#if ENABLE(MODEL_ELEMENT_ENVIRONMENT_MAP)(defined (0 || 0) && (0 || 0))
359 else if (&resource == m_environmentMapResource)
360 environmentMapResourceFinished();
361#endif
362}
363
364// MARK: - ModelPlayerClient overrides.
365
366void HTMLModelElement::didFinishLoading(ModelPlayer& modelPlayer)
367{
368 ASSERT_UNUSED(modelPlayer, &modelPlayer == m_modelPlayer)((void)modelPlayer);
369
370 reportExtraMemoryCost();
371
372 if (CheckedPtr renderer = this->renderer())
373 renderer->updateFromElement();
374 if (!m_readyPromise->isFulfilled())
375 m_readyPromise->resolve(*this);
376}
377
378void HTMLModelElement::didFailLoading(ModelPlayer& modelPlayer, const ResourceError&)
379{
380 ASSERT_UNUSED(modelPlayer, &modelPlayer == m_modelPlayer)((void)modelPlayer);
381 if (!m_readyPromise->isFulfilled())
382 m_readyPromise->reject(Exception { ExceptionCode::AbortError });
383
384 deleteModelPlayer();
385
386 m_dataMemoryCost.store(0, std::memory_order_relaxed);
387 reportExtraMemoryCost();
388}
389
390#if ENABLE(MODEL_PROCESS)(defined 0 && 0)
391
392void HTMLModelElement::didConvertModelData(ModelPlayer& modelPlayer, Ref<SharedBuffer>&& convertedData, const String& convertedMIMEType)
393{
394 ASSERT_UNUSED(modelPlayer, &modelPlayer == m_modelPlayer)((void)modelPlayer);
395 ASSERT(m_dataComplete)((void)0);
396
397 RELEASE_LOG(ModelElement, "%p - HTMLModelElement::didConvertModelData: Received converted model data, size=%zu mimeType=%s", this, convertedData->size(), convertedMIMEType.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 = (LogModelElement
.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
("%p - HTMLModelElement::didConvertModelData: Received converted model data, size=%zu mimeType=%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_LOG21"
) = "%p - HTMLModelElement::didConvertModelData: Received converted model data, size=%zu mimeType=%s"
; uint8_t _Alignas(16) __attribute__((uninitialized)) _os_fmt_buf
[__builtin_os_log_format_buffer_size("%p - HTMLModelElement::didConvertModelData: Received converted model data, size=%zu mimeType=%s"
, this, convertedData->size(), convertedMIMEType.utf8().data
())]; _os_log_impl(&__dso_handle, _log_tmp, _type_tmp, _os_fmt_str
, (uint8_t *)__builtin_os_log_format(_os_fmt_buf, "%p - HTMLModelElement::didConvertModelData: Received converted model data, size=%zu mimeType=%s"
, this, convertedData->size(), convertedMIMEType.utf8().data
()), (uint32_t)sizeof(_os_fmt_buf)) clang diagnostic pop ; })
; } }) clang diagnostic pop
;
398
399 m_model = Model::create(WTF::move(convertedData), String { convertedMIMEType }, m_sourceURL, true /* isConverted */);
400 m_dataMemoryCost.store(m_model->data()->size(), std::memory_order_relaxed);
401 reportExtraMemoryCost();
402}
403
404#endif
405
406#if ENABLE(MODEL_ELEMENT_ENVIRONMENT_MAP)(defined (0 || 0) && (0 || 0))
407
408void HTMLModelElement::didFinishEnvironmentMapLoading(ModelPlayer&, bool succeeded)
409{
410 if (!m_environmentMapURL.isEmpty() && !m_environmentMapReadyPromise->isFulfilled()) {
411 if (succeeded)
412 m_environmentMapReadyPromise->resolve();
413 else {
414 m_environmentMapReadyPromise->reject(Exception { ExceptionCode::AbortError });
415 m_environmentMapDataMemoryCost.store(0, std::memory_order_relaxed);
416 }
417 reportExtraMemoryCost();
418 }
419}
420
421#endif
422
423void HTMLModelElement::didUnload(ModelPlayer& modelPlayer)
424{
425 if (m_modelPlayer != &modelPlayer)
426 return;
427
428 unloadModelPlayer(false);
429
430 if (!isVisible())
431 return;
432
433 // FIXME: rdar://148027600 Prevent infinite reloading of model.
434 startLoadModelTimer();
435}
436
437void HTMLModelElement::didUpdate(ModelPlayer& modelPlayer)
438{
439 ASSERT_UNUSED(modelPlayer, &modelPlayer == m_modelPlayer)((void)modelPlayer);
440
441 if (CheckedPtr renderer = this->renderer())
442 renderer->updateFromElement();
443}
444
445#if ENABLE(MODEL_ELEMENT_ENTITY_TRANSFORM)(defined (0 || 0) && (0 || 0))
446
447void HTMLModelElement::didUpdateEntityTransform(ModelPlayer&, const TransformationMatrix& transform)
448{
449 m_entityTransform = DOMMatrixReadOnly::create(transform, DOMMatrixReadOnly::Is2D::No);
450}
451
452#endif
453
454#if ENABLE(MODEL_ELEMENT_BOUNDING_BOX)(defined (0 || 0) && (0 || 0))
455
456void HTMLModelElement::didUpdateBoundingBox(ModelPlayer&, const FloatPoint3D& center, const FloatPoint3D& extents)
457{
458 m_boundingBoxCenter = DOMPointReadOnly::fromFloatPoint(center);
459 m_boundingBoxExtents = DOMPointReadOnly::fromFloatPoint(extents);
460}
461
462#endif
463
464RefPtr<GraphicsLayer> HTMLModelElement::graphicsLayer() const
465{
466 RefPtr page = document().page();
467 if (!page)
468 return nullptr;
469
470 CheckedPtr renderLayerModelObject = dynamicDowncast<RenderLayerModelObject>(this->renderer());
471 if (!renderLayerModelObject)
472 return nullptr;
473
474 if (!renderLayerModelObject->isComposited())
475 return nullptr;
476
477 return renderLayerModelObject->layer()->backing()->graphicsLayer();
478}
479
480bool HTMLModelElement::isVisible() const
481{
482 bool isVisibleInline = !protect(document())->hidden() && m_isIntersectingViewport;
483#if ENABLE(MODEL_ELEMENT_IMMERSIVE)(defined ENABLE_MODEL_ELEMENT_IMMERSIVE && ENABLE_MODEL_ELEMENT_IMMERSIVE
)
484 return isVisibleInline || m_detachedForImmersive;
485#else
486 return isVisibleInline;
487#endif
488}
489
490void HTMLModelElement::logWarning(ModelPlayer& modelPlayer, const String& warningMessage)
491{
492 ASSERT_UNUSED(modelPlayer, &modelPlayer == m_modelPlayer)((void)modelPlayer);
493
494 protect(document())->addConsoleMessage(MessageSource::Other, MessageLevel::Warning, warningMessage);
495}
496
497// MARK: - ModelPlayer support
498
499void HTMLModelElement::modelDidChange()
500{
501 RefPtr page = document().page();
502 if (!page) {
503 if (!m_readyPromise->isFulfilled())
504 m_readyPromise->reject(Exception { ExceptionCode::AbortError });
505 triggerModelPlayerCreationCallbacksIfNeeded(Exception { ExceptionCode::AbortError, "Model not associated with a page"_s });
506 return;
507 }
508
509#if ENABLE(MODEL_ELEMENT_IMMERSIVE)(defined ENABLE_MODEL_ELEMENT_IMMERSIVE && ENABLE_MODEL_ELEMENT_IMMERSIVE
)
510 bool hasRenderer = this->renderer() || m_detachedForImmersive;
511#else
512 bool hasRenderer = this->renderer();
513#endif
514 if (!hasRenderer) {
515 m_shouldCreateModelPlayerUponRendererAttachment = true;
516 triggerModelPlayerCreationCallbacksIfNeeded(Exception { ExceptionCode::AbortError, "Model cannot be rendered"_s });
517 return;
518 }
519
520 createModelPlayer();
521}
522
523void HTMLModelElement::createModelPlayer()
524{
525 RefPtr model = m_model;
526 if (!model)
527 return;
528
529 if (modelContainerSizeIsEmpty())
530 return triggerModelPlayerCreationCallbacksIfNeeded(Exception { ExceptionCode::AbortError, "Model container size is empty"_s });
531
532 RefPtr modelPlayer = m_modelPlayer;
533 if (modelPlayer)
534 deleteModelPlayer();
535
536 ASSERT(document().page())((void)0);
537
538#if ENABLE(MODEL_ELEMENT_ENTITY_TRANSFORM)(defined (0 || 0) && (0 || 0))
539 m_entityTransform = DOMMatrixReadOnly::create(TransformationMatrix::identity, DOMMatrixReadOnly::Is2D::No);
540#endif
541
542#if ENABLE(MODEL_ELEMENT_BOUNDING_BOX)(defined (0 || 0) && (0 || 0))
543 m_boundingBoxCenter = DOMPointReadOnly::create({ });
544 m_boundingBoxExtents = DOMPointReadOnly::create({ });
545#endif
546
547 if (!m_modelPlayerProvider)
548 m_modelPlayerProvider = protect(document().page())->modelPlayerProvider();
549 if (RefPtr modelPlayerProvider = m_modelPlayerProvider.get()) {
550 modelPlayer = modelPlayerProvider->createModelPlayer(*this);
551 m_modelPlayer = modelPlayer.copyRef();
552 }
553 if (!modelPlayer) {
554 if (!m_readyPromise->isFulfilled())
555 m_readyPromise->reject(Exception { ExceptionCode::AbortError });
556 triggerModelPlayerCreationCallbacksIfNeeded(Exception { ExceptionCode::AbortError, "Model player creation failed"_s });
557 return;
558 }
559
560#if ENABLE(MODEL_ELEMENT_ANIMATIONS_CONTROL)(defined (0 || 0) && (0 || 0))
561 modelPlayer->setAutoplay(autoplay());
562 modelPlayer->setLoop(loop());
563 modelPlayer->setPlaybackRate(m_playbackRate, [&](double) { });
564#endif
565
566#if ENABLE(MODEL_ELEMENT_PORTAL)(defined 0 && 0)
567 modelPlayer->setHasPortal(hasPortal());
568#endif
569
570#if ENABLE(MODEL_ELEMENT_STAGE_MODE)(defined (0 || 0) && (0 || 0))
571 modelPlayer->setStageMode(stageMode());
572#endif
573
574 // FIXME: We need to tell the player if the size changes as well, so passing this
575 // in with load probably doesn't make sense.
576 modelPlayer->load(*model, contentSize());
577
578#if ENABLE(MODEL_ELEMENT_ENVIRONMENT_MAP)(defined (0 || 0) && (0 || 0))
579 if (m_environmentMapData)
580 modelPlayer->setEnvironmentMap(m_environmentMapData.takeBufferAsContiguous().get());
581 else if (!m_environmentMapURL.isEmpty())
582 environmentMapRequestResource();
583#endif
584
585 triggerModelPlayerCreationCallbacksIfNeeded(WTF::move(modelPlayer));
586}
587
588void HTMLModelElement::deleteModelPlayer()
589{
590 auto deleteModelPlayerBlock = [weakThis = WeakPtr { *this }, modelPlayerProvider = RefPtr { m_modelPlayerProvider.get() }, modelPlayer = RefPtr { m_modelPlayer }] {
591 if (modelPlayerProvider && modelPlayer)
592 modelPlayerProvider->deleteModelPlayer(*modelPlayer);
593
594 RefPtr protectedThis = weakThis.get();
595 if (protectedThis)
596 protectedThis->m_modelPlayer = nullptr;
597 };
598
599#if ENABLE(MODEL_ELEMENT_IMMERSIVE)(defined ENABLE_MODEL_ELEMENT_IMMERSIVE && ENABLE_MODEL_ELEMENT_IMMERSIVE
)
600 if (immersive())
601 return protect(document().immersive())->exitRemovedImmersiveElement(this, WTF::move(deleteModelPlayerBlock));
602#endif
603
604 deleteModelPlayerBlock();
605}
606
607void HTMLModelElement::unloadModelPlayer(bool onSuspend)
608{
609 RefPtr modelPlayer = m_modelPlayer;
610 if (!modelPlayer || modelPlayer->isPlaceholder())
611 return;
612
613 auto animationState = modelPlayer->currentAnimationState();
614 auto transformState = modelPlayer->currentTransformState();
615 if (!animationState || !transformState) {
616 RELEASE_LOG(ModelElement, "%p - HTMLModelElement: Model player cannot handle temporary unload", this)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 = (LogModelElement
.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
("%p - HTMLModelElement: Model player cannot handle temporary unload"
), "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_LOG22"
) = "%p - HTMLModelElement: Model player cannot handle temporary unload"
; uint8_t _Alignas(16) __attribute__((uninitialized)) _os_fmt_buf
[__builtin_os_log_format_buffer_size("%p - HTMLModelElement: Model player cannot handle temporary unload"
, this)]; _os_log_impl(&__dso_handle, _log_tmp, _type_tmp
, _os_fmt_str, (uint8_t *)__builtin_os_log_format(_os_fmt_buf
, "%p - HTMLModelElement: Model player cannot handle temporary unload"
, this), (uint32_t)sizeof(_os_fmt_buf)) clang diagnostic pop
; }); } }) clang diagnostic pop
;
617 deleteModelPlayer();
618 return;
619 }
620
621 RELEASE_LOG(ModelElement, "%p - HTMLModelElement: Temporarily unload model player: %p", this, modelPlayer.get())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 = (LogModelElement
.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
("%p - HTMLModelElement: Temporarily unload model player: %p"
), "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_LOG23"
) = "%p - HTMLModelElement: Temporarily unload model player: %p"
; uint8_t _Alignas(16) __attribute__((uninitialized)) _os_fmt_buf
[__builtin_os_log_format_buffer_size("%p - HTMLModelElement: Temporarily unload model player: %p"
, this, modelPlayer.get())]; _os_log_impl(&__dso_handle, _log_tmp
, _type_tmp, _os_fmt_str, (uint8_t *)__builtin_os_log_format(
_os_fmt_buf, "%p - HTMLModelElement: Temporarily unload model player: %p"
, this, modelPlayer.get()), (uint32_t)sizeof(_os_fmt_buf)) clang
diagnostic pop ; }); } }) clang diagnostic pop
;
622 deleteModelPlayer();
623
624 m_modelPlayer = PlaceholderModelPlayer::create(onSuspend, *animationState, WTF::move(*transformState));
625}
626
627void HTMLModelElement::reloadModelPlayer()
628{
629 RefPtr modelPlayer = m_modelPlayer;
630 if (!modelPlayer) {
631 RELEASE_LOG_INFO(ModelElement, "%p - HTMLModelElement::reloadModelPlayer: no model player", this)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 = (LogModelElement
.osLogChannel); os_log_type_t _type_tmp = (OS_LOG_TYPE_INFO);
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
("%p - HTMLModelElement::reloadModelPlayer: no model player")
, "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_LOG24"
) = "%p - HTMLModelElement::reloadModelPlayer: no model player"
; uint8_t _Alignas(16) __attribute__((uninitialized)) _os_fmt_buf
[__builtin_os_log_format_buffer_size("%p - HTMLModelElement::reloadModelPlayer: no model player"
, this)]; _os_log_impl(&__dso_handle, _log_tmp, _type_tmp
, _os_fmt_str, (uint8_t *)__builtin_os_log_format(_os_fmt_buf
, "%p - HTMLModelElement::reloadModelPlayer: no model player"
, this), (uint32_t)sizeof(_os_fmt_buf)) clang diagnostic pop
; }); } }) clang diagnostic pop
;
632 createModelPlayer();
633 return;
634 }
635
636 if (!modelPlayer->isPlaceholder()) {
637 RELEASE_LOG_INFO(ModelElement, "%p - HTMLModelElement::reloadModelPlayer: no placeholder to reload", this)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 = (LogModelElement
.osLogChannel); os_log_type_t _type_tmp = (OS_LOG_TYPE_INFO);
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
("%p - HTMLModelElement::reloadModelPlayer: no placeholder to reload"
), "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_LOG25"
) = "%p - HTMLModelElement::reloadModelPlayer: no placeholder to reload"
; uint8_t _Alignas(16) __attribute__((uninitialized)) _os_fmt_buf
[__builtin_os_log_format_buffer_size("%p - HTMLModelElement::reloadModelPlayer: no placeholder to reload"
, this)]; _os_log_impl(&__dso_handle, _log_tmp, _type_tmp
, _os_fmt_str, (uint8_t *)__builtin_os_log_format(_os_fmt_buf
, "%p - HTMLModelElement::reloadModelPlayer: no placeholder to reload"
, this), (uint32_t)sizeof(_os_fmt_buf)) clang diagnostic pop
; }); } }) clang diagnostic pop
;
638 return;
639 }
640
641 RefPtr model = m_model;
642 if (!model) {
643 RELEASE_LOG_INFO(ModelElement, "%p - HTMLModelElement::reloadModelPlayer: no model to reload", this)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 = (LogModelElement
.osLogChannel); os_log_type_t _type_tmp = (OS_LOG_TYPE_INFO);
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
("%p - HTMLModelElement::reloadModelPlayer: no model to reload"
), "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_LOG26"
) = "%p - HTMLModelElement::reloadModelPlayer: no model to reload"
; uint8_t _Alignas(16) __attribute__((uninitialized)) _os_fmt_buf
[__builtin_os_log_format_buffer_size("%p - HTMLModelElement::reloadModelPlayer: no model to reload"
, this)]; _os_log_impl(&__dso_handle, _log_tmp, _type_tmp
, _os_fmt_str, (uint8_t *)__builtin_os_log_format(_os_fmt_buf
, "%p - HTMLModelElement::reloadModelPlayer: no model to reload"
, this), (uint32_t)sizeof(_os_fmt_buf)) clang diagnostic pop
; }); } }) clang diagnostic pop
;
644 return;
645 }
646
647 if (modelContainerSizeIsEmpty()) {
648 RELEASE_LOG_INFO(ModelElement, "%p - HTMLModelElement::reloadModelPlayer: model container size is empty", this)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 = (LogModelElement
.osLogChannel); os_log_type_t _type_tmp = (OS_LOG_TYPE_INFO);
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
("%p - HTMLModelElement::reloadModelPlayer: model container size is empty"
), "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_LOG27"
) = "%p - HTMLModelElement::reloadModelPlayer: model container size is empty"
; uint8_t _Alignas(16) __attribute__((uninitialized)) _os_fmt_buf
[__builtin_os_log_format_buffer_size("%p - HTMLModelElement::reloadModelPlayer: model container size is empty"
, this)]; _os_log_impl(&__dso_handle, _log_tmp, _type_tmp
, _os_fmt_str, (uint8_t *)__builtin_os_log_format(_os_fmt_buf
, "%p - HTMLModelElement::reloadModelPlayer: model container size is empty"
, this), (uint32_t)sizeof(_os_fmt_buf)) clang diagnostic pop
; }); } }) clang diagnostic pop
;
649 return;
650 }
651
652 ASSERT(document().page())((void)0);
653
654 auto animationState = modelPlayer->currentAnimationState();
655 auto transformState = modelPlayer->currentTransformState();
656 ASSERT(animationState && transformState)((void)0);
657
658 if (!m_modelPlayerProvider)
659 m_modelPlayerProvider = protect(protect(document())->page())->modelPlayerProvider();
660 if (RefPtr modelPlayerProvider = m_modelPlayerProvider.get()) {
661 modelPlayer = modelPlayerProvider->createModelPlayer(*this);
662 m_modelPlayer = modelPlayer.copyRef();
663 }
664 if (!modelPlayer) {
665 RELEASE_LOG_ERROR(ModelElement, "%p - HTMLModelElement: Failed to create model player to reload with", this)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 = (LogModelElement
.osLogChannel); os_log_type_t _type_tmp = OS_LOG_TYPE_ERROR; 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
("%p - HTMLModelElement: Failed to create model player to reload with"
), "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_LOG28"
) = "%p - HTMLModelElement: Failed to create model player to reload with"
; uint8_t _Alignas(16) __attribute__((uninitialized)) _os_fmt_buf
[__builtin_os_log_format_buffer_size("%p - HTMLModelElement: Failed to create model player to reload with"
, this)]; _os_log_error_impl(&__dso_handle, _log_tmp, _type_tmp
, _os_fmt_str, (uint8_t *)__builtin_os_log_format(_os_fmt_buf
, "%p - HTMLModelElement: Failed to create model player to reload with"
, this), (uint32_t)sizeof(_os_fmt_buf)) clang diagnostic pop
; }); } }) clang diagnostic pop
;
666 return;
667 }
668
669 RELEASE_LOG(ModelElement, "%p - HTMLModelElement: Reloading previous states to new model player: %p", this, modelPlayer.get())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 = (LogModelElement
.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
("%p - HTMLModelElement: Reloading previous states to new model player: %p"
), "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_LOG29"
) = "%p - HTMLModelElement: Reloading previous states to new model player: %p"
; uint8_t _Alignas(16) __attribute__((uninitialized)) _os_fmt_buf
[__builtin_os_log_format_buffer_size("%p - HTMLModelElement: Reloading previous states to new model player: %p"
, this, modelPlayer.get())]; _os_log_impl(&__dso_handle, _log_tmp
, _type_tmp, _os_fmt_str, (uint8_t *)__builtin_os_log_format(
_os_fmt_buf, "%p - HTMLModelElement: Reloading previous states to new model player: %p"
, this, modelPlayer.get()), (uint32_t)sizeof(_os_fmt_buf)) clang
diagnostic pop ; }); } }) clang diagnostic pop
;
670 modelPlayer->reload(*model, contentSize(), *animationState, WTF::move(*transformState));
671
672#if ENABLE(MODEL_ELEMENT_ENVIRONMENT_MAP)(defined (0 || 0) && (0 || 0))
673 if (m_environmentMapData)
674 modelPlayer->setEnvironmentMap(m_environmentMapData.takeBufferAsContiguous().get());
675 else if (!m_environmentMapURL.isEmpty())
676 environmentMapRequestResource();
677#endif
678}
679
680void HTMLModelElement::startLoadModelTimer()
681{
682 if (m_loadModelTimer)
683 return;
684
685 Ref document = this->document();
686 Seconds delay = document->page() && document->page()->shouldDisableModelLoadDelaysForTesting() ? 0_s : reloadModelDelay;
687 m_loadModelTimer = protect(document->eventLoop())->scheduleTask(delay, TaskSource::ModelElement, [weakThis = WeakPtr { *this }] {
688 if (weakThis)
689 weakThis->loadModelTimerFired();
690 });
691}
692
693void HTMLModelElement::loadModelTimerFired()
694{
695 m_loadModelTimer = nullptr;
696
697 if (!isVisible())
698 return;
699
700 RELEASE_LOG(ModelElement, "%p - HTMLModelElement: Timer fired for loading model", this)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 = (LogModelElement
.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
("%p - HTMLModelElement: Timer fired for loading model"), "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_LOG30"
) = "%p - HTMLModelElement: Timer fired for loading model"; uint8_t
_Alignas(16) __attribute__((uninitialized)) _os_fmt_buf[__builtin_os_log_format_buffer_size
("%p - HTMLModelElement: Timer fired for loading model", this
)]; _os_log_impl(&__dso_handle, _log_tmp, _type_tmp, _os_fmt_str
, (uint8_t *)__builtin_os_log_format(_os_fmt_buf, "%p - HTMLModelElement: Timer fired for loading model"
, this), (uint32_t)sizeof(_os_fmt_buf)) clang diagnostic pop
; }); } }) clang diagnostic pop
;
701
702 if (isModelDeferred()) {
703 sourceRequestResource();
704 return;
705 }
706
707 reloadModelPlayer();
708}
709
710void HTMLModelElement::sizeMayHaveChanged()
711{
712 if (RefPtr modelPlayer = m_modelPlayer)
713 modelPlayer->sizeDidChange(contentSize());
714 else
715 createModelPlayer();
716}
717
718void HTMLModelElement::configureGraphicsLayer(GraphicsLayer& graphicsLayer, Color backgroundColor)
719{
720 RefPtr modelPlayer = m_modelPlayer;
721 if (!modelPlayer)
722 return;
723
724 modelPlayer->configureGraphicsLayer(graphicsLayer, {
725 .model = model(),
726 .contentSize = contentSize(),
727 .backgroundColor = backgroundColor,
728 .isInteractive = isInteractive(),
729#if ENABLE(MODEL_ELEMENT_PORTAL)(defined 0 && 0)
730 .hasPortal = hasPortal(),
731#endif
732#if ENABLE(MODEL_ELEMENT_IMMERSIVE)(defined ENABLE_MODEL_ELEMENT_IMMERSIVE && ENABLE_MODEL_ELEMENT_IMMERSIVE
)
733 .detachedForImmersive = m_detachedForImmersive,
734#endif
735 });
736}
737
738#if ENABLE(MODEL_ELEMENT_ENTITY_TRANSFORM)(defined (0 || 0) && (0 || 0))
739
740const DOMMatrixReadOnly& HTMLModelElement::entityTransform() const
741{
742 return m_entityTransform.get();
743}
744
745ExceptionOr<void> HTMLModelElement::setEntityTransform(const DOMMatrixReadOnly& transform)
746{
747#if ENABLE(MODEL_ELEMENT_STAGE_MODE)(defined (0 || 0) && (0 || 0))
748 if (canSetEntityTransform())
749 return Exception { ExceptionCode::InvalidStateError, "Transform is read-only unless StageMode is set to 'none'"_s };
750#endif
751
752 auto player = m_modelPlayer;
753 if (!player) {
754 ASSERT_NOT_REACHED()((void)0);
755 return Exception { ExceptionCode::UnknownError };
756 }
757
758 TransformationMatrix matrix = transform.transformationMatrix();
759
760 if (!player->supportsTransform(matrix))
761 return Exception { ExceptionCode::NotSupportedError };
762
763 m_entityTransform = DOMMatrixReadOnly::create(matrix, DOMMatrixReadOnly::Is2D::No);
764 player->setEntityTransform(matrix);
765
766 return { };
767}
768
769#endif
770
771#if ENABLE(MODEL_ELEMENT_BOUNDING_BOX)(defined (0 || 0) && (0 || 0))
772
773const DOMPointReadOnly& HTMLModelElement::boundingBoxCenter() const
774{
775 return m_boundingBoxCenter;
776}
777
778const DOMPointReadOnly& HTMLModelElement::boundingBoxExtents() const
779{
780 return m_boundingBoxExtents;
781}
782
783#endif
784
785#if ENABLE(MODEL_ELEMENT_STAGE_MODE)(defined (0 || 0) && (0 || 0))
786bool HTMLModelElement::canSetEntityTransform() const
787{
788 return stageMode() != StageModeOperation::None;
789}
790#endif
791
792#if ENABLE(MODEL_ELEMENT_STAGE_MODE_INTERACTION)(defined 0 && 0)
793
794bool HTMLModelElement::supportsStageModeInteraction() const
795{
796 return canSetEntityTransform();
797}
798
799void HTMLModelElement::beginStageModeTransform(const TransformationMatrix& transform)
800{
801 if (m_modelPlayer)
802 m_modelPlayer->beginStageModeTransform(transform);
803}
804
805void HTMLModelElement::updateStageModeTransform(const TransformationMatrix& transform)
806{
807 if (m_modelPlayer)
808 m_modelPlayer->updateStageModeTransform(transform);
809}
810
811void HTMLModelElement::endStageModeInteraction()
812{
813 if (m_modelPlayer)
814 m_modelPlayer->endStageModeInteraction();
815}
816
817void HTMLModelElement::tryAnimateModelToFitPortal(bool handledDrag, CompletionHandler<void(bool)>&& completionHandler)
818{
819 if (hasPortal() && m_modelPlayer)
820 return m_modelPlayer->animateModelToFitPortal(WTF::move(completionHandler));
821
822 completionHandler(handledDrag);
823}
824
825void HTMLModelElement::resetModelTransformAfterDrag()
826{
827 if (hasPortal() && m_modelPlayer)
828 m_modelPlayer->resetModelTransformAfterDrag();
829}
830
831#endif
832
833// MARK: - Fullscreen support.
834
835void HTMLModelElement::enterFullscreen()
836{
837 if (RefPtr modelPlayer = m_modelPlayer)
838 modelPlayer->enterFullscreen();
839}
840
841// MARK: - Interaction support.
842
843bool HTMLModelElement::supportsDragging() const
844{
845 RefPtr modelPlayer = m_modelPlayer;
846 if (!modelPlayer)
847 return true;
848
849 return modelPlayer->supportsDragging();
850}
851
852bool HTMLModelElement::isDraggableIgnoringAttributes() const
853{
854 return supportsDragging();
855}
856
857bool HTMLModelElement::isInteractive() const
858{
859#if ENABLE(MODEL_ELEMENT_STAGE_MODE)(defined (0 || 0) && (0 || 0))
860 return canSetEntityTransform();
861#else
862 return hasAttributeWithoutSynchronization(HTMLNames::interactiveAttr);
863#endif
864}
865
866void HTMLModelElement::attributeChanged(const QualifiedName& name, const AtomString& oldValue, const AtomString& newValue, AttributeModificationReason attributeModificationReason)
867{
868 if (name == srcAttr)
869 sourcesChanged();
870 else if (name == interactiveAttr) {
871 if (RefPtr modelPlayer = m_modelPlayer)
872 modelPlayer->setInteractionEnabled(isInteractive());
873 }
874#if ENABLE(MODEL_ELEMENT_ANIMATIONS_CONTROL)(defined (0 || 0) && (0 || 0))
875 else if (name == autoplayAttr)
876 updateAutoplay();
877 else if (name == loopAttr)
878 updateLoop();
879#endif
880#if ENABLE(MODEL_ELEMENT_ENVIRONMENT_MAP)(defined (0 || 0) && (0 || 0))
881 else if (name == environmentmapAttr)
882 updateEnvironmentMap();
883#endif
884#if ENABLE(MODEL_ELEMENT_STAGE_MODE)(defined (0 || 0) && (0 || 0))
885 else if (name == stagemodeAttr)
886 updateStageMode();
887#endif
888#if ENABLE(MODEL_ELEMENT_PORTAL)(defined 0 && 0)
889 else if (document().settings().modelNoPortalAttributeEnabled() && name == noportalAttr)
890 updateHasPortal();
891#endif
892 else
893 HTMLElement::attributeChanged(name, oldValue, newValue, attributeModificationReason);
894}
895
896void HTMLModelElement::defaultEventHandler(Event& event)
897{
898 HTMLElement::defaultEventHandler(event);
899
900 RefPtr modelPlayer = m_modelPlayer;
901 if (!modelPlayer || !modelPlayer->supportsMouseInteraction())
902 return;
903
904 auto type = event.type();
905 bool isMouseEvent = type == eventNames().mousedownEvent || type == eventNames().mousemoveEvent || type == eventNames().mouseupEvent;
906
907#if ENABLE(TOUCH_EVENTS)(defined 0 && 0) && ENABLE(GPU_PROCESS_MODEL)(defined 0 && 0)
908 bool isTouchEvent = type == eventNames().touchstartEvent || type == eventNames().touchmoveEvent || type == eventNames().touchendEvent;
909
910 if (isTouchEvent) {
911 auto& touchEvent = downcast<TouchEvent>(event);
912
913 if (type == eventNames().touchstartEvent && !m_isDragging && !event.defaultPrevented() && isInteractive())
914 dragDidStart(touchEvent);
915 else if (type == eventNames().touchmoveEvent && m_isDragging)
916 dragDidChange(touchEvent);
917 else if ((type == eventNames().touchendEvent || type == eventNames().touchcancelEvent) && m_isDragging)
918 dragDidEnd(touchEvent);
919 return;
920 }
921#endif
922
923 if (!isMouseEvent)
924 return;
925
926 auto& mouseEvent = downcast<MouseEvent>(event);
927
928 if (mouseEvent.button() != MouseButton::Left)
929 return;
930
931 if (type == eventNames().mousedownEvent && !m_isDragging && !event.defaultPrevented() && isInteractive())
932 dragDidStart(mouseEvent);
933 else if (type == eventNames().mousemoveEvent && m_isDragging)
934 dragDidChange(mouseEvent);
935 else if (type == eventNames().mouseupEvent && m_isDragging)
936 dragDidEnd(mouseEvent);
937}
938
939LayoutPoint HTMLModelElement::flippedLocationInElementForMouseEvent(WebCore::MouseRelatedEvent& event)
940{
941 LayoutUnit flippedY { event.offsetY() };
942 if (CheckedPtr renderModel = dynamicDowncast<RenderModel>(renderer()))
943 flippedY = renderModel->paddingBoxHeight() - flippedY;
944 return { LayoutUnit(event.offsetX()), flippedY };
945}
946
947void HTMLModelElement::dragDidStart(WebCore::MouseRelatedEvent& event)
948{
949 ASSERT(!m_isDragging)((void)0);
950
951 RefPtr frame = document().frame();
952 if (!frame)
953 return;
954
955 frame->eventHandler().setCapturingMouseEventsElement(this);
956 event.setDefaultHandled();
957 m_isDragging = true;
958
959 if (RefPtr modelPlayer = m_modelPlayer)
960 modelPlayer->handleMouseDown(flippedLocationInElementForMouseEvent(event), event.timeStamp());
961}
962
963void HTMLModelElement::dragDidChange(WebCore::MouseRelatedEvent& event)
964{
965 ASSERT(m_isDragging)((void)0);
966
967 event.setDefaultHandled();
968
969 if (RefPtr modelPlayer = m_modelPlayer)
970 modelPlayer->handleMouseMove(flippedLocationInElementForMouseEvent(event), event.timeStamp());
971}
972
973void HTMLModelElement::dragDidEnd(WebCore::MouseRelatedEvent& event)
974{
975 ASSERT(m_isDragging)((void)0);
976
977 RefPtr frame = document().frame();
978 if (!frame)
979 return;
980
981 frame->eventHandler().setCapturingMouseEventsElement(nullptr);
982 event.setDefaultHandled();
983 m_isDragging = false;
984
985 if (RefPtr modelPlayer = m_modelPlayer)
986 modelPlayer->handleMouseUp(flippedLocationInElementForMouseEvent(event), event.timeStamp());
987}
988
989std::optional<PlatformLayerIdentifier> HTMLModelElement::layerID() const
990{
991 auto graphicsLayer = this->graphicsLayer();
992 if (!graphicsLayer)
993 return std::nullopt;
994
995 return graphicsLayer->primaryLayerID();
996}
997
998// MARK: - Camera support.
999
1000void HTMLModelElement::getCamera(CameraPromise&& promise)
1001{
1002 RefPtr modelPlayer = m_modelPlayer;
1003 if (!modelPlayer) {
1004 promise.reject(Exception { ExceptionCode::AbortError });
1005 return;
1006 }
1007
1008 modelPlayer->getCamera([promise = WTF::move(promise)](std::optional<HTMLModelElementCamera> camera) mutable {
1009 if (!camera)
1010 promise.reject();
1011 else
1012 promise.resolve(*camera);
1013 });
1014}
1015
1016void HTMLModelElement::setCamera(HTMLModelElementCamera camera, DOMPromiseDeferred<void>&& promise)
1017{
1018 RefPtr modelPlayer = m_modelPlayer;
1019 if (!modelPlayer) {
1020 promise.reject(Exception { ExceptionCode::AbortError });
1021 return;
1022 }
1023
1024 modelPlayer->setCamera(camera, [promise = WTF::move(promise)](bool success) mutable {
1025 if (success)
1026 promise.resolve();
1027 else
1028 promise.reject();
1029 });
1030}
1031
1032// MARK: - Animations support.
1033
1034#if ENABLE(MODEL_ELEMENT_ANIMATIONS_CONTROL)(defined (0 || 0) && (0 || 0))
1035
1036void HTMLModelElement::setPlaybackRate(double playbackRate)
1037{
1038 if (m_playbackRate == playbackRate)
1039 return;
1040
1041 m_playbackRate = playbackRate;
1042
1043 if (m_modelPlayer)
1044 m_modelPlayer->setPlaybackRate(playbackRate, [&](double) { });
1045}
1046
1047double HTMLModelElement::duration() const
1048{
1049 return m_modelPlayer ? m_modelPlayer->duration() : 0;
1050}
1051
1052bool HTMLModelElement::paused() const
1053{
1054 return m_modelPlayer ? m_modelPlayer->paused() : true;
1055}
1056
1057void HTMLModelElement::play(DOMPromiseDeferred<void>&& promise)
1058{
1059 setPaused(false, WTF::move(promise));
1060}
1061
1062void HTMLModelElement::pause(DOMPromiseDeferred<void>&& promise)
1063{
1064 setPaused(true, WTF::move(promise));
1065}
1066
1067void HTMLModelElement::setPaused(bool paused, DOMPromiseDeferred<void>&& promise)
1068{
1069 if (!m_modelPlayer) {
1070 promise.reject();
1071 return;
1072 }
1073
1074 m_modelPlayer->setPaused(paused, [promise = WTF::move(promise)] (bool succeeded) mutable {
1075 if (succeeded)
1076 promise.resolve();
1077 else
1078 promise.reject();
1079 });
1080}
1081
1082bool HTMLModelElement::autoplay() const
1083{
1084 return hasAttributeWithoutSynchronization(HTMLNames::autoplayAttr);
1085}
1086
1087void HTMLModelElement::updateAutoplay()
1088{
1089 if (m_modelPlayer)
1090 m_modelPlayer->setAutoplay(autoplay());
1091}
1092
1093bool HTMLModelElement::loop() const
1094{
1095 return hasAttributeWithoutSynchronization(HTMLNames::loopAttr);
1096}
1097
1098void HTMLModelElement::updateLoop()
1099{
1100 if (m_modelPlayer)
1101 m_modelPlayer->setLoop(loop());
1102}
1103
1104double HTMLModelElement::currentTime() const
1105{
1106 return m_modelPlayer ? m_modelPlayer->currentTime().seconds() : 0;
1107}
1108
1109void HTMLModelElement::setCurrentTime(double currentTime)
1110{
1111 if (m_modelPlayer)
1112 m_modelPlayer->setCurrentTime(Seconds(currentTime), [&] { });
1113}
1114
1115#endif
1116
1117#if ENABLE(MODEL_ELEMENT_STAGE_MODE)(defined (0 || 0) && (0 || 0))
1118
1119WebCore::StageModeOperation HTMLModelElement::stageMode() const
1120{
1121 String attr = attributeWithoutSynchronization(HTMLNames::stagemodeAttr);
1122 if (equalLettersIgnoringASCIICase(attr, "orbit"_s))
1123 return WebCore::StageModeOperation::Orbit;
1124
1125 return WebCore::StageModeOperation::None;
1126}
1127
1128void HTMLModelElement::updateStageMode()
1129{
1130 auto mode = stageMode();
1131 if (m_modelPlayer)
1132 m_modelPlayer->setStageMode(mode);
1133
1134#if ENABLE(TOUCH_EVENTS)(defined 0 && 0)
1135 if (!m_eventListener)
1136 m_eventListener = HTMLModelElementEventListener::create();
1137
1138 if (mode == WebCore::StageModeOperation::Orbit) {
1139 addEventListener(eventNames().touchstartEvent, *m_eventListener, { });
1140 addEventListener(eventNames().touchmoveEvent, *m_eventListener, { });
1141 addEventListener(eventNames().touchendEvent, *m_eventListener, { });
1142 document().didAddTouchEventHandler(*this);
1143 } else {
1144 removeEventListener(eventNames().touchstartEvent, *m_eventListener, { });
1145 removeEventListener(eventNames().touchmoveEvent, *m_eventListener, { });
1146 removeEventListener(eventNames().touchendEvent, *m_eventListener, { });
1147 document().didRemoveTouchEventHandler(*this);
1148 }
1149
1150#endif
1151}
1152
1153#endif
1154
1155#if ENABLE(MODEL_ELEMENT_PORTAL)(defined 0 && 0)
1156
1157bool HTMLModelElement::hasPortal() const
1158{
1159 return !(document().settings().modelNoPortalAttributeEnabled() && hasAttributeWithoutSynchronization(HTMLNames::noportalAttr));
1160}
1161
1162void HTMLModelElement::updateHasPortal()
1163{
1164 if (CheckedPtr renderer = this->renderer())
1165 renderer->updateFromElement();
1166
1167 if (RefPtr modelPlayer = m_modelPlayer)
1168 modelPlayer->setHasPortal(hasPortal());
1169}
1170
1171#endif
1172
1173#if ENABLE(MODEL_ELEMENT_ENVIRONMENT_MAP)(defined (0 || 0) && (0 || 0))
1174
1175const URL& HTMLModelElement::environmentMap() const
1176{
1177 return m_environmentMapURL;
1178}
1179
1180void HTMLModelElement::setEnvironmentMap(const URL& url)
1181{
1182 if (url.string() == m_environmentMapURL.string())
1183 return;
1184
1185 m_environmentMapURL = url;
1186 m_environmentMapDataMemoryCost.store(0, std::memory_order_relaxed);
1187
1188 environmentMapResetAndReject(Exception { ExceptionCode::AbortError });
1189 m_environmentMapReadyPromise = makeUniqueRef<EnvironmentMapPromise>();
1190
1191 if (m_environmentMapURL.isEmpty()) {
1192 // sending a message with empty data to indicate resource removal
1193 if (m_modelPlayer)
1194 m_modelPlayer->setEnvironmentMap(SharedBuffer::create());
1195 reportExtraMemoryCost();
1196 return;
1197 }
1198
1199 environmentMapRequestResource();
1200}
1201
1202void HTMLModelElement::updateEnvironmentMap()
1203{
1204 setEnvironmentMap(selectEnvironmentMapURL());
1205}
1206
1207URL HTMLModelElement::selectEnvironmentMapURL() const
1208{
1209 if (!document().hasBrowsingContext())
1210 return { };
1211
1212 if (hasAttributeWithoutSynchronization(environmentmapAttr)) {
1213 const auto& attr = attributeWithoutSynchronization(environmentmapAttr).string().trim(isASCIIWhitespace);
1214 if (StringView(attr).containsOnly<isASCIIWhitespace<char16_t>>())
1215 return { };
1216 return getURLAttribute(environmentmapAttr);
1217 }
1218
1219 return { };
1220}
1221
1222void HTMLModelElement::environmentMapRequestResource()
1223{
1224 auto request = createResourceRequest(m_environmentMapURL, FetchOptions::Destination::Environmentmap);
1225 auto resource = protect(document().cachedResourceLoader())->requestEnvironmentMapResource(WTF::move(request));
1226 if (!resource.has_value()) {
1227 if (!m_environmentMapReadyPromise->isFulfilled())
1228 m_environmentMapReadyPromise->reject(Exception { ExceptionCode::NetworkError });
1229 // sending a message with empty data to indicate resource removal
1230 if (m_modelPlayer)
1231 m_modelPlayer->setEnvironmentMap(SharedBuffer::create());
1232 return;
1233 }
1234
1235 m_environmentMapData.empty();
1236
1237 m_environmentMapResource = resource.value();
1238 m_environmentMapResource->addClient(*this);
1239}
1240
1241void HTMLModelElement::environmentMapResetAndReject(Exception&& exception)
1242{
1243 m_environmentMapData.reset();
1244
1245 if (m_environmentMapResource) {
1246 m_environmentMapResource->removeClient(*this);
1247 m_environmentMapResource = nullptr;
1248 }
1249
1250 if (!m_environmentMapReadyPromise->isFulfilled())
1251 m_environmentMapReadyPromise->reject(WTF::move(exception));
1252}
1253
1254void HTMLModelElement::environmentMapResourceFinished()
1255{
1256 int status = m_environmentMapResource->response().httpStatusCode();
1257 if (m_environmentMapResource->loadFailedOrCanceled() || (status && (status < 200 || status > 299))) {
1258 environmentMapResetAndReject(Exception { ExceptionCode::NetworkError });
1259
1260 // sending a message with empty data to indicate resource removal
1261 if (m_modelPlayer)
1262 m_modelPlayer->setEnvironmentMap(SharedBuffer::create());
1263 return;
1264 }
1265 if (m_modelPlayer) {
1266 m_environmentMapDataMemoryCost.store(m_environmentMapData.size(), std::memory_order_relaxed);
1267 m_modelPlayer->setEnvironmentMap(m_environmentMapData.takeBufferAsContiguous().get());
1268 }
1269
1270 m_environmentMapResource->removeClient(*this);
1271 m_environmentMapResource = nullptr;
1272}
1273
1274#endif
1275
1276bool HTMLModelElement::shouldDeferLoading() const
1277{
1278 RefPtr frame = document().frame();
1279 if (!frame)
1280 return false;
1281
1282 if (!protect(frame->script())->canExecuteScripts(ReasonForCallingCanExecuteScripts::NotAboutToExecuteScript))
1283 return false;
1284
1285 return !isVisible() && isModelDeferred() && !document().page()->shouldDisableModelLoadDelaysForTesting();
1286}
1287
1288void HTMLModelElement::modelResourceFinished()
1289{
1290 auto invalidateResourceHandleAndUpdateRenderer = [&] {
1291 m_resource->removeClient(*this);
Call argument for 'this' parameter is uncounted and unsafe
1292 m_resource = nullptr;
1293
1294 if (CheckedPtr renderer = this->renderer())
1295 renderer->updateFromElement();
1296 };
1297
1298 if (m_resource->loadFailedOrCanceled()) {
1299 m_data.reset();
1300
1301 ActiveDOMObject::queueTaskToDispatchEvent(*this, TaskSource::DOMManipulation, Event::create(eventNames().errorEvent, Event::CanBubble::No, Event::IsCancelable::No));
1302 invalidateResourceHandleAndUpdateRenderer();
1303
1304 if (!m_readyPromise->isFulfilled())
1305 m_readyPromise->reject(Exception { ExceptionCode::NetworkError });
1306
1307 triggerModelPlayerCreationCallbacksIfNeeded(Exception { ExceptionCode::NetworkError, "The model resource failed to load"_s });
1308 return;
1309 }
1310
1311 m_dataComplete = true;
1312 m_dataMemoryCost.store(m_data.size(), std::memory_order_relaxed);
1313 m_model = Model::create(m_data.takeBufferAsContiguous().get(), m_resource->mimeType(), m_resource->url());
1314
1315 ActiveDOMObject::queueTaskToDispatchEvent(*this, TaskSource::DOMManipulation, Event::create(eventNames().loadEvent, Event::CanBubble::No, Event::IsCancelable::No));
1316
1317 invalidateResourceHandleAndUpdateRenderer();
1318
1319 modelDidChange();
1320}
1321
1322void HTMLModelElement::isPlayingAnimation(IsPlayingAnimationPromise&& promise)
1323{
1324 RefPtr modelPlayer = m_modelPlayer;
1325 if (!modelPlayer) {
1326 promise.reject();
1327 return;
1328 }
1329
1330 modelPlayer->isPlayingAnimation([promise = WTF::move(promise)](std::optional<bool> isPlaying) mutable {
1331 if (!isPlaying)
1332 promise.reject();
1333 else
1334 promise.resolve(*isPlaying);
1335 });
1336}
1337
1338void HTMLModelElement::setAnimationIsPlaying(bool isPlaying, DOMPromiseDeferred<void>&& promise)
1339{
1340 RefPtr modelPlayer = m_modelPlayer;
1341 if (!modelPlayer) {
1342 promise.reject();
1343 return;
1344 }
1345
1346 modelPlayer->setAnimationIsPlaying(isPlaying, [promise = WTF::move(promise)](bool success) mutable {
1347 if (success)
1348 promise.resolve();
1349 else
1350 promise.reject();
1351 });
1352}
1353
1354void HTMLModelElement::playAnimation(DOMPromiseDeferred<void>&& promise)
1355{
1356 setAnimationIsPlaying(true, WTF::move(promise));
1357}
1358
1359void HTMLModelElement::pauseAnimation(DOMPromiseDeferred<void>&& promise)
1360{
1361 setAnimationIsPlaying(false, WTF::move(promise));
1362}
1363
1364void HTMLModelElement::isLoopingAnimation(IsLoopingAnimationPromise&& promise)
1365{
1366 RefPtr modelPlayer = m_modelPlayer;
1367 if (!modelPlayer) {
1368 promise.reject();
1369 return;
1370 }
1371
1372 modelPlayer->isLoopingAnimation([promise = WTF::move(promise)](std::optional<bool> isLooping) mutable {
1373 if (!isLooping)
1374 promise.reject();
1375 else
1376 promise.resolve(*isLooping);
1377 });
1378}
1379
1380void HTMLModelElement::setIsLoopingAnimation(bool isLooping, DOMPromiseDeferred<void>&& promise)
1381{
1382 RefPtr modelPlayer = m_modelPlayer;
1383 if (!modelPlayer) {
1384 promise.reject();
1385 return;
1386 }
1387
1388 modelPlayer->setIsLoopingAnimation(isLooping, [promise = WTF::move(promise)](bool success) mutable {
1389 if (success)
1390 promise.resolve();
1391 else
1392 promise.reject();
1393 });
1394}
1395
1396void HTMLModelElement::animationDuration(DurationPromise&& promise)
1397{
1398 RefPtr modelPlayer = m_modelPlayer;
1399 if (!modelPlayer) {
1400 promise.reject();
1401 return;
1402 }
1403
1404 modelPlayer->animationDuration([promise = WTF::move(promise)] (std::optional<Seconds> duration) mutable {
1405 if (!duration)
1406 promise.reject();
1407 else
1408 promise.resolve(duration->seconds());
1409 });
1410}
1411
1412void HTMLModelElement::animationCurrentTime(CurrentTimePromise&& promise)
1413{
1414 RefPtr modelPlayer = m_modelPlayer;
1415 if (!modelPlayer) {
1416 promise.reject();
1417 return;
1418 }
1419
1420 modelPlayer->animationCurrentTime([promise = WTF::move(promise)] (std::optional<Seconds> currentTime) mutable {
1421 if (!currentTime)
1422 promise.reject();
1423 else
1424 promise.resolve(currentTime->seconds());
1425 });
1426}
1427
1428void HTMLModelElement::setAnimationCurrentTime(double currentTime, DOMPromiseDeferred<void>&& promise)
1429{
1430 RefPtr modelPlayer = m_modelPlayer;
1431 if (!modelPlayer) {
1432 promise.reject();
1433 return;
1434 }
1435
1436 modelPlayer->setAnimationCurrentTime(Seconds(currentTime), [promise = WTF::move(promise)](bool success) mutable {
1437 if (success)
1438 promise.resolve();
1439 else
1440 promise.reject();
1441 });
1442}
1443
1444// MARK: - Audio support.
1445
1446void HTMLModelElement::hasAudio(HasAudioPromise&& promise)
1447{
1448 RefPtr modelPlayer = m_modelPlayer;
1449 if (!modelPlayer) {
1450 promise.reject();
1451 return;
1452 }
1453
1454 modelPlayer->isPlayingAnimation([promise = WTF::move(promise)](std::optional<bool> hasAudio) mutable {
1455 if (!hasAudio)
1456 promise.reject();
1457 else
1458 promise.resolve(*hasAudio);
1459 });
1460}
1461
1462void HTMLModelElement::isMuted(IsMutedPromise&& promise)
1463{
1464 RefPtr modelPlayer = m_modelPlayer;
1465 if (!modelPlayer) {
1466 promise.reject();
1467 return;
1468 }
1469
1470 modelPlayer->isPlayingAnimation([promise = WTF::move(promise)](std::optional<bool> isMuted) mutable {
1471 if (!isMuted)
1472 promise.reject();
1473 else
1474 promise.resolve(*isMuted);
1475 });
1476}
1477
1478void HTMLModelElement::setIsMuted(bool isMuted, DOMPromiseDeferred<void>&& promise)
1479{
1480 RefPtr modelPlayer = m_modelPlayer;
1481 if (!modelPlayer) {
1482 promise.reject();
1483 return;
1484 }
1485
1486 modelPlayer->setIsMuted(isMuted, [promise = WTF::move(promise)](bool success) mutable {
1487 if (success)
1488 promise.resolve();
1489 else
1490 promise.reject();
1491 });
1492}
1493
1494#if ENABLE(MODEL_ELEMENT_IMMERSIVE)(defined ENABLE_MODEL_ELEMENT_IMMERSIVE && ENABLE_MODEL_ELEMENT_IMMERSIVE
)
1495
1496bool HTMLModelElement::immersive() const
1497{
1498 RefPtr documentImmersive = document().immersiveIfExists();
1499 return documentImmersive && documentImmersive->immersiveElement() == this;
1500}
1501
1502void HTMLModelElement::requestImmersive(DOMPromiseDeferred<void>&& promise)
1503{
1504 protect(document().immersive())->requestImmersive(this, [promise = WTF::move(promise)](ExceptionOr<void> result) mutable {
1505 if (result.hasException()) {
1506 promise.reject(result.releaseException());
1507 return;
1508 }
1509 promise.resolve();
1510 });
1511}
1512
1513void HTMLModelElement::ensureImmersivePresentation(CompletionHandler<void(ExceptionOr<LayerHostingContextIdentifier>)>&& completion)
1514{
1515 setDetachedForImmersive(true);
1516 ensureModelPlayer([weakThis = WeakPtr { *this }, completion = WTF::move(completion)](auto result) mutable {
1517 RefPtr protectedThis = weakThis.get();
1518 if (!protectedThis)
1519 return completion(Exception { ExceptionCode::AbortError });
1520
1521 if (result.hasException()) {
1522 protectedThis->setDetachedForImmersive(false);
1523 completion(result.releaseException());
1524 return;
1525 }
1526
1527 RefPtr modelPlayer = result.releaseReturnValue();
1528 if (!modelPlayer) {
1529 protectedThis->setDetachedForImmersive(false);
1530 completion(Exception { ExceptionCode::AbortError });
1531 return;
1532 }
1533
1534 modelPlayer->ensureImmersivePresentation([weakThis, completion = WTF::move(completion)](auto contextID) mutable {
1535 RefPtr protectedThis = weakThis.get();
1536 if (!protectedThis)
1537 return completion(Exception { ExceptionCode::AbortError });
1538
1539 if (!contextID.has_value()) {
1540 protectedThis->setDetachedForImmersive(false);
1541 completion(Exception { ExceptionCode::TypeError, "Failed to decode model"_s });
1542 return;
1543 }
1544
1545 completion(WTF::move(contextID.value()));
1546 });
1547 });
1548}
1549
1550void HTMLModelElement::exitImmersivePresentation(CompletionHandler<void()>&& completion)
1551{
1552 RefPtr modelPlayer = m_modelPlayer;
1553 if (!modelPlayer) {
1554 setDetachedForImmersive(false);
1555 completion();
1556 return;
1557 }
1558
1559 modelPlayer->exitImmersivePresentation([weakThis = WeakPtr { *this }, completion = WTF::move(completion)] mutable {
1560 RefPtr protectedThis = weakThis.get();
1561 if (!protectedThis)
1562 return completion();
1563
1564 protectedThis->setDetachedForImmersive(false);
1565 completion();
1566 });
1567}
1568
1569void HTMLModelElement::setDetachedForImmersive(bool detachedForImmersive)
1570{
1571 m_detachedForImmersive = detachedForImmersive;
1572 visibilityStateChanged();
1573 invalidateStyleAndLayerComposition();
1574 if (CheckedPtr renderer = this->renderer())
1575 renderer->updateFromElement();
1576}
1577
1578void HTMLModelElement::ensureModelPlayer(CompletionHandler<void(ExceptionOr<RefPtr<ModelPlayer>>)>&& completion)
1579{
1580 RefPtr modelPlayer = m_modelPlayer;
1581 if (modelPlayer && modelPlayer->isPlaceholder())
1582 reloadModelPlayer();
1583
1584 if (modelPlayer && !modelPlayer->isPlaceholder())
1585 return completion(RefPtr { modelPlayer });
1586
1587 RELEASE_LOG_INFO(ModelElement, "%p - HTMLModelElement: Model Player creation request: STARTED", this)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 = (LogModelElement
.osLogChannel); os_log_type_t _type_tmp = (OS_LOG_TYPE_INFO);
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
("%p - HTMLModelElement: Model Player creation request: STARTED"
), "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_LOG31"
) = "%p - HTMLModelElement: Model Player creation request: STARTED"
; uint8_t _Alignas(16) __attribute__((uninitialized)) _os_fmt_buf
[__builtin_os_log_format_buffer_size("%p - HTMLModelElement: Model Player creation request: STARTED"
, this)]; _os_log_impl(&__dso_handle, _log_tmp, _type_tmp
, _os_fmt_str, (uint8_t *)__builtin_os_log_format(_os_fmt_buf
, "%p - HTMLModelElement: Model Player creation request: STARTED"
, this), (uint32_t)sizeof(_os_fmt_buf)) clang diagnostic pop
; }); } }) clang diagnostic pop
;
1588 m_modelPlayerCreationCallbacks.append(WTF::move(completion));
1589 sourceRequestResource();
1590}
1591
1592#endif
1593
1594void HTMLModelElement::triggerModelPlayerCreationCallbacksIfNeeded(ExceptionOr<RefPtr<ModelPlayer>>&& result)
1595{
1596#if ENABLE(MODEL_ELEMENT_IMMERSIVE)(defined ENABLE_MODEL_ELEMENT_IMMERSIVE && ENABLE_MODEL_ELEMENT_IMMERSIVE
)
1597 if (m_modelPlayerCreationCallbacks.isEmpty())
1598 return;
1599
1600 if (result.hasException())
1601 RELEASE_LOG_ERROR(ModelElement, "%p - HTMLModelElement: Model Player creation request: FAILED with error: %s", this, result.exception().message().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 = (LogModelElement
.osLogChannel); os_log_type_t _type_tmp = OS_LOG_TYPE_ERROR; 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
("%p - HTMLModelElement: Model Player creation request: FAILED with error: %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_LOG32"
) = "%p - HTMLModelElement: Model Player creation request: FAILED with error: %s"
; uint8_t _Alignas(16) __attribute__((uninitialized)) _os_fmt_buf
[__builtin_os_log_format_buffer_size("%p - HTMLModelElement: Model Player creation request: FAILED with error: %s"
, this, result.exception().message().utf8().data())]; _os_log_error_impl
(&__dso_handle, _log_tmp, _type_tmp, _os_fmt_str, (uint8_t
*)__builtin_os_log_format(_os_fmt_buf, "%p - HTMLModelElement: Model Player creation request: FAILED with error: %s"
, this, result.exception().message().utf8().data()), (uint32_t
)sizeof(_os_fmt_buf)) clang diagnostic pop ; }); } }) clang diagnostic
pop
;
1602 else
1603 RELEASE_LOG_INFO(ModelElement, "%p - HTMLModelElement: Model Player creation request: SUCCEEDED", this)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 = (LogModelElement
.osLogChannel); os_log_type_t _type_tmp = (OS_LOG_TYPE_INFO);
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
("%p - HTMLModelElement: Model Player creation request: SUCCEEDED"
), "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_LOG33"
) = "%p - HTMLModelElement: Model Player creation request: SUCCEEDED"
; uint8_t _Alignas(16) __attribute__((uninitialized)) _os_fmt_buf
[__builtin_os_log_format_buffer_size("%p - HTMLModelElement: Model Player creation request: SUCCEEDED"
, this)]; _os_log_impl(&__dso_handle, _log_tmp, _type_tmp
, _os_fmt_str, (uint8_t *)__builtin_os_log_format(_os_fmt_buf
, "%p - HTMLModelElement: Model Player creation request: SUCCEEDED"
, this), (uint32_t)sizeof(_os_fmt_buf)) clang diagnostic pop
; }); } }) clang diagnostic pop
;
1604
1605 for (auto& callback : std::exchange(m_modelPlayerCreationCallbacks, { }))
1606 callback(result);
1607#else
1608 UNUSED_PARAM(result)(void)result;
1609#endif
1610}
1611
1612bool HTMLModelElement::virtualHasPendingActivity() const
1613{
1614 // We need to ensure the JS wrapper is kept alive if a load is in progress and we may yet dispatch
1615 // "load" or "error" events, ie. as long as we have a resource, meaning we are in the process of loading.
1616 return m_resource;
1617}
1618
1619void HTMLModelElement::stop()
1620{
1621 RELEASE_LOG(ModelElement, "%p - HTMLModelElement::stop()", this)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 = (LogModelElement
.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
("%p - HTMLModelElement::stop()"), "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_LOG34"
) = "%p - HTMLModelElement::stop()"; uint8_t _Alignas(16) __attribute__
((uninitialized)) _os_fmt_buf[__builtin_os_log_format_buffer_size
("%p - HTMLModelElement::stop()", this)]; _os_log_impl(&__dso_handle
, _log_tmp, _type_tmp, _os_fmt_str, (uint8_t *)__builtin_os_log_format
(_os_fmt_buf, "%p - HTMLModelElement::stop()", this), (uint32_t
)sizeof(_os_fmt_buf)) clang diagnostic pop ; }); } }) clang diagnostic
pop
;
1622
1623 LazyLoadModelObserver::unobserve(*this, protect(document()));
1624
1625 m_loadModelTimer = nullptr;
1626
1627 // Once an active DOM object has been stopped it cannot be restarted,
1628 // so we can delete the model player now.
1629 deleteModelPlayer();
1630}
1631
1632#if ENABLE(MODEL_ELEMENT_ACCESSIBILITY)(defined 1 && 1)
1633
1634ModelPlayerAccessibilityChildren HTMLModelElement::accessibilityChildren()
1635{
1636 RefPtr modelPlayer = m_modelPlayer;
1637 if (!modelPlayer)
1638 return { };
1639 return modelPlayer->accessibilityChildren();
1640}
1641
1642#endif
1643
1644LayoutSize HTMLModelElement::contentSize() const
1645{
1646 if (CheckedPtr renderer = this->renderer())
1647 return downcast<RenderReplaced>(*renderer).replacedContentRect().size();
1648
1649 return LayoutSize();
1650}
1651
1652bool HTMLModelElement::modelContainerSizeIsEmpty() const
1653{
1654#if ENABLE(MODEL_ELEMENT_IMMERSIVE)(defined ENABLE_MODEL_ELEMENT_IMMERSIVE && ENABLE_MODEL_ELEMENT_IMMERSIVE
)
1655 return contentSize().isEmpty() && !m_detachedForImmersive;
1656#else
1657 return contentSize().isEmpty();
1658#endif
1659}
1660
1661#if ENABLE(ARKIT_INLINE_PREVIEW_MAC)(defined 0 && 0)
1662
1663String HTMLModelElement::inlinePreviewUUIDForTesting() const
1664{
1665 RefPtr modelPlayer = m_modelPlayer;
1666 if (!modelPlayer)
1667 return emptyString();
1668 return modelPlayer->inlinePreviewUUIDForTesting();
1669}
1670
1671#endif
1672
1673void HTMLModelElement::collectPresentationalHintsForAttribute(const QualifiedName& name, const AtomString& value, MutableStyleProperties& style)
1674{
1675 if (name == widthAttr) {
1676 addHTMLLengthToStyle(style, CSSPropertyWidth, value);
1677 applyAspectRatioFromWidthAndHeightAttributesToStyle(value, attributeWithoutSynchronization(heightAttr), style);
1678 } else if (name == heightAttr) {
1679 addHTMLLengthToStyle(style, CSSPropertyHeight, value);
1680 applyAspectRatioFromWidthAndHeightAttributesToStyle(attributeWithoutSynchronization(widthAttr), value, style);
1681 } else
1682 HTMLElement::collectPresentationalHintsForAttribute(name, value, style);
1683}
1684
1685bool HTMLModelElement::hasPresentationalHintsForAttribute(const QualifiedName& name) const
1686{
1687 if (name == widthAttr || name == heightAttr)
1688 return true;
1689 return HTMLElement::hasPresentationalHintsForAttribute(name);
1690}
1691
1692bool HTMLModelElement::isURLAttribute(const Attribute& attribute) const
1693{
1694 return attribute.name() == srcAttr
1695#if ENABLE(MODEL_ELEMENT_ENVIRONMENT_MAP)(defined (0 || 0) && (0 || 0))
1696 || attribute.name() == environmentmapAttr
1697#endif
1698 || HTMLElement::isURLAttribute(attribute);
1699}
1700
1701Node::InsertedIntoAncestorResult HTMLModelElement::insertedIntoAncestor(InsertionType insertionType, ContainerNode& parentOfInsertedTree)
1702{
1703 auto insertResult = HTMLElement::insertedIntoAncestor(insertionType, parentOfInsertedTree);
1704
1705 if (insertionType.connectedToDocument) {
1706 Ref document = this->document();
1707 document->registerForVisibilityStateChangedCallbacks(*this);
1708#if ENABLE(MODEL_PROCESS)(defined 0 && 0)
1709 document->incrementModelElementCount();
1710#endif
1711 m_modelPlayerProvider = protect(document->page())->modelPlayerProvider();
1712 LazyLoadModelObserver::observe(*this);
1713 }
1714
1715 return insertResult;
1716}
1717
1718void HTMLModelElement::removedFromAncestor(RemovalType removalType, ContainerNode& oldParentOfRemovedTree)
1719{
1720 HTMLElement::removedFromAncestor(removalType, oldParentOfRemovedTree);
1721
1722 if (removalType.disconnectedFromDocument) {
1723 Ref document = this->document();
1724 document->unregisterForVisibilityStateChangedCallbacks(*this);
1725#if ENABLE(MODEL_PROCESS)(defined 0 && 0)
1726 document->decrementModelElementCount();
1727#endif
1728 LazyLoadModelObserver::unobserve(*this, document);
1729
1730 m_loadModelTimer = nullptr;
1731
1732 deleteModelPlayer();
1733 }
1734}
1735
1736void HTMLModelElement::reportExtraMemoryCost()
1737{
1738 const size_t currentCost = memoryCost();
1739 if (m_reportedDataMemoryCost < currentCost) {
1740 RefPtr context = Node::scriptExecutionContext();
1741 if (!context)
1742 return;
1743 JSC::VM& vm = context->vm();
1744 JSC::JSLockHolder lock(vm);
1745 ASSERT_WITH_MESSAGE(vm.currentThreadIsHoldingAPILock(), "Extra memory reporting expects to happen from one thread")((void)0);
1746 vm.heap.reportExtraMemoryAllocated(nullptr, currentCost - m_reportedDataMemoryCost);
1747 m_reportedDataMemoryCost = currentCost;
1748 }
1749}
1750
1751size_t HTMLModelElement::memoryCost() const
1752{
1753 // May be called from GC threads.
1754 auto cost = m_dataMemoryCost.load(std::memory_order_relaxed);
1755#if ENABLE(MODEL_ELEMENT_ENVIRONMENT_MAP)(defined (0 || 0) && (0 || 0))
1756 cost += m_environmentMapDataMemoryCost.load(std::memory_order_relaxed);
1757#endif
1758 return cost;
1759}
1760
1761#if ENABLE(RESOURCE_USAGE)(defined 1 && 1)
1762
1763size_t HTMLModelElement::externalMemoryCost() const
1764{
1765 // For the purposes of Web Inspector, external memory means memory reported as
1766 // 1) being traceable from JS objects, i.e. GC owned memory
1767 // 2) not allocated from "Page" category, e.g. from bmalloc.
1768 return memoryCost();
1769}
1770
1771#endif
1772
1773void HTMLModelElement::sourceRequestResource()
1774{
1775 if (m_sourceURL.isEmpty())
1776 return triggerModelPlayerCreationCallbacksIfNeeded(Exception { ExceptionCode::AbortError, "The source URL is empty"_s });
1777
1778 auto request = createResourceRequest(m_sourceURL, FetchOptions::Destination::Model);
1779 auto resource = protect(protect(document())->cachedResourceLoader())->requestModelResource(WTF::move(request));
1780 if (!resource.has_value()) {
1781 ActiveDOMObject::queueTaskToDispatchEvent(*this, TaskSource::DOMManipulation, Event::create(eventNames().errorEvent, Event::CanBubble::No, Event::IsCancelable::No));
1782 if (!m_readyPromise->isFulfilled())
1783 m_readyPromise->reject(Exception { ExceptionCode::NetworkError });
1784
1785 triggerModelPlayerCreationCallbacksIfNeeded(Exception { ExceptionCode::NetworkError, "The model resource cannot be created"_s });
1786 return;
1787 }
1788
1789 m_data.empty();
1790
1791 m_resource = resource.value();
1792 m_resource->addClient(*this);
1793}
1794
1795void HTMLModelElement::viewportIntersectionChanged(bool isIntersecting)
1796{
1797 if (isIntersecting == m_isIntersectingViewport)
1798 return;
1799
1800 m_isIntersectingViewport = isIntersecting;
1801
1802 visibilityStateChanged();
1803}
1804
1805bool HTMLModelElement::isModelDeferred() const
1806{
1807 return !m_model && !m_resource;
1808}
1809
1810bool HTMLModelElement::isModelLoading() const
1811{
1812 if (!isVisible())
1813 return false;
1814
1815 if ((!m_model && m_resource) || (m_model && !m_modelPlayer))
1816 return true;
1817
1818 RefPtr modelPlayer = m_modelPlayer;
1819 return modelPlayer && modelPlayer->isPlaceholder();
1820}
1821
1822bool HTMLModelElement::isModelLoaded() const
1823{
1824 if (!isVisible())
1825 return false;
1826
1827 RefPtr modelPlayer = m_modelPlayer;
1828 return modelPlayer && !modelPlayer->isPlaceholder();
1829}
1830
1831bool HTMLModelElement::isModelUnloading() const
1832{
1833 if (isVisible())
1834 return false;
1835
1836 RefPtr modelPlayer = m_modelPlayer;
1837 return modelPlayer && !modelPlayer->isPlaceholder();
1838}
1839
1840bool HTMLModelElement::isModelUnloaded() const
1841{
1842 if (isVisible() || !m_model)
1843 return false;
1844
1845 RefPtr modelPlayer = m_modelPlayer;
1846 return !modelPlayer || modelPlayer->isPlaceholder();
1847}
1848
1849String HTMLModelElement::modelElementStateForTesting() const
1850{
1851 if (isModelDeferred())
1852 return "Deferred"_s;
1853 if (isModelLoading())
1854 return "Loading"_s;
1855 if (isModelLoaded())
1856 return "Loaded"_s;
1857 if (isModelUnloading())
1858 return "Unloading"_s;
1859 if (isModelUnloaded())
1860 return "Unloaded"_s;
1861
1862 ASSERT_NOT_REACHED()((void)0);
1863 return "Unknown"_s;
1864}
1865
1866} // namespace WebCore
1867
1868#endif // ENABLE(MODEL_ELEMENT)