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