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