Add support for HEVC codec types in Media Capabilities
[WebKit-https.git] / Source / WebCore / testing / Internals.cpp
1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
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.
14  *
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.
25  */
26
27 #include "config.h"
28 #include "Internals.h"
29
30 #include "AXObjectCache.h"
31 #include "ActiveDOMCallbackMicrotask.h"
32 #include "ActivityState.h"
33 #include "AnimationTimeline.h"
34 #include "ApplicationCacheStorage.h"
35 #include "AudioSession.h"
36 #include "Autofill.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"
48 #include "Chrome.h"
49 #include "ClientOrigin.h"
50 #include "ComposedTreeIterator.h"
51 #include "Cursor.h"
52 #include "DOMRect.h"
53 #include "DOMRectList.h"
54 #include "DOMStringList.h"
55 #include "DOMWindow.h"
56 #include "DeprecatedGlobalSettings.h"
57 #include "DisabledAdaptations.h"
58 #include "DisplayList.h"
59 #include "Document.h"
60 #include "DocumentLoader.h"
61 #include "DocumentMarkerController.h"
62 #include "DocumentTimeline.h"
63 #include "Editor.h"
64 #include "Element.h"
65 #include "EventHandler.h"
66 #include "ExtendableEvent.h"
67 #include "ExtensionStyleSheets.h"
68 #include "FetchResponse.h"
69 #include "File.h"
70 #include "FontCache.h"
71 #include "FormController.h"
72 #include "Frame.h"
73 #include "FrameLoader.h"
74 #include "FrameView.h"
75 #include "GCObservation.h"
76 #include "GridPosition.h"
77 #include "HEVCUtilities.h"
78 #include "HTMLAnchorElement.h"
79 #include "HTMLCanvasElement.h"
80 #include "HTMLIFrameElement.h"
81 #include "HTMLImageElement.h"
82 #include "HTMLInputElement.h"
83 #include "HTMLLinkElement.h"
84 #include "HTMLNames.h"
85 #include "HTMLPictureElement.h"
86 #include "HTMLPlugInElement.h"
87 #include "HTMLPreloadScanner.h"
88 #include "HTMLSelectElement.h"
89 #include "HTMLTextAreaElement.h"
90 #include "HTMLVideoElement.h"
91 #include "HistoryController.h"
92 #include "HistoryItem.h"
93 #include "HitTestResult.h"
94 #include "InspectorClient.h"
95 #include "InspectorController.h"
96 #include "InspectorFrontendClientLocal.h"
97 #include "InspectorOverlay.h"
98 #include "InstrumentingAgents.h"
99 #include "IntRect.h"
100 #include "InternalSettings.h"
101 #include "JSImageData.h"
102 #include "LibWebRTCProvider.h"
103 #include "LoaderStrategy.h"
104 #include "MallocStatistics.h"
105 #include "MediaEngineConfigurationFactory.h"
106 #include "MediaPlayer.h"
107 #include "MediaProducer.h"
108 #include "MediaResourceLoader.h"
109 #include "MediaStreamTrack.h"
110 #include "MemoryCache.h"
111 #include "MemoryInfo.h"
112 #include "MockLibWebRTCPeerConnection.h"
113 #include "MockPageOverlay.h"
114 #include "MockPageOverlayClient.h"
115 #include "NetworkLoadInformation.h"
116 #if USE(CG)
117 #include "PDFDocumentImage.h"
118 #endif
119 #include "Page.h"
120 #include "PageCache.h"
121 #include "PageOverlay.h"
122 #include "PathUtilities.h"
123 #include "PlatformMediaSessionManager.h"
124 #include "PlatformScreen.h"
125 #include "PlatformStrategies.h"
126 #include "PluginData.h"
127 #include "PrintContext.h"
128 #include "PseudoElement.h"
129 #include "Range.h"
130 #include "ReadableStream.h"
131 #include "RenderEmbeddedObject.h"
132 #include "RenderLayerBacking.h"
133 #include "RenderLayerCompositor.h"
134 #include "RenderMenuList.h"
135 #include "RenderTreeAsText.h"
136 #include "RenderView.h"
137 #include "RenderedDocumentMarker.h"
138 #include "ResourceLoadObserver.h"
139 #include "RuntimeEnabledFeatures.h"
140 #include "SMILTimeContainer.h"
141 #include "SVGDocumentExtensions.h"
142 #include "SVGPathStringBuilder.h"
143 #include "SVGSVGElement.h"
144 #include "SWClientConnection.h"
145 #include "SchemeRegistry.h"
146 #include "ScriptedAnimationController.h"
147 #include "ScrollingCoordinator.h"
148 #include "ScrollingMomentumCalculator.h"
149 #include "SecurityOrigin.h"
150 #include "SerializedScriptValue.h"
151 #include "ServiceWorker.h"
152 #include "ServiceWorkerProvider.h"
153 #include "ServiceWorkerRegistrationData.h"
154 #include "Settings.h"
155 #include "ShadowRoot.h"
156 #include "SourceBuffer.h"
157 #include "SpellChecker.h"
158 #include "StaticNodeList.h"
159 #include "StringCallback.h"
160 #include "StyleRule.h"
161 #include "StyleScope.h"
162 #include "StyleSheetContents.h"
163 #include "TextIterator.h"
164 #include "TreeScope.h"
165 #include "TypeConversions.h"
166 #include "UserGestureIndicator.h"
167 #include "UserMediaController.h"
168 #include "ViewportArguments.h"
169 #include "VoidCallback.h"
170 #include "WebCoreJSClientData.h"
171 #include "WindowProxy.h"
172 #include "WorkerThread.h"
173 #include "WritingDirection.h"
174 #include "XMLHttpRequest.h"
175 #include <JavaScriptCore/CodeBlock.h>
176 #include <JavaScriptCore/InspectorAgentBase.h>
177 #include <JavaScriptCore/InspectorFrontendChannel.h>
178 #include <JavaScriptCore/JSCInlines.h>
179 #include <JavaScriptCore/JSCJSValue.h>
180 #include <wtf/JSONValues.h>
181 #include <wtf/Language.h>
182 #include <wtf/MemoryPressureHandler.h>
183 #include <wtf/MonotonicTime.h>
184 #include <wtf/text/StringBuffer.h>
185 #include <wtf/text/StringBuilder.h>
186 #include <wtf/text/StringConcatenateNumbers.h>
187 #include <wtf/text/StringView.h>
188
189 #if ENABLE(INPUT_TYPE_COLOR)
190 #include "ColorChooser.h"
191 #endif
192
193 #if ENABLE(MOUSE_CURSOR_SCALE)
194 #include <wtf/dtoa.h>
195 #endif
196
197 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
198 #include "LegacyCDM.h"
199 #include "LegacyMockCDM.h"
200 #endif
201
202 #if ENABLE(ENCRYPTED_MEDIA)
203 #include "MockCDMFactory.h"
204 #endif
205
206 #if ENABLE(VIDEO_TRACK)
207 #include "CaptionUserPreferences.h"
208 #include "PageGroup.h"
209 #endif
210
211 #if ENABLE(VIDEO)
212 #include "HTMLMediaElement.h"
213 #include "TimeRanges.h"
214 #endif
215
216 #if ENABLE(WEBGL)
217 #include "WebGLRenderingContext.h"
218 #endif
219
220 #if ENABLE(SPEECH_SYNTHESIS)
221 #include "DOMWindowSpeechSynthesis.h"
222 #include "PlatformSpeechSynthesizerMock.h"
223 #include "SpeechSynthesis.h"
224 #endif
225
226 #if ENABLE(MEDIA_STREAM)
227 #include "MediaStream.h"
228 #include "MockRealtimeMediaSourceCenter.h"
229 #endif
230
231 #if ENABLE(WEB_RTC)
232 #include "RTCPeerConnection.h"
233 #endif
234
235 #if ENABLE(MEDIA_SOURCE)
236 #include "MockMediaPlayerMediaSource.h"
237 #endif
238
239 #if ENABLE(CONTENT_FILTERING)
240 #include "MockContentFilterSettings.h"
241 #endif
242
243 #if ENABLE(WEB_AUDIO)
244 #include "AudioContext.h"
245 #endif
246
247 #if ENABLE(MEDIA_SESSION)
248 #include "MediaSession.h"
249 #include "MediaSessionManager.h"
250 #endif
251
252 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
253 #include "MediaPlaybackTargetContext.h"
254 #endif
255
256 #if ENABLE(POINTER_LOCK)
257 #include "PointerLockController.h"
258 #endif
259
260 #if USE(QUICK_LOOK)
261 #include "MockPreviewLoaderClient.h"
262 #include "PreviewLoader.h"
263 #endif
264
265 #if ENABLE(APPLE_PAY)
266 #include "MockPaymentCoordinator.h"
267 #include "PaymentCoordinator.h"
268 #endif
269
270 #if ENABLE(WEB_AUTHN)
271 #include "AuthenticatorCoordinator.h"
272 #include "MockAuthenticatorCoordinator.h"
273 #endif
274
275 #if PLATFORM(MAC) && USE(LIBWEBRTC)
276 #include <webrtc/sdk/WebKit/VideoProcessingSoftLink.h>
277 #endif
278
279 using JSC::CallData;
280 using JSC::CallType;
281 using JSC::CodeBlock;
282 using JSC::FunctionExecutable;
283 using JSC::Identifier;
284 using JSC::JSFunction;
285 using JSC::JSGlobalObject;
286 using JSC::JSObject;
287 using JSC::JSValue;
288 using JSC::MarkedArgumentBuffer;
289 using JSC::PropertySlot;
290 using JSC::ScriptExecutable;
291 using JSC::StackVisitor;
292
293
294 namespace WebCore {
295 using namespace Inspector;
296
297 using namespace HTMLNames;
298
299 class InspectorStubFrontend final : public InspectorFrontendClientLocal, public FrontendChannel {
300 public:
301     InspectorStubFrontend(Page& inspectedPage, RefPtr<DOMWindow>&& frontendWindow);
302     virtual ~InspectorStubFrontend();
303
304 private:
305     void attachWindow(DockSide) final { }
306     void detachWindow() final { }
307     void closeWindow() final;
308     void bringToFront() final { }
309     String localizedStringsURL() final { return String(); }
310     void inspectedURLChanged(const String&) final { }
311     void setAttachedWindowHeight(unsigned) final { }
312     void setAttachedWindowWidth(unsigned) final { }
313
314     void sendMessageToFrontend(const String& message) final;
315     ConnectionType connectionType() const final { return ConnectionType::Local; }
316
317     Page* frontendPage() const
318     {
319         if (!m_frontendWindow || !m_frontendWindow->document())
320             return nullptr;
321
322         return m_frontendWindow->document()->page();
323     }
324
325     RefPtr<DOMWindow> m_frontendWindow;
326     InspectorController& m_frontendController;
327 };
328
329 InspectorStubFrontend::InspectorStubFrontend(Page& inspectedPage, RefPtr<DOMWindow>&& frontendWindow)
330     : InspectorFrontendClientLocal(&inspectedPage.inspectorController(), frontendWindow->document()->page(), std::make_unique<InspectorFrontendClientLocal::Settings>())
331     , m_frontendWindow(frontendWindow.copyRef())
332     , m_frontendController(frontendPage()->inspectorController())
333 {
334     ASSERT_ARG(frontendWindow, frontendWindow);
335
336     m_frontendController.setInspectorFrontendClient(this);
337     inspectedPage.inspectorController().connectFrontend(this);
338 }
339
340 InspectorStubFrontend::~InspectorStubFrontend()
341 {
342     closeWindow();
343 }
344
345 void InspectorStubFrontend::closeWindow()
346 {
347     if (!m_frontendWindow)
348         return;
349
350     m_frontendController.setInspectorFrontendClient(nullptr);
351     inspectedPage()->inspectorController().disconnectFrontend(this);
352
353     m_frontendWindow->close();
354     m_frontendWindow = nullptr;
355 }
356
357 void InspectorStubFrontend::sendMessageToFrontend(const String& message)
358 {
359     ASSERT_ARG(message, !message.isEmpty());
360
361     InspectorClient::doDispatchMessageOnFrontendPage(frontendPage(), message);
362 }
363
364 static bool markerTypeFrom(const String& markerType, DocumentMarker::MarkerType& result)
365 {
366     if (equalLettersIgnoringASCIICase(markerType, "spelling"))
367         result = DocumentMarker::Spelling;
368     else if (equalLettersIgnoringASCIICase(markerType, "grammar"))
369         result = DocumentMarker::Grammar;
370     else if (equalLettersIgnoringASCIICase(markerType, "textmatch"))
371         result = DocumentMarker::TextMatch;
372     else if (equalLettersIgnoringASCIICase(markerType, "replacement"))
373         result = DocumentMarker::Replacement;
374     else if (equalLettersIgnoringASCIICase(markerType, "correctionindicator"))
375         result = DocumentMarker::CorrectionIndicator;
376     else if (equalLettersIgnoringASCIICase(markerType, "rejectedcorrection"))
377         result = DocumentMarker::RejectedCorrection;
378     else if (equalLettersIgnoringASCIICase(markerType, "autocorrected"))
379         result = DocumentMarker::Autocorrected;
380     else if (equalLettersIgnoringASCIICase(markerType, "spellcheckingexemption"))
381         result = DocumentMarker::SpellCheckingExemption;
382     else if (equalLettersIgnoringASCIICase(markerType, "deletedautocorrection"))
383         result = DocumentMarker::DeletedAutocorrection;
384     else if (equalLettersIgnoringASCIICase(markerType, "dictationalternatives"))
385         result = DocumentMarker::DictationAlternatives;
386 #if ENABLE(TELEPHONE_NUMBER_DETECTION)
387     else if (equalLettersIgnoringASCIICase(markerType, "telephonenumber"))
388         result = DocumentMarker::TelephoneNumber;
389 #endif
390     else
391         return false;
392
393     return true;
394 }
395
396 static bool markerTypesFrom(const String& markerType, OptionSet<DocumentMarker::MarkerType>& result)
397 {
398     DocumentMarker::MarkerType singularResult;
399
400     if (markerType.isEmpty() || equalLettersIgnoringASCIICase(markerType, "all"))
401         result = DocumentMarker::allMarkers();
402     else if (markerTypeFrom(markerType, singularResult))
403         result = singularResult;
404     else
405         return false;
406
407     return true;
408 }
409
410 static std::unique_ptr<PrintContext>& printContextForTesting()
411 {
412     static NeverDestroyed<std::unique_ptr<PrintContext>> context;
413     return context;
414 }
415
416 const char* Internals::internalsId = "internals";
417
418 Ref<Internals> Internals::create(Document& document)
419 {
420     return adoptRef(*new Internals(document));
421 }
422
423 Internals::~Internals()
424 {
425 #if ENABLE(MEDIA_STREAM)
426     if (m_track)
427         m_track->source().removeObserver(*this);
428 #endif
429 }
430
431 void Internals::resetToConsistentState(Page& page)
432 {
433     page.setPageScaleFactor(1, IntPoint(0, 0));
434     page.setPagination(Pagination());
435     page.setPaginationLineGridEnabled(false);
436
437     page.setDefersLoading(false);
438
439     page.mainFrame().setTextZoomFactor(1.0f);
440
441     page.setCompositingPolicyOverride(std::nullopt);
442
443     FrameView* mainFrameView = page.mainFrame().view();
444     if (mainFrameView) {
445         mainFrameView->setHeaderHeight(0);
446         mainFrameView->setFooterHeight(0);
447         page.setTopContentInset(0);
448         mainFrameView->setUseFixedLayout(false);
449         mainFrameView->setFixedLayoutSize(IntSize());
450 #if USE(COORDINATED_GRAPHICS)
451         mainFrameView->setFixedVisibleContentRect(IntRect());
452 #endif
453         if (auto* backing = mainFrameView->tiledBacking())
454             backing->setTileSizeUpdateDelayDisabledForTesting(false);
455     }
456
457     WebCore::clearDefaultPortForProtocolMapForTesting();
458     overrideUserPreferredLanguages(Vector<String>());
459     WebCore::DeprecatedGlobalSettings::setUsesOverlayScrollbars(false);
460     WebCore::DeprecatedGlobalSettings::setUsesMockScrollAnimator(false);
461 #if ENABLE(VIDEO_TRACK)
462     page.group().captionPreferences().setTestingMode(true);
463     page.group().captionPreferences().setCaptionsStyleSheetOverride(emptyString());
464     page.group().captionPreferences().setTestingMode(false);
465 #endif
466     if (!page.mainFrame().editor().isContinuousSpellCheckingEnabled())
467         page.mainFrame().editor().toggleContinuousSpellChecking();
468     if (page.mainFrame().editor().isOverwriteModeEnabled())
469         page.mainFrame().editor().toggleOverwriteModeEnabled();
470     page.mainFrame().loader().clearTestingOverrides();
471     page.applicationCacheStorage().setDefaultOriginQuota(ApplicationCacheStorage::noQuota());
472 #if ENABLE(VIDEO)
473     PlatformMediaSessionManager::sharedManager().resetRestrictions();
474     PlatformMediaSessionManager::sharedManager().setWillIgnoreSystemInterruptions(true);
475 #endif
476 #if HAVE(ACCESSIBILITY)
477     AXObjectCache::setEnhancedUserInterfaceAccessibility(false);
478     AXObjectCache::disableAccessibility();
479 #endif
480
481     MockPageOverlayClient::singleton().uninstallAllOverlays();
482
483 #if ENABLE(CONTENT_FILTERING)
484     MockContentFilterSettings::reset();
485 #endif
486
487 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
488     page.setMockMediaPlaybackTargetPickerEnabled(true);
489     page.setMockMediaPlaybackTargetPickerState(emptyString(), MediaPlaybackTargetContext::Unknown);
490 #endif
491
492     page.setShowAllPlugins(false);
493     page.setLowPowerModeEnabledOverrideForTesting(std::nullopt);
494
495 #if USE(QUICK_LOOK)
496     MockPreviewLoaderClient::singleton().setPassword("");
497     PreviewLoader::setClientForTesting(nullptr);
498 #endif
499
500     printContextForTesting() = nullptr;
501
502 #if USE(LIBWEBRTC)
503     auto& rtcProvider = page.libWebRTCProvider();
504     WebCore::useRealRTCPeerConnectionFactory(rtcProvider);
505     rtcProvider.disableNonLocalhostConnections();
506     RuntimeEnabledFeatures::sharedFeatures().setWebRTCUnifiedPlanEnabled(true);
507 #endif
508
509     page.settings().setStorageAccessAPIEnabled(false);
510     page.setFullscreenAutoHideDuration(0_s);
511     page.setFullscreenInsets({ });
512     page.setFullscreenControlsHidden(false);
513
514     MediaEngineConfigurationFactory::disableMock();
515 }
516
517 Internals::Internals(Document& document)
518     : ContextDestructionObserver(&document)
519 #if ENABLE(MEDIA_STREAM)
520     , m_orientationNotifier(0)
521 #endif
522 {
523 #if ENABLE(VIDEO_TRACK)
524     if (document.page())
525         document.page()->group().captionPreferences().setTestingMode(true);
526 #endif
527
528 #if ENABLE(MEDIA_STREAM)
529     setMockMediaCaptureDevicesEnabled(true);
530     WebCore::DeprecatedGlobalSettings::setMediaCaptureRequiresSecureConnection(false);
531 #endif
532
533 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
534     if (document.page())
535         document.page()->setMockMediaPlaybackTargetPickerEnabled(true);
536 #endif
537
538     if (contextDocument() && contextDocument()->frame()) {
539         setAutomaticSpellingCorrectionEnabled(true);
540         setAutomaticQuoteSubstitutionEnabled(false);
541         setAutomaticDashSubstitutionEnabled(false);
542         setAutomaticLinkDetectionEnabled(false);
543         setAutomaticTextReplacementEnabled(true);
544     }
545
546     setConsoleMessageListener(nullptr);
547
548 #if ENABLE(APPLE_PAY)
549     auto* frame = document.frame();
550     if (frame && frame->page()) {
551         m_mockPaymentCoordinator = new MockPaymentCoordinator(*frame->page());
552         frame->page()->setPaymentCoordinator(std::make_unique<PaymentCoordinator>(*m_mockPaymentCoordinator));
553     }
554 #endif
555
556 #if ENABLE(WEB_AUTHN)
557     if (document.page()) {
558         auto mockAuthenticatorCoordinator = std::make_unique<MockAuthenticatorCoordinator>();
559         m_mockAuthenticatorCoordinator = makeWeakPtr(mockAuthenticatorCoordinator.get());
560         document.page()->authenticatorCoordinator().setClient(WTFMove(mockAuthenticatorCoordinator));
561     }
562 #endif
563 }
564
565 Document* Internals::contextDocument() const
566 {
567     return downcast<Document>(scriptExecutionContext());
568 }
569
570 Frame* Internals::frame() const
571 {
572     if (!contextDocument())
573         return nullptr;
574     return contextDocument()->frame();
575 }
576
577 InternalSettings* Internals::settings() const
578 {
579     Document* document = contextDocument();
580     if (!document)
581         return nullptr;
582     Page* page = document->page();
583     if (!page)
584         return nullptr;
585     return InternalSettings::from(page);
586 }
587
588 unsigned Internals::workerThreadCount() const
589 {
590     return WorkerThread::workerThreadCount();
591 }
592
593 ExceptionOr<bool> Internals::areSVGAnimationsPaused() const
594 {
595     auto* document = contextDocument();
596     if (!document)
597         return Exception { InvalidAccessError, "No context document"_s };
598
599     if (!document->svgExtensions())
600         return Exception { NotFoundError, "No SVG animations"_s };
601
602     return document->accessSVGExtensions().areAnimationsPaused();
603 }
604
605 ExceptionOr<double> Internals::svgAnimationsInterval(SVGSVGElement& element) const
606 {
607     auto* document = contextDocument();
608     if (!document)
609         return 0;
610
611     if (!document->svgExtensions())
612         return 0;
613
614     if (document->accessSVGExtensions().areAnimationsPaused())
615         return 0;
616
617     return element.timeContainer().animationFrameDelay().value();
618 }
619
620 String Internals::address(Node& node)
621 {
622     return String::format("%p", &node);
623 }
624
625 bool Internals::nodeNeedsStyleRecalc(Node& node)
626 {
627     return node.needsStyleRecalc();
628 }
629
630 static String styleValidityToToString(Style::Validity validity)
631 {
632     switch (validity) {
633     case Style::Validity::Valid:
634         return "NoStyleChange";
635     case Style::Validity::ElementInvalid:
636         return "InlineStyleChange";
637     case Style::Validity::SubtreeInvalid:
638         return "FullStyleChange";
639     case Style::Validity::SubtreeAndRenderersInvalid:
640         return "ReconstructRenderTree";
641     }
642     ASSERT_NOT_REACHED();
643     return "";
644 }
645
646 String Internals::styleChangeType(Node& node)
647 {
648     node.document().styleScope().flushPendingUpdate();
649
650     return styleValidityToToString(node.styleValidity());
651 }
652
653 String Internals::description(JSC::JSValue value)
654 {
655     return toString(value);
656 }
657
658 bool Internals::isPreloaded(const String& url)
659 {
660     Document* document = contextDocument();
661     return document->cachedResourceLoader().isPreloaded(url);
662 }
663
664 bool Internals::isLoadingFromMemoryCache(const String& url)
665 {
666     if (!contextDocument() || !contextDocument()->page())
667         return false;
668
669     ResourceRequest request(contextDocument()->completeURL(url));
670     request.setDomainForCachePartition(contextDocument()->domainForCachePartition());
671
672     CachedResource* resource = MemoryCache::singleton().resourceForRequest(request, contextDocument()->page()->sessionID());
673     return resource && resource->status() == CachedResource::Cached;
674 }
675
676 static String responseSourceToString(const ResourceResponse& response)
677 {
678     if (response.isNull())
679         return "Null response";
680     switch (response.source()) {
681     case ResourceResponse::Source::Unknown:
682         return "Unknown";
683     case ResourceResponse::Source::Network:
684         return "Network";
685     case ResourceResponse::Source::ServiceWorker:
686         return "Service worker";
687     case ResourceResponse::Source::DiskCache:
688         return "Disk cache";
689     case ResourceResponse::Source::DiskCacheAfterValidation:
690         return "Disk cache after validation";
691     case ResourceResponse::Source::MemoryCache:
692         return "Memory cache";
693     case ResourceResponse::Source::MemoryCacheAfterValidation:
694         return "Memory cache after validation";
695     case ResourceResponse::Source::ApplicationCache:
696         return "Application cache";
697     }
698     ASSERT_NOT_REACHED();
699     return "Error";
700 }
701
702 String Internals::xhrResponseSource(XMLHttpRequest& request)
703 {
704     return responseSourceToString(request.resourceResponse());
705 }
706
707 String Internals::fetchResponseSource(FetchResponse& response)
708 {
709     return responseSourceToString(response.resourceResponse());
710 }
711
712 bool Internals::isSharingStyleSheetContents(HTMLLinkElement& a, HTMLLinkElement& b)
713 {
714     if (!a.sheet() || !b.sheet())
715         return false;
716     return &a.sheet()->contents() == &b.sheet()->contents();
717 }
718
719 bool Internals::isStyleSheetLoadingSubresources(HTMLLinkElement& link)
720 {
721     return link.sheet() && link.sheet()->contents().isLoadingSubresources();
722 }
723
724 static ResourceRequestCachePolicy toResourceRequestCachePolicy(Internals::CachePolicy policy)
725 {
726     switch (policy) {
727     case Internals::CachePolicy::UseProtocolCachePolicy:
728         return ResourceRequestCachePolicy::UseProtocolCachePolicy;
729     case Internals::CachePolicy::ReloadIgnoringCacheData:
730         return ResourceRequestCachePolicy::ReloadIgnoringCacheData;
731     case Internals::CachePolicy::ReturnCacheDataElseLoad:
732         return ResourceRequestCachePolicy::ReturnCacheDataElseLoad;
733     case Internals::CachePolicy::ReturnCacheDataDontLoad:
734         return ResourceRequestCachePolicy::ReturnCacheDataDontLoad;
735     }
736     ASSERT_NOT_REACHED();
737     return ResourceRequestCachePolicy::UseProtocolCachePolicy;
738 }
739
740 void Internals::setOverrideCachePolicy(CachePolicy policy)
741 {
742     frame()->loader().setOverrideCachePolicyForTesting(toResourceRequestCachePolicy(policy));
743 }
744
745 ExceptionOr<void> Internals::setCanShowModalDialogOverride(bool allow)
746 {
747     if (!contextDocument() || !contextDocument()->domWindow())
748         return Exception { InvalidAccessError };
749
750     contextDocument()->domWindow()->setCanShowModalDialogOverride(allow);
751     return { };
752 }
753
754 static ResourceLoadPriority toResourceLoadPriority(Internals::ResourceLoadPriority priority)
755 {
756     switch (priority) {
757     case Internals::ResourceLoadPriority::ResourceLoadPriorityVeryLow:
758         return ResourceLoadPriority::VeryLow;
759     case Internals::ResourceLoadPriority::ResourceLoadPriorityLow:
760         return ResourceLoadPriority::Low;
761     case Internals::ResourceLoadPriority::ResourceLoadPriorityMedium:
762         return ResourceLoadPriority::Medium;
763     case Internals::ResourceLoadPriority::ResourceLoadPriorityHigh:
764         return ResourceLoadPriority::High;
765     case Internals::ResourceLoadPriority::ResourceLoadPriorityVeryHigh:
766         return ResourceLoadPriority::VeryHigh;
767     }
768     ASSERT_NOT_REACHED();
769     return ResourceLoadPriority::Low;
770 }
771
772 void Internals::setOverrideResourceLoadPriority(ResourceLoadPriority priority)
773 {
774     frame()->loader().setOverrideResourceLoadPriorityForTesting(toResourceLoadPriority(priority));
775 }
776
777 void Internals::setStrictRawResourceValidationPolicyDisabled(bool disabled)
778 {
779     frame()->loader().setStrictRawResourceValidationPolicyDisabledForTesting(disabled);
780 }
781
782 void Internals::clearMemoryCache()
783 {
784     MemoryCache::singleton().evictResources();
785 }
786
787 void Internals::pruneMemoryCacheToSize(unsigned size)
788 {
789     MemoryCache::singleton().pruneDeadResourcesToSize(size);
790     MemoryCache::singleton().pruneLiveResourcesToSize(size, true);
791 }
792     
793 void Internals::destroyDecodedDataForAllImages()
794 {
795     MemoryCache::singleton().destroyDecodedDataForAllImages();
796 }
797
798 unsigned Internals::memoryCacheSize() const
799 {
800     return MemoryCache::singleton().size();
801 }
802
803 static Image* imageFromImageElement(HTMLImageElement& element)
804 {
805     auto* cachedImage = element.cachedImage();
806     return cachedImage ? cachedImage->image() : nullptr;
807 }
808
809 static BitmapImage* bitmapImageFromImageElement(HTMLImageElement& element)
810 {
811     auto* image = imageFromImageElement(element);
812     return image && is<BitmapImage>(image) ? &downcast<BitmapImage>(*image) : nullptr;
813 }
814
815 #if USE(CG)
816 static PDFDocumentImage* pdfDocumentImageFromImageElement(HTMLImageElement& element)
817 {
818     auto* image = imageFromImageElement(element);
819     return image && is<PDFDocumentImage>(image) ? &downcast<PDFDocumentImage>(*image) : nullptr;
820 }
821 #endif
822
823 unsigned Internals::imageFrameIndex(HTMLImageElement& element)
824 {
825     auto* bitmapImage = bitmapImageFromImageElement(element);
826     return bitmapImage ? bitmapImage->currentFrame() : 0;
827 }
828
829 void Internals::setImageFrameDecodingDuration(HTMLImageElement& element, float duration)
830 {
831     if (auto* bitmapImage = bitmapImageFromImageElement(element))
832         bitmapImage->setFrameDecodingDurationForTesting(Seconds { duration });
833 }
834
835 void Internals::resetImageAnimation(HTMLImageElement& element)
836 {
837     if (auto* image = imageFromImageElement(element))
838         image->resetAnimation();
839 }
840
841 bool Internals::isImageAnimating(HTMLImageElement& element)
842 {
843     auto* image = imageFromImageElement(element);
844     return image && (image->isAnimating() || image->animationPending());
845 }
846
847 void Internals::setClearDecoderAfterAsyncFrameRequestForTesting(HTMLImageElement& element, bool enabled)
848 {
849     if (auto* bitmapImage = bitmapImageFromImageElement(element))
850         bitmapImage->setClearDecoderAfterAsyncFrameRequestForTesting(enabled);
851 }
852
853 unsigned Internals::imageDecodeCount(HTMLImageElement& element)
854 {
855     auto* bitmapImage = bitmapImageFromImageElement(element);
856     return bitmapImage ? bitmapImage->decodeCountForTesting() : 0;
857 }
858
859 unsigned Internals::pdfDocumentCachingCount(HTMLImageElement& element)
860 {
861 #if USE(CG)
862     auto* pdfDocumentImage = pdfDocumentImageFromImageElement(element);
863     return pdfDocumentImage ? pdfDocumentImage->cachingCountForTesting() : 0;
864 #else
865     UNUSED_PARAM(element);
866     return 0;
867 #endif
868 }
869
870 void Internals::setLargeImageAsyncDecodingEnabledForTesting(HTMLImageElement& element, bool enabled)
871 {
872     if (auto* bitmapImage = bitmapImageFromImageElement(element))
873         bitmapImage->setLargeImageAsyncDecodingEnabledForTesting(enabled);
874 }
875     
876 void Internals::setForceUpdateImageDataEnabledForTesting(HTMLImageElement& element, bool enabled)
877 {
878     if (auto* cachedImage = element.cachedImage())
879         cachedImage->setForceUpdateImageDataEnabledForTesting(enabled);
880 }
881
882 void Internals::setGridMaxTracksLimit(unsigned maxTrackLimit)
883 {
884     GridPosition::setMaxPositionForTesting(maxTrackLimit);
885 }
886
887 void Internals::clearPageCache()
888 {
889     PageCache::singleton().pruneToSizeNow(0, PruningReason::None);
890 }
891
892 unsigned Internals::pageCacheSize() const
893 {
894     return PageCache::singleton().pageCount();
895 }
896
897 void Internals::disableTileSizeUpdateDelay()
898 {
899     Document* document = contextDocument();
900     if (!document || !document->frame())
901         return;
902
903     auto* view = document->frame()->view();
904     if (!view)
905         return;
906
907     if (auto* backing = view->tiledBacking())
908         backing->setTileSizeUpdateDelayDisabledForTesting(true);
909 }
910
911 void Internals::setSpeculativeTilingDelayDisabledForTesting(bool disabled)
912 {
913     Document* document = contextDocument();
914     if (!document || !document->frame())
915         return;
916
917     if (auto* frameView = document->frame()->view())
918         frameView->setSpeculativeTilingDelayDisabledForTesting(disabled);
919 }
920
921
922 Node* Internals::treeScopeRootNode(Node& node)
923 {
924     return &node.treeScope().rootNode();
925 }
926
927 Node* Internals::parentTreeScope(Node& node)
928 {
929     const TreeScope* parentTreeScope = node.treeScope().parentTreeScope();
930     return parentTreeScope ? &parentTreeScope->rootNode() : nullptr;
931 }
932
933 ExceptionOr<unsigned> Internals::lastSpatialNavigationCandidateCount() const
934 {
935     if (!contextDocument() || !contextDocument()->page())
936         return Exception { InvalidAccessError };
937
938     return contextDocument()->page()->lastSpatialNavigationCandidateCount();
939 }
940
941 unsigned Internals::numberOfActiveAnimations() const
942 {
943     if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled())
944         return frame()->document()->timeline().numberOfActiveAnimationsForTesting();
945     return frame()->animation().numberOfActiveAnimations(frame()->document());
946 }
947
948 ExceptionOr<bool> Internals::animationsAreSuspended() const
949 {
950     Document* document = contextDocument();
951     if (!document || !document->frame())
952         return Exception { InvalidAccessError };
953
954     if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled())
955         return document->timeline().animationsAreSuspended();
956     return document->frame()->animation().animationsAreSuspendedForDocument(document);
957 }
958
959 double Internals::animationsInterval() const
960 {
961     Document* document = contextDocument();
962     if (!document)
963         return INFINITY;
964
965     if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled()) {
966         if (auto timeline = document->existingTimeline())
967             return timeline->animationInterval().seconds();
968         return INFINITY;
969     }
970
971     if (!document->frame())
972         return INFINITY;
973     return document->frame()->animation().animationInterval().value();
974 }
975
976 ExceptionOr<void> Internals::suspendAnimations() const
977 {
978     Document* document = contextDocument();
979     if (!document || !document->frame())
980         return Exception { InvalidAccessError };
981
982     if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled()) {
983         document->timeline().suspendAnimations();
984         for (Frame* frame = document->frame(); frame; frame = frame->tree().traverseNext()) {
985             if (Document* document = frame->document())
986                 document->timeline().suspendAnimations();
987         }
988     } else {
989         document->frame()->animation().suspendAnimationsForDocument(document);
990
991         for (Frame* frame = document->frame(); frame; frame = frame->tree().traverseNext()) {
992             if (Document* document = frame->document())
993                 frame->animation().suspendAnimationsForDocument(document);
994         }
995     }
996
997     return { };
998 }
999
1000 ExceptionOr<void> Internals::resumeAnimations() const
1001 {
1002     Document* document = contextDocument();
1003     if (!document || !document->frame())
1004         return Exception { InvalidAccessError };
1005
1006     if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled()) {
1007         document->timeline().resumeAnimations();
1008         for (Frame* frame = document->frame(); frame; frame = frame->tree().traverseNext()) {
1009             if (Document* document = frame->document())
1010                 document->timeline().resumeAnimations();
1011         }
1012     } else {
1013         document->frame()->animation().resumeAnimationsForDocument(document);
1014
1015         for (Frame* frame = document->frame(); frame; frame = frame->tree().traverseNext()) {
1016             if (Document* document = frame->document())
1017                 frame->animation().resumeAnimationsForDocument(document);
1018         }
1019     }
1020
1021     return { };
1022 }
1023
1024 ExceptionOr<bool> Internals::pauseAnimationAtTimeOnElement(const String& animationName, double pauseTime, Element& element)
1025 {
1026     if (pauseTime < 0)
1027         return Exception { InvalidAccessError };
1028     return frame()->animation().pauseAnimationAtTime(element, AtomicString(animationName), pauseTime);
1029 }
1030
1031 ExceptionOr<bool> Internals::pauseAnimationAtTimeOnPseudoElement(const String& animationName, double pauseTime, Element& element, const String& pseudoId)
1032 {
1033     if (pauseTime < 0)
1034         return Exception { InvalidAccessError };
1035
1036     if (pseudoId != "before" && pseudoId != "after")
1037         return Exception { InvalidAccessError };
1038
1039     PseudoElement* pseudoElement = pseudoId == "before" ? element.beforePseudoElement() : element.afterPseudoElement();
1040     if (!pseudoElement)
1041         return Exception { InvalidAccessError };
1042
1043     return frame()->animation().pauseAnimationAtTime(*pseudoElement, AtomicString(animationName), pauseTime);
1044 }
1045
1046 ExceptionOr<bool> Internals::pauseTransitionAtTimeOnElement(const String& propertyName, double pauseTime, Element& element)
1047 {
1048     if (pauseTime < 0)
1049         return Exception { InvalidAccessError };
1050     return frame()->animation().pauseTransitionAtTime(element, propertyName, pauseTime);
1051 }
1052
1053 ExceptionOr<bool> Internals::pauseTransitionAtTimeOnPseudoElement(const String& property, double pauseTime, Element& element, const String& pseudoId)
1054 {
1055     if (pauseTime < 0)
1056         return Exception { InvalidAccessError };
1057
1058     if (pseudoId != "before" && pseudoId != "after")
1059         return Exception { InvalidAccessError };
1060
1061     PseudoElement* pseudoElement = pseudoId == "before" ? element.beforePseudoElement() : element.afterPseudoElement();
1062     if (!pseudoElement)
1063         return Exception { InvalidAccessError };
1064
1065     return frame()->animation().pauseTransitionAtTime(*pseudoElement, property, pauseTime);
1066 }
1067
1068 ExceptionOr<RefPtr<Element>> Internals::pseudoElement(Element& element, const String& pseudoId)
1069 {
1070     if (pseudoId != "before" && pseudoId != "after")
1071         return Exception { InvalidAccessError };
1072
1073     return pseudoId == "before" ? element.beforePseudoElement() : element.afterPseudoElement();
1074 }
1075
1076 ExceptionOr<String> Internals::elementRenderTreeAsText(Element& element)
1077 {
1078     element.document().updateStyleIfNeeded();
1079
1080     String representation = externalRepresentation(&element);
1081     if (representation.isEmpty())
1082         return Exception { InvalidAccessError };
1083
1084     return WTFMove(representation);
1085 }
1086
1087 bool Internals::hasPausedImageAnimations(Element& element)
1088 {
1089     return element.renderer() && element.renderer()->hasPausedImageAnimations();
1090 }
1091     
1092 bool Internals::isPaintingFrequently(Element& element)
1093 {
1094     return element.renderer() && element.renderer()->enclosingLayer() && element.renderer()->enclosingLayer()->paintingFrequently();
1095 }
1096
1097 void Internals::incrementFrequentPaintCounter(Element& element)
1098 {
1099     if (element.renderer() && element.renderer()->enclosingLayer())
1100         element.renderer()->enclosingLayer()->simulateFrequentPaint();
1101 }
1102
1103 Ref<CSSComputedStyleDeclaration> Internals::computedStyleIncludingVisitedInfo(Element& element) const
1104 {
1105     bool allowVisitedStyle = true;
1106     return CSSComputedStyleDeclaration::create(element, allowVisitedStyle);
1107 }
1108
1109 Node* Internals::ensureUserAgentShadowRoot(Element& host)
1110 {
1111     return &host.ensureUserAgentShadowRoot();
1112 }
1113
1114 Node* Internals::shadowRoot(Element& host)
1115 {
1116     return host.shadowRoot();
1117 }
1118
1119 ExceptionOr<String> Internals::shadowRootType(const Node& root) const
1120 {
1121     if (!is<ShadowRoot>(root))
1122         return Exception { InvalidAccessError };
1123
1124     switch (downcast<ShadowRoot>(root).mode()) {
1125     case ShadowRootMode::UserAgent:
1126         return String("UserAgentShadowRoot");
1127     case ShadowRootMode::Closed:
1128         return String("ClosedShadowRoot");
1129     case ShadowRootMode::Open:
1130         return String("OpenShadowRoot");
1131     default:
1132         ASSERT_NOT_REACHED();
1133         return String("Unknown");
1134     }
1135 }
1136
1137 String Internals::shadowPseudoId(Element& element)
1138 {
1139     return element.shadowPseudoId().string();
1140 }
1141
1142 void Internals::setShadowPseudoId(Element& element, const String& id)
1143 {
1144     return element.setPseudo(id);
1145 }
1146
1147 static unsigned deferredStyleRulesCountForList(const Vector<RefPtr<StyleRuleBase>>& childRules)
1148 {
1149     unsigned count = 0;
1150     for (auto rule : childRules) {
1151         if (is<StyleRule>(rule)) {
1152             auto* cssRule = downcast<StyleRule>(rule.get());
1153             if (!cssRule->propertiesWithoutDeferredParsing())
1154                 count++;
1155             continue;
1156         }
1157
1158         StyleRuleGroup* groupRule = nullptr;
1159         if (is<StyleRuleMedia>(rule))
1160             groupRule = downcast<StyleRuleMedia>(rule.get());
1161         else if (is<StyleRuleSupports>(rule))
1162             groupRule = downcast<StyleRuleSupports>(rule.get());
1163         if (!groupRule)
1164             continue;
1165
1166         auto* groupChildRules = groupRule->childRulesWithoutDeferredParsing();
1167         if (!groupChildRules)
1168             continue;
1169
1170         count += deferredStyleRulesCountForList(*groupChildRules);
1171     }
1172
1173     return count;
1174 }
1175
1176 unsigned Internals::deferredStyleRulesCount(StyleSheet& styleSheet)
1177 {
1178     return deferredStyleRulesCountForList(downcast<CSSStyleSheet>(styleSheet).contents().childRules());
1179 }
1180
1181 static unsigned deferredGroupRulesCountForList(const Vector<RefPtr<StyleRuleBase>>& childRules)
1182 {
1183     unsigned count = 0;
1184     for (auto rule : childRules) {
1185         StyleRuleGroup* groupRule = nullptr;
1186         if (is<StyleRuleMedia>(rule))
1187             groupRule = downcast<StyleRuleMedia>(rule.get());
1188         else if (is<StyleRuleSupports>(rule))
1189             groupRule = downcast<StyleRuleSupports>(rule.get());
1190         if (!groupRule)
1191             continue;
1192
1193         auto* groupChildRules = groupRule->childRulesWithoutDeferredParsing();
1194         if (!groupChildRules)
1195             count++;
1196         else
1197             count += deferredGroupRulesCountForList(*groupChildRules);
1198     }
1199     return count;
1200 }
1201
1202 unsigned Internals::deferredGroupRulesCount(StyleSheet& styleSheet)
1203 {
1204     return deferredGroupRulesCountForList(downcast<CSSStyleSheet>(styleSheet).contents().childRules());
1205 }
1206
1207 static unsigned deferredKeyframesRulesCountForList(const Vector<RefPtr<StyleRuleBase>>& childRules)
1208 {
1209     unsigned count = 0;
1210     for (auto rule : childRules) {
1211         if (is<StyleRuleKeyframes>(rule)) {
1212             auto* cssRule = downcast<StyleRuleKeyframes>(rule.get());
1213             if (!cssRule->keyframesWithoutDeferredParsing())
1214                 count++;
1215             continue;
1216         }
1217
1218         StyleRuleGroup* groupRule = nullptr;
1219         if (is<StyleRuleMedia>(rule))
1220             groupRule = downcast<StyleRuleMedia>(rule.get());
1221         else if (is<StyleRuleSupports>(rule))
1222             groupRule = downcast<StyleRuleSupports>(rule.get());
1223         if (!groupRule)
1224             continue;
1225
1226         auto* groupChildRules = groupRule->childRulesWithoutDeferredParsing();
1227         if (!groupChildRules)
1228             continue;
1229
1230         count += deferredKeyframesRulesCountForList(*groupChildRules);
1231     }
1232
1233     return count;
1234 }
1235
1236 unsigned Internals::deferredKeyframesRulesCount(StyleSheet& styleSheet)
1237 {
1238     StyleSheetContents& contents = downcast<CSSStyleSheet>(styleSheet).contents();
1239     return deferredKeyframesRulesCountForList(contents.childRules());
1240 }
1241
1242 ExceptionOr<bool> Internals::isTimerThrottled(int timeoutId)
1243 {
1244     auto* timer = scriptExecutionContext()->findTimeout(timeoutId);
1245     if (!timer)
1246         return Exception { NotFoundError };
1247
1248     if (timer->intervalClampedToMinimum() > timer->m_originalInterval)
1249         return true;
1250
1251     return !!timer->alignedFireTime(MonotonicTime { });
1252 }
1253
1254 bool Internals::isRequestAnimationFrameThrottled() const
1255 {
1256     auto* scriptedAnimationController = contextDocument()->scriptedAnimationController();
1257     if (!scriptedAnimationController)
1258         return false;
1259     return scriptedAnimationController->isThrottled();
1260 }
1261
1262 double Internals::requestAnimationFrameInterval() const
1263 {
1264     auto* scriptedAnimationController = contextDocument()->scriptedAnimationController();
1265     if (!scriptedAnimationController)
1266         return INFINITY;
1267     return scriptedAnimationController->interval().value();
1268 }
1269
1270 bool Internals::scriptedAnimationsAreSuspended() const
1271 {
1272     Document* document = contextDocument();
1273     if (!document || !document->page())
1274         return true;
1275
1276     return document->page()->scriptedAnimationsSuspended();
1277 }
1278
1279 bool Internals::areTimersThrottled() const
1280 {
1281     return contextDocument()->isTimerThrottlingEnabled();
1282 }
1283
1284 void Internals::setEventThrottlingBehaviorOverride(std::optional<EventThrottlingBehavior> value)
1285 {
1286     Document* document = contextDocument();
1287     if (!document || !document->page())
1288         return;
1289
1290     if (!value) {
1291         document->page()->setEventThrottlingBehaviorOverride(std::nullopt);
1292         return;
1293     }
1294
1295     switch (value.value()) {
1296     case Internals::EventThrottlingBehavior::Responsive:
1297         document->page()->setEventThrottlingBehaviorOverride(WebCore::EventThrottlingBehavior::Responsive);
1298         break;
1299     case Internals::EventThrottlingBehavior::Unresponsive:
1300         document->page()->setEventThrottlingBehaviorOverride(WebCore::EventThrottlingBehavior::Unresponsive);
1301         break;
1302     }
1303 }
1304
1305 std::optional<Internals::EventThrottlingBehavior> Internals::eventThrottlingBehaviorOverride() const
1306 {
1307     Document* document = contextDocument();
1308     if (!document || !document->page())
1309         return std::nullopt;
1310
1311     auto behavior = document->page()->eventThrottlingBehaviorOverride();
1312     if (!behavior)
1313         return std::nullopt;
1314
1315     switch (behavior.value()) {
1316     case WebCore::EventThrottlingBehavior::Responsive:
1317         return Internals::EventThrottlingBehavior::Responsive;
1318     case WebCore::EventThrottlingBehavior::Unresponsive:
1319         return Internals::EventThrottlingBehavior::Unresponsive;
1320     }
1321
1322     return std::nullopt;
1323 }
1324
1325 String Internals::visiblePlaceholder(Element& element)
1326 {
1327     if (is<HTMLTextFormControlElement>(element)) {
1328         const HTMLTextFormControlElement& textFormControlElement = downcast<HTMLTextFormControlElement>(element);
1329         if (!textFormControlElement.isPlaceholderVisible())
1330             return String();
1331         if (HTMLElement* placeholderElement = textFormControlElement.placeholderElement())
1332             return placeholderElement->textContent();
1333     }
1334
1335     return String();
1336 }
1337
1338 void Internals::selectColorInColorChooser(HTMLInputElement& element, const String& colorValue)
1339 {
1340     element.selectColor(colorValue);
1341 }
1342
1343 ExceptionOr<Vector<String>> Internals::formControlStateOfPreviousHistoryItem()
1344 {
1345     HistoryItem* mainItem = frame()->loader().history().previousItem();
1346     if (!mainItem)
1347         return Exception { InvalidAccessError };
1348     String uniqueName = frame()->tree().uniqueName();
1349     if (mainItem->target() != uniqueName && !mainItem->childItemWithTarget(uniqueName))
1350         return Exception { InvalidAccessError };
1351     return Vector<String> { mainItem->target() == uniqueName ? mainItem->documentState() : mainItem->childItemWithTarget(uniqueName)->documentState() };
1352 }
1353
1354 ExceptionOr<void> Internals::setFormControlStateOfPreviousHistoryItem(const Vector<String>& state)
1355 {
1356     HistoryItem* mainItem = frame()->loader().history().previousItem();
1357     if (!mainItem)
1358         return Exception { InvalidAccessError };
1359     String uniqueName = frame()->tree().uniqueName();
1360     if (mainItem->target() == uniqueName)
1361         mainItem->setDocumentState(state);
1362     else if (HistoryItem* subItem = mainItem->childItemWithTarget(uniqueName))
1363         subItem->setDocumentState(state);
1364     else
1365         return Exception { InvalidAccessError };
1366     return { };
1367 }
1368
1369 #if ENABLE(SPEECH_SYNTHESIS)
1370
1371 void Internals::enableMockSpeechSynthesizer()
1372 {
1373     Document* document = contextDocument();
1374     if (!document || !document->domWindow())
1375         return;
1376     SpeechSynthesis* synthesis = DOMWindowSpeechSynthesis::speechSynthesis(*document->domWindow());
1377     if (!synthesis)
1378         return;
1379
1380     synthesis->setPlatformSynthesizer(std::make_unique<PlatformSpeechSynthesizerMock>(synthesis));
1381 }
1382
1383 #endif
1384
1385 #if ENABLE(WEB_RTC)
1386
1387 void Internals::emulateRTCPeerConnectionPlatformEvent(RTCPeerConnection& connection, const String& action)
1388 {
1389     if (!LibWebRTCProvider::webRTCAvailable())
1390         return;
1391
1392     connection.emulatePlatformEvent(action);
1393 }
1394
1395 void Internals::useMockRTCPeerConnectionFactory(const String& testCase)
1396 {
1397     // FIXME: We should upgrade mocks to support unified plan APIs, until then use plan B in tests using mock.
1398
1399     ASSERT(!RuntimeEnabledFeatures::sharedFeatures().webRTCUnifiedPlanEnabled());
1400     if (!LibWebRTCProvider::webRTCAvailable())
1401         return;
1402
1403 #if USE(LIBWEBRTC)
1404     Document* document = contextDocument();
1405     LibWebRTCProvider* provider = (document && document->page()) ? &document->page()->libWebRTCProvider() : nullptr;
1406     WebCore::useMockRTCPeerConnectionFactory(provider, testCase);
1407 #else
1408     UNUSED_PARAM(testCase);
1409 #endif
1410 }
1411
1412 void Internals::setICECandidateFiltering(bool enabled)
1413 {
1414     auto* page = contextDocument()->page();
1415     if (!page)
1416         return;
1417
1418     auto& rtcController = page->rtcController();
1419     if (enabled)
1420         rtcController.enableICECandidateFiltering();
1421     else
1422         rtcController.disableICECandidateFilteringForAllOrigins();
1423 }
1424
1425 void Internals::setEnumeratingAllNetworkInterfacesEnabled(bool enabled)
1426 {
1427 #if USE(LIBWEBRTC)
1428     Document* document = contextDocument();
1429     auto* page = document->page();
1430     if (!page)
1431         return;
1432     auto& rtcProvider = page->libWebRTCProvider();
1433     if (enabled)
1434         rtcProvider.enableEnumeratingAllNetworkInterfaces();
1435     else
1436         rtcProvider.disableEnumeratingAllNetworkInterfaces();
1437 #else
1438     UNUSED_PARAM(enabled);
1439 #endif
1440 }
1441
1442 void Internals::stopPeerConnection(RTCPeerConnection& connection)
1443 {
1444     ActiveDOMObject& object = connection;
1445     object.stop();
1446 }
1447
1448 void Internals::applyRotationForOutgoingVideoSources(RTCPeerConnection& connection)
1449 {
1450     connection.applyRotationForOutgoingVideoSources();
1451 }
1452 #endif
1453
1454 #if ENABLE(MEDIA_STREAM)
1455
1456 void Internals::setMockMediaCaptureDevicesEnabled(bool enabled)
1457 {
1458     WebCore::DeprecatedGlobalSettings::setMockCaptureDevicesEnabled(enabled);
1459 }
1460
1461 #endif
1462
1463 ExceptionOr<Ref<DOMRect>> Internals::absoluteCaretBounds()
1464 {
1465     Document* document = contextDocument();
1466     if (!document || !document->frame())
1467         return Exception { InvalidAccessError };
1468
1469     return DOMRect::create(document->frame()->selection().absoluteCaretBounds());
1470 }
1471
1472 Ref<DOMRect> Internals::boundingBox(Element& element)
1473 {
1474     element.document().updateLayoutIgnorePendingStylesheets();
1475     auto renderer = element.renderer();
1476     if (!renderer)
1477         return DOMRect::create();
1478     return DOMRect::create(renderer->absoluteBoundingBoxRectIgnoringTransforms());
1479 }
1480
1481 ExceptionOr<Ref<DOMRectList>> Internals::inspectorHighlightRects()
1482 {
1483     Document* document = contextDocument();
1484     if (!document || !document->page())
1485         return Exception { InvalidAccessError };
1486
1487     Highlight highlight;
1488     document->page()->inspectorController().getHighlight(highlight, InspectorOverlay::CoordinateSystem::View);
1489     return DOMRectList::create(highlight.quads);
1490 }
1491
1492 ExceptionOr<String> Internals::inspectorHighlightObject()
1493 {
1494     Document* document = contextDocument();
1495     if (!document || !document->page())
1496         return Exception { InvalidAccessError };
1497
1498     return document->page()->inspectorController().buildObjectForHighlightedNodes()->toJSONString();
1499 }
1500
1501 ExceptionOr<unsigned> Internals::markerCountForNode(Node& node, const String& markerType)
1502 {
1503     OptionSet<DocumentMarker::MarkerType> markerTypes;
1504     if (!markerTypesFrom(markerType, markerTypes))
1505         return Exception { SyntaxError };
1506
1507     node.document().frame()->editor().updateEditorUINowIfScheduled();
1508     return node.document().markers().markersFor(&node, markerTypes).size();
1509 }
1510
1511 ExceptionOr<RenderedDocumentMarker*> Internals::markerAt(Node& node, const String& markerType, unsigned index)
1512 {
1513     node.document().updateLayoutIgnorePendingStylesheets();
1514
1515     OptionSet<DocumentMarker::MarkerType> markerTypes;
1516     if (!markerTypesFrom(markerType, markerTypes))
1517         return Exception { SyntaxError };
1518
1519     node.document().frame()->editor().updateEditorUINowIfScheduled();
1520
1521     Vector<RenderedDocumentMarker*> markers = node.document().markers().markersFor(&node, markerTypes);
1522     if (markers.size() <= index)
1523         return nullptr;
1524     return markers[index];
1525 }
1526
1527 ExceptionOr<RefPtr<Range>> Internals::markerRangeForNode(Node& node, const String& markerType, unsigned index)
1528 {
1529     auto result = markerAt(node, markerType, index);
1530     if (result.hasException())
1531         return result.releaseException();
1532     auto marker = result.releaseReturnValue();
1533     if (!marker)
1534         return nullptr;
1535     return RefPtr<Range> { Range::create(node.document(), &node, marker->startOffset(), &node, marker->endOffset()) };
1536 }
1537
1538 ExceptionOr<String> Internals::markerDescriptionForNode(Node& node, const String& markerType, unsigned index)
1539 {
1540     auto result = markerAt(node, markerType, index);
1541     if (result.hasException())
1542         return result.releaseException();
1543     auto marker = result.releaseReturnValue();
1544     if (!marker)
1545         return String();
1546     return String { marker->description() };
1547 }
1548
1549 ExceptionOr<String> Internals::dumpMarkerRects(const String& markerTypeString)
1550 {
1551     DocumentMarker::MarkerType markerType;
1552     if (!markerTypeFrom(markerTypeString, markerType))
1553         return Exception { SyntaxError };
1554
1555     contextDocument()->markers().updateRectsForInvalidatedMarkersOfType(markerType);
1556     auto rects = contextDocument()->markers().renderedRectsForMarkers(markerType);
1557
1558     StringBuilder rectString;
1559     rectString.appendLiteral("marker rects: ");
1560     for (const auto& rect : rects) {
1561         rectString.append('(');
1562         rectString.appendNumber(rect.x());
1563         rectString.appendLiteral(", ");
1564         rectString.appendNumber(rect.y());
1565         rectString.appendLiteral(", ");
1566         rectString.appendNumber(rect.width());
1567         rectString.appendLiteral(", ");
1568         rectString.appendNumber(rect.height());
1569         rectString.appendLiteral(") ");
1570     }
1571     return rectString.toString();
1572 }
1573
1574 void Internals::addTextMatchMarker(const Range& range, bool isActive)
1575 {
1576     range.ownerDocument().updateLayoutIgnorePendingStylesheets();
1577     range.ownerDocument().markers().addTextMatchMarker(&range, isActive);
1578 }
1579
1580 ExceptionOr<void> Internals::setMarkedTextMatchesAreHighlighted(bool flag)
1581 {
1582     Document* document = contextDocument();
1583     if (!document || !document->frame())
1584         return Exception { InvalidAccessError };
1585     document->frame()->editor().setMarkedTextMatchesAreHighlighted(flag);
1586     return { };
1587 }
1588
1589 void Internals::invalidateFontCache()
1590 {
1591     FontCache::singleton().invalidate();
1592 }
1593
1594 void Internals::setFontSmoothingEnabled(bool enabled)
1595 {
1596     WebCore::FontCascade::setShouldUseSmoothing(enabled);
1597 }
1598
1599 ExceptionOr<void> Internals::setLowPowerModeEnabled(bool isEnabled)
1600 {
1601     auto* document = contextDocument();
1602     if (!document)
1603         return Exception { InvalidAccessError };
1604     auto* page = document->page();
1605     if (!page)
1606         return Exception { InvalidAccessError };
1607
1608     page->setLowPowerModeEnabledOverrideForTesting(isEnabled);
1609     return { };
1610 }
1611
1612 ExceptionOr<void> Internals::setScrollViewPosition(int x, int y)
1613 {
1614     Document* document = contextDocument();
1615     if (!document || !document->view())
1616         return Exception { InvalidAccessError };
1617
1618     auto& frameView = *document->view();
1619     bool constrainsScrollingToContentEdgeOldValue = frameView.constrainsScrollingToContentEdge();
1620     bool scrollbarsSuppressedOldValue = frameView.scrollbarsSuppressed();
1621
1622     frameView.setConstrainsScrollingToContentEdge(false);
1623     frameView.setScrollbarsSuppressed(false);
1624     frameView.setScrollOffsetFromInternals({ x, y });
1625     frameView.setScrollbarsSuppressed(scrollbarsSuppressedOldValue);
1626     frameView.setConstrainsScrollingToContentEdge(constrainsScrollingToContentEdgeOldValue);
1627
1628     return { };
1629 }
1630
1631 ExceptionOr<void> Internals::unconstrainedScrollTo(Element& element, double x, double y)
1632 {
1633     Document* document = contextDocument();
1634     if (!document || !document->view())
1635         return Exception { InvalidAccessError };
1636
1637     element.scrollTo({ x, y }, ScrollClamping::Unclamped);
1638     return { };
1639 }
1640
1641 ExceptionOr<Ref<DOMRect>> Internals::layoutViewportRect()
1642 {
1643     Document* document = contextDocument();
1644     if (!document || !document->frame())
1645         return Exception { InvalidAccessError };
1646
1647     document->updateLayoutIgnorePendingStylesheets();
1648
1649     auto& frameView = *document->view();
1650     return DOMRect::create(frameView.layoutViewportRect());
1651 }
1652
1653 ExceptionOr<Ref<DOMRect>> Internals::visualViewportRect()
1654 {
1655     Document* document = contextDocument();
1656     if (!document || !document->frame())
1657         return Exception { InvalidAccessError };
1658
1659     document->updateLayoutIgnorePendingStylesheets();
1660
1661     auto& frameView = *document->view();
1662     return DOMRect::create(frameView.visualViewportRect());
1663 }
1664
1665 ExceptionOr<void> Internals::setViewBaseBackgroundColor(const String& colorValue)
1666 {
1667     Document* document = contextDocument();
1668     if (!document || !document->view())
1669         return Exception { InvalidAccessError };
1670
1671     if (colorValue == "transparent") {
1672         document->view()->setBaseBackgroundColor(Color::transparent);
1673         return { };
1674     }
1675     if (colorValue == "white") {
1676         document->view()->setBaseBackgroundColor(Color::white);
1677         return { };
1678     }
1679     return Exception { SyntaxError };
1680 }
1681
1682 ExceptionOr<void> Internals::setPagination(const String& mode, int gap, int pageLength)
1683 {
1684     Document* document = contextDocument();
1685     if (!document || !document->page())
1686         return Exception { InvalidAccessError };
1687
1688     Pagination pagination;
1689     if (mode == "Unpaginated")
1690         pagination.mode = Pagination::Unpaginated;
1691     else if (mode == "LeftToRightPaginated")
1692         pagination.mode = Pagination::LeftToRightPaginated;
1693     else if (mode == "RightToLeftPaginated")
1694         pagination.mode = Pagination::RightToLeftPaginated;
1695     else if (mode == "TopToBottomPaginated")
1696         pagination.mode = Pagination::TopToBottomPaginated;
1697     else if (mode == "BottomToTopPaginated")
1698         pagination.mode = Pagination::BottomToTopPaginated;
1699     else
1700         return Exception { SyntaxError };
1701
1702     pagination.gap = gap;
1703     pagination.pageLength = pageLength;
1704     document->page()->setPagination(pagination);
1705
1706     return { };
1707 }
1708
1709 ExceptionOr<void> Internals::setPaginationLineGridEnabled(bool enabled)
1710 {
1711     Document* document = contextDocument();
1712     if (!document || !document->page())
1713         return Exception { InvalidAccessError };
1714     document->page()->setPaginationLineGridEnabled(enabled);
1715     return { };
1716 }
1717
1718 ExceptionOr<String> Internals::configurationForViewport(float devicePixelRatio, int deviceWidth, int deviceHeight, int availableWidth, int availableHeight)
1719 {
1720     Document* document = contextDocument();
1721     if (!document || !document->page())
1722         return Exception { InvalidAccessError };
1723
1724     const int defaultLayoutWidthForNonMobilePages = 980;
1725
1726     ViewportArguments arguments = document->page()->viewportArguments();
1727     ViewportAttributes attributes = computeViewportAttributes(arguments, defaultLayoutWidthForNonMobilePages, deviceWidth, deviceHeight, devicePixelRatio, IntSize(availableWidth, availableHeight));
1728     restrictMinimumScaleFactorToViewportSize(attributes, IntSize(availableWidth, availableHeight), devicePixelRatio);
1729     restrictScaleFactorToInitialScaleIfNotUserScalable(attributes);
1730
1731     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") };
1732 }
1733
1734 ExceptionOr<bool> Internals::wasLastChangeUserEdit(Element& textField)
1735 {
1736     if (is<HTMLInputElement>(textField))
1737         return downcast<HTMLInputElement>(textField).lastChangeWasUserEdit();
1738
1739     if (is<HTMLTextAreaElement>(textField))
1740         return downcast<HTMLTextAreaElement>(textField).lastChangeWasUserEdit();
1741
1742     return Exception { InvalidNodeTypeError };
1743 }
1744
1745 bool Internals::elementShouldAutoComplete(HTMLInputElement& element)
1746 {
1747     return element.shouldAutocomplete();
1748 }
1749
1750 void Internals::setEditingValue(HTMLInputElement& element, const String& value)
1751 {
1752     element.setEditingValue(value);
1753 }
1754
1755 void Internals::setAutofilled(HTMLInputElement& element, bool enabled)
1756 {
1757     element.setAutoFilled(enabled);
1758 }
1759
1760 static AutoFillButtonType toAutoFillButtonType(Internals::AutoFillButtonType type)
1761 {
1762     switch (type) {
1763     case Internals::AutoFillButtonType::None:
1764         return AutoFillButtonType::None;
1765     case Internals::AutoFillButtonType::Credentials:
1766         return AutoFillButtonType::Credentials;
1767     case Internals::AutoFillButtonType::Contacts:
1768         return AutoFillButtonType::Contacts;
1769     case Internals::AutoFillButtonType::StrongPassword:
1770         return AutoFillButtonType::StrongPassword;
1771     }
1772     ASSERT_NOT_REACHED();
1773     return AutoFillButtonType::None;
1774 }
1775
1776 static Internals::AutoFillButtonType toInternalsAutoFillButtonType(AutoFillButtonType type)
1777 {
1778     switch (type) {
1779     case AutoFillButtonType::None:
1780         return Internals::AutoFillButtonType::None;
1781     case AutoFillButtonType::Credentials:
1782         return Internals::AutoFillButtonType::Credentials;
1783     case AutoFillButtonType::Contacts:
1784         return Internals::AutoFillButtonType::Contacts;
1785     case AutoFillButtonType::StrongPassword:
1786         return Internals::AutoFillButtonType::StrongPassword;
1787     }
1788     ASSERT_NOT_REACHED();
1789     return Internals::AutoFillButtonType::None;
1790 }
1791
1792 void Internals::setShowAutoFillButton(HTMLInputElement& element, AutoFillButtonType type)
1793 {
1794     element.setShowAutoFillButton(toAutoFillButtonType(type));
1795 }
1796
1797 auto Internals::autoFillButtonType(const HTMLInputElement& element) -> AutoFillButtonType
1798 {
1799     return toInternalsAutoFillButtonType(element.autoFillButtonType());
1800 }
1801
1802 auto Internals::lastAutoFillButtonType(const HTMLInputElement& element) -> AutoFillButtonType
1803 {
1804     return toInternalsAutoFillButtonType(element.lastAutoFillButtonType());
1805 }
1806
1807 ExceptionOr<void> Internals::scrollElementToRect(Element& element, int x, int y, int w, int h)
1808 {
1809     FrameView* frameView = element.document().view();
1810     if (!frameView)
1811         return Exception { InvalidAccessError };
1812     frameView->scrollElementToRect(element, { x, y, w, h });
1813     return { };
1814 }
1815
1816 ExceptionOr<String> Internals::autofillFieldName(Element& element)
1817 {
1818     if (!is<HTMLFormControlElement>(element))
1819         return Exception { InvalidNodeTypeError };
1820
1821     return String { downcast<HTMLFormControlElement>(element).autofillData().fieldName };
1822 }
1823
1824 ExceptionOr<void> Internals::invalidateControlTints()
1825 {
1826     Document* document = contextDocument();
1827     if (!document || !document->view())
1828         return Exception { InvalidAccessError };
1829
1830     document->view()->invalidateControlTints();
1831     return { };
1832 }
1833
1834 RefPtr<Range> Internals::rangeFromLocationAndLength(Element& scope, int rangeLocation, int rangeLength)
1835 {
1836     return TextIterator::rangeFromLocationAndLength(&scope, rangeLocation, rangeLength);
1837 }
1838
1839 unsigned Internals::locationFromRange(Element& scope, const Range& range)
1840 {
1841     size_t location = 0;
1842     size_t unusedLength = 0;
1843     TextIterator::getLocationAndLengthFromRange(&scope, &range, location, unusedLength);
1844     return location;
1845 }
1846
1847 unsigned Internals::lengthFromRange(Element& scope, const Range& range)
1848 {
1849     size_t unusedLocation = 0;
1850     size_t length = 0;
1851     TextIterator::getLocationAndLengthFromRange(&scope, &range, unusedLocation, length);
1852     return length;
1853 }
1854
1855 String Internals::rangeAsText(const Range& range)
1856 {
1857     return range.text();
1858 }
1859
1860 Ref<Range> Internals::subrange(Range& range, int rangeLocation, int rangeLength)
1861 {
1862     return TextIterator::subrange(range, rangeLocation, rangeLength);
1863 }
1864
1865 RefPtr<Range> Internals::rangeOfStringNearLocation(const Range& searchRange, const String& text, unsigned targetOffset)
1866 {
1867     return findClosestPlainText(searchRange, text, { }, targetOffset);
1868 }
1869
1870 #if !PLATFORM(MAC)
1871 ExceptionOr<RefPtr<Range>> Internals::rangeForDictionaryLookupAtLocation(int, int)
1872 {
1873     return Exception { InvalidAccessError };
1874 }
1875 #endif
1876
1877 ExceptionOr<void> Internals::setDelegatesScrolling(bool enabled)
1878 {
1879     Document* document = contextDocument();
1880     // Delegate scrolling is valid only on mainframe's view.
1881     if (!document || !document->view() || !document->page() || &document->page()->mainFrame() != document->frame())
1882         return Exception { InvalidAccessError };
1883
1884     document->view()->setDelegatesScrolling(enabled);
1885     return { };
1886 }
1887
1888 ExceptionOr<int> Internals::lastSpellCheckRequestSequence()
1889 {
1890     Document* document = contextDocument();
1891     if (!document || !document->frame())
1892         return Exception { InvalidAccessError };
1893
1894     return document->frame()->editor().spellChecker().lastRequestSequence();
1895 }
1896
1897 ExceptionOr<int> Internals::lastSpellCheckProcessedSequence()
1898 {
1899     Document* document = contextDocument();
1900     if (!document || !document->frame())
1901         return Exception { InvalidAccessError };
1902
1903     return document->frame()->editor().spellChecker().lastProcessedSequence();
1904 }
1905
1906 Vector<String> Internals::userPreferredLanguages() const
1907 {
1908     return WTF::userPreferredLanguages();
1909 }
1910
1911 void Internals::setUserPreferredLanguages(const Vector<String>& languages)
1912 {
1913     overrideUserPreferredLanguages(languages);
1914 }
1915
1916 Vector<String> Internals::userPreferredAudioCharacteristics() const
1917 {
1918     Document* document = contextDocument();
1919     if (!document || !document->page())
1920         return Vector<String>();
1921 #if ENABLE(VIDEO_TRACK)
1922     return document->page()->group().captionPreferences().preferredAudioCharacteristics();
1923 #else
1924     return Vector<String>();
1925 #endif
1926 }
1927
1928 void Internals::setUserPreferredAudioCharacteristic(const String& characteristic)
1929 {
1930     Document* document = contextDocument();
1931     if (!document || !document->page())
1932         return;
1933 #if ENABLE(VIDEO_TRACK)
1934     document->page()->group().captionPreferences().setPreferredAudioCharacteristic(characteristic);
1935 #else
1936     UNUSED_PARAM(characteristic);
1937 #endif
1938 }
1939
1940 ExceptionOr<unsigned> Internals::wheelEventHandlerCount()
1941 {
1942     Document* document = contextDocument();
1943     if (!document)
1944         return Exception { InvalidAccessError };
1945
1946     return document->wheelEventHandlerCount();
1947 }
1948
1949 ExceptionOr<unsigned> Internals::touchEventHandlerCount()
1950 {
1951     Document* document = contextDocument();
1952     if (!document)
1953         return Exception { InvalidAccessError };
1954
1955     return document->touchEventHandlerCount();
1956 }
1957
1958 ExceptionOr<Ref<DOMRectList>> Internals::touchEventRectsForEvent(const String& eventName)
1959 {
1960     Document* document = contextDocument();
1961     if (!document || !document->page())
1962         return Exception { InvalidAccessError };
1963
1964     return document->page()->touchEventRectsForEvent(eventName);
1965 }
1966
1967 ExceptionOr<Ref<DOMRectList>> Internals::passiveTouchEventListenerRects()
1968 {
1969     Document* document = contextDocument();
1970     if (!document || !document->page())
1971         return Exception { InvalidAccessError };
1972
1973     return document->page()->passiveTouchEventListenerRects();
1974 }
1975
1976 // FIXME: Remove the document argument. It is almost always the same as
1977 // contextDocument(), with the exception of a few tests that pass a
1978 // different document, and could just make the call through another Internals
1979 // instance instead.
1980 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
1981 {
1982     if (!document.frame() || !document.frame()->view())
1983         return Exception { InvalidAccessError };
1984
1985     Frame* frame = document.frame();
1986     FrameView* frameView = document.view();
1987     RenderView* renderView = document.renderView();
1988     if (!renderView)
1989         return nullptr;
1990
1991     document.updateLayoutIgnorePendingStylesheets();
1992
1993     float zoomFactor = frame->pageZoomFactor();
1994     LayoutPoint point(centerX * zoomFactor + frameView->scrollX(), centerY * zoomFactor + frameView->scrollY());
1995
1996     HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::CollectMultipleElements;
1997     if (ignoreClipping)
1998         hitType |= HitTestRequest::IgnoreClipping;
1999     if (!allowUserAgentShadowContent)
2000         hitType |= HitTestRequest::DisallowUserAgentShadowContent;
2001     if (allowChildFrameContent)
2002         hitType |= HitTestRequest::AllowChildFrameContent;
2003
2004     HitTestRequest request(hitType);
2005
2006     // When ignoreClipping is false, this method returns null for coordinates outside of the viewport.
2007     if (!request.ignoreClipping() && !frameView->visibleContentRect().intersects(HitTestLocation::rectForPoint(point, topPadding, rightPadding, bottomPadding, leftPadding)))
2008         return nullptr;
2009
2010     HitTestResult result(point, topPadding, rightPadding, bottomPadding, leftPadding);
2011     renderView->hitTest(request, result);
2012     const HitTestResult::NodeSet& nodeSet = result.listBasedTestResult();
2013     Vector<Ref<Node>> matches;
2014     matches.reserveInitialCapacity(nodeSet.size());
2015     for (auto& node : nodeSet)
2016         matches.uncheckedAppend(*node);
2017
2018     return RefPtr<NodeList> { StaticNodeList::create(WTFMove(matches)) };
2019 }
2020
2021 class GetCallerCodeBlockFunctor {
2022 public:
2023     GetCallerCodeBlockFunctor()
2024         : m_iterations(0)
2025         , m_codeBlock(0)
2026     {
2027     }
2028
2029     StackVisitor::Status operator()(StackVisitor& visitor) const
2030     {
2031         ++m_iterations;
2032         if (m_iterations < 2)
2033             return StackVisitor::Continue;
2034
2035         m_codeBlock = visitor->codeBlock();
2036         return StackVisitor::Done;
2037     }
2038
2039     CodeBlock* codeBlock() const { return m_codeBlock; }
2040
2041 private:
2042     mutable int m_iterations;
2043     mutable CodeBlock* m_codeBlock;
2044 };
2045
2046 String Internals::parserMetaData(JSC::JSValue code)
2047 {
2048     JSC::VM& vm = contextDocument()->vm();
2049     JSC::ExecState* exec = vm.topCallFrame;
2050     ScriptExecutable* executable;
2051
2052     if (!code || code.isNull() || code.isUndefined()) {
2053         GetCallerCodeBlockFunctor iter;
2054         exec->iterate(iter);
2055         CodeBlock* codeBlock = iter.codeBlock();
2056         executable = codeBlock->ownerScriptExecutable();
2057     } else if (code.isFunction(vm)) {
2058         JSFunction* funcObj = JSC::jsCast<JSFunction*>(code.toObject(exec));
2059         executable = funcObj->jsExecutable();
2060     } else
2061         return String();
2062
2063     unsigned startLine = executable->firstLine();
2064     unsigned startColumn = executable->startColumn();
2065     unsigned endLine = executable->lastLine();
2066     unsigned endColumn = executable->endColumn();
2067
2068     StringBuilder result;
2069
2070     if (executable->isFunctionExecutable()) {
2071         FunctionExecutable* funcExecutable = reinterpret_cast<FunctionExecutable*>(executable);
2072         String inferredName = funcExecutable->inferredName().string();
2073         result.appendLiteral("function \"");
2074         result.append(inferredName);
2075         result.append('"');
2076     } else if (executable->isEvalExecutable())
2077         result.appendLiteral("eval");
2078     else if (executable->isModuleProgramExecutable())
2079         result.appendLiteral("module");
2080     else if (executable->isProgramExecutable())
2081         result.appendLiteral("program");
2082     else
2083         ASSERT_NOT_REACHED();
2084
2085     result.appendLiteral(" { ");
2086     result.appendNumber(startLine);
2087     result.append(':');
2088     result.appendNumber(startColumn);
2089     result.appendLiteral(" - ");
2090     result.appendNumber(endLine);
2091     result.append(':');
2092     result.appendNumber(endColumn);
2093     result.appendLiteral(" }");
2094
2095     return result.toString();
2096 }
2097
2098 void Internals::updateEditorUINowIfScheduled()
2099 {
2100     if (Document* document = contextDocument()) {
2101         if (Frame* frame = document->frame())
2102             frame->editor().updateEditorUINowIfScheduled();
2103     }
2104 }
2105
2106 bool Internals::hasSpellingMarker(int from, int length)
2107 {
2108     Document* document = contextDocument();
2109     if (!document || !document->frame())
2110         return false;
2111
2112     updateEditorUINowIfScheduled();
2113
2114     return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
2115 }
2116
2117 bool Internals::hasAutocorrectedMarker(int from, int length)
2118 {
2119     Document* document = contextDocument();
2120     if (!document || !document->frame())
2121         return false;
2122
2123     updateEditorUINowIfScheduled();
2124
2125     return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Autocorrected, from, length);
2126 }
2127
2128 void Internals::setContinuousSpellCheckingEnabled(bool enabled)
2129 {
2130     if (!contextDocument() || !contextDocument()->frame())
2131         return;
2132
2133     if (enabled != contextDocument()->frame()->editor().isContinuousSpellCheckingEnabled())
2134         contextDocument()->frame()->editor().toggleContinuousSpellChecking();
2135 }
2136
2137 void Internals::setAutomaticQuoteSubstitutionEnabled(bool enabled)
2138 {
2139     if (!contextDocument() || !contextDocument()->frame())
2140         return;
2141
2142 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
2143     if (enabled != contextDocument()->frame()->editor().isAutomaticQuoteSubstitutionEnabled())
2144         contextDocument()->frame()->editor().toggleAutomaticQuoteSubstitution();
2145 #else
2146     UNUSED_PARAM(enabled);
2147 #endif
2148 }
2149
2150 void Internals::setAutomaticLinkDetectionEnabled(bool enabled)
2151 {
2152     if (!contextDocument() || !contextDocument()->frame())
2153         return;
2154
2155 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
2156     if (enabled != contextDocument()->frame()->editor().isAutomaticLinkDetectionEnabled())
2157         contextDocument()->frame()->editor().toggleAutomaticLinkDetection();
2158 #else
2159     UNUSED_PARAM(enabled);
2160 #endif
2161 }
2162
2163 void Internals::setAutomaticDashSubstitutionEnabled(bool enabled)
2164 {
2165     if (!contextDocument() || !contextDocument()->frame())
2166         return;
2167
2168 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
2169     if (enabled != contextDocument()->frame()->editor().isAutomaticDashSubstitutionEnabled())
2170         contextDocument()->frame()->editor().toggleAutomaticDashSubstitution();
2171 #else
2172     UNUSED_PARAM(enabled);
2173 #endif
2174 }
2175
2176 void Internals::setAutomaticTextReplacementEnabled(bool enabled)
2177 {
2178     if (!contextDocument() || !contextDocument()->frame())
2179         return;
2180
2181 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
2182     if (enabled != contextDocument()->frame()->editor().isAutomaticTextReplacementEnabled())
2183         contextDocument()->frame()->editor().toggleAutomaticTextReplacement();
2184 #else
2185     UNUSED_PARAM(enabled);
2186 #endif
2187 }
2188
2189 void Internals::setAutomaticSpellingCorrectionEnabled(bool enabled)
2190 {
2191     if (!contextDocument() || !contextDocument()->frame())
2192         return;
2193
2194 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
2195     if (enabled != contextDocument()->frame()->editor().isAutomaticSpellingCorrectionEnabled())
2196         contextDocument()->frame()->editor().toggleAutomaticSpellingCorrection();
2197 #else
2198     UNUSED_PARAM(enabled);
2199 #endif
2200 }
2201
2202 void Internals::handleAcceptedCandidate(const String& candidate, unsigned location, unsigned length)
2203 {
2204     if (!contextDocument() || !contextDocument()->frame())
2205         return;
2206
2207     TextCheckingResult result;
2208     result.type = TextCheckingType::None;
2209     result.location = location;
2210     result.length = length;
2211     result.replacement = candidate;
2212     contextDocument()->frame()->editor().handleAcceptedCandidate(result);
2213 }
2214
2215 bool Internals::isOverwriteModeEnabled()
2216 {
2217     Document* document = contextDocument();
2218     if (!document || !document->frame())
2219         return false;
2220
2221     return document->frame()->editor().isOverwriteModeEnabled();
2222 }
2223
2224 void Internals::toggleOverwriteModeEnabled()
2225 {
2226     Document* document = contextDocument();
2227     if (!document || !document->frame())
2228         return;
2229
2230     document->frame()->editor().toggleOverwriteModeEnabled();
2231 }
2232
2233 static ExceptionOr<FindOptions> parseFindOptions(const Vector<String>& optionList)
2234 {
2235     const struct {
2236         const char* name;
2237         FindOptionFlag value;
2238     } flagList[] = {
2239         {"CaseInsensitive", CaseInsensitive},
2240         {"AtWordStarts", AtWordStarts},
2241         {"TreatMedialCapitalAsWordStart", TreatMedialCapitalAsWordStart},
2242         {"Backwards", Backwards},
2243         {"WrapAround", WrapAround},
2244         {"StartInSelection", StartInSelection},
2245         {"DoNotRevealSelection", DoNotRevealSelection},
2246         {"AtWordEnds", AtWordEnds},
2247         {"DoNotTraverseFlatTree", DoNotTraverseFlatTree},
2248     };
2249     FindOptions result;
2250     for (auto& option : optionList) {
2251         bool found = false;
2252         for (auto& flag : flagList) {
2253             if (flag.name == option) {
2254                 result.add(flag.value);
2255                 found = true;
2256                 break;
2257             }
2258         }
2259         if (!found)
2260             return Exception { SyntaxError };
2261     }
2262     return WTFMove(result);
2263 }
2264
2265 ExceptionOr<RefPtr<Range>> Internals::rangeOfString(const String& text, RefPtr<Range>&& referenceRange, const Vector<String>& findOptions)
2266 {
2267     Document* document = contextDocument();
2268     if (!document || !document->frame())
2269         return Exception { InvalidAccessError };
2270
2271     auto parsedOptions = parseFindOptions(findOptions);
2272     if (parsedOptions.hasException())
2273         return parsedOptions.releaseException();
2274
2275     return document->frame()->editor().rangeOfString(text, referenceRange.get(), parsedOptions.releaseReturnValue());
2276 }
2277
2278 ExceptionOr<unsigned> Internals::countMatchesForText(const String& text, const Vector<String>& findOptions, const String& markMatches)
2279 {
2280     Document* document = contextDocument();
2281     if (!document || !document->frame())
2282         return Exception { InvalidAccessError };
2283
2284     auto parsedOptions = parseFindOptions(findOptions);
2285     if (parsedOptions.hasException())
2286         return parsedOptions.releaseException();
2287
2288     bool mark = markMatches == "mark";
2289     return document->frame()->editor().countMatchesForText(text, nullptr, parsedOptions.releaseReturnValue(), 1000, mark, nullptr);
2290 }
2291
2292 ExceptionOr<unsigned> Internals::countFindMatches(const String& text, const Vector<String>& findOptions)
2293 {
2294     Document* document = contextDocument();
2295     if (!document || !document->page())
2296         return Exception { InvalidAccessError };
2297
2298     auto parsedOptions = parseFindOptions(findOptions);
2299     if (parsedOptions.hasException())
2300         return parsedOptions.releaseException();
2301
2302     return document->page()->countFindMatches(text, parsedOptions.releaseReturnValue(), 1000);
2303 }
2304
2305 unsigned Internals::numberOfLiveNodes() const
2306 {
2307     unsigned nodeCount = 0;
2308     for (auto* document : Document::allDocuments())
2309         nodeCount += document->referencingNodeCount();
2310     return nodeCount;
2311 }
2312
2313 unsigned Internals::numberOfLiveDocuments() const
2314 {
2315     return Document::allDocuments().size();
2316 }
2317
2318 unsigned Internals::referencingNodeCount(const Document& document) const
2319 {
2320     return document.referencingNodeCount();
2321 }
2322
2323 #if ENABLE(INTERSECTION_OBSERVER)
2324 unsigned Internals::numberOfIntersectionObservers(const Document& document) const
2325 {
2326     return document.numberOfIntersectionObservers();
2327 }
2328 #endif
2329
2330 uint64_t Internals::documentIdentifier(const Document& document) const
2331 {
2332     return document.identifier().toUInt64();
2333 }
2334
2335 bool Internals::isDocumentAlive(uint64_t documentIdentifier) const
2336 {
2337     return Document::allDocumentsMap().contains(makeObjectIdentifier<DocumentIdentifierType>(documentIdentifier));
2338 }
2339
2340 String Internals::serviceWorkerClientIdentifier(const Document& document) const
2341 {
2342 #if ENABLE(SERVICE_WORKER)
2343     return ServiceWorkerClientIdentifier { ServiceWorkerProvider::singleton().serviceWorkerConnectionForSession(document.sessionID()).serverConnectionIdentifier(), document.identifier() }.toString();
2344 #else
2345     UNUSED_PARAM(document);
2346     return String();
2347 #endif
2348 }
2349
2350 RefPtr<WindowProxy> Internals::openDummyInspectorFrontend(const String& url)
2351 {
2352     auto* inspectedPage = contextDocument()->frame()->page();
2353     auto* window = inspectedPage->mainFrame().document()->domWindow();
2354     auto frontendWindowProxy = window->open(*window, *window, url, "", "").releaseReturnValue();
2355     m_inspectorFrontend = std::make_unique<InspectorStubFrontend>(*inspectedPage, downcast<DOMWindow>(frontendWindowProxy->window()));
2356     return frontendWindowProxy;
2357 }
2358
2359 void Internals::closeDummyInspectorFrontend()
2360 {
2361     m_inspectorFrontend = nullptr;
2362 }
2363
2364 ExceptionOr<void> Internals::setInspectorIsUnderTest(bool isUnderTest)
2365 {
2366     Page* page = contextDocument()->frame()->page();
2367     if (!page)
2368         return Exception { InvalidAccessError };
2369
2370     page->inspectorController().setIsUnderTest(isUnderTest);
2371     return { };
2372 }
2373
2374 bool Internals::hasGrammarMarker(int from, int length)
2375 {
2376     Document* document = contextDocument();
2377     if (!document || !document->frame())
2378         return false;
2379
2380     return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Grammar, from, length);
2381 }
2382
2383 unsigned Internals::numberOfScrollableAreas()
2384 {
2385     Document* document = contextDocument();
2386     if (!document || !document->frame())
2387         return 0;
2388
2389     unsigned count = 0;
2390     Frame* frame = document->frame();
2391     if (frame->view()->scrollableAreas())
2392         count += frame->view()->scrollableAreas()->size();
2393
2394     for (Frame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
2395         if (child->view() && child->view()->scrollableAreas())
2396             count += child->view()->scrollableAreas()->size();
2397     }
2398
2399     return count;
2400 }
2401
2402 ExceptionOr<bool> Internals::isPageBoxVisible(int pageNumber)
2403 {
2404     Document* document = contextDocument();
2405     if (!document)
2406         return Exception { InvalidAccessError };
2407
2408     return document->isPageBoxVisible(pageNumber);
2409 }
2410
2411 static LayerTreeFlags toLayerTreeFlags(unsigned short flags)
2412 {
2413     LayerTreeFlags layerTreeFlags = 0;
2414     if (flags & Internals::LAYER_TREE_INCLUDES_VISIBLE_RECTS)
2415         layerTreeFlags |= LayerTreeFlagsIncludeVisibleRects;
2416     if (flags & Internals::LAYER_TREE_INCLUDES_TILE_CACHES)
2417         layerTreeFlags |= LayerTreeFlagsIncludeTileCaches;
2418     if (flags & Internals::LAYER_TREE_INCLUDES_REPAINT_RECTS)
2419         layerTreeFlags |= LayerTreeFlagsIncludeRepaintRects;
2420     if (flags & Internals::LAYER_TREE_INCLUDES_PAINTING_PHASES)
2421         layerTreeFlags |= LayerTreeFlagsIncludePaintingPhases;
2422     if (flags & Internals::LAYER_TREE_INCLUDES_CONTENT_LAYERS)
2423         layerTreeFlags |= LayerTreeFlagsIncludeContentLayers;
2424     if (flags & Internals::LAYER_TREE_INCLUDES_ACCELERATES_DRAWING)
2425         layerTreeFlags |= LayerTreeFlagsIncludeAcceleratesDrawing;
2426     if (flags & Internals::LAYER_TREE_INCLUDES_BACKING_STORE_ATTACHED)
2427         layerTreeFlags |= LayerTreeFlagsIncludeBackingStoreAttached;
2428
2429     return layerTreeFlags;
2430 }
2431
2432 // FIXME: Remove the document argument. It is almost always the same as
2433 // contextDocument(), with the exception of a few tests that pass a
2434 // different document, and could just make the call through another Internals
2435 // instance instead.
2436 ExceptionOr<String> Internals::layerTreeAsText(Document& document, unsigned short flags) const
2437 {
2438     if (!document.frame())
2439         return Exception { InvalidAccessError };
2440
2441     document.updateLayoutIgnorePendingStylesheets();
2442     return document.frame()->layerTreeAsText(toLayerTreeFlags(flags));
2443 }
2444
2445 ExceptionOr<uint64_t> Internals::layerIDForElement(Element& element)
2446 {
2447     Document* document = contextDocument();
2448     if (!document || !document->frame())
2449         return Exception { InvalidAccessError };
2450
2451     element.document().updateLayoutIgnorePendingStylesheets();
2452
2453     if (!element.renderer() || !element.renderer()->hasLayer())
2454         return Exception { NotFoundError };
2455
2456     auto& layerModelObject = downcast<RenderLayerModelObject>(*element.renderer());
2457     if (!layerModelObject.layer()->isComposited())
2458         return Exception { NotFoundError };
2459
2460     auto* backing = layerModelObject.layer()->backing();
2461     return backing->graphicsLayer()->primaryLayerID();
2462 }
2463
2464 ExceptionOr<String> Internals::repaintRectsAsText() const
2465 {
2466     Document* document = contextDocument();
2467     if (!document || !document->frame())
2468         return Exception { InvalidAccessError };
2469
2470     return document->frame()->trackedRepaintRectsAsText();
2471 }
2472
2473 ExceptionOr<String> Internals::scrollingStateTreeAsText() const
2474 {
2475     Document* document = contextDocument();
2476     if (!document || !document->frame())
2477         return Exception { InvalidAccessError };
2478
2479     Page* page = document->page();
2480     if (!page)
2481         return String();
2482
2483     return page->scrollingStateTreeAsText();
2484 }
2485
2486 ExceptionOr<String> Internals::mainThreadScrollingReasons() const
2487 {
2488     Document* document = contextDocument();
2489     if (!document || !document->frame())
2490         return Exception { InvalidAccessError };
2491
2492     Page* page = document->page();
2493     if (!page)
2494         return String();
2495
2496     return page->synchronousScrollingReasonsAsText();
2497 }
2498
2499 ExceptionOr<Ref<DOMRectList>> Internals::nonFastScrollableRects() const
2500 {
2501     Document* document = contextDocument();
2502     if (!document || !document->frame())
2503         return Exception { InvalidAccessError };
2504
2505     Page* page = document->page();
2506     if (!page)
2507         return DOMRectList::create();
2508
2509     return page->nonFastScrollableRects();
2510 }
2511
2512 ExceptionOr<void> Internals::setElementUsesDisplayListDrawing(Element& element, bool usesDisplayListDrawing)
2513 {
2514     Document* document = contextDocument();
2515     if (!document || !document->renderView())
2516         return Exception { InvalidAccessError };
2517
2518     element.document().updateLayoutIgnorePendingStylesheets();
2519
2520     if (!element.renderer())
2521         return Exception { InvalidAccessError };
2522
2523     if (is<HTMLCanvasElement>(element)) {
2524         downcast<HTMLCanvasElement>(element).setUsesDisplayListDrawing(usesDisplayListDrawing);
2525         return { };
2526     }
2527
2528     if (!element.renderer()->hasLayer())
2529         return Exception { InvalidAccessError };
2530
2531     RenderLayer* layer = downcast<RenderLayerModelObject>(element.renderer())->layer();
2532     if (!layer->isComposited())
2533         return Exception { InvalidAccessError };
2534
2535     layer->backing()->setUsesDisplayListDrawing(usesDisplayListDrawing);
2536     return { };
2537 }
2538
2539 ExceptionOr<void> Internals::setElementTracksDisplayListReplay(Element& element, bool isTrackingReplay)
2540 {
2541     Document* document = contextDocument();
2542     if (!document || !document->renderView())
2543         return Exception { InvalidAccessError };
2544
2545     element.document().updateLayoutIgnorePendingStylesheets();
2546
2547     if (!element.renderer())
2548         return Exception { InvalidAccessError };
2549
2550     if (is<HTMLCanvasElement>(element)) {
2551         downcast<HTMLCanvasElement>(element).setTracksDisplayListReplay(isTrackingReplay);
2552         return { };
2553     }
2554
2555     if (!element.renderer()->hasLayer())
2556         return Exception { InvalidAccessError };
2557
2558     RenderLayer* layer = downcast<RenderLayerModelObject>(element.renderer())->layer();
2559     if (!layer->isComposited())
2560         return Exception { InvalidAccessError };
2561
2562     layer->backing()->setIsTrackingDisplayListReplay(isTrackingReplay);
2563     return { };
2564 }
2565
2566 ExceptionOr<String> Internals::displayListForElement(Element& element, unsigned short flags)
2567 {
2568     Document* document = contextDocument();
2569     if (!document || !document->renderView())
2570         return Exception { InvalidAccessError };
2571
2572     element.document().updateLayoutIgnorePendingStylesheets();
2573
2574     if (!element.renderer())
2575         return Exception { InvalidAccessError };
2576
2577     DisplayList::AsTextFlags displayListFlags = 0;
2578     if (flags & DISPLAY_LIST_INCLUDES_PLATFORM_OPERATIONS)
2579         displayListFlags |= DisplayList::AsTextFlag::IncludesPlatformOperations;
2580
2581     if (is<HTMLCanvasElement>(element))
2582         return downcast<HTMLCanvasElement>(element).displayListAsText(displayListFlags);
2583
2584     if (!element.renderer()->hasLayer())
2585         return Exception { InvalidAccessError };
2586
2587     RenderLayer* layer = downcast<RenderLayerModelObject>(element.renderer())->layer();
2588     if (!layer->isComposited())
2589         return Exception { InvalidAccessError };
2590
2591     return layer->backing()->displayListAsText(displayListFlags);
2592 }
2593
2594 ExceptionOr<String> Internals::replayDisplayListForElement(Element& element, unsigned short flags)
2595 {
2596     Document* document = contextDocument();
2597     if (!document || !document->renderView())
2598         return Exception { InvalidAccessError };
2599
2600     element.document().updateLayoutIgnorePendingStylesheets();
2601
2602     if (!element.renderer())
2603         return Exception { InvalidAccessError };
2604
2605     DisplayList::AsTextFlags displayListFlags = 0;
2606     if (flags & DISPLAY_LIST_INCLUDES_PLATFORM_OPERATIONS)
2607         displayListFlags |= DisplayList::AsTextFlag::IncludesPlatformOperations;
2608
2609     if (is<HTMLCanvasElement>(element))
2610         return downcast<HTMLCanvasElement>(element).replayDisplayListAsText(displayListFlags);
2611
2612     if (!element.renderer()->hasLayer())
2613         return Exception { InvalidAccessError };
2614
2615     RenderLayer* layer = downcast<RenderLayerModelObject>(element.renderer())->layer();
2616     if (!layer->isComposited())
2617         return Exception { InvalidAccessError };
2618
2619     return layer->backing()->replayDisplayListAsText(displayListFlags);
2620 }
2621
2622 ExceptionOr<void> Internals::garbageCollectDocumentResources() const
2623 {
2624     Document* document = contextDocument();
2625     if (!document)
2626         return Exception { InvalidAccessError };
2627     document->cachedResourceLoader().garbageCollectDocumentResources();
2628     return { };
2629 }
2630
2631 bool Internals::isUnderMemoryPressure()
2632 {
2633     return MemoryPressureHandler::singleton().isUnderMemoryPressure();
2634 }
2635
2636 void Internals::beginSimulatedMemoryPressure()
2637 {
2638     MemoryPressureHandler::singleton().beginSimulatedMemoryPressure();
2639 }
2640
2641 void Internals::endSimulatedMemoryPressure()
2642 {
2643     MemoryPressureHandler::singleton().endSimulatedMemoryPressure();
2644 }
2645
2646 ExceptionOr<void> Internals::insertAuthorCSS(const String& css) const
2647 {
2648     Document* document = contextDocument();
2649     if (!document)
2650         return Exception { InvalidAccessError };
2651
2652     auto parsedSheet = StyleSheetContents::create(*document);
2653     parsedSheet.get().setIsUserStyleSheet(false);
2654     parsedSheet.get().parseString(css);
2655     document->extensionStyleSheets().addAuthorStyleSheetForTesting(WTFMove(parsedSheet));
2656     return { };
2657 }
2658
2659 ExceptionOr<void> Internals::insertUserCSS(const String& css) const
2660 {
2661     Document* document = contextDocument();
2662     if (!document)
2663         return Exception { InvalidAccessError };
2664
2665     auto parsedSheet = StyleSheetContents::create(*document);
2666     parsedSheet.get().setIsUserStyleSheet(true);
2667     parsedSheet.get().parseString(css);
2668     document->extensionStyleSheets().addUserStyleSheet(WTFMove(parsedSheet));
2669     return { };
2670 }
2671
2672 String Internals::counterValue(Element& element)
2673 {
2674     return counterValueForElement(&element);
2675 }
2676
2677 int Internals::pageNumber(Element& element, float pageWidth, float pageHeight)
2678 {
2679     return PrintContext::pageNumberForElement(&element, { pageWidth, pageHeight });
2680 }
2681
2682 Vector<String> Internals::shortcutIconURLs() const
2683 {
2684     if (!frame())
2685         return { };
2686     
2687     auto* documentLoader = frame()->loader().documentLoader();
2688     if (!documentLoader)
2689         return { };
2690
2691     Vector<String> result;
2692     for (auto& linkIcon : documentLoader->linkIcons())
2693         result.append(linkIcon.url.string());
2694     
2695     return result;
2696 }
2697
2698 int Internals::numberOfPages(float pageWidth, float pageHeight)
2699 {
2700     if (!frame())
2701         return -1;
2702
2703     return PrintContext::numberOfPages(*frame(), FloatSize(pageWidth, pageHeight));
2704 }
2705
2706 ExceptionOr<String> Internals::pageProperty(const String& propertyName, int pageNumber) const
2707 {
2708     if (!frame())
2709         return Exception { InvalidAccessError };
2710
2711     return PrintContext::pageProperty(frame(), propertyName.utf8().data(), pageNumber);
2712 }
2713
2714 ExceptionOr<String> Internals::pageSizeAndMarginsInPixels(int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft) const
2715 {
2716     if (!frame())
2717         return Exception { InvalidAccessError };
2718
2719     return PrintContext::pageSizeAndMarginsInPixels(frame(), pageNumber, width, height, marginTop, marginRight, marginBottom, marginLeft);
2720 }
2721
2722 ExceptionOr<float> Internals::pageScaleFactor() const
2723 {
2724     Document* document = contextDocument();
2725     if (!document || !document->page())
2726         return Exception { InvalidAccessError };
2727
2728     return document->page()->pageScaleFactor();
2729 }
2730
2731 ExceptionOr<void> Internals::setPageScaleFactor(float scaleFactor, int x, int y)
2732 {
2733     Document* document = contextDocument();
2734     if (!document || !document->page())
2735         return Exception { InvalidAccessError };
2736
2737     document->page()->setPageScaleFactor(scaleFactor, IntPoint(x, y));
2738     return { };
2739 }
2740
2741 ExceptionOr<void> Internals::setPageZoomFactor(float zoomFactor)
2742 {
2743     Document* document = contextDocument();
2744     if (!document || !document->frame())
2745         return Exception { InvalidAccessError };
2746
2747     document->frame()->setPageZoomFactor(zoomFactor);
2748     return { };
2749 }
2750
2751 ExceptionOr<void> Internals::setTextZoomFactor(float zoomFactor)
2752 {
2753     Document* document = contextDocument();
2754     if (!document || !document->frame())
2755         return Exception { InvalidAccessError };
2756
2757     document->frame()->setTextZoomFactor(zoomFactor);
2758     return { };
2759 }
2760
2761 ExceptionOr<void> Internals::setUseFixedLayout(bool useFixedLayout)
2762 {
2763     Document* document = contextDocument();
2764     if (!document || !document->view())
2765         return Exception { InvalidAccessError };
2766
2767     document->view()->setUseFixedLayout(useFixedLayout);
2768     return { };
2769 }
2770
2771 ExceptionOr<void> Internals::setFixedLayoutSize(int width, int height)
2772 {
2773     Document* document = contextDocument();
2774     if (!document || !document->view())
2775         return Exception { InvalidAccessError };
2776
2777     document->view()->setFixedLayoutSize(IntSize(width, height));
2778     return { };
2779 }
2780
2781 ExceptionOr<void> Internals::setViewExposedRect(float x, float y, float width, float height)
2782 {
2783     Document* document = contextDocument();
2784     if (!document || !document->view())
2785         return Exception { InvalidAccessError };
2786
2787     document->view()->setViewExposedRect(FloatRect(x, y, width, height));
2788     return { };
2789 }
2790
2791 void Internals::setPrinting(int width, int height)
2792 {
2793     printContextForTesting() = std::make_unique<PrintContext>(frame());
2794     printContextForTesting()->begin(width, height);
2795 }
2796
2797 void Internals::setHeaderHeight(float height)
2798 {
2799     Document* document = contextDocument();
2800     if (!document || !document->view())
2801         return;
2802
2803     document->view()->setHeaderHeight(height);
2804 }
2805
2806 void Internals::setFooterHeight(float height)
2807 {
2808     Document* document = contextDocument();
2809     if (!document || !document->view())
2810         return;
2811
2812     document->view()->setFooterHeight(height);
2813 }
2814
2815 void Internals::setTopContentInset(float contentInset)
2816 {
2817     Document* document = contextDocument();
2818     if (!document || !document->page())
2819         return;
2820
2821     document->page()->setTopContentInset(contentInset);
2822 }
2823
2824 #if ENABLE(FULLSCREEN_API)
2825
2826 void Internals::webkitWillEnterFullScreenForElement(Element& element)
2827 {
2828     Document* document = contextDocument();
2829     if (!document)
2830         return;
2831     document->webkitWillEnterFullScreenForElement(&element);
2832 }
2833
2834 void Internals::webkitDidEnterFullScreenForElement(Element& element)
2835 {
2836     Document* document = contextDocument();
2837     if (!document)
2838         return;
2839     document->webkitDidEnterFullScreenForElement(&element);
2840 }
2841
2842 void Internals::webkitWillExitFullScreenForElement(Element& element)
2843 {
2844     Document* document = contextDocument();
2845     if (!document)
2846         return;
2847     document->webkitWillExitFullScreenForElement(&element);
2848 }
2849
2850 void Internals::webkitDidExitFullScreenForElement(Element& element)
2851 {
2852     Document* document = contextDocument();
2853     if (!document)
2854         return;
2855     document->webkitDidExitFullScreenForElement(&element);
2856 }
2857
2858 bool Internals::isAnimatingFullScreen() const
2859 {
2860     Document* document = contextDocument();
2861     if (!document)
2862         return false;
2863     return document->isAnimatingFullScreen();
2864 }
2865
2866 #endif
2867
2868 void Internals::setFullscreenInsets(FullscreenInsets insets)
2869 {
2870     Page* page = contextDocument()->frame()->page();
2871     ASSERT(page);
2872
2873     page->setFullscreenInsets(FloatBoxExtent(insets.top, insets.right, insets.bottom, insets.left));
2874 }
2875
2876 void Internals::setFullscreenAutoHideDuration(double duration)
2877 {
2878     Page* page = contextDocument()->frame()->page();
2879     ASSERT(page);
2880
2881     page->setFullscreenAutoHideDuration(Seconds(duration));
2882 }
2883
2884 void Internals::setFullscreenControlsHidden(bool hidden)
2885 {
2886     Page* page = contextDocument()->frame()->page();
2887     ASSERT(page);
2888
2889     page->setFullscreenControlsHidden(hidden);
2890 }
2891
2892 void Internals::setApplicationCacheOriginQuota(unsigned long long quota)
2893 {
2894     Document* document = contextDocument();
2895     if (!document || !document->page())
2896         return;
2897     document->page()->applicationCacheStorage().storeUpdatedQuotaForOrigin(&document->securityOrigin(), quota);
2898 }
2899
2900 void Internals::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme)
2901 {
2902     SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
2903 }
2904
2905 void Internals::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(const String& scheme)
2906 {
2907     SchemeRegistry::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(scheme);
2908 }
2909
2910 void Internals::registerDefaultPortForProtocol(unsigned short port, const String& protocol)
2911 {
2912     registerDefaultPortForProtocolForTesting(port, protocol);
2913 }
2914
2915 Ref<MallocStatistics> Internals::mallocStatistics() const
2916 {
2917     return MallocStatistics::create();
2918 }
2919
2920 Ref<TypeConversions> Internals::typeConversions() const
2921 {
2922     return TypeConversions::create();
2923 }
2924
2925 Ref<MemoryInfo> Internals::memoryInfo() const
2926 {
2927     return MemoryInfo::create();
2928 }
2929
2930 Vector<String> Internals::getReferencedFilePaths() const
2931 {
2932     frame()->loader().history().saveDocumentAndScrollState();
2933     return FormController::referencedFilePaths(frame()->loader().history().currentItem()->documentState());
2934 }
2935
2936 ExceptionOr<void> Internals::startTrackingRepaints()
2937 {
2938     Document* document = contextDocument();
2939     if (!document || !document->view())
2940         return Exception { InvalidAccessError };
2941
2942     document->view()->setTracksRepaints(true);
2943     return { };
2944 }
2945
2946 ExceptionOr<void> Internals::stopTrackingRepaints()
2947 {
2948     Document* document = contextDocument();
2949     if (!document || !document->view())
2950         return Exception { InvalidAccessError };
2951
2952     document->view()->setTracksRepaints(false);
2953     return { };
2954 }
2955
2956 ExceptionOr<void> Internals::startTrackingLayerFlushes()
2957 {
2958     Document* document = contextDocument();
2959     if (!document || !document->renderView())
2960         return Exception { InvalidAccessError };
2961
2962     document->renderView()->compositor().startTrackingLayerFlushes();
2963     return { };
2964 }
2965
2966 ExceptionOr<unsigned> Internals::layerFlushCount()
2967 {
2968     Document* document = contextDocument();
2969     if (!document || !document->renderView())
2970         return Exception { InvalidAccessError };
2971
2972     return document->renderView()->compositor().layerFlushCount();
2973 }
2974
2975 ExceptionOr<void> Internals::startTrackingStyleRecalcs()
2976 {
2977     Document* document = contextDocument();
2978     if (!document)
2979         return Exception { InvalidAccessError };
2980
2981     document->startTrackingStyleRecalcs();
2982     return { };
2983 }
2984
2985 ExceptionOr<unsigned> Internals::styleRecalcCount()
2986 {
2987     Document* document = contextDocument();
2988     if (!document)
2989         return Exception { InvalidAccessError };
2990
2991     return document->styleRecalcCount();
2992 }
2993
2994 unsigned Internals::lastStyleUpdateSize() const
2995 {
2996     Document* document = contextDocument();
2997     if (!document)
2998         return 0;
2999     return document->lastStyleUpdateSizeForTesting();
3000 }
3001
3002 ExceptionOr<void> Internals::startTrackingCompositingUpdates()
3003 {
3004     Document* document = contextDocument();
3005     if (!document || !document->renderView())
3006         return Exception { InvalidAccessError };
3007
3008     document->renderView()->compositor().startTrackingCompositingUpdates();
3009     return { };
3010 }
3011
3012 ExceptionOr<unsigned> Internals::compositingUpdateCount()
3013 {
3014     Document* document = contextDocument();
3015     if (!document || !document->renderView())
3016         return Exception { InvalidAccessError };
3017
3018     return document->renderView()->compositor().compositingUpdateCount();
3019 }
3020
3021 ExceptionOr<void> Internals::setCompositingPolicyOverride(std::optional<CompositingPolicy> policyOverride)
3022 {
3023     Document* document = contextDocument();
3024     if (!document)
3025         return Exception { InvalidAccessError };
3026
3027     if (!policyOverride) {
3028         document->page()->setCompositingPolicyOverride(std::nullopt);
3029         return { };
3030     }
3031
3032     switch (policyOverride.value()) {
3033     case Internals::CompositingPolicy::Normal:
3034         document->page()->setCompositingPolicyOverride(WebCore::CompositingPolicy::Normal);
3035         break;
3036     case Internals::CompositingPolicy::Conservative:
3037         document->page()->setCompositingPolicyOverride(WebCore::CompositingPolicy::Conservative);
3038         break;
3039     }
3040     
3041     return { };
3042 }
3043
3044 ExceptionOr<std::optional<Internals::CompositingPolicy>> Internals::compositingPolicyOverride() const
3045 {
3046     Document* document = contextDocument();
3047     if (!document)
3048         return Exception { InvalidAccessError };
3049
3050     auto policyOverride = document->page()->compositingPolicyOverride();
3051     if (!policyOverride)
3052         return { std::nullopt };
3053
3054     switch (policyOverride.value()) {
3055     case WebCore::CompositingPolicy::Normal:
3056         return { Internals::CompositingPolicy::Normal };
3057     case WebCore::CompositingPolicy::Conservative:
3058         return { Internals::CompositingPolicy::Conservative };
3059     }
3060
3061     return { Internals::CompositingPolicy::Normal };
3062 }
3063
3064 ExceptionOr<void> Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(Node* node)
3065 {
3066     Document* document;
3067     if (!node)
3068         document = contextDocument();
3069     else if (is<Document>(*node))
3070         document = downcast<Document>(node);
3071     else if (is<HTMLIFrameElement>(*node))
3072         document = downcast<HTMLIFrameElement>(*node).contentDocument();
3073     else
3074         return Exception { TypeError };
3075
3076     document->updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasks::Synchronously);
3077     return { };
3078 }
3079
3080 unsigned Internals::layoutCount() const
3081 {
3082     Document* document = contextDocument();
3083     if (!document || !document->view())
3084         return 0;
3085     return document->view()->layoutContext().layoutCount();
3086 }
3087
3088 #if !PLATFORM(IOS)
3089 static const char* cursorTypeToString(Cursor::Type cursorType)
3090 {
3091     switch (cursorType) {
3092     case Cursor::Pointer: return "Pointer";
3093     case Cursor::Cross: return "Cross";
3094     case Cursor::Hand: return "Hand";
3095     case Cursor::IBeam: return "IBeam";
3096     case Cursor::Wait: return "Wait";
3097     case Cursor::Help: return "Help";
3098     case Cursor::EastResize: return "EastResize";
3099     case Cursor::NorthResize: return "NorthResize";
3100     case Cursor::NorthEastResize: return "NorthEastResize";
3101     case Cursor::NorthWestResize: return "NorthWestResize";
3102     case Cursor::SouthResize: return "SouthResize";
3103     case Cursor::SouthEastResize: return "SouthEastResize";
3104     case Cursor::SouthWestResize: return "SouthWestResize";
3105     case Cursor::WestResize: return "WestResize";
3106     case Cursor::NorthSouthResize: return "NorthSouthResize";
3107     case Cursor::EastWestResize: return "EastWestResize";
3108     case Cursor::NorthEastSouthWestResize: return "NorthEastSouthWestResize";
3109     case Cursor::NorthWestSouthEastResize: return "NorthWestSouthEastResize";
3110     case Cursor::ColumnResize: return "ColumnResize";
3111     case Cursor::RowResize: return "RowResize";
3112     case Cursor::MiddlePanning: return "MiddlePanning";
3113     case Cursor::EastPanning: return "EastPanning";
3114     case Cursor::NorthPanning: return "NorthPanning";
3115     case Cursor::NorthEastPanning: return "NorthEastPanning";
3116     case Cursor::NorthWestPanning: return "NorthWestPanning";
3117     case Cursor::SouthPanning: return "SouthPanning";
3118     case Cursor::SouthEastPanning: return "SouthEastPanning";
3119     case Cursor::SouthWestPanning: return "SouthWestPanning";
3120     case Cursor::WestPanning: return "WestPanning";
3121     case Cursor::Move: return "Move";
3122     case Cursor::VerticalText: return "VerticalText";
3123     case Cursor::Cell: return "Cell";
3124     case Cursor::ContextMenu: return "ContextMenu";
3125     case Cursor::Alias: return "Alias";
3126     case Cursor::Progress: return "Progress";
3127     case Cursor::NoDrop: return "NoDrop";
3128     case Cursor::Copy: return "Copy";
3129     case Cursor::None: return "None";
3130     case Cursor::NotAllowed: return "NotAllowed";
3131     case Cursor::ZoomIn: return "ZoomIn";
3132     case Cursor::ZoomOut: return "ZoomOut";
3133     case Cursor::Grab: return "Grab";
3134     case Cursor::Grabbing: return "Grabbing";
3135     case Cursor::Custom: return "Custom";
3136     }
3137
3138     ASSERT_NOT_REACHED();
3139     return "UNKNOWN";
3140 }
3141 #endif
3142
3143 ExceptionOr<String> Internals::getCurrentCursorInfo()
3144 {
3145     Document* document = contextDocument();
3146     if (!document || !document->frame())
3147         return Exception { InvalidAccessError };
3148
3149 #if !PLATFORM(IOS)
3150     Cursor cursor = document->frame()->eventHandler().currentMouseCursor();
3151
3152     StringBuilder result;
3153     result.appendLiteral("type=");
3154     result.append(cursorTypeToString(cursor.type()));
3155     result.appendLiteral(" hotSpot=");
3156     result.appendNumber(cursor.hotSpot().x());
3157     result.append(',');
3158     result.appendNumber(cursor.hotSpot().y());
3159     if (cursor.image()) {
3160         FloatSize size = cursor.image()->size();
3161         result.appendLiteral(" image=");
3162         result.appendNumber(size.width());
3163         result.append('x');
3164         result.appendNumber(size.height());
3165     }
3166 #if ENABLE(MOUSE_CURSOR_SCALE)
3167     if (cursor.imageScaleFactor() != 1) {
3168         result.appendLiteral(" scale=");
3169         NumberToStringBuffer buffer;
3170         result.append(numberToFixedPrecisionString(cursor.imageScaleFactor(), 8, buffer, true));
3171     }
3172 #endif
3173     return result.toString();
3174 #else
3175     return String { "FAIL: Cursor details not available on this platform." };
3176 #endif
3177 }
3178
3179 Ref<ArrayBuffer> Internals::serializeObject(const RefPtr<SerializedScriptValue>& value) const
3180 {
3181     auto& bytes = value->data();
3182     return ArrayBuffer::create(bytes.data(), bytes.size());
3183 }
3184
3185 Ref<SerializedScriptValue> Internals::deserializeBuffer(ArrayBuffer& buffer) const
3186 {
3187     Vector<uint8_t> bytes;
3188     bytes.append(static_cast<const uint8_t*>(buffer.data()), buffer.byteLength());
3189     return SerializedScriptValue::adopt(WTFMove(bytes));
3190 }
3191
3192 bool Internals::isFromCurrentWorld(JSC::JSValue value) const
3193 {
3194     return isWorldCompatible(*contextDocument()->vm().topCallFrame, value);
3195 }
3196
3197 void Internals::setUsesOverlayScrollbars(bool enabled)
3198 {
3199     WebCore::DeprecatedGlobalSettings::setUsesOverlayScrollbars(enabled);
3200 }
3201
3202 void Internals::setUsesMockScrollAnimator(bool enabled)
3203 {
3204     WebCore::DeprecatedGlobalSettings::setUsesMockScrollAnimator(enabled);
3205 }
3206
3207 void Internals::forceReload(bool endToEnd)
3208 {
3209     OptionSet<ReloadOption> reloadOptions;
3210     if (endToEnd)
3211         reloadOptions.add(ReloadOption::FromOrigin);
3212
3213     frame()->loader().reload(reloadOptions);
3214 }
3215
3216 void Internals::reloadExpiredOnly()
3217 {
3218     frame()->loader().reload(ReloadOption::ExpiredOnly);
3219 }
3220
3221 void Internals::enableAutoSizeMode(bool enabled, int minimumWidth, int minimumHeight, int maximumWidth, int maximumHeight)
3222 {
3223     auto* document = contextDocument();
3224     if (!document || !document->view())
3225         return;
3226     document->view()->enableAutoSizeMode(enabled, IntSize(minimumWidth, minimumHeight), IntSize(maximumWidth, maximumHeight));
3227 }
3228
3229 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
3230
3231 void Internals::initializeMockCDM()
3232 {
3233     LegacyCDM::registerCDMFactory([] (LegacyCDM* cdm) { return std::make_unique<LegacyMockCDM>(cdm); },
3234         LegacyMockCDM::supportsKeySystem, LegacyMockCDM::supportsKeySystemAndMimeType);
3235 }
3236
3237 #endif
3238
3239 #if ENABLE(ENCRYPTED_MEDIA)
3240
3241 Ref<MockCDMFactory> Internals::registerMockCDM()
3242 {
3243     return MockCDMFactory::create();
3244 }
3245
3246 #endif
3247
3248 String Internals::markerTextForListItem(Element& element)
3249 {
3250     return WebCore::markerTextForListItem(&element);
3251 }
3252
3253 String Internals::toolTipFromElement(Element& element) const
3254 {
3255     HitTestResult result;
3256     result.setInnerNode(&element);
3257     TextDirection direction;
3258     return result.title(direction);
3259 }
3260
3261 String Internals::getImageSourceURL(Element& element)
3262 {
3263     return element.imageSourceURL();
3264 }
3265
3266 #if ENABLE(VIDEO)
3267
3268 Vector<String> Internals::mediaResponseSources(HTMLMediaElement& media)
3269 {
3270     auto* resourceLoader = media.lastMediaResourceLoaderForTesting();
3271     if (!resourceLoader)
3272         return { };
3273     Vector<String> result;
3274     auto responses = resourceLoader->responsesForTesting();
3275     for (auto& response : responses)
3276         result.append(responseSourceToString(response));
3277     return result;
3278 }
3279
3280 Vector<String> Internals::mediaResponseContentRanges(HTMLMediaElement& media)
3281 {
3282     auto* resourceLoader = media.lastMediaResourceLoaderForTesting();
3283     if (!resourceLoader)
3284         return { };
3285     Vector<String> result;
3286     auto responses = resourceLoader->responsesForTesting();
3287     for (auto& response : responses)
3288         result.append(response.httpHeaderField(HTTPHeaderName::ContentRange));
3289     return result;
3290 }
3291
3292 void Internals::simulateAudioInterruption(HTMLMediaElement& element)
3293 {
3294 #if USE(GSTREAMER)
3295     element.player()->simulateAudioInterruption();
3296 #else
3297     UNUSED_PARAM(element);
3298 #endif
3299 }
3300
3301 ExceptionOr<bool> Internals::mediaElementHasCharacteristic(HTMLMediaElement& element, const String& characteristic)
3302 {
3303     if (equalLettersIgnoringASCIICase(characteristic, "audible"))
3304         return element.hasAudio();
3305     if (equalLettersIgnoringASCIICase(characteristic, "visual"))
3306         return element.hasVideo();
3307     if (equalLettersIgnoringASCIICase(characteristic, "legible"))
3308         return element.hasClosedCaptions();
3309
3310     return Exception { SyntaxError };
3311 }
3312
3313 void Internals::beginSimulatedHDCPError(HTMLMediaElement& element)
3314 {
3315     if (auto player = element.player())
3316         player->beginSimulatedHDCPError();
3317 }
3318
3319 void Internals::endSimulatedHDCPError(HTMLMediaElement& element)
3320 {
3321     if (auto player = element.player())
3322         player->endSimulatedHDCPError();
3323 }
3324
3325 bool Internals::elementShouldBufferData(HTMLMediaElement& element)
3326 {
3327     return element.shouldBufferData();
3328 }
3329
3330 #endif
3331
3332 bool Internals::isSelectPopupVisible(HTMLSelectElement& element)
3333 {
3334     element.document().updateLayoutIgnorePendingStylesheets();
3335
3336     auto* renderer = element.renderer();
3337     if (!is<RenderMenuList>(renderer))
3338         return false;
3339
3340 #if !PLATFORM(IOS)
3341     return downcast<RenderMenuList>(*renderer).popupIsVisible();
3342 #else
3343     return false;
3344 #endif
3345 }
3346
3347 ExceptionOr<String> Internals::captionsStyleSheetOverride()
3348 {
3349     Document* document = contextDocument();
3350     if (!document || !document->page())
3351         return Exception { InvalidAccessError };
3352
3353 #if ENABLE(VIDEO_TRACK)
3354     return document->page()->group().captionPreferences().captionsStyleSheetOverride();
3355 #else
3356     return String { emptyString() };
3357 #endif
3358 }
3359
3360 ExceptionOr<void> Internals::setCaptionsStyleSheetOverride(const String& override)
3361 {
3362     Document* document = contextDocument();
3363     if (!document || !document->page())
3364         return Exception { InvalidAccessError };
3365
3366 #if ENABLE(VIDEO_TRACK)
3367     document->page()->group().captionPreferences().setCaptionsStyleSheetOverride(override);
3368 #else
3369     UNUSED_PARAM(override);
3370 #endif
3371     return { };
3372 }
3373
3374 ExceptionOr<void> Internals::setPrimaryAudioTrackLanguageOverride(const String& language)
3375 {
3376     Document* document = contextDocument();
3377     if (!document || !document->page())
3378         return Exception { InvalidAccessError };
3379
3380 #if ENABLE(VIDEO_TRACK)
3381     document->page()->group().captionPreferences().setPrimaryAudioTrackLanguageOverride(language);
3382 #else
3383     UNUSED_PARAM(language);
3384 #endif
3385     return { };
3386 }
3387
3388 ExceptionOr<void> Internals::setCaptionDisplayMode(const String& mode)
3389 {
3390     Document* document = contextDocument();
3391     if (!document || !document->page())
3392         return Exception { InvalidAccessError };
3393
3394 #if ENABLE(VIDEO_TRACK)
3395     auto& captionPreferences = document->page()->group().captionPreferences();
3396
3397     if (equalLettersIgnoringASCIICase(mode, "automatic"))
3398         captionPreferences.setCaptionDisplayMode(CaptionUserPreferences::Automatic);
3399     else if (equalLettersIgnoringASCIICase(mode, "forcedonly"))
3400         captionPreferences.setCaptionDisplayMode(CaptionUserPreferences::ForcedOnly);
3401     else if (equalLettersIgnoringASCIICase(mode, "alwayson"))
3402         captionPreferences.setCaptionDisplayMode(CaptionUserPreferences::AlwaysOn);
3403     else if (equalLettersIgnoringASCIICase(mode, "manual"))
3404         captionPreferences.setCaptionDisplayMode(CaptionUserPreferences::Manual);
3405     else
3406         return Exception { SyntaxError };
3407 #else
3408     UNUSED_PARAM(mode);
3409 #endif
3410     return { };
3411 }
3412
3413 #if ENABLE(VIDEO)
3414
3415 Ref<TimeRanges> Internals::createTimeRanges(Float32Array& startTimes, Float32Array& endTimes)
3416 {
3417     ASSERT(startTimes.length() == endTimes.length());
3418     Ref<TimeRanges> ranges = TimeRanges::create();
3419
3420     unsigned count = std::min(startTimes.length(), endTimes.length());
3421     for (unsigned i = 0; i < count; ++i)
3422         ranges->add(startTimes.item(i), endTimes.item(i));
3423     return ranges;
3424 }
3425
3426 double Internals::closestTimeToTimeRanges(double time, TimeRanges& ranges)
3427 {
3428     return ranges.nearest(time);
3429 }
3430
3431 #endif
3432
3433 ExceptionOr<Ref<DOMRect>> Internals::selectionBounds()
3434 {
3435     Document* document = contextDocument();
3436     if (!document || !document->frame())
3437         return Exception { InvalidAccessError };
3438
3439     return DOMRect::create(document->frame()->selection().selectionBounds());
3440 }
3441
3442 ExceptionOr<bool> Internals::isPluginUnavailabilityIndicatorObscured(Element& element)
3443 {
3444     if (!is<HTMLPlugInElement>(element))
3445         return Exception { InvalidAccessError };
3446
3447     return downcast<HTMLPlugInElement>(element).isReplacementObscured();
3448 }
3449
3450 ExceptionOr<String> Internals::unavailablePluginReplacementText(Element& element)
3451 {
3452     if (!is<HTMLPlugInElement>(element))
3453         return Exception { InvalidAccessError };
3454
3455     auto* renderer = element.renderer();
3456     if (!is<RenderEmbeddedObject>(renderer))
3457         return String { };
3458
3459     return String { downcast<RenderEmbeddedObject>(*renderer).pluginReplacementTextIfUnavailable() };
3460 }
3461
3462 bool Internals::isPluginSnapshotted(Element& element)
3463 {
3464     return is<HTMLPlugInElement>(element) && downcast<HTMLPlugInElement>(element).displayState() <= HTMLPlugInElement::DisplayingSnapshot;
3465 }
3466
3467 #if ENABLE(MEDIA_SOURCE)
3468
3469 void Internals::initializeMockMediaSource()
3470 {
3471 #if USE(AVFOUNDATION)
3472     WebCore::DeprecatedGlobalSettings::setAVFoundationEnabled(false);
3473 #endif
3474 #if USE(GSTREAMER)
3475     WebCore::DeprecatedGlobalSettings::setGStreamerEnabled(false);
3476 #endif
3477     MediaPlayerFactorySupport::callRegisterMediaEngine(MockMediaPlayerMediaSource::registerMediaEngine);
3478 }
3479
3480 Vector<String> Internals::bufferedSamplesForTrackID(SourceBuffer& buffer, const AtomicString& trackID)
3481 {
3482     return buffer.bufferedSamplesForTrackID(trackID);
3483 }
3484
3485 Vector<String> Internals::enqueuedSamplesForTrackID(SourceBuffer& buffer, const AtomicString& trackID)
3486 {
3487     return buffer.enqueuedSamplesForTrackID(trackID);
3488 }
3489
3490 void Internals::setShouldGenerateTimestamps(SourceBuffer& buffer, bool flag)
3491 {
3492     buffer.setShouldGenerateTimestamps(flag);
3493 }
3494
3495 #endif
3496
3497 void Internals::enableMockMediaCapabilities()
3498 {
3499     MediaEngineConfigurationFactory::enableMock();
3500 }
3501
3502 #if ENABLE(VIDEO)
3503
3504 ExceptionOr<void> Internals::beginMediaSessionInterruption(const String& interruptionString)
3505 {
3506     PlatformMediaSession::InterruptionType interruption = PlatformMediaSession::SystemInterruption;
3507
3508     if (equalLettersIgnoringASCIICase(interruptionString, "system"))
3509         interruption = PlatformMediaSession::SystemInterruption;
3510     else if (equalLettersIgnoringASCIICase(interruptionString, "systemsleep"))
3511         interruption = PlatformMediaSession::SystemSleep;
3512     else if (equalLettersIgnoringASCIICase(interruptionString, "enteringbackground"))
3513         interruption = PlatformMediaSession::EnteringBackground;
3514     else if (equalLettersIgnoringASCIICase(interruptionString, "suspendedunderlock"))
3515         interruption = PlatformMediaSession::SuspendedUnderLock;
3516     else
3517         return Exception { InvalidAccessError };
3518
3519     PlatformMediaSessionManager::sharedManager().beginInterruption(interruption);
3520     return { };
3521 }
3522
3523 void Internals::endMediaSessionInterruption(const String& flagsString)
3524 {
3525     PlatformMediaSession::EndInterruptionFlags flags = PlatformMediaSession::NoFlags;
3526
3527     if (equalLettersIgnoringASCIICase(flagsString, "mayresumeplaying"))
3528         flags = PlatformMediaSession::MayResumePlaying;
3529
3530     PlatformMediaSessionManager::sharedManager().endInterruption(flags);
3531 }
3532
3533 void Internals::applicationWillBecomeInactive()
3534 {
3535     PlatformMediaSessionManager::sharedManager().applicationWillBecomeInactive();
3536 }
3537
3538 void Internals::applicationDidBecomeActive()
3539 {
3540     PlatformMediaSessionManager::sharedManager().applicationDidBecomeActive();
3541 }
3542
3543 void Internals::applicationWillEnterForeground(bool suspendedUnderLock) const
3544 {
3545     PlatformMediaSessionManager::sharedManager().applicationWillEnterForeground(suspendedUnderLock);
3546 }
3547
3548 void Internals::applicationDidEnterBackground(bool suspendedUnderLock) const
3549 {
3550     PlatformMediaSessionManager::sharedManager().applicationDidEnterBackground(suspendedUnderLock);
3551 }
3552
3553 static PlatformMediaSession::MediaType mediaTypeFromString(const String& mediaTypeString)
3554 {
3555     if (equalLettersIgnoringASCIICase(mediaTypeString, "video"))
3556         return PlatformMediaSession::Video;
3557     if (equalLettersIgnoringASCIICase(mediaTypeString, "audio"))
3558         return PlatformMediaSession::Audio;
3559     if (equalLettersIgnoringASCIICase(mediaTypeString, "videoaudio"))
3560         return PlatformMediaSession::VideoAudio;
3561     if (equalLettersIgnoringASCIICase(mediaTypeString, "webaudio"))
3562         return PlatformMediaSession::WebAudio;
3563     if (equalLettersIgnoringASCIICase(mediaTypeString, "mediastreamcapturingaudio"))
3564         return PlatformMediaSession::MediaStreamCapturingAudio;
3565
3566     return PlatformMediaSession::None;
3567 }
3568
3569 ExceptionOr<void> Internals::setMediaSessionRestrictions(const String& mediaTypeString, StringView restrictionsString)
3570 {
3571     PlatformMediaSession::MediaType mediaType = mediaTypeFromString(mediaTypeString);
3572     if (mediaType == PlatformMediaSession::None)
3573         return Exception { InvalidAccessError };
3574
3575     PlatformMediaSessionManager::SessionRestrictions restrictions = PlatformMediaSessionManager::sharedManager().restrictions(mediaType);
3576     PlatformMediaSessionManager::sharedManager().removeRestriction(mediaType, restrictions);
3577
3578     restrictions = PlatformMediaSessionManager::NoRestrictions;
3579
3580     for (StringView restrictionString : restrictionsString.split(',')) {
3581         if (equalLettersIgnoringASCIICase(restrictionString, "concurrentplaybacknotpermitted"))
3582             restrictions |= PlatformMediaSessionManager::ConcurrentPlaybackNotPermitted;
3583         if (equalLettersIgnoringASCIICase(restrictionString, "backgroundprocessplaybackrestricted"))
3584             restrictions |= PlatformMediaSessionManager::BackgroundProcessPlaybackRestricted;
3585         if (equalLettersIgnoringASCIICase(restrictionString, "backgroundtabplaybackrestricted"))
3586             restrictions |= PlatformMediaSessionManager::BackgroundTabPlaybackRestricted;
3587         if (equalLettersIgnoringASCIICase(restrictionString, "interruptedplaybacknotpermitted"))
3588             restrictions |= PlatformMediaSessionManager::InterruptedPlaybackNotPermitted;
3589         if (equalLettersIgnoringASCIICase(restrictionString, "inactiveprocessplaybackrestricted"))
3590             restrictions |= PlatformMediaSessionManager::InactiveProcessPlaybackRestricted;
3591         if (equalLettersIgnoringASCIICase(restrictionString, "suspendedunderlockplaybackrestricted"))
3592             restrictions |= PlatformMediaSessionManager::SuspendedUnderLockPlaybackRestricted;
3593     }
3594     PlatformMediaSessionManager::sharedManager().addRestriction(mediaType, restrictions);
3595     return { };
3596 }
3597
3598 ExceptionOr<String> Internals::mediaSessionRestrictions(const String& mediaTypeString) const
3599 {
3600     PlatformMediaSession::MediaType mediaType = mediaTypeFromString(mediaTypeString);
3601     if (mediaType == PlatformMediaSession::None)
3602         return Exception { InvalidAccessError };
3603
3604     PlatformMediaSessionManager::SessionRestrictions restrictions = PlatformMediaSessionManager::sharedManager().restrictions(mediaType);
3605     if (restrictions == PlatformMediaSessionManager::NoRestrictions)
3606         return String();
3607
3608     StringBuilder builder;
3609     if (restrictions & PlatformMediaSessionManager::ConcurrentPlaybackNotPermitted)
3610         builder.append("concurrentplaybacknotpermitted");
3611     if (restrictions & PlatformMediaSessionManager::BackgroundProcessPlaybackRestricted) {
3612         if (!builder.isEmpty())
3613             builder.append(',');
3614         builder.append("backgroundprocessplaybackrestricted");
3615     }
3616     if (restrictions & PlatformMediaSessionManager::BackgroundTabPlaybackRestricted) {
3617         if (!builder.isEmpty())
3618             builder.append(',');
3619         builder.append("backgroundtabplaybackrestricted");
3620     }
3621     if (restrictions & PlatformMediaSessionManager::InterruptedPlaybackNotPermitted) {
3622         if (!builder.isEmpty())
3623             builder.append(',');
3624         builder.append("interruptedplaybacknotpermitted");
3625     }
3626     return builder.toString();
3627 }
3628
3629 void Internals::setMediaElementRestrictions(HTMLMediaElement& element, StringView restrictionsString)
3630 {
3631     MediaElementSession::BehaviorRestrictions restrictions = element.mediaSession().behaviorRestrictions();
3632     element.mediaSession().removeBehaviorRestriction(restrictions);
3633
3634     restrictions = MediaElementSession::NoRestrictions;
3635
3636     for (StringView restrictionString : restrictionsString.split(',')) {
3637         if (equalLettersIgnoringASCIICase(restrictionString, "norestrictions"))
3638             restrictions |= MediaElementSession::NoRestrictions;
3639         if (equalLettersIgnoringASCIICase(restrictionString, "requireusergestureforload"))
3640             restrictions |= MediaElementSession::RequireUserGestureForLoad;
3641         if (equalLettersIgnoringASCIICase(restrictionString, "requireusergestureforvideoratechange"))
3642             restrictions |= MediaElementSession::RequireUserGestureForVideoRateChange;
3643         if (equalLettersIgnoringASCIICase(restrictionString, "requireusergestureforfullscreen"))
3644             restrictions |= MediaElementSession::RequireUserGestureForFullscreen;
3645         if (equalLettersIgnoringASCIICase(restrictionString, "requirepageconsenttoloadmedia"))
3646             restrictions |= MediaElementSession::RequirePageConsentToLoadMedia;
3647         if (equalLettersIgnoringASCIICase(restrictionString, "requirepageconsenttoresumemedia"))
3648             restrictions |= MediaElementSession::RequirePageConsentToResumeMedia;
3649 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
3650         if (equalLettersIgnoringASCIICase(restrictionString, "requireusergesturetoshowplaybacktargetpicker"))
3651             restrictions |= MediaElementSession::RequireUserGestureToShowPlaybackTargetPicker;
3652         if (equalLettersIgnoringASCIICase(restrictionString, "wirelessvideoplaybackdisabled"))
3653             restrictions |= MediaElementSession::WirelessVideoPlaybackDisabled;
3654 #endif
3655         if (equalLettersIgnoringASCIICase(restrictionString, "requireusergestureforaudioratechange"))
3656             restrictions |= MediaElementSession::RequireUserGestureForAudioRateChange;
3657         if (equalLettersIgnoringASCIICase(restrictionString, "metadatapreloadingnotpermitted"))
3658             restrictions |= MediaElementSession::MetadataPreloadingNotPermitted;
3659         if (equalLettersIgnoringASCIICase(restrictionString, "autopreloadingnotpermitted"))
3660             restrictions |= MediaElementSession::AutoPreloadingNotPermitted;
3661         if (equalLettersIgnoringASCIICase(restrictionString, "invisibleautoplaynotpermitted"))
3662             restrictions |= MediaElementSession::InvisibleAutoplayNotPermitted;
3663         if (equalLettersIgnoringASCIICase(restrictionString, "overrideusergesturerequirementformaincontent"))
3664             restrictions |= MediaElementSession::OverrideUserGestureRequirementForMainContent;
3665     }
3666     element.mediaSession().addBehaviorRestriction(restrictions);
3667 }
3668
3669 ExceptionOr<void> Internals::postRemoteControlCommand(const String& commandString, float argument)
3670 {
3671     PlatformMediaSession::RemoteControlCommandType command;
3672     PlatformMediaSession::RemoteCommandArgument parameter { argument };
3673
3674     if (equalLettersIgnoringASCIICase(commandString, "play"))
3675         command = PlatformMediaSession::PlayCommand;
3676     else if (equalLettersIgnoringASCIICase(commandString, "pause"))
3677         command = PlatformMediaSession::PauseCommand;
3678     else if (equalLettersIgnoringASCIICase(commandString, "stop"))
3679         command = PlatformMediaSession::StopCommand;
3680     else if (equalLettersIgnoringASCIICase(commandString, "toggleplaypause"))
3681         command = PlatformMediaSession::TogglePlayPauseCommand;
3682     else if (equalLettersIgnoringASCIICase(commandString, "beginseekingbackward"))
3683         command = PlatformMediaSession::BeginSeekingBackwardCommand;
3684     else if (equalLettersIgnoringASCIICase(commandString, "endseekingbackward"))
3685         command = PlatformMediaSession::EndSeekingBackwardCommand;
3686     else if (equalLettersIgnoringASCIICase(commandString, "beginseekingforward"))
3687         command = PlatformMediaSession::BeginSeekingForwardCommand;
3688     else if (equalLettersIgnoringASCIICase(commandString, "endseekingforward"))
3689         command = PlatformMediaSession::EndSeekingForwardCommand;
3690     else if (equalLettersIgnoringASCIICase(commandString, "seektoplaybackposition"))
3691         command = PlatformMediaSession::SeekToPlaybackPositionCommand;
3692     else
3693         return Exception { InvalidAccessError };
3694
3695     PlatformMediaSessionManager::sharedManager().didReceiveRemoteControlCommand(command, &parameter);
3696     return { };
3697 }
3698
3699 bool Internals::elementIsBlockingDisplaySleep(HTMLMediaElement& element) const