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