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