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