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