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