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