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