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