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