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