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