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