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