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