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