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