77ace2d7b648daacba778ac4dde107ea13b2e3f6
[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 void Internals::selectColorInColorChooser(Element* element, const String& colorValue)
890 {
891     if (!is<HTMLInputElement>(element))
892         return;
893     auto& inputElement = downcast<HTMLInputElement>(*element);
894     inputElement.selectColor(Color(colorValue));
895 }
896
897 Vector<String> Internals::formControlStateOfPreviousHistoryItem(ExceptionCode& ec)
898 {
899     HistoryItem* mainItem = frame()->loader().history().previousItem();
900     if (!mainItem) {
901         ec = INVALID_ACCESS_ERR;
902         return Vector<String>();
903     }
904     String uniqueName = frame()->tree().uniqueName();
905     if (mainItem->target() != uniqueName && !mainItem->childItemWithTarget(uniqueName)) {
906         ec = INVALID_ACCESS_ERR;
907         return Vector<String>();
908     }
909     return mainItem->target() == uniqueName ? mainItem->documentState() : mainItem->childItemWithTarget(uniqueName)->documentState();
910 }
911
912 void Internals::setFormControlStateOfPreviousHistoryItem(const Vector<String>& state, ExceptionCode& ec)
913 {
914     HistoryItem* mainItem = frame()->loader().history().previousItem();
915     if (!mainItem) {
916         ec = INVALID_ACCESS_ERR;
917         return;
918     }
919     String uniqueName = frame()->tree().uniqueName();
920     if (mainItem->target() == uniqueName)
921         mainItem->setDocumentState(state);
922     else if (HistoryItem* subItem = mainItem->childItemWithTarget(uniqueName))
923         subItem->setDocumentState(state);
924     else
925         ec = INVALID_ACCESS_ERR;
926 }
927
928 #if ENABLE(SPEECH_SYNTHESIS)
929 void Internals::enableMockSpeechSynthesizer()
930 {
931     Document* document = contextDocument();
932     if (!document || !document->domWindow())
933         return;
934     SpeechSynthesis* synthesis = DOMWindowSpeechSynthesis::speechSynthesis(document->domWindow());
935     if (!synthesis)
936         return;
937     
938     synthesis->setPlatformSynthesizer(std::make_unique<PlatformSpeechSynthesizerMock>(synthesis));
939 }
940 #endif
941
942 #if ENABLE(MEDIA_STREAM)
943 void Internals::enableMockRTCPeerConnectionHandler()
944 {
945     RTCPeerConnectionHandler::create = RTCPeerConnectionHandlerMock::create;
946 }
947 #endif
948
949 Ref<ClientRect> Internals::absoluteCaretBounds(ExceptionCode& ec)
950 {
951     Document* document = contextDocument();
952     if (!document || !document->frame()) {
953         ec = INVALID_ACCESS_ERR;
954         return ClientRect::create();
955     }
956
957     return ClientRect::create(document->frame()->selection().absoluteCaretBounds());
958 }
959
960 Ref<ClientRect> Internals::boundingBox(Element* element, ExceptionCode& ec)
961 {
962     if (!element) {
963         ec = INVALID_ACCESS_ERR;
964         return ClientRect::create();
965     }
966
967     element->document().updateLayoutIgnorePendingStylesheets();
968     auto renderer = element->renderer();
969     if (!renderer)
970         return ClientRect::create();
971     return ClientRect::create(renderer->absoluteBoundingBoxRectIgnoringTransforms());
972 }
973
974 Ref<ClientRectList> Internals::inspectorHighlightRects(ExceptionCode& ec)
975 {
976     Document* document = contextDocument();
977     if (!document || !document->page()) {
978         ec = INVALID_ACCESS_ERR;
979         return ClientRectList::create();
980     }
981
982     Highlight highlight;
983     document->page()->inspectorController().getHighlight(highlight, InspectorOverlay::CoordinateSystem::View);
984     return ClientRectList::create(highlight.quads);
985 }
986
987 String Internals::inspectorHighlightObject(ExceptionCode& ec)
988 {
989     Document* document = contextDocument();
990     if (!document || !document->page()) {
991         ec = INVALID_ACCESS_ERR;
992         return String();
993     }
994
995     return document->page()->inspectorController().buildObjectForHighlightedNodes()->toJSONString();
996 }
997
998 unsigned Internals::markerCountForNode(Node* node, const String& markerType, ExceptionCode& ec)
999 {
1000     if (!node) {
1001         ec = INVALID_ACCESS_ERR;
1002         return 0;
1003     }
1004
1005     DocumentMarker::MarkerTypes markerTypes = 0;
1006     if (!markerTypesFrom(markerType, markerTypes)) {
1007         ec = SYNTAX_ERR;
1008         return 0;
1009     }
1010
1011     node->document().frame()->editor().updateEditorUINowIfScheduled();
1012
1013     return node->document().markers().markersFor(node, markerTypes).size();
1014 }
1015
1016 RenderedDocumentMarker* Internals::markerAt(Node* node, const String& markerType, unsigned index, ExceptionCode& ec)
1017 {
1018     node->document().updateLayoutIgnorePendingStylesheets();
1019     if (!node) {
1020         ec = INVALID_ACCESS_ERR;
1021         return nullptr;
1022     }
1023
1024     DocumentMarker::MarkerTypes markerTypes = 0;
1025     if (!markerTypesFrom(markerType, markerTypes)) {
1026         ec = SYNTAX_ERR;
1027         return nullptr;
1028     }
1029
1030     node->document().frame()->editor().updateEditorUINowIfScheduled();
1031
1032     Vector<RenderedDocumentMarker*> markers = node->document().markers().markersFor(node, markerTypes);
1033     if (markers.size() <= index)
1034         return nullptr;
1035     return markers[index];
1036 }
1037
1038 RefPtr<Range> Internals::markerRangeForNode(Node* node, const String& markerType, unsigned index, ExceptionCode& ec)
1039 {
1040     RenderedDocumentMarker* marker = markerAt(node, markerType, index, ec);
1041     if (!marker)
1042         return nullptr;
1043     return Range::create(node->document(), node, marker->startOffset(), node, marker->endOffset());
1044 }
1045
1046 String Internals::markerDescriptionForNode(Node* node, const String& markerType, unsigned index, ExceptionCode& ec)
1047 {
1048     RenderedDocumentMarker* marker = markerAt(node, markerType, index, ec);
1049     if (!marker)
1050         return String();
1051     return marker->description();
1052 }
1053
1054 String Internals::dumpMarkerRects(const String& markerTypeString, ExceptionCode& ec)
1055 {
1056     DocumentMarker::MarkerType markerType;
1057     if (!markerTypeFrom(markerTypeString, markerType)) {
1058         ec = SYNTAX_ERR;
1059         return String();
1060     }
1061
1062     contextDocument()->markers().updateRectsForInvalidatedMarkersOfType(markerType);
1063     auto rects = contextDocument()->markers().renderedRectsForMarkers(markerType);
1064
1065     StringBuilder rectString;
1066     rectString.appendLiteral("marker rects: ");
1067     for (const auto& rect : rects) {
1068         rectString.append('(');
1069         rectString.appendNumber(rect.x());
1070         rectString.appendLiteral(", ");
1071         rectString.appendNumber(rect.y());
1072         rectString.appendLiteral(", ");
1073         rectString.appendNumber(rect.width());
1074         rectString.appendLiteral(", ");
1075         rectString.appendNumber(rect.height());
1076         rectString.appendLiteral(") ");
1077     }
1078     return rectString.toString();
1079 }
1080
1081 void Internals::addTextMatchMarker(const Range* range, bool isActive)
1082 {
1083     range->ownerDocument().updateLayoutIgnorePendingStylesheets();
1084     range->ownerDocument().markers().addTextMatchMarker(range, isActive);
1085 }
1086
1087 void Internals::setMarkedTextMatchesAreHighlighted(bool flag, ExceptionCode& ec)
1088 {
1089     Document* document = contextDocument();
1090     if (!document || !document->frame()) {
1091         ec = INVALID_ACCESS_ERR;
1092         return;
1093     }
1094     document->frame()->editor().setMarkedTextMatchesAreHighlighted(flag);
1095 }
1096
1097 void Internals::invalidateFontCache()
1098 {
1099     FontCache::singleton().invalidate();
1100 }
1101
1102 void Internals::setScrollViewPosition(long x, long y, ExceptionCode& ec)
1103 {
1104     Document* document = contextDocument();
1105     if (!document || !document->view()) {
1106         ec = INVALID_ACCESS_ERR;
1107         return;
1108     }
1109
1110     FrameView* frameView = document->view();
1111     bool constrainsScrollingToContentEdgeOldValue = frameView->constrainsScrollingToContentEdge();
1112     bool scrollbarsSuppressedOldValue = frameView->scrollbarsSuppressed();
1113
1114     frameView->setConstrainsScrollingToContentEdge(false);
1115     frameView->setScrollbarsSuppressed(false);
1116     frameView->setScrollOffsetFromInternals(IntPoint(x, y));
1117     frameView->setScrollbarsSuppressed(scrollbarsSuppressedOldValue);
1118     frameView->setConstrainsScrollingToContentEdge(constrainsScrollingToContentEdgeOldValue);
1119 }
1120
1121 void Internals::setViewBaseBackgroundColor(const String& colorValue, ExceptionCode& ec)
1122 {
1123     Document* document = contextDocument();
1124     if (!document || !document->view()) {
1125         ec = INVALID_ACCESS_ERR;
1126         return;
1127     }
1128
1129     document->view()->setBaseBackgroundColor(Color(colorValue));
1130 }
1131
1132 void Internals::setPagination(const String& mode, int gap, int pageLength, ExceptionCode& ec)
1133 {
1134     Document* document = contextDocument();
1135     if (!document || !document->page()) {
1136         ec = INVALID_ACCESS_ERR;
1137         return;
1138     }
1139     Page* page = document->page();
1140
1141     Pagination pagination;
1142     if (mode == "Unpaginated")
1143         pagination.mode = Pagination::Unpaginated;
1144     else if (mode == "LeftToRightPaginated")
1145         pagination.mode = Pagination::LeftToRightPaginated;
1146     else if (mode == "RightToLeftPaginated")
1147         pagination.mode = Pagination::RightToLeftPaginated;
1148     else if (mode == "TopToBottomPaginated")
1149         pagination.mode = Pagination::TopToBottomPaginated;
1150     else if (mode == "BottomToTopPaginated")
1151         pagination.mode = Pagination::BottomToTopPaginated;
1152     else {
1153         ec = SYNTAX_ERR;
1154         return;
1155     }
1156
1157     pagination.gap = gap;
1158     pagination.pageLength = pageLength;
1159     page->setPagination(pagination);
1160 }
1161
1162 String Internals::configurationForViewport(float devicePixelRatio, int deviceWidth, int deviceHeight, int availableWidth, int availableHeight, ExceptionCode& ec)
1163 {
1164     Document* document = contextDocument();
1165     if (!document || !document->page()) {
1166         ec = INVALID_ACCESS_ERR;
1167         return String();
1168     }
1169     Page* page = document->page();
1170
1171     const int defaultLayoutWidthForNonMobilePages = 980;
1172
1173     ViewportArguments arguments = page->viewportArguments();
1174     ViewportAttributes attributes = computeViewportAttributes(arguments, defaultLayoutWidthForNonMobilePages, deviceWidth, deviceHeight, devicePixelRatio, IntSize(availableWidth, availableHeight));
1175     restrictMinimumScaleFactorToViewportSize(attributes, IntSize(availableWidth, availableHeight), devicePixelRatio);
1176     restrictScaleFactorToInitialScaleIfNotUserScalable(attributes);
1177
1178     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");
1179 }
1180
1181 bool Internals::wasLastChangeUserEdit(Element* textField, ExceptionCode& ec)
1182 {
1183     if (!textField) {
1184         ec = INVALID_ACCESS_ERR;
1185         return false;
1186     }
1187
1188     if (is<HTMLInputElement>(*textField))
1189         return downcast<HTMLInputElement>(*textField).lastChangeWasUserEdit();
1190
1191     if (is<HTMLTextAreaElement>(*textField))
1192         return downcast<HTMLTextAreaElement>(*textField).lastChangeWasUserEdit();
1193
1194     ec = INVALID_NODE_TYPE_ERR;
1195     return false;
1196 }
1197
1198 bool Internals::elementShouldAutoComplete(Element* element, ExceptionCode& ec)
1199 {
1200     if (!element) {
1201         ec = INVALID_ACCESS_ERR;
1202         return false;
1203     }
1204
1205     if (!is<HTMLInputElement>(*element)) {
1206         ec = INVALID_NODE_TYPE_ERR;
1207         return false;
1208     }
1209
1210     return downcast<HTMLInputElement>(*element).shouldAutocomplete();
1211 }
1212
1213 void Internals::setEditingValue(Element* element, const String& value, ExceptionCode& ec)
1214 {
1215     if (!element) {
1216         ec = INVALID_ACCESS_ERR;
1217         return;
1218     }
1219
1220     if (!is<HTMLInputElement>(*element)) {
1221         ec = INVALID_NODE_TYPE_ERR;
1222         return;
1223     }
1224
1225     downcast<HTMLInputElement>(*element).setEditingValue(value);
1226 }
1227
1228 void Internals::setAutofilled(Element* element, bool enabled, ExceptionCode& ec)
1229 {
1230     if (!element) {
1231         ec = INVALID_ACCESS_ERR;
1232         return;
1233     }
1234
1235     if (!is<HTMLInputElement>(*element)) {
1236         ec = INVALID_NODE_TYPE_ERR;
1237         return;
1238     }
1239
1240     downcast<HTMLInputElement>(*element).setAutoFilled(enabled);
1241 }
1242
1243 void Internals::setShowAutoFillButton(Element* element, bool show, ExceptionCode& ec)
1244 {
1245     if (!element) {
1246         ec = INVALID_ACCESS_ERR;
1247         return;
1248     }
1249
1250     if (!is<HTMLInputElement>(*element)) {
1251         ec = INVALID_NODE_TYPE_ERR;
1252         return;
1253     }
1254
1255     downcast<HTMLInputElement>(*element).setShowAutoFillButton(show);
1256 }
1257
1258
1259 void Internals::scrollElementToRect(Element* element, long x, long y, long w, long h, ExceptionCode& ec)
1260 {
1261     if (!element || !element->document().view()) {
1262         ec = INVALID_ACCESS_ERR;
1263         return;
1264     }
1265     FrameView* frameView = element->document().view();
1266     frameView->scrollElementToRect(*element, IntRect(x, y, w, h));
1267 }
1268
1269 void Internals::paintControlTints(ExceptionCode& ec)
1270 {
1271     Document* document = contextDocument();
1272     if (!document || !document->view()) {
1273         ec = INVALID_ACCESS_ERR;
1274         return;
1275     }
1276
1277     FrameView* frameView = document->view();
1278     frameView->paintControlTints();
1279 }
1280
1281 RefPtr<Range> Internals::rangeFromLocationAndLength(Element* scope, int rangeLocation, int rangeLength, ExceptionCode& ec)
1282 {
1283     if (!scope) {
1284         ec = INVALID_ACCESS_ERR;
1285         return nullptr;
1286     }
1287
1288     return TextIterator::rangeFromLocationAndLength(scope, rangeLocation, rangeLength);
1289 }
1290
1291 unsigned Internals::locationFromRange(Element* scope, const Range* range, ExceptionCode& ec)
1292 {
1293     if (!scope || !range) {
1294         ec = INVALID_ACCESS_ERR;
1295         return 0;
1296     }
1297
1298     size_t location = 0;
1299     size_t unusedLength = 0;
1300     TextIterator::getLocationAndLengthFromRange(scope, range, location, unusedLength);
1301     return location;
1302 }
1303
1304 unsigned Internals::lengthFromRange(Element* scope, const Range* range, ExceptionCode& ec)
1305 {
1306     if (!scope || !range) {
1307         ec = INVALID_ACCESS_ERR;
1308         return 0;
1309     }
1310
1311     size_t unusedLocation = 0;
1312     size_t length = 0;
1313     TextIterator::getLocationAndLengthFromRange(scope, range, unusedLocation, length);
1314     return length;
1315 }
1316
1317 String Internals::rangeAsText(const Range* range, ExceptionCode& ec)
1318 {
1319     if (!range) {
1320         ec = INVALID_ACCESS_ERR;
1321         return String();
1322     }
1323
1324     return range->text();
1325 }
1326
1327 RefPtr<Range> Internals::subrange(Range* range, int rangeLocation, int rangeLength, ExceptionCode& ec)
1328 {
1329     if (!range) {
1330         ec = INVALID_ACCESS_ERR;
1331         return nullptr;
1332     }
1333
1334     return TextIterator::subrange(range, rangeLocation, rangeLength);
1335 }
1336
1337 RefPtr<Range> Internals::rangeForDictionaryLookupAtLocation(int x, int y, ExceptionCode& ec)
1338 {
1339 #if PLATFORM(MAC)
1340     Document* document = contextDocument();
1341     if (!document || !document->frame()) {
1342         ec = INVALID_ACCESS_ERR;
1343         return nullptr;
1344     }
1345
1346     document->updateLayoutIgnorePendingStylesheets();
1347     
1348     HitTestResult result = document->frame()->mainFrame().eventHandler().hitTestResultAtPoint(IntPoint(x, y));
1349     NSDictionary *options = nullptr;
1350     return DictionaryLookup::rangeAtHitTestResult(result, &options);
1351 #else
1352     UNUSED_PARAM(x);
1353     UNUSED_PARAM(y);
1354     ec = INVALID_ACCESS_ERR;
1355     return nullptr;
1356 #endif
1357 }
1358
1359 void Internals::setDelegatesScrolling(bool enabled, ExceptionCode& ec)
1360 {
1361     Document* document = contextDocument();
1362     // Delegate scrolling is valid only on mainframe's view.
1363     if (!document || !document->view() || !document->page() || &document->page()->mainFrame() != document->frame()) {
1364         ec = INVALID_ACCESS_ERR;
1365         return;
1366     }
1367
1368     document->view()->setDelegatesScrolling(enabled);
1369 }
1370
1371 int Internals::lastSpellCheckRequestSequence(ExceptionCode& ec)
1372 {
1373     Document* document = contextDocument();
1374     if (!document || !document->frame()) {
1375         ec = INVALID_ACCESS_ERR;
1376         return -1;
1377     }
1378
1379     return document->frame()->editor().spellChecker().lastRequestSequence();
1380 }
1381
1382 int Internals::lastSpellCheckProcessedSequence(ExceptionCode& ec)
1383 {
1384     Document* document = contextDocument();
1385     if (!document || !document->frame()) {
1386         ec = INVALID_ACCESS_ERR;
1387         return -1;
1388     }
1389
1390     return document->frame()->editor().spellChecker().lastProcessedSequence();
1391 }
1392
1393 Vector<String> Internals::userPreferredLanguages() const
1394 {
1395     return WebCore::userPreferredLanguages();
1396 }
1397
1398 void Internals::setUserPreferredLanguages(const Vector<String>& languages)
1399 {
1400     WebCore::overrideUserPreferredLanguages(languages);
1401 }
1402
1403 Vector<String> Internals::userPreferredAudioCharacteristics() const
1404 {
1405     Document* document = contextDocument();
1406     if (!document || !document->page())
1407         return Vector<String>();
1408 #if ENABLE(VIDEO_TRACK)
1409     return document->page()->group().captionPreferences()->preferredAudioCharacteristics();
1410 #else
1411     return Vector<String>();
1412 #endif
1413 }
1414
1415 void Internals::setUserPreferredAudioCharacteristic(const String& characteristic)
1416 {
1417     Document* document = contextDocument();
1418     if (!document || !document->page())
1419         return;
1420 #if ENABLE(VIDEO_TRACK)
1421     document->page()->group().captionPreferences()->setPreferredAudioCharacteristic(characteristic);
1422 #else
1423     UNUSED_PARAM(characteristic);
1424 #endif
1425 }
1426
1427 unsigned Internals::wheelEventHandlerCount(ExceptionCode& ec)
1428 {
1429     Document* document = contextDocument();
1430     if (!document) {
1431         ec = INVALID_ACCESS_ERR;
1432         return 0;
1433     }
1434
1435     return document->wheelEventHandlerCount();
1436 }
1437
1438 unsigned Internals::touchEventHandlerCount(ExceptionCode& ec)
1439 {
1440     Document* document = contextDocument();
1441     if (!document) {
1442         ec = INVALID_ACCESS_ERR;
1443         return 0;
1444     }
1445
1446     return document->touchEventHandlerCount();
1447 }
1448
1449 // FIXME: Remove the document argument. It is almost always the same as
1450 // contextDocument(), with the exception of a few tests that pass a
1451 // different document, and could just make the call through another Internals
1452 // instance instead.
1453 RefPtr<NodeList> Internals::nodesFromRect(Document* document, int centerX, int centerY, unsigned topPadding, unsigned rightPadding,
1454     unsigned bottomPadding, unsigned leftPadding, bool ignoreClipping, bool allowShadowContent, bool allowChildFrameContent, ExceptionCode& ec) const
1455 {
1456     if (!document || !document->frame() || !document->frame()->view()) {
1457         ec = INVALID_ACCESS_ERR;
1458         return nullptr;
1459     }
1460
1461     Frame* frame = document->frame();
1462     FrameView* frameView = document->view();
1463     RenderView* renderView = document->renderView();
1464     if (!renderView)
1465         return nullptr;
1466
1467     document->updateLayoutIgnorePendingStylesheets();
1468
1469     float zoomFactor = frame->pageZoomFactor();
1470     LayoutPoint point(centerX * zoomFactor + frameView->scrollX(), centerY * zoomFactor + frameView->scrollY());
1471
1472     HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active;
1473     if (ignoreClipping)
1474         hitType |= HitTestRequest::IgnoreClipping;
1475     if (!allowShadowContent)
1476         hitType |= HitTestRequest::DisallowShadowContent;
1477     if (allowChildFrameContent)
1478         hitType |= HitTestRequest::AllowChildFrameContent;
1479
1480     HitTestRequest request(hitType);
1481
1482     // When ignoreClipping is false, this method returns null for coordinates outside of the viewport.
1483     if (!request.ignoreClipping() && !frameView->visibleContentRect().intersects(HitTestLocation::rectForPoint(point, topPadding, rightPadding, bottomPadding, leftPadding)))
1484         return nullptr;
1485
1486     Vector<Ref<Node>> matches;
1487
1488     // Need padding to trigger a rect based hit test, but we want to return a NodeList
1489     // so we special case this.
1490     if (!topPadding && !rightPadding && !bottomPadding && !leftPadding) {
1491         HitTestResult result(point);
1492         renderView->hitTest(request, result);
1493         if (result.innerNode())
1494             matches.append(*result.innerNode()->deprecatedShadowAncestorNode());
1495     } else {
1496         HitTestResult result(point, topPadding, rightPadding, bottomPadding, leftPadding);
1497         renderView->hitTest(request, result);
1498         
1499         const HitTestResult::NodeSet& nodeSet = result.rectBasedTestResult();
1500         matches.reserveInitialCapacity(nodeSet.size());
1501         for (auto& node : nodeSet)
1502             matches.uncheckedAppend(*node);
1503     }
1504
1505     return StaticNodeList::adopt(matches);
1506 }
1507
1508 class GetCallerCodeBlockFunctor {
1509 public:
1510     GetCallerCodeBlockFunctor()
1511         : m_iterations(0)
1512         , m_codeBlock(0)
1513     {
1514     }
1515
1516     StackVisitor::Status operator()(StackVisitor& visitor)
1517     {
1518         ++m_iterations;
1519         if (m_iterations < 2)
1520             return StackVisitor::Continue;
1521
1522         m_codeBlock = visitor->codeBlock();
1523         return StackVisitor::Done;
1524     }
1525
1526     CodeBlock* codeBlock() const { return m_codeBlock; }
1527
1528 private:
1529     int m_iterations;
1530     CodeBlock* m_codeBlock;
1531 };
1532
1533 String Internals::parserMetaData(Deprecated::ScriptValue value)
1534 {
1535     JSC::VM& vm = contextDocument()->vm();
1536     JSC::ExecState* exec = vm.topCallFrame;
1537     JSC::JSValue code = value.jsValue();
1538     ScriptExecutable* executable;
1539
1540     if (!code || code.isNull() || code.isUndefined()) {
1541         GetCallerCodeBlockFunctor iter;
1542         exec->iterate(iter);
1543         CodeBlock* codeBlock = iter.codeBlock();
1544         executable = codeBlock->ownerScriptExecutable();
1545     } else if (code.isFunction()) {
1546         JSFunction* funcObj = JSC::jsCast<JSFunction*>(code.toObject(exec));
1547         executable = funcObj->jsExecutable();
1548     } else
1549         return String();
1550
1551     unsigned startLine = executable->firstLine();
1552     unsigned startColumn = executable->startColumn();
1553     unsigned endLine = executable->lastLine();
1554     unsigned endColumn = executable->endColumn();
1555
1556     StringBuilder result;
1557
1558     if (executable->isFunctionExecutable()) {
1559         FunctionExecutable* funcExecutable = reinterpret_cast<FunctionExecutable*>(executable);
1560         String inferredName = funcExecutable->inferredName().string();
1561         result.appendLiteral("function \"");
1562         result.append(inferredName);
1563         result.append('"');
1564     } else if (executable->isEvalExecutable())
1565         result.appendLiteral("eval");
1566     else if (executable->isModuleProgramExecutable())
1567         result.appendLiteral("module");
1568     else if (executable->isProgramExecutable())
1569         result.appendLiteral("program");
1570 #if ENABLE(WEBASSEMBLY)
1571     else if (executable->isWebAssemblyExecutable())
1572         result.appendLiteral("WebAssembly");
1573 #endif
1574     else
1575         ASSERT_NOT_REACHED();
1576
1577     result.appendLiteral(" { ");
1578     result.appendNumber(startLine);
1579     result.append(':');
1580     result.appendNumber(startColumn);
1581     result.appendLiteral(" - ");
1582     result.appendNumber(endLine);
1583     result.append(':');
1584     result.appendNumber(endColumn);
1585     result.appendLiteral(" }");
1586
1587     return result.toString();
1588 }
1589
1590 void Internals::setBatteryStatus(const String& eventType, bool charging, double chargingTime, double dischargingTime, double level, ExceptionCode& ec)
1591 {
1592     Document* document = contextDocument();
1593     if (!document || !document->page()) {
1594         ec = INVALID_ACCESS_ERR;
1595         return;
1596     }
1597
1598 #if ENABLE(BATTERY_STATUS)
1599     BatteryController::from(document->page())->didChangeBatteryStatus(eventType, BatteryStatus::create(charging, chargingTime, dischargingTime, level));
1600 #else
1601     UNUSED_PARAM(eventType);
1602     UNUSED_PARAM(charging);
1603     UNUSED_PARAM(chargingTime);
1604     UNUSED_PARAM(dischargingTime);
1605     UNUSED_PARAM(level);
1606 #endif
1607 }
1608
1609 void Internals::setDeviceProximity(const String& eventType, double value, double min, double max, ExceptionCode& ec)
1610 {
1611     Document* document = contextDocument();
1612     if (!document || !document->page()) {
1613         ec = INVALID_ACCESS_ERR;
1614         return;
1615     }
1616
1617 #if ENABLE(PROXIMITY_EVENTS)
1618     DeviceProximityController::from(document->page())->didChangeDeviceProximity(value, min, max);
1619 #else
1620     UNUSED_PARAM(eventType);
1621     UNUSED_PARAM(value);
1622     UNUSED_PARAM(min);
1623     UNUSED_PARAM(max);
1624 #endif
1625 }
1626
1627 void Internals::updateEditorUINowIfScheduled()
1628 {
1629     if (Document* document = contextDocument()) {
1630         if (Frame* frame = document->frame())
1631             frame->editor().updateEditorUINowIfScheduled();
1632     }
1633 }
1634
1635 bool Internals::hasSpellingMarker(int from, int length, ExceptionCode&)
1636 {
1637     Document* document = contextDocument();
1638     if (!document || !document->frame())
1639         return false;
1640
1641     updateEditorUINowIfScheduled();
1642
1643     return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
1644 }
1645     
1646 bool Internals::hasAutocorrectedMarker(int from, int length, ExceptionCode&)
1647 {
1648     Document* document = contextDocument();
1649     if (!document || !document->frame())
1650         return false;
1651
1652     updateEditorUINowIfScheduled();
1653
1654     return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Autocorrected, from, length);
1655 }
1656
1657 void Internals::setContinuousSpellCheckingEnabled(bool enabled, ExceptionCode&)
1658 {
1659     if (!contextDocument() || !contextDocument()->frame())
1660         return;
1661
1662     if (enabled != contextDocument()->frame()->editor().isContinuousSpellCheckingEnabled())
1663         contextDocument()->frame()->editor().toggleContinuousSpellChecking();
1664 }
1665
1666 void Internals::setAutomaticQuoteSubstitutionEnabled(bool enabled, ExceptionCode&)
1667 {
1668     if (!contextDocument() || !contextDocument()->frame())
1669         return;
1670
1671 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1672     if (enabled != contextDocument()->frame()->editor().isAutomaticQuoteSubstitutionEnabled())
1673         contextDocument()->frame()->editor().toggleAutomaticQuoteSubstitution();
1674 #else
1675     UNUSED_PARAM(enabled);
1676 #endif
1677 }
1678
1679 void Internals::setAutomaticLinkDetectionEnabled(bool enabled, ExceptionCode&)
1680 {
1681     if (!contextDocument() || !contextDocument()->frame())
1682         return;
1683
1684 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1685     if (enabled != contextDocument()->frame()->editor().isAutomaticLinkDetectionEnabled())
1686         contextDocument()->frame()->editor().toggleAutomaticLinkDetection();
1687 #else
1688     UNUSED_PARAM(enabled);
1689 #endif
1690 }
1691
1692 void Internals::setAutomaticDashSubstitutionEnabled(bool enabled, ExceptionCode&)
1693 {
1694     if (!contextDocument() || !contextDocument()->frame())
1695         return;
1696
1697 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1698     if (enabled != contextDocument()->frame()->editor().isAutomaticDashSubstitutionEnabled())
1699         contextDocument()->frame()->editor().toggleAutomaticDashSubstitution();
1700 #else
1701     UNUSED_PARAM(enabled);
1702 #endif
1703 }
1704
1705 void Internals::setAutomaticTextReplacementEnabled(bool enabled, ExceptionCode&)
1706 {
1707     if (!contextDocument() || !contextDocument()->frame())
1708         return;
1709
1710 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1711     if (enabled != contextDocument()->frame()->editor().isAutomaticTextReplacementEnabled())
1712         contextDocument()->frame()->editor().toggleAutomaticTextReplacement();
1713 #else
1714     UNUSED_PARAM(enabled);
1715 #endif
1716 }
1717
1718 void Internals::setAutomaticSpellingCorrectionEnabled(bool enabled, ExceptionCode&)
1719 {
1720     if (!contextDocument() || !contextDocument()->frame())
1721         return;
1722
1723 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1724     if (enabled != contextDocument()->frame()->editor().isAutomaticSpellingCorrectionEnabled())
1725         contextDocument()->frame()->editor().toggleAutomaticSpellingCorrection();
1726 #else
1727     UNUSED_PARAM(enabled);
1728 #endif
1729 }
1730
1731 bool Internals::isOverwriteModeEnabled(ExceptionCode&)
1732 {
1733     Document* document = contextDocument();
1734     if (!document || !document->frame())
1735         return false;
1736
1737     return document->frame()->editor().isOverwriteModeEnabled();
1738 }
1739
1740 void Internals::toggleOverwriteModeEnabled(ExceptionCode&)
1741 {
1742     Document* document = contextDocument();
1743     if (!document || !document->frame())
1744         return;
1745
1746     document->frame()->editor().toggleOverwriteModeEnabled();
1747 }
1748
1749 unsigned Internals::countMatchesForText(const String& text, unsigned findOptions, const String& markMatches, ExceptionCode&)
1750 {
1751     Document* document = contextDocument();
1752     if (!document || !document->frame())
1753         return 0;
1754
1755     bool mark = markMatches == "mark";
1756     return document->frame()->editor().countMatchesForText(text, nullptr, findOptions, 1000, mark, nullptr);
1757 }
1758
1759 const ProfilesArray& Internals::consoleProfiles() const
1760 {
1761     return contextDocument()->page()->console().profiles();
1762 }
1763
1764 unsigned Internals::numberOfLiveNodes() const
1765 {
1766     unsigned nodeCount = 0;
1767     for (auto* document : Document::allDocuments())
1768         nodeCount += document->referencingNodeCount();
1769     return nodeCount;
1770 }
1771
1772 unsigned Internals::numberOfLiveDocuments() const
1773 {
1774     return Document::allDocuments().size();
1775 }
1776
1777 RefPtr<DOMWindow> Internals::openDummyInspectorFrontend(const String& url)
1778 {
1779     Page* inspectedPage = contextDocument()->frame()->page();
1780     RefPtr<DOMWindow> window = inspectedPage->mainFrame().document()->domWindow();
1781     RefPtr<DOMWindow> frontendWindow = window->open(url, "", "", *window, *window);
1782     m_inspectorFrontend = std::make_unique<InspectorStubFrontend>(inspectedPage, frontendWindow.copyRef());
1783
1784     return WTF::move(frontendWindow);
1785 }
1786
1787 void Internals::closeDummyInspectorFrontend()
1788 {
1789     m_inspectorFrontend = nullptr;
1790 }
1791
1792 void Internals::setJavaScriptProfilingEnabled(bool enabled, ExceptionCode& ec)
1793 {
1794     Page* page = contextDocument()->frame()->page();
1795     if (!page) {
1796         ec = INVALID_ACCESS_ERR;
1797         return;
1798     }
1799
1800     page->inspectorController().setProfilerEnabled(enabled);
1801 }
1802
1803 void Internals::setInspectorIsUnderTest(bool isUnderTest, ExceptionCode& ec)
1804 {
1805     Page* page = contextDocument()->frame()->page();
1806     if (!page) {
1807         ec = INVALID_ACCESS_ERR;
1808         return;
1809     }
1810
1811     page->inspectorController().setIsUnderTest(isUnderTest);
1812 }
1813
1814 bool Internals::hasGrammarMarker(int from, int length, ExceptionCode&)
1815 {
1816     Document* document = contextDocument();
1817     if (!document || !document->frame())
1818         return false;
1819
1820     return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Grammar, from, length);
1821 }
1822
1823 unsigned Internals::numberOfScrollableAreas(ExceptionCode&)
1824 {
1825     Document* document = contextDocument();
1826     if (!document || !document->frame())
1827         return 0;
1828
1829     unsigned count = 0;
1830     Frame* frame = document->frame();
1831     if (frame->view()->scrollableAreas())
1832         count += frame->view()->scrollableAreas()->size();
1833
1834     for (Frame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
1835         if (child->view() && child->view()->scrollableAreas())
1836             count += child->view()->scrollableAreas()->size();
1837     }
1838
1839     return count;
1840 }
1841     
1842 bool Internals::isPageBoxVisible(int pageNumber, ExceptionCode& ec)
1843 {
1844     Document* document = contextDocument();
1845     if (!document) {
1846         ec = INVALID_ACCESS_ERR;
1847         return false;
1848     }
1849
1850     return document->isPageBoxVisible(pageNumber);
1851 }
1852
1853 // FIXME: Remove the document argument. It is almost always the same as
1854 // contextDocument(), with the exception of a few tests that pass a
1855 // different document, and could just make the call through another Internals
1856 // instance instead.
1857 String Internals::layerTreeAsText(Document* document, ExceptionCode& ec) const
1858 {
1859     return layerTreeAsText(document, 0, ec);
1860 }
1861
1862 String Internals::layerTreeAsText(Document* document, unsigned flags, ExceptionCode& ec) const
1863 {
1864     if (!document || !document->frame()) {
1865         ec = INVALID_ACCESS_ERR;
1866         return String();
1867     }
1868
1869     LayerTreeFlags layerTreeFlags = 0;
1870     if (flags & LAYER_TREE_INCLUDES_VISIBLE_RECTS)
1871         layerTreeFlags |= LayerTreeFlagsIncludeVisibleRects;
1872     if (flags & LAYER_TREE_INCLUDES_TILE_CACHES)
1873         layerTreeFlags |= LayerTreeFlagsIncludeTileCaches;
1874     if (flags & LAYER_TREE_INCLUDES_REPAINT_RECTS)
1875         layerTreeFlags |= LayerTreeFlagsIncludeRepaintRects;
1876     if (flags & LAYER_TREE_INCLUDES_PAINTING_PHASES)
1877         layerTreeFlags |= LayerTreeFlagsIncludePaintingPhases;
1878     if (flags & LAYER_TREE_INCLUDES_CONTENT_LAYERS)
1879         layerTreeFlags |= LayerTreeFlagsIncludeContentLayers;
1880
1881     return document->frame()->layerTreeAsText(layerTreeFlags);
1882 }
1883
1884 String Internals::repaintRectsAsText(ExceptionCode& ec) const
1885 {
1886     Document* document = contextDocument();
1887     if (!document || !document->frame()) {
1888         ec = INVALID_ACCESS_ERR;
1889         return String();
1890     }
1891
1892     return document->frame()->trackedRepaintRectsAsText();
1893 }
1894
1895 String Internals::scrollingStateTreeAsText(ExceptionCode& ec) const
1896 {
1897     Document* document = contextDocument();
1898     if (!document || !document->frame()) {
1899         ec = INVALID_ACCESS_ERR;
1900         return String();
1901     }
1902
1903     Page* page = document->page();
1904     if (!page)
1905         return String();
1906
1907     return page->scrollingStateTreeAsText();
1908 }
1909
1910 String Internals::mainThreadScrollingReasons(ExceptionCode& ec) const
1911 {
1912     Document* document = contextDocument();
1913     if (!document || !document->frame()) {
1914         ec = INVALID_ACCESS_ERR;
1915         return String();
1916     }
1917
1918     Page* page = document->page();
1919     if (!page)
1920         return String();
1921
1922     return page->synchronousScrollingReasonsAsText();
1923 }
1924
1925 RefPtr<ClientRectList> Internals::nonFastScrollableRects(ExceptionCode& ec) const
1926 {
1927     Document* document = contextDocument();
1928     if (!document || !document->frame()) {
1929         ec = INVALID_ACCESS_ERR;
1930         return nullptr;
1931     }
1932
1933     Page* page = document->page();
1934     if (!page)
1935         return nullptr;
1936
1937     return page->nonFastScrollableRects();
1938 }
1939
1940 void Internals::garbageCollectDocumentResources(ExceptionCode& ec) const
1941 {
1942     Document* document = contextDocument();
1943     if (!document) {
1944         ec = INVALID_ACCESS_ERR;
1945         return;
1946     }
1947     document->cachedResourceLoader().garbageCollectDocumentResources();
1948 }
1949
1950 void Internals::allowRoundingHacks() const
1951 {
1952     TextRun::setAllowsRoundingHacks(true);
1953 }
1954
1955 void Internals::insertAuthorCSS(const String& css, ExceptionCode& ec) const
1956 {
1957     Document* document = contextDocument();
1958     if (!document) {
1959         ec = INVALID_ACCESS_ERR;
1960         return;
1961     }
1962
1963     auto parsedSheet = StyleSheetContents::create(*document);
1964     parsedSheet.get().setIsUserStyleSheet(false);
1965     parsedSheet.get().parseString(css);
1966     document->extensionStyleSheets().addAuthorStyleSheetForTesting(WTF::move(parsedSheet));
1967 }
1968
1969 void Internals::insertUserCSS(const String& css, ExceptionCode& ec) const
1970 {
1971     Document* document = contextDocument();
1972     if (!document) {
1973         ec = INVALID_ACCESS_ERR;
1974         return;
1975     }
1976
1977     auto parsedSheet = StyleSheetContents::create(*document);
1978     parsedSheet.get().setIsUserStyleSheet(true);
1979     parsedSheet.get().parseString(css);
1980     document->extensionStyleSheets().addUserStyleSheet(WTF::move(parsedSheet));
1981 }
1982
1983 String Internals::counterValue(Element* element)
1984 {
1985     if (!element)
1986         return String();
1987
1988     return counterValueForElement(element);
1989 }
1990
1991 int Internals::pageNumber(Element* element, float pageWidth, float pageHeight)
1992 {
1993     if (!element)
1994         return 0;
1995
1996     return PrintContext::pageNumberForElement(element, FloatSize(pageWidth, pageHeight));
1997 }
1998
1999 Vector<String> Internals::shortcutIconURLs() const
2000 {
2001     Vector<String> vector;
2002
2003     if (!frame())
2004         return vector;
2005
2006     auto string = frame()->loader().icon().url().string();
2007     if (!string.isNull())
2008         vector.append(string);
2009     return vector;
2010 }
2011
2012 int Internals::numberOfPages(float pageWidth, float pageHeight)
2013 {
2014     if (!frame())
2015         return -1;
2016
2017     return PrintContext::numberOfPages(*frame(), FloatSize(pageWidth, pageHeight));
2018 }
2019
2020 String Internals::pageProperty(String propertyName, int pageNumber, ExceptionCode& ec) const
2021 {
2022     if (!frame()) {
2023         ec = INVALID_ACCESS_ERR;
2024         return String();
2025     }
2026
2027     return PrintContext::pageProperty(frame(), propertyName.utf8().data(), pageNumber);
2028 }
2029
2030 String Internals::pageSizeAndMarginsInPixels(int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft, ExceptionCode& ec) const
2031 {
2032     if (!frame()) {
2033         ec = INVALID_ACCESS_ERR;
2034         return String();
2035     }
2036
2037     return PrintContext::pageSizeAndMarginsInPixels(frame(), pageNumber, width, height, marginTop, marginRight, marginBottom, marginLeft);
2038 }
2039
2040 void Internals::setPageScaleFactor(float scaleFactor, int x, int y, ExceptionCode& ec)
2041 {
2042     Document* document = contextDocument();
2043     if (!document || !document->page()) {
2044         ec = INVALID_ACCESS_ERR;
2045         return;
2046     }
2047     Page* page = document->page();
2048     page->setPageScaleFactor(scaleFactor, IntPoint(x, y));
2049 }
2050
2051 void Internals::setPageZoomFactor(float zoomFactor, ExceptionCode& ec)
2052 {
2053     Document* document = contextDocument();
2054     if (!document || !document->frame()) {
2055         ec = INVALID_ACCESS_ERR;
2056         return;
2057     }
2058     Frame* frame = document->frame();
2059     frame->setPageZoomFactor(zoomFactor);
2060 }
2061
2062 void Internals::setTextZoomFactor(float zoomFactor, ExceptionCode& ec)
2063 {
2064     Document* document = contextDocument();
2065     if (!document || !document->frame()) {
2066         ec = INVALID_ACCESS_ERR;
2067         return;
2068     }
2069     Frame* frame = document->frame();
2070     frame->setTextZoomFactor(zoomFactor);
2071 }
2072
2073 void Internals::setUseFixedLayout(bool useFixedLayout, ExceptionCode& ec)
2074 {
2075     Document* document = contextDocument();
2076     if (!document || !document->view()) {
2077         ec = INVALID_ACCESS_ERR;
2078         return;
2079     }
2080     FrameView* frameView = document->view();
2081     frameView->setUseFixedLayout(useFixedLayout);
2082 }
2083
2084 void Internals::setFixedLayoutSize(int width, int height, ExceptionCode& ec)
2085 {
2086     Document* document = contextDocument();
2087     if (!document || !document->view()) {
2088         ec = INVALID_ACCESS_ERR;
2089         return;
2090     }
2091     FrameView* frameView = document->view();
2092     frameView->setFixedLayoutSize(IntSize(width, height));
2093 }
2094
2095 void Internals::setHeaderHeight(float height)
2096 {
2097     Document* document = contextDocument();
2098     if (!document || !document->view())
2099         return;
2100
2101     FrameView* frameView = document->view();
2102     frameView->setHeaderHeight(height);
2103 }
2104
2105 void Internals::setFooterHeight(float height)
2106 {
2107     Document* document = contextDocument();
2108     if (!document || !document->view())
2109         return;
2110
2111     FrameView* frameView = document->view();
2112     frameView->setFooterHeight(height);
2113 }
2114     
2115 void Internals::setTopContentInset(float contentInset)
2116 {
2117     Document* document = contextDocument();
2118     if (!document)
2119         return;
2120     
2121     Page* page = document->page();
2122     page->setTopContentInset(contentInset);
2123 }
2124
2125 #if ENABLE(FULLSCREEN_API)
2126 void Internals::webkitWillEnterFullScreenForElement(Element* element)
2127 {
2128     Document* document = contextDocument();
2129     if (!document)
2130         return;
2131     document->webkitWillEnterFullScreenForElement(element);
2132 }
2133
2134 void Internals::webkitDidEnterFullScreenForElement(Element* element)
2135 {
2136     Document* document = contextDocument();
2137     if (!document)
2138         return;
2139     document->webkitDidEnterFullScreenForElement(element);
2140 }
2141
2142 void Internals::webkitWillExitFullScreenForElement(Element* element)
2143 {
2144     Document* document = contextDocument();
2145     if (!document)
2146         return;
2147     document->webkitWillExitFullScreenForElement(element);
2148 }
2149
2150 void Internals::webkitDidExitFullScreenForElement(Element* element)
2151 {
2152     Document* document = contextDocument();
2153     if (!document)
2154         return;
2155     document->webkitDidExitFullScreenForElement(element);
2156 }
2157 #endif
2158
2159 void Internals::setApplicationCacheOriginQuota(unsigned long long quota)
2160 {
2161     Document* document = contextDocument();
2162     if (!document)
2163         return;
2164     ApplicationCacheStorage::singleton().storeUpdatedQuotaForOrigin(document->securityOrigin(), quota);
2165 }
2166
2167 void Internals::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme)
2168 {
2169     SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
2170 }
2171
2172 void Internals::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(const String& scheme)
2173 {
2174     SchemeRegistry::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(scheme);
2175 }
2176
2177 Ref<MallocStatistics> Internals::mallocStatistics() const
2178 {
2179     return MallocStatistics::create();
2180 }
2181
2182 Ref<TypeConversions> Internals::typeConversions() const
2183 {
2184     return TypeConversions::create();
2185 }
2186
2187 Ref<MemoryInfo> Internals::memoryInfo() const
2188 {
2189     return MemoryInfo::create();
2190 }
2191
2192 Vector<String> Internals::getReferencedFilePaths() const
2193 {
2194     frame()->loader().history().saveDocumentAndScrollState();
2195     return FormController::getReferencedFilePaths(frame()->loader().history().currentItem()->documentState());
2196 }
2197
2198 void Internals::startTrackingRepaints(ExceptionCode& ec)
2199 {
2200     Document* document = contextDocument();
2201     if (!document || !document->view()) {
2202         ec = INVALID_ACCESS_ERR;
2203         return;
2204     }
2205
2206     FrameView* frameView = document->view();
2207     frameView->setTracksRepaints(true);
2208 }
2209
2210 void Internals::stopTrackingRepaints(ExceptionCode& ec)
2211 {
2212     Document* document = contextDocument();
2213     if (!document || !document->view()) {
2214         ec = INVALID_ACCESS_ERR;
2215         return;
2216     }
2217
2218     FrameView* frameView = document->view();
2219     frameView->setTracksRepaints(false);
2220 }
2221
2222 void Internals::startTrackingLayerFlushes(ExceptionCode& ec)
2223 {
2224     Document* document = contextDocument();
2225     if (!document || !document->renderView()) {
2226         ec = INVALID_ACCESS_ERR;
2227         return;
2228     }
2229
2230     document->renderView()->compositor().startTrackingLayerFlushes();
2231 }
2232
2233 unsigned long Internals::layerFlushCount(ExceptionCode& ec)
2234 {
2235     Document* document = contextDocument();
2236     if (!document || !document->renderView()) {
2237         ec = INVALID_ACCESS_ERR;
2238         return 0;
2239     }
2240
2241     return document->renderView()->compositor().layerFlushCount();
2242 }
2243
2244 void Internals::startTrackingStyleRecalcs(ExceptionCode& ec)
2245 {
2246     Document* document = contextDocument();
2247     if (!document) {
2248         ec = INVALID_ACCESS_ERR;
2249         return;
2250     }
2251     document->startTrackingStyleRecalcs();
2252 }
2253
2254 unsigned long Internals::styleRecalcCount(ExceptionCode& ec)
2255 {
2256     Document* document = contextDocument();
2257     if (!document) {
2258         ec = INVALID_ACCESS_ERR;
2259         return 0;
2260     }
2261     
2262     return document->styleRecalcCount();
2263 }
2264
2265 void Internals::startTrackingCompositingUpdates(ExceptionCode& ec)
2266 {
2267     Document* document = contextDocument();
2268     if (!document || !document->renderView()) {
2269         ec = INVALID_ACCESS_ERR;
2270         return;
2271     }
2272
2273     document->renderView()->compositor().startTrackingCompositingUpdates();
2274 }
2275
2276 unsigned long Internals::compositingUpdateCount(ExceptionCode& ec)
2277 {
2278     Document* document = contextDocument();
2279     if (!document || !document->renderView()) {
2280         ec = INVALID_ACCESS_ERR;
2281         return 0;
2282     }
2283     
2284     return document->renderView()->compositor().compositingUpdateCount();
2285 }
2286
2287 void Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(ExceptionCode& ec)
2288 {
2289     updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(nullptr, ec);
2290 }
2291
2292 void Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(Node* node, ExceptionCode& ec)
2293 {
2294     Document* document;
2295     if (!node)
2296         document = contextDocument();
2297     else if (is<Document>(*node))
2298         document = downcast<Document>(node);
2299     else if (is<HTMLIFrameElement>(*node))
2300         document = downcast<HTMLIFrameElement>(*node).contentDocument();
2301     else {
2302         ec = TypeError;
2303         return;
2304     }
2305
2306     document->updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasks::Synchronously);
2307 }
2308
2309 unsigned Internals::layoutCount() const
2310 {
2311     Document* document = contextDocument();
2312     if (!document || !document->view())
2313         return 0;
2314     return document->view()->layoutCount();
2315 }
2316
2317 #if !PLATFORM(IOS)
2318 static const char* cursorTypeToString(Cursor::Type cursorType)
2319 {
2320     switch (cursorType) {
2321     case Cursor::Pointer: return "Pointer";
2322     case Cursor::Cross: return "Cross";
2323     case Cursor::Hand: return "Hand";
2324     case Cursor::IBeam: return "IBeam";
2325     case Cursor::Wait: return "Wait";
2326     case Cursor::Help: return "Help";
2327     case Cursor::EastResize: return "EastResize";
2328     case Cursor::NorthResize: return "NorthResize";
2329     case Cursor::NorthEastResize: return "NorthEastResize";
2330     case Cursor::NorthWestResize: return "NorthWestResize";
2331     case Cursor::SouthResize: return "SouthResize";
2332     case Cursor::SouthEastResize: return "SouthEastResize";
2333     case Cursor::SouthWestResize: return "SouthWestResize";
2334     case Cursor::WestResize: return "WestResize";
2335     case Cursor::NorthSouthResize: return "NorthSouthResize";
2336     case Cursor::EastWestResize: return "EastWestResize";
2337     case Cursor::NorthEastSouthWestResize: return "NorthEastSouthWestResize";
2338     case Cursor::NorthWestSouthEastResize: return "NorthWestSouthEastResize";
2339     case Cursor::ColumnResize: return "ColumnResize";
2340     case Cursor::RowResize: return "RowResize";
2341     case Cursor::MiddlePanning: return "MiddlePanning";
2342     case Cursor::EastPanning: return "EastPanning";
2343     case Cursor::NorthPanning: return "NorthPanning";
2344     case Cursor::NorthEastPanning: return "NorthEastPanning";
2345     case Cursor::NorthWestPanning: return "NorthWestPanning";
2346     case Cursor::SouthPanning: return "SouthPanning";
2347     case Cursor::SouthEastPanning: return "SouthEastPanning";
2348     case Cursor::SouthWestPanning: return "SouthWestPanning";
2349     case Cursor::WestPanning: return "WestPanning";
2350     case Cursor::Move: return "Move";
2351     case Cursor::VerticalText: return "VerticalText";
2352     case Cursor::Cell: return "Cell";
2353     case Cursor::ContextMenu: return "ContextMenu";
2354     case Cursor::Alias: return "Alias";
2355     case Cursor::Progress: return "Progress";
2356     case Cursor::NoDrop: return "NoDrop";
2357     case Cursor::Copy: return "Copy";
2358     case Cursor::None: return "None";
2359     case Cursor::NotAllowed: return "NotAllowed";
2360     case Cursor::ZoomIn: return "ZoomIn";
2361     case Cursor::ZoomOut: return "ZoomOut";
2362     case Cursor::Grab: return "Grab";
2363     case Cursor::Grabbing: return "Grabbing";
2364     case Cursor::Custom: return "Custom";
2365     }
2366
2367     ASSERT_NOT_REACHED();
2368     return "UNKNOWN";
2369 }
2370 #endif
2371
2372 String Internals::getCurrentCursorInfo(ExceptionCode& ec)
2373 {
2374     Document* document = contextDocument();
2375     if (!document || !document->frame()) {
2376         ec = INVALID_ACCESS_ERR;
2377         return String();
2378     }
2379
2380 #if !PLATFORM(IOS)
2381     Cursor cursor = document->frame()->eventHandler().currentMouseCursor();
2382
2383     StringBuilder result;
2384     result.appendLiteral("type=");
2385     result.append(cursorTypeToString(cursor.type()));
2386     result.appendLiteral(" hotSpot=");
2387     result.appendNumber(cursor.hotSpot().x());
2388     result.append(',');
2389     result.appendNumber(cursor.hotSpot().y());
2390     if (cursor.image()) {
2391         FloatSize size = cursor.image()->size();
2392         result.appendLiteral(" image=");
2393         result.appendNumber(size.width());
2394         result.append('x');
2395         result.appendNumber(size.height());
2396     }
2397 #if ENABLE(MOUSE_CURSOR_SCALE)
2398     if (cursor.imageScaleFactor() != 1) {
2399         result.appendLiteral(" scale=");
2400         NumberToStringBuffer buffer;
2401         result.append(numberToFixedPrecisionString(cursor.imageScaleFactor(), 8, buffer, true));
2402     }
2403 #endif
2404     return result.toString();
2405 #else
2406     return "FAIL: Cursor details not available on this platform.";
2407 #endif
2408 }
2409
2410 RefPtr<ArrayBuffer> Internals::serializeObject(PassRefPtr<SerializedScriptValue> value) const
2411 {
2412     Vector<uint8_t> bytes = value->data();
2413     return ArrayBuffer::create(bytes.data(), bytes.size());
2414 }
2415
2416 RefPtr<SerializedScriptValue> Internals::deserializeBuffer(PassRefPtr<ArrayBuffer> buffer) const
2417 {
2418     Vector<uint8_t> bytes;
2419     bytes.append(static_cast<const uint8_t*>(buffer->data()), buffer->byteLength());
2420     return SerializedScriptValue::adopt(bytes);
2421 }
2422
2423 bool Internals::isFromCurrentWorld(Deprecated::ScriptValue value) const
2424 {
2425     ASSERT(!value.hasNoValue());
2426     
2427     JSC::ExecState* exec = contextDocument()->vm().topCallFrame;
2428     if (!value.isObject() || &worldForDOMObject(value.jsValue().getObject()) == &currentWorld(exec))
2429         return true;
2430     return false;
2431 }
2432
2433 void Internals::setUsesOverlayScrollbars(bool enabled)
2434 {
2435     WebCore::Settings::setUsesOverlayScrollbars(enabled);
2436 }
2437
2438 void Internals::forceReload(bool endToEnd)
2439 {
2440     frame()->loader().reload(endToEnd);
2441 }
2442
2443 #if ENABLE(ENCRYPTED_MEDIA_V2)
2444 void Internals::initializeMockCDM()
2445 {
2446     CDM::registerCDMFactory([](CDM* cdm) { return std::make_unique<MockCDM>(cdm); },
2447         MockCDM::supportsKeySystem, MockCDM::supportsKeySystemAndMimeType);
2448 }
2449 #endif
2450
2451 String Internals::markerTextForListItem(Element* element, ExceptionCode& ec)
2452 {
2453     if (!element) {
2454         ec = INVALID_ACCESS_ERR;
2455         return String();
2456     }
2457     return WebCore::markerTextForListItem(element);
2458 }
2459
2460 String Internals::toolTipFromElement(Element* element, ExceptionCode& ec) const
2461 {
2462     if (!element) {
2463         ec = INVALID_ACCESS_ERR;
2464         return String();
2465     }
2466     HitTestResult result;
2467     result.setInnerNode(element);
2468     TextDirection dir;
2469     return result.title(dir);
2470 }
2471
2472 String Internals::getImageSourceURL(Element* element, ExceptionCode& ec)
2473 {
2474     if (!element) {
2475         ec = INVALID_ACCESS_ERR;
2476         return String();
2477     }
2478     return element->imageSourceURL();
2479 }
2480
2481 #if ENABLE(VIDEO)
2482 void Internals::simulateAudioInterruption(Node* node)
2483 {
2484 #if USE(GSTREAMER)
2485     HTMLMediaElement* element = downcast<HTMLMediaElement>(node);
2486     element->player()->simulateAudioInterruption();
2487 #else
2488     UNUSED_PARAM(node);
2489 #endif
2490 }
2491
2492 bool Internals::mediaElementHasCharacteristic(Node* node, const String& characteristic, ExceptionCode& ec)
2493 {
2494     if (!is<HTMLMediaElement>(*node))
2495         return false;
2496
2497     HTMLMediaElement* element = downcast<HTMLMediaElement>(node);
2498
2499     if (equalIgnoringCase(characteristic, "Audible"))
2500         return element->hasAudio();
2501     if (equalIgnoringCase(characteristic, "Visual"))
2502         return element->hasVideo();
2503     if (equalIgnoringCase(characteristic, "Legible"))
2504         return element->hasClosedCaptions();
2505
2506     ec = SYNTAX_ERR;
2507     return false;
2508 }
2509 #endif
2510
2511 bool Internals::isSelectPopupVisible(Node* node)
2512 {
2513     if (!is<HTMLSelectElement>(*node))
2514         return false;
2515
2516     HTMLSelectElement& select = downcast<HTMLSelectElement>(*node);
2517
2518     auto* renderer = select.renderer();
2519     ASSERT(renderer);
2520     if (!is<RenderMenuList>(*renderer))
2521         return false;
2522
2523 #if !PLATFORM(IOS)
2524     return downcast<RenderMenuList>(*renderer).popupIsVisible();
2525 #else
2526     return false;
2527 #endif // !PLATFORM(IOS)
2528 }
2529
2530 String Internals::captionsStyleSheetOverride(ExceptionCode& ec)
2531 {
2532     Document* document = contextDocument();
2533     if (!document || !document->page()) {
2534         ec = INVALID_ACCESS_ERR;
2535         return emptyString();
2536     }
2537
2538 #if ENABLE(VIDEO_TRACK)
2539     return document->page()->group().captionPreferences()->captionsStyleSheetOverride();
2540 #else
2541     return emptyString();
2542 #endif
2543 }
2544
2545 void Internals::setCaptionsStyleSheetOverride(const String& override, ExceptionCode& ec)
2546 {
2547     Document* document = contextDocument();
2548     if (!document || !document->page()) {
2549         ec = INVALID_ACCESS_ERR;
2550         return;
2551     }
2552
2553 #if ENABLE(VIDEO_TRACK)
2554     document->page()->group().captionPreferences()->setCaptionsStyleSheetOverride(override);
2555 #else
2556     UNUSED_PARAM(override);
2557 #endif
2558 }
2559
2560 void Internals::setPrimaryAudioTrackLanguageOverride(const String& language, ExceptionCode& ec)
2561 {
2562     Document* document = contextDocument();
2563     if (!document || !document->page()) {
2564         ec = INVALID_ACCESS_ERR;
2565         return;
2566     }
2567
2568 #if ENABLE(VIDEO_TRACK)
2569     document->page()->group().captionPreferences()->setPrimaryAudioTrackLanguageOverride(language);
2570 #else
2571     UNUSED_PARAM(language);
2572 #endif
2573 }
2574
2575 void Internals::setCaptionDisplayMode(const String& mode, ExceptionCode& ec)
2576 {
2577     Document* document = contextDocument();
2578     if (!document || !document->page()) {
2579         ec = INVALID_ACCESS_ERR;
2580         return;
2581     }
2582     
2583 #if ENABLE(VIDEO_TRACK)
2584     CaptionUserPreferences* captionPreferences = document->page()->group().captionPreferences();
2585     
2586     if (equalIgnoringCase(mode, "Automatic"))
2587         captionPreferences->setCaptionDisplayMode(CaptionUserPreferences::Automatic);
2588     else if (equalIgnoringCase(mode, "ForcedOnly"))
2589         captionPreferences->setCaptionDisplayMode(CaptionUserPreferences::ForcedOnly);
2590     else if (equalIgnoringCase(mode, "AlwaysOn"))
2591         captionPreferences->setCaptionDisplayMode(CaptionUserPreferences::AlwaysOn);
2592     else
2593         ec = SYNTAX_ERR;
2594 #else
2595     UNUSED_PARAM(mode);
2596 #endif
2597 }
2598
2599 #if ENABLE(VIDEO)
2600 Ref<TimeRanges> Internals::createTimeRanges(Float32Array* startTimes, Float32Array* endTimes)
2601 {
2602     ASSERT(startTimes && endTimes);
2603     ASSERT(startTimes->length() == endTimes->length());
2604     Ref<TimeRanges> ranges = TimeRanges::create();
2605
2606     unsigned count = std::min(startTimes->length(), endTimes->length());
2607     for (unsigned i = 0; i < count; ++i)
2608         ranges->add(startTimes->item(i), endTimes->item(i));
2609     return ranges;
2610 }
2611
2612 double Internals::closestTimeToTimeRanges(double time, TimeRanges* ranges)
2613 {
2614     return ranges->nearest(time);
2615 }
2616 #endif
2617
2618 Ref<ClientRect> Internals::selectionBounds(ExceptionCode& ec)
2619 {
2620     Document* document = contextDocument();
2621     if (!document || !document->frame()) {
2622         ec = INVALID_ACCESS_ERR;
2623         return ClientRect::create();
2624     }
2625
2626     return ClientRect::create(document->frame()->selection().selectionBounds());
2627 }
2628
2629 #if ENABLE(VIBRATION)
2630 bool Internals::isVibrating()
2631 {
2632     Page* page = contextDocument()->page();
2633     ASSERT(page);
2634
2635     return Vibration::from(page)->isVibrating();
2636 }
2637 #endif
2638
2639 bool Internals::isPluginUnavailabilityIndicatorObscured(Element* element, ExceptionCode& ec)
2640 {
2641     if (!element) {
2642         ec = INVALID_ACCESS_ERR;
2643         return false;
2644     }
2645
2646     auto* renderer = element->renderer();
2647     if (!is<RenderEmbeddedObject>(renderer)) {
2648         ec = INVALID_ACCESS_ERR;
2649         return false;
2650     }
2651
2652     return downcast<RenderEmbeddedObject>(*renderer).isReplacementObscured();
2653 }
2654     
2655 bool Internals::isPluginSnapshotted(Element* element, ExceptionCode& ec)
2656 {
2657     if (!element) {
2658         ec = INVALID_ACCESS_ERR;
2659         return false;
2660     }
2661     HTMLPlugInElement* pluginElement = downcast<HTMLPlugInElement>(element);
2662     return pluginElement->displayState() <= HTMLPlugInElement::DisplayingSnapshot;
2663 }
2664     
2665 #if ENABLE(MEDIA_SOURCE)
2666 void Internals::initializeMockMediaSource()
2667 {
2668 #if USE(AVFOUNDATION)
2669     WebCore::Settings::setAVFoundationEnabled(false);
2670 #endif
2671     MediaPlayerFactorySupport::callRegisterMediaEngine(MockMediaPlayerMediaSource::registerMediaEngine);
2672 }
2673
2674 Vector<String> Internals::bufferedSamplesForTrackID(SourceBuffer* buffer, const AtomicString& trackID)
2675 {
2676     if (!buffer)
2677         return Vector<String>();
2678
2679     return buffer->bufferedSamplesForTrackID(trackID);
2680 }
2681     
2682 void Internals::setShouldGenerateTimestamps(SourceBuffer* buffer, bool flag)
2683 {
2684     if (buffer)
2685         buffer->setShouldGenerateTimestamps(flag);
2686 }
2687 #endif
2688
2689 #if ENABLE(VIDEO)
2690 void Internals::beginMediaSessionInterruption(const String& interruptionString, ExceptionCode& ec)
2691 {
2692     PlatformMediaSession::InterruptionType interruption = PlatformMediaSession::SystemInterruption;
2693
2694     if (equalIgnoringCase(interruptionString, "System"))
2695         interruption = PlatformMediaSession::SystemInterruption;
2696     else if (equalIgnoringCase(interruptionString, "SystemSleep"))
2697         interruption = PlatformMediaSession::SystemSleep;
2698     else if (equalIgnoringCase(interruptionString, "EnteringBackground"))
2699         interruption = PlatformMediaSession::EnteringBackground;
2700     else {
2701         ec = INVALID_ACCESS_ERR;
2702         return;
2703     }
2704
2705     PlatformMediaSessionManager::sharedManager().beginInterruption(interruption);
2706 }
2707
2708 void Internals::endMediaSessionInterruption(const String& flagsString)
2709 {
2710     PlatformMediaSession::EndInterruptionFlags flags = PlatformMediaSession::NoFlags;
2711
2712     if (equalIgnoringCase(flagsString, "MayResumePlaying"))
2713         flags = PlatformMediaSession::MayResumePlaying;
2714     
2715     PlatformMediaSessionManager::sharedManager().endInterruption(flags);
2716 }
2717
2718 void Internals::applicationDidEnterForeground() const
2719 {
2720     PlatformMediaSessionManager::sharedManager().applicationDidEnterForeground();
2721 }
2722
2723 void Internals::applicationWillEnterBackground() const
2724 {
2725     PlatformMediaSessionManager::sharedManager().applicationWillEnterBackground();
2726 }
2727
2728 void Internals::setMediaSessionRestrictions(const String& mediaTypeString, const String& restrictionsString, ExceptionCode& ec)
2729 {
2730     PlatformMediaSession::MediaType mediaType = PlatformMediaSession::None;
2731     if (equalIgnoringCase(mediaTypeString, "Video"))
2732         mediaType = PlatformMediaSession::Video;
2733     else if (equalIgnoringCase(mediaTypeString, "Audio"))
2734         mediaType = PlatformMediaSession::Audio;
2735     else if (equalIgnoringCase(mediaTypeString, "WebAudio"))
2736         mediaType = PlatformMediaSession::WebAudio;
2737     else {
2738         ec = INVALID_ACCESS_ERR;
2739         return;
2740     }
2741
2742     PlatformMediaSessionManager::SessionRestrictions restrictions = PlatformMediaSessionManager::sharedManager().restrictions(mediaType);
2743     PlatformMediaSessionManager::sharedManager().removeRestriction(mediaType, restrictions);
2744
2745     restrictions = PlatformMediaSessionManager::NoRestrictions;
2746
2747     Vector<String> restrictionsArray;
2748     restrictionsString.split(',', false, restrictionsArray);
2749     for (auto& restrictionString : restrictionsArray) {
2750         if (equalIgnoringCase(restrictionString, "ConcurrentPlaybackNotPermitted"))
2751             restrictions |= PlatformMediaSessionManager::ConcurrentPlaybackNotPermitted;
2752         if (equalIgnoringCase(restrictionString, "BackgroundProcessPlaybackRestricted"))
2753             restrictions |= PlatformMediaSessionManager::BackgroundProcessPlaybackRestricted;
2754         if (equalIgnoringCase(restrictionString, "BackgroundTabPlaybackRestricted"))
2755             restrictions |= PlatformMediaSessionManager::BackgroundTabPlaybackRestricted;
2756         if (equalIgnoringCase(restrictionString, "InterruptedPlaybackNotPermitted"))
2757             restrictions |= PlatformMediaSessionManager::InterruptedPlaybackNotPermitted;
2758     }
2759     PlatformMediaSessionManager::sharedManager().addRestriction(mediaType, restrictions);
2760 }
2761
2762 void Internals::setMediaElementRestrictions(HTMLMediaElement* element, const String& restrictionsString, ExceptionCode& ec)
2763 {
2764     if (!element) {
2765         ec = INVALID_ACCESS_ERR;
2766         return;
2767     }
2768
2769     MediaElementSession::BehaviorRestrictions restrictions = element->mediaSession().behaviorRestrictions();
2770     element->mediaSession().removeBehaviorRestriction(restrictions);
2771
2772     restrictions = MediaElementSession::NoRestrictions;
2773
2774     Vector<String> restrictionsArray;
2775     restrictionsString.split(',', false, restrictionsArray);
2776     for (auto& restrictionString : restrictionsArray) {
2777         if (equalIgnoringCase(restrictionString, "NoRestrictions"))
2778             restrictions |= MediaElementSession::NoRestrictions;
2779         if (equalIgnoringCase(restrictionString, "RequireUserGestureForLoad"))
2780             restrictions |= MediaElementSession::RequireUserGestureForLoad;
2781         if (equalIgnoringCase(restrictionString, "RequireUserGestureForRateChange"))
2782             restrictions |= MediaElementSession::RequireUserGestureForRateChange;
2783         if (equalIgnoringCase(restrictionString, "RequireUserGestureForFullscreen"))
2784             restrictions |= MediaElementSession::RequireUserGestureForFullscreen;
2785         if (equalIgnoringCase(restrictionString, "RequirePageConsentToLoadMedia"))
2786             restrictions |= MediaElementSession::RequirePageConsentToLoadMedia;
2787         if (equalIgnoringCase(restrictionString, "RequirePageConsentToResumeMedia"))
2788             restrictions |= MediaElementSession::RequirePageConsentToResumeMedia;
2789 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
2790         if (equalIgnoringCase(restrictionString, "RequireUserGestureToShowPlaybackTargetPicker"))
2791             restrictions |= MediaElementSession::RequireUserGestureToShowPlaybackTargetPicker;
2792         if (equalIgnoringCase(restrictionString, "WirelessVideoPlaybackDisabled"))
2793             restrictions |= MediaElementSession::WirelessVideoPlaybackDisabled;
2794 #endif
2795         if (equalIgnoringCase(restrictionString, "RequireUserGestureForAudioRateChange"))
2796             restrictions |= MediaElementSession::RequireUserGestureForAudioRateChange;
2797         if (equalIgnoringCase(restrictionString, "MetadataPreloadingNotPermitted"))
2798             restrictions |= MediaElementSession::MetadataPreloadingNotPermitted;
2799         if (equalIgnoringCase(restrictionString, "AutoPreloadingNotPermitted"))
2800             restrictions |= MediaElementSession::AutoPreloadingNotPermitted;
2801     }
2802     element->mediaSession().addBehaviorRestriction(restrictions);
2803 }
2804
2805 void Internals::postRemoteControlCommand(const String& commandString, ExceptionCode& ec)
2806 {
2807     PlatformMediaSession::RemoteControlCommandType command;
2808     
2809     if (equalIgnoringCase(commandString, "Play"))
2810         command = PlatformMediaSession::PlayCommand;
2811     else if (equalIgnoringCase(commandString, "Pause"))
2812         command = PlatformMediaSession::PauseCommand;
2813     else if (equalIgnoringCase(commandString, "Stop"))
2814         command = PlatformMediaSession::StopCommand;
2815     else if (equalIgnoringCase(commandString, "TogglePlayPause"))
2816         command = PlatformMediaSession::TogglePlayPauseCommand;
2817     else if (equalIgnoringCase(commandString, "BeginSeekingBackward"))
2818         command = PlatformMediaSession::BeginSeekingBackwardCommand;
2819     else if (equalIgnoringCase(commandString, "EndSeekingBackward"))
2820         command = PlatformMediaSession::EndSeekingBackwardCommand;
2821     else if (equalIgnoringCase(commandString, "BeginSeekingForward"))
2822         command = PlatformMediaSession::BeginSeekingForwardCommand;
2823     else if (equalIgnoringCase(commandString, "EndSeekingForward"))
2824         command = PlatformMediaSession::EndSeekingForwardCommand;
2825     else {
2826         ec = INVALID_ACCESS_ERR;
2827         return;
2828     }
2829     
2830     PlatformMediaSessionManager::sharedManager().didReceiveRemoteControlCommand(command);
2831 }
2832
2833 bool Internals::elementIsBlockingDisplaySleep(Element* element) const
2834 {
2835     HTMLMediaElement* mediaElement = downcast<HTMLMediaElement>(element);
2836     return mediaElement ? mediaElement->isDisablingSleep() : false;
2837 }
2838
2839 #endif // ENABLE(VIDEO)
2840
2841 #if ENABLE(MEDIA_SESSION)
2842 static MediaSessionInterruptingCategory interruptingCategoryFromString(const String& interruptingCategoryString)
2843 {
2844     if (interruptingCategoryString == "content")
2845         return MediaSessionInterruptingCategory::Content;
2846     if (interruptingCategoryString == "transient")
2847         return MediaSessionInterruptingCategory::Transient;
2848     if (interruptingCategoryString == "transient-solo")
2849         return MediaSessionInterruptingCategory::TransientSolo;
2850     ASSERT_NOT_REACHED();
2851     return MediaSessionInterruptingCategory::Content;
2852 }
2853
2854 void Internals::sendMediaSessionStartOfInterruptionNotification(const String& interruptingCategoryString)
2855 {
2856     MediaSessionManager::singleton().didReceiveStartOfInterruptionNotification(interruptingCategoryFromString(interruptingCategoryString));
2857 }
2858
2859 void Internals::sendMediaSessionEndOfInterruptionNotification(const String& interruptingCategoryString)
2860 {
2861     MediaSessionManager::singleton().didReceiveEndOfInterruptionNotification(interruptingCategoryFromString(interruptingCategoryString));
2862 }
2863
2864 String Internals::mediaSessionCurrentState(MediaSession* session) const
2865 {
2866     switch (session->currentState()) {
2867     case MediaSession::State::Active:
2868         return "active";
2869     case MediaSession::State::Interrupted:
2870         return "interrupted";
2871     case MediaSession::State::Idle:
2872         return "idle";
2873     }
2874 }
2875
2876 double Internals::mediaElementPlayerVolume(HTMLMediaElement* element) const
2877 {
2878     ASSERT_ARG(element, element);
2879     return element->playerVolume();
2880 }
2881
2882 void Internals::sendMediaControlEvent(const String& event)
2883 {
2884     if (event == "play-pause")
2885         MediaSessionManager::singleton().togglePlayback();
2886     else if (event == "next-track")
2887         MediaSessionManager::singleton().skipToNextTrack();
2888     else if (event == "previous-track")
2889         MediaSessionManager::singleton().skipToPreviousTrack();
2890     else
2891         ASSERT_NOT_REACHED();
2892 }
2893 #endif // ENABLE(MEDIA_SESSION)
2894
2895 #if ENABLE(WEB_AUDIO)
2896 void Internals::setAudioContextRestrictions(AudioContext* context, const String &restrictionsString, ExceptionCode &ec)
2897 {
2898     if (!context) {
2899         ec = INVALID_ACCESS_ERR;
2900         return;
2901     }
2902
2903     AudioContext::BehaviorRestrictions restrictions = context->behaviorRestrictions();
2904     context->removeBehaviorRestriction(restrictions);
2905
2906     restrictions = MediaElementSession::NoRestrictions;
2907
2908     Vector<String> restrictionsArray;
2909     restrictionsString.split(',', false, restrictionsArray);
2910     for (auto& restrictionString : restrictionsArray) {
2911         if (equalIgnoringCase(restrictionString, "NoRestrictions"))
2912             restrictions |= AudioContext::NoRestrictions;
2913         if (equalIgnoringCase(restrictionString, "RequireUserGestureForAudioStart"))
2914             restrictions |= AudioContext::RequireUserGestureForAudioStartRestriction;
2915         if (equalIgnoringCase(restrictionString, "RequirePageConsentForAudioStart"))
2916             restrictions |= AudioContext::RequirePageConsentForAudioStartRestriction;
2917     }
2918     context->addBehaviorRestriction(restrictions);
2919 }
2920 #endif
2921
2922 void Internals::simulateSystemSleep() const
2923 {
2924 #if ENABLE(VIDEO)
2925     PlatformMediaSessionManager::sharedManager().systemWillSleep();
2926 #endif
2927 }
2928
2929 void Internals::simulateSystemWake() const
2930 {
2931 #if ENABLE(VIDEO)
2932     PlatformMediaSessionManager::sharedManager().systemDidWake();
2933 #endif
2934 }
2935
2936
2937 void Internals::installMockPageOverlay(const String& overlayType, ExceptionCode& ec)
2938 {
2939     Document* document = contextDocument();
2940     if (!document || !document->frame()) {
2941         ec = INVALID_ACCESS_ERR;
2942         return;
2943     }
2944
2945     MockPageOverlayClient::singleton().installOverlay(document->frame()->mainFrame(), overlayType == "view" ? PageOverlay::OverlayType::View : PageOverlay::OverlayType::Document);
2946 }
2947
2948 String Internals::pageOverlayLayerTreeAsText(ExceptionCode& ec) const
2949 {
2950     Document* document = contextDocument();
2951     if (!document || !document->frame()) {
2952         ec = INVALID_ACCESS_ERR;
2953         return String();
2954     }
2955
2956     document->updateLayout();
2957
2958     return MockPageOverlayClient::singleton().layerTreeAsText(document->frame()->mainFrame());
2959 }
2960
2961 void Internals::setPageMuted(bool muted)
2962 {
2963     Document* document = contextDocument();
2964     if (!document)
2965         return;
2966
2967     if (Page* page = document->page())
2968         page->setMuted(muted);
2969 }
2970
2971 bool Internals::isPagePlayingAudio()
2972 {
2973     Document* document = contextDocument();
2974     if (!document || !document->page())
2975         return false;
2976
2977     return !!(document->page()->mediaState() & MediaProducer::IsPlayingAudio);
2978 }
2979
2980 void Internals::setPageDefersLoading(bool defersLoading)
2981 {
2982     Document* document = contextDocument();
2983     if (!document)
2984         return;
2985     if (Page* page = document->page())
2986         page->setDefersLoading(defersLoading);
2987 }
2988
2989 RefPtr<File> Internals::createFile(const String& path)
2990 {
2991     Document* document = contextDocument();
2992     if (!document)
2993         return nullptr;
2994
2995     URL url = document->completeURL(path);
2996     if (!url.isLocalFile())
2997         return nullptr;
2998
2999     return File::create(url.fileSystemPath());
3000 }
3001
3002 void Internals::queueMicroTask(int testNumber)
3003 {
3004     if (contextDocument())
3005         MicroTaskQueue::singleton().queueMicroTask(std::make_unique<MicroTaskTest>(contextDocument()->createWeakPtr(), testNumber));
3006 }
3007
3008 #if ENABLE(CONTENT_FILTERING)
3009 MockContentFilterSettings& Internals::mockContentFilterSettings()
3010 {
3011     return MockContentFilterSettings::singleton();
3012 }
3013 #endif
3014
3015 #if ENABLE(CSS_SCROLL_SNAP)
3016 static void appendOffsets(StringBuilder& builder, const Vector<LayoutUnit>& snapOffsets)
3017 {
3018     bool justStarting = true;
3019
3020     builder.append("{ ");
3021     for (auto& coordinate : snapOffsets) {
3022         if (!justStarting)
3023             builder.append(", ");
3024         else
3025             justStarting = false;
3026         
3027         builder.append(String::number(coordinate.toUnsigned()));
3028     }
3029     builder.append(" }");
3030 }
3031     
3032 String Internals::scrollSnapOffsets(Element* element, ExceptionCode& ec)
3033 {
3034     if (!element) {
3035         ec = INVALID_ACCESS_ERR;
3036         return String();
3037     }
3038
3039     if (!element->renderBox())
3040         return String();
3041
3042     RenderBox& box = *element->renderBox();
3043     ScrollableArea* scrollableArea;
3044     
3045     if (box.isBody()) {
3046         FrameView* frameView = box.frame().mainFrame().view();
3047         if (!frameView || !frameView->isScrollable()) {
3048             ec = INVALID_ACCESS_ERR;
3049             return String();
3050         }
3051         scrollableArea = frameView;
3052         
3053     } else {
3054         if (!box.canBeScrolledAndHasScrollableArea()) {
3055             ec = INVALID_ACCESS_ERR;
3056             return String();
3057         }
3058         scrollableArea = box.layer();
3059     }
3060
3061     if (!scrollableArea)
3062         return String();
3063     
3064     StringBuilder result;
3065
3066     if (scrollableArea->horizontalSnapOffsets()) {
3067         result.append("horizontal = ");
3068         appendOffsets(result, *scrollableArea->horizontalSnapOffsets());
3069     }
3070
3071     if (scrollableArea->verticalSnapOffsets()) {
3072         if (result.length())
3073             result.append(", ");
3074
3075         result.append("vertical = ");
3076         appendOffsets(result, *scrollableArea->verticalSnapOffsets());
3077     }
3078
3079     return result.toString();
3080 }
3081 #endif
3082
3083 bool Internals::testPreloaderSettingViewport()
3084 {
3085     return testPreloadScannerViewportSupport(contextDocument());
3086 }
3087
3088 String Internals::pathStringWithShrinkWrappedRects(Vector<double> rectComponents, double radius, ExceptionCode& ec)
3089 {
3090     if (rectComponents.size() % 4) {
3091         ec = INVALID_ACCESS_ERR;
3092         return String();
3093     }
3094
3095     Vector<FloatRect> rects;
3096     while (!rectComponents.isEmpty()) {
3097         double height = rectComponents.takeLast();
3098         double width = rectComponents.takeLast();
3099         double y = rectComponents.takeLast();
3100         double x = rectComponents.takeLast();
3101
3102         rects.append(FloatRect(x, y, width, height));
3103     }
3104
3105     rects.reverse();
3106
3107     Path path = PathUtilities::pathWithShrinkWrappedRects(rects, radius);
3108
3109     String pathString;
3110     buildStringFromPath(path, pathString);
3111
3112     return pathString;
3113 }
3114
3115
3116 String Internals::getCurrentMediaControlsStatusForElement(HTMLMediaElement* mediaElement)
3117 {
3118 #if !ENABLE(MEDIA_CONTROLS_SCRIPT)
3119     UNUSED_PARAM(mediaElement);
3120     return String();
3121 #else
3122     if (!mediaElement)
3123         return String();
3124
3125     return mediaElement->getCurrentMediaControlsStatus();
3126 #endif
3127 }
3128
3129 #if !PLATFORM(COCOA)
3130 String Internals::userVisibleString(const DOMURL*)
3131 {
3132     // Not implemented in WebCore.
3133     return String();
3134 }
3135 #endif
3136
3137 void Internals::setShowAllPlugins(bool show)
3138 {
3139     Document* document = contextDocument();
3140     if (!document)
3141         return;
3142     
3143     Page* page = document->page();
3144     if (!page)
3145         return;
3146
3147     page->setShowAllPlugins(show);
3148 }
3149
3150 }