2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "Internals.h"
30 #include "AXObjectCache.h"
31 #include "ActiveDOMCallbackMicrotask.h"
32 #include "ActivityState.h"
33 #include "AnimationTimeline.h"
34 #include "ApplicationCacheStorage.h"
35 #include "AudioSession.h"
37 #include "BackForwardController.h"
38 #include "BitmapImage.h"
39 #include "CSSAnimationController.h"
40 #include "CSSKeyframesRule.h"
41 #include "CSSMediaRule.h"
42 #include "CSSStyleRule.h"
43 #include "CSSSupportsRule.h"
44 #include "CacheStorageConnection.h"
45 #include "CacheStorageProvider.h"
46 #include "CachedImage.h"
47 #include "CachedResourceLoader.h"
49 #include "ClientOrigin.h"
50 #include "ComposedTreeIterator.h"
51 #include "CookieJar.h"
54 #include "DOMRectList.h"
55 #include "DOMStringList.h"
56 #include "DOMWindow.h"
57 #include "DeprecatedGlobalSettings.h"
58 #include "DisabledAdaptations.h"
59 #include "DisplayList.h"
61 #include "DocumentLoader.h"
62 #include "DocumentMarkerController.h"
63 #include "DocumentTimeline.h"
66 #include "EventHandler.h"
67 #include "ExtendableEvent.h"
68 #include "ExtensionStyleSheets.h"
69 #include "FetchResponse.h"
71 #include "FontCache.h"
72 #include "FormController.h"
74 #include "FrameLoader.h"
75 #include "FrameView.h"
76 #include "GCObservation.h"
77 #include "GridPosition.h"
78 #include "HEVCUtilities.h"
79 #include "HTMLAnchorElement.h"
80 #include "HTMLCanvasElement.h"
81 #include "HTMLIFrameElement.h"
82 #include "HTMLImageElement.h"
83 #include "HTMLInputElement.h"
84 #include "HTMLLinkElement.h"
85 #include "HTMLNames.h"
86 #include "HTMLPictureElement.h"
87 #include "HTMLPlugInElement.h"
88 #include "HTMLPreloadScanner.h"
89 #include "HTMLSelectElement.h"
90 #include "HTMLTextAreaElement.h"
91 #include "HTMLVideoElement.h"
92 #include "HistoryController.h"
93 #include "HistoryItem.h"
94 #include "HitTestResult.h"
95 #include "InspectorClient.h"
96 #include "InspectorController.h"
97 #include "InspectorFrontendClientLocal.h"
98 #include "InspectorOverlay.h"
99 #include "InstrumentingAgents.h"
101 #include "InternalSettings.h"
102 #include "JSImageData.h"
103 #include "LibWebRTCProvider.h"
104 #include "LoaderStrategy.h"
105 #include "MallocStatistics.h"
106 #include "MediaEngineConfigurationFactory.h"
107 #include "MediaPlayer.h"
108 #include "MediaProducer.h"
109 #include "MediaResourceLoader.h"
110 #include "MediaStreamTrack.h"
111 #include "MemoryCache.h"
112 #include "MemoryInfo.h"
113 #include "MockLibWebRTCPeerConnection.h"
114 #include "MockPageOverlay.h"
115 #include "MockPageOverlayClient.h"
116 #include "NetworkLoadInformation.h"
118 #include "PDFDocumentImage.h"
121 #include "PageCache.h"
122 #include "PageOverlay.h"
123 #include "PathUtilities.h"
124 #include "PlatformMediaSessionManager.h"
125 #include "PlatformScreen.h"
126 #include "PlatformStrategies.h"
127 #include "PluginData.h"
128 #include "PrintContext.h"
129 #include "PseudoElement.h"
131 #include "ReadableStream.h"
132 #include "RenderEmbeddedObject.h"
133 #include "RenderLayerBacking.h"
134 #include "RenderLayerCompositor.h"
135 #include "RenderMenuList.h"
136 #include "RenderTreeAsText.h"
137 #include "RenderView.h"
138 #include "RenderedDocumentMarker.h"
139 #include "ResourceLoadObserver.h"
140 #include "RuntimeEnabledFeatures.h"
141 #include "SMILTimeContainer.h"
142 #include "SVGDocumentExtensions.h"
143 #include "SVGPathStringBuilder.h"
144 #include "SVGSVGElement.h"
145 #include "SWClientConnection.h"
146 #include "SchemeRegistry.h"
147 #include "ScriptedAnimationController.h"
148 #include "ScrollingCoordinator.h"
149 #include "ScrollingMomentumCalculator.h"
150 #include "SecurityOrigin.h"
151 #include "SerializedScriptValue.h"
152 #include "ServiceWorker.h"
153 #include "ServiceWorkerProvider.h"
154 #include "ServiceWorkerRegistrationData.h"
155 #include "Settings.h"
156 #include "ShadowRoot.h"
157 #include "SourceBuffer.h"
158 #include "SpellChecker.h"
159 #include "StaticNodeList.h"
160 #include "StringCallback.h"
161 #include "StyleRule.h"
162 #include "StyleScope.h"
163 #include "StyleSheetContents.h"
164 #include "TextIterator.h"
165 #include "TreeScope.h"
166 #include "TypeConversions.h"
167 #include "UserGestureIndicator.h"
168 #include "UserMediaController.h"
169 #include "ViewportArguments.h"
170 #include "VoidCallback.h"
171 #include "WebCoreJSClientData.h"
172 #include "WindowProxy.h"
173 #include "WorkerThread.h"
174 #include "WritingDirection.h"
175 #include "XMLHttpRequest.h"
176 #include <JavaScriptCore/CodeBlock.h>
177 #include <JavaScriptCore/InspectorAgentBase.h>
178 #include <JavaScriptCore/InspectorFrontendChannel.h>
179 #include <JavaScriptCore/JSCInlines.h>
180 #include <JavaScriptCore/JSCJSValue.h>
181 #include <wtf/JSONValues.h>
182 #include <wtf/Language.h>
183 #include <wtf/MemoryPressureHandler.h>
184 #include <wtf/MonotonicTime.h>
185 #include <wtf/text/StringBuffer.h>
186 #include <wtf/text/StringBuilder.h>
187 #include <wtf/text/StringConcatenateNumbers.h>
188 #include <wtf/text/StringView.h>
190 #if ENABLE(INPUT_TYPE_COLOR)
191 #include "ColorChooser.h"
194 #if ENABLE(MOUSE_CURSOR_SCALE)
195 #include <wtf/dtoa.h>
198 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
199 #include "LegacyCDM.h"
200 #include "LegacyMockCDM.h"
203 #if ENABLE(ENCRYPTED_MEDIA)
204 #include "MockCDMFactory.h"
207 #if ENABLE(VIDEO_TRACK)
208 #include "CaptionUserPreferences.h"
209 #include "PageGroup.h"
213 #include "HTMLMediaElement.h"
214 #include "TimeRanges.h"
218 #include "WebGLRenderingContext.h"
221 #if ENABLE(SPEECH_SYNTHESIS)
222 #include "DOMWindowSpeechSynthesis.h"
223 #include "PlatformSpeechSynthesizerMock.h"
224 #include "SpeechSynthesis.h"
227 #if ENABLE(MEDIA_STREAM)
228 #include "MediaStream.h"
229 #include "MockRealtimeMediaSourceCenter.h"
233 #include "RTCPeerConnection.h"
236 #if ENABLE(MEDIA_SOURCE)
237 #include "MockMediaPlayerMediaSource.h"
240 #if ENABLE(CONTENT_FILTERING)
241 #include "MockContentFilterSettings.h"
244 #if ENABLE(WEB_AUDIO)
245 #include "AudioContext.h"
248 #if ENABLE(MEDIA_SESSION)
249 #include "MediaSession.h"
250 #include "MediaSessionManager.h"
253 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
254 #include "MediaPlaybackTargetContext.h"
257 #if ENABLE(POINTER_LOCK)
258 #include "PointerLockController.h"
262 #include "MockPreviewLoaderClient.h"
263 #include "PreviewLoader.h"
266 #if ENABLE(APPLE_PAY)
267 #include "MockPaymentCoordinator.h"
268 #include "PaymentCoordinator.h"
271 #if ENABLE(WEB_AUTHN)
272 #include "AuthenticatorCoordinator.h"
273 #include "MockAuthenticatorCoordinator.h"
276 #if PLATFORM(MAC) && USE(LIBWEBRTC)
277 #include <webrtc/sdk/WebKit/VideoProcessingSoftLink.h>
282 using JSC::CodeBlock;
283 using JSC::FunctionExecutable;
284 using JSC::Identifier;
285 using JSC::JSFunction;
286 using JSC::JSGlobalObject;
289 using JSC::MarkedArgumentBuffer;
290 using JSC::PropertySlot;
291 using JSC::ScriptExecutable;
292 using JSC::StackVisitor;
296 using namespace Inspector;
298 using namespace HTMLNames;
300 class InspectorStubFrontend final : public InspectorFrontendClientLocal, public FrontendChannel {
302 InspectorStubFrontend(Page& inspectedPage, RefPtr<DOMWindow>&& frontendWindow);
303 virtual ~InspectorStubFrontend();
306 void attachWindow(DockSide) final { }
307 void detachWindow() final { }
308 void closeWindow() final;
309 void bringToFront() final { }
310 String localizedStringsURL() final { return String(); }
311 void inspectedURLChanged(const String&) final { }
312 void setAttachedWindowHeight(unsigned) final { }
313 void setAttachedWindowWidth(unsigned) final { }
315 void sendMessageToFrontend(const String& message) final;
316 ConnectionType connectionType() const final { return ConnectionType::Local; }
318 Page* frontendPage() const
320 if (!m_frontendWindow || !m_frontendWindow->document())
323 return m_frontendWindow->document()->page();
326 RefPtr<DOMWindow> m_frontendWindow;
327 InspectorController& m_frontendController;
330 InspectorStubFrontend::InspectorStubFrontend(Page& inspectedPage, RefPtr<DOMWindow>&& frontendWindow)
331 : InspectorFrontendClientLocal(&inspectedPage.inspectorController(), frontendWindow->document()->page(), std::make_unique<InspectorFrontendClientLocal::Settings>())
332 , m_frontendWindow(frontendWindow.copyRef())
333 , m_frontendController(frontendPage()->inspectorController())
335 ASSERT_ARG(frontendWindow, frontendWindow);
337 m_frontendController.setInspectorFrontendClient(this);
338 inspectedPage.inspectorController().connectFrontend(this);
341 InspectorStubFrontend::~InspectorStubFrontend()
346 void InspectorStubFrontend::closeWindow()
348 if (!m_frontendWindow)
351 m_frontendController.setInspectorFrontendClient(nullptr);
352 inspectedPage()->inspectorController().disconnectFrontend(this);
354 m_frontendWindow->close();
355 m_frontendWindow = nullptr;
358 void InspectorStubFrontend::sendMessageToFrontend(const String& message)
360 ASSERT_ARG(message, !message.isEmpty());
362 InspectorClient::doDispatchMessageOnFrontendPage(frontendPage(), message);
365 static bool markerTypeFrom(const String& markerType, DocumentMarker::MarkerType& result)
367 if (equalLettersIgnoringASCIICase(markerType, "spelling"))
368 result = DocumentMarker::Spelling;
369 else if (equalLettersIgnoringASCIICase(markerType, "grammar"))
370 result = DocumentMarker::Grammar;
371 else if (equalLettersIgnoringASCIICase(markerType, "textmatch"))
372 result = DocumentMarker::TextMatch;
373 else if (equalLettersIgnoringASCIICase(markerType, "replacement"))
374 result = DocumentMarker::Replacement;
375 else if (equalLettersIgnoringASCIICase(markerType, "correctionindicator"))
376 result = DocumentMarker::CorrectionIndicator;
377 else if (equalLettersIgnoringASCIICase(markerType, "rejectedcorrection"))
378 result = DocumentMarker::RejectedCorrection;
379 else if (equalLettersIgnoringASCIICase(markerType, "autocorrected"))
380 result = DocumentMarker::Autocorrected;
381 else if (equalLettersIgnoringASCIICase(markerType, "spellcheckingexemption"))
382 result = DocumentMarker::SpellCheckingExemption;
383 else if (equalLettersIgnoringASCIICase(markerType, "deletedautocorrection"))
384 result = DocumentMarker::DeletedAutocorrection;
385 else if (equalLettersIgnoringASCIICase(markerType, "dictationalternatives"))
386 result = DocumentMarker::DictationAlternatives;
387 #if ENABLE(TELEPHONE_NUMBER_DETECTION)
388 else if (equalLettersIgnoringASCIICase(markerType, "telephonenumber"))
389 result = DocumentMarker::TelephoneNumber;
397 static bool markerTypesFrom(const String& markerType, OptionSet<DocumentMarker::MarkerType>& result)
399 DocumentMarker::MarkerType singularResult;
401 if (markerType.isEmpty() || equalLettersIgnoringASCIICase(markerType, "all"))
402 result = DocumentMarker::allMarkers();
403 else if (markerTypeFrom(markerType, singularResult))
404 result = singularResult;
411 static std::unique_ptr<PrintContext>& printContextForTesting()
413 static NeverDestroyed<std::unique_ptr<PrintContext>> context;
417 const char* Internals::internalsId = "internals";
419 Ref<Internals> Internals::create(Document& document)
421 return adoptRef(*new Internals(document));
424 Internals::~Internals()
426 #if ENABLE(MEDIA_STREAM)
428 m_track->source().removeObserver(*this);
432 void Internals::resetToConsistentState(Page& page)
434 page.setPageScaleFactor(1, IntPoint(0, 0));
435 page.setPagination(Pagination());
436 page.setPaginationLineGridEnabled(false);
438 page.setDefersLoading(false);
440 page.mainFrame().setTextZoomFactor(1.0f);
442 page.setCompositingPolicyOverride(std::nullopt);
444 FrameView* mainFrameView = page.mainFrame().view();
446 mainFrameView->setHeaderHeight(0);
447 mainFrameView->setFooterHeight(0);
448 page.setTopContentInset(0);
449 mainFrameView->setUseFixedLayout(false);
450 mainFrameView->setFixedLayoutSize(IntSize());
451 #if USE(COORDINATED_GRAPHICS)
452 mainFrameView->setFixedVisibleContentRect(IntRect());
454 if (auto* backing = mainFrameView->tiledBacking())
455 backing->setTileSizeUpdateDelayDisabledForTesting(false);
458 WebCore::clearDefaultPortForProtocolMapForTesting();
459 overrideUserPreferredLanguages(Vector<String>());
460 WebCore::DeprecatedGlobalSettings::setUsesOverlayScrollbars(false);
461 WebCore::DeprecatedGlobalSettings::setUsesMockScrollAnimator(false);
462 #if ENABLE(VIDEO_TRACK)
463 page.group().captionPreferences().setTestingMode(true);
464 page.group().captionPreferences().setCaptionsStyleSheetOverride(emptyString());
465 page.group().captionPreferences().setTestingMode(false);
467 if (!page.mainFrame().editor().isContinuousSpellCheckingEnabled())
468 page.mainFrame().editor().toggleContinuousSpellChecking();
469 if (page.mainFrame().editor().isOverwriteModeEnabled())
470 page.mainFrame().editor().toggleOverwriteModeEnabled();
471 page.mainFrame().loader().clearTestingOverrides();
472 page.applicationCacheStorage().setDefaultOriginQuota(ApplicationCacheStorage::noQuota());
474 PlatformMediaSessionManager::sharedManager().resetRestrictions();
475 PlatformMediaSessionManager::sharedManager().setWillIgnoreSystemInterruptions(true);
477 #if HAVE(ACCESSIBILITY)
478 AXObjectCache::setEnhancedUserInterfaceAccessibility(false);
479 AXObjectCache::disableAccessibility();
482 MockPageOverlayClient::singleton().uninstallAllOverlays();
484 #if ENABLE(CONTENT_FILTERING)
485 MockContentFilterSettings::reset();
488 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
489 page.setMockMediaPlaybackTargetPickerEnabled(true);
490 page.setMockMediaPlaybackTargetPickerState(emptyString(), MediaPlaybackTargetContext::Unknown);
493 page.setShowAllPlugins(false);
494 page.setLowPowerModeEnabledOverrideForTesting(std::nullopt);
497 MockPreviewLoaderClient::singleton().setPassword("");
498 PreviewLoader::setClientForTesting(nullptr);
501 printContextForTesting() = nullptr;
504 auto& rtcProvider = page.libWebRTCProvider();
505 WebCore::useRealRTCPeerConnectionFactory(rtcProvider);
506 rtcProvider.disableNonLocalhostConnections();
507 RuntimeEnabledFeatures::sharedFeatures().setWebRTCUnifiedPlanEnabled(true);
510 page.settings().setStorageAccessAPIEnabled(false);
511 page.setFullscreenAutoHideDuration(0_s);
512 page.setFullscreenInsets({ });
513 page.setFullscreenControlsHidden(false);
515 MediaEngineConfigurationFactory::disableMock();
518 Internals::Internals(Document& document)
519 : ContextDestructionObserver(&document)
520 #if ENABLE(MEDIA_STREAM)
521 , m_orientationNotifier(0)
524 #if ENABLE(VIDEO_TRACK)
526 document.page()->group().captionPreferences().setTestingMode(true);
529 #if ENABLE(MEDIA_STREAM)
530 setMockMediaCaptureDevicesEnabled(true);
531 WebCore::DeprecatedGlobalSettings::setMediaCaptureRequiresSecureConnection(false);
534 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
536 document.page()->setMockMediaPlaybackTargetPickerEnabled(true);
539 if (contextDocument() && contextDocument()->frame()) {
540 setAutomaticSpellingCorrectionEnabled(true);
541 setAutomaticQuoteSubstitutionEnabled(false);
542 setAutomaticDashSubstitutionEnabled(false);
543 setAutomaticLinkDetectionEnabled(false);
544 setAutomaticTextReplacementEnabled(true);
547 setConsoleMessageListener(nullptr);
549 #if ENABLE(APPLE_PAY)
550 auto* frame = document.frame();
551 if (frame && frame->page()) {
552 m_mockPaymentCoordinator = new MockPaymentCoordinator(*frame->page());
553 frame->page()->setPaymentCoordinator(std::make_unique<PaymentCoordinator>(*m_mockPaymentCoordinator));
557 #if ENABLE(WEB_AUTHN)
558 if (document.page()) {
559 auto mockAuthenticatorCoordinator = std::make_unique<MockAuthenticatorCoordinator>();
560 m_mockAuthenticatorCoordinator = makeWeakPtr(mockAuthenticatorCoordinator.get());
561 document.page()->authenticatorCoordinator().setClient(WTFMove(mockAuthenticatorCoordinator));
566 Document* Internals::contextDocument() const
568 return downcast<Document>(scriptExecutionContext());
571 Frame* Internals::frame() const
573 if (!contextDocument())
575 return contextDocument()->frame();
578 InternalSettings* Internals::settings() const
580 Document* document = contextDocument();
583 Page* page = document->page();
586 return InternalSettings::from(page);
589 unsigned Internals::workerThreadCount() const
591 return WorkerThread::workerThreadCount();
594 ExceptionOr<bool> Internals::areSVGAnimationsPaused() const
596 auto* document = contextDocument();
598 return Exception { InvalidAccessError, "No context document"_s };
600 if (!document->svgExtensions())
601 return Exception { NotFoundError, "No SVG animations"_s };
603 return document->accessSVGExtensions().areAnimationsPaused();
606 ExceptionOr<double> Internals::svgAnimationsInterval(SVGSVGElement& element) const
608 auto* document = contextDocument();
612 if (!document->svgExtensions())
615 if (document->accessSVGExtensions().areAnimationsPaused())
618 return element.timeContainer().animationFrameDelay().value();
621 String Internals::address(Node& node)
623 return String::format("%p", &node);
626 bool Internals::nodeNeedsStyleRecalc(Node& node)
628 return node.needsStyleRecalc();
631 static String styleValidityToToString(Style::Validity validity)
634 case Style::Validity::Valid:
635 return "NoStyleChange";
636 case Style::Validity::ElementInvalid:
637 return "InlineStyleChange";
638 case Style::Validity::SubtreeInvalid:
639 return "FullStyleChange";
640 case Style::Validity::SubtreeAndRenderersInvalid:
641 return "ReconstructRenderTree";
643 ASSERT_NOT_REACHED();
647 String Internals::styleChangeType(Node& node)
649 node.document().styleScope().flushPendingUpdate();
651 return styleValidityToToString(node.styleValidity());
654 String Internals::description(JSC::JSValue value)
656 return toString(value);
659 bool Internals::isPreloaded(const String& url)
661 Document* document = contextDocument();
662 return document->cachedResourceLoader().isPreloaded(url);
665 bool Internals::isLoadingFromMemoryCache(const String& url)
667 if (!contextDocument() || !contextDocument()->page())
670 ResourceRequest request(contextDocument()->completeURL(url));
671 request.setDomainForCachePartition(contextDocument()->domainForCachePartition());
673 CachedResource* resource = MemoryCache::singleton().resourceForRequest(request, contextDocument()->page()->sessionID());
674 return resource && resource->status() == CachedResource::Cached;
677 static String responseSourceToString(const ResourceResponse& response)
679 if (response.isNull())
680 return "Null response";
681 switch (response.source()) {
682 case ResourceResponse::Source::Unknown:
684 case ResourceResponse::Source::Network:
686 case ResourceResponse::Source::ServiceWorker:
687 return "Service worker";
688 case ResourceResponse::Source::DiskCache:
690 case ResourceResponse::Source::DiskCacheAfterValidation:
691 return "Disk cache after validation";
692 case ResourceResponse::Source::MemoryCache:
693 return "Memory cache";
694 case ResourceResponse::Source::MemoryCacheAfterValidation:
695 return "Memory cache after validation";
696 case ResourceResponse::Source::ApplicationCache:
697 return "Application cache";
699 ASSERT_NOT_REACHED();
703 String Internals::xhrResponseSource(XMLHttpRequest& request)
705 return responseSourceToString(request.resourceResponse());
708 String Internals::fetchResponseSource(FetchResponse& response)
710 return responseSourceToString(response.resourceResponse());
713 bool Internals::isSharingStyleSheetContents(HTMLLinkElement& a, HTMLLinkElement& b)
715 if (!a.sheet() || !b.sheet())
717 return &a.sheet()->contents() == &b.sheet()->contents();
720 bool Internals::isStyleSheetLoadingSubresources(HTMLLinkElement& link)
722 return link.sheet() && link.sheet()->contents().isLoadingSubresources();
725 static ResourceRequestCachePolicy toResourceRequestCachePolicy(Internals::CachePolicy policy)
728 case Internals::CachePolicy::UseProtocolCachePolicy:
729 return ResourceRequestCachePolicy::UseProtocolCachePolicy;
730 case Internals::CachePolicy::ReloadIgnoringCacheData:
731 return ResourceRequestCachePolicy::ReloadIgnoringCacheData;
732 case Internals::CachePolicy::ReturnCacheDataElseLoad:
733 return ResourceRequestCachePolicy::ReturnCacheDataElseLoad;
734 case Internals::CachePolicy::ReturnCacheDataDontLoad:
735 return ResourceRequestCachePolicy::ReturnCacheDataDontLoad;
737 ASSERT_NOT_REACHED();
738 return ResourceRequestCachePolicy::UseProtocolCachePolicy;
741 void Internals::setOverrideCachePolicy(CachePolicy policy)
743 frame()->loader().setOverrideCachePolicyForTesting(toResourceRequestCachePolicy(policy));
746 ExceptionOr<void> Internals::setCanShowModalDialogOverride(bool allow)
748 if (!contextDocument() || !contextDocument()->domWindow())
749 return Exception { InvalidAccessError };
751 contextDocument()->domWindow()->setCanShowModalDialogOverride(allow);
755 static ResourceLoadPriority toResourceLoadPriority(Internals::ResourceLoadPriority priority)
758 case Internals::ResourceLoadPriority::ResourceLoadPriorityVeryLow:
759 return ResourceLoadPriority::VeryLow;
760 case Internals::ResourceLoadPriority::ResourceLoadPriorityLow:
761 return ResourceLoadPriority::Low;
762 case Internals::ResourceLoadPriority::ResourceLoadPriorityMedium:
763 return ResourceLoadPriority::Medium;
764 case Internals::ResourceLoadPriority::ResourceLoadPriorityHigh:
765 return ResourceLoadPriority::High;
766 case Internals::ResourceLoadPriority::ResourceLoadPriorityVeryHigh:
767 return ResourceLoadPriority::VeryHigh;
769 ASSERT_NOT_REACHED();
770 return ResourceLoadPriority::Low;
773 void Internals::setOverrideResourceLoadPriority(ResourceLoadPriority priority)
775 frame()->loader().setOverrideResourceLoadPriorityForTesting(toResourceLoadPriority(priority));
778 void Internals::setStrictRawResourceValidationPolicyDisabled(bool disabled)
780 frame()->loader().setStrictRawResourceValidationPolicyDisabledForTesting(disabled);
783 void Internals::clearMemoryCache()
785 MemoryCache::singleton().evictResources();
788 void Internals::pruneMemoryCacheToSize(unsigned size)
790 MemoryCache::singleton().pruneDeadResourcesToSize(size);
791 MemoryCache::singleton().pruneLiveResourcesToSize(size, true);
794 void Internals::destroyDecodedDataForAllImages()
796 MemoryCache::singleton().destroyDecodedDataForAllImages();
799 unsigned Internals::memoryCacheSize() const
801 return MemoryCache::singleton().size();
804 static Image* imageFromImageElement(HTMLImageElement& element)
806 auto* cachedImage = element.cachedImage();
807 return cachedImage ? cachedImage->image() : nullptr;
810 static BitmapImage* bitmapImageFromImageElement(HTMLImageElement& element)
812 auto* image = imageFromImageElement(element);
813 return image && is<BitmapImage>(image) ? &downcast<BitmapImage>(*image) : nullptr;
817 static PDFDocumentImage* pdfDocumentImageFromImageElement(HTMLImageElement& element)
819 auto* image = imageFromImageElement(element);
820 return image && is<PDFDocumentImage>(image) ? &downcast<PDFDocumentImage>(*image) : nullptr;
824 unsigned Internals::imageFrameIndex(HTMLImageElement& element)
826 auto* bitmapImage = bitmapImageFromImageElement(element);
827 return bitmapImage ? bitmapImage->currentFrame() : 0;
830 void Internals::setImageFrameDecodingDuration(HTMLImageElement& element, float duration)
832 if (auto* bitmapImage = bitmapImageFromImageElement(element))
833 bitmapImage->setFrameDecodingDurationForTesting(Seconds { duration });
836 void Internals::resetImageAnimation(HTMLImageElement& element)
838 if (auto* image = imageFromImageElement(element))
839 image->resetAnimation();
842 bool Internals::isImageAnimating(HTMLImageElement& element)
844 auto* image = imageFromImageElement(element);
845 return image && (image->isAnimating() || image->animationPending());
848 void Internals::setClearDecoderAfterAsyncFrameRequestForTesting(HTMLImageElement& element, bool enabled)
850 if (auto* bitmapImage = bitmapImageFromImageElement(element))
851 bitmapImage->setClearDecoderAfterAsyncFrameRequestForTesting(enabled);
854 unsigned Internals::imageDecodeCount(HTMLImageElement& element)
856 auto* bitmapImage = bitmapImageFromImageElement(element);
857 return bitmapImage ? bitmapImage->decodeCountForTesting() : 0;
860 unsigned Internals::pdfDocumentCachingCount(HTMLImageElement& element)
863 auto* pdfDocumentImage = pdfDocumentImageFromImageElement(element);
864 return pdfDocumentImage ? pdfDocumentImage->cachingCountForTesting() : 0;
866 UNUSED_PARAM(element);
871 void Internals::setLargeImageAsyncDecodingEnabledForTesting(HTMLImageElement& element, bool enabled)
873 if (auto* bitmapImage = bitmapImageFromImageElement(element))
874 bitmapImage->setLargeImageAsyncDecodingEnabledForTesting(enabled);
877 void Internals::setForceUpdateImageDataEnabledForTesting(HTMLImageElement& element, bool enabled)
879 if (auto* cachedImage = element.cachedImage())
880 cachedImage->setForceUpdateImageDataEnabledForTesting(enabled);
883 void Internals::setGridMaxTracksLimit(unsigned maxTrackLimit)
885 GridPosition::setMaxPositionForTesting(maxTrackLimit);
888 void Internals::clearPageCache()
890 PageCache::singleton().pruneToSizeNow(0, PruningReason::None);
893 unsigned Internals::pageCacheSize() const
895 return PageCache::singleton().pageCount();
898 void Internals::disableTileSizeUpdateDelay()
900 Document* document = contextDocument();
901 if (!document || !document->frame())
904 auto* view = document->frame()->view();
908 if (auto* backing = view->tiledBacking())
909 backing->setTileSizeUpdateDelayDisabledForTesting(true);
912 void Internals::setSpeculativeTilingDelayDisabledForTesting(bool disabled)
914 Document* document = contextDocument();
915 if (!document || !document->frame())
918 if (auto* frameView = document->frame()->view())
919 frameView->setSpeculativeTilingDelayDisabledForTesting(disabled);
923 Node* Internals::treeScopeRootNode(Node& node)
925 return &node.treeScope().rootNode();
928 Node* Internals::parentTreeScope(Node& node)
930 const TreeScope* parentTreeScope = node.treeScope().parentTreeScope();
931 return parentTreeScope ? &parentTreeScope->rootNode() : nullptr;
934 ExceptionOr<unsigned> Internals::lastSpatialNavigationCandidateCount() const
936 if (!contextDocument() || !contextDocument()->page())
937 return Exception { InvalidAccessError };
939 return contextDocument()->page()->lastSpatialNavigationCandidateCount();
942 unsigned Internals::numberOfActiveAnimations() const
944 if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled())
945 return frame()->document()->timeline().numberOfActiveAnimationsForTesting();
946 return frame()->animation().numberOfActiveAnimations(frame()->document());
949 ExceptionOr<bool> Internals::animationsAreSuspended() const
951 Document* document = contextDocument();
952 if (!document || !document->frame())
953 return Exception { InvalidAccessError };
955 if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled())
956 return document->timeline().animationsAreSuspended();
957 return document->frame()->animation().animationsAreSuspendedForDocument(document);
960 double Internals::animationsInterval() const
962 Document* document = contextDocument();
966 if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled()) {
967 if (auto timeline = document->existingTimeline())
968 return timeline->animationInterval().seconds();
972 if (!document->frame())
974 return document->frame()->animation().animationInterval().value();
977 ExceptionOr<void> Internals::suspendAnimations() const
979 Document* document = contextDocument();
980 if (!document || !document->frame())
981 return Exception { InvalidAccessError };
983 if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled()) {
984 document->timeline().suspendAnimations();
985 for (Frame* frame = document->frame(); frame; frame = frame->tree().traverseNext()) {
986 if (Document* document = frame->document())
987 document->timeline().suspendAnimations();
990 document->frame()->animation().suspendAnimationsForDocument(document);
992 for (Frame* frame = document->frame(); frame; frame = frame->tree().traverseNext()) {
993 if (Document* document = frame->document())
994 frame->animation().suspendAnimationsForDocument(document);
1001 ExceptionOr<void> Internals::resumeAnimations() const
1003 Document* document = contextDocument();
1004 if (!document || !document->frame())
1005 return Exception { InvalidAccessError };
1007 if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled()) {
1008 document->timeline().resumeAnimations();
1009 for (Frame* frame = document->frame(); frame; frame = frame->tree().traverseNext()) {
1010 if (Document* document = frame->document())
1011 document->timeline().resumeAnimations();
1014 document->frame()->animation().resumeAnimationsForDocument(document);
1016 for (Frame* frame = document->frame(); frame; frame = frame->tree().traverseNext()) {
1017 if (Document* document = frame->document())
1018 frame->animation().resumeAnimationsForDocument(document);
1025 ExceptionOr<bool> Internals::pauseAnimationAtTimeOnElement(const String& animationName, double pauseTime, Element& element)
1028 return Exception { InvalidAccessError };
1029 return frame()->animation().pauseAnimationAtTime(element, AtomicString(animationName), pauseTime);
1032 ExceptionOr<bool> Internals::pauseAnimationAtTimeOnPseudoElement(const String& animationName, double pauseTime, Element& element, const String& pseudoId)
1035 return Exception { InvalidAccessError };
1037 if (pseudoId != "before" && pseudoId != "after")
1038 return Exception { InvalidAccessError };
1040 PseudoElement* pseudoElement = pseudoId == "before" ? element.beforePseudoElement() : element.afterPseudoElement();
1042 return Exception { InvalidAccessError };
1044 return frame()->animation().pauseAnimationAtTime(*pseudoElement, AtomicString(animationName), pauseTime);
1047 ExceptionOr<bool> Internals::pauseTransitionAtTimeOnElement(const String& propertyName, double pauseTime, Element& element)
1050 return Exception { InvalidAccessError };
1051 return frame()->animation().pauseTransitionAtTime(element, propertyName, pauseTime);
1054 ExceptionOr<bool> Internals::pauseTransitionAtTimeOnPseudoElement(const String& property, double pauseTime, Element& element, const String& pseudoId)
1057 return Exception { InvalidAccessError };
1059 if (pseudoId != "before" && pseudoId != "after")
1060 return Exception { InvalidAccessError };
1062 PseudoElement* pseudoElement = pseudoId == "before" ? element.beforePseudoElement() : element.afterPseudoElement();
1064 return Exception { InvalidAccessError };
1066 return frame()->animation().pauseTransitionAtTime(*pseudoElement, property, pauseTime);
1069 Vector<Internals::AcceleratedAnimation> Internals::acceleratedAnimationsForElement(Element& element)
1071 if (!RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled())
1074 Vector<Internals::AcceleratedAnimation> animations;
1075 for (auto animationAsPair : element.document().timeline().acceleratedAnimationsForElement(element))
1076 animations.append({ animationAsPair.first, animationAsPair.second });
1080 unsigned Internals::numberOfAnimationTimelineInvalidations() const
1082 if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled())
1083 return frame()->document()->timeline().numberOfAnimationTimelineInvalidationsForTesting();
1087 ExceptionOr<RefPtr<Element>> Internals::pseudoElement(Element& element, const String& pseudoId)
1089 if (pseudoId != "before" && pseudoId != "after")
1090 return Exception { InvalidAccessError };
1092 return pseudoId == "before" ? element.beforePseudoElement() : element.afterPseudoElement();
1095 ExceptionOr<String> Internals::elementRenderTreeAsText(Element& element)
1097 element.document().updateStyleIfNeeded();
1099 String representation = externalRepresentation(&element);
1100 if (representation.isEmpty())
1101 return Exception { InvalidAccessError };
1103 return WTFMove(representation);
1106 bool Internals::hasPausedImageAnimations(Element& element)
1108 return element.renderer() && element.renderer()->hasPausedImageAnimations();
1111 bool Internals::isPaintingFrequently(Element& element)
1113 return element.renderer() && element.renderer()->enclosingLayer() && element.renderer()->enclosingLayer()->paintingFrequently();
1116 void Internals::incrementFrequentPaintCounter(Element& element)
1118 if (element.renderer() && element.renderer()->enclosingLayer())
1119 element.renderer()->enclosingLayer()->simulateFrequentPaint();
1122 Ref<CSSComputedStyleDeclaration> Internals::computedStyleIncludingVisitedInfo(Element& element) const
1124 bool allowVisitedStyle = true;
1125 return CSSComputedStyleDeclaration::create(element, allowVisitedStyle);
1128 Node* Internals::ensureUserAgentShadowRoot(Element& host)
1130 return &host.ensureUserAgentShadowRoot();
1133 Node* Internals::shadowRoot(Element& host)
1135 return host.shadowRoot();
1138 ExceptionOr<String> Internals::shadowRootType(const Node& root) const
1140 if (!is<ShadowRoot>(root))
1141 return Exception { InvalidAccessError };
1143 switch (downcast<ShadowRoot>(root).mode()) {
1144 case ShadowRootMode::UserAgent:
1145 return String("UserAgentShadowRoot");
1146 case ShadowRootMode::Closed:
1147 return String("ClosedShadowRoot");
1148 case ShadowRootMode::Open:
1149 return String("OpenShadowRoot");
1151 ASSERT_NOT_REACHED();
1152 return String("Unknown");
1156 String Internals::shadowPseudoId(Element& element)
1158 return element.shadowPseudoId().string();
1161 void Internals::setShadowPseudoId(Element& element, const String& id)
1163 return element.setPseudo(id);
1166 static unsigned deferredStyleRulesCountForList(const Vector<RefPtr<StyleRuleBase>>& childRules)
1169 for (auto rule : childRules) {
1170 if (is<StyleRule>(rule)) {
1171 auto* cssRule = downcast<StyleRule>(rule.get());
1172 if (!cssRule->propertiesWithoutDeferredParsing())
1177 StyleRuleGroup* groupRule = nullptr;
1178 if (is<StyleRuleMedia>(rule))
1179 groupRule = downcast<StyleRuleMedia>(rule.get());
1180 else if (is<StyleRuleSupports>(rule))
1181 groupRule = downcast<StyleRuleSupports>(rule.get());
1185 auto* groupChildRules = groupRule->childRulesWithoutDeferredParsing();
1186 if (!groupChildRules)
1189 count += deferredStyleRulesCountForList(*groupChildRules);
1195 unsigned Internals::deferredStyleRulesCount(StyleSheet& styleSheet)
1197 return deferredStyleRulesCountForList(downcast<CSSStyleSheet>(styleSheet).contents().childRules());
1200 static unsigned deferredGroupRulesCountForList(const Vector<RefPtr<StyleRuleBase>>& childRules)
1203 for (auto rule : childRules) {
1204 StyleRuleGroup* groupRule = nullptr;
1205 if (is<StyleRuleMedia>(rule))
1206 groupRule = downcast<StyleRuleMedia>(rule.get());
1207 else if (is<StyleRuleSupports>(rule))
1208 groupRule = downcast<StyleRuleSupports>(rule.get());
1212 auto* groupChildRules = groupRule->childRulesWithoutDeferredParsing();
1213 if (!groupChildRules)
1216 count += deferredGroupRulesCountForList(*groupChildRules);
1221 unsigned Internals::deferredGroupRulesCount(StyleSheet& styleSheet)
1223 return deferredGroupRulesCountForList(downcast<CSSStyleSheet>(styleSheet).contents().childRules());
1226 static unsigned deferredKeyframesRulesCountForList(const Vector<RefPtr<StyleRuleBase>>& childRules)
1229 for (auto rule : childRules) {
1230 if (is<StyleRuleKeyframes>(rule)) {
1231 auto* cssRule = downcast<StyleRuleKeyframes>(rule.get());
1232 if (!cssRule->keyframesWithoutDeferredParsing())
1237 StyleRuleGroup* groupRule = nullptr;
1238 if (is<StyleRuleMedia>(rule))
1239 groupRule = downcast<StyleRuleMedia>(rule.get());
1240 else if (is<StyleRuleSupports>(rule))
1241 groupRule = downcast<StyleRuleSupports>(rule.get());
1245 auto* groupChildRules = groupRule->childRulesWithoutDeferredParsing();
1246 if (!groupChildRules)
1249 count += deferredKeyframesRulesCountForList(*groupChildRules);
1255 unsigned Internals::deferredKeyframesRulesCount(StyleSheet& styleSheet)
1257 StyleSheetContents& contents = downcast<CSSStyleSheet>(styleSheet).contents();
1258 return deferredKeyframesRulesCountForList(contents.childRules());
1261 ExceptionOr<bool> Internals::isTimerThrottled(int timeoutId)
1263 auto* timer = scriptExecutionContext()->findTimeout(timeoutId);
1265 return Exception { NotFoundError };
1267 if (timer->intervalClampedToMinimum() > timer->m_originalInterval)
1270 return !!timer->alignedFireTime(MonotonicTime { });
1273 bool Internals::isRequestAnimationFrameThrottled() const
1275 auto* scriptedAnimationController = contextDocument()->scriptedAnimationController();
1276 if (!scriptedAnimationController)
1278 return scriptedAnimationController->isThrottled();
1281 double Internals::requestAnimationFrameInterval() const
1283 auto* scriptedAnimationController = contextDocument()->scriptedAnimationController();
1284 if (!scriptedAnimationController)
1286 return scriptedAnimationController->interval().value();
1289 bool Internals::scriptedAnimationsAreSuspended() const
1291 Document* document = contextDocument();
1292 if (!document || !document->page())
1295 return document->page()->scriptedAnimationsSuspended();
1298 bool Internals::areTimersThrottled() const
1300 return contextDocument()->isTimerThrottlingEnabled();
1303 void Internals::setEventThrottlingBehaviorOverride(std::optional<EventThrottlingBehavior> value)
1305 Document* document = contextDocument();
1306 if (!document || !document->page())
1310 document->page()->setEventThrottlingBehaviorOverride(std::nullopt);
1314 switch (value.value()) {
1315 case Internals::EventThrottlingBehavior::Responsive:
1316 document->page()->setEventThrottlingBehaviorOverride(WebCore::EventThrottlingBehavior::Responsive);
1318 case Internals::EventThrottlingBehavior::Unresponsive:
1319 document->page()->setEventThrottlingBehaviorOverride(WebCore::EventThrottlingBehavior::Unresponsive);
1324 std::optional<Internals::EventThrottlingBehavior> Internals::eventThrottlingBehaviorOverride() const
1326 Document* document = contextDocument();
1327 if (!document || !document->page())
1328 return std::nullopt;
1330 auto behavior = document->page()->eventThrottlingBehaviorOverride();
1332 return std::nullopt;
1334 switch (behavior.value()) {
1335 case WebCore::EventThrottlingBehavior::Responsive:
1336 return Internals::EventThrottlingBehavior::Responsive;
1337 case WebCore::EventThrottlingBehavior::Unresponsive:
1338 return Internals::EventThrottlingBehavior::Unresponsive;
1341 return std::nullopt;
1344 String Internals::visiblePlaceholder(Element& element)
1346 if (is<HTMLTextFormControlElement>(element)) {
1347 const HTMLTextFormControlElement& textFormControlElement = downcast<HTMLTextFormControlElement>(element);
1348 if (!textFormControlElement.isPlaceholderVisible())
1350 if (HTMLElement* placeholderElement = textFormControlElement.placeholderElement())
1351 return placeholderElement->textContent();
1357 void Internals::selectColorInColorChooser(HTMLInputElement& element, const String& colorValue)
1359 element.selectColor(colorValue);
1362 ExceptionOr<Vector<String>> Internals::formControlStateOfPreviousHistoryItem()
1364 HistoryItem* mainItem = frame()->loader().history().previousItem();
1366 return Exception { InvalidAccessError };
1367 String uniqueName = frame()->tree().uniqueName();
1368 if (mainItem->target() != uniqueName && !mainItem->childItemWithTarget(uniqueName))
1369 return Exception { InvalidAccessError };
1370 return Vector<String> { mainItem->target() == uniqueName ? mainItem->documentState() : mainItem->childItemWithTarget(uniqueName)->documentState() };
1373 ExceptionOr<void> Internals::setFormControlStateOfPreviousHistoryItem(const Vector<String>& state)
1375 HistoryItem* mainItem = frame()->loader().history().previousItem();
1377 return Exception { InvalidAccessError };
1378 String uniqueName = frame()->tree().uniqueName();
1379 if (mainItem->target() == uniqueName)
1380 mainItem->setDocumentState(state);
1381 else if (HistoryItem* subItem = mainItem->childItemWithTarget(uniqueName))
1382 subItem->setDocumentState(state);
1384 return Exception { InvalidAccessError };
1388 #if ENABLE(SPEECH_SYNTHESIS)
1390 void Internals::enableMockSpeechSynthesizer()
1392 Document* document = contextDocument();
1393 if (!document || !document->domWindow())
1395 SpeechSynthesis* synthesis = DOMWindowSpeechSynthesis::speechSynthesis(*document->domWindow());
1399 synthesis->setPlatformSynthesizer(std::make_unique<PlatformSpeechSynthesizerMock>(synthesis));
1406 void Internals::emulateRTCPeerConnectionPlatformEvent(RTCPeerConnection& connection, const String& action)
1408 if (!LibWebRTCProvider::webRTCAvailable())
1411 connection.emulatePlatformEvent(action);
1414 void Internals::useMockRTCPeerConnectionFactory(const String& testCase)
1416 // FIXME: We should upgrade mocks to support unified plan APIs, until then use plan B in tests using mock.
1418 ASSERT(!RuntimeEnabledFeatures::sharedFeatures().webRTCUnifiedPlanEnabled());
1419 if (!LibWebRTCProvider::webRTCAvailable())
1423 Document* document = contextDocument();
1424 LibWebRTCProvider* provider = (document && document->page()) ? &document->page()->libWebRTCProvider() : nullptr;
1425 WebCore::useMockRTCPeerConnectionFactory(provider, testCase);
1427 UNUSED_PARAM(testCase);
1431 void Internals::setICECandidateFiltering(bool enabled)
1433 auto* page = contextDocument()->page();
1437 auto& rtcController = page->rtcController();
1439 rtcController.enableICECandidateFiltering();
1441 rtcController.disableICECandidateFilteringForAllOrigins();
1444 void Internals::setEnumeratingAllNetworkInterfacesEnabled(bool enabled)
1447 Document* document = contextDocument();
1448 auto* page = document->page();
1451 auto& rtcProvider = page->libWebRTCProvider();
1453 rtcProvider.enableEnumeratingAllNetworkInterfaces();
1455 rtcProvider.disableEnumeratingAllNetworkInterfaces();
1457 UNUSED_PARAM(enabled);
1461 void Internals::stopPeerConnection(RTCPeerConnection& connection)
1463 ActiveDOMObject& object = connection;
1467 void Internals::applyRotationForOutgoingVideoSources(RTCPeerConnection& connection)
1469 connection.applyRotationForOutgoingVideoSources();
1473 #if ENABLE(MEDIA_STREAM)
1475 void Internals::setMockMediaCaptureDevicesEnabled(bool enabled)
1477 WebCore::DeprecatedGlobalSettings::setMockCaptureDevicesEnabled(enabled);
1482 ExceptionOr<Ref<DOMRect>> Internals::absoluteCaretBounds()
1484 Document* document = contextDocument();
1485 if (!document || !document->frame())
1486 return Exception { InvalidAccessError };
1488 return DOMRect::create(document->frame()->selection().absoluteCaretBounds());
1491 Ref<DOMRect> Internals::boundingBox(Element& element)
1493 element.document().updateLayoutIgnorePendingStylesheets();
1494 auto renderer = element.renderer();
1496 return DOMRect::create();
1497 return DOMRect::create(renderer->absoluteBoundingBoxRectIgnoringTransforms());
1500 ExceptionOr<Ref<DOMRectList>> Internals::inspectorHighlightRects()
1502 Document* document = contextDocument();
1503 if (!document || !document->page())
1504 return Exception { InvalidAccessError };
1506 Highlight highlight;
1507 document->page()->inspectorController().getHighlight(highlight, InspectorOverlay::CoordinateSystem::View);
1508 return DOMRectList::create(highlight.quads);
1511 ExceptionOr<String> Internals::inspectorHighlightObject()
1513 Document* document = contextDocument();
1514 if (!document || !document->page())
1515 return Exception { InvalidAccessError };
1517 return document->page()->inspectorController().buildObjectForHighlightedNodes()->toJSONString();
1520 ExceptionOr<unsigned> Internals::markerCountForNode(Node& node, const String& markerType)
1522 OptionSet<DocumentMarker::MarkerType> markerTypes;
1523 if (!markerTypesFrom(markerType, markerTypes))
1524 return Exception { SyntaxError };
1526 node.document().frame()->editor().updateEditorUINowIfScheduled();
1527 return node.document().markers().markersFor(&node, markerTypes).size();
1530 ExceptionOr<RenderedDocumentMarker*> Internals::markerAt(Node& node, const String& markerType, unsigned index)
1532 node.document().updateLayoutIgnorePendingStylesheets();
1534 OptionSet<DocumentMarker::MarkerType> markerTypes;
1535 if (!markerTypesFrom(markerType, markerTypes))
1536 return Exception { SyntaxError };
1538 node.document().frame()->editor().updateEditorUINowIfScheduled();
1540 Vector<RenderedDocumentMarker*> markers = node.document().markers().markersFor(&node, markerTypes);
1541 if (markers.size() <= index)
1543 return markers[index];
1546 ExceptionOr<RefPtr<Range>> Internals::markerRangeForNode(Node& node, const String& markerType, unsigned index)
1548 auto result = markerAt(node, markerType, index);
1549 if (result.hasException())
1550 return result.releaseException();
1551 auto marker = result.releaseReturnValue();
1554 return RefPtr<Range> { Range::create(node.document(), &node, marker->startOffset(), &node, marker->endOffset()) };
1557 ExceptionOr<String> Internals::markerDescriptionForNode(Node& node, const String& markerType, unsigned index)
1559 auto result = markerAt(node, markerType, index);
1560 if (result.hasException())
1561 return result.releaseException();
1562 auto marker = result.releaseReturnValue();
1565 return String { marker->description() };
1568 ExceptionOr<String> Internals::dumpMarkerRects(const String& markerTypeString)
1570 DocumentMarker::MarkerType markerType;
1571 if (!markerTypeFrom(markerTypeString, markerType))
1572 return Exception { SyntaxError };
1574 contextDocument()->markers().updateRectsForInvalidatedMarkersOfType(markerType);
1575 auto rects = contextDocument()->markers().renderedRectsForMarkers(markerType);
1577 StringBuilder rectString;
1578 rectString.appendLiteral("marker rects: ");
1579 for (const auto& rect : rects) {
1580 rectString.append('(');
1581 rectString.appendNumber(rect.x());
1582 rectString.appendLiteral(", ");
1583 rectString.appendNumber(rect.y());
1584 rectString.appendLiteral(", ");
1585 rectString.appendNumber(rect.width());
1586 rectString.appendLiteral(", ");
1587 rectString.appendNumber(rect.height());
1588 rectString.appendLiteral(") ");
1590 return rectString.toString();
1593 void Internals::addTextMatchMarker(const Range& range, bool isActive)
1595 range.ownerDocument().updateLayoutIgnorePendingStylesheets();
1596 range.ownerDocument().markers().addTextMatchMarker(&range, isActive);
1599 ExceptionOr<void> Internals::setMarkedTextMatchesAreHighlighted(bool flag)
1601 Document* document = contextDocument();
1602 if (!document || !document->frame())
1603 return Exception { InvalidAccessError };
1604 document->frame()->editor().setMarkedTextMatchesAreHighlighted(flag);
1608 void Internals::invalidateFontCache()
1610 FontCache::singleton().invalidate();
1613 void Internals::setFontSmoothingEnabled(bool enabled)
1615 WebCore::FontCascade::setShouldUseSmoothing(enabled);
1618 ExceptionOr<void> Internals::setLowPowerModeEnabled(bool isEnabled)
1620 auto* document = contextDocument();
1622 return Exception { InvalidAccessError };
1623 auto* page = document->page();
1625 return Exception { InvalidAccessError };
1627 page->setLowPowerModeEnabledOverrideForTesting(isEnabled);
1631 ExceptionOr<void> Internals::setScrollViewPosition(int x, int y)
1633 Document* document = contextDocument();
1634 if (!document || !document->view())
1635 return Exception { InvalidAccessError };
1637 auto& frameView = *document->view();
1638 bool constrainsScrollingToContentEdgeOldValue = frameView.constrainsScrollingToContentEdge();
1639 bool scrollbarsSuppressedOldValue = frameView.scrollbarsSuppressed();
1641 frameView.setConstrainsScrollingToContentEdge(false);
1642 frameView.setScrollbarsSuppressed(false);
1643 frameView.setScrollOffsetFromInternals({ x, y });
1644 frameView.setScrollbarsSuppressed(scrollbarsSuppressedOldValue);
1645 frameView.setConstrainsScrollingToContentEdge(constrainsScrollingToContentEdgeOldValue);
1650 ExceptionOr<void> Internals::unconstrainedScrollTo(Element& element, double x, double y)
1652 Document* document = contextDocument();
1653 if (!document || !document->view())
1654 return Exception { InvalidAccessError };
1656 element.scrollTo({ x, y }, ScrollClamping::Unclamped);
1660 ExceptionOr<Ref<DOMRect>> Internals::layoutViewportRect()
1662 Document* document = contextDocument();
1663 if (!document || !document->frame())
1664 return Exception { InvalidAccessError };
1666 document->updateLayoutIgnorePendingStylesheets();
1668 auto& frameView = *document->view();
1669 return DOMRect::create(frameView.layoutViewportRect());
1672 ExceptionOr<Ref<DOMRect>> Internals::visualViewportRect()
1674 Document* document = contextDocument();
1675 if (!document || !document->frame())
1676 return Exception { InvalidAccessError };
1678 document->updateLayoutIgnorePendingStylesheets();
1680 auto& frameView = *document->view();
1681 return DOMRect::create(frameView.visualViewportRect());
1684 ExceptionOr<void> Internals::setViewBaseBackgroundColor(const String& colorValue)
1686 Document* document = contextDocument();
1687 if (!document || !document->view())
1688 return Exception { InvalidAccessError };
1690 if (colorValue == "transparent") {
1691 document->view()->setBaseBackgroundColor(Color::transparent);
1694 if (colorValue == "white") {
1695 document->view()->setBaseBackgroundColor(Color::white);
1698 return Exception { SyntaxError };
1701 ExceptionOr<void> Internals::setPagination(const String& mode, int gap, int pageLength)
1703 Document* document = contextDocument();
1704 if (!document || !document->page())
1705 return Exception { InvalidAccessError };
1707 Pagination pagination;
1708 if (mode == "Unpaginated")
1709 pagination.mode = Pagination::Unpaginated;
1710 else if (mode == "LeftToRightPaginated")
1711 pagination.mode = Pagination::LeftToRightPaginated;
1712 else if (mode == "RightToLeftPaginated")
1713 pagination.mode = Pagination::RightToLeftPaginated;
1714 else if (mode == "TopToBottomPaginated")
1715 pagination.mode = Pagination::TopToBottomPaginated;
1716 else if (mode == "BottomToTopPaginated")
1717 pagination.mode = Pagination::BottomToTopPaginated;
1719 return Exception { SyntaxError };
1721 pagination.gap = gap;
1722 pagination.pageLength = pageLength;
1723 document->page()->setPagination(pagination);
1728 ExceptionOr<void> Internals::setPaginationLineGridEnabled(bool enabled)
1730 Document* document = contextDocument();
1731 if (!document || !document->page())
1732 return Exception { InvalidAccessError };
1733 document->page()->setPaginationLineGridEnabled(enabled);
1737 ExceptionOr<String> Internals::configurationForViewport(float devicePixelRatio, int deviceWidth, int deviceHeight, int availableWidth, int availableHeight)
1739 Document* document = contextDocument();
1740 if (!document || !document->page())
1741 return Exception { InvalidAccessError };
1743 const int defaultLayoutWidthForNonMobilePages = 980;
1745 ViewportArguments arguments = document->page()->viewportArguments();
1746 ViewportAttributes attributes = computeViewportAttributes(arguments, defaultLayoutWidthForNonMobilePages, deviceWidth, deviceHeight, devicePixelRatio, IntSize(availableWidth, availableHeight));
1747 restrictMinimumScaleFactorToViewportSize(attributes, IntSize(availableWidth, availableHeight), devicePixelRatio);
1748 restrictScaleFactorToInitialScaleIfNotUserScalable(attributes);
1750 return String { "viewport size " + String::number(attributes.layoutSize.width()) + "x" + String::number(attributes.layoutSize.height()) + " scale " + String::number(attributes.initialScale) + " with limits [" + String::number(attributes.minimumScale) + ", " + String::number(attributes.maximumScale) + "] and userScalable " + (attributes.userScalable ? "true" : "false") };
1753 ExceptionOr<bool> Internals::wasLastChangeUserEdit(Element& textField)
1755 if (is<HTMLInputElement>(textField))
1756 return downcast<HTMLInputElement>(textField).lastChangeWasUserEdit();
1758 if (is<HTMLTextAreaElement>(textField))
1759 return downcast<HTMLTextAreaElement>(textField).lastChangeWasUserEdit();
1761 return Exception { InvalidNodeTypeError };
1764 bool Internals::elementShouldAutoComplete(HTMLInputElement& element)
1766 return element.shouldAutocomplete();
1769 void Internals::setEditingValue(HTMLInputElement& element, const String& value)
1771 element.setEditingValue(value);
1774 void Internals::setAutofilled(HTMLInputElement& element, bool enabled)
1776 element.setAutoFilled(enabled);
1779 static AutoFillButtonType toAutoFillButtonType(Internals::AutoFillButtonType type)
1782 case Internals::AutoFillButtonType::None:
1783 return AutoFillButtonType::None;
1784 case Internals::AutoFillButtonType::Credentials:
1785 return AutoFillButtonType::Credentials;
1786 case Internals::AutoFillButtonType::Contacts:
1787 return AutoFillButtonType::Contacts;
1788 case Internals::AutoFillButtonType::StrongPassword:
1789 return AutoFillButtonType::StrongPassword;
1791 ASSERT_NOT_REACHED();
1792 return AutoFillButtonType::None;
1795 static Internals::AutoFillButtonType toInternalsAutoFillButtonType(AutoFillButtonType type)
1798 case AutoFillButtonType::None:
1799 return Internals::AutoFillButtonType::None;
1800 case AutoFillButtonType::Credentials:
1801 return Internals::AutoFillButtonType::Credentials;
1802 case AutoFillButtonType::Contacts:
1803 return Internals::AutoFillButtonType::Contacts;
1804 case AutoFillButtonType::StrongPassword:
1805 return Internals::AutoFillButtonType::StrongPassword;
1807 ASSERT_NOT_REACHED();
1808 return Internals::AutoFillButtonType::None;
1811 void Internals::setShowAutoFillButton(HTMLInputElement& element, AutoFillButtonType type)
1813 element.setShowAutoFillButton(toAutoFillButtonType(type));
1816 auto Internals::autoFillButtonType(const HTMLInputElement& element) -> AutoFillButtonType
1818 return toInternalsAutoFillButtonType(element.autoFillButtonType());
1821 auto Internals::lastAutoFillButtonType(const HTMLInputElement& element) -> AutoFillButtonType
1823 return toInternalsAutoFillButtonType(element.lastAutoFillButtonType());
1826 ExceptionOr<void> Internals::scrollElementToRect(Element& element, int x, int y, int w, int h)
1828 FrameView* frameView = element.document().view();
1830 return Exception { InvalidAccessError };
1831 frameView->scrollElementToRect(element, { x, y, w, h });
1835 ExceptionOr<String> Internals::autofillFieldName(Element& element)
1837 if (!is<HTMLFormControlElement>(element))
1838 return Exception { InvalidNodeTypeError };
1840 return String { downcast<HTMLFormControlElement>(element).autofillData().fieldName };
1843 ExceptionOr<void> Internals::invalidateControlTints()
1845 Document* document = contextDocument();
1846 if (!document || !document->view())
1847 return Exception { InvalidAccessError };
1849 document->view()->invalidateControlTints();
1853 RefPtr<Range> Internals::rangeFromLocationAndLength(Element& scope, int rangeLocation, int rangeLength)
1855 return TextIterator::rangeFromLocationAndLength(&scope, rangeLocation, rangeLength);
1858 unsigned Internals::locationFromRange(Element& scope, const Range& range)
1860 size_t location = 0;
1861 size_t unusedLength = 0;
1862 TextIterator::getLocationAndLengthFromRange(&scope, &range, location, unusedLength);
1866 unsigned Internals::lengthFromRange(Element& scope, const Range& range)
1868 size_t unusedLocation = 0;
1870 TextIterator::getLocationAndLengthFromRange(&scope, &range, unusedLocation, length);
1874 String Internals::rangeAsText(const Range& range)
1876 return range.text();
1879 Ref<Range> Internals::subrange(Range& range, int rangeLocation, int rangeLength)
1881 return TextIterator::subrange(range, rangeLocation, rangeLength);
1884 RefPtr<Range> Internals::rangeOfStringNearLocation(const Range& searchRange, const String& text, unsigned targetOffset)
1886 return findClosestPlainText(searchRange, text, { }, targetOffset);
1890 ExceptionOr<RefPtr<Range>> Internals::rangeForDictionaryLookupAtLocation(int, int)
1892 return Exception { InvalidAccessError };
1896 ExceptionOr<void> Internals::setDelegatesScrolling(bool enabled)
1898 Document* document = contextDocument();
1899 // Delegate scrolling is valid only on mainframe's view.
1900 if (!document || !document->view() || !document->page() || &document->page()->mainFrame() != document->frame())
1901 return Exception { InvalidAccessError };
1903 document->view()->setDelegatesScrolling(enabled);
1907 ExceptionOr<int> Internals::lastSpellCheckRequestSequence()
1909 Document* document = contextDocument();
1910 if (!document || !document->frame())
1911 return Exception { InvalidAccessError };
1913 return document->frame()->editor().spellChecker().lastRequestSequence();
1916 ExceptionOr<int> Internals::lastSpellCheckProcessedSequence()
1918 Document* document = contextDocument();
1919 if (!document || !document->frame())
1920 return Exception { InvalidAccessError };
1922 return document->frame()->editor().spellChecker().lastProcessedSequence();
1925 Vector<String> Internals::userPreferredLanguages() const
1927 return WTF::userPreferredLanguages();
1930 void Internals::setUserPreferredLanguages(const Vector<String>& languages)
1932 overrideUserPreferredLanguages(languages);
1935 Vector<String> Internals::userPreferredAudioCharacteristics() const
1937 Document* document = contextDocument();
1938 if (!document || !document->page())
1939 return Vector<String>();
1940 #if ENABLE(VIDEO_TRACK)
1941 return document->page()->group().captionPreferences().preferredAudioCharacteristics();
1943 return Vector<String>();
1947 void Internals::setUserPreferredAudioCharacteristic(const String& characteristic)
1949 Document* document = contextDocument();
1950 if (!document || !document->page())
1952 #if ENABLE(VIDEO_TRACK)
1953 document->page()->group().captionPreferences().setPreferredAudioCharacteristic(characteristic);
1955 UNUSED_PARAM(characteristic);
1959 ExceptionOr<unsigned> Internals::wheelEventHandlerCount()
1961 Document* document = contextDocument();
1963 return Exception { InvalidAccessError };
1965 return document->wheelEventHandlerCount();
1968 ExceptionOr<unsigned> Internals::touchEventHandlerCount()
1970 Document* document = contextDocument();
1972 return Exception { InvalidAccessError };
1974 return document->touchEventHandlerCount();
1977 ExceptionOr<Ref<DOMRectList>> Internals::touchEventRectsForEvent(const String& eventName)
1979 Document* document = contextDocument();
1980 if (!document || !document->page())
1981 return Exception { InvalidAccessError };
1983 return document->page()->touchEventRectsForEvent(eventName);
1986 ExceptionOr<Ref<DOMRectList>> Internals::passiveTouchEventListenerRects()
1988 Document* document = contextDocument();
1989 if (!document || !document->page())
1990 return Exception { InvalidAccessError };
1992 return document->page()->passiveTouchEventListenerRects();
1995 // FIXME: Remove the document argument. It is almost always the same as
1996 // contextDocument(), with the exception of a few tests that pass a
1997 // different document, and could just make the call through another Internals
1998 // instance instead.
1999 ExceptionOr<RefPtr<NodeList>> Internals::nodesFromRect(Document& document, int centerX, int centerY, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding, bool ignoreClipping, bool allowUserAgentShadowContent, bool allowChildFrameContent) const
2001 if (!document.frame() || !document.frame()->view())
2002 return Exception { InvalidAccessError };
2004 Frame* frame = document.frame();
2005 FrameView* frameView = document.view();
2006 RenderView* renderView = document.renderView();
2010 document.updateLayoutIgnorePendingStylesheets();
2012 float zoomFactor = frame->pageZoomFactor();
2013 LayoutPoint point(centerX * zoomFactor + frameView->scrollX(), centerY * zoomFactor + frameView->scrollY());
2015 HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::CollectMultipleElements;
2017 hitType |= HitTestRequest::IgnoreClipping;
2018 if (!allowUserAgentShadowContent)
2019 hitType |= HitTestRequest::DisallowUserAgentShadowContent;
2020 if (allowChildFrameContent)
2021 hitType |= HitTestRequest::AllowChildFrameContent;
2023 HitTestRequest request(hitType);
2025 // When ignoreClipping is false, this method returns null for coordinates outside of the viewport.
2026 if (!request.ignoreClipping() && !frameView->visibleContentRect().intersects(HitTestLocation::rectForPoint(point, topPadding, rightPadding, bottomPadding, leftPadding)))
2029 HitTestResult result(point, topPadding, rightPadding, bottomPadding, leftPadding);
2030 renderView->hitTest(request, result);
2031 const HitTestResult::NodeSet& nodeSet = result.listBasedTestResult();
2032 Vector<Ref<Node>> matches;
2033 matches.reserveInitialCapacity(nodeSet.size());
2034 for (auto& node : nodeSet)
2035 matches.uncheckedAppend(*node);
2037 return RefPtr<NodeList> { StaticNodeList::create(WTFMove(matches)) };
2040 class GetCallerCodeBlockFunctor {
2042 GetCallerCodeBlockFunctor()
2048 StackVisitor::Status operator()(StackVisitor& visitor) const
2051 if (m_iterations < 2)
2052 return StackVisitor::Continue;
2054 m_codeBlock = visitor->codeBlock();
2055 return StackVisitor::Done;
2058 CodeBlock* codeBlock() const { return m_codeBlock; }
2061 mutable int m_iterations;
2062 mutable CodeBlock* m_codeBlock;
2065 String Internals::parserMetaData(JSC::JSValue code)
2067 JSC::VM& vm = contextDocument()->vm();
2068 JSC::ExecState* exec = vm.topCallFrame;
2069 ScriptExecutable* executable;
2071 if (!code || code.isNull() || code.isUndefined()) {
2072 GetCallerCodeBlockFunctor iter;
2073 exec->iterate(iter);
2074 CodeBlock* codeBlock = iter.codeBlock();
2075 executable = codeBlock->ownerScriptExecutable();
2076 } else if (code.isFunction(vm)) {
2077 JSFunction* funcObj = JSC::jsCast<JSFunction*>(code.toObject(exec));
2078 executable = funcObj->jsExecutable();
2082 unsigned startLine = executable->firstLine();
2083 unsigned startColumn = executable->startColumn();
2084 unsigned endLine = executable->lastLine();
2085 unsigned endColumn = executable->endColumn();
2087 StringBuilder result;
2089 if (executable->isFunctionExecutable()) {
2090 FunctionExecutable* funcExecutable = reinterpret_cast<FunctionExecutable*>(executable);
2091 String inferredName = funcExecutable->inferredName().string();
2092 result.appendLiteral("function \"");
2093 result.append(inferredName);
2095 } else if (executable->isEvalExecutable())
2096 result.appendLiteral("eval");
2097 else if (executable->isModuleProgramExecutable())
2098 result.appendLiteral("module");
2099 else if (executable->isProgramExecutable())
2100 result.appendLiteral("program");
2102 ASSERT_NOT_REACHED();
2104 result.appendLiteral(" { ");
2105 result.appendNumber(startLine);
2107 result.appendNumber(startColumn);
2108 result.appendLiteral(" - ");
2109 result.appendNumber(endLine);
2111 result.appendNumber(endColumn);
2112 result.appendLiteral(" }");
2114 return result.toString();
2117 void Internals::updateEditorUINowIfScheduled()
2119 if (Document* document = contextDocument()) {
2120 if (Frame* frame = document->frame())
2121 frame->editor().updateEditorUINowIfScheduled();
2125 bool Internals::hasSpellingMarker(int from, int length)
2127 Document* document = contextDocument();
2128 if (!document || !document->frame())
2131 updateEditorUINowIfScheduled();
2133 return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
2136 bool Internals::hasAutocorrectedMarker(int from, int length)
2138 Document* document = contextDocument();
2139 if (!document || !document->frame())
2142 updateEditorUINowIfScheduled();
2144 return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Autocorrected, from, length);
2147 void Internals::setContinuousSpellCheckingEnabled(bool enabled)
2149 if (!contextDocument() || !contextDocument()->frame())
2152 if (enabled != contextDocument()->frame()->editor().isContinuousSpellCheckingEnabled())
2153 contextDocument()->frame()->editor().toggleContinuousSpellChecking();
2156 void Internals::setAutomaticQuoteSubstitutionEnabled(bool enabled)
2158 if (!contextDocument() || !contextDocument()->frame())
2161 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
2162 if (enabled != contextDocument()->frame()->editor().isAutomaticQuoteSubstitutionEnabled())
2163 contextDocument()->frame()->editor().toggleAutomaticQuoteSubstitution();
2165 UNUSED_PARAM(enabled);
2169 void Internals::setAutomaticLinkDetectionEnabled(bool enabled)
2171 if (!contextDocument() || !contextDocument()->frame())
2174 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
2175 if (enabled != contextDocument()->frame()->editor().isAutomaticLinkDetectionEnabled())
2176 contextDocument()->frame()->editor().toggleAutomaticLinkDetection();
2178 UNUSED_PARAM(enabled);
2182 void Internals::setAutomaticDashSubstitutionEnabled(bool enabled)
2184 if (!contextDocument() || !contextDocument()->frame())
2187 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
2188 if (enabled != contextDocument()->frame()->editor().isAutomaticDashSubstitutionEnabled())
2189 contextDocument()->frame()->editor().toggleAutomaticDashSubstitution();
2191 UNUSED_PARAM(enabled);
2195 void Internals::setAutomaticTextReplacementEnabled(bool enabled)
2197 if (!contextDocument() || !contextDocument()->frame())
2200 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
2201 if (enabled != contextDocument()->frame()->editor().isAutomaticTextReplacementEnabled())
2202 contextDocument()->frame()->editor().toggleAutomaticTextReplacement();
2204 UNUSED_PARAM(enabled);
2208 void Internals::setAutomaticSpellingCorrectionEnabled(bool enabled)
2210 if (!contextDocument() || !contextDocument()->frame())
2213 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
2214 if (enabled != contextDocument()->frame()->editor().isAutomaticSpellingCorrectionEnabled())
2215 contextDocument()->frame()->editor().toggleAutomaticSpellingCorrection();
2217 UNUSED_PARAM(enabled);
2221 void Internals::handleAcceptedCandidate(const String& candidate, unsigned location, unsigned length)
2223 if (!contextDocument() || !contextDocument()->frame())
2226 TextCheckingResult result;
2227 result.type = TextCheckingType::None;
2228 result.location = location;
2229 result.length = length;
2230 result.replacement = candidate;
2231 contextDocument()->frame()->editor().handleAcceptedCandidate(result);
2234 bool Internals::isOverwriteModeEnabled()
2236 Document* document = contextDocument();
2237 if (!document || !document->frame())
2240 return document->frame()->editor().isOverwriteModeEnabled();
2243 void Internals::toggleOverwriteModeEnabled()
2245 Document* document = contextDocument();
2246 if (!document || !document->frame())
2249 document->frame()->editor().toggleOverwriteModeEnabled();
2252 static ExceptionOr<FindOptions> parseFindOptions(const Vector<String>& optionList)
2256 FindOptionFlag value;
2258 {"CaseInsensitive", CaseInsensitive},
2259 {"AtWordStarts", AtWordStarts},
2260 {"TreatMedialCapitalAsWordStart", TreatMedialCapitalAsWordStart},
2261 {"Backwards", Backwards},
2262 {"WrapAround", WrapAround},
2263 {"StartInSelection", StartInSelection},
2264 {"DoNotRevealSelection", DoNotRevealSelection},
2265 {"AtWordEnds", AtWordEnds},
2266 {"DoNotTraverseFlatTree", DoNotTraverseFlatTree},
2269 for (auto& option : optionList) {
2271 for (auto& flag : flagList) {
2272 if (flag.name == option) {
2273 result.add(flag.value);
2279 return Exception { SyntaxError };
2281 return WTFMove(result);
2284 ExceptionOr<RefPtr<Range>> Internals::rangeOfString(const String& text, RefPtr<Range>&& referenceRange, const Vector<String>& findOptions)
2286 Document* document = contextDocument();
2287 if (!document || !document->frame())
2288 return Exception { InvalidAccessError };
2290 auto parsedOptions = parseFindOptions(findOptions);
2291 if (parsedOptions.hasException())
2292 return parsedOptions.releaseException();
2294 return document->frame()->editor().rangeOfString(text, referenceRange.get(), parsedOptions.releaseReturnValue());
2297 ExceptionOr<unsigned> Internals::countMatchesForText(const String& text, const Vector<String>& findOptions, const String& markMatches)
2299 Document* document = contextDocument();
2300 if (!document || !document->frame())
2301 return Exception { InvalidAccessError };
2303 auto parsedOptions = parseFindOptions(findOptions);
2304 if (parsedOptions.hasException())
2305 return parsedOptions.releaseException();
2307 bool mark = markMatches == "mark";
2308 return document->frame()->editor().countMatchesForText(text, nullptr, parsedOptions.releaseReturnValue(), 1000, mark, nullptr);
2311 ExceptionOr<unsigned> Internals::countFindMatches(const String& text, const Vector<String>& findOptions)
2313 Document* document = contextDocument();
2314 if (!document || !document->page())
2315 return Exception { InvalidAccessError };
2317 auto parsedOptions = parseFindOptions(findOptions);
2318 if (parsedOptions.hasException())
2319 return parsedOptions.releaseException();
2321 return document->page()->countFindMatches(text, parsedOptions.releaseReturnValue(), 1000);
2324 unsigned Internals::numberOfLiveNodes() const
2326 unsigned nodeCount = 0;
2327 for (auto* document : Document::allDocuments())
2328 nodeCount += document->referencingNodeCount();
2332 unsigned Internals::numberOfLiveDocuments() const
2334 return Document::allDocuments().size();
2337 unsigned Internals::referencingNodeCount(const Document& document) const
2339 return document.referencingNodeCount();
2342 #if ENABLE(INTERSECTION_OBSERVER)
2343 unsigned Internals::numberOfIntersectionObservers(const Document& document) const
2345 return document.numberOfIntersectionObservers();
2349 uint64_t Internals::documentIdentifier(const Document& document) const
2351 return document.identifier().toUInt64();
2354 bool Internals::isDocumentAlive(uint64_t documentIdentifier) const
2356 return Document::allDocumentsMap().contains(makeObjectIdentifier<DocumentIdentifierType>(documentIdentifier));
2359 String Internals::serviceWorkerClientIdentifier(const Document& document) const
2361 #if ENABLE(SERVICE_WORKER)
2362 return ServiceWorkerClientIdentifier { ServiceWorkerProvider::singleton().serviceWorkerConnectionForSession(document.sessionID()).serverConnectionIdentifier(), document.identifier() }.toString();
2364 UNUSED_PARAM(document);
2369 RefPtr<WindowProxy> Internals::openDummyInspectorFrontend(const String& url)
2371 auto* inspectedPage = contextDocument()->frame()->page();
2372 auto* window = inspectedPage->mainFrame().document()->domWindow();
2373 auto frontendWindowProxy = window->open(*window, *window, url, "", "").releaseReturnValue();
2374 m_inspectorFrontend = std::make_unique<InspectorStubFrontend>(*inspectedPage, downcast<DOMWindow>(frontendWindowProxy->window()));
2375 return frontendWindowProxy;
2378 void Internals::closeDummyInspectorFrontend()
2380 m_inspectorFrontend = nullptr;
2383 ExceptionOr<void> Internals::setInspectorIsUnderTest(bool isUnderTest)
2385 Page* page = contextDocument()->frame()->page();
2387 return Exception { InvalidAccessError };
2389 page->inspectorController().setIsUnderTest(isUnderTest);
2393 bool Internals::hasGrammarMarker(int from, int length)
2395 Document* document = contextDocument();
2396 if (!document || !document->frame())
2399 return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Grammar, from, length);
2402 unsigned Internals::numberOfScrollableAreas()
2404 Document* document = contextDocument();
2405 if (!document || !document->frame())
2409 Frame* frame = document->frame();
2410 if (frame->view()->scrollableAreas())
2411 count += frame->view()->scrollableAreas()->size();
2413 for (Frame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
2414 if (child->view() && child->view()->scrollableAreas())
2415 count += child->view()->scrollableAreas()->size();
2421 ExceptionOr<bool> Internals::isPageBoxVisible(int pageNumber)
2423 Document* document = contextDocument();
2425 return Exception { InvalidAccessError };
2427 return document->isPageBoxVisible(pageNumber);
2430 static LayerTreeFlags toLayerTreeFlags(unsigned short flags)
2432 LayerTreeFlags layerTreeFlags = 0;
2433 if (flags & Internals::LAYER_TREE_INCLUDES_VISIBLE_RECTS)
2434 layerTreeFlags |= LayerTreeFlagsIncludeVisibleRects;
2435 if (flags & Internals::LAYER_TREE_INCLUDES_TILE_CACHES)
2436 layerTreeFlags |= LayerTreeFlagsIncludeTileCaches;
2437 if (flags & Internals::LAYER_TREE_INCLUDES_REPAINT_RECTS)
2438 layerTreeFlags |= LayerTreeFlagsIncludeRepaintRects;
2439 if (flags & Internals::LAYER_TREE_INCLUDES_PAINTING_PHASES)
2440 layerTreeFlags |= LayerTreeFlagsIncludePaintingPhases;
2441 if (flags & Internals::LAYER_TREE_INCLUDES_CONTENT_LAYERS)
2442 layerTreeFlags |= LayerTreeFlagsIncludeContentLayers;
2443 if (flags & Internals::LAYER_TREE_INCLUDES_ACCELERATES_DRAWING)
2444 layerTreeFlags |= LayerTreeFlagsIncludeAcceleratesDrawing;
2445 if (flags & Internals::LAYER_TREE_INCLUDES_BACKING_STORE_ATTACHED)
2446 layerTreeFlags |= LayerTreeFlagsIncludeBackingStoreAttached;
2448 return layerTreeFlags;
2451 // FIXME: Remove the document argument. It is almost always the same as
2452 // contextDocument(), with the exception of a few tests that pass a
2453 // different document, and could just make the call through another Internals
2454 // instance instead.
2455 ExceptionOr<String> Internals::layerTreeAsText(Document& document, unsigned short flags) const
2457 if (!document.frame())
2458 return Exception { InvalidAccessError };
2460 document.updateLayoutIgnorePendingStylesheets();
2461 return document.frame()->layerTreeAsText(toLayerTreeFlags(flags));
2464 ExceptionOr<uint64_t> Internals::layerIDForElement(Element& element)
2466 Document* document = contextDocument();
2467 if (!document || !document->frame())
2468 return Exception { InvalidAccessError };
2470 element.document().updateLayoutIgnorePendingStylesheets();
2472 if (!element.renderer() || !element.renderer()->hasLayer())
2473 return Exception { NotFoundError };
2475 auto& layerModelObject = downcast<RenderLayerModelObject>(*element.renderer());
2476 if (!layerModelObject.layer()->isComposited())
2477 return Exception { NotFoundError };
2479 auto* backing = layerModelObject.layer()->backing();
2480 return backing->graphicsLayer()->primaryLayerID();
2483 ExceptionOr<String> Internals::repaintRectsAsText() const
2485 Document* document = contextDocument();
2486 if (!document || !document->frame())
2487 return Exception { InvalidAccessError };
2489 return document->frame()->trackedRepaintRectsAsText();
2492 ExceptionOr<String> Internals::scrollingStateTreeAsText() const
2494 Document* document = contextDocument();
2495 if (!document || !document->frame())
2496 return Exception { InvalidAccessError };
2498 Page* page = document->page();
2502 return page->scrollingStateTreeAsText();
2505 ExceptionOr<String> Internals::mainThreadScrollingReasons() const
2507 Document* document = contextDocument();
2508 if (!document || !document->frame())
2509 return Exception { InvalidAccessError };
2511 Page* page = document->page();
2515 return page->synchronousScrollingReasonsAsText();
2518 ExceptionOr<Ref<DOMRectList>> Internals::nonFastScrollableRects() const
2520 Document* document = contextDocument();
2521 if (!document || !document->frame())
2522 return Exception { InvalidAccessError };
2524 Page* page = document->page();
2526 return DOMRectList::create();
2528 return page->nonFastScrollableRects();
2531 ExceptionOr<void> Internals::setElementUsesDisplayListDrawing(Element& element, bool usesDisplayListDrawing)
2533 Document* document = contextDocument();
2534 if (!document || !document->renderView())
2535 return Exception { InvalidAccessError };
2537 element.document().updateLayoutIgnorePendingStylesheets();
2539 if (!element.renderer())
2540 return Exception { InvalidAccessError };
2542 if (is<HTMLCanvasElement>(element)) {
2543 downcast<HTMLCanvasElement>(element).setUsesDisplayListDrawing(usesDisplayListDrawing);
2547 if (!element.renderer()->hasLayer())
2548 return Exception { InvalidAccessError };
2550 RenderLayer* layer = downcast<RenderLayerModelObject>(element.renderer())->layer();
2551 if (!layer->isComposited())
2552 return Exception { InvalidAccessError };
2554 layer->backing()->setUsesDisplayListDrawing(usesDisplayListDrawing);
2558 ExceptionOr<void> Internals::setElementTracksDisplayListReplay(Element& element, bool isTrackingReplay)
2560 Document* document = contextDocument();
2561 if (!document || !document->renderView())
2562 return Exception { InvalidAccessError };
2564 element.document().updateLayoutIgnorePendingStylesheets();
2566 if (!element.renderer())
2567 return Exception { InvalidAccessError };
2569 if (is<HTMLCanvasElement>(element)) {
2570 downcast<HTMLCanvasElement>(element).setTracksDisplayListReplay(isTrackingReplay);
2574 if (!element.renderer()->hasLayer())
2575 return Exception { InvalidAccessError };
2577 RenderLayer* layer = downcast<RenderLayerModelObject>(element.renderer())->layer();
2578 if (!layer->isComposited())
2579 return Exception { InvalidAccessError };
2581 layer->backing()->setIsTrackingDisplayListReplay(isTrackingReplay);
2585 ExceptionOr<String> Internals::displayListForElement(Element& element, unsigned short flags)
2587 Document* document = contextDocument();
2588 if (!document || !document->renderView())
2589 return Exception { InvalidAccessError };
2591 element.document().updateLayoutIgnorePendingStylesheets();
2593 if (!element.renderer())
2594 return Exception { InvalidAccessError };
2596 DisplayList::AsTextFlags displayListFlags = 0;
2597 if (flags & DISPLAY_LIST_INCLUDES_PLATFORM_OPERATIONS)
2598 displayListFlags |= DisplayList::AsTextFlag::IncludesPlatformOperations;
2600 if (is<HTMLCanvasElement>(element))
2601 return downcast<HTMLCanvasElement>(element).displayListAsText(displayListFlags);
2603 if (!element.renderer()->hasLayer())
2604 return Exception { InvalidAccessError };
2606 RenderLayer* layer = downcast<RenderLayerModelObject>(element.renderer())->layer();
2607 if (!layer->isComposited())
2608 return Exception { InvalidAccessError };
2610 return layer->backing()->displayListAsText(displayListFlags);
2613 ExceptionOr<String> Internals::replayDisplayListForElement(Element& element, unsigned short flags)
2615 Document* document = contextDocument();
2616 if (!document || !document->renderView())
2617 return Exception { InvalidAccessError };
2619 element.document().updateLayoutIgnorePendingStylesheets();
2621 if (!element.renderer())
2622 return Exception { InvalidAccessError };
2624 DisplayList::AsTextFlags displayListFlags = 0;
2625 if (flags & DISPLAY_LIST_INCLUDES_PLATFORM_OPERATIONS)
2626 displayListFlags |= DisplayList::AsTextFlag::IncludesPlatformOperations;
2628 if (is<HTMLCanvasElement>(element))
2629 return downcast<HTMLCanvasElement>(element).replayDisplayListAsText(displayListFlags);
2631 if (!element.renderer()->hasLayer())
2632 return Exception { InvalidAccessError };
2634 RenderLayer* layer = downcast<RenderLayerModelObject>(element.renderer())->layer();
2635 if (!layer->isComposited())
2636 return Exception { InvalidAccessError };
2638 return layer->backing()->replayDisplayListAsText(displayListFlags);
2641 ExceptionOr<void> Internals::garbageCollectDocumentResources() const
2643 Document* document = contextDocument();
2645 return Exception { InvalidAccessError };
2646 document->cachedResourceLoader().garbageCollectDocumentResources();
2650 bool Internals::isUnderMemoryPressure()
2652 return MemoryPressureHandler::singleton().isUnderMemoryPressure();
2655 void Internals::beginSimulatedMemoryPressure()
2657 MemoryPressureHandler::singleton().beginSimulatedMemoryPressure();
2660 void Internals::endSimulatedMemoryPressure()
2662 MemoryPressureHandler::singleton().endSimulatedMemoryPressure();
2665 ExceptionOr<void> Internals::insertAuthorCSS(const String& css) const
2667 Document* document = contextDocument();
2669 return Exception { InvalidAccessError };
2671 auto parsedSheet = StyleSheetContents::create(*document);
2672 parsedSheet.get().setIsUserStyleSheet(false);
2673 parsedSheet.get().parseString(css);
2674 document->extensionStyleSheets().addAuthorStyleSheetForTesting(WTFMove(parsedSheet));
2678 ExceptionOr<void> Internals::insertUserCSS(const String& css) const
2680 Document* document = contextDocument();
2682 return Exception { InvalidAccessError };
2684 auto parsedSheet = StyleSheetContents::create(*document);
2685 parsedSheet.get().setIsUserStyleSheet(true);
2686 parsedSheet.get().parseString(css);
2687 document->extensionStyleSheets().addUserStyleSheet(WTFMove(parsedSheet));
2691 String Internals::counterValue(Element& element)
2693 return counterValueForElement(&element);
2696 int Internals::pageNumber(Element& element, float pageWidth, float pageHeight)
2698 return PrintContext::pageNumberForElement(&element, { pageWidth, pageHeight });
2701 Vector<String> Internals::shortcutIconURLs() const
2706 auto* documentLoader = frame()->loader().documentLoader();
2707 if (!documentLoader)
2710 Vector<String> result;
2711 for (auto& linkIcon : documentLoader->linkIcons())
2712 result.append(linkIcon.url.string());
2717 int Internals::numberOfPages(float pageWidth, float pageHeight)
2722 return PrintContext::numberOfPages(*frame(), FloatSize(pageWidth, pageHeight));
2725 ExceptionOr<String> Internals::pageProperty(const String& propertyName, int pageNumber) const
2728 return Exception { InvalidAccessError };
2730 return PrintContext::pageProperty(frame(), propertyName.utf8().data(), pageNumber);
2733 ExceptionOr<String> Internals::pageSizeAndMarginsInPixels(int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft) const
2736 return Exception { InvalidAccessError };
2738 return PrintContext::pageSizeAndMarginsInPixels(frame(), pageNumber, width, height, marginTop, marginRight, marginBottom, marginLeft);
2741 ExceptionOr<float> Internals::pageScaleFactor() const
2743 Document* document = contextDocument();
2744 if (!document || !document->page())
2745 return Exception { InvalidAccessError };
2747 return document->page()->pageScaleFactor();
2750 ExceptionOr<void> Internals::setPageScaleFactor(float scaleFactor, int x, int y)
2752 Document* document = contextDocument();
2753 if (!document || !document->page())
2754 return Exception { InvalidAccessError };
2756 document->page()->setPageScaleFactor(scaleFactor, IntPoint(x, y));
2760 ExceptionOr<void> Internals::setPageZoomFactor(float zoomFactor)
2762 Document* document = contextDocument();
2763 if (!document || !document->frame())
2764 return Exception { InvalidAccessError };
2766 document->frame()->setPageZoomFactor(zoomFactor);
2770 ExceptionOr<void> Internals::setTextZoomFactor(float zoomFactor)
2772 Document* document = contextDocument();
2773 if (!document || !document->frame())
2774 return Exception { InvalidAccessError };
2776 document->frame()->setTextZoomFactor(zoomFactor);
2780 ExceptionOr<void> Internals::setUseFixedLayout(bool useFixedLayout)
2782 Document* document = contextDocument();
2783 if (!document || !document->view())
2784 return Exception { InvalidAccessError };
2786 document->view()->setUseFixedLayout(useFixedLayout);
2790 ExceptionOr<void> Internals::setFixedLayoutSize(int width, int height)
2792 Document* document = contextDocument();
2793 if (!document || !document->view())
2794 return Exception { InvalidAccessError };
2796 document->view()->setFixedLayoutSize(IntSize(width, height));
2800 ExceptionOr<void> Internals::setViewExposedRect(float x, float y, float width, float height)
2802 Document* document = contextDocument();
2803 if (!document || !document->view())
2804 return Exception { InvalidAccessError };
2806 document->view()->setViewExposedRect(FloatRect(x, y, width, height));
2810 void Internals::setPrinting(int width, int height)
2812 printContextForTesting() = std::make_unique<PrintContext>(frame());
2813 printContextForTesting()->begin(width, height);
2816 void Internals::setHeaderHeight(float height)
2818 Document* document = contextDocument();
2819 if (!document || !document->view())
2822 document->view()->setHeaderHeight(height);
2825 void Internals::setFooterHeight(float height)
2827 Document* document = contextDocument();
2828 if (!document || !document->view())
2831 document->view()->setFooterHeight(height);
2834 void Internals::setTopContentInset(float contentInset)
2836 Document* document = contextDocument();
2837 if (!document || !document->page())
2840 document->page()->setTopContentInset(contentInset);
2843 #if ENABLE(FULLSCREEN_API)
2845 void Internals::webkitWillEnterFullScreenForElement(Element& element)
2847 Document* document = contextDocument();
2850 document->webkitWillEnterFullScreenForElement(&element);
2853 void Internals::webkitDidEnterFullScreenForElement(Element& element)
2855 Document* document = contextDocument();
2858 document->webkitDidEnterFullScreenForElement(&element);
2861 void Internals::webkitWillExitFullScreenForElement(Element& element)
2863 Document* document = contextDocument();
2866 document->webkitWillExitFullScreenForElement(&element);
2869 void Internals::webkitDidExitFullScreenForElement(Element& element)
2871 Document* document = contextDocument();
2874 document->webkitDidExitFullScreenForElement(&element);
2877 bool Internals::isAnimatingFullScreen() const
2879 Document* document = contextDocument();
2882 return document->isAnimatingFullScreen();
2887 void Internals::setFullscreenInsets(FullscreenInsets insets)
2889 Page* page = contextDocument()->frame()->page();
2892 page->setFullscreenInsets(FloatBoxExtent(insets.top, insets.right, insets.bottom, insets.left));
2895 void Internals::setFullscreenAutoHideDuration(double duration)
2897 Page* page = contextDocument()->frame()->page();
2900 page->setFullscreenAutoHideDuration(Seconds(duration));
2903 void Internals::setFullscreenControlsHidden(bool hidden)
2905 Page* page = contextDocument()->frame()->page();
2908 page->setFullscreenControlsHidden(hidden);
2911 void Internals::setApplicationCacheOriginQuota(unsigned long long quota)
2913 Document* document = contextDocument();
2914 if (!document || !document->page())
2916 document->page()->applicationCacheStorage().storeUpdatedQuotaForOrigin(&document->securityOrigin(), quota);
2919 void Internals::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme)
2921 SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
2924 void Internals::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(const String& scheme)
2926 SchemeRegistry::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(scheme);
2929 void Internals::registerDefaultPortForProtocol(unsigned short port, const String& protocol)
2931 registerDefaultPortForProtocolForTesting(port, protocol);
2934 Ref<MallocStatistics> Internals::mallocStatistics() const
2936 return MallocStatistics::create();
2939 Ref<TypeConversions> Internals::typeConversions() const
2941 return TypeConversions::create();
2944 Ref<MemoryInfo> Internals::memoryInfo() const
2946 return MemoryInfo::create();
2949 Vector<String> Internals::getReferencedFilePaths() const
2951 frame()->loader().history().saveDocumentAndScrollState();
2952 return FormController::referencedFilePaths(frame()->loader().history().currentItem()->documentState());
2955 ExceptionOr<void> Internals::startTrackingRepaints()
2957 Document* document = contextDocument();
2958 if (!document || !document->view())
2959 return Exception { InvalidAccessError };
2961 document->view()->setTracksRepaints(true);
2965 ExceptionOr<void> Internals::stopTrackingRepaints()
2967 Document* document = contextDocument();
2968 if (!document || !document->view())
2969 return Exception { InvalidAccessError };
2971 document->view()->setTracksRepaints(false);
2975 ExceptionOr<void> Internals::startTrackingLayerFlushes()
2977 Document* document = contextDocument();
2978 if (!document || !document->renderView())
2979 return Exception { InvalidAccessError };
2981 document->renderView()->compositor().startTrackingLayerFlushes();
2985 ExceptionOr<unsigned> Internals::layerFlushCount()
2987 Document* document = contextDocument();
2988 if (!document || !document->renderView())
2989 return Exception { InvalidAccessError };
2991 return document->renderView()->compositor().layerFlushCount();
2994 ExceptionOr<void> Internals::startTrackingStyleRecalcs()
2996 Document* document = contextDocument();
2998 return Exception { InvalidAccessError };
3000 document->startTrackingStyleRecalcs();
3004 ExceptionOr<unsigned> Internals::styleRecalcCount()
3006 Document* document = contextDocument();
3008 return Exception { InvalidAccessError };
3010 return document->styleRecalcCount();
3013 unsigned Internals::lastStyleUpdateSize() const
3015 Document* document = contextDocument();
3018 return document->lastStyleUpdateSizeForTesting();
3021 ExceptionOr<void> Internals::startTrackingCompositingUpdates()
3023 Document* document = contextDocument();
3024 if (!document || !document->renderView())
3025 return Exception { InvalidAccessError };
3027 document->renderView()->compositor().startTrackingCompositingUpdates();
3031 ExceptionOr<unsigned> Internals::compositingUpdateCount()
3033 Document* document = contextDocument();
3034 if (!document || !document->renderView())
3035 return Exception { InvalidAccessError };
3037 return document->renderView()->compositor().compositingUpdateCount();
3040 ExceptionOr<void> Internals::setCompositingPolicyOverride(std::optional<CompositingPolicy> policyOverride)
3042 Document* document = contextDocument();
3044 return Exception { InvalidAccessError };
3046 if (!policyOverride) {
3047 document->page()->setCompositingPolicyOverride(std::nullopt);
3051 switch (policyOverride.value()) {
3052 case Internals::CompositingPolicy::Normal:
3053 document->page()->setCompositingPolicyOverride(WebCore::CompositingPolicy::Normal);
3055 case Internals::CompositingPolicy::Conservative:
3056 document->page()->setCompositingPolicyOverride(WebCore::CompositingPolicy::Conservative);
3063 ExceptionOr<std::optional<Internals::CompositingPolicy>> Internals::compositingPolicyOverride() const
3065 Document* document = contextDocument();
3067 return Exception { InvalidAccessError };
3069 auto policyOverride = document->page()->compositingPolicyOverride();
3070 if (!policyOverride)
3071 return { std::nullopt };
3073 switch (policyOverride.value()) {
3074 case WebCore::CompositingPolicy::Normal:
3075 return { Internals::CompositingPolicy::Normal };
3076 case WebCore::CompositingPolicy::Conservative:
3077 return { Internals::CompositingPolicy::Conservative };
3080 return { Internals::CompositingPolicy::Normal };
3083 ExceptionOr<void> Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(Node* node)
3087 document = contextDocument();
3088 else if (is<Document>(*node))
3089 document = downcast<Document>(node);
3090 else if (is<HTMLIFrameElement>(*node))
3091 document = downcast<HTMLIFrameElement>(*node).contentDocument();
3093 return Exception { TypeError };
3095 document->updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasks::Synchronously);
3099 unsigned Internals::layoutCount() const
3101 Document* document = contextDocument();
3102 if (!document || !document->view())
3104 return document->view()->layoutContext().layoutCount();
3108 static const char* cursorTypeToString(Cursor::Type cursorType)
3110 switch (cursorType) {
3111 case Cursor::Pointer: return "Pointer";
3112 case Cursor::Cross: return "Cross";
3113 case Cursor::Hand: return "Hand";
3114 case Cursor::IBeam: return "IBeam";
3115 case Cursor::Wait: return "Wait";
3116 case Cursor::Help: return "Help";
3117 case Cursor::EastResize: return "EastResize";
3118 case Cursor::NorthResize: return "NorthResize";
3119 case Cursor::NorthEastResize: return "NorthEastResize";
3120 case Cursor::NorthWestResize: return "NorthWestResize";
3121 case Cursor::SouthResize: return "SouthResize";
3122 case Cursor::SouthEastResize: return "SouthEastResize";
3123 case Cursor::SouthWestResize: return "SouthWestResize";
3124 case Cursor::WestResize: return "WestResize";
3125 case Cursor::NorthSouthResize: return "NorthSouthResize";
3126 case Cursor::EastWestResize: return "EastWestResize";
3127 case Cursor::NorthEastSouthWestResize: return "NorthEastSouthWestResize";
3128 case Cursor::NorthWestSouthEastResize: return "NorthWestSouthEastResize";
3129 case Cursor::ColumnResize: return "ColumnResize";
3130 case Cursor::RowResize: return "RowResize";
3131 case Cursor::MiddlePanning: return "MiddlePanning";
3132 case Cursor::EastPanning: return "EastPanning";
3133 case Cursor::NorthPanning: return "NorthPanning";
3134 case Cursor::NorthEastPanning: return "NorthEastPanning";
3135 case Cursor::NorthWestPanning: return "NorthWestPanning";
3136 case Cursor::SouthPanning: return "SouthPanning";
3137 case Cursor::SouthEastPanning: return "SouthEastPanning";
3138 case Cursor::SouthWestPanning: return "SouthWestPanning";
3139 case Cursor::WestPanning: return "WestPanning";
3140 case Cursor::Move: return "Move";
3141 case Cursor::VerticalText: return "VerticalText";
3142 case Cursor::Cell: return "Cell";
3143 case Cursor::ContextMenu: return "ContextMenu";
3144 case Cursor::Alias: return "Alias";
3145 case Cursor::Progress: return "Progress";
3146 case Cursor::NoDrop: return "NoDrop";
3147 case Cursor::Copy: return "Copy";
3148 case Cursor::None: return "None";
3149 case Cursor::NotAllowed: return "NotAllowed";
3150 case Cursor::ZoomIn: return "ZoomIn";
3151 case Cursor::ZoomOut: return "ZoomOut";
3152 case Cursor::Grab: return "Grab";
3153 case Cursor::Grabbing: return "Grabbing";
3154 case Cursor::Custom: return "Custom";
3157 ASSERT_NOT_REACHED();
3162 ExceptionOr<String> Internals::getCurrentCursorInfo()
3164 Document* document = contextDocument();
3165 if (!document || !document->frame())
3166 return Exception { InvalidAccessError };
3169 Cursor cursor = document->frame()->eventHandler().currentMouseCursor();
3171 StringBuilder result;
3172 result.appendLiteral("type=");
3173 result.append(cursorTypeToString(cursor.type()));
3174 result.appendLiteral(" hotSpot=");
3175 result.appendNumber(cursor.hotSpot().x());
3177 result.appendNumber(cursor.hotSpot().y());
3178 if (cursor.image()) {
3179 FloatSize size = cursor.image()->size();
3180 result.appendLiteral(" image=");
3181 result.appendNumber(size.width());
3183 result.appendNumber(size.height());
3185 #if ENABLE(MOUSE_CURSOR_SCALE)
3186 if (cursor.imageScaleFactor() != 1) {
3187 result.appendLiteral(" scale=");
3188 NumberToStringBuffer buffer;
3189 result.append(numberToFixedPrecisionString(cursor.imageScaleFactor(), 8, buffer, true));
3192 return result.toString();
3194 return String { "FAIL: Cursor details not available on this platform." };
3198 Ref<ArrayBuffer> Internals::serializeObject(const RefPtr<SerializedScriptValue>& value) const
3200 auto& bytes = value->data();
3201 return ArrayBuffer::create(bytes.data(), bytes.size());
3204 Ref<SerializedScriptValue> Internals::deserializeBuffer(ArrayBuffer& buffer) const
3206 Vector<uint8_t> bytes;
3207 bytes.append(static_cast<const uint8_t*>(buffer.data()), buffer.byteLength());
3208 return SerializedScriptValue::adopt(WTFMove(bytes));
3211 bool Internals::isFromCurrentWorld(JSC::JSValue value) const
3213 return isWorldCompatible(*contextDocument()->vm().topCallFrame, value);
3216 void Internals::setUsesOverlayScrollbars(bool enabled)
3218 WebCore::DeprecatedGlobalSettings::setUsesOverlayScrollbars(enabled);
3221 void Internals::setUsesMockScrollAnimator(bool enabled)
3223 WebCore::DeprecatedGlobalSettings::setUsesMockScrollAnimator(enabled);
3226 void Internals::forceReload(bool endToEnd)
3228 OptionSet<ReloadOption> reloadOptions;
3230 reloadOptions.add(ReloadOption::FromOrigin);
3232 frame()->loader().reload(reloadOptions);
3235 void Internals::reloadExpiredOnly()
3237 frame()->loader().reload(ReloadOption::ExpiredOnly);
3240 void Internals::enableAutoSizeMode(bool enabled, int minimumWidth, int minimumHeight, int maximumWidth, int maximumHeight)
3242 auto* document = contextDocument();
3243 if (!document || !document->view())
3245 document->view()->enableAutoSizeMode(enabled, IntSize(minimumWidth, minimumHeight), IntSize(maximumWidth, maximumHeight));
3248 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
3250 void Internals::initializeMockCDM()
3252 LegacyCDM::registerCDMFactory([] (LegacyCDM* cdm) { return std::make_unique<LegacyMockCDM>(cdm); },
3253 LegacyMockCDM::supportsKeySystem, LegacyMockCDM::supportsKeySystemAndMimeType);
3258 #if ENABLE(ENCRYPTED_MEDIA)
3260 Ref<MockCDMFactory> Internals::registerMockCDM()
3262 return MockCDMFactory::create();
3267 String Internals::markerTextForListItem(Element& element)
3269 return WebCore::markerTextForListItem(&element);
3272 String Internals::toolTipFromElement(Element& element) const
3274 HitTestResult result;
3275 result.setInnerNode(&element);
3276 TextDirection direction;
3277 return result.title(direction);
3280 String Internals::getImageSourceURL(Element& element)
3282 return element.imageSourceURL();
3287 Vector<String> Internals::mediaResponseSources(HTMLMediaElement& media)
3289 auto* resourceLoader = media.lastMediaResourceLoaderForTesting();
3290 if (!resourceLoader)
3292 Vector<String> result;
3293 auto responses = resourceLoader->responsesForTesting();
3294 for (auto& response : responses)
3295 result.append(responseSourceToString(response));
3299 Vector<String> Internals::mediaResponseContentRanges(HTMLMediaElement& media)
3301 auto* resourceLoader = media.lastMediaResourceLoaderForTesting();
3302 if (!resourceLoader)
3304 Vector<String> result;
3305 auto responses = resourceLoader->responsesForTesting();
3306 for (auto& response : responses)
3307 result.append(response.httpHeaderField(HTTPHeaderName::ContentRange));
3311 void Internals::simulateAudioInterruption(HTMLMediaElement& element)
3314 element.player()->simulateAudioInterruption();
3316 UNUSED_PARAM(element);
3320 ExceptionOr<bool> Internals::mediaElementHasCharacteristic(HTMLMediaElement& element, const String& characteristic)
3322 if (equalLettersIgnoringASCIICase(characteristic, "audible"))
3323 return element.hasAudio();
3324 if (equalLettersIgnoringASCIICase(characteristic, "visual"))
3325 return element.hasVideo();
3326 if (equalLettersIgnoringASCIICase(characteristic, "legible"))
3327 return element.hasClosedCaptions();
3329 return Exception { SyntaxError };
3332 void Internals::beginSimulatedHDCPError(HTMLMediaElement& element)
3334 if (auto player = element.player())
3335 player->beginSimulatedHDCPError();
3338 void Internals::endSimulatedHDCPError(HTMLMediaElement& element)
3340 if (auto player = element.player())
3341 player->endSimulatedHDCPError();
3344 bool Internals::elementShouldBufferData(HTMLMediaElement& element)
3346 return element.shouldBufferData();
3351 bool Internals::isSelectPopupVisible(HTMLSelectElement& element)
3353 element.document().updateLayoutIgnorePendingStylesheets();
3355 auto* renderer = element.renderer();
3356 if (!is<RenderMenuList>(renderer))
3360 return downcast<RenderMenuList>(*renderer).popupIsVisible();
3366 ExceptionOr<String> Internals::captionsStyleSheetOverride()
3368 Document* document = contextDocument();
3369 if (!document || !document->page())
3370 return Exception { InvalidAccessError };
3372 #if ENABLE(VIDEO_TRACK)
3373 return document->page()->group().captionPreferences().captionsStyleSheetOverride();
3375 return String { emptyString() };
3379 ExceptionOr<void> Internals::setCaptionsStyleSheetOverride(const String& override)
3381 Document* document = contextDocument();
3382 if (!document || !document->page())
3383 return Exception { InvalidAccessError };
3385 #if ENABLE(VIDEO_TRACK)
3386 document->page()->group().captionPreferences().setCaptionsStyleSheetOverride(override);
3388 UNUSED_PARAM(override);
3393 ExceptionOr<void> Internals::setPrimaryAudioTrackLanguageOverride(const String& language)
3395 Document* document = contextDocument();
3396 if (!document || !document->page())
3397 return Exception { InvalidAccessError };
3399 #if ENABLE(VIDEO_TRACK)
3400 document->page()->group().captionPreferences().setPrimaryAudioTrackLanguageOverride(language);
3402 UNUSED_PARAM(language);
3407 ExceptionOr<void> Internals::setCaptionDisplayMode(const String& mode)
3409 Document* document = contextDocument();
3410 if (!document || !document->page())
3411 return Exception { InvalidAccessError };
3413 #if ENABLE(VIDEO_TRACK)
3414 auto& captionPreferences = document->page()->group().captionPreferences();
3416 if (equalLettersIgnoringASCIICase(mode, "automatic"))
3417 captionPreferences.setCaptionDisplayMode(CaptionUserPreferences::Automatic);
3418 else if (equalLettersIgnoringASCIICase(mode, "forcedonly"))
3419 captionPreferences.setCaptionDisplayMode(CaptionUserPreferences::ForcedOnly);
3420 else if (equalLettersIgnoringASCIICase(mode, "alwayson"))
3421 captionPreferences.setCaptionDisplayMode(CaptionUserPreferences::AlwaysOn);
3422 else if (equalLettersIgnoringASCIICase(mode, "manual"))
3423 captionPreferences.setCaptionDisplayMode(CaptionUserPreferences::Manual);
3425 return Exception { SyntaxError };
3434 Ref<TimeRanges> Internals::createTimeRanges(Float32Array& startTimes, Float32Array& endTimes)
3436 ASSERT(startTimes.length() == endTimes.length());
3437 Ref<TimeRanges> ranges = TimeRanges::create();
3439 unsigned count = std::min(startTimes.length(), endTimes.length());
3440 for (unsigned i = 0; i < count; ++i)
3441 ranges->add(startTimes.item(i), endTimes.item(i));
3445 double Internals::closestTimeToTimeRanges(double time, TimeRanges& ranges)
3447 return ranges.nearest(time);
3452 ExceptionOr<Ref<DOMRect>> Internals::selectionBounds()
3454 Document* document = contextDocument();
3455 if (!document || !document->frame())
3456 return Exception { InvalidAccessError };
3458 return DOMRect::create(document->frame()->selection().selectionBounds());
3461 ExceptionOr<bool> Internals::isPluginUnavailabilityIndicatorObscured(Element& element)
3463 if (!is<HTMLPlugInElement>(element))
3464 return Exception { InvalidAccessError };
3466 return downcast<HTMLPlugInElement>(element).isReplacementObscured();
3469 ExceptionOr<String> Internals::unavailablePluginReplacementText(Element& element)
3471 if (!is<HTMLPlugInElement>(element))
3472 return Exception { InvalidAccessError };
3474 auto* renderer = element.renderer();
3475 if (!is<RenderEmbeddedObject>(renderer))
3478 return String { downcast<RenderEmbeddedObject>(*renderer).pluginReplacementTextIfUnavailable() };
3481 bool Internals::isPluginSnapshotted(Element& element)
3483 return is<HTMLPlugInElement>(element) && downcast<HTMLPlugInElement>(element).displayState() <= HTMLPlugInElement::DisplayingSnapshot;
3486 #if ENABLE(MEDIA_SOURCE)
3488 void Internals::initializeMockMediaSource()
3490 #if USE(AVFOUNDATION)
3491 WebCore::DeprecatedGlobalSettings::setAVFoundationEnabled(false);
3494 WebCore::DeprecatedGlobalSettings::setGStreamerEnabled(false);
3496 MediaPlayerFactorySupport::callRegisterMediaEngine(MockMediaPlayerMediaSource::registerMediaEngine);
3499 Vector<String> Internals::bufferedSamplesForTrackID(SourceBuffer& buffer, const AtomicString& trackID)
3501 return buffer.bufferedSamplesForTrackID(trackID);
3504 Vector<String> Internals::enqueuedSamplesForTrackID(SourceBuffer& buffer, const AtomicString& trackID)
3506 return buffer.enqueuedSamplesForTrackID(trackID);
3509 void Internals::setShouldGenerateTimestamps(SourceBuffer& buffer, bool flag)
3511 buffer.setShouldGenerateTimestamps(flag);
3516 void Internals::enableMockMediaCapabilities()
3518 MediaEngineConfigurationFactory::enableMock();
3523 ExceptionOr<void> Internals::beginMediaSessionInterruption(const String& interruptionString)
3525 PlatformMediaSession::InterruptionType interruption = PlatformMediaSession::SystemInterruption;
3527 if (equalLettersIgnoringASCIICase(interruptionString, "system"))
3528 interruption = PlatformMediaSession::SystemInterruption;
3529 else if (equalLettersIgnoringASCIICase(interruptionString, "systemsleep"))
3530 interruption = PlatformMediaSession::SystemSleep;
3531 else if (equalLettersIgnoringASCIICase(interruptionString, "enteringbackground"))
3532 interruption = PlatformMediaSession::EnteringBackground;
3533 else if (equalLettersIgnoringASCIICase(interruptionString, "suspendedunderlock"))
3534 interruption = PlatformMediaSession::SuspendedUnderLock;
3536 return Exception { InvalidAccessError };
3538 PlatformMediaSessionManager::sharedManager().beginInterruption(interruption);
3542 void Internals::endMediaSessionInterruption(const String& flagsString)
3544 PlatformMediaSession::EndInterruptionFlags flags = PlatformMediaSession::NoFlags;
3546 if (equalLettersIgnoringASCIICase(flagsString, "mayresumeplaying"))
3547 flags = PlatformMediaSession::MayResumePlaying;
3549 PlatformMediaSessionManager::sharedManager().endInterruption(flags);
3552 void Internals::applicationWillBecomeInactive()
3554 PlatformMediaSessionManager::sharedManager().applicationWillBecomeInactive();
3557 void Internals::applicationDidBecomeActive()
3559 PlatformMediaSessionManager::sharedManager().applicationDidBecomeActive();
3562 void Internals::applicationWillEnterForeground(bool suspendedUnderLock) const
3564 PlatformMediaSessionManager::sharedManager().applicationWillEnterForeground(suspendedUnderLock);
3567 void Internals::applicationDidEnterBackground(bool suspendedUnderLock) const
3569 PlatformMediaSessionManager::sharedManager().applicationDidEnterBackground(suspendedUnderLock);
3572 static PlatformMediaSession::MediaType mediaTypeFromString(const String& mediaTypeString)
3574 if (equalLettersIgnoringASCIICase(mediaTypeString, "video"))
3575 return PlatformMediaSession::Video;
3576 if (equalLettersIgnoringASCIICase(mediaTypeString, "audio"))
3577 return PlatformMediaSession::Audio;
3578 if (equalLettersIgnoringASCIICase(mediaTypeString, "videoaudio"))
3579 return PlatformMediaSession::VideoAudio;
3580 if (equalLettersIgnoringASCIICase(mediaTypeString, "webaudio"))
3581 return PlatformMediaSession::WebAudio;
3582 if (equalLettersIgnoringASCIICase(mediaTypeString, "mediastreamcapturingaudio"))
3583 return PlatformMediaSession::MediaStreamCapturingAudio;
3585 return PlatformMediaSession::None;
3588 ExceptionOr<void> Internals::setMediaSessionRestrictions(const String& mediaTypeString, StringView restrictionsString)
3590 PlatformMediaSession::MediaType mediaType = mediaTypeFromString(mediaTypeString);
3591 if (mediaType == PlatformMediaSession::None)
3592 return Exception { InvalidAccessError };
3594 PlatformMediaSessionManager::SessionRestrictions restrictions = PlatformMediaSessionManager::sharedManager().restrictions(mediaType);
3595 PlatformMediaSessionManager::sharedManager().removeRestriction(mediaType, restrictions);
3597 restrictions = PlatformMediaSessionManager::NoRestrictions;
3599 for (StringView restrictionString : restrictionsString.split(',')) {
3600 if (equalLettersIgnoringASCIICase(restrictionString, "concurrentplaybacknotpermitted"))
3601 restrictions |= PlatformMediaSessionManager::ConcurrentPlaybackNotPermitted;
3602 if (equalLettersIgnoringASCIICase(restrictionString, "backgroundprocessplaybackrestricted"))
3603 restrictions |= PlatformMediaSessionManager::BackgroundProcessPlaybackRestricted;
3604 if (equalLettersIgnoringASCIICase(restrictionString, "backgroundtabplaybackrestricted"))
3605 restrictions |= PlatformMediaSessionManager::BackgroundTabPlaybackRestricted;
3606 if (equalLettersIgnoringASCIICase(restrictionString, "interruptedplaybacknotpermitted"))
3607 restrictions |= PlatformMediaSessionManager::InterruptedPlaybackNotPermitted;
3608 if (equalLettersIgnoringASCIICase(restrictionString, "inactiveprocessplaybackrestricted"))
3609 restrictions |= PlatformMediaSessionManager::InactiveProcessPlaybackRestricted;
3610 if (equalLettersIgnoringASCIICase(restrictionString, "suspendedunderlockplaybackrestricted"))
3611 restrictions |= PlatformMediaSessionManager::SuspendedUnderLockPlaybackRestricted;
3613 PlatformMediaSessionManager::sharedManager().addRestriction(mediaType, restrictions);
3617 ExceptionOr<String> Internals::mediaSessionRestrictions(const String& mediaTypeString) const
3619 PlatformMediaSession::MediaType mediaType = mediaTypeFromString(mediaTypeString);
3620 if (mediaType == PlatformMediaSession::None)
3621 return Exception { InvalidAccessError };
3623 PlatformMediaSessionManager::SessionRestrictions restrictions = PlatformMediaSessionManager::sharedManager().restrictions(mediaType);
3624 if (restrictions == PlatformMediaSessionManager::NoRestrictions)
3627 StringBuilder builder;
3628 if (restrictions & PlatformMediaSessionManager::ConcurrentPlaybackNotPermitted)
3629 builder.append("concurrentplaybacknotpermitted");
3630 if (restrictions & PlatformMediaSessionManager::BackgroundProcessPlaybackRestricted) {
3631 if (!builder.isEmpty())
3632 builder.append(',');
3633 builder.append("backgroundprocessplaybackrestricted");
3635 if (restrictions & PlatformMediaSessionManager::BackgroundTabPlaybackRestricted) {
3636 if (!builder.isEmpty())
3637 builder.append(',');
3638 builder.append("backgroundtabplaybackrestricted");
3640 if (restrictions & PlatformMediaSessionManager::InterruptedPlaybackNotPermitted) {
3641 if (!builder.isEmpty())
3642 builder.append(',');
3643 builder.append("interruptedplaybacknotpermitted");
3645 return builder.toString();
3648 void Internals::setMediaElementRestrictions(HTMLMediaElement& element, StringView restrictionsString)
3650 MediaElementSession::BehaviorRestrictions restrictions = element.mediaSession().behaviorRestrictions();
3651 element.mediaSession().removeBehaviorRestriction(restrictions);
3653 restrictions = MediaElementSession::NoRestrictions;
3655 for (StringView restrictionString : restrictionsString.split(',')) {
3656 if (equalLettersIgnoringASCIICase(restrictionString, "norestrictions"))
3657 restrictions |= MediaElementSession::NoRestrictions;
3658 if (equalLettersIgnoringASCIICase(restrictionString, "requireusergestureforload"))
3659 restrictions |= MediaElementSession::RequireUserGestureForLoad;
3660 if (equalLettersIgnoringASCIICase(restrictionString, "requireusergestureforvideoratechange"))
3661 restrictions |= MediaElementSession::RequireUserGestureForVideoRateChange;
3662 if (equalLettersIgnoringASCIICase(restrictionString, "requireusergestureforfullscreen"))
3663 restrictions |= MediaElementSession::RequireUserGestureForFullscreen;
3664 if (equalLettersIgnoringASCIICase(restrictionString, "requirepageconsenttoloadmedia"))
3665 restrictions |= MediaElementSession::RequirePageConsentToLoadMedia;
3666 if (equalLettersIgnoringASCIICase(restrictionString, "requirepageconsenttoresumemedia"))
3667 restrictions |= MediaElementSession::RequirePageConsentToResumeMedia;
3668 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
3669 if (equalLettersIgnoringASCIICase(restrictionString, "requireusergesturetoshowplaybacktargetpicker"))
3670 restrictions |= MediaElementSession::RequireUserGestureToShowPlaybackTargetPicker;
3671 if (equalLettersIgnoringASCIICase(restrictionString, "wirelessvideoplaybackdisabled"))
3672 restrictions |= MediaElementSession::WirelessVideoPlaybackDisabled;
3674 if (equalLettersIgnoringASCIICase(restrictionString, "requireusergestureforaudioratechange"))
3675 restrictions |= MediaElementSession::RequireUserGestureForAudioRateChange;
3676 if (equalLettersIgnoringASCIICase(restrictionString, "metadatapreloadingnotpermitted"))
3677 restrictions |= MediaElementSession::MetadataPreloadingNotPermitted;
3678 if (equalLettersIgnoringASCIICase(restrictionString, "autopreloadingnotpermitted"))
3679 restrictions |= MediaElementSession::AutoPreloadingNotPermitted;
3680 if (equalLettersIgnoringASCIICase(restrictionString, "invisibleautoplaynotpermitted"))
3681 restrictions |= MediaElementSession::InvisibleAutoplayNotPermitted;
3682 if (equalLettersIgnoringASCIICase(restrictionString, "overrideusergesturerequirementformaincontent"))
3683 restrictions |= MediaElementSession::OverrideUserGestureRequirementForMainContent;
3685 element.mediaSession().addBehaviorRestriction(restrictions);
3688 ExceptionOr<void> Internals::postRemoteControlCommand(const String& commandString, float argument)
3690 PlatformMediaSession::RemoteControlCommandType command;
3691 PlatformMediaSession::RemoteCommandArgument parameter { argument };
3693 if (equalLettersIgnoringASCIICase(commandString, "play"))
3694 command = PlatformMediaSession::PlayCommand;
3695 else if (equalLettersIgnoringASCIICase(commandString, "pause"))
3696 command = PlatformMediaSession::PauseCommand;
3697 else if (equalLettersIgnoringASCIICase(commandString, "stop"))
3698 command = PlatformMediaSession::StopCommand;
3699 else if (equalLettersIgnoringASCIICase(commandString, "toggleplaypause"))
3700 command = PlatformMediaSession::TogglePlayPauseCommand;
3701 else if (equalLettersIgnoringASCIICase(comma