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