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