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