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