Stop using old-style string-based enums in Internals.idl
[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 "HTMLCanvasElement.h"
63 #include "HTMLIFrameElement.h"
64 #include "HTMLImageElement.h"
65 #include "HTMLInputElement.h"
66 #include "HTMLLinkElement.h"
67 #include "HTMLNames.h"
68 #include "HTMLPlugInElement.h"
69 #include "HTMLPreloadScanner.h"
70 #include "HTMLSelectElement.h"
71 #include "HTMLTextAreaElement.h"
72 #include "HTMLVideoElement.h"
73 #include "HistoryController.h"
74 #include "HistoryItem.h"
75 #include "HitTestResult.h"
76 #include "IconController.h"
77 #include "InspectorClient.h"
78 #include "InspectorController.h"
79 #include "InspectorFrontendClientLocal.h"
80 #include "InspectorOverlay.h"
81 #include "InstrumentingAgents.h"
82 #include "IntRect.h"
83 #include "InternalSettings.h"
84 #include "Language.h"
85 #include "MainFrame.h"
86 #include "MallocStatistics.h"
87 #include "MediaPlayer.h"
88 #include "MemoryCache.h"
89 #include "MemoryInfo.h"
90 #include "MockPageOverlay.h"
91 #include "MockPageOverlayClient.h"
92 #include "Page.h"
93 #include "PageCache.h"
94 #include "PageOverlay.h"
95 #include "PathUtilities.h"
96 #include "PlatformMediaSessionManager.h"
97 #include "PrintContext.h"
98 #include "PseudoElement.h"
99 #include "Range.h"
100 #include "RenderEmbeddedObject.h"
101 #include "RenderLayerBacking.h"
102 #include "RenderLayerCompositor.h"
103 #include "RenderMenuList.h"
104 #include "RenderTreeAsText.h"
105 #include "RenderView.h"
106 #include "RenderedDocumentMarker.h"
107 #include "ResourceLoadObserver.h"
108 #include "RuntimeEnabledFeatures.h"
109 #include "SchemeRegistry.h"
110 #include "ScriptedAnimationController.h"
111 #include "ScrollingCoordinator.h"
112 #include "SerializedScriptValue.h"
113 #include "Settings.h"
114 #include "ShadowRoot.h"
115 #include "SourceBuffer.h"
116 #include "SpellChecker.h"
117 #include "StaticNodeList.h"
118 #include "StyleSheetContents.h"
119 #include "TextIterator.h"
120 #include "TreeScope.h"
121 #include "TypeConversions.h"
122 #include "UserMediaController.h"
123 #include "ViewportArguments.h"
124 #include "WebCoreJSClientData.h"
125 #include "WorkerThread.h"
126 #include "XMLHttpRequest.h"
127 #include <JavaScriptCore/Profile.h>
128 #include <bytecode/CodeBlock.h>
129 #include <inspector/InspectorAgentBase.h>
130 #include <inspector/InspectorFrontendChannel.h>
131 #include <inspector/InspectorValues.h>
132 #include <runtime/JSCInlines.h>
133 #include <runtime/JSCJSValue.h>
134 #include <wtf/text/CString.h>
135 #include <wtf/text/StringBuffer.h>
136
137 #if ENABLE(INPUT_TYPE_COLOR)
138 #include "ColorChooser.h"
139 #endif
140
141 #if ENABLE(BATTERY_STATUS)
142 #include "BatteryController.h"
143 #endif
144
145 #if ENABLE(PROXIMITY_EVENTS)
146 #include "DeviceProximityController.h"
147 #endif
148
149 #if ENABLE(MOUSE_CURSOR_SCALE)
150 #include <wtf/dtoa.h>
151 #endif
152
153 #if ENABLE(ENCRYPTED_MEDIA_V2)
154 #include "CDM.h"
155 #include "MockCDM.h"
156 #endif
157
158 #if ENABLE(VIDEO_TRACK)
159 #include "CaptionUserPreferences.h"
160 #include "PageGroup.h"
161 #endif
162
163 #if ENABLE(VIDEO)
164 #include "HTMLMediaElement.h"
165 #include "TimeRanges.h"
166 #endif
167
168 #if ENABLE(SPEECH_SYNTHESIS)
169 #include "DOMWindowSpeechSynthesis.h"
170 #include "PlatformSpeechSynthesizerMock.h"
171 #include "SpeechSynthesis.h"
172 #endif
173
174 #if ENABLE(VIBRATION)
175 #include "Vibration.h"
176 #endif
177
178 #if ENABLE(MEDIA_STREAM)
179 #include "MockRealtimeMediaSourceCenter.h"
180 #endif
181
182 #if ENABLE(WEB_RTC)
183 #include "MockMediaEndpoint.h"
184 #include "RTCPeerConnection.h"
185 #include "RTCPeerConnectionHandlerMock.h"
186 #endif
187
188 #if ENABLE(MEDIA_SOURCE)
189 #include "MockMediaPlayerMediaSource.h"
190 #endif
191
192 #if PLATFORM(MAC)
193 #include "DictionaryLookup.h"
194 #endif
195
196 #if ENABLE(CONTENT_FILTERING)
197 #include "MockContentFilterSettings.h"
198 #endif
199
200 #if ENABLE(WEB_AUDIO)
201 #include "AudioContext.h"
202 #endif
203
204 #if ENABLE(MEDIA_SESSION)
205 #include "MediaSession.h"
206 #include "MediaSessionManager.h"
207 #endif
208
209 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
210 #include "MediaPlaybackTargetContext.h"
211 #endif
212
213 #if PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000
214 #if __has_include(<AccessibilitySupport.h>)
215 #include <AccessibilitySupport.h>
216 #else
217 extern "C" {
218 void _AXSSetForceAllowWebScaling(Boolean);
219 }
220 #endif
221 #endif
222
223 using JSC::CallData;
224 using JSC::CallType;
225 using JSC::CodeBlock;
226 using JSC::FunctionExecutable;
227 using JSC::Identifier;
228 using JSC::JSFunction;
229 using JSC::JSGlobalObject;
230 using JSC::JSObject;
231 using JSC::JSValue;
232 using JSC::MarkedArgumentBuffer;
233 using JSC::PropertySlot;
234 using JSC::ScriptExecutable;
235 using JSC::StackVisitor;
236
237 using namespace Inspector;
238
239 namespace WebCore {
240
241 using namespace HTMLNames;
242
243 class InspectorStubFrontend : public InspectorFrontendClientLocal, public FrontendChannel {
244 public:
245     InspectorStubFrontend(Page& inspectedPage, RefPtr<DOMWindow>&& frontendWindow);
246     virtual ~InspectorStubFrontend();
247
248     // InspectorFrontendClient API
249     void attachWindow(DockSide) override { }
250     void detachWindow() override { }
251     void closeWindow() override;
252     void bringToFront() override { }
253     String localizedStringsURL() override { return String(); }
254     void inspectedURLChanged(const String&) override { }
255 protected:
256     void setAttachedWindowHeight(unsigned) override { }
257     void setAttachedWindowWidth(unsigned) override { }
258
259 public:
260     // Inspector::FrontendChannel API
261     bool sendMessageToFrontend(const String& message) override;
262     ConnectionType connectionType() const override { return ConnectionType::Local; }
263
264 private:
265     Page* frontendPage() const
266     {
267         if (!m_frontendWindow || !m_frontendWindow->document())
268             return nullptr;
269
270         return m_frontendWindow->document()->page();
271     }
272
273     RefPtr<DOMWindow> m_frontendWindow;
274     InspectorController& m_frontendController;
275 };
276
277 InspectorStubFrontend::InspectorStubFrontend(Page& inspectedPage, RefPtr<DOMWindow>&& frontendWindow)
278     : InspectorFrontendClientLocal(&inspectedPage.inspectorController(), frontendWindow->document()->page(), std::make_unique<InspectorFrontendClientLocal::Settings>())
279     , m_frontendWindow(frontendWindow.copyRef())
280     , m_frontendController(frontendPage()->inspectorController())
281 {
282     ASSERT_ARG(frontendWindow, frontendWindow);
283
284     m_frontendController.setInspectorFrontendClient(this);
285     inspectedPage.inspectorController().connectFrontend(this);
286 }
287
288 InspectorStubFrontend::~InspectorStubFrontend()
289 {
290     closeWindow();
291 }
292
293 void InspectorStubFrontend::closeWindow()
294 {
295     if (!m_frontendWindow)
296         return;
297
298     m_frontendController.setInspectorFrontendClient(nullptr);
299     inspectedPage()->inspectorController().disconnectFrontend(this);
300
301     m_frontendWindow->close();
302     m_frontendWindow = nullptr;
303 }
304
305 bool InspectorStubFrontend::sendMessageToFrontend(const String& message)
306 {
307     ASSERT_ARG(message, !message.isEmpty());
308
309     return InspectorClient::doDispatchMessageOnFrontendPage(frontendPage(), message);
310 }
311
312 static bool markerTypeFrom(const String& markerType, DocumentMarker::MarkerType& result)
313 {
314     if (equalLettersIgnoringASCIICase(markerType, "spelling"))
315         result = DocumentMarker::Spelling;
316     else if (equalLettersIgnoringASCIICase(markerType, "grammar"))
317         result = DocumentMarker::Grammar;
318     else if (equalLettersIgnoringASCIICase(markerType, "textmatch"))
319         result = DocumentMarker::TextMatch;
320     else if (equalLettersIgnoringASCIICase(markerType, "replacement"))
321         result = DocumentMarker::Replacement;
322     else if (equalLettersIgnoringASCIICase(markerType, "correctionindicator"))
323         result = DocumentMarker::CorrectionIndicator;
324     else if (equalLettersIgnoringASCIICase(markerType, "rejectedcorrection"))
325         result = DocumentMarker::RejectedCorrection;
326     else if (equalLettersIgnoringASCIICase(markerType, "autocorrected"))
327         result = DocumentMarker::Autocorrected;
328     else if (equalLettersIgnoringASCIICase(markerType, "spellcheckingexemption"))
329         result = DocumentMarker::SpellCheckingExemption;
330     else if (equalLettersIgnoringASCIICase(markerType, "deletedautocorrection"))
331         result = DocumentMarker::DeletedAutocorrection;
332     else if (equalLettersIgnoringASCIICase(markerType, "dictationalternatives"))
333         result = DocumentMarker::DictationAlternatives;
334 #if ENABLE(TELEPHONE_NUMBER_DETECTION)
335     else if (equalLettersIgnoringASCIICase(markerType, "telephonenumber"))
336         result = DocumentMarker::TelephoneNumber;
337 #endif
338     else
339         return false;
340     
341     return true;
342 }
343
344 static bool markerTypesFrom(const String& markerType, DocumentMarker::MarkerTypes& result)
345 {
346     DocumentMarker::MarkerType singularResult;
347
348     if (markerType.isEmpty() || equalLettersIgnoringASCIICase(markerType, "all"))
349         result = DocumentMarker::AllMarkers();
350     else if (markerTypeFrom(markerType, singularResult))
351         result = singularResult;
352     else
353         return false;
354
355     return true;
356 }
357
358 const char* Internals::internalsId = "internals";
359
360 Ref<Internals> Internals::create(Document& document)
361 {
362     return adoptRef(*new Internals(document));
363 }
364
365 Internals::~Internals()
366 {
367 }
368
369 void Internals::resetToConsistentState(Page& page)
370 {
371     page.setPageScaleFactor(1, IntPoint(0, 0));
372     page.setPagination(Pagination());
373     page.setPaginationLineGridEnabled(false);
374
375     page.setDefersLoading(false);
376     
377     page.mainFrame().setTextZoomFactor(1.0f);
378     
379     FrameView* mainFrameView = page.mainFrame().view();
380     if (mainFrameView) {
381         mainFrameView->setHeaderHeight(0);
382         mainFrameView->setFooterHeight(0);
383         page.setTopContentInset(0);
384         mainFrameView->setUseFixedLayout(false);
385         mainFrameView->setFixedLayoutSize(IntSize());
386     }
387
388     WebCore::overrideUserPreferredLanguages(Vector<String>());
389     WebCore::Settings::setUsesOverlayScrollbars(false);
390     WebCore::Settings::setUsesMockScrollAnimator(false);
391     page.inspectorController().setLegacyProfilerEnabled(false);
392 #if ENABLE(VIDEO_TRACK)
393     page.group().captionPreferences().setCaptionsStyleSheetOverride(emptyString());
394     page.group().captionPreferences().setTestingMode(false);
395 #endif
396     if (!page.mainFrame().editor().isContinuousSpellCheckingEnabled())
397         page.mainFrame().editor().toggleContinuousSpellChecking();
398     if (page.mainFrame().editor().isOverwriteModeEnabled())
399         page.mainFrame().editor().toggleOverwriteModeEnabled();
400     page.mainFrame().loader().clearTestingOverrides();
401     page.applicationCacheStorage().setDefaultOriginQuota(ApplicationCacheStorage::noQuota());
402 #if ENABLE(VIDEO)
403     PlatformMediaSessionManager::sharedManager().resetRestrictions();
404     PlatformMediaSessionManager::sharedManager().setWillIgnoreSystemInterruptions(true);
405 #endif
406 #if HAVE(ACCESSIBILITY)
407     AXObjectCache::setEnhancedUserInterfaceAccessibility(false);
408     AXObjectCache::disableAccessibility();
409 #endif
410
411     MockPageOverlayClient::singleton().uninstallAllOverlays();
412
413 #if ENABLE(CONTENT_FILTERING)
414     MockContentFilterSettings::reset();
415 #endif
416
417     page.setShowAllPlugins(false);
418     
419 #if PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000
420     _AXSSetForceAllowWebScaling(false);
421 #endif
422 }
423
424 Internals::Internals(Document& document)
425     : ContextDestructionObserver(&document)
426 {
427 #if ENABLE(VIDEO_TRACK)
428     if (document.page())
429         document.page()->group().captionPreferences().setTestingMode(true);
430 #endif
431
432 #if ENABLE(MEDIA_STREAM)
433     setMockMediaCaptureDevicesEnabled(true);
434 #endif
435
436 #if ENABLE(WEB_RTC)
437     enableMockMediaEndpoint();
438     enableMockRTCPeerConnectionHandler();
439 #endif
440
441 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
442     if (document.page())
443         document.page()->setMockMediaPlaybackTargetPickerEnabled(true);
444 #endif
445 }
446
447 Document* Internals::contextDocument() const
448 {
449     return downcast<Document>(scriptExecutionContext());
450 }
451
452 Frame* Internals::frame() const
453 {
454     if (!contextDocument())
455         return nullptr;
456     return contextDocument()->frame();
457 }
458
459 InternalSettings* Internals::settings() const
460 {
461     Document* document = contextDocument();
462     if (!document)
463         return nullptr;
464     Page* page = document->page();
465     if (!page)
466         return nullptr;
467     return InternalSettings::from(page);
468 }
469
470 unsigned Internals::workerThreadCount() const
471 {
472     return WorkerThread::workerThreadCount();
473 }
474
475 String Internals::address(Node& node)
476 {
477     return String::format("%p", &node);
478 }
479
480 bool Internals::nodeNeedsStyleRecalc(Node& node)
481 {
482     return node.needsStyleRecalc();
483 }
484
485 static String styleChangeTypeToString(StyleChangeType type)
486 {
487     switch (type) {
488     case NoStyleChange:
489         return "NoStyleChange";
490     case InlineStyleChange:
491         return "InlineStyleChange";
492     case FullStyleChange:
493         return "FullStyleChange";
494     case SyntheticStyleChange:
495         return "SyntheticStyleChange";
496     case ReconstructRenderTree:
497         return "ReconstructRenderTree";
498     }
499     ASSERT_NOT_REACHED();
500     return "";
501 }
502
503 String Internals::styleChangeType(Node& node)
504 {
505     return styleChangeTypeToString(node.styleChangeType());
506 }
507
508 String Internals::description(JSC::JSValue value)
509 {
510     return toString(value);
511 }
512
513 bool Internals::isPreloaded(const String& url)
514 {
515     Document* document = contextDocument();
516     return document->cachedResourceLoader().isPreloaded(url);
517 }
518
519 bool Internals::isLoadingFromMemoryCache(const String& url)
520 {
521     if (!contextDocument() || !contextDocument()->page())
522         return false;
523
524     ResourceRequest request(contextDocument()->completeURL(url));
525 #if ENABLE(CACHE_PARTITIONING)
526     request.setDomainForCachePartition(contextDocument()->topOrigin()->domainForCachePartition());
527 #endif
528     CachedResource* resource = MemoryCache::singleton().resourceForRequest(request, contextDocument()->page()->sessionID());
529     return resource && resource->status() == CachedResource::Cached;
530 }
531
532 String Internals::xhrResponseSource(XMLHttpRequest& request)
533 {
534     if (request.resourceResponse().isNull())
535         return "Null response";
536     switch (request.resourceResponse().source()) {
537     case ResourceResponse::Source::Unknown:
538         return "Unknown";
539     case ResourceResponse::Source::Network:
540         return "Network";
541     case ResourceResponse::Source::DiskCache:
542         return "Disk cache";
543     case ResourceResponse::Source::DiskCacheAfterValidation:
544         return "Disk cache after validation";
545     case ResourceResponse::Source::MemoryCache:
546         return "Memory cache";
547     case ResourceResponse::Source::MemoryCacheAfterValidation:
548         return "Memory cache after validation";
549     }
550     ASSERT_NOT_REACHED();
551     return "Error";
552 }
553
554 bool Internals::isSharingStyleSheetContents(HTMLLinkElement& a, HTMLLinkElement& b)
555 {
556     if (!a.sheet() || !b.sheet())
557         return false;
558     return &a.sheet()->contents() == &b.sheet()->contents();
559 }
560
561 bool Internals::isStyleSheetLoadingSubresources(HTMLLinkElement& link)
562 {
563     return link.sheet() && link.sheet()->contents().isLoadingSubresources();
564 }
565
566 static ResourceRequestCachePolicy toResourceRequestCachePolicy(InternalsCachePolicy policy)
567 {
568     switch (policy) {
569     case InternalsCachePolicy::UseProtocolCachePolicy:
570         return UseProtocolCachePolicy;
571     case InternalsCachePolicy::ReloadIgnoringCacheData:
572         return ReloadIgnoringCacheData;
573     case InternalsCachePolicy::ReturnCacheDataElseLoad:
574         return ReturnCacheDataElseLoad;
575     case InternalsCachePolicy::ReturnCacheDataDontLoad:
576         return ReturnCacheDataDontLoad;
577     }
578     ASSERT_NOT_REACHED();
579     return UseProtocolCachePolicy;
580 }
581
582 void Internals::setOverrideCachePolicy(InternalsCachePolicy policy)
583 {
584     frame()->loader().setOverrideCachePolicyForTesting(toResourceRequestCachePolicy(policy));
585 }
586
587 void Internals::setCanShowModalDialogOverride(bool allow, ExceptionCode& ec)
588 {
589     if (!contextDocument() || !contextDocument()->domWindow()) {
590         ec = INVALID_ACCESS_ERR;
591         return;
592     }
593
594     contextDocument()->domWindow()->setCanShowModalDialogOverride(allow);
595 }
596
597 static ResourceLoadPriority toResourceLoadPriority(InternalsResourceLoadPriority priority)
598 {
599     switch (priority) {
600     case InternalsResourceLoadPriority::ResourceLoadPriorityVeryLow:
601         return ResourceLoadPriority::VeryLow;
602     case InternalsResourceLoadPriority::ResourceLoadPriorityLow:
603         return ResourceLoadPriority::Low;
604     case InternalsResourceLoadPriority::ResourceLoadPriorityMedium:
605         return ResourceLoadPriority::Medium;
606     case InternalsResourceLoadPriority::ResourceLoadPriorityHigh:
607         return ResourceLoadPriority::High;
608     case InternalsResourceLoadPriority::ResourceLoadPriorityVeryHigh:
609         return ResourceLoadPriority::VeryHigh;
610     }
611     ASSERT_NOT_REACHED();
612     return ResourceLoadPriority::Low;
613 }
614
615 void Internals::setOverrideResourceLoadPriority(InternalsResourceLoadPriority priority)
616 {
617     frame()->loader().setOverrideResourceLoadPriorityForTesting(toResourceLoadPriority(priority));
618 }
619
620 void Internals::setStrictRawResourceValidationPolicyDisabled(bool disabled)
621 {
622     frame()->loader().setStrictRawResourceValidationPolicyDisabledForTesting(disabled);
623 }
624
625 void Internals::clearMemoryCache()
626 {
627     MemoryCache::singleton().evictResources();
628 }
629
630 void Internals::pruneMemoryCacheToSize(unsigned size)
631 {
632     MemoryCache::singleton().pruneDeadResourcesToSize(size);
633     MemoryCache::singleton().pruneLiveResourcesToSize(size, true);
634 }
635
636 unsigned Internals::memoryCacheSize() const
637 {
638     return MemoryCache::singleton().size();
639 }
640
641 unsigned Internals::imageFrameIndex(HTMLImageElement& element)
642 {
643     auto* cachedImage = element.cachedImage();
644     if (!cachedImage)
645         return 0;
646
647     auto* image = cachedImage->image();
648     return is<BitmapImage>(image) ? downcast<BitmapImage>(*image).currentFrame() : 0;
649 }
650
651 void Internals::clearPageCache()
652 {
653     PageCache::singleton().pruneToSizeNow(0, PruningReason::None);
654 }
655
656 unsigned Internals::pageCacheSize() const
657 {
658     return PageCache::singleton().pageCount();
659 }
660
661 Node* Internals::treeScopeRootNode(Node& node)
662 {
663     return &node.treeScope().rootNode();
664 }
665
666 Node* Internals::parentTreeScope(Node& node)
667 {
668     const TreeScope* parentTreeScope = node.treeScope().parentTreeScope();
669     return parentTreeScope ? &parentTreeScope->rootNode() : nullptr;
670 }
671
672 unsigned Internals::lastSpatialNavigationCandidateCount(ExceptionCode& ec) const
673 {
674     if (!contextDocument() || !contextDocument()->page()) {
675         ec = INVALID_ACCESS_ERR;
676         return 0;
677     }
678
679     return contextDocument()->page()->lastSpatialNavigationCandidateCount();
680 }
681
682 unsigned Internals::numberOfActiveAnimations() const
683 {
684     return frame()->animation().numberOfActiveAnimations(frame()->document());
685 }
686
687 bool Internals::animationsAreSuspended(ExceptionCode& ec) const
688 {
689     Document* document = contextDocument();
690     if (!document || !document->frame()) {
691         ec = INVALID_ACCESS_ERR;
692         return false;
693     }
694
695     return document->frame()->animation().isSuspended();
696 }
697
698 void Internals::suspendAnimations(ExceptionCode& ec) const
699 {
700     Document* document = contextDocument();
701     if (!document || !document->frame()) {
702         ec = INVALID_ACCESS_ERR;
703         return;
704     }
705
706     document->frame()->animation().suspendAnimations();
707 }
708
709 void Internals::resumeAnimations(ExceptionCode& ec) const
710 {
711     Document* document = contextDocument();
712     if (!document || !document->frame()) {
713         ec = INVALID_ACCESS_ERR;
714         return;
715     }
716
717     document->frame()->animation().resumeAnimations();
718 }
719
720 bool Internals::pauseAnimationAtTimeOnElement(const String& animationName, double pauseTime, Element& element, ExceptionCode& ec)
721 {
722     if (pauseTime < 0) {
723         ec = INVALID_ACCESS_ERR;
724         return false;
725     }
726     return frame()->animation().pauseAnimationAtTime(element.renderer(), AtomicString(animationName), pauseTime);
727 }
728
729 bool Internals::pauseAnimationAtTimeOnPseudoElement(const String& animationName, double pauseTime, Element& element, const String& pseudoId, ExceptionCode& ec)
730 {
731     if (pauseTime < 0) {
732         ec = INVALID_ACCESS_ERR;
733         return false;
734     }
735
736     if (pseudoId != "before" && pseudoId != "after") {
737         ec = INVALID_ACCESS_ERR;
738         return false;
739     }
740
741     PseudoElement* pseudoElement = pseudoId == "before" ? element.beforePseudoElement() : element.afterPseudoElement();
742     if (!pseudoElement) {
743         ec = INVALID_ACCESS_ERR;
744         return false;
745     }
746
747     return frame()->animation().pauseAnimationAtTime(pseudoElement->renderer(), AtomicString(animationName), pauseTime);
748 }
749
750 bool Internals::pauseTransitionAtTimeOnElement(const String& propertyName, double pauseTime, Element& element, ExceptionCode& ec)
751 {
752     if (pauseTime < 0) {
753         ec = INVALID_ACCESS_ERR;
754         return false;
755     }
756     return frame()->animation().pauseTransitionAtTime(element.renderer(), propertyName, pauseTime);
757 }
758
759 bool Internals::pauseTransitionAtTimeOnPseudoElement(const String& property, double pauseTime, Element& element, const String& pseudoId, ExceptionCode& ec)
760 {
761     if (pauseTime < 0) {
762         ec = INVALID_ACCESS_ERR;
763         return false;
764     }
765
766     if (pseudoId != "before" && pseudoId != "after") {
767         ec = INVALID_ACCESS_ERR;
768         return false;
769     }
770
771     PseudoElement* pseudoElement = pseudoId == "before" ? element.beforePseudoElement() : element.afterPseudoElement();
772     if (!pseudoElement) {
773         ec = INVALID_ACCESS_ERR;
774         return false;
775     }
776
777     return frame()->animation().pauseTransitionAtTime(pseudoElement->renderer(), property, pauseTime);
778 }
779
780 String Internals::elementRenderTreeAsText(Element& element, ExceptionCode& ec)
781 {
782     element.document().updateStyleIfNeeded();
783
784     String representation = externalRepresentation(&element);
785     if (representation.isEmpty()) {
786         ec = INVALID_ACCESS_ERR;
787         return String();
788     }
789
790     return representation;
791 }
792
793 bool Internals::hasPausedImageAnimations(Element& element)
794 {
795     return element.renderer() && element.renderer()->hasPausedImageAnimations();
796 }
797
798 RefPtr<CSSComputedStyleDeclaration> Internals::computedStyleIncludingVisitedInfo(Node& node) const
799 {
800     bool allowVisitedStyle = true;
801     return CSSComputedStyleDeclaration::create(&node, allowVisitedStyle);
802 }
803
804 Node* Internals::ensureShadowRoot(Element& host, ExceptionCode& ec)
805 {
806     if (ShadowRoot* shadowRoot = host.shadowRoot())
807         return shadowRoot;
808
809     return host.createShadowRoot(ec).get();
810 }
811
812 Node* Internals::ensureUserAgentShadowRoot(Element& host)
813 {
814     return &host.ensureUserAgentShadowRoot();
815 }
816
817 Node* Internals::createShadowRoot(Element& host, ExceptionCode& ec)
818 {
819     return host.createShadowRoot(ec).get();
820 }
821
822 Node* Internals::shadowRoot(Element& host)
823 {
824     return host.shadowRoot();
825 }
826
827 String Internals::shadowRootType(const Node& root, ExceptionCode& ec) const
828 {
829     if (!is<ShadowRoot>(root)) {
830         ec = INVALID_ACCESS_ERR;
831         return String();
832     }
833
834     switch (downcast<ShadowRoot>(root).type()) {
835     case ShadowRoot::Type::UserAgent:
836         return String("UserAgentShadowRoot");
837     case ShadowRoot::Type::Closed:
838         return String("ClosedShadowRoot");
839     case ShadowRoot::Type::Open:
840         return String("OpenShadowRoot");
841     default:
842         ASSERT_NOT_REACHED();
843         return String("Unknown");
844     }
845 }
846
847 String Internals::shadowPseudoId(Element& element)
848 {
849     return element.shadowPseudoId().string();
850 }
851
852 void Internals::setShadowPseudoId(Element& element, const String& id)
853 {
854     return element.setPseudo(id);
855 }
856
857 bool Internals::isTimerThrottled(int timeoutId, ExceptionCode& ec)
858 {
859     DOMTimer* timer = scriptExecutionContext()->findTimeout(timeoutId);
860     if (!timer) {
861         ec = NOT_FOUND_ERR;
862         return false;
863     }
864     return timer->m_throttleState == DOMTimer::ShouldThrottle;
865 }
866
867 bool Internals::isRequestAnimationFrameThrottled() const
868 {
869 #if ENABLE(REQUEST_ANIMATION_FRAME)
870     auto* scriptedAnimationController = contextDocument()->scriptedAnimationController();
871     if (!scriptedAnimationController)
872         return false;
873     return scriptedAnimationController->isThrottled();
874 #else
875     return false;
876 #endif
877 }
878
879 bool Internals::areTimersThrottled() const
880 {
881     return contextDocument()->isTimerThrottlingEnabled();
882 }
883
884 String Internals::visiblePlaceholder(Element& element)
885 {
886     if (is<HTMLTextFormControlElement>(element)) {
887         const HTMLTextFormControlElement& textFormControlElement = downcast<HTMLTextFormControlElement>(element);
888         if (!textFormControlElement.isPlaceholderVisible())
889             return String();
890         if (HTMLElement* placeholderElement = textFormControlElement.placeholderElement())
891             return placeholderElement->textContent();
892     }
893
894     return String();
895 }
896
897 void Internals::selectColorInColorChooser(HTMLInputElement& element, const String& colorValue)
898 {
899     element.selectColor(Color(colorValue));
900 }
901
902 Vector<String> Internals::formControlStateOfPreviousHistoryItem(ExceptionCode& ec)
903 {
904     HistoryItem* mainItem = frame()->loader().history().previousItem();
905     if (!mainItem) {
906         ec = INVALID_ACCESS_ERR;
907         return Vector<String>();
908     }
909     String uniqueName = frame()->tree().uniqueName();
910     if (mainItem->target() != uniqueName && !mainItem->childItemWithTarget(uniqueName)) {
911         ec = INVALID_ACCESS_ERR;
912         return Vector<String>();
913     }
914     return mainItem->target() == uniqueName ? mainItem->documentState() : mainItem->childItemWithTarget(uniqueName)->documentState();
915 }
916
917 void Internals::setFormControlStateOfPreviousHistoryItem(const Vector<String>& state, ExceptionCode& ec)
918 {
919     HistoryItem* mainItem = frame()->loader().history().previousItem();
920     if (!mainItem) {
921         ec = INVALID_ACCESS_ERR;
922         return;
923     }
924     String uniqueName = frame()->tree().uniqueName();
925     if (mainItem->target() == uniqueName)
926         mainItem->setDocumentState(state);
927     else if (HistoryItem* subItem = mainItem->childItemWithTarget(uniqueName))
928         subItem->setDocumentState(state);
929     else
930         ec = INVALID_ACCESS_ERR;
931 }
932
933 #if ENABLE(SPEECH_SYNTHESIS)
934 void Internals::enableMockSpeechSynthesizer()
935 {
936     Document* document = contextDocument();
937     if (!document || !document->domWindow())
938         return;
939     SpeechSynthesis* synthesis = DOMWindowSpeechSynthesis::speechSynthesis(*document->domWindow());
940     if (!synthesis)
941         return;
942     
943     synthesis->setPlatformSynthesizer(std::make_unique<PlatformSpeechSynthesizerMock>(synthesis));
944 }
945 #endif
946
947 #if ENABLE(WEB_RTC)
948 void Internals::enableMockMediaEndpoint()
949 {
950     MediaEndpoint::create = MockMediaEndpoint::create;
951 }
952
953 void Internals::enableMockRTCPeerConnectionHandler()
954 {
955     RTCPeerConnectionHandler::create = RTCPeerConnectionHandlerMock::create;
956 }
957 #endif
958
959 #if ENABLE(MEDIA_STREAM)
960 void Internals::setMockMediaCaptureDevicesEnabled(bool enabled)
961 {
962     WebCore::Settings::setMockCaptureDevicesEnabled(enabled);
963 }
964 #endif
965
966 Ref<ClientRect> Internals::absoluteCaretBounds(ExceptionCode& ec)
967 {
968     Document* document = contextDocument();
969     if (!document || !document->frame()) {
970         ec = INVALID_ACCESS_ERR;
971         return ClientRect::create();
972     }
973
974     return ClientRect::create(document->frame()->selection().absoluteCaretBounds());
975 }
976
977 Ref<ClientRect> Internals::boundingBox(Element& element)
978 {
979     element.document().updateLayoutIgnorePendingStylesheets();
980     auto renderer = element.renderer();
981     if (!renderer)
982         return ClientRect::create();
983     return ClientRect::create(renderer->absoluteBoundingBoxRectIgnoringTransforms());
984 }
985
986 Ref<ClientRectList> Internals::inspectorHighlightRects(ExceptionCode& ec)
987 {
988     Document* document = contextDocument();
989     if (!document || !document->page()) {
990         ec = INVALID_ACCESS_ERR;
991         return ClientRectList::create();
992     }
993
994     Highlight highlight;
995     document->page()->inspectorController().getHighlight(highlight, InspectorOverlay::CoordinateSystem::View);
996     return ClientRectList::create(highlight.quads);
997 }
998
999 String Internals::inspectorHighlightObject(ExceptionCode& ec)
1000 {
1001     Document* document = contextDocument();
1002     if (!document || !document->page()) {
1003         ec = INVALID_ACCESS_ERR;
1004         return String();
1005     }
1006
1007     return document->page()->inspectorController().buildObjectForHighlightedNodes()->toJSONString();
1008 }
1009
1010 unsigned Internals::markerCountForNode(Node& node, const String& markerType, ExceptionCode& ec)
1011 {
1012     DocumentMarker::MarkerTypes markerTypes = 0;
1013     if (!markerTypesFrom(markerType, markerTypes)) {
1014         ec = SYNTAX_ERR;
1015         return 0;
1016     }
1017
1018     node.document().frame()->editor().updateEditorUINowIfScheduled();
1019     return node.document().markers().markersFor(&node, markerTypes).size();
1020 }
1021
1022 RenderedDocumentMarker* Internals::markerAt(Node& node, const String& markerType, unsigned index, ExceptionCode& ec)
1023 {
1024     node.document().updateLayoutIgnorePendingStylesheets();
1025
1026     DocumentMarker::MarkerTypes markerTypes = 0;
1027     if (!markerTypesFrom(markerType, markerTypes)) {
1028         ec = SYNTAX_ERR;
1029         return nullptr;
1030     }
1031
1032     node.document().frame()->editor().updateEditorUINowIfScheduled();
1033
1034     Vector<RenderedDocumentMarker*> markers = node.document().markers().markersFor(&node, markerTypes);
1035     if (markers.size() <= index)
1036         return nullptr;
1037     return markers[index];
1038 }
1039
1040 RefPtr<Range> Internals::markerRangeForNode(Node& node, const String& markerType, unsigned index, ExceptionCode& ec)
1041 {
1042     RenderedDocumentMarker* marker = markerAt(node, markerType, index, ec);
1043     if (!marker)
1044         return nullptr;
1045     return Range::create(node.document(), &node, marker->startOffset(), &node, marker->endOffset());
1046 }
1047
1048 String Internals::markerDescriptionForNode(Node& node, const String& markerType, unsigned index, ExceptionCode& ec)
1049 {
1050     RenderedDocumentMarker* marker = markerAt(node, markerType, index, ec);
1051     if (!marker)
1052         return String();
1053     return marker->description();
1054 }
1055
1056 String Internals::dumpMarkerRects(const String& markerTypeString, ExceptionCode& ec)
1057 {
1058     DocumentMarker::MarkerType markerType;
1059     if (!markerTypeFrom(markerTypeString, markerType)) {
1060         ec = SYNTAX_ERR;
1061         return String();
1062     }
1063
1064     contextDocument()->markers().updateRectsForInvalidatedMarkersOfType(markerType);
1065     auto rects = contextDocument()->markers().renderedRectsForMarkers(markerType);
1066
1067     StringBuilder rectString;
1068     rectString.appendLiteral("marker rects: ");
1069     for (const auto& rect : rects) {
1070         rectString.append('(');
1071         rectString.appendNumber(rect.x());
1072         rectString.appendLiteral(", ");
1073         rectString.appendNumber(rect.y());
1074         rectString.appendLiteral(", ");
1075         rectString.appendNumber(rect.width());
1076         rectString.appendLiteral(", ");
1077         rectString.appendNumber(rect.height());
1078         rectString.appendLiteral(") ");
1079     }
1080     return rectString.toString();
1081 }
1082
1083 void Internals::addTextMatchMarker(const Range& range, bool isActive)
1084 {
1085     range.ownerDocument().updateLayoutIgnorePendingStylesheets();
1086     range.ownerDocument().markers().addTextMatchMarker(&range, isActive);
1087 }
1088
1089 void Internals::setMarkedTextMatchesAreHighlighted(bool flag, ExceptionCode& ec)
1090 {
1091     Document* document = contextDocument();
1092     if (!document || !document->frame()) {
1093         ec = INVALID_ACCESS_ERR;
1094         return;
1095     }
1096     document->frame()->editor().setMarkedTextMatchesAreHighlighted(flag);
1097 }
1098
1099 void Internals::invalidateFontCache()
1100 {
1101     FontCache::singleton().invalidate();
1102 }
1103
1104 void Internals::setScrollViewPosition(int x, int y, ExceptionCode& ec)
1105 {
1106     Document* document = contextDocument();
1107     if (!document || !document->view()) {
1108         ec = INVALID_ACCESS_ERR;
1109         return;
1110     }
1111
1112     FrameView* frameView = document->view();
1113     bool constrainsScrollingToContentEdgeOldValue = frameView->constrainsScrollingToContentEdge();
1114     bool scrollbarsSuppressedOldValue = frameView->scrollbarsSuppressed();
1115
1116     frameView->setConstrainsScrollingToContentEdge(false);
1117     frameView->setScrollbarsSuppressed(false);
1118     frameView->setScrollOffsetFromInternals({ x, y });
1119     frameView->setScrollbarsSuppressed(scrollbarsSuppressedOldValue);
1120     frameView->setConstrainsScrollingToContentEdge(constrainsScrollingToContentEdgeOldValue);
1121 }
1122
1123 void Internals::setViewBaseBackgroundColor(const String& colorValue, ExceptionCode& ec)
1124 {
1125     Document* document = contextDocument();
1126     if (!document || !document->view()) {
1127         ec = INVALID_ACCESS_ERR;
1128         return;
1129     }
1130
1131     document->view()->setBaseBackgroundColor(Color(colorValue));
1132 }
1133
1134 void Internals::setPagination(const String& mode, int gap, int pageLength, ExceptionCode& ec)
1135 {
1136     Document* document = contextDocument();
1137     if (!document || !document->page()) {
1138         ec = INVALID_ACCESS_ERR;
1139         return;
1140     }
1141     Page* page = document->page();
1142
1143     Pagination pagination;
1144     if (mode == "Unpaginated")
1145         pagination.mode = Pagination::Unpaginated;
1146     else if (mode == "LeftToRightPaginated")
1147         pagination.mode = Pagination::LeftToRightPaginated;
1148     else if (mode == "RightToLeftPaginated")
1149         pagination.mode = Pagination::RightToLeftPaginated;
1150     else if (mode == "TopToBottomPaginated")
1151         pagination.mode = Pagination::TopToBottomPaginated;
1152     else if (mode == "BottomToTopPaginated")
1153         pagination.mode = Pagination::BottomToTopPaginated;
1154     else {
1155         ec = SYNTAX_ERR;
1156         return;
1157     }
1158
1159     pagination.gap = gap;
1160     pagination.pageLength = pageLength;
1161     page->setPagination(pagination);
1162 }
1163
1164 void Internals::setPaginationLineGridEnabled(bool enabled, ExceptionCode& ec)
1165 {
1166     Document* document = contextDocument();
1167     if (!document || !document->page()) {
1168         ec = INVALID_ACCESS_ERR;
1169         return;
1170     }
1171     Page* page = document->page();
1172     page->setPaginationLineGridEnabled(enabled);
1173 }
1174
1175 String Internals::configurationForViewport(float devicePixelRatio, int deviceWidth, int deviceHeight, int availableWidth, int availableHeight, ExceptionCode& ec)
1176 {
1177     Document* document = contextDocument();
1178     if (!document || !document->page()) {
1179         ec = INVALID_ACCESS_ERR;
1180         return String();
1181     }
1182     Page* page = document->page();
1183
1184     const int defaultLayoutWidthForNonMobilePages = 980;
1185
1186     ViewportArguments arguments = page->viewportArguments();
1187     ViewportAttributes attributes = computeViewportAttributes(arguments, defaultLayoutWidthForNonMobilePages, deviceWidth, deviceHeight, devicePixelRatio, IntSize(availableWidth, availableHeight));
1188     restrictMinimumScaleFactorToViewportSize(attributes, IntSize(availableWidth, availableHeight), devicePixelRatio);
1189     restrictScaleFactorToInitialScaleIfNotUserScalable(attributes);
1190
1191     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");
1192 }
1193
1194 bool Internals::wasLastChangeUserEdit(Element& textField, ExceptionCode& ec)
1195 {
1196     if (is<HTMLInputElement>(textField))
1197         return downcast<HTMLInputElement>(textField).lastChangeWasUserEdit();
1198
1199     if (is<HTMLTextAreaElement>(textField))
1200         return downcast<HTMLTextAreaElement>(textField).lastChangeWasUserEdit();
1201
1202     ec = INVALID_NODE_TYPE_ERR;
1203     return false;
1204 }
1205
1206 bool Internals::elementShouldAutoComplete(HTMLInputElement& element)
1207 {
1208     return element.shouldAutocomplete();
1209 }
1210
1211 void Internals::setEditingValue(HTMLInputElement& element, const String& value)
1212 {
1213     element.setEditingValue(value);
1214 }
1215
1216 void Internals::setAutofilled(HTMLInputElement& element, bool enabled)
1217 {
1218     element.setAutoFilled(enabled);
1219 }
1220
1221 static AutoFillButtonType toAutoFillButtonType(InternalsAutoFillButtonType type)
1222 {
1223     switch (type) {
1224     case InternalsAutoFillButtonType::AutoFillButtonTypeNone:
1225         return AutoFillButtonType::None;
1226     case InternalsAutoFillButtonType::AutoFillButtonTypeCredentials:
1227         return AutoFillButtonType::Credentials;
1228     case InternalsAutoFillButtonType::AutoFillButtonTypeContacts:
1229         return AutoFillButtonType::Contacts;
1230     }
1231     ASSERT_NOT_REACHED();
1232     return AutoFillButtonType::None;
1233 }
1234
1235 void Internals::setShowAutoFillButton(HTMLInputElement& element, InternalsAutoFillButtonType type)
1236 {
1237     element.setShowAutoFillButton(toAutoFillButtonType(type));
1238 }
1239
1240 void Internals::scrollElementToRect(Element& element, int x, int y, int w, int h, ExceptionCode& ec)
1241 {
1242     FrameView* frameView = element.document().view();
1243     if (!frameView) {
1244         ec = INVALID_ACCESS_ERR;
1245         return;
1246     }
1247     frameView->scrollElementToRect(element, { x, y, w, h });
1248 }
1249
1250 String Internals::autofillFieldName(Element& element, ExceptionCode& ec)
1251 {
1252     if (!is<HTMLFormControlElement>(element)) {
1253         ec = INVALID_NODE_TYPE_ERR;
1254         return { };
1255     }
1256
1257     return downcast<HTMLFormControlElement>(element).autofillData().fieldName;
1258 }
1259
1260 void Internals::paintControlTints(ExceptionCode& ec)
1261 {
1262     Document* document = contextDocument();
1263     if (!document || !document->view()) {
1264         ec = INVALID_ACCESS_ERR;
1265         return;
1266     }
1267
1268     FrameView* frameView = document->view();
1269     frameView->paintControlTints();
1270 }
1271
1272 RefPtr<Range> Internals::rangeFromLocationAndLength(Element& scope, int rangeLocation, int rangeLength)
1273 {
1274     return TextIterator::rangeFromLocationAndLength(&scope, rangeLocation, rangeLength);
1275 }
1276
1277 unsigned Internals::locationFromRange(Element& scope, const Range& range)
1278 {
1279     size_t location = 0;
1280     size_t unusedLength = 0;
1281     TextIterator::getLocationAndLengthFromRange(&scope, &range, location, unusedLength);
1282     return location;
1283 }
1284
1285 unsigned Internals::lengthFromRange(Element& scope, const Range& range)
1286 {
1287     size_t unusedLocation = 0;
1288     size_t length = 0;
1289     TextIterator::getLocationAndLengthFromRange(&scope, &range, unusedLocation, length);
1290     return length;
1291 }
1292
1293 String Internals::rangeAsText(const Range& range)
1294 {
1295     return range.text();
1296 }
1297
1298 RefPtr<Range> Internals::subrange(Range& range, int rangeLocation, int rangeLength)
1299 {
1300     return TextIterator::subrange(&range, rangeLocation, rangeLength);
1301 }
1302
1303 RefPtr<Range> Internals::rangeForDictionaryLookupAtLocation(int x, int y, ExceptionCode& ec)
1304 {
1305 #if PLATFORM(MAC)
1306     Document* document = contextDocument();
1307     if (!document || !document->frame()) {
1308         ec = INVALID_ACCESS_ERR;
1309         return nullptr;
1310     }
1311
1312     document->updateLayoutIgnorePendingStylesheets();
1313     
1314     HitTestResult result = document->frame()->mainFrame().eventHandler().hitTestResultAtPoint(IntPoint(x, y));
1315     NSDictionary *options = nullptr;
1316     return DictionaryLookup::rangeAtHitTestResult(result, &options);
1317 #else
1318     UNUSED_PARAM(x);
1319     UNUSED_PARAM(y);
1320     ec = INVALID_ACCESS_ERR;
1321     return nullptr;
1322 #endif
1323 }
1324
1325 void Internals::setDelegatesScrolling(bool enabled, ExceptionCode& ec)
1326 {
1327     Document* document = contextDocument();
1328     // Delegate scrolling is valid only on mainframe's view.
1329     if (!document || !document->view() || !document->page() || &document->page()->mainFrame() != document->frame()) {
1330         ec = INVALID_ACCESS_ERR;
1331         return;
1332     }
1333
1334     document->view()->setDelegatesScrolling(enabled);
1335 }
1336
1337 int Internals::lastSpellCheckRequestSequence(ExceptionCode& ec)
1338 {
1339     Document* document = contextDocument();
1340     if (!document || !document->frame()) {
1341         ec = INVALID_ACCESS_ERR;
1342         return -1;
1343     }
1344
1345     return document->frame()->editor().spellChecker().lastRequestSequence();
1346 }
1347
1348 int Internals::lastSpellCheckProcessedSequence(ExceptionCode& ec)
1349 {
1350     Document* document = contextDocument();
1351     if (!document || !document->frame()) {
1352         ec = INVALID_ACCESS_ERR;
1353         return -1;
1354     }
1355
1356     return document->frame()->editor().spellChecker().lastProcessedSequence();
1357 }
1358
1359 Vector<String> Internals::userPreferredLanguages() const
1360 {
1361     return WebCore::userPreferredLanguages();
1362 }
1363
1364 void Internals::setUserPreferredLanguages(const Vector<String>& languages)
1365 {
1366     WebCore::overrideUserPreferredLanguages(languages);
1367 }
1368
1369 Vector<String> Internals::userPreferredAudioCharacteristics() const
1370 {
1371     Document* document = contextDocument();
1372     if (!document || !document->page())
1373         return Vector<String>();
1374 #if ENABLE(VIDEO_TRACK)
1375     return document->page()->group().captionPreferences().preferredAudioCharacteristics();
1376 #else
1377     return Vector<String>();
1378 #endif
1379 }
1380
1381 void Internals::setUserPreferredAudioCharacteristic(const String& characteristic)
1382 {
1383     Document* document = contextDocument();
1384     if (!document || !document->page())
1385         return;
1386 #if ENABLE(VIDEO_TRACK)
1387     document->page()->group().captionPreferences().setPreferredAudioCharacteristic(characteristic);
1388 #else
1389     UNUSED_PARAM(characteristic);
1390 #endif
1391 }
1392
1393 unsigned Internals::wheelEventHandlerCount(ExceptionCode& ec)
1394 {
1395     Document* document = contextDocument();
1396     if (!document) {
1397         ec = INVALID_ACCESS_ERR;
1398         return 0;
1399     }
1400
1401     return document->wheelEventHandlerCount();
1402 }
1403
1404 unsigned Internals::touchEventHandlerCount(ExceptionCode& ec)
1405 {
1406     Document* document = contextDocument();
1407     if (!document) {
1408         ec = INVALID_ACCESS_ERR;
1409         return 0;
1410     }
1411
1412     return document->touchEventHandlerCount();
1413 }
1414
1415 // FIXME: Remove the document argument. It is almost always the same as
1416 // contextDocument(), with the exception of a few tests that pass a
1417 // different document, and could just make the call through another Internals
1418 // instance instead.
1419 RefPtr<NodeList> Internals::nodesFromRect(Document& document, int centerX, int centerY, unsigned topPadding, unsigned rightPadding,
1420     unsigned bottomPadding, unsigned leftPadding, bool ignoreClipping, bool allowShadowContent, bool allowChildFrameContent, ExceptionCode& ec) const
1421 {
1422     if (!document.frame() || !document.frame()->view()) {
1423         ec = INVALID_ACCESS_ERR;
1424         return nullptr;
1425     }
1426
1427     Frame* frame = document.frame();
1428     FrameView* frameView = document.view();
1429     RenderView* renderView = document.renderView();
1430     if (!renderView)
1431         return nullptr;
1432
1433     document.updateLayoutIgnorePendingStylesheets();
1434
1435     float zoomFactor = frame->pageZoomFactor();
1436     LayoutPoint point(centerX * zoomFactor + frameView->scrollX(), centerY * zoomFactor + frameView->scrollY());
1437
1438     HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active;
1439     if (ignoreClipping)
1440         hitType |= HitTestRequest::IgnoreClipping;
1441     if (!allowShadowContent)
1442         hitType |= HitTestRequest::DisallowShadowContent;
1443     if (allowChildFrameContent)
1444         hitType |= HitTestRequest::AllowChildFrameContent;
1445
1446     HitTestRequest request(hitType);
1447
1448     // When ignoreClipping is false, this method returns null for coordinates outside of the viewport.
1449     if (!request.ignoreClipping() && !frameView->visibleContentRect().intersects(HitTestLocation::rectForPoint(point, topPadding, rightPadding, bottomPadding, leftPadding)))
1450         return nullptr;
1451
1452     Vector<Ref<Node>> matches;
1453
1454     // Need padding to trigger a rect based hit test, but we want to return a NodeList
1455     // so we special case this.
1456     if (!topPadding && !rightPadding && !bottomPadding && !leftPadding) {
1457         HitTestResult result(point);
1458         renderView->hitTest(request, result);
1459         if (result.innerNode())
1460             matches.append(*result.innerNode()->deprecatedShadowAncestorNode());
1461     } else {
1462         HitTestResult result(point, topPadding, rightPadding, bottomPadding, leftPadding);
1463         renderView->hitTest(request, result);
1464         
1465         const HitTestResult::NodeSet& nodeSet = result.rectBasedTestResult();
1466         matches.reserveInitialCapacity(nodeSet.size());
1467         for (auto& node : nodeSet)
1468             matches.uncheckedAppend(*node);
1469     }
1470
1471     return StaticNodeList::adopt(matches);
1472 }
1473
1474 class GetCallerCodeBlockFunctor {
1475 public:
1476     GetCallerCodeBlockFunctor()
1477         : m_iterations(0)
1478         , m_codeBlock(0)
1479     {
1480     }
1481
1482     StackVisitor::Status operator()(StackVisitor& visitor) const
1483     {
1484         ++m_iterations;
1485         if (m_iterations < 2)
1486             return StackVisitor::Continue;
1487
1488         m_codeBlock = visitor->codeBlock();
1489         return StackVisitor::Done;
1490     }
1491
1492     CodeBlock* codeBlock() const { return m_codeBlock; }
1493
1494 private:
1495     mutable int m_iterations;
1496     mutable CodeBlock* m_codeBlock;
1497 };
1498
1499 String Internals::parserMetaData(JSC::JSValue code)
1500 {
1501     JSC::VM& vm = contextDocument()->vm();
1502     JSC::ExecState* exec = vm.topCallFrame;
1503     ScriptExecutable* executable;
1504
1505     if (!code || code.isNull() || code.isUndefined()) {
1506         GetCallerCodeBlockFunctor iter;
1507         exec->iterate(iter);
1508         CodeBlock* codeBlock = iter.codeBlock();
1509         executable = codeBlock->ownerScriptExecutable();
1510     } else if (code.isFunction()) {
1511         JSFunction* funcObj = JSC::jsCast<JSFunction*>(code.toObject(exec));
1512         executable = funcObj->jsExecutable();
1513     } else
1514         return String();
1515
1516     unsigned startLine = executable->firstLine();
1517     unsigned startColumn = executable->startColumn();
1518     unsigned endLine = executable->lastLine();
1519     unsigned endColumn = executable->endColumn();
1520
1521     StringBuilder result;
1522
1523     if (executable->isFunctionExecutable()) {
1524         FunctionExecutable* funcExecutable = reinterpret_cast<FunctionExecutable*>(executable);
1525         String inferredName = funcExecutable->inferredName().string();
1526         result.appendLiteral("function \"");
1527         result.append(inferredName);
1528         result.append('"');
1529     } else if (executable->isEvalExecutable())
1530         result.appendLiteral("eval");
1531     else if (executable->isModuleProgramExecutable())
1532         result.appendLiteral("module");
1533     else if (executable->isProgramExecutable())
1534         result.appendLiteral("program");
1535 #if ENABLE(WEBASSEMBLY)
1536     else if (executable->isWebAssemblyExecutable())
1537         result.appendLiteral("WebAssembly");
1538 #endif
1539     else
1540         ASSERT_NOT_REACHED();
1541
1542     result.appendLiteral(" { ");
1543     result.appendNumber(startLine);
1544     result.append(':');
1545     result.appendNumber(startColumn);
1546     result.appendLiteral(" - ");
1547     result.appendNumber(endLine);
1548     result.append(':');
1549     result.appendNumber(endColumn);
1550     result.appendLiteral(" }");
1551
1552     return result.toString();
1553 }
1554
1555 void Internals::setBatteryStatus(const String& eventType, bool charging, double chargingTime, double dischargingTime, double level, ExceptionCode& ec)
1556 {
1557     Document* document = contextDocument();
1558     if (!document || !document->page()) {
1559         ec = INVALID_ACCESS_ERR;
1560         return;
1561     }
1562
1563 #if ENABLE(BATTERY_STATUS)
1564     BatteryController::from(document->page())->didChangeBatteryStatus(eventType, BatteryStatus::create(charging, chargingTime, dischargingTime, level));
1565 #else
1566     UNUSED_PARAM(eventType);
1567     UNUSED_PARAM(charging);
1568     UNUSED_PARAM(chargingTime);
1569     UNUSED_PARAM(dischargingTime);
1570     UNUSED_PARAM(level);
1571 #endif
1572 }
1573
1574 void Internals::setDeviceProximity(const String& eventType, double value, double min, double max, ExceptionCode& ec)
1575 {
1576     Document* document = contextDocument();
1577     if (!document || !document->page()) {
1578         ec = INVALID_ACCESS_ERR;
1579         return;
1580     }
1581
1582 #if ENABLE(PROXIMITY_EVENTS)
1583     DeviceProximityController::from(document->page())->didChangeDeviceProximity(value, min, max);
1584 #else
1585     UNUSED_PARAM(eventType);
1586     UNUSED_PARAM(value);
1587     UNUSED_PARAM(min);
1588     UNUSED_PARAM(max);
1589 #endif
1590 }
1591
1592 void Internals::updateEditorUINowIfScheduled()
1593 {
1594     if (Document* document = contextDocument()) {
1595         if (Frame* frame = document->frame())
1596             frame->editor().updateEditorUINowIfScheduled();
1597     }
1598 }
1599
1600 bool Internals::hasSpellingMarker(int from, int length, ExceptionCode&)
1601 {
1602     Document* document = contextDocument();
1603     if (!document || !document->frame())
1604         return false;
1605
1606     updateEditorUINowIfScheduled();
1607
1608     return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
1609 }
1610     
1611 bool Internals::hasAutocorrectedMarker(int from, int length, ExceptionCode&)
1612 {
1613     Document* document = contextDocument();
1614     if (!document || !document->frame())
1615         return false;
1616
1617     updateEditorUINowIfScheduled();
1618
1619     return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Autocorrected, from, length);
1620 }
1621
1622 void Internals::setContinuousSpellCheckingEnabled(bool enabled, ExceptionCode&)
1623 {
1624     if (!contextDocument() || !contextDocument()->frame())
1625         return;
1626
1627     if (enabled != contextDocument()->frame()->editor().isContinuousSpellCheckingEnabled())
1628         contextDocument()->frame()->editor().toggleContinuousSpellChecking();
1629 }
1630
1631 void Internals::setAutomaticQuoteSubstitutionEnabled(bool enabled, ExceptionCode&)
1632 {
1633     if (!contextDocument() || !contextDocument()->frame())
1634         return;
1635
1636 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1637     if (enabled != contextDocument()->frame()->editor().isAutomaticQuoteSubstitutionEnabled())
1638         contextDocument()->frame()->editor().toggleAutomaticQuoteSubstitution();
1639 #else
1640     UNUSED_PARAM(enabled);
1641 #endif
1642 }
1643
1644 void Internals::setAutomaticLinkDetectionEnabled(bool enabled, ExceptionCode&)
1645 {
1646     if (!contextDocument() || !contextDocument()->frame())
1647         return;
1648
1649 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1650     if (enabled != contextDocument()->frame()->editor().isAutomaticLinkDetectionEnabled())
1651         contextDocument()->frame()->editor().toggleAutomaticLinkDetection();
1652 #else
1653     UNUSED_PARAM(enabled);
1654 #endif
1655 }
1656
1657 void Internals::setAutomaticDashSubstitutionEnabled(bool enabled, ExceptionCode&)
1658 {
1659     if (!contextDocument() || !contextDocument()->frame())
1660         return;
1661
1662 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1663     if (enabled != contextDocument()->frame()->editor().isAutomaticDashSubstitutionEnabled())
1664         contextDocument()->frame()->editor().toggleAutomaticDashSubstitution();
1665 #else
1666     UNUSED_PARAM(enabled);
1667 #endif
1668 }
1669
1670 void Internals::setAutomaticTextReplacementEnabled(bool enabled, ExceptionCode&)
1671 {
1672     if (!contextDocument() || !contextDocument()->frame())
1673         return;
1674
1675 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1676     if (enabled != contextDocument()->frame()->editor().isAutomaticTextReplacementEnabled())
1677         contextDocument()->frame()->editor().toggleAutomaticTextReplacement();
1678 #else
1679     UNUSED_PARAM(enabled);
1680 #endif
1681 }
1682
1683 void Internals::setAutomaticSpellingCorrectionEnabled(bool enabled, ExceptionCode&)
1684 {
1685     if (!contextDocument() || !contextDocument()->frame())
1686         return;
1687
1688 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1689     if (enabled != contextDocument()->frame()->editor().isAutomaticSpellingCorrectionEnabled())
1690         contextDocument()->frame()->editor().toggleAutomaticSpellingCorrection();
1691 #else
1692     UNUSED_PARAM(enabled);
1693 #endif
1694 }
1695
1696 void Internals::handleAcceptedCandidate(const String& candidate, ExceptionCode&)
1697 {
1698     if (!contextDocument() || !contextDocument()->frame())
1699         return;
1700
1701     TextCheckingResult result;
1702     result.type = TextCheckingTypeNone;
1703     result.length = candidate.length();
1704     result.replacement = candidate;
1705     contextDocument()->frame()->editor().handleAcceptedCandidate(result);
1706 }
1707
1708 bool Internals::isOverwriteModeEnabled(ExceptionCode&)
1709 {
1710     Document* document = contextDocument();
1711     if (!document || !document->frame())
1712         return false;
1713
1714     return document->frame()->editor().isOverwriteModeEnabled();
1715 }
1716
1717 void Internals::toggleOverwriteModeEnabled(ExceptionCode&)
1718 {
1719     Document* document = contextDocument();
1720     if (!document || !document->frame())
1721         return;
1722
1723     document->frame()->editor().toggleOverwriteModeEnabled();
1724 }
1725
1726 unsigned Internals::countMatchesForText(const String& text, unsigned findOptions, const String& markMatches, ExceptionCode&)
1727 {
1728     Document* document = contextDocument();
1729     if (!document || !document->frame())
1730         return 0;
1731
1732     bool mark = markMatches == "mark";
1733     return document->frame()->editor().countMatchesForText(text, nullptr, findOptions, 1000, mark, nullptr);
1734 }
1735
1736 const ProfilesArray& Internals::consoleProfiles() const
1737 {
1738     return contextDocument()->page()->console().profiles();
1739 }
1740
1741 unsigned Internals::numberOfLiveNodes() const
1742 {
1743     unsigned nodeCount = 0;
1744     for (auto* document : Document::allDocuments())
1745         nodeCount += document->referencingNodeCount();
1746     return nodeCount;
1747 }
1748
1749 unsigned Internals::numberOfLiveDocuments() const
1750 {
1751     return Document::allDocuments().size();
1752 }
1753
1754 RefPtr<DOMWindow> Internals::openDummyInspectorFrontend(const String& url)
1755 {
1756     Page* inspectedPage = contextDocument()->frame()->page();
1757     RefPtr<DOMWindow> window = inspectedPage->mainFrame().document()->domWindow();
1758     RefPtr<DOMWindow> frontendWindow = window->open(url, "", "", *window, *window);
1759     m_inspectorFrontend = std::make_unique<InspectorStubFrontend>(*inspectedPage, frontendWindow.copyRef());
1760
1761     return frontendWindow;
1762 }
1763
1764 void Internals::closeDummyInspectorFrontend()
1765 {
1766     m_inspectorFrontend = nullptr;
1767 }
1768
1769 void Internals::setLegacyJavaScriptProfilingEnabled(bool enabled, ExceptionCode& ec)
1770 {
1771     Page* page = contextDocument()->frame()->page();
1772     if (!page) {
1773         ec = INVALID_ACCESS_ERR;
1774         return;
1775     }
1776
1777     page->inspectorController().setLegacyProfilerEnabled(enabled);
1778 }
1779
1780 void Internals::setInspectorIsUnderTest(bool isUnderTest, ExceptionCode& ec)
1781 {
1782     Page* page = contextDocument()->frame()->page();
1783     if (!page) {
1784         ec = INVALID_ACCESS_ERR;
1785         return;
1786     }
1787
1788     page->inspectorController().setIsUnderTest(isUnderTest);
1789 }
1790
1791 bool Internals::hasGrammarMarker(int from, int length, ExceptionCode&)
1792 {
1793     Document* document = contextDocument();
1794     if (!document || !document->frame())
1795         return false;
1796
1797     return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Grammar, from, length);
1798 }
1799
1800 unsigned Internals::numberOfScrollableAreas(ExceptionCode&)
1801 {
1802     Document* document = contextDocument();
1803     if (!document || !document->frame())
1804         return 0;
1805
1806     unsigned count = 0;
1807     Frame* frame = document->frame();
1808     if (frame->view()->scrollableAreas())
1809         count += frame->view()->scrollableAreas()->size();
1810
1811     for (Frame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
1812         if (child->view() && child->view()->scrollableAreas())
1813             count += child->view()->scrollableAreas()->size();
1814     }
1815
1816     return count;
1817 }
1818     
1819 bool Internals::isPageBoxVisible(int pageNumber, ExceptionCode& ec)
1820 {
1821     Document* document = contextDocument();
1822     if (!document) {
1823         ec = INVALID_ACCESS_ERR;
1824         return false;
1825     }
1826
1827     return document->isPageBoxVisible(pageNumber);
1828 }
1829
1830 // FIXME: Remove the document argument. It is almost always the same as
1831 // contextDocument(), with the exception of a few tests that pass a
1832 // different document, and could just make the call through another Internals
1833 // instance instead.
1834 String Internals::layerTreeAsText(Document& document, unsigned short flags, ExceptionCode& ec) const
1835 {
1836     if (!document.frame()) {
1837         ec = INVALID_ACCESS_ERR;
1838         return String();
1839     }
1840
1841     LayerTreeFlags layerTreeFlags = 0;
1842     if (flags & LAYER_TREE_INCLUDES_VISIBLE_RECTS)
1843         layerTreeFlags |= LayerTreeFlagsIncludeVisibleRects;
1844     if (flags & LAYER_TREE_INCLUDES_TILE_CACHES)
1845         layerTreeFlags |= LayerTreeFlagsIncludeTileCaches;
1846     if (flags & LAYER_TREE_INCLUDES_REPAINT_RECTS)
1847         layerTreeFlags |= LayerTreeFlagsIncludeRepaintRects;
1848     if (flags & LAYER_TREE_INCLUDES_PAINTING_PHASES)
1849         layerTreeFlags |= LayerTreeFlagsIncludePaintingPhases;
1850     if (flags & LAYER_TREE_INCLUDES_CONTENT_LAYERS)
1851         layerTreeFlags |= LayerTreeFlagsIncludeContentLayers;
1852
1853     return document.frame()->layerTreeAsText(layerTreeFlags);
1854 }
1855
1856 String Internals::repaintRectsAsText(ExceptionCode& ec) const
1857 {
1858     Document* document = contextDocument();
1859     if (!document || !document->frame()) {
1860         ec = INVALID_ACCESS_ERR;
1861         return String();
1862     }
1863
1864     return document->frame()->trackedRepaintRectsAsText();
1865 }
1866
1867 String Internals::scrollingStateTreeAsText(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->scrollingStateTreeAsText();
1880 }
1881
1882 String Internals::mainThreadScrollingReasons(ExceptionCode& ec) const
1883 {
1884     Document* document = contextDocument();
1885     if (!document || !document->frame()) {
1886         ec = INVALID_ACCESS_ERR;
1887         return String();
1888     }
1889
1890     Page* page = document->page();
1891     if (!page)
1892         return String();
1893
1894     return page->synchronousScrollingReasonsAsText();
1895 }
1896
1897 RefPtr<ClientRectList> Internals::nonFastScrollableRects(ExceptionCode& ec) const
1898 {
1899     Document* document = contextDocument();
1900     if (!document || !document->frame()) {
1901         ec = INVALID_ACCESS_ERR;
1902         return nullptr;
1903     }
1904
1905     Page* page = document->page();
1906     if (!page)
1907         return nullptr;
1908
1909     return page->nonFastScrollableRects();
1910 }
1911
1912 void Internals::setElementUsesDisplayListDrawing(Element& element, bool usesDisplayListDrawing, ExceptionCode& ec)
1913 {
1914     Document* document = contextDocument();
1915     if (!document || !document->renderView()) {
1916         ec = INVALID_ACCESS_ERR;
1917         return;
1918     }
1919
1920     if (!element.renderer()) {
1921         ec = INVALID_ACCESS_ERR;
1922         return;
1923     }
1924
1925     if (is<HTMLCanvasElement>(element)) {
1926         downcast<HTMLCanvasElement>(element).setUsesDisplayListDrawing(usesDisplayListDrawing);
1927         return;
1928     }
1929
1930     if (!element.renderer()->hasLayer()) {
1931         ec = INVALID_ACCESS_ERR;
1932         return;
1933     }
1934     
1935     RenderLayer* layer = downcast<RenderLayerModelObject>(element.renderer())->layer();
1936     if (!layer->isComposited()) {
1937         ec = INVALID_ACCESS_ERR;
1938         return;
1939     }
1940     
1941     layer->backing()->setUsesDisplayListDrawing(usesDisplayListDrawing);
1942 }
1943
1944 void Internals::setElementTracksDisplayListReplay(Element& element, bool isTrackingReplay, ExceptionCode& ec)
1945 {
1946     Document* document = contextDocument();
1947     if (!document || !document->renderView()) {
1948         ec = INVALID_ACCESS_ERR;
1949         return;
1950     }
1951
1952     if (!element.renderer()) {
1953         ec = INVALID_ACCESS_ERR;
1954         return;
1955     }
1956
1957     if (is<HTMLCanvasElement>(element)) {
1958         downcast<HTMLCanvasElement>(element).setTracksDisplayListReplay(isTrackingReplay);
1959         return;
1960     }
1961
1962     if (!element.renderer()->hasLayer()) {
1963         ec = INVALID_ACCESS_ERR;
1964         return;
1965     }
1966
1967     RenderLayer* layer = downcast<RenderLayerModelObject>(element.renderer())->layer();
1968     if (!layer->isComposited()) {
1969         ec = INVALID_ACCESS_ERR;
1970         return;
1971     }
1972     
1973     layer->backing()->setIsTrackingDisplayListReplay(isTrackingReplay);
1974 }
1975
1976 String Internals::displayListForElement(Element& element, unsigned short flags, ExceptionCode& ec)
1977 {
1978     Document* document = contextDocument();
1979     if (!document || !document->renderView()) {
1980         ec = INVALID_ACCESS_ERR;
1981         return String();
1982     }
1983
1984     if (!element.renderer()) {
1985         ec = INVALID_ACCESS_ERR;
1986         return String();
1987     }
1988
1989     DisplayList::AsTextFlags displayListFlags = 0;
1990     if (flags & DISPLAY_LIST_INCLUDES_PLATFORM_OPERATIONS)
1991         displayListFlags |= DisplayList::AsTextFlag::IncludesPlatformOperations;
1992
1993     if (is<HTMLCanvasElement>(element))
1994         return downcast<HTMLCanvasElement>(element).displayListAsText(displayListFlags);
1995
1996     if (!element.renderer()->hasLayer()) {
1997         ec = INVALID_ACCESS_ERR;
1998         return String();
1999     }
2000
2001     RenderLayer* layer = downcast<RenderLayerModelObject>(element.renderer())->layer();
2002     if (!layer->isComposited()) {
2003         ec = INVALID_ACCESS_ERR;
2004         return String();
2005     }
2006
2007     return layer->backing()->displayListAsText(displayListFlags);
2008 }
2009
2010 String Internals::replayDisplayListForElement(Element& element, unsigned short flags, ExceptionCode& ec)
2011 {
2012     Document* document = contextDocument();
2013     if (!document || !document->renderView()) {
2014         ec = INVALID_ACCESS_ERR;
2015         return String();
2016     }
2017
2018     if (!element.renderer()) {
2019         ec = INVALID_ACCESS_ERR;
2020         return String();
2021     }
2022
2023     DisplayList::AsTextFlags displayListFlags = 0;
2024     if (flags & DISPLAY_LIST_INCLUDES_PLATFORM_OPERATIONS)
2025         displayListFlags |= DisplayList::AsTextFlag::IncludesPlatformOperations;
2026
2027     if (is<HTMLCanvasElement>(element))
2028         return downcast<HTMLCanvasElement>(element).replayDisplayListAsText(displayListFlags);
2029
2030     if (!element.renderer()->hasLayer()) {
2031         ec = INVALID_ACCESS_ERR;
2032         return String();
2033     }
2034
2035     RenderLayer* layer = downcast<RenderLayerModelObject>(element.renderer())->layer();
2036     if (!layer->isComposited()) {
2037         ec = INVALID_ACCESS_ERR;
2038         return String();
2039     }
2040
2041     return layer->backing()->replayDisplayListAsText(displayListFlags);
2042 }
2043
2044 void Internals::garbageCollectDocumentResources(ExceptionCode& ec) const
2045 {
2046     Document* document = contextDocument();
2047     if (!document) {
2048         ec = INVALID_ACCESS_ERR;
2049         return;
2050     }
2051     document->cachedResourceLoader().garbageCollectDocumentResources();
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 && endTimes);
2693     ASSERT(startTimes->length() == endTimes->length());
2694     Ref<TimeRanges> ranges = TimeRanges::create();
2695
2696     unsigned count = std::min(startTimes->length(), endTimes->length());
2697     for (unsigned i = 0; i < count; ++i)
2698         ranges->add(startTimes->item(i), endTimes->item(i));
2699     return ranges;
2700 }
2701
2702 double Internals::closestTimeToTimeRanges(double time, TimeRanges& ranges)
2703 {
2704     return ranges.nearest(time);
2705 }
2706 #endif
2707
2708 Ref<ClientRect> Internals::selectionBounds(ExceptionCode& ec)
2709 {
2710     Document* document = contextDocument();
2711     if (!document || !document->frame()) {
2712         ec = INVALID_ACCESS_ERR;
2713         return ClientRect::create();
2714     }
2715
2716     return ClientRect::create(document->frame()->selection().selectionBounds());
2717 }
2718
2719 #if ENABLE(VIBRATION)
2720 bool Internals::isVibrating()
2721 {
2722     Page* page = contextDocument()->page();
2723     ASSERT(page);
2724
2725     return Vibration::from(page)->isVibrating();
2726 }
2727 #endif
2728
2729 bool Internals::isPluginUnavailabilityIndicatorObscured(Element& element, ExceptionCode& ec)
2730 {
2731     auto* renderer = element.renderer();
2732     if (!is<RenderEmbeddedObject>(renderer)) {
2733         ec = INVALID_ACCESS_ERR;
2734         return false;
2735     }
2736
2737     return downcast<RenderEmbeddedObject>(*renderer).isReplacementObscured();
2738 }
2739     
2740 bool Internals::isPluginSnapshotted(Element& element)
2741 {
2742     return is<HTMLPlugInElement>(element) && downcast<HTMLPlugInElement>(element).displayState() <= HTMLPlugInElement::DisplayingSnapshot;
2743 }
2744     
2745 #if ENABLE(MEDIA_SOURCE)
2746
2747 void Internals::initializeMockMediaSource()
2748 {
2749     MediaPlayerFactorySupport::callRegisterMediaEngine(MockMediaPlayerMediaSource::registerMediaEngine);
2750 }
2751
2752 Vector<String> Internals::bufferedSamplesForTrackID(SourceBuffer& buffer, const AtomicString& trackID)
2753 {
2754     return buffer.bufferedSamplesForTrackID(trackID);
2755 }
2756     
2757 void Internals::setShouldGenerateTimestamps(SourceBuffer& buffer, bool flag)
2758 {
2759     buffer.setShouldGenerateTimestamps(flag);
2760 }
2761
2762 #endif
2763
2764 #if ENABLE(VIDEO)
2765
2766 void Internals::beginMediaSessionInterruption(const String& interruptionString, ExceptionCode& ec)
2767 {
2768     PlatformMediaSession::InterruptionType interruption = PlatformMediaSession::SystemInterruption;
2769
2770     if (equalLettersIgnoringASCIICase(interruptionString, "system"))
2771         interruption = PlatformMediaSession::SystemInterruption;
2772     else if (equalLettersIgnoringASCIICase(interruptionString, "systemsleep"))
2773         interruption = PlatformMediaSession::SystemSleep;
2774     else if (equalLettersIgnoringASCIICase(interruptionString, "enteringbackground"))
2775         interruption = PlatformMediaSession::EnteringBackground;
2776     else {
2777         ec = INVALID_ACCESS_ERR;
2778         return;
2779     }
2780
2781     PlatformMediaSessionManager::sharedManager().beginInterruption(interruption);
2782 }
2783
2784 void Internals::endMediaSessionInterruption(const String& flagsString)
2785 {
2786     PlatformMediaSession::EndInterruptionFlags flags = PlatformMediaSession::NoFlags;
2787
2788     if (equalLettersIgnoringASCIICase(flagsString, "mayresumeplaying"))
2789         flags = PlatformMediaSession::MayResumePlaying;
2790     
2791     PlatformMediaSessionManager::sharedManager().endInterruption(flags);
2792 }
2793
2794 void Internals::applicationDidEnterForeground() const
2795 {
2796     PlatformMediaSessionManager::sharedManager().applicationDidEnterForeground();
2797 }
2798
2799 void Internals::applicationWillEnterBackground() const
2800 {
2801     PlatformMediaSessionManager::sharedManager().applicationWillEnterBackground();
2802 }
2803
2804 void Internals::setMediaSessionRestrictions(const String& mediaTypeString, const String& restrictionsString, ExceptionCode& ec)
2805 {
2806     PlatformMediaSession::MediaType mediaType = PlatformMediaSession::None;
2807     if (equalLettersIgnoringASCIICase(mediaTypeString, "video"))
2808         mediaType = PlatformMediaSession::Video;
2809     else if (equalLettersIgnoringASCIICase(mediaTypeString, "audio"))
2810         mediaType = PlatformMediaSession::Audio;
2811     else if (equalLettersIgnoringASCIICase(mediaTypeString, "webaudio"))
2812         mediaType = PlatformMediaSession::WebAudio;
2813     else {
2814         ec = INVALID_ACCESS_ERR;
2815         return;
2816     }
2817
2818     PlatformMediaSessionManager::SessionRestrictions restrictions = PlatformMediaSessionManager::sharedManager().restrictions(mediaType);
2819     PlatformMediaSessionManager::sharedManager().removeRestriction(mediaType, restrictions);
2820
2821     restrictions = PlatformMediaSessionManager::NoRestrictions;
2822
2823     Vector<String> restrictionsArray;
2824     restrictionsString.split(',', false, restrictionsArray);
2825     for (auto& restrictionString : restrictionsArray) {
2826         if (equalLettersIgnoringASCIICase(restrictionString, "concurrentplaybacknotpermitted"))
2827             restrictions |= PlatformMediaSessionManager::ConcurrentPlaybackNotPermitted;
2828         if (equalLettersIgnoringASCIICase(restrictionString, "backgroundprocessplaybackrestricted"))
2829             restrictions |= PlatformMediaSessionManager::BackgroundProcessPlaybackRestricted;
2830         if (equalLettersIgnoringASCIICase(restrictionString, "backgroundtabplaybackrestricted"))
2831             restrictions |= PlatformMediaSessionManager::BackgroundTabPlaybackRestricted;
2832         if (equalLettersIgnoringASCIICase(restrictionString, "interruptedplaybacknotpermitted"))
2833             restrictions |= PlatformMediaSessionManager::InterruptedPlaybackNotPermitted;
2834     }
2835     PlatformMediaSessionManager::sharedManager().addRestriction(mediaType, restrictions);
2836 }
2837
2838 void Internals::setMediaElementRestrictions(HTMLMediaElement& element, const String& restrictionsString)
2839 {
2840     MediaElementSession::BehaviorRestrictions restrictions = element.mediaSession().behaviorRestrictions();
2841     element.mediaSession().removeBehaviorRestriction(restrictions);
2842
2843     restrictions = MediaElementSession::NoRestrictions;
2844
2845     Vector<String> restrictionsArray;
2846     restrictionsString.split(',', false, restrictionsArray);
2847     for (auto& restrictionString : restrictionsArray) {
2848         if (equalLettersIgnoringASCIICase(restrictionString, "norestrictions"))
2849             restrictions |= MediaElementSession::NoRestrictions;
2850         if (equalLettersIgnoringASCIICase(restrictionString, "requireusergestureforload"))
2851             restrictions |= MediaElementSession::RequireUserGestureForLoad;
2852         if (equalLettersIgnoringASCIICase(restrictionString, "requireusergestureforvideoratechange"))
2853             restrictions |= MediaElementSession::RequireUserGestureForVideoRateChange;
2854         if (equalLettersIgnoringASCIICase(restrictionString, "requireusergestureforfullscreen"))
2855             restrictions |= MediaElementSession::RequireUserGestureForFullscreen;
2856         if (equalLettersIgnoringASCIICase(restrictionString, "requirepageconsenttoloadmedia"))
2857             restrictions |= MediaElementSession::RequirePageConsentToLoadMedia;
2858         if (equalLettersIgnoringASCIICase(restrictionString, "requirepageconsenttoresumemedia"))
2859             restrictions |= MediaElementSession::RequirePageConsentToResumeMedia;
2860 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
2861         if (equalLettersIgnoringASCIICase(restrictionString, "requireusergesturetoshowplaybacktargetpicker"))
2862             restrictions |= MediaElementSession::RequireUserGestureToShowPlaybackTargetPicker;
2863         if (equalLettersIgnoringASCIICase(restrictionString, "wirelessvideoplaybackdisabled"))
2864             restrictions |= MediaElementSession::WirelessVideoPlaybackDisabled;
2865 #endif
2866         if (equalLettersIgnoringASCIICase(restrictionString, "requireusergestureforaudioratechange"))
2867             restrictions |= MediaElementSession::RequireUserGestureForAudioRateChange;
2868         if (equalLettersIgnoringASCIICase(restrictionString, "metadatapreloadingnotpermitted"))
2869             restrictions |= MediaElementSession::MetadataPreloadingNotPermitted;
2870         if (equalLettersIgnoringASCIICase(restrictionString, "autopreloadingnotpermitted"))
2871             restrictions |= MediaElementSession::AutoPreloadingNotPermitted;
2872         if (equalLettersIgnoringASCIICase(restrictionString, "invisibleautoplaynotpermitted"))
2873             restrictions |= MediaElementSession::InvisibleAutoplayNotPermitted;
2874         if (equalLettersIgnoringASCIICase(restrictionString, "overrideusergesturerequirementformaincontent"))
2875             restrictions |= MediaElementSession::OverrideUserGestureRequirementForMainContent;
2876     }
2877     element.mediaSession().addBehaviorRestriction(restrictions);
2878 }
2879
2880 void Internals::postRemoteControlCommand(const String& commandString, ExceptionCode& ec)
2881 {
2882     PlatformMediaSession::RemoteControlCommandType command;
2883     
2884     if (equalLettersIgnoringASCIICase(commandString, "play"))
2885         command = PlatformMediaSession::PlayCommand;
2886     else if (equalLettersIgnoringASCIICase(commandString, "pause"))
2887         command = PlatformMediaSession::PauseCommand;
2888     else if (equalLettersIgnoringASCIICase(commandString, "stop"))
2889         command = PlatformMediaSession::StopCommand;
2890     else if (equalLettersIgnoringASCIICase(commandString, "toggleplaypause"))
2891         command = PlatformMediaSession::TogglePlayPauseCommand;
2892     else if (equalLettersIgnoringASCIICase(commandString, "beginseekingbackward"))
2893         command = PlatformMediaSession::BeginSeekingBackwardCommand;
2894     else if (equalLettersIgnoringASCIICase(commandString, "endseekingbackward"))
2895         command = PlatformMediaSession::EndSeekingBackwardCommand;
2896     else if (equalLettersIgnoringASCIICase(commandString, "beginseekingforward"))
2897         command = PlatformMediaSession::BeginSeekingForwardCommand;
2898     else if (equalLettersIgnoringASCIICase(commandString, "endseekingforward"))
2899         command = PlatformMediaSession::EndSeekingForwardCommand;
2900     else {
2901         ec = INVALID_ACCESS_ERR;
2902         return;
2903     }
2904     
2905     PlatformMediaSessionManager::sharedManager().didReceiveRemoteControlCommand(command);
2906 }
2907
2908 bool Internals::elementIsBlockingDisplaySleep(HTMLMediaElement& element) const
2909 {
2910     return element.isDisablingSleep();
2911 }
2912
2913 #endif // ENABLE(VIDEO)
2914
2915 #if ENABLE(MEDIA_SESSION)
2916
2917 void Internals::sendMediaSessionStartOfInterruptionNotification(MediaSessionInterruptingCategory category)
2918 {
2919     MediaSessionManager::singleton().didReceiveStartOfInterruptionNotification(category);
2920 }
2921
2922 void Internals::sendMediaSessionEndOfInterruptionNotification(MediaSessionInterruptingCategory category)
2923 {
2924     MediaSessionManager::singleton().didReceiveEndOfInterruptionNotification(category);
2925 }
2926
2927 String Internals::mediaSessionCurrentState(MediaSession* session) const
2928 {
2929     switch (session->currentState()) {
2930     case MediaSession::State::Active:
2931         return "active";
2932     case MediaSession::State::Interrupted:
2933         return "interrupted";
2934     case MediaSession::State::Idle:
2935         return "idle";
2936     }
2937 }
2938
2939 double Internals::mediaElementPlayerVolume(HTMLMediaElement* element) const
2940 {
2941     ASSERT_ARG(element, element);
2942     return element->playerVolume();
2943 }
2944
2945 void Internals::sendMediaControlEvent(MediaControlEvent event)
2946 {
2947     // FIXME: No good reason to use a single function with an argument instead of three functions.
2948     switch (event) {
2949     case MediControlEvent::PlayPause:
2950         MediaSessionManager::singleton().togglePlayback();
2951         break;
2952     case MediControlEvent::NextTrack:
2953         MediaSessionManager::singleton().skipToNextTrack();
2954         break;
2955     case MediControlEvent::PreviousTrack:
2956         MediaSessionManager::singleton().skipToPreviousTrack();
2957         break;
2958     }
2959 }
2960
2961 #endif // ENABLE(MEDIA_SESSION)
2962
2963 #if ENABLE(WEB_AUDIO)
2964
2965 void Internals::setAudioContextRestrictions(AudioContext& context, const String& restrictionsString)
2966 {
2967     AudioContext::BehaviorRestrictions restrictions = context.behaviorRestrictions();
2968     context.removeBehaviorRestriction(restrictions);
2969
2970     restrictions = AudioContext::NoRestrictions;
2971
2972     Vector<String> restrictionsArray;
2973     restrictionsString.split(',', false, restrictionsArray);
2974     for (auto& restrictionString : restrictionsArray) {
2975         if (equalLettersIgnoringASCIICase(restrictionString, "norestrictions"))
2976             restrictions |= AudioContext::NoRestrictions;
2977         if (equalLettersIgnoringASCIICase(restrictionString, "requireusergestureforaudiostart"))
2978             restrictions |= AudioContext::RequireUserGestureForAudioStartRestriction;
2979         if (equalLettersIgnoringASCIICase(restrictionString, "requirepageconsentforaudiostart"))
2980             restrictions |= AudioContext::RequirePageConsentForAudioStartRestriction;
2981     }
2982     context.addBehaviorRestriction(restrictions);
2983 }
2984
2985 #endif
2986
2987 void Internals::simulateSystemSleep() const
2988 {
2989 #if ENABLE(VIDEO)
2990     PlatformMediaSessionManager::sharedManager().systemWillSleep();
2991 #endif
2992 }
2993
2994 void Internals::simulateSystemWake() const
2995 {
2996 #if ENABLE(VIDEO)
2997     PlatformMediaSessionManager::sharedManager().systemDidWake();
2998 #endif
2999 }
3000
3001 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
3002
3003 void Internals::setMockMediaPlaybackTargetPickerEnabled(bool enabled)
3004 {
3005     Page* page = contextDocument()->frame()->page();
3006     ASSERT(page);
3007
3008     page->setMockMediaPlaybackTargetPickerEnabled(enabled);
3009 }
3010
3011 void Internals::setMockMediaPlaybackTargetPickerState(const String& deviceName, const String& deviceState, ExceptionCode& ec)
3012 {
3013     Page* page = contextDocument()->frame()->page();
3014     ASSERT(page);
3015
3016     MediaPlaybackTargetContext::State state = MediaPlaybackTargetContext::Unknown;
3017
3018     if (equalLettersIgnoringASCIICase(deviceState, "deviceavailable"))
3019         state = MediaPlaybackTargetContext::OutputDeviceAvailable;
3020     else if (equalLettersIgnoringASCIICase(deviceState, "deviceunavailable"))
3021         state = MediaPlaybackTargetContext::OutputDeviceUnavailable;
3022     else if (equalLettersIgnoringASCIICase(deviceState, "unknown"))
3023         state = MediaPlaybackTargetContext::Unknown;
3024     else {
3025         ec = INVALID_ACCESS_ERR;
3026         return;
3027     }
3028
3029     page->setMockMediaPlaybackTargetPickerState(deviceName, state);
3030 }
3031
3032 #endif
3033
3034 RefPtr<MockPageOverlay> Internals::installMockPageOverlay(PageOverlayType type, ExceptionCode& ec)
3035 {
3036     Document* document = contextDocument();
3037     if (!document || !document->frame()) {
3038         ec = INVALID_ACCESS_ERR;
3039         return nullptr;
3040     }
3041
3042     return MockPageOverlayClient::singleton().installOverlay(document->frame()->mainFrame(), type == PageOverlayType::View ? PageOverlay::OverlayType::View : PageOverlay::OverlayType::Document);
3043 }
3044
3045 String Internals::pageOverlayLayerTreeAsText(ExceptionCode& ec) const
3046 {
3047     Document* document = contextDocument();
3048     if (!document || !document->frame()) {
3049         ec = INVALID_ACCESS_ERR;
3050         return String();
3051     }
3052
3053     document->updateLayout();
3054
3055     return MockPageOverlayClient::singleton().layerTreeAsText(document->frame()->mainFrame());
3056 }
3057
3058 void Internals::setPageMuted(bool muted)
3059 {
3060     Document* document = contextDocument();
3061     if (!document)
3062         return;
3063
3064     if (Page* page = document->page())
3065         page->setMuted(muted);
3066 }
3067
3068 bool Internals::isPagePlayingAudio()
3069 {
3070     Document* document = contextDocument();
3071     if (!document || !document->page())
3072         return false;
3073
3074     return !!(document->page()->mediaState() & MediaProducer::IsPlayingAudio);
3075 }
3076
3077 void Internals::setPageDefersLoading(bool defersLoading)
3078 {
3079     Document* document = contextDocument();
3080     if (!document)
3081         return;
3082     if (Page* page = document->page())
3083         page->setDefersLoading(defersLoading);
3084 }
3085
3086 RefPtr<File> Internals::createFile(const String& path)
3087 {
3088     Document* document = contextDocument();
3089     if (!document)
3090         return nullptr;
3091
3092     URL url = document->completeURL(path);
3093     if (!url.isLocalFile())
3094         return nullptr;
3095
3096     return File::create(url.fileSystemPath());
3097 }
3098
3099 void Internals::queueMicroTask(int testNumber)
3100 {
3101     Document* document = contextDocument();
3102     if (!document)
3103         return;
3104
3105     auto microtask = std::make_unique<ActiveDOMCallbackMicrotask>(MicrotaskQueue::mainThreadQueue(), *document, [document, testNumber]() {
3106         document->addConsoleMessage(MessageSource::JS, MessageLevel::Debug, makeString("MicroTask #", String::number(testNumber), " has run."));
3107     });
3108
3109     MicrotaskQueue::mainThreadQueue().append(WTFMove(microtask));
3110 }
3111
3112 #if ENABLE(CONTENT_FILTERING)
3113
3114 MockContentFilterSettings& Internals::mockContentFilterSettings()
3115 {
3116     return MockContentFilterSettings::singleton();
3117 }
3118
3119 #endif
3120
3121 #if ENABLE(CSS_SCROLL_SNAP)
3122
3123 static void appendOffsets(StringBuilder& builder, const Vector<LayoutUnit>& snapOffsets)
3124 {
3125     bool justStarting = true;
3126
3127     builder.append("{ ");
3128     for (auto& coordinate : snapOffsets) {
3129         if (!justStarting)
3130             builder.append(", ");
3131         else
3132             justStarting = false;
3133         
3134         builder.append(String::number(coordinate.toUnsigned()));
3135     }
3136     builder.append(" }");
3137 }
3138     
3139 String Internals::scrollSnapOffsets(Element& element, ExceptionCode& ec)
3140 {
3141     if (!element.renderBox())
3142         return String();
3143
3144     RenderBox& box = *element.renderBox();
3145     ScrollableArea* scrollableArea;
3146     
3147     if (box.isBody()) {
3148         FrameView* frameView = box.frame().mainFrame().view();
3149         if (!frameView || !frameView->isScrollable()) {
3150             ec = INVALID_ACCESS_ERR;
3151             return String();
3152         }
3153         scrollableArea = frameView;
3154         
3155     } else {
3156         if (!box.canBeScrolledAndHasScrollableArea()) {
3157             ec = INVALID_ACCESS_ERR;
3158             return String();
3159         }
3160         scrollableArea = box.layer();
3161     }
3162
3163     if (!scrollableArea)
3164         return String();
3165     
3166     StringBuilder result;
3167
3168     if (scrollableArea->horizontalSnapOffsets()) {
3169         result.appendLiteral("horizontal = ");
3170         appendOffsets(result, *scrollableArea->horizontalSnapOffsets());
3171     }
3172
3173     if (scrollableArea->verticalSnapOffsets()) {
3174         if (result.length())
3175             result.appendLiteral(", ");
3176
3177         result.appendLiteral("vertical = ");
3178         appendOffsets(result, *scrollableArea->verticalSnapOffsets());
3179     }
3180
3181     return result.toString();
3182 }
3183
3184 #endif
3185
3186 bool Internals::testPreloaderSettingViewport()
3187 {
3188     return testPreloadScannerViewportSupport(contextDocument());
3189 }
3190
3191 String Internals::pathStringWithShrinkWrappedRects(Vector<double> rectComponents, double radius, ExceptionCode& ec)
3192 {
3193     if (rectComponents.size() % 4) {
3194         ec = INVALID_ACCESS_ERR;
3195         return String();
3196     }
3197
3198     Vector<FloatRect> rects;
3199     while (!rectComponents.isEmpty()) {
3200         double height = rectComponents.takeLast();
3201         double width = rectComponents.takeLast();
3202         double y = rectComponents.takeLast();
3203         double x = rectComponents.takeLast();
3204
3205         rects.append(FloatRect(x, y, width, height));
3206     }
3207
3208     rects.reverse();
3209
3210     Path path = PathUtilities::pathWithShrinkWrappedRects(rects, radius);
3211
3212     String pathString;
3213     buildStringFromPath(path, pathString);
3214
3215     return pathString;
3216 }
3217
3218
3219 String Internals::getCurrentMediaControlsStatusForElement(HTMLMediaElement& mediaElement)
3220 {
3221 #if !ENABLE(MEDIA_CONTROLS_SCRIPT)
3222     UNUSED_PARAM(mediaElement);
3223     return String();
3224 #else
3225     return mediaElement.getCurrentMediaControlsStatus();
3226 #endif
3227 }
3228
3229 #if !PLATFORM(COCOA)
3230
3231 String Internals::userVisibleString(const DOMURL&)
3232 {
3233     // Cocoa-specific function. Could ASSERT_NOT_REACHED, but that's probably overkill.
3234     return String();
3235 }
3236
3237 #endif
3238
3239 void Internals::setShowAllPlugins(bool show)
3240 {
3241     Document* document = contextDocument();
3242     if (!document)
3243         return;
3244     
3245     Page* page = document->page();
3246     if (!page)
3247         return;
3248
3249     page->setShowAllPlugins(show);
3250 }
3251
3252 #if ENABLE(STREAMS_API)
3253
3254 bool Internals::isReadableStreamDisturbed(JSC::ExecState& state, JSValue stream)
3255 {
3256     JSGlobalObject* globalObject = state.vmEntryGlobalObject();
3257     JSVMClientData* clientData = static_cast<JSVMClientData*>(state.vm().clientData);
3258     const Identifier& privateName = clientData->builtinFunctions().readableStreamInternalsBuiltins().isReadableStreamDisturbedPrivateName();
3259     JSValue value;
3260     PropertySlot propertySlot(value, PropertySlot::InternalMethodType::Get);
3261     globalObject->methodTable()->getOwnPropertySlot(globalObject, &state, privateName, propertySlot);
3262     value = propertySlot.getValue(&state, privateName);
3263     ASSERT(value.isFunction());
3264
3265     JSObject* function = value.getObject();
3266     CallData callData;
3267     CallType callType = JSC::getCallData(function, callData);
3268     ASSERT(callType != JSC::CallType::None);
3269     MarkedArgumentBuffer arguments;
3270     arguments.append(stream);
3271     JSValue returnedValue = JSC::call(&state, function, callType, callData, JSC::jsUndefined(), arguments);
3272     ASSERT(returnedValue.isBoolean());
3273
3274     return returnedValue.asBoolean();
3275 }
3276
3277 #endif
3278
3279 String Internals::resourceLoadStatisticsForOrigin(String origin)
3280 {
3281     return ResourceLoadObserver::sharedObserver().statisticsForOrigin(origin);
3282 }
3283
3284 void Internals::setResourceLoadStatisticsEnabled(bool enable)
3285 {
3286     Settings::setResourceLoadStatisticsEnabled(enable);
3287 }
3288
3289 String Internals::composedTreeAsText(Node& node)
3290 {
3291     if (!is<ContainerNode>(node))
3292         return emptyString();
3293     return WebCore::composedTreeAsText(downcast<ContainerNode>(node));
3294 }
3295
3296 void Internals::setViewportForceAlwaysUserScalable(bool scalable)
3297 {
3298 #if PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000
3299     _AXSSetForceAllowWebScaling(scalable);
3300 #else
3301     UNUSED_PARAM(scalable);
3302 #endif
3303 }
3304
3305 void Internals::setLinkPreloadSupport(bool enable)
3306 {
3307     RuntimeEnabledFeatures::sharedFeatures().setLinkPreloadEnabled(enable);
3308 }
3309
3310 #if ENABLE(CSS_GRID_LAYOUT)
3311 void Internals::setCSSGridLayoutEnabled(bool enable)
3312 {
3313     RuntimeEnabledFeatures::sharedFeatures().setCSSGridLayoutEnabled(enable);
3314 }
3315 #endif
3316
3317 }