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